From 1f3aea766d9bac15e39df06397943a261c10d17e Mon Sep 17 00:00:00 2001 From: Guangbin Huang Date: Wed, 1 Jun 2022 15:22:57 +0800 Subject: [PATCH] ethtool: add suppport specifications for vxlan by ethtool -u/-U This patch adds two flow type of vxlan4(VxLAN with inner IPv4) and vxlan6 (VxLAN with inner IPv6) for command ethtool -u/-U to get/set specifications of VxLAN. category:Feature bugzilla:https://gitee.com/src-openeuler/ethtool/issues/I624AU Signed-off-by: Guangbin Huang Signed-off-by: Jiantao Xiao --- configure.ac | 10 +++ ethtool.c | 5 ++ rxclass.c | 205 +++++++++++++++++++++++++++++++++++++++++++ uapi/linux/ethtool.h | 56 ++++++++++++ 4 files changed, 276 insertions(+) diff --git a/configure.ac b/configure.ac index 89d0e70..9c4aea4 100644 --- a/configure.ac +++ b/configure.ac @@ -78,5 +78,15 @@ if test x$enable_netlink = xyes; then fi AM_CONDITIONAL([ETHTOOL_ENABLE_NETLINK], [test x$enable_netlink = xyes]) +AC_ARG_ENABLE(fd-vxlan, + [ --enable-fd-vxlan enable fd vxlan interface (enabled by default)], + , + enable_fd_vxlan=no) +if test x$enable_fd_vxlan = xyes; then + AC_DEFINE(ETHTOOL_FD_VXLAN_FEATURE, 1, + Define this to enable vxlan interface to support ethtool fd vxlan.) +fi +AM_CONDITIONAL([ETHTOOL_FD_VXLAN_FEATURE], [test x$enable_fd_vxlan = xyes]) + AC_CONFIG_FILES([Makefile ethtool.spec ethtool.8]) AC_OUTPUT diff --git a/ethtool.c b/ethtool.c index 3207e49..bdd4f15 100644 --- a/ethtool.c +++ b/ethtool.c @@ -5836,7 +5836,12 @@ static const struct option args[] = { .xhelp = " rx-flow-hash tcp4|udp4|ah4|esp4|sctp4|" "tcp6|udp6|ah6|esp6|sctp6 m|v|t|s|d|f|n|r... [context %d] |\n" " flow-type ether|ip4|tcp4|udp4|sctp4|ah4|esp4|" +#ifndef ETHTOOL_FD_VXLAN_FEATURE "ip6|tcp6|udp6|ah6|esp6|sctp6\n" +#else + "ip6|tcp6|udp6|ah6|esp6|sctp6|vxlan4|vxlan6\n" + " [ vni %d [m %x] ]\n" +#endif " [ src %x:%x:%x:%x:%x:%x [m %x:%x:%x:%x:%x:%x] ]\n" " [ dst %x:%x:%x:%x:%x:%x [m %x:%x:%x:%x:%x:%x] ]\n" " [ proto %d [m %x] ]\n" diff --git a/rxclass.c b/rxclass.c index 6cf81fd..a43506b 100644 --- a/rxclass.c +++ b/rxclass.c @@ -58,6 +58,24 @@ static void rxclass_print_ipv6_rule(__be32 *sip, __be32 *sipm, __be32 *dip, tclass, tclassm); } +#ifdef ETHTOOL_FD_VXLAN_FEATURE +static void rxclass_print_eth_rule(u8 *smac, u8 *smacm, u8 *dmac, u8 *dmacm, + u16 eth_type, u16 eth_typem) +{ + fprintf(stdout, + "\tSrc MAC addr: %02X:%02X:%02X:%02X:%02X:%02X" + " mask: %02X:%02X:%02X:%02X:%02X:%02X\n" + "\tDest MAC addr: %02X:%02X:%02X:%02X:%02X:%02X" + " mask: %02X:%02X:%02X:%02X:%02X:%02X\n" + "\tEthertype: 0x%X mask: 0x%X\n", + smac[0], smac[1], smac[2], smac[3], smac[4], smac[5], + smacm[0], smacm[1], smacm[2], smacm[3], smacm[4], smacm[5], + dmac[0], dmac[1], dmac[2], dmac[3], dmac[4], dmac[5], + dmacm[0], dmacm[1], dmacm[2], dmacm[3], dmacm[4], dmacm[5], + eth_type, eth_typem); +} +#endif + static void rxclass_print_nfc_spec_ext(struct ethtool_rx_flow_spec *fsp) { if (fsp->flow_type & FLOW_EXT) { @@ -97,7 +115,9 @@ static void rxclass_print_nfc_spec_ext(struct ethtool_rx_flow_spec *fsp) static void rxclass_print_nfc_rule(struct ethtool_rx_flow_spec *fsp, __u32 rss_context) { +#ifndef ETHTOOL_FD_VXLAN_FEATURE unsigned char *smac, *smacm, *dmac, *dmacm; +#endif __u32 flow_type; fprintf(stdout, "Filter: %d\n", fsp->location); @@ -163,6 +183,29 @@ static void rxclass_print_nfc_rule(struct ethtool_rx_flow_spec *fsp, ntohl(fsp->h_u.usr_ip4_spec.l4_4_bytes), ntohl(fsp->m_u.usr_ip4_spec.l4_4_bytes)); break; +#ifdef ETHTOOL_FD_VXLAN_FEATURE + case VXLAN_V4_FLOW: + fprintf(stdout, "\tRule Type: Vxlan IPv4\n"); + fprintf(stdout, "\tVni: %d mask: 0x%x\n", + ntohl(fsp->h_u.vxlan_ip4_spec.vni), + ntohl(fsp->m_u.vxlan_ip4_spec.vni)); + rxclass_print_eth_rule(fsp->h_u.vxlan_ip4_spec.src, + fsp->m_u.vxlan_ip4_spec.src, + fsp->h_u.vxlan_ip4_spec.dst, + fsp->m_u.vxlan_ip4_spec.dst, + ntohs(fsp->h_u.vxlan_ip4_spec.eth_type), + ntohs(fsp->m_u.vxlan_ip4_spec.eth_type)); + rxclass_print_ipv4_rule(fsp->h_u.vxlan_ip4_spec.ip4src, + fsp->m_u.vxlan_ip4_spec.ip4src, + fsp->h_u.vxlan_ip4_spec.ip4dst, + fsp->m_u.vxlan_ip4_spec.ip4dst, + fsp->h_u.vxlan_ip4_spec.tos, + fsp->m_u.vxlan_ip4_spec.tos); + fprintf(stdout, "\tL4 protocol: %d mask: 0x%x\n", + fsp->h_u.vxlan_ip4_spec.l4_proto, + fsp->m_u.vxlan_ip4_spec.l4_proto); + break; +#endif case TCP_V6_FLOW: case UDP_V6_FLOW: case SCTP_V6_FLOW: @@ -219,7 +262,31 @@ static void rxclass_print_nfc_rule(struct ethtool_rx_flow_spec *fsp, ntohl(fsp->h_u.usr_ip6_spec.l4_4_bytes), ntohl(fsp->m_u.usr_ip6_spec.l4_4_bytes)); break; +#ifdef ETHTOOL_FD_VXLAN_FEATURE + case VXLAN_V6_FLOW: + fprintf(stdout, "\tRule Type: Vxlan IPv6\n"); + fprintf(stdout, "\tVni: %d mask: 0x%x\n", + ntohl(fsp->h_u.vxlan_ip6_spec.vni), + ntohl(fsp->m_u.vxlan_ip6_spec.vni)); + rxclass_print_eth_rule(fsp->h_u.vxlan_ip6_spec.src, + fsp->m_u.vxlan_ip6_spec.src, + fsp->h_u.vxlan_ip6_spec.dst, + fsp->m_u.vxlan_ip6_spec.dst, + ntohs(fsp->h_u.vxlan_ip6_spec.eth_type), + ntohs(fsp->m_u.vxlan_ip6_spec.eth_type)); + rxclass_print_ipv6_rule(fsp->h_u.vxlan_ip6_spec.ip6src, + fsp->m_u.vxlan_ip6_spec.ip6src, + fsp->h_u.vxlan_ip6_spec.ip6dst, + fsp->m_u.vxlan_ip6_spec.ip6dst, + fsp->h_u.vxlan_ip6_spec.tclass, + fsp->m_u.vxlan_ip6_spec.tclass); + fprintf(stdout, "\tL4 Protocol: %d mask: 0x%x\n", + fsp->h_u.vxlan_ip6_spec.l4_proto, + fsp->m_u.vxlan_ip6_spec.l4_proto); + break; +#endif case ETHER_FLOW: +#ifndef ETHTOOL_FD_VXLAN_FEATURE dmac = fsp->h_u.ether_spec.h_dest; dmacm = fsp->m_u.ether_spec.h_dest; smac = fsp->h_u.ether_spec.h_source; @@ -239,6 +306,15 @@ static void rxclass_print_nfc_rule(struct ethtool_rx_flow_spec *fsp, dmacm[4], dmacm[5], ntohs(fsp->h_u.ether_spec.h_proto), ntohs(fsp->m_u.ether_spec.h_proto)); +#else + fprintf(stdout, "\tFlow Type: Raw Ethernet\n"); + rxclass_print_eth_rule(fsp->h_u.ether_spec.h_source, + fsp->m_u.ether_spec.h_source, + fsp->h_u.ether_spec.h_dest, + fsp->m_u.ether_spec.h_dest, + ntohs(fsp->h_u.ether_spec.h_proto), + ntohs(fsp->m_u.ether_spec.h_proto)); +#endif break; default: fprintf(stdout, @@ -285,12 +361,18 @@ static void rxclass_print_rule(struct ethtool_rx_flow_spec *fsp, case SCTP_V4_FLOW: case AH_V4_FLOW: case ESP_V4_FLOW: +#ifdef ETHTOOL_FD_VXLAN_FEATURE + case VXLAN_V4_FLOW: +#endif case TCP_V6_FLOW: case UDP_V6_FLOW: case SCTP_V6_FLOW: case AH_V6_FLOW: case ESP_V6_FLOW: case IPV6_USER_FLOW: +#ifdef ETHTOOL_FD_VXLAN_FEATURE + case VXLAN_V6_FLOW: +#endif case ETHER_FLOW: rxclass_print_nfc_rule(fsp, rss_context); break; @@ -633,6 +715,7 @@ typedef enum { OPT_MAC, } rule_opt_type_t; +#ifndef ETHTOOL_FD_VXLAN_FEATURE #define NFC_FLAG_RING 0x0001 #define NFC_FLAG_LOC 0x0002 #define NFC_FLAG_SADDR 0x0004 @@ -648,6 +731,28 @@ typedef enum { #define NFC_FLAG_MAC_ADDR 0x0800 #define NFC_FLAG_RING_VF 0x1000 #define NFC_FLAG_RING_QUEUE 0x2000 +#else +#define NFC_FLAG_RING 0x00000001 +#define NFC_FLAG_LOC 0x00000002 +#define NFC_FLAG_SADDR 0x00000004 +#define NFC_FLAG_DADDR 0x00000008 +#define NFC_FLAG_SPORT 0x00000010 +#define NFC_FLAG_DPORT 0x00000020 +#define NFC_FLAG_SPI 0x00000030 +#define NFC_FLAG_TOS 0x00000040 +#define NFC_FLAG_PROTO 0x00000080 +#define NTUPLE_FLAG_VLAN 0x00000100 +#define NTUPLE_FLAG_UDEF 0x00000200 +#define NTUPLE_FLAG_VETH 0x00000400 +#define NFC_FLAG_MAC_ADDR 0x00000800 +#define NFC_FLAG_RING_VF 0x00001000 +#define NFC_FLAG_RING_QUEUE 0x00002000 +#define NFC_FLAG_VNI 0x00004000 +#define NFC_FLAG_SRC_IP 0x00008000 +#define NFC_FLAG_DST_IP 0x00010000 +#define NFC_FLAG_L4_PROTO 0x00020000 +#endif + struct rule_opts { const char *name; @@ -777,6 +882,46 @@ static const struct rule_opts rule_nfc_usr_ip4[] = { offsetof(struct ethtool_rx_flow_spec, m_ext.h_dest) }, }; +#ifdef ETHTOOL_FD_VXLAN_FEATURE +static const struct rule_opts rule_nfc_vxlan_ip4[] = { + { "vni", OPT_BE32, NFC_FLAG_VNI, + offsetof(struct ethtool_rx_flow_spec, h_u.vxlan_ip4_spec.vni), + offsetof(struct ethtool_rx_flow_spec, m_u.vxlan_ip4_spec.vni) }, + { "src", OPT_MAC, NFC_FLAG_SADDR, + offsetof(struct ethtool_rx_flow_spec, h_u.vxlan_ip4_spec.src), + offsetof(struct ethtool_rx_flow_spec, m_u.vxlan_ip4_spec.src) }, + { "dst", OPT_MAC, NFC_FLAG_DADDR, + offsetof(struct ethtool_rx_flow_spec, h_u.vxlan_ip4_spec.dst), + offsetof(struct ethtool_rx_flow_spec, m_u.vxlan_ip4_spec.dst) }, + { "proto", OPT_BE16, NFC_FLAG_PROTO, + offsetof(struct ethtool_rx_flow_spec, h_u.vxlan_ip4_spec.eth_type), + offsetof(struct ethtool_rx_flow_spec, m_u.vxlan_ip4_spec.eth_type) }, + { "tos", OPT_U8, NFC_FLAG_TOS, + offsetof(struct ethtool_rx_flow_spec, h_u.vxlan_ip4_spec.tos), + offsetof(struct ethtool_rx_flow_spec, m_u.vxlan_ip4_spec.tos) }, + { "l4proto", OPT_U8, NFC_FLAG_L4_PROTO, + offsetof(struct ethtool_rx_flow_spec, h_u.vxlan_ip4_spec.l4_proto), + offsetof(struct ethtool_rx_flow_spec, m_u.vxlan_ip4_spec.l4_proto) }, + { "src-ip", OPT_IP4, NFC_FLAG_SRC_IP, + offsetof(struct ethtool_rx_flow_spec, h_u.vxlan_ip4_spec.ip4src), + offsetof(struct ethtool_rx_flow_spec, m_u.vxlan_ip4_spec.ip4src) }, + { "dst-ip", OPT_IP4, NFC_FLAG_DST_IP, + offsetof(struct ethtool_rx_flow_spec, h_u.vxlan_ip4_spec.ip4dst), + offsetof(struct ethtool_rx_flow_spec, m_u.vxlan_ip4_spec.ip4dst) }, + { "action", OPT_U64, NFC_FLAG_RING, + offsetof(struct ethtool_rx_flow_spec, ring_cookie), -1 }, + { "vf", OPT_RING_VF, NFC_FLAG_RING_VF, + offsetof(struct ethtool_rx_flow_spec, ring_cookie), -1 }, + { "queue", OPT_RING_QUEUE, NFC_FLAG_RING_QUEUE, + offsetof(struct ethtool_rx_flow_spec, ring_cookie), -1 }, + { "loc", OPT_U32, NFC_FLAG_LOC, + offsetof(struct ethtool_rx_flow_spec, location), -1 }, + { "vlan", OPT_BE16, NTUPLE_FLAG_VLAN, + offsetof(struct ethtool_rx_flow_spec, h_ext.vlan_tci), + offsetof(struct ethtool_rx_flow_spec, m_ext.vlan_tci) }, +}; +#endif + static const struct rule_opts rule_nfc_tcp_ip6[] = { { "src-ip", OPT_IP6, NFC_FLAG_SADDR, offsetof(struct ethtool_rx_flow_spec, h_u.tcp_ip6_spec.ip6src), @@ -897,6 +1042,46 @@ static const struct rule_opts rule_nfc_usr_ip6[] = { offsetof(struct ethtool_rx_flow_spec, m_ext.h_dest) }, }; +#ifdef ETHTOOL_FD_VXLAN_FEATURE +static const struct rule_opts rule_nfc_vxlan_ip6[] = { + { "vni", OPT_BE32, NFC_FLAG_VNI, + offsetof(struct ethtool_rx_flow_spec, h_u.vxlan_ip4_spec.vni), + offsetof(struct ethtool_rx_flow_spec, m_u.vxlan_ip4_spec.vni) }, + { "src", OPT_MAC, NFC_FLAG_SADDR, + offsetof(struct ethtool_rx_flow_spec, h_u.vxlan_ip4_spec.src), + offsetof(struct ethtool_rx_flow_spec, m_u.vxlan_ip4_spec.src) }, + { "dst", OPT_MAC, NFC_FLAG_DADDR, + offsetof(struct ethtool_rx_flow_spec, h_u.vxlan_ip4_spec.dst), + offsetof(struct ethtool_rx_flow_spec, m_u.vxlan_ip4_spec.dst) }, + { "proto", OPT_BE16, NFC_FLAG_PROTO, + offsetof(struct ethtool_rx_flow_spec, h_u.vxlan_ip4_spec.eth_type), + offsetof(struct ethtool_rx_flow_spec, m_u.vxlan_ip4_spec.eth_type) }, + { "tclass", OPT_U8, NFC_FLAG_TOS, + offsetof(struct ethtool_rx_flow_spec, h_u.vxlan_ip6_spec.tclass), + offsetof(struct ethtool_rx_flow_spec, m_u.vxlan_ip6_spec.tclass) }, + { "l4proto", OPT_U8, NFC_FLAG_L4_PROTO, + offsetof(struct ethtool_rx_flow_spec, h_u.vxlan_ip6_spec.l4_proto), + offsetof(struct ethtool_rx_flow_spec, m_u.vxlan_ip6_spec.l4_proto) }, + { "src-ip", OPT_IP6, NFC_FLAG_SRC_IP, + offsetof(struct ethtool_rx_flow_spec, h_u.vxlan_ip6_spec.ip6src), + offsetof(struct ethtool_rx_flow_spec, m_u.vxlan_ip6_spec.ip6src) }, + { "dst-ip", OPT_IP6, NFC_FLAG_DST_IP, + offsetof(struct ethtool_rx_flow_spec, h_u.vxlan_ip6_spec.ip6dst), + offsetof(struct ethtool_rx_flow_spec, m_u.vxlan_ip6_spec.ip6dst) }, + { "action", OPT_U64, NFC_FLAG_RING, + offsetof(struct ethtool_rx_flow_spec, ring_cookie), -1 }, + { "vf", OPT_RING_VF, NFC_FLAG_RING_VF, + offsetof(struct ethtool_rx_flow_spec, ring_cookie), -1 }, + { "queue", OPT_RING_QUEUE, NFC_FLAG_RING_QUEUE, + offsetof(struct ethtool_rx_flow_spec, ring_cookie), -1 }, + { "loc", OPT_U32, NFC_FLAG_LOC, + offsetof(struct ethtool_rx_flow_spec, location), -1 }, + { "vlan", OPT_BE16, NTUPLE_FLAG_VLAN, + offsetof(struct ethtool_rx_flow_spec, h_ext.vlan_tci), + offsetof(struct ethtool_rx_flow_spec, m_ext.vlan_tci) }, +}; +#endif + static const struct rule_opts rule_nfc_ether[] = { { "src", OPT_MAC, NFC_FLAG_SADDR, offsetof(struct ethtool_rx_flow_spec, h_u.ether_spec.h_source), @@ -1289,6 +1474,10 @@ int rxclass_parse_ruleopts(struct cmd_context *ctx, flow_type = ESP_V4_FLOW; else if (!strcmp(argp[0], "ip4")) flow_type = IPV4_USER_FLOW; +#ifdef ETHTOOL_FD_VXLAN_FEATURE + else if (!strcmp(argp[0], "vxlan4")) + flow_type = VXLAN_V4_FLOW; +#endif else if (!strcmp(argp[0], "tcp6")) flow_type = TCP_V6_FLOW; else if (!strcmp(argp[0], "udp6")) @@ -1301,6 +1490,10 @@ int rxclass_parse_ruleopts(struct cmd_context *ctx, flow_type = ESP_V6_FLOW; else if (!strcmp(argp[0], "ip6")) flow_type = IPV6_USER_FLOW; +#ifdef ETHTOOL_FD_VXLAN_FEATURE + else if (!strcmp(argp[0], "vxlan6")) + flow_type = VXLAN_V6_FLOW; +#endif else if (!strcmp(argp[0], "ether")) flow_type = ETHER_FLOW; else @@ -1322,6 +1515,12 @@ int rxclass_parse_ruleopts(struct cmd_context *ctx, options = rule_nfc_usr_ip4; n_opts = ARRAY_SIZE(rule_nfc_usr_ip4); break; +#ifdef ETHTOOL_FD_VXLAN_FEATURE + case VXLAN_V4_FLOW: + options = rule_nfc_vxlan_ip4; + n_opts = ARRAY_SIZE(rule_nfc_vxlan_ip4); + break; +#endif case TCP_V6_FLOW: case UDP_V6_FLOW: case SCTP_V6_FLOW: @@ -1337,6 +1536,12 @@ int rxclass_parse_ruleopts(struct cmd_context *ctx, options = rule_nfc_usr_ip6; n_opts = ARRAY_SIZE(rule_nfc_usr_ip6); break; +#ifdef ETHTOOL_FD_VXLAN_FEATURE + case VXLAN_V6_FLOW: + options = rule_nfc_vxlan_ip6; + n_opts = ARRAY_SIZE(rule_nfc_vxlan_ip6); + break; +#endif case ETHER_FLOW: options = rule_nfc_ether; n_opts = ARRAY_SIZE(rule_nfc_ether); diff --git a/uapi/linux/ethtool.h b/uapi/linux/ethtool.h index 944711c..9d69200 100644 --- a/uapi/linux/ethtool.h +++ b/uapi/linux/ethtool.h @@ -929,6 +929,30 @@ struct ethtool_usrip4_spec { __u8 proto; }; +#ifdef ETHTOOL_FD_VXLAN_FEATURE +/** + * struct ethtool_vxlan4_spec - general flow specification for VxLAN IPv4 + * @vni: VxLAN network identifier + * @dst: Inner destination eth addr + * @src: Inner source eth addr + * @eth_type: Inner ethernet type + * @tos: Inner type-of-service + * @l4_proto: Inner transport protocol number + * @ip4src: Inner source host + * @ip4dst: Inner destination host + */ +struct ethtool_vxlan4_spec { + __be32 vni; + __u8 dst[ETH_ALEN]; + __u8 src[ETH_ALEN]; + __be16 eth_type; + __u8 tos; + __u8 l4_proto; + __be32 ip4src; + __be32 ip4dst; +}; +#endif + /** * struct ethtool_tcpip6_spec - flow specification for TCP/IPv6 etc. * @ip6src: Source host @@ -979,6 +1003,30 @@ struct ethtool_usrip6_spec { __u8 l4_proto; }; +#ifdef ETHTOOL_FD_VXLAN_FEATURE +/** + * struct ethtool_vxlan6_spec - general flow specification for VxLAN IPv6 + * @vni: VxLAN network identifier + * @dst: Inner destination eth addr + * @src: Inner source eth addr + * @eth_type: Inner ethernet type + * @tclass: Inner traffic Class + * @l4_proto: Inner transport protocol number + * @ip6src: Inner source host + * @ip6dst: Inner destination host + */ +struct ethtool_vxlan6_spec { + __be32 vni; + __u8 dst[ETH_ALEN]; + __u8 src[ETH_ALEN]; + __be16 eth_type; + __u8 tclass; + __u8 l4_proto; + __be32 ip6src[4]; + __be32 ip6dst[4]; +}; +#endif + union ethtool_flow_union { struct ethtool_tcpip4_spec tcp_ip4_spec; struct ethtool_tcpip4_spec udp_ip4_spec; @@ -994,6 +1042,10 @@ union ethtool_flow_union { struct ethtool_usrip6_spec usr_ip6_spec; struct ethhdr ether_spec; __u8 hdata[52]; +#ifdef ETHTOOL_FD_VXLAN_FEATURE + struct ethtool_vxlan4_spec vxlan_ip4_spec; + struct ethtool_vxlan6_spec vxlan_ip6_spec; +#endif }; /** @@ -1898,6 +1950,10 @@ static __inline__ int ethtool_validate_duplex(__u8 duplex) #define IPV4_FLOW 0x10 /* hash only */ #define IPV6_FLOW 0x11 /* hash only */ #define ETHER_FLOW 0x12 /* spec only (ether_spec) */ +#ifdef ETHTOOL_FD_VXLAN_FEATURE +#define VXLAN_V4_FLOW 0x43 /* spec only (vxlan_ip4_spec) */ +#define VXLAN_V6_FLOW 0x44 /* spec only (vxlan_ip6_spec) */ +#endif /* Flag to enable additional fields in struct ethtool_rx_flow_spec */ #define FLOW_EXT 0x80000000 #define FLOW_MAC_EXT 0x40000000 -- 2.30.0