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