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