c11 safe string handling support
[vpp.git] / src / plugins / gbp / gbp_api.c
1 /*
2  *------------------------------------------------------------------
3  * Copyright (c) 2018 Cisco and/or its affiliates.
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *------------------------------------------------------------------
16  */
17
18 #include <vnet/vnet.h>
19 #include <vnet/plugin/plugin.h>
20
21 #include <vnet/interface.h>
22 #include <vnet/api_errno.h>
23 #include <vnet/ip/ip_types_api.h>
24 #include <vnet/ethernet/ethernet_types_api.h>
25 #include <vpp/app/version.h>
26
27 #include <gbp/gbp.h>
28
29 #include <vlibapi/api.h>
30 #include <vlibmemory/api.h>
31
32 /* define message IDs */
33 #include <gbp/gbp_msg_enum.h>
34
35 #define vl_typedefs             /* define message structures */
36 #include <gbp/gbp_all_api_h.h>
37 #undef vl_typedefs
38
39 #define vl_endianfun            /* define message structures */
40 #include <gbp/gbp_all_api_h.h>
41 #undef vl_endianfun
42
43 /* instantiate all the print functions we know about */
44 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
45 #define vl_printfun
46 #include <gbp/gbp_all_api_h.h>
47 #undef vl_printfun
48
49 /* Get the API version number */
50 #define vl_api_version(n,v) static u32 api_version=(v);
51 #include <gbp/gbp_all_api_h.h>
52 #undef vl_api_version
53
54 #include <vlibapi/api_helper_macros.h>
55
56 #define foreach_gbp_api_msg                                 \
57   _(GBP_ENDPOINT_ADD, gbp_endpoint_add)                     \
58   _(GBP_ENDPOINT_DEL, gbp_endpoint_del)                     \
59   _(GBP_ENDPOINT_DUMP, gbp_endpoint_dump)                   \
60   _(GBP_SUBNET_ADD_DEL, gbp_subnet_add_del)                 \
61   _(GBP_SUBNET_DUMP, gbp_subnet_dump)                       \
62   _(GBP_ENDPOINT_GROUP_ADD_DEL, gbp_endpoint_group_add_del) \
63   _(GBP_ENDPOINT_GROUP_DUMP, gbp_endpoint_group_dump)       \
64   _(GBP_RECIRC_ADD_DEL, gbp_recirc_add_del)                 \
65   _(GBP_RECIRC_DUMP, gbp_recirc_dump)                       \
66   _(GBP_CONTRACT_ADD_DEL, gbp_contract_add_del)             \
67   _(GBP_CONTRACT_DUMP, gbp_contract_dump)
68
69 gbp_main_t gbp_main;
70
71 static u16 msg_id_base;
72
73 #define GBP_MSG_BASE msg_id_base
74
75 static void
76 vl_api_gbp_endpoint_add_t_handler (vl_api_gbp_endpoint_add_t * mp)
77 {
78   vl_api_gbp_endpoint_add_reply_t *rmp;
79   u32 sw_if_index, handle;
80   ip46_address_t *ips;
81   mac_address_t mac;
82   int rv = 0, ii;
83
84   VALIDATE_SW_IF_INDEX (&(mp->endpoint));
85
86   sw_if_index = ntohl (mp->endpoint.sw_if_index);
87
88   ips = NULL;
89
90   if (mp->endpoint.n_ips)
91     {
92       vec_validate (ips, mp->endpoint.n_ips - 1);
93
94       vec_foreach_index (ii, ips)
95       {
96         ip_address_decode (&mp->endpoint.ips[ii], &ips[ii]);
97       }
98     }
99   mac_address_decode (&mp->endpoint.mac, &mac);
100
101   rv = gbp_endpoint_update (sw_if_index, ips, &mac,
102                             ntohs (mp->endpoint.epg_id), &handle);
103
104   vec_free (ips);
105
106   BAD_SW_IF_INDEX_LABEL;
107
108   /* *INDENT-OFF* */
109   REPLY_MACRO2 (VL_API_GBP_ENDPOINT_ADD_REPLY + GBP_MSG_BASE,
110   ({
111     rmp->handle = htonl (handle);
112   }));
113   /* *INDENT-ON* */
114 }
115
116 static void
117 vl_api_gbp_endpoint_del_t_handler (vl_api_gbp_endpoint_del_t * mp)
118 {
119   vl_api_gbp_endpoint_del_reply_t *rmp;
120   int rv = 0;
121
122   gbp_endpoint_delete (ntohl (mp->handle));
123
124   REPLY_MACRO (VL_API_GBP_ENDPOINT_DEL_REPLY + GBP_MSG_BASE);
125 }
126
127 typedef struct gbp_walk_ctx_t_
128 {
129   vl_api_registration_t *reg;
130   u32 context;
131 } gbp_walk_ctx_t;
132
133 static walk_rc_t
134 gbp_endpoint_send_details (gbp_endpoint_t * gbpe, void *args)
135 {
136   vl_api_gbp_endpoint_details_t *mp;
137   gbp_walk_ctx_t *ctx;
138   u8 n_ips, ii;
139
140   ctx = args;
141   n_ips = vec_len (gbpe->ge_ips);
142   mp = vl_msg_api_alloc (sizeof (*mp) + (sizeof (*mp->endpoint.ips) * n_ips));
143   if (!mp)
144     return 1;
145
146   clib_memset (mp, 0, sizeof (*mp));
147   mp->_vl_msg_id = ntohs (VL_API_GBP_ENDPOINT_DETAILS + GBP_MSG_BASE);
148   mp->context = ctx->context;
149
150   mp->endpoint.sw_if_index = ntohl (gbpe->ge_sw_if_index);
151   mp->endpoint.epg_id = ntohs (gbpe->ge_epg_id);
152   mp->endpoint.n_ips = n_ips;
153   mac_address_encode (&gbpe->ge_mac, &mp->endpoint.mac);
154
155   vec_foreach_index (ii, gbpe->ge_ips)
156   {
157     ip_address_encode (&gbpe->ge_ips[ii], IP46_TYPE_ANY,
158                        &mp->endpoint.ips[ii]);
159   }
160
161   vl_api_send_msg (ctx->reg, (u8 *) mp);
162
163   return (WALK_CONTINUE);
164 }
165
166 static void
167 vl_api_gbp_endpoint_dump_t_handler (vl_api_gbp_endpoint_dump_t * mp)
168 {
169   vl_api_registration_t *reg;
170
171   reg = vl_api_client_index_to_registration (mp->client_index);
172   if (!reg)
173     return;
174
175   gbp_walk_ctx_t ctx = {
176     .reg = reg,
177     .context = mp->context,
178   };
179
180   gbp_endpoint_walk (gbp_endpoint_send_details, &ctx);
181 }
182
183 static void
184   vl_api_gbp_endpoint_group_add_del_t_handler
185   (vl_api_gbp_endpoint_group_add_del_t * mp)
186 {
187   vl_api_gbp_endpoint_group_add_del_reply_t *rmp;
188   u32 uplink_sw_if_index;
189   int rv = 0;
190
191   uplink_sw_if_index = ntohl (mp->epg.uplink_sw_if_index);
192   if (!vnet_sw_if_index_is_api_valid (uplink_sw_if_index))
193     goto bad_sw_if_index;
194
195   if (mp->is_add)
196     {
197       rv = gbp_endpoint_group_add (ntohs (mp->epg.epg_id),
198                                    ntohl (mp->epg.bd_id),
199                                    ntohl (mp->epg.ip4_table_id),
200                                    ntohl (mp->epg.ip6_table_id),
201                                    uplink_sw_if_index);
202     }
203   else
204     {
205       gbp_endpoint_group_delete (ntohs (mp->epg.epg_id));
206     }
207
208   BAD_SW_IF_INDEX_LABEL;
209
210   REPLY_MACRO (VL_API_GBP_ENDPOINT_GROUP_ADD_DEL_REPLY + GBP_MSG_BASE);
211 }
212
213 static void
214 vl_api_gbp_subnet_add_del_t_handler (vl_api_gbp_subnet_add_del_t * mp)
215 {
216   vl_api_gbp_subnet_add_del_reply_t *rmp;
217   fib_prefix_t pfx;
218   int rv = 0;
219
220   ip_prefix_decode (&mp->subnet.prefix, &pfx);
221
222   rv = gbp_subnet_add_del (ntohl (mp->subnet.table_id),
223                            &pfx,
224                            ntohl (mp->subnet.sw_if_index),
225                            ntohs (mp->subnet.epg_id),
226                            mp->is_add, mp->subnet.is_internal);
227
228   REPLY_MACRO (VL_API_GBP_SUBNET_ADD_DEL_REPLY + GBP_MSG_BASE);
229 }
230
231 static int
232 gbp_subnet_send_details (u32 table_id,
233                          const fib_prefix_t * pfx,
234                          u32 sw_if_index,
235                          epg_id_t epg, u8 is_internal, void *args)
236 {
237   vl_api_gbp_subnet_details_t *mp;
238   gbp_walk_ctx_t *ctx;
239
240   ctx = args;
241   mp = vl_msg_api_alloc (sizeof (*mp));
242   if (!mp)
243     return 1;
244
245   clib_memset (mp, 0, sizeof (*mp));
246   mp->_vl_msg_id = ntohs (VL_API_GBP_SUBNET_DETAILS + GBP_MSG_BASE);
247   mp->context = ctx->context;
248
249   mp->subnet.is_internal = is_internal;
250   mp->subnet.sw_if_index = ntohl (sw_if_index);
251   mp->subnet.epg_id = ntohs (epg);
252   mp->subnet.table_id = ntohl (table_id);
253   ip_prefix_encode (pfx, &mp->subnet.prefix);
254
255   vl_api_send_msg (ctx->reg, (u8 *) mp);
256
257   return (1);
258 }
259
260 static void
261 vl_api_gbp_subnet_dump_t_handler (vl_api_gbp_subnet_dump_t * mp)
262 {
263   vl_api_registration_t *reg;
264
265   reg = vl_api_client_index_to_registration (mp->client_index);
266   if (!reg)
267     return;
268
269   gbp_walk_ctx_t ctx = {
270     .reg = reg,
271     .context = mp->context,
272   };
273
274   gbp_subnet_walk (gbp_subnet_send_details, &ctx);
275 }
276
277 static int
278 gbp_endpoint_group_send_details (gbp_endpoint_group_t * gepg, void *args)
279 {
280   vl_api_gbp_endpoint_group_details_t *mp;
281   gbp_walk_ctx_t *ctx;
282
283   ctx = args;
284   mp = vl_msg_api_alloc (sizeof (*mp));
285   if (!mp)
286     return 1;
287
288   clib_memset (mp, 0, sizeof (*mp));
289   mp->_vl_msg_id = ntohs (VL_API_GBP_ENDPOINT_GROUP_DETAILS + GBP_MSG_BASE);
290   mp->context = ctx->context;
291
292   mp->epg.uplink_sw_if_index = ntohl (gepg->gepg_uplink_sw_if_index);
293   mp->epg.epg_id = ntohs (gepg->gepg_id);
294   mp->epg.bd_id = ntohl (gepg->gepg_bd);
295   mp->epg.ip4_table_id = ntohl (gepg->gepg_rd[FIB_PROTOCOL_IP4]);
296   mp->epg.ip6_table_id = ntohl (gepg->gepg_rd[FIB_PROTOCOL_IP6]);
297
298   vl_api_send_msg (ctx->reg, (u8 *) mp);
299
300   return (1);
301 }
302
303 static void
304 vl_api_gbp_endpoint_group_dump_t_handler (vl_api_gbp_endpoint_group_dump_t *
305                                           mp)
306 {
307   vl_api_registration_t *reg;
308
309   reg = vl_api_client_index_to_registration (mp->client_index);
310   if (!reg)
311     return;
312
313   gbp_walk_ctx_t ctx = {
314     .reg = reg,
315     .context = mp->context,
316   };
317
318   gbp_endpoint_group_walk (gbp_endpoint_group_send_details, &ctx);
319 }
320
321 static void
322 vl_api_gbp_recirc_add_del_t_handler (vl_api_gbp_recirc_add_del_t * mp)
323 {
324   vl_api_gbp_recirc_add_del_reply_t *rmp;
325   u32 sw_if_index;
326   int rv = 0;
327
328   sw_if_index = ntohl (mp->recirc.sw_if_index);
329   if (!vnet_sw_if_index_is_api_valid (sw_if_index))
330     goto bad_sw_if_index;
331
332   if (mp->is_add)
333     gbp_recirc_add (sw_if_index,
334                     ntohs (mp->recirc.epg_id), mp->recirc.is_ext);
335   else
336     gbp_recirc_delete (sw_if_index);
337
338   BAD_SW_IF_INDEX_LABEL;
339
340   REPLY_MACRO (VL_API_GBP_RECIRC_ADD_DEL_REPLY + GBP_MSG_BASE);
341 }
342
343 static int
344 gbp_recirc_send_details (gbp_recirc_t * gr, void *args)
345 {
346   vl_api_gbp_recirc_details_t *mp;
347   gbp_walk_ctx_t *ctx;
348
349   ctx = args;
350   mp = vl_msg_api_alloc (sizeof (*mp));
351   if (!mp)
352     return 1;
353
354   clib_memset (mp, 0, sizeof (*mp));
355   mp->_vl_msg_id = ntohs (VL_API_GBP_RECIRC_DETAILS + GBP_MSG_BASE);
356   mp->context = ctx->context;
357
358   mp->recirc.epg_id = ntohs (gr->gr_epg);
359   mp->recirc.sw_if_index = ntohl (gr->gr_sw_if_index);
360   mp->recirc.is_ext = ntohl (gr->gr_is_ext);
361
362   vl_api_send_msg (ctx->reg, (u8 *) mp);
363
364   return (1);
365 }
366
367 static void
368 vl_api_gbp_recirc_dump_t_handler (vl_api_gbp_recirc_dump_t * mp)
369 {
370   vl_api_registration_t *reg;
371
372   reg = vl_api_client_index_to_registration (mp->client_index);
373   if (!reg)
374     return;
375
376   gbp_walk_ctx_t ctx = {
377     .reg = reg,
378     .context = mp->context,
379   };
380
381   gbp_recirc_walk (gbp_recirc_send_details, &ctx);
382 }
383
384 static void
385 vl_api_gbp_contract_add_del_t_handler (vl_api_gbp_contract_add_del_t * mp)
386 {
387   vl_api_gbp_contract_add_del_reply_t *rmp;
388   int rv = 0;
389
390   if (mp->is_add)
391     gbp_contract_update (ntohs (mp->contract.src_epg),
392                          ntohs (mp->contract.dst_epg),
393                          ntohl (mp->contract.acl_index));
394   else
395     gbp_contract_delete (ntohs (mp->contract.src_epg),
396                          ntohs (mp->contract.dst_epg));
397
398   REPLY_MACRO (VL_API_GBP_CONTRACT_ADD_DEL_REPLY + GBP_MSG_BASE);
399 }
400
401 static int
402 gbp_contract_send_details (gbp_contract_t * gbpc, void *args)
403 {
404   vl_api_gbp_contract_details_t *mp;
405   gbp_walk_ctx_t *ctx;
406
407   ctx = args;
408   mp = vl_msg_api_alloc (sizeof (*mp));
409   if (!mp)
410     return 1;
411
412   clib_memset (mp, 0, sizeof (*mp));
413   mp->_vl_msg_id = ntohs (VL_API_GBP_CONTRACT_DETAILS + GBP_MSG_BASE);
414   mp->context = ctx->context;
415
416   mp->contract.src_epg = ntohs (gbpc->gc_key.gck_src);
417   mp->contract.dst_epg = ntohs (gbpc->gc_key.gck_dst);
418   mp->contract.acl_index = ntohl (gbpc->gc_value.gc_acl_index);
419
420   vl_api_send_msg (ctx->reg, (u8 *) mp);
421
422   return (1);
423 }
424
425 static void
426 vl_api_gbp_contract_dump_t_handler (vl_api_gbp_contract_dump_t * mp)
427 {
428   vl_api_registration_t *reg;
429
430   reg = vl_api_client_index_to_registration (mp->client_index);
431   if (!reg)
432     return;
433
434   gbp_walk_ctx_t ctx = {
435     .reg = reg,
436     .context = mp->context,
437   };
438
439   gbp_contract_walk (gbp_contract_send_details, &ctx);
440 }
441
442 /*
443  * gbp_api_hookup
444  * Add vpe's API message handlers to the table.
445  * vlib has already mapped shared memory and
446  * added the client registration handlers.
447  * See .../vlib-api/vlibmemory/memclnt_vlib.c:memclnt_process()
448  */
449 #define vl_msg_name_crc_list
450 #include <gbp/gbp_all_api_h.h>
451 #undef vl_msg_name_crc_list
452
453 static void
454 setup_message_id_table (api_main_t * am)
455 {
456 #define _(id,n,crc)                                     \
457   vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id + GBP_MSG_BASE);
458   foreach_vl_msg_name_crc_gbp;
459 #undef _
460 }
461
462 static void
463 gbp_api_hookup (vlib_main_t * vm)
464 {
465 #define _(N,n)                                                  \
466     vl_msg_api_set_handlers(VL_API_##N + GBP_MSG_BASE,          \
467                             #n,                                 \
468                             vl_api_##n##_t_handler,             \
469                             vl_noop_handler,                    \
470                             vl_api_##n##_t_endian,              \
471                             vl_api_##n##_t_print,               \
472                             sizeof(vl_api_##n##_t), 1);
473   foreach_gbp_api_msg;
474 #undef _
475 }
476
477 static clib_error_t *
478 gbp_init (vlib_main_t * vm)
479 {
480   api_main_t *am = &api_main;
481   gbp_main_t *gbpm = &gbp_main;
482   u8 *name = format (0, "gbp_%08x%c", api_version, 0);
483
484   gbpm->gbp_acl_user_id = ~0;
485
486   /* Ask for a correctly-sized block of API message decode slots */
487   msg_id_base = vl_msg_api_get_msg_ids ((char *) name,
488                                         VL_MSG_FIRST_AVAILABLE);
489   gbp_api_hookup (vm);
490
491   /* Add our API messages to the global name_crc hash table */
492   setup_message_id_table (am);
493
494   vec_free (name);
495   return (NULL);
496 }
497
498 VLIB_API_INIT_FUNCTION (gbp_init);
499
500 /* *INDENT-OFF* */
501 VLIB_PLUGIN_REGISTER () = {
502     .version = VPP_BUILD_VER,
503     .description = "Group Based Policy",
504 };
505 /* *INDENT-ON* */
506
507
508 /*
509  * fd.io coding-style-patch-verification: ON
510  *
511  * Local Variables:
512  * eval: (c-set-style "gnu")
513  * End:
514  */