Skip to content

Commit 93cfb6c

Browse files
tohojodavem330
authored andcommitted
sch_cake: Fix TC filter flow override and expand it to hosts as well
The TC filter flow mapping override completely skipped the call to cake_hash(); however that meant that the internal state was not being updated, which ultimately leads to deadlocks in some configurations. Fix that by passing the overridden flow ID into cake_hash() instead so it can react appropriately. In addition, the major number of the class ID can now be set to override the host mapping in host isolation mode. If both host and flow are overridden (or if the respective modes are disabled), flow dissection and hashing will be skipped entirely; otherwise, the hashing will be kept for the portions that are not set by the filter. Signed-off-by: Toke Høiland-Jørgensen <toke@toke.dk> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 3d0371b commit 93cfb6c

File tree

1 file changed

+19
-4
lines changed

1 file changed

+19
-4
lines changed

net/sched/sch_cake.c

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -620,15 +620,20 @@ static bool cake_ddst(int flow_mode)
620620
}
621621

622622
static u32 cake_hash(struct cake_tin_data *q, const struct sk_buff *skb,
623-
int flow_mode)
623+
int flow_mode, u16 flow_override, u16 host_override)
624624
{
625-
u32 flow_hash = 0, srchost_hash, dsthost_hash;
625+
u32 flow_hash = 0, srchost_hash = 0, dsthost_hash = 0;
626626
u16 reduced_hash, srchost_idx, dsthost_idx;
627627
struct flow_keys keys, host_keys;
628628

629629
if (unlikely(flow_mode == CAKE_FLOW_NONE))
630630
return 0;
631631

632+
/* If both overrides are set we can skip packet dissection entirely */
633+
if ((flow_override || !(flow_mode & CAKE_FLOW_FLOWS)) &&
634+
(host_override || !(flow_mode & CAKE_FLOW_HOSTS)))
635+
goto skip_hash;
636+
632637
skb_flow_dissect_flow_keys(skb, &keys,
633638
FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL);
634639

@@ -675,6 +680,14 @@ static u32 cake_hash(struct cake_tin_data *q, const struct sk_buff *skb,
675680
if (flow_mode & CAKE_FLOW_FLOWS)
676681
flow_hash = flow_hash_from_keys(&keys);
677682

683+
skip_hash:
684+
if (flow_override)
685+
flow_hash = flow_override - 1;
686+
if (host_override) {
687+
dsthost_hash = host_override - 1;
688+
srchost_hash = host_override - 1;
689+
}
690+
678691
if (!(flow_mode & CAKE_FLOW_FLOWS)) {
679692
if (flow_mode & CAKE_FLOW_SRC_IP)
680693
flow_hash ^= srchost_hash;
@@ -1570,7 +1583,7 @@ static u32 cake_classify(struct Qdisc *sch, struct cake_tin_data **t,
15701583
struct cake_sched_data *q = qdisc_priv(sch);
15711584
struct tcf_proto *filter;
15721585
struct tcf_result res;
1573-
u32 flow = 0;
1586+
u16 flow = 0, host = 0;
15741587
int result;
15751588

15761589
filter = rcu_dereference_bh(q->filter_list);
@@ -1594,10 +1607,12 @@ static u32 cake_classify(struct Qdisc *sch, struct cake_tin_data **t,
15941607
#endif
15951608
if (TC_H_MIN(res.classid) <= CAKE_QUEUES)
15961609
flow = TC_H_MIN(res.classid);
1610+
if (TC_H_MAJ(res.classid) <= (CAKE_QUEUES << 16))
1611+
host = TC_H_MAJ(res.classid) >> 16;
15971612
}
15981613
hash:
15991614
*t = cake_select_tin(sch, skb);
1600-
return flow ?: cake_hash(*t, skb, flow_mode) + 1;
1615+
return cake_hash(*t, skb, flow_mode, flow, host) + 1;
16011616
}
16021617

16031618
static void cake_reconfigure(struct Qdisc *sch);

0 commit comments

Comments
 (0)