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