aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorToke Høiland-Jørgensen <toke@toke.dk>2018-08-22 06:29:43 -0400
committerDavid S. Miller <davem@davemloft.net>2018-08-23 00:39:45 -0400
commit93cfb6c17690c465509967aeb237717d10513a88 (patch)
treef28c723e458955719803be8b5e398465c40b29ce
parent3d0371b313b84ba7c16ebf2526a7a34f1c57b19e (diff)
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>
-rw-r--r--net/sched/sch_cake.c23
1 files changed, 19 insertions, 4 deletions
diff --git a/net/sched/sch_cake.c b/net/sched/sch_cake.c
index 4d26b0823cdf..c07c30b916d5 100644
--- a/net/sched/sch_cake.c
+++ b/net/sched/sch_cake.c
@@ -620,15 +620,20 @@ static bool cake_ddst(int flow_mode)
620} 620}
621 621
622static u32 cake_hash(struct cake_tin_data *q, const struct sk_buff *skb, 622static 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)
624{ 624{
625 u32 flow_hash = 0, srchost_hash, dsthost_hash; 625 u32 flow_hash = 0, srchost_hash = 0, dsthost_hash = 0;
626 u16 reduced_hash, srchost_idx, dsthost_idx; 626 u16 reduced_hash, srchost_idx, dsthost_idx;
627 struct flow_keys keys, host_keys; 627 struct flow_keys keys, host_keys;
628 628
629 if (unlikely(flow_mode == CAKE_FLOW_NONE)) 629 if (unlikely(flow_mode == CAKE_FLOW_NONE))
630 return 0; 630 return 0;
631 631
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
632 skb_flow_dissect_flow_keys(skb, &keys, 637 skb_flow_dissect_flow_keys(skb, &keys,
633 FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL); 638 FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL);
634 639
@@ -675,6 +680,14 @@ static u32 cake_hash(struct cake_tin_data *q, const struct sk_buff *skb,
675 if (flow_mode & CAKE_FLOW_FLOWS) 680 if (flow_mode & CAKE_FLOW_FLOWS)
676 flow_hash = flow_hash_from_keys(&keys); 681 flow_hash = flow_hash_from_keys(&keys);
677 682
683skip_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
678 if (!(flow_mode & CAKE_FLOW_FLOWS)) { 691 if (!(flow_mode & CAKE_FLOW_FLOWS)) {
679 if (flow_mode & CAKE_FLOW_SRC_IP) 692 if (flow_mode & CAKE_FLOW_SRC_IP)
680 flow_hash ^= srchost_hash; 693 flow_hash ^= srchost_hash;
@@ -1570,7 +1583,7 @@ static u32 cake_classify(struct Qdisc *sch, struct cake_tin_data **t,
1570 struct cake_sched_data *q = qdisc_priv(sch); 1583 struct cake_sched_data *q = qdisc_priv(sch);
1571 struct tcf_proto *filter; 1584 struct tcf_proto *filter;
1572 struct tcf_result res; 1585 struct tcf_result res;
1573 u32 flow = 0; 1586 u16 flow = 0, host = 0;
1574 int result; 1587 int result;
1575 1588
1576 filter = rcu_dereference_bh(q->filter_list); 1589 filter = rcu_dereference_bh(q->filter_list);
@@ -1594,10 +1607,12 @@ static u32 cake_classify(struct Qdisc *sch, struct cake_tin_data **t,
1594#endif 1607#endif
1595 if (TC_H_MIN(res.classid) <= CAKE_QUEUES) 1608 if (TC_H_MIN(res.classid) <= CAKE_QUEUES)
1596 flow = TC_H_MIN(res.classid); 1609 flow = TC_H_MIN(res.classid);
1610 if (TC_H_MAJ(res.classid) <= (CAKE_QUEUES << 16))
1611 host = TC_H_MAJ(res.classid) >> 16;
1597 } 1612 }
1598hash: 1613hash:
1599 *t = cake_select_tin(sch, skb); 1614 *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;
1601} 1616}
1602 1617
1603static void cake_reconfigure(struct Qdisc *sch); 1618static void cake_reconfigure(struct Qdisc *sch);