The (inner) MTU of a ipip6 (IPv4-in-IPv6) tunnel cannot be set below 1280, which is the minimum MTU in IPv6.
However, there should be no IPv6 on the tunnel interface at all, so the IPv6 rules should not apply.
More info at https://bugzilla.kernel.org/show_bug.cgi?id=15530
This patch allows to check the minimum MTU for ipv6 tunnel according to these rules:
-In case the tunnel is configured with ipip6 mode the minimum MTU is 68.
-In case the tunnel is configured with ip6ip6 or any mode the minimum MTU is 1280.
Signed-off-by: Oussama Ghorbel <[email protected]>
---
net/ipv6/ip6_tunnel.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index 1e55866..a66ead2 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -1423,8 +1423,14 @@ ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
static int
ip6_tnl_change_mtu(struct net_device *dev, int new_mtu)
{
- if (new_mtu < IPV6_MIN_MTU) {
- return -EINVAL;
+ struct ip6_tnl *t = netdev_priv(dev);
+
+ if (t->parms.proto == IPPROTO_IPIP) {
+ if (new_mtu < 68)
+ return -EINVAL;
+ } else {
+ if (new_mtu < IPV6_MIN_MTU)
+ return -EINVAL;
}
dev->mtu = new_mtu;
return 0;
--
1.7.9.5
On Thu, Sep 26, 2013 at 03:51:48PM +0100, Oussama Ghorbel wrote:
> The (inner) MTU of a ipip6 (IPv4-in-IPv6) tunnel cannot be set below 1280, which is the minimum MTU in IPv6.
> However, there should be no IPv6 on the tunnel interface at all, so the IPv6 rules should not apply.
> More info at https://bugzilla.kernel.org/show_bug.cgi?id=15530
>
> This patch allows to check the minimum MTU for ipv6 tunnel according to these rules:
> -In case the tunnel is configured with ipip6 mode the minimum MTU is 68.
> -In case the tunnel is configured with ip6ip6 or any mode the minimum MTU is 1280.
>
> Signed-off-by: Oussama Ghorbel <[email protected]>
> ---
> net/ipv6/ip6_tunnel.c | 10 ++++++++--
> 1 file changed, 8 insertions(+), 2 deletions(-)
>
> diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
> index 1e55866..a66ead2 100644
> --- a/net/ipv6/ip6_tunnel.c
> +++ b/net/ipv6/ip6_tunnel.c
> @@ -1423,8 +1423,14 @@ ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
> static int
> ip6_tnl_change_mtu(struct net_device *dev, int new_mtu)
> {
> - if (new_mtu < IPV6_MIN_MTU) {
> - return -EINVAL;
> + struct ip6_tnl *t = netdev_priv(dev);
> +
> + if (t->parms.proto == IPPROTO_IPIP) {
> + if (new_mtu < 68)
> + return -EINVAL;
Maybe you could have a look at ip_tunnel_change_mtu in ipv4/ip_tunnel.c,
generalize this check as e.g. ip_tunnel_valid_mtu or something and use it
here? Maybe an af-independent ip_tunnel_max_mtu()?
> + } else {
> + if (new_mtu < IPV6_MIN_MTU)
> + return -EINVAL;
This check could also be used here, then.
> }
> dev->mtu = new_mtu;
> return 0;
Thanks,
Hannes
The ip6_tunnel.c module would be then dependent on ip_tunnel.c and may
be it would not be good thing?
As I have check in v3.10 there is no call from ip6_tunnel to ip_tunnel...
For information, there is no check for the maximum MTU for ipv4 in the
patch as this is not done for ipv6.
Regards,
Oussama
On Fri, Sep 27, 2013 at 9:37 AM, Hannes Frederic Sowa
<[email protected]> wrote:
> On Thu, Sep 26, 2013 at 03:51:48PM +0100, Oussama Ghorbel wrote:
>> The (inner) MTU of a ipip6 (IPv4-in-IPv6) tunnel cannot be set below 1280, which is the minimum MTU in IPv6.
>> However, there should be no IPv6 on the tunnel interface at all, so the IPv6 rules should not apply.
>> More info at https://bugzilla.kernel.org/show_bug.cgi?id=15530
>>
>> This patch allows to check the minimum MTU for ipv6 tunnel according to these rules:
>> -In case the tunnel is configured with ipip6 mode the minimum MTU is 68.
>> -In case the tunnel is configured with ip6ip6 or any mode the minimum MTU is 1280.
>>
>> Signed-off-by: Oussama Ghorbel <[email protected]>
>> ---
>> net/ipv6/ip6_tunnel.c | 10 ++++++++--
>> 1 file changed, 8 insertions(+), 2 deletions(-)
>>
>> diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
>> index 1e55866..a66ead2 100644
>> --- a/net/ipv6/ip6_tunnel.c
>> +++ b/net/ipv6/ip6_tunnel.c
>> @@ -1423,8 +1423,14 @@ ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
>> static int
>> ip6_tnl_change_mtu(struct net_device *dev, int new_mtu)
>> {
>> - if (new_mtu < IPV6_MIN_MTU) {
>> - return -EINVAL;
>> + struct ip6_tnl *t = netdev_priv(dev);
>> +
>> + if (t->parms.proto == IPPROTO_IPIP) {
>> + if (new_mtu < 68)
>> + return -EINVAL;
>
> Maybe you could have a look at ip_tunnel_change_mtu in ipv4/ip_tunnel.c,
> generalize this check as e.g. ip_tunnel_valid_mtu or something and use it
> here? Maybe an af-independent ip_tunnel_max_mtu()?
>
>> + } else {
>> + if (new_mtu < IPV6_MIN_MTU)
>> + return -EINVAL;
>
> This check could also be used here, then.
>
>> }
>> dev->mtu = new_mtu;
>> return 0;
>
> Thanks,
>
> Hannes
>
On Fri, Sep 27, 2013 at 11:45:48AM +0100, Oussama Ghorbel wrote:
> The ip6_tunnel.c module would be then dependent on ip_tunnel.c and may
> be it would not be good thing?
It could just be a static inline in some shared header. So there would
be no compile-time dependency.
> As I have check in v3.10 there is no call from ip6_tunnel to ip_tunnel...
>
> For information, there is no check for the maximum MTU for ipv4 in the
> patch as this is not done for ipv6.
I understand, but it would be better to limit the MTU here. There is a
(non-jumo) IPV6_MAXPLEN constant.
Looking through the source it seems grev6 does actually check this,
so it would not hurt adding them here, too.
Otherwise, I think your patch is fine.
Greetings,
Hannes
Please see my comments below
Regards,
Oussama
On Fri, Sep 27, 2013 at 11:58 AM, Hannes Frederic Sowa
<[email protected]> wrote:
> On Fri, Sep 27, 2013 at 11:45:48AM +0100, Oussama Ghorbel wrote:
>> The ip6_tunnel.c module would be then dependent on ip_tunnel.c and may
>> be it would not be good thing?
>
> It could just be a static inline in some shared header. So there would
> be no compile-time dependency.
>
The higher limit of mtu in ip_tunnel_change_mtu() is a calculated value.
This high limit is calculated using the netdev priv struct ip_tunnel
(field hlen).
This netdev priv struct is different in ipv6, it's a ip6_tnl struct.
Therefore implementing a beautiful function like
ip_tunnel_valid_mtu(struct net_device *dev, int mtu) won't be
feasible, unless we implement it in macro or something like like
ip_tunnel_valid_mtu(struct net_device *dev, int hlen, int mtu) which
seems not very nice ...
What do yo think?
>> As I have check in v3.10 there is no call from ip6_tunnel to ip_tunnel...
>>
>> For information, there is no check for the maximum MTU for ipv4 in the
>> patch as this is not done for ipv6.
>
> I understand, but it would be better to limit the MTU here. There is a
> (non-jumo) IPV6_MAXPLEN constant.
>
> Looking through the source it seems grev6 does actually check this,
> so it would not hurt adding them here, too.
what if jumbograms is used, in that case, we can't use IPV6_MAXPLEN.
the limit would be the the full unsigned int.
However checking the higher limit for ipv4 would be useful.
Please also note in case the tunnel mode is any (ipv4 or ipv6 means
ip6_tnl.parms.proto = 0), then we will be required to take the most
restrict limit from both ipv4 and ipv6 which means the lower limit
will be 1280 and the higher limit will be about 65535
Do you agree on this?
>
> Otherwise, I think your patch is fine.
>
> Greetings,
>
> Hannes
>
On Fri, Sep 27, 2013 at 05:36:45PM +0100, Oussama Ghorbel wrote:
> Please see my comments below
>
> Regards,
> Oussama
>
> On Fri, Sep 27, 2013 at 11:58 AM, Hannes Frederic Sowa
> <[email protected]> wrote:
> > On Fri, Sep 27, 2013 at 11:45:48AM +0100, Oussama Ghorbel wrote:
> >> The ip6_tunnel.c module would be then dependent on ip_tunnel.c and may
> >> be it would not be good thing?
> >
> > It could just be a static inline in some shared header. So there would
> > be no compile-time dependency.
> >
>
> The higher limit of mtu in ip_tunnel_change_mtu() is a calculated value.
> This high limit is calculated using the netdev priv struct ip_tunnel
> (field hlen).
> This netdev priv struct is different in ipv6, it's a ip6_tnl struct.
> Therefore implementing a beautiful function like
> ip_tunnel_valid_mtu(struct net_device *dev, int mtu) won't be
> feasible, unless we implement it in macro or something like like
> ip_tunnel_valid_mtu(struct net_device *dev, int hlen, int mtu) which
> seems not very nice ...
> What do yo think?
Ok, let's go with one function per protocol type. Seems easier.
It seems to get more hairy, because it depends on the tunnel driver if the
prepended ip header is accounted in hard_header_len. :/
I don't know if it works out cleanly. Otherwise I would be ok if the checks
just get repeated in ip6_tunnel and leave the rest as-is.
>
> >> As I have check in v3.10 there is no call from ip6_tunnel to ip_tunnel...
> >>
> >> For information, there is no check for the maximum MTU for ipv4 in the
> >> patch as this is not done for ipv6.
> >
> > I understand, but it would be better to limit the MTU here. There is a
> > (non-jumo) IPV6_MAXPLEN constant.
> >
> > Looking through the source it seems grev6 does actually check this,
> > so it would not hurt adding them here, too.
>
> what if jumbograms is used, in that case, we can't use IPV6_MAXPLEN.
> the limit would be the the full unsigned int.
> However checking the higher limit for ipv4 would be useful.
Linux currently cannot create "jumbograms" (only the receiving side
is supported).
> Please also note in case the tunnel mode is any (ipv4 or ipv6 means
> ip6_tnl.parms.proto = 0), then we will be required to take the most
> restrict limit from both ipv4 and ipv6 which means the lower limit
> will be 1280 and the higher limit will be about 65535
> Do you agree on this?
Agreed, this would be needed for e.g. the sit driver, which now can
handle both protocols.
Thanks,
Hannes
On Fri, Sep 27, 2013 at 6:03 PM, Hannes Frederic Sowa
<[email protected]> wrote:
> On Fri, Sep 27, 2013 at 05:36:45PM +0100, Oussama Ghorbel wrote:
>> Please see my comments below
>>
>> Regards,
>> Oussama
>>
>> On Fri, Sep 27, 2013 at 11:58 AM, Hannes Frederic Sowa
>> <[email protected]> wrote:
>> > On Fri, Sep 27, 2013 at 11:45:48AM +0100, Oussama Ghorbel wrote:
>> >> The ip6_tunnel.c module would be then dependent on ip_tunnel.c and may
>> >> be it would not be good thing?
>> >
>> > It could just be a static inline in some shared header. So there would
>> > be no compile-time dependency.
>> >
>>
>> The higher limit of mtu in ip_tunnel_change_mtu() is a calculated value.
>> This high limit is calculated using the netdev priv struct ip_tunnel
>> (field hlen).
>> This netdev priv struct is different in ipv6, it's a ip6_tnl struct.
>> Therefore implementing a beautiful function like
>> ip_tunnel_valid_mtu(struct net_device *dev, int mtu) won't be
>> feasible, unless we implement it in macro or something like like
>> ip_tunnel_valid_mtu(struct net_device *dev, int hlen, int mtu) which
>> seems not very nice ...
>> What do yo think?
>
> Ok, let's go with one function per protocol type. Seems easier.
>
> It seems to get more hairy, because it depends on the tunnel driver if the
> prepended ip header is accounted in hard_header_len. :/
>
> I don't know if it works out cleanly. Otherwise I would be ok if the checks
> just get repeated in ip6_tunnel and leave the rest as-is.
>
Yes, It will be the clean way to do it.
>>
>> >> As I have check in v3.10 there is no call from ip6_tunnel to ip_tunnel...
>> >>
>> >> For information, there is no check for the maximum MTU for ipv4 in the
>> >> patch as this is not done for ipv6.
>> >
>> > I understand, but it would be better to limit the MTU here. There is a
>> > (non-jumo) IPV6_MAXPLEN constant.
>> >
>> > Looking through the source it seems grev6 does actually check this,
>> > so it would not hurt adding them here, too.
>>
>> what if jumbograms is used, in that case, we can't use IPV6_MAXPLEN.
>> the limit would be the the full unsigned int.
>> However checking the higher limit for ipv4 would be useful.
>
> Linux currently cannot create "jumbograms" (only the receiving side
> is supported).
>
I understand, but what are the benefit from this limit or the harm
from not specifying it?
Please check this comment from eth.c
/**
* eth_change_mtu - set new MTU size
* @dev: network device
* @new_mtu: new Maximum Transfer Unit
*
* Allow changing MTU size. Needs to be overridden for devices
* supporting jumbo frames.
*/
int eth_change_mtu(struct net_device *dev, int new_mtu)
So wouldn't be a good idea to let our function open for jumbo frames...?
>> Please also note in case the tunnel mode is any (ipv4 or ipv6 means
>> ip6_tnl.parms.proto = 0), then we will be required to take the most
>> restrict limit from both ipv4 and ipv6 which means the lower limit
>> will be 1280 and the higher limit will be about 65535
>> Do you agree on this?
>
> Agreed, this would be needed for e.g. the sit driver, which now can
> handle both protocols.
>
> Thanks,
>
> Hannes
>
Thanks,
Oussama
On Sun, Sep 29, 2013 at 10:40:11AM +0100, Oussama Ghorbel wrote:
> On Fri, Sep 27, 2013 at 6:03 PM, Hannes Frederic Sowa
> <[email protected]> wrote:
> > Ok, let's go with one function per protocol type. Seems easier.
> >
> > It seems to get more hairy, because it depends on the tunnel driver if the
> > prepended ip header is accounted in hard_header_len. :/
> >
> > I don't know if it works out cleanly. Otherwise I would be ok if the checks
> > just get repeated in ip6_tunnel and leave the rest as-is.
> >
> Yes, It will be the clean way to do it.
Fine. :)
> >
> > Linux currently cannot create "jumbograms" (only the receiving side
> > is supported).
> >
> I understand, but what are the benefit from this limit or the harm
> from not specifying it?
> Please check this comment from eth.c
>
> /**
> * eth_change_mtu - set new MTU size
> * @dev: network device
> * @new_mtu: new Maximum Transfer Unit
> *
> * Allow changing MTU size. Needs to be overridden for devices
> * supporting jumbo frames.
> */
> int eth_change_mtu(struct net_device *dev, int new_mtu)
Hmm, I cannot judge without the full patch. Will it be applicable
to all net_devices or just ethernet ones? The name could be a bit
misleading. Remindes me a lot of dev_set_mtu based on the signature, btw.
> So wouldn't be a good idea to let our function open for jumbo frames...?
Hm, we can document the fact that the function would needed to be updated in
that case. But we should not allow to set a mtu which would require jumbograms
currently.
Greetings,
Hannes
On Sun, Sep 29, 2013 at 4:45 PM, Hannes Frederic Sowa
<[email protected]> wrote:
> On Sun, Sep 29, 2013 at 10:40:11AM +0100, Oussama Ghorbel wrote:
>> On Fri, Sep 27, 2013 at 6:03 PM, Hannes Frederic Sowa
>> <[email protected]> wrote:
>> > Ok, let's go with one function per protocol type. Seems easier.
>> >
>> > It seems to get more hairy, because it depends on the tunnel driver if the
>> > prepended ip header is accounted in hard_header_len. :/
>> >
>> > I don't know if it works out cleanly. Otherwise I would be ok if the checks
>> > just get repeated in ip6_tunnel and leave the rest as-is.
>> >
>> Yes, It will be the clean way to do it.
>
> Fine. :)
>
>> >
>> > Linux currently cannot create "jumbograms" (only the receiving side
>> > is supported).
>> >
>> I understand, but what are the benefit from this limit or the harm
>> from not specifying it?
>> Please check this comment from eth.c
>>
>> /**
>> * eth_change_mtu - set new MTU size
>> * @dev: network device
>> * @new_mtu: new Maximum Transfer Unit
>> *
>> * Allow changing MTU size. Needs to be overridden for devices
>> * supporting jumbo frames.
>> */
>> int eth_change_mtu(struct net_device *dev, int new_mtu)
>
> Hmm, I cannot judge without the full patch. Will it be applicable
> to all net_devices or just ethernet ones? The name could be a bit
> misleading. Remindes me a lot of dev_set_mtu based on the signature, btw.
Normally to all net_devices, otherwise it could get complicated to
check for every dev separately ...
But, never mind, the comment below solve the issue
>
>> So wouldn't be a good idea to let our function open for jumbo frames...?
>
> Hm, we can document the fact that the function would needed to be updated in
> that case. But we should not allow to set a mtu which would require jumbograms
> currently.
OK, sounds a good. I will check the mtu against the limit
IPV6_MAXPLEN, and document the jumbo restriction ...
>
> Greetings,
>
> Hannes
>
Regards,
Oussama
I will send a new patch, the diff will be:
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index 46ba243..4b51b03 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -1429,9 +1429,17 @@ ip6_tnl_ioctl(struct net_device *dev, struct
ifreq *ifr, int cmd)
static int
ip6_tnl_change_mtu(struct net_device *dev, int new_mtu)
{
- if (new_mtu < IPV6_MIN_MTU) {
- return -EINVAL;
+ struct ip6_tnl *tnl = netdev_priv(dev);
+
+ if (tnl->parms.proto == IPPROTO_IPIP) {
+ if (new_mtu < 68)
+ return -EINVAL;
+ } else {
+ if (new_mtu < IPV6_MIN_MTU)
+ return -EINVAL;
}
+ if (new_mtu > 0xFFF8 - dev->hard_header_len)
+ return -EINVAL;
dev->mtu = new_mtu;
return 0;
}
On Sun, Sep 29, 2013 at 5:33 PM, Oussama Ghorbel <[email protected]> wrote:
> On Sun, Sep 29, 2013 at 4:45 PM, Hannes Frederic Sowa
> <[email protected]> wrote:
>> On Sun, Sep 29, 2013 at 10:40:11AM +0100, Oussama Ghorbel wrote:
>>> On Fri, Sep 27, 2013 at 6:03 PM, Hannes Frederic Sowa
>>> <[email protected]> wrote:
>>> > Ok, let's go with one function per protocol type. Seems easier.
>>> >
>>> > It seems to get more hairy, because it depends on the tunnel driver if the
>>> > prepended ip header is accounted in hard_header_len. :/
>>> >
>>> > I don't know if it works out cleanly. Otherwise I would be ok if the checks
>>> > just get repeated in ip6_tunnel and leave the rest as-is.
>>> >
>>> Yes, It will be the clean way to do it.
>>
>> Fine. :)
>>
>>> >
>>> > Linux currently cannot create "jumbograms" (only the receiving side
>>> > is supported).
>>> >
>>> I understand, but what are the benefit from this limit or the harm
>>> from not specifying it?
>>> Please check this comment from eth.c
>>>
>>> /**
>>> * eth_change_mtu - set new MTU size
>>> * @dev: network device
>>> * @new_mtu: new Maximum Transfer Unit
>>> *
>>> * Allow changing MTU size. Needs to be overridden for devices
>>> * supporting jumbo frames.
>>> */
>>> int eth_change_mtu(struct net_device *dev, int new_mtu)
>>
>> Hmm, I cannot judge without the full patch. Will it be applicable
>> to all net_devices or just ethernet ones? The name could be a bit
>> misleading. Remindes me a lot of dev_set_mtu based on the signature, btw.
>
> Normally to all net_devices, otherwise it could get complicated to
> check for every dev separately ...
> But, never mind, the comment below solve the issue
>
>>
>>> So wouldn't be a good idea to let our function open for jumbo frames...?
>>
>> Hm, we can document the fact that the function would needed to be updated in
>> that case. But we should not allow to set a mtu which would require jumbograms
>> currently.
>
> OK, sounds a good. I will check the mtu against the limit
> IPV6_MAXPLEN, and document the jumbo restriction ...
>
>>
>> Greetings,
>>
>> Hannes
>>
>
> Regards,
> Oussama