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