aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKlement Sekera <ksekera@cisco.com>2021-12-14 18:25:11 +0000
committerOle Tr�an <otroan@employees.org>2022-01-31 15:07:58 +0000
commit01c1fa41f04fbc584165806d3f785cfbbd62cedc (patch)
treefeda9d118e6555ebd5b15b03da49f5b3fa13e1fe
parentcf1e8c1eeab1dc07d69210f410a086d7ae4eae90 (diff)
ip: reassembly - add a way to disable for forus
Add API to disable full reassembly of "forus" packets. Mark packets passing through ip[4|6]-local nodes with a new buffer flag and check for that flag in reassembly. Enable IP6 "forus" full reassembly by default to be consistent with existing IP4 setting. Type: improvement Change-Id: I7067792fcd4304182654237968e4c4d9293c6143 Signed-off-by: Klement Sekera <ksekera@cisco.com>
-rw-r--r--src/vnet/ip/ip.api24
-rw-r--r--src/vnet/ip/ip4_forward.c3
-rw-r--r--src/vnet/ip/ip4_input.c1
-rw-r--r--src/vnet/ip/ip4_input.h1
-rw-r--r--src/vnet/ip/ip6_forward.c2
-rw-r--r--src/vnet/ip/ip_api.c24
-rw-r--r--src/vnet/ip/ip_test.c18
-rw-r--r--src/vnet/ip/reass/ip4_full_reass.c122
-rw-r--r--src/vnet/ip/reass/ip4_full_reass.h3
-rw-r--r--src/vnet/ip/reass/ip6_full_reass.c139
-rw-r--r--src/vnet/ip/reass/ip6_full_reass.h2
-rw-r--r--test/Makefile4
-rw-r--r--test/test_reassembly.py109
13 files changed, 384 insertions, 68 deletions
diff --git a/src/vnet/ip/ip.api b/src/vnet/ip/ip.api
index ca1e2008e4f..cd180981773 100644
--- a/src/vnet/ip/ip.api
+++ b/src/vnet/ip/ip.api
@@ -836,6 +836,30 @@ autoreply define ip_reassembly_enable_disable
vl_api_ip_reass_type_t type;
};
+/** enable/disable full reassembly of packets aimed at our addresses */
+autoreply define ip_local_reass_enable_disable
+{
+ u32 client_index;
+ u32 context;
+ bool enable_ip4;
+ bool enable_ip6;
+};
+
+/** get status of local reassembly */
+define ip_local_reass_get
+{
+ u32 client_index;
+ u32 context;
+};
+
+define ip_local_reass_get_reply
+{
+ u32 context;
+ i32 retval;
+ bool ip4_is_enabled;
+ bool ip6_is_enabled;
+};
+
/**
@brief Set a Path MTU value. i.e. a MTU value for a given neighbour.
The neighbour can be described as attached (w/ interface and next-hop)
diff --git a/src/vnet/ip/ip4_forward.c b/src/vnet/ip/ip4_forward.c
index de8e8e8538f..4d0638209e5 100644
--- a/src/vnet/ip/ip4_forward.c
+++ b/src/vnet/ip/ip4_forward.c
@@ -61,6 +61,7 @@
#include <vnet/ip/ip4_forward.h>
#include <vnet/interface_output.h>
#include <vnet/classify/vnet_classify.h>
+#include <vnet/ip/reass/ip4_full_reass.h>
/** @brief IPv4 lookup node.
@node ip4-lookup
@@ -1880,7 +1881,7 @@ VLIB_REGISTER_NODE (ip4_local_node) =
[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-full-reassembly",
+ [IP_LOCAL_NEXT_REASSEMBLY] = "ip4-local-full-reassembly",
},
};
diff --git a/src/vnet/ip/ip4_input.c b/src/vnet/ip/ip4_input.c
index 3b3edf9fca7..0e8d22e188b 100644
--- a/src/vnet/ip/ip4_input.c
+++ b/src/vnet/ip/ip4_input.c
@@ -399,7 +399,6 @@ VLIB_REGISTER_NODE (ip4_input_node) = {
[IP4_INPUT_NEXT_LOOKUP] = "ip4-lookup",
[IP4_INPUT_NEXT_LOOKUP_MULTICAST] = "ip4-mfib-forward-lookup",
[IP4_INPUT_NEXT_ICMP_ERROR] = "ip4-icmp-error",
- [IP4_INPUT_NEXT_REASSEMBLY] = "ip4-full-reassembly",
},
.format_buffer = format_ip4_header,
diff --git a/src/vnet/ip/ip4_input.h b/src/vnet/ip/ip4_input.h
index 53948d60266..57aef0bf77a 100644
--- a/src/vnet/ip/ip4_input.h
+++ b/src/vnet/ip/ip4_input.h
@@ -52,7 +52,6 @@ typedef enum
IP4_INPUT_NEXT_LOOKUP,
IP4_INPUT_NEXT_LOOKUP_MULTICAST,
IP4_INPUT_NEXT_ICMP_ERROR,
- IP4_INPUT_NEXT_REASSEMBLY,
IP4_INPUT_N_NEXT,
} ip4_input_next_t;
diff --git a/src/vnet/ip/ip6_forward.c b/src/vnet/ip/ip6_forward.c
index ce165e0e2e4..b876b6f2a78 100644
--- a/src/vnet/ip/ip6_forward.c
+++ b/src/vnet/ip/ip6_forward.c
@@ -1677,7 +1677,7 @@ 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",
},
};
diff --git a/src/vnet/ip/ip_api.c b/src/vnet/ip/ip_api.c
index b1b7ff3a7ae..3ff3a6ce5e0 100644
--- a/src/vnet/ip/ip_api.c
+++ b/src/vnet/ip/ip_api.c
@@ -1875,6 +1875,30 @@ void
REPLY_MACRO (VL_API_IP_REASSEMBLY_ENABLE_DISABLE_REPLY);
}
+void
+vl_api_ip_local_reass_enable_disable_t_handler (
+ vl_api_ip_local_reass_enable_disable_t *mp)
+{
+ vl_api_ip_local_reass_enable_disable_reply_t *rmp;
+ int rv = 0;
+
+ ip4_local_full_reass_enable_disable (mp->enable_ip4);
+ ip6_local_full_reass_enable_disable (mp->enable_ip6);
+
+ REPLY_MACRO (VL_API_IP_LOCAL_REASS_ENABLE_DISABLE_REPLY);
+}
+
+void
+vl_api_ip_local_reass_get_t_handler (vl_api_ip_local_reass_get_t *mp)
+{
+ vl_api_ip_local_reass_get_reply_t *rmp;
+ int rv = 0;
+ REPLY_MACRO2 (VL_API_IP_LOCAL_REASS_GET, {
+ rmp->ip4_is_enabled = ip4_local_full_reass_enabled ();
+ rmp->ip6_is_enabled = ip6_local_full_reass_enabled ();
+ });
+}
+
static walk_rc_t
send_ip_punt_redirect_details (u32 rx_sw_if_index,
const ip_punt_redirect_rx_t * ipr, void *arg)
diff --git a/src/vnet/ip/ip_test.c b/src/vnet/ip/ip_test.c
index f87b47f8912..7c994868d87 100644
--- a/src/vnet/ip/ip_test.c
+++ b/src/vnet/ip/ip_test.c
@@ -1014,6 +1014,24 @@ api_ip_reassembly_enable_disable (vat_main_t *vat)
return -1;
}
+static int
+api_ip_local_reass_enable_disable (vat_main_t *vat)
+{
+ return -1;
+}
+
+static int
+api_ip_local_reass_get (vat_main_t *vat)
+{
+ return -1;
+}
+
+static void
+vl_api_ip_local_reass_get_reply_t_handler (
+ vl_api_ip_local_reass_get_reply_t *mp)
+{
+}
+
static void
vl_api_ip_reassembly_get_reply_t_handler (vl_api_ip_reassembly_get_reply_t *mp)
{
diff --git a/src/vnet/ip/reass/ip4_full_reass.c b/src/vnet/ip/reass/ip4_full_reass.c
index 79f4673a7f5..220117278c0 100644
--- a/src/vnet/ip/reass/ip4_full_reass.c
+++ b/src/vnet/ip/reass/ip4_full_reass.c
@@ -183,11 +183,15 @@ typedef struct
/** Worker handoff */
u32 fq_index;
+ u32 fq_local_index;
u32 fq_feature_index;
u32 fq_custom_index;
// reference count for enabling/disabling feature - per interface
u32 *feature_use_refcount_per_intf;
+
+ // whether local fragmented packets are reassembled or not
+ int is_local_reass_enabled;
} ip4_full_reass_main_t;
extern ip4_full_reass_main_t ip4_full_reass_main;
@@ -219,6 +223,7 @@ typedef enum
RANGE_OVERLAP,
FINALIZE,
HANDOFF,
+ PASSTHROUGH,
} ip4_full_reass_trace_operation_e;
typedef struct
@@ -329,6 +334,9 @@ format_ip4_full_reass_trace (u8 * s, va_list * args)
format (s, "handoff from thread #%u to thread #%u", t->thread_id,
t->thread_id_to);
break;
+ case PASSTHROUGH:
+ s = format (s, "passthrough - not a fragment");
+ break;
}
return s;
}
@@ -1090,8 +1098,9 @@ ip4_full_reass_update (vlib_main_t * vm, vlib_node_runtime_t * node,
}
always_inline uword
-ip4_full_reass_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
- vlib_frame_t * frame, ip4_full_reass_node_type_t type)
+ip4_full_reass_inline (vlib_main_t *vm, vlib_node_runtime_t *node,
+ vlib_frame_t *frame, ip4_full_reass_node_type_t type,
+ bool is_local)
{
u32 *from = vlib_frame_vector_args (frame);
u32 n_left_from, n_left_to_next, *to_next, next_index;
@@ -1127,8 +1136,17 @@ ip4_full_reass_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
{
next0 = vnet_buffer (b0)->ip.reass.next_index;
}
+ ip4_full_reass_add_trace (vm, node, NULL, bi0, PASSTHROUGH, 0,
+ ~0);
+ goto packet_enqueue;
+ }
+
+ if (is_local && !rm->is_local_reass_enabled)
+ {
+ next0 = IP4_FULL_REASS_NEXT_DROP;
goto packet_enqueue;
}
+
const u32 fragment_first = ip4_get_fragment_offset_bytes (ip0);
const u32 fragment_length =
clib_net_to_host_u16 (ip0->length) - ip4_header_bytes (ip0);
@@ -1269,7 +1287,7 @@ VLIB_NODE_FN (ip4_full_reass_node) (vlib_main_t * vm,
vlib_node_runtime_t * node,
vlib_frame_t * frame)
{
- return ip4_full_reass_inline (vm, node, frame, NORMAL);
+ return ip4_full_reass_inline (vm, node, frame, NORMAL, false /* is_local */);
}
VLIB_REGISTER_NODE (ip4_full_reass_node) = {
@@ -1288,11 +1306,34 @@ VLIB_REGISTER_NODE (ip4_full_reass_node) = {
},
};
+VLIB_NODE_FN (ip4_local_full_reass_node)
+(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
+{
+ return ip4_full_reass_inline (vm, node, frame, NORMAL, true /* is_local */);
+}
+
+VLIB_REGISTER_NODE (ip4_local_full_reass_node) = {
+ .name = "ip4-local-full-reassembly",
+ .vector_size = sizeof (u32),
+ .format_trace = format_ip4_full_reass_trace,
+ .n_errors = ARRAY_LEN (ip4_full_reass_error_strings),
+ .error_strings = ip4_full_reass_error_strings,
+ .n_next_nodes = IP4_FULL_REASS_N_NEXT,
+ .next_nodes =
+ {
+ [IP4_FULL_REASS_NEXT_INPUT] = "ip4-input",
+ [IP4_FULL_REASS_NEXT_DROP] = "ip4-drop",
+ [IP4_FULL_REASS_NEXT_HANDOFF] = "ip4-local-full-reassembly-handoff",
+
+ },
+};
+
VLIB_NODE_FN (ip4_full_reass_node_feature) (vlib_main_t * vm,
vlib_node_runtime_t * node,
vlib_frame_t * frame)
{
- return ip4_full_reass_inline (vm, node, frame, FEATURE);
+ return ip4_full_reass_inline (vm, node, frame, FEATURE,
+ false /* is_local */);
}
VLIB_REGISTER_NODE (ip4_full_reass_node_feature) = {
@@ -1322,7 +1363,7 @@ VLIB_NODE_FN (ip4_full_reass_node_custom) (vlib_main_t * vm,
vlib_node_runtime_t * node,
vlib_frame_t * frame)
{
- return ip4_full_reass_inline (vm, node, frame, CUSTOM);
+ return ip4_full_reass_inline (vm, node, frame, CUSTOM, false /* is_local */);
}
VLIB_REGISTER_NODE (ip4_full_reass_node_custom) = {
@@ -1495,12 +1536,16 @@ ip4_full_reass_init_function (vlib_main_t * vm)
rm->ip4_drop_idx = node->index;
rm->fq_index = vlib_frame_queue_main_init (ip4_full_reass_node.index, 0);
+ rm->fq_local_index =
+ vlib_frame_queue_main_init (ip4_local_full_reass_node.index, 0);
rm->fq_feature_index =
vlib_frame_queue_main_init (ip4_full_reass_node_feature.index, 0);
rm->fq_custom_index =
vlib_frame_queue_main_init (ip4_full_reass_node_custom.index, 0);
rm->feature_use_refcount_per_intf = NULL;
+ rm->is_local_reass_enabled = 1;
+
return error;
}
@@ -1745,10 +1790,10 @@ format_ip4_full_reass_handoff_trace (u8 * s, va_list * args)
}
always_inline uword
-ip4_full_reass_handoff_node_inline (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- vlib_frame_t * frame,
- ip4_full_reass_node_type_t type)
+ip4_full_reass_handoff_node_inline (vlib_main_t *vm, vlib_node_runtime_t *node,
+ vlib_frame_t *frame,
+ ip4_full_reass_node_type_t type,
+ bool is_local)
{
ip4_full_reass_main_t *rm = &ip4_full_reass_main;
@@ -1767,7 +1812,14 @@ ip4_full_reass_handoff_node_inline (vlib_main_t * vm,
switch (type)
{
case NORMAL:
- fq_index = rm->fq_index;
+ if (is_local)
+ {
+ fq_index = rm->fq_local_index;
+ }
+ else
+ {
+ fq_index = rm->fq_index;
+ }
break;
case FEATURE:
fq_index = rm->fq_feature_index;
@@ -1777,7 +1829,6 @@ ip4_full_reass_handoff_node_inline (vlib_main_t * vm,
break;
default:
clib_warning ("Unexpected `type' (%d)!", type);
- ASSERT (0);
}
while (n_left_from > 0)
@@ -1811,7 +1862,8 @@ VLIB_NODE_FN (ip4_full_reass_handoff_node) (vlib_main_t * vm,
vlib_node_runtime_t * node,
vlib_frame_t * frame)
{
- return ip4_full_reass_handoff_node_inline (vm, node, frame, NORMAL);
+ return ip4_full_reass_handoff_node_inline (vm, node, frame, NORMAL,
+ false /* is_local */);
}
@@ -1829,13 +1881,34 @@ VLIB_REGISTER_NODE (ip4_full_reass_handoff_node) = {
},
};
+VLIB_NODE_FN (ip4_local_full_reass_handoff_node)
+(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
+{
+ return ip4_full_reass_handoff_node_inline (vm, node, frame, NORMAL,
+ true /* is_local */);
+}
+
+VLIB_REGISTER_NODE (ip4_local_full_reass_handoff_node) = {
+ .name = "ip4-local-full-reassembly-handoff",
+ .vector_size = sizeof (u32),
+ .n_errors = ARRAY_LEN(ip4_full_reass_handoff_error_strings),
+ .error_strings = ip4_full_reass_handoff_error_strings,
+ .format_trace = format_ip4_full_reass_handoff_trace,
+
+ .n_next_nodes = 1,
+
+ .next_nodes = {
+ [0] = "error-drop",
+ },
+};
VLIB_NODE_FN (ip4_full_reass_feature_handoff_node) (vlib_main_t * vm,
vlib_node_runtime_t *
node,
vlib_frame_t * frame)
{
- return ip4_full_reass_handoff_node_inline (vm, node, frame, FEATURE);
+ return ip4_full_reass_handoff_node_inline (vm, node, frame, FEATURE,
+ false /* is_local */);
}
@@ -1858,7 +1931,8 @@ VLIB_NODE_FN (ip4_full_reass_custom_handoff_node) (vlib_main_t * vm,
node,
vlib_frame_t * frame)
{
- return ip4_full_reass_handoff_node_inline (vm, node, frame, CUSTOM);
+ return ip4_full_reass_handoff_node_inline (vm, node, frame, CUSTOM,
+ false /* is_local */);
}
@@ -1903,6 +1977,26 @@ ip4_full_reass_enable_disable_with_refcnt (u32 sw_if_index, int is_enable)
}
return -1;
}
+
+void
+ip4_local_full_reass_enable_disable (int enable)
+{
+ if (enable)
+ {
+ ip4_full_reass_main.is_local_reass_enabled = 1;
+ }
+ else
+ {
+ ip4_full_reass_main.is_local_reass_enabled = 0;
+ }
+}
+
+int
+ip4_local_full_reass_enabled ()
+{
+ return ip4_full_reass_main.is_local_reass_enabled;
+}
+
#endif
/*
diff --git a/src/vnet/ip/reass/ip4_full_reass.h b/src/vnet/ip/reass/ip4_full_reass.h
index 000c80c5906..5df8107ca48 100644
--- a/src/vnet/ip/reass/ip4_full_reass.h
+++ b/src/vnet/ip/reass/ip4_full_reass.h
@@ -47,6 +47,9 @@ int ip4_full_reass_enable_disable_with_refcnt (u32 sw_if_index,
int is_enable);
uword ip4_full_reass_custom_register_next_node (uword node_index);
+
+void ip4_local_full_reass_enable_disable (int enable);
+int ip4_local_full_reass_enabled ();
#endif /* __included_ip4_full_reass_h__ */
/*
diff --git a/src/vnet/ip/reass/ip6_full_reass.c b/src/vnet/ip/reass/ip6_full_reass.c
index 12cacfc2f33..1bcb6bd0f20 100644
--- a/src/vnet/ip/reass/ip6_full_reass.c
+++ b/src/vnet/ip/reass/ip6_full_reass.c
@@ -164,10 +164,14 @@ typedef struct
/** Worker handoff */
u32 fq_index;
+ u32 fq_local_index;
u32 fq_feature_index;
// reference count for enabling/disabling feature - per interface
u32 *feature_use_refcount_per_intf;
+
+ // whether local fragmented packets are reassembled or not
+ int is_local_reass_enabled;
} ip6_full_reass_main_t;
extern ip6_full_reass_main_t ip6_full_reass_main;
@@ -194,6 +198,7 @@ typedef enum
ICMP_ERROR_FL_NOT_MULT_8,
FINALIZE,
HANDOFF,
+ PASSTHROUGH,
} ip6_full_reass_trace_operation_e;
typedef struct
@@ -306,6 +311,9 @@ format_ip6_full_reass_trace (u8 * s, va_list * args)
format (s, "handoff from thread #%u to thread #%u", t->thread_id,
t->thread_id_to);
break;
+ case PASSTHROUGH:
+ s = format (s, "passthrough - not a fragment");
+ break;
}
return s;
}
@@ -1084,10 +1092,9 @@ ip6_full_reass_verify_packet_size_lt_64k (vlib_main_t * vm,
}
always_inline uword
-ip6_full_reassembly_inline (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- vlib_frame_t * frame, bool is_feature,
- bool is_custom_app)
+ip6_full_reassembly_inline (vlib_main_t *vm, vlib_node_runtime_t *node,
+ vlib_frame_t *frame, bool is_feature,
+ bool is_custom_app, bool is_local)
{
u32 *from = vlib_frame_vector_args (frame);
u32 n_left_from, n_left_to_next, *to_next, next_index;
@@ -1122,6 +1129,13 @@ ip6_full_reassembly_inline (vlib_main_t * vm,
{
// this is a mangled packet - no fragmentation
next0 = IP6_FULL_REASSEMBLY_NEXT_DROP;
+ ip6_full_reass_add_trace (vm, node, NULL, bi0, NULL, PASSTHROUGH,
+ ~0);
+ goto skip_reass;
+ }
+ if (is_local && !rm->is_local_reass_enabled)
+ {
+ next0 = IP6_FULL_REASSEMBLY_NEXT_DROP;
goto skip_reass;
}
frag_hdr =
@@ -1303,8 +1317,9 @@ VLIB_NODE_FN (ip6_full_reass_node) (vlib_main_t * vm,
vlib_node_runtime_t * node,
vlib_frame_t * frame)
{
- return ip6_full_reassembly_inline (vm, node, frame, false /* is_feature */ ,
- false /* is_custom_app */ );
+ return ip6_full_reassembly_inline (vm, node, frame, false /* is_feature */,
+ false /* is_custom_app */,
+ false /* is_local */);
}
VLIB_REGISTER_NODE (ip6_full_reass_node) = {
@@ -1323,12 +1338,37 @@ VLIB_REGISTER_NODE (ip6_full_reass_node) = {
},
};
+VLIB_NODE_FN (ip6_local_full_reass_node)
+(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
+{
+ return ip6_full_reassembly_inline (vm, node, frame, false /* is_feature */,
+ false /* is_custom_app */,
+ true /* is_local */);
+}
+
+VLIB_REGISTER_NODE (ip6_local_full_reass_node) = {
+ .name = "ip6-local-full-reassembly",
+ .vector_size = sizeof (u32),
+ .format_trace = format_ip6_full_reass_trace,
+ .n_errors = ARRAY_LEN (ip6_full_reassembly_error_strings),
+ .error_strings = ip6_full_reassembly_error_strings,
+ .n_next_nodes = IP6_FULL_REASSEMBLY_N_NEXT,
+ .next_nodes =
+ {
+ [IP6_FULL_REASSEMBLY_NEXT_INPUT] = "ip6-input",
+ [IP6_FULL_REASSEMBLY_NEXT_DROP] = "ip6-drop",
+ [IP6_FULL_REASSEMBLY_NEXT_ICMP_ERROR] = "ip6-icmp-error",
+ [IP6_FULL_REASSEMBLY_NEXT_HANDOFF] = "ip6-local-full-reassembly-handoff",
+ },
+};
+
VLIB_NODE_FN (ip6_full_reass_node_feature) (vlib_main_t * vm,
vlib_node_runtime_t * node,
vlib_frame_t * frame)
{
- return ip6_full_reassembly_inline (vm, node, frame, true /* is_feature */ ,
- false /* is_custom_app */ );
+ return ip6_full_reassembly_inline (vm, node, frame, true /* is_feature */,
+ false /* is_custom_app */,
+ false /* is_local */);
}
VLIB_REGISTER_NODE (ip6_full_reass_node_feature) = {
@@ -1500,9 +1540,12 @@ ip6_full_reass_init_function (vlib_main_t * vm)
if ((error = vlib_call_init_function (vm, ip_main_init)))
return error;
ip6_register_protocol (IP_PROTOCOL_IPV6_FRAGMENTATION,
- ip6_full_reass_node.index);
+ ip6_local_full_reass_node.index);
+ rm->is_local_reass_enabled = 1;
rm->fq_index = vlib_frame_queue_main_init (ip6_full_reass_node.index, 0);
+ rm->fq_local_index =
+ vlib_frame_queue_main_init (ip6_local_full_reass_node.index, 0);
rm->fq_feature_index =
vlib_frame_queue_main_init (ip6_full_reass_node_feature.index, 0);
@@ -1777,9 +1820,9 @@ format_ip6_full_reassembly_handoff_trace (u8 * s, va_list * args)
}
always_inline uword
-ip6_full_reassembly_handoff_inline (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- vlib_frame_t * frame, bool is_feature)
+ip6_full_reassembly_handoff_inline (vlib_main_t *vm, vlib_node_runtime_t *node,
+ vlib_frame_t *frame, bool is_feature,
+ bool is_local)
{
ip6_full_reass_main_t *rm = &ip6_full_reass_main;
@@ -1795,7 +1838,21 @@ ip6_full_reassembly_handoff_inline (vlib_main_t * vm,
b = bufs;
ti = thread_indices;
- fq_index = (is_feature) ? rm->fq_feature_index : rm->fq_index;
+ if (is_feature)
+ {
+ fq_index = rm->fq_feature_index;
+ }
+ else
+ {
+ if (is_local)
+ {
+ fq_index = rm->fq_local_index;
+ }
+ else
+ {
+ fq_index = rm->fq_index;
+ }
+ }
while (n_left_from > 0)
{
@@ -1828,8 +1885,8 @@ VLIB_NODE_FN (ip6_full_reassembly_handoff_node) (vlib_main_t * vm,
vlib_node_runtime_t * node,
vlib_frame_t * frame)
{
- return ip6_full_reassembly_handoff_inline (vm, node, frame,
- false /* is_feature */ );
+ return ip6_full_reassembly_handoff_inline (
+ vm, node, frame, false /* is_feature */, false /* is_local */);
}
VLIB_REGISTER_NODE (ip6_full_reassembly_handoff_node) = {
@@ -1846,11 +1903,32 @@ VLIB_REGISTER_NODE (ip6_full_reassembly_handoff_node) = {
},
};
+VLIB_NODE_FN (ip6_local_full_reassembly_handoff_node)
+(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
+{
+ return ip6_full_reassembly_handoff_inline (
+ vm, node, frame, false /* is_feature */, true /* is_feature */);
+}
+
+VLIB_REGISTER_NODE (ip6_local_full_reassembly_handoff_node) = {
+ .name = "ip6-local-full-reassembly-handoff",
+ .vector_size = sizeof (u32),
+ .n_errors = ARRAY_LEN(ip6_full_reassembly_handoff_error_strings),
+ .error_strings = ip6_full_reassembly_handoff_error_strings,
+ .format_trace = format_ip6_full_reassembly_handoff_trace,
+
+ .n_next_nodes = 1,
+
+ .next_nodes = {
+ [0] = "error-drop",
+ },
+};
VLIB_NODE_FN (ip6_full_reassembly_feature_handoff_node) (vlib_main_t * vm,
vlib_node_runtime_t * node, vlib_frame_t * frame)
{
- return ip6_full_reassembly_handoff_inline (vm, node, frame, true /* is_feature */ );
+ return ip6_full_reassembly_handoff_inline (
+ vm, node, frame, true /* is_feature */, false /* is_local */);
}
@@ -1895,6 +1973,35 @@ ip6_full_reass_enable_disable_with_refcnt (u32 sw_if_index, int is_enable)
}
return -1;
}
+
+void
+ip6_local_full_reass_enable_disable (int enable)
+{
+ if (enable)
+ {
+ if (!ip6_full_reass_main.is_local_reass_enabled)
+ {
+ ip6_full_reass_main.is_local_reass_enabled = 1;
+ ip6_register_protocol (IP_PROTOCOL_IPV6_FRAGMENTATION,
+ ip6_local_full_reass_node.index);
+ }
+ }
+ else
+ {
+ if (ip6_full_reass_main.is_local_reass_enabled)
+ {
+ ip6_full_reass_main.is_local_reass_enabled = 0;
+ ip6_unregister_protocol (IP_PROTOCOL_IPV6_FRAGMENTATION);
+ }
+ }
+}
+
+int
+ip6_local_full_reass_enabled ()
+{
+ return ip6_full_reass_main.is_local_reass_enabled;
+}
+
#endif
/*
diff --git a/src/vnet/ip/reass/ip6_full_reass.h b/src/vnet/ip/reass/ip6_full_reass.h
index 546075b04b4..f66cb67d796 100644
--- a/src/vnet/ip/reass/ip6_full_reass.h
+++ b/src/vnet/ip/reass/ip6_full_reass.h
@@ -46,6 +46,8 @@ vnet_api_error_t ip6_full_reass_enable_disable (u32 sw_if_index,
int ip6_full_reass_enable_disable_with_refcnt (u32 sw_if_index,
int is_enable);
+void ip6_local_full_reass_enable_disable (int enable);
+int ip6_local_full_reass_enabled ();
#endif /* __included_ip6_full_reass_h */
/*
diff --git a/test/Makefile b/test/Makefile
index 5616e9c3e55..3dbf00723ce 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -271,8 +271,8 @@ checkstyle-diff: $(PIP_INSTALL_DONE)
@bash -c "source $(VENV_PATH)/bin/activate &&\
$(PYTHON_INTERP) -m pip install pycodestyle"
@bash -c "source $(VENV_PATH)/bin/activate &&\
- cd $(WS_ROOT) && git diff --name-only --no-color --relative HEAD~1 ':!*.patch' | grep '.py$$' | xargs -n 1 -I XXX \
- pycodestyle --show-source --ignore=W504,E126,E241,E226,E305,E704,E741,E722 -v XXX ||\
+ cd $(WS_ROOT) && git diff --name-only --no-color --relative HEAD~1 ':!*.patch' | grep '.py$$' | xargs -n 1 \
+ pycodestyle --show-source --ignore=W504,E126,E241,E226,E305,E704,E741,E722 -v ||\
(echo \"*********************************************************************\" &&\
echo \"* Test framework PEP8 compliance check FAILED (checked changed files)\" &&\
echo \"*********************************************************************\" &&\
diff --git a/test/test_reassembly.py b/test/test_reassembly.py
index faec5f42c30..2291c933833 100644
--- a/test/test_reassembly.py
+++ b/test/test_reassembly.py
@@ -8,10 +8,11 @@ from framework import VppTestCase, VppTestRunner
import scapy.compat
from scapy.packet import Raw
from scapy.layers.l2 import Ether, GRE
-from scapy.layers.inet import IP, UDP, ICMP
+from scapy.layers.inet import IP, UDP, ICMP, icmptypes
from scapy.layers.inet6 import HBHOptUnknown, ICMPv6ParamProblem,\
ICMPv6TimeExceeded, IPv6, IPv6ExtHdrFragment,\
- IPv6ExtHdrHopByHop, IPv6ExtHdrDestOpt, PadN, ICMPv6EchoRequest
+ IPv6ExtHdrHopByHop, IPv6ExtHdrDestOpt, PadN, ICMPv6EchoRequest,\
+ ICMPv6EchoReply
from framework import VppTestCase, VppTestRunner
from util import ppp, ppc, fragment_rfc791, fragment_rfc8200
from vpp_gre_interface import VppGreInterface
@@ -28,7 +29,7 @@ class TestIPv4Reassembly(VppTestCase):
@classmethod
def setUpClass(cls):
- super(TestIPv4Reassembly, cls).setUpClass()
+ super().setUpClass()
cls.create_pg_interfaces([0, 1])
cls.src_if = cls.pg0
@@ -48,11 +49,11 @@ class TestIPv4Reassembly(VppTestCase):
@classmethod
def tearDownClass(cls):
- super(TestIPv4Reassembly, cls).tearDownClass()
+ super().tearDownClass()
def setUp(self):
""" Test setup - force timeout on existing reassemblies """
- super(TestIPv4Reassembly, self).setUp()
+ super().setUp()
self.vapi.ip_reassembly_enable_disable(
sw_if_index=self.src_if.sw_if_index, enable_ip4=True)
self.vapi.ip_reassembly_set(timeout_ms=0, max_reassemblies=1000,
@@ -64,7 +65,9 @@ class TestIPv4Reassembly(VppTestCase):
expire_walk_interval_ms=10000)
def tearDown(self):
- super(TestIPv4Reassembly, self).tearDown()
+ self.vapi.ip_reassembly_enable_disable(
+ sw_if_index=self.src_if.sw_if_index, enable_ip4=False)
+ super().tearDown()
def show_commands_at_teardown(self):
self.logger.debug(self.vapi.ppcli("show ip4-full-reassembly details"))
@@ -511,13 +514,31 @@ Ethernet-Payload.IPv4-Packet.IPv4-Header.Fragment-Offset; Test-case: 5737'''
self.verify_capture(packets, dropped_packet_indexes)
self.src_if.assert_nothing_captured()
+ def test_local_enable_disable(self):
+ """ local reassembly enabled/disable """
+ self.vapi.ip_reassembly_enable_disable(
+ sw_if_index=self.src_if.sw_if_index, enable_ip4=False)
+ self.vapi.ip_local_reass_enable_disable(enable_ip4=True)
+ p = (Ether(src=self.src_if.remote_mac, dst=self.src_if.local_mac) /
+ IP(src=self.src_if.remote_ip4, dst=self.src_if.local_ip4) /
+ ICMP(id=1234, type='echo-request') /
+ Raw('x' * 1000))
+ frags = fragment_rfc791(p, 400)
+ r = self.send_and_expect(self.src_if, frags, self.src_if, n_rx=1)[0]
+ self.assertEqual(1234, r[ICMP].id)
+ self.assertEqual(icmptypes[r[ICMP].type], 'echo-reply')
+ self.vapi.ip_local_reass_enable_disable()
+
+ self.send_and_assert_no_replies(self.src_if, frags)
+ self.vapi.ip_local_reass_enable_disable(enable_ip4=True)
+
class TestIPv4SVReassembly(VppTestCase):
""" IPv4 Shallow Virtual Reassembly """
@classmethod
def setUpClass(cls):
- super(TestIPv4SVReassembly, cls).setUpClass()
+ super().setUpClass()
cls.create_pg_interfaces([0, 1])
cls.src_if = cls.pg0
@@ -531,7 +552,7 @@ class TestIPv4SVReassembly(VppTestCase):
def setUp(self):
""" Test setup - force timeout on existing reassemblies """
- super(TestIPv4SVReassembly, self).setUp()
+ super().setUp()
self.vapi.ip_reassembly_enable_disable(
sw_if_index=self.src_if.sw_if_index, enable_ip4=True,
type=VppEnum.vl_api_ip_reass_type_t.IP_REASS_TYPE_SHALLOW_VIRTUAL)
@@ -548,7 +569,7 @@ class TestIPv4SVReassembly(VppTestCase):
expire_walk_interval_ms=10000)
def tearDown(self):
- super(TestIPv4SVReassembly, self).tearDown()
+ super().tearDown()
self.logger.debug(self.vapi.ppcli("show ip4-sv-reassembly details"))
self.logger.debug(self.vapi.ppcli("show buffers"))
@@ -791,7 +812,7 @@ class TestIPv4MWReassembly(VppTestCase):
@classmethod
def setUpClass(cls):
- super(TestIPv4MWReassembly, cls).setUpClass()
+ super().setUpClass()
cls.create_pg_interfaces(range(cls.vpp_worker_count+1))
cls.src_if = cls.pg0
@@ -815,11 +836,11 @@ class TestIPv4MWReassembly(VppTestCase):
@classmethod
def tearDownClass(cls):
- super(TestIPv4MWReassembly, cls).tearDownClass()
+ super().tearDownClass()
def setUp(self):
""" Test setup - force timeout on existing reassemblies """
- super(TestIPv4MWReassembly, self).setUp()
+ super().setUp()
for intf in self.send_ifs:
self.vapi.ip_reassembly_enable_disable(
sw_if_index=intf.sw_if_index, enable_ip4=True)
@@ -832,7 +853,10 @@ class TestIPv4MWReassembly(VppTestCase):
expire_walk_interval_ms=10000)
def tearDown(self):
- super(TestIPv4MWReassembly, self).tearDown()
+ for intf in self.send_ifs:
+ self.vapi.ip_reassembly_enable_disable(
+ sw_if_index=intf.sw_if_index, enable_ip4=False)
+ super().tearDown()
def show_commands_at_teardown(self):
self.logger.debug(self.vapi.ppcli("show ip4-full-reassembly details"))
@@ -968,7 +992,7 @@ class TestIPv6Reassembly(VppTestCase):
@classmethod
def setUpClass(cls):
- super(TestIPv6Reassembly, cls).setUpClass()
+ super().setUpClass()
cls.create_pg_interfaces([0, 1])
cls.src_if = cls.pg0
@@ -988,11 +1012,11 @@ class TestIPv6Reassembly(VppTestCase):
@classmethod
def tearDownClass(cls):
- super(TestIPv6Reassembly, cls).tearDownClass()
+ super().tearDownClass()
def setUp(self):
""" Test setup - force timeout on existing reassemblies """
- super(TestIPv6Reassembly, self).setUp()
+ super().setUp()
self.vapi.ip_reassembly_enable_disable(
sw_if_index=self.src_if.sw_if_index, enable_ip6=True)
self.vapi.ip_reassembly_set(timeout_ms=0, max_reassemblies=1000,
@@ -1006,7 +1030,9 @@ class TestIPv6Reassembly(VppTestCase):
self.logger.debug(self.vapi.ppcli("show buffers"))
def tearDown(self):
- super(TestIPv6Reassembly, self).tearDown()
+ self.vapi.ip_reassembly_enable_disable(
+ sw_if_index=self.src_if.sw_if_index, enable_ip6=False)
+ super().tearDown()
def show_commands_at_teardown(self):
self.logger.debug(self.vapi.ppcli("show ip6-full-reassembly details"))
@@ -1505,6 +1531,22 @@ class TestIPv6Reassembly(VppTestCase):
rx = self.send_and_expect(self.pg0, [pkt], self.pg0)
self.assertNotIn(IPv6ExtHdrFragment, rx)
+ def test_local_enable_disable(self):
+ """ local reassembly enabled/disable """
+ self.vapi.ip_reassembly_enable_disable(
+ sw_if_index=self.src_if.sw_if_index, enable_ip6=False)
+ self.vapi.ip_local_reass_enable_disable(enable_ip6=True)
+ pkt = (Ether(src=self.src_if.local_mac, dst=self.src_if.remote_mac) /
+ IPv6(src=self.src_if.remote_ip6, dst=self.src_if.local_ip6) /
+ ICMPv6EchoRequest(id=1234)/Raw('X' * 1600))
+ frags = fragment_rfc8200(pkt, 1, 400)
+ r = self.send_and_expect(self.src_if, frags, self.src_if, n_rx=1)[0]
+ self.assertEqual(1234, r[ICMPv6EchoReply].id)
+ self.vapi.ip_local_reass_enable_disable()
+
+ self.send_and_assert_no_replies(self.src_if, frags)
+ self.vapi.ip_local_reass_enable_disable(enable_ip6=True)
+
class TestIPv6MWReassembly(VppTestCase):
""" IPv6 Reassembly (multiple workers) """
@@ -1512,7 +1554,7 @@ class TestIPv6MWReassembly(VppTestCase):
@classmethod
def setUpClass(cls):
- super(TestIPv6MWReassembly, cls).setUpClass()
+ super().setUpClass()
cls.create_pg_interfaces(range(cls.vpp_worker_count+1))
cls.src_if = cls.pg0
@@ -1536,11 +1578,11 @@ class TestIPv6MWReassembly(VppTestCase):
@classmethod
def tearDownClass(cls):
- super(TestIPv6MWReassembly, cls).tearDownClass()
+ super().tearDownClass()
def setUp(self):
""" Test setup - force timeout on existing reassemblies """
- super(TestIPv6MWReassembly, self).setUp()
+ super().setUp()
for intf in self.send_ifs:
self.vapi.ip_reassembly_enable_disable(
sw_if_index=intf.sw_if_index, enable_ip6=True)
@@ -1553,7 +1595,10 @@ class TestIPv6MWReassembly(VppTestCase):
expire_walk_interval_ms=1000, is_ip6=1)
def tearDown(self):
- super(TestIPv6MWReassembly, self).tearDown()
+ for intf in self.send_ifs:
+ self.vapi.ip_reassembly_enable_disable(
+ sw_if_index=intf.sw_if_index, enable_ip6=False)
+ super().tearDown()
def show_commands_at_teardown(self):
self.logger.debug(self.vapi.ppcli("show ip6-full-reassembly details"))
@@ -1689,7 +1734,7 @@ class TestIPv6SVReassembly(VppTestCase):
@classmethod
def setUpClass(cls):
- super(TestIPv6SVReassembly, cls).setUpClass()
+ super().setUpClass()
cls.create_pg_interfaces([0, 1])
cls.src_if = cls.pg0
@@ -1703,7 +1748,7 @@ class TestIPv6SVReassembly(VppTestCase):
def setUp(self):
""" Test setup - force timeout on existing reassemblies """
- super(TestIPv6SVReassembly, self).setUp()
+ super().setUp()
self.vapi.ip_reassembly_enable_disable(
sw_if_index=self.src_if.sw_if_index, enable_ip6=True,
type=VppEnum.vl_api_ip_reass_type_t.IP_REASS_TYPE_SHALLOW_VIRTUAL)
@@ -1720,7 +1765,7 @@ class TestIPv6SVReassembly(VppTestCase):
expire_walk_interval_ms=10000, is_ip6=1)
def tearDown(self):
- super(TestIPv6SVReassembly, self).tearDown()
+ super().tearDown()
self.logger.debug(self.vapi.ppcli("show ip6-sv-reassembly details"))
self.logger.debug(self.vapi.ppcli("show buffers"))
@@ -1941,7 +1986,7 @@ class TestIPv4ReassemblyLocalNode(VppTestCase):
@classmethod
def setUpClass(cls):
- super(TestIPv4ReassemblyLocalNode, cls).setUpClass()
+ super().setUpClass()
cls.create_pg_interfaces([0])
cls.src_dst_if = cls.pg0
@@ -1958,11 +2003,11 @@ class TestIPv4ReassemblyLocalNode(VppTestCase):
@classmethod
def tearDownClass(cls):
- super(TestIPv4ReassemblyLocalNode, cls).tearDownClass()
+ super().tearDownClass()
def setUp(self):
""" Test setup - force timeout on existing reassemblies """
- super(TestIPv4ReassemblyLocalNode, self).setUp()
+ super().setUp()
self.vapi.ip_reassembly_set(timeout_ms=0, max_reassemblies=1000,
max_reassembly_length=1000,
expire_walk_interval_ms=10)
@@ -1972,7 +2017,7 @@ class TestIPv4ReassemblyLocalNode(VppTestCase):
expire_walk_interval_ms=10000)
def tearDown(self):
- super(TestIPv4ReassemblyLocalNode, self).tearDown()
+ super().tearDown()
def show_commands_at_teardown(self):
self.logger.debug(self.vapi.ppcli("show ip4-full-reassembly details"))
@@ -2068,7 +2113,7 @@ class TestFIFReassembly(VppTestCase):
@classmethod
def setUpClass(cls):
- super(TestFIFReassembly, cls).setUpClass()
+ super().setUpClass()
cls.create_pg_interfaces([0, 1])
cls.src_if = cls.pg0
@@ -2085,11 +2130,11 @@ class TestFIFReassembly(VppTestCase):
@classmethod
def tearDownClass(cls):
- super(TestFIFReassembly, cls).tearDownClass()
+ super().tearDownClass()
def setUp(self):
""" Test setup - force timeout on existing reassemblies """
- super(TestFIFReassembly, self).setUp()
+ super().setUp()
self.vapi.ip_reassembly_enable_disable(
sw_if_index=self.src_if.sw_if_index, enable_ip4=True,
enable_ip6=True)
@@ -2111,7 +2156,7 @@ class TestFIFReassembly(VppTestCase):
expire_walk_interval_ms=10000, is_ip6=1)
def tearDown(self):
- super(TestFIFReassembly, self).tearDown()
+ super().tearDown()
def show_commands_at_teardown(self):
self.logger.debug(self.vapi.ppcli("show ip4-full-reassembly details"))