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