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