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