aboutsummaryrefslogtreecommitdiffstats
path: root/src/vnet/ip/ip6_forward.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/vnet/ip/ip6_forward.c')
-rw-r--r--src/vnet/ip/ip6_forward.c185
1 files changed, 94 insertions, 91 deletions
diff --git a/src/vnet/ip/ip6_forward.c b/src/vnet/ip/ip6_forward.c
index ba616ebc7c7..48fb633fd32 100644
--- a/src/vnet/ip/ip6_forward.c
+++ b/src/vnet/ip/ip6_forward.c
@@ -48,6 +48,7 @@
#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>
@@ -70,7 +71,6 @@ ip6_add_interface_prefix_routes (ip6_main_t * im,
ip_lookup_main_t *lm = &im->lookup_main;
ip_interface_prefix_t *if_prefix;
- /* *INDENT-OFF* */
ip_interface_prefix_key_t key = {
.prefix = {
.fp_len = address_length,
@@ -84,7 +84,6 @@ ip6_add_interface_prefix_routes (ip6_main_t * im,
},
.sw_if_index = sw_if_index,
};
- /* *INDENT-ON* */
/* If prefix already set on interface, just increment ref count & return */
if_prefix = ip_get_interface_prefix (lm, &key);
@@ -177,7 +176,6 @@ ip6_del_interface_prefix_routes (ip6_main_t * im,
ip_lookup_main_t *lm = &im->lookup_main;
ip_interface_prefix_t *if_prefix;
- /* *INDENT-OFF* */
ip_interface_prefix_key_t key = {
.prefix = {
.fp_len = address_length,
@@ -191,13 +189,12 @@ ip6_del_interface_prefix_routes (ip6_main_t * im,
},
.sw_if_index = sw_if_index,
};
- /* *INDENT-ON* */
if_prefix = ip_get_interface_prefix (lm, &key);
if (!if_prefix)
{
clib_warning ("Prefix not found while deleting %U",
- format_ip4_address_and_length, address, address_length);
+ format_ip6_address_and_length, address, address_length);
return;
}
@@ -282,7 +279,6 @@ ip6_interface_first_address (ip6_main_t * im, u32 sw_if_index)
ip_interface_address_t *ia = 0;
ip6_address_t *result = 0;
- /* *INDENT-OFF* */
foreach_ip_interface_address (lm, ia, sw_if_index,
1 /* honor unnumbered */,
({
@@ -290,7 +286,6 @@ ip6_interface_first_address (ip6_main_t * im, u32 sw_if_index)
result = a;
break;
}));
- /* *INDENT-ON* */
return result;
}
@@ -308,11 +303,11 @@ ip6_add_del_interface_address (vlib_main_t * vm,
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))
@@ -354,14 +349,10 @@ ip6_add_del_interface_address (vlib_main_t * vm,
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);
- /* *INDENT-OFF* */
if (!is_del)
{
/* When adding an address check that it does not conflict
@@ -419,7 +410,6 @@ ip6_add_del_interface_address (vlib_main_t * vm,
}
}
}
- /* *INDENT-ON* */
if_address_index = ip_interface_address_find (lm, addr_fib, address_length);
@@ -531,9 +521,6 @@ ip6_sw_interface_admin_up_down (vnet_main_t * vnm, u32 sw_if_index, u32 flags)
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);
@@ -542,7 +529,6 @@ ip6_sw_interface_admin_up_down (vnet_main_t * vnm, u32 sw_if_index, u32 flags)
fib_index = vec_elt (im->fib_index_by_sw_if_index, sw_if_index);
- /* *INDENT-OFF* */
foreach_ip_interface_address (&im->lookup_main, ia, sw_if_index,
0 /* honor unnumbered */,
({
@@ -555,7 +541,6 @@ ip6_sw_interface_admin_up_down (vnet_main_t * vnm, u32 sw_if_index, u32 flags)
ip6_del_interface_routes (sw_if_index, im, fib_index,
a, ia->address_length);
}));
- /* *INDENT-ON* */
return 0;
}
@@ -563,7 +548,6 @@ ip6_sw_interface_admin_up_down (vnet_main_t * vnm, u32 sw_if_index, u32 flags)
VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION (ip6_sw_interface_admin_up_down);
/* Built-in ip6 unicast rx feature path definition */
-/* *INDENT-OFF* */
VNET_FEATURE_ARC_INIT (ip6_unicast, static) =
{
.arc_name = "ip6-unicast",
@@ -688,17 +672,22 @@ VNET_FEATURE_INIT (ip6_interface_output, static) = {
.node_name = "interface-output",
.runs_before = 0, /* not before any other features */
};
-/* *INDENT-ON* */
static clib_error_t *
ip6_sw_interface_add_del (vnet_main_t * vnm, u32 sw_if_index, u32 is_add)
{
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;
@@ -708,14 +697,21 @@ ip6_sw_interface_add_del (vnet_main_t * vnm, u32 sw_if_index, u32 is_add)
vlib_main_t *vm = vlib_get_main ();
vnet_sw_interface_update_unnumbered (sw_if_index, ~0, 0);
- /* *INDENT-OFF* */
foreach_ip_interface_address (lm6, ia, sw_if_index, 0,
({
address = ip_interface_address_get_address (lm6, ia);
ip6_add_del_interface_address(vm, sw_if_index, address, ia->address_length, 1);
}));
- /* *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,
@@ -738,7 +734,6 @@ VLIB_NODE_FN (ip6_lookup_node) (vlib_main_t * vm,
static u8 *format_ip6_lookup_trace (u8 * s, va_list * args);
-/* *INDENT-OFF* */
VLIB_REGISTER_NODE (ip6_lookup_node) =
{
.name = "ip6-lookup",
@@ -747,7 +742,6 @@ VLIB_REGISTER_NODE (ip6_lookup_node) =
.n_next_nodes = IP6_LOOKUP_N_NEXT,
.next_nodes = IP6_LOOKUP_NEXT_NODES,
};
-/* *INDENT-ON* */
VLIB_NODE_FN (ip6_load_balance_node) (vlib_main_t * vm,
vlib_node_runtime_t * node,
@@ -925,7 +919,6 @@ VLIB_NODE_FN (ip6_load_balance_node) (vlib_main_t * vm,
return frame->n_vectors;
}
-/* *INDENT-OFF* */
VLIB_REGISTER_NODE (ip6_load_balance_node) =
{
.name = "ip6-load-balance",
@@ -933,7 +926,6 @@ VLIB_REGISTER_NODE (ip6_load_balance_node) =
.sibling_of = "ip6-lookup",
.format_trace = format_ip6_lookup_trace,
};
-/* *INDENT-ON* */
typedef struct
{
@@ -956,8 +948,7 @@ format_ip6_forward_next_trace (u8 * s, va_list * args)
ip6_forward_next_trace_t *t = va_arg (*args, ip6_forward_next_trace_t *);
u32 indent = format_get_indent (s);
- s = format (s, "%Ufib:%d adj:%d flow:%d",
- format_white_space, indent,
+ s = format (s, "%Ufib:%d adj:%d flow:0x%08x", format_white_space, indent,
t->fib_index, t->adj_index, t->flow_hash);
s = format (s, "\n%U%U",
format_white_space, indent,
@@ -1217,23 +1208,17 @@ always_inline u8
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* */
static_always_inline u8
ip6_tcp_udp_icmp_bad_length (vlib_main_t * vm, vlib_buffer_t * p0)
@@ -1270,7 +1255,7 @@ ip6_tcp_udp_icmp_bad_length (vlib_main_t * vm, vlib_buffer_t * p0)
}
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;
@@ -1278,10 +1263,10 @@ ip6_tcp_udp_icmp_bad_length (vlib_main_t * vm, vlib_buffer_t * p0)
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;
@@ -1313,7 +1298,7 @@ ip6_local_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
vlib_prefetch_buffer_data (b[3], LOAD);
}
- ip6_error_t error[2];
+ vl_counter_ip6_enum_t error[2];
error[0] = IP6_ERROR_UNKNOWN_PROTOCOL;
error[1] = IP6_ERROR_UNKNOWN_PROTOCOL;
@@ -1469,6 +1454,23 @@ ip6_local_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
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;
+
+ vnet_buffer (b[0])->ip.rx_sw_if_index =
+ vnet_buffer (b[0])->sw_if_index[VLIB_RX];
+ vnet_buffer (b[1])->ip.rx_sw_if_index =
+ vnet_buffer (b[1])->sw_if_index[VLIB_RX];
+ 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]);
+ if (rd0->rd_sw_if_index != ~0)
+ vnet_buffer (b[0])->ip.rx_sw_if_index = rd0->rd_sw_if_index;
+ if (rd1->rd_sw_if_index != ~0)
+ vnet_buffer (b[1])->ip.rx_sw_if_index = rd1->rd_sw_if_index;
+ }
} /* head_of_feature_arc */
next[0] = lm->local_next_by_ip_protocol[ip[0]->protocol];
@@ -1490,16 +1492,16 @@ ip6_local_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
{
u32 next32 = next[0];
vnet_feature_arc_start (arc_index,
- vnet_buffer (b[0])->sw_if_index
- [VLIB_RX], &next32, b[0]);
+ vnet_buffer (b[0])->ip.rx_sw_if_index,
+ &next32, b[0]);
next[0] = next32;
}
if (PREDICT_TRUE (ip6_unknown[1]))
{
u32 next32 = next[1];
vnet_feature_arc_start (arc_index,
- vnet_buffer (b[1])->sw_if_index
- [VLIB_RX], &next32, b[1]);
+ vnet_buffer (b[1])->ip.rx_sw_if_index,
+ &next32, b[1]);
next[1] = next32;
}
}
@@ -1596,6 +1598,16 @@ ip6_local_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
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;
+
+ vnet_buffer (b[0])->ip.rx_sw_if_index =
+ vnet_buffer (b[0])->sw_if_index[VLIB_RX];
+ if (is_receive_dpo)
+ {
+ receive_dpo_t *rd;
+ rd = receive_dpo_get (vnet_buffer (b[0])->ip.adj_index[VLIB_TX]);
+ if (rd->rd_sw_if_index != ~0)
+ vnet_buffer (b[0])->ip.rx_sw_if_index = rd->rd_sw_if_index;
+ }
} /* head_of_feature_arc */
next[0] = lm->local_next_by_ip_protocol[ip->protocol];
@@ -1610,8 +1622,8 @@ ip6_local_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
{
u32 next32 = next[0];
vnet_feature_arc_start (arc_index,
- vnet_buffer (b[0])->sw_if_index
- [VLIB_RX], &next32, b[0]);
+ vnet_buffer (b[0])->ip.rx_sw_if_index,
+ &next32, b[0]);
next[0] = next32;
}
}
@@ -1629,15 +1641,17 @@ ip6_local_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
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",
.vector_size = sizeof (u32),
.format_trace = format_ip6_forward_next_trace,
+ .n_errors = IP6_N_ERROR,
+ .error_counters = ip6_error_counters,
.n_next_nodes = IP_LOCAL_N_NEXT,
.next_nodes =
{
@@ -1645,19 +1659,32 @@ VLIB_REGISTER_NODE (ip6_local_node) =
[IP_LOCAL_NEXT_PUNT] = "ip6-punt",
[IP_LOCAL_NEXT_UDP_LOOKUP] = "ip6-udp-lookup",
[IP_LOCAL_NEXT_ICMP] = "ip6-icmp-input",
- [IP_LOCAL_NEXT_REASSEMBLY] = "ip6-full-reassembly",
+ [IP_LOCAL_NEXT_REASSEMBLY] = "ip6-local-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),
@@ -1671,7 +1698,6 @@ VNET_FEATURE_INIT (ip6_local_end_of_arc, static) = {
.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;
@@ -1944,13 +1970,6 @@ ip6_rewrite_inline_with_gso (vlib_main_t * vm,
if (is_midchain)
{
- /* before we paint on the next header, update the L4
- * checksums if required, since there's no offload on a tunnel */
- vnet_calc_checksums_inline (vm, p0, 0 /* is_ip4 */ ,
- 1 /* is_ip6 */ );
- vnet_calc_checksums_inline (vm, p1, 0 /* is_ip4 */ ,
- 1 /* is_ip6 */ );
-
/* Guess we are only writing on ipv6 header. */
vnet_rewrite_two_headers (adj0[0], adj1[0],
ip0, ip1, sizeof (ip6_header_t));
@@ -2044,9 +2063,6 @@ ip6_rewrite_inline_with_gso (vlib_main_t * vm,
if (is_midchain)
{
- vnet_calc_checksums_inline (vm, p0, 0 /* is_ip4 */ ,
- 1 /* is_ip6 */ );
-
/* Guess we are only writing on ip6 header. */
vnet_rewrite_one_header (adj0[0], ip0, sizeof (ip6_header_t));
}
@@ -2196,14 +2212,12 @@ VLIB_NODE_FN (ip6_mcast_midchain_node) (vlib_main_t * vm,
return ip6_rewrite_inline (vm, node, frame, 0, 1, 1);
}
-/* *INDENT-OFF* */
-VLIB_REGISTER_NODE (ip6_midchain_node) =
-{
+VLIB_REGISTER_NODE (ip6_midchain_node) = {
.name = "ip6-midchain",
.vector_size = sizeof (u32),
.format_trace = format_ip6_forward_next_trace,
.sibling_of = "ip6-rewrite",
- };
+};
VLIB_REGISTER_NODE (ip6_rewrite_node) =
{
@@ -2244,7 +2258,6 @@ VLIB_REGISTER_NODE (ip6_mcast_midchain_node) =
.sibling_of = "ip6-rewrite",
};
-/* *INDENT-ON* */
/*
* Hop-by-Hop handling
@@ -2258,7 +2271,6 @@ _(PROCESSED, "pkts with ip6 hop-by-hop options") \
_(FORMAT, "incorrectly formatted hop-by-hop options") \
_(UNKNOWN_OPTION, "unknown ip6 hop-by-hop options")
-/* *INDENT-OFF* */
typedef enum
{
#define _(sym,str) IP6_HOP_BY_HOP_ERROR_##sym,
@@ -2266,7 +2278,6 @@ typedef enum
#undef _
IP6_HOP_BY_HOP_N_ERROR,
} ip6_hop_by_hop_error_t;
-/* *INDENT-ON* */
/*
* Primary h-b-h handler trace support
@@ -2693,7 +2704,6 @@ VLIB_NODE_FN (ip6_hop_by_hop_node) (vlib_main_t * vm,
return frame->n_vectors;
}
-/* *INDENT-OFF* */
VLIB_REGISTER_NODE (ip6_hop_by_hop_node) =
{
.name = "ip6-hop-by-hop",
@@ -2705,7 +2715,6 @@ VLIB_REGISTER_NODE (ip6_hop_by_hop_node) =
.error_strings = ip6_hop_by_hop_error_strings,
.n_next_nodes = 0,
};
-/* *INDENT-ON* */
static clib_error_t *
ip6_hop_by_hop_init (vlib_main_t * vm)
@@ -2957,14 +2966,12 @@ set_ip6_flow_hash_command_fn (vlib_main_t * vm,
* @cliexend
* @endparblock
?*/
-/* *INDENT-OFF* */
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] [flowlabel]",
.function = set_ip6_flow_hash_command_fn,
};
-/* *INDENT-ON* */
static clib_error_t *
show_ip6_local_command_fn (vlib_main_t * vm,
@@ -3005,14 +3012,12 @@ show_ip6_local_command_fn (vlib_main_t * vm,
* 115
* @cliexend
?*/
-/* *INDENT-OFF* */
VLIB_CLI_COMMAND (show_ip6_local, static) =
{
.path = "show ip6 local",
.function = show_ip6_local_command_fn,
.short_help = "show ip6 local",
};
-/* *INDENT-ON* */
#ifndef CLIB_MARCH_VARIANT
int
@@ -3124,7 +3129,6 @@ set_ip6_classify_command_fn (vlib_main_t * vm,
* Example of how to assign a classification table to an interface:
* @cliexcmd{set ip6 classify intfc GigabitEthernet2/0/0 table-index 1}
?*/
-/* *INDENT-OFF* */
VLIB_CLI_COMMAND (set_ip6_classify_command, static) =
{
.path = "set ip6 classify",
@@ -3132,7 +3136,6 @@ VLIB_CLI_COMMAND (set_ip6_classify_command, static) =
"set ip6 classify intfc <interface> table-index <classify-idx>",
.function = set_ip6_classify_command_fn,
};
-/* *INDENT-ON* */
/*
* fd.io coding-style-patch-verification: ON