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