Use neutral vector code for ethernet_frame_is_tagged 36/10636/4
authorDamjan Marion <damarion@cisco.com>
Mon, 19 Feb 2018 11:14:06 +0000 (12:14 +0100)
committerFlorin Coras <florin.coras@gmail.com>
Mon, 19 Feb 2018 20:14:30 +0000 (20:14 +0000)
Also it removes ethernet_frame_is_any_taged implemebntation
which seems to be equally costly compared to two
invocations of ethernet_frame_is_tagged.

Change-Id: If1c95f8267cd34b807ec07e0d675cbd0db2fdf9f
Signed-off-by: Damjan Marion <damarion@cisco.com>
src/vnet/ethernet/ethernet.h
src/vnet/ethernet/node.c
src/vppinfra/vector_sse2.h

index 80c6ccd..389bc1b 100644 (file)
@@ -67,25 +67,23 @@ ethernet_mac_address_is_zero (u8 * mac)
   return ((*((u32 *) mac) == 0) && (*((u16 *) (mac + 4)) == 0));
 }
 
+static const u16x8 tagged_ethertypes = {
+  (u16) ETHERNET_TYPE_VLAN,
+  (u16) ETHERNET_TYPE_DOT1AD,
+  (u16) ETHERNET_TYPE_VLAN_9100,
+  (u16) ETHERNET_TYPE_VLAN_9200,
+  /* duplicate last one to fill register */
+  (u16) ETHERNET_TYPE_VLAN_9200,
+  (u16) ETHERNET_TYPE_VLAN_9200,
+  (u16) ETHERNET_TYPE_VLAN_9200,
+  (u16) ETHERNET_TYPE_VLAN_9200
+};
+
 static_always_inline int
 ethernet_frame_is_tagged (u16 type)
 {
-#if __SSE4_2__
-  const __m128i ethertype_mask = _mm_set_epi16 ((u16) ETHERNET_TYPE_VLAN,
-                                               (u16) ETHERNET_TYPE_DOT1AD,
-                                               (u16) ETHERNET_TYPE_VLAN_9100,
-                                               (u16) ETHERNET_TYPE_VLAN_9200,
-                                               /* duplicate last one to
-                                                  fill register */
-                                               (u16) ETHERNET_TYPE_VLAN_9200,
-                                               (u16) ETHERNET_TYPE_VLAN_9200,
-                                               (u16) ETHERNET_TYPE_VLAN_9200,
-                                               (u16)
-                                               ETHERNET_TYPE_VLAN_9200);
-
-  __m128i r = _mm_set1_epi16 (type);
-  r = _mm_cmpeq_epi16 (ethertype_mask, r);
-  return !_mm_test_all_zeros (r, r);
+#ifdef CLIB_HAVE_VEC128
+  return !u16x8_is_all_zero (tagged_ethertypes == u16x8_splat (type));
 #else
   if ((type == ETHERNET_TYPE_VLAN) ||
       (type == ETHERNET_TYPE_DOT1AD) ||
@@ -95,6 +93,33 @@ ethernet_frame_is_tagged (u16 type)
   return 0;
 }
 
+static_always_inline int
+ethernet_frame_is_any_tagged_x2 (u16 type0, u16 type1)
+{
+#ifdef CLIB_HAVE_VEC128
+  u16x8 r0 = (tagged_ethertypes == u16x8_splat (type0));
+  u16x8 r1 = (tagged_ethertypes == u16x8_splat (type1));
+  return !u16x8_is_all_zero (r0 | r1);
+#else
+  return ethernet_frame_is_tagged (type0) || ethernet_frame_is_tagged (type1);
+#endif
+}
+
+static_always_inline int
+ethernet_frame_is_any_tagged_x4 (u16 type0, u16 type1, u16 type2, u16 type3)
+{
+#ifdef CLIB_HAVE_VEC128
+  u16x8 r0 = (tagged_ethertypes == u16x8_splat (type0));
+  u16x8 r1 = (tagged_ethertypes == u16x8_splat (type1));
+  u16x8 r2 = (tagged_ethertypes == u16x8_splat (type2));
+  u16x8 r3 = (tagged_ethertypes == u16x8_splat (type3));
+  return !u16x8_is_all_zero (r0 | r1 | r2 | r3);
+#else
+  return ethernet_frame_is_tagged (type0) || ethernet_frame_is_tagged (type1)
+    || ethernet_frame_is_tagged (type2) || ethernet_frame_is_tagged (type3);
+#endif
+}
+
 /* Max. sized ethernet/vlan header for parsing. */
 typedef struct
 {
index 3b85483..d13af57 100755 (executable)
@@ -285,30 +285,6 @@ determine_next_node (ethernet_main_t * em,
     }
 }
 
-static_always_inline int
-ethernet_frame_is_any_tagged (u16 type0, u16 type1)
-{
-#if __SSE4_2__
-  const __m128i ethertype_mask = _mm_set_epi16 ((u16) ETHERNET_TYPE_VLAN,
-                                               (u16) ETHERNET_TYPE_DOT1AD,
-                                               (u16) ETHERNET_TYPE_VLAN_9100,
-                                               (u16) ETHERNET_TYPE_VLAN_9200,
-                                               /* duplicate for type1 */
-                                               (u16) ETHERNET_TYPE_VLAN,
-                                               (u16) ETHERNET_TYPE_DOT1AD,
-                                               (u16) ETHERNET_TYPE_VLAN_9100,
-                                               (u16)
-                                               ETHERNET_TYPE_VLAN_9200);
-
-  __m128i r =
-    _mm_set_epi16 (type0, type0, type0, type0, type1, type1, type1, type1);
-  r = _mm_cmpeq_epi16 (ethertype_mask, r);
-  return !_mm_test_all_zeros (r, r);
-#else
-  return ethernet_frame_is_tagged (type0) || ethernet_frame_is_tagged (type1);
-#endif
-}
-
 static_always_inline uword
 ethernet_input_inline (vlib_main_t * vm,
                       vlib_node_runtime_t * node,
@@ -401,7 +377,8 @@ ethernet_input_inline (vlib_main_t * vm,
 
          /* Speed-path for the untagged case */
          if (PREDICT_TRUE (variant == ETHERNET_INPUT_VARIANT_ETHERNET
-                           && !ethernet_frame_is_any_tagged (type0, type1)))
+                           && !ethernet_frame_is_any_tagged_x2 (type0,
+                                                                type1)))
            {
              main_intf_t *intf0;
              subint_config_t *subint0;
index 6830d5c..ce1bb81 100644 (file)
@@ -545,6 +545,31 @@ u32x4_is_zero (u32x4 x)
   return u32x4_is_equal (x, zero);
 }
 
+
+always_inline int
+u8x16_is_all_zero (u8x16 x)
+{
+  return _mm_testz_si128 ((__m128i) x, (__m128i) x);
+}
+
+always_inline int
+u16x8_is_all_zero (u16x8 x)
+{
+  return _mm_testz_si128 ((__m128i) x, (__m128i) x);
+}
+
+always_inline int
+u32x4_is_all_zero (u32x4 x)
+{
+  return _mm_testz_si128 ((__m128i) x, (__m128i) x);
+}
+
+always_inline int
+u64x2_is_all_zero (u64x2 x)
+{
+  return _mm_testz_si128 ((__m128i) x, (__m128i) x);
+}
+
 #define u32x4_select(A,MASK)                                           \
 ({                                                                     \
   u32x4 _x, _y;                                                                \