@@ -718,6 +718,47 @@ static int mlx5e_route_lookup_ipv4(struct mlx5e_priv *priv,
718
718
return 0 ;
719
719
}
720
720
721
+ static int mlx5e_route_lookup_ipv6 (struct mlx5e_priv * priv ,
722
+ struct net_device * mirred_dev ,
723
+ struct net_device * * out_dev ,
724
+ struct flowi6 * fl6 ,
725
+ struct neighbour * * out_n ,
726
+ int * out_ttl )
727
+ {
728
+ struct neighbour * n = NULL ;
729
+ struct dst_entry * dst ;
730
+
731
+ #if IS_ENABLED (CONFIG_INET ) && IS_ENABLED (CONFIG_IPV6 )
732
+ struct mlx5_eswitch * esw = priv -> mdev -> priv .eswitch ;
733
+ int ret ;
734
+
735
+ dst = ip6_route_output (dev_net (mirred_dev ), NULL , fl6 );
736
+ if (dst -> error ) {
737
+ ret = dst -> error ;
738
+ dst_release (dst );
739
+ return ret ;
740
+ }
741
+
742
+ * out_ttl = ip6_dst_hoplimit (dst );
743
+
744
+ /* if the egress device isn't on the same HW e-switch, we use the uplink */
745
+ if (!switchdev_port_same_parent_id (priv -> netdev , dst -> dev ))
746
+ * out_dev = mlx5_eswitch_get_uplink_netdev (esw );
747
+ else
748
+ * out_dev = dst -> dev ;
749
+ #else
750
+ return - EOPNOTSUPP ;
751
+ #endif
752
+
753
+ n = dst_neigh_lookup (dst , & fl6 -> daddr );
754
+ dst_release (dst );
755
+ if (!n )
756
+ return - ENOMEM ;
757
+
758
+ * out_n = n ;
759
+ return 0 ;
760
+ }
761
+
721
762
static int gen_vxlan_header_ipv4 (struct net_device * out_dev ,
722
763
char buf [],
723
764
unsigned char h_dest [ETH_ALEN ],
@@ -754,6 +795,41 @@ static int gen_vxlan_header_ipv4(struct net_device *out_dev,
754
795
return encap_size ;
755
796
}
756
797
798
+ static int gen_vxlan_header_ipv6 (struct net_device * out_dev ,
799
+ char buf [],
800
+ unsigned char h_dest [ETH_ALEN ],
801
+ int ttl ,
802
+ struct in6_addr * daddr ,
803
+ struct in6_addr * saddr ,
804
+ __be16 udp_dst_port ,
805
+ __be32 vx_vni )
806
+ {
807
+ int encap_size = VXLAN_HLEN + sizeof (struct ipv6hdr ) + ETH_HLEN ;
808
+ struct ethhdr * eth = (struct ethhdr * )buf ;
809
+ struct ipv6hdr * ip6h = (struct ipv6hdr * )((char * )eth + sizeof (struct ethhdr ));
810
+ struct udphdr * udp = (struct udphdr * )((char * )ip6h + sizeof (struct ipv6hdr ));
811
+ struct vxlanhdr * vxh = (struct vxlanhdr * )((char * )udp + sizeof (struct udphdr ));
812
+
813
+ memset (buf , 0 , encap_size );
814
+
815
+ ether_addr_copy (eth -> h_dest , h_dest );
816
+ ether_addr_copy (eth -> h_source , out_dev -> dev_addr );
817
+ eth -> h_proto = htons (ETH_P_IPV6 );
818
+
819
+ ip6_flow_hdr (ip6h , 0 , 0 );
820
+ /* the HW fills up ipv6 payload len */
821
+ ip6h -> nexthdr = IPPROTO_UDP ;
822
+ ip6h -> hop_limit = ttl ;
823
+ ip6h -> daddr = * daddr ;
824
+ ip6h -> saddr = * saddr ;
825
+
826
+ udp -> dest = udp_dst_port ;
827
+ vxh -> vx_flags = VXLAN_HF_VNI ;
828
+ vxh -> vx_vni = vxlan_vni_field (vx_vni );
829
+
830
+ return encap_size ;
831
+ }
832
+
757
833
static int mlx5e_create_encap_header_ipv4 (struct mlx5e_priv * priv ,
758
834
struct net_device * mirred_dev ,
759
835
struct mlx5_encap_entry * e ,
@@ -821,6 +897,75 @@ static int mlx5e_create_encap_header_ipv4(struct mlx5e_priv *priv,
821
897
return err ;
822
898
}
823
899
900
+ static int mlx5e_create_encap_header_ipv6 (struct mlx5e_priv * priv ,
901
+ struct net_device * mirred_dev ,
902
+ struct mlx5_encap_entry * e ,
903
+ struct net_device * * out_dev )
904
+
905
+ {
906
+ int max_encap_size = MLX5_CAP_ESW (priv -> mdev , max_encap_header_size );
907
+ struct ip_tunnel_key * tun_key = & e -> tun_info .key ;
908
+ int encap_size , err , ttl = 0 ;
909
+ struct neighbour * n = NULL ;
910
+ struct flowi6 fl6 = {};
911
+ char * encap_header ;
912
+
913
+ encap_header = kzalloc (max_encap_size , GFP_KERNEL );
914
+ if (!encap_header )
915
+ return - ENOMEM ;
916
+
917
+ switch (e -> tunnel_type ) {
918
+ case MLX5_HEADER_TYPE_VXLAN :
919
+ fl6 .flowi6_proto = IPPROTO_UDP ;
920
+ fl6 .fl6_dport = tun_key -> tp_dst ;
921
+ break ;
922
+ default :
923
+ err = - EOPNOTSUPP ;
924
+ goto out ;
925
+ }
926
+
927
+ fl6 .flowlabel = ip6_make_flowinfo (RT_TOS (tun_key -> tos ), tun_key -> label );
928
+ fl6 .daddr = tun_key -> u .ipv6 .dst ;
929
+ fl6 .saddr = tun_key -> u .ipv6 .src ;
930
+
931
+ err = mlx5e_route_lookup_ipv6 (priv , mirred_dev , out_dev ,
932
+ & fl6 , & n , & ttl );
933
+ if (err )
934
+ goto out ;
935
+
936
+ if (!(n -> nud_state & NUD_VALID )) {
937
+ pr_warn ("%s: can't offload, neighbour to %pI6 invalid\n" , __func__ , & fl6 .daddr );
938
+ err = - EOPNOTSUPP ;
939
+ goto out ;
940
+ }
941
+
942
+ e -> n = n ;
943
+ e -> out_dev = * out_dev ;
944
+
945
+ neigh_ha_snapshot (e -> h_dest , n , * out_dev );
946
+
947
+ switch (e -> tunnel_type ) {
948
+ case MLX5_HEADER_TYPE_VXLAN :
949
+ encap_size = gen_vxlan_header_ipv6 (* out_dev , encap_header ,
950
+ e -> h_dest , ttl ,
951
+ & fl6 .daddr ,
952
+ & fl6 .saddr , tun_key -> tp_dst ,
953
+ tunnel_id_to_key32 (tun_key -> tun_id ));
954
+ break ;
955
+ default :
956
+ err = - EOPNOTSUPP ;
957
+ goto out ;
958
+ }
959
+
960
+ err = mlx5_encap_alloc (priv -> mdev , e -> tunnel_type ,
961
+ encap_size , encap_header , & e -> encap_id );
962
+ out :
963
+ if (err && n )
964
+ neigh_release (n );
965
+ kfree (encap_header );
966
+ return err ;
967
+ }
968
+
824
969
static int mlx5e_attach_encap (struct mlx5e_priv * priv ,
825
970
struct ip_tunnel_info * tun_info ,
826
971
struct net_device * mirred_dev ,
@@ -831,7 +976,7 @@ static int mlx5e_attach_encap(struct mlx5e_priv *priv,
831
976
struct ip_tunnel_key * key = & tun_info -> key ;
832
977
struct mlx5_encap_entry * e ;
833
978
struct net_device * out_dev ;
834
- int tunnel_type , err ;
979
+ int tunnel_type , err = - EOPNOTSUPP ;
835
980
uintptr_t hash_key ;
836
981
bool found = false;
837
982
@@ -856,12 +1001,6 @@ static int mlx5e_attach_encap(struct mlx5e_priv *priv,
856
1001
return - EOPNOTSUPP ;
857
1002
}
858
1003
859
- if (family == AF_INET6 ) {
860
- netdev_warn (priv -> netdev ,
861
- "IPv6 tunnel encap offload isn't supported\n" );
862
- return - EOPNOTSUPP ;
863
- }
864
-
865
1004
hash_key = hash_encap_info (key );
866
1005
867
1006
hash_for_each_possible_rcu (esw -> offloads .encap_tbl , e ,
@@ -885,7 +1024,11 @@ static int mlx5e_attach_encap(struct mlx5e_priv *priv,
885
1024
e -> tunnel_type = tunnel_type ;
886
1025
INIT_LIST_HEAD (& e -> flows );
887
1026
888
- err = mlx5e_create_encap_header_ipv4 (priv , mirred_dev , e , & out_dev );
1027
+ if (family == AF_INET )
1028
+ err = mlx5e_create_encap_header_ipv4 (priv , mirred_dev , e , & out_dev );
1029
+ else if (family == AF_INET6 )
1030
+ err = mlx5e_create_encap_header_ipv6 (priv , mirred_dev , e , & out_dev );
1031
+
889
1032
if (err )
890
1033
goto out_err ;
891
1034
0 commit comments