API refactoring : flow
[vpp.git] / src / vpp / api / api.c
1 /*
2  *------------------------------------------------------------------
3  * api.c - message handler registration
4  *
5  * Copyright (c) 2010-2016 Cisco and/or its affiliates.
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at:
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *------------------------------------------------------------------
18  */
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <sys/types.h>
24 #include <sys/mman.h>
25 #include <sys/stat.h>
26 #include <netinet/in.h>
27 #include <signal.h>
28 #include <pthread.h>
29 #include <unistd.h>
30 #include <time.h>
31 #include <fcntl.h>
32 #include <string.h>
33 #include <pwd.h>
34 #include <grp.h>
35
36 #include <vppinfra/clib.h>
37 #include <vppinfra/vec.h>
38 #include <vppinfra/hash.h>
39 #include <vppinfra/bitmap.h>
40 #include <vppinfra/fifo.h>
41 #include <vppinfra/time.h>
42 #include <vppinfra/mheap.h>
43 #include <vppinfra/heap.h>
44 #include <vppinfra/pool.h>
45 #include <vppinfra/format.h>
46 #include <vppinfra/error.h>
47
48 #include <vnet/api_errno.h>
49 #include <vnet/vnet.h>
50 #include <vnet/l2/l2_input.h>
51 #include <vnet/l2/l2_bd.h>
52 #include <vnet/ip/ip.h>
53 #include <vnet/ip/ip6.h>
54 #include <vnet/ip/ip6_neighbor.h>
55 #include <vnet/dhcp/proxy.h>
56 #include <vnet/dhcp/client.h>
57 #if WITH_LIBSSL > 0
58 #include <vnet/sr/sr.h>
59 #endif
60 #include <vnet/dhcpv6/proxy.h>
61 #include <vlib/vlib.h>
62 #include <vlib/unix/unix.h>
63 #include <vlibapi/api.h>
64 #include <vlibmemory/api.h>
65 #include <vnet/classify/input_acl.h>
66 #include <vnet/l2/l2_classify.h>
67 #include <vnet/vxlan/vxlan.h>
68 #include <vnet/l2/l2_vtr.h>
69 #include <vnet/vxlan-gpe/vxlan_gpe.h>
70 #include <vnet/map/map.h>
71 #include <vnet/cop/cop.h>
72 #include <vnet/ip/ip6_hop_by_hop.h>
73 #include <vnet/ip/ip_source_and_port_range_check.h>
74 #include <vnet/policer/policer.h>
75 #include <vnet/ip/punt.h>
76 #include <vnet/feature/feature.h>
77
78 #undef BIHASH_TYPE
79 #undef __included_bihash_template_h__
80 #include <vnet/l2/l2_fib.h>
81
82 #include <vpp/stats/stats.h>
83 #include <vpp/oam/oam.h>
84
85 #include <vnet/ethernet/ethernet.h>
86 #include <vnet/ethernet/arp_packet.h>
87 #include <vnet/interface.h>
88 #include <vnet/l2/l2_fib.h>
89 #include <vnet/l2/l2_bd.h>
90 #include <vpp/api/vpe_msg_enum.h>
91 #include <vnet/span/span.h>
92 #include <vnet/fib/ip6_fib.h>
93 #include <vnet/fib/ip4_fib.h>
94 #include <vnet/fib/fib_api.h>
95 #include <vnet/dpo/drop_dpo.h>
96 #include <vnet/dpo/receive_dpo.h>
97 #include <vnet/dpo/lookup_dpo.h>
98 #include <vnet/dpo/classify_dpo.h>
99 #include <vnet/dpo/ip_null_dpo.h>
100 #define vl_typedefs             /* define message structures */
101 #include <vpp/api/vpe_all_api_h.h>
102 #undef vl_typedefs
103 #define vl_endianfun            /* define message structures */
104 #include <vpp/api/vpe_all_api_h.h>
105 #undef vl_endianfun
106 /* instantiate all the print functions we know about */
107 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
108 #define vl_printfun
109 #include <vpp/api/vpe_all_api_h.h>
110 #undef vl_printfun
111 #include <vlibapi/api_helper_macros.h>
112 #define foreach_vpe_api_msg                                             \
113 _(WANT_OAM_EVENTS, want_oam_events)                                     \
114 _(OAM_ADD_DEL, oam_add_del)                                             \
115 _(IS_ADDRESS_REACHABLE, is_address_reachable)                           \
116 _(SW_INTERFACE_SET_MPLS_ENABLE, sw_interface_set_mpls_enable)           \
117 _(SW_INTERFACE_SET_VPATH, sw_interface_set_vpath)                       \
118 _(SW_INTERFACE_SET_VXLAN_BYPASS, sw_interface_set_vxlan_bypass)         \
119 _(SW_INTERFACE_SET_L2_XCONNECT, sw_interface_set_l2_xconnect)           \
120 _(SW_INTERFACE_SET_L2_BRIDGE, sw_interface_set_l2_bridge)               \
121 _(CREATE_VLAN_SUBIF, create_vlan_subif)                                 \
122 _(CREATE_SUBIF, create_subif)                                           \
123 _(PROXY_ARP_ADD_DEL, proxy_arp_add_del)                                 \
124 _(PROXY_ARP_INTFC_ENABLE_DISABLE, proxy_arp_intfc_enable_disable)       \
125 _(VNET_GET_SUMMARY_STATS, vnet_get_summary_stats)                       \
126 _(RESET_FIB, reset_fib)                                                 \
127 _(DHCP_PROXY_CONFIG,dhcp_proxy_config)                                  \
128 _(DHCP_PROXY_CONFIG_2,dhcp_proxy_config_2)                              \
129 _(DHCP_PROXY_SET_VSS,dhcp_proxy_set_vss)                                \
130 _(DHCP_CLIENT_CONFIG, dhcp_client_config)                               \
131 _(CREATE_LOOPBACK, create_loopback)                                     \
132 _(CONTROL_PING, control_ping)                                           \
133 _(CLI_REQUEST, cli_request)                                             \
134 _(CLI_INBAND, cli_inband)                                               \
135 _(SET_ARP_NEIGHBOR_LIMIT, set_arp_neighbor_limit)                       \
136 _(L2_PATCH_ADD_DEL, l2_patch_add_del)                                   \
137 _(CLASSIFY_SET_INTERFACE_IP_TABLE, classify_set_interface_ip_table)     \
138 _(CLASSIFY_SET_INTERFACE_L2_TABLES, classify_set_interface_l2_tables)   \
139 _(GET_NODE_INDEX, get_node_index)                                       \
140 _(ADD_NODE_NEXT, add_node_next)                                         \
141 _(VXLAN_ADD_DEL_TUNNEL, vxlan_add_del_tunnel)                           \
142 _(VXLAN_TUNNEL_DUMP, vxlan_tunnel_dump)                                 \
143 _(L2_INTERFACE_EFP_FILTER, l2_interface_efp_filter)                     \
144 _(L2_INTERFACE_VLAN_TAG_REWRITE, l2_interface_vlan_tag_rewrite)         \
145 _(SHOW_VERSION, show_version)                                           \
146 _(VXLAN_GPE_ADD_DEL_TUNNEL, vxlan_gpe_add_del_tunnel)                   \
147 _(VXLAN_GPE_TUNNEL_DUMP, vxlan_gpe_tunnel_dump)                         \
148 _(INTERFACE_NAME_RENUMBER, interface_name_renumber)                     \
149 _(WANT_IP4_ARP_EVENTS, want_ip4_arp_events)                             \
150 _(WANT_IP6_ND_EVENTS, want_ip6_nd_events)                               \
151 _(INPUT_ACL_SET_INTERFACE, input_acl_set_interface)                     \
152 _(DELETE_LOOPBACK, delete_loopback)                                     \
153 _(BD_IP_MAC_ADD_DEL, bd_ip_mac_add_del)                                 \
154 _(COP_INTERFACE_ENABLE_DISABLE, cop_interface_enable_disable)           \
155 _(COP_WHITELIST_ENABLE_DISABLE, cop_whitelist_enable_disable)           \
156 _(GET_NODE_GRAPH, get_node_graph)                                       \
157 _(IOAM_ENABLE, ioam_enable)                                             \
158 _(IOAM_DISABLE, ioam_disable)                                           \
159 _(POLICER_ADD_DEL, policer_add_del)                                     \
160 _(POLICER_DUMP, policer_dump)                                           \
161 _(GET_NEXT_INDEX, get_next_index)                                       \
162 _(PG_CREATE_INTERFACE, pg_create_interface)                             \
163 _(PG_CAPTURE, pg_capture)                                               \
164 _(PG_ENABLE_DISABLE, pg_enable_disable)                                 \
165 _(IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL,                               \
166   ip_source_and_port_range_check_add_del)                               \
167 _(IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL,                     \
168   ip_source_and_port_range_check_interface_add_del)                     \
169 _(DELETE_SUBIF, delete_subif)                                           \
170 _(L2_INTERFACE_PBB_TAG_REWRITE, l2_interface_pbb_tag_rewrite)           \
171 _(PUNT, punt)                                                           \
172 _(FEATURE_ENABLE_DISABLE, feature_enable_disable)
173
174 #define QUOTE_(x) #x
175 #define QUOTE(x) QUOTE_(x)
176 typedef enum
177 {
178   RESOLVE_IP4_ADD_DEL_ROUTE = 1,
179   RESOLVE_IP6_ADD_DEL_ROUTE,
180 } resolve_t;
181
182 static vlib_node_registration_t vpe_resolver_process_node;
183 vpe_api_main_t vpe_api_main;
184
185 static int arp_change_delete_callback (u32 pool_index, u8 * notused);
186 static int nd_change_delete_callback (u32 pool_index, u8 * notused);
187
188 /* Clean up all registrations belonging to the indicated client */
189 int
190 vl_api_memclnt_delete_callback (u32 client_index)
191 {
192   vpe_api_main_t *vam = &vpe_api_main;
193   vpe_client_registration_t *rp;
194   uword *p;
195   int stats_memclnt_delete_callback (u32 client_index);
196
197   stats_memclnt_delete_callback (client_index);
198
199 #define _(a)                                                    \
200     p = hash_get (vam->a##_registration_hash, client_index);    \
201     if (p) {                                                    \
202         rp = pool_elt_at_index (vam->a##_registrations, p[0]);  \
203         pool_put (vam->a##_registrations, rp);                  \
204         hash_unset (vam->a##_registration_hash, client_index);  \
205     }
206   foreach_registration_hash;
207 #undef _
208   return 0;
209 }
210
211 pub_sub_handler (oam_events, OAM_EVENTS);
212
213 #define RESOLUTION_EVENT 1
214 #define RESOLUTION_PENDING_EVENT 2
215 #define IP4_ARP_EVENT 3
216 #define IP6_ND_EVENT 4
217
218 int ip4_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp);
219
220 int ip6_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp);
221
222 void
223 handle_ip4_arp_event (u32 pool_index)
224 {
225   vpe_api_main_t *vam = &vpe_api_main;
226   vnet_main_t *vnm = vam->vnet_main;
227   vlib_main_t *vm = vam->vlib_main;
228   vl_api_ip4_arp_event_t *event;
229   vl_api_ip4_arp_event_t *mp;
230   unix_shared_memory_queue_t *q;
231
232   /* Client can cancel, die, etc. */
233   if (pool_is_free_index (vam->arp_events, pool_index))
234     return;
235
236   event = pool_elt_at_index (vam->arp_events, pool_index);
237
238   q = vl_api_client_index_to_input_queue (event->client_index);
239   if (!q)
240     {
241       (void) vnet_add_del_ip4_arp_change_event
242         (vnm, arp_change_delete_callback,
243          event->pid, &event->address,
244          vpe_resolver_process_node.index, IP4_ARP_EVENT,
245          ~0 /* pool index, notused */ , 0 /* is_add */ );
246       return;
247     }
248
249   if (q->cursize < q->maxsize)
250     {
251       mp = vl_msg_api_alloc (sizeof (*mp));
252       clib_memcpy (mp, event, sizeof (*mp));
253       vl_msg_api_send_shmem (q, (u8 *) & mp);
254     }
255   else
256     {
257       static f64 last_time;
258       /*
259        * Throttle syslog msgs.
260        * It's pretty tempting to just revoke the registration...
261        */
262       if (vlib_time_now (vm) > last_time + 10.0)
263         {
264           clib_warning ("arp event for %U to pid %d: queue stuffed!",
265                         format_ip4_address, &event->address, event->pid);
266           last_time = vlib_time_now (vm);
267         }
268     }
269 }
270
271 void
272 handle_ip6_nd_event (u32 pool_index)
273 {
274   vpe_api_main_t *vam = &vpe_api_main;
275   vnet_main_t *vnm = vam->vnet_main;
276   vlib_main_t *vm = vam->vlib_main;
277   vl_api_ip6_nd_event_t *event;
278   vl_api_ip6_nd_event_t *mp;
279   unix_shared_memory_queue_t *q;
280
281   /* Client can cancel, die, etc. */
282   if (pool_is_free_index (vam->nd_events, pool_index))
283     return;
284
285   event = pool_elt_at_index (vam->nd_events, pool_index);
286
287   q = vl_api_client_index_to_input_queue (event->client_index);
288   if (!q)
289     {
290       (void) vnet_add_del_ip6_nd_change_event
291         (vnm, nd_change_delete_callback,
292          event->pid, &event->address,
293          vpe_resolver_process_node.index, IP6_ND_EVENT,
294          ~0 /* pool index, notused */ , 0 /* is_add */ );
295       return;
296     }
297
298   if (q->cursize < q->maxsize)
299     {
300       mp = vl_msg_api_alloc (sizeof (*mp));
301       clib_memcpy (mp, event, sizeof (*mp));
302       vl_msg_api_send_shmem (q, (u8 *) & mp);
303     }
304   else
305     {
306       static f64 last_time;
307       /*
308        * Throttle syslog msgs.
309        * It's pretty tempting to just revoke the registration...
310        */
311       if (vlib_time_now (vm) > last_time + 10.0)
312         {
313           clib_warning ("ip6 nd event for %U to pid %d: queue stuffed!",
314                         format_ip6_address, &event->address, event->pid);
315           last_time = vlib_time_now (vm);
316         }
317     }
318 }
319
320 static uword
321 resolver_process (vlib_main_t * vm,
322                   vlib_node_runtime_t * rt, vlib_frame_t * f)
323 {
324   uword event_type;
325   uword *event_data = 0;
326   f64 timeout = 100.0;
327   int i;
328
329   while (1)
330     {
331       vlib_process_wait_for_event_or_clock (vm, timeout);
332
333       event_type = vlib_process_get_events (vm, &event_data);
334
335       switch (event_type)
336         {
337         case RESOLUTION_PENDING_EVENT:
338           timeout = 1.0;
339           break;
340
341         case RESOLUTION_EVENT:
342           clib_warning ("resolver: BOGUS TYPE");
343           break;
344
345         case IP4_ARP_EVENT:
346           for (i = 0; i < vec_len (event_data); i++)
347             handle_ip4_arp_event (event_data[i]);
348           break;
349
350         case IP6_ND_EVENT:
351           for (i = 0; i < vec_len (event_data); i++)
352             handle_ip6_nd_event (event_data[i]);
353           break;
354
355         case ~0:                /* timeout */
356           break;
357         }
358
359       vec_reset_length (event_data);
360     }
361   return 0;                     /* or not */
362 }
363
364 /* *INDENT-OFF* */
365 VLIB_REGISTER_NODE (vpe_resolver_process_node,static) = {
366   .function = resolver_process,
367   .type = VLIB_NODE_TYPE_PROCESS,
368   .name = "vpe-route-resolver-process",
369 };
370 /* *INDENT-ON* */
371
372 static void
373 vl_api_sw_interface_set_vpath_t_handler (vl_api_sw_interface_set_vpath_t * mp)
374 {
375   vl_api_sw_interface_set_vpath_reply_t *rmp;
376   int rv = 0;
377   u32 sw_if_index = ntohl (mp->sw_if_index);
378
379   VALIDATE_SW_IF_INDEX (mp);
380
381   l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_VPATH, mp->enable);
382   vnet_feature_enable_disable ("ip4-unicast", "vpath-input-ip4",
383                                sw_if_index, mp->enable, 0, 0);
384   vnet_feature_enable_disable ("ip4-multicast", "vpath-input-ip4",
385                                sw_if_index, mp->enable, 0, 0);
386   vnet_feature_enable_disable ("ip6-unicast", "vpath-input-ip6",
387                                sw_if_index, mp->enable, 0, 0);
388   vnet_feature_enable_disable ("ip6-multicast", "vpath-input-ip6",
389                                sw_if_index, mp->enable, 0, 0);
390
391   BAD_SW_IF_INDEX_LABEL;
392
393   REPLY_MACRO (VL_API_SW_INTERFACE_SET_VPATH_REPLY);
394 }
395
396 static void
397   vl_api_sw_interface_set_vxlan_bypass_t_handler
398   (vl_api_sw_interface_set_vxlan_bypass_t * mp)
399 {
400   vl_api_sw_interface_set_vxlan_bypass_reply_t *rmp;
401   int rv = 0;
402   u32 sw_if_index = ntohl (mp->sw_if_index);
403
404   VALIDATE_SW_IF_INDEX (mp);
405
406   if (mp->is_ipv6)
407     {
408       /* not yet implemented */
409     }
410   else
411     vnet_feature_enable_disable ("ip4-unicast", "ip4-vxlan-bypass",
412                                  sw_if_index, mp->enable, 0, 0);
413
414   BAD_SW_IF_INDEX_LABEL;
415
416   REPLY_MACRO (VL_API_SW_INTERFACE_SET_VXLAN_BYPASS_REPLY);
417 }
418
419 static void
420   vl_api_sw_interface_set_l2_xconnect_t_handler
421   (vl_api_sw_interface_set_l2_xconnect_t * mp)
422 {
423   vl_api_sw_interface_set_l2_xconnect_reply_t *rmp;
424   int rv = 0;
425   u32 rx_sw_if_index = ntohl (mp->rx_sw_if_index);
426   u32 tx_sw_if_index = ntohl (mp->tx_sw_if_index);
427   vlib_main_t *vm = vlib_get_main ();
428   vnet_main_t *vnm = vnet_get_main ();
429
430   VALIDATE_RX_SW_IF_INDEX (mp);
431
432   if (mp->enable)
433     {
434       VALIDATE_TX_SW_IF_INDEX (mp);
435       rv = set_int_l2_mode (vm, vnm, MODE_L2_XC,
436                             rx_sw_if_index, 0, 0, 0, tx_sw_if_index);
437     }
438   else
439     {
440       rv = set_int_l2_mode (vm, vnm, MODE_L3, rx_sw_if_index, 0, 0, 0, 0);
441     }
442
443   BAD_RX_SW_IF_INDEX_LABEL;
444   BAD_TX_SW_IF_INDEX_LABEL;
445
446   REPLY_MACRO (VL_API_SW_INTERFACE_SET_L2_XCONNECT_REPLY);
447 }
448
449 static void
450   vl_api_sw_interface_set_l2_bridge_t_handler
451   (vl_api_sw_interface_set_l2_bridge_t * mp)
452 {
453   bd_main_t *bdm = &bd_main;
454   vl_api_sw_interface_set_l2_bridge_reply_t *rmp;
455   int rv = 0;
456   u32 rx_sw_if_index = ntohl (mp->rx_sw_if_index);
457   u32 bd_id = ntohl (mp->bd_id);
458   u32 bd_index;
459   u32 bvi = mp->bvi;
460   u8 shg = mp->shg;
461   vlib_main_t *vm = vlib_get_main ();
462   vnet_main_t *vnm = vnet_get_main ();
463
464   VALIDATE_RX_SW_IF_INDEX (mp);
465
466   bd_index = bd_find_or_add_bd_index (bdm, bd_id);
467
468   if (mp->enable)
469     {
470       //VALIDATE_TX_SW_IF_INDEX(mp);
471       rv = set_int_l2_mode (vm, vnm, MODE_L2_BRIDGE,
472                             rx_sw_if_index, bd_index, bvi, shg, 0);
473     }
474   else
475     {
476       rv = set_int_l2_mode (vm, vnm, MODE_L3, rx_sw_if_index, 0, 0, 0, 0);
477     }
478
479   BAD_RX_SW_IF_INDEX_LABEL;
480
481   REPLY_MACRO (VL_API_SW_INTERFACE_SET_L2_BRIDGE_REPLY);
482 }
483
484 static void
485 vl_api_bd_ip_mac_add_del_t_handler (vl_api_bd_ip_mac_add_del_t * mp)
486 {
487   bd_main_t *bdm = &bd_main;
488   vl_api_bd_ip_mac_add_del_reply_t *rmp;
489   int rv = 0;
490   u32 bd_id = ntohl (mp->bd_id);
491   u32 bd_index;
492   uword *p;
493
494   p = hash_get (bdm->bd_index_by_bd_id, bd_id);
495   if (p == 0)
496     {
497       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
498       goto out;
499     }
500
501   bd_index = p[0];
502   if (bd_add_del_ip_mac (bd_index, mp->ip_address,
503                          mp->mac_address, mp->is_ipv6, mp->is_add))
504     rv = VNET_API_ERROR_UNSPECIFIED;
505
506 out:
507   REPLY_MACRO (VL_API_BD_IP_MAC_ADD_DEL_REPLY);
508 }
509
510 static void
511 vl_api_create_vlan_subif_t_handler (vl_api_create_vlan_subif_t * mp)
512 {
513   vl_api_create_vlan_subif_reply_t *rmp;
514   vnet_main_t *vnm = vnet_get_main ();
515   u32 hw_if_index, sw_if_index = (u32) ~ 0;
516   vnet_hw_interface_t *hi;
517   int rv = 0;
518   u32 id;
519   vnet_sw_interface_t template;
520   uword *p;
521   vnet_interface_main_t *im = &vnm->interface_main;
522   u64 sup_and_sub_key;
523   u64 *kp;
524   unix_shared_memory_queue_t *q;
525   clib_error_t *error;
526
527   VALIDATE_SW_IF_INDEX (mp);
528
529   hw_if_index = ntohl (mp->sw_if_index);
530   hi = vnet_get_hw_interface (vnm, hw_if_index);
531
532   id = ntohl (mp->vlan_id);
533   if (id == 0 || id > 4095)
534     {
535       rv = VNET_API_ERROR_INVALID_VLAN;
536       goto out;
537     }
538
539   sup_and_sub_key = ((u64) (hi->sw_if_index) << 32) | (u64) id;
540
541   p = hash_get_mem (im->sw_if_index_by_sup_and_sub, &sup_and_sub_key);
542   if (p)
543     {
544       rv = VNET_API_ERROR_VLAN_ALREADY_EXISTS;
545       goto out;
546     }
547
548   kp = clib_mem_alloc (sizeof (*kp));
549   *kp = sup_and_sub_key;
550
551   memset (&template, 0, sizeof (template));
552   template.type = VNET_SW_INTERFACE_TYPE_SUB;
553   template.sup_sw_if_index = hi->sw_if_index;
554   template.sub.id = id;
555   template.sub.eth.raw_flags = 0;
556   template.sub.eth.flags.one_tag = 1;
557   template.sub.eth.outer_vlan_id = id;
558   template.sub.eth.flags.exact_match = 1;
559
560   error = vnet_create_sw_interface (vnm, &template, &sw_if_index);
561   if (error)
562     {
563       clib_error_report (error);
564       rv = VNET_API_ERROR_INVALID_REGISTRATION;
565       goto out;
566     }
567   hash_set (hi->sub_interface_sw_if_index_by_id, id, sw_if_index);
568   hash_set_mem (im->sw_if_index_by_sup_and_sub, kp, sw_if_index);
569
570   BAD_SW_IF_INDEX_LABEL;
571
572 out:
573   q = vl_api_client_index_to_input_queue (mp->client_index);
574   if (!q)
575     return;
576
577   rmp = vl_msg_api_alloc (sizeof (*rmp));
578   rmp->_vl_msg_id = ntohs (VL_API_CREATE_VLAN_SUBIF_REPLY);
579   rmp->context = mp->context;
580   rmp->retval = ntohl (rv);
581   rmp->sw_if_index = ntohl (sw_if_index);
582   vl_msg_api_send_shmem (q, (u8 *) & rmp);
583 }
584
585 static void
586 vl_api_create_subif_t_handler (vl_api_create_subif_t * mp)
587 {
588   vl_api_create_subif_reply_t *rmp;
589   vnet_main_t *vnm = vnet_get_main ();
590   u32 sw_if_index = ~0;
591   int rv = 0;
592   u32 sub_id;
593   vnet_sw_interface_t *si;
594   vnet_hw_interface_t *hi;
595   vnet_sw_interface_t template;
596   uword *p;
597   vnet_interface_main_t *im = &vnm->interface_main;
598   u64 sup_and_sub_key;
599   u64 *kp;
600   clib_error_t *error;
601
602   VALIDATE_SW_IF_INDEX (mp);
603
604   si = vnet_get_sup_sw_interface (vnm, ntohl (mp->sw_if_index));
605   hi = vnet_get_sup_hw_interface (vnm, ntohl (mp->sw_if_index));
606
607   if (hi->bond_info == VNET_HW_INTERFACE_BOND_INFO_SLAVE)
608     {
609       rv = VNET_API_ERROR_BOND_SLAVE_NOT_ALLOWED;
610       goto out;
611     }
612
613   sw_if_index = si->sw_if_index;
614   sub_id = ntohl (mp->sub_id);
615
616   sup_and_sub_key = ((u64) (sw_if_index) << 32) | (u64) sub_id;
617
618   p = hash_get_mem (im->sw_if_index_by_sup_and_sub, &sup_and_sub_key);
619   if (p)
620     {
621       if (CLIB_DEBUG > 0)
622         clib_warning ("sup sw_if_index %d, sub id %d already exists\n",
623                       sw_if_index, sub_id);
624       rv = VNET_API_ERROR_SUBIF_ALREADY_EXISTS;
625       goto out;
626     }
627
628   kp = clib_mem_alloc (sizeof (*kp));
629   *kp = sup_and_sub_key;
630
631   memset (&template, 0, sizeof (template));
632   template.type = VNET_SW_INTERFACE_TYPE_SUB;
633   template.sup_sw_if_index = sw_if_index;
634   template.sub.id = sub_id;
635   template.sub.eth.flags.no_tags = mp->no_tags;
636   template.sub.eth.flags.one_tag = mp->one_tag;
637   template.sub.eth.flags.two_tags = mp->two_tags;
638   template.sub.eth.flags.dot1ad = mp->dot1ad;
639   template.sub.eth.flags.exact_match = mp->exact_match;
640   template.sub.eth.flags.default_sub = mp->default_sub;
641   template.sub.eth.flags.outer_vlan_id_any = mp->outer_vlan_id_any;
642   template.sub.eth.flags.inner_vlan_id_any = mp->inner_vlan_id_any;
643   template.sub.eth.outer_vlan_id = ntohs (mp->outer_vlan_id);
644   template.sub.eth.inner_vlan_id = ntohs (mp->inner_vlan_id);
645
646   error = vnet_create_sw_interface (vnm, &template, &sw_if_index);
647   if (error)
648     {
649       clib_error_report (error);
650       rv = VNET_API_ERROR_SUBIF_CREATE_FAILED;
651       goto out;
652     }
653
654   hash_set (hi->sub_interface_sw_if_index_by_id, sub_id, sw_if_index);
655   hash_set_mem (im->sw_if_index_by_sup_and_sub, kp, sw_if_index);
656
657   BAD_SW_IF_INDEX_LABEL;
658
659 out:
660
661   /* *INDENT-OFF* */
662   REPLY_MACRO2(VL_API_CREATE_SUBIF_REPLY,
663   ({
664     rmp->sw_if_index = ntohl(sw_if_index);
665   }));
666   /* *INDENT-ON* */
667 }
668
669 static void
670 vl_api_proxy_arp_add_del_t_handler (vl_api_proxy_arp_add_del_t * mp)
671 {
672   vl_api_proxy_arp_add_del_reply_t *rmp;
673   u32 fib_index;
674   int rv;
675   ip4_main_t *im = &ip4_main;
676   stats_main_t *sm = &stats_main;
677   int vnet_proxy_arp_add_del (ip4_address_t * lo_addr,
678                               ip4_address_t * hi_addr,
679                               u32 fib_index, int is_del);
680   uword *p;
681
682   dslock (sm, 1 /* release hint */ , 6 /* tag */ );
683
684   p = hash_get (im->fib_index_by_table_id, ntohl (mp->vrf_id));
685
686   if (!p)
687     {
688       rv = VNET_API_ERROR_NO_SUCH_FIB;
689       goto out;
690     }
691
692   fib_index = p[0];
693
694   rv = vnet_proxy_arp_add_del ((ip4_address_t *) mp->low_address,
695                                (ip4_address_t *) mp->hi_address,
696                                fib_index, mp->is_add == 0);
697
698 out:
699   dsunlock (sm);
700   REPLY_MACRO (VL_API_PROXY_ARP_ADD_DEL_REPLY);
701 }
702
703 static void
704   vl_api_proxy_arp_intfc_enable_disable_t_handler
705   (vl_api_proxy_arp_intfc_enable_disable_t * mp)
706 {
707   int rv = 0;
708   vnet_main_t *vnm = vnet_get_main ();
709   vl_api_proxy_arp_intfc_enable_disable_reply_t *rmp;
710   vnet_sw_interface_t *si;
711   u32 sw_if_index;
712
713   VALIDATE_SW_IF_INDEX (mp);
714
715   sw_if_index = ntohl (mp->sw_if_index);
716
717   if (pool_is_free_index (vnm->interface_main.sw_interfaces, sw_if_index))
718     {
719       rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
720       goto out;
721     }
722
723   si = vnet_get_sw_interface (vnm, sw_if_index);
724
725   ASSERT (si);
726
727   if (mp->enable_disable)
728     si->flags |= VNET_SW_INTERFACE_FLAG_PROXY_ARP;
729   else
730     si->flags &= ~VNET_SW_INTERFACE_FLAG_PROXY_ARP;
731
732   BAD_SW_IF_INDEX_LABEL;
733
734 out:
735   REPLY_MACRO (VL_API_PROXY_ARP_INTFC_ENABLE_DISABLE_REPLY);
736 }
737
738 static void
739 vl_api_is_address_reachable_t_handler (vl_api_is_address_reachable_t * mp)
740 {
741 #if 0
742   vpe_main_t *rm = &vpe_main;
743   ip4_main_t *im4 = &ip4_main;
744   ip6_main_t *im6 = &ip6_main;
745   ip_lookup_main_t *lm;
746   union
747   {
748     ip4_address_t ip4;
749     ip6_address_t ip6;
750   } addr;
751   u32 adj_index, sw_if_index;
752   vl_api_is_address_reachable_t *rmp;
753   ip_adjacency_t *adj;
754   unix_shared_memory_queue_t *q;
755
756   q = vl_api_client_index_to_input_queue (mp->client_index);
757   if (!q)
758     {
759       increment_missing_api_client_counter (rm->vlib_main);
760       return;
761     }
762
763   rmp = vl_msg_api_alloc (sizeof (*rmp));
764   clib_memcpy (rmp, mp, sizeof (*rmp));
765
766   sw_if_index = mp->next_hop_sw_if_index;
767   clib_memcpy (&addr, mp->address, sizeof (addr));
768   if (mp->is_ipv6)
769     {
770       lm = &im6->lookup_main;
771       adj_index = ip6_fib_lookup (im6, sw_if_index, &addr.ip6);
772     }
773   else
774     {
775       lm = &im4->lookup_main;
776       // FIXME NOT an ADJ
777       adj_index = ip4_fib_lookup (im4, sw_if_index, &addr.ip4);
778     }
779   if (adj_index == ~0)
780     {
781       rmp->is_error = 1;
782       goto send;
783     }
784   adj = ip_get_adjacency (lm, adj_index);
785
786   if (adj->lookup_next_index == IP_LOOKUP_NEXT_REWRITE
787       && adj->rewrite_header.sw_if_index == sw_if_index)
788     {
789       rmp->is_known = 1;
790     }
791   else
792     {
793       if (adj->lookup_next_index == IP_LOOKUP_NEXT_ARP
794           && adj->rewrite_header.sw_if_index == sw_if_index)
795         {
796           if (mp->is_ipv6)
797             ip6_probe_neighbor (rm->vlib_main, &addr.ip6, sw_if_index);
798           else
799             ip4_probe_neighbor (rm->vlib_main, &addr.ip4, sw_if_index);
800         }
801       else if (adj->lookup_next_index == IP_LOOKUP_NEXT_DROP)
802         {
803           rmp->is_known = 1;
804           goto send;
805         }
806       rmp->is_known = 0;
807     }
808
809 send:
810   vl_msg_api_send_shmem (q, (u8 *) & rmp);
811 #endif
812 }
813
814 static void
815   vl_api_sw_interface_set_mpls_enable_t_handler
816   (vl_api_sw_interface_set_mpls_enable_t * mp)
817 {
818   vl_api_sw_interface_set_mpls_enable_reply_t *rmp;
819   int rv = 0;
820
821   VALIDATE_SW_IF_INDEX (mp);
822
823   mpls_sw_interface_enable_disable (&mpls_main,
824                                     ntohl (mp->sw_if_index), mp->enable);
825
826   BAD_SW_IF_INDEX_LABEL;
827   REPLY_MACRO (VL_API_SW_INTERFACE_SET_MPLS_ENABLE_REPLY);
828 }
829
830 void
831 send_oam_event (oam_target_t * t)
832 {
833   vpe_api_main_t *vam = &vpe_api_main;
834   unix_shared_memory_queue_t *q;
835   vpe_client_registration_t *reg;
836   vl_api_oam_event_t *mp;
837
838   /* *INDENT-OFF* */
839   pool_foreach(reg, vam->oam_events_registrations,
840   ({
841     q = vl_api_client_index_to_input_queue (reg->client_index);
842     if (q)
843       {
844         mp = vl_msg_api_alloc (sizeof (*mp));
845         mp->_vl_msg_id = ntohs (VL_API_OAM_EVENT);
846         clib_memcpy (mp->dst_address, &t->dst_address,
847                      sizeof (mp->dst_address));
848         mp->state = t->state;
849         vl_msg_api_send_shmem (q, (u8 *)&mp);
850       }
851   }));
852   /* *INDENT-ON* */
853 }
854
855 static void
856 vl_api_oam_add_del_t_handler (vl_api_oam_add_del_t * mp)
857 {
858   vl_api_oam_add_del_reply_t *rmp;
859   int rv;
860
861   rv = vpe_oam_add_del_target ((ip4_address_t *) mp->src_address,
862                                (ip4_address_t *) mp->dst_address,
863                                ntohl (mp->vrf_id), (int) (mp->is_add));
864
865   REPLY_MACRO (VL_API_OAM_ADD_DEL_REPLY);
866 }
867
868 static void
869 vl_api_vnet_get_summary_stats_t_handler (vl_api_vnet_get_summary_stats_t * mp)
870 {
871   stats_main_t *sm = &stats_main;
872   vnet_interface_main_t *im = sm->interface_main;
873   vl_api_vnet_summary_stats_reply_t *rmp;
874   vlib_combined_counter_main_t *cm;
875   vlib_counter_t v;
876   int i, which;
877   u64 total_pkts[VLIB_N_RX_TX];
878   u64 total_bytes[VLIB_N_RX_TX];
879
880   unix_shared_memory_queue_t *q =
881     vl_api_client_index_to_input_queue (mp->client_index);
882
883   if (!q)
884     return;
885
886   rmp = vl_msg_api_alloc (sizeof (*rmp));
887   rmp->_vl_msg_id = ntohs (VL_API_VNET_SUMMARY_STATS_REPLY);
888   rmp->context = mp->context;
889   rmp->retval = 0;
890
891   memset (total_pkts, 0, sizeof (total_pkts));
892   memset (total_bytes, 0, sizeof (total_bytes));
893
894   vnet_interface_counter_lock (im);
895
896   vec_foreach (cm, im->combined_sw_if_counters)
897   {
898     which = cm - im->combined_sw_if_counters;
899
900     for (i = 0; i < vec_len (cm->maxi); i++)
901       {
902         vlib_get_combined_counter (cm, i, &v);
903         total_pkts[which] += v.packets;
904         total_bytes[which] += v.bytes;
905       }
906   }
907   vnet_interface_counter_unlock (im);
908
909   rmp->total_pkts[VLIB_RX] = clib_host_to_net_u64 (total_pkts[VLIB_RX]);
910   rmp->total_bytes[VLIB_RX] = clib_host_to_net_u64 (total_bytes[VLIB_RX]);
911   rmp->total_pkts[VLIB_TX] = clib_host_to_net_u64 (total_pkts[VLIB_TX]);
912   rmp->total_bytes[VLIB_TX] = clib_host_to_net_u64 (total_bytes[VLIB_TX]);
913   rmp->vector_rate =
914     clib_host_to_net_u64 (vlib_last_vector_length_per_node (sm->vlib_main));
915
916   vl_msg_api_send_shmem (q, (u8 *) & rmp);
917 }
918
919 /* *INDENT-OFF* */
920 typedef CLIB_PACKED (struct {
921   ip4_address_t address;
922   u32 address_length: 6;
923   u32 index:26;
924 }) ip4_route_t;
925 /* *INDENT-ON* */
926
927 static int
928 ip4_reset_fib_t_handler (vl_api_reset_fib_t * mp)
929 {
930   vnet_main_t *vnm = vnet_get_main ();
931   vnet_interface_main_t *im = &vnm->interface_main;
932   ip4_main_t *im4 = &ip4_main;
933   static u32 *sw_if_indices_to_shut;
934   stats_main_t *sm = &stats_main;
935   fib_table_t *fib_table;
936   ip4_fib_t *fib;
937   u32 sw_if_index;
938   int i;
939   int rv = VNET_API_ERROR_NO_SUCH_FIB;
940   u32 target_fib_id = ntohl (mp->vrf_id);
941
942   dslock (sm, 1 /* release hint */ , 8 /* tag */ );
943
944   /* *INDENT-OFF* */
945   pool_foreach (fib_table, im4->fibs,
946   ({
947     fib = &fib_table->v4;
948     vnet_sw_interface_t * si;
949
950     if (fib->table_id != target_fib_id)
951       continue;
952
953     /* remove any mpls encap/decap labels */
954     mpls_fib_reset_labels (fib->table_id);
955
956     /* remove any proxy arps in this fib */
957     vnet_proxy_arp_fib_reset (fib->table_id);
958
959     /* Set the flow hash for this fib to the default */
960     vnet_set_ip4_flow_hash (fib->table_id, IP_FLOW_HASH_DEFAULT);
961
962     vec_reset_length (sw_if_indices_to_shut);
963
964     /* Shut down interfaces in this FIB / clean out intfc routes */
965     pool_foreach (si, im->sw_interfaces,
966     ({
967       u32 sw_if_index = si->sw_if_index;
968
969       if (sw_if_index < vec_len (im4->fib_index_by_sw_if_index)
970           && (im4->fib_index_by_sw_if_index[si->sw_if_index] ==
971               fib->index))
972         vec_add1 (sw_if_indices_to_shut, si->sw_if_index);
973     }));
974
975     for (i = 0; i < vec_len (sw_if_indices_to_shut); i++) {
976       sw_if_index = sw_if_indices_to_shut[i];
977       // vec_foreach (sw_if_index, sw_if_indices_to_shut) {
978
979       u32 flags = vnet_sw_interface_get_flags (vnm, sw_if_index);
980       flags &= ~(VNET_SW_INTERFACE_FLAG_ADMIN_UP);
981       vnet_sw_interface_set_flags (vnm, sw_if_index, flags);
982     }
983
984     fib_table_flush(fib->index, FIB_PROTOCOL_IP4, FIB_SOURCE_API);
985     fib_table_flush(fib->index, FIB_PROTOCOL_IP4, FIB_SOURCE_INTERFACE);
986
987     rv = 0;
988     break;
989     })); /* pool_foreach (fib) */
990     /* *INDENT-ON* */
991
992   dsunlock (sm);
993   return rv;
994 }
995
996 static int
997 ip6_reset_fib_t_handler (vl_api_reset_fib_t * mp)
998 {
999   vnet_main_t *vnm = vnet_get_main ();
1000   vnet_interface_main_t *im = &vnm->interface_main;
1001   ip6_main_t *im6 = &ip6_main;
1002   stats_main_t *sm = &stats_main;
1003   static u32 *sw_if_indices_to_shut;
1004   fib_table_t *fib_table;
1005   ip6_fib_t *fib;
1006   u32 sw_if_index;
1007   int i;
1008   int rv = VNET_API_ERROR_NO_SUCH_FIB;
1009   u32 target_fib_id = ntohl (mp->vrf_id);
1010
1011   dslock (sm, 1 /* release hint */ , 9 /* tag */ );
1012
1013   /* *INDENT-OFF* */
1014   pool_foreach (fib_table, im6->fibs,
1015   ({
1016     vnet_sw_interface_t * si;
1017     fib = &(fib_table->v6);
1018
1019     if (fib->table_id != target_fib_id)
1020       continue;
1021
1022     vec_reset_length (sw_if_indices_to_shut);
1023
1024     /* Shut down interfaces in this FIB / clean out intfc routes */
1025     pool_foreach (si, im->sw_interfaces,
1026                   ({
1027                     if (im6->fib_index_by_sw_if_index[si->sw_if_index] ==
1028                         fib->index)
1029                       vec_add1 (sw_if_indices_to_shut, si->sw_if_index);
1030                   }));
1031
1032     for (i = 0; i < vec_len (sw_if_indices_to_shut); i++) {
1033       sw_if_index = sw_if_indices_to_shut[i];
1034       // vec_foreach (sw_if_index, sw_if_indices_to_shut) {
1035
1036       u32 flags = vnet_sw_interface_get_flags (vnm, sw_if_index);
1037       flags &= ~(VNET_SW_INTERFACE_FLAG_ADMIN_UP);
1038       vnet_sw_interface_set_flags (vnm, sw_if_index, flags);
1039     }
1040
1041     fib_table_flush(fib->index, FIB_PROTOCOL_IP6, FIB_SOURCE_API);
1042     fib_table_flush(fib->index, FIB_PROTOCOL_IP6, FIB_SOURCE_INTERFACE);
1043
1044     rv = 0;
1045     break;
1046   })); /* pool_foreach (fib) */
1047   /* *INDENT-ON* */
1048
1049   dsunlock (sm);
1050   return rv;
1051 }
1052
1053 static void
1054 vl_api_reset_fib_t_handler (vl_api_reset_fib_t * mp)
1055 {
1056   int rv;
1057   vl_api_reset_fib_reply_t *rmp;
1058
1059   if (mp->is_ipv6)
1060     rv = ip6_reset_fib_t_handler (mp);
1061   else
1062     rv = ip4_reset_fib_t_handler (mp);
1063
1064   REPLY_MACRO (VL_API_RESET_FIB_REPLY);
1065 }
1066
1067
1068 static void
1069 dhcpv4_proxy_config (vl_api_dhcp_proxy_config_t * mp)
1070 {
1071   vl_api_dhcp_proxy_config_reply_t *rmp;
1072   int rv;
1073
1074   rv = dhcp_proxy_set_server ((ip4_address_t *) (&mp->dhcp_server),
1075                               (ip4_address_t *) (&mp->dhcp_src_address),
1076                               (u32) ntohl (mp->vrf_id),
1077                               (int) mp->insert_circuit_id,
1078                               (int) (mp->is_add == 0));
1079
1080   REPLY_MACRO (VL_API_DHCP_PROXY_CONFIG_REPLY);
1081 }
1082
1083
1084 static void
1085 dhcpv6_proxy_config (vl_api_dhcp_proxy_config_t * mp)
1086 {
1087   vl_api_dhcp_proxy_config_reply_t *rmp;
1088   int rv = -1;
1089
1090   rv = dhcpv6_proxy_set_server ((ip6_address_t *) (&mp->dhcp_server),
1091                                 (ip6_address_t *) (&mp->dhcp_src_address),
1092                                 (u32) ntohl (mp->vrf_id),
1093                                 (int) mp->insert_circuit_id,
1094                                 (int) (mp->is_add == 0));
1095
1096   REPLY_MACRO (VL_API_DHCP_PROXY_CONFIG_REPLY);
1097 }
1098
1099 static void
1100 dhcpv4_proxy_config_2 (vl_api_dhcp_proxy_config_2_t * mp)
1101 {
1102   vl_api_dhcp_proxy_config_reply_t *rmp;
1103   int rv;
1104
1105   rv = dhcp_proxy_set_server_2 ((ip4_address_t *) (&mp->dhcp_server),
1106                                 (ip4_address_t *) (&mp->dhcp_src_address),
1107                                 (u32) ntohl (mp->rx_vrf_id),
1108                                 (u32) ntohl (mp->server_vrf_id),
1109                                 (int) mp->insert_circuit_id,
1110                                 (int) (mp->is_add == 0));
1111
1112   REPLY_MACRO (VL_API_DHCP_PROXY_CONFIG_2_REPLY);
1113 }
1114
1115
1116 static void
1117 dhcpv6_proxy_config_2 (vl_api_dhcp_proxy_config_2_t * mp)
1118 {
1119   vl_api_dhcp_proxy_config_reply_t *rmp;
1120   int rv = -1;
1121
1122   rv = dhcpv6_proxy_set_server_2 ((ip6_address_t *) (&mp->dhcp_server),
1123                                   (ip6_address_t *) (&mp->dhcp_src_address),
1124                                   (u32) ntohl (mp->rx_vrf_id),
1125                                   (u32) ntohl (mp->server_vrf_id),
1126                                   (int) mp->insert_circuit_id,
1127                                   (int) (mp->is_add == 0));
1128
1129   REPLY_MACRO (VL_API_DHCP_PROXY_CONFIG_2_REPLY);
1130 }
1131
1132
1133 static void
1134 vl_api_dhcp_proxy_set_vss_t_handler (vl_api_dhcp_proxy_set_vss_t * mp)
1135 {
1136   vl_api_dhcp_proxy_set_vss_reply_t *rmp;
1137   int rv;
1138   if (!mp->is_ipv6)
1139     rv = dhcp_proxy_set_option82_vss (ntohl (mp->tbl_id),
1140                                       ntohl (mp->oui),
1141                                       ntohl (mp->fib_id),
1142                                       (int) mp->is_add == 0);
1143   else
1144     rv = dhcpv6_proxy_set_vss (ntohl (mp->tbl_id),
1145                                ntohl (mp->oui),
1146                                ntohl (mp->fib_id), (int) mp->is_add == 0);
1147
1148   REPLY_MACRO (VL_API_DHCP_PROXY_SET_VSS_REPLY);
1149 }
1150
1151
1152 static void vl_api_dhcp_proxy_config_t_handler
1153   (vl_api_dhcp_proxy_config_t * mp)
1154 {
1155   if (mp->is_ipv6 == 0)
1156     dhcpv4_proxy_config (mp);
1157   else
1158     dhcpv6_proxy_config (mp);
1159 }
1160
1161 static void vl_api_dhcp_proxy_config_2_t_handler
1162   (vl_api_dhcp_proxy_config_2_t * mp)
1163 {
1164   if (mp->is_ipv6 == 0)
1165     dhcpv4_proxy_config_2 (mp);
1166   else
1167     dhcpv6_proxy_config_2 (mp);
1168 }
1169
1170 void
1171 dhcp_compl_event_callback (u32 client_index, u32 pid, u8 * hostname,
1172                            u8 is_ipv6, u8 * host_address, u8 * router_address,
1173                            u8 * host_mac)
1174 {
1175   unix_shared_memory_queue_t *q;
1176   vl_api_dhcp_compl_event_t *mp;
1177
1178   q = vl_api_client_index_to_input_queue (client_index);
1179   if (!q)
1180     return;
1181
1182   mp = vl_msg_api_alloc (sizeof (*mp));
1183   mp->client_index = client_index;
1184   mp->pid = pid;
1185   mp->is_ipv6 = is_ipv6;
1186   clib_memcpy (&mp->hostname, hostname, vec_len (hostname));
1187   mp->hostname[vec_len (hostname) + 1] = '\n';
1188   clib_memcpy (&mp->host_address[0], host_address, 16);
1189   clib_memcpy (&mp->router_address[0], router_address, 16);
1190
1191   if (NULL != host_mac)
1192     clib_memcpy (&mp->host_mac[0], host_mac, 6);
1193
1194   mp->_vl_msg_id = ntohs (VL_API_DHCP_COMPL_EVENT);
1195
1196   vl_msg_api_send_shmem (q, (u8 *) & mp);
1197 }
1198
1199 static void vl_api_dhcp_client_config_t_handler
1200   (vl_api_dhcp_client_config_t * mp)
1201 {
1202   vlib_main_t *vm = vlib_get_main ();
1203   vl_api_dhcp_client_config_reply_t *rmp;
1204   int rv = 0;
1205
1206   VALIDATE_SW_IF_INDEX (mp);
1207
1208   rv = dhcp_client_config (vm, ntohl (mp->sw_if_index),
1209                            mp->hostname, mp->is_add, mp->client_index,
1210                            mp->want_dhcp_event ? dhcp_compl_event_callback :
1211                            NULL, mp->pid);
1212
1213   BAD_SW_IF_INDEX_LABEL;
1214
1215   REPLY_MACRO (VL_API_DHCP_CLIENT_CONFIG_REPLY);
1216 }
1217
1218 static void
1219 vl_api_create_loopback_t_handler (vl_api_create_loopback_t * mp)
1220 {
1221   vl_api_create_loopback_reply_t *rmp;
1222   u32 sw_if_index;
1223   int rv;
1224
1225   rv = vnet_create_loopback_interface (&sw_if_index, mp->mac_address);
1226
1227   /* *INDENT-OFF* */
1228   REPLY_MACRO2(VL_API_CREATE_LOOPBACK_REPLY,
1229   ({
1230     rmp->sw_if_index = ntohl (sw_if_index);
1231   }));
1232   /* *INDENT-ON* */
1233 }
1234
1235 static void
1236 vl_api_delete_loopback_t_handler (vl_api_delete_loopback_t * mp)
1237 {
1238   vl_api_delete_loopback_reply_t *rmp;
1239   u32 sw_if_index;
1240   int rv;
1241
1242   sw_if_index = ntohl (mp->sw_if_index);
1243   rv = vnet_delete_loopback_interface (sw_if_index);
1244
1245   REPLY_MACRO (VL_API_DELETE_LOOPBACK_REPLY);
1246 }
1247
1248 static void
1249 vl_api_control_ping_t_handler (vl_api_control_ping_t * mp)
1250 {
1251   vl_api_control_ping_reply_t *rmp;
1252   int rv = 0;
1253
1254   /* *INDENT-OFF* */
1255   REPLY_MACRO2(VL_API_CONTROL_PING_REPLY,
1256   ({
1257     rmp->vpe_pid = ntohl (getpid());
1258   }));
1259   /* *INDENT-ON* */
1260 }
1261
1262 static void
1263 shmem_cli_output (uword arg, u8 * buffer, uword buffer_bytes)
1264 {
1265   u8 **shmem_vecp = (u8 **) arg;
1266   u8 *shmem_vec;
1267   void *oldheap;
1268   api_main_t *am = &api_main;
1269   u32 offset;
1270
1271   shmem_vec = *shmem_vecp;
1272
1273   offset = vec_len (shmem_vec);
1274
1275   pthread_mutex_lock (&am->vlib_rp->mutex);
1276   oldheap = svm_push_data_heap (am->vlib_rp);
1277
1278   vec_validate (shmem_vec, offset + buffer_bytes - 1);
1279
1280   clib_memcpy (shmem_vec + offset, buffer, buffer_bytes);
1281
1282   svm_pop_heap (oldheap);
1283   pthread_mutex_unlock (&am->vlib_rp->mutex);
1284
1285   *shmem_vecp = shmem_vec;
1286 }
1287
1288
1289 static void
1290 vl_api_cli_request_t_handler (vl_api_cli_request_t * mp)
1291 {
1292   vl_api_cli_reply_t *rp;
1293   unix_shared_memory_queue_t *q;
1294   vlib_main_t *vm = vlib_get_main ();
1295   api_main_t *am = &api_main;
1296   unformat_input_t input;
1297   u8 *shmem_vec = 0;
1298   void *oldheap;
1299
1300   q = vl_api_client_index_to_input_queue (mp->client_index);
1301   if (!q)
1302     return;
1303
1304   rp = vl_msg_api_alloc (sizeof (*rp));
1305   rp->_vl_msg_id = ntohs (VL_API_CLI_REPLY);
1306   rp->context = mp->context;
1307
1308   unformat_init_vector (&input, (u8 *) (uword) mp->cmd_in_shmem);
1309
1310   vlib_cli_input (vm, &input, shmem_cli_output, (uword) & shmem_vec);
1311
1312   pthread_mutex_lock (&am->vlib_rp->mutex);
1313   oldheap = svm_push_data_heap (am->vlib_rp);
1314
1315   vec_add1 (shmem_vec, 0);
1316
1317   svm_pop_heap (oldheap);
1318   pthread_mutex_unlock (&am->vlib_rp->mutex);
1319
1320   rp->reply_in_shmem = (uword) shmem_vec;
1321
1322   vl_msg_api_send_shmem (q, (u8 *) & rp);
1323 }
1324
1325 static void
1326 inband_cli_output (uword arg, u8 * buffer, uword buffer_bytes)
1327 {
1328   u8 **mem_vecp = (u8 **) arg;
1329   u8 *mem_vec = *mem_vecp;
1330   u32 offset = vec_len (mem_vec);
1331
1332   vec_validate (mem_vec, offset + buffer_bytes - 1);
1333   clib_memcpy (mem_vec + offset, buffer, buffer_bytes);
1334   *mem_vecp = mem_vec;
1335 }
1336
1337 static void
1338 vl_api_cli_inband_t_handler (vl_api_cli_inband_t * mp)
1339 {
1340   vl_api_cli_inband_reply_t *rmp;
1341   int rv = 0;
1342   unix_shared_memory_queue_t *q;
1343   vlib_main_t *vm = vlib_get_main ();
1344   unformat_input_t input;
1345   u8 *out_vec = 0;
1346
1347   q = vl_api_client_index_to_input_queue (mp->client_index);
1348   if (!q)
1349     return;
1350
1351   unformat_init_string (&input, (char *) mp->cmd, ntohl (mp->length));
1352   vlib_cli_input (vm, &input, inband_cli_output, (uword) & out_vec);
1353
1354   u32 len = vec_len (out_vec);
1355   /* *INDENT-OFF* */
1356   REPLY_MACRO3(VL_API_CLI_INBAND_REPLY, len,
1357   ({
1358     rmp->length = htonl (len);
1359     clib_memcpy (rmp->reply, out_vec, len);
1360   }));
1361   /* *INDENT-ON* */
1362   vec_free (out_vec);
1363 }
1364
1365 static void
1366 vl_api_set_arp_neighbor_limit_t_handler (vl_api_set_arp_neighbor_limit_t * mp)
1367 {
1368   int rv;
1369   vl_api_set_arp_neighbor_limit_reply_t *rmp;
1370   vnet_main_t *vnm = vnet_get_main ();
1371   clib_error_t *error;
1372
1373   vnm->api_errno = 0;
1374
1375   if (mp->is_ipv6)
1376     error = ip6_set_neighbor_limit (ntohl (mp->arp_neighbor_limit));
1377   else
1378     error = ip4_set_arp_limit (ntohl (mp->arp_neighbor_limit));
1379
1380   if (error)
1381     {
1382       clib_error_report (error);
1383       rv = VNET_API_ERROR_UNSPECIFIED;
1384     }
1385   else
1386     {
1387       rv = vnm->api_errno;
1388     }
1389
1390   REPLY_MACRO (VL_API_SET_ARP_NEIGHBOR_LIMIT_REPLY);
1391 }
1392
1393 static void vl_api_classify_set_interface_ip_table_t_handler
1394   (vl_api_classify_set_interface_ip_table_t * mp)
1395 {
1396   vlib_main_t *vm = vlib_get_main ();
1397   vl_api_classify_set_interface_ip_table_reply_t *rmp;
1398   int rv;
1399   u32 table_index, sw_if_index;
1400
1401   table_index = ntohl (mp->table_index);
1402   sw_if_index = ntohl (mp->sw_if_index);
1403
1404   VALIDATE_SW_IF_INDEX (mp);
1405
1406   if (mp->is_ipv6)
1407     rv = vnet_set_ip6_classify_intfc (vm, sw_if_index, table_index);
1408   else
1409     rv = vnet_set_ip4_classify_intfc (vm, sw_if_index, table_index);
1410
1411   BAD_SW_IF_INDEX_LABEL;
1412
1413   REPLY_MACRO (VL_API_CLASSIFY_SET_INTERFACE_IP_TABLE_REPLY);
1414 }
1415
1416 static void vl_api_classify_set_interface_l2_tables_t_handler
1417   (vl_api_classify_set_interface_l2_tables_t * mp)
1418 {
1419   vl_api_classify_set_interface_l2_tables_reply_t *rmp;
1420   int rv;
1421   u32 sw_if_index, ip4_table_index, ip6_table_index, other_table_index;
1422   int enable;
1423
1424   ip4_table_index = ntohl (mp->ip4_table_index);
1425   ip6_table_index = ntohl (mp->ip6_table_index);
1426   other_table_index = ntohl (mp->other_table_index);
1427   sw_if_index = ntohl (mp->sw_if_index);
1428
1429   VALIDATE_SW_IF_INDEX (mp);
1430
1431   if (mp->is_input)
1432     rv = vnet_l2_input_classify_set_tables (sw_if_index, ip4_table_index,
1433                                             ip6_table_index,
1434                                             other_table_index);
1435   else
1436     rv = vnet_l2_output_classify_set_tables (sw_if_index, ip4_table_index,
1437                                              ip6_table_index,
1438                                              other_table_index);
1439
1440   if (rv == 0)
1441     {
1442       if (ip4_table_index != ~0 || ip6_table_index != ~0
1443           || other_table_index != ~0)
1444         enable = 1;
1445       else
1446         enable = 0;
1447
1448       if (mp->is_input)
1449         vnet_l2_input_classify_enable_disable (sw_if_index, enable);
1450       else
1451         vnet_l2_output_classify_enable_disable (sw_if_index, enable);
1452     }
1453
1454   BAD_SW_IF_INDEX_LABEL;
1455
1456   REPLY_MACRO (VL_API_CLASSIFY_SET_INTERFACE_L2_TABLES_REPLY);
1457 }
1458
1459 extern void l2_efp_filter_configure (vnet_main_t * vnet_main,
1460                                      u32 sw_if_index, u32 enable);
1461
1462 static void
1463 vl_api_l2_interface_efp_filter_t_handler (vl_api_l2_interface_efp_filter_t *
1464                                           mp)
1465 {
1466   int rv;
1467   vl_api_l2_interface_efp_filter_reply_t *rmp;
1468   vnet_main_t *vnm = vnet_get_main ();
1469
1470   // enable/disable the feature
1471   l2_efp_filter_configure (vnm, mp->sw_if_index, mp->enable_disable);
1472   rv = vnm->api_errno;
1473
1474   REPLY_MACRO (VL_API_L2_INTERFACE_EFP_FILTER_REPLY);
1475 }
1476
1477 static void
1478   vl_api_l2_interface_vlan_tag_rewrite_t_handler
1479   (vl_api_l2_interface_vlan_tag_rewrite_t * mp)
1480 {
1481   int rv = 0;
1482   vl_api_l2_interface_vlan_tag_rewrite_reply_t *rmp;
1483   vnet_main_t *vnm = vnet_get_main ();
1484   vlib_main_t *vm = vlib_get_main ();
1485   u32 vtr_op;
1486
1487   VALIDATE_SW_IF_INDEX (mp);
1488
1489   vtr_op = ntohl (mp->vtr_op);
1490
1491   /* The L2 code is unsuspicious */
1492   switch (vtr_op)
1493     {
1494     case L2_VTR_DISABLED:
1495     case L2_VTR_PUSH_1:
1496     case L2_VTR_PUSH_2:
1497     case L2_VTR_POP_1:
1498     case L2_VTR_POP_2:
1499     case L2_VTR_TRANSLATE_1_1:
1500     case L2_VTR_TRANSLATE_1_2:
1501     case L2_VTR_TRANSLATE_2_1:
1502     case L2_VTR_TRANSLATE_2_2:
1503       break;
1504
1505     default:
1506       rv = VNET_API_ERROR_INVALID_VALUE;
1507       goto bad_sw_if_index;
1508     }
1509
1510   rv = l2vtr_configure (vm, vnm, ntohl (mp->sw_if_index), vtr_op,
1511                         ntohl (mp->push_dot1q), ntohl (mp->tag1),
1512                         ntohl (mp->tag2));
1513
1514   BAD_SW_IF_INDEX_LABEL;
1515
1516   REPLY_MACRO (VL_API_L2_INTERFACE_VLAN_TAG_REWRITE_REPLY);
1517 }
1518
1519 static void
1520 vl_api_show_version_t_handler (vl_api_show_version_t * mp)
1521 {
1522   vl_api_show_version_reply_t *rmp;
1523   int rv = 0;
1524   char *vpe_api_get_build_directory (void);
1525   char *vpe_api_get_version (void);
1526   char *vpe_api_get_build_date (void);
1527
1528   unix_shared_memory_queue_t *q =
1529     vl_api_client_index_to_input_queue (mp->client_index);
1530
1531   if (!q)
1532     return;
1533
1534   /* *INDENT-OFF* */
1535   REPLY_MACRO2(VL_API_SHOW_VERSION_REPLY,
1536   ({
1537     strncpy ((char *) rmp->program, "vpe", ARRAY_LEN(rmp->program)-1);
1538     strncpy ((char *) rmp->build_directory, vpe_api_get_build_directory(),
1539              ARRAY_LEN(rmp->build_directory)-1);
1540     strncpy ((char *) rmp->version, vpe_api_get_version(),
1541              ARRAY_LEN(rmp->version)-1);
1542     strncpy ((char *) rmp->build_date, vpe_api_get_build_date(),
1543              ARRAY_LEN(rmp->build_date)-1);
1544   }));
1545   /* *INDENT-ON* */
1546 }
1547
1548 static void
1549 vl_api_get_node_index_t_handler (vl_api_get_node_index_t * mp)
1550 {
1551   vlib_main_t *vm = vlib_get_main ();
1552   vl_api_get_node_index_reply_t *rmp;
1553   vlib_node_t *n;
1554   int rv = 0;
1555   u32 node_index = ~0;
1556
1557   n = vlib_get_node_by_name (vm, mp->node_name);
1558
1559   if (n == 0)
1560     rv = VNET_API_ERROR_NO_SUCH_NODE;
1561   else
1562     node_index = n->index;
1563
1564   /* *INDENT-OFF* */
1565   REPLY_MACRO2(VL_API_GET_NODE_INDEX_REPLY,
1566   ({
1567     rmp->node_index = ntohl(node_index);
1568   }));
1569   /* *INDENT-ON* */
1570 }
1571
1572 static void
1573 vl_api_get_next_index_t_handler (vl_api_get_next_index_t * mp)
1574 {
1575   vlib_main_t *vm = vlib_get_main ();
1576   vl_api_get_next_index_reply_t *rmp;
1577   vlib_node_t *node, *next_node;
1578   int rv = 0;
1579   u32 next_node_index = ~0, next_index = ~0;
1580   uword *p;
1581
1582   node = vlib_get_node_by_name (vm, mp->node_name);
1583
1584   if (node == 0)
1585     {
1586       rv = VNET_API_ERROR_NO_SUCH_NODE;
1587       goto out;
1588     }
1589
1590   next_node = vlib_get_node_by_name (vm, mp->next_name);
1591
1592   if (next_node == 0)
1593     {
1594       rv = VNET_API_ERROR_NO_SUCH_NODE2;
1595       goto out;
1596     }
1597   else
1598     next_node_index = next_node->index;
1599
1600   p = hash_get (node->next_slot_by_node, next_node_index);
1601
1602   if (p == 0)
1603     {
1604       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1605       goto out;
1606     }
1607   else
1608     next_index = p[0];
1609
1610 out:
1611   /* *INDENT-OFF* */
1612   REPLY_MACRO2(VL_API_GET_NEXT_INDEX_REPLY,
1613   ({
1614     rmp->next_index = ntohl(next_index);
1615   }));
1616   /* *INDENT-ON* */
1617 }
1618
1619 static void
1620 vl_api_add_node_next_t_handler (vl_api_add_node_next_t * mp)
1621 {
1622   vlib_main_t *vm = vlib_get_main ();
1623   vl_api_add_node_next_reply_t *rmp;
1624   vlib_node_t *n, *next;
1625   int rv = 0;
1626   u32 next_index = ~0;
1627
1628   n = vlib_get_node_by_name (vm, mp->node_name);
1629
1630   if (n == 0)
1631     {
1632       rv = VNET_API_ERROR_NO_SUCH_NODE;
1633       goto out;
1634     }
1635
1636   next = vlib_get_node_by_name (vm, mp->next_name);
1637
1638   if (next == 0)
1639     rv = VNET_API_ERROR_NO_SUCH_NODE2;
1640   else
1641     next_index = vlib_node_add_next (vm, n->index, next->index);
1642
1643 out:
1644   /* *INDENT-OFF* */
1645   REPLY_MACRO2(VL_API_GET_NODE_INDEX_REPLY,
1646   ({
1647     rmp->next_index = ntohl(next_index);
1648   }));
1649   /* *INDENT-ON* */
1650 }
1651
1652 static void vl_api_vxlan_add_del_tunnel_t_handler
1653   (vl_api_vxlan_add_del_tunnel_t * mp)
1654 {
1655   vl_api_vxlan_add_del_tunnel_reply_t *rmp;
1656   int rv = 0;
1657   vnet_vxlan_add_del_tunnel_args_t _a, *a = &_a;
1658   u32 encap_fib_index;
1659   uword *p;
1660   ip4_main_t *im = &ip4_main;
1661   vnet_main_t *vnm = vnet_get_main ();
1662   u32 sw_if_index = ~0;
1663
1664   p = hash_get (im->fib_index_by_table_id, ntohl (mp->encap_vrf_id));
1665   if (!p)
1666     {
1667       rv = VNET_API_ERROR_NO_SUCH_FIB;
1668       goto out;
1669     }
1670   encap_fib_index = p[0];
1671   memset (a, 0, sizeof (*a));
1672
1673   a->is_add = mp->is_add;
1674   a->is_ip6 = mp->is_ipv6;
1675
1676   /* ip addresses sent in network byte order */
1677   ip46_from_addr_buf (mp->is_ipv6, mp->dst_address, &a->dst);
1678   ip46_from_addr_buf (mp->is_ipv6, mp->src_address, &a->src);
1679
1680   /* Check src & dst are different */
1681   if (ip46_address_cmp (&a->dst, &a->src) == 0)
1682     {
1683       rv = VNET_API_ERROR_SAME_SRC_DST;
1684       goto out;
1685     }
1686   a->mcast_sw_if_index = ntohl (mp->mcast_sw_if_index);
1687   if (ip46_address_is_multicast (&a->dst) &&
1688       pool_is_free_index (vnm->interface_main.sw_interfaces,
1689                           a->mcast_sw_if_index))
1690     {
1691       rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
1692       goto out;
1693     }
1694   a->encap_fib_index = encap_fib_index;
1695   a->decap_next_index = ntohl (mp->decap_next_index);
1696   a->vni = ntohl (mp->vni);
1697   rv = vnet_vxlan_add_del_tunnel (a, &sw_if_index);
1698
1699 out:
1700   /* *INDENT-OFF* */
1701   REPLY_MACRO2(VL_API_VXLAN_ADD_DEL_TUNNEL_REPLY,
1702   ({
1703     rmp->sw_if_index = ntohl (sw_if_index);
1704   }));
1705   /* *INDENT-ON* */
1706 }
1707
1708 static void send_vxlan_tunnel_details
1709   (vxlan_tunnel_t * t, unix_shared_memory_queue_t * q, u32 context)
1710 {
1711   vl_api_vxlan_tunnel_details_t *rmp;
1712   ip4_main_t *im4 = &ip4_main;
1713   ip6_main_t *im6 = &ip6_main;
1714   u8 is_ipv6 = !ip46_address_is_ip4 (&t->dst);
1715
1716   rmp = vl_msg_api_alloc (sizeof (*rmp));
1717   memset (rmp, 0, sizeof (*rmp));
1718   rmp->_vl_msg_id = ntohs (VL_API_VXLAN_TUNNEL_DETAILS);
1719   if (is_ipv6)
1720     {
1721       memcpy (rmp->src_address, t->src.ip6.as_u8, 16);
1722       memcpy (rmp->dst_address, t->dst.ip6.as_u8, 16);
1723       rmp->encap_vrf_id = htonl (im6->fibs[t->encap_fib_index].ft_table_id);
1724     }
1725   else
1726     {
1727       memcpy (rmp->src_address, t->src.ip4.as_u8, 4);
1728       memcpy (rmp->dst_address, t->dst.ip4.as_u8, 4);
1729       rmp->encap_vrf_id = htonl (im4->fibs[t->encap_fib_index].ft_table_id);
1730     }
1731   rmp->mcast_sw_if_index = htonl (t->mcast_sw_if_index);
1732   rmp->vni = htonl (t->vni);
1733   rmp->decap_next_index = htonl (t->decap_next_index);
1734   rmp->sw_if_index = htonl (t->sw_if_index);
1735   rmp->is_ipv6 = is_ipv6;
1736   rmp->context = context;
1737
1738   vl_msg_api_send_shmem (q, (u8 *) & rmp);
1739 }
1740
1741 static void vl_api_vxlan_tunnel_dump_t_handler
1742   (vl_api_vxlan_tunnel_dump_t * mp)
1743 {
1744   unix_shared_memory_queue_t *q;
1745   vxlan_main_t *vxm = &vxlan_main;
1746   vxlan_tunnel_t *t;
1747   u32 sw_if_index;
1748
1749   q = vl_api_client_index_to_input_queue (mp->client_index);
1750   if (q == 0)
1751     {
1752       return;
1753     }
1754
1755   sw_if_index = ntohl (mp->sw_if_index);
1756
1757   if (~0 == sw_if_index)
1758     {
1759       /* *INDENT-OFF* */
1760       pool_foreach (t, vxm->tunnels,
1761       ({
1762         send_vxlan_tunnel_details(t, q, mp->context);
1763       }));
1764       /* *INDENT-ON* */
1765     }
1766   else
1767     {
1768       if ((sw_if_index >= vec_len (vxm->tunnel_index_by_sw_if_index)) ||
1769           (~0 == vxm->tunnel_index_by_sw_if_index[sw_if_index]))
1770         {
1771           return;
1772         }
1773       t = &vxm->tunnels[vxm->tunnel_index_by_sw_if_index[sw_if_index]];
1774       send_vxlan_tunnel_details (t, q, mp->context);
1775     }
1776 }
1777
1778 static void
1779 vl_api_l2_patch_add_del_t_handler (vl_api_l2_patch_add_del_t * mp)
1780 {
1781   extern int vnet_l2_patch_add_del (u32 rx_sw_if_index, u32 tx_sw_if_index,
1782                                     int is_add);
1783   vl_api_l2_patch_add_del_reply_t *rmp;
1784   int vnet_l2_patch_add_del (u32 rx_sw_if_index, u32 tx_sw_if_index,
1785                              int is_add);
1786   int rv = 0;
1787
1788   VALIDATE_RX_SW_IF_INDEX (mp);
1789   VALIDATE_TX_SW_IF_INDEX (mp);
1790
1791   rv = vnet_l2_patch_add_del (ntohl (mp->rx_sw_if_index),
1792                               ntohl (mp->tx_sw_if_index),
1793                               (int) (mp->is_add != 0));
1794
1795   BAD_RX_SW_IF_INDEX_LABEL;
1796   BAD_TX_SW_IF_INDEX_LABEL;
1797
1798   REPLY_MACRO (VL_API_L2_PATCH_ADD_DEL_REPLY);
1799 }
1800
1801 static void
1802   vl_api_vxlan_gpe_add_del_tunnel_t_handler
1803   (vl_api_vxlan_gpe_add_del_tunnel_t * mp)
1804 {
1805   vl_api_vxlan_gpe_add_del_tunnel_reply_t *rmp;
1806   int rv = 0;
1807   vnet_vxlan_gpe_add_del_tunnel_args_t _a, *a = &_a;
1808   u32 encap_fib_index, decap_fib_index;
1809   u8 protocol;
1810   uword *p;
1811   ip4_main_t *im = &ip4_main;
1812   u32 sw_if_index = ~0;
1813
1814
1815   p = hash_get (im->fib_index_by_table_id, ntohl (mp->encap_vrf_id));
1816   if (!p)
1817     {
1818       rv = VNET_API_ERROR_NO_SUCH_FIB;
1819       goto out;
1820     }
1821   encap_fib_index = p[0];
1822
1823   protocol = mp->protocol;
1824
1825   /* Interpret decap_vrf_id as an opaque if sending to other-than-ip4-input */
1826   if (protocol == VXLAN_GPE_INPUT_NEXT_IP4_INPUT)
1827     {
1828       p = hash_get (im->fib_index_by_table_id, ntohl (mp->decap_vrf_id));
1829       if (!p)
1830         {
1831           rv = VNET_API_ERROR_NO_SUCH_INNER_FIB;
1832           goto out;
1833         }
1834       decap_fib_index = p[0];
1835     }
1836   else
1837     {
1838       decap_fib_index = ntohl (mp->decap_vrf_id);
1839     }
1840
1841   /* Check src & dst are different */
1842   if ((mp->is_ipv6 && memcmp (mp->local, mp->remote, 16) == 0) ||
1843       (!mp->is_ipv6 && memcmp (mp->local, mp->remote, 4) == 0))
1844     {
1845       rv = VNET_API_ERROR_SAME_SRC_DST;
1846       goto out;
1847     }
1848   memset (a, 0, sizeof (*a));
1849
1850   a->is_add = mp->is_add;
1851   a->is_ip6 = mp->is_ipv6;
1852   /* ip addresses sent in network byte order */
1853   if (a->is_ip6)
1854     {
1855       clib_memcpy (&(a->local.ip6), mp->local, 16);
1856       clib_memcpy (&(a->remote.ip6), mp->remote, 16);
1857     }
1858   else
1859     {
1860       clib_memcpy (&(a->local.ip4), mp->local, 4);
1861       clib_memcpy (&(a->remote.ip4), mp->remote, 4);
1862     }
1863   a->encap_fib_index = encap_fib_index;
1864   a->decap_fib_index = decap_fib_index;
1865   a->protocol = protocol;
1866   a->vni = ntohl (mp->vni);
1867   rv = vnet_vxlan_gpe_add_del_tunnel (a, &sw_if_index);
1868
1869 out:
1870   /* *INDENT-OFF* */
1871   REPLY_MACRO2(VL_API_VXLAN_GPE_ADD_DEL_TUNNEL_REPLY,
1872   ({
1873     rmp->sw_if_index = ntohl (sw_if_index);
1874   }));
1875   /* *INDENT-ON* */
1876 }
1877
1878 static void send_vxlan_gpe_tunnel_details
1879   (vxlan_gpe_tunnel_t * t, unix_shared_memory_queue_t * q, u32 context)
1880 {
1881   vl_api_vxlan_gpe_tunnel_details_t *rmp;
1882   ip4_main_t *im4 = &ip4_main;
1883   ip6_main_t *im6 = &ip6_main;
1884   u8 is_ipv6 = !(t->flags & VXLAN_GPE_TUNNEL_IS_IPV4);
1885
1886   rmp = vl_msg_api_alloc (sizeof (*rmp));
1887   memset (rmp, 0, sizeof (*rmp));
1888   rmp->_vl_msg_id = ntohs (VL_API_VXLAN_GPE_TUNNEL_DETAILS);
1889   if (is_ipv6)
1890     {
1891       memcpy (rmp->local, &(t->local.ip6), 16);
1892       memcpy (rmp->remote, &(t->remote.ip6), 16);
1893       rmp->encap_vrf_id = htonl (im6->fibs[t->encap_fib_index].ft_table_id);
1894       rmp->decap_vrf_id = htonl (im6->fibs[t->decap_fib_index].ft_table_id);
1895     }
1896   else
1897     {
1898       memcpy (rmp->local, &(t->local.ip4), 4);
1899       memcpy (rmp->remote, &(t->remote.ip4), 4);
1900       rmp->encap_vrf_id = htonl (im4->fibs[t->encap_fib_index].ft_table_id);
1901       rmp->decap_vrf_id = htonl (im4->fibs[t->decap_fib_index].ft_table_id);
1902     }
1903   rmp->vni = htonl (t->vni);
1904   rmp->protocol = t->protocol;
1905   rmp->sw_if_index = htonl (t->sw_if_index);
1906   rmp->is_ipv6 = is_ipv6;
1907   rmp->context = context;
1908
1909   vl_msg_api_send_shmem (q, (u8 *) & rmp);
1910 }
1911
1912 static void vl_api_vxlan_gpe_tunnel_dump_t_handler
1913   (vl_api_vxlan_gpe_tunnel_dump_t * mp)
1914 {
1915   unix_shared_memory_queue_t *q;
1916   vxlan_gpe_main_t *vgm = &vxlan_gpe_main;
1917   vxlan_gpe_tunnel_t *t;
1918   u32 sw_if_index;
1919
1920   q = vl_api_client_index_to_input_queue (mp->client_index);
1921   if (q == 0)
1922     {
1923       return;
1924     }
1925
1926   sw_if_index = ntohl (mp->sw_if_index);
1927
1928   if (~0 == sw_if_index)
1929     {
1930       /* *INDENT-OFF* */
1931       pool_foreach (t, vgm->tunnels,
1932       ({
1933         send_vxlan_gpe_tunnel_details(t, q, mp->context);
1934       }));
1935       /* *INDENT-ON* */
1936     }
1937   else
1938     {
1939       if ((sw_if_index >= vec_len (vgm->tunnel_index_by_sw_if_index)) ||
1940           (~0 == vgm->tunnel_index_by_sw_if_index[sw_if_index]))
1941         {
1942           return;
1943         }
1944       t = &vgm->tunnels[vgm->tunnel_index_by_sw_if_index[sw_if_index]];
1945       send_vxlan_gpe_tunnel_details (t, q, mp->context);
1946     }
1947 }
1948
1949 static void
1950 vl_api_interface_name_renumber_t_handler (vl_api_interface_name_renumber_t *
1951                                           mp)
1952 {
1953   vl_api_interface_name_renumber_reply_t *rmp;
1954   int rv = 0;
1955
1956   VALIDATE_SW_IF_INDEX (mp);
1957
1958   rv = vnet_interface_name_renumber
1959     (ntohl (mp->sw_if_index), ntohl (mp->new_show_dev_instance));
1960
1961   BAD_SW_IF_INDEX_LABEL;
1962
1963   REPLY_MACRO (VL_API_INTERFACE_NAME_RENUMBER_REPLY);
1964 }
1965
1966 static int
1967 arp_change_data_callback (u32 pool_index, u8 * new_mac,
1968                           u32 sw_if_index, u32 address)
1969 {
1970   vpe_api_main_t *am = &vpe_api_main;
1971   vlib_main_t *vm = am->vlib_main;
1972   vl_api_ip4_arp_event_t *event;
1973   static f64 arp_event_last_time;
1974   f64 now = vlib_time_now (vm);
1975
1976   if (pool_is_free_index (am->arp_events, pool_index))
1977     return 1;
1978
1979   event = pool_elt_at_index (am->arp_events, pool_index);
1980   /* *INDENT-OFF* */
1981   if (memcmp (&event->new_mac, new_mac, sizeof (event->new_mac)))
1982     {
1983       clib_memcpy (event->new_mac, new_mac, sizeof (event->new_mac));
1984     }
1985   else
1986     {                           /* same mac */
1987       if (sw_if_index == event->sw_if_index &&
1988           (!event->mac_ip ||
1989            /* for BD case, also check IP address with 10 sec timeout */
1990            (address == event->address &&
1991             (now - arp_event_last_time) < 10.0)))
1992         return 1;
1993     }
1994   /* *INDENT-ON* */
1995
1996   arp_event_last_time = now;
1997   event->sw_if_index = sw_if_index;
1998   if (event->mac_ip)
1999     event->address = address;
2000   return 0;
2001 }
2002
2003 static int
2004 nd_change_data_callback (u32 pool_index, u8 * new_mac,
2005                          u32 sw_if_index, ip6_address_t * address)
2006 {
2007   vpe_api_main_t *am = &vpe_api_main;
2008   vlib_main_t *vm = am->vlib_main;
2009   vl_api_ip6_nd_event_t *event;
2010   static f64 nd_event_last_time;
2011   f64 now = vlib_time_now (vm);
2012
2013   if (pool_is_free_index (am->nd_events, pool_index))
2014     return 1;
2015
2016   event = pool_elt_at_index (am->nd_events, pool_index);
2017
2018   /* *INDENT-OFF* */
2019   if (memcmp (&event->new_mac, new_mac, sizeof (event->new_mac)))
2020     {
2021       clib_memcpy (event->new_mac, new_mac, sizeof (event->new_mac));
2022     }
2023   else
2024     {                           /* same mac */
2025       if (sw_if_index == event->sw_if_index &&
2026           (!event->mac_ip ||
2027            /* for BD case, also check IP address with 10 sec timeout */
2028            (ip6_address_is_equal (address,
2029                                   (ip6_address_t *) event->address) &&
2030             (now - nd_event_last_time) < 10.0)))
2031         return 1;
2032     }
2033   /* *INDENT-ON* */
2034
2035   nd_event_last_time = now;
2036   event->sw_if_index = sw_if_index;
2037   if (event->mac_ip)
2038     clib_memcpy (event->address, address, sizeof (event->address));
2039   return 0;
2040 }
2041
2042 static int
2043 arp_change_delete_callback (u32 pool_index, u8 * notused)
2044 {
2045   vpe_api_main_t *am = &vpe_api_main;
2046
2047   if (pool_is_free_index (am->arp_events, pool_index))
2048     return 1;
2049
2050   pool_put_index (am->arp_events, pool_index);
2051   return 0;
2052 }
2053
2054 static int
2055 nd_change_delete_callback (u32 pool_index, u8 * notused)
2056 {
2057   vpe_api_main_t *am = &vpe_api_main;
2058
2059   if (pool_is_free_index (am->nd_events, pool_index))
2060     return 1;
2061
2062   pool_put_index (am->nd_events, pool_index);
2063   return 0;
2064 }
2065
2066 static void
2067 vl_api_want_ip4_arp_events_t_handler (vl_api_want_ip4_arp_events_t * mp)
2068 {
2069   vpe_api_main_t *am = &vpe_api_main;
2070   vnet_main_t *vnm = vnet_get_main ();
2071   vl_api_want_ip4_arp_events_reply_t *rmp;
2072   vl_api_ip4_arp_event_t *event;
2073   int rv;
2074
2075   if (mp->enable_disable)
2076     {
2077       pool_get (am->arp_events, event);
2078       memset (event, 0, sizeof (*event));
2079
2080       event->_vl_msg_id = ntohs (VL_API_IP4_ARP_EVENT);
2081       event->client_index = mp->client_index;
2082       event->context = mp->context;
2083       event->address = mp->address;
2084       event->pid = mp->pid;
2085       if (mp->address == 0)
2086         event->mac_ip = 1;
2087
2088       rv = vnet_add_del_ip4_arp_change_event
2089         (vnm, arp_change_data_callback,
2090          mp->pid, &mp->address /* addr, in net byte order */ ,
2091          vpe_resolver_process_node.index,
2092          IP4_ARP_EVENT, event - am->arp_events, 1 /* is_add */ );
2093     }
2094   else
2095     {
2096       rv = vnet_add_del_ip4_arp_change_event
2097         (vnm, arp_change_delete_callback,
2098          mp->pid, &mp->address /* addr, in net byte order */ ,
2099          vpe_resolver_process_node.index,
2100          IP4_ARP_EVENT, ~0 /* pool index */ , 0 /* is_add */ );
2101     }
2102   REPLY_MACRO (VL_API_WANT_IP4_ARP_EVENTS_REPLY);
2103 }
2104
2105 static void
2106 vl_api_want_ip6_nd_events_t_handler (vl_api_want_ip6_nd_events_t * mp)
2107 {
2108   vpe_api_main_t *am = &vpe_api_main;
2109   vnet_main_t *vnm = vnet_get_main ();
2110   vl_api_want_ip6_nd_events_reply_t *rmp;
2111   vl_api_ip6_nd_event_t *event;
2112   int rv;
2113
2114   if (mp->enable_disable)
2115     {
2116       pool_get (am->nd_events, event);
2117       memset (event, 0, sizeof (*event));
2118
2119       event->_vl_msg_id = ntohs (VL_API_IP6_ND_EVENT);
2120       event->client_index = mp->client_index;
2121       event->context = mp->context;
2122       clib_memcpy (event->address, mp->address, 16);
2123       event->pid = mp->pid;
2124       if (ip6_address_is_zero ((ip6_address_t *) mp->address))
2125         event->mac_ip = 1;
2126
2127       rv = vnet_add_del_ip6_nd_change_event
2128         (vnm, nd_change_data_callback,
2129          mp->pid, mp->address /* addr, in net byte order */ ,
2130          vpe_resolver_process_node.index,
2131          IP6_ND_EVENT, event - am->nd_events, 1 /* is_add */ );
2132     }
2133   else
2134     {
2135       rv = vnet_add_del_ip6_nd_change_event
2136         (vnm, nd_change_delete_callback,
2137          mp->pid, mp->address /* addr, in net byte order */ ,
2138          vpe_resolver_process_node.index,
2139          IP6_ND_EVENT, ~0 /* pool index */ , 0 /* is_add */ );
2140     }
2141   REPLY_MACRO (VL_API_WANT_IP6_ND_EVENTS_REPLY);
2142 }
2143
2144 static void vl_api_input_acl_set_interface_t_handler
2145   (vl_api_input_acl_set_interface_t * mp)
2146 {
2147   vlib_main_t *vm = vlib_get_main ();
2148   vl_api_input_acl_set_interface_reply_t *rmp;
2149   int rv;
2150   u32 sw_if_index, ip4_table_index, ip6_table_index, l2_table_index;
2151
2152   ip4_table_index = ntohl (mp->ip4_table_index);
2153   ip6_table_index = ntohl (mp->ip6_table_index);
2154   l2_table_index = ntohl (mp->l2_table_index);
2155   sw_if_index = ntohl (mp->sw_if_index);
2156
2157   VALIDATE_SW_IF_INDEX (mp);
2158
2159   rv = vnet_set_input_acl_intfc (vm, sw_if_index, ip4_table_index,
2160                                  ip6_table_index, l2_table_index, mp->is_add);
2161
2162   BAD_SW_IF_INDEX_LABEL;
2163
2164   REPLY_MACRO (VL_API_INPUT_ACL_SET_INTERFACE_REPLY);
2165 }
2166
2167 static void vl_api_cop_interface_enable_disable_t_handler
2168   (vl_api_cop_interface_enable_disable_t * mp)
2169 {
2170   vl_api_cop_interface_enable_disable_reply_t *rmp;
2171   int rv;
2172   u32 sw_if_index = ntohl (mp->sw_if_index);
2173   int enable_disable;
2174
2175   VALIDATE_SW_IF_INDEX (mp);
2176
2177   enable_disable = (int) mp->enable_disable;
2178
2179   rv = cop_interface_enable_disable (sw_if_index, enable_disable);
2180
2181   BAD_SW_IF_INDEX_LABEL;
2182
2183   REPLY_MACRO (VL_API_COP_INTERFACE_ENABLE_DISABLE_REPLY);
2184 }
2185
2186 static void vl_api_cop_whitelist_enable_disable_t_handler
2187   (vl_api_cop_whitelist_enable_disable_t * mp)
2188 {
2189   vl_api_cop_whitelist_enable_disable_reply_t *rmp;
2190   cop_whitelist_enable_disable_args_t _a, *a = &_a;
2191   u32 sw_if_index = ntohl (mp->sw_if_index);
2192   int rv;
2193
2194   VALIDATE_SW_IF_INDEX (mp);
2195
2196   a->sw_if_index = sw_if_index;
2197   a->ip4 = mp->ip4;
2198   a->ip6 = mp->ip6;
2199   a->default_cop = mp->default_cop;
2200   a->fib_id = ntohl (mp->fib_id);
2201
2202   rv = cop_whitelist_enable_disable (a);
2203
2204   BAD_SW_IF_INDEX_LABEL;
2205
2206   REPLY_MACRO (VL_API_COP_WHITELIST_ENABLE_DISABLE_REPLY);
2207 }
2208
2209 static void
2210 vl_api_get_node_graph_t_handler (vl_api_get_node_graph_t * mp)
2211 {
2212   int rv = 0;
2213   u8 *vector = 0;
2214   api_main_t *am = &api_main;
2215   vlib_main_t *vm = vlib_get_main ();
2216   void *oldheap;
2217   vl_api_get_node_graph_reply_t *rmp;
2218
2219   pthread_mutex_lock (&am->vlib_rp->mutex);
2220   oldheap = svm_push_data_heap (am->vlib_rp);
2221
2222   /*
2223    * Keep the number of memcpy ops to a minimum (e.g. 1).
2224    */
2225   vec_validate (vector, 16384);
2226   vec_reset_length (vector);
2227
2228   /* $$$$ FIXME */
2229   vector = vlib_node_serialize (&vm->node_main, vector,
2230                                 (u32) ~ 0 /* all threads */ ,
2231                                 1 /* include nexts */ ,
2232                                 1 /* include stats */ );
2233
2234   svm_pop_heap (oldheap);
2235   pthread_mutex_unlock (&am->vlib_rp->mutex);
2236
2237   /* *INDENT-OFF* */
2238   REPLY_MACRO2(VL_API_GET_NODE_GRAPH_REPLY,
2239   ({
2240     rmp->reply_in_shmem = (uword) vector;
2241   }));
2242   /* *INDENT-ON* */
2243 }
2244
2245 static void
2246 vl_api_ioam_enable_t_handler (vl_api_ioam_enable_t * mp)
2247 {
2248   int rv = 0;
2249   vl_api_ioam_enable_reply_t *rmp;
2250   clib_error_t *error;
2251
2252   /* Ignoring the profile id as currently a single profile
2253    * is supported */
2254   error = ip6_ioam_enable (mp->trace_enable, mp->pot_enable,
2255                            mp->seqno, mp->analyse);
2256   if (error)
2257     {
2258       clib_error_report (error);
2259       rv = clib_error_get_code (error);
2260     }
2261
2262   REPLY_MACRO (VL_API_IOAM_ENABLE_REPLY);
2263 }
2264
2265 static void
2266 vl_api_ioam_disable_t_handler (vl_api_ioam_disable_t * mp)
2267 {
2268   int rv = 0;
2269   vl_api_ioam_disable_reply_t *rmp;
2270   clib_error_t *error;
2271
2272   error = clear_ioam_rewrite_fn ();
2273   if (error)
2274     {
2275       clib_error_report (error);
2276       rv = clib_error_get_code (error);
2277     }
2278
2279   REPLY_MACRO (VL_API_IOAM_DISABLE_REPLY);
2280 }
2281
2282 static void
2283 vl_api_policer_add_del_t_handler (vl_api_policer_add_del_t * mp)
2284 {
2285   vlib_main_t *vm = vlib_get_main ();
2286   vl_api_policer_add_del_reply_t *rmp;
2287   int rv = 0;
2288   u8 *name = NULL;
2289   sse2_qos_pol_cfg_params_st cfg;
2290   clib_error_t *error;
2291   u32 policer_index;
2292
2293   name = format (0, "%s", mp->name);
2294
2295   memset (&cfg, 0, sizeof (cfg));
2296   cfg.rfc = mp->type;
2297   cfg.rnd_type = mp->round_type;
2298   cfg.rate_type = mp->rate_type;
2299   cfg.rb.kbps.cir_kbps = mp->cir;
2300   cfg.rb.kbps.eir_kbps = mp->eir;
2301   cfg.rb.kbps.cb_bytes = mp->cb;
2302   cfg.rb.kbps.eb_bytes = mp->eb;
2303   cfg.conform_action.action_type = mp->conform_action_type;
2304   cfg.conform_action.dscp = mp->conform_dscp;
2305   cfg.exceed_action.action_type = mp->exceed_action_type;
2306   cfg.exceed_action.dscp = mp->exceed_dscp;
2307   cfg.violate_action.action_type = mp->violate_action_type;
2308   cfg.violate_action.dscp = mp->violate_dscp;
2309   cfg.color_aware = mp->color_aware;
2310
2311   error = policer_add_del (vm, name, &cfg, &policer_index, mp->is_add);
2312
2313   if (error)
2314     rv = VNET_API_ERROR_UNSPECIFIED;
2315
2316   /* *INDENT-OFF* */
2317   REPLY_MACRO2(VL_API_POLICER_ADD_DEL_REPLY,
2318   ({
2319     if (rv == 0 &&  mp->is_add)
2320       rmp->policer_index = ntohl(policer_index);
2321     else
2322       rmp->policer_index = ~0;
2323   }));
2324   /* *INDENT-ON* */
2325 }
2326
2327 static void
2328 send_policer_details (u8 * name,
2329                       sse2_qos_pol_cfg_params_st * config,
2330                       policer_read_response_type_st * templ,
2331                       unix_shared_memory_queue_t * q, u32 context)
2332 {
2333   vl_api_policer_details_t *mp;
2334
2335   mp = vl_msg_api_alloc (sizeof (*mp));
2336   memset (mp, 0, sizeof (*mp));
2337   mp->_vl_msg_id = ntohs (VL_API_POLICER_DETAILS);
2338   mp->context = context;
2339   mp->cir = htonl (config->rb.kbps.cir_kbps);
2340   mp->eir = htonl (config->rb.kbps.eir_kbps);
2341   mp->cb = htonl (config->rb.kbps.cb_bytes);
2342   mp->eb = htonl (config->rb.kbps.eb_bytes);
2343   mp->rate_type = config->rate_type;
2344   mp->round_type = config->rnd_type;
2345   mp->type = config->rfc;
2346   mp->conform_action_type = config->conform_action.action_type;
2347   mp->conform_dscp = config->conform_action.dscp;
2348   mp->exceed_action_type = config->exceed_action.action_type;
2349   mp->exceed_dscp = config->exceed_action.dscp;
2350   mp->violate_action_type = config->violate_action.action_type;
2351   mp->violate_dscp = config->violate_action.dscp;
2352   mp->single_rate = templ->single_rate ? 1 : 0;
2353   mp->color_aware = templ->color_aware ? 1 : 0;
2354   mp->scale = htonl (templ->scale);
2355   mp->cir_tokens_per_period = htonl (templ->cir_tokens_per_period);
2356   mp->pir_tokens_per_period = htonl (templ->pir_tokens_per_period);
2357   mp->current_limit = htonl (templ->current_limit);
2358   mp->current_bucket = htonl (templ->current_bucket);
2359   mp->extended_limit = htonl (templ->extended_limit);
2360   mp->extended_bucket = htonl (templ->extended_bucket);
2361   mp->last_update_time = clib_host_to_net_u64 (templ->last_update_time);
2362
2363   strncpy ((char *) mp->name, (char *) name, ARRAY_LEN (mp->name) - 1);
2364
2365   vl_msg_api_send_shmem (q, (u8 *) & mp);
2366 }
2367
2368 static void
2369 vl_api_policer_dump_t_handler (vl_api_policer_dump_t * mp)
2370 {
2371   unix_shared_memory_queue_t *q;
2372   vnet_policer_main_t *pm = &vnet_policer_main;
2373   hash_pair_t *hp;
2374   uword *p;
2375   u32 pool_index;
2376   u8 *match_name = 0;
2377   u8 *name;
2378   sse2_qos_pol_cfg_params_st *config;
2379   policer_read_response_type_st *templ;
2380
2381   q = vl_api_client_index_to_input_queue (mp->client_index);
2382   if (q == 0)
2383     return;
2384
2385   if (mp->match_name_valid)
2386     {
2387       match_name = format (0, "%s%c", mp->match_name, 0);
2388     }
2389
2390   if (mp->match_name_valid)
2391     {
2392       p = hash_get_mem (pm->policer_config_by_name, match_name);
2393       if (p)
2394         {
2395           pool_index = p[0];
2396           config = pool_elt_at_index (pm->configs, pool_index);
2397           templ = pool_elt_at_index (pm->policer_templates, pool_index);
2398           send_policer_details (match_name, config, templ, q, mp->context);
2399         }
2400     }
2401   else
2402     {
2403       /* *INDENT-OFF* */
2404       hash_foreach_pair (hp, pm->policer_config_by_name,
2405       ({
2406         name = (u8 *) hp->key;
2407         pool_index = hp->value[0];
2408         config = pool_elt_at_index (pm->configs, pool_index);
2409         templ = pool_elt_at_index (pm->policer_templates, pool_index);
2410         send_policer_details(name, config, templ, q, mp->context);
2411       }));
2412       /* *INDENT-ON* */
2413     }
2414 }
2415
2416
2417 static void
2418 vl_api_pg_create_interface_t_handler (vl_api_pg_create_interface_t * mp)
2419 {
2420   vl_api_pg_create_interface_reply_t *rmp;
2421   int rv = 0;
2422
2423   pg_main_t *pg = &pg_main;
2424   u32 pg_if_id = pg_interface_add_or_get (pg, ntohl (mp->interface_id));
2425   pg_interface_t *pi = pool_elt_at_index (pg->interfaces, pg_if_id);
2426
2427   /* *INDENT-OFF* */
2428   REPLY_MACRO2(VL_API_PG_CREATE_INTERFACE_REPLY,
2429   ({
2430     rmp->sw_if_index = ntohl(pi->sw_if_index);
2431   }));
2432   /* *INDENT-ON* */
2433 }
2434
2435 static void
2436 vl_api_pg_capture_t_handler (vl_api_pg_capture_t * mp)
2437 {
2438   vl_api_pg_capture_reply_t *rmp;
2439   int rv = 0;
2440
2441   vnet_main_t *vnm = vnet_get_main ();
2442   vnet_interface_main_t *im = &vnm->interface_main;
2443   vnet_hw_interface_t *hi = 0;
2444
2445   u8 *intf_name = format (0, "pg%d", ntohl (mp->interface_id), 0);
2446   u32 hw_if_index = ~0;
2447   uword *p = hash_get_mem (im->hw_interface_by_name, intf_name);
2448   if (p)
2449     hw_if_index = *p;
2450   vec_free (intf_name);
2451
2452   if (hw_if_index != ~0)
2453     {
2454       pg_capture_args_t _a, *a = &_a;
2455
2456       u32 len = ntohl (mp->pcap_name_length);
2457       u8 *pcap_file_name = vec_new (u8, len);
2458       clib_memcpy (pcap_file_name, mp->pcap_file_name, len);
2459
2460       hi = vnet_get_sup_hw_interface (vnm, hw_if_index);
2461       a->hw_if_index = hw_if_index;
2462       a->dev_instance = hi->dev_instance;
2463       a->is_enabled = mp->is_enabled;
2464       a->pcap_file_name = pcap_file_name;
2465       a->count = ntohl (mp->count);
2466
2467       clib_error_t *e = pg_capture (a);
2468       if (e)
2469         {
2470           clib_error_report (e);
2471           rv = VNET_API_ERROR_CANNOT_CREATE_PCAP_FILE;
2472         }
2473
2474       vec_free (pcap_file_name);
2475     }
2476   REPLY_MACRO (VL_API_PG_CAPTURE_REPLY);
2477 }
2478
2479 static void
2480 vl_api_pg_enable_disable_t_handler (vl_api_pg_enable_disable_t * mp)
2481 {
2482   vl_api_pg_enable_disable_reply_t *rmp;
2483   int rv = 0;
2484
2485   pg_main_t *pg = &pg_main;
2486   u32 stream_index = ~0;
2487
2488   int is_enable = mp->is_enabled != 0;
2489   u32 len = ntohl (mp->stream_name_length) - 1;
2490
2491   if (len > 0)
2492     {
2493       u8 *stream_name = vec_new (u8, len);
2494       clib_memcpy (stream_name, mp->stream_name, len);
2495       uword *p = hash_get_mem (pg->stream_index_by_name, stream_name);
2496       if (p)
2497         stream_index = *p;
2498       vec_free (stream_name);
2499     }
2500
2501   pg_enable_disable (stream_index, is_enable);
2502
2503   REPLY_MACRO (VL_API_PG_ENABLE_DISABLE_REPLY);
2504 }
2505
2506 static void
2507   vl_api_ip_source_and_port_range_check_add_del_t_handler
2508   (vl_api_ip_source_and_port_range_check_add_del_t * mp)
2509 {
2510   vl_api_ip_source_and_port_range_check_add_del_reply_t *rmp;
2511   int rv = 0;
2512
2513   u8 is_ipv6 = mp->is_ipv6;
2514   u8 is_add = mp->is_add;
2515   u8 mask_length = mp->mask_length;
2516   ip4_address_t ip4_addr;
2517   ip6_address_t ip6_addr;
2518   u16 *low_ports = 0;
2519   u16 *high_ports = 0;
2520   u32 vrf_id;
2521   u16 tmp_low, tmp_high;
2522   u8 num_ranges;
2523   int i;
2524
2525   // Validate port range
2526   num_ranges = mp->number_of_ranges;
2527   if (num_ranges > 32)
2528     {                           // This is size of array in VPE.API
2529       rv = VNET_API_ERROR_EXCEEDED_NUMBER_OF_RANGES_CAPACITY;
2530       goto reply;
2531     }
2532
2533   vec_reset_length (low_ports);
2534   vec_reset_length (high_ports);
2535
2536   for (i = 0; i < num_ranges; i++)
2537     {
2538       tmp_low = mp->low_ports[i];
2539       tmp_high = mp->high_ports[i];
2540       // If tmp_low <= tmp_high then only need to check tmp_low = 0
2541       // If tmp_low <= tmp_high then only need to check tmp_high > 65535
2542       if (tmp_low > tmp_high || tmp_low == 0 || tmp_high > 65535)
2543         {
2544           rv = VNET_API_ERROR_INVALID_VALUE;
2545           goto reply;
2546         }
2547       vec_add1 (low_ports, tmp_low);
2548       vec_add1 (high_ports, tmp_high + 1);
2549     }
2550
2551   // Validate mask_length
2552   if ((is_ipv6 && mask_length > 128) || (!is_ipv6 && mask_length > 32))
2553     {
2554       rv = VNET_API_ERROR_ADDRESS_LENGTH_MISMATCH;
2555       goto reply;
2556     }
2557
2558   vrf_id = ntohl (mp->vrf_id);
2559
2560   if (vrf_id < 1)
2561     {
2562       rv = VNET_API_ERROR_INVALID_VALUE;
2563       goto reply;
2564     }
2565
2566
2567   if (is_ipv6)
2568     {
2569       clib_memcpy (ip6_addr.as_u8, mp->address, sizeof (ip6_addr.as_u8));
2570       rv = ip6_source_and_port_range_check_add_del (&ip6_addr,
2571                                                     mask_length,
2572                                                     vrf_id,
2573                                                     low_ports,
2574                                                     high_ports, is_add);
2575     }
2576   else
2577     {
2578       clib_memcpy (ip4_addr.data, mp->address, sizeof (ip4_addr));
2579       rv = ip4_source_and_port_range_check_add_del (&ip4_addr,
2580                                                     mask_length,
2581                                                     vrf_id,
2582                                                     low_ports,
2583                                                     high_ports, is_add);
2584     }
2585
2586 reply:
2587   vec_free (low_ports);
2588   vec_free (high_ports);
2589   REPLY_MACRO (VL_API_IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL_REPLY);
2590 }
2591
2592 static void
2593   vl_api_ip_source_and_port_range_check_interface_add_del_t_handler
2594   (vl_api_ip_source_and_port_range_check_interface_add_del_t * mp)
2595 {
2596   vlib_main_t *vm = vlib_get_main ();
2597   vl_api_ip_source_and_port_range_check_interface_add_del_reply_t *rmp;
2598   ip4_main_t *im = &ip4_main;
2599   int rv;
2600   u32 sw_if_index;
2601   u32 fib_index[IP_SOURCE_AND_PORT_RANGE_CHECK_N_PROTOCOLS];
2602   u32 vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_N_PROTOCOLS];
2603   uword *p = 0;
2604   int i;
2605
2606   vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_TCP_OUT] =
2607     ntohl (mp->tcp_out_vrf_id);
2608   vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_UDP_OUT] =
2609     ntohl (mp->udp_out_vrf_id);
2610   vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_TCP_IN] =
2611     ntohl (mp->tcp_in_vrf_id);
2612   vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_UDP_IN] =
2613     ntohl (mp->udp_in_vrf_id);
2614
2615
2616   for (i = 0; i < IP_SOURCE_AND_PORT_RANGE_CHECK_N_PROTOCOLS; i++)
2617     {
2618       if (vrf_id[i] != 0 && vrf_id[i] != ~0)
2619         {
2620           p = hash_get (im->fib_index_by_table_id, vrf_id[i]);
2621
2622           if (p == 0)
2623             {
2624               rv = VNET_API_ERROR_INVALID_VALUE;
2625               goto reply;
2626             }
2627
2628           fib_index[i] = p[0];
2629         }
2630       else
2631         fib_index[i] = ~0;
2632     }
2633   sw_if_index = ntohl (mp->sw_if_index);
2634
2635   VALIDATE_SW_IF_INDEX (mp);
2636
2637   rv =
2638     set_ip_source_and_port_range_check (vm, fib_index, sw_if_index,
2639                                         mp->is_add);
2640
2641   BAD_SW_IF_INDEX_LABEL;
2642 reply:
2643
2644   REPLY_MACRO (VL_API_IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL_REPLY);
2645 }
2646
2647 static void
2648 vl_api_delete_subif_t_handler (vl_api_delete_subif_t * mp)
2649 {
2650   vl_api_delete_subif_reply_t *rmp;
2651   int rv;
2652
2653   rv = vnet_delete_sub_interface (ntohl (mp->sw_if_index));
2654
2655   REPLY_MACRO (VL_API_DELETE_SUBIF_REPLY);
2656 }
2657
2658 static void
2659   vl_api_l2_interface_pbb_tag_rewrite_t_handler
2660   (vl_api_l2_interface_pbb_tag_rewrite_t * mp)
2661 {
2662   vl_api_l2_interface_pbb_tag_rewrite_reply_t *rmp;
2663   vnet_main_t *vnm = vnet_get_main ();
2664   vlib_main_t *vm = vlib_get_main ();
2665   u32 vtr_op;
2666   int rv = 0;
2667
2668   VALIDATE_SW_IF_INDEX (mp);
2669
2670   vtr_op = ntohl (mp->vtr_op);
2671
2672   switch (vtr_op)
2673     {
2674     case L2_VTR_DISABLED:
2675     case L2_VTR_PUSH_2:
2676     case L2_VTR_POP_2:
2677     case L2_VTR_TRANSLATE_2_1:
2678       break;
2679
2680     default:
2681       rv = VNET_API_ERROR_INVALID_VALUE;
2682       goto bad_sw_if_index;
2683     }
2684
2685   rv = l2pbb_configure (vm, vnm, ntohl (mp->sw_if_index), vtr_op,
2686                         mp->b_dmac, mp->b_smac, ntohs (mp->b_vlanid),
2687                         ntohl (mp->i_sid), ntohs (mp->outer_tag));
2688
2689   BAD_SW_IF_INDEX_LABEL;
2690
2691   REPLY_MACRO (VL_API_L2_INTERFACE_PBB_TAG_REWRITE_REPLY);
2692
2693 }
2694
2695 static void
2696 vl_api_punt_t_handler (vl_api_punt_t * mp)
2697 {
2698   vl_api_punt_reply_t *rmp;
2699   vlib_main_t *vm = vlib_get_main ();
2700   int rv = 0;
2701   clib_error_t *error;
2702
2703   error = vnet_punt_add_del (vm, mp->ipv, mp->l4_protocol,
2704                              ntohs (mp->l4_port), mp->is_add);
2705   if (error)
2706     {
2707       rv = -1;
2708       clib_error_report (error);
2709     }
2710
2711   REPLY_MACRO (VL_API_PUNT_REPLY);
2712 }
2713
2714 static void
2715 vl_api_feature_enable_disable_t_handler (vl_api_feature_enable_disable_t * mp)
2716 {
2717   vl_api_feature_enable_disable_reply_t *rmp;
2718   int rv = 0;
2719   u8 *arc_name, *feature_name;
2720
2721   VALIDATE_SW_IF_INDEX (mp);
2722
2723   arc_name = format (0, "%s%c", mp->arc_name, 0);
2724   feature_name = format (0, "%s%c", mp->feature_name, 0);
2725
2726   vnet_feature_registration_t *reg;
2727   reg =
2728     vnet_get_feature_reg ((const char *) arc_name,
2729                           (const char *) feature_name);
2730   if (reg == 0)
2731     rv = VNET_API_ERROR_INVALID_VALUE;
2732   else
2733     {
2734       u32 sw_if_index;
2735       clib_error_t *error = 0;
2736
2737       sw_if_index = ntohl (mp->sw_if_index);
2738       if (reg->enable_disable_cb)
2739         error = reg->enable_disable_cb (sw_if_index, mp->enable);
2740       if (!error)
2741         vnet_feature_enable_disable ((const char *) arc_name,
2742                                      (const char *) feature_name,
2743                                      sw_if_index, mp->enable, 0, 0);
2744       else
2745         {
2746           clib_error_report (error);
2747           rv = VNET_API_ERROR_CANNOT_ENABLE_DISABLE_FEATURE;
2748         }
2749     }
2750
2751   vec_free (feature_name);
2752   vec_free (arc_name);
2753
2754   BAD_SW_IF_INDEX_LABEL;
2755
2756   REPLY_MACRO (VL_API_FEATURE_ENABLE_DISABLE_REPLY);
2757 }
2758
2759 #define BOUNCE_HANDLER(nn)                                              \
2760 static void vl_api_##nn##_t_handler (                                   \
2761     vl_api_##nn##_t *mp)                                                \
2762 {                                                                       \
2763     vpe_client_registration_t *reg;                                     \
2764     vpe_api_main_t * vam = &vpe_api_main;                               \
2765     unix_shared_memory_queue_t * q;                                     \
2766                                                                         \
2767     /* One registration only... */                                      \
2768     pool_foreach(reg, vam->nn##_registrations,                          \
2769     ({                                                                  \
2770         q = vl_api_client_index_to_input_queue (reg->client_index);     \
2771         if (q) {                                                        \
2772             /*                                                          \
2773              * If the queue is stuffed, turf the msg and complain       \
2774              * It's unlikely that the intended recipient is             \
2775              * alive; avoid deadlock at all costs.                      \
2776              */                                                         \
2777             if (q->cursize == q->maxsize) {                             \
2778                 clib_warning ("ERROR: receiver queue full, drop msg");  \
2779                 vl_msg_api_free (mp);                                   \
2780                 return;                                                 \
2781             }                                                           \
2782             vl_msg_api_send_shmem (q, (u8 *)&mp);                       \
2783             return;                                                     \
2784         }                                                               \
2785     }));                                                                \
2786     vl_msg_api_free (mp);                                               \
2787 }
2788
2789 static void setup_message_id_table (api_main_t * am);
2790
2791 /*
2792  * vpe_api_hookup
2793  * Add vpe's API message handlers to the table.
2794  * vlib has alread mapped shared memory and
2795  * added the client registration handlers.
2796  * See .../open-repo/vlib/memclnt_vlib.c:memclnt_process()
2797  */
2798 static clib_error_t *
2799 vpe_api_hookup (vlib_main_t * vm)
2800 {
2801   api_main_t *am = &api_main;
2802
2803 #define _(N,n)                                                  \
2804     vl_msg_api_set_handlers(VL_API_##N, #n,                     \
2805                            vl_api_##n##_t_handler,              \
2806                            vl_noop_handler,                     \
2807                            vl_api_##n##_t_endian,               \
2808                            vl_api_##n##_t_print,                \
2809                            sizeof(vl_api_##n##_t), 1);
2810   foreach_vpe_api_msg;
2811 #undef _
2812
2813   /*
2814    * Trace space for classifier mask+match
2815    */
2816   am->api_trace_cfg[VL_API_CLASSIFY_ADD_DEL_TABLE].size += 5 * sizeof (u32x4);
2817   am->api_trace_cfg[VL_API_CLASSIFY_ADD_DEL_SESSION].size
2818     += 5 * sizeof (u32x4);
2819   am->api_trace_cfg[VL_API_VXLAN_ADD_DEL_TUNNEL].size += 16 * sizeof (u32);
2820
2821   /*
2822    * Thread-safe API messages
2823    */
2824   am->is_mp_safe[VL_API_IP_ADD_DEL_ROUTE] = 1;
2825   am->is_mp_safe[VL_API_GET_NODE_GRAPH] = 1;
2826
2827   /*
2828    * Set up the (msg_name, crc, message-id) table
2829    */
2830   setup_message_id_table (am);
2831
2832   return 0;
2833 }
2834
2835 VLIB_API_INIT_FUNCTION (vpe_api_hookup);
2836
2837 static clib_error_t *
2838 vpe_api_init (vlib_main_t * vm)
2839 {
2840   vpe_api_main_t *am = &vpe_api_main;
2841
2842   am->vlib_main = vm;
2843   am->vnet_main = vnet_get_main ();
2844   am->interface_events_registration_hash = hash_create (0, sizeof (uword));
2845   am->to_netconf_server_registration_hash = hash_create (0, sizeof (uword));
2846   am->from_netconf_server_registration_hash = hash_create (0, sizeof (uword));
2847   am->to_netconf_client_registration_hash = hash_create (0, sizeof (uword));
2848   am->from_netconf_client_registration_hash = hash_create (0, sizeof (uword));
2849   am->oam_events_registration_hash = hash_create (0, sizeof (uword));
2850   am->bfd_events_registration_hash = hash_create (0, sizeof (uword));
2851
2852   vl_api_init (vm);
2853   vl_set_memory_region_name ("/vpe-api");
2854   vl_enable_disable_memory_api (vm, 1 /* enable it */ );
2855
2856   return 0;
2857 }
2858
2859 VLIB_INIT_FUNCTION (vpe_api_init);
2860
2861
2862 static clib_error_t *
2863 api_segment_config (vlib_main_t * vm, unformat_input_t * input)
2864 {
2865   u8 *chroot_path;
2866   u64 baseva, size, pvt_heap_size;
2867   int uid, gid, rv;
2868   const int max_buf_size = 4096;
2869   char *s, *buf;
2870   struct passwd _pw, *pw;
2871   struct group _grp, *grp;
2872   clib_error_t *e;
2873   buf = vec_new (char, 128);
2874   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
2875     {
2876       if (unformat (input, "prefix %s", &chroot_path))
2877         {
2878           vec_add1 (chroot_path, 0);
2879           vl_set_memory_root_path ((char *) chroot_path);
2880         }
2881       else if (unformat (input, "uid %d", &uid))
2882         vl_set_memory_uid (uid);
2883       else if (unformat (input, "gid %d", &gid))
2884         vl_set_memory_gid (gid);
2885       else if (unformat (input, "baseva %llx", &baseva))
2886         vl_set_global_memory_baseva (baseva);
2887       else if (unformat (input, "global-size %lldM", &size))
2888         vl_set_global_memory_size (size * (1ULL << 20));
2889       else if (unformat (input, "global-size %lldG", &size))
2890         vl_set_global_memory_size (size * (1ULL << 30));
2891       else if (unformat (input, "global-size %lld", &size))
2892         vl_set_global_memory_size (size);
2893       else if (unformat (input, "global-pvt-heap-size %lldM", &pvt_heap_size))
2894         vl_set_global_pvt_heap_size (pvt_heap_size * (1ULL << 20));
2895       else if (unformat (input, "global-pvt-heap-size size %lld",
2896                          &pvt_heap_size))
2897         vl_set_global_pvt_heap_size (pvt_heap_size);
2898       else if (unformat (input, "api-pvt-heap-size %lldM", &pvt_heap_size))
2899         vl_set_api_pvt_heap_size (pvt_heap_size * (1ULL << 20));
2900       else if (unformat (input, "api-pvt-heap-size size %lld",
2901                          &pvt_heap_size))
2902         vl_set_api_pvt_heap_size (pvt_heap_size);
2903       else if (unformat (input, "api-size %lldM", &size))
2904         vl_set_api_memory_size (size * (1ULL << 20));
2905       else if (unformat (input, "api-size %lldG", &size))
2906         vl_set_api_memory_size (size * (1ULL << 30));
2907       else if (unformat (input, "api-size %lld", &size))
2908         vl_set_api_memory_size (size);
2909       else if (unformat (input, "uid %s", &s))
2910         {
2911           /* lookup the username */
2912           pw = NULL;
2913           while (((rv =
2914                    getpwnam_r (s, &_pw, buf, vec_len (buf), &pw)) == ERANGE)
2915                  && (vec_len (buf) <= max_buf_size))
2916             {
2917               vec_resize (buf, vec_len (buf) * 2);
2918             }
2919           if (rv < 0)
2920             {
2921               e = clib_error_return_code (0, rv,
2922                                           CLIB_ERROR_ERRNO_VALID |
2923                                           CLIB_ERROR_FATAL,
2924                                           "cannot fetch username %s", s);
2925               vec_free (s);
2926               vec_free (buf);
2927               return e;
2928             }
2929           if (pw == NULL)
2930             {
2931               e =
2932                 clib_error_return_fatal (0, "username %s does not exist", s);
2933               vec_free (s);
2934               vec_free (buf);
2935               return e;
2936             }
2937           vec_free (s);
2938           vl_set_memory_uid (pw->pw_uid);
2939         }
2940       else if (unformat (input, "gid %s", &s))
2941         {
2942           /* lookup the group name */
2943           grp = NULL;
2944           while (((rv =
2945                    getgrnam_r (s, &_grp, buf, vec_len (buf), &grp)) == ERANGE)
2946                  && (vec_len (buf) <= max_buf_size))
2947             {
2948               vec_resize (buf, vec_len (buf) * 2);
2949             }
2950           if (rv != 0)
2951             {
2952               e = clib_error_return_code (0, rv,
2953                                           CLIB_ERROR_ERRNO_VALID |
2954                                           CLIB_ERROR_FATAL,
2955                                           "cannot fetch group %s", s);
2956               vec_free (s);
2957               vec_free (buf);
2958               return e;
2959             }
2960           if (grp == NULL)
2961             {
2962               e = clib_error_return_fatal (0, "group %s does not exist", s);
2963               vec_free (s);
2964               vec_free (buf);
2965               return e;
2966             }
2967           vec_free (s);
2968           vec_free (buf);
2969           vl_set_memory_gid (grp->gr_gid);
2970         }
2971       else
2972         return clib_error_return (0, "unknown input `%U'",
2973                                   format_unformat_error, input);
2974     }
2975   return 0;
2976 }
2977
2978 VLIB_EARLY_CONFIG_FUNCTION (api_segment_config, "api-segment");
2979
2980 void *
2981 get_unformat_vnet_sw_interface (void)
2982 {
2983   return (void *) &unformat_vnet_sw_interface;
2984 }
2985
2986 static u8 *
2987 format_arp_event (u8 * s, va_list * args)
2988 {
2989   vl_api_ip4_arp_event_t *event = va_arg (*args, vl_api_ip4_arp_event_t *);
2990
2991   s = format (s, "pid %d: ", event->pid);
2992   if (event->mac_ip)
2993     s = format (s, "bd mac/ip4 binding events");
2994   else
2995     s = format (s, "resolution for %U", format_ip4_address, &event->address);
2996   return s;
2997 }
2998
2999 static u8 *
3000 format_nd_event (u8 * s, va_list * args)
3001 {
3002   vl_api_ip6_nd_event_t *event = va_arg (*args, vl_api_ip6_nd_event_t *);
3003
3004   s = format (s, "pid %d: ", event->pid);
3005   if (event->mac_ip)
3006     s = format (s, "bd mac/ip6 binding events");
3007   else
3008     s = format (s, "resolution for %U", format_ip6_address, event->address);
3009   return s;
3010 }
3011
3012 static clib_error_t *
3013 show_ip_arp_nd_events_fn (vlib_main_t * vm,
3014                           unformat_input_t * input, vlib_cli_command_t * cmd)
3015 {
3016   vpe_api_main_t *am = &vpe_api_main;
3017   vl_api_ip4_arp_event_t *arp_event;
3018   vl_api_ip6_nd_event_t *nd_event;
3019
3020   if ((pool_elts (am->arp_events) == 0) && (pool_elts (am->nd_events) == 0))
3021     {
3022       vlib_cli_output (vm, "No active arp or nd event registrations");
3023       return 0;
3024     }
3025
3026   /* *INDENT-OFF* */
3027   pool_foreach (arp_event, am->arp_events,
3028   ({
3029     vlib_cli_output (vm, "%U", format_arp_event, arp_event);
3030   }));
3031
3032   pool_foreach (nd_event, am->nd_events,
3033   ({
3034     vlib_cli_output (vm, "%U", format_nd_event, nd_event);
3035   }));
3036   /* *INDENT-ON* */
3037
3038   return 0;
3039 }
3040
3041 /* *INDENT-OFF* */
3042 VLIB_CLI_COMMAND (show_ip_arp_nd_events, static) = {
3043   .path = "show arp-nd-event registrations",
3044   .function = show_ip_arp_nd_events_fn,
3045   .short_help = "Show ip4 arp and ip6 nd event registrations",
3046 };
3047 /* *INDENT-ON* */
3048
3049 #define vl_msg_name_crc_list
3050 #include <vpp/api/vpe_all_api_h.h>
3051 #undef vl_msg_name_crc_list
3052
3053 static void
3054 setup_message_id_table (api_main_t * am)
3055 {
3056 #define _(id,n,crc) vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id);
3057   foreach_vl_msg_name_crc_memclnt;
3058   foreach_vl_msg_name_crc_vpe;
3059 #undef _
3060 }
3061
3062
3063 /*
3064  * fd.io coding-style-patch-verification: ON
3065  *
3066  * Local Variables:
3067  * eval: (c-set-style "gnu")
3068  * End:
3069  */