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