@@ -553,13 +553,28 @@ static int ip6erspan_rcv(struct sk_buff *skb, int gre_hdr_len,
553
553
return PACKET_REJECT ;
554
554
555
555
memcpy (md , pkt_md , sizeof (* md ));
556
+ md -> version = ver ;
556
557
info -> key .tun_flags |= TUNNEL_ERSPAN_OPT ;
557
558
info -> options_len = sizeof (* md );
558
559
559
560
ip6_tnl_rcv (tunnel , skb , tpi , tun_dst , log_ecn_error );
560
561
561
562
} else {
562
- tunnel -> parms .index = ntohl (pkt_md -> u .index );
563
+ tunnel -> parms .erspan_ver = ver ;
564
+
565
+ if (ver == 1 ) {
566
+ tunnel -> parms .index = ntohl (pkt_md -> u .index );
567
+ } else {
568
+ u16 md2_flags ;
569
+ u16 dir , hwid ;
570
+
571
+ md2_flags = ntohs (pkt_md -> u .md2 .flags );
572
+ dir = (md2_flags & DIR_MASK ) >> DIR_OFFSET ;
573
+ hwid = (md2_flags & HWID_MASK ) >> HWID_OFFSET ;
574
+ tunnel -> parms .dir = dir ;
575
+ tunnel -> parms .hwid = hwid ;
576
+ }
577
+
563
578
ip6_tnl_rcv (tunnel , skb , tpi , NULL , log_ecn_error );
564
579
}
565
580
@@ -582,7 +597,8 @@ static int gre_rcv(struct sk_buff *skb)
582
597
if (iptunnel_pull_header (skb , hdr_len , tpi .proto , false))
583
598
goto drop ;
584
599
585
- if (unlikely (tpi .proto == htons (ETH_P_ERSPAN ))) {
600
+ if (unlikely (tpi .proto == htons (ETH_P_ERSPAN ) ||
601
+ tpi .proto == htons (ETH_P_ERSPAN2 ))) {
586
602
if (ip6erspan_rcv (skb , hdr_len , & tpi ) == PACKET_RCVD )
587
603
return 0 ;
588
604
goto drop ;
@@ -927,9 +943,24 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,
927
943
if (!md )
928
944
goto tx_err ;
929
945
930
- erspan_build_header (skb , tunnel_id_to_key32 (key -> tun_id ),
931
- ntohl (md -> u .index ), truncate , false);
932
-
946
+ if (md -> version == 1 ) {
947
+ erspan_build_header (skb ,
948
+ tunnel_id_to_key32 (key -> tun_id ),
949
+ ntohl (md -> u .index ), truncate ,
950
+ false);
951
+ } else if (md -> version == 2 ) {
952
+ u16 md2_flags ;
953
+ u16 dir , hwid ;
954
+
955
+ md2_flags = ntohs (md -> u .md2 .flags );
956
+ dir = (md2_flags & DIR_MASK ) >> DIR_OFFSET ;
957
+ hwid = (md2_flags & HWID_MASK ) >> HWID_OFFSET ;
958
+
959
+ erspan_build_header_v2 (skb ,
960
+ tunnel_id_to_key32 (key -> tun_id ),
961
+ dir , hwid , truncate ,
962
+ false);
963
+ }
933
964
} else {
934
965
switch (skb -> protocol ) {
935
966
case htons (ETH_P_IP ):
@@ -949,8 +980,15 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,
949
980
break ;
950
981
}
951
982
952
- erspan_build_header (skb , t -> parms .o_key , t -> parms .index ,
953
- truncate , false);
983
+ if (t -> parms .erspan_ver == 1 )
984
+ erspan_build_header (skb , t -> parms .o_key ,
985
+ t -> parms .index ,
986
+ truncate , false);
987
+ else
988
+ erspan_build_header_v2 (skb , t -> parms .o_key ,
989
+ t -> parms .dir ,
990
+ t -> parms .hwid ,
991
+ truncate , false);
954
992
fl6 .daddr = t -> parms .raddr ;
955
993
}
956
994
@@ -1514,7 +1552,7 @@ static int ip6erspan_tap_validate(struct nlattr *tb[], struct nlattr *data[],
1514
1552
struct netlink_ext_ack * extack )
1515
1553
{
1516
1554
__be16 flags = 0 ;
1517
- int ret ;
1555
+ int ret , ver = 0 ;
1518
1556
1519
1557
if (!data )
1520
1558
return 0 ;
@@ -1543,12 +1581,35 @@ static int ip6erspan_tap_validate(struct nlattr *tb[], struct nlattr *data[],
1543
1581
(ntohl (nla_get_be32 (data [IFLA_GRE_OKEY ])) & ~ID_MASK ))
1544
1582
return - EINVAL ;
1545
1583
1546
- if (data [IFLA_GRE_ERSPAN_INDEX ]) {
1547
- u32 index = nla_get_u32 (data [IFLA_GRE_ERSPAN_INDEX ]);
1548
-
1549
- if (index & ~INDEX_MASK )
1584
+ if (data [IFLA_GRE_ERSPAN_VER ]) {
1585
+ ver = nla_get_u8 (data [IFLA_GRE_ERSPAN_VER ]);
1586
+ if (ver != 1 && ver != 2 )
1550
1587
return - EINVAL ;
1551
1588
}
1589
+
1590
+ if (ver == 1 ) {
1591
+ if (data [IFLA_GRE_ERSPAN_INDEX ]) {
1592
+ u32 index = nla_get_u32 (data [IFLA_GRE_ERSPAN_INDEX ]);
1593
+
1594
+ if (index & ~INDEX_MASK )
1595
+ return - EINVAL ;
1596
+ }
1597
+ } else if (ver == 2 ) {
1598
+ if (data [IFLA_GRE_ERSPAN_DIR ]) {
1599
+ u16 dir = nla_get_u8 (data [IFLA_GRE_ERSPAN_DIR ]);
1600
+
1601
+ if (dir & ~(DIR_MASK >> DIR_OFFSET ))
1602
+ return - EINVAL ;
1603
+ }
1604
+
1605
+ if (data [IFLA_GRE_ERSPAN_HWID ]) {
1606
+ u16 hwid = nla_get_u16 (data [IFLA_GRE_ERSPAN_HWID ]);
1607
+
1608
+ if (hwid & ~(HWID_MASK >> HWID_OFFSET ))
1609
+ return - EINVAL ;
1610
+ }
1611
+ }
1612
+
1552
1613
return 0 ;
1553
1614
}
1554
1615
@@ -1598,11 +1659,21 @@ static void ip6gre_netlink_parms(struct nlattr *data[],
1598
1659
if (data [IFLA_GRE_FWMARK ])
1599
1660
parms -> fwmark = nla_get_u32 (data [IFLA_GRE_FWMARK ]);
1600
1661
1601
- if (data [IFLA_GRE_ERSPAN_INDEX ])
1602
- parms -> index = nla_get_u32 (data [IFLA_GRE_ERSPAN_INDEX ]);
1603
-
1604
1662
if (data [IFLA_GRE_COLLECT_METADATA ])
1605
1663
parms -> collect_md = true;
1664
+
1665
+ if (data [IFLA_GRE_ERSPAN_VER ])
1666
+ parms -> erspan_ver = nla_get_u8 (data [IFLA_GRE_ERSPAN_VER ]);
1667
+
1668
+ if (parms -> erspan_ver == 1 ) {
1669
+ if (data [IFLA_GRE_ERSPAN_INDEX ])
1670
+ parms -> index = nla_get_u32 (data [IFLA_GRE_ERSPAN_INDEX ]);
1671
+ } else if (parms -> erspan_ver == 2 ) {
1672
+ if (data [IFLA_GRE_ERSPAN_DIR ])
1673
+ parms -> dir = nla_get_u8 (data [IFLA_GRE_ERSPAN_DIR ]);
1674
+ if (data [IFLA_GRE_ERSPAN_HWID ])
1675
+ parms -> hwid = nla_get_u16 (data [IFLA_GRE_ERSPAN_HWID ]);
1676
+ }
1606
1677
}
1607
1678
1608
1679
static int ip6gre_tap_init (struct net_device * dev )
@@ -1664,7 +1735,7 @@ static int ip6erspan_tap_init(struct net_device *dev)
1664
1735
1665
1736
tunnel -> tun_hlen = 8 ;
1666
1737
tunnel -> hlen = tunnel -> tun_hlen + tunnel -> encap_hlen +
1667
- sizeof ( struct erspan_base_hdr ) + ERSPAN_V1_MDSIZE ;
1738
+ erspan_hdr_len ( tunnel -> parms . erspan_ver ) ;
1668
1739
t_hlen = tunnel -> hlen + sizeof (struct ipv6hdr );
1669
1740
1670
1741
dev -> hard_header_len = LL_MAX_HEADER + t_hlen ;
@@ -1932,6 +2003,19 @@ static int ip6gre_fill_info(struct sk_buff *skb, const struct net_device *dev)
1932
2003
goto nla_put_failure ;
1933
2004
}
1934
2005
2006
+ if (nla_put_u8 (skb , IFLA_GRE_ERSPAN_VER , p -> erspan_ver ))
2007
+ goto nla_put_failure ;
2008
+
2009
+ if (p -> erspan_ver == 1 ) {
2010
+ if (nla_put_u32 (skb , IFLA_GRE_ERSPAN_INDEX , p -> index ))
2011
+ goto nla_put_failure ;
2012
+ } else if (p -> erspan_ver == 2 ) {
2013
+ if (nla_put_u8 (skb , IFLA_GRE_ERSPAN_DIR , p -> dir ))
2014
+ goto nla_put_failure ;
2015
+ if (nla_put_u16 (skb , IFLA_GRE_ERSPAN_HWID , p -> hwid ))
2016
+ goto nla_put_failure ;
2017
+ }
2018
+
1935
2019
return 0 ;
1936
2020
1937
2021
nla_put_failure :
@@ -1957,6 +2041,9 @@ static const struct nla_policy ip6gre_policy[IFLA_GRE_MAX + 1] = {
1957
2041
[IFLA_GRE_COLLECT_METADATA ] = { .type = NLA_FLAG },
1958
2042
[IFLA_GRE_FWMARK ] = { .type = NLA_U32 },
1959
2043
[IFLA_GRE_ERSPAN_INDEX ] = { .type = NLA_U32 },
2044
+ [IFLA_GRE_ERSPAN_VER ] = { .type = NLA_U8 },
2045
+ [IFLA_GRE_ERSPAN_DIR ] = { .type = NLA_U8 },
2046
+ [IFLA_GRE_ERSPAN_HWID ] = { .type = NLA_U16 },
1960
2047
};
1961
2048
1962
2049
static void ip6erspan_tap_setup (struct net_device * dev )
2078
2165
MODULE_DESCRIPTION ("GRE over IPv6 tunneling device" );
2079
2166
MODULE_ALIAS_RTNL_LINK ("ip6gre" );
2080
2167
MODULE_ALIAS_RTNL_LINK ("ip6gretap" );
2168
+ MODULE_ALIAS_RTNL_LINK ("ip6erspan" );
2081
2169
MODULE_ALIAS_NETDEV ("ip6gre0" );
0 commit comments