From 0053de63ec4bf8b9bce7817f1b61c9791baf6c26 Mon Sep 17 00:00:00 2001 From: Neale Ranns Date: Tue, 22 May 2018 08:40:52 -0700 Subject: ARP proxy dumps Change-Id: I8335ebf266becf2f42bb3f28a17dfed8d9b08f97 Signed-off-by: Neale Ranns --- src/vnet/adj/adj.c | 4 +- src/vnet/adj/adj_glean.c | 4 +- src/vnet/adj/adj_mcast.c | 4 +- src/vnet/adj/adj_nbr.c | 3 +- src/vnet/ethernet/arp.c | 31 ++++++++++---- src/vnet/ethernet/arp.h | 56 ++++++++++++++++++++++++ src/vnet/ethernet/ethernet.h | 11 ----- src/vnet/interface.c | 21 ++++++++- src/vnet/interface_funcs.h | 27 +++++++++++- src/vnet/ip/ip.api | 57 +++++++++++++++++++++--- src/vnet/ip/ip_api.c | 100 ++++++++++++++++++++++++++++++++++++++++--- src/vnet/ip/ip_neighbor.c | 2 +- 12 files changed, 279 insertions(+), 41 deletions(-) create mode 100644 src/vnet/ethernet/arp.h (limited to 'src/vnet') diff --git a/src/vnet/adj/adj.c b/src/vnet/adj/adj.c index ed4bada6f24..abfe8729b39 100644 --- a/src/vnet/adj/adj.c +++ b/src/vnet/adj/adj.c @@ -353,7 +353,7 @@ adj_mtu_update_walk_cb (adj_index_t ai, return (ADJ_WALK_RC_CONTINUE); } -static void +static walk_rc_t adj_sw_mtu_update (vnet_main_t * vnm, u32 sw_if_index, void *ctx) @@ -362,6 +362,8 @@ adj_sw_mtu_update (vnet_main_t * vnm, * Walk all the adjacencies on the interface to update the cached MTU */ adj_walk (sw_if_index, adj_mtu_update_walk_cb, NULL); + + return (WALK_CONTINUE); } void diff --git a/src/vnet/adj/adj_glean.c b/src/vnet/adj/adj_glean.c index 41bc4c9f68d..74881d7f67c 100644 --- a/src/vnet/adj/adj_glean.c +++ b/src/vnet/adj/adj_glean.c @@ -173,12 +173,14 @@ VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION(adj_glean_interface_state_change); * @brief Invoked on each SW interface of a HW interface when the * HW interface state changes */ -static void +static walk_rc_t adj_nbr_hw_sw_interface_state_change (vnet_main_t * vnm, u32 sw_if_index, void *arg) { adj_glean_interface_state_change(vnm, sw_if_index, (uword) arg); + + return (WALK_CONTINUE); } /** diff --git a/src/vnet/adj/adj_mcast.c b/src/vnet/adj/adj_mcast.c index deaa7fcffa4..593c1b66a8a 100644 --- a/src/vnet/adj/adj_mcast.c +++ b/src/vnet/adj/adj_mcast.c @@ -220,12 +220,14 @@ VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION(adj_mcast_interface_state_change); * @brief Invoked on each SW interface of a HW interface when the * HW interface state changes */ -static void +static walk_rc_t adj_mcast_hw_sw_interface_state_change (vnet_main_t * vnm, u32 sw_if_index, void *arg) { adj_mcast_interface_state_change(vnm, sw_if_index, (uword) arg); + + return (WALK_CONTINUE); } /** diff --git a/src/vnet/adj/adj_nbr.c b/src/vnet/adj/adj_nbr.c index eff7d4ce1fb..6fd9b40efc3 100644 --- a/src/vnet/adj/adj_nbr.c +++ b/src/vnet/adj/adj_nbr.c @@ -751,7 +751,7 @@ VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION_PRIO( * @brief Invoked on each SW interface of a HW interface when the * HW interface state changes */ -static void +static walk_rc_t adj_nbr_hw_sw_interface_state_change (vnet_main_t * vnm, u32 sw_if_index, void *arg) @@ -768,6 +768,7 @@ adj_nbr_hw_sw_interface_state_change (vnet_main_t * vnm, adj_nbr_interface_state_change_one, ctx); } + return (WALK_CONTINUE); } /** diff --git a/src/vnet/ethernet/arp.c b/src/vnet/ethernet/arp.c index 55beb7025dd..49a16f764f3 100644 --- a/src/vnet/ethernet/arp.c +++ b/src/vnet/ethernet/arp.c @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include #include @@ -52,8 +52,8 @@ typedef struct ethernet_arp_interface_t_ typedef struct { - u32 lo_addr; - u32 hi_addr; + ip4_address_t lo_addr; + ip4_address_t hi_addr; u32 fib_index; } ethernet_proxy_arp_t; @@ -1226,8 +1226,8 @@ arp_input (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) vec_foreach (pa, am->proxy_arps) { - u32 lo_addr = clib_net_to_host_u32 (pa->lo_addr); - u32 hi_addr = clib_net_to_host_u32 (pa->hi_addr); + u32 lo_addr = clib_net_to_host_u32 (pa->lo_addr.as_u32); + u32 hi_addr = clib_net_to_host_u32 (pa->hi_addr.as_u32); /* an ARP request hit in the proxy-arp table? */ if ((this_addr >= lo_addr && this_addr <= hi_addr) && @@ -1963,6 +1963,19 @@ vnet_arp_set_ip4_over_ethernet (vnet_main_t * vnm, return 0; } +void +proxy_arp_walk (proxy_arp_walk_t cb, void *data) +{ + ethernet_arp_main_t *am = ðernet_arp_main; + ethernet_proxy_arp_t *pa; + + vec_foreach (pa, am->proxy_arps) + { + if (!cb (&pa->lo_addr, &pa->hi_addr, pa->fib_index, data)) + break; + } +} + int vnet_proxy_arp_add_del (ip4_address_t * lo_addr, ip4_address_t * hi_addr, u32 fib_index, int is_del) @@ -1973,8 +1986,8 @@ vnet_proxy_arp_add_del (ip4_address_t * lo_addr, vec_foreach (pa, am->proxy_arps) { - if (pa->lo_addr == lo_addr->as_u32 - && pa->hi_addr == hi_addr->as_u32 && pa->fib_index == fib_index) + if (pa->lo_addr.as_u32 == lo_addr->as_u32 && + pa->hi_addr.as_u32 == hi_addr->as_u32 && pa->fib_index == fib_index) { found_at_index = pa - am->proxy_arps; break; @@ -1994,8 +2007,8 @@ vnet_proxy_arp_add_del (ip4_address_t * lo_addr, /* add, not in table */ vec_add2 (am->proxy_arps, pa, 1); - pa->lo_addr = lo_addr->as_u32; - pa->hi_addr = hi_addr->as_u32; + pa->lo_addr.as_u32 = lo_addr->as_u32; + pa->hi_addr.as_u32 = hi_addr->as_u32; pa->fib_index = fib_index; return 0; } diff --git a/src/vnet/ethernet/arp.h b/src/vnet/ethernet/arp.h new file mode 100644 index 00000000000..7b50ed77538 --- /dev/null +++ b/src/vnet/ethernet/arp.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2015 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __ARP_H__ +#define __ARP_H__ + +#include +#include +#include + +extern int vnet_proxy_arp_add_del (ip4_address_t * lo_addr, + ip4_address_t * hi_addr, + u32 fib_index, int is_del); + +extern int vnet_arp_set_ip4_over_ethernet (vnet_main_t * vnm, + u32 sw_if_index, + void *a_arg, + int is_static, + int is_no_fib_entry); + +extern int vnet_arp_unset_ip4_over_ethernet (vnet_main_t * vnm, + u32 sw_if_index, void *a_arg); + +extern int vnet_proxy_arp_fib_reset (u32 fib_id); + +/** + * call back function when walking the DB of proxy ARPs + * @return 0 to stop the walk !0 to continue + */ +typedef walk_rc_t (proxy_arp_walk_t) (const ip4_address_t * lo_addr, + const ip4_address_t * hi_addr, + u32 fib_index, void *dat); + +extern void proxy_arp_walk (proxy_arp_walk_t cb, void *data); + +#endif + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/src/vnet/ethernet/ethernet.h b/src/vnet/ethernet/ethernet.h index fb7e2c5ba81..79ae7e6e909 100644 --- a/src/vnet/ethernet/ethernet.h +++ b/src/vnet/ethernet/ethernet.h @@ -435,17 +435,6 @@ void ethernet_sw_interface_set_l2_mode_noport (vnet_main_t * vnm, void ethernet_set_rx_redirect (vnet_main_t * vnm, vnet_hw_interface_t * hi, u32 enable); -int -vnet_arp_set_ip4_over_ethernet (vnet_main_t * vnm, - u32 sw_if_index, void *a_arg, - int is_static, int is_no_fib_entry); - -int -vnet_arp_unset_ip4_over_ethernet (vnet_main_t * vnm, - u32 sw_if_index, void *a_arg); - -int vnet_proxy_arp_fib_reset (u32 fib_id); - clib_error_t *next_by_ethertype_init (next_by_ethertype_t * l3_next); clib_error_t *next_by_ethertype_register (next_by_ethertype_t * l3_next, u32 ethertype, u32 next_index); diff --git a/src/vnet/interface.c b/src/vnet/interface.c index d3ad896be12..36793f1177e 100644 --- a/src/vnet/interface.c +++ b/src/vnet/interface.c @@ -998,11 +998,30 @@ vnet_hw_interface_walk_sw (vnet_main_t * vnm, hash_foreach (id, sw_if_index, hi->sub_interface_sw_if_index_by_id, ({ - fn (vnm, sw_if_index, ctx); + if (WALK_STOP == fn (vnm, sw_if_index, ctx)) + break; })); /* *INDENT-ON* */ } +void +vnet_sw_interface_walk (vnet_main_t * vnm, + vnet_sw_interface_walk_t fn, void *ctx) +{ + vnet_interface_main_t *im; + vnet_sw_interface_t *si; + + im = &vnm->interface_main; + + /* *INDENT-OFF* */ + pool_foreach (si, im->sw_interfaces, + { + if (WALK_STOP == fn (vnm, si, ctx)) + break; + }); + /* *INDENT-ON* */ +} + static void serialize_vnet_hw_interface_set_class (serialize_main_t * m, va_list * va) { diff --git a/src/vnet/interface_funcs.h b/src/vnet/interface_funcs.h index 3f910f9d13f..e1568e33b5d 100644 --- a/src/vnet/interface_funcs.h +++ b/src/vnet/interface_funcs.h @@ -147,11 +147,20 @@ vnet_clear_sw_interface_tag (vnet_main_t * vnm, u32 sw_if_index) } } +/** + * Walk return code + */ +typedef enum walk_rc_t_ +{ + WALK_STOP, + WALK_CONTINUE, +} walk_rc_t; + /** * Call back walk type for walking SW indices on a HW interface */ -typedef void (*vnet_hw_sw_interface_walk_t) (vnet_main_t * vnm, - u32 sw_if_index, void *ctx); +typedef walk_rc_t (*vnet_hw_sw_interface_walk_t) (vnet_main_t * vnm, + u32 sw_if_index, void *ctx); /** * @brief @@ -162,6 +171,20 @@ void vnet_hw_interface_walk_sw (vnet_main_t * vnm, u32 hw_if_index, vnet_hw_sw_interface_walk_t fn, void *ctx); +/** + * Call back walk type for walking SW indices on a HW interface + */ +typedef walk_rc_t (*vnet_sw_interface_walk_t) (vnet_main_t * vnm, + vnet_sw_interface_t * si, + void *ctx); + +/** + * @brief + * Walk all the SW interfaces in the system. + */ +void vnet_sw_interface_walk (vnet_main_t * vnm, + vnet_sw_interface_walk_t fn, void *ctx); + /* Register a hardware interface instance. */ u32 vnet_register_interface (vnet_main_t * vnm, u32 dev_class_index, diff --git a/src/vnet/ip/ip.api b/src/vnet/ip/ip.api index 7f4f030882d..c5be0c67fbb 100644 --- a/src/vnet/ip/ip.api +++ b/src/vnet/ip/ip.api @@ -860,18 +860,13 @@ service { events ip6_nd_event; }; -/** \brief Proxy ARP add / del request - @param client_index - opaque cookie to identify the sender - @param context - sender context, to match reply w/ request +/** \brief Proxy ARP configuration type @param vrf_id - VRF / Fib table ID - @param is_add - 1 if adding the Proxy ARP range, 0 if deleting @param low_address[4] - Low address of the Proxy ARP range @param hi_address[4] - High address of the Proxy ARP range */ -autoreply define proxy_arp_add_del +typeonly define proxy_arp { - u32 client_index; - u32 context; u32 vrf_id; u8 is_add; u8 low_address[4]; @@ -879,6 +874,37 @@ autoreply define proxy_arp_add_del }; /** \brief Proxy ARP add / del request + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request + @param is_add - 1 if adding the Proxy ARP range, 0 if deleting + @param proxy - Proxy configuration +*/ +autoreply define proxy_arp_add_del +{ + u32 client_index; + u32 context; + u8 is_add; + vl_api_proxy_arp_t proxy; +}; + +/** \brief Proxy ARP dump request + */ +define proxy_arp_dump +{ + u32 client_index; + u32 context; +}; + +/** \brief Proxy ARP dump details reply + * @param proxy - Same data as used to configure + */ +define proxy_arp_details +{ + u32 context; + vl_api_proxy_arp_t proxy; +}; + +/** \brief Proxy ARP add / del interface request @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request @param sw_if_index - Which interface to enable / disable Proxy Arp on @@ -893,6 +919,23 @@ autoreply define proxy_arp_intfc_enable_disable u8 enable_disable; }; +/** \brief Proxy ARP interface dump request + */ +define proxy_arp_intfc_dump +{ + u32 client_index; + u32 context; +}; + +/** \brief Proxy ARP interface dump details reply + * @param sw_if_index The interface on which ARP proxy is enabled. + */ +define proxy_arp_intfc_details +{ + u32 context; + u32 sw_if_index; +}; + /** \brief Reset fib table request @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request diff --git a/src/vnet/ip/ip_api.c b/src/vnet/ip/ip_api.c index ce3ff79acfa..8464b1ddc98 100644 --- a/src/vnet/ip/ip_api.c +++ b/src/vnet/ip/ip_api.c @@ -45,6 +45,7 @@ #include #include #include +#include #include @@ -84,7 +85,9 @@ _(WANT_IP4_ARP_EVENTS, want_ip4_arp_events) \ _(WANT_IP6_ND_EVENTS, want_ip6_nd_events) \ _(WANT_IP6_RA_EVENTS, want_ip6_ra_events) \ _(PROXY_ARP_ADD_DEL, proxy_arp_add_del) \ +_(PROXY_ARP_DUMP, proxy_arp_dump) \ _(PROXY_ARP_INTFC_ENABLE_DISABLE, proxy_arp_intfc_enable_disable) \ + _(PROXY_ARP_INTFC_DUMP, proxy_arp_intfc_dump) \ _(RESET_FIB, reset_fib) \ _(IP_ADD_DEL_ROUTE, ip_add_del_route) \ _(IP_TABLE_ADD_DEL, ip_table_add_del) \ @@ -2715,14 +2718,11 @@ vl_api_proxy_arp_add_del_t_handler (vl_api_proxy_arp_add_del_t * mp) u32 fib_index; int rv; ip4_main_t *im = &ip4_main; - int vnet_proxy_arp_add_del (ip4_address_t * lo_addr, - ip4_address_t * hi_addr, - u32 fib_index, int is_del); uword *p; stats_dslock_with_hint (1 /* release hint */ , 6 /* tag */ ); - p = hash_get (im->fib_index_by_table_id, ntohl (mp->vrf_id)); + p = hash_get (im->fib_index_by_table_id, ntohl (mp->proxy.vrf_id)); if (!p) { @@ -2732,8 +2732,8 @@ vl_api_proxy_arp_add_del_t_handler (vl_api_proxy_arp_add_del_t * mp) fib_index = p[0]; - rv = vnet_proxy_arp_add_del ((ip4_address_t *) mp->low_address, - (ip4_address_t *) mp->hi_address, + rv = vnet_proxy_arp_add_del ((ip4_address_t *) mp->proxy.low_address, + (ip4_address_t *) mp->proxy.hi_address, fib_index, mp->is_add == 0); out: @@ -2741,6 +2741,94 @@ out: REPLY_MACRO (VL_API_PROXY_ARP_ADD_DEL_REPLY); } +typedef struct proxy_arp_walk_ctx_t_ +{ + vl_api_registration_t *reg; + u32 context; +} proxy_arp_walk_ctx_t; + +static walk_rc_t +send_proxy_arp_details (const ip4_address_t * lo_addr, + const ip4_address_t * hi_addr, + u32 fib_index, void *data) +{ + vl_api_proxy_arp_details_t *mp; + proxy_arp_walk_ctx_t *ctx; + + ctx = data; + + mp = vl_msg_api_alloc (sizeof (*mp)); + memset (mp, 0, sizeof (*mp)); + mp->_vl_msg_id = ntohs (VL_API_PROXY_ARP_DETAILS); + mp->context = ctx->context; + mp->proxy.vrf_id = htonl (fib_index); + clib_memcpy (mp->proxy.low_address, lo_addr, + sizeof (mp->proxy.low_address)); + clib_memcpy (mp->proxy.hi_address, hi_addr, sizeof (mp->proxy.hi_address)); + + vl_api_send_msg (ctx->reg, (u8 *) mp); + + return (WALK_CONTINUE); +} + +static void +vl_api_proxy_arp_dump_t_handler (vl_api_proxy_arp_dump_t * mp) +{ + vl_api_registration_t *reg; + + reg = vl_api_client_index_to_registration (mp->client_index); + if (!reg) + return; + + proxy_arp_walk_ctx_t wctx = { + .reg = reg, + .context = mp->context, + }; + + proxy_arp_walk (send_proxy_arp_details, &wctx); +} + +static walk_rc_t +send_proxy_arp_intfc_details (vnet_main_t * vnm, + vnet_sw_interface_t * si, void *data) +{ + vl_api_proxy_arp_intfc_details_t *mp; + proxy_arp_walk_ctx_t *ctx; + + if (!(si->flags & VNET_SW_INTERFACE_FLAG_PROXY_ARP)) + return (WALK_CONTINUE); + + ctx = data; + + mp = vl_msg_api_alloc (sizeof (*mp)); + memset (mp, 0, sizeof (*mp)); + mp->_vl_msg_id = ntohs (VL_API_PROXY_ARP_INTFC_DETAILS); + mp->context = ctx->context; + mp->sw_if_index = htonl (si->sw_if_index); + + vl_api_send_msg (ctx->reg, (u8 *) mp); + + return (WALK_CONTINUE); +} + +static void +vl_api_proxy_arp_intfc_dump_t_handler (vl_api_proxy_arp_intfc_dump_t * mp) +{ + vl_api_registration_t *reg; + + reg = vl_api_client_index_to_registration (mp->client_index); + if (!reg) + return; + + proxy_arp_walk_ctx_t wctx = { + .reg = reg, + .context = mp->context, + }; + + vnet_sw_interface_walk (vnet_get_main (), + send_proxy_arp_intfc_details, &wctx); +} + static void vl_api_proxy_arp_intfc_enable_disable_t_handler (vl_api_proxy_arp_intfc_enable_disable_t * mp) diff --git a/src/vnet/ip/ip_neighbor.c b/src/vnet/ip/ip_neighbor.c index a43fdfd58b3..b9c03aa703c 100644 --- a/src/vnet/ip/ip_neighbor.c +++ b/src/vnet/ip/ip_neighbor.c @@ -19,7 +19,7 @@ #include #include #include -#include +#include /* * IP neighbor scan parameter defaults are as follows: -- cgit 1.2.3-korg