Skip to content

Commit 9892672

Browse files
committed
Merge: ipv6: stable backport for 10.1 phase 1
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-10/-/merge_requests/630 JIRA: https://issues.redhat.com/browse/RHEL-84540 * 3a1beab ipv6: Remove redundant unlikely() * 7213a1c ip6mr: Add __init to ip6_mr_cleanup(). * d51cfd5 ipv6: mcast: reduce ipv6_chk_mcast_addr() indentation * 6269629 ipv6: mcast: annotate data-races around mc->mca_sfcount[MCAST_EXCLUDE] * 00bf203 ipv6: mcast: annotate data-race around psf->sf_count[MCAST_XXX] * 2c2b61d netlink: add IGMP/MLD join/leave notifications * aa4ad7c netlink: correct nlmsg size for multicast notifications * 33d97a0 netlink: add IPv6 anycast join/leave notifications * 3440fa3 inet: ipmr: fix data-races * 9740890 ipv6: Fix memleak of nhc_pcpu_rth_output in fib_check_nh_v6_gw(). * 9a81fc3 ipv6: Set errno after ip_fib_metrics_init() in ip6_route_info_create(). 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-03-26 11:23 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://gitlab.com/cki-project/kernel-workflow/-/issues/new?issue%5Btitle%5D=backporter%20webhook%20issue)</small> Approved-by: Antoine Tenart <atenart@redhat.com> Approved-by: Ivan Vecera <ivecera@redhat.com> Approved-by: CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> Merged-by: Julio Faracco <jfaracco@redhat.com>
2 parents 8877b60 + d78dcb2 commit 9892672

File tree

14 files changed

+271
-93
lines changed

14 files changed

+271
-93
lines changed

drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1003,10 +1003,10 @@ static void mlxsw_sp_mr_route_stats_update(struct mlxsw_sp *mlxsw_sp,
10031003
mr->mr_ops->route_stats(mlxsw_sp, mr_route->route_priv, &packets,
10041004
&bytes);
10051005

1006-
if (mr_route->mfc->mfc_un.res.pkt != packets)
1007-
mr_route->mfc->mfc_un.res.lastuse = jiffies;
1008-
mr_route->mfc->mfc_un.res.pkt = packets;
1009-
mr_route->mfc->mfc_un.res.bytes = bytes;
1006+
if (atomic_long_read(&mr_route->mfc->mfc_un.res.pkt) != packets)
1007+
WRITE_ONCE(mr_route->mfc->mfc_un.res.lastuse, jiffies);
1008+
atomic_long_set(&mr_route->mfc->mfc_un.res.pkt, packets);
1009+
atomic_long_set(&mr_route->mfc->mfc_un.res.bytes, bytes);
10101010
}
10111011

10121012
static void mlxsw_sp_mr_stats_update(struct work_struct *work)

include/linux/igmp.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ struct ip_mc_list {
8787
char loaded;
8888
unsigned char gsquery; /* check source marks? */
8989
unsigned char crcount;
90+
unsigned long mca_cstamp;
91+
unsigned long mca_tstamp;
9092
struct rcu_head rcu;
9193
};
9294

include/linux/mroute_base.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -146,9 +146,9 @@ struct mr_mfc {
146146
unsigned long last_assert;
147147
int minvif;
148148
int maxvif;
149-
unsigned long bytes;
150-
unsigned long pkt;
151-
unsigned long wrong_if;
149+
atomic_long_t bytes;
150+
atomic_long_t pkt;
151+
atomic_long_t wrong_if;
152152
unsigned long lastuse;
153153
unsigned char ttls[MAXVIFS];
154154
refcount_t refcount;

include/net/addrconf.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,23 @@ struct ifa6_config {
8888
u16 scope;
8989
};
9090

91+
enum addr_type_t {
92+
UNICAST_ADDR,
93+
MULTICAST_ADDR,
94+
ANYCAST_ADDR,
95+
};
96+
97+
struct inet6_fill_args {
98+
u32 portid;
99+
u32 seq;
100+
int event;
101+
unsigned int flags;
102+
int netnsid;
103+
int ifindex;
104+
enum addr_type_t type;
105+
bool force_rt_scope_universe;
106+
};
107+
91108
int addrconf_init(void);
92109
void addrconf_cleanup(void);
93110

@@ -525,4 +542,11 @@ int if6_proc_init(void);
525542
void if6_proc_exit(void);
526543
#endif
527544

545+
int inet6_fill_ifmcaddr(struct sk_buff *skb,
546+
const struct ifmcaddr6 *ifmca,
547+
struct inet6_fill_args *args);
548+
549+
int inet6_fill_ifacaddr(struct sk_buff *skb,
550+
const struct ifacaddr6 *ifaca,
551+
struct inet6_fill_args *args);
528552
#endif

include/uapi/linux/rtnetlink.h

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,10 +93,18 @@ enum {
9393
RTM_NEWPREFIX = 52,
9494
#define RTM_NEWPREFIX RTM_NEWPREFIX
9595

96-
RTM_GETMULTICAST = 58,
96+
RTM_NEWMULTICAST = 56,
97+
#define RTM_NEWMULTICAST RTM_NEWMULTICAST
98+
RTM_DELMULTICAST,
99+
#define RTM_DELMULTICAST RTM_DELMULTICAST
100+
RTM_GETMULTICAST,
97101
#define RTM_GETMULTICAST RTM_GETMULTICAST
98102

99-
RTM_GETANYCAST = 62,
103+
RTM_NEWANYCAST = 60,
104+
#define RTM_NEWANYCAST RTM_NEWANYCAST
105+
RTM_DELANYCAST,
106+
#define RTM_DELANYCAST RTM_DELANYCAST
107+
RTM_GETANYCAST,
100108
#define RTM_GETANYCAST RTM_GETANYCAST
101109

102110
RTM_NEWNEIGHTBL = 64,
@@ -774,6 +782,12 @@ enum rtnetlink_groups {
774782
#define RTNLGRP_TUNNEL RTNLGRP_TUNNEL
775783
RTNLGRP_STATS,
776784
#define RTNLGRP_STATS RTNLGRP_STATS
785+
RTNLGRP_IPV4_MCADDR,
786+
#define RTNLGRP_IPV4_MCADDR RTNLGRP_IPV4_MCADDR
787+
RTNLGRP_IPV6_MCADDR,
788+
#define RTNLGRP_IPV6_MCADDR RTNLGRP_IPV6_MCADDR
789+
RTNLGRP_IPV6_ACADDR,
790+
#define RTNLGRP_IPV6_ACADDR RTNLGRP_IPV6_ACADDR
777791
__RTNLGRP_MAX
778792
};
779793
#define RTNLGRP_MAX (__RTNLGRP_MAX - 1)

net/ipv4/igmp.c

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@
8888
#include <linux/byteorder/generic.h>
8989

9090
#include <net/net_namespace.h>
91+
#include <net/netlink.h>
92+
#include <net/addrconf.h>
9193
#include <net/arp.h>
9294
#include <net/ip.h>
9395
#include <net/protocol.h>
@@ -1430,6 +1432,65 @@ static void ip_mc_hash_remove(struct in_device *in_dev,
14301432
*mc_hash = im->next_hash;
14311433
}
14321434

1435+
static int inet_fill_ifmcaddr(struct sk_buff *skb, struct net_device *dev,
1436+
const struct ip_mc_list *im, int event)
1437+
{
1438+
struct ifa_cacheinfo ci;
1439+
struct ifaddrmsg *ifm;
1440+
struct nlmsghdr *nlh;
1441+
1442+
nlh = nlmsg_put(skb, 0, 0, event, sizeof(struct ifaddrmsg), 0);
1443+
if (!nlh)
1444+
return -EMSGSIZE;
1445+
1446+
ifm = nlmsg_data(nlh);
1447+
ifm->ifa_family = AF_INET;
1448+
ifm->ifa_prefixlen = 32;
1449+
ifm->ifa_flags = IFA_F_PERMANENT;
1450+
ifm->ifa_scope = RT_SCOPE_UNIVERSE;
1451+
ifm->ifa_index = dev->ifindex;
1452+
1453+
ci.cstamp = (READ_ONCE(im->mca_cstamp) - INITIAL_JIFFIES) * 100UL / HZ;
1454+
ci.tstamp = ci.cstamp;
1455+
ci.ifa_prefered = INFINITY_LIFE_TIME;
1456+
ci.ifa_valid = INFINITY_LIFE_TIME;
1457+
1458+
if (nla_put_in_addr(skb, IFA_MULTICAST, im->multiaddr) < 0 ||
1459+
nla_put(skb, IFA_CACHEINFO, sizeof(ci), &ci) < 0) {
1460+
nlmsg_cancel(skb, nlh);
1461+
return -EMSGSIZE;
1462+
}
1463+
1464+
nlmsg_end(skb, nlh);
1465+
return 0;
1466+
}
1467+
1468+
static void inet_ifmcaddr_notify(struct net_device *dev,
1469+
const struct ip_mc_list *im, int event)
1470+
{
1471+
struct net *net = dev_net(dev);
1472+
struct sk_buff *skb;
1473+
int err = -ENOMEM;
1474+
1475+
skb = nlmsg_new(NLMSG_ALIGN(sizeof(struct ifaddrmsg)) +
1476+
nla_total_size(sizeof(__be32)) +
1477+
nla_total_size(sizeof(struct ifa_cacheinfo)),
1478+
GFP_KERNEL);
1479+
if (!skb)
1480+
goto error;
1481+
1482+
err = inet_fill_ifmcaddr(skb, dev, im, event);
1483+
if (err < 0) {
1484+
WARN_ON_ONCE(err == -EMSGSIZE);
1485+
nlmsg_free(skb);
1486+
goto error;
1487+
}
1488+
1489+
rtnl_notify(skb, net, 0, RTNLGRP_IPV4_MCADDR, NULL, GFP_KERNEL);
1490+
return;
1491+
error:
1492+
rtnl_set_sk_err(net, RTNLGRP_IPV4_MCADDR, err);
1493+
}
14331494

14341495
/*
14351496
* A socket has joined a multicast group on device dev.
@@ -1457,6 +1518,8 @@ static void ____ip_mc_inc_group(struct in_device *in_dev, __be32 addr,
14571518
im->interface = in_dev;
14581519
in_dev_hold(in_dev);
14591520
im->multiaddr = addr;
1521+
im->mca_cstamp = jiffies;
1522+
im->mca_tstamp = im->mca_cstamp;
14601523
/* initial mode is (EX, empty) */
14611524
im->sfmode = mode;
14621525
im->sfcount[mode] = 1;
@@ -1476,6 +1539,7 @@ static void ____ip_mc_inc_group(struct in_device *in_dev, __be32 addr,
14761539
igmpv3_del_delrec(in_dev, im);
14771540
#endif
14781541
igmp_group_added(im);
1542+
inet_ifmcaddr_notify(in_dev->dev, im, RTM_NEWMULTICAST);
14791543
if (!in_dev->dead)
14801544
ip_rt_multicast_event(in_dev);
14811545
out:
@@ -1689,6 +1753,8 @@ void __ip_mc_dec_group(struct in_device *in_dev, __be32 addr, gfp_t gfp)
16891753
*ip = i->next_rcu;
16901754
in_dev->mc_count--;
16911755
__igmp_group_dropped(i, gfp);
1756+
inet_ifmcaddr_notify(in_dev->dev, i,
1757+
RTM_DELMULTICAST);
16921758
ip_mc_clear_src(i);
16931759

16941760
if (!in_dev->dead)

net/ipv4/ipmr.c

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -831,7 +831,7 @@ static void ipmr_update_thresholds(struct mr_table *mrt, struct mr_mfc *cache,
831831
cache->mfc_un.res.maxvif = vifi + 1;
832832
}
833833
}
834-
cache->mfc_un.res.lastuse = jiffies;
834+
WRITE_ONCE(cache->mfc_un.res.lastuse, jiffies);
835835
}
836836

837837
static int vif_add(struct net *net, struct mr_table *mrt,
@@ -1681,9 +1681,9 @@ int ipmr_ioctl(struct sock *sk, int cmd, void *arg)
16811681
rcu_read_lock();
16821682
c = ipmr_cache_find(mrt, sr->src.s_addr, sr->grp.s_addr);
16831683
if (c) {
1684-
sr->pktcnt = c->_c.mfc_un.res.pkt;
1685-
sr->bytecnt = c->_c.mfc_un.res.bytes;
1686-
sr->wrong_if = c->_c.mfc_un.res.wrong_if;
1684+
sr->pktcnt = atomic_long_read(&c->_c.mfc_un.res.pkt);
1685+
sr->bytecnt = atomic_long_read(&c->_c.mfc_un.res.bytes);
1686+
sr->wrong_if = atomic_long_read(&c->_c.mfc_un.res.wrong_if);
16871687
rcu_read_unlock();
16881688
return 0;
16891689
}
@@ -1753,9 +1753,9 @@ int ipmr_compat_ioctl(struct sock *sk, unsigned int cmd, void __user *arg)
17531753
rcu_read_lock();
17541754
c = ipmr_cache_find(mrt, sr.src.s_addr, sr.grp.s_addr);
17551755
if (c) {
1756-
sr.pktcnt = c->_c.mfc_un.res.pkt;
1757-
sr.bytecnt = c->_c.mfc_un.res.bytes;
1758-
sr.wrong_if = c->_c.mfc_un.res.wrong_if;
1756+
sr.pktcnt = atomic_long_read(&c->_c.mfc_un.res.pkt);
1757+
sr.bytecnt = atomic_long_read(&c->_c.mfc_un.res.bytes);
1758+
sr.wrong_if = atomic_long_read(&c->_c.mfc_un.res.wrong_if);
17591759
rcu_read_unlock();
17601760

17611761
if (copy_to_user(arg, &sr, sizeof(sr)))
@@ -1988,9 +1988,9 @@ static void ip_mr_forward(struct net *net, struct mr_table *mrt,
19881988
int vif, ct;
19891989

19901990
vif = c->_c.mfc_parent;
1991-
c->_c.mfc_un.res.pkt++;
1992-
c->_c.mfc_un.res.bytes += skb->len;
1993-
c->_c.mfc_un.res.lastuse = jiffies;
1991+
atomic_long_inc(&c->_c.mfc_un.res.pkt);
1992+
atomic_long_add(skb->len, &c->_c.mfc_un.res.bytes);
1993+
WRITE_ONCE(c->_c.mfc_un.res.lastuse, jiffies);
19941994

19951995
if (c->mfc_origin == htonl(INADDR_ANY) && true_vifi >= 0) {
19961996
struct mfc_cache *cache_proxy;
@@ -2021,7 +2021,7 @@ static void ip_mr_forward(struct net *net, struct mr_table *mrt,
20212021
goto dont_forward;
20222022
}
20232023

2024-
c->_c.mfc_un.res.wrong_if++;
2024+
atomic_long_inc(&c->_c.mfc_un.res.wrong_if);
20252025

20262026
if (true_vifi >= 0 && mrt->mroute_do_assert &&
20272027
/* pimsm uses asserts, when switching from RPT to SPT,
@@ -3029,9 +3029,9 @@ static int ipmr_mfc_seq_show(struct seq_file *seq, void *v)
30293029

30303030
if (it->cache != &mrt->mfc_unres_queue) {
30313031
seq_printf(seq, " %8lu %8lu %8lu",
3032-
mfc->_c.mfc_un.res.pkt,
3033-
mfc->_c.mfc_un.res.bytes,
3034-
mfc->_c.mfc_un.res.wrong_if);
3032+
atomic_long_read(&mfc->_c.mfc_un.res.pkt),
3033+
atomic_long_read(&mfc->_c.mfc_un.res.bytes),
3034+
atomic_long_read(&mfc->_c.mfc_un.res.wrong_if));
30353035
for (n = mfc->_c.mfc_un.res.minvif;
30363036
n < mfc->_c.mfc_un.res.maxvif; n++) {
30373037
if (VIF_EXISTS(mrt, n) &&

net/ipv4/ipmr_base.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -263,9 +263,9 @@ int mr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb,
263263
lastuse = READ_ONCE(c->mfc_un.res.lastuse);
264264
lastuse = time_after_eq(jiffies, lastuse) ? jiffies - lastuse : 0;
265265

266-
mfcs.mfcs_packets = c->mfc_un.res.pkt;
267-
mfcs.mfcs_bytes = c->mfc_un.res.bytes;
268-
mfcs.mfcs_wrong_if = c->mfc_un.res.wrong_if;
266+
mfcs.mfcs_packets = atomic_long_read(&c->mfc_un.res.pkt);
267+
mfcs.mfcs_bytes = atomic_long_read(&c->mfc_un.res.bytes);
268+
mfcs.mfcs_wrong_if = atomic_long_read(&c->mfc_un.res.wrong_if);
269269
if (nla_put_64bit(skb, RTA_MFC_STATS, sizeof(mfcs), &mfcs, RTA_PAD) ||
270270
nla_put_u64_64bit(skb, RTA_EXPIRES, jiffies_to_clock_t(lastuse),
271271
RTA_PAD))

net/ipv6/addrconf.c

Lines changed: 11 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5130,22 +5130,6 @@ static inline int inet6_ifaddr_msgsize(void)
51305130
+ nla_total_size(4) /* IFA_RT_PRIORITY */;
51315131
}
51325132

5133-
enum addr_type_t {
5134-
UNICAST_ADDR,
5135-
MULTICAST_ADDR,
5136-
ANYCAST_ADDR,
5137-
};
5138-
5139-
struct inet6_fill_args {
5140-
u32 portid;
5141-
u32 seq;
5142-
int event;
5143-
unsigned int flags;
5144-
int netnsid;
5145-
int ifindex;
5146-
enum addr_type_t type;
5147-
};
5148-
51495133
static int inet6_fill_ifaddr(struct sk_buff *skb,
51505134
const struct inet6_ifaddr *ifa,
51515135
struct inet6_fill_args *args)
@@ -5224,15 +5208,16 @@ static int inet6_fill_ifaddr(struct sk_buff *skb,
52245208
return -EMSGSIZE;
52255209
}
52265210

5227-
static int inet6_fill_ifmcaddr(struct sk_buff *skb,
5228-
const struct ifmcaddr6 *ifmca,
5229-
struct inet6_fill_args *args)
5211+
int inet6_fill_ifmcaddr(struct sk_buff *skb,
5212+
const struct ifmcaddr6 *ifmca,
5213+
struct inet6_fill_args *args)
52305214
{
52315215
int ifindex = ifmca->idev->dev->ifindex;
52325216
u8 scope = RT_SCOPE_UNIVERSE;
52335217
struct nlmsghdr *nlh;
52345218

5235-
if (ipv6_addr_scope(&ifmca->mca_addr) & IFA_SITE)
5219+
if (!args->force_rt_scope_universe &&
5220+
ipv6_addr_scope(&ifmca->mca_addr) & IFA_SITE)
52365221
scope = RT_SCOPE_SITE;
52375222

52385223
nlh = nlmsg_put(skb, args->portid, args->seq, args->event,
@@ -5258,9 +5243,9 @@ static int inet6_fill_ifmcaddr(struct sk_buff *skb,
52585243
return 0;
52595244
}
52605245

5261-
static int inet6_fill_ifacaddr(struct sk_buff *skb,
5262-
const struct ifacaddr6 *ifaca,
5263-
struct inet6_fill_args *args)
5246+
int inet6_fill_ifacaddr(struct sk_buff *skb,
5247+
const struct ifacaddr6 *ifaca,
5248+
struct inet6_fill_args *args)
52645249
{
52655250
struct net_device *dev = fib6_info_nh_dev(ifaca->aca_rt);
52665251
int ifindex = dev ? dev->ifindex : 1;
@@ -5421,6 +5406,7 @@ static int inet6_dump_addr(struct sk_buff *skb, struct netlink_callback *cb,
54215406
.flags = NLM_F_MULTI,
54225407
.netnsid = -1,
54235408
.type = type,
5409+
.force_rt_scope_universe = false,
54245410
};
54255411
struct {
54265412
unsigned long ifindex;
@@ -5549,6 +5535,7 @@ static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr *nlh,
55495535
.event = RTM_NEWADDR,
55505536
.flags = 0,
55515537
.netnsid = -1,
5538+
.force_rt_scope_universe = false,
55525539
};
55535540
struct ifaddrmsg *ifm;
55545541
struct nlattr *tb[IFA_MAX+1];
@@ -5620,6 +5607,7 @@ static void inet6_ifa_notify(int event, struct inet6_ifaddr *ifa)
56205607
.event = event,
56215608
.flags = 0,
56225609
.netnsid = -1,
5610+
.force_rt_scope_universe = false,
56235611
};
56245612
int err = -ENOBUFS;
56255613

0 commit comments

Comments
 (0)