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.
For details of version II, see https://tools.ietf.org/html/draft-foschiano-erspan-03 Signed-off-by: William Tu <u9012...@gmail.com> --- include/uapi/linux/if_ether.h | 1 + include/uapi/linux/if_tunnel.h | 3 +++ ip/link_gre.c | 59 +++++++++++++++++++++++++++++++++++++--- ip/link_gre6.c | 61 +++++++++++++++++++++++++++++++++++++++--- 4 files changed, 117 insertions(+), 7 deletions(-) diff --git a/include/uapi/linux/if_ether.h b/include/uapi/linux/if_ether.h index 2eb529a90250..5fd5c12ef8e9 100644 --- a/include/uapi/linux/if_ether.h +++ b/include/uapi/linux/if_ether.h @@ -47,6 +47,7 @@ #define ETH_P_PUP 0x0200 /* Xerox PUP packet */ #define ETH_P_PUPAT 0x0201 /* Xerox PUP Addr Trans packet */ #define ETH_P_TSN 0x22F0 /* TSN (IEEE 1722) packet */ +#define ETH_P_ERsPAN2 0x22EB /* ERSPAN version 2 (type III) */ #define ETH_P_IP 0x0800 /* Internet Protocol packet */ #define ETH_P_X25 0x0805 /* CCITT X.25 */ #define ETH_P_ARP 0x0806 /* Address Resolution packet */ diff --git a/include/uapi/linux/if_tunnel.h b/include/uapi/linux/if_tunnel.h index 38cdf90692f8..29602df037e9 100644 --- a/include/uapi/linux/if_tunnel.h +++ b/include/uapi/linux/if_tunnel.h @@ -137,6 +137,9 @@ enum { IFLA_GRE_IGNORE_DF, IFLA_GRE_FWMARK, IFLA_GRE_ERSPAN_INDEX, + IFLA_GRE_ERSPAN_VER, + IFLA_GRE_ERSPAN_DIR, + IFLA_GRE_ERSPAN_HWID, __IFLA_GRE_MAX, }; diff --git a/ip/link_gre.c b/ip/link_gre.c index 43cb1af6196a..924a05530f5c 100644 --- a/ip/link_gre.c +++ b/ip/link_gre.c @@ -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,22 @@ 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 (get_u8(&erspan_dir, *argv, 0)) + invarg("invalid erspan direction\n", *argv); + if (erspan_dir != 0 && erspan_dir != 1) + invarg("erspan direction must be 0(Ingress) or 1(Egress)\n", *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 +402,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 +549,25 @@ 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]); + + print_uint(PRINT_ANY, "erspan_dir", "erspan_dir %u", erspan_dir); + } + + 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 %x", erspan_hwid); } if (tb[IFLA_GRE_ENCAP_TYPE] && diff --git a/ip/link_gre6.c b/ip/link_gre6.c index 2cb46ca116d0..71181af91bc8 100644 --- a/ip/link_gre6.c +++ b/ip/link_gre6.c @@ -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,22 @@ 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 (get_u8(&erspan_dir, *argv, 0)) + invarg("invalid erspan direction\n", *argv); + if (erspan_dir != 0 && erspan_dir != 1) + invarg("erspan direction must be 0(Ingress) or 1(Egress)\n", *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 +436,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,9 +621,28 @@ 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]); + + print_uint(PRINT_ANY, "erspan_dir", "erspan_dir %u", erspan_dir); + } + + 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 %x", erspan_hwid); + } + + if (tb[IFLA_GRE_ENCAP_TYPE] && rta_getattr_u16(tb[IFLA_GRE_ENCAP_TYPE]) != TUNNEL_ENCAP_NONE) { __u16 type = rta_getattr_u16(tb[IFLA_GRE_ENCAP_TYPE]); -- 2.7.4