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