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