abf_api.c revision 097fa66b
1/*
2 * Copyright (c) 2016 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include <stddef.h>
17
18#include <vnet/vnet.h>
19#include <vnet/plugin/plugin.h>
20#include <abf/abf_policy.h>
21#include <abf/abf_itf_attach.h>
22#include <vnet/mpls/mpls_types.h>
23#include <vnet/fib/fib_path_list.h>
24#include <vnet/fib/fib_api.h>
25
26#include <vpp/app/version.h>
27
28#include <vlibapi/api.h>
29#include <vlibmemory/api.h>
30
31/* define message IDs */
32#include <abf/abf_msg_enum.h>
33
34/* define message structures */
35#define vl_typedefs
36#include <abf/abf_all_api_h.h>
37#undef vl_typedefs
38
39/* define generated endian-swappers */
40#define vl_endianfun
41#include <abf/abf_all_api_h.h>
42#undef vl_endianfun
43
44/* instantiate all the print functions we know about */
45#define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
46#define vl_printfun
47#include <abf/abf_all_api_h.h>
48#undef vl_printfun
49
50/* Get the API version number */
51#define vl_api_version(n,v) static u32 api_version=(v);
52#include <abf/abf_all_api_h.h>
53#undef vl_api_version
54
55/**
56 * Base message ID fot the plugin
57 */
58static u32 abf_base_msg_id;
59
60#include <vlibapi/api_helper_macros.h>
61
62/* List of message types that this plugin understands */
63
64#define foreach_abf_plugin_api_msg                    \
65_(ABF_PLUGIN_GET_VERSION, abf_plugin_get_version)     \
66_(ABF_POLICY_ADD_DEL, abf_policy_add_del)             \
67_(ABF_POLICY_DUMP, abf_policy_dump)                   \
68_(ABF_ITF_ATTACH_ADD_DEL, abf_itf_attach_add_del)     \
69_(ABF_ITF_ATTACH_DUMP, abf_itf_attach_dump)
70
71static void
72vl_api_abf_plugin_get_version_t_handler (vl_api_abf_plugin_get_version_t * mp)
73{
74  vl_api_abf_plugin_get_version_reply_t *rmp;
75  vl_api_registration_t *rp;
76
77  rp = vl_api_client_index_to_registration (mp->client_index);
78  if (rp == 0)
79    return;
80
81  rmp = vl_msg_api_alloc (sizeof (*rmp));
82  rmp->_vl_msg_id =
83    ntohs (VL_API_ABF_PLUGIN_GET_VERSION_REPLY + abf_base_msg_id);
84  rmp->context = mp->context;
85  rmp->major = htonl (ABF_PLUGIN_VERSION_MAJOR);
86  rmp->minor = htonl (ABF_PLUGIN_VERSION_MINOR);
87
88  vl_api_send_msg (rp, (u8 *) rmp);
89}
90
91static void
92vl_api_abf_policy_add_del_t_handler (vl_api_abf_policy_add_del_t * mp)
93{
94  vl_api_abf_policy_add_del_reply_t *rmp;
95  fib_route_path_t *paths = NULL, *path;
96  int rv = 0;
97  u8 pi;
98
99  vec_validate (paths, mp->policy.n_paths - 1);
100
101  for (pi = 0; pi < mp->policy.n_paths; pi++)
102    {
103      path = &paths[pi];
104      rv = fib_api_path_decode (&mp->policy.paths[pi], path);
105
106      if (0 != rv)
107	{
108	  goto done;
109	}
110    }
111
112  if (mp->is_add)
113    {
114      rv = abf_policy_update (ntohl (mp->policy.policy_id),
115			      ntohl (mp->policy.acl_index), paths);
116    }
117  else
118    {
119      rv = abf_policy_delete (ntohl (mp->policy.policy_id), paths);
120    }
121done:
122  vec_free (paths);
123
124  REPLY_MACRO (VL_API_ABF_POLICY_ADD_DEL_REPLY + abf_base_msg_id);
125}
126
127static void
128vl_api_abf_itf_attach_add_del_t_handler (vl_api_abf_itf_attach_add_del_t * mp)
129{
130  vl_api_abf_itf_attach_add_del_reply_t *rmp;
131  fib_protocol_t fproto = (mp->attach.is_ipv6 ?
132			   FIB_PROTOCOL_IP6 : FIB_PROTOCOL_IP4);
133  int rv = 0;
134
135  if (mp->is_add)
136    {
137      abf_itf_attach (fproto,
138		      ntohl (mp->attach.policy_id),
139		      ntohl (mp->attach.priority),
140		      ntohl (mp->attach.sw_if_index));
141    }
142  else
143    {
144      abf_itf_detach (fproto,
145		      ntohl (mp->attach.policy_id),
146		      ntohl (mp->attach.sw_if_index));
147    }
148
149  REPLY_MACRO (VL_API_ABF_ITF_ATTACH_ADD_DEL_REPLY + abf_base_msg_id);
150}
151
152typedef struct abf_dump_walk_ctx_t_
153{
154  vl_api_registration_t *rp;
155  u32 context;
156} abf_dump_walk_ctx_t;
157
158static int
159abf_policy_send_details (u32 api, void *args)
160{
161  fib_path_encode_ctx_t walk_ctx = {
162    .rpaths = NULL,
163  };
164  vl_api_abf_policy_details_t *mp;
165  abf_dump_walk_ctx_t *ctx;
166  fib_route_path_t *rpath;
167  vl_api_fib_path_t *fp;
168  size_t msg_size;
169  abf_policy_t *ap;
170  u8 n_paths;
171
172  ctx = args;
173  ap = abf_policy_get (api);
174  n_paths = fib_path_list_get_n_paths (ap->ap_pl);
175  msg_size = sizeof (*mp) + sizeof (mp->policy.paths[0]) * n_paths;
176
177  mp = vl_msg_api_alloc (msg_size);
178  clib_memset (mp, 0, msg_size);
179  mp->_vl_msg_id = ntohs (VL_API_ABF_POLICY_DETAILS + abf_base_msg_id);
180
181  /* fill in the message */
182  mp->context = ctx->context;
183  mp->policy.n_paths = n_paths;
184  mp->policy.acl_index = htonl (ap->ap_acl);
185  mp->policy.policy_id = htonl (ap->ap_id);
186
187  fib_path_list_walk_w_ext (ap->ap_pl, NULL, fib_path_encode, &walk_ctx);
188
189  fp = mp->policy.paths;
190  vec_foreach (rpath, walk_ctx.rpaths)
191  {
192    fib_api_path_encode (rpath, fp);
193    fp++;
194  }
195
196  vl_api_send_msg (ctx->rp, (u8 *) mp);
197
198  vec_free (walk_ctx.rpaths);
199
200  return (1);
201}
202
203static void
204vl_api_abf_policy_dump_t_handler (vl_api_abf_policy_dump_t * mp)
205{
206  vl_api_registration_t *rp;
207
208  rp = vl_api_client_index_to_registration (mp->client_index);
209  if (rp == 0)
210    return;
211
212  abf_dump_walk_ctx_t ctx = {
213    .rp = rp,
214    .context = mp->context,
215  };
216
217  abf_policy_walk (abf_policy_send_details, &ctx);
218}
219
220static int
221abf_itf_attach_send_details (u32 aiai, void *args)
222{
223  vl_api_abf_itf_attach_details_t *mp;
224  abf_dump_walk_ctx_t *ctx;
225  abf_itf_attach_t *aia;
226  abf_policy_t *ap;
227
228  ctx = args;
229  aia = abf_itf_attach_get (aiai);
230  ap = abf_policy_get (aia->aia_abf);
231
232  mp = vl_msg_api_alloc (sizeof (*mp));
233  mp->_vl_msg_id = ntohs (VL_API_ABF_ITF_ATTACH_DETAILS + abf_base_msg_id);
234
235  mp->context = ctx->context;
236  mp->attach.policy_id = htonl (ap->ap_id);
237  mp->attach.sw_if_index = htonl (aia->aia_sw_if_index);
238  mp->attach.priority = htonl (aia->aia_prio);
239  mp->attach.is_ipv6 = (aia->aia_proto == FIB_PROTOCOL_IP6);
240
241  vl_api_send_msg (ctx->rp, (u8 *) mp);
242
243  return (1);
244}
245
246static void
247vl_api_abf_itf_attach_dump_t_handler (vl_api_abf_itf_attach_dump_t * mp)
248{
249  vl_api_registration_t *rp;
250
251  rp = vl_api_client_index_to_registration (mp->client_index);
252  if (rp == 0)
253    return;
254
255  abf_dump_walk_ctx_t ctx = {
256    .rp = rp,
257    .context = mp->context,
258  };
259
260  abf_itf_attach_walk (abf_itf_attach_send_details, &ctx);
261}
262
263#define vl_msg_name_crc_list
264#include <abf/abf_all_api_h.h>
265#undef vl_msg_name_crc_list
266
267/* Set up the API message handling tables */
268static clib_error_t *
269abf_plugin_api_hookup (vlib_main_t * vm)
270{
271#define _(N,n)                                                  \
272    vl_msg_api_set_handlers((VL_API_##N + abf_base_msg_id),     \
273                            #n,					\
274                            vl_api_##n##_t_handler,             \
275                            vl_noop_handler,                    \
276                            vl_api_##n##_t_endian,              \
277                            vl_api_##n##_t_print,               \
278                            sizeof(vl_api_##n##_t), 1);
279  foreach_abf_plugin_api_msg;
280#undef _
281
282  return 0;
283}
284
285static void
286setup_message_id_table (api_main_t * apim)
287{
288#define _(id,n,crc) \
289  vl_msg_api_add_msg_name_crc (apim, #n "_" #crc, id + abf_base_msg_id);
290  foreach_vl_msg_name_crc_abf;
291#undef _
292}
293
294static clib_error_t *
295abf_api_init (vlib_main_t * vm)
296{
297  clib_error_t *error = 0;
298
299  u8 *name = format (0, "abf_%08x%c", api_version, 0);
300
301  /* Ask for a correctly-sized block of API message decode slots */
302  abf_base_msg_id = vl_msg_api_get_msg_ids ((char *) name,
303					    VL_MSG_FIRST_AVAILABLE);
304
305  error = abf_plugin_api_hookup (vm);
306
307  /* Add our API messages to the global name_crc hash table */
308  setup_message_id_table (&api_main);
309
310  vec_free (name);
311
312  return error;
313}
314
315VLIB_INIT_FUNCTION (abf_api_init);
316
317/* *INDENT-OFF* */
318VLIB_PLUGIN_REGISTER () = {
319    .version = VPP_BUILD_VER,
320    .description = "Access Control List (ACL) Based Forwarding",
321};
322/* *INDENT-ON* */
323
324/*
325 * fd.io coding-style-patch-verification: ON
326 *
327 * Local Variables:
328 * eval: (c-set-style "gnu")
329 * End:
330 */
331