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