Skip to content

Commit e8368d9

Browse files
committed
Merge branch 'net-Ease-to-follow-an-interface-that-moves-to-another-netns'
Nicolas Dichtel says: ==================== net: Ease to follow an interface that moves to another netns The goal of this series is to ease the user to follow an interface that moves to another netns. After this series, with a patched iproute2: $ ip netns bar foo $ ip monitor link & $ ip link set dummy0 netns foo Deleted 5: dummy0: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN group default link/ether 6e:a7:82:35:96:46 brd ff:ff:ff:ff:ff:ff new-nsid 0 new-ifindex 6 => new nsid: 0, new ifindex: 6 (was 5 in the previous netns) $ ip link set eth1 netns bar Deleted 3: eth1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default link/ether 52:54:01:12:34:57 brd ff:ff:ff:ff:ff:ff new-nsid 1 new-ifindex 3 => new nsid: 1, new ifindex: 3 (same ifindex) $ ip netns bar (id: 1) foo (id: 0) ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 6b9e654 + 38e01b3 commit e8368d9

File tree

4 files changed

+36
-23
lines changed

4 files changed

+36
-23
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 & 10 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,11 +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-
if (dev->rtnl_link_ops && dev->rtnl_link_ops->get_link_net)
8533-
new_nsid = peernet2id_alloc(dev_net(dev), net);
8532+
8533+
new_nsid = peernet2id_alloc(dev_net(dev), net);
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);
85348537
else
8535-
new_nsid = peernet2id(dev_net(dev), net);
8536-
rtmsg_ifinfo_newnet(RTM_DELLINK, dev, ~0U, GFP_KERNEL, &new_nsid);
8538+
new_ifindex = dev->ifindex;
8539+
8540+
rtmsg_ifinfo_newnet(RTM_DELLINK, dev, ~0U, GFP_KERNEL, &new_nsid,
8541+
new_ifindex);
85378542

85388543
/*
85398544
* Flush the unicast and multicast chains
@@ -8547,10 +8552,7 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char
85478552

85488553
/* Actually switch the network namespace */
85498554
dev_net_set(dev, net);
8550-
8551-
/* If there is an ifindex conflict assign a new one */
8552-
if (__dev_get_by_index(net, dev->ifindex))
8553-
dev->ifindex = dev_new_index(net);
8555+
dev->ifindex = new_ifindex;
85548556

85558557
/* Send a netdev-add uevent to the new namespace */
85568558
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)