API refactoring : netmap
[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/l2tp/l2tp.h>
53 #include <vnet/ip/ip.h>
54 #include <vnet/ip/ip6.h>
55 #include <vnet/ip/ip6_neighbor.h>
56 #include <vnet/mpls/mpls.h>
57 #include <vnet/mpls/mpls_tunnel.h>
58 #include <vnet/dhcp/proxy.h>
59 #include <vnet/dhcp/client.h>
60 #if IPV6SR > 0
61 #include <vnet/sr/sr.h>
62 #endif
63 #include <vnet/dhcpv6/proxy.h>
64 #include <vlib/vlib.h>
65 #include <vlib/unix/unix.h>
66 #include <vlibapi/api.h>
67 #include <vlibmemory/api.h>
68 #include <vnet/classify/vnet_classify.h>
69 #include <vnet/classify/input_acl.h>
70 #include <vnet/classify/policer_classify.h>
71 #include <vnet/classify/flow_classify.h>
72 #include <vnet/l2/l2_classify.h>
73 #include <vnet/vxlan/vxlan.h>
74 #include <vnet/gre/gre.h>
75 #include <vnet/l2/l2_vtr.h>
76 #include <vnet/vxlan-gpe/vxlan_gpe.h>
77 #include <vnet/lisp-gpe/lisp_gpe.h>
78 #include <vnet/lisp-gpe/lisp_gpe_fwd_entry.h>
79 #include <vnet/lisp-gpe/lisp_gpe_tenant.h>
80 #include <vnet/lisp-cp/control.h>
81 #include <vnet/map/map.h>
82 #include <vnet/cop/cop.h>
83 #include <vnet/ip/ip6_hop_by_hop.h>
84 #include <vnet/ip/ip_source_and_port_range_check.h>
85 #include <vnet/policer/policer.h>
86 #include <vnet/flow/flow_report.h>
87 #include <vnet/ipsec-gre/ipsec_gre.h>
88 #include <vnet/flow/flow_report_classify.h>
89 #include <vnet/ip/punt.h>
90 #include <vnet/feature/feature.h>
91
92 #undef BIHASH_TYPE
93 #undef __included_bihash_template_h__
94 #include <vnet/l2/l2_fib.h>
95
96 #if DPDK > 0
97 #include <vnet/devices/dpdk/dpdk.h>
98 #endif
99
100 #if IPSEC > 0
101 #include <vnet/ipsec/ipsec.h>
102 #include <vnet/ipsec/ikev2.h>
103 #endif /* IPSEC */
104 #include <vnet/devices/virtio/vhost-user.h>
105
106 #include <stats/stats.h>
107 #include <oam/oam.h>
108
109 #include <vnet/ethernet/ethernet.h>
110 #include <vnet/ethernet/arp_packet.h>
111 #include <vnet/interface.h>
112
113 #include <vnet/l2/l2_fib.h>
114 #include <vnet/l2/l2_bd.h>
115 #include <vpp-api/vpe_msg_enum.h>
116 #include <vnet/span/span.h>
117
118 #include <vnet/bfd/bfd_main.h>
119 #include <vnet/bfd/bfd_api.h>
120 #include <vnet/fib/ip6_fib.h>
121 #include <vnet/fib/ip4_fib.h>
122 #include <vnet/fib/fib_api.h>
123 #include <vnet/dpo/drop_dpo.h>
124 #include <vnet/dpo/receive_dpo.h>
125 #include <vnet/dpo/lookup_dpo.h>
126 #include <vnet/dpo/classify_dpo.h>
127 #include <vnet/dpo/ip_null_dpo.h>
128
129 #define vl_typedefs             /* define message structures */
130 #include <vpp-api/vpe_all_api_h.h>
131 #undef vl_typedefs
132
133 #define vl_endianfun            /* define message structures */
134 #include <vpp-api/vpe_all_api_h.h>
135 #undef vl_endianfun
136
137 /* instantiate all the print functions we know about */
138 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
139 #define vl_printfun
140 #include <vpp-api/vpe_all_api_h.h>
141 #undef vl_printfun
142
143 #include <vlibapi/api_helper_macros.h>
144
145 #define foreach_vpe_api_msg                                             \
146 _(WANT_OAM_EVENTS, want_oam_events)                                     \
147 _(OAM_ADD_DEL, oam_add_del)                                             \
148 _(MPLS_ROUTE_ADD_DEL, mpls_route_add_del)                               \
149 _(MPLS_IP_BIND_UNBIND, mpls_ip_bind_unbind)                             \
150 _(IS_ADDRESS_REACHABLE, is_address_reachable)                           \
151 _(SW_INTERFACE_SET_MPLS_ENABLE, sw_interface_set_mpls_enable)           \
152 _(SW_INTERFACE_SET_VPATH, sw_interface_set_vpath)                       \
153 _(SW_INTERFACE_SET_VXLAN_BYPASS, sw_interface_set_vxlan_bypass)         \
154 _(SW_INTERFACE_SET_L2_XCONNECT, sw_interface_set_l2_xconnect)           \
155 _(SW_INTERFACE_SET_L2_BRIDGE, sw_interface_set_l2_bridge)               \
156 _(SW_INTERFACE_SET_DPDK_HQOS_PIPE, sw_interface_set_dpdk_hqos_pipe)     \
157 _(SW_INTERFACE_SET_DPDK_HQOS_SUBPORT, sw_interface_set_dpdk_hqos_subport) \
158 _(SW_INTERFACE_SET_DPDK_HQOS_TCTBL, sw_interface_set_dpdk_hqos_tctbl)   \
159 _(BRIDGE_DOMAIN_ADD_DEL, bridge_domain_add_del)                         \
160 _(BRIDGE_DOMAIN_DUMP, bridge_domain_dump)                               \
161 _(BRIDGE_DOMAIN_DETAILS, bridge_domain_details)                         \
162 _(BRIDGE_DOMAIN_SW_IF_DETAILS, bridge_domain_sw_if_details)             \
163 _(L2FIB_ADD_DEL, l2fib_add_del)                                         \
164 _(L2_FLAGS, l2_flags)                                                   \
165 _(BRIDGE_FLAGS, bridge_flags)                                           \
166 _(CREATE_VLAN_SUBIF, create_vlan_subif)                                 \
167 _(CREATE_SUBIF, create_subif)                                           \
168 _(MPLS_TUNNEL_ADD_DEL, mpls_tunnel_add_del)                             \
169 _(PROXY_ARP_ADD_DEL, proxy_arp_add_del)                                 \
170 _(PROXY_ARP_INTFC_ENABLE_DISABLE, proxy_arp_intfc_enable_disable)       \
171 _(VNET_GET_SUMMARY_STATS, vnet_get_summary_stats)                       \
172 _(RESET_FIB, reset_fib)                                                 \
173 _(DHCP_PROXY_CONFIG,dhcp_proxy_config)                                  \
174 _(DHCP_PROXY_CONFIG_2,dhcp_proxy_config_2)                              \
175 _(DHCP_PROXY_SET_VSS,dhcp_proxy_set_vss)                                \
176 _(DHCP_CLIENT_CONFIG, dhcp_client_config)                               \
177 _(CREATE_LOOPBACK, create_loopback)                                     \
178 _(CONTROL_PING, control_ping)                                           \
179 _(CLI_REQUEST, cli_request)                                             \
180 _(CLI_INBAND, cli_inband)                                               \
181 _(SET_ARP_NEIGHBOR_LIMIT, set_arp_neighbor_limit)                       \
182 _(L2_PATCH_ADD_DEL, l2_patch_add_del)                                   \
183 _(CLASSIFY_ADD_DEL_TABLE, classify_add_del_table)                       \
184 _(CLASSIFY_ADD_DEL_SESSION, classify_add_del_session)                   \
185 _(CLASSIFY_SET_INTERFACE_IP_TABLE, classify_set_interface_ip_table)     \
186 _(CLASSIFY_SET_INTERFACE_L2_TABLES, classify_set_interface_l2_tables)   \
187 _(GET_NODE_INDEX, get_node_index)                                       \
188 _(ADD_NODE_NEXT, add_node_next)                                         \
189 _(L2TPV3_CREATE_TUNNEL, l2tpv3_create_tunnel)                           \
190 _(L2TPV3_SET_TUNNEL_COOKIES, l2tpv3_set_tunnel_cookies)                 \
191 _(L2TPV3_INTERFACE_ENABLE_DISABLE, l2tpv3_interface_enable_disable)     \
192 _(L2TPV3_SET_LOOKUP_KEY, l2tpv3_set_lookup_key)                         \
193 _(SW_IF_L2TPV3_TUNNEL_DUMP, sw_if_l2tpv3_tunnel_dump)                   \
194 _(VXLAN_ADD_DEL_TUNNEL, vxlan_add_del_tunnel)                           \
195 _(VXLAN_TUNNEL_DUMP, vxlan_tunnel_dump)                                 \
196 _(GRE_ADD_DEL_TUNNEL, gre_add_del_tunnel)                               \
197 _(GRE_TUNNEL_DUMP, gre_tunnel_dump)                                     \
198 _(L2_FIB_CLEAR_TABLE, l2_fib_clear_table)                               \
199 _(L2_INTERFACE_EFP_FILTER, l2_interface_efp_filter)                     \
200 _(L2_INTERFACE_VLAN_TAG_REWRITE, l2_interface_vlan_tag_rewrite)         \
201 _(CREATE_VHOST_USER_IF, create_vhost_user_if)                           \
202 _(MODIFY_VHOST_USER_IF, modify_vhost_user_if)                           \
203 _(DELETE_VHOST_USER_IF, delete_vhost_user_if)                           \
204 _(SW_INTERFACE_VHOST_USER_DUMP, sw_interface_vhost_user_dump)           \
205 _(SW_INTERFACE_VHOST_USER_DETAILS, sw_interface_vhost_user_details)     \
206 _(SHOW_VERSION, show_version)                                           \
207 _(L2_FIB_TABLE_DUMP, l2_fib_table_dump)                                 \
208 _(L2_FIB_TABLE_ENTRY, l2_fib_table_entry)                               \
209 _(VXLAN_GPE_ADD_DEL_TUNNEL, vxlan_gpe_add_del_tunnel)                   \
210 _(VXLAN_GPE_TUNNEL_DUMP, vxlan_gpe_tunnel_dump)                         \
211 _(INTERFACE_NAME_RENUMBER, interface_name_renumber)                     \
212 _(WANT_IP4_ARP_EVENTS, want_ip4_arp_events)                             \
213 _(WANT_IP6_ND_EVENTS, want_ip6_nd_events)                               \
214 _(INPUT_ACL_SET_INTERFACE, input_acl_set_interface)                     \
215 _(IPSEC_SPD_ADD_DEL, ipsec_spd_add_del)                                 \
216 _(IPSEC_INTERFACE_ADD_DEL_SPD, ipsec_interface_add_del_spd)             \
217 _(IPSEC_SPD_ADD_DEL_ENTRY, ipsec_spd_add_del_entry)                     \
218 _(IPSEC_SAD_ADD_DEL_ENTRY, ipsec_sad_add_del_entry)                     \
219 _(IPSEC_SA_SET_KEY, ipsec_sa_set_key)                                   \
220 _(IKEV2_PROFILE_ADD_DEL, ikev2_profile_add_del)                         \
221 _(IKEV2_PROFILE_SET_AUTH, ikev2_profile_set_auth)                       \
222 _(IKEV2_PROFILE_SET_ID, ikev2_profile_set_id)                           \
223 _(IKEV2_PROFILE_SET_TS, ikev2_profile_set_ts)                           \
224 _(IKEV2_SET_LOCAL_KEY, ikev2_set_local_key)                             \
225 _(DELETE_LOOPBACK, delete_loopback)                                     \
226 _(BD_IP_MAC_ADD_DEL, bd_ip_mac_add_del)                                 \
227 _(COP_INTERFACE_ENABLE_DISABLE, cop_interface_enable_disable)           \
228 _(COP_WHITELIST_ENABLE_DISABLE, cop_whitelist_enable_disable)           \
229 _(GET_NODE_GRAPH, get_node_graph)                                       \
230 _(IOAM_ENABLE, ioam_enable)                                             \
231 _(IOAM_DISABLE, ioam_disable)                                           \
232 _(LISP_ADD_DEL_LOCATOR_SET, lisp_add_del_locator_set)                   \
233 _(LISP_ADD_DEL_LOCATOR, lisp_add_del_locator)                           \
234 _(LISP_ADD_DEL_LOCAL_EID, lisp_add_del_local_eid)                       \
235 _(LISP_GPE_ADD_DEL_FWD_ENTRY, lisp_gpe_add_del_fwd_entry)               \
236 _(LISP_ADD_DEL_MAP_RESOLVER, lisp_add_del_map_resolver)                 \
237 _(LISP_ADD_DEL_MAP_SERVER, lisp_add_del_map_server)                     \
238 _(LISP_GPE_ENABLE_DISABLE, lisp_gpe_enable_disable)                     \
239 _(LISP_ENABLE_DISABLE, lisp_enable_disable)                             \
240 _(LISP_RLOC_PROBE_ENABLE_DISABLE, lisp_rloc_probe_enable_disable)       \
241 _(LISP_MAP_REGISTER_ENABLE_DISABLE, lisp_map_register_enable_disable)   \
242 _(LISP_GPE_ADD_DEL_IFACE, lisp_gpe_add_del_iface)                       \
243 _(LISP_ADD_DEL_REMOTE_MAPPING, lisp_add_del_remote_mapping)             \
244 _(LISP_ADD_DEL_ADJACENCY, lisp_add_del_adjacency)                       \
245 _(LISP_PITR_SET_LOCATOR_SET, lisp_pitr_set_locator_set)                 \
246 _(LISP_MAP_REQUEST_MODE, lisp_map_request_mode)                         \
247 _(LISP_EID_TABLE_ADD_DEL_MAP, lisp_eid_table_add_del_map)               \
248 _(LISP_LOCATOR_SET_DUMP, lisp_locator_set_dump)                         \
249 _(LISP_LOCATOR_DUMP, lisp_locator_dump)                                 \
250 _(LISP_EID_TABLE_DUMP, lisp_eid_table_dump)                             \
251 _(LISP_GPE_TUNNEL_DUMP, lisp_gpe_tunnel_dump)                           \
252 _(LISP_MAP_RESOLVER_DUMP, lisp_map_resolver_dump)                       \
253 _(LISP_MAP_SERVER_DUMP, lisp_map_server_dump)                           \
254 _(LISP_EID_TABLE_MAP_DUMP, lisp_eid_table_map_dump)                     \
255 _(LISP_EID_TABLE_VNI_DUMP, lisp_eid_table_vni_dump)                     \
256 _(LISP_ADJACENCIES_GET, lisp_adjacencies_get)                           \
257 _(SHOW_LISP_RLOC_PROBE_STATE, show_lisp_rloc_probe_state)               \
258 _(SHOW_LISP_MAP_REGISTER_STATE, show_lisp_map_register_state)           \
259 _(SHOW_LISP_STATUS, show_lisp_status)                                   \
260 _(LISP_ADD_DEL_MAP_REQUEST_ITR_RLOCS,                                   \
261   lisp_add_del_map_request_itr_rlocs)                                   \
262 _(LISP_GET_MAP_REQUEST_ITR_RLOCS, lisp_get_map_request_itr_rlocs)       \
263 _(SHOW_LISP_PITR, show_lisp_pitr)                                       \
264 _(SHOW_LISP_MAP_REQUEST_MODE, show_lisp_map_request_mode)               \
265 _(SR_MULTICAST_MAP_ADD_DEL, sr_multicast_map_add_del)                   \
266 _(POLICER_ADD_DEL, policer_add_del)                                     \
267 _(POLICER_DUMP, policer_dump)                                           \
268 _(POLICER_CLASSIFY_SET_INTERFACE, policer_classify_set_interface)       \
269 _(POLICER_CLASSIFY_DUMP, policer_classify_dump)                         \
270 _(MPLS_TUNNEL_DUMP, mpls_tunnel_dump)                                   \
271 _(MPLS_TUNNEL_DETAILS, mpls_tunnel_details)                             \
272 _(MPLS_FIB_DUMP, mpls_fib_dump)                                         \
273 _(MPLS_FIB_DETAILS, mpls_fib_details)                                   \
274 _(CLASSIFY_TABLE_IDS,classify_table_ids)                                \
275 _(CLASSIFY_TABLE_BY_INTERFACE, classify_table_by_interface)             \
276 _(CLASSIFY_TABLE_INFO,classify_table_info)                              \
277 _(CLASSIFY_SESSION_DUMP,classify_session_dump)                          \
278 _(CLASSIFY_SESSION_DETAILS,classify_session_details)                    \
279 _(SET_IPFIX_EXPORTER, set_ipfix_exporter)                               \
280 _(IPFIX_EXPORTER_DUMP, ipfix_exporter_dump)                             \
281 _(SET_IPFIX_CLASSIFY_STREAM, set_ipfix_classify_stream)                 \
282 _(IPFIX_CLASSIFY_STREAM_DUMP, ipfix_classify_stream_dump)               \
283 _(IPFIX_CLASSIFY_TABLE_ADD_DEL, ipfix_classify_table_add_del)           \
284 _(IPFIX_CLASSIFY_TABLE_DUMP, ipfix_classify_table_dump)                 \
285 _(GET_NEXT_INDEX, get_next_index)                                       \
286 _(PG_CREATE_INTERFACE, pg_create_interface)                             \
287 _(PG_CAPTURE, pg_capture)                                               \
288 _(PG_ENABLE_DISABLE, pg_enable_disable)                                 \
289 _(IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL,                               \
290   ip_source_and_port_range_check_add_del)                               \
291 _(IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL,                     \
292   ip_source_and_port_range_check_interface_add_del)                     \
293 _(IPSEC_GRE_ADD_DEL_TUNNEL, ipsec_gre_add_del_tunnel)                   \
294 _(IPSEC_GRE_TUNNEL_DUMP, ipsec_gre_tunnel_dump)                         \
295 _(DELETE_SUBIF, delete_subif)                                           \
296 _(L2_INTERFACE_PBB_TAG_REWRITE, l2_interface_pbb_tag_rewrite)           \
297 _(PUNT, punt)                                                           \
298 _(FLOW_CLASSIFY_SET_INTERFACE, flow_classify_set_interface)             \
299 _(FLOW_CLASSIFY_DUMP, flow_classify_dump)                               \
300 _(IPSEC_SPD_DUMP, ipsec_spd_dump)                                       \
301 _(FEATURE_ENABLE_DISABLE, feature_enable_disable)                       \
302 _(BFD_UDP_ADD, bfd_udp_add)                                             \
303 _(BFD_UDP_DEL, bfd_udp_del)                                             \
304 _(BFD_UDP_SESSION_DUMP, bfd_udp_session_dump)                           \
305 _(BFD_SESSION_SET_FLAGS, bfd_session_set_flags)                         \
306 _(WANT_BFD_EVENTS, want_bfd_events)
307
308 #define QUOTE_(x) #x
309 #define QUOTE(x) QUOTE_(x)
310
311 typedef enum
312 {
313   RESOLVE_IP4_ADD_DEL_ROUTE = 1,
314   RESOLVE_IP6_ADD_DEL_ROUTE,
315 } resolve_t;
316
317 static vlib_node_registration_t vpe_resolver_process_node;
318 vpe_api_main_t vpe_api_main;
319
320 static int arp_change_delete_callback (u32 pool_index, u8 * notused);
321 static int nd_change_delete_callback (u32 pool_index, u8 * notused);
322
323 /* Clean up all registrations belonging to the indicated client */
324 int
325 vl_api_memclnt_delete_callback (u32 client_index)
326 {
327   vpe_api_main_t *vam = &vpe_api_main;
328   vpe_client_registration_t *rp;
329   uword *p;
330   int stats_memclnt_delete_callback (u32 client_index);
331
332   stats_memclnt_delete_callback (client_index);
333
334 #define _(a)                                                    \
335     p = hash_get (vam->a##_registration_hash, client_index);    \
336     if (p) {                                                    \
337         rp = pool_elt_at_index (vam->a##_registrations, p[0]);  \
338         pool_put (vam->a##_registrations, rp);                  \
339         hash_unset (vam->a##_registration_hash, client_index);  \
340     }
341   foreach_registration_hash;
342 #undef _
343   return 0;
344 }
345
346 pub_sub_handler (oam_events, OAM_EVENTS);
347 pub_sub_handler (bfd_events, BFD_EVENTS);
348
349 #define RESOLUTION_EVENT 1
350 #define RESOLUTION_PENDING_EVENT 2
351 #define IP4_ARP_EVENT 3
352 #define IP6_ND_EVENT 4
353
354 int ip4_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp);
355
356 int ip6_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp);
357
358 void
359 handle_ip4_arp_event (u32 pool_index)
360 {
361   vpe_api_main_t *vam = &vpe_api_main;
362   vnet_main_t *vnm = vam->vnet_main;
363   vlib_main_t *vm = vam->vlib_main;
364   vl_api_ip4_arp_event_t *event;
365   vl_api_ip4_arp_event_t *mp;
366   unix_shared_memory_queue_t *q;
367
368   /* Client can cancel, die, etc. */
369   if (pool_is_free_index (vam->arp_events, pool_index))
370     return;
371
372   event = pool_elt_at_index (vam->arp_events, pool_index);
373
374   q = vl_api_client_index_to_input_queue (event->client_index);
375   if (!q)
376     {
377       (void) vnet_add_del_ip4_arp_change_event
378         (vnm, arp_change_delete_callback,
379          event->pid, &event->address,
380          vpe_resolver_process_node.index, IP4_ARP_EVENT,
381          ~0 /* pool index, notused */ , 0 /* is_add */ );
382       return;
383     }
384
385   if (q->cursize < q->maxsize)
386     {
387       mp = vl_msg_api_alloc (sizeof (*mp));
388       clib_memcpy (mp, event, sizeof (*mp));
389       vl_msg_api_send_shmem (q, (u8 *) & mp);
390     }
391   else
392     {
393       static f64 last_time;
394       /*
395        * Throttle syslog msgs.
396        * It's pretty tempting to just revoke the registration...
397        */
398       if (vlib_time_now (vm) > last_time + 10.0)
399         {
400           clib_warning ("arp event for %U to pid %d: queue stuffed!",
401                         format_ip4_address, &event->address, event->pid);
402           last_time = vlib_time_now (vm);
403         }
404     }
405 }
406
407 void
408 handle_ip6_nd_event (u32 pool_index)
409 {
410   vpe_api_main_t *vam = &vpe_api_main;
411   vnet_main_t *vnm = vam->vnet_main;
412   vlib_main_t *vm = vam->vlib_main;
413   vl_api_ip6_nd_event_t *event;
414   vl_api_ip6_nd_event_t *mp;
415   unix_shared_memory_queue_t *q;
416
417   /* Client can cancel, die, etc. */
418   if (pool_is_free_index (vam->nd_events, pool_index))
419     return;
420
421   event = pool_elt_at_index (vam->nd_events, pool_index);
422
423   q = vl_api_client_index_to_input_queue (event->client_index);
424   if (!q)
425     {
426       (void) vnet_add_del_ip6_nd_change_event
427         (vnm, nd_change_delete_callback,
428          event->pid, &event->address,
429          vpe_resolver_process_node.index, IP6_ND_EVENT,
430          ~0 /* pool index, notused */ , 0 /* is_add */ );
431       return;
432     }
433
434   if (q->cursize < q->maxsize)
435     {
436       mp = vl_msg_api_alloc (sizeof (*mp));
437       clib_memcpy (mp, event, sizeof (*mp));
438       vl_msg_api_send_shmem (q, (u8 *) & mp);
439     }
440   else
441     {
442       static f64 last_time;
443       /*
444        * Throttle syslog msgs.
445        * It's pretty tempting to just revoke the registration...
446        */
447       if (vlib_time_now (vm) > last_time + 10.0)
448         {
449           clib_warning ("ip6 nd event for %U to pid %d: queue stuffed!",
450                         format_ip6_address, &event->address, event->pid);
451           last_time = vlib_time_now (vm);
452         }
453     }
454 }
455
456 static uword
457 resolver_process (vlib_main_t * vm,
458                   vlib_node_runtime_t * rt, vlib_frame_t * f)
459 {
460   uword event_type;
461   uword *event_data = 0;
462   f64 timeout = 100.0;
463   int i;
464
465   while (1)
466     {
467       vlib_process_wait_for_event_or_clock (vm, timeout);
468
469       event_type = vlib_process_get_events (vm, &event_data);
470
471       switch (event_type)
472         {
473         case RESOLUTION_PENDING_EVENT:
474           timeout = 1.0;
475           break;
476
477         case RESOLUTION_EVENT:
478           clib_warning ("resolver: BOGUS TYPE");
479           break;
480
481         case IP4_ARP_EVENT:
482           for (i = 0; i < vec_len (event_data); i++)
483             handle_ip4_arp_event (event_data[i]);
484           break;
485
486         case IP6_ND_EVENT:
487           for (i = 0; i < vec_len (event_data); i++)
488             handle_ip6_nd_event (event_data[i]);
489           break;
490
491         case ~0:                /* timeout */
492           break;
493         }
494
495       vec_reset_length (event_data);
496     }
497   return 0;                     /* or not */
498 }
499
500 /* *INDENT-OFF* */
501 VLIB_REGISTER_NODE (vpe_resolver_process_node,static) = {
502   .function = resolver_process,
503   .type = VLIB_NODE_TYPE_PROCESS,
504   .name = "vpe-route-resolver-process",
505 };
506 /* *INDENT-ON* */
507
508 static int
509 mpls_route_add_del_t_handler (vnet_main_t * vnm,
510                               vl_api_mpls_route_add_del_t * mp)
511 {
512   u32 fib_index, next_hop_fib_index;
513   mpls_label_t *label_stack = NULL;
514   int rv, ii, n_labels;;
515
516   fib_prefix_t pfx = {
517     .fp_len = 21,
518     .fp_proto = FIB_PROTOCOL_MPLS,
519     .fp_eos = mp->mr_eos,
520     .fp_label = ntohl (mp->mr_label),
521   };
522   if (pfx.fp_eos)
523     {
524       if (mp->mr_next_hop_proto_is_ip4)
525         {
526           pfx.fp_payload_proto = DPO_PROTO_IP4;
527         }
528       else
529         {
530           pfx.fp_payload_proto = DPO_PROTO_IP6;
531         }
532     }
533   else
534     {
535       pfx.fp_payload_proto = DPO_PROTO_MPLS;
536     }
537
538   rv = add_del_route_check (FIB_PROTOCOL_MPLS,
539                             mp->mr_table_id,
540                             mp->mr_next_hop_sw_if_index,
541                             dpo_proto_to_fib (pfx.fp_payload_proto),
542                             mp->mr_next_hop_table_id,
543                             mp->mr_create_table_if_needed,
544                             &fib_index, &next_hop_fib_index);
545
546   if (0 != rv)
547     return (rv);
548
549   ip46_address_t nh;
550   memset (&nh, 0, sizeof (nh));
551
552   if (mp->mr_next_hop_proto_is_ip4)
553     memcpy (&nh.ip4, mp->mr_next_hop, sizeof (nh.ip4));
554   else
555     memcpy (&nh.ip6, mp->mr_next_hop, sizeof (nh.ip6));
556
557   n_labels = mp->mr_next_hop_n_out_labels;
558   if (n_labels == 0)
559     ;
560   else if (1 == n_labels)
561     vec_add1 (label_stack, ntohl (mp->mr_next_hop_out_label_stack[0]));
562   else
563     {
564       vec_validate (label_stack, n_labels - 1);
565       for (ii = 0; ii < n_labels; ii++)
566         label_stack[ii] = ntohl (mp->mr_next_hop_out_label_stack[ii]);
567     }
568
569   return (add_del_route_t_handler (mp->mr_is_multipath, mp->mr_is_add, 0,       // mp->is_drop,
570                                    0,   // mp->is_unreach,
571                                    0,   // mp->is_prohibit,
572                                    0,   // mp->is_local,
573                                    mp->mr_is_classify,
574                                    mp->mr_classify_table_index,
575                                    mp->mr_is_resolve_host,
576                                    mp->mr_is_resolve_attached,
577                                    fib_index, &pfx,
578                                    mp->mr_next_hop_proto_is_ip4,
579                                    &nh, ntohl (mp->mr_next_hop_sw_if_index),
580                                    next_hop_fib_index,
581                                    mp->mr_next_hop_weight,
582                                    ntohl (mp->mr_next_hop_via_label),
583                                    label_stack));
584 }
585
586 void
587 vl_api_mpls_route_add_del_t_handler (vl_api_mpls_route_add_del_t * mp)
588 {
589   vl_api_mpls_route_add_del_reply_t *rmp;
590   vnet_main_t *vnm;
591   int rv;
592
593   vnm = vnet_get_main ();
594   vnm->api_errno = 0;
595
596   rv = mpls_route_add_del_t_handler (vnm, mp);
597
598   rv = (rv == 0) ? vnm->api_errno : rv;
599
600   REPLY_MACRO (VL_API_MPLS_ROUTE_ADD_DEL_REPLY);
601 }
602
603 static int
604 mpls_ip_bind_unbind_handler (vnet_main_t * vnm,
605                              vl_api_mpls_ip_bind_unbind_t * mp)
606 {
607   u32 mpls_fib_index, ip_fib_index;
608
609   mpls_fib_index =
610     fib_table_find (FIB_PROTOCOL_MPLS, ntohl (mp->mb_mpls_table_id));
611
612   if (~0 == mpls_fib_index)
613     {
614       if (mp->mb_create_table_if_needed)
615         {
616           mpls_fib_index =
617             fib_table_find_or_create_and_lock (FIB_PROTOCOL_MPLS,
618                                                ntohl (mp->mb_mpls_table_id));
619         }
620       else
621         return VNET_API_ERROR_NO_SUCH_FIB;
622     }
623
624   ip_fib_index = fib_table_find ((mp->mb_is_ip4 ?
625                                   FIB_PROTOCOL_IP4 :
626                                   FIB_PROTOCOL_IP6),
627                                  ntohl (mp->mb_ip_table_id));
628   if (~0 == ip_fib_index)
629     return VNET_API_ERROR_NO_SUCH_FIB;
630
631   fib_prefix_t pfx = {
632     .fp_len = mp->mb_address_length,
633   };
634
635   if (mp->mb_is_ip4)
636     {
637       pfx.fp_proto = FIB_PROTOCOL_IP4;
638       clib_memcpy (&pfx.fp_addr.ip4, mp->mb_address,
639                    sizeof (pfx.fp_addr.ip4));
640     }
641   else
642     {
643       pfx.fp_proto = FIB_PROTOCOL_IP6;
644       clib_memcpy (&pfx.fp_addr.ip6, mp->mb_address,
645                    sizeof (pfx.fp_addr.ip6));
646     }
647
648   if (mp->mb_is_bind)
649     fib_table_entry_local_label_add (ip_fib_index, &pfx,
650                                      ntohl (mp->mb_label));
651   else
652     fib_table_entry_local_label_remove (ip_fib_index, &pfx,
653                                         ntohl (mp->mb_label));
654
655   return (0);
656 }
657
658 void
659 vl_api_mpls_ip_bind_unbind_t_handler (vl_api_mpls_ip_bind_unbind_t * mp)
660 {
661   vl_api_mpls_route_add_del_reply_t *rmp;
662   vnet_main_t *vnm;
663   int rv;
664
665   vnm = vnet_get_main ();
666   vnm->api_errno = 0;
667
668   rv = mpls_ip_bind_unbind_handler (vnm, mp);
669
670   rv = (rv == 0) ? vnm->api_errno : rv;
671
672   REPLY_MACRO (VL_API_MPLS_ROUTE_ADD_DEL_REPLY);
673 }
674
675 static void
676 vl_api_sw_interface_set_vpath_t_handler (vl_api_sw_interface_set_vpath_t * mp)
677 {
678   vl_api_sw_interface_set_vpath_reply_t *rmp;
679   int rv = 0;
680   u32 sw_if_index = ntohl (mp->sw_if_index);
681
682   VALIDATE_SW_IF_INDEX (mp);
683
684   l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_VPATH, mp->enable);
685   vnet_feature_enable_disable ("ip4-unicast", "vpath-input-ip4",
686                                sw_if_index, mp->enable, 0, 0);
687   vnet_feature_enable_disable ("ip4-multicast", "vpath-input-ip4",
688                                sw_if_index, mp->enable, 0, 0);
689   vnet_feature_enable_disable ("ip6-unicast", "vpath-input-ip6",
690                                sw_if_index, mp->enable, 0, 0);
691   vnet_feature_enable_disable ("ip6-multicast", "vpath-input-ip6",
692                                sw_if_index, mp->enable, 0, 0);
693
694   BAD_SW_IF_INDEX_LABEL;
695
696   REPLY_MACRO (VL_API_SW_INTERFACE_SET_VPATH_REPLY);
697 }
698
699 static void
700   vl_api_sw_interface_set_vxlan_bypass_t_handler
701   (vl_api_sw_interface_set_vxlan_bypass_t * mp)
702 {
703   vl_api_sw_interface_set_vxlan_bypass_reply_t *rmp;
704   int rv = 0;
705   u32 sw_if_index = ntohl (mp->sw_if_index);
706
707   VALIDATE_SW_IF_INDEX (mp);
708
709   if (mp->is_ipv6)
710     {
711       /* not yet implemented */
712     }
713   else
714     vnet_feature_enable_disable ("ip4-unicast", "ip4-vxlan-bypass",
715                                  sw_if_index, mp->enable, 0, 0);
716
717   BAD_SW_IF_INDEX_LABEL;
718
719   REPLY_MACRO (VL_API_SW_INTERFACE_SET_VXLAN_BYPASS_REPLY);
720 }
721
722 static void
723   vl_api_sw_interface_set_l2_xconnect_t_handler
724   (vl_api_sw_interface_set_l2_xconnect_t * mp)
725 {
726   vl_api_sw_interface_set_l2_xconnect_reply_t *rmp;
727   int rv = 0;
728   u32 rx_sw_if_index = ntohl (mp->rx_sw_if_index);
729   u32 tx_sw_if_index = ntohl (mp->tx_sw_if_index);
730   vlib_main_t *vm = vlib_get_main ();
731   vnet_main_t *vnm = vnet_get_main ();
732
733   VALIDATE_RX_SW_IF_INDEX (mp);
734
735   if (mp->enable)
736     {
737       VALIDATE_TX_SW_IF_INDEX (mp);
738       rv = set_int_l2_mode (vm, vnm, MODE_L2_XC,
739                             rx_sw_if_index, 0, 0, 0, tx_sw_if_index);
740     }
741   else
742     {
743       rv = set_int_l2_mode (vm, vnm, MODE_L3, rx_sw_if_index, 0, 0, 0, 0);
744     }
745
746   BAD_RX_SW_IF_INDEX_LABEL;
747   BAD_TX_SW_IF_INDEX_LABEL;
748
749   REPLY_MACRO (VL_API_SW_INTERFACE_SET_L2_XCONNECT_REPLY);
750 }
751
752 static void
753   vl_api_sw_interface_set_l2_bridge_t_handler
754   (vl_api_sw_interface_set_l2_bridge_t * mp)
755 {
756   bd_main_t *bdm = &bd_main;
757   vl_api_sw_interface_set_l2_bridge_reply_t *rmp;
758   int rv = 0;
759   u32 rx_sw_if_index = ntohl (mp->rx_sw_if_index);
760   u32 bd_id = ntohl (mp->bd_id);
761   u32 bd_index;
762   u32 bvi = mp->bvi;
763   u8 shg = mp->shg;
764   vlib_main_t *vm = vlib_get_main ();
765   vnet_main_t *vnm = vnet_get_main ();
766
767   VALIDATE_RX_SW_IF_INDEX (mp);
768
769   bd_index = bd_find_or_add_bd_index (bdm, bd_id);
770
771   if (mp->enable)
772     {
773       //VALIDATE_TX_SW_IF_INDEX(mp);
774       rv = set_int_l2_mode (vm, vnm, MODE_L2_BRIDGE,
775                             rx_sw_if_index, bd_index, bvi, shg, 0);
776     }
777   else
778     {
779       rv = set_int_l2_mode (vm, vnm, MODE_L3, rx_sw_if_index, 0, 0, 0, 0);
780     }
781
782   BAD_RX_SW_IF_INDEX_LABEL;
783
784   REPLY_MACRO (VL_API_SW_INTERFACE_SET_L2_BRIDGE_REPLY);
785 }
786
787 static void
788   vl_api_sw_interface_set_dpdk_hqos_pipe_t_handler
789   (vl_api_sw_interface_set_dpdk_hqos_pipe_t * mp)
790 {
791   vl_api_sw_interface_set_dpdk_hqos_pipe_reply_t *rmp;
792   int rv = 0;
793
794 #if DPDK > 0
795   dpdk_main_t *dm = &dpdk_main;
796   dpdk_device_t *xd;
797
798   u32 sw_if_index = ntohl (mp->sw_if_index);
799   u32 subport = ntohl (mp->subport);
800   u32 pipe = ntohl (mp->pipe);
801   u32 profile = ntohl (mp->profile);
802   vnet_hw_interface_t *hw;
803
804   VALIDATE_SW_IF_INDEX (mp);
805
806   /* hw_if & dpdk device */
807   hw = vnet_get_sup_hw_interface (dm->vnet_main, sw_if_index);
808
809   xd = vec_elt_at_index (dm->devices, hw->dev_instance);
810
811   rv = rte_sched_pipe_config (xd->hqos_ht->hqos, subport, pipe, profile);
812
813   BAD_SW_IF_INDEX_LABEL;
814 #else
815   clib_warning ("setting HQoS pipe parameters without DPDK not implemented");
816   rv = VNET_API_ERROR_UNIMPLEMENTED;
817 #endif /* DPDK */
818
819   REPLY_MACRO (VL_API_SW_INTERFACE_SET_DPDK_HQOS_PIPE_REPLY);
820 }
821
822 static void
823   vl_api_sw_interface_set_dpdk_hqos_subport_t_handler
824   (vl_api_sw_interface_set_dpdk_hqos_subport_t * mp)
825 {
826   vl_api_sw_interface_set_dpdk_hqos_subport_reply_t *rmp;
827   int rv = 0;
828
829 #if DPDK > 0
830   dpdk_main_t *dm = &dpdk_main;
831   dpdk_device_t *xd;
832   struct rte_sched_subport_params p;
833
834   u32 sw_if_index = ntohl (mp->sw_if_index);
835   u32 subport = ntohl (mp->subport);
836   p.tb_rate = ntohl (mp->tb_rate);
837   p.tb_size = ntohl (mp->tb_size);
838   p.tc_rate[0] = ntohl (mp->tc_rate[0]);
839   p.tc_rate[1] = ntohl (mp->tc_rate[1]);
840   p.tc_rate[2] = ntohl (mp->tc_rate[2]);
841   p.tc_rate[3] = ntohl (mp->tc_rate[3]);
842   p.tc_period = ntohl (mp->tc_period);
843
844   vnet_hw_interface_t *hw;
845
846   VALIDATE_SW_IF_INDEX (mp);
847
848   /* hw_if & dpdk device */
849   hw = vnet_get_sup_hw_interface (dm->vnet_main, sw_if_index);
850
851   xd = vec_elt_at_index (dm->devices, hw->dev_instance);
852
853   rv = rte_sched_subport_config (xd->hqos_ht->hqos, subport, &p);
854
855   BAD_SW_IF_INDEX_LABEL;
856 #else
857   clib_warning
858     ("setting HQoS subport parameters without DPDK not implemented");
859   rv = VNET_API_ERROR_UNIMPLEMENTED;
860 #endif /* DPDK */
861
862   REPLY_MACRO (VL_API_SW_INTERFACE_SET_DPDK_HQOS_SUBPORT_REPLY);
863 }
864
865 static void
866   vl_api_sw_interface_set_dpdk_hqos_tctbl_t_handler
867   (vl_api_sw_interface_set_dpdk_hqos_tctbl_t * mp)
868 {
869   vl_api_sw_interface_set_dpdk_hqos_tctbl_reply_t *rmp;
870   int rv = 0;
871
872 #if DPDK > 0
873   dpdk_main_t *dm = &dpdk_main;
874   vlib_thread_main_t *tm = vlib_get_thread_main ();
875   dpdk_device_t *xd;
876
877   u32 sw_if_index = ntohl (mp->sw_if_index);
878   u32 entry = ntohl (mp->entry);
879   u32 tc = ntohl (mp->tc);
880   u32 queue = ntohl (mp->queue);
881   u32 val, i;
882
883   vnet_hw_interface_t *hw;
884
885   VALIDATE_SW_IF_INDEX (mp);
886
887   /* hw_if & dpdk device */
888   hw = vnet_get_sup_hw_interface (dm->vnet_main, sw_if_index);
889
890   xd = vec_elt_at_index (dm->devices, hw->dev_instance);
891
892   if (tc >= RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE)
893     {
894       clib_warning ("invalid traffic class !!");
895       rv = VNET_API_ERROR_INVALID_VALUE;
896       goto done;
897     }
898   if (queue >= RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS)
899     {
900       clib_warning ("invalid queue !!");
901       rv = VNET_API_ERROR_INVALID_VALUE;
902       goto done;
903     }
904
905   /* Detect the set of worker threads */
906   uword *p = hash_get_mem (tm->thread_registrations_by_name, "workers");
907
908   if (p == 0)
909     {
910       clib_warning ("worker thread registration AWOL !!");
911       rv = VNET_API_ERROR_INVALID_VALUE_2;
912       goto done;
913     }
914
915   vlib_thread_registration_t *tr = (vlib_thread_registration_t *) p[0];
916   int worker_thread_first = tr->first_index;
917   int worker_thread_count = tr->count;
918
919   val = tc * RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS + queue;
920   for (i = 0; i < worker_thread_count; i++)
921     xd->hqos_wt[worker_thread_first + i].hqos_tc_table[entry] = val;
922
923   BAD_SW_IF_INDEX_LABEL;
924 done:
925 #else
926   clib_warning ("setting HQoS DSCP table entry without DPDK not implemented");
927   rv = VNET_API_ERROR_UNIMPLEMENTED;
928 #endif /* DPDK */
929
930   REPLY_MACRO (VL_API_SW_INTERFACE_SET_DPDK_HQOS_TCTBL_REPLY);
931 }
932
933 static void
934 vl_api_bridge_domain_add_del_t_handler (vl_api_bridge_domain_add_del_t * mp)
935 {
936   vlib_main_t *vm = vlib_get_main ();
937   bd_main_t *bdm = &bd_main;
938   vl_api_bridge_domain_add_del_reply_t *rmp;
939   int rv = 0;
940   u32 enable_flags = 0, disable_flags = 0;
941   u32 bd_id = ntohl (mp->bd_id);
942   u32 bd_index;
943
944   if (mp->is_add)
945     {
946       bd_index = bd_find_or_add_bd_index (bdm, bd_id);
947
948       if (mp->flood)
949         enable_flags |= L2_FLOOD;
950       else
951         disable_flags |= L2_FLOOD;
952
953       if (mp->uu_flood)
954         enable_flags |= L2_UU_FLOOD;
955       else
956         disable_flags |= L2_UU_FLOOD;
957
958       if (mp->forward)
959         enable_flags |= L2_FWD;
960       else
961         disable_flags |= L2_FWD;
962
963       if (mp->arp_term)
964         enable_flags |= L2_ARP_TERM;
965       else
966         disable_flags |= L2_ARP_TERM;
967
968       if (mp->learn)
969         enable_flags |= L2_LEARN;
970       else
971         disable_flags |= L2_LEARN;
972
973       if (enable_flags)
974         bd_set_flags (vm, bd_index, enable_flags, 1 /* enable */ );
975
976       if (disable_flags)
977         bd_set_flags (vm, bd_index, disable_flags, 0 /* disable */ );
978
979       bd_set_mac_age (vm, bd_index, mp->mac_age);
980     }
981   else
982     rv = bd_delete_bd_index (bdm, bd_id);
983
984   REPLY_MACRO (VL_API_BRIDGE_DOMAIN_ADD_DEL_REPLY);
985 }
986
987 static void
988 vl_api_bridge_domain_details_t_handler (vl_api_bridge_domain_details_t * mp)
989 {
990   clib_warning ("BUG");
991 }
992
993 static void
994   vl_api_bridge_domain_sw_if_details_t_handler
995   (vl_api_bridge_domain_sw_if_details_t * mp)
996 {
997   clib_warning ("BUG");
998 }
999
1000 static void
1001 send_bridge_domain_details (unix_shared_memory_queue_t * q,
1002                             l2_bridge_domain_t * bd_config,
1003                             u32 n_sw_ifs, u32 context)
1004 {
1005   vl_api_bridge_domain_details_t *mp;
1006
1007   mp = vl_msg_api_alloc (sizeof (*mp));
1008   memset (mp, 0, sizeof (*mp));
1009   mp->_vl_msg_id = ntohs (VL_API_BRIDGE_DOMAIN_DETAILS);
1010   mp->bd_id = ntohl (bd_config->bd_id);
1011   mp->flood = bd_feature_flood (bd_config);
1012   mp->uu_flood = bd_feature_uu_flood (bd_config);
1013   mp->forward = bd_feature_forward (bd_config);
1014   mp->learn = bd_feature_learn (bd_config);
1015   mp->arp_term = bd_feature_arp_term (bd_config);
1016   mp->bvi_sw_if_index = ntohl (bd_config->bvi_sw_if_index);
1017   mp->mac_age = bd_config->mac_age;
1018   mp->n_sw_ifs = ntohl (n_sw_ifs);
1019   mp->context = context;
1020
1021   vl_msg_api_send_shmem (q, (u8 *) & mp);
1022 }
1023
1024 static void
1025 send_bd_sw_if_details (l2input_main_t * l2im,
1026                        unix_shared_memory_queue_t * q,
1027                        l2_flood_member_t * member, u32 bd_id, u32 context)
1028 {
1029   vl_api_bridge_domain_sw_if_details_t *mp;
1030   l2_input_config_t *input_cfg;
1031
1032   mp = vl_msg_api_alloc (sizeof (*mp));
1033   memset (mp, 0, sizeof (*mp));
1034   mp->_vl_msg_id = ntohs (VL_API_BRIDGE_DOMAIN_SW_IF_DETAILS);
1035   mp->bd_id = ntohl (bd_id);
1036   mp->sw_if_index = ntohl (member->sw_if_index);
1037   input_cfg = vec_elt_at_index (l2im->configs, member->sw_if_index);
1038   mp->shg = input_cfg->shg;
1039   mp->context = context;
1040
1041   vl_msg_api_send_shmem (q, (u8 *) & mp);
1042 }
1043
1044 static void
1045 vl_api_bridge_domain_dump_t_handler (vl_api_bridge_domain_dump_t * mp)
1046 {
1047   bd_main_t *bdm = &bd_main;
1048   l2input_main_t *l2im = &l2input_main;
1049   unix_shared_memory_queue_t *q;
1050   l2_bridge_domain_t *bd_config;
1051   u32 bd_id, bd_index;
1052   u32 end;
1053
1054   q = vl_api_client_index_to_input_queue (mp->client_index);
1055
1056   if (q == 0)
1057     return;
1058
1059   bd_id = ntohl (mp->bd_id);
1060
1061   bd_index = (bd_id == ~0) ? 0 : bd_find_or_add_bd_index (bdm, bd_id);
1062   end = (bd_id == ~0) ? vec_len (l2im->bd_configs) : bd_index + 1;
1063   for (; bd_index < end; bd_index++)
1064     {
1065       bd_config = l2input_bd_config_from_index (l2im, bd_index);
1066       /* skip dummy bd_id 0 */
1067       if (bd_config && (bd_config->bd_id > 0))
1068         {
1069           u32 n_sw_ifs;
1070           l2_flood_member_t *m;
1071
1072           n_sw_ifs = vec_len (bd_config->members);
1073           send_bridge_domain_details (q, bd_config, n_sw_ifs, mp->context);
1074
1075           vec_foreach (m, bd_config->members)
1076           {
1077             send_bd_sw_if_details (l2im, q, m, bd_config->bd_id, mp->context);
1078           }
1079         }
1080     }
1081 }
1082
1083 static void
1084 vl_api_l2fib_add_del_t_handler (vl_api_l2fib_add_del_t * mp)
1085 {
1086   bd_main_t *bdm = &bd_main;
1087   l2input_main_t *l2im = &l2input_main;
1088   vl_api_l2fib_add_del_reply_t *rmp;
1089   int rv = 0;
1090   u64 mac = 0;
1091   u32 sw_if_index = ntohl (mp->sw_if_index);
1092   u32 bd_id = ntohl (mp->bd_id);
1093   u32 bd_index;
1094   u32 static_mac;
1095   u32 filter_mac;
1096   u32 bvi_mac;
1097   uword *p;
1098
1099   mac = mp->mac;
1100
1101   p = hash_get (bdm->bd_index_by_bd_id, bd_id);
1102   if (!p)
1103     {
1104       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1105       goto bad_sw_if_index;
1106     }
1107   bd_index = p[0];
1108
1109   if (mp->is_add)
1110     {
1111       filter_mac = mp->filter_mac ? 1 : 0;
1112       if (filter_mac == 0)
1113         {
1114           VALIDATE_SW_IF_INDEX (mp);
1115           if (vec_len (l2im->configs) <= sw_if_index)
1116             {
1117               rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
1118               goto bad_sw_if_index;
1119             }
1120           else
1121             {
1122               l2_input_config_t *config;
1123               config = vec_elt_at_index (l2im->configs, sw_if_index);
1124               if (config->bridge == 0)
1125                 {
1126                   rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
1127                   goto bad_sw_if_index;
1128                 }
1129             }
1130         }
1131       static_mac = mp->static_mac ? 1 : 0;
1132       bvi_mac = mp->bvi_mac ? 1 : 0;
1133       l2fib_add_entry (mac, bd_index, sw_if_index, static_mac, filter_mac,
1134                        bvi_mac);
1135     }
1136   else
1137     {
1138       l2fib_del_entry (mac, bd_index);
1139     }
1140
1141   BAD_SW_IF_INDEX_LABEL;
1142
1143   REPLY_MACRO (VL_API_L2FIB_ADD_DEL_REPLY);
1144 }
1145
1146 static void
1147 vl_api_l2_flags_t_handler (vl_api_l2_flags_t * mp)
1148 {
1149   vl_api_l2_flags_reply_t *rmp;
1150   int rv = 0;
1151   u32 sw_if_index = ntohl (mp->sw_if_index);
1152   u32 flags = ntohl (mp->feature_bitmap);
1153   u32 rbm = 0;
1154
1155   VALIDATE_SW_IF_INDEX (mp);
1156
1157 #define _(a,b) \
1158     if (flags & L2INPUT_FEAT_ ## a) \
1159         rbm = l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_ ## a, mp->is_set);
1160   foreach_l2input_feat;
1161 #undef _
1162
1163   BAD_SW_IF_INDEX_LABEL;
1164
1165   /* *INDENT-OFF* */
1166   REPLY_MACRO2(VL_API_L2_FLAGS_REPLY,
1167   ({
1168     rmp->resulting_feature_bitmap = ntohl(rbm);
1169   }));
1170   /* *INDENT-ON* */
1171 }
1172
1173 static void
1174 vl_api_bridge_flags_t_handler (vl_api_bridge_flags_t * mp)
1175 {
1176   vlib_main_t *vm = vlib_get_main ();
1177   bd_main_t *bdm = &bd_main;
1178   vl_api_bridge_flags_reply_t *rmp;
1179   int rv = 0;
1180   u32 bd_id = ntohl (mp->bd_id);
1181   u32 bd_index;
1182   u32 flags = ntohl (mp->feature_bitmap);
1183   uword *p;
1184
1185   p = hash_get (bdm->bd_index_by_bd_id, bd_id);
1186   if (p == 0)
1187     {
1188       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1189       goto out;
1190     }
1191
1192   bd_index = p[0];
1193
1194   bd_set_flags (vm, bd_index, flags, mp->is_set);
1195
1196 out:
1197   /* *INDENT-OFF* */
1198   REPLY_MACRO2(VL_API_BRIDGE_FLAGS_REPLY,
1199   ({
1200     rmp->resulting_feature_bitmap = ntohl(flags);
1201   }));
1202   /* *INDENT-ON* */
1203 }
1204
1205 static void
1206 vl_api_bd_ip_mac_add_del_t_handler (vl_api_bd_ip_mac_add_del_t * mp)
1207 {
1208   bd_main_t *bdm = &bd_main;
1209   vl_api_bd_ip_mac_add_del_reply_t *rmp;
1210   int rv = 0;
1211   u32 bd_id = ntohl (mp->bd_id);
1212   u32 bd_index;
1213   uword *p;
1214
1215   p = hash_get (bdm->bd_index_by_bd_id, bd_id);
1216   if (p == 0)
1217     {
1218       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1219       goto out;
1220     }
1221
1222   bd_index = p[0];
1223   if (bd_add_del_ip_mac (bd_index, mp->ip_address,
1224                          mp->mac_address, mp->is_ipv6, mp->is_add))
1225     rv = VNET_API_ERROR_UNSPECIFIED;
1226
1227 out:
1228   REPLY_MACRO (VL_API_BD_IP_MAC_ADD_DEL_REPLY);
1229 }
1230
1231 static void
1232 vl_api_create_vlan_subif_t_handler (vl_api_create_vlan_subif_t * mp)
1233 {
1234   vl_api_create_vlan_subif_reply_t *rmp;
1235   vnet_main_t *vnm = vnet_get_main ();
1236   u32 hw_if_index, sw_if_index = (u32) ~ 0;
1237   vnet_hw_interface_t *hi;
1238   int rv = 0;
1239   u32 id;
1240   vnet_sw_interface_t template;
1241   uword *p;
1242   vnet_interface_main_t *im = &vnm->interface_main;
1243   u64 sup_and_sub_key;
1244   u64 *kp;
1245   unix_shared_memory_queue_t *q;
1246   clib_error_t *error;
1247
1248   VALIDATE_SW_IF_INDEX (mp);
1249
1250   hw_if_index = ntohl (mp->sw_if_index);
1251   hi = vnet_get_hw_interface (vnm, hw_if_index);
1252
1253   id = ntohl (mp->vlan_id);
1254   if (id == 0 || id > 4095)
1255     {
1256       rv = VNET_API_ERROR_INVALID_VLAN;
1257       goto out;
1258     }
1259
1260   sup_and_sub_key = ((u64) (hi->sw_if_index) << 32) | (u64) id;
1261
1262   p = hash_get_mem (im->sw_if_index_by_sup_and_sub, &sup_and_sub_key);
1263   if (p)
1264     {
1265       rv = VNET_API_ERROR_VLAN_ALREADY_EXISTS;
1266       goto out;
1267     }
1268
1269   kp = clib_mem_alloc (sizeof (*kp));
1270   *kp = sup_and_sub_key;
1271
1272   memset (&template, 0, sizeof (template));
1273   template.type = VNET_SW_INTERFACE_TYPE_SUB;
1274   template.sup_sw_if_index = hi->sw_if_index;
1275   template.sub.id = id;
1276   template.sub.eth.raw_flags = 0;
1277   template.sub.eth.flags.one_tag = 1;
1278   template.sub.eth.outer_vlan_id = id;
1279   template.sub.eth.flags.exact_match = 1;
1280
1281   error = vnet_create_sw_interface (vnm, &template, &sw_if_index);
1282   if (error)
1283     {
1284       clib_error_report (error);
1285       rv = VNET_API_ERROR_INVALID_REGISTRATION;
1286       goto out;
1287     }
1288   hash_set (hi->sub_interface_sw_if_index_by_id, id, sw_if_index);
1289   hash_set_mem (im->sw_if_index_by_sup_and_sub, kp, sw_if_index);
1290
1291   BAD_SW_IF_INDEX_LABEL;
1292
1293 out:
1294   q = vl_api_client_index_to_input_queue (mp->client_index);
1295   if (!q)
1296     return;
1297
1298   rmp = vl_msg_api_alloc (sizeof (*rmp));
1299   rmp->_vl_msg_id = ntohs (VL_API_CREATE_VLAN_SUBIF_REPLY);
1300   rmp->context = mp->context;
1301   rmp->retval = ntohl (rv);
1302   rmp->sw_if_index = ntohl (sw_if_index);
1303   vl_msg_api_send_shmem (q, (u8 *) & rmp);
1304 }
1305
1306 static void
1307 vl_api_create_subif_t_handler (vl_api_create_subif_t * mp)
1308 {
1309   vl_api_create_subif_reply_t *rmp;
1310   vnet_main_t *vnm = vnet_get_main ();
1311   u32 sw_if_index = ~0;
1312   int rv = 0;
1313   u32 sub_id;
1314   vnet_sw_interface_t *si;
1315   vnet_hw_interface_t *hi;
1316   vnet_sw_interface_t template;
1317   uword *p;
1318   vnet_interface_main_t *im = &vnm->interface_main;
1319   u64 sup_and_sub_key;
1320   u64 *kp;
1321   clib_error_t *error;
1322
1323   VALIDATE_SW_IF_INDEX (mp);
1324
1325   si = vnet_get_sup_sw_interface (vnm, ntohl (mp->sw_if_index));
1326   hi = vnet_get_sup_hw_interface (vnm, ntohl (mp->sw_if_index));
1327
1328   if (hi->bond_info == VNET_HW_INTERFACE_BOND_INFO_SLAVE)
1329     {
1330       rv = VNET_API_ERROR_BOND_SLAVE_NOT_ALLOWED;
1331       goto out;
1332     }
1333
1334   sw_if_index = si->sw_if_index;
1335   sub_id = ntohl (mp->sub_id);
1336
1337   sup_and_sub_key = ((u64) (sw_if_index) << 32) | (u64) sub_id;
1338
1339   p = hash_get_mem (im->sw_if_index_by_sup_and_sub, &sup_and_sub_key);
1340   if (p)
1341     {
1342       if (CLIB_DEBUG > 0)
1343         clib_warning ("sup sw_if_index %d, sub id %d already exists\n",
1344                       sw_if_index, sub_id);
1345       rv = VNET_API_ERROR_SUBIF_ALREADY_EXISTS;
1346       goto out;
1347     }
1348
1349   kp = clib_mem_alloc (sizeof (*kp));
1350   *kp = sup_and_sub_key;
1351
1352   memset (&template, 0, sizeof (template));
1353   template.type = VNET_SW_INTERFACE_TYPE_SUB;
1354   template.sup_sw_if_index = sw_if_index;
1355   template.sub.id = sub_id;
1356   template.sub.eth.flags.no_tags = mp->no_tags;
1357   template.sub.eth.flags.one_tag = mp->one_tag;
1358   template.sub.eth.flags.two_tags = mp->two_tags;
1359   template.sub.eth.flags.dot1ad = mp->dot1ad;
1360   template.sub.eth.flags.exact_match = mp->exact_match;
1361   template.sub.eth.flags.default_sub = mp->default_sub;
1362   template.sub.eth.flags.outer_vlan_id_any = mp->outer_vlan_id_any;
1363   template.sub.eth.flags.inner_vlan_id_any = mp->inner_vlan_id_any;
1364   template.sub.eth.outer_vlan_id = ntohs (mp->outer_vlan_id);
1365   template.sub.eth.inner_vlan_id = ntohs (mp->inner_vlan_id);
1366
1367   error = vnet_create_sw_interface (vnm, &template, &sw_if_index);
1368   if (error)
1369     {
1370       clib_error_report (error);
1371       rv = VNET_API_ERROR_SUBIF_CREATE_FAILED;
1372       goto out;
1373     }
1374
1375   hash_set (hi->sub_interface_sw_if_index_by_id, sub_id, sw_if_index);
1376   hash_set_mem (im->sw_if_index_by_sup_and_sub, kp, sw_if_index);
1377
1378   BAD_SW_IF_INDEX_LABEL;
1379
1380 out:
1381
1382   /* *INDENT-OFF* */
1383   REPLY_MACRO2(VL_API_CREATE_SUBIF_REPLY,
1384   ({
1385     rmp->sw_if_index = ntohl(sw_if_index);
1386   }));
1387   /* *INDENT-ON* */
1388 }
1389
1390 static void
1391 vl_api_mpls_tunnel_add_del_t_handler (vl_api_mpls_tunnel_add_del_t * mp)
1392 {
1393   vl_api_mpls_tunnel_add_del_reply_t *rmp;
1394   int rv = 0;
1395   stats_main_t *sm = &stats_main;
1396   u32 tunnel_sw_if_index;
1397   int ii;
1398
1399   dslock (sm, 1 /* release hint */ , 5 /* tag */ );
1400
1401   if (mp->mt_is_add)
1402     {
1403       fib_route_path_t rpath, *rpaths = NULL;
1404       mpls_label_t *label_stack = NULL;
1405
1406       memset (&rpath, 0, sizeof (rpath));
1407
1408       if (mp->mt_next_hop_proto_is_ip4)
1409         {
1410           rpath.frp_proto = FIB_PROTOCOL_IP4;
1411           clib_memcpy (&rpath.frp_addr.ip4,
1412                        mp->mt_next_hop, sizeof (rpath.frp_addr.ip4));
1413         }
1414       else
1415         {
1416           rpath.frp_proto = FIB_PROTOCOL_IP6;
1417           clib_memcpy (&rpath.frp_addr.ip6,
1418                        mp->mt_next_hop, sizeof (rpath.frp_addr.ip6));
1419         }
1420       rpath.frp_sw_if_index = ntohl (mp->mt_next_hop_sw_if_index);
1421
1422       for (ii = 0; ii < mp->mt_next_hop_n_out_labels; ii++)
1423         vec_add1 (label_stack, ntohl (mp->mt_next_hop_out_label_stack[ii]));
1424
1425       vec_add1 (rpaths, rpath);
1426
1427       vnet_mpls_tunnel_add (rpaths, label_stack,
1428                             mp->mt_l2_only, &tunnel_sw_if_index);
1429       vec_free (rpaths);
1430       vec_free (label_stack);
1431     }
1432   else
1433     {
1434       tunnel_sw_if_index = ntohl (mp->mt_sw_if_index);
1435       vnet_mpls_tunnel_del (tunnel_sw_if_index);
1436     }
1437
1438   dsunlock (sm);
1439
1440   /* *INDENT-OFF* */
1441   REPLY_MACRO2(VL_API_MPLS_TUNNEL_ADD_DEL_REPLY,
1442   ({
1443     rmp->sw_if_index = ntohl(tunnel_sw_if_index);
1444   }));
1445   /* *INDENT-ON* */
1446 }
1447
1448 static void
1449 vl_api_proxy_arp_add_del_t_handler (vl_api_proxy_arp_add_del_t * mp)
1450 {
1451   vl_api_proxy_arp_add_del_reply_t *rmp;
1452   u32 fib_index;
1453   int rv;
1454   ip4_main_t *im = &ip4_main;
1455   stats_main_t *sm = &stats_main;
1456   int vnet_proxy_arp_add_del (ip4_address_t * lo_addr,
1457                               ip4_address_t * hi_addr,
1458                               u32 fib_index, int is_del);
1459   uword *p;
1460
1461   dslock (sm, 1 /* release hint */ , 6 /* tag */ );
1462
1463   p = hash_get (im->fib_index_by_table_id, ntohl (mp->vrf_id));
1464
1465   if (!p)
1466     {
1467       rv = VNET_API_ERROR_NO_SUCH_FIB;
1468       goto out;
1469     }
1470
1471   fib_index = p[0];
1472
1473   rv = vnet_proxy_arp_add_del ((ip4_address_t *) mp->low_address,
1474                                (ip4_address_t *) mp->hi_address,
1475                                fib_index, mp->is_add == 0);
1476
1477 out:
1478   dsunlock (sm);
1479   REPLY_MACRO (VL_API_PROXY_ARP_ADD_DEL_REPLY);
1480 }
1481
1482 static void
1483   vl_api_proxy_arp_intfc_enable_disable_t_handler
1484   (vl_api_proxy_arp_intfc_enable_disable_t * mp)
1485 {
1486   int rv = 0;
1487   vnet_main_t *vnm = vnet_get_main ();
1488   vl_api_proxy_arp_intfc_enable_disable_reply_t *rmp;
1489   vnet_sw_interface_t *si;
1490   u32 sw_if_index;
1491
1492   VALIDATE_SW_IF_INDEX (mp);
1493
1494   sw_if_index = ntohl (mp->sw_if_index);
1495
1496   if (pool_is_free_index (vnm->interface_main.sw_interfaces, sw_if_index))
1497     {
1498       rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
1499       goto out;
1500     }
1501
1502   si = vnet_get_sw_interface (vnm, sw_if_index);
1503
1504   ASSERT (si);
1505
1506   if (mp->enable_disable)
1507     si->flags |= VNET_SW_INTERFACE_FLAG_PROXY_ARP;
1508   else
1509     si->flags &= ~VNET_SW_INTERFACE_FLAG_PROXY_ARP;
1510
1511   BAD_SW_IF_INDEX_LABEL;
1512
1513 out:
1514   REPLY_MACRO (VL_API_PROXY_ARP_INTFC_ENABLE_DISABLE_REPLY);
1515 }
1516
1517 static void
1518 vl_api_is_address_reachable_t_handler (vl_api_is_address_reachable_t * mp)
1519 {
1520 #if 0
1521   vpe_main_t *rm = &vpe_main;
1522   ip4_main_t *im4 = &ip4_main;
1523   ip6_main_t *im6 = &ip6_main;
1524   ip_lookup_main_t *lm;
1525   union
1526   {
1527     ip4_address_t ip4;
1528     ip6_address_t ip6;
1529   } addr;
1530   u32 adj_index, sw_if_index;
1531   vl_api_is_address_reachable_t *rmp;
1532   ip_adjacency_t *adj;
1533   unix_shared_memory_queue_t *q;
1534
1535   q = vl_api_client_index_to_input_queue (mp->client_index);
1536   if (!q)
1537     {
1538       increment_missing_api_client_counter (rm->vlib_main);
1539       return;
1540     }
1541
1542   rmp = vl_msg_api_alloc (sizeof (*rmp));
1543   clib_memcpy (rmp, mp, sizeof (*rmp));
1544
1545   sw_if_index = mp->next_hop_sw_if_index;
1546   clib_memcpy (&addr, mp->address, sizeof (addr));
1547   if (mp->is_ipv6)
1548     {
1549       lm = &im6->lookup_main;
1550       adj_index = ip6_fib_lookup (im6, sw_if_index, &addr.ip6);
1551     }
1552   else
1553     {
1554       lm = &im4->lookup_main;
1555       // FIXME NOT an ADJ
1556       adj_index = ip4_fib_lookup (im4, sw_if_index, &addr.ip4);
1557     }
1558   if (adj_index == ~0)
1559     {
1560       rmp->is_error = 1;
1561       goto send;
1562     }
1563   adj = ip_get_adjacency (lm, adj_index);
1564
1565   if (adj->lookup_next_index == IP_LOOKUP_NEXT_REWRITE
1566       && adj->rewrite_header.sw_if_index == sw_if_index)
1567     {
1568       rmp->is_known = 1;
1569     }
1570   else
1571     {
1572       if (adj->lookup_next_index == IP_LOOKUP_NEXT_ARP
1573           && adj->rewrite_header.sw_if_index == sw_if_index)
1574         {
1575           if (mp->is_ipv6)
1576             ip6_probe_neighbor (rm->vlib_main, &addr.ip6, sw_if_index);
1577           else
1578             ip4_probe_neighbor (rm->vlib_main, &addr.ip4, sw_if_index);
1579         }
1580       else if (adj->lookup_next_index == IP_LOOKUP_NEXT_DROP)
1581         {
1582           rmp->is_known = 1;
1583           goto send;
1584         }
1585       rmp->is_known = 0;
1586     }
1587
1588 send:
1589   vl_msg_api_send_shmem (q, (u8 *) & rmp);
1590 #endif
1591 }
1592
1593 static void
1594   vl_api_sw_interface_set_mpls_enable_t_handler
1595   (vl_api_sw_interface_set_mpls_enable_t * mp)
1596 {
1597   vl_api_sw_interface_set_mpls_enable_reply_t *rmp;
1598   int rv = 0;
1599
1600   VALIDATE_SW_IF_INDEX (mp);
1601
1602   mpls_sw_interface_enable_disable (&mpls_main,
1603                                     ntohl (mp->sw_if_index), mp->enable);
1604
1605   BAD_SW_IF_INDEX_LABEL;
1606   REPLY_MACRO (VL_API_SW_INTERFACE_SET_MPLS_ENABLE_REPLY);
1607 }
1608
1609 /*
1610  * WARNING: replicated pending api refactor completion
1611  */
1612 static void
1613 send_sw_interface_flags_deleted (vpe_api_main_t * am,
1614                                  unix_shared_memory_queue_t * q,
1615                                  u32 sw_if_index)
1616 {
1617   vl_api_sw_interface_set_flags_t *mp;
1618
1619   mp = vl_msg_api_alloc (sizeof (*mp));
1620   memset (mp, 0, sizeof (*mp));
1621   mp->_vl_msg_id = ntohs (VL_API_SW_INTERFACE_SET_FLAGS);
1622   mp->sw_if_index = ntohl (sw_if_index);
1623
1624   mp->admin_up_down = 0;
1625   mp->link_up_down = 0;
1626   mp->deleted = 1;
1627   vl_msg_api_send_shmem (q, (u8 *) & mp);
1628 }
1629
1630 void
1631 send_oam_event (oam_target_t * t)
1632 {
1633   vpe_api_main_t *vam = &vpe_api_main;
1634   unix_shared_memory_queue_t *q;
1635   vpe_client_registration_t *reg;
1636   vl_api_oam_event_t *mp;
1637
1638   /* *INDENT-OFF* */
1639   pool_foreach(reg, vam->oam_events_registrations,
1640   ({
1641     q = vl_api_client_index_to_input_queue (reg->client_index);
1642     if (q)
1643       {
1644         mp = vl_msg_api_alloc (sizeof (*mp));
1645         mp->_vl_msg_id = ntohs (VL_API_OAM_EVENT);
1646         clib_memcpy (mp->dst_address, &t->dst_address,
1647                      sizeof (mp->dst_address));
1648         mp->state = t->state;
1649         vl_msg_api_send_shmem (q, (u8 *)&mp);
1650       }
1651   }));
1652   /* *INDENT-ON* */
1653 }
1654
1655 static void
1656 vl_api_oam_add_del_t_handler (vl_api_oam_add_del_t * mp)
1657 {
1658   vl_api_oam_add_del_reply_t *rmp;
1659   int rv;
1660
1661   rv = vpe_oam_add_del_target ((ip4_address_t *) mp->src_address,
1662                                (ip4_address_t *) mp->dst_address,
1663                                ntohl (mp->vrf_id), (int) (mp->is_add));
1664
1665   REPLY_MACRO (VL_API_OAM_ADD_DEL_REPLY);
1666 }
1667
1668 static void
1669 vl_api_vnet_get_summary_stats_t_handler (vl_api_vnet_get_summary_stats_t * mp)
1670 {
1671   stats_main_t *sm = &stats_main;
1672   vnet_interface_main_t *im = sm->interface_main;
1673   vl_api_vnet_summary_stats_reply_t *rmp;
1674   vlib_combined_counter_main_t *cm;
1675   vlib_counter_t v;
1676   int i, which;
1677   u64 total_pkts[VLIB_N_RX_TX];
1678   u64 total_bytes[VLIB_N_RX_TX];
1679
1680   unix_shared_memory_queue_t *q =
1681     vl_api_client_index_to_input_queue (mp->client_index);
1682
1683   if (!q)
1684     return;
1685
1686   rmp = vl_msg_api_alloc (sizeof (*rmp));
1687   rmp->_vl_msg_id = ntohs (VL_API_VNET_SUMMARY_STATS_REPLY);
1688   rmp->context = mp->context;
1689   rmp->retval = 0;
1690
1691   memset (total_pkts, 0, sizeof (total_pkts));
1692   memset (total_bytes, 0, sizeof (total_bytes));
1693
1694   vnet_interface_counter_lock (im);
1695
1696   vec_foreach (cm, im->combined_sw_if_counters)
1697   {
1698     which = cm - im->combined_sw_if_counters;
1699
1700     for (i = 0; i < vec_len (cm->maxi); i++)
1701       {
1702         vlib_get_combined_counter (cm, i, &v);
1703         total_pkts[which] += v.packets;
1704         total_bytes[which] += v.bytes;
1705       }
1706   }
1707   vnet_interface_counter_unlock (im);
1708
1709   rmp->total_pkts[VLIB_RX] = clib_host_to_net_u64 (total_pkts[VLIB_RX]);
1710   rmp->total_bytes[VLIB_RX] = clib_host_to_net_u64 (total_bytes[VLIB_RX]);
1711   rmp->total_pkts[VLIB_TX] = clib_host_to_net_u64 (total_pkts[VLIB_TX]);
1712   rmp->total_bytes[VLIB_TX] = clib_host_to_net_u64 (total_bytes[VLIB_TX]);
1713   rmp->vector_rate =
1714     clib_host_to_net_u64 (vlib_last_vector_length_per_node (sm->vlib_main));
1715
1716   vl_msg_api_send_shmem (q, (u8 *) & rmp);
1717 }
1718
1719 /* *INDENT-OFF* */
1720 typedef CLIB_PACKED (struct {
1721   ip4_address_t address;
1722   u32 address_length: 6;
1723   u32 index:26;
1724 }) ip4_route_t;
1725 /* *INDENT-ON* */
1726
1727 static int
1728 ip4_reset_fib_t_handler (vl_api_reset_fib_t * mp)
1729 {
1730   vnet_main_t *vnm = vnet_get_main ();
1731   vnet_interface_main_t *im = &vnm->interface_main;
1732   ip4_main_t *im4 = &ip4_main;
1733   static u32 *sw_if_indices_to_shut;
1734   stats_main_t *sm = &stats_main;
1735   fib_table_t *fib_table;
1736   ip4_fib_t *fib;
1737   u32 sw_if_index;
1738   int i;
1739   int rv = VNET_API_ERROR_NO_SUCH_FIB;
1740   u32 target_fib_id = ntohl (mp->vrf_id);
1741
1742   dslock (sm, 1 /* release hint */ , 8 /* tag */ );
1743
1744   /* *INDENT-OFF* */
1745   pool_foreach (fib_table, im4->fibs,
1746   ({
1747     fib = &fib_table->v4;
1748     vnet_sw_interface_t * si;
1749
1750     if (fib->table_id != target_fib_id)
1751       continue;
1752
1753     /* remove any mpls encap/decap labels */
1754     mpls_fib_reset_labels (fib->table_id);
1755
1756     /* remove any proxy arps in this fib */
1757     vnet_proxy_arp_fib_reset (fib->table_id);
1758
1759     /* Set the flow hash for this fib to the default */
1760     vnet_set_ip4_flow_hash (fib->table_id, IP_FLOW_HASH_DEFAULT);
1761
1762     vec_reset_length (sw_if_indices_to_shut);
1763
1764     /* Shut down interfaces in this FIB / clean out intfc routes */
1765     pool_foreach (si, im->sw_interfaces,
1766     ({
1767       u32 sw_if_index = si->sw_if_index;
1768
1769       if (sw_if_index < vec_len (im4->fib_index_by_sw_if_index)
1770           && (im4->fib_index_by_sw_if_index[si->sw_if_index] ==
1771               fib->index))
1772         vec_add1 (sw_if_indices_to_shut, si->sw_if_index);
1773     }));
1774
1775     for (i = 0; i < vec_len (sw_if_indices_to_shut); i++) {
1776       sw_if_index = sw_if_indices_to_shut[i];
1777       // vec_foreach (sw_if_index, sw_if_indices_to_shut) {
1778
1779       u32 flags = vnet_sw_interface_get_flags (vnm, sw_if_index);
1780       flags &= ~(VNET_SW_INTERFACE_FLAG_ADMIN_UP);
1781       vnet_sw_interface_set_flags (vnm, sw_if_index, flags);
1782     }
1783
1784     fib_table_flush(fib->index, FIB_PROTOCOL_IP4, FIB_SOURCE_API);
1785     fib_table_flush(fib->index, FIB_PROTOCOL_IP4, FIB_SOURCE_INTERFACE);
1786
1787     rv = 0;
1788     break;
1789     })); /* pool_foreach (fib) */
1790     /* *INDENT-ON* */
1791
1792   dsunlock (sm);
1793   return rv;
1794 }
1795
1796 static int
1797 ip6_reset_fib_t_handler (vl_api_reset_fib_t * mp)
1798 {
1799   vnet_main_t *vnm = vnet_get_main ();
1800   vnet_interface_main_t *im = &vnm->interface_main;
1801   ip6_main_t *im6 = &ip6_main;
1802   stats_main_t *sm = &stats_main;
1803   static u32 *sw_if_indices_to_shut;
1804   fib_table_t *fib_table;
1805   ip6_fib_t *fib;
1806   u32 sw_if_index;
1807   int i;
1808   int rv = VNET_API_ERROR_NO_SUCH_FIB;
1809   u32 target_fib_id = ntohl (mp->vrf_id);
1810
1811   dslock (sm, 1 /* release hint */ , 9 /* tag */ );
1812
1813   /* *INDENT-OFF* */
1814   pool_foreach (fib_table, im6->fibs,
1815   ({
1816     vnet_sw_interface_t * si;
1817     fib = &(fib_table->v6);
1818
1819     if (fib->table_id != target_fib_id)
1820       continue;
1821
1822     vec_reset_length (sw_if_indices_to_shut);
1823
1824     /* Shut down interfaces in this FIB / clean out intfc routes */
1825     pool_foreach (si, im->sw_interfaces,
1826                   ({
1827                     if (im6->fib_index_by_sw_if_index[si->sw_if_index] ==
1828                         fib->index)
1829                       vec_add1 (sw_if_indices_to_shut, si->sw_if_index);
1830                   }));
1831
1832     for (i = 0; i < vec_len (sw_if_indices_to_shut); i++) {
1833       sw_if_index = sw_if_indices_to_shut[i];
1834       // vec_foreach (sw_if_index, sw_if_indices_to_shut) {
1835
1836       u32 flags = vnet_sw_interface_get_flags (vnm, sw_if_index);
1837       flags &= ~(VNET_SW_INTERFACE_FLAG_ADMIN_UP);
1838       vnet_sw_interface_set_flags (vnm, sw_if_index, flags);
1839     }
1840
1841     fib_table_flush(fib->index, FIB_PROTOCOL_IP6, FIB_SOURCE_API);
1842     fib_table_flush(fib->index, FIB_PROTOCOL_IP6, FIB_SOURCE_INTERFACE);
1843
1844     rv = 0;
1845     break;
1846   })); /* pool_foreach (fib) */
1847   /* *INDENT-ON* */
1848
1849   dsunlock (sm);
1850   return rv;
1851 }
1852
1853 static void
1854 vl_api_reset_fib_t_handler (vl_api_reset_fib_t * mp)
1855 {
1856   int rv;
1857   vl_api_reset_fib_reply_t *rmp;
1858
1859   if (mp->is_ipv6)
1860     rv = ip6_reset_fib_t_handler (mp);
1861   else
1862     rv = ip4_reset_fib_t_handler (mp);
1863
1864   REPLY_MACRO (VL_API_RESET_FIB_REPLY);
1865 }
1866
1867
1868 static void
1869 dhcpv4_proxy_config (vl_api_dhcp_proxy_config_t * mp)
1870 {
1871   vl_api_dhcp_proxy_config_reply_t *rmp;
1872   int rv;
1873
1874   rv = dhcp_proxy_set_server ((ip4_address_t *) (&mp->dhcp_server),
1875                               (ip4_address_t *) (&mp->dhcp_src_address),
1876                               (u32) ntohl (mp->vrf_id),
1877                               (int) mp->insert_circuit_id,
1878                               (int) (mp->is_add == 0));
1879
1880   REPLY_MACRO (VL_API_DHCP_PROXY_CONFIG_REPLY);
1881 }
1882
1883
1884 static void
1885 dhcpv6_proxy_config (vl_api_dhcp_proxy_config_t * mp)
1886 {
1887   vl_api_dhcp_proxy_config_reply_t *rmp;
1888   int rv = -1;
1889
1890   rv = dhcpv6_proxy_set_server ((ip6_address_t *) (&mp->dhcp_server),
1891                                 (ip6_address_t *) (&mp->dhcp_src_address),
1892                                 (u32) ntohl (mp->vrf_id),
1893                                 (int) mp->insert_circuit_id,
1894                                 (int) (mp->is_add == 0));
1895
1896   REPLY_MACRO (VL_API_DHCP_PROXY_CONFIG_REPLY);
1897 }
1898
1899 static void
1900 dhcpv4_proxy_config_2 (vl_api_dhcp_proxy_config_2_t * mp)
1901 {
1902   vl_api_dhcp_proxy_config_reply_t *rmp;
1903   int rv;
1904
1905   rv = dhcp_proxy_set_server_2 ((ip4_address_t *) (&mp->dhcp_server),
1906                                 (ip4_address_t *) (&mp->dhcp_src_address),
1907                                 (u32) ntohl (mp->rx_vrf_id),
1908                                 (u32) ntohl (mp->server_vrf_id),
1909                                 (int) mp->insert_circuit_id,
1910                                 (int) (mp->is_add == 0));
1911
1912   REPLY_MACRO (VL_API_DHCP_PROXY_CONFIG_2_REPLY);
1913 }
1914
1915
1916 static void
1917 dhcpv6_proxy_config_2 (vl_api_dhcp_proxy_config_2_t * mp)
1918 {
1919   vl_api_dhcp_proxy_config_reply_t *rmp;
1920   int rv = -1;
1921
1922   rv = dhcpv6_proxy_set_server_2 ((ip6_address_t *) (&mp->dhcp_server),
1923                                   (ip6_address_t *) (&mp->dhcp_src_address),
1924                                   (u32) ntohl (mp->rx_vrf_id),
1925                                   (u32) ntohl (mp->server_vrf_id),
1926                                   (int) mp->insert_circuit_id,
1927                                   (int) (mp->is_add == 0));
1928
1929   REPLY_MACRO (VL_API_DHCP_PROXY_CONFIG_2_REPLY);
1930 }
1931
1932
1933 static void
1934 vl_api_dhcp_proxy_set_vss_t_handler (vl_api_dhcp_proxy_set_vss_t * mp)
1935 {
1936   vl_api_dhcp_proxy_set_vss_reply_t *rmp;
1937   int rv;
1938   if (!mp->is_ipv6)
1939     rv = dhcp_proxy_set_option82_vss (ntohl (mp->tbl_id),
1940                                       ntohl (mp->oui),
1941                                       ntohl (mp->fib_id),
1942                                       (int) mp->is_add == 0);
1943   else
1944     rv = dhcpv6_proxy_set_vss (ntohl (mp->tbl_id),
1945                                ntohl (mp->oui),
1946                                ntohl (mp->fib_id), (int) mp->is_add == 0);
1947
1948   REPLY_MACRO (VL_API_DHCP_PROXY_SET_VSS_REPLY);
1949 }
1950
1951
1952 static void vl_api_dhcp_proxy_config_t_handler
1953   (vl_api_dhcp_proxy_config_t * mp)
1954 {
1955   if (mp->is_ipv6 == 0)
1956     dhcpv4_proxy_config (mp);
1957   else
1958     dhcpv6_proxy_config (mp);
1959 }
1960
1961 static void vl_api_dhcp_proxy_config_2_t_handler
1962   (vl_api_dhcp_proxy_config_2_t * mp)
1963 {
1964   if (mp->is_ipv6 == 0)
1965     dhcpv4_proxy_config_2 (mp);
1966   else
1967     dhcpv6_proxy_config_2 (mp);
1968 }
1969
1970 void
1971 dhcp_compl_event_callback (u32 client_index, u32 pid, u8 * hostname,
1972                            u8 is_ipv6, u8 * host_address, u8 * router_address,
1973                            u8 * host_mac)
1974 {
1975   unix_shared_memory_queue_t *q;
1976   vl_api_dhcp_compl_event_t *mp;
1977
1978   q = vl_api_client_index_to_input_queue (client_index);
1979   if (!q)
1980     return;
1981
1982   mp = vl_msg_api_alloc (sizeof (*mp));
1983   mp->client_index = client_index;
1984   mp->pid = pid;
1985   mp->is_ipv6 = is_ipv6;
1986   clib_memcpy (&mp->hostname, hostname, vec_len (hostname));
1987   mp->hostname[vec_len (hostname) + 1] = '\n';
1988   clib_memcpy (&mp->host_address[0], host_address, 16);
1989   clib_memcpy (&mp->router_address[0], router_address, 16);
1990
1991   if (NULL != host_mac)
1992     clib_memcpy (&mp->host_mac[0], host_mac, 6);
1993
1994   mp->_vl_msg_id = ntohs (VL_API_DHCP_COMPL_EVENT);
1995
1996   vl_msg_api_send_shmem (q, (u8 *) & mp);
1997 }
1998
1999 static void vl_api_dhcp_client_config_t_handler
2000   (vl_api_dhcp_client_config_t * mp)
2001 {
2002   vlib_main_t *vm = vlib_get_main ();
2003   vl_api_dhcp_client_config_reply_t *rmp;
2004   int rv = 0;
2005
2006   VALIDATE_SW_IF_INDEX (mp);
2007
2008   rv = dhcp_client_config (vm, ntohl (mp->sw_if_index),
2009                            mp->hostname, mp->is_add, mp->client_index,
2010                            mp->want_dhcp_event ? dhcp_compl_event_callback :
2011                            NULL, mp->pid);
2012
2013   BAD_SW_IF_INDEX_LABEL;
2014
2015   REPLY_MACRO (VL_API_DHCP_CLIENT_CONFIG_REPLY);
2016 }
2017
2018 static void
2019 vl_api_create_loopback_t_handler (vl_api_create_loopback_t * mp)
2020 {
2021   vl_api_create_loopback_reply_t *rmp;
2022   u32 sw_if_index;
2023   int rv;
2024
2025   rv = vnet_create_loopback_interface (&sw_if_index, mp->mac_address);
2026
2027   /* *INDENT-OFF* */
2028   REPLY_MACRO2(VL_API_CREATE_LOOPBACK_REPLY,
2029   ({
2030     rmp->sw_if_index = ntohl (sw_if_index);
2031   }));
2032   /* *INDENT-ON* */
2033 }
2034
2035 static void
2036 vl_api_delete_loopback_t_handler (vl_api_delete_loopback_t * mp)
2037 {
2038   vl_api_delete_loopback_reply_t *rmp;
2039   u32 sw_if_index;
2040   int rv;
2041
2042   sw_if_index = ntohl (mp->sw_if_index);
2043   rv = vnet_delete_loopback_interface (sw_if_index);
2044
2045   REPLY_MACRO (VL_API_DELETE_LOOPBACK_REPLY);
2046 }
2047
2048 static void
2049 vl_api_control_ping_t_handler (vl_api_control_ping_t * mp)
2050 {
2051   vl_api_control_ping_reply_t *rmp;
2052   int rv = 0;
2053
2054   /* *INDENT-OFF* */
2055   REPLY_MACRO2(VL_API_CONTROL_PING_REPLY,
2056   ({
2057     rmp->vpe_pid = ntohl (getpid());
2058   }));
2059   /* *INDENT-ON* */
2060 }
2061
2062 static void
2063 shmem_cli_output (uword arg, u8 * buffer, uword buffer_bytes)
2064 {
2065   u8 **shmem_vecp = (u8 **) arg;
2066   u8 *shmem_vec;
2067   void *oldheap;
2068   api_main_t *am = &api_main;
2069   u32 offset;
2070
2071   shmem_vec = *shmem_vecp;
2072
2073   offset = vec_len (shmem_vec);
2074
2075   pthread_mutex_lock (&am->vlib_rp->mutex);
2076   oldheap = svm_push_data_heap (am->vlib_rp);
2077
2078   vec_validate (shmem_vec, offset + buffer_bytes - 1);
2079
2080   clib_memcpy (shmem_vec + offset, buffer, buffer_bytes);
2081
2082   svm_pop_heap (oldheap);
2083   pthread_mutex_unlock (&am->vlib_rp->mutex);
2084
2085   *shmem_vecp = shmem_vec;
2086 }
2087
2088
2089 static void
2090 vl_api_cli_request_t_handler (vl_api_cli_request_t * mp)
2091 {
2092   vl_api_cli_reply_t *rp;
2093   unix_shared_memory_queue_t *q;
2094   vlib_main_t *vm = vlib_get_main ();
2095   api_main_t *am = &api_main;
2096   unformat_input_t input;
2097   u8 *shmem_vec = 0;
2098   void *oldheap;
2099
2100   q = vl_api_client_index_to_input_queue (mp->client_index);
2101   if (!q)
2102     return;
2103
2104   rp = vl_msg_api_alloc (sizeof (*rp));
2105   rp->_vl_msg_id = ntohs (VL_API_CLI_REPLY);
2106   rp->context = mp->context;
2107
2108   unformat_init_vector (&input, (u8 *) (uword) mp->cmd_in_shmem);
2109
2110   vlib_cli_input (vm, &input, shmem_cli_output, (uword) & shmem_vec);
2111
2112   pthread_mutex_lock (&am->vlib_rp->mutex);
2113   oldheap = svm_push_data_heap (am->vlib_rp);
2114
2115   vec_add1 (shmem_vec, 0);
2116
2117   svm_pop_heap (oldheap);
2118   pthread_mutex_unlock (&am->vlib_rp->mutex);
2119
2120   rp->reply_in_shmem = (uword) shmem_vec;
2121
2122   vl_msg_api_send_shmem (q, (u8 *) & rp);
2123 }
2124
2125 static void
2126 inband_cli_output (uword arg, u8 * buffer, uword buffer_bytes)
2127 {
2128   u8 **mem_vecp = (u8 **) arg;
2129   u8 *mem_vec = *mem_vecp;
2130   u32 offset = vec_len (mem_vec);
2131
2132   vec_validate (mem_vec, offset + buffer_bytes - 1);
2133   clib_memcpy (mem_vec + offset, buffer, buffer_bytes);
2134   *mem_vecp = mem_vec;
2135 }
2136
2137 static void
2138 vl_api_cli_inband_t_handler (vl_api_cli_inband_t * mp)
2139 {
2140   vl_api_cli_inband_reply_t *rmp;
2141   int rv = 0;
2142   unix_shared_memory_queue_t *q;
2143   vlib_main_t *vm = vlib_get_main ();
2144   unformat_input_t input;
2145   u8 *out_vec = 0;
2146
2147   q = vl_api_client_index_to_input_queue (mp->client_index);
2148   if (!q)
2149     return;
2150
2151   unformat_init_string (&input, (char *) mp->cmd, ntohl (mp->length));
2152   vlib_cli_input (vm, &input, inband_cli_output, (uword) & out_vec);
2153
2154   u32 len = vec_len (out_vec);
2155   /* *INDENT-OFF* */
2156   REPLY_MACRO3(VL_API_CLI_INBAND_REPLY, len,
2157   ({
2158     rmp->length = htonl (len);
2159     clib_memcpy (rmp->reply, out_vec, len);
2160   }));
2161   /* *INDENT-ON* */
2162   vec_free (out_vec);
2163 }
2164
2165 static void
2166 vl_api_set_arp_neighbor_limit_t_handler (vl_api_set_arp_neighbor_limit_t * mp)
2167 {
2168   int rv;
2169   vl_api_set_arp_neighbor_limit_reply_t *rmp;
2170   vnet_main_t *vnm = vnet_get_main ();
2171   clib_error_t *error;
2172
2173   vnm->api_errno = 0;
2174
2175   if (mp->is_ipv6)
2176     error = ip6_set_neighbor_limit (ntohl (mp->arp_neighbor_limit));
2177   else
2178     error = ip4_set_arp_limit (ntohl (mp->arp_neighbor_limit));
2179
2180   if (error)
2181     {
2182       clib_error_report (error);
2183       rv = VNET_API_ERROR_UNSPECIFIED;
2184     }
2185   else
2186     {
2187       rv = vnm->api_errno;
2188     }
2189
2190   REPLY_MACRO (VL_API_SET_ARP_NEIGHBOR_LIMIT_REPLY);
2191 }
2192
2193 static void vl_api_sr_tunnel_add_del_t_handler
2194   (vl_api_sr_tunnel_add_del_t * mp)
2195 {
2196 #if IP6SR == 0
2197   clib_warning ("unimplemented");
2198 #else
2199   ip6_sr_add_del_tunnel_args_t _a, *a = &_a;
2200   int rv = 0;
2201   vl_api_sr_tunnel_add_del_reply_t *rmp;
2202   ip6_address_t *segments = 0, *seg;
2203   ip6_address_t *tags = 0, *tag;
2204   ip6_address_t *this_address;
2205   int i;
2206
2207   if (mp->n_segments == 0)
2208     {
2209       rv = -11;
2210       goto out;
2211     }
2212
2213   memset (a, 0, sizeof (*a));
2214   a->src_address = (ip6_address_t *) & mp->src_address;
2215   a->dst_address = (ip6_address_t *) & mp->dst_address;
2216   a->dst_mask_width = mp->dst_mask_width;
2217   a->flags_net_byte_order = mp->flags_net_byte_order;
2218   a->is_del = (mp->is_add == 0);
2219   a->rx_table_id = ntohl (mp->outer_vrf_id);
2220   a->tx_table_id = ntohl (mp->inner_vrf_id);
2221
2222   a->name = format (0, "%s", mp->name);
2223   if (!(vec_len (a->name)))
2224     a->name = 0;
2225
2226   a->policy_name = format (0, "%s", mp->policy_name);
2227   if (!(vec_len (a->policy_name)))
2228     a->policy_name = 0;
2229
2230   /* Yank segments and tags out of the API message */
2231   this_address = (ip6_address_t *) mp->segs_and_tags;
2232   for (i = 0; i < mp->n_segments; i++)
2233     {
2234       vec_add2 (segments, seg, 1);
2235       clib_memcpy (seg->as_u8, this_address->as_u8, sizeof (*this_address));
2236       this_address++;
2237     }
2238   for (i = 0; i < mp->n_tags; i++)
2239     {
2240       vec_add2 (tags, tag, 1);
2241       clib_memcpy (tag->as_u8, this_address->as_u8, sizeof (*this_address));
2242       this_address++;
2243     }
2244
2245   a->segments = segments;
2246   a->tags = tags;
2247
2248   rv = ip6_sr_add_del_tunnel (a);
2249
2250 out:
2251
2252   REPLY_MACRO (VL_API_SR_TUNNEL_ADD_DEL_REPLY);
2253 #endif
2254 }
2255
2256 static void vl_api_sr_policy_add_del_t_handler
2257   (vl_api_sr_policy_add_del_t * mp)
2258 {
2259 #if IP6SR == 0
2260   clib_warning ("unimplemented");
2261 #else
2262   ip6_sr_add_del_policy_args_t _a, *a = &_a;
2263   int rv = 0;
2264   vl_api_sr_policy_add_del_reply_t *rmp;
2265   int i;
2266
2267   memset (a, 0, sizeof (*a));
2268   a->is_del = (mp->is_add == 0);
2269
2270   a->name = format (0, "%s", mp->name);
2271   if (!(vec_len (a->name)))
2272     {
2273       rv = VNET_API_ERROR_NO_SUCH_NODE2;
2274       goto out;
2275     }
2276
2277   if (!(mp->tunnel_names[0]))
2278     {
2279       rv = VNET_API_ERROR_NO_SUCH_NODE2;
2280       goto out;
2281     }
2282
2283   // start deserializing tunnel_names
2284   int num_tunnels = mp->tunnel_names[0];        //number of tunnels
2285   u8 *deser_tun_names = mp->tunnel_names;
2286   deser_tun_names += 1;         //moving along
2287
2288   u8 *tun_name = 0;
2289   int tun_name_len = 0;
2290
2291   for (i = 0; i < num_tunnels; i++)
2292     {
2293       tun_name_len = *deser_tun_names;
2294       deser_tun_names += 1;
2295       vec_resize (tun_name, tun_name_len);
2296       memcpy (tun_name, deser_tun_names, tun_name_len);
2297       vec_add1 (a->tunnel_names, tun_name);
2298       deser_tun_names += tun_name_len;
2299       tun_name = 0;
2300     }
2301
2302   rv = ip6_sr_add_del_policy (a);
2303
2304 out:
2305
2306   REPLY_MACRO (VL_API_SR_POLICY_ADD_DEL_REPLY);
2307 #endif
2308 }
2309
2310 static void vl_api_sr_multicast_map_add_del_t_handler
2311   (vl_api_sr_multicast_map_add_del_t * mp)
2312 {
2313 #if IP6SR == 0
2314   clib_warning ("unimplemented");
2315 #else
2316   ip6_sr_add_del_multicastmap_args_t _a, *a = &_a;
2317   int rv = 0;
2318   vl_api_sr_multicast_map_add_del_reply_t *rmp;
2319
2320   memset (a, 0, sizeof (*a));
2321   a->is_del = (mp->is_add == 0);
2322
2323   a->multicast_address = (ip6_address_t *) & mp->multicast_address;
2324   a->policy_name = format (0, "%s", mp->policy_name);
2325
2326   if (a->multicast_address == 0)
2327     {
2328       rv = -1;
2329       goto out;
2330     }
2331
2332   if (!(a->policy_name))
2333     {
2334       rv = -2;
2335       goto out;
2336     }
2337
2338 #if DPDK > 0                    /* Cannot call replicate without DPDK */
2339   rv = ip6_sr_add_del_multicastmap (a);
2340 #else
2341   clib_warning ("multicast replication without DPDK not implemented");
2342   rv = VNET_API_ERROR_UNIMPLEMENTED;
2343 #endif /* DPDK */
2344
2345 out:
2346
2347   REPLY_MACRO (VL_API_SR_MULTICAST_MAP_ADD_DEL_REPLY);
2348 #endif
2349 }
2350
2351 #define foreach_classify_add_del_table_field    \
2352 _(table_index)                                  \
2353 _(nbuckets)                                     \
2354 _(memory_size)                                  \
2355 _(skip_n_vectors)                               \
2356 _(match_n_vectors)                              \
2357 _(next_table_index)                             \
2358 _(miss_next_index)                              \
2359 _(current_data_flag)                            \
2360 _(current_data_offset)
2361
2362 static void vl_api_classify_add_del_table_t_handler
2363   (vl_api_classify_add_del_table_t * mp)
2364 {
2365   vl_api_classify_add_del_table_reply_t *rmp;
2366   vnet_classify_main_t *cm = &vnet_classify_main;
2367   vnet_classify_table_t *t;
2368   int rv;
2369
2370 #define _(a) u32 a;
2371   foreach_classify_add_del_table_field;
2372 #undef _
2373
2374 #define _(a) a = ntohl(mp->a);
2375   foreach_classify_add_del_table_field;
2376 #undef _
2377
2378   /* The underlying API fails silently, on purpose, so check here */
2379   if (mp->is_add == 0)          /* delete */
2380     {
2381       if (pool_is_free_index (cm->tables, table_index))
2382         {
2383           rv = VNET_API_ERROR_NO_SUCH_TABLE;
2384           goto out;
2385         }
2386     }
2387   else                          /* add or update */
2388     {
2389       if (table_index != ~0 && pool_is_free_index (cm->tables, table_index))
2390         table_index = ~0;
2391     }
2392
2393   rv = vnet_classify_add_del_table
2394     (cm, mp->mask, nbuckets, memory_size,
2395      skip_n_vectors, match_n_vectors,
2396      next_table_index, miss_next_index, &table_index,
2397      current_data_flag, current_data_offset, mp->is_add, mp->del_chain);
2398
2399 out:
2400   /* *INDENT-OFF* */
2401   REPLY_MACRO2(VL_API_CLASSIFY_ADD_DEL_TABLE_REPLY,
2402   ({
2403     if (rv == 0 && mp->is_add)
2404       {
2405         t = pool_elt_at_index (cm->tables, table_index);
2406         rmp->skip_n_vectors = ntohl(t->skip_n_vectors);
2407         rmp->match_n_vectors = ntohl(t->match_n_vectors);
2408         rmp->new_table_index = ntohl(table_index);
2409       }
2410     else
2411       {
2412         rmp->skip_n_vectors = ~0;
2413         rmp->match_n_vectors = ~0;
2414         rmp->new_table_index = ~0;
2415       }
2416   }));
2417   /* *INDENT-ON* */
2418 }
2419
2420 static void vl_api_classify_add_del_session_t_handler
2421   (vl_api_classify_add_del_session_t * mp)
2422 {
2423   vnet_classify_main_t *cm = &vnet_classify_main;
2424   vl_api_classify_add_del_session_reply_t *rmp;
2425   int rv;
2426   u32 table_index, hit_next_index, opaque_index, metadata;
2427   i32 advance;
2428   u8 action;
2429
2430   table_index = ntohl (mp->table_index);
2431   hit_next_index = ntohl (mp->hit_next_index);
2432   opaque_index = ntohl (mp->opaque_index);
2433   advance = ntohl (mp->advance);
2434   action = mp->action;
2435   metadata = ntohl (mp->metadata);
2436
2437   rv = vnet_classify_add_del_session
2438     (cm, table_index, mp->match, hit_next_index, opaque_index,
2439      advance, action, metadata, mp->is_add);
2440
2441   REPLY_MACRO (VL_API_CLASSIFY_ADD_DEL_SESSION_REPLY);
2442 }
2443
2444 static void vl_api_classify_set_interface_ip_table_t_handler
2445   (vl_api_classify_set_interface_ip_table_t * mp)
2446 {
2447   vlib_main_t *vm = vlib_get_main ();
2448   vl_api_classify_set_interface_ip_table_reply_t *rmp;
2449   int rv;
2450   u32 table_index, sw_if_index;
2451
2452   table_index = ntohl (mp->table_index);
2453   sw_if_index = ntohl (mp->sw_if_index);
2454
2455   VALIDATE_SW_IF_INDEX (mp);
2456
2457   if (mp->is_ipv6)
2458     rv = vnet_set_ip6_classify_intfc (vm, sw_if_index, table_index);
2459   else
2460     rv = vnet_set_ip4_classify_intfc (vm, sw_if_index, table_index);
2461
2462   BAD_SW_IF_INDEX_LABEL;
2463
2464   REPLY_MACRO (VL_API_CLASSIFY_SET_INTERFACE_IP_TABLE_REPLY);
2465 }
2466
2467 static void vl_api_classify_set_interface_l2_tables_t_handler
2468   (vl_api_classify_set_interface_l2_tables_t * mp)
2469 {
2470   vl_api_classify_set_interface_l2_tables_reply_t *rmp;
2471   int rv;
2472   u32 sw_if_index, ip4_table_index, ip6_table_index, other_table_index;
2473   int enable;
2474
2475   ip4_table_index = ntohl (mp->ip4_table_index);
2476   ip6_table_index = ntohl (mp->ip6_table_index);
2477   other_table_index = ntohl (mp->other_table_index);
2478   sw_if_index = ntohl (mp->sw_if_index);
2479
2480   VALIDATE_SW_IF_INDEX (mp);
2481
2482   if (mp->is_input)
2483     rv = vnet_l2_input_classify_set_tables (sw_if_index, ip4_table_index,
2484                                             ip6_table_index,
2485                                             other_table_index);
2486   else
2487     rv = vnet_l2_output_classify_set_tables (sw_if_index, ip4_table_index,
2488                                              ip6_table_index,
2489                                              other_table_index);
2490
2491   if (rv == 0)
2492     {
2493       if (ip4_table_index != ~0 || ip6_table_index != ~0
2494           || other_table_index != ~0)
2495         enable = 1;
2496       else
2497         enable = 0;
2498
2499       if (mp->is_input)
2500         vnet_l2_input_classify_enable_disable (sw_if_index, enable);
2501       else
2502         vnet_l2_output_classify_enable_disable (sw_if_index, enable);
2503     }
2504
2505   BAD_SW_IF_INDEX_LABEL;
2506
2507   REPLY_MACRO (VL_API_CLASSIFY_SET_INTERFACE_L2_TABLES_REPLY);
2508 }
2509
2510 static void
2511 vl_api_l2_fib_clear_table_t_handler (vl_api_l2_fib_clear_table_t * mp)
2512 {
2513   int rv = 0;
2514   vl_api_l2_fib_clear_table_reply_t *rmp;
2515
2516   /* DAW-FIXME: This API should only clear non-static l2fib entries, but
2517    *            that is not currently implemented.  When that TODO is fixed
2518    *            this call should be changed to pass 1 instead of 0.
2519    */
2520   l2fib_clear_table (0);
2521
2522   REPLY_MACRO (VL_API_L2_FIB_CLEAR_TABLE_REPLY);
2523 }
2524
2525 extern void l2_efp_filter_configure (vnet_main_t * vnet_main,
2526                                      u32 sw_if_index, u32 enable);
2527
2528 static void
2529 vl_api_l2_interface_efp_filter_t_handler (vl_api_l2_interface_efp_filter_t *
2530                                           mp)
2531 {
2532   int rv;
2533   vl_api_l2_interface_efp_filter_reply_t *rmp;
2534   vnet_main_t *vnm = vnet_get_main ();
2535
2536   // enable/disable the feature
2537   l2_efp_filter_configure (vnm, mp->sw_if_index, mp->enable_disable);
2538   rv = vnm->api_errno;
2539
2540   REPLY_MACRO (VL_API_L2_INTERFACE_EFP_FILTER_REPLY);
2541 }
2542
2543 static void
2544   vl_api_l2_interface_vlan_tag_rewrite_t_handler
2545   (vl_api_l2_interface_vlan_tag_rewrite_t * mp)
2546 {
2547   int rv = 0;
2548   vl_api_l2_interface_vlan_tag_rewrite_reply_t *rmp;
2549   vnet_main_t *vnm = vnet_get_main ();
2550   vlib_main_t *vm = vlib_get_main ();
2551   u32 vtr_op;
2552
2553   VALIDATE_SW_IF_INDEX (mp);
2554
2555   vtr_op = ntohl (mp->vtr_op);
2556
2557   /* The L2 code is unsuspicious */
2558   switch (vtr_op)
2559     {
2560     case L2_VTR_DISABLED:
2561     case L2_VTR_PUSH_1:
2562     case L2_VTR_PUSH_2:
2563     case L2_VTR_POP_1:
2564     case L2_VTR_POP_2:
2565     case L2_VTR_TRANSLATE_1_1:
2566     case L2_VTR_TRANSLATE_1_2:
2567     case L2_VTR_TRANSLATE_2_1:
2568     case L2_VTR_TRANSLATE_2_2:
2569       break;
2570
2571     default:
2572       rv = VNET_API_ERROR_INVALID_VALUE;
2573       goto bad_sw_if_index;
2574     }
2575
2576   rv = l2vtr_configure (vm, vnm, ntohl (mp->sw_if_index), vtr_op,
2577                         ntohl (mp->push_dot1q), ntohl (mp->tag1),
2578                         ntohl (mp->tag2));
2579
2580   BAD_SW_IF_INDEX_LABEL;
2581
2582   REPLY_MACRO (VL_API_L2_INTERFACE_VLAN_TAG_REWRITE_REPLY);
2583 }
2584
2585 static void
2586 vl_api_create_vhost_user_if_t_handler (vl_api_create_vhost_user_if_t * mp)
2587 {
2588   int rv = 0;
2589   vl_api_create_vhost_user_if_reply_t *rmp;
2590   u32 sw_if_index = (u32) ~ 0;
2591   vnet_main_t *vnm = vnet_get_main ();
2592   vlib_main_t *vm = vlib_get_main ();
2593
2594   rv = vhost_user_create_if (vnm, vm, (char *) mp->sock_filename,
2595                              mp->is_server, &sw_if_index, (u64) ~ 0,
2596                              mp->renumber, ntohl (mp->custom_dev_instance),
2597                              (mp->use_custom_mac) ? mp->mac_address : NULL);
2598
2599   /* Remember an interface tag for the new interface */
2600   if (rv == 0)
2601     {
2602       /* If a tag was supplied... */
2603       if (mp->tag[0])
2604         {
2605           /* Make sure it's a proper C-string */
2606           mp->tag[ARRAY_LEN (mp->tag) - 1] = 0;
2607           u8 *tag = format (0, "%s%c", mp->tag, 0);
2608           vnet_set_sw_interface_tag (vnm, tag, sw_if_index);
2609         }
2610     }
2611
2612   /* *INDENT-OFF* */
2613   REPLY_MACRO2(VL_API_CREATE_VHOST_USER_IF_REPLY,
2614   ({
2615     rmp->sw_if_index = ntohl (sw_if_index);
2616   }));
2617   /* *INDENT-ON* */
2618 }
2619
2620 static void
2621 vl_api_modify_vhost_user_if_t_handler (vl_api_modify_vhost_user_if_t * mp)
2622 {
2623   int rv = 0;
2624   vl_api_modify_vhost_user_if_reply_t *rmp;
2625   u32 sw_if_index = ntohl (mp->sw_if_index);
2626
2627   vnet_main_t *vnm = vnet_get_main ();
2628   vlib_main_t *vm = vlib_get_main ();
2629
2630   rv = vhost_user_modify_if (vnm, vm, (char *) mp->sock_filename,
2631                              mp->is_server, sw_if_index, (u64) ~ 0,
2632                              mp->renumber, ntohl (mp->custom_dev_instance));
2633
2634   REPLY_MACRO (VL_API_MODIFY_VHOST_USER_IF_REPLY);
2635 }
2636
2637 static void
2638 vl_api_delete_vhost_user_if_t_handler (vl_api_delete_vhost_user_if_t * mp)
2639 {
2640   int rv = 0;
2641   vl_api_delete_vhost_user_if_reply_t *rmp;
2642   vpe_api_main_t *vam = &vpe_api_main;
2643   u32 sw_if_index = ntohl (mp->sw_if_index);
2644
2645   vnet_main_t *vnm = vnet_get_main ();
2646   vlib_main_t *vm = vlib_get_main ();
2647
2648   rv = vhost_user_delete_if (vnm, vm, sw_if_index);
2649
2650   REPLY_MACRO (VL_API_DELETE_VHOST_USER_IF_REPLY);
2651   if (!rv)
2652     {
2653       unix_shared_memory_queue_t *q =
2654         vl_api_client_index_to_input_queue (mp->client_index);
2655       if (!q)
2656         return;
2657
2658       vnet_clear_sw_interface_tag (vnm, sw_if_index);
2659       send_sw_interface_flags_deleted (vam, q, sw_if_index);
2660     }
2661 }
2662
2663 static void
2664   vl_api_sw_interface_vhost_user_details_t_handler
2665   (vl_api_sw_interface_vhost_user_details_t * mp)
2666 {
2667   clib_warning ("BUG");
2668 }
2669
2670 static void
2671 send_sw_interface_vhost_user_details (vpe_api_main_t * am,
2672                                       unix_shared_memory_queue_t * q,
2673                                       vhost_user_intf_details_t * vui,
2674                                       u32 context)
2675 {
2676   vl_api_sw_interface_vhost_user_details_t *mp;
2677
2678   mp = vl_msg_api_alloc (sizeof (*mp));
2679   memset (mp, 0, sizeof (*mp));
2680   mp->_vl_msg_id = ntohs (VL_API_SW_INTERFACE_VHOST_USER_DETAILS);
2681   mp->sw_if_index = ntohl (vui->sw_if_index);
2682   mp->virtio_net_hdr_sz = ntohl (vui->virtio_net_hdr_sz);
2683   mp->features = clib_net_to_host_u64 (vui->features);
2684   mp->is_server = vui->is_server;
2685   mp->num_regions = ntohl (vui->num_regions);
2686   mp->sock_errno = ntohl (vui->sock_errno);
2687   mp->context = context;
2688
2689   strncpy ((char *) mp->sock_filename,
2690            (char *) vui->sock_filename, ARRAY_LEN (mp->sock_filename) - 1);
2691   strncpy ((char *) mp->interface_name,
2692            (char *) vui->if_name, ARRAY_LEN (mp->interface_name) - 1);
2693
2694   vl_msg_api_send_shmem (q, (u8 *) & mp);
2695 }
2696
2697 static void
2698   vl_api_sw_interface_vhost_user_dump_t_handler
2699   (vl_api_sw_interface_vhost_user_dump_t * mp)
2700 {
2701   int rv = 0;
2702   vpe_api_main_t *am = &vpe_api_main;
2703   vnet_main_t *vnm = vnet_get_main ();
2704   vlib_main_t *vm = vlib_get_main ();
2705   vhost_user_intf_details_t *ifaces = NULL;
2706   vhost_user_intf_details_t *vuid = NULL;
2707   unix_shared_memory_queue_t *q;
2708
2709   q = vl_api_client_index_to_input_queue (mp->client_index);
2710   if (q == 0)
2711     return;
2712
2713   rv = vhost_user_dump_ifs (vnm, vm, &ifaces);
2714   if (rv)
2715     return;
2716
2717   vec_foreach (vuid, ifaces)
2718   {
2719     send_sw_interface_vhost_user_details (am, q, vuid, mp->context);
2720   }
2721   vec_free (ifaces);
2722 }
2723
2724 static void
2725 send_sw_if_l2tpv3_tunnel_details (vpe_api_main_t * am,
2726                                   unix_shared_memory_queue_t * q,
2727                                   l2t_session_t * s,
2728                                   l2t_main_t * lm, u32 context)
2729 {
2730   vl_api_sw_if_l2tpv3_tunnel_details_t *mp;
2731   u8 *if_name = NULL;
2732   vnet_sw_interface_t *si = NULL;
2733
2734   si = vnet_get_hw_sw_interface (lm->vnet_main, s->hw_if_index);
2735
2736   if_name = format (if_name, "%U",
2737                     format_vnet_sw_interface_name, lm->vnet_main, si);
2738
2739   mp = vl_msg_api_alloc (sizeof (*mp));
2740   memset (mp, 0, sizeof (*mp));
2741   mp->_vl_msg_id = ntohs (VL_API_SW_IF_L2TPV3_TUNNEL_DETAILS);
2742   strncpy ((char *) mp->interface_name,
2743            (char *) if_name, ARRAY_LEN (mp->interface_name) - 1);
2744   mp->sw_if_index = ntohl (si->sw_if_index);
2745   mp->local_session_id = s->local_session_id;
2746   mp->remote_session_id = s->remote_session_id;
2747   mp->local_cookie[0] = s->local_cookie[0];
2748   mp->local_cookie[1] = s->local_cookie[1];
2749   mp->remote_cookie = s->remote_cookie;
2750   clib_memcpy (mp->client_address, &s->client_address,
2751                sizeof (s->client_address));
2752   clib_memcpy (mp->our_address, &s->our_address, sizeof (s->our_address));
2753   mp->l2_sublayer_present = s->l2_sublayer_present;
2754   mp->context = context;
2755
2756   vl_msg_api_send_shmem (q, (u8 *) & mp);
2757 }
2758
2759
2760 static void
2761 vl_api_sw_if_l2tpv3_tunnel_dump_t_handler (vl_api_sw_if_l2tpv3_tunnel_dump_t *
2762                                            mp)
2763 {
2764   vpe_api_main_t *am = &vpe_api_main;
2765   l2t_main_t *lm = &l2t_main;
2766   unix_shared_memory_queue_t *q;
2767   l2t_session_t *session;
2768
2769   q = vl_api_client_index_to_input_queue (mp->client_index);
2770   if (q == 0)
2771     return;
2772
2773   /* *INDENT-OFF* */
2774   pool_foreach (session, lm->sessions,
2775   ({
2776     send_sw_if_l2tpv3_tunnel_details (am, q, session, lm, mp->context);
2777   }));
2778   /* *INDENT-ON* */
2779 }
2780
2781 static void
2782 vl_api_l2_fib_table_entry_t_handler (vl_api_l2_fib_table_entry_t * mp)
2783 {
2784   clib_warning ("BUG");
2785 }
2786
2787 static void
2788 send_l2fib_table_entry (vpe_api_main_t * am,
2789                         unix_shared_memory_queue_t * q,
2790                         l2fib_entry_key_t * l2fe_key,
2791                         l2fib_entry_result_t * l2fe_res, u32 context)
2792 {
2793   vl_api_l2_fib_table_entry_t *mp;
2794
2795   mp = vl_msg_api_alloc (sizeof (*mp));
2796   memset (mp, 0, sizeof (*mp));
2797   mp->_vl_msg_id = ntohs (VL_API_L2_FIB_TABLE_ENTRY);
2798
2799   mp->bd_id =
2800     ntohl (l2input_main.bd_configs[l2fe_key->fields.bd_index].bd_id);
2801
2802   mp->mac = l2fib_make_key (l2fe_key->fields.mac, 0);
2803   mp->sw_if_index = ntohl (l2fe_res->fields.sw_if_index);
2804   mp->static_mac = l2fe_res->fields.static_mac;
2805   mp->filter_mac = l2fe_res->fields.filter;
2806   mp->bvi_mac = l2fe_res->fields.bvi;
2807   mp->context = context;
2808
2809   vl_msg_api_send_shmem (q, (u8 *) & mp);
2810 }
2811
2812 static void
2813 vl_api_l2_fib_table_dump_t_handler (vl_api_l2_fib_table_dump_t * mp)
2814 {
2815   vpe_api_main_t *am = &vpe_api_main;
2816   bd_main_t *bdm = &bd_main;
2817   l2fib_entry_key_t *l2fe_key = NULL;
2818   l2fib_entry_result_t *l2fe_res = NULL;
2819   u32 ni, bd_id = ntohl (mp->bd_id);
2820   u32 bd_index;
2821   unix_shared_memory_queue_t *q;
2822   uword *p;
2823
2824   q = vl_api_client_index_to_input_queue (mp->client_index);
2825   if (q == 0)
2826     return;
2827
2828   /* see l2fib_table_dump: ~0 means "any" */
2829   if (bd_id == ~0)
2830     bd_index = ~0;
2831   else
2832     {
2833       p = hash_get (bdm->bd_index_by_bd_id, bd_id);
2834       if (p == 0)
2835         return;
2836
2837       bd_index = p[0];
2838     }
2839
2840   l2fib_table_dump (bd_index, &l2fe_key, &l2fe_res);
2841
2842   vec_foreach_index (ni, l2fe_key)
2843   {
2844     send_l2fib_table_entry (am, q, vec_elt_at_index (l2fe_key, ni),
2845                             vec_elt_at_index (l2fe_res, ni), mp->context);
2846   }
2847   vec_free (l2fe_key);
2848   vec_free (l2fe_res);
2849 }
2850
2851 static void
2852 vl_api_show_version_t_handler (vl_api_show_version_t * mp)
2853 {
2854   vl_api_show_version_reply_t *rmp;
2855   int rv = 0;
2856   char *vpe_api_get_build_directory (void);
2857   char *vpe_api_get_version (void);
2858   char *vpe_api_get_build_date (void);
2859
2860   unix_shared_memory_queue_t *q =
2861     vl_api_client_index_to_input_queue (mp->client_index);
2862
2863   if (!q)
2864     return;
2865
2866   /* *INDENT-OFF* */
2867   REPLY_MACRO2(VL_API_SHOW_VERSION_REPLY,
2868   ({
2869     strncpy ((char *) rmp->program, "vpe", ARRAY_LEN(rmp->program)-1);
2870     strncpy ((char *) rmp->build_directory, vpe_api_get_build_directory(),
2871              ARRAY_LEN(rmp->build_directory)-1);
2872     strncpy ((char *) rmp->version, vpe_api_get_version(),
2873              ARRAY_LEN(rmp->version)-1);
2874     strncpy ((char *) rmp->build_date, vpe_api_get_build_date(),
2875              ARRAY_LEN(rmp->build_date)-1);
2876   }));
2877   /* *INDENT-ON* */
2878 }
2879
2880 static void
2881 vl_api_get_node_index_t_handler (vl_api_get_node_index_t * mp)
2882 {
2883   vlib_main_t *vm = vlib_get_main ();
2884   vl_api_get_node_index_reply_t *rmp;
2885   vlib_node_t *n;
2886   int rv = 0;
2887   u32 node_index = ~0;
2888
2889   n = vlib_get_node_by_name (vm, mp->node_name);
2890
2891   if (n == 0)
2892     rv = VNET_API_ERROR_NO_SUCH_NODE;
2893   else
2894     node_index = n->index;
2895
2896   /* *INDENT-OFF* */
2897   REPLY_MACRO2(VL_API_GET_NODE_INDEX_REPLY,
2898   ({
2899     rmp->node_index = ntohl(node_index);
2900   }));
2901   /* *INDENT-ON* */
2902 }
2903
2904 static void
2905 vl_api_get_next_index_t_handler (vl_api_get_next_index_t * mp)
2906 {
2907   vlib_main_t *vm = vlib_get_main ();
2908   vl_api_get_next_index_reply_t *rmp;
2909   vlib_node_t *node, *next_node;
2910   int rv = 0;
2911   u32 next_node_index = ~0, next_index = ~0;
2912   uword *p;
2913
2914   node = vlib_get_node_by_name (vm, mp->node_name);
2915
2916   if (node == 0)
2917     {
2918       rv = VNET_API_ERROR_NO_SUCH_NODE;
2919       goto out;
2920     }
2921
2922   next_node = vlib_get_node_by_name (vm, mp->next_name);
2923
2924   if (next_node == 0)
2925     {
2926       rv = VNET_API_ERROR_NO_SUCH_NODE2;
2927       goto out;
2928     }
2929   else
2930     next_node_index = next_node->index;
2931
2932   p = hash_get (node->next_slot_by_node, next_node_index);
2933
2934   if (p == 0)
2935     {
2936       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
2937       goto out;
2938     }
2939   else
2940     next_index = p[0];
2941
2942 out:
2943   /* *INDENT-OFF* */
2944   REPLY_MACRO2(VL_API_GET_NEXT_INDEX_REPLY,
2945   ({
2946     rmp->next_index = ntohl(next_index);
2947   }));
2948   /* *INDENT-ON* */
2949 }
2950
2951 static void
2952 vl_api_add_node_next_t_handler (vl_api_add_node_next_t * mp)
2953 {
2954   vlib_main_t *vm = vlib_get_main ();
2955   vl_api_add_node_next_reply_t *rmp;
2956   vlib_node_t *n, *next;
2957   int rv = 0;
2958   u32 next_index = ~0;
2959
2960   n = vlib_get_node_by_name (vm, mp->node_name);
2961
2962   if (n == 0)
2963     {
2964       rv = VNET_API_ERROR_NO_SUCH_NODE;
2965       goto out;
2966     }
2967
2968   next = vlib_get_node_by_name (vm, mp->next_name);
2969
2970   if (next == 0)
2971     rv = VNET_API_ERROR_NO_SUCH_NODE2;
2972   else
2973     next_index = vlib_node_add_next (vm, n->index, next->index);
2974
2975 out:
2976   /* *INDENT-OFF* */
2977   REPLY_MACRO2(VL_API_GET_NODE_INDEX_REPLY,
2978   ({
2979     rmp->next_index = ntohl(next_index);
2980   }));
2981   /* *INDENT-ON* */
2982 }
2983
2984 static void vl_api_l2tpv3_create_tunnel_t_handler
2985   (vl_api_l2tpv3_create_tunnel_t * mp)
2986 {
2987   vl_api_l2tpv3_create_tunnel_reply_t *rmp;
2988   l2t_main_t *lm = &l2t_main;
2989   u32 sw_if_index = (u32) ~ 0;
2990   int rv;
2991
2992   if (mp->is_ipv6 != 1)
2993     {
2994       rv = VNET_API_ERROR_UNIMPLEMENTED;
2995       goto out;
2996     }
2997
2998   u32 encap_fib_index;
2999
3000   if (mp->encap_vrf_id != ~0)
3001     {
3002       uword *p;
3003       ip6_main_t *im = &ip6_main;
3004       if (!
3005           (p =
3006            hash_get (im->fib_index_by_table_id, ntohl (mp->encap_vrf_id))))
3007         {
3008           rv = VNET_API_ERROR_NO_SUCH_FIB;
3009           goto out;
3010         }
3011       encap_fib_index = p[0];
3012     }
3013   else
3014     {
3015       encap_fib_index = ~0;
3016     }
3017
3018   rv = create_l2tpv3_ipv6_tunnel (lm,
3019                                   (ip6_address_t *) mp->client_address,
3020                                   (ip6_address_t *) mp->our_address,
3021                                   ntohl (mp->local_session_id),
3022                                   ntohl (mp->remote_session_id),
3023                                   clib_net_to_host_u64 (mp->local_cookie),
3024                                   clib_net_to_host_u64 (mp->remote_cookie),
3025                                   mp->l2_sublayer_present,
3026                                   encap_fib_index, &sw_if_index);
3027
3028 out:
3029   /* *INDENT-OFF* */
3030   REPLY_MACRO2(VL_API_L2TPV3_CREATE_TUNNEL_REPLY,
3031   ({
3032     rmp->sw_if_index = ntohl (sw_if_index);
3033   }));
3034   /* *INDENT-ON* */
3035 }
3036
3037 static void vl_api_l2tpv3_set_tunnel_cookies_t_handler
3038   (vl_api_l2tpv3_set_tunnel_cookies_t * mp)
3039 {
3040   vl_api_l2tpv3_set_tunnel_cookies_reply_t *rmp;
3041   l2t_main_t *lm = &l2t_main;
3042   int rv;
3043
3044   VALIDATE_SW_IF_INDEX (mp);
3045
3046   rv = l2tpv3_set_tunnel_cookies (lm, ntohl (mp->sw_if_index),
3047                                   clib_net_to_host_u64 (mp->new_local_cookie),
3048                                   clib_net_to_host_u64
3049                                   (mp->new_remote_cookie));
3050
3051   BAD_SW_IF_INDEX_LABEL;
3052
3053   REPLY_MACRO (VL_API_L2TPV3_SET_TUNNEL_COOKIES_REPLY);
3054 }
3055
3056 static void vl_api_l2tpv3_interface_enable_disable_t_handler
3057   (vl_api_l2tpv3_interface_enable_disable_t * mp)
3058 {
3059   int rv;
3060   vnet_main_t *vnm = vnet_get_main ();
3061   vl_api_l2tpv3_interface_enable_disable_reply_t *rmp;
3062
3063   VALIDATE_SW_IF_INDEX (mp);
3064
3065   rv = l2tpv3_interface_enable_disable
3066     (vnm, ntohl (mp->sw_if_index), mp->enable_disable);
3067
3068   BAD_SW_IF_INDEX_LABEL;
3069
3070   REPLY_MACRO (VL_API_L2TPV3_INTERFACE_ENABLE_DISABLE_REPLY);
3071 }
3072
3073 static void vl_api_l2tpv3_set_lookup_key_t_handler
3074   (vl_api_l2tpv3_set_lookup_key_t * mp)
3075 {
3076   int rv = 0;
3077   l2t_main_t *lm = &l2t_main;
3078   vl_api_l2tpv3_set_lookup_key_reply_t *rmp;
3079
3080   if (mp->key > L2T_LOOKUP_SESSION_ID)
3081     {
3082       rv = VNET_API_ERROR_INVALID_VALUE;
3083       goto out;
3084     }
3085
3086   lm->lookup_type = mp->key;
3087
3088 out:
3089   REPLY_MACRO (VL_API_L2TPV3_SET_LOOKUP_KEY_REPLY);
3090 }
3091
3092 static void vl_api_vxlan_add_del_tunnel_t_handler
3093   (vl_api_vxlan_add_del_tunnel_t * mp)
3094 {
3095   vl_api_vxlan_add_del_tunnel_reply_t *rmp;
3096   int rv = 0;
3097   vnet_vxlan_add_del_tunnel_args_t _a, *a = &_a;
3098   u32 encap_fib_index;
3099   uword *p;
3100   ip4_main_t *im = &ip4_main;
3101   vnet_main_t *vnm = vnet_get_main ();
3102   u32 sw_if_index = ~0;
3103
3104   p = hash_get (im->fib_index_by_table_id, ntohl (mp->encap_vrf_id));
3105   if (!p)
3106     {
3107       rv = VNET_API_ERROR_NO_SUCH_FIB;
3108       goto out;
3109     }
3110   encap_fib_index = p[0];
3111   memset (a, 0, sizeof (*a));
3112
3113   a->is_add = mp->is_add;
3114   a->is_ip6 = mp->is_ipv6;
3115
3116   /* ip addresses sent in network byte order */
3117   ip46_from_addr_buf (mp->is_ipv6, mp->dst_address, &a->dst);
3118   ip46_from_addr_buf (mp->is_ipv6, mp->src_address, &a->src);
3119
3120   /* Check src & dst are different */
3121   if (ip46_address_cmp (&a->dst, &a->src) == 0)
3122     {
3123       rv = VNET_API_ERROR_SAME_SRC_DST;
3124       goto out;
3125     }
3126   a->mcast_sw_if_index = ntohl (mp->mcast_sw_if_index);
3127   if (ip46_address_is_multicast (&a->dst) &&
3128       pool_is_free_index (vnm->interface_main.sw_interfaces,
3129                           a->mcast_sw_if_index))
3130     {
3131       rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
3132       goto out;
3133     }
3134   a->encap_fib_index = encap_fib_index;
3135   a->decap_next_index = ntohl (mp->decap_next_index);
3136   a->vni = ntohl (mp->vni);
3137   rv = vnet_vxlan_add_del_tunnel (a, &sw_if_index);
3138
3139 out:
3140   /* *INDENT-OFF* */
3141   REPLY_MACRO2(VL_API_VXLAN_ADD_DEL_TUNNEL_REPLY,
3142   ({
3143     rmp->sw_if_index = ntohl (sw_if_index);
3144   }));
3145   /* *INDENT-ON* */
3146 }
3147
3148 static void send_vxlan_tunnel_details
3149   (vxlan_tunnel_t * t, unix_shared_memory_queue_t * q, u32 context)
3150 {
3151   vl_api_vxlan_tunnel_details_t *rmp;
3152   ip4_main_t *im4 = &ip4_main;
3153   ip6_main_t *im6 = &ip6_main;
3154   u8 is_ipv6 = !ip46_address_is_ip4 (&t->dst);
3155
3156   rmp = vl_msg_api_alloc (sizeof (*rmp));
3157   memset (rmp, 0, sizeof (*rmp));
3158   rmp->_vl_msg_id = ntohs (VL_API_VXLAN_TUNNEL_DETAILS);
3159   if (is_ipv6)
3160     {
3161       memcpy (rmp->src_address, t->src.ip6.as_u8, 16);
3162       memcpy (rmp->dst_address, t->dst.ip6.as_u8, 16);
3163       rmp->encap_vrf_id = htonl (im6->fibs[t->encap_fib_index].ft_table_id);
3164     }
3165   else
3166     {
3167       memcpy (rmp->src_address, t->src.ip4.as_u8, 4);
3168       memcpy (rmp->dst_address, t->dst.ip4.as_u8, 4);
3169       rmp->encap_vrf_id = htonl (im4->fibs[t->encap_fib_index].ft_table_id);
3170     }
3171   rmp->mcast_sw_if_index = htonl (t->mcast_sw_if_index);
3172   rmp->vni = htonl (t->vni);
3173   rmp->decap_next_index = htonl (t->decap_next_index);
3174   rmp->sw_if_index = htonl (t->sw_if_index);
3175   rmp->is_ipv6 = is_ipv6;
3176   rmp->context = context;
3177
3178   vl_msg_api_send_shmem (q, (u8 *) & rmp);
3179 }
3180
3181 static void vl_api_vxlan_tunnel_dump_t_handler
3182   (vl_api_vxlan_tunnel_dump_t * mp)
3183 {
3184   unix_shared_memory_queue_t *q;
3185   vxlan_main_t *vxm = &vxlan_main;
3186   vxlan_tunnel_t *t;
3187   u32 sw_if_index;
3188
3189   q = vl_api_client_index_to_input_queue (mp->client_index);
3190   if (q == 0)
3191     {
3192       return;
3193     }
3194
3195   sw_if_index = ntohl (mp->sw_if_index);
3196
3197   if (~0 == sw_if_index)
3198     {
3199       /* *INDENT-OFF* */
3200       pool_foreach (t, vxm->tunnels,
3201       ({
3202         send_vxlan_tunnel_details(t, q, mp->context);
3203       }));
3204       /* *INDENT-ON* */
3205     }
3206   else
3207     {
3208       if ((sw_if_index >= vec_len (vxm->tunnel_index_by_sw_if_index)) ||
3209           (~0 == vxm->tunnel_index_by_sw_if_index[sw_if_index]))
3210         {
3211           return;
3212         }
3213       t = &vxm->tunnels[vxm->tunnel_index_by_sw_if_index[sw_if_index]];
3214       send_vxlan_tunnel_details (t, q, mp->context);
3215     }
3216 }
3217
3218 static void vl_api_gre_add_del_tunnel_t_handler
3219   (vl_api_gre_add_del_tunnel_t * mp)
3220 {
3221   vl_api_gre_add_del_tunnel_reply_t *rmp;
3222   int rv = 0;
3223   vnet_gre_add_del_tunnel_args_t _a, *a = &_a;
3224   u32 outer_fib_id;
3225   uword *p;
3226   ip4_main_t *im = &ip4_main;
3227   u32 sw_if_index = ~0;
3228
3229   p = hash_get (im->fib_index_by_table_id, ntohl (mp->outer_fib_id));
3230   if (!p)
3231     {
3232       rv = VNET_API_ERROR_NO_SUCH_FIB;
3233       goto out;
3234     }
3235   outer_fib_id = p[0];
3236
3237   /* Check src & dst are different */
3238   if ((mp->is_ipv6 && memcmp (mp->src_address, mp->dst_address, 16) == 0) ||
3239       (!mp->is_ipv6 && memcmp (mp->src_address, mp->dst_address, 4) == 0))
3240     {
3241       rv = VNET_API_ERROR_SAME_SRC_DST;
3242       goto out;
3243     }
3244   memset (a, 0, sizeof (*a));
3245
3246   a->is_add = mp->is_add;
3247   a->teb = mp->teb;
3248
3249   /* ip addresses sent in network byte order */
3250   clib_memcpy (&(a->src), mp->src_address, 4);
3251   clib_memcpy (&(a->dst), mp->dst_address, 4);
3252
3253   a->outer_fib_id = outer_fib_id;
3254   rv = vnet_gre_add_del_tunnel (a, &sw_if_index);
3255
3256 out:
3257   /* *INDENT-OFF* */
3258   REPLY_MACRO2(VL_API_GRE_ADD_DEL_TUNNEL_REPLY,
3259   ({
3260     rmp->sw_if_index = ntohl (sw_if_index);
3261   }));
3262   /* *INDENT-ON* */
3263 }
3264
3265 static void send_gre_tunnel_details
3266   (gre_tunnel_t * t, unix_shared_memory_queue_t * q, u32 context)
3267 {
3268   vl_api_gre_tunnel_details_t *rmp;
3269   ip4_main_t *im = &ip4_main;
3270
3271   rmp = vl_msg_api_alloc (sizeof (*rmp));
3272   memset (rmp, 0, sizeof (*rmp));
3273   rmp->_vl_msg_id = ntohs (VL_API_GRE_TUNNEL_DETAILS);
3274   clib_memcpy (rmp->src_address, &(t->tunnel_src), 4);
3275   clib_memcpy (rmp->dst_address, &(t->tunnel_dst), 4);
3276   rmp->outer_fib_id = htonl (im->fibs[t->outer_fib_index].ft_table_id);
3277   rmp->teb = (GRE_TUNNEL_TYPE_TEB == t->type);
3278   rmp->sw_if_index = htonl (t->sw_if_index);
3279   rmp->context = context;
3280
3281   vl_msg_api_send_shmem (q, (u8 *) & rmp);
3282 }
3283
3284 static void
3285 vl_api_gre_tunnel_dump_t_handler (vl_api_gre_tunnel_dump_t * mp)
3286 {
3287   unix_shared_memory_queue_t *q;
3288   gre_main_t *gm = &gre_main;
3289   gre_tunnel_t *t;
3290   u32 sw_if_index;
3291
3292   q = vl_api_client_index_to_input_queue (mp->client_index);
3293   if (q == 0)
3294     {
3295       return;
3296     }
3297
3298   sw_if_index = ntohl (mp->sw_if_index);
3299
3300   if (~0 == sw_if_index)
3301     {
3302       /* *INDENT-OFF* */
3303       pool_foreach (t, gm->tunnels,
3304       ({
3305         send_gre_tunnel_details(t, q, mp->context);
3306       }));
3307       /* *INDENT-ON* */
3308     }
3309   else
3310     {
3311       if ((sw_if_index >= vec_len (gm->tunnel_index_by_sw_if_index)) ||
3312           (~0 == gm->tunnel_index_by_sw_if_index[sw_if_index]))
3313         {
3314           return;
3315         }
3316       t = &gm->tunnels[gm->tunnel_index_by_sw_if_index[sw_if_index]];
3317       send_gre_tunnel_details (t, q, mp->context);
3318     }
3319 }
3320
3321 static void
3322 vl_api_l2_patch_add_del_t_handler (vl_api_l2_patch_add_del_t * mp)
3323 {
3324   extern int vnet_l2_patch_add_del (u32 rx_sw_if_index, u32 tx_sw_if_index,
3325                                     int is_add);
3326   vl_api_l2_patch_add_del_reply_t *rmp;
3327   int vnet_l2_patch_add_del (u32 rx_sw_if_index, u32 tx_sw_if_index,
3328                              int is_add);
3329   int rv = 0;
3330
3331   VALIDATE_RX_SW_IF_INDEX (mp);
3332   VALIDATE_TX_SW_IF_INDEX (mp);
3333
3334   rv = vnet_l2_patch_add_del (ntohl (mp->rx_sw_if_index),
3335                               ntohl (mp->tx_sw_if_index),
3336                               (int) (mp->is_add != 0));
3337
3338   BAD_RX_SW_IF_INDEX_LABEL;
3339   BAD_TX_SW_IF_INDEX_LABEL;
3340
3341   REPLY_MACRO (VL_API_L2_PATCH_ADD_DEL_REPLY);
3342 }
3343
3344 static void
3345   vl_api_vxlan_gpe_add_del_tunnel_t_handler
3346   (vl_api_vxlan_gpe_add_del_tunnel_t * mp)
3347 {
3348   vl_api_vxlan_gpe_add_del_tunnel_reply_t *rmp;
3349   int rv = 0;
3350   vnet_vxlan_gpe_add_del_tunnel_args_t _a, *a = &_a;
3351   u32 encap_fib_index, decap_fib_index;
3352   u8 protocol;
3353   uword *p;
3354   ip4_main_t *im = &ip4_main;
3355   u32 sw_if_index = ~0;
3356
3357
3358   p = hash_get (im->fib_index_by_table_id, ntohl (mp->encap_vrf_id));
3359   if (!p)
3360     {
3361       rv = VNET_API_ERROR_NO_SUCH_FIB;
3362       goto out;
3363     }
3364   encap_fib_index = p[0];
3365
3366   protocol = mp->protocol;
3367
3368   /* Interpret decap_vrf_id as an opaque if sending to other-than-ip4-input */
3369   if (protocol == VXLAN_GPE_INPUT_NEXT_IP4_INPUT)
3370     {
3371       p = hash_get (im->fib_index_by_table_id, ntohl (mp->decap_vrf_id));
3372       if (!p)
3373         {
3374           rv = VNET_API_ERROR_NO_SUCH_INNER_FIB;
3375           goto out;
3376         }
3377       decap_fib_index = p[0];
3378     }
3379   else
3380     {
3381       decap_fib_index = ntohl (mp->decap_vrf_id);
3382     }
3383
3384   /* Check src & dst are different */
3385   if ((mp->is_ipv6 && memcmp (mp->local, mp->remote, 16) == 0) ||
3386       (!mp->is_ipv6 && memcmp (mp->local, mp->remote, 4) == 0))
3387     {
3388       rv = VNET_API_ERROR_SAME_SRC_DST;
3389       goto out;
3390     }
3391   memset (a, 0, sizeof (*a));
3392
3393   a->is_add = mp->is_add;
3394   a->is_ip6 = mp->is_ipv6;
3395   /* ip addresses sent in network byte order */
3396   if (a->is_ip6)
3397     {
3398       clib_memcpy (&(a->local.ip6), mp->local, 16);
3399       clib_memcpy (&(a->remote.ip6), mp->remote, 16);
3400     }
3401   else
3402     {
3403       clib_memcpy (&(a->local.ip4), mp->local, 4);
3404       clib_memcpy (&(a->remote.ip4), mp->remote, 4);
3405     }
3406   a->encap_fib_index = encap_fib_index;
3407   a->decap_fib_index = decap_fib_index;
3408   a->protocol = protocol;
3409   a->vni = ntohl (mp->vni);
3410   rv = vnet_vxlan_gpe_add_del_tunnel (a, &sw_if_index);
3411
3412 out:
3413   /* *INDENT-OFF* */
3414   REPLY_MACRO2(VL_API_VXLAN_GPE_ADD_DEL_TUNNEL_REPLY,
3415   ({
3416     rmp->sw_if_index = ntohl (sw_if_index);
3417   }));
3418   /* *INDENT-ON* */
3419 }
3420
3421 static void send_vxlan_gpe_tunnel_details
3422   (vxlan_gpe_tunnel_t * t, unix_shared_memory_queue_t * q, u32 context)
3423 {
3424   vl_api_vxlan_gpe_tunnel_details_t *rmp;
3425   ip4_main_t *im4 = &ip4_main;
3426   ip6_main_t *im6 = &ip6_main;
3427   u8 is_ipv6 = !(t->flags & VXLAN_GPE_TUNNEL_IS_IPV4);
3428
3429   rmp = vl_msg_api_alloc (sizeof (*rmp));
3430   memset (rmp, 0, sizeof (*rmp));
3431   rmp->_vl_msg_id = ntohs (VL_API_VXLAN_GPE_TUNNEL_DETAILS);
3432   if (is_ipv6)
3433     {
3434       memcpy (rmp->local, &(t->local.ip6), 16);
3435       memcpy (rmp->remote, &(t->remote.ip6), 16);
3436       rmp->encap_vrf_id = htonl (im6->fibs[t->encap_fib_index].ft_table_id);
3437       rmp->decap_vrf_id = htonl (im6->fibs[t->decap_fib_index].ft_table_id);
3438     }
3439   else
3440     {
3441       memcpy (rmp->local, &(t->local.ip4), 4);
3442       memcpy (rmp->remote, &(t->remote.ip4), 4);
3443       rmp->encap_vrf_id = htonl (im4->fibs[t->encap_fib_index].ft_table_id);
3444       rmp->decap_vrf_id = htonl (im4->fibs[t->decap_fib_index].ft_table_id);
3445     }
3446   rmp->vni = htonl (t->vni);
3447   rmp->protocol = t->protocol;
3448   rmp->sw_if_index = htonl (t->sw_if_index);
3449   rmp->is_ipv6 = is_ipv6;
3450   rmp->context = context;
3451
3452   vl_msg_api_send_shmem (q, (u8 *) & rmp);
3453 }
3454
3455 static void vl_api_vxlan_gpe_tunnel_dump_t_handler
3456   (vl_api_vxlan_gpe_tunnel_dump_t * mp)
3457 {
3458   unix_shared_memory_queue_t *q;
3459   vxlan_gpe_main_t *vgm = &vxlan_gpe_main;
3460   vxlan_gpe_tunnel_t *t;
3461   u32 sw_if_index;
3462
3463   q = vl_api_client_index_to_input_queue (mp->client_index);
3464   if (q == 0)
3465     {
3466       return;
3467     }
3468
3469   sw_if_index = ntohl (mp->sw_if_index);
3470
3471   if (~0 == sw_if_index)
3472     {
3473       /* *INDENT-OFF* */
3474       pool_foreach (t, vgm->tunnels,
3475       ({
3476         send_vxlan_gpe_tunnel_details(t, q, mp->context);
3477       }));
3478       /* *INDENT-ON* */
3479     }
3480   else
3481     {
3482       if ((sw_if_index >= vec_len (vgm->tunnel_index_by_sw_if_index)) ||
3483           (~0 == vgm->tunnel_index_by_sw_if_index[sw_if_index]))
3484         {
3485           return;
3486         }
3487       t = &vgm->tunnels[vgm->tunnel_index_by_sw_if_index[sw_if_index]];
3488       send_vxlan_gpe_tunnel_details (t, q, mp->context);
3489     }
3490 }
3491
3492 /** Used for transferring locators via VPP API */
3493 /* *INDENT-OFF* */
3494 typedef CLIB_PACKED (struct {
3495   u32 sw_if_index; /**< locator sw_if_index */
3496   u8 priority; /**< locator priority */
3497   u8 weight; /**< locator weight */
3498 }) ls_locator_t;
3499 /* *INDENT-ON* */
3500
3501 static void
3502 vl_api_lisp_add_del_locator_set_t_handler (vl_api_lisp_add_del_locator_set_t *
3503                                            mp)
3504 {
3505   vl_api_lisp_add_del_locator_set_reply_t *rmp;
3506   int rv = 0;
3507   vnet_lisp_add_del_locator_set_args_t _a, *a = &_a;
3508   locator_t locator;
3509   ls_locator_t *ls_loc;
3510   u32 ls_index = ~0, locator_num;
3511   u8 *locator_name = NULL;
3512   int i;
3513
3514   memset (a, 0, sizeof (a[0]));
3515
3516   locator_name = format (0, "%s", mp->locator_set_name);
3517
3518   a->name = locator_name;
3519   a->is_add = mp->is_add;
3520   a->local = 1;
3521   locator_num = clib_net_to_host_u32 (mp->locator_num);
3522
3523   memset (&locator, 0, sizeof (locator));
3524   for (i = 0; i < locator_num; i++)
3525     {
3526       ls_loc = &((ls_locator_t *) mp->locators)[i];
3527       VALIDATE_SW_IF_INDEX (ls_loc);
3528
3529       locator.sw_if_index = htonl (ls_loc->sw_if_index);
3530       locator.priority = ls_loc->priority;
3531       locator.weight = ls_loc->weight;
3532       locator.local = 1;
3533       vec_add1 (a->locators, locator);
3534     }
3535
3536   rv = vnet_lisp_add_del_locator_set (a, &ls_index);
3537
3538   BAD_SW_IF_INDEX_LABEL;
3539
3540   vec_free (locator_name);
3541   vec_free (a->locators);
3542
3543   /* *INDENT-OFF* */
3544   REPLY_MACRO2 (VL_API_LISP_ADD_DEL_LOCATOR_SET_REPLY,
3545   ({
3546     rmp->ls_index = clib_host_to_net_u32 (ls_index);
3547   }));
3548   /* *INDENT-ON* */
3549 }
3550
3551 static void
3552 vl_api_lisp_add_del_locator_t_handler (vl_api_lisp_add_del_locator_t * mp)
3553 {
3554   vl_api_lisp_add_del_locator_reply_t *rmp;
3555   int rv = 0;
3556   locator_t locator, *locators = NULL;
3557   vnet_lisp_add_del_locator_set_args_t _a, *a = &_a;
3558   u32 ls_index = ~0;
3559   u8 *locator_name = NULL;
3560
3561   memset (&locator, 0, sizeof (locator));
3562   memset (a, 0, sizeof (a[0]));
3563
3564   locator.sw_if_index = ntohl (mp->sw_if_index);
3565   locator.priority = mp->priority;
3566   locator.weight = mp->weight;
3567   locator.local = 1;
3568   vec_add1 (locators, locator);
3569
3570   locator_name = format (0, "%s", mp->locator_set_name);
3571
3572   a->name = locator_name;
3573   a->locators = locators;
3574   a->is_add = mp->is_add;
3575   a->local = 1;
3576
3577   rv = vnet_lisp_add_del_locator (a, NULL, &ls_index);
3578
3579   vec_free (locators);
3580   vec_free (locator_name);
3581
3582   REPLY_MACRO (VL_API_LISP_ADD_DEL_LOCATOR_REPLY);
3583 }
3584
3585 static int
3586 unformat_lisp_eid_api (gid_address_t * dst, u32 vni, u8 type, void *src,
3587                        u8 len)
3588 {
3589   switch (type)
3590     {
3591     case 0:                     /* ipv4 */
3592       gid_address_type (dst) = GID_ADDR_IP_PREFIX;
3593       gid_address_ip_set (dst, src, IP4);
3594       gid_address_ippref_len (dst) = len;
3595       ip_prefix_normalize (&gid_address_ippref (dst));
3596       break;
3597     case 1:                     /* ipv6 */
3598       gid_address_type (dst) = GID_ADDR_IP_PREFIX;
3599       gid_address_ip_set (dst, src, IP6);
3600       gid_address_ippref_len (dst) = len;
3601       ip_prefix_normalize (&gid_address_ippref (dst));
3602       break;
3603     case 2:                     /* l2 mac */
3604       gid_address_type (dst) = GID_ADDR_MAC;
3605       clib_memcpy (&gid_address_mac (dst), src, 6);
3606       break;
3607     default:
3608       /* unknown type */
3609       return VNET_API_ERROR_INVALID_VALUE;
3610     }
3611
3612   gid_address_vni (dst) = vni;
3613
3614   return 0;
3615 }
3616
3617 static void
3618 vl_api_lisp_add_del_local_eid_t_handler (vl_api_lisp_add_del_local_eid_t * mp)
3619 {
3620   vl_api_lisp_add_del_local_eid_reply_t *rmp;
3621   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
3622   int rv = 0;
3623   gid_address_t _eid, *eid = &_eid;
3624   uword *p = NULL;
3625   u32 locator_set_index = ~0, map_index = ~0;
3626   vnet_lisp_add_del_mapping_args_t _a, *a = &_a;
3627   u8 *name = NULL, *key = NULL;
3628   memset (a, 0, sizeof (a[0]));
3629   memset (eid, 0, sizeof (eid[0]));
3630
3631   rv = unformat_lisp_eid_api (eid, clib_net_to_host_u32 (mp->vni),
3632                               mp->eid_type, mp->eid, mp->prefix_len);
3633   if (rv)
3634     goto out;
3635
3636   name = format (0, "%s", mp->locator_set_name);
3637   p = hash_get_mem (lcm->locator_set_index_by_name, name);
3638   if (!p)
3639     {
3640       rv = VNET_API_ERROR_INVALID_VALUE;
3641       goto out;
3642     }
3643   locator_set_index = p[0];
3644
3645   if (*mp->key)
3646     key = format (0, "%s", mp->key);
3647
3648   /* XXX treat batch configuration */
3649   a->is_add = mp->is_add;
3650   gid_address_copy (&a->eid, eid);
3651   a->locator_set_index = locator_set_index;
3652   a->local = 1;
3653   a->key = key;
3654   a->key_id = clib_net_to_host_u16 (mp->key_id);
3655
3656   rv = vnet_lisp_add_del_local_mapping (a, &map_index);
3657
3658 out:
3659   vec_free (name);
3660   vec_free (key);
3661   gid_address_free (&a->eid);
3662
3663   REPLY_MACRO (VL_API_LISP_ADD_DEL_LOCAL_EID_REPLY);
3664 }
3665
3666 static void
3667   vl_api_lisp_eid_table_add_del_map_t_handler
3668   (vl_api_lisp_eid_table_add_del_map_t * mp)
3669 {
3670   vl_api_lisp_eid_table_add_del_map_reply_t *rmp;
3671   int rv = 0;
3672   rv = vnet_lisp_eid_table_map (clib_net_to_host_u32 (mp->vni),
3673                                 clib_net_to_host_u32 (mp->dp_table),
3674                                 mp->is_l2, mp->is_add);
3675 REPLY_MACRO (VL_API_LISP_EID_TABLE_ADD_DEL_MAP_REPLY)}
3676
3677 /** Used for transferring locators via VPP API */
3678 /* *INDENT-OFF* */
3679 typedef CLIB_PACKED (struct {
3680   u8 is_ip4; /**< is locator an IPv4 address */
3681   u8 priority; /**< locator priority */
3682   u8 weight; /**< locator weight */
3683   u8 addr[16]; /**< IPv4/IPv6 address */
3684 }) rloc_t;
3685 /* *INDENT-ON* */
3686
3687 static locator_pair_t *
3688 unformat_lisp_loc_pairs (void *lcl_locs, void *rmt_locs, u32 rloc_num)
3689 {
3690   u32 i;
3691   locator_pair_t *pairs = 0, pair;
3692   rloc_t *r;
3693
3694   for (i = 0; i < rloc_num; i++)
3695     {
3696       /* local locator */
3697       r = &((rloc_t *) lcl_locs)[i];
3698       memset (&pair.lcl_loc, 0, sizeof (pair.lcl_loc));
3699       ip_address_set (&pair.lcl_loc, &r->addr, r->is_ip4 ? IP4 : IP6);
3700
3701       /* remote locators */
3702       r = &((rloc_t *) rmt_locs)[i];
3703       memset (&pair.rmt_loc, 0, sizeof (pair.rmt_loc));
3704       ip_address_set (&pair.rmt_loc, &r->addr, r->is_ip4 ? IP4 : IP6);
3705
3706       pair.priority = r->priority;
3707       pair.weight = r->weight;
3708
3709       vec_add1 (pairs, pair);
3710     }
3711   return pairs;
3712 }
3713
3714 static locator_t *
3715 unformat_lisp_locs (void *rmt_locs, u32 rloc_num)
3716 {
3717   u32 i;
3718   locator_t *locs = 0, loc;
3719   rloc_t *r;
3720
3721   for (i = 0; i < rloc_num; i++)
3722     {
3723       /* remote locators */
3724       r = &((rloc_t *) rmt_locs)[i];
3725       memset (&loc, 0, sizeof (loc));
3726       gid_address_ip_set (&loc.address, &r->addr, r->is_ip4 ? IP4 : IP6);
3727
3728       loc.priority = r->priority;
3729       loc.weight = r->weight;
3730
3731       vec_add1 (locs, loc);
3732     }
3733   return locs;
3734 }
3735
3736 static void
3737   vl_api_lisp_gpe_add_del_fwd_entry_t_handler
3738   (vl_api_lisp_gpe_add_del_fwd_entry_t * mp)
3739 {
3740   vl_api_lisp_gpe_add_del_fwd_entry_reply_t *rmp;
3741   vnet_lisp_gpe_add_del_fwd_entry_args_t _a, *a = &_a;
3742   locator_pair_t *pairs = 0;
3743   int rv = 0;
3744
3745   memset (a, 0, sizeof (a[0]));
3746
3747   rv = unformat_lisp_eid_api (&a->rmt_eid, mp->vni, mp->eid_type,
3748                               mp->rmt_eid, mp->rmt_len);
3749   rv |= unformat_lisp_eid_api (&a->lcl_eid, mp->vni, mp->eid_type,
3750                                mp->lcl_eid, mp->lcl_len);
3751
3752   pairs = unformat_lisp_loc_pairs (mp->lcl_locs, mp->rmt_locs, mp->loc_num);
3753
3754   if (rv || 0 == pairs)
3755     goto send_reply;
3756
3757   a->is_add = mp->is_add;
3758   a->locator_pairs = pairs;
3759   a->dp_table = mp->dp_table;
3760   a->vni = mp->vni;
3761   a->action = mp->action;
3762
3763   rv = vnet_lisp_gpe_add_del_fwd_entry (a, 0);
3764   vec_free (pairs);
3765 send_reply:
3766   REPLY_MACRO (VL_API_LISP_GPE_ADD_DEL_FWD_ENTRY_REPLY);
3767 }
3768
3769 static void
3770 vl_api_lisp_add_del_map_server_t_handler (vl_api_lisp_add_del_map_server_t
3771                                           * mp)
3772 {
3773   vl_api_lisp_add_del_map_server_reply_t *rmp;
3774   int rv = 0;
3775   ip_address_t addr;
3776
3777   memset (&addr, 0, sizeof (addr));
3778
3779   ip_address_set (&addr, mp->ip_address, mp->is_ipv6 ? IP6 : IP4);
3780   rv = vnet_lisp_add_del_map_server (&addr, mp->is_add);
3781
3782   REPLY_MACRO (VL_API_LISP_ADD_DEL_MAP_SERVER_REPLY);
3783 }
3784
3785 static void
3786 vl_api_lisp_add_del_map_resolver_t_handler (vl_api_lisp_add_del_map_resolver_t
3787                                             * mp)
3788 {
3789   vl_api_lisp_add_del_map_resolver_reply_t *rmp;
3790   int rv = 0;
3791   vnet_lisp_add_del_map_resolver_args_t _a, *a = &_a;
3792
3793   memset (a, 0, sizeof (a[0]));
3794
3795   a->is_add = mp->is_add;
3796   ip_address_set (&a->address, mp->ip_address, mp->is_ipv6 ? IP6 : IP4);
3797
3798   rv = vnet_lisp_add_del_map_resolver (a);
3799
3800   REPLY_MACRO (VL_API_LISP_ADD_DEL_MAP_RESOLVER_REPLY);
3801 }
3802
3803 static void
3804 vl_api_lisp_gpe_enable_disable_t_handler (vl_api_lisp_gpe_enable_disable_t *
3805                                           mp)
3806 {
3807   vl_api_lisp_gpe_enable_disable_reply_t *rmp;
3808   int rv = 0;
3809   vnet_lisp_gpe_enable_disable_args_t _a, *a = &_a;
3810
3811   a->is_en = mp->is_en;
3812   vnet_lisp_gpe_enable_disable (a);
3813
3814   REPLY_MACRO (VL_API_LISP_GPE_ENABLE_DISABLE_REPLY);
3815 }
3816
3817 static void
3818   vl_api_lisp_map_register_enable_disable_t_handler
3819   (vl_api_lisp_map_register_enable_disable_t * mp)
3820 {
3821   vl_api_lisp_map_register_enable_disable_reply_t *rmp;
3822   int rv = 0;
3823
3824   vnet_lisp_map_register_enable_disable (mp->is_enabled);
3825   REPLY_MACRO (VL_API_LISP_ENABLE_DISABLE_REPLY);
3826 }
3827
3828 static void
3829   vl_api_lisp_rloc_probe_enable_disable_t_handler
3830   (vl_api_lisp_rloc_probe_enable_disable_t * mp)
3831 {
3832   vl_api_lisp_rloc_probe_enable_disable_reply_t *rmp;
3833   int rv = 0;
3834
3835   vnet_lisp_rloc_probe_enable_disable (mp->is_enabled);
3836   REPLY_MACRO (VL_API_LISP_ENABLE_DISABLE_REPLY);
3837 }
3838
3839 static void
3840 vl_api_lisp_enable_disable_t_handler (vl_api_lisp_enable_disable_t * mp)
3841 {
3842   vl_api_lisp_enable_disable_reply_t *rmp;
3843   int rv = 0;
3844
3845   vnet_lisp_enable_disable (mp->is_en);
3846   REPLY_MACRO (VL_API_LISP_ENABLE_DISABLE_REPLY);
3847 }
3848
3849 static void
3850 vl_api_lisp_gpe_add_del_iface_t_handler (vl_api_lisp_gpe_add_del_iface_t * mp)
3851 {
3852   vl_api_lisp_gpe_add_del_iface_reply_t *rmp;
3853   int rv = 0;
3854
3855   if (mp->is_l2)
3856     {
3857       if (mp->is_add)
3858         {
3859           if (~0 ==
3860               lisp_gpe_tenant_l2_iface_add_or_lock (mp->vni, mp->dp_table))
3861             rv = 1;
3862         }
3863       else
3864         lisp_gpe_tenant_l2_iface_unlock (mp->vni);
3865     }
3866   else
3867     {
3868       if (mp->is_add)
3869         {
3870           if (~0 ==
3871               lisp_gpe_tenant_l3_iface_add_or_lock (mp->vni, mp->dp_table))
3872             rv = 1;
3873         }
3874       else
3875         lisp_gpe_tenant_l3_iface_unlock (mp->vni);
3876     }
3877
3878   REPLY_MACRO (VL_API_LISP_GPE_ADD_DEL_IFACE_REPLY);
3879 }
3880
3881 static void
3882   vl_api_show_lisp_map_request_mode_t_handler
3883   (vl_api_show_lisp_map_request_mode_t * mp)
3884 {
3885   int rv = 0;
3886   vl_api_show_lisp_map_request_mode_reply_t *rmp;
3887
3888   /* *INDENT-OFF* */
3889   REPLY_MACRO2(VL_API_SHOW_LISP_MAP_REQUEST_MODE_REPLY,
3890   ({
3891     rmp->mode = vnet_lisp_get_map_request_mode ();
3892   }));
3893   /* *INDENT-ON* */
3894 }
3895
3896 static void
3897 vl_api_lisp_map_request_mode_t_handler (vl_api_lisp_map_request_mode_t * mp)
3898 {
3899   vl_api_lisp_map_request_mode_reply_t *rmp;
3900   int rv = 0;
3901
3902   rv = vnet_lisp_set_map_request_mode (mp->mode);
3903
3904   REPLY_MACRO (VL_API_LISP_MAP_REQUEST_MODE_REPLY);
3905 }
3906
3907 static void
3908 vl_api_lisp_pitr_set_locator_set_t_handler (vl_api_lisp_pitr_set_locator_set_t
3909                                             * mp)
3910 {
3911   vl_api_lisp_pitr_set_locator_set_reply_t *rmp;
3912   int rv = 0;
3913   u8 *ls_name = 0;
3914
3915   ls_name = format (0, "%s", mp->ls_name);
3916   rv = vnet_lisp_pitr_set_locator_set (ls_name, mp->is_add);
3917   vec_free (ls_name);
3918
3919   REPLY_MACRO (VL_API_LISP_PITR_SET_LOCATOR_SET_REPLY);
3920 }
3921
3922 static void
3923   vl_api_lisp_add_del_map_request_itr_rlocs_t_handler
3924   (vl_api_lisp_add_del_map_request_itr_rlocs_t * mp)
3925 {
3926   vl_api_lisp_add_del_map_request_itr_rlocs_reply_t *rmp;
3927   int rv = 0;
3928   u8 *locator_set_name = NULL;
3929   vnet_lisp_add_del_mreq_itr_rloc_args_t _a, *a = &_a;
3930
3931   locator_set_name = format (0, "%s", mp->locator_set_name);
3932
3933   a->is_add = mp->is_add;
3934   a->locator_set_name = locator_set_name;
3935
3936   rv = vnet_lisp_add_del_mreq_itr_rlocs (a);
3937
3938   vec_free (locator_set_name);
3939
3940   REPLY_MACRO (VL_API_LISP_ADD_DEL_MAP_REQUEST_ITR_RLOCS_REPLY);
3941 }
3942
3943 static void
3944   vl_api_lisp_add_del_remote_mapping_t_handler
3945   (vl_api_lisp_add_del_remote_mapping_t * mp)
3946 {
3947   locator_t *rlocs = 0;
3948   vl_api_lisp_add_del_remote_mapping_reply_t *rmp;
3949   int rv = 0;
3950   gid_address_t _eid, *eid = &_eid;
3951   u32 rloc_num = clib_net_to_host_u32 (mp->rloc_num);
3952
3953   memset (eid, 0, sizeof (eid[0]));
3954
3955   rv = unformat_lisp_eid_api (eid, clib_net_to_host_u32 (mp->vni),
3956                               mp->eid_type, mp->eid, mp->eid_len);
3957   if (rv)
3958     goto send_reply;
3959
3960   rlocs = unformat_lisp_locs (mp->rlocs, rloc_num);
3961
3962   if (!mp->is_add)
3963     {
3964       vnet_lisp_add_del_adjacency_args_t _a, *a = &_a;
3965       gid_address_copy (&a->reid, eid);
3966       a->is_add = 0;
3967       rv = vnet_lisp_add_del_adjacency (a);
3968       if (rv)
3969         {
3970           goto out;
3971         }
3972     }
3973
3974   /* NOTE: for now this works as a static remote mapping, i.e.,
3975    * not authoritative and ttl infinite. */
3976   rv = vnet_lisp_add_del_mapping (eid, rlocs, mp->action, 0, ~0,
3977                                   mp->is_add, 1 /* is_static */ , 0);
3978
3979   if (mp->del_all)
3980     vnet_lisp_clear_all_remote_adjacencies ();
3981
3982 out:
3983   vec_free (rlocs);
3984 send_reply:
3985   REPLY_MACRO (VL_API_LISP_ADD_DEL_REMOTE_MAPPING_REPLY);
3986 }
3987
3988 static void
3989 vl_api_lisp_add_del_adjacency_t_handler (vl_api_lisp_add_del_adjacency_t * mp)
3990 {
3991   vl_api_lisp_add_del_adjacency_reply_t *rmp;
3992   vnet_lisp_add_del_adjacency_args_t _a, *a = &_a;
3993
3994   int rv = 0;
3995   memset (a, 0, sizeof (a[0]));
3996
3997   rv = unformat_lisp_eid_api (&a->leid, clib_net_to_host_u32 (mp->vni),
3998                               mp->eid_type, mp->leid, mp->leid_len);
3999   rv |= unformat_lisp_eid_api (&a->reid, clib_net_to_host_u32 (mp->vni),
4000                                mp->eid_type, mp->reid, mp->reid_len);
4001
4002   if (rv)
4003     goto send_reply;
4004
4005   a->is_add = mp->is_add;
4006   rv = vnet_lisp_add_del_adjacency (a);
4007
4008 send_reply:
4009   REPLY_MACRO (VL_API_LISP_ADD_DEL_ADJACENCY_REPLY);
4010 }
4011
4012 static void
4013 send_lisp_locator_details (lisp_cp_main_t * lcm,
4014                            locator_t * loc,
4015                            unix_shared_memory_queue_t * q, u32 context)
4016 {
4017   vl_api_lisp_locator_details_t *rmp;
4018
4019   rmp = vl_msg_api_alloc (sizeof (*rmp));
4020   memset (rmp, 0, sizeof (*rmp));
4021   rmp->_vl_msg_id = ntohs (VL_API_LISP_LOCATOR_DETAILS);
4022   rmp->context = context;
4023
4024   rmp->local = loc->local;
4025   if (loc->local)
4026     {
4027       rmp->sw_if_index = ntohl (loc->sw_if_index);
4028     }
4029   else
4030     {
4031       rmp->is_ipv6 = gid_address_ip_version (&loc->address);
4032       ip_address_copy_addr (rmp->ip_address, &gid_address_ip (&loc->address));
4033     }
4034   rmp->priority = loc->priority;
4035   rmp->weight = loc->weight;
4036
4037   vl_msg_api_send_shmem (q, (u8 *) & rmp);
4038 }
4039
4040 static void
4041 vl_api_lisp_locator_dump_t_handler (vl_api_lisp_locator_dump_t * mp)
4042 {
4043   u8 *ls_name = 0;
4044   unix_shared_memory_queue_t *q = 0;
4045   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
4046   locator_set_t *lsit = 0;
4047   locator_t *loc = 0;
4048   u32 ls_index = ~0, *locit = 0;
4049   uword *p = 0;
4050
4051   q = vl_api_client_index_to_input_queue (mp->client_index);
4052   if (q == 0)
4053     {
4054       return;
4055     }
4056
4057   if (mp->is_index_set)
4058     ls_index = htonl (mp->ls_index);
4059   else
4060     {
4061       /* make sure we get a proper C-string */
4062       mp->ls_name[sizeof (mp->ls_name) - 1] = 0;
4063       ls_name = format (0, "%s", mp->ls_name);
4064       p = hash_get_mem (lcm->locator_set_index_by_name, ls_name);
4065       if (!p)
4066         goto out;
4067       ls_index = p[0];
4068     }
4069
4070   if (pool_is_free_index (lcm->locator_set_pool, ls_index))
4071     return;
4072
4073   lsit = pool_elt_at_index (lcm->locator_set_pool, ls_index);
4074
4075   vec_foreach (locit, lsit->locator_indices)
4076   {
4077     loc = pool_elt_at_index (lcm->locator_pool, locit[0]);
4078     send_lisp_locator_details (lcm, loc, q, mp->context);
4079   };
4080 out:
4081   vec_free (ls_name);
4082 }
4083
4084 static void
4085 send_lisp_locator_set_details (lisp_cp_main_t * lcm,
4086                                locator_set_t * lsit,
4087                                unix_shared_memory_queue_t * q,
4088                                u32 context, u32 ls_index)
4089 {
4090   vl_api_lisp_locator_set_details_t *rmp;
4091   u8 *str = 0;
4092
4093   rmp = vl_msg_api_alloc (sizeof (*rmp));
4094   memset (rmp, 0, sizeof (*rmp));
4095   rmp->_vl_msg_id = ntohs (VL_API_LISP_LOCATOR_SET_DETAILS);
4096   rmp->context = context;
4097
4098   rmp->ls_index = htonl (ls_index);
4099   if (lsit->local)
4100     {
4101       ASSERT (lsit->name != NULL);
4102       strncpy ((char *) rmp->ls_name, (char *) lsit->name,
4103                vec_len (lsit->name));
4104     }
4105   else
4106     {
4107       str = format (0, "<remote-%d>", ls_index);
4108       strncpy ((char *) rmp->ls_name, (char *) str, vec_len (str));
4109       vec_free (str);
4110     }
4111
4112   vl_msg_api_send_shmem (q, (u8 *) & rmp);
4113 }
4114
4115 static void
4116 vl_api_lisp_locator_set_dump_t_handler (vl_api_lisp_locator_set_dump_t * mp)
4117 {
4118   unix_shared_memory_queue_t *q = NULL;
4119   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
4120   locator_set_t *lsit = NULL;
4121   u8 filter;
4122
4123   q = vl_api_client_index_to_input_queue (mp->client_index);
4124   if (q == 0)
4125     {
4126       return;
4127     }
4128
4129   filter = mp->filter;
4130   /* *INDENT-OFF* */
4131   pool_foreach (lsit, lcm->locator_set_pool,
4132   ({
4133     if (filter && !((1 == filter && lsit->local) ||
4134                     (2 == filter && !lsit->local)))
4135       {
4136         continue;
4137       }
4138     send_lisp_locator_set_details (lcm, lsit, q, mp->context,
4139                                    lsit - lcm->locator_set_pool);
4140   }));
4141   /* *INDENT-ON* */
4142 }
4143
4144 static void
4145 lisp_fid_put_api (u8 * dst, fid_address_t * src, u8 * prefix_length)
4146 {
4147   ASSERT (prefix_length);
4148   ip_prefix_t *ippref = &fid_addr_ippref (src);
4149
4150   switch (fid_addr_type (src))
4151     {
4152     case FID_ADDR_IP_PREF:
4153       if (ip_prefix_version (ippref) == IP4)
4154         clib_memcpy (dst, &ip_prefix_v4 (ippref), 4);
4155       else
4156         clib_memcpy (dst, &ip_prefix_v6 (ippref), 16);
4157       prefix_length[0] = ip_prefix_len (ippref);
4158       break;
4159
4160     case FID_ADDR_MAC:
4161       prefix_length[0] = 0;
4162       clib_memcpy (dst, fid_addr_mac (src), 6);
4163       break;
4164
4165     default:
4166       clib_warning ("Unknown FID type %d!", fid_addr_type (src));
4167       break;
4168     }
4169 }
4170
4171 static u8
4172 fid_type_to_api_type (fid_address_t * fid)
4173 {
4174   ip_prefix_t *ippref;
4175
4176   switch (fid_addr_type (fid))
4177     {
4178     case FID_ADDR_IP_PREF:
4179       ippref = &fid_addr_ippref (fid);
4180       if (ip_prefix_version (ippref) == IP4)
4181         return 0;
4182       else if (ip_prefix_version (ippref) == IP6)
4183         return 1;
4184       else
4185         return ~0;
4186
4187     case FID_ADDR_MAC:
4188       return 2;
4189     }
4190
4191   return ~0;
4192 }
4193
4194 static void
4195 send_lisp_eid_table_details (mapping_t * mapit,
4196                              unix_shared_memory_queue_t * q,
4197                              u32 context, u8 filter)
4198 {
4199   fid_address_t *fid;
4200   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
4201   locator_set_t *ls = 0;
4202   vl_api_lisp_eid_table_details_t *rmp = NULL;
4203   gid_address_t *gid = NULL;
4204   u8 *mac = 0;
4205   ip_prefix_t *ip_prefix = NULL;
4206
4207   switch (filter)
4208     {
4209     case 0:                     /* all mappings */
4210       break;
4211
4212     case 1:                     /* local only */
4213       if (!mapit->local)
4214         return;
4215       break;
4216     case 2:                     /* remote only */
4217       if (mapit->local)
4218         return;
4219       break;
4220     default:
4221       clib_warning ("Filter error, unknown filter: %d", filter);
4222       return;
4223     }
4224
4225   gid = &mapit->eid;
4226   ip_prefix = &gid_address_ippref (gid);
4227   mac = gid_address_mac (gid);
4228
4229   rmp = vl_msg_api_alloc (sizeof (*rmp));
4230   memset (rmp, 0, sizeof (*rmp));
4231   rmp->_vl_msg_id = ntohs (VL_API_LISP_EID_TABLE_DETAILS);
4232
4233   ls = pool_elt_at_index (lcm->locator_set_pool, mapit->locator_set_index);
4234   if (vec_len (ls->locator_indices) == 0)
4235     rmp->locator_set_index = ~0;
4236   else
4237     rmp->locator_set_index = clib_host_to_net_u32 (mapit->locator_set_index);
4238
4239   rmp->is_local = mapit->local;
4240   rmp->ttl = clib_host_to_net_u32 (mapit->ttl);
4241   rmp->action = mapit->action;
4242   rmp->authoritative = mapit->authoritative;
4243
4244   switch (gid_address_type (gid))
4245     {
4246     case GID_ADDR_SRC_DST:
4247       rmp->is_src_dst = 1;
4248       fid = &gid_address_sd_src (gid);
4249       rmp->eid_type = fid_type_to_api_type (fid);
4250       lisp_fid_put_api (rmp->seid, &gid_address_sd_src (gid),
4251                         &rmp->seid_prefix_len);
4252       lisp_fid_put_api (rmp->eid, &gid_address_sd_dst (gid),
4253                         &rmp->eid_prefix_len);
4254       break;
4255     case GID_ADDR_IP_PREFIX:
4256       rmp->eid_prefix_len = ip_prefix_len (ip_prefix);
4257       if (ip_prefix_version (ip_prefix) == IP4)
4258         {
4259           rmp->eid_type = 0;    /* ipv4 type */
4260           clib_memcpy (rmp->eid, &ip_prefix_v4 (ip_prefix),
4261                        sizeof (ip_prefix_v4 (ip_prefix)));
4262         }
4263       else
4264         {
4265           rmp->eid_type = 1;    /* ipv6 type */
4266           clib_memcpy (rmp->eid, &ip_prefix_v6 (ip_prefix),
4267                        sizeof (ip_prefix_v6 (ip_prefix)));
4268         }
4269       break;
4270     case GID_ADDR_MAC:
4271       rmp->eid_type = 2;        /* l2 mac type */
4272       clib_memcpy (rmp->eid, mac, 6);
4273       break;
4274     default:
4275       ASSERT (0);
4276     }
4277   rmp->context = context;
4278   rmp->vni = clib_host_to_net_u32 (gid_address_vni (gid));
4279   rmp->key_id = clib_host_to_net_u16 (mapit->key_id);
4280   memcpy (rmp->key, mapit->key, vec_len (mapit->key));
4281   vl_msg_api_send_shmem (q, (u8 *) & rmp);
4282 }
4283
4284 static void
4285 vl_api_lisp_eid_table_dump_t_handler (vl_api_lisp_eid_table_dump_t * mp)
4286 {
4287   u32 mi;
4288   unix_shared_memory_queue_t *q = NULL;
4289   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
4290   mapping_t *mapit = NULL;
4291   gid_address_t _eid, *eid = &_eid;
4292
4293   q = vl_api_client_index_to_input_queue (mp->client_index);
4294   if (q == 0)
4295     {
4296       return;
4297     }
4298
4299   if (mp->eid_set)
4300     {
4301       memset (eid, 0, sizeof (*eid));
4302
4303       unformat_lisp_eid_api (eid, clib_net_to_host_u32 (mp->vni),
4304                              mp->eid_type, mp->eid, mp->prefix_length);
4305
4306       mi = gid_dictionary_lookup (&lcm->mapping_index_by_gid, eid);
4307       if ((u32) ~ 0 == mi)
4308         return;
4309
4310       mapit = pool_elt_at_index (lcm->mapping_pool, mi);
4311       send_lisp_eid_table_details (mapit, q, mp->context,
4312                                    0 /* ignore filter */ );
4313     }
4314   else
4315     {
4316       /* *INDENT-OFF* */
4317       pool_foreach (mapit, lcm->mapping_pool,
4318       ({
4319         send_lisp_eid_table_details(mapit, q, mp->context,
4320                                     mp->filter);
4321       }));
4322       /* *INDENT-ON* */
4323     }
4324 }
4325
4326 static void
4327 send_lisp_gpe_fwd_entry_details (lisp_gpe_fwd_entry_t * lfe,
4328                                  unix_shared_memory_queue_t * q, u32 context)
4329 {
4330   vl_api_lisp_gpe_tunnel_details_t *rmp;
4331   lisp_gpe_main_t *lgm = &lisp_gpe_main;
4332
4333   rmp = vl_msg_api_alloc (sizeof (*rmp));
4334   memset (rmp, 0, sizeof (*rmp));
4335   rmp->_vl_msg_id = ntohs (VL_API_LISP_GPE_TUNNEL_DETAILS);
4336
4337   rmp->tunnels = lfe - lgm->lisp_fwd_entry_pool;
4338
4339   rmp->is_ipv6 = ip_prefix_version (&(lfe->key->rmt.ippref)) == IP6 ? 1 : 0;
4340   ip_address_copy_addr (rmp->source_ip,
4341                         &ip_prefix_addr (&(lfe->key->rmt.ippref)));
4342   ip_address_copy_addr (rmp->destination_ip,
4343                         &ip_prefix_addr (&(lfe->key->rmt.ippref)));
4344
4345   rmp->encap_fib_id = htonl (0);
4346   rmp->decap_fib_id = htonl (lfe->eid_fib_index);
4347   rmp->iid = htonl (lfe->key->vni);
4348   rmp->context = context;
4349
4350   vl_msg_api_send_shmem (q, (u8 *) & rmp);
4351 }
4352
4353 static void
4354 vl_api_lisp_gpe_tunnel_dump_t_handler (vl_api_lisp_gpe_tunnel_dump_t * mp)
4355 {
4356   unix_shared_memory_queue_t *q = NULL;
4357   lisp_gpe_main_t *lgm = &lisp_gpe_main;
4358   lisp_gpe_fwd_entry_t *lfe = NULL;
4359
4360   if (pool_elts (lgm->lisp_fwd_entry_pool) == 0)
4361     {
4362       return;
4363     }
4364
4365   q = vl_api_client_index_to_input_queue (mp->client_index);
4366   if (q == 0)
4367     {
4368       return;
4369     }
4370
4371   /* *INDENT-OFF* */
4372   pool_foreach(lfe, lgm->lisp_fwd_entry_pool,
4373   ({
4374     send_lisp_gpe_fwd_entry_details(lfe, q, mp->context);
4375   }));
4376   /* *INDENT-ON* */
4377 }
4378
4379 static void
4380 send_lisp_map_server_details (ip_address_t * ip,
4381                               unix_shared_memory_queue_t * q, u32 context)
4382 {
4383   vl_api_lisp_map_server_details_t *rmp = NULL;
4384
4385   rmp = vl_msg_api_alloc (sizeof (*rmp));
4386   memset (rmp, 0, sizeof (*rmp));
4387   rmp->_vl_msg_id = ntohs (VL_API_LISP_MAP_SERVER_DETAILS);
4388
4389   switch (ip_addr_version (ip))
4390     {
4391     case IP4:
4392       rmp->is_ipv6 = 0;
4393       clib_memcpy (rmp->ip_address, &ip_addr_v4 (ip),
4394                    sizeof (ip_addr_v4 (ip)));
4395       break;
4396
4397     case IP6:
4398       rmp->is_ipv6 = 1;
4399       clib_memcpy (rmp->ip_address, &ip_addr_v6 (ip),
4400                    sizeof (ip_addr_v6 (ip)));
4401       break;
4402
4403     default:
4404       ASSERT (0);
4405     }
4406   rmp->context = context;
4407
4408   vl_msg_api_send_shmem (q, (u8 *) & rmp);
4409 }
4410
4411 static void
4412 vl_api_lisp_map_server_dump_t_handler (vl_api_lisp_map_server_dump_t * mp)
4413 {
4414   unix_shared_memory_queue_t *q = NULL;
4415   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
4416   lisp_msmr_t *mr;
4417
4418   q = vl_api_client_index_to_input_queue (mp->client_index);
4419   if (q == 0)
4420     {
4421       return;
4422     }
4423
4424   vec_foreach (mr, lcm->map_servers)
4425   {
4426     send_lisp_map_server_details (&mr->address, q, mp->context);
4427   }
4428 }
4429
4430 static void
4431 send_lisp_map_resolver_details (ip_address_t * ip,
4432                                 unix_shared_memory_queue_t * q, u32 context)
4433 {
4434   vl_api_lisp_map_resolver_details_t *rmp = NULL;
4435
4436   rmp = vl_msg_api_alloc (sizeof (*rmp));
4437   memset (rmp, 0, sizeof (*rmp));
4438   rmp->_vl_msg_id = ntohs (VL_API_LISP_MAP_RESOLVER_DETAILS);
4439
4440   switch (ip_addr_version (ip))
4441     {
4442     case IP4:
4443       rmp->is_ipv6 = 0;
4444       clib_memcpy (rmp->ip_address, &ip_addr_v4 (ip),
4445                    sizeof (ip_addr_v4 (ip)));
4446       break;
4447
4448     case IP6:
4449       rmp->is_ipv6 = 1;
4450       clib_memcpy (rmp->ip_address, &ip_addr_v6 (ip),
4451                    sizeof (ip_addr_v6 (ip)));
4452       break;
4453
4454     default:
4455       ASSERT (0);
4456     }
4457   rmp->context = context;
4458
4459   vl_msg_api_send_shmem (q, (u8 *) & rmp);
4460 }
4461
4462 static void
4463 vl_api_lisp_map_resolver_dump_t_handler (vl_api_lisp_map_resolver_dump_t * mp)
4464 {
4465   unix_shared_memory_queue_t *q = NULL;
4466   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
4467   lisp_msmr_t *mr;
4468
4469   q = vl_api_client_index_to_input_queue (mp->client_index);
4470   if (q == 0)
4471     {
4472       return;
4473     }
4474
4475   vec_foreach (mr, lcm->map_resolvers)
4476   {
4477     send_lisp_map_resolver_details (&mr->address, q, mp->context);
4478   }
4479 }
4480
4481 static void
4482 send_eid_table_map_pair (hash_pair_t * p,
4483                          unix_shared_memory_queue_t * q, u32 context)
4484 {
4485   vl_api_lisp_eid_table_map_details_t *rmp = NULL;
4486
4487   rmp = vl_msg_api_alloc (sizeof (*rmp));
4488   memset (rmp, 0, sizeof (*rmp));
4489   rmp->_vl_msg_id = ntohs (VL_API_LISP_EID_TABLE_MAP_DETAILS);
4490
4491   rmp->vni = clib_host_to_net_u32 (p->key);
4492   rmp->dp_table = clib_host_to_net_u32 (p->value[0]);
4493   rmp->context = context;
4494   vl_msg_api_send_shmem (q, (u8 *) & rmp);
4495 }
4496
4497 static void
4498 vl_api_lisp_eid_table_map_dump_t_handler (vl_api_lisp_eid_table_map_dump_t *
4499                                           mp)
4500 {
4501   unix_shared_memory_queue_t *q = NULL;
4502   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
4503   hash_pair_t *p;
4504   uword *vni_table = 0;
4505
4506   q = vl_api_client_index_to_input_queue (mp->client_index);
4507   if (q == 0)
4508     {
4509       return;
4510     }
4511
4512   if (mp->is_l2)
4513     {
4514       vni_table = lcm->bd_id_by_vni;
4515     }
4516   else
4517     {
4518       vni_table = lcm->table_id_by_vni;
4519     }
4520
4521   /* *INDENT-OFF* */
4522   hash_foreach_pair (p, vni_table,
4523   ({
4524     send_eid_table_map_pair (p, q, mp->context);
4525   }));
4526   /* *INDENT-ON* */
4527 }
4528
4529 static void
4530 send_eid_table_vni (u32 vni, unix_shared_memory_queue_t * q, u32 context)
4531 {
4532   vl_api_lisp_eid_table_vni_details_t *rmp = 0;
4533
4534   rmp = vl_msg_api_alloc (sizeof (*rmp));
4535   memset (rmp, 0, sizeof (*rmp));
4536   rmp->_vl_msg_id = ntohs (VL_API_LISP_EID_TABLE_VNI_DETAILS);
4537   rmp->context = context;
4538   rmp->vni = clib_host_to_net_u32 (vni);
4539   vl_msg_api_send_shmem (q, (u8 *) & rmp);
4540 }
4541
4542 static void
4543 lisp_adjacency_copy (vl_api_lisp_adjacency_t * dst, lisp_adjacency_t * adjs)
4544 {
4545   lisp_adjacency_t *adj;
4546   vl_api_lisp_adjacency_t a;
4547   u32 i, n = vec_len (adjs);
4548
4549   for (i = 0; i < n; i++)
4550     {
4551       adj = vec_elt_at_index (adjs, i);
4552       memset (&a, 0, sizeof (a));
4553
4554       switch (gid_address_type (&adj->reid))
4555         {
4556         case GID_ADDR_IP_PREFIX:
4557           a.reid_prefix_len = gid_address_ippref_len (&adj->reid);
4558           a.leid_prefix_len = gid_address_ippref_len (&adj->leid);
4559           if (gid_address_ip_version (&adj->reid) == IP4)
4560             {
4561               a.eid_type = 0;   /* ipv4 type */
4562               clib_memcpy (a.reid, &gid_address_ip (&adj->reid), 4);
4563               clib_memcpy (a.leid, &gid_address_ip (&adj->leid), 4);
4564             }
4565           else
4566             {
4567               a.eid_type = 1;   /* ipv6 type */
4568               clib_memcpy (a.reid, &gid_address_ip (&adj->reid), 16);
4569               clib_memcpy (a.leid, &gid_address_ip (&adj->leid), 16);
4570             }
4571           break;
4572         case GID_ADDR_MAC:
4573           a.eid_type = 2;       /* l2 mac type */
4574           mac_copy (a.reid, gid_address_mac (&adj->reid));
4575           mac_copy (a.leid, gid_address_mac (&adj->leid));
4576           break;
4577         default:
4578           ASSERT (0);
4579         }
4580       dst[i] = a;
4581     }
4582 }
4583
4584 static void
4585   vl_api_show_lisp_rloc_probe_state_t_handler
4586   (vl_api_show_lisp_rloc_probe_state_t * mp)
4587 {
4588   vl_api_show_lisp_rloc_probe_state_reply_t *rmp = 0;
4589   int rv = 0;
4590
4591   /* *INDENT-OFF* */
4592   REPLY_MACRO2 (VL_API_SHOW_LISP_RLOC_PROBE_STATE_REPLY,
4593   {
4594     rmp->is_enabled = vnet_lisp_rloc_probe_state_get ();
4595   });
4596   /* *INDENT-ON* */
4597 }
4598
4599 static void
4600   vl_api_show_lisp_map_register_state_t_handler
4601   (vl_api_show_lisp_map_register_state_t * mp)
4602 {
4603   vl_api_show_lisp_map_register_state_reply_t *rmp = 0;
4604   int rv = 0;
4605
4606   /* *INDENT-OFF* */
4607   REPLY_MACRO2 (VL_API_SHOW_LISP_MAP_REGISTER_STATE_REPLY,
4608   {
4609     rmp->is_enabled = vnet_lisp_map_register_state_get ();
4610   });
4611   /* *INDENT-ON* */
4612 }
4613
4614 static void
4615 vl_api_lisp_adjacencies_get_t_handler (vl_api_lisp_adjacencies_get_t * mp)
4616 {
4617   vl_api_lisp_adjacencies_get_reply_t *rmp = 0;
4618   lisp_adjacency_t *adjs = 0;
4619   int rv = 0;
4620   vl_api_lisp_adjacency_t a;
4621   u32 size = ~0;
4622   u32 vni = clib_net_to_host_u32 (mp->vni);
4623
4624   adjs = vnet_lisp_adjacencies_get_by_vni (vni);
4625   size = vec_len (adjs) * sizeof (a);
4626
4627   /* *INDENT-OFF* */
4628   REPLY_MACRO4 (VL_API_LISP_ADJACENCIES_GET_REPLY, size,
4629   {
4630     rmp->count = clib_host_to_net_u32 (vec_len (adjs));
4631     lisp_adjacency_copy (rmp->adjacencies, adjs);
4632   });
4633   /* *INDENT-ON* */
4634
4635   vec_free (adjs);
4636 }
4637
4638 static void
4639 vl_api_lisp_eid_table_vni_dump_t_handler (vl_api_lisp_eid_table_vni_dump_t *
4640                                           mp)
4641 {
4642   hash_pair_t *p;
4643   u32 *vnis = 0;
4644   unix_shared_memory_queue_t *q = 0;
4645   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
4646
4647   q = vl_api_client_index_to_input_queue (mp->client_index);
4648   if (q == 0)
4649     {
4650       return;
4651     }
4652
4653   /* *INDENT-OFF* */
4654   hash_foreach_pair (p, lcm->table_id_by_vni,
4655   ({
4656     hash_set (vnis, p->key, 0);
4657   }));
4658
4659   hash_foreach_pair (p, lcm->bd_id_by_vni,
4660   ({
4661     hash_set (vnis, p->key, 0);
4662   }));
4663
4664   hash_foreach_pair (p, vnis,
4665   ({
4666     send_eid_table_vni (p->key, q, mp->context);
4667   }));
4668   /* *INDENT-ON* */
4669
4670   hash_free (vnis);
4671 }
4672
4673 static void
4674 vl_api_show_lisp_status_t_handler (vl_api_show_lisp_status_t * mp)
4675 {
4676   unix_shared_memory_queue_t *q = NULL;
4677   vl_api_show_lisp_status_reply_t *rmp = NULL;
4678   int rv = 0;
4679
4680   q = vl_api_client_index_to_input_queue (mp->client_index);
4681   if (q == 0)
4682     {
4683       return;
4684     }
4685
4686   /* *INDENT-OFF* */
4687   REPLY_MACRO2(VL_API_SHOW_LISP_STATUS_REPLY,
4688   ({
4689     rmp->gpe_status = vnet_lisp_gpe_enable_disable_status ();
4690     rmp->feature_status = vnet_lisp_enable_disable_status ();
4691   }));
4692   /* *INDENT-ON* */
4693 }
4694
4695 static void
4696   vl_api_lisp_get_map_request_itr_rlocs_t_handler
4697   (vl_api_lisp_get_map_request_itr_rlocs_t * mp)
4698 {
4699   unix_shared_memory_queue_t *q = NULL;
4700   vl_api_lisp_get_map_request_itr_rlocs_reply_t *rmp = NULL;
4701   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
4702   locator_set_t *loc_set = 0;
4703   u8 *tmp_str = 0;
4704   int rv = 0;
4705
4706   q = vl_api_client_index_to_input_queue (mp->client_index);
4707   if (q == 0)
4708     {
4709       return;
4710     }
4711
4712   if (~0 == lcm->mreq_itr_rlocs)
4713     {
4714       tmp_str = format (0, " ");
4715     }
4716   else
4717     {
4718       loc_set =
4719         pool_elt_at_index (lcm->locator_set_pool, lcm->mreq_itr_rlocs);
4720       tmp_str = format (0, "%s", loc_set->name);
4721     }
4722
4723   /* *INDENT-OFF* */
4724   REPLY_MACRO2(VL_API_LISP_GET_MAP_REQUEST_ITR_RLOCS_REPLY,
4725   ({
4726     strncpy((char *) rmp->locator_set_name, (char *) tmp_str,
4727             ARRAY_LEN(rmp->locator_set_name) - 1);
4728   }));
4729   /* *INDENT-ON* */
4730
4731   vec_free (tmp_str);
4732 }
4733
4734 static void
4735 vl_api_show_lisp_pitr_t_handler (vl_api_show_lisp_pitr_t * mp)
4736 {
4737   unix_shared_memory_queue_t *q = NULL;
4738   vl_api_show_lisp_pitr_reply_t *rmp = NULL;
4739   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
4740   mapping_t *m;
4741   locator_set_t *ls = 0;
4742   u8 *tmp_str = 0;
4743   int rv = 0;
4744
4745   q = vl_api_client_index_to_input_queue (mp->client_index);
4746   if (q == 0)
4747     {
4748       return;
4749     }
4750
4751   if (!lcm->lisp_pitr)
4752     {
4753       tmp_str = format (0, "N/A");
4754     }
4755   else
4756     {
4757       m = pool_elt_at_index (lcm->mapping_pool, lcm->pitr_map_index);
4758       if (~0 != m->locator_set_index)
4759         {
4760           ls =
4761             pool_elt_at_index (lcm->locator_set_pool, m->locator_set_index);
4762           tmp_str = format (0, "%s", ls->name);
4763         }
4764       else
4765         {
4766           tmp_str = format (0, "N/A");
4767         }
4768     }
4769   vec_add1 (tmp_str, 0);
4770
4771   /* *INDENT-OFF* */
4772   REPLY_MACRO2(VL_API_SHOW_LISP_PITR_REPLY,
4773   ({
4774     rmp->status = lcm->lisp_pitr;
4775     strncpy((char *) rmp->locator_set_name, (char *) tmp_str,
4776             ARRAY_LEN(rmp->locator_set_name) - 1);
4777   }));
4778   /* *INDENT-ON* */
4779 }
4780
4781 static void
4782 vl_api_interface_name_renumber_t_handler (vl_api_interface_name_renumber_t *
4783                                           mp)
4784 {
4785   vl_api_interface_name_renumber_reply_t *rmp;
4786   int rv = 0;
4787
4788   VALIDATE_SW_IF_INDEX (mp);
4789
4790   rv = vnet_interface_name_renumber
4791     (ntohl (mp->sw_if_index), ntohl (mp->new_show_dev_instance));
4792
4793   BAD_SW_IF_INDEX_LABEL;
4794
4795   REPLY_MACRO (VL_API_INTERFACE_NAME_RENUMBER_REPLY);
4796 }
4797
4798 static int
4799 arp_change_data_callback (u32 pool_index, u8 * new_mac,
4800                           u32 sw_if_index, u32 address)
4801 {
4802   vpe_api_main_t *am = &vpe_api_main;
4803   vlib_main_t *vm = am->vlib_main;
4804   vl_api_ip4_arp_event_t *event;
4805   static f64 arp_event_last_time;
4806   f64 now = vlib_time_now (vm);
4807
4808   if (pool_is_free_index (am->arp_events, pool_index))
4809     return 1;
4810
4811   event = pool_elt_at_index (am->arp_events, pool_index);
4812   /* *INDENT-OFF* */
4813   if (memcmp (&event->new_mac, new_mac, sizeof (event->new_mac)))
4814     {
4815       clib_memcpy (event->new_mac, new_mac, sizeof (event->new_mac));
4816     }
4817   else
4818     {                           /* same mac */
4819       if (sw_if_index == event->sw_if_index &&
4820           (!event->mac_ip ||
4821            /* for BD case, also check IP address with 10 sec timeout */
4822            (address == event->address &&
4823             (now - arp_event_last_time) < 10.0)))
4824         return 1;
4825     }
4826   /* *INDENT-ON* */
4827
4828   arp_event_last_time = now;
4829   event->sw_if_index = sw_if_index;
4830   if (event->mac_ip)
4831     event->address = address;
4832   return 0;
4833 }
4834
4835 static int
4836 nd_change_data_callback (u32 pool_index, u8 * new_mac,
4837                          u32 sw_if_index, ip6_address_t * address)
4838 {
4839   vpe_api_main_t *am = &vpe_api_main;
4840   vlib_main_t *vm = am->vlib_main;
4841   vl_api_ip6_nd_event_t *event;
4842   static f64 nd_event_last_time;
4843   f64 now = vlib_time_now (vm);
4844
4845   if (pool_is_free_index (am->nd_events, pool_index))
4846     return 1;
4847
4848   event = pool_elt_at_index (am->nd_events, pool_index);
4849
4850   /* *INDENT-OFF* */
4851   if (memcmp (&event->new_mac, new_mac, sizeof (event->new_mac)))
4852     {
4853       clib_memcpy (event->new_mac, new_mac, sizeof (event->new_mac));
4854     }
4855   else
4856     {                           /* same mac */
4857       if (sw_if_index == event->sw_if_index &&
4858           (!event->mac_ip ||
4859            /* for BD case, also check IP address with 10 sec timeout */
4860            (ip6_address_is_equal (address,
4861                                   (ip6_address_t *) event->address) &&
4862             (now - nd_event_last_time) < 10.0)))
4863         return 1;
4864     }
4865   /* *INDENT-ON* */
4866
4867   nd_event_last_time = now;
4868   event->sw_if_index = sw_if_index;
4869   if (event->mac_ip)
4870     clib_memcpy (event->address, address, sizeof (event->address));
4871   return 0;
4872 }
4873
4874 static int
4875 arp_change_delete_callback (u32 pool_index, u8 * notused)
4876 {
4877   vpe_api_main_t *am = &vpe_api_main;
4878
4879   if (pool_is_free_index (am->arp_events, pool_index))
4880     return 1;
4881
4882   pool_put_index (am->arp_events, pool_index);
4883   return 0;
4884 }
4885
4886 static int
4887 nd_change_delete_callback (u32 pool_index, u8 * notused)
4888 {
4889   vpe_api_main_t *am = &vpe_api_main;
4890
4891   if (pool_is_free_index (am->nd_events, pool_index))
4892     return 1;
4893
4894   pool_put_index (am->nd_events, pool_index);
4895   return 0;
4896 }
4897
4898 static void
4899 vl_api_want_ip4_arp_events_t_handler (vl_api_want_ip4_arp_events_t * mp)
4900 {
4901   vpe_api_main_t *am = &vpe_api_main;
4902   vnet_main_t *vnm = vnet_get_main ();
4903   vl_api_want_ip4_arp_events_reply_t *rmp;
4904   vl_api_ip4_arp_event_t *event;
4905   int rv;
4906
4907   if (mp->enable_disable)
4908     {
4909       pool_get (am->arp_events, event);
4910       memset (event, 0, sizeof (*event));
4911
4912       event->_vl_msg_id = ntohs (VL_API_IP4_ARP_EVENT);
4913       event->client_index = mp->client_index;
4914       event->context = mp->context;
4915       event->address = mp->address;
4916       event->pid = mp->pid;
4917       if (mp->address == 0)
4918         event->mac_ip = 1;
4919
4920       rv = vnet_add_del_ip4_arp_change_event
4921         (vnm, arp_change_data_callback,
4922          mp->pid, &mp->address /* addr, in net byte order */ ,
4923          vpe_resolver_process_node.index,
4924          IP4_ARP_EVENT, event - am->arp_events, 1 /* is_add */ );
4925     }
4926   else
4927     {
4928       rv = vnet_add_del_ip4_arp_change_event
4929         (vnm, arp_change_delete_callback,
4930          mp->pid, &mp->address /* addr, in net byte order */ ,
4931          vpe_resolver_process_node.index,
4932          IP4_ARP_EVENT, ~0 /* pool index */ , 0 /* is_add */ );
4933     }
4934   REPLY_MACRO (VL_API_WANT_IP4_ARP_EVENTS_REPLY);
4935 }
4936
4937 static void
4938 vl_api_want_ip6_nd_events_t_handler (vl_api_want_ip6_nd_events_t * mp)
4939 {
4940   vpe_api_main_t *am = &vpe_api_main;
4941   vnet_main_t *vnm = vnet_get_main ();
4942   vl_api_want_ip6_nd_events_reply_t *rmp;
4943   vl_api_ip6_nd_event_t *event;
4944   int rv;
4945
4946   if (mp->enable_disable)
4947     {
4948       pool_get (am->nd_events, event);
4949       memset (event, 0, sizeof (*event));
4950
4951       event->_vl_msg_id = ntohs (VL_API_IP6_ND_EVENT);
4952       event->client_index = mp->client_index;
4953       event->context = mp->context;
4954       clib_memcpy (event->address, mp->address, 16);
4955       event->pid = mp->pid;
4956       if (ip6_address_is_zero ((ip6_address_t *) mp->address))
4957         event->mac_ip = 1;
4958
4959       rv = vnet_add_del_ip6_nd_change_event
4960         (vnm, nd_change_data_callback,
4961          mp->pid, mp->address /* addr, in net byte order */ ,
4962          vpe_resolver_process_node.index,
4963          IP6_ND_EVENT, event - am->nd_events, 1 /* is_add */ );
4964     }
4965   else
4966     {
4967       rv = vnet_add_del_ip6_nd_change_event
4968         (vnm, nd_change_delete_callback,
4969          mp->pid, mp->address /* addr, in net byte order */ ,
4970          vpe_resolver_process_node.index,
4971          IP6_ND_EVENT, ~0 /* pool index */ , 0 /* is_add */ );
4972     }
4973   REPLY_MACRO (VL_API_WANT_IP6_ND_EVENTS_REPLY);
4974 }
4975
4976 static void vl_api_input_acl_set_interface_t_handler
4977   (vl_api_input_acl_set_interface_t * mp)
4978 {
4979   vlib_main_t *vm = vlib_get_main ();
4980   vl_api_input_acl_set_interface_reply_t *rmp;
4981   int rv;
4982   u32 sw_if_index, ip4_table_index, ip6_table_index, l2_table_index;
4983
4984   ip4_table_index = ntohl (mp->ip4_table_index);
4985   ip6_table_index = ntohl (mp->ip6_table_index);
4986   l2_table_index = ntohl (mp->l2_table_index);
4987   sw_if_index = ntohl (mp->sw_if_index);
4988
4989   VALIDATE_SW_IF_INDEX (mp);
4990
4991   rv = vnet_set_input_acl_intfc (vm, sw_if_index, ip4_table_index,
4992                                  ip6_table_index, l2_table_index, mp->is_add);
4993
4994   BAD_SW_IF_INDEX_LABEL;
4995
4996   REPLY_MACRO (VL_API_INPUT_ACL_SET_INTERFACE_REPLY);
4997 }
4998
4999 static void vl_api_ipsec_spd_add_del_t_handler
5000   (vl_api_ipsec_spd_add_del_t * mp)
5001 {
5002 #if IPSEC == 0
5003   clib_warning ("unimplemented");
5004 #else
5005
5006   vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
5007   vl_api_ipsec_spd_add_del_reply_t *rmp;
5008   int rv;
5009
5010 #if DPDK > 0
5011   rv = ipsec_add_del_spd (vm, ntohl (mp->spd_id), mp->is_add);
5012 #else
5013   rv = VNET_API_ERROR_UNIMPLEMENTED;
5014 #endif
5015
5016   REPLY_MACRO (VL_API_IPSEC_SPD_ADD_DEL_REPLY);
5017 #endif
5018 }
5019
5020 static void vl_api_ipsec_interface_add_del_spd_t_handler
5021   (vl_api_ipsec_interface_add_del_spd_t * mp)
5022 {
5023   vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
5024   vl_api_ipsec_interface_add_del_spd_reply_t *rmp;
5025   int rv;
5026   u32 sw_if_index __attribute__ ((unused));
5027   u32 spd_id __attribute__ ((unused));
5028
5029   sw_if_index = ntohl (mp->sw_if_index);
5030   spd_id = ntohl (mp->spd_id);
5031
5032   VALIDATE_SW_IF_INDEX (mp);
5033
5034 #if IPSEC > 0
5035   rv = ipsec_set_interface_spd (vm, sw_if_index, spd_id, mp->is_add);
5036 #else
5037   rv = VNET_API_ERROR_UNIMPLEMENTED;
5038 #endif
5039
5040   BAD_SW_IF_INDEX_LABEL;
5041
5042   REPLY_MACRO (VL_API_IPSEC_INTERFACE_ADD_DEL_SPD_REPLY);
5043 }
5044
5045 static void vl_api_ipsec_spd_add_del_entry_t_handler
5046   (vl_api_ipsec_spd_add_del_entry_t * mp)
5047 {
5048   vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
5049   vl_api_ipsec_spd_add_del_entry_reply_t *rmp;
5050   int rv;
5051
5052 #if IPSEC > 0
5053   ipsec_policy_t p;
5054
5055   memset (&p, 0, sizeof (p));
5056
5057   p.id = ntohl (mp->spd_id);
5058   p.priority = ntohl (mp->priority);
5059   p.is_outbound = mp->is_outbound;
5060   p.is_ipv6 = mp->is_ipv6;
5061
5062   if (mp->is_ipv6 || mp->is_ip_any)
5063     {
5064       clib_memcpy (&p.raddr.start, mp->remote_address_start, 16);
5065       clib_memcpy (&p.raddr.stop, mp->remote_address_stop, 16);
5066       clib_memcpy (&p.laddr.start, mp->local_address_start, 16);
5067       clib_memcpy (&p.laddr.stop, mp->local_address_stop, 16);
5068     }
5069   else
5070     {
5071       clib_memcpy (&p.raddr.start.ip4.data, mp->remote_address_start, 4);
5072       clib_memcpy (&p.raddr.stop.ip4.data, mp->remote_address_stop, 4);
5073       clib_memcpy (&p.laddr.start.ip4.data, mp->local_address_start, 4);
5074       clib_memcpy (&p.laddr.stop.ip4.data, mp->local_address_stop, 4);
5075     }
5076   p.protocol = mp->protocol;
5077   p.rport.start = ntohs (mp->remote_port_start);
5078   p.rport.stop = ntohs (mp->remote_port_stop);
5079   p.lport.start = ntohs (mp->local_port_start);
5080   p.lport.stop = ntohs (mp->local_port_stop);
5081   /* policy action resolve unsupported */
5082   if (mp->policy == IPSEC_POLICY_ACTION_RESOLVE)
5083     {
5084       clib_warning ("unsupported action: 'resolve'");
5085       rv = VNET_API_ERROR_UNIMPLEMENTED;
5086       goto out;
5087     }
5088   p.policy = mp->policy;
5089   p.sa_id = ntohl (mp->sa_id);
5090
5091   rv = ipsec_add_del_policy (vm, &p, mp->is_add);
5092   if (rv)
5093     goto out;
5094
5095   if (mp->is_ip_any)
5096     {
5097       p.is_ipv6 = 1;
5098       rv = ipsec_add_del_policy (vm, &p, mp->is_add);
5099     }
5100 #else
5101   rv = VNET_API_ERROR_UNIMPLEMENTED;
5102   goto out;
5103 #endif
5104
5105 out:
5106   REPLY_MACRO (VL_API_IPSEC_SPD_ADD_DEL_ENTRY_REPLY);
5107 }
5108
5109 static void vl_api_ipsec_sad_add_del_entry_t_handler
5110   (vl_api_ipsec_sad_add_del_entry_t * mp)
5111 {
5112   vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
5113   vl_api_ipsec_sad_add_del_entry_reply_t *rmp;
5114   int rv;
5115 #if IPSEC > 0
5116   ipsec_sa_t sa;
5117
5118   memset (&sa, 0, sizeof (sa));
5119
5120   sa.id = ntohl (mp->sad_id);
5121   sa.spi = ntohl (mp->spi);
5122   /* security protocol AH unsupported */
5123   if (mp->protocol == IPSEC_PROTOCOL_AH)
5124     {
5125       clib_warning ("unsupported security protocol 'AH'");
5126       rv = VNET_API_ERROR_UNIMPLEMENTED;
5127       goto out;
5128     }
5129   sa.protocol = mp->protocol;
5130   /* check for unsupported crypto-alg */
5131   if (mp->crypto_algorithm < IPSEC_CRYPTO_ALG_AES_CBC_128 ||
5132       mp->crypto_algorithm >= IPSEC_CRYPTO_N_ALG)
5133     {
5134       clib_warning ("unsupported crypto-alg: '%U'", format_ipsec_crypto_alg,
5135                     mp->crypto_algorithm);
5136       rv = VNET_API_ERROR_UNIMPLEMENTED;
5137       goto out;
5138     }
5139   sa.crypto_alg = mp->crypto_algorithm;
5140   sa.crypto_key_len = mp->crypto_key_length;
5141   clib_memcpy (&sa.crypto_key, mp->crypto_key, sizeof (sa.crypto_key));
5142   /* check for unsupported integ-alg */
5143 #if DPDK_CRYPTO==1
5144   if (mp->integrity_algorithm < IPSEC_INTEG_ALG_NONE ||
5145 #else
5146   if (mp->integrity_algorithm < IPSEC_INTEG_ALG_SHA1_96 ||
5147 #endif
5148       mp->integrity_algorithm >= IPSEC_INTEG_N_ALG)
5149     {
5150       clib_warning ("unsupported integ-alg: '%U'", format_ipsec_integ_alg,
5151                     mp->integrity_algorithm);
5152       rv = VNET_API_ERROR_UNIMPLEMENTED;
5153       goto out;
5154     }
5155
5156 #if DPDK_CRYPTO==1
5157   /*Special cases, aes-gcm-128 encryption */
5158   if (mp->crypto_algorithm == IPSEC_CRYPTO_ALG_AES_GCM_128)
5159     {
5160       if (mp->integrity_algorithm != IPSEC_INTEG_ALG_NONE
5161           && mp->integrity_algorithm != IPSEC_INTEG_ALG_AES_GCM_128)
5162         {
5163           clib_warning
5164             ("unsupported: aes-gcm-128 crypto-alg needs none as integ-alg");
5165           rv = VNET_API_ERROR_UNIMPLEMENTED;
5166           goto out;
5167         }
5168       else                      /*set integ-alg internally to aes-gcm-128 */
5169         mp->integrity_algorithm = IPSEC_INTEG_ALG_AES_GCM_128;
5170     }
5171   else if (mp->integrity_algorithm == IPSEC_INTEG_ALG_AES_GCM_128)
5172     {
5173       clib_warning ("unsupported integ-alg: aes-gcm-128");
5174       rv = VNET_API_ERROR_UNIMPLEMENTED;
5175       goto out;
5176     }
5177   else if (mp->integrity_algorithm == IPSEC_INTEG_ALG_NONE)
5178     {
5179       clib_warning ("unsupported integ-alg: none");
5180       rv = VNET_API_ERROR_UNIMPLEMENTED;
5181       goto out;
5182     }
5183 #endif
5184
5185   sa.integ_alg = mp->integrity_algorithm;
5186   sa.integ_key_len = mp->integrity_key_length;
5187   clib_memcpy (&sa.integ_key, mp->integrity_key, sizeof (sa.integ_key));
5188   sa.use_esn = mp->use_extended_sequence_number;
5189   sa.is_tunnel = mp->is_tunnel;
5190   sa.is_tunnel_ip6 = mp->is_tunnel_ipv6;
5191   if (sa.is_tunnel_ip6)
5192     {
5193       clib_memcpy (&sa.tunnel_src_addr, mp->tunnel_src_address, 16);
5194       clib_memcpy (&sa.tunnel_dst_addr, mp->tunnel_dst_address, 16);
5195     }
5196   else
5197     {
5198       clib_memcpy (&sa.tunnel_src_addr.ip4.data, mp->tunnel_src_address, 4);
5199       clib_memcpy (&sa.tunnel_dst_addr.ip4.data, mp->tunnel_dst_address, 4);
5200     }
5201
5202   rv = ipsec_add_del_sa (vm, &sa, mp->is_add);
5203 #else
5204   rv = VNET_API_ERROR_UNIMPLEMENTED;
5205   goto out;
5206 #endif
5207
5208 out:
5209   REPLY_MACRO (VL_API_IPSEC_SAD_ADD_DEL_ENTRY_REPLY);
5210 }
5211
5212 static void
5213 vl_api_ikev2_profile_add_del_t_handler (vl_api_ikev2_profile_add_del_t * mp)
5214 {
5215   vl_api_ikev2_profile_add_del_reply_t *rmp;
5216   int rv = 0;
5217
5218 #if IPSEC > 0
5219   vlib_main_t *vm = vlib_get_main ();
5220   clib_error_t *error;
5221   u8 *tmp = format (0, "%s", mp->name);
5222   error = ikev2_add_del_profile (vm, tmp, mp->is_add);
5223   vec_free (tmp);
5224   if (error)
5225     rv = VNET_API_ERROR_UNSPECIFIED;
5226 #else
5227   rv = VNET_API_ERROR_UNIMPLEMENTED;
5228 #endif
5229
5230   REPLY_MACRO (VL_API_IKEV2_PROFILE_ADD_DEL_REPLY);
5231 }
5232
5233 static void
5234   vl_api_ikev2_profile_set_auth_t_handler
5235   (vl_api_ikev2_profile_set_auth_t * mp)
5236 {
5237   vl_api_ikev2_profile_set_auth_reply_t *rmp;
5238   int rv = 0;
5239
5240 #if IPSEC > 0
5241   vlib_main_t *vm = vlib_get_main ();
5242   clib_error_t *error;
5243   u8 *tmp = format (0, "%s", mp->name);
5244   u8 *data = vec_new (u8, mp->data_len);
5245   clib_memcpy (data, mp->data, mp->data_len);
5246   error = ikev2_set_profile_auth (vm, tmp, mp->auth_method, data, mp->is_hex);
5247   vec_free (tmp);
5248   vec_free (data);
5249   if (error)
5250     rv = VNET_API_ERROR_UNSPECIFIED;
5251 #else
5252   rv = VNET_API_ERROR_UNIMPLEMENTED;
5253 #endif
5254
5255   REPLY_MACRO (VL_API_IKEV2_PROFILE_SET_AUTH_REPLY);
5256 }
5257
5258 static void
5259 vl_api_ikev2_profile_set_id_t_handler (vl_api_ikev2_profile_set_id_t * mp)
5260 {
5261   vl_api_ikev2_profile_add_del_reply_t *rmp;
5262   int rv = 0;
5263
5264 #if IPSEC > 0
5265   vlib_main_t *vm = vlib_get_main ();
5266   clib_error_t *error;
5267   u8 *tmp = format (0, "%s", mp->name);
5268   u8 *data = vec_new (u8, mp->data_len);
5269   clib_memcpy (data, mp->data, mp->data_len);
5270   error = ikev2_set_profile_id (vm, tmp, mp->id_type, data, mp->is_local);
5271   vec_free (tmp);
5272   vec_free (data);
5273   if (error)
5274     rv = VNET_API_ERROR_UNSPECIFIED;
5275 #else
5276   rv = VNET_API_ERROR_UNIMPLEMENTED;
5277 #endif
5278
5279   REPLY_MACRO (VL_API_IKEV2_PROFILE_SET_ID_REPLY);
5280 }
5281
5282 static void
5283 vl_api_ikev2_profile_set_ts_t_handler (vl_api_ikev2_profile_set_ts_t * mp)
5284 {
5285   vl_api_ikev2_profile_set_ts_reply_t *rmp;
5286   int rv = 0;
5287
5288 #if IPSEC > 0
5289   vlib_main_t *vm = vlib_get_main ();
5290   clib_error_t *error;
5291   u8 *tmp = format (0, "%s", mp->name);
5292   error = ikev2_set_profile_ts (vm, tmp, mp->proto, mp->start_port,
5293                                 mp->end_port, (ip4_address_t) mp->start_addr,
5294                                 (ip4_address_t) mp->end_addr, mp->is_local);
5295   vec_free (tmp);
5296   if (error)
5297     rv = VNET_API_ERROR_UNSPECIFIED;
5298 #else
5299   rv = VNET_API_ERROR_UNIMPLEMENTED;
5300 #endif
5301
5302   REPLY_MACRO (VL_API_IKEV2_PROFILE_SET_TS_REPLY);
5303 }
5304
5305 static void
5306 vl_api_ikev2_set_local_key_t_handler (vl_api_ikev2_set_local_key_t * mp)
5307 {
5308   vl_api_ikev2_profile_set_ts_reply_t *rmp;
5309   int rv = 0;
5310
5311 #if IPSEC > 0
5312   vlib_main_t *vm = vlib_get_main ();
5313   clib_error_t *error;
5314
5315   error = ikev2_set_local_key (vm, mp->key_file);
5316   if (error)
5317     rv = VNET_API_ERROR_UNSPECIFIED;
5318 #else
5319   rv = VNET_API_ERROR_UNIMPLEMENTED;
5320 #endif
5321
5322   REPLY_MACRO (VL_API_IKEV2_SET_LOCAL_KEY_REPLY);
5323 }
5324
5325 static void
5326 vl_api_ipsec_sa_set_key_t_handler (vl_api_ipsec_sa_set_key_t * mp)
5327 {
5328   vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
5329   vl_api_ipsec_sa_set_key_reply_t *rmp;
5330   int rv;
5331 #if IPSEC > 0
5332   ipsec_sa_t sa;
5333   sa.id = ntohl (mp->sa_id);
5334   sa.crypto_key_len = mp->crypto_key_length;
5335   clib_memcpy (&sa.crypto_key, mp->crypto_key, sizeof (sa.crypto_key));
5336   sa.integ_key_len = mp->integrity_key_length;
5337   clib_memcpy (&sa.integ_key, mp->integrity_key, sizeof (sa.integ_key));
5338
5339   rv = ipsec_set_sa_key (vm, &sa);
5340 #else
5341   rv = VNET_API_ERROR_UNIMPLEMENTED;
5342 #endif
5343
5344   REPLY_MACRO (VL_API_IPSEC_SA_SET_KEY_REPLY);
5345 }
5346
5347 static void vl_api_cop_interface_enable_disable_t_handler
5348   (vl_api_cop_interface_enable_disable_t * mp)
5349 {
5350   vl_api_cop_interface_enable_disable_reply_t *rmp;
5351   int rv;
5352   u32 sw_if_index = ntohl (mp->sw_if_index);
5353   int enable_disable;
5354
5355   VALIDATE_SW_IF_INDEX (mp);
5356
5357   enable_disable = (int) mp->enable_disable;
5358
5359   rv = cop_interface_enable_disable (sw_if_index, enable_disable);
5360
5361   BAD_SW_IF_INDEX_LABEL;
5362
5363   REPLY_MACRO (VL_API_COP_INTERFACE_ENABLE_DISABLE_REPLY);
5364 }
5365
5366 static void vl_api_cop_whitelist_enable_disable_t_handler
5367   (vl_api_cop_whitelist_enable_disable_t * mp)
5368 {
5369   vl_api_cop_whitelist_enable_disable_reply_t *rmp;
5370   cop_whitelist_enable_disable_args_t _a, *a = &_a;
5371   u32 sw_if_index = ntohl (mp->sw_if_index);
5372   int rv;
5373
5374   VALIDATE_SW_IF_INDEX (mp);
5375
5376   a->sw_if_index = sw_if_index;
5377   a->ip4 = mp->ip4;
5378   a->ip6 = mp->ip6;
5379   a->default_cop = mp->default_cop;
5380   a->fib_id = ntohl (mp->fib_id);
5381
5382   rv = cop_whitelist_enable_disable (a);
5383
5384   BAD_SW_IF_INDEX_LABEL;
5385
5386   REPLY_MACRO (VL_API_COP_WHITELIST_ENABLE_DISABLE_REPLY);
5387 }
5388
5389 static void
5390 vl_api_get_node_graph_t_handler (vl_api_get_node_graph_t * mp)
5391 {
5392   int rv = 0;
5393   u8 *vector = 0;
5394   api_main_t *am = &api_main;
5395   vlib_main_t *vm = vlib_get_main ();
5396   void *oldheap;
5397   vl_api_get_node_graph_reply_t *rmp;
5398
5399   pthread_mutex_lock (&am->vlib_rp->mutex);
5400   oldheap = svm_push_data_heap (am->vlib_rp);
5401
5402   /*
5403    * Keep the number of memcpy ops to a minimum (e.g. 1).
5404    */
5405   vec_validate (vector, 16384);
5406   vec_reset_length (vector);
5407
5408   /* $$$$ FIXME */
5409   vector = vlib_node_serialize (&vm->node_main, vector,
5410                                 (u32) ~ 0 /* all threads */ ,
5411                                 1 /* include nexts */ ,
5412                                 1 /* include stats */ );
5413
5414   svm_pop_heap (oldheap);
5415   pthread_mutex_unlock (&am->vlib_rp->mutex);
5416
5417   /* *INDENT-OFF* */
5418   REPLY_MACRO2(VL_API_GET_NODE_GRAPH_REPLY,
5419   ({
5420     rmp->reply_in_shmem = (uword) vector;
5421   }));
5422   /* *INDENT-ON* */
5423 }
5424
5425 static void
5426 vl_api_ioam_enable_t_handler (vl_api_ioam_enable_t * mp)
5427 {
5428   int rv = 0;
5429   vl_api_ioam_enable_reply_t *rmp;
5430   clib_error_t *error;
5431
5432   /* Ignoring the profile id as currently a single profile
5433    * is supported */
5434   error = ip6_ioam_enable (mp->trace_enable, mp->pot_enable,
5435                            mp->seqno, mp->analyse);
5436   if (error)
5437     {
5438       clib_error_report (error);
5439       rv = clib_error_get_code (error);
5440     }
5441
5442   REPLY_MACRO (VL_API_IOAM_ENABLE_REPLY);
5443 }
5444
5445 static void
5446 vl_api_ioam_disable_t_handler (vl_api_ioam_disable_t * mp)
5447 {
5448   int rv = 0;
5449   vl_api_ioam_disable_reply_t *rmp;
5450   clib_error_t *error;
5451
5452   error = clear_ioam_rewrite_fn ();
5453   if (error)
5454     {
5455       clib_error_report (error);
5456       rv = clib_error_get_code (error);
5457     }
5458
5459   REPLY_MACRO (VL_API_IOAM_DISABLE_REPLY);
5460 }
5461
5462 static void
5463 vl_api_policer_add_del_t_handler (vl_api_policer_add_del_t * mp)
5464 {
5465   vlib_main_t *vm = vlib_get_main ();
5466   vl_api_policer_add_del_reply_t *rmp;
5467   int rv = 0;
5468   u8 *name = NULL;
5469   sse2_qos_pol_cfg_params_st cfg;
5470   clib_error_t *error;
5471   u32 policer_index;
5472
5473   name = format (0, "%s", mp->name);
5474
5475   memset (&cfg, 0, sizeof (cfg));
5476   cfg.rfc = mp->type;
5477   cfg.rnd_type = mp->round_type;
5478   cfg.rate_type = mp->rate_type;
5479   cfg.rb.kbps.cir_kbps = mp->cir;
5480   cfg.rb.kbps.eir_kbps = mp->eir;
5481   cfg.rb.kbps.cb_bytes = mp->cb;
5482   cfg.rb.kbps.eb_bytes = mp->eb;
5483   cfg.conform_action.action_type = mp->conform_action_type;
5484   cfg.conform_action.dscp = mp->conform_dscp;
5485   cfg.exceed_action.action_type = mp->exceed_action_type;
5486   cfg.exceed_action.dscp = mp->exceed_dscp;
5487   cfg.violate_action.action_type = mp->violate_action_type;
5488   cfg.violate_action.dscp = mp->violate_dscp;
5489   cfg.color_aware = mp->color_aware;
5490
5491   error = policer_add_del (vm, name, &cfg, &policer_index, mp->is_add);
5492
5493   if (error)
5494     rv = VNET_API_ERROR_UNSPECIFIED;
5495
5496   /* *INDENT-OFF* */
5497   REPLY_MACRO2(VL_API_POLICER_ADD_DEL_REPLY,
5498   ({
5499     if (rv == 0 &&  mp->is_add)
5500       rmp->policer_index = ntohl(policer_index);
5501     else
5502       rmp->policer_index = ~0;
5503   }));
5504   /* *INDENT-ON* */
5505 }
5506
5507 static void
5508 send_policer_details (u8 * name,
5509                       sse2_qos_pol_cfg_params_st * config,
5510                       policer_read_response_type_st * templ,
5511                       unix_shared_memory_queue_t * q, u32 context)
5512 {
5513   vl_api_policer_details_t *mp;
5514
5515   mp = vl_msg_api_alloc (sizeof (*mp));
5516   memset (mp, 0, sizeof (*mp));
5517   mp->_vl_msg_id = ntohs (VL_API_POLICER_DETAILS);
5518   mp->context = context;
5519   mp->cir = htonl (config->rb.kbps.cir_kbps);
5520   mp->eir = htonl (config->rb.kbps.eir_kbps);
5521   mp->cb = htonl (config->rb.kbps.cb_bytes);
5522   mp->eb = htonl (config->rb.kbps.eb_bytes);
5523   mp->rate_type = config->rate_type;
5524   mp->round_type = config->rnd_type;
5525   mp->type = config->rfc;
5526   mp->conform_action_type = config->conform_action.action_type;
5527   mp->conform_dscp = config->conform_action.dscp;
5528   mp->exceed_action_type = config->exceed_action.action_type;
5529   mp->exceed_dscp = config->exceed_action.dscp;
5530   mp->violate_action_type = config->violate_action.action_type;
5531   mp->violate_dscp = config->violate_action.dscp;
5532   mp->single_rate = templ->single_rate ? 1 : 0;
5533   mp->color_aware = templ->color_aware ? 1 : 0;
5534   mp->scale = htonl (templ->scale);
5535   mp->cir_tokens_per_period = htonl (templ->cir_tokens_per_period);
5536   mp->pir_tokens_per_period = htonl (templ->pir_tokens_per_period);
5537   mp->current_limit = htonl (templ->current_limit);
5538   mp->current_bucket = htonl (templ->current_bucket);
5539   mp->extended_limit = htonl (templ->extended_limit);
5540   mp->extended_bucket = htonl (templ->extended_bucket);
5541   mp->last_update_time = clib_host_to_net_u64 (templ->last_update_time);
5542
5543   strncpy ((char *) mp->name, (char *) name, ARRAY_LEN (mp->name) - 1);
5544
5545   vl_msg_api_send_shmem (q, (u8 *) & mp);
5546 }
5547
5548 static void
5549 vl_api_policer_dump_t_handler (vl_api_policer_dump_t * mp)
5550 {
5551   unix_shared_memory_queue_t *q;
5552   vnet_policer_main_t *pm = &vnet_policer_main;
5553   hash_pair_t *hp;
5554   uword *p;
5555   u32 pool_index;
5556   u8 *match_name = 0;
5557   u8 *name;
5558   sse2_qos_pol_cfg_params_st *config;
5559   policer_read_response_type_st *templ;
5560
5561   q = vl_api_client_index_to_input_queue (mp->client_index);
5562   if (q == 0)
5563     return;
5564
5565   if (mp->match_name_valid)
5566     {
5567       match_name = format (0, "%s%c", mp->match_name, 0);
5568     }
5569
5570   if (mp->match_name_valid)
5571     {
5572       p = hash_get_mem (pm->policer_config_by_name, match_name);
5573       if (p)
5574         {
5575           pool_index = p[0];
5576           config = pool_elt_at_index (pm->configs, pool_index);
5577           templ = pool_elt_at_index (pm->policer_templates, pool_index);
5578           send_policer_details (match_name, config, templ, q, mp->context);
5579         }
5580     }
5581   else
5582     {
5583       /* *INDENT-OFF* */
5584       hash_foreach_pair (hp, pm->policer_config_by_name,
5585       ({
5586         name = (u8 *) hp->key;
5587         pool_index = hp->value[0];
5588         config = pool_elt_at_index (pm->configs, pool_index);
5589         templ = pool_elt_at_index (pm->policer_templates, pool_index);
5590         send_policer_details(name, config, templ, q, mp->context);
5591       }));
5592       /* *INDENT-ON* */
5593     }
5594 }
5595
5596 static void
5597   vl_api_policer_classify_set_interface_t_handler
5598   (vl_api_policer_classify_set_interface_t * mp)
5599 {
5600   vlib_main_t *vm = vlib_get_main ();
5601   vl_api_policer_classify_set_interface_reply_t *rmp;
5602   int rv;
5603   u32 sw_if_index, ip4_table_index, ip6_table_index, l2_table_index;
5604
5605   ip4_table_index = ntohl (mp->ip4_table_index);
5606   ip6_table_index = ntohl (mp->ip6_table_index);
5607   l2_table_index = ntohl (mp->l2_table_index);
5608   sw_if_index = ntohl (mp->sw_if_index);
5609
5610   VALIDATE_SW_IF_INDEX (mp);
5611
5612   rv = vnet_set_policer_classify_intfc (vm, sw_if_index, ip4_table_index,
5613                                         ip6_table_index, l2_table_index,
5614                                         mp->is_add);
5615
5616   BAD_SW_IF_INDEX_LABEL;
5617
5618   REPLY_MACRO (VL_API_POLICER_CLASSIFY_SET_INTERFACE_REPLY);
5619 }
5620
5621 static void
5622 send_policer_classify_details (u32 sw_if_index,
5623                                u32 table_index,
5624                                unix_shared_memory_queue_t * q, u32 context)
5625 {
5626   vl_api_policer_classify_details_t *mp;
5627
5628   mp = vl_msg_api_alloc (sizeof (*mp));
5629   memset (mp, 0, sizeof (*mp));
5630   mp->_vl_msg_id = ntohs (VL_API_POLICER_CLASSIFY_DETAILS);
5631   mp->context = context;
5632   mp->sw_if_index = htonl (sw_if_index);
5633   mp->table_index = htonl (table_index);
5634
5635   vl_msg_api_send_shmem (q, (u8 *) & mp);
5636 }
5637
5638 static void
5639 vl_api_policer_classify_dump_t_handler (vl_api_policer_classify_dump_t * mp)
5640 {
5641   unix_shared_memory_queue_t *q;
5642   policer_classify_main_t *pcm = &policer_classify_main;
5643   u32 *vec_tbl;
5644   int i;
5645
5646   q = vl_api_client_index_to_input_queue (mp->client_index);
5647   if (q == 0)
5648     return;
5649
5650   vec_tbl = pcm->classify_table_index_by_sw_if_index[mp->type];
5651
5652   if (vec_len (vec_tbl))
5653     {
5654       for (i = 0; i < vec_len (vec_tbl); i++)
5655         {
5656           if (vec_elt (vec_tbl, i) == ~0)
5657             continue;
5658
5659           send_policer_classify_details (i, vec_elt (vec_tbl, i), q,
5660                                          mp->context);
5661         }
5662     }
5663 }
5664
5665 static void
5666 vl_api_mpls_tunnel_details_t_handler (vl_api_mpls_fib_details_t * mp)
5667 {
5668   clib_warning ("BUG");
5669 }
5670
5671 typedef struct mpls_tunnel_send_walk_ctx_t_
5672 {
5673   unix_shared_memory_queue_t *q;
5674   u32 index;
5675   u32 context;
5676 } mpls_tunnel_send_walk_ctx_t;
5677
5678 static void
5679 send_mpls_tunnel_entry (u32 mti, void *arg)
5680 {
5681   mpls_tunnel_send_walk_ctx_t *ctx;
5682   vl_api_mpls_tunnel_details_t *mp;
5683   const mpls_tunnel_t *mt;
5684   u32 nlabels;
5685
5686   ctx = arg;
5687
5688   if (~0 != ctx->index && mti != ctx->index)
5689     return;
5690
5691   mt = mpls_tunnel_get (mti);
5692   nlabels = vec_len (mt->mt_label_stack);
5693
5694   mp = vl_msg_api_alloc (sizeof (*mp) + nlabels * sizeof (u32));
5695   memset (mp, 0, sizeof (*mp));
5696   mp->_vl_msg_id = ntohs (VL_API_MPLS_TUNNEL_DETAILS);
5697   mp->context = ctx->context;
5698
5699   mp->tunnel_index = ntohl (mti);
5700   memcpy (mp->mt_next_hop_out_labels,
5701           mt->mt_label_stack, nlabels * sizeof (u32));
5702
5703   // FIXME
5704
5705   vl_msg_api_send_shmem (ctx->q, (u8 *) & mp);
5706 }
5707
5708 static void
5709 vl_api_mpls_tunnel_dump_t_handler (vl_api_mpls_tunnel_dump_t * mp)
5710 {
5711   unix_shared_memory_queue_t *q;
5712
5713   q = vl_api_client_index_to_input_queue (mp->client_index);
5714   if (q == 0)
5715     return;
5716
5717   mpls_tunnel_send_walk_ctx_t ctx = {
5718     .q = q,
5719     .index = ntohl (mp->tunnel_index),
5720     .context = mp->context,
5721   };
5722   mpls_tunnel_walk (send_mpls_tunnel_entry, &ctx);
5723 }
5724
5725 static void
5726 vl_api_mpls_fib_details_t_handler (vl_api_mpls_fib_details_t * mp)
5727 {
5728   clib_warning ("BUG");
5729 }
5730
5731 static void
5732 vl_api_mpls_fib_details_t_endian (vl_api_mpls_fib_details_t * mp)
5733 {
5734   clib_warning ("BUG");
5735 }
5736
5737 static void
5738 vl_api_mpls_fib_details_t_print (vl_api_mpls_fib_details_t * mp)
5739 {
5740   clib_warning ("BUG");
5741 }
5742
5743 static void
5744 send_mpls_fib_details (vpe_api_main_t * am,
5745                        unix_shared_memory_queue_t * q,
5746                        u32 table_id, u32 label, u32 eos,
5747                        fib_route_path_encode_t * api_rpaths, u32 context)
5748 {
5749   vl_api_mpls_fib_details_t *mp;
5750   fib_route_path_encode_t *api_rpath;
5751   vl_api_fib_path2_t *fp;
5752   int path_count;
5753
5754   path_count = vec_len (api_rpaths);
5755   mp = vl_msg_api_alloc (sizeof (*mp) + path_count * sizeof (*fp));
5756   if (!mp)
5757     return;
5758   memset (mp, 0, sizeof (*mp));
5759   mp->_vl_msg_id = ntohs (VL_API_MPLS_FIB_DETAILS);
5760   mp->context = context;
5761
5762   mp->table_id = htonl (table_id);
5763   mp->eos_bit = eos;
5764   mp->label = htonl (label);
5765
5766   mp->count = htonl (path_count);
5767   fp = mp->path;
5768   vec_foreach (api_rpath, api_rpaths)
5769   {
5770     memset (fp, 0, sizeof (*fp));
5771     fp->weight = htonl (api_rpath->rpath.frp_weight);
5772     fp->sw_if_index = htonl (api_rpath->rpath.frp_sw_if_index);
5773     copy_fib_next_hop (api_rpath, fp);
5774     fp++;
5775   }
5776
5777   vl_msg_api_send_shmem (q, (u8 *) & mp);
5778 }
5779
5780 static void
5781 vl_api_mpls_fib_dump_t_handler (vl_api_mpls_fib_dump_t * mp)
5782 {
5783   vpe_api_main_t *am = &vpe_api_main;
5784   unix_shared_memory_queue_t *q;
5785   mpls_main_t *mm = &mpls_main;
5786   fib_table_t *fib_table;
5787   fib_node_index_t lfei, *lfeip, *lfeis = NULL;
5788   mpls_label_t key;
5789   fib_prefix_t pfx;
5790   u32 fib_index;
5791   fib_route_path_encode_t *api_rpaths;
5792
5793   q = vl_api_client_index_to_input_queue (mp->client_index);
5794   if (q == 0)
5795     return;
5796
5797   /* *INDENT-OFF* */
5798   pool_foreach (fib_table, mm->fibs,
5799   ({
5800     hash_foreach(key, lfei, fib_table->mpls.mf_entries,
5801     ({
5802         vec_add1(lfeis, lfei);
5803     }));
5804   }));
5805   vec_sort_with_function(lfeis, fib_entry_cmp_for_sort);
5806
5807   vec_foreach(lfeip, lfeis)
5808   {
5809     fib_entry_get_prefix(*lfeip, &pfx);
5810     fib_index = fib_entry_get_fib_index(*lfeip);
5811     fib_table = fib_table_get(fib_index, pfx.fp_proto);
5812     api_rpaths = NULL;
5813     fib_entry_encode(*lfeip, &api_rpaths);
5814     send_mpls_fib_details (am, q,
5815                            fib_table->ft_table_id,
5816                            pfx.fp_label,
5817                            pfx.fp_eos,
5818                            api_rpaths,
5819                            mp->context);
5820     vec_free(api_rpaths);
5821   }
5822
5823   vec_free (lfeis);
5824 }
5825
5826 static void
5827 vl_api_classify_table_ids_t_handler (vl_api_classify_table_ids_t * mp)
5828 {
5829   unix_shared_memory_queue_t *q;
5830
5831   q = vl_api_client_index_to_input_queue (mp->client_index);
5832   if (q == 0)
5833     return;
5834
5835   vnet_classify_main_t *cm = &vnet_classify_main;
5836   vnet_classify_table_t *t;
5837   u32 *table_ids = 0;
5838   u32 count;
5839
5840   /* *INDENT-OFF* */
5841   pool_foreach (t, cm->tables,
5842   ({
5843     vec_add1 (table_ids, ntohl(t - cm->tables));
5844   }));
5845   /* *INDENT-ON* */
5846   count = vec_len (table_ids);
5847
5848   vl_api_classify_table_ids_reply_t *rmp;
5849   rmp = vl_msg_api_alloc_as_if_client (sizeof (*rmp) + count * sizeof (u32));
5850   rmp->_vl_msg_id = ntohs (VL_API_CLASSIFY_TABLE_IDS_REPLY);
5851   rmp->context = mp->context;
5852   rmp->count = ntohl (count);
5853   clib_memcpy (rmp->ids, table_ids, count * sizeof (u32));
5854   rmp->retval = 0;
5855
5856   vl_msg_api_send_shmem (q, (u8 *) & rmp);
5857
5858   vec_free (table_ids);
5859 }
5860
5861 static void
5862   vl_api_classify_table_by_interface_t_handler
5863   (vl_api_classify_table_by_interface_t * mp)
5864 {
5865   vl_api_classify_table_by_interface_reply_t *rmp;
5866   int rv = 0;
5867
5868   u32 sw_if_index = ntohl (mp->sw_if_index);
5869   u32 *acl = 0;
5870
5871   vec_validate (acl, INPUT_ACL_N_TABLES - 1);
5872   vec_set (acl, ~0);
5873
5874   VALIDATE_SW_IF_INDEX (mp);
5875
5876   input_acl_main_t *am = &input_acl_main;
5877
5878   int if_idx;
5879   u32 type;
5880
5881   for (type = 0; type < INPUT_ACL_N_TABLES; type++)
5882     {
5883       u32 *vec_tbl = am->classify_table_index_by_sw_if_index[type];
5884       if (vec_len (vec_tbl))
5885         {
5886           for (if_idx = 0; if_idx < vec_len (vec_tbl); if_idx++)
5887             {
5888               if (vec_elt (vec_tbl, if_idx) == ~0 || sw_if_index != if_idx)
5889                 {
5890                   continue;
5891                 }
5892               acl[type] = vec_elt (vec_tbl, if_idx);
5893             }
5894         }
5895     }
5896
5897   BAD_SW_IF_INDEX_LABEL;
5898
5899   /* *INDENT-OFF* */
5900   REPLY_MACRO2(VL_API_CLASSIFY_TABLE_BY_INTERFACE_REPLY,
5901   ({
5902     rmp->sw_if_index = ntohl(sw_if_index);
5903     rmp->l2_table_id = ntohl(acl[INPUT_ACL_TABLE_L2]);
5904     rmp->ip4_table_id = ntohl(acl[INPUT_ACL_TABLE_IP4]);
5905     rmp->ip6_table_id = ntohl(acl[INPUT_ACL_TABLE_IP6]);
5906   }));
5907   /* *INDENT-ON* */
5908   vec_free (acl);
5909 }
5910
5911 static void
5912 vl_api_classify_table_info_t_handler (vl_api_classify_table_info_t * mp)
5913 {
5914   unix_shared_memory_queue_t *q;
5915
5916   q = vl_api_client_index_to_input_queue (mp->client_index);
5917   if (q == 0)
5918     return;
5919
5920   vl_api_classify_table_info_reply_t *rmp = 0;
5921
5922   vnet_classify_main_t *cm = &vnet_classify_main;
5923   u32 table_id = ntohl (mp->table_id);
5924   vnet_classify_table_t *t;
5925
5926   /* *INDENT-OFF* */
5927   pool_foreach (t, cm->tables,
5928   ({
5929     if (table_id == t - cm->tables)
5930       {
5931         rmp = vl_msg_api_alloc_as_if_client
5932           (sizeof (*rmp) + t->match_n_vectors * sizeof (u32x4));
5933         rmp->_vl_msg_id = ntohs (VL_API_CLASSIFY_TABLE_INFO_REPLY);
5934         rmp->context = mp->context;
5935         rmp->table_id = ntohl(table_id);
5936         rmp->nbuckets = ntohl(t->nbuckets);
5937         rmp->match_n_vectors = ntohl(t->match_n_vectors);
5938         rmp->skip_n_vectors = ntohl(t->skip_n_vectors);
5939         rmp->active_sessions = ntohl(t->active_elements);
5940         rmp->next_table_index = ntohl(t->next_table_index);
5941         rmp->miss_next_index = ntohl(t->miss_next_index);
5942         rmp->mask_length = ntohl(t->match_n_vectors * sizeof (u32x4));
5943         clib_memcpy(rmp->mask, t->mask, t->match_n_vectors * sizeof(u32x4));
5944         rmp->retval = 0;
5945         break;
5946       }
5947   }));
5948   /* *INDENT-ON* */
5949
5950   if (rmp == 0)
5951     {
5952       rmp = vl_msg_api_alloc (sizeof (*rmp));
5953       rmp->_vl_msg_id = ntohs ((VL_API_CLASSIFY_TABLE_INFO_REPLY));
5954       rmp->context = mp->context;
5955       rmp->retval = ntohl (VNET_API_ERROR_CLASSIFY_TABLE_NOT_FOUND);
5956     }
5957
5958   vl_msg_api_send_shmem (q, (u8 *) & rmp);
5959 }
5960
5961 static void
5962 vl_api_classify_session_details_t_handler (vl_api_classify_session_details_t *
5963                                            mp)
5964 {
5965   clib_warning ("BUG");
5966 }
5967
5968 static void
5969 send_classify_session_details (unix_shared_memory_queue_t * q,
5970                                u32 table_id,
5971                                u32 match_length,
5972                                vnet_classify_entry_t * e, u32 context)
5973 {
5974   vl_api_classify_session_details_t *rmp;
5975
5976   rmp = vl_msg_api_alloc (sizeof (*rmp));
5977   memset (rmp, 0, sizeof (*rmp));
5978   rmp->_vl_msg_id = ntohs (VL_API_CLASSIFY_SESSION_DETAILS);
5979   rmp->context = context;
5980   rmp->table_id = ntohl (table_id);
5981   rmp->hit_next_index = ntohl (e->next_index);
5982   rmp->advance = ntohl (e->advance);
5983   rmp->opaque_index = ntohl (e->opaque_index);
5984   rmp->match_length = ntohl (match_length);
5985   clib_memcpy (rmp->match, e->key, match_length);
5986
5987   vl_msg_api_send_shmem (q, (u8 *) & rmp);
5988 }
5989
5990 static void
5991 vl_api_classify_session_dump_t_handler (vl_api_classify_session_dump_t * mp)
5992 {
5993   vnet_classify_main_t *cm = &vnet_classify_main;
5994   unix_shared_memory_queue_t *q;
5995
5996   u32 table_id = ntohl (mp->table_id);
5997   vnet_classify_table_t *t;
5998
5999   q = vl_api_client_index_to_input_queue (mp->client_index);
6000   if (!q)
6001     return;
6002
6003   /* *INDENT-OFF* */
6004   pool_foreach (t, cm->tables,
6005   ({
6006     if (table_id == t - cm->tables)
6007       {
6008         vnet_classify_bucket_t * b;
6009         vnet_classify_entry_t * v, * save_v;
6010         int i, j, k;
6011
6012         for (i = 0; i < t->nbuckets; i++)
6013           {
6014             b = &t->buckets [i];
6015             if (b->offset == 0)
6016               continue;
6017
6018             save_v = vnet_classify_get_entry (t, b->offset);
6019             for (j = 0; j < (1<<b->log2_pages); j++)
6020               {
6021                 for (k = 0; k < t->entries_per_page; k++)
6022                   {
6023                     v = vnet_classify_entry_at_index
6024                       (t, save_v, j*t->entries_per_page + k);
6025                     if (vnet_classify_entry_is_free (v))
6026                       continue;
6027
6028                     send_classify_session_details
6029                       (q, table_id, t->match_n_vectors * sizeof (u32x4),
6030                        v, mp->context);
6031                   }
6032               }
6033           }
6034         break;
6035       }
6036   }));
6037   /* *INDENT-ON* */
6038 }
6039
6040 static void
6041 vl_api_set_ipfix_exporter_t_handler (vl_api_set_ipfix_exporter_t * mp)
6042 {
6043   vlib_main_t *vm = vlib_get_main ();
6044   flow_report_main_t *frm = &flow_report_main;
6045   vl_api_set_ipfix_exporter_reply_t *rmp;
6046   ip4_address_t collector, src;
6047   u16 collector_port = UDP_DST_PORT_ipfix;
6048   u32 path_mtu;
6049   u32 template_interval;
6050   u8 udp_checksum;
6051   u32 fib_id;
6052   u32 fib_index = ~0;
6053   int rv = 0;
6054
6055   memcpy (collector.data, mp->collector_address, sizeof (collector.data));
6056   collector_port = ntohs (mp->collector_port);
6057   if (collector_port == (u16) ~ 0)
6058     collector_port = UDP_DST_PORT_ipfix;
6059   memcpy (src.data, mp->src_address, sizeof (src.data));
6060   fib_id = ntohl (mp->vrf_id);
6061
6062   ip4_main_t *im = &ip4_main;
6063   if (fib_id == ~0)
6064     {
6065       fib_index = ~0;
6066     }
6067   else
6068     {
6069       uword *p = hash_get (im->fib_index_by_table_id, fib_id);
6070       if (!p)
6071         {
6072           rv = VNET_API_ERROR_NO_SUCH_FIB;
6073           goto out;
6074         }
6075       fib_index = p[0];
6076     }
6077
6078   path_mtu = ntohl (mp->path_mtu);
6079   if (path_mtu == ~0)
6080     path_mtu = 512;             // RFC 7011 section 10.3.3.
6081   template_interval = ntohl (mp->template_interval);
6082   if (template_interval == ~0)
6083     template_interval = 20;
6084   udp_checksum = mp->udp_checksum;
6085
6086   if (collector.as_u32 == 0)
6087     {
6088       rv = VNET_API_ERROR_INVALID_VALUE;
6089       goto out;
6090     }
6091
6092   if (src.as_u32 == 0)
6093     {
6094       rv = VNET_API_ERROR_INVALID_VALUE;
6095       goto out;
6096     }
6097
6098   if (path_mtu > 1450 /* vpp does not support fragmentation */ )
6099     {
6100       rv = VNET_API_ERROR_INVALID_VALUE;
6101       goto out;
6102     }
6103
6104   if (path_mtu < 68)
6105     {
6106       rv = VNET_API_ERROR_INVALID_VALUE;
6107       goto out;
6108     }
6109
6110   /* Reset report streams if we are reconfiguring IP addresses */
6111   if (frm->ipfix_collector.as_u32 != collector.as_u32 ||
6112       frm->src_address.as_u32 != src.as_u32 ||
6113       frm->collector_port != collector_port)
6114     vnet_flow_reports_reset (frm);
6115
6116   frm->ipfix_collector.as_u32 = collector.as_u32;
6117   frm->collector_port = collector_port;
6118   frm->src_address.as_u32 = src.as_u32;
6119   frm->fib_index = fib_index;
6120   frm->path_mtu = path_mtu;
6121   frm->template_interval = template_interval;
6122   frm->udp_checksum = udp_checksum;
6123
6124   /* Turn on the flow reporting process */
6125   vlib_process_signal_event (vm, flow_report_process_node.index, 1, 0);
6126
6127 out:
6128   REPLY_MACRO (VL_API_SET_IPFIX_EXPORTER_REPLY);
6129 }
6130
6131 static void
6132 vl_api_ipfix_exporter_dump_t_handler (vl_api_ipfix_exporter_dump_t * mp)
6133 {
6134   flow_report_main_t *frm = &flow_report_main;
6135   unix_shared_memory_queue_t *q;
6136   vl_api_ipfix_exporter_details_t *rmp;
6137   ip4_main_t *im = &ip4_main;
6138   u32 vrf_id;
6139
6140   q = vl_api_client_index_to_input_queue (mp->client_index);
6141   if (!q)
6142     return;
6143
6144   rmp = vl_msg_api_alloc (sizeof (*rmp));
6145   memset (rmp, 0, sizeof (*rmp));
6146   rmp->_vl_msg_id = ntohs (VL_API_IPFIX_EXPORTER_DETAILS);
6147   rmp->context = mp->context;
6148   memcpy (rmp->collector_address, frm->ipfix_collector.data,
6149           sizeof (frm->ipfix_collector.data));
6150   rmp->collector_port = htons (frm->collector_port);
6151   memcpy (rmp->src_address, frm->src_address.data,
6152           sizeof (frm->src_address.data));
6153   if (frm->fib_index == ~0)
6154     vrf_id = ~0;
6155   else
6156     vrf_id = im->fibs[frm->fib_index].ft_table_id;
6157   rmp->vrf_id = htonl (vrf_id);
6158   rmp->path_mtu = htonl (frm->path_mtu);
6159   rmp->template_interval = htonl (frm->template_interval);
6160   rmp->udp_checksum = (frm->udp_checksum != 0);
6161
6162   vl_msg_api_send_shmem (q, (u8 *) & rmp);
6163 }
6164
6165 static void
6166   vl_api_set_ipfix_classify_stream_t_handler
6167   (vl_api_set_ipfix_classify_stream_t * mp)
6168 {
6169   vl_api_set_ipfix_classify_stream_reply_t *rmp;
6170   flow_report_classify_main_t *fcm = &flow_report_classify_main;
6171   flow_report_main_t *frm = &flow_report_main;
6172   u32 domain_id = 0;
6173   u32 src_port = UDP_DST_PORT_ipfix;
6174   int rv = 0;
6175
6176   domain_id = ntohl (mp->domain_id);
6177   src_port = ntohs (mp->src_port);
6178
6179   if (fcm->src_port != 0 &&
6180       (fcm->domain_id != domain_id || fcm->src_port != (u16) src_port))
6181     {
6182       int rv = vnet_stream_change (frm, fcm->domain_id, fcm->src_port,
6183                                    domain_id, (u16) src_port);
6184       ASSERT (rv == 0);
6185     }
6186
6187   fcm->domain_id = domain_id;
6188   fcm->src_port = (u16) src_port;
6189
6190   REPLY_MACRO (VL_API_SET_IPFIX_CLASSIFY_STREAM_REPLY);
6191 }
6192
6193 static void
6194   vl_api_ipfix_classify_stream_dump_t_handler
6195   (vl_api_ipfix_classify_stream_dump_t * mp)
6196 {
6197   flow_report_classify_main_t *fcm = &flow_report_classify_main;
6198   unix_shared_memory_queue_t *q;
6199   vl_api_ipfix_classify_stream_details_t *rmp;
6200
6201   q = vl_api_client_index_to_input_queue (mp->client_index);
6202   if (!q)
6203     return;
6204
6205   rmp = vl_msg_api_alloc (sizeof (*rmp));
6206   memset (rmp, 0, sizeof (*rmp));
6207   rmp->_vl_msg_id = ntohs (VL_API_IPFIX_CLASSIFY_STREAM_DETAILS);
6208   rmp->context = mp->context;
6209   rmp->domain_id = htonl (fcm->domain_id);
6210   rmp->src_port = htons (fcm->src_port);
6211
6212   vl_msg_api_send_shmem (q, (u8 *) & rmp);
6213 }
6214
6215 static void
6216   vl_api_ipfix_classify_table_add_del_t_handler
6217   (vl_api_ipfix_classify_table_add_del_t * mp)
6218 {
6219   vl_api_ipfix_classify_table_add_del_reply_t *rmp;
6220   flow_report_classify_main_t *fcm = &flow_report_classify_main;
6221   flow_report_main_t *frm = &flow_report_main;
6222   vnet_flow_report_add_del_args_t args;
6223   ipfix_classify_table_t *table;
6224   int is_add;
6225   u32 classify_table_index;
6226   u8 ip_version;
6227   u8 transport_protocol;
6228   int rv = 0;
6229
6230   classify_table_index = ntohl (mp->table_id);
6231   ip_version = mp->ip_version;
6232   transport_protocol = mp->transport_protocol;
6233   is_add = mp->is_add;
6234
6235   if (fcm->src_port == 0)
6236     {
6237       /* call set_ipfix_classify_stream first */
6238       rv = VNET_API_ERROR_UNSPECIFIED;
6239       goto out;
6240     }
6241
6242   memset (&args, 0, sizeof (args));
6243
6244   table = 0;
6245   int i;
6246   for (i = 0; i < vec_len (fcm->tables); i++)
6247     if (ipfix_classify_table_index_valid (i))
6248       if (fcm->tables[i].classify_table_index == classify_table_index)
6249         {
6250           table = &fcm->tables[i];
6251           break;
6252         }
6253
6254   if (is_add)
6255     {
6256       if (table)
6257         {
6258           rv = VNET_API_ERROR_VALUE_EXIST;
6259           goto out;
6260         }
6261       table = ipfix_classify_add_table ();
6262       table->classify_table_index = classify_table_index;
6263     }
6264   else
6265     {
6266       if (!table)
6267         {
6268           rv = VNET_API_ERROR_NO_SUCH_ENTRY;
6269           goto out;
6270         }
6271     }
6272
6273   table->ip_version = ip_version;
6274   table->transport_protocol = transport_protocol;
6275
6276   args.opaque.as_uword = table - fcm->tables;
6277   args.rewrite_callback = ipfix_classify_template_rewrite;
6278   args.flow_data_callback = ipfix_classify_send_flows;
6279   args.is_add = is_add;
6280   args.domain_id = fcm->domain_id;
6281   args.src_port = fcm->src_port;
6282
6283   rv = vnet_flow_report_add_del (frm, &args);
6284
6285   /* If deleting, or add failed */
6286   if (is_add == 0 || (rv && is_add))
6287     ipfix_classify_delete_table (table - fcm->tables);
6288
6289 out:
6290   REPLY_MACRO (VL_API_SET_IPFIX_CLASSIFY_STREAM_REPLY);
6291 }
6292
6293 static void
6294 send_ipfix_classify_table_details (u32 table_index,
6295                                    unix_shared_memory_queue_t * q,
6296                                    u32 context)
6297 {
6298   flow_report_classify_main_t *fcm = &flow_report_classify_main;
6299   vl_api_ipfix_classify_table_details_t *mp;
6300
6301   ipfix_classify_table_t *table = &fcm->tables[table_index];
6302
6303   mp = vl_msg_api_alloc (sizeof (*mp));
6304   memset (mp, 0, sizeof (*mp));
6305   mp->_vl_msg_id = ntohs (VL_API_IPFIX_CLASSIFY_TABLE_DETAILS);
6306   mp->context = context;
6307   mp->table_id = htonl (table->classify_table_index);
6308   mp->ip_version = table->ip_version;
6309   mp->transport_protocol = table->transport_protocol;
6310
6311   vl_msg_api_send_shmem (q, (u8 *) & mp);
6312 }
6313
6314 static void
6315   vl_api_ipfix_classify_table_dump_t_handler
6316   (vl_api_ipfix_classify_table_dump_t * mp)
6317 {
6318   flow_report_classify_main_t *fcm = &flow_report_classify_main;
6319   unix_shared_memory_queue_t *q;
6320   u32 i;
6321
6322   q = vl_api_client_index_to_input_queue (mp->client_index);
6323   if (!q)
6324     return;
6325
6326   for (i = 0; i < vec_len (fcm->tables); i++)
6327     if (ipfix_classify_table_index_valid (i))
6328       send_ipfix_classify_table_details (i, q, mp->context);
6329 }
6330
6331 static void
6332 vl_api_pg_create_interface_t_handler (vl_api_pg_create_interface_t * mp)
6333 {
6334   vl_api_pg_create_interface_reply_t *rmp;
6335   int rv = 0;
6336
6337   pg_main_t *pg = &pg_main;
6338   u32 pg_if_id = pg_interface_add_or_get (pg, ntohl (mp->interface_id));
6339   pg_interface_t *pi = pool_elt_at_index (pg->interfaces, pg_if_id);
6340
6341   /* *INDENT-OFF* */
6342   REPLY_MACRO2(VL_API_PG_CREATE_INTERFACE_REPLY,
6343   ({
6344     rmp->sw_if_index = ntohl(pi->sw_if_index);
6345   }));
6346   /* *INDENT-ON* */
6347 }
6348
6349 static void
6350 vl_api_pg_capture_t_handler (vl_api_pg_capture_t * mp)
6351 {
6352   vl_api_pg_capture_reply_t *rmp;
6353   int rv = 0;
6354
6355   vnet_main_t *vnm = vnet_get_main ();
6356   vnet_interface_main_t *im = &vnm->interface_main;
6357   vnet_hw_interface_t *hi = 0;
6358
6359   u8 *intf_name = format (0, "pg%d", ntohl (mp->interface_id), 0);
6360   u32 hw_if_index = ~0;
6361   uword *p = hash_get_mem (im->hw_interface_by_name, intf_name);
6362   if (p)
6363     hw_if_index = *p;
6364   vec_free (intf_name);
6365
6366   if (hw_if_index != ~0)
6367     {
6368       pg_capture_args_t _a, *a = &_a;
6369
6370       u32 len = ntohl (mp->pcap_name_length);
6371       u8 *pcap_file_name = vec_new (u8, len);
6372       clib_memcpy (pcap_file_name, mp->pcap_file_name, len);
6373
6374       hi = vnet_get_sup_hw_interface (vnm, hw_if_index);
6375       a->hw_if_index = hw_if_index;
6376       a->dev_instance = hi->dev_instance;
6377       a->is_enabled = mp->is_enabled;
6378       a->pcap_file_name = pcap_file_name;
6379       a->count = ntohl (mp->count);
6380
6381       clib_error_t *e = pg_capture (a);
6382       if (e)
6383         {
6384           clib_error_report (e);
6385           rv = VNET_API_ERROR_CANNOT_CREATE_PCAP_FILE;
6386         }
6387
6388       vec_free (pcap_file_name);
6389     }
6390   REPLY_MACRO (VL_API_PG_CAPTURE_REPLY);
6391 }
6392
6393 static void
6394 vl_api_pg_enable_disable_t_handler (vl_api_pg_enable_disable_t * mp)
6395 {
6396   vl_api_pg_enable_disable_reply_t *rmp;
6397   int rv = 0;
6398
6399   pg_main_t *pg = &pg_main;
6400   u32 stream_index = ~0;
6401
6402   int is_enable = mp->is_enabled != 0;
6403   u32 len = ntohl (mp->stream_name_length) - 1;
6404
6405   if (len > 0)
6406     {
6407       u8 *stream_name = vec_new (u8, len);
6408       clib_memcpy (stream_name, mp->stream_name, len);
6409       uword *p = hash_get_mem (pg->stream_index_by_name, stream_name);
6410       if (p)
6411         stream_index = *p;
6412       vec_free (stream_name);
6413     }
6414
6415   pg_enable_disable (stream_index, is_enable);
6416
6417   REPLY_MACRO (VL_API_PG_ENABLE_DISABLE_REPLY);
6418 }
6419
6420 static void
6421   vl_api_ip_source_and_port_range_check_add_del_t_handler
6422   (vl_api_ip_source_and_port_range_check_add_del_t * mp)
6423 {
6424   vl_api_ip_source_and_port_range_check_add_del_reply_t *rmp;
6425   int rv = 0;
6426
6427   u8 is_ipv6 = mp->is_ipv6;
6428   u8 is_add = mp->is_add;
6429   u8 mask_length = mp->mask_length;
6430   ip4_address_t ip4_addr;
6431   ip6_address_t ip6_addr;
6432   u16 *low_ports = 0;
6433   u16 *high_ports = 0;
6434   u32 vrf_id;
6435   u16 tmp_low, tmp_high;
6436   u8 num_ranges;
6437   int i;
6438
6439   // Validate port range
6440   num_ranges = mp->number_of_ranges;
6441   if (num_ranges > 32)
6442     {                           // This is size of array in VPE.API
6443       rv = VNET_API_ERROR_EXCEEDED_NUMBER_OF_RANGES_CAPACITY;
6444       goto reply;
6445     }
6446
6447   vec_reset_length (low_ports);
6448   vec_reset_length (high_ports);
6449
6450   for (i = 0; i < num_ranges; i++)
6451     {
6452       tmp_low = mp->low_ports[i];
6453       tmp_high = mp->high_ports[i];
6454       // If tmp_low <= tmp_high then only need to check tmp_low = 0
6455       // If tmp_low <= tmp_high then only need to check tmp_high > 65535
6456       if (tmp_low > tmp_high || tmp_low == 0 || tmp_high > 65535)
6457         {
6458           rv = VNET_API_ERROR_INVALID_VALUE;
6459           goto reply;
6460         }
6461       vec_add1 (low_ports, tmp_low);
6462       vec_add1 (high_ports, tmp_high + 1);
6463     }
6464
6465   // Validate mask_length
6466   if ((is_ipv6 && mask_length > 128) || (!is_ipv6 && mask_length > 32))
6467     {
6468       rv = VNET_API_ERROR_ADDRESS_LENGTH_MISMATCH;
6469       goto reply;
6470     }
6471
6472   vrf_id = ntohl (mp->vrf_id);
6473
6474   if (vrf_id < 1)
6475     {
6476       rv = VNET_API_ERROR_INVALID_VALUE;
6477       goto reply;
6478     }
6479
6480
6481   if (is_ipv6)
6482     {
6483       clib_memcpy (ip6_addr.as_u8, mp->address, sizeof (ip6_addr.as_u8));
6484       rv = ip6_source_and_port_range_check_add_del (&ip6_addr,
6485                                                     mask_length,
6486                                                     vrf_id,
6487                                                     low_ports,
6488                                                     high_ports, is_add);
6489     }
6490   else
6491     {
6492       clib_memcpy (ip4_addr.data, mp->address, sizeof (ip4_addr));
6493       rv = ip4_source_and_port_range_check_add_del (&ip4_addr,
6494                                                     mask_length,
6495                                                     vrf_id,
6496                                                     low_ports,
6497                                                     high_ports, is_add);
6498     }
6499
6500 reply:
6501   vec_free (low_ports);
6502   vec_free (high_ports);
6503   REPLY_MACRO (VL_API_IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL_REPLY);
6504 }
6505
6506 static void
6507   vl_api_ip_source_and_port_range_check_interface_add_del_t_handler
6508   (vl_api_ip_source_and_port_range_check_interface_add_del_t * mp)
6509 {
6510   vlib_main_t *vm = vlib_get_main ();
6511   vl_api_ip_source_and_port_range_check_interface_add_del_reply_t *rmp;
6512   ip4_main_t *im = &ip4_main;
6513   int rv;
6514   u32 sw_if_index;
6515   u32 fib_index[IP_SOURCE_AND_PORT_RANGE_CHECK_N_PROTOCOLS];
6516   u32 vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_N_PROTOCOLS];
6517   uword *p = 0;
6518   int i;
6519
6520   vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_TCP_OUT] =
6521     ntohl (mp->tcp_out_vrf_id);
6522   vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_UDP_OUT] =
6523     ntohl (mp->udp_out_vrf_id);
6524   vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_TCP_IN] =
6525     ntohl (mp->tcp_in_vrf_id);
6526   vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_UDP_IN] =
6527     ntohl (mp->udp_in_vrf_id);
6528
6529
6530   for (i = 0; i < IP_SOURCE_AND_PORT_RANGE_CHECK_N_PROTOCOLS; i++)
6531     {
6532       if (vrf_id[i] != 0 && vrf_id[i] != ~0)
6533         {
6534           p = hash_get (im->fib_index_by_table_id, vrf_id[i]);
6535
6536           if (p == 0)
6537             {
6538               rv = VNET_API_ERROR_INVALID_VALUE;
6539               goto reply;
6540             }
6541
6542           fib_index[i] = p[0];
6543         }
6544       else
6545         fib_index[i] = ~0;
6546     }
6547   sw_if_index = ntohl (mp->sw_if_index);
6548
6549   VALIDATE_SW_IF_INDEX (mp);
6550
6551   rv =
6552     set_ip_source_and_port_range_check (vm, fib_index, sw_if_index,
6553                                         mp->is_add);
6554
6555   BAD_SW_IF_INDEX_LABEL;
6556 reply:
6557
6558   REPLY_MACRO (VL_API_IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL_REPLY);
6559 }
6560
6561 static void
6562 vl_api_ipsec_gre_add_del_tunnel_t_handler (vl_api_ipsec_gre_add_del_tunnel_t *
6563                                            mp)
6564 {
6565   vl_api_ipsec_gre_add_del_tunnel_reply_t *rmp;
6566   int rv = 0;
6567   vnet_ipsec_gre_add_del_tunnel_args_t _a, *a = &_a;
6568   u32 sw_if_index = ~0;
6569
6570   /* Check src & dst are different */
6571   if (memcmp (mp->src_address, mp->dst_address, 4) == 0)
6572     {
6573       rv = VNET_API_ERROR_SAME_SRC_DST;
6574       goto out;
6575     }
6576
6577   memset (a, 0, sizeof (*a));
6578
6579   /* ip addresses sent in network byte order */
6580   clib_memcpy (&(a->src), mp->src_address, 4);
6581   clib_memcpy (&(a->dst), mp->dst_address, 4);
6582   a->is_add = mp->is_add;
6583   a->lsa = ntohl (mp->local_sa_id);
6584   a->rsa = ntohl (mp->remote_sa_id);
6585
6586   rv = vnet_ipsec_gre_add_del_tunnel (a, &sw_if_index);
6587
6588 out:
6589     /* *INDENT-OFF* */
6590     REPLY_MACRO2(VL_API_GRE_ADD_DEL_TUNNEL_REPLY,
6591     ({
6592         rmp->sw_if_index = ntohl (sw_if_index);
6593     }));
6594     /* *INDENT-ON* */
6595 }
6596
6597 static void send_ipsec_gre_tunnel_details
6598   (ipsec_gre_tunnel_t * t, unix_shared_memory_queue_t * q, u32 context)
6599 {
6600   vl_api_ipsec_gre_tunnel_details_t *rmp;
6601
6602   rmp = vl_msg_api_alloc (sizeof (*rmp));
6603   memset (rmp, 0, sizeof (*rmp));
6604   rmp->_vl_msg_id = ntohs (VL_API_IPSEC_GRE_TUNNEL_DETAILS);
6605   clib_memcpy (rmp->src_address, &(t->tunnel_src), 4);
6606   clib_memcpy (rmp->dst_address, &(t->tunnel_dst), 4);
6607   rmp->sw_if_index = htonl (t->sw_if_index);
6608   rmp->local_sa_id = htonl (t->local_sa_id);
6609   rmp->remote_sa_id = htonl (t->remote_sa_id);
6610   rmp->context = context;
6611
6612   vl_msg_api_send_shmem (q, (u8 *) & rmp);
6613 }
6614
6615 static void vl_api_ipsec_gre_tunnel_dump_t_handler
6616   (vl_api_ipsec_gre_tunnel_dump_t * mp)
6617 {
6618   unix_shared_memory_queue_t *q;
6619   ipsec_gre_main_t *igm = &ipsec_gre_main;
6620   ipsec_gre_tunnel_t *t;
6621   u32 sw_if_index;
6622
6623   q = vl_api_client_index_to_input_queue (mp->client_index);
6624   if (q == 0)
6625     {
6626       return;
6627     }
6628
6629   sw_if_index = ntohl (mp->sw_if_index);
6630
6631   if (~0 == sw_if_index)
6632     {
6633         /* *INDENT-OFF* */
6634         pool_foreach (t, igm->tunnels,
6635         ({
6636             send_ipsec_gre_tunnel_details(t, q, mp->context);
6637         }));
6638         /* *INDENT-ON* */
6639     }
6640   else
6641     {
6642       if ((sw_if_index >= vec_len (igm->tunnel_index_by_sw_if_index)) ||
6643           (~0 == igm->tunnel_index_by_sw_if_index[sw_if_index]))
6644         {
6645           return;
6646         }
6647       t = &igm->tunnels[igm->tunnel_index_by_sw_if_index[sw_if_index]];
6648       send_ipsec_gre_tunnel_details (t, q, mp->context);
6649     }
6650 }
6651
6652 static void
6653 vl_api_delete_subif_t_handler (vl_api_delete_subif_t * mp)
6654 {
6655   vl_api_delete_subif_reply_t *rmp;
6656   int rv;
6657
6658   rv = vnet_delete_sub_interface (ntohl (mp->sw_if_index));
6659
6660   REPLY_MACRO (VL_API_DELETE_SUBIF_REPLY);
6661 }
6662
6663 static void
6664   vl_api_l2_interface_pbb_tag_rewrite_t_handler
6665   (vl_api_l2_interface_pbb_tag_rewrite_t * mp)
6666 {
6667   vl_api_l2_interface_pbb_tag_rewrite_reply_t *rmp;
6668   vnet_main_t *vnm = vnet_get_main ();
6669   vlib_main_t *vm = vlib_get_main ();
6670   u32 vtr_op;
6671   int rv = 0;
6672
6673   VALIDATE_SW_IF_INDEX (mp);
6674
6675   vtr_op = ntohl (mp->vtr_op);
6676
6677   switch (vtr_op)
6678     {
6679     case L2_VTR_DISABLED:
6680     case L2_VTR_PUSH_2:
6681     case L2_VTR_POP_2:
6682     case L2_VTR_TRANSLATE_2_1:
6683       break;
6684
6685     default:
6686       rv = VNET_API_ERROR_INVALID_VALUE;
6687       goto bad_sw_if_index;
6688     }
6689
6690   rv = l2pbb_configure (vm, vnm, ntohl (mp->sw_if_index), vtr_op,
6691                         mp->b_dmac, mp->b_smac, ntohs (mp->b_vlanid),
6692                         ntohl (mp->i_sid), ntohs (mp->outer_tag));
6693
6694   BAD_SW_IF_INDEX_LABEL;
6695
6696   REPLY_MACRO (VL_API_L2_INTERFACE_PBB_TAG_REWRITE_REPLY);
6697
6698 }
6699
6700 static void
6701 vl_api_bfd_udp_add_t_handler (vl_api_bfd_udp_add_t * mp)
6702 {
6703   vl_api_bfd_udp_add_reply_t *rmp;
6704   int rv;
6705
6706   VALIDATE_SW_IF_INDEX (mp);
6707
6708   ip46_address_t local_addr;
6709   memset (&local_addr, 0, sizeof (local_addr));
6710   ip46_address_t peer_addr;
6711   memset (&peer_addr, 0, sizeof (peer_addr));
6712   if (mp->is_ipv6)
6713     {
6714       clib_memcpy (&local_addr.ip6, mp->local_addr, sizeof (local_addr.ip6));
6715       clib_memcpy (&peer_addr.ip6, mp->peer_addr, sizeof (peer_addr.ip6));
6716     }
6717   else
6718     {
6719       clib_memcpy (&local_addr.ip4, mp->local_addr, sizeof (local_addr.ip4));
6720       clib_memcpy (&peer_addr.ip4, mp->peer_addr, sizeof (peer_addr.ip4));
6721     }
6722
6723   rv = bfd_udp_add_session (clib_net_to_host_u32 (mp->sw_if_index),
6724                             clib_net_to_host_u32 (mp->desired_min_tx),
6725                             clib_net_to_host_u32 (mp->required_min_rx),
6726                             mp->detect_mult, &local_addr, &peer_addr);
6727
6728   BAD_SW_IF_INDEX_LABEL;
6729   REPLY_MACRO (VL_API_BFD_UDP_ADD_REPLY);
6730 }
6731
6732 static void
6733 vl_api_bfd_udp_del_t_handler (vl_api_bfd_udp_del_t * mp)
6734 {
6735   vl_api_bfd_udp_del_reply_t *rmp;
6736   int rv;
6737
6738   VALIDATE_SW_IF_INDEX (mp);
6739
6740   ip46_address_t local_addr;
6741   memset (&local_addr, 0, sizeof (local_addr));
6742   ip46_address_t peer_addr;
6743   memset (&peer_addr, 0, sizeof (peer_addr));
6744   if (mp->is_ipv6)
6745     {
6746       clib_memcpy (&local_addr.ip6, mp->local_addr, sizeof (local_addr.ip6));
6747       clib_memcpy (&peer_addr.ip6, mp->peer_addr, sizeof (peer_addr.ip6));
6748     }
6749   else
6750     {
6751       clib_memcpy (&local_addr.ip4, mp->local_addr, sizeof (local_addr.ip4));
6752       clib_memcpy (&peer_addr.ip4, mp->peer_addr, sizeof (peer_addr.ip4));
6753     }
6754
6755   rv =
6756     bfd_udp_del_session (clib_net_to_host_u32 (mp->sw_if_index), &local_addr,
6757                          &peer_addr);
6758
6759   BAD_SW_IF_INDEX_LABEL;
6760   REPLY_MACRO (VL_API_BFD_UDP_DEL_REPLY);
6761 }
6762
6763 void
6764 send_bfd_udp_session_details (unix_shared_memory_queue_t * q, u32 context,
6765                               bfd_session_t * bs)
6766 {
6767   if (bs->transport != BFD_TRANSPORT_UDP4 &&
6768       bs->transport != BFD_TRANSPORT_UDP6)
6769     {
6770       return;
6771     }
6772
6773   vl_api_bfd_udp_session_details_t *mp = vl_msg_api_alloc (sizeof (*mp));
6774   memset (mp, 0, sizeof (*mp));
6775   mp->_vl_msg_id = ntohs (VL_API_BFD_UDP_SESSION_DETAILS);
6776   mp->context = context;
6777   mp->bs_index = clib_host_to_net_u32 (bs->bs_idx);
6778   mp->state = bs->local_state;
6779   bfd_udp_session_t *bus = &bs->udp;
6780   bfd_udp_key_t *key = &bus->key;
6781   mp->sw_if_index = clib_host_to_net_u32 (key->sw_if_index);
6782   mp->is_ipv6 = !(ip46_address_is_ip4 (&key->local_addr));
6783   if (mp->is_ipv6)
6784     {
6785       clib_memcpy (mp->local_addr, &key->local_addr,
6786                    sizeof (key->local_addr));
6787       clib_memcpy (mp->peer_addr, &key->peer_addr, sizeof (key->peer_addr));
6788     }
6789   else
6790     {
6791       clib_memcpy (mp->local_addr, key->local_addr.ip4.data,
6792                    sizeof (key->local_addr.ip4.data));
6793       clib_memcpy (mp->peer_addr, key->peer_addr.ip4.data,
6794                    sizeof (key->peer_addr.ip4.data));
6795     }
6796
6797   vl_msg_api_send_shmem (q, (u8 *) & mp);
6798 }
6799
6800 void
6801 bfd_event (bfd_main_t * bm, bfd_session_t * bs)
6802 {
6803   vpe_api_main_t *vam = &vpe_api_main;
6804   vpe_client_registration_t *reg;
6805   unix_shared_memory_queue_t *q;
6806   /* *INDENT-OFF* */
6807   pool_foreach (reg, vam->bfd_events_registrations, ({
6808                   q = vl_api_client_index_to_input_queue (reg->client_index);
6809                   if (q)
6810                     {
6811                       switch (bs->transport)
6812                         {
6813                         case BFD_TRANSPORT_UDP4:
6814                         /* fallthrough */
6815                         case BFD_TRANSPORT_UDP6:
6816                           send_bfd_udp_session_details (q, 0, bs);
6817                         }
6818                     }
6819                 }));
6820   /* *INDENT-ON* */
6821 }
6822
6823 static void
6824 vl_api_bfd_udp_session_dump_t_handler (vl_api_bfd_udp_session_dump_t * mp)
6825 {
6826   unix_shared_memory_queue_t *q;
6827
6828   q = vl_api_client_index_to_input_queue (mp->client_index);
6829
6830   if (q == 0)
6831     return;
6832
6833   bfd_session_t *bs = NULL;
6834   /* *INDENT-OFF* */
6835   pool_foreach (bs, bfd_main.sessions, ({
6836                   if (bs->transport == BFD_TRANSPORT_UDP4 ||
6837                       bs->transport == BFD_TRANSPORT_UDP6)
6838                     send_bfd_udp_session_details (q, mp->context, bs);
6839                 }));
6840   /* *INDENT-ON* */
6841 }
6842
6843 static void
6844 vl_api_bfd_session_set_flags_t_handler (vl_api_bfd_session_set_flags_t * mp)
6845 {
6846   vl_api_bfd_session_set_flags_reply_t *rmp;
6847   int rv;
6848
6849   rv =
6850     bfd_session_set_flags (clib_net_to_host_u32 (mp->bs_index),
6851                            mp->admin_up_down);
6852
6853   REPLY_MACRO (VL_API_BFD_SESSION_SET_FLAGS_REPLY);
6854 }
6855
6856 static void
6857 vl_api_punt_t_handler (vl_api_punt_t * mp)
6858 {
6859   vl_api_punt_reply_t *rmp;
6860   vlib_main_t *vm = vlib_get_main ();
6861   int rv = 0;
6862   clib_error_t *error;
6863
6864   error = vnet_punt_add_del (vm, mp->ipv, mp->l4_protocol,
6865                              ntohs (mp->l4_port), mp->is_add);
6866   if (error)
6867     {
6868       rv = -1;
6869       clib_error_report (error);
6870     }
6871
6872   REPLY_MACRO (VL_API_PUNT_REPLY);
6873 }
6874
6875 static void
6876   vl_api_flow_classify_set_interface_t_handler
6877   (vl_api_flow_classify_set_interface_t * mp)
6878 {
6879   vlib_main_t *vm = vlib_get_main ();
6880   vl_api_flow_classify_set_interface_reply_t *rmp;
6881   int rv;
6882   u32 sw_if_index, ip4_table_index, ip6_table_index;
6883
6884   ip4_table_index = ntohl (mp->ip4_table_index);
6885   ip6_table_index = ntohl (mp->ip6_table_index);
6886   sw_if_index = ntohl (mp->sw_if_index);
6887
6888   VALIDATE_SW_IF_INDEX (mp);
6889
6890   rv = vnet_set_flow_classify_intfc (vm, sw_if_index, ip4_table_index,
6891                                      ip6_table_index, mp->is_add);
6892
6893   BAD_SW_IF_INDEX_LABEL;
6894
6895   REPLY_MACRO (VL_API_FLOW_CLASSIFY_SET_INTERFACE_REPLY);
6896 }
6897
6898 static void
6899 send_flow_classify_details (u32 sw_if_index,
6900                             u32 table_index,
6901                             unix_shared_memory_queue_t * q, u32 context)
6902 {
6903   vl_api_flow_classify_details_t *mp;
6904
6905   mp = vl_msg_api_alloc (sizeof (*mp));
6906   memset (mp, 0, sizeof (*mp));
6907   mp->_vl_msg_id = ntohs (VL_API_FLOW_CLASSIFY_DETAILS);
6908   mp->context = context;
6909   mp->sw_if_index = htonl (sw_if_index);
6910   mp->table_index = htonl (table_index);
6911
6912   vl_msg_api_send_shmem (q, (u8 *) & mp);
6913 }
6914
6915 static void
6916 vl_api_flow_classify_dump_t_handler (vl_api_flow_classify_dump_t * mp)
6917 {
6918   unix_shared_memory_queue_t *q;
6919   flow_classify_main_t *pcm = &flow_classify_main;
6920   u32 *vec_tbl;
6921   int i;
6922
6923   q = vl_api_client_index_to_input_queue (mp->client_index);
6924   if (q == 0)
6925     return;
6926
6927   vec_tbl = pcm->classify_table_index_by_sw_if_index[mp->type];
6928
6929   if (vec_len (vec_tbl))
6930     {
6931       for (i = 0; i < vec_len (vec_tbl); i++)
6932         {
6933           if (vec_elt (vec_tbl, i) == ~0)
6934             continue;
6935
6936           send_flow_classify_details (i, vec_elt (vec_tbl, i), q,
6937                                       mp->context);
6938         }
6939     }
6940 }
6941
6942 static void
6943 send_ipsec_spd_details (ipsec_policy_t * p, unix_shared_memory_queue_t * q,
6944                         u32 context)
6945 {
6946   vl_api_ipsec_spd_details_t *mp;
6947
6948   mp = vl_msg_api_alloc (sizeof (*mp));
6949   memset (mp, 0, sizeof (*mp));
6950   mp->_vl_msg_id = ntohs (VL_API_IPSEC_SPD_DETAILS);
6951   mp->context = context;
6952
6953   mp->spd_id = htonl (p->id);
6954   mp->priority = htonl (p->priority);
6955   mp->is_outbound = p->is_outbound;
6956   mp->is_ipv6 = p->is_ipv6;
6957   if (p->is_ipv6)
6958     {
6959       memcpy (mp->local_start_addr, &p->laddr.start.ip6, 16);
6960       memcpy (mp->local_stop_addr, &p->laddr.stop.ip6, 16);
6961       memcpy (mp->remote_start_addr, &p->raddr.start.ip6, 16);
6962       memcpy (mp->remote_stop_addr, &p->raddr.stop.ip6, 16);
6963     }
6964   else
6965     {
6966       memcpy (mp->local_start_addr, &p->laddr.start.ip4, 4);
6967       memcpy (mp->local_stop_addr, &p->laddr.stop.ip4, 4);
6968       memcpy (mp->remote_start_addr, &p->raddr.start.ip4, 4);
6969       memcpy (mp->remote_stop_addr, &p->raddr.stop.ip4, 4);
6970     }
6971   mp->local_start_port = htons (p->lport.start);
6972   mp->local_stop_port = htons (p->lport.stop);
6973   mp->remote_start_port = htons (p->rport.start);
6974   mp->remote_stop_port = htons (p->rport.stop);
6975   mp->protocol = p->protocol;
6976   mp->policy = p->policy;
6977   mp->sa_id = htonl (p->sa_id);
6978   mp->bytes = clib_host_to_net_u64 (p->counter.bytes);
6979   mp->packets = clib_host_to_net_u64 (p->counter.packets);
6980
6981   vl_msg_api_send_shmem (q, (u8 *) & mp);
6982 }
6983
6984 static void
6985 vl_api_ipsec_spd_dump_t_handler (vl_api_ipsec_spd_dump_t * mp)
6986 {
6987   unix_shared_memory_queue_t *q;
6988   ipsec_main_t *im = &ipsec_main;
6989   ipsec_policy_t *policy;
6990   ipsec_spd_t *spd;
6991   uword *p;
6992   u32 spd_index;
6993 #if IPSEC > 0
6994   q = vl_api_client_index_to_input_queue (mp->client_index);
6995   if (q == 0)
6996     return;
6997
6998   p = hash_get (im->spd_index_by_spd_id, ntohl (mp->spd_id));
6999   if (!p)
7000     return;
7001
7002   spd_index = p[0];
7003   spd = pool_elt_at_index (im->spds, spd_index);
7004
7005   /* *INDENT-OFF* */
7006   pool_foreach (policy, spd->policies,
7007   ({
7008     if (mp->sa_id == ~(0) || ntohl (mp->sa_id) == policy->sa_id)
7009       send_ipsec_spd_details (policy, q,
7010                               mp->context);}
7011     ));
7012   /* *INDENT-ON* */
7013 #else
7014   clib_warning ("unimplemented");
7015 #endif
7016 }
7017
7018 static void
7019 vl_api_feature_enable_disable_t_handler (vl_api_feature_enable_disable_t * mp)
7020 {
7021   vl_api_feature_enable_disable_reply_t *rmp;
7022   int rv = 0;
7023   u8 *arc_name, *feature_name;
7024
7025   VALIDATE_SW_IF_INDEX (mp);
7026
7027   arc_name = format (0, "%s%c", mp->arc_name, 0);
7028   feature_name = format (0, "%s%c", mp->feature_name, 0);
7029
7030   vnet_feature_registration_t *reg;
7031   reg =
7032     vnet_get_feature_reg ((const char *) arc_name,
7033                           (const char *) feature_name);
7034   if (reg == 0)
7035     rv = VNET_API_ERROR_INVALID_VALUE;
7036   else
7037     {
7038       u32 sw_if_index;
7039       clib_error_t *error = 0;
7040
7041       sw_if_index = ntohl (mp->sw_if_index);
7042       if (reg->enable_disable_cb)
7043         error = reg->enable_disable_cb (sw_if_index, mp->enable);
7044       if (!error)
7045         vnet_feature_enable_disable ((const char *) arc_name,
7046                                      (const char *) feature_name,
7047                                      sw_if_index, mp->enable, 0, 0);
7048       else
7049         {
7050           clib_error_report (error);
7051           rv = VNET_API_ERROR_CANNOT_ENABLE_DISABLE_FEATURE;
7052         }
7053     }
7054
7055   vec_free (feature_name);
7056   vec_free (arc_name);
7057
7058   BAD_SW_IF_INDEX_LABEL;
7059
7060   REPLY_MACRO (VL_API_FEATURE_ENABLE_DISABLE_REPLY);
7061 }
7062
7063 #define BOUNCE_HANDLER(nn)                                              \
7064 static void vl_api_##nn##_t_handler (                                   \
7065     vl_api_##nn##_t *mp)                                                \
7066 {                                                                       \
7067     vpe_client_registration_t *reg;                                     \
7068     vpe_api_main_t * vam = &vpe_api_main;                               \
7069     unix_shared_memory_queue_t * q;                                     \
7070                                                                         \
7071     /* One registration only... */                                      \
7072     pool_foreach(reg, vam->nn##_registrations,                          \
7073     ({                                                                  \
7074         q = vl_api_client_index_to_input_queue (reg->client_index);     \
7075         if (q) {                                                        \
7076             /*                                                          \
7077              * If the queue is stuffed, turf the msg and complain       \
7078              * It's unlikely that the intended recipient is             \
7079              * alive; avoid deadlock at all costs.                      \
7080              */                                                         \
7081             if (q->cursize == q->maxsize) {                             \
7082                 clib_warning ("ERROR: receiver queue full, drop msg");  \
7083                 vl_msg_api_free (mp);                                   \
7084                 return;                                                 \
7085             }                                                           \
7086             vl_msg_api_send_shmem (q, (u8 *)&mp);                       \
7087             return;                                                     \
7088         }                                                               \
7089     }));                                                                \
7090     vl_msg_api_free (mp);                                               \
7091 }
7092
7093 static void setup_message_id_table (api_main_t * am);
7094
7095 /*
7096  * vpe_api_hookup
7097  * Add vpe's API message handlers to the table.
7098  * vlib has alread mapped shared memory and
7099  * added the client registration handlers.
7100  * See .../open-repo/vlib/memclnt_vlib.c:memclnt_process()
7101  */
7102 static clib_error_t *
7103 vpe_api_hookup (vlib_main_t * vm)
7104 {
7105   api_main_t *am = &api_main;
7106
7107 #define _(N,n)                                                  \
7108     vl_msg_api_set_handlers(VL_API_##N, #n,                     \
7109                            vl_api_##n##_t_handler,              \
7110                            vl_noop_handler,                     \
7111                            vl_api_##n##_t_endian,               \
7112                            vl_api_##n##_t_print,                \
7113                            sizeof(vl_api_##n##_t), 1);
7114   foreach_vpe_api_msg;
7115 #undef _
7116
7117   /*
7118    * Manually register the sr tunnel add del msg, so we trace
7119    * enough bytes to capture a typical segment list
7120    */
7121   vl_msg_api_set_handlers (VL_API_SR_TUNNEL_ADD_DEL,
7122                            "sr_tunnel_add_del",
7123                            vl_api_sr_tunnel_add_del_t_handler,
7124                            vl_noop_handler,
7125                            vl_api_sr_tunnel_add_del_t_endian,
7126                            vl_api_sr_tunnel_add_del_t_print, 256, 1);
7127
7128
7129   /*
7130    * Manually register the sr policy add del msg, so we trace
7131    * enough bytes to capture a typical tunnel name list
7132    */
7133   vl_msg_api_set_handlers (VL_API_SR_POLICY_ADD_DEL,
7134                            "sr_policy_add_del",
7135                            vl_api_sr_policy_add_del_t_handler,
7136                            vl_noop_handler,
7137                            vl_api_sr_policy_add_del_t_endian,
7138                            vl_api_sr_policy_add_del_t_print, 256, 1);
7139
7140   /*
7141    * Trace space for 8 MPLS encap labels, classifier mask+match
7142    */
7143   am->api_trace_cfg[VL_API_MPLS_TUNNEL_ADD_DEL].size += 8 * sizeof (u32);
7144   am->api_trace_cfg[VL_API_CLASSIFY_ADD_DEL_TABLE].size += 5 * sizeof (u32x4);
7145   am->api_trace_cfg[VL_API_CLASSIFY_ADD_DEL_SESSION].size
7146     += 5 * sizeof (u32x4);
7147   am->api_trace_cfg[VL_API_VXLAN_ADD_DEL_TUNNEL].size += 16 * sizeof (u32);
7148
7149   /*
7150    * Thread-safe API messages
7151    */
7152   am->is_mp_safe[VL_API_IP_ADD_DEL_ROUTE] = 1;
7153   am->is_mp_safe[VL_API_GET_NODE_GRAPH] = 1;
7154
7155   /*
7156    * Set up the (msg_name, crc, message-id) table
7157    */
7158   setup_message_id_table (am);
7159
7160   return 0;
7161 }
7162
7163 VLIB_API_INIT_FUNCTION (vpe_api_hookup);
7164
7165 static clib_error_t *
7166 vpe_api_init (vlib_main_t * vm)
7167 {
7168   vpe_api_main_t *am = &vpe_api_main;
7169
7170   am->vlib_main = vm;
7171   am->vnet_main = vnet_get_main ();
7172   am->interface_events_registration_hash = hash_create (0, sizeof (uword));
7173   am->to_netconf_server_registration_hash = hash_create (0, sizeof (uword));
7174   am->from_netconf_server_registration_hash = hash_create (0, sizeof (uword));
7175   am->to_netconf_client_registration_hash = hash_create (0, sizeof (uword));
7176   am->from_netconf_client_registration_hash = hash_create (0, sizeof (uword));
7177   am->oam_events_registration_hash = hash_create (0, sizeof (uword));
7178   am->bfd_events_registration_hash = hash_create (0, sizeof (uword));
7179
7180   vl_api_init (vm);
7181   vl_set_memory_region_name ("/vpe-api");
7182   vl_enable_disable_memory_api (vm, 1 /* enable it */ );
7183
7184   return 0;
7185 }
7186
7187 VLIB_INIT_FUNCTION (vpe_api_init);
7188
7189
7190 static clib_error_t *
7191 api_segment_config (vlib_main_t * vm, unformat_input_t * input)
7192 {
7193   u8 *chroot_path;
7194   u64 baseva, size, pvt_heap_size;
7195   int uid, gid, rv;
7196   const int max_buf_size = 4096;
7197   char *s, *buf;
7198   struct passwd _pw, *pw;
7199   struct group _grp, *grp;
7200   clib_error_t *e;
7201   buf = vec_new (char, 128);
7202   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7203     {
7204       if (unformat (input, "prefix %s", &chroot_path))
7205         {
7206           vec_add1 (chroot_path, 0);
7207           vl_set_memory_root_path ((char *) chroot_path);
7208         }
7209       else if (unformat (input, "uid %d", &uid))
7210         vl_set_memory_uid (uid);
7211       else if (unformat (input, "gid %d", &gid))
7212         vl_set_memory_gid (gid);
7213       else if (unformat (input, "baseva %llx", &baseva))
7214         vl_set_global_memory_baseva (baseva);
7215       else if (unformat (input, "global-size %lldM", &size))
7216         vl_set_global_memory_size (size * (1ULL << 20));
7217       else if (unformat (input, "global-size %lldG", &size))
7218         vl_set_global_memory_size (size * (1ULL << 30));
7219       else if (unformat (input, "global-size %lld", &size))
7220         vl_set_global_memory_size (size);
7221       else if (unformat (input, "global-pvt-heap-size %lldM", &pvt_heap_size))
7222         vl_set_global_pvt_heap_size (pvt_heap_size * (1ULL << 20));
7223       else if (unformat (input, "global-pvt-heap-size size %lld",
7224                          &pvt_heap_size))
7225         vl_set_global_pvt_heap_size (pvt_heap_size);
7226       else if (unformat (input, "api-pvt-heap-size %lldM", &pvt_heap_size))
7227         vl_set_api_pvt_heap_size (pvt_heap_size * (1ULL << 20));
7228       else if (unformat (input, "api-pvt-heap-size size %lld",
7229                          &pvt_heap_size))
7230         vl_set_api_pvt_heap_size (pvt_heap_size);
7231       else if (unformat (input, "api-size %lldM", &size))
7232         vl_set_api_memory_size (size * (1ULL << 20));
7233       else if (unformat (input, "api-size %lldG", &size))
7234         vl_set_api_memory_size (size * (1ULL << 30));
7235       else if (unformat (input, "api-size %lld", &size))
7236         vl_set_api_memory_size (size);
7237       else if (unformat (input, "uid %s", &s))
7238         {
7239           /* lookup the username */
7240           pw = NULL;
7241           while (((rv =
7242                    getpwnam_r (s, &_pw, buf, vec_len (buf), &pw)) == ERANGE)
7243                  && (vec_len (buf) <= max_buf_size))
7244             {
7245               vec_resize (buf, vec_len (buf) * 2);
7246             }
7247           if (rv < 0)
7248             {
7249               e = clib_error_return_code (0, rv,
7250                                           CLIB_ERROR_ERRNO_VALID |
7251                                           CLIB_ERROR_FATAL,
7252                                           "cannot fetch username %s", s);
7253               vec_free (s);
7254               vec_free (buf);
7255               return e;
7256             }
7257           if (pw == NULL)
7258             {
7259               e =
7260                 clib_error_return_fatal (0, "username %s does not exist", s);
7261               vec_free (s);
7262               vec_free (buf);
7263               return e;
7264             }
7265           vec_free (s);
7266           vl_set_memory_uid (pw->pw_uid);
7267         }
7268       else if (unformat (input, "gid %s", &s))
7269         {
7270           /* lookup the group name */
7271           grp = NULL;
7272           while (((rv =
7273                    getgrnam_r (s, &_grp, buf, vec_len (buf), &grp)) == ERANGE)
7274                  && (vec_len (buf) <= max_buf_size))
7275             {
7276               vec_resize (buf, vec_len (buf) * 2);
7277             }
7278           if (rv != 0)
7279             {
7280               e = clib_error_return_code (0, rv,
7281                                           CLIB_ERROR_ERRNO_VALID |
7282                                           CLIB_ERROR_FATAL,
7283                                           "cannot fetch group %s", s);
7284               vec_free (s);
7285               vec_free (buf);
7286               return e;
7287             }
7288           if (grp == NULL)
7289             {
7290               e = clib_error_return_fatal (0, "group %s does not exist", s);
7291               vec_free (s);
7292               vec_free (buf);
7293               return e;
7294             }
7295           vec_free (s);
7296           vec_free (buf);
7297           vl_set_memory_gid (grp->gr_gid);
7298         }
7299       else
7300         return clib_error_return (0, "unknown input `%U'",
7301                                   format_unformat_error, input);
7302     }
7303   return 0;
7304 }
7305
7306 VLIB_EARLY_CONFIG_FUNCTION (api_segment_config, "api-segment");
7307
7308 void *
7309 get_unformat_vnet_sw_interface (void)
7310 {
7311   return (void *) &unformat_vnet_sw_interface;
7312 }
7313
7314 static u8 *
7315 format_arp_event (u8 * s, va_list * args)
7316 {
7317   vl_api_ip4_arp_event_t *event = va_arg (*args, vl_api_ip4_arp_event_t *);
7318
7319   s = format (s, "pid %d: ", event->pid);
7320   if (event->mac_ip)
7321     s = format (s, "bd mac/ip4 binding events");
7322   else
7323     s = format (s, "resolution for %U", format_ip4_address, &event->address);
7324   return s;
7325 }
7326
7327 static u8 *
7328 format_nd_event (u8 * s, va_list * args)
7329 {
7330   vl_api_ip6_nd_event_t *event = va_arg (*args, vl_api_ip6_nd_event_t *);
7331
7332   s = format (s, "pid %d: ", event->pid);
7333   if (event->mac_ip)
7334     s = format (s, "bd mac/ip6 binding events");
7335   else
7336     s = format (s, "resolution for %U", format_ip6_address, event->address);
7337   return s;
7338 }
7339
7340 static clib_error_t *
7341 show_ip_arp_nd_events_fn (vlib_main_t * vm,
7342                           unformat_input_t * input, vlib_cli_command_t * cmd)
7343 {
7344   vpe_api_main_t *am = &vpe_api_main;
7345   vl_api_ip4_arp_event_t *arp_event;
7346   vl_api_ip6_nd_event_t *nd_event;
7347
7348   if ((pool_elts (am->arp_events) == 0) && (pool_elts (am->nd_events) == 0))
7349     {
7350       vlib_cli_output (vm, "No active arp or nd event registrations");
7351       return 0;
7352     }
7353
7354   /* *INDENT-OFF* */
7355   pool_foreach (arp_event, am->arp_events,
7356   ({
7357     vlib_cli_output (vm, "%U", format_arp_event, arp_event);
7358   }));
7359
7360   pool_foreach (nd_event, am->nd_events,
7361   ({
7362     vlib_cli_output (vm, "%U", format_nd_event, nd_event);
7363   }));
7364   /* *INDENT-ON* */
7365
7366   return 0;
7367 }
7368
7369 /* *INDENT-OFF* */
7370 VLIB_CLI_COMMAND (show_ip_arp_nd_events, static) = {
7371   .path = "show arp-nd-event registrations",
7372   .function = show_ip_arp_nd_events_fn,
7373   .short_help = "Show ip4 arp and ip6 nd event registrations",
7374 };
7375 /* *INDENT-ON* */
7376
7377 #define vl_msg_name_crc_list
7378 #include <vpp-api/vpe_all_api_h.h>
7379 #undef vl_msg_name_crc_list
7380
7381 static void
7382 setup_message_id_table (api_main_t * am)
7383 {
7384 #define _(id,n,crc) vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id);
7385   foreach_vl_msg_name_crc_memclnt;
7386   foreach_vl_msg_name_crc_vpe;
7387 #undef _
7388 }
7389
7390
7391 /*
7392  * fd.io coding-style-patch-verification: ON
7393  *
7394  * Local Variables:
7395  * eval: (c-set-style "gnu")
7396  * End:
7397  */