diff options
author | Petr Machata <petrm@mellanox.com> | 2018-05-17 10:36:51 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-05-17 16:50:06 -0400 |
commit | 2d665034f239412927b1e71329f20f001c92da09 (patch) | |
tree | 69b5c67423f30b1a6dccb2c152a15fec0195d19b /net | |
parent | c8632fc30bb03aa0c3bd7bcce85355a10feb8149 (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.c | 74 |
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); | |||
81 | static void ip6gre_tunnel_setup(struct net_device *dev); | 81 | static void ip6gre_tunnel_setup(struct net_device *dev); |
82 | static void ip6gre_tunnel_link(struct ip6gre_net *ign, struct ip6_tnl *t); | 82 | static void ip6gre_tunnel_link(struct ip6gre_net *ign, struct ip6_tnl *t); |
83 | static void ip6gre_tnl_link_config(struct ip6_tnl *t, int set_mtu); | 83 | static void ip6gre_tnl_link_config(struct ip6_tnl *t, int set_mtu); |
84 | static 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 | ||
1758 | static 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 | |||
1757 | static int ip6erspan_tap_init(struct net_device *dev) | 1771 | static 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 | ||
2133 | static 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 | |||
2148 | static 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 | |||
2154 | static 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 | |||
2162 | static 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 | |||
2124 | static struct rtnl_link_ops ip6gre_link_ops __read_mostly = { | 2180 | static 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, |