Skip to content

Commit 14193d5

Browse files
committed
Merge branch 'net-sched-fix-ct-zone-matching-for-invalid-conntrack-state'
Paul Blakey says: ==================== net/sched: Fix ct zone matching for invalid conntrack state Currently, when a packet is marked as invalid conntrack_in in act_ct, post_ct will be set, and connection info (nf_conn) will be removed from the skb. Later openvswitch and flower matching will parse this as ct_state=+trk+inv. But because the connection info is missing, there is also no zone info to match against even though the packet is tracked. This series fixes that, by passing the last executed zone by act_ct. The zone info is passed along from act_ct to the ct flow dissector (used by flower to extract zone info) and to ovs, the same way as post_ct is passed, via qdisc layer skb cb to dissector, and via skb extension to OVS. Since adding any more data to qdisc skb cb, there will be no room for BPF skb cb to extend it and stay under skb->cb size, this series moves the tc related info from within qdisc skb cb to a tc specific cb that also extends it. ==================== Link: https://lore.kernel.org/r/20211214172435.24207-1-paulb@nvidia.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2 parents 8ca4090 + 635d448 commit 14193d5

10 files changed

Lines changed: 50 additions & 21 deletions

File tree

include/linux/skbuff.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,7 @@ struct nf_bridge_info {
286286
struct tc_skb_ext {
287287
__u32 chain;
288288
__u16 mru;
289+
__u16 zone;
289290
bool post_ct;
290291
};
291292
#endif
@@ -1380,7 +1381,7 @@ skb_flow_dissect_ct(const struct sk_buff *skb,
13801381
struct flow_dissector *flow_dissector,
13811382
void *target_container,
13821383
u16 *ctinfo_map, size_t mapsize,
1383-
bool post_ct);
1384+
bool post_ct, u16 zone);
13841385
void
13851386
skb_flow_dissect_tunnel_info(const struct sk_buff *skb,
13861387
struct flow_dissector *flow_dissector,

include/net/pkt_sched.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,4 +193,20 @@ static inline void skb_txtime_consumed(struct sk_buff *skb)
193193
skb->tstamp = ktime_set(0, 0);
194194
}
195195

196+
struct tc_skb_cb {
197+
struct qdisc_skb_cb qdisc_cb;
198+
199+
u16 mru;
200+
bool post_ct;
201+
u16 zone; /* Only valid if post_ct = true */
202+
};
203+
204+
static inline struct tc_skb_cb *tc_skb_cb(const struct sk_buff *skb)
205+
{
206+
struct tc_skb_cb *cb = (struct tc_skb_cb *)skb->cb;
207+
208+
BUILD_BUG_ON(sizeof(*cb) > sizeof_field(struct sk_buff, cb));
209+
return cb;
210+
}
211+
196212
#endif

include/net/sch_generic.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -447,8 +447,6 @@ struct qdisc_skb_cb {
447447
};
448448
#define QDISC_CB_PRIV_LEN 20
449449
unsigned char data[QDISC_CB_PRIV_LEN];
450-
u16 mru;
451-
bool post_ct;
452450
};
453451

454452
typedef void tcf_chain_head_change_t(struct tcf_proto *tp_head, void *priv);

net/core/dev.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3941,8 +3941,8 @@ sch_handle_egress(struct sk_buff *skb, int *ret, struct net_device *dev)
39413941
return skb;
39423942

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

39483948
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,
51035103
}
51045104

51055105
qdisc_skb_cb(skb)->pkt_len = skb->len;
5106-
qdisc_skb_cb(skb)->mru = 0;
5107-
qdisc_skb_cb(skb)->post_ct = false;
5106+
tc_skb_cb(skb)->mru = 0;
5107+
tc_skb_cb(skb)->post_ct = false;
51085108
skb->tc_at_ingress = 1;
51095109
mini_qdisc_bstats_cpu_update(miniq, skb);
51105110

net/core/flow_dissector.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ void
238238
skb_flow_dissect_ct(const struct sk_buff *skb,
239239
struct flow_dissector *flow_dissector,
240240
void *target_container, u16 *ctinfo_map,
241-
size_t mapsize, bool post_ct)
241+
size_t mapsize, bool post_ct, u16 zone)
242242
{
243243
#if IS_ENABLED(CONFIG_NF_CONNTRACK)
244244
struct flow_dissector_key_ct *key;
@@ -260,6 +260,7 @@ skb_flow_dissect_ct(const struct sk_buff *skb,
260260
if (!ct) {
261261
key->ct_state = TCA_FLOWER_KEY_CT_FLAGS_TRACKED |
262262
TCA_FLOWER_KEY_CT_FLAGS_INVALID;
263+
key->ct_zone = zone;
263264
return;
264265
}
265266

net/openvswitch/flow.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include <net/mpls.h>
3535
#include <net/ndisc.h>
3636
#include <net/nsh.h>
37+
#include <net/netfilter/nf_conntrack_zones.h>
3738

3839
#include "conntrack.h"
3940
#include "datapath.h"
@@ -860,6 +861,7 @@ int ovs_flow_key_extract(const struct ip_tunnel_info *tun_info,
860861
#endif
861862
bool post_ct = false;
862863
int res, err;
864+
u16 zone = 0;
863865

864866
/* Extract metadata from packet. */
865867
if (tun_info) {
@@ -898,6 +900,7 @@ int ovs_flow_key_extract(const struct ip_tunnel_info *tun_info,
898900
key->recirc_id = tc_ext ? tc_ext->chain : 0;
899901
OVS_CB(skb)->mru = tc_ext ? tc_ext->mru : 0;
900902
post_ct = tc_ext ? tc_ext->post_ct : false;
903+
zone = post_ct ? tc_ext->zone : 0;
901904
} else {
902905
key->recirc_id = 0;
903906
}
@@ -906,8 +909,11 @@ int ovs_flow_key_extract(const struct ip_tunnel_info *tun_info,
906909
#endif
907910

908911
err = key_extract(skb, key);
909-
if (!err)
912+
if (!err) {
910913
ovs_ct_fill_key(skb, key, post_ct); /* Must be after key_extract(). */
914+
if (post_ct && !skb_get_nfct(skb))
915+
key->ct_zone = zone;
916+
}
911917
return err;
912918
}
913919

net/sched/act_ct.c

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -690,10 +690,10 @@ static int tcf_ct_handle_fragments(struct net *net, struct sk_buff *skb,
690690
u8 family, u16 zone, bool *defrag)
691691
{
692692
enum ip_conntrack_info ctinfo;
693-
struct qdisc_skb_cb cb;
694693
struct nf_conn *ct;
695694
int err = 0;
696695
bool frag;
696+
u16 mru;
697697

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

710710
skb_get(skb);
711-
cb = *qdisc_skb_cb(skb);
711+
mru = tc_skb_cb(skb)->mru;
712712

713713
if (family == NFPROTO_IPV4) {
714714
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,
722722

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

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

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

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

1051-
qdisc_skb_cb(skb)->post_ct = true;
1051+
tc_skb_cb(skb)->post_ct = true;
1052+
tc_skb_cb(skb)->zone = p->zone;
10521053
out_clear:
10531054
if (defrag)
10541055
qdisc_skb_cb(skb)->pkt_len = skb->len;

net/sched/cls_api.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1617,12 +1617,15 @@ int tcf_classify(struct sk_buff *skb,
16171617

16181618
/* If we missed on some chain */
16191619
if (ret == TC_ACT_UNSPEC && last_executed_chain) {
1620+
struct tc_skb_cb *cb = tc_skb_cb(skb);
1621+
16201622
ext = tc_skb_ext_alloc(skb);
16211623
if (WARN_ON_ONCE(!ext))
16221624
return TC_ACT_SHOT;
16231625
ext->chain = last_executed_chain;
1624-
ext->mru = qdisc_skb_cb(skb)->mru;
1625-
ext->post_ct = qdisc_skb_cb(skb)->post_ct;
1626+
ext->mru = cb->mru;
1627+
ext->post_ct = cb->post_ct;
1628+
ext->zone = cb->zone;
16261629
}
16271630

16281631
return ret;

net/sched/cls_flower.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
#include <net/sch_generic.h>
2121
#include <net/pkt_cls.h>
22+
#include <net/pkt_sched.h>
2223
#include <net/ip.h>
2324
#include <net/flow_dissector.h>
2425
#include <net/geneve.h>
@@ -309,7 +310,8 @@ static int fl_classify(struct sk_buff *skb, const struct tcf_proto *tp,
309310
struct tcf_result *res)
310311
{
311312
struct cls_fl_head *head = rcu_dereference_bh(tp->root);
312-
bool post_ct = qdisc_skb_cb(skb)->post_ct;
313+
bool post_ct = tc_skb_cb(skb)->post_ct;
314+
u16 zone = tc_skb_cb(skb)->zone;
313315
struct fl_flow_key skb_key;
314316
struct fl_flow_mask *mask;
315317
struct cls_fl_filter *f;
@@ -327,7 +329,7 @@ static int fl_classify(struct sk_buff *skb, const struct tcf_proto *tp,
327329
skb_flow_dissect_ct(skb, &mask->dissector, &skb_key,
328330
fl_ct_info_to_flower_map,
329331
ARRAY_SIZE(fl_ct_info_to_flower_map),
330-
post_ct);
332+
post_ct, zone);
331333
skb_flow_dissect_hash(skb, &mask->dissector, &skb_key);
332334
skb_flow_dissect(skb, &mask->dissector, &skb_key,
333335
FLOW_DISSECTOR_F_STOP_BEFORE_ENCAP);

net/sched/sch_frag.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
22
#include <net/netlink.h>
33
#include <net/sch_generic.h>
4+
#include <net/pkt_sched.h>
45
#include <net/dst.h>
56
#include <net/ip.h>
67
#include <net/ip6_fib.h>
@@ -137,7 +138,7 @@ static int sch_fragment(struct net *net, struct sk_buff *skb,
137138

138139
int sch_frag_xmit_hook(struct sk_buff *skb, int (*xmit)(struct sk_buff *skb))
139140
{
140-
u16 mru = qdisc_skb_cb(skb)->mru;
141+
u16 mru = tc_skb_cb(skb)->mru;
141142
int err;
142143

143144
if (mru && skb->len > mru + skb->dev->hard_header_len)

0 commit comments

Comments
 (0)