66 lines
2.1 KiB
Diff
66 lines
2.1 KiB
Diff
|
From 04c825484d6ecdcc8ce09b350235c9077eaca6e3 Mon Sep 17 00:00:00 2001
|
||
|
From: John Crispin <john@phrozen.org>
|
||
|
Date: Wed, 9 Aug 2017 08:20:21 +0200
|
||
|
Subject: [PATCH 41/57] net-next: dsa: fix flow dissection
|
||
|
|
||
|
RPS and probably other kernel features are currently broken on some if not
|
||
|
all DSA devices. The root cause of this is that skb_hash will call the
|
||
|
flow_dissector. At this point the skb still contains the magic switch
|
||
|
header and the skb->protocol field is not set up to the correct 802.3
|
||
|
value yet. By the time the tag specific code is called, removing the header
|
||
|
and =roperly setting the protocol an invalid hash is already set. In the
|
||
|
case of the mt7530 this will result in all flows always having the same
|
||
|
hash.
|
||
|
|
||
|
This patch makes the flow dissector honour the nh and protocol offset
|
||
|
defined by the dsa tag driver thus fixing dissection, hashing and RPS.
|
||
|
|
||
|
Signed-off-by: John Crispin <john@phrozen.org>
|
||
|
---
|
||
|
net/core/flow_dissector.c | 14 +++++++++++++-
|
||
|
1 file changed, 13 insertions(+), 1 deletion(-)
|
||
|
|
||
|
--- a/net/core/flow_dissector.c
|
||
|
+++ b/net/core/flow_dissector.c
|
||
|
@@ -4,6 +4,7 @@
|
||
|
#include <linux/ip.h>
|
||
|
#include <linux/ipv6.h>
|
||
|
#include <linux/if_vlan.h>
|
||
|
+#include <net/dsa.h>
|
||
|
#include <net/ip.h>
|
||
|
#include <net/ipv6.h>
|
||
|
#include <net/gre.h>
|
||
|
@@ -123,13 +124,23 @@ bool __skb_flow_dissect(const struct sk_
|
||
|
bool skip_vlan = false;
|
||
|
u8 ip_proto = 0;
|
||
|
bool ret;
|
||
|
-
|
||
|
if (!data) {
|
||
|
data = skb->data;
|
||
|
proto = skb_vlan_tag_present(skb) ?
|
||
|
skb->vlan_proto : skb->protocol;
|
||
|
nhoff = skb_network_offset(skb);
|
||
|
hlen = skb_headlen(skb);
|
||
|
+ if (unlikely(netdev_uses_dsa(skb->dev))) {
|
||
|
+ const struct dsa_device_ops *ops;
|
||
|
+ int offset;
|
||
|
+
|
||
|
+ ops = skb->dev->dsa_ptr->tag_ops;
|
||
|
+ if (ops->flow_dissect &&
|
||
|
+ !ops->flow_dissect(skb, &proto, &offset)) {
|
||
|
+ hlen -= offset;
|
||
|
+ nhoff += offset;
|
||
|
+ }
|
||
|
+ }
|
||
|
}
|
||
|
|
||
|
/* It is ensured by skb_flow_dissector_init() that control key will
|
||
|
@@ -162,6 +173,7 @@ again:
|
||
|
case htons(ETH_P_IP): {
|
||
|
const struct iphdr *iph;
|
||
|
struct iphdr _iph;
|
||
|
+
|
||
|
ip:
|
||
|
iph = __skb_header_pointer(skb, nhoff, sizeof(_iph), data, hlen, &_iph);
|
||
|
if (!iph || iph->ihl < 5)
|