diff --git a/net/sched/sch_fq.c b/net/sched/sch_fq.c index dfc7f98b600f..a282812c192e 100644 --- a/net/sched/sch_fq.c +++ b/net/sched/sch_fq.c @@ -159,6 +159,9 @@ struct fq_sched_data { u64 stat_allocation_errors; }; +/* EDT timestamps to clear beyond now. */ +static const int fq_offload_slack_ns = 400; + /* return the i-th 2-bit value ("crumb") */ static u8 fq_prio2band(const u8 *prio2band, unsigned int prio) { @@ -421,6 +424,10 @@ static struct fq_flow *fq_classify(struct Qdisc *sch, struct sk_buff *skb, smp_store_release(&sk->sk_pacing_status, SK_PACING_FQ); + if (offload_horizon && + fq_skb_cb(skb)->time_to_send <= now + fq_offload_slack_ns) + skb_set_delivery_time(skb, 0, SKB_CLOCK_REALTIME); + return &q->internal; } @@ -731,6 +738,7 @@ static struct sk_buff *fq_dequeue(struct Qdisc *sch) u64 offload_horizon = fq_offload_horizon(sch, q); struct fq_perband_flows *pband; struct fq_flow_head *head; + u64 time_next_packet = 0; struct sk_buff *skb; struct fq_flow *f; unsigned long rate; @@ -745,7 +753,7 @@ static struct sk_buff *fq_dequeue(struct Qdisc *sch) if (skb) { q->internal.qlen--; fq_dequeue_skb(sch, &q->internal, skb); - goto out; + return skb; } now = ktime_get_ns(); @@ -782,8 +790,8 @@ begin: skb = fq_peek(f); if (skb) { - u64 time_next_packet = max_t(u64, fq_skb_cb(skb)->time_to_send, - f->time_next_packet); + time_next_packet = max_t(u64, fq_skb_cb(skb)->time_to_send, + f->time_next_packet); if (now + offload_horizon < time_next_packet) { head->first = f->next; @@ -862,6 +870,10 @@ begin: } out: + if (offload_horizon && + time_next_packet && time_next_packet <= now + fq_offload_slack_ns) + skb_set_delivery_time(skb, 0, SKB_CLOCK_REALTIME); + return skb; }