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

Commit 3b3ae880 authored by Daniel Borkmann's avatar Daniel Borkmann Committed by David S. Miller
Browse files

net: sched: consolidate tc_classify{,_compat}



For classifiers getting invoked via tc_classify(), we always need an
extra function call into tc_classify_compat(), as both are being
exported as symbols and tc_classify() itself doesn't do much except
handling of reclassifications when tp->classify() returned with
TC_ACT_RECLASSIFY.

CBQ and ATM are the only qdiscs that directly call into tc_classify_compat(),
all others use tc_classify(). When tc actions are being configured
out in the kernel, tc_classify() effectively does nothing besides
delegating.

We could spare this layer and consolidate both functions. pktgen on
single CPU constantly pushing skbs directly into the netif_receive_skb()
path with a dummy classifier on ingress qdisc attached, improves
slightly from 22.3Mpps to 23.1Mpps.

Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
Acked-by: default avatarAlexei Starovoitov <ast@plumgrid.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent fe218823
Loading
Loading
Loading
Loading
+1 −3
Original line number Diff line number Diff line
@@ -110,10 +110,8 @@ static inline void qdisc_run(struct Qdisc *q)
		__qdisc_run(q);
}

int tc_classify_compat(struct sk_buff *skb, const struct tcf_proto *tp,
		       struct tcf_result *res);
int tc_classify(struct sk_buff *skb, const struct tcf_proto *tp,
		struct tcf_result *res);
		struct tcf_result *res, bool compat_mode);

static inline __be16 tc_skb_protocol(const struct sk_buff *skb)
{
+1 −1
Original line number Diff line number Diff line
@@ -3657,7 +3657,7 @@ static inline struct sk_buff *handle_ing(struct sk_buff *skb,
	skb->tc_verd = SET_TC_AT(skb->tc_verd, AT_INGRESS);
	qdisc_bstats_cpu_update(cl->q, skb);

	switch (tc_classify(skb, cl, &cl_res)) {
	switch (tc_classify(skb, cl, &cl_res, false)) {
	case TC_ACT_OK:
	case TC_ACT_RECLASSIFY:
		skb->tc_index = TC_H_MIN(cl_res.classid);
+25 −30
Original line number Diff line number Diff line
@@ -1806,51 +1806,46 @@ static int tc_dump_tclass(struct sk_buff *skb, struct netlink_callback *cb)
 * to this qdisc, (optionally) tests for protocol and asks
 * specific classifiers.
 */
int tc_classify_compat(struct sk_buff *skb, const struct tcf_proto *tp,
		       struct tcf_result *res)
int tc_classify(struct sk_buff *skb, const struct tcf_proto *tp,
		struct tcf_result *res, bool compat_mode)
{
	__be16 protocol = tc_skb_protocol(skb);
	int err;
#ifdef CONFIG_NET_CLS_ACT
	const struct tcf_proto *old_tp = tp;
	int limit = 0;

reclassify:
#endif
	for (; tp; tp = rcu_dereference_bh(tp->next)) {
		int err;

		if (tp->protocol != protocol &&
		    tp->protocol != htons(ETH_P_ALL))
			continue;
		err = tp->classify(skb, tp, res);

		err = tp->classify(skb, tp, res);
#ifdef CONFIG_NET_CLS_ACT
		if (unlikely(err == TC_ACT_RECLASSIFY &&
			     !compat_mode))
			goto reset;
#endif
		if (err >= 0)
			return err;
	}
	return -1;
}
EXPORT_SYMBOL(tc_classify_compat);

int tc_classify(struct sk_buff *skb, const struct tcf_proto *tp,
		struct tcf_result *res)
{
	int err = 0;
#ifdef CONFIG_NET_CLS_ACT
	const struct tcf_proto *otp = tp;
	int limit = 0;
reclassify:
#endif

	err = tc_classify_compat(skb, tp, res);
	return -1;
#ifdef CONFIG_NET_CLS_ACT
	if (err == TC_ACT_RECLASSIFY) {
		tp = otp;

reset:
	if (unlikely(limit++ >= MAX_REC_LOOP)) {
			net_notice_ratelimited("%s: packet reclassify loop rule prio %u protocol %02x\n",
					       tp->q->ops->id,
					       tp->prio & 0xffff,
					       ntohs(tp->protocol));
		net_notice_ratelimited("%s: reclassify loop, rule prio %u, "
				       "protocol %02x\n", tp->q->ops->id,
				       tp->prio & 0xffff, ntohs(tp->protocol));
		return TC_ACT_SHOT;
	}

	tp = old_tp;
	goto reclassify;
	}
#endif
	return err;
}
EXPORT_SYMBOL(tc_classify);

+1 −1
Original line number Diff line number Diff line
@@ -375,7 +375,7 @@ static int atm_tc_enqueue(struct sk_buff *skb, struct Qdisc *sch)
		list_for_each_entry(flow, &p->flows, list) {
			fl = rcu_dereference_bh(flow->filter_list);
			if (fl) {
				result = tc_classify_compat(skb, fl, &res);
				result = tc_classify(skb, fl, &res, true);
				if (result < 0)
					continue;
				flow = (struct atm_flow_data *)res.class;
+1 −1
Original line number Diff line number Diff line
@@ -240,7 +240,7 @@ cbq_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr)
		/*
		 * Step 2+n. Apply classifier.
		 */
		result = tc_classify_compat(skb, fl, &res);
		result = tc_classify(skb, fl, &res, true);
		if (!fl || result < 0)
			goto fallback;

Loading