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