* [PATCH net-next 04/12] tools: bpftool: add JSON output for `bpftool prog show *` command
From: Jakub Kicinski @ 2017-10-23 16:24 UTC (permalink / raw)
To: netdev; +Cc: oss-drivers, alexei.starovoitov, daniel, Quentin Monnet
In-Reply-To: <20171023162416.32753-1-jakub.kicinski@netronome.com>
From: Quentin Monnet <quentin.monnet@netronome.com>
Reuse the json_writer API introduced in an earlier commit to make
bpftool able to generate JSON output on `bpftool prog show *` commands.
For readability, the code from show_prog() has been split into two
functions, one for plain output, one for JSON.
Outputs from sample programs have been successfully tested against a
JSON validator.
Signed-off-by: Quentin Monnet <quentin.monnet@netronome.com>
---
tools/bpf/bpftool/prog.c | 139 ++++++++++++++++++++++++++++++++++++-----------
1 file changed, 107 insertions(+), 32 deletions(-)
diff --git a/tools/bpf/bpftool/prog.c b/tools/bpf/bpftool/prog.c
index 7838206a455b..f373f2baef5a 100644
--- a/tools/bpf/bpftool/prog.c
+++ b/tools/bpf/bpftool/prog.c
@@ -195,51 +195,100 @@ static void show_prog_maps(int fd, u32 num_maps)
if (err || !info.nr_map_ids)
return;
- printf(" map_ids ");
- for (i = 0; i < info.nr_map_ids; i++)
- printf("%u%s", map_ids[i],
- i == info.nr_map_ids - 1 ? "" : ",");
+ if (json_output) {
+ jsonw_name(json_wtr, "map_ids");
+ jsonw_start_array(json_wtr);
+ for (i = 0; i < info.nr_map_ids; i++)
+ jsonw_uint(json_wtr, map_ids[i]);
+ jsonw_end_array(json_wtr);
+ } else {
+ printf(" map_ids ");
+ for (i = 0; i < info.nr_map_ids; i++)
+ printf("%u%s", map_ids[i],
+ i == info.nr_map_ids - 1 ? "" : ",");
+ }
}
-static int show_prog(int fd)
+static void print_prog_json(struct bpf_prog_info *info, int fd)
{
- struct bpf_prog_info info = {};
- __u32 len = sizeof(info);
char *memlock;
- int err;
- err = bpf_obj_get_info_by_fd(fd, &info, &len);
- if (err) {
- err("can't get prog info: %s\n", strerror(errno));
- return -1;
+ jsonw_start_object(json_wtr);
+ jsonw_uint_field(json_wtr, "id", info->id);
+ if (info->type < ARRAY_SIZE(prog_type_name))
+ jsonw_string_field(json_wtr, "type",
+ prog_type_name[info->type]);
+ else
+ jsonw_uint_field(json_wtr, "type", info->type);
+
+ if (*info->name)
+ jsonw_string_field(json_wtr, "name", info->name);
+
+ jsonw_name(json_wtr, "tag");
+ jsonw_printf(json_wtr, "\"" BPF_TAG_FMT "\"",
+ info->tag[0], info->tag[1], info->tag[2], info->tag[3],
+ info->tag[4], info->tag[5], info->tag[6], info->tag[7]);
+
+ if (info->load_time) {
+ char buf[32];
+
+ print_boot_time(info->load_time, buf, sizeof(buf));
+
+ /* Piggy back on load_time, since 0 uid is a valid one */
+ jsonw_string_field(json_wtr, "loaded_at", buf);
+ jsonw_uint_field(json_wtr, "uid", info->created_by_uid);
}
- printf("%u: ", info.id);
- if (info.type < ARRAY_SIZE(prog_type_name))
- printf("%s ", prog_type_name[info.type]);
+ jsonw_uint_field(json_wtr, "bytes_xlated", info->xlated_prog_len);
+
+ if (info->jited_prog_len) {
+ jsonw_bool_field(json_wtr, "jited", true);
+ jsonw_uint_field(json_wtr, "bytes_jited", info->jited_prog_len);
+ } else {
+ jsonw_bool_field(json_wtr, "jited", false);
+ }
+
+ memlock = get_fdinfo(fd, "memlock");
+ if (memlock)
+ jsonw_int_field(json_wtr, "bytes_memlock", atoi(memlock));
+ free(memlock);
+
+ if (info->nr_map_ids)
+ show_prog_maps(fd, info->nr_map_ids);
+
+ jsonw_end_object(json_wtr);
+}
+
+static void print_prog_plain(struct bpf_prog_info *info, int fd)
+{
+ char *memlock;
+
+ printf("%u: ", info->id);
+ if (info->type < ARRAY_SIZE(prog_type_name))
+ printf("%s ", prog_type_name[info->type]);
else
- printf("type %u ", info.type);
+ printf("type %u ", info->type);
- if (*info.name)
- printf("name %s ", info.name);
+ if (*info->name)
+ printf("name %s ", info->name);
printf("tag ");
- fprint_hex(stdout, info.tag, BPF_TAG_SIZE, "");
+ fprint_hex(stdout, info->tag, BPF_TAG_SIZE, "");
printf("\n");
- if (info.load_time) {
+ if (info->load_time) {
char buf[32];
- print_boot_time(info.load_time, buf, sizeof(buf));
+ print_boot_time(info->load_time, buf, sizeof(buf));
/* Piggy back on load_time, since 0 uid is a valid one */
- printf("\tloaded_at %s uid %u\n", buf, info.created_by_uid);
+ printf("\tloaded_at %s uid %u\n", buf, info->created_by_uid);
}
- printf("\txlated %uB", info.xlated_prog_len);
+ printf("\txlated %uB", info->xlated_prog_len);
- if (info.jited_prog_len)
- printf(" jited %uB", info.jited_prog_len);
+ if (info->jited_prog_len)
+ printf(" jited %uB", info->jited_prog_len);
else
printf(" not jited");
@@ -248,16 +297,35 @@ static int show_prog(int fd)
printf(" memlock %sB", memlock);
free(memlock);
- if (info.nr_map_ids)
- show_prog_maps(fd, info.nr_map_ids);
+ if (info->nr_map_ids)
+ show_prog_maps(fd, info->nr_map_ids);
printf("\n");
+}
+
+static int show_prog(int fd)
+{
+ struct bpf_prog_info info = {};
+ __u32 len = sizeof(info);
+ int err;
+
+ err = bpf_obj_get_info_by_fd(fd, &info, &len);
+ if (err) {
+ err("can't get prog info: %s\n", strerror(errno));
+ return -1;
+ }
+
+ if (json_output)
+ print_prog_json(&info, fd);
+ else
+ print_prog_plain(&info, fd);
return 0;
}
static int do_show(int argc, char **argv)
-{ __u32 id = 0;
+{
+ __u32 id = 0;
int err;
int fd;
@@ -272,6 +340,8 @@ static int do_show(int argc, char **argv)
if (argc)
return BAD_ARG();
+ if (json_output)
+ jsonw_start_array(json_wtr);
while (true) {
err = bpf_prog_get_next_id(id, &id);
if (err) {
@@ -282,23 +352,28 @@ static int do_show(int argc, char **argv)
err("can't get next program: %s\n", strerror(errno));
if (errno == EINVAL)
err("kernel too old?\n");
- return -1;
+ err = -1;
+ break;
}
fd = bpf_prog_get_fd_by_id(id);
if (fd < 0) {
err("can't get prog by id (%u): %s\n",
id, strerror(errno));
- return -1;
+ err = -1;
+ break;
}
err = show_prog(fd);
close(fd);
if (err)
- return err;
+ break;
}
- return 0;
+ if (json_output)
+ jsonw_end_array(json_wtr);
+
+ return err;
}
static void print_insn(struct bpf_verifier_env *env, const char *fmt, ...)
--
2.14.1
^ permalink raw reply related
* [PATCH net-next 03/12] tools: bpftool: introduce --json and --pretty options
From: Jakub Kicinski @ 2017-10-23 16:24 UTC (permalink / raw)
To: netdev; +Cc: oss-drivers, alexei.starovoitov, daniel, Quentin Monnet
In-Reply-To: <20171023162416.32753-1-jakub.kicinski@netronome.com>
From: Quentin Monnet <quentin.monnet@netronome.com>
These two options can be used to ask for a JSON output (--j or -json),
and to make this JSON human-readable (-p or --pretty).
A json_writer object is created when JSON is required, and will be used
in follow-up commits to produce JSON output.
Note that --pretty implies --json.
Update for the manual pages and interactive help messages comes in a
later patch of the series.
Signed-off-by: Quentin Monnet <quentin.monnet@netronome.com>
---
tools/bpf/bpftool/main.c | 33 ++++++++++++++++++++++++++++++---
tools/bpf/bpftool/main.h | 5 +++++
2 files changed, 35 insertions(+), 3 deletions(-)
diff --git a/tools/bpf/bpftool/main.c b/tools/bpf/bpftool/main.c
index 613e3c75f78a..14bfc17cd4de 100644
--- a/tools/bpf/bpftool/main.c
+++ b/tools/bpf/bpftool/main.c
@@ -51,6 +51,9 @@ const char *bin_name;
static int last_argc;
static char **last_argv;
static int (*last_do_help)(int argc, char **argv);
+json_writer_t *json_wtr;
+bool pretty_output;
+bool json_output;
void usage(void)
{
@@ -217,22 +220,32 @@ static int do_batch(int argc, char **argv)
int main(int argc, char **argv)
{
static const struct option options[] = {
+ { "json", no_argument, NULL, 'j' },
{ "help", no_argument, NULL, 'h' },
+ { "pretty", no_argument, NULL, 'p' },
{ "version", no_argument, NULL, 'V' },
{ 0 }
};
- int opt;
+ int opt, ret;
last_do_help = do_help;
+ pretty_output = false;
+ json_output = false;
bin_name = argv[0];
- while ((opt = getopt_long(argc, argv, "Vh",
+ while ((opt = getopt_long(argc, argv, "Vhpj",
options, NULL)) >= 0) {
switch (opt) {
case 'V':
return do_version(argc, argv);
case 'h':
return do_help(argc, argv);
+ case 'p':
+ pretty_output = true;
+ /* fall through */
+ case 'j':
+ json_output = true;
+ break;
default:
usage();
}
@@ -243,7 +256,21 @@ int main(int argc, char **argv)
if (argc < 0)
usage();
+ if (json_output) {
+ json_wtr = jsonw_new(stdout);
+ if (!json_wtr) {
+ err("failed to create JSON writer\n");
+ return -1;
+ }
+ jsonw_pretty(json_wtr, pretty_output);
+ }
+
bfd_init();
- return cmd_select(cmds, argc, argv, do_help);
+ ret = cmd_select(cmds, argc, argv, do_help);
+
+ if (json_output)
+ jsonw_destroy(&json_wtr);
+
+ return ret;
}
diff --git a/tools/bpf/bpftool/main.h b/tools/bpf/bpftool/main.h
index 41e6c7d3fcad..15927fc9fb31 100644
--- a/tools/bpf/bpftool/main.h
+++ b/tools/bpf/bpftool/main.h
@@ -43,6 +43,8 @@
#include <linux/bpf.h>
#include <linux/kernel.h>
+#include "json_writer.h"
+
#define err(msg...) fprintf(stderr, "Error: " msg)
#define warn(msg...) fprintf(stderr, "Warning: " msg)
#define info(msg...) fprintf(stderr, msg)
@@ -66,6 +68,9 @@ enum bpf_obj_type {
extern const char *bin_name;
+extern json_writer_t *json_wtr;
+extern bool json_output;
+
bool is_prefix(const char *pfx, const char *str);
void fprint_hex(FILE *f, void *arg, unsigned int n, const char *sep);
void usage(void) __attribute__((noreturn));
--
2.14.1
^ permalink raw reply related
* [PATCH net-next 02/12] tools: bpftool: add option parsing to bpftool, --help and --version
From: Jakub Kicinski @ 2017-10-23 16:24 UTC (permalink / raw)
To: netdev; +Cc: oss-drivers, alexei.starovoitov, daniel, Quentin Monnet
In-Reply-To: <20171023162416.32753-1-jakub.kicinski@netronome.com>
From: Quentin Monnet <quentin.monnet@netronome.com>
Add an option parsing facility to bpftool, in prevision of future
options for demanding JSON output. Currently, two options are added:
--help and --version, that act the same as the respective commands
`help` and `version`.
Signed-off-by: Quentin Monnet <quentin.monnet@netronome.com>
---
tools/bpf/bpftool/Documentation/bpftool-map.rst | 8 +++++++
tools/bpf/bpftool/Documentation/bpftool-prog.rst | 8 +++++++
tools/bpf/bpftool/Documentation/bpftool.rst | 8 +++++++
tools/bpf/bpftool/main.c | 27 +++++++++++++++++++++++-
4 files changed, 50 insertions(+), 1 deletion(-)
diff --git a/tools/bpf/bpftool/Documentation/bpftool-map.rst b/tools/bpf/bpftool/Documentation/bpftool-map.rst
index ff63e89e4b6c..5210c4fab356 100644
--- a/tools/bpf/bpftool/Documentation/bpftool-map.rst
+++ b/tools/bpf/bpftool/Documentation/bpftool-map.rst
@@ -68,6 +68,14 @@ DESCRIPTION
**bpftool map help**
Print short help message.
+OPTIONS
+=======
+ -h, --help
+ Print short generic help message (similar to **bpftool help**).
+
+ -v, --version
+ Print version number (similar to **bpftool version**).
+
EXAMPLES
========
**# bpftool map show**
diff --git a/tools/bpf/bpftool/Documentation/bpftool-prog.rst b/tools/bpf/bpftool/Documentation/bpftool-prog.rst
index 69b3770370c8..6620a81d9dc9 100644
--- a/tools/bpf/bpftool/Documentation/bpftool-prog.rst
+++ b/tools/bpf/bpftool/Documentation/bpftool-prog.rst
@@ -50,6 +50,14 @@ DESCRIPTION
**bpftool prog help**
Print short help message.
+OPTIONS
+=======
+ -h, --help
+ Print short generic help message (similar to **bpftool help**).
+
+ -v, --version
+ Print version number (similar to **bpftool version**).
+
EXAMPLES
========
**# bpftool prog show**
diff --git a/tools/bpf/bpftool/Documentation/bpftool.rst b/tools/bpf/bpftool/Documentation/bpftool.rst
index 45ad8baf1915..9c04cd6677bd 100644
--- a/tools/bpf/bpftool/Documentation/bpftool.rst
+++ b/tools/bpf/bpftool/Documentation/bpftool.rst
@@ -31,6 +31,14 @@ DESCRIPTION
Note that format of the output of all tools is not guaranteed to be
stable and should not be depended upon.
+OPTIONS
+=======
+ -h, --help
+ Print short help message (similar to **bpftool help**).
+
+ -v, --version
+ Print version number (similar to **bpftool version**).
+
SEE ALSO
========
**bpftool-map**\ (8), **bpftool-prog**\ (8)
diff --git a/tools/bpf/bpftool/main.c b/tools/bpf/bpftool/main.c
index 814d19e1b53f..613e3c75f78a 100644
--- a/tools/bpf/bpftool/main.c
+++ b/tools/bpf/bpftool/main.c
@@ -36,6 +36,7 @@
#include <bfd.h>
#include <ctype.h>
#include <errno.h>
+#include <getopt.h>
#include <linux/bpf.h>
#include <linux/version.h>
#include <stdio.h>
@@ -215,8 +216,32 @@ static int do_batch(int argc, char **argv)
int main(int argc, char **argv)
{
+ static const struct option options[] = {
+ { "help", no_argument, NULL, 'h' },
+ { "version", no_argument, NULL, 'V' },
+ { 0 }
+ };
+ int opt;
+
+ last_do_help = do_help;
bin_name = argv[0];
- NEXT_ARG();
+
+ while ((opt = getopt_long(argc, argv, "Vh",
+ options, NULL)) >= 0) {
+ switch (opt) {
+ case 'V':
+ return do_version(argc, argv);
+ case 'h':
+ return do_help(argc, argv);
+ default:
+ usage();
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+ if (argc < 0)
+ usage();
bfd_init();
--
2.14.1
^ permalink raw reply related
* [PATCH net-next 01/12] tools: bpftool: copy JSON writer from iproute2 repository
From: Jakub Kicinski @ 2017-10-23 16:24 UTC (permalink / raw)
To: netdev; +Cc: oss-drivers, alexei.starovoitov, daniel, Quentin Monnet
In-Reply-To: <20171023162416.32753-1-jakub.kicinski@netronome.com>
From: Quentin Monnet <quentin.monnet@netronome.com>
In prevision of following commits, supposed to add JSON output to the
tool, two files are copied from the iproute2 repository (taken at commit
268a9eee985f): lib/json_writer.c and include/json_writer.h.
Signed-off-by: Quentin Monnet <quentin.monnet@netronome.com>
---
tools/bpf/bpftool/json_writer.c | 348 ++++++++++++++++++++++++++++++++++++++++
tools/bpf/bpftool/json_writer.h | 70 ++++++++
2 files changed, 418 insertions(+)
create mode 100644 tools/bpf/bpftool/json_writer.c
create mode 100644 tools/bpf/bpftool/json_writer.h
diff --git a/tools/bpf/bpftool/json_writer.c b/tools/bpf/bpftool/json_writer.c
new file mode 100644
index 000000000000..6b77d288cce2
--- /dev/null
+++ b/tools/bpf/bpftool/json_writer.c
@@ -0,0 +1,348 @@
+/*
+ * Simple streaming JSON writer
+ *
+ * This takes care of the annoying bits of JSON syntax like the commas
+ * after elements
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Authors: Stephen Hemminger <stephen@networkplumber.org>
+ */
+
+#include <stdio.h>
+#include <stdbool.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <malloc.h>
+#include <inttypes.h>
+#include <stdint.h>
+
+#include "json_writer.h"
+
+struct json_writer {
+ FILE *out; /* output file */
+ unsigned depth; /* nesting */
+ bool pretty; /* optional whitepace */
+ char sep; /* either nul or comma */
+};
+
+/* indentation for pretty print */
+static void jsonw_indent(json_writer_t *self)
+{
+ unsigned i;
+ for (i = 0; i < self->depth; ++i)
+ fputs(" ", self->out);
+}
+
+/* end current line and indent if pretty printing */
+static void jsonw_eol(json_writer_t *self)
+{
+ if (!self->pretty)
+ return;
+
+ putc('\n', self->out);
+ jsonw_indent(self);
+}
+
+/* If current object is not empty print a comma */
+static void jsonw_eor(json_writer_t *self)
+{
+ if (self->sep != '\0')
+ putc(self->sep, self->out);
+ self->sep = ',';
+}
+
+
+/* Output JSON encoded string */
+/* Handles C escapes, does not do Unicode */
+static void jsonw_puts(json_writer_t *self, const char *str)
+{
+ putc('"', self->out);
+ for (; *str; ++str)
+ switch (*str) {
+ case '\t':
+ fputs("\\t", self->out);
+ break;
+ case '\n':
+ fputs("\\n", self->out);
+ break;
+ case '\r':
+ fputs("\\r", self->out);
+ break;
+ case '\f':
+ fputs("\\f", self->out);
+ break;
+ case '\b':
+ fputs("\\b", self->out);
+ break;
+ case '\\':
+ fputs("\\n", self->out);
+ break;
+ case '"':
+ fputs("\\\"", self->out);
+ break;
+ case '\'':
+ fputs("\\\'", self->out);
+ break;
+ default:
+ putc(*str, self->out);
+ }
+ putc('"', self->out);
+}
+
+/* Create a new JSON stream */
+json_writer_t *jsonw_new(FILE *f)
+{
+ json_writer_t *self = malloc(sizeof(*self));
+ if (self) {
+ self->out = f;
+ self->depth = 0;
+ self->pretty = false;
+ self->sep = '\0';
+ }
+ return self;
+}
+
+/* End output to JSON stream */
+void jsonw_destroy(json_writer_t **self_p)
+{
+ json_writer_t *self = *self_p;
+
+ assert(self->depth == 0);
+ fputs("\n", self->out);
+ fflush(self->out);
+ free(self);
+ *self_p = NULL;
+}
+
+void jsonw_pretty(json_writer_t *self, bool on)
+{
+ self->pretty = on;
+}
+
+/* Basic blocks */
+static void jsonw_begin(json_writer_t *self, int c)
+{
+ jsonw_eor(self);
+ putc(c, self->out);
+ ++self->depth;
+ self->sep = '\0';
+}
+
+static void jsonw_end(json_writer_t *self, int c)
+{
+ assert(self->depth > 0);
+
+ --self->depth;
+ if (self->sep != '\0')
+ jsonw_eol(self);
+ putc(c, self->out);
+ self->sep = ',';
+}
+
+
+/* Add a JSON property name */
+void jsonw_name(json_writer_t *self, const char *name)
+{
+ jsonw_eor(self);
+ jsonw_eol(self);
+ self->sep = '\0';
+ jsonw_puts(self, name);
+ putc(':', self->out);
+ if (self->pretty)
+ putc(' ', self->out);
+}
+
+void jsonw_printf(json_writer_t *self, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ jsonw_eor(self);
+ vfprintf(self->out, fmt, ap);
+ va_end(ap);
+}
+
+/* Collections */
+void jsonw_start_object(json_writer_t *self)
+{
+ jsonw_begin(self, '{');
+}
+
+void jsonw_end_object(json_writer_t *self)
+{
+ jsonw_end(self, '}');
+}
+
+void jsonw_start_array(json_writer_t *self)
+{
+ jsonw_begin(self, '[');
+}
+
+void jsonw_end_array(json_writer_t *self)
+{
+ jsonw_end(self, ']');
+}
+
+/* JSON value types */
+void jsonw_string(json_writer_t *self, const char *value)
+{
+ jsonw_eor(self);
+ jsonw_puts(self, value);
+}
+
+void jsonw_bool(json_writer_t *self, bool val)
+{
+ jsonw_printf(self, "%s", val ? "true" : "false");
+}
+
+void jsonw_null(json_writer_t *self)
+{
+ jsonw_printf(self, "null");
+}
+
+void jsonw_float_fmt(json_writer_t *self, const char *fmt, double num)
+{
+ jsonw_printf(self, fmt, num);
+}
+
+#ifdef notused
+void jsonw_float(json_writer_t *self, double num)
+{
+ jsonw_printf(self, "%g", num);
+}
+#endif
+
+void jsonw_hu(json_writer_t *self, unsigned short num)
+{
+ jsonw_printf(self, "%hu", num);
+}
+
+void jsonw_uint(json_writer_t *self, uint64_t num)
+{
+ jsonw_printf(self, "%"PRIu64, num);
+}
+
+void jsonw_lluint(json_writer_t *self, unsigned long long int num)
+{
+ jsonw_printf(self, "%llu", num);
+}
+
+void jsonw_int(json_writer_t *self, int64_t num)
+{
+ jsonw_printf(self, "%"PRId64, num);
+}
+
+/* Basic name/value objects */
+void jsonw_string_field(json_writer_t *self, const char *prop, const char *val)
+{
+ jsonw_name(self, prop);
+ jsonw_string(self, val);
+}
+
+void jsonw_bool_field(json_writer_t *self, const char *prop, bool val)
+{
+ jsonw_name(self, prop);
+ jsonw_bool(self, val);
+}
+
+#ifdef notused
+void jsonw_float_field(json_writer_t *self, const char *prop, double val)
+{
+ jsonw_name(self, prop);
+ jsonw_float(self, val);
+}
+#endif
+
+void jsonw_float_field_fmt(json_writer_t *self,
+ const char *prop,
+ const char *fmt,
+ double val)
+{
+ jsonw_name(self, prop);
+ jsonw_float_fmt(self, fmt, val);
+}
+
+void jsonw_uint_field(json_writer_t *self, const char *prop, uint64_t num)
+{
+ jsonw_name(self, prop);
+ jsonw_uint(self, num);
+}
+
+void jsonw_hu_field(json_writer_t *self, const char *prop, unsigned short num)
+{
+ jsonw_name(self, prop);
+ jsonw_hu(self, num);
+}
+
+void jsonw_lluint_field(json_writer_t *self,
+ const char *prop,
+ unsigned long long int num)
+{
+ jsonw_name(self, prop);
+ jsonw_lluint(self, num);
+}
+
+void jsonw_int_field(json_writer_t *self, const char *prop, int64_t num)
+{
+ jsonw_name(self, prop);
+ jsonw_int(self, num);
+}
+
+void jsonw_null_field(json_writer_t *self, const char *prop)
+{
+ jsonw_name(self, prop);
+ jsonw_null(self);
+}
+
+#ifdef TEST
+int main(int argc, char **argv)
+{
+ json_writer_t *wr = jsonw_new(stdout);
+
+ jsonw_start_object(wr);
+ jsonw_pretty(wr, true);
+ jsonw_name(wr, "Vyatta");
+ jsonw_start_object(wr);
+ jsonw_string_field(wr, "url", "http://vyatta.com");
+ jsonw_uint_field(wr, "downloads", 2000000ul);
+ jsonw_float_field(wr, "stock", 8.16);
+
+ jsonw_name(wr, "ARGV");
+ jsonw_start_array(wr);
+ while (--argc)
+ jsonw_string(wr, *++argv);
+ jsonw_end_array(wr);
+
+ jsonw_name(wr, "empty");
+ jsonw_start_array(wr);
+ jsonw_end_array(wr);
+
+ jsonw_name(wr, "NIL");
+ jsonw_start_object(wr);
+ jsonw_end_object(wr);
+
+ jsonw_null_field(wr, "my_null");
+
+ jsonw_name(wr, "special chars");
+ jsonw_start_array(wr);
+ jsonw_string_field(wr, "slash", "/");
+ jsonw_string_field(wr, "newline", "\n");
+ jsonw_string_field(wr, "tab", "\t");
+ jsonw_string_field(wr, "ff", "\f");
+ jsonw_string_field(wr, "quote", "\"");
+ jsonw_string_field(wr, "tick", "\'");
+ jsonw_string_field(wr, "backslash", "\\");
+ jsonw_end_array(wr);
+
+ jsonw_end_object(wr);
+
+ jsonw_end_object(wr);
+ jsonw_destroy(&wr);
+ return 0;
+}
+
+#endif
diff --git a/tools/bpf/bpftool/json_writer.h b/tools/bpf/bpftool/json_writer.h
new file mode 100644
index 000000000000..1516aafba59d
--- /dev/null
+++ b/tools/bpf/bpftool/json_writer.h
@@ -0,0 +1,70 @@
+/*
+ * Simple streaming JSON writer
+ *
+ * This takes care of the annoying bits of JSON syntax like the commas
+ * after elements
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Authors: Stephen Hemminger <stephen@networkplumber.org>
+ */
+
+#ifndef _JSON_WRITER_H_
+#define _JSON_WRITER_H_
+
+#include <stdbool.h>
+#include <stdint.h>
+
+/* Opaque class structure */
+typedef struct json_writer json_writer_t;
+
+/* Create a new JSON stream */
+json_writer_t *jsonw_new(FILE *f);
+/* End output to JSON stream */
+void jsonw_destroy(json_writer_t **self_p);
+
+/* Cause output to have pretty whitespace */
+void jsonw_pretty(json_writer_t *self, bool on);
+
+/* Add property name */
+void jsonw_name(json_writer_t *self, const char *name);
+
+/* Add value */
+void jsonw_printf(json_writer_t *self, const char *fmt, ...);
+void jsonw_string(json_writer_t *self, const char *value);
+void jsonw_bool(json_writer_t *self, bool value);
+void jsonw_float(json_writer_t *self, double number);
+void jsonw_float_fmt(json_writer_t *self, const char *fmt, double num);
+void jsonw_uint(json_writer_t *self, uint64_t number);
+void jsonw_hu(json_writer_t *self, unsigned short number);
+void jsonw_int(json_writer_t *self, int64_t number);
+void jsonw_null(json_writer_t *self);
+void jsonw_lluint(json_writer_t *self, unsigned long long int num);
+
+/* Useful Combinations of name and value */
+void jsonw_string_field(json_writer_t *self, const char *prop, const char *val);
+void jsonw_bool_field(json_writer_t *self, const char *prop, bool value);
+void jsonw_float_field(json_writer_t *self, const char *prop, double num);
+void jsonw_uint_field(json_writer_t *self, const char *prop, uint64_t num);
+void jsonw_hu_field(json_writer_t *self, const char *prop, unsigned short num);
+void jsonw_int_field(json_writer_t *self, const char *prop, int64_t num);
+void jsonw_null_field(json_writer_t *self, const char *prop);
+void jsonw_lluint_field(json_writer_t *self, const char *prop,
+ unsigned long long int num);
+void jsonw_float_field_fmt(json_writer_t *self, const char *prop,
+ const char *fmt, double val);
+
+/* Collections */
+void jsonw_start_object(json_writer_t *self);
+void jsonw_end_object(json_writer_t *self);
+
+void jsonw_start_array(json_writer_t *self);
+void jsonw_end_array(json_writer_t *self);
+
+/* Override default exception handling */
+typedef void (jsonw_err_handler_fn)(const char *);
+
+#endif /* _JSON_WRITER_H_ */
--
2.14.1
^ permalink raw reply related
* [PATCH net-next 00/12] tools: bpftool: Add JSON output to bpftool
From: Jakub Kicinski @ 2017-10-23 16:24 UTC (permalink / raw)
To: netdev; +Cc: oss-drivers, alexei.starovoitov, daniel, Jakub Kicinski
Quentin says:
This series introduces support for JSON output to all bpftool commands. It
adds option parsing, and several options are created:
* -j, --json Switch to JSON output.
* -p, --pretty Switch to JSON and print it in a human-friendly fashion.
* -h, --help Print generic help message.
* -V, --version Print version number.
This code uses a "json_writer", which is a copy of the one written by
Stephen Hemminger in iproute2.
---
I don't know if there is an easy way to share the code for json_write
without copying the file, so I am very open to suggestions on this matter.
Quentin Monnet (12):
tools: bpftool: copy JSON writer from iproute2 repository
tools: bpftool: add option parsing to bpftool, --help and --version
tools: bpftool: introduce --json and --pretty options
tools: bpftool: add JSON output for `bpftool prog show *` command
tools: bpftool: add JSON output for `bpftool prog dump jited *`
command
tools: bpftool: add JSON output for `bpftool prog dump xlated *`
command
tools: bpftool: add JSON output for `bpftool map *` commands
tools: bpftool: add JSON output for `bpftool batch file FILE` command
tools: bpftool: turn err() and info() macros into functions
tools: bpftool: provide JSON output for all possible commands
tools: bpftool: add cosmetic changes for the manual pages
tools: bpftool: update documentation for --json and --pretty usage
tools/bpf/bpftool/Documentation/bpftool-map.rst | 44 ++-
tools/bpf/bpftool/Documentation/bpftool-prog.rst | 81 +++++-
tools/bpf/bpftool/Documentation/bpftool.rst | 30 +-
tools/bpf/bpftool/common.c | 36 ++-
tools/bpf/bpftool/jit_disasm.c | 86 +++++-
tools/bpf/bpftool/json_writer.c | 356 +++++++++++++++++++++++
tools/bpf/bpftool/json_writer.h | 72 +++++
tools/bpf/bpftool/main.c | 121 +++++++-
tools/bpf/bpftool/main.h | 43 ++-
tools/bpf/bpftool/map.c | 253 ++++++++++++----
tools/bpf/bpftool/prog.c | 271 +++++++++++++----
11 files changed, 1209 insertions(+), 184 deletions(-)
create mode 100644 tools/bpf/bpftool/json_writer.c
create mode 100644 tools/bpf/bpftool/json_writer.h
--
2.14.1
^ permalink raw reply
* [PATCH v2 net-next 4/6] tcp: add tracepoint trace_tcp_receive_reset
From: Song Liu @ 2017-10-23 16:20 UTC (permalink / raw)
To: netdev, davem; +Cc: alexei.starovoitov, liu.song.a23, Song Liu
In-Reply-To: <20171023162027.2880430-1-songliubraving@fb.com>
New tracepoint trace_tcp_receive_reset is added and called from
tcp_reset(). This tracepoint is define with a new class tcp_event_sk.
Signed-off-by: Song Liu <songliubraving@fb.com>
---
include/trace/events/tcp.h | 66 ++++++++++++++++++++++++++++++++++++++++++++++
net/ipv4/tcp_input.c | 3 +++
2 files changed, 69 insertions(+)
diff --git a/include/trace/events/tcp.h b/include/trace/events/tcp.h
index 3e57e1a..c83c711 100644
--- a/include/trace/events/tcp.h
+++ b/include/trace/events/tcp.h
@@ -88,6 +88,72 @@ DEFINE_EVENT(tcp_event_sk_skb, tcp_send_reset,
TP_ARGS(sk, skb)
);
+/*
+ * tcp event with arguments sk
+ *
+ * Note: this class requires a valid sk pointer.
+ */
+DECLARE_EVENT_CLASS(tcp_event_sk,
+
+ TP_PROTO(const struct sock *sk),
+
+ TP_ARGS(sk),
+
+ TP_STRUCT__entry(
+ __field(const void *, skaddr)
+ __field(__u16, sport)
+ __field(__u16, dport)
+ __array(__u8, saddr, 4)
+ __array(__u8, daddr, 4)
+ __array(__u8, saddr_v6, 16)
+ __array(__u8, daddr_v6, 16)
+ ),
+
+ TP_fast_assign(
+ struct inet_sock *inet = inet_sk(sk);
+ struct in6_addr *pin6;
+ __be32 *p32;
+
+ __entry->skaddr = sk;
+
+ __entry->sport = ntohs(inet->inet_sport);
+ __entry->dport = ntohs(inet->inet_dport);
+
+ p32 = (__be32 *) __entry->saddr;
+ *p32 = inet->inet_saddr;
+
+ p32 = (__be32 *) __entry->daddr;
+ *p32 = inet->inet_daddr;
+
+#if IS_ENABLED(CONFIG_IPV6)
+ if (sk->sk_family == AF_INET6) {
+ pin6 = (struct in6_addr *)__entry->saddr_v6;
+ *pin6 = sk->sk_v6_rcv_saddr;
+ pin6 = (struct in6_addr *)__entry->daddr_v6;
+ *pin6 = sk->sk_v6_daddr;
+ } else
+#endif
+ {
+ pin6 = (struct in6_addr *)__entry->saddr_v6;
+ ipv6_addr_set_v4mapped(inet->inet_saddr, pin6);
+ pin6 = (struct in6_addr *)__entry->daddr_v6;
+ ipv6_addr_set_v4mapped(inet->inet_daddr, pin6);
+ }
+ ),
+
+ TP_printk("sport=%hu dport=%hu saddr=%pI4 daddr=%pI4 saddrv6=%pI6c daddrv6=%pI6c",
+ __entry->sport, __entry->dport,
+ __entry->saddr, __entry->daddr,
+ __entry->saddr_v6, __entry->daddr_v6)
+);
+
+DEFINE_EVENT(tcp_event_sk, tcp_receive_reset,
+
+ TP_PROTO(const struct sock *sk),
+
+ TP_ARGS(sk)
+);
+
#endif /* _TRACE_TCP_H */
/* This part must be outside protection */
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index ab3f128..c5e64d4 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -75,6 +75,7 @@
#include <linux/ipsec.h>
#include <asm/unaligned.h>
#include <linux/errqueue.h>
+#include <trace/events/tcp.h>
int sysctl_tcp_fack __read_mostly;
int sysctl_tcp_max_reordering __read_mostly = 300;
@@ -4010,6 +4011,8 @@ static inline bool tcp_sequence(const struct tcp_sock *tp, u32 seq, u32 end_seq)
/* When we get a reset we do this. */
void tcp_reset(struct sock *sk)
{
+ trace_tcp_receive_reset(sk);
+
/* We want the right error as BSD sees it (and indeed as we do). */
switch (sk->sk_state) {
case TCP_SYN_SENT:
--
2.9.5
^ permalink raw reply related
* [PATCH v2 net-next 3/6] tcp: add tracepoint trace_tcp_send_reset
From: Song Liu @ 2017-10-23 16:20 UTC (permalink / raw)
To: netdev, davem; +Cc: alexei.starovoitov, liu.song.a23, Song Liu
In-Reply-To: <20171023162027.2880430-1-songliubraving@fb.com>
New tracepoint trace_tcp_send_reset is added and called from
tcp_v4_send_reset(), tcp_v6_send_reset() and tcp_send_active_reset().
Signed-off-by: Song Liu <songliubraving@fb.com>
---
include/trace/events/tcp.h | 11 +++++++++++
net/core/net-traces.c | 2 ++
net/ipv4/tcp_ipv4.c | 6 +++++-
net/ipv4/tcp_output.c | 5 +++++
net/ipv6/tcp_ipv6.c | 10 ++++++++--
5 files changed, 31 insertions(+), 3 deletions(-)
diff --git a/include/trace/events/tcp.h b/include/trace/events/tcp.h
index 2b6fe72..3e57e1a 100644
--- a/include/trace/events/tcp.h
+++ b/include/trace/events/tcp.h
@@ -77,6 +77,17 @@ DEFINE_EVENT(tcp_event_sk_skb, tcp_retransmit_skb,
TP_ARGS(sk, skb)
);
+/*
+ * skb of trace_tcp_send_reset is the skb that caused RST. In case of
+ * active reset, skb should be NULL
+ */
+DEFINE_EVENT(tcp_event_sk_skb, tcp_send_reset,
+
+ TP_PROTO(const struct sock *sk, const struct sk_buff *skb),
+
+ TP_ARGS(sk, skb)
+);
+
#endif /* _TRACE_TCP_H */
/* This part must be outside protection */
diff --git a/net/core/net-traces.c b/net/core/net-traces.c
index f4e4fa2..8dcd9b0 100644
--- a/net/core/net-traces.c
+++ b/net/core/net-traces.c
@@ -49,3 +49,5 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(br_fdb_update);
EXPORT_TRACEPOINT_SYMBOL_GPL(kfree_skb);
EXPORT_TRACEPOINT_SYMBOL_GPL(napi_poll);
+
+EXPORT_TRACEPOINT_SYMBOL_GPL(tcp_send_reset);
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index e22439f..eb3f3b8 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -85,6 +85,8 @@
#include <crypto/hash.h>
#include <linux/scatterlist.h>
+#include <trace/events/tcp.h>
+
#ifdef CONFIG_TCP_MD5SIG
static int tcp_v4_md5_hash_hdr(char *md5_hash, const struct tcp_md5sig_key *key,
__be32 daddr, __be32 saddr, const struct tcphdr *th);
@@ -701,8 +703,10 @@ static void tcp_v4_send_reset(const struct sock *sk, struct sk_buff *skb)
* routing might fail in this case. No choice here, if we choose to force
* input interface, we will misroute in case of asymmetric route.
*/
- if (sk)
+ if (sk) {
arg.bound_dev_if = sk->sk_bound_dev_if;
+ trace_tcp_send_reset(sk, skb);
+ }
BUILD_BUG_ON(offsetof(struct sock, sk_bound_dev_if) !=
offsetof(struct inet_timewait_sock, tw_bound_dev_if));
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 988733f..1f01f4c 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -3084,6 +3084,11 @@ void tcp_send_active_reset(struct sock *sk, gfp_t priority)
/* Send it off. */
if (tcp_transmit_skb(sk, skb, 0, priority))
NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPABORTFAILED);
+
+ /* skb of trace_tcp_send_reset() keeps the skb that caused RST,
+ * skb here is different to the troublesome skb, so use NULL
+ */
+ trace_tcp_send_reset(sk, NULL);
}
/* Send a crossed SYN-ACK during socket establishment.
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index ae83615..0e25299 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -69,6 +69,8 @@
#include <crypto/hash.h>
#include <linux/scatterlist.h>
+#include <trace/events/tcp.h>
+
static void tcp_v6_send_reset(const struct sock *sk, struct sk_buff *skb);
static void tcp_v6_reqsk_send_ack(const struct sock *sk, struct sk_buff *skb,
struct request_sock *req);
@@ -890,7 +892,7 @@ static void tcp_v6_send_reset(const struct sock *sk, struct sk_buff *skb)
int genhash;
struct sock *sk1 = NULL;
#endif
- int oif;
+ int oif = 0;
if (th->rst)
return;
@@ -939,7 +941,11 @@ static void tcp_v6_send_reset(const struct sock *sk, struct sk_buff *skb)
ack_seq = ntohl(th->seq) + th->syn + th->fin + skb->len -
(th->doff << 2);
- oif = sk ? sk->sk_bound_dev_if : 0;
+ if (sk) {
+ oif = sk->sk_bound_dev_if;
+ trace_tcp_send_reset(sk, skb);
+ }
+
tcp_v6_send_response(sk, skb, seq, ack_seq, 0, 0, 0, oif, key, 1, 0, 0);
#ifdef CONFIG_TCP_MD5SIG
--
2.9.5
^ permalink raw reply related
* [PATCH v2 net-next 1/6] tcp: add trace event class tcp_event_sk_skb
From: Song Liu @ 2017-10-23 16:20 UTC (permalink / raw)
To: netdev, davem; +Cc: alexei.starovoitov, liu.song.a23, Song Liu
In-Reply-To: <20171023162027.2880430-1-songliubraving@fb.com>
Introduce event class tcp_event_sk_skb for tcp tracepoints that
have arguments sk and skb.
Existing tracepoint trace_tcp_retransmit_skb() falls into this class.
This patch rewrites the definition of trace_tcp_retransmit_skb() with
tcp_event_sk_skb.
Signed-off-by: Song Liu <songliubraving@fb.com>
---
include/trace/events/tcp.h | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/include/trace/events/tcp.h b/include/trace/events/tcp.h
index c3220d9..14b0a708 100644
--- a/include/trace/events/tcp.h
+++ b/include/trace/events/tcp.h
@@ -9,7 +9,13 @@
#include <linux/tracepoint.h>
#include <net/ipv6.h>
-TRACE_EVENT(tcp_retransmit_skb,
+/*
+ * tcp event with arguments sk and skb
+ *
+ * Note: this class requires a valid sk pointer; while skb pointer could
+ * be NULL.
+ */
+DECLARE_EVENT_CLASS(tcp_event_sk_skb,
TP_PROTO(struct sock *sk, struct sk_buff *skb),
@@ -64,6 +70,13 @@ TRACE_EVENT(tcp_retransmit_skb,
__entry->saddr_v6, __entry->daddr_v6)
);
+DEFINE_EVENT(tcp_event_sk_skb, tcp_retransmit_skb,
+
+ TP_PROTO(struct sock *sk, struct sk_buff *skb),
+
+ TP_ARGS(sk, skb)
+);
+
#endif /* _TRACE_TCP_H */
/* This part must be outside protection */
--
2.9.5
^ permalink raw reply related
* [PATCH v2 net-next 6/6] tcp: add tracepoint trace_tcp_set_state()
From: Song Liu @ 2017-10-23 16:20 UTC (permalink / raw)
To: netdev, davem; +Cc: alexei.starovoitov, liu.song.a23, Song Liu
In-Reply-To: <20171023162027.2880430-1-songliubraving@fb.com>
This patch adds tracepoint trace_tcp_set_state. Besides usual fields
(s/d ports, IP addresses), old and new state of the socket is also
printed with TP_printk, with __print_symbolic().
Signed-off-by: Song Liu <songliubraving@fb.com>
---
include/trace/events/tcp.h | 76 ++++++++++++++++++++++++++++++++++++++++++++++
net/ipv4/tcp.c | 4 +++
2 files changed, 80 insertions(+)
diff --git a/include/trace/events/tcp.h b/include/trace/events/tcp.h
index 1724c12..03699ba 100644
--- a/include/trace/events/tcp.h
+++ b/include/trace/events/tcp.h
@@ -9,6 +9,22 @@
#include <linux/tracepoint.h>
#include <net/ipv6.h>
+#define tcp_state_name(state) { state, #state }
+#define show_tcp_state_name(val) \
+ __print_symbolic(val, \
+ tcp_state_name(TCP_ESTABLISHED), \
+ tcp_state_name(TCP_SYN_SENT), \
+ tcp_state_name(TCP_SYN_RECV), \
+ tcp_state_name(TCP_FIN_WAIT1), \
+ tcp_state_name(TCP_FIN_WAIT2), \
+ tcp_state_name(TCP_TIME_WAIT), \
+ tcp_state_name(TCP_CLOSE), \
+ tcp_state_name(TCP_CLOSE_WAIT), \
+ tcp_state_name(TCP_LAST_ACK), \
+ tcp_state_name(TCP_LISTEN), \
+ tcp_state_name(TCP_CLOSING), \
+ tcp_state_name(TCP_NEW_SYN_RECV))
+
/*
* tcp event with arguments sk and skb
*
@@ -161,6 +177,66 @@ DEFINE_EVENT(tcp_event_sk, tcp_destroy_sock,
TP_ARGS(sk)
);
+TRACE_EVENT(tcp_set_state,
+
+ TP_PROTO(const struct sock *sk, const int oldstate, const int newstate),
+
+ TP_ARGS(sk, oldstate, newstate),
+
+ TP_STRUCT__entry(
+ __field(const void *, skaddr)
+ __field(int, oldstate)
+ __field(int, newstate)
+ __field(__u16, sport)
+ __field(__u16, dport)
+ __array(__u8, saddr, 4)
+ __array(__u8, daddr, 4)
+ __array(__u8, saddr_v6, 16)
+ __array(__u8, daddr_v6, 16)
+ ),
+
+ TP_fast_assign(
+ struct inet_sock *inet = inet_sk(sk);
+ struct in6_addr *pin6;
+ __be32 *p32;
+
+ __entry->skaddr = sk;
+ __entry->oldstate = oldstate;
+ __entry->newstate = newstate;
+
+ __entry->sport = ntohs(inet->inet_sport);
+ __entry->dport = ntohs(inet->inet_dport);
+
+ p32 = (__be32 *) __entry->saddr;
+ *p32 = inet->inet_saddr;
+
+ p32 = (__be32 *) __entry->daddr;
+ *p32 = inet->inet_daddr;
+
+#if IS_ENABLED(CONFIG_IPV6)
+ if (sk->sk_family == AF_INET6) {
+ pin6 = (struct in6_addr *)__entry->saddr_v6;
+ *pin6 = sk->sk_v6_rcv_saddr;
+ pin6 = (struct in6_addr *)__entry->daddr_v6;
+ *pin6 = sk->sk_v6_daddr;
+ } else
+#endif
+ {
+ pin6 = (struct in6_addr *)__entry->saddr_v6;
+ ipv6_addr_set_v4mapped(inet->inet_saddr, pin6);
+ pin6 = (struct in6_addr *)__entry->daddr_v6;
+ ipv6_addr_set_v4mapped(inet->inet_daddr, pin6);
+ }
+ ),
+
+ TP_printk("sport=%hu dport=%hu saddr=%pI4 daddr=%pI4 saddrv6=%pI6c daddrv6=%pI6c oldstate=%s newstate=%s",
+ __entry->sport, __entry->dport,
+ __entry->saddr, __entry->daddr,
+ __entry->saddr_v6, __entry->daddr_v6,
+ show_tcp_state_name(__entry->oldstate),
+ show_tcp_state_name(__entry->newstate))
+);
+
#endif /* _TRACE_TCP_H */
/* This part must be outside protection */
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 8b1fa4d..be07e9b 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -282,6 +282,8 @@
#include <asm/ioctls.h>
#include <net/busy_poll.h>
+#include <trace/events/tcp.h>
+
int sysctl_tcp_min_tso_segs __read_mostly = 2;
int sysctl_tcp_autocorking __read_mostly = 1;
@@ -2040,6 +2042,8 @@ void tcp_set_state(struct sock *sk, int state)
{
int oldstate = sk->sk_state;
+ trace_tcp_set_state(sk, oldstate, state);
+
switch (state) {
case TCP_ESTABLISHED:
if (oldstate != TCP_ESTABLISHED)
--
2.9.5
^ permalink raw reply related
* [PATCH v2 net-next 0/6] add a set of tracepoints to tcp stack
From: Song Liu @ 2017-10-23 16:20 UTC (permalink / raw)
To: netdev, davem; +Cc: alexei.starovoitov, liu.song.a23, Song Liu
Changes from v1:
Fix build error (with ipv6 as ko) by adding EXPORT_TRACEPOINT_SYMBOL_GPL
for trace_tcp_send_reset.
These patches add the following tracepoints to tcp stack.
tcp_send_reset
tcp_receive_reset
tcp_destroy_sock
tcp_set_state
These tracepoints can be used to track TCP state changes. Such state
changes include but are not limited to: connection establish,
connection termination, tx and rx of RST, various retransmits.
Currently, we use the following kprobes to trace these events:
int kprobe__tcp_validate_incoming
int kprobe__tcp_send_active_reset
int kprobe__tcp_v4_send_reset
int kprobe__tcp_v6_send_reset
int kprobe__tcp_v4_destroy_sock
int kprobe__tcp_set_state
int kprobe__tcp_retransmit_skb
These tracepoints will help us simplify this work.
Thanks,
Song
Song Liu (6):
tcp: add trace event class tcp_event_sk_skb
tcp: mark trace event arguments sk and skb as const
tcp: add tracepoint trace_tcp_send_reset
tcp: add tracepoint trace_tcp_receive_reset
tcp: add tracepoint trace_tcp_destroy_sock
tcp: add tracepoint trace_tcp_set_state()
include/trace/events/tcp.h | 181 ++++++++++++++++++++++++++++++++++++++++++++-
net/core/net-traces.c | 2 +
net/ipv4/tcp.c | 4 +
net/ipv4/tcp_input.c | 3 +
net/ipv4/tcp_ipv4.c | 8 +-
net/ipv4/tcp_output.c | 5 ++
net/ipv6/tcp_ipv6.c | 10 ++-
7 files changed, 206 insertions(+), 7 deletions(-)
^ permalink raw reply
* [PATCH v2 net-next 2/6] tcp: mark trace event arguments sk and skb as const
From: Song Liu @ 2017-10-23 16:20 UTC (permalink / raw)
To: netdev, davem; +Cc: alexei.starovoitov, liu.song.a23, Song Liu
In-Reply-To: <20171023162027.2880430-1-songliubraving@fb.com>
Some functions that we plan to add trace points require const sk
and/or skb. So we mark these fields as const in the tracepoint.
Signed-off-by: Song Liu <songliubraving@fb.com>
---
include/trace/events/tcp.h | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/include/trace/events/tcp.h b/include/trace/events/tcp.h
index 14b0a708..2b6fe72 100644
--- a/include/trace/events/tcp.h
+++ b/include/trace/events/tcp.h
@@ -17,13 +17,13 @@
*/
DECLARE_EVENT_CLASS(tcp_event_sk_skb,
- TP_PROTO(struct sock *sk, struct sk_buff *skb),
+ TP_PROTO(const struct sock *sk, const struct sk_buff *skb),
TP_ARGS(sk, skb),
TP_STRUCT__entry(
- __field(void *, skbaddr)
- __field(void *, skaddr)
+ __field(const void *, skbaddr)
+ __field(const void *, skaddr)
__field(__u16, sport)
__field(__u16, dport)
__array(__u8, saddr, 4)
@@ -72,7 +72,7 @@ DECLARE_EVENT_CLASS(tcp_event_sk_skb,
DEFINE_EVENT(tcp_event_sk_skb, tcp_retransmit_skb,
- TP_PROTO(struct sock *sk, struct sk_buff *skb),
+ TP_PROTO(const struct sock *sk, const struct sk_buff *skb),
TP_ARGS(sk, skb)
);
--
2.9.5
^ permalink raw reply related
* [PATCH v2 net-next 5/6] tcp: add tracepoint trace_tcp_destroy_sock
From: Song Liu @ 2017-10-23 16:20 UTC (permalink / raw)
To: netdev, davem; +Cc: alexei.starovoitov, liu.song.a23, Song Liu
In-Reply-To: <20171023162027.2880430-1-songliubraving@fb.com>
This patch adds trace event trace_tcp_destroy_sock.
Signed-off-by: Song Liu <songliubraving@fb.com>
---
include/trace/events/tcp.h | 7 +++++++
net/ipv4/tcp_ipv4.c | 2 ++
2 files changed, 9 insertions(+)
diff --git a/include/trace/events/tcp.h b/include/trace/events/tcp.h
index c83c711..1724c12 100644
--- a/include/trace/events/tcp.h
+++ b/include/trace/events/tcp.h
@@ -154,6 +154,13 @@ DEFINE_EVENT(tcp_event_sk, tcp_receive_reset,
TP_ARGS(sk)
);
+DEFINE_EVENT(tcp_event_sk, tcp_destroy_sock,
+
+ TP_PROTO(const struct sock *sk),
+
+ TP_ARGS(sk)
+);
+
#endif /* _TRACE_TCP_H */
/* This part must be outside protection */
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index eb3f3b8..23a8100 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1869,6 +1869,8 @@ void tcp_v4_destroy_sock(struct sock *sk)
{
struct tcp_sock *tp = tcp_sk(sk);
+ trace_tcp_destroy_sock(sk);
+
tcp_clear_xmit_timers(sk);
tcp_cleanup_congestion_control(sk);
--
2.9.5
^ permalink raw reply related
* Re: problem with rtnetlink 'reference' count
From: Peter Zijlstra @ 2017-10-23 16:20 UTC (permalink / raw)
To: Florian Westphal; +Cc: David Miller, netdev
In-Reply-To: <20171023153200.GA12422@breakpoint.cc>
On Mon, Oct 23, 2017 at 05:32:00PM +0200, Florian Westphal wrote:
> > 1) it not in fact a refcount, so using refcount_t is silly
>
> Your suggestion is...?
Normal atomic_t
> > 2) there is a distinct lack of memory barriers, so we can easily
> > observe the decrement while the msg_handler is still in progress.
>
> I guess you mean it needs:
>
> + smp_mb__before_atomic();
> refcount_dec(&rtnl_msg_handlers_ref[family]);
> ?
Yes, but also:
atomic_inc();
smp_mb__after_atomic();
To avoid the problem of te inc being observed late.
> However, this refcount_dec is misplaced anyway as it would need
> to occur from nlcb->done() (the handler function gets stored in socket for
> use by next recvmsg), so this change is indeed not helpful at all.
>
> > 3) waiting with a schedule()/yield() loop is complete crap and subject
> > life-locks, imagine doing that rtnl_unregister_all() from a RT task.
> Alternatively we can of course sleep instead of schedule() but that
> doesn't appear too appealing either (albeit it is a lot less intrusive).
That is much better than a yield loop.
> Any other idea?
This rtnetlink_rcv_msg() is called from softirq-context, right? Also,
all that stuff happens with rcu_read_lock() held.
So why isn't that synchronize_net() call sufficient? You first clear
rtnl_msg_handlers[protocol], and then you do synchronize_net() which
will wait for all concurrent softirq handlers to complete. Which, if
rtnetlink_rcv_msg() is called from softir, guarantees nobody still uses
it.
Also, if that is all softirq, you should maybe use rcu_read_lock_bh(),
alternatively you should use synchronize_rcu(), as is its a bit
inconsistent.
^ permalink raw reply
* Re: [PATCH v2 net-next] tcp: Enable TFO without a cookie on a per-socket basis
From: Christoph Paasch @ 2017-10-23 16:17 UTC (permalink / raw)
To: Yuchung Cheng; +Cc: David Miller, netdev, Eric Dumazet
In-Reply-To: <CAK6E8=da6_xi6fGGXKFE=adhHiRtZHBTZcJOm-9Ac5oa6ufFVw@mail.gmail.com>
Hello,
On 20/10/17 - 17:46:06, Yuchung Cheng wrote:
> On Fri, Oct 20, 2017 at 2:13 PM, Christoph Paasch <cpaasch@apple.com> wrote:
> >
> > We already allow to enable TFO without a cookie by using the
> > fastopen-sysctl and setting it to TFO_SERVER_COOKIE_NOT_REQD (0x200).
> > This is safe to do in certain environments where we know that there
> > isn't a malicous host (aka., data-centers).
> >
> > A server however might be talking to both sides (public Internet and
> > data-center). So, this server would want to enable cookie-less TFO for
> > the connections that go to the data-center while enforcing cookies for
> > the traffic from the Internet.
> >
> > This patch exposes a socket-option to enable this (protected by
> > CAP_NET_ADMIN).
> the protection is removed in this version?
yes, removed it upon suggestion by Eric. I missed to update the commit log.
Will do so in the v3.
>
> >
> > Signed-off-by: Christoph Paasch <cpaasch@apple.com>
> > ---
> >
> > Notes:
> > v2: * Rename to fastopen_no_cookie and TCP_FASTOPEN_NO_COOKIE
> > * Add per-route attribute for fastopen_no_cookie
> > * Get rid of the capability check
> >
> > include/linux/tcp.h | 3 ++-
> > include/net/tcp.h | 3 ++-
> > include/uapi/linux/rtnetlink.h | 2 ++
> > include/uapi/linux/tcp.h | 1 +
> > net/ipv4/tcp.c | 12 ++++++++++++
> > net/ipv4/tcp_fastopen.c | 14 +++++++++++---
> > net/ipv4/tcp_input.c | 2 +-
> > 7 files changed, 31 insertions(+), 6 deletions(-)
> >
> > diff --git a/include/linux/tcp.h b/include/linux/tcp.h
> > index 1d2c44e09e31..173a7c2f9636 100644
> > --- a/include/linux/tcp.h
> > +++ b/include/linux/tcp.h
> > @@ -215,7 +215,8 @@ struct tcp_sock {
> > u8 chrono_type:2, /* current chronograph type */
> > rate_app_limited:1, /* rate_{delivered,interval_us} limited? */
> > fastopen_connect:1, /* FASTOPEN_CONNECT sockopt */
> > - unused:4;
> > + fastopen_no_cookie:1, /* Allow send/recv SYN+data without a cookie */
> > + unused:3;
> > u8 nonagle : 4,/* Disable Nagle algorithm? */
> > thin_lto : 1,/* Use linear timeouts for thin streams */
> > unused1 : 1,
> > diff --git a/include/net/tcp.h b/include/net/tcp.h
> > index 1efe8365cb28..020b20c3f50a 100644
> > --- a/include/net/tcp.h
> > +++ b/include/net/tcp.h
> > @@ -1562,7 +1562,8 @@ int tcp_fastopen_reset_cipher(struct net *net, struct sock *sk,
> > void tcp_fastopen_add_skb(struct sock *sk, struct sk_buff *skb);
> > struct sock *tcp_try_fastopen(struct sock *sk, struct sk_buff *skb,
> > struct request_sock *req,
> > - struct tcp_fastopen_cookie *foc);
> > + struct tcp_fastopen_cookie *foc,
> > + const struct dst_entry *dst);
> > void tcp_fastopen_init_key_once(struct net *net);
> > bool tcp_fastopen_cookie_check(struct sock *sk, u16 *mss,
> > struct tcp_fastopen_cookie *cookie);
> > diff --git a/include/uapi/linux/rtnetlink.h b/include/uapi/linux/rtnetlink.h
> > index dab7dad9e01a..fe6679268901 100644
> > --- a/include/uapi/linux/rtnetlink.h
> > +++ b/include/uapi/linux/rtnetlink.h
> > @@ -430,6 +430,8 @@ enum {
> > #define RTAX_QUICKACK RTAX_QUICKACK
> > RTAX_CC_ALGO,
> > #define RTAX_CC_ALGO RTAX_CC_ALGO
> > + RTAX_FASTOPEN_NO_COOKIE,
> > +#define RTAX_FASTOPEN_NO_COOKIE RTAX_FASTOPEN_NO_COOKIE
> > __RTAX_MAX
> > };
> >
> > diff --git a/include/uapi/linux/tcp.h b/include/uapi/linux/tcp.h
> > index 69c7493e42f8..d67e1d40c6d6 100644
> > --- a/include/uapi/linux/tcp.h
> > +++ b/include/uapi/linux/tcp.h
> > @@ -120,6 +120,7 @@ enum {
> > #define TCP_ULP 31 /* Attach a ULP to a TCP connection */
> > #define TCP_MD5SIG_EXT 32 /* TCP MD5 Signature with extensions */
> > #define TCP_FASTOPEN_KEY 33 /* Set the key for Fast Open (cookie) */
> > +#define TCP_FASTOPEN_NO_COOKIE 34 /* Enable TFO without a TFO cookie */
> >
> > struct tcp_repair_opt {
> > __u32 opt_code;
> > diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
> > index 8b1fa4dd4538..a3d46a781abd 100644
> > --- a/net/ipv4/tcp.c
> > +++ b/net/ipv4/tcp.c
> > @@ -2832,6 +2832,14 @@ static int do_tcp_setsockopt(struct sock *sk, int level,
> > err = -EOPNOTSUPP;
> > }
> > break;
> > + case TCP_FASTOPEN_NO_COOKIE:
> > + if (val > 1 || val < 0)
> > + err = -EINVAL;
> > + else if (!((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN)))
> > + err = -EINVAL;
> > + else
> > + tp->fastopen_no_cookie = 1;
> > + break;
> > case TCP_TIMESTAMP:
> > if (!tp->repair)
> > err = -EPERM;
> > @@ -3252,6 +3260,10 @@ static int do_tcp_getsockopt(struct sock *sk, int level,
> > val = tp->fastopen_connect;
> > break;
> >
> > + case TCP_FASTOPEN_NO_COOKIE:
> > + val = tp->fastopen_no_cookie;
> > + break;
> > +
> > case TCP_TIMESTAMP:
> > val = tcp_time_stamp_raw() + tp->tsoffset;
> > break;
> > diff --git a/net/ipv4/tcp_fastopen.c b/net/ipv4/tcp_fastopen.c
> > index 21075ce19cb6..e704bd86fdf9 100644
> > --- a/net/ipv4/tcp_fastopen.c
> > +++ b/net/ipv4/tcp_fastopen.c
> > @@ -316,7 +316,8 @@ static bool tcp_fastopen_queue_check(struct sock *sk)
> > */
> > struct sock *tcp_try_fastopen(struct sock *sk, struct sk_buff *skb,
> > struct request_sock *req,
> > - struct tcp_fastopen_cookie *foc)
> > + struct tcp_fastopen_cookie *foc,
> > + const struct dst_entry *dst)
> > {
> > bool syn_data = TCP_SKB_CB(skb)->end_seq != TCP_SKB_CB(skb)->seq + 1;
> > int tcp_fastopen = sock_net(sk)->ipv4.sysctl_tcp_fastopen;
> > @@ -333,7 +334,9 @@ struct sock *tcp_try_fastopen(struct sock *sk, struct sk_buff *skb,
> > return NULL;
> > }
> >
> > - if (syn_data && (tcp_fastopen & TFO_SERVER_COOKIE_NOT_REQD))
> > + if (syn_data && ((tcp_fastopen & TFO_SERVER_COOKIE_NOT_REQD) ||
> > + tcp_sk(sk)->fastopen_no_cookie ||
> > + (dst && dst_metric(dst, RTAX_FASTOPEN_NO_COOKIE))))
> > goto fastopen;
> >
> > if (foc->len >= 0 && /* Client presents or requests a cookie */
> > @@ -370,6 +373,7 @@ bool tcp_fastopen_cookie_check(struct sock *sk, u16 *mss,
> > struct tcp_fastopen_cookie *cookie)
> > {
> > unsigned long last_syn_loss = 0;
> > + const struct dst_entry *dst;
> > int syn_loss = 0;
> >
> > tcp_fastopen_cache_get(sk, mss, cookie, &syn_loss, &last_syn_loss);
> > @@ -387,7 +391,11 @@ bool tcp_fastopen_cookie_check(struct sock *sk, u16 *mss,
> > return false;
> > }
> >
> > - if (sock_net(sk)->ipv4.sysctl_tcp_fastopen & TFO_CLIENT_NO_COOKIE) {
> > + dst = __sk_dst_get(sk);
> > +
> > + if ((sock_net(sk)->ipv4.sysctl_tcp_fastopen & TFO_CLIENT_NO_COOKIE) ||
> > + tcp_sk(sk)->fastopen_no_cookie ||
> > + (dst && dst_metric(dst, RTAX_FASTOPEN_NO_COOKIE))) {
> perhaps a helper e.g. tcp_fastopen_needs_cookie(syscl_flag) for this
> function and tcp_try_fastopen() to tidy the code a bit?
Sure, I will create a helper.
Thanks,
Christoph
^ permalink raw reply
* Re: [for-next 08/12] net/mlx5e: IPoIB, Use hash-table to map between QPN to child netdev
From: Jason Gunthorpe @ 2017-10-23 15:47 UTC (permalink / raw)
To: Saeed Mahameed
Cc: David S. Miller, Doug Ledford, netdev-u79uwXL29TY76Z2rM5mHXA,
linux-rdma-u79uwXL29TY76Z2rM5mHXA, Leon Romanovsky, Alex Vesker
In-Reply-To: <20171014184827.18491-9-saeedm-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
On Sat, Oct 14, 2017 at 11:48:23AM -0700, Saeed Mahameed wrote:
> From: Alex Vesker <valex-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
>
> This change is needed for PKEY support, since the RQs are shared
> between the child interface and the parent. The parent is responsible
> for NAPI and the precessing of RX completions. Using the dqpn in the
> completion descriptor we set the corresponding child IPoIB netdevice
> on the SKB.
> The mapping between the dqpn and the netdevice is done using a HT,
> each mlx5 IPoIB interface registers its mapping on creation.
It seems really really weird to share the receive Q across all of the
children and do the sorting in software.. why is this done like this?
Wouldn't it be better to allow the children to progress concurrently,
potentially on multiple cores? They all have their own QPs after all..
Jason
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [patch net v2 1/4] net/sched: Change tc_action refcnt and bindcnt to atomic
From: Cong Wang @ 2017-10-23 15:39 UTC (permalink / raw)
To: Chris Mi
Cc: Jamal Hadi Salim, Linux Kernel Network Developers, Lucas Bates,
Jiri Pirko, David Miller
In-Reply-To: <VI1PR0501MB2143994E767A6C7C9BE1754AAB460@VI1PR0501MB2143.eurprd05.prod.outlook.com>
On Sun, Oct 22, 2017 at 7:47 PM, Chris Mi <chrism@mellanox.com> wrote:
>
> It seems it is not easy to discard call_rcu(). I'm afraid even if we have a final solution
> without call_rcu(), it is not mature at the beginning as well. I mean we also need time
Why do you believe it is not easy? RTNL lock is already there,
list_splice_init_rcu() is there too. I can naturally divide my patches
for each module so that they are much easier to backport than
yours.
> to fix the possible bugs of the new design. And maybe to destroy the filters in parallel
> is the right direction. If this bug is the last bug brought by call_rcu(), then changing it
> may not be a good idea.
Again, you have to prove this is the last bug, I seriously doubt
it is.
>
> Patch 1 is straightforward to use atomic. Patch 2 is to convert the list to array.
Both are big in size.
> I think there is no harm to the new design. Patch 3 and 4 are useful test case.
It definitely doesn't harm, but why do we waste time on it when we
know there is a better way? It is clearly not easy for backport either,
in fact it is harder w.r.t. size.
> We also need it with new design to make sure there is no regression.
>
Are you saying I can't trust your test cases? ;)
> So I think my patch set should not be held so long time.
I think your patches should be dropped except the last two,
I will take the last two for you.
Thanks!
^ permalink raw reply
* [PATCH v2] net/sock: Update sk rcu iterator macro.
From: Tim Hansen @ 2017-10-23 15:39 UTC (permalink / raw)
To: davem; +Cc: netdev, linux-kernel, alexander.levin, devtimhansen
Mark hlist nodes in sk rcu iterator as protected by the rcu.
hlist_next_rcu accomplishes this and silences the warnings
sparse throws for net/ipv4/udp.c and net/ipv6/udp.c.
Found with make C=1 net/ipv4/udp.o on linux-next tag
next-20171009.
Signed-off-by: Tim Hansen <devtimhansen@gmail.com>
---
include/net/sock.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/include/net/sock.h b/include/net/sock.h
index 64e5ac41b9cf..96cb7b7e4924 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -737,10 +737,10 @@ static inline void sk_add_bind_node(struct sock *sk,
*
*/
#define sk_for_each_entry_offset_rcu(tpos, pos, head, offset) \
- for (pos = rcu_dereference((head)->first); \
+ for (pos = rcu_dereference(hlist_next_rcu((head)->first)); \
pos != NULL && \
({ tpos = (typeof(*tpos) *)((void *)pos - offset); 1;}); \
- pos = rcu_dereference(pos->next))
+ pos = rcu_dereference(hlist_next_rcu(pos->next)))
static inline struct user_namespace *sk_user_ns(struct sock *sk)
{
--
2.15.0.rc0
^ permalink raw reply related
* [PATCH 3/3] batman-adv: use inline kernel-doc for uapi constants
From: Simon Wunderlich @ 2017-10-23 15:37 UTC (permalink / raw)
To: davem; +Cc: netdev, b.a.t.m.a.n, Sven Eckelmann, Simon Wunderlich
In-Reply-To: <20171023153704.32120-1-sw@simonwunderlich.de>
From: Sven Eckelmann <sven@narfation.org>
The enums of constants for netlink tends to become rather large over time.
Documenting them is easier when the kernel-doc is actually next to constant
and not in a different block above the enum.
Also inline kernel-doc allows multi-paragraph description. This could be
required to better document the netlink command types and the expected
return values.
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
---
include/uapi/linux/batman_adv.h | 369 +++++++++++++++++++++++++++++++---------
1 file changed, 290 insertions(+), 79 deletions(-)
diff --git a/include/uapi/linux/batman_adv.h b/include/uapi/linux/batman_adv.h
index a83ddb7b63db..efd641c8a5d6 100644
--- a/include/uapi/linux/batman_adv.h
+++ b/include/uapi/linux/batman_adv.h
@@ -24,20 +24,6 @@
/**
* enum batadv_tt_client_flags - TT client specific flags
- * @BATADV_TT_CLIENT_DEL: the client has to be deleted from the table
- * @BATADV_TT_CLIENT_ROAM: the client roamed to/from another node and the new
- * update telling its new real location has not been received/sent yet
- * @BATADV_TT_CLIENT_WIFI: this client is connected through a wifi interface.
- * This information is used by the "AP Isolation" feature
- * @BATADV_TT_CLIENT_ISOLA: this client is considered "isolated". This
- * information is used by the Extended Isolation feature
- * @BATADV_TT_CLIENT_NOPURGE: this client should never be removed from the table
- * @BATADV_TT_CLIENT_NEW: this client has been added to the local table but has
- * not been announced yet
- * @BATADV_TT_CLIENT_PENDING: this client is marked for removal but it is kept
- * in the table for one more originator interval for consistency purposes
- * @BATADV_TT_CLIENT_TEMP: this global client has been detected to be part of
- * the network but no nnode has already announced it
*
* Bits from 0 to 7 are called _remote flags_ because they are sent on the wire.
* Bits from 8 to 15 are called _local flags_ because they are used for local
@@ -48,160 +34,385 @@
* in the TT CRC computation.
*/
enum batadv_tt_client_flags {
+ /**
+ * @BATADV_TT_CLIENT_DEL: the client has to be deleted from the table
+ */
BATADV_TT_CLIENT_DEL = (1 << 0),
+
+ /**
+ * @BATADV_TT_CLIENT_ROAM: the client roamed to/from another node and
+ * the new update telling its new real location has not been
+ * received/sent yet
+ */
BATADV_TT_CLIENT_ROAM = (1 << 1),
+
+ /**
+ * @BATADV_TT_CLIENT_WIFI: this client is connected through a wifi
+ * interface. This information is used by the "AP Isolation" feature
+ */
BATADV_TT_CLIENT_WIFI = (1 << 4),
+
+ /**
+ * @BATADV_TT_CLIENT_ISOLA: this client is considered "isolated". This
+ * information is used by the Extended Isolation feature
+ */
BATADV_TT_CLIENT_ISOLA = (1 << 5),
+
+ /**
+ * @BATADV_TT_CLIENT_NOPURGE: this client should never be removed from
+ * the table
+ */
BATADV_TT_CLIENT_NOPURGE = (1 << 8),
+
+ /**
+ * @BATADV_TT_CLIENT_NEW: this client has been added to the local table
+ * but has not been announced yet
+ */
BATADV_TT_CLIENT_NEW = (1 << 9),
+
+ /**
+ * @BATADV_TT_CLIENT_PENDING: this client is marked for removal but it
+ * is kept in the table for one more originator interval for consistency
+ * purposes
+ */
BATADV_TT_CLIENT_PENDING = (1 << 10),
+
+ /**
+ * @BATADV_TT_CLIENT_TEMP: this global client has been detected to be
+ * part of the network but no nnode has already announced it
+ */
BATADV_TT_CLIENT_TEMP = (1 << 11),
};
/**
* enum batadv_nl_attrs - batman-adv netlink attributes
- *
- * @BATADV_ATTR_UNSPEC: unspecified attribute to catch errors
- * @BATADV_ATTR_VERSION: batman-adv version string
- * @BATADV_ATTR_ALGO_NAME: name of routing algorithm
- * @BATADV_ATTR_MESH_IFINDEX: index of the batman-adv interface
- * @BATADV_ATTR_MESH_IFNAME: name of the batman-adv interface
- * @BATADV_ATTR_MESH_ADDRESS: mac address of the batman-adv interface
- * @BATADV_ATTR_HARD_IFINDEX: index of the non-batman-adv interface
- * @BATADV_ATTR_HARD_IFNAME: name of the non-batman-adv interface
- * @BATADV_ATTR_HARD_ADDRESS: mac address of the non-batman-adv interface
- * @BATADV_ATTR_ORIG_ADDRESS: originator mac address
- * @BATADV_ATTR_TPMETER_RESULT: result of run (see batadv_tp_meter_status)
- * @BATADV_ATTR_TPMETER_TEST_TIME: time (msec) the run took
- * @BATADV_ATTR_TPMETER_BYTES: amount of acked bytes during run
- * @BATADV_ATTR_TPMETER_COOKIE: session cookie to match tp_meter session
- * @BATADV_ATTR_PAD: attribute used for padding for 64-bit alignment
- * @BATADV_ATTR_ACTIVE: Flag indicating if the hard interface is active
- * @BATADV_ATTR_TT_ADDRESS: Client MAC address
- * @BATADV_ATTR_TT_TTVN: Translation table version
- * @BATADV_ATTR_TT_LAST_TTVN: Previous translation table version
- * @BATADV_ATTR_TT_CRC32: CRC32 over translation table
- * @BATADV_ATTR_TT_VID: VLAN ID
- * @BATADV_ATTR_TT_FLAGS: Translation table client flags
- * @BATADV_ATTR_FLAG_BEST: Flags indicating entry is the best
- * @BATADV_ATTR_LAST_SEEN_MSECS: Time in milliseconds since last seen
- * @BATADV_ATTR_NEIGH_ADDRESS: Neighbour MAC address
- * @BATADV_ATTR_TQ: TQ to neighbour
- * @BATADV_ATTR_THROUGHPUT: Estimated throughput to Neighbour
- * @BATADV_ATTR_BANDWIDTH_UP: Reported uplink bandwidth
- * @BATADV_ATTR_BANDWIDTH_DOWN: Reported downlink bandwidth
- * @BATADV_ATTR_ROUTER: Gateway router MAC address
- * @BATADV_ATTR_BLA_OWN: Flag indicating own originator
- * @BATADV_ATTR_BLA_ADDRESS: Bridge loop avoidance claim MAC address
- * @BATADV_ATTR_BLA_VID: BLA VLAN ID
- * @BATADV_ATTR_BLA_BACKBONE: BLA gateway originator MAC address
- * @BATADV_ATTR_BLA_CRC: BLA CRC
- * @__BATADV_ATTR_AFTER_LAST: internal use
- * @NUM_BATADV_ATTR: total number of batadv_nl_attrs available
- * @BATADV_ATTR_MAX: highest attribute number currently defined
*/
enum batadv_nl_attrs {
+ /**
+ * @BATADV_ATTR_UNSPEC: unspecified attribute to catch errors
+ */
BATADV_ATTR_UNSPEC,
+
+ /**
+ * @BATADV_ATTR_VERSION: batman-adv version string
+ */
BATADV_ATTR_VERSION,
+
+ /**
+ * @BATADV_ATTR_ALGO_NAME: name of routing algorithm
+ */
BATADV_ATTR_ALGO_NAME,
+
+ /**
+ * @BATADV_ATTR_MESH_IFINDEX: index of the batman-adv interface
+ */
BATADV_ATTR_MESH_IFINDEX,
+
+ /**
+ * @BATADV_ATTR_MESH_IFNAME: name of the batman-adv interface
+ */
BATADV_ATTR_MESH_IFNAME,
+
+ /**
+ * @BATADV_ATTR_MESH_ADDRESS: mac address of the batman-adv interface
+ */
BATADV_ATTR_MESH_ADDRESS,
+
+ /**
+ * @BATADV_ATTR_HARD_IFINDEX: index of the non-batman-adv interface
+ */
BATADV_ATTR_HARD_IFINDEX,
+
+ /**
+ * @BATADV_ATTR_HARD_IFNAME: name of the non-batman-adv interface
+ */
BATADV_ATTR_HARD_IFNAME,
+
+ /**
+ * @BATADV_ATTR_HARD_ADDRESS: mac address of the non-batman-adv
+ * interface
+ */
BATADV_ATTR_HARD_ADDRESS,
+
+ /**
+ * @BATADV_ATTR_ORIG_ADDRESS: originator mac address
+ */
BATADV_ATTR_ORIG_ADDRESS,
+
+ /**
+ * @BATADV_ATTR_TPMETER_RESULT: result of run (see
+ * batadv_tp_meter_status)
+ */
BATADV_ATTR_TPMETER_RESULT,
+
+ /**
+ * @BATADV_ATTR_TPMETER_TEST_TIME: time (msec) the run took
+ */
BATADV_ATTR_TPMETER_TEST_TIME,
+
+ /**
+ * @BATADV_ATTR_TPMETER_BYTES: amount of acked bytes during run
+ */
BATADV_ATTR_TPMETER_BYTES,
+
+ /**
+ * @BATADV_ATTR_TPMETER_COOKIE: session cookie to match tp_meter session
+ */
BATADV_ATTR_TPMETER_COOKIE,
+
+ /**
+ * @BATADV_ATTR_PAD: attribute used for padding for 64-bit alignment
+ */
BATADV_ATTR_PAD,
+
+ /**
+ * @BATADV_ATTR_ACTIVE: Flag indicating if the hard interface is active
+ */
BATADV_ATTR_ACTIVE,
+
+ /**
+ * @BATADV_ATTR_TT_ADDRESS: Client MAC address
+ */
BATADV_ATTR_TT_ADDRESS,
+
+ /**
+ * @BATADV_ATTR_TT_TTVN: Translation table version
+ */
BATADV_ATTR_TT_TTVN,
+
+ /**
+ * @BATADV_ATTR_TT_LAST_TTVN: Previous translation table version
+ */
BATADV_ATTR_TT_LAST_TTVN,
+
+ /**
+ * @BATADV_ATTR_TT_CRC32: CRC32 over translation table
+ */
BATADV_ATTR_TT_CRC32,
+
+ /**
+ * @BATADV_ATTR_TT_VID: VLAN ID
+ */
BATADV_ATTR_TT_VID,
+
+ /**
+ * @BATADV_ATTR_TT_FLAGS: Translation table client flags
+ */
BATADV_ATTR_TT_FLAGS,
+
+ /**
+ * @BATADV_ATTR_FLAG_BEST: Flags indicating entry is the best
+ */
BATADV_ATTR_FLAG_BEST,
+
+ /**
+ * @BATADV_ATTR_LAST_SEEN_MSECS: Time in milliseconds since last seen
+ */
BATADV_ATTR_LAST_SEEN_MSECS,
+
+ /**
+ * @BATADV_ATTR_NEIGH_ADDRESS: Neighbour MAC address
+ */
BATADV_ATTR_NEIGH_ADDRESS,
+
+ /**
+ * @BATADV_ATTR_TQ: TQ to neighbour
+ */
BATADV_ATTR_TQ,
+
+ /**
+ * @BATADV_ATTR_THROUGHPUT: Estimated throughput to Neighbour
+ */
BATADV_ATTR_THROUGHPUT,
+
+ /**
+ * @BATADV_ATTR_BANDWIDTH_UP: Reported uplink bandwidth
+ */
BATADV_ATTR_BANDWIDTH_UP,
+
+ /**
+ * @BATADV_ATTR_BANDWIDTH_DOWN: Reported downlink bandwidth
+ */
BATADV_ATTR_BANDWIDTH_DOWN,
+
+ /**
+ * @BATADV_ATTR_ROUTER: Gateway router MAC address
+ */
BATADV_ATTR_ROUTER,
+
+ /**
+ * @BATADV_ATTR_BLA_OWN: Flag indicating own originator
+ */
BATADV_ATTR_BLA_OWN,
+
+ /**
+ * @BATADV_ATTR_BLA_ADDRESS: Bridge loop avoidance claim MAC address
+ */
BATADV_ATTR_BLA_ADDRESS,
+
+ /**
+ * @BATADV_ATTR_BLA_VID: BLA VLAN ID
+ */
BATADV_ATTR_BLA_VID,
+
+ /**
+ * @BATADV_ATTR_BLA_BACKBONE: BLA gateway originator MAC address
+ */
BATADV_ATTR_BLA_BACKBONE,
+
+ /**
+ * @BATADV_ATTR_BLA_CRC: BLA CRC
+ */
BATADV_ATTR_BLA_CRC,
+
/* add attributes above here, update the policy in netlink.c */
+
+ /**
+ * @__BATADV_ATTR_AFTER_LAST: internal use
+ */
__BATADV_ATTR_AFTER_LAST,
+
+ /**
+ * @NUM_BATADV_ATTR: total number of batadv_nl_attrs available
+ */
NUM_BATADV_ATTR = __BATADV_ATTR_AFTER_LAST,
+
+ /**
+ * @BATADV_ATTR_MAX: highest attribute number currently defined
+ */
BATADV_ATTR_MAX = __BATADV_ATTR_AFTER_LAST - 1
};
/**
* enum batadv_nl_commands - supported batman-adv netlink commands
- *
- * @BATADV_CMD_UNSPEC: unspecified command to catch errors
- * @BATADV_CMD_GET_MESH_INFO: Query basic information about batman-adv device
- * @BATADV_CMD_TP_METER: Start a tp meter session
- * @BATADV_CMD_TP_METER_CANCEL: Cancel a tp meter session
- * @BATADV_CMD_GET_ROUTING_ALGOS: Query the list of routing algorithms.
- * @BATADV_CMD_GET_HARDIFS: Query list of hard interfaces
- * @BATADV_CMD_GET_TRANSTABLE_LOCAL: Query list of local translations
- * @BATADV_CMD_GET_TRANSTABLE_GLOBAL Query list of global translations
- * @BATADV_CMD_GET_ORIGINATORS: Query list of originators
- * @BATADV_CMD_GET_NEIGHBORS: Query list of neighbours
- * @BATADV_CMD_GET_GATEWAYS: Query list of gateways
- * @BATADV_CMD_GET_BLA_CLAIM: Query list of bridge loop avoidance claims
- * @BATADV_CMD_GET_BLA_BACKBONE: Query list of bridge loop avoidance backbones
- * @__BATADV_CMD_AFTER_LAST: internal use
- * @BATADV_CMD_MAX: highest used command number
*/
enum batadv_nl_commands {
+ /**
+ * @BATADV_CMD_UNSPEC: unspecified command to catch errors
+ */
BATADV_CMD_UNSPEC,
+
+ /**
+ * @BATADV_CMD_GET_MESH_INFO: Query basic information about batman-adv
+ * device
+ */
BATADV_CMD_GET_MESH_INFO,
+
+ /**
+ * @BATADV_CMD_TP_METER: Start a tp meter session
+ */
BATADV_CMD_TP_METER,
+
+ /**
+ * @BATADV_CMD_TP_METER_CANCEL: Cancel a tp meter session
+ */
BATADV_CMD_TP_METER_CANCEL,
+
+ /**
+ * @BATADV_CMD_GET_ROUTING_ALGOS: Query the list of routing algorithms.
+ */
BATADV_CMD_GET_ROUTING_ALGOS,
+
+ /**
+ * @BATADV_CMD_GET_HARDIFS: Query list of hard interfaces
+ */
BATADV_CMD_GET_HARDIFS,
+
+ /**
+ * @BATADV_CMD_GET_TRANSTABLE_LOCAL: Query list of local translations
+ */
BATADV_CMD_GET_TRANSTABLE_LOCAL,
+
+ /**
+ * @BATADV_CMD_GET_TRANSTABLE_GLOBAL: Query list of global translations
+ */
BATADV_CMD_GET_TRANSTABLE_GLOBAL,
+
+ /**
+ * @BATADV_CMD_GET_ORIGINATORS: Query list of originators
+ */
BATADV_CMD_GET_ORIGINATORS,
+
+ /**
+ * @BATADV_CMD_GET_NEIGHBORS: Query list of neighbours
+ */
BATADV_CMD_GET_NEIGHBORS,
+
+ /**
+ * @BATADV_CMD_GET_GATEWAYS: Query list of gateways
+ */
BATADV_CMD_GET_GATEWAYS,
+
+ /**
+ * @BATADV_CMD_GET_BLA_CLAIM: Query list of bridge loop avoidance claims
+ */
BATADV_CMD_GET_BLA_CLAIM,
+
+ /**
+ * @BATADV_CMD_GET_BLA_BACKBONE: Query list of bridge loop avoidance
+ * backbones
+ */
BATADV_CMD_GET_BLA_BACKBONE,
+
/* add new commands above here */
+
+ /**
+ * @__BATADV_CMD_AFTER_LAST: internal use
+ */
__BATADV_CMD_AFTER_LAST,
+
+ /**
+ * @BATADV_CMD_MAX: highest used command number
+ */
BATADV_CMD_MAX = __BATADV_CMD_AFTER_LAST - 1
};
/**
* enum batadv_tp_meter_reason - reason of a tp meter test run stop
- * @BATADV_TP_REASON_COMPLETE: sender finished tp run
- * @BATADV_TP_REASON_CANCEL: sender was stopped during run
- * @BATADV_TP_REASON_DST_UNREACHABLE: receiver could not be reached or didn't
- * answer
- * @BATADV_TP_REASON_RESEND_LIMIT: (unused) sender retry reached limit
- * @BATADV_TP_REASON_ALREADY_ONGOING: test to or from the same node already
- * ongoing
- * @BATADV_TP_REASON_MEMORY_ERROR: test was stopped due to low memory
- * @BATADV_TP_REASON_CANT_SEND: failed to send via outgoing interface
- * @BATADV_TP_REASON_TOO_MANY: too many ongoing sessions
*/
enum batadv_tp_meter_reason {
+ /**
+ * @BATADV_TP_REASON_COMPLETE: sender finished tp run
+ */
BATADV_TP_REASON_COMPLETE = 3,
+
+ /**
+ * @BATADV_TP_REASON_CANCEL: sender was stopped during run
+ */
BATADV_TP_REASON_CANCEL = 4,
+
/* error status >= 128 */
+
+ /**
+ * @BATADV_TP_REASON_DST_UNREACHABLE: receiver could not be reached or
+ * didn't answer
+ */
BATADV_TP_REASON_DST_UNREACHABLE = 128,
+
+ /**
+ * @BATADV_TP_REASON_RESEND_LIMIT: (unused) sender retry reached limit
+ */
BATADV_TP_REASON_RESEND_LIMIT = 129,
+
+ /**
+ * @BATADV_TP_REASON_ALREADY_ONGOING: test to or from the same node
+ * already ongoing
+ */
BATADV_TP_REASON_ALREADY_ONGOING = 130,
+
+ /**
+ * @BATADV_TP_REASON_MEMORY_ERROR: test was stopped due to low memory
+ */
BATADV_TP_REASON_MEMORY_ERROR = 131,
+
+ /**
+ * @BATADV_TP_REASON_CANT_SEND: failed to send via outgoing interface
+ */
BATADV_TP_REASON_CANT_SEND = 132,
+
+ /**
+ * @BATADV_TP_REASON_TOO_MANY: too many ongoing sessions
+ */
BATADV_TP_REASON_TOO_MANY = 133,
};
--
2.11.0
^ permalink raw reply related
* [PATCH 0/3] pull request for net-next: batman-adv 2017-10-23
From: Simon Wunderlich @ 2017-10-23 15:37 UTC (permalink / raw)
To: davem; +Cc: netdev, b.a.t.m.a.n, Simon Wunderlich
Hi David,
here is another small documentation/cleanup pull request of batman-adv to go
into net-next.
Please pull or let me know of any problem!
Thank you,
Simon
The following changes since commit 4bc4e64c2cfdafa6b8ecdcc5edf10cc1a147587f:
Merge tag 'batadv-next-for-davem-20171006' of git://git.open-mesh.org/linux-merge (2017-10-06 10:12:52 -0700)
are available in the git repository at:
git://git.open-mesh.org/linux-merge.git tags/batadv-next-for-davem-20171023
for you to fetch changes up to 40b16b9be5773a314948656c96adf7bf7cfdbd0b:
batman-adv: use inline kernel-doc for uapi constants (2017-10-23 14:22:25 +0200)
----------------------------------------------------------------
This documentation/cleanup patchset includes the following patches:
- Fix parameter kerneldoc which caused kerneldoc warnings, by Sven Eckelmann
- Remove spurious warnings in B.A.T.M.A.N. V neighbor comparison,
by Sven Eckelmann
- Use inline kernel-doc style for UAPI constants, by Sven Eckelmann
----------------------------------------------------------------
Sven Eckelmann (3):
batman-adv: Add missing kerneldoc for extack
batman-adv: Avoid spurious warnings from bat_v neigh_cmp implementation
batman-adv: use inline kernel-doc for uapi constants
include/uapi/linux/batman_adv.h | 369 +++++++++++++++++++++++++++++++---------
net/batman-adv/bat_v.c | 9 +-
net/batman-adv/soft-interface.c | 1 +
3 files changed, 295 insertions(+), 84 deletions(-)
^ permalink raw reply
* [PATCH 1/3] batman-adv: Add missing kerneldoc for extack
From: Simon Wunderlich @ 2017-10-23 15:37 UTC (permalink / raw)
To: davem; +Cc: netdev, b.a.t.m.a.n, Sven Eckelmann, Simon Wunderlich
In-Reply-To: <20171023153704.32120-1-sw@simonwunderlich.de>
From: Sven Eckelmann <sven@narfation.org>
The parameter extack was added to batadv_softif_slave_add without adding
the kernel-doc for it. This caused kernel-doc warnings.
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Acked-by: David Ahern <dsahern@gmail.com>
Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
---
net/batman-adv/soft-interface.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c
index 543d2c3e0f0d..9f673cdfecf8 100644
--- a/net/batman-adv/soft-interface.c
+++ b/net/batman-adv/soft-interface.c
@@ -863,6 +863,7 @@ static int batadv_softif_init_late(struct net_device *dev)
* batadv_softif_slave_add - Add a slave interface to a batadv_soft_interface
* @dev: batadv_soft_interface used as master interface
* @slave_dev: net_device which should become the slave interface
+ * @extack: extended ACK report struct
*
* Return: 0 if successful or error otherwise.
*/
--
2.11.0
^ permalink raw reply related
* [PATCH 2/3] batman-adv: Avoid spurious warnings from bat_v neigh_cmp implementation
From: Simon Wunderlich @ 2017-10-23 15:37 UTC (permalink / raw)
To: davem; +Cc: netdev, b.a.t.m.a.n, Sven Eckelmann, Simon Wunderlich
In-Reply-To: <20171023153704.32120-1-sw@simonwunderlich.de>
From: Sven Eckelmann <sven.eckelmann@openmesh.com>
The neighbor compare API implementation for B.A.T.M.A.N. V checks whether
the neigh_ifinfo for this neighbor on a specific interface exists. A
warning is printed when it isn't found.
But it is not called inside a lock which would prevent that this
information is lost right before batadv_neigh_ifinfo_get. It must therefore
be expected that batadv_v_neigh_(cmp|is_sob) might not be able to get the
requested neigh_ifinfo.
A WARN_ON for such a situation seems not to be appropriate because this
will only flood the kernel logs. The warnings must therefore be removed.
Signed-off-by: Sven Eckelmann <sven.eckelmann@openmesh.com>
Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
---
net/batman-adv/bat_v.c | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/net/batman-adv/bat_v.c b/net/batman-adv/bat_v.c
index 93ef1c06227e..341ceab8338d 100644
--- a/net/batman-adv/bat_v.c
+++ b/net/batman-adv/bat_v.c
@@ -19,7 +19,6 @@
#include "main.h"
#include <linux/atomic.h>
-#include <linux/bug.h>
#include <linux/cache.h>
#include <linux/errno.h>
#include <linux/if_ether.h>
@@ -623,11 +622,11 @@ static int batadv_v_neigh_cmp(struct batadv_neigh_node *neigh1,
int ret = 0;
ifinfo1 = batadv_neigh_ifinfo_get(neigh1, if_outgoing1);
- if (WARN_ON(!ifinfo1))
+ if (!ifinfo1)
goto err_ifinfo1;
ifinfo2 = batadv_neigh_ifinfo_get(neigh2, if_outgoing2);
- if (WARN_ON(!ifinfo2))
+ if (!ifinfo2)
goto err_ifinfo2;
ret = ifinfo1->bat_v.throughput - ifinfo2->bat_v.throughput;
@@ -649,11 +648,11 @@ static bool batadv_v_neigh_is_sob(struct batadv_neigh_node *neigh1,
bool ret = false;
ifinfo1 = batadv_neigh_ifinfo_get(neigh1, if_outgoing1);
- if (WARN_ON(!ifinfo1))
+ if (!ifinfo1)
goto err_ifinfo1;
ifinfo2 = batadv_neigh_ifinfo_get(neigh2, if_outgoing2);
- if (WARN_ON(!ifinfo2))
+ if (!ifinfo2)
goto err_ifinfo2;
threshold = ifinfo1->bat_v.throughput / 4;
--
2.11.0
^ permalink raw reply related
* Re: problem with rtnetlink 'reference' count
From: Florian Westphal @ 2017-10-23 15:32 UTC (permalink / raw)
To: Peter Zijlstra; +Cc: David Miller, fw, netdev
In-Reply-To: <20171023142555.GF3165@worktop.lehotels.local>
Peter Zijlstra <peterz@infradead.org> wrote:
> 019a316992ee ("rtnetlink: add reference counting to prevent module unload while dump is in progress")
>
> And that commit is _completely_ broken.
>
> 1) it not in fact a refcount, so using refcount_t is silly
Your suggestion is...?
> 2) there is a distinct lack of memory barriers, so we can easily
> observe the decrement while the msg_handler is still in progress.
I guess you mean it needs:
+ smp_mb__before_atomic();
refcount_dec(&rtnl_msg_handlers_ref[family]);
?
However, this refcount_dec is misplaced anyway as it would need
to occur from nlcb->done() (the handler function gets stored in socket for
use by next recvmsg), so this change is indeed not helpful at all.
> 3) waiting with a schedule()/yield() loop is complete crap and subject
> life-locks, imagine doing that rtnl_unregister_all() from a RT task.
Whats the alternative?
Only one I see is to pass THIS_MODULE to hook reg/unreg so we know what module registered the
family for purpose of module get/put but thats going to be messy.
Alternatively we can of course sleep instead of schedule() but that
doesn't appear too appealing either (albeit it is a lot less intrusive).
Any other idea?
^ permalink raw reply
* Re: [PATCH net-next v2 1/6] devlink: Add permanent config parameter get/set operations
From: Steve Lin @ 2017-10-23 15:27 UTC (permalink / raw)
To: Yuval Mintz
Cc: netdev@vger.kernel.org, Jiri Pirko, davem@davemloft.net,
michael.chan@broadcom.com, linville@tuxdriver.com,
gospo@broadcom.com
In-Reply-To: <AM0PR0502MB3683CA10099EA2075269A979BF400@AM0PR0502MB3683.eurprd05.prod.outlook.com>
On Sat, Oct 21, 2017 at 10:12 AM, Yuval Mintz <yuvalm@mellanox.com> wrote:
>> On Thu, Oct 19, 2017 at 4:21 PM, Yuval Mintz <yuvalm@mellanox.com>
>> wrote:
>> >> Subject: [PATCH net-next v2 1/6] devlink: Add permanent config
>> parameter
>> >> get/set operations
>> >>
>> >> Add support for permanent config parameter get/set commands. Used
>> >> for parameters held in NVRAM, persistent device configuration.
>> >
>> > Given some of the attributes aren't Boolean, what about an API that
>> > allows the user to learn of supported values per option?
>> > Otherwise only way for configuring some of them would be trial & error.
>>
>> Interesting suggestion. There's a couple of places where this could
>> be a factor. (1) When a user wants to know what values are
>> defined/available in the API, and (2) When the user wants to know what
>> values are supported by a specific driver/device.
>>
>> The intention for (1) is to push that into userspace. The userspace
>> devlink tool patches I am working on (not yet submitted) essentially
>> mirror the config parameters and their options, with string "keywords"
>> associated with each parameter and option, since it's the userspace
>> app that will be parsing the command line strings and converting to
>> API enums. So the userspace app can provide the list of
>> parameters/options it supports, which could be a subset of what's
>> available in the API.
>>
>> For (2), currently there is no mechanism other than trial/error as you
>> suggest (up to driver to either return an error or else make use of
>> the value specified by the user). We could contemplate adding such a
>> mechanism, but it's a little complicated as some options take a range
>> (i.e. # of VFs per PF for example), and others may take one of a set
>> of enumerated values (pre-boot link speed for example).
>>
>> To clarify, are you suggesting some mechanism to allow a driver to
>> report which parameters and options it supports (case (2))? Or are
>> you suggesting something in the kernel API to handle case (1) above?
>
> I was thinking of (2). And I agree it would take some effort.
I don't disagree that this could be a useful addition. But, it seems
like this could be added as a follow on patch. I think many/most
users of this permanent device config API probably already know what
capabilities their device offers, and if they are wrong, the driver
can indicate invalid config options. Nothing in the patchset prevents
future work to add a new devlink operation to query the driver for
supported options. Thoughts?
>> > Isn't it possible that a response for a single request for multiple ATTRs
>> > wouldn't fit in a single message?
>> >
>>
>> Hmm... Given the small size and relatively small total number of these
>> attributes, even when additional drivers add their own, I think it's
>
> We probably have a different idea about 'small'.
> Didn’t your *initial* series attempt to add 35 attributes at once?
>
Yes, and I'd still like to get those ~35 parameters in eventually! :)
But even if there were 100 parameters, and all 100 were being get or
set at once, if you assume 20 bytes per parameter (4 bytes each for
DEVLINK_ATTR_CONFIG, DEVLINK_ATTR_CONFIG_PARAMETER,
DEVLINK_ATTR_CONFIG_VALUE, 8 for nesting), that's ~2000 bytes in the
message. A little overhead, too, of course, but still less than half
a typical netlink message size of 4KB.
So, at some point - if a device with 250 parameters comes along, say,
all of which are set/get at once - this could be a problem, but it's
not clear if this is a realistic scenario to prepare for?
^ permalink raw reply
* [PATCH] cdc_ether: flag the Huawei ME906/ME909 as WWAN
From: Aleksander Morgado @ 2017-10-23 15:16 UTC (permalink / raw)
To: linux-usb, netdev, oliver, davem; +Cc: linux-kernel, Aleksander Morgado
The Huawei ME906 (12d1:15c1) comes with a standard ECM interface that
requires management via AT commands sent over one of the control TTYs
(e.g. connected with AT^NDISDUP).
Signed-off-by: Aleksander Morgado <aleksander@aleksander.es>
---
drivers/net/usb/cdc_ether.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c
index 52ea80bcd639..788953afaba3 100644
--- a/drivers/net/usb/cdc_ether.c
+++ b/drivers/net/usb/cdc_ether.c
@@ -863,6 +863,12 @@ static const struct usb_device_id products[] = {
USB_DEVICE_AND_INTERFACE_INFO(DELL_VENDOR_ID, 0x81ba, USB_CLASS_COMM,
USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
.driver_info = (kernel_ulong_t)&wwan_info,
+}, {
+ /* Huawei ME906 and ME909 */
+ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0x15c1, USB_CLASS_COMM,
+ USB_CDC_SUBCLASS_ETHERNET,
+ USB_CDC_PROTO_NONE),
+ .driver_info = (unsigned long)&wwan_info,
}, {
/* ZTE modules */
USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, USB_CLASS_COMM,
--
2.14.2
^ permalink raw reply related
* Re: [PATCHv2 net-next 3/3] bonding: remove rtmsg_ifinfo called after bond_lower_state_changed
From: Xin Long @ 2017-10-23 15:15 UTC (permalink / raw)
To: kbuild test robot; +Cc: kbuild-all, network dev, davem, Jiri Pirko
In-Reply-To: <201710232254.INLL2XLz%fengguang.wu@intel.com>
On Mon, Oct 23, 2017 at 10:44 PM, kbuild test robot <lkp@intel.com> wrote:
> Hi Xin,
>
> [auto build test ERROR on net-next/master]
>
> url: https://github.com/0day-ci/linux/commits/Xin-Long/bonding-void-calling-rtmsg_ifinfo-for-netlink-notifications/20171023-203332
> config: x86_64-rhel (attached as .config)
> compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
> reproduce:
> # save the attached .config to linux build tree
> make ARCH=x86_64
>
> All errors (new ones prefixed by >>):
>
>>> ERROR: "rtmsg_ifinfo" [net/bridge/bridge.ko] undefined!
sorry, didn't notice bridge is still using rtmsg_ifinfo.
rtmsg_ifinfo actually is no need to be called in br_del_if(),
since patch:
dc709f3 rtnetlink: bring NETDEV_CHANGEUPPER event process back in
rtnetlink_event
I will propose another patch to remove this.
for this bonding one, I will post v3 without removing rtmsg_ifinfo
export first.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox