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