Commit ec624fe7 authored by Paul Blakey's avatar Paul Blakey Committed by Jakub Kicinski
Browse files

net/sched: Extend qdisc control block with tc control block



BPF layer extends the qdisc control block via struct bpf_skb_data_end
and because of that there is no more room to add variables to the
qdisc layer control block without going over the skb->cb size.

Extend the qdisc control block with a tc control block,
and move all tc related variables to there as a pre-step for
extending the tc control block with additional members.

Signed-off-by: default avatarPaul Blakey <paulb@nvidia.com>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 8ca4090f
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -193,4 +193,19 @@ static inline void skb_txtime_consumed(struct sk_buff *skb)
	skb->tstamp = ktime_set(0, 0);
}

struct tc_skb_cb {
	struct qdisc_skb_cb qdisc_cb;

	u16 mru;
	bool post_ct;
};

static inline struct tc_skb_cb *tc_skb_cb(const struct sk_buff *skb)
{
	struct tc_skb_cb *cb = (struct tc_skb_cb *)skb->cb;

	BUILD_BUG_ON(sizeof(*cb) > sizeof_field(struct sk_buff, cb));
	return cb;
}

#endif
+0 −2
Original line number Diff line number Diff line
@@ -447,8 +447,6 @@ struct qdisc_skb_cb {
	};
#define QDISC_CB_PRIV_LEN 20
	unsigned char		data[QDISC_CB_PRIV_LEN];
	u16			mru;
	bool			post_ct;
};

typedef void tcf_chain_head_change_t(struct tcf_proto *tp_head, void *priv);
+4 −4
Original line number Diff line number Diff line
@@ -3941,8 +3941,8 @@ sch_handle_egress(struct sk_buff *skb, int *ret, struct net_device *dev)
		return skb;

	/* qdisc_skb_cb(skb)->pkt_len was already set by the caller. */
	qdisc_skb_cb(skb)->mru = 0;
	qdisc_skb_cb(skb)->post_ct = false;
	tc_skb_cb(skb)->mru = 0;
	tc_skb_cb(skb)->post_ct = false;
	mini_qdisc_bstats_cpu_update(miniq, skb);

	switch (tcf_classify(skb, miniq->block, miniq->filter_list, &cl_res, false)) {
@@ -5103,8 +5103,8 @@ sch_handle_ingress(struct sk_buff *skb, struct packet_type **pt_prev, int *ret,
	}

	qdisc_skb_cb(skb)->pkt_len = skb->len;
	qdisc_skb_cb(skb)->mru = 0;
	qdisc_skb_cb(skb)->post_ct = false;
	tc_skb_cb(skb)->mru = 0;
	tc_skb_cb(skb)->post_ct = false;
	skb->tc_at_ingress = 1;
	mini_qdisc_bstats_cpu_update(miniq, skb);

+7 −7
Original line number Diff line number Diff line
@@ -690,10 +690,10 @@ static int tcf_ct_handle_fragments(struct net *net, struct sk_buff *skb,
				   u8 family, u16 zone, bool *defrag)
{
	enum ip_conntrack_info ctinfo;
	struct qdisc_skb_cb cb;
	struct nf_conn *ct;
	int err = 0;
	bool frag;
	u16 mru;

	/* Previously seen (loopback)? Ignore. */
	ct = nf_ct_get(skb, &ctinfo);
@@ -708,7 +708,7 @@ static int tcf_ct_handle_fragments(struct net *net, struct sk_buff *skb,
		return err;

	skb_get(skb);
	cb = *qdisc_skb_cb(skb);
	mru = tc_skb_cb(skb)->mru;

	if (family == NFPROTO_IPV4) {
		enum ip_defrag_users user = IP_DEFRAG_CONNTRACK_IN + zone;
@@ -722,7 +722,7 @@ static int tcf_ct_handle_fragments(struct net *net, struct sk_buff *skb,

		if (!err) {
			*defrag = true;
			cb.mru = IPCB(skb)->frag_max_size;
			mru = IPCB(skb)->frag_max_size;
		}
	} else { /* NFPROTO_IPV6 */
#if IS_ENABLED(CONFIG_NF_DEFRAG_IPV6)
@@ -735,7 +735,7 @@ static int tcf_ct_handle_fragments(struct net *net, struct sk_buff *skb,

		if (!err) {
			*defrag = true;
			cb.mru = IP6CB(skb)->frag_max_size;
			mru = IP6CB(skb)->frag_max_size;
		}
#else
		err = -EOPNOTSUPP;
@@ -744,7 +744,7 @@ static int tcf_ct_handle_fragments(struct net *net, struct sk_buff *skb,
	}

	if (err != -EINPROGRESS)
		*qdisc_skb_cb(skb) = cb;
		tc_skb_cb(skb)->mru = mru;
	skb_clear_hash(skb);
	skb->ignore_df = 1;
	return err;
@@ -963,7 +963,7 @@ static int tcf_ct_act(struct sk_buff *skb, const struct tc_action *a,
	tcf_action_update_bstats(&c->common, skb);

	if (clear) {
		qdisc_skb_cb(skb)->post_ct = false;
		tc_skb_cb(skb)->post_ct = false;
		ct = nf_ct_get(skb, &ctinfo);
		if (ct) {
			nf_conntrack_put(&ct->ct_general);
@@ -1048,7 +1048,7 @@ static int tcf_ct_act(struct sk_buff *skb, const struct tc_action *a,
out_push:
	skb_push_rcsum(skb, nh_ofs);

	qdisc_skb_cb(skb)->post_ct = true;
	tc_skb_cb(skb)->post_ct = true;
out_clear:
	if (defrag)
		qdisc_skb_cb(skb)->pkt_len = skb->len;
+4 −2
Original line number Diff line number Diff line
@@ -1617,12 +1617,14 @@ int tcf_classify(struct sk_buff *skb,

	/* If we missed on some chain */
	if (ret == TC_ACT_UNSPEC && last_executed_chain) {
		struct tc_skb_cb *cb = tc_skb_cb(skb);

		ext = tc_skb_ext_alloc(skb);
		if (WARN_ON_ONCE(!ext))
			return TC_ACT_SHOT;
		ext->chain = last_executed_chain;
		ext->mru = qdisc_skb_cb(skb)->mru;
		ext->post_ct = qdisc_skb_cb(skb)->post_ct;
		ext->mru = cb->mru;
		ext->post_ct = cb->post_ct;
	}

	return ret;
Loading