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