From 27886a12416dd315cf386cfbfa93c2fb2aceca98 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 31 Aug 2018 15:03:49 -0700 Subject: [PATCH 01/15] uapi: update ib_verbs Merge current uapi from 4.19-rc1 Signed-off-by: Stephen Hemminger --- rdma/include/uapi/rdma/ib_user_verbs.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/rdma/include/uapi/rdma/ib_user_verbs.h b/rdma/include/uapi/rdma/ib_user_verbs.h index 4f9991de..25a16760 100644 --- a/rdma/include/uapi/rdma/ib_user_verbs.h +++ b/rdma/include/uapi/rdma/ib_user_verbs.h @@ -279,7 +279,7 @@ struct ib_uverbs_query_port { }; struct ib_uverbs_query_port_resp { - __u32 port_cap_flags; + __u32 port_cap_flags; /* see ib_uverbs_query_port_cap_flags */ __u32 max_msg_sz; __u32 bad_pkey_cntr; __u32 qkey_viol_cntr; @@ -299,7 +299,8 @@ struct ib_uverbs_query_port_resp { __u8 active_speed; __u8 phys_state; __u8 link_layer; - __u8 reserved[2]; + __u8 flags; /* see ib_uverbs_query_port_flags */ + __u8 reserved; }; struct ib_uverbs_alloc_pd { From 781ee3270d135d82abcae404ec649fe729e69851 Mon Sep 17 00:00:00 2001 From: Caleb Raitto Date: Wed, 5 Sep 2018 13:23:33 -0700 Subject: [PATCH 02/15] man: Change numtc to num_tc The argument parser only accepts num_tc: https://git.kernel.org/pub/scm/network/iproute2/iproute2.git/tree/tc/q_mqprio.c#n55 Signed-off-by: Caleb Raitto Signed-off-by: Stephen Hemminger --- man/man8/tc-mqprio.8 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/man/man8/tc-mqprio.8 b/man/man8/tc-mqprio.8 index a1bedd35..4b9e942e 100644 --- a/man/man8/tc-mqprio.8 +++ b/man/man8/tc-mqprio.8 @@ -8,7 +8,7 @@ dev classid .B | root) [ handle major: -.B ] mqprio [ numtc +.B ] mqprio [ num_tc tcs .B ] [ map P0 P1 P2... From f5fc73873611702ad8947481b4be4c301dd2bd12 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 6 Sep 2018 14:14:46 +0100 Subject: [PATCH 03/15] bridge: minor change to mdb print Get port ifname once rather than on both sides of if(is_json_context). Signed-off-by: Stephen Hemminger --- bridge/mdb.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bridge/mdb.c b/bridge/mdb.c index f38dc67c..9bdef026 100644 --- a/bridge/mdb.c +++ b/bridge/mdb.c @@ -208,19 +208,19 @@ static void print_router_entries(FILE *fp, struct nlmsghdr *n, } else { struct rtattr *i = RTA_DATA(router); uint32_t *port_ifindex = RTA_DATA(i); + const char *port_name = ll_index_to_name(*port_ifindex); if (is_json_context()) { open_json_array(PRINT_JSON, brifname); open_json_object(NULL); print_string(PRINT_JSON, "port", NULL, - ll_index_to_name(*port_ifindex)); + port_name); close_json_object(); close_json_array(PRINT_JSON, NULL); } else { fprintf(fp, "router port dev %s master %s\n", - ll_index_to_name(*port_ifindex), - brifname); + port_name, brifname); } } close_json_array(PRINT_JSON, NULL); From 2ed82667b8dcc65fd14727dcf365821d63bd2c75 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 6 Sep 2018 14:15:36 +0100 Subject: [PATCH 04/15] bridge: use print_json for some outputs Rather than using is_json_context(), use the print_string functions which handle both cases. Signed-off-by: Stephen Hemminger --- bridge/mdb.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/bridge/mdb.c b/bridge/mdb.c index 9bdef026..cc1b4547 100644 --- a/bridge/mdb.c +++ b/bridge/mdb.c @@ -131,15 +131,8 @@ static void print_mdb_entry(FILE *f, int ifindex, const struct br_mdb_entry *e, if (n->nlmsg_type == RTM_DELMDB) print_bool(PRINT_ANY, "deleted", "Deleted ", true); - - if (is_json_context()) { - print_int(PRINT_JSON, "index", NULL, ifindex); - print_string(PRINT_JSON, "dev", NULL, dev); - } else { - fprintf(f, "%u: ", ifindex); - color_fprintf(f, COLOR_IFNAME, "%s ", dev); - } - + print_int(PRINT_ANY, "index", "%u: ", ifindex); + print_color_string(PRINT_ANY, COLOR_IFNAME, "dev", "%s ", dev); print_string(PRINT_ANY, "port", " %s ", ll_index_to_name(e->ifindex)); From 0f36267485e30099a4f735c3aadfa58b5efa1918 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 6 Sep 2018 14:42:46 +0100 Subject: [PATCH 05/15] bridge: fix vlan show formatting The output of vlan show was broken previous change to use json_print. Clean the code up and return to original format. Note: the JSON syntax has changed to make the bridge vlan show more like other outputs (e.g. ip -j li show). Signed-off-by: Stephen Hemminger --- bridge/br_common.h | 5 ++-- bridge/link.c | 6 ++--- bridge/vlan.c | 61 +++++++++++++++++++++++++++------------------- 3 files changed, 41 insertions(+), 31 deletions(-) diff --git a/bridge/br_common.h b/bridge/br_common.h index 7bf15e95..00a4e9ea 100644 --- a/bridge/br_common.h +++ b/bridge/br_common.h @@ -6,10 +6,9 @@ #define MDB_RTR_RTA(r) \ ((struct rtattr *)(((char *)(r)) + RTA_ALIGN(sizeof(__u32)))) -void print_vlan_info(FILE *fp, struct rtattr *tb); +void print_vlan_info(struct rtattr *tb, int ifindex); int print_linkinfo(const struct sockaddr_nl *who, - struct nlmsghdr *n, - void *arg); + struct nlmsghdr *n, void *arg); int print_fdb(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg); int print_mdb(const struct sockaddr_nl *who, diff --git a/bridge/link.c b/bridge/link.c index 9656ca33..85570263 100644 --- a/bridge/link.c +++ b/bridge/link.c @@ -164,7 +164,7 @@ static void print_protinfo(FILE *fp, struct rtattr *attr) * This is reported by HW devices that have some bridging * capabilities. */ -static void print_af_spec(FILE *fp, struct rtattr *attr) +static void print_af_spec(struct rtattr *attr, int ifindex) { struct rtattr *aftb[IFLA_BRIDGE_MAX+1]; @@ -177,7 +177,7 @@ static void print_af_spec(FILE *fp, struct rtattr *attr) return; if (aftb[IFLA_BRIDGE_VLAN_INFO]) - print_vlan_info(fp, aftb[IFLA_BRIDGE_VLAN_INFO]); + print_vlan_info(aftb[IFLA_BRIDGE_VLAN_INFO], ifindex); } int print_linkinfo(const struct sockaddr_nl *who, @@ -232,7 +232,7 @@ int print_linkinfo(const struct sockaddr_nl *who, print_protinfo(fp, tb[IFLA_PROTINFO]); if (tb[IFLA_AF_SPEC]) - print_af_spec(fp, tb[IFLA_AF_SPEC]); + print_af_spec(tb[IFLA_AF_SPEC], ifi->ifi_index); print_string(PRINT_FP, NULL, "%s", "\n"); close_json_object(); diff --git a/bridge/vlan.c b/bridge/vlan.c index 19a36b80..bdce55ae 100644 --- a/bridge/vlan.c +++ b/bridge/vlan.c @@ -252,10 +252,18 @@ static int filter_vlan_check(__u16 vid, __u16 flags) return 1; } -static void print_vlan_port(FILE *fp, int ifi_index) +static void open_vlan_port(int ifi_index) { - print_string(PRINT_ANY, NULL, "%s", + open_json_object(NULL); + print_string(PRINT_ANY, "ifname", "%s", ll_index_to_name(ifi_index)); + open_json_array(PRINT_JSON, "vlans"); +} + +static void close_vlan_port(void) +{ + close_json_array(PRINT_JSON, NULL); + close_json_object(); } static void print_range(const char *name, __u16 start, __u16 id) @@ -278,7 +286,7 @@ static void print_vlan_tunnel_info(FILE *fp, struct rtattr *tb, int ifindex) __u32 last_tunid_start = 0; if (!filter_vlan) - print_vlan_port(fp, ifindex); + open_vlan_port(ifindex); open_json_array(PRINT_JSON, "tunnel"); for (i = RTA_DATA(list); RTA_OK(i, rem); i = RTA_NEXT(i, rem)) { @@ -323,18 +331,20 @@ static void print_vlan_tunnel_info(FILE *fp, struct rtattr *tb, int ifindex) continue; if (filter_vlan) - print_vlan_port(fp, ifindex); + open_vlan_port(ifindex); open_json_object(NULL); print_range("vlan", last_vid_start, tunnel_vid); print_range("tunid", last_tunid_start, tunnel_id); close_json_object(); - if (!is_json_context()) - fprintf(fp, "\n"); - + print_string(PRINT_FP, NULL, "%s", _SL_); + if (filter_vlan) + close_vlan_port(); } - close_json_array(PRINT_JSON, NULL); + + if (!filter_vlan) + close_vlan_port(); } static int print_vlan_tunnel(const struct sockaddr_nl *who, @@ -421,8 +431,8 @@ static int print_vlan(const struct sockaddr_nl *who, return 0; } - print_vlan_port(fp, ifm->ifi_index); - print_vlan_info(fp, tb[IFLA_AF_SPEC]); + print_vlan_info(tb[IFLA_AF_SPEC], ifm->ifi_index); + print_string(PRINT_FP, NULL, "%s", _SL_); fflush(fp); return 0; @@ -430,11 +440,16 @@ static int print_vlan(const struct sockaddr_nl *who, static void print_vlan_flags(__u16 flags) { + if (flags == 0) + return; + + open_json_array(PRINT_JSON, "flags"); if (flags & BRIDGE_VLAN_INFO_PVID) - print_null(PRINT_ANY, "pvid", " %s", "PVID"); + print_string(PRINT_ANY, NULL, " %s", "PVID"); if (flags & BRIDGE_VLAN_INFO_UNTAGGED) - print_null(PRINT_ANY, "untagged", " %s", "untagged"); + print_string(PRINT_ANY, NULL, " %s", "Egress Untagged"); + close_json_array(PRINT_JSON, NULL); } static void print_one_vlan_stats(const struct bridge_vlan_xstats *vstats) @@ -461,6 +476,7 @@ static void print_vlan_stats_attr(struct rtattr *attr, int ifindex) { struct rtattr *brtb[LINK_XSTATS_TYPE_MAX+1]; struct rtattr *i, *list; + const char *ifname; int rem; parse_rtattr(brtb, LINK_XSTATS_TYPE_MAX, RTA_DATA(attr), @@ -471,13 +487,12 @@ static void print_vlan_stats_attr(struct rtattr *attr, int ifindex) list = brtb[LINK_XSTATS_TYPE_BRIDGE]; rem = RTA_PAYLOAD(list); - open_json_object(NULL); + ifname = ll_index_to_name(ifindex); + open_json_object(ifname); - print_color_string(PRINT_ANY, COLOR_IFNAME, - "dev", "%-16s", - ll_index_to_name(ifindex)); + print_color_string(PRINT_FP, COLOR_IFNAME, + NULL, "%-16s", ifname); - open_json_array(PRINT_JSON, "xstats"); for (i = RTA_DATA(list); RTA_OK(i, rem); i = RTA_NEXT(i, rem)) { const struct bridge_vlan_xstats *vstats = RTA_DATA(i); @@ -494,7 +509,6 @@ static void print_vlan_stats_attr(struct rtattr *attr, int ifindex) print_one_vlan_stats(vstats); } - close_json_array(PRINT_ANY, "\n"); close_json_object(); } @@ -623,16 +637,13 @@ static int vlan_show(int argc, char **argv) return 0; } -void print_vlan_info(FILE *fp, struct rtattr *tb) +void print_vlan_info(struct rtattr *tb, int ifindex) { struct rtattr *i, *list = tb; int rem = RTA_PAYLOAD(list); __u16 last_vid_start = 0; - if (!is_json_context()) - fprintf(fp, "%s", _SL_); - - open_json_array(PRINT_JSON, "vlan"); + open_vlan_port(ifindex); for (i = RTA_DATA(list); RTA_OK(i, rem); i = RTA_NEXT(i, rem)) { struct bridge_vlan_info *vinfo; @@ -656,9 +667,9 @@ void print_vlan_info(FILE *fp, struct rtattr *tb) print_vlan_flags(vinfo->flags); close_json_object(); + print_string(PRINT_FP, NULL, "%s", _SL_); } - - close_json_array(PRINT_ANY, "\n"); + close_vlan_port(); } int do_vlan(int argc, char **argv) From ad618b7984dbb1f355d9c07f959f16fa947026cf Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 10 Sep 2018 11:50:22 -0700 Subject: [PATCH 06/15] tc/fifo: remove unnecessary prototype The prototype for prio_print_opt is already in tc_util.h Signed-off-by: Stephen Hemminger --- tc/q_fifo.c | 1 - 1 file changed, 1 deletion(-) diff --git a/tc/q_fifo.c b/tc/q_fifo.c index 5fd6c1b1..cb86a404 100644 --- a/tc/q_fifo.c +++ b/tc/q_fifo.c @@ -94,7 +94,6 @@ struct qdisc_util pfifo_head_drop_qdisc_util = { .print_qopt = fifo_print_opt, }; -extern int prio_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt); struct qdisc_util pfifo_fast_qdisc_util = { .id = "pfifo_fast", .print_qopt = prio_print_opt, From ae775666cf7d30f1fc7857152298af44114f3d19 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 10 Sep 2018 11:53:07 -0700 Subject: [PATCH 07/15] genl: remove unnecessary extern extern not necessary on function prototype. Signed-off-by: Stephen Hemminger --- include/libgenl.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/libgenl.h b/include/libgenl.h index cd13f476..656493a2 100644 --- a/include/libgenl.h +++ b/include/libgenl.h @@ -21,8 +21,8 @@ struct { \ }, \ } -extern int genl_resolve_family(struct rtnl_handle *grth, const char *family); -extern int genl_init_handle(struct rtnl_handle *grth, const char *family, - int *genl_family); +int genl_resolve_family(struct rtnl_handle *grth, const char *family); +int genl_init_handle(struct rtnl_handle *grth, const char *family, + int *genl_family); #endif /* __LIBGENL_H__ */ From 40c2916fda23bc9bd124009934544d3c0fddd1c0 Mon Sep 17 00:00:00 2001 From: Caleb Raitto Date: Thu, 6 Sep 2018 14:01:17 -0700 Subject: [PATCH 08/15] tc/mqprio: Print extra info on invalid args. Print the name of the argument that wasn't understood. Signed-off-by: Caleb Raitto Signed-off-by: Stephen Hemminger --- tc/q_mqprio.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tc/q_mqprio.c b/tc/q_mqprio.c index 89b46002..7cd18ae1 100644 --- a/tc/q_mqprio.c +++ b/tc/q_mqprio.c @@ -167,8 +167,7 @@ static int mqprio_parse_opt(struct qdisc_util *qu, int argc, explain(); return -1; } else { - fprintf(stderr, "Unknown argument\n"); - return -1; + invarg("unknown argument", *argv); } argc--; argv++; } From bd59e5b1517b09b6f26d59f38fe6077d953c2396 Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Thu, 6 Sep 2018 15:31:51 +0200 Subject: [PATCH 09/15] ip-route: Fix segfault with many nexthops It was possible to crash ip-route by adding an IPv6 route with 37 nexthop statements. A simple reproducer is: | for i in `seq 37`; do | nhs="nexthop via 1111::$i "$nhs | done | ip -6 route add 3333::/64 $nhs The related code was broken in multiple ways: * parse_one_nh() assumed that rta points to 4kB of storage but caller provided just 1kB. Fixed by passing 'len' parameter with the correct value. * Error checking of rta_addattr*() calls in parse_one_nh() and called functions was completely absent, so with above fix in place output flood would occur due to parser looping forever. While being at it, increase message buffer sizes to 4k. This allows for at most 144 nexthops. Signed-off-by: Phil Sutter Signed-off-by: Stephen Hemminger --- ip/iproute.c | 43 ++++++++++------- ip/iproute_lwtunnel.c | 108 +++++++++++++++++++++++++----------------- 2 files changed, 91 insertions(+), 60 deletions(-) diff --git a/ip/iproute.c b/ip/iproute.c index 30833414..398322fd 100644 --- a/ip/iproute.c +++ b/ip/iproute.c @@ -941,7 +941,7 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) } static int parse_one_nh(struct nlmsghdr *n, struct rtmsg *r, - struct rtattr *rta, struct rtnexthop *rtnh, + struct rtattr *rta, size_t len, struct rtnexthop *rtnh, int *argcp, char ***argvp) { int argc = *argcp; @@ -962,11 +962,16 @@ static int parse_one_nh(struct nlmsghdr *n, struct rtmsg *r, if (r->rtm_family == AF_UNSPEC) r->rtm_family = addr.family; if (addr.family == r->rtm_family) { - rta_addattr_l(rta, 4096, RTA_GATEWAY, &addr.data, addr.bytelen); - rtnh->rtnh_len += sizeof(struct rtattr) + addr.bytelen; + if (rta_addattr_l(rta, len, RTA_GATEWAY, + &addr.data, addr.bytelen)) + return -1; + rtnh->rtnh_len += sizeof(struct rtattr) + + addr.bytelen; } else { - rta_addattr_l(rta, 4096, RTA_VIA, &addr.family, addr.bytelen+2); - rtnh->rtnh_len += RTA_SPACE(addr.bytelen+2); + if (rta_addattr_l(rta, len, RTA_VIA, + &addr.family, addr.bytelen + 2)) + return -1; + rtnh->rtnh_len += RTA_SPACE(addr.bytelen + 2); } } else if (strcmp(*argv, "dev") == 0) { NEXT_ARG(); @@ -988,13 +993,15 @@ static int parse_one_nh(struct nlmsghdr *n, struct rtmsg *r, NEXT_ARG(); if (get_rt_realms_or_raw(&realm, *argv)) invarg("\"realm\" value is invalid\n", *argv); - rta_addattr32(rta, 4096, RTA_FLOW, realm); + if (rta_addattr32(rta, len, RTA_FLOW, realm)) + return -1; rtnh->rtnh_len += sizeof(struct rtattr) + 4; } else if (strcmp(*argv, "encap") == 0) { - int len = rta->rta_len; + int old_len = rta->rta_len; - lwt_parse_encap(rta, 4096, &argc, &argv); - rtnh->rtnh_len += rta->rta_len - len; + if (lwt_parse_encap(rta, len, &argc, &argv)) + return -1; + rtnh->rtnh_len += rta->rta_len - old_len; } else if (strcmp(*argv, "as") == 0) { inet_prefix addr; @@ -1002,8 +1009,9 @@ static int parse_one_nh(struct nlmsghdr *n, struct rtmsg *r, if (strcmp(*argv, "to") == 0) NEXT_ARG(); get_addr(&addr, *argv, r->rtm_family); - rta_addattr_l(rta, 4096, RTA_NEWDST, &addr.data, - addr.bytelen); + if (rta_addattr_l(rta, len, RTA_NEWDST, + &addr.data, addr.bytelen)) + return -1; rtnh->rtnh_len += sizeof(struct rtattr) + addr.bytelen; } else break; @@ -1016,7 +1024,7 @@ static int parse_one_nh(struct nlmsghdr *n, struct rtmsg *r, static int parse_nexthops(struct nlmsghdr *n, struct rtmsg *r, int argc, char **argv) { - char buf[1024]; + char buf[4096]; struct rtattr *rta = (void *)buf; struct rtnexthop *rtnh; @@ -1036,7 +1044,7 @@ static int parse_nexthops(struct nlmsghdr *n, struct rtmsg *r, memset(rtnh, 0, sizeof(*rtnh)); rtnh->rtnh_len = sizeof(*rtnh); rta->rta_len += rtnh->rtnh_len; - if (parse_one_nh(n, r, rta, rtnh, &argc, &argv)) { + if (parse_one_nh(n, r, rta, 4096, rtnh, &argc, &argv)) { fprintf(stderr, "Error: cannot parse nexthop\n"); exit(-1); } @@ -1044,7 +1052,8 @@ static int parse_nexthops(struct nlmsghdr *n, struct rtmsg *r, } if (rta->rta_len > RTA_LENGTH(0)) - addattr_l(n, 1024, RTA_MULTIPATH, RTA_DATA(rta), RTA_PAYLOAD(rta)); + return addattr_l(n, 4096, RTA_MULTIPATH, + RTA_DATA(rta), RTA_PAYLOAD(rta)); return 0; } @@ -1053,7 +1062,7 @@ static int iproute_modify(int cmd, unsigned int flags, int argc, char **argv) struct { struct nlmsghdr n; struct rtmsg r; - char buf[1024]; + char buf[4096]; } req = { .n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)), .n.nlmsg_flags = NLM_F_REQUEST | flags, @@ -1484,8 +1493,8 @@ static int iproute_modify(int cmd, unsigned int flags, int argc, char **argv) addattr_l(&req.n, sizeof(req), RTA_METRICS, RTA_DATA(mxrta), RTA_PAYLOAD(mxrta)); } - if (nhs_ok) - parse_nexthops(&req.n, &req.r, argc, argv); + if (nhs_ok && parse_nexthops(&req.n, &req.r, argc, argv)) + return -1; if (req.r.rtm_family == AF_UNSPEC) req.r.rtm_family = AF_INET; diff --git a/ip/iproute_lwtunnel.c b/ip/iproute_lwtunnel.c index e6044811..969a4763 100644 --- a/ip/iproute_lwtunnel.c +++ b/ip/iproute_lwtunnel.c @@ -538,8 +538,9 @@ static int parse_encap_seg6(struct rtattr *rta, size_t len, int *argcp, memcpy(tuninfo->srh, srh, srhlen); - rta_addattr_l(rta, len, SEG6_IPTUNNEL_SRH, tuninfo, - sizeof(*tuninfo) + srhlen); + if (rta_addattr_l(rta, len, SEG6_IPTUNNEL_SRH, tuninfo, + sizeof(*tuninfo) + srhlen)) + return -1; free(tuninfo); free(srh); @@ -611,6 +612,7 @@ static int parse_encap_seg6local(struct rtattr *rta, size_t len, int *argcp, char segbuf[1024]; inet_prefix addr; __u32 hmac = 0; + int ret = 0; while (argc > 0) { if (strcmp(*argv, "action") == 0) { @@ -620,27 +622,28 @@ static int parse_encap_seg6local(struct rtattr *rta, size_t len, int *argcp, action = read_action_type(*argv); if (!action) invarg("\"action\" value is invalid\n", *argv); - rta_addattr32(rta, len, SEG6_LOCAL_ACTION, action); + ret = rta_addattr32(rta, len, SEG6_LOCAL_ACTION, + action); } else if (strcmp(*argv, "table") == 0) { NEXT_ARG(); if (table_ok++) duparg2("table", *argv); get_u32(&table, *argv, 0); - rta_addattr32(rta, len, SEG6_LOCAL_TABLE, table); + ret = rta_addattr32(rta, len, SEG6_LOCAL_TABLE, table); } else if (strcmp(*argv, "nh4") == 0) { NEXT_ARG(); if (nh4_ok++) duparg2("nh4", *argv); get_addr(&addr, *argv, AF_INET); - rta_addattr_l(rta, len, SEG6_LOCAL_NH4, &addr.data, - addr.bytelen); + ret = rta_addattr_l(rta, len, SEG6_LOCAL_NH4, + &addr.data, addr.bytelen); } else if (strcmp(*argv, "nh6") == 0) { NEXT_ARG(); if (nh6_ok++) duparg2("nh6", *argv); get_addr(&addr, *argv, AF_INET6); - rta_addattr_l(rta, len, SEG6_LOCAL_NH6, &addr.data, - addr.bytelen); + ret = rta_addattr_l(rta, len, SEG6_LOCAL_NH6, + &addr.data, addr.bytelen); } else if (strcmp(*argv, "iif") == 0) { NEXT_ARG(); if (iif_ok++) @@ -648,7 +651,7 @@ static int parse_encap_seg6local(struct rtattr *rta, size_t len, int *argcp, iif = ll_name_to_index(*argv); if (!iif) exit(nodev(*argv)); - rta_addattr32(rta, len, SEG6_LOCAL_IIF, iif); + ret = rta_addattr32(rta, len, SEG6_LOCAL_IIF, iif); } else if (strcmp(*argv, "oif") == 0) { NEXT_ARG(); if (oif_ok++) @@ -656,7 +659,7 @@ static int parse_encap_seg6local(struct rtattr *rta, size_t len, int *argcp, oif = ll_name_to_index(*argv); if (!oif) exit(nodev(*argv)); - rta_addattr32(rta, len, SEG6_LOCAL_OIF, oif); + ret = rta_addattr32(rta, len, SEG6_LOCAL_OIF, oif); } else if (strcmp(*argv, "srh") == 0) { NEXT_ARG(); if (srh_ok++) @@ -691,6 +694,8 @@ static int parse_encap_seg6local(struct rtattr *rta, size_t len, int *argcp, } else { break; } + if (ret) + return ret; argc--; argv++; } @@ -705,14 +710,14 @@ static int parse_encap_seg6local(struct rtattr *rta, size_t len, int *argcp, srh = parse_srh(segbuf, hmac, action == SEG6_LOCAL_ACTION_END_B6_ENCAP); srhlen = (srh->hdrlen + 1) << 3; - rta_addattr_l(rta, len, SEG6_LOCAL_SRH, srh, srhlen); + ret = rta_addattr_l(rta, len, SEG6_LOCAL_SRH, srh, srhlen); free(srh); } *argcp = argc + 1; *argvp = argv - 1; - return 0; + return ret; } static int parse_encap_mpls(struct rtattr *rta, size_t len, @@ -730,8 +735,9 @@ static int parse_encap_mpls(struct rtattr *rta, size_t len, exit(1); } - rta_addattr_l(rta, len, MPLS_IPTUNNEL_DST, &addr.data, - addr.bytelen); + if (rta_addattr_l(rta, len, MPLS_IPTUNNEL_DST, + &addr.data, addr.bytelen)) + return -1; argc--; argv++; @@ -745,7 +751,8 @@ static int parse_encap_mpls(struct rtattr *rta, size_t len, duparg2("ttl", *argv); if (get_u8(&ttl, *argv, 0)) invarg("\"ttl\" value is invalid\n", *argv); - rta_addattr8(rta, len, MPLS_IPTUNNEL_TTL, ttl); + if (rta_addattr8(rta, len, MPLS_IPTUNNEL_TTL, ttl)) + return -1; } else { break; } @@ -768,6 +775,7 @@ static int parse_encap_ip(struct rtattr *rta, size_t len, int id_ok = 0, dst_ok = 0, tos_ok = 0, ttl_ok = 0; char **argv = *argvp; int argc = *argcp; + int ret = 0; while (argc > 0) { if (strcmp(*argv, "id") == 0) { @@ -778,7 +786,7 @@ static int parse_encap_ip(struct rtattr *rta, size_t len, duparg2("id", *argv); if (get_be64(&id, *argv, 0)) invarg("\"id\" value is invalid\n", *argv); - rta_addattr64(rta, len, LWTUNNEL_IP_ID, id); + ret = rta_addattr64(rta, len, LWTUNNEL_IP_ID, id); } else if (strcmp(*argv, "dst") == 0) { inet_prefix addr; @@ -786,8 +794,8 @@ static int parse_encap_ip(struct rtattr *rta, size_t len, if (dst_ok++) duparg2("dst", *argv); get_addr(&addr, *argv, AF_INET); - rta_addattr_l(rta, len, LWTUNNEL_IP_DST, - &addr.data, addr.bytelen); + ret = rta_addattr_l(rta, len, LWTUNNEL_IP_DST, + &addr.data, addr.bytelen); } else if (strcmp(*argv, "tos") == 0) { __u32 tos; @@ -796,7 +804,7 @@ static int parse_encap_ip(struct rtattr *rta, size_t len, duparg2("tos", *argv); if (rtnl_dsfield_a2n(&tos, *argv)) invarg("\"tos\" value is invalid\n", *argv); - rta_addattr8(rta, len, LWTUNNEL_IP_TOS, tos); + ret = rta_addattr8(rta, len, LWTUNNEL_IP_TOS, tos); } else if (strcmp(*argv, "ttl") == 0) { __u8 ttl; @@ -805,10 +813,12 @@ static int parse_encap_ip(struct rtattr *rta, size_t len, duparg2("ttl", *argv); if (get_u8(&ttl, *argv, 0)) invarg("\"ttl\" value is invalid\n", *argv); - rta_addattr8(rta, len, LWTUNNEL_IP_TTL, ttl); + ret = rta_addattr8(rta, len, LWTUNNEL_IP_TTL, ttl); } else { break; } + if (ret) + break; argc--; argv++; } @@ -819,7 +829,7 @@ static int parse_encap_ip(struct rtattr *rta, size_t len, *argcp = argc + 1; *argvp = argv - 1; - return 0; + return ret; } static int parse_encap_ila(struct rtattr *rta, size_t len, @@ -828,6 +838,7 @@ static int parse_encap_ila(struct rtattr *rta, size_t len, __u64 locator; int argc = *argcp; char **argv = *argvp; + int ret = 0; if (get_addr64(&locator, *argv) < 0) { fprintf(stderr, "Bad locator: %s\n", *argv); @@ -836,7 +847,8 @@ static int parse_encap_ila(struct rtattr *rta, size_t len, argc--; argv++; - rta_addattr64(rta, 1024, ILA_ATTR_LOCATOR, locator); + if (rta_addattr64(rta, 1024, ILA_ATTR_LOCATOR, locator)) + return -1; while (argc > 0) { if (strcmp(*argv, "csum-mode") == 0) { @@ -849,8 +861,8 @@ static int parse_encap_ila(struct rtattr *rta, size_t len, invarg("\"csum-mode\" value is invalid\n", *argv); - rta_addattr8(rta, 1024, ILA_ATTR_CSUM_MODE, - (__u8)csum_mode); + ret = rta_addattr8(rta, 1024, ILA_ATTR_CSUM_MODE, + (__u8)csum_mode); argc--; argv++; } else if (strcmp(*argv, "ident-type") == 0) { @@ -863,8 +875,8 @@ static int parse_encap_ila(struct rtattr *rta, size_t len, invarg("\"ident-type\" value is invalid\n", *argv); - rta_addattr8(rta, 1024, ILA_ATTR_IDENT_TYPE, - (__u8)ident_type); + ret = rta_addattr8(rta, 1024, ILA_ATTR_IDENT_TYPE, + (__u8)ident_type); argc--; argv++; } else if (strcmp(*argv, "hook-type") == 0) { @@ -877,13 +889,15 @@ static int parse_encap_ila(struct rtattr *rta, size_t len, invarg("\"hook-type\" value is invalid\n", *argv); - rta_addattr8(rta, 1024, ILA_ATTR_HOOK_TYPE, - (__u8)hook_type); + ret = rta_addattr8(rta, 1024, ILA_ATTR_HOOK_TYPE, + (__u8)hook_type); argc--; argv++; } else { break; } + if (ret) + break; } /* argv is currently the first unparsed argument, @@ -893,7 +907,7 @@ static int parse_encap_ila(struct rtattr *rta, size_t len, *argcp = argc + 1; *argvp = argv - 1; - return 0; + return ret; } static int parse_encap_ip6(struct rtattr *rta, size_t len, @@ -902,6 +916,7 @@ static int parse_encap_ip6(struct rtattr *rta, size_t len, int id_ok = 0, dst_ok = 0, tos_ok = 0, ttl_ok = 0; char **argv = *argvp; int argc = *argcp; + int ret = 0; while (argc > 0) { if (strcmp(*argv, "id") == 0) { @@ -912,7 +927,7 @@ static int parse_encap_ip6(struct rtattr *rta, size_t len, duparg2("id", *argv); if (get_be64(&id, *argv, 0)) invarg("\"id\" value is invalid\n", *argv); - rta_addattr64(rta, len, LWTUNNEL_IP6_ID, id); + ret = rta_addattr64(rta, len, LWTUNNEL_IP6_ID, id); } else if (strcmp(*argv, "dst") == 0) { inet_prefix addr; @@ -920,8 +935,8 @@ static int parse_encap_ip6(struct rtattr *rta, size_t len, if (dst_ok++) duparg2("dst", *argv); get_addr(&addr, *argv, AF_INET6); - rta_addattr_l(rta, len, LWTUNNEL_IP6_DST, - &addr.data, addr.bytelen); + ret = rta_addattr_l(rta, len, LWTUNNEL_IP6_DST, + &addr.data, addr.bytelen); } else if (strcmp(*argv, "tc") == 0) { __u32 tc; @@ -930,7 +945,7 @@ static int parse_encap_ip6(struct rtattr *rta, size_t len, duparg2("tc", *argv); if (rtnl_dsfield_a2n(&tc, *argv)) invarg("\"tc\" value is invalid\n", *argv); - rta_addattr8(rta, len, LWTUNNEL_IP6_TC, tc); + ret = rta_addattr8(rta, len, LWTUNNEL_IP6_TC, tc); } else if (strcmp(*argv, "hoplimit") == 0) { __u8 hoplimit; @@ -940,10 +955,13 @@ static int parse_encap_ip6(struct rtattr *rta, size_t len, if (get_u8(&hoplimit, *argv, 0)) invarg("\"hoplimit\" value is invalid\n", *argv); - rta_addattr8(rta, len, LWTUNNEL_IP6_HOPLIMIT, hoplimit); + ret = rta_addattr8(rta, len, LWTUNNEL_IP6_HOPLIMIT, + hoplimit); } else { break; } + if (ret) + break; argc--; argv++; } @@ -954,7 +972,7 @@ static int parse_encap_ip6(struct rtattr *rta, size_t len, *argcp = argc + 1; *argvp = argv - 1; - return 0; + return ret; } static void lwt_bpf_usage(void) @@ -1021,6 +1039,7 @@ int lwt_parse_encap(struct rtattr *rta, size_t len, int *argcp, char ***argvp) int argc = *argcp; char **argv = *argvp; __u16 type; + int ret = 0; NEXT_ARG(); type = read_encap_type(*argv); @@ -1037,37 +1056,40 @@ int lwt_parse_encap(struct rtattr *rta, size_t len, int *argcp, char ***argvp) nest = rta_nest(rta, 1024, RTA_ENCAP); switch (type) { case LWTUNNEL_ENCAP_MPLS: - parse_encap_mpls(rta, len, &argc, &argv); + ret = parse_encap_mpls(rta, len, &argc, &argv); break; case LWTUNNEL_ENCAP_IP: - parse_encap_ip(rta, len, &argc, &argv); + ret = parse_encap_ip(rta, len, &argc, &argv); break; case LWTUNNEL_ENCAP_ILA: - parse_encap_ila(rta, len, &argc, &argv); + ret = parse_encap_ila(rta, len, &argc, &argv); break; case LWTUNNEL_ENCAP_IP6: - parse_encap_ip6(rta, len, &argc, &argv); + ret = parse_encap_ip6(rta, len, &argc, &argv); break; case LWTUNNEL_ENCAP_BPF: if (parse_encap_bpf(rta, len, &argc, &argv) < 0) exit(-1); break; case LWTUNNEL_ENCAP_SEG6: - parse_encap_seg6(rta, len, &argc, &argv); + ret = parse_encap_seg6(rta, len, &argc, &argv); break; case LWTUNNEL_ENCAP_SEG6_LOCAL: - parse_encap_seg6local(rta, len, &argc, &argv); + ret = parse_encap_seg6local(rta, len, &argc, &argv); break; default: fprintf(stderr, "Error: unsupported encap type\n"); break; } + if (ret) + return ret; + rta_nest_end(rta, nest); - rta_addattr16(rta, 1024, RTA_ENCAP_TYPE, type); + ret = rta_addattr16(rta, 1024, RTA_ENCAP_TYPE, type); *argcp = argc; *argvp = argv; - return 0; + return ret; } From b85076cd74e77538918d35992b1a9cd17ff86af8 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 11 Sep 2018 08:29:33 -0700 Subject: [PATCH 10/15] lib: introduce print_nl Common pattern in iproute commands is to print a line seperator in non-json mode. Make that a simple function. Signed-off-by: Stephen Hemminger --- bridge/bridge.c | 1 - include/json_print.h | 2 ++ ip/ip.c | 1 - ip/ipaddress.c | 12 ++++++------ ip/ipila.c | 2 +- ip/ipl2tp.c | 14 +++++++------- ip/ipmacsec.c | 2 +- ip/ipmaddr.c | 2 +- ip/ipmroute.c | 2 +- ip/ipntable.c | 16 ++++++++-------- lib/json_print.c | 7 +++++++ lib/utils.c | 1 + tc/tc.c | 1 - 13 files changed, 35 insertions(+), 28 deletions(-) diff --git a/bridge/bridge.c b/bridge/bridge.c index 663a35b2..ac4d6a14 100644 --- a/bridge/bridge.c +++ b/bridge/bridge.c @@ -30,7 +30,6 @@ int json; int timestamp; char *batch_file; int force; -const char *_SL_; static void usage(void) __attribute__((noreturn)); diff --git a/include/json_print.h b/include/json_print.h index 218fedc5..78a6c83f 100644 --- a/include/json_print.h +++ b/include/json_print.h @@ -41,6 +41,8 @@ void close_json_object(void); void open_json_array(enum output_type type, const char *delim); void close_json_array(enum output_type type, const char *delim); +void print_nl(void); + #define _PRINT_FUNC(type_name, type) \ void print_color_##type_name(enum output_type t, \ enum color_attr color, \ diff --git a/ip/ip.c b/ip/ip.c index 58c643df..c324120f 100644 --- a/ip/ip.c +++ b/ip/ip.c @@ -33,7 +33,6 @@ int oneline; int brief; int json; int timestamp; -const char *_SL_; int force; int max_flush_loops = 10; int batch_mode; diff --git a/ip/ipaddress.c b/ip/ipaddress.c index c94ddba8..8dc6c32f 100644 --- a/ip/ipaddress.c +++ b/ip/ipaddress.c @@ -240,7 +240,7 @@ static void print_linktype(FILE *fp, struct rtattr *tb) const char *kind = rta_getattr_str(linkinfo[IFLA_INFO_KIND]); - print_string(PRINT_FP, NULL, "%s", _SL_); + print_nl(); print_string(PRINT_ANY, "info_kind", " %s ", kind); lu = get_link_kind(kind); @@ -269,7 +269,7 @@ static void print_linktype(FILE *fp, struct rtattr *tb) const char *slave_kind = rta_getattr_str(linkinfo[IFLA_INFO_SLAVE_KIND]); - print_string(PRINT_FP, NULL, "%s", _SL_); + print_nl(); print_string(PRINT_ANY, "info_slave_kind", " %s_slave ", @@ -765,7 +765,7 @@ static void print_link_stats(FILE *fp, struct nlmsghdr *n) parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), n->nlmsg_len - NLMSG_LENGTH(sizeof(*ifi))); __print_link_stats(fp, tb); - fprintf(fp, "%s", _SL_); + print_nl(); } static int print_linkinfo_brief(FILE *fp, const char *name, @@ -929,7 +929,7 @@ int print_linkinfo(const struct sockaddr_nl *who, print_link_event(fp, rta_getattr_u32(tb[IFLA_EVENT])); if (!filter.family || filter.family == AF_PACKET || show_details) { - print_string(PRINT_FP, NULL, "%s", _SL_); + print_nl(); print_string(PRINT_ANY, "link_type", " link/%s ", @@ -1090,7 +1090,7 @@ int print_linkinfo(const struct sockaddr_nl *who, xdp_dump(fp, tb[IFLA_XDP], true, true); if (do_link && show_stats) { - print_string(PRINT_FP, NULL, "%s", _SL_); + print_nl(); __print_link_stats(fp, tb); } @@ -1418,7 +1418,7 @@ int print_addrinfo(const struct sockaddr_nl *who, struct nlmsghdr *n, if (rta_tb[IFA_CACHEINFO]) { struct ifa_cacheinfo *ci = RTA_DATA(rta_tb[IFA_CACHEINFO]); - print_string(PRINT_FP, NULL, "%s", _SL_); + print_nl(); print_string(PRINT_FP, NULL, " valid_lft ", NULL); if (ci->ifa_valid == INFINITY_LIFE_TIME) { diff --git a/ip/ipila.c b/ip/ipila.c index 370385c0..895fe0cd 100644 --- a/ip/ipila.c +++ b/ip/ipila.c @@ -128,7 +128,7 @@ static int print_ila_mapping(const struct sockaddr_nl *who, else print_string(PRINT_FP, NULL, "%s", "-"); - print_string(PRINT_FP, NULL, "%s", _SL_); + print_nl(); close_json_object(); return 0; diff --git a/ip/ipl2tp.c b/ip/ipl2tp.c index 5e7f0390..16561ecc 100644 --- a/ip/ipl2tp.c +++ b/ip/ipl2tp.c @@ -219,7 +219,7 @@ static void print_tunnel(const struct l2tp_data *data) print_string(PRINT_ANY, "encap", " encap %s", p->encap == L2TP_ENCAPTYPE_UDP ? "UDP" : p->encap == L2TP_ENCAPTYPE_IP ? "IP" : "??"); - print_string(PRINT_FP, NULL, "%s", _SL_); + print_nl(); print_string(PRINT_ANY, "local", " From %s ", inet_ntop(p->local_ip.family, p->local_ip.data, @@ -227,11 +227,11 @@ static void print_tunnel(const struct l2tp_data *data) print_string(PRINT_ANY, "peer", "to %s", inet_ntop(p->peer_ip.family, p->peer_ip.data, buf, sizeof(buf))); - print_string(PRINT_FP, NULL, "%s", _SL_); + print_nl(); print_uint(PRINT_ANY, "peer_tunnel", " Peer tunnel %u", p->peer_tunnel_id); - print_string(PRINT_FP, NULL, "%s", _SL_); + print_nl(); if (p->encap == L2TP_ENCAPTYPE_UDP) { print_string(PRINT_FP, NULL, @@ -241,7 +241,7 @@ static void print_tunnel(const struct l2tp_data *data) p->local_udp_port); print_uint(PRINT_ANY, "peer_port", "/%hu", p->peer_udp_port); - print_string(PRINT_FP, NULL, "%s", _SL_); + print_nl(); switch (p->local_ip.family) { case AF_INET: @@ -283,18 +283,18 @@ static void print_session(struct l2tp_data *data) print_uint(PRINT_ANY, "session_id", "Session %u", p->session_id); print_uint(PRINT_ANY, "tunnel_id", " in tunnel %u", p->tunnel_id); - print_string(PRINT_FP, NULL, "%s", _SL_); + print_nl(); print_uint(PRINT_ANY, "peer_session_id", " Peer session %u,", p->peer_session_id); print_uint(PRINT_ANY, "peer_tunnel_id", " tunnel %u", p->peer_tunnel_id); - print_string(PRINT_FP, NULL, "%s", _SL_); + print_nl(); if (p->ifname != NULL) { print_color_string(PRINT_ANY, COLOR_IFNAME, "interface", " interface name: %s" , p->ifname); - print_string(PRINT_FP, NULL, "%s", _SL_); + print_nl(); } /* Show offsets only for plain console output (for legacy scripts) */ diff --git a/ip/ipmacsec.c b/ip/ipmacsec.c index 4e4e158e..fa56e0ee 100644 --- a/ip/ipmacsec.c +++ b/ip/ipmacsec.c @@ -627,7 +627,7 @@ static void print_attrs(struct rtattr *attrs[]) if (attrs[MACSEC_SECY_ATTR_CIPHER_SUITE]) { __u64 cid = rta_getattr_u64(attrs[MACSEC_SECY_ATTR_CIPHER_SUITE]); - print_string(PRINT_FP, NULL, "%s", _SL_); + print_nl(); print_string(PRINT_ANY, "cipher_suite", " cipher suite: %s,", cs_id_to_name(cid)); } diff --git a/ip/ipmaddr.c b/ip/ipmaddr.c index abf83784..105b23a8 100644 --- a/ip/ipmaddr.c +++ b/ip/ipmaddr.c @@ -240,7 +240,7 @@ static void print_mlist(FILE *fp, struct ma_info *list) print_uint(PRINT_ANY, "ifindex", "%d:", list->index); print_color_string(PRINT_ANY, COLOR_IFNAME, "ifname", "\t%s", list->name); - print_string(PRINT_FP, NULL, "%s", _SL_); + print_nl(); cur_index = list->index; open_json_array(PRINT_JSON, "maddr"); diff --git a/ip/ipmroute.c b/ip/ipmroute.c index cdb4d898..bc23cfea 100644 --- a/ip/ipmroute.c +++ b/ip/ipmroute.c @@ -181,7 +181,7 @@ int print_mroute(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) if (show_stats && tb[RTA_MFC_STATS]) { struct rta_mfc_stats *mfcs = RTA_DATA(tb[RTA_MFC_STATS]); - print_string(PRINT_FP, NULL, "%s", _SL_); + print_nl(); print_u64(PRINT_ANY, "packets", " %"PRIu64" packets,", mfcs->mfcs_packets); print_u64(PRINT_ANY, "bytes", " %"PRIu64" bytes", mfcs->mfcs_bytes); diff --git a/ip/ipntable.c b/ip/ipntable.c index 4fae181d..dd4f7c2e 100644 --- a/ip/ipntable.c +++ b/ip/ipntable.c @@ -346,7 +346,7 @@ static void print_ndtconfig(const struct ndt_config *ndtc) "entry_size %u ", ndtc->ndtc_entry_size); print_uint(PRINT_ANY, "entries", "entries %u ", ndtc->ndtc_entries); - print_string(PRINT_FP, NULL, "%s", _SL_); + print_nl(); print_string(PRINT_ANY, "last_flush", " last_flush %s ", @@ -355,7 +355,7 @@ static void print_ndtconfig(const struct ndt_config *ndtc) "last_rand %s ", ntable_strtime_delta(ndtc->ndtc_last_rand)); - print_string(PRINT_FP, NULL, "%s", _SL_); + print_nl(); print_uint(PRINT_ANY, "hash_rnd", " hash_rnd %u ", ndtc->ndtc_hash_rnd); @@ -367,7 +367,7 @@ static void print_ndtconfig(const struct ndt_config *ndtc) print_uint(PRINT_ANY, "proxy_qlen", "proxy_qlen %u ", ndtc->ndtc_proxy_qlen); - print_string(PRINT_FP, NULL, "%s", _SL_); + print_nl(); } static void print_ndtparams(struct rtattr *tpb[]) @@ -379,7 +379,7 @@ static void print_ndtparams(struct rtattr *tpb[]) print_string(PRINT_FP, NULL, " dev ", NULL); print_color_string(PRINT_ANY, COLOR_IFNAME, "dev", "%s ", ll_index_to_name(ifindex)); - print_string(PRINT_FP, NULL, "%s", _SL_); + print_nl(); } print_string(PRINT_FP, NULL, " ", NULL); @@ -482,7 +482,7 @@ static void print_ndtparams(struct rtattr *tpb[]) print_u64(PRINT_ANY, "locktime", "locktime %llu ", locktime); } - print_string(PRINT_FP, NULL, "%s", _SL_); + print_nl(); } static void print_ndtstats(const struct ndt_stats *ndts) @@ -517,7 +517,7 @@ static void print_ndtstats(const struct ndt_stats *ndts) print_u64(PRINT_ANY, "forced_gc_runs", "forced_gc_runs %llu ", ndts->ndts_forced_gc_runs); - print_string(PRINT_FP, NULL, "%s", _SL_); + print_nl(); } static int print_ntable(const struct sockaddr_nl *who, @@ -579,7 +579,7 @@ static int print_ntable(const struct sockaddr_nl *who, print_string(PRINT_ANY, "name", "%s ", name); } - print_string(PRINT_FP, NULL, "%s", _SL_); + print_nl(); ret = (tb[NDTA_THRESH1] || tb[NDTA_THRESH2] || tb[NDTA_THRESH3] || tb[NDTA_GC_INTERVAL]); @@ -611,7 +611,7 @@ static int print_ntable(const struct sockaddr_nl *who, } if (ret) - print_string(PRINT_FP, NULL, "%s", _SL_); + print_nl(); if (tb[NDTA_CONFIG] && show_stats) print_ndtconfig(RTA_DATA(tb[NDTA_CONFIG])); diff --git a/lib/json_print.c b/lib/json_print.c index 77902824..eed109c5 100644 --- a/lib/json_print.c +++ b/lib/json_print.c @@ -222,3 +222,10 @@ void print_color_null(enum output_type type, color_fprintf(stdout, color, fmt, value); } } + +/* Print line seperator (if not in JSON mode) */ +void print_nl(void) +{ + if (!_jw) + printf("%s", _SL_); +} diff --git a/lib/utils.c b/lib/utils.c index 02ce6772..e87ecf31 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -42,6 +42,7 @@ int resolve_hosts; int timestamp_short; int pretty; +const char *_SL_ = "\n"; int read_prop(const char *dev, char *prop, long *value) { diff --git a/tc/tc.c b/tc/tc.c index 4b28e9b1..c493d5e9 100644 --- a/tc/tc.c +++ b/tc/tc.c @@ -43,7 +43,6 @@ bool use_names; int json; int color; int oneline; -const char *_SL_; static char *conf_file; From b914fe5f1c5d7beef742b565c98888c5e34efc02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Toke=20H=C3=B8iland-J=C3=B8rgensen?= Date: Wed, 12 Sep 2018 00:32:16 +0200 Subject: [PATCH 11/15] q_cake: Add printing of no-split-gso option MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the GSO splitting was turned into dual split-gso/no-split-gso options, the printing of the latter was left out. Add that, so output is consistent with the options passed. Signed-off-by: Toke Høiland-Jørgensen Signed-off-by: Stephen Hemminger --- tc/q_cake.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tc/q_cake.c b/tc/q_cake.c index 50de46a7..077bf84f 100644 --- a/tc/q_cake.c +++ b/tc/q_cake.c @@ -524,6 +524,8 @@ static int cake_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt) if (split_gso) print_string(PRINT_FP, NULL, "split-gso ", NULL); + else + print_string(PRINT_FP, NULL, "no-split-gso ", NULL); print_bool(PRINT_JSON, "split_gso", NULL, split_gso); if (interval) From 92bba4ed4016af3ce7f7071d3c37f2cb34f240f5 Mon Sep 17 00:00:00 2001 From: Hangbin Liu Date: Wed, 12 Sep 2018 09:39:44 +0800 Subject: [PATCH 12/15] bridge/mdb: fix missing new line when show bridge mdb The bridge mdb show is broken on current iproute2. e.g. ]# bridge mdb show 34: br0 veth0_br 224.1.1.2 temp 34: br0 veth0_br 224.1.1.1 temp After fix: ]# bridge mdb show 34: br0 veth0_br 224.1.1.2 temp 34: br0 veth0_br 224.1.1.1 temp v2: Use json print lib as Stephen suggested. v3: No need to use is_json_context() as print_string() could handle both cases. v4: use new function print_nl() to print new line in non-json mode. Reported-by: Ying Xu Fixes: c7c1a1ef51aea ("bridge: colorize output and use JSON print library") Signed-off-by: Hangbin Liu Signed-off-by: Stephen Hemminger --- bridge/mdb.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/bridge/mdb.c b/bridge/mdb.c index cc1b4547..841a3612 100644 --- a/bridge/mdb.c +++ b/bridge/mdb.c @@ -107,6 +107,10 @@ static void br_print_router_ports(FILE *f, struct rtattr *attr, fprintf(f, "%s ", port_ifname); } } + + if (!show_stats) + print_nl(); + close_json_array(PRINT_JSON, NULL); } @@ -157,6 +161,8 @@ static void print_mdb_entry(FILE *f, int ifindex, const struct br_mdb_entry *e, print_string(PRINT_ANY, "timer", " %s", format_timer(timer)); } + + print_nl(); close_json_object(); } From 2153e01f361ca57dc1baf3cdff1f4ec4323abf38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Toke=20H=C3=B8iland-J=C3=B8rgensen?= Date: Fri, 14 Sep 2018 15:51:39 +0200 Subject: [PATCH 13/15] q_cake: Also print nonat, nowash and no-ack-filter keywords MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Similar to the previous patch for no-split-gso, the negative keywords for 'nat', 'wash' and 'ack-filter' were not printed either. Add those well. Signed-off-by: Toke Høiland-Jørgensen Signed-off-by: Stephen Hemminger --- tc/q_cake.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tc/q_cake.c b/tc/q_cake.c index 077bf84f..e827e3f1 100644 --- a/tc/q_cake.c +++ b/tc/q_cake.c @@ -468,6 +468,8 @@ static int cake_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt) if (nat) print_string(PRINT_FP, NULL, "nat ", NULL); + else + print_string(PRINT_FP, NULL, "nonat ", NULL); print_bool(PRINT_JSON, "nat", NULL, nat); if (tb[TCA_CAKE_WASH] && @@ -508,6 +510,8 @@ static int cake_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt) if (wash) print_string(PRINT_FP, NULL, "wash ", NULL); + else + print_string(PRINT_FP, NULL, "nowash ", NULL); print_bool(PRINT_JSON, "wash", NULL, wash); if (ingress) @@ -520,7 +524,7 @@ static int cake_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt) else if (ack_filter == CAKE_ACK_FILTER) print_string(PRINT_ANY, "ack-filter", "ack-filter ", "enabled"); else - print_string(PRINT_JSON, "ack-filter", NULL, "disabled"); + print_string(PRINT_ANY, "ack-filter", "no-ack-filter ", "disabled"); if (split_gso) print_string(PRINT_FP, NULL, "split-gso ", NULL); From c60389e4f9ea88d7246dbb148d28791d577fe5b4 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 13 Sep 2018 12:33:38 -0700 Subject: [PATCH 14/15] libnetlink: fix leak and using unused memory on error If an error happens in multi-segment message (tc only) then report the error and stop processing further responses. This also fixes refering to the buffer after free. The sequence check is not necessary here because the response message has already been validated to be in the window of the sequence number of the iov. Reported-by: Mahesh Bandewar Signed-off-by: Stephen Hemminger Acked-by: Mahesh Bandewar --- lib/libnetlink.c | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/lib/libnetlink.c b/lib/libnetlink.c index 928de1dd..58680929 100644 --- a/lib/libnetlink.c +++ b/lib/libnetlink.c @@ -617,7 +617,6 @@ static int __rtnl_talk_iov(struct rtnl_handle *rtnl, struct iovec *iov, msg.msg_iovlen = 1; i = 0; while (1) { -next: status = rtnl_recvmsg(rtnl->fd, &msg, &buf); ++i; @@ -660,27 +659,23 @@ next: if (l < sizeof(struct nlmsgerr)) { fprintf(stderr, "ERROR truncated\n"); - } else if (!err->error) { + free(buf); + return -1; + } + + if (!err->error) /* check messages from kernel */ nl_dump_ext_ack(h, errfn); - if (answer) - *answer = (struct nlmsghdr *)buf; - else - free(buf); - if (h->nlmsg_seq == seq) - return 0; - else if (i < iovlen) - goto next; - return 0; - } - if (rtnl->proto != NETLINK_SOCK_DIAG && show_rtnl_err) rtnl_talk_error(h, err, errfn); errno = -err->error; - free(buf); + if (answer) + *answer = (struct nlmsghdr *)buf; + else + free(buf); return -i; } From d090fbf33bd15d82978596920b07616aa119ac2f Mon Sep 17 00:00:00 2001 From: Leon Romanovsky Date: Sun, 16 Sep 2018 20:28:13 +0300 Subject: [PATCH 15/15] rdma: Fix representation of PortInfo CapabilityMask The port capability mask represents IBTA PortInfo specification, but as it is written in description of kernel commit 2f944c0fbf58 ("RDMA: Fix storage of PortInfo CapabilityMask in the kernel"), the bit 26 was mistakenly overwritten. The rdmatool followed it too and mislead users by presenting wrong value. Since it never showed proper value, we update the whole port_cap_mask to comply with IBTA and show real HW values. Fixes: da990ab40a92 ("rdma: Add link object") Signed-off-by: Leon Romanovsky Signed-off-by: Stephen Hemminger --- rdma/link.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/rdma/link.c b/rdma/link.c index 7e914c87..7a6d4b7e 100644 --- a/rdma/link.c +++ b/rdma/link.c @@ -20,6 +20,7 @@ static int link_help(struct rd *rd) static const char *caps_to_str(uint32_t idx) { #define RDMA_PORT_FLAGS(x) \ + x(RESERVED, 0) \ x(SM, 1) \ x(NOTICE, 2) \ x(TRAP, 3) \ @@ -32,7 +33,9 @@ static const char *caps_to_str(uint32_t idx) x(SM_DISABLED, 10) \ x(SYS_IMAGE_GUID, 11) \ x(PKEY_SW_EXT_PORT_TRAP, 12) \ + x(CABLE_INFO, 13) \ x(EXTENDED_SPEEDS, 14) \ + x(CAP_MASK2, 15) \ x(CM, 16) \ x(SNMP_TUNNEL, 17) \ x(REINIT, 18) \ @@ -43,7 +46,12 @@ static const char *caps_to_str(uint32_t idx) x(BOOT_MGMT, 23) \ x(LINK_LATENCY, 24) \ x(CLIENT_REG, 25) \ - x(IP_BASED_GIDS, 26) + x(OTHER_LOCAL_CHANGES, 26) \ + x(LINK_SPPED_WIDTH, 27) \ + x(VENDOR_SPECIFIC_MADS, 28) \ + x(MULT_PKER_TRAP, 29) \ + x(MULT_FDB, 30) \ + x(HIERARCHY_INFO, 31) enum { RDMA_PORT_FLAGS(RDMA_BITMAP_ENUM) }; @@ -51,9 +59,7 @@ static const char *caps_to_str(uint32_t idx) rdma_port_names[] = { RDMA_PORT_FLAGS(RDMA_BITMAP_NAMES) }; #undef RDMA_PORT_FLAGS - if (idx < ARRAY_SIZE(rdma_port_names) && rdma_port_names[idx]) - return rdma_port_names[idx]; - return "UNKNOWN"; + return rdma_port_names[idx]; } static void link_print_caps(struct rd *rd, struct nlattr **tb)