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