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