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