mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	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: Paul Blakey <paulb@nvidia.com> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
		
							parent
							
								
									8ca4090fec
								
							
						
					
					
						commit
						ec624fe740
					
				
					 7 changed files with 34 additions and 17 deletions
				
			
		| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,6 +19,7 @@
 | 
			
		|||
 | 
			
		||||
#include <net/sch_generic.h>
 | 
			
		||||
#include <net/pkt_cls.h>
 | 
			
		||||
#include <net/pkt_sched.h>
 | 
			
		||||
#include <net/ip.h>
 | 
			
		||||
#include <net/flow_dissector.h>
 | 
			
		||||
#include <net/geneve.h>
 | 
			
		||||
| 
						 | 
				
			
			@ -309,7 +310,7 @@ static int fl_classify(struct sk_buff *skb, const struct tcf_proto *tp,
 | 
			
		|||
		       struct tcf_result *res)
 | 
			
		||||
{
 | 
			
		||||
	struct cls_fl_head *head = rcu_dereference_bh(tp->root);
 | 
			
		||||
	bool post_ct = qdisc_skb_cb(skb)->post_ct;
 | 
			
		||||
	bool post_ct = tc_skb_cb(skb)->post_ct;
 | 
			
		||||
	struct fl_flow_key skb_key;
 | 
			
		||||
	struct fl_flow_mask *mask;
 | 
			
		||||
	struct cls_fl_filter *f;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,7 @@
 | 
			
		|||
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
 | 
			
		||||
#include <net/netlink.h>
 | 
			
		||||
#include <net/sch_generic.h>
 | 
			
		||||
#include <net/pkt_sched.h>
 | 
			
		||||
#include <net/dst.h>
 | 
			
		||||
#include <net/ip.h>
 | 
			
		||||
#include <net/ip6_fib.h>
 | 
			
		||||
| 
						 | 
				
			
			@ -137,7 +138,7 @@ static int sch_fragment(struct net *net, struct sk_buff *skb,
 | 
			
		|||
 | 
			
		||||
int sch_frag_xmit_hook(struct sk_buff *skb, int (*xmit)(struct sk_buff *skb))
 | 
			
		||||
{
 | 
			
		||||
	u16 mru = qdisc_skb_cb(skb)->mru;
 | 
			
		||||
	u16 mru = tc_skb_cb(skb)->mru;
 | 
			
		||||
	int err;
 | 
			
		||||
 | 
			
		||||
	if (mru && skb->len > mru + skb->dev->hard_header_len)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue