Merge branch 'sched-A-couple-of-fixes-for-sch_cake'
Toke Høiland-Jørgensen says: ==================== sched: A couple of fixes for sch_cake This series contains a couple of fixes for diffserv handling in sch_cake that provide a nice speedup (with a somewhat pedantic nit fix tacked on to the end). Not quite sure about whether this should go to stable; it does provide a nice speedup, but it's not strictly a fix in the "correctness" sense. I lean towards including this in stable as well, since our most important consumer of that (OpenWrt) is likely to backport the series anyway. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Коммит
6aeaf26222
|
@ -1551,32 +1551,51 @@ static unsigned int cake_drop(struct Qdisc *sch, struct sk_buff **to_free)
|
|||
return idx + (tin << 16);
|
||||
}
|
||||
|
||||
static u8 cake_handle_diffserv(struct sk_buff *skb, u16 wash)
|
||||
static u8 cake_handle_diffserv(struct sk_buff *skb, bool wash)
|
||||
{
|
||||
int wlen = skb_network_offset(skb);
|
||||
const int offset = skb_network_offset(skb);
|
||||
u16 *buf, buf_;
|
||||
u8 dscp;
|
||||
|
||||
switch (tc_skb_protocol(skb)) {
|
||||
case htons(ETH_P_IP):
|
||||
wlen += sizeof(struct iphdr);
|
||||
if (!pskb_may_pull(skb, wlen) ||
|
||||
skb_try_make_writable(skb, wlen))
|
||||
buf = skb_header_pointer(skb, offset, sizeof(buf_), &buf_);
|
||||
if (unlikely(!buf))
|
||||
return 0;
|
||||
|
||||
dscp = ipv4_get_dsfield(ip_hdr(skb)) >> 2;
|
||||
if (wash && dscp)
|
||||
/* ToS is in the second byte of iphdr */
|
||||
dscp = ipv4_get_dsfield((struct iphdr *)buf) >> 2;
|
||||
|
||||
if (wash && dscp) {
|
||||
const int wlen = offset + sizeof(struct iphdr);
|
||||
|
||||
if (!pskb_may_pull(skb, wlen) ||
|
||||
skb_try_make_writable(skb, wlen))
|
||||
return 0;
|
||||
|
||||
ipv4_change_dsfield(ip_hdr(skb), INET_ECN_MASK, 0);
|
||||
}
|
||||
|
||||
return dscp;
|
||||
|
||||
case htons(ETH_P_IPV6):
|
||||
wlen += sizeof(struct ipv6hdr);
|
||||
if (!pskb_may_pull(skb, wlen) ||
|
||||
skb_try_make_writable(skb, wlen))
|
||||
buf = skb_header_pointer(skb, offset, sizeof(buf_), &buf_);
|
||||
if (unlikely(!buf))
|
||||
return 0;
|
||||
|
||||
dscp = ipv6_get_dsfield(ipv6_hdr(skb)) >> 2;
|
||||
if (wash && dscp)
|
||||
/* Traffic class is in the first and second bytes of ipv6hdr */
|
||||
dscp = ipv6_get_dsfield((struct ipv6hdr *)buf) >> 2;
|
||||
|
||||
if (wash && dscp) {
|
||||
const int wlen = offset + sizeof(struct ipv6hdr);
|
||||
|
||||
if (!pskb_may_pull(skb, wlen) ||
|
||||
skb_try_make_writable(skb, wlen))
|
||||
return 0;
|
||||
|
||||
ipv6_change_dsfield(ipv6_hdr(skb), INET_ECN_MASK, 0);
|
||||
}
|
||||
|
||||
return dscp;
|
||||
|
||||
case htons(ETH_P_ARP):
|
||||
|
@ -1593,14 +1612,17 @@ static struct cake_tin_data *cake_select_tin(struct Qdisc *sch,
|
|||
{
|
||||
struct cake_sched_data *q = qdisc_priv(sch);
|
||||
u32 tin, mark;
|
||||
bool wash;
|
||||
u8 dscp;
|
||||
|
||||
/* Tin selection: Default to diffserv-based selection, allow overriding
|
||||
* using firewall marks or skb->priority.
|
||||
* using firewall marks or skb->priority. Call DSCP parsing early if
|
||||
* wash is enabled, otherwise defer to below to skip unneeded parsing.
|
||||
*/
|
||||
dscp = cake_handle_diffserv(skb,
|
||||
q->rate_flags & CAKE_FLAG_WASH);
|
||||
mark = (skb->mark & q->fwmark_mask) >> q->fwmark_shft;
|
||||
wash = !!(q->rate_flags & CAKE_FLAG_WASH);
|
||||
if (wash)
|
||||
dscp = cake_handle_diffserv(skb, wash);
|
||||
|
||||
if (q->tin_mode == CAKE_DIFFSERV_BESTEFFORT)
|
||||
tin = 0;
|
||||
|
@ -1614,6 +1636,8 @@ static struct cake_tin_data *cake_select_tin(struct Qdisc *sch,
|
|||
tin = q->tin_order[TC_H_MIN(skb->priority) - 1];
|
||||
|
||||
else {
|
||||
if (!wash)
|
||||
dscp = cake_handle_diffserv(skb, wash);
|
||||
tin = q->tin_index[dscp];
|
||||
|
||||
if (unlikely(tin >= q->tin_cnt))
|
||||
|
@ -2691,7 +2715,7 @@ static int cake_init(struct Qdisc *sch, struct nlattr *opt,
|
|||
qdisc_watchdog_init(&q->watchdog, sch);
|
||||
|
||||
if (opt) {
|
||||
int err = cake_change(sch, opt, extack);
|
||||
err = cake_change(sch, opt, extack);
|
||||
|
||||
if (err)
|
||||
return err;
|
||||
|
@ -3008,7 +3032,7 @@ static int cake_dump_class_stats(struct Qdisc *sch, unsigned long cl,
|
|||
PUT_STAT_S32(BLUE_TIMER_US,
|
||||
ktime_to_us(
|
||||
ktime_sub(now,
|
||||
flow->cvars.blue_timer)));
|
||||
flow->cvars.blue_timer)));
|
||||
}
|
||||
if (flow->cvars.dropping) {
|
||||
PUT_STAT_S32(DROP_NEXT_US,
|
||||
|
|
Загрузка…
Ссылка в новой задаче