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