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