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