From patchwork Tue Apr 1 21:17:34 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vlad Yasevich X-Patchwork-Id: 336164 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 5E67F14007D for ; Wed, 2 Apr 2014 08:17:50 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751534AbaDAVRo (ORCPT ); Tue, 1 Apr 2014 17:17:44 -0400 Received: from mx1.redhat.com ([209.132.183.28]:45854 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751366AbaDAVRn (ORCPT ); Tue, 1 Apr 2014 17:17:43 -0400 Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id s31LHePC025796 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Tue, 1 Apr 2014 17:17:40 -0400 Received: from vyasevic.redhat.com (ovpn-113-172.phx2.redhat.com [10.3.113.172]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id s31LHdnp017315; Tue, 1 Apr 2014 17:17:39 -0400 From: Vlad Yasevich To: netdev@vger.kernel.org Cc: Vlad Yasevich , Patrik McHardy Subject: [RFC PATCH] vlan: Try to adjust lower device mtu when configuring 802.1AD vlans Date: Tue, 1 Apr 2014 17:17:34 -0400 Message-Id: <1396387054-4510-1-git-send-email-vyasevic@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org 802.1AD vlans supposed to encapsulate 802.1Q vlans. To do this, we need an extra 4 bytes of header which are typically not accounted for by lower devices. Some devices can not support frames longer then 1522 bytes at all. Such devices can not really support 802.1AD, even in software, without the vlan reducing its mtu value. This patch propses to increate the lower devices MTU to 1504 in case of 802.1AD configuration, and if device doesn't support it, fail the creation of the vlan. The user has an option to configure older-style Q-in-Q vlans and manually lower the mtu to support such encapsulation. CC: Patrik McHardy Signed-off-by: Vlad Yasevich --- net/8021q/vlan.c | 17 +++++++++++++++++ net/8021q/vlan_netlink.c | 11 ++++++++--- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index 175273f..0328d73 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c @@ -126,6 +126,7 @@ int vlan_check_real_dev(struct net_device *real_dev, __be16 protocol, u16 vlan_id) { const char *name = real_dev->name; + int err; if (real_dev->features & NETIF_F_VLAN_CHALLENGED) { pr_info("VLANs not supported on %s\n", name); @@ -135,6 +136,21 @@ int vlan_check_real_dev(struct net_device *real_dev, if (vlan_find_dev(real_dev, protocol, vlan_id) != NULL) return -EEXIST; + if (protocol == htons(ETH_P_8021AD)) { + /* 8021AD vlan is meant to encapsulate 8021Q and thus we + * need to make sure that lower device can handle a + * larger mtu. + * If the lower device still has a default ethernet mtu, + * bump it up 4 bytes. If not, it was set by user and + * we'll trust the user knows what he is doing. + */ + if (real_dev->mtu == VLAN_ETH_DATA_LEN && + dev_set_mtu(real_dev, real_dev->mtu + VLAN_HLEN)) + pr_warn("802.1AD mode is not supported on %s due to mtu limitations.\n", name); + return -EOPNOTSUPP + } + } + return 0; } @@ -259,6 +275,7 @@ static int register_vlan_device(struct net_device *real_dev, u16 vlan_id) * hope the underlying device can handle it. */ new_dev->mtu = real_dev->mtu; + new_dev->priv_flags |= (real_dev->priv_flags & IFF_UNICAST_FLT); vlan = vlan_dev_priv(new_dev); diff --git a/net/8021q/vlan_netlink.c b/net/8021q/vlan_netlink.c index c7e634a..a925a8d 100644 --- a/net/8021q/vlan_netlink.c +++ b/net/8021q/vlan_netlink.c @@ -144,10 +144,15 @@ static int vlan_newlink(struct net *src_net, struct net_device *dev, if (err < 0) return err; - if (!tb[IFLA_MTU]) - dev->mtu = real_dev->mtu; - else if (dev->mtu > real_dev->mtu) + if (!tb[IFLA_MTU]) { + if (vlan->vlan_proto == htons(ETH_P_8021AD) && + real_dev->mtu == VLAN_ETH_DATA_LEN + VLAN_HLEN) + dev->mtu = VLAN_ETH_DATA_LEN; + else + dev->mtu = real_dev->mtu; + } else if (dev->mtu > real_dev->mtu) { return -EINVAL; + } err = vlan_changelink(dev, tb, data); if (err < 0)