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