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