mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-04 18:09:57 +00:00
net: use skb_flow_dissect() in __skb_get_rxhash()
No functional changes. This uses the code we factorized in skb_flow_dissect() Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
0744dd00c1
commit
4504b8613b
1 changed files with 14 additions and 111 deletions
125
net/core/dev.c
125
net/core/dev.c
|
@ -133,11 +133,9 @@
|
||||||
#include <linux/pci.h>
|
#include <linux/pci.h>
|
||||||
#include <linux/inetdevice.h>
|
#include <linux/inetdevice.h>
|
||||||
#include <linux/cpu_rmap.h>
|
#include <linux/cpu_rmap.h>
|
||||||
#include <linux/if_tunnel.h>
|
|
||||||
#include <linux/if_pppox.h>
|
|
||||||
#include <linux/ppp_defs.h>
|
|
||||||
#include <linux/net_tstamp.h>
|
#include <linux/net_tstamp.h>
|
||||||
#include <linux/jump_label.h>
|
#include <linux/jump_label.h>
|
||||||
|
#include <net/flow_keys.h>
|
||||||
|
|
||||||
#include "net-sysfs.h"
|
#include "net-sysfs.h"
|
||||||
|
|
||||||
|
@ -2598,123 +2596,28 @@ static inline void ____napi_schedule(struct softnet_data *sd,
|
||||||
*/
|
*/
|
||||||
void __skb_get_rxhash(struct sk_buff *skb)
|
void __skb_get_rxhash(struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
int nhoff, hash = 0, poff;
|
struct flow_keys keys;
|
||||||
const struct ipv6hdr *ip6;
|
u32 hash;
|
||||||
const struct iphdr *ip;
|
|
||||||
const struct vlan_hdr *vlan;
|
|
||||||
u8 ip_proto;
|
|
||||||
u32 addr1, addr2;
|
|
||||||
u16 proto;
|
|
||||||
union {
|
|
||||||
u32 v32;
|
|
||||||
u16 v16[2];
|
|
||||||
} ports;
|
|
||||||
|
|
||||||
nhoff = skb_network_offset(skb);
|
if (!skb_flow_dissect(skb, &keys))
|
||||||
proto = skb->protocol;
|
return;
|
||||||
|
|
||||||
again:
|
if (keys.ports) {
|
||||||
switch (proto) {
|
if ((__force u16)keys.port16[1] < (__force u16)keys.port16[0])
|
||||||
case __constant_htons(ETH_P_IP):
|
swap(keys.port16[0], keys.port16[1]);
|
||||||
ip:
|
skb->l4_rxhash = 1;
|
||||||
if (!pskb_may_pull(skb, sizeof(*ip) + nhoff))
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
ip = (const struct iphdr *) (skb->data + nhoff);
|
|
||||||
if (ip_is_fragment(ip))
|
|
||||||
ip_proto = 0;
|
|
||||||
else
|
|
||||||
ip_proto = ip->protocol;
|
|
||||||
addr1 = (__force u32) ip->saddr;
|
|
||||||
addr2 = (__force u32) ip->daddr;
|
|
||||||
nhoff += ip->ihl * 4;
|
|
||||||
break;
|
|
||||||
case __constant_htons(ETH_P_IPV6):
|
|
||||||
ipv6:
|
|
||||||
if (!pskb_may_pull(skb, sizeof(*ip6) + nhoff))
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
ip6 = (const struct ipv6hdr *) (skb->data + nhoff);
|
|
||||||
ip_proto = ip6->nexthdr;
|
|
||||||
addr1 = (__force u32) ip6->saddr.s6_addr32[3];
|
|
||||||
addr2 = (__force u32) ip6->daddr.s6_addr32[3];
|
|
||||||
nhoff += 40;
|
|
||||||
break;
|
|
||||||
case __constant_htons(ETH_P_8021Q):
|
|
||||||
if (!pskb_may_pull(skb, sizeof(*vlan) + nhoff))
|
|
||||||
goto done;
|
|
||||||
vlan = (const struct vlan_hdr *) (skb->data + nhoff);
|
|
||||||
proto = vlan->h_vlan_encapsulated_proto;
|
|
||||||
nhoff += sizeof(*vlan);
|
|
||||||
goto again;
|
|
||||||
case __constant_htons(ETH_P_PPP_SES):
|
|
||||||
if (!pskb_may_pull(skb, PPPOE_SES_HLEN + nhoff))
|
|
||||||
goto done;
|
|
||||||
proto = *((__be16 *) (skb->data + nhoff +
|
|
||||||
sizeof(struct pppoe_hdr)));
|
|
||||||
nhoff += PPPOE_SES_HLEN;
|
|
||||||
switch (proto) {
|
|
||||||
case __constant_htons(PPP_IP):
|
|
||||||
goto ip;
|
|
||||||
case __constant_htons(PPP_IPV6):
|
|
||||||
goto ipv6;
|
|
||||||
default:
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (ip_proto) {
|
|
||||||
case IPPROTO_GRE:
|
|
||||||
if (pskb_may_pull(skb, nhoff + 16)) {
|
|
||||||
u8 *h = skb->data + nhoff;
|
|
||||||
__be16 flags = *(__be16 *)h;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Only look inside GRE if version zero and no
|
|
||||||
* routing
|
|
||||||
*/
|
|
||||||
if (!(flags & (GRE_VERSION|GRE_ROUTING))) {
|
|
||||||
proto = *(__be16 *)(h + 2);
|
|
||||||
nhoff += 4;
|
|
||||||
if (flags & GRE_CSUM)
|
|
||||||
nhoff += 4;
|
|
||||||
if (flags & GRE_KEY)
|
|
||||||
nhoff += 4;
|
|
||||||
if (flags & GRE_SEQ)
|
|
||||||
nhoff += 4;
|
|
||||||
goto again;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case IPPROTO_IPIP:
|
|
||||||
goto again;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
ports.v32 = 0;
|
|
||||||
poff = proto_ports_offset(ip_proto);
|
|
||||||
if (poff >= 0) {
|
|
||||||
nhoff += poff;
|
|
||||||
if (pskb_may_pull(skb, nhoff + 4)) {
|
|
||||||
ports.v32 = * (__force u32 *) (skb->data + nhoff);
|
|
||||||
if (ports.v16[1] < ports.v16[0])
|
|
||||||
swap(ports.v16[0], ports.v16[1]);
|
|
||||||
skb->l4_rxhash = 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get a consistent hash (same value on both flow directions) */
|
/* get a consistent hash (same value on both flow directions) */
|
||||||
if (addr2 < addr1)
|
if ((__force u32)keys.dst < (__force u32)keys.src)
|
||||||
swap(addr1, addr2);
|
swap(keys.dst, keys.src);
|
||||||
|
|
||||||
hash = jhash_3words(addr1, addr2, ports.v32, hashrnd);
|
hash = jhash_3words((__force u32)keys.dst,
|
||||||
|
(__force u32)keys.src,
|
||||||
|
(__force u32)keys.ports, hashrnd);
|
||||||
if (!hash)
|
if (!hash)
|
||||||
hash = 1;
|
hash = 1;
|
||||||
|
|
||||||
done:
|
|
||||||
skb->rxhash = hash;
|
skb->rxhash = hash;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(__skb_get_rxhash);
|
EXPORT_SYMBOL(__skb_get_rxhash);
|
||||||
|
|
Loading…
Reference in a new issue