VPP-148 added bvi_mac flag to l2fib_add_del api call similarly to 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     u32 bvi_mac;
1656     uword * p;
1657
1658     mac = mp->mac;
1659
1660     p = hash_get (bdm->bd_index_by_bd_id, bd_id);
1661     if (!p) {
1662         rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1663         goto bad_sw_if_index;
1664     }
1665     bd_index = p[0];
1666
1667     if (mp->is_add) {
1668         VALIDATE_SW_IF_INDEX(mp);
1669         if (vec_len(l2im->configs) <= sw_if_index) {
1670             rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
1671             goto bad_sw_if_index;
1672         } else {
1673             l2_input_config_t * config;
1674             config = vec_elt_at_index(l2im->configs, sw_if_index);
1675             if (config->bridge == 0) {
1676                 rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
1677                 goto bad_sw_if_index;
1678             }
1679         }
1680         static_mac = mp->static_mac ? 1 : 0;
1681         filter_mac = mp->filter_mac ? 1 : 0;
1682     bvi_mac = mp->bvi_mac ? 1 : 0;
1683         l2fib_add_entry(mac, bd_index, sw_if_index, static_mac, filter_mac,
1684                         bvi_mac);
1685     } else {
1686         l2fib_del_entry(mac, bd_index);
1687     }
1688
1689     BAD_SW_IF_INDEX_LABEL;
1690
1691     REPLY_MACRO(VL_API_L2FIB_ADD_DEL_REPLY);
1692 }
1693
1694 static void
1695 vl_api_l2_flags_t_handler (
1696     vl_api_l2_flags_t *mp)
1697 {
1698     vl_api_l2_flags_reply_t * rmp;
1699     int rv = 0;
1700     u32 sw_if_index = ntohl(mp->sw_if_index);
1701     u32 flags = ntohl(mp->feature_bitmap);
1702     u32 rbm = 0;
1703
1704     VALIDATE_SW_IF_INDEX(mp);
1705
1706 #define _(a,b) \
1707     if (flags & L2INPUT_FEAT_ ## a) \
1708         rbm = l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_ ## a, mp->is_set);
1709     foreach_l2input_feat;
1710 #undef _
1711
1712     BAD_SW_IF_INDEX_LABEL;
1713
1714     REPLY_MACRO2(VL_API_L2_FLAGS_REPLY, rmp->resulting_feature_bitmap = ntohl(rbm));
1715 }
1716
1717 static void
1718 vl_api_bridge_flags_t_handler (
1719     vl_api_bridge_flags_t *mp)
1720 {
1721     vlib_main_t *vm  = vlib_get_main();
1722     bd_main_t * bdm = &bd_main;
1723     vl_api_bridge_flags_reply_t * rmp;
1724     int rv = 0;
1725     u32 bd_id = ntohl(mp->bd_id);
1726     u32 bd_index;
1727     u32 flags = ntohl(mp->feature_bitmap);
1728     uword * p;
1729
1730     p = hash_get (bdm->bd_index_by_bd_id, bd_id);
1731     if (p == 0) {
1732         rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1733         goto out;
1734     }
1735
1736     bd_index = p[0];
1737
1738     bd_set_flags(vm, bd_index, flags, mp->is_set);
1739
1740 out:
1741     REPLY_MACRO2(VL_API_BRIDGE_FLAGS_REPLY,
1742                  rmp->resulting_feature_bitmap = ntohl(flags));
1743 }
1744
1745 static void
1746 vl_api_bd_ip_mac_add_del_t_handler (
1747     vl_api_bd_ip_mac_add_del_t *mp)
1748 {
1749     bd_main_t * bdm = &bd_main;
1750     vl_api_bd_ip_mac_add_del_reply_t * rmp;
1751     int rv = 0;
1752     u32 bd_id = ntohl(mp->bd_id);
1753     u32 bd_index;
1754     uword * p;
1755
1756     p = hash_get (bdm->bd_index_by_bd_id, bd_id);
1757     if (p == 0) {
1758         rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1759         goto out;
1760     }
1761
1762     bd_index = p[0];
1763     if (bd_add_del_ip_mac(bd_index,  mp->ip_address,
1764                           mp->mac_address, mp->is_ipv6, mp->is_add))
1765         rv = VNET_API_ERROR_UNSPECIFIED;
1766
1767 out:
1768     REPLY_MACRO(VL_API_BD_IP_MAC_ADD_DEL_REPLY);
1769 }
1770
1771 static void
1772 vl_api_tap_connect_t_handler (vl_api_tap_connect_t *mp, vlib_main_t *vm)
1773 {
1774     int rv;
1775     vl_api_tap_connect_reply_t * rmp;
1776     unix_shared_memory_queue_t * q;
1777     u32 sw_if_index = (u32)~0;
1778
1779     rv = vnet_tap_connect_renumber (vm, mp->tap_name,
1780                            mp->use_random_mac ? 0 : mp->mac_address,
1781                            &sw_if_index, mp->renumber,
1782                            ntohl(mp->custom_dev_instance));
1783
1784     q = vl_api_client_index_to_input_queue (mp->client_index);
1785     if (!q)
1786         return;
1787
1788     rmp = vl_msg_api_alloc (sizeof (*rmp));
1789     rmp->_vl_msg_id = ntohs(VL_API_TAP_CONNECT_REPLY);
1790     rmp->context = mp->context;
1791     rmp->retval = ntohl(rv);
1792     rmp->sw_if_index = ntohl(sw_if_index);
1793
1794     vl_msg_api_send_shmem (q, (u8 *)&rmp);
1795 }
1796
1797 static void
1798 vl_api_tap_modify_t_handler (vl_api_tap_modify_t *mp, vlib_main_t *vm)
1799 {
1800     int rv;
1801     vl_api_tap_modify_reply_t * rmp;
1802     unix_shared_memory_queue_t * q;
1803     u32 sw_if_index = (u32)~0;
1804
1805     rv = vnet_tap_modify (vm, ntohl(mp->sw_if_index), mp->tap_name,
1806                            mp->use_random_mac ? 0 : mp->mac_address,
1807                            &sw_if_index, mp->renumber,
1808                            ntohl(mp->custom_dev_instance));
1809
1810     q = vl_api_client_index_to_input_queue (mp->client_index);
1811     if (!q)
1812         return;
1813
1814     rmp = vl_msg_api_alloc (sizeof (*rmp));
1815     rmp->_vl_msg_id = ntohs(VL_API_TAP_MODIFY_REPLY);
1816     rmp->context = mp->context;
1817     rmp->retval = ntohl(rv);
1818     rmp->sw_if_index = ntohl(sw_if_index);
1819
1820     vl_msg_api_send_shmem (q, (u8 *)&rmp);
1821 }
1822
1823 static void
1824 vl_api_tap_delete_t_handler (vl_api_tap_delete_t *mp, vlib_main_t *vm)
1825 {
1826     int rv;
1827     vpe_api_main_t * vam = &vpe_api_main;
1828     vl_api_tap_delete_reply_t * rmp;
1829     unix_shared_memory_queue_t * q;
1830     u32 sw_if_index = ntohl(mp->sw_if_index);
1831
1832     rv = vnet_tap_delete (vm, sw_if_index);
1833
1834     q = vl_api_client_index_to_input_queue (mp->client_index);
1835     if (!q)
1836         return;
1837
1838     rmp = vl_msg_api_alloc (sizeof (*rmp));
1839     rmp->_vl_msg_id = ntohs(VL_API_TAP_DELETE_REPLY);
1840     rmp->context = mp->context;
1841     rmp->retval = ntohl(rv);
1842
1843     vl_msg_api_send_shmem (q, (u8 *)&rmp);
1844
1845     if (!rv)
1846         send_sw_interface_flags_deleted (vam, q, sw_if_index);
1847 }
1848
1849 static void
1850 vl_api_create_vlan_subif_t_handler (vl_api_create_vlan_subif_t * mp)
1851 {
1852     vl_api_create_vlan_subif_reply_t * rmp;
1853     vnet_main_t * vnm = vnet_get_main();
1854     u32 hw_if_index, sw_if_index = (u32)~0;
1855     vnet_hw_interface_t * hi;
1856     int rv = 0;
1857     u32 id;
1858     vnet_sw_interface_t template;
1859     uword * p;
1860     vnet_interface_main_t * im = &vnm->interface_main;
1861     u64 sup_and_sub_key;
1862     u64 * kp;
1863     unix_shared_memory_queue_t * q;
1864     clib_error_t * error;
1865
1866     VALIDATE_SW_IF_INDEX(mp);
1867
1868     hw_if_index = ntohl(mp->sw_if_index);
1869     hi = vnet_get_hw_interface (vnm, hw_if_index);
1870
1871     id = ntohl(mp->vlan_id);
1872     if (id == 0 || id > 4095) {
1873         rv = VNET_API_ERROR_INVALID_VLAN;
1874         goto out;
1875     }
1876
1877     sup_and_sub_key = ((u64)(hi->sw_if_index) << 32) | (u64) id;
1878
1879     p = hash_get_mem (im->sw_if_index_by_sup_and_sub, &sup_and_sub_key);
1880     if (p) {
1881         rv = VNET_API_ERROR_VLAN_ALREADY_EXISTS;
1882         goto out;
1883     }
1884
1885     kp = clib_mem_alloc (sizeof (*kp));
1886     *kp = sup_and_sub_key;
1887
1888     memset (&template, 0, sizeof (template));
1889     template.type = VNET_SW_INTERFACE_TYPE_SUB;
1890     template.sup_sw_if_index = hi->sw_if_index;
1891     template.sub.id = id;
1892     template.sub.eth.raw_flags = 0;
1893     template.sub.eth.flags.one_tag = 1;
1894     template.sub.eth.outer_vlan_id = id;
1895     template.sub.eth.flags.exact_match = 1;
1896
1897     error = vnet_create_sw_interface (vnm, &template, &sw_if_index);
1898     if (error) {
1899         clib_error_report(error);
1900         rv = VNET_API_ERROR_INVALID_REGISTRATION;
1901         goto out;
1902     }
1903     hash_set (hi->sub_interface_sw_if_index_by_id, id, sw_if_index);
1904     hash_set_mem (im->sw_if_index_by_sup_and_sub, kp, sw_if_index);
1905
1906     BAD_SW_IF_INDEX_LABEL;
1907
1908 out:
1909     q = vl_api_client_index_to_input_queue (mp->client_index);
1910     if (!q)
1911         return;
1912
1913     rmp = vl_msg_api_alloc (sizeof (*rmp));
1914     rmp->_vl_msg_id = ntohs(VL_API_CREATE_VLAN_SUBIF_REPLY);
1915     rmp->context = mp->context;
1916     rmp->retval = ntohl(rv);
1917     rmp->sw_if_index = ntohl(sw_if_index);
1918     vl_msg_api_send_shmem (q, (u8 *)&rmp);
1919 }
1920
1921 static void
1922 vl_api_create_subif_t_handler (vl_api_create_subif_t * mp)
1923 {
1924     vl_api_create_subif_reply_t * rmp;
1925     vnet_main_t * vnm = vnet_get_main();
1926     u32 sw_if_index = ~0;
1927     int rv = 0;
1928     u32 sub_id;
1929     vnet_sw_interface_t *si;
1930     vnet_hw_interface_t *hi;
1931     vnet_sw_interface_t template;
1932     uword * p;
1933     vnet_interface_main_t * im = &vnm->interface_main;
1934     u64 sup_and_sub_key;
1935     u64 * kp;
1936     clib_error_t * error;
1937
1938     VALIDATE_SW_IF_INDEX(mp);
1939
1940     si = vnet_get_sup_sw_interface (vnm, ntohl(mp->sw_if_index));
1941     hi = vnet_get_sup_hw_interface (vnm, ntohl(mp->sw_if_index));
1942
1943     if (hi->bond_info == VNET_HW_INTERFACE_BOND_INFO_SLAVE) {
1944          rv = VNET_API_ERROR_BOND_SLAVE_NOT_ALLOWED;
1945         goto out;
1946     }
1947
1948     sw_if_index = si->sw_if_index;
1949     sub_id = ntohl(mp->sub_id);
1950
1951     sup_and_sub_key = ((u64)(sw_if_index) << 32) | (u64) sub_id;
1952
1953     p = hash_get_mem (im->sw_if_index_by_sup_and_sub, &sup_and_sub_key);
1954     if (p) {
1955         if (CLIB_DEBUG > 0)
1956             clib_warning ("sup sw_if_index %d, sub id %d already exists\n",
1957                           sw_if_index, sub_id);
1958         rv = VNET_API_ERROR_SUBIF_ALREADY_EXISTS;
1959         goto out;
1960     }
1961
1962     kp = clib_mem_alloc (sizeof (*kp));
1963     *kp = sup_and_sub_key;
1964
1965     memset (&template, 0, sizeof (template));
1966     template.type = VNET_SW_INTERFACE_TYPE_SUB;
1967     template.sup_sw_if_index = sw_if_index;
1968     template.sub.id = sub_id;
1969     template.sub.eth.flags.no_tags = mp->no_tags;
1970     template.sub.eth.flags.one_tag = mp->one_tag;
1971     template.sub.eth.flags.two_tags = mp->two_tags;
1972     template.sub.eth.flags.dot1ad = mp->dot1ad;
1973     template.sub.eth.flags.exact_match = mp->exact_match;
1974     template.sub.eth.flags.default_sub = mp->default_sub;
1975     template.sub.eth.flags.outer_vlan_id_any = mp->outer_vlan_id_any;
1976     template.sub.eth.flags.inner_vlan_id_any = mp->inner_vlan_id_any;
1977     template.sub.eth.outer_vlan_id = ntohs(mp->outer_vlan_id);
1978     template.sub.eth.inner_vlan_id = ntohs(mp->inner_vlan_id);
1979
1980     error = vnet_create_sw_interface (vnm, &template, &sw_if_index);
1981     if (error) {
1982         clib_error_report (error);
1983         rv = VNET_API_ERROR_SUBIF_CREATE_FAILED;
1984         goto out;
1985     }
1986
1987     hash_set (hi->sub_interface_sw_if_index_by_id, sub_id, sw_if_index);
1988     hash_set_mem (im->sw_if_index_by_sup_and_sub, kp, sw_if_index);
1989
1990     BAD_SW_IF_INDEX_LABEL;
1991
1992 out:
1993
1994     REPLY_MACRO2(VL_API_CREATE_SUBIF_REPLY,
1995     ({
1996         rmp->sw_if_index = ntohl(sw_if_index);
1997     }));
1998 }
1999
2000 static void
2001 vl_api_mpls_gre_add_del_tunnel_t_handler (vl_api_mpls_gre_add_del_tunnel_t *mp)
2002 {
2003     vl_api_mpls_gre_add_del_tunnel_reply_t * rmp;
2004     int rv = 0;
2005     stats_main_t * sm = &stats_main;
2006     u32 tunnel_sw_if_index = ~0;
2007
2008     dslock (sm, 1 /* release hint */, 5 /* tag */);
2009
2010     rv = vnet_mpls_gre_add_del_tunnel ((ip4_address_t *)(mp->src_address),
2011                                        (ip4_address_t *)(mp->dst_address),
2012                                        (ip4_address_t *)(mp->intfc_address),
2013                                        (u32)(mp->intfc_address_length),
2014                                        ntohl(mp->inner_vrf_id),
2015                                        ntohl(mp->outer_vrf_id),
2016                                        &tunnel_sw_if_index,
2017                                        mp->l2_only,
2018                                        mp->is_add);
2019     dsunlock (sm);
2020
2021     REPLY_MACRO2(VL_API_MPLS_GRE_ADD_DEL_TUNNEL_REPLY,
2022     ({
2023         rmp->tunnel_sw_if_index = ntohl(tunnel_sw_if_index);
2024     }));
2025 }
2026
2027 static void
2028 vl_api_mpls_ethernet_add_del_tunnel_t_handler
2029 (vl_api_mpls_ethernet_add_del_tunnel_t *mp)
2030 {
2031     vl_api_mpls_ethernet_add_del_tunnel_reply_t * rmp;
2032     int rv = 0;
2033     stats_main_t * sm = &stats_main;
2034     u32 tunnel_sw_if_index;
2035
2036     dslock (sm, 1 /* release hint */, 5 /* tag */);
2037
2038     rv = vnet_mpls_ethernet_add_del_tunnel
2039         (mp->dst_mac_address, (ip4_address_t *)(mp->adj_address),
2040          (u32)(mp->adj_address_length), ntohl(mp->vrf_id),
2041          ntohl(mp->tx_sw_if_index),
2042          &tunnel_sw_if_index,
2043          mp->l2_only,
2044          mp->is_add);
2045
2046     dsunlock (sm);
2047
2048     REPLY_MACRO2(VL_API_MPLS_ETHERNET_ADD_DEL_TUNNEL_REPLY,
2049     ({
2050         rmp->tunnel_sw_if_index = ntohl(tunnel_sw_if_index);
2051     }));
2052 }
2053
2054 /*
2055  * This piece of misery brought to you because the control-plane
2056  * can't figure out the tx interface + dst-mac address all by itself
2057  */
2058 static int mpls_ethernet_add_del_tunnel_2_t_handler
2059 (vl_api_mpls_ethernet_add_del_tunnel_2_t *mp)
2060 {
2061     pending_route_t * pr;
2062     vl_api_mpls_ethernet_add_del_tunnel_2_t *pme;
2063     vnet_main_t * vnm = vnet_get_main();
2064     vlib_main_t * vm = vlib_get_main();
2065     stats_main_t * sm = &stats_main;
2066     vpe_api_main_t * vam = &vpe_api_main;
2067     u32 inner_fib_index, outer_fib_index;
2068     ip4_main_t * im = &ip4_main;
2069     ip_lookup_main_t * lm = &im->lookup_main;
2070     ip_adjacency_t * adj = 0;
2071     u32 lookup_result;
2072     u32 tx_sw_if_index;
2073     u8 * dst_mac_address;
2074     clib_error_t * e;
2075     uword * p;
2076     int rv;
2077     u32 tunnel_sw_if_index;
2078
2079     p = hash_get (im->fib_index_by_table_id, ntohl(mp->outer_vrf_id));
2080     if (!p)
2081         return VNET_API_ERROR_NO_SUCH_FIB;
2082     else
2083         outer_fib_index = p[0];
2084
2085
2086     p = hash_get (im->fib_index_by_table_id, ntohl(mp->inner_vrf_id));
2087     if (!p)
2088         return VNET_API_ERROR_NO_SUCH_INNER_FIB;
2089     else
2090         inner_fib_index = p[0];
2091
2092     if (inner_fib_index == outer_fib_index)
2093         return VNET_API_ERROR_INVALID_VALUE;
2094
2095     lookup_result = ip4_fib_lookup_with_table
2096         (im, outer_fib_index,
2097          (ip4_address_t *)mp->next_hop_ip4_address_in_outer_vrf,
2098          1 /* disable default route */);
2099
2100     adj = ip_get_adjacency (lm, lookup_result);
2101     tx_sw_if_index = adj->rewrite_header.sw_if_index;
2102
2103     if (mp->is_add && mp->resolve_if_needed) {
2104         if (adj->lookup_next_index == IP_LOOKUP_NEXT_ARP) {
2105             pool_get (vam->pending_routes, pr);
2106             pr->resolve_type = RESOLVE_MPLS_ETHERNET_ADD_DEL;
2107             pme = &pr->t;
2108             clib_memcpy (pme, mp, sizeof (*pme));
2109             /* recursion block, "just in case" */
2110             pme->resolve_if_needed = 0;
2111             pme->resolve_attempts = ntohl(mp->resolve_attempts);
2112             pme->resolve_opaque = tx_sw_if_index;
2113             vnet_register_ip4_arp_resolution_event
2114                 (vnm,
2115                  (ip4_address_t *)&(pme->next_hop_ip4_address_in_outer_vrf),
2116                  vpe_resolver_process_node.index,
2117                  RESOLUTION_EVENT, pr - vam->pending_routes);
2118
2119             vlib_process_signal_event
2120                 (vm, vpe_resolver_process_node.index,
2121                  RESOLUTION_PENDING_EVENT, 0 /* data */);
2122
2123             /* The interface may be down, etc. */
2124             e = ip4_probe_neighbor
2125                 (vm, (ip4_address_t *)&(mp->next_hop_ip4_address_in_outer_vrf),
2126                  tx_sw_if_index);
2127
2128             if (e)
2129                 clib_error_report(e);
2130
2131             return VNET_API_ERROR_IN_PROGRESS;
2132         }
2133     }
2134
2135     if (adj->lookup_next_index != IP_LOOKUP_NEXT_REWRITE)
2136         return VNET_API_ERROR_NEXT_HOP_NOT_IN_FIB;
2137
2138     dst_mac_address =
2139         vnet_rewrite_get_data_internal
2140         (&adj->rewrite_header, sizeof (adj->rewrite_data));
2141
2142     dslock (sm, 1 /* release hint */, 10 /* tag */);
2143
2144     rv = vnet_mpls_ethernet_add_del_tunnel
2145         (dst_mac_address, (ip4_address_t *)(mp->adj_address),
2146          (u32)(mp->adj_address_length), ntohl(mp->inner_vrf_id),
2147          tx_sw_if_index, &tunnel_sw_if_index, mp->l2_only, mp->is_add);
2148
2149     dsunlock (sm);
2150
2151     return rv;
2152 }
2153
2154 static void
2155 vl_api_mpls_ethernet_add_del_tunnel_2_t_handler
2156 (vl_api_mpls_ethernet_add_del_tunnel_2_t *mp)
2157 {
2158     vl_api_mpls_ethernet_add_del_tunnel_reply_t * rmp;
2159     int rv = 0;
2160
2161     rv = mpls_ethernet_add_del_tunnel_2_t_handler (mp);
2162
2163     REPLY_MACRO(VL_API_MPLS_ETHERNET_ADD_DEL_TUNNEL_2_REPLY);
2164 }
2165
2166
2167 static void
2168 vl_api_mpls_add_del_encap_t_handler (vl_api_mpls_add_del_encap_t *mp)
2169 {
2170     vl_api_mpls_add_del_encap_reply_t * rmp;
2171     int rv;
2172     static u32 * labels;
2173     int i;
2174
2175     vec_reset_length (labels);
2176
2177     for (i = 0; i < mp->nlabels; i++)
2178         vec_add1 (labels, ntohl(mp->labels[i]));
2179
2180     /* $$$$ fixme */
2181     rv = vnet_mpls_add_del_encap ((ip4_address_t *)mp->dst_address,
2182                                   ntohl(mp->vrf_id), labels,
2183                                   ~0 /* policy_tunnel_index */,
2184                                   0 /* no_dst_hash */,
2185                                   0 /* indexp */,
2186                                   mp->is_add);
2187
2188     REPLY_MACRO(VL_API_MPLS_ADD_DEL_ENCAP_REPLY);
2189 }
2190
2191 static void
2192 vl_api_mpls_add_del_decap_t_handler
2193 (vl_api_mpls_add_del_decap_t *mp)
2194 {
2195     vl_api_mpls_add_del_decap_reply_t * rmp;
2196     int rv;
2197
2198     rv = vnet_mpls_add_del_decap (ntohl(mp->rx_vrf_id), ntohl(mp->tx_vrf_id),
2199                                   ntohl(mp->label), ntohl(mp->next_index),
2200                                   mp->s_bit, mp->is_add);
2201
2202     REPLY_MACRO(VL_API_MPLS_ADD_DEL_DECAP_REPLY);
2203 }
2204
2205 static void
2206 vl_api_proxy_arp_add_del_t_handler (vl_api_proxy_arp_add_del_t *mp)
2207 {
2208     vl_api_proxy_arp_add_del_reply_t * rmp;
2209     u32 fib_index;
2210     int rv;
2211     ip4_main_t * im = &ip4_main;
2212     stats_main_t * sm = &stats_main;
2213     int vnet_proxy_arp_add_del (ip4_address_t *lo_addr,
2214                                 ip4_address_t *hi_addr,
2215                                 u32 fib_index, int is_del);
2216     uword * p;
2217
2218     dslock (sm, 1 /* release hint */, 6 /* tag */);
2219
2220     p = hash_get (im->fib_index_by_table_id, ntohl(mp->vrf_id));
2221
2222     if (! p) {
2223         rv = VNET_API_ERROR_NO_SUCH_FIB;
2224         goto out;
2225     }
2226
2227     fib_index = p[0];
2228
2229     rv = vnet_proxy_arp_add_del ((ip4_address_t *)mp->low_address,
2230                                  (ip4_address_t *)mp->hi_address,
2231                                  fib_index, mp->is_add == 0);
2232
2233 out:
2234     dsunlock (sm);
2235     REPLY_MACRO(VL_API_PROXY_ARP_ADD_DEL_REPLY);
2236 }
2237
2238 static void
2239 vl_api_proxy_arp_intfc_enable_disable_t_handler
2240 (vl_api_proxy_arp_intfc_enable_disable_t *mp)
2241 {
2242     int rv = 0;
2243     vnet_main_t * vnm = vnet_get_main();
2244     vl_api_proxy_arp_intfc_enable_disable_reply_t *rmp;
2245     vnet_sw_interface_t * si;
2246     u32 sw_if_index;
2247
2248     VALIDATE_SW_IF_INDEX(mp);
2249
2250     sw_if_index = ntohl(mp->sw_if_index);
2251
2252     if (pool_is_free_index (vnm->interface_main.sw_interfaces,
2253                             sw_if_index)) {
2254         rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
2255         goto out;
2256     }
2257
2258     si = vnet_get_sw_interface (vnm, sw_if_index);
2259
2260     ASSERT(si);
2261
2262     if (mp->enable_disable)
2263         si->flags |= VNET_SW_INTERFACE_FLAG_PROXY_ARP;
2264     else
2265         si->flags &= ~VNET_SW_INTERFACE_FLAG_PROXY_ARP;
2266
2267     BAD_SW_IF_INDEX_LABEL;
2268
2269     out:
2270     REPLY_MACRO(VL_API_PROXY_ARP_INTFC_ENABLE_DISABLE_REPLY);
2271 }
2272
2273 static void
2274 vl_api_ip_neighbor_add_del_t_handler (vl_api_ip_neighbor_add_del_t *mp, vlib_main_t * vm)
2275 {
2276     vl_api_ip_neighbor_add_del_reply_t * rmp;
2277     vnet_main_t * vnm = vnet_get_main();
2278     u32 fib_index;
2279     int rv=0;
2280     stats_main_t * sm = &stats_main;
2281
2282     VALIDATE_SW_IF_INDEX(mp);
2283
2284     dslock (sm, 1 /* release hint */, 7 /* tag */);
2285
2286     if (mp->is_ipv6) {
2287         if (mp->is_add)
2288             rv = vnet_set_ip6_ethernet_neighbor
2289                 (vm, ntohl(mp->sw_if_index),
2290                  (ip6_address_t *)(mp->dst_address),
2291                  mp->mac_address, sizeof (mp->mac_address), mp->is_static);
2292         else
2293             rv = vnet_unset_ip6_ethernet_neighbor
2294                 (vm, ntohl(mp->sw_if_index),
2295                  (ip6_address_t *)(mp->dst_address),
2296                  mp->mac_address, sizeof(mp->mac_address));
2297     } else {
2298         ip4_main_t * im = &ip4_main;
2299         ip_lookup_main_t * lm = &im->lookup_main;
2300         ethernet_arp_ip4_over_ethernet_address_t a;
2301         u32 ai;
2302         ip_adjacency_t *nh_adj;
2303
2304         uword * p = hash_get (im->fib_index_by_table_id, ntohl(mp->vrf_id));
2305         if (! p) {
2306             rv = VNET_API_ERROR_NO_SUCH_FIB;
2307             goto out;
2308         }
2309         fib_index = p[0];
2310
2311         /*
2312          * Unfortunately, folks have a penchant for
2313          * adding interface addresses to the ARP cache, and
2314          * wondering why the forwarder eventually ASSERTs...
2315          */
2316         ai = ip4_fib_lookup_with_table
2317             (im, fib_index, (ip4_address_t *)(mp->dst_address),
2318              1 /* disable default route */);
2319
2320         if (ai != 0) {
2321             nh_adj = ip_get_adjacency (lm, ai);
2322             /* Never allow manipulation of a local adj! */
2323             if (nh_adj->lookup_next_index == IP_LOOKUP_NEXT_LOCAL) {
2324                 clib_warning("%U matches local adj",
2325                              format_ip4_address,
2326                              (ip4_address_t *)(mp->dst_address));
2327                 rv = VNET_API_ERROR_ADDRESS_MATCHES_INTERFACE_ADDRESS;
2328                 goto out;
2329             }
2330         }
2331
2332         clib_memcpy (&a.ethernet, mp->mac_address, 6);
2333         clib_memcpy (&a.ip4, mp->dst_address, 4);
2334
2335         if (mp->is_add)
2336             rv = vnet_arp_set_ip4_over_ethernet (vnm, ntohl(mp->sw_if_index),
2337                                                  fib_index, &a, mp->is_static);
2338         else
2339             rv = vnet_arp_unset_ip4_over_ethernet (vnm, ntohl(mp->sw_if_index),
2340                                                    fib_index, &a);
2341     }
2342
2343     BAD_SW_IF_INDEX_LABEL;
2344     out:
2345     dsunlock (sm);
2346     REPLY_MACRO(VL_API_IP_NEIGHBOR_ADD_DEL_REPLY);
2347 }
2348
2349 static void
2350 vl_api_is_address_reachable_t_handler (vl_api_is_address_reachable_t *mp)
2351 {
2352 #if 0
2353     vpe_main_t *rm = &vpe_main;
2354     ip4_main_t *im4 = &ip4_main;
2355     ip6_main_t *im6 = &ip6_main;
2356     ip_lookup_main_t * lm;
2357     union {
2358         ip4_address_t ip4;
2359         ip6_address_t ip6;
2360     } addr;
2361     u32 adj_index, sw_if_index;
2362     vl_api_is_address_reachable_t *rmp;
2363     ip_adjacency_t * adj;
2364     unix_shared_memory_queue_t *q;
2365
2366     q = vl_api_client_index_to_input_queue (mp->client_index);
2367     if (!q) {
2368         increment_missing_api_client_counter (rm->vlib_main);
2369         return;
2370     }
2371
2372     rmp = vl_msg_api_alloc (sizeof (*rmp));
2373     clib_memcpy (rmp, mp, sizeof (*rmp));
2374
2375     sw_if_index = mp->next_hop_sw_if_index;
2376     clib_memcpy (&addr, mp->address, sizeof (addr));
2377     if (mp->is_ipv6) {
2378         lm = &im6->lookup_main;
2379         adj_index =
2380             ip6_fib_lookup (im6, sw_if_index, &addr.ip6);
2381     } else {
2382         lm = &im4->lookup_main;
2383         adj_index =
2384             ip4_fib_lookup (im4, sw_if_index, &addr.ip4);
2385     }
2386     if (adj_index == ~0) {
2387         rmp->is_error = 1;
2388         goto send;
2389     }
2390     adj = ip_get_adjacency (lm, adj_index);
2391
2392     if (adj->lookup_next_index == IP_LOOKUP_NEXT_REWRITE
2393         && adj->rewrite_header.sw_if_index == sw_if_index) {
2394         rmp->is_known = 1;
2395     } else {
2396         if (adj->lookup_next_index == IP_LOOKUP_NEXT_ARP
2397             && adj->rewrite_header.sw_if_index == sw_if_index) {
2398             if (mp->is_ipv6)
2399                 ip6_probe_neighbor (rm->vlib_main, &addr.ip6, sw_if_index);
2400             else
2401                 ip4_probe_neighbor (rm->vlib_main, &addr.ip4, sw_if_index);
2402         } else if (adj->lookup_next_index == IP_LOOKUP_NEXT_DROP) {
2403             rmp->is_known = 1;
2404             goto send;
2405         }
2406         rmp->is_known = 0;
2407     }
2408
2409 send:
2410     vl_msg_api_send_shmem (q, (u8 *)&rmp);
2411 #endif
2412 }
2413
2414 static void vl_api_sw_interface_details_t_handler (
2415     vl_api_sw_interface_details_t * mp)
2416 {
2417     clib_warning ("BUG");
2418 }
2419
2420 static void vl_api_sw_interface_set_flags_t_handler (
2421     vl_api_sw_interface_set_flags_t * mp)
2422 {
2423    vl_api_sw_interface_set_flags_reply_t *rmp;
2424    vnet_main_t * vnm = vnet_get_main();
2425    int rv = 0;
2426    clib_error_t * error;
2427    u16 flags;
2428
2429    VALIDATE_SW_IF_INDEX(mp);
2430
2431    flags = mp->admin_up_down ? VNET_SW_INTERFACE_FLAG_ADMIN_UP : 0;
2432
2433    error = vnet_sw_interface_set_flags (vnm,
2434                                         ntohl(mp->sw_if_index),
2435                                         flags);
2436    if (error) {
2437        rv = -1;
2438        clib_error_report (error);
2439    }
2440
2441    BAD_SW_IF_INDEX_LABEL;
2442    REPLY_MACRO(VL_API_SW_INTERFACE_SET_FLAGS_REPLY);
2443 }
2444
2445 static void vl_api_sw_interface_clear_stats_t_handler (
2446     vl_api_sw_interface_clear_stats_t * mp)
2447 {
2448    vl_api_sw_interface_clear_stats_reply_t *rmp;
2449
2450    vnet_main_t * vnm = vnet_get_main();
2451    vnet_interface_main_t * im = &vnm->interface_main;
2452    vlib_simple_counter_main_t * sm;
2453    vlib_combined_counter_main_t * cm;
2454    static vnet_main_t ** my_vnet_mains;
2455    int i, j, n_counters;
2456
2457    int rv = 0;
2458
2459    vec_reset_length (my_vnet_mains);
2460
2461    for (i = 0; i < vec_len (vnet_mains); i++)
2462      {
2463        if (vnet_mains[i])
2464          vec_add1 (my_vnet_mains, vnet_mains[i]);
2465      }
2466
2467    if (vec_len (vnet_mains) == 0)
2468      vec_add1 (my_vnet_mains, vnm);
2469
2470    n_counters = vec_len (im->combined_sw_if_counters);
2471
2472    for (j = 0; j < n_counters; j++)
2473      {
2474        for (i = 0; i < vec_len(my_vnet_mains); i++)
2475          {
2476            im = &my_vnet_mains[i]->interface_main;
2477            cm = im->combined_sw_if_counters + j;
2478            if (mp->sw_if_index == (u32)~0)
2479              vlib_clear_combined_counters (cm);
2480            else
2481              vlib_zero_combined_counter (cm, ntohl(mp->sw_if_index));
2482          }
2483      }
2484
2485    n_counters = vec_len (im->sw_if_counters);
2486
2487    for (j = 0; j < n_counters; j++)
2488      {
2489        for (i = 0; i < vec_len(my_vnet_mains); i++)
2490          {
2491            im = &my_vnet_mains[i]->interface_main;
2492            sm = im->sw_if_counters + j;
2493            if (mp->sw_if_index == (u32)~0)
2494              vlib_clear_simple_counters (sm);
2495            else
2496              vlib_zero_simple_counter (sm, ntohl(mp->sw_if_index));
2497          }
2498      }
2499
2500    REPLY_MACRO(VL_API_SW_INTERFACE_CLEAR_STATS_REPLY);
2501 }
2502
2503 static void send_sw_interface_details (vpe_api_main_t * am,
2504                                        unix_shared_memory_queue_t *q,
2505                                        vnet_sw_interface_t * swif,
2506                                        u8 * interface_name,
2507                                        u32 context)
2508 {
2509     vl_api_sw_interface_details_t * mp;
2510     vnet_hw_interface_t * hi;
2511
2512     hi = vnet_get_sup_hw_interface (am->vnet_main, swif->sw_if_index);
2513
2514     mp = vl_msg_api_alloc (sizeof (*mp));
2515     memset (mp, 0, sizeof (*mp));
2516     mp->_vl_msg_id = ntohs(VL_API_SW_INTERFACE_DETAILS);
2517     mp->sw_if_index = ntohl(swif->sw_if_index);
2518     mp->sup_sw_if_index = ntohl(swif->sup_sw_if_index);
2519     mp->admin_up_down = (swif->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ?
2520         1 : 0;
2521     mp->link_up_down = (hi->flags & VNET_HW_INTERFACE_FLAG_LINK_UP) ?
2522         1 : 0;
2523     mp->link_duplex = ((hi->flags & VNET_HW_INTERFACE_FLAG_DUPLEX_MASK) >>
2524                        VNET_HW_INTERFACE_FLAG_DUPLEX_SHIFT);
2525     mp->link_speed = ((hi->flags & VNET_HW_INTERFACE_FLAG_SPEED_MASK) >>
2526                       VNET_HW_INTERFACE_FLAG_SPEED_SHIFT);
2527     mp->link_mtu = ntohs(hi->max_packet_bytes);
2528     mp->context = context;
2529
2530     strncpy ((char *) mp->interface_name,
2531              (char *) interface_name, ARRAY_LEN(mp->interface_name)-1);
2532
2533     /* Send the L2 address for ethernet physical intfcs */
2534     if (swif->sup_sw_if_index == swif->sw_if_index
2535         && hi->hw_class_index == ethernet_hw_interface_class.index) {
2536         ethernet_main_t *em = ethernet_get_main (am->vlib_main);
2537         ethernet_interface_t *ei;
2538
2539         ei = pool_elt_at_index (em->interfaces, hi->hw_instance);
2540         ASSERT (sizeof (mp->l2_address) >= sizeof (ei->address));
2541         clib_memcpy (mp->l2_address, ei->address, sizeof (ei->address));
2542         mp->l2_address_length = ntohl(sizeof (ei->address));
2543     } else if (swif->sup_sw_if_index != swif->sw_if_index) {
2544         vnet_sub_interface_t *sub = &swif->sub;
2545         mp->sub_id = ntohl(sub->id);
2546         mp->sub_dot1ad = sub->eth.flags.dot1ad;
2547         mp->sub_number_of_tags = sub->eth.flags.one_tag + sub->eth.flags.two_tags*2;
2548         mp->sub_outer_vlan_id = ntohs(sub->eth.outer_vlan_id);
2549         mp->sub_inner_vlan_id = ntohs(sub->eth.inner_vlan_id);
2550         mp->sub_exact_match = sub->eth.flags.exact_match;
2551         mp->sub_default = sub->eth.flags.default_sub;
2552         mp->sub_outer_vlan_id_any = sub->eth.flags.outer_vlan_id_any;
2553         mp->sub_inner_vlan_id_any = sub->eth.flags.inner_vlan_id_any;
2554
2555         /* vlan tag rewrite data */
2556         u32 vtr_op = L2_VTR_DISABLED;
2557         u32 vtr_push_dot1q = 0, vtr_tag1 = 0, vtr_tag2 = 0;
2558
2559         if (l2vtr_get(am->vlib_main, am->vnet_main, swif->sw_if_index,
2560                       &vtr_op, &vtr_push_dot1q, &vtr_tag1, &vtr_tag2) != 0) {
2561             // error - default to disabled
2562             mp->vtr_op = ntohl(L2_VTR_DISABLED);
2563             clib_warning("cannot get vlan tag rewrite for sw_if_index %d",
2564                     swif->sw_if_index);
2565         } else {
2566             mp->vtr_op = ntohl(vtr_op);
2567             mp->vtr_push_dot1q = ntohl(vtr_push_dot1q);
2568             mp->vtr_tag1 = ntohl(vtr_tag1);
2569             mp->vtr_tag2 = ntohl(vtr_tag2);
2570         }
2571     }
2572
2573     vl_msg_api_send_shmem (q, (u8 *)&mp);
2574 }
2575
2576 static void send_sw_interface_flags (vpe_api_main_t * am,
2577                                      unix_shared_memory_queue_t *q,
2578                                      vnet_sw_interface_t * swif)
2579 {
2580     vl_api_sw_interface_set_flags_t *mp;
2581     vnet_main_t * vnm = am->vnet_main;
2582
2583     vnet_hw_interface_t *hi = vnet_get_sup_hw_interface (vnm,
2584                                                          swif->sw_if_index);
2585     mp = vl_msg_api_alloc (sizeof (*mp));
2586     memset (mp, 0, sizeof (*mp));
2587     mp->_vl_msg_id = ntohs(VL_API_SW_INTERFACE_SET_FLAGS);
2588     mp->sw_if_index = ntohl(swif->sw_if_index);
2589
2590     mp->admin_up_down = (swif->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ?
2591         1 : 0;
2592     mp->link_up_down = (hi->flags & VNET_HW_INTERFACE_FLAG_LINK_UP) ?
2593         1 : 0;
2594     vl_msg_api_send_shmem (q, (u8 *)&mp);
2595 }
2596
2597 static void send_sw_interface_flags_deleted (vpe_api_main_t * am,
2598                                      unix_shared_memory_queue_t *q,
2599                                              u32 sw_if_index)
2600     __attribute__((unused));
2601
2602 static void send_sw_interface_flags_deleted (vpe_api_main_t * am,
2603                                      unix_shared_memory_queue_t *q,
2604                                      u32 sw_if_index)
2605 {
2606     vl_api_sw_interface_set_flags_t *mp;
2607
2608     mp = vl_msg_api_alloc (sizeof (*mp));
2609     memset (mp, 0, sizeof (*mp));
2610     mp->_vl_msg_id = ntohs(VL_API_SW_INTERFACE_SET_FLAGS);
2611     mp->sw_if_index = ntohl(sw_if_index);
2612
2613     mp->admin_up_down = 0;
2614     mp->link_up_down = 0;
2615     mp->deleted = 1;
2616     vl_msg_api_send_shmem (q, (u8 *)&mp);
2617 }
2618
2619 static void vl_api_sw_interface_dump_t_handler (
2620     vl_api_sw_interface_dump_t *mp)
2621 {
2622     vpe_api_main_t * am = &vpe_api_main;
2623     vnet_sw_interface_t * swif;
2624     vnet_interface_main_t * im = &am->vnet_main->interface_main;
2625     u8 * filter_string = 0, * name_string = 0;
2626     unix_shared_memory_queue_t * q;
2627     char * strcasestr (char *, char *); /* lnx hdr file botch */
2628
2629     q = vl_api_client_index_to_input_queue (mp->client_index);
2630
2631     if (q == 0)
2632         return;
2633
2634     if (mp->name_filter_valid) {
2635         mp->name_filter [ARRAY_LEN(mp->name_filter)-1] = 0;
2636         filter_string = format (0, "%s%c", mp->name_filter, 0);
2637     }
2638
2639     pool_foreach (swif, im->sw_interfaces,
2640     ({
2641         name_string = format (name_string, "%U%c",
2642                               format_vnet_sw_interface_name,
2643                               am->vnet_main, swif, 0);
2644
2645         if (mp->name_filter_valid == 0 ||
2646             strcasestr((char *) name_string, (char *) filter_string)) {
2647
2648             send_sw_interface_details (am, q, swif, name_string, mp->context);
2649         }
2650         _vec_len (name_string) = 0;
2651     }));
2652
2653     vec_free (name_string);
2654     vec_free (filter_string);
2655 }
2656
2657 void send_oam_event (oam_target_t * t)
2658 {
2659     vpe_api_main_t * vam = &vpe_api_main;
2660     unix_shared_memory_queue_t * q;
2661     vpe_client_registration_t *reg;
2662     vl_api_oam_event_t * mp;
2663
2664     pool_foreach(reg, vam->oam_events_registrations,
2665     ({
2666         q = vl_api_client_index_to_input_queue (reg->client_index);
2667         if (q) {
2668             mp = vl_msg_api_alloc (sizeof (*mp));
2669             mp->_vl_msg_id = ntohs (VL_API_OAM_EVENT);
2670             clib_memcpy (mp->dst_address, &t->dst_address, sizeof (mp->dst_address));
2671             mp->state = t->state;
2672             vl_msg_api_send_shmem (q, (u8 *)&mp);
2673         }
2674     }));
2675 }
2676
2677 static void
2678 vl_api_oam_add_del_t_handler (vl_api_oam_add_del_t *mp)
2679 {
2680     vl_api_oam_add_del_reply_t * rmp;
2681     int rv;
2682
2683     rv = vpe_oam_add_del_target ((ip4_address_t *)mp->src_address,
2684                                  (ip4_address_t *)mp->dst_address,
2685                                  ntohl(mp->vrf_id),
2686                                  (int)(mp->is_add));
2687
2688     REPLY_MACRO(VL_API_OAM_ADD_DEL_REPLY);
2689 }
2690
2691 static void
2692 vl_api_vnet_get_summary_stats_t_handler (
2693     vl_api_vnet_get_summary_stats_t *mp)
2694 {
2695     stats_main_t * sm = &stats_main;
2696     vnet_interface_main_t * im = sm->interface_main;
2697     vl_api_vnet_summary_stats_reply_t *rmp;
2698     vlib_combined_counter_main_t * cm;
2699     vlib_counter_t v;
2700     int i, which;
2701     u64 total_pkts[VLIB_N_RX_TX];
2702     u64 total_bytes[VLIB_N_RX_TX];
2703
2704     unix_shared_memory_queue_t * q =
2705         vl_api_client_index_to_input_queue (mp->client_index);
2706
2707     if (!q)
2708         return;
2709
2710     rmp = vl_msg_api_alloc (sizeof (*rmp));
2711     rmp->_vl_msg_id = ntohs(VL_API_VNET_SUMMARY_STATS_REPLY);
2712     rmp->context = mp->context;
2713     rmp->retval = 0;
2714
2715     memset (total_pkts, 0, sizeof (total_pkts));
2716     memset (total_bytes, 0, sizeof (total_bytes));
2717
2718     vnet_interface_counter_lock (im);
2719
2720     vec_foreach (cm, im->combined_sw_if_counters) {
2721         which = cm - im->combined_sw_if_counters;
2722
2723         for (i = 0; i < vec_len (cm->maxi); i++) {
2724             vlib_get_combined_counter (cm, i, &v);
2725             total_pkts[which] += v.packets;
2726             total_bytes[which] += v.bytes;
2727         }
2728     }
2729     vnet_interface_counter_unlock (im);
2730
2731     /* Note: in HOST byte order! */
2732     rmp->total_pkts[VLIB_RX] = total_pkts[VLIB_RX];
2733     rmp->total_bytes[VLIB_RX] = total_bytes[VLIB_RX];
2734     rmp->total_pkts[VLIB_TX] = total_pkts[VLIB_TX];
2735     rmp->total_bytes[VLIB_TX] = total_bytes[VLIB_TX];
2736     rmp->vector_rate = vlib_last_vector_length_per_node (sm->vlib_main);
2737
2738     vl_msg_api_send_shmem (q, (u8 *)&rmp);
2739 }
2740
2741 typedef CLIB_PACKED (struct {
2742   ip4_address_t address;
2743
2744   u32 address_length : 6;
2745
2746   u32 index : 26;
2747 }) ip4_route_t;
2748
2749 static int ip4_reset_fib_t_handler (vl_api_reset_fib_t *mp)
2750 {
2751     vnet_main_t * vnm = vnet_get_main();
2752     vnet_interface_main_t * im = &vnm->interface_main;
2753     ip4_main_t * im4 = &ip4_main;
2754     static ip4_route_t * routes;
2755     static u32 * sw_if_indices_to_shut;
2756     stats_main_t * sm = &stats_main;
2757     ip4_route_t * r;
2758     ip4_fib_t * fib;
2759     u32 sw_if_index;
2760     int i;
2761     int rv = VNET_API_ERROR_NO_SUCH_FIB;
2762     u32 target_fib_id = ntohl(mp->vrf_id);
2763
2764     dslock (sm, 1 /* release hint */, 8 /* tag */);
2765
2766     vec_foreach (fib, im4->fibs) {
2767         vnet_sw_interface_t * si;
2768
2769         if (fib->table_id != target_fib_id)
2770             continue;
2771
2772         /* remove any mpls/gre tunnels in this fib */
2773         vnet_mpls_gre_delete_fib_tunnels (fib->table_id);
2774
2775         /* remove any mpls encap/decap labels */
2776         mpls_fib_reset_labels (fib->table_id);
2777
2778         /* remove any proxy arps in this fib */
2779         vnet_proxy_arp_fib_reset (fib->table_id);
2780
2781         /* Set the flow hash for this fib to the default */
2782         vnet_set_ip4_flow_hash (fib->table_id, IP_FLOW_HASH_DEFAULT);
2783
2784         vec_reset_length (sw_if_indices_to_shut);
2785
2786         /* Shut down interfaces in this FIB / clean out intfc routes */
2787         pool_foreach (si, im->sw_interfaces,
2788         ({
2789             u32 sw_if_index = si->sw_if_index;
2790
2791             if (sw_if_index < vec_len (im4->fib_index_by_sw_if_index)
2792                 && (im4->fib_index_by_sw_if_index[si->sw_if_index] ==
2793                     fib - im4->fibs))
2794                 vec_add1 (sw_if_indices_to_shut, si->sw_if_index);
2795         }));
2796
2797         for (i = 0; i < vec_len (sw_if_indices_to_shut); i++) {
2798             sw_if_index = sw_if_indices_to_shut[i];
2799             // vec_foreach (sw_if_index, sw_if_indices_to_shut) {
2800
2801             u32 flags = vnet_sw_interface_get_flags (vnm, sw_if_index);
2802             flags &= ~(VNET_SW_INTERFACE_FLAG_ADMIN_UP);
2803             vnet_sw_interface_set_flags (vnm, sw_if_index, flags);
2804         }
2805
2806         vec_reset_length (routes);
2807
2808         for (i = 0; i < ARRAY_LEN (fib->adj_index_by_dst_address); i++) {
2809             uword * hash = fib->adj_index_by_dst_address[i];
2810             hash_pair_t * p;
2811             ip4_route_t x;
2812
2813             x.address_length = i;
2814
2815             hash_foreach_pair (p, hash,
2816             ({
2817                 x.address.data_u32 = p->key;
2818                 vec_add1 (routes, x);
2819             }));
2820         }
2821
2822         vec_foreach (r, routes) {
2823             ip4_add_del_route_args_t a;
2824
2825             memset (&a, 0, sizeof (a));
2826             a.flags = IP4_ROUTE_FLAG_FIB_INDEX | IP4_ROUTE_FLAG_DEL;
2827             a.table_index_or_table_id = fib - im4->fibs;
2828             a.dst_address = r->address;
2829             a.dst_address_length = r->address_length;
2830             a.adj_index = ~0;
2831
2832             ip4_add_del_route (im4, &a);
2833             ip4_maybe_remap_adjacencies (im4, fib - im4->fibs,
2834                                          IP4_ROUTE_FLAG_FIB_INDEX);
2835         }
2836         rv = 0;
2837         break;
2838     } /* vec_foreach (fib) */
2839
2840     dsunlock(sm);
2841     return rv;
2842 }
2843
2844 typedef struct {
2845   ip6_address_t address;
2846   u32 address_length;
2847   u32 index;
2848 } ip6_route_t;
2849
2850 typedef struct {
2851   u32 fib_index;
2852   ip6_route_t ** routep;
2853 } add_routes_in_fib_arg_t;
2854
2855 static void add_routes_in_fib (clib_bihash_kv_24_8_t * kvp, void *arg)
2856 {
2857   add_routes_in_fib_arg_t * ap = arg;
2858
2859   if (kvp->key[2]>>32 == ap->fib_index)
2860     {
2861       ip6_address_t *addr;
2862       ip6_route_t * r;
2863       addr = (ip6_address_t *) kvp;
2864       vec_add2 (*ap->routep, r, 1);
2865       r->address = addr[0];
2866       r->address_length = kvp->key[2] & 0xFF;
2867       r->index = kvp->value;
2868     }
2869 }
2870
2871 static int ip6_reset_fib_t_handler (vl_api_reset_fib_t *mp)
2872 {
2873     vnet_main_t * vnm = vnet_get_main();
2874     vnet_interface_main_t * im = &vnm->interface_main;
2875     ip6_main_t * im6 = &ip6_main;
2876     stats_main_t * sm = &stats_main;
2877     static ip6_route_t * routes;
2878     static u32 * sw_if_indices_to_shut;
2879     ip6_route_t * r;
2880     ip6_fib_t * fib;
2881     u32 sw_if_index;
2882     int i;
2883     int rv = VNET_API_ERROR_NO_SUCH_FIB;
2884     u32 target_fib_id = ntohl(mp->vrf_id);
2885     add_routes_in_fib_arg_t _a, *a=&_a;
2886     clib_bihash_24_8_t * h = &im6->ip6_lookup_table;
2887
2888     dslock (sm, 1 /* release hint */, 9 /* tag */);
2889
2890     vec_foreach (fib, im6->fibs) {
2891         vnet_sw_interface_t * si;
2892
2893         if (fib->table_id != target_fib_id)
2894             continue;
2895
2896         vec_reset_length (sw_if_indices_to_shut);
2897
2898         /* Shut down interfaces in this FIB / clean out intfc routes */
2899         pool_foreach (si, im->sw_interfaces,
2900         ({
2901             if (im6->fib_index_by_sw_if_index[si->sw_if_index] ==
2902                 fib - im6->fibs)
2903                 vec_add1 (sw_if_indices_to_shut, si->sw_if_index);
2904         }));
2905
2906         for (i = 0; i < vec_len (sw_if_indices_to_shut); i++) {
2907             sw_if_index = sw_if_indices_to_shut[i];
2908             // vec_foreach (sw_if_index, sw_if_indices_to_shut) {
2909
2910             u32 flags = vnet_sw_interface_get_flags (vnm, sw_if_index);
2911             flags &= ~(VNET_SW_INTERFACE_FLAG_ADMIN_UP);
2912             vnet_sw_interface_set_flags (vnm, sw_if_index, flags);
2913         }
2914
2915         vec_reset_length (routes);
2916
2917         a->fib_index = fib - im6->fibs;
2918         a->routep = &routes;
2919
2920         clib_bihash_foreach_key_value_pair_24_8 (h, add_routes_in_fib, a);
2921
2922         vec_foreach (r, routes) {
2923             ip6_add_del_route_args_t a;
2924
2925             memset (&a, 0, sizeof (a));
2926             a.flags = IP6_ROUTE_FLAG_FIB_INDEX | IP6_ROUTE_FLAG_DEL;
2927             a.table_index_or_table_id = fib - im6->fibs;
2928             a.dst_address = r->address;
2929             a.dst_address_length = r->address_length;
2930             a.adj_index = ~0;
2931
2932             ip6_add_del_route (im6, &a);
2933             ip6_maybe_remap_adjacencies (im6, fib - im6->fibs,
2934                                          IP6_ROUTE_FLAG_FIB_INDEX);
2935         }
2936         rv = 0;
2937         /* Reinstall the neighbor / router discovery routes */
2938         vnet_ip6_fib_init (im6, fib - im6->fibs);
2939         break;
2940     } /* vec_foreach (fib) */
2941
2942     dsunlock(sm);
2943     return rv;
2944 }
2945
2946 static void vl_api_reset_fib_t_handler (vl_api_reset_fib_t *mp)
2947 {
2948     int rv;
2949     vl_api_reset_fib_reply_t * rmp;
2950
2951     if (mp->is_ipv6)
2952         rv = ip6_reset_fib_t_handler (mp);
2953     else
2954         rv = ip4_reset_fib_t_handler (mp);
2955
2956     REPLY_MACRO(VL_API_RESET_FIB_REPLY);
2957 }
2958
2959
2960 static void
2961 dhcpv4_proxy_config (vl_api_dhcp_proxy_config_t *mp)
2962 {
2963     vl_api_dhcp_proxy_config_reply_t * rmp;
2964     int rv;
2965
2966     rv = dhcp_proxy_set_server ((ip4_address_t *)(&mp->dhcp_server),
2967                                 (ip4_address_t *)(&mp->dhcp_src_address),
2968                                 (u32) ntohl(mp->vrf_id),
2969                                 (int) mp->insert_circuit_id,
2970                                 (int) (mp->is_add == 0));
2971
2972     REPLY_MACRO(VL_API_DHCP_PROXY_CONFIG_REPLY);
2973 }
2974
2975
2976 static void
2977 dhcpv6_proxy_config (vl_api_dhcp_proxy_config_t *mp)
2978 {
2979     vl_api_dhcp_proxy_config_reply_t * rmp;
2980     int rv = -1;
2981
2982     rv = dhcpv6_proxy_set_server ((ip6_address_t *)(&mp->dhcp_server),
2983                                 (ip6_address_t *)(&mp->dhcp_src_address),
2984                                 (u32) ntohl(mp->vrf_id),
2985                                 (int) mp->insert_circuit_id,
2986                                 (int) (mp->is_add == 0));
2987
2988     REPLY_MACRO(VL_API_DHCP_PROXY_CONFIG_REPLY);
2989 }
2990
2991 static void
2992 dhcpv4_proxy_config_2 (vl_api_dhcp_proxy_config_2_t *mp)
2993 {
2994     vl_api_dhcp_proxy_config_reply_t * rmp;
2995     int rv;
2996
2997     rv = dhcp_proxy_set_server_2 ((ip4_address_t *)(&mp->dhcp_server),
2998                                 (ip4_address_t *)(&mp->dhcp_src_address),
2999                                 (u32) ntohl(mp->rx_vrf_id),
3000                                 (u32) ntohl(mp->server_vrf_id),
3001                                 (int) mp->insert_circuit_id,
3002                                 (int) (mp->is_add == 0));
3003
3004     REPLY_MACRO(VL_API_DHCP_PROXY_CONFIG_2_REPLY);
3005 }
3006
3007
3008 static void
3009 dhcpv6_proxy_config_2 (vl_api_dhcp_proxy_config_2_t *mp)
3010 {
3011     vl_api_dhcp_proxy_config_reply_t * rmp;
3012     int rv = -1;
3013
3014 #if 0 // $$$$ FIXME
3015     rv = dhcpv6_proxy_set_server_2 ((ip6_address_t *)(&mp->dhcp_server),
3016                                 (ip6_address_t *)(&mp->dhcp_src_address),
3017                                 (u32) ntohl(mp->rx_vrf_id),
3018                                 (u32) ntohl(mp->server_vrf_id),
3019                                 (int) mp->insert_circuit_id,
3020                                 (int) (mp->is_add == 0));
3021 #else
3022     rv = VNET_API_ERROR_UNIMPLEMENTED;
3023 #endif
3024
3025     REPLY_MACRO(VL_API_DHCP_PROXY_CONFIG_2_REPLY);
3026 }
3027
3028
3029 static void
3030 vl_api_dhcp_proxy_set_vss_t_handler (vl_api_dhcp_proxy_set_vss_t *mp)
3031 {
3032     vl_api_dhcp_proxy_set_vss_reply_t *rmp;
3033     int rv;
3034     if (!mp->is_ipv6)
3035         rv = dhcp_proxy_set_option82_vss(ntohl(mp->tbl_id),
3036                                          ntohl(mp->oui),
3037                                          ntohl(mp->fib_id),
3038                                          (int)mp->is_add == 0);
3039     else
3040          rv = dhcpv6_proxy_set_vss( ntohl(mp->tbl_id),
3041                                          ntohl(mp->oui),
3042                                          ntohl(mp->fib_id),
3043                                          (int)mp->is_add == 0);
3044
3045     REPLY_MACRO(VL_API_DHCP_PROXY_SET_VSS_REPLY);
3046 }
3047
3048
3049 static void vl_api_dhcp_proxy_config_t_handler
3050 (vl_api_dhcp_proxy_config_t *mp)
3051 {
3052     if (mp->is_ipv6 == 0)
3053         dhcpv4_proxy_config (mp);
3054     else
3055         dhcpv6_proxy_config (mp);
3056 }
3057
3058 static void vl_api_dhcp_proxy_config_2_t_handler
3059 (vl_api_dhcp_proxy_config_2_t *mp)
3060 {
3061     if (mp->is_ipv6 == 0)
3062         dhcpv4_proxy_config_2 (mp);
3063     else
3064         dhcpv6_proxy_config_2 (mp);
3065 }
3066
3067 void dhcp_compl_event_callback (u32 client_index, u32 pid, u8 * hostname,
3068        u8 is_ipv6, u8 * host_address, u8 * router_address, u8 * host_mac)
3069 {
3070     unix_shared_memory_queue_t * q;
3071     vl_api_dhcp_compl_event_t * mp;
3072
3073     q = vl_api_client_index_to_input_queue (client_index);
3074     if (!q)
3075         return;
3076
3077     mp = vl_msg_api_alloc (sizeof (*mp));
3078     mp->client_index = client_index;
3079     mp->pid = pid;
3080     mp->is_ipv6 = is_ipv6;
3081     clib_memcpy (&mp->hostname, hostname, vec_len(hostname));
3082     mp->hostname[vec_len(hostname) + 1] = '\n';
3083     clib_memcpy (&mp->host_address[0], host_address, 16);
3084     clib_memcpy (&mp->router_address[0], router_address, 16);
3085     clib_memcpy (&mp->host_mac[0], host_mac, 6);
3086
3087     mp->_vl_msg_id = ntohs (VL_API_DHCP_COMPL_EVENT);
3088
3089     vl_msg_api_send_shmem (q, (u8 *)&mp);
3090 }
3091
3092 static void vl_api_dhcp_client_config_t_handler
3093 (vl_api_dhcp_client_config_t *mp)
3094 {
3095     vlib_main_t *vm = vlib_get_main();
3096     vl_api_dhcp_client_config_reply_t * rmp;
3097     int rv = 0;
3098
3099     VALIDATE_SW_IF_INDEX(mp);
3100
3101     rv = dhcp_client_config(vm, ntohl(mp->sw_if_index),
3102              mp->hostname, mp->is_add, mp->client_index,
3103              mp->want_dhcp_event ? dhcp_compl_event_callback : NULL,
3104              mp->pid);
3105
3106     BAD_SW_IF_INDEX_LABEL;
3107
3108     REPLY_MACRO(VL_API_DHCP_CLIENT_CONFIG_REPLY);
3109 }
3110
3111 static void
3112 vl_api_sw_interface_ip6nd_ra_config_t_handler
3113 (vl_api_sw_interface_ip6nd_ra_config_t *mp, vlib_main_t *vm)
3114 {
3115    vl_api_sw_interface_ip6nd_ra_config_reply_t * rmp;
3116     int rv = 0;
3117     u8  is_no,  suppress, managed, other, ll_option, send_unicast, cease, default_router;
3118
3119     is_no = mp->is_no == 1;
3120     suppress = mp->suppress == 1;
3121     managed = mp->managed == 1;
3122    other = mp->other == 1;
3123     ll_option = mp->ll_option == 1;
3124     send_unicast = mp->send_unicast == 1;
3125     cease = mp->cease == 1;
3126     default_router = mp->default_router  == 1;
3127
3128     VALIDATE_SW_IF_INDEX(mp);
3129
3130     rv = ip6_neighbor_ra_config(vm, ntohl(mp->sw_if_index),
3131                                 suppress,  managed,  other,
3132                                 ll_option,  send_unicast,  cease,
3133                                 default_router, ntohl (mp->lifetime),
3134                                 ntohl(mp->initial_count),  ntohl(mp->initial_interval),
3135                                 ntohl(mp->max_interval), ntohl( mp->min_interval),
3136                                 is_no);
3137
3138     BAD_SW_IF_INDEX_LABEL;
3139
3140     REPLY_MACRO(VL_API_SW_INTERFACE_IP6ND_RA_CONFIG_REPLY);
3141 }
3142
3143 static void
3144 vl_api_sw_interface_ip6nd_ra_prefix_t_handler
3145 (vl_api_sw_interface_ip6nd_ra_prefix_t *mp, vlib_main_t *vm)
3146 {
3147    vl_api_sw_interface_ip6nd_ra_prefix_reply_t * rmp;
3148     int rv = 0;
3149     u8  is_no,  use_default,  no_advertise, off_link, no_autoconfig, no_onlink;
3150
3151     VALIDATE_SW_IF_INDEX(mp);
3152
3153     is_no = mp->is_no == 1;
3154     use_default = mp->use_default == 1;
3155     no_advertise = mp->no_advertise == 1;
3156     off_link = mp->off_link == 1;
3157     no_autoconfig = mp->no_autoconfig == 1;
3158     no_onlink = mp->no_onlink == 1;
3159
3160     rv = ip6_neighbor_ra_prefix(vm,  ntohl(mp->sw_if_index),
3161                                 (ip6_address_t *)mp->address,  mp->address_length,
3162                                 use_default,  ntohl(mp->val_lifetime), ntohl(mp->pref_lifetime),
3163                                 no_advertise,  off_link, no_autoconfig, no_onlink,
3164                                 is_no);
3165
3166     BAD_SW_IF_INDEX_LABEL;
3167     REPLY_MACRO(VL_API_SW_INTERFACE_IP6ND_RA_PREFIX_REPLY);
3168 }
3169
3170 static void
3171 vl_api_sw_interface_ip6_enable_disable_t_handler
3172 (vl_api_sw_interface_ip6_enable_disable_t *mp, vlib_main_t *vm)
3173 {
3174     vl_api_sw_interface_ip6_enable_disable_reply_t * rmp;
3175     vnet_main_t * vnm = vnet_get_main();
3176     int rv = 0;
3177     clib_error_t * error;
3178
3179     vnm->api_errno = 0;
3180
3181     VALIDATE_SW_IF_INDEX(mp);
3182
3183     error = ( mp->enable == 1) ? enable_ip6_interface(vm,ntohl(mp->sw_if_index)) :
3184         disable_ip6_interface(vm,ntohl(mp->sw_if_index));
3185
3186     if (error)  {
3187         clib_error_report(error);
3188         rv = VNET_API_ERROR_UNSPECIFIED;
3189     } else {
3190         rv = vnm->api_errno;
3191     }
3192
3193     BAD_SW_IF_INDEX_LABEL;
3194
3195     REPLY_MACRO(VL_API_SW_INTERFACE_IP6_ENABLE_DISABLE_REPLY);
3196 }
3197
3198 static void
3199 vl_api_sw_interface_ip6_set_link_local_address_t_handler
3200 (vl_api_sw_interface_ip6_set_link_local_address_t *mp, vlib_main_t *vm)
3201 {
3202     vl_api_sw_interface_ip6_set_link_local_address_reply_t * rmp;
3203     int rv = 0;
3204     clib_error_t * error;
3205     vnet_main_t * vnm = vnet_get_main();
3206
3207     vnm->api_errno = 0;
3208
3209     VALIDATE_SW_IF_INDEX(mp);
3210
3211     error = set_ip6_link_local_address(vm,
3212                                        ntohl(mp->sw_if_index),
3213                                        (ip6_address_t *)mp->address,
3214                                        mp->address_length);
3215     if (error)  {
3216       clib_error_report(error);
3217       rv = VNET_API_ERROR_UNSPECIFIED;
3218     } else {
3219         rv = vnm->api_errno;
3220     }
3221
3222     BAD_SW_IF_INDEX_LABEL;
3223
3224     REPLY_MACRO(VL_API_SW_INTERFACE_IP6_SET_LINK_LOCAL_ADDRESS_REPLY);
3225 }
3226
3227 static void set_ip6_flow_hash (vl_api_set_ip_flow_hash_t *mp)
3228 {
3229     vl_api_set_ip_flow_hash_reply_t *rmp;
3230     int rv = VNET_API_ERROR_UNIMPLEMENTED;
3231
3232     clib_warning ("unimplemented...");
3233
3234     REPLY_MACRO(VL_API_SET_IP_FLOW_HASH_REPLY);
3235 }
3236
3237 static void set_ip4_flow_hash (vl_api_set_ip_flow_hash_t *mp)
3238 {
3239     vl_api_set_ip_flow_hash_reply_t *rmp;
3240     int rv;
3241     u32 table_id;
3242     u32 flow_hash_config = 0;
3243
3244     table_id = ntohl(mp->vrf_id);
3245
3246 #define _(a,b) if (mp->a) flow_hash_config |= b;
3247     foreach_flow_hash_bit;
3248 #undef _
3249
3250     rv = vnet_set_ip4_flow_hash (table_id, flow_hash_config);
3251
3252     REPLY_MACRO(VL_API_SET_IP_FLOW_HASH_REPLY);
3253 }
3254
3255
3256 static void vl_api_set_ip_flow_hash_t_handler
3257 (vl_api_set_ip_flow_hash_t *mp)
3258 {
3259     if (mp->is_ipv6 == 0)
3260         set_ip4_flow_hash (mp);
3261     else
3262         set_ip6_flow_hash (mp);
3263 }
3264
3265 static void vl_api_sw_interface_set_unnumbered_t_handler
3266 (vl_api_sw_interface_set_unnumbered_t *mp)
3267 {
3268     vl_api_sw_interface_set_unnumbered_reply_t * rmp;
3269     int rv = 0;
3270     vnet_sw_interface_t * si;
3271     vnet_main_t *vnm = vnet_get_main();
3272     u32 sw_if_index, unnumbered_sw_if_index;
3273
3274     sw_if_index = ntohl(mp->sw_if_index);
3275     unnumbered_sw_if_index = ntohl(mp->unnumbered_sw_if_index);
3276
3277     /*
3278      * The API message field names are backwards from
3279      * the underlying data structure names.
3280      * It's not worth changing them now.
3281      */
3282     if (pool_is_free_index (vnm->interface_main.sw_interfaces,
3283                             unnumbered_sw_if_index)) {
3284         rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
3285         goto done;
3286     }
3287
3288     /* Only check the "use loop0" field when setting the binding */
3289     if (mp->is_add &&
3290         pool_is_free_index (vnm->interface_main.sw_interfaces, sw_if_index)) {
3291         rv = VNET_API_ERROR_INVALID_SW_IF_INDEX_2;
3292         goto done;
3293     }
3294
3295     si = vnet_get_sw_interface (vnm, unnumbered_sw_if_index);
3296
3297     if (mp->is_add) {
3298         si->flags |= VNET_SW_INTERFACE_FLAG_UNNUMBERED;
3299         si->unnumbered_sw_if_index = sw_if_index;
3300     } else {
3301         si->flags &= ~(VNET_SW_INTERFACE_FLAG_UNNUMBERED);
3302         si->unnumbered_sw_if_index = (u32)~0;
3303     }
3304
3305  done:
3306     REPLY_MACRO(VL_API_SW_INTERFACE_SET_UNNUMBERED_REPLY);
3307 }
3308
3309 static void vl_api_create_loopback_t_handler
3310 (vl_api_create_loopback_t *mp)
3311 {
3312     vl_api_create_loopback_reply_t * rmp;
3313     u32 sw_if_index;
3314     int rv;
3315
3316     rv = vnet_create_loopback_interface (&sw_if_index, mp->mac_address);
3317
3318     REPLY_MACRO2(VL_API_CREATE_LOOPBACK_REPLY,
3319     ({
3320         rmp->sw_if_index = ntohl (sw_if_index);
3321     }));
3322 }
3323
3324 static void vl_api_delete_loopback_t_handler
3325 (vl_api_delete_loopback_t *mp)
3326 {
3327     vl_api_delete_loopback_reply_t * rmp;
3328     u32 sw_if_index;
3329     int rv;
3330
3331     sw_if_index = ntohl (mp->sw_if_index);
3332     rv = vnet_delete_loopback_interface (sw_if_index);
3333
3334     REPLY_MACRO(VL_API_DELETE_LOOPBACK_REPLY);
3335 }
3336
3337 static void vl_api_control_ping_t_handler
3338 (vl_api_control_ping_t *mp)
3339 {
3340     vl_api_control_ping_reply_t * rmp;
3341     int rv = 0;
3342
3343     REPLY_MACRO2(VL_API_CONTROL_PING_REPLY,
3344     ({
3345         rmp->vpe_pid = ntohl (getpid());
3346     }));
3347 }
3348
3349 static void shmem_cli_output (uword arg, u8 * buffer, uword buffer_bytes)
3350 {
3351     u8 **shmem_vecp = (u8 **)arg;
3352     u8 *shmem_vec;
3353     void *oldheap;
3354     api_main_t * am = &api_main;
3355     u32 offset;
3356
3357     shmem_vec = *shmem_vecp;
3358
3359     offset = vec_len (shmem_vec);
3360
3361     pthread_mutex_lock (&am->vlib_rp->mutex);
3362     oldheap = svm_push_data_heap (am->vlib_rp);
3363
3364     vec_validate (shmem_vec, offset + buffer_bytes - 1);
3365
3366     clib_memcpy (shmem_vec + offset, buffer, buffer_bytes);
3367
3368     svm_pop_heap (oldheap);
3369     pthread_mutex_unlock (&am->vlib_rp->mutex);
3370
3371     *shmem_vecp = shmem_vec;
3372 }
3373
3374
3375 static void vl_api_cli_request_t_handler
3376 (vl_api_cli_request_t *mp)
3377 {
3378     vl_api_cli_reply_t *rp;
3379     unix_shared_memory_queue_t *q;
3380     vlib_main_t * vm = vlib_get_main();
3381     api_main_t * am = &api_main;
3382     unformat_input_t input;
3383     u8 *shmem_vec=0;
3384     void *oldheap;
3385
3386     q = vl_api_client_index_to_input_queue (mp->client_index);
3387     if (!q)
3388         return;
3389
3390     rp = vl_msg_api_alloc (sizeof (*rp));
3391     rp->_vl_msg_id = ntohs(VL_API_CLI_REPLY);
3392     rp->context = mp->context;
3393
3394     unformat_init_vector (&input, (u8 *)(uword)mp->cmd_in_shmem);
3395
3396     vlib_cli_input (vm, &input, shmem_cli_output,
3397                     (uword)&shmem_vec);
3398
3399     pthread_mutex_lock (&am->vlib_rp->mutex);
3400     oldheap = svm_push_data_heap (am->vlib_rp);
3401
3402     vec_add1(shmem_vec, 0);
3403
3404     svm_pop_heap (oldheap);
3405     pthread_mutex_unlock (&am->vlib_rp->mutex);
3406
3407     rp->reply_in_shmem = (uword)shmem_vec;
3408
3409     vl_msg_api_send_shmem (q, (u8 *)&rp);
3410 }
3411
3412 static void vl_api_set_arp_neighbor_limit_t_handler (vl_api_set_arp_neighbor_limit_t *mp)
3413 {
3414     int rv;
3415     vl_api_set_arp_neighbor_limit_reply_t * rmp;
3416     vnet_main_t *vnm = vnet_get_main();
3417     clib_error_t * error;
3418
3419     vnm->api_errno = 0;
3420
3421     if (mp->is_ipv6)
3422         error = ip6_set_neighbor_limit (ntohl(mp->arp_neighbor_limit));
3423     else
3424         error = ip4_set_arp_limit (ntohl(mp->arp_neighbor_limit));
3425
3426     if (error)  {
3427         clib_error_report(error);
3428         rv = VNET_API_ERROR_UNSPECIFIED;
3429     } else {
3430         rv = vnm->api_errno;
3431     }
3432
3433     REPLY_MACRO(VL_API_SET_ARP_NEIGHBOR_LIMIT_REPLY);
3434 }
3435
3436 static void vl_api_sr_tunnel_add_del_t_handler
3437 (vl_api_sr_tunnel_add_del_t *mp)
3438 {
3439 #if IPV6SR == 0
3440     clib_warning ("unimplemented");
3441 #else
3442     ip6_sr_add_del_tunnel_args_t _a, *a=&_a;
3443     int rv = 0;
3444     vl_api_sr_tunnel_add_del_reply_t * rmp;
3445     ip6_address_t * segments = 0, * seg;
3446     ip6_address_t * tags = 0, *tag;
3447     ip6_address_t * this_address;
3448     int i;
3449
3450     if (mp->n_segments == 0) {
3451         rv = -11;
3452         goto out;
3453     }
3454
3455     memset (a, 0, sizeof (*a));
3456     a->src_address = (ip6_address_t *)&mp->src_address;
3457     a->dst_address = (ip6_address_t *)&mp->dst_address;
3458     a->dst_mask_width = mp->dst_mask_width;
3459     a->flags_net_byte_order = mp->flags_net_byte_order;
3460     a->is_del = (mp->is_add == 0);
3461     a->rx_table_id = ntohl(mp->outer_vrf_id);
3462     a->tx_table_id = ntohl(mp->inner_vrf_id);
3463
3464     a->name = format(0, "%s", mp->name);
3465     if (!(vec_len(a->name)))
3466       a->name = 0;
3467
3468     a->policy_name = format(0, "%s", mp->policy_name);
3469     if (!(vec_len(a->policy_name)))
3470       a->policy_name = 0;
3471
3472     /* Yank segments and tags out of the API message */
3473     this_address = (ip6_address_t *)mp->segs_and_tags;
3474     for (i = 0; i < mp->n_segments; i++) {
3475         vec_add2 (segments, seg, 1);
3476         clib_memcpy (seg->as_u8, this_address->as_u8, sizeof (*this_address));
3477         this_address++;
3478     }
3479     for (i = 0; i < mp->n_tags; i++) {
3480         vec_add2 (tags, tag, 1);
3481         clib_memcpy (tag->as_u8, this_address->as_u8, sizeof (*this_address));
3482         this_address++;
3483     }
3484
3485     a->segments = segments;
3486     a->tags = tags;
3487
3488     rv = ip6_sr_add_del_tunnel (a);
3489
3490 out:
3491
3492     REPLY_MACRO(VL_API_SR_TUNNEL_ADD_DEL_REPLY);
3493 #endif
3494 }
3495
3496 static void vl_api_sr_policy_add_del_t_handler
3497 (vl_api_sr_policy_add_del_t *mp)
3498 {
3499 #if IPV6SR == 0
3500     clib_warning ("unimplemented");
3501 #else
3502     ip6_sr_add_del_policy_args_t _a, *a=&_a;
3503     int rv = 0;
3504     vl_api_sr_policy_add_del_reply_t * rmp;
3505     int i;
3506
3507     memset (a, 0, sizeof (*a));
3508     a->is_del = (mp->is_add == 0);
3509
3510     a->name = format(0, "%s", mp->name);
3511     if (!(vec_len(a->name)))
3512       {
3513         rv = VNET_API_ERROR_NO_SUCH_NODE2;
3514         goto out;
3515       }
3516
3517     if (!(mp->tunnel_names[0]))
3518       {
3519         rv = VNET_API_ERROR_NO_SUCH_NODE2;
3520         goto out;
3521       }
3522
3523     // start deserializing tunnel_names
3524     int num_tunnels = mp->tunnel_names[0]; //number of tunnels
3525     u8 * deser_tun_names = mp->tunnel_names;
3526     deser_tun_names += 1; //moving along
3527
3528     u8 * tun_name = 0;
3529     int tun_name_len = 0;
3530
3531     for (i=0; i < num_tunnels; i++)
3532       {
3533         tun_name_len= *deser_tun_names;
3534         deser_tun_names += 1;
3535         vec_resize (tun_name, tun_name_len);
3536         memcpy(tun_name, deser_tun_names, tun_name_len);
3537         vec_add1 (a->tunnel_names, tun_name);
3538         deser_tun_names += tun_name_len;
3539         tun_name = 0;
3540       }
3541
3542     rv = ip6_sr_add_del_policy (a);
3543
3544 out:
3545
3546     REPLY_MACRO(VL_API_SR_POLICY_ADD_DEL_REPLY);
3547 #endif
3548 }
3549
3550 static void vl_api_sr_multicast_map_add_del_t_handler
3551 (vl_api_sr_multicast_map_add_del_t *mp)
3552 {
3553 #if IPV6SR == 0
3554     clib_warning ("unimplemented");
3555 #else
3556     ip6_sr_add_del_multicastmap_args_t _a, *a=&_a;
3557     int rv = 0;
3558     vl_api_sr_multicast_map_add_del_reply_t * rmp;
3559
3560     memset (a, 0, sizeof (*a));
3561     a->is_del = (mp->is_add == 0);
3562
3563     a->multicast_address = (ip6_address_t *)&mp->multicast_address;
3564     a->policy_name = format(0, "%s", mp->policy_name);
3565
3566     if (a->multicast_address == 0)
3567       {
3568         rv = -1 ;
3569         goto out;
3570       }
3571
3572     if (!(a->policy_name))
3573       {
3574         rv = -2 ;
3575         goto out;
3576       }
3577
3578 #if DPDK > 0 /* Cannot call replicate without DPDK */
3579     rv = ip6_sr_add_del_multicastmap (a);
3580 #else
3581     clib_warning ("multicast replication without DPDK not implemented");
3582     rv = VNET_API_ERROR_UNIMPLEMENTED;
3583 #endif /* DPDK */
3584
3585 out:
3586
3587     REPLY_MACRO(VL_API_SR_MULTICAST_MAP_ADD_DEL_REPLY);
3588 #endif
3589 }
3590
3591 #define foreach_classify_add_del_table_field    \
3592 _(table_index)                                  \
3593 _(nbuckets)                                     \
3594 _(memory_size)                                  \
3595 _(skip_n_vectors)                               \
3596 _(match_n_vectors)                              \
3597 _(next_table_index)                             \
3598 _(miss_next_index)
3599
3600 static void vl_api_classify_add_del_table_t_handler
3601 (vl_api_classify_add_del_table_t * mp)
3602 {
3603     vl_api_classify_add_del_table_reply_t * rmp;
3604     vnet_classify_main_t * cm = &vnet_classify_main;
3605     vnet_classify_table_t * t;
3606     int rv;
3607
3608 #define _(a) u32 a;
3609     foreach_classify_add_del_table_field;
3610 #undef _
3611
3612 #define _(a) a = ntohl(mp->a);
3613     foreach_classify_add_del_table_field;
3614 #undef _
3615
3616     /* The underlying API fails silently, on purpose, so check here */
3617     if (mp->is_add == 0)
3618         if (pool_is_free_index (cm->tables, table_index)) {
3619             rv = VNET_API_ERROR_NO_SUCH_TABLE;
3620             goto out;
3621         }
3622
3623     rv = vnet_classify_add_del_table
3624         (cm, mp->mask, nbuckets, memory_size,
3625          skip_n_vectors, match_n_vectors,
3626          next_table_index, miss_next_index,
3627          &table_index, mp->is_add);
3628
3629 out:
3630     REPLY_MACRO2(VL_API_CLASSIFY_ADD_DEL_TABLE_REPLY,
3631     ({
3632         if (rv == 0 && mp->is_add) {
3633             t = pool_elt_at_index (cm->tables, table_index);
3634             rmp->skip_n_vectors = ntohl(t->skip_n_vectors);
3635             rmp->match_n_vectors = ntohl(t->match_n_vectors);
3636             rmp->new_table_index = ntohl(table_index);
3637         } else {
3638             rmp->skip_n_vectors = ~0;
3639             rmp->match_n_vectors = ~0;
3640             rmp->new_table_index = ~0;
3641         }
3642     }));
3643 }
3644
3645 static void vl_api_classify_add_del_session_t_handler
3646 (vl_api_classify_add_del_session_t * mp)
3647 {
3648     vnet_classify_main_t * cm = &vnet_classify_main;
3649     vl_api_classify_add_del_session_reply_t * rmp;
3650     int rv;
3651     u32 table_index, hit_next_index, opaque_index;
3652     i32 advance;
3653
3654     table_index = ntohl (mp->table_index);
3655     hit_next_index = ntohl (mp->hit_next_index);
3656     opaque_index = ntohl (mp->opaque_index);
3657     advance = ntohl (mp->advance);
3658
3659     rv = vnet_classify_add_del_session
3660         (cm, table_index, mp->match, hit_next_index, opaque_index,
3661          advance, mp->is_add);
3662
3663     REPLY_MACRO(VL_API_CLASSIFY_ADD_DEL_SESSION_REPLY);
3664 }
3665
3666 static void vl_api_classify_set_interface_ip_table_t_handler
3667 (vl_api_classify_set_interface_ip_table_t * mp)
3668 {
3669     vlib_main_t * vm = vlib_get_main();
3670     vl_api_classify_set_interface_ip_table_reply_t * rmp;
3671     int rv;
3672     u32 table_index, sw_if_index;
3673
3674     table_index = ntohl (mp->table_index);
3675     sw_if_index = ntohl (mp->sw_if_index);
3676
3677     VALIDATE_SW_IF_INDEX(mp);
3678
3679     if (mp->is_ipv6)
3680         rv = vnet_set_ip6_classify_intfc (vm, sw_if_index, table_index);
3681     else
3682         rv = vnet_set_ip4_classify_intfc (vm, sw_if_index, table_index);
3683
3684     BAD_SW_IF_INDEX_LABEL;
3685
3686     REPLY_MACRO(VL_API_CLASSIFY_SET_INTERFACE_IP_TABLE_REPLY);
3687 }
3688
3689 static void vl_api_classify_set_interface_l2_tables_t_handler
3690 (vl_api_classify_set_interface_l2_tables_t * mp)
3691 {
3692     vl_api_classify_set_interface_l2_tables_reply_t * rmp;
3693     int rv;
3694     u32 sw_if_index, ip4_table_index, ip6_table_index, other_table_index;
3695     int enable;
3696
3697     ip4_table_index = ntohl(mp->ip4_table_index);
3698     ip6_table_index = ntohl(mp->ip6_table_index);
3699     other_table_index = ntohl(mp->other_table_index);
3700     sw_if_index = ntohl(mp->sw_if_index);
3701
3702     VALIDATE_SW_IF_INDEX(mp);
3703
3704     rv = vnet_l2_classify_set_tables (sw_if_index, ip4_table_index,
3705                                       ip6_table_index, other_table_index);
3706
3707     if (rv == 0) {
3708         if (ip4_table_index != ~0 || ip6_table_index != ~0
3709             || other_table_index != ~0)
3710             enable = 1;
3711         else
3712             enable = 0;
3713
3714         vnet_l2_classify_enable_disable (sw_if_index, enable);
3715     }
3716
3717     BAD_SW_IF_INDEX_LABEL;
3718
3719     REPLY_MACRO(VL_API_CLASSIFY_SET_INTERFACE_L2_TABLES_REPLY);
3720 }
3721
3722 static void
3723 vl_api_l2_fib_clear_table_t_handler (vl_api_l2_fib_clear_table_t *mp)
3724 {
3725     int rv = 0;
3726     vl_api_l2_fib_clear_table_reply_t * rmp;
3727
3728     /* DAW-FIXME: This API should only clear non-static l2fib entries, but
3729      *            that is not currently implemented.  When that TODO is fixed
3730      *            this call should be changed to pass 1 instead of 0.
3731      */
3732     l2fib_clear_table (0);
3733
3734     REPLY_MACRO(VL_API_L2_FIB_CLEAR_TABLE_REPLY);
3735 }
3736
3737 extern void l2_efp_filter_configure(vnet_main_t * vnet_main,
3738                                     u32           sw_if_index,
3739                                     u32           enable);
3740
3741 static void
3742 vl_api_l2_interface_efp_filter_t_handler (vl_api_l2_interface_efp_filter_t *mp)
3743 {
3744     int rv;
3745     vl_api_l2_interface_efp_filter_reply_t * rmp;
3746     vnet_main_t *vnm = vnet_get_main();
3747
3748     // enable/disable the feature
3749     l2_efp_filter_configure (vnm, mp->sw_if_index, mp->enable_disable);
3750     rv = vnm->api_errno;
3751
3752     REPLY_MACRO(VL_API_L2_INTERFACE_EFP_FILTER_REPLY);
3753 }
3754
3755 static void
3756 vl_api_l2_interface_vlan_tag_rewrite_t_handler (vl_api_l2_interface_vlan_tag_rewrite_t *mp)
3757 {
3758     int rv = 0;
3759     vl_api_l2_interface_vlan_tag_rewrite_reply_t * rmp;
3760     vnet_main_t * vnm = vnet_get_main();
3761     vlib_main_t * vm = vlib_get_main();
3762     u32 vtr_op;
3763
3764     VALIDATE_SW_IF_INDEX(mp);
3765
3766     vtr_op = ntohl(mp->vtr_op);
3767
3768     /* The L2 code is unsuspicious */
3769     switch(vtr_op) {
3770     case L2_VTR_DISABLED:
3771     case L2_VTR_PUSH_1:
3772     case L2_VTR_PUSH_2:
3773     case L2_VTR_POP_1:
3774     case L2_VTR_POP_2:
3775     case L2_VTR_TRANSLATE_1_1:
3776     case L2_VTR_TRANSLATE_1_2:
3777     case L2_VTR_TRANSLATE_2_1:
3778     case L2_VTR_TRANSLATE_2_2:
3779         break;
3780
3781     default:
3782         rv = VNET_API_ERROR_INVALID_VALUE;
3783         goto bad_sw_if_index;
3784     }
3785
3786     rv = l2vtr_configure (vm, vnm, ntohl(mp->sw_if_index), vtr_op,
3787                           ntohl(mp->push_dot1q), ntohl(mp->tag1),
3788                           ntohl(mp->tag2));
3789
3790     BAD_SW_IF_INDEX_LABEL;
3791
3792     REPLY_MACRO(VL_API_L2_INTERFACE_VLAN_TAG_REWRITE_REPLY);
3793 }
3794
3795 static void
3796 vl_api_create_vhost_user_if_t_handler (vl_api_create_vhost_user_if_t *mp)
3797 {
3798 #if DPDK > 0
3799     int rv = 0;
3800     vl_api_create_vhost_user_if_reply_t * rmp;
3801     u32 sw_if_index = (u32)~0;
3802
3803     vnet_main_t * vnm = vnet_get_main();
3804     vlib_main_t * vm = vlib_get_main();
3805
3806     rv = dpdk_vhost_user_create_if(vnm, vm, (char *)mp->sock_filename,
3807                               mp->is_server, &sw_if_index, (u64)~0,
3808                               mp->renumber, ntohl(mp->custom_dev_instance),
3809                               (mp->use_custom_mac)?mp->mac_address:NULL);
3810
3811     REPLY_MACRO2(VL_API_CREATE_VHOST_USER_IF_REPLY,
3812     ({
3813       rmp->sw_if_index = ntohl (sw_if_index);
3814     }));
3815 #endif
3816 }
3817
3818 static void
3819 vl_api_modify_vhost_user_if_t_handler (vl_api_modify_vhost_user_if_t *mp)
3820 {
3821 #if DPDK > 0
3822     int rv = 0;
3823     vl_api_modify_vhost_user_if_reply_t * rmp;
3824     u32 sw_if_index = ntohl(mp->sw_if_index);
3825
3826     vnet_main_t * vnm = vnet_get_main();
3827     vlib_main_t * vm = vlib_get_main();
3828
3829     rv = dpdk_vhost_user_modify_if(vnm, vm, (char *)mp->sock_filename,
3830                               mp->is_server, sw_if_index, (u64)~0,
3831                               mp->renumber, ntohl(mp->custom_dev_instance));
3832
3833     REPLY_MACRO(VL_API_MODIFY_VHOST_USER_IF_REPLY);
3834 #endif
3835 }
3836
3837 static void
3838 vl_api_delete_vhost_user_if_t_handler (vl_api_delete_vhost_user_if_t *mp)
3839 {
3840 #if DPDK > 0
3841     int rv = 0;
3842     vpe_api_main_t * vam = &vpe_api_main;
3843     vl_api_delete_vhost_user_if_reply_t * rmp;
3844     u32 sw_if_index = ntohl(mp->sw_if_index);
3845
3846     vnet_main_t * vnm = vnet_get_main();
3847     vlib_main_t * vm = vlib_get_main();
3848
3849     rv = dpdk_vhost_user_delete_if(vnm, vm, sw_if_index);
3850
3851     REPLY_MACRO(VL_API_DELETE_VHOST_USER_IF_REPLY);
3852     if (!rv) {
3853         unix_shared_memory_queue_t * q =
3854             vl_api_client_index_to_input_queue (mp->client_index);
3855         if (!q)
3856             return;
3857
3858         send_sw_interface_flags_deleted (vam, q, sw_if_index);
3859     }
3860 #endif
3861 }
3862
3863 static void vl_api_sw_interface_vhost_user_details_t_handler (
3864     vl_api_sw_interface_vhost_user_details_t * mp)
3865 {
3866     clib_warning ("BUG");
3867 }
3868
3869 #if DPDK > 0
3870 static void send_sw_interface_vhost_user_details (vpe_api_main_t * am,
3871                                        unix_shared_memory_queue_t *q,
3872                                        vhost_user_intf_details_t * vui,
3873                                        u32 context)
3874 {
3875     vl_api_sw_interface_vhost_user_details_t * mp;
3876
3877     mp = vl_msg_api_alloc (sizeof (*mp));
3878     memset (mp, 0, sizeof (*mp));
3879     mp->_vl_msg_id = ntohs(VL_API_SW_INTERFACE_VHOST_USER_DETAILS);
3880     mp->sw_if_index = ntohl(vui->sw_if_index);
3881     mp->virtio_net_hdr_sz = ntohl (vui->virtio_net_hdr_sz);
3882     mp->features = clib_net_to_host_u64 (vui->features);
3883     mp->is_server = vui->is_server;
3884     mp->num_regions = ntohl(vui->num_regions);
3885     mp->sock_errno = ntohl(vui->sock_errno);
3886     mp->context = context;
3887
3888     strncpy ((char *) mp->sock_filename,
3889              (char *) vui->sock_filename, ARRAY_LEN(mp->sock_filename)-1);
3890     strncpy ((char *) mp->interface_name,
3891              (char *) vui->if_name, ARRAY_LEN(mp->interface_name)-1);
3892
3893     vl_msg_api_send_shmem (q, (u8 *)&mp);
3894 }
3895 #endif
3896
3897 static void
3898 vl_api_sw_interface_vhost_user_dump_t_handler (
3899         vl_api_sw_interface_vhost_user_dump_t *mp)
3900 {
3901 #if DPDK > 0
3902     int rv = 0;
3903     vpe_api_main_t * am = &vpe_api_main;
3904     vnet_main_t * vnm = vnet_get_main();
3905     vlib_main_t * vm = vlib_get_main();
3906     vhost_user_intf_details_t *ifaces = NULL;
3907     vhost_user_intf_details_t *vuid = NULL;
3908     unix_shared_memory_queue_t * q;
3909
3910     q = vl_api_client_index_to_input_queue (mp->client_index);
3911     if (q == 0)
3912         return;
3913
3914     rv = dpdk_vhost_user_dump_ifs(vnm, vm, &ifaces);
3915     if (rv)
3916         return;
3917
3918     vec_foreach (vuid, ifaces) {
3919         send_sw_interface_vhost_user_details (am, q, vuid, mp->context);
3920     }
3921     vec_free(ifaces);
3922 #endif
3923 }
3924
3925 static void send_sw_if_l2tpv3_tunnel_details (vpe_api_main_t * am,
3926                                        unix_shared_memory_queue_t *q,
3927                                        l2t_session_t *s,
3928                                        l2t_main_t * lm,
3929                                        u32 context)
3930 {
3931     vl_api_sw_if_l2tpv3_tunnel_details_t * mp;
3932     u8 * if_name = NULL;
3933     vnet_sw_interface_t * si = NULL;
3934
3935     si = vnet_get_hw_sw_interface (lm->vnet_main, s->hw_if_index);
3936
3937     if_name = format(if_name, "%U",
3938                      format_vnet_sw_interface_name, lm->vnet_main, si);
3939
3940     mp = vl_msg_api_alloc (sizeof (*mp));
3941     memset (mp, 0, sizeof (*mp));
3942     mp->_vl_msg_id = ntohs(VL_API_SW_IF_L2TPV3_TUNNEL_DETAILS);
3943     strncpy((char *)mp->interface_name,
3944             (char *)if_name, ARRAY_LEN(mp->interface_name)-1);
3945     mp->sw_if_index = ntohl(si->sw_if_index);
3946     mp->local_session_id = s->local_session_id;
3947     mp->remote_session_id = s->remote_session_id;
3948     mp->local_cookie[0] = s->local_cookie[0];
3949     mp->local_cookie[1] = s->local_cookie[1];
3950     mp->remote_cookie = s->remote_cookie;
3951     clib_memcpy(mp->client_address, &s->client_address, sizeof(s->client_address));
3952     clib_memcpy(mp->our_address, &s->our_address, sizeof(s->our_address));
3953     mp->l2_sublayer_present = s->l2_sublayer_present;
3954     mp->context = context;
3955
3956     vl_msg_api_send_shmem (q, (u8 *)&mp);
3957 }
3958
3959 static void send_ip_address_details (vpe_api_main_t * am,
3960                                      unix_shared_memory_queue_t * q,
3961                                      u8 * ip,
3962                                      u16 prefix_length,
3963                                      u8 is_ipv6,
3964                                      u32 context)
3965 {
3966     vl_api_ip_address_details_t * mp;
3967
3968     mp = vl_msg_api_alloc (sizeof (*mp));
3969     memset (mp, 0, sizeof (*mp));
3970     mp->_vl_msg_id = ntohs(VL_API_IP_ADDRESS_DETAILS);
3971
3972     if (is_ipv6) {
3973         clib_memcpy(&mp->ip, ip, sizeof(mp->ip));
3974     } else {
3975         u32 * tp = (u32 *)mp->ip;
3976         *tp = ntohl(*(u32*)ip);
3977     }
3978     mp->prefix_length = prefix_length;
3979     mp->context = context;
3980
3981     vl_msg_api_send_shmem (q, (u8 *)&mp);
3982 }
3983
3984 static void
3985 vl_api_ip_address_dump_t_handler (vl_api_ip_address_dump_t *mp)
3986 {
3987     vpe_api_main_t * am = &vpe_api_main;
3988     unix_shared_memory_queue_t * q;
3989     ip6_address_t * r6;
3990     ip4_address_t * r4;
3991     ip6_main_t * im6 = &ip6_main;
3992     ip4_main_t * im4 = &ip4_main;
3993     ip_lookup_main_t * lm6 = &im6->lookup_main;
3994     ip_lookup_main_t * lm4 = &im4->lookup_main;
3995     ip_interface_address_t * ia = 0;
3996     u32 sw_if_index = ~0;
3997     int rv __attribute__ ((unused)) = 0;
3998
3999     VALIDATE_SW_IF_INDEX(mp);
4000
4001     sw_if_index = ntohl(mp->sw_if_index);
4002
4003     q = vl_api_client_index_to_input_queue (mp->client_index);
4004     if (q == 0) {
4005         return;
4006     }
4007
4008     if (mp->is_ipv6) {
4009         foreach_ip_interface_address (lm6, ia, sw_if_index,
4010                                       1 /* honor unnumbered */,
4011         ({
4012             r6 = ip_interface_address_get_address (lm6, ia);
4013             u16 prefix_length = ia->address_length;
4014             send_ip_address_details(am, q, (u8*)r6, prefix_length, 1, mp->context);
4015         }));
4016     } else {
4017         foreach_ip_interface_address (lm4, ia, sw_if_index,
4018                                       1 /* honor unnumbered */,
4019         ({
4020             r4 = ip_interface_address_get_address (lm4, ia);
4021             u16 prefix_length = ia->address_length;
4022             send_ip_address_details(am, q, (u8*)r4, prefix_length, 0, mp->context);
4023         }));
4024     }
4025     BAD_SW_IF_INDEX_LABEL;
4026 }
4027
4028 static void send_ip_details (vpe_api_main_t * am,
4029                                unix_shared_memory_queue_t *q,
4030                                u32 sw_if_index,
4031                                u32 context)
4032 {
4033     vl_api_ip_details_t * mp;
4034
4035     mp = vl_msg_api_alloc (sizeof (*mp));
4036     memset (mp, 0, sizeof (*mp));
4037     mp->_vl_msg_id = ntohs(VL_API_IP_DETAILS);
4038
4039     mp->sw_if_index = ntohl(sw_if_index);
4040     mp->context = context;
4041
4042     vl_msg_api_send_shmem (q, (u8 *)&mp);
4043 }
4044
4045 static void
4046 vl_api_sw_if_l2tpv3_tunnel_dump_t_handler (
4047         vl_api_sw_if_l2tpv3_tunnel_dump_t *mp)
4048 {
4049     vpe_api_main_t * am = &vpe_api_main;
4050     l2t_main_t * lm = &l2t_main;
4051     unix_shared_memory_queue_t * q;
4052     l2t_session_t *session;
4053
4054     q = vl_api_client_index_to_input_queue (mp->client_index);
4055     if (q == 0)
4056         return;
4057
4058     pool_foreach (session, lm->sessions,
4059     ({
4060         send_sw_if_l2tpv3_tunnel_details (am, q, session, lm, mp->context);
4061     }));
4062 }
4063
4064
4065 static void send_sw_interface_tap_details (vpe_api_main_t * am,
4066                                        unix_shared_memory_queue_t *q,
4067                                        tapcli_interface_details_t *tap_if,
4068                                        u32 context)
4069 {
4070     vl_api_sw_interface_tap_details_t * mp;
4071     mp = vl_msg_api_alloc (sizeof (*mp));
4072     memset (mp, 0, sizeof (*mp));
4073     mp->_vl_msg_id = ntohs(VL_API_SW_INTERFACE_TAP_DETAILS);
4074     mp->sw_if_index = ntohl(tap_if->sw_if_index);
4075     strncpy((char *)mp->dev_name,
4076             (char *)tap_if->dev_name, ARRAY_LEN(mp->dev_name)-1);
4077     mp->context = context;
4078
4079     vl_msg_api_send_shmem (q, (u8 *)&mp);
4080 }
4081
4082 static void
4083 vl_api_sw_interface_tap_dump_t_handler (
4084         vl_api_sw_interface_tap_dump_t *mp)
4085 {
4086     int rv = 0;
4087     vpe_api_main_t * am = &vpe_api_main;
4088     unix_shared_memory_queue_t * q;
4089     tapcli_interface_details_t *tapifs = NULL;
4090     tapcli_interface_details_t *tap_if = NULL;
4091
4092     q = vl_api_client_index_to_input_queue (mp->client_index);
4093     if (q == 0)
4094         return;
4095
4096     rv = vnet_tap_dump_ifs(&tapifs);
4097     if (rv)
4098         return;
4099
4100     vec_foreach(tap_if, tapifs) {
4101         send_sw_interface_tap_details(am, q, tap_if, mp->context);
4102     }
4103
4104     vec_free(tapifs);
4105 }
4106
4107 static void
4108 vl_api_ip_dump_t_handler (vl_api_ip_dump_t *mp)
4109 {
4110     vpe_api_main_t * am = &vpe_api_main;
4111     vnet_main_t * vnm = vnet_get_main();
4112     vlib_main_t * vm = vlib_get_main();
4113     vnet_interface_main_t * im = &vnm->interface_main;
4114     unix_shared_memory_queue_t * q;
4115     vnet_sw_interface_t * si, * sorted_sis;
4116     u32 sw_if_index = ~0;
4117
4118     q = vl_api_client_index_to_input_queue (mp->client_index);
4119     if (q == 0) {
4120         return;
4121     }
4122
4123     /* Gather interfaces. */
4124     sorted_sis = vec_new (vnet_sw_interface_t, pool_elts (im->sw_interfaces));
4125     _vec_len (sorted_sis) = 0;
4126     pool_foreach (si, im->sw_interfaces, ({ vec_add1 (sorted_sis, si[0]); }));
4127
4128     vec_foreach (si, sorted_sis) {
4129         if (!(si->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED)) {
4130             if (mp->is_ipv6 && !ip6_interface_enabled(vm, si->sw_if_index)) {
4131                 continue;
4132             }
4133             sw_if_index = si->sw_if_index;
4134             send_ip_details(am, q, sw_if_index, mp->context);
4135         }
4136     }
4137 }
4138
4139 static void vl_api_l2_fib_table_entry_t_handler (
4140     vl_api_l2_fib_table_entry_t * mp)
4141 {
4142     clib_warning ("BUG");
4143 }
4144
4145 static void send_l2fib_table_entry (vpe_api_main_t * am,
4146                                     unix_shared_memory_queue_t *q,
4147                                     l2fib_entry_key_t * l2fe_key,
4148                                     l2fib_entry_result_t * l2fe_res,
4149                                     u32 context)
4150 {
4151     vl_api_l2_fib_table_entry_t * mp;
4152
4153     mp = vl_msg_api_alloc (sizeof (*mp));
4154     memset (mp, 0, sizeof (*mp));
4155     mp->_vl_msg_id = ntohs(VL_API_L2_FIB_TABLE_ENTRY);
4156
4157     mp->bd_id = ntohl(l2input_main.bd_configs[l2fe_key->fields.bd_index].bd_id);
4158
4159     mp->mac = l2fib_make_key (l2fe_key->fields.mac, 0);
4160     mp->sw_if_index = ntohl(l2fe_res->fields.sw_if_index);
4161     mp->static_mac = l2fe_res->fields.static_mac;
4162     mp->filter_mac = l2fe_res->fields.filter;
4163     mp->bvi_mac = l2fe_res->fields.bvi;
4164     mp->context = context;
4165
4166     vl_msg_api_send_shmem (q, (u8 *)&mp);
4167 }
4168
4169 static void
4170 vl_api_l2_fib_table_dump_t_handler (vl_api_l2_fib_table_dump_t *mp)
4171 {
4172     vpe_api_main_t * am = &vpe_api_main;
4173     bd_main_t * bdm = &bd_main;
4174     l2fib_entry_key_t *l2fe_key = NULL;
4175     l2fib_entry_result_t *l2fe_res = NULL;
4176     u32 ni, bd_id = ntohl (mp->bd_id);
4177     u32 bd_index;
4178     unix_shared_memory_queue_t * q;
4179     uword * p;
4180
4181     q = vl_api_client_index_to_input_queue (mp->client_index);
4182     if (q == 0)
4183         return;
4184
4185     /* see l2fib_table_dump: ~0 means "any" */
4186     if (bd_id == ~0)
4187         bd_index = ~0;
4188     else {
4189         p = hash_get (bdm->bd_index_by_bd_id, bd_id);
4190         if (p == 0)
4191             return;
4192
4193         bd_index = p[0];
4194     }
4195
4196     l2fib_table_dump (bd_index, &l2fe_key, &l2fe_res);
4197
4198     vec_foreach_index (ni, l2fe_key) {
4199         send_l2fib_table_entry (am, q, vec_elt_at_index(l2fe_key, ni),
4200                                 vec_elt_at_index(l2fe_res, ni), mp->context);
4201     }
4202     vec_free(l2fe_key);
4203     vec_free(l2fe_res);
4204 }
4205
4206 static void
4207 vl_api_show_version_t_handler (vl_api_show_version_t *mp)
4208 {
4209     vl_api_show_version_reply_t *rmp;
4210     int rv = 0;
4211     char * vpe_api_get_build_directory(void);
4212     char * vpe_api_get_version(void);
4213     char * vpe_api_get_build_date(void);
4214
4215     unix_shared_memory_queue_t * q =
4216         vl_api_client_index_to_input_queue (mp->client_index);
4217
4218     if (!q)
4219         return;
4220
4221     REPLY_MACRO2(VL_API_SHOW_VERSION_REPLY,
4222     ({
4223         strncpy ((char *) rmp->program, "vpe", ARRAY_LEN(rmp->program)-1);
4224         strncpy ((char *) rmp->build_directory, vpe_api_get_build_directory(),
4225                  ARRAY_LEN(rmp->build_directory)-1);
4226         strncpy ((char *) rmp->version, vpe_api_get_version(),
4227                  ARRAY_LEN(rmp->version)-1);
4228         strncpy ((char *) rmp->build_date, vpe_api_get_build_date(),
4229                  ARRAY_LEN(rmp->build_date)-1);
4230     }));
4231 }
4232
4233 static void vl_api_get_node_index_t_handler
4234 (vl_api_get_node_index_t * mp)
4235 {
4236     vlib_main_t * vm = vlib_get_main();
4237     vl_api_get_node_index_reply_t * rmp;
4238     vlib_node_t * n;
4239     int rv = 0;
4240     u32 node_index = ~0;
4241
4242     n = vlib_get_node_by_name (vm, mp->node_name);
4243
4244     if (n == 0)
4245         rv = VNET_API_ERROR_NO_SUCH_NODE;
4246     else
4247         node_index = n->index;
4248
4249     REPLY_MACRO2(VL_API_GET_NODE_INDEX_REPLY,
4250     ({
4251         rmp->node_index = ntohl(node_index);
4252     }))
4253 }
4254
4255 static void vl_api_add_node_next_t_handler
4256 (vl_api_add_node_next_t * mp)
4257 {
4258     vlib_main_t * vm = vlib_get_main();
4259     vl_api_add_node_next_reply_t * rmp;
4260     vlib_node_t * n, * next;
4261     int rv = 0;
4262     u32 next_index = ~0;
4263
4264     n = vlib_get_node_by_name (vm, mp->node_name);
4265
4266     if (n == 0) {
4267         rv = VNET_API_ERROR_NO_SUCH_NODE;
4268         goto out;
4269     }
4270
4271     next = vlib_get_node_by_name (vm, mp->next_name);
4272
4273     if (next == 0)
4274         rv = VNET_API_ERROR_NO_SUCH_NODE2;
4275     else
4276         next_index = vlib_node_add_next (vm, n->index, next->index);
4277
4278 out:
4279     REPLY_MACRO2(VL_API_GET_NODE_INDEX_REPLY,
4280     ({
4281         rmp->next_index = ntohl(next_index);
4282     }))
4283 }
4284
4285 static void vl_api_l2tpv3_create_tunnel_t_handler
4286 (vl_api_l2tpv3_create_tunnel_t *mp)
4287 {
4288     vl_api_l2tpv3_create_tunnel_reply_t * rmp;
4289     l2t_main_t *lm = &l2t_main;
4290     u32 sw_if_index = (u32)~0;
4291     int rv;
4292
4293     if (mp->is_ipv6 != 1) {
4294         rv = VNET_API_ERROR_UNIMPLEMENTED;
4295         goto out;
4296     }
4297
4298     rv = create_l2tpv3_ipv6_tunnel (lm,
4299                                (ip6_address_t *) mp->client_address,
4300                                (ip6_address_t *) mp->our_address,
4301                                ntohl(mp->local_session_id),
4302                                ntohl(mp->remote_session_id),
4303                                clib_net_to_host_u64(mp->local_cookie),
4304                                clib_net_to_host_u64(mp->remote_cookie),
4305                                mp->l2_sublayer_present,
4306                                &sw_if_index);
4307
4308 out:
4309     REPLY_MACRO2(VL_API_L2TPV3_CREATE_TUNNEL_REPLY,
4310     ({
4311         rmp->sw_if_index = ntohl (sw_if_index);
4312     }))
4313 }
4314
4315 static void vl_api_l2tpv3_set_tunnel_cookies_t_handler
4316 (vl_api_l2tpv3_set_tunnel_cookies_t *mp)
4317 {
4318     vl_api_l2tpv3_set_tunnel_cookies_reply_t * rmp;
4319     l2t_main_t *lm = &l2t_main;
4320     int rv;
4321
4322     VALIDATE_SW_IF_INDEX(mp);
4323
4324     rv = l2tpv3_set_tunnel_cookies (lm, ntohl(mp->sw_if_index),
4325                                   clib_net_to_host_u64(mp->new_local_cookie),
4326                                   clib_net_to_host_u64(mp->new_remote_cookie));
4327
4328     BAD_SW_IF_INDEX_LABEL;
4329
4330     REPLY_MACRO (VL_API_L2TPV3_SET_TUNNEL_COOKIES_REPLY);
4331 }
4332
4333 static void vl_api_l2tpv3_interface_enable_disable_t_handler
4334 (vl_api_l2tpv3_interface_enable_disable_t * mp)
4335 {
4336     int rv;
4337     vnet_main_t * vnm = vnet_get_main();
4338     vl_api_l2tpv3_interface_enable_disable_reply_t * rmp;
4339
4340     VALIDATE_SW_IF_INDEX(mp);
4341
4342     rv = l2tpv3_interface_enable_disable
4343         (vnm, ntohl(mp->sw_if_index), mp->enable_disable);
4344
4345     BAD_SW_IF_INDEX_LABEL;
4346
4347     REPLY_MACRO (VL_API_L2TPV3_INTERFACE_ENABLE_DISABLE_REPLY);
4348 }
4349
4350 static void vl_api_l2tpv3_set_lookup_key_t_handler
4351 (vl_api_l2tpv3_set_lookup_key_t * mp)
4352 {
4353     int rv = 0;
4354     l2t_main_t *lm = &l2t_main;
4355     vl_api_l2tpv3_set_lookup_key_reply_t * rmp;
4356
4357     if (mp->key > L2T_LOOKUP_SESSION_ID) {
4358         rv = VNET_API_ERROR_INVALID_VALUE;
4359         goto out;
4360     }
4361
4362     lm->lookup_type = mp->key;
4363
4364 out:
4365     REPLY_MACRO (VL_API_L2TPV3_SET_LOOKUP_KEY_REPLY);
4366 }
4367
4368 static void vl_api_vxlan_add_del_tunnel_t_handler
4369 (vl_api_vxlan_add_del_tunnel_t * mp)
4370 {
4371     vl_api_vxlan_add_del_tunnel_reply_t * rmp;
4372     int rv = 0;
4373     vnet_vxlan_add_del_tunnel_args_t _a, *a = &_a;
4374     u32 encap_fib_index;
4375     uword * p;
4376     ip4_main_t * im = &ip4_main;
4377     u32 sw_if_index = ~0;
4378
4379     p = hash_get (im->fib_index_by_table_id, ntohl(mp->encap_vrf_id));
4380     if (! p) {
4381         rv = VNET_API_ERROR_NO_SUCH_FIB;
4382         goto out;
4383     }
4384     encap_fib_index = p[0];
4385
4386     /* Check src & dst are different */
4387     if ((mp->is_ipv6 && memcmp(mp->src_address, mp->dst_address, 16) == 0) ||
4388        (!mp->is_ipv6 && memcmp(mp->src_address, mp->dst_address, 4) == 0)) {
4389         rv = VNET_API_ERROR_SAME_SRC_DST;
4390         goto out;
4391     }
4392     memset (a, 0, sizeof (*a));
4393
4394     a->is_add = mp->is_add;
4395     a->is_ip6 = mp->is_ipv6;
4396
4397     /* ip addresses sent in network byte order */
4398     if (a->is_ip6) {
4399         memcpy(&(a->src.ip6), mp->src_address, 16);
4400         memcpy(&(a->dst.ip6), mp->dst_address, 16);
4401     } else {
4402         memcpy(&(a->src.ip4), mp->src_address, 4);
4403         memcpy(&(a->dst.ip4), mp->dst_address, 4);
4404     }
4405
4406     a->encap_fib_index = encap_fib_index;
4407     a->decap_next_index = ntohl(mp->decap_next_index);
4408     a->vni = ntohl(mp->vni);
4409     rv = vnet_vxlan_add_del_tunnel (a, &sw_if_index);
4410
4411 out:
4412     REPLY_MACRO2(VL_API_VXLAN_ADD_DEL_TUNNEL_REPLY,
4413     ({
4414         rmp->sw_if_index = ntohl (sw_if_index);
4415     }));
4416 }
4417
4418 static void send_vxlan_tunnel_details
4419 (vxlan_tunnel_t * t, unix_shared_memory_queue_t * q, u32 context)
4420 {
4421     vl_api_vxlan_tunnel_details_t * rmp;
4422     ip4_main_t * im4 = &ip4_main;
4423     ip6_main_t * im6 = &ip6_main;
4424     u8 is_ipv6 = !(t->flags & VXLAN_TUNNEL_IS_IPV4);
4425
4426     rmp = vl_msg_api_alloc (sizeof (*rmp));
4427     memset (rmp, 0, sizeof (*rmp));
4428     rmp->_vl_msg_id = ntohs(VL_API_VXLAN_TUNNEL_DETAILS);
4429     if (is_ipv6) {
4430         memcpy(rmp->src_address, &(t->src.ip6), 16);
4431         memcpy(rmp->dst_address, &(t->dst.ip6), 16);
4432         rmp->encap_vrf_id = htonl(im6->fibs[t->encap_fib_index].table_id);
4433     } else {
4434         memcpy(rmp->src_address, &(t->src.ip4), 4);
4435         memcpy(rmp->dst_address, &(t->dst.ip4), 4);
4436         rmp->encap_vrf_id = htonl(im4->fibs[t->encap_fib_index].table_id);
4437     }
4438     rmp->vni = htonl(t->vni);
4439     rmp->decap_next_index = htonl(t->decap_next_index);
4440     rmp->sw_if_index = htonl(t->sw_if_index);
4441     rmp->is_ipv6 = is_ipv6;
4442     rmp->context = context;
4443
4444     vl_msg_api_send_shmem (q, (u8 *)&rmp);
4445 }
4446
4447 static void vl_api_vxlan_tunnel_dump_t_handler
4448 (vl_api_vxlan_tunnel_dump_t * mp)
4449 {
4450     unix_shared_memory_queue_t * q;
4451     vxlan_main_t * vxm = &vxlan_main;
4452     vxlan_tunnel_t * t;
4453     u32 sw_if_index;
4454
4455     q = vl_api_client_index_to_input_queue (mp->client_index);
4456     if (q == 0) {
4457         return;
4458     }
4459
4460     sw_if_index = ntohl(mp->sw_if_index);
4461
4462     if (~0 == sw_if_index) {
4463         pool_foreach (t, vxm->tunnels,
4464         ({
4465             send_vxlan_tunnel_details(t, q, mp->context);
4466         }));
4467     } else {
4468         if ((sw_if_index >= vec_len(vxm->tunnel_index_by_sw_if_index)) ||
4469                 (~0 == vxm->tunnel_index_by_sw_if_index[sw_if_index])) {
4470             return;
4471         }
4472         t = &vxm->tunnels[vxm->tunnel_index_by_sw_if_index[sw_if_index]];
4473         send_vxlan_tunnel_details(t, q, mp->context);
4474     }
4475 }
4476
4477 static void vl_api_gre_add_del_tunnel_t_handler
4478 (vl_api_gre_add_del_tunnel_t * mp)
4479 {
4480     vl_api_gre_add_del_tunnel_reply_t * rmp;
4481     int rv = 0;
4482     vnet_gre_add_del_tunnel_args_t _a, *a = &_a;
4483     u32 outer_table_id;
4484     uword * p;
4485     ip4_main_t * im = &ip4_main;
4486     u32 sw_if_index = ~0;
4487
4488     p = hash_get (im->fib_index_by_table_id, ntohl(mp->outer_table_id));
4489     if (! p) {
4490         rv = VNET_API_ERROR_NO_SUCH_FIB;
4491         goto out;
4492     }
4493     outer_table_id = p[0];
4494
4495     /* Check src & dst are different */
4496     if (memcmp(&mp->src_address, &mp->dst_address, 4) == 0) {
4497         rv = VNET_API_ERROR_SAME_SRC_DST;
4498         goto out;
4499     }
4500
4501     memset (a, 0, sizeof (*a));
4502
4503     a->is_add = mp->is_add;
4504
4505     /* ip addresses sent in network byte order */
4506     a->src.as_u32 = mp->src_address;
4507     a->dst.as_u32 = mp->dst_address;
4508
4509     a->outer_table_id = outer_table_id;
4510     rv = vnet_gre_add_del_tunnel (a, &sw_if_index);
4511
4512 out:
4513     REPLY_MACRO2(VL_API_GRE_ADD_DEL_TUNNEL_REPLY,
4514     ({
4515         rmp->sw_if_index = ntohl (sw_if_index);
4516     }));
4517 }
4518
4519 static void send_gre_tunnel_details
4520 (gre_tunnel_t * t, unix_shared_memory_queue_t * q, u32 context)
4521 {
4522     vl_api_gre_tunnel_details_t * rmp;
4523     ip4_main_t * im = &ip4_main;
4524
4525     rmp = vl_msg_api_alloc (sizeof (*rmp));
4526     memset (rmp, 0, sizeof (*rmp));
4527     rmp->_vl_msg_id = ntohs(VL_API_GRE_TUNNEL_DETAILS);
4528     rmp->src_address = t->tunnel_src.data_u32;
4529     rmp->dst_address = t->tunnel_dst.data_u32;
4530     rmp->outer_table_id = htonl(im->fibs[t->outer_fib_index].table_id);
4531     rmp->sw_if_index = htonl(t->sw_if_index);
4532     rmp->context = context;
4533
4534     vl_msg_api_send_shmem (q, (u8 *)&rmp);
4535 }
4536
4537 static void vl_api_gre_tunnel_dump_t_handler
4538 (vl_api_gre_tunnel_dump_t * mp)
4539 {
4540     unix_shared_memory_queue_t * q;
4541     gre_main_t * gm = &gre_main;
4542     gre_tunnel_t * t;
4543     u32 sw_if_index;
4544
4545     q = vl_api_client_index_to_input_queue (mp->client_index);
4546     if (q == 0) {
4547         return;
4548     }
4549
4550     sw_if_index = ntohl(mp->sw_if_index);
4551
4552     if (~0 == sw_if_index) {
4553         pool_foreach (t, gm->tunnels,
4554         ({
4555             send_gre_tunnel_details(t, q, mp->context);
4556         }));
4557     } else {
4558         if ((sw_if_index >= vec_len(gm->tunnel_index_by_sw_if_index)) ||
4559                 (~0 == gm->tunnel_index_by_sw_if_index[sw_if_index])) {
4560             return;
4561         }
4562         t = &gm->tunnels[gm->tunnel_index_by_sw_if_index[sw_if_index]];
4563         send_gre_tunnel_details(t, q, mp->context);
4564     }
4565 }
4566
4567 static void
4568 vl_api_l2_patch_add_del_t_handler (vl_api_l2_patch_add_del_t *mp)
4569 {
4570     extern int vnet_l2_patch_add_del (u32 rx_sw_if_index, u32 tx_sw_if_index,
4571                                       int is_add);
4572     vl_api_l2_patch_add_del_reply_t * rmp;
4573     int vnet_l2_patch_add_del (u32 rx_sw_if_index, u32 tx_sw_if_index,
4574                                int is_add);
4575     int rv = 0;
4576
4577     VALIDATE_RX_SW_IF_INDEX(mp);
4578     VALIDATE_TX_SW_IF_INDEX(mp);
4579
4580     rv = vnet_l2_patch_add_del (ntohl(mp->rx_sw_if_index),
4581                                 ntohl(mp->tx_sw_if_index),
4582                                 (int)(mp->is_add != 0));
4583
4584     BAD_RX_SW_IF_INDEX_LABEL;
4585     BAD_TX_SW_IF_INDEX_LABEL;
4586
4587     REPLY_MACRO(VL_API_L2_PATCH_ADD_DEL_REPLY);
4588 }
4589
4590 static void
4591 vl_api_vxlan_gpe_add_del_tunnel_t_handler
4592 (vl_api_vxlan_gpe_add_del_tunnel_t * mp)
4593 {
4594     vl_api_vxlan_gpe_add_del_tunnel_reply_t * rmp;
4595     int rv = 0;
4596     vnet_vxlan_gpe_add_del_tunnel_args_t _a, *a = &_a;
4597     u32 encap_fib_index, decap_fib_index;
4598     u8 protocol;
4599     uword * p;
4600     ip4_main_t * im = &ip4_main;
4601     u32 sw_if_index = ~0;
4602
4603
4604     p = hash_get (im->fib_index_by_table_id, ntohl(mp->encap_vrf_id));
4605     if (! p) {
4606         rv = VNET_API_ERROR_NO_SUCH_FIB;
4607         goto out;
4608     }
4609     encap_fib_index = p[0];
4610
4611     protocol = mp->protocol;
4612
4613     /* Interpret decap_vrf_id as an opaque if sending to other-than-ip4-input */
4614     if (protocol == VXLAN_GPE_INPUT_NEXT_IP4_INPUT) {
4615         p = hash_get (im->fib_index_by_table_id, ntohl(mp->decap_vrf_id));
4616         if (! p) {
4617             rv = VNET_API_ERROR_NO_SUCH_INNER_FIB;
4618             goto out;
4619         }
4620         decap_fib_index = p[0];
4621     } else {
4622         decap_fib_index = ntohl(mp->decap_vrf_id);
4623     }
4624
4625     /* Check src & dst are different */
4626     if ((mp->is_ipv6 && memcmp(mp->local, mp->remote, 16) == 0) ||
4627        (!mp->is_ipv6 && memcmp(mp->local, mp->remote, 4) == 0)) {
4628         rv = VNET_API_ERROR_SAME_SRC_DST;
4629         goto out;
4630     }
4631     memset (a, 0, sizeof (*a));
4632
4633     a->is_add = mp->is_add;
4634     a->is_ip6 = mp->is_ipv6;
4635     /* ip addresses sent in network byte order */
4636     if (a->is_ip6) {
4637       clib_memcpy(&(a->local.ip6), mp->local, 16);
4638       clib_memcpy(&(a->remote.ip6), mp->remote, 16);
4639     } else {
4640       clib_memcpy(&(a->local.ip4), mp->local, 4);
4641       clib_memcpy(&(a->remote.ip4), mp->remote, 4);
4642     }
4643     a->encap_fib_index = encap_fib_index;
4644     a->decap_fib_index = decap_fib_index;
4645     a->protocol = protocol;
4646     a->vni = ntohl(mp->vni);
4647     rv = vnet_vxlan_gpe_add_del_tunnel (a, &sw_if_index);
4648
4649 out:
4650     REPLY_MACRO2(VL_API_VXLAN_GPE_ADD_DEL_TUNNEL_REPLY,
4651     ({
4652         rmp->sw_if_index = ntohl (sw_if_index);
4653     }));
4654 }
4655
4656 static void send_vxlan_gpe_tunnel_details
4657 (vxlan_gpe_tunnel_t * t, unix_shared_memory_queue_t * q, u32 context)
4658 {
4659     vl_api_vxlan_gpe_tunnel_details_t * rmp;
4660     ip4_main_t * im4 = &ip4_main;
4661     ip6_main_t * im6 = &ip6_main;
4662     u8 is_ipv6 = !(t->flags & VXLAN_GPE_TUNNEL_IS_IPV4);
4663
4664     rmp = vl_msg_api_alloc (sizeof (*rmp));
4665     memset (rmp, 0, sizeof (*rmp));
4666     rmp->_vl_msg_id = ntohs(VL_API_VXLAN_GPE_TUNNEL_DETAILS);
4667     if (is_ipv6) {
4668         memcpy(rmp->local, &(t->local.ip6), 16);
4669         memcpy(rmp->remote, &(t->remote.ip6), 16);
4670         rmp->encap_vrf_id = htonl(im6->fibs[t->encap_fib_index].table_id);
4671         rmp->decap_vrf_id = htonl(im6->fibs[t->decap_fib_index].table_id);
4672     } else {
4673         memcpy(rmp->local, &(t->local.ip4), 4);
4674         memcpy(rmp->remote, &(t->remote.ip4), 4);
4675         rmp->encap_vrf_id = htonl(im4->fibs[t->encap_fib_index].table_id);
4676         rmp->decap_vrf_id = htonl(im4->fibs[t->decap_fib_index].table_id);
4677     }
4678     rmp->vni = htonl(t->vni);
4679     rmp->protocol = t->protocol;
4680     rmp->sw_if_index = htonl(t->sw_if_index);
4681     rmp->is_ipv6 = is_ipv6;
4682     rmp->context = context;
4683
4684     vl_msg_api_send_shmem (q, (u8 *)&rmp);
4685 }
4686
4687 static void vl_api_vxlan_gpe_tunnel_dump_t_handler
4688 (vl_api_vxlan_gpe_tunnel_dump_t * mp)
4689 {
4690     unix_shared_memory_queue_t * q;
4691     vxlan_gpe_main_t * vgm = &vxlan_gpe_main;
4692     vxlan_gpe_tunnel_t * t;
4693     u32 sw_if_index;
4694
4695     q = vl_api_client_index_to_input_queue (mp->client_index);
4696     if (q == 0) {
4697         return;
4698     }
4699
4700     sw_if_index = ntohl(mp->sw_if_index);
4701
4702     if (~0 == sw_if_index) {
4703         pool_foreach (t, vgm->tunnels,
4704         ({
4705             send_vxlan_gpe_tunnel_details(t, q, mp->context);
4706         }));
4707     } else {
4708         if ((sw_if_index >= vec_len(vgm->tunnel_index_by_sw_if_index)) ||
4709                 (~0 == vgm->tunnel_index_by_sw_if_index[sw_if_index])) {
4710             return;
4711         }
4712         t = &vgm->tunnels[vgm->tunnel_index_by_sw_if_index[sw_if_index]];
4713         send_vxlan_gpe_tunnel_details(t, q, mp->context);
4714     }
4715 }
4716
4717 static void
4718 vl_api_lisp_add_del_locator_set_t_handler(vl_api_lisp_add_del_locator_set_t *mp)
4719 {
4720     vl_api_lisp_add_del_locator_set_reply_t *rmp;
4721     int rv = 0;
4722     vnet_lisp_add_del_locator_set_args_t _a, *a = &_a;
4723     u32 ls_index = ~0;
4724     u8 *locator_name = NULL;
4725
4726     memset(a, 0, sizeof(a[0]));
4727
4728     locator_name = format(0, "%s", mp->locator_set_name);
4729
4730     a->name = locator_name;
4731     a->locators = NULL;
4732     a->is_add = mp->is_add;
4733     a->local = 1;
4734
4735     rv = vnet_lisp_add_del_locator_set(a, &ls_index);
4736
4737     vec_free(locator_name);
4738
4739     REPLY_MACRO(VL_API_LISP_ADD_DEL_LOCATOR_SET_REPLY);
4740 }
4741
4742 static void
4743 vl_api_lisp_add_del_locator_t_handler(
4744     vl_api_lisp_add_del_locator_t *mp)
4745 {
4746     vl_api_lisp_add_del_locator_reply_t *rmp;
4747     int rv = 0;
4748     locator_t locator, *locators = NULL;
4749     vnet_lisp_add_del_locator_set_args_t _a, *a = &_a;
4750     u32 ls_index = ~0;
4751     u8 *locator_name = NULL;
4752
4753     memset(&locator, 0, sizeof(locator));
4754     memset(a, 0, sizeof(a[0]));
4755
4756     locator.sw_if_index = ntohl(mp->sw_if_index);
4757     locator.priority = mp->priority;
4758     locator.weight = mp->weight;
4759     locator.local = 1;
4760     vec_add1(locators, locator);
4761
4762     locator_name = format(0, "%s", mp->locator_set_name);
4763
4764     a->name = locator_name;
4765     a->locators = locators;
4766     a->is_add = mp->is_add;
4767     a->local = 1;
4768
4769     rv = vnet_lisp_add_del_locator(a, NULL, &ls_index);
4770
4771     vec_free(locators);
4772     vec_free(locator_name);
4773
4774     REPLY_MACRO(VL_API_LISP_ADD_DEL_LOCATOR_REPLY);
4775 }
4776
4777 static void
4778 vl_api_lisp_add_del_local_eid_t_handler(
4779     vl_api_lisp_add_del_local_eid_t *mp)
4780 {
4781     vl_api_lisp_add_del_local_eid_reply_t *rmp;
4782     lisp_cp_main_t * lcm = vnet_lisp_cp_get_main();
4783     int rv = 0;
4784     ip_prefix_t  *prefp = NULL;
4785     ip_address_t *ip_eid = NULL;
4786     gid_address_t eid;
4787     u8 * mac = gid_address_mac (&eid);
4788     uword * p = NULL;
4789     u32 locator_set_index = ~0, map_index = ~0;
4790     vnet_lisp_add_del_mapping_args_t _a, *a = &_a;
4791     u8 *name = NULL;
4792     memset (a, 0, sizeof (a[0]));
4793     memset (&eid, 0, sizeof (eid));
4794
4795     prefp = &gid_address_ippref(&eid);
4796     ip_eid = &ip_prefix_addr(prefp);
4797
4798     switch (mp->eid_type)
4799       {
4800       case 0: /* ipv4*/
4801         gid_address_type (&eid) = GID_ADDR_IP_PREFIX;
4802         ip_address_set(ip_eid, mp->eid, IP4);
4803         ip_prefix_len(prefp) = mp->prefix_len;
4804         break;
4805       case 1: /* ipv6 */
4806         gid_address_type (&eid) = GID_ADDR_IP_PREFIX;
4807         ip_address_set(ip_eid, mp->eid, IP6);
4808         ip_prefix_len(prefp) = mp->prefix_len;
4809         break;
4810       case 2: /* l2 mac */
4811         gid_address_type (&eid) = GID_ADDR_MAC;
4812         clib_memcpy(mac, mp->eid, 6);
4813         break;
4814       default:
4815         rv = VNET_API_ERROR_INVALID_EID_TYPE;
4816         goto out;
4817       }
4818
4819     name = format(0, "%s", mp->locator_set_name);
4820     p = hash_get_mem(lcm->locator_set_index_by_name, name);
4821     if (!p) {
4822         rv = VNET_API_ERROR_INVALID_VALUE;
4823         goto out;
4824     }
4825     locator_set_index = p[0];
4826
4827   /* XXX treat batch configuration */
4828     a->is_add = mp->is_add;
4829     gid_address_vni (&eid) = clib_net_to_host_u32 (mp->vni);
4830     gid_address_copy (&a->eid, &eid);
4831     a->locator_set_index = locator_set_index;
4832     a->local = 1;
4833     rv = vnet_lisp_add_del_local_mapping(a, &map_index);
4834
4835 out:
4836     vec_free(name);
4837     gid_address_free (&a->eid);
4838
4839     REPLY_MACRO(VL_API_LISP_ADD_DEL_LOCAL_EID_REPLY);
4840 }
4841
4842 static void
4843 vl_api_lisp_eid_table_add_del_map_t_handler(
4844     vl_api_lisp_eid_table_add_del_map_t *mp)
4845 {
4846     vl_api_lisp_eid_table_add_del_map_reply_t *rmp;
4847     int rv = 0;
4848     rv = vnet_lisp_eid_table_map (clib_net_to_host_u32 (mp->vni),
4849                                   clib_net_to_host_u32 (mp->vrf), mp->is_add);
4850     REPLY_MACRO(VL_API_LISP_EID_TABLE_ADD_DEL_MAP_REPLY)
4851 }
4852
4853 static void
4854 lisp_gpe_add_del_fwd_entry_set_address(
4855     vl_api_lisp_gpe_add_del_fwd_entry_t *mp,
4856     ip_address_t                        *slocator,
4857     ip_address_t                        *dlocator,
4858     gid_address_t                       *eid)
4859 {
4860     ip_address_t *ip_eid = NULL;
4861     ip_prefix_t *prefp = NULL;
4862
4863     prefp = &gid_address_ippref(eid);
4864     ip_eid = &ip_prefix_addr(prefp);
4865
4866     if (mp->eid_is_ipv6) {
4867         clib_memcpy(&ip_addr_v6(ip_eid), mp->eid_ip_address,
4868                sizeof(ip_addr_v6(ip_eid)));
4869         ip_addr_version(ip_eid) = IP6;
4870     } else {
4871         clib_memcpy(&ip_addr_v4(ip_eid), mp->eid_ip_address,
4872                sizeof(ip_addr_v4(ip_eid)));
4873         ip_addr_version(ip_eid) = IP4;
4874     }
4875     ip_prefix_len(prefp) = mp->eid_prefix_len;
4876
4877     if (mp->address_is_ipv6) {
4878         clib_memcpy(&ip_addr_v6(slocator), mp->source_ip_address,
4879                sizeof(ip_addr_v6(slocator)));
4880         ip_addr_version(slocator) = IP6;
4881         clib_memcpy(&ip_addr_v6(dlocator), mp->destination_ip_address,
4882                sizeof(ip_addr_v6(dlocator)));
4883         ip_addr_version(dlocator) = IP6;
4884     } else {
4885         clib_memcpy(&ip_addr_v4(slocator), mp->source_ip_address,
4886                sizeof(ip_addr_v4(slocator)));
4887         ip_addr_version(slocator) = IP4;
4888         clib_memcpy(&ip_addr_v4(dlocator), mp->destination_ip_address,
4889                sizeof(ip_addr_v4(dlocator)));
4890         ip_addr_version(dlocator) = IP4;
4891     }
4892 }
4893
4894 static void
4895 vl_api_lisp_gpe_add_del_fwd_entry_t_handler(
4896     vl_api_lisp_gpe_add_del_fwd_entry_t *mp)
4897 {
4898     vl_api_lisp_gpe_add_del_fwd_entry_reply_t *rmp;
4899     int rv = 0;
4900     ip_address_t slocator, dlocator;
4901     gid_address_t eid;
4902     vnet_lisp_gpe_add_del_fwd_entry_args_t a;
4903
4904     lisp_gpe_add_del_fwd_entry_set_address(mp, &slocator, &dlocator, &eid);
4905
4906     memset (&a, 0, sizeof(a));
4907
4908     a.is_add = mp->is_add;
4909     a.deid = eid;
4910     a.slocator = slocator;
4911     a.dlocator = dlocator;
4912     rv = vnet_lisp_gpe_add_del_fwd_entry (&a, 0);
4913
4914     REPLY_MACRO(VL_API_LISP_GPE_ADD_DEL_FWD_ENTRY_REPLY);
4915 }
4916
4917 static void
4918 vl_api_lisp_add_del_map_resolver_t_handler(
4919     vl_api_lisp_add_del_map_resolver_t *mp)
4920 {
4921     vl_api_lisp_add_del_map_resolver_reply_t *rmp;
4922     int rv = 0;
4923     ip_address_t *ip_addr = NULL;
4924     vnet_lisp_add_del_map_resolver_args_t _a, * a = &_a;
4925
4926     a->is_add = mp->is_add;
4927     ip_addr = &a->address;
4928
4929     if (mp->is_ipv6) {
4930         clib_memcpy(&ip_addr_v6(ip_addr), mp->ip_address,
4931                sizeof(ip_addr_v6(ip_addr)));
4932         ip_addr_version(ip_addr) = IP6;
4933     } else {
4934         clib_memcpy(&ip_addr_v4(ip_addr), mp->ip_address,
4935                sizeof(ip_addr_v4(ip_addr)));
4936         ip_addr_version(ip_addr) = IP4;
4937     }
4938
4939     rv = vnet_lisp_add_del_map_resolver (a);
4940
4941     REPLY_MACRO(VL_API_LISP_ADD_DEL_MAP_RESOLVER_REPLY);
4942 }
4943
4944 static void
4945 vl_api_lisp_gpe_enable_disable_t_handler(
4946     vl_api_lisp_gpe_enable_disable_t *mp)
4947 {
4948     vl_api_lisp_gpe_enable_disable_reply_t *rmp;
4949     int rv = 0;
4950     vnet_lisp_gpe_enable_disable_args_t _a, * a = &_a;
4951
4952     a->is_en = mp->is_en;
4953     vnet_lisp_gpe_enable_disable (a);
4954
4955     REPLY_MACRO(VL_API_LISP_GPE_ENABLE_DISABLE_REPLY);
4956 }
4957
4958 static void
4959 vl_api_lisp_enable_disable_t_handler(
4960     vl_api_lisp_enable_disable_t *mp)
4961 {
4962     vl_api_lisp_enable_disable_reply_t *rmp;
4963     int rv = 0;
4964
4965     vnet_lisp_enable_disable (mp->is_en);
4966     REPLY_MACRO(VL_API_LISP_ENABLE_DISABLE_REPLY);
4967 }
4968
4969 static void
4970 vl_api_lisp_gpe_add_del_iface_t_handler(
4971     vl_api_lisp_gpe_add_del_iface_t *mp)
4972 {
4973     vl_api_lisp_gpe_add_del_iface_reply_t *rmp;
4974     int rv = 0;
4975     vnet_lisp_gpe_add_del_iface_args_t _a, * a = &_a;
4976
4977     a->is_add = mp->is_add;
4978     a->table_id = mp->table_id;
4979     a->vni = mp->vni;
4980     rv = vnet_lisp_gpe_add_del_iface (a, 0);
4981
4982     REPLY_MACRO(VL_API_LISP_GPE_ADD_DEL_IFACE_REPLY);
4983 }
4984
4985 static void
4986 vl_api_lisp_pitr_set_locator_set_t_handler(
4987   vl_api_lisp_pitr_set_locator_set_t *mp)
4988 {
4989     vl_api_lisp_pitr_set_locator_set_reply_t *rmp;
4990     int rv = 0;
4991     u8 * ls_name = 0;
4992
4993     ls_name = format (0, "%s", mp->ls_name);
4994     rv = vnet_lisp_pitr_set_locator_set (ls_name, mp->is_add);
4995     vec_free (ls_name);
4996
4997     REPLY_MACRO(VL_API_LISP_PITR_SET_LOCATOR_SET_REPLY);
4998 }
4999
5000 static void
5001 vl_api_lisp_add_del_map_request_itr_rlocs_t_handler
5002 (vl_api_lisp_add_del_map_request_itr_rlocs_t *mp)
5003 {
5004     vl_api_lisp_add_del_map_request_itr_rlocs_reply_t *rmp;
5005     int rv = 0;
5006     u8 * locator_set_name = NULL;
5007     vnet_lisp_add_del_mreq_itr_rloc_args_t _a, * a = &_a;
5008
5009     locator_set_name = format (0, "%s", mp->locator_set_name);
5010
5011     a->is_add = mp->is_add;
5012     a->locator_set_name = locator_set_name;
5013
5014     rv = vnet_lisp_add_del_mreq_itr_rlocs(a);
5015
5016     vec_free(locator_set_name);
5017
5018     REPLY_MACRO(VL_API_LISP_ADD_DEL_MAP_REQUEST_ITR_RLOCS_REPLY);
5019 }
5020
5021 /** Used for transferring locators via VPP API */
5022 typedef CLIB_PACKED(struct
5023 {
5024   u8 is_ip4; /**< is locator an IPv4 address */
5025   u8 addr[16]; /**< IPv4/IPv6 address */
5026 }) rloc_t;
5027
5028 static void
5029 send_lisp_locator_set_details_set_address
5030 (vl_api_lisp_locator_set_details_t *rmp,
5031  gid_address_t *gid_address)
5032 {
5033     ip_prefix_t *ip_addr;
5034
5035     if (gid_address_type(gid_address) != GID_ADDR_IP_PREFIX) {
5036         return;
5037     }
5038
5039     ip_addr = &gid_address_ippref(gid_address);
5040     rmp->prefix_len = ip_prefix_len(ip_addr);
5041     rmp->is_ipv6 = ip_prefix_version(ip_addr);
5042     ip_address_copy_addr(rmp->ip_address, &ip_prefix_addr(ip_addr));
5043 }
5044
5045 static void
5046 vl_api_lisp_add_del_remote_mapping_t_handler (
5047     vl_api_lisp_add_del_remote_mapping_t *mp)
5048 {
5049     u32 i;
5050     locator_t rloc, * rlocs = 0;
5051     vl_api_lisp_add_del_remote_mapping_reply_t * rmp;
5052     int rv = 0;
5053     gid_address_t _seid, * seid = &_seid;
5054     gid_address_t _deid, * deid = &_deid;
5055     ip_prefix_t * seid_pref = &gid_address_ippref(seid);
5056     ip_prefix_t * deid_pref = &gid_address_ippref(deid);
5057
5058     /* TODO remove seid from API */
5059     memset (seid, 0, sizeof (seid[0]));
5060     memset (deid, 0, sizeof (deid[0]));
5061     ip_address_t * seid_addr = &ip_prefix_addr(seid_pref);
5062     ip_address_t * deid_addr = &ip_prefix_addr(deid_pref);
5063     ip_prefix_len(seid_pref) = mp->seid_len;
5064     ip_prefix_len(deid_pref) = mp->deid_len;
5065     u8 * seid_mac = gid_address_mac (seid);
5066     u8 * deid_mac = gid_address_mac (deid);
5067     gid_address_vni (seid) = ntohl (mp->vni);
5068     gid_address_vni (deid) = ntohl (mp->vni);
5069
5070     switch (mp->eid_type)
5071       {
5072       case 0: /* ipv4 */
5073         gid_address_type(seid) = GID_ADDR_IP_PREFIX;
5074         gid_address_type(deid) = GID_ADDR_IP_PREFIX;
5075         ip_address_set (seid_addr, mp->seid, IP4);
5076         ip_address_set (deid_addr, mp->deid, IP4);
5077         break;
5078       case 1: /* ipv6 */
5079         gid_address_type(seid) = GID_ADDR_IP_PREFIX;
5080         gid_address_type(deid) = GID_ADDR_IP_PREFIX;
5081         ip_address_set (seid_addr, mp->seid, IP6);
5082         ip_address_set (deid_addr, mp->deid, IP6);
5083         break;
5084       case 2: /* l2 mac */
5085         gid_address_type(seid) = GID_ADDR_MAC;
5086         gid_address_type(deid) = GID_ADDR_MAC;
5087         clib_memcpy (seid_mac, mp->seid, 6);
5088         clib_memcpy (deid_mac, mp->deid, 6);
5089         break;
5090       default:
5091         rv = VNET_API_ERROR_INVALID_EID_TYPE;
5092         goto send_reply;
5093       }
5094
5095     for (i = 0; i < mp->rloc_num; i++) {
5096         rloc_t * r = &((rloc_t *) mp->rlocs)[i];
5097         memset(&rloc, 0, sizeof(rloc));
5098         ip_address_set(&gid_address_ip(&rloc.address), &r->addr,
5099                        r->is_ip4 ? IP4 : IP6);
5100         gid_address_ippref_len(&rloc.address) = r->is_ip4 ? 32: 128;
5101         gid_address_type(&rloc.address) = GID_ADDR_IP_PREFIX;
5102         /* TODO fix API to pass priority and weight */
5103         rloc.priority = 1;
5104         rloc.weight = 1;
5105         vec_add1 (rlocs, rloc);
5106     }
5107
5108     /* TODO Uncomment once https://gerrit.fd.io/r/#/c/1802 is merged and CSIT
5109      * is switched to lisp_add_del_adjacency */
5110 //    if (!mp->is_add) {
5111 //        vnet_lisp_add_del_adjacency_args_t _a, * a = &_a;
5112 //        gid_address_copy(&a->deid, deid);
5113 //        a->is_add = 0;
5114 //        rv = vnet_lisp_add_del_adjacency (a);
5115 //    } else {
5116 //        /* NOTE: for now this works as a static remote mapping, i.e.,
5117 //         * not authoritative and ttl infinite. */
5118 //        rv = vnet_lisp_add_del_mapping (deid, rlocs, mp->action, 0, ~0,
5119 //                                        mp->is_add, 0);
5120 //    }
5121
5122     /* TODO: remove once the above is merged */
5123     vnet_lisp_add_del_adjacency_args_t _a, * a = &_a;
5124     a->is_add = mp->is_add;
5125     a->authoritative = 0;
5126     a->action = mp->action;
5127     a->locators = rlocs;
5128     gid_address_copy(&a->seid, seid);
5129     gid_address_copy(&a->deid, deid);
5130     rv = vnet_lisp_add_del_adjacency (a);
5131
5132     if (mp->del_all)
5133       vnet_lisp_clear_all_remote_adjacencies ();
5134
5135     vec_free (rlocs);
5136 send_reply:
5137     REPLY_MACRO(VL_API_LISP_ADD_DEL_REMOTE_MAPPING_REPLY);
5138 }
5139
5140 static void
5141 vl_api_lisp_add_del_adjacency_t_handler (
5142     vl_api_lisp_add_del_adjacency_t *mp)
5143 {
5144     u32 i;
5145     locator_t rloc;
5146     vl_api_lisp_add_del_adjacency_reply_t * rmp;
5147     vnet_lisp_add_del_adjacency_args_t _a, * a = &_a;
5148
5149     int rv = 0;
5150     memset(a, 0, sizeof(a[0]));
5151
5152     ip_prefix_t * seid_pref = &gid_address_ippref(&a->seid);
5153     ip_prefix_t * deid_pref = &gid_address_ippref(&a->deid);
5154
5155     ip_address_t * seid_addr = &ip_prefix_addr(seid_pref);
5156     ip_address_t * deid_addr = &ip_prefix_addr(deid_pref);
5157     ip_prefix_len(seid_pref) = mp->seid_len;
5158     ip_prefix_len(deid_pref) = mp->deid_len;
5159     u8 * seid_mac = gid_address_mac (&a->seid);
5160     u8 * deid_mac = gid_address_mac (&a->deid);
5161     gid_address_vni(&a->seid) = ntohl (mp->vni);
5162     gid_address_vni(&a->deid) = ntohl (mp->vni);
5163
5164     switch (mp->eid_type)
5165       {
5166       case 0: /* ipv4 */
5167         gid_address_type(&a->seid) = GID_ADDR_IP_PREFIX;
5168         gid_address_type(&a->deid) = GID_ADDR_IP_PREFIX;
5169         ip_address_set (seid_addr, mp->seid, IP4);
5170         ip_address_set (deid_addr, mp->deid, IP4);
5171         break;
5172       case 1: /* ipv6 */
5173         gid_address_type(&a->seid) = GID_ADDR_IP_PREFIX;
5174         gid_address_type(&a->deid) = GID_ADDR_IP_PREFIX;
5175         ip_address_set (seid_addr, mp->seid, IP6);
5176         ip_address_set (deid_addr, mp->deid, IP6);
5177         break;
5178       case 2: /* l2 mac */
5179         gid_address_type(&a->seid) = GID_ADDR_MAC;
5180         gid_address_type(&a->deid) = GID_ADDR_MAC;
5181         clib_memcpy (seid_mac, mp->seid, 6);
5182         clib_memcpy (deid_mac, mp->deid, 6);
5183         break;
5184       default:
5185         rv = VNET_API_ERROR_INVALID_EID_TYPE;
5186         goto send_reply;
5187       }
5188
5189     for (i = 0; i < mp->rloc_num; i++) {
5190         rloc_t * r = &((rloc_t *) mp->rlocs)[i];
5191         memset(&rloc, 0, sizeof(rloc));
5192         ip_address_set(&gid_address_ip(&rloc.address), &r->addr,
5193                        r->is_ip4 ? IP4 : IP6);
5194         gid_address_ippref_len(&rloc.address) = r->is_ip4 ? 32: 128;
5195         gid_address_type(&rloc.address) = GID_ADDR_IP_PREFIX;
5196         /* TODO fix API to pass priority and weight */
5197         rloc.priority = 1;
5198         rloc.weight = 1;
5199         vec_add1 (a->locators, rloc);
5200     }
5201
5202     a->action = mp->action;
5203     a->is_add = mp->is_add;
5204
5205     /* NOTE: the remote mapping is static, i.e.,  not authoritative and
5206      * ttl is infinite. */
5207     a->authoritative = 0;
5208     a->ttl = ~0;
5209
5210     rv = vnet_lisp_add_del_adjacency (a);
5211
5212     vec_free (a->locators);
5213 send_reply:
5214     REPLY_MACRO(VL_API_LISP_ADD_DEL_ADJACENCY_REPLY);
5215 }
5216
5217 static void
5218 send_lisp_locator_set_details (lisp_cp_main_t *lcm,
5219                                locator_set_t *lsit,
5220                                unix_shared_memory_queue_t *q,
5221                                u32 context,
5222                                u32 index)
5223 {
5224     vl_api_lisp_locator_set_details_t *rmp;
5225     locator_t *loc = NULL;
5226     u32 * locit = NULL;
5227     u8 * str = NULL;
5228
5229     vec_foreach (locit, lsit->locator_indices) {
5230         loc = pool_elt_at_index (lcm->locator_pool, locit[0]);
5231         rmp = vl_msg_api_alloc (sizeof (*rmp));
5232         memset (rmp, 0, sizeof (*rmp));
5233         rmp->_vl_msg_id = ntohs(VL_API_LISP_LOCATOR_SET_DETAILS);
5234         rmp->local = lsit->local;
5235         if (lsit->local) {
5236             ASSERT(lsit->name != NULL);
5237             strncpy((char *) rmp->locator_set_name,
5238                     (char *) lsit->name, ARRAY_LEN(rmp->locator_set_name) - 1);
5239             rmp->sw_if_index = htonl(loc->sw_if_index);
5240         } else {
5241             str = format(0, "remote-%d", index);
5242             strncpy((char *) rmp->locator_set_name, (char *) str,
5243                     ARRAY_LEN(rmp->locator_set_name) - 1);
5244             send_lisp_locator_set_details_set_address(rmp, &loc->address);
5245
5246             vec_free(str);
5247         }
5248         rmp->priority = loc->priority;
5249         rmp->weight = loc->weight;
5250         rmp->context = context;
5251
5252         vl_msg_api_send_shmem (q, (u8 *)&rmp);
5253     }
5254 }
5255
5256 static void
5257 vl_api_lisp_locator_set_dump_t_handler (vl_api_lisp_locator_set_dump_t *mp)
5258 {
5259     unix_shared_memory_queue_t * q = NULL;
5260     lisp_cp_main_t * lcm = vnet_lisp_cp_get_main();
5261     locator_set_t * lsit = NULL;
5262     u32 index;
5263
5264     q = vl_api_client_index_to_input_queue (mp->client_index);
5265     if (q == 0) {
5266         return;
5267     }
5268
5269     index = 0;
5270     pool_foreach (lsit, lcm->locator_set_pool,
5271         ({
5272             send_lisp_locator_set_details(lcm, lsit, q, mp->context, index++);
5273         }));
5274 }
5275
5276 static void
5277 send_lisp_local_eid_table_details (mapping_t *mapit,
5278                                    unix_shared_memory_queue_t *q,
5279                                    u32 context)
5280 {
5281     vl_api_lisp_local_eid_table_details_t *rmp = NULL;
5282     lisp_cp_main_t * lcm = vnet_lisp_cp_get_main();
5283     locator_set_t *ls = NULL;
5284     gid_address_t *gid = NULL;
5285     u8 * mac = 0;
5286     ip_prefix_t *ip_prefix = NULL;
5287     u8 * str = NULL;
5288
5289     ls = pool_elt_at_index (lcm->locator_set_pool,
5290                             mapit->locator_set_index);
5291     gid = &mapit->eid;
5292     ip_prefix = &gid_address_ippref(gid);
5293     mac = gid_address_mac(gid);
5294
5295     rmp = vl_msg_api_alloc (sizeof (*rmp));
5296     memset (rmp, 0, sizeof (*rmp));
5297     rmp->_vl_msg_id = ntohs(VL_API_LISP_LOCAL_EID_TABLE_DETAILS);
5298     if (ls->local) {
5299         ASSERT(ls->name != NULL);
5300         strncpy((char *) rmp->locator_set_name,
5301                 (char *) ls->name, ARRAY_LEN(rmp->locator_set_name) - 1);
5302     } else {
5303             str = format(0, "remote-%d", mapit->locator_set_index);
5304             strncpy((char *) rmp->locator_set_name, (char *) str,
5305                     ARRAY_LEN(rmp->locator_set_name) - 1);
5306             vec_free(str);
5307     }
5308
5309     switch (gid_address_type (gid))
5310       {
5311       case GID_ADDR_IP_PREFIX:
5312         rmp->eid_prefix_len = ip_prefix_len(ip_prefix);
5313         if (ip_prefix_version(ip_prefix) == IP4)
5314           {
5315             rmp->eid_type = 0; /* ipv4 type */
5316             clib_memcpy(rmp->eid, &ip_prefix_v4(ip_prefix),
5317                    sizeof(ip_prefix_v4(ip_prefix)));
5318           }
5319         else
5320           {
5321             rmp->eid_type = 1; /* ipv6 type */
5322             clib_memcpy(rmp->eid, &ip_prefix_v6(ip_prefix),
5323                    sizeof(ip_prefix_v6(ip_prefix)));
5324           }
5325         break;
5326       case GID_ADDR_MAC:
5327         rmp->eid_type = 2; /* l2 mac type */
5328         clib_memcpy(rmp->eid, mac, 6);
5329         break;
5330       default:
5331         ASSERT(0);
5332       }
5333     rmp->context = context;
5334     rmp->vni = clib_host_to_net_u32 (gid_address_vni (gid));
5335     vl_msg_api_send_shmem (q, (u8 *)&rmp);
5336 }
5337
5338 static void
5339 vl_api_lisp_local_eid_table_dump_t_handler (
5340     vl_api_lisp_local_eid_table_dump_t *mp)
5341 {
5342     u32 mi;
5343     unix_shared_memory_queue_t * q = NULL;
5344     lisp_cp_main_t * lcm = vnet_lisp_cp_get_main();
5345     mapping_t * mapit = NULL;
5346     gid_address_t _eid, * eid = &_eid;
5347
5348     q = vl_api_client_index_to_input_queue (mp->client_index);
5349     if (q == 0) {
5350         return;
5351     }
5352
5353     if (mp->eid_set) {
5354         memset (eid, 0, sizeof (*eid));
5355         gid_address_vni(eid) = ntohl(mp->vni);
5356         switch (mp->eid_type) {
5357         case 0:
5358             gid_address_type(eid) = GID_ADDR_IP_PREFIX;
5359             gid_address_ippref_len(eid) = mp->prefix_length;
5360             gid_address_ip_version(eid) = IP4;
5361             clib_memcpy (&gid_address_ippref(eid), mp->eid, 4);
5362             break;
5363         case 1:
5364             gid_address_type(eid) = GID_ADDR_IP_PREFIX;
5365             gid_address_ippref_len(eid) = mp->prefix_length;
5366             gid_address_ip_version(eid) = IP6;
5367             clib_memcpy (&gid_address_ippref(eid), mp->eid, 16);
5368             break;
5369         case 2:
5370             gid_address_type(eid) = GID_ADDR_MAC;
5371             clib_memcpy (gid_address_mac(eid), mp->eid, 6);
5372             break;
5373         }
5374         mi = gid_dictionary_lookup (&lcm->mapping_index_by_gid, eid);
5375         if ((u32)~0 == mi)
5376           return;
5377
5378         mapit = pool_elt_at_index (lcm->mapping_pool, mi);
5379         send_lisp_local_eid_table_details(mapit, q, mp->context);
5380     } else {
5381         pool_foreach (mapit, lcm->mapping_pool,
5382         ({
5383             send_lisp_local_eid_table_details(mapit, q, mp->context);
5384         }));
5385     }
5386 }
5387
5388 static void
5389 send_lisp_gpe_tunnel_details (lisp_gpe_tunnel_t *tunnel,
5390                               unix_shared_memory_queue_t *q,
5391                               u32 context)
5392 {
5393     vl_api_lisp_gpe_tunnel_details_t *rmp;
5394     lisp_gpe_main_t * lgm = &lisp_gpe_main;
5395
5396     rmp = vl_msg_api_alloc (sizeof (*rmp));
5397     memset (rmp, 0, sizeof (*rmp));
5398     rmp->_vl_msg_id = ntohs(VL_API_LISP_GPE_TUNNEL_DETAILS);
5399
5400     rmp->tunnels = tunnel - lgm->tunnels;
5401
5402     rmp->is_ipv6 = ip_addr_version(&tunnel->src) == IP6 ? 1 : 0;
5403     ip_address_copy_addr(rmp->source_ip, &tunnel->src);
5404     ip_address_copy_addr(rmp->destination_ip, &tunnel->dst);
5405
5406     rmp->encap_fib_id = htonl(tunnel->encap_fib_index);
5407     rmp->decap_fib_id = htonl(tunnel->decap_fib_index);
5408     rmp->dcap_next = htonl(tunnel->decap_next_index);
5409     rmp->lisp_ver = tunnel->ver_res;
5410     rmp->next_protocol = tunnel->next_protocol;
5411     rmp->flags = tunnel->flags;
5412     rmp->ver_res = tunnel->ver_res;
5413     rmp->res = tunnel->res;
5414     rmp->iid = htonl(tunnel->vni);
5415     rmp->context = context;
5416
5417     vl_msg_api_send_shmem (q, (u8 *)&rmp);
5418 }
5419
5420 static void
5421 vl_api_lisp_gpe_tunnel_dump_t_handler (
5422     vl_api_lisp_gpe_tunnel_dump_t *mp)
5423 {
5424     unix_shared_memory_queue_t * q = NULL;
5425     lisp_gpe_main_t * lgm = &lisp_gpe_main;
5426     lisp_gpe_tunnel_t * tunnel = NULL;
5427
5428     if (pool_elts(lgm->tunnels) == 0) {
5429         return;
5430     }
5431
5432     q = vl_api_client_index_to_input_queue (mp->client_index);
5433     if (q == 0) {
5434         return;
5435     }
5436
5437     pool_foreach(tunnel, lgm->tunnels,
5438                  ({
5439                      send_lisp_gpe_tunnel_details(tunnel, q, mp->context);
5440                 }));
5441 }
5442
5443 static void
5444 send_lisp_map_resolver_details (ip_address_t *ip,
5445                                 unix_shared_memory_queue_t *q,
5446                                 u32 context)
5447 {
5448     vl_api_lisp_map_resolver_details_t *rmp = NULL;
5449
5450     rmp = vl_msg_api_alloc (sizeof (*rmp));
5451     memset (rmp, 0, sizeof (*rmp));
5452     rmp->_vl_msg_id = ntohs(VL_API_LISP_MAP_RESOLVER_DETAILS);
5453
5454     switch (ip_addr_version(ip)) {
5455         case IP4:
5456             rmp->is_ipv6 = 0;
5457             clib_memcpy(rmp->ip_address, &ip_addr_v4(ip), sizeof(ip_addr_v4(ip)));
5458             break;
5459
5460         case IP6:
5461             rmp->is_ipv6 = 1;
5462             clib_memcpy(rmp->ip_address, &ip_addr_v6(ip), sizeof(ip_addr_v6(ip)));
5463             break;
5464
5465         default:
5466             ASSERT(0);
5467     }
5468     rmp->context = context;
5469
5470     vl_msg_api_send_shmem (q, (u8 *)&rmp);
5471 }
5472
5473 static void
5474 vl_api_lisp_map_resolver_dump_t_handler (
5475     vl_api_lisp_map_resolver_dump_t *mp)
5476 {
5477     unix_shared_memory_queue_t * q = NULL;
5478     lisp_cp_main_t * lcm = vnet_lisp_cp_get_main();
5479     ip_address_t *ip = NULL;
5480
5481     q = vl_api_client_index_to_input_queue (mp->client_index);
5482     if (q == 0) {
5483         return;
5484     }
5485
5486     vec_foreach(ip, lcm->map_resolvers) {
5487         send_lisp_map_resolver_details(ip, q, mp->context);
5488     }
5489
5490 }
5491
5492 static void
5493 vl_api_lisp_eid_table_map_dump_t_handler (
5494     vl_api_lisp_eid_table_map_dump_t *mp)
5495 {
5496     unix_shared_memory_queue_t * q = NULL;
5497     lisp_cp_main_t * lcm = vnet_lisp_cp_get_main();
5498     hash_pair_t * p;
5499
5500     q = vl_api_client_index_to_input_queue (mp->client_index);
5501     if (q == 0) {
5502         return;
5503     }
5504     hash_foreach_pair (p, lcm->table_id_by_vni, {
5505         vl_api_lisp_eid_table_map_details_t * rmp = NULL;
5506         memset (rmp, 0, sizeof (*rmp));
5507         rmp->_vl_msg_id = ntohs(VL_API_LISP_EID_TABLE_MAP_DETAILS);
5508         rmp->vni = p->key;
5509         rmp->vrf = p->value[0];
5510         rmp->context = mp->context;
5511     });
5512 }
5513
5514 static void
5515 send_lisp_enable_disable_details (unix_shared_memory_queue_t *q,
5516                                       u32 context)
5517 {
5518     vl_api_lisp_enable_disable_status_details_t *rmp = NULL;
5519
5520     rmp = vl_msg_api_alloc (sizeof (*rmp));
5521     memset (rmp, 0, sizeof (*rmp));
5522     rmp->_vl_msg_id = ntohs(VL_API_LISP_ENABLE_DISABLE_STATUS_DETAILS);
5523
5524     rmp->gpe_status = vnet_lisp_gpe_enable_disable_status ();
5525     rmp->feature_status = vnet_lisp_enable_disable_status ();
5526     rmp->context = context;
5527
5528     vl_msg_api_send_shmem (q, (u8 *)&rmp);
5529 }
5530
5531 static void
5532 vl_api_lisp_enable_disable_status_dump_t_handler
5533 (vl_api_lisp_enable_disable_status_dump_t *mp)
5534 {
5535     unix_shared_memory_queue_t * q = NULL;
5536
5537     q = vl_api_client_index_to_input_queue (mp->client_index);
5538     if (q == 0) {
5539         return;
5540     }
5541
5542     send_lisp_enable_disable_details(q, mp->context);
5543 }
5544
5545 static void
5546 vl_api_lisp_get_map_request_itr_rlocs_t_handler (
5547     vl_api_lisp_get_map_request_itr_rlocs_t *mp)
5548 {
5549     unix_shared_memory_queue_t * q = NULL;
5550     vl_api_lisp_get_map_request_itr_rlocs_reply_t *rmp = NULL;
5551     lisp_cp_main_t * lcm = vnet_lisp_cp_get_main();
5552     locator_set_t * loc_set = 0;
5553     u8 * tmp_str = 0;
5554     int rv = 0;
5555
5556     q = vl_api_client_index_to_input_queue (mp->client_index);
5557     if (q == 0) {
5558         return;
5559     }
5560
5561     if (~0 == lcm->mreq_itr_rlocs) {
5562       tmp_str = format(0, " ");
5563     } else {
5564       loc_set = pool_elt_at_index (lcm->locator_set_pool, lcm->mreq_itr_rlocs);
5565       tmp_str = format(0, "%s", loc_set->name);
5566     }
5567
5568     REPLY_MACRO2(VL_API_LISP_GET_MAP_REQUEST_ITR_RLOCS_REPLY,
5569     ({
5570       strncpy((char *) rmp->locator_set_name, (char *) tmp_str,
5571               ARRAY_LEN(rmp->locator_set_name) - 1);
5572     }));
5573
5574     vec_free(tmp_str);
5575 }
5576
5577 static void
5578 vl_api_interface_name_renumber_t_handler (vl_api_interface_name_renumber_t *mp)
5579 {
5580     vl_api_interface_name_renumber_reply_t * rmp;
5581     int rv = 0;
5582
5583     VALIDATE_SW_IF_INDEX(mp);
5584
5585     rv = vnet_interface_name_renumber
5586         (ntohl(mp->sw_if_index), ntohl(mp->new_show_dev_instance));
5587
5588     BAD_SW_IF_INDEX_LABEL;
5589
5590     REPLY_MACRO(VL_API_INTERFACE_NAME_RENUMBER_REPLY);
5591 }
5592
5593 static int arp_change_data_callback (u32 pool_index, u8 * new_mac,
5594                                      u32 sw_if_index, u32 address)
5595 {
5596     vpe_api_main_t * am = &vpe_api_main;
5597     vlib_main_t * vm = am->vlib_main;
5598     vl_api_ip4_arp_event_t * event;
5599     static f64 arp_event_last_time;
5600     f64 now = vlib_time_now (vm);
5601
5602     if (pool_is_free_index (am->arp_events, pool_index))
5603         return 1;
5604
5605     event = pool_elt_at_index (am->arp_events, pool_index);
5606     if (memcmp (&event->new_mac, new_mac, sizeof (event->new_mac))) {
5607         clib_memcpy (event->new_mac, new_mac, sizeof(event->new_mac));
5608     } else { /* same mac */
5609         if ((sw_if_index == event->sw_if_index) &&
5610             ((address == 0) ||
5611              /* for BD case, also check IP address with 10 sec timeout */
5612              ((address == event->address) &&
5613               ((now - arp_event_last_time) < 10.0))))
5614             return 1;
5615     }
5616
5617     arp_event_last_time = now;
5618     event->sw_if_index = sw_if_index;
5619     if (address) event->address = address;
5620     return 0;
5621 }
5622
5623 static int arp_change_delete_callback (u32 pool_index, u8 * notused)
5624 {
5625     vpe_api_main_t * am = &vpe_api_main;
5626
5627     if (pool_is_free_index (am->arp_events, pool_index))
5628         return 1;
5629
5630     pool_put_index (am->arp_events, pool_index);
5631     return 0;
5632 }
5633
5634 static void
5635 vl_api_want_ip4_arp_events_t_handler
5636 (vl_api_want_ip4_arp_events_t * mp)
5637 {
5638     vpe_api_main_t * am = &vpe_api_main;
5639     vnet_main_t * vnm = vnet_get_main();
5640     vl_api_want_ip4_arp_events_reply_t *rmp;
5641     vl_api_ip4_arp_event_t * event;
5642     int rv;
5643
5644     if (mp->enable_disable) {
5645         pool_get (am->arp_events, event);
5646         memset (event, 0, sizeof (*event));
5647
5648         event->_vl_msg_id = ntohs(VL_API_IP4_ARP_EVENT);
5649         event->client_index = mp->client_index;
5650         event->context = mp->context;
5651         event->address = mp->address;
5652         event->pid = mp->pid;
5653
5654         rv = vnet_add_del_ip4_arp_change_event
5655             (vnm, arp_change_data_callback,
5656              mp->pid,
5657              &mp->address /* addr, in net byte order */,
5658              vpe_resolver_process_node.index,
5659              IP4_ARP_EVENT, event - am->arp_events, 1 /* is_add */);
5660     } else {
5661         rv = vnet_add_del_ip4_arp_change_event
5662             (vnm, arp_change_delete_callback,
5663              mp->pid,
5664              &mp->address /* addr, in net byte order */,
5665              vpe_resolver_process_node.index,
5666              IP4_ARP_EVENT, ~0 /* pool index */, 0 /* is_add */);
5667     }
5668     REPLY_MACRO(VL_API_WANT_IP4_ARP_EVENTS_REPLY);
5669 }
5670
5671 static void vl_api_input_acl_set_interface_t_handler
5672 (vl_api_input_acl_set_interface_t * mp)
5673 {
5674     vlib_main_t *vm = vlib_get_main();
5675     vl_api_input_acl_set_interface_reply_t * rmp;
5676     int rv;
5677     u32 sw_if_index, ip4_table_index, ip6_table_index, l2_table_index;
5678
5679     ip4_table_index = ntohl(mp->ip4_table_index);
5680     ip6_table_index = ntohl(mp->ip6_table_index);
5681     l2_table_index = ntohl(mp->l2_table_index);
5682     sw_if_index = ntohl(mp->sw_if_index);
5683
5684     VALIDATE_SW_IF_INDEX(mp);
5685
5686     rv = vnet_set_input_acl_intfc (vm, sw_if_index, ip4_table_index,
5687                                    ip6_table_index, l2_table_index,
5688                                    mp->is_add);
5689
5690     BAD_SW_IF_INDEX_LABEL;
5691
5692     REPLY_MACRO(VL_API_INPUT_ACL_SET_INTERFACE_REPLY);
5693 }
5694
5695 static void vl_api_ipsec_spd_add_del_t_handler
5696 (vl_api_ipsec_spd_add_del_t * mp)
5697 {
5698 #if IPSEC == 0
5699     clib_warning ("unimplemented");
5700 #else
5701
5702     vlib_main_t *vm __attribute__((unused)) = vlib_get_main();
5703     vl_api_ipsec_spd_add_del_reply_t * rmp;
5704     int rv;
5705
5706 #if DPDK > 0
5707     rv = ipsec_add_del_spd (vm, ntohl(mp->spd_id), mp->is_add);
5708 #else
5709     rv = VNET_API_ERROR_UNIMPLEMENTED;
5710 #endif
5711
5712     REPLY_MACRO(VL_API_IPSEC_SPD_ADD_DEL_REPLY);
5713 #endif
5714 }
5715
5716 static void vl_api_ipsec_interface_add_del_spd_t_handler
5717 (vl_api_ipsec_interface_add_del_spd_t * mp)
5718 {
5719     vlib_main_t *vm __attribute__((unused)) = vlib_get_main();
5720     vl_api_ipsec_interface_add_del_spd_reply_t * rmp;
5721     int rv;
5722     u32 sw_if_index __attribute__((unused));
5723     u32 spd_id __attribute__((unused));
5724
5725     sw_if_index = ntohl(mp->sw_if_index);
5726     spd_id = ntohl(mp->spd_id);
5727
5728     VALIDATE_SW_IF_INDEX(mp);
5729
5730 #if IPSEC > 0
5731     rv = ipsec_set_interface_spd(vm, sw_if_index, spd_id, mp->is_add);
5732 #else
5733     rv = VNET_API_ERROR_UNIMPLEMENTED;
5734 #endif
5735
5736     BAD_SW_IF_INDEX_LABEL;
5737
5738     REPLY_MACRO(VL_API_IPSEC_INTERFACE_ADD_DEL_SPD_REPLY);
5739 }
5740
5741 static void vl_api_ipsec_spd_add_del_entry_t_handler
5742 (vl_api_ipsec_spd_add_del_entry_t * mp)
5743 {
5744     vlib_main_t *vm __attribute__((unused)) = vlib_get_main();
5745     vl_api_ipsec_spd_add_del_entry_reply_t * rmp;
5746     int rv;
5747
5748 #if IPSEC > 0
5749     ipsec_policy_t p;
5750
5751     memset(&p, 0, sizeof(p));
5752
5753     p.id = ntohl(mp->spd_id);
5754     p.priority = ntohl(mp->priority);
5755     p.is_outbound = mp->is_outbound;
5756     p.is_ipv6 = mp->is_ipv6;
5757
5758     if (mp->is_ipv6) {
5759         clib_memcpy(&p.raddr.start, mp->remote_address_start, 16);
5760         clib_memcpy(&p.raddr.stop, mp->remote_address_stop, 16);
5761         clib_memcpy(&p.laddr.start, mp->local_address_start, 16);
5762         clib_memcpy(&p.laddr.stop, mp->local_address_stop, 16);
5763     } else {
5764         clib_memcpy(&p.raddr.start.ip4.data, mp->remote_address_start, 4);
5765         clib_memcpy(&p.raddr.stop.ip4.data, mp->remote_address_stop, 4);
5766         clib_memcpy(&p.laddr.start.ip4.data, mp->local_address_start, 4);
5767         clib_memcpy(&p.laddr.stop.ip4.data, mp->local_address_stop, 4);
5768     }
5769     p.protocol = mp->protocol;
5770     p.rport.start = ntohs(mp->remote_port_start);
5771     p.rport.stop  = ntohs(mp->remote_port_stop);
5772     p.lport.start = ntohs(mp->local_port_start);
5773     p.lport.stop  = ntohs(mp->local_port_stop);
5774     /* policy action resolve unsupported */
5775     if (mp->policy == IPSEC_POLICY_ACTION_RESOLVE) {
5776         clib_warning("unsupported action: 'resolve'");
5777         rv = VNET_API_ERROR_UNIMPLEMENTED;
5778         goto out;
5779     }
5780     p.policy = mp->policy;
5781     p.sa_id = ntohl(mp->sa_id);
5782
5783     rv = ipsec_add_del_policy(vm, &p, mp->is_add);
5784     if (rv)
5785       goto out;
5786
5787     if (mp->is_ip_any) {
5788       p.is_ipv6 = 1;
5789       rv = ipsec_add_del_policy(vm, &p, mp->is_add);
5790     }
5791 #else
5792     rv = VNET_API_ERROR_UNIMPLEMENTED;
5793     goto out;
5794 #endif
5795
5796 out:
5797     REPLY_MACRO(VL_API_IPSEC_SPD_ADD_DEL_ENTRY_REPLY);
5798 }
5799
5800 static void vl_api_ipsec_sad_add_del_entry_t_handler
5801 (vl_api_ipsec_sad_add_del_entry_t * mp)
5802 {
5803     vlib_main_t *vm __attribute__((unused)) = vlib_get_main();
5804     vl_api_ipsec_sad_add_del_entry_reply_t * rmp;
5805     int rv;
5806 #if IPSEC > 0
5807     ipsec_sa_t sa;
5808
5809     memset(&sa, 0, sizeof(sa));
5810
5811     sa.id = ntohl(mp->sad_id);
5812     sa.spi = ntohl(mp->spi);
5813     /* security protocol AH unsupported */
5814     if (mp->protocol == IPSEC_PROTOCOL_AH) {
5815         clib_warning("unsupported security protocol 'AH'");
5816         rv = VNET_API_ERROR_UNIMPLEMENTED;
5817         goto out;
5818     }
5819     sa.protocol = mp->protocol;
5820     /* check for unsupported crypto-alg */
5821     if (mp->crypto_algorithm < IPSEC_CRYPTO_ALG_AES_CBC_128 ||
5822         mp->crypto_algorithm > IPSEC_CRYPTO_ALG_AES_CBC_256) {
5823         clib_warning("unsupported crypto-alg: '%U'", format_ipsec_crypto_alg,
5824                      mp->crypto_algorithm);
5825         rv = VNET_API_ERROR_UNIMPLEMENTED;
5826         goto out;
5827     }
5828     sa.crypto_alg = mp->crypto_algorithm;
5829     sa.crypto_key_len = mp->crypto_key_length;
5830     clib_memcpy(&sa.crypto_key, mp->crypto_key, sizeof(sa.crypto_key));
5831     /* check for unsupported integ-alg */
5832     if (mp->integrity_algorithm < IPSEC_INTEG_ALG_SHA1_96 ||
5833         mp->integrity_algorithm > IPSEC_INTEG_ALG_SHA_512_256) {
5834         clib_warning("unsupported integ-alg: '%U'", format_ipsec_integ_alg,
5835                      mp->integrity_algorithm);
5836         rv = VNET_API_ERROR_UNIMPLEMENTED;
5837         goto out;
5838     }
5839     sa.integ_alg = mp->integrity_algorithm;
5840     sa.integ_key_len = mp->integrity_key_length;
5841     clib_memcpy(&sa.integ_key, mp->integrity_key, sizeof(sa.integ_key));
5842     sa.use_esn = mp->use_extended_sequence_number;
5843     sa.is_tunnel = mp->is_tunnel;
5844     sa.is_tunnel_ip6 = mp->is_tunnel_ipv6;
5845     if (sa.is_tunnel_ip6) {
5846         clib_memcpy(&sa.tunnel_src_addr, mp->tunnel_src_address, 16);
5847         clib_memcpy(&sa.tunnel_dst_addr, mp->tunnel_dst_address, 16);
5848     } else {
5849         clib_memcpy(&sa.tunnel_src_addr.ip4.data, mp->tunnel_src_address, 4);
5850         clib_memcpy(&sa.tunnel_dst_addr.ip4.data, mp->tunnel_dst_address, 4);
5851     }
5852
5853     rv = ipsec_add_del_sa(vm, &sa, mp->is_add);
5854 #else
5855     rv = VNET_API_ERROR_UNIMPLEMENTED;
5856     goto out;
5857 #endif
5858
5859 out:
5860     REPLY_MACRO(VL_API_IPSEC_SAD_ADD_DEL_ENTRY_REPLY);
5861 }
5862
5863 static void
5864 vl_api_ikev2_profile_add_del_t_handler
5865 (vl_api_ikev2_profile_add_del_t * mp)
5866 {
5867     vl_api_ikev2_profile_add_del_reply_t * rmp;
5868     int rv = 0;
5869
5870 #if IPSEC > 0
5871     vlib_main_t * vm = vlib_get_main();
5872     clib_error_t * error;
5873     u8 * tmp = format(0, "%s", mp->name);
5874     error = ikev2_add_del_profile(vm, tmp, mp->is_add);
5875     vec_free (tmp);
5876     if (error)
5877       rv = VNET_API_ERROR_UNSPECIFIED;
5878 #else
5879     rv = VNET_API_ERROR_UNIMPLEMENTED;
5880 #endif
5881
5882    REPLY_MACRO(VL_API_IKEV2_PROFILE_ADD_DEL_REPLY);
5883 }
5884
5885 static void
5886 vl_api_ikev2_profile_set_auth_t_handler
5887 (vl_api_ikev2_profile_set_auth_t * mp)
5888 {
5889     vl_api_ikev2_profile_set_auth_reply_t * rmp;
5890     int rv = 0;
5891
5892 #if IPSEC > 0
5893     vlib_main_t * vm = vlib_get_main();
5894     clib_error_t * error;
5895     u8 * tmp = format(0, "%s", mp->name);
5896     u8 * data = vec_new (u8, mp->data_len);
5897     clib_memcpy(data, mp->data, mp->data_len);
5898     error = ikev2_set_profile_auth(vm, tmp, mp->auth_method, data, mp->is_hex);
5899     vec_free (tmp);
5900     vec_free (data);
5901     if (error)
5902       rv = VNET_API_ERROR_UNSPECIFIED;
5903 #else
5904     rv = VNET_API_ERROR_UNIMPLEMENTED;
5905 #endif
5906
5907    REPLY_MACRO(VL_API_IKEV2_PROFILE_SET_AUTH_REPLY);
5908 }
5909
5910 static void
5911 vl_api_ikev2_profile_set_id_t_handler
5912 (vl_api_ikev2_profile_set_id_t * mp)
5913 {
5914     vl_api_ikev2_profile_add_del_reply_t * rmp;
5915     int rv = 0;
5916
5917 #if IPSEC > 0
5918     vlib_main_t * vm = vlib_get_main();
5919     clib_error_t * error;
5920     u8 * tmp = format(0, "%s", mp->name);
5921     u8 * data = vec_new (u8, mp->data_len);
5922     clib_memcpy(data, mp->data, mp->data_len);
5923     error = ikev2_set_profile_id(vm, tmp, mp->id_type, data, mp->is_local);
5924     vec_free (tmp);
5925     vec_free (data);
5926     if (error)
5927       rv = VNET_API_ERROR_UNSPECIFIED;
5928 #else
5929     rv = VNET_API_ERROR_UNIMPLEMENTED;
5930 #endif
5931
5932    REPLY_MACRO(VL_API_IKEV2_PROFILE_SET_ID_REPLY);
5933 }
5934
5935 static void
5936 vl_api_ikev2_profile_set_ts_t_handler
5937 (vl_api_ikev2_profile_set_ts_t * mp)
5938 {
5939     vl_api_ikev2_profile_set_ts_reply_t * rmp;
5940     int rv = 0;
5941
5942 #if IPSEC > 0
5943     vlib_main_t * vm = vlib_get_main();
5944     clib_error_t * error;
5945     u8 * tmp = format(0, "%s", mp->name);
5946     error = ikev2_set_profile_ts(vm, tmp, mp->proto, mp->start_port,
5947                                  mp->end_port, (ip4_address_t) mp->start_addr,
5948                                  (ip4_address_t) mp->end_addr, mp->is_local);
5949     vec_free (tmp);
5950     if (error)
5951       rv = VNET_API_ERROR_UNSPECIFIED;
5952 #else
5953     rv = VNET_API_ERROR_UNIMPLEMENTED;
5954 #endif
5955
5956    REPLY_MACRO(VL_API_IKEV2_PROFILE_SET_TS_REPLY);
5957 }
5958
5959 static void
5960 vl_api_ikev2_set_local_key_t_handler
5961 (vl_api_ikev2_set_local_key_t * mp)
5962 {
5963     vl_api_ikev2_profile_set_ts_reply_t * rmp;
5964     int rv = 0;
5965
5966 #if IPSEC > 0
5967     vlib_main_t * vm = vlib_get_main();
5968     clib_error_t * error;
5969
5970     error = ikev2_set_local_key(vm, mp->key_file);
5971     if (error)
5972       rv = VNET_API_ERROR_UNSPECIFIED;
5973 #else
5974     rv = VNET_API_ERROR_UNIMPLEMENTED;
5975 #endif
5976
5977    REPLY_MACRO(VL_API_IKEV2_SET_LOCAL_KEY_REPLY);
5978 }
5979
5980 static void
5981 vl_api_map_add_domain_t_handler
5982 (vl_api_map_add_domain_t * mp)
5983 {
5984   vl_api_map_add_domain_reply_t * rmp;
5985   int rv = 0;
5986   u32 index;
5987   u8 flags = mp->is_translation ? MAP_DOMAIN_TRANSLATION : 0;
5988   rv = map_create_domain((ip4_address_t *)&mp->ip4_prefix, mp->ip4_prefix_len,
5989                          (ip6_address_t *)&mp->ip6_prefix, mp->ip6_prefix_len,
5990                          (ip6_address_t *)&mp->ip6_src, mp->ip6_src_prefix_len,
5991                          mp->ea_bits_len, mp->psid_offset, mp->psid_length, &index, ntohs(mp->mtu), flags);
5992
5993   REPLY_MACRO2(VL_API_MAP_ADD_DOMAIN_REPLY,
5994                ({
5995                  rmp->index = ntohl(index);
5996                }));
5997 }
5998
5999 static void
6000 vl_api_map_del_domain_t_handler
6001 (vl_api_map_del_domain_t * mp)
6002 {
6003   vl_api_map_del_domain_reply_t * rmp;
6004   int rv = 0;
6005
6006   rv = map_delete_domain(ntohl(mp->index));
6007
6008   REPLY_MACRO(VL_API_MAP_DEL_DOMAIN_REPLY);
6009 }
6010
6011 static void
6012 vl_api_map_add_del_rule_t_handler
6013 (vl_api_map_add_del_rule_t * mp)
6014 {
6015   vl_api_map_del_domain_reply_t * rmp;
6016   int rv = 0;
6017
6018   rv = map_add_del_psid(ntohl(mp->index), ntohs(mp->psid), (ip6_address_t *)mp->ip6_dst, mp->is_add);
6019
6020   REPLY_MACRO(VL_API_MAP_ADD_DEL_RULE_REPLY);
6021 }
6022
6023 static void
6024 vl_api_map_domain_dump_t_handler
6025 (vl_api_map_domain_dump_t * mp)
6026 {
6027   vl_api_map_domain_details_t * rmp;
6028   map_main_t *mm = &map_main;
6029   map_domain_t *d;
6030   unix_shared_memory_queue_t * q;
6031
6032   if (pool_elts (mm->domains) == 0)
6033       return;
6034
6035   q = vl_api_client_index_to_input_queue (mp->client_index);
6036   if (q == 0) {
6037     return;
6038   }
6039
6040   pool_foreach(d, mm->domains, ({
6041     /* Make sure every field is initiated (or don't skip the memset()) */
6042     rmp = vl_msg_api_alloc (sizeof (*rmp));
6043     rmp->_vl_msg_id = ntohs(VL_API_MAP_DOMAIN_DETAILS);
6044     rmp->domain_index = htonl(d - mm->domains);
6045     rmp->ea_bits_len = d->ea_bits_len;
6046     rmp->psid_offset = d->psid_offset;
6047     rmp->psid_length = d->psid_length;
6048     clib_memcpy(rmp->ip4_prefix, &d->ip4_prefix, sizeof(rmp->ip4_prefix));
6049     rmp->ip4_prefix_len = d->ip4_prefix_len;
6050     clib_memcpy(rmp->ip6_prefix, &d->ip6_prefix, sizeof(rmp->ip6_prefix));
6051     rmp->ip6_prefix_len = d->ip6_prefix_len;
6052     clib_memcpy(rmp->ip6_src, &d->ip6_src, sizeof(rmp->ip6_src));
6053     rmp->ip6_src_len = d->ip6_src_len;
6054     rmp->mtu = htons(d->mtu);
6055     rmp->is_translation = (d->flags & MAP_DOMAIN_TRANSLATION);
6056     rmp->context = mp->context;
6057
6058     vl_msg_api_send_shmem (q, (u8 *)&rmp);
6059   }));
6060 }
6061
6062 static void
6063 vl_api_map_rule_dump_t_handler
6064 (vl_api_map_rule_dump_t * mp)
6065 {
6066   unix_shared_memory_queue_t * q;
6067   u16 i;
6068   ip6_address_t dst;
6069   vl_api_map_rule_details_t * rmp;
6070   map_main_t *mm = &map_main;
6071   u32 domain_index = ntohl(mp->domain_index);
6072   map_domain_t *d;
6073
6074   if (pool_elts (mm->domains) == 0)
6075    return;
6076
6077   d = pool_elt_at_index(mm->domains, domain_index);
6078   if (!d || !d->rules) {
6079     return;
6080   }
6081
6082   q = vl_api_client_index_to_input_queue (mp->client_index);
6083   if (q == 0) {
6084     return;
6085   }
6086
6087   for (i = 0; i < (0x1 << d->psid_length); i++) {
6088     dst = d->rules[i];
6089     if (dst.as_u64[0] == 0 && dst.as_u64[1] == 0) {
6090       continue;
6091     }
6092     rmp = vl_msg_api_alloc(sizeof(*rmp));
6093     memset(rmp, 0, sizeof(*rmp));
6094     rmp->_vl_msg_id = ntohs(VL_API_MAP_RULE_DETAILS);
6095     rmp->psid = htons(i);
6096     clib_memcpy(rmp->ip6_dst, &dst, sizeof(rmp->ip6_dst));
6097     rmp->context = mp->context;
6098     vl_msg_api_send_shmem(q, (u8 *)&rmp);
6099   }
6100 }
6101
6102 static void
6103 vl_api_map_summary_stats_t_handler (
6104     vl_api_map_summary_stats_t *mp)
6105 {
6106     vl_api_map_summary_stats_reply_t *rmp;
6107     vlib_combined_counter_main_t *cm;
6108     vlib_counter_t v;
6109     int i, which;
6110     u64 total_pkts[VLIB_N_RX_TX];
6111     u64 total_bytes[VLIB_N_RX_TX];
6112     map_main_t *mm = &map_main;
6113     unix_shared_memory_queue_t *q =
6114         vl_api_client_index_to_input_queue(mp->client_index);
6115
6116     if (!q)
6117         return;
6118
6119     rmp = vl_msg_api_alloc (sizeof (*rmp));
6120     rmp->_vl_msg_id = ntohs(VL_API_MAP_SUMMARY_STATS_REPLY);
6121     rmp->context = mp->context;
6122     rmp->retval = 0;
6123
6124     memset (total_pkts, 0, sizeof (total_pkts));
6125     memset (total_bytes, 0, sizeof (total_bytes));
6126
6127     map_domain_counter_lock (mm);
6128     vec_foreach(cm, mm->domain_counters) {
6129       which = cm - mm->domain_counters;
6130
6131       for (i = 0; i < vec_len(cm->maxi); i++) {
6132         vlib_get_combined_counter (cm, i, &v);
6133         total_pkts[which] += v.packets;
6134         total_bytes[which] += v.bytes;
6135       }
6136     }
6137
6138     map_domain_counter_unlock (mm);
6139
6140     /* Note: in network byte order! */
6141     rmp->total_pkts[MAP_DOMAIN_COUNTER_RX] = clib_host_to_net_u64(total_pkts[MAP_DOMAIN_COUNTER_RX]);
6142     rmp->total_bytes[MAP_DOMAIN_COUNTER_RX] = clib_host_to_net_u64(total_bytes[MAP_DOMAIN_COUNTER_RX]);
6143     rmp->total_pkts[MAP_DOMAIN_COUNTER_TX] = clib_host_to_net_u64(total_pkts[MAP_DOMAIN_COUNTER_TX]);
6144     rmp->total_bytes[MAP_DOMAIN_COUNTER_TX] = clib_host_to_net_u64(total_bytes[MAP_DOMAIN_COUNTER_TX]);
6145     rmp->total_bindings = clib_host_to_net_u64(pool_elts(mm->domains));
6146     rmp->total_ip4_fragments = 0; // Not yet implemented. Should be a simple counter.
6147     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));
6148     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));
6149
6150     vl_msg_api_send_shmem(q, (u8 *)&rmp);
6151 }
6152
6153 static void vl_api_ipsec_sa_set_key_t_handler
6154 (vl_api_ipsec_sa_set_key_t * mp)
6155 {
6156     vlib_main_t *vm __attribute__((unused)) = vlib_get_main();
6157     vl_api_ipsec_sa_set_key_reply_t *rmp;
6158     int rv;
6159 #if IPSEC > 0
6160     ipsec_sa_t sa;
6161     sa.id = ntohl(mp->sa_id);
6162     sa.crypto_key_len = mp->crypto_key_length;
6163     clib_memcpy(&sa.crypto_key, mp->crypto_key, sizeof(sa.crypto_key));
6164     sa.integ_key_len = mp->integrity_key_length;
6165     clib_memcpy(&sa.integ_key, mp->integrity_key, sizeof(sa.integ_key));
6166
6167     rv = ipsec_set_sa_key(vm, &sa);
6168 #else
6169     rv = VNET_API_ERROR_UNIMPLEMENTED;
6170 #endif
6171
6172     REPLY_MACRO(VL_API_IPSEC_SA_SET_KEY_REPLY);
6173 }
6174
6175 static void vl_api_cop_interface_enable_disable_t_handler
6176 (vl_api_cop_interface_enable_disable_t * mp)
6177 {
6178     vl_api_cop_interface_enable_disable_reply_t * rmp;
6179     int rv;
6180     u32 sw_if_index = ntohl(mp->sw_if_index);
6181     int enable_disable;
6182
6183     VALIDATE_SW_IF_INDEX(mp);
6184
6185     enable_disable = (int) mp->enable_disable;
6186
6187     rv = cop_interface_enable_disable (sw_if_index, enable_disable);
6188
6189     BAD_SW_IF_INDEX_LABEL;
6190
6191     REPLY_MACRO(VL_API_COP_INTERFACE_ENABLE_DISABLE_REPLY);
6192 }
6193
6194 static void vl_api_cop_whitelist_enable_disable_t_handler
6195 (vl_api_cop_whitelist_enable_disable_t * mp)
6196 {
6197     vl_api_cop_whitelist_enable_disable_reply_t * rmp;
6198     cop_whitelist_enable_disable_args_t _a, *a=&_a;
6199     u32 sw_if_index = ntohl(mp->sw_if_index);
6200     int rv;
6201
6202     VALIDATE_SW_IF_INDEX(mp);
6203
6204     a->sw_if_index = sw_if_index;
6205     a->ip4 = mp->ip4;
6206     a->ip6 = mp->ip6;
6207     a->default_cop = mp->default_cop;
6208     a->fib_id = ntohl(mp->fib_id);
6209
6210     rv = cop_whitelist_enable_disable (a);
6211
6212     BAD_SW_IF_INDEX_LABEL;
6213
6214     REPLY_MACRO(VL_API_COP_WHITELIST_ENABLE_DISABLE_REPLY);
6215 }
6216
6217 static void vl_api_get_node_graph_t_handler
6218 (vl_api_get_node_graph_t * mp)
6219 {
6220     int rv = 0;
6221     u8 * vector = 0;
6222     api_main_t * am = &api_main;
6223     vlib_main_t * vm = vlib_get_main();
6224     void * oldheap;
6225     vl_api_get_node_graph_reply_t * rmp;
6226
6227     pthread_mutex_lock (&am->vlib_rp->mutex);
6228     oldheap = svm_push_data_heap (am->vlib_rp);
6229
6230     /*
6231      * Keep the number of memcpy ops to a minimum (e.g. 1).
6232      */
6233     vec_validate (vector, 16384);
6234     vec_reset_length (vector);
6235
6236     /* $$$$ FIXME */
6237     vector = vlib_node_serialize (&vm->node_main, vector,
6238                                   (u32)~0 /* all threads */,
6239                                   1 /* include nexts */,
6240                                   1 /* include stats */);
6241
6242     svm_pop_heap (oldheap);
6243     pthread_mutex_unlock (&am->vlib_rp->mutex);
6244
6245     REPLY_MACRO2(VL_API_GET_NODE_GRAPH_REPLY,
6246                  rmp->reply_in_shmem = (uword) vector);
6247 }
6248
6249 static void vl_api_trace_profile_add_t_handler
6250 (vl_api_trace_profile_add_t *mp)
6251 {
6252     int rv = 0;
6253     vl_api_trace_profile_add_reply_t * rmp;
6254     clib_error_t *error;
6255
6256     /* Ignoring the profile id as currently a single profile
6257      * is supported */
6258     error = ip6_ioam_trace_profile_set(mp->trace_num_elt, mp->trace_type,
6259                                ntohl(mp->node_id), ntohl(mp->trace_app_data),
6260                                mp->pow_enable, mp->trace_tsp,
6261                                mp->trace_ppc);
6262     if (error) {
6263       clib_error_report(error);
6264       rv = clib_error_get_code(error);
6265     }
6266
6267     REPLY_MACRO(VL_API_TRACE_PROFILE_ADD_REPLY);
6268 }
6269
6270 static void vl_api_trace_profile_apply_t_handler
6271 (vl_api_trace_profile_apply_t *mp)
6272 {
6273     int rv = 0;
6274     vl_api_trace_profile_apply_reply_t * rmp;
6275
6276     if (mp->enable != 0) {
6277       rv = ip6_ioam_set_destination ((ip6_address_t *)(&mp->dest_ipv6),
6278                                 ntohl(mp->prefix_length),
6279                                 ntohl(mp->vrf_id),
6280                         mp->trace_op == IOAM_HBYH_ADD,
6281                         mp->trace_op == IOAM_HBYH_POP,
6282                         mp->trace_op == IOAM_HBYH_MOD);
6283     } else {
6284       //ip6_ioam_clear_destination(&ip6, mp->prefix_length, mp->vrf_id);
6285     }
6286     REPLY_MACRO(VL_API_TRACE_PROFILE_APPLY_REPLY);
6287 }
6288
6289 static void vl_api_trace_profile_del_t_handler
6290 (vl_api_trace_profile_del_t *mp)
6291 {
6292     int rv = 0;
6293     vl_api_trace_profile_del_reply_t * rmp;
6294     clib_error_t *error;
6295
6296     error = clear_ioam_rewrite_fn();
6297     if (error) {
6298       clib_error_report(error);
6299       rv = clib_error_get_code(error);
6300     }
6301
6302     REPLY_MACRO(VL_API_TRACE_PROFILE_DEL_REPLY);
6303 }
6304
6305 static void
6306 vl_api_af_packet_create_t_handler
6307 (vl_api_af_packet_create_t *mp)
6308 {
6309     vlib_main_t *vm = vlib_get_main();
6310     vl_api_af_packet_create_reply_t *rmp;
6311     int rv = 0;
6312     u8 *host_if_name = NULL;
6313     u32 sw_if_index;
6314
6315     host_if_name = format(0, "%s", mp->host_if_name);
6316     vec_add1 (host_if_name, 0);
6317
6318     rv = af_packet_create_if(vm, host_if_name,
6319                              mp->use_random_hw_addr ? 0 : mp->hw_addr, &sw_if_index);
6320
6321     vec_free(host_if_name);
6322
6323     REPLY_MACRO2(VL_API_AF_PACKET_CREATE_REPLY,
6324                  rmp->sw_if_index = clib_host_to_net_u32(sw_if_index));
6325 }
6326
6327 static void
6328 vl_api_af_packet_delete_t_handler
6329 (vl_api_af_packet_delete_t *mp)
6330 {
6331     vlib_main_t * vm = vlib_get_main();
6332     vl_api_af_packet_delete_reply_t *rmp;
6333     int rv = 0;
6334     u8 *host_if_name = NULL;
6335
6336     host_if_name = format(0, "%s", mp->host_if_name);
6337     vec_add1 (host_if_name, 0);
6338
6339     rv = af_packet_delete_if(vm, host_if_name);
6340
6341     vec_free(host_if_name);
6342
6343     REPLY_MACRO(VL_API_AF_PACKET_DELETE_REPLY);
6344 }
6345
6346 static void
6347 vl_api_policer_add_del_t_handler
6348 (vl_api_policer_add_del_t *mp)
6349 {
6350     vlib_main_t * vm = vlib_get_main();
6351     vl_api_policer_add_del_reply_t *rmp;
6352     int rv = 0;
6353     u8 *name = NULL;
6354     sse2_qos_pol_cfg_params_st cfg;
6355     clib_error_t * error;
6356
6357     name = format(0, "%s", mp->name);
6358
6359     memset (&cfg, 0, sizeof (cfg));
6360     cfg.rfc = mp->type;
6361     cfg.rnd_type = mp->round_type;
6362     cfg.rate_type = mp->rate_type;
6363     cfg.rb.kbps.cir_kbps = mp->cir;
6364     cfg.rb.kbps.eir_kbps = mp->eir;
6365     cfg.rb.kbps.cb_bytes = mp->cb;
6366     cfg.rb.kbps.eb_bytes = mp->eb;
6367
6368     error = policer_add_del(vm, name, &cfg, mp->is_add);
6369
6370     if (error)
6371       rv = VNET_API_ERROR_UNSPECIFIED;
6372
6373     REPLY_MACRO(VL_API_POLICER_ADD_DEL_REPLY);
6374 }
6375
6376 static void
6377 send_policer_details (u8 *name,
6378                       sse2_qos_pol_cfg_params_st *config,
6379                       policer_read_response_type_st *templ,
6380                       unix_shared_memory_queue_t *q,
6381                       u32 context)
6382 {
6383     vl_api_policer_details_t * mp;
6384
6385     mp = vl_msg_api_alloc (sizeof (*mp));
6386     memset (mp, 0, sizeof (*mp));
6387     mp->_vl_msg_id = ntohs (VL_API_POLICER_DETAILS);
6388     mp->context = context;
6389     mp->cir = htonl(config->rb.kbps.cir_kbps);
6390     mp->eir = htonl(config->rb.kbps.eir_kbps);
6391     mp->cb = htonl(config->rb.kbps.cb_bytes);
6392     mp->eb = htonl(config->rb.kbps.eb_bytes);
6393     mp->rate_type = config->rate_type;
6394     mp->round_type = config->rnd_type;
6395     mp->type = config->rfc;
6396     mp->single_rate = templ->single_rate ? 1 : 0;
6397     mp->color_aware = templ->color_aware ? 1 : 0;
6398     mp->scale = htonl(templ->scale);
6399     mp->cir_tokens_per_period = htonl(templ->cir_tokens_per_period);
6400     mp->pir_tokens_per_period = htonl(templ->pir_tokens_per_period);
6401     mp->current_limit = htonl(templ->current_limit);
6402     mp->current_bucket = htonl(templ->current_bucket);
6403     mp->extended_limit = htonl(templ->extended_limit);
6404     mp->extended_bucket = htonl(templ->extended_bucket);
6405     mp->last_update_time = clib_host_to_net_u64(templ->last_update_time);
6406
6407     strncpy ((char *) mp->name, (char *) name, ARRAY_LEN(mp->name) - 1);
6408
6409     vl_msg_api_send_shmem (q, (u8 *)&mp);
6410 }
6411
6412 static void
6413 vl_api_policer_dump_t_handler
6414 (vl_api_policer_dump_t *mp)
6415 {
6416     unix_shared_memory_queue_t * q;
6417     vnet_policer_main_t * pm = &vnet_policer_main;
6418     hash_pair_t * hp;
6419     uword * p;
6420     u32 pool_index;
6421     u8 * match_name = 0;
6422     u8 * name;
6423     sse2_qos_pol_cfg_params_st *config;
6424     policer_read_response_type_st *templ;
6425
6426     q = vl_api_client_index_to_input_queue (mp->client_index);
6427     if (q == 0)
6428         return;
6429
6430     if (mp->match_name_valid) {
6431         match_name = format(0, "%s%c", mp->match_name, 0);
6432     }
6433
6434     if (mp->match_name_valid) {
6435         p = hash_get_mem (pm->policer_config_by_name, match_name);
6436         if (p) {
6437             pool_index = p[0];
6438             config = pool_elt_at_index (pm->configs, pool_index);
6439             templ = pool_elt_at_index (pm->policer_templates, pool_index);
6440             send_policer_details(match_name, config, templ, q, mp->context);
6441         }
6442     } else {
6443         hash_foreach_pair (hp, pm->policer_config_by_name,
6444         ({
6445             name = (u8 *) hp->key;
6446             pool_index = hp->value[0];
6447             config = pool_elt_at_index (pm->configs, pool_index);
6448             templ = pool_elt_at_index (pm->policer_templates, pool_index);
6449             send_policer_details(name, config, templ, q, mp->context);
6450         }));
6451     }
6452 }
6453
6454 static void
6455 vl_api_netmap_create_t_handler
6456 (vl_api_netmap_create_t *mp)
6457 {
6458     vlib_main_t *vm = vlib_get_main();
6459     vl_api_netmap_create_reply_t *rmp;
6460     int rv = 0;
6461     u8 *if_name = NULL;
6462
6463     if_name = format(0, "%s", mp->netmap_if_name);
6464     vec_add1 (if_name, 0);
6465
6466     rv = netmap_create_if(vm, if_name, mp->use_random_hw_addr ? 0 : mp->hw_addr,
6467                           mp->is_pipe, mp->is_master, 0);
6468
6469     vec_free(if_name);
6470
6471     REPLY_MACRO(VL_API_NETMAP_CREATE_REPLY);
6472 }
6473
6474 static void
6475 vl_api_netmap_delete_t_handler
6476 (vl_api_netmap_delete_t *mp)
6477 {
6478     vlib_main_t * vm = vlib_get_main();
6479     vl_api_netmap_delete_reply_t *rmp;
6480     int rv = 0;
6481     u8 *if_name = NULL;
6482
6483     if_name = format(0, "%s", mp->netmap_if_name);
6484     vec_add1 (if_name, 0);
6485
6486     rv = netmap_delete_if(vm, if_name);
6487
6488     vec_free(if_name);
6489
6490     REPLY_MACRO(VL_API_NETMAP_DELETE_REPLY);
6491 }
6492
6493 static void vl_api_mpls_gre_tunnel_details_t_handler (
6494     vl_api_mpls_gre_tunnel_details_t * mp)
6495 {
6496     clib_warning ("BUG");
6497 }
6498
6499 static void send_mpls_gre_tunnel_entry (vpe_api_main_t * am,
6500                                     unix_shared_memory_queue_t *q,
6501                                     mpls_gre_tunnel_t * gt,
6502                                     u32 index,
6503                                     u32 context)
6504 {
6505     vl_api_mpls_gre_tunnel_details_t * mp;
6506
6507     mp = vl_msg_api_alloc (sizeof (*mp));
6508     memset (mp, 0, sizeof (*mp));
6509     mp->_vl_msg_id = ntohs(VL_API_MPLS_GRE_TUNNEL_DETAILS);
6510     mp->context = context;
6511
6512     if (gt != NULL) {
6513         mp->tunnel_index    = htonl(index);
6514         mp->tunnel_src      = gt->tunnel_src.as_u32;
6515         mp->tunnel_dst      = gt->tunnel_dst.as_u32;
6516         mp->intfc_address   = gt->intfc_address.as_u32;
6517         mp->mask_width      = htonl(gt->mask_width);
6518         mp->inner_fib_index = htonl(gt->inner_fib_index);
6519         mp->outer_fib_index = htonl(gt->outer_fib_index);
6520         mp->encap_index     = htonl(gt->encap_index);
6521         mp->hw_if_index     = htonl(gt->hw_if_index);
6522         mp->l2_only         = htonl(gt->l2_only);
6523     }
6524
6525     mpls_main_t * mm = &mpls_main;
6526     mpls_encap_t * e;
6527     int i;
6528     u32 len = 0;
6529
6530     e = pool_elt_at_index (mm->encaps, gt->encap_index);
6531     len = vec_len (e->labels);
6532     mp->nlabels = htonl(len);
6533
6534     for (i = 0; i < len; i++) {
6535         mp->labels[i] = htonl(vnet_mpls_uc_get_label(
6536                 clib_host_to_net_u32(e->labels[i].label_exp_s_ttl)));
6537     }
6538
6539     vl_msg_api_send_shmem (q, (u8 *)&mp);
6540 }
6541
6542 static void
6543 vl_api_mpls_gre_tunnel_dump_t_handler (vl_api_mpls_gre_tunnel_dump_t *mp)
6544 {
6545     vpe_api_main_t * am = &vpe_api_main;
6546     unix_shared_memory_queue_t * q;
6547     vlib_main_t * vm = &vlib_global_main;
6548     mpls_main_t * mm = &mpls_main;
6549     mpls_gre_tunnel_t * gt;
6550     u32 index = ntohl(mp->tunnel_index);
6551
6552     q = vl_api_client_index_to_input_queue (mp->client_index);
6553     if (q == 0)
6554         return;
6555
6556     if (pool_elts (mm->gre_tunnels)) {
6557         if(mp->tunnel_index >= 0) {
6558             vlib_cli_output (vm, "MPLS-GRE tunnel %u", index);
6559             gt = pool_elt_at_index (mm->gre_tunnels, index);
6560             send_mpls_gre_tunnel_entry (am, q, gt, gt - mm->gre_tunnels, mp->context);
6561         } else {
6562             vlib_cli_output (vm, "MPLS-GRE tunnels");
6563             pool_foreach (gt, mm->gre_tunnels,
6564             ({
6565               send_mpls_gre_tunnel_entry (am, q, gt, gt - mm->gre_tunnels, mp->context);
6566             }));
6567         }
6568     } else {
6569         vlib_cli_output (vm, "No MPLS-GRE tunnels");
6570     }
6571 }
6572
6573 static void vl_api_mpls_eth_tunnel_details_t_handler (
6574     vl_api_mpls_eth_tunnel_details_t * mp)
6575 {
6576     clib_warning ("BUG");
6577 }
6578
6579 static void send_mpls_eth_tunnel_entry (vpe_api_main_t * am,
6580                                     unix_shared_memory_queue_t *q,
6581                                     mpls_eth_tunnel_t * et,
6582                                     u32 index,
6583                                     u32 context)
6584 {
6585     vl_api_mpls_eth_tunnel_details_t * mp;
6586
6587     mp = vl_msg_api_alloc (sizeof (*mp));
6588     memset (mp, 0, sizeof (*mp));
6589     mp->_vl_msg_id = ntohs(VL_API_MPLS_ETH_TUNNEL_DETAILS);
6590     mp->context = context;
6591
6592     if (et != NULL) {
6593         mp->tunnel_index    = htonl(index);
6594         memcpy(mp->tunnel_dst_mac, et->tunnel_dst, 6);
6595         mp->intfc_address   = et->intfc_address.as_u32;
6596         mp->tx_sw_if_index  = htonl(et->tx_sw_if_index);
6597         mp->inner_fib_index = htonl(et->inner_fib_index);
6598         mp->mask_width      = htonl(et->mask_width);
6599         mp->encap_index     = htonl(et->encap_index);
6600         mp->hw_if_index     = htonl(et->hw_if_index);
6601         mp->l2_only         = htonl(et->l2_only);
6602     }
6603
6604     mpls_main_t * mm = &mpls_main;
6605     mpls_encap_t * e;
6606     int i;
6607     u32 len = 0;
6608
6609     e = pool_elt_at_index (mm->encaps, et->encap_index);
6610     len = vec_len (e->labels);
6611     mp->nlabels = htonl(len);
6612
6613     for (i = 0; i < len; i++) {
6614         mp->labels[i] = htonl(vnet_mpls_uc_get_label(
6615                 clib_host_to_net_u32(e->labels[i].label_exp_s_ttl)));
6616     }
6617
6618     vl_msg_api_send_shmem (q, (u8 *)&mp);
6619 }
6620
6621 static void
6622 vl_api_mpls_eth_tunnel_dump_t_handler (vl_api_mpls_eth_tunnel_dump_t *mp)
6623 {
6624     vpe_api_main_t * am = &vpe_api_main;
6625     unix_shared_memory_queue_t * q;
6626     vlib_main_t * vm = &vlib_global_main;
6627     mpls_main_t * mm = &mpls_main;
6628     mpls_eth_tunnel_t * et;
6629     u32 index = ntohl(mp->tunnel_index);
6630
6631     q = vl_api_client_index_to_input_queue (mp->client_index);
6632     if (q == 0)
6633         return;
6634
6635     clib_warning("Received mpls_eth_tunnel_dump");
6636     clib_warning("Received tunnel index: %u from client %u", index, mp->client_index);
6637
6638     if (pool_elts (mm->eth_tunnels)) {
6639         if(mp->tunnel_index >= 0) {
6640             vlib_cli_output (vm, "MPLS-Ethernet tunnel %u", index);
6641             et = pool_elt_at_index (mm->eth_tunnels, index);
6642             send_mpls_eth_tunnel_entry (am, q, et, et - mm->eth_tunnels, mp->context);
6643         } else {
6644             clib_warning("MPLS-Ethernet tunnels");
6645             pool_foreach (et, mm->eth_tunnels,
6646             ({
6647                 send_mpls_eth_tunnel_entry (am, q, et, et - mm->eth_tunnels, mp->context);
6648             }));
6649         }
6650     } else {
6651         clib_warning("No MPLS-Ethernet tunnels");
6652     }
6653 }
6654
6655 static void vl_api_mpls_fib_encap_details_t_handler (
6656     vl_api_mpls_fib_encap_details_t * mp)
6657 {
6658     clib_warning ("BUG");
6659 }
6660
6661 static void send_mpls_fib_encap_details (vpe_api_main_t * am,
6662                                     unix_shared_memory_queue_t *q,
6663                                     show_mpls_fib_t *s,
6664                                     u32 context)
6665 {
6666     vl_api_mpls_fib_encap_details_t * mp;
6667
6668     mp = vl_msg_api_alloc (sizeof (*mp));
6669     memset (mp, 0, sizeof (*mp));
6670     mp->_vl_msg_id = ntohs(VL_API_MPLS_FIB_ENCAP_DETAILS);
6671     mp->context = context;
6672
6673     mp->fib_index   = htonl(s->fib_index);
6674     mp->entry_index = htonl(s->entry_index);
6675     mp->dest        = s->dest;
6676     mp->s_bit       = htonl(s->s_bit);
6677
6678     mpls_main_t * mm = &mpls_main;
6679     mpls_encap_t * e;
6680     int i;
6681     u32 len = 0;
6682
6683     e = pool_elt_at_index (mm->encaps, s->entry_index);
6684     len = vec_len (e->labels);
6685     mp->nlabels = htonl(len);
6686
6687     for (i = 0; i < len; i++) {
6688         mp->labels[i] = htonl(vnet_mpls_uc_get_label(
6689                 clib_host_to_net_u32(e->labels[i].label_exp_s_ttl)));
6690     }
6691
6692     vl_msg_api_send_shmem (q, (u8 *)&mp);
6693 }
6694
6695 static void
6696 vl_api_mpls_fib_encap_dump_t_handler (vl_api_mpls_fib_encap_dump_t *mp)
6697 {
6698     vpe_api_main_t * am = &vpe_api_main;
6699     unix_shared_memory_queue_t * q;
6700     vlib_main_t * vm = &vlib_global_main;
6701     u64 key;
6702     u32 value;
6703     show_mpls_fib_t *records = 0;
6704     show_mpls_fib_t *s;
6705     mpls_main_t * mm = &mpls_main;
6706     ip4_main_t * im = &ip4_main;
6707     ip4_fib_t * rx_fib;
6708
6709     q = vl_api_client_index_to_input_queue (mp->client_index);
6710     if (q == 0)
6711         return;
6712
6713     hash_foreach (key, value, mm->mpls_encap_by_fib_and_dest,
6714     ({
6715         vec_add2 (records, s, 1);
6716         s->fib_index = (u32)(key>>32);
6717         s->dest = (u32)(key & 0xFFFFFFFF);
6718         s->entry_index = (u32) value;
6719     }));
6720
6721     if (0 == vec_len(records)) {
6722         vlib_cli_output(vm, "MPLS encap table empty");
6723         goto out;
6724     }
6725
6726     /* sort output by dst address within fib */
6727     vec_sort_with_function(records, mpls_dest_cmp);
6728     vec_sort_with_function(records, mpls_fib_index_cmp);
6729     vlib_cli_output(vm, "MPLS encap table");
6730     vlib_cli_output(vm, "%=6s%=16s%=16s", "Table", "Dest address", "Labels");
6731     vec_foreach (s, records)
6732     {
6733         rx_fib = vec_elt_at_index(im->fibs, s->fib_index);
6734         vlib_cli_output(vm, "%=6d%=16U%=16U", rx_fib->table_id,
6735                 format_ip4_address, &s->dest, format_mpls_encap_index, mm,
6736                 s->entry_index);
6737         send_mpls_fib_encap_details (am, q, s, mp->context);
6738     }
6739
6740 out:
6741     vec_free(records);
6742 }
6743
6744 static void vl_api_mpls_fib_decap_details_t_handler (
6745     vl_api_mpls_fib_decap_details_t * mp)
6746 {
6747     clib_warning ("BUG");
6748 }
6749
6750 static void send_mpls_fib_decap_details (vpe_api_main_t * am,
6751                                     unix_shared_memory_queue_t *q,
6752                                     show_mpls_fib_t *s,
6753                                     u32 rx_table_id,
6754                                     u32 tx_table_id,
6755                                     char *swif_tag,
6756                                     u32 context)
6757 {
6758     vl_api_mpls_fib_decap_details_t * mp;
6759
6760     mp = vl_msg_api_alloc (sizeof (*mp));
6761     memset (mp, 0, sizeof (*mp));
6762     mp->_vl_msg_id = ntohs(VL_API_MPLS_FIB_DECAP_DETAILS);
6763     mp->context = context;
6764
6765     mp->fib_index   = htonl(s->fib_index);
6766     mp->entry_index = htonl(s->entry_index);
6767     mp->dest        = s->dest;
6768     mp->s_bit       = htonl(s->s_bit);
6769     mp->label       = htonl(s->label);
6770     mp->rx_table_id = htonl(rx_table_id);
6771     mp->tx_table_id = htonl(tx_table_id);
6772     strncpy ((char *) mp->swif_tag,
6773              (char *) swif_tag, ARRAY_LEN(mp->swif_tag)-1);
6774
6775     vl_msg_api_send_shmem (q, (u8 *)&mp);
6776 }
6777
6778 static void
6779 vl_api_mpls_fib_decap_dump_t_handler (vl_api_mpls_fib_decap_dump_t *mp)
6780 {
6781     vpe_api_main_t * am = &vpe_api_main;
6782     unix_shared_memory_queue_t * q;
6783     vlib_main_t * vm = &vlib_global_main;
6784     u64 key;
6785     u32 value;
6786     show_mpls_fib_t *records = 0;
6787     show_mpls_fib_t *s;
6788     mpls_main_t * mm = &mpls_main;
6789     ip4_main_t * im = &ip4_main;
6790     ip4_fib_t * rx_fib;
6791     ip4_fib_t *tx_fib;
6792     u32 tx_table_id;
6793     char *swif_tag;
6794
6795     q = vl_api_client_index_to_input_queue (mp->client_index);
6796     if (q == 0)
6797         return;
6798
6799     hash_foreach (key, value, mm->mpls_decap_by_rx_fib_and_label,
6800     ({
6801         vec_add2 (records, s, 1);
6802         s->fib_index = (u32)(key>>32);
6803         s->entry_index = (u32) value;
6804         s->label = ((u32) key)>>12;
6805         s->s_bit = (key & (1<<8)) != 0;
6806     }));
6807
6808     if (!vec_len(records)) {
6809         vlib_cli_output(vm, "MPLS decap table empty");
6810         goto out;
6811     }
6812
6813     vec_sort_with_function(records, mpls_label_cmp);
6814     vlib_cli_output(vm, "MPLS decap table");
6815     vlib_cli_output(vm, "%=10s%=15s%=6s%=6s", "RX Table", "TX Table/Intfc",
6816             "Label", "S-bit");
6817     vec_foreach (s, records)
6818     {
6819         mpls_decap_t * d;
6820         d = pool_elt_at_index(mm->decaps, s->entry_index);
6821         if (d->next_index == MPLS_INPUT_NEXT_IP4_INPUT) {
6822             tx_fib = vec_elt_at_index(im->fibs, d->tx_fib_index);
6823             tx_table_id = tx_fib->table_id;
6824             swif_tag = "     ";
6825         } else {
6826             tx_table_id = d->tx_fib_index;
6827             swif_tag = "(i)  ";
6828         }
6829         rx_fib = vec_elt_at_index(im->fibs, s->fib_index);
6830
6831         vlib_cli_output(vm, "%=10d%=10d%=5s%=6d%=6d", rx_fib->table_id,
6832                 tx_table_id, swif_tag, s->label, s->s_bit);
6833
6834         send_mpls_fib_decap_details (am, q, s, rx_fib->table_id,
6835                 tx_table_id, swif_tag, mp->context);
6836     }
6837
6838 out:
6839     vec_free(records);
6840 }
6841
6842 static void vl_api_classify_table_ids_t_handler (vl_api_classify_table_ids_t *mp)
6843 {
6844     unix_shared_memory_queue_t * q;
6845
6846     q = vl_api_client_index_to_input_queue (mp->client_index);
6847     if (q == 0)
6848         return;
6849
6850     vnet_classify_main_t * cm = &vnet_classify_main;
6851     vnet_classify_table_t * t;
6852     u32 * table_ids = 0;
6853     u32 count;
6854
6855     pool_foreach (t, cm->tables,
6856     ({
6857         vec_add1 (table_ids, ntohl(t - cm->tables));
6858     }));
6859     count = vec_len(table_ids);
6860
6861     vl_api_classify_table_ids_reply_t *rmp;
6862     rmp = vl_msg_api_alloc_as_if_client(sizeof (*rmp) + count);
6863     rmp->_vl_msg_id = ntohs (VL_API_CLASSIFY_TABLE_IDS_REPLY);
6864     rmp->context = mp->context;
6865     rmp->count = ntohl(count);
6866     clib_memcpy(rmp->ids, table_ids, count * sizeof(u32));
6867     rmp->retval = 0;
6868
6869     vl_msg_api_send_shmem (q, (u8 *)&rmp);
6870
6871     vec_free (table_ids);
6872 }
6873
6874 static void vl_api_classify_table_by_interface_t_handler (vl_api_classify_table_by_interface_t *mp)
6875 {
6876     vl_api_classify_table_by_interface_reply_t *rmp;
6877     int rv = 0;
6878
6879     u32 sw_if_index = ntohl(mp->sw_if_index);
6880     u32 * acl = 0;
6881
6882     vec_validate (acl, INPUT_ACL_N_TABLES - 1);
6883     vec_set (acl, ~0);
6884
6885     VALIDATE_SW_IF_INDEX(mp);
6886
6887     input_acl_main_t * am = &input_acl_main;
6888
6889     int if_idx;
6890     u32 type;
6891
6892     for (type = 0; type < INPUT_ACL_N_TABLES; type++)
6893     {
6894         u32 * vec_tbl = am->classify_table_index_by_sw_if_index[type];
6895                 if (vec_len(vec_tbl)) {
6896                         for (if_idx = 0; if_idx < vec_len (vec_tbl); if_idx++)
6897                         {
6898                             if (vec_elt(vec_tbl, if_idx) == ~0 || sw_if_index != if_idx) {
6899                                     continue;
6900                             }
6901                             acl[type] = vec_elt(vec_tbl, if_idx);
6902                         }
6903                 }
6904     }
6905
6906     BAD_SW_IF_INDEX_LABEL;
6907
6908     REPLY_MACRO2(VL_API_CLASSIFY_TABLE_BY_INTERFACE_REPLY,
6909     ({
6910        rmp->sw_if_index = ntohl(sw_if_index);
6911        rmp->l2_table_id = ntohl(acl[INPUT_ACL_TABLE_L2]);
6912        rmp->ip4_table_id = ntohl(acl[INPUT_ACL_TABLE_IP4]);
6913        rmp->ip6_table_id = ntohl(acl[INPUT_ACL_TABLE_IP6]);
6914     }));
6915     vec_free(acl);
6916 }
6917
6918 static void vl_api_classify_table_info_t_handler (vl_api_classify_table_info_t *mp)
6919 {
6920     unix_shared_memory_queue_t * q;
6921
6922     q = vl_api_client_index_to_input_queue (mp->client_index);
6923     if (q == 0)
6924         return;
6925
6926     vl_api_classify_table_info_reply_t *rmp = 0;
6927
6928     vnet_classify_main_t * cm = &vnet_classify_main;
6929     u32 table_id = ntohl(mp->table_id);
6930     vnet_classify_table_t * t;
6931
6932     pool_foreach (t, cm->tables,
6933     ({
6934         if (table_id == t - cm->tables) {
6935             rmp = vl_msg_api_alloc_as_if_client(sizeof (*rmp) + t->match_n_vectors * sizeof (u32x4));
6936             rmp->_vl_msg_id = ntohs (VL_API_CLASSIFY_TABLE_INFO_REPLY);
6937             rmp->context = mp->context;
6938             rmp->table_id = ntohl(table_id);
6939             rmp->nbuckets = ntohl(t->nbuckets);
6940             rmp->match_n_vectors = ntohl(t->match_n_vectors);
6941             rmp->skip_n_vectors = ntohl(t->skip_n_vectors);
6942             rmp->active_sessions = ntohl(t->active_elements);
6943             rmp->next_table_index = ntohl(t->next_table_index);
6944             rmp->miss_next_index = ntohl(t->miss_next_index);
6945             rmp->mask_length = ntohl(t->match_n_vectors * sizeof (u32x4));
6946             clib_memcpy(rmp->mask, t->mask, t->match_n_vectors * sizeof(u32x4));
6947             rmp->retval = 0;
6948             break;
6949         }
6950     }));
6951
6952     if (rmp == 0) {
6953         rmp = vl_msg_api_alloc (sizeof (*rmp));
6954         rmp->_vl_msg_id = ntohs((VL_API_CLASSIFY_TABLE_INFO_REPLY));
6955         rmp->context = mp->context;
6956         rmp->retval = ntohl(VNET_API_ERROR_CLASSIFY_TABLE_NOT_FOUND);
6957     }
6958
6959     vl_msg_api_send_shmem (q, (u8 *)&rmp);
6960 }
6961
6962 static void vl_api_classify_session_details_t_handler (vl_api_classify_session_details_t * mp)
6963 {
6964     clib_warning ("BUG");
6965 }
6966
6967 static void send_classify_session_details (unix_shared_memory_queue_t * q,
6968                                            u32 table_id,
6969                                            u32 match_length,
6970                                            vnet_classify_entry_t * e,
6971                                            u32 context)
6972 {
6973     vl_api_classify_session_details_t *rmp;
6974
6975     rmp = vl_msg_api_alloc (sizeof (*rmp));
6976     memset (rmp, 0, sizeof (*rmp));
6977     rmp->_vl_msg_id = ntohs(VL_API_CLASSIFY_SESSION_DETAILS);
6978     rmp->context = context;
6979     rmp->table_id = ntohl(table_id);
6980     rmp->hit_next_index = ntohl(e->next_index);
6981     rmp->advance = ntohl(e->advance);
6982     rmp->opaque_index = ntohl(e->opaque_index);
6983     rmp->match_length = ntohl(match_length);
6984     clib_memcpy(rmp->match, e->key, match_length);
6985
6986     vl_msg_api_send_shmem (q, (u8 *)&rmp);
6987 }
6988
6989 static void vl_api_classify_session_dump_t_handler (vl_api_classify_session_dump_t *mp)
6990 {
6991     vnet_classify_main_t * cm = &vnet_classify_main;
6992     unix_shared_memory_queue_t * q;
6993
6994     u32 table_id = ntohl(mp->table_id);
6995     vnet_classify_table_t * t;
6996
6997     q = vl_api_client_index_to_input_queue (mp->client_index);
6998
6999     pool_foreach (t, cm->tables,
7000     ({
7001         if (table_id == t - cm->tables) {
7002             vnet_classify_bucket_t * b;
7003             vnet_classify_entry_t * v, * save_v;
7004             int i, j, k;
7005
7006             for (i = 0; i < t->nbuckets; i++)
7007             {
7008                 b = &t->buckets [i];
7009                 if (b->offset == 0)
7010                    continue;
7011
7012                 save_v = vnet_classify_get_entry (t, b->offset);
7013                 for (j = 0; j < (1<<b->log2_pages); j++)
7014                 {
7015                         for (k = 0; k < t->entries_per_page; k++)
7016                         {
7017                             v = vnet_classify_entry_at_index (t, save_v, j*t->entries_per_page + k);
7018                             if (vnet_classify_entry_is_free (v))
7019                                 continue;
7020
7021                                 send_classify_session_details(q, table_id,
7022                                                 t->match_n_vectors * sizeof (u32x4), v, mp->context);
7023                         }
7024                 }
7025             }
7026             break;
7027         }
7028     }));
7029 }
7030
7031 #define BOUNCE_HANDLER(nn)                                              \
7032 static void vl_api_##nn##_t_handler (                                   \
7033     vl_api_##nn##_t *mp)                                                \
7034 {                                                                       \
7035     vpe_client_registration_t *reg;                                     \
7036     vpe_api_main_t * vam = &vpe_api_main;                               \
7037     unix_shared_memory_queue_t * q;                                     \
7038                                                                         \
7039     /* One registration only... */                                      \
7040     pool_foreach(reg, vam->nn##_registrations,                          \
7041     ({                                                                  \
7042         q = vl_api_client_index_to_input_queue (reg->client_index);     \
7043         if (q) {                                                        \
7044             /*                                                          \
7045              * If the queue is stuffed, turf the msg and complain       \
7046              * It's unlikely that the intended recipient is             \
7047              * alive; avoid deadlock at all costs.                      \
7048              */                                                         \
7049             if (q->cursize == q->maxsize) {                             \
7050                 clib_warning ("ERROR: receiver queue full, drop msg");  \
7051                 vl_msg_api_free (mp);                                   \
7052                 return;                                                 \
7053             }                                                           \
7054             vl_msg_api_send_shmem (q, (u8 *)&mp);                       \
7055             return;                                                     \
7056         }                                                               \
7057     }));                                                                \
7058     vl_msg_api_free (mp);                                               \
7059 }
7060
7061 /*
7062  * vpe_api_hookup
7063  * Add vpe's API message handlers to the table.
7064  * vlib has alread mapped shared memory and
7065  * added the client registration handlers.
7066  * See .../open-repo/vlib/memclnt_vlib.c:memclnt_process()
7067  */
7068
7069 static clib_error_t *
7070 vpe_api_hookup (vlib_main_t *vm)
7071 {
7072     api_main_t * am = &api_main;
7073
7074 #define _(N,n)                                                  \
7075     vl_msg_api_set_handlers(VL_API_##N, #n,                     \
7076                            vl_api_##n##_t_handler,              \
7077                            vl_noop_handler,                     \
7078                            vl_api_##n##_t_endian,               \
7079                            vl_api_##n##_t_print,                \
7080                            sizeof(vl_api_##n##_t), 1);
7081     foreach_vpe_api_msg;
7082 #undef _
7083
7084     /*
7085      * Manually register the sr tunnel add del msg, so we trace
7086      * enough bytes to capture a typical segment list
7087      */
7088     vl_msg_api_set_handlers (VL_API_SR_TUNNEL_ADD_DEL,
7089                              "sr_tunnel_add_del",
7090                              vl_api_sr_tunnel_add_del_t_handler,
7091                              vl_noop_handler,
7092                              vl_api_sr_tunnel_add_del_t_endian,
7093                              vl_api_sr_tunnel_add_del_t_print,
7094                              256, 1);
7095
7096
7097     /*
7098      * Manually register the sr policy add del msg, so we trace
7099      * enough bytes to capture a typical tunnel name list
7100      */
7101     vl_msg_api_set_handlers (VL_API_SR_POLICY_ADD_DEL,
7102                              "sr_policy_add_del",
7103                              vl_api_sr_policy_add_del_t_handler,
7104                              vl_noop_handler,
7105                              vl_api_sr_policy_add_del_t_endian,
7106                              vl_api_sr_policy_add_del_t_print,
7107                              256, 1);
7108
7109     /*
7110      * Trace space for 8 MPLS encap labels, classifier mask+match
7111      */
7112     am->api_trace_cfg [VL_API_MPLS_ADD_DEL_ENCAP].size += 8 * sizeof(u32);
7113     am->api_trace_cfg [VL_API_CLASSIFY_ADD_DEL_TABLE].size
7114         += 5 * sizeof (u32x4);
7115     am->api_trace_cfg [VL_API_CLASSIFY_ADD_DEL_SESSION].size
7116         += 5 * sizeof (u32x4);
7117     am->api_trace_cfg [VL_API_VXLAN_ADD_DEL_TUNNEL].size
7118         += 16 * sizeof (u32);
7119
7120     /*
7121      * Thread-safe API messages
7122      */
7123     am->is_mp_safe [VL_API_IP_ADD_DEL_ROUTE] = 1;
7124     am->is_mp_safe [VL_API_GET_NODE_GRAPH] = 1;
7125
7126     return 0;
7127 }
7128
7129 VLIB_API_INIT_FUNCTION(vpe_api_hookup);
7130
7131 static clib_error_t *
7132 vpe_api_init (vlib_main_t *vm)
7133 {
7134     vpe_api_main_t *am = &vpe_api_main;
7135
7136     am->vlib_main = vm;
7137     am->vnet_main = vnet_get_main();
7138     am->interface_events_registration_hash = hash_create (0, sizeof (uword));
7139     am->to_netconf_server_registration_hash = hash_create (0, sizeof (uword));
7140     am->from_netconf_server_registration_hash = hash_create (0, sizeof (uword));
7141     am->to_netconf_client_registration_hash = hash_create (0, sizeof (uword));
7142     am->from_netconf_client_registration_hash = hash_create (0, sizeof (uword));
7143     am->oam_events_registration_hash = hash_create (0, sizeof (uword));
7144
7145     vl_api_init (vm);
7146     vl_set_memory_region_name ("/vpe-api");
7147     vl_enable_disable_memory_api (vm, 1 /* enable it */);
7148
7149     return 0;
7150 }
7151
7152 VLIB_INIT_FUNCTION(vpe_api_init);
7153
7154
7155 static clib_error_t *
7156 api_segment_config (vlib_main_t * vm, unformat_input_t * input)
7157 {
7158   u8 * chroot_path;
7159   int uid, gid, rv;
7160   char *s, buf[128];
7161   struct passwd _pw, *pw;
7162   struct group _grp, *grp;
7163   clib_error_t *e;
7164
7165   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7166     {
7167       if (unformat (input, "prefix %s", &chroot_path))
7168         {
7169           vec_add1 (chroot_path, 0);
7170           vl_set_memory_root_path ((char *)chroot_path);
7171         }
7172       else if (unformat (input, "uid %d", &uid))
7173         vl_set_memory_uid (uid);
7174       else if (unformat (input, "gid %d", &gid))
7175         vl_set_memory_gid (gid);
7176       else if (unformat (input, "uid %s", &s))
7177         {
7178           /* lookup the username */
7179           pw = NULL;
7180           rv = getpwnam_r(s, &_pw, buf, sizeof(buf), &pw);
7181           if (rv < 0)
7182             {
7183               e = clib_error_return_code(0, rv,
7184                        CLIB_ERROR_ERRNO_VALID | CLIB_ERROR_FATAL,
7185                        "cannot fetch username %s", s);
7186               vec_free (s);
7187               return e;
7188             }
7189           if (pw == NULL)
7190             {
7191               e = clib_error_return_fatal(0, "username %s does not exist", s);
7192               vec_free (s);
7193               return e;
7194             }
7195           vec_free (s);
7196           vl_set_memory_uid (pw->pw_uid);
7197         }
7198       else if (unformat (input, "gid %s", &s))
7199         {
7200           /* lookup the group name */
7201           grp = NULL;
7202           rv = getgrnam_r(s, &_grp, buf, sizeof(buf), &grp);
7203           if (rv != 0)
7204             {
7205               e = clib_error_return_code(0, rv,
7206                        CLIB_ERROR_ERRNO_VALID | CLIB_ERROR_FATAL,
7207                        "cannot fetch group %s", s);
7208               vec_free (s);
7209               return e;
7210             }
7211           if (grp == NULL)
7212             {
7213               e = clib_error_return_fatal(0, "group %s does not exist", s);
7214               vec_free (s);
7215               return e;
7216             }
7217           vec_free (s);
7218           vl_set_memory_gid (grp->gr_gid);
7219         }
7220       else
7221         return clib_error_return (0, "unknown input `%U'",
7222                                   format_unformat_error, input);
7223     }
7224   return 0;
7225 }
7226 VLIB_EARLY_CONFIG_FUNCTION (api_segment_config, "api-segment");
7227
7228 void * get_unformat_vnet_sw_interface (void)
7229 {
7230     return (void *) &unformat_vnet_sw_interface;
7231 }
7232
7233 #undef vl_api_version
7234 #define vl_api_version(n,v) static u32 vpe_api_version = v;
7235 #include <vpp-api/vpe.api.h>
7236 #undef vl_api_version
7237
7238 int vl_msg_api_version_check (vl_api_memclnt_create_t * mp)
7239 {
7240     if (clib_host_to_net_u32(mp->api_versions[0]) != vpe_api_version) {
7241         clib_warning ("vpe API mismatch: 0x%08x instead of 0x%08x",
7242                       clib_host_to_net_u32 (mp->api_versions[0]),
7243                       vpe_api_version);
7244         return -1;
7245     }
7246     return 0;
7247 }
7248
7249 static u8 * format_arp_event (u8 * s, va_list * args)
7250 {
7251     vl_api_ip4_arp_event_t * event = va_arg (*args, vl_api_ip4_arp_event_t *);
7252
7253     s = format (s, "pid %d: %U", event->pid,
7254                 format_ip4_address, &event->address);
7255     return s;
7256 }
7257
7258 static clib_error_t *
7259 show_ip4_arp_events_fn (vlib_main_t * vm,
7260                         unformat_input_t * input,
7261                         vlib_cli_command_t * cmd)
7262 {
7263     vpe_api_main_t * am = &vpe_api_main;
7264     vl_api_ip4_arp_event_t * event;
7265
7266     if (pool_elts (am->arp_events) == 0) {
7267         vlib_cli_output (vm, "No active arp event registrations");
7268         return 0;
7269     }
7270
7271     pool_foreach (event, am->arp_events,
7272     ({
7273         vlib_cli_output (vm, "%U", format_arp_event, event);
7274     }));
7275
7276     return 0;
7277 }
7278
7279 VLIB_CLI_COMMAND (show_ip4_arp_events, static) = {
7280   .path = "show arp event registrations",
7281   .function = show_ip4_arp_events_fn,
7282   .short_help = "Show arp event registrations",
7283 };