erspan: add erspan version II support

The patch adds support for configuring the erspan v2, for both
ipv4 and ipv6 erspan implementation.  Three additional fields
are added: 'erspan_ver' for distinguishing v1 or v2, 'erspan_dir'
for specifying direction of the mirrored traffic, and 'erspan_hwid'
for users to set ERSPAN engine ID within a system.

As for manpage, the ERSPAN descriptions used to be under GRE, IPIP,
SIT Type paragraph.  Since IP6GRE/IP6GRETAP also supports ERSPAN,
the patch removes the old one, creates a separate ERSPAN paragrah,
and adds an example.

Signed-off-by: William Tu <u9012063@gmail.com>
Signed-off-by: David Ahern <dsahern@gmail.com>
This commit is contained in:
William Tu 2017-12-19 18:01:06 -08:00 committed by David Ahern
parent f82517f80d
commit 2897636267
3 changed files with 206 additions and 19 deletions

View File

@ -98,6 +98,9 @@ static int gre_parse_opt(struct link_util *lu, int argc, char **argv,
__u8 ignore_df = 0;
__u32 fwmark = 0;
__u32 erspan_idx = 0;
__u8 erspan_ver = 0;
__u8 erspan_dir = 0;
__u16 erspan_hwid = 0;
if (!(n->nlmsg_flags & NLM_F_CREATE)) {
if (rtnl_talk(&rth, &req.n, &answer) < 0) {
@ -179,6 +182,15 @@ get_failed:
if (greinfo[IFLA_GRE_ERSPAN_INDEX])
erspan_idx = rta_getattr_u32(greinfo[IFLA_GRE_ERSPAN_INDEX]);
if (greinfo[IFLA_GRE_ERSPAN_VER])
erspan_ver = rta_getattr_u8(greinfo[IFLA_GRE_ERSPAN_VER]);
if (greinfo[IFLA_GRE_ERSPAN_DIR])
erspan_dir = rta_getattr_u8(greinfo[IFLA_GRE_ERSPAN_DIR]);
if (greinfo[IFLA_GRE_ERSPAN_HWID])
erspan_hwid = rta_getattr_u16(greinfo[IFLA_GRE_ERSPAN_HWID]);
free(answer);
}
@ -343,6 +355,24 @@ get_failed:
invarg("invalid erspan index\n", *argv);
if (erspan_idx & ~((1<<20) - 1) || erspan_idx == 0)
invarg("erspan index must be > 0 and <= 20-bit\n", *argv);
} else if (strcmp(*argv, "erspan_ver") == 0) {
NEXT_ARG();
if (get_u8(&erspan_ver, *argv, 0))
invarg("invalid erspan version\n", *argv);
if (erspan_ver != 1 && erspan_ver != 2)
invarg("erspan version must be 1 or 2\n", *argv);
} else if (strcmp(*argv, "erspan_dir") == 0) {
NEXT_ARG();
if (matches(*argv, "ingress") == 0)
erspan_dir = 0;
else if (matches(*argv, "egress") == 0)
erspan_dir = 1;
else
invarg("Invalid erspan direction.", *argv);
} else if (strcmp(*argv, "erspan_hwid") == 0) {
NEXT_ARG();
if (get_u16(&erspan_hwid, *argv, 0))
invarg("invalid erspan hwid\n", *argv);
} else
usage();
argc--; argv++;
@ -374,8 +404,15 @@ get_failed:
addattr_l(n, 1024, IFLA_GRE_TTL, &ttl, 1);
addattr_l(n, 1024, IFLA_GRE_TOS, &tos, 1);
addattr32(n, 1024, IFLA_GRE_FWMARK, fwmark);
if (erspan_idx != 0)
addattr32(n, 1024, IFLA_GRE_ERSPAN_INDEX, erspan_idx);
if (erspan_ver) {
addattr8(n, 1024, IFLA_GRE_ERSPAN_VER, erspan_ver);
if (erspan_ver == 1 && erspan_idx != 0) {
addattr32(n, 1024, IFLA_GRE_ERSPAN_INDEX, erspan_idx);
} else if (erspan_ver == 2) {
addattr8(n, 1024, IFLA_GRE_ERSPAN_DIR, erspan_dir);
addattr16(n, 1024, IFLA_GRE_ERSPAN_HWID, erspan_hwid);
}
}
} else {
addattr_l(n, 1024, IFLA_GRE_COLLECT_METADATA, NULL, 0);
}
@ -514,7 +551,30 @@ static void gre_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
if (tb[IFLA_GRE_ERSPAN_INDEX]) {
__u32 erspan_idx = rta_getattr_u32(tb[IFLA_GRE_ERSPAN_INDEX]);
fprintf(f, "erspan_index %u ", erspan_idx);
print_uint(PRINT_ANY, "erspan_index", "erspan_index %u ", erspan_idx);
}
if (tb[IFLA_GRE_ERSPAN_VER]) {
__u8 erspan_ver = rta_getattr_u8(tb[IFLA_GRE_ERSPAN_VER]);
print_uint(PRINT_ANY, "erspan_ver", "erspan_ver %u ", erspan_ver);
}
if (tb[IFLA_GRE_ERSPAN_DIR]) {
__u8 erspan_dir = rta_getattr_u8(tb[IFLA_GRE_ERSPAN_DIR]);
if (erspan_dir == 0)
print_string(PRINT_ANY, "erspan_dir",
"erspan_dir ingress ", NULL);
else
print_string(PRINT_ANY, "erspan_dir",
"erspan_dir egress ", NULL);
}
if (tb[IFLA_GRE_ERSPAN_HWID]) {
__u16 erspan_hwid = rta_getattr_u16(tb[IFLA_GRE_ERSPAN_HWID]);
print_hex(PRINT_ANY, "erspan_hwid", "erspan_hwid 0x%x ", erspan_hwid);
}
if (tb[IFLA_GRE_ENCAP_TYPE] &&

View File

@ -109,6 +109,9 @@ static int gre_parse_opt(struct link_util *lu, int argc, char **argv,
int len;
__u32 fwmark = 0;
__u32 erspan_idx = 0;
__u8 erspan_ver = 0;
__u8 erspan_dir = 0;
__u16 erspan_hwid = 0;
if (!(n->nlmsg_flags & NLM_F_CREATE)) {
if (rtnl_talk(&rth, &req.n, &answer) < 0) {
@ -191,6 +194,15 @@ get_failed:
if (greinfo[IFLA_GRE_ERSPAN_INDEX])
erspan_idx = rta_getattr_u32(greinfo[IFLA_GRE_ERSPAN_INDEX]);
if (greinfo[IFLA_GRE_ERSPAN_VER])
erspan_ver = rta_getattr_u8(greinfo[IFLA_GRE_ERSPAN_VER]);
if (greinfo[IFLA_GRE_ERSPAN_DIR])
erspan_dir = rta_getattr_u8(greinfo[IFLA_GRE_ERSPAN_DIR]);
if (greinfo[IFLA_GRE_ERSPAN_HWID])
erspan_hwid = rta_getattr_u16(greinfo[IFLA_GRE_ERSPAN_HWID]);
free(answer);
}
@ -389,6 +401,24 @@ get_failed:
invarg("invalid erspan index\n", *argv);
if (erspan_idx & ~((1<<20) - 1) || erspan_idx == 0)
invarg("erspan index must be > 0 and <= 20-bit\n", *argv);
} else if (strcmp(*argv, "erspan_ver") == 0) {
NEXT_ARG();
if (get_u8(&erspan_ver, *argv, 0))
invarg("invalid erspan version\n", *argv);
if (erspan_ver != 1 && erspan_ver != 2)
invarg("erspan version must be 1 or 2\n", *argv);
} else if (strcmp(*argv, "erspan_dir") == 0) {
NEXT_ARG();
if (matches(*argv, "ingress") == 0)
erspan_dir = 0;
else if (matches(*argv, "egress") == 0)
erspan_dir = 1;
else
invarg("Invalid erspan direction.", *argv);
} else if (strcmp(*argv, "erspan_hwid") == 0) {
NEXT_ARG();
if (get_u16(&erspan_hwid, *argv, 0))
invarg("invalid erspan hwid\n", *argv);
} else
usage();
argc--; argv++;
@ -408,9 +438,15 @@ get_failed:
addattr_l(n, 1024, IFLA_GRE_FLOWINFO, &flowinfo, 4);
addattr32(n, 1024, IFLA_GRE_FLAGS, flags);
addattr32(n, 1024, IFLA_GRE_FWMARK, fwmark);
if (erspan_idx != 0)
addattr32(n, 1024, IFLA_GRE_ERSPAN_INDEX, erspan_idx);
if (erspan_ver) {
addattr8(n, 1024, IFLA_GRE_ERSPAN_VER, erspan_ver);
if (erspan_ver == 1 && erspan_idx != 0) {
addattr32(n, 1024, IFLA_GRE_ERSPAN_INDEX, erspan_idx);
} else {
addattr8(n, 1024, IFLA_GRE_ERSPAN_DIR, erspan_dir);
addattr16(n, 1024, IFLA_GRE_ERSPAN_HWID, erspan_hwid);
}
}
addattr16(n, 1024, IFLA_GRE_ENCAP_TYPE, encaptype);
addattr16(n, 1024, IFLA_GRE_ENCAP_FLAGS, encapflags);
addattr16(n, 1024, IFLA_GRE_ENCAP_SPORT, htons(encapsport));
@ -587,7 +623,30 @@ static void gre_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
if (tb[IFLA_GRE_ERSPAN_INDEX]) {
__u32 erspan_idx = rta_getattr_u32(tb[IFLA_GRE_ERSPAN_INDEX]);
fprintf(f, "erspan_index %u ", erspan_idx);
print_uint(PRINT_ANY, "erspan_index", "erspan_index %u ", erspan_idx);
}
if (tb[IFLA_GRE_ERSPAN_VER]) {
__u8 erspan_ver = rta_getattr_u8(tb[IFLA_GRE_ERSPAN_VER]);
print_uint(PRINT_ANY, "erspan_ver", "erspan_ver %u ", erspan_ver);
}
if (tb[IFLA_GRE_ERSPAN_DIR]) {
__u8 erspan_dir = rta_getattr_u8(tb[IFLA_GRE_ERSPAN_DIR]);
if (erspan_dir == 0)
print_string(PRINT_ANY, "erspan_dir",
"erspan_dir ingress ", NULL);
else
print_string(PRINT_ANY, "erspan_dir",
"erspan_dir egress ", NULL);
}
if (tb[IFLA_GRE_ERSPAN_HWID]) {
__u16 erspan_hwid = rta_getattr_u16(tb[IFLA_GRE_ERSPAN_HWID]);
print_hex(PRINT_ANY, "erspan_hwid", "erspan_hwid 0x%x ", erspan_hwid);
}
if (tb[IFLA_GRE_ENCAP_TYPE] &&

View File

@ -665,13 +665,13 @@ keyword.
.in -8
.TP
GRE, IPIP, SIT, ERSPAN Type Support
GRE, IPIP, SIT Type Support
For a link of types
.I GRE/IPIP/SIT/ERSPAN
.I GRE/IPIP/SIT
the following additional arguments are supported:
.BI "ip link add " DEVICE
.BR type " { " gre " | " ipip " | " sit " | " erspan " }"
.BR type " { " gre " | " ipip " | " sit " }"
.BI " remote " ADDR " local " ADDR
[
.BR encap " { " fou " | " gue " | " none " }"
@ -685,8 +685,6 @@ the following additional arguments are supported:
.I " [no]encap-remcsum "
] [
.I " mode " { ip6ip | ipip | mplsip | any } "
] [
.BR erspan " \fIIDX "
]
.in +8
@ -731,13 +729,6 @@ MPLS-Over-IPv4, "any" indicates IPv6, IPv4 or MPLS Over IPv4. Supported for
SIT where the default is "ip6ip" and IPIP where the default is "ipip".
IPv6-Over-IPv4 is not supported for IPIP.
.sp
.BR erspan " \fIIDX "
- specifies the ERSPAN index field.
.IR IDX
indicates a 20 bit index/port number associated with the ERSPAN
traffic's source port and direction.
.in -8
.TP
@ -882,6 +873,76 @@ the following additional arguments are supported:
.BI mode " MODE "
- specifies the mode (datagram or connected) to use.
.TP
ERSPAN Type Support
For a link of type
.I ERSPAN/IP6ERSPAN
the following additional arguments are supported:
.BI "ip link add " DEVICE
.BR type " { " erspan " | " ip6erspan " }"
.BI remote " ADDR " local " ADDR " seq
.RB key
.I KEY
.BR erspan_ver " \fIversion "
[
.BR erspan " \fIIDX "
] [
.BR erspan_dir " { " \fIingress " | " \fIegress " }"
] [
.BR erspan_hwid " \fIhwid "
] [
.RB external
]
.in +8
.sp
.BI remote " ADDR "
- specifies the remote address of the tunnel.
.sp
.BI local " ADDR "
- specifies the fixed local address for tunneled packets.
It must be an address on another interface on this host.
.sp
.BR erspan_ver " \fIversion "
- specifies the ERSPAN version number.
.IR version
indicates the ERSPAN version to be created: 1 for version 1 (type II)
or 2 for version 2 (type III).
.sp
.BR erspan " \fIIDX "
- specifies the ERSPAN v1 index field.
.IR IDX
indicates a 20 bit index/port number associated with the ERSPAN
traffic's source port and direction.
.sp
.BR erspan_dir " { " \fIingress " | " \fIegress " }"
- specifies the ERSPAN v2 mirrored traffic's direction.
.sp
.BR erspan_hwid " \fIhwid "
- an unique identifier of an ERSPAN v2 engine within a system.
.IR hwid
is a 6-bit value for users to configure.
.sp
.BR external
- make this tunnel externally controlled (or not, which is the default).
In the kernel, this is referred to as collect metadata mode. This flag is
mutually exclusive with the
.BR remote ,
.BR local ,
.BR erspan_ver ,
.BR erspan ,
.BR erspan_dir " and " erspan_hwid
options.
.in -8
.TP
GENEVE Type Support
For a link of type
@ -2062,6 +2123,13 @@ ip link add link wpan0 lowpan0 type lowpan
Creates a 6LoWPAN interface named lowpan0 on the underlying
IEEE 802.15.4 device wpan0.
.RE
.PP
ip link add dev ip6erspan11 type ip6erspan seq key 102
local fc00:100::2 remote fc00:100::1
erspan_ver 2 erspan_dir ingress erspan_hwid 17
.RS 4
Creates a IP6ERSPAN version 2 interface named ip6erspan00.
.RE
.SH SEE ALSO
.br