#include <vnet/fib/ip6_fib.h>
#include <vnet/mfib/ip6_mfib.h>
#include <vnet/dpo/load_balance_map.h>
+#include <vnet/dpo/receive_dpo.h>
#include <vnet/dpo/classify_dpo.h>
#include <vnet/classify/vnet_classify.h>
+#include <vnet/pg/pg.h>
#ifndef CLIB_MARCH_VARIANT
#include <vppinfra/bihash_template.c>
#endif
#include <vnet/ip/ip6_forward.h>
-#include <vnet/ipsec/ipsec_tun.h>
#include <vnet/interface_output.h>
/* Flag used by IOAM code. Classifier sets it pop-hop-by-hop checks it */
ip6_address_fib_t ip6_af, *addr_fib = 0;
const ip6_address_t *ll_addr;
- /* local0 interface doesn't support IP addressing */
- if (sw_if_index == 0)
+ error = vnet_sw_interface_supports_addressing (vnm, sw_if_index);
+ if (error)
{
- return
- clib_error_create ("local0 interface doesn't support IP addressing");
+ vnm->api_errno = VNET_API_ERROR_UNSUPPORTED;
+ return error;
}
if (ip6_address_is_link_local_unicast (address))
return (NULL);
}
- vec_validate (im->fib_index_by_sw_if_index, sw_if_index);
- vec_validate (im->mfib_index_by_sw_if_index, sw_if_index);
-
ip6_addr_fib_init (&ip6_af, address,
vec_elt (im->fib_index_by_sw_if_index, sw_if_index));
vec_add1 (addr_fib, ip6_af);
ip6_address_t *a;
u32 is_admin_up, fib_index;
- /* Fill in lookup tables with default table (0). */
- vec_validate (im->fib_index_by_sw_if_index, sw_if_index);
-
vec_validate_init_empty (im->
lookup_main.if_address_pool_index_by_sw_if_index,
sw_if_index, ~0);
{
ip6_main_t *im = &ip6_main;
- vec_validate (im->fib_index_by_sw_if_index, sw_if_index);
- vec_validate (im->mfib_index_by_sw_if_index, sw_if_index);
+ vec_validate_init_empty (im->fib_index_by_sw_if_index, sw_if_index, ~0);
+ vec_validate_init_empty (im->mfib_index_by_sw_if_index, sw_if_index, ~0);
- if (!is_add)
+ if (is_add)
+ {
+ /* Fill in lookup tables with default table (0). */
+ im->fib_index_by_sw_if_index[sw_if_index] = 0;
+ im->mfib_index_by_sw_if_index[sw_if_index] = 0;
+ }
+ else
{
/* Ensure that IPv6 is disabled */
ip6_main_t *im6 = &ip6_main;
}));
/* *INDENT-ON* */
ip6_mfib_interface_enable_disable (sw_if_index, 0);
+
+ if (0 != im6->fib_index_by_sw_if_index[sw_if_index])
+ fib_table_bind (FIB_PROTOCOL_IP6, sw_if_index, 0);
+ if (0 != im6->mfib_index_by_sw_if_index[sw_if_index])
+ mfib_table_bind (FIB_PROTOCOL_IP6, sw_if_index, 0);
+
+ /* Erase the lookup tables just in case */
+ im6->fib_index_by_sw_if_index[sw_if_index] = ~0;
+ im6->mfib_index_by_sw_if_index[sw_if_index] = ~0;
}
vnet_feature_enable_disable ("ip6-unicast", "ip6-not-enabled", sw_if_index,
ip6_next_proto_is_tcp_udp (vlib_buffer_t * p0, ip6_header_t * ip0,
u32 * udp_offset0)
{
- u32 proto0;
- proto0 = ip6_locate_header (p0, ip0, IP_PROTOCOL_UDP, udp_offset0);
- if (proto0 != IP_PROTOCOL_UDP)
- {
- proto0 = ip6_locate_header (p0, ip0, IP_PROTOCOL_TCP, udp_offset0);
- proto0 = (proto0 == IP_PROTOCOL_TCP) ? proto0 : 0;
- }
- return proto0;
+ int nh = ip6_locate_header (p0, ip0, -1, udp_offset0);
+ if (nh > 0)
+ if (nh == IP_PROTOCOL_UDP || nh == IP_PROTOCOL_TCP)
+ return nh;
+ return 0;
}
/* *INDENT-OFF* */
-VNET_FEATURE_ARC_INIT (ip6_local) =
-{
- .arc_name = "ip6-local",
- .start_nodes = VNET_FEATURES ("ip6-local"),
+VNET_FEATURE_ARC_INIT (ip6_local) = {
+ .arc_name = "ip6-local",
+ .start_nodes = VNET_FEATURES ("ip6-local", "ip6-receive"),
};
/* *INDENT-ON* */
}
n_bytes_left -= n_this_buffer;
- n_bytes_left -= p0->total_length_not_including_first_buffer;
+ n_bytes_left -= vlib_buffer_length_in_chain (vm, p0) - p0->current_length;
if (n_bytes_left == 0)
return 0;
return 1;
}
-
always_inline uword
-ip6_local_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
- vlib_frame_t * frame, int head_of_feature_arc)
+ip6_local_inline (vlib_main_t *vm, vlib_node_runtime_t *node,
+ vlib_frame_t *frame, int head_of_feature_arc,
+ int is_receive_dpo)
{
ip6_main_t *im = &ip6_main;
ip_lookup_main_t *lm = &im->lookup_main;
flags[0] = b[0]->flags;
flags[1] = b[1]->flags;
+ vnet_buffer_oflags_t oflags[2];
+ oflags[0] = vnet_buffer (b[0])->oflags;
+ oflags[1] = vnet_buffer (b[1])->oflags;
+
+ u32 l4_offload[2];
+ l4_offload[0] = (flags[0] & VNET_BUFFER_F_OFFLOAD) &&
+ (oflags[0] & (VNET_BUFFER_OFFLOAD_F_TCP_CKSUM |
+ VNET_BUFFER_OFFLOAD_F_UDP_CKSUM));
+ l4_offload[1] = (flags[1] & VNET_BUFFER_F_OFFLOAD) &&
+ (oflags[1] & (VNET_BUFFER_OFFLOAD_F_TCP_CKSUM |
+ VNET_BUFFER_OFFLOAD_F_UDP_CKSUM));
+
u32 good_l4_csum[2];
good_l4_csum[0] =
- flags[0] & (VNET_BUFFER_F_L4_CHECKSUM_CORRECT |
- VNET_BUFFER_F_OFFLOAD_TCP_CKSUM |
- VNET_BUFFER_F_OFFLOAD_UDP_CKSUM);
+ (flags[0] & VNET_BUFFER_F_L4_CHECKSUM_CORRECT) | l4_offload[0];
good_l4_csum[1] =
- flags[1] & (VNET_BUFFER_F_L4_CHECKSUM_CORRECT |
- VNET_BUFFER_F_OFFLOAD_TCP_CKSUM |
- VNET_BUFFER_F_OFFLOAD_UDP_CKSUM);
+ (flags[1] & VNET_BUFFER_F_L4_CHECKSUM_CORRECT) | l4_offload[1];
u32 udp_offset[2] = { };
u8 is_tcp_udp[2];
vnet_buffer (b[1])->sw_if_index[VLIB_TX] != ~0 ?
vnet_buffer (b[1])->sw_if_index[VLIB_TX] :
vnet_buffer (b[1])->ip.fib_index;
+ if (is_receive_dpo)
+ {
+ const receive_dpo_t *rd0, *rd1;
+ rd0 =
+ receive_dpo_get (vnet_buffer (b[0])->ip.adj_index[VLIB_TX]);
+ rd1 =
+ receive_dpo_get (vnet_buffer (b[1])->ip.adj_index[VLIB_TX]);
+ vnet_buffer (b[0])->ip.rx_sw_if_index = rd0->rd_sw_if_index;
+ vnet_buffer (b[1])->ip.rx_sw_if_index = rd1->rd_sw_if_index;
+ }
+ else
+ {
+ vnet_buffer (b[0])->ip.rx_sw_if_index =
+ vnet_buffer (b[0])->ip.adj_index[VLIB_RX];
+ vnet_buffer (b[1])->ip.rx_sw_if_index =
+ vnet_buffer (b[1])->ip.adj_index[VLIB_RX];
+ }
} /* head_of_feature_arc */
next[0] = lm->local_next_by_ip_protocol[ip[0]->protocol];
u8 type = lm->builtin_protocol_by_ip_protocol[ip->protocol];
u32 flags = b[0]->flags;
- u32 good_l4_csum =
- flags & (VNET_BUFFER_F_L4_CHECKSUM_CORRECT |
- VNET_BUFFER_F_OFFLOAD_TCP_CKSUM |
- VNET_BUFFER_F_OFFLOAD_UDP_CKSUM);
+ vnet_buffer_oflags_t oflags = vnet_buffer (b[0])->oflags;
+
+ u32 l4_offload = (flags & VNET_BUFFER_F_OFFLOAD) &&
+ (oflags & (VNET_BUFFER_OFFLOAD_F_TCP_CKSUM |
+ VNET_BUFFER_OFFLOAD_F_UDP_CKSUM));
+
+ u32 good_l4_csum =
+ (flags & VNET_BUFFER_F_L4_CHECKSUM_CORRECT) | l4_offload;
u32 udp_offset;
i16 len_diff = 0;
u8 is_tcp_udp = ip6_next_proto_is_tcp_udp (b[0], ip, &udp_offset);
good_l4_csum |= type == IP_BUILTIN_PROTOCOL_UNKNOWN;
len_diff = type == IP_BUILTIN_PROTOCOL_UDP ? len_diff : 0;
- u8 need_csum = type != IP_BUILTIN_PROTOCOL_UNKNOWN && !good_l4_csum
- && !(flags & VNET_BUFFER_F_L4_CHECKSUM_COMPUTED);
+ u8 need_csum = type != IP_BUILTIN_PROTOCOL_UNKNOWN &&
+ !good_l4_csum &&
+ !(flags & VNET_BUFFER_F_L4_CHECKSUM_COMPUTED);
if (PREDICT_FALSE (need_csum))
{
flags = ip6_tcp_udp_icmp_validate_checksum (vm, b[0]);
error = len_diff < 0 ? IP6_ERROR_UDP_LENGTH : error;
-
STATIC_ASSERT (IP6_ERROR_UDP_CHECKSUM + IP_BUILTIN_PROTOCOL_UDP ==
IP6_ERROR_UDP_CHECKSUM,
"Wrong IP6 errors constants");
vnet_buffer (b[0])->sw_if_index[VLIB_TX] != ~0 ?
vnet_buffer (b[0])->sw_if_index[VLIB_TX] :
vnet_buffer (b[0])->ip.fib_index;
+ if (is_receive_dpo)
+ {
+ receive_dpo_t *rd;
+ rd = receive_dpo_get (vnet_buffer (b[0])->ip.adj_index[VLIB_TX]);
+ vnet_buffer (b[0])->ip.rx_sw_if_index = rd->rd_sw_if_index;
+ }
+ else
+ vnet_buffer (b[0])->ip.rx_sw_if_index =
+ vnet_buffer (b[0])->ip.adj_index[VLIB_RX];
} /* head_of_feature_arc */
next[0] = lm->local_next_by_ip_protocol[ip->protocol];
VLIB_NODE_FN (ip6_local_node) (vlib_main_t * vm, vlib_node_runtime_t * node,
vlib_frame_t * frame)
{
- return ip6_local_inline (vm, node, frame, 1 /* head of feature arc */ );
+ return ip6_local_inline (vm, node, frame, 1 /* head of feature arc */,
+ 0 /* ip6_local_inline */);
}
-/* *INDENT-OFF* */
VLIB_REGISTER_NODE (ip6_local_node) =
{
.name = "ip6-local",
[IP_LOCAL_NEXT_REASSEMBLY] = "ip6-full-reassembly",
},
};
-/* *INDENT-ON* */
+
+VLIB_NODE_FN (ip6_receive_local_node)
+(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
+{
+ return ip6_local_inline (vm, node, frame, 1 /* head of feature arc */,
+ 1 /* is_receive_dpo */);
+}
+
+VLIB_REGISTER_NODE (ip6_receive_local_node) = {
+ .name = "ip6-receive",
+ .vector_size = sizeof (u32),
+ .format_trace = format_ip6_forward_next_trace,
+ .sibling_of = "ip6-local"
+};
VLIB_NODE_FN (ip6_local_end_of_arc_node) (vlib_main_t * vm,
vlib_node_runtime_t * node,
vlib_frame_t * frame)
{
- return ip6_local_inline (vm, node, frame, 0 /* head of feature arc */ );
+ return ip6_local_inline (vm, node, frame, 0 /* head of feature arc */,
+ 0 /* ip6_local_inline */);
}
-/* *INDENT-OFF* */
VLIB_REGISTER_NODE (ip6_local_end_of_arc_node) = {
.name = "ip6-local-end-of-arc",
.vector_size = sizeof (u32),
.node_name = "ip6-local-end-of-arc",
.runs_before = 0, /* not before any other features */
};
-/* *INDENT-ON* */
#ifdef CLIB_MARCH_VARIANT
extern vlib_node_registration_t ip6_local_node;
vlib_prefetch_buffer_header (p2, LOAD);
vlib_prefetch_buffer_header (p3, LOAD);
- CLIB_PREFETCH (p2->pre_data, 32, STORE);
- CLIB_PREFETCH (p3->pre_data, 32, STORE);
+ clib_prefetch_store (p2->pre_data);
+ clib_prefetch_store (p3->pre_data);
CLIB_PREFETCH (p2->data, sizeof (ip0[0]), STORE);
CLIB_PREFETCH (p3->data, sizeof (ip0[0]), STORE);
if (p1->flags & VNET_BUFFER_F_GSO)
ip1_len = gso_mtu_sz (p1);
-
-
ip6_mtu_check (p0, ip0_len,
adj0[0].rewrite_header.max_l3_packet_bytes,
is_locally_originated0, &next0, is_midchain,
adj1[0].rewrite_header.max_l3_packet_bytes,
is_locally_originated1, &next1, is_midchain,
&error1);
-
/* Don't adjust the buffer for hop count issue; icmp-error node
* wants to see the IP header */
if (PREDICT_TRUE (error0 == IP6_ERROR_NONE))
{
p0->current_data -= rw_len0;
p0->current_length += rw_len0;
-
tx_sw_if_index0 = adj0[0].rewrite_header.sw_if_index;
vnet_buffer (p0)->sw_if_index[VLIB_TX] = tx_sw_if_index0;
next0 = adj0[0].rewrite_header.next_index;
-
if (PREDICT_FALSE
(adj0[0].rewrite_header.flags & VNET_REWRITE_HAS_FEATURES))
vnet_feature_arc_start_w_cfg_index
adj0[0].rewrite_header.max_l3_packet_bytes,
is_locally_originated0, &next0, is_midchain,
&error0);
-
/* Don't adjust the buffer for hop count issue; icmp-error node
* wants to see the IP header */
if (PREDICT_TRUE (error0 == IP6_ERROR_NONE))
ip6_hop_by_hop_option_t *opt0, *limit0;
ip6_hop_by_hop_main_t *hm = &ip6_hop_by_hop_main;
u8 type0;
-
s = format (s, "IP6_HOP_BY_HOP: next protocol %d len %d total %d",
hbh0->protocol, (hbh0->length + 1) << 3, total_len);
}
else
{
- s =
- format (s, "\n unrecognized option %d length %d", type0,
- opt0->length);
+ s = format (s, "\n unrecognized option %d length %d", type0,
+ opt0->length);
}
opt0 =
(ip6_hop_by_hop_option_t *) (((u8 *) opt0) + opt0->length +
}
else
{
- s =
- format (s, "\n unrecognized option %d length %d", type0,
- opt0->length);
+ s = format (s, "\n unrecognized option %d length %d", type0,
+ opt0->length);
}
opt0 =
(ip6_hop_by_hop_option_t *) (((u8 *) opt0) + opt0->length +
VLIB_INIT_FUNCTION (ip6_lookup_init);
-#ifndef CLIB_MARCH_VARIANT
-int
-vnet_set_ip6_flow_hash (u32 table_id, u32 flow_hash_config)
-{
- u32 fib_index;
-
- fib_index = fib_table_find (FIB_PROTOCOL_IP6, table_id);
-
- if (~0 == fib_index)
- return VNET_API_ERROR_NO_SUCH_FIB;
-
- fib_table_set_flow_hash_config (fib_index, FIB_PROTOCOL_IP6,
- flow_hash_config);
-
- return 0;
-}
-#endif
-
static clib_error_t *
set_ip6_flow_hash_command_fn (vlib_main_t * vm,
unformat_input_t * input,
{
if (unformat (input, "table %d", &table_id))
matched = 1;
-#define _(a,v) \
- else if (unformat (input, #a)) { flow_hash_config |= v; matched=1;}
+#define _(a, b, v) \
+ else if (unformat (input, #a)) \
+ { \
+ flow_hash_config |= v; \
+ matched = 1; \
+ }
foreach_flow_hash_bit
#undef _
else
return clib_error_return (0, "unknown input `%U'",
format_unformat_error, input);
- rv = vnet_set_ip6_flow_hash (table_id, flow_hash_config);
+ rv = ip_flow_hash_set (AF_IP6, table_id, flow_hash_config);
switch (rv)
{
case 0:
* @endparblock
?*/
/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (set_ip6_flow_hash_command, static) =
-{
+VLIB_CLI_COMMAND (set_ip6_flow_hash_command, static) = {
.path = "set ip6 flow-hash",
- .short_help =
- "set ip6 flow-hash table <table-id> [src] [dst] [sport] [dport] [proto] [reverse]",
+ .short_help = "set ip6 flow-hash table <table-id> [src] [dst] [sport] "
+ "[dport] [proto] [reverse] [flowlabel]",
.function = set_ip6_flow_hash_command_fn,
};
/* *INDENT-ON* */
#ifndef CLIB_MARCH_VARIANT
int
-vnet_set_ip6_classify_intfc (vlib_main_t * vm, u32 sw_if_index,
- u32 table_index)
+vnet_set_ip6_classify_intfc (vlib_main_t *vm, u32 sw_if_index, u32 table_index)
{
vnet_main_t *vnm = vnet_get_main ();
vnet_interface_main_t *im = &vnm->interface_main;
fib_index = fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP4,
sw_if_index);
-
-
if (table_index != (u32) ~ 0)
{
dpo_id_t dpo = DPO_INVALID;
-
dpo_set (&dpo,
DPO_CLASSIFY,
DPO_PROTO_IP6,
classify_dpo_create (DPO_PROTO_IP6, table_index));
-
fib_table_entry_special_dpo_add (fib_index,
&pfx,
FIB_SOURCE_CLASSIFY,