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;
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;
}
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;
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;
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;
}
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;
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;
}
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;
}
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;
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,
};
struct in6_addr dst_ip;
};
+struct iavf_fdir_eth {
+ __be16 etype;
+};
+
struct iavf_fdir_ip {
union {
struct iavf_ipv4_addrs v4_addrs;
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;