Skip to content

Commit f6cc9c0

Browse files
pmachatadavem330
authored andcommitted
ip_tunnel: Emit events for post-register MTU changes
For tunnels created with IFLA_MTU, MTU of the netdevice is set by rtnl_create_link() (called from rtnl_newlink()) before the device is registered. However without IFLA_MTU that's not done. rtnl_newlink() proceeds by calling struct rtnl_link_ops.newlink, which via ip_tunnel_newlink() calls register_netdevice(), and that emits NETDEV_REGISTER. Thus any listeners that inspect the netdevice get the MTU of 0. After ip_tunnel_newlink() corrects the MTU after registering the netdevice, but since there's no event, the listeners don't get to know about the MTU until something else happens--such as a NETDEV_UP event. That's not ideal. So instead of setting the MTU directly, go through dev_set_mtu(), which takes care of distributing the necessary NETDEV_PRECHANGEMTU and NETDEV_CHANGEMTU events. Fixes: 1da177e ("Linux-2.6.12-rc2") Signed-off-by: Petr Machata <[email protected]> Signed-off-by: Ido Schimmel <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent f36b753 commit f6cc9c0

File tree

1 file changed

+21
-5
lines changed

1 file changed

+21
-5
lines changed

net/ipv4/ip_tunnel.c

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -362,20 +362,29 @@ static struct ip_tunnel *ip_tunnel_create(struct net *net,
362362
struct ip_tunnel *nt;
363363
struct net_device *dev;
364364
int t_hlen;
365+
int mtu;
366+
int err;
365367

366368
BUG_ON(!itn->fb_tunnel_dev);
367369
dev = __ip_tunnel_create(net, itn->fb_tunnel_dev->rtnl_link_ops, parms);
368370
if (IS_ERR(dev))
369371
return ERR_CAST(dev);
370372

371-
dev->mtu = ip_tunnel_bind_dev(dev);
373+
mtu = ip_tunnel_bind_dev(dev);
374+
err = dev_set_mtu(dev, mtu);
375+
if (err)
376+
goto err_dev_set_mtu;
372377

373378
nt = netdev_priv(dev);
374379
t_hlen = nt->hlen + sizeof(struct iphdr);
375380
dev->min_mtu = ETH_MIN_MTU;
376381
dev->max_mtu = 0xFFF8 - dev->hard_header_len - t_hlen;
377382
ip_tunnel_add(itn, nt);
378383
return nt;
384+
385+
err_dev_set_mtu:
386+
unregister_netdevice(dev);
387+
return ERR_PTR(err);
379388
}
380389

381390
int ip_tunnel_rcv(struct ip_tunnel *tunnel, struct sk_buff *skb,
@@ -1102,17 +1111,24 @@ int ip_tunnel_newlink(struct net_device *dev, struct nlattr *tb[],
11021111
nt->fwmark = fwmark;
11031112
err = register_netdevice(dev);
11041113
if (err)
1105-
goto out;
1114+
goto err_register_netdevice;
11061115

11071116
if (dev->type == ARPHRD_ETHER && !tb[IFLA_ADDRESS])
11081117
eth_hw_addr_random(dev);
11091118

11101119
mtu = ip_tunnel_bind_dev(dev);
1111-
if (!tb[IFLA_MTU])
1112-
dev->mtu = mtu;
1120+
if (!tb[IFLA_MTU]) {
1121+
err = dev_set_mtu(dev, mtu);
1122+
if (err)
1123+
goto err_dev_set_mtu;
1124+
}
11131125

11141126
ip_tunnel_add(itn, nt);
1115-
out:
1127+
return 0;
1128+
1129+
err_dev_set_mtu:
1130+
unregister_netdevice(dev);
1131+
err_register_netdevice:
11161132
return err;
11171133
}
11181134
EXPORT_SYMBOL_GPL(ip_tunnel_newlink);

0 commit comments

Comments
 (0)