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