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