mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-30 02:29:01 +00:00
d59dc14515
From upstream: b8392808eb3f sch_cake: add RFC 8622 LE PHB support to CAKE diffserv handling 3f608f0c4136 sch_cake: fix a few style nits 8c95eca0bb8c sch_cake: don't call diffserv parsing code when it is not needed 9208d2863ac6 sch_cake: don't try to reallocate or unshare skb unconditionally From netdev not yet accepted: sch_cake: fix IP protocol handling in the presence of VLAN tags The VLAN tag handling is actually wider than just cake so upstream are working out how to fix it generically. We fix it here just for cake. Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
115 lines
3.6 KiB
Diff
115 lines
3.6 KiB
Diff
From a00590d570212c3c633bd463cef8ec7377cc7993 Mon Sep 17 00:00:00 2001
|
|
From: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
|
|
Date: Tue, 30 Jun 2020 12:07:44 +0100
|
|
Subject: [PATCH] sch_cake: fix IP protocol handling in the presence of VLAN
|
|
tags
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
From: Ilya Ponetayev <i.ponetaev@ndmsystems.com>
|
|
|
|
CAKE was using the return value of tc_skb_protocol() and expecting it to be
|
|
the IP protocol type. This can fail in the presence of QinQ VLAN tags,
|
|
making CAKE unable to handle ECN marking and diffserv parsing in this case.
|
|
Fix this by implementing our own version of tc_skb_protocol(), which will
|
|
use skb->protocol directly, but also parse and skip over any VLAN tags and
|
|
return the inner protocol number instead.
|
|
|
|
Also fix CE marking by implementing a version of INET_ECN_set_ce() that
|
|
uses the same parsing routine.
|
|
|
|
Fixes: ea82511518f4 ("sch_cake: Add NAT awareness to packet classifier")
|
|
Fixes: b2100cc56fca ("sch_cake: Use tc_skb_protocol() helper for getting packet protocol")
|
|
Fixes: 046f6fd5daef ("sched: Add Common Applications Kept Enhanced (cake) qdisc")
|
|
Signed-off-by: Ilya Ponetayev <i.ponetaev@ndmsystems.com>
|
|
[ squash original two patches, rewrite commit message ]
|
|
Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
|
|
Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
|
|
---
|
|
net/sched/sch_cake.c | 52 +++++++++++++++++++++++++++++++++++++++++---
|
|
1 file changed, 49 insertions(+), 3 deletions(-)
|
|
|
|
--- a/net/sched/sch_cake.c
|
|
+++ b/net/sched/sch_cake.c
|
|
@@ -497,6 +497,52 @@ static bool cobalt_queue_empty(struct co
|
|
return down;
|
|
}
|
|
|
|
+static __be16 cake_skb_proto(const struct sk_buff *skb)
|
|
+{
|
|
+ unsigned int offset = skb_mac_offset(skb) + sizeof(struct ethhdr);
|
|
+ __be16 proto = skb->protocol;
|
|
+ struct vlan_hdr vhdr, *vh;
|
|
+
|
|
+ while (proto == htons(ETH_P_8021Q) || proto == htons(ETH_P_8021AD)) {
|
|
+ vh = skb_header_pointer(skb, offset, sizeof(vhdr), &vhdr);
|
|
+ if (!vh)
|
|
+ break;
|
|
+
|
|
+ proto = vh->h_vlan_encapsulated_proto;
|
|
+ offset += sizeof(vhdr);
|
|
+ }
|
|
+
|
|
+ return proto;
|
|
+}
|
|
+
|
|
+static int cake_set_ce(struct sk_buff *skb)
|
|
+{
|
|
+ int wlen = skb_network_offset(skb);
|
|
+
|
|
+ switch (cake_skb_proto(skb)) {
|
|
+ case htons(ETH_P_IP):
|
|
+ wlen += sizeof(struct iphdr);
|
|
+ if (!pskb_may_pull(skb, wlen) ||
|
|
+ skb_try_make_writable(skb, wlen))
|
|
+ return 0;
|
|
+
|
|
+ return IP_ECN_set_ce(ip_hdr(skb));
|
|
+
|
|
+ case htons(ETH_P_IPV6):
|
|
+ wlen += sizeof(struct ipv6hdr);
|
|
+ if (!pskb_may_pull(skb, wlen) ||
|
|
+ skb_try_make_writable(skb, wlen))
|
|
+ return 0;
|
|
+
|
|
+ return IP6_ECN_set_ce(skb, ipv6_hdr(skb));
|
|
+
|
|
+ default:
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
/* Call this with a freshly dequeued packet for possible congestion marking.
|
|
* Returns true as an instruction to drop the packet, false for delivery.
|
|
*/
|
|
@@ -549,7 +595,7 @@ static bool cobalt_should_drop(struct co
|
|
|
|
if (next_due && vars->dropping) {
|
|
/* Use ECN mark if possible, otherwise drop */
|
|
- drop = !(vars->ecn_marked = INET_ECN_set_ce(skb));
|
|
+ drop = !(vars->ecn_marked = cake_set_ce(skb));
|
|
|
|
vars->count++;
|
|
if (!vars->count)
|
|
@@ -592,7 +638,7 @@ static bool cake_update_flowkeys(struct
|
|
bool rev = !skb->_nfct, upd = false;
|
|
__be32 ip;
|
|
|
|
- if (tc_skb_protocol(skb) != htons(ETH_P_IP))
|
|
+ if (cake_skb_proto(skb) != htons(ETH_P_IP))
|
|
return false;
|
|
|
|
if (!nf_ct_get_tuple_skb(&tuple, skb))
|
|
@@ -1557,7 +1603,7 @@ static u8 cake_handle_diffserv(struct sk
|
|
u16 *buf, buf_;
|
|
u8 dscp;
|
|
|
|
- switch (tc_skb_protocol(skb)) {
|
|
+ switch (cake_skb_proto(skb)) {
|
|
case htons(ETH_P_IP):
|
|
buf = skb_header_pointer(skb, offset, sizeof(buf_), &buf_);
|
|
if (unlikely(!buf))
|