ice: Add direction metadata
authorMarcin Szycik <marcin.szycik@linux.intel.com>
Thu, 22 Jun 2023 13:35:12 +0000 (15:35 +0200)
committerTony Nguyen <anthony.l.nguyen@intel.com>
Mon, 7 Aug 2023 20:01:29 +0000 (13:01 -0700)
Currently it is possible to create a filter which breaks TX traffic, e.g.:

tc filter add dev $PF1 ingress protocol ip prio 1 flower ip_proto udp
dst_port $PORT action mirred egress redirect dev $VF1_PR

This adds a rule which might match both TX and RX traffic, and in TX path
the PF will actually receive the traffic, which breaks communication.

To fix this, add a match on direction metadata flag when adding a tc rule.

Because of the way metadata is currently handled, a duplicate lookup word
would appear if VLAN metadata is also added. The lookup would still work
correctly, but one word would be wasted. To prevent it, lookup 0 now always
contains all metadata. When any metadata needs to be added, it is added to
lookup 0 and lookup count is not incremented. This way, two flags residing
in the same word will take up one word, instead of two.

Note: the drop action is also affected, i.e. it will now only work in one
direction.

Signed-off-by: Marcin Szycik <marcin.szycik@linux.intel.com>
Reviewed-by: Simon Horman <simon.horman@corigine.com>
Tested-by: Sujai Buvaneswaran <sujai.buvaneswaran@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
drivers/net/ethernet/intel/ice/ice_protocol_type.h
drivers/net/ethernet/intel/ice/ice_switch.c
drivers/net/ethernet/intel/ice/ice_switch.h
drivers/net/ethernet/intel/ice/ice_tc_lib.c

index 6a93647..9812b98 100644 (file)
@@ -287,6 +287,7 @@ struct ice_nvgre_hdr {
  * M = EVLAN (0x8100) - Outer L2 header has EVLAN (ethernet type 0x8100)
  * N = EVLAN (0x9100) - Outer L2 header has EVLAN (ethernet type 0x9100)
  */
+#define ICE_PKT_FROM_NETWORK   BIT(3)
 #define ICE_PKT_VLAN_STAG      BIT(12)
 #define ICE_PKT_VLAN_ITAG      BIT(13)
 #define ICE_PKT_VLAN_EVLAN     (BIT(14) | BIT(15))
index 91bc92f..dcbb69b 100644 (file)
@@ -6058,14 +6058,21 @@ ice_adv_add_update_vsi_list(struct ice_hw *hw,
 void ice_rule_add_tunnel_metadata(struct ice_adv_lkup_elem *lkup)
 {
        lkup->type = ICE_HW_METADATA;
-       lkup->m_u.metadata.flags[ICE_PKT_FLAGS_TUNNEL] =
+       lkup->m_u.metadata.flags[ICE_PKT_FLAGS_TUNNEL] |=
                cpu_to_be16(ICE_PKT_TUNNEL_MASK);
 }
 
+void ice_rule_add_direction_metadata(struct ice_adv_lkup_elem *lkup)
+{
+       lkup->type = ICE_HW_METADATA;
+       lkup->m_u.metadata.flags[ICE_PKT_FLAGS_VLAN] |=
+               cpu_to_be16(ICE_PKT_FROM_NETWORK);
+}
+
 void ice_rule_add_vlan_metadata(struct ice_adv_lkup_elem *lkup)
 {
        lkup->type = ICE_HW_METADATA;
-       lkup->m_u.metadata.flags[ICE_PKT_FLAGS_VLAN] =
+       lkup->m_u.metadata.flags[ICE_PKT_FLAGS_VLAN] |=
                cpu_to_be16(ICE_PKT_VLAN_MASK);
 }
 
index 250823a..0bd4320 100644 (file)
@@ -359,6 +359,7 @@ int ice_share_res(struct ice_hw *hw, u16 type, u8 shared, u16 res_id);
 
 /* Switch/bridge related commands */
 void ice_rule_add_tunnel_metadata(struct ice_adv_lkup_elem *lkup);
+void ice_rule_add_direction_metadata(struct ice_adv_lkup_elem *lkup);
 void ice_rule_add_vlan_metadata(struct ice_adv_lkup_elem *lkup);
 void ice_rule_add_src_vsi_metadata(struct ice_adv_lkup_elem *lkup);
 int
index 38547db..37b54db 100644 (file)
@@ -7,6 +7,8 @@
 #include "ice_lib.h"
 #include "ice_protocol_type.h"
 
+#define ICE_TC_METADATA_LKUP_IDX 0
+
 /**
  * ice_tc_count_lkups - determine lookup count for switch filter
  * @flags: TC-flower flags
@@ -19,7 +21,13 @@ static int
 ice_tc_count_lkups(u32 flags, struct ice_tc_flower_lyr_2_4_hdrs *headers,
                   struct ice_tc_flower_fltr *fltr)
 {
-       int lkups_cnt = 0;
+       int lkups_cnt = 1; /* 0th lookup is metadata */
+
+       /* Always add metadata as the 0th lookup. Included elements:
+        * - Direction flag (always present)
+        * - ICE_TC_FLWR_FIELD_VLAN_TPID (present if specified)
+        * - Tunnel flag (present if tunnel)
+        */
 
        if (flags & ICE_TC_FLWR_FIELD_TENANT_ID)
                lkups_cnt++;
@@ -54,10 +62,6 @@ ice_tc_count_lkups(u32 flags, struct ice_tc_flower_lyr_2_4_hdrs *headers,
        if (flags & (ICE_TC_FLWR_FIELD_VLAN | ICE_TC_FLWR_FIELD_VLAN_PRIO))
                lkups_cnt++;
 
-       /* is VLAN TPID specified */
-       if (flags & ICE_TC_FLWR_FIELD_VLAN_TPID)
-               lkups_cnt++;
-
        /* is CVLAN specified? */
        if (flags & (ICE_TC_FLWR_FIELD_CVLAN | ICE_TC_FLWR_FIELD_CVLAN_PRIO))
                lkups_cnt++;
@@ -84,10 +88,6 @@ ice_tc_count_lkups(u32 flags, struct ice_tc_flower_lyr_2_4_hdrs *headers,
                     ICE_TC_FLWR_FIELD_SRC_L4_PORT))
                lkups_cnt++;
 
-       /* matching for tunneled packets in metadata */
-       if (fltr->tunnel_type != TNL_LAST)
-               lkups_cnt++;
-
        return lkups_cnt;
 }
 
@@ -176,10 +176,9 @@ static u16 ice_check_supported_vlan_tpid(u16 vlan_tpid)
 
 static int
 ice_tc_fill_tunnel_outer(u32 flags, struct ice_tc_flower_fltr *fltr,
-                        struct ice_adv_lkup_elem *list)
+                        struct ice_adv_lkup_elem *list, int i)
 {
        struct ice_tc_flower_lyr_2_4_hdrs *hdr = &fltr->outer_headers;
-       int i = 0;
 
        if (flags & ICE_TC_FLWR_FIELD_TENANT_ID) {
                u32 tenant_id;
@@ -329,8 +328,7 @@ ice_tc_fill_tunnel_outer(u32 flags, struct ice_tc_flower_fltr *fltr,
        }
 
        /* always fill matching on tunneled packets in metadata */
-       ice_rule_add_tunnel_metadata(&list[i]);
-       i++;
+       ice_rule_add_tunnel_metadata(&list[ICE_TC_METADATA_LKUP_IDX]);
 
        return i;
 }
@@ -358,13 +356,16 @@ ice_tc_fill_rules(struct ice_hw *hw, u32 flags,
        struct ice_tc_flower_lyr_2_4_hdrs *headers = &tc_fltr->outer_headers;
        bool inner = false;
        u16 vlan_tpid = 0;
-       int i = 0;
+       int i = 1; /* 0th lookup is metadata */
 
        rule_info->vlan_type = vlan_tpid;
 
+       /* Always add direction metadata */
+       ice_rule_add_direction_metadata(&list[ICE_TC_METADATA_LKUP_IDX]);
+
        rule_info->tun_type = ice_sw_type_from_tunnel(tc_fltr->tunnel_type);
        if (tc_fltr->tunnel_type != TNL_LAST) {
-               i = ice_tc_fill_tunnel_outer(flags, tc_fltr, list);
+               i = ice_tc_fill_tunnel_outer(flags, tc_fltr, list, i);
 
                headers = &tc_fltr->inner_headers;
                inner = true;
@@ -431,8 +432,7 @@ ice_tc_fill_rules(struct ice_hw *hw, u32 flags,
                rule_info->vlan_type =
                                ice_check_supported_vlan_tpid(vlan_tpid);
 
-               ice_rule_add_vlan_metadata(&list[i]);
-               i++;
+               ice_rule_add_vlan_metadata(&list[ICE_TC_METADATA_LKUP_IDX]);
        }
 
        if (flags & (ICE_TC_FLWR_FIELD_CVLAN | ICE_TC_FLWR_FIELD_CVLAN_PRIO)) {