Florian Westphal <fw@xxxxxxxxx> wrote: > ... doesn't solve the nft_hash.c issue (which calls _symmetric version, and > that uses flow_key definiton that isn't exported outside flow_dissector.o. and here is the diff that would pass net for _symmetric, not too horrible I think. With that and the copypaste of skb_get_hash into nf_trace infra netfilter can still pass skbs to the flow dissector with NULL skb->sk,dev but the WARN would no longer trigger as struct net is non-null. diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 9254bca2813d..e9e6cf3d148c 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -524,12 +524,13 @@ static inline void tun_flow_save_rps_rxhash(struct tun_flow_entry *e, u32 hash) */ static u16 tun_automq_select_queue(struct tun_struct *tun, struct sk_buff *skb) { + const struct net *net = dev_net(tun->dev); struct tun_flow_entry *e; u32 txq, numqueues; numqueues = READ_ONCE(tun->numqueues); - txq = __skb_get_hash_symmetric(skb); + txq = __skb_get_hash_symmetric(net, skb); e = tun_flow_find(&tun->flows[tun_hashfn(txq)], txq); if (e) { tun_flow_save_rps_rxhash(e, txq); @@ -1038,10 +1039,11 @@ static void tun_automq_xmit(struct tun_struct *tun, struct sk_buff *skb) /* Select queue was not called for the skbuff, so we extract the * RPS hash and save it into the flow_table here. */ + const struct net *net = dev_net(tun->dev); struct tun_flow_entry *e; __u32 rxhash; - rxhash = __skb_get_hash_symmetric(skb); + rxhash = __skb_get_hash_symmetric(net, skb); e = tun_flow_find(&tun->flows[tun_hashfn(rxhash)], rxhash); if (e) tun_flow_save_rps_rxhash(e, rxhash); @@ -1938,7 +1940,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, */ if (!rcu_access_pointer(tun->steering_prog) && tun->numqueues > 1 && !tfile->detached) - rxhash = __skb_get_hash_symmetric(skb); + rxhash = __skb_get_hash_symmetric(dev_net(tun->dev), skb); rcu_read_lock(); if (unlikely(!(tun->dev->flags & IFF_UP))) { @@ -2521,7 +2523,7 @@ static int tun_xdp_one(struct tun_struct *tun, if (!rcu_dereference(tun->steering_prog) && tun->numqueues > 1 && !tfile->detached) - rxhash = __skb_get_hash_symmetric(skb); + rxhash = __skb_get_hash_symmetric(dev_net(tun->dev), skb); if (tfile->napi_enabled) { queue = &tfile->sk.sk_write_queue; diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 1c2902eaebd3..60a4dc5586c8 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -1493,7 +1493,7 @@ __skb_set_sw_hash(struct sk_buff *skb, __u32 hash, bool is_l4) } void __skb_get_hash(struct sk_buff *skb); -u32 __skb_get_hash_symmetric(const struct sk_buff *skb); +u32 __skb_get_hash_symmetric(const struct net *net, const struct sk_buff *skb); u32 skb_get_poff(const struct sk_buff *skb); u32 __skb_get_poff(const struct sk_buff *skb, const void *data, const struct flow_keys_basic *keys, int hlen); diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c index f82e9a7d3b37..634896129780 100644 --- a/net/core/flow_dissector.c +++ b/net/core/flow_dissector.c @@ -1831,14 +1831,14 @@ EXPORT_SYMBOL(make_flow_keys_digest); static struct flow_dissector flow_keys_dissector_symmetric __read_mostly; -u32 __skb_get_hash_symmetric(const struct sk_buff *skb) +u32 __skb_get_hash_symmetric(const struct net *net, const struct sk_buff *skb) { struct flow_keys keys; __flow_hash_secret_init(); memset(&keys, 0, sizeof(keys)); - __skb_flow_dissect(NULL, skb, &flow_keys_dissector_symmetric, + __skb_flow_dissect(net, skb, &flow_keys_dissector_symmetric, &keys, NULL, 0, 0, 0, 0); return __flow_hash_from_keys(&keys, &hashrnd); diff --git a/net/netfilter/nft_hash.c b/net/netfilter/nft_hash.c index 92d47e469204..3e7296ed5319 100644 --- a/net/netfilter/nft_hash.c +++ b/net/netfilter/nft_hash.c @@ -51,7 +51,8 @@ static void nft_symhash_eval(const struct nft_expr *expr, struct sk_buff *skb = pkt->skb; u32 h; - h = reciprocal_scale(__skb_get_hash_symmetric(skb), priv->modulus); + h = reciprocal_scale(__skb_get_hash_symmetric(nft_net(pkt), skb), + priv->modulus); regs->data[priv->dreg] = h + priv->offset; } diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c index 964225580824..0e6166784972 100644 --- a/net/openvswitch/actions.c +++ b/net/openvswitch/actions.c @@ -1084,7 +1084,8 @@ static int clone(struct datapath *dp, struct sk_buff *skb, !dont_clone_flow_key); } -static void execute_hash(struct sk_buff *skb, struct sw_flow_key *key, +static void execute_hash(const struct net *net, + struct sk_buff *skb, struct sw_flow_key *key, const struct nlattr *attr) { struct ovs_action_hash *hash_act = nla_data(attr); @@ -1097,7 +1098,7 @@ static void execute_hash(struct sk_buff *skb, struct sw_flow_key *key, /* OVS_HASH_ALG_SYM_L4 hashing type. NOTE: this doesn't * extend past an encapsulated header. */ - hash = __skb_get_hash_symmetric(skb); + hash = __skb_get_hash_symmetric(net, skb); } hash = jhash_1word(hash, hash_act->hash_basis); @@ -1359,7 +1360,7 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb, break; case OVS_ACTION_ATTR_HASH: - execute_hash(skb, key, a); + execute_hash(ovs_dp_get_net(dp), skb, key, a); break; case OVS_ACTION_ATTR_PUSH_MPLS: { diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index ea3ebc160e25..b047fdb0c02c 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -1364,7 +1364,9 @@ static unsigned int fanout_demux_hash(struct packet_fanout *f, struct sk_buff *skb, unsigned int num) { - return reciprocal_scale(__skb_get_hash_symmetric(skb), num); + struct net *net = read_pnet(&f->net); + + return reciprocal_scale(__skb_get_hash_symmetric(net, skb), num); } static unsigned int fanout_demux_lb(struct packet_fanout *f,