aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--vnet/vnet/ip/ip4_source_and_port_range_check.c818
-rw-r--r--vnet/vnet/ip/ip_source_and_port_range_check.h48
-rw-r--r--vpp-api-test/vat/api_format.c49
-rw-r--r--vpp/vpp-api/api.c73
-rw-r--r--vpp/vpp-api/custom_dump.c16
-rw-r--r--vpp/vpp-api/vpe.api11
6 files changed, 606 insertions, 409 deletions
diff --git a/vnet/vnet/ip/ip4_source_and_port_range_check.c b/vnet/vnet/ip/ip4_source_and_port_range_check.c
index 9dfb5228056..c36678c9860 100644
--- a/vnet/vnet/ip/ip4_source_and_port_range_check.c
+++ b/vnet/vnet/ip/ip4_source_and_port_range_check.c
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -13,35 +13,14 @@
* limitations under the License.
*/
#include <vnet/ip/ip.h>
+#include <vnet/ip/ip_source_and_port_range_check.h>
-typedef struct {
- u32 ranges_per_adjacency;
- u32 special_adjacency_format_function_index;
-
- /* convenience */
- vlib_main_t *vlib_main;
- vnet_main_t *vnet_main;
-} source_range_check_main_t;
-
-source_range_check_main_t source_range_check_main;
vlib_node_registration_t ip4_source_port_and_range_check;
-typedef struct {
- union {
- u16x8 as_u16x8;
- u16 as_u16[8];
- };
-} u16x8vec_t;
-
-typedef struct {
- u16x8vec_t low;
- u16x8vec_t hi;
-} port_range_t;
-
-#define foreach_ip4_source_and_port_range_check_error \
-_(CHECK_FAIL, "ip4 source and port range check bad packets") \
-_(CHECK_OK, "ip4 source and port range check good packets")
+#define foreach_ip4_source_and_port_range_check_error \
+ _(CHECK_FAIL, "ip4 source and port range check bad packets") \
+ _(CHECK_OK, "ip4 source and port range check good packets")
typedef enum {
#define _(sym,str) IP4_SOURCE_AND_PORT_RANGE_CHECK_ERROR_##sym,
@@ -62,6 +41,7 @@ typedef struct {
u32 is_tcp;
ip4_address_t src_addr;
u16 dst_port;
+ u32 fib_index;
} ip4_source_and_port_range_check_trace_t;
static u8 * format_ip4_source_and_port_range_check_trace (u8 * s, va_list * va)
@@ -74,10 +54,10 @@ static u8 * format_ip4_source_and_port_range_check_trace (u8 * s, va_list * va)
if (t->bypass)
s = format (s, "PASS (bypass case)");
else
- s = format (s, "src ip %U %s dst port %d: %s",
- format_ip4_address, &t->src_addr, t->is_tcp ? "TCP" : "UDP",
- (u32) t->dst_port,
- (t->pass == 1) ? "PASS" : "FAIL");
+ s = format (s, "fib %d src ip %U %s dst port %d: %s",
+ t->fib_index, format_ip4_address, &t->src_addr, t->is_tcp ? "TCP" : "UDP",
+ (u32) t->dst_port,
+ (t->pass == 1) ? "PASS" : "FAIL");
return s;
}
@@ -86,15 +66,12 @@ typedef enum {
IP4_SOURCE_AND_PORT_RANGE_CHECK_N_NEXT,
} ip4_source_and_port_range_check_next_t;
-typedef union {
- u32 fib_index;
-} ip4_source_and_port_range_check_config_t;
static inline u32 check_adj_port_range_x1 (ip_adjacency_t * adj,
u16 dst_port,
u32 next)
{
- port_range_t *range;
+ protocol_port_range_t *range;
u16x8vec_t key;
u16x8vec_t diff1;
u16x8vec_t diff2;
@@ -107,14 +84,14 @@ static inline u32 check_adj_port_range_x1 (ip_adjacency_t * adj,
return IP4_SOURCE_AND_PORT_RANGE_CHECK_NEXT_DROP;
rwh = (u8 *)(&adj->rewrite_header);
- range = (port_range_t *)rwh;
+ range = (protocol_port_range_t *)rwh;
/* Make the obvious screw-case work. A variant also works w/ no MMX */
if (PREDICT_FALSE(dst_port == 65535))
{
int j;
- for (i = 0; i < VLIB_BUFFER_PRE_DATA_SIZE / sizeof(port_range_t); i++)
+ for (i = 0; i < VLIB_BUFFER_PRE_DATA_SIZE / sizeof(protocol_port_range_t); i++)
{
for (j = 0; j < 8; j++)
if (range->low.as_u16x8[j] == 65535)
@@ -126,7 +103,7 @@ static inline u32 check_adj_port_range_x1 (ip_adjacency_t * adj,
key.as_u16x8 = u16x8_splat (dst_port);
- for (i = 0; i < VLIB_BUFFER_PRE_DATA_SIZE / sizeof(port_range_t); i++)
+ for (i = 0; i < VLIB_BUFFER_PRE_DATA_SIZE / sizeof(protocol_port_range_t); i++)
{
diff1.as_u16x8 = u16x8_sub_saturate (range->low.as_u16x8, key.as_u16x8);
diff2.as_u16x8 = u16x8_sub_saturate (range->hi.as_u16x8, key.as_u16x8);
@@ -154,6 +131,7 @@ ip4_source_and_port_range_check_inline
u32 next_index;
vlib_node_runtime_t * error_node = node;
u32 good_packets = 0;
+ int i;
from = vlib_frame_vector_args (frame);
n_left_from = frame->n_vectors;
@@ -164,130 +142,166 @@ ip4_source_and_port_range_check_inline
u32 n_left_to_next;
vlib_get_next_frame (vm, node, next_index,
- to_next, n_left_to_next);
+ to_next, n_left_to_next);
+
while (n_left_from >= 4 && n_left_to_next >= 2)
- {
+ {
vlib_buffer_t * b0, * b1;
- ip4_header_t * ip0, * ip1;
- ip4_fib_mtrie_t * mtrie0, * mtrie1;
- ip4_fib_mtrie_leaf_t leaf0, leaf1;
- ip4_source_and_port_range_check_config_t * c0, * c1;
- ip_adjacency_t * adj0, * adj1;
- u32 bi0, next0, adj_index0, pass0, save_next0;
- u32 bi1, next1, adj_index1, pass1, save_next1;
+ ip4_header_t * ip0, * ip1;
+ ip4_fib_mtrie_t * mtrie0, * mtrie1;
+ ip4_fib_mtrie_leaf_t leaf0, leaf1;
+ ip_source_and_port_range_check_config_t * c0, * c1;
+ ip_adjacency_t * adj0 = 0, * adj1 = 0;
+ u32 bi0, next0, adj_index0, pass0, save_next0, fib_index0;
+ u32 bi1, next1, adj_index1, pass1, save_next1, fib_index1;
udp_header_t * udp0, * udp1;
- /* Prefetch next iteration. */
- {
- vlib_buffer_t * p2, * p3;
+ /* Prefetch next iteration. */
+ {
+ vlib_buffer_t * p2, * p3;
+
+ p2 = vlib_get_buffer (vm, from[2]);
+ p3 = vlib_get_buffer (vm, from[3]);
- p2 = vlib_get_buffer (vm, from[2]);
- p3 = vlib_get_buffer (vm, from[3]);
+ vlib_prefetch_buffer_header (p2, LOAD);
+ vlib_prefetch_buffer_header (p3, LOAD);
- vlib_prefetch_buffer_header (p2, LOAD);
- vlib_prefetch_buffer_header (p3, LOAD);
+ CLIB_PREFETCH (p2->data, sizeof (ip0[0]), LOAD);
+ CLIB_PREFETCH (p3->data, sizeof (ip1[0]), LOAD);
+ }
- CLIB_PREFETCH (p2->data, sizeof (ip0[0]), LOAD);
- CLIB_PREFETCH (p3->data, sizeof (ip1[0]), LOAD);
- }
+ bi0 = to_next[0] = from[0];
+ bi1 = to_next[1] = from[1];
+ from += 2;
+ to_next += 2;
+ n_left_from -= 2;
+ n_left_to_next -= 2;
- bi0 = to_next[0] = from[0];
- bi1 = to_next[1] = from[1];
- from += 2;
- to_next += 2;
- n_left_from -= 2;
- n_left_to_next -= 2;
+ b0 = vlib_get_buffer (vm, bi0);
+ b1 = vlib_get_buffer (vm, bi1);
- b0 = vlib_get_buffer (vm, bi0);
- b1 = vlib_get_buffer (vm, bi1);
+ fib_index0 = vec_elt (im->fib_index_by_sw_if_index, vnet_buffer (b0)->sw_if_index[VLIB_RX]);
+ fib_index1 = vec_elt (im->fib_index_by_sw_if_index, vnet_buffer (b1)->sw_if_index[VLIB_RX]);
- ip0 = vlib_buffer_get_current (b0);
- ip1 = vlib_buffer_get_current (b1);
+ ip0 = vlib_buffer_get_current (b0);
+ ip1 = vlib_buffer_get_current (b1);
- c0 = vnet_get_config_data (&cm->config_main,
- &b0->current_config_index,
- &next0,
- sizeof (c0[0]));
- c1 = vnet_get_config_data (&cm->config_main,
- &b1->current_config_index,
- &next1,
- sizeof (c1[0]));
+ c0 = vnet_get_config_data (&cm->config_main,
+ &b0->current_config_index,
+ &next0,
+ sizeof (c0[0]));
+ c1 = vnet_get_config_data (&cm->config_main,
+ &b1->current_config_index,
+ &next1,
+ sizeof (c1[0]));
/* we can't use the default VRF here... */
- ASSERT (c0->fib_index && c1->fib_index);
+ for (i = 0; i < IP_SOURCE_AND_PORT_RANGE_CHECK_N_PROTOCOLS; i++)
+ {
+ ASSERT(c0->fib_index[i] && c1->fib_index[i]);
+ }
+
+
+ if (ip0->protocol == IP_PROTOCOL_UDP)
+ fib_index0 = c0->fib_index[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_UDP_OUT];
+ if (ip0->protocol == IP_PROTOCOL_TCP)
+ fib_index0 = c0->fib_index[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_TCP_OUT];
+
+ if (PREDICT_TRUE(fib_index0 != ~0))
+ {
- mtrie0 = &vec_elt_at_index (im->fibs, c0->fib_index)->mtrie;
- mtrie1 = &vec_elt_at_index (im->fibs, c1->fib_index)->mtrie;
+ mtrie0 = &vec_elt_at_index (im->fibs, fib_index0)->mtrie;
- leaf0 = leaf1 = IP4_FIB_MTRIE_LEAF_ROOT;
+ leaf0 = IP4_FIB_MTRIE_LEAF_ROOT;
- leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0,
- &ip0->src_address, 0);
- leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1,
- &ip1->src_address, 0);
+ leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0,
+ &ip0->src_address, 0);
- leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0,
- &ip0->src_address, 1);
- leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1,
- &ip1->src_address, 1);
+ leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0,
+ &ip0->src_address, 1);
- leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0,
- &ip0->src_address, 2);
- leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1,
- &ip1->src_address, 2);
+ leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0,
+ &ip0->src_address, 2);
- leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0,
- &ip0->src_address, 3);
- leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1,
- &ip1->src_address, 3);
+ leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0,
+ &ip0->src_address, 3);
- adj_index0 = ip4_fib_mtrie_leaf_get_adj_index (leaf0);
- adj_index1 = ip4_fib_mtrie_leaf_get_adj_index (leaf1);
+ adj_index0 = ip4_fib_mtrie_leaf_get_adj_index (leaf0);
- ASSERT (adj_index0 == ip4_fib_lookup_with_table (im, c0->fib_index,
- &ip0->src_address,
+ ASSERT (adj_index0 == ip4_fib_lookup_with_table (im, fib_index0,
+ &ip0->src_address,
0 /* use dflt rt */));
+ adj0 = ip_get_adjacency (lm, adj_index0);
+ }
+
+ if (ip1->protocol == IP_PROTOCOL_UDP)
+ fib_index1 = c1->fib_index[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_UDP_OUT];
+ if (ip1->protocol == IP_PROTOCOL_TCP)
+ fib_index1 = c1->fib_index[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_TCP_OUT];
+
+ if (PREDICT_TRUE(fib_index1 != ~0))
+ {
+
+ mtrie1 = &vec_elt_at_index (im->fibs, fib_index1)->mtrie;
+
+ leaf1 = IP4_FIB_MTRIE_LEAF_ROOT;
+
+ leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1,
+ &ip1->src_address, 0);
+
+ leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1,
+ &ip1->src_address, 1);
+
+ leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1,
+ &ip1->src_address, 2);
+
+ leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1,
+ &ip1->src_address, 3);
+
+ adj_index1 = ip4_fib_mtrie_leaf_get_adj_index (leaf1);
- ASSERT (adj_index1 == ip4_fib_lookup_with_table (im, c1->fib_index,
- &ip1->src_address,
- 0));
- adj0 = ip_get_adjacency (lm, adj_index0);
- adj1 = ip_get_adjacency (lm, adj_index1);
+ ASSERT (adj_index1 == ip4_fib_lookup_with_table (im, fib_index1,
+ &ip1->src_address,
+ 0));
+ adj1 = ip_get_adjacency (lm, adj_index1);
+ }
pass0 = 0;
+ pass0 |= adj0 == 0;
pass0 |= ip4_address_is_multicast (&ip0->src_address);
pass0 |= ip0->src_address.as_u32 == clib_host_to_net_u32(0xFFFFFFFF);
pass0 |= (ip0->protocol != IP_PROTOCOL_UDP) &&
- (ip0->protocol != IP_PROTOCOL_TCP);
+ (ip0->protocol != IP_PROTOCOL_TCP);
pass1 = 0;
+ pass1 |= adj1 == 0;
pass1 |= ip4_address_is_multicast (&ip1->src_address);
pass1 |= ip1->src_address.as_u32 == clib_host_to_net_u32(0xFFFFFFFF);
pass1 |= (ip1->protocol != IP_PROTOCOL_UDP) &&
- (ip1->protocol != IP_PROTOCOL_TCP);
+ (ip1->protocol != IP_PROTOCOL_TCP);
- save_next0 = next0;
- udp0 = ip4_next_header (ip0);
- save_next1 = next1;
- udp1 = ip4_next_header (ip1);
+ save_next0 = next0;
+ udp0 = ip4_next_header (ip0);
+ save_next1 = next1;
+ udp1 = ip4_next_header (ip1);
if (PREDICT_TRUE(pass0 == 0))
{
- good_packets ++;
+ good_packets ++;
next0 = check_adj_port_range_x1
(adj0, clib_net_to_host_u16(udp0->dst_port), next0);
- good_packets -= (save_next0 != next0);
+ good_packets -= (save_next0 != next0);
b0->error = error_node->errors
[IP4_SOURCE_AND_PORT_RANGE_CHECK_ERROR_CHECK_FAIL];
}
if (PREDICT_TRUE(pass1 == 0))
{
- good_packets ++;
+ good_packets ++;
next1 = check_adj_port_range_x1
(adj1, clib_net_to_host_u16(udp1->dst_port), next1);
- good_packets -= (save_next1 != next1);
+ good_packets -= (save_next1 != next1);
b1->error = error_node->errors
[IP4_SOURCE_AND_PORT_RANGE_CHECK_ERROR_CHECK_FAIL];
}
@@ -295,103 +309,121 @@ ip4_source_and_port_range_check_inline
if (PREDICT_FALSE((node->flags & VLIB_NODE_FLAG_TRACE)
&& (b0->flags & VLIB_BUFFER_IS_TRACED))) {
ip4_source_and_port_range_check_trace_t * t =
- vlib_add_trace (vm, node, b0, sizeof (*t));
+ vlib_add_trace (vm, node, b0, sizeof (*t));
t->pass = next0 == save_next0;
- t->bypass = pass0;
- t->src_addr.as_u32 = ip0->src_address.as_u32;
- t->dst_port = (pass0 == 0) ?
- clib_net_to_host_u16(udp0->dst_port) : 0;
- t->is_tcp = ip0->protocol == IP_PROTOCOL_TCP;
- }
+ t->bypass = pass0;
+ t->fib_index = fib_index0;
+ t->src_addr.as_u32 = ip0->src_address.as_u32;
+ t->dst_port = (pass0 == 0) ?
+ clib_net_to_host_u16(udp0->dst_port) : 0;
+ t->is_tcp = ip0->protocol == IP_PROTOCOL_TCP;
+ }
if (PREDICT_FALSE((node->flags & VLIB_NODE_FLAG_TRACE)
&& (b1->flags & VLIB_BUFFER_IS_TRACED))) {
ip4_source_and_port_range_check_trace_t * t =
- vlib_add_trace (vm, node, b1, sizeof (*t));
+ vlib_add_trace (vm, node, b1, sizeof (*t));
t->pass = next1 == save_next1;
- t->bypass = pass1;
- t->src_addr.as_u32 = ip1->src_address.as_u32;
- t->dst_port = (pass1 == 0) ?
- clib_net_to_host_u16(udp1->dst_port) : 0;
- t->is_tcp = ip1->protocol == IP_PROTOCOL_TCP;
- }
+ t->bypass = pass1;
+ t->fib_index = fib_index1;
+ t->src_addr.as_u32 = ip1->src_address.as_u32;
+ t->dst_port = (pass1 == 0) ?
+ clib_net_to_host_u16(udp1->dst_port) : 0;
+ t->is_tcp = ip1->protocol == IP_PROTOCOL_TCP;
+ }
- vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
- to_next, n_left_to_next,
- bi0, bi1, next0, next1);
- }
+ vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
+ to_next, n_left_to_next,
+ bi0, bi1, next0, next1);
+ }
while (n_left_from > 0 && n_left_to_next > 0)
- {
- vlib_buffer_t * b0;
- ip4_header_t * ip0;
- ip4_fib_mtrie_t * mtrie0;
- ip4_fib_mtrie_leaf_t leaf0;
- ip4_source_and_port_range_check_config_t * c0;
- ip_adjacency_t * adj0;
- u32 bi0, next0, adj_index0, pass0, save_next0;
+ {
+ vlib_buffer_t * b0;
+ ip4_header_t * ip0;
+ ip4_fib_mtrie_t * mtrie0;
+ ip4_fib_mtrie_leaf_t leaf0;
+ ip_source_and_port_range_check_config_t * c0;
+ ip_adjacency_t * adj0 = 0;
+ u32 bi0, next0, adj_index0, pass0, save_next0, fib_index0;
udp_header_t * udp0;
- bi0 = from[0];
- to_next[0] = bi0;
- from += 1;
- to_next += 1;
- n_left_from -= 1;
- n_left_to_next -= 1;
+ bi0 = from[0];
+ to_next[0] = bi0;
+ from += 1;
+ to_next += 1;
+ n_left_from -= 1;
+ n_left_to_next -= 1;
+
+ b0 = vlib_get_buffer (vm, bi0);
+
+ fib_index0 = vec_elt (im->fib_index_by_sw_if_index, vnet_buffer (b0)->sw_if_index[VLIB_RX]);
- b0 = vlib_get_buffer (vm, bi0);
- ip0 = vlib_buffer_get_current (b0);
+ ip0 = vlib_buffer_get_current (b0);
- c0 = vnet_get_config_data
+ c0 = vnet_get_config_data
(&cm->config_main, &b0->current_config_index,
&next0,
sizeof (c0[0]));
/* we can't use the default VRF here... */
- ASSERT(c0->fib_index);
+ for (i = 0; i < IP_SOURCE_AND_PORT_RANGE_CHECK_N_PROTOCOLS; i++)
+ {
+ ASSERT(c0->fib_index[i]);
+ }
+
- mtrie0 = &vec_elt_at_index (im->fibs, c0->fib_index)->mtrie;
+ if (ip0->protocol == IP_PROTOCOL_UDP)
+ fib_index0 = c0->fib_index[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_UDP_OUT];
+ if (ip0->protocol == IP_PROTOCOL_TCP)
+ fib_index0 = c0->fib_index[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_TCP_OUT];
- leaf0 = IP4_FIB_MTRIE_LEAF_ROOT;
+ if (fib_index0 != ~0)
+ {
+
+ mtrie0 = &vec_elt_at_index (im->fibs, fib_index0)->mtrie;
- leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0,
- &ip0->src_address, 0);
+ leaf0 = IP4_FIB_MTRIE_LEAF_ROOT;
- leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0,
- &ip0->src_address, 1);
+ leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0,
+ &ip0->src_address, 0);
- leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0,
- &ip0->src_address, 2);
+ leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0,
+ &ip0->src_address, 1);
- leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0,
- &ip0->src_address, 3);
+ leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0,
+ &ip0->src_address, 2);
- adj_index0 = ip4_fib_mtrie_leaf_get_adj_index (leaf0);
+ leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0,
+ &ip0->src_address, 3);
- ASSERT (adj_index0 == ip4_fib_lookup_with_table
- (im, c0->fib_index,
- &ip0->src_address,
- 0 /* use default route */));
- adj0 = ip_get_adjacency (lm, adj_index0);
+ adj_index0 = ip4_fib_mtrie_leaf_get_adj_index (leaf0);
- /*
- * $$$ which (src,dst) categories should we always pass?
- */
+ ASSERT (adj_index0 == ip4_fib_lookup_with_table
+ (im, fib_index0,
+ &ip0->src_address,
+ 0 /* use default route */));
+ adj0 = ip_get_adjacency (lm, adj_index0);
+ }
+ /*
+ * $$$ which (src,dst) categories should we always pass?
+ */
pass0 = 0;
+ pass0 |= adj0 == 0;
pass0 |= ip4_address_is_multicast (&ip0->src_address);
pass0 |= ip0->src_address.as_u32 == clib_host_to_net_u32(0xFFFFFFFF);
pass0 |= (ip0->protocol != IP_PROTOCOL_UDP) &&
- (ip0->protocol != IP_PROTOCOL_TCP);
+ (ip0->protocol != IP_PROTOCOL_TCP);
- save_next0 = next0;
- udp0 = ip4_next_header (ip0);
+ save_next0 = next0;
+ udp0 = ip4_next_header (ip0);
if (PREDICT_TRUE(pass0 == 0))
{
- good_packets ++;
+ good_packets ++;
next0 = check_adj_port_range_x1
(adj0, clib_net_to_host_u16(udp0->dst_port), next0);
- good_packets -= (save_next0 != next0);
+ good_packets -= (save_next0 != next0);
b0->error = error_node->errors
[IP4_SOURCE_AND_PORT_RANGE_CHECK_ERROR_CHECK_FAIL];
}
@@ -399,26 +431,27 @@ ip4_source_and_port_range_check_inline
if (PREDICT_FALSE((node->flags & VLIB_NODE_FLAG_TRACE)
&& (b0->flags & VLIB_BUFFER_IS_TRACED))) {
ip4_source_and_port_range_check_trace_t * t =
- vlib_add_trace (vm, node, b0, sizeof (*t));
+ vlib_add_trace (vm, node, b0, sizeof (*t));
t->pass = next0 == save_next0;
- t->bypass = pass0;
- t->src_addr.as_u32 = ip0->src_address.as_u32;
- t->dst_port = (pass0 == 0) ?
- clib_net_to_host_u16(udp0->dst_port) : 0;
- t->is_tcp = ip0->protocol == IP_PROTOCOL_TCP;
- }
+ t->bypass = pass0;
+ t->fib_index = fib_index0;
+ t->src_addr.as_u32 = ip0->src_address.as_u32;
+ t->dst_port = (pass0 == 0) ?
+ clib_net_to_host_u16(udp0->dst_port) : 0;
+ t->is_tcp = ip0->protocol == IP_PROTOCOL_TCP;
+ }
- vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
- to_next, n_left_to_next,
- bi0, next0);
- }
+ vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
+ to_next, n_left_to_next,
+ bi0, next0);
+ }
vlib_put_next_frame (vm, node, next_index, n_left_to_next);
}
vlib_node_increment_counter (vm, ip4_source_port_and_range_check.index,
- IP4_SOURCE_AND_PORT_RANGE_CHECK_ERROR_CHECK_OK,
- good_packets);
+ IP4_SOURCE_AND_PORT_RANGE_CHECK_ERROR_CHECK_OK,
+ good_packets);
return frame->n_vectors;
}
@@ -448,7 +481,7 @@ VLIB_REGISTER_NODE (ip4_source_port_and_range_check) = {
};
int set_ip_source_and_port_range_check (vlib_main_t * vm,
- u32 fib_index,
+ u32 * fib_index,
u32 sw_if_index,
u32 is_add)
{
@@ -456,20 +489,24 @@ int set_ip_source_and_port_range_check (vlib_main_t * vm,
ip_lookup_main_t * lm = &im->lookup_main;
ip_config_main_t * rx_cm = &lm->rx_config_mains[VNET_UNICAST];
u32 ci;
- ip4_source_and_port_range_check_config_t config;
+ ip_source_and_port_range_check_config_t config;
u32 feature_index;
int rv = 0;
- u8 is_del = !is_add;
+ int i;
+
+ for (i = 0; i < IP_SOURCE_AND_PORT_RANGE_CHECK_N_PROTOCOLS; i++)
+ {
+ config.fib_index[i] = fib_index[i];
+ }
- config.fib_index = fib_index;
feature_index = im->ip4_unicast_rx_feature_source_and_port_range_check;
vec_validate (rx_cm->config_index_by_sw_if_index, sw_if_index);
ci = rx_cm->config_index_by_sw_if_index[sw_if_index];
- ci = (is_del
- ? vnet_config_del_feature
- : vnet_config_add_feature)
+ ci = (is_add
+ ? vnet_config_add_feature
+ : vnet_config_del_feature)
(vm, &rx_cm->config_main,
ci,
feature_index,
@@ -482,49 +519,69 @@ int set_ip_source_and_port_range_check (vlib_main_t * vm,
static clib_error_t *
set_ip_source_and_port_range_check_fn (vlib_main_t * vm,
- unformat_input_t * input,
- vlib_cli_command_t * cmd)
+ unformat_input_t * input,
+ vlib_cli_command_t * cmd)
{
vnet_main_t * vnm = vnet_get_main();
ip4_main_t * im = &ip4_main;
clib_error_t * error = 0;
- u32 is_add = 1;
+ u8 is_add = 1;
u32 sw_if_index = ~0;
- u32 vrf_id = ~0;
- u32 fib_index;
+ u32 vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_N_PROTOCOLS];
+ u32 fib_index[IP_SOURCE_AND_PORT_RANGE_CHECK_N_PROTOCOLS];
+ int vrf_set = 0;
uword * p;
int rv = 0;
+ int i;
sw_if_index = ~0;
+ for (i = 0; i < IP_SOURCE_AND_PORT_RANGE_CHECK_N_PROTOCOLS; i++)
+ {
+ fib_index[i] = ~0;
+ vrf_id[i] = ~0;
+ }
while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
{
if (unformat (input, "%U", unformat_vnet_sw_interface, vnm,
- &sw_if_index))
- ;
- else if (unformat (input, "vrf %d", &vrf_id))
- ;
+ &sw_if_index))
+ ;
+ else if (unformat (input, "tcp-out-vrf %d", &vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_TCP_OUT]))
+ vrf_set = 1;
+ else if (unformat (input, "udp-out-vrf %d", &vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_UDP_OUT]))
+ vrf_set = 1;
+ else if (unformat (input, "tcp-in-vrf %d", &vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_TCP_IN]))
+ vrf_set = 1;
+ else if (unformat (input, "udp-in-vrf %d", &vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_UDP_IN]))
+ vrf_set = 1;
else if (unformat (input, "del"))
- is_add = 0;
+ is_add = 0;
else
- break;
+ break;
}
if (sw_if_index == ~0)
return clib_error_return (0, "Interface required but not specified");
- if (vrf_id == ~0)
- return clib_error_return (0, "VRF ID required but not specified");
+ if (!vrf_set)
+ return clib_error_return (0, "TCP or UDP VRF ID required but not specified");
- if (vrf_id == 0)
- return clib_error_return (0, "VRF ID should not be default. Should be distinct VRF for this purpose. ");
+ for (i = 0; i < IP_SOURCE_AND_PORT_RANGE_CHECK_N_PROTOCOLS; i++)
+ {
- p = hash_get (im->fib_index_by_table_id, vrf_id);
+ if (vrf_id[i] == 0)
+ return clib_error_return (0, "TCP, UDP VRF ID should not be 0 (default). Should be distinct VRF for this purpose. ");
- if (p == 0)
- return clib_error_return (0, "Invalid VRF ID %d", vrf_id);
+ if (vrf_id[i] != ~0)
+ {
+ p = hash_get (im->fib_index_by_table_id, vrf_id[i]);
- fib_index = p[0];
+ if (p == 0)
+ return clib_error_return (0, "Invalid VRF ID %d", vrf_id[i]);
+
+ fib_index[i] = p[0];
+ }
+ }
rv = set_ip_source_and_port_range_check (vm, fib_index, sw_if_index, is_add);
switch(rv)
@@ -543,7 +600,7 @@ VLIB_CLI_COMMAND (set_interface_ip_source_and_port_range_check_command,
static) = {
.path = "set interface ip source-and-port-range-check",
.function = set_ip_source_and_port_range_check_fn,
- .short_help = "set int ip source-and-port-range-check <intfc> vrf <n> [del]",
+ .short_help = "set int ip source-and-port-range-check <intfc> [tcp-out-vrf <n>] [udp-out-vrf <n>] [tcp-in-vrf <n>] [udp-in-vrf <n>] [del]",
};
static u8 * format_source_and_port_rc_adjacency (u8 * s, va_list * args)
@@ -554,11 +611,11 @@ static u8 * format_source_and_port_rc_adjacency (u8 * s, va_list * args)
ip_adjacency_t * adj = ip_get_adjacency (lm, adj_index);
source_range_check_main_t * srm = &source_range_check_main;
u8 * rwh = (u8 *) (&adj->rewrite_header);
- port_range_t * range;
+ protocol_port_range_t * range;
int i, j;
int printed = 0;
- range = (port_range_t *) rwh;
+ range = (protocol_port_range_t *) rwh;
s = format (s, "allow ");
@@ -594,8 +651,8 @@ clib_error_t * ip4_source_and_port_range_check_init (vlib_main_t * vm)
srm->ranges_per_adjacency = VLIB_BUFFER_PRE_DATA_SIZE / (2*sizeof(u16x8));
srm->special_adjacency_format_function_index =
- vnet_register_special_adjacency_format_function
- (lm, format_source_and_port_rc_adjacency);
+ vnet_register_special_adjacency_format_function
+ (lm, format_source_and_port_rc_adjacency);
ASSERT (srm->special_adjacency_format_function_index);
return 0;
@@ -603,155 +660,199 @@ clib_error_t * ip4_source_and_port_range_check_init (vlib_main_t * vm)
VLIB_INIT_FUNCTION (ip4_source_and_port_range_check_init);
-
-int ip4_source_and_port_range_check_add_del
-(ip4_address_t * address, u32 length, u32 vrf_id, u16 * low_ports,
- u16 * hi_ports, int is_add)
+int add_port_range_adjacency(ip4_address_t * address,
+ u32 length,
+ u32 adj_index,
+ u16 * low_ports,
+ u16 * high_ports,
+ u32 fib_index)
{
+ ip_adjacency_t * adj;
+ int i, j, k;
source_range_check_main_t * srm = &source_range_check_main;
ip4_main_t * im = &ip4_main;
ip_lookup_main_t * lm = &im->lookup_main;
- uword * p;
- u32 fib_index;
- u32 adj_index;
- ip_adjacency_t * adj;
- int i, j, k;
- port_range_t * range;
+ protocol_port_range_t * range;
u8 *rwh;
- p = hash_get (im->fib_index_by_table_id, vrf_id);
- if (!p)
- {
- ip4_fib_t * f;
- f = find_ip4_fib_by_table_index_or_id (im, vrf_id, 0 /* flags */);
- fib_index = f->index;
- }
- else
- fib_index = p[0];
+ adj = ip_get_adjacency (lm, adj_index);
+ /* $$$$ fixme: add ports if address + mask match */
+ if (adj->lookup_next_index == IP_LOOKUP_NEXT_ICMP_ERROR)
+ return VNET_API_ERROR_INCORRECT_ADJACENCY_TYPE;
- adj_index = ip4_fib_lookup_with_table
- (im, fib_index, address, 0 /* disable_default_route */);
+ ip_adjacency_t template_adj;
+ ip4_add_del_route_args_t a;
- if (is_add == 0)
- {
- adj = ip_get_adjacency (lm, adj_index);
- if (adj->lookup_next_index != IP_LOOKUP_NEXT_ICMP_ERROR)
- return VNET_API_ERROR_INCORRECT_ADJACENCY_TYPE;
+ memset (&template_adj, 0, sizeof (template_adj));
- rwh = (u8 *)(&adj->rewrite_header);
+ template_adj.lookup_next_index = IP_LOOKUP_NEXT_ICMP_ERROR;
+ template_adj.if_address_index = ~0;
+ template_adj.special_adjacency_format_function_index =
+ srm->special_adjacency_format_function_index;
- for (i = 0; i < vec_len (low_ports); i++)
+ rwh = (u8 *) (&template_adj.rewrite_header);
+
+ range = (protocol_port_range_t *) rwh;
+
+ if (vec_len (low_ports) > 8 * srm->ranges_per_adjacency)
+ return VNET_API_ERROR_EXCEEDED_NUMBER_OF_RANGES_CAPACITY;
+
+ j = k = 0;
+
+ for (i = 0; i < vec_len (low_ports); i++)
+ {
+ for (; j < srm->ranges_per_adjacency; j++)
{
- range = (port_range_t *) rwh;
- for (j = 0; j < srm->ranges_per_adjacency; j++)
+ for (; k < 8; k++)
{
- for (k = 0; k < 8; k++)
+ if (range->low.as_u16[k] == 0)
{
- if (low_ports[i] == range->low.as_u16[k] &&
- hi_ports[i] == range->hi.as_u16[k])
+ range->low.as_u16[k] = low_ports[i];
+ range->hi.as_u16[k] = high_ports[i];
+ k++;
+ if (k == 7)
{
- range->low.as_u16[k] = range->hi.as_u16[k] = 0;
- goto doublebreak;
+ k = 0;
+ j++;
}
+ goto doublebreak2;
}
- range++;
}
- doublebreak: ;
+ k = 0;
+ range++;
}
+ j = 0;
+ /* Too many ports specified... */
+ return VNET_API_ERROR_EXCEEDED_NUMBER_OF_PORTS_CAPACITY;
- range = (port_range_t *) rwh;
- /* Have we deleted all ranges yet? */
- for (i = 0; i < srm->ranges_per_adjacency; i++)
+ doublebreak2: ;
+ }
+
+ memset (&a, 0, sizeof(a));
+ a.flags = IP4_ROUTE_FLAG_FIB_INDEX;
+ a.table_index_or_table_id = fib_index;
+ a.dst_address = address[0];
+ a.dst_address_length = length;
+ a.add_adj = &template_adj;
+ a.n_add_adj = 1;
+
+ ip4_add_del_route (im, &a);
+ return 0;
+}
+
+int remove_port_range_adjacency(ip4_address_t * address,
+ u32 length,
+ u32 adj_index,
+ u16 * low_ports,
+ u16 * high_ports,
+ u32 fib_index)
+{
+ ip_adjacency_t * adj;
+ int i, j, k;
+ source_range_check_main_t * srm = &source_range_check_main;
+ ip4_main_t * im = &ip4_main;
+ ip_lookup_main_t * lm = &im->lookup_main;
+ protocol_port_range_t * range;
+ u8 *rwh;
+
+ adj = ip_get_adjacency (lm, adj_index);
+ if (adj->lookup_next_index != IP_LOOKUP_NEXT_ICMP_ERROR) /* _ICMP_ERROR is a dummy placeholder */
+ return VNET_API_ERROR_INCORRECT_ADJACENCY_TYPE;
+
+ rwh = (u8 *)(&adj->rewrite_header);
+
+ for (i = 0; i < vec_len (low_ports); i++)
+ {
+ range = (protocol_port_range_t *) rwh;
+ for (j = 0; j < srm->ranges_per_adjacency; j++)
{
- for (j = 0; j < 8; j++)
+ for (k = 0; k < 8; k++)
{
- if (range->low.as_u16[i] != 0)
- goto still_occupied;
+ if (low_ports[i] == range->low.as_u16[k] &&
+ high_ports[i] == range->hi.as_u16[k])
+ {
+ range->low.as_u16[k] = range->hi.as_u16[k] = 0;
+ goto doublebreak;
+ }
}
range++;
}
- /* Yes, lose the adjacency... */
- {
- ip4_add_del_route_args_t a;
-
- memset (&a, 0, sizeof(a));
- a.flags = IP4_ROUTE_FLAG_FIB_INDEX | IP4_ROUTE_FLAG_DEL;
- a.table_index_or_table_id = fib_index;
- a.dst_address = address[0];
- a.dst_address_length = length;
- a.adj_index = adj_index;
- ip4_add_del_route (im, &a);
- }
-
- still_occupied:
- ;
+ doublebreak: ;
}
- else
- {
- adj = ip_get_adjacency (lm, adj_index);
- /* $$$$ fixme: add ports if address + mask match */
- if (adj->lookup_next_index == IP_LOOKUP_NEXT_ICMP_ERROR)
- return VNET_API_ERROR_INCORRECT_ADJACENCY_TYPE;
- {
- ip_adjacency_t template_adj;
- ip4_add_del_route_args_t a;
-
- memset (&template_adj, 0, sizeof (template_adj));
-
- template_adj.lookup_next_index = IP_LOOKUP_NEXT_ICMP_ERROR;
- template_adj.if_address_index = ~0;
- template_adj.special_adjacency_format_function_index =
- srm->special_adjacency_format_function_index;
-
- rwh = (u8 *) (&template_adj.rewrite_header);
+ range = (protocol_port_range_t *) rwh;
+ /* Have we deleted all ranges yet? */
+ for (i = 0; i < srm->ranges_per_adjacency; i++)
+ {
+ for (j = 0; j < 8; j++)
+ {
+ if (range->low.as_u16[i] != 0)
+ goto still_occupied;
+ }
+ range++;
+ }
+ /* Yes, lose the adjacency... */
+ {
+ ip4_add_del_route_args_t a;
- range = (port_range_t *) rwh;
+ memset (&a, 0, sizeof(a));
+ a.flags = IP4_ROUTE_FLAG_FIB_INDEX | IP4_ROUTE_FLAG_DEL;
+ a.table_index_or_table_id = fib_index;
+ a.dst_address = address[0];
+ a.dst_address_length = length;
+ a.adj_index = adj_index;
+ ip4_add_del_route (im, &a);
+ }
+
+ still_occupied:
+ ;
+ return 0;
+}
- if (vec_len (low_ports) > 8 * srm->ranges_per_adjacency)
- return VNET_API_ERROR_EXCEEDED_NUMBER_OF_RANGES_CAPACITY;
+// This will be moved to another file and implemented post API freeze.
+int ip6_source_and_port_range_check_add_del (ip6_address_t * address,
+ u32 length,
+ u32 vrf_id,
+ u16 * low_ports,
+ u16 * high_ports,
+ int is_add)
+{
+ return 0;
+}
+int ip4_source_and_port_range_check_add_del (ip4_address_t * address,
+ u32 length,
+ u32 vrf_id,
+ u16 * low_ports,
+ u16 * high_ports,
+ int is_add)
+{
- j = k = 0;
+ ip4_main_t * im = &ip4_main;
+ // ip_lookup_main_t * lm = &im->lookup_main;
+ uword * p;
+ u32 fib_index;
+ u32 adj_index;
- for (i = 0; i < vec_len (low_ports); i++)
- {
- for (; j < srm->ranges_per_adjacency; j++)
- {
- for (; k < 8; k++)
- {
- if (range->low.as_u16[k] == 0)
- {
- range->low.as_u16[k] = low_ports[i];
- range->hi.as_u16[k] = hi_ports[i];
- k++;
- if (k == 7)
- {
- k = 0;
- j++;
- }
- goto doublebreak2;
- }
- }
- k = 0;
- range++;
- }
- j = 0;
- /* Too many ports specified... */
- return VNET_API_ERROR_EXCEEDED_NUMBER_OF_PORTS_CAPACITY;
-
- doublebreak2: ;
- }
+ p = hash_get (im->fib_index_by_table_id, vrf_id);
+ if (!p)
+ {
+ ip4_fib_t * f;
+ f = find_ip4_fib_by_table_index_or_id (im, vrf_id, 0 /* flags */);
+ fib_index = f->index;
+ }
+ else
+ fib_index = p[0];
- memset (&a, 0, sizeof(a));
- a.flags = IP4_ROUTE_FLAG_FIB_INDEX;
- a.table_index_or_table_id = fib_index;
- a.dst_address = address[0];
- a.dst_address_length = length;
- a.add_adj = &template_adj;
- a.n_add_adj = 1;
+ adj_index = ip4_fib_lookup_with_table
+ (im, fib_index, address, 0 /* disable_default_route */);
- ip4_add_del_route (im, &a);
- }
+ if (is_add == 0)
+ {
+ remove_port_range_adjacency(address, length, adj_index, low_ports, high_ports, fib_index);
+ }
+ else
+ {
+ add_port_range_adjacency(address, length, adj_index, low_ports, high_ports, fib_index);
}
return 0;
@@ -766,18 +867,21 @@ ip_source_and_port_range_check_command_fn (vlib_main_t * vm,
u16 * high_ports = 0;
u16 this_low;
u16 this_hi;
- ip4_address_t addr;
+ ip4_address_t ip4_addr;
+ ip6_address_t ip6_addr; //This function will be moved to generic impl when v6 done.
u32 length;
u32 tmp, tmp2;
- u8 prefix_set = 0;
u32 vrf_id = ~0;
- int is_add = 1;
+ int is_add = 1, ip_ver = ~0;
int rv;
+
while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
{
- if (unformat (input, "%U/%d", unformat_ip4_address, &addr, &length))
- prefix_set = 1;
+ if (unformat (input, "%U/%d", unformat_ip4_address, &ip4_addr, &length))
+ ip_ver = 4;
+ else if (unformat (input, "%U/%d", unformat_ip6_address, &ip6_addr, &length))
+ ip_ver = 6;
else if (unformat (input, "vrf %d", &vrf_id))
;
else if (unformat (input, "del"))
@@ -799,7 +903,7 @@ ip_source_and_port_range_check_command_fn (vlib_main_t * vm,
if (tmp == 0 || tmp > 65535)
return clib_error_return (0, "low port %d out of range", tmp);
if (tmp2 == 0 || tmp2 > 65535)
- return clib_error_return (0, "hi port %d out of range", tmp2);
+ return clib_error_return (0, "high port %d out of range", tmp2);
this_low = tmp;
this_hi = tmp2+1;
vec_add1 (low_ports, this_low);
@@ -809,20 +913,24 @@ ip_source_and_port_range_check_command_fn (vlib_main_t * vm,
break;
}
- if (prefix_set == 0)
- return clib_error_return (0, "<address>/<mask> not specified");
+ if (ip_ver == ~0)
+ return clib_error_return (0, " <address>/<mask> not specified");
if (vrf_id == ~0)
- return clib_error_return (0, "VRF ID required, not specified");
+ return clib_error_return (0, " VRF ID required, not specified");
+
+ if ( vec_len (low_ports) == 0)
+ return clib_error_return (0, " Both VRF ID and range/port must be set for a protocol.");
if (vrf_id == 0)
- return clib_error_return (0, "VRF ID should not be default. Should be distinct VRF for this purpose. ");
+ return clib_error_return (0, " VRF ID can not be 0 (default).");
- if (vec_len(low_ports) == 0)
- return clib_error_return (0, "At least one port or port range required");
- rv = ip4_source_and_port_range_check_add_del
- (&addr, length, vrf_id, low_ports, high_ports, is_add);
+ if (ip_ver == 4)
+ rv = ip4_source_and_port_range_check_add_del
+ (&ip4_addr, length, vrf_id, low_ports, high_ports, is_add);
+ else
+ return clib_error_return (0, " IPv6 in subsequent patch");
switch(rv)
{
@@ -831,19 +939,19 @@ ip_source_and_port_range_check_command_fn (vlib_main_t * vm,
case VNET_API_ERROR_INCORRECT_ADJACENCY_TYPE:
return clib_error_return
- (0, "Incorrect adjacency for add/del operation in ip4 source and port-range check.");
+ (0, " Incorrect adjacency for add/del operation");
case VNET_API_ERROR_EXCEEDED_NUMBER_OF_PORTS_CAPACITY:
return clib_error_return
- (0, "Too many ports in add/del operation in ip4 source and port-range check.");
+ (0, " Too many ports in add/del operation");
case VNET_API_ERROR_EXCEEDED_NUMBER_OF_RANGES_CAPACITY:
return clib_error_return
- (0, "Too many ranges requested for add operation in ip4 source and port-range check.");
+ (0, " Too many ranges requested for add operation");
default:
return clib_error_return
- (0, "ip4_source_and_port_range_check_add returned an unexpected value: %d", rv);
+ (0, " returned an unexpected value: %d", rv);
}
return 0;
@@ -853,7 +961,7 @@ VLIB_CLI_COMMAND (ip_source_and_port_range_check_command, static) = {
.path = "set ip source-and-port-range-check",
.function = ip_source_and_port_range_check_command_fn,
.short_help =
- "set ip source-and-port-range-check <ip-addr>/<mask> range <nn>-<nn> vrf <id>",
+ "set ip source-and-port-range-check <ip-addr>/<mask> [range <nn>-<nn> tcp-vrf <id>] [vrf <id>] [del]",
};
@@ -865,7 +973,7 @@ show_source_and_port_range_check_fn (vlib_main_t * vm,
source_range_check_main_t * srm = & source_range_check_main;
ip4_main_t * im = &ip4_main;
ip_lookup_main_t * lm = &im->lookup_main;
- port_range_t * range;
+ protocol_port_range_t * range;
u32 fib_index;
ip4_address_t addr;
u8 addr_set = 0;
@@ -929,7 +1037,7 @@ show_source_and_port_range_check_fn (vlib_main_t * vm,
s = format (0, "%U: ", format_ip4_address, &addr);
- range = (port_range_t *) rwh;
+ range = (protocol_port_range_t *) rwh;
for (i = 0; i < srm->ranges_per_adjacency; i++)
{
diff --git a/vnet/vnet/ip/ip_source_and_port_range_check.h b/vnet/vnet/ip/ip_source_and_port_range_check.h
index 7fbb2b0f702..1429057bf1d 100644
--- a/vnet/vnet/ip/ip_source_and_port_range_check.h
+++ b/vnet/vnet/ip/ip_source_and_port_range_check.h
@@ -16,6 +16,44 @@
#ifndef included_ip_ip_source_and_port_range_check_h
#define included_ip_ip_source_and_port_range_check_h
+
+typedef struct {
+ u32 ranges_per_adjacency;
+ u32 special_adjacency_format_function_index;
+
+ /* convenience */
+ vlib_main_t *vlib_main;
+ vnet_main_t *vnet_main;
+} source_range_check_main_t;
+
+source_range_check_main_t source_range_check_main;
+
+typedef enum {
+ IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_TCP_OUT,
+ IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_UDP_OUT,
+ IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_TCP_IN,
+ IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_UDP_IN,
+ IP_SOURCE_AND_PORT_RANGE_CHECK_N_PROTOCOLS,
+} ip_source_and_port_range_check_protocol_t;
+
+typedef struct {
+ u32 fib_index[IP_SOURCE_AND_PORT_RANGE_CHECK_N_PROTOCOLS];
+} ip_source_and_port_range_check_config_t;
+
+#define IP_SOURCE_AND_PORT_RANGE_CHECK_RANGE_LIMIT VLIB_BUFFER_PRE_DATA_SIZE/(2*sizeof(u16x8));
+
+typedef struct {
+ union {
+ u16x8 as_u16x8;
+ u16 as_u16[8];
+ };
+} u16x8vec_t;
+
+typedef struct {
+ u16x8vec_t low;
+ u16x8vec_t hi;
+} protocol_port_range_t;
+
int ip4_source_and_port_range_check_add_del (ip4_address_t * address,
u32 length,
u32 vrf_id,
@@ -23,8 +61,16 @@ int ip4_source_and_port_range_check_add_del (ip4_address_t * address,
u16 * hi_ports,
int is_add);
+// This will be moved to another file in another patch -- for API freeze
+int ip6_source_and_port_range_check_add_del (ip6_address_t * address,
+ u32 length,
+ u32 vrf_id,
+ u16 * low_ports,
+ u16 * hi_ports,
+ int is_add);
+
int set_ip_source_and_port_range_check (vlib_main_t * vm,
- u32 fib_index,
+ u32 * fib_index,
u32 sw_if_index,
u32 is_add);
diff --git a/vpp-api-test/vat/api_format.c b/vpp-api-test/vat/api_format.c
index 3590a076d85..d410955e9ff 100644
--- a/vpp-api-test/vat/api_format.c
+++ b/vpp-api-test/vat/api_format.c
@@ -13557,34 +13557,45 @@ int api_ip_source_and_port_range_check_interface_add_del (vat_main_t * vam)
vl_api_ip_source_and_port_range_check_interface_add_del_t *mp;
f64 timeout;
u32 sw_if_index = ~0;
- u32 vrf_id = ~0;
+ int vrf_set = 0;
+ u32 tcp_out_vrf_id = ~0, udp_out_vrf_id = ~0;
+ u32 tcp_in_vrf_id = ~0, udp_in_vrf_id = ~0;
u8 is_add = 1;
while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (input, "%U", unformat_sw_if_index, vam, &sw_if_index))
+ {
+ if (unformat (input, "%U", unformat_sw_if_index, vam, &sw_if_index))
;
- else if (unformat (input, "sw_if_index %d", &sw_if_index))
+ else if (unformat (input, "sw_if_index %d", &sw_if_index))
;
- else if (unformat (input, "vrf %d", &vrf_id))
- ;
- else if (unformat (input, "del"))
- is_add = 0;
- else
- break;
- }
+ else if (unformat (input, "tcp-out-vrf %d", &tcp_out_vrf_id))
+ vrf_set=1;
+ else if (unformat (input, "udp-out-vrf %d", &udp_out_vrf_id))
+ vrf_set=1;
+ else if (unformat (input, "tcp-in-vrf %d", &tcp_in_vrf_id))
+ vrf_set=1;
+ else if (unformat (input, "udp-in-vrf %d", &udp_in_vrf_id))
+ vrf_set=1;
+ else if (unformat (input, "del"))
+ is_add = 0;
+ else
+ break;
+ }
if (sw_if_index == ~0) {
- errmsg ("Interface required but not specified\n");
- return -99;
+ errmsg ("Interface required but not specified\n");
+ return -99;
}
- if (vrf_id == ~0) {
+ if (vrf_set == 0) {
errmsg ("VRF ID required but not specified\n");
return -99;
}
- if (vrf_id == 0) {
+ if (tcp_out_vrf_id == 0
+ || udp_out_vrf_id == 0
+ || tcp_in_vrf_id == 0
+ || udp_in_vrf_id == 0) {
errmsg ("VRF ID should not be default. Should be distinct VRF for this purpose.\n");
return -99;
}
@@ -13594,7 +13605,10 @@ int api_ip_source_and_port_range_check_interface_add_del (vat_main_t * vam)
mp->sw_if_index = ntohl (sw_if_index);
mp->is_add = is_add;
- mp->vrf_id = ntohl (vrf_id);
+ mp->tcp_out_vrf_id = ntohl (tcp_out_vrf_id);
+ mp->udp_out_vrf_id = ntohl (udp_out_vrf_id);
+ mp->tcp_in_vrf_id = ntohl (tcp_in_vrf_id);
+ mp->udp_in_vrf_id = ntohl (udp_in_vrf_id);
/* send it... */
S;
@@ -14135,7 +14149,8 @@ _(pg_enable_disable, "[stream <id>] disable") \
_(ip_source_and_port_range_check_add_del, \
"<ip-addr>/<mask> range <nn>-<nn> vrf <id>") \
_(ip_source_and_port_range_check_interface_add_del, \
- "<intf> | sw_if_index <nn> vrf <id>")
+ "<intf> | sw_if_index <nn> [tcp-out-vrf <id>] [tcp-in-vrf <id>]" \
+ "[udp-in-vrf <id>] [udp-out-vrf <id>]")
/* List of command functions, CLI names map directly to functions */
#define foreach_cli_function \
diff --git a/vpp/vpp-api/api.c b/vpp/vpp-api/api.c
index 73ecbd7237f..18999a5f7bb 100644
--- a/vpp/vpp-api/api.c
+++ b/vpp/vpp-api/api.c
@@ -7380,13 +7380,13 @@ static void vl_api_ip_source_and_port_range_check_add_del_t_handler (
u8 is_add = mp->is_add;
u8 mask_length = mp->mask_length;
ip4_address_t ip4_addr;
- //ip6_address_t ip6_addr;
- u16 * low_ports = 0 ;
- u16 * high_ports = 0 ;
+ ip6_address_t ip6_addr;
+ u16 * low_ports = 0;
+ u16 * high_ports = 0;
+ u32 vrf_id;
u16 tmp_low, tmp_high;
u8 num_ranges ;
int i;
- u32 vrf_id;
// Validate port range
num_ranges = mp->number_of_ranges;
@@ -7415,8 +7415,8 @@ static void vl_api_ip_source_and_port_range_check_add_del_t_handler (
if (mask_length < 0 ||
( is_ipv6 && mask_length > 128) ||
( !is_ipv6 && mask_length > 32)) {
- rv = VNET_API_ERROR_ADDRESS_LENGTH_MISMATCH;
- goto reply;
+ rv = VNET_API_ERROR_ADDRESS_LENGTH_MISMATCH;
+ goto reply;
}
vrf_id = ntohl (mp->vrf_id);
@@ -7425,33 +7425,31 @@ static void vl_api_ip_source_and_port_range_check_add_del_t_handler (
rv = VNET_API_ERROR_INVALID_VALUE;
goto reply;
}
- //ip6
+
+
if (is_ipv6) {
- /* clib_memcpy (ip6_addr.as_u8, mp->address, */
- /* sizeof (ip6_addr.as_u8)); */
- /* rv = ip6_source_and_port_range_check_add_del (ip6_addr, */
- /* mask_length, */
- /* vrf_id, */
- /* low_ports, */
- /* high_ports, */
- /* is_add); */
-
- //ip4
- } else {
- clib_memcpy (ip4_addr.data, mp->address,
- sizeof (ip4_addr));
- rv = ip4_source_and_port_range_check_add_del (&ip4_addr,
+ clib_memcpy (ip6_addr.as_u8, mp->address,
+ sizeof (ip6_addr.as_u8));
+ rv = ip6_source_and_port_range_check_add_del (&ip6_addr,
mask_length,
vrf_id,
low_ports,
high_ports,
is_add);
+ } else {
+ clib_memcpy (ip4_addr.data, mp->address,
+ sizeof (ip4_addr));
+ rv = ip4_source_and_port_range_check_add_del (&ip4_addr,
+ mask_length,
+ vrf_id,
+ low_ports,
+ high_ports,
+ is_add);
}
reply:
vec_free (low_ports);
vec_free (high_ports);
-
REPLY_MACRO(VL_API_IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL_REPLY);
}
@@ -7463,20 +7461,35 @@ vl_api_ip_source_and_port_range_check_interface_add_del_t_handler
vl_api_ip_source_and_port_range_check_interface_add_del_reply_t * rmp;
ip4_main_t * im = &ip4_main;
int rv;
- u32 sw_if_index, fib_index, vrf_id;
+ u32 sw_if_index;
+ u32 fib_index[IP_SOURCE_AND_PORT_RANGE_CHECK_N_PROTOCOLS];
+ u32 vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_N_PROTOCOLS];
uword * p = 0;
+ int i;
- vrf_id = ntohl(mp->vrf_id);
+ vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_TCP_OUT] = ntohl(mp->tcp_out_vrf_id);
+ vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_UDP_OUT] = ntohl(mp->udp_out_vrf_id);
+ vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_TCP_IN] = ntohl(mp->tcp_in_vrf_id);
+ vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_UDP_IN] = ntohl(mp->udp_in_vrf_id);
- p = hash_get (im->fib_index_by_table_id, vrf_id);
- if (p == 0) {
- rv = VNET_API_ERROR_INVALID_VALUE;
- goto reply;
- }
+ for (i = 0; i < IP_SOURCE_AND_PORT_RANGE_CHECK_N_PROTOCOLS; i++)
+ {
+ if (vrf_id[i] !=0 && vrf_id[i] != ~0)
+ {
+ p = hash_get (im->fib_index_by_table_id, vrf_id[i]);
- fib_index = p[0];
+ if (p == 0)
+ {
+ rv = VNET_API_ERROR_INVALID_VALUE;
+ goto reply;
+ }
+ fib_index[i] = p[0];
+ }
+ else
+ fib_index[i] = ~0;
+ }
sw_if_index = ntohl(mp->sw_if_index);
VALIDATE_SW_IF_INDEX(mp);
diff --git a/vpp/vpp-api/custom_dump.c b/vpp/vpp-api/custom_dump.c
index 51bf81d92cf..bf02ac4335b 100644
--- a/vpp/vpp-api/custom_dump.c
+++ b/vpp/vpp-api/custom_dump.c
@@ -2099,7 +2099,7 @@ static void *vl_api_ip_source_and_port_range_check_add_del_t_print
mp->mask_length);
for (i = 0; i < mp->number_of_ranges; i++) {
- s = format (s, "range %d - %d", mp->low_ports[i], mp->high_ports[i]);
+ s = format (s, "range %d - %d ", mp->low_ports[i], mp->high_ports[i]);
}
s = format (s, "vrf %d ", ntohl(mp->vrf_id));
@@ -2117,9 +2117,19 @@ static void *vl_api_ip_source_and_port_range_check_interface_add_del_t_print
s = format (0, "SCRIPT: ip_source_and_port_range_check_interface_add_del ");
- s = format (s, "%d ", ntohl(mp->sw_if_index));
+ s = format (s, "sw_if_index %d ", ntohl(mp->sw_if_index));
- s = format (s, "vrf %d ", ntohl(mp->vrf_id));
+ if (mp->tcp_out_vrf_id != ~0)
+ s = format (s, "tcp-out-vrf %d ", ntohl(mp->tcp_out_vrf_id));
+
+ if (mp->udp_out_vrf_id != ~0)
+ s = format (s, "udp-out-vrf %d ", ntohl(mp->udp_out_vrf_id));
+
+ if (mp->tcp_in_vrf_id != ~0)
+ s = format (s, "tcp-in-vrf %d ", ntohl(mp->tcp_in_vrf_id));
+
+ if (mp->udp_in_vrf_id != ~0)
+ s = format (s, "udp-in-vrf %d ", ntohl(mp->udp_in_vrf_id));
if (mp->is_add == 0)
s = format (s, "del ");
diff --git a/vpp/vpp-api/vpe.api b/vpp/vpp-api/vpe.api
index 67e742e7155..4b8aa818d8d 100644
--- a/vpp/vpp-api/vpe.api
+++ b/vpp/vpp-api/vpe.api
@@ -4342,7 +4342,7 @@ define pg_capture_reply {
@param client_index - opaque cookie to identify the sender
@param context - sender context, to match reply w/ request
@param is_enabled - 1 if enabling streams, 0 if disabling
- @param stream - stream name to be enable/disabled, if not specified handle all streams
+ @param stream - stream name to be enable/disabled, if not specified handle all streams
*/
define pg_enable_disable {
u32 client_index;
@@ -4368,6 +4368,7 @@ define pg_enable_disable_reply {
@param is_add - 1 if add, 0 if delete
@param mask_length - mask length for address entry
@param address - array of address bytes
+ @param number_of_ranges - length of low_port and high_port arrays (must match)
@param low_ports[32] - up to 32 low end of port range entries (must have corresponding high_ports entry)
@param high_ports[32] - up to 32 high end of port range entries (must have corresponding low_ports entry)
@param vrf_id - fib table/vrf id to associate the source and port-range check with
@@ -4399,14 +4400,18 @@ define ip_source_and_port_range_check_add_del_reply {
@param client_index - opaque cookie to identify the sender
@param context - sender context, to match reply w/ request
@param interface_id - interface index
- @param vrf_id - VRF associated with source and L4 port-range check
+ @param tcp_vrf_id - VRF associated with source and TCP port-range check
+ @param udp_vrf_id - VRF associated with source and TCP port-range check
*/
define ip_source_and_port_range_check_interface_add_del {
u32 client_index;
u32 context;
u8 is_add;
u32 sw_if_index;
- u32 vrf_id;
+ u32 tcp_in_vrf_id;
+ u32 tcp_out_vrf_id;
+ u32 udp_in_vrf_id;
+ u32 udp_out_vrf_id;
};
/** \brief Set interface source and L4 port-range response