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