aboutsummaryrefslogtreecommitdiffstats
path: root/src/vnet/arp/arp.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/vnet/arp/arp.c')
-rw-r--r--src/vnet/arp/arp.c249
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