]> git.ipfire.org Git - thirdparty/iproute2.git/commitdiff
erspan: add erspan version II support
authorWilliam Tu <u9012063@gmail.com>
Wed, 20 Dec 2017 02:01:06 +0000 (18:01 -0800)
committerDavid Ahern <dsahern@gmail.com>
Wed, 20 Dec 2017 23:18:04 +0000 (15:18 -0800)
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>
ip/link_gre.c
ip/link_gre6.c
man/man8/ip-link.8.in

index 43cb1af6196a1aa0b64cf3e7efd4ad115ae0347c..0b9c71baebafe0303f972dee34ba4d4d817830ce 100644 (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] &&
index 2cb46ca116d0bb918de9482364c6e9559cb5e1b8..e4a8e1f5ee41339575f01b1d3f2ec82badc13c73 100644 (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] &&
index 9e9a5f0d2cefbe4e87f50175997befe98974a917..0086b3dfa09dab9e40265eec52671b4c11a9db18 100644 (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