Commit d2675fe9 authored by Jakub Kicinski's avatar Jakub Kicinski

Merge branch 'net-flow-dissector-allow-explicit-passing-of-netns'

Florian Westphal says:

====================
net: flow dissector: allow explicit passing of netns

Change since last version:
 fix kdoc comment warning reported by kbuild robot, no other changes,
 thus retaining RvB tags from Eric and Willem.
 v1: https://lore.kernel.org/netdev/20240607083205.3000-1-fw@strlen.de/

Years ago flow dissector gained ability to delegate flow dissection
to a bpf program, scoped per netns.

The netns is derived from skb->dev, and if that is not available, from
skb->sk.  If neither is set, we hit a (benign) WARN_ON_ONCE().

This WARN_ON_ONCE can be triggered from netfilter.
Known skb origins are nf_send_reset and ipv4 stack generated IGMP
messages.

Lets allow callers to pass the current netns explicitly and make
nf_tables use those instead.

This targets net-next instead of net because the WARN is benign and this
is not a regression.
====================

Link: https://lore.kernel.org/r/20240608221057.16070-1-fw@strlen.deSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 91579c93 d1dab4f7
...@@ -1498,8 +1498,14 @@ __skb_set_sw_hash(struct sk_buff *skb, __u32 hash, bool is_l4) ...@@ -1498,8 +1498,14 @@ __skb_set_sw_hash(struct sk_buff *skb, __u32 hash, bool is_l4)
__skb_set_hash(skb, hash, true, is_l4); __skb_set_hash(skb, hash, true, is_l4);
} }
void __skb_get_hash(struct sk_buff *skb); u32 __skb_get_hash_symmetric_net(const struct net *net, const struct sk_buff *skb);
u32 __skb_get_hash_symmetric(const struct sk_buff *skb);
static inline u32 __skb_get_hash_symmetric(const struct sk_buff *skb)
{
return __skb_get_hash_symmetric_net(NULL, skb);
}
void __skb_get_hash_net(const struct net *net, struct sk_buff *skb);
u32 skb_get_poff(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, u32 __skb_get_poff(const struct sk_buff *skb, const void *data,
const struct flow_keys_basic *keys, int hlen); const struct flow_keys_basic *keys, int hlen);
...@@ -1578,10 +1584,18 @@ void skb_flow_dissect_hash(const struct sk_buff *skb, ...@@ -1578,10 +1584,18 @@ void skb_flow_dissect_hash(const struct sk_buff *skb,
struct flow_dissector *flow_dissector, struct flow_dissector *flow_dissector,
void *target_container); void *target_container);
static inline __u32 skb_get_hash_net(const struct net *net, struct sk_buff *skb)
{
if (!skb->l4_hash && !skb->sw_hash)
__skb_get_hash_net(net, skb);
return skb->hash;
}
static inline __u32 skb_get_hash(struct sk_buff *skb) static inline __u32 skb_get_hash(struct sk_buff *skb)
{ {
if (!skb->l4_hash && !skb->sw_hash) if (!skb->l4_hash && !skb->sw_hash)
__skb_get_hash(skb); __skb_get_hash_net(NULL, skb);
return skb->hash; return skb->hash;
} }
......
...@@ -1845,22 +1845,23 @@ EXPORT_SYMBOL(make_flow_keys_digest); ...@@ -1845,22 +1845,23 @@ EXPORT_SYMBOL(make_flow_keys_digest);
static struct flow_dissector flow_keys_dissector_symmetric __read_mostly; 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_net(const struct net *net, const struct sk_buff *skb)
{ {
struct flow_keys keys; struct flow_keys keys;
__flow_hash_secret_init(); __flow_hash_secret_init();
memset(&keys, 0, sizeof(keys)); 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); &keys, NULL, 0, 0, 0, 0);
return __flow_hash_from_keys(&keys, &hashrnd); return __flow_hash_from_keys(&keys, &hashrnd);
} }
EXPORT_SYMBOL_GPL(__skb_get_hash_symmetric); EXPORT_SYMBOL_GPL(__skb_get_hash_symmetric_net);
/** /**
* __skb_get_hash: calculate a flow hash * __skb_get_hash_net: calculate a flow hash
* @net: associated network namespace, derived from @skb if NULL
* @skb: sk_buff to calculate flow hash from * @skb: sk_buff to calculate flow hash from
* *
* This function calculates a flow hash based on src/dst addresses * This function calculates a flow hash based on src/dst addresses
...@@ -1868,18 +1869,24 @@ EXPORT_SYMBOL_GPL(__skb_get_hash_symmetric); ...@@ -1868,18 +1869,24 @@ EXPORT_SYMBOL_GPL(__skb_get_hash_symmetric);
* on success, zero indicates no valid hash. Also, sets l4_hash in skb * on success, zero indicates no valid hash. Also, sets l4_hash in skb
* if hash is a canonical 4-tuple hash over transport ports. * if hash is a canonical 4-tuple hash over transport ports.
*/ */
void __skb_get_hash(struct sk_buff *skb) void __skb_get_hash_net(const struct net *net, struct sk_buff *skb)
{ {
struct flow_keys keys; struct flow_keys keys;
u32 hash; 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);
__flow_hash_secret_init(); __flow_hash_secret_init();
hash = ___skb_get_hash(skb, &keys, &hashrnd); hash = __flow_hash_from_keys(&keys, &hashrnd);
__skb_set_sw_hash(skb, hash, flow_keys_have_l4(&keys)); __skb_set_sw_hash(skb, hash, flow_keys_have_l4(&keys));
} }
EXPORT_SYMBOL(__skb_get_hash); EXPORT_SYMBOL(__skb_get_hash_net);
__u32 skb_get_hash_perturb(const struct sk_buff *skb, __u32 skb_get_hash_perturb(const struct sk_buff *skb,
const siphash_key_t *perturb) const siphash_key_t *perturb)
......
...@@ -317,7 +317,7 @@ void nft_trace_init(struct nft_traceinfo *info, const struct nft_pktinfo *pkt, ...@@ -317,7 +317,7 @@ void nft_trace_init(struct nft_traceinfo *info, const struct nft_pktinfo *pkt,
net_get_random_once(&trace_key, sizeof(trace_key)); net_get_random_once(&trace_key, sizeof(trace_key));
info->skbid = (u32)siphash_3u32(hash32_ptr(skb), info->skbid = (u32)siphash_3u32(hash32_ptr(skb),
skb_get_hash(skb), skb_get_hash_net(nft_net(pkt), skb),
skb->skb_iif, skb->skb_iif,
&trace_key); &trace_key);
} }
...@@ -51,7 +51,8 @@ static void nft_symhash_eval(const struct nft_expr *expr, ...@@ -51,7 +51,8 @@ static void nft_symhash_eval(const struct nft_expr *expr,
struct sk_buff *skb = pkt->skb; struct sk_buff *skb = pkt->skb;
u32 h; u32 h;
h = reciprocal_scale(__skb_get_hash_symmetric(skb), priv->modulus); h = reciprocal_scale(__skb_get_hash_symmetric_net(nft_net(pkt), skb),
priv->modulus);
regs->data[priv->dreg] = h + priv->offset; regs->data[priv->dreg] = h + priv->offset;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment