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