diff options
author | Or Gerlitz <ogerlitz@mellanox.com> | 2017-04-06 12:28:30 -0400 |
---|---|---|
committer | Saeed Mahameed <saeedm@mellanox.com> | 2017-04-22 14:52:37 -0400 |
commit | 225aabaffe9ab42b2dd8770359442f019083275e (patch) | |
tree | cb2920318f319edde99e7dfc17853867b35782a5 | |
parent | 32f3671f6951836cfe9d84e1a6554908b85c61d7 (diff) |
net/mlx5e: Make sure the FW max encap size is enough for ipv6 tunnels
Otherwise the code that fills the ipv6 encapsulation headers could be writing
beyond the allocated headers buffer.
Fixes: ce99f6b97fcd ('net/mlx5e: Support SRIOV TC encapsulation offloads for IPv6 tunnels')
Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
Reviewed-by: Roi Dayan <roid@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 42 |
1 files changed, 23 insertions, 19 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index fc7c1d30461c..5436866798f4 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | |||
@@ -819,16 +819,15 @@ static void gen_vxlan_header_ipv4(struct net_device *out_dev, | |||
819 | vxh->vx_vni = vxlan_vni_field(vx_vni); | 819 | vxh->vx_vni = vxlan_vni_field(vx_vni); |
820 | } | 820 | } |
821 | 821 | ||
822 | static int gen_vxlan_header_ipv6(struct net_device *out_dev, | 822 | static void gen_vxlan_header_ipv6(struct net_device *out_dev, |
823 | char buf[], | 823 | char buf[], int encap_size, |
824 | unsigned char h_dest[ETH_ALEN], | 824 | unsigned char h_dest[ETH_ALEN], |
825 | int ttl, | 825 | int ttl, |
826 | struct in6_addr *daddr, | 826 | struct in6_addr *daddr, |
827 | struct in6_addr *saddr, | 827 | struct in6_addr *saddr, |
828 | __be16 udp_dst_port, | 828 | __be16 udp_dst_port, |
829 | __be32 vx_vni) | 829 | __be32 vx_vni) |
830 | { | 830 | { |
831 | int encap_size = VXLAN_HLEN + sizeof(struct ipv6hdr) + ETH_HLEN; | ||
832 | struct ethhdr *eth = (struct ethhdr *)buf; | 831 | struct ethhdr *eth = (struct ethhdr *)buf; |
833 | struct ipv6hdr *ip6h = (struct ipv6hdr *)((char *)eth + sizeof(struct ethhdr)); | 832 | struct ipv6hdr *ip6h = (struct ipv6hdr *)((char *)eth + sizeof(struct ethhdr)); |
834 | struct udphdr *udp = (struct udphdr *)((char *)ip6h + sizeof(struct ipv6hdr)); | 833 | struct udphdr *udp = (struct udphdr *)((char *)ip6h + sizeof(struct ipv6hdr)); |
@@ -850,8 +849,6 @@ static int gen_vxlan_header_ipv6(struct net_device *out_dev, | |||
850 | udp->dest = udp_dst_port; | 849 | udp->dest = udp_dst_port; |
851 | vxh->vx_flags = VXLAN_HF_VNI; | 850 | vxh->vx_flags = VXLAN_HF_VNI; |
852 | vxh->vx_vni = vxlan_vni_field(vx_vni); | 851 | vxh->vx_vni = vxlan_vni_field(vx_vni); |
853 | |||
854 | return encap_size; | ||
855 | } | 852 | } |
856 | 853 | ||
857 | static int mlx5e_create_encap_header_ipv4(struct mlx5e_priv *priv, | 854 | static int mlx5e_create_encap_header_ipv4(struct mlx5e_priv *priv, |
@@ -935,13 +932,20 @@ static int mlx5e_create_encap_header_ipv6(struct mlx5e_priv *priv, | |||
935 | 932 | ||
936 | { | 933 | { |
937 | int max_encap_size = MLX5_CAP_ESW(priv->mdev, max_encap_header_size); | 934 | int max_encap_size = MLX5_CAP_ESW(priv->mdev, max_encap_header_size); |
935 | int ipv6_encap_size = ETH_HLEN + sizeof(struct ipv6hdr) + VXLAN_HLEN; | ||
938 | struct ip_tunnel_key *tun_key = &e->tun_info.key; | 936 | struct ip_tunnel_key *tun_key = &e->tun_info.key; |
939 | int encap_size, err, ttl = 0; | ||
940 | struct neighbour *n = NULL; | 937 | struct neighbour *n = NULL; |
941 | struct flowi6 fl6 = {}; | 938 | struct flowi6 fl6 = {}; |
942 | char *encap_header; | 939 | char *encap_header; |
940 | int err, ttl = 0; | ||
943 | 941 | ||
944 | encap_header = kzalloc(max_encap_size, GFP_KERNEL); | 942 | if (max_encap_size < ipv6_encap_size) { |
943 | mlx5_core_warn(priv->mdev, "encap size %d too big, max supported is %d\n", | ||
944 | ipv6_encap_size, max_encap_size); | ||
945 | return -EOPNOTSUPP; | ||
946 | } | ||
947 | |||
948 | encap_header = kzalloc(ipv6_encap_size, GFP_KERNEL); | ||
945 | if (!encap_header) | 949 | if (!encap_header) |
946 | return -ENOMEM; | 950 | return -ENOMEM; |
947 | 951 | ||
@@ -977,11 +981,11 @@ static int mlx5e_create_encap_header_ipv6(struct mlx5e_priv *priv, | |||
977 | 981 | ||
978 | switch (e->tunnel_type) { | 982 | switch (e->tunnel_type) { |
979 | case MLX5_HEADER_TYPE_VXLAN: | 983 | case MLX5_HEADER_TYPE_VXLAN: |
980 | encap_size = gen_vxlan_header_ipv6(*out_dev, encap_header, | 984 | gen_vxlan_header_ipv6(*out_dev, encap_header, |
981 | e->h_dest, ttl, | 985 | ipv6_encap_size, e->h_dest, ttl, |
982 | &fl6.daddr, | 986 | &fl6.daddr, |
983 | &fl6.saddr, tun_key->tp_dst, | 987 | &fl6.saddr, tun_key->tp_dst, |
984 | tunnel_id_to_key32(tun_key->tun_id)); | 988 | tunnel_id_to_key32(tun_key->tun_id)); |
985 | break; | 989 | break; |
986 | default: | 990 | default: |
987 | err = -EOPNOTSUPP; | 991 | err = -EOPNOTSUPP; |
@@ -989,7 +993,7 @@ static int mlx5e_create_encap_header_ipv6(struct mlx5e_priv *priv, | |||
989 | } | 993 | } |
990 | 994 | ||
991 | err = mlx5_encap_alloc(priv->mdev, e->tunnel_type, | 995 | err = mlx5_encap_alloc(priv->mdev, e->tunnel_type, |
992 | encap_size, encap_header, &e->encap_id); | 996 | ipv6_encap_size, encap_header, &e->encap_id); |
993 | out: | 997 | out: |
994 | if (err && n) | 998 | if (err && n) |
995 | neigh_release(n); | 999 | neigh_release(n); |