diff options
Diffstat (limited to 'src/vnet/arp/arp.c')
-rw-r--r-- | src/vnet/arp/arp.c | 249 |
1 files changed, 129 insertions, 120 deletions
diff --git a/src/vnet/arp/arp.c b/src/vnet/arp/arp.c index ced3c1cb7a7..43b2a93a7b3 100644 --- a/src/vnet/arp/arp.c +++ b/src/vnet/arp/arp.c @@ -25,6 +25,7 @@ #include <vnet/pg/pg.h> #include <vnet/ip-neighbor/ip_neighbor.h> +#include <vnet/ip-neighbor/ip4_neighbor.h> #include <vnet/ip-neighbor/ip_neighbor_dp.h> #include <vlibmemory/api.h> @@ -190,7 +191,6 @@ always_inline u32 arp_learn (u32 sw_if_index, const ethernet_arp_ip4_over_ethernet_address_t * addr) { - /* *INDENT-OFF* */ ip_neighbor_learn_t l = { .ip = { .ip.ip4 = addr->ip4, @@ -199,11 +199,10 @@ arp_learn (u32 sw_if_index, .mac = addr->mac, .sw_if_index = sw_if_index, }; - /* *INDENT-ON* */ ip_neighbor_learn_dp (&l); - return (ETHERNET_ARP_ERROR_l3_src_address_learned); + return (ARP_ERROR_L3_SRC_ADDRESS_LEARNED); } typedef enum arp_input_next_t_ @@ -248,22 +247,21 @@ arp_input (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) p0 = vlib_get_buffer (vm, pi0); arp0 = vlib_buffer_get_current (p0); - error0 = ETHERNET_ARP_ERROR_replies_sent; + error0 = ARP_ERROR_REPLIES_SENT; next0 = ARP_INPUT_NEXT_DROP; - error0 = - (arp0->l2_type != - clib_net_to_host_u16 (ETHERNET_ARP_HARDWARE_TYPE_ethernet) ? - ETHERNET_ARP_ERROR_l2_type_not_ethernet : error0); - error0 = - (arp0->l3_type != - clib_net_to_host_u16 (ETHERNET_TYPE_IP4) ? - ETHERNET_ARP_ERROR_l3_type_not_ip4 : error0); - error0 = - (0 == arp0->ip4_over_ethernet[0].ip4.as_u32 ? - ETHERNET_ARP_ERROR_l3_dst_address_unset : error0); - - if (ETHERNET_ARP_ERROR_replies_sent == error0) + error0 = (arp0->l2_type != clib_net_to_host_u16 ( + ETHERNET_ARP_HARDWARE_TYPE_ethernet) ? + ARP_ERROR_L2_TYPE_NOT_ETHERNET : + error0); + error0 = (arp0->l3_type != clib_net_to_host_u16 (ETHERNET_TYPE_IP4) ? + ARP_ERROR_L3_TYPE_NOT_IP4 : + error0); + error0 = (0 == arp0->ip4_over_ethernet[0].ip4.as_u32 ? + ARP_ERROR_L3_DST_ADDRESS_UNSET : + error0); + + if (ARP_ERROR_REPLIES_SENT == error0) { next0 = ARP_INPUT_NEXT_DISABLED; vnet_feature_arc_start (am->feature_arc_index, @@ -289,23 +287,6 @@ typedef enum arp_disabled_next_t_ ARP_DISABLED_N_NEXT, } arp_disabled_next_t; -#define foreach_arp_disabled_error \ - _ (DISABLED, "ARP Disabled on this interface") \ - -typedef enum -{ -#define _(sym,string) ARP_DISABLED_ERROR_##sym, - foreach_arp_disabled_error -#undef _ - ARP_DISABLED_N_ERROR, -} arp_disabled_error_t; - -static char *arp_disabled_error_strings[] = { -#define _(sym,string) string, - foreach_arp_disabled_error -#undef _ -}; - static uword arp_disabled (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) @@ -332,7 +313,7 @@ arp_disabled (vlib_main_t * vm, u32 pi0, error0; next0 = ARP_DISABLED_NEXT_DROP; - error0 = ARP_DISABLED_ERROR_DISABLED; + error0 = ARP_ERROR_DISABLED; pi0 = to_next[0] = from[0]; from += 1; @@ -371,7 +352,6 @@ arp_dst_fib_check (const fib_node_index_t fei, fib_entry_flag_t * flags) const fib_entry_t *entry = fib_entry_get (fei); const fib_entry_src_t *entry_src; fib_source_t src; - /* *INDENT-OFF* */ FOR_EACH_SRC_ADDED(entry, entry_src, src, ({ *flags = fib_entry_get_flags_for_source (fei, src); @@ -380,7 +360,6 @@ arp_dst_fib_check (const fib_node_index_t fei, fib_entry_flag_t * flags) else if (FIB_ENTRY_FLAG_CONNECTED & *flags) return ARP_DST_FIB_CONN; })) - /* *INDENT-ON* */ return ARP_DST_FIB_NONE; } @@ -432,18 +411,22 @@ arp_reply (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) eth_rx = ethernet_buffer_get_header (p0); next0 = ARP_REPLY_NEXT_DROP; - error0 = ETHERNET_ARP_ERROR_replies_sent; + error0 = ARP_ERROR_REPLIES_SENT; sw_if_index0 = vnet_buffer (p0)->sw_if_index[VLIB_RX]; /* Check that IP address is local and matches incoming interface. */ fib_index0 = ip4_fib_table_get_index_for_sw_if_index (sw_if_index0); if (~0 == fib_index0) { - error0 = ETHERNET_ARP_ERROR_interface_no_table; + error0 = ARP_ERROR_INTERFACE_NO_TABLE; goto drop; } + dst_fei = ip4_fib_table_lookup (ip4_fib_get (fib_index0), + &arp0->ip4_over_ethernet[1].ip4, 32); + conn_sw_if_index0 = fib_entry_get_any_resolving_interface (dst_fei); + { /* * we're looking for FIB entries that indicate the source @@ -476,7 +459,6 @@ arp_reply (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) * flags we need, or the flags we must not have, * is not the best source, so check then all. */ - /* *INDENT-OFF* */ FOR_EACH_SRC_ADDED(src_fib_entry, src, source, ({ src_flags = fib_entry_get_flags_for_source (src_fei, source); @@ -485,36 +467,35 @@ arp_reply (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) address. */ if (FIB_ENTRY_FLAG_LOCAL & src_flags) { - error0 = ETHERNET_ARP_ERROR_l3_src_address_is_local; - /* - * When VPP has an interface whose address is also - * applied to a TAP interface on the host, then VPP's - * TAP interface will be unnumbered to the 'real' - * interface and do proxy ARP from the host. - * The curious aspect of this setup is that ARP requests - * from the host will come from the VPP's own address. - * So don't drop immediately here, instead go see if this - * is a proxy ARP case. - */ - goto next_feature; - } - /* A Source must also be local to subnet of matching - * interface address. */ - if ((FIB_ENTRY_FLAG_ATTACHED & src_flags) || - (FIB_ENTRY_FLAG_CONNECTED & src_flags)) - { - attached = 1; - break; - } - /* - * else - * The packet was sent from an address that is not - * connected nor attached i.e. it is not from an - * address that is covered by a link's sub-net, - * nor is it a already learned host resp. - */ + error0 = ARP_ERROR_L3_SRC_ADDRESS_IS_LOCAL; + /* + * When VPP has an interface whose address is also + * applied to a TAP interface on the host, then VPP's + * TAP interface will be unnumbered to the 'real' + * interface and do proxy ARP from the host. + * The curious aspect of this setup is that ARP requests + * from the host will come from the VPP's own address. + * So don't drop immediately here, instead go see if this + * is a proxy ARP case. + */ + goto next_feature; + } + /* A Source must also be local to subnet of matching + * interface address. */ + if ((FIB_ENTRY_FLAG_ATTACHED & src_flags) || + (FIB_ENTRY_FLAG_CONNECTED & src_flags)) + { + attached = 1; + break; + } + /* + * else + * The packet was sent from an address that is not + * connected nor attached i.e. it is not from an + * address that is covered by a link's sub-net, + * nor is it a already learned host resp. + */ })); - /* *INDENT-ON* */ /* * shorter mask lookup for the next iteration. @@ -532,24 +513,20 @@ arp_reply (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) while (!attached && !fib_entry_is_sourced (src_fei, FIB_SOURCE_DEFAULT_ROUTE)); - if (!attached) + if (!attached && + !arp_unnumbered (p0, sw_if_index0, conn_sw_if_index0)) { /* - * the matching route is a not attached, i.e. it was - * added as a result of routing, rather than interface/ARP - * configuration. If the matching route is not a host route - * (i.e. a /32) + * the matching route is a not attached and not unnumbered, + * i.e. it was added as a result of routing, rather than + * interface/ARP configuration. If the matching route is not + * a host route (i.e. a /32) */ - error0 = ETHERNET_ARP_ERROR_l3_src_address_not_local; + error0 = ARP_ERROR_L3_SRC_ADDRESS_NOT_LOCAL; goto drop; } } - dst_fei = ip4_fib_table_lookup (ip4_fib_get (fib_index0), - &arp0->ip4_over_ethernet[1].ip4, - 32); - conn_sw_if_index0 = fib_entry_get_any_resolving_interface (dst_fei); - switch (arp_dst_fib_check (dst_fei, &dst_flags)) { case ARP_DST_FIB_ADJ: @@ -562,18 +539,24 @@ arp_reply (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) * blow our ARP cache */ if (conn_sw_if_index0 != sw_if_index0) - error0 = ETHERNET_ARP_ERROR_l3_dst_address_not_local; + error0 = ARP_ERROR_L3_DST_ADDRESS_NOT_LOCAL; else if (arp0->ip4_over_ethernet[0].ip4.as_u32 == arp0->ip4_over_ethernet[1].ip4.as_u32) - error0 = arp_learn (sw_if_index0, - &arp0->ip4_over_ethernet[0]); - goto drop; + { + vlib_increment_simple_counter ( + &ip_neighbor_counters[AF_IP4] + .ipnc[VLIB_RX][IP_NEIGHBOR_CTR_GRAT], + vm->thread_index, sw_if_index0, 1); + error0 = + arp_learn (sw_if_index0, &arp0->ip4_over_ethernet[0]); + } + goto next_feature; case ARP_DST_FIB_CONN: /* destination is connected, continue to process */ break; case ARP_DST_FIB_NONE: /* destination is not connected, stop here */ - error0 = ETHERNET_ARP_ERROR_l3_dst_address_not_local; + error0 = ARP_ERROR_L3_DST_ADDRESS_NOT_LOCAL; goto next_feature; } @@ -596,10 +579,18 @@ arp_reply (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) (eth_rx->src_address, arp0->ip4_over_ethernet[0].mac.bytes) && !is_vrrp_reply0) { - error0 = ETHERNET_ARP_ERROR_l2_address_mismatch; + error0 = ARP_ERROR_L2_ADDRESS_MISMATCH; goto drop; } + vlib_increment_simple_counter ( + &ip_neighbor_counters[AF_IP4] + .ipnc[VLIB_RX][arp0->opcode == clib_host_to_net_u16 ( + ETHERNET_ARP_OPCODE_reply) ? + IP_NEIGHBOR_CTR_REPLY : + IP_NEIGHBOR_CTR_REQUEST], + vm->thread_index, sw_if_index0, 1); + /* Learn or update sender's mapping only for replies to addresses * that are local to the subnet */ if (arp0->opcode == @@ -612,7 +603,7 @@ arp_reply (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) /* a reply for a non-local destination could be a GARP. * GARPs for hosts we know were handled above, so this one * we drop */ - error0 = ETHERNET_ARP_ERROR_l3_dst_address_not_local; + error0 = ARP_ERROR_L3_DST_ADDRESS_NOT_LOCAL; goto next_feature; } @@ -628,37 +619,38 @@ arp_reply (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) sw_if_index0 != fib_entry_get_resolving_interface (src_fei)) { /* - * The interface the ARP is sent to or was received on is not the - * interface on which the covering prefix is configured. - * Maybe this is a case for unnumbered. + * The interface the ARP is sent to or was received on is + * not the interface on which the covering prefix is + * configured. Maybe this is a case for unnumbered. */ if (!arp_unnumbered (p0, sw_if_index0, conn_sw_if_index0)) { - error0 = ETHERNET_ARP_ERROR_unnumbered_mismatch; + error0 = ARP_ERROR_UNNUMBERED_MISMATCH; goto drop; } } if (arp0->ip4_over_ethernet[0].ip4.as_u32 == arp0->ip4_over_ethernet[1].ip4.as_u32) { - error0 = ETHERNET_ARP_ERROR_gratuitous_arp; + error0 = ARP_ERROR_GRATUITOUS_ARP; goto drop; } - next0 = arp_mk_reply (vnm, p0, sw_if_index0, - if_addr0, arp0, eth_rx); + next0 = arp_mk_reply (vnm, p0, sw_if_index0, if_addr0, arp0, eth_rx); /* We are going to reply to this request, so, in the absence of errors, learn the sender */ if (!error0) error0 = arp_learn (sw_if_index0, &arp0->ip4_over_ethernet[1]); + vlib_increment_simple_counter ( + &ip_neighbor_counters[AF_IP4].ipnc[VLIB_TX][IP_NEIGHBOR_CTR_REPLY], + vm->thread_index, sw_if_index0, 1); n_replies_sent += 1; goto enqueue; next_feature: vnet_feature_next (&next0, p0); - goto enqueue; drop: p0->error = node->errors[error0]; @@ -671,28 +663,21 @@ arp_reply (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) vlib_put_next_frame (vm, node, next_index, n_left_to_next); } - vlib_error_count (vm, node->node_index, - ETHERNET_ARP_ERROR_replies_sent, n_replies_sent); + vlib_error_count (vm, node->node_index, ARP_ERROR_REPLIES_SENT, + n_replies_sent); return frame->n_vectors; } -static char *ethernet_arp_error_strings[] = { -#define _(sym,string) string, - foreach_ethernet_arp_error -#undef _ -}; - -/* *INDENT-OFF* */ VLIB_REGISTER_NODE (arp_input_node, static) = { .function = arp_input, .name = "arp-input", .vector_size = sizeof (u32), - .n_errors = ETHERNET_ARP_N_ERROR, - .error_strings = ethernet_arp_error_strings, + .n_errors = ARP_N_ERROR, + .error_counters = arp_error_counters, .n_next_nodes = ARP_INPUT_N_NEXT, .next_nodes = { [ARP_INPUT_NEXT_DROP] = "error-drop", @@ -707,8 +692,8 @@ VLIB_REGISTER_NODE (arp_disabled_node, static) = .function = arp_disabled, .name = "arp-disabled", .vector_size = sizeof (u32), - .n_errors = ARP_DISABLED_N_ERROR, - .error_strings = arp_disabled_error_strings, + .n_errors = ARP_N_ERROR, + .error_counters = arp_error_counters, .n_next_nodes = ARP_DISABLED_N_NEXT, .next_nodes = { [ARP_INPUT_NEXT_DROP] = "error-drop", @@ -722,8 +707,8 @@ VLIB_REGISTER_NODE (arp_reply_node, static) = .function = arp_reply, .name = "arp-reply", .vector_size = sizeof (u32), - .n_errors = ETHERNET_ARP_N_ERROR, - .error_strings = ethernet_arp_error_strings, + .n_errors = ARP_N_ERROR, + .error_counters = arp_error_counters, .n_next_nodes = ARP_REPLY_N_NEXT, .next_nodes = { [ARP_REPLY_NEXT_DROP] = "error-drop", @@ -771,7 +756,6 @@ VNET_FEATURE_INIT (arp_drop_feat_node, static) = .runs_before = 0, /* last feature */ }; -/* *INDENT-ON* */ typedef struct { @@ -870,7 +854,7 @@ VNET_SW_INTERFACE_ADD_DEL_FUNCTION (vnet_arp_add_del_sw_interface); const static ip_neighbor_vft_t arp_vft = { .inv_proxy4_add = arp_proxy_add, .inv_proxy4_del = arp_proxy_del, - .inv_proxy4_enable = arp_proxy_disable, + .inv_proxy4_enable = arp_proxy_enable, .inv_proxy4_disable = arp_proxy_disable, }; @@ -896,12 +880,39 @@ ethernet_arp_init (vlib_main_t * vm) vlib_node_runtime_t *rt = vlib_node_get_runtime (vm, arp_input_node.index); -#define _(a,b) \ - vnet_pcap_drop_trace_filter_add_del \ - (rt->errors[ETHERNET_ARP_ERROR_##a], \ - 1 /* is_add */); - foreach_ethernet_arp_error -#undef _ + vnet_pcap_drop_trace_filter_add_del (rt->errors[ARP_ERROR_REPLIES_SENT], + 1); + vnet_pcap_drop_trace_filter_add_del (rt->errors[ARP_ERROR_DISABLED], 1); + vnet_pcap_drop_trace_filter_add_del ( + rt->errors[ARP_ERROR_L2_TYPE_NOT_ETHERNET], 1); + vnet_pcap_drop_trace_filter_add_del (rt->errors[ARP_ERROR_L3_TYPE_NOT_IP4], + 1); + vnet_pcap_drop_trace_filter_add_del ( + rt->errors[ARP_ERROR_L3_SRC_ADDRESS_NOT_LOCAL], 1); + vnet_pcap_drop_trace_filter_add_del ( + rt->errors[ARP_ERROR_L3_DST_ADDRESS_NOT_LOCAL], 1); + vnet_pcap_drop_trace_filter_add_del ( + rt->errors[ARP_ERROR_L3_DST_ADDRESS_UNSET], 1); + vnet_pcap_drop_trace_filter_add_del ( + rt->errors[ARP_ERROR_L3_SRC_ADDRESS_IS_LOCAL], 1); + vnet_pcap_drop_trace_filter_add_del ( + rt->errors[ARP_ERROR_L3_SRC_ADDRESS_LEARNED], 1); + vnet_pcap_drop_trace_filter_add_del ( + rt->errors[ARP_ERROR_REPLIES_RECEIVED], 1); + vnet_pcap_drop_trace_filter_add_del ( + rt->errors[ARP_ERROR_OPCODE_NOT_REQUEST], 1); + vnet_pcap_drop_trace_filter_add_del ( + rt->errors[ARP_ERROR_PROXY_ARP_REPLIES_SENT], 1); + vnet_pcap_drop_trace_filter_add_del ( + rt->errors[ARP_ERROR_L2_ADDRESS_MISMATCH], 1); + vnet_pcap_drop_trace_filter_add_del (rt->errors[ARP_ERROR_GRATUITOUS_ARP], + 1); + vnet_pcap_drop_trace_filter_add_del ( + rt->errors[ARP_ERROR_INTERFACE_NO_TABLE], 1); + vnet_pcap_drop_trace_filter_add_del ( + rt->errors[ARP_ERROR_INTERFACE_NOT_IP_ENABLED], 1); + vnet_pcap_drop_trace_filter_add_del ( + rt->errors[ARP_ERROR_UNNUMBERED_MISMATCH], 1); } { @@ -916,13 +927,11 @@ ethernet_arp_init (vlib_main_t * vm) return 0; } -/* *INDENT-OFF* */ VLIB_INIT_FUNCTION (ethernet_arp_init) = { .runs_after = VLIB_INITS("ethernet_init", "ip_neighbor_init"), }; -/* *INDENT-ON* */ /* * fd.io coding-style-patch-verification: ON |