@@ -553,13 +553,28 @@ static int ip6erspan_rcv(struct sk_buff *skb, int gre_hdr_len,
553553 return PACKET_REJECT ;
554554
555555 memcpy (md , pkt_md , sizeof (* md ));
556+ md -> version = ver ;
556557 info -> key .tun_flags |= TUNNEL_ERSPAN_OPT ;
557558 info -> options_len = sizeof (* md );
558559
559560 ip6_tnl_rcv (tunnel , skb , tpi , tun_dst , log_ecn_error );
560561
561562 } 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+
563578 ip6_tnl_rcv (tunnel , skb , tpi , NULL , log_ecn_error );
564579 }
565580
@@ -582,7 +597,8 @@ static int gre_rcv(struct sk_buff *skb)
582597 if (iptunnel_pull_header (skb , hdr_len , tpi .proto , false))
583598 goto drop ;
584599
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 ))) {
586602 if (ip6erspan_rcv (skb , hdr_len , & tpi ) == PACKET_RCVD )
587603 return 0 ;
588604 goto drop ;
@@ -927,9 +943,24 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,
927943 if (!md )
928944 goto tx_err ;
929945
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+ }
933964 } else {
934965 switch (skb -> protocol ) {
935966 case htons (ETH_P_IP ):
@@ -949,8 +980,15 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,
949980 break ;
950981 }
951982
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);
954992 fl6 .daddr = t -> parms .raddr ;
955993 }
956994
@@ -1514,7 +1552,7 @@ static int ip6erspan_tap_validate(struct nlattr *tb[], struct nlattr *data[],
15141552 struct netlink_ext_ack * extack )
15151553{
15161554 __be16 flags = 0 ;
1517- int ret ;
1555+ int ret , ver = 0 ;
15181556
15191557 if (!data )
15201558 return 0 ;
@@ -1543,12 +1581,35 @@ static int ip6erspan_tap_validate(struct nlattr *tb[], struct nlattr *data[],
15431581 (ntohl (nla_get_be32 (data [IFLA_GRE_OKEY ])) & ~ID_MASK ))
15441582 return - EINVAL ;
15451583
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 )
15501587 return - EINVAL ;
15511588 }
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+
15521613 return 0 ;
15531614}
15541615
@@ -1598,11 +1659,21 @@ static void ip6gre_netlink_parms(struct nlattr *data[],
15981659 if (data [IFLA_GRE_FWMARK ])
15991660 parms -> fwmark = nla_get_u32 (data [IFLA_GRE_FWMARK ]);
16001661
1601- if (data [IFLA_GRE_ERSPAN_INDEX ])
1602- parms -> index = nla_get_u32 (data [IFLA_GRE_ERSPAN_INDEX ]);
1603-
16041662 if (data [IFLA_GRE_COLLECT_METADATA ])
16051663 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+ }
16061677}
16071678
16081679static int ip6gre_tap_init (struct net_device * dev )
@@ -1664,7 +1735,7 @@ static int ip6erspan_tap_init(struct net_device *dev)
16641735
16651736 tunnel -> tun_hlen = 8 ;
16661737 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 ) ;
16681739 t_hlen = tunnel -> hlen + sizeof (struct ipv6hdr );
16691740
16701741 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)
19322003 goto nla_put_failure ;
19332004 }
19342005
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+
19352019 return 0 ;
19362020
19372021nla_put_failure :
@@ -1957,6 +2041,9 @@ static const struct nla_policy ip6gre_policy[IFLA_GRE_MAX + 1] = {
19572041 [IFLA_GRE_COLLECT_METADATA ] = { .type = NLA_FLAG },
19582042 [IFLA_GRE_FWMARK ] = { .type = NLA_U32 },
19592043 [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 },
19602047};
19612048
19622049static void ip6erspan_tap_setup (struct net_device * dev )
@@ -2078,4 +2165,5 @@ MODULE_AUTHOR("D. Kozlov (xeb@mail.ru)");
20782165MODULE_DESCRIPTION ("GRE over IPv6 tunneling device" );
20792166MODULE_ALIAS_RTNL_LINK ("ip6gre" );
20802167MODULE_ALIAS_RTNL_LINK ("ip6gretap" );
2168+ MODULE_ALIAS_RTNL_LINK ("ip6erspan" );
20812169MODULE_ALIAS_NETDEV ("ip6gre0" );
0 commit comments