aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/acl/public_inlines.h
diff options
context:
space:
mode:
authorAndrew Yourtchenko <ayourtch@gmail.com>2018-10-25 19:01:49 +0200
committerFlorin Coras <florin.coras@gmail.com>2018-11-05 21:53:43 +0000
commit87ee947d0b053b33571c5e33617b138236bada59 (patch)
tree5f4fb61107d8ffa2faba1743c4b62c583724745b /src/plugins/acl/public_inlines.h
parentb0073e276d9e12f02f8f9874fd09ae532a0baa47 (diff)
acl-plugin: 5-tuple parse: get rid of memcpy and move to flags vs. bitfields
Using bitfield struct for 5tuple proved to be fragile from the performance standpoint - the zeroizing of the entire structure and then setting the separate pieces of it triggers increased memory latency. So, move to using flags byte. Also, use the direct object copies rather than memcpy. Change-Id: Iad8faf9de050ff1256e40c950dee212cbd3e5267 Signed-off-by: Andrew Yourtchenko <ayourtch@gmail.com>
Diffstat (limited to 'src/plugins/acl/public_inlines.h')
-rw-r--r--src/plugins/acl/public_inlines.h125
1 files changed, 55 insertions, 70 deletions
diff --git a/src/plugins/acl/public_inlines.h b/src/plugins/acl/public_inlines.h
index 850babfa872..ba174c9b2a6 100644
--- a/src/plugins/acl/public_inlines.h
+++ b/src/plugins/acl/public_inlines.h
@@ -58,6 +58,13 @@ offset_within_packet (vlib_buffer_t * b0, int offset)
return (offset <= (b0->current_length - 8));
}
+always_inline int
+offset_beyond_packet (vlib_buffer_t * b0, int offset)
+{
+ /* For the purposes of this code, "within" means we have at least 8 bytes after it */
+ return (offset > (b0->current_length - 8));
+}
+
always_inline void
acl_fill_5tuple_l3_data (acl_main_t * am, vlib_buffer_t * b0, int is_ip6,
@@ -65,20 +72,19 @@ acl_fill_5tuple_l3_data (acl_main_t * am, vlib_buffer_t * b0, int is_ip6,
{
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));
+ ip6_header_t *ip6 = vlib_buffer_get_current (b0) + l3_offset;
+ p5tuple_pkt->ip6_addr[0] = ip6->src_address;
+ p5tuple_pkt->ip6_addr[1] = ip6->dst_address;
}
else
{
- clib_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));
+ int ii;
+ for(ii=0; ii<6; ii++) {
+ p5tuple_pkt->l3_zero_pad[ii] = 0;
+ }
+ ip4_header_t *ip4 = vlib_buffer_get_current (b0) + l3_offset;
+ p5tuple_pkt->ip4_addr[0] = ip4->src_address;
+ p5tuple_pkt->ip4_addr[1] = ip4->dst_address;
}
}
@@ -90,23 +96,19 @@ acl_fill_5tuple_l4_and_pkt_data (acl_main_t * am, u32 sw_if_index0, vlib_buffer_
static u8 icmp_protos_v4v6[] = { IP_PROTOCOL_ICMP, IP_PROTOCOL_ICMP6 };
int l4_offset;
- u16 ports[2];
+ u16 ports[2] = { 0 };
u8 proto;
- fa_session_l4_key_t tmp_l4 = { .lsb_of_sw_if_index = sw_if_index0 & 0xffff };
+ u8 tmp_l4_flags = 0;
fa_packet_info_t tmp_pkt = { .is_ip6 = is_ip6, .mask_type_index_lsb = ~0 };
if (is_ip6)
{
- proto =
- *(u8 *) get_ptr_to_offset (b0,
- offsetof (ip6_header_t,
- protocol) + l3_offset);
+ ip6_header_t *ip6 = vlib_buffer_get_current (b0) + l3_offset;
+ proto = ip6->protocol;
+
l4_offset = l3_offset + sizeof (ip6_header_t);
-#ifdef FA_NODE_VERBOSE_DEBUG
- clib_warning ("ACL_FA_NODE_DBG: proto: %d, l4_offset: %d", proto,
- l4_offset);
-#endif
+
/* IP6 EH handling is here, increment l4_offset if needs to, update the proto */
int need_skip_eh = clib_bitmap_get (am->fa_ipv6_known_eh_bitmap, proto);
if (PREDICT_FALSE (need_skip_eh))
@@ -117,8 +119,7 @@ acl_fill_5tuple_l4_and_pkt_data (acl_main_t * am, u32 sw_if_index0, vlib_buffer_
if (PREDICT_FALSE(ACL_EH_FRAGMENT == proto))
{
proto = *(u8 *) get_ptr_to_offset (b0, l4_offset);
- u16 frag_offset;
- clib_memcpy (&frag_offset, get_ptr_to_offset (b0, 2 + l4_offset), sizeof(frag_offset));
+ u16 frag_offset = *(u16 *) get_ptr_to_offset (b0, 2 + l4_offset);
frag_offset = clib_net_to_host_u16(frag_offset) >> 3;
if (frag_offset)
{
@@ -138,10 +139,6 @@ acl_fill_5tuple_l4_and_pkt_data (acl_main_t * am, u32 sw_if_index0, vlib_buffer_
proto = *(u8 *) get_ptr_to_offset (b0, l4_offset);
l4_offset += 8 * (1 + (u16) nwords);
}
-#ifdef FA_NODE_VERBOSE_DEBUG
- clib_warning ("ACL_FA_NODE_DBG: new proto: %d, new offset: %d",
- proto, l4_offset);
-#endif
need_skip_eh =
clib_bitmap_get (am->fa_ipv6_known_eh_bitmap, proto);
}
@@ -149,21 +146,12 @@ acl_fill_5tuple_l4_and_pkt_data (acl_main_t * am, u32 sw_if_index0, vlib_buffer_
}
else
{
- proto =
- *(u8 *) get_ptr_to_offset (b0,
- offsetof (ip4_header_t,
- protocol) + l3_offset);
- l4_offset = l3_offset + sizeof (ip4_header_t);
- u16 flags_and_fragment_offset;
- clib_memcpy (&flags_and_fragment_offset,
- get_ptr_to_offset (b0,
- offsetof (ip4_header_t,
- flags_and_fragment_offset)) + l3_offset,
- sizeof(flags_and_fragment_offset));
- flags_and_fragment_offset = clib_net_to_host_u16 (flags_and_fragment_offset);
+ ip4_header_t *ip4 = vlib_buffer_get_current (b0) + l3_offset;
+ proto = ip4->protocol;
+ l4_offset = l3_offset + ip4_header_bytes(ip4);
/* non-initial fragments have non-zero offset */
- if ((PREDICT_FALSE(0xfff & flags_and_fragment_offset)))
+ if (PREDICT_FALSE(ip4_get_fragment_offset(ip4)))
{
tmp_pkt.is_nonfirst_fragment = 1;
/* invalidate L4 offset so we don't try to find L4 info */
@@ -171,50 +159,47 @@ acl_fill_5tuple_l4_and_pkt_data (acl_main_t * am, u32 sw_if_index0, vlib_buffer_
}
}
- tmp_l4.proto = proto;
- tmp_l4.is_input = is_input;
+ tmp_l4_flags |= is_input ? FA_SK_L4_FLAG_IS_INPUT : 0;
if (PREDICT_TRUE (offset_within_packet (b0, l4_offset)))
{
+ tcp_header_t *tcph = vlib_buffer_get_current (b0) + l4_offset;
+ udp_header_t *udph = vlib_buffer_get_current (b0) + l4_offset;
tmp_pkt.l4_valid = 1;
- if (icmp_protos_v4v6[is_ip6] == proto)
+
+ if (PREDICT_FALSE(icmp_protos_v4v6[is_ip6] == proto))
{
- /* type */
- tmp_l4.port[0] =
- *(u8 *) get_ptr_to_offset (b0,
- l4_offset + offsetof (icmp46_header_t,
- type));
- /* code */
- tmp_l4.port[1] =
- *(u8 *) get_ptr_to_offset (b0,
- l4_offset + offsetof (icmp46_header_t,
- code));
- tmp_l4.is_slowpath = 1;
+ icmp46_header_t *icmph = vlib_buffer_get_current (b0) + l4_offset;
+ ports[0] = icmph->type;
+ ports[1] = icmph->code;
+ /* ICMP needs special handling */
+ tmp_l4_flags |= FA_SK_L4_FLAG_IS_SLOWPATH;
}
- else if ((IP_PROTOCOL_TCP == proto) || (IP_PROTOCOL_UDP == proto))
+ else if (IP_PROTOCOL_TCP == proto)
{
- clib_memcpy (&ports,
- get_ptr_to_offset (b0,
- l4_offset + offsetof (tcp_header_t,
- src_port)),
- sizeof (ports));
- tmp_l4.port[0] = clib_net_to_host_u16 (ports[0]);
- tmp_l4.port[1] = clib_net_to_host_u16 (ports[1]);
-
- tmp_pkt.tcp_flags =
- *(u8 *) get_ptr_to_offset (b0,
- l4_offset + offsetof (tcp_header_t,
- flags));
- tmp_pkt.tcp_flags_valid = (proto == IP_PROTOCOL_TCP);
- tmp_l4.is_slowpath = 0;
+ ports[0] = clib_net_to_host_u16(tcph->src_port);
+ ports[1] = clib_net_to_host_u16(tcph->dst_port);
+ tmp_pkt.tcp_flags = tcph->flags;
+ tmp_pkt.tcp_flags_valid = 1;
}
+ else if (IP_PROTOCOL_UDP == proto)
+ {
+ ports[0] = clib_net_to_host_u16(udph->src_port);
+ ports[1] = clib_net_to_host_u16(udph->dst_port);
+ }
else
{
- tmp_l4.is_slowpath = 1;
+ tmp_l4_flags |= FA_SK_L4_FLAG_IS_SLOWPATH;
}
}
p5tuple_pkt->as_u64 = tmp_pkt.as_u64;
+
+ fa_session_l4_key_t tmp_l4 = { .port = { ports[0], ports[1] },
+ .proto = proto,
+ .l4_flags = tmp_l4_flags,
+ .lsb_of_sw_if_index = sw_if_index0 & 0xffff };
+
p5tuple_l4->as_u64 = tmp_l4.as_u64;
}