Skip to content

Commit 73bcbd6

Browse files
committed
Merge: ipv6: stable backport for 10.1 phase 2
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-10/-/merge_requests/1043 JIRA: https://issues.redhat.com/browse/RHEL-96599 * 078aabd netlabel: Fix NULL pointer exception caused by CALIPSO on IPv4 sockets * 4d0ab3a ipv6: Start path selection from the first nexthop * 8b8e0dd ipv6: Do not consider link down nexthops in path selection * 7ac6ea4 ipv6: fix omitted netlink attributes when using RTEXT_FILTER_SKIP_STATS * 6933cd4 ipv6: Align behavior across nexthops during path selection * c46286f mr: consolidate the ipmr_can_free_table() checks. Signed-off-by: CKI Backport Bot <cki-ci-bot+cki-gitlab-backport-bot@redhat.com> Signed-off-by: Hangbin Liu <haliu@redhat.com> --- <small>Created 2025-06-13 05:39 UTC by backporter - [KWF FAQ](https://red.ht/kernel_workflow_doc) - [Slack #team-kernel-workflow](https://redhat-internal.slack.com/archives/C04LRUPMJQ5) - [Source](https://gitlab.com/cki-project/kernel-workflow/-/blob/main/webhook/utils/backporter.py) - [Documentation](https://gitlab.com/cki-project/kernel-workflow/-/blob/main/docs/README.backporter.md) - [Report an issue](https://issues.redhat.com/secure/CreateIssueDetails!init.jspa?pid=12334433&issuetype=1&priority=4&summary=backporter+webhook+issue&components=kernel-workflow+/+backporter)</small> Approved-by: Florian Westphal <fwestpha@redhat.com> Approved-by: Antoine Tenart <atenart@redhat.com> Approved-by: CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> Merged-by: Jan Stancek <jstancek@redhat.com>
2 parents 7f632dc + f3ab453 commit 73bcbd6

File tree

6 files changed

+88
-41
lines changed

6 files changed

+88
-41
lines changed

include/linux/mroute_base.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,11 @@ struct mr_table {
262262
int mroute_reg_vif_num;
263263
};
264264

265+
static inline bool mr_can_free_table(struct net *net)
266+
{
267+
return !check_net(net) || !net_initialized(net);
268+
}
269+
265270
#ifdef CONFIG_IP_MROUTE_COMMON
266271
void vif_device_init(struct vif_device *v,
267272
struct net_device *dev,

net/ipv4/ipmr.c

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -120,11 +120,6 @@ static void ipmr_expire_process(struct timer_list *t);
120120
lockdep_rtnl_is_held() || \
121121
list_empty(&net->ipv4.mr_tables))
122122

123-
static bool ipmr_can_free_table(struct net *net)
124-
{
125-
return !check_net(net) || !net_initialized(net);
126-
}
127-
128123
static struct mr_table *ipmr_mr_table_iter(struct net *net,
129124
struct mr_table *mrt)
130125
{
@@ -317,11 +312,6 @@ EXPORT_SYMBOL(ipmr_rule_default);
317312
#define ipmr_for_each_table(mrt, net) \
318313
for (mrt = net->ipv4.mrt; mrt; mrt = NULL)
319314

320-
static bool ipmr_can_free_table(struct net *net)
321-
{
322-
return !check_net(net);
323-
}
324-
325315
static struct mr_table *ipmr_mr_table_iter(struct net *net,
326316
struct mr_table *mrt)
327317
{
@@ -437,7 +427,7 @@ static void ipmr_free_table(struct mr_table *mrt)
437427
{
438428
struct net *net = read_pnet(&mrt->net);
439429

440-
WARN_ON_ONCE(!ipmr_can_free_table(net));
430+
WARN_ON_ONCE(!mr_can_free_table(net));
441431

442432
timer_shutdown_sync(&mrt->ipmr_expire_timer);
443433
mroute_clean_tables(mrt, MRT_FLUSH_VIFS | MRT_FLUSH_VIFS_STATIC |

net/ipv6/addrconf.c

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5798,6 +5798,27 @@ static void snmp6_fill_stats(u64 *stats, struct inet6_dev *idev, int attrtype,
57985798
}
57995799
}
58005800

5801+
static int inet6_fill_ifla6_stats_attrs(struct sk_buff *skb,
5802+
struct inet6_dev *idev)
5803+
{
5804+
struct nlattr *nla;
5805+
5806+
nla = nla_reserve(skb, IFLA_INET6_STATS, IPSTATS_MIB_MAX * sizeof(u64));
5807+
if (!nla)
5808+
goto nla_put_failure;
5809+
snmp6_fill_stats(nla_data(nla), idev, IFLA_INET6_STATS, nla_len(nla));
5810+
5811+
nla = nla_reserve(skb, IFLA_INET6_ICMP6STATS, ICMP6_MIB_MAX * sizeof(u64));
5812+
if (!nla)
5813+
goto nla_put_failure;
5814+
snmp6_fill_stats(nla_data(nla), idev, IFLA_INET6_ICMP6STATS, nla_len(nla));
5815+
5816+
return 0;
5817+
5818+
nla_put_failure:
5819+
return -EMSGSIZE;
5820+
}
5821+
58015822
static int inet6_fill_ifla6_attrs(struct sk_buff *skb, struct inet6_dev *idev,
58025823
u32 ext_filter_mask)
58035824
{
@@ -5820,18 +5841,10 @@ static int inet6_fill_ifla6_attrs(struct sk_buff *skb, struct inet6_dev *idev,
58205841

58215842
/* XXX - MC not implemented */
58225843

5823-
if (ext_filter_mask & RTEXT_FILTER_SKIP_STATS)
5824-
return 0;
5825-
5826-
nla = nla_reserve(skb, IFLA_INET6_STATS, IPSTATS_MIB_MAX * sizeof(u64));
5827-
if (!nla)
5828-
goto nla_put_failure;
5829-
snmp6_fill_stats(nla_data(nla), idev, IFLA_INET6_STATS, nla_len(nla));
5830-
5831-
nla = nla_reserve(skb, IFLA_INET6_ICMP6STATS, ICMP6_MIB_MAX * sizeof(u64));
5832-
if (!nla)
5833-
goto nla_put_failure;
5834-
snmp6_fill_stats(nla_data(nla), idev, IFLA_INET6_ICMP6STATS, nla_len(nla));
5844+
if (!(ext_filter_mask & RTEXT_FILTER_SKIP_STATS)) {
5845+
if (inet6_fill_ifla6_stats_attrs(skb, idev) < 0)
5846+
goto nla_put_failure;
5847+
}
58355848

58365849
nla = nla_reserve(skb, IFLA_INET6_TOKEN, sizeof(struct in6_addr));
58375850
if (!nla)

net/ipv6/calipso.c

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1072,8 +1072,13 @@ static int calipso_sock_getattr(struct sock *sk,
10721072
struct ipv6_opt_hdr *hop;
10731073
int opt_len, len, ret_val = -ENOMSG, offset;
10741074
unsigned char *opt;
1075-
struct ipv6_txoptions *txopts = txopt_get(inet6_sk(sk));
1075+
struct ipv6_pinfo *pinfo = inet6_sk(sk);
1076+
struct ipv6_txoptions *txopts;
1077+
1078+
if (!pinfo)
1079+
return -EAFNOSUPPORT;
10761080

1081+
txopts = txopt_get(pinfo);
10771082
if (!txopts || !txopts->hopopt)
10781083
goto done;
10791084

@@ -1125,8 +1130,13 @@ static int calipso_sock_setattr(struct sock *sk,
11251130
{
11261131
int ret_val;
11271132
struct ipv6_opt_hdr *old, *new;
1128-
struct ipv6_txoptions *txopts = txopt_get(inet6_sk(sk));
1133+
struct ipv6_pinfo *pinfo = inet6_sk(sk);
1134+
struct ipv6_txoptions *txopts;
1135+
1136+
if (!pinfo)
1137+
return -EAFNOSUPPORT;
11291138

1139+
txopts = txopt_get(pinfo);
11301140
old = NULL;
11311141
if (txopts)
11321142
old = txopts->hopopt;
@@ -1153,8 +1163,13 @@ static int calipso_sock_setattr(struct sock *sk,
11531163
static void calipso_sock_delattr(struct sock *sk)
11541164
{
11551165
struct ipv6_opt_hdr *new_hop;
1156-
struct ipv6_txoptions *txopts = txopt_get(inet6_sk(sk));
1166+
struct ipv6_pinfo *pinfo = inet6_sk(sk);
1167+
struct ipv6_txoptions *txopts;
1168+
1169+
if (!pinfo)
1170+
return;
11571171

1172+
txopts = txopt_get(pinfo);
11581173
if (!txopts || !txopts->hopopt)
11591174
goto done;
11601175

net/ipv6/ip6mr.c

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -108,11 +108,6 @@ static void ipmr_expire_process(struct timer_list *t);
108108
lockdep_rtnl_is_held() || \
109109
list_empty(&net->ipv6.mr6_tables))
110110

111-
static bool ip6mr_can_free_table(struct net *net)
112-
{
113-
return !check_net(net) || !net_initialized(net);
114-
}
115-
116111
static struct mr_table *ip6mr_mr_table_iter(struct net *net,
117112
struct mr_table *mrt)
118113
{
@@ -306,11 +301,6 @@ EXPORT_SYMBOL(ip6mr_rule_default);
306301
#define ip6mr_for_each_table(mrt, net) \
307302
for (mrt = net->ipv6.mrt6; mrt; mrt = NULL)
308303

309-
static bool ip6mr_can_free_table(struct net *net)
310-
{
311-
return !check_net(net);
312-
}
313-
314304
static struct mr_table *ip6mr_mr_table_iter(struct net *net,
315305
struct mr_table *mrt)
316306
{
@@ -416,7 +406,7 @@ static void ip6mr_free_table(struct mr_table *mrt)
416406
{
417407
struct net *net = read_pnet(&mrt->net);
418408

419-
WARN_ON_ONCE(!ip6mr_can_free_table(net));
409+
WARN_ON_ONCE(!mr_can_free_table(net));
420410

421411
timer_shutdown_sync(&mrt->ipmr_expire_timer);
422412
mroute_clean_tables(mrt, MRT6_FLUSH_MIFS | MRT6_FLUSH_MIFS_STATIC |

net/ipv6/route.c

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -412,12 +412,37 @@ static bool rt6_check_expired(const struct rt6_info *rt)
412412
return false;
413413
}
414414

415+
static struct fib6_info *
416+
rt6_multipath_first_sibling_rcu(const struct fib6_info *rt)
417+
{
418+
struct fib6_info *iter;
419+
struct fib6_node *fn;
420+
421+
fn = rcu_dereference(rt->fib6_node);
422+
if (!fn)
423+
goto out;
424+
iter = rcu_dereference(fn->leaf);
425+
if (!iter)
426+
goto out;
427+
428+
while (iter) {
429+
if (iter->fib6_metric == rt->fib6_metric &&
430+
rt6_qualify_for_ecmp(iter))
431+
return iter;
432+
iter = rcu_dereference(iter->fib6_next);
433+
}
434+
435+
out:
436+
return NULL;
437+
}
438+
415439
void fib6_select_path(const struct net *net, struct fib6_result *res,
416440
struct flowi6 *fl6, int oif, bool have_oif_match,
417441
const struct sk_buff *skb, int strict)
418442
{
419-
struct fib6_info *match = res->f6i;
443+
struct fib6_info *first, *match = res->f6i;
420444
struct fib6_info *sibling;
445+
int hash;
421446

422447
if (!match->nh && (!match->fib6_nsiblings || have_oif_match))
423448
goto out;
@@ -440,16 +465,25 @@ void fib6_select_path(const struct net *net, struct fib6_result *res,
440465
return;
441466
}
442467

443-
if (fl6->mp_hash <= atomic_read(&match->fib6_nh->fib_nh_upper_bound))
468+
first = rt6_multipath_first_sibling_rcu(match);
469+
if (!first)
444470
goto out;
445471

446-
list_for_each_entry_rcu(sibling, &match->fib6_siblings,
472+
hash = fl6->mp_hash;
473+
if (hash <= atomic_read(&first->fib6_nh->fib_nh_upper_bound)) {
474+
if (rt6_score_route(first->fib6_nh, first->fib6_flags, oif,
475+
strict) >= 0)
476+
match = first;
477+
goto out;
478+
}
479+
480+
list_for_each_entry_rcu(sibling, &first->fib6_siblings,
447481
fib6_siblings) {
448482
const struct fib6_nh *nh = sibling->fib6_nh;
449483
int nh_upper_bound;
450484

451485
nh_upper_bound = atomic_read(&nh->fib_nh_upper_bound);
452-
if (fl6->mp_hash > nh_upper_bound)
486+
if (hash > nh_upper_bound)
453487
continue;
454488
if (rt6_score_route(nh, sibling->fib6_flags, oif, strict) < 0)
455489
break;

0 commit comments

Comments
 (0)