VXLAN tunnel encap forwarding optimization with FIB 2.0
[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 = !ip46_address_is_ip4 (&t->dst);
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   /* decap_next_index is deprecated, hard code to l2-input */
4947   rmp->decap_next_index = htonl (VXLAN_INPUT_NEXT_L2_INPUT);
4948   rmp->sw_if_index = htonl (t->sw_if_index);
4949   rmp->is_ipv6 = is_ipv6;
4950   rmp->context = context;
4951
4952   vl_msg_api_send_shmem (q, (u8 *) & rmp);
4953 }
4954
4955 static void vl_api_vxlan_tunnel_dump_t_handler
4956   (vl_api_vxlan_tunnel_dump_t * mp)
4957 {
4958   unix_shared_memory_queue_t *q;
4959   vxlan_main_t *vxm = &vxlan_main;
4960   vxlan_tunnel_t *t;
4961   u32 sw_if_index;
4962
4963   q = vl_api_client_index_to_input_queue (mp->client_index);
4964   if (q == 0)
4965     {
4966       return;
4967     }
4968
4969   sw_if_index = ntohl (mp->sw_if_index);
4970
4971   if (~0 == sw_if_index)
4972     {
4973       /* *INDENT-OFF* */
4974       pool_foreach (t, vxm->tunnels,
4975       ({
4976         send_vxlan_tunnel_details(t, q, mp->context);
4977       }));
4978       /* *INDENT-ON* */
4979     }
4980   else
4981     {
4982       if ((sw_if_index >= vec_len (vxm->tunnel_index_by_sw_if_index)) ||
4983           (~0 == vxm->tunnel_index_by_sw_if_index[sw_if_index]))
4984         {
4985           return;
4986         }
4987       t = &vxm->tunnels[vxm->tunnel_index_by_sw_if_index[sw_if_index]];
4988       send_vxlan_tunnel_details (t, q, mp->context);
4989     }
4990 }
4991
4992 static void vl_api_gre_add_del_tunnel_t_handler
4993   (vl_api_gre_add_del_tunnel_t * mp)
4994 {
4995   vl_api_gre_add_del_tunnel_reply_t *rmp;
4996   int rv = 0;
4997   vnet_gre_add_del_tunnel_args_t _a, *a = &_a;
4998   u32 outer_fib_id;
4999   uword *p;
5000   ip4_main_t *im = &ip4_main;
5001   u32 sw_if_index = ~0;
5002
5003   p = hash_get (im->fib_index_by_table_id, ntohl (mp->outer_fib_id));
5004   if (!p)
5005     {
5006       rv = VNET_API_ERROR_NO_SUCH_FIB;
5007       goto out;
5008     }
5009   outer_fib_id = p[0];
5010
5011   /* Check src & dst are different */
5012   if ((mp->is_ipv6 && memcmp (mp->src_address, mp->dst_address, 16) == 0) ||
5013       (!mp->is_ipv6 && memcmp (mp->src_address, mp->dst_address, 4) == 0))
5014     {
5015       rv = VNET_API_ERROR_SAME_SRC_DST;
5016       goto out;
5017     }
5018   memset (a, 0, sizeof (*a));
5019
5020   a->is_add = mp->is_add;
5021   a->teb = mp->teb;
5022
5023   /* ip addresses sent in network byte order */
5024   clib_memcpy (&(a->src), mp->src_address, 4);
5025   clib_memcpy (&(a->dst), mp->dst_address, 4);
5026
5027   a->outer_fib_id = outer_fib_id;
5028   rv = vnet_gre_add_del_tunnel (a, &sw_if_index);
5029
5030 out:
5031   /* *INDENT-OFF* */
5032   REPLY_MACRO2(VL_API_GRE_ADD_DEL_TUNNEL_REPLY,
5033   ({
5034     rmp->sw_if_index = ntohl (sw_if_index);
5035   }));
5036   /* *INDENT-ON* */
5037 }
5038
5039 static void send_gre_tunnel_details
5040   (gre_tunnel_t * t, unix_shared_memory_queue_t * q, u32 context)
5041 {
5042   vl_api_gre_tunnel_details_t *rmp;
5043   ip4_main_t *im = &ip4_main;
5044
5045   rmp = vl_msg_api_alloc (sizeof (*rmp));
5046   memset (rmp, 0, sizeof (*rmp));
5047   rmp->_vl_msg_id = ntohs (VL_API_GRE_TUNNEL_DETAILS);
5048   clib_memcpy (rmp->src_address, &(t->tunnel_src), 4);
5049   clib_memcpy (rmp->dst_address, &(t->tunnel_dst), 4);
5050   rmp->outer_fib_id = htonl (im->fibs[t->outer_fib_index].ft_table_id);
5051   rmp->teb = t->teb;
5052   rmp->sw_if_index = htonl (t->sw_if_index);
5053   rmp->context = context;
5054
5055   vl_msg_api_send_shmem (q, (u8 *) & rmp);
5056 }
5057
5058 static void
5059 vl_api_gre_tunnel_dump_t_handler (vl_api_gre_tunnel_dump_t * mp)
5060 {
5061   unix_shared_memory_queue_t *q;
5062   gre_main_t *gm = &gre_main;
5063   gre_tunnel_t *t;
5064   u32 sw_if_index;
5065
5066   q = vl_api_client_index_to_input_queue (mp->client_index);
5067   if (q == 0)
5068     {
5069       return;
5070     }
5071
5072   sw_if_index = ntohl (mp->sw_if_index);
5073
5074   if (~0 == sw_if_index)
5075     {
5076       /* *INDENT-OFF* */
5077       pool_foreach (t, gm->tunnels,
5078       ({
5079         send_gre_tunnel_details(t, q, mp->context);
5080       }));
5081       /* *INDENT-ON* */
5082     }
5083   else
5084     {
5085       if ((sw_if_index >= vec_len (gm->tunnel_index_by_sw_if_index)) ||
5086           (~0 == gm->tunnel_index_by_sw_if_index[sw_if_index]))
5087         {
5088           return;
5089         }
5090       t = &gm->tunnels[gm->tunnel_index_by_sw_if_index[sw_if_index]];
5091       send_gre_tunnel_details (t, q, mp->context);
5092     }
5093 }
5094
5095 static void
5096 vl_api_l2_patch_add_del_t_handler (vl_api_l2_patch_add_del_t * mp)
5097 {
5098   extern int vnet_l2_patch_add_del (u32 rx_sw_if_index, u32 tx_sw_if_index,
5099                                     int is_add);
5100   vl_api_l2_patch_add_del_reply_t *rmp;
5101   int vnet_l2_patch_add_del (u32 rx_sw_if_index, u32 tx_sw_if_index,
5102                              int is_add);
5103   int rv = 0;
5104
5105   VALIDATE_RX_SW_IF_INDEX (mp);
5106   VALIDATE_TX_SW_IF_INDEX (mp);
5107
5108   rv = vnet_l2_patch_add_del (ntohl (mp->rx_sw_if_index),
5109                               ntohl (mp->tx_sw_if_index),
5110                               (int) (mp->is_add != 0));
5111
5112   BAD_RX_SW_IF_INDEX_LABEL;
5113   BAD_TX_SW_IF_INDEX_LABEL;
5114
5115   REPLY_MACRO (VL_API_L2_PATCH_ADD_DEL_REPLY);
5116 }
5117
5118 static void
5119   vl_api_vxlan_gpe_add_del_tunnel_t_handler
5120   (vl_api_vxlan_gpe_add_del_tunnel_t * mp)
5121 {
5122   vl_api_vxlan_gpe_add_del_tunnel_reply_t *rmp;
5123   int rv = 0;
5124   vnet_vxlan_gpe_add_del_tunnel_args_t _a, *a = &_a;
5125   u32 encap_fib_index, decap_fib_index;
5126   u8 protocol;
5127   uword *p;
5128   ip4_main_t *im = &ip4_main;
5129   u32 sw_if_index = ~0;
5130
5131
5132   p = hash_get (im->fib_index_by_table_id, ntohl (mp->encap_vrf_id));
5133   if (!p)
5134     {
5135       rv = VNET_API_ERROR_NO_SUCH_FIB;
5136       goto out;
5137     }
5138   encap_fib_index = p[0];
5139
5140   protocol = mp->protocol;
5141
5142   /* Interpret decap_vrf_id as an opaque if sending to other-than-ip4-input */
5143   if (protocol == VXLAN_GPE_INPUT_NEXT_IP4_INPUT)
5144     {
5145       p = hash_get (im->fib_index_by_table_id, ntohl (mp->decap_vrf_id));
5146       if (!p)
5147         {
5148           rv = VNET_API_ERROR_NO_SUCH_INNER_FIB;
5149           goto out;
5150         }
5151       decap_fib_index = p[0];
5152     }
5153   else
5154     {
5155       decap_fib_index = ntohl (mp->decap_vrf_id);
5156     }
5157
5158   /* Check src & dst are different */
5159   if ((mp->is_ipv6 && memcmp (mp->local, mp->remote, 16) == 0) ||
5160       (!mp->is_ipv6 && memcmp (mp->local, mp->remote, 4) == 0))
5161     {
5162       rv = VNET_API_ERROR_SAME_SRC_DST;
5163       goto out;
5164     }
5165   memset (a, 0, sizeof (*a));
5166
5167   a->is_add = mp->is_add;
5168   a->is_ip6 = mp->is_ipv6;
5169   /* ip addresses sent in network byte order */
5170   if (a->is_ip6)
5171     {
5172       clib_memcpy (&(a->local.ip6), mp->local, 16);
5173       clib_memcpy (&(a->remote.ip6), mp->remote, 16);
5174     }
5175   else
5176     {
5177       clib_memcpy (&(a->local.ip4), mp->local, 4);
5178       clib_memcpy (&(a->remote.ip4), mp->remote, 4);
5179     }
5180   a->encap_fib_index = encap_fib_index;
5181   a->decap_fib_index = decap_fib_index;
5182   a->protocol = protocol;
5183   a->vni = ntohl (mp->vni);
5184   rv = vnet_vxlan_gpe_add_del_tunnel (a, &sw_if_index);
5185
5186 out:
5187   /* *INDENT-OFF* */
5188   REPLY_MACRO2(VL_API_VXLAN_GPE_ADD_DEL_TUNNEL_REPLY,
5189   ({
5190     rmp->sw_if_index = ntohl (sw_if_index);
5191   }));
5192   /* *INDENT-ON* */
5193 }
5194
5195 static void send_vxlan_gpe_tunnel_details
5196   (vxlan_gpe_tunnel_t * t, unix_shared_memory_queue_t * q, u32 context)
5197 {
5198   vl_api_vxlan_gpe_tunnel_details_t *rmp;
5199   ip4_main_t *im4 = &ip4_main;
5200   ip6_main_t *im6 = &ip6_main;
5201   u8 is_ipv6 = !(t->flags & VXLAN_GPE_TUNNEL_IS_IPV4);
5202
5203   rmp = vl_msg_api_alloc (sizeof (*rmp));
5204   memset (rmp, 0, sizeof (*rmp));
5205   rmp->_vl_msg_id = ntohs (VL_API_VXLAN_GPE_TUNNEL_DETAILS);
5206   if (is_ipv6)
5207     {
5208       memcpy (rmp->local, &(t->local.ip6), 16);
5209       memcpy (rmp->remote, &(t->remote.ip6), 16);
5210       rmp->encap_vrf_id = htonl (im6->fibs[t->encap_fib_index].ft_table_id);
5211       rmp->decap_vrf_id = htonl (im6->fibs[t->decap_fib_index].ft_table_id);
5212     }
5213   else
5214     {
5215       memcpy (rmp->local, &(t->local.ip4), 4);
5216       memcpy (rmp->remote, &(t->remote.ip4), 4);
5217       rmp->encap_vrf_id = htonl (im4->fibs[t->encap_fib_index].ft_table_id);
5218       rmp->decap_vrf_id = htonl (im4->fibs[t->decap_fib_index].ft_table_id);
5219     }
5220   rmp->vni = htonl (t->vni);
5221   rmp->protocol = t->protocol;
5222   rmp->sw_if_index = htonl (t->sw_if_index);
5223   rmp->is_ipv6 = is_ipv6;
5224   rmp->context = context;
5225
5226   vl_msg_api_send_shmem (q, (u8 *) & rmp);
5227 }
5228
5229 static void vl_api_vxlan_gpe_tunnel_dump_t_handler
5230   (vl_api_vxlan_gpe_tunnel_dump_t * mp)
5231 {
5232   unix_shared_memory_queue_t *q;
5233   vxlan_gpe_main_t *vgm = &vxlan_gpe_main;
5234   vxlan_gpe_tunnel_t *t;
5235   u32 sw_if_index;
5236
5237   q = vl_api_client_index_to_input_queue (mp->client_index);
5238   if (q == 0)
5239     {
5240       return;
5241     }
5242
5243   sw_if_index = ntohl (mp->sw_if_index);
5244
5245   if (~0 == sw_if_index)
5246     {
5247       /* *INDENT-OFF* */
5248       pool_foreach (t, vgm->tunnels,
5249       ({
5250         send_vxlan_gpe_tunnel_details(t, q, mp->context);
5251       }));
5252       /* *INDENT-ON* */
5253     }
5254   else
5255     {
5256       if ((sw_if_index >= vec_len (vgm->tunnel_index_by_sw_if_index)) ||
5257           (~0 == vgm->tunnel_index_by_sw_if_index[sw_if_index]))
5258         {
5259           return;
5260         }
5261       t = &vgm->tunnels[vgm->tunnel_index_by_sw_if_index[sw_if_index]];
5262       send_vxlan_gpe_tunnel_details (t, q, mp->context);
5263     }
5264 }
5265
5266 /** Used for transferring locators via VPP API */
5267 /* *INDENT-OFF* */
5268 typedef CLIB_PACKED (struct {
5269   u32 sw_if_index; /**< locator sw_if_index */
5270   u8 priority; /**< locator priority */
5271   u8 weight; /**< locator weight */
5272 }) ls_locator_t;
5273 /* *INDENT-ON* */
5274
5275 static void
5276 vl_api_lisp_add_del_locator_set_t_handler (vl_api_lisp_add_del_locator_set_t *
5277                                            mp)
5278 {
5279   vl_api_lisp_add_del_locator_set_reply_t *rmp;
5280   int rv = 0;
5281   vnet_lisp_add_del_locator_set_args_t _a, *a = &_a;
5282   locator_t locator;
5283   ls_locator_t *ls_loc;
5284   u32 ls_index = ~0, locator_num;
5285   u8 *locator_name = NULL;
5286   int i;
5287
5288   memset (a, 0, sizeof (a[0]));
5289
5290   locator_name = format (0, "%s", mp->locator_set_name);
5291
5292   a->name = locator_name;
5293   a->is_add = mp->is_add;
5294   a->local = 1;
5295   locator_num = clib_net_to_host_u32 (mp->locator_num);
5296
5297   memset (&locator, 0, sizeof (locator));
5298   for (i = 0; i < locator_num; i++)
5299     {
5300       ls_loc = &((ls_locator_t *) mp->locators)[i];
5301       VALIDATE_SW_IF_INDEX (ls_loc);
5302
5303       locator.sw_if_index = htonl (ls_loc->sw_if_index);
5304       locator.priority = ls_loc->priority;
5305       locator.weight = ls_loc->weight;
5306       locator.local = 1;
5307       vec_add1 (a->locators, locator);
5308     }
5309
5310   rv = vnet_lisp_add_del_locator_set (a, &ls_index);
5311
5312   BAD_SW_IF_INDEX_LABEL;
5313
5314   vec_free (locator_name);
5315   vec_free (a->locators);
5316
5317   /* *INDENT-OFF* */
5318   REPLY_MACRO2 (VL_API_LISP_ADD_DEL_LOCATOR_SET_REPLY,
5319   ({
5320     rmp->ls_index = clib_host_to_net_u32 (ls_index);
5321   }));
5322   /* *INDENT-ON* */
5323 }
5324
5325 static void
5326 vl_api_lisp_add_del_locator_t_handler (vl_api_lisp_add_del_locator_t * mp)
5327 {
5328   vl_api_lisp_add_del_locator_reply_t *rmp;
5329   int rv = 0;
5330   locator_t locator, *locators = NULL;
5331   vnet_lisp_add_del_locator_set_args_t _a, *a = &_a;
5332   u32 ls_index = ~0;
5333   u8 *locator_name = NULL;
5334
5335   memset (&locator, 0, sizeof (locator));
5336   memset (a, 0, sizeof (a[0]));
5337
5338   locator.sw_if_index = ntohl (mp->sw_if_index);
5339   locator.priority = mp->priority;
5340   locator.weight = mp->weight;
5341   locator.local = 1;
5342   vec_add1 (locators, locator);
5343
5344   locator_name = format (0, "%s", mp->locator_set_name);
5345
5346   a->name = locator_name;
5347   a->locators = locators;
5348   a->is_add = mp->is_add;
5349   a->local = 1;
5350
5351   rv = vnet_lisp_add_del_locator (a, NULL, &ls_index);
5352
5353   vec_free (locators);
5354   vec_free (locator_name);
5355
5356   REPLY_MACRO (VL_API_LISP_ADD_DEL_LOCATOR_REPLY);
5357 }
5358
5359 static int
5360 unformat_lisp_eid_api (gid_address_t * dst, u32 vni, u8 type, void *src,
5361                        u8 len)
5362 {
5363   switch (type)
5364     {
5365     case 0:                     /* ipv4 */
5366       gid_address_type (dst) = GID_ADDR_IP_PREFIX;
5367       gid_address_ip_set (dst, src, IP4);
5368       gid_address_ippref_len (dst) = len;
5369       ip_prefix_normalize (&gid_address_ippref (dst));
5370       break;
5371     case 1:                     /* ipv6 */
5372       gid_address_type (dst) = GID_ADDR_IP_PREFIX;
5373       gid_address_ip_set (dst, src, IP6);
5374       gid_address_ippref_len (dst) = len;
5375       ip_prefix_normalize (&gid_address_ippref (dst));
5376       break;
5377     case 2:                     /* l2 mac */
5378       gid_address_type (dst) = GID_ADDR_MAC;
5379       clib_memcpy (&gid_address_mac (dst), src, 6);
5380       break;
5381     default:
5382       /* unknown type */
5383       return VNET_API_ERROR_INVALID_VALUE;
5384     }
5385
5386   gid_address_vni (dst) = vni;
5387
5388   return 0;
5389 }
5390
5391 static void
5392 vl_api_lisp_add_del_local_eid_t_handler (vl_api_lisp_add_del_local_eid_t * mp)
5393 {
5394   vl_api_lisp_add_del_local_eid_reply_t *rmp;
5395   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
5396   int rv = 0;
5397   gid_address_t _eid, *eid = &_eid;
5398   uword *p = NULL;
5399   u32 locator_set_index = ~0, map_index = ~0;
5400   vnet_lisp_add_del_mapping_args_t _a, *a = &_a;
5401   u8 *name = NULL;
5402   memset (a, 0, sizeof (a[0]));
5403   memset (eid, 0, sizeof (eid[0]));
5404
5405   rv = unformat_lisp_eid_api (eid, clib_net_to_host_u32 (mp->vni),
5406                               mp->eid_type, mp->eid, mp->prefix_len);
5407   if (rv)
5408     goto out;
5409
5410   name = format (0, "%s", mp->locator_set_name);
5411   p = hash_get_mem (lcm->locator_set_index_by_name, name);
5412   if (!p)
5413     {
5414       rv = VNET_API_ERROR_INVALID_VALUE;
5415       goto out;
5416     }
5417   locator_set_index = p[0];
5418
5419   /* XXX treat batch configuration */
5420   a->is_add = mp->is_add;
5421   gid_address_copy (&a->eid, eid);
5422   a->locator_set_index = locator_set_index;
5423   a->local = 1;
5424   rv = vnet_lisp_add_del_local_mapping (a, &map_index);
5425
5426 out:
5427   vec_free (name);
5428   gid_address_free (&a->eid);
5429
5430   REPLY_MACRO (VL_API_LISP_ADD_DEL_LOCAL_EID_REPLY);
5431 }
5432
5433 static void
5434   vl_api_lisp_eid_table_add_del_map_t_handler
5435   (vl_api_lisp_eid_table_add_del_map_t * mp)
5436 {
5437   vl_api_lisp_eid_table_add_del_map_reply_t *rmp;
5438   int rv = 0;
5439   rv = vnet_lisp_eid_table_map (clib_net_to_host_u32 (mp->vni),
5440                                 clib_net_to_host_u32 (mp->dp_table),
5441                                 mp->is_l2, mp->is_add);
5442 REPLY_MACRO (VL_API_LISP_EID_TABLE_ADD_DEL_MAP_REPLY)}
5443
5444 /** Used for transferring locators via VPP API */
5445 /* *INDENT-OFF* */
5446 typedef CLIB_PACKED (struct {
5447   u8 is_ip4; /**< is locator an IPv4 address */
5448   u8 priority; /**< locator priority */
5449   u8 weight; /**< locator weight */
5450   u8 addr[16]; /**< IPv4/IPv6 address */
5451 }) rloc_t;
5452 /* *INDENT-ON* */
5453
5454 static locator_pair_t *
5455 unformat_lisp_loc_pairs (void *lcl_locs, void *rmt_locs, u32 rloc_num)
5456 {
5457   u32 i;
5458   locator_pair_t *pairs = 0, pair;
5459   rloc_t *r;
5460
5461   for (i = 0; i < rloc_num; i++)
5462     {
5463       /* local locator */
5464       r = &((rloc_t *) lcl_locs)[i];
5465       memset (&pair.lcl_loc, 0, sizeof (pair.lcl_loc));
5466       ip_address_set (&pair.lcl_loc, &r->addr, r->is_ip4 ? IP4 : IP6);
5467
5468       /* remote locators */
5469       r = &((rloc_t *) rmt_locs)[i];
5470       memset (&pair.rmt_loc, 0, sizeof (pair.rmt_loc));
5471       ip_address_set (&pair.rmt_loc, &r->addr, r->is_ip4 ? IP4 : IP6);
5472
5473       pair.priority = r->priority;
5474       pair.weight = r->weight;
5475
5476       vec_add1 (pairs, pair);
5477     }
5478   return pairs;
5479 }
5480
5481 static locator_t *
5482 unformat_lisp_locs (void *rmt_locs, u32 rloc_num)
5483 {
5484   u32 i;
5485   locator_t *locs = 0, loc;
5486   rloc_t *r;
5487
5488   for (i = 0; i < rloc_num; i++)
5489     {
5490       /* remote locators */
5491       r = &((rloc_t *) rmt_locs)[i];
5492       memset (&loc, 0, sizeof (loc));
5493       gid_address_ip_set (&loc.address, &r->addr, r->is_ip4 ? IP4 : IP6);
5494
5495       loc.priority = r->priority;
5496       loc.weight = r->weight;
5497
5498       vec_add1 (locs, loc);
5499     }
5500   return locs;
5501 }
5502
5503 static void
5504   vl_api_lisp_gpe_add_del_fwd_entry_t_handler
5505   (vl_api_lisp_gpe_add_del_fwd_entry_t * mp)
5506 {
5507   vl_api_lisp_gpe_add_del_fwd_entry_reply_t *rmp;
5508   vnet_lisp_gpe_add_del_fwd_entry_args_t _a, *a = &_a;
5509   locator_pair_t *pairs = 0;
5510   int rv = 0;
5511
5512   memset (a, 0, sizeof (a[0]));
5513
5514   rv = unformat_lisp_eid_api (&a->rmt_eid, mp->vni, mp->eid_type,
5515                               mp->rmt_eid, mp->rmt_len);
5516   rv |= unformat_lisp_eid_api (&a->lcl_eid, mp->vni, mp->eid_type,
5517                                mp->lcl_eid, mp->lcl_len);
5518
5519   pairs = unformat_lisp_loc_pairs (mp->lcl_locs, mp->rmt_locs, mp->loc_num);
5520
5521   if (rv || 0 == pairs)
5522     goto send_reply;
5523
5524   a->is_add = mp->is_add;
5525   a->locator_pairs = pairs;
5526   a->dp_table = mp->dp_table;
5527   a->vni = mp->vni;
5528   a->action = mp->action;
5529
5530   rv = vnet_lisp_gpe_add_del_fwd_entry (a, 0);
5531   vec_free (pairs);
5532 send_reply:
5533   REPLY_MACRO (VL_API_LISP_GPE_ADD_DEL_FWD_ENTRY_REPLY);
5534 }
5535
5536 static void
5537 vl_api_lisp_add_del_map_resolver_t_handler (vl_api_lisp_add_del_map_resolver_t
5538                                             * mp)
5539 {
5540   vl_api_lisp_add_del_map_resolver_reply_t *rmp;
5541   int rv = 0;
5542   vnet_lisp_add_del_map_resolver_args_t _a, *a = &_a;
5543
5544   memset (a, 0, sizeof (a[0]));
5545
5546   a->is_add = mp->is_add;
5547   ip_address_set (&a->address, mp->ip_address, mp->is_ipv6 ? IP6 : IP4);
5548
5549   rv = vnet_lisp_add_del_map_resolver (a);
5550
5551   REPLY_MACRO (VL_API_LISP_ADD_DEL_MAP_RESOLVER_REPLY);
5552 }
5553
5554 static void
5555 vl_api_lisp_gpe_enable_disable_t_handler (vl_api_lisp_gpe_enable_disable_t *
5556                                           mp)
5557 {
5558   vl_api_lisp_gpe_enable_disable_reply_t *rmp;
5559   int rv = 0;
5560   vnet_lisp_gpe_enable_disable_args_t _a, *a = &_a;
5561
5562   a->is_en = mp->is_en;
5563   vnet_lisp_gpe_enable_disable (a);
5564
5565   REPLY_MACRO (VL_API_LISP_GPE_ENABLE_DISABLE_REPLY);
5566 }
5567
5568 static void
5569 vl_api_lisp_enable_disable_t_handler (vl_api_lisp_enable_disable_t * mp)
5570 {
5571   vl_api_lisp_enable_disable_reply_t *rmp;
5572   int rv = 0;
5573
5574   vnet_lisp_enable_disable (mp->is_en);
5575   REPLY_MACRO (VL_API_LISP_ENABLE_DISABLE_REPLY);
5576 }
5577
5578 static void
5579 vl_api_lisp_gpe_add_del_iface_t_handler (vl_api_lisp_gpe_add_del_iface_t * mp)
5580 {
5581   vl_api_lisp_gpe_add_del_iface_reply_t *rmp;
5582   int rv = 0;
5583
5584   if (mp->is_l2)
5585     {
5586       if (mp->is_add)
5587         {
5588           if (~0 ==
5589               lisp_gpe_tenant_l2_iface_add_or_lock (mp->vni, mp->dp_table))
5590             rv = 1;
5591         }
5592       else
5593         lisp_gpe_tenant_l2_iface_unlock (mp->vni);
5594     }
5595   else
5596     {
5597       if (mp->is_add)
5598         {
5599           if (~0 ==
5600               lisp_gpe_tenant_l3_iface_add_or_lock (mp->vni, mp->dp_table))
5601             rv = 1;
5602         }
5603       else
5604         lisp_gpe_tenant_l3_iface_unlock (mp->vni);
5605     }
5606
5607   REPLY_MACRO (VL_API_LISP_GPE_ADD_DEL_IFACE_REPLY);
5608 }
5609
5610 static void
5611   vl_api_show_lisp_map_request_mode_t_handler
5612   (vl_api_show_lisp_map_request_mode_t * mp)
5613 {
5614   int rv = 0;
5615   vl_api_show_lisp_map_request_mode_reply_t *rmp;
5616
5617   /* *INDENT-OFF* */
5618   REPLY_MACRO2(VL_API_SHOW_LISP_MAP_REQUEST_MODE_REPLY,
5619   ({
5620     rmp->mode = vnet_lisp_get_map_request_mode ();
5621   }));
5622   /* *INDENT-ON* */
5623 }
5624
5625 static void
5626 vl_api_lisp_map_request_mode_t_handler (vl_api_lisp_map_request_mode_t * mp)
5627 {
5628   vl_api_lisp_map_request_mode_reply_t *rmp;
5629   int rv = 0;
5630
5631   rv = vnet_lisp_set_map_request_mode (mp->mode);
5632
5633   REPLY_MACRO (VL_API_LISP_MAP_REQUEST_MODE_REPLY);
5634 }
5635
5636 static void
5637 vl_api_lisp_pitr_set_locator_set_t_handler (vl_api_lisp_pitr_set_locator_set_t
5638                                             * mp)
5639 {
5640   vl_api_lisp_pitr_set_locator_set_reply_t *rmp;
5641   int rv = 0;
5642   u8 *ls_name = 0;
5643
5644   ls_name = format (0, "%s", mp->ls_name);
5645   rv = vnet_lisp_pitr_set_locator_set (ls_name, mp->is_add);
5646   vec_free (ls_name);
5647
5648   REPLY_MACRO (VL_API_LISP_PITR_SET_LOCATOR_SET_REPLY);
5649 }
5650
5651 static void
5652   vl_api_lisp_add_del_map_request_itr_rlocs_t_handler
5653   (vl_api_lisp_add_del_map_request_itr_rlocs_t * mp)
5654 {
5655   vl_api_lisp_add_del_map_request_itr_rlocs_reply_t *rmp;
5656   int rv = 0;
5657   u8 *locator_set_name = NULL;
5658   vnet_lisp_add_del_mreq_itr_rloc_args_t _a, *a = &_a;
5659
5660   locator_set_name = format (0, "%s", mp->locator_set_name);
5661
5662   a->is_add = mp->is_add;
5663   a->locator_set_name = locator_set_name;
5664
5665   rv = vnet_lisp_add_del_mreq_itr_rlocs (a);
5666
5667   vec_free (locator_set_name);
5668
5669   REPLY_MACRO (VL_API_LISP_ADD_DEL_MAP_REQUEST_ITR_RLOCS_REPLY);
5670 }
5671
5672 static void
5673   vl_api_lisp_add_del_remote_mapping_t_handler
5674   (vl_api_lisp_add_del_remote_mapping_t * mp)
5675 {
5676   locator_t *rlocs = 0;
5677   vl_api_lisp_add_del_remote_mapping_reply_t *rmp;
5678   int rv = 0;
5679   gid_address_t _eid, *eid = &_eid;
5680   u32 rloc_num = clib_net_to_host_u32 (mp->rloc_num);
5681
5682   memset (eid, 0, sizeof (eid[0]));
5683
5684   rv = unformat_lisp_eid_api (eid, clib_net_to_host_u32 (mp->vni),
5685                               mp->eid_type, mp->eid, mp->eid_len);
5686   if (rv)
5687     goto send_reply;
5688
5689   rlocs = unformat_lisp_locs (mp->rlocs, rloc_num);
5690
5691   if (!mp->is_add)
5692     {
5693       vnet_lisp_add_del_adjacency_args_t _a, *a = &_a;
5694       gid_address_copy (&a->reid, eid);
5695       a->is_add = 0;
5696       rv = vnet_lisp_add_del_adjacency (a);
5697       if (rv)
5698         {
5699           goto out;
5700         }
5701     }
5702
5703   /* NOTE: for now this works as a static remote mapping, i.e.,
5704    * not authoritative and ttl infinite. */
5705   rv = vnet_lisp_add_del_mapping (eid, rlocs, mp->action, 0, ~0,
5706                                   mp->is_add, 1 /* is_static */ , 0);
5707
5708   if (mp->del_all)
5709     vnet_lisp_clear_all_remote_adjacencies ();
5710
5711 out:
5712   vec_free (rlocs);
5713 send_reply:
5714   REPLY_MACRO (VL_API_LISP_ADD_DEL_REMOTE_MAPPING_REPLY);
5715 }
5716
5717 static void
5718 vl_api_lisp_add_del_adjacency_t_handler (vl_api_lisp_add_del_adjacency_t * mp)
5719 {
5720   vl_api_lisp_add_del_adjacency_reply_t *rmp;
5721   vnet_lisp_add_del_adjacency_args_t _a, *a = &_a;
5722
5723   int rv = 0;
5724   memset (a, 0, sizeof (a[0]));
5725
5726   rv = unformat_lisp_eid_api (&a->leid, clib_net_to_host_u32 (mp->vni),
5727                               mp->eid_type, mp->leid, mp->leid_len);
5728   rv |= unformat_lisp_eid_api (&a->reid, clib_net_to_host_u32 (mp->vni),
5729                                mp->eid_type, mp->reid, mp->reid_len);
5730
5731   if (rv)
5732     goto send_reply;
5733
5734   a->is_add = mp->is_add;
5735   rv = vnet_lisp_add_del_adjacency (a);
5736
5737 send_reply:
5738   REPLY_MACRO (VL_API_LISP_ADD_DEL_ADJACENCY_REPLY);
5739 }
5740
5741 static void
5742 send_lisp_locator_details (lisp_cp_main_t * lcm,
5743                            locator_t * loc,
5744                            unix_shared_memory_queue_t * q, u32 context)
5745 {
5746   vl_api_lisp_locator_details_t *rmp;
5747
5748   rmp = vl_msg_api_alloc (sizeof (*rmp));
5749   memset (rmp, 0, sizeof (*rmp));
5750   rmp->_vl_msg_id = ntohs (VL_API_LISP_LOCATOR_DETAILS);
5751   rmp->context = context;
5752
5753   rmp->local = loc->local;
5754   if (loc->local)
5755     {
5756       rmp->sw_if_index = ntohl (loc->sw_if_index);
5757     }
5758   else
5759     {
5760       rmp->is_ipv6 = gid_address_ip_version (&loc->address);
5761       ip_address_copy_addr (rmp->ip_address, &gid_address_ip (&loc->address));
5762     }
5763   rmp->priority = loc->priority;
5764   rmp->weight = loc->weight;
5765
5766   vl_msg_api_send_shmem (q, (u8 *) & rmp);
5767 }
5768
5769 static void
5770 vl_api_lisp_locator_dump_t_handler (vl_api_lisp_locator_dump_t * mp)
5771 {
5772   u8 *ls_name = 0;
5773   unix_shared_memory_queue_t *q = 0;
5774   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
5775   locator_set_t *lsit = 0;
5776   locator_t *loc = 0;
5777   u32 ls_index = ~0, *locit = 0;
5778   uword *p = 0;
5779
5780   q = vl_api_client_index_to_input_queue (mp->client_index);
5781   if (q == 0)
5782     {
5783       return;
5784     }
5785
5786   if (mp->is_index_set)
5787     ls_index = htonl (mp->ls_index);
5788   else
5789     {
5790       /* make sure we get a proper C-string */
5791       mp->ls_name[sizeof (mp->ls_name) - 1] = 0;
5792       ls_name = format (0, "%s", mp->ls_name);
5793       p = hash_get_mem (lcm->locator_set_index_by_name, ls_name);
5794       if (!p)
5795         goto out;
5796       ls_index = p[0];
5797     }
5798
5799   if (pool_is_free_index (lcm->locator_set_pool, ls_index))
5800     return;
5801
5802   lsit = pool_elt_at_index (lcm->locator_set_pool, ls_index);
5803
5804   vec_foreach (locit, lsit->locator_indices)
5805   {
5806     loc = pool_elt_at_index (lcm->locator_pool, locit[0]);
5807     send_lisp_locator_details (lcm, loc, q, mp->context);
5808   };
5809 out:
5810   vec_free (ls_name);
5811 }
5812
5813 static void
5814 send_lisp_locator_set_details (lisp_cp_main_t * lcm,
5815                                locator_set_t * lsit,
5816                                unix_shared_memory_queue_t * q,
5817                                u32 context, u32 ls_index)
5818 {
5819   vl_api_lisp_locator_set_details_t *rmp;
5820   u8 *str = 0;
5821
5822   rmp = vl_msg_api_alloc (sizeof (*rmp));
5823   memset (rmp, 0, sizeof (*rmp));
5824   rmp->_vl_msg_id = ntohs (VL_API_LISP_LOCATOR_SET_DETAILS);
5825   rmp->context = context;
5826
5827   rmp->ls_index = htonl (ls_index);
5828   if (lsit->local)
5829     {
5830       ASSERT (lsit->name != NULL);
5831       strncpy ((char *) rmp->ls_name, (char *) lsit->name,
5832                vec_len (lsit->name));
5833     }
5834   else
5835     {
5836       str = format (0, "<remote-%d>", ls_index);
5837       strncpy ((char *) rmp->ls_name, (char *) str, vec_len (str));
5838       vec_free (str);
5839     }
5840
5841   vl_msg_api_send_shmem (q, (u8 *) & rmp);
5842 }
5843
5844 static void
5845 vl_api_lisp_locator_set_dump_t_handler (vl_api_lisp_locator_set_dump_t * mp)
5846 {
5847   unix_shared_memory_queue_t *q = NULL;
5848   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
5849   locator_set_t *lsit = NULL;
5850   u8 filter;
5851
5852   q = vl_api_client_index_to_input_queue (mp->client_index);
5853   if (q == 0)
5854     {
5855       return;
5856     }
5857
5858   filter = mp->filter;
5859   /* *INDENT-OFF* */
5860   pool_foreach (lsit, lcm->locator_set_pool,
5861   ({
5862     if (filter && !((1 == filter && lsit->local) ||
5863                     (2 == filter && !lsit->local)))
5864       {
5865         continue;
5866       }
5867     send_lisp_locator_set_details (lcm, lsit, q, mp->context,
5868                                    lsit - lcm->locator_set_pool);
5869   }));
5870   /* *INDENT-ON* */
5871 }
5872
5873 static void
5874 lisp_fid_put_api (u8 * dst, fid_address_t * src, u8 * prefix_length)
5875 {
5876   ASSERT (prefix_length);
5877   ip_prefix_t *ippref = &fid_addr_ippref (src);
5878
5879   switch (fid_addr_type (src))
5880     {
5881     case FID_ADDR_IP_PREF:
5882       if (ip_prefix_version (ippref) == IP4)
5883         clib_memcpy (dst, &ip_prefix_v4 (ippref), 4);
5884       else
5885         clib_memcpy (dst, &ip_prefix_v6 (ippref), 16);
5886       prefix_length[0] = ip_prefix_len (ippref);
5887       break;
5888
5889     case FID_ADDR_MAC:
5890       prefix_length[0] = 0;
5891       clib_memcpy (dst, fid_addr_mac (src), 6);
5892       break;
5893
5894     default:
5895       clib_warning ("Unknown FID type %d!", fid_addr_type (src));
5896       break;
5897     }
5898 }
5899
5900 static u8
5901 fid_type_to_api_type (fid_address_t * fid)
5902 {
5903   ip_prefix_t *ippref;
5904
5905   switch (fid_addr_type (fid))
5906     {
5907     case FID_ADDR_IP_PREF:
5908       ippref = &fid_addr_ippref (fid);
5909       if (ip_prefix_version (ippref) == IP4)
5910         return 0;
5911       else if (ip_prefix_version (ippref) == IP6)
5912         return 1;
5913       else
5914         return ~0;
5915
5916     case FID_ADDR_MAC:
5917       return 2;
5918     }
5919
5920   return ~0;
5921 }
5922
5923 static void
5924 send_lisp_eid_table_details (mapping_t * mapit,
5925                              unix_shared_memory_queue_t * q,
5926                              u32 context, u8 filter)
5927 {
5928   fid_address_t *fid;
5929   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
5930   locator_set_t *ls = 0;
5931   vl_api_lisp_eid_table_details_t *rmp = NULL;
5932   gid_address_t *gid = NULL;
5933   u8 *mac = 0;
5934   ip_prefix_t *ip_prefix = NULL;
5935
5936   switch (filter)
5937     {
5938     case 0:                     /* all mappings */
5939       break;
5940
5941     case 1:                     /* local only */
5942       if (!mapit->local)
5943         return;
5944       break;
5945     case 2:                     /* remote only */
5946       if (mapit->local)
5947         return;
5948       break;
5949     default:
5950       clib_warning ("Filter error, unknown filter: %d", filter);
5951       return;
5952     }
5953
5954   gid = &mapit->eid;
5955   ip_prefix = &gid_address_ippref (gid);
5956   mac = gid_address_mac (gid);
5957
5958   rmp = vl_msg_api_alloc (sizeof (*rmp));
5959   memset (rmp, 0, sizeof (*rmp));
5960   rmp->_vl_msg_id = ntohs (VL_API_LISP_EID_TABLE_DETAILS);
5961
5962   ls = pool_elt_at_index (lcm->locator_set_pool, mapit->locator_set_index);
5963   if (vec_len (ls->locator_indices) == 0)
5964     rmp->locator_set_index = ~0;
5965   else
5966     rmp->locator_set_index = clib_host_to_net_u32 (mapit->locator_set_index);
5967
5968   rmp->is_local = mapit->local;
5969   rmp->ttl = clib_host_to_net_u32 (mapit->ttl);
5970   rmp->action = mapit->action;
5971   rmp->authoritative = mapit->authoritative;
5972
5973   switch (gid_address_type (gid))
5974     {
5975     case GID_ADDR_SRC_DST:
5976       rmp->is_src_dst = 1;
5977       fid = &gid_address_sd_src (gid);
5978       rmp->eid_type = fid_type_to_api_type (fid);
5979       lisp_fid_put_api (rmp->seid, &gid_address_sd_src (gid),
5980                         &rmp->seid_prefix_len);
5981       lisp_fid_put_api (rmp->eid, &gid_address_sd_dst (gid),
5982                         &rmp->eid_prefix_len);
5983       break;
5984     case GID_ADDR_IP_PREFIX:
5985       rmp->eid_prefix_len = ip_prefix_len (ip_prefix);
5986       if (ip_prefix_version (ip_prefix) == IP4)
5987         {
5988           rmp->eid_type = 0;    /* ipv4 type */
5989           clib_memcpy (rmp->eid, &ip_prefix_v4 (ip_prefix),
5990                        sizeof (ip_prefix_v4 (ip_prefix)));
5991         }
5992       else
5993         {
5994           rmp->eid_type = 1;    /* ipv6 type */
5995           clib_memcpy (rmp->eid, &ip_prefix_v6 (ip_prefix),
5996                        sizeof (ip_prefix_v6 (ip_prefix)));
5997         }
5998       break;
5999     case GID_ADDR_MAC:
6000       rmp->eid_type = 2;        /* l2 mac type */
6001       clib_memcpy (rmp->eid, mac, 6);
6002       break;
6003     default:
6004       ASSERT (0);
6005     }
6006   rmp->context = context;
6007   rmp->vni = clib_host_to_net_u32 (gid_address_vni (gid));
6008   vl_msg_api_send_shmem (q, (u8 *) & rmp);
6009 }
6010
6011 static void
6012 vl_api_lisp_eid_table_dump_t_handler (vl_api_lisp_eid_table_dump_t * mp)
6013 {
6014   u32 mi;
6015   unix_shared_memory_queue_t *q = NULL;
6016   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
6017   mapping_t *mapit = NULL;
6018   gid_address_t _eid, *eid = &_eid;
6019
6020   q = vl_api_client_index_to_input_queue (mp->client_index);
6021   if (q == 0)
6022     {
6023       return;
6024     }
6025
6026   if (mp->eid_set)
6027     {
6028       memset (eid, 0, sizeof (*eid));
6029
6030       unformat_lisp_eid_api (eid, clib_net_to_host_u32 (mp->vni),
6031                              mp->eid_type, mp->eid, mp->prefix_length);
6032
6033       mi = gid_dictionary_lookup (&lcm->mapping_index_by_gid, eid);
6034       if ((u32) ~ 0 == mi)
6035         return;
6036
6037       mapit = pool_elt_at_index (lcm->mapping_pool, mi);
6038       send_lisp_eid_table_details (mapit, q, mp->context,
6039                                    0 /* ignore filter */ );
6040     }
6041   else
6042     {
6043       /* *INDENT-OFF* */
6044       pool_foreach (mapit, lcm->mapping_pool,
6045       ({
6046         send_lisp_eid_table_details(mapit, q, mp->context,
6047                                     mp->filter);
6048       }));
6049       /* *INDENT-ON* */
6050     }
6051 }
6052
6053 static void
6054 send_lisp_gpe_fwd_entry_details (lisp_gpe_fwd_entry_t * lfe,
6055                                  unix_shared_memory_queue_t * q, u32 context)
6056 {
6057   vl_api_lisp_gpe_tunnel_details_t *rmp;
6058   lisp_gpe_main_t *lgm = &lisp_gpe_main;
6059
6060   rmp = vl_msg_api_alloc (sizeof (*rmp));
6061   memset (rmp, 0, sizeof (*rmp));
6062   rmp->_vl_msg_id = ntohs (VL_API_LISP_GPE_TUNNEL_DETAILS);
6063
6064   rmp->tunnels = lfe - lgm->lisp_fwd_entry_pool;
6065
6066   rmp->is_ipv6 = ip_prefix_version (&(lfe->key->rmt.ippref)) == IP6 ? 1 : 0;
6067   ip_address_copy_addr (rmp->source_ip,
6068                         &ip_prefix_addr (&(lfe->key->rmt.ippref)));
6069   ip_address_copy_addr (rmp->destination_ip,
6070                         &ip_prefix_addr (&(lfe->key->rmt.ippref)));
6071
6072   rmp->encap_fib_id = htonl (0);
6073   rmp->decap_fib_id = htonl (lfe->eid_fib_index);
6074   rmp->iid = htonl (lfe->key->vni);
6075   rmp->context = context;
6076
6077   vl_msg_api_send_shmem (q, (u8 *) & rmp);
6078 }
6079
6080 static void
6081 vl_api_lisp_gpe_tunnel_dump_t_handler (vl_api_lisp_gpe_tunnel_dump_t * mp)
6082 {
6083   unix_shared_memory_queue_t *q = NULL;
6084   lisp_gpe_main_t *lgm = &lisp_gpe_main;
6085   lisp_gpe_fwd_entry_t *lfe = NULL;
6086
6087   if (pool_elts (lgm->lisp_fwd_entry_pool) == 0)
6088     {
6089       return;
6090     }
6091
6092   q = vl_api_client_index_to_input_queue (mp->client_index);
6093   if (q == 0)
6094     {
6095       return;
6096     }
6097
6098   /* *INDENT-OFF* */
6099   pool_foreach(lfe, lgm->lisp_fwd_entry_pool,
6100   ({
6101     send_lisp_gpe_fwd_entry_details(lfe, q, mp->context);
6102   }));
6103   /* *INDENT-ON* */
6104 }
6105
6106 static void
6107 send_lisp_map_resolver_details (ip_address_t * ip,
6108                                 unix_shared_memory_queue_t * q, u32 context)
6109 {
6110   vl_api_lisp_map_resolver_details_t *rmp = NULL;
6111
6112   rmp = vl_msg_api_alloc (sizeof (*rmp));
6113   memset (rmp, 0, sizeof (*rmp));
6114   rmp->_vl_msg_id = ntohs (VL_API_LISP_MAP_RESOLVER_DETAILS);
6115
6116   switch (ip_addr_version (ip))
6117     {
6118     case IP4:
6119       rmp->is_ipv6 = 0;
6120       clib_memcpy (rmp->ip_address, &ip_addr_v4 (ip),
6121                    sizeof (ip_addr_v4 (ip)));
6122       break;
6123
6124     case IP6:
6125       rmp->is_ipv6 = 1;
6126       clib_memcpy (rmp->ip_address, &ip_addr_v6 (ip),
6127                    sizeof (ip_addr_v6 (ip)));
6128       break;
6129
6130     default:
6131       ASSERT (0);
6132     }
6133   rmp->context = context;
6134
6135   vl_msg_api_send_shmem (q, (u8 *) & rmp);
6136 }
6137
6138 static void
6139 vl_api_lisp_map_resolver_dump_t_handler (vl_api_lisp_map_resolver_dump_t * mp)
6140 {
6141   unix_shared_memory_queue_t *q = NULL;
6142   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
6143   map_resolver_t *mr;
6144
6145   q = vl_api_client_index_to_input_queue (mp->client_index);
6146   if (q == 0)
6147     {
6148       return;
6149     }
6150
6151   vec_foreach (mr, lcm->map_resolvers)
6152   {
6153     send_lisp_map_resolver_details (&mr->address, q, mp->context);
6154   }
6155 }
6156
6157 static void
6158 send_eid_table_map_pair (hash_pair_t * p,
6159                          unix_shared_memory_queue_t * q, u32 context)
6160 {
6161   vl_api_lisp_eid_table_map_details_t *rmp = NULL;
6162
6163   rmp = vl_msg_api_alloc (sizeof (*rmp));
6164   memset (rmp, 0, sizeof (*rmp));
6165   rmp->_vl_msg_id = ntohs (VL_API_LISP_EID_TABLE_MAP_DETAILS);
6166
6167   rmp->vni = clib_host_to_net_u32 (p->key);
6168   rmp->dp_table = clib_host_to_net_u32 (p->value[0]);
6169   rmp->context = context;
6170   vl_msg_api_send_shmem (q, (u8 *) & rmp);
6171 }
6172
6173 static void
6174 vl_api_lisp_eid_table_map_dump_t_handler (vl_api_lisp_eid_table_map_dump_t *
6175                                           mp)
6176 {
6177   unix_shared_memory_queue_t *q = NULL;
6178   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
6179   hash_pair_t *p;
6180   uword *vni_table = 0;
6181
6182   q = vl_api_client_index_to_input_queue (mp->client_index);
6183   if (q == 0)
6184     {
6185       return;
6186     }
6187
6188   if (mp->is_l2)
6189     {
6190       vni_table = lcm->bd_id_by_vni;
6191     }
6192   else
6193     {
6194       vni_table = lcm->table_id_by_vni;
6195     }
6196
6197   /* *INDENT-OFF* */
6198   hash_foreach_pair (p, vni_table,
6199   ({
6200     send_eid_table_map_pair (p, q, mp->context);
6201   }));
6202   /* *INDENT-ON* */
6203 }
6204
6205 static void
6206 send_eid_table_vni (u32 vni, unix_shared_memory_queue_t * q, u32 context)
6207 {
6208   vl_api_lisp_eid_table_vni_details_t *rmp = 0;
6209
6210   rmp = vl_msg_api_alloc (sizeof (*rmp));
6211   memset (rmp, 0, sizeof (*rmp));
6212   rmp->_vl_msg_id = ntohs (VL_API_LISP_EID_TABLE_VNI_DETAILS);
6213   rmp->context = context;
6214   rmp->vni = clib_host_to_net_u32 (vni);
6215   vl_msg_api_send_shmem (q, (u8 *) & rmp);
6216 }
6217
6218 static void
6219 lisp_adjacency_copy (vl_api_lisp_adjacency_t * dst, lisp_adjacency_t * adjs)
6220 {
6221   lisp_adjacency_t *adj;
6222   vl_api_lisp_adjacency_t a;
6223   u32 i, n = vec_len (adjs);
6224
6225   for (i = 0; i < n; i++)
6226     {
6227       adj = vec_elt_at_index (adjs, i);
6228       memset (&a, 0, sizeof (a));
6229
6230       switch (gid_address_type (&adj->reid))
6231         {
6232         case GID_ADDR_IP_PREFIX:
6233           a.reid_prefix_len = gid_address_ippref_len (&adj->reid);
6234           a.leid_prefix_len = gid_address_ippref_len (&adj->leid);
6235           if (gid_address_ip_version (&adj->reid) == IP4)
6236             {
6237               a.eid_type = 0;   /* ipv4 type */
6238               clib_memcpy (a.reid, &gid_address_ip (&adj->reid), 4);
6239               clib_memcpy (a.leid, &gid_address_ip (&adj->leid), 4);
6240             }
6241           else
6242             {
6243               a.eid_type = 1;   /* ipv6 type */
6244               clib_memcpy (a.reid, &gid_address_ip (&adj->reid), 16);
6245               clib_memcpy (a.leid, &gid_address_ip (&adj->leid), 16);
6246             }
6247           break;
6248         case GID_ADDR_MAC:
6249           a.eid_type = 2;       /* l2 mac type */
6250           mac_copy (a.reid, gid_address_mac (&adj->reid));
6251           mac_copy (a.leid, gid_address_mac (&adj->leid));
6252           break;
6253         default:
6254           ASSERT (0);
6255         }
6256       dst[i] = a;
6257     }
6258 }
6259
6260 static void
6261 vl_api_lisp_adjacencies_get_t_handler (vl_api_lisp_adjacencies_get_t * mp)
6262 {
6263   vl_api_lisp_adjacencies_get_reply_t *rmp = 0;
6264   lisp_adjacency_t *adjs = 0;
6265   int rv = 0;
6266   vl_api_lisp_adjacency_t a;
6267   u32 size = ~0;
6268   u32 vni = clib_net_to_host_u32 (mp->vni);
6269
6270   adjs = vnet_lisp_adjacencies_get_by_vni (vni);
6271   size = vec_len (adjs) * sizeof (a);
6272
6273   /* *INDENT-OFF* */
6274   REPLY_MACRO4 (VL_API_LISP_ADJACENCIES_GET_REPLY, size,
6275   {
6276     rmp->count = clib_host_to_net_u32 (vec_len (adjs));
6277     lisp_adjacency_copy (rmp->adjacencies, adjs);
6278   });
6279   /* *INDENT-ON* */
6280
6281   vec_free (adjs);
6282 }
6283
6284 static void
6285 vl_api_lisp_eid_table_vni_dump_t_handler (vl_api_lisp_eid_table_vni_dump_t *
6286                                           mp)
6287 {
6288   hash_pair_t *p;
6289   u32 *vnis = 0;
6290   unix_shared_memory_queue_t *q = 0;
6291   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
6292
6293   q = vl_api_client_index_to_input_queue (mp->client_index);
6294   if (q == 0)
6295     {
6296       return;
6297     }
6298
6299   /* *INDENT-OFF* */
6300   hash_foreach_pair (p, lcm->table_id_by_vni,
6301   ({
6302     hash_set (vnis, p->key, 0);
6303   }));
6304
6305   hash_foreach_pair (p, lcm->bd_id_by_vni,
6306   ({
6307     hash_set (vnis, p->key, 0);
6308   }));
6309
6310   hash_foreach_pair (p, vnis,
6311   ({
6312     send_eid_table_vni (p->key, q, mp->context);
6313   }));
6314   /* *INDENT-ON* */
6315
6316   hash_free (vnis);
6317 }
6318
6319 static void
6320 vl_api_show_lisp_status_t_handler (vl_api_show_lisp_status_t * mp)
6321 {
6322   unix_shared_memory_queue_t *q = NULL;
6323   vl_api_show_lisp_status_reply_t *rmp = NULL;
6324   int rv = 0;
6325
6326   q = vl_api_client_index_to_input_queue (mp->client_index);
6327   if (q == 0)
6328     {
6329       return;
6330     }
6331
6332   /* *INDENT-OFF* */
6333   REPLY_MACRO2(VL_API_SHOW_LISP_STATUS_REPLY,
6334   ({
6335     rmp->gpe_status = vnet_lisp_gpe_enable_disable_status ();
6336     rmp->feature_status = vnet_lisp_enable_disable_status ();
6337   }));
6338   /* *INDENT-ON* */
6339 }
6340
6341 static void
6342   vl_api_lisp_get_map_request_itr_rlocs_t_handler
6343   (vl_api_lisp_get_map_request_itr_rlocs_t * mp)
6344 {
6345   unix_shared_memory_queue_t *q = NULL;
6346   vl_api_lisp_get_map_request_itr_rlocs_reply_t *rmp = NULL;
6347   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
6348   locator_set_t *loc_set = 0;
6349   u8 *tmp_str = 0;
6350   int rv = 0;
6351
6352   q = vl_api_client_index_to_input_queue (mp->client_index);
6353   if (q == 0)
6354     {
6355       return;
6356     }
6357
6358   if (~0 == lcm->mreq_itr_rlocs)
6359     {
6360       tmp_str = format (0, " ");
6361     }
6362   else
6363     {
6364       loc_set =
6365         pool_elt_at_index (lcm->locator_set_pool, lcm->mreq_itr_rlocs);
6366       tmp_str = format (0, "%s", loc_set->name);
6367     }
6368
6369   /* *INDENT-OFF* */
6370   REPLY_MACRO2(VL_API_LISP_GET_MAP_REQUEST_ITR_RLOCS_REPLY,
6371   ({
6372     strncpy((char *) rmp->locator_set_name, (char *) tmp_str,
6373             ARRAY_LEN(rmp->locator_set_name) - 1);
6374   }));
6375   /* *INDENT-ON* */
6376
6377   vec_free (tmp_str);
6378 }
6379
6380 static void
6381 vl_api_show_lisp_pitr_t_handler (vl_api_show_lisp_pitr_t * mp)
6382 {
6383   unix_shared_memory_queue_t *q = NULL;
6384   vl_api_show_lisp_pitr_reply_t *rmp = NULL;
6385   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
6386   mapping_t *m;
6387   locator_set_t *ls = 0;
6388   u8 *tmp_str = 0;
6389   int rv = 0;
6390
6391   q = vl_api_client_index_to_input_queue (mp->client_index);
6392   if (q == 0)
6393     {
6394       return;
6395     }
6396
6397   if (!lcm->lisp_pitr)
6398     {
6399       tmp_str = format (0, "N/A");
6400     }
6401   else
6402     {
6403       m = pool_elt_at_index (lcm->mapping_pool, lcm->pitr_map_index);
6404       if (~0 != m->locator_set_index)
6405         {
6406           ls =
6407             pool_elt_at_index (lcm->locator_set_pool, m->locator_set_index);
6408           tmp_str = format (0, "%s", ls->name);
6409         }
6410       else
6411         {
6412           tmp_str = format (0, "N/A");
6413         }
6414     }
6415   vec_add1 (tmp_str, 0);
6416
6417   /* *INDENT-OFF* */
6418   REPLY_MACRO2(VL_API_SHOW_LISP_PITR_REPLY,
6419   ({
6420     rmp->status = lcm->lisp_pitr;
6421     strncpy((char *) rmp->locator_set_name, (char *) tmp_str,
6422             ARRAY_LEN(rmp->locator_set_name) - 1);
6423   }));
6424   /* *INDENT-ON* */
6425 }
6426
6427 static void
6428 vl_api_interface_name_renumber_t_handler (vl_api_interface_name_renumber_t *
6429                                           mp)
6430 {
6431   vl_api_interface_name_renumber_reply_t *rmp;
6432   int rv = 0;
6433
6434   VALIDATE_SW_IF_INDEX (mp);
6435
6436   rv = vnet_interface_name_renumber
6437     (ntohl (mp->sw_if_index), ntohl (mp->new_show_dev_instance));
6438
6439   BAD_SW_IF_INDEX_LABEL;
6440
6441   REPLY_MACRO (VL_API_INTERFACE_NAME_RENUMBER_REPLY);
6442 }
6443
6444 static int
6445 arp_change_data_callback (u32 pool_index, u8 * new_mac,
6446                           u32 sw_if_index, u32 address)
6447 {
6448   vpe_api_main_t *am = &vpe_api_main;
6449   vlib_main_t *vm = am->vlib_main;
6450   vl_api_ip4_arp_event_t *event;
6451   static f64 arp_event_last_time;
6452   f64 now = vlib_time_now (vm);
6453
6454   if (pool_is_free_index (am->arp_events, pool_index))
6455     return 1;
6456
6457   event = pool_elt_at_index (am->arp_events, pool_index);
6458   /* *INDENT-OFF* */
6459   if (memcmp (&event->new_mac, new_mac, sizeof (event->new_mac)))
6460     {
6461       clib_memcpy (event->new_mac, new_mac, sizeof (event->new_mac));
6462     }
6463   else
6464     {                           /* same mac */
6465       if (sw_if_index == event->sw_if_index &&
6466           (!event->mac_ip ||
6467            /* for BD case, also check IP address with 10 sec timeout */
6468            (address == event->address &&
6469             (now - arp_event_last_time) < 10.0)))
6470         return 1;
6471     }
6472   /* *INDENT-ON* */
6473
6474   arp_event_last_time = now;
6475   event->sw_if_index = sw_if_index;
6476   if (event->mac_ip)
6477     event->address = address;
6478   return 0;
6479 }
6480
6481 static int
6482 nd_change_data_callback (u32 pool_index, u8 * new_mac,
6483                          u32 sw_if_index, ip6_address_t * address)
6484 {
6485   vpe_api_main_t *am = &vpe_api_main;
6486   vlib_main_t *vm = am->vlib_main;
6487   vl_api_ip6_nd_event_t *event;
6488   static f64 nd_event_last_time;
6489   f64 now = vlib_time_now (vm);
6490
6491   if (pool_is_free_index (am->nd_events, pool_index))
6492     return 1;
6493
6494   event = pool_elt_at_index (am->nd_events, pool_index);
6495
6496   /* *INDENT-OFF* */
6497   if (memcmp (&event->new_mac, new_mac, sizeof (event->new_mac)))
6498     {
6499       clib_memcpy (event->new_mac, new_mac, sizeof (event->new_mac));
6500     }
6501   else
6502     {                           /* same mac */
6503       if (sw_if_index == event->sw_if_index &&
6504           (!event->mac_ip ||
6505            /* for BD case, also check IP address with 10 sec timeout */
6506            (ip6_address_is_equal (address,
6507                                   (ip6_address_t *) event->address) &&
6508             (now - nd_event_last_time) < 10.0)))
6509         return 1;
6510     }
6511   /* *INDENT-ON* */
6512
6513   nd_event_last_time = now;
6514   event->sw_if_index = sw_if_index;
6515   if (event->mac_ip)
6516     clib_memcpy (event->address, address, sizeof (event->address));
6517   return 0;
6518 }
6519
6520 static int
6521 arp_change_delete_callback (u32 pool_index, u8 * notused)
6522 {
6523   vpe_api_main_t *am = &vpe_api_main;
6524
6525   if (pool_is_free_index (am->arp_events, pool_index))
6526     return 1;
6527
6528   pool_put_index (am->arp_events, pool_index);
6529   return 0;
6530 }
6531
6532 static int
6533 nd_change_delete_callback (u32 pool_index, u8 * notused)
6534 {
6535   vpe_api_main_t *am = &vpe_api_main;
6536
6537   if (pool_is_free_index (am->nd_events, pool_index))
6538     return 1;
6539
6540   pool_put_index (am->nd_events, pool_index);
6541   return 0;
6542 }
6543
6544 static void
6545 vl_api_want_ip4_arp_events_t_handler (vl_api_want_ip4_arp_events_t * mp)
6546 {
6547   vpe_api_main_t *am = &vpe_api_main;
6548   vnet_main_t *vnm = vnet_get_main ();
6549   vl_api_want_ip4_arp_events_reply_t *rmp;
6550   vl_api_ip4_arp_event_t *event;
6551   int rv;
6552
6553   if (mp->enable_disable)
6554     {
6555       pool_get (am->arp_events, event);
6556       memset (event, 0, sizeof (*event));
6557
6558       event->_vl_msg_id = ntohs (VL_API_IP4_ARP_EVENT);
6559       event->client_index = mp->client_index;
6560       event->context = mp->context;
6561       event->address = mp->address;
6562       event->pid = mp->pid;
6563       if (mp->address == 0)
6564         event->mac_ip = 1;
6565
6566       rv = vnet_add_del_ip4_arp_change_event
6567         (vnm, arp_change_data_callback,
6568          mp->pid, &mp->address /* addr, in net byte order */ ,
6569          vpe_resolver_process_node.index,
6570          IP4_ARP_EVENT, event - am->arp_events, 1 /* is_add */ );
6571     }
6572   else
6573     {
6574       rv = vnet_add_del_ip4_arp_change_event
6575         (vnm, arp_change_delete_callback,
6576          mp->pid, &mp->address /* addr, in net byte order */ ,
6577          vpe_resolver_process_node.index,
6578          IP4_ARP_EVENT, ~0 /* pool index */ , 0 /* is_add */ );
6579     }
6580   REPLY_MACRO (VL_API_WANT_IP4_ARP_EVENTS_REPLY);
6581 }
6582
6583 static void
6584 vl_api_want_ip6_nd_events_t_handler (vl_api_want_ip6_nd_events_t * mp)
6585 {
6586   vpe_api_main_t *am = &vpe_api_main;
6587   vnet_main_t *vnm = vnet_get_main ();
6588   vl_api_want_ip6_nd_events_reply_t *rmp;
6589   vl_api_ip6_nd_event_t *event;
6590   int rv;
6591
6592   if (mp->enable_disable)
6593     {
6594       pool_get (am->nd_events, event);
6595       memset (event, 0, sizeof (*event));
6596
6597       event->_vl_msg_id = ntohs (VL_API_IP6_ND_EVENT);
6598       event->client_index = mp->client_index;
6599       event->context = mp->context;
6600       clib_memcpy (event->address, mp->address, 16);
6601       event->pid = mp->pid;
6602       if (ip6_address_is_zero ((ip6_address_t *) mp->address))
6603         event->mac_ip = 1;
6604
6605       rv = vnet_add_del_ip6_nd_change_event
6606         (vnm, nd_change_data_callback,
6607          mp->pid, mp->address /* addr, in net byte order */ ,
6608          vpe_resolver_process_node.index,
6609          IP6_ND_EVENT, event - am->nd_events, 1 /* is_add */ );
6610     }
6611   else
6612     {
6613       rv = vnet_add_del_ip6_nd_change_event
6614         (vnm, nd_change_delete_callback,
6615          mp->pid, mp->address /* addr, in net byte order */ ,
6616          vpe_resolver_process_node.index,
6617          IP6_ND_EVENT, ~0 /* pool index */ , 0 /* is_add */ );
6618     }
6619   REPLY_MACRO (VL_API_WANT_IP6_ND_EVENTS_REPLY);
6620 }
6621
6622 static void vl_api_input_acl_set_interface_t_handler
6623   (vl_api_input_acl_set_interface_t * mp)
6624 {
6625   vlib_main_t *vm = vlib_get_main ();
6626   vl_api_input_acl_set_interface_reply_t *rmp;
6627   int rv;
6628   u32 sw_if_index, ip4_table_index, ip6_table_index, l2_table_index;
6629
6630   ip4_table_index = ntohl (mp->ip4_table_index);
6631   ip6_table_index = ntohl (mp->ip6_table_index);
6632   l2_table_index = ntohl (mp->l2_table_index);
6633   sw_if_index = ntohl (mp->sw_if_index);
6634
6635   VALIDATE_SW_IF_INDEX (mp);
6636
6637   rv = vnet_set_input_acl_intfc (vm, sw_if_index, ip4_table_index,
6638                                  ip6_table_index, l2_table_index, mp->is_add);
6639
6640   BAD_SW_IF_INDEX_LABEL;
6641
6642   REPLY_MACRO (VL_API_INPUT_ACL_SET_INTERFACE_REPLY);
6643 }
6644
6645 static void vl_api_ipsec_spd_add_del_t_handler
6646   (vl_api_ipsec_spd_add_del_t * mp)
6647 {
6648 #if IPSEC == 0
6649   clib_warning ("unimplemented");
6650 #else
6651
6652   vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
6653   vl_api_ipsec_spd_add_del_reply_t *rmp;
6654   int rv;
6655
6656 #if DPDK > 0
6657   rv = ipsec_add_del_spd (vm, ntohl (mp->spd_id), mp->is_add);
6658 #else
6659   rv = VNET_API_ERROR_UNIMPLEMENTED;
6660 #endif
6661
6662   REPLY_MACRO (VL_API_IPSEC_SPD_ADD_DEL_REPLY);
6663 #endif
6664 }
6665
6666 static void vl_api_ipsec_interface_add_del_spd_t_handler
6667   (vl_api_ipsec_interface_add_del_spd_t * mp)
6668 {
6669   vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
6670   vl_api_ipsec_interface_add_del_spd_reply_t *rmp;
6671   int rv;
6672   u32 sw_if_index __attribute__ ((unused));
6673   u32 spd_id __attribute__ ((unused));
6674
6675   sw_if_index = ntohl (mp->sw_if_index);
6676   spd_id = ntohl (mp->spd_id);
6677
6678   VALIDATE_SW_IF_INDEX (mp);
6679
6680 #if IPSEC > 0
6681   rv = ipsec_set_interface_spd (vm, sw_if_index, spd_id, mp->is_add);
6682 #else
6683   rv = VNET_API_ERROR_UNIMPLEMENTED;
6684 #endif
6685
6686   BAD_SW_IF_INDEX_LABEL;
6687
6688   REPLY_MACRO (VL_API_IPSEC_INTERFACE_ADD_DEL_SPD_REPLY);
6689 }
6690
6691 static void vl_api_ipsec_spd_add_del_entry_t_handler
6692   (vl_api_ipsec_spd_add_del_entry_t * mp)
6693 {
6694   vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
6695   vl_api_ipsec_spd_add_del_entry_reply_t *rmp;
6696   int rv;
6697
6698 #if IPSEC > 0
6699   ipsec_policy_t p;
6700
6701   memset (&p, 0, sizeof (p));
6702
6703   p.id = ntohl (mp->spd_id);
6704   p.priority = ntohl (mp->priority);
6705   p.is_outbound = mp->is_outbound;
6706   p.is_ipv6 = mp->is_ipv6;
6707
6708   if (mp->is_ipv6 || mp->is_ip_any)
6709     {
6710       clib_memcpy (&p.raddr.start, mp->remote_address_start, 16);
6711       clib_memcpy (&p.raddr.stop, mp->remote_address_stop, 16);
6712       clib_memcpy (&p.laddr.start, mp->local_address_start, 16);
6713       clib_memcpy (&p.laddr.stop, mp->local_address_stop, 16);
6714     }
6715   else
6716     {
6717       clib_memcpy (&p.raddr.start.ip4.data, mp->remote_address_start, 4);
6718       clib_memcpy (&p.raddr.stop.ip4.data, mp->remote_address_stop, 4);
6719       clib_memcpy (&p.laddr.start.ip4.data, mp->local_address_start, 4);
6720       clib_memcpy (&p.laddr.stop.ip4.data, mp->local_address_stop, 4);
6721     }
6722   p.protocol = mp->protocol;
6723   p.rport.start = ntohs (mp->remote_port_start);
6724   p.rport.stop = ntohs (mp->remote_port_stop);
6725   p.lport.start = ntohs (mp->local_port_start);
6726   p.lport.stop = ntohs (mp->local_port_stop);
6727   /* policy action resolve unsupported */
6728   if (mp->policy == IPSEC_POLICY_ACTION_RESOLVE)
6729     {
6730       clib_warning ("unsupported action: 'resolve'");
6731       rv = VNET_API_ERROR_UNIMPLEMENTED;
6732       goto out;
6733     }
6734   p.policy = mp->policy;
6735   p.sa_id = ntohl (mp->sa_id);
6736
6737   rv = ipsec_add_del_policy (vm, &p, mp->is_add);
6738   if (rv)
6739     goto out;
6740
6741   if (mp->is_ip_any)
6742     {
6743       p.is_ipv6 = 1;
6744       rv = ipsec_add_del_policy (vm, &p, mp->is_add);
6745     }
6746 #else
6747   rv = VNET_API_ERROR_UNIMPLEMENTED;
6748   goto out;
6749 #endif
6750
6751 out:
6752   REPLY_MACRO (VL_API_IPSEC_SPD_ADD_DEL_ENTRY_REPLY);
6753 }
6754
6755 static void vl_api_ipsec_sad_add_del_entry_t_handler
6756   (vl_api_ipsec_sad_add_del_entry_t * mp)
6757 {
6758   vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
6759   vl_api_ipsec_sad_add_del_entry_reply_t *rmp;
6760   int rv;
6761 #if IPSEC > 0
6762   ipsec_sa_t sa;
6763
6764   memset (&sa, 0, sizeof (sa));
6765
6766   sa.id = ntohl (mp->sad_id);
6767   sa.spi = ntohl (mp->spi);
6768   /* security protocol AH unsupported */
6769   if (mp->protocol == IPSEC_PROTOCOL_AH)
6770     {
6771       clib_warning ("unsupported security protocol 'AH'");
6772       rv = VNET_API_ERROR_UNIMPLEMENTED;
6773       goto out;
6774     }
6775   sa.protocol = mp->protocol;
6776   /* check for unsupported crypto-alg */
6777   if (mp->crypto_algorithm < IPSEC_CRYPTO_ALG_AES_CBC_128 ||
6778       mp->crypto_algorithm > IPSEC_CRYPTO_ALG_AES_CBC_256)
6779     {
6780       clib_warning ("unsupported crypto-alg: '%U'", format_ipsec_crypto_alg,
6781                     mp->crypto_algorithm);
6782       rv = VNET_API_ERROR_UNIMPLEMENTED;
6783       goto out;
6784     }
6785   sa.crypto_alg = mp->crypto_algorithm;
6786   sa.crypto_key_len = mp->crypto_key_length;
6787   clib_memcpy (&sa.crypto_key, mp->crypto_key, sizeof (sa.crypto_key));
6788   /* check for unsupported integ-alg */
6789   if (mp->integrity_algorithm < IPSEC_INTEG_ALG_SHA1_96 ||
6790       mp->integrity_algorithm > IPSEC_INTEG_ALG_SHA_512_256)
6791     {
6792       clib_warning ("unsupported integ-alg: '%U'", format_ipsec_integ_alg,
6793                     mp->integrity_algorithm);
6794       rv = VNET_API_ERROR_UNIMPLEMENTED;
6795       goto out;
6796     }
6797   sa.integ_alg = mp->integrity_algorithm;
6798   sa.integ_key_len = mp->integrity_key_length;
6799   clib_memcpy (&sa.integ_key, mp->integrity_key, sizeof (sa.integ_key));
6800   sa.use_esn = mp->use_extended_sequence_number;
6801   sa.is_tunnel = mp->is_tunnel;
6802   sa.is_tunnel_ip6 = mp->is_tunnel_ipv6;
6803   if (sa.is_tunnel_ip6)
6804     {
6805       clib_memcpy (&sa.tunnel_src_addr, mp->tunnel_src_address, 16);
6806       clib_memcpy (&sa.tunnel_dst_addr, mp->tunnel_dst_address, 16);
6807     }
6808   else
6809     {
6810       clib_memcpy (&sa.tunnel_src_addr.ip4.data, mp->tunnel_src_address, 4);
6811       clib_memcpy (&sa.tunnel_dst_addr.ip4.data, mp->tunnel_dst_address, 4);
6812     }
6813
6814   rv = ipsec_add_del_sa (vm, &sa, mp->is_add);
6815 #else
6816   rv = VNET_API_ERROR_UNIMPLEMENTED;
6817   goto out;
6818 #endif
6819
6820 out:
6821   REPLY_MACRO (VL_API_IPSEC_SAD_ADD_DEL_ENTRY_REPLY);
6822 }
6823
6824 static void
6825 vl_api_ikev2_profile_add_del_t_handler (vl_api_ikev2_profile_add_del_t * mp)
6826 {
6827   vl_api_ikev2_profile_add_del_reply_t *rmp;
6828   int rv = 0;
6829
6830 #if IPSEC > 0
6831   vlib_main_t *vm = vlib_get_main ();
6832   clib_error_t *error;
6833   u8 *tmp = format (0, "%s", mp->name);
6834   error = ikev2_add_del_profile (vm, tmp, mp->is_add);
6835   vec_free (tmp);
6836   if (error)
6837     rv = VNET_API_ERROR_UNSPECIFIED;
6838 #else
6839   rv = VNET_API_ERROR_UNIMPLEMENTED;
6840 #endif
6841
6842   REPLY_MACRO (VL_API_IKEV2_PROFILE_ADD_DEL_REPLY);
6843 }
6844
6845 static void
6846   vl_api_ikev2_profile_set_auth_t_handler
6847   (vl_api_ikev2_profile_set_auth_t * mp)
6848 {
6849   vl_api_ikev2_profile_set_auth_reply_t *rmp;
6850   int rv = 0;
6851
6852 #if IPSEC > 0
6853   vlib_main_t *vm = vlib_get_main ();
6854   clib_error_t *error;
6855   u8 *tmp = format (0, "%s", mp->name);
6856   u8 *data = vec_new (u8, mp->data_len);
6857   clib_memcpy (data, mp->data, mp->data_len);
6858   error = ikev2_set_profile_auth (vm, tmp, mp->auth_method, data, mp->is_hex);
6859   vec_free (tmp);
6860   vec_free (data);
6861   if (error)
6862     rv = VNET_API_ERROR_UNSPECIFIED;
6863 #else
6864   rv = VNET_API_ERROR_UNIMPLEMENTED;
6865 #endif
6866
6867   REPLY_MACRO (VL_API_IKEV2_PROFILE_SET_AUTH_REPLY);
6868 }
6869
6870 static void
6871 vl_api_ikev2_profile_set_id_t_handler (vl_api_ikev2_profile_set_id_t * mp)
6872 {
6873   vl_api_ikev2_profile_add_del_reply_t *rmp;
6874   int rv = 0;
6875
6876 #if IPSEC > 0
6877   vlib_main_t *vm = vlib_get_main ();
6878   clib_error_t *error;
6879   u8 *tmp = format (0, "%s", mp->name);
6880   u8 *data = vec_new (u8, mp->data_len);
6881   clib_memcpy (data, mp->data, mp->data_len);
6882   error = ikev2_set_profile_id (vm, tmp, mp->id_type, data, mp->is_local);
6883   vec_free (tmp);
6884   vec_free (data);
6885   if (error)
6886     rv = VNET_API_ERROR_UNSPECIFIED;
6887 #else
6888   rv = VNET_API_ERROR_UNIMPLEMENTED;
6889 #endif
6890
6891   REPLY_MACRO (VL_API_IKEV2_PROFILE_SET_ID_REPLY);
6892 }
6893
6894 static void
6895 vl_api_ikev2_profile_set_ts_t_handler (vl_api_ikev2_profile_set_ts_t * mp)
6896 {
6897   vl_api_ikev2_profile_set_ts_reply_t *rmp;
6898   int rv = 0;
6899
6900 #if IPSEC > 0
6901   vlib_main_t *vm = vlib_get_main ();
6902   clib_error_t *error;
6903   u8 *tmp = format (0, "%s", mp->name);
6904   error = ikev2_set_profile_ts (vm, tmp, mp->proto, mp->start_port,
6905                                 mp->end_port, (ip4_address_t) mp->start_addr,
6906                                 (ip4_address_t) mp->end_addr, mp->is_local);
6907   vec_free (tmp);
6908   if (error)
6909     rv = VNET_API_ERROR_UNSPECIFIED;
6910 #else
6911   rv = VNET_API_ERROR_UNIMPLEMENTED;
6912 #endif
6913
6914   REPLY_MACRO (VL_API_IKEV2_PROFILE_SET_TS_REPLY);
6915 }
6916
6917 static void
6918 vl_api_ikev2_set_local_key_t_handler (vl_api_ikev2_set_local_key_t * mp)
6919 {
6920   vl_api_ikev2_profile_set_ts_reply_t *rmp;
6921   int rv = 0;
6922
6923 #if IPSEC > 0
6924   vlib_main_t *vm = vlib_get_main ();
6925   clib_error_t *error;
6926
6927   error = ikev2_set_local_key (vm, mp->key_file);
6928   if (error)
6929     rv = VNET_API_ERROR_UNSPECIFIED;
6930 #else
6931   rv = VNET_API_ERROR_UNIMPLEMENTED;
6932 #endif
6933
6934   REPLY_MACRO (VL_API_IKEV2_SET_LOCAL_KEY_REPLY);
6935 }
6936
6937 static void
6938 vl_api_map_add_domain_t_handler (vl_api_map_add_domain_t * mp)
6939 {
6940   vl_api_map_add_domain_reply_t *rmp;
6941   int rv = 0;
6942   u32 index;
6943   u8 flags = mp->is_translation ? MAP_DOMAIN_TRANSLATION : 0;
6944   rv =
6945     map_create_domain ((ip4_address_t *) & mp->ip4_prefix, mp->ip4_prefix_len,
6946                        (ip6_address_t *) & mp->ip6_prefix, mp->ip6_prefix_len,
6947                        (ip6_address_t *) & mp->ip6_src,
6948                        mp->ip6_src_prefix_len, mp->ea_bits_len,
6949                        mp->psid_offset, mp->psid_length, &index,
6950                        ntohs (mp->mtu), flags);
6951
6952   /* *INDENT-OFF* */
6953   REPLY_MACRO2(VL_API_MAP_ADD_DOMAIN_REPLY,
6954   ({
6955     rmp->index = ntohl(index);
6956   }));
6957   /* *INDENT-ON* */
6958 }
6959
6960 static void
6961 vl_api_map_del_domain_t_handler (vl_api_map_del_domain_t * mp)
6962 {
6963   vl_api_map_del_domain_reply_t *rmp;
6964   int rv = 0;
6965
6966   rv = map_delete_domain (ntohl (mp->index));
6967
6968   REPLY_MACRO (VL_API_MAP_DEL_DOMAIN_REPLY);
6969 }
6970
6971 static void
6972 vl_api_map_add_del_rule_t_handler (vl_api_map_add_del_rule_t * mp)
6973 {
6974   vl_api_map_del_domain_reply_t *rmp;
6975   int rv = 0;
6976
6977   rv =
6978     map_add_del_psid (ntohl (mp->index), ntohs (mp->psid),
6979                       (ip6_address_t *) mp->ip6_dst, mp->is_add);
6980
6981   REPLY_MACRO (VL_API_MAP_ADD_DEL_RULE_REPLY);
6982 }
6983
6984 static void
6985 vl_api_map_domain_dump_t_handler (vl_api_map_domain_dump_t * mp)
6986 {
6987   vl_api_map_domain_details_t *rmp;
6988   map_main_t *mm = &map_main;
6989   map_domain_t *d;
6990   unix_shared_memory_queue_t *q;
6991
6992   if (pool_elts (mm->domains) == 0)
6993     return;
6994
6995   q = vl_api_client_index_to_input_queue (mp->client_index);
6996   if (q == 0)
6997     {
6998       return;
6999     }
7000
7001   /* *INDENT-OFF* */
7002   pool_foreach(d, mm->domains,
7003   ({
7004     /* Make sure every field is initiated (or don't skip the memset()) */
7005     rmp = vl_msg_api_alloc (sizeof (*rmp));
7006     rmp->_vl_msg_id = ntohs(VL_API_MAP_DOMAIN_DETAILS);
7007     rmp->domain_index = htonl(d - mm->domains);
7008     rmp->ea_bits_len = d->ea_bits_len;
7009     rmp->psid_offset = d->psid_offset;
7010     rmp->psid_length = d->psid_length;
7011     clib_memcpy(rmp->ip4_prefix, &d->ip4_prefix, sizeof(rmp->ip4_prefix));
7012     rmp->ip4_prefix_len = d->ip4_prefix_len;
7013     clib_memcpy(rmp->ip6_prefix, &d->ip6_prefix, sizeof(rmp->ip6_prefix));
7014     rmp->ip6_prefix_len = d->ip6_prefix_len;
7015     clib_memcpy(rmp->ip6_src, &d->ip6_src, sizeof(rmp->ip6_src));
7016     rmp->ip6_src_len = d->ip6_src_len;
7017     rmp->mtu = htons(d->mtu);
7018     rmp->is_translation = (d->flags & MAP_DOMAIN_TRANSLATION);
7019     rmp->context = mp->context;
7020
7021     vl_msg_api_send_shmem (q, (u8 *)&rmp);
7022   }));
7023   /* *INDENT-ON* */
7024 }
7025
7026 static void
7027 vl_api_map_rule_dump_t_handler (vl_api_map_rule_dump_t * mp)
7028 {
7029   unix_shared_memory_queue_t *q;
7030   u16 i;
7031   ip6_address_t dst;
7032   vl_api_map_rule_details_t *rmp;
7033   map_main_t *mm = &map_main;
7034   u32 domain_index = ntohl (mp->domain_index);
7035   map_domain_t *d;
7036
7037   if (pool_elts (mm->domains) == 0)
7038     return;
7039
7040   d = pool_elt_at_index (mm->domains, domain_index);
7041   if (!d || !d->rules)
7042     {
7043       return;
7044     }
7045
7046   q = vl_api_client_index_to_input_queue (mp->client_index);
7047   if (q == 0)
7048     {
7049       return;
7050     }
7051
7052   for (i = 0; i < (0x1 << d->psid_length); i++)
7053     {
7054       dst = d->rules[i];
7055       if (dst.as_u64[0] == 0 && dst.as_u64[1] == 0)
7056         {
7057           continue;
7058         }
7059       rmp = vl_msg_api_alloc (sizeof (*rmp));
7060       memset (rmp, 0, sizeof (*rmp));
7061       rmp->_vl_msg_id = ntohs (VL_API_MAP_RULE_DETAILS);
7062       rmp->psid = htons (i);
7063       clib_memcpy (rmp->ip6_dst, &dst, sizeof (rmp->ip6_dst));
7064       rmp->context = mp->context;
7065       vl_msg_api_send_shmem (q, (u8 *) & rmp);
7066     }
7067 }
7068
7069 static void
7070 vl_api_map_summary_stats_t_handler (vl_api_map_summary_stats_t * mp)
7071 {
7072   vl_api_map_summary_stats_reply_t *rmp;
7073   vlib_combined_counter_main_t *cm;
7074   vlib_counter_t v;
7075   int i, which;
7076   u64 total_pkts[VLIB_N_RX_TX];
7077   u64 total_bytes[VLIB_N_RX_TX];
7078   map_main_t *mm = &map_main;
7079   unix_shared_memory_queue_t *q =
7080     vl_api_client_index_to_input_queue (mp->client_index);
7081
7082   if (!q)
7083     return;
7084
7085   rmp = vl_msg_api_alloc (sizeof (*rmp));
7086   rmp->_vl_msg_id = ntohs (VL_API_MAP_SUMMARY_STATS_REPLY);
7087   rmp->context = mp->context;
7088   rmp->retval = 0;
7089
7090   memset (total_pkts, 0, sizeof (total_pkts));
7091   memset (total_bytes, 0, sizeof (total_bytes));
7092
7093   map_domain_counter_lock (mm);
7094   vec_foreach (cm, mm->domain_counters)
7095   {
7096     which = cm - mm->domain_counters;
7097
7098     for (i = 0; i < vec_len (cm->maxi); i++)
7099       {
7100         vlib_get_combined_counter (cm, i, &v);
7101         total_pkts[which] += v.packets;
7102         total_bytes[which] += v.bytes;
7103       }
7104   }
7105
7106   map_domain_counter_unlock (mm);
7107
7108   /* Note: in network byte order! */
7109   rmp->total_pkts[MAP_DOMAIN_COUNTER_RX] =
7110     clib_host_to_net_u64 (total_pkts[MAP_DOMAIN_COUNTER_RX]);
7111   rmp->total_bytes[MAP_DOMAIN_COUNTER_RX] =
7112     clib_host_to_net_u64 (total_bytes[MAP_DOMAIN_COUNTER_RX]);
7113   rmp->total_pkts[MAP_DOMAIN_COUNTER_TX] =
7114     clib_host_to_net_u64 (total_pkts[MAP_DOMAIN_COUNTER_TX]);
7115   rmp->total_bytes[MAP_DOMAIN_COUNTER_TX] =
7116     clib_host_to_net_u64 (total_bytes[MAP_DOMAIN_COUNTER_TX]);
7117   rmp->total_bindings = clib_host_to_net_u64 (pool_elts (mm->domains));
7118   rmp->total_ip4_fragments = 0; // Not yet implemented. Should be a simple counter.
7119   rmp->total_security_check[MAP_DOMAIN_COUNTER_TX] =
7120     clib_host_to_net_u64 (map_error_counter_get
7121                           (ip4_map_node.index, MAP_ERROR_ENCAP_SEC_CHECK));
7122   rmp->total_security_check[MAP_DOMAIN_COUNTER_RX] =
7123     clib_host_to_net_u64 (map_error_counter_get
7124                           (ip4_map_node.index, MAP_ERROR_DECAP_SEC_CHECK));
7125
7126   vl_msg_api_send_shmem (q, (u8 *) & rmp);
7127 }
7128
7129 static void
7130 vl_api_ipsec_sa_set_key_t_handler (vl_api_ipsec_sa_set_key_t * mp)
7131 {
7132   vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
7133   vl_api_ipsec_sa_set_key_reply_t *rmp;
7134   int rv;
7135 #if IPSEC > 0
7136   ipsec_sa_t sa;
7137   sa.id = ntohl (mp->sa_id);
7138   sa.crypto_key_len = mp->crypto_key_length;
7139   clib_memcpy (&sa.crypto_key, mp->crypto_key, sizeof (sa.crypto_key));
7140   sa.integ_key_len = mp->integrity_key_length;
7141   clib_memcpy (&sa.integ_key, mp->integrity_key, sizeof (sa.integ_key));
7142
7143   rv = ipsec_set_sa_key (vm, &sa);
7144 #else
7145   rv = VNET_API_ERROR_UNIMPLEMENTED;
7146 #endif
7147
7148   REPLY_MACRO (VL_API_IPSEC_SA_SET_KEY_REPLY);
7149 }
7150
7151 static void vl_api_cop_interface_enable_disable_t_handler
7152   (vl_api_cop_interface_enable_disable_t * mp)
7153 {
7154   vl_api_cop_interface_enable_disable_reply_t *rmp;
7155   int rv;
7156   u32 sw_if_index = ntohl (mp->sw_if_index);
7157   int enable_disable;
7158
7159   VALIDATE_SW_IF_INDEX (mp);
7160
7161   enable_disable = (int) mp->enable_disable;
7162
7163   rv = cop_interface_enable_disable (sw_if_index, enable_disable);
7164
7165   BAD_SW_IF_INDEX_LABEL;
7166
7167   REPLY_MACRO (VL_API_COP_INTERFACE_ENABLE_DISABLE_REPLY);
7168 }
7169
7170 static void vl_api_cop_whitelist_enable_disable_t_handler
7171   (vl_api_cop_whitelist_enable_disable_t * mp)
7172 {
7173   vl_api_cop_whitelist_enable_disable_reply_t *rmp;
7174   cop_whitelist_enable_disable_args_t _a, *a = &_a;
7175   u32 sw_if_index = ntohl (mp->sw_if_index);
7176   int rv;
7177
7178   VALIDATE_SW_IF_INDEX (mp);
7179
7180   a->sw_if_index = sw_if_index;
7181   a->ip4 = mp->ip4;
7182   a->ip6 = mp->ip6;
7183   a->default_cop = mp->default_cop;
7184   a->fib_id = ntohl (mp->fib_id);
7185
7186   rv = cop_whitelist_enable_disable (a);
7187
7188   BAD_SW_IF_INDEX_LABEL;
7189
7190   REPLY_MACRO (VL_API_COP_WHITELIST_ENABLE_DISABLE_REPLY);
7191 }
7192
7193 static void
7194 vl_api_get_node_graph_t_handler (vl_api_get_node_graph_t * mp)
7195 {
7196   int rv = 0;
7197   u8 *vector = 0;
7198   api_main_t *am = &api_main;
7199   vlib_main_t *vm = vlib_get_main ();
7200   void *oldheap;
7201   vl_api_get_node_graph_reply_t *rmp;
7202
7203   pthread_mutex_lock (&am->vlib_rp->mutex);
7204   oldheap = svm_push_data_heap (am->vlib_rp);
7205
7206   /*
7207    * Keep the number of memcpy ops to a minimum (e.g. 1).
7208    */
7209   vec_validate (vector, 16384);
7210   vec_reset_length (vector);
7211
7212   /* $$$$ FIXME */
7213   vector = vlib_node_serialize (&vm->node_main, vector,
7214                                 (u32) ~ 0 /* all threads */ ,
7215                                 1 /* include nexts */ ,
7216                                 1 /* include stats */ );
7217
7218   svm_pop_heap (oldheap);
7219   pthread_mutex_unlock (&am->vlib_rp->mutex);
7220
7221   /* *INDENT-OFF* */
7222   REPLY_MACRO2(VL_API_GET_NODE_GRAPH_REPLY,
7223   ({
7224     rmp->reply_in_shmem = (uword) vector;
7225   }));
7226   /* *INDENT-ON* */
7227 }
7228
7229 static void
7230 vl_api_ioam_enable_t_handler (vl_api_ioam_enable_t * mp)
7231 {
7232   int rv = 0;
7233   vl_api_ioam_enable_reply_t *rmp;
7234   clib_error_t *error;
7235
7236   /* Ignoring the profile id as currently a single profile
7237    * is supported */
7238   error = ip6_ioam_enable (mp->trace_enable, mp->pot_enable,
7239                            mp->seqno, mp->analyse);
7240   if (error)
7241     {
7242       clib_error_report (error);
7243       rv = clib_error_get_code (error);
7244     }
7245
7246   REPLY_MACRO (VL_API_IOAM_ENABLE_REPLY);
7247 }
7248
7249 static void
7250 vl_api_ioam_disable_t_handler (vl_api_ioam_disable_t * mp)
7251 {
7252   int rv = 0;
7253   vl_api_ioam_disable_reply_t *rmp;
7254   clib_error_t *error;
7255
7256   error = clear_ioam_rewrite_fn ();
7257   if (error)
7258     {
7259       clib_error_report (error);
7260       rv = clib_error_get_code (error);
7261     }
7262
7263   REPLY_MACRO (VL_API_IOAM_DISABLE_REPLY);
7264 }
7265
7266 static void
7267 vl_api_af_packet_create_t_handler (vl_api_af_packet_create_t * mp)
7268 {
7269   vlib_main_t *vm = vlib_get_main ();
7270   vl_api_af_packet_create_reply_t *rmp;
7271   int rv = 0;
7272   u8 *host_if_name = NULL;
7273   u32 sw_if_index;
7274
7275   host_if_name = format (0, "%s", mp->host_if_name);
7276   vec_add1 (host_if_name, 0);
7277
7278   rv = af_packet_create_if (vm, host_if_name,
7279                             mp->use_random_hw_addr ? 0 : mp->hw_addr,
7280                             &sw_if_index);
7281
7282   vec_free (host_if_name);
7283
7284   /* *INDENT-OFF* */
7285   REPLY_MACRO2(VL_API_AF_PACKET_CREATE_REPLY,
7286   ({
7287     rmp->sw_if_index = clib_host_to_net_u32(sw_if_index);
7288   }));
7289   /* *INDENT-ON* */
7290 }
7291
7292 static void
7293 vl_api_af_packet_delete_t_handler (vl_api_af_packet_delete_t * mp)
7294 {
7295   vlib_main_t *vm = vlib_get_main ();
7296   vl_api_af_packet_delete_reply_t *rmp;
7297   int rv = 0;
7298   u8 *host_if_name = NULL;
7299
7300   host_if_name = format (0, "%s", mp->host_if_name);
7301   vec_add1 (host_if_name, 0);
7302
7303   rv = af_packet_delete_if (vm, host_if_name);
7304
7305   vec_free (host_if_name);
7306
7307   REPLY_MACRO (VL_API_AF_PACKET_DELETE_REPLY);
7308 }
7309
7310 static void
7311 vl_api_policer_add_del_t_handler (vl_api_policer_add_del_t * mp)
7312 {
7313   vlib_main_t *vm = vlib_get_main ();
7314   vl_api_policer_add_del_reply_t *rmp;
7315   int rv = 0;
7316   u8 *name = NULL;
7317   sse2_qos_pol_cfg_params_st cfg;
7318   clib_error_t *error;
7319   u32 policer_index;
7320
7321   name = format (0, "%s", mp->name);
7322
7323   memset (&cfg, 0, sizeof (cfg));
7324   cfg.rfc = mp->type;
7325   cfg.rnd_type = mp->round_type;
7326   cfg.rate_type = mp->rate_type;
7327   cfg.rb.kbps.cir_kbps = mp->cir;
7328   cfg.rb.kbps.eir_kbps = mp->eir;
7329   cfg.rb.kbps.cb_bytes = mp->cb;
7330   cfg.rb.kbps.eb_bytes = mp->eb;
7331   cfg.conform_action.action_type = mp->conform_action_type;
7332   cfg.conform_action.dscp = mp->conform_dscp;
7333   cfg.exceed_action.action_type = mp->exceed_action_type;
7334   cfg.exceed_action.dscp = mp->exceed_dscp;
7335   cfg.violate_action.action_type = mp->violate_action_type;
7336   cfg.violate_action.dscp = mp->violate_dscp;
7337   cfg.color_aware = mp->color_aware;
7338
7339   error = policer_add_del (vm, name, &cfg, &policer_index, mp->is_add);
7340
7341   if (error)
7342     rv = VNET_API_ERROR_UNSPECIFIED;
7343
7344   /* *INDENT-OFF* */
7345   REPLY_MACRO2(VL_API_POLICER_ADD_DEL_REPLY,
7346   ({
7347     if (rv == 0 &&  mp->is_add)
7348       rmp->policer_index = ntohl(policer_index);
7349     else
7350       rmp->policer_index = ~0;
7351   }));
7352   /* *INDENT-ON* */
7353 }
7354
7355 static void
7356 send_policer_details (u8 * name,
7357                       sse2_qos_pol_cfg_params_st * config,
7358                       policer_read_response_type_st * templ,
7359                       unix_shared_memory_queue_t * q, u32 context)
7360 {
7361   vl_api_policer_details_t *mp;
7362
7363   mp = vl_msg_api_alloc (sizeof (*mp));
7364   memset (mp, 0, sizeof (*mp));
7365   mp->_vl_msg_id = ntohs (VL_API_POLICER_DETAILS);
7366   mp->context = context;
7367   mp->cir = htonl (config->rb.kbps.cir_kbps);
7368   mp->eir = htonl (config->rb.kbps.eir_kbps);
7369   mp->cb = htonl (config->rb.kbps.cb_bytes);
7370   mp->eb = htonl (config->rb.kbps.eb_bytes);
7371   mp->rate_type = config->rate_type;
7372   mp->round_type = config->rnd_type;
7373   mp->type = config->rfc;
7374   mp->conform_action_type = config->conform_action.action_type;
7375   mp->conform_dscp = config->conform_action.dscp;
7376   mp->exceed_action_type = config->exceed_action.action_type;
7377   mp->exceed_dscp = config->exceed_action.dscp;
7378   mp->violate_action_type = config->violate_action.action_type;
7379   mp->violate_dscp = config->violate_action.dscp;
7380   mp->single_rate = templ->single_rate ? 1 : 0;
7381   mp->color_aware = templ->color_aware ? 1 : 0;
7382   mp->scale = htonl (templ->scale);
7383   mp->cir_tokens_per_period = htonl (templ->cir_tokens_per_period);
7384   mp->pir_tokens_per_period = htonl (templ->pir_tokens_per_period);
7385   mp->current_limit = htonl (templ->current_limit);
7386   mp->current_bucket = htonl (templ->current_bucket);
7387   mp->extended_limit = htonl (templ->extended_limit);
7388   mp->extended_bucket = htonl (templ->extended_bucket);
7389   mp->last_update_time = clib_host_to_net_u64 (templ->last_update_time);
7390
7391   strncpy ((char *) mp->name, (char *) name, ARRAY_LEN (mp->name) - 1);
7392
7393   vl_msg_api_send_shmem (q, (u8 *) & mp);
7394 }
7395
7396 static void
7397 vl_api_policer_dump_t_handler (vl_api_policer_dump_t * mp)
7398 {
7399   unix_shared_memory_queue_t *q;
7400   vnet_policer_main_t *pm = &vnet_policer_main;
7401   hash_pair_t *hp;
7402   uword *p;
7403   u32 pool_index;
7404   u8 *match_name = 0;
7405   u8 *name;
7406   sse2_qos_pol_cfg_params_st *config;
7407   policer_read_response_type_st *templ;
7408
7409   q = vl_api_client_index_to_input_queue (mp->client_index);
7410   if (q == 0)
7411     return;
7412
7413   if (mp->match_name_valid)
7414     {
7415       match_name = format (0, "%s%c", mp->match_name, 0);
7416     }
7417
7418   if (mp->match_name_valid)
7419     {
7420       p = hash_get_mem (pm->policer_config_by_name, match_name);
7421       if (p)
7422         {
7423           pool_index = p[0];
7424           config = pool_elt_at_index (pm->configs, pool_index);
7425           templ = pool_elt_at_index (pm->policer_templates, pool_index);
7426           send_policer_details (match_name, config, templ, q, mp->context);
7427         }
7428     }
7429   else
7430     {
7431       /* *INDENT-OFF* */
7432       hash_foreach_pair (hp, pm->policer_config_by_name,
7433       ({
7434         name = (u8 *) hp->key;
7435         pool_index = hp->value[0];
7436         config = pool_elt_at_index (pm->configs, pool_index);
7437         templ = pool_elt_at_index (pm->policer_templates, pool_index);
7438         send_policer_details(name, config, templ, q, mp->context);
7439       }));
7440       /* *INDENT-ON* */
7441     }
7442 }
7443
7444 static void
7445   vl_api_policer_classify_set_interface_t_handler
7446   (vl_api_policer_classify_set_interface_t * mp)
7447 {
7448   vlib_main_t *vm = vlib_get_main ();
7449   vl_api_policer_classify_set_interface_reply_t *rmp;
7450   int rv;
7451   u32 sw_if_index, ip4_table_index, ip6_table_index, l2_table_index;
7452
7453   ip4_table_index = ntohl (mp->ip4_table_index);
7454   ip6_table_index = ntohl (mp->ip6_table_index);
7455   l2_table_index = ntohl (mp->l2_table_index);
7456   sw_if_index = ntohl (mp->sw_if_index);
7457
7458   VALIDATE_SW_IF_INDEX (mp);
7459
7460   rv = vnet_set_policer_classify_intfc (vm, sw_if_index, ip4_table_index,
7461                                         ip6_table_index, l2_table_index,
7462                                         mp->is_add);
7463
7464   BAD_SW_IF_INDEX_LABEL;
7465
7466   REPLY_MACRO (VL_API_POLICER_CLASSIFY_SET_INTERFACE_REPLY);
7467 }
7468
7469 static void
7470 send_policer_classify_details (u32 sw_if_index,
7471                                u32 table_index,
7472                                unix_shared_memory_queue_t * q, u32 context)
7473 {
7474   vl_api_policer_classify_details_t *mp;
7475
7476   mp = vl_msg_api_alloc (sizeof (*mp));
7477   memset (mp, 0, sizeof (*mp));
7478   mp->_vl_msg_id = ntohs (VL_API_POLICER_CLASSIFY_DETAILS);
7479   mp->context = context;
7480   mp->sw_if_index = htonl (sw_if_index);
7481   mp->table_index = htonl (table_index);
7482
7483   vl_msg_api_send_shmem (q, (u8 *) & mp);
7484 }
7485
7486 static void
7487 vl_api_policer_classify_dump_t_handler (vl_api_policer_classify_dump_t * mp)
7488 {
7489   unix_shared_memory_queue_t *q;
7490   policer_classify_main_t *pcm = &policer_classify_main;
7491   u32 *vec_tbl;
7492   int i;
7493
7494   q = vl_api_client_index_to_input_queue (mp->client_index);
7495   if (q == 0)
7496     return;
7497
7498   vec_tbl = pcm->classify_table_index_by_sw_if_index[mp->type];
7499
7500   if (vec_len (vec_tbl))
7501     {
7502       for (i = 0; i < vec_len (vec_tbl); i++)
7503         {
7504           if (vec_elt (vec_tbl, i) == ~0)
7505             continue;
7506
7507           send_policer_classify_details (i, vec_elt (vec_tbl, i), q,
7508                                          mp->context);
7509         }
7510     }
7511 }
7512
7513 static void
7514 vl_api_netmap_create_t_handler (vl_api_netmap_create_t * mp)
7515 {
7516   vlib_main_t *vm = vlib_get_main ();
7517   vl_api_netmap_create_reply_t *rmp;
7518   int rv = 0;
7519   u8 *if_name = NULL;
7520
7521   if_name = format (0, "%s", mp->netmap_if_name);
7522   vec_add1 (if_name, 0);
7523
7524   rv =
7525     netmap_create_if (vm, if_name, mp->use_random_hw_addr ? 0 : mp->hw_addr,
7526                       mp->is_pipe, mp->is_master, 0);
7527
7528   vec_free (if_name);
7529
7530   REPLY_MACRO (VL_API_NETMAP_CREATE_REPLY);
7531 }
7532
7533 static void
7534 vl_api_netmap_delete_t_handler (vl_api_netmap_delete_t * mp)
7535 {
7536   vlib_main_t *vm = vlib_get_main ();
7537   vl_api_netmap_delete_reply_t *rmp;
7538   int rv = 0;
7539   u8 *if_name = NULL;
7540
7541   if_name = format (0, "%s", mp->netmap_if_name);
7542   vec_add1 (if_name, 0);
7543
7544   rv = netmap_delete_if (vm, if_name);
7545
7546   vec_free (if_name);
7547
7548   REPLY_MACRO (VL_API_NETMAP_DELETE_REPLY);
7549 }
7550
7551 static void
7552 vl_api_mpls_eth_tunnel_details_t_handler (vl_api_mpls_eth_tunnel_details_t *
7553                                           mp)
7554 {
7555   clib_warning ("BUG");
7556 }
7557
7558 static void
7559 send_mpls_eth_tunnel_entry (vpe_api_main_t * am,
7560                             unix_shared_memory_queue_t * q,
7561                             mpls_eth_tunnel_t * et, u32 index, u32 context)
7562 {
7563   mpls_main_t *mm = &mpls_main;
7564   mpls_encap_t *e;
7565   int i;
7566   u32 nlabels;
7567   vl_api_mpls_eth_tunnel_details_t *mp;
7568
7569   e = pool_elt_at_index (mm->encaps, et->encap_index);
7570   nlabels = vec_len (e->labels);
7571
7572   mp = vl_msg_api_alloc (sizeof (*mp) + nlabels * sizeof (u32));
7573   memset (mp, 0, sizeof (*mp));
7574   mp->_vl_msg_id = ntohs (VL_API_MPLS_ETH_TUNNEL_DETAILS);
7575   mp->context = context;
7576
7577   mp->tunnel_index = htonl (index);
7578   memcpy (mp->tunnel_dst_mac, et->tunnel_dst, 6);
7579   mp->intfc_address = et->intfc_address.as_u32;
7580   mp->tx_sw_if_index = htonl (et->tx_sw_if_index);
7581   mp->inner_fib_index = htonl (et->inner_fib_index);
7582   mp->mask_width = htonl (et->mask_width);
7583   mp->encap_index = htonl (et->encap_index);
7584   mp->hw_if_index = htonl (et->hw_if_index);
7585   mp->l2_only = htonl (et->l2_only);
7586   mp->nlabels = htonl (nlabels);
7587
7588   for (i = 0; i < nlabels; i++)
7589     {
7590       mp->labels[i] =
7591         htonl (vnet_mpls_uc_get_label
7592                (clib_host_to_net_u32 (e->labels[i].label_exp_s_ttl)));
7593     }
7594
7595   vl_msg_api_send_shmem (q, (u8 *) & mp);
7596 }
7597
7598 static void
7599 vl_api_mpls_eth_tunnel_dump_t_handler (vl_api_mpls_eth_tunnel_dump_t * mp)
7600 {
7601   vpe_api_main_t *am = &vpe_api_main;
7602   unix_shared_memory_queue_t *q;
7603   mpls_main_t *mm = &mpls_main;
7604   mpls_eth_tunnel_t *et;
7605   u32 index = ntohl (mp->tunnel_index);
7606
7607   q = vl_api_client_index_to_input_queue (mp->client_index);
7608   if (q == 0)
7609     return;
7610
7611   if (index != ~0)
7612     {
7613       if (!pool_is_free_index (mm->eth_tunnels, index))
7614         {
7615           et = pool_elt_at_index (mm->eth_tunnels, index);
7616           send_mpls_eth_tunnel_entry (am, q, et, et - mm->eth_tunnels,
7617                                       mp->context);
7618         }
7619     }
7620   else
7621     {
7622       /* *INDENT-OFF* */
7623       pool_foreach (et, mm->eth_tunnels,
7624       ({
7625         send_mpls_eth_tunnel_entry (am, q, et, et - mm->eth_tunnels,
7626                                     mp->context);
7627       }));
7628       /* *INDENT-ON* */
7629     }
7630 }
7631
7632 static void
7633 vl_api_mpls_fib_details_t_handler (vl_api_mpls_fib_details_t * mp)
7634 {
7635   clib_warning ("BUG");
7636 }
7637
7638 static void
7639 send_mpls_fib_details (vpe_api_main_t * am,
7640                        unix_shared_memory_queue_t * q,
7641                        u32 table_id, u32 label, u32 eos, u32 context)
7642 {
7643   vl_api_mpls_fib_details_t *mp;
7644
7645   mp = vl_msg_api_alloc (sizeof (*mp));
7646   memset (mp, 0, sizeof (*mp));
7647   mp->_vl_msg_id = ntohs (VL_API_MPLS_FIB_DETAILS);
7648   mp->context = context;
7649
7650   mp->table_id = htonl (table_id);
7651   mp->eos_bit = eos;
7652   mp->label = htonl (label);
7653
7654   vl_msg_api_send_shmem (q, (u8 *) & mp);
7655 }
7656
7657 static void
7658 vl_api_mpls_fib_dump_t_handler (vl_api_mpls_fib_dump_t * mp)
7659 {
7660   vpe_api_main_t *am = &vpe_api_main;
7661   unix_shared_memory_queue_t *q;
7662   mpls_main_t *mm = &mpls_main;
7663   fib_table_t *fib_table;
7664   fib_node_index_t lfei, *lfeip, *lfeis = NULL;
7665   mpls_label_t key;
7666   fib_prefix_t pfx;
7667   u32 fib_index;
7668
7669   q = vl_api_client_index_to_input_queue (mp->client_index);
7670   if (q == 0)
7671     return;
7672
7673   /* *INDENT-OFF* */
7674   pool_foreach (fib_table, mm->fibs,
7675   ({
7676     hash_foreach(key, lfei, fib_table->mpls.mf_entries,
7677     ({
7678         vec_add1(lfeis, lfei);
7679     }));
7680   }));
7681   vec_sort_with_function(lfeis, fib_entry_cmp_for_sort);
7682
7683   vec_foreach(lfeip, lfeis)
7684   {
7685     fib_entry_get_prefix(*lfeip, &pfx);
7686     fib_index = fib_entry_get_fib_index(*lfeip);
7687
7688     fib_table = fib_table_get(fib_index, pfx.fp_proto);
7689
7690     send_mpls_fib_details (am, q,
7691                            fib_table->ft_table_id,
7692                            pfx.fp_label,
7693                            pfx.fp_eos,
7694                            mp->context);
7695   }
7696
7697   vec_free (lfeis);
7698 }
7699
7700 static void
7701 vl_api_mpls_fib_encap_details_t_handler (vl_api_mpls_fib_encap_details_t * mp)
7702 {
7703   clib_warning ("BUG");
7704 }
7705
7706 static void
7707 send_mpls_fib_encap_details (vpe_api_main_t * am,
7708                              unix_shared_memory_queue_t * q,
7709                              show_mpls_fib_t * s, u32 context)
7710 {
7711   vl_api_mpls_fib_encap_details_t *mp;
7712   mpls_main_t *mm = &mpls_main;
7713   mpls_encap_t *e;
7714   int i;
7715   u32 nlabels;
7716
7717   e = pool_elt_at_index (mm->encaps, s->entry_index);
7718   nlabels = vec_len (e->labels);
7719
7720   mp = vl_msg_api_alloc (sizeof (*mp) + nlabels * sizeof (u32));
7721   memset (mp, 0, sizeof (*mp));
7722   mp->_vl_msg_id = ntohs (VL_API_MPLS_FIB_ENCAP_DETAILS);
7723   mp->context = context;
7724
7725   mp->fib_index = htonl (s->fib_index);
7726   mp->entry_index = htonl (s->entry_index);
7727   mp->dest = s->dest;
7728   mp->s_bit = htonl (s->s_bit);
7729
7730   mp->nlabels = htonl (nlabels);
7731
7732   for (i = 0; i < nlabels; i++)
7733     {
7734       mp->labels[i] =
7735         htonl (vnet_mpls_uc_get_label
7736                (clib_host_to_net_u32 (e->labels[i].label_exp_s_ttl)));
7737     }
7738
7739   vl_msg_api_send_shmem (q, (u8 *) & mp);
7740 }
7741
7742 static void
7743 vl_api_mpls_fib_encap_dump_t_handler (vl_api_mpls_fib_encap_dump_t * mp)
7744 {
7745   vpe_api_main_t *am = &vpe_api_main;
7746   unix_shared_memory_queue_t *q;
7747   vlib_main_t *vm = &vlib_global_main;
7748   u64 key;
7749   u32 value;
7750   show_mpls_fib_t *records = 0;
7751   show_mpls_fib_t *s;
7752   mpls_main_t *mm = &mpls_main;
7753   ip4_fib_t *rx_fib;
7754
7755   q = vl_api_client_index_to_input_queue (mp->client_index);
7756   if (q == 0)
7757     return;
7758
7759   /* *INDENT-OFF* */
7760   hash_foreach (key, value, mm->mpls_encap_by_fib_and_dest,
7761   ({
7762     vec_add2 (records, s, 1);
7763     s->fib_index = (u32)(key>>32);
7764     s->dest = (u32)(key & 0xFFFFFFFF);
7765     s->entry_index = (u32) value;
7766   }));
7767   /* *INDENT-ON* */
7768
7769   if (0 == vec_len (records))
7770     {
7771       vlib_cli_output (vm, "MPLS encap table empty");
7772       goto out;
7773     }
7774
7775   /* sort output by dst address within fib */
7776   vec_sort_with_function (records, mpls_dest_cmp);
7777   vec_sort_with_function (records, mpls_fib_index_cmp);
7778   vlib_cli_output (vm, "MPLS encap table");
7779   vlib_cli_output (vm, "%=6s%=16s%=16s", "Table", "Dest address", "Labels");
7780   vec_foreach (s, records)
7781   {
7782     rx_fib = ip4_fib_get (s->fib_index);
7783     vlib_cli_output (vm, "%=6d%=16U%=16U", rx_fib->table_id,
7784                      format_ip4_address, &s->dest, format_mpls_encap_index,
7785                      mm, s->entry_index);
7786     send_mpls_fib_encap_details (am, q, s, mp->context);
7787   }
7788
7789 out:
7790   vec_free (records);
7791 }
7792
7793 static void
7794 vl_api_classify_table_ids_t_handler (vl_api_classify_table_ids_t * mp)
7795 {
7796   unix_shared_memory_queue_t *q;
7797
7798   q = vl_api_client_index_to_input_queue (mp->client_index);
7799   if (q == 0)
7800     return;
7801
7802   vnet_classify_main_t *cm = &vnet_classify_main;
7803   vnet_classify_table_t *t;
7804   u32 *table_ids = 0;
7805   u32 count;
7806
7807   /* *INDENT-OFF* */
7808   pool_foreach (t, cm->tables,
7809   ({
7810     vec_add1 (table_ids, ntohl(t - cm->tables));
7811   }));
7812   /* *INDENT-ON* */
7813   count = vec_len (table_ids);
7814
7815   vl_api_classify_table_ids_reply_t *rmp;
7816   rmp = vl_msg_api_alloc_as_if_client (sizeof (*rmp) + count * sizeof (u32));
7817   rmp->_vl_msg_id = ntohs (VL_API_CLASSIFY_TABLE_IDS_REPLY);
7818   rmp->context = mp->context;
7819   rmp->count = ntohl (count);
7820   clib_memcpy (rmp->ids, table_ids, count * sizeof (u32));
7821   rmp->retval = 0;
7822
7823   vl_msg_api_send_shmem (q, (u8 *) & rmp);
7824
7825   vec_free (table_ids);
7826 }
7827
7828 static void
7829   vl_api_classify_table_by_interface_t_handler
7830   (vl_api_classify_table_by_interface_t * mp)
7831 {
7832   vl_api_classify_table_by_interface_reply_t *rmp;
7833   int rv = 0;
7834
7835   u32 sw_if_index = ntohl (mp->sw_if_index);
7836   u32 *acl = 0;
7837
7838   vec_validate (acl, INPUT_ACL_N_TABLES - 1);
7839   vec_set (acl, ~0);
7840
7841   VALIDATE_SW_IF_INDEX (mp);
7842
7843   input_acl_main_t *am = &input_acl_main;
7844
7845   int if_idx;
7846   u32 type;
7847
7848   for (type = 0; type < INPUT_ACL_N_TABLES; type++)
7849     {
7850       u32 *vec_tbl = am->classify_table_index_by_sw_if_index[type];
7851       if (vec_len (vec_tbl))
7852         {
7853           for (if_idx = 0; if_idx < vec_len (vec_tbl); if_idx++)
7854             {
7855               if (vec_elt (vec_tbl, if_idx) == ~0 || sw_if_index != if_idx)
7856                 {
7857                   continue;
7858                 }
7859               acl[type] = vec_elt (vec_tbl, if_idx);
7860             }
7861         }
7862     }
7863
7864   BAD_SW_IF_INDEX_LABEL;
7865
7866   /* *INDENT-OFF* */
7867   REPLY_MACRO2(VL_API_CLASSIFY_TABLE_BY_INTERFACE_REPLY,
7868   ({
7869     rmp->sw_if_index = ntohl(sw_if_index);
7870     rmp->l2_table_id = ntohl(acl[INPUT_ACL_TABLE_L2]);
7871     rmp->ip4_table_id = ntohl(acl[INPUT_ACL_TABLE_IP4]);
7872     rmp->ip6_table_id = ntohl(acl[INPUT_ACL_TABLE_IP6]);
7873   }));
7874   /* *INDENT-ON* */
7875   vec_free (acl);
7876 }
7877
7878 static void
7879 vl_api_classify_table_info_t_handler (vl_api_classify_table_info_t * mp)
7880 {
7881   unix_shared_memory_queue_t *q;
7882
7883   q = vl_api_client_index_to_input_queue (mp->client_index);
7884   if (q == 0)
7885     return;
7886
7887   vl_api_classify_table_info_reply_t *rmp = 0;
7888
7889   vnet_classify_main_t *cm = &vnet_classify_main;
7890   u32 table_id = ntohl (mp->table_id);
7891   vnet_classify_table_t *t;
7892
7893   /* *INDENT-OFF* */
7894   pool_foreach (t, cm->tables,
7895   ({
7896     if (table_id == t - cm->tables)
7897       {
7898         rmp = vl_msg_api_alloc_as_if_client
7899           (sizeof (*rmp) + t->match_n_vectors * sizeof (u32x4));
7900         rmp->_vl_msg_id = ntohs (VL_API_CLASSIFY_TABLE_INFO_REPLY);
7901         rmp->context = mp->context;
7902         rmp->table_id = ntohl(table_id);
7903         rmp->nbuckets = ntohl(t->nbuckets);
7904         rmp->match_n_vectors = ntohl(t->match_n_vectors);
7905         rmp->skip_n_vectors = ntohl(t->skip_n_vectors);
7906         rmp->active_sessions = ntohl(t->active_elements);
7907         rmp->next_table_index = ntohl(t->next_table_index);
7908         rmp->miss_next_index = ntohl(t->miss_next_index);
7909         rmp->mask_length = ntohl(t->match_n_vectors * sizeof (u32x4));
7910         clib_memcpy(rmp->mask, t->mask, t->match_n_vectors * sizeof(u32x4));
7911         rmp->retval = 0;
7912         break;
7913       }
7914   }));
7915   /* *INDENT-ON* */
7916
7917   if (rmp == 0)
7918     {
7919       rmp = vl_msg_api_alloc (sizeof (*rmp));
7920       rmp->_vl_msg_id = ntohs ((VL_API_CLASSIFY_TABLE_INFO_REPLY));
7921       rmp->context = mp->context;
7922       rmp->retval = ntohl (VNET_API_ERROR_CLASSIFY_TABLE_NOT_FOUND);
7923     }
7924
7925   vl_msg_api_send_shmem (q, (u8 *) & rmp);
7926 }
7927
7928 static void
7929 vl_api_classify_session_details_t_handler (vl_api_classify_session_details_t *
7930                                            mp)
7931 {
7932   clib_warning ("BUG");
7933 }
7934
7935 static void
7936 send_classify_session_details (unix_shared_memory_queue_t * q,
7937                                u32 table_id,
7938                                u32 match_length,
7939                                vnet_classify_entry_t * e, u32 context)
7940 {
7941   vl_api_classify_session_details_t *rmp;
7942
7943   rmp = vl_msg_api_alloc (sizeof (*rmp));
7944   memset (rmp, 0, sizeof (*rmp));
7945   rmp->_vl_msg_id = ntohs (VL_API_CLASSIFY_SESSION_DETAILS);
7946   rmp->context = context;
7947   rmp->table_id = ntohl (table_id);
7948   rmp->hit_next_index = ntohl (e->next_index);
7949   rmp->advance = ntohl (e->advance);
7950   rmp->opaque_index = ntohl (e->opaque_index);
7951   rmp->match_length = ntohl (match_length);
7952   clib_memcpy (rmp->match, e->key, match_length);
7953
7954   vl_msg_api_send_shmem (q, (u8 *) & rmp);
7955 }
7956
7957 static void
7958 vl_api_classify_session_dump_t_handler (vl_api_classify_session_dump_t * mp)
7959 {
7960   vnet_classify_main_t *cm = &vnet_classify_main;
7961   unix_shared_memory_queue_t *q;
7962
7963   u32 table_id = ntohl (mp->table_id);
7964   vnet_classify_table_t *t;
7965
7966   q = vl_api_client_index_to_input_queue (mp->client_index);
7967   if (!q)
7968     return;
7969
7970   /* *INDENT-OFF* */
7971   pool_foreach (t, cm->tables,
7972   ({
7973     if (table_id == t - cm->tables)
7974       {
7975         vnet_classify_bucket_t * b;
7976         vnet_classify_entry_t * v, * save_v;
7977         int i, j, k;
7978
7979         for (i = 0; i < t->nbuckets; i++)
7980           {
7981             b = &t->buckets [i];
7982             if (b->offset == 0)
7983               continue;
7984
7985             save_v = vnet_classify_get_entry (t, b->offset);
7986             for (j = 0; j < (1<<b->log2_pages); j++)
7987               {
7988                 for (k = 0; k < t->entries_per_page; k++)
7989                   {
7990                     v = vnet_classify_entry_at_index
7991                       (t, save_v, j*t->entries_per_page + k);
7992                     if (vnet_classify_entry_is_free (v))
7993                       continue;
7994
7995                     send_classify_session_details
7996                       (q, table_id, t->match_n_vectors * sizeof (u32x4),
7997                        v, mp->context);
7998                   }
7999               }
8000           }
8001         break;
8002       }
8003   }));
8004   /* *INDENT-ON* */
8005 }
8006
8007 static void
8008 vl_api_set_ipfix_exporter_t_handler (vl_api_set_ipfix_exporter_t * mp)
8009 {
8010   vlib_main_t *vm = vlib_get_main ();
8011   flow_report_main_t *frm = &flow_report_main;
8012   vl_api_set_ipfix_exporter_reply_t *rmp;
8013   ip4_address_t collector, src;
8014   u16 collector_port = UDP_DST_PORT_ipfix;
8015   u32 path_mtu;
8016   u32 template_interval;
8017   u8 udp_checksum;
8018   u32 fib_id;
8019   u32 fib_index = ~0;
8020   int rv = 0;
8021
8022   memcpy (collector.data, mp->collector_address, sizeof (collector.data));
8023   collector_port = ntohs (mp->collector_port);
8024   if (collector_port == (u16) ~ 0)
8025     collector_port = UDP_DST_PORT_ipfix;
8026   memcpy (src.data, mp->src_address, sizeof (src.data));
8027   fib_id = ntohl (mp->vrf_id);
8028
8029   ip4_main_t *im = &ip4_main;
8030   if (fib_id == ~0)
8031     {
8032       fib_index = ~0;
8033     }
8034   else
8035     {
8036       uword *p = hash_get (im->fib_index_by_table_id, fib_id);
8037       if (!p)
8038         {
8039           rv = VNET_API_ERROR_NO_SUCH_FIB;
8040           goto out;
8041         }
8042       fib_index = p[0];
8043     }
8044
8045   path_mtu = ntohl (mp->path_mtu);
8046   if (path_mtu == ~0)
8047     path_mtu = 512;             // RFC 7011 section 10.3.3.
8048   template_interval = ntohl (mp->template_interval);
8049   if (template_interval == ~0)
8050     template_interval = 20;
8051   udp_checksum = mp->udp_checksum;
8052
8053   if (collector.as_u32 == 0)
8054     {
8055       rv = VNET_API_ERROR_INVALID_VALUE;
8056       goto out;
8057     }
8058
8059   if (src.as_u32 == 0)
8060     {
8061       rv = VNET_API_ERROR_INVALID_VALUE;
8062       goto out;
8063     }
8064
8065   if (path_mtu > 1450 /* vpp does not support fragmentation */ )
8066     {
8067       rv = VNET_API_ERROR_INVALID_VALUE;
8068       goto out;
8069     }
8070
8071   if (path_mtu < 68)
8072     {
8073       rv = VNET_API_ERROR_INVALID_VALUE;
8074       goto out;
8075     }
8076
8077   /* Reset report streams if we are reconfiguring IP addresses */
8078   if (frm->ipfix_collector.as_u32 != collector.as_u32 ||
8079       frm->src_address.as_u32 != src.as_u32 ||
8080       frm->collector_port != collector_port)
8081     vnet_flow_reports_reset (frm);
8082
8083   frm->ipfix_collector.as_u32 = collector.as_u32;
8084   frm->collector_port = collector_port;
8085   frm->src_address.as_u32 = src.as_u32;
8086   frm->fib_index = fib_index;
8087   frm->path_mtu = path_mtu;
8088   frm->template_interval = template_interval;
8089   frm->udp_checksum = udp_checksum;
8090
8091   /* Turn on the flow reporting process */
8092   vlib_process_signal_event (vm, flow_report_process_node.index, 1, 0);
8093
8094 out:
8095   REPLY_MACRO (VL_API_SET_IPFIX_EXPORTER_REPLY);
8096 }
8097
8098 static void
8099 vl_api_ipfix_exporter_dump_t_handler (vl_api_ipfix_exporter_dump_t * mp)
8100 {
8101   flow_report_main_t *frm = &flow_report_main;
8102   unix_shared_memory_queue_t *q;
8103   vl_api_ipfix_exporter_details_t *rmp;
8104   ip4_main_t *im = &ip4_main;
8105   u32 vrf_id;
8106
8107   q = vl_api_client_index_to_input_queue (mp->client_index);
8108   if (!q)
8109     return;
8110
8111   rmp = vl_msg_api_alloc (sizeof (*rmp));
8112   memset (rmp, 0, sizeof (*rmp));
8113   rmp->_vl_msg_id = ntohs (VL_API_IPFIX_EXPORTER_DETAILS);
8114   rmp->context = mp->context;
8115   memcpy (rmp->collector_address, frm->ipfix_collector.data,
8116           sizeof (frm->ipfix_collector.data));
8117   rmp->collector_port = htons (frm->collector_port);
8118   memcpy (rmp->src_address, frm->src_address.data,
8119           sizeof (frm->src_address.data));
8120   if (frm->fib_index == ~0)
8121     vrf_id = ~0;
8122   else
8123     vrf_id = im->fibs[frm->fib_index].ft_table_id;
8124   rmp->vrf_id = htonl (vrf_id);
8125   rmp->path_mtu = htonl (frm->path_mtu);
8126   rmp->template_interval = htonl (frm->template_interval);
8127   rmp->udp_checksum = (frm->udp_checksum != 0);
8128
8129   vl_msg_api_send_shmem (q, (u8 *) & rmp);
8130 }
8131
8132 static void
8133   vl_api_set_ipfix_classify_stream_t_handler
8134   (vl_api_set_ipfix_classify_stream_t * mp)
8135 {
8136   vl_api_set_ipfix_classify_stream_reply_t *rmp;
8137   flow_report_classify_main_t *fcm = &flow_report_classify_main;
8138   flow_report_main_t *frm = &flow_report_main;
8139   u32 domain_id = 0;
8140   u32 src_port = UDP_DST_PORT_ipfix;
8141   int rv = 0;
8142
8143   domain_id = ntohl (mp->domain_id);
8144   src_port = ntohs (mp->src_port);
8145
8146   if (fcm->src_port != 0 &&
8147       (fcm->domain_id != domain_id || fcm->src_port != (u16) src_port))
8148     {
8149       int rv = vnet_stream_change (frm, fcm->domain_id, fcm->src_port,
8150                                    domain_id, (u16) src_port);
8151       ASSERT (rv == 0);
8152     }
8153
8154   fcm->domain_id = domain_id;
8155   fcm->src_port = (u16) src_port;
8156
8157   REPLY_MACRO (VL_API_SET_IPFIX_CLASSIFY_STREAM_REPLY);
8158 }
8159
8160 static void
8161   vl_api_ipfix_classify_stream_dump_t_handler
8162   (vl_api_ipfix_classify_stream_dump_t * mp)
8163 {
8164   flow_report_classify_main_t *fcm = &flow_report_classify_main;
8165   unix_shared_memory_queue_t *q;
8166   vl_api_ipfix_classify_stream_details_t *rmp;
8167
8168   q = vl_api_client_index_to_input_queue (mp->client_index);
8169   if (!q)
8170     return;
8171
8172   rmp = vl_msg_api_alloc (sizeof (*rmp));
8173   memset (rmp, 0, sizeof (*rmp));
8174   rmp->_vl_msg_id = ntohs (VL_API_IPFIX_CLASSIFY_STREAM_DETAILS);
8175   rmp->context = mp->context;
8176   rmp->domain_id = htonl (fcm->domain_id);
8177   rmp->src_port = htons (fcm->src_port);
8178
8179   vl_msg_api_send_shmem (q, (u8 *) & rmp);
8180 }
8181
8182 static void
8183   vl_api_ipfix_classify_table_add_del_t_handler
8184   (vl_api_ipfix_classify_table_add_del_t * mp)
8185 {
8186   vl_api_ipfix_classify_table_add_del_reply_t *rmp;
8187   flow_report_classify_main_t *fcm = &flow_report_classify_main;
8188   flow_report_main_t *frm = &flow_report_main;
8189   vnet_flow_report_add_del_args_t args;
8190   ipfix_classify_table_t *table;
8191   int is_add;
8192   u32 classify_table_index;
8193   u8 ip_version;
8194   u8 transport_protocol;
8195   int rv = 0;
8196
8197   classify_table_index = ntohl (mp->table_id);
8198   ip_version = mp->ip_version;
8199   transport_protocol = mp->transport_protocol;
8200   is_add = mp->is_add;
8201
8202   if (fcm->src_port == 0)
8203     {
8204       /* call set_ipfix_classify_stream first */
8205       rv = VNET_API_ERROR_UNSPECIFIED;
8206       goto out;
8207     }
8208
8209   memset (&args, 0, sizeof (args));
8210
8211   table = 0;
8212   int i;
8213   for (i = 0; i < vec_len (fcm->tables); i++)
8214     if (ipfix_classify_table_index_valid (i))
8215       if (fcm->tables[i].classify_table_index == classify_table_index)
8216         {
8217           table = &fcm->tables[i];
8218           break;
8219         }
8220
8221   if (is_add)
8222     {
8223       if (table)
8224         {
8225           rv = VNET_API_ERROR_VALUE_EXIST;
8226           goto out;
8227         }
8228       table = ipfix_classify_add_table ();
8229       table->classify_table_index = classify_table_index;
8230     }
8231   else
8232     {
8233       if (!table)
8234         {
8235           rv = VNET_API_ERROR_NO_SUCH_ENTRY;
8236           goto out;
8237         }
8238     }
8239
8240   table->ip_version = ip_version;
8241   table->transport_protocol = transport_protocol;
8242
8243   args.opaque.as_uword = table - fcm->tables;
8244   args.rewrite_callback = ipfix_classify_template_rewrite;
8245   args.flow_data_callback = ipfix_classify_send_flows;
8246   args.is_add = is_add;
8247   args.domain_id = fcm->domain_id;
8248   args.src_port = fcm->src_port;
8249
8250   rv = vnet_flow_report_add_del (frm, &args);
8251
8252   /* If deleting, or add failed */
8253   if (is_add == 0 || (rv && is_add))
8254     ipfix_classify_delete_table (table - fcm->tables);
8255
8256 out:
8257   REPLY_MACRO (VL_API_SET_IPFIX_CLASSIFY_STREAM_REPLY);
8258 }
8259
8260 static void
8261 send_ipfix_classify_table_details (u32 table_index,
8262                                    unix_shared_memory_queue_t * q,
8263                                    u32 context)
8264 {
8265   flow_report_classify_main_t *fcm = &flow_report_classify_main;
8266   vl_api_ipfix_classify_table_details_t *mp;
8267
8268   ipfix_classify_table_t *table = &fcm->tables[table_index];
8269
8270   mp = vl_msg_api_alloc (sizeof (*mp));
8271   memset (mp, 0, sizeof (*mp));
8272   mp->_vl_msg_id = ntohs (VL_API_IPFIX_CLASSIFY_TABLE_DETAILS);
8273   mp->context = context;
8274   mp->table_id = htonl (table->classify_table_index);
8275   mp->ip_version = table->ip_version;
8276   mp->transport_protocol = table->transport_protocol;
8277
8278   vl_msg_api_send_shmem (q, (u8 *) & mp);
8279 }
8280
8281 static void
8282   vl_api_ipfix_classify_table_dump_t_handler
8283   (vl_api_ipfix_classify_table_dump_t * mp)
8284 {
8285   flow_report_classify_main_t *fcm = &flow_report_classify_main;
8286   unix_shared_memory_queue_t *q;
8287   u32 i;
8288
8289   q = vl_api_client_index_to_input_queue (mp->client_index);
8290   if (!q)
8291     return;
8292
8293   for (i = 0; i < vec_len (fcm->tables); i++)
8294     if (ipfix_classify_table_index_valid (i))
8295       send_ipfix_classify_table_details (i, q, mp->context);
8296 }
8297
8298 static void
8299 vl_api_pg_create_interface_t_handler (vl_api_pg_create_interface_t * mp)
8300 {
8301   vl_api_pg_create_interface_reply_t *rmp;
8302   int rv = 0;
8303
8304   pg_main_t *pg = &pg_main;
8305   u32 pg_if_id = pg_interface_add_or_get (pg, ntohl (mp->interface_id));
8306   pg_interface_t *pi = pool_elt_at_index (pg->interfaces, pg_if_id);
8307
8308   /* *INDENT-OFF* */
8309   REPLY_MACRO2(VL_API_PG_CREATE_INTERFACE_REPLY,
8310   ({
8311     rmp->sw_if_index = ntohl(pi->sw_if_index);
8312   }));
8313   /* *INDENT-ON* */
8314 }
8315
8316 static void
8317 vl_api_pg_capture_t_handler (vl_api_pg_capture_t * mp)
8318 {
8319   vl_api_pg_capture_reply_t *rmp;
8320   int rv = 0;
8321
8322   vnet_main_t *vnm = vnet_get_main ();
8323   vnet_interface_main_t *im = &vnm->interface_main;
8324   vnet_hw_interface_t *hi = 0;
8325
8326   u8 *intf_name = format (0, "pg%d", ntohl (mp->interface_id), 0);
8327   u32 hw_if_index = ~0;
8328   uword *p = hash_get_mem (im->hw_interface_by_name, intf_name);
8329   if (p)
8330     hw_if_index = *p;
8331   vec_free (intf_name);
8332
8333   if (hw_if_index != ~0)
8334     {
8335       pg_capture_args_t _a, *a = &_a;
8336
8337       u32 len = ntohl (mp->pcap_name_length);
8338       u8 *pcap_file_name = vec_new (u8, len);
8339       clib_memcpy (pcap_file_name, mp->pcap_file_name, len);
8340
8341       hi = vnet_get_sup_hw_interface (vnm, hw_if_index);
8342       a->hw_if_index = hw_if_index;
8343       a->dev_instance = hi->dev_instance;
8344       a->is_enabled = mp->is_enabled;
8345       a->pcap_file_name = pcap_file_name;
8346       a->count = ntohl (mp->count);
8347
8348       clib_error_t *e = pg_capture (a);
8349       if (e)
8350         {
8351           clib_error_report (e);
8352           rv = VNET_API_ERROR_CANNOT_CREATE_PCAP_FILE;
8353         }
8354
8355       vec_free (pcap_file_name);
8356     }
8357   REPLY_MACRO (VL_API_PG_CAPTURE_REPLY);
8358 }
8359
8360 static void
8361 vl_api_pg_enable_disable_t_handler (vl_api_pg_enable_disable_t * mp)
8362 {
8363   vl_api_pg_enable_disable_reply_t *rmp;
8364   int rv = 0;
8365
8366   pg_main_t *pg = &pg_main;
8367   u32 stream_index = ~0;
8368
8369   int is_enable = mp->is_enabled != 0;
8370   u32 len = ntohl (mp->stream_name_length) - 1;
8371
8372   if (len > 0)
8373     {
8374       u8 *stream_name = vec_new (u8, len);
8375       clib_memcpy (stream_name, mp->stream_name, len);
8376       uword *p = hash_get_mem (pg->stream_index_by_name, stream_name);
8377       if (p)
8378         stream_index = *p;
8379       vec_free (stream_name);
8380     }
8381
8382   pg_enable_disable (stream_index, is_enable);
8383
8384   REPLY_MACRO (VL_API_PG_ENABLE_DISABLE_REPLY);
8385 }
8386
8387 static void
8388   vl_api_ip_source_and_port_range_check_add_del_t_handler
8389   (vl_api_ip_source_and_port_range_check_add_del_t * mp)
8390 {
8391   vl_api_ip_source_and_port_range_check_add_del_reply_t *rmp;
8392   int rv = 0;
8393
8394   u8 is_ipv6 = mp->is_ipv6;
8395   u8 is_add = mp->is_add;
8396   u8 mask_length = mp->mask_length;
8397   ip4_address_t ip4_addr;
8398   ip6_address_t ip6_addr;
8399   u16 *low_ports = 0;
8400   u16 *high_ports = 0;
8401   u32 vrf_id;
8402   u16 tmp_low, tmp_high;
8403   u8 num_ranges;
8404   int i;
8405
8406   // Validate port range
8407   num_ranges = mp->number_of_ranges;
8408   if (num_ranges > 32)
8409     {                           // This is size of array in VPE.API
8410       rv = VNET_API_ERROR_EXCEEDED_NUMBER_OF_RANGES_CAPACITY;
8411       goto reply;
8412     }
8413
8414   vec_reset_length (low_ports);
8415   vec_reset_length (high_ports);
8416
8417   for (i = 0; i < num_ranges; i++)
8418     {
8419       tmp_low = mp->low_ports[i];
8420       tmp_high = mp->high_ports[i];
8421       // If tmp_low <= tmp_high then only need to check tmp_low = 0
8422       // If tmp_low <= tmp_high then only need to check tmp_high > 65535
8423       if (tmp_low > tmp_high || tmp_low == 0 || tmp_high > 65535)
8424         {
8425           rv = VNET_API_ERROR_INVALID_VALUE;
8426           goto reply;
8427         }
8428       vec_add1 (low_ports, tmp_low);
8429       vec_add1 (high_ports, tmp_high + 1);
8430     }
8431
8432   // Validate mask_length
8433   if ((is_ipv6 && mask_length > 128) || (!is_ipv6 && mask_length > 32))
8434     {
8435       rv = VNET_API_ERROR_ADDRESS_LENGTH_MISMATCH;
8436       goto reply;
8437     }
8438
8439   vrf_id = ntohl (mp->vrf_id);
8440
8441   if (vrf_id < 1)
8442     {
8443       rv = VNET_API_ERROR_INVALID_VALUE;
8444       goto reply;
8445     }
8446
8447
8448   if (is_ipv6)
8449     {
8450       clib_memcpy (ip6_addr.as_u8, mp->address, sizeof (ip6_addr.as_u8));
8451       rv = ip6_source_and_port_range_check_add_del (&ip6_addr,
8452                                                     mask_length,
8453                                                     vrf_id,
8454                                                     low_ports,
8455                                                     high_ports, is_add);
8456     }
8457   else
8458     {
8459       clib_memcpy (ip4_addr.data, mp->address, sizeof (ip4_addr));
8460       rv = ip4_source_and_port_range_check_add_del (&ip4_addr,
8461                                                     mask_length,
8462                                                     vrf_id,
8463                                                     low_ports,
8464                                                     high_ports, is_add);
8465     }
8466
8467 reply:
8468   vec_free (low_ports);
8469   vec_free (high_ports);
8470   REPLY_MACRO (VL_API_IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL_REPLY);
8471 }
8472
8473 static void
8474   vl_api_ip_source_and_port_range_check_interface_add_del_t_handler
8475   (vl_api_ip_source_and_port_range_check_interface_add_del_t * mp)
8476 {
8477   vlib_main_t *vm = vlib_get_main ();
8478   vl_api_ip_source_and_port_range_check_interface_add_del_reply_t *rmp;
8479   ip4_main_t *im = &ip4_main;
8480   int rv;
8481   u32 sw_if_index;
8482   u32 fib_index[IP_SOURCE_AND_PORT_RANGE_CHECK_N_PROTOCOLS];
8483   u32 vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_N_PROTOCOLS];
8484   uword *p = 0;
8485   int i;
8486
8487   vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_TCP_OUT] =
8488     ntohl (mp->tcp_out_vrf_id);
8489   vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_UDP_OUT] =
8490     ntohl (mp->udp_out_vrf_id);
8491   vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_TCP_IN] =
8492     ntohl (mp->tcp_in_vrf_id);
8493   vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_UDP_IN] =
8494     ntohl (mp->udp_in_vrf_id);
8495
8496
8497   for (i = 0; i < IP_SOURCE_AND_PORT_RANGE_CHECK_N_PROTOCOLS; i++)
8498     {
8499       if (vrf_id[i] != 0 && vrf_id[i] != ~0)
8500         {
8501           p = hash_get (im->fib_index_by_table_id, vrf_id[i]);
8502
8503           if (p == 0)
8504             {
8505               rv = VNET_API_ERROR_INVALID_VALUE;
8506               goto reply;
8507             }
8508
8509           fib_index[i] = p[0];
8510         }
8511       else
8512         fib_index[i] = ~0;
8513     }
8514   sw_if_index = ntohl (mp->sw_if_index);
8515
8516   VALIDATE_SW_IF_INDEX (mp);
8517
8518   rv =
8519     set_ip_source_and_port_range_check (vm, fib_index, sw_if_index,
8520                                         mp->is_add);
8521
8522   BAD_SW_IF_INDEX_LABEL;
8523 reply:
8524
8525   REPLY_MACRO (VL_API_IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL_REPLY);
8526 }
8527
8528 static void
8529 vl_api_ipsec_gre_add_del_tunnel_t_handler (vl_api_ipsec_gre_add_del_tunnel_t *
8530                                            mp)
8531 {
8532   vl_api_ipsec_gre_add_del_tunnel_reply_t *rmp;
8533   int rv = 0;
8534   vnet_ipsec_gre_add_del_tunnel_args_t _a, *a = &_a;
8535   u32 sw_if_index = ~0;
8536
8537   /* Check src & dst are different */
8538   if (memcmp (mp->src_address, mp->dst_address, 4) == 0)
8539     {
8540       rv = VNET_API_ERROR_SAME_SRC_DST;
8541       goto out;
8542     }
8543
8544   memset (a, 0, sizeof (*a));
8545
8546   /* ip addresses sent in network byte order */
8547   clib_memcpy (&(a->src), mp->src_address, 4);
8548   clib_memcpy (&(a->dst), mp->dst_address, 4);
8549   a->is_add = mp->is_add;
8550   a->lsa = ntohl (mp->local_sa_id);
8551   a->rsa = ntohl (mp->remote_sa_id);
8552
8553   rv = vnet_ipsec_gre_add_del_tunnel (a, &sw_if_index);
8554
8555 out:
8556     /* *INDENT-OFF* */
8557     REPLY_MACRO2(VL_API_GRE_ADD_DEL_TUNNEL_REPLY,
8558     ({
8559         rmp->sw_if_index = ntohl (sw_if_index);
8560     }));
8561     /* *INDENT-ON* */
8562 }
8563
8564 static void send_ipsec_gre_tunnel_details
8565   (ipsec_gre_tunnel_t * t, unix_shared_memory_queue_t * q, u32 context)
8566 {
8567   vl_api_ipsec_gre_tunnel_details_t *rmp;
8568
8569   rmp = vl_msg_api_alloc (sizeof (*rmp));
8570   memset (rmp, 0, sizeof (*rmp));
8571   rmp->_vl_msg_id = ntohs (VL_API_IPSEC_GRE_TUNNEL_DETAILS);
8572   clib_memcpy (rmp->src_address, &(t->tunnel_src), 4);
8573   clib_memcpy (rmp->dst_address, &(t->tunnel_dst), 4);
8574   rmp->sw_if_index = htonl (t->sw_if_index);
8575   rmp->local_sa_id = htonl (t->local_sa_id);
8576   rmp->remote_sa_id = htonl (t->remote_sa_id);
8577   rmp->context = context;
8578
8579   vl_msg_api_send_shmem (q, (u8 *) & rmp);
8580 }
8581
8582 static void vl_api_ipsec_gre_tunnel_dump_t_handler
8583   (vl_api_ipsec_gre_tunnel_dump_t * mp)
8584 {
8585   unix_shared_memory_queue_t *q;
8586   ipsec_gre_main_t *igm = &ipsec_gre_main;
8587   ipsec_gre_tunnel_t *t;
8588   u32 sw_if_index;
8589
8590   q = vl_api_client_index_to_input_queue (mp->client_index);
8591   if (q == 0)
8592     {
8593       return;
8594     }
8595
8596   sw_if_index = ntohl (mp->sw_if_index);
8597
8598   if (~0 == sw_if_index)
8599     {
8600         /* *INDENT-OFF* */
8601         pool_foreach (t, igm->tunnels,
8602         ({
8603             send_ipsec_gre_tunnel_details(t, q, mp->context);
8604         }));
8605         /* *INDENT-ON* */
8606     }
8607   else
8608     {
8609       if ((sw_if_index >= vec_len (igm->tunnel_index_by_sw_if_index)) ||
8610           (~0 == igm->tunnel_index_by_sw_if_index[sw_if_index]))
8611         {
8612           return;
8613         }
8614       t = &igm->tunnels[igm->tunnel_index_by_sw_if_index[sw_if_index]];
8615       send_ipsec_gre_tunnel_details (t, q, mp->context);
8616     }
8617 }
8618
8619 static void
8620 vl_api_delete_subif_t_handler (vl_api_delete_subif_t * mp)
8621 {
8622   vl_api_delete_subif_reply_t *rmp;
8623   int rv;
8624
8625   rv = vnet_delete_sub_interface (ntohl (mp->sw_if_index));
8626
8627   REPLY_MACRO (VL_API_DELETE_SUBIF_REPLY);
8628 }
8629
8630 static void
8631   vl_api_l2_interface_pbb_tag_rewrite_t_handler
8632   (vl_api_l2_interface_pbb_tag_rewrite_t * mp)
8633 {
8634   vl_api_l2_interface_pbb_tag_rewrite_reply_t *rmp;
8635   vnet_main_t *vnm = vnet_get_main ();
8636   vlib_main_t *vm = vlib_get_main ();
8637   u32 vtr_op;
8638   int rv = 0;
8639
8640   VALIDATE_SW_IF_INDEX (mp);
8641
8642   vtr_op = ntohl (mp->vtr_op);
8643
8644   switch (vtr_op)
8645     {
8646     case L2_VTR_DISABLED:
8647     case L2_VTR_PUSH_2:
8648     case L2_VTR_POP_2:
8649     case L2_VTR_TRANSLATE_2_1:
8650       break;
8651
8652     default:
8653       rv = VNET_API_ERROR_INVALID_VALUE;
8654       goto bad_sw_if_index;
8655     }
8656
8657   rv = l2pbb_configure (vm, vnm, ntohl (mp->sw_if_index), vtr_op,
8658                         mp->b_dmac, mp->b_smac, ntohs (mp->b_vlanid),
8659                         ntohl (mp->i_sid), ntohs (mp->outer_tag));
8660
8661   BAD_SW_IF_INDEX_LABEL;
8662
8663   REPLY_MACRO (VL_API_L2_INTERFACE_PBB_TAG_REWRITE_REPLY);
8664 }
8665
8666 static void
8667 vl_api_punt_t_handler (vl_api_punt_t * mp)
8668 {
8669   vl_api_punt_reply_t *rmp;
8670   vlib_main_t *vm = vlib_get_main ();
8671   int rv = 0;
8672   clib_error_t *error;
8673
8674   error = vnet_punt_add_del (vm, mp->ipv, mp->l4_protocol,
8675                              ntohs (mp->l4_port), mp->is_add);
8676   if (error)
8677     {
8678       rv = -1;
8679       clib_error_report (error);
8680     }
8681
8682   REPLY_MACRO (VL_API_PUNT_REPLY);
8683 }
8684
8685 static void
8686   vl_api_flow_classify_set_interface_t_handler
8687   (vl_api_flow_classify_set_interface_t * mp)
8688 {
8689   vlib_main_t *vm = vlib_get_main ();
8690   vl_api_flow_classify_set_interface_reply_t *rmp;
8691   int rv;
8692   u32 sw_if_index, ip4_table_index, ip6_table_index;
8693
8694   ip4_table_index = ntohl (mp->ip4_table_index);
8695   ip6_table_index = ntohl (mp->ip6_table_index);
8696   sw_if_index = ntohl (mp->sw_if_index);
8697
8698   VALIDATE_SW_IF_INDEX (mp);
8699
8700   rv = vnet_set_flow_classify_intfc (vm, sw_if_index, ip4_table_index,
8701                                      ip6_table_index, mp->is_add);
8702
8703   BAD_SW_IF_INDEX_LABEL;
8704
8705   REPLY_MACRO (VL_API_FLOW_CLASSIFY_SET_INTERFACE_REPLY);
8706 }
8707
8708 static void
8709 send_flow_classify_details (u32 sw_if_index,
8710                             u32 table_index,
8711                             unix_shared_memory_queue_t * q, u32 context)
8712 {
8713   vl_api_flow_classify_details_t *mp;
8714
8715   mp = vl_msg_api_alloc (sizeof (*mp));
8716   memset (mp, 0, sizeof (*mp));
8717   mp->_vl_msg_id = ntohs (VL_API_FLOW_CLASSIFY_DETAILS);
8718   mp->context = context;
8719   mp->sw_if_index = htonl (sw_if_index);
8720   mp->table_index = htonl (table_index);
8721
8722   vl_msg_api_send_shmem (q, (u8 *) & mp);
8723 }
8724
8725 static void
8726 vl_api_flow_classify_dump_t_handler (vl_api_flow_classify_dump_t * mp)
8727 {
8728   unix_shared_memory_queue_t *q;
8729   flow_classify_main_t *pcm = &flow_classify_main;
8730   u32 *vec_tbl;
8731   int i;
8732
8733   q = vl_api_client_index_to_input_queue (mp->client_index);
8734   if (q == 0)
8735     return;
8736
8737   vec_tbl = pcm->classify_table_index_by_sw_if_index[mp->type];
8738
8739   if (vec_len (vec_tbl))
8740     {
8741       for (i = 0; i < vec_len (vec_tbl); i++)
8742         {
8743           if (vec_elt (vec_tbl, i) == ~0)
8744             continue;
8745
8746           send_flow_classify_details (i, vec_elt (vec_tbl, i), q,
8747                                       mp->context);
8748         }
8749     }
8750 }
8751
8752 static void
8753 send_ipsec_spd_details (ipsec_policy_t * p, unix_shared_memory_queue_t * q,
8754                         u32 context)
8755 {
8756   vl_api_ipsec_spd_details_t *mp;
8757
8758   mp = vl_msg_api_alloc (sizeof (*mp));
8759   memset (mp, 0, sizeof (*mp));
8760   mp->_vl_msg_id = ntohs (VL_API_IPSEC_SPD_DETAILS);
8761   mp->context = context;
8762
8763   mp->spd_id = htonl (p->id);
8764   mp->priority = htonl (p->priority);
8765   mp->is_outbound = p->is_outbound;
8766   mp->is_ipv6 = p->is_ipv6;
8767   if (p->is_ipv6)
8768     {
8769       memcpy (mp->local_start_addr, &p->laddr.start.ip6, 16);
8770       memcpy (mp->local_stop_addr, &p->laddr.stop.ip6, 16);
8771       memcpy (mp->remote_start_addr, &p->raddr.start.ip6, 16);
8772       memcpy (mp->remote_stop_addr, &p->raddr.stop.ip6, 16);
8773     }
8774   else
8775     {
8776       memcpy (mp->local_start_addr, &p->laddr.start.ip4, 4);
8777       memcpy (mp->local_stop_addr, &p->laddr.stop.ip4, 4);
8778       memcpy (mp->remote_start_addr, &p->raddr.start.ip4, 4);
8779       memcpy (mp->remote_stop_addr, &p->raddr.stop.ip4, 4);
8780     }
8781   mp->local_start_port = htons (p->lport.start);
8782   mp->local_stop_port = htons (p->lport.stop);
8783   mp->remote_start_port = htons (p->rport.start);
8784   mp->remote_stop_port = htons (p->rport.stop);
8785   mp->protocol = p->protocol;
8786   mp->policy = p->policy;
8787   mp->sa_id = htonl (p->sa_id);
8788   mp->bytes = clib_host_to_net_u64 (p->counter.bytes);
8789   mp->packets = clib_host_to_net_u64 (p->counter.packets);
8790
8791   vl_msg_api_send_shmem (q, (u8 *) & mp);
8792 }
8793
8794 static void
8795 vl_api_ipsec_spd_dump_t_handler (vl_api_ipsec_spd_dump_t * mp)
8796 {
8797   unix_shared_memory_queue_t *q;
8798   ipsec_main_t *im = &ipsec_main;
8799   ipsec_policy_t *policy;
8800   ipsec_spd_t *spd;
8801   uword *p;
8802   u32 spd_index;
8803 #if IPSEC > 0
8804   q = vl_api_client_index_to_input_queue (mp->client_index);
8805   if (q == 0)
8806     return;
8807
8808   p = hash_get (im->spd_index_by_spd_id, ntohl (mp->spd_id));
8809   if (!p)
8810     return;
8811
8812   spd_index = p[0];
8813   spd = pool_elt_at_index (im->spds, spd_index);
8814
8815   pool_foreach (policy, spd->policies, (
8816                                          {
8817                                          if (mp->sa_id == ~(0)
8818                                              || ntohl (mp->sa_id) ==
8819                                              policy->sa_id)
8820                                          send_ipsec_spd_details (policy, q,
8821                                                                  mp->context);}
8822                 ));
8823 #else
8824   clib_warning ("unimplemented");
8825 #endif
8826 }
8827
8828 #define BOUNCE_HANDLER(nn)                                              \
8829 static void vl_api_##nn##_t_handler (                                   \
8830     vl_api_##nn##_t *mp)                                                \
8831 {                                                                       \
8832     vpe_client_registration_t *reg;                                     \
8833     vpe_api_main_t * vam = &vpe_api_main;                               \
8834     unix_shared_memory_queue_t * q;                                     \
8835                                                                         \
8836     /* One registration only... */                                      \
8837     pool_foreach(reg, vam->nn##_registrations,                          \
8838     ({                                                                  \
8839         q = vl_api_client_index_to_input_queue (reg->client_index);     \
8840         if (q) {                                                        \
8841             /*                                                          \
8842              * If the queue is stuffed, turf the msg and complain       \
8843              * It's unlikely that the intended recipient is             \
8844              * alive; avoid deadlock at all costs.                      \
8845              */                                                         \
8846             if (q->cursize == q->maxsize) {                             \
8847                 clib_warning ("ERROR: receiver queue full, drop msg");  \
8848                 vl_msg_api_free (mp);                                   \
8849                 return;                                                 \
8850             }                                                           \
8851             vl_msg_api_send_shmem (q, (u8 *)&mp);                       \
8852             return;                                                     \
8853         }                                                               \
8854     }));                                                                \
8855     vl_msg_api_free (mp);                                               \
8856 }
8857
8858 /*
8859  * vpe_api_hookup
8860  * Add vpe's API message handlers to the table.
8861  * vlib has alread mapped shared memory and
8862  * added the client registration handlers.
8863  * See .../open-repo/vlib/memclnt_vlib.c:memclnt_process()
8864  */
8865
8866 static clib_error_t *
8867 vpe_api_hookup (vlib_main_t * vm)
8868 {
8869   api_main_t *am = &api_main;
8870
8871 #define _(N,n)                                                  \
8872     vl_msg_api_set_handlers(VL_API_##N, #n,                     \
8873                            vl_api_##n##_t_handler,              \
8874                            vl_noop_handler,                     \
8875                            vl_api_##n##_t_endian,               \
8876                            vl_api_##n##_t_print,                \
8877                            sizeof(vl_api_##n##_t), 1);
8878   foreach_vpe_api_msg;
8879 #undef _
8880
8881   /*
8882    * Manually register the sr tunnel add del msg, so we trace
8883    * enough bytes to capture a typical segment list
8884    */
8885   vl_msg_api_set_handlers (VL_API_SR_TUNNEL_ADD_DEL,
8886                            "sr_tunnel_add_del",
8887                            vl_api_sr_tunnel_add_del_t_handler,
8888                            vl_noop_handler,
8889                            vl_api_sr_tunnel_add_del_t_endian,
8890                            vl_api_sr_tunnel_add_del_t_print, 256, 1);
8891
8892
8893   /*
8894    * Manually register the sr policy add del msg, so we trace
8895    * enough bytes to capture a typical tunnel name list
8896    */
8897   vl_msg_api_set_handlers (VL_API_SR_POLICY_ADD_DEL,
8898                            "sr_policy_add_del",
8899                            vl_api_sr_policy_add_del_t_handler,
8900                            vl_noop_handler,
8901                            vl_api_sr_policy_add_del_t_endian,
8902                            vl_api_sr_policy_add_del_t_print, 256, 1);
8903
8904   /*
8905    * Trace space for 8 MPLS encap labels, classifier mask+match
8906    */
8907   am->api_trace_cfg[VL_API_MPLS_ADD_DEL_ENCAP].size += 8 * sizeof (u32);
8908   am->api_trace_cfg[VL_API_CLASSIFY_ADD_DEL_TABLE].size += 5 * sizeof (u32x4);
8909   am->api_trace_cfg[VL_API_CLASSIFY_ADD_DEL_SESSION].size
8910     += 5 * sizeof (u32x4);
8911   am->api_trace_cfg[VL_API_VXLAN_ADD_DEL_TUNNEL].size += 16 * sizeof (u32);
8912
8913   /*
8914    * Thread-safe API messages
8915    */
8916   am->is_mp_safe[VL_API_IP_ADD_DEL_ROUTE] = 1;
8917   am->is_mp_safe[VL_API_GET_NODE_GRAPH] = 1;
8918
8919   return 0;
8920 }
8921
8922 VLIB_API_INIT_FUNCTION (vpe_api_hookup);
8923
8924 static clib_error_t *
8925 vpe_api_init (vlib_main_t * vm)
8926 {
8927   vpe_api_main_t *am = &vpe_api_main;
8928
8929   am->vlib_main = vm;
8930   am->vnet_main = vnet_get_main ();
8931   am->interface_events_registration_hash = hash_create (0, sizeof (uword));
8932   am->to_netconf_server_registration_hash = hash_create (0, sizeof (uword));
8933   am->from_netconf_server_registration_hash = hash_create (0, sizeof (uword));
8934   am->to_netconf_client_registration_hash = hash_create (0, sizeof (uword));
8935   am->from_netconf_client_registration_hash = hash_create (0, sizeof (uword));
8936   am->oam_events_registration_hash = hash_create (0, sizeof (uword));
8937
8938   vl_api_init (vm);
8939   vl_set_memory_region_name ("/vpe-api");
8940   vl_enable_disable_memory_api (vm, 1 /* enable it */ );
8941
8942   return 0;
8943 }
8944
8945 VLIB_INIT_FUNCTION (vpe_api_init);
8946
8947
8948 static clib_error_t *
8949 api_segment_config (vlib_main_t * vm, unformat_input_t * input)
8950 {
8951   u8 *chroot_path;
8952   u64 baseva, size, pvt_heap_size;
8953   int uid, gid, rv;
8954   const int max_buf_size = 4096;
8955   char *s, *buf;
8956   struct passwd _pw, *pw;
8957   struct group _grp, *grp;
8958   clib_error_t *e;
8959   buf = vec_new (char, 128);
8960   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
8961     {
8962       if (unformat (input, "prefix %s", &chroot_path))
8963         {
8964           vec_add1 (chroot_path, 0);
8965           vl_set_memory_root_path ((char *) chroot_path);
8966         }
8967       else if (unformat (input, "uid %d", &uid))
8968         vl_set_memory_uid (uid);
8969       else if (unformat (input, "gid %d", &gid))
8970         vl_set_memory_gid (gid);
8971       else if (unformat (input, "baseva %llx", &baseva))
8972         vl_set_global_memory_baseva (baseva);
8973       else if (unformat (input, "global-size %lldM", &size))
8974         vl_set_global_memory_size (size * (1ULL << 20));
8975       else if (unformat (input, "global-size %lldG", &size))
8976         vl_set_global_memory_size (size * (1ULL << 30));
8977       else if (unformat (input, "global-size %lld", &size))
8978         vl_set_global_memory_size (size);
8979       else if (unformat (input, "global-pvt-heap-size %lldM", &pvt_heap_size))
8980         vl_set_global_pvt_heap_size (pvt_heap_size * (1ULL << 20));
8981       else if (unformat (input, "global-pvt-heap-size size %lld",
8982                          &pvt_heap_size))
8983         vl_set_global_pvt_heap_size (pvt_heap_size);
8984       else if (unformat (input, "api-pvt-heap-size %lldM", &pvt_heap_size))
8985         vl_set_api_pvt_heap_size (pvt_heap_size * (1ULL << 20));
8986       else if (unformat (input, "api-pvt-heap-size size %lld",
8987                          &pvt_heap_size))
8988         vl_set_api_pvt_heap_size (pvt_heap_size);
8989       else if (unformat (input, "api-size %lldM", &size))
8990         vl_set_api_memory_size (size * (1ULL << 20));
8991       else if (unformat (input, "api-size %lldG", &size))
8992         vl_set_api_memory_size (size * (1ULL << 30));
8993       else if (unformat (input, "api-size %lld", &size))
8994         vl_set_api_memory_size (size);
8995       else if (unformat (input, "uid %s", &s))
8996         {
8997           /* lookup the username */
8998           pw = NULL;
8999           while (((rv =
9000                    getpwnam_r (s, &_pw, buf, vec_len (buf), &pw)) == ERANGE)
9001                  && (vec_len (buf) <= max_buf_size))
9002             {
9003               vec_resize (buf, vec_len (buf) * 2);
9004             }
9005           if (rv < 0)
9006             {
9007               e = clib_error_return_code (0, rv,
9008                                           CLIB_ERROR_ERRNO_VALID |
9009                                           CLIB_ERROR_FATAL,
9010                                           "cannot fetch username %s", s);
9011               vec_free (s);
9012               vec_free (buf);
9013               return e;
9014             }
9015           if (pw == NULL)
9016             {
9017               e =
9018                 clib_error_return_fatal (0, "username %s does not exist", s);
9019               vec_free (s);
9020               vec_free (buf);
9021               return e;
9022             }
9023           vec_free (s);
9024           vl_set_memory_uid (pw->pw_uid);
9025         }
9026       else if (unformat (input, "gid %s", &s))
9027         {
9028           /* lookup the group name */
9029           grp = NULL;
9030           while (((rv =
9031                    getgrnam_r (s, &_grp, buf, vec_len (buf), &grp)) == ERANGE)
9032                  && (vec_len (buf) <= max_buf_size))
9033             {
9034               vec_resize (buf, vec_len (buf) * 2);
9035             }
9036           if (rv != 0)
9037             {
9038               e = clib_error_return_code (0, rv,
9039                                           CLIB_ERROR_ERRNO_VALID |
9040                                           CLIB_ERROR_FATAL,
9041                                           "cannot fetch group %s", s);
9042               vec_free (s);
9043               vec_free (buf);
9044               return e;
9045             }
9046           if (grp == NULL)
9047             {
9048               e = clib_error_return_fatal (0, "group %s does not exist", s);
9049               vec_free (s);
9050               vec_free (buf);
9051               return e;
9052             }
9053           vec_free (s);
9054           vec_free (buf);
9055           vl_set_memory_gid (grp->gr_gid);
9056         }
9057       else
9058         return clib_error_return (0, "unknown input `%U'",
9059                                   format_unformat_error, input);
9060     }
9061   return 0;
9062 }
9063
9064 VLIB_EARLY_CONFIG_FUNCTION (api_segment_config, "api-segment");
9065
9066 void *
9067 get_unformat_vnet_sw_interface (void)
9068 {
9069   return (void *) &unformat_vnet_sw_interface;
9070 }
9071
9072 #undef vl_api_version
9073 #define vl_api_version(n,v) static u32 vpe_api_version = v;
9074 #include <vpp-api/vpe.api.h>
9075 #undef vl_api_version
9076
9077 int
9078 vl_msg_api_version_check (vl_api_memclnt_create_t * mp)
9079 {
9080   if (clib_host_to_net_u32 (mp->api_versions[0]) != vpe_api_version)
9081     {
9082       clib_warning ("vpe API mismatch: 0x%08x instead of 0x%08x",
9083                     clib_host_to_net_u32 (mp->api_versions[0]),
9084                     vpe_api_version);
9085       return -1;
9086     }
9087   return 0;
9088 }
9089
9090 static u8 *
9091 format_arp_event (u8 * s, va_list * args)
9092 {
9093   vl_api_ip4_arp_event_t *event = va_arg (*args, vl_api_ip4_arp_event_t *);
9094
9095   s = format (s, "pid %d: ", event->pid);
9096   if (event->mac_ip)
9097     s = format (s, "bd mac/ip4 binding events");
9098   else
9099     s = format (s, "resolution for %U", format_ip4_address, &event->address);
9100   return s;
9101 }
9102
9103 static u8 *
9104 format_nd_event (u8 * s, va_list * args)
9105 {
9106   vl_api_ip6_nd_event_t *event = va_arg (*args, vl_api_ip6_nd_event_t *);
9107
9108   s = format (s, "pid %d: ", event->pid);
9109   if (event->mac_ip)
9110     s = format (s, "bd mac/ip6 binding events");
9111   else
9112     s = format (s, "resolution for %U", format_ip6_address, event->address);
9113   return s;
9114 }
9115
9116 static clib_error_t *
9117 show_ip_arp_nd_events_fn (vlib_main_t * vm,
9118                           unformat_input_t * input, vlib_cli_command_t * cmd)
9119 {
9120   vpe_api_main_t *am = &vpe_api_main;
9121   vl_api_ip4_arp_event_t *arp_event;
9122   vl_api_ip6_nd_event_t *nd_event;
9123
9124   if ((pool_elts (am->arp_events) == 0) && (pool_elts (am->nd_events) == 0))
9125     {
9126       vlib_cli_output (vm, "No active arp or nd event registrations");
9127       return 0;
9128     }
9129
9130   /* *INDENT-OFF* */
9131   pool_foreach (arp_event, am->arp_events,
9132   ({
9133     vlib_cli_output (vm, "%U", format_arp_event, arp_event);
9134   }));
9135
9136   pool_foreach (nd_event, am->nd_events,
9137   ({
9138     vlib_cli_output (vm, "%U", format_nd_event, nd_event);
9139   }));
9140   /* *INDENT-ON* */
9141
9142   return 0;
9143 }
9144
9145 /* *INDENT-OFF* */
9146 VLIB_CLI_COMMAND (show_ip_arp_nd_events, static) = {
9147   .path = "show arp-nd-event registrations",
9148   .function = show_ip_arp_nd_events_fn,
9149   .short_help = "Show ip4 arp and ip6 nd event registrations",
9150 };
9151 /* *INDENT-ON* */
9152
9153 /*
9154  * fd.io coding-style-patch-verification: ON
9155  *
9156  * Local Variables:
9157  * eval: (c-set-style "gnu")
9158  * End:
9159  */