mirror of https://gitee.com/openkylin/linux.git
sfc: use flow dissector helpers for aRFS
Signed-off-by: Edward Cree <ecree@solarflare.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
421eeea10d
commit
68bb399e65
|
@ -842,33 +842,15 @@ int efx_filter_rfs(struct net_device *net_dev, const struct sk_buff *skb,
|
|||
struct efx_nic *efx = netdev_priv(net_dev);
|
||||
struct efx_channel *channel;
|
||||
struct efx_filter_spec spec;
|
||||
const __be16 *ports;
|
||||
__be16 ether_type;
|
||||
int nhoff;
|
||||
struct flow_keys fk;
|
||||
int rc;
|
||||
|
||||
/* The core RPS/RFS code has already parsed and validated
|
||||
* VLAN, IP and transport headers. We assume they are in the
|
||||
* header area.
|
||||
*/
|
||||
if (!skb_flow_dissect_flow_keys(skb, &fk, 0))
|
||||
return -EPROTONOSUPPORT;
|
||||
|
||||
if (skb->protocol == htons(ETH_P_8021Q)) {
|
||||
const struct vlan_hdr *vh =
|
||||
(const struct vlan_hdr *)skb->data;
|
||||
|
||||
/* We can't filter on the IP 5-tuple and the vlan
|
||||
* together, so just strip the vlan header and filter
|
||||
* on the IP part.
|
||||
*/
|
||||
EFX_BUG_ON_PARANOID(skb_headlen(skb) < sizeof(*vh));
|
||||
ether_type = vh->h_vlan_encapsulated_proto;
|
||||
nhoff = sizeof(struct vlan_hdr);
|
||||
} else {
|
||||
ether_type = skb->protocol;
|
||||
nhoff = 0;
|
||||
}
|
||||
|
||||
if (ether_type != htons(ETH_P_IP) && ether_type != htons(ETH_P_IPV6))
|
||||
if (fk.basic.n_proto != htons(ETH_P_IP) && fk.basic.n_proto != htons(ETH_P_IPV6))
|
||||
return -EPROTONOSUPPORT;
|
||||
if (fk.control.flags & FLOW_DIS_IS_FRAGMENT)
|
||||
return -EPROTONOSUPPORT;
|
||||
|
||||
efx_filter_init_rx(&spec, EFX_FILTER_PRI_HINT,
|
||||
|
@ -878,34 +860,19 @@ int efx_filter_rfs(struct net_device *net_dev, const struct sk_buff *skb,
|
|||
EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
|
||||
EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT |
|
||||
EFX_FILTER_MATCH_REM_HOST | EFX_FILTER_MATCH_REM_PORT;
|
||||
spec.ether_type = ether_type;
|
||||
spec.ether_type = fk.basic.n_proto;
|
||||
spec.ip_proto = fk.basic.ip_proto;
|
||||
|
||||
if (ether_type == htons(ETH_P_IP)) {
|
||||
const struct iphdr *ip =
|
||||
(const struct iphdr *)(skb->data + nhoff);
|
||||
|
||||
EFX_BUG_ON_PARANOID(skb_headlen(skb) < nhoff + sizeof(*ip));
|
||||
if (ip_is_fragment(ip))
|
||||
return -EPROTONOSUPPORT;
|
||||
spec.ip_proto = ip->protocol;
|
||||
spec.rem_host[0] = ip->saddr;
|
||||
spec.loc_host[0] = ip->daddr;
|
||||
EFX_BUG_ON_PARANOID(skb_headlen(skb) < nhoff + 4 * ip->ihl + 4);
|
||||
ports = (const __be16 *)(skb->data + nhoff + 4 * ip->ihl);
|
||||
if (fk.basic.n_proto == htons(ETH_P_IP)) {
|
||||
spec.rem_host[0] = fk.addrs.v4addrs.src;
|
||||
spec.loc_host[0] = fk.addrs.v4addrs.dst;
|
||||
} else {
|
||||
const struct ipv6hdr *ip6 =
|
||||
(const struct ipv6hdr *)(skb->data + nhoff);
|
||||
|
||||
EFX_BUG_ON_PARANOID(skb_headlen(skb) <
|
||||
nhoff + sizeof(*ip6) + 4);
|
||||
spec.ip_proto = ip6->nexthdr;
|
||||
memcpy(spec.rem_host, &ip6->saddr, sizeof(ip6->saddr));
|
||||
memcpy(spec.loc_host, &ip6->daddr, sizeof(ip6->daddr));
|
||||
ports = (const __be16 *)(ip6 + 1);
|
||||
memcpy(spec.rem_host, &fk.addrs.v6addrs.src, sizeof(struct in6_addr));
|
||||
memcpy(spec.loc_host, &fk.addrs.v6addrs.dst, sizeof(struct in6_addr));
|
||||
}
|
||||
|
||||
spec.rem_port = ports[0];
|
||||
spec.loc_port = ports[1];
|
||||
spec.rem_port = fk.ports.src;
|
||||
spec.loc_port = fk.ports.dst;
|
||||
|
||||
rc = efx->type->filter_rfs_insert(efx, &spec);
|
||||
if (rc < 0)
|
||||
|
@ -916,18 +883,18 @@ int efx_filter_rfs(struct net_device *net_dev, const struct sk_buff *skb,
|
|||
channel = efx_get_channel(efx, skb_get_rx_queue(skb));
|
||||
++channel->rfs_filters_added;
|
||||
|
||||
if (ether_type == htons(ETH_P_IP))
|
||||
if (spec.ether_type == htons(ETH_P_IP))
|
||||
netif_info(efx, rx_status, efx->net_dev,
|
||||
"steering %s %pI4:%u:%pI4:%u to queue %u [flow %u filter %d]\n",
|
||||
(spec.ip_proto == IPPROTO_TCP) ? "TCP" : "UDP",
|
||||
spec.rem_host, ntohs(ports[0]), spec.loc_host,
|
||||
ntohs(ports[1]), rxq_index, flow_id, rc);
|
||||
spec.rem_host, ntohs(spec.rem_port), spec.loc_host,
|
||||
ntohs(spec.loc_port), rxq_index, flow_id, rc);
|
||||
else
|
||||
netif_info(efx, rx_status, efx->net_dev,
|
||||
"steering %s [%pI6]:%u:[%pI6]:%u to queue %u [flow %u filter %d]\n",
|
||||
(spec.ip_proto == IPPROTO_TCP) ? "TCP" : "UDP",
|
||||
spec.rem_host, ntohs(ports[0]), spec.loc_host,
|
||||
ntohs(ports[1]), rxq_index, flow_id, rc);
|
||||
spec.rem_host, ntohs(spec.rem_port), spec.loc_host,
|
||||
ntohs(spec.loc_port), rxq_index, flow_id, rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue