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