From c4dfddccef4e092065d7bb696d64bb46f4223567 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 9 Apr 2020 20:29:51 +0200 Subject: [PATCH 1/5] devlink: fix JSON output of mon command The current JSON output of mon command is broken. Fix it and make sure that the output is a valid JSON. Also, handle SIGINT gracefully to allow to end the JSON properly. Example: $ devlink mon -j -p { "mon": [ { "command": "new", "dev": { "netdevsim/netdevsim10": {} } },{ "command": "new", "port": { "netdevsim/netdevsim10/0": { "type": "notset", "flavour": "physical", "port": 1 } } },{ "command": "new", "port": { "netdevsim/netdevsim10/0": { "type": "eth", "netdev": "eth0", "flavour": "physical", "port": 1 } } },{ "command": "new", "port": { "netdevsim/netdevsim10/0": { "type": "notset", "flavour": "physical", "port": 1 } } },{ "command": "del", "port": { "netdevsim/netdevsim10/0": { "type": "notset", "flavour": "physical", "port": 1 } } },{ "command": "del", "dev": { "netdevsim/netdevsim10": {} } } ] } Signed-off-by: Jiri Pirko Signed-off-by: Stephen Hemminger --- devlink/devlink.c | 54 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/devlink/devlink.c b/devlink/devlink.c index 4cf58f40..f67fe6dd 100644 --- a/devlink/devlink.c +++ b/devlink/devlink.c @@ -152,6 +152,30 @@ static int _mnlg_socket_recv_run(struct mnlg_socket *nlg, return 0; } +static void dummy_signal_handler(int signum) +{ +} + +static int _mnlg_socket_recv_run_intr(struct mnlg_socket *nlg, + mnl_cb_t data_cb, void *data) +{ + struct sigaction act, oact; + int err; + + act.sa_handler = dummy_signal_handler; + sigemptyset(&act.sa_mask); + act.sa_flags = SA_NODEFER; + + sigaction(SIGINT, &act, &oact); + err = mnlg_socket_recv_run(nlg, data_cb, data); + sigaction(SIGINT, &oact, NULL); + if (err < 0 && errno != EINTR) { + pr_err("devlink answers: %s\n", strerror(errno)); + return -errno; + } + return 0; +} + static int _mnlg_socket_send(struct mnlg_socket *nlg, const struct nlmsghdr *nlh) { @@ -4236,7 +4260,21 @@ static const char *cmd_obj(uint8_t cmd) static void pr_out_mon_header(uint8_t cmd) { - pr_out("[%s,%s] ", cmd_obj(cmd), cmd_name(cmd)); + if (!is_json_context()) { + pr_out("[%s,%s] ", cmd_obj(cmd), cmd_name(cmd)); + } else { + open_json_object(NULL); + print_string(PRINT_JSON, "command", NULL, cmd_name(cmd)); + open_json_object(cmd_obj(cmd)); + } +} + +static void pr_out_mon_footer(void) +{ + if (is_json_context()) { + close_json_object(); + close_json_object(); + } } static bool cmd_filter_check(struct dl *dl, uint8_t cmd) @@ -4306,6 +4344,7 @@ static int cmd_mon_show_cb(const struct nlmsghdr *nlh, void *data) return MNL_CB_ERROR; pr_out_mon_header(genl->cmd); pr_out_handle(dl, tb); + pr_out_mon_footer(); break; case DEVLINK_CMD_PORT_GET: /* fall through */ case DEVLINK_CMD_PORT_SET: /* fall through */ @@ -4317,6 +4356,7 @@ static int cmd_mon_show_cb(const struct nlmsghdr *nlh, void *data) return MNL_CB_ERROR; pr_out_mon_header(genl->cmd); pr_out_port(dl, tb); + pr_out_mon_footer(); break; case DEVLINK_CMD_PARAM_GET: /* fall through */ case DEVLINK_CMD_PARAM_SET: /* fall through */ @@ -4328,6 +4368,7 @@ static int cmd_mon_show_cb(const struct nlmsghdr *nlh, void *data) return MNL_CB_ERROR; pr_out_mon_header(genl->cmd); pr_out_param(dl, tb, false); + pr_out_mon_footer(); break; case DEVLINK_CMD_REGION_GET: /* fall through */ case DEVLINK_CMD_REGION_SET: /* fall through */ @@ -4339,6 +4380,7 @@ static int cmd_mon_show_cb(const struct nlmsghdr *nlh, void *data) return MNL_CB_ERROR; pr_out_mon_header(genl->cmd); pr_out_region(dl, tb); + pr_out_mon_footer(); break; case DEVLINK_CMD_FLASH_UPDATE: /* fall through */ case DEVLINK_CMD_FLASH_UPDATE_END: /* fall through */ @@ -4348,6 +4390,7 @@ static int cmd_mon_show_cb(const struct nlmsghdr *nlh, void *data) return MNL_CB_ERROR; pr_out_mon_header(genl->cmd); pr_out_flash_update(dl, tb); + pr_out_mon_footer(); break; case DEVLINK_CMD_HEALTH_REPORTER_RECOVER: mnl_attr_parse(nlh, sizeof(*genl), attr_cb, tb); @@ -4356,6 +4399,7 @@ static int cmd_mon_show_cb(const struct nlmsghdr *nlh, void *data) return MNL_CB_ERROR; pr_out_mon_header(genl->cmd); pr_out_health(dl, tb); + pr_out_mon_footer(); break; case DEVLINK_CMD_TRAP_GET: /* fall through */ case DEVLINK_CMD_TRAP_SET: /* fall through */ @@ -4372,6 +4416,7 @@ static int cmd_mon_show_cb(const struct nlmsghdr *nlh, void *data) return MNL_CB_ERROR; pr_out_mon_header(genl->cmd); pr_out_trap(dl, tb, false); + pr_out_mon_footer(); break; case DEVLINK_CMD_TRAP_GROUP_GET: /* fall through */ case DEVLINK_CMD_TRAP_GROUP_SET: /* fall through */ @@ -4384,6 +4429,7 @@ static int cmd_mon_show_cb(const struct nlmsghdr *nlh, void *data) return MNL_CB_ERROR; pr_out_mon_header(genl->cmd); pr_out_trap_group(dl, tb, false); + pr_out_mon_footer(); break; case DEVLINK_CMD_TRAP_POLICER_GET: /* fall through */ case DEVLINK_CMD_TRAP_POLICER_SET: /* fall through */ @@ -4423,7 +4469,11 @@ static int cmd_mon_show(struct dl *dl) err = _mnlg_socket_group_add(dl->nlg, DEVLINK_GENL_MCGRP_CONFIG_NAME); if (err) return err; - err = _mnlg_socket_recv_run(dl->nlg, cmd_mon_show_cb, dl); + open_json_object(NULL); + open_json_array(PRINT_JSON, "mon"); + err = _mnlg_socket_recv_run_intr(dl->nlg, cmd_mon_show_cb, dl); + close_json_array(PRINT_JSON, NULL); + close_json_object(); if (err) return err; return 0; From 20927e0525e0cca165cd1252ac18da07cb082c4d Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Sat, 4 Apr 2020 01:55:34 +0300 Subject: [PATCH 2/5] ip: link_gre: Do not send ERSPAN attributes to GRE tunnels In the commit referenced below, ip link started sending ERSPAN-specific attributes even for GRE and gretap tunnels. Fix by more carefully distinguishing between the GRE/tap and ERSPAN modes. Do not show ERSPAN-related help in GRE/tap mode, likewise do not accept ERSPAN arguments, or send ERSPAN attributes. Fixes: 83c543af872e ("erspan: set erspan_ver to 1 by default") Signed-off-by: Petr Machata Acked-by: William Tu Signed-off-by: Stephen Hemminger --- ip/link_gre.c | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/ip/link_gre.c b/ip/link_gre.c index e42f21ae..d616a970 100644 --- a/ip/link_gre.c +++ b/ip/link_gre.c @@ -23,8 +23,15 @@ #include "ip_common.h" #include "tunnel.h" +static bool gre_is_erspan(struct link_util *lu) +{ + return !strcmp(lu->id, "erspan"); +} + static void gre_print_help(struct link_util *lu, int argc, char **argv, FILE *f) { + bool is_erspan = gre_is_erspan(lu); + fprintf(f, "Usage: ... %-9s [ remote ADDR ]\n" " [ local ADDR ]\n" @@ -44,18 +51,20 @@ static void gre_print_help(struct link_util *lu, int argc, char **argv, FILE *f) " [ encap-dport PORT ]\n" " [ [no]encap-csum ]\n" " [ [no]encap-csum6 ]\n" - " [ [no]encap-remcsum ]\n" - " [ erspan_ver version ]\n" - " [ erspan IDX ]\n" - " [ erspan_dir { ingress | egress } ]\n" - " [ erspan_hwid hwid ]\n" + " [ [no]encap-remcsum ]\n", lu->id); + if (is_erspan) + fprintf(f, + " [ erspan_ver version ]\n" + " [ erspan IDX ]\n" + " [ erspan_dir { ingress | egress } ]\n" + " [ erspan_hwid hwid ]\n"); + fprintf(f, "\n" "Where: ADDR := { IP_ADDRESS | any }\n" " TOS := { NUMBER | inherit }\n" " TTL := { 1..255 | inherit }\n" " KEY := { DOTTED_QUAD | NUMBER }\n" - " MARK := { 0x0..0xffffffff }\n", - lu->id); + " MARK := { 0x0..0xffffffff }\n"); } static int gre_parse_opt(struct link_util *lu, int argc, char **argv, @@ -93,6 +102,7 @@ static int gre_parse_opt(struct link_util *lu, int argc, char **argv, __u16 encapdport = 0; __u8 metadata = 0; __u32 fwmark = 0; + bool is_erspan = gre_is_erspan(lu); __u32 erspan_idx = 0; __u8 erspan_ver = 1; __u8 erspan_dir = 0; @@ -334,19 +344,19 @@ get_failed: NEXT_ARG(); if (get_u32(&fwmark, *argv, 0)) invarg("invalid fwmark\n", *argv); - } else if (strcmp(*argv, "erspan") == 0) { + } else if (is_erspan && strcmp(*argv, "erspan") == 0) { NEXT_ARG(); if (get_u32(&erspan_idx, *argv, 0)) invarg("invalid erspan index\n", *argv); if (erspan_idx & ~((1<<20) - 1) || erspan_idx == 0) invarg("erspan index must be > 0 and <= 20-bit\n", *argv); - } else if (strcmp(*argv, "erspan_ver") == 0) { + } else if (is_erspan && strcmp(*argv, "erspan_ver") == 0) { NEXT_ARG(); if (get_u8(&erspan_ver, *argv, 0)) invarg("invalid erspan version\n", *argv); if (erspan_ver != 1 && erspan_ver != 2) invarg("erspan version must be 1 or 2\n", *argv); - } else if (strcmp(*argv, "erspan_dir") == 0) { + } else if (is_erspan && strcmp(*argv, "erspan_dir") == 0) { NEXT_ARG(); if (matches(*argv, "ingress") == 0) erspan_dir = 0; @@ -354,7 +364,7 @@ get_failed: erspan_dir = 1; else invarg("Invalid erspan direction.", *argv); - } else if (strcmp(*argv, "erspan_hwid") == 0) { + } else if (is_erspan && strcmp(*argv, "erspan_hwid") == 0) { NEXT_ARG(); if (get_u16(&erspan_hwid, *argv, 0)) invarg("invalid erspan hwid\n", *argv); @@ -402,7 +412,7 @@ get_failed: addattr32(n, 1024, IFLA_GRE_LINK, link); addattr_l(n, 1024, IFLA_GRE_TTL, &ttl, 1); addattr32(n, 1024, IFLA_GRE_FWMARK, fwmark); - if (erspan_ver) { + if (is_erspan) { addattr8(n, 1024, IFLA_GRE_ERSPAN_VER, erspan_ver); if (erspan_ver == 1 && erspan_idx != 0) { addattr32(n, 1024, IFLA_GRE_ERSPAN_INDEX, erspan_idx); From d8d59421b61f114ac8406aeca73f5747854bd230 Mon Sep 17 00:00:00 2001 From: Benjamin Lee Date: Wed, 8 Apr 2020 22:12:13 -0700 Subject: [PATCH 3/5] man: tc-htb.8: add missing qdisc parameter r2q Add description for htb qdisc parameter r2q. Signed-off-by: Benjamin Lee Signed-off-by: Stephen Hemminger --- man/man8/tc-htb.8 | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/man/man8/tc-htb.8 b/man/man8/tc-htb.8 index ae310f43..2bcb9c46 100644 --- a/man/man8/tc-htb.8 +++ b/man/man8/tc-htb.8 @@ -10,6 +10,8 @@ classid major: .B ] htb [ default minor-id +.B ] [ r2q +divisor .B ] .B tc class ... dev @@ -93,6 +95,13 @@ will be generated within this qdisc. .TP default minor-id Unclassified traffic gets sent to the class with this minor-id. +.TP +r2q divisor +Divisor used to calculate +.B quantum +values for classes. Classes divide +.B rate +by this number. Default value is 10. .SH CLASSES Classes have a host of parameters to configure their operation. From 6ecd0198c0bc49413699b8177e247995e0234ac5 Mon Sep 17 00:00:00 2001 From: Benjamin Lee Date: Wed, 8 Apr 2020 22:12:14 -0700 Subject: [PATCH 4/5] man: tc-htb.8: add missing class parameter quantum Add description for htb class parameter quantum. Signed-off-by: Benjamin Lee Signed-off-by: Stephen Hemminger --- man/man8/tc-htb.8 | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/man/man8/tc-htb.8 b/man/man8/tc-htb.8 index 2bcb9c46..9accfecd 100644 --- a/man/man8/tc-htb.8 +++ b/man/man8/tc-htb.8 @@ -30,6 +30,8 @@ bytes bytes .B ] [ prio priority +.B ] [ quantum +bytes .B ] .SH DESCRIPTION @@ -143,6 +145,17 @@ Amount of bytes that can be burst at 'infinite' speed, in other words, as fast as the interface can transmit them. For perfect evening out, should be equal to at most one average packet. Should be at least as high as the highest cburst of all children. +.TP +quantum bytes +Number of bytes to serve from this class before the scheduler moves to the next class. +Default value is +.B rate +divided by the qdisc +.B r2q +parameter. If specified, +.B r2q +is ignored. + .SH NOTES Due to Unix timing constraints, the maximum ceil rate is not infinite and may in fact be quite low. On Intel, there are 100 timer events per second, the maximum rate is that rate at which 'burst' bytes are sent each timer tick. From fe821d64e60cee2abc4347b3f67e8a3d698777a0 Mon Sep 17 00:00:00 2001 From: Benjamin Lee Date: Wed, 8 Apr 2020 22:12:15 -0700 Subject: [PATCH 5/5] man: tc-htb.8: fix class prio is not mandatory Fix description for htb class prio parameter to indicate it's not mandatory. Signed-off-by: Benjamin Lee Signed-off-by: Stephen Hemminger --- man/man8/tc-htb.8 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/man/man8/tc-htb.8 b/man/man8/tc-htb.8 index 9accfecd..a4162342 100644 --- a/man/man8/tc-htb.8 +++ b/man/man8/tc-htb.8 @@ -120,7 +120,7 @@ class is going to have children. .TP prio priority In the round-robin process, classes with the lowest priority field are tried -for packets first. Mandatory. +for packets first. .TP rate rate