From b94bdad5c04450aad59feb8a5806a87fe37da088 Mon Sep 17 00:00:00 2001 From: Damjan Marion Date: Mon, 19 Sep 2016 11:32:03 +0200 Subject: Use SSE instructions for matching tagged frames by ethertype This change improves performance in l2 scenarios for about 1-2%. Change-Id: Ie35ed8ad70a3b95dd78c0d158c485a10dabaf0eb Signed-off-by: Damjan Marion --- vnet/vnet/ethernet/ethernet.h | 27 +++++++++++++++++++++++++++ vnet/vnet/ethernet/node.c | 5 +---- vnet/vnet/l2/l2_input.h | 5 +---- 3 files changed, 29 insertions(+), 8 deletions(-) diff --git a/vnet/vnet/ethernet/ethernet.h b/vnet/vnet/ethernet/ethernet.h index b5c4ee91..8a1369c1 100644 --- a/vnet/vnet/ethernet/ethernet.h +++ b/vnet/vnet/ethernet/ethernet.h @@ -60,6 +60,33 @@ ethernet_mac_address_is_multicast_u64 (u64 a) return (a & (1ULL << (5 * 8))) != 0; } +static_always_inline int +ethernet_frame_is_tagged (u16 type) +{ +#if __SSE4_2__ + const __m128i ethertype_mask = _mm_set_epi16 (ETHERNET_TYPE_VLAN, + ETHERNET_TYPE_DOT1AD, + ETHERNET_TYPE_VLAN_9100, + ETHERNET_TYPE_VLAN_9200, + /* duplicate last one to + fill register */ + ETHERNET_TYPE_VLAN_9200, + ETHERNET_TYPE_VLAN_9200, + ETHERNET_TYPE_VLAN_9200, + ETHERNET_TYPE_VLAN_9200); + + __m128i r = _mm_set1_epi16 (type); + r = _mm_cmpeq_epi16 (ethertype_mask, r); + return !_mm_test_all_zeros (r, r); +#else + if ((type == ETHERNET_TYPE_VLAN) || + (type == ETHERNET_TYPE_DOT1AD) || + (type == ETHERNET_TYPE_VLAN_9100) || (type == ETHERNET_TYPE_VLAN_9200)) + return 1; +#endif + return 0; +} + /* Max. sized ethernet/vlan header for parsing. */ typedef struct { diff --git a/vnet/vnet/ethernet/node.c b/vnet/vnet/ethernet/node.c index a8a4fcd0..aaa0434b 100644 --- a/vnet/vnet/ethernet/node.c +++ b/vnet/vnet/ethernet/node.c @@ -130,10 +130,7 @@ parse_header (ethernet_input_variant_t variant, vlan_count = 0; // check for vlan encaps - if ((*type == ETHERNET_TYPE_VLAN) || - (*type == ETHERNET_TYPE_DOT1AD) || - (*type == ETHERNET_TYPE_VLAN_9100) || - (*type == ETHERNET_TYPE_VLAN_9200)) + if (ethernet_frame_is_tagged (*type)) { ethernet_vlan_header_t *h0; u16 tag; diff --git a/vnet/vnet/l2/l2_input.h b/vnet/vnet/l2/l2_input.h index 48597ce7..c1c9eb1d 100644 --- a/vnet/vnet/l2/l2_input.h +++ b/vnet/vnet/l2/l2_input.h @@ -244,10 +244,7 @@ vnet_update_l2_len (vlib_buffer_t * b) */ vnet_buffer (b)->l2.l2_len = sizeof (ethernet_header_t); ethertype = clib_net_to_host_u16 (eth->type); - if ((ethertype == ETHERNET_TYPE_VLAN) || - (ethertype == ETHERNET_TYPE_DOT1AD) || - (ethertype == ETHERNET_TYPE_VLAN_9100) || - (ethertype == ETHERNET_TYPE_VLAN_9200)) + if (ethernet_frame_is_tagged (ethertype)) { ethernet_vlan_header_t *vlan; vnet_buffer (b)->l2.l2_len += sizeof (*vlan); -- cgit 1.2.3-korg