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

Commit c926def1 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "net_sched: Add flow control support to prio qdisc"

parents 0e53ef51 c6e14f9e
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -133,6 +133,8 @@ static inline __be16 tc_skb_protocol(const struct sk_buff *skb)
	return skb->protocol;
}

extern int tc_qdisc_flow_control(struct net_device *dev, u32 tcm_handle,
				  int flow_enable);
/* Calculate maximal size of packet seen by hard_start_xmit
   routine of this device.
 */
+3 −0
Original line number Diff line number Diff line
@@ -147,8 +147,11 @@ struct tc_skbprio_qopt {
struct tc_prio_qopt {
	int	bands;			/* Number of bands */
	__u8	priomap[TC_PRIO_MAX+1];	/* Map: logical priority -> PRIO band */
	__u8	enable_flow;		/* Enable dequeue */
};

#define TCQ_PRIO_FLOW_CONTROL 1

/* MULTIQ section */

struct tc_multiq_qopt {
+34 −0
Original line number Diff line number Diff line
@@ -1404,6 +1404,40 @@ static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n,
	return 0;
}

/*
 * enable/disable flow on qdisc.
 */
int
tc_qdisc_flow_control(struct net_device *dev, u32 tcm_handle, int enable_flow)
{
	struct Qdisc *q;
	int qdisc_len = 0;
	struct __qdisc_change_req {
		struct nlattr attr;
		struct tc_prio_qopt data;
	} req =	{
		.attr = {sizeof(struct __qdisc_change_req), TCA_OPTIONS},
		.data = {3, {1, 2, 2, 2, 1, 2, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1}, 1}
		};

	/* override flow bit */
	req.data.enable_flow = enable_flow;

	/* look up using tcm handle */
	q = qdisc_lookup(dev, tcm_handle);

	/* call registered change function */
	if (likely(q && q->ops)) {
		if (likely(q->ops->change)) {
			qdisc_len = q->q.qlen;
			if (q->ops->change(q, &req.attr, NULL))
				pr_err("%s(): qdisc change failed\n", __func__);
		}
	}
	return qdisc_len;
}
EXPORT_SYMBOL(tc_qdisc_flow_control);

/*
 * Create/change qdisc.
 */
+21 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <net/netlink.h>
#include <net/pkt_sched.h>
#include <net/pkt_cls.h>
@@ -28,6 +29,7 @@ struct prio_sched_data {
	struct tcf_block *block;
	u8  prio2band[TC_PRIO_MAX+1];
	struct Qdisc *queues[TCQ_PRIO_BANDS];
	u8 enable_flow;
};


@@ -102,6 +104,9 @@ static struct sk_buff *prio_peek(struct Qdisc *sch)
	struct prio_sched_data *q = qdisc_priv(sch);
	int prio;

	if (!q->enable_flow)
		return NULL;

	for (prio = 0; prio < q->bands; prio++) {
		struct Qdisc *qdisc = q->queues[prio];
		struct sk_buff *skb = qdisc->ops->peek(qdisc);
@@ -116,6 +121,9 @@ static struct sk_buff *prio_dequeue(struct Qdisc *sch)
	struct prio_sched_data *q = qdisc_priv(sch);
	int prio;

	if (!q->enable_flow)
		return NULL;

	for (prio = 0; prio < q->bands; prio++) {
		struct Qdisc *qdisc = q->queues[prio];
		struct sk_buff *skb = qdisc_dequeue_peeked(qdisc);
@@ -140,6 +148,7 @@ prio_reset(struct Qdisc *sch)
		qdisc_reset(q->queues[prio]);
	sch->qstats.backlog = 0;
	sch->q.qlen = 0;
	q->enable_flow = 1;
}

static int prio_offload(struct Qdisc *sch, struct tc_prio_qopt *qopt)
@@ -185,6 +194,7 @@ static int prio_tune(struct Qdisc *sch, struct nlattr *opt,
	struct Qdisc *queues[TCQ_PRIO_BANDS];
	int oldbands = q->bands, i;
	struct tc_prio_qopt *qopt;
	int flow_change = 0;

	if (nla_len(opt) < sizeof(*qopt))
		return -EINVAL;
@@ -212,6 +222,10 @@ static int prio_tune(struct Qdisc *sch, struct nlattr *opt,

	prio_offload(sch, qopt);
	sch_tree_lock(sch);
	if (q->enable_flow != qopt->enable_flow) {
		q->enable_flow = qopt->enable_flow;
		flow_change = 1;
	}
	q->bands = qopt->bands;
	memcpy(q->prio2band, qopt->priomap, TC_PRIO_MAX+1);

@@ -230,6 +244,12 @@ static int prio_tune(struct Qdisc *sch, struct nlattr *opt,
	}

	sch_tree_unlock(sch);

	/* Schedule qdisc when flow re-enabled */
	if (flow_change && q->enable_flow) {
		if (!test_bit(__QDISC_STATE_DEACTIVATED, &sch->state))
			__netif_schedule(qdisc_root(sch));
	}
	return 0;
}

@@ -288,6 +308,7 @@ static int prio_dump(struct Qdisc *sch, struct sk_buff *skb)
	int err;

	opt.bands = q->bands;
	opt.enable_flow = q->enable_flow;
	memcpy(&opt.priomap, q->prio2band, TC_PRIO_MAX + 1);

	err = prio_dump_offload(sch);