diff options
author | Damjan Marion <damarion@cisco.com> | 2016-09-19 11:32:03 +0200 |
---|---|---|
committer | John Lo <loj@cisco.com> | 2016-09-20 17:37:02 +0000 |
commit | b94bdad5c04450aad59feb8a5806a87fe37da088 (patch) | |
tree | 3b4bd38253e5b00d76c8a66ae83dc710f3a10003 | |
parent | 48a9a54e7c8e295c0cba3491a05c8aa0a5a1f81a (diff) |
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 <damarion@cisco.com>
-rw-r--r-- | vnet/vnet/ethernet/ethernet.h | 27 | ||||
-rw-r--r-- | vnet/vnet/ethernet/node.c | 5 | ||||
-rw-r--r-- | 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 b5c4ee919e5..8a1369c1093 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 a8a4fcd074d..aaa0434bc89 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 48597ce7b28..c1c9eb1daa2 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); |