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