Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7eec4174 authored by Eric Dumazet's avatar Eric Dumazet Committed by David S. Miller
Browse files

pkt_sched: fq: fix non TCP flows pacing



Steinar reported FQ pacing was not working for UDP flows.

It looks like the initial sk->sk_pacing_rate value of 0 was
a wrong choice. We should init it to ~0U (unlimited)

Then, TCA_FQ_FLOW_DEFAULT_RATE should be removed because it makes
no real sense. The default rate is really unlimited, and we
need to avoid a zero divide.

Reported-by: default avatarSteinar H. Gunderson <sesse@google.com>
Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 2b1f18a4
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -2319,6 +2319,7 @@ void sock_init_data(struct socket *sock, struct sock *sk)
	sk->sk_ll_usec		=	sysctl_net_busy_read;
	sk->sk_ll_usec		=	sysctl_net_busy_read;
#endif
#endif


	sk->sk_pacing_rate = ~0U;
	/*
	/*
	 * Before updating sk_refcnt, we must commit prior changes to memory
	 * Before updating sk_refcnt, we must commit prior changes to memory
	 * (Documentation/RCU/rculist_nulls.txt for details)
	 * (Documentation/RCU/rculist_nulls.txt for details)
+9 −11
Original line number Original line Diff line number Diff line
@@ -472,19 +472,15 @@ static struct sk_buff *fq_dequeue(struct Qdisc *sch)
	if (f->credit > 0 || !q->rate_enable)
	if (f->credit > 0 || !q->rate_enable)
		goto out;
		goto out;


	if (skb->sk && skb->sk->sk_state != TCP_TIME_WAIT) {
		rate = skb->sk->sk_pacing_rate ?: q->flow_default_rate;

		rate = min(rate, q->flow_max_rate);
	} else {
	rate = q->flow_max_rate;
	rate = q->flow_max_rate;
		if (rate == ~0U)
	if (skb->sk && skb->sk->sk_state != TCP_TIME_WAIT)
			goto out;
		rate = min(skb->sk->sk_pacing_rate, rate);
	}

	if (rate) {
	if (rate != ~0U) {
		u32 plen = max(qdisc_pkt_len(skb), q->quantum);
		u32 plen = max(qdisc_pkt_len(skb), q->quantum);
		u64 len = (u64)plen * NSEC_PER_SEC;
		u64 len = (u64)plen * NSEC_PER_SEC;


		if (likely(rate))
			do_div(len, rate);
			do_div(len, rate);
		/* Since socket rate can change later,
		/* Since socket rate can change later,
		 * clamp the delay to 125 ms.
		 * clamp the delay to 125 ms.
@@ -735,12 +731,14 @@ static int fq_dump(struct Qdisc *sch, struct sk_buff *skb)
	if (opts == NULL)
	if (opts == NULL)
		goto nla_put_failure;
		goto nla_put_failure;


	/* TCA_FQ_FLOW_DEFAULT_RATE is not used anymore,
	 * do not bother giving its value
	 */
	if (nla_put_u32(skb, TCA_FQ_PLIMIT, sch->limit) ||
	if (nla_put_u32(skb, TCA_FQ_PLIMIT, sch->limit) ||
	    nla_put_u32(skb, TCA_FQ_FLOW_PLIMIT, q->flow_plimit) ||
	    nla_put_u32(skb, TCA_FQ_FLOW_PLIMIT, q->flow_plimit) ||
	    nla_put_u32(skb, TCA_FQ_QUANTUM, q->quantum) ||
	    nla_put_u32(skb, TCA_FQ_QUANTUM, q->quantum) ||
	    nla_put_u32(skb, TCA_FQ_INITIAL_QUANTUM, q->initial_quantum) ||
	    nla_put_u32(skb, TCA_FQ_INITIAL_QUANTUM, q->initial_quantum) ||
	    nla_put_u32(skb, TCA_FQ_RATE_ENABLE, q->rate_enable) ||
	    nla_put_u32(skb, TCA_FQ_RATE_ENABLE, q->rate_enable) ||
	    nla_put_u32(skb, TCA_FQ_FLOW_DEFAULT_RATE, q->flow_default_rate) ||
	    nla_put_u32(skb, TCA_FQ_FLOW_MAX_RATE, q->flow_max_rate) ||
	    nla_put_u32(skb, TCA_FQ_FLOW_MAX_RATE, q->flow_max_rate) ||
	    nla_put_u32(skb, TCA_FQ_BUCKETS_LOG, q->fq_trees_log))
	    nla_put_u32(skb, TCA_FQ_BUCKETS_LOG, q->fq_trees_log))
		goto nla_put_failure;
		goto nla_put_failure;