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