summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Yourtchenko <ayourtch@gmail.com>2018-05-27 17:41:27 +0200
committerDamjan Marion <dmarion@me.com>2018-06-17 12:05:55 +0000
commite0b6c8a96d6d3fce583d0ef4b851a50a74afba5d (patch)
treebc338e43ed637e64ed4f8ebdfada376057eef357
parentc1c5baa1a99c5754cfa73c679ed4fe664ef3f881 (diff)
acl-plugin: split (L3) and (L4/pkt) logic of creation of 5tuple structure, optimize stores in the (l4/pkt)
Having two pieces of code - one for now much simpler to recreate L3 info, one for a more difficult do build L4/pkt metadata allows more degrees of freedom for optimizations. Also, construct the metadata in local variables first before saving it into the memory structure, this fewer memory stores and they are better aligned, allowing to coalesce with subsequent reads if needed. Change-Id: Icb35d933834b14294f875362c9b58db3feb38d99 Signed-off-by: Andrew Yourtchenko <ayourtch@gmail.com>
-rw-r--r--src/plugins/acl/public_inlines.h116
1 files changed, 70 insertions, 46 deletions
diff --git a/src/plugins/acl/public_inlines.h b/src/plugins/acl/public_inlines.h
index 6d8f0ddb125..b358f640ffb 100644
--- a/src/plugins/acl/public_inlines.h
+++ b/src/plugins/acl/public_inlines.h
@@ -182,43 +182,46 @@ offset_within_packet (vlib_buffer_t * b0, int offset)
return (offset <= (b0->current_length - 8));
}
+
always_inline void
-acl_fill_5tuple (acl_main_t * am, vlib_buffer_t * b0, int is_ip6,
- int is_input, int is_l2_path, fa_5tuple_t * p5tuple_pkt)
+acl_fill_5tuple_l3_data (acl_main_t * am, vlib_buffer_t * b0, int is_ip6,
+ int l3_offset, fa_5tuple_t * p5tuple_pkt)
+{
+ if (is_ip6)
+ {
+ clib_memcpy (&p5tuple_pkt->ip6_addr,
+ get_ptr_to_offset (b0,
+ offsetof (ip6_header_t,
+ src_address) + l3_offset),
+ sizeof (p5tuple_pkt->ip6_addr));
+ }
+ else
+ {
+ memset(p5tuple_pkt->l3_zero_pad, 0, sizeof(p5tuple_pkt->l3_zero_pad));
+ clib_memcpy (&p5tuple_pkt->ip4_addr,
+ get_ptr_to_offset (b0,
+ offsetof (ip4_header_t,
+ src_address) + l3_offset),
+ sizeof (p5tuple_pkt->ip4_addr));
+ }
+}
+
+always_inline void
+acl_fill_5tuple_l4_and_pkt_data (acl_main_t * am, u32 sw_if_index0, vlib_buffer_t * b0, int is_ip6, int is_input,
+ int l3_offset, fa_session_l4_key_t *p5tuple_l4, fa_packet_info_t *p5tuple_pkt)
{
/* IP4 and IP6 protocol numbers of ICMP */
static u8 icmp_protos_v4v6[] = { IP_PROTOCOL_ICMP, IP_PROTOCOL_ICMP6 };
- int l3_offset;
int l4_offset;
u16 ports[2];
u8 proto;
- if (is_l2_path)
- {
- l3_offset = ethernet_buffer_header_size(b0);
- }
- else
- {
- if (is_input)
- l3_offset = 0;
- else
- l3_offset = vnet_buffer(b0)->ip.save_rewrite_length;
- }
-
- /* key[0..3] contains src/dst address and is cleared/set below */
- /* Remainder of the key and per-packet non-key data */
- p5tuple_pkt->kv_40_8.key[4] = 0;
- p5tuple_pkt->kv_40_8.value = 0;
- p5tuple_pkt->pkt.is_ip6 = is_ip6;
+ fa_session_l4_key_t tmp_l4 = { .lsb_of_sw_if_index = sw_if_index0 & 0xffff };
+ fa_packet_info_t tmp_pkt = { .is_ip6 = is_ip6, .mask_type_index_lsb = ~0 };
if (is_ip6)
{
- clib_memcpy (&p5tuple_pkt->ip6_addr,
- get_ptr_to_offset (b0,
- offsetof (ip6_header_t,
- src_address) + l3_offset),
- sizeof (p5tuple_pkt->ip6_addr));
proto =
*(u8 *) get_ptr_to_offset (b0,
offsetof (ip6_header_t,
@@ -243,7 +246,7 @@ acl_fill_5tuple (acl_main_t * am, vlib_buffer_t * b0, int is_ip6,
frag_offset = clib_net_to_host_u16(frag_offset) >> 3;
if (frag_offset)
{
- p5tuple_pkt->pkt.is_nonfirst_fragment = 1;
+ tmp_pkt.is_nonfirst_fragment = 1;
/* invalidate L4 offset so we don't try to find L4 info */
l4_offset += b0->current_length;
}
@@ -270,12 +273,6 @@ acl_fill_5tuple (acl_main_t * am, vlib_buffer_t * b0, int is_ip6,
}
else
{
- memset(p5tuple_pkt->l3_zero_pad, 0, sizeof(p5tuple_pkt->l3_zero_pad));
- clib_memcpy (&p5tuple_pkt->ip4_addr,
- get_ptr_to_offset (b0,
- offsetof (ip4_header_t,
- src_address) + l3_offset),
- sizeof (p5tuple_pkt->ip4_addr));
proto =
*(u8 *) get_ptr_to_offset (b0,
offsetof (ip4_header_t,
@@ -292,31 +289,31 @@ acl_fill_5tuple (acl_main_t * am, vlib_buffer_t * b0, int is_ip6,
/* non-initial fragments have non-zero offset */
if ((PREDICT_FALSE(0xfff & flags_and_fragment_offset)))
{
- p5tuple_pkt->pkt.is_nonfirst_fragment = 1;
+ tmp_pkt.is_nonfirst_fragment = 1;
/* invalidate L4 offset so we don't try to find L4 info */
l4_offset += b0->current_length;
}
}
- p5tuple_pkt->l4.proto = proto;
- p5tuple_pkt->l4.is_input = is_input;
+ tmp_l4.proto = proto;
+ tmp_l4.is_input = is_input;
if (PREDICT_TRUE (offset_within_packet (b0, l4_offset)))
{
- p5tuple_pkt->pkt.l4_valid = 1;
+ tmp_pkt.l4_valid = 1;
if (icmp_protos_v4v6[is_ip6] == proto)
{
/* type */
- p5tuple_pkt->l4.port[0] =
+ tmp_l4.port[0] =
*(u8 *) get_ptr_to_offset (b0,
l4_offset + offsetof (icmp46_header_t,
type));
/* code */
- p5tuple_pkt->l4.port[1] =
+ tmp_l4.port[1] =
*(u8 *) get_ptr_to_offset (b0,
l4_offset + offsetof (icmp46_header_t,
code));
- p5tuple_pkt->l4.is_slowpath = 1;
+ tmp_l4.is_slowpath = 1;
}
else if ((IP_PROTOCOL_TCP == proto) || (IP_PROTOCOL_UDP == proto))
{
@@ -325,21 +322,48 @@ acl_fill_5tuple (acl_main_t * am, vlib_buffer_t * b0, int is_ip6,
l4_offset + offsetof (tcp_header_t,
src_port)),
sizeof (ports));
- p5tuple_pkt->l4.port[0] = clib_net_to_host_u16 (ports[0]);
- p5tuple_pkt->l4.port[1] = clib_net_to_host_u16 (ports[1]);
+ tmp_l4.port[0] = clib_net_to_host_u16 (ports[0]);
+ tmp_l4.port[1] = clib_net_to_host_u16 (ports[1]);
- p5tuple_pkt->pkt.tcp_flags =
+ tmp_pkt.tcp_flags =
*(u8 *) get_ptr_to_offset (b0,
l4_offset + offsetof (tcp_header_t,
flags));
- p5tuple_pkt->pkt.tcp_flags_valid = (proto == IP_PROTOCOL_TCP);
- p5tuple_pkt->l4.is_slowpath = 0;
+ tmp_pkt.tcp_flags_valid = (proto == IP_PROTOCOL_TCP);
+ tmp_l4.is_slowpath = 0;
}
else
{
- p5tuple_pkt->l4.is_slowpath = 1;
+ tmp_l4.is_slowpath = 1;
}
}
+
+ p5tuple_pkt->as_u64 = tmp_pkt.as_u64;
+ p5tuple_l4->as_u64 = tmp_l4.as_u64;
+}
+
+always_inline void
+acl_fill_5tuple (acl_main_t * am, u32 sw_if_index0, vlib_buffer_t * b0, int is_ip6,
+ int is_input, int is_l2_path, fa_5tuple_t * p5tuple_pkt)
+{
+ int l3_offset;
+
+ if (is_l2_path)
+ {
+ l3_offset = ethernet_buffer_header_size(b0);
+ }
+ else
+ {
+ if (is_input)
+ l3_offset = 0;
+ else
+ l3_offset = vnet_buffer(b0)->ip.save_rewrite_length;
+ }
+
+ /* key[0..3] contains src/dst address and is cleared/set below */
+ /* Remainder of the key and per-packet non-key data */
+ acl_fill_5tuple_l3_data(am, b0, is_ip6, l3_offset, p5tuple_pkt);
+ acl_fill_5tuple_l4_and_pkt_data(am, sw_if_index0, b0, is_ip6, is_input, l3_offset, &p5tuple_pkt->l4, &p5tuple_pkt->pkt);
}
always_inline void
@@ -347,7 +371,7 @@ acl_plugin_fill_5tuple_inline (u32 lc_index, vlib_buffer_t * b0, int is_ip6,
int is_input, int is_l2_path, fa_5tuple_opaque_t * p5tuple_pkt)
{
acl_main_t *am = p_acl_main;
- acl_fill_5tuple(am, b0, is_ip6, is_input, is_l2_path, (fa_5tuple_t *)p5tuple_pkt);
+ acl_fill_5tuple(am, 0, b0, is_ip6, is_input, is_l2_path, (fa_5tuple_t *)p5tuple_pkt);
}