* [PATCH ethtool] tunnels: implement new --show-tunnels command
@ 2020-09-09 22:18 Jakub Kicinski
2020-09-10 10:16 ` Michal Kubecek
0 siblings, 1 reply; 3+ messages in thread
From: Jakub Kicinski @ 2020-09-09 22:18 UTC (permalink / raw)
To: mkubecek; +Cc: netdev, Jakub Kicinski
Add support for the new show-tunnels command. Support dump.
# ethtool --show-tunnels \*
Tunnel information for eth0:
UDP port table 0:
Size: 4
Types: vxlan
No entries
UDP port table 1:
Size: 4
Types: geneve, vxlan-gpe
Entries (2):
port 1230, vxlan-gpe
port 6081, geneve
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
Makefile.am | 2 +-
ethtool.8.in | 9 ++
ethtool.c | 5 +
netlink/extapi.h | 2 +
netlink/tunnels.c | 236 ++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 253 insertions(+), 1 deletion(-)
create mode 100644 netlink/tunnels.c
diff --git a/Makefile.am b/Makefile.am
index aca0ad7bc773..0e237d070d4b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -37,7 +37,7 @@ ethtool_SOURCES += \
netlink/channels.c netlink/coalesce.c netlink/pause.c \
netlink/eee.c netlink/tsinfo.c \
netlink/desc-ethtool.c netlink/desc-genlctrl.c \
- netlink/desc-rtnl.c netlink/cable_test.c \
+ netlink/desc-rtnl.c netlink/cable_test.c netlink/tunnels.c \
uapi/linux/ethtool_netlink.h \
uapi/linux/netlink.h uapi/linux/genetlink.h \
uapi/linux/rtnetlink.h uapi/linux/if_link.h
diff --git a/ethtool.8.in b/ethtool.8.in
index a50a4769895c..42c4767db33e 100644
--- a/ethtool.8.in
+++ b/ethtool.8.in
@@ -459,6 +459,9 @@ ethtool \- query or control network driver and hardware settings
.BN last N
.BN step N
.BN pair N
+.HP
+.B ethtool \-\-show\-tunnels
+.I devname
.
.\" Adjust lines (i.e. full justification) and hyphenate.
.ad
@@ -1383,6 +1386,12 @@ shown.
If a device name is used as argument, only notification for this device are
shown. Default is to show notifications for all devices.
.RE
+.TP
+.B \-\-show\-tunnels
+Show tunnel-related device capabilities and state.
+List UDP ports kernel has programmed the device to parse as VxLAN,
+or GENEVE tunnels.
+.RE
.SH BUGS
Not supported (in part or whole) on all network drivers.
.SH AUTHOR
diff --git a/ethtool.c b/ethtool.c
index 606af3e6b48f..23ecfcfd069c 100644
--- a/ethtool.c
+++ b/ethtool.c
@@ -5919,6 +5919,11 @@ static const struct option args[] = {
" [ step N ]\n"
" [ pair N ]\n"
},
+ {
+ .opts = "--show-tunnels",
+ .nlfunc = nl_gtunnels,
+ .help = "Show NIC tunnel offload information",
+ },
{
.opts = "-h|--help",
.no_dev = true,
diff --git a/netlink/extapi.h b/netlink/extapi.h
index a35d5f2c0b26..9285e2325dfd 100644
--- a/netlink/extapi.h
+++ b/netlink/extapi.h
@@ -37,6 +37,7 @@ int nl_seee(struct cmd_context *ctx);
int nl_tsinfo(struct cmd_context *ctx);
int nl_cable_test(struct cmd_context *ctx);
int nl_cable_test_tdr(struct cmd_context *ctx);
+int nl_gtunnels(struct cmd_context *ctx);
int nl_monitor(struct cmd_context *ctx);
void nl_monitor_usage(void);
@@ -84,6 +85,7 @@ static inline void nl_monitor_usage(void)
#define nl_tsinfo NULL
#define nl_cable_test NULL
#define nl_cable_test_tdr NULL
+#define nl_gtunnels NULL
#endif /* ETHTOOL_ENABLE_NETLINK */
diff --git a/netlink/tunnels.c b/netlink/tunnels.c
new file mode 100644
index 000000000000..71daa267dce8
--- /dev/null
+++ b/netlink/tunnels.c
@@ -0,0 +1,236 @@
+/*
+ * tunnel.c - device tunnel information
+ *
+ * Implementation of "ethtool --show-tunnels <dev>"
+ */
+
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <arpa/inet.h>
+
+#include "../common.h"
+#include "../internal.h"
+
+#include "bitset.h"
+#include "netlink.h"
+#include "strset.h"
+
+/* TUNNEL_INFO_GET */
+
+static int
+tunnel_info_strings_load(struct nl_context *nlctx,
+ const struct stringset **strings)
+{
+ int ret;
+
+ if (*strings)
+ return 0;
+ ret = netlink_init_ethnl2_socket(nlctx);
+ if (ret < 0)
+ return ret;
+ *strings = global_stringset(ETH_SS_UDP_TUNNEL_TYPES,
+ nlctx->ethnl2_socket);
+ return 0;
+}
+
+static int
+tunnel_info_dump_udp_entry(struct nl_context *nlctx, const struct nlattr *entry,
+ const struct stringset **strings)
+{
+ const struct nlattr *entry_tb[ETHTOOL_A_TUNNEL_UDP_ENTRY_MAX + 1] = {};
+ DECLARE_ATTR_TB_INFO(entry_tb);
+ const struct nlattr *attr;
+ unsigned int port, type;
+ int ret;
+
+ if (tunnel_info_strings_load(nlctx, strings))
+ return 1;
+
+ ret = mnl_attr_parse_nested(entry, attr_cb, &entry_tb_info);
+ if (ret < 0) {
+ fprintf(stderr, "malformed netlink message (udp entry)\n");
+ return 1;
+ }
+
+ attr = entry_tb[ETHTOOL_A_TUNNEL_UDP_ENTRY_PORT];
+ if (!attr || mnl_attr_validate(attr, MNL_TYPE_U16) < 0) {
+ fprintf(stderr, "malformed netlink message (port)\n");
+ return 1;
+ }
+ port = htons(mnl_attr_get_u16(attr));
+
+ attr = entry_tb[ETHTOOL_A_TUNNEL_UDP_ENTRY_TYPE];
+ if (!attr || mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
+ fprintf(stderr, "malformed netlink message (tunnel type)\n");
+ return 1;
+ }
+ type = mnl_attr_get_u32(attr);
+
+ printf(" port %d, %s\n", port, get_string(*strings, type));
+
+ return 0;
+}
+
+static void tunnel_info_dump_cb(unsigned int idx, const char *name, bool val,
+ void *data)
+{
+ bool *first = data;
+
+ if (!val)
+ return;
+
+ if (!*first)
+ putchar(',');
+ *first = false;
+
+ if (name)
+ printf(" %s", name);
+ else
+ printf(" bit%u", idx);
+}
+
+static int
+tunnel_info_dump_list(struct nl_context *nlctx, const struct nlattr *attr,
+ const struct stringset **strings)
+{
+ bool first = true;
+ int ret;
+
+ if (bitset_is_empty(attr, false, &ret) || ret) {
+ if (ret)
+ return 1;
+
+ printf(" Types: none (static entries)\n");
+ return 0;
+ }
+
+ if (bitset_is_compact(attr) &&
+ tunnel_info_strings_load(nlctx, strings))
+ return 1;
+
+ printf(" Types:");
+ ret = walk_bitset(attr, *strings, tunnel_info_dump_cb, &first);
+ putchar('\n');
+ return ret;
+}
+
+static int
+tunnel_info_dump_udp_table(const struct nlattr *table, struct nl_context *nlctx,
+ const struct stringset **strings)
+{
+ const struct nlattr *table_tb[ETHTOOL_A_TUNNEL_UDP_TABLE_MAX + 1] = {};
+ DECLARE_ATTR_TB_INFO(table_tb);
+ const struct nlattr *attr;
+ int i, ret;
+
+ ret = mnl_attr_parse_nested(table, attr_cb, &table_tb_info);
+ if (ret < 0) {
+ fprintf(stderr, "malformed netlink message (udp table)\n");
+ return 1;
+ }
+
+ attr = table_tb[ETHTOOL_A_TUNNEL_UDP_TABLE_SIZE];
+ if (!attr || mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
+ fprintf(stderr, "malformed netlink message (table size)\n");
+ return 1;
+ }
+ printf(" Size: %d\n", mnl_attr_get_u32(attr));
+
+ attr = table_tb[ETHTOOL_A_TUNNEL_UDP_TABLE_TYPES];
+ if (!attr || tunnel_info_dump_list(nlctx, attr, strings)) {
+ fprintf(stderr, "malformed netlink message (types)\n");
+ return 1;
+ }
+
+ if (!table_tb[ETHTOOL_A_TUNNEL_UDP_TABLE_ENTRY]) {
+ printf(" No entries\n");
+ return 0;
+ }
+
+ i = 0;
+ mnl_attr_for_each_nested(attr, table) {
+ if (mnl_attr_get_type(attr) == ETHTOOL_A_TUNNEL_UDP_TABLE_ENTRY)
+ i++;
+ }
+
+ printf(" Entries (%d):\n", i++);
+ mnl_attr_for_each_nested(attr, table) {
+ if (mnl_attr_get_type(attr) == ETHTOOL_A_TUNNEL_UDP_TABLE_ENTRY)
+ if (tunnel_info_dump_udp_entry(nlctx, attr, strings))
+ return 1;
+ }
+
+ return 0;
+}
+
+static int
+tunnel_info_dump_udp(const struct nlattr *udp_ports, struct nl_context *nlctx)
+{
+ const struct stringset *strings = NULL;
+ const struct nlattr *table;
+ int i, err;
+
+ i = 0;
+ mnl_attr_for_each_nested(table, udp_ports) {
+ if (mnl_attr_get_type(table) != ETHTOOL_A_TUNNEL_UDP_TABLE)
+ continue;
+
+ printf(" UDP port table %d: \n", i++);
+ err = tunnel_info_dump_udp_table(table, nlctx, &strings);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
+static int tunnel_info_reply_cb(const struct nlmsghdr *nlhdr, void *data)
+{
+ const struct nlattr *tb[ETHTOOL_A_TUNNEL_INFO_MAX + 1] = {};
+ DECLARE_ATTR_TB_INFO(tb);
+ const struct nlattr *udp_ports;
+ struct nl_context *nlctx = data;
+ bool silent;
+ int err_ret;
+ int ret;
+
+ silent = nlctx->is_dump;
+ err_ret = silent ? MNL_CB_OK : MNL_CB_ERROR;
+ ret = mnl_attr_parse(nlhdr, GENL_HDRLEN, attr_cb, &tb_info);
+ if (ret < 0)
+ return err_ret;
+ nlctx->devname = get_dev_name(tb[ETHTOOL_A_TUNNEL_INFO_HEADER]);
+ if (!dev_ok(nlctx))
+ return err_ret;
+
+ printf("Tunnel information for %s:\n", nlctx->devname);
+
+ udp_ports = tb[ETHTOOL_A_TUNNEL_INFO_UDP_PORTS];
+ if (udp_ports)
+ if (tunnel_info_dump_udp(udp_ports, nlctx))
+ return err_ret;
+
+ return MNL_CB_OK;
+}
+
+int nl_gtunnels(struct cmd_context *ctx)
+{
+ struct nl_context *nlctx = ctx->nlctx;
+ struct nl_socket *nlsk = nlctx->ethnl_socket;
+ int ret;
+
+ if (netlink_cmd_check(ctx, ETHTOOL_MSG_TUNNEL_INFO_GET, true))
+ return -EOPNOTSUPP;
+ if (ctx->argc > 0) {
+ fprintf(stderr, "ethtool: unexpected parameter '%s'\n",
+ *ctx->argp);
+ return 1;
+ }
+
+ ret = nlsock_prep_get_request(nlsk, ETHTOOL_MSG_TUNNEL_INFO_GET,
+ ETHTOOL_A_TUNNEL_INFO_HEADER, 0);
+ if (ret < 0)
+ return ret;
+ return nlsock_send_get_request(nlsk, tunnel_info_reply_cb);
+}
--
2.26.2
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH ethtool] tunnels: implement new --show-tunnels command
2020-09-09 22:18 [PATCH ethtool] tunnels: implement new --show-tunnels command Jakub Kicinski
@ 2020-09-10 10:16 ` Michal Kubecek
2020-09-10 19:10 ` Jakub Kicinski
0 siblings, 1 reply; 3+ messages in thread
From: Michal Kubecek @ 2020-09-10 10:16 UTC (permalink / raw)
To: Jakub Kicinski; +Cc: netdev
On Wed, Sep 09, 2020 at 03:18:11PM -0700, Jakub Kicinski wrote:
> Add support for the new show-tunnels command. Support dump.
>
> # ethtool --show-tunnels \*
> Tunnel information for eth0:
> UDP port table 0:
> Size: 4
> Types: vxlan
> No entries
> UDP port table 1:
> Size: 4
> Types: geneve, vxlan-gpe
> Entries (2):
> port 1230, vxlan-gpe
> port 6081, geneve
>
> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
The patch looks good except for one cosmetic issue below. But you will
need to update the uapi header copies first to get the new constants.
You can use the script at the end of this mail.
[...]
> +static int
> +tunnel_info_dump_udp_entry(struct nl_context *nlctx, const struct nlattr *entry,
> + const struct stringset **strings)
> +{
> + const struct nlattr *entry_tb[ETHTOOL_A_TUNNEL_UDP_ENTRY_MAX + 1] = {};
> + DECLARE_ATTR_TB_INFO(entry_tb);
> + const struct nlattr *attr;
> + unsigned int port, type;
> + int ret;
> +
> + if (tunnel_info_strings_load(nlctx, strings))
> + return 1;
> +
> + ret = mnl_attr_parse_nested(entry, attr_cb, &entry_tb_info);
> + if (ret < 0) {
> + fprintf(stderr, "malformed netlink message (udp entry)\n");
> + return 1;
> + }
> +
> + attr = entry_tb[ETHTOOL_A_TUNNEL_UDP_ENTRY_PORT];
> + if (!attr || mnl_attr_validate(attr, MNL_TYPE_U16) < 0) {
> + fprintf(stderr, "malformed netlink message (port)\n");
> + return 1;
> + }
> + port = htons(mnl_attr_get_u16(attr));
This should be ntohs() as the attribute is in network byte order and we
convert it to host byte order (the result is the same, of course).
> +
> + attr = entry_tb[ETHTOOL_A_TUNNEL_UDP_ENTRY_TYPE];
> + if (!attr || mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
> + fprintf(stderr, "malformed netlink message (tunnel type)\n");
> + return 1;
> + }
> + type = mnl_attr_get_u32(attr);
> +
> + printf(" port %d, %s\n", port, get_string(*strings, type));
> +
> + return 0;
> +}
The script below expects LINUX_GIT to be set to the directory with
kernel git repository. It takes an optional argument which is a tag or
commit id to import uapi headers from; without an argument it updates
from what is currently checked out in $LINUX_GIT. So you can run e.g.
LINUX_GIT=~/git/kernel ethtool-import-uapi v5.9-rc1
Michal
------------------------------------------------------------------------------
#!/bin/bash -e
sn="${0##*/}"
export ARCH="x86_64"
if [ ! -d "$LINUX_GIT" ]; then
echo "${sn}: LINUX_GIT not set" >&2
exit 1
fi
pushd "$LINUX_GIT"
if [ -n "$1" ]; then
git checkout "$1"
fi
desc=$(git describe --exact-match 2>/dev/null \
|| git show -s --abbrev=12 --pretty='commit %h')
kobj=$(mktemp -d)
make -j16 O="$kobj" allmodconfig
make -j16 O="$kobj" prepare
make -j16 O="$kobj" INSTALL_HDR_PATH="${kobj}/hdr" headers_install
popd
pushd uapi
find . -type f -name '*.h' -exec cp -v "${kobj}/hdr/include/{}" {} \;
popd
rm -rf "$kobj"
git add uapi
git commit -s -F - <<EOT
update UAPI header copies
Update to kernel ${desc}.
EOT
------------------------------------------------------------------------------
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH ethtool] tunnels: implement new --show-tunnels command
2020-09-10 10:16 ` Michal Kubecek
@ 2020-09-10 19:10 ` Jakub Kicinski
0 siblings, 0 replies; 3+ messages in thread
From: Jakub Kicinski @ 2020-09-10 19:10 UTC (permalink / raw)
To: Michal Kubecek; +Cc: netdev
On Thu, 10 Sep 2020 12:16:05 +0200 Michal Kubecek wrote:
> On Wed, Sep 09, 2020 at 03:18:11PM -0700, Jakub Kicinski wrote:
> > Add support for the new show-tunnels command. Support dump.
> >
> > # ethtool --show-tunnels \*
> > Tunnel information for eth0:
> > UDP port table 0:
> > Size: 4
> > Types: vxlan
> > No entries
> > UDP port table 1:
> > Size: 4
> > Types: geneve, vxlan-gpe
> > Entries (2):
> > port 1230, vxlan-gpe
> > port 6081, geneve
> >
> > Signed-off-by: Jakub Kicinski <kuba@kernel.org>
>
> The patch looks good except for one cosmetic issue below. But you will
> need to update the uapi header copies first to get the new constants.
> You can use the script at the end of this mail.
Thanks! I wasn't sure if you sync yourself, like iproute2 folks do.
Now I know :)
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2020-09-10 19:11 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-09-09 22:18 [PATCH ethtool] tunnels: implement new --show-tunnels command Jakub Kicinski
2020-09-10 10:16 ` Michal Kubecek
2020-09-10 19:10 ` Jakub Kicinski
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.