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