@@ -995,6 +995,8 @@ typedef u16 (*select_queue_fallback_t)(struct net_device *dev,
* Callback to use for xmit over the accelerated station. This
* is used in place of ndo_start_xmit on accelerated net
* devices.
+ * void (*ndo_tunnel_rename)(struct net_device *dev)
+ * Callback to use for renaming tunnel when rename net_device.
*/
struct net_device_ops {
int (*ndo_init)(struct net_device *dev);
@@ -1141,6 +1143,7 @@ struct net_device_ops {
netdev_tx_t (*ndo_dfwd_start_xmit) (struct sk_buff *skb,
struct net_device *dev,
void *priv);
+ void (*ndo_tunnel_rename) (struct net_device *dev);
};
/**
@@ -69,6 +69,7 @@ int ip6_tnl_xmit_ctl(struct ip6_tnl *t);
__u16 ip6_tnl_parse_tlv_enc_lim(struct sk_buff *skb, __u8 *raw);
__u32 ip6_tnl_get_cap(struct ip6_tnl *t, const struct in6_addr *laddr,
const struct in6_addr *raddr);
+void ip6_tunnel_rename(struct net_device *dev);
static inline void ip6tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
{
@@ -113,6 +113,7 @@ void ip_tunnel_delete_net(struct ip_tunnel_net *itn, struct rtnl_link_ops *ops);
void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
const struct iphdr *tnl_params, const u8 protocol);
int ip_tunnel_ioctl(struct net_device *dev, struct ip_tunnel_parm *p, int cmd);
+void ip_tunnel_rename(struct net_device *dev);
int ip_tunnel_change_mtu(struct net_device *dev, int new_mtu);
struct rtnl_link_stats64 *ip_tunnel_get_stats64(struct net_device *dev,
@@ -1086,6 +1086,7 @@ int dev_change_name(struct net_device *dev, const char *newname)
int err = 0;
int ret;
struct net *net;
+ struct net_device_ops *ops = dev->netdev_ops;
ASSERT_RTNL();
BUG_ON(!dev_net(dev));
@@ -1148,6 +1149,9 @@ rollback:
}
}
+ if (ops->ndo_tunnel_rename)
+ ops->ndo_tunnel_rename(dev);
+
return err;
}
@@ -453,6 +453,7 @@ static const struct net_device_ops ipgre_netdev_ops = {
.ndo_do_ioctl = ipgre_tunnel_ioctl,
.ndo_change_mtu = ip_tunnel_change_mtu,
.ndo_get_stats64 = ip_tunnel_get_stats64,
+ .ndo_tunnel_rename = ip_tunnel_rename,
};
#define GRE_FEATURES (NETIF_F_SG | \
@@ -643,6 +644,7 @@ static const struct net_device_ops gre_tap_netdev_ops = {
.ndo_validate_addr = eth_validate_addr,
.ndo_change_mtu = ip_tunnel_change_mtu,
.ndo_get_stats64 = ip_tunnel_get_stats64,
+ .ndo_tunnel_rename = ip_tunnel_rename,
};
static void ipgre_tap_setup(struct net_device *dev)
@@ -818,6 +818,14 @@ done:
}
EXPORT_SYMBOL_GPL(ip_tunnel_ioctl);
+void ip_tunnel_rename(struct net_device *dev)
+{
+ struct ip_tunnel *tunnel = netdev_priv(dev);
+
+ strcpy(tunnel->parms.name, dev->name);
+}
+EXPORT_SYMBOL_GPL(ip_tunnel_rename);
+
int ip_tunnel_change_mtu(struct net_device *dev, int new_mtu)
{
struct ip_tunnel *tunnel = netdev_priv(dev);
@@ -332,6 +332,7 @@ static const struct net_device_ops vti_netdev_ops = {
.ndo_do_ioctl = vti_tunnel_ioctl,
.ndo_change_mtu = ip_tunnel_change_mtu,
.ndo_get_stats64 = ip_tunnel_get_stats64,
+ .ndo_tunnel_rename = ip_tunnel_rename,
};
static void vti_tunnel_setup(struct net_device *dev)
@@ -270,6 +270,7 @@ static const struct net_device_ops ipip_netdev_ops = {
.ndo_do_ioctl = ipip_tunnel_ioctl,
.ndo_change_mtu = ip_tunnel_change_mtu,
.ndo_get_stats64 = ip_tunnel_get_stats64,
+ .ndo_tunnel_rename = ip_tunnel_rename,
};
#define IPIP_FEATURES (NETIF_F_SG | \
@@ -1208,6 +1208,7 @@ static const struct net_device_ops ip6gre_netdev_ops = {
.ndo_do_ioctl = ip6gre_tunnel_ioctl,
.ndo_change_mtu = ip6gre_tunnel_change_mtu,
.ndo_get_stats64 = ip_tunnel_get_stats64,
+ .ndo_tunnel_rename = ip6_tunnel_rename,
};
static void ip6gre_dev_free(struct net_device *dev)
@@ -1481,6 +1482,7 @@ static const struct net_device_ops ip6gre_tap_netdev_ops = {
.ndo_validate_addr = eth_validate_addr,
.ndo_change_mtu = ip6gre_tunnel_change_mtu,
.ndo_get_stats64 = ip_tunnel_get_stats64,
+ .ndo_tunnel_rename = ip6_tunnel_rename,
};
static void ip6gre_tap_setup(struct net_device *dev)
@@ -1453,6 +1453,13 @@ ip6_tnl_change_mtu(struct net_device *dev, int new_mtu)
return 0;
}
+void ip6_tunnel_rename(struct net_device *dev)
+{
+ struct ip6_tnl *tnl = netdev_priv(dev);
+
+ strcpy(tnl->parms.name, dev->name);
+}
+EXPORT_SYMBOL_GPL(ip6_tunnel_rename);
static const struct net_device_ops ip6_tnl_netdev_ops = {
.ndo_uninit = ip6_tnl_dev_uninit,
@@ -1460,6 +1467,7 @@ static const struct net_device_ops ip6_tnl_netdev_ops = {
.ndo_do_ioctl = ip6_tnl_ioctl,
.ndo_change_mtu = ip6_tnl_change_mtu,
.ndo_get_stats = ip6_get_stats,
+ .ndo_tunnel_rename = ip6_tunnel_rename,
};
@@ -781,6 +781,7 @@ static const struct net_device_ops vti6_netdev_ops = {
.ndo_do_ioctl = vti6_ioctl,
.ndo_change_mtu = vti6_change_mtu,
.ndo_get_stats64 = ip_tunnel_get_stats64,
+ .ndo_tunnel_rename = ip6_tunnel_rename,
};
/**
@@ -1318,6 +1318,7 @@ static const struct net_device_ops ipip6_netdev_ops = {
.ndo_do_ioctl = ipip6_tunnel_ioctl,
.ndo_change_mtu = ipip6_tunnel_change_mtu,
.ndo_get_stats64 = ip_tunnel_get_stats64,
+ .ndo_tunnel_rename = ip6_tunnel_rename,
};
static void ipip6_dev_free(struct net_device *dev)
After executing command "ip tunnel add before local 192.168.0.19 mode gre", the tunnel "before" and the link "before" are created. Now if user executes command "ip link set dev before name after", the tunnel's name is still "before", but the link's name is "after". At last, user executes command "ip tunnel del before", and error "No such device" will arise. ip-tunnel uses ioctl to handle command. It firstly gets link through tunnel name, but because link has a different name with tunnel, so the error "No such device" arised. In order to handle this situation, tunnel's name should be modified when changing link's name. Signed-off-by: Duan Jiong <duanj.fnst@cn.fujitsu.com> --- include/linux/netdevice.h | 3 +++ include/net/ip6_tunnel.h | 1 + include/net/ip_tunnels.h | 1 + net/core/dev.c | 4 ++++ net/ipv4/ip_gre.c | 2 ++ net/ipv4/ip_tunnel.c | 8 ++++++++ net/ipv4/ip_vti.c | 1 + net/ipv4/ipip.c | 1 + net/ipv6/ip6_gre.c | 2 ++ net/ipv6/ip6_tunnel.c | 8 ++++++++ net/ipv6/ip6_vti.c | 1 + net/ipv6/sit.c | 1 + 12 files changed, 33 insertions(+)