f4f085166fe60c5a3db42ee9d8707381941554d4
[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;
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
5141   memset (&locator, 0, sizeof (locator));
5142   for (i = 0; i < mp->locator_num; i++)
5143     {
5144       ls_loc = &((ls_locator_t *) mp->locators)[i];
5145       VALIDATE_SW_IF_INDEX (ls_loc);
5146
5147       locator.sw_if_index = htonl (ls_loc->sw_if_index);
5148       locator.priority = ls_loc->priority;
5149       locator.weight = ls_loc->weight;
5150       locator.local = 1;
5151       vec_add1 (a->locators, locator);
5152     }
5153
5154   rv = vnet_lisp_add_del_locator_set (a, &ls_index);
5155
5156   BAD_SW_IF_INDEX_LABEL;
5157
5158   vec_free (locator_name);
5159   vec_free (a->locators);
5160
5161   /* *INDENT-OFF* */
5162   REPLY_MACRO2 (VL_API_LISP_ADD_DEL_LOCATOR_SET_REPLY,
5163   ({
5164     rmp->ls_index = clib_host_to_net_u32 (ls_index);
5165   }));
5166   /* *INDENT-ON* */
5167 }
5168
5169 static void
5170 vl_api_lisp_add_del_locator_t_handler (vl_api_lisp_add_del_locator_t * mp)
5171 {
5172   vl_api_lisp_add_del_locator_reply_t *rmp;
5173   int rv = 0;
5174   locator_t locator, *locators = NULL;
5175   vnet_lisp_add_del_locator_set_args_t _a, *a = &_a;
5176   u32 ls_index = ~0;
5177   u8 *locator_name = NULL;
5178
5179   memset (&locator, 0, sizeof (locator));
5180   memset (a, 0, sizeof (a[0]));
5181
5182   locator.sw_if_index = ntohl (mp->sw_if_index);
5183   locator.priority = mp->priority;
5184   locator.weight = mp->weight;
5185   locator.local = 1;
5186   vec_add1 (locators, locator);
5187
5188   locator_name = format (0, "%s", mp->locator_set_name);
5189
5190   a->name = locator_name;
5191   a->locators = locators;
5192   a->is_add = mp->is_add;
5193   a->local = 1;
5194
5195   rv = vnet_lisp_add_del_locator (a, NULL, &ls_index);
5196
5197   vec_free (locators);
5198   vec_free (locator_name);
5199
5200   REPLY_MACRO (VL_API_LISP_ADD_DEL_LOCATOR_REPLY);
5201 }
5202
5203 static int
5204 unformat_lisp_eid_api (gid_address_t * dst, u32 vni, u8 type, void *src,
5205                        u8 len)
5206 {
5207   switch (type)
5208     {
5209     case 0:                     /* ipv4 */
5210       gid_address_type (dst) = GID_ADDR_IP_PREFIX;
5211       gid_address_ip_set (dst, src, IP4);
5212       gid_address_ippref_len (dst) = len;
5213       ip_prefix_normalize (&gid_address_ippref (dst));
5214       break;
5215     case 1:                     /* ipv6 */
5216       gid_address_type (dst) = GID_ADDR_IP_PREFIX;
5217       gid_address_ip_set (dst, src, IP6);
5218       gid_address_ippref_len (dst) = len;
5219       ip_prefix_normalize (&gid_address_ippref (dst));
5220       break;
5221     case 2:                     /* l2 mac */
5222       gid_address_type (dst) = GID_ADDR_MAC;
5223       clib_memcpy (&gid_address_mac (dst), src, 6);
5224       break;
5225     default:
5226       /* unknown type */
5227       return VNET_API_ERROR_INVALID_VALUE;
5228     }
5229
5230   gid_address_vni (dst) = vni;
5231
5232   return 0;
5233 }
5234
5235 static void
5236 vl_api_lisp_add_del_local_eid_t_handler (vl_api_lisp_add_del_local_eid_t * mp)
5237 {
5238   vl_api_lisp_add_del_local_eid_reply_t *rmp;
5239   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
5240   int rv = 0;
5241   gid_address_t _eid, *eid = &_eid;
5242   uword *p = NULL;
5243   u32 locator_set_index = ~0, map_index = ~0;
5244   vnet_lisp_add_del_mapping_args_t _a, *a = &_a;
5245   u8 *name = NULL;
5246   memset (a, 0, sizeof (a[0]));
5247   memset (eid, 0, sizeof (eid[0]));
5248
5249   rv = unformat_lisp_eid_api (eid, clib_net_to_host_u32 (mp->vni),
5250                               mp->eid_type, mp->eid, mp->prefix_len);
5251   if (rv)
5252     goto out;
5253
5254   name = format (0, "%s", mp->locator_set_name);
5255   p = hash_get_mem (lcm->locator_set_index_by_name, name);
5256   if (!p)
5257     {
5258       rv = VNET_API_ERROR_INVALID_VALUE;
5259       goto out;
5260     }
5261   locator_set_index = p[0];
5262
5263   /* XXX treat batch configuration */
5264   a->is_add = mp->is_add;
5265   gid_address_copy (&a->eid, eid);
5266   a->locator_set_index = locator_set_index;
5267   a->local = 1;
5268   rv = vnet_lisp_add_del_local_mapping (a, &map_index);
5269
5270 out:
5271   vec_free (name);
5272   gid_address_free (&a->eid);
5273
5274   REPLY_MACRO (VL_API_LISP_ADD_DEL_LOCAL_EID_REPLY);
5275 }
5276
5277 static void
5278   vl_api_lisp_eid_table_add_del_map_t_handler
5279   (vl_api_lisp_eid_table_add_del_map_t * mp)
5280 {
5281   vl_api_lisp_eid_table_add_del_map_reply_t *rmp;
5282   int rv = 0;
5283   rv = vnet_lisp_eid_table_map (clib_net_to_host_u32 (mp->vni),
5284                                 clib_net_to_host_u32 (mp->dp_table),
5285                                 mp->is_l2, mp->is_add);
5286 REPLY_MACRO (VL_API_LISP_EID_TABLE_ADD_DEL_MAP_REPLY)}
5287
5288 /** Used for transferring locators via VPP API */
5289 /* *INDENT-OFF* */
5290 typedef CLIB_PACKED (struct {
5291   u8 is_ip4; /**< is locator an IPv4 address */
5292   u8 priority; /**< locator priority */
5293   u8 weight; /**< locator weight */
5294   u8 addr[16]; /**< IPv4/IPv6 address */
5295 }) rloc_t;
5296 /* *INDENT-ON* */
5297
5298 static locator_pair_t *
5299 unformat_lisp_loc_pairs (void *lcl_locs, void *rmt_locs, u32 rloc_num)
5300 {
5301   u32 i;
5302   locator_pair_t *pairs = 0, pair;
5303   rloc_t *r;
5304
5305   for (i = 0; i < rloc_num; i++)
5306     {
5307       /* local locator */
5308       r = &((rloc_t *) lcl_locs)[i];
5309       memset (&pair.lcl_loc, 0, sizeof (pair.lcl_loc));
5310       ip_address_set (&pair.lcl_loc, &r->addr, r->is_ip4 ? IP4 : IP6);
5311
5312       /* remote locators */
5313       r = &((rloc_t *) rmt_locs)[i];
5314       memset (&pair.rmt_loc, 0, sizeof (pair.rmt_loc));
5315       ip_address_set (&pair.rmt_loc, &r->addr, r->is_ip4 ? IP4 : IP6);
5316
5317       pair.priority = r->priority;
5318       pair.weight = r->weight;
5319
5320       vec_add1 (pairs, pair);
5321     }
5322   return pairs;
5323 }
5324
5325 static locator_t *
5326 unformat_lisp_locs (void *rmt_locs, u32 rloc_num)
5327 {
5328   u32 i;
5329   locator_t *locs = 0, loc;
5330   rloc_t *r;
5331
5332   for (i = 0; i < rloc_num; i++)
5333     {
5334       /* remote locators */
5335       r = &((rloc_t *) rmt_locs)[i];
5336       memset (&loc, 0, sizeof (loc));
5337       gid_address_ip_set (&loc.address, &r->addr, r->is_ip4 ? IP4 : IP6);
5338
5339       loc.priority = r->priority;
5340       loc.weight = r->weight;
5341
5342       vec_add1 (locs, loc);
5343     }
5344   return locs;
5345 }
5346
5347 static void
5348   vl_api_lisp_gpe_add_del_fwd_entry_t_handler
5349   (vl_api_lisp_gpe_add_del_fwd_entry_t * mp)
5350 {
5351   vl_api_lisp_gpe_add_del_fwd_entry_reply_t *rmp;
5352   vnet_lisp_gpe_add_del_fwd_entry_args_t _a, *a = &_a;
5353   locator_pair_t *pairs = 0;
5354   int rv = 0;
5355
5356   memset (a, 0, sizeof (a[0]));
5357
5358   rv = unformat_lisp_eid_api (&a->rmt_eid, mp->vni, mp->eid_type,
5359                               mp->rmt_eid, mp->rmt_len);
5360   rv |= unformat_lisp_eid_api (&a->lcl_eid, mp->vni, mp->eid_type,
5361                                mp->lcl_eid, mp->lcl_len);
5362
5363   pairs = unformat_lisp_loc_pairs (mp->lcl_locs, mp->rmt_locs, mp->loc_num);
5364
5365   if (rv || 0 == pairs)
5366     goto send_reply;
5367
5368   a->is_add = mp->is_add;
5369   a->locator_pairs = pairs;
5370   a->dp_table = mp->dp_table;
5371   a->vni = mp->vni;
5372   a->action = mp->action;
5373
5374   rv = vnet_lisp_gpe_add_del_fwd_entry (a, 0);
5375   vec_free (pairs);
5376 send_reply:
5377   REPLY_MACRO (VL_API_LISP_GPE_ADD_DEL_FWD_ENTRY_REPLY);
5378 }
5379
5380 static void
5381 vl_api_lisp_add_del_map_resolver_t_handler (vl_api_lisp_add_del_map_resolver_t
5382                                             * mp)
5383 {
5384   vl_api_lisp_add_del_map_resolver_reply_t *rmp;
5385   int rv = 0;
5386   vnet_lisp_add_del_map_resolver_args_t _a, *a = &_a;
5387
5388   memset (a, 0, sizeof (a[0]));
5389
5390   a->is_add = mp->is_add;
5391   ip_address_set (&a->address, mp->ip_address, mp->is_ipv6 ? IP6 : IP4);
5392
5393   rv = vnet_lisp_add_del_map_resolver (a);
5394
5395   REPLY_MACRO (VL_API_LISP_ADD_DEL_MAP_RESOLVER_REPLY);
5396 }
5397
5398 static void
5399 vl_api_lisp_gpe_enable_disable_t_handler (vl_api_lisp_gpe_enable_disable_t *
5400                                           mp)
5401 {
5402   vl_api_lisp_gpe_enable_disable_reply_t *rmp;
5403   int rv = 0;
5404   vnet_lisp_gpe_enable_disable_args_t _a, *a = &_a;
5405
5406   a->is_en = mp->is_en;
5407   vnet_lisp_gpe_enable_disable (a);
5408
5409   REPLY_MACRO (VL_API_LISP_GPE_ENABLE_DISABLE_REPLY);
5410 }
5411
5412 static void
5413 vl_api_lisp_enable_disable_t_handler (vl_api_lisp_enable_disable_t * mp)
5414 {
5415   vl_api_lisp_enable_disable_reply_t *rmp;
5416   int rv = 0;
5417
5418   vnet_lisp_enable_disable (mp->is_en);
5419   REPLY_MACRO (VL_API_LISP_ENABLE_DISABLE_REPLY);
5420 }
5421
5422 static void
5423 vl_api_lisp_gpe_add_del_iface_t_handler (vl_api_lisp_gpe_add_del_iface_t * mp)
5424 {
5425   vl_api_lisp_gpe_add_del_iface_reply_t *rmp;
5426   int rv = 0;
5427   vnet_lisp_gpe_add_del_iface_args_t _a, *a = &_a;
5428
5429   a->is_add = mp->is_add;
5430   a->dp_table = mp->dp_table;
5431   a->vni = mp->vni;
5432   a->is_l2 = mp->is_l2;
5433   rv = vnet_lisp_gpe_add_del_iface (a, 0);
5434
5435   REPLY_MACRO (VL_API_LISP_GPE_ADD_DEL_IFACE_REPLY);
5436 }
5437
5438 static void
5439 vl_api_lisp_pitr_set_locator_set_t_handler (vl_api_lisp_pitr_set_locator_set_t
5440                                             * mp)
5441 {
5442   vl_api_lisp_pitr_set_locator_set_reply_t *rmp;
5443   int rv = 0;
5444   u8 *ls_name = 0;
5445
5446   ls_name = format (0, "%s", mp->ls_name);
5447   rv = vnet_lisp_pitr_set_locator_set (ls_name, mp->is_add);
5448   vec_free (ls_name);
5449
5450   REPLY_MACRO (VL_API_LISP_PITR_SET_LOCATOR_SET_REPLY);
5451 }
5452
5453 static void
5454   vl_api_lisp_add_del_map_request_itr_rlocs_t_handler
5455   (vl_api_lisp_add_del_map_request_itr_rlocs_t * mp)
5456 {
5457   vl_api_lisp_add_del_map_request_itr_rlocs_reply_t *rmp;
5458   int rv = 0;
5459   u8 *locator_set_name = NULL;
5460   vnet_lisp_add_del_mreq_itr_rloc_args_t _a, *a = &_a;
5461
5462   locator_set_name = format (0, "%s", mp->locator_set_name);
5463
5464   a->is_add = mp->is_add;
5465   a->locator_set_name = locator_set_name;
5466
5467   rv = vnet_lisp_add_del_mreq_itr_rlocs (a);
5468
5469   vec_free (locator_set_name);
5470
5471   REPLY_MACRO (VL_API_LISP_ADD_DEL_MAP_REQUEST_ITR_RLOCS_REPLY);
5472 }
5473
5474 static void
5475   vl_api_lisp_add_del_remote_mapping_t_handler
5476   (vl_api_lisp_add_del_remote_mapping_t * mp)
5477 {
5478   locator_t *rlocs = 0;
5479   vl_api_lisp_add_del_remote_mapping_reply_t *rmp;
5480   int rv = 0;
5481   gid_address_t _eid, *eid = &_eid;
5482
5483   memset (eid, 0, sizeof (eid[0]));
5484
5485   rv = unformat_lisp_eid_api (eid, clib_net_to_host_u32 (mp->vni),
5486                               mp->eid_type, mp->eid, mp->eid_len);
5487   if (rv)
5488     goto send_reply;
5489
5490   rlocs = unformat_lisp_locs (mp->rlocs, mp->rloc_num);
5491   if (0 == rlocs)
5492     goto send_reply;
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   vl_api_lisp_eid_table_details_t *rmp = NULL;
5675   gid_address_t *gid = NULL;
5676   u8 *mac = 0;
5677   ip_prefix_t *ip_prefix = NULL;
5678
5679   switch (filter)
5680     {
5681     case 0:                     /* all mappings */
5682       break;
5683
5684     case 1:                     /* local only */
5685       if (!mapit->local)
5686         return;
5687       break;
5688     case 2:                     /* remote only */
5689       if (mapit->local)
5690         return;
5691       break;
5692     default:
5693       clib_warning ("Filter error, unknown filter: %d", filter);
5694       return;
5695     }
5696
5697   gid = &mapit->eid;
5698   ip_prefix = &gid_address_ippref (gid);
5699   mac = gid_address_mac (gid);
5700
5701   rmp = vl_msg_api_alloc (sizeof (*rmp));
5702   memset (rmp, 0, sizeof (*rmp));
5703   rmp->_vl_msg_id = ntohs (VL_API_LISP_EID_TABLE_DETAILS);
5704   rmp->locator_set_index = mapit->locator_set_index;
5705   rmp->is_local = mapit->local;
5706   rmp->ttl = mapit->ttl;
5707   rmp->authoritative = mapit->authoritative;
5708
5709   switch (gid_address_type (gid))
5710     {
5711     case GID_ADDR_IP_PREFIX:
5712       rmp->eid_prefix_len = ip_prefix_len (ip_prefix);
5713       if (ip_prefix_version (ip_prefix) == IP4)
5714         {
5715           rmp->eid_type = 0;    /* ipv4 type */
5716           clib_memcpy (rmp->eid, &ip_prefix_v4 (ip_prefix),
5717                        sizeof (ip_prefix_v4 (ip_prefix)));
5718         }
5719       else
5720         {
5721           rmp->eid_type = 1;    /* ipv6 type */
5722           clib_memcpy (rmp->eid, &ip_prefix_v6 (ip_prefix),
5723                        sizeof (ip_prefix_v6 (ip_prefix)));
5724         }
5725       break;
5726     case GID_ADDR_MAC:
5727       rmp->eid_type = 2;        /* l2 mac type */
5728       clib_memcpy (rmp->eid, mac, 6);
5729       break;
5730     default:
5731       ASSERT (0);
5732     }
5733   rmp->context = context;
5734   rmp->vni = clib_host_to_net_u32 (gid_address_vni (gid));
5735   vl_msg_api_send_shmem (q, (u8 *) & rmp);
5736 }
5737
5738 static void
5739 vl_api_lisp_eid_table_dump_t_handler (vl_api_lisp_eid_table_dump_t * mp)
5740 {
5741   u32 mi;
5742   unix_shared_memory_queue_t *q = NULL;
5743   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
5744   mapping_t *mapit = NULL;
5745   gid_address_t _eid, *eid = &_eid;
5746
5747   q = vl_api_client_index_to_input_queue (mp->client_index);
5748   if (q == 0)
5749     {
5750       return;
5751     }
5752
5753   if (mp->eid_set)
5754     {
5755       memset (eid, 0, sizeof (*eid));
5756
5757       unformat_lisp_eid_api (eid, clib_net_to_host_u32 (mp->vni),
5758                              mp->eid_type, mp->eid, mp->prefix_length);
5759
5760       mi = gid_dictionary_lookup (&lcm->mapping_index_by_gid, eid);
5761       if ((u32) ~ 0 == mi)
5762         return;
5763
5764       mapit = pool_elt_at_index (lcm->mapping_pool, mi);
5765       send_lisp_eid_table_details (mapit, q, mp->context,
5766                                    0 /* ignore filter */ );
5767     }
5768   else
5769     {
5770       /* *INDENT-OFF* */
5771       pool_foreach (mapit, lcm->mapping_pool,
5772       ({
5773         send_lisp_eid_table_details(mapit, q, mp->context,
5774                                     mp->filter);
5775       }));
5776       /* *INDENT-ON* */
5777     }
5778 }
5779
5780 static void
5781 send_lisp_gpe_tunnel_details (lisp_gpe_tunnel_t * tunnel,
5782                               unix_shared_memory_queue_t * q, u32 context)
5783 {
5784   vl_api_lisp_gpe_tunnel_details_t *rmp;
5785   lisp_gpe_main_t *lgm = &lisp_gpe_main;
5786
5787   rmp = vl_msg_api_alloc (sizeof (*rmp));
5788   memset (rmp, 0, sizeof (*rmp));
5789   rmp->_vl_msg_id = ntohs (VL_API_LISP_GPE_TUNNEL_DETAILS);
5790
5791   rmp->tunnels = tunnel - lgm->tunnels;
5792
5793   rmp->is_ipv6 = ip_addr_version (&tunnel->src) == IP6 ? 1 : 0;
5794   ip_address_copy_addr (rmp->source_ip, &tunnel->src);
5795   ip_address_copy_addr (rmp->destination_ip, &tunnel->dst);
5796
5797   rmp->encap_fib_id = htonl (tunnel->encap_fib_index);
5798   rmp->decap_fib_id = htonl (tunnel->decap_fib_index);
5799   rmp->dcap_next = htonl (tunnel->decap_next_index);
5800   rmp->lisp_ver = tunnel->ver_res;
5801   rmp->next_protocol = tunnel->next_protocol;
5802   rmp->flags = tunnel->flags;
5803   rmp->ver_res = tunnel->ver_res;
5804   rmp->res = tunnel->res;
5805   rmp->iid = htonl (tunnel->vni);
5806   rmp->context = context;
5807
5808   vl_msg_api_send_shmem (q, (u8 *) & rmp);
5809 }
5810
5811 static void
5812 vl_api_lisp_gpe_tunnel_dump_t_handler (vl_api_lisp_gpe_tunnel_dump_t * mp)
5813 {
5814   unix_shared_memory_queue_t *q = NULL;
5815   lisp_gpe_main_t *lgm = &lisp_gpe_main;
5816   lisp_gpe_tunnel_t *tunnel = NULL;
5817
5818   if (pool_elts (lgm->tunnels) == 0)
5819     {
5820       return;
5821     }
5822
5823   q = vl_api_client_index_to_input_queue (mp->client_index);
5824   if (q == 0)
5825     {
5826       return;
5827     }
5828
5829   /* *INDENT-OFF* */
5830   pool_foreach(tunnel, lgm->tunnels,
5831   ({
5832     send_lisp_gpe_tunnel_details(tunnel, q, mp->context);
5833   }));
5834   /* *INDENT-ON* */
5835 }
5836
5837 static void
5838 send_lisp_map_resolver_details (ip_address_t * ip,
5839                                 unix_shared_memory_queue_t * q, u32 context)
5840 {
5841   vl_api_lisp_map_resolver_details_t *rmp = NULL;
5842
5843   rmp = vl_msg_api_alloc (sizeof (*rmp));
5844   memset (rmp, 0, sizeof (*rmp));
5845   rmp->_vl_msg_id = ntohs (VL_API_LISP_MAP_RESOLVER_DETAILS);
5846
5847   switch (ip_addr_version (ip))
5848     {
5849     case IP4:
5850       rmp->is_ipv6 = 0;
5851       clib_memcpy (rmp->ip_address, &ip_addr_v4 (ip),
5852                    sizeof (ip_addr_v4 (ip)));
5853       break;
5854
5855     case IP6:
5856       rmp->is_ipv6 = 1;
5857       clib_memcpy (rmp->ip_address, &ip_addr_v6 (ip),
5858                    sizeof (ip_addr_v6 (ip)));
5859       break;
5860
5861     default:
5862       ASSERT (0);
5863     }
5864   rmp->context = context;
5865
5866   vl_msg_api_send_shmem (q, (u8 *) & rmp);
5867 }
5868
5869 static void
5870 vl_api_lisp_map_resolver_dump_t_handler (vl_api_lisp_map_resolver_dump_t * mp)
5871 {
5872   unix_shared_memory_queue_t *q = NULL;
5873   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
5874   map_resolver_t *mr;
5875
5876   q = vl_api_client_index_to_input_queue (mp->client_index);
5877   if (q == 0)
5878     {
5879       return;
5880     }
5881
5882   vec_foreach (mr, lcm->map_resolvers)
5883   {
5884     send_lisp_map_resolver_details (&mr->address, q, mp->context);
5885   }
5886 }
5887
5888 static void
5889 send_eid_table_map_pair (hash_pair_t * p,
5890                          unix_shared_memory_queue_t * q, u32 context)
5891 {
5892   vl_api_lisp_eid_table_map_details_t *rmp = NULL;
5893
5894   rmp = vl_msg_api_alloc (sizeof (*rmp));
5895   memset (rmp, 0, sizeof (*rmp));
5896   rmp->_vl_msg_id = ntohs (VL_API_LISP_EID_TABLE_MAP_DETAILS);
5897
5898   rmp->vni = clib_host_to_net_u32 (p->key);
5899   rmp->dp_table = clib_host_to_net_u32 (p->value[0]);
5900   rmp->context = context;
5901   vl_msg_api_send_shmem (q, (u8 *) & rmp);
5902 }
5903
5904 static void
5905 vl_api_lisp_eid_table_map_dump_t_handler (vl_api_lisp_eid_table_map_dump_t *
5906                                           mp)
5907 {
5908   unix_shared_memory_queue_t *q = NULL;
5909   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
5910   hash_pair_t *p;
5911   uword *vni_table = 0;
5912
5913   q = vl_api_client_index_to_input_queue (mp->client_index);
5914   if (q == 0)
5915     {
5916       return;
5917     }
5918
5919   if (mp->is_l2)
5920     {
5921       vni_table = lcm->bd_id_by_vni;
5922     }
5923   else
5924     {
5925       vni_table = lcm->table_id_by_vni;
5926     }
5927
5928   /* *INDENT-OFF* */
5929   hash_foreach_pair (p, vni_table,
5930   ({
5931     send_eid_table_map_pair (p, q, mp->context);
5932   }));
5933   /* *INDENT-ON* */
5934 }
5935
5936 static void
5937 send_eid_table_vni (u32 vni, unix_shared_memory_queue_t * q, u32 context)
5938 {
5939   vl_api_lisp_eid_table_vni_details_t *rmp = 0;
5940
5941   rmp = vl_msg_api_alloc (sizeof (*rmp));
5942   memset (rmp, 0, sizeof (*rmp));
5943   rmp->_vl_msg_id = ntohs (VL_API_LISP_EID_TABLE_VNI_DETAILS);
5944   rmp->context = context;
5945   rmp->vni = clib_host_to_net_u32 (vni);
5946   vl_msg_api_send_shmem (q, (u8 *) & rmp);
5947 }
5948
5949 static void
5950 vl_api_lisp_eid_table_vni_dump_t_handler (vl_api_lisp_eid_table_vni_dump_t *
5951                                           mp)
5952 {
5953   hash_pair_t *p;
5954   u32 *vnis = 0;
5955   unix_shared_memory_queue_t *q = 0;
5956   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
5957
5958   q = vl_api_client_index_to_input_queue (mp->client_index);
5959   if (q == 0)
5960     {
5961       return;
5962     }
5963
5964   /* *INDENT-OFF* */
5965   hash_foreach_pair (p, lcm->table_id_by_vni,
5966   ({
5967     hash_set (vnis, p->key, 0);
5968   }));
5969
5970   hash_foreach_pair (p, lcm->bd_id_by_vni,
5971   ({
5972     hash_set (vnis, p->key, 0);
5973   }));
5974
5975   hash_foreach_pair (p, vnis,
5976   ({
5977     send_eid_table_vni (p->key, q, mp->context);
5978   }));
5979   /* *INDENT-ON* */
5980
5981   hash_free (vnis);
5982 }
5983
5984 static void
5985 vl_api_show_lisp_status_t_handler (vl_api_show_lisp_status_t * mp)
5986 {
5987   unix_shared_memory_queue_t *q = NULL;
5988   vl_api_show_lisp_status_reply_t *rmp = NULL;
5989   int rv = 0;
5990
5991   q = vl_api_client_index_to_input_queue (mp->client_index);
5992   if (q == 0)
5993     {
5994       return;
5995     }
5996
5997   /* *INDENT-OFF* */
5998   REPLY_MACRO2(VL_API_SHOW_LISP_STATUS_REPLY,
5999   ({
6000     rmp->gpe_status = vnet_lisp_gpe_enable_disable_status ();
6001     rmp->feature_status = vnet_lisp_enable_disable_status ();
6002   }));
6003   /* *INDENT-ON* */
6004 }
6005
6006 static void
6007   vl_api_lisp_get_map_request_itr_rlocs_t_handler
6008   (vl_api_lisp_get_map_request_itr_rlocs_t * mp)
6009 {
6010   unix_shared_memory_queue_t *q = NULL;
6011   vl_api_lisp_get_map_request_itr_rlocs_reply_t *rmp = NULL;
6012   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
6013   locator_set_t *loc_set = 0;
6014   u8 *tmp_str = 0;
6015   int rv = 0;
6016
6017   q = vl_api_client_index_to_input_queue (mp->client_index);
6018   if (q == 0)
6019     {
6020       return;
6021     }
6022
6023   if (~0 == lcm->mreq_itr_rlocs)
6024     {
6025       tmp_str = format (0, " ");
6026     }
6027   else
6028     {
6029       loc_set =
6030         pool_elt_at_index (lcm->locator_set_pool, lcm->mreq_itr_rlocs);
6031       tmp_str = format (0, "%s", loc_set->name);
6032     }
6033
6034   /* *INDENT-OFF* */
6035   REPLY_MACRO2(VL_API_LISP_GET_MAP_REQUEST_ITR_RLOCS_REPLY,
6036   ({
6037     strncpy((char *) rmp->locator_set_name, (char *) tmp_str,
6038             ARRAY_LEN(rmp->locator_set_name) - 1);
6039   }));
6040   /* *INDENT-ON* */
6041
6042   vec_free (tmp_str);
6043 }
6044
6045 static void
6046 vl_api_show_lisp_pitr_t_handler (vl_api_show_lisp_pitr_t * mp)
6047 {
6048   unix_shared_memory_queue_t *q = NULL;
6049   vl_api_show_lisp_pitr_reply_t *rmp = NULL;
6050   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
6051   mapping_t *m;
6052   locator_set_t *ls = 0;
6053   u8 *tmp_str = 0;
6054   int rv = 0;
6055
6056   q = vl_api_client_index_to_input_queue (mp->client_index);
6057   if (q == 0)
6058     {
6059       return;
6060     }
6061
6062   if (!lcm->lisp_pitr)
6063     {
6064       tmp_str = format (0, "N/A");
6065     }
6066   else
6067     {
6068       m = pool_elt_at_index (lcm->mapping_pool, lcm->pitr_map_index);
6069       if (~0 != m->locator_set_index)
6070         {
6071           ls =
6072             pool_elt_at_index (lcm->locator_set_pool, m->locator_set_index);
6073           tmp_str = format (0, "%s", ls->name);
6074         }
6075       else
6076         {
6077           tmp_str = format (0, "N/A");
6078         }
6079     }
6080   vec_add1 (tmp_str, 0);
6081
6082   /* *INDENT-OFF* */
6083   REPLY_MACRO2(VL_API_SHOW_LISP_PITR_REPLY,
6084   ({
6085     rmp->status = lcm->lisp_pitr;
6086     strncpy((char *) rmp->locator_set_name, (char *) tmp_str,
6087             ARRAY_LEN(rmp->locator_set_name) - 1);
6088   }));
6089   /* *INDENT-ON* */
6090 }
6091
6092 static void
6093 vl_api_interface_name_renumber_t_handler (vl_api_interface_name_renumber_t *
6094                                           mp)
6095 {
6096   vl_api_interface_name_renumber_reply_t *rmp;
6097   int rv = 0;
6098
6099   VALIDATE_SW_IF_INDEX (mp);
6100
6101   rv = vnet_interface_name_renumber
6102     (ntohl (mp->sw_if_index), ntohl (mp->new_show_dev_instance));
6103
6104   BAD_SW_IF_INDEX_LABEL;
6105
6106   REPLY_MACRO (VL_API_INTERFACE_NAME_RENUMBER_REPLY);
6107 }
6108
6109 static int
6110 arp_change_data_callback (u32 pool_index, u8 * new_mac,
6111                           u32 sw_if_index, u32 address)
6112 {
6113   vpe_api_main_t *am = &vpe_api_main;
6114   vlib_main_t *vm = am->vlib_main;
6115   vl_api_ip4_arp_event_t *event;
6116   static f64 arp_event_last_time;
6117   f64 now = vlib_time_now (vm);
6118
6119   if (pool_is_free_index (am->arp_events, pool_index))
6120     return 1;
6121
6122   event = pool_elt_at_index (am->arp_events, pool_index);
6123   if (memcmp (&event->new_mac, new_mac, sizeof (event->new_mac)))
6124     {
6125       clib_memcpy (event->new_mac, new_mac, sizeof (event->new_mac));
6126     }
6127   else
6128     {                           /* same mac */
6129       if ((sw_if_index == event->sw_if_index) && ((address == 0) ||
6130                                                   /* for BD case, also check IP address with 10 sec timeout */
6131                                                   ((address == event->address)
6132                                                    &&
6133                                                    ((now -
6134                                                      arp_event_last_time) <
6135                                                     10.0))))
6136         return 1;
6137     }
6138
6139   arp_event_last_time = now;
6140   event->sw_if_index = sw_if_index;
6141   if (address)
6142     event->address = address;
6143   return 0;
6144 }
6145
6146 static int
6147 arp_change_delete_callback (u32 pool_index, u8 * notused)
6148 {
6149   vpe_api_main_t *am = &vpe_api_main;
6150
6151   if (pool_is_free_index (am->arp_events, pool_index))
6152     return 1;
6153
6154   pool_put_index (am->arp_events, pool_index);
6155   return 0;
6156 }
6157
6158 static void
6159 vl_api_want_ip4_arp_events_t_handler (vl_api_want_ip4_arp_events_t * mp)
6160 {
6161   vpe_api_main_t *am = &vpe_api_main;
6162   vnet_main_t *vnm = vnet_get_main ();
6163   vl_api_want_ip4_arp_events_reply_t *rmp;
6164   vl_api_ip4_arp_event_t *event;
6165   int rv;
6166
6167   if (mp->enable_disable)
6168     {
6169       pool_get (am->arp_events, event);
6170       memset (event, 0, sizeof (*event));
6171
6172       event->_vl_msg_id = ntohs (VL_API_IP4_ARP_EVENT);
6173       event->client_index = mp->client_index;
6174       event->context = mp->context;
6175       event->address = mp->address;
6176       event->pid = mp->pid;
6177
6178       rv = vnet_add_del_ip4_arp_change_event
6179         (vnm, arp_change_data_callback,
6180          mp->pid, &mp->address /* addr, in net byte order */ ,
6181          vpe_resolver_process_node.index,
6182          IP4_ARP_EVENT, event - am->arp_events, 1 /* is_add */ );
6183     }
6184   else
6185     {
6186       rv = vnet_add_del_ip4_arp_change_event
6187         (vnm, arp_change_delete_callback,
6188          mp->pid, &mp->address /* addr, in net byte order */ ,
6189          vpe_resolver_process_node.index,
6190          IP4_ARP_EVENT, ~0 /* pool index */ , 0 /* is_add */ );
6191     }
6192   REPLY_MACRO (VL_API_WANT_IP4_ARP_EVENTS_REPLY);
6193 }
6194
6195 static void vl_api_input_acl_set_interface_t_handler
6196   (vl_api_input_acl_set_interface_t * mp)
6197 {
6198   vlib_main_t *vm = vlib_get_main ();
6199   vl_api_input_acl_set_interface_reply_t *rmp;
6200   int rv;
6201   u32 sw_if_index, ip4_table_index, ip6_table_index, l2_table_index;
6202
6203   ip4_table_index = ntohl (mp->ip4_table_index);
6204   ip6_table_index = ntohl (mp->ip6_table_index);
6205   l2_table_index = ntohl (mp->l2_table_index);
6206   sw_if_index = ntohl (mp->sw_if_index);
6207
6208   VALIDATE_SW_IF_INDEX (mp);
6209
6210   rv = vnet_set_input_acl_intfc (vm, sw_if_index, ip4_table_index,
6211                                  ip6_table_index, l2_table_index, mp->is_add);
6212
6213   BAD_SW_IF_INDEX_LABEL;
6214
6215   REPLY_MACRO (VL_API_INPUT_ACL_SET_INTERFACE_REPLY);
6216 }
6217
6218 static void vl_api_ipsec_spd_add_del_t_handler
6219   (vl_api_ipsec_spd_add_del_t * mp)
6220 {
6221 #if IPSEC == 0
6222   clib_warning ("unimplemented");
6223 #else
6224
6225   vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
6226   vl_api_ipsec_spd_add_del_reply_t *rmp;
6227   int rv;
6228
6229 #if DPDK > 0
6230   rv = ipsec_add_del_spd (vm, ntohl (mp->spd_id), mp->is_add);
6231 #else
6232   rv = VNET_API_ERROR_UNIMPLEMENTED;
6233 #endif
6234
6235   REPLY_MACRO (VL_API_IPSEC_SPD_ADD_DEL_REPLY);
6236 #endif
6237 }
6238
6239 static void vl_api_ipsec_interface_add_del_spd_t_handler
6240   (vl_api_ipsec_interface_add_del_spd_t * mp)
6241 {
6242   vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
6243   vl_api_ipsec_interface_add_del_spd_reply_t *rmp;
6244   int rv;
6245   u32 sw_if_index __attribute__ ((unused));
6246   u32 spd_id __attribute__ ((unused));
6247
6248   sw_if_index = ntohl (mp->sw_if_index);
6249   spd_id = ntohl (mp->spd_id);
6250
6251   VALIDATE_SW_IF_INDEX (mp);
6252
6253 #if IPSEC > 0
6254   rv = ipsec_set_interface_spd (vm, sw_if_index, spd_id, mp->is_add);
6255 #else
6256   rv = VNET_API_ERROR_UNIMPLEMENTED;
6257 #endif
6258
6259   BAD_SW_IF_INDEX_LABEL;
6260
6261   REPLY_MACRO (VL_API_IPSEC_INTERFACE_ADD_DEL_SPD_REPLY);
6262 }
6263
6264 static void vl_api_ipsec_spd_add_del_entry_t_handler
6265   (vl_api_ipsec_spd_add_del_entry_t * mp)
6266 {
6267   vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
6268   vl_api_ipsec_spd_add_del_entry_reply_t *rmp;
6269   int rv;
6270
6271 #if IPSEC > 0
6272   ipsec_policy_t p;
6273
6274   memset (&p, 0, sizeof (p));
6275
6276   p.id = ntohl (mp->spd_id);
6277   p.priority = ntohl (mp->priority);
6278   p.is_outbound = mp->is_outbound;
6279   p.is_ipv6 = mp->is_ipv6;
6280
6281   if (mp->is_ipv6 || mp->is_ip_any)
6282     {
6283       clib_memcpy (&p.raddr.start, mp->remote_address_start, 16);
6284       clib_memcpy (&p.raddr.stop, mp->remote_address_stop, 16);
6285       clib_memcpy (&p.laddr.start, mp->local_address_start, 16);
6286       clib_memcpy (&p.laddr.stop, mp->local_address_stop, 16);
6287     }
6288   else
6289     {
6290       clib_memcpy (&p.raddr.start.ip4.data, mp->remote_address_start, 4);
6291       clib_memcpy (&p.raddr.stop.ip4.data, mp->remote_address_stop, 4);
6292       clib_memcpy (&p.laddr.start.ip4.data, mp->local_address_start, 4);
6293       clib_memcpy (&p.laddr.stop.ip4.data, mp->local_address_stop, 4);
6294     }
6295   p.protocol = mp->protocol;
6296   p.rport.start = ntohs (mp->remote_port_start);
6297   p.rport.stop = ntohs (mp->remote_port_stop);
6298   p.lport.start = ntohs (mp->local_port_start);
6299   p.lport.stop = ntohs (mp->local_port_stop);
6300   /* policy action resolve unsupported */
6301   if (mp->policy == IPSEC_POLICY_ACTION_RESOLVE)
6302     {
6303       clib_warning ("unsupported action: 'resolve'");
6304       rv = VNET_API_ERROR_UNIMPLEMENTED;
6305       goto out;
6306     }
6307   p.policy = mp->policy;
6308   p.sa_id = ntohl (mp->sa_id);
6309
6310   rv = ipsec_add_del_policy (vm, &p, mp->is_add);
6311   if (rv)
6312     goto out;
6313
6314   if (mp->is_ip_any)
6315     {
6316       p.is_ipv6 = 1;
6317       rv = ipsec_add_del_policy (vm, &p, mp->is_add);
6318     }
6319 #else
6320   rv = VNET_API_ERROR_UNIMPLEMENTED;
6321   goto out;
6322 #endif
6323
6324 out:
6325   REPLY_MACRO (VL_API_IPSEC_SPD_ADD_DEL_ENTRY_REPLY);
6326 }
6327
6328 static void vl_api_ipsec_sad_add_del_entry_t_handler
6329   (vl_api_ipsec_sad_add_del_entry_t * mp)
6330 {
6331   vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
6332   vl_api_ipsec_sad_add_del_entry_reply_t *rmp;
6333   int rv;
6334 #if IPSEC > 0
6335   ipsec_sa_t sa;
6336
6337   memset (&sa, 0, sizeof (sa));
6338
6339   sa.id = ntohl (mp->sad_id);
6340   sa.spi = ntohl (mp->spi);
6341   /* security protocol AH unsupported */
6342   if (mp->protocol == IPSEC_PROTOCOL_AH)
6343     {
6344       clib_warning ("unsupported security protocol 'AH'");
6345       rv = VNET_API_ERROR_UNIMPLEMENTED;
6346       goto out;
6347     }
6348   sa.protocol = mp->protocol;
6349   /* check for unsupported crypto-alg */
6350   if (mp->crypto_algorithm < IPSEC_CRYPTO_ALG_AES_CBC_128 ||
6351       mp->crypto_algorithm > IPSEC_CRYPTO_ALG_AES_CBC_256)
6352     {
6353       clib_warning ("unsupported crypto-alg: '%U'", format_ipsec_crypto_alg,
6354                     mp->crypto_algorithm);
6355       rv = VNET_API_ERROR_UNIMPLEMENTED;
6356       goto out;
6357     }
6358   sa.crypto_alg = mp->crypto_algorithm;
6359   sa.crypto_key_len = mp->crypto_key_length;
6360   clib_memcpy (&sa.crypto_key, mp->crypto_key, sizeof (sa.crypto_key));
6361   /* check for unsupported integ-alg */
6362   if (mp->integrity_algorithm < IPSEC_INTEG_ALG_SHA1_96 ||
6363       mp->integrity_algorithm > IPSEC_INTEG_ALG_SHA_512_256)
6364     {
6365       clib_warning ("unsupported integ-alg: '%U'", format_ipsec_integ_alg,
6366                     mp->integrity_algorithm);
6367       rv = VNET_API_ERROR_UNIMPLEMENTED;
6368       goto out;
6369     }
6370   sa.integ_alg = mp->integrity_algorithm;
6371   sa.integ_key_len = mp->integrity_key_length;
6372   clib_memcpy (&sa.integ_key, mp->integrity_key, sizeof (sa.integ_key));
6373   sa.use_esn = mp->use_extended_sequence_number;
6374   sa.is_tunnel = mp->is_tunnel;
6375   sa.is_tunnel_ip6 = mp->is_tunnel_ipv6;
6376   if (sa.is_tunnel_ip6)
6377     {
6378       clib_memcpy (&sa.tunnel_src_addr, mp->tunnel_src_address, 16);
6379       clib_memcpy (&sa.tunnel_dst_addr, mp->tunnel_dst_address, 16);
6380     }
6381   else
6382     {
6383       clib_memcpy (&sa.tunnel_src_addr.ip4.data, mp->tunnel_src_address, 4);
6384       clib_memcpy (&sa.tunnel_dst_addr.ip4.data, mp->tunnel_dst_address, 4);
6385     }
6386
6387   rv = ipsec_add_del_sa (vm, &sa, mp->is_add);
6388 #else
6389   rv = VNET_API_ERROR_UNIMPLEMENTED;
6390   goto out;
6391 #endif
6392
6393 out:
6394   REPLY_MACRO (VL_API_IPSEC_SAD_ADD_DEL_ENTRY_REPLY);
6395 }
6396
6397 static void
6398 vl_api_ikev2_profile_add_del_t_handler (vl_api_ikev2_profile_add_del_t * mp)
6399 {
6400   vl_api_ikev2_profile_add_del_reply_t *rmp;
6401   int rv = 0;
6402
6403 #if IPSEC > 0
6404   vlib_main_t *vm = vlib_get_main ();
6405   clib_error_t *error;
6406   u8 *tmp = format (0, "%s", mp->name);
6407   error = ikev2_add_del_profile (vm, tmp, mp->is_add);
6408   vec_free (tmp);
6409   if (error)
6410     rv = VNET_API_ERROR_UNSPECIFIED;
6411 #else
6412   rv = VNET_API_ERROR_UNIMPLEMENTED;
6413 #endif
6414
6415   REPLY_MACRO (VL_API_IKEV2_PROFILE_ADD_DEL_REPLY);
6416 }
6417
6418 static void
6419   vl_api_ikev2_profile_set_auth_t_handler
6420   (vl_api_ikev2_profile_set_auth_t * mp)
6421 {
6422   vl_api_ikev2_profile_set_auth_reply_t *rmp;
6423   int rv = 0;
6424
6425 #if IPSEC > 0
6426   vlib_main_t *vm = vlib_get_main ();
6427   clib_error_t *error;
6428   u8 *tmp = format (0, "%s", mp->name);
6429   u8 *data = vec_new (u8, mp->data_len);
6430   clib_memcpy (data, mp->data, mp->data_len);
6431   error = ikev2_set_profile_auth (vm, tmp, mp->auth_method, data, mp->is_hex);
6432   vec_free (tmp);
6433   vec_free (data);
6434   if (error)
6435     rv = VNET_API_ERROR_UNSPECIFIED;
6436 #else
6437   rv = VNET_API_ERROR_UNIMPLEMENTED;
6438 #endif
6439
6440   REPLY_MACRO (VL_API_IKEV2_PROFILE_SET_AUTH_REPLY);
6441 }
6442
6443 static void
6444 vl_api_ikev2_profile_set_id_t_handler (vl_api_ikev2_profile_set_id_t * mp)
6445 {
6446   vl_api_ikev2_profile_add_del_reply_t *rmp;
6447   int rv = 0;
6448
6449 #if IPSEC > 0
6450   vlib_main_t *vm = vlib_get_main ();
6451   clib_error_t *error;
6452   u8 *tmp = format (0, "%s", mp->name);
6453   u8 *data = vec_new (u8, mp->data_len);
6454   clib_memcpy (data, mp->data, mp->data_len);
6455   error = ikev2_set_profile_id (vm, tmp, mp->id_type, data, mp->is_local);
6456   vec_free (tmp);
6457   vec_free (data);
6458   if (error)
6459     rv = VNET_API_ERROR_UNSPECIFIED;
6460 #else
6461   rv = VNET_API_ERROR_UNIMPLEMENTED;
6462 #endif
6463
6464   REPLY_MACRO (VL_API_IKEV2_PROFILE_SET_ID_REPLY);
6465 }
6466
6467 static void
6468 vl_api_ikev2_profile_set_ts_t_handler (vl_api_ikev2_profile_set_ts_t * mp)
6469 {
6470   vl_api_ikev2_profile_set_ts_reply_t *rmp;
6471   int rv = 0;
6472
6473 #if IPSEC > 0
6474   vlib_main_t *vm = vlib_get_main ();
6475   clib_error_t *error;
6476   u8 *tmp = format (0, "%s", mp->name);
6477   error = ikev2_set_profile_ts (vm, tmp, mp->proto, mp->start_port,
6478                                 mp->end_port, (ip4_address_t) mp->start_addr,
6479                                 (ip4_address_t) mp->end_addr, mp->is_local);
6480   vec_free (tmp);
6481   if (error)
6482     rv = VNET_API_ERROR_UNSPECIFIED;
6483 #else
6484   rv = VNET_API_ERROR_UNIMPLEMENTED;
6485 #endif
6486
6487   REPLY_MACRO (VL_API_IKEV2_PROFILE_SET_TS_REPLY);
6488 }
6489
6490 static void
6491 vl_api_ikev2_set_local_key_t_handler (vl_api_ikev2_set_local_key_t * mp)
6492 {
6493   vl_api_ikev2_profile_set_ts_reply_t *rmp;
6494   int rv = 0;
6495
6496 #if IPSEC > 0
6497   vlib_main_t *vm = vlib_get_main ();
6498   clib_error_t *error;
6499
6500   error = ikev2_set_local_key (vm, mp->key_file);
6501   if (error)
6502     rv = VNET_API_ERROR_UNSPECIFIED;
6503 #else
6504   rv = VNET_API_ERROR_UNIMPLEMENTED;
6505 #endif
6506
6507   REPLY_MACRO (VL_API_IKEV2_SET_LOCAL_KEY_REPLY);
6508 }
6509
6510 static void
6511 vl_api_map_add_domain_t_handler (vl_api_map_add_domain_t * mp)
6512 {
6513   vl_api_map_add_domain_reply_t *rmp;
6514   int rv = 0;
6515   u32 index;
6516   u8 flags = mp->is_translation ? MAP_DOMAIN_TRANSLATION : 0;
6517   rv =
6518     map_create_domain ((ip4_address_t *) & mp->ip4_prefix, mp->ip4_prefix_len,
6519                        (ip6_address_t *) & mp->ip6_prefix, mp->ip6_prefix_len,
6520                        (ip6_address_t *) & mp->ip6_src,
6521                        mp->ip6_src_prefix_len, mp->ea_bits_len,
6522                        mp->psid_offset, mp->psid_length, &index,
6523                        ntohs (mp->mtu), flags);
6524
6525   /* *INDENT-OFF* */
6526   REPLY_MACRO2(VL_API_MAP_ADD_DOMAIN_REPLY,
6527   ({
6528     rmp->index = ntohl(index);
6529   }));
6530   /* *INDENT-ON* */
6531 }
6532
6533 static void
6534 vl_api_map_del_domain_t_handler (vl_api_map_del_domain_t * mp)
6535 {
6536   vl_api_map_del_domain_reply_t *rmp;
6537   int rv = 0;
6538
6539   rv = map_delete_domain (ntohl (mp->index));
6540
6541   REPLY_MACRO (VL_API_MAP_DEL_DOMAIN_REPLY);
6542 }
6543
6544 static void
6545 vl_api_map_add_del_rule_t_handler (vl_api_map_add_del_rule_t * mp)
6546 {
6547   vl_api_map_del_domain_reply_t *rmp;
6548   int rv = 0;
6549
6550   rv =
6551     map_add_del_psid (ntohl (mp->index), ntohs (mp->psid),
6552                       (ip6_address_t *) mp->ip6_dst, mp->is_add);
6553
6554   REPLY_MACRO (VL_API_MAP_ADD_DEL_RULE_REPLY);
6555 }
6556
6557 static void
6558 vl_api_map_domain_dump_t_handler (vl_api_map_domain_dump_t * mp)
6559 {
6560   vl_api_map_domain_details_t *rmp;
6561   map_main_t *mm = &map_main;
6562   map_domain_t *d;
6563   unix_shared_memory_queue_t *q;
6564
6565   if (pool_elts (mm->domains) == 0)
6566     return;
6567
6568   q = vl_api_client_index_to_input_queue (mp->client_index);
6569   if (q == 0)
6570     {
6571       return;
6572     }
6573
6574   /* *INDENT-OFF* */
6575   pool_foreach(d, mm->domains,
6576   ({
6577     /* Make sure every field is initiated (or don't skip the memset()) */
6578     rmp = vl_msg_api_alloc (sizeof (*rmp));
6579     rmp->_vl_msg_id = ntohs(VL_API_MAP_DOMAIN_DETAILS);
6580     rmp->domain_index = htonl(d - mm->domains);
6581     rmp->ea_bits_len = d->ea_bits_len;
6582     rmp->psid_offset = d->psid_offset;
6583     rmp->psid_length = d->psid_length;
6584     clib_memcpy(rmp->ip4_prefix, &d->ip4_prefix, sizeof(rmp->ip4_prefix));
6585     rmp->ip4_prefix_len = d->ip4_prefix_len;
6586     clib_memcpy(rmp->ip6_prefix, &d->ip6_prefix, sizeof(rmp->ip6_prefix));
6587     rmp->ip6_prefix_len = d->ip6_prefix_len;
6588     clib_memcpy(rmp->ip6_src, &d->ip6_src, sizeof(rmp->ip6_src));
6589     rmp->ip6_src_len = d->ip6_src_len;
6590     rmp->mtu = htons(d->mtu);
6591     rmp->is_translation = (d->flags & MAP_DOMAIN_TRANSLATION);
6592     rmp->context = mp->context;
6593
6594     vl_msg_api_send_shmem (q, (u8 *)&rmp);
6595   }));
6596   /* *INDENT-ON* */
6597 }
6598
6599 static void
6600 vl_api_map_rule_dump_t_handler (vl_api_map_rule_dump_t * mp)
6601 {
6602   unix_shared_memory_queue_t *q;
6603   u16 i;
6604   ip6_address_t dst;
6605   vl_api_map_rule_details_t *rmp;
6606   map_main_t *mm = &map_main;
6607   u32 domain_index = ntohl (mp->domain_index);
6608   map_domain_t *d;
6609
6610   if (pool_elts (mm->domains) == 0)
6611     return;
6612
6613   d = pool_elt_at_index (mm->domains, domain_index);
6614   if (!d || !d->rules)
6615     {
6616       return;
6617     }
6618
6619   q = vl_api_client_index_to_input_queue (mp->client_index);
6620   if (q == 0)
6621     {
6622       return;
6623     }
6624
6625   for (i = 0; i < (0x1 << d->psid_length); i++)
6626     {
6627       dst = d->rules[i];
6628       if (dst.as_u64[0] == 0 && dst.as_u64[1] == 0)
6629         {
6630           continue;
6631         }
6632       rmp = vl_msg_api_alloc (sizeof (*rmp));
6633       memset (rmp, 0, sizeof (*rmp));
6634       rmp->_vl_msg_id = ntohs (VL_API_MAP_RULE_DETAILS);
6635       rmp->psid = htons (i);
6636       clib_memcpy (rmp->ip6_dst, &dst, sizeof (rmp->ip6_dst));
6637       rmp->context = mp->context;
6638       vl_msg_api_send_shmem (q, (u8 *) & rmp);
6639     }
6640 }
6641
6642 static void
6643 vl_api_map_summary_stats_t_handler (vl_api_map_summary_stats_t * mp)
6644 {
6645   vl_api_map_summary_stats_reply_t *rmp;
6646   vlib_combined_counter_main_t *cm;
6647   vlib_counter_t v;
6648   int i, which;
6649   u64 total_pkts[VLIB_N_RX_TX];
6650   u64 total_bytes[VLIB_N_RX_TX];
6651   map_main_t *mm = &map_main;
6652   unix_shared_memory_queue_t *q =
6653     vl_api_client_index_to_input_queue (mp->client_index);
6654
6655   if (!q)
6656     return;
6657
6658   rmp = vl_msg_api_alloc (sizeof (*rmp));
6659   rmp->_vl_msg_id = ntohs (VL_API_MAP_SUMMARY_STATS_REPLY);
6660   rmp->context = mp->context;
6661   rmp->retval = 0;
6662
6663   memset (total_pkts, 0, sizeof (total_pkts));
6664   memset (total_bytes, 0, sizeof (total_bytes));
6665
6666   map_domain_counter_lock (mm);
6667   vec_foreach (cm, mm->domain_counters)
6668   {
6669     which = cm - mm->domain_counters;
6670
6671     for (i = 0; i < vec_len (cm->maxi); i++)
6672       {
6673         vlib_get_combined_counter (cm, i, &v);
6674         total_pkts[which] += v.packets;
6675         total_bytes[which] += v.bytes;
6676       }
6677   }
6678
6679   map_domain_counter_unlock (mm);
6680
6681   /* Note: in network byte order! */
6682   rmp->total_pkts[MAP_DOMAIN_COUNTER_RX] =
6683     clib_host_to_net_u64 (total_pkts[MAP_DOMAIN_COUNTER_RX]);
6684   rmp->total_bytes[MAP_DOMAIN_COUNTER_RX] =
6685     clib_host_to_net_u64 (total_bytes[MAP_DOMAIN_COUNTER_RX]);
6686   rmp->total_pkts[MAP_DOMAIN_COUNTER_TX] =
6687     clib_host_to_net_u64 (total_pkts[MAP_DOMAIN_COUNTER_TX]);
6688   rmp->total_bytes[MAP_DOMAIN_COUNTER_TX] =
6689     clib_host_to_net_u64 (total_bytes[MAP_DOMAIN_COUNTER_TX]);
6690   rmp->total_bindings = clib_host_to_net_u64 (pool_elts (mm->domains));
6691   rmp->total_ip4_fragments = 0; // Not yet implemented. Should be a simple counter.
6692   rmp->total_security_check[MAP_DOMAIN_COUNTER_TX] =
6693     clib_host_to_net_u64 (map_error_counter_get
6694                           (ip4_map_node.index, MAP_ERROR_ENCAP_SEC_CHECK));
6695   rmp->total_security_check[MAP_DOMAIN_COUNTER_RX] =
6696     clib_host_to_net_u64 (map_error_counter_get
6697                           (ip4_map_node.index, MAP_ERROR_DECAP_SEC_CHECK));
6698
6699   vl_msg_api_send_shmem (q, (u8 *) & rmp);
6700 }
6701
6702 static void
6703 vl_api_ipsec_sa_set_key_t_handler (vl_api_ipsec_sa_set_key_t * mp)
6704 {
6705   vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
6706   vl_api_ipsec_sa_set_key_reply_t *rmp;
6707   int rv;
6708 #if IPSEC > 0
6709   ipsec_sa_t sa;
6710   sa.id = ntohl (mp->sa_id);
6711   sa.crypto_key_len = mp->crypto_key_length;
6712   clib_memcpy (&sa.crypto_key, mp->crypto_key, sizeof (sa.crypto_key));
6713   sa.integ_key_len = mp->integrity_key_length;
6714   clib_memcpy (&sa.integ_key, mp->integrity_key, sizeof (sa.integ_key));
6715
6716   rv = ipsec_set_sa_key (vm, &sa);
6717 #else
6718   rv = VNET_API_ERROR_UNIMPLEMENTED;
6719 #endif
6720
6721   REPLY_MACRO (VL_API_IPSEC_SA_SET_KEY_REPLY);
6722 }
6723
6724 static void vl_api_cop_interface_enable_disable_t_handler
6725   (vl_api_cop_interface_enable_disable_t * mp)
6726 {
6727   vl_api_cop_interface_enable_disable_reply_t *rmp;
6728   int rv;
6729   u32 sw_if_index = ntohl (mp->sw_if_index);
6730   int enable_disable;
6731
6732   VALIDATE_SW_IF_INDEX (mp);
6733
6734   enable_disable = (int) mp->enable_disable;
6735
6736   rv = cop_interface_enable_disable (sw_if_index, enable_disable);
6737
6738   BAD_SW_IF_INDEX_LABEL;
6739
6740   REPLY_MACRO (VL_API_COP_INTERFACE_ENABLE_DISABLE_REPLY);
6741 }
6742
6743 static void vl_api_cop_whitelist_enable_disable_t_handler
6744   (vl_api_cop_whitelist_enable_disable_t * mp)
6745 {
6746   vl_api_cop_whitelist_enable_disable_reply_t *rmp;
6747   cop_whitelist_enable_disable_args_t _a, *a = &_a;
6748   u32 sw_if_index = ntohl (mp->sw_if_index);
6749   int rv;
6750
6751   VALIDATE_SW_IF_INDEX (mp);
6752
6753   a->sw_if_index = sw_if_index;
6754   a->ip4 = mp->ip4;
6755   a->ip6 = mp->ip6;
6756   a->default_cop = mp->default_cop;
6757   a->fib_id = ntohl (mp->fib_id);
6758
6759   rv = cop_whitelist_enable_disable (a);
6760
6761   BAD_SW_IF_INDEX_LABEL;
6762
6763   REPLY_MACRO (VL_API_COP_WHITELIST_ENABLE_DISABLE_REPLY);
6764 }
6765
6766 static void
6767 vl_api_get_node_graph_t_handler (vl_api_get_node_graph_t * mp)
6768 {
6769   int rv = 0;
6770   u8 *vector = 0;
6771   api_main_t *am = &api_main;
6772   vlib_main_t *vm = vlib_get_main ();
6773   void *oldheap;
6774   vl_api_get_node_graph_reply_t *rmp;
6775
6776   pthread_mutex_lock (&am->vlib_rp->mutex);
6777   oldheap = svm_push_data_heap (am->vlib_rp);
6778
6779   /*
6780    * Keep the number of memcpy ops to a minimum (e.g. 1).
6781    */
6782   vec_validate (vector, 16384);
6783   vec_reset_length (vector);
6784
6785   /* $$$$ FIXME */
6786   vector = vlib_node_serialize (&vm->node_main, vector,
6787                                 (u32) ~ 0 /* all threads */ ,
6788                                 1 /* include nexts */ ,
6789                                 1 /* include stats */ );
6790
6791   svm_pop_heap (oldheap);
6792   pthread_mutex_unlock (&am->vlib_rp->mutex);
6793
6794   /* *INDENT-OFF* */
6795   REPLY_MACRO2(VL_API_GET_NODE_GRAPH_REPLY,
6796   ({
6797     rmp->reply_in_shmem = (uword) vector;
6798   }));
6799   /* *INDENT-ON* */
6800 }
6801
6802 static void vl_api_trace_profile_add_t_handler
6803   (vl_api_trace_profile_add_t * mp)
6804 {
6805   int rv = 0;
6806   vl_api_trace_profile_add_reply_t *rmp;
6807   clib_error_t *error;
6808
6809   /* Ignoring the profile id as currently a single profile
6810    * is supported */
6811   error = ip6_ioam_trace_profile_set (mp->trace_num_elt, mp->trace_type,
6812                                       ntohl (mp->node_id),
6813                                       ntohl (mp->trace_app_data),
6814                                       mp->pow_enable, mp->trace_tsp,
6815                                       mp->trace_ppc);
6816   if (error)
6817     {
6818       clib_error_report (error);
6819       rv = clib_error_get_code (error);
6820     }
6821
6822   REPLY_MACRO (VL_API_TRACE_PROFILE_ADD_REPLY);
6823 }
6824
6825 static void vl_api_trace_profile_apply_t_handler
6826   (vl_api_trace_profile_apply_t * mp)
6827 {
6828   int rv = 0;
6829   vl_api_trace_profile_apply_reply_t *rmp;
6830
6831   if (mp->enable != 0)
6832     {
6833       rv = ip6_ioam_set_destination ((ip6_address_t *) (&mp->dest_ipv6),
6834                                      ntohl (mp->prefix_length),
6835                                      ntohl (mp->vrf_id),
6836                                      mp->trace_op == IOAM_HBYH_ADD,
6837                                      mp->trace_op == IOAM_HBYH_POP,
6838                                      mp->trace_op == IOAM_HBYH_MOD);
6839     }
6840   else
6841     {
6842       //ip6_ioam_clear_destination(&ip6, mp->prefix_length, mp->vrf_id);
6843     }
6844   REPLY_MACRO (VL_API_TRACE_PROFILE_APPLY_REPLY);
6845 }
6846
6847 static void vl_api_trace_profile_del_t_handler
6848   (vl_api_trace_profile_del_t * mp)
6849 {
6850   int rv = 0;
6851   vl_api_trace_profile_del_reply_t *rmp;
6852   clib_error_t *error;
6853
6854   error = clear_ioam_rewrite_fn ();
6855   if (error)
6856     {
6857       clib_error_report (error);
6858       rv = clib_error_get_code (error);
6859     }
6860
6861   REPLY_MACRO (VL_API_TRACE_PROFILE_DEL_REPLY);
6862 }
6863
6864 static void
6865 vl_api_af_packet_create_t_handler (vl_api_af_packet_create_t * mp)
6866 {
6867   vlib_main_t *vm = vlib_get_main ();
6868   vl_api_af_packet_create_reply_t *rmp;
6869   int rv = 0;
6870   u8 *host_if_name = NULL;
6871   u32 sw_if_index;
6872
6873   host_if_name = format (0, "%s", mp->host_if_name);
6874   vec_add1 (host_if_name, 0);
6875
6876   rv = af_packet_create_if (vm, host_if_name,
6877                             mp->use_random_hw_addr ? 0 : mp->hw_addr,
6878                             &sw_if_index);
6879
6880   vec_free (host_if_name);
6881
6882   /* *INDENT-OFF* */
6883   REPLY_MACRO2(VL_API_AF_PACKET_CREATE_REPLY,
6884   ({
6885     rmp->sw_if_index = clib_host_to_net_u32(sw_if_index);
6886   }));
6887   /* *INDENT-ON* */
6888 }
6889
6890 static void
6891 vl_api_af_packet_delete_t_handler (vl_api_af_packet_delete_t * mp)
6892 {
6893   vlib_main_t *vm = vlib_get_main ();
6894   vl_api_af_packet_delete_reply_t *rmp;
6895   int rv = 0;
6896   u8 *host_if_name = NULL;
6897
6898   host_if_name = format (0, "%s", mp->host_if_name);
6899   vec_add1 (host_if_name, 0);
6900
6901   rv = af_packet_delete_if (vm, host_if_name);
6902
6903   vec_free (host_if_name);
6904
6905   REPLY_MACRO (VL_API_AF_PACKET_DELETE_REPLY);
6906 }
6907
6908 static void
6909 vl_api_policer_add_del_t_handler (vl_api_policer_add_del_t * mp)
6910 {
6911   vlib_main_t *vm = vlib_get_main ();
6912   vl_api_policer_add_del_reply_t *rmp;
6913   int rv = 0;
6914   u8 *name = NULL;
6915   sse2_qos_pol_cfg_params_st cfg;
6916   clib_error_t *error;
6917   u32 policer_index;
6918
6919   name = format (0, "%s", mp->name);
6920
6921   memset (&cfg, 0, sizeof (cfg));
6922   cfg.rfc = mp->type;
6923   cfg.rnd_type = mp->round_type;
6924   cfg.rate_type = mp->rate_type;
6925   cfg.rb.kbps.cir_kbps = mp->cir;
6926   cfg.rb.kbps.eir_kbps = mp->eir;
6927   cfg.rb.kbps.cb_bytes = mp->cb;
6928   cfg.rb.kbps.eb_bytes = mp->eb;
6929   cfg.conform_action.action_type = mp->conform_action_type;
6930   cfg.conform_action.dscp = mp->conform_dscp;
6931   cfg.exceed_action.action_type = mp->exceed_action_type;
6932   cfg.exceed_action.dscp = mp->exceed_dscp;
6933   cfg.violate_action.action_type = mp->violate_action_type;
6934   cfg.violate_action.dscp = mp->violate_dscp;
6935   cfg.color_aware = mp->color_aware;
6936
6937   error = policer_add_del (vm, name, &cfg, &policer_index, mp->is_add);
6938
6939   if (error)
6940     rv = VNET_API_ERROR_UNSPECIFIED;
6941
6942   /* *INDENT-OFF* */
6943   REPLY_MACRO2(VL_API_POLICER_ADD_DEL_REPLY,
6944   ({
6945     if (rv == 0 &&  mp->is_add)
6946       rmp->policer_index = ntohl(policer_index);
6947     else
6948       rmp->policer_index = ~0;
6949   }));
6950   /* *INDENT-ON* */
6951 }
6952
6953 static void
6954 send_policer_details (u8 * name,
6955                       sse2_qos_pol_cfg_params_st * config,
6956                       policer_read_response_type_st * templ,
6957                       unix_shared_memory_queue_t * q, u32 context)
6958 {
6959   vl_api_policer_details_t *mp;
6960
6961   mp = vl_msg_api_alloc (sizeof (*mp));
6962   memset (mp, 0, sizeof (*mp));
6963   mp->_vl_msg_id = ntohs (VL_API_POLICER_DETAILS);
6964   mp->context = context;
6965   mp->cir = htonl (config->rb.kbps.cir_kbps);
6966   mp->eir = htonl (config->rb.kbps.eir_kbps);
6967   mp->cb = htonl (config->rb.kbps.cb_bytes);
6968   mp->eb = htonl (config->rb.kbps.eb_bytes);
6969   mp->rate_type = config->rate_type;
6970   mp->round_type = config->rnd_type;
6971   mp->type = config->rfc;
6972   mp->conform_action_type = config->conform_action.action_type;
6973   mp->conform_dscp = config->conform_action.dscp;
6974   mp->exceed_action_type = config->exceed_action.action_type;
6975   mp->exceed_dscp = config->exceed_action.dscp;
6976   mp->violate_action_type = config->violate_action.action_type;
6977   mp->violate_dscp = config->violate_action.dscp;
6978   mp->single_rate = templ->single_rate ? 1 : 0;
6979   mp->color_aware = templ->color_aware ? 1 : 0;
6980   mp->scale = htonl (templ->scale);
6981   mp->cir_tokens_per_period = htonl (templ->cir_tokens_per_period);
6982   mp->pir_tokens_per_period = htonl (templ->pir_tokens_per_period);
6983   mp->current_limit = htonl (templ->current_limit);
6984   mp->current_bucket = htonl (templ->current_bucket);
6985   mp->extended_limit = htonl (templ->extended_limit);
6986   mp->extended_bucket = htonl (templ->extended_bucket);
6987   mp->last_update_time = clib_host_to_net_u64 (templ->last_update_time);
6988
6989   strncpy ((char *) mp->name, (char *) name, ARRAY_LEN (mp->name) - 1);
6990
6991   vl_msg_api_send_shmem (q, (u8 *) & mp);
6992 }
6993
6994 static void
6995 vl_api_policer_dump_t_handler (vl_api_policer_dump_t * mp)
6996 {
6997   unix_shared_memory_queue_t *q;
6998   vnet_policer_main_t *pm = &vnet_policer_main;
6999   hash_pair_t *hp;
7000   uword *p;
7001   u32 pool_index;
7002   u8 *match_name = 0;
7003   u8 *name;
7004   sse2_qos_pol_cfg_params_st *config;
7005   policer_read_response_type_st *templ;
7006
7007   q = vl_api_client_index_to_input_queue (mp->client_index);
7008   if (q == 0)
7009     return;
7010
7011   if (mp->match_name_valid)
7012     {
7013       match_name = format (0, "%s%c", mp->match_name, 0);
7014     }
7015
7016   if (mp->match_name_valid)
7017     {
7018       p = hash_get_mem (pm->policer_config_by_name, match_name);
7019       if (p)
7020         {
7021           pool_index = p[0];
7022           config = pool_elt_at_index (pm->configs, pool_index);
7023           templ = pool_elt_at_index (pm->policer_templates, pool_index);
7024           send_policer_details (match_name, config, templ, q, mp->context);
7025         }
7026     }
7027   else
7028     {
7029       /* *INDENT-OFF* */
7030       hash_foreach_pair (hp, pm->policer_config_by_name,
7031       ({
7032         name = (u8 *) hp->key;
7033         pool_index = hp->value[0];
7034         config = pool_elt_at_index (pm->configs, pool_index);
7035         templ = pool_elt_at_index (pm->policer_templates, pool_index);
7036         send_policer_details(name, config, templ, q, mp->context);
7037       }));
7038       /* *INDENT-ON* */
7039     }
7040 }
7041
7042 static void
7043   vl_api_policer_classify_set_interface_t_handler
7044   (vl_api_policer_classify_set_interface_t * mp)
7045 {
7046   vlib_main_t *vm = vlib_get_main ();
7047   vl_api_policer_classify_set_interface_reply_t *rmp;
7048   int rv;
7049   u32 sw_if_index, ip4_table_index, ip6_table_index, l2_table_index;
7050
7051   ip4_table_index = ntohl (mp->ip4_table_index);
7052   ip6_table_index = ntohl (mp->ip6_table_index);
7053   l2_table_index = ntohl (mp->l2_table_index);
7054   sw_if_index = ntohl (mp->sw_if_index);
7055
7056   VALIDATE_SW_IF_INDEX (mp);
7057
7058   rv = vnet_set_policer_classify_intfc (vm, sw_if_index, ip4_table_index,
7059                                         ip6_table_index, l2_table_index,
7060                                         mp->is_add);
7061
7062   BAD_SW_IF_INDEX_LABEL;
7063
7064   REPLY_MACRO (VL_API_POLICER_CLASSIFY_SET_INTERFACE_REPLY);
7065 }
7066
7067 static void
7068 send_policer_classify_details (u32 sw_if_index,
7069                                u32 table_index,
7070                                unix_shared_memory_queue_t * q, u32 context)
7071 {
7072   vl_api_policer_classify_details_t *mp;
7073
7074   mp = vl_msg_api_alloc (sizeof (*mp));
7075   memset (mp, 0, sizeof (*mp));
7076   mp->_vl_msg_id = ntohs (VL_API_POLICER_CLASSIFY_DETAILS);
7077   mp->context = context;
7078   mp->sw_if_index = htonl (sw_if_index);
7079   mp->table_index = htonl (table_index);
7080
7081   vl_msg_api_send_shmem (q, (u8 *) & mp);
7082 }
7083
7084 static void
7085 vl_api_policer_classify_dump_t_handler (vl_api_policer_classify_dump_t * mp)
7086 {
7087   unix_shared_memory_queue_t *q;
7088   policer_classify_main_t *pcm = &policer_classify_main;
7089   u32 *vec_tbl;
7090   int i;
7091
7092   q = vl_api_client_index_to_input_queue (mp->client_index);
7093   if (q == 0)
7094     return;
7095
7096   vec_tbl = pcm->classify_table_index_by_sw_if_index[mp->type];
7097
7098   if (vec_len (vec_tbl))
7099     {
7100       for (i = 0; i < vec_len (vec_tbl); i++)
7101         {
7102           if (vec_elt (vec_tbl, i) == ~0)
7103             continue;
7104
7105           send_policer_classify_details (i, vec_elt (vec_tbl, i), q,
7106                                          mp->context);
7107         }
7108     }
7109 }
7110
7111 static void
7112 vl_api_netmap_create_t_handler (vl_api_netmap_create_t * mp)
7113 {
7114   vlib_main_t *vm = vlib_get_main ();
7115   vl_api_netmap_create_reply_t *rmp;
7116   int rv = 0;
7117   u8 *if_name = NULL;
7118
7119   if_name = format (0, "%s", mp->netmap_if_name);
7120   vec_add1 (if_name, 0);
7121
7122   rv =
7123     netmap_create_if (vm, if_name, mp->use_random_hw_addr ? 0 : mp->hw_addr,
7124                       mp->is_pipe, mp->is_master, 0);
7125
7126   vec_free (if_name);
7127
7128   REPLY_MACRO (VL_API_NETMAP_CREATE_REPLY);
7129 }
7130
7131 static void
7132 vl_api_netmap_delete_t_handler (vl_api_netmap_delete_t * mp)
7133 {
7134   vlib_main_t *vm = vlib_get_main ();
7135   vl_api_netmap_delete_reply_t *rmp;
7136   int rv = 0;
7137   u8 *if_name = NULL;
7138
7139   if_name = format (0, "%s", mp->netmap_if_name);
7140   vec_add1 (if_name, 0);
7141
7142   rv = netmap_delete_if (vm, if_name);
7143
7144   vec_free (if_name);
7145
7146   REPLY_MACRO (VL_API_NETMAP_DELETE_REPLY);
7147 }
7148
7149 static void
7150 vl_api_mpls_gre_tunnel_details_t_handler (vl_api_mpls_gre_tunnel_details_t *
7151                                           mp)
7152 {
7153   clib_warning ("BUG");
7154 }
7155
7156 static void
7157 send_mpls_gre_tunnel_entry (vpe_api_main_t * am,
7158                             unix_shared_memory_queue_t * q,
7159                             mpls_gre_tunnel_t * gt, u32 index, u32 context)
7160 {
7161   vl_api_mpls_gre_tunnel_details_t *mp;
7162   mpls_main_t *mm = &mpls_main;
7163   mpls_encap_t *e;
7164   int i;
7165   u32 nlabels;
7166
7167   e = pool_elt_at_index (mm->encaps, gt->encap_index);
7168   nlabels = vec_len (e->labels);
7169
7170   mp = vl_msg_api_alloc (sizeof (*mp) + nlabels * sizeof (u32));
7171   memset (mp, 0, sizeof (*mp));
7172   mp->_vl_msg_id = ntohs (VL_API_MPLS_GRE_TUNNEL_DETAILS);
7173   mp->context = context;
7174
7175   mp->tunnel_index = htonl (index);
7176   mp->tunnel_src = gt->tunnel_src.as_u32;
7177   mp->tunnel_dst = gt->tunnel_dst.as_u32;
7178   mp->intfc_address = gt->intfc_address.as_u32;
7179   mp->mask_width = htonl (gt->mask_width);
7180   mp->inner_fib_index = htonl (gt->inner_fib_index);
7181   mp->outer_fib_index = htonl (gt->outer_fib_index);
7182   mp->encap_index = htonl (gt->encap_index);
7183   mp->hw_if_index = htonl (gt->hw_if_index);
7184   mp->l2_only = htonl (gt->l2_only);
7185   mp->nlabels = htonl (nlabels);
7186
7187   for (i = 0; i < nlabels; i++)
7188     {
7189       mp->labels[i] =
7190         htonl (vnet_mpls_uc_get_label
7191                (clib_host_to_net_u32 (e->labels[i].label_exp_s_ttl)));
7192     }
7193
7194   vl_msg_api_send_shmem (q, (u8 *) & mp);
7195 }
7196
7197 static void
7198 vl_api_mpls_gre_tunnel_dump_t_handler (vl_api_mpls_gre_tunnel_dump_t * mp)
7199 {
7200   vpe_api_main_t *am = &vpe_api_main;
7201   unix_shared_memory_queue_t *q;
7202   mpls_main_t *mm = &mpls_main;
7203   mpls_gre_tunnel_t *gt;
7204   u32 index = ntohl (mp->tunnel_index);
7205
7206   q = vl_api_client_index_to_input_queue (mp->client_index);
7207   if (q == 0)
7208     return;
7209
7210   if (index != ~0)
7211     {
7212       if (!pool_is_free_index (mm->gre_tunnels, index))
7213         {
7214           gt = pool_elt_at_index (mm->gre_tunnels, index);
7215           send_mpls_gre_tunnel_entry (am, q, gt, gt - mm->gre_tunnels,
7216                                       mp->context);
7217         }
7218     }
7219   else
7220     {
7221       /* *INDENT-OFF* */
7222       pool_foreach (gt, mm->gre_tunnels,
7223       ({
7224         send_mpls_gre_tunnel_entry (am, q, gt, gt - mm->gre_tunnels,
7225                                     mp->context);
7226       }));
7227       /* *INDENT-ON* */
7228     }
7229 }
7230
7231 static void
7232 vl_api_mpls_eth_tunnel_details_t_handler (vl_api_mpls_eth_tunnel_details_t *
7233                                           mp)
7234 {
7235   clib_warning ("BUG");
7236 }
7237
7238 static void
7239 send_mpls_eth_tunnel_entry (vpe_api_main_t * am,
7240                             unix_shared_memory_queue_t * q,
7241                             mpls_eth_tunnel_t * et, u32 index, u32 context)
7242 {
7243   mpls_main_t *mm = &mpls_main;
7244   mpls_encap_t *e;
7245   int i;
7246   u32 nlabels;
7247   vl_api_mpls_eth_tunnel_details_t *mp;
7248
7249   e = pool_elt_at_index (mm->encaps, et->encap_index);
7250   nlabels = vec_len (e->labels);
7251
7252   mp = vl_msg_api_alloc (sizeof (*mp) + nlabels * sizeof (u32));
7253   memset (mp, 0, sizeof (*mp));
7254   mp->_vl_msg_id = ntohs (VL_API_MPLS_ETH_TUNNEL_DETAILS);
7255   mp->context = context;
7256
7257   mp->tunnel_index = htonl (index);
7258   memcpy (mp->tunnel_dst_mac, et->tunnel_dst, 6);
7259   mp->intfc_address = et->intfc_address.as_u32;
7260   mp->tx_sw_if_index = htonl (et->tx_sw_if_index);
7261   mp->inner_fib_index = htonl (et->inner_fib_index);
7262   mp->mask_width = htonl (et->mask_width);
7263   mp->encap_index = htonl (et->encap_index);
7264   mp->hw_if_index = htonl (et->hw_if_index);
7265   mp->l2_only = htonl (et->l2_only);
7266   mp->nlabels = htonl (nlabels);
7267
7268   for (i = 0; i < nlabels; i++)
7269     {
7270       mp->labels[i] =
7271         htonl (vnet_mpls_uc_get_label
7272                (clib_host_to_net_u32 (e->labels[i].label_exp_s_ttl)));
7273     }
7274
7275   vl_msg_api_send_shmem (q, (u8 *) & mp);
7276 }
7277
7278 static void
7279 vl_api_mpls_eth_tunnel_dump_t_handler (vl_api_mpls_eth_tunnel_dump_t * mp)
7280 {
7281   vpe_api_main_t *am = &vpe_api_main;
7282   unix_shared_memory_queue_t *q;
7283   mpls_main_t *mm = &mpls_main;
7284   mpls_eth_tunnel_t *et;
7285   u32 index = ntohl (mp->tunnel_index);
7286
7287   q = vl_api_client_index_to_input_queue (mp->client_index);
7288   if (q == 0)
7289     return;
7290
7291   if (index != ~0)
7292     {
7293       if (!pool_is_free_index (mm->eth_tunnels, index))
7294         {
7295           et = pool_elt_at_index (mm->eth_tunnels, index);
7296           send_mpls_eth_tunnel_entry (am, q, et, et - mm->eth_tunnels,
7297                                       mp->context);
7298         }
7299     }
7300   else
7301     {
7302       /* *INDENT-OFF* */
7303       pool_foreach (et, mm->eth_tunnels,
7304       ({
7305         send_mpls_eth_tunnel_entry (am, q, et, et - mm->eth_tunnels,
7306                                     mp->context);
7307       }));
7308       /* *INDENT-ON* */
7309     }
7310 }
7311
7312 static void
7313 vl_api_mpls_fib_encap_details_t_handler (vl_api_mpls_fib_encap_details_t * mp)
7314 {
7315   clib_warning ("BUG");
7316 }
7317
7318 static void
7319 send_mpls_fib_encap_details (vpe_api_main_t * am,
7320                              unix_shared_memory_queue_t * q,
7321                              show_mpls_fib_t * s, u32 context)
7322 {
7323   vl_api_mpls_fib_encap_details_t *mp;
7324   mpls_main_t *mm = &mpls_main;
7325   mpls_encap_t *e;
7326   int i;
7327   u32 nlabels;
7328
7329   e = pool_elt_at_index (mm->encaps, s->entry_index);
7330   nlabels = vec_len (e->labels);
7331
7332   mp = vl_msg_api_alloc (sizeof (*mp) + nlabels * sizeof (u32));
7333   memset (mp, 0, sizeof (*mp));
7334   mp->_vl_msg_id = ntohs (VL_API_MPLS_FIB_ENCAP_DETAILS);
7335   mp->context = context;
7336
7337   mp->fib_index = htonl (s->fib_index);
7338   mp->entry_index = htonl (s->entry_index);
7339   mp->dest = s->dest;
7340   mp->s_bit = htonl (s->s_bit);
7341
7342   mp->nlabels = htonl (nlabels);
7343
7344   for (i = 0; i < nlabels; i++)
7345     {
7346       mp->labels[i] =
7347         htonl (vnet_mpls_uc_get_label
7348                (clib_host_to_net_u32 (e->labels[i].label_exp_s_ttl)));
7349     }
7350
7351   vl_msg_api_send_shmem (q, (u8 *) & mp);
7352 }
7353
7354 static void
7355 vl_api_mpls_fib_encap_dump_t_handler (vl_api_mpls_fib_encap_dump_t * mp)
7356 {
7357   vpe_api_main_t *am = &vpe_api_main;
7358   unix_shared_memory_queue_t *q;
7359   vlib_main_t *vm = &vlib_global_main;
7360   u64 key;
7361   u32 value;
7362   show_mpls_fib_t *records = 0;
7363   show_mpls_fib_t *s;
7364   mpls_main_t *mm = &mpls_main;
7365   ip4_main_t *im = &ip4_main;
7366   ip4_fib_t *rx_fib;
7367
7368   q = vl_api_client_index_to_input_queue (mp->client_index);
7369   if (q == 0)
7370     return;
7371
7372   /* *INDENT-OFF* */
7373   hash_foreach (key, value, mm->mpls_encap_by_fib_and_dest,
7374   ({
7375     vec_add2 (records, s, 1);
7376     s->fib_index = (u32)(key>>32);
7377     s->dest = (u32)(key & 0xFFFFFFFF);
7378     s->entry_index = (u32) value;
7379   }));
7380   /* *INDENT-ON* */
7381
7382   if (0 == vec_len (records))
7383     {
7384       vlib_cli_output (vm, "MPLS encap table empty");
7385       goto out;
7386     }
7387
7388   /* sort output by dst address within fib */
7389   vec_sort_with_function (records, mpls_dest_cmp);
7390   vec_sort_with_function (records, mpls_fib_index_cmp);
7391   vlib_cli_output (vm, "MPLS encap table");
7392   vlib_cli_output (vm, "%=6s%=16s%=16s", "Table", "Dest address", "Labels");
7393   vec_foreach (s, records)
7394   {
7395     rx_fib = vec_elt_at_index (im->fibs, s->fib_index);
7396     vlib_cli_output (vm, "%=6d%=16U%=16U", rx_fib->table_id,
7397                      format_ip4_address, &s->dest, format_mpls_encap_index,
7398                      mm, s->entry_index);
7399     send_mpls_fib_encap_details (am, q, s, mp->context);
7400   }
7401
7402 out:
7403   vec_free (records);
7404 }
7405
7406 static void
7407 vl_api_mpls_fib_decap_details_t_handler (vl_api_mpls_fib_decap_details_t * mp)
7408 {
7409   clib_warning ("BUG");
7410 }
7411
7412 static void
7413 send_mpls_fib_decap_details (vpe_api_main_t * am,
7414                              unix_shared_memory_queue_t * q,
7415                              show_mpls_fib_t * s,
7416                              u32 rx_table_id,
7417                              u32 tx_table_id, char *swif_tag, u32 context)
7418 {
7419   vl_api_mpls_fib_decap_details_t *mp;
7420
7421   mp = vl_msg_api_alloc (sizeof (*mp));
7422   memset (mp, 0, sizeof (*mp));
7423   mp->_vl_msg_id = ntohs (VL_API_MPLS_FIB_DECAP_DETAILS);
7424   mp->context = context;
7425
7426   mp->fib_index = htonl (s->fib_index);
7427   mp->entry_index = htonl (s->entry_index);
7428   mp->dest = s->dest;
7429   mp->s_bit = htonl (s->s_bit);
7430   mp->label = htonl (s->label);
7431   mp->rx_table_id = htonl (rx_table_id);
7432   mp->tx_table_id = htonl (tx_table_id);
7433   strncpy ((char *) mp->swif_tag,
7434            (char *) swif_tag, ARRAY_LEN (mp->swif_tag) - 1);
7435
7436   vl_msg_api_send_shmem (q, (u8 *) & mp);
7437 }
7438
7439 static void
7440 vl_api_mpls_fib_decap_dump_t_handler (vl_api_mpls_fib_decap_dump_t * mp)
7441 {
7442   vpe_api_main_t *am = &vpe_api_main;
7443   unix_shared_memory_queue_t *q;
7444   vlib_main_t *vm = &vlib_global_main;
7445   u64 key;
7446   u32 value;
7447   show_mpls_fib_t *records = 0;
7448   show_mpls_fib_t *s;
7449   mpls_main_t *mm = &mpls_main;
7450   ip4_main_t *im = &ip4_main;
7451   ip4_fib_t *rx_fib;
7452   ip4_fib_t *tx_fib;
7453   u32 tx_table_id;
7454   char *swif_tag;
7455
7456   q = vl_api_client_index_to_input_queue (mp->client_index);
7457   if (q == 0)
7458     return;
7459
7460   /* *INDENT-OFF* */
7461   hash_foreach (key, value, mm->mpls_decap_by_rx_fib_and_label,
7462   ({
7463     vec_add2 (records, s, 1);
7464     s->fib_index = (u32)(key>>32);
7465     s->entry_index = (u32) value;
7466     s->label = ((u32) key)>>12;
7467     s->s_bit = (key & (1<<8)) != 0;
7468   }));
7469   /* *INDENT-ON* */
7470
7471   if (!vec_len (records))
7472     {
7473       vlib_cli_output (vm, "MPLS decap table empty");
7474       goto out;
7475     }
7476
7477   vec_sort_with_function (records, mpls_label_cmp);
7478   vlib_cli_output (vm, "MPLS decap table");
7479   vlib_cli_output (vm, "%=10s%=15s%=6s%=6s", "RX Table", "TX Table/Intfc",
7480                    "Label", "S-bit");
7481   vec_foreach (s, records)
7482   {
7483     mpls_decap_t *d;
7484     d = pool_elt_at_index (mm->decaps, s->entry_index);
7485     if (d->next_index == MPLS_INPUT_NEXT_IP4_INPUT)
7486       {
7487         tx_fib = vec_elt_at_index (im->fibs, d->tx_fib_index);
7488         tx_table_id = tx_fib->table_id;
7489         swif_tag = "     ";
7490       }
7491     else
7492       {
7493         tx_table_id = d->tx_fib_index;
7494         swif_tag = "(i)  ";
7495       }
7496     rx_fib = vec_elt_at_index (im->fibs, s->fib_index);
7497
7498     vlib_cli_output (vm, "%=10d%=10d%=5s%=6d%=6d", rx_fib->table_id,
7499                      tx_table_id, swif_tag, s->label, s->s_bit);
7500
7501     send_mpls_fib_decap_details (am, q, s, rx_fib->table_id,
7502                                  tx_table_id, swif_tag, mp->context);
7503   }
7504
7505 out:
7506   vec_free (records);
7507 }
7508
7509 static void
7510 vl_api_classify_table_ids_t_handler (vl_api_classify_table_ids_t * mp)
7511 {
7512   unix_shared_memory_queue_t *q;
7513
7514   q = vl_api_client_index_to_input_queue (mp->client_index);
7515   if (q == 0)
7516     return;
7517
7518   vnet_classify_main_t *cm = &vnet_classify_main;
7519   vnet_classify_table_t *t;
7520   u32 *table_ids = 0;
7521   u32 count;
7522
7523   /* *INDENT-OFF* */
7524   pool_foreach (t, cm->tables,
7525   ({
7526     vec_add1 (table_ids, ntohl(t - cm->tables));
7527   }));
7528   /* *INDENT-ON* */
7529   count = vec_len (table_ids);
7530
7531   vl_api_classify_table_ids_reply_t *rmp;
7532   rmp = vl_msg_api_alloc_as_if_client (sizeof (*rmp) + count * sizeof (u32));
7533   rmp->_vl_msg_id = ntohs (VL_API_CLASSIFY_TABLE_IDS_REPLY);
7534   rmp->context = mp->context;
7535   rmp->count = ntohl (count);
7536   clib_memcpy (rmp->ids, table_ids, count * sizeof (u32));
7537   rmp->retval = 0;
7538
7539   vl_msg_api_send_shmem (q, (u8 *) & rmp);
7540
7541   vec_free (table_ids);
7542 }
7543
7544 static void
7545   vl_api_classify_table_by_interface_t_handler
7546   (vl_api_classify_table_by_interface_t * mp)
7547 {
7548   vl_api_classify_table_by_interface_reply_t *rmp;
7549   int rv = 0;
7550
7551   u32 sw_if_index = ntohl (mp->sw_if_index);
7552   u32 *acl = 0;
7553
7554   vec_validate (acl, INPUT_ACL_N_TABLES - 1);
7555   vec_set (acl, ~0);
7556
7557   VALIDATE_SW_IF_INDEX (mp);
7558
7559   input_acl_main_t *am = &input_acl_main;
7560
7561   int if_idx;
7562   u32 type;
7563
7564   for (type = 0; type < INPUT_ACL_N_TABLES; type++)
7565     {
7566       u32 *vec_tbl = am->classify_table_index_by_sw_if_index[type];
7567       if (vec_len (vec_tbl))
7568         {
7569           for (if_idx = 0; if_idx < vec_len (vec_tbl); if_idx++)
7570             {
7571               if (vec_elt (vec_tbl, if_idx) == ~0 || sw_if_index != if_idx)
7572                 {
7573                   continue;
7574                 }
7575               acl[type] = vec_elt (vec_tbl, if_idx);
7576             }
7577         }
7578     }
7579
7580   BAD_SW_IF_INDEX_LABEL;
7581
7582   /* *INDENT-OFF* */
7583   REPLY_MACRO2(VL_API_CLASSIFY_TABLE_BY_INTERFACE_REPLY,
7584   ({
7585     rmp->sw_if_index = ntohl(sw_if_index);
7586     rmp->l2_table_id = ntohl(acl[INPUT_ACL_TABLE_L2]);
7587     rmp->ip4_table_id = ntohl(acl[INPUT_ACL_TABLE_IP4]);
7588     rmp->ip6_table_id = ntohl(acl[INPUT_ACL_TABLE_IP6]);
7589   }));
7590   /* *INDENT-ON* */
7591   vec_free (acl);
7592 }
7593
7594 static void
7595 vl_api_classify_table_info_t_handler (vl_api_classify_table_info_t * mp)
7596 {
7597   unix_shared_memory_queue_t *q;
7598
7599   q = vl_api_client_index_to_input_queue (mp->client_index);
7600   if (q == 0)
7601     return;
7602
7603   vl_api_classify_table_info_reply_t *rmp = 0;
7604
7605   vnet_classify_main_t *cm = &vnet_classify_main;
7606   u32 table_id = ntohl (mp->table_id);
7607   vnet_classify_table_t *t;
7608
7609   /* *INDENT-OFF* */
7610   pool_foreach (t, cm->tables,
7611   ({
7612     if (table_id == t - cm->tables)
7613       {
7614         rmp = vl_msg_api_alloc_as_if_client
7615           (sizeof (*rmp) + t->match_n_vectors * sizeof (u32x4));
7616         rmp->_vl_msg_id = ntohs (VL_API_CLASSIFY_TABLE_INFO_REPLY);
7617         rmp->context = mp->context;
7618         rmp->table_id = ntohl(table_id);
7619         rmp->nbuckets = ntohl(t->nbuckets);
7620         rmp->match_n_vectors = ntohl(t->match_n_vectors);
7621         rmp->skip_n_vectors = ntohl(t->skip_n_vectors);
7622         rmp->active_sessions = ntohl(t->active_elements);
7623         rmp->next_table_index = ntohl(t->next_table_index);
7624         rmp->miss_next_index = ntohl(t->miss_next_index);
7625         rmp->mask_length = ntohl(t->match_n_vectors * sizeof (u32x4));
7626         clib_memcpy(rmp->mask, t->mask, t->match_n_vectors * sizeof(u32x4));
7627         rmp->retval = 0;
7628         break;
7629       }
7630   }));
7631   /* *INDENT-ON* */
7632
7633   if (rmp == 0)
7634     {
7635       rmp = vl_msg_api_alloc (sizeof (*rmp));
7636       rmp->_vl_msg_id = ntohs ((VL_API_CLASSIFY_TABLE_INFO_REPLY));
7637       rmp->context = mp->context;
7638       rmp->retval = ntohl (VNET_API_ERROR_CLASSIFY_TABLE_NOT_FOUND);
7639     }
7640
7641   vl_msg_api_send_shmem (q, (u8 *) & rmp);
7642 }
7643
7644 static void
7645 vl_api_classify_session_details_t_handler (vl_api_classify_session_details_t *
7646                                            mp)
7647 {
7648   clib_warning ("BUG");
7649 }
7650
7651 static void
7652 send_classify_session_details (unix_shared_memory_queue_t * q,
7653                                u32 table_id,
7654                                u32 match_length,
7655                                vnet_classify_entry_t * e, u32 context)
7656 {
7657   vl_api_classify_session_details_t *rmp;
7658
7659   rmp = vl_msg_api_alloc (sizeof (*rmp));
7660   memset (rmp, 0, sizeof (*rmp));
7661   rmp->_vl_msg_id = ntohs (VL_API_CLASSIFY_SESSION_DETAILS);
7662   rmp->context = context;
7663   rmp->table_id = ntohl (table_id);
7664   rmp->hit_next_index = ntohl (e->next_index);
7665   rmp->advance = ntohl (e->advance);
7666   rmp->opaque_index = ntohl (e->opaque_index);
7667   rmp->match_length = ntohl (match_length);
7668   clib_memcpy (rmp->match, e->key, match_length);
7669
7670   vl_msg_api_send_shmem (q, (u8 *) & rmp);
7671 }
7672
7673 static void
7674 vl_api_classify_session_dump_t_handler (vl_api_classify_session_dump_t * mp)
7675 {
7676   vnet_classify_main_t *cm = &vnet_classify_main;
7677   unix_shared_memory_queue_t *q;
7678
7679   u32 table_id = ntohl (mp->table_id);
7680   vnet_classify_table_t *t;
7681
7682   q = vl_api_client_index_to_input_queue (mp->client_index);
7683
7684   /* *INDENT-OFF* */
7685   pool_foreach (t, cm->tables,
7686   ({
7687     if (table_id == t - cm->tables)
7688       {
7689         vnet_classify_bucket_t * b;
7690         vnet_classify_entry_t * v, * save_v;
7691         int i, j, k;
7692
7693         for (i = 0; i < t->nbuckets; i++)
7694           {
7695             b = &t->buckets [i];
7696             if (b->offset == 0)
7697               continue;
7698
7699             save_v = vnet_classify_get_entry (t, b->offset);
7700             for (j = 0; j < (1<<b->log2_pages); j++)
7701               {
7702                 for (k = 0; k < t->entries_per_page; k++)
7703                   {
7704                     v = vnet_classify_entry_at_index
7705                       (t, save_v, j*t->entries_per_page + k);
7706                     if (vnet_classify_entry_is_free (v))
7707                       continue;
7708
7709                     send_classify_session_details
7710                       (q, table_id, t->match_n_vectors * sizeof (u32x4),
7711                        v, mp->context);
7712                   }
7713               }
7714           }
7715         break;
7716       }
7717   }));
7718   /* *INDENT-ON* */
7719 }
7720
7721 static void
7722 vl_api_ipfix_enable_t_handler (vl_api_ipfix_enable_t * mp)
7723 {
7724   vlib_main_t *vm = vlib_get_main ();
7725   flow_report_main_t *frm = &flow_report_main;
7726   vl_api_ipfix_enable_reply_t *rmp;
7727   ip4_address_t collector, src;
7728   u16 collector_port = UDP_DST_PORT_ipfix;
7729   u32 path_mtu;
7730   u32 template_interval;
7731   u32 fib_id;
7732   u32 fib_index = ~0;
7733   int rv = 0;
7734
7735   memcpy (collector.data, mp->collector_address, sizeof (collector.data));
7736   collector_port = ntohs (mp->collector_port);
7737   if (collector_port == (u16) ~ 0)
7738     collector_port = UDP_DST_PORT_ipfix;
7739   memcpy (src.data, mp->src_address, sizeof (src.data));
7740   fib_id = ntohl (mp->vrf_id);
7741
7742   ip4_main_t *im = &ip4_main;
7743   uword *p = hash_get (im->fib_index_by_table_id, fib_id);
7744   if (!p)
7745     {
7746       rv = VNET_API_ERROR_NO_SUCH_FIB;
7747       goto out;
7748     }
7749   fib_index = p[0];
7750
7751   path_mtu = ntohl (mp->path_mtu);
7752   if (path_mtu == ~0)
7753     path_mtu = 512;             // RFC 7011 section 10.3.3.
7754   template_interval = ntohl (mp->template_interval);
7755   if (template_interval == ~0)
7756     template_interval = 20;
7757
7758   if (collector.as_u32 == 0)
7759     {
7760       rv = VNET_API_ERROR_INVALID_VALUE;
7761       goto out;
7762     }
7763
7764   if (src.as_u32 == 0)
7765     {
7766       rv = VNET_API_ERROR_INVALID_VALUE;
7767       goto out;
7768     }
7769
7770   if (path_mtu > 1450 /* vpp does not support fragmentation */ )
7771     {
7772       rv = VNET_API_ERROR_INVALID_VALUE;
7773       goto out;
7774     }
7775
7776   if (path_mtu < 68)
7777     {
7778       rv = VNET_API_ERROR_INVALID_VALUE;
7779       goto out;
7780     }
7781
7782   /* Reset report streams if we are reconfiguring IP addresses */
7783   if (frm->ipfix_collector.as_u32 != collector.as_u32 ||
7784       frm->src_address.as_u32 != src.as_u32 ||
7785       frm->collector_port != collector_port)
7786     vnet_flow_reports_reset (frm);
7787
7788   frm->ipfix_collector.as_u32 = collector.as_u32;
7789   frm->collector_port = collector_port;
7790   frm->src_address.as_u32 = src.as_u32;
7791   frm->fib_index = fib_index;
7792   frm->path_mtu = path_mtu;
7793   frm->template_interval = template_interval;
7794
7795   /* Turn on the flow reporting process */
7796   vlib_process_signal_event (vm, flow_report_process_node.index, 1, 0);
7797
7798 out:
7799   REPLY_MACRO (VL_API_IPFIX_ENABLE_REPLY);
7800 }
7801
7802 static void
7803 vl_api_ipfix_dump_t_handler (vl_api_ipfix_dump_t * mp)
7804 {
7805   flow_report_main_t *frm = &flow_report_main;
7806   unix_shared_memory_queue_t *q;
7807   vl_api_ipfix_details_t *rmp;
7808
7809   q = vl_api_client_index_to_input_queue (mp->client_index);
7810   if (!q)
7811     return;
7812
7813   rmp = vl_msg_api_alloc (sizeof (*rmp));
7814   memset (rmp, 0, sizeof (*rmp));
7815   rmp->_vl_msg_id = ntohs (VL_API_IPFIX_DETAILS);
7816   rmp->context = mp->context;
7817   memcpy (rmp->collector_address, frm->ipfix_collector.data,
7818           sizeof (frm->ipfix_collector.data));
7819   rmp->collector_port = htons (frm->collector_port);
7820   memcpy (rmp->src_address, frm->src_address.data,
7821           sizeof (frm->src_address.data));
7822   rmp->fib_index = htonl (frm->fib_index);
7823   rmp->path_mtu = htonl (frm->path_mtu);
7824   rmp->template_interval = htonl (frm->template_interval);
7825
7826   vl_msg_api_send_shmem (q, (u8 *) & rmp);
7827 }
7828
7829 static void
7830 vl_api_pg_create_interface_t_handler (vl_api_pg_create_interface_t * mp)
7831 {
7832   vl_api_pg_create_interface_reply_t *rmp;
7833   int rv = 0;
7834
7835   pg_main_t *pg = &pg_main;
7836   u32 sw_if_index = pg_interface_add_or_get (pg, ntohl (mp->interface_id));
7837
7838   /* *INDENT-OFF* */
7839   REPLY_MACRO2(VL_API_PG_CREATE_INTERFACE_REPLY,
7840   ({
7841     rmp->sw_if_index = ntohl(sw_if_index);
7842   }));
7843   /* *INDENT-ON* */
7844 }
7845
7846 static void
7847 vl_api_pg_capture_t_handler (vl_api_pg_capture_t * mp)
7848 {
7849   vl_api_pg_capture_reply_t *rmp;
7850   int rv = 0;
7851
7852   vnet_main_t *vnm = vnet_get_main ();
7853   vnet_interface_main_t *im = &vnm->interface_main;
7854   vnet_hw_interface_t *hi = 0;
7855
7856   u8 *intf_name = format (0, "pg%d", ntohl (mp->interface_id), 0);
7857   u32 hw_if_index = ~0;
7858   uword *p = hash_get_mem (im->hw_interface_by_name, intf_name);
7859   if (p)
7860     hw_if_index = *p;
7861   vec_free (intf_name);
7862
7863   if (hw_if_index != ~0)
7864     {
7865       pg_capture_args_t _a, *a = &_a;
7866
7867       u32 len = ntohl (mp->pcap_name_length);
7868       u8 *pcap_file_name = vec_new (u8, len);
7869       clib_memcpy (pcap_file_name, mp->pcap_file_name, len);
7870
7871       hi = vnet_get_sup_hw_interface (vnm, hw_if_index);
7872       a->hw_if_index = hw_if_index;
7873       a->dev_instance = hi->dev_instance;
7874       a->is_enabled = mp->is_enabled;
7875       a->pcap_file_name = pcap_file_name;
7876       a->count = ntohl (mp->count);
7877
7878       clib_error_t *e = pg_capture (a);
7879       if (e)
7880         {
7881           clib_error_report (e);
7882           rv = VNET_API_ERROR_CANNOT_CREATE_PCAP_FILE;
7883         }
7884
7885       vec_free (pcap_file_name);
7886     }
7887   REPLY_MACRO (VL_API_PG_CAPTURE_REPLY);
7888 }
7889
7890 static void
7891 vl_api_pg_enable_disable_t_handler (vl_api_pg_enable_disable_t * mp)
7892 {
7893   vl_api_pg_enable_disable_reply_t *rmp;
7894   int rv = 0;
7895
7896   pg_main_t *pg = &pg_main;
7897   u32 stream_index = ~0;
7898
7899   int is_enable = mp->is_enabled != 0;
7900   u32 len = ntohl (mp->stream_name_length) - 1;
7901
7902   if (len > 0)
7903     {
7904       u8 *stream_name = vec_new (u8, len);
7905       clib_memcpy (stream_name, mp->stream_name, len);
7906       uword *p = hash_get_mem (pg->stream_index_by_name, stream_name);
7907       if (p)
7908         stream_index = *p;
7909       vec_free (stream_name);
7910     }
7911
7912   pg_enable_disable (stream_index, is_enable);
7913
7914   REPLY_MACRO (VL_API_PG_ENABLE_DISABLE_REPLY);
7915 }
7916
7917 static void
7918   vl_api_ip_source_and_port_range_check_add_del_t_handler
7919   (vl_api_ip_source_and_port_range_check_add_del_t * mp)
7920 {
7921   vl_api_ip_source_and_port_range_check_add_del_reply_t *rmp;
7922   int rv = 0;
7923
7924   u8 is_ipv6 = mp->is_ipv6;
7925   u8 is_add = mp->is_add;
7926   u8 mask_length = mp->mask_length;
7927   ip4_address_t ip4_addr;
7928   ip6_address_t ip6_addr;
7929   u16 *low_ports = 0;
7930   u16 *high_ports = 0;
7931   u32 vrf_id;
7932   u16 tmp_low, tmp_high;
7933   u8 num_ranges;
7934   int i;
7935
7936   // Validate port range
7937   num_ranges = mp->number_of_ranges;
7938   if (num_ranges > 32)
7939     {                           // This is size of array in VPE.API
7940       rv = VNET_API_ERROR_EXCEEDED_NUMBER_OF_RANGES_CAPACITY;
7941       goto reply;
7942     }
7943
7944   vec_reset_length (low_ports);
7945   vec_reset_length (high_ports);
7946
7947   for (i = 0; i < num_ranges; i++)
7948     {
7949       tmp_low = mp->low_ports[i];
7950       tmp_high = mp->high_ports[i];
7951       // If tmp_low <= tmp_high then only need to check tmp_low = 0
7952       // If tmp_low <= tmp_high then only need to check tmp_high > 65535
7953       if (tmp_low > tmp_high || tmp_low == 0 || tmp_high > 65535)
7954         {
7955           rv = VNET_API_ERROR_INVALID_VALUE;
7956           goto reply;
7957         }
7958       vec_add1 (low_ports, tmp_low);
7959       vec_add1 (high_ports, tmp_high + 1);
7960     }
7961
7962   // Validate mask_length
7963   if ((is_ipv6 && mask_length > 128) || (!is_ipv6 && mask_length > 32))
7964     {
7965       rv = VNET_API_ERROR_ADDRESS_LENGTH_MISMATCH;
7966       goto reply;
7967     }
7968
7969   vrf_id = ntohl (mp->vrf_id);
7970
7971   if (vrf_id < 1)
7972     {
7973       rv = VNET_API_ERROR_INVALID_VALUE;
7974       goto reply;
7975     }
7976
7977
7978   if (is_ipv6)
7979     {
7980       clib_memcpy (ip6_addr.as_u8, mp->address, sizeof (ip6_addr.as_u8));
7981       rv = ip6_source_and_port_range_check_add_del (&ip6_addr,
7982                                                     mask_length,
7983                                                     vrf_id,
7984                                                     low_ports,
7985                                                     high_ports, is_add);
7986     }
7987   else
7988     {
7989       clib_memcpy (ip4_addr.data, mp->address, sizeof (ip4_addr));
7990       rv = ip4_source_and_port_range_check_add_del (&ip4_addr,
7991                                                     mask_length,
7992                                                     vrf_id,
7993                                                     low_ports,
7994                                                     high_ports, is_add);
7995     }
7996
7997 reply:
7998   vec_free (low_ports);
7999   vec_free (high_ports);
8000   REPLY_MACRO (VL_API_IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL_REPLY);
8001 }
8002
8003 static void
8004   vl_api_ip_source_and_port_range_check_interface_add_del_t_handler
8005   (vl_api_ip_source_and_port_range_check_interface_add_del_t * mp)
8006 {
8007   vlib_main_t *vm = vlib_get_main ();
8008   vl_api_ip_source_and_port_range_check_interface_add_del_reply_t *rmp;
8009   ip4_main_t *im = &ip4_main;
8010   int rv;
8011   u32 sw_if_index;
8012   u32 fib_index[IP_SOURCE_AND_PORT_RANGE_CHECK_N_PROTOCOLS];
8013   u32 vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_N_PROTOCOLS];
8014   uword *p = 0;
8015   int i;
8016
8017   vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_TCP_OUT] =
8018     ntohl (mp->tcp_out_vrf_id);
8019   vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_UDP_OUT] =
8020     ntohl (mp->udp_out_vrf_id);
8021   vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_TCP_IN] =
8022     ntohl (mp->tcp_in_vrf_id);
8023   vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_UDP_IN] =
8024     ntohl (mp->udp_in_vrf_id);
8025
8026
8027   for (i = 0; i < IP_SOURCE_AND_PORT_RANGE_CHECK_N_PROTOCOLS; i++)
8028     {
8029       if (vrf_id[i] != 0 && vrf_id[i] != ~0)
8030         {
8031           p = hash_get (im->fib_index_by_table_id, vrf_id[i]);
8032
8033           if (p == 0)
8034             {
8035               rv = VNET_API_ERROR_INVALID_VALUE;
8036               goto reply;
8037             }
8038
8039           fib_index[i] = p[0];
8040         }
8041       else
8042         fib_index[i] = ~0;
8043     }
8044   sw_if_index = ntohl (mp->sw_if_index);
8045
8046   VALIDATE_SW_IF_INDEX (mp);
8047
8048   rv =
8049     set_ip_source_and_port_range_check (vm, fib_index, sw_if_index,
8050                                         mp->is_add);
8051
8052   BAD_SW_IF_INDEX_LABEL;
8053 reply:
8054
8055   REPLY_MACRO (VL_API_IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL_REPLY);
8056 }
8057
8058 static void
8059 vl_api_ipsec_gre_add_del_tunnel_t_handler (vl_api_ipsec_gre_add_del_tunnel_t *
8060                                            mp)
8061 {
8062   vl_api_ipsec_gre_add_del_tunnel_reply_t *rmp;
8063   int rv = 0;
8064   vnet_ipsec_gre_add_del_tunnel_args_t _a, *a = &_a;
8065   u32 sw_if_index = ~0;
8066
8067   /* Check src & dst are different */
8068   if (memcmp (mp->src_address, mp->dst_address, 4) == 0)
8069     {
8070       rv = VNET_API_ERROR_SAME_SRC_DST;
8071       goto out;
8072     }
8073
8074   memset (a, 0, sizeof (*a));
8075
8076   /* ip addresses sent in network byte order */
8077   clib_memcpy (&(a->src), mp->src_address, 4);
8078   clib_memcpy (&(a->dst), mp->dst_address, 4);
8079   a->is_add = mp->is_add;
8080   a->lsa = ntohl (mp->local_sa_id);
8081   a->rsa = ntohl (mp->remote_sa_id);
8082
8083   rv = vnet_ipsec_gre_add_del_tunnel (a, &sw_if_index);
8084
8085 out:
8086     /* *INDENT-OFF* */
8087     REPLY_MACRO2(VL_API_GRE_ADD_DEL_TUNNEL_REPLY,
8088     ({
8089         rmp->sw_if_index = ntohl (sw_if_index);
8090     }));
8091     /* *INDENT-ON* */
8092 }
8093
8094 static void send_ipsec_gre_tunnel_details
8095   (ipsec_gre_tunnel_t * t, unix_shared_memory_queue_t * q, u32 context)
8096 {
8097   vl_api_ipsec_gre_tunnel_details_t *rmp;
8098
8099   rmp = vl_msg_api_alloc (sizeof (*rmp));
8100   memset (rmp, 0, sizeof (*rmp));
8101   rmp->_vl_msg_id = ntohs (VL_API_IPSEC_GRE_TUNNEL_DETAILS);
8102   clib_memcpy (rmp->src_address, &(t->tunnel_src), 4);
8103   clib_memcpy (rmp->dst_address, &(t->tunnel_dst), 4);
8104   rmp->sw_if_index = htonl (t->sw_if_index);
8105   rmp->local_sa_id = htonl (t->local_sa_id);
8106   rmp->remote_sa_id = htonl (t->remote_sa_id);
8107   rmp->context = context;
8108
8109   vl_msg_api_send_shmem (q, (u8 *) & rmp);
8110 }
8111
8112 static void vl_api_ipsec_gre_tunnel_dump_t_handler
8113   (vl_api_ipsec_gre_tunnel_dump_t * mp)
8114 {
8115   unix_shared_memory_queue_t *q;
8116   ipsec_gre_main_t *igm = &ipsec_gre_main;
8117   ipsec_gre_tunnel_t *t;
8118   u32 sw_if_index;
8119
8120   q = vl_api_client_index_to_input_queue (mp->client_index);
8121   if (q == 0)
8122     {
8123       return;
8124     }
8125
8126   sw_if_index = ntohl (mp->sw_if_index);
8127
8128   if (~0 == sw_if_index)
8129     {
8130         /* *INDENT-OFF* */
8131         pool_foreach (t, igm->tunnels,
8132         ({
8133             send_ipsec_gre_tunnel_details(t, q, mp->context);
8134         }));
8135         /* *INDENT-ON* */
8136     }
8137   else
8138     {
8139       if ((sw_if_index >= vec_len (igm->tunnel_index_by_sw_if_index)) ||
8140           (~0 == igm->tunnel_index_by_sw_if_index[sw_if_index]))
8141         {
8142           return;
8143         }
8144       t = &igm->tunnels[igm->tunnel_index_by_sw_if_index[sw_if_index]];
8145       send_ipsec_gre_tunnel_details (t, q, mp->context);
8146     }
8147 }
8148
8149 #define BOUNCE_HANDLER(nn)                                              \
8150 static void vl_api_##nn##_t_handler (                                   \
8151     vl_api_##nn##_t *mp)                                                \
8152 {                                                                       \
8153     vpe_client_registration_t *reg;                                     \
8154     vpe_api_main_t * vam = &vpe_api_main;                               \
8155     unix_shared_memory_queue_t * q;                                     \
8156                                                                         \
8157     /* One registration only... */                                      \
8158     pool_foreach(reg, vam->nn##_registrations,                          \
8159     ({                                                                  \
8160         q = vl_api_client_index_to_input_queue (reg->client_index);     \
8161         if (q) {                                                        \
8162             /*                                                          \
8163              * If the queue is stuffed, turf the msg and complain       \
8164              * It's unlikely that the intended recipient is             \
8165              * alive; avoid deadlock at all costs.                      \
8166              */                                                         \
8167             if (q->cursize == q->maxsize) {                             \
8168                 clib_warning ("ERROR: receiver queue full, drop msg");  \
8169                 vl_msg_api_free (mp);                                   \
8170                 return;                                                 \
8171             }                                                           \
8172             vl_msg_api_send_shmem (q, (u8 *)&mp);                       \
8173             return;                                                     \
8174         }                                                               \
8175     }));                                                                \
8176     vl_msg_api_free (mp);                                               \
8177 }
8178
8179 /*
8180  * vpe_api_hookup
8181  * Add vpe's API message handlers to the table.
8182  * vlib has alread mapped shared memory and
8183  * added the client registration handlers.
8184  * See .../open-repo/vlib/memclnt_vlib.c:memclnt_process()
8185  */
8186
8187 static clib_error_t *
8188 vpe_api_hookup (vlib_main_t * vm)
8189 {
8190   api_main_t *am = &api_main;
8191
8192 #define _(N,n)                                                  \
8193     vl_msg_api_set_handlers(VL_API_##N, #n,                     \
8194                            vl_api_##n##_t_handler,              \
8195                            vl_noop_handler,                     \
8196                            vl_api_##n##_t_endian,               \
8197                            vl_api_##n##_t_print,                \
8198                            sizeof(vl_api_##n##_t), 1);
8199   foreach_vpe_api_msg;
8200 #undef _
8201
8202   /*
8203    * Manually register the sr tunnel add del msg, so we trace
8204    * enough bytes to capture a typical segment list
8205    */
8206   vl_msg_api_set_handlers (VL_API_SR_TUNNEL_ADD_DEL,
8207                            "sr_tunnel_add_del",
8208                            vl_api_sr_tunnel_add_del_t_handler,
8209                            vl_noop_handler,
8210                            vl_api_sr_tunnel_add_del_t_endian,
8211                            vl_api_sr_tunnel_add_del_t_print, 256, 1);
8212
8213
8214   /*
8215    * Manually register the sr policy add del msg, so we trace
8216    * enough bytes to capture a typical tunnel name list
8217    */
8218   vl_msg_api_set_handlers (VL_API_SR_POLICY_ADD_DEL,
8219                            "sr_policy_add_del",
8220                            vl_api_sr_policy_add_del_t_handler,
8221                            vl_noop_handler,
8222                            vl_api_sr_policy_add_del_t_endian,
8223                            vl_api_sr_policy_add_del_t_print, 256, 1);
8224
8225   /*
8226    * Trace space for 8 MPLS encap labels, classifier mask+match
8227    */
8228   am->api_trace_cfg[VL_API_MPLS_ADD_DEL_ENCAP].size += 8 * sizeof (u32);
8229   am->api_trace_cfg[VL_API_CLASSIFY_ADD_DEL_TABLE].size += 5 * sizeof (u32x4);
8230   am->api_trace_cfg[VL_API_CLASSIFY_ADD_DEL_SESSION].size
8231     += 5 * sizeof (u32x4);
8232   am->api_trace_cfg[VL_API_VXLAN_ADD_DEL_TUNNEL].size += 16 * sizeof (u32);
8233
8234   /*
8235    * Thread-safe API messages
8236    */
8237   am->is_mp_safe[VL_API_IP_ADD_DEL_ROUTE] = 1;
8238   am->is_mp_safe[VL_API_GET_NODE_GRAPH] = 1;
8239
8240   return 0;
8241 }
8242
8243 VLIB_API_INIT_FUNCTION (vpe_api_hookup);
8244
8245 static clib_error_t *
8246 vpe_api_init (vlib_main_t * vm)
8247 {
8248   vpe_api_main_t *am = &vpe_api_main;
8249
8250   am->vlib_main = vm;
8251   am->vnet_main = vnet_get_main ();
8252   am->interface_events_registration_hash = hash_create (0, sizeof (uword));
8253   am->to_netconf_server_registration_hash = hash_create (0, sizeof (uword));
8254   am->from_netconf_server_registration_hash = hash_create (0, sizeof (uword));
8255   am->to_netconf_client_registration_hash = hash_create (0, sizeof (uword));
8256   am->from_netconf_client_registration_hash = hash_create (0, sizeof (uword));
8257   am->oam_events_registration_hash = hash_create (0, sizeof (uword));
8258
8259   vl_api_init (vm);
8260   vl_set_memory_region_name ("/vpe-api");
8261   vl_enable_disable_memory_api (vm, 1 /* enable it */ );
8262
8263   return 0;
8264 }
8265
8266 VLIB_INIT_FUNCTION (vpe_api_init);
8267
8268
8269 static clib_error_t *
8270 api_segment_config (vlib_main_t * vm, unformat_input_t * input)
8271 {
8272   u8 *chroot_path;
8273   u64 baseva, size, pvt_heap_size;
8274   int uid, gid, rv;
8275   const int max_buf_size = 4096;
8276   char *s, *buf;
8277   struct passwd _pw, *pw;
8278   struct group _grp, *grp;
8279   clib_error_t *e;
8280   buf = vec_new (char, 128);
8281   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
8282     {
8283       if (unformat (input, "prefix %s", &chroot_path))
8284         {
8285           vec_add1 (chroot_path, 0);
8286           vl_set_memory_root_path ((char *) chroot_path);
8287         }
8288       else if (unformat (input, "uid %d", &uid))
8289         vl_set_memory_uid (uid);
8290       else if (unformat (input, "gid %d", &gid))
8291         vl_set_memory_gid (gid);
8292       else if (unformat (input, "baseva %llx", &baseva))
8293         vl_set_global_memory_baseva (baseva);
8294       else if (unformat (input, "global-size %lldM", &size))
8295         vl_set_global_memory_size (size * (1ULL << 20));
8296       else if (unformat (input, "global-size %lldG", &size))
8297         vl_set_global_memory_size (size * (1ULL << 30));
8298       else if (unformat (input, "global-size %lld", &size))
8299         vl_set_global_memory_size (size);
8300       else if (unformat (input, "global-pvt-heap-size %lldM", &pvt_heap_size))
8301         vl_set_global_pvt_heap_size (pvt_heap_size * (1ULL << 20));
8302       else if (unformat (input, "global-pvt-heap-size size %lld",
8303                          &pvt_heap_size))
8304         vl_set_global_pvt_heap_size (pvt_heap_size);
8305       else if (unformat (input, "api-pvt-heap-size %lldM", &pvt_heap_size))
8306         vl_set_api_pvt_heap_size (pvt_heap_size * (1ULL << 20));
8307       else if (unformat (input, "api-pvt-heap-size size %lld",
8308                          &pvt_heap_size))
8309         vl_set_api_pvt_heap_size (pvt_heap_size);
8310       else if (unformat (input, "api-size %lldM", &size))
8311         vl_set_api_memory_size (size * (1ULL << 20));
8312       else if (unformat (input, "api-size %lldG", &size))
8313         vl_set_api_memory_size (size * (1ULL << 30));
8314       else if (unformat (input, "api-size %lld", &size))
8315         vl_set_api_memory_size (size);
8316       else if (unformat (input, "uid %s", &s))
8317         {
8318           /* lookup the username */
8319           pw = NULL;
8320           while (((rv =
8321                    getpwnam_r (s, &_pw, buf, vec_len (buf), &pw)) == ERANGE)
8322                  && (vec_len (buf) <= max_buf_size))
8323             {
8324               vec_resize (buf, vec_len (buf) * 2);
8325             }
8326           if (rv < 0)
8327             {
8328               e = clib_error_return_code (0, rv,
8329                                           CLIB_ERROR_ERRNO_VALID |
8330                                           CLIB_ERROR_FATAL,
8331                                           "cannot fetch username %s", s);
8332               vec_free (s);
8333               vec_free (buf);
8334               return e;
8335             }
8336           if (pw == NULL)
8337             {
8338               e =
8339                 clib_error_return_fatal (0, "username %s does not exist", s);
8340               vec_free (s);
8341               vec_free (buf);
8342               return e;
8343             }
8344           vec_free (s);
8345           vl_set_memory_uid (pw->pw_uid);
8346         }
8347       else if (unformat (input, "gid %s", &s))
8348         {
8349           /* lookup the group name */
8350           grp = NULL;
8351           while (((rv =
8352                    getgrnam_r (s, &_grp, buf, vec_len (buf), &grp)) == ERANGE)
8353                  && (vec_len (buf) <= max_buf_size))
8354             {
8355               vec_resize (buf, vec_len (buf) * 2);
8356             }
8357           if (rv != 0)
8358             {
8359               e = clib_error_return_code (0, rv,
8360                                           CLIB_ERROR_ERRNO_VALID |
8361                                           CLIB_ERROR_FATAL,
8362                                           "cannot fetch group %s", s);
8363               vec_free (s);
8364               vec_free (buf);
8365               return e;
8366             }
8367           if (grp == NULL)
8368             {
8369               e = clib_error_return_fatal (0, "group %s does not exist", s);
8370               vec_free (s);
8371               vec_free (buf);
8372               return e;
8373             }
8374           vec_free (s);
8375           vec_free (buf);
8376           vl_set_memory_gid (grp->gr_gid);
8377         }
8378       else
8379         return clib_error_return (0, "unknown input `%U'",
8380                                   format_unformat_error, input);
8381     }
8382   return 0;
8383 }
8384
8385 VLIB_EARLY_CONFIG_FUNCTION (api_segment_config, "api-segment");
8386
8387 void *
8388 get_unformat_vnet_sw_interface (void)
8389 {
8390   return (void *) &unformat_vnet_sw_interface;
8391 }
8392
8393 #undef vl_api_version
8394 #define vl_api_version(n,v) static u32 vpe_api_version = v;
8395 #include <vpp-api/vpe.api.h>
8396 #undef vl_api_version
8397
8398 int
8399 vl_msg_api_version_check (vl_api_memclnt_create_t * mp)
8400 {
8401   if (clib_host_to_net_u32 (mp->api_versions[0]) != vpe_api_version)
8402     {
8403       clib_warning ("vpe API mismatch: 0x%08x instead of 0x%08x",
8404                     clib_host_to_net_u32 (mp->api_versions[0]),
8405                     vpe_api_version);
8406       return -1;
8407     }
8408   return 0;
8409 }
8410
8411 static u8 *
8412 format_arp_event (u8 * s, va_list * args)
8413 {
8414   vl_api_ip4_arp_event_t *event = va_arg (*args, vl_api_ip4_arp_event_t *);
8415
8416   s = format (s, "pid %d: %U", event->pid,
8417               format_ip4_address, &event->address);
8418   return s;
8419 }
8420
8421 static clib_error_t *
8422 show_ip4_arp_events_fn (vlib_main_t * vm,
8423                         unformat_input_t * input, vlib_cli_command_t * cmd)
8424 {
8425   vpe_api_main_t *am = &vpe_api_main;
8426   vl_api_ip4_arp_event_t *event;
8427
8428   if (pool_elts (am->arp_events) == 0)
8429     {
8430       vlib_cli_output (vm, "No active arp event registrations");
8431       return 0;
8432     }
8433
8434   /* *INDENT-OFF* */
8435   pool_foreach (event, am->arp_events,
8436   ({
8437     vlib_cli_output (vm, "%U", format_arp_event, event);
8438   }));
8439   /* *INDENT-ON* */
8440
8441   return 0;
8442 }
8443
8444 /* *INDENT-OFF* */
8445 VLIB_CLI_COMMAND (show_ip4_arp_events, static) = {
8446   .path = "show arp event registrations",
8447   .function = show_ip4_arp_events_fn,
8448   .short_help = "Show arp event registrations",
8449 };
8450 /* *INDENT-ON* */
8451
8452 /*
8453  * fd.io coding-style-patch-verification: ON
8454  *
8455  * Local Variables:
8456  * eval: (c-set-style "gnu")
8457  * End:
8458  */