@@ -524,8 +524,37 @@ static int ip6erspan_rcv(struct sk_buff *skb, int gre_hdr_len,
524
524
false, false) < 0 )
525
525
return PACKET_REJECT ;
526
526
527
- tunnel -> parms .index = ntohl (index );
528
- ip6_tnl_rcv (tunnel , skb , tpi , NULL , log_ecn_error );
527
+ if (tunnel -> parms .collect_md ) {
528
+ struct metadata_dst * tun_dst ;
529
+ struct ip_tunnel_info * info ;
530
+ struct erspan_metadata * md ;
531
+ __be64 tun_id ;
532
+ __be16 flags ;
533
+
534
+ tpi -> flags |= TUNNEL_KEY ;
535
+ flags = tpi -> flags ;
536
+ tun_id = key32_to_tunnel_id (tpi -> key );
537
+
538
+ tun_dst = ipv6_tun_rx_dst (skb , flags , tun_id ,
539
+ sizeof (* md ));
540
+ if (!tun_dst )
541
+ return PACKET_REJECT ;
542
+
543
+ info = & tun_dst -> u .tun_info ;
544
+ md = ip_tunnel_info_opts (info );
545
+ if (!md )
546
+ return PACKET_REJECT ;
547
+
548
+ md -> index = index ;
549
+ info -> key .tun_flags |= TUNNEL_ERSPAN_OPT ;
550
+ info -> options_len = sizeof (* md );
551
+
552
+ ip6_tnl_rcv (tunnel , skb , tpi , tun_dst , log_ecn_error );
553
+
554
+ } else {
555
+ tunnel -> parms .index = ntohl (index );
556
+ ip6_tnl_rcv (tunnel , skb , tpi , NULL , log_ecn_error );
557
+ }
529
558
530
559
return PACKET_RCVD ;
531
560
}
@@ -857,42 +886,73 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,
857
886
if (gre_handle_offloads (skb , false))
858
887
goto tx_err ;
859
888
860
- switch (skb -> protocol ) {
861
- case htons (ETH_P_IP ):
862
- memset (& (IPCB (skb )-> opt ), 0 , sizeof (IPCB (skb )-> opt ));
863
- prepare_ip6gre_xmit_ipv4 (skb , dev , & fl6 ,
864
- & dsfield , & encap_limit );
865
- break ;
866
- case htons (ETH_P_IPV6 ):
867
- if (ipv6_addr_equal (& t -> parms .raddr , & ipv6h -> saddr ))
868
- goto tx_err ;
869
- if (prepare_ip6gre_xmit_ipv6 (skb , dev , & fl6 ,
870
- & dsfield , & encap_limit ))
871
- goto tx_err ;
872
- break ;
873
- default :
874
- memcpy (& fl6 , & t -> fl .u .ip6 , sizeof (fl6 ));
875
- break ;
876
- }
877
-
878
889
if (skb -> len > dev -> mtu + dev -> hard_header_len ) {
879
890
pskb_trim (skb , dev -> mtu + dev -> hard_header_len );
880
891
truncate = true;
881
892
}
882
893
883
- erspan_build_header (skb , t -> parms .o_key , t -> parms .index ,
884
- truncate , false);
885
894
t -> parms .o_flags &= ~TUNNEL_KEY ;
886
-
887
895
IPCB (skb )-> flags = 0 ;
888
- fl6 .daddr = t -> parms .raddr ;
896
+
897
+ /* For collect_md mode, derive fl6 from the tunnel key,
898
+ * for native mode, call prepare_ip6gre_xmit_{ipv4,ipv6}.
899
+ */
900
+ if (t -> parms .collect_md ) {
901
+ struct ip_tunnel_info * tun_info ;
902
+ const struct ip_tunnel_key * key ;
903
+ struct erspan_metadata * md ;
904
+
905
+ tun_info = skb_tunnel_info (skb );
906
+ if (unlikely (!tun_info ||
907
+ !(tun_info -> mode & IP_TUNNEL_INFO_TX ) ||
908
+ ip_tunnel_info_af (tun_info ) != AF_INET6 ))
909
+ return - EINVAL ;
910
+
911
+ key = & tun_info -> key ;
912
+ memset (& fl6 , 0 , sizeof (fl6 ));
913
+ fl6 .flowi6_proto = IPPROTO_GRE ;
914
+ fl6 .daddr = key -> u .ipv6 .dst ;
915
+ fl6 .flowlabel = key -> label ;
916
+ fl6 .flowi6_uid = sock_net_uid (dev_net (dev ), NULL );
917
+
918
+ dsfield = key -> tos ;
919
+ md = ip_tunnel_info_opts (tun_info );
920
+ if (!md )
921
+ goto tx_err ;
922
+
923
+ erspan_build_header (skb , tunnel_id_to_key32 (key -> tun_id ),
924
+ ntohl (md -> index ), truncate , false);
925
+
926
+ } else {
927
+ switch (skb -> protocol ) {
928
+ case htons (ETH_P_IP ):
929
+ memset (& (IPCB (skb )-> opt ), 0 , sizeof (IPCB (skb )-> opt ));
930
+ prepare_ip6gre_xmit_ipv4 (skb , dev , & fl6 ,
931
+ & dsfield , & encap_limit );
932
+ break ;
933
+ case htons (ETH_P_IPV6 ):
934
+ if (ipv6_addr_equal (& t -> parms .raddr , & ipv6h -> saddr ))
935
+ goto tx_err ;
936
+ if (prepare_ip6gre_xmit_ipv6 (skb , dev , & fl6 ,
937
+ & dsfield , & encap_limit ))
938
+ goto tx_err ;
939
+ break ;
940
+ default :
941
+ memcpy (& fl6 , & t -> fl .u .ip6 , sizeof (fl6 ));
942
+ break ;
943
+ }
944
+
945
+ erspan_build_header (skb , t -> parms .o_key , t -> parms .index ,
946
+ truncate , false);
947
+ fl6 .daddr = t -> parms .raddr ;
948
+ }
889
949
890
950
/* Push GRE header. */
891
951
gre_build_header (skb , 8 , TUNNEL_SEQ ,
892
952
htons (ETH_P_ERSPAN ), 0 , htonl (t -> o_seqno ++ ));
893
953
894
954
/* TooBig packet may have updated dst->dev's mtu */
895
- if (dst && dst_mtu (dst ) > dst -> dev -> mtu )
955
+ if (! t -> parms . collect_md && dst && dst_mtu (dst ) > dst -> dev -> mtu )
896
956
dst -> ops -> update_pmtu (dst , NULL , skb , dst -> dev -> mtu );
897
957
898
958
err = ip6_tnl_xmit (skb , dev , dsfield , & fl6 , encap_limit , & mtu ,
0 commit comments