aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorStefano Brivio <sbrivio@redhat.com>2018-03-15 12:17:12 -0400
committerSteffen Klassert <steffen.klassert@secunet.com>2018-03-19 03:45:50 -0400
commit7a67e69a339a6824be2fc483073782ab2f47fcd2 (patch)
tree9ad2cfaf899bb8dddcd2b44da677bd5eae2693c4 /net
parentc6741fbed6dc0f183d26c4b6bca4517672f92e6c (diff)
vti6: Keep set MTU on link creation or change, validate it
In vti6_link_config(), if MTU is already given on link creation or change, validate and use it instead of recomputing it. To do that, we need to propagate the knowledge that MTU was set by userspace all the way down to vti6_link_config(). To keep this simple, vti6_dev_init() sets the new 'keep_mtu' argument of vti6_link_config() to true: on initialization, we don't have convenient access to netlink attributes there, but we will anyway check whether dev->mtu is set in vti6_link_config(). If it's non-zero, it was set to the value of the IFLA_MTU attribute during creation. Otherwise, determine a reasonable value. Fixes: ed1efb2aefbb ("ipv6: Add support for IPsec virtual tunnel interfaces") Fixes: 53c81e95df17 ("ip6_vti: adjust vti mtu according to mtu of lower device") Signed-off-by: Stefano Brivio <sbrivio@redhat.com> Acked-by: Sabrina Dubroca <sd@queasysnail.net> Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
Diffstat (limited to 'net')
-rw-r--r--net/ipv6/ip6_vti.c24
1 files changed, 16 insertions, 8 deletions
diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c
index 2ceef41cc097..971175142e14 100644
--- a/net/ipv6/ip6_vti.c
+++ b/net/ipv6/ip6_vti.c
@@ -622,7 +622,7 @@ static int vti6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
622 return 0; 622 return 0;
623} 623}
624 624
625static void vti6_link_config(struct ip6_tnl *t) 625static void vti6_link_config(struct ip6_tnl *t, bool keep_mtu)
626{ 626{
627 struct net_device *dev = t->dev; 627 struct net_device *dev = t->dev;
628 struct __ip6_tnl_parm *p = &t->parms; 628 struct __ip6_tnl_parm *p = &t->parms;
@@ -641,6 +641,11 @@ static void vti6_link_config(struct ip6_tnl *t)
641 else 641 else
642 dev->flags &= ~IFF_POINTOPOINT; 642 dev->flags &= ~IFF_POINTOPOINT;
643 643
644 if (keep_mtu && dev->mtu) {
645 dev->mtu = clamp(dev->mtu, dev->min_mtu, dev->max_mtu);
646 return;
647 }
648
644 if (p->flags & IP6_TNL_F_CAP_XMIT) { 649 if (p->flags & IP6_TNL_F_CAP_XMIT) {
645 int strict = (ipv6_addr_type(&p->raddr) & 650 int strict = (ipv6_addr_type(&p->raddr) &
646 (IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL)); 651 (IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL));
@@ -668,12 +673,14 @@ static void vti6_link_config(struct ip6_tnl *t)
668 * vti6_tnl_change - update the tunnel parameters 673 * vti6_tnl_change - update the tunnel parameters
669 * @t: tunnel to be changed 674 * @t: tunnel to be changed
670 * @p: tunnel configuration parameters 675 * @p: tunnel configuration parameters
676 * @keep_mtu: MTU was set from userspace, don't re-compute it
671 * 677 *
672 * Description: 678 * Description:
673 * vti6_tnl_change() updates the tunnel parameters 679 * vti6_tnl_change() updates the tunnel parameters
674 **/ 680 **/
675static int 681static int
676vti6_tnl_change(struct ip6_tnl *t, const struct __ip6_tnl_parm *p) 682vti6_tnl_change(struct ip6_tnl *t, const struct __ip6_tnl_parm *p,
683 bool keep_mtu)
677{ 684{
678 t->parms.laddr = p->laddr; 685 t->parms.laddr = p->laddr;
679 t->parms.raddr = p->raddr; 686 t->parms.raddr = p->raddr;
@@ -683,11 +690,12 @@ vti6_tnl_change(struct ip6_tnl *t, const struct __ip6_tnl_parm *p)
683 t->parms.proto = p->proto; 690 t->parms.proto = p->proto;
684 t->parms.fwmark = p->fwmark; 691 t->parms.fwmark = p->fwmark;
685 dst_cache_reset(&t->dst_cache); 692 dst_cache_reset(&t->dst_cache);
686 vti6_link_config(t); 693 vti6_link_config(t, keep_mtu);
687 return 0; 694 return 0;
688} 695}
689 696
690static int vti6_update(struct ip6_tnl *t, struct __ip6_tnl_parm *p) 697static int vti6_update(struct ip6_tnl *t, struct __ip6_tnl_parm *p,
698 bool keep_mtu)
691{ 699{
692 struct net *net = dev_net(t->dev); 700 struct net *net = dev_net(t->dev);
693 struct vti6_net *ip6n = net_generic(net, vti6_net_id); 701 struct vti6_net *ip6n = net_generic(net, vti6_net_id);
@@ -695,7 +703,7 @@ static int vti6_update(struct ip6_tnl *t, struct __ip6_tnl_parm *p)
695 703
696 vti6_tnl_unlink(ip6n, t); 704 vti6_tnl_unlink(ip6n, t);
697 synchronize_net(); 705 synchronize_net();
698 err = vti6_tnl_change(t, p); 706 err = vti6_tnl_change(t, p, keep_mtu);
699 vti6_tnl_link(ip6n, t); 707 vti6_tnl_link(ip6n, t);
700 netdev_state_change(t->dev); 708 netdev_state_change(t->dev);
701 return err; 709 return err;
@@ -808,7 +816,7 @@ vti6_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
808 } else 816 } else
809 t = netdev_priv(dev); 817 t = netdev_priv(dev);
810 818
811 err = vti6_update(t, &p1); 819 err = vti6_update(t, &p1, false);
812 } 820 }
813 if (t) { 821 if (t) {
814 err = 0; 822 err = 0;
@@ -907,7 +915,7 @@ static int vti6_dev_init(struct net_device *dev)
907 915
908 if (err) 916 if (err)
909 return err; 917 return err;
910 vti6_link_config(t); 918 vti6_link_config(t, true);
911 return 0; 919 return 0;
912} 920}
913 921
@@ -1012,7 +1020,7 @@ static int vti6_changelink(struct net_device *dev, struct nlattr *tb[],
1012 } else 1020 } else
1013 t = netdev_priv(dev); 1021 t = netdev_priv(dev);
1014 1022
1015 return vti6_update(t, &p); 1023 return vti6_update(t, &p, tb && tb[IFLA_MTU]);
1016} 1024}
1017 1025
1018static size_t vti6_get_size(const struct net_device *dev) 1026static size_t vti6_get_size(const struct net_device *dev)