Reorganize source tree to use single autotools instance
[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/mpls/mpls.h>
56 #include <vnet/mpls/mpls_tunnel.h>
57 #include <vnet/dhcp/proxy.h>
58 #include <vnet/dhcp/client.h>
59 #if IPV6SR > 0
60 #include <vnet/sr/sr.h>
61 #endif
62 #include <vnet/dhcpv6/proxy.h>
63 #include <vlib/vlib.h>
64 #include <vlib/unix/unix.h>
65 #include <vlibapi/api.h>
66 #include <vlibmemory/api.h>
67 #include <vnet/classify/vnet_classify.h>
68 #include <vnet/classify/input_acl.h>
69 #include <vnet/classify/policer_classify.h>
70 #include <vnet/classify/flow_classify.h>
71 #include <vnet/l2/l2_classify.h>
72 #include <vnet/vxlan/vxlan.h>
73 #include <vnet/l2/l2_vtr.h>
74 #include <vnet/vxlan-gpe/vxlan_gpe.h>
75 #include <vnet/map/map.h>
76 #include <vnet/cop/cop.h>
77 #include <vnet/ip/ip6_hop_by_hop.h>
78 #include <vnet/ip/ip_source_and_port_range_check.h>
79 #include <vnet/policer/policer.h>
80 #include <vnet/flow/flow_report.h>
81 #include <vnet/flow/flow_report_classify.h>
82 #include <vnet/ip/punt.h>
83 #include <vnet/feature/feature.h>
84
85 #undef BIHASH_TYPE
86 #undef __included_bihash_template_h__
87 #include <vnet/l2/l2_fib.h>
88
89 #if DPDK > 0
90 #include <vnet/devices/dpdk/dpdk.h>
91 #endif
92
93 #include <vpp/stats/stats.h>
94 #include <vpp/oam/oam.h>
95
96 #include <vnet/ethernet/ethernet.h>
97 #include <vnet/ethernet/arp_packet.h>
98 #include <vnet/interface.h>
99 #include <vnet/l2/l2_fib.h>
100 #include <vnet/l2/l2_bd.h>
101 #include <vpp/api/vpe_msg_enum.h>
102 #include <vnet/span/span.h>
103 #include <vnet/fib/ip6_fib.h>
104 #include <vnet/fib/ip4_fib.h>
105 #include <vnet/fib/fib_api.h>
106 #include <vnet/dpo/drop_dpo.h>
107 #include <vnet/dpo/receive_dpo.h>
108 #include <vnet/dpo/lookup_dpo.h>
109 #include <vnet/dpo/classify_dpo.h>
110 #include <vnet/dpo/ip_null_dpo.h>
111 #define vl_typedefs             /* define message structures */
112 #include <vpp/api/vpe_all_api_h.h>
113 #undef vl_typedefs
114 #define vl_endianfun            /* define message structures */
115 #include <vpp/api/vpe_all_api_h.h>
116 #undef vl_endianfun
117 /* instantiate all the print functions we know about */
118 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
119 #define vl_printfun
120 #include <vpp/api/vpe_all_api_h.h>
121 #undef vl_printfun
122 #include <vlibapi/api_helper_macros.h>
123 #define foreach_vpe_api_msg                                             \
124 _(WANT_OAM_EVENTS, want_oam_events)                                     \
125 _(OAM_ADD_DEL, oam_add_del)                                             \
126 _(MPLS_ROUTE_ADD_DEL, mpls_route_add_del)                               \
127 _(MPLS_IP_BIND_UNBIND, mpls_ip_bind_unbind)                             \
128 _(IS_ADDRESS_REACHABLE, is_address_reachable)                           \
129 _(SW_INTERFACE_SET_MPLS_ENABLE, sw_interface_set_mpls_enable)           \
130 _(SW_INTERFACE_SET_VPATH, sw_interface_set_vpath)                       \
131 _(SW_INTERFACE_SET_VXLAN_BYPASS, sw_interface_set_vxlan_bypass)         \
132 _(SW_INTERFACE_SET_L2_XCONNECT, sw_interface_set_l2_xconnect)           \
133 _(SW_INTERFACE_SET_L2_BRIDGE, sw_interface_set_l2_bridge)               \
134 _(SW_INTERFACE_SET_DPDK_HQOS_PIPE, sw_interface_set_dpdk_hqos_pipe)     \
135 _(SW_INTERFACE_SET_DPDK_HQOS_SUBPORT, sw_interface_set_dpdk_hqos_subport) \
136 _(SW_INTERFACE_SET_DPDK_HQOS_TCTBL, sw_interface_set_dpdk_hqos_tctbl)   \
137 _(BRIDGE_DOMAIN_ADD_DEL, bridge_domain_add_del)                         \
138 _(BRIDGE_DOMAIN_DUMP, bridge_domain_dump)                               \
139 _(BRIDGE_DOMAIN_DETAILS, bridge_domain_details)                         \
140 _(BRIDGE_DOMAIN_SW_IF_DETAILS, bridge_domain_sw_if_details)             \
141 _(L2FIB_ADD_DEL, l2fib_add_del)                                         \
142 _(L2_FLAGS, l2_flags)                                                   \
143 _(BRIDGE_FLAGS, bridge_flags)                                           \
144 _(CREATE_VLAN_SUBIF, create_vlan_subif)                                 \
145 _(CREATE_SUBIF, create_subif)                                           \
146 _(MPLS_TUNNEL_ADD_DEL, mpls_tunnel_add_del)                             \
147 _(PROXY_ARP_ADD_DEL, proxy_arp_add_del)                                 \
148 _(PROXY_ARP_INTFC_ENABLE_DISABLE, proxy_arp_intfc_enable_disable)       \
149 _(VNET_GET_SUMMARY_STATS, vnet_get_summary_stats)                       \
150 _(RESET_FIB, reset_fib)                                                 \
151 _(DHCP_PROXY_CONFIG,dhcp_proxy_config)                                  \
152 _(DHCP_PROXY_CONFIG_2,dhcp_proxy_config_2)                              \
153 _(DHCP_PROXY_SET_VSS,dhcp_proxy_set_vss)                                \
154 _(DHCP_CLIENT_CONFIG, dhcp_client_config)                               \
155 _(CREATE_LOOPBACK, create_loopback)                                     \
156 _(CONTROL_PING, control_ping)                                           \
157 _(CLI_REQUEST, cli_request)                                             \
158 _(CLI_INBAND, cli_inband)                                               \
159 _(SET_ARP_NEIGHBOR_LIMIT, set_arp_neighbor_limit)                       \
160 _(L2_PATCH_ADD_DEL, l2_patch_add_del)                                   \
161 _(CLASSIFY_ADD_DEL_TABLE, classify_add_del_table)                       \
162 _(CLASSIFY_ADD_DEL_SESSION, classify_add_del_session)                   \
163 _(CLASSIFY_SET_INTERFACE_IP_TABLE, classify_set_interface_ip_table)     \
164 _(CLASSIFY_SET_INTERFACE_L2_TABLES, classify_set_interface_l2_tables)   \
165 _(GET_NODE_INDEX, get_node_index)                                       \
166 _(ADD_NODE_NEXT, add_node_next)                                         \
167 _(VXLAN_ADD_DEL_TUNNEL, vxlan_add_del_tunnel)                           \
168 _(VXLAN_TUNNEL_DUMP, vxlan_tunnel_dump)                                 \
169 _(L2_FIB_CLEAR_TABLE, l2_fib_clear_table)                               \
170 _(L2_INTERFACE_EFP_FILTER, l2_interface_efp_filter)                     \
171 _(L2_INTERFACE_VLAN_TAG_REWRITE, l2_interface_vlan_tag_rewrite)         \
172 _(SHOW_VERSION, show_version)                                           \
173 _(L2_FIB_TABLE_DUMP, l2_fib_table_dump)                                 \
174 _(L2_FIB_TABLE_ENTRY, l2_fib_table_entry)                               \
175 _(VXLAN_GPE_ADD_DEL_TUNNEL, vxlan_gpe_add_del_tunnel)                   \
176 _(VXLAN_GPE_TUNNEL_DUMP, vxlan_gpe_tunnel_dump)                         \
177 _(INTERFACE_NAME_RENUMBER, interface_name_renumber)                     \
178 _(WANT_IP4_ARP_EVENTS, want_ip4_arp_events)                             \
179 _(WANT_IP6_ND_EVENTS, want_ip6_nd_events)                               \
180 _(INPUT_ACL_SET_INTERFACE, input_acl_set_interface)                     \
181 _(DELETE_LOOPBACK, delete_loopback)                                     \
182 _(BD_IP_MAC_ADD_DEL, bd_ip_mac_add_del)                                 \
183 _(COP_INTERFACE_ENABLE_DISABLE, cop_interface_enable_disable)           \
184 _(COP_WHITELIST_ENABLE_DISABLE, cop_whitelist_enable_disable)           \
185 _(GET_NODE_GRAPH, get_node_graph)                                       \
186 _(IOAM_ENABLE, ioam_enable)                                             \
187 _(IOAM_DISABLE, ioam_disable)                                           \
188 _(SR_MULTICAST_MAP_ADD_DEL, sr_multicast_map_add_del)                   \
189 _(POLICER_ADD_DEL, policer_add_del)                                     \
190 _(POLICER_DUMP, policer_dump)                                           \
191 _(POLICER_CLASSIFY_SET_INTERFACE, policer_classify_set_interface)       \
192 _(POLICER_CLASSIFY_DUMP, policer_classify_dump)                         \
193 _(MPLS_TUNNEL_DUMP, mpls_tunnel_dump)                                   \
194 _(MPLS_TUNNEL_DETAILS, mpls_tunnel_details)                             \
195 _(MPLS_FIB_DUMP, mpls_fib_dump)                                         \
196 _(MPLS_FIB_DETAILS, mpls_fib_details)                                   \
197 _(CLASSIFY_TABLE_IDS,classify_table_ids)                                \
198 _(CLASSIFY_TABLE_BY_INTERFACE, classify_table_by_interface)             \
199 _(CLASSIFY_TABLE_INFO,classify_table_info)                              \
200 _(CLASSIFY_SESSION_DUMP,classify_session_dump)                          \
201 _(CLASSIFY_SESSION_DETAILS,classify_session_details)                    \
202 _(SET_IPFIX_EXPORTER, set_ipfix_exporter)                               \
203 _(IPFIX_EXPORTER_DUMP, ipfix_exporter_dump)                             \
204 _(SET_IPFIX_CLASSIFY_STREAM, set_ipfix_classify_stream)                 \
205 _(IPFIX_CLASSIFY_STREAM_DUMP, ipfix_classify_stream_dump)               \
206 _(IPFIX_CLASSIFY_TABLE_ADD_DEL, ipfix_classify_table_add_del)           \
207 _(IPFIX_CLASSIFY_TABLE_DUMP, ipfix_classify_table_dump)                 \
208 _(GET_NEXT_INDEX, get_next_index)                                       \
209 _(PG_CREATE_INTERFACE, pg_create_interface)                             \
210 _(PG_CAPTURE, pg_capture)                                               \
211 _(PG_ENABLE_DISABLE, pg_enable_disable)                                 \
212 _(IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL,                               \
213   ip_source_and_port_range_check_add_del)                               \
214 _(IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL,                     \
215   ip_source_and_port_range_check_interface_add_del)                     \
216 _(DELETE_SUBIF, delete_subif)                                           \
217 _(L2_INTERFACE_PBB_TAG_REWRITE, l2_interface_pbb_tag_rewrite)           \
218 _(PUNT, punt)                                                           \
219 _(FLOW_CLASSIFY_SET_INTERFACE, flow_classify_set_interface)             \
220 _(FLOW_CLASSIFY_DUMP, flow_classify_dump)                               \
221 _(FEATURE_ENABLE_DISABLE, feature_enable_disable)
222
223 #define QUOTE_(x) #x
224 #define QUOTE(x) QUOTE_(x)
225 typedef enum
226 {
227   RESOLVE_IP4_ADD_DEL_ROUTE = 1,
228   RESOLVE_IP6_ADD_DEL_ROUTE,
229 } resolve_t;
230
231 static vlib_node_registration_t vpe_resolver_process_node;
232 vpe_api_main_t vpe_api_main;
233
234 static int arp_change_delete_callback (u32 pool_index, u8 * notused);
235 static int nd_change_delete_callback (u32 pool_index, u8 * notused);
236
237 /* Clean up all registrations belonging to the indicated client */
238 int
239 vl_api_memclnt_delete_callback (u32 client_index)
240 {
241   vpe_api_main_t *vam = &vpe_api_main;
242   vpe_client_registration_t *rp;
243   uword *p;
244   int stats_memclnt_delete_callback (u32 client_index);
245
246   stats_memclnt_delete_callback (client_index);
247
248 #define _(a)                                                    \
249     p = hash_get (vam->a##_registration_hash, client_index);    \
250     if (p) {                                                    \
251         rp = pool_elt_at_index (vam->a##_registrations, p[0]);  \
252         pool_put (vam->a##_registrations, rp);                  \
253         hash_unset (vam->a##_registration_hash, client_index);  \
254     }
255   foreach_registration_hash;
256 #undef _
257   return 0;
258 }
259
260 pub_sub_handler (oam_events, OAM_EVENTS);
261
262 #define RESOLUTION_EVENT 1
263 #define RESOLUTION_PENDING_EVENT 2
264 #define IP4_ARP_EVENT 3
265 #define IP6_ND_EVENT 4
266
267 int ip4_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp);
268
269 int ip6_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp);
270
271 void
272 handle_ip4_arp_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_ip4_arp_event_t *event;
278   vl_api_ip4_arp_event_t *mp;
279   unix_shared_memory_queue_t *q;
280
281   /* Client can cancel, die, etc. */
282   if (pool_is_free_index (vam->arp_events, pool_index))
283     return;
284
285   event = pool_elt_at_index (vam->arp_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_ip4_arp_change_event
291         (vnm, arp_change_delete_callback,
292          event->pid, &event->address,
293          vpe_resolver_process_node.index, IP4_ARP_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 ("arp event for %U to pid %d: queue stuffed!",
314                         format_ip4_address, &event->address, event->pid);
315           last_time = vlib_time_now (vm);
316         }
317     }
318 }
319
320 void
321 handle_ip6_nd_event (u32 pool_index)
322 {
323   vpe_api_main_t *vam = &vpe_api_main;
324   vnet_main_t *vnm = vam->vnet_main;
325   vlib_main_t *vm = vam->vlib_main;
326   vl_api_ip6_nd_event_t *event;
327   vl_api_ip6_nd_event_t *mp;
328   unix_shared_memory_queue_t *q;
329
330   /* Client can cancel, die, etc. */
331   if (pool_is_free_index (vam->nd_events, pool_index))
332     return;
333
334   event = pool_elt_at_index (vam->nd_events, pool_index);
335
336   q = vl_api_client_index_to_input_queue (event->client_index);
337   if (!q)
338     {
339       (void) vnet_add_del_ip6_nd_change_event
340         (vnm, nd_change_delete_callback,
341          event->pid, &event->address,
342          vpe_resolver_process_node.index, IP6_ND_EVENT,
343          ~0 /* pool index, notused */ , 0 /* is_add */ );
344       return;
345     }
346
347   if (q->cursize < q->maxsize)
348     {
349       mp = vl_msg_api_alloc (sizeof (*mp));
350       clib_memcpy (mp, event, sizeof (*mp));
351       vl_msg_api_send_shmem (q, (u8 *) & mp);
352     }
353   else
354     {
355       static f64 last_time;
356       /*
357        * Throttle syslog msgs.
358        * It's pretty tempting to just revoke the registration...
359        */
360       if (vlib_time_now (vm) > last_time + 10.0)
361         {
362           clib_warning ("ip6 nd event for %U to pid %d: queue stuffed!",
363                         format_ip6_address, &event->address, event->pid);
364           last_time = vlib_time_now (vm);
365         }
366     }
367 }
368
369 static uword
370 resolver_process (vlib_main_t * vm,
371                   vlib_node_runtime_t * rt, vlib_frame_t * f)
372 {
373   uword event_type;
374   uword *event_data = 0;
375   f64 timeout = 100.0;
376   int i;
377
378   while (1)
379     {
380       vlib_process_wait_for_event_or_clock (vm, timeout);
381
382       event_type = vlib_process_get_events (vm, &event_data);
383
384       switch (event_type)
385         {
386         case RESOLUTION_PENDING_EVENT:
387           timeout = 1.0;
388           break;
389
390         case RESOLUTION_EVENT:
391           clib_warning ("resolver: BOGUS TYPE");
392           break;
393
394         case IP4_ARP_EVENT:
395           for (i = 0; i < vec_len (event_data); i++)
396             handle_ip4_arp_event (event_data[i]);
397           break;
398
399         case IP6_ND_EVENT:
400           for (i = 0; i < vec_len (event_data); i++)
401             handle_ip6_nd_event (event_data[i]);
402           break;
403
404         case ~0:                /* timeout */
405           break;
406         }
407
408       vec_reset_length (event_data);
409     }
410   return 0;                     /* or not */
411 }
412
413 /* *INDENT-OFF* */
414 VLIB_REGISTER_NODE (vpe_resolver_process_node,static) = {
415   .function = resolver_process,
416   .type = VLIB_NODE_TYPE_PROCESS,
417   .name = "vpe-route-resolver-process",
418 };
419 /* *INDENT-ON* */
420
421 static int
422 mpls_route_add_del_t_handler (vnet_main_t * vnm,
423                               vl_api_mpls_route_add_del_t * mp)
424 {
425   u32 fib_index, next_hop_fib_index;
426   mpls_label_t *label_stack = NULL;
427   int rv, ii, n_labels;;
428
429   fib_prefix_t pfx = {
430     .fp_len = 21,
431     .fp_proto = FIB_PROTOCOL_MPLS,
432     .fp_eos = mp->mr_eos,
433     .fp_label = ntohl (mp->mr_label),
434   };
435   if (pfx.fp_eos)
436     {
437       if (mp->mr_next_hop_proto_is_ip4)
438         {
439           pfx.fp_payload_proto = DPO_PROTO_IP4;
440         }
441       else
442         {
443           pfx.fp_payload_proto = DPO_PROTO_IP6;
444         }
445     }
446   else
447     {
448       pfx.fp_payload_proto = DPO_PROTO_MPLS;
449     }
450
451   rv = add_del_route_check (FIB_PROTOCOL_MPLS,
452                             mp->mr_table_id,
453                             mp->mr_next_hop_sw_if_index,
454                             dpo_proto_to_fib (pfx.fp_payload_proto),
455                             mp->mr_next_hop_table_id,
456                             mp->mr_create_table_if_needed,
457                             &fib_index, &next_hop_fib_index);
458
459   if (0 != rv)
460     return (rv);
461
462   ip46_address_t nh;
463   memset (&nh, 0, sizeof (nh));
464
465   if (mp->mr_next_hop_proto_is_ip4)
466     memcpy (&nh.ip4, mp->mr_next_hop, sizeof (nh.ip4));
467   else
468     memcpy (&nh.ip6, mp->mr_next_hop, sizeof (nh.ip6));
469
470   n_labels = mp->mr_next_hop_n_out_labels;
471   if (n_labels == 0)
472     ;
473   else if (1 == n_labels)
474     vec_add1 (label_stack, ntohl (mp->mr_next_hop_out_label_stack[0]));
475   else
476     {
477       vec_validate (label_stack, n_labels - 1);
478       for (ii = 0; ii < n_labels; ii++)
479         label_stack[ii] = ntohl (mp->mr_next_hop_out_label_stack[ii]);
480     }
481
482   return (add_del_route_t_handler (mp->mr_is_multipath, mp->mr_is_add, 0,       // mp->is_drop,
483                                    0,   // mp->is_unreach,
484                                    0,   // mp->is_prohibit,
485                                    0,   // mp->is_local,
486                                    mp->mr_is_classify,
487                                    mp->mr_classify_table_index,
488                                    mp->mr_is_resolve_host,
489                                    mp->mr_is_resolve_attached,
490                                    fib_index, &pfx,
491                                    mp->mr_next_hop_proto_is_ip4,
492                                    &nh, ntohl (mp->mr_next_hop_sw_if_index),
493                                    next_hop_fib_index,
494                                    mp->mr_next_hop_weight,
495                                    ntohl (mp->mr_next_hop_via_label),
496                                    label_stack));
497 }
498
499 void
500 vl_api_mpls_route_add_del_t_handler (vl_api_mpls_route_add_del_t * mp)
501 {
502   vl_api_mpls_route_add_del_reply_t *rmp;
503   vnet_main_t *vnm;
504   int rv;
505
506   vnm = vnet_get_main ();
507   vnm->api_errno = 0;
508
509   rv = mpls_route_add_del_t_handler (vnm, mp);
510
511   rv = (rv == 0) ? vnm->api_errno : rv;
512
513   REPLY_MACRO (VL_API_MPLS_ROUTE_ADD_DEL_REPLY);
514 }
515
516 static int
517 mpls_ip_bind_unbind_handler (vnet_main_t * vnm,
518                              vl_api_mpls_ip_bind_unbind_t * mp)
519 {
520   u32 mpls_fib_index, ip_fib_index;
521
522   mpls_fib_index =
523     fib_table_find (FIB_PROTOCOL_MPLS, ntohl (mp->mb_mpls_table_id));
524
525   if (~0 == mpls_fib_index)
526     {
527       if (mp->mb_create_table_if_needed)
528         {
529           mpls_fib_index =
530             fib_table_find_or_create_and_lock (FIB_PROTOCOL_MPLS,
531                                                ntohl (mp->mb_mpls_table_id));
532         }
533       else
534         return VNET_API_ERROR_NO_SUCH_FIB;
535     }
536
537   ip_fib_index = fib_table_find ((mp->mb_is_ip4 ?
538                                   FIB_PROTOCOL_IP4 :
539                                   FIB_PROTOCOL_IP6),
540                                  ntohl (mp->mb_ip_table_id));
541   if (~0 == ip_fib_index)
542     return VNET_API_ERROR_NO_SUCH_FIB;
543
544   fib_prefix_t pfx = {
545     .fp_len = mp->mb_address_length,
546   };
547
548   if (mp->mb_is_ip4)
549     {
550       pfx.fp_proto = FIB_PROTOCOL_IP4;
551       clib_memcpy (&pfx.fp_addr.ip4, mp->mb_address,
552                    sizeof (pfx.fp_addr.ip4));
553     }
554   else
555     {
556       pfx.fp_proto = FIB_PROTOCOL_IP6;
557       clib_memcpy (&pfx.fp_addr.ip6, mp->mb_address,
558                    sizeof (pfx.fp_addr.ip6));
559     }
560
561   if (mp->mb_is_bind)
562     fib_table_entry_local_label_add (ip_fib_index, &pfx,
563                                      ntohl (mp->mb_label));
564   else
565     fib_table_entry_local_label_remove (ip_fib_index, &pfx,
566                                         ntohl (mp->mb_label));
567
568   return (0);
569 }
570
571 void
572 vl_api_mpls_ip_bind_unbind_t_handler (vl_api_mpls_ip_bind_unbind_t * mp)
573 {
574   vl_api_mpls_route_add_del_reply_t *rmp;
575   vnet_main_t *vnm;
576   int rv;
577
578   vnm = vnet_get_main ();
579   vnm->api_errno = 0;
580
581   rv = mpls_ip_bind_unbind_handler (vnm, mp);
582
583   rv = (rv == 0) ? vnm->api_errno : rv;
584
585   REPLY_MACRO (VL_API_MPLS_ROUTE_ADD_DEL_REPLY);
586 }
587
588 static void
589 vl_api_sw_interface_set_vpath_t_handler (vl_api_sw_interface_set_vpath_t * mp)
590 {
591   vl_api_sw_interface_set_vpath_reply_t *rmp;
592   int rv = 0;
593   u32 sw_if_index = ntohl (mp->sw_if_index);
594
595   VALIDATE_SW_IF_INDEX (mp);
596
597   l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_VPATH, mp->enable);
598   vnet_feature_enable_disable ("ip4-unicast", "vpath-input-ip4",
599                                sw_if_index, mp->enable, 0, 0);
600   vnet_feature_enable_disable ("ip4-multicast", "vpath-input-ip4",
601                                sw_if_index, mp->enable, 0, 0);
602   vnet_feature_enable_disable ("ip6-unicast", "vpath-input-ip6",
603                                sw_if_index, mp->enable, 0, 0);
604   vnet_feature_enable_disable ("ip6-multicast", "vpath-input-ip6",
605                                sw_if_index, mp->enable, 0, 0);
606
607   BAD_SW_IF_INDEX_LABEL;
608
609   REPLY_MACRO (VL_API_SW_INTERFACE_SET_VPATH_REPLY);
610 }
611
612 static void
613   vl_api_sw_interface_set_vxlan_bypass_t_handler
614   (vl_api_sw_interface_set_vxlan_bypass_t * mp)
615 {
616   vl_api_sw_interface_set_vxlan_bypass_reply_t *rmp;
617   int rv = 0;
618   u32 sw_if_index = ntohl (mp->sw_if_index);
619
620   VALIDATE_SW_IF_INDEX (mp);
621
622   if (mp->is_ipv6)
623     {
624       /* not yet implemented */
625     }
626   else
627     vnet_feature_enable_disable ("ip4-unicast", "ip4-vxlan-bypass",
628                                  sw_if_index, mp->enable, 0, 0);
629
630   BAD_SW_IF_INDEX_LABEL;
631
632   REPLY_MACRO (VL_API_SW_INTERFACE_SET_VXLAN_BYPASS_REPLY);
633 }
634
635 static void
636   vl_api_sw_interface_set_l2_xconnect_t_handler
637   (vl_api_sw_interface_set_l2_xconnect_t * mp)
638 {
639   vl_api_sw_interface_set_l2_xconnect_reply_t *rmp;
640   int rv = 0;
641   u32 rx_sw_if_index = ntohl (mp->rx_sw_if_index);
642   u32 tx_sw_if_index = ntohl (mp->tx_sw_if_index);
643   vlib_main_t *vm = vlib_get_main ();
644   vnet_main_t *vnm = vnet_get_main ();
645
646   VALIDATE_RX_SW_IF_INDEX (mp);
647
648   if (mp->enable)
649     {
650       VALIDATE_TX_SW_IF_INDEX (mp);
651       rv = set_int_l2_mode (vm, vnm, MODE_L2_XC,
652                             rx_sw_if_index, 0, 0, 0, tx_sw_if_index);
653     }
654   else
655     {
656       rv = set_int_l2_mode (vm, vnm, MODE_L3, rx_sw_if_index, 0, 0, 0, 0);
657     }
658
659   BAD_RX_SW_IF_INDEX_LABEL;
660   BAD_TX_SW_IF_INDEX_LABEL;
661
662   REPLY_MACRO (VL_API_SW_INTERFACE_SET_L2_XCONNECT_REPLY);
663 }
664
665 static void
666   vl_api_sw_interface_set_l2_bridge_t_handler
667   (vl_api_sw_interface_set_l2_bridge_t * mp)
668 {
669   bd_main_t *bdm = &bd_main;
670   vl_api_sw_interface_set_l2_bridge_reply_t *rmp;
671   int rv = 0;
672   u32 rx_sw_if_index = ntohl (mp->rx_sw_if_index);
673   u32 bd_id = ntohl (mp->bd_id);
674   u32 bd_index;
675   u32 bvi = mp->bvi;
676   u8 shg = mp->shg;
677   vlib_main_t *vm = vlib_get_main ();
678   vnet_main_t *vnm = vnet_get_main ();
679
680   VALIDATE_RX_SW_IF_INDEX (mp);
681
682   bd_index = bd_find_or_add_bd_index (bdm, bd_id);
683
684   if (mp->enable)
685     {
686       //VALIDATE_TX_SW_IF_INDEX(mp);
687       rv = set_int_l2_mode (vm, vnm, MODE_L2_BRIDGE,
688                             rx_sw_if_index, bd_index, bvi, shg, 0);
689     }
690   else
691     {
692       rv = set_int_l2_mode (vm, vnm, MODE_L3, rx_sw_if_index, 0, 0, 0, 0);
693     }
694
695   BAD_RX_SW_IF_INDEX_LABEL;
696
697   REPLY_MACRO (VL_API_SW_INTERFACE_SET_L2_BRIDGE_REPLY);
698 }
699
700 static void
701   vl_api_sw_interface_set_dpdk_hqos_pipe_t_handler
702   (vl_api_sw_interface_set_dpdk_hqos_pipe_t * mp)
703 {
704   vl_api_sw_interface_set_dpdk_hqos_pipe_reply_t *rmp;
705   int rv = 0;
706
707 #if DPDK > 0
708   dpdk_main_t *dm = &dpdk_main;
709   dpdk_device_t *xd;
710
711   u32 sw_if_index = ntohl (mp->sw_if_index);
712   u32 subport = ntohl (mp->subport);
713   u32 pipe = ntohl (mp->pipe);
714   u32 profile = ntohl (mp->profile);
715   vnet_hw_interface_t *hw;
716
717   VALIDATE_SW_IF_INDEX (mp);
718
719   /* hw_if & dpdk device */
720   hw = vnet_get_sup_hw_interface (dm->vnet_main, sw_if_index);
721
722   xd = vec_elt_at_index (dm->devices, hw->dev_instance);
723
724   rv = rte_sched_pipe_config (xd->hqos_ht->hqos, subport, pipe, profile);
725
726   BAD_SW_IF_INDEX_LABEL;
727 #else
728   clib_warning ("setting HQoS pipe parameters without DPDK not implemented");
729   rv = VNET_API_ERROR_UNIMPLEMENTED;
730 #endif /* DPDK */
731
732   REPLY_MACRO (VL_API_SW_INTERFACE_SET_DPDK_HQOS_PIPE_REPLY);
733 }
734
735 static void
736   vl_api_sw_interface_set_dpdk_hqos_subport_t_handler
737   (vl_api_sw_interface_set_dpdk_hqos_subport_t * mp)
738 {
739   vl_api_sw_interface_set_dpdk_hqos_subport_reply_t *rmp;
740   int rv = 0;
741
742 #if DPDK > 0
743   dpdk_main_t *dm = &dpdk_main;
744   dpdk_device_t *xd;
745   struct rte_sched_subport_params p;
746
747   u32 sw_if_index = ntohl (mp->sw_if_index);
748   u32 subport = ntohl (mp->subport);
749   p.tb_rate = ntohl (mp->tb_rate);
750   p.tb_size = ntohl (mp->tb_size);
751   p.tc_rate[0] = ntohl (mp->tc_rate[0]);
752   p.tc_rate[1] = ntohl (mp->tc_rate[1]);
753   p.tc_rate[2] = ntohl (mp->tc_rate[2]);
754   p.tc_rate[3] = ntohl (mp->tc_rate[3]);
755   p.tc_period = ntohl (mp->tc_period);
756
757   vnet_hw_interface_t *hw;
758
759   VALIDATE_SW_IF_INDEX (mp);
760
761   /* hw_if & dpdk device */
762   hw = vnet_get_sup_hw_interface (dm->vnet_main, sw_if_index);
763
764   xd = vec_elt_at_index (dm->devices, hw->dev_instance);
765
766   rv = rte_sched_subport_config (xd->hqos_ht->hqos, subport, &p);
767
768   BAD_SW_IF_INDEX_LABEL;
769 #else
770   clib_warning
771     ("setting HQoS subport parameters without DPDK not implemented");
772   rv = VNET_API_ERROR_UNIMPLEMENTED;
773 #endif /* DPDK */
774
775   REPLY_MACRO (VL_API_SW_INTERFACE_SET_DPDK_HQOS_SUBPORT_REPLY);
776 }
777
778 static void
779   vl_api_sw_interface_set_dpdk_hqos_tctbl_t_handler
780   (vl_api_sw_interface_set_dpdk_hqos_tctbl_t * mp)
781 {
782   vl_api_sw_interface_set_dpdk_hqos_tctbl_reply_t *rmp;
783   int rv = 0;
784
785 #if DPDK > 0
786   dpdk_main_t *dm = &dpdk_main;
787   vlib_thread_main_t *tm = vlib_get_thread_main ();
788   dpdk_device_t *xd;
789
790   u32 sw_if_index = ntohl (mp->sw_if_index);
791   u32 entry = ntohl (mp->entry);
792   u32 tc = ntohl (mp->tc);
793   u32 queue = ntohl (mp->queue);
794   u32 val, i;
795
796   vnet_hw_interface_t *hw;
797
798   VALIDATE_SW_IF_INDEX (mp);
799
800   /* hw_if & dpdk device */
801   hw = vnet_get_sup_hw_interface (dm->vnet_main, sw_if_index);
802
803   xd = vec_elt_at_index (dm->devices, hw->dev_instance);
804
805   if (tc >= RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE)
806     {
807       clib_warning ("invalid traffic class !!");
808       rv = VNET_API_ERROR_INVALID_VALUE;
809       goto done;
810     }
811   if (queue >= RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS)
812     {
813       clib_warning ("invalid queue !!");
814       rv = VNET_API_ERROR_INVALID_VALUE;
815       goto done;
816     }
817
818   /* Detect the set of worker threads */
819   uword *p = hash_get_mem (tm->thread_registrations_by_name, "workers");
820
821   if (p == 0)
822     {
823       clib_warning ("worker thread registration AWOL !!");
824       rv = VNET_API_ERROR_INVALID_VALUE_2;
825       goto done;
826     }
827
828   vlib_thread_registration_t *tr = (vlib_thread_registration_t *) p[0];
829   int worker_thread_first = tr->first_index;
830   int worker_thread_count = tr->count;
831
832   val = tc * RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS + queue;
833   for (i = 0; i < worker_thread_count; i++)
834     xd->hqos_wt[worker_thread_first + i].hqos_tc_table[entry] = val;
835
836   BAD_SW_IF_INDEX_LABEL;
837 done:
838 #else
839   clib_warning ("setting HQoS DSCP table entry without DPDK not implemented");
840   rv = VNET_API_ERROR_UNIMPLEMENTED;
841 #endif /* DPDK */
842
843   REPLY_MACRO (VL_API_SW_INTERFACE_SET_DPDK_HQOS_TCTBL_REPLY);
844 }
845
846 static void
847 vl_api_bridge_domain_add_del_t_handler (vl_api_bridge_domain_add_del_t * mp)
848 {
849   vlib_main_t *vm = vlib_get_main ();
850   bd_main_t *bdm = &bd_main;
851   vl_api_bridge_domain_add_del_reply_t *rmp;
852   int rv = 0;
853   u32 enable_flags = 0, disable_flags = 0;
854   u32 bd_id = ntohl (mp->bd_id);
855   u32 bd_index;
856
857   if (mp->is_add)
858     {
859       bd_index = bd_find_or_add_bd_index (bdm, bd_id);
860
861       if (mp->flood)
862         enable_flags |= L2_FLOOD;
863       else
864         disable_flags |= L2_FLOOD;
865
866       if (mp->uu_flood)
867         enable_flags |= L2_UU_FLOOD;
868       else
869         disable_flags |= L2_UU_FLOOD;
870
871       if (mp->forward)
872         enable_flags |= L2_FWD;
873       else
874         disable_flags |= L2_FWD;
875
876       if (mp->arp_term)
877         enable_flags |= L2_ARP_TERM;
878       else
879         disable_flags |= L2_ARP_TERM;
880
881       if (mp->learn)
882         enable_flags |= L2_LEARN;
883       else
884         disable_flags |= L2_LEARN;
885
886       if (enable_flags)
887         bd_set_flags (vm, bd_index, enable_flags, 1 /* enable */ );
888
889       if (disable_flags)
890         bd_set_flags (vm, bd_index, disable_flags, 0 /* disable */ );
891
892       bd_set_mac_age (vm, bd_index, mp->mac_age);
893     }
894   else
895     rv = bd_delete_bd_index (bdm, bd_id);
896
897   REPLY_MACRO (VL_API_BRIDGE_DOMAIN_ADD_DEL_REPLY);
898 }
899
900 static void
901 vl_api_bridge_domain_details_t_handler (vl_api_bridge_domain_details_t * mp)
902 {
903   clib_warning ("BUG");
904 }
905
906 static void
907   vl_api_bridge_domain_sw_if_details_t_handler
908   (vl_api_bridge_domain_sw_if_details_t * mp)
909 {
910   clib_warning ("BUG");
911 }
912
913 static void
914 send_bridge_domain_details (unix_shared_memory_queue_t * q,
915                             l2_bridge_domain_t * bd_config,
916                             u32 n_sw_ifs, u32 context)
917 {
918   vl_api_bridge_domain_details_t *mp;
919
920   mp = vl_msg_api_alloc (sizeof (*mp));
921   memset (mp, 0, sizeof (*mp));
922   mp->_vl_msg_id = ntohs (VL_API_BRIDGE_DOMAIN_DETAILS);
923   mp->bd_id = ntohl (bd_config->bd_id);
924   mp->flood = bd_feature_flood (bd_config);
925   mp->uu_flood = bd_feature_uu_flood (bd_config);
926   mp->forward = bd_feature_forward (bd_config);
927   mp->learn = bd_feature_learn (bd_config);
928   mp->arp_term = bd_feature_arp_term (bd_config);
929   mp->bvi_sw_if_index = ntohl (bd_config->bvi_sw_if_index);
930   mp->mac_age = bd_config->mac_age;
931   mp->n_sw_ifs = ntohl (n_sw_ifs);
932   mp->context = context;
933
934   vl_msg_api_send_shmem (q, (u8 *) & mp);
935 }
936
937 static void
938 send_bd_sw_if_details (l2input_main_t * l2im,
939                        unix_shared_memory_queue_t * q,
940                        l2_flood_member_t * member, u32 bd_id, u32 context)
941 {
942   vl_api_bridge_domain_sw_if_details_t *mp;
943   l2_input_config_t *input_cfg;
944
945   mp = vl_msg_api_alloc (sizeof (*mp));
946   memset (mp, 0, sizeof (*mp));
947   mp->_vl_msg_id = ntohs (VL_API_BRIDGE_DOMAIN_SW_IF_DETAILS);
948   mp->bd_id = ntohl (bd_id);
949   mp->sw_if_index = ntohl (member->sw_if_index);
950   input_cfg = vec_elt_at_index (l2im->configs, member->sw_if_index);
951   mp->shg = input_cfg->shg;
952   mp->context = context;
953
954   vl_msg_api_send_shmem (q, (u8 *) & mp);
955 }
956
957 static void
958 vl_api_bridge_domain_dump_t_handler (vl_api_bridge_domain_dump_t * mp)
959 {
960   bd_main_t *bdm = &bd_main;
961   l2input_main_t *l2im = &l2input_main;
962   unix_shared_memory_queue_t *q;
963   l2_bridge_domain_t *bd_config;
964   u32 bd_id, bd_index;
965   u32 end;
966
967   q = vl_api_client_index_to_input_queue (mp->client_index);
968
969   if (q == 0)
970     return;
971
972   bd_id = ntohl (mp->bd_id);
973
974   bd_index = (bd_id == ~0) ? 0 : bd_find_or_add_bd_index (bdm, bd_id);
975   end = (bd_id == ~0) ? vec_len (l2im->bd_configs) : bd_index + 1;
976   for (; bd_index < end; bd_index++)
977     {
978       bd_config = l2input_bd_config_from_index (l2im, bd_index);
979       /* skip dummy bd_id 0 */
980       if (bd_config && (bd_config->bd_id > 0))
981         {
982           u32 n_sw_ifs;
983           l2_flood_member_t *m;
984
985           n_sw_ifs = vec_len (bd_config->members);
986           send_bridge_domain_details (q, bd_config, n_sw_ifs, mp->context);
987
988           vec_foreach (m, bd_config->members)
989           {
990             send_bd_sw_if_details (l2im, q, m, bd_config->bd_id, mp->context);
991           }
992         }
993     }
994 }
995
996 static void
997 vl_api_l2fib_add_del_t_handler (vl_api_l2fib_add_del_t * mp)
998 {
999   bd_main_t *bdm = &bd_main;
1000   l2input_main_t *l2im = &l2input_main;
1001   vl_api_l2fib_add_del_reply_t *rmp;
1002   int rv = 0;
1003   u64 mac = 0;
1004   u32 sw_if_index = ntohl (mp->sw_if_index);
1005   u32 bd_id = ntohl (mp->bd_id);
1006   u32 bd_index;
1007   u32 static_mac;
1008   u32 filter_mac;
1009   u32 bvi_mac;
1010   uword *p;
1011
1012   mac = mp->mac;
1013
1014   p = hash_get (bdm->bd_index_by_bd_id, bd_id);
1015   if (!p)
1016     {
1017       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1018       goto bad_sw_if_index;
1019     }
1020   bd_index = p[0];
1021
1022   if (mp->is_add)
1023     {
1024       filter_mac = mp->filter_mac ? 1 : 0;
1025       if (filter_mac == 0)
1026         {
1027           VALIDATE_SW_IF_INDEX (mp);
1028           if (vec_len (l2im->configs) <= sw_if_index)
1029             {
1030               rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
1031               goto bad_sw_if_index;
1032             }
1033           else
1034             {
1035               l2_input_config_t *config;
1036               config = vec_elt_at_index (l2im->configs, sw_if_index);
1037               if (config->bridge == 0)
1038                 {
1039                   rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
1040                   goto bad_sw_if_index;
1041                 }
1042             }
1043         }
1044       static_mac = mp->static_mac ? 1 : 0;
1045       bvi_mac = mp->bvi_mac ? 1 : 0;
1046       l2fib_add_entry (mac, bd_index, sw_if_index, static_mac, filter_mac,
1047                        bvi_mac);
1048     }
1049   else
1050     {
1051       l2fib_del_entry (mac, bd_index);
1052     }
1053
1054   BAD_SW_IF_INDEX_LABEL;
1055
1056   REPLY_MACRO (VL_API_L2FIB_ADD_DEL_REPLY);
1057 }
1058
1059 static void
1060 vl_api_l2_flags_t_handler (vl_api_l2_flags_t * mp)
1061 {
1062   vl_api_l2_flags_reply_t *rmp;
1063   int rv = 0;
1064   u32 sw_if_index = ntohl (mp->sw_if_index);
1065   u32 flags = ntohl (mp->feature_bitmap);
1066   u32 rbm = 0;
1067
1068   VALIDATE_SW_IF_INDEX (mp);
1069
1070 #define _(a,b) \
1071     if (flags & L2INPUT_FEAT_ ## a) \
1072         rbm = l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_ ## a, mp->is_set);
1073   foreach_l2input_feat;
1074 #undef _
1075
1076   BAD_SW_IF_INDEX_LABEL;
1077
1078   /* *INDENT-OFF* */
1079   REPLY_MACRO2(VL_API_L2_FLAGS_REPLY,
1080   ({
1081     rmp->resulting_feature_bitmap = ntohl(rbm);
1082   }));
1083   /* *INDENT-ON* */
1084 }
1085
1086 static void
1087 vl_api_bridge_flags_t_handler (vl_api_bridge_flags_t * mp)
1088 {
1089   vlib_main_t *vm = vlib_get_main ();
1090   bd_main_t *bdm = &bd_main;
1091   vl_api_bridge_flags_reply_t *rmp;
1092   int rv = 0;
1093   u32 bd_id = ntohl (mp->bd_id);
1094   u32 bd_index;
1095   u32 flags = ntohl (mp->feature_bitmap);
1096   uword *p;
1097
1098   p = hash_get (bdm->bd_index_by_bd_id, bd_id);
1099   if (p == 0)
1100     {
1101       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1102       goto out;
1103     }
1104
1105   bd_index = p[0];
1106
1107   bd_set_flags (vm, bd_index, flags, mp->is_set);
1108
1109 out:
1110   /* *INDENT-OFF* */
1111   REPLY_MACRO2(VL_API_BRIDGE_FLAGS_REPLY,
1112   ({
1113     rmp->resulting_feature_bitmap = ntohl(flags);
1114   }));
1115   /* *INDENT-ON* */
1116 }
1117
1118 static void
1119 vl_api_bd_ip_mac_add_del_t_handler (vl_api_bd_ip_mac_add_del_t * mp)
1120 {
1121   bd_main_t *bdm = &bd_main;
1122   vl_api_bd_ip_mac_add_del_reply_t *rmp;
1123   int rv = 0;
1124   u32 bd_id = ntohl (mp->bd_id);
1125   u32 bd_index;
1126   uword *p;
1127
1128   p = hash_get (bdm->bd_index_by_bd_id, bd_id);
1129   if (p == 0)
1130     {
1131       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1132       goto out;
1133     }
1134
1135   bd_index = p[0];
1136   if (bd_add_del_ip_mac (bd_index, mp->ip_address,
1137                          mp->mac_address, mp->is_ipv6, mp->is_add))
1138     rv = VNET_API_ERROR_UNSPECIFIED;
1139
1140 out:
1141   REPLY_MACRO (VL_API_BD_IP_MAC_ADD_DEL_REPLY);
1142 }
1143
1144 static void
1145 vl_api_create_vlan_subif_t_handler (vl_api_create_vlan_subif_t * mp)
1146 {
1147   vl_api_create_vlan_subif_reply_t *rmp;
1148   vnet_main_t *vnm = vnet_get_main ();
1149   u32 hw_if_index, sw_if_index = (u32) ~ 0;
1150   vnet_hw_interface_t *hi;
1151   int rv = 0;
1152   u32 id;
1153   vnet_sw_interface_t template;
1154   uword *p;
1155   vnet_interface_main_t *im = &vnm->interface_main;
1156   u64 sup_and_sub_key;
1157   u64 *kp;
1158   unix_shared_memory_queue_t *q;
1159   clib_error_t *error;
1160
1161   VALIDATE_SW_IF_INDEX (mp);
1162
1163   hw_if_index = ntohl (mp->sw_if_index);
1164   hi = vnet_get_hw_interface (vnm, hw_if_index);
1165
1166   id = ntohl (mp->vlan_id);
1167   if (id == 0 || id > 4095)
1168     {
1169       rv = VNET_API_ERROR_INVALID_VLAN;
1170       goto out;
1171     }
1172
1173   sup_and_sub_key = ((u64) (hi->sw_if_index) << 32) | (u64) id;
1174
1175   p = hash_get_mem (im->sw_if_index_by_sup_and_sub, &sup_and_sub_key);
1176   if (p)
1177     {
1178       rv = VNET_API_ERROR_VLAN_ALREADY_EXISTS;
1179       goto out;
1180     }
1181
1182   kp = clib_mem_alloc (sizeof (*kp));
1183   *kp = sup_and_sub_key;
1184
1185   memset (&template, 0, sizeof (template));
1186   template.type = VNET_SW_INTERFACE_TYPE_SUB;
1187   template.sup_sw_if_index = hi->sw_if_index;
1188   template.sub.id = id;
1189   template.sub.eth.raw_flags = 0;
1190   template.sub.eth.flags.one_tag = 1;
1191   template.sub.eth.outer_vlan_id = id;
1192   template.sub.eth.flags.exact_match = 1;
1193
1194   error = vnet_create_sw_interface (vnm, &template, &sw_if_index);
1195   if (error)
1196     {
1197       clib_error_report (error);
1198       rv = VNET_API_ERROR_INVALID_REGISTRATION;
1199       goto out;
1200     }
1201   hash_set (hi->sub_interface_sw_if_index_by_id, id, sw_if_index);
1202   hash_set_mem (im->sw_if_index_by_sup_and_sub, kp, sw_if_index);
1203
1204   BAD_SW_IF_INDEX_LABEL;
1205
1206 out:
1207   q = vl_api_client_index_to_input_queue (mp->client_index);
1208   if (!q)
1209     return;
1210
1211   rmp = vl_msg_api_alloc (sizeof (*rmp));
1212   rmp->_vl_msg_id = ntohs (VL_API_CREATE_VLAN_SUBIF_REPLY);
1213   rmp->context = mp->context;
1214   rmp->retval = ntohl (rv);
1215   rmp->sw_if_index = ntohl (sw_if_index);
1216   vl_msg_api_send_shmem (q, (u8 *) & rmp);
1217 }
1218
1219 static void
1220 vl_api_create_subif_t_handler (vl_api_create_subif_t * mp)
1221 {
1222   vl_api_create_subif_reply_t *rmp;
1223   vnet_main_t *vnm = vnet_get_main ();
1224   u32 sw_if_index = ~0;
1225   int rv = 0;
1226   u32 sub_id;
1227   vnet_sw_interface_t *si;
1228   vnet_hw_interface_t *hi;
1229   vnet_sw_interface_t template;
1230   uword *p;
1231   vnet_interface_main_t *im = &vnm->interface_main;
1232   u64 sup_and_sub_key;
1233   u64 *kp;
1234   clib_error_t *error;
1235
1236   VALIDATE_SW_IF_INDEX (mp);
1237
1238   si = vnet_get_sup_sw_interface (vnm, ntohl (mp->sw_if_index));
1239   hi = vnet_get_sup_hw_interface (vnm, ntohl (mp->sw_if_index));
1240
1241   if (hi->bond_info == VNET_HW_INTERFACE_BOND_INFO_SLAVE)
1242     {
1243       rv = VNET_API_ERROR_BOND_SLAVE_NOT_ALLOWED;
1244       goto out;
1245     }
1246
1247   sw_if_index = si->sw_if_index;
1248   sub_id = ntohl (mp->sub_id);
1249
1250   sup_and_sub_key = ((u64) (sw_if_index) << 32) | (u64) sub_id;
1251
1252   p = hash_get_mem (im->sw_if_index_by_sup_and_sub, &sup_and_sub_key);
1253   if (p)
1254     {
1255       if (CLIB_DEBUG > 0)
1256         clib_warning ("sup sw_if_index %d, sub id %d already exists\n",
1257                       sw_if_index, sub_id);
1258       rv = VNET_API_ERROR_SUBIF_ALREADY_EXISTS;
1259       goto out;
1260     }
1261
1262   kp = clib_mem_alloc (sizeof (*kp));
1263   *kp = sup_and_sub_key;
1264
1265   memset (&template, 0, sizeof (template));
1266   template.type = VNET_SW_INTERFACE_TYPE_SUB;
1267   template.sup_sw_if_index = sw_if_index;
1268   template.sub.id = sub_id;
1269   template.sub.eth.flags.no_tags = mp->no_tags;
1270   template.sub.eth.flags.one_tag = mp->one_tag;
1271   template.sub.eth.flags.two_tags = mp->two_tags;
1272   template.sub.eth.flags.dot1ad = mp->dot1ad;
1273   template.sub.eth.flags.exact_match = mp->exact_match;
1274   template.sub.eth.flags.default_sub = mp->default_sub;
1275   template.sub.eth.flags.outer_vlan_id_any = mp->outer_vlan_id_any;
1276   template.sub.eth.flags.inner_vlan_id_any = mp->inner_vlan_id_any;
1277   template.sub.eth.outer_vlan_id = ntohs (mp->outer_vlan_id);
1278   template.sub.eth.inner_vlan_id = ntohs (mp->inner_vlan_id);
1279
1280   error = vnet_create_sw_interface (vnm, &template, &sw_if_index);
1281   if (error)
1282     {
1283       clib_error_report (error);
1284       rv = VNET_API_ERROR_SUBIF_CREATE_FAILED;
1285       goto out;
1286     }
1287
1288   hash_set (hi->sub_interface_sw_if_index_by_id, sub_id, sw_if_index);
1289   hash_set_mem (im->sw_if_index_by_sup_and_sub, kp, sw_if_index);
1290
1291   BAD_SW_IF_INDEX_LABEL;
1292
1293 out:
1294
1295   /* *INDENT-OFF* */
1296   REPLY_MACRO2(VL_API_CREATE_SUBIF_REPLY,
1297   ({
1298     rmp->sw_if_index = ntohl(sw_if_index);
1299   }));
1300   /* *INDENT-ON* */
1301 }
1302
1303 static void
1304 vl_api_mpls_tunnel_add_del_t_handler (vl_api_mpls_tunnel_add_del_t * mp)
1305 {
1306   vl_api_mpls_tunnel_add_del_reply_t *rmp;
1307   int rv = 0;
1308   stats_main_t *sm = &stats_main;
1309   u32 tunnel_sw_if_index;
1310   int ii;
1311
1312   dslock (sm, 1 /* release hint */ , 5 /* tag */ );
1313
1314   if (mp->mt_is_add)
1315     {
1316       fib_route_path_t rpath, *rpaths = NULL;
1317       mpls_label_t *label_stack = NULL;
1318
1319       memset (&rpath, 0, sizeof (rpath));
1320
1321       if (mp->mt_next_hop_proto_is_ip4)
1322         {
1323           rpath.frp_proto = FIB_PROTOCOL_IP4;
1324           clib_memcpy (&rpath.frp_addr.ip4,
1325                        mp->mt_next_hop, sizeof (rpath.frp_addr.ip4));
1326         }
1327       else
1328         {
1329           rpath.frp_proto = FIB_PROTOCOL_IP6;
1330           clib_memcpy (&rpath.frp_addr.ip6,
1331                        mp->mt_next_hop, sizeof (rpath.frp_addr.ip6));
1332         }
1333       rpath.frp_sw_if_index = ntohl (mp->mt_next_hop_sw_if_index);
1334
1335       for (ii = 0; ii < mp->mt_next_hop_n_out_labels; ii++)
1336         vec_add1 (label_stack, ntohl (mp->mt_next_hop_out_label_stack[ii]));
1337
1338       vec_add1 (rpaths, rpath);
1339
1340       vnet_mpls_tunnel_add (rpaths, label_stack,
1341                             mp->mt_l2_only, &tunnel_sw_if_index);
1342       vec_free (rpaths);
1343       vec_free (label_stack);
1344     }
1345   else
1346     {
1347       tunnel_sw_if_index = ntohl (mp->mt_sw_if_index);
1348       vnet_mpls_tunnel_del (tunnel_sw_if_index);
1349     }
1350
1351   dsunlock (sm);
1352
1353   /* *INDENT-OFF* */
1354   REPLY_MACRO2(VL_API_MPLS_TUNNEL_ADD_DEL_REPLY,
1355   ({
1356     rmp->sw_if_index = ntohl(tunnel_sw_if_index);
1357   }));
1358   /* *INDENT-ON* */
1359 }
1360
1361 static void
1362 vl_api_proxy_arp_add_del_t_handler (vl_api_proxy_arp_add_del_t * mp)
1363 {
1364   vl_api_proxy_arp_add_del_reply_t *rmp;
1365   u32 fib_index;
1366   int rv;
1367   ip4_main_t *im = &ip4_main;
1368   stats_main_t *sm = &stats_main;
1369   int vnet_proxy_arp_add_del (ip4_address_t * lo_addr,
1370                               ip4_address_t * hi_addr,
1371                               u32 fib_index, int is_del);
1372   uword *p;
1373
1374   dslock (sm, 1 /* release hint */ , 6 /* tag */ );
1375
1376   p = hash_get (im->fib_index_by_table_id, ntohl (mp->vrf_id));
1377
1378   if (!p)
1379     {
1380       rv = VNET_API_ERROR_NO_SUCH_FIB;
1381       goto out;
1382     }
1383
1384   fib_index = p[0];
1385
1386   rv = vnet_proxy_arp_add_del ((ip4_address_t *) mp->low_address,
1387                                (ip4_address_t *) mp->hi_address,
1388                                fib_index, mp->is_add == 0);
1389
1390 out:
1391   dsunlock (sm);
1392   REPLY_MACRO (VL_API_PROXY_ARP_ADD_DEL_REPLY);
1393 }
1394
1395 static void
1396   vl_api_proxy_arp_intfc_enable_disable_t_handler
1397   (vl_api_proxy_arp_intfc_enable_disable_t * mp)
1398 {
1399   int rv = 0;
1400   vnet_main_t *vnm = vnet_get_main ();
1401   vl_api_proxy_arp_intfc_enable_disable_reply_t *rmp;
1402   vnet_sw_interface_t *si;
1403   u32 sw_if_index;
1404
1405   VALIDATE_SW_IF_INDEX (mp);
1406
1407   sw_if_index = ntohl (mp->sw_if_index);
1408
1409   if (pool_is_free_index (vnm->interface_main.sw_interfaces, sw_if_index))
1410     {
1411       rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
1412       goto out;
1413     }
1414
1415   si = vnet_get_sw_interface (vnm, sw_if_index);
1416
1417   ASSERT (si);
1418
1419   if (mp->enable_disable)
1420     si->flags |= VNET_SW_INTERFACE_FLAG_PROXY_ARP;
1421   else
1422     si->flags &= ~VNET_SW_INTERFACE_FLAG_PROXY_ARP;
1423
1424   BAD_SW_IF_INDEX_LABEL;
1425
1426 out:
1427   REPLY_MACRO (VL_API_PROXY_ARP_INTFC_ENABLE_DISABLE_REPLY);
1428 }
1429
1430 static void
1431 vl_api_is_address_reachable_t_handler (vl_api_is_address_reachable_t * mp)
1432 {
1433 #if 0
1434   vpe_main_t *rm = &vpe_main;
1435   ip4_main_t *im4 = &ip4_main;
1436   ip6_main_t *im6 = &ip6_main;
1437   ip_lookup_main_t *lm;
1438   union
1439   {
1440     ip4_address_t ip4;
1441     ip6_address_t ip6;
1442   } addr;
1443   u32 adj_index, sw_if_index;
1444   vl_api_is_address_reachable_t *rmp;
1445   ip_adjacency_t *adj;
1446   unix_shared_memory_queue_t *q;
1447
1448   q = vl_api_client_index_to_input_queue (mp->client_index);
1449   if (!q)
1450     {
1451       increment_missing_api_client_counter (rm->vlib_main);
1452       return;
1453     }
1454
1455   rmp = vl_msg_api_alloc (sizeof (*rmp));
1456   clib_memcpy (rmp, mp, sizeof (*rmp));
1457
1458   sw_if_index = mp->next_hop_sw_if_index;
1459   clib_memcpy (&addr, mp->address, sizeof (addr));
1460   if (mp->is_ipv6)
1461     {
1462       lm = &im6->lookup_main;
1463       adj_index = ip6_fib_lookup (im6, sw_if_index, &addr.ip6);
1464     }
1465   else
1466     {
1467       lm = &im4->lookup_main;
1468       // FIXME NOT an ADJ
1469       adj_index = ip4_fib_lookup (im4, sw_if_index, &addr.ip4);
1470     }
1471   if (adj_index == ~0)
1472     {
1473       rmp->is_error = 1;
1474       goto send;
1475     }
1476   adj = ip_get_adjacency (lm, adj_index);
1477
1478   if (adj->lookup_next_index == IP_LOOKUP_NEXT_REWRITE
1479       && adj->rewrite_header.sw_if_index == sw_if_index)
1480     {
1481       rmp->is_known = 1;
1482     }
1483   else
1484     {
1485       if (adj->lookup_next_index == IP_LOOKUP_NEXT_ARP
1486           && adj->rewrite_header.sw_if_index == sw_if_index)
1487         {
1488           if (mp->is_ipv6)
1489             ip6_probe_neighbor (rm->vlib_main, &addr.ip6, sw_if_index);
1490           else
1491             ip4_probe_neighbor (rm->vlib_main, &addr.ip4, sw_if_index);
1492         }
1493       else if (adj->lookup_next_index == IP_LOOKUP_NEXT_DROP)
1494         {
1495           rmp->is_known = 1;
1496           goto send;
1497         }
1498       rmp->is_known = 0;
1499     }
1500
1501 send:
1502   vl_msg_api_send_shmem (q, (u8 *) & rmp);
1503 #endif
1504 }
1505
1506 static void
1507   vl_api_sw_interface_set_mpls_enable_t_handler
1508   (vl_api_sw_interface_set_mpls_enable_t * mp)
1509 {
1510   vl_api_sw_interface_set_mpls_enable_reply_t *rmp;
1511   int rv = 0;
1512
1513   VALIDATE_SW_IF_INDEX (mp);
1514
1515   mpls_sw_interface_enable_disable (&mpls_main,
1516                                     ntohl (mp->sw_if_index), mp->enable);
1517
1518   BAD_SW_IF_INDEX_LABEL;
1519   REPLY_MACRO (VL_API_SW_INTERFACE_SET_MPLS_ENABLE_REPLY);
1520 }
1521
1522 void
1523 send_oam_event (oam_target_t * t)
1524 {
1525   vpe_api_main_t *vam = &vpe_api_main;
1526   unix_shared_memory_queue_t *q;
1527   vpe_client_registration_t *reg;
1528   vl_api_oam_event_t *mp;
1529
1530   /* *INDENT-OFF* */
1531   pool_foreach(reg, vam->oam_events_registrations,
1532   ({
1533     q = vl_api_client_index_to_input_queue (reg->client_index);
1534     if (q)
1535       {
1536         mp = vl_msg_api_alloc (sizeof (*mp));
1537         mp->_vl_msg_id = ntohs (VL_API_OAM_EVENT);
1538         clib_memcpy (mp->dst_address, &t->dst_address,
1539                      sizeof (mp->dst_address));
1540         mp->state = t->state;
1541         vl_msg_api_send_shmem (q, (u8 *)&mp);
1542       }
1543   }));
1544   /* *INDENT-ON* */
1545 }
1546
1547 static void
1548 vl_api_oam_add_del_t_handler (vl_api_oam_add_del_t * mp)
1549 {
1550   vl_api_oam_add_del_reply_t *rmp;
1551   int rv;
1552
1553   rv = vpe_oam_add_del_target ((ip4_address_t *) mp->src_address,
1554                                (ip4_address_t *) mp->dst_address,
1555                                ntohl (mp->vrf_id), (int) (mp->is_add));
1556
1557   REPLY_MACRO (VL_API_OAM_ADD_DEL_REPLY);
1558 }
1559
1560 static void
1561 vl_api_vnet_get_summary_stats_t_handler (vl_api_vnet_get_summary_stats_t * mp)
1562 {
1563   stats_main_t *sm = &stats_main;
1564   vnet_interface_main_t *im = sm->interface_main;
1565   vl_api_vnet_summary_stats_reply_t *rmp;
1566   vlib_combined_counter_main_t *cm;
1567   vlib_counter_t v;
1568   int i, which;
1569   u64 total_pkts[VLIB_N_RX_TX];
1570   u64 total_bytes[VLIB_N_RX_TX];
1571
1572   unix_shared_memory_queue_t *q =
1573     vl_api_client_index_to_input_queue (mp->client_index);
1574
1575   if (!q)
1576     return;
1577
1578   rmp = vl_msg_api_alloc (sizeof (*rmp));
1579   rmp->_vl_msg_id = ntohs (VL_API_VNET_SUMMARY_STATS_REPLY);
1580   rmp->context = mp->context;
1581   rmp->retval = 0;
1582
1583   memset (total_pkts, 0, sizeof (total_pkts));
1584   memset (total_bytes, 0, sizeof (total_bytes));
1585
1586   vnet_interface_counter_lock (im);
1587
1588   vec_foreach (cm, im->combined_sw_if_counters)
1589   {
1590     which = cm - im->combined_sw_if_counters;
1591
1592     for (i = 0; i < vec_len (cm->maxi); i++)
1593       {
1594         vlib_get_combined_counter (cm, i, &v);
1595         total_pkts[which] += v.packets;
1596         total_bytes[which] += v.bytes;
1597       }
1598   }
1599   vnet_interface_counter_unlock (im);
1600
1601   rmp->total_pkts[VLIB_RX] = clib_host_to_net_u64 (total_pkts[VLIB_RX]);
1602   rmp->total_bytes[VLIB_RX] = clib_host_to_net_u64 (total_bytes[VLIB_RX]);
1603   rmp->total_pkts[VLIB_TX] = clib_host_to_net_u64 (total_pkts[VLIB_TX]);
1604   rmp->total_bytes[VLIB_TX] = clib_host_to_net_u64 (total_bytes[VLIB_TX]);
1605   rmp->vector_rate =
1606     clib_host_to_net_u64 (vlib_last_vector_length_per_node (sm->vlib_main));
1607
1608   vl_msg_api_send_shmem (q, (u8 *) & rmp);
1609 }
1610
1611 /* *INDENT-OFF* */
1612 typedef CLIB_PACKED (struct {
1613   ip4_address_t address;
1614   u32 address_length: 6;
1615   u32 index:26;
1616 }) ip4_route_t;
1617 /* *INDENT-ON* */
1618
1619 static int
1620 ip4_reset_fib_t_handler (vl_api_reset_fib_t * mp)
1621 {
1622   vnet_main_t *vnm = vnet_get_main ();
1623   vnet_interface_main_t *im = &vnm->interface_main;
1624   ip4_main_t *im4 = &ip4_main;
1625   static u32 *sw_if_indices_to_shut;
1626   stats_main_t *sm = &stats_main;
1627   fib_table_t *fib_table;
1628   ip4_fib_t *fib;
1629   u32 sw_if_index;
1630   int i;
1631   int rv = VNET_API_ERROR_NO_SUCH_FIB;
1632   u32 target_fib_id = ntohl (mp->vrf_id);
1633
1634   dslock (sm, 1 /* release hint */ , 8 /* tag */ );
1635
1636   /* *INDENT-OFF* */
1637   pool_foreach (fib_table, im4->fibs,
1638   ({
1639     fib = &fib_table->v4;
1640     vnet_sw_interface_t * si;
1641
1642     if (fib->table_id != target_fib_id)
1643       continue;
1644
1645     /* remove any mpls encap/decap labels */
1646     mpls_fib_reset_labels (fib->table_id);
1647
1648     /* remove any proxy arps in this fib */
1649     vnet_proxy_arp_fib_reset (fib->table_id);
1650
1651     /* Set the flow hash for this fib to the default */
1652     vnet_set_ip4_flow_hash (fib->table_id, IP_FLOW_HASH_DEFAULT);
1653
1654     vec_reset_length (sw_if_indices_to_shut);
1655
1656     /* Shut down interfaces in this FIB / clean out intfc routes */
1657     pool_foreach (si, im->sw_interfaces,
1658     ({
1659       u32 sw_if_index = si->sw_if_index;
1660
1661       if (sw_if_index < vec_len (im4->fib_index_by_sw_if_index)
1662           && (im4->fib_index_by_sw_if_index[si->sw_if_index] ==
1663               fib->index))
1664         vec_add1 (sw_if_indices_to_shut, si->sw_if_index);
1665     }));
1666
1667     for (i = 0; i < vec_len (sw_if_indices_to_shut); i++) {
1668       sw_if_index = sw_if_indices_to_shut[i];
1669       // vec_foreach (sw_if_index, sw_if_indices_to_shut) {
1670
1671       u32 flags = vnet_sw_interface_get_flags (vnm, sw_if_index);
1672       flags &= ~(VNET_SW_INTERFACE_FLAG_ADMIN_UP);
1673       vnet_sw_interface_set_flags (vnm, sw_if_index, flags);
1674     }
1675
1676     fib_table_flush(fib->index, FIB_PROTOCOL_IP4, FIB_SOURCE_API);
1677     fib_table_flush(fib->index, FIB_PROTOCOL_IP4, FIB_SOURCE_INTERFACE);
1678
1679     rv = 0;
1680     break;
1681     })); /* pool_foreach (fib) */
1682     /* *INDENT-ON* */
1683
1684   dsunlock (sm);
1685   return rv;
1686 }
1687
1688 static int
1689 ip6_reset_fib_t_handler (vl_api_reset_fib_t * mp)
1690 {
1691   vnet_main_t *vnm = vnet_get_main ();
1692   vnet_interface_main_t *im = &vnm->interface_main;
1693   ip6_main_t *im6 = &ip6_main;
1694   stats_main_t *sm = &stats_main;
1695   static u32 *sw_if_indices_to_shut;
1696   fib_table_t *fib_table;
1697   ip6_fib_t *fib;
1698   u32 sw_if_index;
1699   int i;
1700   int rv = VNET_API_ERROR_NO_SUCH_FIB;
1701   u32 target_fib_id = ntohl (mp->vrf_id);
1702
1703   dslock (sm, 1 /* release hint */ , 9 /* tag */ );
1704
1705   /* *INDENT-OFF* */
1706   pool_foreach (fib_table, im6->fibs,
1707   ({
1708     vnet_sw_interface_t * si;
1709     fib = &(fib_table->v6);
1710
1711     if (fib->table_id != target_fib_id)
1712       continue;
1713
1714     vec_reset_length (sw_if_indices_to_shut);
1715
1716     /* Shut down interfaces in this FIB / clean out intfc routes */
1717     pool_foreach (si, im->sw_interfaces,
1718                   ({
1719                     if (im6->fib_index_by_sw_if_index[si->sw_if_index] ==
1720                         fib->index)
1721                       vec_add1 (sw_if_indices_to_shut, si->sw_if_index);
1722                   }));
1723
1724     for (i = 0; i < vec_len (sw_if_indices_to_shut); i++) {
1725       sw_if_index = sw_if_indices_to_shut[i];
1726       // vec_foreach (sw_if_index, sw_if_indices_to_shut) {
1727
1728       u32 flags = vnet_sw_interface_get_flags (vnm, sw_if_index);
1729       flags &= ~(VNET_SW_INTERFACE_FLAG_ADMIN_UP);
1730       vnet_sw_interface_set_flags (vnm, sw_if_index, flags);
1731     }
1732
1733     fib_table_flush(fib->index, FIB_PROTOCOL_IP6, FIB_SOURCE_API);
1734     fib_table_flush(fib->index, FIB_PROTOCOL_IP6, FIB_SOURCE_INTERFACE);
1735
1736     rv = 0;
1737     break;
1738   })); /* pool_foreach (fib) */
1739   /* *INDENT-ON* */
1740
1741   dsunlock (sm);
1742   return rv;
1743 }
1744
1745 static void
1746 vl_api_reset_fib_t_handler (vl_api_reset_fib_t * mp)
1747 {
1748   int rv;
1749   vl_api_reset_fib_reply_t *rmp;
1750
1751   if (mp->is_ipv6)
1752     rv = ip6_reset_fib_t_handler (mp);
1753   else
1754     rv = ip4_reset_fib_t_handler (mp);
1755
1756   REPLY_MACRO (VL_API_RESET_FIB_REPLY);
1757 }
1758
1759
1760 static void
1761 dhcpv4_proxy_config (vl_api_dhcp_proxy_config_t * mp)
1762 {
1763   vl_api_dhcp_proxy_config_reply_t *rmp;
1764   int rv;
1765
1766   rv = dhcp_proxy_set_server ((ip4_address_t *) (&mp->dhcp_server),
1767                               (ip4_address_t *) (&mp->dhcp_src_address),
1768                               (u32) ntohl (mp->vrf_id),
1769                               (int) mp->insert_circuit_id,
1770                               (int) (mp->is_add == 0));
1771
1772   REPLY_MACRO (VL_API_DHCP_PROXY_CONFIG_REPLY);
1773 }
1774
1775
1776 static void
1777 dhcpv6_proxy_config (vl_api_dhcp_proxy_config_t * mp)
1778 {
1779   vl_api_dhcp_proxy_config_reply_t *rmp;
1780   int rv = -1;
1781
1782   rv = dhcpv6_proxy_set_server ((ip6_address_t *) (&mp->dhcp_server),
1783                                 (ip6_address_t *) (&mp->dhcp_src_address),
1784                                 (u32) ntohl (mp->vrf_id),
1785                                 (int) mp->insert_circuit_id,
1786                                 (int) (mp->is_add == 0));
1787
1788   REPLY_MACRO (VL_API_DHCP_PROXY_CONFIG_REPLY);
1789 }
1790
1791 static void
1792 dhcpv4_proxy_config_2 (vl_api_dhcp_proxy_config_2_t * mp)
1793 {
1794   vl_api_dhcp_proxy_config_reply_t *rmp;
1795   int rv;
1796
1797   rv = dhcp_proxy_set_server_2 ((ip4_address_t *) (&mp->dhcp_server),
1798                                 (ip4_address_t *) (&mp->dhcp_src_address),
1799                                 (u32) ntohl (mp->rx_vrf_id),
1800                                 (u32) ntohl (mp->server_vrf_id),
1801                                 (int) mp->insert_circuit_id,
1802                                 (int) (mp->is_add == 0));
1803
1804   REPLY_MACRO (VL_API_DHCP_PROXY_CONFIG_2_REPLY);
1805 }
1806
1807
1808 static void
1809 dhcpv6_proxy_config_2 (vl_api_dhcp_proxy_config_2_t * mp)
1810 {
1811   vl_api_dhcp_proxy_config_reply_t *rmp;
1812   int rv = -1;
1813
1814   rv = dhcpv6_proxy_set_server_2 ((ip6_address_t *) (&mp->dhcp_server),
1815                                   (ip6_address_t *) (&mp->dhcp_src_address),
1816                                   (u32) ntohl (mp->rx_vrf_id),
1817                                   (u32) ntohl (mp->server_vrf_id),
1818                                   (int) mp->insert_circuit_id,
1819                                   (int) (mp->is_add == 0));
1820
1821   REPLY_MACRO (VL_API_DHCP_PROXY_CONFIG_2_REPLY);
1822 }
1823
1824
1825 static void
1826 vl_api_dhcp_proxy_set_vss_t_handler (vl_api_dhcp_proxy_set_vss_t * mp)
1827 {
1828   vl_api_dhcp_proxy_set_vss_reply_t *rmp;
1829   int rv;
1830   if (!mp->is_ipv6)
1831     rv = dhcp_proxy_set_option82_vss (ntohl (mp->tbl_id),
1832                                       ntohl (mp->oui),
1833                                       ntohl (mp->fib_id),
1834                                       (int) mp->is_add == 0);
1835   else
1836     rv = dhcpv6_proxy_set_vss (ntohl (mp->tbl_id),
1837                                ntohl (mp->oui),
1838                                ntohl (mp->fib_id), (int) mp->is_add == 0);
1839
1840   REPLY_MACRO (VL_API_DHCP_PROXY_SET_VSS_REPLY);
1841 }
1842
1843
1844 static void vl_api_dhcp_proxy_config_t_handler
1845   (vl_api_dhcp_proxy_config_t * mp)
1846 {
1847   if (mp->is_ipv6 == 0)
1848     dhcpv4_proxy_config (mp);
1849   else
1850     dhcpv6_proxy_config (mp);
1851 }
1852
1853 static void vl_api_dhcp_proxy_config_2_t_handler
1854   (vl_api_dhcp_proxy_config_2_t * mp)
1855 {
1856   if (mp->is_ipv6 == 0)
1857     dhcpv4_proxy_config_2 (mp);
1858   else
1859     dhcpv6_proxy_config_2 (mp);
1860 }
1861
1862 void
1863 dhcp_compl_event_callback (u32 client_index, u32 pid, u8 * hostname,
1864                            u8 is_ipv6, u8 * host_address, u8 * router_address,
1865                            u8 * host_mac)
1866 {
1867   unix_shared_memory_queue_t *q;
1868   vl_api_dhcp_compl_event_t *mp;
1869
1870   q = vl_api_client_index_to_input_queue (client_index);
1871   if (!q)
1872     return;
1873
1874   mp = vl_msg_api_alloc (sizeof (*mp));
1875   mp->client_index = client_index;
1876   mp->pid = pid;
1877   mp->is_ipv6 = is_ipv6;
1878   clib_memcpy (&mp->hostname, hostname, vec_len (hostname));
1879   mp->hostname[vec_len (hostname) + 1] = '\n';
1880   clib_memcpy (&mp->host_address[0], host_address, 16);
1881   clib_memcpy (&mp->router_address[0], router_address, 16);
1882
1883   if (NULL != host_mac)
1884     clib_memcpy (&mp->host_mac[0], host_mac, 6);
1885
1886   mp->_vl_msg_id = ntohs (VL_API_DHCP_COMPL_EVENT);
1887
1888   vl_msg_api_send_shmem (q, (u8 *) & mp);
1889 }
1890
1891 static void vl_api_dhcp_client_config_t_handler
1892   (vl_api_dhcp_client_config_t * mp)
1893 {
1894   vlib_main_t *vm = vlib_get_main ();
1895   vl_api_dhcp_client_config_reply_t *rmp;
1896   int rv = 0;
1897
1898   VALIDATE_SW_IF_INDEX (mp);
1899
1900   rv = dhcp_client_config (vm, ntohl (mp->sw_if_index),
1901                            mp->hostname, mp->is_add, mp->client_index,
1902                            mp->want_dhcp_event ? dhcp_compl_event_callback :
1903                            NULL, mp->pid);
1904
1905   BAD_SW_IF_INDEX_LABEL;
1906
1907   REPLY_MACRO (VL_API_DHCP_CLIENT_CONFIG_REPLY);
1908 }
1909
1910 static void
1911 vl_api_create_loopback_t_handler (vl_api_create_loopback_t * mp)
1912 {
1913   vl_api_create_loopback_reply_t *rmp;
1914   u32 sw_if_index;
1915   int rv;
1916
1917   rv = vnet_create_loopback_interface (&sw_if_index, mp->mac_address);
1918
1919   /* *INDENT-OFF* */
1920   REPLY_MACRO2(VL_API_CREATE_LOOPBACK_REPLY,
1921   ({
1922     rmp->sw_if_index = ntohl (sw_if_index);
1923   }));
1924   /* *INDENT-ON* */
1925 }
1926
1927 static void
1928 vl_api_delete_loopback_t_handler (vl_api_delete_loopback_t * mp)
1929 {
1930   vl_api_delete_loopback_reply_t *rmp;
1931   u32 sw_if_index;
1932   int rv;
1933
1934   sw_if_index = ntohl (mp->sw_if_index);
1935   rv = vnet_delete_loopback_interface (sw_if_index);
1936
1937   REPLY_MACRO (VL_API_DELETE_LOOPBACK_REPLY);
1938 }
1939
1940 static void
1941 vl_api_control_ping_t_handler (vl_api_control_ping_t * mp)
1942 {
1943   vl_api_control_ping_reply_t *rmp;
1944   int rv = 0;
1945
1946   /* *INDENT-OFF* */
1947   REPLY_MACRO2(VL_API_CONTROL_PING_REPLY,
1948   ({
1949     rmp->vpe_pid = ntohl (getpid());
1950   }));
1951   /* *INDENT-ON* */
1952 }
1953
1954 static void
1955 shmem_cli_output (uword arg, u8 * buffer, uword buffer_bytes)
1956 {
1957   u8 **shmem_vecp = (u8 **) arg;
1958   u8 *shmem_vec;
1959   void *oldheap;
1960   api_main_t *am = &api_main;
1961   u32 offset;
1962
1963   shmem_vec = *shmem_vecp;
1964
1965   offset = vec_len (shmem_vec);
1966
1967   pthread_mutex_lock (&am->vlib_rp->mutex);
1968   oldheap = svm_push_data_heap (am->vlib_rp);
1969
1970   vec_validate (shmem_vec, offset + buffer_bytes - 1);
1971
1972   clib_memcpy (shmem_vec + offset, buffer, buffer_bytes);
1973
1974   svm_pop_heap (oldheap);
1975   pthread_mutex_unlock (&am->vlib_rp->mutex);
1976
1977   *shmem_vecp = shmem_vec;
1978 }
1979
1980
1981 static void
1982 vl_api_cli_request_t_handler (vl_api_cli_request_t * mp)
1983 {
1984   vl_api_cli_reply_t *rp;
1985   unix_shared_memory_queue_t *q;
1986   vlib_main_t *vm = vlib_get_main ();
1987   api_main_t *am = &api_main;
1988   unformat_input_t input;
1989   u8 *shmem_vec = 0;
1990   void *oldheap;
1991
1992   q = vl_api_client_index_to_input_queue (mp->client_index);
1993   if (!q)
1994     return;
1995
1996   rp = vl_msg_api_alloc (sizeof (*rp));
1997   rp->_vl_msg_id = ntohs (VL_API_CLI_REPLY);
1998   rp->context = mp->context;
1999
2000   unformat_init_vector (&input, (u8 *) (uword) mp->cmd_in_shmem);
2001
2002   vlib_cli_input (vm, &input, shmem_cli_output, (uword) & shmem_vec);
2003
2004   pthread_mutex_lock (&am->vlib_rp->mutex);
2005   oldheap = svm_push_data_heap (am->vlib_rp);
2006
2007   vec_add1 (shmem_vec, 0);
2008
2009   svm_pop_heap (oldheap);
2010   pthread_mutex_unlock (&am->vlib_rp->mutex);
2011
2012   rp->reply_in_shmem = (uword) shmem_vec;
2013
2014   vl_msg_api_send_shmem (q, (u8 *) & rp);
2015 }
2016
2017 static void
2018 inband_cli_output (uword arg, u8 * buffer, uword buffer_bytes)
2019 {
2020   u8 **mem_vecp = (u8 **) arg;
2021   u8 *mem_vec = *mem_vecp;
2022   u32 offset = vec_len (mem_vec);
2023
2024   vec_validate (mem_vec, offset + buffer_bytes - 1);
2025   clib_memcpy (mem_vec + offset, buffer, buffer_bytes);
2026   *mem_vecp = mem_vec;
2027 }
2028
2029 static void
2030 vl_api_cli_inband_t_handler (vl_api_cli_inband_t * mp)
2031 {
2032   vl_api_cli_inband_reply_t *rmp;
2033   int rv = 0;
2034   unix_shared_memory_queue_t *q;
2035   vlib_main_t *vm = vlib_get_main ();
2036   unformat_input_t input;
2037   u8 *out_vec = 0;
2038
2039   q = vl_api_client_index_to_input_queue (mp->client_index);
2040   if (!q)
2041     return;
2042
2043   unformat_init_string (&input, (char *) mp->cmd, ntohl (mp->length));
2044   vlib_cli_input (vm, &input, inband_cli_output, (uword) & out_vec);
2045
2046   u32 len = vec_len (out_vec);
2047   /* *INDENT-OFF* */
2048   REPLY_MACRO3(VL_API_CLI_INBAND_REPLY, len,
2049   ({
2050     rmp->length = htonl (len);
2051     clib_memcpy (rmp->reply, out_vec, len);
2052   }));
2053   /* *INDENT-ON* */
2054   vec_free (out_vec);
2055 }
2056
2057 static void
2058 vl_api_set_arp_neighbor_limit_t_handler (vl_api_set_arp_neighbor_limit_t * mp)
2059 {
2060   int rv;
2061   vl_api_set_arp_neighbor_limit_reply_t *rmp;
2062   vnet_main_t *vnm = vnet_get_main ();
2063   clib_error_t *error;
2064
2065   vnm->api_errno = 0;
2066
2067   if (mp->is_ipv6)
2068     error = ip6_set_neighbor_limit (ntohl (mp->arp_neighbor_limit));
2069   else
2070     error = ip4_set_arp_limit (ntohl (mp->arp_neighbor_limit));
2071
2072   if (error)
2073     {
2074       clib_error_report (error);
2075       rv = VNET_API_ERROR_UNSPECIFIED;
2076     }
2077   else
2078     {
2079       rv = vnm->api_errno;
2080     }
2081
2082   REPLY_MACRO (VL_API_SET_ARP_NEIGHBOR_LIMIT_REPLY);
2083 }
2084
2085 static void vl_api_sr_tunnel_add_del_t_handler
2086   (vl_api_sr_tunnel_add_del_t * mp)
2087 {
2088 #if IP6SR == 0
2089   clib_warning ("unimplemented");
2090 #else
2091   ip6_sr_add_del_tunnel_args_t _a, *a = &_a;
2092   int rv = 0;
2093   vl_api_sr_tunnel_add_del_reply_t *rmp;
2094   ip6_address_t *segments = 0, *seg;
2095   ip6_address_t *tags = 0, *tag;
2096   ip6_address_t *this_address;
2097   int i;
2098
2099   if (mp->n_segments == 0)
2100     {
2101       rv = -11;
2102       goto out;
2103     }
2104
2105   memset (a, 0, sizeof (*a));
2106   a->src_address = (ip6_address_t *) & mp->src_address;
2107   a->dst_address = (ip6_address_t *) & mp->dst_address;
2108   a->dst_mask_width = mp->dst_mask_width;
2109   a->flags_net_byte_order = mp->flags_net_byte_order;
2110   a->is_del = (mp->is_add == 0);
2111   a->rx_table_id = ntohl (mp->outer_vrf_id);
2112   a->tx_table_id = ntohl (mp->inner_vrf_id);
2113
2114   a->name = format (0, "%s", mp->name);
2115   if (!(vec_len (a->name)))
2116     a->name = 0;
2117
2118   a->policy_name = format (0, "%s", mp->policy_name);
2119   if (!(vec_len (a->policy_name)))
2120     a->policy_name = 0;
2121
2122   /* Yank segments and tags out of the API message */
2123   this_address = (ip6_address_t *) mp->segs_and_tags;
2124   for (i = 0; i < mp->n_segments; i++)
2125     {
2126       vec_add2 (segments, seg, 1);
2127       clib_memcpy (seg->as_u8, this_address->as_u8, sizeof (*this_address));
2128       this_address++;
2129     }
2130   for (i = 0; i < mp->n_tags; i++)
2131     {
2132       vec_add2 (tags, tag, 1);
2133       clib_memcpy (tag->as_u8, this_address->as_u8, sizeof (*this_address));
2134       this_address++;
2135     }
2136
2137   a->segments = segments;
2138   a->tags = tags;
2139
2140   rv = ip6_sr_add_del_tunnel (a);
2141
2142 out:
2143
2144   REPLY_MACRO (VL_API_SR_TUNNEL_ADD_DEL_REPLY);
2145 #endif
2146 }
2147
2148 static void vl_api_sr_policy_add_del_t_handler
2149   (vl_api_sr_policy_add_del_t * mp)
2150 {
2151 #if IP6SR == 0
2152   clib_warning ("unimplemented");
2153 #else
2154   ip6_sr_add_del_policy_args_t _a, *a = &_a;
2155   int rv = 0;
2156   vl_api_sr_policy_add_del_reply_t *rmp;
2157   int i;
2158
2159   memset (a, 0, sizeof (*a));
2160   a->is_del = (mp->is_add == 0);
2161
2162   a->name = format (0, "%s", mp->name);
2163   if (!(vec_len (a->name)))
2164     {
2165       rv = VNET_API_ERROR_NO_SUCH_NODE2;
2166       goto out;
2167     }
2168
2169   if (!(mp->tunnel_names[0]))
2170     {
2171       rv = VNET_API_ERROR_NO_SUCH_NODE2;
2172       goto out;
2173     }
2174
2175   // start deserializing tunnel_names
2176   int num_tunnels = mp->tunnel_names[0];        //number of tunnels
2177   u8 *deser_tun_names = mp->tunnel_names;
2178   deser_tun_names += 1;         //moving along
2179
2180   u8 *tun_name = 0;
2181   int tun_name_len = 0;
2182
2183   for (i = 0; i < num_tunnels; i++)
2184     {
2185       tun_name_len = *deser_tun_names;
2186       deser_tun_names += 1;
2187       vec_resize (tun_name, tun_name_len);
2188       memcpy (tun_name, deser_tun_names, tun_name_len);
2189       vec_add1 (a->tunnel_names, tun_name);
2190       deser_tun_names += tun_name_len;
2191       tun_name = 0;
2192     }
2193
2194   rv = ip6_sr_add_del_policy (a);
2195
2196 out:
2197
2198   REPLY_MACRO (VL_API_SR_POLICY_ADD_DEL_REPLY);
2199 #endif
2200 }
2201
2202 static void vl_api_sr_multicast_map_add_del_t_handler
2203   (vl_api_sr_multicast_map_add_del_t * mp)
2204 {
2205 #if IP6SR == 0
2206   clib_warning ("unimplemented");
2207 #else
2208   ip6_sr_add_del_multicastmap_args_t _a, *a = &_a;
2209   int rv = 0;
2210   vl_api_sr_multicast_map_add_del_reply_t *rmp;
2211
2212   memset (a, 0, sizeof (*a));
2213   a->is_del = (mp->is_add == 0);
2214
2215   a->multicast_address = (ip6_address_t *) & mp->multicast_address;
2216   a->policy_name = format (0, "%s", mp->policy_name);
2217
2218   if (a->multicast_address == 0)
2219     {
2220       rv = -1;
2221       goto out;
2222     }
2223
2224   if (!(a->policy_name))
2225     {
2226       rv = -2;
2227       goto out;
2228     }
2229
2230 #if DPDK > 0                    /* Cannot call replicate without DPDK */
2231   rv = ip6_sr_add_del_multicastmap (a);
2232 #else
2233   clib_warning ("multicast replication without DPDK not implemented");
2234   rv = VNET_API_ERROR_UNIMPLEMENTED;
2235 #endif /* DPDK */
2236
2237 out:
2238
2239   REPLY_MACRO (VL_API_SR_MULTICAST_MAP_ADD_DEL_REPLY);
2240 #endif
2241 }
2242
2243 #define foreach_classify_add_del_table_field    \
2244 _(table_index)                                  \
2245 _(nbuckets)                                     \
2246 _(memory_size)                                  \
2247 _(skip_n_vectors)                               \
2248 _(match_n_vectors)                              \
2249 _(next_table_index)                             \
2250 _(miss_next_index)                              \
2251 _(current_data_flag)                            \
2252 _(current_data_offset)
2253
2254 static void vl_api_classify_add_del_table_t_handler
2255   (vl_api_classify_add_del_table_t * mp)
2256 {
2257   vl_api_classify_add_del_table_reply_t *rmp;
2258   vnet_classify_main_t *cm = &vnet_classify_main;
2259   vnet_classify_table_t *t;
2260   int rv;
2261
2262 #define _(a) u32 a;
2263   foreach_classify_add_del_table_field;
2264 #undef _
2265
2266 #define _(a) a = ntohl(mp->a);
2267   foreach_classify_add_del_table_field;
2268 #undef _
2269
2270   /* The underlying API fails silently, on purpose, so check here */
2271   if (mp->is_add == 0)          /* delete */
2272     {
2273       if (pool_is_free_index (cm->tables, table_index))
2274         {
2275           rv = VNET_API_ERROR_NO_SUCH_TABLE;
2276           goto out;
2277         }
2278     }
2279   else                          /* add or update */
2280     {
2281       if (table_index != ~0 && pool_is_free_index (cm->tables, table_index))
2282         table_index = ~0;
2283     }
2284
2285   rv = vnet_classify_add_del_table
2286     (cm, mp->mask, nbuckets, memory_size,
2287      skip_n_vectors, match_n_vectors,
2288      next_table_index, miss_next_index, &table_index,
2289      current_data_flag, current_data_offset, mp->is_add, mp->del_chain);
2290
2291 out:
2292   /* *INDENT-OFF* */
2293   REPLY_MACRO2(VL_API_CLASSIFY_ADD_DEL_TABLE_REPLY,
2294   ({
2295     if (rv == 0 && mp->is_add)
2296       {
2297         t = pool_elt_at_index (cm->tables, table_index);
2298         rmp->skip_n_vectors = ntohl(t->skip_n_vectors);
2299         rmp->match_n_vectors = ntohl(t->match_n_vectors);
2300         rmp->new_table_index = ntohl(table_index);
2301       }
2302     else
2303       {
2304         rmp->skip_n_vectors = ~0;
2305         rmp->match_n_vectors = ~0;
2306         rmp->new_table_index = ~0;
2307       }
2308   }));
2309   /* *INDENT-ON* */
2310 }
2311
2312 static void vl_api_classify_add_del_session_t_handler
2313   (vl_api_classify_add_del_session_t * mp)
2314 {
2315   vnet_classify_main_t *cm = &vnet_classify_main;
2316   vl_api_classify_add_del_session_reply_t *rmp;
2317   int rv;
2318   u32 table_index, hit_next_index, opaque_index, metadata;
2319   i32 advance;
2320   u8 action;
2321
2322   table_index = ntohl (mp->table_index);
2323   hit_next_index = ntohl (mp->hit_next_index);
2324   opaque_index = ntohl (mp->opaque_index);
2325   advance = ntohl (mp->advance);
2326   action = mp->action;
2327   metadata = ntohl (mp->metadata);
2328
2329   rv = vnet_classify_add_del_session
2330     (cm, table_index, mp->match, hit_next_index, opaque_index,
2331      advance, action, metadata, mp->is_add);
2332
2333   REPLY_MACRO (VL_API_CLASSIFY_ADD_DEL_SESSION_REPLY);
2334 }
2335
2336 static void vl_api_classify_set_interface_ip_table_t_handler
2337   (vl_api_classify_set_interface_ip_table_t * mp)
2338 {
2339   vlib_main_t *vm = vlib_get_main ();
2340   vl_api_classify_set_interface_ip_table_reply_t *rmp;
2341   int rv;
2342   u32 table_index, sw_if_index;
2343
2344   table_index = ntohl (mp->table_index);
2345   sw_if_index = ntohl (mp->sw_if_index);
2346
2347   VALIDATE_SW_IF_INDEX (mp);
2348
2349   if (mp->is_ipv6)
2350     rv = vnet_set_ip6_classify_intfc (vm, sw_if_index, table_index);
2351   else
2352     rv = vnet_set_ip4_classify_intfc (vm, sw_if_index, table_index);
2353
2354   BAD_SW_IF_INDEX_LABEL;
2355
2356   REPLY_MACRO (VL_API_CLASSIFY_SET_INTERFACE_IP_TABLE_REPLY);
2357 }
2358
2359 static void vl_api_classify_set_interface_l2_tables_t_handler
2360   (vl_api_classify_set_interface_l2_tables_t * mp)
2361 {
2362   vl_api_classify_set_interface_l2_tables_reply_t *rmp;
2363   int rv;
2364   u32 sw_if_index, ip4_table_index, ip6_table_index, other_table_index;
2365   int enable;
2366
2367   ip4_table_index = ntohl (mp->ip4_table_index);
2368   ip6_table_index = ntohl (mp->ip6_table_index);
2369   other_table_index = ntohl (mp->other_table_index);
2370   sw_if_index = ntohl (mp->sw_if_index);
2371
2372   VALIDATE_SW_IF_INDEX (mp);
2373
2374   if (mp->is_input)
2375     rv = vnet_l2_input_classify_set_tables (sw_if_index, ip4_table_index,
2376                                             ip6_table_index,
2377                                             other_table_index);
2378   else
2379     rv = vnet_l2_output_classify_set_tables (sw_if_index, ip4_table_index,
2380                                              ip6_table_index,
2381                                              other_table_index);
2382
2383   if (rv == 0)
2384     {
2385       if (ip4_table_index != ~0 || ip6_table_index != ~0
2386           || other_table_index != ~0)
2387         enable = 1;
2388       else
2389         enable = 0;
2390
2391       if (mp->is_input)
2392         vnet_l2_input_classify_enable_disable (sw_if_index, enable);
2393       else
2394         vnet_l2_output_classify_enable_disable (sw_if_index, enable);
2395     }
2396
2397   BAD_SW_IF_INDEX_LABEL;
2398
2399   REPLY_MACRO (VL_API_CLASSIFY_SET_INTERFACE_L2_TABLES_REPLY);
2400 }
2401
2402 static void
2403 vl_api_l2_fib_clear_table_t_handler (vl_api_l2_fib_clear_table_t * mp)
2404 {
2405   int rv = 0;
2406   vl_api_l2_fib_clear_table_reply_t *rmp;
2407
2408   /* DAW-FIXME: This API should only clear non-static l2fib entries, but
2409    *            that is not currently implemented.  When that TODO is fixed
2410    *            this call should be changed to pass 1 instead of 0.
2411    */
2412   l2fib_clear_table (0);
2413
2414   REPLY_MACRO (VL_API_L2_FIB_CLEAR_TABLE_REPLY);
2415 }
2416
2417 extern void l2_efp_filter_configure (vnet_main_t * vnet_main,
2418                                      u32 sw_if_index, u32 enable);
2419
2420 static void
2421 vl_api_l2_interface_efp_filter_t_handler (vl_api_l2_interface_efp_filter_t *
2422                                           mp)
2423 {
2424   int rv;
2425   vl_api_l2_interface_efp_filter_reply_t *rmp;
2426   vnet_main_t *vnm = vnet_get_main ();
2427
2428   // enable/disable the feature
2429   l2_efp_filter_configure (vnm, mp->sw_if_index, mp->enable_disable);
2430   rv = vnm->api_errno;
2431
2432   REPLY_MACRO (VL_API_L2_INTERFACE_EFP_FILTER_REPLY);
2433 }
2434
2435 static void
2436   vl_api_l2_interface_vlan_tag_rewrite_t_handler
2437   (vl_api_l2_interface_vlan_tag_rewrite_t * mp)
2438 {
2439   int rv = 0;
2440   vl_api_l2_interface_vlan_tag_rewrite_reply_t *rmp;
2441   vnet_main_t *vnm = vnet_get_main ();
2442   vlib_main_t *vm = vlib_get_main ();
2443   u32 vtr_op;
2444
2445   VALIDATE_SW_IF_INDEX (mp);
2446
2447   vtr_op = ntohl (mp->vtr_op);
2448
2449   /* The L2 code is unsuspicious */
2450   switch (vtr_op)
2451     {
2452     case L2_VTR_DISABLED:
2453     case L2_VTR_PUSH_1:
2454     case L2_VTR_PUSH_2:
2455     case L2_VTR_POP_1:
2456     case L2_VTR_POP_2:
2457     case L2_VTR_TRANSLATE_1_1:
2458     case L2_VTR_TRANSLATE_1_2:
2459     case L2_VTR_TRANSLATE_2_1:
2460     case L2_VTR_TRANSLATE_2_2:
2461       break;
2462
2463     default:
2464       rv = VNET_API_ERROR_INVALID_VALUE;
2465       goto bad_sw_if_index;
2466     }
2467
2468   rv = l2vtr_configure (vm, vnm, ntohl (mp->sw_if_index), vtr_op,
2469                         ntohl (mp->push_dot1q), ntohl (mp->tag1),
2470                         ntohl (mp->tag2));
2471
2472   BAD_SW_IF_INDEX_LABEL;
2473
2474   REPLY_MACRO (VL_API_L2_INTERFACE_VLAN_TAG_REWRITE_REPLY);
2475 }
2476
2477 static void
2478 vl_api_l2_fib_table_entry_t_handler (vl_api_l2_fib_table_entry_t * mp)
2479 {
2480   clib_warning ("BUG");
2481 }
2482
2483 static void
2484 send_l2fib_table_entry (vpe_api_main_t * am,
2485                         unix_shared_memory_queue_t * q,
2486                         l2fib_entry_key_t * l2fe_key,
2487                         l2fib_entry_result_t * l2fe_res, u32 context)
2488 {
2489   vl_api_l2_fib_table_entry_t *mp;
2490
2491   mp = vl_msg_api_alloc (sizeof (*mp));
2492   memset (mp, 0, sizeof (*mp));
2493   mp->_vl_msg_id = ntohs (VL_API_L2_FIB_TABLE_ENTRY);
2494
2495   mp->bd_id =
2496     ntohl (l2input_main.bd_configs[l2fe_key->fields.bd_index].bd_id);
2497
2498   mp->mac = l2fib_make_key (l2fe_key->fields.mac, 0);
2499   mp->sw_if_index = ntohl (l2fe_res->fields.sw_if_index);
2500   mp->static_mac = l2fe_res->fields.static_mac;
2501   mp->filter_mac = l2fe_res->fields.filter;
2502   mp->bvi_mac = l2fe_res->fields.bvi;
2503   mp->context = context;
2504
2505   vl_msg_api_send_shmem (q, (u8 *) & mp);
2506 }
2507
2508 static void
2509 vl_api_l2_fib_table_dump_t_handler (vl_api_l2_fib_table_dump_t * mp)
2510 {
2511   vpe_api_main_t *am = &vpe_api_main;
2512   bd_main_t *bdm = &bd_main;
2513   l2fib_entry_key_t *l2fe_key = NULL;
2514   l2fib_entry_result_t *l2fe_res = NULL;
2515   u32 ni, bd_id = ntohl (mp->bd_id);
2516   u32 bd_index;
2517   unix_shared_memory_queue_t *q;
2518   uword *p;
2519
2520   q = vl_api_client_index_to_input_queue (mp->client_index);
2521   if (q == 0)
2522     return;
2523
2524   /* see l2fib_table_dump: ~0 means "any" */
2525   if (bd_id == ~0)
2526     bd_index = ~0;
2527   else
2528     {
2529       p = hash_get (bdm->bd_index_by_bd_id, bd_id);
2530       if (p == 0)
2531         return;
2532
2533       bd_index = p[0];
2534     }
2535
2536   l2fib_table_dump (bd_index, &l2fe_key, &l2fe_res);
2537
2538   vec_foreach_index (ni, l2fe_key)
2539   {
2540     send_l2fib_table_entry (am, q, vec_elt_at_index (l2fe_key, ni),
2541                             vec_elt_at_index (l2fe_res, ni), mp->context);
2542   }
2543   vec_free (l2fe_key);
2544   vec_free (l2fe_res);
2545 }
2546
2547 static void
2548 vl_api_show_version_t_handler (vl_api_show_version_t * mp)
2549 {
2550   vl_api_show_version_reply_t *rmp;
2551   int rv = 0;
2552   char *vpe_api_get_build_directory (void);
2553   char *vpe_api_get_version (void);
2554   char *vpe_api_get_build_date (void);
2555
2556   unix_shared_memory_queue_t *q =
2557     vl_api_client_index_to_input_queue (mp->client_index);
2558
2559   if (!q)
2560     return;
2561
2562   /* *INDENT-OFF* */
2563   REPLY_MACRO2(VL_API_SHOW_VERSION_REPLY,
2564   ({
2565     strncpy ((char *) rmp->program, "vpe", ARRAY_LEN(rmp->program)-1);
2566     strncpy ((char *) rmp->build_directory, vpe_api_get_build_directory(),
2567              ARRAY_LEN(rmp->build_directory)-1);
2568     strncpy ((char *) rmp->version, vpe_api_get_version(),
2569              ARRAY_LEN(rmp->version)-1);
2570     strncpy ((char *) rmp->build_date, vpe_api_get_build_date(),
2571              ARRAY_LEN(rmp->build_date)-1);
2572   }));
2573   /* *INDENT-ON* */
2574 }
2575
2576 static void
2577 vl_api_get_node_index_t_handler (vl_api_get_node_index_t * mp)
2578 {
2579   vlib_main_t *vm = vlib_get_main ();
2580   vl_api_get_node_index_reply_t *rmp;
2581   vlib_node_t *n;
2582   int rv = 0;
2583   u32 node_index = ~0;
2584
2585   n = vlib_get_node_by_name (vm, mp->node_name);
2586
2587   if (n == 0)
2588     rv = VNET_API_ERROR_NO_SUCH_NODE;
2589   else
2590     node_index = n->index;
2591
2592   /* *INDENT-OFF* */
2593   REPLY_MACRO2(VL_API_GET_NODE_INDEX_REPLY,
2594   ({
2595     rmp->node_index = ntohl(node_index);
2596   }));
2597   /* *INDENT-ON* */
2598 }
2599
2600 static void
2601 vl_api_get_next_index_t_handler (vl_api_get_next_index_t * mp)
2602 {
2603   vlib_main_t *vm = vlib_get_main ();
2604   vl_api_get_next_index_reply_t *rmp;
2605   vlib_node_t *node, *next_node;
2606   int rv = 0;
2607   u32 next_node_index = ~0, next_index = ~0;
2608   uword *p;
2609
2610   node = vlib_get_node_by_name (vm, mp->node_name);
2611
2612   if (node == 0)
2613     {
2614       rv = VNET_API_ERROR_NO_SUCH_NODE;
2615       goto out;
2616     }
2617
2618   next_node = vlib_get_node_by_name (vm, mp->next_name);
2619
2620   if (next_node == 0)
2621     {
2622       rv = VNET_API_ERROR_NO_SUCH_NODE2;
2623       goto out;
2624     }
2625   else
2626     next_node_index = next_node->index;
2627
2628   p = hash_get (node->next_slot_by_node, next_node_index);
2629
2630   if (p == 0)
2631     {
2632       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
2633       goto out;
2634     }
2635   else
2636     next_index = p[0];
2637
2638 out:
2639   /* *INDENT-OFF* */
2640   REPLY_MACRO2(VL_API_GET_NEXT_INDEX_REPLY,
2641   ({
2642     rmp->next_index = ntohl(next_index);
2643   }));
2644   /* *INDENT-ON* */
2645 }
2646
2647 static void
2648 vl_api_add_node_next_t_handler (vl_api_add_node_next_t * mp)
2649 {
2650   vlib_main_t *vm = vlib_get_main ();
2651   vl_api_add_node_next_reply_t *rmp;
2652   vlib_node_t *n, *next;
2653   int rv = 0;
2654   u32 next_index = ~0;
2655
2656   n = vlib_get_node_by_name (vm, mp->node_name);
2657
2658   if (n == 0)
2659     {
2660       rv = VNET_API_ERROR_NO_SUCH_NODE;
2661       goto out;
2662     }
2663
2664   next = vlib_get_node_by_name (vm, mp->next_name);
2665
2666   if (next == 0)
2667     rv = VNET_API_ERROR_NO_SUCH_NODE2;
2668   else
2669     next_index = vlib_node_add_next (vm, n->index, next->index);
2670
2671 out:
2672   /* *INDENT-OFF* */
2673   REPLY_MACRO2(VL_API_GET_NODE_INDEX_REPLY,
2674   ({
2675     rmp->next_index = ntohl(next_index);
2676   }));
2677   /* *INDENT-ON* */
2678 }
2679
2680 static void vl_api_vxlan_add_del_tunnel_t_handler
2681   (vl_api_vxlan_add_del_tunnel_t * mp)
2682 {
2683   vl_api_vxlan_add_del_tunnel_reply_t *rmp;
2684   int rv = 0;
2685   vnet_vxlan_add_del_tunnel_args_t _a, *a = &_a;
2686   u32 encap_fib_index;
2687   uword *p;
2688   ip4_main_t *im = &ip4_main;
2689   vnet_main_t *vnm = vnet_get_main ();
2690   u32 sw_if_index = ~0;
2691
2692   p = hash_get (im->fib_index_by_table_id, ntohl (mp->encap_vrf_id));
2693   if (!p)
2694     {
2695       rv = VNET_API_ERROR_NO_SUCH_FIB;
2696       goto out;
2697     }
2698   encap_fib_index = p[0];
2699   memset (a, 0, sizeof (*a));
2700
2701   a->is_add = mp->is_add;
2702   a->is_ip6 = mp->is_ipv6;
2703
2704   /* ip addresses sent in network byte order */
2705   ip46_from_addr_buf (mp->is_ipv6, mp->dst_address, &a->dst);
2706   ip46_from_addr_buf (mp->is_ipv6, mp->src_address, &a->src);
2707
2708   /* Check src & dst are different */
2709   if (ip46_address_cmp (&a->dst, &a->src) == 0)
2710     {
2711       rv = VNET_API_ERROR_SAME_SRC_DST;
2712       goto out;
2713     }
2714   a->mcast_sw_if_index = ntohl (mp->mcast_sw_if_index);
2715   if (ip46_address_is_multicast (&a->dst) &&
2716       pool_is_free_index (vnm->interface_main.sw_interfaces,
2717                           a->mcast_sw_if_index))
2718     {
2719       rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
2720       goto out;
2721     }
2722   a->encap_fib_index = encap_fib_index;
2723   a->decap_next_index = ntohl (mp->decap_next_index);
2724   a->vni = ntohl (mp->vni);
2725   rv = vnet_vxlan_add_del_tunnel (a, &sw_if_index);
2726
2727 out:
2728   /* *INDENT-OFF* */
2729   REPLY_MACRO2(VL_API_VXLAN_ADD_DEL_TUNNEL_REPLY,
2730   ({
2731     rmp->sw_if_index = ntohl (sw_if_index);
2732   }));
2733   /* *INDENT-ON* */
2734 }
2735
2736 static void send_vxlan_tunnel_details
2737   (vxlan_tunnel_t * t, unix_shared_memory_queue_t * q, u32 context)
2738 {
2739   vl_api_vxlan_tunnel_details_t *rmp;
2740   ip4_main_t *im4 = &ip4_main;
2741   ip6_main_t *im6 = &ip6_main;
2742   u8 is_ipv6 = !ip46_address_is_ip4 (&t->dst);
2743
2744   rmp = vl_msg_api_alloc (sizeof (*rmp));
2745   memset (rmp, 0, sizeof (*rmp));
2746   rmp->_vl_msg_id = ntohs (VL_API_VXLAN_TUNNEL_DETAILS);
2747   if (is_ipv6)
2748     {
2749       memcpy (rmp->src_address, t->src.ip6.as_u8, 16);
2750       memcpy (rmp->dst_address, t->dst.ip6.as_u8, 16);
2751       rmp->encap_vrf_id = htonl (im6->fibs[t->encap_fib_index].ft_table_id);
2752     }
2753   else
2754     {
2755       memcpy (rmp->src_address, t->src.ip4.as_u8, 4);
2756       memcpy (rmp->dst_address, t->dst.ip4.as_u8, 4);
2757       rmp->encap_vrf_id = htonl (im4->fibs[t->encap_fib_index].ft_table_id);
2758     }
2759   rmp->mcast_sw_if_index = htonl (t->mcast_sw_if_index);
2760   rmp->vni = htonl (t->vni);
2761   rmp->decap_next_index = htonl (t->decap_next_index);
2762   rmp->sw_if_index = htonl (t->sw_if_index);
2763   rmp->is_ipv6 = is_ipv6;
2764   rmp->context = context;
2765
2766   vl_msg_api_send_shmem (q, (u8 *) & rmp);
2767 }
2768
2769 static void vl_api_vxlan_tunnel_dump_t_handler
2770   (vl_api_vxlan_tunnel_dump_t * mp)
2771 {
2772   unix_shared_memory_queue_t *q;
2773   vxlan_main_t *vxm = &vxlan_main;
2774   vxlan_tunnel_t *t;
2775   u32 sw_if_index;
2776
2777   q = vl_api_client_index_to_input_queue (mp->client_index);
2778   if (q == 0)
2779     {
2780       return;
2781     }
2782
2783   sw_if_index = ntohl (mp->sw_if_index);
2784
2785   if (~0 == sw_if_index)
2786     {
2787       /* *INDENT-OFF* */
2788       pool_foreach (t, vxm->tunnels,
2789       ({
2790         send_vxlan_tunnel_details(t, q, mp->context);
2791       }));
2792       /* *INDENT-ON* */
2793     }
2794   else
2795     {
2796       if ((sw_if_index >= vec_len (vxm->tunnel_index_by_sw_if_index)) ||
2797           (~0 == vxm->tunnel_index_by_sw_if_index[sw_if_index]))
2798         {
2799           return;
2800         }
2801       t = &vxm->tunnels[vxm->tunnel_index_by_sw_if_index[sw_if_index]];
2802       send_vxlan_tunnel_details (t, q, mp->context);
2803     }
2804 }
2805
2806 static void
2807 vl_api_l2_patch_add_del_t_handler (vl_api_l2_patch_add_del_t * mp)
2808 {
2809   extern int vnet_l2_patch_add_del (u32 rx_sw_if_index, u32 tx_sw_if_index,
2810                                     int is_add);
2811   vl_api_l2_patch_add_del_reply_t *rmp;
2812   int vnet_l2_patch_add_del (u32 rx_sw_if_index, u32 tx_sw_if_index,
2813                              int is_add);
2814   int rv = 0;
2815
2816   VALIDATE_RX_SW_IF_INDEX (mp);
2817   VALIDATE_TX_SW_IF_INDEX (mp);
2818
2819   rv = vnet_l2_patch_add_del (ntohl (mp->rx_sw_if_index),
2820                               ntohl (mp->tx_sw_if_index),
2821                               (int) (mp->is_add != 0));
2822
2823   BAD_RX_SW_IF_INDEX_LABEL;
2824   BAD_TX_SW_IF_INDEX_LABEL;
2825
2826   REPLY_MACRO (VL_API_L2_PATCH_ADD_DEL_REPLY);
2827 }
2828
2829 static void
2830   vl_api_vxlan_gpe_add_del_tunnel_t_handler
2831   (vl_api_vxlan_gpe_add_del_tunnel_t * mp)
2832 {
2833   vl_api_vxlan_gpe_add_del_tunnel_reply_t *rmp;
2834   int rv = 0;
2835   vnet_vxlan_gpe_add_del_tunnel_args_t _a, *a = &_a;
2836   u32 encap_fib_index, decap_fib_index;
2837   u8 protocol;
2838   uword *p;
2839   ip4_main_t *im = &ip4_main;
2840   u32 sw_if_index = ~0;
2841
2842
2843   p = hash_get (im->fib_index_by_table_id, ntohl (mp->encap_vrf_id));
2844   if (!p)
2845     {
2846       rv = VNET_API_ERROR_NO_SUCH_FIB;
2847       goto out;
2848     }
2849   encap_fib_index = p[0];
2850
2851   protocol = mp->protocol;
2852
2853   /* Interpret decap_vrf_id as an opaque if sending to other-than-ip4-input */
2854   if (protocol == VXLAN_GPE_INPUT_NEXT_IP4_INPUT)
2855     {
2856       p = hash_get (im->fib_index_by_table_id, ntohl (mp->decap_vrf_id));
2857       if (!p)
2858         {
2859           rv = VNET_API_ERROR_NO_SUCH_INNER_FIB;
2860           goto out;
2861         }
2862       decap_fib_index = p[0];
2863     }
2864   else
2865     {
2866       decap_fib_index = ntohl (mp->decap_vrf_id);
2867     }
2868
2869   /* Check src & dst are different */
2870   if ((mp->is_ipv6 && memcmp (mp->local, mp->remote, 16) == 0) ||
2871       (!mp->is_ipv6 && memcmp (mp->local, mp->remote, 4) == 0))
2872     {
2873       rv = VNET_API_ERROR_SAME_SRC_DST;
2874       goto out;
2875     }
2876   memset (a, 0, sizeof (*a));
2877
2878   a->is_add = mp->is_add;
2879   a->is_ip6 = mp->is_ipv6;
2880   /* ip addresses sent in network byte order */
2881   if (a->is_ip6)
2882     {
2883       clib_memcpy (&(a->local.ip6), mp->local, 16);
2884       clib_memcpy (&(a->remote.ip6), mp->remote, 16);
2885     }
2886   else
2887     {
2888       clib_memcpy (&(a->local.ip4), mp->local, 4);
2889       clib_memcpy (&(a->remote.ip4), mp->remote, 4);
2890     }
2891   a->encap_fib_index = encap_fib_index;
2892   a->decap_fib_index = decap_fib_index;
2893   a->protocol = protocol;
2894   a->vni = ntohl (mp->vni);
2895   rv = vnet_vxlan_gpe_add_del_tunnel (a, &sw_if_index);
2896
2897 out:
2898   /* *INDENT-OFF* */
2899   REPLY_MACRO2(VL_API_VXLAN_GPE_ADD_DEL_TUNNEL_REPLY,
2900   ({
2901     rmp->sw_if_index = ntohl (sw_if_index);
2902   }));
2903   /* *INDENT-ON* */
2904 }
2905
2906 static void send_vxlan_gpe_tunnel_details
2907   (vxlan_gpe_tunnel_t * t, unix_shared_memory_queue_t * q, u32 context)
2908 {
2909   vl_api_vxlan_gpe_tunnel_details_t *rmp;
2910   ip4_main_t *im4 = &ip4_main;
2911   ip6_main_t *im6 = &ip6_main;
2912   u8 is_ipv6 = !(t->flags & VXLAN_GPE_TUNNEL_IS_IPV4);
2913
2914   rmp = vl_msg_api_alloc (sizeof (*rmp));
2915   memset (rmp, 0, sizeof (*rmp));
2916   rmp->_vl_msg_id = ntohs (VL_API_VXLAN_GPE_TUNNEL_DETAILS);
2917   if (is_ipv6)
2918     {
2919       memcpy (rmp->local, &(t->local.ip6), 16);
2920       memcpy (rmp->remote, &(t->remote.ip6), 16);
2921       rmp->encap_vrf_id = htonl (im6->fibs[t->encap_fib_index].ft_table_id);
2922       rmp->decap_vrf_id = htonl (im6->fibs[t->decap_fib_index].ft_table_id);
2923     }
2924   else
2925     {
2926       memcpy (rmp->local, &(t->local.ip4), 4);
2927       memcpy (rmp->remote, &(t->remote.ip4), 4);
2928       rmp->encap_vrf_id = htonl (im4->fibs[t->encap_fib_index].ft_table_id);
2929       rmp->decap_vrf_id = htonl (im4->fibs[t->decap_fib_index].ft_table_id);
2930     }
2931   rmp->vni = htonl (t->vni);
2932   rmp->protocol = t->protocol;
2933   rmp->sw_if_index = htonl (t->sw_if_index);
2934   rmp->is_ipv6 = is_ipv6;
2935   rmp->context = context;
2936
2937   vl_msg_api_send_shmem (q, (u8 *) & rmp);
2938 }
2939
2940 static void vl_api_vxlan_gpe_tunnel_dump_t_handler
2941   (vl_api_vxlan_gpe_tunnel_dump_t * mp)
2942 {
2943   unix_shared_memory_queue_t *q;
2944   vxlan_gpe_main_t *vgm = &vxlan_gpe_main;
2945   vxlan_gpe_tunnel_t *t;
2946   u32 sw_if_index;
2947
2948   q = vl_api_client_index_to_input_queue (mp->client_index);
2949   if (q == 0)
2950     {
2951       return;
2952     }
2953
2954   sw_if_index = ntohl (mp->sw_if_index);
2955
2956   if (~0 == sw_if_index)
2957     {
2958       /* *INDENT-OFF* */
2959       pool_foreach (t, vgm->tunnels,
2960       ({
2961         send_vxlan_gpe_tunnel_details(t, q, mp->context);
2962       }));
2963       /* *INDENT-ON* */
2964     }
2965   else
2966     {
2967       if ((sw_if_index >= vec_len (vgm->tunnel_index_by_sw_if_index)) ||
2968           (~0 == vgm->tunnel_index_by_sw_if_index[sw_if_index]))
2969         {
2970           return;
2971         }
2972       t = &vgm->tunnels[vgm->tunnel_index_by_sw_if_index[sw_if_index]];
2973       send_vxlan_gpe_tunnel_details (t, q, mp->context);
2974     }
2975 }
2976
2977 static void
2978 vl_api_interface_name_renumber_t_handler (vl_api_interface_name_renumber_t *
2979                                           mp)
2980 {
2981   vl_api_interface_name_renumber_reply_t *rmp;
2982   int rv = 0;
2983
2984   VALIDATE_SW_IF_INDEX (mp);
2985
2986   rv = vnet_interface_name_renumber
2987     (ntohl (mp->sw_if_index), ntohl (mp->new_show_dev_instance));
2988
2989   BAD_SW_IF_INDEX_LABEL;
2990
2991   REPLY_MACRO (VL_API_INTERFACE_NAME_RENUMBER_REPLY);
2992 }
2993
2994 static int
2995 arp_change_data_callback (u32 pool_index, u8 * new_mac,
2996                           u32 sw_if_index, u32 address)
2997 {
2998   vpe_api_main_t *am = &vpe_api_main;
2999   vlib_main_t *vm = am->vlib_main;
3000   vl_api_ip4_arp_event_t *event;
3001   static f64 arp_event_last_time;
3002   f64 now = vlib_time_now (vm);
3003
3004   if (pool_is_free_index (am->arp_events, pool_index))
3005     return 1;
3006
3007   event = pool_elt_at_index (am->arp_events, pool_index);
3008   /* *INDENT-OFF* */
3009   if (memcmp (&event->new_mac, new_mac, sizeof (event->new_mac)))
3010     {
3011       clib_memcpy (event->new_mac, new_mac, sizeof (event->new_mac));
3012     }
3013   else
3014     {                           /* same mac */
3015       if (sw_if_index == event->sw_if_index &&
3016           (!event->mac_ip ||
3017            /* for BD case, also check IP address with 10 sec timeout */
3018            (address == event->address &&
3019             (now - arp_event_last_time) < 10.0)))
3020         return 1;
3021     }
3022   /* *INDENT-ON* */
3023
3024   arp_event_last_time = now;
3025   event->sw_if_index = sw_if_index;
3026   if (event->mac_ip)
3027     event->address = address;
3028   return 0;
3029 }
3030
3031 static int
3032 nd_change_data_callback (u32 pool_index, u8 * new_mac,
3033                          u32 sw_if_index, ip6_address_t * address)
3034 {
3035   vpe_api_main_t *am = &vpe_api_main;
3036   vlib_main_t *vm = am->vlib_main;
3037   vl_api_ip6_nd_event_t *event;
3038   static f64 nd_event_last_time;
3039   f64 now = vlib_time_now (vm);
3040
3041   if (pool_is_free_index (am->nd_events, pool_index))
3042     return 1;
3043
3044   event = pool_elt_at_index (am->nd_events, pool_index);
3045
3046   /* *INDENT-OFF* */
3047   if (memcmp (&event->new_mac, new_mac, sizeof (event->new_mac)))
3048     {
3049       clib_memcpy (event->new_mac, new_mac, sizeof (event->new_mac));
3050     }
3051   else
3052     {                           /* same mac */
3053       if (sw_if_index == event->sw_if_index &&
3054           (!event->mac_ip ||
3055            /* for BD case, also check IP address with 10 sec timeout */
3056            (ip6_address_is_equal (address,
3057                                   (ip6_address_t *) event->address) &&
3058             (now - nd_event_last_time) < 10.0)))
3059         return 1;
3060     }
3061   /* *INDENT-ON* */
3062
3063   nd_event_last_time = now;
3064   event->sw_if_index = sw_if_index;
3065   if (event->mac_ip)
3066     clib_memcpy (event->address, address, sizeof (event->address));
3067   return 0;
3068 }
3069
3070 static int
3071 arp_change_delete_callback (u32 pool_index, u8 * notused)
3072 {
3073   vpe_api_main_t *am = &vpe_api_main;
3074
3075   if (pool_is_free_index (am->arp_events, pool_index))
3076     return 1;
3077
3078   pool_put_index (am->arp_events, pool_index);
3079   return 0;
3080 }
3081
3082 static int
3083 nd_change_delete_callback (u32 pool_index, u8 * notused)
3084 {
3085   vpe_api_main_t *am = &vpe_api_main;
3086
3087   if (pool_is_free_index (am->nd_events, pool_index))
3088     return 1;
3089
3090   pool_put_index (am->nd_events, pool_index);
3091   return 0;
3092 }
3093
3094 static void
3095 vl_api_want_ip4_arp_events_t_handler (vl_api_want_ip4_arp_events_t * mp)
3096 {
3097   vpe_api_main_t *am = &vpe_api_main;
3098   vnet_main_t *vnm = vnet_get_main ();
3099   vl_api_want_ip4_arp_events_reply_t *rmp;
3100   vl_api_ip4_arp_event_t *event;
3101   int rv;
3102
3103   if (mp->enable_disable)
3104     {
3105       pool_get (am->arp_events, event);
3106       memset (event, 0, sizeof (*event));
3107
3108       event->_vl_msg_id = ntohs (VL_API_IP4_ARP_EVENT);
3109       event->client_index = mp->client_index;
3110       event->context = mp->context;
3111       event->address = mp->address;
3112       event->pid = mp->pid;
3113       if (mp->address == 0)
3114         event->mac_ip = 1;
3115
3116       rv = vnet_add_del_ip4_arp_change_event
3117         (vnm, arp_change_data_callback,
3118          mp->pid, &mp->address /* addr, in net byte order */ ,
3119          vpe_resolver_process_node.index,
3120          IP4_ARP_EVENT, event - am->arp_events, 1 /* is_add */ );
3121     }
3122   else
3123     {
3124       rv = vnet_add_del_ip4_arp_change_event
3125         (vnm, arp_change_delete_callback,
3126          mp->pid, &mp->address /* addr, in net byte order */ ,
3127          vpe_resolver_process_node.index,
3128          IP4_ARP_EVENT, ~0 /* pool index */ , 0 /* is_add */ );
3129     }
3130   REPLY_MACRO (VL_API_WANT_IP4_ARP_EVENTS_REPLY);
3131 }
3132
3133 static void
3134 vl_api_want_ip6_nd_events_t_handler (vl_api_want_ip6_nd_events_t * mp)
3135 {
3136   vpe_api_main_t *am = &vpe_api_main;
3137   vnet_main_t *vnm = vnet_get_main ();
3138   vl_api_want_ip6_nd_events_reply_t *rmp;
3139   vl_api_ip6_nd_event_t *event;
3140   int rv;
3141
3142   if (mp->enable_disable)
3143     {
3144       pool_get (am->nd_events, event);
3145       memset (event, 0, sizeof (*event));
3146
3147       event->_vl_msg_id = ntohs (VL_API_IP6_ND_EVENT);
3148       event->client_index = mp->client_index;
3149       event->context = mp->context;
3150       clib_memcpy (event->address, mp->address, 16);
3151       event->pid = mp->pid;
3152       if (ip6_address_is_zero ((ip6_address_t *) mp->address))
3153         event->mac_ip = 1;
3154
3155       rv = vnet_add_del_ip6_nd_change_event
3156         (vnm, nd_change_data_callback,
3157          mp->pid, mp->address /* addr, in net byte order */ ,
3158          vpe_resolver_process_node.index,
3159          IP6_ND_EVENT, event - am->nd_events, 1 /* is_add */ );
3160     }
3161   else
3162     {
3163       rv = vnet_add_del_ip6_nd_change_event
3164         (vnm, nd_change_delete_callback,
3165          mp->pid, mp->address /* addr, in net byte order */ ,
3166          vpe_resolver_process_node.index,
3167          IP6_ND_EVENT, ~0 /* pool index */ , 0 /* is_add */ );
3168     }
3169   REPLY_MACRO (VL_API_WANT_IP6_ND_EVENTS_REPLY);
3170 }
3171
3172 static void vl_api_input_acl_set_interface_t_handler
3173   (vl_api_input_acl_set_interface_t * mp)
3174 {
3175   vlib_main_t *vm = vlib_get_main ();
3176   vl_api_input_acl_set_interface_reply_t *rmp;
3177   int rv;
3178   u32 sw_if_index, ip4_table_index, ip6_table_index, l2_table_index;
3179
3180   ip4_table_index = ntohl (mp->ip4_table_index);
3181   ip6_table_index = ntohl (mp->ip6_table_index);
3182   l2_table_index = ntohl (mp->l2_table_index);
3183   sw_if_index = ntohl (mp->sw_if_index);
3184
3185   VALIDATE_SW_IF_INDEX (mp);
3186
3187   rv = vnet_set_input_acl_intfc (vm, sw_if_index, ip4_table_index,
3188                                  ip6_table_index, l2_table_index, mp->is_add);
3189
3190   BAD_SW_IF_INDEX_LABEL;
3191
3192   REPLY_MACRO (VL_API_INPUT_ACL_SET_INTERFACE_REPLY);
3193 }
3194
3195 static void vl_api_cop_interface_enable_disable_t_handler
3196   (vl_api_cop_interface_enable_disable_t * mp)
3197 {
3198   vl_api_cop_interface_enable_disable_reply_t *rmp;
3199   int rv;
3200   u32 sw_if_index = ntohl (mp->sw_if_index);
3201   int enable_disable;
3202
3203   VALIDATE_SW_IF_INDEX (mp);
3204
3205   enable_disable = (int) mp->enable_disable;
3206
3207   rv = cop_interface_enable_disable (sw_if_index, enable_disable);
3208
3209   BAD_SW_IF_INDEX_LABEL;
3210
3211   REPLY_MACRO (VL_API_COP_INTERFACE_ENABLE_DISABLE_REPLY);
3212 }
3213
3214 static void vl_api_cop_whitelist_enable_disable_t_handler
3215   (vl_api_cop_whitelist_enable_disable_t * mp)
3216 {
3217   vl_api_cop_whitelist_enable_disable_reply_t *rmp;
3218   cop_whitelist_enable_disable_args_t _a, *a = &_a;
3219   u32 sw_if_index = ntohl (mp->sw_if_index);
3220   int rv;
3221
3222   VALIDATE_SW_IF_INDEX (mp);
3223
3224   a->sw_if_index = sw_if_index;
3225   a->ip4 = mp->ip4;
3226   a->ip6 = mp->ip6;
3227   a->default_cop = mp->default_cop;
3228   a->fib_id = ntohl (mp->fib_id);
3229
3230   rv = cop_whitelist_enable_disable (a);
3231
3232   BAD_SW_IF_INDEX_LABEL;
3233
3234   REPLY_MACRO (VL_API_COP_WHITELIST_ENABLE_DISABLE_REPLY);
3235 }
3236
3237 static void
3238 vl_api_get_node_graph_t_handler (vl_api_get_node_graph_t * mp)
3239 {
3240   int rv = 0;
3241   u8 *vector = 0;
3242   api_main_t *am = &api_main;
3243   vlib_main_t *vm = vlib_get_main ();
3244   void *oldheap;
3245   vl_api_get_node_graph_reply_t *rmp;
3246
3247   pthread_mutex_lock (&am->vlib_rp->mutex);
3248   oldheap = svm_push_data_heap (am->vlib_rp);
3249
3250   /*
3251    * Keep the number of memcpy ops to a minimum (e.g. 1).
3252    */
3253   vec_validate (vector, 16384);
3254   vec_reset_length (vector);
3255
3256   /* $$$$ FIXME */
3257   vector = vlib_node_serialize (&vm->node_main, vector,
3258                                 (u32) ~ 0 /* all threads */ ,
3259                                 1 /* include nexts */ ,
3260                                 1 /* include stats */ );
3261
3262   svm_pop_heap (oldheap);
3263   pthread_mutex_unlock (&am->vlib_rp->mutex);
3264
3265   /* *INDENT-OFF* */
3266   REPLY_MACRO2(VL_API_GET_NODE_GRAPH_REPLY,
3267   ({
3268     rmp->reply_in_shmem = (uword) vector;
3269   }));
3270   /* *INDENT-ON* */
3271 }
3272
3273 static void
3274 vl_api_ioam_enable_t_handler (vl_api_ioam_enable_t * mp)
3275 {
3276   int rv = 0;
3277   vl_api_ioam_enable_reply_t *rmp;
3278   clib_error_t *error;
3279
3280   /* Ignoring the profile id as currently a single profile
3281    * is supported */
3282   error = ip6_ioam_enable (mp->trace_enable, mp->pot_enable,
3283                            mp->seqno, mp->analyse);
3284   if (error)
3285     {
3286       clib_error_report (error);
3287       rv = clib_error_get_code (error);
3288     }
3289
3290   REPLY_MACRO (VL_API_IOAM_ENABLE_REPLY);
3291 }
3292
3293 static void
3294 vl_api_ioam_disable_t_handler (vl_api_ioam_disable_t * mp)
3295 {
3296   int rv = 0;
3297   vl_api_ioam_disable_reply_t *rmp;
3298   clib_error_t *error;
3299
3300   error = clear_ioam_rewrite_fn ();
3301   if (error)
3302     {
3303       clib_error_report (error);
3304       rv = clib_error_get_code (error);
3305     }
3306
3307   REPLY_MACRO (VL_API_IOAM_DISABLE_REPLY);
3308 }
3309
3310 static void
3311 vl_api_policer_add_del_t_handler (vl_api_policer_add_del_t * mp)
3312 {
3313   vlib_main_t *vm = vlib_get_main ();
3314   vl_api_policer_add_del_reply_t *rmp;
3315   int rv = 0;
3316   u8 *name = NULL;
3317   sse2_qos_pol_cfg_params_st cfg;
3318   clib_error_t *error;
3319   u32 policer_index;
3320
3321   name = format (0, "%s", mp->name);
3322
3323   memset (&cfg, 0, sizeof (cfg));
3324   cfg.rfc = mp->type;
3325   cfg.rnd_type = mp->round_type;
3326   cfg.rate_type = mp->rate_type;
3327   cfg.rb.kbps.cir_kbps = mp->cir;
3328   cfg.rb.kbps.eir_kbps = mp->eir;
3329   cfg.rb.kbps.cb_bytes = mp->cb;
3330   cfg.rb.kbps.eb_bytes = mp->eb;
3331   cfg.conform_action.action_type = mp->conform_action_type;
3332   cfg.conform_action.dscp = mp->conform_dscp;
3333   cfg.exceed_action.action_type = mp->exceed_action_type;
3334   cfg.exceed_action.dscp = mp->exceed_dscp;
3335   cfg.violate_action.action_type = mp->violate_action_type;
3336   cfg.violate_action.dscp = mp->violate_dscp;
3337   cfg.color_aware = mp->color_aware;
3338
3339   error = policer_add_del (vm, name, &cfg, &policer_index, mp->is_add);
3340
3341   if (error)
3342     rv = VNET_API_ERROR_UNSPECIFIED;
3343
3344   /* *INDENT-OFF* */
3345   REPLY_MACRO2(VL_API_POLICER_ADD_DEL_REPLY,
3346   ({
3347     if (rv == 0 &&  mp->is_add)
3348       rmp->policer_index = ntohl(policer_index);
3349     else
3350       rmp->policer_index = ~0;
3351   }));
3352   /* *INDENT-ON* */
3353 }
3354
3355 static void
3356 send_policer_details (u8 * name,
3357                       sse2_qos_pol_cfg_params_st * config,
3358                       policer_read_response_type_st * templ,
3359                       unix_shared_memory_queue_t * q, u32 context)
3360 {
3361   vl_api_policer_details_t *mp;
3362
3363   mp = vl_msg_api_alloc (sizeof (*mp));
3364   memset (mp, 0, sizeof (*mp));
3365   mp->_vl_msg_id = ntohs (VL_API_POLICER_DETAILS);
3366   mp->context = context;
3367   mp->cir = htonl (config->rb.kbps.cir_kbps);
3368   mp->eir = htonl (config->rb.kbps.eir_kbps);
3369   mp->cb = htonl (config->rb.kbps.cb_bytes);
3370   mp->eb = htonl (config->rb.kbps.eb_bytes);
3371   mp->rate_type = config->rate_type;
3372   mp->round_type = config->rnd_type;
3373   mp->type = config->rfc;
3374   mp->conform_action_type = config->conform_action.action_type;
3375   mp->conform_dscp = config->conform_action.dscp;
3376   mp->exceed_action_type = config->exceed_action.action_type;
3377   mp->exceed_dscp = config->exceed_action.dscp;
3378   mp->violate_action_type = config->violate_action.action_type;
3379   mp->violate_dscp = config->violate_action.dscp;
3380   mp->single_rate = templ->single_rate ? 1 : 0;
3381   mp->color_aware = templ->color_aware ? 1 : 0;
3382   mp->scale = htonl (templ->scale);
3383   mp->cir_tokens_per_period = htonl (templ->cir_tokens_per_period);
3384   mp->pir_tokens_per_period = htonl (templ->pir_tokens_per_period);
3385   mp->current_limit = htonl (templ->current_limit);
3386   mp->current_bucket = htonl (templ->current_bucket);
3387   mp->extended_limit = htonl (templ->extended_limit);
3388   mp->extended_bucket = htonl (templ->extended_bucket);
3389   mp->last_update_time = clib_host_to_net_u64 (templ->last_update_time);
3390
3391   strncpy ((char *) mp->name, (char *) name, ARRAY_LEN (mp->name) - 1);
3392
3393   vl_msg_api_send_shmem (q, (u8 *) & mp);
3394 }
3395
3396 static void
3397 vl_api_policer_dump_t_handler (vl_api_policer_dump_t * mp)
3398 {
3399   unix_shared_memory_queue_t *q;
3400   vnet_policer_main_t *pm = &vnet_policer_main;
3401   hash_pair_t *hp;
3402   uword *p;
3403   u32 pool_index;
3404   u8 *match_name = 0;
3405   u8 *name;
3406   sse2_qos_pol_cfg_params_st *config;
3407   policer_read_response_type_st *templ;
3408
3409   q = vl_api_client_index_to_input_queue (mp->client_index);
3410   if (q == 0)
3411     return;
3412
3413   if (mp->match_name_valid)
3414     {
3415       match_name = format (0, "%s%c", mp->match_name, 0);
3416     }
3417
3418   if (mp->match_name_valid)
3419     {
3420       p = hash_get_mem (pm->policer_config_by_name, match_name);
3421       if (p)
3422         {
3423           pool_index = p[0];
3424           config = pool_elt_at_index (pm->configs, pool_index);
3425           templ = pool_elt_at_index (pm->policer_templates, pool_index);
3426           send_policer_details (match_name, config, templ, q, mp->context);
3427         }
3428     }
3429   else
3430     {
3431       /* *INDENT-OFF* */
3432       hash_foreach_pair (hp, pm->policer_config_by_name,
3433       ({
3434         name = (u8 *) hp->key;
3435         pool_index = hp->value[0];
3436         config = pool_elt_at_index (pm->configs, pool_index);
3437         templ = pool_elt_at_index (pm->policer_templates, pool_index);
3438         send_policer_details(name, config, templ, q, mp->context);
3439       }));
3440       /* *INDENT-ON* */
3441     }
3442 }
3443
3444 static void
3445   vl_api_policer_classify_set_interface_t_handler
3446   (vl_api_policer_classify_set_interface_t * mp)
3447 {
3448   vlib_main_t *vm = vlib_get_main ();
3449   vl_api_policer_classify_set_interface_reply_t *rmp;
3450   int rv;
3451   u32 sw_if_index, ip4_table_index, ip6_table_index, l2_table_index;
3452
3453   ip4_table_index = ntohl (mp->ip4_table_index);
3454   ip6_table_index = ntohl (mp->ip6_table_index);
3455   l2_table_index = ntohl (mp->l2_table_index);
3456   sw_if_index = ntohl (mp->sw_if_index);
3457
3458   VALIDATE_SW_IF_INDEX (mp);
3459
3460   rv = vnet_set_policer_classify_intfc (vm, sw_if_index, ip4_table_index,
3461                                         ip6_table_index, l2_table_index,
3462                                         mp->is_add);
3463
3464   BAD_SW_IF_INDEX_LABEL;
3465
3466   REPLY_MACRO (VL_API_POLICER_CLASSIFY_SET_INTERFACE_REPLY);
3467 }
3468
3469 static void
3470 send_policer_classify_details (u32 sw_if_index,
3471                                u32 table_index,
3472                                unix_shared_memory_queue_t * q, u32 context)
3473 {
3474   vl_api_policer_classify_details_t *mp;
3475
3476   mp = vl_msg_api_alloc (sizeof (*mp));
3477   memset (mp, 0, sizeof (*mp));
3478   mp->_vl_msg_id = ntohs (VL_API_POLICER_CLASSIFY_DETAILS);
3479   mp->context = context;
3480   mp->sw_if_index = htonl (sw_if_index);
3481   mp->table_index = htonl (table_index);
3482
3483   vl_msg_api_send_shmem (q, (u8 *) & mp);
3484 }
3485
3486 static void
3487 vl_api_policer_classify_dump_t_handler (vl_api_policer_classify_dump_t * mp)
3488 {
3489   unix_shared_memory_queue_t *q;
3490   policer_classify_main_t *pcm = &policer_classify_main;
3491   u32 *vec_tbl;
3492   int i;
3493
3494   q = vl_api_client_index_to_input_queue (mp->client_index);
3495   if (q == 0)
3496     return;
3497
3498   vec_tbl = pcm->classify_table_index_by_sw_if_index[mp->type];
3499
3500   if (vec_len (vec_tbl))
3501     {
3502       for (i = 0; i < vec_len (vec_tbl); i++)
3503         {
3504           if (vec_elt (vec_tbl, i) == ~0)
3505             continue;
3506
3507           send_policer_classify_details (i, vec_elt (vec_tbl, i), q,
3508                                          mp->context);
3509         }
3510     }
3511 }
3512
3513 static void
3514 vl_api_mpls_tunnel_details_t_handler (vl_api_mpls_fib_details_t * mp)
3515 {
3516   clib_warning ("BUG");
3517 }
3518
3519 typedef struct mpls_tunnel_send_walk_ctx_t_
3520 {
3521   unix_shared_memory_queue_t *q;
3522   u32 index;
3523   u32 context;
3524 } mpls_tunnel_send_walk_ctx_t;
3525
3526 static void
3527 send_mpls_tunnel_entry (u32 mti, void *arg)
3528 {
3529   mpls_tunnel_send_walk_ctx_t *ctx;
3530   vl_api_mpls_tunnel_details_t *mp;
3531   const mpls_tunnel_t *mt;
3532   u32 nlabels;
3533
3534   ctx = arg;
3535
3536   if (~0 != ctx->index && mti != ctx->index)
3537     return;
3538
3539   mt = mpls_tunnel_get (mti);
3540   nlabels = vec_len (mt->mt_label_stack);
3541
3542   mp = vl_msg_api_alloc (sizeof (*mp) + nlabels * sizeof (u32));
3543   memset (mp, 0, sizeof (*mp));
3544   mp->_vl_msg_id = ntohs (VL_API_MPLS_TUNNEL_DETAILS);
3545   mp->context = ctx->context;
3546
3547   mp->tunnel_index = ntohl (mti);
3548   memcpy (mp->mt_next_hop_out_labels,
3549           mt->mt_label_stack, nlabels * sizeof (u32));
3550
3551   // FIXME
3552
3553   vl_msg_api_send_shmem (ctx->q, (u8 *) & mp);
3554 }
3555
3556 static void
3557 vl_api_mpls_tunnel_dump_t_handler (vl_api_mpls_tunnel_dump_t * mp)
3558 {
3559   unix_shared_memory_queue_t *q;
3560
3561   q = vl_api_client_index_to_input_queue (mp->client_index);
3562   if (q == 0)
3563     return;
3564
3565   mpls_tunnel_send_walk_ctx_t ctx = {
3566     .q = q,
3567     .index = ntohl (mp->tunnel_index),
3568     .context = mp->context,
3569   };
3570   mpls_tunnel_walk (send_mpls_tunnel_entry, &ctx);
3571 }
3572
3573 static void
3574 vl_api_mpls_fib_details_t_handler (vl_api_mpls_fib_details_t * mp)
3575 {
3576   clib_warning ("BUG");
3577 }
3578
3579 static void
3580 vl_api_mpls_fib_details_t_endian (vl_api_mpls_fib_details_t * mp)
3581 {
3582   clib_warning ("BUG");
3583 }
3584
3585 static void
3586 vl_api_mpls_fib_details_t_print (vl_api_mpls_fib_details_t * mp)
3587 {
3588   clib_warning ("BUG");
3589 }
3590
3591 static void
3592 send_mpls_fib_details (vpe_api_main_t * am,
3593                        unix_shared_memory_queue_t * q,
3594                        u32 table_id, u32 label, u32 eos,
3595                        fib_route_path_encode_t * api_rpaths, u32 context)
3596 {
3597   vl_api_mpls_fib_details_t *mp;
3598   fib_route_path_encode_t *api_rpath;
3599   vl_api_fib_path2_t *fp;
3600   int path_count;
3601
3602   path_count = vec_len (api_rpaths);
3603   mp = vl_msg_api_alloc (sizeof (*mp) + path_count * sizeof (*fp));
3604   if (!mp)
3605     return;
3606   memset (mp, 0, sizeof (*mp));
3607   mp->_vl_msg_id = ntohs (VL_API_MPLS_FIB_DETAILS);
3608   mp->context = context;
3609
3610   mp->table_id = htonl (table_id);
3611   mp->eos_bit = eos;
3612   mp->label = htonl (label);
3613
3614   mp->count = htonl (path_count);
3615   fp = mp->path;
3616   vec_foreach (api_rpath, api_rpaths)
3617   {
3618     memset (fp, 0, sizeof (*fp));
3619     fp->weight = htonl (api_rpath->rpath.frp_weight);
3620     fp->sw_if_index = htonl (api_rpath->rpath.frp_sw_if_index);
3621     copy_fib_next_hop (api_rpath, fp);
3622     fp++;
3623   }
3624
3625   vl_msg_api_send_shmem (q, (u8 *) & mp);
3626 }
3627
3628 static void
3629 vl_api_mpls_fib_dump_t_handler (vl_api_mpls_fib_dump_t * mp)
3630 {
3631   vpe_api_main_t *am = &vpe_api_main;
3632   unix_shared_memory_queue_t *q;
3633   mpls_main_t *mm = &mpls_main;
3634   fib_table_t *fib_table;
3635   fib_node_index_t lfei, *lfeip, *lfeis = NULL;
3636   mpls_label_t key;
3637   fib_prefix_t pfx;
3638   u32 fib_index;
3639   fib_route_path_encode_t *api_rpaths;
3640
3641   q = vl_api_client_index_to_input_queue (mp->client_index);
3642   if (q == 0)
3643     return;
3644
3645   /* *INDENT-OFF* */
3646   pool_foreach (fib_table, mm->fibs,
3647   ({
3648     hash_foreach(key, lfei, fib_table->mpls.mf_entries,
3649     ({
3650         vec_add1(lfeis, lfei);
3651     }));
3652   }));
3653   vec_sort_with_function(lfeis, fib_entry_cmp_for_sort);
3654
3655   vec_foreach(lfeip, lfeis)
3656   {
3657     fib_entry_get_prefix(*lfeip, &pfx);
3658     fib_index = fib_entry_get_fib_index(*lfeip);
3659     fib_table = fib_table_get(fib_index, pfx.fp_proto);
3660     api_rpaths = NULL;
3661     fib_entry_encode(*lfeip, &api_rpaths);
3662     send_mpls_fib_details (am, q,
3663                            fib_table->ft_table_id,
3664                            pfx.fp_label,
3665                            pfx.fp_eos,
3666                            api_rpaths,
3667                            mp->context);
3668     vec_free(api_rpaths);
3669   }
3670
3671   vec_free (lfeis);
3672 }
3673
3674 static void
3675 vl_api_classify_table_ids_t_handler (vl_api_classify_table_ids_t * mp)
3676 {
3677   unix_shared_memory_queue_t *q;
3678
3679   q = vl_api_client_index_to_input_queue (mp->client_index);
3680   if (q == 0)
3681     return;
3682
3683   vnet_classify_main_t *cm = &vnet_classify_main;
3684   vnet_classify_table_t *t;
3685   u32 *table_ids = 0;
3686   u32 count;
3687
3688   /* *INDENT-OFF* */
3689   pool_foreach (t, cm->tables,
3690   ({
3691     vec_add1 (table_ids, ntohl(t - cm->tables));
3692   }));
3693   /* *INDENT-ON* */
3694   count = vec_len (table_ids);
3695
3696   vl_api_classify_table_ids_reply_t *rmp;
3697   rmp = vl_msg_api_alloc_as_if_client (sizeof (*rmp) + count * sizeof (u32));
3698   rmp->_vl_msg_id = ntohs (VL_API_CLASSIFY_TABLE_IDS_REPLY);
3699   rmp->context = mp->context;
3700   rmp->count = ntohl (count);
3701   clib_memcpy (rmp->ids, table_ids, count * sizeof (u32));
3702   rmp->retval = 0;
3703
3704   vl_msg_api_send_shmem (q, (u8 *) & rmp);
3705
3706   vec_free (table_ids);
3707 }
3708
3709 static void
3710   vl_api_classify_table_by_interface_t_handler
3711   (vl_api_classify_table_by_interface_t * mp)
3712 {
3713   vl_api_classify_table_by_interface_reply_t *rmp;
3714   int rv = 0;
3715
3716   u32 sw_if_index = ntohl (mp->sw_if_index);
3717   u32 *acl = 0;
3718
3719   vec_validate (acl, INPUT_ACL_N_TABLES - 1);
3720   vec_set (acl, ~0);
3721
3722   VALIDATE_SW_IF_INDEX (mp);
3723
3724   input_acl_main_t *am = &input_acl_main;
3725
3726   int if_idx;
3727   u32 type;
3728
3729   for (type = 0; type < INPUT_ACL_N_TABLES; type++)
3730     {
3731       u32 *vec_tbl = am->classify_table_index_by_sw_if_index[type];
3732       if (vec_len (vec_tbl))
3733         {
3734           for (if_idx = 0; if_idx < vec_len (vec_tbl); if_idx++)
3735             {
3736               if (vec_elt (vec_tbl, if_idx) == ~0 || sw_if_index != if_idx)
3737                 {
3738                   continue;
3739                 }
3740               acl[type] = vec_elt (vec_tbl, if_idx);
3741             }
3742         }
3743     }
3744
3745   BAD_SW_IF_INDEX_LABEL;
3746
3747   /* *INDENT-OFF* */
3748   REPLY_MACRO2(VL_API_CLASSIFY_TABLE_BY_INTERFACE_REPLY,
3749   ({
3750     rmp->sw_if_index = ntohl(sw_if_index);
3751     rmp->l2_table_id = ntohl(acl[INPUT_ACL_TABLE_L2]);
3752     rmp->ip4_table_id = ntohl(acl[INPUT_ACL_TABLE_IP4]);
3753     rmp->ip6_table_id = ntohl(acl[INPUT_ACL_TABLE_IP6]);
3754   }));
3755   /* *INDENT-ON* */
3756   vec_free (acl);
3757 }
3758
3759 static void
3760 vl_api_classify_table_info_t_handler (vl_api_classify_table_info_t * mp)
3761 {
3762   unix_shared_memory_queue_t *q;
3763
3764   q = vl_api_client_index_to_input_queue (mp->client_index);
3765   if (q == 0)
3766     return;
3767
3768   vl_api_classify_table_info_reply_t *rmp = 0;
3769
3770   vnet_classify_main_t *cm = &vnet_classify_main;
3771   u32 table_id = ntohl (mp->table_id);
3772   vnet_classify_table_t *t;
3773
3774   /* *INDENT-OFF* */
3775   pool_foreach (t, cm->tables,
3776   ({
3777     if (table_id == t - cm->tables)
3778       {
3779         rmp = vl_msg_api_alloc_as_if_client
3780           (sizeof (*rmp) + t->match_n_vectors * sizeof (u32x4));
3781         rmp->_vl_msg_id = ntohs (VL_API_CLASSIFY_TABLE_INFO_REPLY);
3782         rmp->context = mp->context;
3783         rmp->table_id = ntohl(table_id);
3784         rmp->nbuckets = ntohl(t->nbuckets);
3785         rmp->match_n_vectors = ntohl(t->match_n_vectors);
3786         rmp->skip_n_vectors = ntohl(t->skip_n_vectors);
3787         rmp->active_sessions = ntohl(t->active_elements);
3788         rmp->next_table_index = ntohl(t->next_table_index);
3789         rmp->miss_next_index = ntohl(t->miss_next_index);
3790         rmp->mask_length = ntohl(t->match_n_vectors * sizeof (u32x4));
3791         clib_memcpy(rmp->mask, t->mask, t->match_n_vectors * sizeof(u32x4));
3792         rmp->retval = 0;
3793         break;
3794       }
3795   }));
3796   /* *INDENT-ON* */
3797
3798   if (rmp == 0)
3799     {
3800       rmp = vl_msg_api_alloc (sizeof (*rmp));
3801       rmp->_vl_msg_id = ntohs ((VL_API_CLASSIFY_TABLE_INFO_REPLY));
3802       rmp->context = mp->context;
3803       rmp->retval = ntohl (VNET_API_ERROR_CLASSIFY_TABLE_NOT_FOUND);
3804     }
3805
3806   vl_msg_api_send_shmem (q, (u8 *) & rmp);
3807 }
3808
3809 static void
3810 vl_api_classify_session_details_t_handler (vl_api_classify_session_details_t *
3811                                            mp)
3812 {
3813   clib_warning ("BUG");
3814 }
3815
3816 static void
3817 send_classify_session_details (unix_shared_memory_queue_t * q,
3818                                u32 table_id,
3819                                u32 match_length,
3820                                vnet_classify_entry_t * e, u32 context)
3821 {
3822   vl_api_classify_session_details_t *rmp;
3823
3824   rmp = vl_msg_api_alloc (sizeof (*rmp));
3825   memset (rmp, 0, sizeof (*rmp));
3826   rmp->_vl_msg_id = ntohs (VL_API_CLASSIFY_SESSION_DETAILS);
3827   rmp->context = context;
3828   rmp->table_id = ntohl (table_id);
3829   rmp->hit_next_index = ntohl (e->next_index);
3830   rmp->advance = ntohl (e->advance);
3831   rmp->opaque_index = ntohl (e->opaque_index);
3832   rmp->match_length = ntohl (match_length);
3833   clib_memcpy (rmp->match, e->key, match_length);
3834
3835   vl_msg_api_send_shmem (q, (u8 *) & rmp);
3836 }
3837
3838 static void
3839 vl_api_classify_session_dump_t_handler (vl_api_classify_session_dump_t * mp)
3840 {
3841   vnet_classify_main_t *cm = &vnet_classify_main;
3842   unix_shared_memory_queue_t *q;
3843
3844   u32 table_id = ntohl (mp->table_id);
3845   vnet_classify_table_t *t;
3846
3847   q = vl_api_client_index_to_input_queue (mp->client_index);
3848   if (!q)
3849     return;
3850
3851   /* *INDENT-OFF* */
3852   pool_foreach (t, cm->tables,
3853   ({
3854     if (table_id == t - cm->tables)
3855       {
3856         vnet_classify_bucket_t * b;
3857         vnet_classify_entry_t * v, * save_v;
3858         int i, j, k;
3859
3860         for (i = 0; i < t->nbuckets; i++)
3861           {
3862             b = &t->buckets [i];
3863             if (b->offset == 0)
3864               continue;
3865
3866             save_v = vnet_classify_get_entry (t, b->offset);
3867             for (j = 0; j < (1<<b->log2_pages); j++)
3868               {
3869                 for (k = 0; k < t->entries_per_page; k++)
3870                   {
3871                     v = vnet_classify_entry_at_index
3872                       (t, save_v, j*t->entries_per_page + k);
3873                     if (vnet_classify_entry_is_free (v))
3874                       continue;
3875
3876                     send_classify_session_details
3877                       (q, table_id, t->match_n_vectors * sizeof (u32x4),
3878                        v, mp->context);
3879                   }
3880               }
3881           }
3882         break;
3883       }
3884   }));
3885   /* *INDENT-ON* */
3886 }
3887
3888 static void
3889 vl_api_set_ipfix_exporter_t_handler (vl_api_set_ipfix_exporter_t * mp)
3890 {
3891   vlib_main_t *vm = vlib_get_main ();
3892   flow_report_main_t *frm = &flow_report_main;
3893   vl_api_set_ipfix_exporter_reply_t *rmp;
3894   ip4_address_t collector, src;
3895   u16 collector_port = UDP_DST_PORT_ipfix;
3896   u32 path_mtu;
3897   u32 template_interval;
3898   u8 udp_checksum;
3899   u32 fib_id;
3900   u32 fib_index = ~0;
3901   int rv = 0;
3902
3903   memcpy (collector.data, mp->collector_address, sizeof (collector.data));
3904   collector_port = ntohs (mp->collector_port);
3905   if (collector_port == (u16) ~ 0)
3906     collector_port = UDP_DST_PORT_ipfix;
3907   memcpy (src.data, mp->src_address, sizeof (src.data));
3908   fib_id = ntohl (mp->vrf_id);
3909
3910   ip4_main_t *im = &ip4_main;
3911   if (fib_id == ~0)
3912     {
3913       fib_index = ~0;
3914     }
3915   else
3916     {
3917       uword *p = hash_get (im->fib_index_by_table_id, fib_id);
3918       if (!p)
3919         {
3920           rv = VNET_API_ERROR_NO_SUCH_FIB;
3921           goto out;
3922         }
3923       fib_index = p[0];
3924     }
3925
3926   path_mtu = ntohl (mp->path_mtu);
3927   if (path_mtu == ~0)
3928     path_mtu = 512;             // RFC 7011 section 10.3.3.
3929   template_interval = ntohl (mp->template_interval);
3930   if (template_interval == ~0)
3931     template_interval = 20;
3932   udp_checksum = mp->udp_checksum;
3933
3934   if (collector.as_u32 == 0)
3935     {
3936       rv = VNET_API_ERROR_INVALID_VALUE;
3937       goto out;
3938     }
3939
3940   if (src.as_u32 == 0)
3941     {
3942       rv = VNET_API_ERROR_INVALID_VALUE;
3943       goto out;
3944     }
3945
3946   if (path_mtu > 1450 /* vpp does not support fragmentation */ )
3947     {
3948       rv = VNET_API_ERROR_INVALID_VALUE;
3949       goto out;
3950     }
3951
3952   if (path_mtu < 68)
3953     {
3954       rv = VNET_API_ERROR_INVALID_VALUE;
3955       goto out;
3956     }
3957
3958   /* Reset report streams if we are reconfiguring IP addresses */
3959   if (frm->ipfix_collector.as_u32 != collector.as_u32 ||
3960       frm->src_address.as_u32 != src.as_u32 ||
3961       frm->collector_port != collector_port)
3962     vnet_flow_reports_reset (frm);
3963
3964   frm->ipfix_collector.as_u32 = collector.as_u32;
3965   frm->collector_port = collector_port;
3966   frm->src_address.as_u32 = src.as_u32;
3967   frm->fib_index = fib_index;
3968   frm->path_mtu = path_mtu;
3969   frm->template_interval = template_interval;
3970   frm->udp_checksum = udp_checksum;
3971
3972   /* Turn on the flow reporting process */
3973   vlib_process_signal_event (vm, flow_report_process_node.index, 1, 0);
3974
3975 out:
3976   REPLY_MACRO (VL_API_SET_IPFIX_EXPORTER_REPLY);
3977 }
3978
3979 static void
3980 vl_api_ipfix_exporter_dump_t_handler (vl_api_ipfix_exporter_dump_t * mp)
3981 {
3982   flow_report_main_t *frm = &flow_report_main;
3983   unix_shared_memory_queue_t *q;
3984   vl_api_ipfix_exporter_details_t *rmp;
3985   ip4_main_t *im = &ip4_main;
3986   u32 vrf_id;
3987
3988   q = vl_api_client_index_to_input_queue (mp->client_index);
3989   if (!q)
3990     return;
3991
3992   rmp = vl_msg_api_alloc (sizeof (*rmp));
3993   memset (rmp, 0, sizeof (*rmp));
3994   rmp->_vl_msg_id = ntohs (VL_API_IPFIX_EXPORTER_DETAILS);
3995   rmp->context = mp->context;
3996   memcpy (rmp->collector_address, frm->ipfix_collector.data,
3997           sizeof (frm->ipfix_collector.data));
3998   rmp->collector_port = htons (frm->collector_port);
3999   memcpy (rmp->src_address, frm->src_address.data,
4000           sizeof (frm->src_address.data));
4001   if (frm->fib_index == ~0)
4002     vrf_id = ~0;
4003   else
4004     vrf_id = im->fibs[frm->fib_index].ft_table_id;
4005   rmp->vrf_id = htonl (vrf_id);
4006   rmp->path_mtu = htonl (frm->path_mtu);
4007   rmp->template_interval = htonl (frm->template_interval);
4008   rmp->udp_checksum = (frm->udp_checksum != 0);
4009
4010   vl_msg_api_send_shmem (q, (u8 *) & rmp);
4011 }
4012
4013 static void
4014   vl_api_set_ipfix_classify_stream_t_handler
4015   (vl_api_set_ipfix_classify_stream_t * mp)
4016 {
4017   vl_api_set_ipfix_classify_stream_reply_t *rmp;
4018   flow_report_classify_main_t *fcm = &flow_report_classify_main;
4019   flow_report_main_t *frm = &flow_report_main;
4020   u32 domain_id = 0;
4021   u32 src_port = UDP_DST_PORT_ipfix;
4022   int rv = 0;
4023
4024   domain_id = ntohl (mp->domain_id);
4025   src_port = ntohs (mp->src_port);
4026
4027   if (fcm->src_port != 0 &&
4028       (fcm->domain_id != domain_id || fcm->src_port != (u16) src_port))
4029     {
4030       int rv = vnet_stream_change (frm, fcm->domain_id, fcm->src_port,
4031                                    domain_id, (u16) src_port);
4032       ASSERT (rv == 0);
4033     }
4034
4035   fcm->domain_id = domain_id;
4036   fcm->src_port = (u16) src_port;
4037
4038   REPLY_MACRO (VL_API_SET_IPFIX_CLASSIFY_STREAM_REPLY);
4039 }
4040
4041 static void
4042   vl_api_ipfix_classify_stream_dump_t_handler
4043   (vl_api_ipfix_classify_stream_dump_t * mp)
4044 {
4045   flow_report_classify_main_t *fcm = &flow_report_classify_main;
4046   unix_shared_memory_queue_t *q;
4047   vl_api_ipfix_classify_stream_details_t *rmp;
4048
4049   q = vl_api_client_index_to_input_queue (mp->client_index);
4050   if (!q)
4051     return;
4052
4053   rmp = vl_msg_api_alloc (sizeof (*rmp));
4054   memset (rmp, 0, sizeof (*rmp));
4055   rmp->_vl_msg_id = ntohs (VL_API_IPFIX_CLASSIFY_STREAM_DETAILS);
4056   rmp->context = mp->context;
4057   rmp->domain_id = htonl (fcm->domain_id);
4058   rmp->src_port = htons (fcm->src_port);
4059
4060   vl_msg_api_send_shmem (q, (u8 *) & rmp);
4061 }
4062
4063 static void
4064   vl_api_ipfix_classify_table_add_del_t_handler
4065   (vl_api_ipfix_classify_table_add_del_t * mp)
4066 {
4067   vl_api_ipfix_classify_table_add_del_reply_t *rmp;
4068   flow_report_classify_main_t *fcm = &flow_report_classify_main;
4069   flow_report_main_t *frm = &flow_report_main;
4070   vnet_flow_report_add_del_args_t args;
4071   ipfix_classify_table_t *table;
4072   int is_add;
4073   u32 classify_table_index;
4074   u8 ip_version;
4075   u8 transport_protocol;
4076   int rv = 0;
4077
4078   classify_table_index = ntohl (mp->table_id);
4079   ip_version = mp->ip_version;
4080   transport_protocol = mp->transport_protocol;
4081   is_add = mp->is_add;
4082
4083   if (fcm->src_port == 0)
4084     {
4085       /* call set_ipfix_classify_stream first */
4086       rv = VNET_API_ERROR_UNSPECIFIED;
4087       goto out;
4088     }
4089
4090   memset (&args, 0, sizeof (args));
4091
4092   table = 0;
4093   int i;
4094   for (i = 0; i < vec_len (fcm->tables); i++)
4095     if (ipfix_classify_table_index_valid (i))
4096       if (fcm->tables[i].classify_table_index == classify_table_index)
4097         {
4098           table = &fcm->tables[i];
4099           break;
4100         }
4101
4102   if (is_add)
4103     {
4104       if (table)
4105         {
4106           rv = VNET_API_ERROR_VALUE_EXIST;
4107           goto out;
4108         }
4109       table = ipfix_classify_add_table ();
4110       table->classify_table_index = classify_table_index;
4111     }
4112   else
4113     {
4114       if (!table)
4115         {
4116           rv = VNET_API_ERROR_NO_SUCH_ENTRY;
4117           goto out;
4118         }
4119     }
4120
4121   table->ip_version = ip_version;
4122   table->transport_protocol = transport_protocol;
4123
4124   args.opaque.as_uword = table - fcm->tables;
4125   args.rewrite_callback = ipfix_classify_template_rewrite;
4126   args.flow_data_callback = ipfix_classify_send_flows;
4127   args.is_add = is_add;
4128   args.domain_id = fcm->domain_id;
4129   args.src_port = fcm->src_port;
4130
4131   rv = vnet_flow_report_add_del (frm, &args);
4132
4133   /* If deleting, or add failed */
4134   if (is_add == 0 || (rv && is_add))
4135     ipfix_classify_delete_table (table - fcm->tables);
4136
4137 out:
4138   REPLY_MACRO (VL_API_SET_IPFIX_CLASSIFY_STREAM_REPLY);
4139 }
4140
4141 static void
4142 send_ipfix_classify_table_details (u32 table_index,
4143                                    unix_shared_memory_queue_t * q,
4144                                    u32 context)
4145 {
4146   flow_report_classify_main_t *fcm = &flow_report_classify_main;
4147   vl_api_ipfix_classify_table_details_t *mp;
4148
4149   ipfix_classify_table_t *table = &fcm->tables[table_index];
4150
4151   mp = vl_msg_api_alloc (sizeof (*mp));
4152   memset (mp, 0, sizeof (*mp));
4153   mp->_vl_msg_id = ntohs (VL_API_IPFIX_CLASSIFY_TABLE_DETAILS);
4154   mp->context = context;
4155   mp->table_id = htonl (table->classify_table_index);
4156   mp->ip_version = table->ip_version;
4157   mp->transport_protocol = table->transport_protocol;
4158
4159   vl_msg_api_send_shmem (q, (u8 *) & mp);
4160 }
4161
4162 static void
4163   vl_api_ipfix_classify_table_dump_t_handler
4164   (vl_api_ipfix_classify_table_dump_t * mp)
4165 {
4166   flow_report_classify_main_t *fcm = &flow_report_classify_main;
4167   unix_shared_memory_queue_t *q;
4168   u32 i;
4169
4170   q = vl_api_client_index_to_input_queue (mp->client_index);
4171   if (!q)
4172     return;
4173
4174   for (i = 0; i < vec_len (fcm->tables); i++)
4175     if (ipfix_classify_table_index_valid (i))
4176       send_ipfix_classify_table_details (i, q, mp->context);
4177 }
4178
4179 static void
4180 vl_api_pg_create_interface_t_handler (vl_api_pg_create_interface_t * mp)
4181 {
4182   vl_api_pg_create_interface_reply_t *rmp;
4183   int rv = 0;
4184
4185   pg_main_t *pg = &pg_main;
4186   u32 pg_if_id = pg_interface_add_or_get (pg, ntohl (mp->interface_id));
4187   pg_interface_t *pi = pool_elt_at_index (pg->interfaces, pg_if_id);
4188
4189   /* *INDENT-OFF* */
4190   REPLY_MACRO2(VL_API_PG_CREATE_INTERFACE_REPLY,
4191   ({
4192     rmp->sw_if_index = ntohl(pi->sw_if_index);
4193   }));
4194   /* *INDENT-ON* */
4195 }
4196
4197 static void
4198 vl_api_pg_capture_t_handler (vl_api_pg_capture_t * mp)
4199 {
4200   vl_api_pg_capture_reply_t *rmp;
4201   int rv = 0;
4202
4203   vnet_main_t *vnm = vnet_get_main ();
4204   vnet_interface_main_t *im = &vnm->interface_main;
4205   vnet_hw_interface_t *hi = 0;
4206
4207   u8 *intf_name = format (0, "pg%d", ntohl (mp->interface_id), 0);
4208   u32 hw_if_index = ~0;
4209   uword *p = hash_get_mem (im->hw_interface_by_name, intf_name);
4210   if (p)
4211     hw_if_index = *p;
4212   vec_free (intf_name);
4213
4214   if (hw_if_index != ~0)
4215     {
4216       pg_capture_args_t _a, *a = &_a;
4217
4218       u32 len = ntohl (mp->pcap_name_length);
4219       u8 *pcap_file_name = vec_new (u8, len);
4220       clib_memcpy (pcap_file_name, mp->pcap_file_name, len);
4221
4222       hi = vnet_get_sup_hw_interface (vnm, hw_if_index);
4223       a->hw_if_index = hw_if_index;
4224       a->dev_instance = hi->dev_instance;
4225       a->is_enabled = mp->is_enabled;
4226       a->pcap_file_name = pcap_file_name;
4227       a->count = ntohl (mp->count);
4228
4229       clib_error_t *e = pg_capture (a);
4230       if (e)
4231         {
4232           clib_error_report (e);
4233           rv = VNET_API_ERROR_CANNOT_CREATE_PCAP_FILE;
4234         }
4235
4236       vec_free (pcap_file_name);
4237     }
4238   REPLY_MACRO (VL_API_PG_CAPTURE_REPLY);
4239 }
4240
4241 static void
4242 vl_api_pg_enable_disable_t_handler (vl_api_pg_enable_disable_t * mp)
4243 {
4244   vl_api_pg_enable_disable_reply_t *rmp;
4245   int rv = 0;
4246
4247   pg_main_t *pg = &pg_main;
4248   u32 stream_index = ~0;
4249
4250   int is_enable = mp->is_enabled != 0;
4251   u32 len = ntohl (mp->stream_name_length) - 1;
4252
4253   if (len > 0)
4254     {
4255       u8 *stream_name = vec_new (u8, len);
4256       clib_memcpy (stream_name, mp->stream_name, len);
4257       uword *p = hash_get_mem (pg->stream_index_by_name, stream_name);
4258       if (p)
4259         stream_index = *p;
4260       vec_free (stream_name);
4261     }
4262
4263   pg_enable_disable (stream_index, is_enable);
4264
4265   REPLY_MACRO (VL_API_PG_ENABLE_DISABLE_REPLY);
4266 }
4267
4268 static void
4269   vl_api_ip_source_and_port_range_check_add_del_t_handler
4270   (vl_api_ip_source_and_port_range_check_add_del_t * mp)
4271 {
4272   vl_api_ip_source_and_port_range_check_add_del_reply_t *rmp;
4273   int rv = 0;
4274
4275   u8 is_ipv6 = mp->is_ipv6;
4276   u8 is_add = mp->is_add;
4277   u8 mask_length = mp->mask_length;
4278   ip4_address_t ip4_addr;
4279   ip6_address_t ip6_addr;
4280   u16 *low_ports = 0;
4281   u16 *high_ports = 0;
4282   u32 vrf_id;
4283   u16 tmp_low, tmp_high;
4284   u8 num_ranges;
4285   int i;
4286
4287   // Validate port range
4288   num_ranges = mp->number_of_ranges;
4289   if (num_ranges > 32)
4290     {                           // This is size of array in VPE.API
4291       rv = VNET_API_ERROR_EXCEEDED_NUMBER_OF_RANGES_CAPACITY;
4292       goto reply;
4293     }
4294
4295   vec_reset_length (low_ports);
4296   vec_reset_length (high_ports);
4297
4298   for (i = 0; i < num_ranges; i++)
4299     {
4300       tmp_low = mp->low_ports[i];
4301       tmp_high = mp->high_ports[i];
4302       // If tmp_low <= tmp_high then only need to check tmp_low = 0
4303       // If tmp_low <= tmp_high then only need to check tmp_high > 65535
4304       if (tmp_low > tmp_high || tmp_low == 0 || tmp_high > 65535)
4305         {
4306           rv = VNET_API_ERROR_INVALID_VALUE;
4307           goto reply;
4308         }
4309       vec_add1 (low_ports, tmp_low);
4310       vec_add1 (high_ports, tmp_high + 1);
4311     }
4312
4313   // Validate mask_length
4314   if ((is_ipv6 && mask_length > 128) || (!is_ipv6 && mask_length > 32))
4315     {
4316       rv = VNET_API_ERROR_ADDRESS_LENGTH_MISMATCH;
4317       goto reply;
4318     }
4319
4320   vrf_id = ntohl (mp->vrf_id);
4321
4322   if (vrf_id < 1)
4323     {
4324       rv = VNET_API_ERROR_INVALID_VALUE;
4325       goto reply;
4326     }
4327
4328
4329   if (is_ipv6)
4330     {
4331       clib_memcpy (ip6_addr.as_u8, mp->address, sizeof (ip6_addr.as_u8));
4332       rv = ip6_source_and_port_range_check_add_del (&ip6_addr,
4333                                                     mask_length,
4334                                                     vrf_id,
4335                                                     low_ports,
4336                                                     high_ports, is_add);
4337     }
4338   else
4339     {
4340       clib_memcpy (ip4_addr.data, mp->address, sizeof (ip4_addr));
4341       rv = ip4_source_and_port_range_check_add_del (&ip4_addr,
4342                                                     mask_length,
4343                                                     vrf_id,
4344                                                     low_ports,
4345                                                     high_ports, is_add);
4346     }
4347
4348 reply:
4349   vec_free (low_ports);
4350   vec_free (high_ports);
4351   REPLY_MACRO (VL_API_IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL_REPLY);
4352 }
4353
4354 static void
4355   vl_api_ip_source_and_port_range_check_interface_add_del_t_handler
4356   (vl_api_ip_source_and_port_range_check_interface_add_del_t * mp)
4357 {
4358   vlib_main_t *vm = vlib_get_main ();
4359   vl_api_ip_source_and_port_range_check_interface_add_del_reply_t *rmp;
4360   ip4_main_t *im = &ip4_main;
4361   int rv;
4362   u32 sw_if_index;
4363   u32 fib_index[IP_SOURCE_AND_PORT_RANGE_CHECK_N_PROTOCOLS];
4364   u32 vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_N_PROTOCOLS];
4365   uword *p = 0;
4366   int i;
4367
4368   vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_TCP_OUT] =
4369     ntohl (mp->tcp_out_vrf_id);
4370   vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_UDP_OUT] =
4371     ntohl (mp->udp_out_vrf_id);
4372   vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_TCP_IN] =
4373     ntohl (mp->tcp_in_vrf_id);
4374   vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_UDP_IN] =
4375     ntohl (mp->udp_in_vrf_id);
4376
4377
4378   for (i = 0; i < IP_SOURCE_AND_PORT_RANGE_CHECK_N_PROTOCOLS; i++)
4379     {
4380       if (vrf_id[i] != 0 && vrf_id[i] != ~0)
4381         {
4382           p = hash_get (im->fib_index_by_table_id, vrf_id[i]);
4383
4384           if (p == 0)
4385             {
4386               rv = VNET_API_ERROR_INVALID_VALUE;
4387               goto reply;
4388             }
4389
4390           fib_index[i] = p[0];
4391         }
4392       else
4393         fib_index[i] = ~0;
4394     }
4395   sw_if_index = ntohl (mp->sw_if_index);
4396
4397   VALIDATE_SW_IF_INDEX (mp);
4398
4399   rv =
4400     set_ip_source_and_port_range_check (vm, fib_index, sw_if_index,
4401                                         mp->is_add);
4402
4403   BAD_SW_IF_INDEX_LABEL;
4404 reply:
4405
4406   REPLY_MACRO (VL_API_IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL_REPLY);
4407 }
4408
4409 static void
4410 vl_api_delete_subif_t_handler (vl_api_delete_subif_t * mp)
4411 {
4412   vl_api_delete_subif_reply_t *rmp;
4413   int rv;
4414
4415   rv = vnet_delete_sub_interface (ntohl (mp->sw_if_index));
4416
4417   REPLY_MACRO (VL_API_DELETE_SUBIF_REPLY);
4418 }
4419
4420 static void
4421   vl_api_l2_interface_pbb_tag_rewrite_t_handler
4422   (vl_api_l2_interface_pbb_tag_rewrite_t * mp)
4423 {
4424   vl_api_l2_interface_pbb_tag_rewrite_reply_t *rmp;
4425   vnet_main_t *vnm = vnet_get_main ();
4426   vlib_main_t *vm = vlib_get_main ();
4427   u32 vtr_op;
4428   int rv = 0;
4429
4430   VALIDATE_SW_IF_INDEX (mp);
4431
4432   vtr_op = ntohl (mp->vtr_op);
4433
4434   switch (vtr_op)
4435     {
4436     case L2_VTR_DISABLED:
4437     case L2_VTR_PUSH_2:
4438     case L2_VTR_POP_2:
4439     case L2_VTR_TRANSLATE_2_1:
4440       break;
4441
4442     default:
4443       rv = VNET_API_ERROR_INVALID_VALUE;
4444       goto bad_sw_if_index;
4445     }
4446
4447   rv = l2pbb_configure (vm, vnm, ntohl (mp->sw_if_index), vtr_op,
4448                         mp->b_dmac, mp->b_smac, ntohs (mp->b_vlanid),
4449                         ntohl (mp->i_sid), ntohs (mp->outer_tag));
4450
4451   BAD_SW_IF_INDEX_LABEL;
4452
4453   REPLY_MACRO (VL_API_L2_INTERFACE_PBB_TAG_REWRITE_REPLY);
4454
4455 }
4456
4457 static void
4458 vl_api_punt_t_handler (vl_api_punt_t * mp)
4459 {
4460   vl_api_punt_reply_t *rmp;
4461   vlib_main_t *vm = vlib_get_main ();
4462   int rv = 0;
4463   clib_error_t *error;
4464
4465   error = vnet_punt_add_del (vm, mp->ipv, mp->l4_protocol,
4466                              ntohs (mp->l4_port), mp->is_add);
4467   if (error)
4468     {
4469       rv = -1;
4470       clib_error_report (error);
4471     }
4472
4473   REPLY_MACRO (VL_API_PUNT_REPLY);
4474 }
4475
4476 static void
4477   vl_api_flow_classify_set_interface_t_handler
4478   (vl_api_flow_classify_set_interface_t * mp)
4479 {
4480   vlib_main_t *vm = vlib_get_main ();
4481   vl_api_flow_classify_set_interface_reply_t *rmp;
4482   int rv;
4483   u32 sw_if_index, ip4_table_index, ip6_table_index;
4484
4485   ip4_table_index = ntohl (mp->ip4_table_index);
4486   ip6_table_index = ntohl (mp->ip6_table_index);
4487   sw_if_index = ntohl (mp->sw_if_index);
4488
4489   VALIDATE_SW_IF_INDEX (mp);
4490
4491   rv = vnet_set_flow_classify_intfc (vm, sw_if_index, ip4_table_index,
4492                                      ip6_table_index, mp->is_add);
4493
4494   BAD_SW_IF_INDEX_LABEL;
4495
4496   REPLY_MACRO (VL_API_FLOW_CLASSIFY_SET_INTERFACE_REPLY);
4497 }
4498
4499 static void
4500 send_flow_classify_details (u32 sw_if_index,
4501                             u32 table_index,
4502                             unix_shared_memory_queue_t * q, u32 context)
4503 {
4504   vl_api_flow_classify_details_t *mp;
4505
4506   mp = vl_msg_api_alloc (sizeof (*mp));
4507   memset (mp, 0, sizeof (*mp));
4508   mp->_vl_msg_id = ntohs (VL_API_FLOW_CLASSIFY_DETAILS);
4509   mp->context = context;
4510   mp->sw_if_index = htonl (sw_if_index);
4511   mp->table_index = htonl (table_index);
4512
4513   vl_msg_api_send_shmem (q, (u8 *) & mp);
4514 }
4515
4516 static void
4517 vl_api_flow_classify_dump_t_handler (vl_api_flow_classify_dump_t * mp)
4518 {
4519   unix_shared_memory_queue_t *q;
4520   flow_classify_main_t *pcm = &flow_classify_main;
4521   u32 *vec_tbl;
4522   int i;
4523
4524   q = vl_api_client_index_to_input_queue (mp->client_index);
4525   if (q == 0)
4526     return;
4527
4528   vec_tbl = pcm->classify_table_index_by_sw_if_index[mp->type];
4529
4530   if (vec_len (vec_tbl))
4531     {
4532       for (i = 0; i < vec_len (vec_tbl); i++)
4533         {
4534           if (vec_elt (vec_tbl, i) == ~0)
4535             continue;
4536
4537           send_flow_classify_details (i, vec_elt (vec_tbl, i), q,
4538                                       mp->context);
4539         }
4540     }
4541 }
4542
4543 static void
4544 vl_api_feature_enable_disable_t_handler (vl_api_feature_enable_disable_t * mp)
4545 {
4546   vl_api_feature_enable_disable_reply_t *rmp;
4547   int rv = 0;
4548   u8 *arc_name, *feature_name;
4549
4550   VALIDATE_SW_IF_INDEX (mp);
4551
4552   arc_name = format (0, "%s%c", mp->arc_name, 0);
4553   feature_name = format (0, "%s%c", mp->feature_name, 0);
4554
4555   vnet_feature_registration_t *reg;
4556   reg =
4557     vnet_get_feature_reg ((const char *) arc_name,
4558                           (const char *) feature_name);
4559   if (reg == 0)
4560     rv = VNET_API_ERROR_INVALID_VALUE;
4561   else
4562     {
4563       u32 sw_if_index;
4564       clib_error_t *error = 0;
4565
4566       sw_if_index = ntohl (mp->sw_if_index);
4567       if (reg->enable_disable_cb)
4568         error = reg->enable_disable_cb (sw_if_index, mp->enable);
4569       if (!error)
4570         vnet_feature_enable_disable ((const char *) arc_name,
4571                                      (const char *) feature_name,
4572                                      sw_if_index, mp->enable, 0, 0);
4573       else
4574         {
4575           clib_error_report (error);
4576           rv = VNET_API_ERROR_CANNOT_ENABLE_DISABLE_FEATURE;
4577         }
4578     }
4579
4580   vec_free (feature_name);
4581   vec_free (arc_name);
4582
4583   BAD_SW_IF_INDEX_LABEL;
4584
4585   REPLY_MACRO (VL_API_FEATURE_ENABLE_DISABLE_REPLY);
4586 }
4587
4588 #define BOUNCE_HANDLER(nn)                                              \
4589 static void vl_api_##nn##_t_handler (                                   \
4590     vl_api_##nn##_t *mp)                                                \
4591 {                                                                       \
4592     vpe_client_registration_t *reg;                                     \
4593     vpe_api_main_t * vam = &vpe_api_main;                               \
4594     unix_shared_memory_queue_t * q;                                     \
4595                                                                         \
4596     /* One registration only... */                                      \
4597     pool_foreach(reg, vam->nn##_registrations,                          \
4598     ({                                                                  \
4599         q = vl_api_client_index_to_input_queue (reg->client_index);     \
4600         if (q) {                                                        \
4601             /*                                                          \
4602              * If the queue is stuffed, turf the msg and complain       \
4603              * It's unlikely that the intended recipient is             \
4604              * alive; avoid deadlock at all costs.                      \
4605              */                                                         \
4606             if (q->cursize == q->maxsize) {                             \
4607                 clib_warning ("ERROR: receiver queue full, drop msg");  \
4608                 vl_msg_api_free (mp);                                   \
4609                 return;                                                 \
4610             }                                                           \
4611             vl_msg_api_send_shmem (q, (u8 *)&mp);                       \
4612             return;                                                     \
4613         }                                                               \
4614     }));                                                                \
4615     vl_msg_api_free (mp);                                               \
4616 }
4617
4618 static void setup_message_id_table (api_main_t * am);
4619
4620 /*
4621  * vpe_api_hookup
4622  * Add vpe's API message handlers to the table.
4623  * vlib has alread mapped shared memory and
4624  * added the client registration handlers.
4625  * See .../open-repo/vlib/memclnt_vlib.c:memclnt_process()
4626  */
4627 static clib_error_t *
4628 vpe_api_hookup (vlib_main_t * vm)
4629 {
4630   api_main_t *am = &api_main;
4631
4632 #define _(N,n)                                                  \
4633     vl_msg_api_set_handlers(VL_API_##N, #n,                     \
4634                            vl_api_##n##_t_handler,              \
4635                            vl_noop_handler,                     \
4636                            vl_api_##n##_t_endian,               \
4637                            vl_api_##n##_t_print,                \
4638                            sizeof(vl_api_##n##_t), 1);
4639   foreach_vpe_api_msg;
4640 #undef _
4641
4642   /*
4643    * Manually register the sr tunnel add del msg, so we trace
4644    * enough bytes to capture a typical segment list
4645    */
4646   vl_msg_api_set_handlers (VL_API_SR_TUNNEL_ADD_DEL,
4647                            "sr_tunnel_add_del",
4648                            vl_api_sr_tunnel_add_del_t_handler,
4649                            vl_noop_handler,
4650                            vl_api_sr_tunnel_add_del_t_endian,
4651                            vl_api_sr_tunnel_add_del_t_print, 256, 1);
4652
4653
4654   /*
4655    * Manually register the sr policy add del msg, so we trace
4656    * enough bytes to capture a typical tunnel name list
4657    */
4658   vl_msg_api_set_handlers (VL_API_SR_POLICY_ADD_DEL,
4659                            "sr_policy_add_del",
4660                            vl_api_sr_policy_add_del_t_handler,
4661                            vl_noop_handler,
4662                            vl_api_sr_policy_add_del_t_endian,
4663                            vl_api_sr_policy_add_del_t_print, 256, 1);
4664
4665   /*
4666    * Trace space for 8 MPLS encap labels, classifier mask+match
4667    */
4668   am->api_trace_cfg[VL_API_MPLS_TUNNEL_ADD_DEL].size += 8 * sizeof (u32);
4669   am->api_trace_cfg[VL_API_CLASSIFY_ADD_DEL_TABLE].size += 5 * sizeof (u32x4);
4670   am->api_trace_cfg[VL_API_CLASSIFY_ADD_DEL_SESSION].size
4671     += 5 * sizeof (u32x4);
4672   am->api_trace_cfg[VL_API_VXLAN_ADD_DEL_TUNNEL].size += 16 * sizeof (u32);
4673
4674   /*
4675    * Thread-safe API messages
4676    */
4677   am->is_mp_safe[VL_API_IP_ADD_DEL_ROUTE] = 1;
4678   am->is_mp_safe[VL_API_GET_NODE_GRAPH] = 1;
4679
4680   /*
4681    * Set up the (msg_name, crc, message-id) table
4682    */
4683   setup_message_id_table (am);
4684
4685   return 0;
4686 }
4687
4688 VLIB_API_INIT_FUNCTION (vpe_api_hookup);
4689
4690 static clib_error_t *
4691 vpe_api_init (vlib_main_t * vm)
4692 {
4693   vpe_api_main_t *am = &vpe_api_main;
4694
4695   am->vlib_main = vm;
4696   am->vnet_main = vnet_get_main ();
4697   am->interface_events_registration_hash = hash_create (0, sizeof (uword));
4698   am->to_netconf_server_registration_hash = hash_create (0, sizeof (uword));
4699   am->from_netconf_server_registration_hash = hash_create (0, sizeof (uword));
4700   am->to_netconf_client_registration_hash = hash_create (0, sizeof (uword));
4701   am->from_netconf_client_registration_hash = hash_create (0, sizeof (uword));
4702   am->oam_events_registration_hash = hash_create (0, sizeof (uword));
4703   am->bfd_events_registration_hash = hash_create (0, sizeof (uword));
4704
4705   vl_api_init (vm);
4706   vl_set_memory_region_name ("/vpe-api");
4707   vl_enable_disable_memory_api (vm, 1 /* enable it */ );
4708
4709   return 0;
4710 }
4711
4712 VLIB_INIT_FUNCTION (vpe_api_init);
4713
4714
4715 static clib_error_t *
4716 api_segment_config (vlib_main_t * vm, unformat_input_t * input)
4717 {
4718   u8 *chroot_path;
4719   u64 baseva, size, pvt_heap_size;
4720   int uid, gid, rv;
4721   const int max_buf_size = 4096;
4722   char *s, *buf;
4723   struct passwd _pw, *pw;
4724   struct group _grp, *grp;
4725   clib_error_t *e;
4726   buf = vec_new (char, 128);
4727   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
4728     {
4729       if (unformat (input, "prefix %s", &chroot_path))
4730         {
4731           vec_add1 (chroot_path, 0);
4732           vl_set_memory_root_path ((char *) chroot_path);
4733         }
4734       else if (unformat (input, "uid %d", &uid))
4735         vl_set_memory_uid (uid);
4736       else if (unformat (input, "gid %d", &gid))
4737         vl_set_memory_gid (gid);
4738       else if (unformat (input, "baseva %llx", &baseva))
4739         vl_set_global_memory_baseva (baseva);
4740       else if (unformat (input, "global-size %lldM", &size))
4741         vl_set_global_memory_size (size * (1ULL << 20));
4742       else if (unformat (input, "global-size %lldG", &size))
4743         vl_set_global_memory_size (size * (1ULL << 30));
4744       else if (unformat (input, "global-size %lld", &size))
4745         vl_set_global_memory_size (size);
4746       else if (unformat (input, "global-pvt-heap-size %lldM", &pvt_heap_size))
4747         vl_set_global_pvt_heap_size (pvt_heap_size * (1ULL << 20));
4748       else if (unformat (input, "global-pvt-heap-size size %lld",
4749                          &pvt_heap_size))
4750         vl_set_global_pvt_heap_size (pvt_heap_size);
4751       else if (unformat (input, "api-pvt-heap-size %lldM", &pvt_heap_size))
4752         vl_set_api_pvt_heap_size (pvt_heap_size * (1ULL << 20));
4753       else if (unformat (input, "api-pvt-heap-size size %lld",
4754                          &pvt_heap_size))
4755         vl_set_api_pvt_heap_size (pvt_heap_size);
4756       else if (unformat (input, "api-size %lldM", &size))
4757         vl_set_api_memory_size (size * (1ULL << 20));
4758       else if (unformat (input, "api-size %lldG", &size))
4759         vl_set_api_memory_size (size * (1ULL << 30));
4760       else if (unformat (input, "api-size %lld", &size))
4761         vl_set_api_memory_size (size);
4762       else if (unformat (input, "uid %s", &s))
4763         {
4764           /* lookup the username */
4765           pw = NULL;
4766           while (((rv =
4767                    getpwnam_r (s, &_pw, buf, vec_len (buf), &pw)) == ERANGE)
4768                  && (vec_len (buf) <= max_buf_size))
4769             {
4770               vec_resize (buf, vec_len (buf) * 2);
4771             }
4772           if (rv < 0)
4773             {
4774               e = clib_error_return_code (0, rv,
4775                                           CLIB_ERROR_ERRNO_VALID |
4776                                           CLIB_ERROR_FATAL,
4777                                           "cannot fetch username %s", s);
4778               vec_free (s);
4779               vec_free (buf);
4780               return e;
4781             }
4782           if (pw == NULL)
4783             {
4784               e =
4785                 clib_error_return_fatal (0, "username %s does not exist", s);
4786               vec_free (s);
4787               vec_free (buf);
4788               return e;
4789             }
4790           vec_free (s);
4791           vl_set_memory_uid (pw->pw_uid);
4792         }
4793       else if (unformat (input, "gid %s", &s))
4794         {
4795           /* lookup the group name */
4796           grp = NULL;
4797           while (((rv =
4798                    getgrnam_r (s, &_grp, buf, vec_len (buf), &grp)) == ERANGE)
4799                  && (vec_len (buf) <= max_buf_size))
4800             {
4801               vec_resize (buf, vec_len (buf) * 2);
4802             }
4803           if (rv != 0)
4804             {
4805               e = clib_error_return_code (0, rv,
4806                                           CLIB_ERROR_ERRNO_VALID |
4807                                           CLIB_ERROR_FATAL,
4808                                           "cannot fetch group %s", s);
4809               vec_free (s);
4810               vec_free (buf);
4811               return e;
4812             }
4813           if (grp == NULL)
4814             {
4815               e = clib_error_return_fatal (0, "group %s does not exist", s);
4816               vec_free (s);
4817               vec_free (buf);
4818               return e;
4819             }
4820           vec_free (s);
4821           vec_free (buf);
4822           vl_set_memory_gid (grp->gr_gid);
4823         }
4824       else
4825         return clib_error_return (0, "unknown input `%U'",
4826                                   format_unformat_error, input);
4827     }
4828   return 0;
4829 }
4830
4831 VLIB_EARLY_CONFIG_FUNCTION (api_segment_config, "api-segment");
4832
4833 void *
4834 get_unformat_vnet_sw_interface (void)
4835 {
4836   return (void *) &unformat_vnet_sw_interface;
4837 }
4838
4839 static u8 *
4840 format_arp_event (u8 * s, va_list * args)
4841 {
4842   vl_api_ip4_arp_event_t *event = va_arg (*args, vl_api_ip4_arp_event_t *);
4843
4844   s = format (s, "pid %d: ", event->pid);
4845   if (event->mac_ip)
4846     s = format (s, "bd mac/ip4 binding events");
4847   else
4848     s = format (s, "resolution for %U", format_ip4_address, &event->address);
4849   return s;
4850 }
4851
4852 static u8 *
4853 format_nd_event (u8 * s, va_list * args)
4854 {
4855   vl_api_ip6_nd_event_t *event = va_arg (*args, vl_api_ip6_nd_event_t *);
4856
4857   s = format (s, "pid %d: ", event->pid);
4858   if (event->mac_ip)
4859     s = format (s, "bd mac/ip6 binding events");
4860   else
4861     s = format (s, "resolution for %U", format_ip6_address, event->address);
4862   return s;
4863 }
4864
4865 static clib_error_t *
4866 show_ip_arp_nd_events_fn (vlib_main_t * vm,
4867                           unformat_input_t * input, vlib_cli_command_t * cmd)
4868 {
4869   vpe_api_main_t *am = &vpe_api_main;
4870   vl_api_ip4_arp_event_t *arp_event;
4871   vl_api_ip6_nd_event_t *nd_event;
4872
4873   if ((pool_elts (am->arp_events) == 0) && (pool_elts (am->nd_events) == 0))
4874     {
4875       vlib_cli_output (vm, "No active arp or nd event registrations");
4876       return 0;
4877     }
4878
4879   /* *INDENT-OFF* */
4880   pool_foreach (arp_event, am->arp_events,
4881   ({
4882     vlib_cli_output (vm, "%U", format_arp_event, arp_event);
4883   }));
4884
4885   pool_foreach (nd_event, am->nd_events,
4886   ({
4887     vlib_cli_output (vm, "%U", format_nd_event, nd_event);
4888   }));
4889   /* *INDENT-ON* */
4890
4891   return 0;
4892 }
4893
4894 /* *INDENT-OFF* */
4895 VLIB_CLI_COMMAND (show_ip_arp_nd_events, static) = {
4896   .path = "show arp-nd-event registrations",
4897   .function = show_ip_arp_nd_events_fn,
4898   .short_help = "Show ip4 arp and ip6 nd event registrations",
4899 };
4900 /* *INDENT-ON* */
4901
4902 #define vl_msg_name_crc_list
4903 #include <vpp/api/vpe_all_api_h.h>
4904 #undef vl_msg_name_crc_list
4905
4906 static void
4907 setup_message_id_table (api_main_t * am)
4908 {
4909 #define _(id,n,crc) vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id);
4910   foreach_vl_msg_name_crc_memclnt;
4911   foreach_vl_msg_name_crc_vpe;
4912 #undef _
4913 }
4914
4915
4916 /*
4917  * fd.io coding-style-patch-verification: ON
4918  *
4919  * Local Variables:
4920  * eval: (c-set-style "gnu")
4921  * End:
4922  */