Comments
Patch
@@ -1226,6 +1226,7 @@ extern int dev_change_flags(struct net_device *, unsigned);
extern int dev_change_name(struct net_device *, char *);
extern int dev_change_net_namespace(struct net_device *,
struct net *, const char *);
+extern void dev_notify_mtu(struct net_device *);
extern int dev_set_mtu(struct net_device *, int);
extern int dev_set_mac_address(struct net_device *,
struct sockaddr *);
@@ -347,6 +347,7 @@ static int register_vlan_device(struct net_device *real_dev, u16 vlan_id)
new_dev->mtu = real_dev->mtu;
vlan_dev_info(new_dev)->vlan_id = vlan_id;
+ vlan_dev_info(new_dev)->mtu = new_dev->mtu;
vlan_dev_info(new_dev)->real_dev = real_dev;
vlan_dev_info(new_dev)->dent = NULL;
vlan_dev_info(new_dev)->flags = VLAN_FLAG_REORDER_HDR;
@@ -477,6 +478,18 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
break;
+ case NETDEV_CHANGEMTU:
+ for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
+ vlandev = vlan_group_get_device(grp, i);
+ if (!vlandev)
+ continue;
+
+ vlandev->mtu = min(vlan_dev_info(vlandev)->mtu,
+ dev->mtu);
+ dev_notify_mtu(vlandev);
+ }
+ break;
+
case NETDEV_DOWN:
/* Put all VLANs for this dev in the down state too. */
for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
@@ -24,6 +24,7 @@ struct vlan_priority_tci_mapping {
* @egress_priority_map: hash of egress priority mappings
* @vlan_id: VLAN identifier
* @flags: device flags
+ * @mtu: desired MTU - effective MTU is limited by MTU of real device
* @real_dev: underlying netdevice
* @real_dev_addr: address of underlying netdevice
* @dent: proc dir entry
@@ -38,6 +39,7 @@ struct vlan_dev_info {
u16 vlan_id;
u16 flags;
+ unsigned int mtu;
struct net_device *real_dev;
unsigned char real_dev_addr[ETH_ALEN];
@@ -347,14 +347,13 @@ static int vlan_dev_hwaccel_hard_start_xmit(struct sk_buff *skb,
static int vlan_dev_change_mtu(struct net_device *dev, int new_mtu)
{
+ struct vlan_dev_info *vlan = vlan_dev_info(dev);
+
/* TODO: gotta make sure the underlying layer can handle it,
* maybe an IFF_VLAN_CAPABLE flag for devices?
*/
- if (vlan_dev_info(dev)->real_dev->mtu < new_mtu)
- return -ERANGE;
-
- dev->mtu = new_mtu;
-
+ vlan->mtu = new_mtu;
+ dev->mtu = min_t(unsigned int, vlan->real_dev->mtu, new_mtu);
return 0;
}
@@ -125,9 +125,9 @@ static int vlan_newlink(struct net_device *dev,
return err;
if (!tb[IFLA_MTU])
- dev->mtu = real_dev->mtu;
- else if (dev->mtu > real_dev->mtu)
- return -EINVAL;
+ dev->mtu = vlan->mtu = real_dev->mtu;
+ else
+ vlan->mtu = nla_get_u32(tb[IFLA_MTU]);
err = vlan_changelink(dev, tb, data);
if (err < 0)
@@ -3399,6 +3399,13 @@ int dev_change_flags(struct net_device *dev, unsigned flags)
return ret;
}
+void dev_notify_mtu(struct net_device *dev)
+{
+ if (dev->flags & IFF_UP)
+ call_netdevice_notifiers(NETDEV_CHANGEMTU, dev);
+}
+EXPORT_SYMBOL_GPL(dev_notify_mtu);
+
int dev_set_mtu(struct net_device *dev, int new_mtu)
{
int err;
@@ -3418,8 +3425,8 @@ int dev_set_mtu(struct net_device *dev, int new_mtu)
err = dev->change_mtu(dev, new_mtu);
else
dev->mtu = new_mtu;
- if (!err && dev->flags & IFF_UP)
- call_netdevice_notifiers(NETDEV_CHANGEMTU, dev);
+ if (!err)
+ dev_notify_mtu(dev);
return err;
}