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