iavf: Support Ethernet Type Flow Director filters
authorHaiyue Wang <haiyue.wang@intel.com>
Tue, 9 Mar 2021 03:08:14 +0000 (11:08 +0800)
committerTony Nguyen <anthony.l.nguyen@intel.com>
Mon, 22 Mar 2021 18:32:12 +0000 (11:32 -0700)
Support the addition and deletion of Ethernet filters.

Supported fields are: proto
Supported flow-types are: ether

Example usage:
ethtool -N ens787f0v0 flow-type ether proto 0x8863 action 6
ethtool -N ens787f0v0 flow-type ether proto 0x8864 action 7

Signed-off-by: Haiyue Wang <haiyue.wang@intel.com>
Tested-by: Chen Bo <BoX.C.Chen@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
drivers/net/ethernet/intel/iavf/iavf_ethtool.c
drivers/net/ethernet/intel/iavf/iavf_fdir.c
drivers/net/ethernet/intel/iavf/iavf_fdir.h

index 8d856f5..24ee6dd 100644 (file)
@@ -861,6 +861,8 @@ static int iavf_fltr_to_ethtool_flow(enum iavf_fdir_flow_type flow)
                return ESP_V6_FLOW;
        case IAVF_FDIR_FLOW_IPV6_OTHER:
                return IPV6_USER_FLOW;
+       case IAVF_FDIR_FLOW_NON_IP_L2:
+               return ETHER_FLOW;
        default:
                /* 0 is undefined ethtool flow */
                return 0;
@@ -900,6 +902,8 @@ static enum iavf_fdir_flow_type iavf_ethtool_flow_to_fltr(int eth)
                return IAVF_FDIR_FLOW_IPV6_ESP;
        case IPV6_USER_FLOW:
                return IAVF_FDIR_FLOW_IPV6_OTHER;
+       case ETHER_FLOW:
+               return IAVF_FDIR_FLOW_NON_IP_L2;
        default:
                return IAVF_FDIR_FLOW_NONE;
        }
@@ -1025,6 +1029,10 @@ iavf_get_ethtool_fdir_entry(struct iavf_adapter *adapter,
                fsp->m_u.usr_ip6_spec.tclass = rule->ip_mask.tclass;
                fsp->m_u.usr_ip6_spec.l4_proto = rule->ip_mask.proto;
                break;
+       case ETHER_FLOW:
+               fsp->h_u.ether_spec.h_proto = rule->eth_data.etype;
+               fsp->m_u.ether_spec.h_proto = rule->eth_mask.etype;
+               break;
        default:
                ret = -EINVAL;
                break;
@@ -1197,6 +1205,10 @@ iavf_add_fdir_fltr_info(struct iavf_adapter *adapter, struct ethtool_rx_flow_spe
                fltr->ip_mask.tclass = fsp->m_u.usr_ip6_spec.tclass;
                fltr->ip_mask.proto = fsp->m_u.usr_ip6_spec.l4_proto;
                break;
+       case ETHER_FLOW:
+               fltr->eth_data.etype = fsp->h_u.ether_spec.h_proto;
+               fltr->eth_mask.etype = fsp->m_u.ether_spec.h_proto;
+               break;
        default:
                /* not doing un-parsed flow types */
                return -EINVAL;
index f84f2ab..e1e1af1 100644 (file)
@@ -277,9 +277,19 @@ iavf_fill_fdir_eth_hdr(struct iavf_fdir_fltr *fltr,
                       struct virtchnl_proto_hdrs *proto_hdrs)
 {
        struct virtchnl_proto_hdr *hdr = &proto_hdrs->proto_hdr[proto_hdrs->count++];
+       struct ethhdr *ehdr = (struct ethhdr *)hdr->buffer;
 
        VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, ETH);
 
+       if (fltr->eth_mask.etype == htons(U16_MAX)) {
+               if (fltr->eth_data.etype == htons(ETH_P_IP) ||
+                   fltr->eth_data.etype == htons(ETH_P_IPV6))
+                       return -EOPNOTSUPP;
+
+               ehdr->h_proto = fltr->eth_data.etype;
+               VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, ETH, ETHERTYPE);
+       }
+
        return 0;
 }
 
@@ -351,6 +361,8 @@ int iavf_fill_fdir_add_msg(struct iavf_adapter *adapter, struct iavf_fdir_fltr *
                err = iavf_fill_fdir_ip6_hdr(fltr, proto_hdrs) |
                      iavf_fill_fdir_l4_hdr(fltr, proto_hdrs);
                break;
+       case IAVF_FDIR_FLOW_NON_IP_L2:
+               break;
        default:
                err = -EINVAL;
                break;
@@ -392,6 +404,8 @@ static const char *iavf_fdir_flow_proto_name(enum iavf_fdir_flow_type flow_type)
        case IAVF_FDIR_FLOW_IPV4_OTHER:
        case IAVF_FDIR_FLOW_IPV6_OTHER:
                return "Other";
+       case IAVF_FDIR_FLOW_NON_IP_L2:
+               return "Ethernet";
        default:
                return NULL;
        }
@@ -468,6 +482,11 @@ void iavf_print_fdir_fltr(struct iavf_adapter *adapter, struct iavf_fdir_fltr *f
                         fltr->ip_data.proto,
                         ntohl(fltr->ip_data.l4_header));
                break;
+       case IAVF_FDIR_FLOW_NON_IP_L2:
+               dev_info(&adapter->pdev->dev, "Rule ID: %u eth_type: 0x%x\n",
+                        fltr->loc,
+                        ntohs(fltr->eth_data.etype));
+               break;
        default:
                break;
        }
@@ -489,7 +508,9 @@ bool iavf_fdir_is_dup_fltr(struct iavf_adapter *adapter, struct iavf_fdir_fltr *
                if (tmp->flow_type != fltr->flow_type)
                        continue;
 
-               if (!memcmp(&tmp->ip_data, &fltr->ip_data,
+               if (!memcmp(&tmp->eth_data, &fltr->eth_data,
+                           sizeof(fltr->eth_data)) &&
+                   !memcmp(&tmp->ip_data, &fltr->ip_data,
                            sizeof(fltr->ip_data))) {
                        ret = true;
                        break;
index f5b222b..ad75b89 100644 (file)
@@ -30,6 +30,7 @@ enum iavf_fdir_flow_type {
        IAVF_FDIR_FLOW_IPV6_AH,
        IAVF_FDIR_FLOW_IPV6_ESP,
        IAVF_FDIR_FLOW_IPV6_OTHER,
+       IAVF_FDIR_FLOW_NON_IP_L2,
        /* MAX - this must be last and add anything new just above it */
        IAVF_FDIR_FLOW_PTYPE_MAX,
 };
@@ -44,6 +45,10 @@ struct iavf_ipv6_addrs {
        struct in6_addr dst_ip;
 };
 
+struct iavf_fdir_eth {
+       __be16 etype;
+};
+
 struct iavf_fdir_ip {
        union {
                struct iavf_ipv4_addrs v4_addrs;
@@ -66,6 +71,9 @@ struct iavf_fdir_fltr {
 
        enum iavf_fdir_flow_type flow_type;
 
+       struct iavf_fdir_eth eth_data;
+       struct iavf_fdir_eth eth_mask;
+
        struct iavf_fdir_ip ip_data;
        struct iavf_fdir_ip ip_mask;