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