Commit 18d3df3e authored by Paolo Abeni's avatar Paolo Abeni Committed by David S. Miller

vlan: use a valid default mtu value for vlan over macsec

macsec can't cope with mtu frames which need vlan tag insertion, and
vlan device set the default mtu equal to the underlying dev's one.
By default vlan over macsec devices use invalid mtu, dropping
all the large packets.
This patch adds a netif helper to check if an upper vlan device
needs mtu reduction. The helper is used during vlan devices
initialization to set a valid default and during mtu updating to
forbid invalid, too bit, mtu values.
The helper currently only check if the lower dev is a macsec device,
if we get more users, we need to update only the helper (possibly
reserving an additional IFF bit).
Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent e86663c4
...@@ -4145,6 +4145,13 @@ static inline void netif_keep_dst(struct net_device *dev) ...@@ -4145,6 +4145,13 @@ static inline void netif_keep_dst(struct net_device *dev)
dev->priv_flags &= ~(IFF_XMIT_DST_RELEASE | IFF_XMIT_DST_RELEASE_PERM); dev->priv_flags &= ~(IFF_XMIT_DST_RELEASE | IFF_XMIT_DST_RELEASE_PERM);
} }
/* return true if dev can't cope with mtu frames that need vlan tag insertion */
static inline bool netif_reduces_vlan_mtu(struct net_device *dev)
{
/* TODO: reserve and use an additional IFF bit, if we get more users */
return dev->priv_flags & IFF_MACSEC;
}
extern struct pernet_operations __net_initdata loopback_net_ops; extern struct pernet_operations __net_initdata loopback_net_ops;
/* Logging, debugging and troubleshooting/diagnostic helpers. */ /* Logging, debugging and troubleshooting/diagnostic helpers. */
......
...@@ -146,10 +146,12 @@ static netdev_tx_t vlan_dev_hard_start_xmit(struct sk_buff *skb, ...@@ -146,10 +146,12 @@ static netdev_tx_t vlan_dev_hard_start_xmit(struct sk_buff *skb,
static int vlan_dev_change_mtu(struct net_device *dev, int new_mtu) static int vlan_dev_change_mtu(struct net_device *dev, int new_mtu)
{ {
/* TODO: gotta make sure the underlying layer can handle it, struct net_device *real_dev = vlan_dev_priv(dev)->real_dev;
* maybe an IFF_VLAN_CAPABLE flag for devices? unsigned int max_mtu = real_dev->mtu;
*/
if (vlan_dev_priv(dev)->real_dev->mtu < new_mtu) if (netif_reduces_vlan_mtu(real_dev))
max_mtu -= VLAN_HLEN;
if (max_mtu < new_mtu)
return -ERANGE; return -ERANGE;
dev->mtu = new_mtu; dev->mtu = new_mtu;
......
...@@ -118,6 +118,7 @@ static int vlan_newlink(struct net *src_net, struct net_device *dev, ...@@ -118,6 +118,7 @@ static int vlan_newlink(struct net *src_net, struct net_device *dev,
{ {
struct vlan_dev_priv *vlan = vlan_dev_priv(dev); struct vlan_dev_priv *vlan = vlan_dev_priv(dev);
struct net_device *real_dev; struct net_device *real_dev;
unsigned int max_mtu;
__be16 proto; __be16 proto;
int err; int err;
...@@ -144,9 +145,11 @@ static int vlan_newlink(struct net *src_net, struct net_device *dev, ...@@ -144,9 +145,11 @@ static int vlan_newlink(struct net *src_net, struct net_device *dev,
if (err < 0) if (err < 0)
return err; return err;
max_mtu = netif_reduces_vlan_mtu(real_dev) ? real_dev->mtu - VLAN_HLEN :
real_dev->mtu;
if (!tb[IFLA_MTU]) if (!tb[IFLA_MTU])
dev->mtu = real_dev->mtu; dev->mtu = max_mtu;
else if (dev->mtu > real_dev->mtu) else if (dev->mtu > max_mtu)
return -EINVAL; return -EINVAL;
err = vlan_changelink(dev, tb, data); err = vlan_changelink(dev, tb, data);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment