|
@@ -1278,6 +1278,7 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev,
|
|
|
struct net_device *lowerdev;
|
|
struct net_device *lowerdev;
|
|
|
int err;
|
|
int err;
|
|
|
int macmode;
|
|
int macmode;
|
|
|
|
|
+ bool create = false;
|
|
|
|
|
|
|
|
if (!tb[IFLA_LINK])
|
|
if (!tb[IFLA_LINK])
|
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
@@ -1304,12 +1305,18 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev,
|
|
|
err = macvlan_port_create(lowerdev);
|
|
err = macvlan_port_create(lowerdev);
|
|
|
if (err < 0)
|
|
if (err < 0)
|
|
|
return err;
|
|
return err;
|
|
|
|
|
+ create = true;
|
|
|
}
|
|
}
|
|
|
port = macvlan_port_get_rtnl(lowerdev);
|
|
port = macvlan_port_get_rtnl(lowerdev);
|
|
|
|
|
|
|
|
/* Only 1 macvlan device can be created in passthru mode */
|
|
/* Only 1 macvlan device can be created in passthru mode */
|
|
|
- if (port->passthru)
|
|
|
|
|
- return -EINVAL;
|
|
|
|
|
|
|
+ if (port->passthru) {
|
|
|
|
|
+ /* The macvlan port must be not created this time,
|
|
|
|
|
+ * still goto destroy_macvlan_port for readability.
|
|
|
|
|
+ */
|
|
|
|
|
+ err = -EINVAL;
|
|
|
|
|
+ goto destroy_macvlan_port;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
vlan->lowerdev = lowerdev;
|
|
vlan->lowerdev = lowerdev;
|
|
|
vlan->dev = dev;
|
|
vlan->dev = dev;
|
|
@@ -1325,24 +1332,28 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev,
|
|
|
vlan->flags = nla_get_u16(data[IFLA_MACVLAN_FLAGS]);
|
|
vlan->flags = nla_get_u16(data[IFLA_MACVLAN_FLAGS]);
|
|
|
|
|
|
|
|
if (vlan->mode == MACVLAN_MODE_PASSTHRU) {
|
|
if (vlan->mode == MACVLAN_MODE_PASSTHRU) {
|
|
|
- if (port->count)
|
|
|
|
|
- return -EINVAL;
|
|
|
|
|
|
|
+ if (port->count) {
|
|
|
|
|
+ err = -EINVAL;
|
|
|
|
|
+ goto destroy_macvlan_port;
|
|
|
|
|
+ }
|
|
|
port->passthru = true;
|
|
port->passthru = true;
|
|
|
eth_hw_addr_inherit(dev, lowerdev);
|
|
eth_hw_addr_inherit(dev, lowerdev);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (data && data[IFLA_MACVLAN_MACADDR_MODE]) {
|
|
if (data && data[IFLA_MACVLAN_MACADDR_MODE]) {
|
|
|
- if (vlan->mode != MACVLAN_MODE_SOURCE)
|
|
|
|
|
- return -EINVAL;
|
|
|
|
|
|
|
+ if (vlan->mode != MACVLAN_MODE_SOURCE) {
|
|
|
|
|
+ err = -EINVAL;
|
|
|
|
|
+ goto destroy_macvlan_port;
|
|
|
|
|
+ }
|
|
|
macmode = nla_get_u32(data[IFLA_MACVLAN_MACADDR_MODE]);
|
|
macmode = nla_get_u32(data[IFLA_MACVLAN_MACADDR_MODE]);
|
|
|
err = macvlan_changelink_sources(vlan, macmode, data);
|
|
err = macvlan_changelink_sources(vlan, macmode, data);
|
|
|
if (err)
|
|
if (err)
|
|
|
- return err;
|
|
|
|
|
|
|
+ goto destroy_macvlan_port;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
err = register_netdevice(dev);
|
|
err = register_netdevice(dev);
|
|
|
if (err < 0)
|
|
if (err < 0)
|
|
|
- return err;
|
|
|
|
|
|
|
+ goto destroy_macvlan_port;
|
|
|
|
|
|
|
|
dev->priv_flags |= IFF_MACVLAN;
|
|
dev->priv_flags |= IFF_MACVLAN;
|
|
|
err = netdev_upper_dev_link(lowerdev, dev);
|
|
err = netdev_upper_dev_link(lowerdev, dev);
|
|
@@ -1357,7 +1368,9 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev,
|
|
|
|
|
|
|
|
unregister_netdev:
|
|
unregister_netdev:
|
|
|
unregister_netdevice(dev);
|
|
unregister_netdevice(dev);
|
|
|
-
|
|
|
|
|
|
|
+destroy_macvlan_port:
|
|
|
|
|
+ if (create)
|
|
|
|
|
+ macvlan_port_destroy(port->dev);
|
|
|
return err;
|
|
return err;
|
|
|
}
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(macvlan_common_newlink);
|
|
EXPORT_SYMBOL_GPL(macvlan_common_newlink);
|