Skip to content

Commit 0b0dff5

Browse files
wdebruijkuba-moo
authored andcommitted
ipv6: per-netns exclusive flowlabel checks
Ipv6 flowlabels historically require a reservation before use. Optionally in exclusive mode (e.g., user-private). Commit 59c820b ("ipv6: elide flowlabel check if no exclusive leases exist") introduced a fastpath that avoids this check when no exclusive leases exist in the system, and thus any flowlabel use will be granted. That allows skipping the control operation to reserve a flowlabel entirely. Though with a warning if the fast path fails: This is an optimization. Robust applications still have to revert to requesting leases if the fast path fails due to an exclusive lease. Still, this is subtle. Better isolate network namespaces from each other. Flowlabels are per-netns. Also record per-netns whether exclusive leases are in use. Then behavior does not change based on activity in other netns. Changes v2 - wrap in IS_ENABLED(CONFIG_IPV6) to avoid breakage if disabled Fixes: 59c820b ("ipv6: elide flowlabel check if no exclusive leases exist") Link: https://lore.kernel.org/netdev/MWHPR2201MB1072BCCCFCE779E4094837ACD0329@MWHPR2201MB1072.namprd22.prod.outlook.com/ Reported-by: Congyu Liu <liu3101@purdue.edu> Signed-off-by: Willem de Bruijn <willemb@google.com> Tested-by: Congyu Liu <liu3101@purdue.edu> Link: https://lore.kernel.org/r/20220215160037.1976072-1-willemdebruijn.kernel@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
1 parent c832962 commit 0b0dff5

File tree

3 files changed

+9
-3
lines changed

3 files changed

+9
-3
lines changed

include/net/ipv6.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -393,17 +393,20 @@ static inline void txopt_put(struct ipv6_txoptions *opt)
393393
kfree_rcu(opt, rcu);
394394
}
395395

396+
#if IS_ENABLED(CONFIG_IPV6)
396397
struct ip6_flowlabel *__fl6_sock_lookup(struct sock *sk, __be32 label);
397398

398399
extern struct static_key_false_deferred ipv6_flowlabel_exclusive;
399400
static inline struct ip6_flowlabel *fl6_sock_lookup(struct sock *sk,
400401
__be32 label)
401402
{
402-
if (static_branch_unlikely(&ipv6_flowlabel_exclusive.key))
403+
if (static_branch_unlikely(&ipv6_flowlabel_exclusive.key) &&
404+
READ_ONCE(sock_net(sk)->ipv6.flowlabel_has_excl))
403405
return __fl6_sock_lookup(sk, label) ? : ERR_PTR(-ENOENT);
404406

405407
return NULL;
406408
}
409+
#endif
407410

408411
struct ipv6_txoptions *fl6_merge_options(struct ipv6_txoptions *opt_space,
409412
struct ip6_flowlabel *fl,

include/net/netns/ipv6.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,10 @@ struct netns_ipv6 {
7777
spinlock_t fib6_gc_lock;
7878
unsigned int ip6_rt_gc_expire;
7979
unsigned long ip6_rt_last_gc;
80+
unsigned char flowlabel_has_excl;
8081
#ifdef CONFIG_IPV6_MULTIPLE_TABLES
81-
unsigned int fib6_rules_require_fldissect;
8282
bool fib6_has_custom_rules;
83+
unsigned int fib6_rules_require_fldissect;
8384
#ifdef CONFIG_IPV6_SUBTREES
8485
unsigned int fib6_routes_require_src;
8586
#endif

net/ipv6/ip6_flowlabel.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -450,8 +450,10 @@ fl_create(struct net *net, struct sock *sk, struct in6_flowlabel_req *freq,
450450
err = -EINVAL;
451451
goto done;
452452
}
453-
if (fl_shared_exclusive(fl) || fl->opt)
453+
if (fl_shared_exclusive(fl) || fl->opt) {
454+
WRITE_ONCE(sock_net(sk)->ipv6.flowlabel_has_excl, 1);
454455
static_branch_deferred_inc(&ipv6_flowlabel_exclusive);
456+
}
455457
return fl;
456458

457459
done:

0 commit comments

Comments
 (0)