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