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