2 *------------------------------------------------------------------
3 * api.c - message handler registration
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:
10 * http://www.apache.org/licenses/LICENSE-2.0
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 *------------------------------------------------------------------
23 #include <sys/types.h>
26 #include <netinet/in.h>
33 #include <vppinfra/clib.h>
34 #include <vppinfra/vec.h>
35 #include <vppinfra/hash.h>
36 #include <vppinfra/bitmap.h>
37 #include <vppinfra/fifo.h>
38 #include <vppinfra/time.h>
39 #include <vppinfra/mheap.h>
40 #include <vppinfra/heap.h>
41 #include <vppinfra/pool.h>
42 #include <vppinfra/format.h>
43 #include <vppinfra/error.h>
45 #include <vnet/vnet.h>
46 #include <vnet/l2/l2_input.h>
47 #include <vnet/l2/l2_bd.h>
48 #include <vnet/l2tp/l2tp.h>
49 #include <vnet/ip/ip.h>
50 #include <vnet/unix/tuntap.h>
51 #include <vnet/unix/tapcli.h>
52 #include <vnet/mpls-gre/mpls.h>
53 #include <vnet/dhcp/proxy.h>
54 #include <vnet/dhcp/client.h>
55 #include <vnet/sr/sr.h>
56 #include <vnet/dhcpv6/proxy.h>
57 #include <vlib/vlib.h>
58 #include <vlib/unix/unix.h>
59 #include <vlibapi/api.h>
60 #include <vlibmemory/api.h>
61 #include <vnet/classify/vnet_classify.h>
62 #include <vnet/classify/input_acl.h>
63 #include <vnet/l2/l2_classify.h>
64 #include <vnet/vxlan/vxlan.h>
65 #include <vnet/l2/l2_vtr.h>
66 #include <vnet/nsh-gre/nsh_gre.h>
67 #include <vnet/nsh-vxlan-gpe/nsh_vxlan_gpe.h>
68 #include <vnet/lisp-gpe/lisp_gpe.h>
69 #include <vnet/map/map.h>
72 #undef __included_bihash_template_h__
73 #include <vnet/l2/l2_fib.h>
76 #include <vnet/ipsec/ipsec.h>
77 #include <vnet/devices/virtio/vhost-user.h>
80 #include <stats/stats.h>
83 #include <vnet/ethernet/ethernet.h>
84 #include <vnet/ethernet/arp_packet.h>
85 #include <vnet/interface.h>
87 #include <vnet/l2/l2_fib.h>
88 #include <vnet/l2/l2_bd.h>
89 #include <api/vpe_msg_enum.h>
92 #define f64_print(a,b)
94 #define vl_typedefs /* define message structures */
95 #include <api/vpe_all_api_h.h>
98 #define vl_endianfun /* define message structures */
99 #include <api/vpe_all_api_h.h>
102 /* instantiate all the print functions we know about */
103 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
105 #include <api/vpe_all_api_h.h>
108 #define REPLY_MACRO(t) \
110 unix_shared_memory_queue_t * q; \
111 rv = vl_msg_api_pd_handler (mp, rv); \
112 q = vl_api_client_index_to_input_queue (mp->client_index); \
116 rmp = vl_msg_api_alloc (sizeof (*rmp)); \
117 rmp->_vl_msg_id = ntohs((t)); \
118 rmp->context = mp->context; \
119 rmp->retval = ntohl(rv); \
121 vl_msg_api_send_shmem (q, (u8 *)&rmp); \
124 #define REPLY_MACRO2(t, body) \
126 unix_shared_memory_queue_t * q; \
127 rv = vl_msg_api_pd_handler (mp, rv); \
128 q = vl_api_client_index_to_input_queue (mp->client_index); \
132 rmp = vl_msg_api_alloc (sizeof (*rmp)); \
133 rmp->_vl_msg_id = ntohs((t)); \
134 rmp->context = mp->context; \
135 rmp->retval = ntohl(rv); \
136 do {body;} while (0); \
137 vl_msg_api_send_shmem (q, (u8 *)&rmp); \
140 #if (1 || CLIB_DEBUG > 0) /* "trust, but verify" */
142 #define VALIDATE_SW_IF_INDEX(mp) \
143 do { u32 __sw_if_index = ntohl(mp->sw_if_index); \
144 vnet_main_t *__vnm = vnet_get_main(); \
145 if (pool_is_free_index(__vnm->interface_main.sw_interfaces, \
147 rv = VNET_API_ERROR_INVALID_SW_IF_INDEX; \
148 goto bad_sw_if_index; \
152 #define BAD_SW_IF_INDEX_LABEL \
158 #define VALIDATE_RX_SW_IF_INDEX(mp) \
159 do { u32 __rx_sw_if_index = ntohl(mp->rx_sw_if_index); \
160 vnet_main_t *__vnm = vnet_get_main(); \
161 if (pool_is_free_index(__vnm->interface_main.sw_interfaces, \
162 __rx_sw_if_index)) { \
163 rv = VNET_API_ERROR_INVALID_SW_IF_INDEX; \
164 goto bad_rx_sw_if_index; \
168 #define BAD_RX_SW_IF_INDEX_LABEL \
170 bad_rx_sw_if_index: \
174 #define VALIDATE_TX_SW_IF_INDEX(mp) \
175 do { u32 __tx_sw_if_index = ntohl(mp->tx_sw_if_index); \
176 vnet_main_t *__vnm = vnet_get_main(); \
177 if (pool_is_free_index(__vnm->interface_main.sw_interfaces, \
178 __tx_sw_if_index)) { \
179 rv = VNET_API_ERROR_INVALID_SW_IF_INDEX; \
180 goto bad_tx_sw_if_index; \
184 #define BAD_TX_SW_IF_INDEX_LABEL \
186 bad_tx_sw_if_index: \
192 #define VALIDATE_SW_IF_INDEX(mp)
193 #define BAD_SW_IF_INDEX_LABEL
194 #define VALIDATE_RX_SW_IF_INDEX(mp)
195 #define BAD_RX_SW_IF_INDEX_LABEL
196 #define VALIDATE_TX_SW_IF_INDEX(mp)
197 #define BAD_TX_SW_IF_INDEX_LABEL
199 #endif /* CLIB_DEBUG > 0 */
201 #define foreach_vpe_api_msg \
202 _(WANT_INTERFACE_EVENTS, want_interface_events) \
203 _(WANT_FROM_NETCONF_SERVER, want_from_netconf_server) \
204 _(WANT_TO_NETCONF_SERVER, want_to_netconf_server) \
205 _(WANT_FROM_NETCONF_CLIENT, want_from_netconf_client) \
206 _(WANT_TO_NETCONF_CLIENT, want_to_netconf_client) \
207 _(FROM_NETCONF_SERVER, from_netconf_server) \
208 _(TO_NETCONF_SERVER, to_netconf_server) \
209 _(FROM_NETCONF_CLIENT, from_netconf_client) \
210 _(TO_NETCONF_CLIENT, to_netconf_client) \
211 _(WANT_OAM_EVENTS, want_oam_events) \
212 _(OAM_ADD_DEL, oam_add_del) \
213 _(SW_INTERFACE_DUMP, sw_interface_dump) \
214 _(SW_INTERFACE_DETAILS, sw_interface_details) \
215 _(SW_INTERFACE_SET_FLAGS, sw_interface_set_flags) \
216 _(IP_ADD_DEL_ROUTE, ip_add_del_route) \
217 _(IS_ADDRESS_REACHABLE, is_address_reachable) \
218 _(SW_INTERFACE_ADD_DEL_ADDRESS, sw_interface_add_del_address) \
219 _(SW_INTERFACE_SET_TABLE, sw_interface_set_table) \
220 _(SW_INTERFACE_SET_VPATH, sw_interface_set_vpath) \
221 _(SW_INTERFACE_SET_L2_XCONNECT, sw_interface_set_l2_xconnect) \
222 _(SW_INTERFACE_SET_L2_BRIDGE, sw_interface_set_l2_bridge) \
223 _(BRIDGE_DOMAIN_ADD_DEL, bridge_domain_add_del) \
224 _(BRIDGE_DOMAIN_DUMP, bridge_domain_dump) \
225 _(BRIDGE_DOMAIN_DETAILS, bridge_domain_details) \
226 _(BRIDGE_DOMAIN_SW_IF_DETAILS, bridge_domain_sw_if_details) \
227 _(L2FIB_ADD_DEL, l2fib_add_del) \
228 _(L2_FLAGS, l2_flags) \
229 _(BRIDGE_FLAGS, bridge_flags) \
230 _(TAP_CONNECT, tap_connect) \
231 _(TAP_MODIFY, tap_modify) \
232 _(TAP_DELETE, tap_delete) \
233 _(SW_INTERFACE_TAP_DUMP, sw_interface_tap_dump) \
234 _(CREATE_VLAN_SUBIF, create_vlan_subif) \
235 _(CREATE_SUBIF, create_subif) \
236 _(MPLS_GRE_ADD_DEL_TUNNEL, mpls_gre_add_del_tunnel) \
237 _(MPLS_ETHERNET_ADD_DEL_TUNNEL, mpls_ethernet_add_del_tunnel) \
238 _(MPLS_ETHERNET_ADD_DEL_TUNNEL_2, mpls_ethernet_add_del_tunnel_2) \
239 _(MPLS_ADD_DEL_ENCAP, mpls_add_del_encap) \
240 _(MPLS_ADD_DEL_DECAP, mpls_add_del_decap) \
241 _(PROXY_ARP_ADD_DEL, proxy_arp_add_del) \
242 _(PROXY_ARP_INTFC_ENABLE_DISABLE, proxy_arp_intfc_enable_disable) \
243 _(IP_NEIGHBOR_ADD_DEL, ip_neighbor_add_del) \
244 _(VNET_GET_SUMMARY_STATS, vnet_get_summary_stats) \
245 _(RESET_FIB, reset_fib) \
246 _(DHCP_PROXY_CONFIG,dhcp_proxy_config) \
247 _(DHCP_PROXY_CONFIG_2,dhcp_proxy_config_2) \
248 _(DHCP_PROXY_SET_VSS,dhcp_proxy_set_vss) \
249 _(DHCP_CLIENT_CONFIG, dhcp_client_config) \
250 _(SET_IP_FLOW_HASH,set_ip_flow_hash) \
251 _(SW_INTERFACE_IP6ND_RA_CONFIG, sw_interface_ip6nd_ra_config) \
252 _(SW_INTERFACE_IP6ND_RA_PREFIX, sw_interface_ip6nd_ra_prefix) \
253 _(SW_INTERFACE_IP6_ENABLE_DISABLE, sw_interface_ip6_enable_disable ) \
254 _(SW_INTERFACE_IP6_SET_LINK_LOCAL_ADDRESS, \
255 sw_interface_ip6_set_link_local_address) \
256 _(SW_INTERFACE_SET_UNNUMBERED, sw_interface_set_unnumbered) \
257 _(CREATE_LOOPBACK, create_loopback) \
258 _(CONTROL_PING, control_ping) \
259 _(CLI_REQUEST, cli_request) \
260 _(SET_ARP_NEIGHBOR_LIMIT, set_arp_neighbor_limit) \
261 _(L2_PATCH_ADD_DEL, l2_patch_add_del) \
262 _(CLASSIFY_ADD_DEL_TABLE, classify_add_del_table) \
263 _(CLASSIFY_ADD_DEL_SESSION, classify_add_del_session) \
264 _(CLASSIFY_SET_INTERFACE_IP_TABLE, classify_set_interface_ip_table) \
265 _(CLASSIFY_SET_INTERFACE_L2_TABLES, classify_set_interface_l2_tables) \
266 _(GET_NODE_INDEX, get_node_index) \
267 _(ADD_NODE_NEXT, add_node_next) \
268 _(L2TPV3_CREATE_TUNNEL, l2tpv3_create_tunnel) \
269 _(L2TPV3_SET_TUNNEL_COOKIES, l2tpv3_set_tunnel_cookies) \
270 _(L2TPV3_INTERFACE_ENABLE_DISABLE, l2tpv3_interface_enable_disable) \
271 _(L2TPV3_SET_LOOKUP_KEY, l2tpv3_set_lookup_key) \
272 _(SW_IF_L2TPV3_TUNNEL_DUMP, sw_if_l2tpv3_tunnel_dump) \
273 _(VXLAN_ADD_DEL_TUNNEL, vxlan_add_del_tunnel) \
274 _(VXLAN_TUNNEL_DUMP, vxlan_tunnel_dump) \
275 _(L2_FIB_CLEAR_TABLE, l2_fib_clear_table) \
276 _(L2_INTERFACE_EFP_FILTER, l2_interface_efp_filter) \
277 _(L2_INTERFACE_VLAN_TAG_REWRITE, l2_interface_vlan_tag_rewrite) \
278 _(CREATE_VHOST_USER_IF, create_vhost_user_if) \
279 _(MODIFY_VHOST_USER_IF, modify_vhost_user_if) \
280 _(DELETE_VHOST_USER_IF, delete_vhost_user_if) \
281 _(SW_INTERFACE_VHOST_USER_DUMP, sw_interface_vhost_user_dump) \
282 _(IP_ADDRESS_DUMP, ip_address_dump) \
283 _(IP_DUMP, ip_dump) \
284 _(SW_INTERFACE_VHOST_USER_DETAILS, sw_interface_vhost_user_details) \
285 _(SHOW_VERSION, show_version) \
286 _(NSH_GRE_ADD_DEL_TUNNEL, nsh_gre_add_del_tunnel) \
287 _(L2_FIB_TABLE_DUMP, l2_fib_table_dump) \
288 _(L2_FIB_TABLE_ENTRY, l2_fib_table_entry) \
289 _(NSH_VXLAN_GPE_ADD_DEL_TUNNEL, nsh_vxlan_gpe_add_del_tunnel) \
290 _(LISP_GPE_ADD_DEL_TUNNEL, lisp_gpe_add_del_tunnel) \
291 _(INTERFACE_NAME_RENUMBER, interface_name_renumber) \
292 _(WANT_IP4_ARP_EVENTS, want_ip4_arp_events) \
293 _(INPUT_ACL_SET_INTERFACE, input_acl_set_interface) \
294 _(IPSEC_SPD_ADD_DEL, ipsec_spd_add_del) \
295 _(IPSEC_INTERFACE_ADD_DEL_SPD, ipsec_interface_add_del_spd) \
296 _(IPSEC_SPD_ADD_DEL_ENTRY, ipsec_spd_add_del_entry) \
297 _(IPSEC_SAD_ADD_DEL_ENTRY, ipsec_sad_add_del_entry) \
298 _(IPSEC_SA_SET_KEY, ipsec_sa_set_key) \
299 _(DELETE_LOOPBACK, delete_loopback) \
300 _(BD_IP_MAC_ADD_DEL, bd_ip_mac_add_del) \
301 _(MAP_ADD_DOMAIN, map_add_domain) \
302 _(MAP_DEL_DOMAIN, map_del_domain) \
303 _(MAP_ADD_DEL_RULE, map_add_del_rule) \
304 _(MAP_DOMAIN_DUMP, map_domain_dump) \
305 _(MAP_RULE_DUMP, map_rule_dump) \
306 _(MAP_SUMMARY_STATS, map_summary_stats)
309 #define QUOTE(x) QUOTE_(x)
311 #define foreach_registration_hash \
312 _(interface_events) \
313 _(to_netconf_server) \
314 _(from_netconf_server) \
315 _(to_netconf_client) \
316 _(from_netconf_client) \
320 RESOLVE_IP4_ADD_DEL_ROUTE=1,
321 RESOLVE_IP6_ADD_DEL_ROUTE,
322 RESOLVE_MPLS_ETHERNET_ADD_DEL,
328 vl_api_ip_add_del_route_t r;
329 vl_api_mpls_ethernet_add_del_tunnel_2_t t;
335 #define _(a) uword *a##_registration_hash; \
336 vpe_client_registration_t * a##_registrations;
337 foreach_registration_hash
340 /* notifications happen really early in the game */
341 u8 link_state_process_up;
343 /* ip4 pending route adds */
344 pending_route_t * pending_routes;
346 /* ip4 arp event registration pool */
347 vl_api_ip4_arp_event_t * arp_events;
350 vlib_main_t * vlib_main;
351 vnet_main_t * vnet_main;
354 static vlib_node_registration_t vpe_resolver_process_node;
355 static vpe_api_main_t vpe_api_main;
357 static void send_sw_interface_flags (vpe_api_main_t * am,
358 unix_shared_memory_queue_t *q,
359 vnet_sw_interface_t * swif);
360 static void send_sw_interface_flags_deleted (vpe_api_main_t * am,
361 unix_shared_memory_queue_t *q,
364 static int arp_change_delete_callback (u32 pool_index, u8 * notused);
367 /* Clean up all registrations belonging to the indicated client */
368 int vl_api_memclnt_delete_callback (u32 client_index)
370 vpe_api_main_t * vam = &vpe_api_main;
371 vpe_client_registration_t *rp;
373 int stats_memclnt_delete_callback (u32 client_index);
375 stats_memclnt_delete_callback (client_index);
378 p = hash_get (vam->a##_registration_hash, client_index); \
380 rp = pool_elt_at_index (vam->a##_registrations, p[0]); \
381 pool_put (vam->a##_registrations, rp); \
382 hash_unset (vam->a##_registration_hash, client_index); \
384 foreach_registration_hash;
389 #define API_LINK_STATE_EVENT 1
390 #define API_ADMIN_UP_DOWN_EVENT 2
393 event_data_cmp (void * a1, void * a2)
398 return (word) e1[0] - (word) e2[0];
402 link_state_process (vlib_main_t * vm,
403 vlib_node_runtime_t * rt,
406 vpe_api_main_t * vam = &vpe_api_main;
407 vnet_main_t * vnm = vam->vnet_main;
408 vnet_sw_interface_t * swif;
409 uword * event_data = 0;
410 vpe_client_registration_t *reg;
412 u32 prev_sw_if_index;
413 unix_shared_memory_queue_t * q;
415 vam->link_state_process_up = 1;
418 vlib_process_wait_for_event (vm);
420 /* Unified list of changed link or admin state sw_if_indices */
421 vlib_process_get_events_with_type
422 (vm, &event_data, API_LINK_STATE_EVENT);
423 vlib_process_get_events_with_type
424 (vm, &event_data, API_ADMIN_UP_DOWN_EVENT);
426 /* Sort, so we can eliminate duplicates */
427 vec_sort_with_function (event_data, event_data_cmp);
429 prev_sw_if_index = ~0;
431 for (i = 0; i < vec_len(event_data); i++) {
432 /* Only one message per swif */
433 if (prev_sw_if_index == event_data[i])
435 prev_sw_if_index = event_data[i];
437 pool_foreach(reg, vam->interface_events_registrations,
439 q = vl_api_client_index_to_input_queue (reg->client_index);
441 // sw_interface may be deleted already
442 if (!pool_is_free_index (vnm->interface_main.sw_interfaces,
445 swif = vnet_get_sw_interface (vnm, event_data[i]);
446 send_sw_interface_flags (vam, q, swif);
451 vec_reset_length (event_data);
457 static clib_error_t *
458 link_up_down_function (vnet_main_t *vm, u32 hw_if_index, u32 flags);
459 static clib_error_t *
460 admin_up_down_function (vnet_main_t *vm, u32 hw_if_index, u32 flags);
462 VLIB_REGISTER_NODE (link_state_process_node,static) = {
463 .function = link_state_process,
464 .type = VLIB_NODE_TYPE_PROCESS,
465 .name = "vpe-link-state-process",
468 VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION (admin_up_down_function);
469 VNET_HW_INTERFACE_LINK_UP_DOWN_FUNCTION (link_up_down_function);
471 static clib_error_t *
472 link_up_down_function (vnet_main_t *vm, u32 hw_if_index, u32 flags)
474 vpe_api_main_t * vam = &vpe_api_main;
475 vnet_hw_interface_t *hi = vnet_get_hw_interface (vm, hw_if_index);
477 if (vam->link_state_process_up)
478 vlib_process_signal_event (vam->vlib_main,
479 link_state_process_node.index,
480 API_LINK_STATE_EVENT,
485 static clib_error_t *
486 admin_up_down_function (vnet_main_t *vm, u32 sw_if_index, u32 flags)
488 vpe_api_main_t * vam = &vpe_api_main;
491 * Note: it's perfectly fair to set a subif admin up / admin down.
492 * Note the subtle distinction between this routine and the previous
495 if (vam->link_state_process_up)
496 vlib_process_signal_event (vam->vlib_main,
497 link_state_process_node.index,
498 API_ADMIN_UP_DOWN_EVENT,
503 #define pub_sub_handler(lca,UCA) \
504 static void vl_api_want_##lca##_t_handler ( \
505 vl_api_want_##lca##_t *mp) \
507 vpe_api_main_t *vam = &vpe_api_main; \
508 vpe_client_registration_t *rp; \
509 vl_api_want_##lca##_reply_t *rmp; \
513 p = hash_get (vam->lca##_registration_hash, mp->client_index); \
515 if (mp->enable_disable) { \
516 clib_warning ("pid %d: already enabled...", mp->pid); \
517 rv = VNET_API_ERROR_INVALID_REGISTRATION; \
520 rp = pool_elt_at_index (vam->lca##_registrations, p[0]); \
521 pool_put (vam->lca##_registrations, rp); \
522 hash_unset (vam->lca##_registration_hash, \
527 if (mp->enable_disable == 0) { \
528 clib_warning ("pid %d: already disabled...", mp->pid); \
529 rv = VNET_API_ERROR_INVALID_REGISTRATION; \
532 pool_get (vam->lca##_registrations, rp); \
533 rp->client_index = mp->client_index; \
534 rp->client_pid = mp->pid; \
535 hash_set (vam->lca##_registration_hash, rp->client_index, \
536 rp - vam->lca##_registrations); \
539 REPLY_MACRO (VL_API_WANT_##UCA##_REPLY); \
542 pub_sub_handler (interface_events,INTERFACE_EVENTS)
543 pub_sub_handler (from_netconf_server,FROM_NETCONF_SERVER)
544 pub_sub_handler (to_netconf_server,TO_NETCONF_SERVER)
545 pub_sub_handler (from_netconf_client,FROM_NETCONF_CLIENT)
546 pub_sub_handler (to_netconf_client,TO_NETCONF_CLIENT)
547 pub_sub_handler (oam_events,OAM_EVENTS)
549 #define RESOLUTION_EVENT 1
550 #define RESOLUTION_PENDING_EVENT 2
551 #define IP4_ARP_EVENT 3
553 static int ip4_add_del_route_t_handler (vl_api_ip_add_del_route_t *mp);
554 static int ip6_add_del_route_t_handler (vl_api_ip_add_del_route_t *mp);
555 static int mpls_ethernet_add_del_tunnel_2_t_handler
556 (vl_api_mpls_ethernet_add_del_tunnel_2_t *mp);
558 void handle_ip4_arp_event (u32 pool_index)
560 vpe_api_main_t * vam = &vpe_api_main;
561 vnet_main_t * vnm = vam->vnet_main;
562 vlib_main_t * vm = vam->vlib_main;
563 vl_api_ip4_arp_event_t * event;
564 vl_api_ip4_arp_event_t * mp;
565 unix_shared_memory_queue_t * q;
567 /* Client can cancel, die, etc. */
568 if (pool_is_free_index (vam->arp_events, pool_index))
571 event = pool_elt_at_index (vam->arp_events, pool_index);
573 q = vl_api_client_index_to_input_queue (event->client_index);
575 (void) vnet_add_del_ip4_arp_change_event
576 (vnm, arp_change_delete_callback,
577 event->pid, &event->address,
578 vpe_resolver_process_node.index, IP4_ARP_EVENT,
579 ~0 /* pool index, notused */, 0 /* is_add */);
583 if (q->cursize < q->maxsize) {
584 mp = vl_msg_api_alloc (sizeof (*mp));
585 memcpy (mp, event, sizeof (*mp));
586 vl_msg_api_send_shmem (q, (u8 *)&mp);
588 static f64 last_time;
590 * Throttle syslog msgs.
591 * It's pretty tempting to just revoke the registration...
593 if (vlib_time_now (vm) > last_time + 10.0) {
594 clib_warning ("arp event for %U to pid %d: queue stuffed!",
595 format_ip4_address, &event->address, event->pid);
596 last_time = vlib_time_now(vm);
602 resolver_process (vlib_main_t * vm,
603 vlib_node_runtime_t * rt,
607 uword *event_data = 0;
609 vpe_api_main_t * vam = &vpe_api_main;
610 pending_route_t * pr;
611 vl_api_ip_add_del_route_t * adr;
612 vl_api_mpls_ethernet_add_del_tunnel_2_t *pme;
613 u32 * resolution_failures = 0;
618 vlib_process_wait_for_event_or_clock (vm, timeout);
620 event_type = vlib_process_get_events (vm, &event_data);
622 switch (event_type) {
623 case RESOLUTION_PENDING_EVENT:
627 case RESOLUTION_EVENT:
628 for (i = 0; i < vec_len(event_data); i++) {
630 * Resolution events can occur long after the
631 * original request has timed out. $$$ add a cancel
634 if (pool_is_free_index (vam->pending_routes, event_data[i]))
637 pr = pool_elt_at_index (vam->pending_routes, event_data[i]);
641 switch (pr->resolve_type) {
642 case RESOLVE_IP4_ADD_DEL_ROUTE:
643 rv = ip4_add_del_route_t_handler (adr);
644 clib_warning ("resolver: add %U/%d via %U %s",
646 (ip4_address_t *)&(adr->dst_address),
647 adr->dst_address_length,
649 (ip4_address_t *)&(adr->next_hop_address),
650 (rv >= 0) ? "succeeded" : "failed");
653 case RESOLVE_IP6_ADD_DEL_ROUTE:
654 rv = ip6_add_del_route_t_handler (adr);
655 clib_warning ("resolver: add %U/%d via %U %s",
657 (ip6_address_t *)&(adr->dst_address),
658 adr->dst_address_length,
660 (ip6_address_t *)&(adr->next_hop_address),
661 (rv >= 0) ? "succeeded" : "failed");
664 case RESOLVE_MPLS_ETHERNET_ADD_DEL:
665 rv = mpls_ethernet_add_del_tunnel_2_t_handler (pme);
666 clib_warning ("resolver: add mpls-o-e via %U %s",
668 (ip4_address_t *)&(pme->next_hop_ip4_address_in_outer_vrf),
669 (rv >= 0) ? "succeeded" : "failed");
673 clib_warning ("resolver: BOGUS TYPE %d", pr->resolve_type);
675 pool_put (vam->pending_routes, pr);
680 for (i = 0; i < vec_len(event_data); i++)
681 handle_ip4_arp_event (event_data[i]);
684 case ~0: /* timeout, retry pending resolutions */
685 pool_foreach (pr, vam->pending_routes,
691 /* May fail, e.g. due to interface down */
692 switch (pr->resolve_type) {
693 case RESOLVE_IP4_ADD_DEL_ROUTE:
694 e = ip4_probe_neighbor
695 (vm, (ip4_address_t *)&(adr->next_hop_address),
696 ntohl(adr->next_hop_sw_if_index));
699 case RESOLVE_IP6_ADD_DEL_ROUTE:
700 e = ip6_probe_neighbor
701 (vm, (ip6_address_t *)&(adr->next_hop_address),
702 ntohl(adr->next_hop_sw_if_index));
705 case RESOLVE_MPLS_ETHERNET_ADD_DEL:
707 e = ip4_probe_neighbor
709 (ip4_address_t *)&(pme->next_hop_ip4_address_in_outer_vrf),
710 pme->resolve_opaque);
714 e = clib_error_return (0, "resolver: BOGUS TYPE %d",
718 clib_error_report (e);
720 adr->resolve_attempts = 1;
722 pme->resolve_attempts = 1;
726 adr->resolve_attempts -= 1;
727 if (adr->resolve_attempts == 0)
728 vec_add1 (resolution_failures,
729 pr - vam->pending_routes);
731 pme->resolve_attempts -= 1;
732 if (pme->resolve_attempts == 0)
733 vec_add1 (resolution_failures,
734 pr - vam->pending_routes);
738 for (i = 0; i < vec_len (resolution_failures); i++) {
739 pr = pool_elt_at_index (vam->pending_routes,
740 resolution_failures[i]);
744 switch (pr->resolve_type) {
745 case RESOLVE_IP4_ADD_DEL_ROUTE:
746 clib_warning ("resolver: add %U/%d via %U retry failure",
748 (ip4_address_t *)&(adr->dst_address),
749 adr->dst_address_length,
751 (ip4_address_t *)&(adr->next_hop_address));
754 case RESOLVE_IP6_ADD_DEL_ROUTE:
755 clib_warning ("resolver: add %U/%d via %U retry failure",
757 (ip6_address_t *)&(adr->dst_address),
758 adr->dst_address_length,
760 (ip6_address_t *)&(adr->next_hop_address));
763 case RESOLVE_MPLS_ETHERNET_ADD_DEL:
764 clib_warning ("resolver: add mpls-o-e via %U retry failure",
766 (ip4_address_t *)&(pme->next_hop_ip4_address_in_outer_vrf));
770 clib_warning ("BUG");
772 pool_put(vam->pending_routes, pr);
774 vec_reset_length (resolution_failures);
777 if (pool_elts (vam->pending_routes) == 0)
779 vec_reset_length (event_data);
781 return 0; /* or not */
784 VLIB_REGISTER_NODE (vpe_resolver_process_node,static) = {
785 .function = resolver_process,
786 .type = VLIB_NODE_TYPE_PROCESS,
787 .name = "vpe-route-resolver-process",
790 static int ip4_add_del_route_t_handler (vl_api_ip_add_del_route_t *mp)
792 ip4_main_t * im = &ip4_main;
793 ip_lookup_main_t * lm = &im->lookup_main;
794 vnet_classify_main_t * cm = &vnet_classify_main;
795 stats_main_t * sm = &stats_main;
796 ip4_add_del_route_args_t a;
797 ip4_address_t next_hop_address;
799 vpe_api_main_t * vam = &vpe_api_main;
800 vnet_main_t * vnm = vam->vnet_main;
801 vlib_main_t * vm = vlib_get_main();
802 pending_route_t * pr;
803 vl_api_ip_add_del_route_t * adr;
807 ip_adjacency_t *nh_adj, *add_adj = 0;
809 p = hash_get (im->fib_index_by_table_id, ntohl(mp->vrf_id));
811 if (mp->create_vrf_if_needed) {
813 f = find_ip4_fib_by_table_index_or_id (im, ntohl(mp->vrf_id),
815 fib_index = f->index;
817 /* No such VRF, and we weren't asked to create one */
818 return VNET_API_ERROR_NO_SUCH_FIB;
824 if (pool_is_free_index (vnm->interface_main.sw_interfaces,
825 ntohl(mp->next_hop_sw_if_index)))
826 return VNET_API_ERROR_NO_MATCHING_INTERFACE;
828 memcpy (next_hop_address.data, mp->next_hop_address,
829 sizeof (next_hop_address.data));
831 /* Arp for the next_hop if necessary */
832 if (mp->is_add && mp->resolve_if_needed) {
834 ip_adjacency_t * adj;
836 lookup_result = ip4_fib_lookup_with_table
837 (im, fib_index, &next_hop_address, 1 /* disable default route */);
839 adj = ip_get_adjacency (lm, lookup_result);
841 if (adj->lookup_next_index == IP_LOOKUP_NEXT_ARP) {
842 pool_get (vam->pending_routes, pr);
843 pr->resolve_type = RESOLVE_IP4_ADD_DEL_ROUTE;
845 memcpy (adr, mp, sizeof (*adr));
846 /* recursion block, "just in case" */
847 adr->resolve_if_needed = 0;
848 adr->resolve_attempts = ntohl(mp->resolve_attempts);
849 vnet_register_ip4_arp_resolution_event
850 (vnm, &next_hop_address, vpe_resolver_process_node.index,
851 RESOLUTION_EVENT, pr - vam->pending_routes);
853 vlib_process_signal_event
854 (vm, vpe_resolver_process_node.index,
855 RESOLUTION_PENDING_EVENT, 0 /* data */);
857 /* The interface may be down, etc. */
858 e = ip4_probe_neighbor
859 (vm, (ip4_address_t *)&(mp->next_hop_address),
860 ntohl(mp->next_hop_sw_if_index));
863 clib_error_report(e);
865 return VNET_API_ERROR_IN_PROGRESS;
869 if (mp->is_multipath) {
872 dslock (sm, 1 /* release hint */, 10 /* tag */);
875 flags = IP4_ROUTE_FLAG_ADD;
877 flags = IP4_ROUTE_FLAG_DEL;
880 flags |= IP4_ROUTE_FLAG_NOT_LAST_IN_GROUP;
882 ip4_add_del_route_next_hop (im, flags,
883 (ip4_address_t *) mp->dst_address,
884 (u32) mp->dst_address_length,
885 (ip4_address_t *) mp->next_hop_address,
886 ntohl(mp->next_hop_sw_if_index),
887 (u32) mp->next_hop_weight,
894 memset (&a, 0, sizeof (a));
895 memcpy (a.dst_address.data, mp->dst_address, sizeof (a.dst_address.data));
897 a.dst_address_length = mp->dst_address_length;
899 a.flags = (mp->is_add ? IP4_ROUTE_FLAG_ADD : IP4_ROUTE_FLAG_DEL);
900 a.flags |= IP4_ROUTE_FLAG_FIB_INDEX;
901 a.table_index_or_table_id = fib_index;
906 a.flags |= IP4_ROUTE_FLAG_NOT_LAST_IN_GROUP;
908 dslock (sm, 1 /* release hint */, 2 /* tag */);
912 ai = lm->drop_adj_index;
913 else if (mp->is_local)
914 ai = lm->local_adj_index;
915 else if (mp->is_classify) {
917 memset(&cadj, 0, sizeof(cadj));
918 cadj.lookup_next_index = IP_LOOKUP_NEXT_CLASSIFY;
919 cadj.classify_table_index = ntohl(mp->classify_table_index);
920 if (pool_is_free_index (cm->tables, cadj.classify_table_index)) {
922 return VNET_API_ERROR_NO_SUCH_TABLE;
924 vec_add1 (add_adj, cadj);
928 ai = ip4_fib_lookup_with_table
929 (im, fib_index, &next_hop_address,
930 1 /* disable default route */);
931 if (ai == lm->miss_adj_index) {
933 return VNET_API_ERROR_NEXT_HOP_NOT_IN_FIB;
937 nh_adj = ip_get_adjacency (lm, ai);
938 vec_add1 (add_adj, nh_adj[0]);
939 if (mp->lookup_in_vrf) {
940 p = hash_get (im->fib_index_by_table_id, ntohl(mp->lookup_in_vrf));
942 add_adj[0].explicit_fib_index = p[0];
946 return VNET_API_ERROR_NO_SUCH_INNER_FIB;
950 ip_adjacency_t * adj;
951 int disable_default_route = 1;
953 /* Trying to delete the default route? */
954 if (a.dst_address.as_u32 == 0 &&
955 a.dst_address_length == 0)
956 disable_default_route = 0;
958 ai = ip4_fib_lookup_with_table
959 (im, fib_index, &a.dst_address, disable_default_route);
960 if (ai == lm->miss_adj_index) {
962 return VNET_API_ERROR_UNKNOWN_DESTINATION;
965 adj = ip_get_adjacency (lm, ai);
966 if (adj->lookup_next_index == IP_LOOKUP_NEXT_ARP) {
968 return VNET_API_ERROR_ADDRESS_MATCHES_INTERFACE_ADDRESS;
975 a.n_add_adj = vec_len(add_adj);
976 ip4_add_del_route (im, &a);
984 static int ip6_add_del_route_t_handler (vl_api_ip_add_del_route_t *mp)
986 ip6_main_t * im = &ip6_main;
987 ip_lookup_main_t * lm = &im->lookup_main;
988 vnet_main_t * vnm = vnet_get_main();
989 vlib_main_t * vm = vlib_get_main();
990 vpe_api_main_t * vam = &vpe_api_main;
991 stats_main_t * sm = &stats_main;
992 ip6_add_del_route_args_t a;
993 ip6_address_t next_hop_address;
994 pending_route_t * pr;
995 vl_api_ip_add_del_route_t * adr;
1000 ip_adjacency_t * nh_adj, * add_adj = 0;
1003 p = hash_get (im->fib_index_by_table_id, ntohl(mp->vrf_id));
1006 if (mp->create_vrf_if_needed) {
1008 f = find_ip6_fib_by_table_index_or_id (im, ntohl(mp->vrf_id),
1010 fib_index = f->index;
1012 /* No such VRF, and we weren't asked to create one */
1013 return VNET_API_ERROR_NO_SUCH_FIB;
1019 if (pool_is_free_index (vnm->interface_main.sw_interfaces,
1020 ntohl(mp->next_hop_sw_if_index)))
1021 return VNET_API_ERROR_NO_MATCHING_INTERFACE;
1023 memcpy (next_hop_address.as_u8, mp->next_hop_address,
1024 sizeof (next_hop_address.as_u8));
1026 /* Arp for the next_hop if necessary */
1027 if (mp->is_add && mp->resolve_if_needed) {
1029 ip_adjacency_t * adj;
1031 lookup_result = ip6_fib_lookup_with_table
1032 (im, fib_index, &next_hop_address);
1034 adj = ip_get_adjacency (lm, lookup_result);
1036 if (adj->lookup_next_index == IP_LOOKUP_NEXT_ARP) {
1037 pool_get (vam->pending_routes, pr);
1039 pr->resolve_type = RESOLVE_IP6_ADD_DEL_ROUTE;
1040 memcpy (adr, mp, sizeof (*adr));
1041 /* recursion block, "just in case" */
1042 adr->resolve_if_needed = 0;
1043 adr->resolve_attempts = ntohl(mp->resolve_attempts);
1044 vnet_register_ip6_neighbor_resolution_event
1045 (vnm, &next_hop_address, vpe_resolver_process_node.index,
1046 RESOLUTION_EVENT, pr - vam->pending_routes);
1048 vlib_process_signal_event
1049 (vm, vpe_resolver_process_node.index,
1050 RESOLUTION_PENDING_EVENT, 0 /* data */);
1052 /* The interface may be down, etc. */
1053 e = ip6_probe_neighbor
1054 (vm, (ip6_address_t *)&(mp->next_hop_address),
1055 ntohl(mp->next_hop_sw_if_index));
1058 clib_error_report(e);
1060 return VNET_API_ERROR_IN_PROGRESS;
1064 if (mp->is_multipath) {
1067 dslock (sm, 1 /* release hint */, 11 /* tag */);
1070 flags = IP6_ROUTE_FLAG_ADD;
1072 flags = IP6_ROUTE_FLAG_DEL;
1075 flags |= IP6_ROUTE_FLAG_NOT_LAST_IN_GROUP;
1077 ip6_add_del_route_next_hop (im, flags, (ip6_address_t *)mp->dst_address,
1078 (u32) mp->dst_address_length,
1079 (ip6_address_t *)mp->next_hop_address,
1080 ntohl(mp->next_hop_sw_if_index),
1081 (u32) mp->next_hop_weight,
1088 memset (&a, 0, sizeof (a));
1089 memcpy (a.dst_address.as_u8, mp->dst_address, sizeof (a.dst_address.as_u8));
1091 a.dst_address_length = mp->dst_address_length;
1093 a.flags = (mp->is_add ? IP6_ROUTE_FLAG_ADD : IP6_ROUTE_FLAG_DEL);
1094 a.flags |= IP6_ROUTE_FLAG_FIB_INDEX;
1095 a.table_index_or_table_id = fib_index;
1100 a.flags |= IP6_ROUTE_FLAG_NOT_LAST_IN_GROUP;
1102 dslock (sm, 1 /* release hint */, 3 /* tag */);
1106 ai = lm->drop_adj_index;
1107 else if (mp->is_local)
1108 ai = lm->local_adj_index;
1110 ai = ip6_fib_lookup_with_table
1111 (im, fib_index, &next_hop_address);
1112 if (ai == lm->miss_adj_index) {
1114 return VNET_API_ERROR_NEXT_HOP_NOT_IN_FIB;
1118 nh_adj = ip_get_adjacency (lm, ai);
1119 vec_add1 (add_adj, nh_adj[0]);
1120 if (mp->lookup_in_vrf) {
1121 p = hash_get (im->fib_index_by_table_id, ntohl(mp->lookup_in_vrf));
1123 add_adj[0].explicit_fib_index = p[0];
1127 return VNET_API_ERROR_NO_SUCH_INNER_FIB;
1131 ip_adjacency_t * adj;
1133 ai = ip6_fib_lookup_with_table
1134 (im, fib_index, &a.dst_address);
1135 if (ai == lm->miss_adj_index) {
1137 return VNET_API_ERROR_UNKNOWN_DESTINATION;
1139 adj = ip_get_adjacency (lm, ai);
1140 if (adj->lookup_next_index == IP_LOOKUP_NEXT_ARP) {
1142 return VNET_API_ERROR_ADDRESS_MATCHES_INTERFACE_ADDRESS;
1147 a.add_adj = add_adj;
1148 a.n_add_adj = vec_len(add_adj);
1149 ip6_add_del_route (im, &a);
1157 void vl_api_ip_add_del_route_t_handler (
1158 vl_api_ip_add_del_route_t *mp)
1160 vl_api_ip_add_del_route_reply_t * rmp;
1162 vnet_main_t * vnm = vnet_get_main();
1167 rv = ip6_add_del_route_t_handler (mp);
1169 rv = ip4_add_del_route_t_handler (mp);
1171 rv = (rv == 0) ? vnm->api_errno : rv;
1173 REPLY_MACRO(VL_API_IP_ADD_DEL_ROUTE_REPLY);
1176 void api_config_default_ip_route (u8 is_ipv6, u8 is_add, u32 vrf_id,
1177 u32 sw_if_index, u8 *next_hop_addr)
1179 vl_api_ip_add_del_route_t mp;
1182 memset (&mp, 0, sizeof(vl_api_ip_add_del_route_t));
1185 * Configure default IP route:
1186 * - ip route add 0.0.0.0/1 via <GW IP>
1187 * - ip route add 128.0.0.0/1 via <GW IP>
1189 mp.next_hop_sw_if_index = ntohl(sw_if_index);
1191 mp.resolve_attempts = ~0;
1192 mp.resolve_if_needed = 1;
1194 mp.is_ipv6 = is_ipv6;
1195 mp.next_hop_weight = 1;
1197 memcpy (&mp.next_hop_address[0], next_hop_addr, 16);
1200 rv = ip6_add_del_route_t_handler (&mp);
1203 mp.dst_address_length = 1;
1205 mp.dst_address[0] = 0;
1206 rv = ip4_add_del_route_t_handler (&mp);
1208 mp.dst_address[0] = 128;
1209 rv |= ip4_add_del_route_t_handler (&mp);
1213 clib_error_return (0, "failed to config default IP route");
1218 vl_api_sw_interface_add_del_address_t_handler
1219 (vl_api_sw_interface_add_del_address_t *mp)
1221 vlib_main_t *vm = vlib_get_main();
1222 vl_api_sw_interface_add_del_address_reply_t * rmp;
1226 VALIDATE_SW_IF_INDEX(mp);
1228 is_del = mp->is_add == 0;
1231 ip_del_all_interface_addresses (vm, ntohl(mp->sw_if_index));
1232 else if (mp->is_ipv6)
1233 ip6_add_del_interface_address (vm, ntohl(mp->sw_if_index),
1234 (void *)mp->address,
1235 mp->address_length, is_del);
1237 ip4_add_del_interface_address (vm, ntohl(mp->sw_if_index),
1238 (void *) mp->address,
1239 mp->address_length, is_del);
1241 BAD_SW_IF_INDEX_LABEL;
1243 REPLY_MACRO(VL_API_SW_INTERFACE_ADD_DEL_ADDRESS_REPLY);
1247 vl_api_sw_interface_set_table_t_handler (vl_api_sw_interface_set_table_t *mp)
1250 u32 table_id = ntohl(mp->vrf_id);
1251 u32 sw_if_index = ntohl(mp->sw_if_index);
1252 vl_api_sw_interface_set_table_reply_t * rmp;
1253 stats_main_t * sm = &stats_main;
1255 VALIDATE_SW_IF_INDEX(mp);
1257 dslock (sm, 1 /* release hint */, 4 /* tag */);
1260 ip6_main_t * im = &ip6_main;
1262 find_ip6_fib_by_table_index_or_id (im, table_id,
1263 IP6_ROUTE_FLAG_TABLE_ID);
1265 vec_validate (im->fib_index_by_sw_if_index, sw_if_index);
1266 im->fib_index_by_sw_if_index[sw_if_index] = fib->index;
1268 rv = VNET_API_ERROR_NO_SUCH_FIB;
1271 ip4_main_t * im = &ip4_main;
1272 ip4_fib_t * fib = find_ip4_fib_by_table_index_or_id
1273 (im, table_id, IP4_ROUTE_FLAG_TABLE_ID);
1275 /* Truthfully this can't fail */
1277 vec_validate (im->fib_index_by_sw_if_index, sw_if_index);
1278 im->fib_index_by_sw_if_index[sw_if_index] = fib->index;
1280 rv = VNET_API_ERROR_NO_SUCH_FIB;
1285 BAD_SW_IF_INDEX_LABEL;
1287 REPLY_MACRO(VL_API_SW_INTERFACE_SET_TABLE_REPLY);
1291 vl_api_sw_interface_set_vpath_t_handler (vl_api_sw_interface_set_vpath_t *mp)
1293 vlib_main_t *vm = vlib_get_main();
1294 vl_api_sw_interface_set_vpath_reply_t * rmp;
1297 u32 sw_if_index = ntohl(mp->sw_if_index);
1298 ip4_main_t *ip4m = &ip4_main;
1299 ip6_main_t *ip6m = &ip6_main;
1300 ip_lookup_main_t *ip4lm = &ip4m->lookup_main;
1301 ip_lookup_main_t *ip6lm = &ip6m->lookup_main;
1302 ip_config_main_t *rx_cm4u = &ip4lm->rx_config_mains[VNET_UNICAST];
1303 ip_config_main_t *rx_cm4m = &ip4lm->rx_config_mains[VNET_MULTICAST];
1304 ip_config_main_t *rx_cm6u = &ip6lm->rx_config_mains[VNET_UNICAST];
1305 ip_config_main_t *rx_cm6m = &ip6lm->rx_config_mains[VNET_MULTICAST];
1307 VALIDATE_SW_IF_INDEX(mp);
1309 l2input_intf_bitmap_enable(sw_if_index, L2INPUT_FEAT_VPATH, mp->enable);
1311 ci = rx_cm4u->config_index_by_sw_if_index[sw_if_index]; //IP4 unicast
1312 ci = vnet_config_add_feature(vm, &rx_cm4u->config_main,
1313 ci, IP4_RX_FEATURE_VPATH, 0, 0);
1314 rx_cm4u->config_index_by_sw_if_index[sw_if_index] = ci;
1315 ci = rx_cm4m->config_index_by_sw_if_index[sw_if_index]; //IP4 mcast
1316 ci = vnet_config_add_feature(vm, &rx_cm4m->config_main,
1317 ci, IP4_RX_FEATURE_VPATH, 0, 0);
1318 rx_cm4m->config_index_by_sw_if_index[sw_if_index] = ci;
1319 ci = rx_cm6u->config_index_by_sw_if_index[sw_if_index]; //IP6 unicast
1320 ci = vnet_config_add_feature(vm, &rx_cm6u->config_main,
1321 ci, IP6_RX_FEATURE_VPATH, 0, 0);
1322 rx_cm6u->config_index_by_sw_if_index[sw_if_index] = ci;
1323 ci = rx_cm6m->config_index_by_sw_if_index[sw_if_index]; //IP6 mcast
1324 ci = vnet_config_add_feature(vm, &rx_cm6m->config_main,
1325 ci, IP6_RX_FEATURE_VPATH, 0, 0);
1326 rx_cm6m->config_index_by_sw_if_index[sw_if_index] = ci;
1328 ci = rx_cm4u->config_index_by_sw_if_index[sw_if_index]; //IP4 unicast
1329 ci = vnet_config_del_feature(vm, &rx_cm4u->config_main,
1330 ci, IP4_RX_FEATURE_VPATH, 0, 0);
1331 rx_cm4u->config_index_by_sw_if_index[sw_if_index] = ci;
1332 ci = rx_cm4m->config_index_by_sw_if_index[sw_if_index]; //IP4 mcast
1333 ci = vnet_config_del_feature(vm, &rx_cm4m->config_main,
1334 ci, IP4_RX_FEATURE_VPATH, 0, 0);
1335 rx_cm4m->config_index_by_sw_if_index[sw_if_index] = ci;
1336 ci = rx_cm6u->config_index_by_sw_if_index[sw_if_index]; //IP6 unicast
1337 ci = vnet_config_del_feature(vm, &rx_cm6u->config_main,
1338 ci, IP6_RX_FEATURE_VPATH, 0, 0);
1339 rx_cm6u->config_index_by_sw_if_index[sw_if_index] = ci;
1340 ci = rx_cm6m->config_index_by_sw_if_index[sw_if_index]; //IP6 mcast
1341 ci = vnet_config_del_feature(vm, &rx_cm6m->config_main,
1342 ci, IP6_RX_FEATURE_VPATH, 0, 0);
1343 rx_cm6m->config_index_by_sw_if_index[sw_if_index] = ci;
1346 BAD_SW_IF_INDEX_LABEL;
1348 REPLY_MACRO(VL_API_SW_INTERFACE_SET_VPATH_REPLY);
1352 vl_api_sw_interface_set_l2_xconnect_t_handler (
1353 vl_api_sw_interface_set_l2_xconnect_t *mp)
1355 vl_api_sw_interface_set_l2_xconnect_reply_t * rmp;
1357 u32 rx_sw_if_index = ntohl(mp->rx_sw_if_index);
1358 u32 tx_sw_if_index = ntohl(mp->tx_sw_if_index);
1359 vlib_main_t *vm = vlib_get_main();
1360 vnet_main_t *vnm = vnet_get_main();
1362 VALIDATE_RX_SW_IF_INDEX(mp);
1365 VALIDATE_TX_SW_IF_INDEX(mp);
1366 rv = set_int_l2_mode(vm, vnm, MODE_L2_XC,
1367 rx_sw_if_index, 0, 0, 0, tx_sw_if_index);
1369 rv = set_int_l2_mode(vm, vnm, MODE_L3, rx_sw_if_index, 0, 0, 0, 0);
1372 BAD_RX_SW_IF_INDEX_LABEL;
1373 BAD_TX_SW_IF_INDEX_LABEL;
1375 REPLY_MACRO(VL_API_SW_INTERFACE_SET_L2_XCONNECT_REPLY);
1379 vl_api_sw_interface_set_l2_bridge_t_handler (
1380 vl_api_sw_interface_set_l2_bridge_t *mp)
1382 bd_main_t * bdm = &bd_main;
1383 vl_api_sw_interface_set_l2_bridge_reply_t * rmp;
1385 u32 rx_sw_if_index = ntohl(mp->rx_sw_if_index);
1386 u32 bd_id = ntohl(mp->bd_id);
1390 vlib_main_t *vm = vlib_get_main();
1391 vnet_main_t *vnm = vnet_get_main();
1393 VALIDATE_RX_SW_IF_INDEX(mp);
1395 bd_index = bd_find_or_add_bd_index (bdm, bd_id);
1398 //VALIDATE_TX_SW_IF_INDEX(mp);
1399 rv = set_int_l2_mode(vm, vnm, MODE_L2_BRIDGE,
1400 rx_sw_if_index, bd_index, bvi, shg, 0);
1402 rv = set_int_l2_mode(vm, vnm, MODE_L3, rx_sw_if_index, 0, 0, 0, 0);
1405 BAD_RX_SW_IF_INDEX_LABEL;
1407 REPLY_MACRO(VL_API_SW_INTERFACE_SET_L2_BRIDGE_REPLY);
1411 vl_api_bridge_domain_add_del_t_handler (
1412 vl_api_bridge_domain_add_del_t *mp)
1414 vlib_main_t * vm = vlib_get_main ();
1415 bd_main_t * bdm = &bd_main;
1416 vl_api_bridge_domain_add_del_reply_t * rmp;
1418 u32 enable_flags = 0, disable_flags = 0;
1419 u32 bd_id = ntohl(mp->bd_id);
1423 bd_index = bd_find_or_add_bd_index (bdm, bd_id);
1426 enable_flags |= L2_FLOOD;
1428 disable_flags |= L2_FLOOD;
1431 enable_flags |= L2_UU_FLOOD;
1433 disable_flags |= L2_UU_FLOOD;
1436 enable_flags |= L2_FWD;
1438 disable_flags |= L2_FWD;
1441 enable_flags |= L2_ARP_TERM;
1443 disable_flags |= L2_ARP_TERM;
1446 enable_flags |= L2_LEARN;
1448 disable_flags |= L2_LEARN;
1451 bd_set_flags (vm, bd_index, enable_flags, 1 /* enable */);
1454 bd_set_flags (vm, bd_index, disable_flags, 0 /* disable */);
1457 rv = bd_delete_bd_index(bdm, bd_id);
1459 REPLY_MACRO(VL_API_BRIDGE_DOMAIN_ADD_DEL_REPLY);
1462 static void vl_api_bridge_domain_details_t_handler (
1463 vl_api_bridge_domain_details_t * mp)
1465 clib_warning ("BUG");
1468 static void vl_api_bridge_domain_sw_if_details_t_handler (
1469 vl_api_bridge_domain_sw_if_details_t * mp)
1471 clib_warning ("BUG");
1474 static void send_bridge_domain_details (unix_shared_memory_queue_t *q,
1475 l2_bridge_domain_t * bd_config,
1478 vl_api_bridge_domain_details_t * mp;
1480 mp = vl_msg_api_alloc (sizeof (*mp));
1481 memset (mp, 0, sizeof (*mp));
1482 mp->_vl_msg_id = ntohs (VL_API_BRIDGE_DOMAIN_DETAILS);
1483 mp->bd_id = ntohl (bd_config->bd_id);
1484 mp->flood = bd_feature_flood (bd_config);
1485 mp->uu_flood = bd_feature_uu_flood (bd_config);
1486 mp->forward = bd_feature_forward (bd_config);
1487 mp->learn = bd_feature_learn (bd_config);
1488 mp->arp_term = bd_feature_arp_term (bd_config);
1489 mp->bvi_sw_if_index = ntohl (bd_config->bvi_sw_if_index);
1490 mp->n_sw_ifs = ntohl (n_sw_ifs);
1492 vl_msg_api_send_shmem (q, (u8 *)&mp);
1495 static void send_bd_sw_if_details (l2input_main_t * l2im,
1496 unix_shared_memory_queue_t *q,
1497 l2_flood_member_t * member, u32 bd_id)
1499 vl_api_bridge_domain_sw_if_details_t * mp;
1500 l2_input_config_t * input_cfg;
1502 mp = vl_msg_api_alloc (sizeof (*mp));
1503 memset (mp, 0, sizeof (*mp));
1504 mp->_vl_msg_id = ntohs (VL_API_BRIDGE_DOMAIN_SW_IF_DETAILS);
1505 mp->bd_id = ntohl (bd_id);
1506 mp->sw_if_index = ntohl (member->sw_if_index);
1507 input_cfg = vec_elt_at_index (l2im->configs, member->sw_if_index);
1508 mp->shg = input_cfg->shg;
1510 vl_msg_api_send_shmem (q, (u8 *)&mp);
1513 static void vl_api_bridge_domain_dump_t_handler (
1514 vl_api_bridge_domain_dump_t *mp)
1516 bd_main_t * bdm = &bd_main;
1517 l2input_main_t * l2im = &l2input_main;
1518 unix_shared_memory_queue_t * q;
1519 l2_bridge_domain_t * bd_config;
1520 u32 bd_id, bd_index;
1523 q = vl_api_client_index_to_input_queue (mp->client_index);
1528 bd_id = ntohl(mp->bd_id);
1530 bd_index = (bd_id == ~0) ? 0 : bd_find_or_add_bd_index (bdm, bd_id);
1531 end = (bd_id == ~0) ? vec_len (l2im->bd_configs) : bd_index + 1;
1532 for (; bd_index < end; bd_index++) {
1533 bd_config = l2input_bd_config_from_index (l2im, bd_index);
1534 /* skip dummy bd_id 0 */
1535 if (bd_config && (bd_config->bd_id > 0)) {
1537 l2_flood_member_t * m;
1539 n_sw_ifs = vec_len (bd_config->members);
1540 send_bridge_domain_details (q, bd_config, n_sw_ifs);
1542 vec_foreach (m, bd_config->members) {
1543 send_bd_sw_if_details (l2im, q, m, bd_config->bd_id);
1550 vl_api_l2fib_add_del_t_handler (
1551 vl_api_l2fib_add_del_t *mp)
1553 bd_main_t * bdm = &bd_main;
1554 l2input_main_t * l2im = &l2input_main;
1555 vl_api_l2fib_add_del_reply_t * rmp;
1558 u32 sw_if_index = ntohl(mp->sw_if_index);
1559 u32 bd_id = ntohl(mp->bd_id);
1567 p = hash_get (bdm->bd_index_by_bd_id, bd_id);
1569 rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1570 goto bad_sw_if_index;
1575 VALIDATE_SW_IF_INDEX(mp);
1576 if (vec_len(l2im->configs) <= sw_if_index) {
1577 rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
1578 goto bad_sw_if_index;
1580 l2_input_config_t * config;
1581 config = vec_elt_at_index(l2im->configs, sw_if_index);
1582 if (config->bridge == 0) {
1583 rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
1584 goto bad_sw_if_index;
1587 static_mac = mp->static_mac ? 1 : 0;
1588 filter_mac = mp->filter_mac ? 1 : 0;
1589 l2fib_add_entry(mac, bd_index, sw_if_index, static_mac, filter_mac,
1592 l2fib_del_entry(mac, bd_index);
1595 BAD_SW_IF_INDEX_LABEL;
1597 REPLY_MACRO(VL_API_L2FIB_ADD_DEL_REPLY);
1601 vl_api_l2_flags_t_handler (
1602 vl_api_l2_flags_t *mp)
1604 vl_api_l2_flags_reply_t * rmp;
1606 u32 sw_if_index = ntohl(mp->sw_if_index);
1607 u32 flags = ntohl(mp->feature_bitmap);
1610 VALIDATE_SW_IF_INDEX(mp);
1613 if (flags & L2INPUT_FEAT_ ## a) \
1614 rbm = l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_ ## a, mp->is_set);
1615 foreach_l2input_feat;
1618 BAD_SW_IF_INDEX_LABEL;
1620 REPLY_MACRO2(VL_API_L2_FLAGS_REPLY, rmp->resulting_feature_bitmap = ntohl(rbm));
1624 vl_api_bridge_flags_t_handler (
1625 vl_api_bridge_flags_t *mp)
1627 vlib_main_t *vm = vlib_get_main();
1628 bd_main_t * bdm = &bd_main;
1629 vl_api_bridge_flags_reply_t * rmp;
1631 u32 bd_id = ntohl(mp->bd_id);
1633 u32 flags = ntohl(mp->feature_bitmap);
1636 p = hash_get (bdm->bd_index_by_bd_id, bd_id);
1638 rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1644 bd_set_flags(vm, bd_index, flags, mp->is_set);
1647 REPLY_MACRO2(VL_API_BRIDGE_FLAGS_REPLY,
1648 rmp->resulting_feature_bitmap = ntohl(flags));
1652 vl_api_bd_ip_mac_add_del_t_handler (
1653 vl_api_bd_ip_mac_add_del_t *mp)
1655 bd_main_t * bdm = &bd_main;
1656 vl_api_bd_ip_mac_add_del_reply_t * rmp;
1658 u32 bd_id = ntohl(mp->bd_id);
1662 p = hash_get (bdm->bd_index_by_bd_id, bd_id);
1664 rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1669 if (bd_add_del_ip_mac(bd_index, mp->ip_address,
1670 mp->mac_address, mp->is_ipv6, mp->is_add))
1671 rv = VNET_API_ERROR_UNSPECIFIED;
1674 REPLY_MACRO(VL_API_BD_IP_MAC_ADD_DEL_REPLY);
1678 vl_api_tap_connect_t_handler (vl_api_tap_connect_t *mp, vlib_main_t *vm)
1681 vl_api_tap_connect_reply_t * rmp;
1682 unix_shared_memory_queue_t * q;
1683 u32 sw_if_index = (u32)~0;
1685 rv = vnet_tap_connect_renumber (vm, mp->tap_name,
1686 mp->use_random_mac ? 0 : mp->mac_address,
1687 &sw_if_index, mp->renumber,
1688 ntohl(mp->custom_dev_instance));
1690 q = vl_api_client_index_to_input_queue (mp->client_index);
1694 rmp = vl_msg_api_alloc (sizeof (*rmp));
1695 rmp->_vl_msg_id = ntohs(VL_API_TAP_CONNECT_REPLY);
1696 rmp->context = mp->context;
1697 rmp->retval = ntohl(rv);
1698 rmp->sw_if_index = ntohl(sw_if_index);
1700 vl_msg_api_send_shmem (q, (u8 *)&rmp);
1704 vl_api_tap_modify_t_handler (vl_api_tap_modify_t *mp, vlib_main_t *vm)
1707 vl_api_tap_modify_reply_t * rmp;
1708 unix_shared_memory_queue_t * q;
1709 u32 sw_if_index = (u32)~0;
1711 rv = vnet_tap_modify (vm, ntohl(mp->sw_if_index), mp->tap_name,
1712 mp->use_random_mac ? 0 : mp->mac_address,
1713 &sw_if_index, mp->renumber,
1714 ntohl(mp->custom_dev_instance));
1716 q = vl_api_client_index_to_input_queue (mp->client_index);
1720 rmp = vl_msg_api_alloc (sizeof (*rmp));
1721 rmp->_vl_msg_id = ntohs(VL_API_TAP_MODIFY_REPLY);
1722 rmp->context = mp->context;
1723 rmp->retval = ntohl(rv);
1724 rmp->sw_if_index = ntohl(sw_if_index);
1726 vl_msg_api_send_shmem (q, (u8 *)&rmp);
1730 vl_api_tap_delete_t_handler (vl_api_tap_delete_t *mp, vlib_main_t *vm)
1733 vpe_api_main_t * vam = &vpe_api_main;
1734 vl_api_tap_delete_reply_t * rmp;
1735 unix_shared_memory_queue_t * q;
1736 u32 sw_if_index = ntohl(mp->sw_if_index);
1738 rv = vnet_tap_delete (vm, sw_if_index);
1740 q = vl_api_client_index_to_input_queue (mp->client_index);
1744 rmp = vl_msg_api_alloc (sizeof (*rmp));
1745 rmp->_vl_msg_id = ntohs(VL_API_TAP_DELETE_REPLY);
1746 rmp->context = mp->context;
1747 rmp->retval = ntohl(rv);
1749 vl_msg_api_send_shmem (q, (u8 *)&rmp);
1752 send_sw_interface_flags_deleted (vam, q, sw_if_index);
1756 vl_api_create_vlan_subif_t_handler (vl_api_create_vlan_subif_t * mp)
1758 vl_api_create_vlan_subif_reply_t * rmp;
1759 vnet_main_t * vnm = vnet_get_main();
1760 u32 hw_if_index, sw_if_index = (u32)~0;
1761 vnet_hw_interface_t * hi;
1764 vnet_sw_interface_t template;
1766 vnet_interface_main_t * im = &vnm->interface_main;
1767 u64 sup_and_sub_key;
1769 unix_shared_memory_queue_t * q;
1770 clib_error_t * error;
1772 VALIDATE_SW_IF_INDEX(mp);
1774 hw_if_index = ntohl(mp->sw_if_index);
1775 hi = vnet_get_hw_interface (vnm, hw_if_index);
1777 id = ntohl(mp->vlan_id);
1778 if (id == 0 || id > 4095) {
1779 rv = VNET_API_ERROR_INVALID_VLAN;
1783 sup_and_sub_key = ((u64)(hi->sw_if_index) << 32) | (u64) id;
1785 p = hash_get_mem (im->sw_if_index_by_sup_and_sub, &sup_and_sub_key);
1787 rv = VNET_API_ERROR_VLAN_ALREADY_EXISTS;
1791 kp = clib_mem_alloc (sizeof (*kp));
1792 *kp = sup_and_sub_key;
1794 template.type = VNET_SW_INTERFACE_TYPE_SUB;
1795 template.sup_sw_if_index = hi->sw_if_index;
1796 template.sub.id = id;
1797 template.sub.eth.raw_flags = 0;
1798 template.sub.eth.flags.one_tag = 1;
1799 template.sub.eth.outer_vlan_id = id;
1800 template.sub.eth.flags.exact_match = 1;
1802 error = vnet_create_sw_interface (vnm, &template, &sw_if_index);
1804 clib_error_report(error);
1805 rv = VNET_API_ERROR_INVALID_REGISTRATION;
1808 hash_set (hi->sub_interface_sw_if_index_by_id, id, sw_if_index);
1809 hash_set_mem (im->sw_if_index_by_sup_and_sub, kp, sw_if_index);
1811 BAD_SW_IF_INDEX_LABEL;
1814 q = vl_api_client_index_to_input_queue (mp->client_index);
1818 rmp = vl_msg_api_alloc (sizeof (*rmp));
1819 rmp->_vl_msg_id = ntohs(VL_API_CREATE_VLAN_SUBIF_REPLY);
1820 rmp->context = mp->context;
1821 rmp->retval = ntohl(rv);
1822 rmp->sw_if_index = ntohl(sw_if_index);
1823 vl_msg_api_send_shmem (q, (u8 *)&rmp);
1827 vl_api_create_subif_t_handler (vl_api_create_subif_t * mp)
1829 vl_api_create_subif_reply_t * rmp;
1830 vnet_main_t * vnm = vnet_get_main();
1831 u32 sw_if_index = ~0;
1834 vnet_sw_interface_t *si;
1835 vnet_hw_interface_t *hi;
1836 vnet_sw_interface_t template;
1838 vnet_interface_main_t * im = &vnm->interface_main;
1839 u64 sup_and_sub_key;
1841 clib_error_t * error;
1843 VALIDATE_SW_IF_INDEX(mp);
1845 si = vnet_get_sup_sw_interface (vnm, ntohl(mp->sw_if_index));
1846 hi = vnet_get_sup_hw_interface (vnm, ntohl(mp->sw_if_index));
1848 sw_if_index = si->sw_if_index;
1849 sub_id = ntohl(mp->sub_id);
1851 sup_and_sub_key = ((u64)(sw_if_index) << 32) | (u64) sub_id;
1853 p = hash_get_mem (im->sw_if_index_by_sup_and_sub, &sup_and_sub_key);
1856 clib_warning ("sup sw_if_index %d, sub id %d already exists\n",
1857 sw_if_index, sub_id);
1858 rv = VNET_API_ERROR_SUBIF_ALREADY_EXISTS;
1862 kp = clib_mem_alloc (sizeof (*kp));
1863 *kp = sup_and_sub_key;
1865 memset (&template, 0, sizeof (template));
1866 template.type = VNET_SW_INTERFACE_TYPE_SUB;
1867 template.sup_sw_if_index = sw_if_index;
1868 template.sub.id = sub_id;
1869 template.sub.eth.flags.no_tags = mp->no_tags;
1870 template.sub.eth.flags.one_tag = mp->one_tag;
1871 template.sub.eth.flags.two_tags = mp->two_tags;
1872 template.sub.eth.flags.dot1ad = mp->dot1ad;
1873 template.sub.eth.flags.exact_match = mp->exact_match;
1874 template.sub.eth.flags.default_sub = mp->default_sub;
1875 template.sub.eth.flags.outer_vlan_id_any = mp->outer_vlan_id_any;
1876 template.sub.eth.flags.inner_vlan_id_any = mp->inner_vlan_id_any;
1877 template.sub.eth.outer_vlan_id = ntohs(mp->outer_vlan_id);
1878 template.sub.eth.inner_vlan_id = ntohs(mp->inner_vlan_id);
1880 error = vnet_create_sw_interface (vnm, &template, &sw_if_index);
1882 clib_error_report (error);
1883 rv = VNET_API_ERROR_SUBIF_CREATE_FAILED;
1887 hash_set (hi->sub_interface_sw_if_index_by_id, sub_id, sw_if_index);
1888 hash_set_mem (im->sw_if_index_by_sup_and_sub, kp, sw_if_index);
1890 BAD_SW_IF_INDEX_LABEL;
1894 REPLY_MACRO2(VL_API_CREATE_SUBIF_REPLY,
1896 rmp->sw_if_index = ntohl(sw_if_index);
1901 vl_api_mpls_gre_add_del_tunnel_t_handler (vl_api_mpls_gre_add_del_tunnel_t *mp)
1903 vl_api_mpls_gre_add_del_tunnel_reply_t * rmp;
1905 stats_main_t * sm = &stats_main;
1906 u32 tunnel_sw_if_index = ~0;
1908 dslock (sm, 1 /* release hint */, 5 /* tag */);
1910 rv = vnet_mpls_gre_add_del_tunnel ((ip4_address_t *)(mp->src_address),
1911 (ip4_address_t *)(mp->dst_address),
1912 (ip4_address_t *)(mp->intfc_address),
1913 (u32)(mp->intfc_address_length),
1914 ntohl(mp->inner_vrf_id),
1915 ntohl(mp->outer_vrf_id),
1916 &tunnel_sw_if_index,
1921 REPLY_MACRO2(VL_API_MPLS_GRE_ADD_DEL_TUNNEL_REPLY,
1923 rmp->tunnel_sw_if_index = ntohl(tunnel_sw_if_index);
1928 vl_api_mpls_ethernet_add_del_tunnel_t_handler
1929 (vl_api_mpls_ethernet_add_del_tunnel_t *mp)
1931 vl_api_mpls_ethernet_add_del_tunnel_reply_t * rmp;
1933 stats_main_t * sm = &stats_main;
1934 u32 tunnel_sw_if_index;
1936 dslock (sm, 1 /* release hint */, 5 /* tag */);
1938 rv = vnet_mpls_ethernet_add_del_tunnel
1939 (mp->dst_mac_address, (ip4_address_t *)(mp->adj_address),
1940 (u32)(mp->adj_address_length), ntohl(mp->vrf_id),
1941 ntohl(mp->tx_sw_if_index),
1942 &tunnel_sw_if_index,
1948 REPLY_MACRO2(VL_API_MPLS_ETHERNET_ADD_DEL_TUNNEL_REPLY,
1950 rmp->tunnel_sw_if_index = ntohl(tunnel_sw_if_index);
1955 * This piece of misery brought to you because the control-plane
1956 * can't figure out the tx interface + dst-mac address all by itself
1958 static int mpls_ethernet_add_del_tunnel_2_t_handler
1959 (vl_api_mpls_ethernet_add_del_tunnel_2_t *mp)
1961 pending_route_t * pr;
1962 vl_api_mpls_ethernet_add_del_tunnel_2_t *pme;
1963 vnet_main_t * vnm = vnet_get_main();
1964 vlib_main_t * vm = vlib_get_main();
1965 stats_main_t * sm = &stats_main;
1966 vpe_api_main_t * vam = &vpe_api_main;
1967 u32 inner_fib_index, outer_fib_index;
1968 ip4_main_t * im = &ip4_main;
1969 ip_lookup_main_t * lm = &im->lookup_main;
1970 ip_adjacency_t * adj = 0;
1973 u8 * dst_mac_address;
1977 u32 tunnel_sw_if_index;
1979 p = hash_get (im->fib_index_by_table_id, ntohl(mp->outer_vrf_id));
1981 return VNET_API_ERROR_NO_SUCH_FIB;
1983 outer_fib_index = p[0];
1986 p = hash_get (im->fib_index_by_table_id, ntohl(mp->inner_vrf_id));
1988 return VNET_API_ERROR_NO_SUCH_INNER_FIB;
1990 inner_fib_index = p[0];
1992 if (inner_fib_index == outer_fib_index)
1993 return VNET_API_ERROR_INVALID_VALUE;
1995 lookup_result = ip4_fib_lookup_with_table
1996 (im, outer_fib_index,
1997 (ip4_address_t *)mp->next_hop_ip4_address_in_outer_vrf,
1998 1 /* disable default route */);
2000 adj = ip_get_adjacency (lm, lookup_result);
2001 tx_sw_if_index = adj->rewrite_header.sw_if_index;
2003 if (mp->is_add && mp->resolve_if_needed) {
2004 if (adj->lookup_next_index == IP_LOOKUP_NEXT_ARP) {
2005 pool_get (vam->pending_routes, pr);
2006 pr->resolve_type = RESOLVE_MPLS_ETHERNET_ADD_DEL;
2008 memcpy (pme, mp, sizeof (*pme));
2009 /* recursion block, "just in case" */
2010 pme->resolve_if_needed = 0;
2011 pme->resolve_attempts = ntohl(mp->resolve_attempts);
2012 pme->resolve_opaque = tx_sw_if_index;
2013 vnet_register_ip4_arp_resolution_event
2015 (ip4_address_t *)&(pme->next_hop_ip4_address_in_outer_vrf),
2016 vpe_resolver_process_node.index,
2017 RESOLUTION_EVENT, pr - vam->pending_routes);
2019 vlib_process_signal_event
2020 (vm, vpe_resolver_process_node.index,
2021 RESOLUTION_PENDING_EVENT, 0 /* data */);
2023 /* The interface may be down, etc. */
2024 e = ip4_probe_neighbor
2025 (vm, (ip4_address_t *)&(mp->next_hop_ip4_address_in_outer_vrf),
2029 clib_error_report(e);
2031 return VNET_API_ERROR_IN_PROGRESS;
2035 if (adj->lookup_next_index != IP_LOOKUP_NEXT_REWRITE)
2036 return VNET_API_ERROR_NEXT_HOP_NOT_IN_FIB;
2039 vnet_rewrite_get_data_internal
2040 (&adj->rewrite_header, sizeof (adj->rewrite_data));
2042 dslock (sm, 1 /* release hint */, 10 /* tag */);
2044 rv = vnet_mpls_ethernet_add_del_tunnel
2045 (dst_mac_address, (ip4_address_t *)(mp->adj_address),
2046 (u32)(mp->adj_address_length), ntohl(mp->inner_vrf_id),
2047 tx_sw_if_index, &tunnel_sw_if_index, mp->l2_only, mp->is_add);
2055 vl_api_mpls_ethernet_add_del_tunnel_2_t_handler
2056 (vl_api_mpls_ethernet_add_del_tunnel_2_t *mp)
2058 vl_api_mpls_ethernet_add_del_tunnel_reply_t * rmp;
2061 rv = mpls_ethernet_add_del_tunnel_2_t_handler (mp);
2063 REPLY_MACRO(VL_API_MPLS_ETHERNET_ADD_DEL_TUNNEL_2_REPLY);
2068 vl_api_mpls_add_del_encap_t_handler (vl_api_mpls_add_del_encap_t *mp)
2070 vl_api_mpls_add_del_encap_reply_t * rmp;
2072 static u32 * labels;
2075 vec_reset_length (labels);
2077 for (i = 0; i < mp->nlabels; i++)
2078 vec_add1 (labels, ntohl(mp->labels[i]));
2081 rv = vnet_mpls_add_del_encap ((ip4_address_t *)mp->dst_address,
2082 ntohl(mp->vrf_id), labels,
2083 ~0 /* policy_tunnel_index */,
2084 0 /* no_dst_hash */,
2088 REPLY_MACRO(VL_API_MPLS_ADD_DEL_ENCAP_REPLY);
2092 vl_api_mpls_add_del_decap_t_handler
2093 (vl_api_mpls_add_del_decap_t *mp)
2095 vl_api_mpls_add_del_decap_reply_t * rmp;
2098 rv = vnet_mpls_add_del_decap (ntohl(mp->rx_vrf_id), ntohl(mp->tx_vrf_id),
2099 ntohl(mp->label), ntohl(mp->next_index),
2100 mp->s_bit, mp->is_add);
2102 REPLY_MACRO(VL_API_MPLS_ADD_DEL_DECAP_REPLY);
2106 vl_api_proxy_arp_add_del_t_handler (vl_api_proxy_arp_add_del_t *mp)
2108 vl_api_proxy_arp_add_del_reply_t * rmp;
2111 ip4_main_t * im = &ip4_main;
2112 stats_main_t * sm = &stats_main;
2113 int vnet_proxy_arp_add_del (ip4_address_t *lo_addr,
2114 ip4_address_t *hi_addr,
2115 u32 fib_index, int is_del);
2118 dslock (sm, 1 /* release hint */, 6 /* tag */);
2120 p = hash_get (im->fib_index_by_table_id, ntohl(mp->vrf_id));
2123 rv = VNET_API_ERROR_NO_SUCH_FIB;
2129 rv = vnet_proxy_arp_add_del ((ip4_address_t *)mp->low_address,
2130 (ip4_address_t *)mp->hi_address,
2131 fib_index, mp->is_add == 0);
2135 REPLY_MACRO(VL_API_PROXY_ARP_ADD_DEL_REPLY);
2139 vl_api_proxy_arp_intfc_enable_disable_t_handler
2140 (vl_api_proxy_arp_intfc_enable_disable_t *mp)
2143 vnet_main_t * vnm = vnet_get_main();
2144 vl_api_proxy_arp_intfc_enable_disable_reply_t *rmp;
2145 vnet_sw_interface_t * si;
2148 VALIDATE_SW_IF_INDEX(mp);
2150 sw_if_index = ntohl(mp->sw_if_index);
2152 if (pool_is_free_index (vnm->interface_main.sw_interfaces,
2154 rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
2158 si = vnet_get_sw_interface (vnm, sw_if_index);
2162 if (mp->enable_disable)
2163 si->flags |= VNET_SW_INTERFACE_FLAG_PROXY_ARP;
2165 si->flags &= ~VNET_SW_INTERFACE_FLAG_PROXY_ARP;
2167 BAD_SW_IF_INDEX_LABEL;
2170 REPLY_MACRO(VL_API_PROXY_ARP_INTFC_ENABLE_DISABLE_REPLY);
2174 vl_api_ip_neighbor_add_del_t_handler (vl_api_ip_neighbor_add_del_t *mp, vlib_main_t * vm)
2176 vl_api_ip_neighbor_add_del_reply_t * rmp;
2177 vnet_main_t * vnm = vnet_get_main();
2180 stats_main_t * sm = &stats_main;
2182 VALIDATE_SW_IF_INDEX(mp);
2184 dslock (sm, 1 /* release hint */, 7 /* tag */);
2188 rv = vnet_set_ip6_ethernet_neighbor
2189 (vm, ntohl(mp->sw_if_index),
2190 (ip6_address_t *)(mp->dst_address),
2191 mp->mac_address, sizeof (mp->mac_address));
2193 rv = vnet_unset_ip6_ethernet_neighbor
2194 (vm, ntohl(mp->sw_if_index),
2195 (ip6_address_t *)(mp->dst_address),
2196 mp->mac_address, sizeof(mp->mac_address));
2198 ip4_main_t * im = &ip4_main;
2199 ip_lookup_main_t * lm = &im->lookup_main;
2200 ethernet_arp_ip4_over_ethernet_address_t a;
2202 ip_adjacency_t *nh_adj;
2204 uword * p = hash_get (im->fib_index_by_table_id, ntohl(mp->vrf_id));
2206 rv = VNET_API_ERROR_NO_SUCH_FIB;
2212 * Unfortunately, folks have a penchant for
2213 * adding interface addresses to the ARP cache, and
2214 * wondering why the forwarder eventually ASSERTs...
2216 ai = ip4_fib_lookup_with_table
2217 (im, fib_index, (ip4_address_t *)(mp->dst_address),
2218 1 /* disable default route */);
2221 nh_adj = ip_get_adjacency (lm, ai);
2222 /* Never allow manipulation of a local adj! */
2223 if (nh_adj->lookup_next_index == IP_LOOKUP_NEXT_LOCAL) {
2224 clib_warning("%U matches local adj",
2226 (ip4_address_t *)(mp->dst_address));
2227 rv = VNET_API_ERROR_ADDRESS_MATCHES_INTERFACE_ADDRESS;
2232 memcpy (&a.ethernet, mp->mac_address, 6);
2233 memcpy (&a.ip4, mp->dst_address, 4);
2236 rv = vnet_arp_set_ip4_over_ethernet (vnm, ntohl(mp->sw_if_index),
2237 fib_index, &a, mp->is_static);
2239 rv = vnet_arp_unset_ip4_over_ethernet (vnm, ntohl(mp->sw_if_index),
2243 BAD_SW_IF_INDEX_LABEL;
2246 REPLY_MACRO(VL_API_IP_NEIGHBOR_ADD_DEL_REPLY);
2250 vl_api_is_address_reachable_t_handler (vl_api_is_address_reachable_t *mp)
2253 vpe_main_t *rm = &vpe_main;
2254 ip4_main_t *im4 = &ip4_main;
2255 ip6_main_t *im6 = &ip6_main;
2256 ip_lookup_main_t * lm;
2261 u32 adj_index, sw_if_index;
2262 vl_api_is_address_reachable_t *rmp;
2263 ip_adjacency_t * adj;
2264 unix_shared_memory_queue_t *q;
2266 q = vl_api_client_index_to_input_queue (mp->client_index);
2268 increment_missing_api_client_counter (rm->vlib_main);
2272 rmp = vl_msg_api_alloc (sizeof (*rmp));
2273 memcpy (rmp, mp, sizeof (*rmp));
2275 sw_if_index = mp->next_hop_sw_if_index;
2276 memcpy (&addr, mp->address, sizeof (addr));
2278 lm = &im6->lookup_main;
2280 ip6_fib_lookup (im6, sw_if_index, &addr.ip6);
2282 lm = &im4->lookup_main;
2284 ip4_fib_lookup (im4, sw_if_index, &addr.ip4);
2286 if (adj_index == ~0) {
2290 adj = ip_get_adjacency (lm, adj_index);
2292 if (adj->lookup_next_index == IP_LOOKUP_NEXT_REWRITE
2293 && adj->rewrite_header.sw_if_index == sw_if_index) {
2296 if (adj->lookup_next_index == IP_LOOKUP_NEXT_ARP
2297 && adj->rewrite_header.sw_if_index == sw_if_index) {
2299 ip6_probe_neighbor (rm->vlib_main, &addr.ip6, sw_if_index);
2301 ip4_probe_neighbor (rm->vlib_main, &addr.ip4, sw_if_index);
2302 } else if (adj->lookup_next_index == IP_LOOKUP_NEXT_DROP) {
2310 vl_msg_api_send_shmem (q, (u8 *)&rmp);
2314 static void vl_api_sw_interface_details_t_handler (
2315 vl_api_sw_interface_details_t * mp)
2317 clib_warning ("BUG");
2320 static void vl_api_sw_interface_set_flags_t_handler (
2321 vl_api_sw_interface_set_flags_t * mp)
2323 vl_api_sw_interface_set_flags_reply_t *rmp;
2324 vnet_main_t * vnm = vnet_get_main();
2326 clib_error_t * error;
2329 VALIDATE_SW_IF_INDEX(mp);
2331 flags = mp->admin_up_down ? VNET_SW_INTERFACE_FLAG_ADMIN_UP : 0;
2333 error = vnet_sw_interface_set_flags (vnm,
2334 ntohl(mp->sw_if_index),
2338 clib_error_report (error);
2341 BAD_SW_IF_INDEX_LABEL;
2342 REPLY_MACRO(VL_API_SW_INTERFACE_SET_FLAGS_REPLY);
2345 static void send_sw_interface_details (vpe_api_main_t * am,
2346 unix_shared_memory_queue_t *q,
2347 vnet_sw_interface_t * swif,
2348 u8 * interface_name)
2350 vl_api_sw_interface_details_t * mp;
2351 vnet_hw_interface_t * hi;
2353 hi = vnet_get_sup_hw_interface (am->vnet_main, swif->sw_if_index);
2355 mp = vl_msg_api_alloc (sizeof (*mp));
2356 memset (mp, 0, sizeof (*mp));
2357 mp->_vl_msg_id = ntohs(VL_API_SW_INTERFACE_DETAILS);
2358 mp->sw_if_index = ntohl(swif->sw_if_index);
2359 mp->sup_sw_if_index = ntohl(swif->sup_sw_if_index);
2360 mp->admin_up_down = (swif->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ?
2362 mp->link_up_down = (hi->flags & VNET_HW_INTERFACE_FLAG_LINK_UP) ?
2364 mp->link_duplex = ((hi->flags & VNET_HW_INTERFACE_FLAG_DUPLEX_MASK) >>
2365 VNET_HW_INTERFACE_FLAG_DUPLEX_SHIFT);
2366 mp->link_speed = ((hi->flags & VNET_HW_INTERFACE_FLAG_SPEED_MASK) >>
2367 VNET_HW_INTERFACE_FLAG_SPEED_SHIFT);
2369 strncpy ((char *) mp->interface_name,
2370 (char *) interface_name, ARRAY_LEN(mp->interface_name)-1);
2372 /* Send the L2 address for ethernet physical intfcs */
2373 if (swif->sup_sw_if_index == swif->sw_if_index
2374 && hi->hw_class_index == ethernet_hw_interface_class.index) {
2375 ethernet_main_t *em = ethernet_get_main (am->vlib_main);
2376 ethernet_interface_t *ei;
2378 ei = pool_elt_at_index (em->interfaces, hi->hw_instance);
2379 ASSERT (sizeof (mp->l2_address) >= sizeof (ei->address));
2380 memcpy (mp->l2_address, ei->address, sizeof (ei->address));
2381 mp->l2_address_length = ntohl(sizeof (ei->address));
2382 } else if (swif->sup_sw_if_index != swif->sw_if_index) {
2383 vnet_sub_interface_t *sub = &swif->sub;
2384 mp->sub_id = ntohl(sub->id);
2385 mp->sub_dot1ad = sub->eth.flags.dot1ad;
2386 mp->sub_number_of_tags = sub->eth.flags.one_tag + sub->eth.flags.two_tags*2;
2387 mp->sub_outer_vlan_id = ntohs(sub->eth.outer_vlan_id);
2388 mp->sub_inner_vlan_id = ntohs(sub->eth.inner_vlan_id);
2389 mp->sub_exact_match = sub->eth.flags.exact_match;
2390 mp->sub_default = sub->eth.flags.default_sub;
2391 mp->sub_outer_vlan_id_any = sub->eth.flags.outer_vlan_id_any;
2392 mp->sub_inner_vlan_id_any = sub->eth.flags.inner_vlan_id_any;
2394 /* vlan tag rewrite data */
2395 u32 vtr_op = L2_VTR_DISABLED;
2396 u32 vtr_push_dot1q = 0, vtr_tag1 = 0, vtr_tag2 = 0;
2398 if (l2vtr_get(am->vlib_main, am->vnet_main, swif->sw_if_index,
2399 &vtr_op, &vtr_push_dot1q, &vtr_tag1, &vtr_tag2) != 0) {
2400 // error - default to disabled
2401 mp->vtr_op = ntohl(L2_VTR_DISABLED);
2402 clib_warning("cannot get vlan tag rewrite for sw_if_index %d",
2405 mp->vtr_op = ntohl(vtr_op);
2406 mp->vtr_push_dot1q = ntohl(vtr_push_dot1q);
2407 mp->vtr_tag1 = ntohl(vtr_tag1);
2408 mp->vtr_tag2 = ntohl(vtr_tag2);
2412 vl_msg_api_send_shmem (q, (u8 *)&mp);
2415 static void send_sw_interface_flags (vpe_api_main_t * am,
2416 unix_shared_memory_queue_t *q,
2417 vnet_sw_interface_t * swif)
2419 vl_api_sw_interface_set_flags_t *mp;
2420 vnet_main_t * vnm = am->vnet_main;
2422 vnet_hw_interface_t *hi = vnet_get_sup_hw_interface (vnm,
2424 mp = vl_msg_api_alloc (sizeof (*mp));
2425 memset (mp, 0, sizeof (*mp));
2426 mp->_vl_msg_id = ntohs(VL_API_SW_INTERFACE_SET_FLAGS);
2427 mp->sw_if_index = ntohl(swif->sw_if_index);
2429 mp->admin_up_down = (swif->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ?
2431 mp->link_up_down = (hi->flags & VNET_HW_INTERFACE_FLAG_LINK_UP) ?
2433 vl_msg_api_send_shmem (q, (u8 *)&mp);
2436 static void send_sw_interface_flags_deleted (vpe_api_main_t * am,
2437 unix_shared_memory_queue_t *q,
2439 __attribute__((unused));
2441 static void send_sw_interface_flags_deleted (vpe_api_main_t * am,
2442 unix_shared_memory_queue_t *q,
2445 vl_api_sw_interface_set_flags_t *mp;
2447 mp = vl_msg_api_alloc (sizeof (*mp));
2448 memset (mp, 0, sizeof (*mp));
2449 mp->_vl_msg_id = ntohs(VL_API_SW_INTERFACE_SET_FLAGS);
2450 mp->sw_if_index = ntohl(sw_if_index);
2452 mp->admin_up_down = 0;
2453 mp->link_up_down = 0;
2455 vl_msg_api_send_shmem (q, (u8 *)&mp);
2458 static void vl_api_sw_interface_dump_t_handler (
2459 vl_api_sw_interface_dump_t *mp)
2461 vpe_api_main_t * am = &vpe_api_main;
2462 vnet_sw_interface_t * swif;
2463 vnet_interface_main_t * im = &am->vnet_main->interface_main;
2464 u8 * filter_string = 0, * name_string = 0;
2465 unix_shared_memory_queue_t * q;
2466 char * strcasestr (char *, char *); /* lnx hdr file botch */
2468 q = vl_api_client_index_to_input_queue (mp->client_index);
2473 if (mp->name_filter_valid) {
2474 mp->name_filter [ARRAY_LEN(mp->name_filter)-1] = 0;
2475 filter_string = format (0, "%s%c", mp->name_filter, 0);
2478 pool_foreach (swif, im->sw_interfaces,
2480 name_string = format (name_string, "%U%c",
2481 format_vnet_sw_interface_name,
2482 am->vnet_main, swif, 0);
2484 if (mp->name_filter_valid == 0 ||
2485 strcasestr((char *) name_string, (char *) filter_string)) {
2487 send_sw_interface_details (am, q, swif, name_string);
2488 send_sw_interface_flags (am, q, swif);
2490 _vec_len (name_string) = 0;
2493 vec_free (name_string);
2494 vec_free (filter_string);
2497 void send_oam_event (oam_target_t * t)
2499 vpe_api_main_t * vam = &vpe_api_main;
2500 unix_shared_memory_queue_t * q;
2501 vpe_client_registration_t *reg;
2502 vl_api_oam_event_t * mp;
2504 pool_foreach(reg, vam->oam_events_registrations,
2506 q = vl_api_client_index_to_input_queue (reg->client_index);
2508 mp = vl_msg_api_alloc (sizeof (*mp));
2509 mp->_vl_msg_id = ntohs (VL_API_OAM_EVENT);
2510 memcpy (mp->dst_address, &t->dst_address, sizeof (mp->dst_address));
2511 mp->state = t->state;
2512 vl_msg_api_send_shmem (q, (u8 *)&mp);
2518 vl_api_oam_add_del_t_handler (vl_api_oam_add_del_t *mp)
2520 vl_api_oam_add_del_reply_t * rmp;
2523 rv = vpe_oam_add_del_target ((ip4_address_t *)mp->src_address,
2524 (ip4_address_t *)mp->dst_address,
2528 REPLY_MACRO(VL_API_OAM_ADD_DEL_REPLY);
2532 vl_api_vnet_get_summary_stats_t_handler (
2533 vl_api_vnet_get_summary_stats_t *mp)
2535 stats_main_t * sm = &stats_main;
2536 vnet_interface_main_t * im = sm->interface_main;
2537 vl_api_vnet_summary_stats_reply_t *rmp;
2538 vlib_combined_counter_main_t * cm;
2541 u64 total_pkts[VLIB_N_RX_TX];
2542 u64 total_bytes[VLIB_N_RX_TX];
2544 unix_shared_memory_queue_t * q =
2545 vl_api_client_index_to_input_queue (mp->client_index);
2550 rmp = vl_msg_api_alloc (sizeof (*rmp));
2551 rmp->_vl_msg_id = ntohs(VL_API_VNET_SUMMARY_STATS_REPLY);
2552 rmp->context = mp->context;
2555 memset (total_pkts, 0, sizeof (total_pkts));
2556 memset (total_bytes, 0, sizeof (total_bytes));
2558 vnet_interface_counter_lock (im);
2560 vec_foreach (cm, im->combined_sw_if_counters) {
2561 which = cm - im->combined_sw_if_counters;
2563 for (i = 0; i < vec_len (cm->maxi); i++) {
2564 vlib_get_combined_counter (cm, i, &v);
2565 total_pkts[which] += v.packets;
2566 total_bytes[which] += v.bytes;
2569 vnet_interface_counter_unlock (im);
2571 /* Note: in HOST byte order! */
2572 rmp->total_pkts[VLIB_RX] = total_pkts[VLIB_RX];
2573 rmp->total_bytes[VLIB_RX] = total_bytes[VLIB_RX];
2574 rmp->total_pkts[VLIB_TX] = total_pkts[VLIB_TX];
2575 rmp->total_bytes[VLIB_TX] = total_bytes[VLIB_TX];
2576 rmp->vector_rate = vlib_last_vector_length_per_node (sm->vlib_main);
2578 vl_msg_api_send_shmem (q, (u8 *)&rmp);
2581 typedef CLIB_PACKED (struct {
2582 ip4_address_t address;
2584 u32 address_length : 6;
2589 static int ip4_reset_fib_t_handler (vl_api_reset_fib_t *mp)
2591 vnet_main_t * vnm = vnet_get_main();
2592 vnet_interface_main_t * im = &vnm->interface_main;
2593 ip4_main_t * im4 = &ip4_main;
2594 static ip4_route_t * routes;
2595 static u32 * sw_if_indices_to_shut;
2596 stats_main_t * sm = &stats_main;
2601 int rv = VNET_API_ERROR_NO_SUCH_FIB;
2602 u32 target_fib_id = ntohl(mp->vrf_id);
2604 dslock (sm, 1 /* release hint */, 8 /* tag */);
2606 vec_foreach (fib, im4->fibs) {
2607 vnet_sw_interface_t * si;
2609 if (fib->table_id != target_fib_id)
2612 /* remove any mpls/gre tunnels in this fib */
2613 vnet_mpls_gre_delete_fib_tunnels (fib->table_id);
2615 /* remove any mpls encap/decap labels */
2616 mpls_fib_reset_labels (fib->table_id);
2618 /* remove any proxy arps in this fib */
2619 vnet_proxy_arp_fib_reset (fib->table_id);
2621 /* Set the flow hash for this fib to the default */
2622 vnet_set_ip4_flow_hash (fib->table_id, IP_FLOW_HASH_DEFAULT);
2624 vec_reset_length (sw_if_indices_to_shut);
2626 /* Shut down interfaces in this FIB / clean out intfc routes */
2627 pool_foreach (si, im->sw_interfaces,
2629 u32 sw_if_index = si->sw_if_index;
2631 if (sw_if_index < vec_len (im4->fib_index_by_sw_if_index)
2632 && (im4->fib_index_by_sw_if_index[si->sw_if_index] ==
2634 vec_add1 (sw_if_indices_to_shut, si->sw_if_index);
2637 for (i = 0; i < vec_len (sw_if_indices_to_shut); i++) {
2638 sw_if_index = sw_if_indices_to_shut[i];
2639 // vec_foreach (sw_if_index, sw_if_indices_to_shut) {
2641 u32 flags = vnet_sw_interface_get_flags (vnm, sw_if_index);
2642 flags &= ~(VNET_SW_INTERFACE_FLAG_ADMIN_UP);
2643 vnet_sw_interface_set_flags (vnm, sw_if_index, flags);
2646 vec_reset_length (routes);
2648 for (i = 0; i < ARRAY_LEN (fib->adj_index_by_dst_address); i++) {
2649 uword * hash = fib->adj_index_by_dst_address[i];
2653 x.address_length = i;
2655 hash_foreach_pair (p, hash,
2657 x.address.data_u32 = p->key;
2658 vec_add1 (routes, x);
2662 vec_foreach (r, routes) {
2663 ip4_add_del_route_args_t a;
2665 memset (&a, 0, sizeof (a));
2666 a.flags = IP4_ROUTE_FLAG_FIB_INDEX | IP4_ROUTE_FLAG_DEL;
2667 a.table_index_or_table_id = fib - im4->fibs;
2668 a.dst_address = r->address;
2669 a.dst_address_length = r->address_length;
2672 ip4_add_del_route (im4, &a);
2673 ip4_maybe_remap_adjacencies (im4, fib - im4->fibs,
2674 IP4_ROUTE_FLAG_FIB_INDEX);
2678 } /* vec_foreach (fib) */
2685 ip6_address_t address;
2692 ip6_route_t ** routep;
2693 } add_routes_in_fib_arg_t;
2695 static void add_routes_in_fib (clib_bihash_kv_24_8_t * kvp, void *arg)
2697 add_routes_in_fib_arg_t * ap = arg;
2699 if (kvp->key[2]>>32 == ap->fib_index)
2701 ip6_address_t *addr;
2703 addr = (ip6_address_t *) kvp;
2704 vec_add2 (*ap->routep, r, 1);
2705 r->address = addr[0];
2706 r->address_length = kvp->key[2] & 0xFF;
2707 r->index = kvp->value;
2711 static int ip6_reset_fib_t_handler (vl_api_reset_fib_t *mp)
2713 vnet_main_t * vnm = vnet_get_main();
2714 vnet_interface_main_t * im = &vnm->interface_main;
2715 ip6_main_t * im6 = &ip6_main;
2716 stats_main_t * sm = &stats_main;
2717 static ip6_route_t * routes;
2718 static u32 * sw_if_indices_to_shut;
2723 int rv = VNET_API_ERROR_NO_SUCH_FIB;
2724 u32 target_fib_id = ntohl(mp->vrf_id);
2725 add_routes_in_fib_arg_t _a, *a=&_a;
2726 clib_bihash_24_8_t * h = &im6->ip6_lookup_table;
2728 dslock (sm, 1 /* release hint */, 9 /* tag */);
2730 vec_foreach (fib, im6->fibs) {
2731 vnet_sw_interface_t * si;
2733 if (fib->table_id != target_fib_id)
2736 vec_reset_length (sw_if_indices_to_shut);
2738 /* Shut down interfaces in this FIB / clean out intfc routes */
2739 pool_foreach (si, im->sw_interfaces,
2741 if (im6->fib_index_by_sw_if_index[si->sw_if_index] ==
2743 vec_add1 (sw_if_indices_to_shut, si->sw_if_index);
2746 for (i = 0; i < vec_len (sw_if_indices_to_shut); i++) {
2747 sw_if_index = sw_if_indices_to_shut[i];
2748 // vec_foreach (sw_if_index, sw_if_indices_to_shut) {
2750 u32 flags = vnet_sw_interface_get_flags (vnm, sw_if_index);
2751 flags &= ~(VNET_SW_INTERFACE_FLAG_ADMIN_UP);
2752 vnet_sw_interface_set_flags (vnm, sw_if_index, flags);
2755 vec_reset_length (routes);
2757 a->fib_index = fib - im6->fibs;
2758 a->routep = &routes;
2760 clib_bihash_foreach_key_value_pair_24_8 (h, add_routes_in_fib, a);
2762 vec_foreach (r, routes) {
2763 ip6_add_del_route_args_t a;
2765 memset (&a, 0, sizeof (a));
2766 a.flags = IP6_ROUTE_FLAG_FIB_INDEX | IP6_ROUTE_FLAG_DEL;
2767 a.table_index_or_table_id = fib - im6->fibs;
2768 a.dst_address = r->address;
2769 a.dst_address_length = r->address_length;
2772 ip6_add_del_route (im6, &a);
2773 ip6_maybe_remap_adjacencies (im6, fib - im6->fibs,
2774 IP6_ROUTE_FLAG_FIB_INDEX);
2777 /* Reinstall the neighbor / router discovery routes */
2778 vnet_ip6_fib_init (im6, fib - im6->fibs);
2780 } /* vec_foreach (fib) */
2786 static void vl_api_reset_fib_t_handler (vl_api_reset_fib_t *mp)
2789 vl_api_reset_fib_reply_t * rmp;
2792 rv = ip6_reset_fib_t_handler (mp);
2794 rv = ip4_reset_fib_t_handler (mp);
2796 REPLY_MACRO(VL_API_RESET_FIB_REPLY);
2801 dhcpv4_proxy_config (vl_api_dhcp_proxy_config_t *mp)
2803 vl_api_dhcp_proxy_config_reply_t * rmp;
2806 rv = dhcp_proxy_set_server ((ip4_address_t *)(&mp->dhcp_server),
2807 (ip4_address_t *)(&mp->dhcp_src_address),
2808 (u32) ntohl(mp->vrf_id),
2809 (int) mp->insert_circuit_id,
2810 (int) (mp->is_add == 0));
2812 REPLY_MACRO(VL_API_DHCP_PROXY_CONFIG_REPLY);
2817 dhcpv6_proxy_config (vl_api_dhcp_proxy_config_t *mp)
2819 vl_api_dhcp_proxy_config_reply_t * rmp;
2822 rv = dhcpv6_proxy_set_server ((ip6_address_t *)(&mp->dhcp_server),
2823 (ip6_address_t *)(&mp->dhcp_src_address),
2824 (u32) ntohl(mp->vrf_id),
2825 (int) mp->insert_circuit_id,
2826 (int) (mp->is_add == 0));
2828 REPLY_MACRO(VL_API_DHCP_PROXY_CONFIG_REPLY);
2832 dhcpv4_proxy_config_2 (vl_api_dhcp_proxy_config_2_t *mp)
2834 vl_api_dhcp_proxy_config_reply_t * rmp;
2837 rv = dhcp_proxy_set_server_2 ((ip4_address_t *)(&mp->dhcp_server),
2838 (ip4_address_t *)(&mp->dhcp_src_address),
2839 (u32) ntohl(mp->rx_vrf_id),
2840 (u32) ntohl(mp->server_vrf_id),
2841 (int) mp->insert_circuit_id,
2842 (int) (mp->is_add == 0));
2844 REPLY_MACRO(VL_API_DHCP_PROXY_CONFIG_2_REPLY);
2849 dhcpv6_proxy_config_2 (vl_api_dhcp_proxy_config_2_t *mp)
2851 vl_api_dhcp_proxy_config_reply_t * rmp;
2855 rv = dhcpv6_proxy_set_server_2 ((ip6_address_t *)(&mp->dhcp_server),
2856 (ip6_address_t *)(&mp->dhcp_src_address),
2857 (u32) ntohl(mp->rx_vrf_id),
2858 (u32) ntohl(mp->server_vrf_id),
2859 (int) mp->insert_circuit_id,
2860 (int) (mp->is_add == 0));
2862 rv = VNET_API_ERROR_UNIMPLEMENTED;
2865 REPLY_MACRO(VL_API_DHCP_PROXY_CONFIG_2_REPLY);
2870 vl_api_dhcp_proxy_set_vss_t_handler (vl_api_dhcp_proxy_set_vss_t *mp)
2872 vl_api_dhcp_proxy_set_vss_reply_t *rmp;
2875 rv = dhcp_proxy_set_option82_vss(ntohl(mp->tbl_id),
2878 (int)mp->is_add == 0);
2880 rv = dhcpv6_proxy_set_vss( ntohl(mp->tbl_id),
2883 (int)mp->is_add == 0);
2885 REPLY_MACRO(VL_API_DHCP_PROXY_SET_VSS_REPLY);
2889 static void vl_api_dhcp_proxy_config_t_handler
2890 (vl_api_dhcp_proxy_config_t *mp)
2892 if (mp->is_ipv6 == 0)
2893 dhcpv4_proxy_config (mp);
2895 dhcpv6_proxy_config (mp);
2898 static void vl_api_dhcp_proxy_config_2_t_handler
2899 (vl_api_dhcp_proxy_config_2_t *mp)
2901 if (mp->is_ipv6 == 0)
2902 dhcpv4_proxy_config_2 (mp);
2904 dhcpv6_proxy_config_2 (mp);
2907 void dhcp_compl_event_callback (u32 client_index, u32 pid, u8 * hostname,
2908 u8 is_ipv6, u8 * host_address, u8 * router_address, u8 * host_mac)
2910 unix_shared_memory_queue_t * q;
2911 vl_api_dhcp_compl_event_t * mp;
2913 q = vl_api_client_index_to_input_queue (client_index);
2917 mp = vl_msg_api_alloc (sizeof (*mp));
2918 mp->client_index = client_index;
2920 mp->is_ipv6 = is_ipv6;
2921 memcpy (&mp->hostname, hostname, vec_len(hostname));
2922 mp->hostname[vec_len(hostname) + 1] = '\n';
2923 memcpy (&mp->host_address[0], host_address, 16);
2924 memcpy (&mp->router_address[0], router_address, 16);
2925 memcpy (&mp->host_mac[0], host_mac, 6);
2927 mp->_vl_msg_id = ntohs (VL_API_DHCP_COMPL_EVENT);
2929 vl_msg_api_send_shmem (q, (u8 *)&mp);
2932 static void vl_api_dhcp_client_config_t_handler
2933 (vl_api_dhcp_client_config_t *mp)
2935 vlib_main_t *vm = vlib_get_main();
2936 vl_api_dhcp_client_config_reply_t * rmp;
2939 VALIDATE_SW_IF_INDEX(mp);
2941 rv = dhcp_client_config(vm, ntohl(mp->sw_if_index),
2942 mp->hostname, mp->is_add, mp->client_index,
2943 mp->want_dhcp_event ? dhcp_compl_event_callback : NULL,
2946 BAD_SW_IF_INDEX_LABEL;
2948 REPLY_MACRO(VL_API_DHCP_CLIENT_CONFIG_REPLY);
2952 vl_api_sw_interface_ip6nd_ra_config_t_handler
2953 (vl_api_sw_interface_ip6nd_ra_config_t *mp, vlib_main_t *vm)
2955 vl_api_sw_interface_ip6nd_ra_config_reply_t * rmp;
2957 u8 is_no, surpress, managed, other, ll_option, send_unicast, cease, default_router;
2959 is_no = mp->is_no == 1;
2960 surpress = mp->surpress == 1;
2961 managed = mp->managed == 1;
2962 other = mp->other == 1;
2963 ll_option = mp->ll_option == 1;
2964 send_unicast = mp->send_unicast == 1;
2965 cease = mp->cease == 1;
2966 default_router = mp->default_router == 1;
2968 VALIDATE_SW_IF_INDEX(mp);
2970 rv = ip6_neighbor_ra_config(vm, ntohl(mp->sw_if_index),
2971 surpress, managed, other,
2972 ll_option, send_unicast, cease,
2973 default_router, ntohl (mp->lifetime),
2974 ntohl(mp->initial_count), ntohl(mp->initial_interval),
2975 ntohl(mp->max_interval), ntohl( mp->min_interval),
2978 BAD_SW_IF_INDEX_LABEL;
2980 REPLY_MACRO(VL_API_SW_INTERFACE_IP6ND_RA_CONFIG_REPLY);
2984 vl_api_sw_interface_ip6nd_ra_prefix_t_handler
2985 (vl_api_sw_interface_ip6nd_ra_prefix_t *mp, vlib_main_t *vm)
2987 vl_api_sw_interface_ip6nd_ra_prefix_reply_t * rmp;
2989 u8 is_no, use_default, no_advertise, off_link, no_autoconfig, no_onlink;
2991 VALIDATE_SW_IF_INDEX(mp);
2993 is_no = mp->is_no == 1;
2994 use_default = mp->use_default == 1;
2995 no_advertise = mp->no_advertise == 1;
2996 off_link = mp->off_link == 1;
2997 no_autoconfig = mp->no_autoconfig == 1;
2998 no_onlink = mp->no_onlink == 1;
3000 rv = ip6_neighbor_ra_prefix(vm, ntohl(mp->sw_if_index),
3001 (ip6_address_t *)mp->address, mp->address_length,
3002 use_default, ntohl(mp->val_lifetime), ntohl(mp->pref_lifetime),
3003 no_advertise, off_link, no_autoconfig, no_onlink,
3006 BAD_SW_IF_INDEX_LABEL;
3007 REPLY_MACRO(VL_API_SW_INTERFACE_IP6ND_RA_PREFIX_REPLY);
3011 vl_api_sw_interface_ip6_enable_disable_t_handler
3012 (vl_api_sw_interface_ip6_enable_disable_t *mp, vlib_main_t *vm)
3014 vl_api_sw_interface_ip6_enable_disable_reply_t * rmp;
3015 vnet_main_t * vnm = vnet_get_main();
3017 clib_error_t * error;
3021 VALIDATE_SW_IF_INDEX(mp);
3023 error = ( mp->enable == 1) ? enable_ip6_interface(vm,ntohl(mp->sw_if_index)) :
3024 disable_ip6_interface(vm,ntohl(mp->sw_if_index));
3027 clib_error_report(error);
3028 rv = VNET_API_ERROR_UNSPECIFIED;
3030 rv = vnm->api_errno;
3033 BAD_SW_IF_INDEX_LABEL;
3035 REPLY_MACRO(VL_API_SW_INTERFACE_IP6_ENABLE_DISABLE_REPLY);
3039 vl_api_sw_interface_ip6_set_link_local_address_t_handler
3040 (vl_api_sw_interface_ip6_set_link_local_address_t *mp, vlib_main_t *vm)
3042 vl_api_sw_interface_ip6_set_link_local_address_reply_t * rmp;
3044 clib_error_t * error;
3045 vnet_main_t * vnm = vnet_get_main();
3049 VALIDATE_SW_IF_INDEX(mp);
3051 error = set_ip6_link_local_address(vm,
3052 ntohl(mp->sw_if_index),
3053 (ip6_address_t *)mp->address,
3054 mp->address_length);
3056 clib_error_report(error);
3057 rv = VNET_API_ERROR_UNSPECIFIED;
3059 rv = vnm->api_errno;
3062 BAD_SW_IF_INDEX_LABEL;
3064 REPLY_MACRO(VL_API_SW_INTERFACE_IP6_SET_LINK_LOCAL_ADDRESS_REPLY);
3067 static void set_ip6_flow_hash (vl_api_set_ip_flow_hash_t *mp)
3069 vl_api_set_ip_flow_hash_reply_t *rmp;
3070 int rv = VNET_API_ERROR_UNIMPLEMENTED;
3072 clib_warning ("unimplemented...");
3074 REPLY_MACRO(VL_API_SET_IP_FLOW_HASH_REPLY);
3077 static void set_ip4_flow_hash (vl_api_set_ip_flow_hash_t *mp)
3079 vl_api_set_ip_flow_hash_reply_t *rmp;
3082 u32 flow_hash_config = 0;
3084 table_id = ntohl(mp->vrf_id);
3086 #define _(a,b) if (mp->a) flow_hash_config |= b;
3087 foreach_flow_hash_bit;
3090 rv = vnet_set_ip4_flow_hash (table_id, flow_hash_config);
3092 REPLY_MACRO(VL_API_SET_IP_FLOW_HASH_REPLY);
3096 static void vl_api_set_ip_flow_hash_t_handler
3097 (vl_api_set_ip_flow_hash_t *mp)
3099 if (mp->is_ipv6 == 0)
3100 set_ip4_flow_hash (mp);
3102 set_ip6_flow_hash (mp);
3105 static void vl_api_sw_interface_set_unnumbered_t_handler
3106 (vl_api_sw_interface_set_unnumbered_t *mp)
3108 vl_api_sw_interface_set_unnumbered_reply_t * rmp;
3110 vnet_sw_interface_t * si;
3111 vnet_main_t *vnm = vnet_get_main();
3112 u32 sw_if_index, unnumbered_sw_if_index;
3114 sw_if_index = ntohl(mp->sw_if_index);
3115 unnumbered_sw_if_index = ntohl(mp->unnumbered_sw_if_index);
3118 * The API message field names are backwards from
3119 * the underlying data structure names.
3120 * It's not worth changing them now.
3122 if (pool_is_free_index (vnm->interface_main.sw_interfaces,
3123 unnumbered_sw_if_index)) {
3124 rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
3128 /* Only check the "use loop0" field when setting the binding */
3130 pool_is_free_index (vnm->interface_main.sw_interfaces, sw_if_index)) {
3131 rv = VNET_API_ERROR_INVALID_SW_IF_INDEX_2;
3135 si = vnet_get_sw_interface (vnm, unnumbered_sw_if_index);
3138 si->flags |= VNET_SW_INTERFACE_FLAG_UNNUMBERED;
3139 si->unnumbered_sw_if_index = sw_if_index;
3141 si->flags &= ~(VNET_SW_INTERFACE_FLAG_UNNUMBERED);
3142 si->unnumbered_sw_if_index = (u32)~0;
3146 REPLY_MACRO(VL_API_SW_INTERFACE_SET_UNNUMBERED_REPLY);
3149 static void vl_api_create_loopback_t_handler
3150 (vl_api_create_loopback_t *mp)
3152 vl_api_create_loopback_reply_t * rmp;
3156 rv = vnet_create_loopback_interface (&sw_if_index, mp->mac_address);
3158 REPLY_MACRO2(VL_API_CREATE_LOOPBACK_REPLY,
3160 rmp->sw_if_index = ntohl (sw_if_index);
3164 static void vl_api_delete_loopback_t_handler
3165 (vl_api_delete_loopback_t *mp)
3167 vl_api_delete_loopback_reply_t * rmp;
3171 sw_if_index = ntohl (mp->sw_if_index);
3172 rv = vnet_delete_loopback_interface (sw_if_index);
3174 REPLY_MACRO(VL_API_DELETE_LOOPBACK_REPLY);
3177 static void vl_api_control_ping_t_handler
3178 (vl_api_control_ping_t *mp)
3180 vl_api_control_ping_reply_t * rmp;
3183 REPLY_MACRO2(VL_API_CONTROL_PING_REPLY,
3185 rmp->vpe_pid = ntohl (getpid());
3189 static void shmem_cli_output (uword arg, u8 * buffer, uword buffer_bytes)
3191 u8 **shmem_vecp = (u8 **)arg;
3194 api_main_t * am = &api_main;
3197 shmem_vec = *shmem_vecp;
3199 offset = vec_len (shmem_vec);
3201 pthread_mutex_lock (&am->vlib_rp->mutex);
3202 oldheap = svm_push_data_heap (am->vlib_rp);
3204 vec_validate (shmem_vec, offset + buffer_bytes - 1);
3206 memcpy (shmem_vec + offset, buffer, buffer_bytes);
3208 svm_pop_heap (oldheap);
3209 pthread_mutex_unlock (&am->vlib_rp->mutex);
3211 *shmem_vecp = shmem_vec;
3215 static void vl_api_cli_request_t_handler
3216 (vl_api_cli_request_t *mp)
3218 vl_api_cli_reply_t *rp;
3219 unix_shared_memory_queue_t *q;
3220 vlib_main_t * vm = vlib_get_main();
3221 api_main_t * am = &api_main;
3222 unformat_input_t input;
3226 q = vl_api_client_index_to_input_queue (mp->client_index);
3230 rp = vl_msg_api_alloc (sizeof (*rp));
3231 rp->_vl_msg_id = ntohs(VL_API_CLI_REPLY);
3232 rp->context = mp->context;
3234 unformat_init_vector (&input, (u8 *)mp->cmd_in_shmem);
3236 vlib_cli_input (vm, &input, shmem_cli_output,
3239 pthread_mutex_lock (&am->vlib_rp->mutex);
3240 oldheap = svm_push_data_heap (am->vlib_rp);
3242 vec_add1(shmem_vec, 0);
3244 svm_pop_heap (oldheap);
3245 pthread_mutex_unlock (&am->vlib_rp->mutex);
3247 rp->reply_in_shmem = (uword)shmem_vec;
3249 vl_msg_api_send_shmem (q, (u8 *)&rp);
3252 static void vl_api_set_arp_neighbor_limit_t_handler (vl_api_set_arp_neighbor_limit_t *mp)
3255 vl_api_set_arp_neighbor_limit_reply_t * rmp;
3256 vnet_main_t *vnm = vnet_get_main();
3257 clib_error_t * error;
3262 error = ip6_set_neighbor_limit (ntohl(mp->arp_neighbor_limit));
3264 error = ip4_set_arp_limit (ntohl(mp->arp_neighbor_limit));
3267 clib_error_report(error);
3268 rv = VNET_API_ERROR_UNSPECIFIED;
3270 rv = vnm->api_errno;
3273 REPLY_MACRO(VL_API_SET_ARP_NEIGHBOR_LIMIT_REPLY);
3276 static void vl_api_sr_tunnel_add_del_t_handler
3277 (vl_api_sr_tunnel_add_del_t *mp)
3279 ip6_sr_add_del_tunnel_args_t _a, *a=&_a;
3281 vl_api_sr_tunnel_add_del_reply_t * rmp;
3282 ip6_address_t * segments = 0, * seg;
3283 ip6_address_t * tags = 0, *tag;
3284 ip6_address_t * this_address;
3287 if (mp->n_segments == 0) {
3292 memset (a, 0, sizeof (*a));
3293 a->src_address = (ip6_address_t *)&mp->src_address;
3294 a->dst_address = (ip6_address_t *)&mp->dst_address;
3295 a->dst_mask_width = mp->dst_mask_width;
3296 a->flags_net_byte_order = mp->flags_net_byte_order;
3297 a->is_del = (mp->is_add == 0);
3298 a->rx_table_id = ntohl(mp->outer_vrf_id);
3299 a->tx_table_id = ntohl(mp->inner_vrf_id);
3301 /* Yank segments and tags out of the API message */
3302 this_address = (ip6_address_t *)mp->segs_and_tags;
3303 for (i = 0; i < mp->n_segments; i++) {
3304 vec_add2 (segments, seg, 1);
3305 memcpy (seg->as_u8, this_address->as_u8, sizeof (*this_address));
3308 for (i = 0; i < mp->n_tags; i++) {
3309 vec_add2 (tags, tag, 1);
3310 memcpy (tag->as_u8, this_address->as_u8, sizeof (*this_address));
3314 a->segments = segments;
3317 rv = ip6_sr_add_del_tunnel (a);
3321 REPLY_MACRO(VL_API_SR_TUNNEL_ADD_DEL_REPLY);
3324 #define foreach_classify_add_del_table_field \
3329 _(match_n_vectors) \
3330 _(next_table_index) \
3333 static void vl_api_classify_add_del_table_t_handler
3334 (vl_api_classify_add_del_table_t * mp)
3336 vl_api_classify_add_del_table_reply_t * rmp;
3337 vnet_classify_main_t * cm = &vnet_classify_main;
3338 vnet_classify_table_t * t;
3342 foreach_classify_add_del_table_field;
3345 #define _(a) a = ntohl(mp->a);
3346 foreach_classify_add_del_table_field;
3349 /* The underlying API fails silently, on purpose, so check here */
3350 if (mp->is_add == 0)
3351 if (pool_is_free_index (cm->tables, table_index)) {
3352 rv = VNET_API_ERROR_NO_SUCH_TABLE;
3356 rv = vnet_classify_add_del_table
3357 (cm, mp->mask, nbuckets, memory_size,
3358 skip_n_vectors, match_n_vectors,
3359 next_table_index, miss_next_index,
3360 &table_index, mp->is_add);
3363 REPLY_MACRO2(VL_API_CLASSIFY_ADD_DEL_TABLE_REPLY,
3365 if (rv == 0 && mp->is_add) {
3366 t = pool_elt_at_index (cm->tables, table_index);
3367 rmp->skip_n_vectors = ntohl(t->skip_n_vectors);
3368 rmp->match_n_vectors = ntohl(t->match_n_vectors);
3369 rmp->new_table_index = ntohl(table_index);
3371 rmp->skip_n_vectors = ~0;
3372 rmp->match_n_vectors = ~0;
3373 rmp->new_table_index = ~0;
3378 static void vl_api_classify_add_del_session_t_handler
3379 (vl_api_classify_add_del_session_t * mp)
3381 vnet_classify_main_t * cm = &vnet_classify_main;
3382 vl_api_classify_add_del_session_reply_t * rmp;
3384 u32 table_index, hit_next_index, opaque_index;
3387 table_index = ntohl (mp->table_index);
3388 hit_next_index = ntohl (mp->hit_next_index);
3389 opaque_index = ntohl (mp->opaque_index);
3390 advance = ntohl (mp->advance);
3392 rv = vnet_classify_add_del_session
3393 (cm, table_index, mp->match, hit_next_index, opaque_index,
3394 advance, mp->is_add);
3396 REPLY_MACRO(VL_API_CLASSIFY_ADD_DEL_SESSION_REPLY);
3399 static void vl_api_classify_set_interface_ip_table_t_handler
3400 (vl_api_classify_set_interface_ip_table_t * mp)
3402 vlib_main_t * vm = vlib_get_main();
3403 vl_api_classify_set_interface_ip_table_reply_t * rmp;
3405 u32 table_index, sw_if_index;
3407 table_index = ntohl (mp->table_index);
3408 sw_if_index = ntohl (mp->sw_if_index);
3410 VALIDATE_SW_IF_INDEX(mp);
3413 rv = vnet_set_ip6_classify_intfc (vm, sw_if_index, table_index);
3415 rv = vnet_set_ip4_classify_intfc (vm, sw_if_index, table_index);
3417 BAD_SW_IF_INDEX_LABEL;
3419 REPLY_MACRO(VL_API_CLASSIFY_SET_INTERFACE_IP_TABLE_REPLY);
3422 static void vl_api_classify_set_interface_l2_tables_t_handler
3423 (vl_api_classify_set_interface_l2_tables_t * mp)
3425 vl_api_classify_set_interface_l2_tables_reply_t * rmp;
3427 u32 sw_if_index, ip4_table_index, ip6_table_index, other_table_index;
3430 ip4_table_index = ntohl(mp->ip4_table_index);
3431 ip6_table_index = ntohl(mp->ip6_table_index);
3432 other_table_index = ntohl(mp->other_table_index);
3433 sw_if_index = ntohl(mp->sw_if_index);
3435 VALIDATE_SW_IF_INDEX(mp);
3437 rv = vnet_l2_classify_set_tables (sw_if_index, ip4_table_index,
3438 ip6_table_index, other_table_index);
3441 if (ip4_table_index != ~0 || ip6_table_index != ~0
3442 || other_table_index != ~0)
3447 vnet_l2_classify_enable_disable (sw_if_index, enable);
3450 BAD_SW_IF_INDEX_LABEL;
3452 REPLY_MACRO(VL_API_CLASSIFY_SET_INTERFACE_L2_TABLES_REPLY);
3456 vl_api_l2_fib_clear_table_t_handler (vl_api_l2_fib_clear_table_t *mp)
3459 vl_api_l2_fib_clear_table_reply_t * rmp;
3461 /* DAW-FIXME: This API should only clear non-static l2fib entries, but
3462 * that is not currently implemented. When that TODO is fixed
3463 * this call should be changed to pass 1 instead of 0.
3465 l2fib_clear_table (0);
3467 REPLY_MACRO(VL_API_L2_FIB_CLEAR_TABLE_REPLY);
3470 extern void l2_efp_filter_configure(vnet_main_t * vnet_main,
3475 vl_api_l2_interface_efp_filter_t_handler (vl_api_l2_interface_efp_filter_t *mp)
3478 vl_api_l2_interface_efp_filter_reply_t * rmp;
3479 vnet_main_t *vnm = vnet_get_main();
3481 // enable/disable the feature
3482 l2_efp_filter_configure (vnm, mp->sw_if_index, mp->enable_disable);
3483 rv = vnm->api_errno;
3485 REPLY_MACRO(VL_API_L2_INTERFACE_EFP_FILTER_REPLY);
3489 vl_api_l2_interface_vlan_tag_rewrite_t_handler (vl_api_l2_interface_vlan_tag_rewrite_t *mp)
3492 vl_api_l2_interface_vlan_tag_rewrite_reply_t * rmp;
3493 vnet_main_t * vnm = vnet_get_main();
3494 vlib_main_t * vm = vlib_get_main();
3497 VALIDATE_SW_IF_INDEX(mp);
3499 vtr_op = ntohl(mp->vtr_op);
3501 /* The L2 code is unsuspicious */
3503 case L2_VTR_DISABLED:
3508 case L2_VTR_TRANSLATE_1_1:
3509 case L2_VTR_TRANSLATE_1_2:
3510 case L2_VTR_TRANSLATE_2_1:
3511 case L2_VTR_TRANSLATE_2_2:
3515 rv = VNET_API_ERROR_INVALID_VALUE;
3516 goto bad_sw_if_index;
3519 rv = l2vtr_configure (vm, vnm, ntohl(mp->sw_if_index), vtr_op,
3520 ntohl(mp->push_dot1q), ntohl(mp->tag1),
3523 BAD_SW_IF_INDEX_LABEL;
3525 REPLY_MACRO(VL_API_L2_INTERFACE_VLAN_TAG_REWRITE_REPLY);
3529 vl_api_create_vhost_user_if_t_handler (vl_api_create_vhost_user_if_t *mp)
3533 vl_api_create_vhost_user_if_reply_t * rmp;
3534 u32 sw_if_index = (u32)~0;
3536 vnet_main_t * vnm = vnet_get_main();
3537 vlib_main_t * vm = vlib_get_main();
3539 rv = dpdk_vhost_user_create_if(vnm, vm, (char *)mp->sock_filename,
3540 mp->is_server, &sw_if_index, (u64)~0,
3541 mp->renumber, ntohl(mp->custom_dev_instance));
3543 REPLY_MACRO2(VL_API_CREATE_VHOST_USER_IF_REPLY,
3545 rmp->sw_if_index = ntohl (sw_if_index);
3551 vl_api_modify_vhost_user_if_t_handler (vl_api_modify_vhost_user_if_t *mp)
3555 vl_api_modify_vhost_user_if_reply_t * rmp;
3556 u32 sw_if_index = ntohl(mp->sw_if_index);
3558 vnet_main_t * vnm = vnet_get_main();
3559 vlib_main_t * vm = vlib_get_main();
3561 rv = dpdk_vhost_user_modify_if(vnm, vm, (char *)mp->sock_filename,
3562 mp->is_server, sw_if_index, (u64)~0,
3563 mp->renumber, ntohl(mp->custom_dev_instance));
3565 REPLY_MACRO(VL_API_MODIFY_VHOST_USER_IF_REPLY);
3570 vl_api_delete_vhost_user_if_t_handler (vl_api_delete_vhost_user_if_t *mp)
3574 vpe_api_main_t * vam = &vpe_api_main;
3575 vl_api_delete_vhost_user_if_reply_t * rmp;
3576 u32 sw_if_index = ntohl(mp->sw_if_index);
3578 vnet_main_t * vnm = vnet_get_main();
3579 vlib_main_t * vm = vlib_get_main();
3581 rv = dpdk_vhost_user_delete_if(vnm, vm, sw_if_index);
3583 REPLY_MACRO(VL_API_DELETE_VHOST_USER_IF_REPLY);
3585 unix_shared_memory_queue_t * q =
3586 vl_api_client_index_to_input_queue (mp->client_index);
3590 send_sw_interface_flags_deleted (vam, q, sw_if_index);
3595 static void vl_api_sw_interface_vhost_user_details_t_handler (
3596 vl_api_sw_interface_vhost_user_details_t * mp)
3598 clib_warning ("BUG");
3602 static void send_sw_interface_vhost_user_details (vpe_api_main_t * am,
3603 unix_shared_memory_queue_t *q,
3604 vhost_user_intf_details_t * vui)
3606 vl_api_sw_interface_vhost_user_details_t * mp;
3608 mp = vl_msg_api_alloc (sizeof (*mp));
3609 memset (mp, 0, sizeof (*mp));
3610 mp->_vl_msg_id = ntohs(VL_API_SW_INTERFACE_VHOST_USER_DETAILS);
3611 mp->sw_if_index = ntohl(vui->sw_if_index);
3612 mp->virtio_net_hdr_sz = ntohl (vui->virtio_net_hdr_sz);
3613 mp->features = clib_net_to_host_u64 (vui->features);
3614 mp->is_server = vui->is_server;
3615 mp->num_regions = ntohl(vui->num_regions);
3616 mp->sock_errno = ntohl(vui->sock_errno);
3618 strncpy ((char *) mp->sock_filename,
3619 (char *) vui->sock_filename, ARRAY_LEN(mp->sock_filename)-1);
3620 strncpy ((char *) mp->interface_name,
3621 (char *) vui->if_name, ARRAY_LEN(mp->interface_name)-1);
3623 vl_msg_api_send_shmem (q, (u8 *)&mp);
3628 vl_api_sw_interface_vhost_user_dump_t_handler (
3629 vl_api_sw_interface_vhost_user_dump_t *mp)
3633 vpe_api_main_t * am = &vpe_api_main;
3634 vnet_main_t * vnm = vnet_get_main();
3635 vlib_main_t * vm = vlib_get_main();
3636 vhost_user_intf_details_t *ifaces = NULL;
3637 vhost_user_intf_details_t *vuid = NULL;
3638 unix_shared_memory_queue_t * q;
3640 q = vl_api_client_index_to_input_queue (mp->client_index);
3644 rv = dpdk_vhost_user_dump_ifs(vnm, vm, &ifaces);
3648 vec_foreach (vuid, ifaces) {
3649 send_sw_interface_vhost_user_details (am, q, vuid);
3655 static void send_sw_if_l2tpv3_tunnel_details (vpe_api_main_t * am,
3656 unix_shared_memory_queue_t *q,
3660 vl_api_sw_if_l2tpv3_tunnel_details_t * mp;
3661 u8 * if_name = NULL;
3662 vnet_sw_interface_t * si = NULL;
3664 si = vnet_get_hw_sw_interface (lm->vnet_main, s->hw_if_index);
3666 if_name = format(if_name, "%U",
3667 format_vnet_sw_interface_name, lm->vnet_main, si);
3669 mp = vl_msg_api_alloc (sizeof (*mp));
3670 memset (mp, 0, sizeof (*mp));
3671 mp->_vl_msg_id = ntohs(VL_API_SW_IF_L2TPV3_TUNNEL_DETAILS);
3672 strncpy((char *)mp->interface_name,
3673 (char *)if_name, ARRAY_LEN(mp->interface_name)-1);
3674 mp->sw_if_index = ntohl(si->sw_if_index);
3675 mp->local_session_id = s->local_session_id;
3676 mp->remote_session_id = s->remote_session_id;
3677 mp->local_cookie[0] = s->local_cookie[0];
3678 mp->local_cookie[1] = s->local_cookie[1];
3679 mp->remote_cookie = s->remote_cookie;
3680 memcpy(mp->client_address, &s->client_address, sizeof(s->client_address));
3681 memcpy(mp->our_address, &s->our_address, sizeof(s->our_address));
3682 mp->l2_sublayer_present = s->l2_sublayer_present;
3684 vl_msg_api_send_shmem (q, (u8 *)&mp);
3687 static void send_ip_address_details (vpe_api_main_t * am,
3688 unix_shared_memory_queue_t * q,
3693 vl_api_ip_address_details_t * mp;
3695 mp = vl_msg_api_alloc (sizeof (*mp));
3696 memset (mp, 0, sizeof (*mp));
3697 mp->_vl_msg_id = ntohs(VL_API_IP_ADDRESS_DETAILS);
3700 memcpy(&mp->ip, ip, sizeof(mp->ip));
3702 u32 * tp = (u32 *)mp->ip;
3703 *tp = ntohl(*(u32*)ip);
3705 mp->prefix_length = prefix_length;
3707 vl_msg_api_send_shmem (q, (u8 *)&mp);
3711 vl_api_ip_address_dump_t_handler (vl_api_ip_address_dump_t *mp)
3713 vpe_api_main_t * am = &vpe_api_main;
3714 unix_shared_memory_queue_t * q;
3717 ip6_main_t * im6 = &ip6_main;
3718 ip4_main_t * im4 = &ip4_main;
3719 ip_lookup_main_t * lm6 = &im6->lookup_main;
3720 ip_lookup_main_t * lm4 = &im4->lookup_main;
3721 ip_interface_address_t * ia = 0;
3722 u32 sw_if_index = ~0;
3724 sw_if_index = ntohl(mp->sw_if_index);
3726 q = vl_api_client_index_to_input_queue (mp->client_index);
3732 foreach_ip_interface_address (lm6, ia, sw_if_index,
3733 1 /* honor unnumbered */,
3735 r6 = ip_interface_address_get_address (lm6, ia);
3736 u16 prefix_length = ia->address_length;
3737 send_ip_address_details(am, q, (u8*)r6, prefix_length, 1);
3740 foreach_ip_interface_address (lm4, ia, sw_if_index,
3741 1 /* honor unnumbered */,
3743 r4 = ip_interface_address_get_address (lm4, ia);
3744 u16 prefix_length = ia->address_length;
3745 send_ip_address_details(am, q, (u8*)r4, prefix_length, 0);
3750 static void send_ip_details (vpe_api_main_t * am,
3751 unix_shared_memory_queue_t *q,
3754 vl_api_ip_details_t * mp;
3756 mp = vl_msg_api_alloc (sizeof (*mp));
3757 memset (mp, 0, sizeof (*mp));
3758 mp->_vl_msg_id = ntohs(VL_API_IP_DETAILS);
3760 mp->sw_if_index = ntohl(sw_if_index);
3762 vl_msg_api_send_shmem (q, (u8 *)&mp);
3766 vl_api_sw_if_l2tpv3_tunnel_dump_t_handler (
3767 vl_api_sw_if_l2tpv3_tunnel_dump_t *mp)
3769 vpe_api_main_t * am = &vpe_api_main;
3770 l2t_main_t * lm = &l2t_main;
3771 unix_shared_memory_queue_t * q;
3772 l2t_session_t *session;
3774 q = vl_api_client_index_to_input_queue (mp->client_index);
3778 pool_foreach (session, lm->sessions,
3780 send_sw_if_l2tpv3_tunnel_details (am, q, session, lm);
3785 static void send_sw_interface_tap_details (vpe_api_main_t * am,
3786 unix_shared_memory_queue_t *q,
3787 tapcli_interface_details_t *tap_if)
3789 vl_api_sw_interface_tap_details_t * mp;
3790 mp = vl_msg_api_alloc (sizeof (*mp));
3791 memset (mp, 0, sizeof (*mp));
3792 mp->_vl_msg_id = ntohs(VL_API_SW_INTERFACE_TAP_DETAILS);
3793 mp->sw_if_index = ntohl(tap_if->sw_if_index);
3794 strncpy((char *)mp->dev_name,
3795 (char *)tap_if->dev_name, ARRAY_LEN(mp->dev_name)-1);
3797 vl_msg_api_send_shmem (q, (u8 *)&mp);
3801 vl_api_sw_interface_tap_dump_t_handler (
3802 vl_api_sw_interface_tap_dump_t *mp)
3805 vpe_api_main_t * am = &vpe_api_main;
3806 unix_shared_memory_queue_t * q;
3807 tapcli_interface_details_t *tapifs = NULL;
3808 tapcli_interface_details_t *tap_if = NULL;
3810 q = vl_api_client_index_to_input_queue (mp->client_index);
3814 rv = vnet_tap_dump_ifs(&tapifs);
3818 vec_foreach(tap_if, tapifs) {
3819 send_sw_interface_tap_details(am, q, tap_if);
3826 vl_api_ip_dump_t_handler (vl_api_ip_dump_t *mp)
3828 vpe_api_main_t * am = &vpe_api_main;
3829 vnet_main_t * vnm = vnet_get_main();
3830 vlib_main_t * vm = vlib_get_main();
3831 vnet_interface_main_t * im = &vnm->interface_main;
3832 unix_shared_memory_queue_t * q;
3833 vnet_sw_interface_t * si, * sorted_sis;
3834 u32 sw_if_index = ~0;
3836 q = vl_api_client_index_to_input_queue (mp->client_index);
3841 /* Gather interfaces. */
3842 sorted_sis = vec_new (vnet_sw_interface_t, pool_elts (im->sw_interfaces));
3843 _vec_len (sorted_sis) = 0;
3844 pool_foreach (si, im->sw_interfaces, ({ vec_add1 (sorted_sis, si[0]); }));
3846 vec_foreach (si, sorted_sis) {
3847 if (!(si->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED)) {
3848 if (mp->is_ipv6 && !ip6_interface_enabled(vm, si->sw_if_index)) {
3851 sw_if_index = si->sw_if_index;
3852 send_ip_details(am, q, sw_if_index);
3857 static void vl_api_l2_fib_table_entry_t_handler (
3858 vl_api_l2_fib_table_entry_t * mp)
3860 clib_warning ("BUG");
3863 static void send_l2fib_table_entry (vpe_api_main_t * am,
3864 unix_shared_memory_queue_t *q,
3865 l2fib_entry_key_t * l2fe_key,
3866 l2fib_entry_result_t * l2fe_res)
3868 vl_api_l2_fib_table_entry_t * mp;
3870 mp = vl_msg_api_alloc (sizeof (*mp));
3871 memset (mp, 0, sizeof (*mp));
3872 mp->_vl_msg_id = ntohs(VL_API_L2_FIB_TABLE_ENTRY);
3874 mp->bd_id = ntohl(l2input_main.bd_configs[l2fe_key->fields.bd_index].bd_id);
3876 mp->mac = l2fib_make_key (l2fe_key->fields.mac, 0);
3877 mp->sw_if_index = ntohl(l2fe_res->fields.sw_if_index);
3878 mp->static_mac = l2fe_res->fields.static_mac;
3879 mp->filter_mac = l2fe_res->fields.filter;
3880 mp->bvi_mac = l2fe_res->fields.bvi;
3882 vl_msg_api_send_shmem (q, (u8 *)&mp);
3886 vl_api_l2_fib_table_dump_t_handler (vl_api_l2_fib_table_dump_t *mp)
3888 vpe_api_main_t * am = &vpe_api_main;
3889 bd_main_t * bdm = &bd_main;
3890 l2fib_entry_key_t *l2fe_key = NULL;
3891 l2fib_entry_result_t *l2fe_res = NULL;
3892 u32 ni, bd_id = ntohl (mp->bd_id);
3894 unix_shared_memory_queue_t * q;
3897 q = vl_api_client_index_to_input_queue (mp->client_index);
3901 /* see l2fib_table_dump: ~0 means "any" */
3905 p = hash_get (bdm->bd_index_by_bd_id, bd_id);
3912 l2fib_table_dump (bd_index, &l2fe_key, &l2fe_res);
3914 vec_foreach_index (ni, l2fe_key) {
3915 send_l2fib_table_entry (am, q, vec_elt_at_index(l2fe_key, ni),
3916 vec_elt_at_index(l2fe_res, ni));
3923 vl_api_show_version_t_handler (vl_api_show_version_t *mp)
3925 vl_api_show_version_reply_t *rmp;
3927 char * vpe_api_get_build_directory(void);
3928 char * vpe_api_get_version(void);
3929 char * vpe_api_get_build_date(void);
3931 unix_shared_memory_queue_t * q =
3932 vl_api_client_index_to_input_queue (mp->client_index);
3937 REPLY_MACRO2(VL_API_SHOW_VERSION_REPLY,
3939 strncpy ((char *) rmp->program, "vpe", ARRAY_LEN(rmp->program)-1);
3940 strncpy ((char *) rmp->build_directory, vpe_api_get_build_directory(),
3941 ARRAY_LEN(rmp->build_directory)-1);
3942 strncpy ((char *) rmp->version, vpe_api_get_version(),
3943 ARRAY_LEN(rmp->version)-1);
3944 strncpy ((char *) rmp->build_date, vpe_api_get_build_date(),
3945 ARRAY_LEN(rmp->build_date)-1);
3949 static void vl_api_get_node_index_t_handler
3950 (vl_api_get_node_index_t * mp)
3952 vlib_main_t * vm = vlib_get_main();
3953 vl_api_get_node_index_reply_t * rmp;
3956 u32 node_index = ~0;
3958 n = vlib_get_node_by_name (vm, mp->node_name);
3961 rv = VNET_API_ERROR_NO_SUCH_NODE;
3963 node_index = n->index;
3965 REPLY_MACRO2(VL_API_GET_NODE_INDEX_REPLY,
3967 rmp->node_index = ntohl(node_index);
3971 static void vl_api_add_node_next_t_handler
3972 (vl_api_add_node_next_t * mp)
3974 vlib_main_t * vm = vlib_get_main();
3975 vl_api_add_node_next_reply_t * rmp;
3976 vlib_node_t * n, * next;
3978 u32 next_index = ~0;
3980 n = vlib_get_node_by_name (vm, mp->node_name);
3983 rv = VNET_API_ERROR_NO_SUCH_NODE;
3987 next = vlib_get_node_by_name (vm, mp->next_name);
3990 rv = VNET_API_ERROR_NO_SUCH_NODE2;
3992 next_index = vlib_node_add_next (vm, n->index, next->index);
3995 REPLY_MACRO2(VL_API_GET_NODE_INDEX_REPLY,
3997 rmp->next_index = ntohl(next_index);
4001 static void vl_api_l2tpv3_create_tunnel_t_handler
4002 (vl_api_l2tpv3_create_tunnel_t *mp)
4004 vl_api_l2tpv3_create_tunnel_reply_t * rmp;
4005 l2t_main_t *lm = &l2t_main;
4006 u32 sw_if_index = (u32)~0;
4009 if (mp->is_ipv6 != 1) {
4010 rv = VNET_API_ERROR_UNIMPLEMENTED;
4014 rv = create_l2tpv3_ipv6_tunnel (lm,
4015 (ip6_address_t *) mp->client_address,
4016 (ip6_address_t *) mp->our_address,
4017 ntohl(mp->local_session_id),
4018 ntohl(mp->remote_session_id),
4019 clib_net_to_host_u64(mp->local_cookie),
4020 clib_net_to_host_u64(mp->remote_cookie),
4021 mp->l2_sublayer_present,
4025 REPLY_MACRO2(VL_API_L2TPV3_CREATE_TUNNEL_REPLY,
4027 rmp->sw_if_index = ntohl (sw_if_index);
4031 static void vl_api_l2tpv3_set_tunnel_cookies_t_handler
4032 (vl_api_l2tpv3_set_tunnel_cookies_t *mp)
4034 vl_api_l2tpv3_set_tunnel_cookies_reply_t * rmp;
4035 l2t_main_t *lm = &l2t_main;
4038 VALIDATE_SW_IF_INDEX(mp);
4040 rv = l2tpv3_set_tunnel_cookies (lm, ntohl(mp->sw_if_index),
4041 clib_net_to_host_u64(mp->new_local_cookie),
4042 clib_net_to_host_u64(mp->new_remote_cookie));
4044 BAD_SW_IF_INDEX_LABEL;
4046 REPLY_MACRO (VL_API_L2TPV3_SET_TUNNEL_COOKIES_REPLY);
4049 static void vl_api_l2tpv3_interface_enable_disable_t_handler
4050 (vl_api_l2tpv3_interface_enable_disable_t * mp)
4053 vnet_main_t * vnm = vnet_get_main();
4054 vl_api_l2tpv3_interface_enable_disable_reply_t * rmp;
4056 VALIDATE_SW_IF_INDEX(mp);
4058 rv = l2tpv3_interface_enable_disable
4059 (vnm, ntohl(mp->sw_if_index), mp->enable_disable);
4061 BAD_SW_IF_INDEX_LABEL;
4063 REPLY_MACRO (VL_API_L2TPV3_INTERFACE_ENABLE_DISABLE_REPLY);
4066 static void vl_api_l2tpv3_set_lookup_key_t_handler
4067 (vl_api_l2tpv3_set_lookup_key_t * mp)
4070 l2t_main_t *lm = &l2t_main;
4071 vl_api_l2tpv3_set_lookup_key_reply_t * rmp;
4073 if (mp->key > L2T_LOOKUP_SESSION_ID) {
4074 rv = VNET_API_ERROR_INVALID_VALUE;
4078 lm->lookup_type = mp->key;
4081 REPLY_MACRO (VL_API_L2TPV3_SET_LOOKUP_KEY_REPLY);
4084 static void vl_api_vxlan_add_del_tunnel_t_handler
4085 (vl_api_vxlan_add_del_tunnel_t * mp)
4087 vl_api_vxlan_add_del_tunnel_reply_t * rmp;
4089 vnet_vxlan_add_del_tunnel_args_t _a, *a = &_a;
4090 u32 encap_fib_index;
4092 ip4_main_t * im = &ip4_main;
4093 u32 sw_if_index = ~0;
4095 p = hash_get (im->fib_index_by_table_id, ntohl(mp->encap_vrf_id));
4097 rv = VNET_API_ERROR_NO_SUCH_FIB;
4100 encap_fib_index = p[0];
4102 memset (a, 0, sizeof (*a));
4104 a->is_add = mp->is_add;
4106 /* ip addresses sent in network byte order */
4107 a->src.as_u32 = mp->src_address;
4108 a->dst.as_u32 = mp->dst_address;
4110 a->encap_fib_index = encap_fib_index;
4111 a->decap_next_index = ntohl(mp->decap_next_index);
4112 a->vni = ntohl(mp->vni);
4113 rv = vnet_vxlan_add_del_tunnel (a, &sw_if_index);
4116 REPLY_MACRO2(VL_API_VXLAN_ADD_DEL_TUNNEL_REPLY,
4118 rmp->sw_if_index = ntohl (sw_if_index);
4122 static void send_vxlan_tunnel_details
4123 (vxlan_tunnel_t * t, unix_shared_memory_queue_t * q)
4125 vl_api_vxlan_tunnel_details_t * rmp;
4126 ip4_main_t * im = &ip4_main;
4128 rmp = vl_msg_api_alloc (sizeof (*rmp));
4129 memset (rmp, 0, sizeof (*rmp));
4130 rmp->_vl_msg_id = ntohs(VL_API_VXLAN_TUNNEL_DETAILS);
4131 rmp->src_address = t->src.data_u32;
4132 rmp->dst_address = t->dst.data_u32;
4133 rmp->encap_vrf_id = htonl(im->fibs[t->encap_fib_index].table_id);
4134 rmp->vni = htonl(t->vni);
4135 rmp->decap_next_index = htonl(t->decap_next_index);
4136 rmp->sw_if_index = htonl(t->sw_if_index);
4138 vl_msg_api_send_shmem (q, (u8 *)&rmp);
4141 static void vl_api_vxlan_tunnel_dump_t_handler
4142 (vl_api_vxlan_tunnel_dump_t * mp)
4144 unix_shared_memory_queue_t * q;
4145 vxlan_main_t * vxm = &vxlan_main;
4149 q = vl_api_client_index_to_input_queue (mp->client_index);
4154 sw_if_index = ntohl(mp->sw_if_index);
4156 if (~0 == sw_if_index) {
4157 pool_foreach (t, vxm->tunnels,
4159 send_vxlan_tunnel_details(t, q);
4162 if ((sw_if_index >= vec_len(vxm->tunnel_index_by_sw_if_index)) ||
4163 (~0 == vxm->tunnel_index_by_sw_if_index[sw_if_index])) {
4166 t = &vxm->tunnels[vxm->tunnel_index_by_sw_if_index[sw_if_index]];
4167 send_vxlan_tunnel_details(t, q);
4172 vl_api_l2_patch_add_del_t_handler (vl_api_l2_patch_add_del_t *mp)
4174 extern int vnet_l2_patch_add_del (u32 rx_sw_if_index, u32 tx_sw_if_index,
4176 vl_api_l2_patch_add_del_reply_t * rmp;
4177 int vnet_l2_patch_add_del (u32 rx_sw_if_index, u32 tx_sw_if_index,
4181 VALIDATE_RX_SW_IF_INDEX(mp);
4182 VALIDATE_TX_SW_IF_INDEX(mp);
4184 rv = vnet_l2_patch_add_del (ntohl(mp->rx_sw_if_index),
4185 ntohl(mp->tx_sw_if_index),
4186 (int)(mp->is_add != 0));
4188 BAD_RX_SW_IF_INDEX_LABEL;
4189 BAD_TX_SW_IF_INDEX_LABEL;
4191 REPLY_MACRO(VL_API_L2_PATCH_ADD_DEL_REPLY);
4195 vl_api_nsh_gre_add_del_tunnel_t_handler
4196 (vl_api_nsh_gre_add_del_tunnel_t * mp)
4198 vl_api_nsh_gre_add_del_tunnel_reply_t * rmp;
4200 vnet_nsh_gre_add_del_tunnel_args_t _a, *a = &_a;
4201 u32 encap_fib_index, decap_fib_index;
4202 u32 decap_next_index;
4204 ip4_main_t * im = &ip4_main;
4206 u32 sw_if_index = ~0;
4209 p = hash_get (im->fib_index_by_table_id, ntohl(mp->encap_vrf_id));
4211 rv = VNET_API_ERROR_NO_SUCH_FIB;
4214 encap_fib_index = p[0];
4216 decap_next_index = ntohl(mp->decap_next_index);
4218 /* Interpret decap_vrf_id as an opaque if sending to other-than-ip4-input */
4219 if (decap_next_index == NSH_INPUT_NEXT_IP4_INPUT) {
4220 p = hash_get (im->fib_index_by_table_id, ntohl(mp->decap_vrf_id));
4222 rv = VNET_API_ERROR_NO_SUCH_INNER_FIB;
4225 decap_fib_index = p[0];
4227 decap_fib_index = ntohl(mp->decap_vrf_id);
4230 memset (a, 0, sizeof (*a));
4232 a->is_add = mp->is_add;
4233 /* ip addresses sent in network byte order */
4234 a->src.as_u32 = ntohl(mp->src);
4235 a->dst.as_u32 = ntohl(mp->dst);
4236 a->encap_fib_index = encap_fib_index;
4237 a->decap_fib_index = decap_fib_index;
4238 a->decap_next_index = decap_next_index;
4239 a->ver_o_c = mp->ver_o_c;
4240 a->length = mp->length;
4241 a->md_type = mp->md_type;
4242 a->next_protocol = mp->next_protocol;
4243 a->spi_si = ntohl(mp->spi_si);
4244 a->c1 = ntohl(mp->c1);
4245 a->c2 = ntohl(mp->c2);
4246 a->c3 = ntohl(mp->c3);
4247 a->c4 = ntohl(mp->c4);
4249 for (i = 0; i < mp->tlv_len_in_words; i++)
4250 vec_add1 (tlvs, ntohl(mp->tlvs[i]));
4254 rv = vnet_nsh_gre_add_del_tunnel (a, &sw_if_index);
4257 REPLY_MACRO2(VL_API_NSH_GRE_ADD_DEL_TUNNEL_REPLY,
4259 rmp->sw_if_index = ntohl (sw_if_index);
4264 vl_api_nsh_vxlan_gpe_add_del_tunnel_t_handler
4265 (vl_api_nsh_vxlan_gpe_add_del_tunnel_t * mp)
4267 vl_api_nsh_vxlan_gpe_add_del_tunnel_reply_t * rmp;
4269 vnet_nsh_vxlan_gpe_add_del_tunnel_args_t _a, *a = &_a;
4270 u32 encap_fib_index, decap_fib_index;
4271 u32 decap_next_index;
4273 ip4_main_t * im = &ip4_main;
4275 u32 sw_if_index = ~0;
4278 p = hash_get (im->fib_index_by_table_id, ntohl(mp->encap_vrf_id));
4280 rv = VNET_API_ERROR_NO_SUCH_FIB;
4283 encap_fib_index = p[0];
4285 decap_next_index = ntohl(mp->decap_next_index);
4287 /* Interpret decap_vrf_id as an opaque if sending to other-than-ip4-input */
4288 if (decap_next_index == NSH_INPUT_NEXT_IP4_INPUT) {
4289 p = hash_get (im->fib_index_by_table_id, ntohl(mp->decap_vrf_id));
4291 rv = VNET_API_ERROR_NO_SUCH_INNER_FIB;
4294 decap_fib_index = p[0];
4296 decap_fib_index = ntohl(mp->decap_vrf_id);
4299 memset (a, 0, sizeof (*a));
4301 a->is_add = mp->is_add;
4302 /* ip addresses sent in network byte order */
4303 a->src.as_u32 = ntohl(mp->src);
4304 a->dst.as_u32 = ntohl(mp->dst);
4305 a->encap_fib_index = encap_fib_index;
4306 a->decap_fib_index = decap_fib_index;
4307 a->decap_next_index = decap_next_index;
4308 a->vni = ntohl(mp->vni);
4309 a->ver_o_c = mp->ver_o_c;
4310 a->length = mp->length;
4311 a->md_type = mp->md_type;
4312 a->next_protocol = mp->next_protocol;
4313 a->spi_si = ntohl(mp->spi_si);
4314 a->c1 = ntohl(mp->c1);
4315 a->c2 = ntohl(mp->c2);
4316 a->c3 = ntohl(mp->c3);
4317 a->c4 = ntohl(mp->c4);
4319 for (i = 0; i < mp->tlv_len_in_words; i++)
4320 vec_add1 (tlvs, ntohl(mp->tlvs[i]));
4324 rv = vnet_nsh_vxlan_gpe_add_del_tunnel (a, &sw_if_index);
4327 REPLY_MACRO2(VL_API_NSH_VXLAN_GPE_ADD_DEL_TUNNEL_REPLY,
4329 rmp->sw_if_index = ntohl (sw_if_index);
4334 vl_api_lisp_gpe_add_del_tunnel_t_handler
4335 (vl_api_lisp_gpe_add_del_tunnel_t * mp)
4337 vl_api_lisp_gpe_add_del_tunnel_reply_t * rmp;
4339 vnet_lisp_gpe_add_del_tunnel_args_t _a, *a = &_a;
4340 u32 encap_fib_index, decap_fib_index;
4341 u32 decap_next_index;
4343 ip4_main_t * im = &ip4_main;
4344 u32 sw_if_index = ~0;
4346 p = hash_get (im->fib_index_by_table_id, ntohl(mp->encap_vrf_id));
4348 rv = VNET_API_ERROR_NO_SUCH_FIB;
4351 encap_fib_index = p[0];
4353 decap_next_index = ntohl(mp->decap_next_index);
4355 /* Interpret decap_vrf_id as an opaque if sending to other-than-ip4-input */
4356 if (decap_next_index == NSH_INPUT_NEXT_IP4_INPUT) {
4357 p = hash_get (im->fib_index_by_table_id, ntohl(mp->decap_vrf_id));
4359 rv = VNET_API_ERROR_NO_SUCH_INNER_FIB;
4362 decap_fib_index = p[0];
4364 decap_fib_index = ntohl(mp->decap_vrf_id);
4367 memset (a, 0, sizeof (*a));
4369 a->is_add = mp->is_add;
4370 /* ip addresses sent in network byte order */
4371 a->src.as_u32 = mp->src;
4372 a->dst.as_u32 = mp->dst;
4373 a->encap_fib_index = encap_fib_index;
4374 a->decap_fib_index = decap_fib_index;
4375 a->decap_next_index = decap_next_index;
4376 a->flags = mp->flags;
4377 a->ver_res = mp->ver_res;
4379 a->next_protocol = mp->next_protocol;
4380 a->iid = clib_net_to_host_u32 (mp->iid);
4382 rv = vnet_lisp_gpe_add_del_tunnel (a, &sw_if_index);
4385 REPLY_MACRO2(VL_API_LISP_GPE_ADD_DEL_TUNNEL_REPLY,
4387 rmp->sw_if_index = ntohl (sw_if_index);
4392 vl_api_interface_name_renumber_t_handler (vl_api_interface_name_renumber_t *mp)
4394 vl_api_interface_name_renumber_reply_t * rmp;
4397 VALIDATE_SW_IF_INDEX(mp);
4399 rv = vnet_interface_name_renumber
4400 (ntohl(mp->sw_if_index), ntohl(mp->new_show_dev_instance));
4402 BAD_SW_IF_INDEX_LABEL;
4404 REPLY_MACRO(VL_API_INTERFACE_NAME_RENUMBER_REPLY);
4407 static int arp_change_data_callback (u32 pool_index, u8 * new_mac,
4408 u32 sw_if_index, u32 address)
4410 vpe_api_main_t * am = &vpe_api_main;
4411 vlib_main_t * vm = am->vlib_main;
4412 vl_api_ip4_arp_event_t * event;
4413 static f64 arp_event_last_time;
4414 f64 now = vlib_time_now (vm);
4416 if (pool_is_free_index (am->arp_events, pool_index))
4419 event = pool_elt_at_index (am->arp_events, pool_index);
4420 if (memcmp (&event->new_mac, new_mac, sizeof (event->new_mac))) {
4421 memcpy (event->new_mac, new_mac, sizeof(event->new_mac));
4422 } else { /* same mac */
4423 if ((sw_if_index == event->sw_if_index) &&
4425 /* for BD case, also check IP address with 10 sec timeout */
4426 ((address == event->address) &&
4427 ((now - arp_event_last_time) < 10.0))))
4431 arp_event_last_time = now;
4432 event->sw_if_index = sw_if_index;
4433 if (address) event->address = address;
4437 static int arp_change_delete_callback (u32 pool_index, u8 * notused)
4439 vpe_api_main_t * am = &vpe_api_main;
4441 if (pool_is_free_index (am->arp_events, pool_index))
4444 pool_put_index (am->arp_events, pool_index);
4449 vl_api_want_ip4_arp_events_t_handler
4450 (vl_api_want_ip4_arp_events_t * mp)
4452 vpe_api_main_t * am = &vpe_api_main;
4453 vnet_main_t * vnm = vnet_get_main();
4454 vl_api_want_ip4_arp_events_reply_t *rmp;
4455 vl_api_ip4_arp_event_t * event;
4458 if (mp->enable_disable) {
4459 pool_get (am->arp_events, event);
4460 memset (event, 0, sizeof (*event));
4462 event->_vl_msg_id = ntohs(VL_API_IP4_ARP_EVENT);
4463 event->client_index = mp->client_index;
4464 event->context = mp->context;
4465 event->address = mp->address;
4466 event->pid = mp->pid;
4468 rv = vnet_add_del_ip4_arp_change_event
4469 (vnm, arp_change_data_callback,
4471 &mp->address /* addr, in net byte order */,
4472 vpe_resolver_process_node.index,
4473 IP4_ARP_EVENT, event - am->arp_events, 1 /* is_add */);
4475 rv = vnet_add_del_ip4_arp_change_event
4476 (vnm, arp_change_delete_callback,
4478 &mp->address /* addr, in net byte order */,
4479 vpe_resolver_process_node.index,
4480 IP4_ARP_EVENT, ~0 /* pool index */, 0 /* is_add */);
4482 REPLY_MACRO(VL_API_WANT_IP4_ARP_EVENTS_REPLY);
4485 static void vl_api_input_acl_set_interface_t_handler
4486 (vl_api_input_acl_set_interface_t * mp)
4488 vlib_main_t *vm = vlib_get_main();
4489 vl_api_input_acl_set_interface_reply_t * rmp;
4491 u32 sw_if_index, ip4_table_index, ip6_table_index, l2_table_index;
4493 ip4_table_index = ntohl(mp->ip4_table_index);
4494 ip6_table_index = ntohl(mp->ip6_table_index);
4495 l2_table_index = ntohl(mp->l2_table_index);
4496 sw_if_index = ntohl(mp->sw_if_index);
4498 VALIDATE_SW_IF_INDEX(mp);
4500 rv = vnet_set_input_acl_intfc (vm, sw_if_index, ip4_table_index,
4501 ip6_table_index, l2_table_index,
4504 BAD_SW_IF_INDEX_LABEL;
4506 REPLY_MACRO(VL_API_INPUT_ACL_SET_INTERFACE_REPLY);
4509 static void vl_api_ipsec_spd_add_del_t_handler
4510 (vl_api_ipsec_spd_add_del_t * mp)
4512 vlib_main_t *vm __attribute__((unused)) = vlib_get_main();
4513 vl_api_ipsec_spd_add_del_reply_t * rmp;
4517 rv = ipsec_add_del_spd (vm, ntohl(mp->spd_id), mp->is_add);
4519 rv = VNET_API_ERROR_UNIMPLEMENTED;
4522 REPLY_MACRO(VL_API_IPSEC_SPD_ADD_DEL_REPLY);
4525 static void vl_api_ipsec_interface_add_del_spd_t_handler
4526 (vl_api_ipsec_interface_add_del_spd_t * mp)
4528 vlib_main_t *vm __attribute__((unused)) = vlib_get_main();
4529 vl_api_ipsec_interface_add_del_spd_reply_t * rmp;
4531 u32 sw_if_index __attribute__((unused));
4532 u32 spd_id __attribute__((unused));
4534 sw_if_index = ntohl(mp->sw_if_index);
4535 spd_id = ntohl(mp->spd_id);
4537 VALIDATE_SW_IF_INDEX(mp);
4540 rv = ipsec_set_interface_spd(vm, sw_if_index, spd_id, mp->is_add);
4542 rv = VNET_API_ERROR_UNIMPLEMENTED;
4545 BAD_SW_IF_INDEX_LABEL;
4547 REPLY_MACRO(VL_API_IPSEC_INTERFACE_ADD_DEL_SPD_REPLY);
4550 static void vl_api_ipsec_spd_add_del_entry_t_handler
4551 (vl_api_ipsec_spd_add_del_entry_t * mp)
4553 vlib_main_t *vm __attribute__((unused)) = vlib_get_main();
4554 vl_api_ipsec_spd_add_del_entry_reply_t * rmp;
4560 p.id = ntohl(mp->spd_id);
4561 p.priority = ntohl(mp->priority);
4562 p.is_outbound = mp->is_outbound;
4563 p.is_ipv6 = mp->is_ipv6;
4565 memcpy(&p.raddr.start, mp->remote_address_start, 16);
4566 memcpy(&p.raddr.stop, mp->remote_address_stop, 16);
4567 memcpy(&p.laddr.start, mp->local_address_start, 16);
4568 memcpy(&p.laddr.stop, mp->local_address_stop, 16);
4570 p.protocol = mp->protocol;
4571 p.rport.start = ntohs(mp->remote_port_start);
4572 p.rport.stop = ntohs(mp->remote_port_stop);
4573 p.lport.start = ntohs(mp->local_port_start);
4574 p.lport.stop = ntohs(mp->local_port_stop);
4575 /* policy action resolve unsupported */
4576 if (mp->policy == IPSEC_POLICY_ACTION_RESOLVE) {
4577 clib_warning("unsupported action: 'resolve'");
4578 rv = VNET_API_ERROR_UNIMPLEMENTED;
4581 p.policy = mp->policy;
4582 p.sa_id = ntohl(mp->sa_id);
4584 rv = ipsec_add_del_policy(vm, &p, mp->is_add);
4588 if (mp->is_ip_any) {
4590 rv = ipsec_add_del_policy(vm, &p, mp->is_add);
4593 rv = VNET_API_ERROR_UNIMPLEMENTED;
4598 REPLY_MACRO(VL_API_IPSEC_SPD_ADD_DEL_ENTRY_REPLY);
4601 static void vl_api_ipsec_sad_add_del_entry_t_handler
4602 (vl_api_ipsec_sad_add_del_entry_t * mp)
4604 vlib_main_t *vm __attribute__((unused)) = vlib_get_main();
4605 vl_api_ipsec_sad_add_del_entry_reply_t * rmp;
4610 sa.id = ntohl(mp->sad_id);
4611 sa.spi = ntohl(mp->spi);
4612 /* security protocol AH unsupported */
4613 if (mp->protocol == IPSEC_PROTOCOL_AH) {
4614 clib_warning("unsupported security protocol 'AH'");
4615 rv = VNET_API_ERROR_UNIMPLEMENTED;
4618 sa.protocol = mp->protocol;
4619 /* check for unsupported crypto-alg */
4620 if (mp->crypto_algorithm < IPSEC_CRYPTO_ALG_AES_CBC_128 ||
4621 mp->crypto_algorithm > IPSEC_CRYPTO_ALG_AES_CBC_256) {
4622 clib_warning("unsupported crypto-alg: '%U'", format_ipsec_crypto_alg,
4623 mp->crypto_algorithm);
4624 rv = VNET_API_ERROR_UNIMPLEMENTED;
4627 sa.crypto_alg = mp->crypto_algorithm;
4628 sa.crypto_key_len = mp->crypto_key_length;
4629 memcpy(&sa.crypto_key, mp->crypto_key, sizeof(sa.crypto_key));
4630 /* check for unsupported integ-alg */
4631 if (mp->integrity_algorithm < IPSEC_INTEG_ALG_SHA1_96 ||
4632 mp->integrity_algorithm > IPSEC_INTEG_ALG_SHA_512_256) {
4633 clib_warning("unsupported integ-alg: '%U'", format_ipsec_integ_alg,
4634 mp->integrity_algorithm);
4635 rv = VNET_API_ERROR_UNIMPLEMENTED;
4638 sa.integ_alg = mp->integrity_algorithm;
4639 sa.integ_key_len = mp->integrity_key_length;
4640 memcpy(&sa.integ_key, mp->integrity_key, sizeof(sa.integ_key));
4641 sa.use_esn = mp->use_extended_sequence_number;
4642 sa.is_tunnel = mp->is_tunnel;
4643 sa.is_tunnel_ip6 = mp->is_tunnel_ipv6;
4644 memcpy(&sa.tunnel_src_addr, mp->tunnel_src_address, 16);
4645 memcpy(&sa.tunnel_dst_addr, mp->tunnel_dst_address, 16);
4647 rv = ipsec_add_del_sa(vm, &sa, mp->is_add);
4649 rv = VNET_API_ERROR_UNIMPLEMENTED;
4654 REPLY_MACRO(VL_API_IPSEC_SAD_ADD_DEL_ENTRY_REPLY);
4657 vl_api_map_add_domain_t_handler
4658 (vl_api_map_add_domain_t * mp)
4660 vl_api_map_add_domain_reply_t * rmp;
4663 u8 flags = mp->is_translation ? MAP_DOMAIN_TRANSLATION : 0;
4664 rv = map_create_domain((ip4_address_t *)&mp->ip4_prefix, mp->ip4_prefix_len,
4665 (ip6_address_t *)&mp->ip6_prefix, mp->ip6_prefix_len,
4666 (ip6_address_t *)&mp->ip6_src, mp->ip6_src_prefix_len,
4667 mp->ea_bits_len, mp->psid_offset, mp->psid_length, &index, ntohs(mp->mtu), flags);
4669 REPLY_MACRO2(VL_API_MAP_ADD_DOMAIN_REPLY,
4671 rmp->index = ntohl(index);
4676 vl_api_map_del_domain_t_handler
4677 (vl_api_map_del_domain_t * mp)
4679 vl_api_map_del_domain_reply_t * rmp;
4682 rv = map_delete_domain(ntohl(mp->index));
4684 REPLY_MACRO(VL_API_MAP_DEL_DOMAIN_REPLY);
4688 vl_api_map_add_del_rule_t_handler
4689 (vl_api_map_add_del_rule_t * mp)
4691 vl_api_map_del_domain_reply_t * rmp;
4694 rv = map_add_del_psid(ntohl(mp->index), ntohs(mp->psid), (ip6_address_t *)mp->ip6_dst, mp->is_add);
4696 REPLY_MACRO(VL_API_MAP_ADD_DEL_RULE_REPLY);
4700 vl_api_map_domain_dump_t_handler
4701 (vl_api_map_domain_dump_t * mp)
4703 vl_api_map_domain_details_t * rmp;
4704 map_main_t *mm = &map_main;
4706 unix_shared_memory_queue_t * q;
4708 if (pool_elts (mm->domains) == 0)
4711 q = vl_api_client_index_to_input_queue (mp->client_index);
4716 pool_foreach(d, mm->domains, ({
4717 rmp = vl_msg_api_alloc (sizeof (*rmp));
4718 memset (rmp, 0, sizeof (*rmp));
4719 rmp->_vl_msg_id = ntohs(VL_API_MAP_DOMAIN_DETAILS);
4720 rmp->domain_index = htonl(d - mm->domains);
4721 rmp->ea_bits_len = d->ea_bits_len;
4722 rmp->psid_offset = d->psid_offset;
4723 rmp->psid_length = d->psid_length;
4724 memcpy(rmp->ip4_prefix, &d->ip4_prefix, sizeof(rmp->ip4_prefix));
4725 rmp->ip4_prefix_len = d->ip4_prefix_len;
4726 memcpy(rmp->ip6_prefix, &d->ip6_prefix, sizeof(rmp->ip6_prefix));
4727 rmp->ip6_prefix_len = d->ip6_prefix_len;
4728 memcpy(rmp->ip6_src, &d->ip6_src, sizeof(rmp->ip6_src));
4729 rmp->ip6_src_len = d->ip6_src_len;
4730 rmp->mtu = htons(d->mtu);
4731 rmp->is_translation = (d->flags & MAP_DOMAIN_TRANSLATION);
4733 vl_msg_api_send_shmem (q, (u8 *)&rmp);
4738 vl_api_map_rule_dump_t_handler
4739 (vl_api_map_rule_dump_t * mp)
4741 unix_shared_memory_queue_t * q;
4744 vl_api_map_rule_details_t * rmp;
4745 map_main_t *mm = &map_main;
4746 u32 domain_index = ntohl(mp->domain_index);
4749 if (pool_elts (mm->domains) == 0)
4752 d = pool_elt_at_index(mm->domains, domain_index);
4753 if (!d || !d->rules) {
4757 q = vl_api_client_index_to_input_queue (mp->client_index);
4762 for (i = 0; i < (0x1 << d->psid_length); i++) {
4764 if (dst.as_u64[0] == 0 && dst.as_u64[1] == 0) {
4767 rmp = vl_msg_api_alloc(sizeof(*rmp));
4768 memset(rmp, 0, sizeof(*rmp));
4769 rmp->_vl_msg_id = ntohs(VL_API_MAP_RULE_DETAILS);
4770 rmp->psid = htons(i);
4771 memcpy(rmp->ip6_dst, &dst, sizeof(rmp->ip6_dst));
4772 vl_msg_api_send_shmem(q, (u8 *)&rmp);
4777 vl_api_map_summary_stats_t_handler (
4778 vl_api_map_summary_stats_t *mp)
4780 vl_api_map_summary_stats_reply_t *rmp;
4781 vlib_combined_counter_main_t *cm;
4784 u64 total_pkts[VLIB_N_RX_TX];
4785 u64 total_bytes[VLIB_N_RX_TX];
4786 map_main_t *mm = &map_main;
4787 unix_shared_memory_queue_t *q =
4788 vl_api_client_index_to_input_queue(mp->client_index);
4793 rmp = vl_msg_api_alloc (sizeof (*rmp));
4794 rmp->_vl_msg_id = ntohs(VL_API_MAP_SUMMARY_STATS_REPLY);
4795 rmp->context = mp->context;
4798 memset (total_pkts, 0, sizeof (total_pkts));
4799 memset (total_bytes, 0, sizeof (total_bytes));
4801 map_domain_counter_lock (mm);
4802 vec_foreach(cm, mm->domain_counters) {
4803 which = cm - mm->domain_counters;
4805 for (i = 0; i < vec_len(cm->maxi); i++) {
4806 vlib_get_combined_counter (cm, i, &v);
4807 total_pkts[which] += v.packets;
4808 total_bytes[which] += v.bytes;
4812 map_domain_counter_unlock (mm);
4814 /* Note: in HOST byte order! */
4815 rmp->total_pkts[MAP_DOMAIN_COUNTER_RX] = total_pkts[MAP_DOMAIN_COUNTER_RX];
4816 rmp->total_bytes[MAP_DOMAIN_COUNTER_RX] = total_bytes[MAP_DOMAIN_COUNTER_RX];
4817 rmp->total_pkts[MAP_DOMAIN_COUNTER_TX] = total_pkts[MAP_DOMAIN_COUNTER_TX];
4818 rmp->total_bytes[MAP_DOMAIN_COUNTER_TX] = total_bytes[MAP_DOMAIN_COUNTER_TX];
4819 rmp->total_bindings = pool_elts(mm->domains);
4820 rmp->total_ip4_fragments = 0; // Not yet implemented. Should be a simple counter.
4821 rmp->total_security_check[MAP_DOMAIN_COUNTER_TX] = map_error_counter_get(ip4_map_node.index, MAP_ERROR_ENCAP_SEC_CHECK);
4822 rmp->total_security_check[MAP_DOMAIN_COUNTER_RX] = map_error_counter_get(ip4_map_node.index, MAP_ERROR_DECAP_SEC_CHECK);
4824 vl_msg_api_send_shmem(q, (u8 *)&rmp);
4827 static void vl_api_ipsec_sa_set_key_t_handler
4828 (vl_api_ipsec_sa_set_key_t * mp)
4830 vlib_main_t *vm __attribute__((unused)) = vlib_get_main();
4831 vl_api_ipsec_sa_set_key_reply_t *rmp;
4835 sa.id = ntohl(mp->sa_id);
4836 sa.crypto_key_len = mp->crypto_key_length;
4837 memcpy(&sa.crypto_key, mp->crypto_key, sizeof(sa.crypto_key));
4838 sa.integ_key_len = mp->integrity_key_length;
4839 memcpy(&sa.integ_key, mp->integrity_key, sizeof(sa.integ_key));
4841 rv = ipsec_set_sa_key(vm, &sa);
4843 rv = VNET_API_ERROR_UNIMPLEMENTED;
4846 REPLY_MACRO(VL_API_IPSEC_SA_SET_KEY_REPLY);
4849 #define BOUNCE_HANDLER(nn) \
4850 static void vl_api_##nn##_t_handler ( \
4851 vl_api_##nn##_t *mp) \
4853 vpe_client_registration_t *reg; \
4854 vpe_api_main_t * vam = &vpe_api_main; \
4855 unix_shared_memory_queue_t * q; \
4857 /* One registration only... */ \
4858 pool_foreach(reg, vam->nn##_registrations, \
4860 q = vl_api_client_index_to_input_queue (reg->client_index); \
4863 * If the queue is stuffed, turf the msg and complain \
4864 * It's unlikely that the intended recipient is \
4865 * alive; avoid deadlock at all costs. \
4867 if (q->cursize == q->maxsize) { \
4868 clib_warning ("ERROR: receiver queue full, drop msg"); \
4869 vl_msg_api_free (mp); \
4872 vl_msg_api_send_shmem (q, (u8 *)&mp); \
4876 vl_msg_api_free (mp); \
4879 BOUNCE_HANDLER(to_netconf_server);
4880 BOUNCE_HANDLER(from_netconf_server);
4881 BOUNCE_HANDLER(to_netconf_client);
4882 BOUNCE_HANDLER(from_netconf_client);
4886 * Add vpe's API message handlers to the table.
4887 * vlib has alread mapped shared memory and
4888 * added the client registration handlers.
4889 * See .../open-repo/vlib/memclnt_vlib.c:memclnt_process()
4892 static clib_error_t *
4893 vpe_api_hookup (vlib_main_t *vm)
4895 api_main_t * am = &api_main;
4898 vl_msg_api_set_handlers(VL_API_##N, #n, \
4899 vl_api_##n##_t_handler, \
4901 vl_api_##n##_t_endian, \
4902 vl_api_##n##_t_print, \
4903 sizeof(vl_api_##n##_t), 1);
4904 foreach_vpe_api_msg;
4908 * Manually register the sr tunnel add del msg, so we trace
4909 * enough bytes to capture a typical segment list
4911 vl_msg_api_set_handlers (VL_API_SR_TUNNEL_ADD_DEL,
4912 "sr_tunnel_add_del",
4913 vl_api_sr_tunnel_add_del_t_handler,
4915 vl_api_sr_tunnel_add_del_t_endian,
4916 vl_api_sr_tunnel_add_del_t_print,
4919 am->message_bounce [VL_API_FROM_NETCONF_SERVER] = 1;
4920 am->message_bounce [VL_API_TO_NETCONF_SERVER] = 1;
4921 am->message_bounce [VL_API_FROM_NETCONF_CLIENT] = 1;
4922 am->message_bounce [VL_API_TO_NETCONF_CLIENT] = 1;
4925 * Trace space for 8 MPLS encap labels, classifier mask+match
4927 am->api_trace_cfg [VL_API_MPLS_ADD_DEL_ENCAP].size += 8 * sizeof(u32);
4928 am->api_trace_cfg [VL_API_CLASSIFY_ADD_DEL_TABLE].size
4929 += 5 * sizeof (u32x4);
4930 am->api_trace_cfg [VL_API_CLASSIFY_ADD_DEL_SESSION].size
4931 += 5 * sizeof (u32x4);
4932 am->api_trace_cfg [VL_API_VXLAN_ADD_DEL_TUNNEL].size
4933 += 16 * sizeof (u32);
4936 * trace space for 4 nsh-gre variable TLV words
4938 am->api_trace_cfg [VL_API_NSH_GRE_ADD_DEL_TUNNEL].size
4939 += 4 * sizeof (u32);
4944 VLIB_API_INIT_FUNCTION(vpe_api_hookup);
4946 static clib_error_t *
4947 vpe_api_init (vlib_main_t *vm)
4949 vpe_api_main_t *am = &vpe_api_main;
4952 am->vnet_main = vnet_get_main();
4953 am->interface_events_registration_hash = hash_create (0, sizeof (uword));
4954 am->to_netconf_server_registration_hash = hash_create (0, sizeof (uword));
4955 am->from_netconf_server_registration_hash = hash_create (0, sizeof (uword));
4956 am->to_netconf_client_registration_hash = hash_create (0, sizeof (uword));
4957 am->from_netconf_client_registration_hash = hash_create (0, sizeof (uword));
4958 am->oam_events_registration_hash = hash_create (0, sizeof (uword));
4961 vl_set_memory_region_name ("/vpe-api");
4962 vl_enable_disable_memory_api (vm, 1 /* enable it */);
4967 VLIB_INIT_FUNCTION(vpe_api_init);
4969 void * get_unformat_vnet_sw_interface (void)
4971 return (void *) &unformat_vnet_sw_interface;
4974 #undef vl_api_version
4975 #define vl_api_version(n,v) static u32 vpe_api_version = v;
4976 #include <api/vpe.api.h>
4977 #undef vl_api_version
4979 int vl_msg_api_version_check (vl_api_memclnt_create_t * mp)
4981 if (clib_host_to_net_u32(mp->api_versions[0]) != vpe_api_version) {
4982 clib_warning ("vpe API mismatch: 0x%08x instead of 0x%08x",
4983 clib_host_to_net_u32 (mp->api_versions[0]),
4990 static u8 * format_arp_event (u8 * s, va_list * args)
4992 vl_api_ip4_arp_event_t * event = va_arg (*args, vl_api_ip4_arp_event_t *);
4994 s = format (s, "pid %d: %U", event->pid,
4995 format_ip4_address, &event->address);
4999 static clib_error_t *
5000 show_ip4_arp_events_fn (vlib_main_t * vm,
5001 unformat_input_t * input,
5002 vlib_cli_command_t * cmd)
5004 vpe_api_main_t * am = &vpe_api_main;
5005 vl_api_ip4_arp_event_t * event;
5007 if (pool_elts (am->arp_events) == 0) {
5008 vlib_cli_output (vm, "No active arp event registrations");
5012 pool_foreach (event, am->arp_events,
5014 vlib_cli_output (vm, "%U", format_arp_event, event);
5020 VLIB_CLI_COMMAND (show_ip4_arp_events, static) = {
5021 .path = "show arp event registrations",
5022 .function = show_ip4_arp_events_fn,
5023 .short_help = "Show arp event registrations",