LISP EID virtualization support
[vpp.git] / 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> // alagalah TODO : committers please pay note, is this ok?
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/unix/tuntap.h>
55 #include <vnet/unix/tapcli.h>
56 #include <vnet/mpls-gre/mpls.h>
57 #include <vnet/dhcp/proxy.h>
58 #include <vnet/dhcp/client.h>
59 #if IPV6SR > 0
60 #include <vnet/sr/sr.h>
61 #endif
62 #include <vnet/dhcpv6/proxy.h>
63 #include <vlib/vlib.h>
64 #include <vlib/unix/unix.h>
65 #include <vlibapi/api.h>
66 #include <vlibmemory/api.h>
67 #include <vnet/classify/vnet_classify.h>
68 #include <vnet/classify/input_acl.h>
69 #include <vnet/l2/l2_classify.h>
70 #include <vnet/vxlan/vxlan.h>
71 #include <vnet/gre/gre.h>
72 #include <vnet/l2/l2_vtr.h>
73 #include <vnet/vxlan-gpe/vxlan_gpe.h>
74 #include <vnet/lisp-gpe/lisp_gpe.h>
75 #include <vnet/lisp-cp/control.h>
76 #include <vnet/map/map.h>
77 #include <vnet/cop/cop.h>
78 #include <vnet/ip/ip6_hop_by_hop.h>
79 #include <vnet/devices/af_packet/af_packet.h>
80 #include <vnet/policer/policer.h>
81 #include <vnet/devices/netmap/netmap.h>
82
83 #undef BIHASH_TYPE
84 #undef __included_bihash_template_h__
85 #include <vnet/l2/l2_fib.h>
86
87 #if IPSEC > 0
88 #include <vnet/ipsec/ipsec.h>
89 #include <vnet/ipsec/ikev2.h>
90 #endif /* IPSEC */
91 #if DPDK > 0
92 #include <vnet/devices/virtio/vhost-user.h>
93 #endif
94
95 #include <stats/stats.h>
96 #include <oam/oam.h>
97
98 #include <vnet/ethernet/ethernet.h>
99 #include <vnet/ethernet/arp_packet.h>
100 #include <vnet/interface.h>
101
102 #include <vnet/l2/l2_fib.h>
103 #include <vnet/l2/l2_bd.h>
104 #include <api/vpe_msg_enum.h>
105
106 #define f64_endian(a)
107 #define f64_print(a,b)
108
109 #define vl_typedefs             /* define message structures */
110 #include <api/vpe_all_api_h.h>
111 #undef vl_typedefs
112
113 #define vl_endianfun             /* define message structures */
114 #include <api/vpe_all_api_h.h>
115 #undef vl_endianfun
116
117 /* instantiate all the print functions we know about */
118 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
119 #define vl_printfun
120 #include <api/vpe_all_api_h.h>
121 #undef vl_printfun
122
123 #define REPLY_MACRO(t)                                          \
124 do {                                                            \
125     unix_shared_memory_queue_t * q;                             \
126     rv = vl_msg_api_pd_handler (mp, rv);                        \
127     q = vl_api_client_index_to_input_queue (mp->client_index);  \
128     if (!q)                                                     \
129         return;                                                 \
130                                                                 \
131     rmp = vl_msg_api_alloc (sizeof (*rmp));                     \
132     rmp->_vl_msg_id = ntohs((t));                               \
133     rmp->context = mp->context;                                 \
134     rmp->retval = ntohl(rv);                                    \
135                                                                 \
136     vl_msg_api_send_shmem (q, (u8 *)&rmp);                      \
137 } while(0);
138
139 #define REPLY_MACRO2(t, body)                                   \
140 do {                                                            \
141     unix_shared_memory_queue_t * q;                             \
142     rv = vl_msg_api_pd_handler (mp, rv);                        \
143     q = vl_api_client_index_to_input_queue (mp->client_index);  \
144     if (!q)                                                     \
145         return;                                                 \
146                                                                 \
147     rmp = vl_msg_api_alloc (sizeof (*rmp));                     \
148     rmp->_vl_msg_id = ntohs((t));                               \
149     rmp->context = mp->context;                                 \
150     rmp->retval = ntohl(rv);                                    \
151     do {body;} while (0);                                       \
152     vl_msg_api_send_shmem (q, (u8 *)&rmp);                      \
153 } while(0);
154
155 #if (1 || CLIB_DEBUG > 0)       /* "trust, but verify" */
156
157 #define VALIDATE_SW_IF_INDEX(mp)                                \
158  do { u32 __sw_if_index = ntohl(mp->sw_if_index);               \
159     vnet_main_t *__vnm = vnet_get_main();                       \
160     if (pool_is_free_index(__vnm->interface_main.sw_interfaces, \
161                            __sw_if_index)) {                    \
162         rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;                \
163         goto bad_sw_if_index;                                   \
164     }                                                           \
165 } while(0);
166
167 #define BAD_SW_IF_INDEX_LABEL                   \
168 do {                                            \
169 bad_sw_if_index:                                \
170     ;                                           \
171 } while (0);
172
173 #define VALIDATE_RX_SW_IF_INDEX(mp)                             \
174  do { u32 __rx_sw_if_index = ntohl(mp->rx_sw_if_index);         \
175     vnet_main_t *__vnm = vnet_get_main();                       \
176     if (pool_is_free_index(__vnm->interface_main.sw_interfaces, \
177                            __rx_sw_if_index)) {                 \
178         rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;                \
179         goto bad_rx_sw_if_index;                                \
180     }                                                           \
181 } while(0);
182
183 #define BAD_RX_SW_IF_INDEX_LABEL                \
184 do {                                            \
185 bad_rx_sw_if_index:                             \
186     ;                                           \
187 } while (0);
188
189 #define VALIDATE_TX_SW_IF_INDEX(mp)                             \
190  do { u32 __tx_sw_if_index = ntohl(mp->tx_sw_if_index);         \
191     vnet_main_t *__vnm = vnet_get_main();                       \
192     if (pool_is_free_index(__vnm->interface_main.sw_interfaces, \
193                            __tx_sw_if_index)) {                 \
194         rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;                \
195         goto bad_tx_sw_if_index;                                \
196     }                                                           \
197 } while(0);
198
199 #define BAD_TX_SW_IF_INDEX_LABEL                \
200 do {                                            \
201 bad_tx_sw_if_index:                             \
202     ;                                           \
203 } while (0);
204
205 #else
206
207 #define VALIDATE_SW_IF_INDEX(mp)
208 #define BAD_SW_IF_INDEX_LABEL
209 #define VALIDATE_RX_SW_IF_INDEX(mp)
210 #define BAD_RX_SW_IF_INDEX_LABEL
211 #define VALIDATE_TX_SW_IF_INDEX(mp)
212 #define BAD_TX_SW_IF_INDEX_LABEL
213
214 #endif  /* CLIB_DEBUG > 0 */
215
216 #define foreach_vpe_api_msg                                             \
217 _(WANT_INTERFACE_EVENTS, want_interface_events)                         \
218 _(WANT_OAM_EVENTS, want_oam_events)                                     \
219 _(OAM_ADD_DEL, oam_add_del)                                             \
220 _(SW_INTERFACE_DUMP, sw_interface_dump)                                 \
221 _(SW_INTERFACE_DETAILS, sw_interface_details)                           \
222 _(SW_INTERFACE_SET_FLAGS, sw_interface_set_flags)                       \
223 _(IP_ADD_DEL_ROUTE, ip_add_del_route)                                   \
224 _(IS_ADDRESS_REACHABLE, is_address_reachable)                           \
225 _(SW_INTERFACE_ADD_DEL_ADDRESS, sw_interface_add_del_address)           \
226 _(SW_INTERFACE_SET_TABLE, sw_interface_set_table)                       \
227 _(SW_INTERFACE_SET_VPATH, sw_interface_set_vpath)                       \
228 _(SW_INTERFACE_SET_L2_XCONNECT, sw_interface_set_l2_xconnect)           \
229 _(SW_INTERFACE_SET_L2_BRIDGE, sw_interface_set_l2_bridge)               \
230 _(BRIDGE_DOMAIN_ADD_DEL, bridge_domain_add_del)                         \
231 _(BRIDGE_DOMAIN_DUMP, bridge_domain_dump)                               \
232 _(BRIDGE_DOMAIN_DETAILS, bridge_domain_details)                         \
233 _(BRIDGE_DOMAIN_SW_IF_DETAILS, bridge_domain_sw_if_details)             \
234 _(L2FIB_ADD_DEL, l2fib_add_del)                                         \
235 _(L2_FLAGS, l2_flags)                                                   \
236 _(BRIDGE_FLAGS, bridge_flags)                                           \
237 _(TAP_CONNECT, tap_connect)                                             \
238 _(TAP_MODIFY, tap_modify)                                               \
239 _(TAP_DELETE, tap_delete)                                               \
240 _(SW_INTERFACE_TAP_DUMP, sw_interface_tap_dump)                         \
241 _(CREATE_VLAN_SUBIF, create_vlan_subif)                                 \
242 _(CREATE_SUBIF, create_subif)                                           \
243 _(MPLS_GRE_ADD_DEL_TUNNEL, mpls_gre_add_del_tunnel)                     \
244 _(MPLS_ETHERNET_ADD_DEL_TUNNEL, mpls_ethernet_add_del_tunnel)           \
245 _(MPLS_ETHERNET_ADD_DEL_TUNNEL_2, mpls_ethernet_add_del_tunnel_2)       \
246 _(MPLS_ADD_DEL_ENCAP, mpls_add_del_encap)                               \
247 _(MPLS_ADD_DEL_DECAP, mpls_add_del_decap)                               \
248 _(PROXY_ARP_ADD_DEL, proxy_arp_add_del)                                 \
249 _(PROXY_ARP_INTFC_ENABLE_DISABLE, proxy_arp_intfc_enable_disable)       \
250 _(IP_NEIGHBOR_ADD_DEL, ip_neighbor_add_del)                             \
251 _(VNET_GET_SUMMARY_STATS, vnet_get_summary_stats)                       \
252 _(RESET_FIB, reset_fib)                                                 \
253 _(DHCP_PROXY_CONFIG,dhcp_proxy_config)                                  \
254 _(DHCP_PROXY_CONFIG_2,dhcp_proxy_config_2)                              \
255 _(DHCP_PROXY_SET_VSS,dhcp_proxy_set_vss)                                \
256 _(DHCP_CLIENT_CONFIG, dhcp_client_config)                               \
257 _(SET_IP_FLOW_HASH,set_ip_flow_hash)                                    \
258 _(SW_INTERFACE_IP6ND_RA_CONFIG, sw_interface_ip6nd_ra_config)           \
259 _(SW_INTERFACE_IP6ND_RA_PREFIX, sw_interface_ip6nd_ra_prefix)           \
260 _(SW_INTERFACE_IP6_ENABLE_DISABLE, sw_interface_ip6_enable_disable )    \
261 _(SW_INTERFACE_IP6_SET_LINK_LOCAL_ADDRESS,                              \
262   sw_interface_ip6_set_link_local_address)                              \
263 _(SW_INTERFACE_SET_UNNUMBERED, sw_interface_set_unnumbered)             \
264 _(CREATE_LOOPBACK, create_loopback)                                     \
265 _(CONTROL_PING, control_ping)                                           \
266 _(CLI_REQUEST, cli_request)                                             \
267 _(SET_ARP_NEIGHBOR_LIMIT, set_arp_neighbor_limit)                       \
268 _(L2_PATCH_ADD_DEL, l2_patch_add_del)                                   \
269 _(CLASSIFY_ADD_DEL_TABLE, classify_add_del_table)                       \
270 _(CLASSIFY_ADD_DEL_SESSION, classify_add_del_session)                   \
271 _(CLASSIFY_SET_INTERFACE_IP_TABLE, classify_set_interface_ip_table)     \
272 _(CLASSIFY_SET_INTERFACE_L2_TABLES, classify_set_interface_l2_tables)   \
273 _(GET_NODE_INDEX, get_node_index)                                       \
274 _(ADD_NODE_NEXT, add_node_next)                                         \
275 _(L2TPV3_CREATE_TUNNEL, l2tpv3_create_tunnel)                           \
276 _(L2TPV3_SET_TUNNEL_COOKIES, l2tpv3_set_tunnel_cookies)                 \
277 _(L2TPV3_INTERFACE_ENABLE_DISABLE, l2tpv3_interface_enable_disable)     \
278 _(L2TPV3_SET_LOOKUP_KEY, l2tpv3_set_lookup_key)                         \
279 _(SW_IF_L2TPV3_TUNNEL_DUMP, sw_if_l2tpv3_tunnel_dump)                   \
280 _(VXLAN_ADD_DEL_TUNNEL, vxlan_add_del_tunnel)                           \
281 _(VXLAN_TUNNEL_DUMP, vxlan_tunnel_dump)                                 \
282 _(GRE_ADD_DEL_TUNNEL, gre_add_del_tunnel)                               \
283 _(GRE_TUNNEL_DUMP, gre_tunnel_dump)                                     \
284 _(L2_FIB_CLEAR_TABLE, l2_fib_clear_table)                               \
285 _(L2_INTERFACE_EFP_FILTER, l2_interface_efp_filter)                     \
286 _(L2_INTERFACE_VLAN_TAG_REWRITE, l2_interface_vlan_tag_rewrite)         \
287 _(CREATE_VHOST_USER_IF, create_vhost_user_if)                           \
288 _(MODIFY_VHOST_USER_IF, modify_vhost_user_if)                           \
289 _(DELETE_VHOST_USER_IF, delete_vhost_user_if)                           \
290 _(SW_INTERFACE_VHOST_USER_DUMP, sw_interface_vhost_user_dump)           \
291 _(IP_ADDRESS_DUMP, ip_address_dump)                                     \
292 _(IP_DUMP, ip_dump)                                                     \
293 _(SW_INTERFACE_VHOST_USER_DETAILS, sw_interface_vhost_user_details)     \
294 _(SHOW_VERSION, show_version)                                           \
295 _(L2_FIB_TABLE_DUMP, l2_fib_table_dump)                                 \
296 _(L2_FIB_TABLE_ENTRY, l2_fib_table_entry)                               \
297 _(VXLAN_GPE_ADD_DEL_TUNNEL, vxlan_gpe_add_del_tunnel)                   \
298 _(VXLAN_GPE_TUNNEL_DUMP, vxlan_gpe_tunnel_dump)                         \
299 _(INTERFACE_NAME_RENUMBER, interface_name_renumber)                     \
300 _(WANT_IP4_ARP_EVENTS, want_ip4_arp_events)                             \
301 _(INPUT_ACL_SET_INTERFACE, input_acl_set_interface)                     \
302 _(IPSEC_SPD_ADD_DEL, ipsec_spd_add_del)                                 \
303 _(IPSEC_INTERFACE_ADD_DEL_SPD, ipsec_interface_add_del_spd)             \
304 _(IPSEC_SPD_ADD_DEL_ENTRY, ipsec_spd_add_del_entry)                     \
305 _(IPSEC_SAD_ADD_DEL_ENTRY, ipsec_sad_add_del_entry)                     \
306 _(IPSEC_SA_SET_KEY, ipsec_sa_set_key)                                   \
307 _(IKEV2_PROFILE_ADD_DEL, ikev2_profile_add_del)                         \
308 _(IKEV2_PROFILE_SET_AUTH, ikev2_profile_set_auth)                       \
309 _(IKEV2_PROFILE_SET_ID, ikev2_profile_set_id)                           \
310 _(IKEV2_PROFILE_SET_TS, ikev2_profile_set_ts)                           \
311 _(IKEV2_SET_LOCAL_KEY, ikev2_set_local_key)                             \
312 _(DELETE_LOOPBACK, delete_loopback)                                     \
313 _(BD_IP_MAC_ADD_DEL, bd_ip_mac_add_del)                                 \
314 _(MAP_ADD_DOMAIN, map_add_domain)                                       \
315 _(MAP_DEL_DOMAIN, map_del_domain)                                       \
316 _(MAP_ADD_DEL_RULE, map_add_del_rule)                                   \
317 _(MAP_DOMAIN_DUMP, map_domain_dump)                                     \
318 _(MAP_RULE_DUMP, map_rule_dump)                                         \
319 _(MAP_SUMMARY_STATS, map_summary_stats)                                 \
320 _(COP_INTERFACE_ENABLE_DISABLE, cop_interface_enable_disable)           \
321 _(COP_WHITELIST_ENABLE_DISABLE, cop_whitelist_enable_disable)           \
322 _(GET_NODE_GRAPH, get_node_graph)                                       \
323 _(SW_INTERFACE_CLEAR_STATS, sw_interface_clear_stats)                   \
324 _(TRACE_PROFILE_ADD, trace_profile_add)                                 \
325 _(TRACE_PROFILE_APPLY, trace_profile_apply)                             \
326 _(TRACE_PROFILE_DEL, trace_profile_del)                                 \
327 _(LISP_ADD_DEL_LOCATOR_SET, lisp_add_del_locator_set)                   \
328 _(LISP_ADD_DEL_LOCATOR, lisp_add_del_locator)                           \
329 _(LISP_ADD_DEL_LOCAL_EID, lisp_add_del_local_eid)                       \
330 _(LISP_GPE_ADD_DEL_FWD_ENTRY, lisp_gpe_add_del_fwd_entry)               \
331 _(LISP_ADD_DEL_MAP_RESOLVER, lisp_add_del_map_resolver)                 \
332 _(LISP_GPE_ENABLE_DISABLE, lisp_gpe_enable_disable)                     \
333 _(LISP_ENABLE_DISABLE, lisp_enable_disable)                             \
334 _(LISP_GPE_ADD_DEL_IFACE, lisp_gpe_add_del_iface)                       \
335 _(LISP_ADD_DEL_REMOTE_MAPPING, lisp_add_del_remote_mapping)             \
336 _(LISP_PITR_SET_LOCATOR_SET, lisp_pitr_set_locator_set)                 \
337 _(LISP_EID_TABLE_ADD_DEL_MAP, lisp_eid_table_add_del_map)               \
338 _(LISP_LOCATOR_SET_DUMP, lisp_locator_set_dump)                         \
339 _(LISP_LOCAL_EID_TABLE_DUMP, lisp_local_eid_table_dump)                 \
340 _(LISP_GPE_TUNNEL_DUMP, lisp_gpe_tunnel_dump)                           \
341 _(LISP_MAP_RESOLVER_DUMP, lisp_map_resolver_dump)                       \
342 _(LISP_EID_TABLE_MAP_DUMP, lisp_eid_table_map_dump)                     \
343 _(LISP_ENABLE_DISABLE_STATUS_DUMP,                                      \
344   lisp_enable_disable_status_dump)                                      \
345 _(LISP_ADD_DEL_MAP_REQUEST_ITR_RLOCS,                                   \
346   lisp_add_del_map_request_itr_rlocs)                                   \
347 _(LISP_GET_MAP_REQUEST_ITR_RLOCS, lisp_get_map_request_itr_rlocs)       \
348 _(SR_MULTICAST_MAP_ADD_DEL, sr_multicast_map_add_del)                   \
349 _(AF_PACKET_CREATE, af_packet_create)                                   \
350 _(AF_PACKET_DELETE, af_packet_delete)                                   \
351 _(POLICER_ADD_DEL, policer_add_del)                                     \
352 _(POLICER_DUMP, policer_dump)                                           \
353 _(NETMAP_CREATE, netmap_create)                                         \
354 _(NETMAP_DELETE, netmap_delete)
355
356 #define QUOTE_(x) #x
357 #define QUOTE(x) QUOTE_(x)
358
359 #define foreach_registration_hash               \
360 _(interface_events)                             \
361 _(to_netconf_server)                            \
362 _(from_netconf_server)                          \
363 _(to_netconf_client)                            \
364 _(from_netconf_client)                          \
365 _(oam_events)
366
367 typedef enum {
368     RESOLVE_IP4_ADD_DEL_ROUTE=1,
369     RESOLVE_IP6_ADD_DEL_ROUTE,
370     RESOLVE_MPLS_ETHERNET_ADD_DEL,
371 } resolve_t;
372
373 typedef struct {
374     u8 resolve_type;
375     union {
376         vl_api_ip_add_del_route_t r;
377         vl_api_mpls_ethernet_add_del_tunnel_2_t t;
378     };
379 } pending_route_t;
380
381 typedef struct {
382
383 #define _(a) uword *a##_registration_hash;              \
384     vpe_client_registration_t * a##_registrations;
385 foreach_registration_hash
386 #undef _
387
388     /* notifications happen really early in the game */
389     u8 link_state_process_up;
390
391     /* ip4 pending route adds */
392     pending_route_t * pending_routes;
393
394     /* ip4 arp event registration pool */
395     vl_api_ip4_arp_event_t * arp_events;
396
397     /* convenience */
398     vlib_main_t * vlib_main;
399     vnet_main_t * vnet_main;
400 } vpe_api_main_t;
401
402 static vlib_node_registration_t vpe_resolver_process_node;
403 static vpe_api_main_t vpe_api_main;
404
405 static void send_sw_interface_flags (vpe_api_main_t * am,
406                                      unix_shared_memory_queue_t *q,
407                                      vnet_sw_interface_t * swif);
408 static void send_sw_interface_flags_deleted (vpe_api_main_t * am,
409                                      unix_shared_memory_queue_t *q,
410                                      u32 sw_if_index);
411
412 static int arp_change_delete_callback (u32 pool_index, u8 * notused);
413
414
415 /* Clean up all registrations belonging to the indicated client */
416 int vl_api_memclnt_delete_callback (u32 client_index)
417 {
418     vpe_api_main_t * vam = &vpe_api_main;
419     vpe_client_registration_t *rp;
420     uword * p;
421     int stats_memclnt_delete_callback (u32 client_index);
422
423     stats_memclnt_delete_callback (client_index);
424
425 #define _(a)                                                    \
426     p = hash_get (vam->a##_registration_hash, client_index);    \
427     if (p) {                                                    \
428         rp = pool_elt_at_index (vam->a##_registrations, p[0]);  \
429         pool_put (vam->a##_registrations, rp);                  \
430         hash_unset (vam->a##_registration_hash, client_index);  \
431     }
432     foreach_registration_hash;
433 #undef _
434     return 0;
435 }
436
437 #define API_LINK_STATE_EVENT 1
438 #define API_ADMIN_UP_DOWN_EVENT 2
439
440 static int
441 event_data_cmp (void * a1, void * a2)
442 {
443   uword * e1 = a1;
444   uword * e2 = a2;
445
446   return (word) e1[0] - (word) e2[0];
447 }
448
449 static uword
450 link_state_process (vlib_main_t * vm,
451                     vlib_node_runtime_t * rt,
452                     vlib_frame_t * f)
453 {
454     vpe_api_main_t * vam = &vpe_api_main;
455     vnet_main_t * vnm = vam->vnet_main;
456     vnet_sw_interface_t * swif;
457     uword * event_data = 0;
458     vpe_client_registration_t *reg;
459     int i;
460     u32 prev_sw_if_index;
461     unix_shared_memory_queue_t * q;
462
463     vam->link_state_process_up = 1;
464
465     while (1) {
466         vlib_process_wait_for_event (vm);
467
468         /* Unified list of changed link or admin state sw_if_indices */
469         vlib_process_get_events_with_type
470             (vm, &event_data, API_LINK_STATE_EVENT);
471         vlib_process_get_events_with_type
472             (vm, &event_data, API_ADMIN_UP_DOWN_EVENT);
473
474         /* Sort, so we can eliminate duplicates */
475         vec_sort_with_function (event_data, event_data_cmp);
476
477         prev_sw_if_index = ~0;
478
479         for (i = 0; i < vec_len(event_data); i++) {
480             /* Only one message per swif */
481             if (prev_sw_if_index == event_data[i])
482                 continue;
483             prev_sw_if_index = event_data[i];
484
485             pool_foreach(reg, vam->interface_events_registrations,
486             ({
487                 q = vl_api_client_index_to_input_queue (reg->client_index);
488                 if (q) {
489                     // sw_interface may be deleted already
490                     if (!pool_is_free_index (vnm->interface_main.sw_interfaces,
491                             event_data[i]))
492                     {
493                         swif = vnet_get_sw_interface (vnm, event_data[i]);
494                         send_sw_interface_flags (vam, q, swif);
495                     }
496                 }
497             }));
498         }
499         vec_reset_length (event_data);
500     }
501
502     return 0;
503 }
504
505 static clib_error_t *
506 link_up_down_function (vnet_main_t *vm, u32 hw_if_index, u32 flags);
507 static clib_error_t *
508 admin_up_down_function (vnet_main_t *vm, u32 hw_if_index, u32 flags);
509
510 VLIB_REGISTER_NODE (link_state_process_node,static) = {
511     .function = link_state_process,
512     .type = VLIB_NODE_TYPE_PROCESS,
513     .name = "vpe-link-state-process",
514 };
515
516 VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION (admin_up_down_function);
517 VNET_HW_INTERFACE_LINK_UP_DOWN_FUNCTION (link_up_down_function);
518
519 static clib_error_t *
520 link_up_down_function (vnet_main_t *vm, u32 hw_if_index, u32 flags)
521 {
522     vpe_api_main_t * vam = &vpe_api_main;
523     vnet_hw_interface_t *hi = vnet_get_hw_interface (vm, hw_if_index);
524
525     if (vam->link_state_process_up)
526         vlib_process_signal_event (vam->vlib_main,
527                                    link_state_process_node.index,
528                                    API_LINK_STATE_EVENT,
529                                    hi->sw_if_index);
530     return 0;
531 }
532
533 static clib_error_t *
534 admin_up_down_function (vnet_main_t *vm, u32 sw_if_index, u32 flags)
535 {
536     vpe_api_main_t * vam = &vpe_api_main;
537
538     /*
539      * Note: it's perfectly fair to set a subif admin up / admin down.
540      * Note the subtle distinction between this routine and the previous
541      * routine.
542      */
543     if (vam->link_state_process_up)
544         vlib_process_signal_event (vam->vlib_main,
545                                    link_state_process_node.index,
546                                    API_ADMIN_UP_DOWN_EVENT,
547                                    sw_if_index);
548     return 0;
549 }
550
551 #define pub_sub_handler(lca,UCA)                                        \
552 static void vl_api_want_##lca##_t_handler (                             \
553     vl_api_want_##lca##_t *mp)                                          \
554 {                                                                       \
555     vpe_api_main_t *vam = &vpe_api_main;                                \
556     vpe_client_registration_t *rp;                                      \
557     vl_api_want_##lca##_reply_t *rmp;                                   \
558     uword *p;                                                           \
559     i32 rv = 0;                                                         \
560                                                                         \
561     p = hash_get (vam->lca##_registration_hash, mp->client_index);      \
562     if (p) {                                                            \
563         if (mp->enable_disable) {                                       \
564             clib_warning ("pid %d: already enabled...", mp->pid);       \
565             rv = VNET_API_ERROR_INVALID_REGISTRATION;                   \
566             goto reply;                                                 \
567         } else {                                                        \
568             rp = pool_elt_at_index (vam->lca##_registrations, p[0]);    \
569             pool_put (vam->lca##_registrations, rp);                    \
570             hash_unset (vam->lca##_registration_hash,                   \
571                 mp->client_index);                                      \
572             goto reply;                                                 \
573         }                                                               \
574     }                                                                   \
575     if (mp->enable_disable == 0) {                                      \
576         clib_warning ("pid %d: already disabled...", mp->pid);          \
577         rv = VNET_API_ERROR_INVALID_REGISTRATION;                       \
578         goto reply;                                                     \
579     }                                                                   \
580     pool_get (vam->lca##_registrations, rp);                            \
581     rp->client_index = mp->client_index;                                \
582     rp->client_pid = mp->pid;                                           \
583     hash_set (vam->lca##_registration_hash, rp->client_index,           \
584               rp - vam->lca##_registrations);                           \
585                                                                         \
586 reply:                                                                  \
587     REPLY_MACRO (VL_API_WANT_##UCA##_REPLY);                            \
588 }
589
590 pub_sub_handler (interface_events,INTERFACE_EVENTS)
591 pub_sub_handler (oam_events,OAM_EVENTS)
592
593 #define RESOLUTION_EVENT 1
594 #define RESOLUTION_PENDING_EVENT 2
595 #define IP4_ARP_EVENT 3
596
597 static int ip4_add_del_route_t_handler (vl_api_ip_add_del_route_t *mp);
598 static int ip6_add_del_route_t_handler (vl_api_ip_add_del_route_t *mp);
599 static int mpls_ethernet_add_del_tunnel_2_t_handler
600 (vl_api_mpls_ethernet_add_del_tunnel_2_t *mp);
601
602 void handle_ip4_arp_event (u32 pool_index)
603 {
604     vpe_api_main_t * vam = &vpe_api_main;
605     vnet_main_t * vnm = vam->vnet_main;
606     vlib_main_t * vm = vam->vlib_main;
607     vl_api_ip4_arp_event_t * event;
608     vl_api_ip4_arp_event_t * mp;
609     unix_shared_memory_queue_t * q;
610
611     /* Client can cancel, die, etc. */
612     if (pool_is_free_index (vam->arp_events, pool_index))
613         return;
614
615     event = pool_elt_at_index (vam->arp_events, pool_index);
616
617     q = vl_api_client_index_to_input_queue (event->client_index);
618     if (!q) {
619         (void) vnet_add_del_ip4_arp_change_event
620             (vnm, arp_change_delete_callback,
621              event->pid, &event->address,
622              vpe_resolver_process_node.index, IP4_ARP_EVENT,
623              ~0 /* pool index, notused */, 0 /* is_add */);
624         return;
625     }
626
627     if (q->cursize < q->maxsize) {
628         mp =  vl_msg_api_alloc (sizeof (*mp));
629         clib_memcpy (mp, event, sizeof (*mp));
630         vl_msg_api_send_shmem (q, (u8 *)&mp);
631     } else {
632         static f64 last_time;
633         /*
634          * Throttle syslog msgs.
635          * It's pretty tempting to just revoke the registration...
636          */
637         if (vlib_time_now (vm) > last_time + 10.0) {
638             clib_warning ("arp event for %U to pid %d: queue stuffed!",
639                           format_ip4_address, &event->address, event->pid);
640             last_time = vlib_time_now(vm);
641         }
642     }
643 }
644
645 static uword
646 resolver_process (vlib_main_t * vm,
647                     vlib_node_runtime_t * rt,
648                     vlib_frame_t * f)
649 {
650     uword event_type;
651     uword *event_data = 0;
652     f64 timeout = 100.0;
653     vpe_api_main_t * vam = &vpe_api_main;
654     pending_route_t * pr;
655     vl_api_ip_add_del_route_t * adr;
656     vl_api_mpls_ethernet_add_del_tunnel_2_t *pme;
657     u32 * resolution_failures = 0;
658     int i, rv;
659     clib_error_t * e;
660
661     while (1) {
662         vlib_process_wait_for_event_or_clock (vm, timeout);
663
664         event_type = vlib_process_get_events (vm, &event_data);
665
666         switch (event_type) {
667         case RESOLUTION_PENDING_EVENT:
668             timeout = 1.0;
669             break;
670
671         case RESOLUTION_EVENT:
672             for (i = 0; i < vec_len(event_data); i++) {
673                 /*
674                  * Resolution events can occur long after the
675                  * original request has timed out. $$$ add a cancel
676                  * mechanism..
677                  */
678                 if (pool_is_free_index (vam->pending_routes, event_data[i]))
679                     continue;
680
681                 pr = pool_elt_at_index (vam->pending_routes, event_data[i]);
682                 adr = &pr->r;
683                 pme = &pr->t;
684
685                 switch (pr->resolve_type) {
686                 case RESOLVE_IP4_ADD_DEL_ROUTE:
687                     rv = ip4_add_del_route_t_handler (adr);
688                     clib_warning ("resolver: add %U/%d via %U %s",
689                                   format_ip4_address,
690                                   (ip4_address_t *)&(adr->dst_address),
691                                   adr->dst_address_length,
692                                   format_ip4_address,
693                                   (ip4_address_t *)&(adr->next_hop_address),
694                                   (rv >= 0) ? "succeeded" : "failed");
695                     break;
696
697                 case RESOLVE_IP6_ADD_DEL_ROUTE:
698                     rv = ip6_add_del_route_t_handler (adr);
699                     clib_warning ("resolver: add %U/%d via %U %s",
700                                   format_ip6_address,
701                                   (ip6_address_t *)&(adr->dst_address),
702                                   adr->dst_address_length,
703                                   format_ip6_address,
704                                   (ip6_address_t *)&(adr->next_hop_address),
705                                   (rv >= 0) ? "succeeded" : "failed");
706                     break;
707
708                 case RESOLVE_MPLS_ETHERNET_ADD_DEL:
709                     rv = mpls_ethernet_add_del_tunnel_2_t_handler (pme);
710                     clib_warning ("resolver: add mpls-o-e via %U %s",
711                                   format_ip4_address,
712             (ip4_address_t *)&(pme->next_hop_ip4_address_in_outer_vrf),
713                                   (rv >= 0) ? "succeeded" : "failed");
714                     break;
715
716                 default:
717                     clib_warning ("resolver: BOGUS TYPE %d", pr->resolve_type);
718                 }
719                 pool_put (vam->pending_routes, pr);
720             }
721             break;
722
723         case IP4_ARP_EVENT:
724             for (i = 0; i < vec_len(event_data); i++)
725                 handle_ip4_arp_event (event_data[i]);
726             break;
727
728         case ~0:                /* timeout, retry pending resolutions */
729             pool_foreach (pr, vam->pending_routes,
730             ({
731                 int is_adr = 1;
732                 adr = &pr->r;
733                 pme = &pr->t;
734
735                 /* May fail, e.g. due to interface down */
736                 switch (pr->resolve_type) {
737                 case RESOLVE_IP4_ADD_DEL_ROUTE:
738                     e = ip4_probe_neighbor
739                         (vm, (ip4_address_t *)&(adr->next_hop_address),
740                          ntohl(adr->next_hop_sw_if_index));
741                     break;
742
743                 case RESOLVE_IP6_ADD_DEL_ROUTE:
744                     e = ip6_probe_neighbor
745                         (vm, (ip6_address_t *)&(adr->next_hop_address),
746                          ntohl(adr->next_hop_sw_if_index));
747                     break;
748
749                 case RESOLVE_MPLS_ETHERNET_ADD_DEL:
750                     is_adr = 0;
751                     e = ip4_probe_neighbor
752                         (vm,
753             (ip4_address_t *)&(pme->next_hop_ip4_address_in_outer_vrf),
754                          pme->resolve_opaque);
755                     break;
756
757                 default:
758                     e = clib_error_return (0, "resolver: BOGUS TYPE %d",
759                                            pr->resolve_type);
760                 }
761                 if (e) {
762                     clib_error_report (e);
763                     if (is_adr)
764                         adr->resolve_attempts = 1;
765                     else
766                         pme->resolve_attempts = 1;
767
768                 }
769                 if (is_adr) {
770                     adr->resolve_attempts -= 1;
771                     if (adr->resolve_attempts == 0)
772                         vec_add1 (resolution_failures,
773                                   pr - vam->pending_routes);
774                 } else {
775                     pme->resolve_attempts -= 1;
776                     if (pme->resolve_attempts == 0)
777                         vec_add1 (resolution_failures,
778                                   pr - vam->pending_routes);
779                 }
780
781             }));
782             for (i = 0; i < vec_len (resolution_failures); i++) {
783                 pr = pool_elt_at_index (vam->pending_routes,
784                                         resolution_failures[i]);
785                 adr = &pr->r;
786                 pme = &pr->t;
787
788                 switch (pr->resolve_type) {
789                 case RESOLVE_IP4_ADD_DEL_ROUTE:
790                     clib_warning ("resolver: add %U/%d via %U retry failure",
791                                   format_ip4_address,
792                                   (ip4_address_t *)&(adr->dst_address),
793                                   adr->dst_address_length,
794                                   format_ip4_address,
795                                   (ip4_address_t *)&(adr->next_hop_address));
796                     break;
797
798                 case RESOLVE_IP6_ADD_DEL_ROUTE:
799                     clib_warning ("resolver: add %U/%d via %U retry failure",
800                                   format_ip6_address,
801                                   (ip6_address_t *)&(adr->dst_address),
802                                   adr->dst_address_length,
803                                   format_ip6_address,
804                                   (ip6_address_t *)&(adr->next_hop_address));
805                     break;
806
807                 case RESOLVE_MPLS_ETHERNET_ADD_DEL:
808                     clib_warning ("resolver: add mpls-o-e via %U retry failure",
809                                   format_ip4_address,
810                    (ip4_address_t *)&(pme->next_hop_ip4_address_in_outer_vrf));
811                     break;
812
813                 default:
814                     clib_warning ("BUG");
815                 }
816                 pool_put(vam->pending_routes, pr);
817             }
818             vec_reset_length (resolution_failures);
819             break;
820         }
821         if (pool_elts (vam->pending_routes) == 0)
822             timeout = 100.0;
823         vec_reset_length (event_data);
824     }
825     return 0; /* or not */
826 }
827
828 VLIB_REGISTER_NODE (vpe_resolver_process_node,static) = {
829     .function = resolver_process,
830     .type = VLIB_NODE_TYPE_PROCESS,
831     .name = "vpe-route-resolver-process",
832 };
833
834 static int ip4_add_del_route_t_handler (vl_api_ip_add_del_route_t *mp)
835 {
836     ip4_main_t * im = &ip4_main;
837     ip_lookup_main_t * lm = &im->lookup_main;
838     vnet_classify_main_t * cm = &vnet_classify_main;
839     stats_main_t * sm = &stats_main;
840     ip4_add_del_route_args_t a;
841     ip4_address_t next_hop_address;
842     u32 fib_index;
843     vpe_api_main_t * vam = &vpe_api_main;
844     vnet_main_t * vnm = vam->vnet_main;
845     vlib_main_t * vm = vlib_get_main();
846     pending_route_t * pr;
847     vl_api_ip_add_del_route_t * adr;
848     uword * p;
849     clib_error_t * e;
850     u32 ai;
851     ip_adjacency_t *nh_adj, *add_adj = 0;
852
853     p = hash_get (im->fib_index_by_table_id, ntohl(mp->vrf_id));
854     if (!p) {
855         if (mp->create_vrf_if_needed) {
856             ip4_fib_t * f;
857             f = find_ip4_fib_by_table_index_or_id (im, ntohl(mp->vrf_id),
858                                                    0 /* flags */);
859             fib_index = f->index;
860         } else {
861             /* No such VRF, and we weren't asked to create one */
862             return VNET_API_ERROR_NO_SUCH_FIB;
863         }
864     } else {
865         fib_index = p[0];
866     }
867
868     if (pool_is_free_index (vnm->interface_main.sw_interfaces,
869                             ntohl(mp->next_hop_sw_if_index)))
870         return VNET_API_ERROR_NO_MATCHING_INTERFACE;
871
872     clib_memcpy (next_hop_address.data, mp->next_hop_address,
873             sizeof (next_hop_address.data));
874
875     /* Arp for the next_hop if necessary */
876     if (mp->is_add && mp->resolve_if_needed) {
877         u32 lookup_result;
878         ip_adjacency_t * adj;
879
880         lookup_result = ip4_fib_lookup_with_table
881             (im, fib_index, &next_hop_address, 1 /* disable default route */);
882
883         adj = ip_get_adjacency (lm, lookup_result);
884
885         if (adj->lookup_next_index == IP_LOOKUP_NEXT_ARP) {
886             pool_get (vam->pending_routes, pr);
887             pr->resolve_type = RESOLVE_IP4_ADD_DEL_ROUTE;
888             adr = &pr->r;
889             clib_memcpy (adr, mp, sizeof (*adr));
890             /* recursion block, "just in case" */
891             adr->resolve_if_needed = 0;
892             adr->resolve_attempts = ntohl(mp->resolve_attempts);
893             vnet_register_ip4_arp_resolution_event
894                 (vnm, &next_hop_address, vpe_resolver_process_node.index,
895                  RESOLUTION_EVENT, pr - vam->pending_routes);
896
897             vlib_process_signal_event
898                 (vm, vpe_resolver_process_node.index,
899                  RESOLUTION_PENDING_EVENT, 0 /* data */);
900
901             /* The interface may be down, etc. */
902             e = ip4_probe_neighbor
903                 (vm, (ip4_address_t *)&(mp->next_hop_address),
904                  ntohl(mp->next_hop_sw_if_index));
905
906             if (e)
907                 clib_error_report(e);
908
909             return VNET_API_ERROR_IN_PROGRESS;
910         }
911     }
912
913     if (mp->is_multipath) {
914         u32 flags;
915
916         dslock (sm, 1 /* release hint */, 10 /* tag */);
917
918         if (mp->is_add)
919            flags = IP4_ROUTE_FLAG_ADD;
920         else
921            flags = IP4_ROUTE_FLAG_DEL;
922
923         if (mp->not_last)
924             flags |= IP4_ROUTE_FLAG_NOT_LAST_IN_GROUP;
925
926         ip4_add_del_route_next_hop (im, flags,
927                                     (ip4_address_t *) mp->dst_address,
928                                     (u32) mp->dst_address_length,
929                                     (ip4_address_t *) mp->next_hop_address,
930                                     ntohl(mp->next_hop_sw_if_index),
931                                     (u32) mp->next_hop_weight,
932                                     ~0 /* adj_index */,
933                                     fib_index);
934         dsunlock(sm);
935         return 0;
936     }
937
938     memset (&a, 0, sizeof (a));
939     clib_memcpy (a.dst_address.data, mp->dst_address, sizeof (a.dst_address.data));
940
941     a.dst_address_length = mp->dst_address_length;
942
943     a.flags = (mp->is_add ? IP4_ROUTE_FLAG_ADD : IP4_ROUTE_FLAG_DEL);
944     a.flags |= IP4_ROUTE_FLAG_FIB_INDEX;
945     a.table_index_or_table_id = fib_index;
946     a.add_adj = 0;
947     a.n_add_adj = 0;
948
949     if (mp->not_last)
950         a.flags |= IP4_ROUTE_FLAG_NOT_LAST_IN_GROUP;
951
952     dslock (sm, 1 /* release hint */, 2 /* tag */);
953
954     if (mp->is_add) {
955         if (mp->is_drop)
956             ai = lm->drop_adj_index;
957         else if (mp->is_local)
958             ai = lm->local_adj_index;
959         else if (mp->is_classify) {
960             ip_adjacency_t cadj;
961             memset(&cadj, 0, sizeof(cadj));
962             cadj.lookup_next_index = IP_LOOKUP_NEXT_CLASSIFY;
963             cadj.classify.table_index = ntohl(mp->classify_table_index);
964             if (pool_is_free_index (cm->tables, cadj.classify.table_index)) {
965                 dsunlock(sm);
966                 return VNET_API_ERROR_NO_SUCH_TABLE;
967             }
968             vec_add1 (add_adj, cadj);
969             goto do_add_del;
970         }
971         else {
972             ai = ip4_fib_lookup_with_table
973                 (im, fib_index, &next_hop_address,
974                  1 /* disable default route */);
975             if (ai == lm->miss_adj_index) {
976                 dsunlock(sm);
977                 return VNET_API_ERROR_NEXT_HOP_NOT_IN_FIB;
978             }
979         }
980
981         nh_adj = ip_get_adjacency (lm, ai);
982         if (nh_adj->lookup_next_index == IP_LOOKUP_NEXT_ARP &&
983             nh_adj->arp.next_hop.ip4.as_u32 == 0) {
984             /* the next-hop resovles via a glean adj. create and use
985              * a ARP adj for the next-hop */
986             a.adj_index = vnet_arp_glean_add(fib_index, &next_hop_address);
987             a.add_adj = NULL;
988             a.n_add_adj = 0;
989             ip4_add_del_route (im, &a);
990
991             goto done;
992         }
993         vec_add1 (add_adj, nh_adj[0]);
994         if (mp->lookup_in_vrf) {
995             p = hash_get (im->fib_index_by_table_id, ntohl(mp->lookup_in_vrf));
996             if (p)
997                 add_adj[0].explicit_fib_index = p[0];
998             else {
999                 vec_free (add_adj);
1000                 dsunlock(sm);
1001                 return VNET_API_ERROR_NO_SUCH_INNER_FIB;
1002             }
1003         }
1004     } else {
1005         ip_adjacency_t * adj;
1006         int disable_default_route = 1;
1007
1008         /* Trying to delete the default route? */
1009         if (a.dst_address.as_u32 == 0 &&
1010             a.dst_address_length == 0)
1011             disable_default_route = 0;
1012
1013         ai = ip4_fib_lookup_with_table
1014             (im, fib_index, &a.dst_address, disable_default_route);
1015         if (ai == lm->miss_adj_index) {
1016             dsunlock(sm);
1017             return VNET_API_ERROR_UNKNOWN_DESTINATION;
1018         }
1019
1020         adj = ip_get_adjacency (lm, ai);
1021         if (adj->lookup_next_index == IP_LOOKUP_NEXT_ARP) {
1022             dsunlock(sm);
1023             return VNET_API_ERROR_ADDRESS_MATCHES_INTERFACE_ADDRESS;
1024         }
1025     }
1026
1027 do_add_del:
1028     a.adj_index = ~0;
1029     a.add_adj = add_adj;
1030     a.n_add_adj = vec_len(add_adj);
1031     ip4_add_del_route (im, &a);
1032
1033     vec_free (add_adj);
1034
1035 done:
1036     dsunlock (sm);
1037     return 0;
1038 }
1039
1040 static int ip6_add_del_route_t_handler (vl_api_ip_add_del_route_t *mp)
1041 {
1042     ip6_main_t * im = &ip6_main;
1043     ip_lookup_main_t * lm = &im->lookup_main;
1044     vnet_main_t * vnm = vnet_get_main();
1045     vlib_main_t * vm = vlib_get_main();
1046     vpe_api_main_t * vam = &vpe_api_main;
1047     stats_main_t * sm = &stats_main;
1048     ip6_add_del_route_args_t a;
1049     ip6_address_t next_hop_address;
1050     pending_route_t * pr;
1051     vl_api_ip_add_del_route_t * adr;
1052
1053     u32 fib_index;
1054     uword * p;
1055     clib_error_t * e;
1056     ip_adjacency_t * nh_adj, * add_adj = 0;
1057     u32 ai;
1058
1059     p = hash_get (im->fib_index_by_table_id, ntohl(mp->vrf_id));
1060
1061     if (!p) {
1062         if (mp->create_vrf_if_needed) {
1063             ip6_fib_t * f;
1064             f = find_ip6_fib_by_table_index_or_id (im, ntohl(mp->vrf_id),
1065                                                    0 /* flags */);
1066             fib_index = f->index;
1067         } else {
1068             /* No such VRF, and we weren't asked to create one */
1069             return VNET_API_ERROR_NO_SUCH_FIB;
1070         }
1071     } else {
1072         fib_index = p[0];
1073     }
1074
1075     if (pool_is_free_index (vnm->interface_main.sw_interfaces,
1076                             ntohl(mp->next_hop_sw_if_index)))
1077         return VNET_API_ERROR_NO_MATCHING_INTERFACE;
1078
1079     clib_memcpy (next_hop_address.as_u8, mp->next_hop_address,
1080             sizeof (next_hop_address.as_u8));
1081
1082     /* Arp for the next_hop if necessary */
1083     if (mp->is_add && mp->resolve_if_needed) {
1084         u32 lookup_result;
1085         ip_adjacency_t * adj;
1086
1087         lookup_result = ip6_fib_lookup_with_table
1088             (im, fib_index, &next_hop_address);
1089
1090         adj = ip_get_adjacency (lm, lookup_result);
1091
1092         if (adj->lookup_next_index == IP_LOOKUP_NEXT_ARP) {
1093             pool_get (vam->pending_routes, pr);
1094             adr = &pr->r;
1095             pr->resolve_type = RESOLVE_IP6_ADD_DEL_ROUTE;
1096             clib_memcpy (adr, mp, sizeof (*adr));
1097             /* recursion block, "just in case" */
1098             adr->resolve_if_needed = 0;
1099             adr->resolve_attempts = ntohl(mp->resolve_attempts);
1100             vnet_register_ip6_neighbor_resolution_event
1101                 (vnm, &next_hop_address, vpe_resolver_process_node.index,
1102                  RESOLUTION_EVENT, pr - vam->pending_routes);
1103
1104             vlib_process_signal_event
1105                 (vm, vpe_resolver_process_node.index,
1106                  RESOLUTION_PENDING_EVENT, 0 /* data */);
1107
1108             /* The interface may be down, etc. */
1109             e = ip6_probe_neighbor
1110                 (vm, (ip6_address_t *)&(mp->next_hop_address),
1111                  ntohl(mp->next_hop_sw_if_index));
1112
1113             if (e)
1114                 clib_error_report(e);
1115
1116             return VNET_API_ERROR_IN_PROGRESS;
1117         }
1118     }
1119
1120     if (mp->is_multipath) {
1121         u32 flags;
1122
1123         dslock (sm, 1 /* release hint */, 11 /* tag */);
1124
1125         if (mp->is_add)
1126             flags = IP6_ROUTE_FLAG_ADD;
1127         else
1128             flags = IP6_ROUTE_FLAG_DEL;
1129
1130         if (mp->not_last)
1131             flags |= IP6_ROUTE_FLAG_NOT_LAST_IN_GROUP;
1132
1133         ip6_add_del_route_next_hop (im, flags, (ip6_address_t *)mp->dst_address,
1134                                     (u32) mp->dst_address_length,
1135                                     (ip6_address_t *)mp->next_hop_address,
1136                                     ntohl(mp->next_hop_sw_if_index),
1137                                     (u32) mp->next_hop_weight,
1138                                     ~0 /* adj_index */,
1139                                     fib_index);
1140         dsunlock(sm);
1141         return 0;
1142     }
1143
1144     memset (&a, 0, sizeof (a));
1145     clib_memcpy (a.dst_address.as_u8, mp->dst_address, sizeof (a.dst_address.as_u8));
1146
1147     a.dst_address_length = mp->dst_address_length;
1148
1149     a.flags = (mp->is_add ? IP6_ROUTE_FLAG_ADD : IP6_ROUTE_FLAG_DEL);
1150     a.flags |= IP6_ROUTE_FLAG_FIB_INDEX;
1151     a.table_index_or_table_id = fib_index;
1152     a.add_adj = 0;
1153     a.n_add_adj = 0;
1154
1155     if (mp->not_last)
1156         a.flags |= IP6_ROUTE_FLAG_NOT_LAST_IN_GROUP;
1157
1158     dslock (sm, 1 /* release hint */, 3 /* tag */);
1159
1160     if (mp->is_add) {
1161         if (mp->is_drop)
1162             ai = lm->drop_adj_index;
1163         else if (mp->is_local)
1164             ai = lm->local_adj_index;
1165         else {
1166             ai = ip6_fib_lookup_with_table
1167                 (im, fib_index, &next_hop_address);
1168             if (ai == lm->miss_adj_index) {
1169                 dsunlock(sm);
1170                 return VNET_API_ERROR_NEXT_HOP_NOT_IN_FIB;
1171             }
1172         }
1173
1174         nh_adj = ip_get_adjacency (lm, ai);
1175         vec_add1 (add_adj, nh_adj[0]);
1176         if (mp->lookup_in_vrf) {
1177             p = hash_get (im->fib_index_by_table_id, ntohl(mp->lookup_in_vrf));
1178             if (p)
1179                 add_adj[0].explicit_fib_index = p[0];
1180             else {
1181                 vec_free (add_adj);
1182                 dsunlock(sm);
1183                 return VNET_API_ERROR_NO_SUCH_INNER_FIB;
1184             }
1185         }
1186     } else {
1187         ip_adjacency_t * adj;
1188
1189         ai = ip6_fib_lookup_with_table
1190             (im, fib_index, &a.dst_address);
1191         if (ai == lm->miss_adj_index) {
1192             dsunlock(sm);
1193             return VNET_API_ERROR_UNKNOWN_DESTINATION;
1194         }
1195         adj = ip_get_adjacency (lm, ai);
1196         if (adj->lookup_next_index == IP_LOOKUP_NEXT_ARP) {
1197             dsunlock(sm);
1198             return VNET_API_ERROR_ADDRESS_MATCHES_INTERFACE_ADDRESS;
1199         }
1200     }
1201
1202     a.adj_index = ~0;
1203     a.add_adj = add_adj;
1204     a.n_add_adj = vec_len(add_adj);
1205     ip6_add_del_route (im, &a);
1206
1207     vec_free (add_adj);
1208
1209     dsunlock (sm);
1210     return 0;
1211 }
1212
1213 void vl_api_ip_add_del_route_t_handler (
1214     vl_api_ip_add_del_route_t *mp)
1215 {
1216     vl_api_ip_add_del_route_reply_t * rmp;
1217     int rv;
1218     vnet_main_t * vnm = vnet_get_main();
1219
1220     vnm->api_errno = 0;
1221
1222     if (mp->is_ipv6)
1223         rv = ip6_add_del_route_t_handler (mp);
1224     else
1225         rv = ip4_add_del_route_t_handler (mp);
1226
1227     rv = (rv == 0) ? vnm->api_errno : rv;
1228
1229     REPLY_MACRO(VL_API_IP_ADD_DEL_ROUTE_REPLY);
1230 }
1231
1232 void api_config_default_ip_route (u8 is_ipv6, u8 is_add, u32 vrf_id,
1233                                   u32 sw_if_index, u8 *next_hop_addr)
1234 {
1235     vl_api_ip_add_del_route_t mp;
1236     int rv;
1237
1238     memset (&mp, 0, sizeof(vl_api_ip_add_del_route_t));
1239
1240     /*
1241      * Configure default IP route:
1242      *  - ip route add 0.0.0.0/1 via <GW IP>
1243      *  - ip route add 128.0.0.0/1 via <GW IP>
1244      */
1245     mp.next_hop_sw_if_index = ntohl(sw_if_index);
1246     mp.vrf_id = vrf_id;
1247     mp.resolve_attempts = ~0;
1248     mp.resolve_if_needed = 1;
1249     mp.is_add = is_add;
1250     mp.is_ipv6 = is_ipv6;
1251     mp.next_hop_weight = 1;
1252
1253     clib_memcpy (&mp.next_hop_address[0], next_hop_addr, 16);
1254
1255     if (is_ipv6)
1256         rv = ip6_add_del_route_t_handler (&mp);
1257     else
1258       {
1259         mp.dst_address_length = 1;
1260
1261         mp.dst_address[0] = 0;
1262         rv = ip4_add_del_route_t_handler (&mp);
1263
1264         mp.dst_address[0] = 128;
1265         rv |= ip4_add_del_route_t_handler (&mp);
1266       }
1267
1268     if (rv)
1269         clib_error_return (0, "failed to config default IP route");
1270
1271 }
1272
1273 static void
1274 vl_api_sw_interface_add_del_address_t_handler
1275 (vl_api_sw_interface_add_del_address_t *mp)
1276 {
1277     vlib_main_t *vm = vlib_get_main();
1278     vl_api_sw_interface_add_del_address_reply_t * rmp;
1279     int rv = 0;
1280     u32 is_del;
1281
1282     VALIDATE_SW_IF_INDEX(mp);
1283
1284     is_del = mp->is_add == 0;
1285
1286     if (mp->del_all)
1287         ip_del_all_interface_addresses (vm, ntohl(mp->sw_if_index));
1288     else if (mp->is_ipv6)
1289         ip6_add_del_interface_address (vm, ntohl(mp->sw_if_index),
1290                                        (void *)mp->address,
1291                                        mp->address_length, is_del);
1292     else
1293         ip4_add_del_interface_address (vm, ntohl(mp->sw_if_index),
1294                                        (void *) mp->address,
1295                                        mp->address_length, is_del);
1296
1297     BAD_SW_IF_INDEX_LABEL;
1298
1299     REPLY_MACRO(VL_API_SW_INTERFACE_ADD_DEL_ADDRESS_REPLY);
1300 }
1301
1302 static void
1303 vl_api_sw_interface_set_table_t_handler (vl_api_sw_interface_set_table_t *mp)
1304 {
1305     int rv = 0;
1306     u32 table_id = ntohl(mp->vrf_id);
1307     u32 sw_if_index = ntohl(mp->sw_if_index);
1308     vl_api_sw_interface_set_table_reply_t * rmp;
1309     stats_main_t * sm = &stats_main;
1310
1311     VALIDATE_SW_IF_INDEX(mp);
1312
1313     dslock (sm, 1 /* release hint */, 4 /* tag */);
1314
1315     if (mp->is_ipv6) {
1316         ip6_main_t * im = &ip6_main;
1317         ip6_fib_t * fib =
1318             find_ip6_fib_by_table_index_or_id (im, table_id,
1319                                                IP6_ROUTE_FLAG_TABLE_ID);
1320         if (fib) {
1321             vec_validate (im->fib_index_by_sw_if_index, sw_if_index);
1322             im->fib_index_by_sw_if_index[sw_if_index] = fib->index;
1323         } else {
1324             rv = VNET_API_ERROR_NO_SUCH_FIB;
1325         }
1326     } else {
1327         ip4_main_t * im = &ip4_main;
1328         ip4_fib_t * fib = find_ip4_fib_by_table_index_or_id
1329             (im, table_id, IP4_ROUTE_FLAG_TABLE_ID);
1330
1331         /* Truthfully this can't fail */
1332         if (fib) {
1333             vec_validate (im->fib_index_by_sw_if_index, sw_if_index);
1334             im->fib_index_by_sw_if_index[sw_if_index] = fib->index;
1335         } else {
1336             rv = VNET_API_ERROR_NO_SUCH_FIB;
1337         }
1338     }
1339     dsunlock(sm);
1340
1341     BAD_SW_IF_INDEX_LABEL;
1342
1343     REPLY_MACRO(VL_API_SW_INTERFACE_SET_TABLE_REPLY);
1344 }
1345
1346 static void
1347 vl_api_sw_interface_set_vpath_t_handler (vl_api_sw_interface_set_vpath_t *mp)
1348 {
1349     vlib_main_t *vm = vlib_get_main();
1350     ip4_main_t * im4 = &ip4_main;
1351     ip6_main_t * im6 = &ip6_main;
1352     vl_api_sw_interface_set_vpath_reply_t * rmp;
1353     int rv = 0;
1354     u32 ci;
1355     u32 sw_if_index = ntohl(mp->sw_if_index);
1356     ip4_main_t   *ip4m = &ip4_main;
1357     ip6_main_t   *ip6m = &ip6_main;
1358     ip_lookup_main_t *ip4lm = &ip4m->lookup_main;
1359     ip_lookup_main_t *ip6lm = &ip6m->lookup_main;
1360     ip_config_main_t *rx_cm4u = &ip4lm->rx_config_mains[VNET_UNICAST];
1361     ip_config_main_t *rx_cm4m = &ip4lm->rx_config_mains[VNET_MULTICAST];
1362     ip_config_main_t *rx_cm6u = &ip6lm->rx_config_mains[VNET_UNICAST];
1363     ip_config_main_t *rx_cm6m = &ip6lm->rx_config_mains[VNET_MULTICAST];
1364
1365     VALIDATE_SW_IF_INDEX(mp);
1366
1367     l2input_intf_bitmap_enable(sw_if_index, L2INPUT_FEAT_VPATH, mp->enable);
1368     if (mp->enable) {
1369         ci = rx_cm4u->config_index_by_sw_if_index[sw_if_index]; //IP4 unicast
1370         ci = vnet_config_add_feature(vm, &rx_cm4u->config_main,
1371                                      ci, 
1372                                      im4->ip4_unicast_rx_feature_vpath,
1373                                      0, 0);
1374         rx_cm4u->config_index_by_sw_if_index[sw_if_index] = ci;
1375         ci = rx_cm4m->config_index_by_sw_if_index[sw_if_index]; //IP4 mcast
1376         ci = vnet_config_add_feature(vm, &rx_cm4m->config_main,
1377                                      ci, 
1378                                      im4->ip4_multicast_rx_feature_vpath,
1379                                      0, 0);
1380         rx_cm4m->config_index_by_sw_if_index[sw_if_index] = ci;
1381         ci = rx_cm6u->config_index_by_sw_if_index[sw_if_index]; //IP6 unicast
1382         ci = vnet_config_add_feature(vm, &rx_cm6u->config_main,
1383                                      ci, 
1384                                      im6->ip6_unicast_rx_feature_vpath,
1385                                      0, 0);
1386         rx_cm6u->config_index_by_sw_if_index[sw_if_index] = ci;
1387         ci = rx_cm6m->config_index_by_sw_if_index[sw_if_index]; //IP6 mcast
1388         ci = vnet_config_add_feature(vm, &rx_cm6m->config_main,
1389                                      ci, 
1390                                      im6->ip6_multicast_rx_feature_vpath,
1391                                      0, 0);
1392         rx_cm6m->config_index_by_sw_if_index[sw_if_index] = ci;
1393     } else {
1394         ci = rx_cm4u->config_index_by_sw_if_index[sw_if_index]; //IP4 unicast
1395         ci = vnet_config_del_feature(vm, &rx_cm4u->config_main,
1396                                      ci, 
1397                                      im4->ip4_unicast_rx_feature_vpath,
1398                                      0, 0);
1399         rx_cm4u->config_index_by_sw_if_index[sw_if_index] = ci;
1400         ci = rx_cm4m->config_index_by_sw_if_index[sw_if_index]; //IP4 mcast
1401         ci = vnet_config_del_feature(vm, &rx_cm4m->config_main,
1402                                      ci, 
1403                                      im4->ip4_multicast_rx_feature_vpath,
1404                                      0, 0);
1405         rx_cm4m->config_index_by_sw_if_index[sw_if_index] = ci;
1406         ci = rx_cm6u->config_index_by_sw_if_index[sw_if_index]; //IP6 unicast
1407         ci = vnet_config_del_feature(vm, &rx_cm6u->config_main,
1408                                      ci, 
1409                                      im6->ip6_unicast_rx_feature_vpath,
1410                                      0, 0);
1411         rx_cm6u->config_index_by_sw_if_index[sw_if_index] = ci;
1412         ci = rx_cm6m->config_index_by_sw_if_index[sw_if_index]; //IP6 mcast
1413         ci = vnet_config_del_feature(vm, &rx_cm6m->config_main,
1414                                      ci, 
1415                                      im6->ip6_multicast_rx_feature_vpath,
1416                                      0, 0);
1417         rx_cm6m->config_index_by_sw_if_index[sw_if_index] = ci;
1418     }
1419
1420     BAD_SW_IF_INDEX_LABEL;
1421
1422     REPLY_MACRO(VL_API_SW_INTERFACE_SET_VPATH_REPLY);
1423 }
1424
1425 static void
1426 vl_api_sw_interface_set_l2_xconnect_t_handler (
1427     vl_api_sw_interface_set_l2_xconnect_t *mp)
1428 {
1429     vl_api_sw_interface_set_l2_xconnect_reply_t * rmp;
1430     int rv = 0;
1431     u32 rx_sw_if_index = ntohl(mp->rx_sw_if_index);
1432     u32 tx_sw_if_index = ntohl(mp->tx_sw_if_index);
1433     vlib_main_t *vm  = vlib_get_main();
1434     vnet_main_t *vnm = vnet_get_main();
1435
1436     VALIDATE_RX_SW_IF_INDEX(mp);
1437
1438     if (mp->enable) {
1439         VALIDATE_TX_SW_IF_INDEX(mp);
1440         rv = set_int_l2_mode(vm, vnm, MODE_L2_XC,
1441                              rx_sw_if_index, 0, 0, 0, tx_sw_if_index);
1442     } else {
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     BAD_TX_SW_IF_INDEX_LABEL;
1448
1449     REPLY_MACRO(VL_API_SW_INTERFACE_SET_L2_XCONNECT_REPLY);
1450 }
1451
1452 static void
1453 vl_api_sw_interface_set_l2_bridge_t_handler (
1454     vl_api_sw_interface_set_l2_bridge_t *mp)
1455 {
1456     bd_main_t * bdm = &bd_main;
1457     vl_api_sw_interface_set_l2_bridge_reply_t * rmp;
1458     int rv = 0;
1459     u32 rx_sw_if_index = ntohl(mp->rx_sw_if_index);
1460     u32 bd_id = ntohl(mp->bd_id);
1461     u32 bd_index;
1462     u32 bvi = mp->bvi;
1463     u8 shg = mp->shg;
1464     vlib_main_t *vm  = vlib_get_main();
1465     vnet_main_t *vnm = vnet_get_main();
1466
1467     VALIDATE_RX_SW_IF_INDEX(mp);
1468
1469     bd_index = bd_find_or_add_bd_index (bdm, bd_id);
1470
1471     if (mp->enable) {
1472         //VALIDATE_TX_SW_IF_INDEX(mp);
1473         rv = set_int_l2_mode(vm, vnm, MODE_L2_BRIDGE,
1474                              rx_sw_if_index, bd_index, bvi, shg, 0);
1475     } else {
1476         rv = set_int_l2_mode(vm, vnm, MODE_L3, rx_sw_if_index, 0, 0, 0, 0);
1477     }
1478
1479     BAD_RX_SW_IF_INDEX_LABEL;
1480
1481     REPLY_MACRO(VL_API_SW_INTERFACE_SET_L2_BRIDGE_REPLY);
1482 }
1483
1484 static void
1485 vl_api_bridge_domain_add_del_t_handler (
1486     vl_api_bridge_domain_add_del_t *mp)
1487 {
1488     vlib_main_t * vm = vlib_get_main ();
1489     bd_main_t * bdm = &bd_main;
1490     vl_api_bridge_domain_add_del_reply_t * rmp;
1491     int rv = 0;
1492     u32 enable_flags = 0, disable_flags = 0;
1493     u32 bd_id = ntohl(mp->bd_id);
1494     u32 bd_index;
1495
1496     if (mp->is_add) {
1497         bd_index = bd_find_or_add_bd_index (bdm, bd_id);
1498
1499         if (mp->flood)
1500             enable_flags |= L2_FLOOD;
1501         else
1502             disable_flags |= L2_FLOOD;
1503
1504         if (mp->uu_flood)
1505             enable_flags |= L2_UU_FLOOD;
1506         else
1507             disable_flags |= L2_UU_FLOOD;
1508
1509         if (mp->forward)
1510             enable_flags |= L2_FWD;
1511         else
1512             disable_flags |= L2_FWD;
1513
1514         if (mp->arp_term)
1515             enable_flags |= L2_ARP_TERM;
1516         else
1517             disable_flags |= L2_ARP_TERM;
1518
1519         if (mp->learn)
1520             enable_flags |= L2_LEARN;
1521         else
1522             disable_flags |= L2_LEARN;
1523
1524         if (enable_flags)
1525             bd_set_flags (vm, bd_index, enable_flags, 1 /* enable */);
1526
1527         if (disable_flags)
1528             bd_set_flags (vm, bd_index, disable_flags, 0 /* disable */);
1529
1530     } else
1531         rv = bd_delete_bd_index(bdm, bd_id);
1532
1533     REPLY_MACRO(VL_API_BRIDGE_DOMAIN_ADD_DEL_REPLY);
1534 }
1535
1536 static void vl_api_bridge_domain_details_t_handler (
1537     vl_api_bridge_domain_details_t * mp)
1538 {
1539     clib_warning ("BUG");
1540 }
1541
1542 static void vl_api_bridge_domain_sw_if_details_t_handler (
1543     vl_api_bridge_domain_sw_if_details_t * mp)
1544 {
1545     clib_warning ("BUG");
1546 }
1547
1548 static void send_bridge_domain_details (unix_shared_memory_queue_t *q,
1549                                         l2_bridge_domain_t * bd_config,
1550                                         u32 n_sw_ifs,
1551                                         u32 context)
1552 {
1553     vl_api_bridge_domain_details_t * mp;
1554
1555     mp = vl_msg_api_alloc (sizeof (*mp));
1556     memset (mp, 0, sizeof (*mp));
1557     mp->_vl_msg_id = ntohs (VL_API_BRIDGE_DOMAIN_DETAILS);
1558     mp->bd_id = ntohl (bd_config->bd_id);
1559     mp->flood = bd_feature_flood (bd_config);
1560     mp->uu_flood = bd_feature_uu_flood (bd_config);
1561     mp->forward = bd_feature_forward (bd_config);
1562     mp->learn = bd_feature_learn (bd_config);
1563     mp->arp_term = bd_feature_arp_term (bd_config);
1564     mp->bvi_sw_if_index = ntohl (bd_config->bvi_sw_if_index);
1565     mp->n_sw_ifs = ntohl (n_sw_ifs);
1566     mp->context = context;
1567
1568     vl_msg_api_send_shmem (q, (u8 *)&mp);
1569 }
1570
1571 static void send_bd_sw_if_details (l2input_main_t * l2im,
1572                                    unix_shared_memory_queue_t *q,
1573                                    l2_flood_member_t * member, u32 bd_id,
1574                                    u32 context)
1575 {
1576     vl_api_bridge_domain_sw_if_details_t * mp;
1577     l2_input_config_t * input_cfg;
1578
1579     mp = vl_msg_api_alloc (sizeof (*mp));
1580     memset (mp, 0, sizeof (*mp));
1581     mp->_vl_msg_id = ntohs (VL_API_BRIDGE_DOMAIN_SW_IF_DETAILS);
1582     mp->bd_id = ntohl (bd_id);
1583     mp->sw_if_index = ntohl (member->sw_if_index);
1584     input_cfg = vec_elt_at_index (l2im->configs, member->sw_if_index);
1585     mp->shg = input_cfg->shg;
1586     mp->context = context;
1587
1588     vl_msg_api_send_shmem (q, (u8 *)&mp);
1589 }
1590
1591 static void vl_api_bridge_domain_dump_t_handler (
1592     vl_api_bridge_domain_dump_t *mp)
1593 {
1594     bd_main_t * bdm = &bd_main;
1595     l2input_main_t * l2im = &l2input_main;
1596     unix_shared_memory_queue_t * q;
1597     l2_bridge_domain_t * bd_config;
1598     u32 bd_id, bd_index;
1599     u32 end;
1600
1601     q = vl_api_client_index_to_input_queue (mp->client_index);
1602
1603     if (q == 0)
1604         return;
1605
1606     bd_id = ntohl(mp->bd_id);
1607
1608     bd_index = (bd_id == ~0) ? 0 : bd_find_or_add_bd_index (bdm, bd_id);
1609     end = (bd_id == ~0) ? vec_len (l2im->bd_configs) : bd_index + 1;
1610     for (; bd_index < end; bd_index++) {
1611         bd_config = l2input_bd_config_from_index (l2im, bd_index);
1612         /* skip dummy bd_id 0 */
1613         if (bd_config && (bd_config->bd_id > 0)) {
1614             u32 n_sw_ifs;
1615             l2_flood_member_t * m;
1616
1617             n_sw_ifs = vec_len (bd_config->members);
1618             send_bridge_domain_details (q, bd_config, n_sw_ifs, mp->context);
1619
1620             vec_foreach (m, bd_config->members) {
1621                 send_bd_sw_if_details (l2im, q, m, bd_config->bd_id, mp->context);
1622             }
1623         }
1624     }
1625 }
1626
1627 static void
1628 vl_api_l2fib_add_del_t_handler (
1629     vl_api_l2fib_add_del_t *mp)
1630 {
1631     bd_main_t * bdm = &bd_main;
1632     l2input_main_t * l2im = &l2input_main;
1633     vl_api_l2fib_add_del_reply_t * rmp;
1634     int rv = 0;
1635     u64 mac = 0;
1636     u32 sw_if_index = ntohl(mp->sw_if_index);
1637     u32 bd_id = ntohl(mp->bd_id);
1638     u32 bd_index;
1639     u32 static_mac;
1640     u32 filter_mac;
1641     uword * p;
1642
1643     mac = mp->mac;
1644
1645     p = hash_get (bdm->bd_index_by_bd_id, bd_id);
1646     if (!p) {
1647         rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1648         goto bad_sw_if_index;
1649     }
1650     bd_index = p[0];
1651
1652     if (mp->is_add) {
1653         VALIDATE_SW_IF_INDEX(mp);
1654         if (vec_len(l2im->configs) <= sw_if_index) {
1655             rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
1656             goto bad_sw_if_index;
1657         } else {
1658             l2_input_config_t * config;
1659             config = vec_elt_at_index(l2im->configs, sw_if_index);
1660             if (config->bridge == 0) {
1661                 rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
1662                 goto bad_sw_if_index;
1663             }
1664         }
1665         static_mac = mp->static_mac ? 1 : 0;
1666         filter_mac = mp->filter_mac ? 1 : 0;
1667         l2fib_add_entry(mac, bd_index, sw_if_index, static_mac, filter_mac,
1668                         0 /* bvi_mac */);
1669     } else {
1670         l2fib_del_entry(mac, bd_index);
1671     }
1672
1673     BAD_SW_IF_INDEX_LABEL;
1674
1675     REPLY_MACRO(VL_API_L2FIB_ADD_DEL_REPLY);
1676 }
1677
1678 static void
1679 vl_api_l2_flags_t_handler (
1680     vl_api_l2_flags_t *mp)
1681 {
1682     vl_api_l2_flags_reply_t * rmp;
1683     int rv = 0;
1684     u32 sw_if_index = ntohl(mp->sw_if_index);
1685     u32 flags = ntohl(mp->feature_bitmap);
1686     u32 rbm = 0;
1687
1688     VALIDATE_SW_IF_INDEX(mp);
1689
1690 #define _(a,b) \
1691     if (flags & L2INPUT_FEAT_ ## a) \
1692         rbm = l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_ ## a, mp->is_set);
1693     foreach_l2input_feat;
1694 #undef _
1695
1696     BAD_SW_IF_INDEX_LABEL;
1697
1698     REPLY_MACRO2(VL_API_L2_FLAGS_REPLY, rmp->resulting_feature_bitmap = ntohl(rbm));
1699 }
1700
1701 static void
1702 vl_api_bridge_flags_t_handler (
1703     vl_api_bridge_flags_t *mp)
1704 {
1705     vlib_main_t *vm  = vlib_get_main();
1706     bd_main_t * bdm = &bd_main;
1707     vl_api_bridge_flags_reply_t * rmp;
1708     int rv = 0;
1709     u32 bd_id = ntohl(mp->bd_id);
1710     u32 bd_index;
1711     u32 flags = ntohl(mp->feature_bitmap);
1712     uword * p;
1713
1714     p = hash_get (bdm->bd_index_by_bd_id, bd_id);
1715     if (p == 0) {
1716         rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1717         goto out;
1718     }
1719
1720     bd_index = p[0];
1721
1722     bd_set_flags(vm, bd_index, flags, mp->is_set);
1723
1724 out:
1725     REPLY_MACRO2(VL_API_BRIDGE_FLAGS_REPLY,
1726                  rmp->resulting_feature_bitmap = ntohl(flags));
1727 }
1728
1729 static void
1730 vl_api_bd_ip_mac_add_del_t_handler (
1731     vl_api_bd_ip_mac_add_del_t *mp)
1732 {
1733     bd_main_t * bdm = &bd_main;
1734     vl_api_bd_ip_mac_add_del_reply_t * rmp;
1735     int rv = 0;
1736     u32 bd_id = ntohl(mp->bd_id);
1737     u32 bd_index;
1738     uword * p;
1739
1740     p = hash_get (bdm->bd_index_by_bd_id, bd_id);
1741     if (p == 0) {
1742         rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1743         goto out;
1744     }
1745
1746     bd_index = p[0];
1747     if (bd_add_del_ip_mac(bd_index,  mp->ip_address,
1748                           mp->mac_address, mp->is_ipv6, mp->is_add))
1749         rv = VNET_API_ERROR_UNSPECIFIED;
1750
1751 out:
1752     REPLY_MACRO(VL_API_BD_IP_MAC_ADD_DEL_REPLY);
1753 }
1754
1755 static void
1756 vl_api_tap_connect_t_handler (vl_api_tap_connect_t *mp, vlib_main_t *vm)
1757 {
1758     int rv;
1759     vl_api_tap_connect_reply_t * rmp;
1760     unix_shared_memory_queue_t * q;
1761     u32 sw_if_index = (u32)~0;
1762
1763     rv = vnet_tap_connect_renumber (vm, mp->tap_name,
1764                            mp->use_random_mac ? 0 : mp->mac_address,
1765                            &sw_if_index, mp->renumber,
1766                            ntohl(mp->custom_dev_instance));
1767
1768     q = vl_api_client_index_to_input_queue (mp->client_index);
1769     if (!q)
1770         return;
1771
1772     rmp = vl_msg_api_alloc (sizeof (*rmp));
1773     rmp->_vl_msg_id = ntohs(VL_API_TAP_CONNECT_REPLY);
1774     rmp->context = mp->context;
1775     rmp->retval = ntohl(rv);
1776     rmp->sw_if_index = ntohl(sw_if_index);
1777
1778     vl_msg_api_send_shmem (q, (u8 *)&rmp);
1779 }
1780
1781 static void
1782 vl_api_tap_modify_t_handler (vl_api_tap_modify_t *mp, vlib_main_t *vm)
1783 {
1784     int rv;
1785     vl_api_tap_modify_reply_t * rmp;
1786     unix_shared_memory_queue_t * q;
1787     u32 sw_if_index = (u32)~0;
1788
1789     rv = vnet_tap_modify (vm, ntohl(mp->sw_if_index), mp->tap_name,
1790                            mp->use_random_mac ? 0 : mp->mac_address,
1791                            &sw_if_index, mp->renumber,
1792                            ntohl(mp->custom_dev_instance));
1793
1794     q = vl_api_client_index_to_input_queue (mp->client_index);
1795     if (!q)
1796         return;
1797
1798     rmp = vl_msg_api_alloc (sizeof (*rmp));
1799     rmp->_vl_msg_id = ntohs(VL_API_TAP_MODIFY_REPLY);
1800     rmp->context = mp->context;
1801     rmp->retval = ntohl(rv);
1802     rmp->sw_if_index = ntohl(sw_if_index);
1803
1804     vl_msg_api_send_shmem (q, (u8 *)&rmp);
1805 }
1806
1807 static void
1808 vl_api_tap_delete_t_handler (vl_api_tap_delete_t *mp, vlib_main_t *vm)
1809 {
1810     int rv;
1811     vpe_api_main_t * vam = &vpe_api_main;
1812     vl_api_tap_delete_reply_t * rmp;
1813     unix_shared_memory_queue_t * q;
1814     u32 sw_if_index = ntohl(mp->sw_if_index);
1815
1816     rv = vnet_tap_delete (vm, sw_if_index);
1817
1818     q = vl_api_client_index_to_input_queue (mp->client_index);
1819     if (!q)
1820         return;
1821
1822     rmp = vl_msg_api_alloc (sizeof (*rmp));
1823     rmp->_vl_msg_id = ntohs(VL_API_TAP_DELETE_REPLY);
1824     rmp->context = mp->context;
1825     rmp->retval = ntohl(rv);
1826
1827     vl_msg_api_send_shmem (q, (u8 *)&rmp);
1828
1829     if (!rv)
1830         send_sw_interface_flags_deleted (vam, q, sw_if_index);
1831 }
1832
1833 static void
1834 vl_api_create_vlan_subif_t_handler (vl_api_create_vlan_subif_t * mp)
1835 {
1836     vl_api_create_vlan_subif_reply_t * rmp;
1837     vnet_main_t * vnm = vnet_get_main();
1838     u32 hw_if_index, sw_if_index = (u32)~0;
1839     vnet_hw_interface_t * hi;
1840     int rv = 0;
1841     u32 id;
1842     vnet_sw_interface_t template;
1843     uword * p;
1844     vnet_interface_main_t * im = &vnm->interface_main;
1845     u64 sup_and_sub_key;
1846     u64 * kp;
1847     unix_shared_memory_queue_t * q;
1848     clib_error_t * error;
1849
1850     VALIDATE_SW_IF_INDEX(mp);
1851
1852     hw_if_index = ntohl(mp->sw_if_index);
1853     hi = vnet_get_hw_interface (vnm, hw_if_index);
1854
1855     id = ntohl(mp->vlan_id);
1856     if (id == 0 || id > 4095) {
1857         rv = VNET_API_ERROR_INVALID_VLAN;
1858         goto out;
1859     }
1860
1861     sup_and_sub_key = ((u64)(hi->sw_if_index) << 32) | (u64) id;
1862
1863     p = hash_get_mem (im->sw_if_index_by_sup_and_sub, &sup_and_sub_key);
1864     if (p) {
1865         rv = VNET_API_ERROR_VLAN_ALREADY_EXISTS;
1866         goto out;
1867     }
1868
1869     kp = clib_mem_alloc (sizeof (*kp));
1870     *kp = sup_and_sub_key;
1871
1872     memset (&template, 0, sizeof (template));
1873     template.type = VNET_SW_INTERFACE_TYPE_SUB;
1874     template.sup_sw_if_index = hi->sw_if_index;
1875     template.sub.id = id;
1876     template.sub.eth.raw_flags = 0;
1877     template.sub.eth.flags.one_tag = 1;
1878     template.sub.eth.outer_vlan_id = id;
1879     template.sub.eth.flags.exact_match = 1;
1880
1881     error = vnet_create_sw_interface (vnm, &template, &sw_if_index);
1882     if (error) {
1883         clib_error_report(error);
1884         rv = VNET_API_ERROR_INVALID_REGISTRATION;
1885         goto out;
1886     }
1887     hash_set (hi->sub_interface_sw_if_index_by_id, id, sw_if_index);
1888     hash_set_mem (im->sw_if_index_by_sup_and_sub, kp, sw_if_index);
1889
1890     BAD_SW_IF_INDEX_LABEL;
1891
1892 out:
1893     q = vl_api_client_index_to_input_queue (mp->client_index);
1894     if (!q)
1895         return;
1896
1897     rmp = vl_msg_api_alloc (sizeof (*rmp));
1898     rmp->_vl_msg_id = ntohs(VL_API_CREATE_VLAN_SUBIF_REPLY);
1899     rmp->context = mp->context;
1900     rmp->retval = ntohl(rv);
1901     rmp->sw_if_index = ntohl(sw_if_index);
1902     vl_msg_api_send_shmem (q, (u8 *)&rmp);
1903 }
1904
1905 static void
1906 vl_api_create_subif_t_handler (vl_api_create_subif_t * mp)
1907 {
1908     vl_api_create_subif_reply_t * rmp;
1909     vnet_main_t * vnm = vnet_get_main();
1910     u32 sw_if_index = ~0;
1911     int rv = 0;
1912     u32 sub_id;
1913     vnet_sw_interface_t *si;
1914     vnet_hw_interface_t *hi;
1915     vnet_sw_interface_t template;
1916     uword * p;
1917     vnet_interface_main_t * im = &vnm->interface_main;
1918     u64 sup_and_sub_key;
1919     u64 * kp;
1920     clib_error_t * error;
1921
1922     VALIDATE_SW_IF_INDEX(mp);
1923
1924     si = vnet_get_sup_sw_interface (vnm, ntohl(mp->sw_if_index));
1925     hi = vnet_get_sup_hw_interface (vnm, ntohl(mp->sw_if_index));
1926
1927     if (hi->bond_info == VNET_HW_INTERFACE_BOND_INFO_SLAVE) {
1928          rv = VNET_API_ERROR_BOND_SLAVE_NOT_ALLOWED;
1929         goto out;
1930     }
1931
1932     sw_if_index = si->sw_if_index;
1933     sub_id = ntohl(mp->sub_id);
1934
1935     sup_and_sub_key = ((u64)(sw_if_index) << 32) | (u64) sub_id;
1936
1937     p = hash_get_mem (im->sw_if_index_by_sup_and_sub, &sup_and_sub_key);
1938     if (p) {
1939         if (CLIB_DEBUG > 0)
1940             clib_warning ("sup sw_if_index %d, sub id %d already exists\n",
1941                           sw_if_index, sub_id);
1942         rv = VNET_API_ERROR_SUBIF_ALREADY_EXISTS;
1943         goto out;
1944     }
1945
1946     kp = clib_mem_alloc (sizeof (*kp));
1947     *kp = sup_and_sub_key;
1948
1949     memset (&template, 0, sizeof (template));
1950     template.type = VNET_SW_INTERFACE_TYPE_SUB;
1951     template.sup_sw_if_index = sw_if_index;
1952     template.sub.id = sub_id;
1953     template.sub.eth.flags.no_tags = mp->no_tags;
1954     template.sub.eth.flags.one_tag = mp->one_tag;
1955     template.sub.eth.flags.two_tags = mp->two_tags;
1956     template.sub.eth.flags.dot1ad = mp->dot1ad;
1957     template.sub.eth.flags.exact_match = mp->exact_match;
1958     template.sub.eth.flags.default_sub = mp->default_sub;
1959     template.sub.eth.flags.outer_vlan_id_any = mp->outer_vlan_id_any;
1960     template.sub.eth.flags.inner_vlan_id_any = mp->inner_vlan_id_any;
1961     template.sub.eth.outer_vlan_id = ntohs(mp->outer_vlan_id);
1962     template.sub.eth.inner_vlan_id = ntohs(mp->inner_vlan_id);
1963
1964     error = vnet_create_sw_interface (vnm, &template, &sw_if_index);
1965     if (error) {
1966         clib_error_report (error);
1967         rv = VNET_API_ERROR_SUBIF_CREATE_FAILED;
1968         goto out;
1969     }
1970
1971     hash_set (hi->sub_interface_sw_if_index_by_id, sub_id, sw_if_index);
1972     hash_set_mem (im->sw_if_index_by_sup_and_sub, kp, sw_if_index);
1973
1974     BAD_SW_IF_INDEX_LABEL;
1975
1976 out:
1977
1978     REPLY_MACRO2(VL_API_CREATE_SUBIF_REPLY,
1979     ({
1980         rmp->sw_if_index = ntohl(sw_if_index);
1981     }));
1982 }
1983
1984 static void
1985 vl_api_mpls_gre_add_del_tunnel_t_handler (vl_api_mpls_gre_add_del_tunnel_t *mp)
1986 {
1987     vl_api_mpls_gre_add_del_tunnel_reply_t * rmp;
1988     int rv = 0;
1989     stats_main_t * sm = &stats_main;
1990     u32 tunnel_sw_if_index = ~0;
1991
1992     dslock (sm, 1 /* release hint */, 5 /* tag */);
1993
1994     rv = vnet_mpls_gre_add_del_tunnel ((ip4_address_t *)(mp->src_address),
1995                                        (ip4_address_t *)(mp->dst_address),
1996                                        (ip4_address_t *)(mp->intfc_address),
1997                                        (u32)(mp->intfc_address_length),
1998                                        ntohl(mp->inner_vrf_id),
1999                                        ntohl(mp->outer_vrf_id),
2000                                        &tunnel_sw_if_index,
2001                                        mp->l2_only,
2002                                        mp->is_add);
2003     dsunlock (sm);
2004
2005     REPLY_MACRO2(VL_API_MPLS_GRE_ADD_DEL_TUNNEL_REPLY,
2006     ({
2007         rmp->tunnel_sw_if_index = ntohl(tunnel_sw_if_index);
2008     }));
2009 }
2010
2011 static void
2012 vl_api_mpls_ethernet_add_del_tunnel_t_handler
2013 (vl_api_mpls_ethernet_add_del_tunnel_t *mp)
2014 {
2015     vl_api_mpls_ethernet_add_del_tunnel_reply_t * rmp;
2016     int rv = 0;
2017     stats_main_t * sm = &stats_main;
2018     u32 tunnel_sw_if_index;
2019
2020     dslock (sm, 1 /* release hint */, 5 /* tag */);
2021
2022     rv = vnet_mpls_ethernet_add_del_tunnel
2023         (mp->dst_mac_address, (ip4_address_t *)(mp->adj_address),
2024          (u32)(mp->adj_address_length), ntohl(mp->vrf_id),
2025          ntohl(mp->tx_sw_if_index),
2026          &tunnel_sw_if_index,
2027          mp->l2_only,
2028          mp->is_add);
2029
2030     dsunlock (sm);
2031
2032     REPLY_MACRO2(VL_API_MPLS_ETHERNET_ADD_DEL_TUNNEL_REPLY,
2033     ({
2034         rmp->tunnel_sw_if_index = ntohl(tunnel_sw_if_index);
2035     }));
2036 }
2037
2038 /*
2039  * This piece of misery brought to you because the control-plane
2040  * can't figure out the tx interface + dst-mac address all by itself
2041  */
2042 static int mpls_ethernet_add_del_tunnel_2_t_handler
2043 (vl_api_mpls_ethernet_add_del_tunnel_2_t *mp)
2044 {
2045     pending_route_t * pr;
2046     vl_api_mpls_ethernet_add_del_tunnel_2_t *pme;
2047     vnet_main_t * vnm = vnet_get_main();
2048     vlib_main_t * vm = vlib_get_main();
2049     stats_main_t * sm = &stats_main;
2050     vpe_api_main_t * vam = &vpe_api_main;
2051     u32 inner_fib_index, outer_fib_index;
2052     ip4_main_t * im = &ip4_main;
2053     ip_lookup_main_t * lm = &im->lookup_main;
2054     ip_adjacency_t * adj = 0;
2055     u32 lookup_result;
2056     u32 tx_sw_if_index;
2057     u8 * dst_mac_address;
2058     clib_error_t * e;
2059     uword * p;
2060     int rv;
2061     u32 tunnel_sw_if_index;
2062
2063     p = hash_get (im->fib_index_by_table_id, ntohl(mp->outer_vrf_id));
2064     if (!p)
2065         return VNET_API_ERROR_NO_SUCH_FIB;
2066     else
2067         outer_fib_index = p[0];
2068
2069
2070     p = hash_get (im->fib_index_by_table_id, ntohl(mp->inner_vrf_id));
2071     if (!p)
2072         return VNET_API_ERROR_NO_SUCH_INNER_FIB;
2073     else
2074         inner_fib_index = p[0];
2075
2076     if (inner_fib_index == outer_fib_index)
2077         return VNET_API_ERROR_INVALID_VALUE;
2078
2079     lookup_result = ip4_fib_lookup_with_table
2080         (im, outer_fib_index,
2081          (ip4_address_t *)mp->next_hop_ip4_address_in_outer_vrf,
2082          1 /* disable default route */);
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         if (adj->lookup_next_index == IP_LOOKUP_NEXT_ARP) {
2089             pool_get (vam->pending_routes, pr);
2090             pr->resolve_type = RESOLVE_MPLS_ETHERNET_ADD_DEL;
2091             pme = &pr->t;
2092             clib_memcpy (pme, mp, sizeof (*pme));
2093             /* recursion block, "just in case" */
2094             pme->resolve_if_needed = 0;
2095             pme->resolve_attempts = ntohl(mp->resolve_attempts);
2096             pme->resolve_opaque = tx_sw_if_index;
2097             vnet_register_ip4_arp_resolution_event
2098                 (vnm,
2099                  (ip4_address_t *)&(pme->next_hop_ip4_address_in_outer_vrf),
2100                  vpe_resolver_process_node.index,
2101                  RESOLUTION_EVENT, pr - vam->pending_routes);
2102
2103             vlib_process_signal_event
2104                 (vm, vpe_resolver_process_node.index,
2105                  RESOLUTION_PENDING_EVENT, 0 /* data */);
2106
2107             /* The interface may be down, etc. */
2108             e = ip4_probe_neighbor
2109                 (vm, (ip4_address_t *)&(mp->next_hop_ip4_address_in_outer_vrf),
2110                  tx_sw_if_index);
2111
2112             if (e)
2113                 clib_error_report(e);
2114
2115             return VNET_API_ERROR_IN_PROGRESS;
2116         }
2117     }
2118
2119     if (adj->lookup_next_index != IP_LOOKUP_NEXT_REWRITE)
2120         return VNET_API_ERROR_NEXT_HOP_NOT_IN_FIB;
2121
2122     dst_mac_address =
2123         vnet_rewrite_get_data_internal
2124         (&adj->rewrite_header, sizeof (adj->rewrite_data));
2125
2126     dslock (sm, 1 /* release hint */, 10 /* tag */);
2127
2128     rv = vnet_mpls_ethernet_add_del_tunnel
2129         (dst_mac_address, (ip4_address_t *)(mp->adj_address),
2130          (u32)(mp->adj_address_length), ntohl(mp->inner_vrf_id),
2131          tx_sw_if_index, &tunnel_sw_if_index, mp->l2_only, mp->is_add);
2132
2133     dsunlock (sm);
2134
2135     return rv;
2136 }
2137
2138 static void
2139 vl_api_mpls_ethernet_add_del_tunnel_2_t_handler
2140 (vl_api_mpls_ethernet_add_del_tunnel_2_t *mp)
2141 {
2142     vl_api_mpls_ethernet_add_del_tunnel_reply_t * rmp;
2143     int rv = 0;
2144
2145     rv = mpls_ethernet_add_del_tunnel_2_t_handler (mp);
2146
2147     REPLY_MACRO(VL_API_MPLS_ETHERNET_ADD_DEL_TUNNEL_2_REPLY);
2148 }
2149
2150
2151 static void
2152 vl_api_mpls_add_del_encap_t_handler (vl_api_mpls_add_del_encap_t *mp)
2153 {
2154     vl_api_mpls_add_del_encap_reply_t * rmp;
2155     int rv;
2156     static u32 * labels;
2157     int i;
2158
2159     vec_reset_length (labels);
2160
2161     for (i = 0; i < mp->nlabels; i++)
2162         vec_add1 (labels, ntohl(mp->labels[i]));
2163
2164     /* $$$$ fixme */
2165     rv = vnet_mpls_add_del_encap ((ip4_address_t *)mp->dst_address,
2166                                   ntohl(mp->vrf_id), labels,
2167                                   ~0 /* policy_tunnel_index */,
2168                                   0 /* no_dst_hash */,
2169                                   0 /* indexp */,
2170                                   mp->is_add);
2171
2172     REPLY_MACRO(VL_API_MPLS_ADD_DEL_ENCAP_REPLY);
2173 }
2174
2175 static void
2176 vl_api_mpls_add_del_decap_t_handler
2177 (vl_api_mpls_add_del_decap_t *mp)
2178 {
2179     vl_api_mpls_add_del_decap_reply_t * rmp;
2180     int rv;
2181
2182     rv = vnet_mpls_add_del_decap (ntohl(mp->rx_vrf_id), ntohl(mp->tx_vrf_id),
2183                                   ntohl(mp->label), ntohl(mp->next_index),
2184                                   mp->s_bit, mp->is_add);
2185
2186     REPLY_MACRO(VL_API_MPLS_ADD_DEL_DECAP_REPLY);
2187 }
2188
2189 static void
2190 vl_api_proxy_arp_add_del_t_handler (vl_api_proxy_arp_add_del_t *mp)
2191 {
2192     vl_api_proxy_arp_add_del_reply_t * rmp;
2193     u32 fib_index;
2194     int rv;
2195     ip4_main_t * im = &ip4_main;
2196     stats_main_t * sm = &stats_main;
2197     int vnet_proxy_arp_add_del (ip4_address_t *lo_addr,
2198                                 ip4_address_t *hi_addr,
2199                                 u32 fib_index, int is_del);
2200     uword * p;
2201
2202     dslock (sm, 1 /* release hint */, 6 /* tag */);
2203
2204     p = hash_get (im->fib_index_by_table_id, ntohl(mp->vrf_id));
2205
2206     if (! p) {
2207         rv = VNET_API_ERROR_NO_SUCH_FIB;
2208         goto out;
2209     }
2210
2211     fib_index = p[0];
2212
2213     rv = vnet_proxy_arp_add_del ((ip4_address_t *)mp->low_address,
2214                                  (ip4_address_t *)mp->hi_address,
2215                                  fib_index, mp->is_add == 0);
2216
2217 out:
2218     dsunlock (sm);
2219     REPLY_MACRO(VL_API_PROXY_ARP_ADD_DEL_REPLY);
2220 }
2221
2222 static void
2223 vl_api_proxy_arp_intfc_enable_disable_t_handler
2224 (vl_api_proxy_arp_intfc_enable_disable_t *mp)
2225 {
2226     int rv = 0;
2227     vnet_main_t * vnm = vnet_get_main();
2228     vl_api_proxy_arp_intfc_enable_disable_reply_t *rmp;
2229     vnet_sw_interface_t * si;
2230     u32 sw_if_index;
2231
2232     VALIDATE_SW_IF_INDEX(mp);
2233
2234     sw_if_index = ntohl(mp->sw_if_index);
2235
2236     if (pool_is_free_index (vnm->interface_main.sw_interfaces,
2237                             sw_if_index)) {
2238         rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
2239         goto out;
2240     }
2241
2242     si = vnet_get_sw_interface (vnm, sw_if_index);
2243
2244     ASSERT(si);
2245
2246     if (mp->enable_disable)
2247         si->flags |= VNET_SW_INTERFACE_FLAG_PROXY_ARP;
2248     else
2249         si->flags &= ~VNET_SW_INTERFACE_FLAG_PROXY_ARP;
2250
2251     BAD_SW_IF_INDEX_LABEL;
2252
2253     out:
2254     REPLY_MACRO(VL_API_PROXY_ARP_INTFC_ENABLE_DISABLE_REPLY);
2255 }
2256
2257 static void
2258 vl_api_ip_neighbor_add_del_t_handler (vl_api_ip_neighbor_add_del_t *mp, vlib_main_t * vm)
2259 {
2260     vl_api_ip_neighbor_add_del_reply_t * rmp;
2261     vnet_main_t * vnm = vnet_get_main();
2262     u32 fib_index;
2263     int rv=0;
2264     stats_main_t * sm = &stats_main;
2265
2266     VALIDATE_SW_IF_INDEX(mp);
2267
2268     dslock (sm, 1 /* release hint */, 7 /* tag */);
2269
2270     if (mp->is_ipv6) {
2271         if (mp->is_add)
2272             rv = vnet_set_ip6_ethernet_neighbor
2273                 (vm, ntohl(mp->sw_if_index),
2274                  (ip6_address_t *)(mp->dst_address),
2275                  mp->mac_address, sizeof (mp->mac_address), mp->is_static);
2276         else
2277             rv = vnet_unset_ip6_ethernet_neighbor
2278                 (vm, ntohl(mp->sw_if_index),
2279                  (ip6_address_t *)(mp->dst_address),
2280                  mp->mac_address, sizeof(mp->mac_address));
2281     } else {
2282         ip4_main_t * im = &ip4_main;
2283         ip_lookup_main_t * lm = &im->lookup_main;
2284         ethernet_arp_ip4_over_ethernet_address_t a;
2285         u32 ai;
2286         ip_adjacency_t *nh_adj;
2287
2288         uword * p = hash_get (im->fib_index_by_table_id, ntohl(mp->vrf_id));
2289         if (! p) {
2290             rv = VNET_API_ERROR_NO_SUCH_FIB;
2291             goto out;
2292         }
2293         fib_index = p[0];
2294
2295         /*
2296          * Unfortunately, folks have a penchant for
2297          * adding interface addresses to the ARP cache, and
2298          * wondering why the forwarder eventually ASSERTs...
2299          */
2300         ai = ip4_fib_lookup_with_table
2301             (im, fib_index, (ip4_address_t *)(mp->dst_address),
2302              1 /* disable default route */);
2303
2304         if (ai != 0) {
2305             nh_adj = ip_get_adjacency (lm, ai);
2306             /* Never allow manipulation of a local adj! */
2307             if (nh_adj->lookup_next_index == IP_LOOKUP_NEXT_LOCAL) {
2308                 clib_warning("%U matches local adj",
2309                              format_ip4_address,
2310                              (ip4_address_t *)(mp->dst_address));
2311                 rv = VNET_API_ERROR_ADDRESS_MATCHES_INTERFACE_ADDRESS;
2312                 goto out;
2313             }
2314         }
2315
2316         clib_memcpy (&a.ethernet, mp->mac_address, 6);
2317         clib_memcpy (&a.ip4, mp->dst_address, 4);
2318
2319         if (mp->is_add)
2320             rv = vnet_arp_set_ip4_over_ethernet (vnm, ntohl(mp->sw_if_index),
2321                                                  fib_index, &a, mp->is_static);
2322         else
2323             rv = vnet_arp_unset_ip4_over_ethernet (vnm, ntohl(mp->sw_if_index),
2324                                                    fib_index, &a);
2325     }
2326
2327     BAD_SW_IF_INDEX_LABEL;
2328     out:
2329     dsunlock (sm);
2330     REPLY_MACRO(VL_API_IP_NEIGHBOR_ADD_DEL_REPLY);
2331 }
2332
2333 static void
2334 vl_api_is_address_reachable_t_handler (vl_api_is_address_reachable_t *mp)
2335 {
2336 #if 0
2337     vpe_main_t *rm = &vpe_main;
2338     ip4_main_t *im4 = &ip4_main;
2339     ip6_main_t *im6 = &ip6_main;
2340     ip_lookup_main_t * lm;
2341     union {
2342         ip4_address_t ip4;
2343         ip6_address_t ip6;
2344     } addr;
2345     u32 adj_index, sw_if_index;
2346     vl_api_is_address_reachable_t *rmp;
2347     ip_adjacency_t * adj;
2348     unix_shared_memory_queue_t *q;
2349
2350     q = vl_api_client_index_to_input_queue (mp->client_index);
2351     if (!q) {
2352         increment_missing_api_client_counter (rm->vlib_main);
2353         return;
2354     }
2355
2356     rmp = vl_msg_api_alloc (sizeof (*rmp));
2357     clib_memcpy (rmp, mp, sizeof (*rmp));
2358
2359     sw_if_index = mp->next_hop_sw_if_index;
2360     clib_memcpy (&addr, mp->address, sizeof (addr));
2361     if (mp->is_ipv6) {
2362         lm = &im6->lookup_main;
2363         adj_index =
2364             ip6_fib_lookup (im6, sw_if_index, &addr.ip6);
2365     } else {
2366         lm = &im4->lookup_main;
2367         adj_index =
2368             ip4_fib_lookup (im4, sw_if_index, &addr.ip4);
2369     }
2370     if (adj_index == ~0) {
2371         rmp->is_error = 1;
2372         goto send;
2373     }
2374     adj = ip_get_adjacency (lm, adj_index);
2375
2376     if (adj->lookup_next_index == IP_LOOKUP_NEXT_REWRITE
2377         && adj->rewrite_header.sw_if_index == sw_if_index) {
2378         rmp->is_known = 1;
2379     } else {
2380         if (adj->lookup_next_index == IP_LOOKUP_NEXT_ARP
2381             && adj->rewrite_header.sw_if_index == sw_if_index) {
2382             if (mp->is_ipv6)
2383                 ip6_probe_neighbor (rm->vlib_main, &addr.ip6, sw_if_index);
2384             else
2385                 ip4_probe_neighbor (rm->vlib_main, &addr.ip4, sw_if_index);
2386         } else if (adj->lookup_next_index == IP_LOOKUP_NEXT_DROP) {
2387             rmp->is_known = 1;
2388             goto send;
2389         }
2390         rmp->is_known = 0;
2391     }
2392
2393 send:
2394     vl_msg_api_send_shmem (q, (u8 *)&rmp);
2395 #endif
2396 }
2397
2398 static void vl_api_sw_interface_details_t_handler (
2399     vl_api_sw_interface_details_t * mp)
2400 {
2401     clib_warning ("BUG");
2402 }
2403
2404 static void vl_api_sw_interface_set_flags_t_handler (
2405     vl_api_sw_interface_set_flags_t * mp)
2406 {
2407    vl_api_sw_interface_set_flags_reply_t *rmp;
2408    vnet_main_t * vnm = vnet_get_main();
2409    int rv = 0;
2410    clib_error_t * error;
2411    u16 flags;
2412
2413    VALIDATE_SW_IF_INDEX(mp);
2414
2415    flags = mp->admin_up_down ? VNET_SW_INTERFACE_FLAG_ADMIN_UP : 0;
2416
2417    error = vnet_sw_interface_set_flags (vnm,
2418                                         ntohl(mp->sw_if_index),
2419                                         flags);
2420    if (error) {
2421        rv = -1;
2422        clib_error_report (error);
2423    }
2424
2425    BAD_SW_IF_INDEX_LABEL;
2426    REPLY_MACRO(VL_API_SW_INTERFACE_SET_FLAGS_REPLY);
2427 }
2428
2429 static void vl_api_sw_interface_clear_stats_t_handler (
2430     vl_api_sw_interface_clear_stats_t * mp)
2431 {
2432    vl_api_sw_interface_clear_stats_reply_t *rmp;
2433
2434    vnet_main_t * vnm = vnet_get_main();
2435    vnet_interface_main_t * im = &vnm->interface_main;
2436    vlib_simple_counter_main_t * sm;
2437    vlib_combined_counter_main_t * cm;
2438    static vnet_main_t ** my_vnet_mains;
2439    int i, j, n_counters;
2440
2441    int rv = 0;
2442
2443    vec_reset_length (my_vnet_mains);
2444
2445    for (i = 0; i < vec_len (vnet_mains); i++)
2446      {
2447        if (vnet_mains[i])
2448          vec_add1 (my_vnet_mains, vnet_mains[i]);
2449      }
2450
2451    if (vec_len (vnet_mains) == 0)
2452      vec_add1 (my_vnet_mains, vnm);
2453
2454    n_counters = vec_len (im->combined_sw_if_counters);
2455
2456    for (j = 0; j < n_counters; j++)
2457      {
2458        for (i = 0; i < vec_len(my_vnet_mains); i++)
2459          {
2460            im = &my_vnet_mains[i]->interface_main;
2461            cm = im->combined_sw_if_counters + j;
2462            if (mp->sw_if_index == (u32)~0)
2463              vlib_clear_combined_counters (cm);
2464            else
2465              vlib_zero_combined_counter (cm, ntohl(mp->sw_if_index));
2466          }
2467      }
2468
2469    n_counters = vec_len (im->sw_if_counters);
2470
2471    for (j = 0; j < n_counters; j++)
2472      {
2473        for (i = 0; i < vec_len(my_vnet_mains); i++)
2474          {
2475            im = &my_vnet_mains[i]->interface_main;
2476            sm = im->sw_if_counters + j;
2477            if (mp->sw_if_index == (u32)~0)
2478              vlib_clear_simple_counters (sm);
2479            else
2480              vlib_zero_simple_counter (sm, ntohl(mp->sw_if_index));
2481          }
2482      }
2483
2484    REPLY_MACRO(VL_API_SW_INTERFACE_CLEAR_STATS_REPLY);
2485 }
2486
2487 static void send_sw_interface_details (vpe_api_main_t * am,
2488                                        unix_shared_memory_queue_t *q,
2489                                        vnet_sw_interface_t * swif,
2490                                        u8 * interface_name,
2491                                        u32 context)
2492 {
2493     vl_api_sw_interface_details_t * mp;
2494     vnet_hw_interface_t * hi;
2495
2496     hi = vnet_get_sup_hw_interface (am->vnet_main, swif->sw_if_index);
2497
2498     mp = vl_msg_api_alloc (sizeof (*mp));
2499     memset (mp, 0, sizeof (*mp));
2500     mp->_vl_msg_id = ntohs(VL_API_SW_INTERFACE_DETAILS);
2501     mp->sw_if_index = ntohl(swif->sw_if_index);
2502     mp->sup_sw_if_index = ntohl(swif->sup_sw_if_index);
2503     mp->admin_up_down = (swif->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ?
2504         1 : 0;
2505     mp->link_up_down = (hi->flags & VNET_HW_INTERFACE_FLAG_LINK_UP) ?
2506         1 : 0;
2507     mp->link_duplex = ((hi->flags & VNET_HW_INTERFACE_FLAG_DUPLEX_MASK) >>
2508                        VNET_HW_INTERFACE_FLAG_DUPLEX_SHIFT);
2509     mp->link_speed = ((hi->flags & VNET_HW_INTERFACE_FLAG_SPEED_MASK) >>
2510                       VNET_HW_INTERFACE_FLAG_SPEED_SHIFT);
2511     mp->link_mtu = ntohs(hi->max_packet_bytes);
2512     mp->context = context;
2513
2514     strncpy ((char *) mp->interface_name,
2515              (char *) interface_name, ARRAY_LEN(mp->interface_name)-1);
2516
2517     /* Send the L2 address for ethernet physical intfcs */
2518     if (swif->sup_sw_if_index == swif->sw_if_index
2519         && hi->hw_class_index == ethernet_hw_interface_class.index) {
2520         ethernet_main_t *em = ethernet_get_main (am->vlib_main);
2521         ethernet_interface_t *ei;
2522
2523         ei = pool_elt_at_index (em->interfaces, hi->hw_instance);
2524         ASSERT (sizeof (mp->l2_address) >= sizeof (ei->address));
2525         clib_memcpy (mp->l2_address, ei->address, sizeof (ei->address));
2526         mp->l2_address_length = ntohl(sizeof (ei->address));
2527     } else if (swif->sup_sw_if_index != swif->sw_if_index) {
2528         vnet_sub_interface_t *sub = &swif->sub;
2529         mp->sub_id = ntohl(sub->id);
2530         mp->sub_dot1ad = sub->eth.flags.dot1ad;
2531         mp->sub_number_of_tags = sub->eth.flags.one_tag + sub->eth.flags.two_tags*2;
2532         mp->sub_outer_vlan_id = ntohs(sub->eth.outer_vlan_id);
2533         mp->sub_inner_vlan_id = ntohs(sub->eth.inner_vlan_id);
2534         mp->sub_exact_match = sub->eth.flags.exact_match;
2535         mp->sub_default = sub->eth.flags.default_sub;
2536         mp->sub_outer_vlan_id_any = sub->eth.flags.outer_vlan_id_any;
2537         mp->sub_inner_vlan_id_any = sub->eth.flags.inner_vlan_id_any;
2538
2539         /* vlan tag rewrite data */
2540         u32 vtr_op = L2_VTR_DISABLED;
2541         u32 vtr_push_dot1q = 0, vtr_tag1 = 0, vtr_tag2 = 0;
2542
2543         if (l2vtr_get(am->vlib_main, am->vnet_main, swif->sw_if_index,
2544                       &vtr_op, &vtr_push_dot1q, &vtr_tag1, &vtr_tag2) != 0) {
2545             // error - default to disabled
2546             mp->vtr_op = ntohl(L2_VTR_DISABLED);
2547             clib_warning("cannot get vlan tag rewrite for sw_if_index %d",
2548                     swif->sw_if_index);
2549         } else {
2550             mp->vtr_op = ntohl(vtr_op);
2551             mp->vtr_push_dot1q = ntohl(vtr_push_dot1q);
2552             mp->vtr_tag1 = ntohl(vtr_tag1);
2553             mp->vtr_tag2 = ntohl(vtr_tag2);
2554         }
2555     }
2556
2557     vl_msg_api_send_shmem (q, (u8 *)&mp);
2558 }
2559
2560 static void send_sw_interface_flags (vpe_api_main_t * am,
2561                                      unix_shared_memory_queue_t *q,
2562                                      vnet_sw_interface_t * swif)
2563 {
2564     vl_api_sw_interface_set_flags_t *mp;
2565     vnet_main_t * vnm = am->vnet_main;
2566
2567     vnet_hw_interface_t *hi = vnet_get_sup_hw_interface (vnm,
2568                                                          swif->sw_if_index);
2569     mp = vl_msg_api_alloc (sizeof (*mp));
2570     memset (mp, 0, sizeof (*mp));
2571     mp->_vl_msg_id = ntohs(VL_API_SW_INTERFACE_SET_FLAGS);
2572     mp->sw_if_index = ntohl(swif->sw_if_index);
2573
2574     mp->admin_up_down = (swif->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ?
2575         1 : 0;
2576     mp->link_up_down = (hi->flags & VNET_HW_INTERFACE_FLAG_LINK_UP) ?
2577         1 : 0;
2578     vl_msg_api_send_shmem (q, (u8 *)&mp);
2579 }
2580
2581 static void send_sw_interface_flags_deleted (vpe_api_main_t * am,
2582                                      unix_shared_memory_queue_t *q,
2583                                              u32 sw_if_index)
2584     __attribute__((unused));
2585
2586 static void send_sw_interface_flags_deleted (vpe_api_main_t * am,
2587                                      unix_shared_memory_queue_t *q,
2588                                      u32 sw_if_index)
2589 {
2590     vl_api_sw_interface_set_flags_t *mp;
2591
2592     mp = vl_msg_api_alloc (sizeof (*mp));
2593     memset (mp, 0, sizeof (*mp));
2594     mp->_vl_msg_id = ntohs(VL_API_SW_INTERFACE_SET_FLAGS);
2595     mp->sw_if_index = ntohl(sw_if_index);
2596
2597     mp->admin_up_down = 0;
2598     mp->link_up_down = 0;
2599     mp->deleted = 1;
2600     vl_msg_api_send_shmem (q, (u8 *)&mp);
2601 }
2602
2603 static void vl_api_sw_interface_dump_t_handler (
2604     vl_api_sw_interface_dump_t *mp)
2605 {
2606     vpe_api_main_t * am = &vpe_api_main;
2607     vnet_sw_interface_t * swif;
2608     vnet_interface_main_t * im = &am->vnet_main->interface_main;
2609     u8 * filter_string = 0, * name_string = 0;
2610     unix_shared_memory_queue_t * q;
2611     char * strcasestr (char *, char *); /* lnx hdr file botch */
2612
2613     q = vl_api_client_index_to_input_queue (mp->client_index);
2614
2615     if (q == 0)
2616         return;
2617
2618     if (mp->name_filter_valid) {
2619         mp->name_filter [ARRAY_LEN(mp->name_filter)-1] = 0;
2620         filter_string = format (0, "%s%c", mp->name_filter, 0);
2621     }
2622
2623     pool_foreach (swif, im->sw_interfaces,
2624     ({
2625         name_string = format (name_string, "%U%c",
2626                               format_vnet_sw_interface_name,
2627                               am->vnet_main, swif, 0);
2628
2629         if (mp->name_filter_valid == 0 ||
2630             strcasestr((char *) name_string, (char *) filter_string)) {
2631
2632             send_sw_interface_details (am, q, swif, name_string, mp->context);
2633         }
2634         _vec_len (name_string) = 0;
2635     }));
2636
2637     vec_free (name_string);
2638     vec_free (filter_string);
2639 }
2640
2641 void send_oam_event (oam_target_t * t)
2642 {
2643     vpe_api_main_t * vam = &vpe_api_main;
2644     unix_shared_memory_queue_t * q;
2645     vpe_client_registration_t *reg;
2646     vl_api_oam_event_t * mp;
2647
2648     pool_foreach(reg, vam->oam_events_registrations,
2649     ({
2650         q = vl_api_client_index_to_input_queue (reg->client_index);
2651         if (q) {
2652             mp = vl_msg_api_alloc (sizeof (*mp));
2653             mp->_vl_msg_id = ntohs (VL_API_OAM_EVENT);
2654             clib_memcpy (mp->dst_address, &t->dst_address, sizeof (mp->dst_address));
2655             mp->state = t->state;
2656             vl_msg_api_send_shmem (q, (u8 *)&mp);
2657         }
2658     }));
2659 }
2660
2661 static void
2662 vl_api_oam_add_del_t_handler (vl_api_oam_add_del_t *mp)
2663 {
2664     vl_api_oam_add_del_reply_t * rmp;
2665     int rv;
2666
2667     rv = vpe_oam_add_del_target ((ip4_address_t *)mp->src_address,
2668                                  (ip4_address_t *)mp->dst_address,
2669                                  ntohl(mp->vrf_id),
2670                                  (int)(mp->is_add));
2671
2672     REPLY_MACRO(VL_API_OAM_ADD_DEL_REPLY);
2673 }
2674
2675 static void
2676 vl_api_vnet_get_summary_stats_t_handler (
2677     vl_api_vnet_get_summary_stats_t *mp)
2678 {
2679     stats_main_t * sm = &stats_main;
2680     vnet_interface_main_t * im = sm->interface_main;
2681     vl_api_vnet_summary_stats_reply_t *rmp;
2682     vlib_combined_counter_main_t * cm;
2683     vlib_counter_t v;
2684     int i, which;
2685     u64 total_pkts[VLIB_N_RX_TX];
2686     u64 total_bytes[VLIB_N_RX_TX];
2687
2688     unix_shared_memory_queue_t * q =
2689         vl_api_client_index_to_input_queue (mp->client_index);
2690
2691     if (!q)
2692         return;
2693
2694     rmp = vl_msg_api_alloc (sizeof (*rmp));
2695     rmp->_vl_msg_id = ntohs(VL_API_VNET_SUMMARY_STATS_REPLY);
2696     rmp->context = mp->context;
2697     rmp->retval = 0;
2698
2699     memset (total_pkts, 0, sizeof (total_pkts));
2700     memset (total_bytes, 0, sizeof (total_bytes));
2701
2702     vnet_interface_counter_lock (im);
2703
2704     vec_foreach (cm, im->combined_sw_if_counters) {
2705         which = cm - im->combined_sw_if_counters;
2706
2707         for (i = 0; i < vec_len (cm->maxi); i++) {
2708             vlib_get_combined_counter (cm, i, &v);
2709             total_pkts[which] += v.packets;
2710             total_bytes[which] += v.bytes;
2711         }
2712     }
2713     vnet_interface_counter_unlock (im);
2714
2715     /* Note: in HOST byte order! */
2716     rmp->total_pkts[VLIB_RX] = total_pkts[VLIB_RX];
2717     rmp->total_bytes[VLIB_RX] = total_bytes[VLIB_RX];
2718     rmp->total_pkts[VLIB_TX] = total_pkts[VLIB_TX];
2719     rmp->total_bytes[VLIB_TX] = total_bytes[VLIB_TX];
2720     rmp->vector_rate = vlib_last_vector_length_per_node (sm->vlib_main);
2721
2722     vl_msg_api_send_shmem (q, (u8 *)&rmp);
2723 }
2724
2725 typedef CLIB_PACKED (struct {
2726   ip4_address_t address;
2727
2728   u32 address_length : 6;
2729
2730   u32 index : 26;
2731 }) ip4_route_t;
2732
2733 static int ip4_reset_fib_t_handler (vl_api_reset_fib_t *mp)
2734 {
2735     vnet_main_t * vnm = vnet_get_main();
2736     vnet_interface_main_t * im = &vnm->interface_main;
2737     ip4_main_t * im4 = &ip4_main;
2738     static ip4_route_t * routes;
2739     static u32 * sw_if_indices_to_shut;
2740     stats_main_t * sm = &stats_main;
2741     ip4_route_t * r;
2742     ip4_fib_t * fib;
2743     u32 sw_if_index;
2744     int i;
2745     int rv = VNET_API_ERROR_NO_SUCH_FIB;
2746     u32 target_fib_id = ntohl(mp->vrf_id);
2747
2748     dslock (sm, 1 /* release hint */, 8 /* tag */);
2749
2750     vec_foreach (fib, im4->fibs) {
2751         vnet_sw_interface_t * si;
2752
2753         if (fib->table_id != target_fib_id)
2754             continue;
2755
2756         /* remove any mpls/gre tunnels in this fib */
2757         vnet_mpls_gre_delete_fib_tunnels (fib->table_id);
2758
2759         /* remove any mpls encap/decap labels */
2760         mpls_fib_reset_labels (fib->table_id);
2761
2762         /* remove any proxy arps in this fib */
2763         vnet_proxy_arp_fib_reset (fib->table_id);
2764
2765         /* Set the flow hash for this fib to the default */
2766         vnet_set_ip4_flow_hash (fib->table_id, IP_FLOW_HASH_DEFAULT);
2767
2768         vec_reset_length (sw_if_indices_to_shut);
2769
2770         /* Shut down interfaces in this FIB / clean out intfc routes */
2771         pool_foreach (si, im->sw_interfaces,
2772         ({
2773             u32 sw_if_index = si->sw_if_index;
2774
2775             if (sw_if_index < vec_len (im4->fib_index_by_sw_if_index)
2776                 && (im4->fib_index_by_sw_if_index[si->sw_if_index] ==
2777                     fib - im4->fibs))
2778                 vec_add1 (sw_if_indices_to_shut, si->sw_if_index);
2779         }));
2780
2781         for (i = 0; i < vec_len (sw_if_indices_to_shut); i++) {
2782             sw_if_index = sw_if_indices_to_shut[i];
2783             // vec_foreach (sw_if_index, sw_if_indices_to_shut) {
2784
2785             u32 flags = vnet_sw_interface_get_flags (vnm, sw_if_index);
2786             flags &= ~(VNET_SW_INTERFACE_FLAG_ADMIN_UP);
2787             vnet_sw_interface_set_flags (vnm, sw_if_index, flags);
2788         }
2789
2790         vec_reset_length (routes);
2791
2792         for (i = 0; i < ARRAY_LEN (fib->adj_index_by_dst_address); i++) {
2793             uword * hash = fib->adj_index_by_dst_address[i];
2794             hash_pair_t * p;
2795             ip4_route_t x;
2796
2797             x.address_length = i;
2798
2799             hash_foreach_pair (p, hash,
2800             ({
2801                 x.address.data_u32 = p->key;
2802                 vec_add1 (routes, x);
2803             }));
2804         }
2805
2806         vec_foreach (r, routes) {
2807             ip4_add_del_route_args_t a;
2808
2809             memset (&a, 0, sizeof (a));
2810             a.flags = IP4_ROUTE_FLAG_FIB_INDEX | IP4_ROUTE_FLAG_DEL;
2811             a.table_index_or_table_id = fib - im4->fibs;
2812             a.dst_address = r->address;
2813             a.dst_address_length = r->address_length;
2814             a.adj_index = ~0;
2815
2816             ip4_add_del_route (im4, &a);
2817             ip4_maybe_remap_adjacencies (im4, fib - im4->fibs,
2818                                          IP4_ROUTE_FLAG_FIB_INDEX);
2819         }
2820         rv = 0;
2821         break;
2822     } /* vec_foreach (fib) */
2823
2824     dsunlock(sm);
2825     return rv;
2826 }
2827
2828 typedef struct {
2829   ip6_address_t address;
2830   u32 address_length;
2831   u32 index;
2832 } ip6_route_t;
2833
2834 typedef struct {
2835   u32 fib_index;
2836   ip6_route_t ** routep;
2837 } add_routes_in_fib_arg_t;
2838
2839 static void add_routes_in_fib (clib_bihash_kv_24_8_t * kvp, void *arg)
2840 {
2841   add_routes_in_fib_arg_t * ap = arg;
2842
2843   if (kvp->key[2]>>32 == ap->fib_index)
2844     {
2845       ip6_address_t *addr;
2846       ip6_route_t * r;
2847       addr = (ip6_address_t *) kvp;
2848       vec_add2 (*ap->routep, r, 1);
2849       r->address = addr[0];
2850       r->address_length = kvp->key[2] & 0xFF;
2851       r->index = kvp->value;
2852     }
2853 }
2854
2855 static int ip6_reset_fib_t_handler (vl_api_reset_fib_t *mp)
2856 {
2857     vnet_main_t * vnm = vnet_get_main();
2858     vnet_interface_main_t * im = &vnm->interface_main;
2859     ip6_main_t * im6 = &ip6_main;
2860     stats_main_t * sm = &stats_main;
2861     static ip6_route_t * routes;
2862     static u32 * sw_if_indices_to_shut;
2863     ip6_route_t * r;
2864     ip6_fib_t * fib;
2865     u32 sw_if_index;
2866     int i;
2867     int rv = VNET_API_ERROR_NO_SUCH_FIB;
2868     u32 target_fib_id = ntohl(mp->vrf_id);
2869     add_routes_in_fib_arg_t _a, *a=&_a;
2870     clib_bihash_24_8_t * h = &im6->ip6_lookup_table;
2871
2872     dslock (sm, 1 /* release hint */, 9 /* tag */);
2873
2874     vec_foreach (fib, im6->fibs) {
2875         vnet_sw_interface_t * si;
2876
2877         if (fib->table_id != target_fib_id)
2878             continue;
2879
2880         vec_reset_length (sw_if_indices_to_shut);
2881
2882         /* Shut down interfaces in this FIB / clean out intfc routes */
2883         pool_foreach (si, im->sw_interfaces,
2884         ({
2885             if (im6->fib_index_by_sw_if_index[si->sw_if_index] ==
2886                 fib - im6->fibs)
2887                 vec_add1 (sw_if_indices_to_shut, si->sw_if_index);
2888         }));
2889
2890         for (i = 0; i < vec_len (sw_if_indices_to_shut); i++) {
2891             sw_if_index = sw_if_indices_to_shut[i];
2892             // vec_foreach (sw_if_index, sw_if_indices_to_shut) {
2893
2894             u32 flags = vnet_sw_interface_get_flags (vnm, sw_if_index);
2895             flags &= ~(VNET_SW_INTERFACE_FLAG_ADMIN_UP);
2896             vnet_sw_interface_set_flags (vnm, sw_if_index, flags);
2897         }
2898
2899         vec_reset_length (routes);
2900
2901         a->fib_index = fib - im6->fibs;
2902         a->routep = &routes;
2903
2904         clib_bihash_foreach_key_value_pair_24_8 (h, add_routes_in_fib, a);
2905
2906         vec_foreach (r, routes) {
2907             ip6_add_del_route_args_t a;
2908
2909             memset (&a, 0, sizeof (a));
2910             a.flags = IP6_ROUTE_FLAG_FIB_INDEX | IP6_ROUTE_FLAG_DEL;
2911             a.table_index_or_table_id = fib - im6->fibs;
2912             a.dst_address = r->address;
2913             a.dst_address_length = r->address_length;
2914             a.adj_index = ~0;
2915
2916             ip6_add_del_route (im6, &a);
2917             ip6_maybe_remap_adjacencies (im6, fib - im6->fibs,
2918                                          IP6_ROUTE_FLAG_FIB_INDEX);
2919         }
2920         rv = 0;
2921         /* Reinstall the neighbor / router discovery routes */
2922         vnet_ip6_fib_init (im6, fib - im6->fibs);
2923         break;
2924     } /* vec_foreach (fib) */
2925
2926     dsunlock(sm);
2927     return rv;
2928 }
2929
2930 static void vl_api_reset_fib_t_handler (vl_api_reset_fib_t *mp)
2931 {
2932     int rv;
2933     vl_api_reset_fib_reply_t * rmp;
2934
2935     if (mp->is_ipv6)
2936         rv = ip6_reset_fib_t_handler (mp);
2937     else
2938         rv = ip4_reset_fib_t_handler (mp);
2939
2940     REPLY_MACRO(VL_API_RESET_FIB_REPLY);
2941 }
2942
2943
2944 static void
2945 dhcpv4_proxy_config (vl_api_dhcp_proxy_config_t *mp)
2946 {
2947     vl_api_dhcp_proxy_config_reply_t * rmp;
2948     int rv;
2949
2950     rv = dhcp_proxy_set_server ((ip4_address_t *)(&mp->dhcp_server),
2951                                 (ip4_address_t *)(&mp->dhcp_src_address),
2952                                 (u32) ntohl(mp->vrf_id),
2953                                 (int) mp->insert_circuit_id,
2954                                 (int) (mp->is_add == 0));
2955
2956     REPLY_MACRO(VL_API_DHCP_PROXY_CONFIG_REPLY);
2957 }
2958
2959
2960 static void
2961 dhcpv6_proxy_config (vl_api_dhcp_proxy_config_t *mp)
2962 {
2963     vl_api_dhcp_proxy_config_reply_t * rmp;
2964     int rv = -1;
2965
2966     rv = dhcpv6_proxy_set_server ((ip6_address_t *)(&mp->dhcp_server),
2967                                 (ip6_address_t *)(&mp->dhcp_src_address),
2968                                 (u32) ntohl(mp->vrf_id),
2969                                 (int) mp->insert_circuit_id,
2970                                 (int) (mp->is_add == 0));
2971
2972     REPLY_MACRO(VL_API_DHCP_PROXY_CONFIG_REPLY);
2973 }
2974
2975 static void
2976 dhcpv4_proxy_config_2 (vl_api_dhcp_proxy_config_2_t *mp)
2977 {
2978     vl_api_dhcp_proxy_config_reply_t * rmp;
2979     int rv;
2980
2981     rv = dhcp_proxy_set_server_2 ((ip4_address_t *)(&mp->dhcp_server),
2982                                 (ip4_address_t *)(&mp->dhcp_src_address),
2983                                 (u32) ntohl(mp->rx_vrf_id),
2984                                 (u32) ntohl(mp->server_vrf_id),
2985                                 (int) mp->insert_circuit_id,
2986                                 (int) (mp->is_add == 0));
2987
2988     REPLY_MACRO(VL_API_DHCP_PROXY_CONFIG_2_REPLY);
2989 }
2990
2991
2992 static void
2993 dhcpv6_proxy_config_2 (vl_api_dhcp_proxy_config_2_t *mp)
2994 {
2995     vl_api_dhcp_proxy_config_reply_t * rmp;
2996     int rv = -1;
2997
2998 #if 0 // $$$$ FIXME
2999     rv = dhcpv6_proxy_set_server_2 ((ip6_address_t *)(&mp->dhcp_server),
3000                                 (ip6_address_t *)(&mp->dhcp_src_address),
3001                                 (u32) ntohl(mp->rx_vrf_id),
3002                                 (u32) ntohl(mp->server_vrf_id),
3003                                 (int) mp->insert_circuit_id,
3004                                 (int) (mp->is_add == 0));
3005 #else
3006     rv = VNET_API_ERROR_UNIMPLEMENTED;
3007 #endif
3008
3009     REPLY_MACRO(VL_API_DHCP_PROXY_CONFIG_2_REPLY);
3010 }
3011
3012
3013 static void
3014 vl_api_dhcp_proxy_set_vss_t_handler (vl_api_dhcp_proxy_set_vss_t *mp)
3015 {
3016     vl_api_dhcp_proxy_set_vss_reply_t *rmp;
3017     int rv;
3018     if (!mp->is_ipv6)
3019         rv = dhcp_proxy_set_option82_vss(ntohl(mp->tbl_id),
3020                                          ntohl(mp->oui),
3021                                          ntohl(mp->fib_id),
3022                                          (int)mp->is_add == 0);
3023     else
3024          rv = dhcpv6_proxy_set_vss( ntohl(mp->tbl_id),
3025                                          ntohl(mp->oui),
3026                                          ntohl(mp->fib_id),
3027                                          (int)mp->is_add == 0);
3028
3029     REPLY_MACRO(VL_API_DHCP_PROXY_SET_VSS_REPLY);
3030 }
3031
3032
3033 static void vl_api_dhcp_proxy_config_t_handler
3034 (vl_api_dhcp_proxy_config_t *mp)
3035 {
3036     if (mp->is_ipv6 == 0)
3037         dhcpv4_proxy_config (mp);
3038     else
3039         dhcpv6_proxy_config (mp);
3040 }
3041
3042 static void vl_api_dhcp_proxy_config_2_t_handler
3043 (vl_api_dhcp_proxy_config_2_t *mp)
3044 {
3045     if (mp->is_ipv6 == 0)
3046         dhcpv4_proxy_config_2 (mp);
3047     else
3048         dhcpv6_proxy_config_2 (mp);
3049 }
3050
3051 void dhcp_compl_event_callback (u32 client_index, u32 pid, u8 * hostname,
3052        u8 is_ipv6, u8 * host_address, u8 * router_address, u8 * host_mac)
3053 {
3054     unix_shared_memory_queue_t * q;
3055     vl_api_dhcp_compl_event_t * mp;
3056
3057     q = vl_api_client_index_to_input_queue (client_index);
3058     if (!q)
3059         return;
3060
3061     mp = vl_msg_api_alloc (sizeof (*mp));
3062     mp->client_index = client_index;
3063     mp->pid = pid;
3064     mp->is_ipv6 = is_ipv6;
3065     clib_memcpy (&mp->hostname, hostname, vec_len(hostname));
3066     mp->hostname[vec_len(hostname) + 1] = '\n';
3067     clib_memcpy (&mp->host_address[0], host_address, 16);
3068     clib_memcpy (&mp->router_address[0], router_address, 16);
3069     clib_memcpy (&mp->host_mac[0], host_mac, 6);
3070
3071     mp->_vl_msg_id = ntohs (VL_API_DHCP_COMPL_EVENT);
3072
3073     vl_msg_api_send_shmem (q, (u8 *)&mp);
3074 }
3075
3076 static void vl_api_dhcp_client_config_t_handler
3077 (vl_api_dhcp_client_config_t *mp)
3078 {
3079     vlib_main_t *vm = vlib_get_main();
3080     vl_api_dhcp_client_config_reply_t * rmp;
3081     int rv = 0;
3082
3083     VALIDATE_SW_IF_INDEX(mp);
3084
3085     rv = dhcp_client_config(vm, ntohl(mp->sw_if_index),
3086              mp->hostname, mp->is_add, mp->client_index,
3087              mp->want_dhcp_event ? dhcp_compl_event_callback : NULL,
3088              mp->pid);
3089
3090     BAD_SW_IF_INDEX_LABEL;
3091
3092     REPLY_MACRO(VL_API_DHCP_CLIENT_CONFIG_REPLY);
3093 }
3094
3095 static void
3096 vl_api_sw_interface_ip6nd_ra_config_t_handler
3097 (vl_api_sw_interface_ip6nd_ra_config_t *mp, vlib_main_t *vm)
3098 {
3099    vl_api_sw_interface_ip6nd_ra_config_reply_t * rmp;
3100     int rv = 0;
3101     u8  is_no,  surpress, managed, other, ll_option, send_unicast, cease, default_router;
3102
3103     is_no = mp->is_no == 1;
3104     surpress = mp->surpress == 1;
3105     managed = mp->managed == 1;
3106    other = mp->other == 1;
3107     ll_option = mp->ll_option == 1;
3108     send_unicast = mp->send_unicast == 1;
3109     cease = mp->cease == 1;
3110     default_router = mp->default_router  == 1;
3111
3112     VALIDATE_SW_IF_INDEX(mp);
3113
3114     rv = ip6_neighbor_ra_config(vm, ntohl(mp->sw_if_index),
3115                                 surpress,  managed,  other,
3116                                 ll_option,  send_unicast,  cease,
3117                                 default_router, ntohl (mp->lifetime),
3118                                 ntohl(mp->initial_count),  ntohl(mp->initial_interval),
3119                                 ntohl(mp->max_interval), ntohl( mp->min_interval),
3120                                 is_no);
3121
3122     BAD_SW_IF_INDEX_LABEL;
3123
3124     REPLY_MACRO(VL_API_SW_INTERFACE_IP6ND_RA_CONFIG_REPLY);
3125 }
3126
3127 static void
3128 vl_api_sw_interface_ip6nd_ra_prefix_t_handler
3129 (vl_api_sw_interface_ip6nd_ra_prefix_t *mp, vlib_main_t *vm)
3130 {
3131    vl_api_sw_interface_ip6nd_ra_prefix_reply_t * rmp;
3132     int rv = 0;
3133     u8  is_no,  use_default,  no_advertise, off_link, no_autoconfig, no_onlink;
3134
3135     VALIDATE_SW_IF_INDEX(mp);
3136
3137     is_no = mp->is_no == 1;
3138     use_default = mp->use_default == 1;
3139     no_advertise = mp->no_advertise == 1;
3140     off_link = mp->off_link == 1;
3141     no_autoconfig = mp->no_autoconfig == 1;
3142     no_onlink = mp->no_onlink == 1;
3143
3144     rv = ip6_neighbor_ra_prefix(vm,  ntohl(mp->sw_if_index),
3145                                 (ip6_address_t *)mp->address,  mp->address_length,
3146                                 use_default,  ntohl(mp->val_lifetime), ntohl(mp->pref_lifetime),
3147                                 no_advertise,  off_link, no_autoconfig, no_onlink,
3148                                 is_no);
3149
3150     BAD_SW_IF_INDEX_LABEL;
3151     REPLY_MACRO(VL_API_SW_INTERFACE_IP6ND_RA_PREFIX_REPLY);
3152 }
3153
3154 static void
3155 vl_api_sw_interface_ip6_enable_disable_t_handler
3156 (vl_api_sw_interface_ip6_enable_disable_t *mp, vlib_main_t *vm)
3157 {
3158     vl_api_sw_interface_ip6_enable_disable_reply_t * rmp;
3159     vnet_main_t * vnm = vnet_get_main();
3160     int rv = 0;
3161     clib_error_t * error;
3162
3163     vnm->api_errno = 0;
3164
3165     VALIDATE_SW_IF_INDEX(mp);
3166
3167     error = ( mp->enable == 1) ? enable_ip6_interface(vm,ntohl(mp->sw_if_index)) :
3168         disable_ip6_interface(vm,ntohl(mp->sw_if_index));
3169
3170     if (error)  {
3171         clib_error_report(error);
3172         rv = VNET_API_ERROR_UNSPECIFIED;
3173     } else {
3174         rv = vnm->api_errno;
3175     }
3176
3177     BAD_SW_IF_INDEX_LABEL;
3178
3179     REPLY_MACRO(VL_API_SW_INTERFACE_IP6_ENABLE_DISABLE_REPLY);
3180 }
3181
3182 static void
3183 vl_api_sw_interface_ip6_set_link_local_address_t_handler
3184 (vl_api_sw_interface_ip6_set_link_local_address_t *mp, vlib_main_t *vm)
3185 {
3186     vl_api_sw_interface_ip6_set_link_local_address_reply_t * rmp;
3187     int rv = 0;
3188     clib_error_t * error;
3189     vnet_main_t * vnm = vnet_get_main();
3190
3191     vnm->api_errno = 0;
3192
3193     VALIDATE_SW_IF_INDEX(mp);
3194
3195     error = set_ip6_link_local_address(vm,
3196                                        ntohl(mp->sw_if_index),
3197                                        (ip6_address_t *)mp->address,
3198                                        mp->address_length);
3199     if (error)  {
3200       clib_error_report(error);
3201       rv = VNET_API_ERROR_UNSPECIFIED;
3202     } else {
3203         rv = vnm->api_errno;
3204     }
3205
3206     BAD_SW_IF_INDEX_LABEL;
3207
3208     REPLY_MACRO(VL_API_SW_INTERFACE_IP6_SET_LINK_LOCAL_ADDRESS_REPLY);
3209 }
3210
3211 static void set_ip6_flow_hash (vl_api_set_ip_flow_hash_t *mp)
3212 {
3213     vl_api_set_ip_flow_hash_reply_t *rmp;
3214     int rv = VNET_API_ERROR_UNIMPLEMENTED;
3215
3216     clib_warning ("unimplemented...");
3217
3218     REPLY_MACRO(VL_API_SET_IP_FLOW_HASH_REPLY);
3219 }
3220
3221 static void set_ip4_flow_hash (vl_api_set_ip_flow_hash_t *mp)
3222 {
3223     vl_api_set_ip_flow_hash_reply_t *rmp;
3224     int rv;
3225     u32 table_id;
3226     u32 flow_hash_config = 0;
3227
3228     table_id = ntohl(mp->vrf_id);
3229
3230 #define _(a,b) if (mp->a) flow_hash_config |= b;
3231     foreach_flow_hash_bit;
3232 #undef _
3233
3234     rv = vnet_set_ip4_flow_hash (table_id, flow_hash_config);
3235
3236     REPLY_MACRO(VL_API_SET_IP_FLOW_HASH_REPLY);
3237 }
3238
3239
3240 static void vl_api_set_ip_flow_hash_t_handler
3241 (vl_api_set_ip_flow_hash_t *mp)
3242 {
3243     if (mp->is_ipv6 == 0)
3244         set_ip4_flow_hash (mp);
3245     else
3246         set_ip6_flow_hash (mp);
3247 }
3248
3249 static void vl_api_sw_interface_set_unnumbered_t_handler
3250 (vl_api_sw_interface_set_unnumbered_t *mp)
3251 {
3252     vl_api_sw_interface_set_unnumbered_reply_t * rmp;
3253     int rv = 0;
3254     vnet_sw_interface_t * si;
3255     vnet_main_t *vnm = vnet_get_main();
3256     u32 sw_if_index, unnumbered_sw_if_index;
3257
3258     sw_if_index = ntohl(mp->sw_if_index);
3259     unnumbered_sw_if_index = ntohl(mp->unnumbered_sw_if_index);
3260
3261     /*
3262      * The API message field names are backwards from
3263      * the underlying data structure names.
3264      * It's not worth changing them now.
3265      */
3266     if (pool_is_free_index (vnm->interface_main.sw_interfaces,
3267                             unnumbered_sw_if_index)) {
3268         rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
3269         goto done;
3270     }
3271
3272     /* Only check the "use loop0" field when setting the binding */
3273     if (mp->is_add &&
3274         pool_is_free_index (vnm->interface_main.sw_interfaces, sw_if_index)) {
3275         rv = VNET_API_ERROR_INVALID_SW_IF_INDEX_2;
3276         goto done;
3277     }
3278
3279     si = vnet_get_sw_interface (vnm, unnumbered_sw_if_index);
3280
3281     if (mp->is_add) {
3282         si->flags |= VNET_SW_INTERFACE_FLAG_UNNUMBERED;
3283         si->unnumbered_sw_if_index = sw_if_index;
3284     } else {
3285         si->flags &= ~(VNET_SW_INTERFACE_FLAG_UNNUMBERED);
3286         si->unnumbered_sw_if_index = (u32)~0;
3287     }
3288
3289  done:
3290     REPLY_MACRO(VL_API_SW_INTERFACE_SET_UNNUMBERED_REPLY);
3291 }
3292
3293 static void vl_api_create_loopback_t_handler
3294 (vl_api_create_loopback_t *mp)
3295 {
3296     vl_api_create_loopback_reply_t * rmp;
3297     u32 sw_if_index;
3298     int rv;
3299
3300     rv = vnet_create_loopback_interface (&sw_if_index, mp->mac_address);
3301
3302     REPLY_MACRO2(VL_API_CREATE_LOOPBACK_REPLY,
3303     ({
3304         rmp->sw_if_index = ntohl (sw_if_index);
3305     }));
3306 }
3307
3308 static void vl_api_delete_loopback_t_handler
3309 (vl_api_delete_loopback_t *mp)
3310 {
3311     vl_api_delete_loopback_reply_t * rmp;
3312     u32 sw_if_index;
3313     int rv;
3314
3315     sw_if_index = ntohl (mp->sw_if_index);
3316     rv = vnet_delete_loopback_interface (sw_if_index);
3317
3318     REPLY_MACRO(VL_API_DELETE_LOOPBACK_REPLY);
3319 }
3320
3321 static void vl_api_control_ping_t_handler
3322 (vl_api_control_ping_t *mp)
3323 {
3324     vl_api_control_ping_reply_t * rmp;
3325     int rv = 0;
3326
3327     REPLY_MACRO2(VL_API_CONTROL_PING_REPLY,
3328     ({
3329         rmp->vpe_pid = ntohl (getpid());
3330     }));
3331 }
3332
3333 static void shmem_cli_output (uword arg, u8 * buffer, uword buffer_bytes)
3334 {
3335     u8 **shmem_vecp = (u8 **)arg;
3336     u8 *shmem_vec;
3337     void *oldheap;
3338     api_main_t * am = &api_main;
3339     u32 offset;
3340
3341     shmem_vec = *shmem_vecp;
3342
3343     offset = vec_len (shmem_vec);
3344
3345     pthread_mutex_lock (&am->vlib_rp->mutex);
3346     oldheap = svm_push_data_heap (am->vlib_rp);
3347
3348     vec_validate (shmem_vec, offset + buffer_bytes - 1);
3349
3350     clib_memcpy (shmem_vec + offset, buffer, buffer_bytes);
3351
3352     svm_pop_heap (oldheap);
3353     pthread_mutex_unlock (&am->vlib_rp->mutex);
3354
3355     *shmem_vecp = shmem_vec;
3356 }
3357
3358
3359 static void vl_api_cli_request_t_handler
3360 (vl_api_cli_request_t *mp)
3361 {
3362     vl_api_cli_reply_t *rp;
3363     unix_shared_memory_queue_t *q;
3364     vlib_main_t * vm = vlib_get_main();
3365     api_main_t * am = &api_main;
3366     unformat_input_t input;
3367     u8 *shmem_vec=0;
3368     void *oldheap;
3369
3370     q = vl_api_client_index_to_input_queue (mp->client_index);
3371     if (!q)
3372         return;
3373
3374     rp = vl_msg_api_alloc (sizeof (*rp));
3375     rp->_vl_msg_id = ntohs(VL_API_CLI_REPLY);
3376     rp->context = mp->context;
3377
3378     unformat_init_vector (&input, (u8 *)(uword)mp->cmd_in_shmem);
3379
3380     vlib_cli_input (vm, &input, shmem_cli_output,
3381                     (uword)&shmem_vec);
3382
3383     pthread_mutex_lock (&am->vlib_rp->mutex);
3384     oldheap = svm_push_data_heap (am->vlib_rp);
3385
3386     vec_add1(shmem_vec, 0);
3387
3388     svm_pop_heap (oldheap);
3389     pthread_mutex_unlock (&am->vlib_rp->mutex);
3390
3391     rp->reply_in_shmem = (uword)shmem_vec;
3392
3393     vl_msg_api_send_shmem (q, (u8 *)&rp);
3394 }
3395
3396 static void vl_api_set_arp_neighbor_limit_t_handler (vl_api_set_arp_neighbor_limit_t *mp)
3397 {
3398     int rv;
3399     vl_api_set_arp_neighbor_limit_reply_t * rmp;
3400     vnet_main_t *vnm = vnet_get_main();
3401     clib_error_t * error;
3402
3403     vnm->api_errno = 0;
3404
3405     if (mp->is_ipv6)
3406         error = ip6_set_neighbor_limit (ntohl(mp->arp_neighbor_limit));
3407     else
3408         error = ip4_set_arp_limit (ntohl(mp->arp_neighbor_limit));
3409
3410     if (error)  {
3411         clib_error_report(error);
3412         rv = VNET_API_ERROR_UNSPECIFIED;
3413     } else {
3414         rv = vnm->api_errno;
3415     }
3416
3417     REPLY_MACRO(VL_API_SET_ARP_NEIGHBOR_LIMIT_REPLY);
3418 }
3419
3420 static void vl_api_sr_tunnel_add_del_t_handler
3421 (vl_api_sr_tunnel_add_del_t *mp)
3422 {
3423 #if IPV6SR == 0
3424     clib_warning ("unimplemented");
3425 #else
3426     ip6_sr_add_del_tunnel_args_t _a, *a=&_a;
3427     int rv = 0;
3428     vl_api_sr_tunnel_add_del_reply_t * rmp;
3429     ip6_address_t * segments = 0, * seg;
3430     ip6_address_t * tags = 0, *tag;
3431     ip6_address_t * this_address;
3432     int i;
3433
3434     if (mp->n_segments == 0) {
3435         rv = -11;
3436         goto out;
3437     }
3438
3439     memset (a, 0, sizeof (*a));
3440     a->src_address = (ip6_address_t *)&mp->src_address;
3441     a->dst_address = (ip6_address_t *)&mp->dst_address;
3442     a->dst_mask_width = mp->dst_mask_width;
3443     a->flags_net_byte_order = mp->flags_net_byte_order;
3444     a->is_del = (mp->is_add == 0);
3445     a->rx_table_id = ntohl(mp->outer_vrf_id);
3446     a->tx_table_id = ntohl(mp->inner_vrf_id);
3447
3448     a->name = format(0, "%s", mp->name);
3449     if (!(vec_len(a->name)))
3450       a->name = 0;
3451
3452     a->policy_name = format(0, "%s", mp->policy_name);
3453     if (!(vec_len(a->policy_name)))
3454       a->policy_name = 0;
3455
3456     /* Yank segments and tags out of the API message */
3457     this_address = (ip6_address_t *)mp->segs_and_tags;
3458     for (i = 0; i < mp->n_segments; i++) {
3459         vec_add2 (segments, seg, 1);
3460         clib_memcpy (seg->as_u8, this_address->as_u8, sizeof (*this_address));
3461         this_address++;
3462     }
3463     for (i = 0; i < mp->n_tags; i++) {
3464         vec_add2 (tags, tag, 1);
3465         clib_memcpy (tag->as_u8, this_address->as_u8, sizeof (*this_address));
3466         this_address++;
3467     }
3468
3469     a->segments = segments;
3470     a->tags = tags;
3471
3472     rv = ip6_sr_add_del_tunnel (a);
3473
3474 out:
3475
3476     REPLY_MACRO(VL_API_SR_TUNNEL_ADD_DEL_REPLY);
3477 #endif
3478 }
3479
3480 static void vl_api_sr_policy_add_del_t_handler
3481 (vl_api_sr_policy_add_del_t *mp)
3482 {
3483 #if IPV6SR == 0
3484     clib_warning ("unimplemented");
3485 #else
3486     ip6_sr_add_del_policy_args_t _a, *a=&_a;
3487     int rv = 0;
3488     vl_api_sr_policy_add_del_reply_t * rmp;
3489     int i;
3490
3491     memset (a, 0, sizeof (*a));
3492     a->is_del = (mp->is_add == 0);
3493
3494     a->name = format(0, "%s", mp->name);
3495     if (!(vec_len(a->name)))
3496       {
3497         rv = VNET_API_ERROR_NO_SUCH_NODE2;
3498         goto out;
3499       }
3500
3501     if (!(mp->tunnel_names[0]))
3502       {
3503         rv = VNET_API_ERROR_NO_SUCH_NODE2;
3504         goto out;
3505       }
3506
3507     // start deserializing tunnel_names
3508     int num_tunnels = mp->tunnel_names[0]; //number of tunnels
3509     u8 * deser_tun_names = mp->tunnel_names;
3510     deser_tun_names += 1; //moving along
3511
3512     u8 * tun_name = 0;
3513     int tun_name_len = 0;
3514
3515     for (i=0; i < num_tunnels; i++)
3516       {
3517         tun_name_len= *deser_tun_names;
3518         deser_tun_names += 1;
3519         vec_resize (tun_name, tun_name_len);
3520         memcpy(tun_name, deser_tun_names, tun_name_len);
3521         vec_add1 (a->tunnel_names, tun_name);
3522         deser_tun_names += tun_name_len;
3523         tun_name = 0;
3524       }
3525
3526     rv = ip6_sr_add_del_policy (a);
3527
3528 out:
3529
3530     REPLY_MACRO(VL_API_SR_POLICY_ADD_DEL_REPLY);
3531 #endif
3532 }
3533
3534 static void vl_api_sr_multicast_map_add_del_t_handler
3535 (vl_api_sr_multicast_map_add_del_t *mp)
3536 {
3537 #if IPV6SR == 0
3538     clib_warning ("unimplemented");
3539 #else
3540     ip6_sr_add_del_multicastmap_args_t _a, *a=&_a;
3541     int rv = 0;
3542     vl_api_sr_multicast_map_add_del_reply_t * rmp;
3543
3544     memset (a, 0, sizeof (*a));
3545     a->is_del = (mp->is_add == 0);
3546
3547     a->multicast_address = (ip6_address_t *)&mp->multicast_address;
3548     a->policy_name = format(0, "%s", mp->policy_name);
3549
3550     if (a->multicast_address == 0)
3551       {
3552         rv = -1 ;
3553         goto out;
3554       }
3555
3556     if (!(a->policy_name))
3557       {
3558         rv = -2 ;
3559         goto out;
3560       }
3561
3562 #if DPDK > 0 /* Cannot call replicate without DPDK */
3563     rv = ip6_sr_add_del_multicastmap (a);
3564 #else
3565     clib_warning ("multicast replication without DPDK not implemented");
3566     rv = VNET_API_ERROR_UNIMPLEMENTED;
3567 #endif /* DPDK */
3568
3569 out:
3570
3571     REPLY_MACRO(VL_API_SR_MULTICAST_MAP_ADD_DEL_REPLY);
3572 #endif
3573 }
3574
3575 #define foreach_classify_add_del_table_field    \
3576 _(table_index)                                  \
3577 _(nbuckets)                                     \
3578 _(memory_size)                                  \
3579 _(skip_n_vectors)                               \
3580 _(match_n_vectors)                              \
3581 _(next_table_index)                             \
3582 _(miss_next_index)
3583
3584 static void vl_api_classify_add_del_table_t_handler
3585 (vl_api_classify_add_del_table_t * mp)
3586 {
3587     vl_api_classify_add_del_table_reply_t * rmp;
3588     vnet_classify_main_t * cm = &vnet_classify_main;
3589     vnet_classify_table_t * t;
3590     int rv;
3591
3592 #define _(a) u32 a;
3593     foreach_classify_add_del_table_field;
3594 #undef _
3595
3596 #define _(a) a = ntohl(mp->a);
3597     foreach_classify_add_del_table_field;
3598 #undef _
3599
3600     /* The underlying API fails silently, on purpose, so check here */
3601     if (mp->is_add == 0)
3602         if (pool_is_free_index (cm->tables, table_index)) {
3603             rv = VNET_API_ERROR_NO_SUCH_TABLE;
3604             goto out;
3605         }
3606
3607     rv = vnet_classify_add_del_table
3608         (cm, mp->mask, nbuckets, memory_size,
3609          skip_n_vectors, match_n_vectors,
3610          next_table_index, miss_next_index,
3611          &table_index, mp->is_add);
3612
3613 out:
3614     REPLY_MACRO2(VL_API_CLASSIFY_ADD_DEL_TABLE_REPLY,
3615     ({
3616         if (rv == 0 && mp->is_add) {
3617             t = pool_elt_at_index (cm->tables, table_index);
3618             rmp->skip_n_vectors = ntohl(t->skip_n_vectors);
3619             rmp->match_n_vectors = ntohl(t->match_n_vectors);
3620             rmp->new_table_index = ntohl(table_index);
3621         } else {
3622             rmp->skip_n_vectors = ~0;
3623             rmp->match_n_vectors = ~0;
3624             rmp->new_table_index = ~0;
3625         }
3626     }));
3627 }
3628
3629 static void vl_api_classify_add_del_session_t_handler
3630 (vl_api_classify_add_del_session_t * mp)
3631 {
3632     vnet_classify_main_t * cm = &vnet_classify_main;
3633     vl_api_classify_add_del_session_reply_t * rmp;
3634     int rv;
3635     u32 table_index, hit_next_index, opaque_index;
3636     i32 advance;
3637
3638     table_index = ntohl (mp->table_index);
3639     hit_next_index = ntohl (mp->hit_next_index);
3640     opaque_index = ntohl (mp->opaque_index);
3641     advance = ntohl (mp->advance);
3642
3643     rv = vnet_classify_add_del_session
3644         (cm, table_index, mp->match, hit_next_index, opaque_index,
3645          advance, mp->is_add);
3646
3647     REPLY_MACRO(VL_API_CLASSIFY_ADD_DEL_SESSION_REPLY);
3648 }
3649
3650 static void vl_api_classify_set_interface_ip_table_t_handler
3651 (vl_api_classify_set_interface_ip_table_t * mp)
3652 {
3653     vlib_main_t * vm = vlib_get_main();
3654     vl_api_classify_set_interface_ip_table_reply_t * rmp;
3655     int rv;
3656     u32 table_index, sw_if_index;
3657
3658     table_index = ntohl (mp->table_index);
3659     sw_if_index = ntohl (mp->sw_if_index);
3660
3661     VALIDATE_SW_IF_INDEX(mp);
3662
3663     if (mp->is_ipv6)
3664         rv = vnet_set_ip6_classify_intfc (vm, sw_if_index, table_index);
3665     else
3666         rv = vnet_set_ip4_classify_intfc (vm, sw_if_index, table_index);
3667
3668     BAD_SW_IF_INDEX_LABEL;
3669
3670     REPLY_MACRO(VL_API_CLASSIFY_SET_INTERFACE_IP_TABLE_REPLY);
3671 }
3672
3673 static void vl_api_classify_set_interface_l2_tables_t_handler
3674 (vl_api_classify_set_interface_l2_tables_t * mp)
3675 {
3676     vl_api_classify_set_interface_l2_tables_reply_t * rmp;
3677     int rv;
3678     u32 sw_if_index, ip4_table_index, ip6_table_index, other_table_index;
3679     int enable;
3680
3681     ip4_table_index = ntohl(mp->ip4_table_index);
3682     ip6_table_index = ntohl(mp->ip6_table_index);
3683     other_table_index = ntohl(mp->other_table_index);
3684     sw_if_index = ntohl(mp->sw_if_index);
3685
3686     VALIDATE_SW_IF_INDEX(mp);
3687
3688     rv = vnet_l2_classify_set_tables (sw_if_index, ip4_table_index,
3689                                       ip6_table_index, other_table_index);
3690
3691     if (rv == 0) {
3692         if (ip4_table_index != ~0 || ip6_table_index != ~0
3693             || other_table_index != ~0)
3694             enable = 1;
3695         else
3696             enable = 0;
3697
3698         vnet_l2_classify_enable_disable (sw_if_index, enable);
3699     }
3700
3701     BAD_SW_IF_INDEX_LABEL;
3702
3703     REPLY_MACRO(VL_API_CLASSIFY_SET_INTERFACE_L2_TABLES_REPLY);
3704 }
3705
3706 static void
3707 vl_api_l2_fib_clear_table_t_handler (vl_api_l2_fib_clear_table_t *mp)
3708 {
3709     int rv = 0;
3710     vl_api_l2_fib_clear_table_reply_t * rmp;
3711
3712     /* DAW-FIXME: This API should only clear non-static l2fib entries, but
3713      *            that is not currently implemented.  When that TODO is fixed
3714      *            this call should be changed to pass 1 instead of 0.
3715      */
3716     l2fib_clear_table (0);
3717
3718     REPLY_MACRO(VL_API_L2_FIB_CLEAR_TABLE_REPLY);
3719 }
3720
3721 extern void l2_efp_filter_configure(vnet_main_t * vnet_main,
3722                                     u32           sw_if_index,
3723                                     u32           enable);
3724
3725 static void
3726 vl_api_l2_interface_efp_filter_t_handler (vl_api_l2_interface_efp_filter_t *mp)
3727 {
3728     int rv;
3729     vl_api_l2_interface_efp_filter_reply_t * rmp;
3730     vnet_main_t *vnm = vnet_get_main();
3731
3732     // enable/disable the feature
3733     l2_efp_filter_configure (vnm, mp->sw_if_index, mp->enable_disable);
3734     rv = vnm->api_errno;
3735
3736     REPLY_MACRO(VL_API_L2_INTERFACE_EFP_FILTER_REPLY);
3737 }
3738
3739 static void
3740 vl_api_l2_interface_vlan_tag_rewrite_t_handler (vl_api_l2_interface_vlan_tag_rewrite_t *mp)
3741 {
3742     int rv = 0;
3743     vl_api_l2_interface_vlan_tag_rewrite_reply_t * rmp;
3744     vnet_main_t * vnm = vnet_get_main();
3745     vlib_main_t * vm = vlib_get_main();
3746     u32 vtr_op;
3747
3748     VALIDATE_SW_IF_INDEX(mp);
3749
3750     vtr_op = ntohl(mp->vtr_op);
3751
3752     /* The L2 code is unsuspicious */
3753     switch(vtr_op) {
3754     case L2_VTR_DISABLED:
3755     case L2_VTR_PUSH_1:
3756     case L2_VTR_PUSH_2:
3757     case L2_VTR_POP_1:
3758     case L2_VTR_POP_2:
3759     case L2_VTR_TRANSLATE_1_1:
3760     case L2_VTR_TRANSLATE_1_2:
3761     case L2_VTR_TRANSLATE_2_1:
3762     case L2_VTR_TRANSLATE_2_2:
3763         break;
3764
3765     default:
3766         rv = VNET_API_ERROR_INVALID_VALUE;
3767         goto bad_sw_if_index;
3768     }
3769
3770     rv = l2vtr_configure (vm, vnm, ntohl(mp->sw_if_index), vtr_op,
3771                           ntohl(mp->push_dot1q), ntohl(mp->tag1),
3772                           ntohl(mp->tag2));
3773
3774     BAD_SW_IF_INDEX_LABEL;
3775
3776     REPLY_MACRO(VL_API_L2_INTERFACE_VLAN_TAG_REWRITE_REPLY);
3777 }
3778
3779 static void
3780 vl_api_create_vhost_user_if_t_handler (vl_api_create_vhost_user_if_t *mp)
3781 {
3782 #if DPDK > 0
3783     int rv = 0;
3784     vl_api_create_vhost_user_if_reply_t * rmp;
3785     u32 sw_if_index = (u32)~0;
3786
3787     vnet_main_t * vnm = vnet_get_main();
3788     vlib_main_t * vm = vlib_get_main();
3789
3790     rv = dpdk_vhost_user_create_if(vnm, vm, (char *)mp->sock_filename,
3791                               mp->is_server, &sw_if_index, (u64)~0,
3792                               mp->renumber, ntohl(mp->custom_dev_instance),
3793                               (mp->use_custom_mac)?mp->mac_address:NULL);
3794
3795     REPLY_MACRO2(VL_API_CREATE_VHOST_USER_IF_REPLY,
3796     ({
3797       rmp->sw_if_index = ntohl (sw_if_index);
3798     }));
3799 #endif
3800 }
3801
3802 static void
3803 vl_api_modify_vhost_user_if_t_handler (vl_api_modify_vhost_user_if_t *mp)
3804 {
3805 #if DPDK > 0
3806     int rv = 0;
3807     vl_api_modify_vhost_user_if_reply_t * rmp;
3808     u32 sw_if_index = ntohl(mp->sw_if_index);
3809
3810     vnet_main_t * vnm = vnet_get_main();
3811     vlib_main_t * vm = vlib_get_main();
3812
3813     rv = dpdk_vhost_user_modify_if(vnm, vm, (char *)mp->sock_filename,
3814                               mp->is_server, sw_if_index, (u64)~0,
3815                               mp->renumber, ntohl(mp->custom_dev_instance));
3816
3817     REPLY_MACRO(VL_API_MODIFY_VHOST_USER_IF_REPLY);
3818 #endif
3819 }
3820
3821 static void
3822 vl_api_delete_vhost_user_if_t_handler (vl_api_delete_vhost_user_if_t *mp)
3823 {
3824 #if DPDK > 0
3825     int rv = 0;
3826     vpe_api_main_t * vam = &vpe_api_main;
3827     vl_api_delete_vhost_user_if_reply_t * rmp;
3828     u32 sw_if_index = ntohl(mp->sw_if_index);
3829
3830     vnet_main_t * vnm = vnet_get_main();
3831     vlib_main_t * vm = vlib_get_main();
3832
3833     rv = dpdk_vhost_user_delete_if(vnm, vm, sw_if_index);
3834
3835     REPLY_MACRO(VL_API_DELETE_VHOST_USER_IF_REPLY);
3836     if (!rv) {
3837         unix_shared_memory_queue_t * q =
3838             vl_api_client_index_to_input_queue (mp->client_index);
3839         if (!q)
3840             return;
3841
3842         send_sw_interface_flags_deleted (vam, q, sw_if_index);
3843     }
3844 #endif
3845 }
3846
3847 static void vl_api_sw_interface_vhost_user_details_t_handler (
3848     vl_api_sw_interface_vhost_user_details_t * mp)
3849 {
3850     clib_warning ("BUG");
3851 }
3852
3853 #if DPDK > 0
3854 static void send_sw_interface_vhost_user_details (vpe_api_main_t * am,
3855                                        unix_shared_memory_queue_t *q,
3856                                        vhost_user_intf_details_t * vui,
3857                                        u32 context)
3858 {
3859     vl_api_sw_interface_vhost_user_details_t * mp;
3860
3861     mp = vl_msg_api_alloc (sizeof (*mp));
3862     memset (mp, 0, sizeof (*mp));
3863     mp->_vl_msg_id = ntohs(VL_API_SW_INTERFACE_VHOST_USER_DETAILS);
3864     mp->sw_if_index = ntohl(vui->sw_if_index);
3865     mp->virtio_net_hdr_sz = ntohl (vui->virtio_net_hdr_sz);
3866     mp->features = clib_net_to_host_u64 (vui->features);
3867     mp->is_server = vui->is_server;
3868     mp->num_regions = ntohl(vui->num_regions);
3869     mp->sock_errno = ntohl(vui->sock_errno);
3870     mp->context = context;
3871
3872     strncpy ((char *) mp->sock_filename,
3873              (char *) vui->sock_filename, ARRAY_LEN(mp->sock_filename)-1);
3874     strncpy ((char *) mp->interface_name,
3875              (char *) vui->if_name, ARRAY_LEN(mp->interface_name)-1);
3876
3877     vl_msg_api_send_shmem (q, (u8 *)&mp);
3878 }
3879 #endif
3880
3881 static void
3882 vl_api_sw_interface_vhost_user_dump_t_handler (
3883         vl_api_sw_interface_vhost_user_dump_t *mp)
3884 {
3885 #if DPDK > 0
3886     int rv = 0;
3887     vpe_api_main_t * am = &vpe_api_main;
3888     vnet_main_t * vnm = vnet_get_main();
3889     vlib_main_t * vm = vlib_get_main();
3890     vhost_user_intf_details_t *ifaces = NULL;
3891     vhost_user_intf_details_t *vuid = NULL;
3892     unix_shared_memory_queue_t * q;
3893
3894     q = vl_api_client_index_to_input_queue (mp->client_index);
3895     if (q == 0)
3896         return;
3897
3898     rv = dpdk_vhost_user_dump_ifs(vnm, vm, &ifaces);
3899     if (rv)
3900         return;
3901
3902     vec_foreach (vuid, ifaces) {
3903         send_sw_interface_vhost_user_details (am, q, vuid, mp->context);
3904     }
3905     vec_free(ifaces);
3906 #endif
3907 }
3908
3909 static void send_sw_if_l2tpv3_tunnel_details (vpe_api_main_t * am,
3910                                        unix_shared_memory_queue_t *q,
3911                                        l2t_session_t *s,
3912                                        l2t_main_t * lm,
3913                                        u32 context)
3914 {
3915     vl_api_sw_if_l2tpv3_tunnel_details_t * mp;
3916     u8 * if_name = NULL;
3917     vnet_sw_interface_t * si = NULL;
3918
3919     si = vnet_get_hw_sw_interface (lm->vnet_main, s->hw_if_index);
3920
3921     if_name = format(if_name, "%U",
3922                      format_vnet_sw_interface_name, lm->vnet_main, si);
3923
3924     mp = vl_msg_api_alloc (sizeof (*mp));
3925     memset (mp, 0, sizeof (*mp));
3926     mp->_vl_msg_id = ntohs(VL_API_SW_IF_L2TPV3_TUNNEL_DETAILS);
3927     strncpy((char *)mp->interface_name,
3928             (char *)if_name, ARRAY_LEN(mp->interface_name)-1);
3929     mp->sw_if_index = ntohl(si->sw_if_index);
3930     mp->local_session_id = s->local_session_id;
3931     mp->remote_session_id = s->remote_session_id;
3932     mp->local_cookie[0] = s->local_cookie[0];
3933     mp->local_cookie[1] = s->local_cookie[1];
3934     mp->remote_cookie = s->remote_cookie;
3935     clib_memcpy(mp->client_address, &s->client_address, sizeof(s->client_address));
3936     clib_memcpy(mp->our_address, &s->our_address, sizeof(s->our_address));
3937     mp->l2_sublayer_present = s->l2_sublayer_present;
3938     mp->context = context;
3939
3940     vl_msg_api_send_shmem (q, (u8 *)&mp);
3941 }
3942
3943 static void send_ip_address_details (vpe_api_main_t * am,
3944                                      unix_shared_memory_queue_t * q,
3945                                      u8 * ip,
3946                                      u16 prefix_length,
3947                                      u8 is_ipv6,
3948                                      u32 context)
3949 {
3950     vl_api_ip_address_details_t * mp;
3951
3952     mp = vl_msg_api_alloc (sizeof (*mp));
3953     memset (mp, 0, sizeof (*mp));
3954     mp->_vl_msg_id = ntohs(VL_API_IP_ADDRESS_DETAILS);
3955
3956     if (is_ipv6) {
3957         clib_memcpy(&mp->ip, ip, sizeof(mp->ip));
3958     } else {
3959         u32 * tp = (u32 *)mp->ip;
3960         *tp = ntohl(*(u32*)ip);
3961     }
3962     mp->prefix_length = prefix_length;
3963     mp->context = context;
3964
3965     vl_msg_api_send_shmem (q, (u8 *)&mp);
3966 }
3967
3968 static void
3969 vl_api_ip_address_dump_t_handler (vl_api_ip_address_dump_t *mp)
3970 {
3971     vpe_api_main_t * am = &vpe_api_main;
3972     unix_shared_memory_queue_t * q;
3973     ip6_address_t * r6;
3974     ip4_address_t * r4;
3975     ip6_main_t * im6 = &ip6_main;
3976     ip4_main_t * im4 = &ip4_main;
3977     ip_lookup_main_t * lm6 = &im6->lookup_main;
3978     ip_lookup_main_t * lm4 = &im4->lookup_main;
3979     ip_interface_address_t * ia = 0;
3980     u32 sw_if_index = ~0;
3981     int rv __attribute__ ((unused)) = 0;
3982
3983     VALIDATE_SW_IF_INDEX(mp);
3984
3985     sw_if_index = ntohl(mp->sw_if_index);
3986
3987     q = vl_api_client_index_to_input_queue (mp->client_index);
3988     if (q == 0) {
3989         return;
3990     }
3991
3992     if (mp->is_ipv6) {
3993         foreach_ip_interface_address (lm6, ia, sw_if_index,
3994                                       1 /* honor unnumbered */,
3995         ({
3996             r6 = ip_interface_address_get_address (lm6, ia);
3997             u16 prefix_length = ia->address_length;
3998             send_ip_address_details(am, q, (u8*)r6, prefix_length, 1, mp->context);
3999         }));
4000     } else {
4001         foreach_ip_interface_address (lm4, ia, sw_if_index,
4002                                       1 /* honor unnumbered */,
4003         ({
4004             r4 = ip_interface_address_get_address (lm4, ia);
4005             u16 prefix_length = ia->address_length;
4006             send_ip_address_details(am, q, (u8*)r4, prefix_length, 0, mp->context);
4007         }));
4008     }
4009     BAD_SW_IF_INDEX_LABEL;
4010 }
4011
4012 static void send_ip_details (vpe_api_main_t * am,
4013                                unix_shared_memory_queue_t *q,
4014                                u32 sw_if_index,
4015                                u32 context)
4016 {
4017     vl_api_ip_details_t * mp;
4018
4019     mp = vl_msg_api_alloc (sizeof (*mp));
4020     memset (mp, 0, sizeof (*mp));
4021     mp->_vl_msg_id = ntohs(VL_API_IP_DETAILS);
4022
4023     mp->sw_if_index = ntohl(sw_if_index);
4024     mp->context = context;
4025
4026     vl_msg_api_send_shmem (q, (u8 *)&mp);
4027 }
4028
4029 static void
4030 vl_api_sw_if_l2tpv3_tunnel_dump_t_handler (
4031         vl_api_sw_if_l2tpv3_tunnel_dump_t *mp)
4032 {
4033     vpe_api_main_t * am = &vpe_api_main;
4034     l2t_main_t * lm = &l2t_main;
4035     unix_shared_memory_queue_t * q;
4036     l2t_session_t *session;
4037
4038     q = vl_api_client_index_to_input_queue (mp->client_index);
4039     if (q == 0)
4040         return;
4041
4042     pool_foreach (session, lm->sessions,
4043     ({
4044         send_sw_if_l2tpv3_tunnel_details (am, q, session, lm, mp->context);
4045     }));
4046 }
4047
4048
4049 static void send_sw_interface_tap_details (vpe_api_main_t * am,
4050                                        unix_shared_memory_queue_t *q,
4051                                        tapcli_interface_details_t *tap_if,
4052                                        u32 context)
4053 {
4054     vl_api_sw_interface_tap_details_t * mp;
4055     mp = vl_msg_api_alloc (sizeof (*mp));
4056     memset (mp, 0, sizeof (*mp));
4057     mp->_vl_msg_id = ntohs(VL_API_SW_INTERFACE_TAP_DETAILS);
4058     mp->sw_if_index = ntohl(tap_if->sw_if_index);
4059     strncpy((char *)mp->dev_name,
4060             (char *)tap_if->dev_name, ARRAY_LEN(mp->dev_name)-1);
4061     mp->context = context;
4062
4063     vl_msg_api_send_shmem (q, (u8 *)&mp);
4064 }
4065
4066 static void
4067 vl_api_sw_interface_tap_dump_t_handler (
4068         vl_api_sw_interface_tap_dump_t *mp)
4069 {
4070     int rv = 0;
4071     vpe_api_main_t * am = &vpe_api_main;
4072     unix_shared_memory_queue_t * q;
4073     tapcli_interface_details_t *tapifs = NULL;
4074     tapcli_interface_details_t *tap_if = NULL;
4075
4076     q = vl_api_client_index_to_input_queue (mp->client_index);
4077     if (q == 0)
4078         return;
4079
4080     rv = vnet_tap_dump_ifs(&tapifs);
4081     if (rv)
4082         return;
4083
4084     vec_foreach(tap_if, tapifs) {
4085         send_sw_interface_tap_details(am, q, tap_if, mp->context);
4086     }
4087
4088     vec_free(tapifs);
4089 }
4090
4091 static void
4092 vl_api_ip_dump_t_handler (vl_api_ip_dump_t *mp)
4093 {
4094     vpe_api_main_t * am = &vpe_api_main;
4095     vnet_main_t * vnm = vnet_get_main();
4096     vlib_main_t * vm = vlib_get_main();
4097     vnet_interface_main_t * im = &vnm->interface_main;
4098     unix_shared_memory_queue_t * q;
4099     vnet_sw_interface_t * si, * sorted_sis;
4100     u32 sw_if_index = ~0;
4101
4102     q = vl_api_client_index_to_input_queue (mp->client_index);
4103     if (q == 0) {
4104         return;
4105     }
4106
4107     /* Gather interfaces. */
4108     sorted_sis = vec_new (vnet_sw_interface_t, pool_elts (im->sw_interfaces));
4109     _vec_len (sorted_sis) = 0;
4110     pool_foreach (si, im->sw_interfaces, ({ vec_add1 (sorted_sis, si[0]); }));
4111
4112     vec_foreach (si, sorted_sis) {
4113         if (!(si->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED)) {
4114             if (mp->is_ipv6 && !ip6_interface_enabled(vm, si->sw_if_index)) {
4115                 continue;
4116             }
4117             sw_if_index = si->sw_if_index;
4118             send_ip_details(am, q, sw_if_index, mp->context);
4119         }
4120     }
4121 }
4122
4123 static void vl_api_l2_fib_table_entry_t_handler (
4124     vl_api_l2_fib_table_entry_t * mp)
4125 {
4126     clib_warning ("BUG");
4127 }
4128
4129 static void send_l2fib_table_entry (vpe_api_main_t * am,
4130                                     unix_shared_memory_queue_t *q,
4131                                     l2fib_entry_key_t * l2fe_key,
4132                                     l2fib_entry_result_t * l2fe_res,
4133                                     u32 context)
4134 {
4135     vl_api_l2_fib_table_entry_t * mp;
4136
4137     mp = vl_msg_api_alloc (sizeof (*mp));
4138     memset (mp, 0, sizeof (*mp));
4139     mp->_vl_msg_id = ntohs(VL_API_L2_FIB_TABLE_ENTRY);
4140
4141     mp->bd_id = ntohl(l2input_main.bd_configs[l2fe_key->fields.bd_index].bd_id);
4142
4143     mp->mac = l2fib_make_key (l2fe_key->fields.mac, 0);
4144     mp->sw_if_index = ntohl(l2fe_res->fields.sw_if_index);
4145     mp->static_mac = l2fe_res->fields.static_mac;
4146     mp->filter_mac = l2fe_res->fields.filter;
4147     mp->bvi_mac = l2fe_res->fields.bvi;
4148     mp->context = context;
4149
4150     vl_msg_api_send_shmem (q, (u8 *)&mp);
4151 }
4152
4153 static void
4154 vl_api_l2_fib_table_dump_t_handler (vl_api_l2_fib_table_dump_t *mp)
4155 {
4156     vpe_api_main_t * am = &vpe_api_main;
4157     bd_main_t * bdm = &bd_main;
4158     l2fib_entry_key_t *l2fe_key = NULL;
4159     l2fib_entry_result_t *l2fe_res = NULL;
4160     u32 ni, bd_id = ntohl (mp->bd_id);
4161     u32 bd_index;
4162     unix_shared_memory_queue_t * q;
4163     uword * p;
4164
4165     q = vl_api_client_index_to_input_queue (mp->client_index);
4166     if (q == 0)
4167         return;
4168
4169     /* see l2fib_table_dump: ~0 means "any" */
4170     if (bd_id == ~0)
4171         bd_index = ~0;
4172     else {
4173         p = hash_get (bdm->bd_index_by_bd_id, bd_id);
4174         if (p == 0)
4175             return;
4176
4177         bd_index = p[0];
4178     }
4179
4180     l2fib_table_dump (bd_index, &l2fe_key, &l2fe_res);
4181
4182     vec_foreach_index (ni, l2fe_key) {
4183         send_l2fib_table_entry (am, q, vec_elt_at_index(l2fe_key, ni),
4184                                 vec_elt_at_index(l2fe_res, ni), mp->context);
4185     }
4186     vec_free(l2fe_key);
4187     vec_free(l2fe_res);
4188 }
4189
4190 static void
4191 vl_api_show_version_t_handler (vl_api_show_version_t *mp)
4192 {
4193     vl_api_show_version_reply_t *rmp;
4194     int rv = 0;
4195     char * vpe_api_get_build_directory(void);
4196     char * vpe_api_get_version(void);
4197     char * vpe_api_get_build_date(void);
4198
4199     unix_shared_memory_queue_t * q =
4200         vl_api_client_index_to_input_queue (mp->client_index);
4201
4202     if (!q)
4203         return;
4204
4205     REPLY_MACRO2(VL_API_SHOW_VERSION_REPLY,
4206     ({
4207         strncpy ((char *) rmp->program, "vpe", ARRAY_LEN(rmp->program)-1);
4208         strncpy ((char *) rmp->build_directory, vpe_api_get_build_directory(),
4209                  ARRAY_LEN(rmp->build_directory)-1);
4210         strncpy ((char *) rmp->version, vpe_api_get_version(),
4211                  ARRAY_LEN(rmp->version)-1);
4212         strncpy ((char *) rmp->build_date, vpe_api_get_build_date(),
4213                  ARRAY_LEN(rmp->build_date)-1);
4214     }));
4215 }
4216
4217 static void vl_api_get_node_index_t_handler
4218 (vl_api_get_node_index_t * mp)
4219 {
4220     vlib_main_t * vm = vlib_get_main();
4221     vl_api_get_node_index_reply_t * rmp;
4222     vlib_node_t * n;
4223     int rv = 0;
4224     u32 node_index = ~0;
4225
4226     n = vlib_get_node_by_name (vm, mp->node_name);
4227
4228     if (n == 0)
4229         rv = VNET_API_ERROR_NO_SUCH_NODE;
4230     else
4231         node_index = n->index;
4232
4233     REPLY_MACRO2(VL_API_GET_NODE_INDEX_REPLY,
4234     ({
4235         rmp->node_index = ntohl(node_index);
4236     }))
4237 }
4238
4239 static void vl_api_add_node_next_t_handler
4240 (vl_api_add_node_next_t * mp)
4241 {
4242     vlib_main_t * vm = vlib_get_main();
4243     vl_api_add_node_next_reply_t * rmp;
4244     vlib_node_t * n, * next;
4245     int rv = 0;
4246     u32 next_index = ~0;
4247
4248     n = vlib_get_node_by_name (vm, mp->node_name);
4249
4250     if (n == 0) {
4251         rv = VNET_API_ERROR_NO_SUCH_NODE;
4252         goto out;
4253     }
4254
4255     next = vlib_get_node_by_name (vm, mp->next_name);
4256
4257     if (next == 0)
4258         rv = VNET_API_ERROR_NO_SUCH_NODE2;
4259     else
4260         next_index = vlib_node_add_next (vm, n->index, next->index);
4261
4262 out:
4263     REPLY_MACRO2(VL_API_GET_NODE_INDEX_REPLY,
4264     ({
4265         rmp->next_index = ntohl(next_index);
4266     }))
4267 }
4268
4269 static void vl_api_l2tpv3_create_tunnel_t_handler
4270 (vl_api_l2tpv3_create_tunnel_t *mp)
4271 {
4272     vl_api_l2tpv3_create_tunnel_reply_t * rmp;
4273     l2t_main_t *lm = &l2t_main;
4274     u32 sw_if_index = (u32)~0;
4275     int rv;
4276
4277     if (mp->is_ipv6 != 1) {
4278         rv = VNET_API_ERROR_UNIMPLEMENTED;
4279         goto out;
4280     }
4281
4282     rv = create_l2tpv3_ipv6_tunnel (lm,
4283                                (ip6_address_t *) mp->client_address,
4284                                (ip6_address_t *) mp->our_address,
4285                                ntohl(mp->local_session_id),
4286                                ntohl(mp->remote_session_id),
4287                                clib_net_to_host_u64(mp->local_cookie),
4288                                clib_net_to_host_u64(mp->remote_cookie),
4289                                mp->l2_sublayer_present,
4290                                &sw_if_index);
4291
4292 out:
4293     REPLY_MACRO2(VL_API_L2TPV3_CREATE_TUNNEL_REPLY,
4294     ({
4295         rmp->sw_if_index = ntohl (sw_if_index);
4296     }))
4297 }
4298
4299 static void vl_api_l2tpv3_set_tunnel_cookies_t_handler
4300 (vl_api_l2tpv3_set_tunnel_cookies_t *mp)
4301 {
4302     vl_api_l2tpv3_set_tunnel_cookies_reply_t * rmp;
4303     l2t_main_t *lm = &l2t_main;
4304     int rv;
4305
4306     VALIDATE_SW_IF_INDEX(mp);
4307
4308     rv = l2tpv3_set_tunnel_cookies (lm, ntohl(mp->sw_if_index),
4309                                   clib_net_to_host_u64(mp->new_local_cookie),
4310                                   clib_net_to_host_u64(mp->new_remote_cookie));
4311
4312     BAD_SW_IF_INDEX_LABEL;
4313
4314     REPLY_MACRO (VL_API_L2TPV3_SET_TUNNEL_COOKIES_REPLY);
4315 }
4316
4317 static void vl_api_l2tpv3_interface_enable_disable_t_handler
4318 (vl_api_l2tpv3_interface_enable_disable_t * mp)
4319 {
4320     int rv;
4321     vnet_main_t * vnm = vnet_get_main();
4322     vl_api_l2tpv3_interface_enable_disable_reply_t * rmp;
4323
4324     VALIDATE_SW_IF_INDEX(mp);
4325
4326     rv = l2tpv3_interface_enable_disable
4327         (vnm, ntohl(mp->sw_if_index), mp->enable_disable);
4328
4329     BAD_SW_IF_INDEX_LABEL;
4330
4331     REPLY_MACRO (VL_API_L2TPV3_INTERFACE_ENABLE_DISABLE_REPLY);
4332 }
4333
4334 static void vl_api_l2tpv3_set_lookup_key_t_handler
4335 (vl_api_l2tpv3_set_lookup_key_t * mp)
4336 {
4337     int rv = 0;
4338     l2t_main_t *lm = &l2t_main;
4339     vl_api_l2tpv3_set_lookup_key_reply_t * rmp;
4340
4341     if (mp->key > L2T_LOOKUP_SESSION_ID) {
4342         rv = VNET_API_ERROR_INVALID_VALUE;
4343         goto out;
4344     }
4345
4346     lm->lookup_type = mp->key;
4347
4348 out:
4349     REPLY_MACRO (VL_API_L2TPV3_SET_LOOKUP_KEY_REPLY);
4350 }
4351
4352 static void vl_api_vxlan_add_del_tunnel_t_handler
4353 (vl_api_vxlan_add_del_tunnel_t * mp)
4354 {
4355     vl_api_vxlan_add_del_tunnel_reply_t * rmp;
4356     int rv = 0;
4357     vnet_vxlan_add_del_tunnel_args_t _a, *a = &_a;
4358     u32 encap_fib_index;
4359     uword * p;
4360     ip4_main_t * im = &ip4_main;
4361     u32 sw_if_index = ~0;
4362
4363     p = hash_get (im->fib_index_by_table_id, ntohl(mp->encap_vrf_id));
4364     if (! p) {
4365         rv = VNET_API_ERROR_NO_SUCH_FIB;
4366         goto out;
4367     }
4368     encap_fib_index = p[0];
4369
4370     /* Check src & dst are different */
4371     if ((mp->is_ipv6 && memcmp(mp->src_address, mp->dst_address, 16) == 0) ||
4372        (!mp->is_ipv6 && memcmp(mp->src_address, mp->dst_address, 4) == 0)) {
4373         rv = VNET_API_ERROR_SAME_SRC_DST;
4374         goto out;
4375     }
4376     memset (a, 0, sizeof (*a));
4377
4378     a->is_add = mp->is_add;
4379     a->is_ip6 = mp->is_ipv6;
4380
4381     /* ip addresses sent in network byte order */
4382     if (a->is_ip6) {
4383         memcpy(&(a->src.ip6), mp->src_address, 16);
4384         memcpy(&(a->dst.ip6), mp->dst_address, 16);
4385     } else {
4386         memcpy(&(a->src.ip4), mp->src_address, 4);
4387         memcpy(&(a->dst.ip4), mp->dst_address, 4);
4388     }
4389
4390     a->encap_fib_index = encap_fib_index;
4391     a->decap_next_index = ntohl(mp->decap_next_index);
4392     a->vni = ntohl(mp->vni);
4393     rv = vnet_vxlan_add_del_tunnel (a, &sw_if_index);
4394
4395 out:
4396     REPLY_MACRO2(VL_API_VXLAN_ADD_DEL_TUNNEL_REPLY,
4397     ({
4398         rmp->sw_if_index = ntohl (sw_if_index);
4399     }));
4400 }
4401
4402 static void send_vxlan_tunnel_details
4403 (vxlan_tunnel_t * t, unix_shared_memory_queue_t * q, u32 context)
4404 {
4405     vl_api_vxlan_tunnel_details_t * rmp;
4406     ip4_main_t * im4 = &ip4_main;
4407     ip6_main_t * im6 = &ip6_main;
4408     u8 is_ipv6 = !(t->flags & VXLAN_TUNNEL_IS_IPV4);
4409
4410     rmp = vl_msg_api_alloc (sizeof (*rmp));
4411     memset (rmp, 0, sizeof (*rmp));
4412     rmp->_vl_msg_id = ntohs(VL_API_VXLAN_TUNNEL_DETAILS);
4413     if (is_ipv6) {
4414         memcpy(rmp->src_address, &(t->src.ip6), 16);
4415         memcpy(rmp->dst_address, &(t->dst.ip6), 16);
4416         rmp->encap_vrf_id = htonl(im6->fibs[t->encap_fib_index].table_id);
4417     } else {
4418         memcpy(rmp->src_address, &(t->src.ip4), 4);
4419         memcpy(rmp->dst_address, &(t->dst.ip4), 4);
4420         rmp->encap_vrf_id = htonl(im4->fibs[t->encap_fib_index].table_id);
4421     }
4422     rmp->vni = htonl(t->vni);
4423     rmp->decap_next_index = htonl(t->decap_next_index);
4424     rmp->sw_if_index = htonl(t->sw_if_index);
4425     rmp->is_ipv6 = is_ipv6;
4426     rmp->context = context;
4427
4428     vl_msg_api_send_shmem (q, (u8 *)&rmp);
4429 }
4430
4431 static void vl_api_vxlan_tunnel_dump_t_handler
4432 (vl_api_vxlan_tunnel_dump_t * mp)
4433 {
4434     unix_shared_memory_queue_t * q;
4435     vxlan_main_t * vxm = &vxlan_main;
4436     vxlan_tunnel_t * t;
4437     u32 sw_if_index;
4438
4439     q = vl_api_client_index_to_input_queue (mp->client_index);
4440     if (q == 0) {
4441         return;
4442     }
4443
4444     sw_if_index = ntohl(mp->sw_if_index);
4445
4446     if (~0 == sw_if_index) {
4447         pool_foreach (t, vxm->tunnels,
4448         ({
4449             send_vxlan_tunnel_details(t, q, mp->context);
4450         }));
4451     } else {
4452         if ((sw_if_index >= vec_len(vxm->tunnel_index_by_sw_if_index)) ||
4453                 (~0 == vxm->tunnel_index_by_sw_if_index[sw_if_index])) {
4454             return;
4455         }
4456         t = &vxm->tunnels[vxm->tunnel_index_by_sw_if_index[sw_if_index]];
4457         send_vxlan_tunnel_details(t, q, mp->context);
4458     }
4459 }
4460
4461 static void vl_api_gre_add_del_tunnel_t_handler
4462 (vl_api_gre_add_del_tunnel_t * mp)
4463 {
4464     vl_api_gre_add_del_tunnel_reply_t * rmp;
4465     int rv = 0;
4466     vnet_gre_add_del_tunnel_args_t _a, *a = &_a;
4467     u32 outer_table_id;
4468     uword * p;
4469     ip4_main_t * im = &ip4_main;
4470     u32 sw_if_index = ~0;
4471
4472     p = hash_get (im->fib_index_by_table_id, ntohl(mp->outer_table_id));
4473     if (! p) {
4474         rv = VNET_API_ERROR_NO_SUCH_FIB;
4475         goto out;
4476     }
4477     outer_table_id = p[0];
4478
4479     /* Check src & dst are different */
4480     if (memcmp(&mp->src_address, &mp->dst_address, 4) == 0) {
4481         rv = VNET_API_ERROR_SAME_SRC_DST;
4482         goto out;
4483     }
4484
4485     memset (a, 0, sizeof (*a));
4486
4487     a->is_add = mp->is_add;
4488
4489     /* ip addresses sent in network byte order */
4490     a->src.as_u32 = mp->src_address;
4491     a->dst.as_u32 = mp->dst_address;
4492
4493     a->outer_table_id = outer_table_id;
4494     rv = vnet_gre_add_del_tunnel (a, &sw_if_index);
4495
4496 out:
4497     REPLY_MACRO2(VL_API_GRE_ADD_DEL_TUNNEL_REPLY,
4498     ({
4499         rmp->sw_if_index = ntohl (sw_if_index);
4500     }));
4501 }
4502
4503 static void send_gre_tunnel_details
4504 (gre_tunnel_t * t, unix_shared_memory_queue_t * q, u32 context)
4505 {
4506     vl_api_gre_tunnel_details_t * rmp;
4507     ip4_main_t * im = &ip4_main;
4508
4509     rmp = vl_msg_api_alloc (sizeof (*rmp));
4510     memset (rmp, 0, sizeof (*rmp));
4511     rmp->_vl_msg_id = ntohs(VL_API_GRE_TUNNEL_DETAILS);
4512     rmp->src_address = t->tunnel_src.data_u32;
4513     rmp->dst_address = t->tunnel_dst.data_u32;
4514     rmp->outer_table_id = htonl(im->fibs[t->outer_fib_index].table_id);
4515     rmp->sw_if_index = htonl(t->sw_if_index);
4516     rmp->context = context;
4517
4518     vl_msg_api_send_shmem (q, (u8 *)&rmp);
4519 }
4520
4521 static void vl_api_gre_tunnel_dump_t_handler
4522 (vl_api_gre_tunnel_dump_t * mp)
4523 {
4524     unix_shared_memory_queue_t * q;
4525     gre_main_t * gm = &gre_main;
4526     gre_tunnel_t * t;
4527     u32 sw_if_index;
4528
4529     q = vl_api_client_index_to_input_queue (mp->client_index);
4530     if (q == 0) {
4531         return;
4532     }
4533
4534     sw_if_index = ntohl(mp->sw_if_index);
4535
4536     if (~0 == sw_if_index) {
4537         pool_foreach (t, gm->tunnels,
4538         ({
4539             send_gre_tunnel_details(t, q, mp->context);
4540         }));
4541     } else {
4542         if ((sw_if_index >= vec_len(gm->tunnel_index_by_sw_if_index)) ||
4543                 (~0 == gm->tunnel_index_by_sw_if_index[sw_if_index])) {
4544             return;
4545         }
4546         t = &gm->tunnels[gm->tunnel_index_by_sw_if_index[sw_if_index]];
4547         send_gre_tunnel_details(t, q, mp->context);
4548     }
4549 }
4550
4551 static void
4552 vl_api_l2_patch_add_del_t_handler (vl_api_l2_patch_add_del_t *mp)
4553 {
4554     extern int vnet_l2_patch_add_del (u32 rx_sw_if_index, u32 tx_sw_if_index,
4555                                       int is_add);
4556     vl_api_l2_patch_add_del_reply_t * rmp;
4557     int vnet_l2_patch_add_del (u32 rx_sw_if_index, u32 tx_sw_if_index,
4558                                int is_add);
4559     int rv = 0;
4560
4561     VALIDATE_RX_SW_IF_INDEX(mp);
4562     VALIDATE_TX_SW_IF_INDEX(mp);
4563
4564     rv = vnet_l2_patch_add_del (ntohl(mp->rx_sw_if_index),
4565                                 ntohl(mp->tx_sw_if_index),
4566                                 (int)(mp->is_add != 0));
4567
4568     BAD_RX_SW_IF_INDEX_LABEL;
4569     BAD_TX_SW_IF_INDEX_LABEL;
4570
4571     REPLY_MACRO(VL_API_L2_PATCH_ADD_DEL_REPLY);
4572 }
4573
4574 static void
4575 vl_api_vxlan_gpe_add_del_tunnel_t_handler
4576 (vl_api_vxlan_gpe_add_del_tunnel_t * mp)
4577 {
4578     vl_api_vxlan_gpe_add_del_tunnel_reply_t * rmp;
4579     int rv = 0;
4580     vnet_vxlan_gpe_add_del_tunnel_args_t _a, *a = &_a;
4581     u32 encap_fib_index, decap_fib_index;
4582     u8 protocol;
4583     uword * p;
4584     ip4_main_t * im = &ip4_main;
4585     u32 sw_if_index = ~0;
4586
4587
4588     p = hash_get (im->fib_index_by_table_id, ntohl(mp->encap_vrf_id));
4589     if (! p) {
4590         rv = VNET_API_ERROR_NO_SUCH_FIB;
4591         goto out;
4592     }
4593     encap_fib_index = p[0];
4594
4595     protocol = mp->protocol;
4596
4597     /* Interpret decap_vrf_id as an opaque if sending to other-than-ip4-input */
4598     if (protocol == VXLAN_GPE_INPUT_NEXT_IP4_INPUT) {
4599         p = hash_get (im->fib_index_by_table_id, ntohl(mp->decap_vrf_id));
4600         if (! p) {
4601             rv = VNET_API_ERROR_NO_SUCH_INNER_FIB;
4602             goto out;
4603         }
4604         decap_fib_index = p[0];
4605     } else {
4606         decap_fib_index = ntohl(mp->decap_vrf_id);
4607     }
4608
4609     /* Check src & dst are different */
4610     if ((mp->is_ipv6 && memcmp(mp->local, mp->remote, 16) == 0) ||
4611        (!mp->is_ipv6 && memcmp(mp->local, mp->remote, 4) == 0)) {
4612         rv = VNET_API_ERROR_SAME_SRC_DST;
4613         goto out;
4614     }
4615     memset (a, 0, sizeof (*a));
4616
4617     a->is_add = mp->is_add;
4618     a->is_ip6 = mp->is_ipv6;
4619     /* ip addresses sent in network byte order */
4620     if (a->is_ip6) {
4621       clib_memcpy(&(a->local.ip6), mp->local, 16);
4622       clib_memcpy(&(a->remote.ip6), mp->remote, 16);
4623     } else {
4624       clib_memcpy(&(a->local.ip4), mp->local, 4);
4625       clib_memcpy(&(a->remote.ip4), mp->remote, 4);
4626     }
4627     a->encap_fib_index = encap_fib_index;
4628     a->decap_fib_index = decap_fib_index;
4629     a->protocol = protocol;
4630     a->vni = ntohl(mp->vni);
4631     rv = vnet_vxlan_gpe_add_del_tunnel (a, &sw_if_index);
4632
4633 out:
4634     REPLY_MACRO2(VL_API_VXLAN_GPE_ADD_DEL_TUNNEL_REPLY,
4635     ({
4636         rmp->sw_if_index = ntohl (sw_if_index);
4637     }));
4638 }
4639
4640 static void send_vxlan_gpe_tunnel_details
4641 (vxlan_gpe_tunnel_t * t, unix_shared_memory_queue_t * q, u32 context)
4642 {
4643     vl_api_vxlan_gpe_tunnel_details_t * rmp;
4644     ip4_main_t * im4 = &ip4_main;
4645     ip6_main_t * im6 = &ip6_main;
4646     u8 is_ipv6 = !(t->flags & VXLAN_GPE_TUNNEL_IS_IPV4);
4647
4648     rmp = vl_msg_api_alloc (sizeof (*rmp));
4649     memset (rmp, 0, sizeof (*rmp));
4650     rmp->_vl_msg_id = ntohs(VL_API_VXLAN_GPE_TUNNEL_DETAILS);
4651     if (is_ipv6) {
4652         memcpy(rmp->local, &(t->local.ip6), 16);
4653         memcpy(rmp->remote, &(t->remote.ip6), 16);
4654         rmp->encap_vrf_id = htonl(im6->fibs[t->encap_fib_index].table_id);
4655         rmp->decap_vrf_id = htonl(im6->fibs[t->decap_fib_index].table_id);
4656     } else {
4657         memcpy(rmp->local, &(t->local.ip4), 4);
4658         memcpy(rmp->remote, &(t->remote.ip4), 4);
4659         rmp->encap_vrf_id = htonl(im4->fibs[t->encap_fib_index].table_id);
4660         rmp->decap_vrf_id = htonl(im4->fibs[t->decap_fib_index].table_id);
4661     }
4662     rmp->vni = htonl(t->vni);
4663     rmp->protocol = t->protocol;
4664     rmp->sw_if_index = htonl(t->sw_if_index);
4665     rmp->is_ipv6 = is_ipv6;
4666     rmp->context = context;
4667
4668     vl_msg_api_send_shmem (q, (u8 *)&rmp);
4669 }
4670
4671 static void vl_api_vxlan_gpe_tunnel_dump_t_handler
4672 (vl_api_vxlan_gpe_tunnel_dump_t * mp)
4673 {
4674     unix_shared_memory_queue_t * q;
4675     vxlan_gpe_main_t * vgm = &vxlan_gpe_main;
4676     vxlan_gpe_tunnel_t * t;
4677     u32 sw_if_index;
4678
4679     q = vl_api_client_index_to_input_queue (mp->client_index);
4680     if (q == 0) {
4681         return;
4682     }
4683
4684     sw_if_index = ntohl(mp->sw_if_index);
4685
4686     if (~0 == sw_if_index) {
4687         pool_foreach (t, vgm->tunnels,
4688         ({
4689             send_vxlan_gpe_tunnel_details(t, q, mp->context);
4690         }));
4691     } else {
4692         if ((sw_if_index >= vec_len(vgm->tunnel_index_by_sw_if_index)) ||
4693                 (~0 == vgm->tunnel_index_by_sw_if_index[sw_if_index])) {
4694             return;
4695         }
4696         t = &vgm->tunnels[vgm->tunnel_index_by_sw_if_index[sw_if_index]];
4697         send_vxlan_gpe_tunnel_details(t, q, mp->context);
4698     }
4699 }
4700
4701 static void
4702 vl_api_lisp_add_del_locator_set_t_handler(vl_api_lisp_add_del_locator_set_t *mp)
4703 {
4704     vl_api_lisp_add_del_locator_set_reply_t *rmp;
4705     int rv = 0;
4706     vnet_lisp_add_del_locator_set_args_t _a, *a = &_a;
4707     u32 ls_index = ~0;
4708     u8 *locator_name = NULL;
4709
4710     memset(a, 0, sizeof(a[0]));
4711
4712     locator_name = format(0, "%s", mp->locator_set_name);
4713
4714     a->name = locator_name;
4715     a->locators = NULL;
4716     a->is_add = mp->is_add;
4717     a->local = 1;
4718
4719     rv = vnet_lisp_add_del_locator_set(a, &ls_index);
4720
4721     vec_free(locator_name);
4722
4723     REPLY_MACRO(VL_API_LISP_ADD_DEL_LOCATOR_SET_REPLY);
4724 }
4725
4726 static void
4727 vl_api_lisp_add_del_locator_t_handler(
4728     vl_api_lisp_add_del_locator_t *mp)
4729 {
4730     vl_api_lisp_add_del_locator_reply_t *rmp;
4731     int rv = 0;
4732     locator_t locator, *locators = NULL;
4733     vnet_lisp_add_del_locator_set_args_t _a, *a = &_a;
4734     u32 ls_index = ~0;
4735     u8 *locator_name = NULL;
4736
4737     memset(&locator, 0, sizeof(locator));
4738     memset(a, 0, sizeof(a[0]));
4739
4740     locator.sw_if_index = ntohl(mp->sw_if_index);
4741     locator.priority = mp->priority;
4742     locator.weight = mp->weight;
4743     locator.local = 1;
4744     vec_add1(locators, locator);
4745
4746     locator_name = format(0, "%s", mp->locator_set_name);
4747
4748     a->name = locator_name;
4749     a->locators = locators;
4750     a->is_add = mp->is_add;
4751     a->local = 1;
4752
4753     rv = vnet_lisp_add_del_locator(a, NULL, &ls_index);
4754
4755     vec_free(locators);
4756     vec_free(locator_name);
4757
4758     REPLY_MACRO(VL_API_LISP_ADD_DEL_LOCATOR_REPLY);
4759 }
4760
4761 static void
4762 vl_api_lisp_add_del_local_eid_t_handler(
4763     vl_api_lisp_add_del_local_eid_t *mp)
4764 {
4765     vl_api_lisp_add_del_local_eid_reply_t *rmp;
4766     lisp_cp_main_t * lcm = vnet_lisp_cp_get_main();
4767     int rv = 0;
4768     ip_prefix_t  *prefp = NULL;
4769     ip_address_t *ip_eid = NULL;
4770     gid_address_t eid;
4771     uword * p = NULL;
4772     u32 locator_set_index = ~0, map_index = ~0;
4773     vnet_lisp_add_del_mapping_args_t _a, *a = &_a;
4774     u8 *name = NULL;
4775     memset (a, 0, sizeof (a[0]));
4776
4777     prefp = &gid_address_ippref(&eid);
4778     ip_eid = &ip_prefix_addr(prefp);
4779     gid_address_type (&eid) = GID_ADDR_IP_PREFIX;
4780
4781     if (mp->is_ipv6) {
4782         clib_memcpy(&ip_addr_v6(ip_eid), mp->ip_address,
4783                sizeof(ip_addr_v6(ip_eid)));
4784         ip_addr_version(ip_eid) = IP6;
4785     } else {
4786         clib_memcpy(&ip_addr_v4(ip_eid), mp->ip_address,
4787                sizeof(ip_addr_v4(ip_eid)));
4788         ip_addr_version(ip_eid) = IP4;
4789     }
4790     ip_prefix_len(prefp) = mp->prefix_len;
4791
4792     name = format(0, "%s", mp->locator_set_name);
4793     p = hash_get_mem(lcm->locator_set_index_by_name, name);
4794     if (!p) {
4795         rv = VNET_API_ERROR_INVALID_VALUE;
4796         goto out;
4797     }
4798     locator_set_index = p[0];
4799
4800   /* XXX treat batch configuration */
4801     a->is_add = mp->is_add;
4802     gid_address_vni (&eid) = clib_net_to_host_u32 (mp->vni);
4803     a->deid = eid;
4804     a->locator_set_index = locator_set_index;
4805     a->local = 1;
4806     rv = vnet_lisp_add_del_local_mapping(a, &map_index);
4807
4808 out:
4809     vec_free(name);
4810     gid_address_free (&a->deid);
4811
4812     REPLY_MACRO(VL_API_LISP_ADD_DEL_LOCAL_EID_REPLY);
4813 }
4814
4815 static void
4816 vl_api_lisp_eid_table_add_del_map_t_handler(
4817     vl_api_lisp_eid_table_add_del_map_t *mp)
4818 {
4819     vl_api_lisp_eid_table_add_del_map_reply_t *rmp;
4820     int rv = 0;
4821     rv = vnet_lisp_eid_table_map (clib_net_to_host_u32 (mp->vni),
4822                                   clib_net_to_host_u32 (mp->vrf), mp->is_add);
4823     REPLY_MACRO(VL_API_LISP_EID_TABLE_ADD_DEL_MAP_REPLY)
4824 }
4825
4826 static void
4827 lisp_gpe_add_del_fwd_entry_set_address(
4828     vl_api_lisp_gpe_add_del_fwd_entry_t *mp,
4829     ip_address_t                        *slocator,
4830     ip_address_t                        *dlocator,
4831     gid_address_t                       *eid)
4832 {
4833     ip_address_t *ip_eid = NULL;
4834     ip_prefix_t *prefp = NULL;
4835
4836     prefp = &gid_address_ippref(eid);
4837     ip_eid = &ip_prefix_addr(prefp);
4838
4839     if (mp->eid_is_ipv6) {
4840         clib_memcpy(&ip_addr_v6(ip_eid), mp->eid_ip_address,
4841                sizeof(ip_addr_v6(ip_eid)));
4842         ip_addr_version(ip_eid) = IP6;
4843     } else {
4844         clib_memcpy(&ip_addr_v4(ip_eid), mp->eid_ip_address,
4845                sizeof(ip_addr_v4(ip_eid)));
4846         ip_addr_version(ip_eid) = IP4;
4847     }
4848     ip_prefix_len(prefp) = mp->eid_prefix_len;
4849
4850     if (mp->address_is_ipv6) {
4851         clib_memcpy(&ip_addr_v6(slocator), mp->source_ip_address,
4852                sizeof(ip_addr_v6(slocator)));
4853         ip_addr_version(slocator) = IP6;
4854         clib_memcpy(&ip_addr_v6(dlocator), mp->destination_ip_address,
4855                sizeof(ip_addr_v6(dlocator)));
4856         ip_addr_version(dlocator) = IP6;
4857     } else {
4858         clib_memcpy(&ip_addr_v4(slocator), mp->source_ip_address,
4859                sizeof(ip_addr_v4(slocator)));
4860         ip_addr_version(slocator) = IP4;
4861         clib_memcpy(&ip_addr_v4(dlocator), mp->destination_ip_address,
4862                sizeof(ip_addr_v4(dlocator)));
4863         ip_addr_version(dlocator) = IP4;
4864     }
4865 }
4866
4867 static void
4868 vl_api_lisp_gpe_add_del_fwd_entry_t_handler(
4869     vl_api_lisp_gpe_add_del_fwd_entry_t *mp)
4870 {
4871     vl_api_lisp_gpe_add_del_fwd_entry_reply_t *rmp;
4872     int rv = 0;
4873     ip_address_t slocator, dlocator;
4874     gid_address_t eid;
4875     vnet_lisp_gpe_add_del_fwd_entry_args_t a;
4876
4877     lisp_gpe_add_del_fwd_entry_set_address(mp, &slocator, &dlocator, &eid);
4878
4879     memset (&a, 0, sizeof(a));
4880
4881     a.is_add = mp->is_add;
4882     a.deid = eid;
4883     a.slocator = slocator;
4884     a.dlocator = dlocator;
4885     rv = vnet_lisp_gpe_add_del_fwd_entry (&a, 0);
4886
4887     REPLY_MACRO(VL_API_LISP_GPE_ADD_DEL_FWD_ENTRY_REPLY);
4888 }
4889
4890 static void
4891 vl_api_lisp_add_del_map_resolver_t_handler(
4892     vl_api_lisp_add_del_map_resolver_t *mp)
4893 {
4894     vl_api_lisp_add_del_map_resolver_reply_t *rmp;
4895     int rv = 0;
4896     ip_address_t *ip_addr = NULL;
4897     vnet_lisp_add_del_map_resolver_args_t _a, * a = &_a;
4898
4899     a->is_add = mp->is_add;
4900     ip_addr = &a->address;
4901
4902     if (mp->is_ipv6) {
4903         clib_memcpy(&ip_addr_v6(ip_addr), mp->ip_address,
4904                sizeof(ip_addr_v6(ip_addr)));
4905         ip_addr_version(ip_addr) = IP6;
4906     } else {
4907         clib_memcpy(&ip_addr_v4(ip_addr), mp->ip_address,
4908                sizeof(ip_addr_v4(ip_addr)));
4909         ip_addr_version(ip_addr) = IP4;
4910     }
4911
4912     rv = vnet_lisp_add_del_map_resolver (a);
4913
4914     REPLY_MACRO(VL_API_LISP_ADD_DEL_MAP_RESOLVER_REPLY);
4915 }
4916
4917 static void
4918 vl_api_lisp_gpe_enable_disable_t_handler(
4919     vl_api_lisp_gpe_enable_disable_t *mp)
4920 {
4921     vl_api_lisp_gpe_enable_disable_reply_t *rmp;
4922     int rv = 0;
4923     vnet_lisp_gpe_enable_disable_args_t _a, * a = &_a;
4924
4925     a->is_en = mp->is_en;
4926     vnet_lisp_gpe_enable_disable (a);
4927
4928     REPLY_MACRO(VL_API_LISP_GPE_ENABLE_DISABLE_REPLY);
4929 }
4930
4931 static void
4932 vl_api_lisp_enable_disable_t_handler(
4933     vl_api_lisp_enable_disable_t *mp)
4934 {
4935     vl_api_lisp_enable_disable_reply_t *rmp;
4936     int rv = 0;
4937
4938     vnet_lisp_enable_disable (mp->is_en);
4939     REPLY_MACRO(VL_API_LISP_ENABLE_DISABLE_REPLY);
4940 }
4941
4942 static void
4943 vl_api_lisp_gpe_add_del_iface_t_handler(
4944     vl_api_lisp_gpe_add_del_iface_t *mp)
4945 {
4946     vl_api_lisp_gpe_add_del_iface_reply_t *rmp;
4947     int rv = 0;
4948     vnet_lisp_gpe_add_del_iface_args_t _a, * a = &_a;
4949
4950     a->is_add = mp->is_add;
4951     a->table_id = mp->table_id;
4952     a->vni = mp->vni;
4953     rv = vnet_lisp_gpe_add_del_iface (a, 0);
4954
4955     REPLY_MACRO(VL_API_LISP_GPE_ADD_DEL_IFACE_REPLY);
4956 }
4957
4958 static void
4959 vl_api_lisp_pitr_set_locator_set_t_handler(
4960   vl_api_lisp_pitr_set_locator_set_t *mp)
4961 {
4962     vl_api_lisp_pitr_set_locator_set_reply_t *rmp;
4963     int rv = 0;
4964     u8 * ls_name = 0;
4965
4966     ls_name = format (0, "%s", mp->ls_name);
4967     rv = vnet_lisp_pitr_set_locator_set (ls_name, mp->is_add);
4968     vec_free (ls_name);
4969
4970     REPLY_MACRO(VL_API_LISP_PITR_SET_LOCATOR_SET_REPLY);
4971 }
4972
4973 static void
4974 vl_api_lisp_add_del_map_request_itr_rlocs_t_handler
4975 (vl_api_lisp_add_del_map_request_itr_rlocs_t *mp)
4976 {
4977     vl_api_lisp_add_del_map_request_itr_rlocs_reply_t *rmp;
4978     int rv = 0;
4979     u8 * locator_set_name = NULL;
4980     vnet_lisp_add_del_mreq_itr_rloc_args_t _a, * a = &_a;
4981
4982     locator_set_name = format (0, "%s", mp->locator_set_name);
4983
4984     a->is_add = mp->is_add;
4985     a->locator_set_name = locator_set_name;
4986
4987     rv = vnet_lisp_add_del_mreq_itr_rlocs(a);
4988
4989     vec_free(locator_set_name);
4990
4991     REPLY_MACRO(VL_API_LISP_ADD_DEL_MAP_REQUEST_ITR_RLOCS_REPLY);
4992 }
4993
4994 /** Used for transferring locators via VPP API */
4995 typedef CLIB_PACKED(struct
4996 {
4997   u8 is_ip4; /**< is locator an IPv4 address */
4998   u8 addr[16]; /**< IPv4/IPv6 address */
4999 }) rloc_t;
5000
5001 static void
5002 send_lisp_locator_set_details_set_address
5003 (vl_api_lisp_locator_set_details_t *rmp,
5004  gid_address_t *gid_address)
5005 {
5006     ip_prefix_t *ip_addr;
5007
5008     if (gid_address_type(gid_address) != GID_ADDR_IP_PREFIX) {
5009         return;
5010     }
5011
5012     ip_addr = &gid_address_ippref(gid_address);
5013     rmp->prefix_len = ip_prefix_len(ip_addr);
5014     rmp->is_ipv6 = ip_prefix_version(ip_addr);
5015     ip_address_copy_addr(rmp->ip_address, &ip_prefix_addr(ip_addr));
5016 }
5017
5018 static void
5019 vl_api_lisp_add_del_remote_mapping_t_handler (
5020     vl_api_lisp_add_del_remote_mapping_t *mp)
5021 {
5022     u32 i;
5023     ip_address_t rloc, * rlocs = 0;
5024     vl_api_lisp_add_del_remote_mapping_reply_t * rmp;
5025     int rv = 0;
5026     gid_address_t _seid, * seid = &_seid;
5027     gid_address_t _deid, * deid = &_deid;
5028     ip_prefix_t * seid_pref = &gid_address_ippref(seid);
5029     ip_prefix_t * deid_pref = &gid_address_ippref(deid);
5030
5031     gid_address_type(seid) = GID_ADDR_IP_PREFIX;
5032     gid_address_type(deid) = GID_ADDR_IP_PREFIX;
5033     ip_address_t * seid_addr = &ip_prefix_addr(seid_pref);
5034     ip_address_t * deid_addr = &ip_prefix_addr(deid_pref);
5035     ip_prefix_len(seid_pref) = mp->seid_len;
5036     ip_prefix_len(deid_pref) = mp->deid_len;
5037     gid_address_vni (seid) = ntohl (mp->vni);
5038     gid_address_vni (deid) = ntohl (mp->vni);
5039
5040     if (mp->eid_is_ip4) {
5041         ip_prefix_version(seid_pref) = IP4;
5042         ip_prefix_version(deid_pref) = IP4;
5043         clib_memcpy (&ip_addr_v4(seid_addr),
5044                      mp->seid, sizeof (ip_addr_v4(seid_addr)));
5045         clib_memcpy (&ip_addr_v4(deid_addr),
5046                      mp->deid, sizeof (ip_addr_v4(deid_addr)));
5047     } else {
5048         ip_prefix_version(seid_pref) = IP6;
5049         ip_prefix_version(deid_pref) = IP6;
5050         clib_memcpy (&ip_addr_v6(seid_addr),
5051                      mp->seid, sizeof (ip_addr_v6(seid_addr)));
5052         clib_memcpy (&ip_addr_v6(deid_addr),
5053                      mp->deid, sizeof (ip_addr_v6(deid_addr)));
5054     }
5055
5056     for (i = 0; i < mp->rloc_num; i++) {
5057         rloc_t * r = &((rloc_t *) mp->rlocs)[i];
5058         if (r->is_ip4) {
5059             clib_memcpy (&ip_addr_v4(&rloc), &r->addr, sizeof (rloc_t));
5060             ip_addr_version (&rloc) = IP4;
5061         } else {
5062             clib_memcpy (&ip_addr_v6(&rloc), &r->addr, sizeof (rloc_t));
5063             ip_addr_version (&rloc) = IP6;
5064         }
5065         vec_add1 (rlocs, rloc);
5066     }
5067
5068     rv = vnet_lisp_add_del_remote_mapping (deid, seid, rlocs, mp->action,
5069                                            mp->is_add, mp->del_all);
5070     vec_free (rlocs);
5071     REPLY_MACRO(VL_API_LISP_GPE_ADD_DEL_IFACE_REPLY);
5072 }
5073
5074 static void
5075 send_lisp_locator_set_details (lisp_cp_main_t *lcm,
5076                                locator_set_t *lsit,
5077                                unix_shared_memory_queue_t *q,
5078                                u32 context,
5079                                u32 index)
5080 {
5081     vl_api_lisp_locator_set_details_t *rmp;
5082     locator_t *loc = NULL;
5083     u32 * locit = NULL;
5084     u8 * str = NULL;
5085
5086     vec_foreach (locit, lsit->locator_indices) {
5087         loc = pool_elt_at_index (lcm->locator_pool, locit[0]);
5088         rmp = vl_msg_api_alloc (sizeof (*rmp));
5089         memset (rmp, 0, sizeof (*rmp));
5090         rmp->_vl_msg_id = ntohs(VL_API_LISP_LOCATOR_SET_DETAILS);
5091         rmp->local = lsit->local;
5092         if (lsit->local) {
5093             ASSERT(lsit->name != NULL);
5094             strncpy((char *) rmp->locator_set_name,
5095                     (char *) lsit->name, ARRAY_LEN(rmp->locator_set_name) - 1);
5096             rmp->sw_if_index = htonl(loc->sw_if_index);
5097         } else {
5098             str = format(0, "remote-%d", index);
5099             strncpy((char *) rmp->locator_set_name, (char *) str,
5100                     ARRAY_LEN(rmp->locator_set_name) - 1);
5101             send_lisp_locator_set_details_set_address(rmp, &loc->address);
5102
5103             vec_free(str);
5104         }
5105         rmp->priority = loc->priority;
5106         rmp->weight = loc->weight;
5107         rmp->context = context;
5108
5109         vl_msg_api_send_shmem (q, (u8 *)&rmp);
5110     }
5111 }
5112
5113 static void
5114 vl_api_lisp_locator_set_dump_t_handler (vl_api_lisp_locator_set_dump_t *mp)
5115 {
5116     unix_shared_memory_queue_t * q = NULL;
5117     lisp_cp_main_t * lcm = vnet_lisp_cp_get_main();
5118     locator_set_t * lsit = NULL;
5119     u32 index;
5120
5121     q = vl_api_client_index_to_input_queue (mp->client_index);
5122     if (q == 0) {
5123         return;
5124     }
5125
5126     index = 0;
5127     pool_foreach (lsit, lcm->locator_set_pool,
5128         ({
5129             send_lisp_locator_set_details(lcm, lsit, q, mp->context, index++);
5130         }));
5131 }
5132
5133 static void
5134 send_lisp_local_eid_table_details (mapping_t *mapit,
5135                                    unix_shared_memory_queue_t *q,
5136                                    u32 context)
5137 {
5138     vl_api_lisp_local_eid_table_details_t *rmp = NULL;
5139     lisp_cp_main_t * lcm = vnet_lisp_cp_get_main();
5140     locator_set_t *ls = NULL;
5141     gid_address_t *gid = NULL;
5142     ip_prefix_t *ip_prefix = NULL;
5143     u8 * str = NULL;
5144     u8 type = ~0;
5145
5146     ls = pool_elt_at_index (lcm->locator_set_pool,
5147                             mapit->locator_set_index);
5148
5149     gid = &mapit->eid;
5150     type = gid_address_type(gid);
5151
5152     if (type != GID_ADDR_IP_PREFIX) {
5153         return;
5154     }
5155
5156     ip_prefix = &gid_address_ippref(gid);
5157
5158     rmp = vl_msg_api_alloc (sizeof (*rmp));
5159     memset (rmp, 0, sizeof (*rmp));
5160     rmp->_vl_msg_id = ntohs(VL_API_LISP_LOCAL_EID_TABLE_DETAILS);
5161     if (ls->local) {
5162         ASSERT(ls->name != NULL);
5163         strncpy((char *) rmp->locator_set_name,
5164                 (char *) ls->name, ARRAY_LEN(rmp->locator_set_name) - 1);
5165     } else {
5166             str = format(0, "remote-%d", mapit->locator_set_index);
5167             strncpy((char *) rmp->locator_set_name, (char *) str,
5168                     ARRAY_LEN(rmp->locator_set_name) - 1);
5169             vec_free(str);
5170     }
5171
5172     switch (ip_prefix_version(ip_prefix)) {
5173         case IP4:
5174             rmp->eid_is_ipv6 = 0;
5175             clib_memcpy(rmp->eid_ip_address, &ip_prefix_v4(ip_prefix),
5176                    sizeof(ip_prefix_v4(ip_prefix)));
5177             break;
5178
5179         case IP6:
5180             rmp->eid_is_ipv6 = 1;
5181             clib_memcpy(rmp->eid_ip_address, &ip_prefix_v6(ip_prefix),
5182                    sizeof(ip_prefix_v6(ip_prefix)));
5183             break;
5184
5185         default:
5186             ASSERT(0);
5187     }
5188     rmp->eid_prefix_len = ip_prefix_len(ip_prefix);
5189     rmp->context = context;
5190     rmp->vni = clib_host_to_net_u32 (gid_address_vni (gid));
5191     vl_msg_api_send_shmem (q, (u8 *)&rmp);
5192 }
5193
5194 static void
5195 vl_api_lisp_local_eid_table_dump_t_handler (
5196     vl_api_lisp_local_eid_table_dump_t *mp)
5197 {
5198     unix_shared_memory_queue_t * q = NULL;
5199     lisp_cp_main_t * lcm = vnet_lisp_cp_get_main();
5200     mapping_t * mapit = NULL;
5201
5202     q = vl_api_client_index_to_input_queue (mp->client_index);
5203     if (q == 0) {
5204         return;
5205     }
5206
5207     pool_foreach (mapit, lcm->mapping_pool,
5208         ({
5209             send_lisp_local_eid_table_details(mapit, q, mp->context);
5210         }));
5211 }
5212
5213 static void
5214 send_lisp_gpe_tunnel_details (lisp_gpe_tunnel_t *tunnel,
5215                               unix_shared_memory_queue_t *q,
5216                               u32 context)
5217 {
5218     vl_api_lisp_gpe_tunnel_details_t *rmp;
5219     lisp_gpe_main_t * lgm = &lisp_gpe_main;
5220
5221     rmp = vl_msg_api_alloc (sizeof (*rmp));
5222     memset (rmp, 0, sizeof (*rmp));
5223     rmp->_vl_msg_id = ntohs(VL_API_LISP_GPE_TUNNEL_DETAILS);
5224
5225     rmp->tunnels = tunnel - lgm->tunnels;
5226
5227     rmp->is_ipv6 = ip_addr_version(&tunnel->src) == IP6 ? 1 : 0;
5228     ip_address_copy_addr(rmp->source_ip, &tunnel->src);
5229     ip_address_copy_addr(rmp->destination_ip, &tunnel->dst);
5230
5231     rmp->encap_fib_id = htonl(tunnel->encap_fib_index);
5232     rmp->decap_fib_id = htonl(tunnel->decap_fib_index);
5233     rmp->dcap_next = htonl(tunnel->decap_next_index);
5234     rmp->lisp_ver = tunnel->ver_res;
5235     rmp->next_protocol = tunnel->next_protocol;
5236     rmp->flags = tunnel->flags;
5237     rmp->ver_res = tunnel->ver_res;
5238     rmp->res = tunnel->res;
5239     rmp->iid = htonl(tunnel->vni);
5240     rmp->context = context;
5241
5242     vl_msg_api_send_shmem (q, (u8 *)&rmp);
5243 }
5244
5245 static void
5246 vl_api_lisp_gpe_tunnel_dump_t_handler (
5247     vl_api_lisp_gpe_tunnel_dump_t *mp)
5248 {
5249     unix_shared_memory_queue_t * q = NULL;
5250     lisp_gpe_main_t * lgm = &lisp_gpe_main;
5251     lisp_gpe_tunnel_t * tunnel = NULL;
5252
5253     if (pool_elts(lgm->tunnels) == 0) {
5254         return;
5255     }
5256
5257     q = vl_api_client_index_to_input_queue (mp->client_index);
5258     if (q == 0) {
5259         return;
5260     }
5261
5262     pool_foreach(tunnel, lgm->tunnels,
5263                  ({
5264                      send_lisp_gpe_tunnel_details(tunnel, q, mp->context);
5265                 }));
5266 }
5267
5268 static void
5269 send_lisp_map_resolver_details (ip_address_t *ip,
5270                                 unix_shared_memory_queue_t *q,
5271                                 u32 context)
5272 {
5273     vl_api_lisp_map_resolver_details_t *rmp = NULL;
5274
5275     rmp = vl_msg_api_alloc (sizeof (*rmp));
5276     memset (rmp, 0, sizeof (*rmp));
5277     rmp->_vl_msg_id = ntohs(VL_API_LISP_MAP_RESOLVER_DETAILS);
5278
5279     switch (ip_addr_version(ip)) {
5280         case IP4:
5281             rmp->is_ipv6 = 0;
5282             clib_memcpy(rmp->ip_address, &ip_addr_v4(ip), sizeof(ip_addr_v4(ip)));
5283             break;
5284
5285         case IP6:
5286             rmp->is_ipv6 = 1;
5287             clib_memcpy(rmp->ip_address, &ip_addr_v6(ip), sizeof(ip_addr_v6(ip)));
5288             break;
5289
5290         default:
5291             ASSERT(0);
5292     }
5293     rmp->context = context;
5294
5295     vl_msg_api_send_shmem (q, (u8 *)&rmp);
5296 }
5297
5298 static void
5299 vl_api_lisp_map_resolver_dump_t_handler (
5300     vl_api_lisp_map_resolver_dump_t *mp)
5301 {
5302     unix_shared_memory_queue_t * q = NULL;
5303     lisp_cp_main_t * lcm = vnet_lisp_cp_get_main();
5304     ip_address_t *ip = NULL;
5305
5306     q = vl_api_client_index_to_input_queue (mp->client_index);
5307     if (q == 0) {
5308         return;
5309     }
5310
5311     vec_foreach(ip, lcm->map_resolvers) {
5312         send_lisp_map_resolver_details(ip, q, mp->context);
5313     }
5314
5315 }
5316
5317 static void
5318 vl_api_lisp_eid_table_map_dump_t_handler (
5319     vl_api_lisp_eid_table_map_dump_t *mp)
5320 {
5321     unix_shared_memory_queue_t * q = NULL;
5322     lisp_cp_main_t * lcm = vnet_lisp_cp_get_main();
5323     hash_pair_t * p;
5324
5325     q = vl_api_client_index_to_input_queue (mp->client_index);
5326     if (q == 0) {
5327         return;
5328     }
5329     hash_foreach_pair (p, lcm->table_id_by_vni, {
5330         vl_api_lisp_eid_table_map_details_t * rmp = NULL;
5331         memset (rmp, 0, sizeof (*rmp));
5332         rmp->_vl_msg_id = ntohs(VL_API_LISP_EID_TABLE_MAP_DETAILS);
5333         rmp->vni = p->key;
5334         rmp->vrf = p->value[0];
5335         rmp->context = mp->context;
5336     });
5337 }
5338
5339 static void
5340 send_lisp_enable_disable_details (unix_shared_memory_queue_t *q,
5341                                       u32 context)
5342 {
5343     vl_api_lisp_enable_disable_status_details_t *rmp = NULL;
5344
5345     rmp = vl_msg_api_alloc (sizeof (*rmp));
5346     memset (rmp, 0, sizeof (*rmp));
5347     rmp->_vl_msg_id = ntohs(VL_API_LISP_ENABLE_DISABLE_STATUS_DETAILS);
5348
5349     rmp->gpe_status = vnet_lisp_gpe_enable_disable_status ();
5350     rmp->feature_status = vnet_lisp_enable_disable_status ();
5351     rmp->context = context;
5352
5353     vl_msg_api_send_shmem (q, (u8 *)&rmp);
5354 }
5355
5356 static void
5357 vl_api_lisp_enable_disable_status_dump_t_handler
5358 (vl_api_lisp_enable_disable_status_dump_t *mp)
5359 {
5360     unix_shared_memory_queue_t * q = NULL;
5361
5362     q = vl_api_client_index_to_input_queue (mp->client_index);
5363     if (q == 0) {
5364         return;
5365     }
5366
5367     send_lisp_enable_disable_details(q, mp->context);
5368 }
5369
5370 static void
5371 vl_api_lisp_get_map_request_itr_rlocs_t_handler (
5372     vl_api_lisp_get_map_request_itr_rlocs_t *mp)
5373 {
5374     unix_shared_memory_queue_t * q = NULL;
5375     vl_api_lisp_get_map_request_itr_rlocs_reply_t *rmp = NULL;
5376     lisp_cp_main_t * lcm = vnet_lisp_cp_get_main();
5377     locator_set_t * loc_set = 0;
5378     u8 * tmp_str = 0;
5379     int rv = 0;
5380
5381     q = vl_api_client_index_to_input_queue (mp->client_index);
5382     if (q == 0) {
5383         return;
5384     }
5385
5386     if (~0 == lcm->mreq_itr_rlocs) {
5387       tmp_str = format(0, " ");
5388     } else {
5389       loc_set = pool_elt_at_index (lcm->locator_set_pool, lcm->mreq_itr_rlocs);
5390       tmp_str = format(0, "%s", loc_set->name);
5391     }
5392
5393     REPLY_MACRO2(VL_API_LISP_GET_MAP_REQUEST_ITR_RLOCS_REPLY,
5394     ({
5395       strncpy((char *) rmp->locator_set_name, (char *) tmp_str,
5396               ARRAY_LEN(rmp->locator_set_name) - 1);
5397     }));
5398
5399     vec_free(tmp_str);
5400 }
5401
5402 static void
5403 vl_api_interface_name_renumber_t_handler (vl_api_interface_name_renumber_t *mp)
5404 {
5405     vl_api_interface_name_renumber_reply_t * rmp;
5406     int rv = 0;
5407
5408     VALIDATE_SW_IF_INDEX(mp);
5409
5410     rv = vnet_interface_name_renumber
5411         (ntohl(mp->sw_if_index), ntohl(mp->new_show_dev_instance));
5412
5413     BAD_SW_IF_INDEX_LABEL;
5414
5415     REPLY_MACRO(VL_API_INTERFACE_NAME_RENUMBER_REPLY);
5416 }
5417
5418 static int arp_change_data_callback (u32 pool_index, u8 * new_mac,
5419                                      u32 sw_if_index, u32 address)
5420 {
5421     vpe_api_main_t * am = &vpe_api_main;
5422     vlib_main_t * vm = am->vlib_main;
5423     vl_api_ip4_arp_event_t * event;
5424     static f64 arp_event_last_time;
5425     f64 now = vlib_time_now (vm);
5426
5427     if (pool_is_free_index (am->arp_events, pool_index))
5428         return 1;
5429
5430     event = pool_elt_at_index (am->arp_events, pool_index);
5431     if (memcmp (&event->new_mac, new_mac, sizeof (event->new_mac))) {
5432         clib_memcpy (event->new_mac, new_mac, sizeof(event->new_mac));
5433     } else { /* same mac */
5434         if ((sw_if_index == event->sw_if_index) &&
5435             ((address == 0) ||
5436              /* for BD case, also check IP address with 10 sec timeout */
5437              ((address == event->address) &&
5438               ((now - arp_event_last_time) < 10.0))))
5439             return 1;
5440     }
5441
5442     arp_event_last_time = now;
5443     event->sw_if_index = sw_if_index;
5444     if (address) event->address = address;
5445     return 0;
5446 }
5447
5448 static int arp_change_delete_callback (u32 pool_index, u8 * notused)
5449 {
5450     vpe_api_main_t * am = &vpe_api_main;
5451
5452     if (pool_is_free_index (am->arp_events, pool_index))
5453         return 1;
5454
5455     pool_put_index (am->arp_events, pool_index);
5456     return 0;
5457 }
5458
5459 static void
5460 vl_api_want_ip4_arp_events_t_handler
5461 (vl_api_want_ip4_arp_events_t * mp)
5462 {
5463     vpe_api_main_t * am = &vpe_api_main;
5464     vnet_main_t * vnm = vnet_get_main();
5465     vl_api_want_ip4_arp_events_reply_t *rmp;
5466     vl_api_ip4_arp_event_t * event;
5467     int rv;
5468
5469     if (mp->enable_disable) {
5470         pool_get (am->arp_events, event);
5471         memset (event, 0, sizeof (*event));
5472
5473         event->_vl_msg_id = ntohs(VL_API_IP4_ARP_EVENT);
5474         event->client_index = mp->client_index;
5475         event->context = mp->context;
5476         event->address = mp->address;
5477         event->pid = mp->pid;
5478
5479         rv = vnet_add_del_ip4_arp_change_event
5480             (vnm, arp_change_data_callback,
5481              mp->pid,
5482              &mp->address /* addr, in net byte order */,
5483              vpe_resolver_process_node.index,
5484              IP4_ARP_EVENT, event - am->arp_events, 1 /* is_add */);
5485     } else {
5486         rv = vnet_add_del_ip4_arp_change_event
5487             (vnm, arp_change_delete_callback,
5488              mp->pid,
5489              &mp->address /* addr, in net byte order */,
5490              vpe_resolver_process_node.index,
5491              IP4_ARP_EVENT, ~0 /* pool index */, 0 /* is_add */);
5492     }
5493     REPLY_MACRO(VL_API_WANT_IP4_ARP_EVENTS_REPLY);
5494 }
5495
5496 static void vl_api_input_acl_set_interface_t_handler
5497 (vl_api_input_acl_set_interface_t * mp)
5498 {
5499     vlib_main_t *vm = vlib_get_main();
5500     vl_api_input_acl_set_interface_reply_t * rmp;
5501     int rv;
5502     u32 sw_if_index, ip4_table_index, ip6_table_index, l2_table_index;
5503
5504     ip4_table_index = ntohl(mp->ip4_table_index);
5505     ip6_table_index = ntohl(mp->ip6_table_index);
5506     l2_table_index = ntohl(mp->l2_table_index);
5507     sw_if_index = ntohl(mp->sw_if_index);
5508
5509     VALIDATE_SW_IF_INDEX(mp);
5510
5511     rv = vnet_set_input_acl_intfc (vm, sw_if_index, ip4_table_index,
5512                                    ip6_table_index, l2_table_index,
5513                                    mp->is_add);
5514
5515     BAD_SW_IF_INDEX_LABEL;
5516
5517     REPLY_MACRO(VL_API_INPUT_ACL_SET_INTERFACE_REPLY);
5518 }
5519
5520 static void vl_api_ipsec_spd_add_del_t_handler
5521 (vl_api_ipsec_spd_add_del_t * mp)
5522 {
5523 #if IPSEC == 0
5524     clib_warning ("unimplemented");
5525 #else
5526
5527     vlib_main_t *vm __attribute__((unused)) = vlib_get_main();
5528     vl_api_ipsec_spd_add_del_reply_t * rmp;
5529     int rv;
5530
5531 #if DPDK > 0
5532     rv = ipsec_add_del_spd (vm, ntohl(mp->spd_id), mp->is_add);
5533 #else
5534     rv = VNET_API_ERROR_UNIMPLEMENTED;
5535 #endif
5536
5537     REPLY_MACRO(VL_API_IPSEC_SPD_ADD_DEL_REPLY);
5538 #endif
5539 }
5540
5541 static void vl_api_ipsec_interface_add_del_spd_t_handler
5542 (vl_api_ipsec_interface_add_del_spd_t * mp)
5543 {
5544     vlib_main_t *vm __attribute__((unused)) = vlib_get_main();
5545     vl_api_ipsec_interface_add_del_spd_reply_t * rmp;
5546     int rv;
5547     u32 sw_if_index __attribute__((unused));
5548     u32 spd_id __attribute__((unused));
5549
5550     sw_if_index = ntohl(mp->sw_if_index);
5551     spd_id = ntohl(mp->spd_id);
5552
5553     VALIDATE_SW_IF_INDEX(mp);
5554
5555 #if IPSEC > 0
5556     rv = ipsec_set_interface_spd(vm, sw_if_index, spd_id, mp->is_add);
5557 #else
5558     rv = VNET_API_ERROR_UNIMPLEMENTED;
5559 #endif
5560
5561     BAD_SW_IF_INDEX_LABEL;
5562
5563     REPLY_MACRO(VL_API_IPSEC_INTERFACE_ADD_DEL_SPD_REPLY);
5564 }
5565
5566 static void vl_api_ipsec_spd_add_del_entry_t_handler
5567 (vl_api_ipsec_spd_add_del_entry_t * mp)
5568 {
5569     vlib_main_t *vm __attribute__((unused)) = vlib_get_main();
5570     vl_api_ipsec_spd_add_del_entry_reply_t * rmp;
5571     int rv;
5572
5573 #if IPSEC > 0
5574     ipsec_policy_t p;
5575
5576     memset(&p, 0, sizeof(p));
5577
5578     p.id = ntohl(mp->spd_id);
5579     p.priority = ntohl(mp->priority);
5580     p.is_outbound = mp->is_outbound;
5581     p.is_ipv6 = mp->is_ipv6;
5582
5583     clib_memcpy(&p.raddr.start, mp->remote_address_start, 16);
5584     clib_memcpy(&p.raddr.stop, mp->remote_address_stop, 16);
5585     clib_memcpy(&p.laddr.start, mp->local_address_start, 16);
5586     clib_memcpy(&p.laddr.stop, mp->local_address_stop, 16);
5587
5588     p.protocol = mp->protocol;
5589     p.rport.start = ntohs(mp->remote_port_start);
5590     p.rport.stop  = ntohs(mp->remote_port_stop);
5591     p.lport.start = ntohs(mp->local_port_start);
5592     p.lport.stop  = ntohs(mp->local_port_stop);
5593     /* policy action resolve unsupported */
5594     if (mp->policy == IPSEC_POLICY_ACTION_RESOLVE) {
5595         clib_warning("unsupported action: 'resolve'");
5596         rv = VNET_API_ERROR_UNIMPLEMENTED;
5597         goto out;
5598     }
5599     p.policy = mp->policy;
5600     p.sa_id = ntohl(mp->sa_id);
5601
5602     rv = ipsec_add_del_policy(vm, &p, mp->is_add);
5603     if (rv)
5604       goto out;
5605
5606     if (mp->is_ip_any) {
5607       p.is_ipv6 = 1;
5608       rv = ipsec_add_del_policy(vm, &p, mp->is_add);
5609     }
5610 #else
5611     rv = VNET_API_ERROR_UNIMPLEMENTED;
5612     goto out;
5613 #endif
5614
5615 out:
5616     REPLY_MACRO(VL_API_IPSEC_SPD_ADD_DEL_ENTRY_REPLY);
5617 }
5618
5619 static void vl_api_ipsec_sad_add_del_entry_t_handler
5620 (vl_api_ipsec_sad_add_del_entry_t * mp)
5621 {
5622     vlib_main_t *vm __attribute__((unused)) = vlib_get_main();
5623     vl_api_ipsec_sad_add_del_entry_reply_t * rmp;
5624     int rv;
5625 #if IPSEC > 0
5626     ipsec_sa_t sa;
5627
5628     memset(&sa, 0, sizeof(sa));
5629
5630     sa.id = ntohl(mp->sad_id);
5631     sa.spi = ntohl(mp->spi);
5632     /* security protocol AH unsupported */
5633     if (mp->protocol == IPSEC_PROTOCOL_AH) {
5634         clib_warning("unsupported security protocol 'AH'");
5635         rv = VNET_API_ERROR_UNIMPLEMENTED;
5636         goto out;
5637     }
5638     sa.protocol = mp->protocol;
5639     /* check for unsupported crypto-alg */
5640     if (mp->crypto_algorithm < IPSEC_CRYPTO_ALG_AES_CBC_128 ||
5641         mp->crypto_algorithm > IPSEC_CRYPTO_ALG_AES_CBC_256) {
5642         clib_warning("unsupported crypto-alg: '%U'", format_ipsec_crypto_alg,
5643                      mp->crypto_algorithm);
5644         rv = VNET_API_ERROR_UNIMPLEMENTED;
5645         goto out;
5646     }
5647     sa.crypto_alg = mp->crypto_algorithm;
5648     sa.crypto_key_len = mp->crypto_key_length;
5649     clib_memcpy(&sa.crypto_key, mp->crypto_key, sizeof(sa.crypto_key));
5650     /* check for unsupported integ-alg */
5651     if (mp->integrity_algorithm < IPSEC_INTEG_ALG_SHA1_96 ||
5652         mp->integrity_algorithm > IPSEC_INTEG_ALG_SHA_512_256) {
5653         clib_warning("unsupported integ-alg: '%U'", format_ipsec_integ_alg,
5654                      mp->integrity_algorithm);
5655         rv = VNET_API_ERROR_UNIMPLEMENTED;
5656         goto out;
5657     }
5658     sa.integ_alg = mp->integrity_algorithm;
5659     sa.integ_key_len = mp->integrity_key_length;
5660     clib_memcpy(&sa.integ_key, mp->integrity_key, sizeof(sa.integ_key));
5661     sa.use_esn = mp->use_extended_sequence_number;
5662     sa.is_tunnel = mp->is_tunnel;
5663     sa.is_tunnel_ip6 = mp->is_tunnel_ipv6;
5664     clib_memcpy(&sa.tunnel_src_addr, mp->tunnel_src_address, 16);
5665     clib_memcpy(&sa.tunnel_dst_addr, mp->tunnel_dst_address, 16);
5666
5667     rv = ipsec_add_del_sa(vm, &sa, mp->is_add);
5668 #else
5669     rv = VNET_API_ERROR_UNIMPLEMENTED;
5670     goto out;
5671 #endif
5672
5673 out:
5674     REPLY_MACRO(VL_API_IPSEC_SAD_ADD_DEL_ENTRY_REPLY);
5675 }
5676
5677 static void
5678 vl_api_ikev2_profile_add_del_t_handler
5679 (vl_api_ikev2_profile_add_del_t * mp)
5680 {
5681     vl_api_ikev2_profile_add_del_reply_t * rmp;
5682     int rv = 0;
5683
5684 #if IPSEC > 0
5685     vlib_main_t * vm = vlib_get_main();
5686     clib_error_t * error;
5687     u8 * tmp = format(0, "%s", mp->name);
5688     error = ikev2_add_del_profile(vm, tmp, mp->is_add);
5689     vec_free (tmp);
5690     if (error)
5691       rv = VNET_API_ERROR_UNSPECIFIED;
5692 #else
5693     rv = VNET_API_ERROR_UNIMPLEMENTED;
5694 #endif
5695
5696    REPLY_MACRO(VL_API_IKEV2_PROFILE_ADD_DEL_REPLY);
5697 }
5698
5699 static void
5700 vl_api_ikev2_profile_set_auth_t_handler
5701 (vl_api_ikev2_profile_set_auth_t * mp)
5702 {
5703     vl_api_ikev2_profile_set_auth_reply_t * rmp;
5704     int rv = 0;
5705
5706 #if IPSEC > 0
5707     vlib_main_t * vm = vlib_get_main();
5708     clib_error_t * error;
5709     u8 * tmp = format(0, "%s", mp->name);
5710     u8 * data = vec_new (u8, mp->data_len);
5711     clib_memcpy(data, mp->data, mp->data_len);
5712     error = ikev2_set_profile_auth(vm, tmp, mp->auth_method, data, mp->is_hex);
5713     vec_free (tmp);
5714     vec_free (data);
5715     if (error)
5716       rv = VNET_API_ERROR_UNSPECIFIED;
5717 #else
5718     rv = VNET_API_ERROR_UNIMPLEMENTED;
5719 #endif
5720
5721    REPLY_MACRO(VL_API_IKEV2_PROFILE_SET_AUTH_REPLY);
5722 }
5723
5724 static void
5725 vl_api_ikev2_profile_set_id_t_handler
5726 (vl_api_ikev2_profile_set_id_t * mp)
5727 {
5728     vl_api_ikev2_profile_add_del_reply_t * rmp;
5729     int rv = 0;
5730
5731 #if IPSEC > 0
5732     vlib_main_t * vm = vlib_get_main();
5733     clib_error_t * error;
5734     u8 * tmp = format(0, "%s", mp->name);
5735     u8 * data = vec_new (u8, mp->data_len);
5736     clib_memcpy(data, mp->data, mp->data_len);
5737     error = ikev2_set_profile_id(vm, tmp, mp->id_type, data, mp->is_local);
5738     vec_free (tmp);
5739     vec_free (data);
5740     if (error)
5741       rv = VNET_API_ERROR_UNSPECIFIED;
5742 #else
5743     rv = VNET_API_ERROR_UNIMPLEMENTED;
5744 #endif
5745
5746    REPLY_MACRO(VL_API_IKEV2_PROFILE_SET_ID_REPLY);
5747 }
5748
5749 static void
5750 vl_api_ikev2_profile_set_ts_t_handler
5751 (vl_api_ikev2_profile_set_ts_t * mp)
5752 {
5753     vl_api_ikev2_profile_set_ts_reply_t * rmp;
5754     int rv = 0;
5755
5756 #if IPSEC > 0
5757     vlib_main_t * vm = vlib_get_main();
5758     clib_error_t * error;
5759     u8 * tmp = format(0, "%s", mp->name);
5760     error = ikev2_set_profile_ts(vm, tmp, mp->proto, mp->start_port,
5761                                  mp->end_port, (ip4_address_t) mp->start_addr,
5762                                  (ip4_address_t) mp->end_addr, mp->is_local);
5763     vec_free (tmp);
5764     if (error)
5765       rv = VNET_API_ERROR_UNSPECIFIED;
5766 #else
5767     rv = VNET_API_ERROR_UNIMPLEMENTED;
5768 #endif
5769
5770    REPLY_MACRO(VL_API_IKEV2_PROFILE_SET_TS_REPLY);
5771 }
5772
5773 static void
5774 vl_api_ikev2_set_local_key_t_handler
5775 (vl_api_ikev2_set_local_key_t * mp)
5776 {
5777     vl_api_ikev2_profile_set_ts_reply_t * rmp;
5778     int rv = 0;
5779
5780 #if IPSEC > 0
5781     vlib_main_t * vm = vlib_get_main();
5782     clib_error_t * error;
5783
5784     error = ikev2_set_local_key(vm, mp->key_file);
5785     if (error)
5786       rv = VNET_API_ERROR_UNSPECIFIED;
5787 #else
5788     rv = VNET_API_ERROR_UNIMPLEMENTED;
5789 #endif
5790
5791    REPLY_MACRO(VL_API_IKEV2_SET_LOCAL_KEY_REPLY);
5792 }
5793
5794 static void
5795 vl_api_map_add_domain_t_handler
5796 (vl_api_map_add_domain_t * mp)
5797 {
5798   vl_api_map_add_domain_reply_t * rmp;
5799   int rv = 0;
5800   u32 index;
5801   u8 flags = mp->is_translation ? MAP_DOMAIN_TRANSLATION : 0;
5802   rv = map_create_domain((ip4_address_t *)&mp->ip4_prefix, mp->ip4_prefix_len,
5803                          (ip6_address_t *)&mp->ip6_prefix, mp->ip6_prefix_len,
5804                          (ip6_address_t *)&mp->ip6_src, mp->ip6_src_prefix_len,
5805                          mp->ea_bits_len, mp->psid_offset, mp->psid_length, &index, ntohs(mp->mtu), flags);
5806
5807   REPLY_MACRO2(VL_API_MAP_ADD_DOMAIN_REPLY,
5808                ({
5809                  rmp->index = ntohl(index);
5810                }));
5811 }
5812
5813 static void
5814 vl_api_map_del_domain_t_handler
5815 (vl_api_map_del_domain_t * mp)
5816 {
5817   vl_api_map_del_domain_reply_t * rmp;
5818   int rv = 0;
5819
5820   rv = map_delete_domain(ntohl(mp->index));
5821
5822   REPLY_MACRO(VL_API_MAP_DEL_DOMAIN_REPLY);
5823 }
5824
5825 static void
5826 vl_api_map_add_del_rule_t_handler
5827 (vl_api_map_add_del_rule_t * mp)
5828 {
5829   vl_api_map_del_domain_reply_t * rmp;
5830   int rv = 0;
5831
5832   rv = map_add_del_psid(ntohl(mp->index), ntohs(mp->psid), (ip6_address_t *)mp->ip6_dst, mp->is_add);
5833
5834   REPLY_MACRO(VL_API_MAP_ADD_DEL_RULE_REPLY);
5835 }
5836
5837 static void
5838 vl_api_map_domain_dump_t_handler
5839 (vl_api_map_domain_dump_t * mp)
5840 {
5841   vl_api_map_domain_details_t * rmp;
5842   map_main_t *mm = &map_main;
5843   map_domain_t *d;
5844   unix_shared_memory_queue_t * q;
5845
5846   if (pool_elts (mm->domains) == 0)
5847       return;
5848
5849   q = vl_api_client_index_to_input_queue (mp->client_index);
5850   if (q == 0) {
5851     return;
5852   }
5853
5854   pool_foreach(d, mm->domains, ({
5855     /* Make sure every field is initiated (or don't skip the memset()) */
5856     rmp = vl_msg_api_alloc (sizeof (*rmp));
5857     rmp->_vl_msg_id = ntohs(VL_API_MAP_DOMAIN_DETAILS);
5858     rmp->domain_index = htonl(d - mm->domains);
5859     rmp->ea_bits_len = d->ea_bits_len;
5860     rmp->psid_offset = d->psid_offset;
5861     rmp->psid_length = d->psid_length;
5862     clib_memcpy(rmp->ip4_prefix, &d->ip4_prefix, sizeof(rmp->ip4_prefix));
5863     rmp->ip4_prefix_len = d->ip4_prefix_len;
5864     clib_memcpy(rmp->ip6_prefix, &d->ip6_prefix, sizeof(rmp->ip6_prefix));
5865     rmp->ip6_prefix_len = d->ip6_prefix_len;
5866     clib_memcpy(rmp->ip6_src, &d->ip6_src, sizeof(rmp->ip6_src));
5867     rmp->ip6_src_len = d->ip6_src_len;
5868     rmp->mtu = htons(d->mtu);
5869     rmp->is_translation = (d->flags & MAP_DOMAIN_TRANSLATION);
5870     rmp->context = mp->context;
5871
5872     vl_msg_api_send_shmem (q, (u8 *)&rmp);
5873   }));
5874 }
5875
5876 static void
5877 vl_api_map_rule_dump_t_handler
5878 (vl_api_map_rule_dump_t * mp)
5879 {
5880   unix_shared_memory_queue_t * q;
5881   u16 i;
5882   ip6_address_t dst;
5883   vl_api_map_rule_details_t * rmp;
5884   map_main_t *mm = &map_main;
5885   u32 domain_index = ntohl(mp->domain_index);
5886   map_domain_t *d;
5887
5888   if (pool_elts (mm->domains) == 0)
5889    return;
5890
5891   d = pool_elt_at_index(mm->domains, domain_index);
5892   if (!d || !d->rules) {
5893     return;
5894   }
5895
5896   q = vl_api_client_index_to_input_queue (mp->client_index);
5897   if (q == 0) {
5898     return;
5899   }
5900
5901   for (i = 0; i < (0x1 << d->psid_length); i++) {
5902     dst = d->rules[i];
5903     if (dst.as_u64[0] == 0 && dst.as_u64[1] == 0) {
5904       continue;
5905     }
5906     rmp = vl_msg_api_alloc(sizeof(*rmp));
5907     memset(rmp, 0, sizeof(*rmp));
5908     rmp->_vl_msg_id = ntohs(VL_API_MAP_RULE_DETAILS);
5909     rmp->psid = htons(i);
5910     clib_memcpy(rmp->ip6_dst, &dst, sizeof(rmp->ip6_dst));
5911     rmp->context = mp->context;
5912     vl_msg_api_send_shmem(q, (u8 *)&rmp);
5913   }
5914 }
5915
5916 static void
5917 vl_api_map_summary_stats_t_handler (
5918     vl_api_map_summary_stats_t *mp)
5919 {
5920     vl_api_map_summary_stats_reply_t *rmp;
5921     vlib_combined_counter_main_t *cm;
5922     vlib_counter_t v;
5923     int i, which;
5924     u64 total_pkts[VLIB_N_RX_TX];
5925     u64 total_bytes[VLIB_N_RX_TX];
5926     map_main_t *mm = &map_main;
5927     unix_shared_memory_queue_t *q =
5928         vl_api_client_index_to_input_queue(mp->client_index);
5929
5930     if (!q)
5931         return;
5932
5933     rmp = vl_msg_api_alloc (sizeof (*rmp));
5934     rmp->_vl_msg_id = ntohs(VL_API_MAP_SUMMARY_STATS_REPLY);
5935     rmp->context = mp->context;
5936     rmp->retval = 0;
5937
5938     memset (total_pkts, 0, sizeof (total_pkts));
5939     memset (total_bytes, 0, sizeof (total_bytes));
5940
5941     map_domain_counter_lock (mm);
5942     vec_foreach(cm, mm->domain_counters) {
5943       which = cm - mm->domain_counters;
5944
5945       for (i = 0; i < vec_len(cm->maxi); i++) {
5946         vlib_get_combined_counter (cm, i, &v);
5947         total_pkts[which] += v.packets;
5948         total_bytes[which] += v.bytes;
5949       }
5950     }
5951
5952     map_domain_counter_unlock (mm);
5953
5954     /* Note: in network byte order! */
5955     rmp->total_pkts[MAP_DOMAIN_COUNTER_RX] = clib_host_to_net_u64(total_pkts[MAP_DOMAIN_COUNTER_RX]);
5956     rmp->total_bytes[MAP_DOMAIN_COUNTER_RX] = clib_host_to_net_u64(total_bytes[MAP_DOMAIN_COUNTER_RX]);
5957     rmp->total_pkts[MAP_DOMAIN_COUNTER_TX] = clib_host_to_net_u64(total_pkts[MAP_DOMAIN_COUNTER_TX]);
5958     rmp->total_bytes[MAP_DOMAIN_COUNTER_TX] = clib_host_to_net_u64(total_bytes[MAP_DOMAIN_COUNTER_TX]);
5959     rmp->total_bindings = clib_host_to_net_u64(pool_elts(mm->domains));
5960     rmp->total_ip4_fragments = 0; // Not yet implemented. Should be a simple counter.
5961     rmp->total_security_check[MAP_DOMAIN_COUNTER_TX] = clib_host_to_net_u64(map_error_counter_get(ip4_map_node.index, MAP_ERROR_ENCAP_SEC_CHECK));
5962     rmp->total_security_check[MAP_DOMAIN_COUNTER_RX] = clib_host_to_net_u64(map_error_counter_get(ip4_map_node.index, MAP_ERROR_DECAP_SEC_CHECK));
5963
5964     vl_msg_api_send_shmem(q, (u8 *)&rmp);
5965 }
5966
5967 static void vl_api_ipsec_sa_set_key_t_handler
5968 (vl_api_ipsec_sa_set_key_t * mp)
5969 {
5970     vlib_main_t *vm __attribute__((unused)) = vlib_get_main();
5971     vl_api_ipsec_sa_set_key_reply_t *rmp;
5972     int rv;
5973 #if IPSEC > 0
5974     ipsec_sa_t sa;
5975     sa.id = ntohl(mp->sa_id);
5976     sa.crypto_key_len = mp->crypto_key_length;
5977     clib_memcpy(&sa.crypto_key, mp->crypto_key, sizeof(sa.crypto_key));
5978     sa.integ_key_len = mp->integrity_key_length;
5979     clib_memcpy(&sa.integ_key, mp->integrity_key, sizeof(sa.integ_key));
5980
5981     rv = ipsec_set_sa_key(vm, &sa);
5982 #else
5983     rv = VNET_API_ERROR_UNIMPLEMENTED;
5984 #endif
5985
5986     REPLY_MACRO(VL_API_IPSEC_SA_SET_KEY_REPLY);
5987 }
5988
5989 static void vl_api_cop_interface_enable_disable_t_handler
5990 (vl_api_cop_interface_enable_disable_t * mp)
5991 {
5992     vl_api_cop_interface_enable_disable_reply_t * rmp;
5993     int rv;
5994     u32 sw_if_index = ntohl(mp->sw_if_index);
5995     int enable_disable;
5996
5997     VALIDATE_SW_IF_INDEX(mp);
5998
5999     enable_disable = (int) mp->enable_disable;
6000
6001     rv = cop_interface_enable_disable (sw_if_index, enable_disable);
6002
6003     BAD_SW_IF_INDEX_LABEL;
6004
6005     REPLY_MACRO(VL_API_COP_INTERFACE_ENABLE_DISABLE_REPLY);
6006 }
6007
6008 static void vl_api_cop_whitelist_enable_disable_t_handler
6009 (vl_api_cop_whitelist_enable_disable_t * mp)
6010 {
6011     vl_api_cop_whitelist_enable_disable_reply_t * rmp;
6012     cop_whitelist_enable_disable_args_t _a, *a=&_a;
6013     u32 sw_if_index = ntohl(mp->sw_if_index);
6014     int rv;
6015
6016     VALIDATE_SW_IF_INDEX(mp);
6017
6018     a->sw_if_index = sw_if_index;
6019     a->ip4 = mp->ip4;
6020     a->ip6 = mp->ip6;
6021     a->default_cop = mp->default_cop;
6022     a->fib_id = ntohl(mp->fib_id);
6023
6024     rv = cop_whitelist_enable_disable (a);
6025
6026     BAD_SW_IF_INDEX_LABEL;
6027
6028     REPLY_MACRO(VL_API_COP_WHITELIST_ENABLE_DISABLE_REPLY);
6029 }
6030
6031 static void vl_api_get_node_graph_t_handler
6032 (vl_api_get_node_graph_t * mp)
6033 {
6034     int rv = 0;
6035     u8 * vector = 0;
6036     api_main_t * am = &api_main;
6037     vlib_main_t * vm = vlib_get_main();
6038     void * oldheap;
6039     vl_api_get_node_graph_reply_t * rmp;
6040
6041     pthread_mutex_lock (&am->vlib_rp->mutex);
6042     oldheap = svm_push_data_heap (am->vlib_rp);
6043
6044     /*
6045      * Keep the number of memcpy ops to a minimum (e.g. 1).
6046      */
6047     vec_validate (vector, 16384);
6048     vec_reset_length (vector);
6049
6050     /* $$$$ FIXME */
6051     vector = vlib_node_serialize (&vm->node_main, vector,
6052                                   (u32)~0 /* all threads */,
6053                                   1 /* include nexts */,
6054                                   1 /* include stats */);
6055
6056     svm_pop_heap (oldheap);
6057     pthread_mutex_unlock (&am->vlib_rp->mutex);
6058
6059     REPLY_MACRO2(VL_API_GET_NODE_GRAPH_REPLY,
6060                  rmp->reply_in_shmem = (uword) vector);
6061 }
6062
6063 static void vl_api_trace_profile_add_t_handler
6064 (vl_api_trace_profile_add_t *mp)
6065 {
6066     int rv = 0;
6067     vl_api_trace_profile_add_reply_t * rmp;
6068     clib_error_t *error;
6069
6070     /* Ignoring the profile id as currently a single profile
6071      * is supported */
6072     error = ip6_ioam_trace_profile_set(mp->trace_num_elt, mp->trace_type,
6073                                ntohl(mp->node_id), ntohl(mp->trace_app_data),
6074                                mp->pow_enable, mp->trace_tsp,
6075                                mp->trace_ppc);
6076     if (error) {
6077       clib_error_report(error);
6078       rv = clib_error_get_code(error);
6079     }
6080
6081     REPLY_MACRO(VL_API_TRACE_PROFILE_ADD_REPLY);
6082 }
6083
6084 static void vl_api_trace_profile_apply_t_handler
6085 (vl_api_trace_profile_apply_t *mp)
6086 {
6087     int rv = 0;
6088     vl_api_trace_profile_apply_reply_t * rmp;
6089
6090     if (mp->enable != 0) {
6091       rv = ip6_ioam_set_destination ((ip6_address_t *)(&mp->dest_ipv6),
6092                                 ntohl(mp->prefix_length),
6093                                 ntohl(mp->vrf_id),
6094                         mp->trace_op == IOAM_HBYH_ADD,
6095                         mp->trace_op == IOAM_HBYH_POP,
6096                         mp->trace_op == IOAM_HBYH_MOD);
6097     } else {
6098       //ip6_ioam_clear_destination(&ip6, mp->prefix_length, mp->vrf_id);
6099     }
6100     REPLY_MACRO(VL_API_TRACE_PROFILE_APPLY_REPLY);
6101 }
6102
6103 static void vl_api_trace_profile_del_t_handler
6104 (vl_api_trace_profile_del_t *mp)
6105 {
6106     int rv = 0;
6107     vl_api_trace_profile_del_reply_t * rmp;
6108     clib_error_t *error;
6109
6110     error = clear_ioam_rewrite_fn();
6111     if (error) {
6112       clib_error_report(error);
6113       rv = clib_error_get_code(error);
6114     }
6115
6116     REPLY_MACRO(VL_API_TRACE_PROFILE_DEL_REPLY);
6117 }
6118
6119 static void
6120 vl_api_af_packet_create_t_handler
6121 (vl_api_af_packet_create_t *mp)
6122 {
6123     vlib_main_t *vm = vlib_get_main();
6124     vl_api_af_packet_create_reply_t *rmp;
6125     int rv = 0;
6126     u8 *host_if_name = NULL;
6127     u32 sw_if_index;
6128
6129     host_if_name = format(0, "%s", mp->host_if_name);
6130     vec_add1 (host_if_name, 0);
6131
6132     rv = af_packet_create_if(vm, host_if_name,
6133                              mp->use_random_hw_addr ? 0 : mp->hw_addr, &sw_if_index);
6134
6135     vec_free(host_if_name);
6136
6137     REPLY_MACRO2(VL_API_AF_PACKET_CREATE_REPLY,
6138                  rmp->sw_if_index = clib_host_to_net_u32(sw_if_index));
6139 }
6140
6141 static void
6142 vl_api_af_packet_delete_t_handler
6143 (vl_api_af_packet_delete_t *mp)
6144 {
6145     vlib_main_t * vm = vlib_get_main();
6146     vl_api_af_packet_delete_reply_t *rmp;
6147     int rv = 0;
6148     u8 *host_if_name = NULL;
6149
6150     host_if_name = format(0, "%s", mp->host_if_name);
6151     vec_add1 (host_if_name, 0);
6152
6153     rv = af_packet_delete_if(vm, host_if_name);
6154
6155     vec_free(host_if_name);
6156
6157     REPLY_MACRO(VL_API_AF_PACKET_DELETE_REPLY);
6158 }
6159
6160 static void
6161 vl_api_policer_add_del_t_handler
6162 (vl_api_policer_add_del_t *mp)
6163 {
6164     vlib_main_t * vm = vlib_get_main();
6165     vl_api_policer_add_del_reply_t *rmp;
6166     int rv = 0;
6167     u8 *name = NULL;
6168     sse2_qos_pol_cfg_params_st cfg;
6169     clib_error_t * error;
6170
6171     name = format(0, "%s", mp->name);
6172
6173     memset (&cfg, 0, sizeof (cfg));
6174     cfg.rfc = mp->type;
6175     cfg.rnd_type = mp->round_type;
6176     cfg.rate_type = mp->rate_type;
6177     cfg.rb.kbps.cir_kbps = mp->cir;
6178     cfg.rb.kbps.eir_kbps = mp->eir;
6179     cfg.rb.kbps.cb_bytes = mp->cb;
6180     cfg.rb.kbps.eb_bytes = mp->eb;
6181
6182     error = policer_add_del(vm, name, &cfg, mp->is_add);
6183
6184     if (error)
6185       rv = VNET_API_ERROR_UNSPECIFIED;
6186
6187     REPLY_MACRO(VL_API_POLICER_ADD_DEL_REPLY);
6188 }
6189
6190 static void
6191 send_policer_details (u8 *name,
6192                       sse2_qos_pol_cfg_params_st *config,
6193                       policer_read_response_type_st *templ,
6194                       unix_shared_memory_queue_t *q,
6195                       u32 context)
6196 {
6197     vl_api_policer_details_t * mp;
6198
6199     mp = vl_msg_api_alloc (sizeof (*mp));
6200     memset (mp, 0, sizeof (*mp));
6201     mp->_vl_msg_id = ntohs (VL_API_POLICER_DETAILS);
6202     mp->context = context;
6203     mp->cir = htonl(config->rb.kbps.cir_kbps);
6204     mp->eir = htonl(config->rb.kbps.eir_kbps);
6205     mp->cb = htonl(config->rb.kbps.cb_bytes);
6206     mp->eb = htonl(config->rb.kbps.eb_bytes);
6207     mp->rate_type = config->rate_type;
6208     mp->round_type = config->rnd_type;
6209     mp->type = config->rfc;
6210     mp->single_rate = templ->single_rate ? 1 : 0;
6211     mp->color_aware = templ->color_aware ? 1 : 0;
6212     mp->scale = htonl(templ->scale);
6213     mp->cir_tokens_per_period = htonl(templ->cir_tokens_per_period);
6214     mp->pir_tokens_per_period = htonl(templ->pir_tokens_per_period);
6215     mp->current_limit = htonl(templ->current_limit);
6216     mp->current_bucket = htonl(templ->current_bucket);
6217     mp->extended_limit = htonl(templ->extended_limit);
6218     mp->extended_bucket = htonl(templ->extended_bucket);
6219     mp->last_update_time = clib_host_to_net_u64(templ->last_update_time);
6220
6221     strncpy ((char *) mp->name, (char *) name, ARRAY_LEN(mp->name) - 1);
6222
6223     vl_msg_api_send_shmem (q, (u8 *)&mp);
6224 }
6225
6226 static void
6227 vl_api_policer_dump_t_handler
6228 (vl_api_policer_dump_t *mp)
6229 {
6230     unix_shared_memory_queue_t * q;
6231     vnet_policer_main_t * pm = &vnet_policer_main;
6232     hash_pair_t * hp;
6233     uword * p;
6234     u32 pool_index;
6235     u8 * match_name = 0;
6236     u8 * name;
6237     sse2_qos_pol_cfg_params_st *config;
6238     policer_read_response_type_st *templ;
6239
6240     q = vl_api_client_index_to_input_queue (mp->client_index);
6241     if (q == 0)
6242         return;
6243
6244     if (mp->match_name_valid) {
6245         match_name = format(0, "%s%c", mp->match_name, 0);
6246     }
6247
6248     if (mp->match_name_valid) {
6249         p = hash_get_mem (pm->policer_config_by_name, match_name);
6250         if (p) {
6251             pool_index = p[0];
6252             config = pool_elt_at_index (pm->configs, pool_index);
6253             templ = pool_elt_at_index (pm->policer_templates, pool_index);
6254             send_policer_details(match_name, config, templ, q, mp->context);
6255         }
6256     } else {
6257         hash_foreach_pair (hp, pm->policer_config_by_name,
6258         ({
6259             name = (u8 *) hp->key;
6260             pool_index = hp->value[0];
6261             config = pool_elt_at_index (pm->configs, pool_index);
6262             templ = pool_elt_at_index (pm->policer_templates, pool_index);
6263             send_policer_details(name, config, templ, q, mp->context);
6264         }));
6265     }
6266 }
6267
6268 static void
6269 vl_api_netmap_create_t_handler
6270 (vl_api_netmap_create_t *mp)
6271 {
6272     vlib_main_t *vm = vlib_get_main();
6273     vl_api_netmap_create_reply_t *rmp;
6274     int rv = 0;
6275     u8 *if_name = NULL;
6276
6277     if_name = format(0, "%s", mp->netmap_if_name);
6278     vec_add1 (if_name, 0);
6279
6280     rv = netmap_create_if(vm, if_name, mp->use_random_hw_addr ? 0 : mp->hw_addr,
6281                           mp->is_pipe, mp->is_master, 0);
6282
6283     vec_free(if_name);
6284
6285     REPLY_MACRO(VL_API_NETMAP_CREATE_REPLY);
6286 }
6287
6288 static void
6289 vl_api_netmap_delete_t_handler
6290 (vl_api_netmap_delete_t *mp)
6291 {
6292     vlib_main_t * vm = vlib_get_main();
6293     vl_api_netmap_delete_reply_t *rmp;
6294     int rv = 0;
6295     u8 *if_name = NULL;
6296
6297     if_name = format(0, "%s", mp->netmap_if_name);
6298     vec_add1 (if_name, 0);
6299
6300     rv = netmap_delete_if(vm, if_name);
6301
6302     vec_free(if_name);
6303
6304     REPLY_MACRO(VL_API_NETMAP_DELETE_REPLY);
6305 }
6306
6307 #define BOUNCE_HANDLER(nn)                                              \
6308 static void vl_api_##nn##_t_handler (                                   \
6309     vl_api_##nn##_t *mp)                                                \
6310 {                                                                       \
6311     vpe_client_registration_t *reg;                                     \
6312     vpe_api_main_t * vam = &vpe_api_main;                               \
6313     unix_shared_memory_queue_t * q;                                     \
6314                                                                         \
6315     /* One registration only... */                                      \
6316     pool_foreach(reg, vam->nn##_registrations,                          \
6317     ({                                                                  \
6318         q = vl_api_client_index_to_input_queue (reg->client_index);     \
6319         if (q) {                                                        \
6320             /*                                                          \
6321              * If the queue is stuffed, turf the msg and complain       \
6322              * It's unlikely that the intended recipient is             \
6323              * alive; avoid deadlock at all costs.                      \
6324              */                                                         \
6325             if (q->cursize == q->maxsize) {                             \
6326                 clib_warning ("ERROR: receiver queue full, drop msg");  \
6327                 vl_msg_api_free (mp);                                   \
6328                 return;                                                 \
6329             }                                                           \
6330             vl_msg_api_send_shmem (q, (u8 *)&mp);                       \
6331             return;                                                     \
6332         }                                                               \
6333     }));                                                                \
6334     vl_msg_api_free (mp);                                               \
6335 }
6336
6337 /*
6338  * vpe_api_hookup
6339  * Add vpe's API message handlers to the table.
6340  * vlib has alread mapped shared memory and
6341  * added the client registration handlers.
6342  * See .../open-repo/vlib/memclnt_vlib.c:memclnt_process()
6343  */
6344
6345 static clib_error_t *
6346 vpe_api_hookup (vlib_main_t *vm)
6347 {
6348     api_main_t * am = &api_main;
6349
6350 #define _(N,n)                                                  \
6351     vl_msg_api_set_handlers(VL_API_##N, #n,                     \
6352                            vl_api_##n##_t_handler,              \
6353                            vl_noop_handler,                     \
6354                            vl_api_##n##_t_endian,               \
6355                            vl_api_##n##_t_print,                \
6356                            sizeof(vl_api_##n##_t), 1);
6357     foreach_vpe_api_msg;
6358 #undef _
6359
6360     /*
6361      * Manually register the sr tunnel add del msg, so we trace
6362      * enough bytes to capture a typical segment list
6363      */
6364     vl_msg_api_set_handlers (VL_API_SR_TUNNEL_ADD_DEL,
6365                              "sr_tunnel_add_del",
6366                              vl_api_sr_tunnel_add_del_t_handler,
6367                              vl_noop_handler,
6368                              vl_api_sr_tunnel_add_del_t_endian,
6369                              vl_api_sr_tunnel_add_del_t_print,
6370                              256, 1);
6371
6372
6373     /*
6374      * Manually register the sr policy add del msg, so we trace
6375      * enough bytes to capture a typical tunnel name list
6376      */
6377     vl_msg_api_set_handlers (VL_API_SR_POLICY_ADD_DEL,
6378                              "sr_policy_add_del",
6379                              vl_api_sr_policy_add_del_t_handler,
6380                              vl_noop_handler,
6381                              vl_api_sr_policy_add_del_t_endian,
6382                              vl_api_sr_policy_add_del_t_print,
6383                              256, 1);
6384
6385     /*
6386      * Trace space for 8 MPLS encap labels, classifier mask+match
6387      */
6388     am->api_trace_cfg [VL_API_MPLS_ADD_DEL_ENCAP].size += 8 * sizeof(u32);
6389     am->api_trace_cfg [VL_API_CLASSIFY_ADD_DEL_TABLE].size
6390         += 5 * sizeof (u32x4);
6391     am->api_trace_cfg [VL_API_CLASSIFY_ADD_DEL_SESSION].size
6392         += 5 * sizeof (u32x4);
6393     am->api_trace_cfg [VL_API_VXLAN_ADD_DEL_TUNNEL].size
6394         += 16 * sizeof (u32);
6395
6396     /*
6397      * Thread-safe API messages
6398      */
6399     am->is_mp_safe [VL_API_IP_ADD_DEL_ROUTE] = 1;
6400     am->is_mp_safe [VL_API_GET_NODE_GRAPH] = 1;
6401
6402     return 0;
6403 }
6404
6405 VLIB_API_INIT_FUNCTION(vpe_api_hookup);
6406
6407 static clib_error_t *
6408 vpe_api_init (vlib_main_t *vm)
6409 {
6410     vpe_api_main_t *am = &vpe_api_main;
6411
6412     am->vlib_main = vm;
6413     am->vnet_main = vnet_get_main();
6414     am->interface_events_registration_hash = hash_create (0, sizeof (uword));
6415     am->to_netconf_server_registration_hash = hash_create (0, sizeof (uword));
6416     am->from_netconf_server_registration_hash = hash_create (0, sizeof (uword));
6417     am->to_netconf_client_registration_hash = hash_create (0, sizeof (uword));
6418     am->from_netconf_client_registration_hash = hash_create (0, sizeof (uword));
6419     am->oam_events_registration_hash = hash_create (0, sizeof (uword));
6420
6421     vl_api_init (vm);
6422     vl_set_memory_region_name ("/vpe-api");
6423     vl_enable_disable_memory_api (vm, 1 /* enable it */);
6424
6425     return 0;
6426 }
6427
6428 VLIB_INIT_FUNCTION(vpe_api_init);
6429
6430
6431 static clib_error_t *
6432 api_segment_config (vlib_main_t * vm, unformat_input_t * input)
6433 {
6434   u8 * chroot_path;
6435   int uid, gid, rv;
6436   char *s, buf[128];
6437   struct passwd _pw, *pw;
6438   struct group _grp, *grp;
6439   clib_error_t *e;
6440
6441   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
6442     {
6443       if (unformat (input, "prefix %s", &chroot_path))
6444         {
6445           vec_add1 (chroot_path, 0);
6446           vl_set_memory_root_path ((char *)chroot_path);
6447         }
6448       else if (unformat (input, "uid %d", &uid))
6449         vl_set_memory_uid (uid);
6450       else if (unformat (input, "gid %d", &gid))
6451         vl_set_memory_gid (gid);
6452       else if (unformat (input, "uid %s", &s))
6453         {
6454           /* lookup the username */
6455           pw = NULL;
6456           rv = getpwnam_r(s, &_pw, buf, sizeof(buf), &pw);
6457           if (rv < 0)
6458             {
6459               e = clib_error_return_code(0, rv,
6460                        CLIB_ERROR_ERRNO_VALID | CLIB_ERROR_FATAL,
6461                        "cannot fetch username %s", s);
6462               vec_free (s);
6463               return e;
6464             }
6465           if (pw == NULL)
6466             {
6467               e = clib_error_return_fatal(0, "username %s does not exist", s);
6468               vec_free (s);
6469               return e;
6470             }
6471           vec_free (s);
6472           vl_set_memory_uid (pw->pw_uid);
6473         }
6474       else if (unformat (input, "gid %s", &s))
6475         {
6476           /* lookup the group name */
6477           grp = NULL;
6478           rv = getgrnam_r(s, &_grp, buf, sizeof(buf), &grp);
6479           if (rv != 0)
6480             {
6481               e = clib_error_return_code(0, rv,
6482                        CLIB_ERROR_ERRNO_VALID | CLIB_ERROR_FATAL,
6483                        "cannot fetch group %s", s);
6484               vec_free (s);
6485               return e;
6486             }
6487           if (grp == NULL)
6488             {
6489               e = clib_error_return_fatal(0, "group %s does not exist", s);
6490               vec_free (s);
6491               return e;
6492             }
6493           vec_free (s);
6494           vl_set_memory_gid (grp->gr_gid);
6495         }
6496       else
6497         return clib_error_return (0, "unknown input `%U'",
6498                                   format_unformat_error, input);
6499     }
6500   return 0;
6501 }
6502 VLIB_EARLY_CONFIG_FUNCTION (api_segment_config, "api-segment");
6503
6504 void * get_unformat_vnet_sw_interface (void)
6505 {
6506     return (void *) &unformat_vnet_sw_interface;
6507 }
6508
6509 #undef vl_api_version
6510 #define vl_api_version(n,v) static u32 vpe_api_version = v;
6511 #include <api/vpe.api.h>
6512 #undef vl_api_version
6513
6514 int vl_msg_api_version_check (vl_api_memclnt_create_t * mp)
6515 {
6516     if (clib_host_to_net_u32(mp->api_versions[0]) != vpe_api_version) {
6517         clib_warning ("vpe API mismatch: 0x%08x instead of 0x%08x",
6518                       clib_host_to_net_u32 (mp->api_versions[0]),
6519                       vpe_api_version);
6520         return -1;
6521     }
6522     return 0;
6523 }
6524
6525 static u8 * format_arp_event (u8 * s, va_list * args)
6526 {
6527     vl_api_ip4_arp_event_t * event = va_arg (*args, vl_api_ip4_arp_event_t *);
6528
6529     s = format (s, "pid %d: %U", event->pid,
6530                 format_ip4_address, &event->address);
6531     return s;
6532 }
6533
6534 static clib_error_t *
6535 show_ip4_arp_events_fn (vlib_main_t * vm,
6536                         unformat_input_t * input,
6537                         vlib_cli_command_t * cmd)
6538 {
6539     vpe_api_main_t * am = &vpe_api_main;
6540     vl_api_ip4_arp_event_t * event;
6541
6542     if (pool_elts (am->arp_events) == 0) {
6543         vlib_cli_output (vm, "No active arp event registrations");
6544         return 0;
6545     }
6546
6547     pool_foreach (event, am->arp_events,
6548     ({
6549         vlib_cli_output (vm, "%U", format_arp_event, event);
6550     }));
6551
6552     return 0;
6553 }
6554
6555 VLIB_CLI_COMMAND (show_ip4_arp_events, static) = {
6556   .path = "show arp event registrations",
6557   .function = show_ip4_arp_events_fn,
6558   .short_help = "Show arp event registrations",
6559 };