#include <vnet/api_errno.h> /* for API error numbers */
#include <vnet/fib/fib_table.h> /* for FIB table and entry creation */
#include <vnet/fib/fib_entry.h> /* for FIB table and entry creation */
+#include <vnet/fib/fib_urpf_list.h> /* for FIB uRPF check */
#include <vnet/fib/ip4_fib.h>
#include <vnet/dpo/load_balance.h>
#include <vnet/dpo/classify_dpo.h>
}
/* Built-in ip4 unicast rx feature path definition */
+VNET_IP4_UNICAST_FEATURE_INIT (ip4_flow_classify, static) = {
+ .node_name = "ip4-flow-classify",
+ .runs_before = ORDER_CONSTRAINTS {"ip4-inacl", 0},
+ .feature_index = &ip4_main.ip4_unicast_rx_feature_flow_classify,
+};
+
VNET_IP4_UNICAST_FEATURE_INIT (ip4_inacl, static) = {
.node_name = "ip4-inacl",
.runs_before = ORDER_CONSTRAINTS {"ip4-source-check-via-rx", 0},
typedef struct {
/* Adjacency taken. */
- u32 adj_index;
+ u32 dpo_index;
u32 flow_hash;
u32 fib_index;
uword indent = format_get_indent (s);
s = format (s, "fib %d dpo-idx %d flow hash: 0x%08x",
- t->fib_index, t->adj_index, t->flow_hash);
+ t->fib_index, t->dpo_index, t->flow_hash);
s = format (s, "\n%U%U",
format_white_space, indent,
format_ip4_header, t->packet_data, sizeof (t->packet_data));
vnet_main_t * vnm = vnet_get_main();
uword indent = format_get_indent (s);
- s = format (s, "tx_sw_if_index %d adj-idx %d : %U flow hash: 0x%08x",
- t->fib_index, t->adj_index, format_ip_adjacency,
- vnm, t->adj_index, FORMAT_IP_ADJACENCY_NONE,
+ s = format (s, "tx_sw_if_index %d dpo-idx %d : %U flow hash: 0x%08x",
+ t->fib_index, t->dpo_index, format_ip_adjacency,
+ vnm, t->dpo_index, FORMAT_IP_ADJACENCY_NONE,
t->flow_hash);
s = format (s, "\n%U%U",
format_white_space, indent,
format_ip_adjacency_packet_data,
- vnm, t->adj_index,
+ vnm, t->dpo_index,
t->packet_data, sizeof (t->packet_data));
return s;
}
if (b0->flags & VLIB_BUFFER_IS_TRACED)
{
t0 = vlib_add_trace (vm, node, b0, sizeof (t0[0]));
- t0->adj_index = vnet_buffer (b0)->ip.adj_index[which_adj_index];
+ t0->dpo_index = vnet_buffer (b0)->ip.adj_index[which_adj_index];
t0->flow_hash = vnet_buffer (b0)->ip.flow_hash;
t0->fib_index = (vnet_buffer(b0)->sw_if_index[VLIB_TX] != (u32)~0) ?
vnet_buffer(b0)->sw_if_index[VLIB_TX] :
if (b1->flags & VLIB_BUFFER_IS_TRACED)
{
t1 = vlib_add_trace (vm, node, b1, sizeof (t1[0]));
- t1->adj_index = vnet_buffer (b1)->ip.adj_index[which_adj_index];
+ t1->dpo_index = vnet_buffer (b1)->ip.adj_index[which_adj_index];
t1->flow_hash = vnet_buffer (b1)->ip.flow_hash;
t1->fib_index = (vnet_buffer(b1)->sw_if_index[VLIB_TX] != (u32)~0) ?
vnet_buffer(b1)->sw_if_index[VLIB_TX] :
if (b0->flags & VLIB_BUFFER_IS_TRACED)
{
t0 = vlib_add_trace (vm, node, b0, sizeof (t0[0]));
- t0->adj_index = vnet_buffer (b0)->ip.adj_index[which_adj_index];
+ t0->dpo_index = vnet_buffer (b0)->ip.adj_index[which_adj_index];
t0->flow_hash = vnet_buffer (b0)->ip.flow_hash;
t0->fib_index = (vnet_buffer(b0)->sw_if_index[VLIB_TX] != (u32)~0) ?
vnet_buffer(b0)->sw_if_index[VLIB_TX] :
/*
* Must have a route to source otherwise we drop the packet.
* ip4 broadcasts are accepted, e.g. to make dhcp client work
+ *
+ * The checks are:
+ * - the source is a recieve => it's from us => bogus, do this
+ * first since it sets a different error code.
+ * - uRPF check for any route to source - accept if passes.
+ * - allow packets destined to the broadcast address from unknown sources
*/
- error0 = (error0 == IP4_ERROR_UNKNOWN_PROTOCOL
- && dpo0->dpoi_type != DPO_ADJACENCY
- && dpo0->dpoi_type != DPO_ADJACENCY_INCOMPLETE
- && dpo0->dpoi_type != DPO_RECEIVE
- && dpo0->dpoi_type != DPO_DROP
- && dpo0->dpoi_type != DPO_ADJACENCY_GLEAN
- && ip0->dst_address.as_u32 != 0xFFFFFFFF
- ? IP4_ERROR_SRC_LOOKUP_MISS
- : error0);
- error0 = (dpo0->dpoi_type == DPO_RECEIVE ?
+ error0 = ((error0 == IP4_ERROR_UNKNOWN_PROTOCOL &&
+ dpo0->dpoi_type == DPO_RECEIVE) ?
IP4_ERROR_SPOOFED_LOCAL_PACKETS :
error0);
- error1 = (error1 == IP4_ERROR_UNKNOWN_PROTOCOL
- && dpo1->dpoi_type != DPO_ADJACENCY
- && dpo1->dpoi_type != DPO_ADJACENCY_INCOMPLETE
- && dpo1->dpoi_type != DPO_RECEIVE
- && dpo1->dpoi_type != DPO_DROP
- && dpo1->dpoi_type != DPO_ADJACENCY_GLEAN
- && ip1->dst_address.as_u32 != 0xFFFFFFFF
+ error0 = ((error0 == IP4_ERROR_UNKNOWN_PROTOCOL &&
+ !fib_urpf_check_size(lb0->lb_urpf) &&
+ ip0->dst_address.as_u32 != 0xFFFFFFFF)
? IP4_ERROR_SRC_LOOKUP_MISS
- : error1);
- error1 = (dpo0->dpoi_type == DPO_RECEIVE ?
+ : error0);
+ error1 = ((error1 == IP4_ERROR_UNKNOWN_PROTOCOL &&
+ dpo1->dpoi_type == DPO_RECEIVE) ?
IP4_ERROR_SPOOFED_LOCAL_PACKETS :
error1);
+ error1 = ((error1 == IP4_ERROR_UNKNOWN_PROTOCOL &&
+ !fib_urpf_check_size(lb1->lb_urpf) &&
+ ip1->dst_address.as_u32 != 0xFFFFFFFF)
+ ? IP4_ERROR_SRC_LOOKUP_MISS
+ : error1);
next0 = lm->local_next_by_ip_protocol[proto0];
next1 = lm->local_next_by_ip_protocol[proto1];
vnet_buffer (p0)->ip.adj_index[VLIB_RX] =
dpo0->dpoi_index;
- /* Must have a route to source otherwise we drop the packet. */
- error0 = (error0 == IP4_ERROR_UNKNOWN_PROTOCOL
- && dpo0->dpoi_type != DPO_ADJACENCY
- && dpo0->dpoi_type != DPO_ADJACENCY_INCOMPLETE
- && dpo0->dpoi_type != DPO_RECEIVE
- && dpo0->dpoi_type != DPO_DROP
- && dpo0->dpoi_type != DPO_ADJACENCY_GLEAN
- && ip0->dst_address.as_u32 != 0xFFFFFFFF
- ? IP4_ERROR_SRC_LOOKUP_MISS
- : error0);
- /* Packet originated from a local address => spoofing */
- error0 = (dpo0->dpoi_type == DPO_RECEIVE ?
+ error0 = ((error0 == IP4_ERROR_UNKNOWN_PROTOCOL &&
+ dpo0->dpoi_type == DPO_RECEIVE) ?
IP4_ERROR_SPOOFED_LOCAL_PACKETS :
error0);
+ error0 = ((error0 == IP4_ERROR_UNKNOWN_PROTOCOL &&
+ !fib_urpf_check_size(lb0->lb_urpf) &&
+ ip0->dst_address.as_u32 != 0xFFFFFFFF)
+ ? IP4_ERROR_SRC_LOOKUP_MISS
+ : error0);
next0 = lm->local_next_by_ip_protocol[proto0];