Florian Westphal <fw@xxxxxxxxx> wrote: > When this was added (handle dissection from bpf prog, per netns), the correct > solution would have been to pass 'struct net' explicitly via skb_get_hash() > and all variants. As that was likely deemed to be too much code churn it > tries to infer struct net via skb->{dev,sk}. > > So there are several options here: > 1. remove the WARN_ON_ONCE and be done with it > 2. remove the WARN_ON_ONCE and pretend net was init_net > 3. also look at skb_dst(skb)->dev if skb->dev is unset, then back to 1) > or 2) > 4. stop using skb_get_hash() from netfilter (but there are likely other > callers that might hit this). diff --git a/net/netfilter/nf_tables_trace.c b/net/netfilter/nf_tables_trace.c --- a/net/netfilter/nf_tables_trace.c +++ b/net/netfilter/nf_tables_trace.c @@ -303,6 +303,30 @@ void nft_trace_notify(const struct nft_pktinfo *pkt, kfree_skb(skb); } +static u32 __nf_skb_get_hash(const struct net *net, struct sk_buff *skb) +{ + struct flow_keys keys; + u32 hash; + + memset(&keys, 0, sizeof(keys)); + + __skb_flow_dissect(net, skb, &flow_keys_dissector, + &keys, NULL, 0, 0, 0, + FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL); + + hash = flow_hash_from_keys(&keys); + __skb_set_sw_hash(skb, hash, flow_keys_have_l4(&keys)); + return hash; +} + +static u32 nf_skb_get_hash(const struct net *net, struct sk_buff *skb) +{ + if (!skb->l4_hash && !skb->sw_hash) + return __nf_skb_get_hash(net, skb); + + return skb->hash; +} + void nft_trace_init(struct nft_traceinfo *info, const struct nft_pktinfo *pkt, const struct nft_chain *chain) { @@ -317,7 +341,7 @@ void nft_trace_init(struct nft_traceinfo *info, const struct nft_pktinfo *pkt, net_get_random_once(&trace_key, sizeof(trace_key)); info->skbid = (u32)siphash_3u32(hash32_ptr(skb), - skb_get_hash(skb), + nf_skb_get_hash(nft_net(pkt), skb), skb->skb_iif, &trace_key); } ... 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.