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