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