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