GBP: Sclass to src-epg conversions
[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 #include <gbp/gbp_learn.h>
29 #include <gbp/gbp_itf.h>
30 #include <gbp/gbp_vxlan.h>
31 #include <gbp/gbp_bridge_domain.h>
32 #include <gbp/gbp_route_domain.h>
33 #include <gbp/gbp_ext_itf.h>
34
35 #include <vlibapi/api.h>
36 #include <vlibmemory/api.h>
37
38 /* define message IDs */
39 #include <gbp/gbp_msg_enum.h>
40
41 #define vl_typedefs             /* define message structures */
42 #include <gbp/gbp_all_api_h.h>
43 #undef vl_typedefs
44
45 #define vl_endianfun            /* define message structures */
46 #include <gbp/gbp_all_api_h.h>
47 #undef vl_endianfun
48
49 /* instantiate all the print functions we know about */
50 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
51 #define vl_printfun
52 #include <gbp/gbp_all_api_h.h>
53 #undef vl_printfun
54
55 /* Get the API version number */
56 #define vl_api_version(n,v) static u32 api_version=(v);
57 #include <gbp/gbp_all_api_h.h>
58 #undef vl_api_version
59
60 #include <vlibapi/api_helper_macros.h>
61
62 #define foreach_gbp_api_msg                                 \
63   _(GBP_ENDPOINT_ADD, gbp_endpoint_add)                     \
64   _(GBP_ENDPOINT_DEL, gbp_endpoint_del)                     \
65   _(GBP_ENDPOINT_DUMP, gbp_endpoint_dump)                   \
66   _(GBP_SUBNET_ADD_DEL, gbp_subnet_add_del)                 \
67   _(GBP_SUBNET_DUMP, gbp_subnet_dump)                       \
68   _(GBP_ENDPOINT_GROUP_ADD, gbp_endpoint_group_add)         \
69   _(GBP_ENDPOINT_GROUP_DEL, gbp_endpoint_group_del)         \
70   _(GBP_ENDPOINT_GROUP_DUMP, gbp_endpoint_group_dump)       \
71   _(GBP_BRIDGE_DOMAIN_ADD, gbp_bridge_domain_add)           \
72   _(GBP_BRIDGE_DOMAIN_DEL, gbp_bridge_domain_del)           \
73   _(GBP_BRIDGE_DOMAIN_DUMP, gbp_bridge_domain_dump)         \
74   _(GBP_ROUTE_DOMAIN_ADD, gbp_route_domain_add)             \
75   _(GBP_ROUTE_DOMAIN_DEL, gbp_route_domain_del)             \
76   _(GBP_ROUTE_DOMAIN_DUMP, gbp_route_domain_dump)           \
77   _(GBP_RECIRC_ADD_DEL, gbp_recirc_add_del)                 \
78   _(GBP_RECIRC_DUMP, gbp_recirc_dump)                       \
79   _(GBP_EXT_ITF_ADD_DEL, gbp_ext_itf_add_del)               \
80   _(GBP_EXT_ITF_DUMP, gbp_ext_itf_dump)                     \
81   _(GBP_CONTRACT_ADD_DEL, gbp_contract_add_del)             \
82   _(GBP_CONTRACT_DUMP, gbp_contract_dump)                   \
83   _(GBP_ENDPOINT_LEARN_SET_INACTIVE_THRESHOLD, gbp_endpoint_learn_set_inactive_threshold) \
84   _(GBP_VXLAN_TUNNEL_ADD, gbp_vxlan_tunnel_add)                         \
85   _(GBP_VXLAN_TUNNEL_DEL, gbp_vxlan_tunnel_del)                         \
86   _(GBP_VXLAN_TUNNEL_DUMP, gbp_vxlan_tunnel_dump)
87
88 gbp_main_t gbp_main;
89
90 static u16 msg_id_base;
91
92 #define GBP_MSG_BASE msg_id_base
93
94 static gbp_endpoint_flags_t
95 gbp_endpoint_flags_decode (vl_api_gbp_endpoint_flags_t v)
96 {
97   gbp_endpoint_flags_t f = GBP_ENDPOINT_FLAG_NONE;
98
99   v = ntohl (v);
100
101   if (v & GBP_API_ENDPOINT_FLAG_BOUNCE)
102     f |= GBP_ENDPOINT_FLAG_BOUNCE;
103   if (v & GBP_API_ENDPOINT_FLAG_REMOTE)
104     f |= GBP_ENDPOINT_FLAG_REMOTE;
105   if (v & GBP_API_ENDPOINT_FLAG_LEARNT)
106     f |= GBP_ENDPOINT_FLAG_LEARNT;
107   if (v & GBP_API_ENDPOINT_FLAG_EXTERNAL)
108     f |= GBP_ENDPOINT_FLAG_EXTERNAL;
109
110   return (f);
111 }
112
113 static vl_api_gbp_endpoint_flags_t
114 gbp_endpoint_flags_encode (gbp_endpoint_flags_t f)
115 {
116   vl_api_gbp_endpoint_flags_t v = 0;
117
118
119   if (f & GBP_ENDPOINT_FLAG_BOUNCE)
120     v |= GBP_API_ENDPOINT_FLAG_BOUNCE;
121   if (f & GBP_ENDPOINT_FLAG_REMOTE)
122     v |= GBP_API_ENDPOINT_FLAG_REMOTE;
123   if (f & GBP_ENDPOINT_FLAG_LEARNT)
124     v |= GBP_API_ENDPOINT_FLAG_LEARNT;
125   if (f & GBP_ENDPOINT_FLAG_EXTERNAL)
126     v |= GBP_API_ENDPOINT_FLAG_EXTERNAL;
127
128   v = htonl (v);
129
130   return (v);
131 }
132
133 static void
134 vl_api_gbp_endpoint_add_t_handler (vl_api_gbp_endpoint_add_t * mp)
135 {
136   vl_api_gbp_endpoint_add_reply_t *rmp;
137   gbp_endpoint_flags_t gef;
138   u32 sw_if_index, handle;
139   ip46_address_t *ips;
140   mac_address_t mac;
141   int rv = 0, ii;
142
143   VALIDATE_SW_IF_INDEX (&(mp->endpoint));
144
145   gef = gbp_endpoint_flags_decode (mp->endpoint.flags), ips = NULL;
146   sw_if_index = ntohl (mp->endpoint.sw_if_index);
147
148   if (mp->endpoint.n_ips)
149     {
150       vec_validate (ips, mp->endpoint.n_ips - 1);
151
152       vec_foreach_index (ii, ips)
153       {
154         ip_address_decode (&mp->endpoint.ips[ii], &ips[ii]);
155       }
156     }
157   mac_address_decode (mp->endpoint.mac, &mac);
158
159   if (GBP_ENDPOINT_FLAG_REMOTE & gef)
160     {
161       ip46_address_t tun_src, tun_dst;
162
163       ip_address_decode (&mp->endpoint.tun.src, &tun_src);
164       ip_address_decode (&mp->endpoint.tun.dst, &tun_dst);
165
166       rv = gbp_endpoint_update_and_lock (GBP_ENDPOINT_SRC_CP,
167                                          sw_if_index, ips, &mac,
168                                          INDEX_INVALID, INDEX_INVALID,
169                                          ntohs (mp->endpoint.epg_id),
170                                          gef, &tun_src, &tun_dst, &handle);
171     }
172   else
173     {
174       rv = gbp_endpoint_update_and_lock (GBP_ENDPOINT_SRC_CP,
175                                          sw_if_index, ips, &mac,
176                                          INDEX_INVALID, INDEX_INVALID,
177                                          ntohs (mp->endpoint.epg_id),
178                                          gef, NULL, NULL, &handle);
179     }
180   vec_free (ips);
181   BAD_SW_IF_INDEX_LABEL;
182
183   /* *INDENT-OFF* */
184   REPLY_MACRO2 (VL_API_GBP_ENDPOINT_ADD_REPLY + GBP_MSG_BASE,
185   ({
186     rmp->handle = htonl (handle);
187   }));
188   /* *INDENT-ON* */
189 }
190
191 static void
192 vl_api_gbp_endpoint_del_t_handler (vl_api_gbp_endpoint_del_t * mp)
193 {
194   vl_api_gbp_endpoint_del_reply_t *rmp;
195   int rv = 0;
196
197   gbp_endpoint_unlock (GBP_ENDPOINT_SRC_CP, ntohl (mp->handle));
198
199   REPLY_MACRO (VL_API_GBP_ENDPOINT_DEL_REPLY + GBP_MSG_BASE);
200 }
201
202 static void
203   vl_api_gbp_endpoint_learn_set_inactive_threshold_t_handler
204   (vl_api_gbp_endpoint_learn_set_inactive_threshold_t * mp)
205 {
206   vl_api_gbp_endpoint_learn_set_inactive_threshold_reply_t *rmp;
207   int rv = 0;
208
209   gbp_learn_set_inactive_threshold (ntohl (mp->threshold));
210
211   REPLY_MACRO (VL_API_GBP_ENDPOINT_LEARN_SET_INACTIVE_THRESHOLD_REPLY +
212                GBP_MSG_BASE);
213 }
214
215 typedef struct gbp_walk_ctx_t_
216 {
217   vl_api_registration_t *reg;
218   u32 context;
219 } gbp_walk_ctx_t;
220
221 static walk_rc_t
222 gbp_endpoint_send_details (index_t gei, void *args)
223 {
224   vl_api_gbp_endpoint_details_t *mp;
225   gbp_endpoint_loc_t *gel;
226   gbp_endpoint_fwd_t *gef;
227   gbp_endpoint_t *ge;
228   gbp_walk_ctx_t *ctx;
229   u8 n_ips, ii;
230
231   ctx = args;
232   ge = gbp_endpoint_get (gei);
233
234   n_ips = vec_len (ge->ge_key.gek_ips);
235   mp = vl_msg_api_alloc (sizeof (*mp) + (sizeof (*mp->endpoint.ips) * n_ips));
236   if (!mp)
237     return 1;
238
239   clib_memset (mp, 0, sizeof (*mp));
240   mp->_vl_msg_id = ntohs (VL_API_GBP_ENDPOINT_DETAILS + GBP_MSG_BASE);
241   mp->context = ctx->context;
242
243   gel = &ge->ge_locs[0];
244   gef = &ge->ge_fwd;
245
246   if (gbp_endpoint_is_remote (ge))
247     {
248       mp->endpoint.sw_if_index = ntohl (gel->tun.gel_parent_sw_if_index);
249       ip_address_encode (&gel->tun.gel_src, IP46_TYPE_ANY,
250                          &mp->endpoint.tun.src);
251       ip_address_encode (&gel->tun.gel_dst, IP46_TYPE_ANY,
252                          &mp->endpoint.tun.dst);
253     }
254   else
255     {
256       mp->endpoint.sw_if_index = ntohl (gef->gef_itf);
257     }
258   mp->endpoint.epg_id = ntohs (ge->ge_fwd.gef_epg_id);
259   mp->endpoint.n_ips = n_ips;
260   mp->endpoint.flags = gbp_endpoint_flags_encode (gef->gef_flags);
261   mp->handle = htonl (gei);
262   mp->age = vlib_time_now (vlib_get_main ()) - ge->ge_last_time;
263   mac_address_encode (&ge->ge_key.gek_mac, mp->endpoint.mac);
264
265   vec_foreach_index (ii, ge->ge_key.gek_ips)
266   {
267     ip_address_encode (&ge->ge_key.gek_ips[ii].fp_addr,
268                        IP46_TYPE_ANY, &mp->endpoint.ips[ii]);
269   }
270
271   vl_api_send_msg (ctx->reg, (u8 *) mp);
272
273   return (WALK_CONTINUE);
274 }
275
276 static void
277 vl_api_gbp_endpoint_dump_t_handler (vl_api_gbp_endpoint_dump_t * mp)
278 {
279   vl_api_registration_t *reg;
280
281   reg = vl_api_client_index_to_registration (mp->client_index);
282   if (!reg)
283     return;
284
285   gbp_walk_ctx_t ctx = {
286     .reg = reg,
287     .context = mp->context,
288   };
289
290   gbp_endpoint_walk (gbp_endpoint_send_details, &ctx);
291 }
292
293 static void
294   vl_api_gbp_endpoint_group_add_t_handler
295   (vl_api_gbp_endpoint_group_add_t * mp)
296 {
297   vl_api_gbp_endpoint_group_add_reply_t *rmp;
298   int rv = 0;
299
300   rv = gbp_endpoint_group_add_and_lock (ntohs (mp->epg.epg_id),
301                                         ntohs (mp->epg.sclass),
302                                         ntohl (mp->epg.bd_id),
303                                         ntohl (mp->epg.rd_id),
304                                         ntohl (mp->epg.uplink_sw_if_index));
305
306   REPLY_MACRO (VL_API_GBP_ENDPOINT_GROUP_ADD_REPLY + GBP_MSG_BASE);
307 }
308
309 static void
310   vl_api_gbp_endpoint_group_del_t_handler
311   (vl_api_gbp_endpoint_group_del_t * mp)
312 {
313   vl_api_gbp_endpoint_group_del_reply_t *rmp;
314   int rv = 0;
315
316   rv = gbp_endpoint_group_delete (ntohs (mp->epg_id));
317
318   REPLY_MACRO (VL_API_GBP_ENDPOINT_GROUP_DEL_REPLY + GBP_MSG_BASE);
319 }
320
321 static gbp_bridge_domain_flags_t
322 gbp_bridge_domain_flags_from_api (vl_api_gbp_bridge_domain_flags_t a)
323 {
324   gbp_bridge_domain_flags_t g;
325
326   g = GBP_BD_FLAG_NONE;
327   a = clib_net_to_host_u32 (a);
328
329   if (a & GBP_BD_API_FLAG_DO_NOT_LEARN)
330     g |= GBP_BD_FLAG_DO_NOT_LEARN;
331
332   return (g);
333 }
334
335 static void
336 vl_api_gbp_bridge_domain_add_t_handler (vl_api_gbp_bridge_domain_add_t * mp)
337 {
338   vl_api_gbp_bridge_domain_add_reply_t *rmp;
339   int rv = 0;
340
341   rv = gbp_bridge_domain_add_and_lock (ntohl (mp->bd.bd_id),
342                                        gbp_bridge_domain_flags_from_api
343                                        (mp->bd.flags),
344                                        ntohl (mp->bd.bvi_sw_if_index),
345                                        ntohl (mp->bd.uu_fwd_sw_if_index),
346                                        ntohl (mp->bd.bm_flood_sw_if_index));
347
348   REPLY_MACRO (VL_API_GBP_BRIDGE_DOMAIN_ADD_REPLY + GBP_MSG_BASE);
349 }
350
351 static void
352 vl_api_gbp_bridge_domain_del_t_handler (vl_api_gbp_bridge_domain_del_t * mp)
353 {
354   vl_api_gbp_bridge_domain_del_reply_t *rmp;
355   int rv = 0;
356
357   rv = gbp_bridge_domain_delete (ntohl (mp->bd_id));
358
359   REPLY_MACRO (VL_API_GBP_BRIDGE_DOMAIN_DEL_REPLY + GBP_MSG_BASE);
360 }
361
362 static void
363 vl_api_gbp_route_domain_add_t_handler (vl_api_gbp_route_domain_add_t * mp)
364 {
365   vl_api_gbp_route_domain_add_reply_t *rmp;
366   int rv = 0;
367
368   rv = gbp_route_domain_add_and_lock (ntohl (mp->rd.rd_id),
369                                       ntohl (mp->rd.ip4_table_id),
370                                       ntohl (mp->rd.ip6_table_id),
371                                       ntohl (mp->rd.ip4_uu_sw_if_index),
372                                       ntohl (mp->rd.ip6_uu_sw_if_index));
373
374   REPLY_MACRO (VL_API_GBP_ROUTE_DOMAIN_ADD_REPLY + GBP_MSG_BASE);
375 }
376
377 static void
378 vl_api_gbp_route_domain_del_t_handler (vl_api_gbp_route_domain_del_t * mp)
379 {
380   vl_api_gbp_route_domain_del_reply_t *rmp;
381   int rv = 0;
382
383   rv = gbp_route_domain_delete (ntohl (mp->rd_id));
384
385   REPLY_MACRO (VL_API_GBP_ROUTE_DOMAIN_DEL_REPLY + GBP_MSG_BASE);
386 }
387
388 static int
389 gub_subnet_type_from_api (vl_api_gbp_subnet_type_t a, gbp_subnet_type_t * t)
390 {
391   a = clib_net_to_host_u32 (a);
392
393   switch (a)
394     {
395     case GBP_API_SUBNET_TRANSPORT:
396       *t = GBP_SUBNET_TRANSPORT;
397       return (0);
398     case GBP_API_SUBNET_L3_OUT:
399       *t = GBP_SUBNET_L3_OUT;
400       return (0);
401     case GBP_API_SUBNET_STITCHED_INTERNAL:
402       *t = GBP_SUBNET_STITCHED_INTERNAL;
403       return (0);
404     case GBP_API_SUBNET_STITCHED_EXTERNAL:
405       *t = GBP_SUBNET_STITCHED_EXTERNAL;
406       return (0);
407     }
408
409   return (-1);
410 }
411
412 static void
413 vl_api_gbp_subnet_add_del_t_handler (vl_api_gbp_subnet_add_del_t * mp)
414 {
415   vl_api_gbp_subnet_add_del_reply_t *rmp;
416   gbp_subnet_type_t type;
417   fib_prefix_t pfx;
418   int rv = 0;
419
420   ip_prefix_decode (&mp->subnet.prefix, &pfx);
421
422   rv = gub_subnet_type_from_api (mp->subnet.type, &type);
423
424   if (0 != rv)
425     goto out;
426
427   if (mp->is_add)
428     rv = gbp_subnet_add (ntohl (mp->subnet.rd_id),
429                          &pfx, type,
430                          ntohl (mp->subnet.sw_if_index),
431                          ntohs (mp->subnet.epg_id));
432   else
433     rv = gbp_subnet_del (ntohl (mp->subnet.rd_id), &pfx);
434
435 out:
436   REPLY_MACRO (VL_API_GBP_SUBNET_ADD_DEL_REPLY + GBP_MSG_BASE);
437 }
438
439 static vl_api_gbp_subnet_type_t
440 gub_subnet_type_to_api (gbp_subnet_type_t t)
441 {
442   vl_api_gbp_subnet_type_t a = 0;
443
444   switch (t)
445     {
446     case GBP_SUBNET_TRANSPORT:
447       a = GBP_API_SUBNET_TRANSPORT;
448       break;
449     case GBP_SUBNET_STITCHED_INTERNAL:
450       a = GBP_API_SUBNET_STITCHED_INTERNAL;
451       break;
452     case GBP_SUBNET_STITCHED_EXTERNAL:
453       a = GBP_API_SUBNET_STITCHED_EXTERNAL;
454       break;
455     case GBP_SUBNET_L3_OUT:
456       a = GBP_API_SUBNET_L3_OUT;
457       break;
458     }
459
460   a = clib_host_to_net_u32 (a);
461
462   return (a);
463 }
464
465 static walk_rc_t
466 gbp_subnet_send_details (u32 rd_id,
467                          const fib_prefix_t * pfx,
468                          gbp_subnet_type_t type,
469                          u32 sw_if_index, epg_id_t epg, void *args)
470 {
471   vl_api_gbp_subnet_details_t *mp;
472   gbp_walk_ctx_t *ctx;
473
474   ctx = args;
475   mp = vl_msg_api_alloc (sizeof (*mp));
476   if (!mp)
477     return 1;
478
479   clib_memset (mp, 0, sizeof (*mp));
480   mp->_vl_msg_id = ntohs (VL_API_GBP_SUBNET_DETAILS + GBP_MSG_BASE);
481   mp->context = ctx->context;
482
483   mp->subnet.type = gub_subnet_type_to_api (type);
484   mp->subnet.sw_if_index = ntohl (sw_if_index);
485   mp->subnet.epg_id = ntohs (epg);
486   mp->subnet.rd_id = ntohl (rd_id);
487   ip_prefix_encode (pfx, &mp->subnet.prefix);
488
489   vl_api_send_msg (ctx->reg, (u8 *) mp);
490
491   return (WALK_CONTINUE);
492 }
493
494 static void
495 vl_api_gbp_subnet_dump_t_handler (vl_api_gbp_subnet_dump_t * mp)
496 {
497   vl_api_registration_t *reg;
498
499   reg = vl_api_client_index_to_registration (mp->client_index);
500   if (!reg)
501     return;
502
503   gbp_walk_ctx_t ctx = {
504     .reg = reg,
505     .context = mp->context,
506   };
507
508   gbp_subnet_walk (gbp_subnet_send_details, &ctx);
509 }
510
511 static int
512 gbp_endpoint_group_send_details (gbp_endpoint_group_t * gg, void *args)
513 {
514   vl_api_gbp_endpoint_group_details_t *mp;
515   gbp_walk_ctx_t *ctx;
516
517   ctx = args;
518   mp = vl_msg_api_alloc (sizeof (*mp));
519   if (!mp)
520     return 1;
521
522   clib_memset (mp, 0, sizeof (*mp));
523   mp->_vl_msg_id = ntohs (VL_API_GBP_ENDPOINT_GROUP_DETAILS + GBP_MSG_BASE);
524   mp->context = ctx->context;
525
526   mp->epg.uplink_sw_if_index = ntohl (gg->gg_uplink_sw_if_index);
527   mp->epg.epg_id = ntohs (gg->gg_id);
528   mp->epg.sclass = ntohs (gg->gg_sclass);
529   mp->epg.bd_id = ntohl (gbp_endpoint_group_get_bd_id (gg));
530   mp->epg.rd_id = ntohl (gbp_route_domain_get_rd_id (gg->gg_rd));
531
532   vl_api_send_msg (ctx->reg, (u8 *) mp);
533
534   return (1);
535 }
536
537 static void
538 vl_api_gbp_endpoint_group_dump_t_handler (vl_api_gbp_endpoint_group_dump_t *
539                                           mp)
540 {
541   vl_api_registration_t *reg;
542
543   reg = vl_api_client_index_to_registration (mp->client_index);
544   if (!reg)
545     return;
546
547   gbp_walk_ctx_t ctx = {
548     .reg = reg,
549     .context = mp->context,
550   };
551
552   gbp_endpoint_group_walk (gbp_endpoint_group_send_details, &ctx);
553 }
554
555 static int
556 gbp_bridge_domain_send_details (gbp_bridge_domain_t * gb, void *args)
557 {
558   vl_api_gbp_bridge_domain_details_t *mp;
559   gbp_walk_ctx_t *ctx;
560
561   ctx = args;
562   mp = vl_msg_api_alloc (sizeof (*mp));
563   if (!mp)
564     return 1;
565
566   memset (mp, 0, sizeof (*mp));
567   mp->_vl_msg_id = ntohs (VL_API_GBP_BRIDGE_DOMAIN_DETAILS + GBP_MSG_BASE);
568   mp->context = ctx->context;
569
570   mp->bd.bd_id = ntohl (gb->gb_bd_id);
571   mp->bd.bvi_sw_if_index = ntohl (gb->gb_bvi_sw_if_index);
572   mp->bd.uu_fwd_sw_if_index = ntohl (gb->gb_uu_fwd_sw_if_index);
573   mp->bd.bm_flood_sw_if_index = ntohl (gb->gb_bm_flood_sw_if_index);
574
575   vl_api_send_msg (ctx->reg, (u8 *) mp);
576
577   return (1);
578 }
579
580 static void
581 vl_api_gbp_bridge_domain_dump_t_handler (vl_api_gbp_bridge_domain_dump_t * mp)
582 {
583   vl_api_registration_t *reg;
584
585   reg = vl_api_client_index_to_registration (mp->client_index);
586   if (!reg)
587     return;
588
589   gbp_walk_ctx_t ctx = {
590     .reg = reg,
591     .context = mp->context,
592   };
593
594   gbp_bridge_domain_walk (gbp_bridge_domain_send_details, &ctx);
595 }
596
597 static int
598 gbp_route_domain_send_details (gbp_route_domain_t * grd, void *args)
599 {
600   vl_api_gbp_route_domain_details_t *mp;
601   gbp_walk_ctx_t *ctx;
602
603   ctx = args;
604   mp = vl_msg_api_alloc (sizeof (*mp));
605   if (!mp)
606     return 1;
607
608   memset (mp, 0, sizeof (*mp));
609   mp->_vl_msg_id = ntohs (VL_API_GBP_ROUTE_DOMAIN_DETAILS + GBP_MSG_BASE);
610   mp->context = ctx->context;
611
612   mp->rd.rd_id = ntohl (grd->grd_id);
613   mp->rd.ip4_uu_sw_if_index =
614     ntohl (grd->grd_uu_sw_if_index[FIB_PROTOCOL_IP4]);
615   mp->rd.ip6_uu_sw_if_index =
616     ntohl (grd->grd_uu_sw_if_index[FIB_PROTOCOL_IP6]);
617
618   vl_api_send_msg (ctx->reg, (u8 *) mp);
619
620   return (1);
621 }
622
623 static void
624 vl_api_gbp_route_domain_dump_t_handler (vl_api_gbp_route_domain_dump_t * mp)
625 {
626   vl_api_registration_t *reg;
627
628   reg = vl_api_client_index_to_registration (mp->client_index);
629   if (!reg)
630     return;
631
632   gbp_walk_ctx_t ctx = {
633     .reg = reg,
634     .context = mp->context,
635   };
636
637   gbp_route_domain_walk (gbp_route_domain_send_details, &ctx);
638 }
639
640 static void
641 vl_api_gbp_recirc_add_del_t_handler (vl_api_gbp_recirc_add_del_t * mp)
642 {
643   vl_api_gbp_recirc_add_del_reply_t *rmp;
644   u32 sw_if_index;
645   int rv = 0;
646
647   sw_if_index = ntohl (mp->recirc.sw_if_index);
648   if (!vnet_sw_if_index_is_api_valid (sw_if_index))
649     goto bad_sw_if_index;
650
651   if (mp->is_add)
652     rv = gbp_recirc_add (sw_if_index,
653                          ntohs (mp->recirc.epg_id), mp->recirc.is_ext);
654   else
655     rv = gbp_recirc_delete (sw_if_index);
656
657   BAD_SW_IF_INDEX_LABEL;
658
659   REPLY_MACRO (VL_API_GBP_RECIRC_ADD_DEL_REPLY + GBP_MSG_BASE);
660 }
661
662 static walk_rc_t
663 gbp_recirc_send_details (gbp_recirc_t * gr, void *args)
664 {
665   vl_api_gbp_recirc_details_t *mp;
666   gbp_walk_ctx_t *ctx;
667
668   ctx = args;
669   mp = vl_msg_api_alloc (sizeof (*mp));
670   if (!mp)
671     return (WALK_STOP);
672
673   clib_memset (mp, 0, sizeof (*mp));
674   mp->_vl_msg_id = ntohs (VL_API_GBP_RECIRC_DETAILS + GBP_MSG_BASE);
675   mp->context = ctx->context;
676
677   mp->recirc.epg_id = ntohs (gr->gr_epg);
678   mp->recirc.sw_if_index = ntohl (gr->gr_sw_if_index);
679   mp->recirc.is_ext = gr->gr_is_ext;
680
681   vl_api_send_msg (ctx->reg, (u8 *) mp);
682
683   return (WALK_CONTINUE);
684 }
685
686 static void
687 vl_api_gbp_recirc_dump_t_handler (vl_api_gbp_recirc_dump_t * mp)
688 {
689   vl_api_registration_t *reg;
690
691   reg = vl_api_client_index_to_registration (mp->client_index);
692   if (!reg)
693     return;
694
695   gbp_walk_ctx_t ctx = {
696     .reg = reg,
697     .context = mp->context,
698   };
699
700   gbp_recirc_walk (gbp_recirc_send_details, &ctx);
701 }
702
703 static void
704 vl_api_gbp_ext_itf_add_del_t_handler (vl_api_gbp_ext_itf_add_del_t * mp)
705 {
706   vl_api_gbp_ext_itf_add_del_reply_t *rmp;
707   u32 sw_if_index = ~0;
708   vl_api_gbp_ext_itf_t *ext_itf;
709   int rv = 0;
710
711   ext_itf = &mp->ext_itf;
712   if (ext_itf)
713     sw_if_index = ntohl (ext_itf->sw_if_index);
714
715   if (!vnet_sw_if_index_is_api_valid (sw_if_index))
716     goto bad_sw_if_index;
717
718   if (mp->is_add)
719     rv = gbp_ext_itf_add (sw_if_index,
720                           ntohl (ext_itf->bd_id), ntohl (ext_itf->rd_id));
721   else
722     rv = gbp_ext_itf_delete (sw_if_index);
723
724   BAD_SW_IF_INDEX_LABEL;
725
726   REPLY_MACRO (VL_API_GBP_EXT_ITF_ADD_DEL_REPLY + GBP_MSG_BASE);
727 }
728
729 static walk_rc_t
730 gbp_ext_itf_send_details (gbp_ext_itf_t * gx, void *args)
731 {
732   vl_api_gbp_ext_itf_details_t *mp;
733   gbp_walk_ctx_t *ctx;
734
735   ctx = args;
736   mp = vl_msg_api_alloc (sizeof (*mp));
737   if (!mp)
738     return (WALK_STOP);
739
740   clib_memset (mp, 0, sizeof (*mp));
741   mp->_vl_msg_id = ntohs (VL_API_GBP_EXT_ITF_DETAILS + GBP_MSG_BASE);
742   mp->context = ctx->context;
743
744   mp->ext_itf.bd_id = ntohl (gbp_bridge_domain_get_bd_id (gx->gx_bd));
745   mp->ext_itf.rd_id = ntohl (gbp_route_domain_get_rd_id (gx->gx_rd));
746   mp->ext_itf.sw_if_index = ntohl (gx->gx_itf);
747
748   vl_api_send_msg (ctx->reg, (u8 *) mp);
749
750   return (WALK_CONTINUE);
751 }
752
753 static void
754 vl_api_gbp_ext_itf_dump_t_handler (vl_api_gbp_ext_itf_dump_t * mp)
755 {
756   vl_api_registration_t *reg;
757
758   reg = vl_api_client_index_to_registration (mp->client_index);
759   if (!reg)
760     return;
761
762   gbp_walk_ctx_t ctx = {
763     .reg = reg,
764     .context = mp->context,
765   };
766
767   gbp_ext_itf_walk (gbp_ext_itf_send_details, &ctx);
768 }
769
770 static int
771 gbp_contract_rule_action_deocde (vl_api_gbp_rule_action_t in,
772                                  gbp_rule_action_t * out)
773 {
774   in = clib_net_to_host_u32 (in);
775
776   switch (in)
777     {
778     case GBP_API_RULE_PERMIT:
779       *out = GBP_RULE_PERMIT;
780       return (0);
781     case GBP_API_RULE_DENY:
782       *out = GBP_RULE_DENY;
783       return (0);
784     case GBP_API_RULE_REDIRECT:
785       *out = GBP_RULE_REDIRECT;
786       return (0);
787     }
788
789   return (-1);
790 }
791
792 static int
793 gbp_hash_mode_decode (vl_api_gbp_hash_mode_t in, gbp_hash_mode_t * out)
794 {
795   in = clib_net_to_host_u32 (in);
796
797   switch (in)
798     {
799     case GBP_API_HASH_MODE_SRC_IP:
800       *out = GBP_HASH_MODE_SRC_IP;
801       return (0);
802     case GBP_API_HASH_MODE_DST_IP:
803       *out = GBP_HASH_MODE_DST_IP;
804       return (0);
805     case GBP_API_HASH_MODE_SYMMETRIC:
806       *out = GBP_HASH_MODE_SYMMETRIC;
807       return (0);
808     }
809
810   return (-2);
811 }
812
813 static int
814 gbp_next_hop_decode (const vl_api_gbp_next_hop_t * in, index_t * gnhi)
815 {
816   ip46_address_t ip;
817   mac_address_t mac;
818   index_t grd, gbd;
819
820   gbd = gbp_bridge_domain_find_and_lock (ntohl (in->bd_id));
821
822   if (INDEX_INVALID == gbd)
823     return (VNET_API_ERROR_BD_NOT_MODIFIABLE);
824
825   grd = gbp_route_domain_find_and_lock (ntohl (in->rd_id));
826
827   if (INDEX_INVALID == grd)
828     return (VNET_API_ERROR_NO_SUCH_FIB);
829
830   ip_address_decode (&in->ip, &ip);
831   mac_address_decode (in->mac, &mac);
832
833   *gnhi = gbp_next_hop_alloc (&ip, grd, &mac, gbd);
834
835   return (0);
836 }
837
838 static int
839 gbp_next_hop_set_decode (const vl_api_gbp_next_hop_set_t * in,
840                          gbp_hash_mode_t * hash_mode, index_t ** out)
841 {
842
843   index_t *gnhis = NULL;
844   int rv;
845   u8 ii;
846
847   rv = gbp_hash_mode_decode (in->hash_mode, hash_mode);
848
849   if (0 != rv)
850     return rv;
851
852   vec_validate (gnhis, in->n_nhs - 1);
853
854   for (ii = 0; ii < in->n_nhs; ii++)
855     {
856       rv = gbp_next_hop_decode (&in->nhs[ii], &gnhis[ii]);
857
858       if (0 != rv)
859         {
860           vec_free (gnhis);
861           break;
862         }
863     }
864
865   *out = gnhis;
866   return (rv);
867 }
868
869 static int
870 gbp_contract_rule_decode (const vl_api_gbp_rule_t * in, index_t * gui)
871 {
872   gbp_hash_mode_t hash_mode;
873   gbp_rule_action_t action;
874   index_t *nhs = NULL;
875   int rv;
876
877   rv = gbp_contract_rule_action_deocde (in->action, &action);
878
879   if (0 != rv)
880     return rv;
881
882   if (GBP_RULE_REDIRECT == action)
883     {
884       rv = gbp_next_hop_set_decode (&in->nh_set, &hash_mode, &nhs);
885
886       if (0 != rv)
887         return (rv);
888     }
889   else
890     {
891       hash_mode = GBP_HASH_MODE_SRC_IP;
892     }
893
894   *gui = gbp_rule_alloc (action, hash_mode, nhs);
895
896   return (rv);
897 }
898
899 static int
900 gbp_contract_rules_decode (u8 n_rules,
901                            const vl_api_gbp_rule_t * rules, index_t ** out)
902 {
903   index_t *guis = NULL;
904   int rv;
905   u8 ii;
906
907   if (0 == n_rules)
908     {
909       *out = NULL;
910       return (0);
911     }
912
913   vec_validate (guis, n_rules - 1);
914
915   for (ii = 0; ii < n_rules; ii++)
916     {
917       rv = gbp_contract_rule_decode (&rules[ii], &guis[ii]);
918
919       if (0 != rv)
920         {
921           vec_free (guis);
922           return (rv);
923         }
924     }
925
926   *out = guis;
927   return (rv);
928 }
929
930 static void
931 vl_api_gbp_contract_add_del_t_handler (vl_api_gbp_contract_add_del_t * mp)
932 {
933   vl_api_gbp_contract_add_del_reply_t *rmp;
934   u16 *allowed_ethertypes;
935   index_t *rules;
936   int ii, rv = 0;
937   u8 *data, n_et;
938   u16 *et;
939
940   if (mp->is_add)
941     {
942       rv = gbp_contract_rules_decode (mp->contract.n_rules,
943                                       mp->contract.rules, &rules);
944       if (0 != rv)
945         goto out;
946
947       allowed_ethertypes = NULL;
948
949       /*
950        * move past the variable legnth array of rules to get to the
951        * allowed ether types
952        */
953       data = (((u8 *) & mp->contract.n_ether_types) +
954               (sizeof (mp->contract.rules[0]) * mp->contract.n_rules));
955       n_et = *data;
956       et = (u16 *) (++data);
957       vec_validate (allowed_ethertypes, n_et - 1);
958
959       for (ii = 0; ii < n_et; ii++)
960         {
961           /* leave the ether types in network order */
962           allowed_ethertypes[ii] = et[ii];
963         }
964
965       rv = gbp_contract_update (ntohs (mp->contract.src_epg),
966                                 ntohs (mp->contract.dst_epg),
967                                 ntohl (mp->contract.acl_index),
968                                 rules, allowed_ethertypes);
969     }
970   else
971     rv = gbp_contract_delete (ntohs (mp->contract.src_epg),
972                               ntohs (mp->contract.dst_epg));
973
974 out:
975   REPLY_MACRO (VL_API_GBP_CONTRACT_ADD_DEL_REPLY + GBP_MSG_BASE);
976 }
977
978 static int
979 gbp_contract_send_details (gbp_contract_t * gbpc, void *args)
980 {
981   vl_api_gbp_contract_details_t *mp;
982   gbp_walk_ctx_t *ctx;
983
984   ctx = args;
985   mp = vl_msg_api_alloc (sizeof (*mp));
986   if (!mp)
987     return 1;
988
989   clib_memset (mp, 0, sizeof (*mp));
990   mp->_vl_msg_id = ntohs (VL_API_GBP_CONTRACT_DETAILS + GBP_MSG_BASE);
991   mp->context = ctx->context;
992
993   mp->contract.src_epg = ntohs (gbpc->gc_key.gck_src);
994   mp->contract.dst_epg = ntohs (gbpc->gc_key.gck_dst);
995   // mp->contract.acl_index = ntohl (gbpc->gc_value.gc_acl_index);
996
997   vl_api_send_msg (ctx->reg, (u8 *) mp);
998
999   return (1);
1000 }
1001
1002 static void
1003 vl_api_gbp_contract_dump_t_handler (vl_api_gbp_contract_dump_t * mp)
1004 {
1005   vl_api_registration_t *reg;
1006
1007   reg = vl_api_client_index_to_registration (mp->client_index);
1008   if (!reg)
1009     return;
1010
1011   gbp_walk_ctx_t ctx = {
1012     .reg = reg,
1013     .context = mp->context,
1014   };
1015
1016   gbp_contract_walk (gbp_contract_send_details, &ctx);
1017 }
1018
1019 static int
1020 gbp_vxlan_tunnel_mode_2_layer (vl_api_gbp_vxlan_tunnel_mode_t mode,
1021                                gbp_vxlan_tunnel_layer_t * l)
1022 {
1023   mode = clib_net_to_host_u32 (mode);
1024
1025   switch (mode)
1026     {
1027     case GBP_VXLAN_TUNNEL_MODE_L2:
1028       *l = GBP_VXLAN_TUN_L2;
1029       return (0);
1030     case GBP_VXLAN_TUNNEL_MODE_L3:
1031       *l = GBP_VXLAN_TUN_L3;
1032       return (0);
1033     }
1034   return (-1);
1035 }
1036
1037 static void
1038 vl_api_gbp_vxlan_tunnel_add_t_handler (vl_api_gbp_vxlan_tunnel_add_t * mp)
1039 {
1040   vl_api_gbp_vxlan_tunnel_add_reply_t *rmp;
1041   gbp_vxlan_tunnel_layer_t layer;
1042   u32 sw_if_index;
1043   int rv = 0;
1044
1045   rv = gbp_vxlan_tunnel_mode_2_layer (mp->tunnel.mode, &layer);
1046
1047   if (0 != rv)
1048     goto out;
1049
1050   rv = gbp_vxlan_tunnel_add (ntohl (mp->tunnel.vni),
1051                              layer,
1052                              ntohl (mp->tunnel.bd_rd_id), &sw_if_index);
1053
1054 out:
1055   /* *INDENT-OFF* */
1056   REPLY_MACRO2 (VL_API_GBP_VXLAN_TUNNEL_ADD_REPLY + GBP_MSG_BASE,
1057   ({
1058     rmp->sw_if_index = htonl (sw_if_index);
1059   }));
1060   /* *INDENT-ON* */
1061 }
1062
1063 static void
1064 vl_api_gbp_vxlan_tunnel_del_t_handler (vl_api_gbp_vxlan_tunnel_add_t * mp)
1065 {
1066   vl_api_gbp_vxlan_tunnel_del_reply_t *rmp;
1067   int rv = 0;
1068
1069   rv = gbp_vxlan_tunnel_del (ntohl (mp->tunnel.vni));
1070
1071   REPLY_MACRO (VL_API_GBP_VXLAN_TUNNEL_DEL_REPLY + GBP_MSG_BASE);
1072 }
1073
1074 static vl_api_gbp_vxlan_tunnel_mode_t
1075 gbp_vxlan_tunnel_layer_2_mode (gbp_vxlan_tunnel_layer_t layer)
1076 {
1077   vl_api_gbp_vxlan_tunnel_mode_t mode = GBP_VXLAN_TUNNEL_MODE_L2;
1078
1079   switch (layer)
1080     {
1081     case GBP_VXLAN_TUN_L2:
1082       mode = GBP_VXLAN_TUNNEL_MODE_L2;
1083       break;
1084     case GBP_VXLAN_TUN_L3:
1085       mode = GBP_VXLAN_TUNNEL_MODE_L3;
1086       break;
1087     }
1088   mode = clib_host_to_net_u32 (mode);
1089
1090   return (mode);
1091 }
1092
1093 static walk_rc_t
1094 gbp_vxlan_tunnel_send_details (gbp_vxlan_tunnel_t * gt, void *args)
1095 {
1096   vl_api_gbp_vxlan_tunnel_details_t *mp;
1097   gbp_walk_ctx_t *ctx;
1098
1099   ctx = args;
1100   mp = vl_msg_api_alloc (sizeof (*mp));
1101   if (!mp)
1102     return 1;
1103
1104   memset (mp, 0, sizeof (*mp));
1105   mp->_vl_msg_id = htons (VL_API_GBP_VXLAN_TUNNEL_DETAILS + GBP_MSG_BASE);
1106   mp->context = ctx->context;
1107
1108   mp->tunnel.vni = htonl (gt->gt_vni);
1109   mp->tunnel.mode = gbp_vxlan_tunnel_layer_2_mode (gt->gt_layer);
1110   mp->tunnel.bd_rd_id = htonl (gt->gt_bd_rd_id);
1111
1112   vl_api_send_msg (ctx->reg, (u8 *) mp);
1113
1114   return (1);
1115 }
1116
1117 static void
1118 vl_api_gbp_vxlan_tunnel_dump_t_handler (vl_api_gbp_vxlan_tunnel_dump_t * mp)
1119 {
1120   vl_api_registration_t *reg;
1121
1122   reg = vl_api_client_index_to_registration (mp->client_index);
1123   if (!reg)
1124     return;
1125
1126   gbp_walk_ctx_t ctx = {
1127     .reg = reg,
1128     .context = mp->context,
1129   };
1130
1131   gbp_vxlan_walk (gbp_vxlan_tunnel_send_details, &ctx);
1132 }
1133
1134 /*
1135  * gbp_api_hookup
1136  * Add vpe's API message handlers to the table.
1137  * vlib has already mapped shared memory and
1138  * added the client registration handlers.
1139  * See .../vlib-api/vlibmemory/memclnt_vlib.c:memclnt_process()
1140  */
1141 #define vl_msg_name_crc_list
1142 #include <gbp/gbp_all_api_h.h>
1143 #undef vl_msg_name_crc_list
1144
1145 static void
1146 setup_message_id_table (api_main_t * am)
1147 {
1148 #define _(id,n,crc)                                     \
1149   vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id + GBP_MSG_BASE);
1150   foreach_vl_msg_name_crc_gbp;
1151 #undef _
1152 }
1153
1154 static void
1155 gbp_api_hookup (vlib_main_t * vm)
1156 {
1157 #define _(N,n)                                                  \
1158     vl_msg_api_set_handlers(VL_API_##N + GBP_MSG_BASE,          \
1159                             #n,                                 \
1160                             vl_api_##n##_t_handler,             \
1161                             vl_noop_handler,                    \
1162                             vl_api_##n##_t_endian,              \
1163                             vl_api_##n##_t_print,               \
1164                             sizeof(vl_api_##n##_t), 1);
1165   foreach_gbp_api_msg;
1166 #undef _
1167 }
1168
1169 static clib_error_t *
1170 gbp_init (vlib_main_t * vm)
1171 {
1172   api_main_t *am = &api_main;
1173   gbp_main_t *gbpm = &gbp_main;
1174   u8 *name = format (0, "gbp_%08x%c", api_version, 0);
1175
1176   gbpm->gbp_acl_user_id = ~0;
1177
1178   /* Ask for a correctly-sized block of API message decode slots */
1179   msg_id_base = vl_msg_api_get_msg_ids ((char *) name,
1180                                         VL_MSG_FIRST_AVAILABLE);
1181   gbp_api_hookup (vm);
1182
1183   /* Add our API messages to the global name_crc hash table */
1184   setup_message_id_table (am);
1185
1186   vec_free (name);
1187   return (NULL);
1188 }
1189
1190 VLIB_API_INIT_FUNCTION (gbp_init);
1191
1192 /* *INDENT-OFF* */
1193 VLIB_PLUGIN_REGISTER () = {
1194     .version = VPP_BUILD_VER,
1195     .description = "Group Based Policy",
1196 };
1197 /* *INDENT-ON* */
1198
1199
1200 /*
1201  * fd.io coding-style-patch-verification: ON
1202  *
1203  * Local Variables:
1204  * eval: (c-set-style "gnu")
1205  * End:
1206  */