aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorPetr Machata <petrm@mellanox.com>2018-05-17 10:36:51 -0400
committerDavid S. Miller <davem@davemloft.net>2018-05-17 16:50:06 -0400
commit2d665034f239412927b1e71329f20f001c92da09 (patch)
tree69b5c67423f30b1a6dccb2c152a15fec0195d19b /net
parentc8632fc30bb03aa0c3bd7bcce85355a10feb8149 (diff)
net: ip6_gre: Fix ip6erspan hlen calculation
Even though ip6erspan_tap_init() sets up hlen and tun_hlen according to what ERSPAN needs, it goes ahead to call ip6gre_tnl_link_config() which overwrites these settings with GRE-specific ones. Similarly for changelink callbacks, which are handled by ip6gre_changelink() calls ip6gre_tnl_change() calls ip6gre_tnl_link_config() as well. The difference ends up being 12 vs. 20 bytes, and this is generally not a problem, because a 12-byte request likely ends up allocating more and the extra 8 bytes are thus available. However correct it is not. So replace the newlink and changelink callbacks with an ERSPAN-specific ones, reusing the newly-introduced _common() functions. Fixes: 5a963eb61b7c ("ip6_gre: Add ERSPAN native tunnel support") Signed-off-by: Petr Machata <petrm@mellanox.com> Acked-by: William Tu <u9012063@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/ipv6/ip6_gre.c74
1 files changed, 65 insertions, 9 deletions
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
index 41fd5735f931..5162ecc45c20 100644
--- a/net/ipv6/ip6_gre.c
+++ b/net/ipv6/ip6_gre.c
@@ -81,6 +81,7 @@ static int ip6gre_tunnel_init(struct net_device *dev);
81static void ip6gre_tunnel_setup(struct net_device *dev); 81static void ip6gre_tunnel_setup(struct net_device *dev);
82static void ip6gre_tunnel_link(struct ip6gre_net *ign, struct ip6_tnl *t); 82static void ip6gre_tunnel_link(struct ip6gre_net *ign, struct ip6_tnl *t);
83static void ip6gre_tnl_link_config(struct ip6_tnl *t, int set_mtu); 83static void ip6gre_tnl_link_config(struct ip6_tnl *t, int set_mtu);
84static void ip6erspan_tnl_link_config(struct ip6_tnl *t, int set_mtu);
84 85
85/* Tunnel hash table */ 86/* Tunnel hash table */
86 87
@@ -1754,6 +1755,19 @@ static const struct net_device_ops ip6gre_tap_netdev_ops = {
1754 .ndo_get_iflink = ip6_tnl_get_iflink, 1755 .ndo_get_iflink = ip6_tnl_get_iflink,
1755}; 1756};
1756 1757
1758static int ip6erspan_calc_hlen(struct ip6_tnl *tunnel)
1759{
1760 int t_hlen;
1761
1762 tunnel->tun_hlen = 8;
1763 tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen +
1764 erspan_hdr_len(tunnel->parms.erspan_ver);
1765
1766 t_hlen = tunnel->hlen + sizeof(struct ipv6hdr);
1767 tunnel->dev->hard_header_len = LL_MAX_HEADER + t_hlen;
1768 return t_hlen;
1769}
1770
1757static int ip6erspan_tap_init(struct net_device *dev) 1771static int ip6erspan_tap_init(struct net_device *dev)
1758{ 1772{
1759 struct ip6_tnl *tunnel; 1773 struct ip6_tnl *tunnel;
@@ -1777,12 +1791,7 @@ static int ip6erspan_tap_init(struct net_device *dev)
1777 return ret; 1791 return ret;
1778 } 1792 }
1779 1793
1780 tunnel->tun_hlen = 8; 1794 t_hlen = ip6erspan_calc_hlen(tunnel);
1781 tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen +
1782 erspan_hdr_len(tunnel->parms.erspan_ver);
1783 t_hlen = tunnel->hlen + sizeof(struct ipv6hdr);
1784
1785 dev->hard_header_len = LL_MAX_HEADER + t_hlen;
1786 dev->mtu = ETH_DATA_LEN - t_hlen; 1795 dev->mtu = ETH_DATA_LEN - t_hlen;
1787 if (dev->type == ARPHRD_ETHER) 1796 if (dev->type == ARPHRD_ETHER)
1788 dev->mtu -= ETH_HLEN; 1797 dev->mtu -= ETH_HLEN;
@@ -1790,7 +1799,7 @@ static int ip6erspan_tap_init(struct net_device *dev)
1790 dev->mtu -= 8; 1799 dev->mtu -= 8;
1791 1800
1792 dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; 1801 dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
1793 ip6gre_tnl_link_config(tunnel, 1); 1802 ip6erspan_tnl_link_config(tunnel, 1);
1794 1803
1795 return 0; 1804 return 0;
1796} 1805}
@@ -2121,6 +2130,53 @@ static void ip6erspan_tap_setup(struct net_device *dev)
2121 netif_keep_dst(dev); 2130 netif_keep_dst(dev);
2122} 2131}
2123 2132
2133static int ip6erspan_newlink(struct net *src_net, struct net_device *dev,
2134 struct nlattr *tb[], struct nlattr *data[],
2135 struct netlink_ext_ack *extack)
2136{
2137 int err = ip6gre_newlink_common(src_net, dev, tb, data, extack);
2138 struct ip6_tnl *nt = netdev_priv(dev);
2139 struct net *net = dev_net(dev);
2140
2141 if (!err) {
2142 ip6erspan_tnl_link_config(nt, !tb[IFLA_MTU]);
2143 ip6gre_tunnel_link(net_generic(net, ip6gre_net_id), nt);
2144 }
2145 return err;
2146}
2147
2148static void ip6erspan_tnl_link_config(struct ip6_tnl *t, int set_mtu)
2149{
2150 ip6gre_tnl_link_config_common(t);
2151 ip6gre_tnl_link_config_route(t, set_mtu, ip6erspan_calc_hlen(t));
2152}
2153
2154static int ip6erspan_tnl_change(struct ip6_tnl *t,
2155 const struct __ip6_tnl_parm *p, int set_mtu)
2156{
2157 ip6gre_tnl_copy_tnl_parm(t, p);
2158 ip6erspan_tnl_link_config(t, set_mtu);
2159 return 0;
2160}
2161
2162static int ip6erspan_changelink(struct net_device *dev, struct nlattr *tb[],
2163 struct nlattr *data[],
2164 struct netlink_ext_ack *extack)
2165{
2166 struct ip6gre_net *ign = net_generic(dev_net(dev), ip6gre_net_id);
2167 struct __ip6_tnl_parm p;
2168 struct ip6_tnl *t;
2169
2170 t = ip6gre_changelink_common(dev, tb, data, &p, extack);
2171 if (IS_ERR(t))
2172 return PTR_ERR(t);
2173
2174 ip6gre_tunnel_unlink(ign, t);
2175 ip6erspan_tnl_change(t, &p, !tb[IFLA_MTU]);
2176 ip6gre_tunnel_link(ign, t);
2177 return 0;
2178}
2179
2124static struct rtnl_link_ops ip6gre_link_ops __read_mostly = { 2180static struct rtnl_link_ops ip6gre_link_ops __read_mostly = {
2125 .kind = "ip6gre", 2181 .kind = "ip6gre",
2126 .maxtype = IFLA_GRE_MAX, 2182 .maxtype = IFLA_GRE_MAX,
@@ -2157,8 +2213,8 @@ static struct rtnl_link_ops ip6erspan_tap_ops __read_mostly = {
2157 .priv_size = sizeof(struct ip6_tnl), 2213 .priv_size = sizeof(struct ip6_tnl),
2158 .setup = ip6erspan_tap_setup, 2214 .setup = ip6erspan_tap_setup,
2159 .validate = ip6erspan_tap_validate, 2215 .validate = ip6erspan_tap_validate,
2160 .newlink = ip6gre_newlink, 2216 .newlink = ip6erspan_newlink,
2161 .changelink = ip6gre_changelink, 2217 .changelink = ip6erspan_changelink,
2162 .get_size = ip6gre_get_size, 2218 .get_size = ip6gre_get_size,
2163 .fill_info = ip6gre_fill_info, 2219 .fill_info = ip6gre_fill_info,
2164 .get_link_net = ip6_tnl_get_link_net, 2220 .get_link_net = ip6_tnl_get_link_net,