Skip to content

Commit 38e01b3

Browse files
NicolasDichteldavem330
authored andcommitted
dev: advertise the new ifindex when the netns iface changes
The goal is to let the user follow an interface that moves to another netns. CC: Jiri Benc <[email protected]> CC: Christian Brauner <[email protected]> Signed-off-by: Nicolas Dichtel <[email protected]> Reviewed-by: Jiri Benc <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent c36ac8e commit 38e01b3

File tree

4 files changed

+36
-20
lines changed

4 files changed

+36
-20
lines changed

include/linux/rtnetlink.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,11 @@ extern int rtnl_put_cacheinfo(struct sk_buff *skb, struct dst_entry *dst,
1919

2020
void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change, gfp_t flags);
2121
void rtmsg_ifinfo_newnet(int type, struct net_device *dev, unsigned int change,
22-
gfp_t flags, int *new_nsid);
22+
gfp_t flags, int *new_nsid, int new_ifindex);
2323
struct sk_buff *rtmsg_ifinfo_build_skb(int type, struct net_device *dev,
2424
unsigned change, u32 event,
25-
gfp_t flags, int *new_nsid);
25+
gfp_t flags, int *new_nsid,
26+
int new_ifindex);
2627
void rtmsg_ifinfo_send(struct sk_buff *skb, struct net_device *dev,
2728
gfp_t flags);
2829

include/uapi/linux/if_link.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ enum {
163163
IFLA_IF_NETNSID,
164164
IFLA_CARRIER_UP_COUNT,
165165
IFLA_CARRIER_DOWN_COUNT,
166+
IFLA_NEW_IFINDEX,
166167
__IFLA_MAX
167168
};
168169

net/core/dev.c

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7360,7 +7360,7 @@ static void rollback_registered_many(struct list_head *head)
73607360
if (!dev->rtnl_link_ops ||
73617361
dev->rtnl_link_state == RTNL_LINK_INITIALIZED)
73627362
skb = rtmsg_ifinfo_build_skb(RTM_DELLINK, dev, ~0U, 0,
7363-
GFP_KERNEL, NULL);
7363+
GFP_KERNEL, NULL, 0);
73647364

73657365
/*
73667366
* Flush the unicast and multicast chains
@@ -8473,7 +8473,7 @@ EXPORT_SYMBOL(unregister_netdev);
84738473

84748474
int dev_change_net_namespace(struct net_device *dev, struct net *net, const char *pat)
84758475
{
8476-
int err, new_nsid;
8476+
int err, new_nsid, new_ifindex;
84778477

84788478
ASSERT_RTNL();
84798479

@@ -8529,8 +8529,16 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char
85298529
call_netdevice_notifiers(NETDEV_UNREGISTER, dev);
85308530
rcu_barrier();
85318531
call_netdevice_notifiers(NETDEV_UNREGISTER_FINAL, dev);
8532+
85328533
new_nsid = peernet2id_alloc(dev_net(dev), net);
8533-
rtmsg_ifinfo_newnet(RTM_DELLINK, dev, ~0U, GFP_KERNEL, &new_nsid);
8534+
/* If there is an ifindex conflict assign a new one */
8535+
if (__dev_get_by_index(net, dev->ifindex))
8536+
new_ifindex = dev_new_index(net);
8537+
else
8538+
new_ifindex = dev->ifindex;
8539+
8540+
rtmsg_ifinfo_newnet(RTM_DELLINK, dev, ~0U, GFP_KERNEL, &new_nsid,
8541+
new_ifindex);
85348542

85358543
/*
85368544
* Flush the unicast and multicast chains
@@ -8544,10 +8552,7 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char
85448552

85458553
/* Actually switch the network namespace */
85468554
dev_net_set(dev, net);
8547-
8548-
/* If there is an ifindex conflict assign a new one */
8549-
if (__dev_get_by_index(net, dev->ifindex))
8550-
dev->ifindex = dev_new_index(net);
8555+
dev->ifindex = new_ifindex;
85518556

85528557
/* Send a netdev-add uevent to the new namespace */
85538558
kobject_uevent(&dev->dev.kobj, KOBJ_ADD);

net/core/rtnetlink.c

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -988,6 +988,7 @@ static noinline size_t if_nlmsg_size(const struct net_device *dev,
988988
+ rtnl_xdp_size() /* IFLA_XDP */
989989
+ nla_total_size(4) /* IFLA_EVENT */
990990
+ nla_total_size(4) /* IFLA_NEW_NETNSID */
991+
+ nla_total_size(4) /* IFLA_NEW_IFINDEX */
991992
+ nla_total_size(1) /* IFLA_PROTO_DOWN */
992993
+ nla_total_size(4) /* IFLA_IF_NETNSID */
993994
+ nla_total_size(4) /* IFLA_CARRIER_UP_COUNT */
@@ -1511,7 +1512,8 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb,
15111512
struct net_device *dev, struct net *src_net,
15121513
int type, u32 pid, u32 seq, u32 change,
15131514
unsigned int flags, u32 ext_filter_mask,
1514-
u32 event, int *new_nsid, int tgt_netnsid)
1515+
u32 event, int *new_nsid, int new_ifindex,
1516+
int tgt_netnsid)
15151517
{
15161518
struct ifinfomsg *ifm;
15171519
struct nlmsghdr *nlh;
@@ -1608,6 +1610,10 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb,
16081610
if (new_nsid &&
16091611
nla_put_s32(skb, IFLA_NEW_NETNSID, *new_nsid) < 0)
16101612
goto nla_put_failure;
1613+
if (new_ifindex &&
1614+
nla_put_s32(skb, IFLA_NEW_IFINDEX, new_ifindex) < 0)
1615+
goto nla_put_failure;
1616+
16111617

16121618
rcu_read_lock();
16131619
if (rtnl_fill_link_af(skb, dev, ext_filter_mask))
@@ -1853,7 +1859,7 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
18531859
NETLINK_CB(cb->skb).portid,
18541860
cb->nlh->nlmsg_seq, 0,
18551861
flags,
1856-
ext_filter_mask, 0, NULL,
1862+
ext_filter_mask, 0, NULL, 0,
18571863
netnsid);
18581864

18591865
if (err < 0) {
@@ -3088,7 +3094,7 @@ static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr *nlh,
30883094
err = rtnl_fill_ifinfo(nskb, dev, net,
30893095
RTM_NEWLINK, NETLINK_CB(skb).portid,
30903096
nlh->nlmsg_seq, 0, 0, ext_filter_mask,
3091-
0, NULL, netnsid);
3097+
0, NULL, 0, netnsid);
30923098
if (err < 0) {
30933099
/* -EMSGSIZE implies BUG in if_nlmsg_size */
30943100
WARN_ON(err == -EMSGSIZE);
@@ -3184,7 +3190,8 @@ static int rtnl_dump_all(struct sk_buff *skb, struct netlink_callback *cb)
31843190

31853191
struct sk_buff *rtmsg_ifinfo_build_skb(int type, struct net_device *dev,
31863192
unsigned int change,
3187-
u32 event, gfp_t flags, int *new_nsid)
3193+
u32 event, gfp_t flags, int *new_nsid,
3194+
int new_ifindex)
31883195
{
31893196
struct net *net = dev_net(dev);
31903197
struct sk_buff *skb;
@@ -3197,7 +3204,7 @@ struct sk_buff *rtmsg_ifinfo_build_skb(int type, struct net_device *dev,
31973204

31983205
err = rtnl_fill_ifinfo(skb, dev, dev_net(dev),
31993206
type, 0, 0, change, 0, 0, event,
3200-
new_nsid, -1);
3207+
new_nsid, new_ifindex, -1);
32013208
if (err < 0) {
32023209
/* -EMSGSIZE implies BUG in if_nlmsg_size() */
32033210
WARN_ON(err == -EMSGSIZE);
@@ -3220,29 +3227,31 @@ void rtmsg_ifinfo_send(struct sk_buff *skb, struct net_device *dev, gfp_t flags)
32203227

32213228
static void rtmsg_ifinfo_event(int type, struct net_device *dev,
32223229
unsigned int change, u32 event,
3223-
gfp_t flags, int *new_nsid)
3230+
gfp_t flags, int *new_nsid, int new_ifindex)
32243231
{
32253232
struct sk_buff *skb;
32263233

32273234
if (dev->reg_state != NETREG_REGISTERED)
32283235
return;
32293236

3230-
skb = rtmsg_ifinfo_build_skb(type, dev, change, event, flags, new_nsid);
3237+
skb = rtmsg_ifinfo_build_skb(type, dev, change, event, flags, new_nsid,
3238+
new_ifindex);
32313239
if (skb)
32323240
rtmsg_ifinfo_send(skb, dev, flags);
32333241
}
32343242

32353243
void rtmsg_ifinfo(int type, struct net_device *dev, unsigned int change,
32363244
gfp_t flags)
32373245
{
3238-
rtmsg_ifinfo_event(type, dev, change, rtnl_get_event(0), flags, NULL);
3246+
rtmsg_ifinfo_event(type, dev, change, rtnl_get_event(0), flags,
3247+
NULL, 0);
32393248
}
32403249

32413250
void rtmsg_ifinfo_newnet(int type, struct net_device *dev, unsigned int change,
3242-
gfp_t flags, int *new_nsid)
3251+
gfp_t flags, int *new_nsid, int new_ifindex)
32433252
{
32443253
rtmsg_ifinfo_event(type, dev, change, rtnl_get_event(0), flags,
3245-
new_nsid);
3254+
new_nsid, new_ifindex);
32463255
}
32473256

32483257
static int nlmsg_populate_fdb_fill(struct sk_buff *skb,
@@ -4642,7 +4651,7 @@ static int rtnetlink_event(struct notifier_block *this, unsigned long event, voi
46424651
case NETDEV_CHANGELOWERSTATE:
46434652
case NETDEV_CHANGE_TX_QUEUE_LEN:
46444653
rtmsg_ifinfo_event(RTM_NEWLINK, dev, 0, rtnl_get_event(event),
4645-
GFP_KERNEL, NULL);
4654+
GFP_KERNEL, NULL, 0);
46464655
break;
46474656
default:
46484657
break;

0 commit comments

Comments
 (0)