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