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