n_left_from = frame->n_vectors;
next = node->cached_next_index;
- if (node->flags & VLIB_NODE_FLAG_TRACE)
- ip4_forward_next_trace (vm, node, frame, VLIB_TX);
-
while (n_left_from > 0)
{
vlib_get_next_frame (vm, node, next, to_next, n_left_to_next);
vlib_put_next_frame (vm, node, next, n_left_to_next);
}
+ if (node->flags & VLIB_NODE_FLAG_TRACE)
+ ip4_forward_next_trace (vm, node, frame, VLIB_TX);
+
return frame->n_vectors;
}
{
.arc_name = "ip4-unicast",
.start_nodes = VNET_FEATURES ("ip4-input", "ip4-input-no-checksum"),
+ .last_in_arc = "ip4-lookup",
.arc_index_ptr = &ip4_main.lookup_main.ucast_feature_arc_index,
};
{
.arc_name = "ip4-unicast",
.node_name = "ip4-policer-classify",
- .runs_before = VNET_FEATURES ("ipsec-input-ip4"),
+ .runs_before = VNET_FEATURES ("ipsec4-input-feature"),
};
VNET_FEATURE_INIT (ip4_ipsec, static) =
{
.arc_name = "ip4-unicast",
- .node_name = "ipsec-input-ip4",
+ .node_name = "ipsec4-input-feature",
.runs_before = VNET_FEATURES ("vpath-input-ip4"),
};
{
.arc_name = "ip4-multicast",
.start_nodes = VNET_FEATURES ("ip4-input", "ip4-input-no-checksum"),
+ .last_in_arc = "ip4-mfib-forward-lookup",
.arc_index_ptr = &ip4_main.lookup_main.mcast_feature_arc_index,
};
{
.arc_name = "ip4-output",
.start_nodes = VNET_FEATURES ("ip4-rewrite", "ip4-midchain", "ip4-dvr-dpo"),
+ .last_in_arc = "interface-output",
.arc_index_ptr = &ip4_main.lookup_main.output_feature_arc_index,
};
{
.arc_name = "ip4-output",
.node_name = "ip4-outacl",
- .runs_before = VNET_FEATURES ("ipsec-output-ip4"),
+ .runs_before = VNET_FEATURES ("ipsec4-output-feature"),
};
VNET_FEATURE_INIT (ip4_ipsec_output, static) =
{
.arc_name = "ip4-output",
- .node_name = "ipsec-output-ip4",
+ .node_name = "ipsec4-output-feature",
.runs_before = VNET_FEATURES ("interface-output"),
};
VNET_SW_INTERFACE_ADD_DEL_FUNCTION (ip4_sw_interface_add_del);
/* Global IP4 main. */
+#ifndef CLIB_MARCH_VARIANT
ip4_main_t ip4_main;
+#endif /* CLIB_MARCH_VARIANT */
static clib_error_t *
ip4_lookup_init (vlib_main_t * vm)
{
ethernet_arp_header_t h;
- memset (&h, 0, sizeof (h));
-
- /* Set target ethernet address to all zeros. */
- memset (h.ip4_over_ethernet[1].ethernet, 0,
- sizeof (h.ip4_over_ethernet[1].ethernet));
+ clib_memset (&h, 0, sizeof (h));
#define _16(f,v) h.f = clib_host_to_net_u16 (v);
#define _8(f,v) h.f = v;
vec_elt (im->fib_index_by_sw_if_index,
vnet_buffer (b0)->sw_if_index[VLIB_RX]);
- clib_memcpy (t0->packet_data,
- vlib_buffer_get_current (b0),
- sizeof (t0->packet_data));
+ clib_memcpy_fast (t0->packet_data,
+ vlib_buffer_get_current (b0),
+ sizeof (t0->packet_data));
}
if (b1->flags & VLIB_BUFFER_IS_TRACED)
{
(u32) ~ 0) ? vnet_buffer (b1)->sw_if_index[VLIB_TX] :
vec_elt (im->fib_index_by_sw_if_index,
vnet_buffer (b1)->sw_if_index[VLIB_RX]);
- clib_memcpy (t1->packet_data, vlib_buffer_get_current (b1),
- sizeof (t1->packet_data));
+ clib_memcpy_fast (t1->packet_data, vlib_buffer_get_current (b1),
+ sizeof (t1->packet_data));
}
from += 2;
n_left -= 2;
(u32) ~ 0) ? vnet_buffer (b0)->sw_if_index[VLIB_TX] :
vec_elt (im->fib_index_by_sw_if_index,
vnet_buffer (b0)->sw_if_index[VLIB_RX]);
- clib_memcpy (t0->packet_data, vlib_buffer_get_current (b0),
- sizeof (t0->packet_data));
+ clib_memcpy_fast (t0->packet_data, vlib_buffer_get_current (b0),
+ sizeof (t0->packet_data));
}
from += 1;
n_left -= 1;
{
.arc_name = "ip4-local",
.start_nodes = VNET_FEATURES ("ip4-local"),
+ .last_in_arc = "ip4-local-end-of-arc",
};
/* *INDENT-ON* */
ip4_address_t src;
u32 lbi;
u8 error;
+ u8 first;
} ip4_local_last_check_t;
static inline void
vnet_buffer (b)->sw_if_index[VLIB_TX] != ~0 ?
vnet_buffer (b)->sw_if_index[VLIB_TX] : vnet_buffer (b)->ip.fib_index;
- if (PREDICT_FALSE (last_check->src.as_u32 != ip0->src_address.as_u32))
+ if (PREDICT_FALSE (last_check->first ||
+ (last_check->src.as_u32 != ip0->src_address.as_u32)))
{
mtrie0 = &ip4_fib_get (vnet_buffer (b)->ip.fib_index)->mtrie;
leaf0 = ip4_fib_mtrie_lookup_step_one (mtrie0, &ip0->src_address);
vnet_buffer (b)->ip.adj_index[VLIB_TX] = last_check->lbi;
vnet_buffer (b)->ip.adj_index[VLIB_RX] = last_check->lbi;
*error0 = last_check->error;
+ last_check->first = 0;
}
}
ip4_fib_mtrie_t *mtrie[2];
const dpo_id_t *dpo[2];
load_balance_t *lb[2];
- u32 not_last_hit = 0;
+ u32 not_last_hit;
u32 lbi[2];
+ not_last_hit = last_check->first;
not_last_hit |= ip[0]->src_address.as_u32 ^ last_check->src.as_u32;
not_last_hit |= ip[1]->src_address.as_u32 ^ last_check->src.as_u32;
error[0] = last_check->error;
error[1] = last_check->error;
+ last_check->first = 0;
}
}
{
IP_LOCAL_PACKET_TYPE_L4,
IP_LOCAL_PACKET_TYPE_NAT,
+ IP_LOCAL_PACKET_TYPE_FRAG,
};
/**
{
ip_lookup_main_t *lm = &ip4_main.lookup_main;
+ if (PREDICT_FALSE (ip4_is_fragment (ip)))
+ {
+ *next = IP_LOCAL_NEXT_REASSEMBLY;
+ return IP_LOCAL_PACKET_TYPE_FRAG;
+ }
if (PREDICT_FALSE (b->flags & VNET_BUFFER_F_IS_NATED))
{
*next = lm->local_next_by_ip_protocol[ip->protocol];
u8 error[2], pt[2];
ip4_local_last_check_t last_check = {
+ /*
+ * 0.0.0.0 can appear as the source address of an IP packet,
+ * as can any other address, hence the need to use the 'first'
+ * member to make sure the .lbi is initialised for the first
+ * packet.
+ */
.src = {.as_u32 = 0},
.lbi = ~0,
- .error = IP4_ERROR_UNKNOWN_PROTOCOL
+ .error = IP4_ERROR_UNKNOWN_PROTOCOL,
+ .first = 1,
};
from = vlib_frame_vector_args (frame);
[IP_LOCAL_NEXT_PUNT] = "ip4-punt",
[IP_LOCAL_NEXT_UDP_LOOKUP] = "ip4-udp-lookup",
[IP_LOCAL_NEXT_ICMP] = "ip4-icmp-input",
+ [IP_LOCAL_NEXT_REASSEMBLY] = "ip4-reassembly",
},
};
/* *INDENT-ON* */
u32 *from, *to_next_drop;
uword n_left_from, n_left_to_next_drop, next_index;
u32 thread_index = vm->thread_index;
- u32 seed;
+ u64 seed;
if (node->flags & VLIB_NODE_FLAG_TRACE)
ip4_forward_next_trace (vm, node, frame, VLIB_TX);
while (n_left_from > 0 && n_left_to_next_drop > 0)
{
- u32 pi0, adj_index0, r0, sw_if_index0, drop0;
+ u32 pi0, bi0, adj_index0, sw_if_index0;
ip_adjacency_t *adj0;
- vlib_buffer_t *p0;
- ip4_header_t *ip0;
+ vlib_buffer_t *p0, *b0;
+ ip4_address_t resolve0;
+ ethernet_arp_header_t *h0;
+ vnet_hw_interface_t *hw_if0;
+ u64 r0;
pi0 = from[0];
-
p0 = vlib_get_buffer (vm, pi0);
+ from += 1;
+ n_left_from -= 1;
+ to_next_drop[0] = pi0;
+ to_next_drop += 1;
+ n_left_to_next_drop -= 1;
+
adj_index0 = vnet_buffer (p0)->ip.adj_index[VLIB_TX];
adj0 = adj_get (adj_index0);
- ip0 = vlib_buffer_get_current (p0);
- sw_if_index0 = adj0->rewrite_header.sw_if_index;
- vnet_buffer (p0)->sw_if_index[VLIB_TX] = sw_if_index0;
-
- if (PREDICT_TRUE (is_glean))
+ if (is_glean)
{
- /*
- * this is the Glean case, so we are ARPing for the
- * packet's destination
- */
- r0 = ip0->dst_address.data_u32;
+ /* resolve the packet's destination */
+ ip4_header_t *ip0 = vlib_buffer_get_current (p0);
+ resolve0 = ip0->dst_address;
}
else
{
- r0 = adj0->sub_type.nbr.next_hop.ip4.data_u32;
+ /* resolve the incomplete adj */
+ resolve0 = adj0->sub_type.nbr.next_hop.ip4;
}
- drop0 = throttle_check (&im->arp_throttle, thread_index, r0, seed);
-
- from += 1;
- n_left_from -= 1;
- to_next_drop[0] = pi0;
- to_next_drop += 1;
- n_left_to_next_drop -= 1;
+ /* combine the address and interface for the hash key */
+ sw_if_index0 = adj0->rewrite_header.sw_if_index;
+ r0 = (u64) resolve0.data_u32 << 32;
+ r0 |= sw_if_index0;
- p0->error =
- node->errors[drop0 ? IP4_ARP_ERROR_DROP :
- IP4_ARP_ERROR_REQUEST_SENT];
+ if (throttle_check (&im->arp_throttle, thread_index, r0, seed))
+ {
+ p0->error = node->errors[IP4_ARP_ERROR_THROTTLED];
+ continue;
+ }
/*
* the adj has been updated to a rewrite but the node the DPO that got
* us here hasn't - yet. no big deal. we'll drop while we wait.
*/
if (IP_LOOKUP_NEXT_REWRITE == adj0->lookup_next_index)
- continue;
-
- if (drop0)
- continue;
+ {
+ p0->error = node->errors[IP4_ARP_ERROR_RESOLVED];
+ continue;
+ }
/*
* Can happen if the control-plane is programming tables
|| (!is_glean && adj0->lookup_next_index != IP_LOOKUP_NEXT_ARP))
{
p0->error = node->errors[IP4_ARP_ERROR_NON_ARP_ADJ];
+ continue;
}
- else
- /* Send ARP request. */
+ /* Send ARP request. */
+ h0 =
+ vlib_packet_template_get_packet (vm,
+ &im->ip4_arp_request_packet_template,
+ &bi0);
+ b0 = vlib_get_buffer (vm, bi0);
+
+ /* copy the persistent fields from the original */
+ clib_memcpy_fast (b0->opaque2, p0->opaque2, sizeof (p0->opaque2));
+
+ /* Seems we're out of buffers */
+ if (PREDICT_FALSE (!h0))
{
- u32 bi0 = 0;
- vlib_buffer_t *b0;
- ethernet_arp_header_t *h0;
- vnet_hw_interface_t *hw_if0;
-
- h0 =
- vlib_packet_template_get_packet (vm,
- &im->ip4_arp_request_packet_template,
- &bi0);
-
- /* Seems we're out of buffers */
- if (PREDICT_FALSE (!h0))
- continue;
-
- /* Add rewrite/encap string for ARP packet. */
- vnet_rewrite_one_header (adj0[0], h0,
- sizeof (ethernet_header_t));
+ p0->error = node->errors[IP4_ARP_ERROR_NO_BUFFERS];
+ continue;
+ }
- hw_if0 = vnet_get_sup_hw_interface (vnm, sw_if_index0);
+ /* Add rewrite/encap string for ARP packet. */
+ vnet_rewrite_one_header (adj0[0], h0, sizeof (ethernet_header_t));
- /* Src ethernet address in ARP header. */
- clib_memcpy (h0->ip4_over_ethernet[0].ethernet,
- hw_if0->hw_address,
- sizeof (h0->ip4_over_ethernet[0].ethernet));
+ hw_if0 = vnet_get_sup_hw_interface (vnm, sw_if_index0);
- if (is_glean)
- {
- /* The interface's source address is stashed in the Glean Adj */
- h0->ip4_over_ethernet[0].ip4 =
- adj0->sub_type.glean.receive_addr.ip4;
-
- /* Copy in destination address we are requesting. This is the
- * glean case, so it's the packet's destination.*/
- h0->ip4_over_ethernet[1].ip4.data_u32 =
- ip0->dst_address.data_u32;
- }
- else
+ /* Src ethernet address in ARP header. */
+ mac_address_from_bytes (&h0->ip4_over_ethernet[0].mac,
+ hw_if0->hw_address);
+ if (is_glean)
+ {
+ /* The interface's source address is stashed in the Glean Adj */
+ h0->ip4_over_ethernet[0].ip4 =
+ adj0->sub_type.glean.receive_addr.ip4;
+ }
+ else
+ {
+ /* Src IP address in ARP header. */
+ if (ip4_src_address_for_packet (lm, sw_if_index0,
+ &h0->ip4_over_ethernet[0].ip4))
{
- /* Src IP address in ARP header. */
- if (ip4_src_address_for_packet (lm, sw_if_index0,
- &h0->
- ip4_over_ethernet[0].ip4))
- {
- /* No source address available */
- p0->error =
- node->errors[IP4_ARP_ERROR_NO_SOURCE_ADDRESS];
- vlib_buffer_free (vm, &bi0, 1);
- continue;
- }
-
- /* Copy in destination address we are requesting from the
- incomplete adj */
- h0->ip4_over_ethernet[1].ip4.data_u32 =
- adj0->sub_type.nbr.next_hop.ip4.as_u32;
+ /* No source address available */
+ p0->error = node->errors[IP4_ARP_ERROR_NO_SOURCE_ADDRESS];
+ vlib_buffer_free (vm, &bi0, 1);
+ continue;
}
+ }
+ h0->ip4_over_ethernet[1].ip4 = resolve0;
- vlib_buffer_copy_trace_flag (vm, p0, bi0);
- b0 = vlib_get_buffer (vm, bi0);
- VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0);
- vnet_buffer (b0)->sw_if_index[VLIB_TX] = sw_if_index0;
+ p0->error = node->errors[IP4_ARP_ERROR_REQUEST_SENT];
- vlib_buffer_advance (b0, -adj0->rewrite_header.data_bytes);
+ vlib_buffer_copy_trace_flag (vm, p0, bi0);
+ VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0);
+ vnet_buffer (b0)->sw_if_index[VLIB_TX] = sw_if_index0;
- vlib_set_next_frame_buffer (vm, node,
- adj0->rewrite_header.next_index,
- bi0);
- }
+ vlib_buffer_advance (b0, -adj0->rewrite_header.data_bytes);
+
+ vlib_set_next_frame_buffer (vm, node,
+ adj0->rewrite_header.next_index, bi0);
}
vlib_put_next_frame (vm, node, IP4_ARP_NEXT_DROP, n_left_to_next_drop);
}
static char *ip4_arp_error_strings[] = {
- [IP4_ARP_ERROR_DROP] = "address overflow drops",
+ [IP4_ARP_ERROR_THROTTLED] = "ARP requests throttled",
+ [IP4_ARP_ERROR_RESOLVED] = "ARP requests resolved",
+ [IP4_ARP_ERROR_NO_BUFFERS] = "ARP requests out of buffer",
[IP4_ARP_ERROR_REQUEST_SENT] = "ARP requests sent",
[IP4_ARP_ERROR_NON_ARP_ADJ] = "ARPs to non-ARP adjacencies",
- [IP4_ARP_ERROR_REPLICATE_DROP] = "ARP replication completed",
- [IP4_ARP_ERROR_REPLICATE_FAIL] = "ARP replication failed",
[IP4_ARP_ERROR_NO_SOURCE_ADDRESS] = "no source address for ARP request",
};
/* *INDENT-ON* */
#define foreach_notrace_ip4_arp_error \
-_(DROP) \
+_(THROTTLED) \
+_(RESOLVED) \
+_(NO_BUFFERS) \
_(REQUEST_SENT) \
-_(REPLICATE_DROP) \
-_(REPLICATE_FAIL)
+_(NON_ARP_ADJ) \
+_(NO_SOURCE_ADDRESS)
static clib_error_t *
arp_notrace_init (vlib_main_t * vm)
sw_if_index);
}
- clib_memcpy (h->ip4_over_ethernet[0].ethernet, hi->hw_address,
- sizeof (h->ip4_over_ethernet[0].ethernet));
+ mac_address_from_bytes (&h->ip4_over_ethernet[0].mac, hi->hw_address);
h->ip4_over_ethernet[0].ip4 = src[0];
h->ip4_over_ethernet[1].ip4 = dst[0];
if (n_left_from >= 6)
{
int i;
- for (i = 0; i < 6; i++)
+ for (i = 2; i < 6; i++)
vlib_prefetch_buffer_header (bufs[i], LOAD);
}
adj0->sub_type.midchain.fixup_func
(vm, adj0, b[0], adj0->sub_type.midchain.fixup_data);
adj1->sub_type.midchain.fixup_func
- (vm, adj1, b[1], adj0->sub_type.midchain.fixup_data);
+ (vm, adj1, b[1], adj1->sub_type.midchain.fixup_data);
}
if (is_mcast)
adj0->rewrite_header.dst_mcast_offset,
&ip0->dst_address.as_u32, (u8 *) ip0);
vnet_ip_mcast_fixup_header (IP4_MCAST_ADDR_MASK,
- adj0->rewrite_header.dst_mcast_offset,
+ adj1->rewrite_header.dst_mcast_offset,
&ip1->dst_address.as_u32, (u8 *) ip1);
}