Skip to content

Commit 94d7d8f

Browse files
williamtudavem330
authored andcommitted
ip6_gre: add erspan v2 support
Similar to support for ipv4 erspan, this patch adds erspan v2 to ip6erspan tunnel. Signed-off-by: William Tu <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent f551c91 commit 94d7d8f

File tree

2 files changed

+107
-16
lines changed

2 files changed

+107
-16
lines changed

include/net/ip6_tunnel.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ struct __ip6_tnl_parm {
3737

3838
__u32 fwmark;
3939
__u32 index; /* ERSPAN type II index */
40+
__u8 erspan_ver; /* ERSPAN version */
41+
__u8 dir; /* direction */
42+
__u16 hwid; /* hwid */
4043
};
4144

4245
/* IPv6 tunnel */

net/ipv6/ip6_gre.c

Lines changed: 104 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -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

16081679
static 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

19372021
nla_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

19622049
static void ip6erspan_tap_setup(struct net_device *dev)
@@ -2078,4 +2165,5 @@ MODULE_AUTHOR("D. Kozlov ([email protected])");
20782165
MODULE_DESCRIPTION("GRE over IPv6 tunneling device");
20792166
MODULE_ALIAS_RTNL_LINK("ip6gre");
20802167
MODULE_ALIAS_RTNL_LINK("ip6gretap");
2168+
MODULE_ALIAS_RTNL_LINK("ip6erspan");
20812169
MODULE_ALIAS_NETDEV("ip6gre0");

0 commit comments

Comments
 (0)