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

Commit c0affa19 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'sch-accurate-backlog'



Cong Wang says:

====================
net_sched: update backlog for hierarchical qdisc's

For hierarchical qdisc like HTB, we currently only update its qlen
but leave its backlog as zero:

    qdisc htb 1: dev eth0 root refcnt 2 r2q 10 default 1 direct_packets_stat 0 ver 3.17
     Sent 172680457356 bytes 222469449 pkt (dropped 0, overlimits 123575834 requeues 0)
     backlog 0b 72p requeues 0

This patchset makes backlog as accurate as qlen.

v3: rebase and fix the n==0 case for qdisc_tree_reduce_backlog()
v2: rebase and update changelog, not code change
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents f12d33f4 bdf17661
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -162,12 +162,14 @@ struct codel_vars {
 * struct codel_stats - contains codel shared variables and stats
 * @maxpacket:	largest packet we've seen so far
 * @drop_count:	temp count of dropped packets in dequeue()
 * @drop_len:	bytes of dropped packets in dequeue()
 * ecn_mark:	number of packets we ECN marked instead of dropping
 * ce_mark:	number of packets CE marked because sojourn time was above ce_threshold
 */
struct codel_stats {
	u32		maxpacket;
	u32		drop_count;
	u32		drop_len;
	u32		ecn_mark;
	u32		ce_mark;
};
@@ -308,6 +310,7 @@ static struct sk_buff *codel_dequeue(struct Qdisc *sch,
								  vars->rec_inv_sqrt);
					goto end;
				}
				stats->drop_len += qdisc_pkt_len(skb);
				qdisc_drop(skb, sch);
				stats->drop_count++;
				skb = dequeue_func(vars, sch);
@@ -330,6 +333,7 @@ static struct sk_buff *codel_dequeue(struct Qdisc *sch,
		if (params->ecn && INET_ECN_set_ce(skb)) {
			stats->ecn_mark++;
		} else {
			stats->drop_len += qdisc_pkt_len(skb);
			qdisc_drop(skb, sch);
			stats->drop_count++;

+19 −1
Original line number Diff line number Diff line
@@ -396,7 +396,8 @@ struct Qdisc *dev_graft_qdisc(struct netdev_queue *dev_queue,
			      struct Qdisc *qdisc);
void qdisc_reset(struct Qdisc *qdisc);
void qdisc_destroy(struct Qdisc *qdisc);
void qdisc_tree_decrease_qlen(struct Qdisc *qdisc, unsigned int n);
void qdisc_tree_reduce_backlog(struct Qdisc *qdisc, unsigned int n,
			       unsigned int len);
struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue,
			  const struct Qdisc_ops *ops);
struct Qdisc *qdisc_create_dflt(struct netdev_queue *dev_queue,
@@ -707,6 +708,23 @@ static inline void qdisc_reset_queue(struct Qdisc *sch)
	sch->qstats.backlog = 0;
}

static inline struct Qdisc *qdisc_replace(struct Qdisc *sch, struct Qdisc *new,
					  struct Qdisc **pold)
{
	struct Qdisc *old;

	sch_tree_lock(sch);
	old = *pold;
	*pold = new;
	if (old != NULL) {
		qdisc_tree_reduce_backlog(old, old->q.qlen, old->qstats.backlog);
		qdisc_reset(old);
	}
	sch_tree_unlock(sch);

	return old;
}

static inline unsigned int __qdisc_queue_drop(struct Qdisc *sch,
					      struct sk_buff_head *list)
{
+5 −3
Original line number Diff line number Diff line
@@ -744,14 +744,15 @@ static u32 qdisc_alloc_handle(struct net_device *dev)
	return 0;
}

void qdisc_tree_decrease_qlen(struct Qdisc *sch, unsigned int n)
void qdisc_tree_reduce_backlog(struct Qdisc *sch, unsigned int n,
			       unsigned int len)
{
	const struct Qdisc_class_ops *cops;
	unsigned long cl;
	u32 parentid;
	int drops;

	if (n == 0)
	if (n == 0 && len == 0)
		return;
	drops = max_t(int, n, 0);
	rcu_read_lock();
@@ -774,11 +775,12 @@ void qdisc_tree_decrease_qlen(struct Qdisc *sch, unsigned int n)
			cops->put(sch, cl);
		}
		sch->q.qlen -= n;
		sch->qstats.backlog -= len;
		__qdisc_qstats_drop(sch, drops);
	}
	rcu_read_unlock();
}
EXPORT_SYMBOL(qdisc_tree_decrease_qlen);
EXPORT_SYMBOL(qdisc_tree_reduce_backlog);

static void notify_and_destroy(struct net *net, struct sk_buff *skb,
			       struct nlmsghdr *n, u32 clid,
+4 −8
Original line number Diff line number Diff line
@@ -1624,13 +1624,8 @@ static int cbq_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
			new->reshape_fail = cbq_reshape_fail;
#endif
	}
	sch_tree_lock(sch);
	*old = cl->q;
	cl->q = new;
	qdisc_tree_decrease_qlen(*old, (*old)->q.qlen);
	qdisc_reset(*old);
	sch_tree_unlock(sch);

	*old = qdisc_replace(sch, new, &cl->q);
	return 0;
}

@@ -1914,7 +1909,7 @@ static int cbq_delete(struct Qdisc *sch, unsigned long arg)
{
	struct cbq_sched_data *q = qdisc_priv(sch);
	struct cbq_class *cl = (struct cbq_class *)arg;
	unsigned int qlen;
	unsigned int qlen, backlog;

	if (cl->filters || cl->children || cl == &q->link)
		return -EBUSY;
@@ -1922,8 +1917,9 @@ static int cbq_delete(struct Qdisc *sch, unsigned long arg)
	sch_tree_lock(sch);

	qlen = cl->q->q.qlen;
	backlog = cl->q->qstats.backlog;
	qdisc_reset(cl->q);
	qdisc_tree_decrease_qlen(cl->q, qlen);
	qdisc_tree_reduce_backlog(cl->q, qlen, backlog);

	if (cl->next_alive)
		cbq_deactivate_class(cl);
+4 −2
Original line number Diff line number Diff line
@@ -128,8 +128,8 @@ static void choke_drop_by_idx(struct Qdisc *sch, unsigned int idx)
		choke_zap_tail_holes(q);

	qdisc_qstats_backlog_dec(sch, skb);
	qdisc_tree_reduce_backlog(sch, 1, qdisc_pkt_len(skb));
	qdisc_drop(skb, sch);
	qdisc_tree_decrease_qlen(sch, 1);
	--sch->q.qlen;
}

@@ -456,6 +456,7 @@ static int choke_change(struct Qdisc *sch, struct nlattr *opt)
		old = q->tab;
		if (old) {
			unsigned int oqlen = sch->q.qlen, tail = 0;
			unsigned dropped = 0;

			while (q->head != q->tail) {
				struct sk_buff *skb = q->tab[q->head];
@@ -467,11 +468,12 @@ static int choke_change(struct Qdisc *sch, struct nlattr *opt)
					ntab[tail++] = skb;
					continue;
				}
				dropped += qdisc_pkt_len(skb);
				qdisc_qstats_backlog_dec(sch, skb);
				--sch->q.qlen;
				qdisc_drop(skb, sch);
			}
			qdisc_tree_decrease_qlen(sch, oqlen - sch->q.qlen);
			qdisc_tree_reduce_backlog(sch, oqlen - sch->q.qlen, dropped);
			q->head = 0;
			q->tail = tail;
		}
Loading