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