All of lore.kernel.org
 help / color / mirror / Atom feed
From: Patrick McHardy <kaber@trash.net>
To: Stephen Hemminger <shemminger@vyatta.com>,
	Rick Jones <rick.jones2@hp.com>,
	Linux Netdev List <netdev@vger.kernel.org>
Subject: VLAN MTU propagation
Date: Wed, 08 Oct 2008 14:18:48 +0200	[thread overview]
Message-ID: <48ECA528.7060301@trash.net> (raw)

[-- Attachment #1: Type: text/plain, Size: 522 bytes --]

How about this patch (still compiling, so untested)?

Its based on Rick's suggestion of using an operational and a desired
MTU. The operational MTU is simply the net_device's MTU and is always
set to the minimum of the lower device's MTU and the desired MTU.
The desired MTU can be changed by configuring a MTU for the VLAN device
manually.

The remaining question is whether we should report the desired MTU to
userspace using the netlink interface, or maybe print a message when
the MTU is limited by the lower device.


[-- Attachment #2: x --]
[-- Type: text/plain, Size: 4158 bytes --]

diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 488c56e..eac3641 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -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 *);
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index b661f47..c542807 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -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++) {
diff --git a/net/8021q/vlan.h b/net/8021q/vlan.h
index a6603a4..84f2c11 100644
--- a/net/8021q/vlan.h
+++ b/net/8021q/vlan.h
@@ -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];
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index 4bf014e..18d85c4 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -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;
 }
 
diff --git a/net/8021q/vlan_netlink.c b/net/8021q/vlan_netlink.c
index e9c91dc..d9f9b17 100644
--- a/net/8021q/vlan_netlink.c
+++ b/net/8021q/vlan_netlink.c
@@ -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)
diff --git a/net/core/dev.c b/net/core/dev.c
index fd992c0..2a2094a 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -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;
 }
 

                 reply	other threads:[~2008-10-08 12:18 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=48ECA528.7060301@trash.net \
    --to=kaber@trash.net \
    --cc=netdev@vger.kernel.org \
    --cc=rick.jones2@hp.com \
    --cc=shemminger@vyatta.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.