diff options
author | Michal Soltys <soltys@ziu.info> | 2016-06-30 02:26:44 +0200 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-07-01 11:03:43 +0200 |
commit | 12d0ad3be9c3854e52ec74bb83bb6f43612827c7 (patch) | |
tree | abdffc0beb64f19e9535603f30ed21a67a8f46d4 /net/sched/sch_hfsc.c | |
parent | tcp: md5: use kmalloc() backed scratch areas (diff) | |
download | linux-12d0ad3be9c3854e52ec74bb83bb6f43612827c7.tar.xz linux-12d0ad3be9c3854e52ec74bb83bb6f43612827c7.zip |
net/sched/sch_hfsc.c: handle corner cases where head may change invalidating calculated deadline
Realtime scheduling implemented in HFSC uses head of the queue to make
the decision about which packet to schedule next. But in case of any
head drop, the deadline calculated for the previous head is not
necessarily correct for the next head (unless both packets have the same
length).
Thanks to peek() function used during dequeue - which internally is a
dequeue operation - hfsc is almost safe from this issue, as peek()
dequeues and isolates the head storing it temporarily until the real
dequeue happens.
But there is one exception: if after the class activation a drop happens
before the first dequeue operation, there's never a chance to do the
peek().
Adding peek() call in enqueue - if this is the first packet in a new
backlog period AND the scheduler has realtime curve defined - fixes that
one corner case. The 1st hfsc_dequeue() will use that peeked packet,
similarly as every subsequent hfsc_dequeue() call uses packet peeked by
the previous call.
Signed-off-by: Michal Soltys <soltys@ziu.info>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sched/sch_hfsc.c')
-rw-r--r-- | net/sched/sch_hfsc.c | 11 |
1 files changed, 10 insertions, 1 deletions
diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c index 8cb5eff7b79c..6d6df6b2d38f 100644 --- a/net/sched/sch_hfsc.c +++ b/net/sched/sch_hfsc.c @@ -1594,8 +1594,17 @@ hfsc_enqueue(struct sk_buff *skb, struct Qdisc *sch, struct sk_buff **to_free) return err; } - if (cl->qdisc->q.qlen == 1) + if (cl->qdisc->q.qlen == 1) { set_active(cl, qdisc_pkt_len(skb)); + /* + * If this is the first packet, isolate the head so an eventual + * head drop before the first dequeue operation has no chance + * to invalidate the deadline. + */ + if (cl->cl_flags & HFSC_RSC) + cl->qdisc->ops->peek(cl->qdisc); + + } qdisc_qstats_backlog_inc(sch, skb); sch->q.qlen++; |