From ac6561417a4d0d4167c1b54e7d163e2062d7f430 Mon Sep 17 00:00:00 2001 From: David Ahern Date: Fri, 5 Jan 2018 19:42:05 -0800 Subject: [PATCH 01/34] Restore --no-print-directory option for silent builds Commit 69fed534a533 ("change how Config is used in Makefile's") removed Config from Makefile. Config had the checks to set VERBOSE based on user request and VERBOSE is used to add the --no-print-directory argument. Since Config is gone, add the relevant setup for VERBOSE to Makefile to restore quieter builds by default. Fixes: 69fed534a533 ("change how Config is used in Makefile's") Signed-off-by: David Ahern Signed-off-by: Stephen Hemminger --- Makefile | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Makefile b/Makefile index 6a51e0db..32587db3 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,13 @@ # SPDX-License-Identifier: GPL-2.0 # Top level Makefile for iproute2 +ifeq ("$(origin V)", "command line") +VERBOSE = $(V) +endif +ifndef VERBOSE +VERBOSE = 0 +endif + ifeq ($(VERBOSE),0) MAKEFLAGS += --no-print-directory endif From 33f6dd23a51c4ed5afbf161317c8d01f003f2c2a Mon Sep 17 00:00:00 2001 From: Filip Moc Date: Sun, 7 Jan 2018 15:28:13 +0100 Subject: [PATCH 02/34] ip fou: pass family attribute as u8 This fixes fou on big-endian systems. Signed-off-by: Filip Moc Signed-off-by: Stephen Hemminger --- ip/ipfou.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ip/ipfou.c b/ip/ipfou.c index febc2c8c..1f392ade 100644 --- a/ip/ipfou.c +++ b/ip/ipfou.c @@ -52,7 +52,7 @@ static int fou_parse_opt(int argc, char **argv, struct nlmsghdr *n, __u8 ipproto, type; bool gue_set = false; int ipproto_set = 0; - unsigned short family = AF_INET; + __u8 family = AF_INET; while (argc > 0) { if (!matches(*argv, "port")) { @@ -103,7 +103,7 @@ static int fou_parse_opt(int argc, char **argv, struct nlmsghdr *n, addattr16(n, 1024, FOU_ATTR_PORT, port); addattr8(n, 1024, FOU_ATTR_TYPE, type); - addattr16(n, 1024, FOU_ATTR_AF, family); + addattr8(n, 1024, FOU_ATTR_AF, family); if (ipproto_set) addattr8(n, 1024, FOU_ATTR_IPPROTO, ipproto); From 192be8fccbdd752f37afc31ee0fa806a662bb9dd Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Sun, 7 Jan 2018 02:31:49 +0800 Subject: [PATCH 03/34] ss: fix crash when skipping disabled header field When the first header field is disabled (i.e. when passing the -t option), field_flush() is invoked with the `buffer` global variable still zero'd. However, in field_flush() we try to access buffer.cur->len during variables initialization, thus leading to a SIGSEGV. It's interesting to note that this bug appears only when the code is compiled with -O0, because the compiler is smart enough to immediately jump to the return statement if optimizations are enabled and skip the faulty instruction. Cc: Stefano Brivio Cc: Stephen Hemminger Signed-off-by: Antonio Quartulli Signed-off-by: Stephen Hemminger --- misc/ss.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/misc/ss.c b/misc/ss.c index 1abf43d0..b35859dc 100644 --- a/misc/ss.c +++ b/misc/ss.c @@ -1018,12 +1018,15 @@ static void print_right_spacing(struct column *f, int printed) /* Done with field: update buffer pointer, start new token after current one */ static void field_flush(struct column *f) { - struct buf_chunk *chunk = buffer.tail; - unsigned int pad = buffer.cur->len % 2; + struct buf_chunk *chunk; + unsigned int pad; if (f->disabled) return; + chunk = buffer.tail; + pad = buffer.cur->len % 2; + if (buffer.cur->len > f->max_len) f->max_len = buffer.cur->len; From ebbb219c924ccedbc59e209d40b77d5dbeecd7cd Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Sun, 7 Jan 2018 02:31:50 +0800 Subject: [PATCH 04/34] ss: fix NULL pointer access when parsing unix sockets with oldformat When parsing and printing the unix sockets in unix_show(), if the oldformat is detected, the peer_name member of the sockstat object is left uninitialized (NULL). For this reason, if a filter has been specified on the command line, a strcmp() will crash when trying to access it. Avoid crash by checking that peer_name is not NULL before passing it to strcmp(). Cc: Stefano Brivio Cc: Stephen Hemminger Signed-off-by: Antonio Quartulli Reviewed-by: Stefano Brivio Signed-off-by: Stephen Hemminger --- misc/ss.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/misc/ss.c b/misc/ss.c index b35859dc..29a25070 100644 --- a/misc/ss.c +++ b/misc/ss.c @@ -3711,7 +3711,10 @@ static int unix_show(struct filter *f) }; memcpy(st.local.data, &u->name, sizeof(u->name)); - if (strcmp(u->peer_name, "*")) + /* when parsing the old format rport is set to 0 and + * therefore peer_name remains NULL + */ + if (u->peer_name && strcmp(u->peer_name, "*")) memcpy(st.remote.data, &u->peer_name, sizeof(u->peer_name)); if (run_ssfilter(f->f, &st) == 0) { From a3665089136dc649177ddc00609a846d70d3a9e3 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 9 Jan 2018 08:06:06 -0800 Subject: [PATCH 05/34] include: update ethernet headers Incorporate upstream changes to fix compliation with MUSL. See commit 6926e041a892 ("uapi/if_ether.h: prevent redefinition of struct ethhdr") Signed-off-by: Stephen Hemminger --- include/uapi/linux/if_ether.h | 3 ++ include/uapi/linux/libc-compat.h | 61 +++++++++++++++++++++++++++++++- 2 files changed, 63 insertions(+), 1 deletion(-) diff --git a/include/uapi/linux/if_ether.h b/include/uapi/linux/if_ether.h index 2eb529a9..5be262f4 100644 --- a/include/uapi/linux/if_ether.h +++ b/include/uapi/linux/if_ether.h @@ -23,6 +23,7 @@ #define _LINUX_IF_ETHER_H #include +#include /* * IEEE 802.3 Ethernet magic constants. The frame sizes omit the preamble @@ -149,11 +150,13 @@ * This is an Ethernet frame header. */ +#if __UAPI_DEF_ETHHDR struct ethhdr { unsigned char h_dest[ETH_ALEN]; /* destination eth addr */ unsigned char h_source[ETH_ALEN]; /* source ether addr */ __be16 h_proto; /* packet type ID field */ } __attribute__((packed)); +#endif #endif /* _LINUX_IF_ETHER_H */ diff --git a/include/uapi/linux/libc-compat.h b/include/uapi/linux/libc-compat.h index 9ab3ace0..5668ec3d 100644 --- a/include/uapi/linux/libc-compat.h +++ b/include/uapi/linux/libc-compat.h @@ -168,47 +168,106 @@ /* If we did not see any headers from any supported C libraries, * or we are being included in the kernel, then define everything - * that we need. */ + * that we need. Check for previous __UAPI_* definitions to give + * unsupported C libraries a way to opt out of any kernel definition. */ #else /* !defined(__GLIBC__) */ /* Definitions for if.h */ +#ifndef __UAPI_DEF_IF_IFCONF #define __UAPI_DEF_IF_IFCONF 1 +#endif +#ifndef __UAPI_DEF_IF_IFMAP #define __UAPI_DEF_IF_IFMAP 1 +#endif +#ifndef __UAPI_DEF_IF_IFNAMSIZ #define __UAPI_DEF_IF_IFNAMSIZ 1 +#endif +#ifndef __UAPI_DEF_IF_IFREQ #define __UAPI_DEF_IF_IFREQ 1 +#endif /* Everything up to IFF_DYNAMIC, matches net/if.h until glibc 2.23 */ +#ifndef __UAPI_DEF_IF_NET_DEVICE_FLAGS #define __UAPI_DEF_IF_NET_DEVICE_FLAGS 1 +#endif /* For the future if glibc adds IFF_LOWER_UP, IFF_DORMANT and IFF_ECHO */ +#ifndef __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO #define __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO 1 +#endif /* Definitions for in.h */ +#ifndef __UAPI_DEF_IN_ADDR #define __UAPI_DEF_IN_ADDR 1 +#endif +#ifndef __UAPI_DEF_IN_IPPROTO #define __UAPI_DEF_IN_IPPROTO 1 +#endif +#ifndef __UAPI_DEF_IN_PKTINFO #define __UAPI_DEF_IN_PKTINFO 1 +#endif +#ifndef __UAPI_DEF_IP_MREQ #define __UAPI_DEF_IP_MREQ 1 +#endif +#ifndef __UAPI_DEF_SOCKADDR_IN #define __UAPI_DEF_SOCKADDR_IN 1 +#endif +#ifndef __UAPI_DEF_IN_CLASS #define __UAPI_DEF_IN_CLASS 1 +#endif /* Definitions for in6.h */ +#ifndef __UAPI_DEF_IN6_ADDR #define __UAPI_DEF_IN6_ADDR 1 +#endif +#ifndef __UAPI_DEF_IN6_ADDR_ALT #define __UAPI_DEF_IN6_ADDR_ALT 1 +#endif +#ifndef __UAPI_DEF_SOCKADDR_IN6 #define __UAPI_DEF_SOCKADDR_IN6 1 +#endif +#ifndef __UAPI_DEF_IPV6_MREQ #define __UAPI_DEF_IPV6_MREQ 1 +#endif +#ifndef __UAPI_DEF_IPPROTO_V6 #define __UAPI_DEF_IPPROTO_V6 1 +#endif +#ifndef __UAPI_DEF_IPV6_OPTIONS #define __UAPI_DEF_IPV6_OPTIONS 1 +#endif +#ifndef __UAPI_DEF_IN6_PKTINFO #define __UAPI_DEF_IN6_PKTINFO 1 +#endif +#ifndef __UAPI_DEF_IP6_MTUINFO #define __UAPI_DEF_IP6_MTUINFO 1 +#endif /* Definitions for ipx.h */ +#ifndef __UAPI_DEF_SOCKADDR_IPX #define __UAPI_DEF_SOCKADDR_IPX 1 +#endif +#ifndef __UAPI_DEF_IPX_ROUTE_DEFINITION #define __UAPI_DEF_IPX_ROUTE_DEFINITION 1 +#endif +#ifndef __UAPI_DEF_IPX_INTERFACE_DEFINITION #define __UAPI_DEF_IPX_INTERFACE_DEFINITION 1 +#endif +#ifndef __UAPI_DEF_IPX_CONFIG_DATA #define __UAPI_DEF_IPX_CONFIG_DATA 1 +#endif +#ifndef __UAPI_DEF_IPX_ROUTE_DEF #define __UAPI_DEF_IPX_ROUTE_DEF 1 +#endif /* Definitions for xattr.h */ +#ifndef __UAPI_DEF_XATTR #define __UAPI_DEF_XATTR 1 +#endif #endif /* __GLIBC__ */ +/* Definitions for if_ether.h */ +/* allow libcs like musl to deactivate this, glibc does not implement this. */ +#ifndef __UAPI_DEF_ETHHDR +#define __UAPI_DEF_ETHHDR 1 +#endif + #endif /* _LIBC_COMPAT_H */ From 24a5a48e2735e5f1ef82b91aaae2e657d15e1cbe Mon Sep 17 00:00:00 2001 From: Jamal Hadi Salim Date: Sun, 7 Jan 2018 09:43:28 -0500 Subject: [PATCH 06/34] tc: Fix filter protocol output Fixes: 249284ff5a44 ("tc: jsonify filter core") Signed-off-by: Jamal Hadi Salim Acked-by: Jiri Pirko --- tc/tc_filter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tc/tc_filter.c b/tc/tc_filter.c index 545cc3a1..546311a8 100644 --- a/tc/tc_filter.c +++ b/tc/tc_filter.c @@ -276,7 +276,7 @@ int print_filter(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) if (!filter_protocol || filter_protocol != f_proto) { if (f_proto) { SPRINT_BUF(b1); - print_string(PRINT_JSON, "protocol", + print_string(PRINT_ANY, "protocol", "protocol %s ", ll_proto_n2a(f_proto, b1, sizeof(b1))); } From b76b24006cdbb4c29ad162e61bac720203ac2cda Mon Sep 17 00:00:00 2001 From: Serhey Popovych Date: Wed, 10 Jan 2018 17:53:09 +0200 Subject: [PATCH 07/34] ip6/tunnel: Fix tclass output In link_gre6.c it seems copy paste error: tclass is 8 bits, not 20 as flowlabel. In link_iptnl.c rename "flowinfo_tclass" to "tclass" as it correct name since flowinfo is implementation internal name used to label combined within u32 attribute tclass and flowlabel. Fixes: 1facc1c61c07 ("ip: link_ip6tnl.c: add json output support") Fixes: 2e706e12d9b0 ("Merge branch 'master' into net-next") Signed-off-by: Serhey Popovych Signed-off-by: Stephen Hemminger --- ip/link_gre6.c | 2 +- ip/link_ip6tnl.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ip/link_gre6.c b/ip/link_gre6.c index 7ae4b492..87c313c2 100644 --- a/ip/link_gre6.c +++ b/ip/link_gre6.c @@ -475,7 +475,7 @@ static void gre_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) if (is_json_context()) { SPRINT_BUF(b1); - snprintf(b1, sizeof(b1), "0x%05x", + snprintf(b1, sizeof(b1), "0x%02x", ntohl(flowinfo & IP6_FLOWINFO_TCLASS) >> 20); print_string(PRINT_JSON, "tclass", NULL, b1); } else { diff --git a/ip/link_ip6tnl.c b/ip/link_ip6tnl.c index 84205b12..8e84ed06 100644 --- a/ip/link_ip6tnl.c +++ b/ip/link_ip6tnl.c @@ -416,7 +416,7 @@ static void ip6tunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb SPRINT_BUF(b1); snprintf(b1, sizeof(b1), "0x%02x", (__u8)(val >> 20)); - print_string(PRINT_JSON, "flowinfo_tclass", NULL, b1); + print_string(PRINT_JSON, "tclass", NULL, b1); } else { printf("tclass 0x%02x ", (__u8)(val >> 20)); } From 4dc6665b6becc5666672d63e9ad6bd8a6e227d34 Mon Sep 17 00:00:00 2001 From: Serhey Popovych Date: Wed, 10 Jan 2018 17:53:10 +0200 Subject: [PATCH 08/34] ip6tnl/tunnel: Do not print obscure flowinfo It is implementation internal and main purpose of printing it seems debugging. Signed-off-by: Serhey Popovych Signed-off-by: Stephen Hemminger --- ip/link_ip6tnl.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/ip/link_ip6tnl.c b/ip/link_ip6tnl.c index 8e84ed06..e0849755 100644 --- a/ip/link_ip6tnl.c +++ b/ip/link_ip6tnl.c @@ -440,16 +440,6 @@ static void ip6tunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb } } - if (is_json_context()) { - SPRINT_BUF(flwinfo); - - snprintf(flwinfo, sizeof(flwinfo), "0x%08x", ntohl(flowinfo)); - print_string(PRINT_JSON, "flowinfo", NULL, flwinfo); - } else { - printf("(flowinfo 0x%08x) ", ntohl(flowinfo)); - - } - if (flags & IP6_TNL_F_RCV_DSCP_COPY) print_bool(PRINT_ANY, "ip6_tnl_f_rcv_dscp_copy", From 090524f8995a56ed45734376a9eab6dc7803aa04 Mon Sep 17 00:00:00 2001 From: Serhey Popovych Date: Wed, 10 Jan 2018 17:53:11 +0200 Subject: [PATCH 09/34] ip6/tunnel: Unify tclass printing Use @s2 buffer to store string representation of tclass and get rid of extra SPRINT_BUF(): no need to preserve @s2 contents for later. Use print_string(PRINT_ANY, ...) with prepared by snprintf() string for both PRINT_JSON and PRINT_FP cases. While there use __u32 for flowinfo in link_gre6.c and check for IFLA_GRE_FLOWINFO attribute presense. Signed-off-by: Serhey Popovych Signed-off-by: Stephen Hemminger --- ip/link_gre6.c | 16 +++++----------- ip/link_ip6tnl.c | 16 +++++----------- 2 files changed, 10 insertions(+), 22 deletions(-) diff --git a/ip/link_gre6.c b/ip/link_gre6.c index 87c313c2..a02dd4a4 100644 --- a/ip/link_gre6.c +++ b/ip/link_gre6.c @@ -380,7 +380,7 @@ static void gre_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) unsigned int iflags = 0; unsigned int oflags = 0; unsigned int flags = 0; - unsigned int flowinfo = 0; + __u32 flowinfo = 0; struct in6_addr in6_addr_any = IN6ADDR_ANY_INIT; if (!tb) @@ -471,17 +471,11 @@ static void gre_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) "ip6_tnl_f_use_orig_tclass", "tclass inherit ", true); - } else { - if (is_json_context()) { - SPRINT_BUF(b1); + } else if (tb[IFLA_GRE_FLOWINFO]) { + __u32 val = ntohl(flowinfo & IP6_FLOWINFO_TCLASS) >> 20; - snprintf(b1, sizeof(b1), "0x%02x", - ntohl(flowinfo & IP6_FLOWINFO_TCLASS) >> 20); - print_string(PRINT_JSON, "tclass", NULL, b1); - } else { - fprintf(f, "tclass 0x%02x ", - ntohl(flowinfo & IP6_FLOWINFO_TCLASS) >> 20); - } + snprintf(s2, sizeof(s2), "0x%02x", val); + print_string(PRINT_ANY, "tclass", "tclass %s ", s2); } if (flags & IP6_TNL_F_RCV_DSCP_COPY) diff --git a/ip/link_ip6tnl.c b/ip/link_ip6tnl.c index e0849755..05322fdf 100644 --- a/ip/link_ip6tnl.c +++ b/ip/link_ip6tnl.c @@ -404,22 +404,16 @@ static void ip6tunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb "hoplimit %u ", rta_getattr_u8(tb[IFLA_IPTUN_TTL])); - if (flags & IP6_TNL_F_USE_ORIG_TCLASS) + if (flags & IP6_TNL_F_USE_ORIG_TCLASS) { print_bool(PRINT_ANY, "ip6_tnl_f_use_orig_tclass", "tclass inherit ", true); - else if (tb[IFLA_IPTUN_FLOWINFO]) { - __u32 val = ntohl(flowinfo & IP6_FLOWINFO_TCLASS); + } else if (tb[IFLA_IPTUN_FLOWINFO]) { + __u32 val = ntohl(flowinfo & IP6_FLOWINFO_TCLASS) >> 20; - if (is_json_context()) { - SPRINT_BUF(b1); - - snprintf(b1, sizeof(b1), "0x%02x", (__u8)(val >> 20)); - print_string(PRINT_JSON, "tclass", NULL, b1); - } else { - printf("tclass 0x%02x ", (__u8)(val >> 20)); - } + snprintf(s2, sizeof(s2), "0x%02x", val); + print_string(PRINT_ANY, "tclass", "tclass %s ", s2); } if (flags & IP6_TNL_F_USE_ORIG_FLOWLABEL) { From a0fd0c3a30c82f4be486190a96fe7dd9428fa5ba Mon Sep 17 00:00:00 2001 From: Serhey Popovych Date: Wed, 10 Jan 2018 17:53:12 +0200 Subject: [PATCH 10/34] ip6/tunnel: Unify flowlabel printing Use @s2 buffer to store string representation of flowlabel and get rid of extra SPRINT_BUF(): no need to preserve @s2 contents for later. Use print_string(PRINT_ANY, ...) with prepared by snprintf() string for both PRINT_JSON and PRINT_FP cases. Omit flowlabel from output if no flowinfo attribute is given and IP6_TNL_F_USE_ORIG_FLOWLABEL isn't set. Signed-off-by: Serhey Popovych Signed-off-by: Stephen Hemminger --- ip/link_gre6.c | 15 ++++----------- ip/link_ip6tnl.c | 14 ++++---------- 2 files changed, 8 insertions(+), 21 deletions(-) diff --git a/ip/link_gre6.c b/ip/link_gre6.c index a02dd4a4..1205946f 100644 --- a/ip/link_gre6.c +++ b/ip/link_gre6.c @@ -452,18 +452,11 @@ static void gre_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) "ip6_tnl_f_use_orig_flowlabel", "flowlabel inherit ", true); - } else { - if (is_json_context()) { - SPRINT_BUF(b1); + } else if (tb[IFLA_GRE_FLOWINFO]) { + __u32 val = ntohl(flowinfo & IP6_FLOWINFO_FLOWLABEL); - snprintf(b1, sizeof(b1), "0x%05x", - ntohl(flowinfo & IP6_FLOWINFO_FLOWLABEL)); - print_string(PRINT_JSON, "flowlabel", NULL, b1); - - } else { - fprintf(f, "flowlabel 0x%05x ", - ntohl(flowinfo & IP6_FLOWINFO_FLOWLABEL)); - } + snprintf(s2, sizeof(s2), "0x%05x", val); + print_string(PRINT_ANY, "flowlabel", "flowlabel %s ", s2); } if (flags & IP6_TNL_F_USE_ORIG_TCLASS) { diff --git a/ip/link_ip6tnl.c b/ip/link_ip6tnl.c index 05322fdf..7000056b 100644 --- a/ip/link_ip6tnl.c +++ b/ip/link_ip6tnl.c @@ -421,17 +421,11 @@ static void ip6tunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb "ip6_tnl_f_use_orig_flowlabel", "flowlabel inherit ", true); - } else { - if (is_json_context()) { - SPRINT_BUF(b1); + } else if (tb[IFLA_IPTUN_FLOWINFO]) { + __u32 val = ntohl(flowinfo & IP6_FLOWINFO_FLOWLABEL); - snprintf(b1, sizeof(b1), "0x%05x", - ntohl(flowinfo & IP6_FLOWINFO_FLOWLABEL)); - print_string(PRINT_JSON, "flowlabel", NULL, b1); - } else { - printf("flowlabel 0x%05x ", - ntohl(flowinfo & IP6_FLOWINFO_FLOWLABEL)); - } + snprintf(s2, sizeof(s2), "0x%05x", val); + print_string(PRINT_ANY, "flowlabel", "flowlabel %s ", s2); } if (flags & IP6_TNL_F_RCV_DSCP_COPY) From e3945d92b0d2671d85c9a06bc573cc2adcbfb08a Mon Sep 17 00:00:00 2001 From: Serhey Popovych Date: Wed, 10 Jan 2018 17:53:13 +0200 Subject: [PATCH 11/34] ip6/tunnel: Unify encap_limit printing Use %u format specifier to print it in link_gre6.c and make code more readable. Signed-off-by: Serhey Popovych Signed-off-by: Stephen Hemminger --- ip/link_gre6.c | 11 ++++------- ip/link_ip6tnl.c | 12 ++++++------ 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/ip/link_gre6.c b/ip/link_gre6.c index 1205946f..8014207d 100644 --- a/ip/link_gre6.c +++ b/ip/link_gre6.c @@ -433,18 +433,15 @@ static void gre_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) print_int(PRINT_JSON, "ttl", NULL, ttl); } - if (flags & IP6_TNL_F_IGN_ENCAP_LIMIT) + if (flags & IP6_TNL_F_IGN_ENCAP_LIMIT) { print_bool(PRINT_ANY, "ip6_tnl_f_ign_encap_limit", "encaplimit none ", true); - else if (tb[IFLA_GRE_ENCAP_LIMIT]) { - int encap_limit = rta_getattr_u8(tb[IFLA_GRE_ENCAP_LIMIT]); + } else if (tb[IFLA_GRE_ENCAP_LIMIT]) { + __u8 val = rta_getattr_u8(tb[IFLA_GRE_ENCAP_LIMIT]); - print_int(PRINT_ANY, - "encap_limit", - "encaplimit %d ", - encap_limit); + print_uint(PRINT_ANY, "encap_limit", "encaplimit %u ", val); } if (flags & IP6_TNL_F_USE_ORIG_FLOWLABEL) { diff --git a/ip/link_ip6tnl.c b/ip/link_ip6tnl.c index 7000056b..379eb331 100644 --- a/ip/link_ip6tnl.c +++ b/ip/link_ip6tnl.c @@ -387,16 +387,16 @@ static void ip6tunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb print_uint(PRINT_ANY, "link_index", "dev %u ", link); } - if (flags & IP6_TNL_F_IGN_ENCAP_LIMIT) + if (flags & IP6_TNL_F_IGN_ENCAP_LIMIT) { print_bool(PRINT_ANY, "ip6_tnl_f_ign_encap_limit", "encaplimit none ", true); - else if (tb[IFLA_IPTUN_ENCAP_LIMIT]) - print_uint(PRINT_ANY, - "encap_limit", - "encaplimit %u ", - rta_getattr_u8(tb[IFLA_IPTUN_ENCAP_LIMIT])); + } else if (tb[IFLA_IPTUN_ENCAP_LIMIT]) { + __u8 val = rta_getattr_u8(tb[IFLA_IPTUN_ENCAP_LIMIT]); + + print_uint(PRINT_ANY, "encap_limit", "encaplimit %u ", val); + } if (tb[IFLA_IPTUN_TTL]) print_uint(PRINT_ANY, From 763cf4956dbc7e6548f885f9ac5f6ed4db008058 Mon Sep 17 00:00:00 2001 From: Serhey Popovych Date: Wed, 10 Jan 2018 17:53:14 +0200 Subject: [PATCH 12/34] gre6/tunnel: Output flowlabel after tclass To follow ip6tnl output print flowlabel after tclass in link_gre6.c. Signed-off-by: Serhey Popovych Signed-off-by: Stephen Hemminger --- ip/link_gre6.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/ip/link_gre6.c b/ip/link_gre6.c index 8014207d..55bd1fbb 100644 --- a/ip/link_gre6.c +++ b/ip/link_gre6.c @@ -444,18 +444,6 @@ static void gre_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) print_uint(PRINT_ANY, "encap_limit", "encaplimit %u ", val); } - if (flags & IP6_TNL_F_USE_ORIG_FLOWLABEL) { - print_bool(PRINT_ANY, - "ip6_tnl_f_use_orig_flowlabel", - "flowlabel inherit ", - true); - } else if (tb[IFLA_GRE_FLOWINFO]) { - __u32 val = ntohl(flowinfo & IP6_FLOWINFO_FLOWLABEL); - - snprintf(s2, sizeof(s2), "0x%05x", val); - print_string(PRINT_ANY, "flowlabel", "flowlabel %s ", s2); - } - if (flags & IP6_TNL_F_USE_ORIG_TCLASS) { print_bool(PRINT_ANY, "ip6_tnl_f_use_orig_tclass", @@ -468,6 +456,18 @@ static void gre_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) print_string(PRINT_ANY, "tclass", "tclass %s ", s2); } + if (flags & IP6_TNL_F_USE_ORIG_FLOWLABEL) { + print_bool(PRINT_ANY, + "ip6_tnl_f_use_orig_flowlabel", + "flowlabel inherit ", + true); + } else if (tb[IFLA_GRE_FLOWINFO]) { + __u32 val = ntohl(flowinfo & IP6_FLOWINFO_FLOWLABEL); + + snprintf(s2, sizeof(s2), "0x%05x", val); + print_string(PRINT_ANY, "flowlabel", "flowlabel %s ", s2); + } + if (flags & IP6_TNL_F_RCV_DSCP_COPY) print_bool(PRINT_ANY, "ip6_tnl_f_rcv_dscp_copy", From cc899123ccb7ba98d2a8272fe3fc1ee4913aa6cf Mon Sep 17 00:00:00 2001 From: Serhey Popovych Date: Wed, 10 Jan 2018 17:53:15 +0200 Subject: [PATCH 13/34] ip6tnl/tunnel: Output hoplimit before encapsulation limit To follow gre6 output print hoplimit before encapsulation limit in link_ip6tnl.c. Signed-off-by: Serhey Popovych Signed-off-by: Stephen Hemminger --- ip/link_ip6tnl.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/ip/link_ip6tnl.c b/ip/link_ip6tnl.c index 379eb331..bbc7878c 100644 --- a/ip/link_ip6tnl.c +++ b/ip/link_ip6tnl.c @@ -387,6 +387,13 @@ static void ip6tunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb print_uint(PRINT_ANY, "link_index", "dev %u ", link); } + if (tb[IFLA_IPTUN_TTL]) { + print_uint(PRINT_ANY, + "ttl", + "hoplimit %u ", + rta_getattr_u8(tb[IFLA_IPTUN_TTL])); + } + if (flags & IP6_TNL_F_IGN_ENCAP_LIMIT) { print_bool(PRINT_ANY, "ip6_tnl_f_ign_encap_limit", @@ -398,12 +405,6 @@ static void ip6tunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb print_uint(PRINT_ANY, "encap_limit", "encaplimit %u ", val); } - if (tb[IFLA_IPTUN_TTL]) - print_uint(PRINT_ANY, - "ttl", - "hoplimit %u ", - rta_getattr_u8(tb[IFLA_IPTUN_TTL])); - if (flags & IP6_TNL_F_USE_ORIG_TCLASS) { print_bool(PRINT_ANY, "ip6_tnl_f_use_orig_tclass", From 7d63671030438bef63448eb117d092cf305c9a16 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 10 Jan 2018 08:21:22 -0800 Subject: [PATCH 14/34] tc: remove no longer relevant README This document described how kernel and tc used to handle timing. In last two years, kernel has switched over to using ktime. Nothing to see here, move along. Signed-off-by: Stephen Hemminger --- tc/README.last | 45 --------------------------------------------- 1 file changed, 45 deletions(-) delete mode 100644 tc/README.last diff --git a/tc/README.last b/tc/README.last deleted file mode 100644 index 63f6f7b0..00000000 --- a/tc/README.last +++ /dev/null @@ -1,45 +0,0 @@ -Kernel code and interface. --------------------------- - -* Compile time switches - -There is only one, but very important, compile time switch. -It is not settable by "make config", but should be selected -manually and after a bit of thinking in - -PSCHED_CLOCK_SOURCE can take three values: - - PSCHED_GETTIMEOFDAY - PSCHED_JIFFIES - PSCHED_CPU - - - PSCHED_GETTIMEOFDAY - -Default setting is the most conservative PSCHED_GETTIMEOFDAY. -It is very slow both because of weird slowness of do_gettimeofday() -and because it forces code to use unnatural "timeval" format, -where microseconds and seconds fields are separate. -Besides that, it will misbehave, when delays exceed 2 seconds -(f.e. very slow links or classes bounded to small slice of bandwidth) -To resume: as only you will get it working, select correct clock -source and forget about PSCHED_GETTIMEOFDAY forever. - - - PSCHED_JIFFIES - -Clock is derived from jiffies. On architectures with HZ=100 -granularity of this clock is not enough to make reasonable -bindings to real time. However, taking into account Linux -architecture problems, which force us to use artificial -integrated clock in any case, this switch is not so bad -for schduling even on high speed networks, though policing -is not reliable. - - - PSCHED_CPU - -It is available only for alpha and pentiums with correct -CPU timestamp. It is the fastest way, use it when it is available, -but remember: not all pentiums have this facility, and -a lot of them have clock, broken by APM etc. etc. From 54f5991acd5c37727461434bb9e9629bdf2d8625 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Tue, 9 Jan 2018 18:20:03 -0500 Subject: [PATCH 15/34] mark shell scripts +x This makes it easier to execute locally for testing. Signed-off-by: Mike Frysinger --- ip/ifcfg | 0 ip/routef | 0 ip/routel | 0 ip/rtpr | 0 4 files changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 ip/ifcfg mode change 100644 => 100755 ip/routef mode change 100644 => 100755 ip/routel mode change 100644 => 100755 ip/rtpr diff --git a/ip/ifcfg b/ip/ifcfg old mode 100644 new mode 100755 diff --git a/ip/routef b/ip/routef old mode 100644 new mode 100755 diff --git a/ip/routel b/ip/routel old mode 100644 new mode 100755 diff --git a/ip/rtpr b/ip/rtpr old mode 100644 new mode 100755 From a8b970d7d241de8ea2885d6d0b72fec0f557422d Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Tue, 9 Jan 2018 18:19:59 -0500 Subject: [PATCH 16/34] ifcfg/rtpr: convert to POSIX shell These files are already mostly written in POSIX shell, so convert their shebangs to /bin/sh and tweak the few bashisms in here. URL: https://crbug.com/756559 Reported-by: Pat Erley Signed-off-by: Mike Frysinger --- ip/ifcfg | 12 ++++++------ ip/rtpr | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/ip/ifcfg b/ip/ifcfg index 851b9215..5b34decd 100755 --- a/ip/ifcfg +++ b/ip/ifcfg @@ -1,4 +1,4 @@ -#! /bin/bash +#! /bin/sh # SPDX-License-Identifier: GPL-2.0 CheckForwarding () { @@ -7,7 +7,7 @@ CheckForwarding () { fwd=0 if [ -d $sbase ]; then for dir in $sbase/*/forwarding; do - fwd=$[$fwd + `cat $dir`] + fwd=$(( fwd + $(cat "$dir") )) done else fwd=2 @@ -128,12 +128,12 @@ fi arping -q -A -c 1 -I $dev $ipaddr noarp=$? ( sleep 2 ; - arping -q -U -c 1 -I $dev $ipaddr ) >& /dev/null /dev/null 2>&1 & /dev/null -ip route add unreachable 255.255.255.255 >& /dev/null +ip route add unreachable 224.0.0.0/24 >/dev/null 2>&1 +ip route add unreachable 255.255.255.255 >/dev/null 2>&1 if [ "`ip link ls $dev | grep -c MULTICAST`" -ge 1 ]; then - ip route add 224.0.0.0/4 dev $dev scope global >& /dev/null + ip route add 224.0.0.0/4 dev $dev scope global >/dev/null 2>&1 fi if [ $fwd -eq 0 ]; then diff --git a/ip/rtpr b/ip/rtpr index 192a476f..7e48674b 100755 --- a/ip/rtpr +++ b/ip/rtpr @@ -1,4 +1,4 @@ -#! /bin/bash +#! /bin/sh # SPDX-License-Identifier: GPL-2.0 exec tr "[\\\\]" "[ From 4afbeaeeafe8475d42127935fcf511aca30b2063 Mon Sep 17 00:00:00 2001 From: Christian Ehrhardt Date: Wed, 10 Jan 2018 16:11:36 +0100 Subject: [PATCH 17/34] tests: read limited amount from /dev/urandom In some test environments like e.g. Ubuntu & Debian autopkgtest it can happen that while generating random device names the pipes between tr and head are considered dead while processing. That prints (non fatal) issues like: Running ip/link/new_link.t [iproute2-this/4.13.0-17-generic]: tr: write error: Broken pipe tr: write error PASS This only happens if reading an infinite amount of chars with the read from urandom, so reading a defined amount fixes the issue. Signed-off-by: Christian Ehrhardt Signed-off-by: Stephen Hemminger --- testsuite/lib/generic.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testsuite/lib/generic.sh b/testsuite/lib/generic.sh index b7de7044..3645ff52 100644 --- a/testsuite/lib/generic.sh +++ b/testsuite/lib/generic.sh @@ -87,7 +87,7 @@ ts_qdisc_available() rand_dev() { - echo "dev-$(tr -dc "[:alpha:]" < /dev/urandom | head -c 6)" + echo "dev-$(head -c 250 /dev/urandom | tr -dc '[:alpha:]' | head -c 6)" } pr_failed() From 9bed02a5d576f2d3cb3c8b250d8938f4978343f3 Mon Sep 17 00:00:00 2001 From: Christian Ehrhardt Date: Wed, 10 Jan 2018 16:11:37 +0100 Subject: [PATCH 18/34] tests: make sure rand_dev suffix has 6 chars The change to limit the read size from /dev/urandom is a tradeoff. Reading too much can trigger an issue, but so it could if the suggested 250 random chars would not contain enough [:alpha:] chars. If they contain: a) >=6 all is ok b) [1-5] the devname would be shorter than expected (non fatal). c) 0 things would break In loops of hundreds of thousands it always was (a) for my, but since if occuring in a test it might be hard to track what happened avoid this issue by retrying on the length condition. Signed-off-by: Christian Ehrhardt Signed-off-by: Stephen Hemminger --- testsuite/lib/generic.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/testsuite/lib/generic.sh b/testsuite/lib/generic.sh index 3645ff52..8cef20fa 100644 --- a/testsuite/lib/generic.sh +++ b/testsuite/lib/generic.sh @@ -87,7 +87,11 @@ ts_qdisc_available() rand_dev() { - echo "dev-$(head -c 250 /dev/urandom | tr -dc '[:alpha:]' | head -c 6)" + rnd="" + while [ ${#rnd} -ne 6 ]; do + rnd="$(head -c 250 /dev/urandom | tr -dc '[:alpha:]' | head -c 6)" + done + echo "dev-$rnd" } pr_failed() From 6f7df6b2a1fef1b8df249a2a84a0c6cb029007c5 Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Fri, 12 Jan 2018 12:20:21 +0100 Subject: [PATCH 19/34] tc: Optimize gact action lookup When adding a filter with a gact action such as 'drop', tc first tries to open a shared object with equivalent name (m_drop.so in this case) before trying gact. Avoid this by matching the action name against those handled by gact prior to calling get_action_kind(). Cc: Jiri Pirko Cc: Jamal Hadi Salim Cc: David Ahern Signed-off-by: Phil Sutter --- tc/m_action.c | 5 ++++- tc/tc_util.c | 10 ++++++---- tc/tc_util.h | 2 ++ 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/tc/m_action.c b/tc/m_action.c index fc422364..d3df93c0 100644 --- a/tc/m_action.c +++ b/tc/m_action.c @@ -194,7 +194,10 @@ int parse_action(int *argc_p, char ***argv_p, int tca_id, struct nlmsghdr *n) } else { struct action_util *a = NULL; - strncpy(k, *argv, sizeof(k) - 1); + if (!action_a2n(*argv, NULL, false)) + strncpy(k, "gact", sizeof(k) - 1); + else + strncpy(k, *argv, sizeof(k) - 1); eap = 0; if (argc > 0) { a = get_action_kind(k); diff --git a/tc/tc_util.c b/tc/tc_util.c index ee9a70aa..10e5aa91 100644 --- a/tc/tc_util.c +++ b/tc/tc_util.c @@ -511,7 +511,7 @@ static const char *action_n2a(int action) * * In error case, returns -1 and does not touch @result. Otherwise returns 0. */ -static int action_a2n(char *arg, int *result, bool allow_num) +int action_a2n(char *arg, int *result, bool allow_num) { int n; char dummy; @@ -535,13 +535,15 @@ static int action_a2n(char *arg, int *result, bool allow_num) for (iter = a2n; iter->a; iter++) { if (matches(arg, iter->a) != 0) continue; - *result = iter->n; - return 0; + n = iter->n; + goto out_ok; } if (!allow_num || sscanf(arg, "%d%c", &n, &dummy) != 1) return -1; - *result = n; +out_ok: + if (result) + *result = n; return 0; } diff --git a/tc/tc_util.h b/tc/tc_util.h index 1218610d..e354765f 100644 --- a/tc/tc_util.h +++ b/tc/tc_util.h @@ -132,4 +132,6 @@ int prio_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt); int cls_names_init(char *path); void cls_names_uninit(void); +int action_a2n(char *arg, int *result, bool allow_num); + #endif From a3e0229e25fa2e9d0bc66317cc140efbfeed2ebc Mon Sep 17 00:00:00 2001 From: Serhey Popovych Date: Fri, 12 Jan 2018 20:03:39 +0200 Subject: [PATCH 20/34] ipaddress: Use family_name() for better code reuse Signed-off-by: Serhey Popovych --- ip/ipaddress.c | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/ip/ipaddress.c b/ip/ipaddress.c index f150d919..a3595c1e 100644 --- a/ip/ipaddress.c +++ b/ip/ipaddress.c @@ -1558,6 +1558,8 @@ int print_addrinfo(const struct sockaddr_nl *who, struct nlmsghdr *n, print_bool(PRINT_ANY, "deleted", "Deleted ", true); if (!brief) { + const char *name; + if (filter.oneline || filter.flushb) { const char *dev = ll_index_to_name(ifa->ifa_index); @@ -1570,20 +1572,13 @@ int print_addrinfo(const struct sockaddr_nl *who, struct nlmsghdr *n, } } - int family = ifa->ifa_family; - - if (ifa->ifa_family == AF_INET) - print_string(PRINT_ANY, "family", " %s ", "inet"); - else if (ifa->ifa_family == AF_INET6) - print_string(PRINT_ANY, "family", " %s ", "inet6"); - else if (ifa->ifa_family == AF_DECnet) - print_string(PRINT_ANY, "family", " %s ", "dnet"); - else if (ifa->ifa_family == AF_IPX) - print_string(PRINT_ANY, "family", " %s ", "ipx"); - else - print_int(PRINT_ANY, - "family_index", - " family %d ", family); + name = family_name(ifa->ifa_family); + if (*name != '?') { + print_string(PRINT_ANY, "family", " %s ", name); + } else { + print_int(PRINT_ANY, "family_index", " family %d ", + ifa->ifa_family); + } } if (rta_tb[IFA_LOCAL]) { From 04be08e0bd2ed67bbedb787b70d1d73e91322d75 Mon Sep 17 00:00:00 2001 From: Gal Pressman Date: Tue, 16 Jan 2018 15:41:58 +0200 Subject: [PATCH 21/34] iplink: Validate minimum tx rate is less than maximum tx rate According to the documentation (man ip-link), the minimum TXRATE should be always <= Maximum TXRATE, but commit f89a2a05ffa9 ("Add support to configure SR-IOV VF minimum and maximum Tx rate through ip tool") didn't enforce it. Fixes: f89a2a05ffa9 ("Add support to configure SR-IOV VF minimum and maximum Tx rate through ip tool") Cc: Sucheta Chakraborty Signed-off-by: Gal Pressman Reviewed-by: Eran Ben Elisha Reviewed-by: Leon Romanovsky --- ip/iplink.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/ip/iplink.c b/ip/iplink.c index 4c967112..22c9a29c 100644 --- a/ip/iplink.c +++ b/ip/iplink.c @@ -539,6 +539,14 @@ static int iplink_parse_vf(int vf, int *argcp, char ***argvp, if (tivt.max_tx_rate == -1) tivt.max_tx_rate = tmax; } + + if (tivt.max_tx_rate && tivt.min_tx_rate > tivt.max_tx_rate) { + fprintf(stderr, + "Invalid min_tx_rate %d - must be <= max_tx_rate %d\n", + tivt.min_tx_rate, tivt.max_tx_rate); + return -1; + } + addattr_l(&req->n, sizeof(*req), IFLA_VF_RATE, &tivt, sizeof(tivt)); } From 39315157ab16205846ed34996cf4c8c0f58113c0 Mon Sep 17 00:00:00 2001 From: Gal Pressman Date: Tue, 16 Jan 2018 15:41:59 +0200 Subject: [PATCH 22/34] ipaddress: Make sure VF min/max rate API is supported before using it When using the new minimum rate API and providing only one parameter (minimum rate/maximum rate), we query the VF min and max rate regardless of kernel support. This resulted in segmentation fault in ipaddr_loop_each_vf, which tries to access NULL pointer. This patch identifies such cases by testing the VF table for NULL pointer in IFLA_VF_RATE, and aborts the operation. Aborting on the first VF is valid since if the kernel does not support the new API for the first VF, it will not support it for the other VFs as well. Fixes: f89a2a05ffa9 ("Add support to configure SR-IOV VF minimum and maximum Tx rate through ip tool") Cc: Sucheta Chakraborty Signed-off-by: Gal Pressman Reviewed-by: Eran Ben Elisha Reviewed-by: Leon Romanovsky --- ip/ipaddress.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ip/ipaddress.c b/ip/ipaddress.c index a3595c1e..c41e24b5 100644 --- a/ip/ipaddress.c +++ b/ip/ipaddress.c @@ -2246,6 +2246,12 @@ ipaddr_loop_each_vf(struct rtattr *tb[], int vfnum, int *min, int *max) for (i = RTA_DATA(vflist); RTA_OK(i, rem); i = RTA_NEXT(i, rem)) { parse_rtattr_nested(vf, IFLA_VF_MAX, i); + + if (!vf[IFLA_VF_RATE]) { + fprintf(stderr, "VF min/max rate API not supported\n"); + exit(1); + } + vf_rate = RTA_DATA(vf[IFLA_VF_RATE]); if (vf_rate->vf == vfnum) { *min = vf_rate->min_tx_rate; From c7db3921ec0481c1298e5f299cde3dea59ded08e Mon Sep 17 00:00:00 2001 From: Gal Pressman Date: Tue, 16 Jan 2018 15:42:00 +0200 Subject: [PATCH 23/34] man: Document the meaning of zero in min/max_tx_rate parameters Zero value in min/max_tx_rate has a special meaning of no rate limit, document it. Signed-off-by: Gal Pressman Reviewed-by: Eran Ben Elisha Reviewed-by: Leon Romanovsky --- man/man8/ip-link.8.in | 2 ++ 1 file changed, 2 insertions(+) diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in index ff6bb9a2..5e498502 100644 --- a/man/man8/ip-link.8.in +++ b/man/man8/ip-link.8.in @@ -1595,6 +1595,7 @@ option instead. .sp .BI max_tx_rate " TXRATE" - change the allowed maximum transmit bandwidth, in Mbps, for the specified VF. +Setting this parameter to 0 disables rate limiting. .B vf parameter must be specified. @@ -1602,6 +1603,7 @@ parameter must be specified. .BI min_tx_rate " TXRATE" - change the allowed minimum transmit bandwidth, in Mbps, for the specified VF. Minimum TXRATE should be always <= Maximum TXRATE. +Setting this parameter to 0 disables rate limiting. .B vf parameter must be specified. From c4fb35bdfcef9c8974392df3fb702b91cc54a755 Mon Sep 17 00:00:00 2001 From: Serhey Popovych Date: Thu, 18 Jan 2018 16:24:40 +0200 Subject: [PATCH 24/34] iplink: Fix "alias" parameter length calculations We need NEXT_ARG() to get *argv pointing to "alias" parameter value. Overwise we get and check "alias" string length. Fixes: f88becf35e08 ("iplink: Process "alias" parameter correctly") Signed-off-by: Serhey Popovych Signed-off-by: Stephen Hemminger --- ip/iplink.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ip/iplink.c b/ip/iplink.c index 22c9a29c..2db2c691 100644 --- a/ip/iplink.c +++ b/ip/iplink.c @@ -778,10 +778,10 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req, argc--; argv++; break; } else if (matches(*argv, "alias") == 0) { + NEXT_ARG(); len = strlen(*argv); if (len >= IFALIASZ) invarg("alias too long\n", *argv); - NEXT_ARG(); addattr_l(&req->n, sizeof(*req), IFLA_IFALIAS, *argv, len); } else if (strcmp(*argv, "group") == 0) { From c619f2be8b7824ab8e19203d8040fbc5e766a183 Mon Sep 17 00:00:00 2001 From: Arkadi Sharshevsky Date: Wed, 17 Jan 2018 15:28:00 +0200 Subject: [PATCH 25/34] devlink: Ignore unknown attributes In case of extending the UAPI old packages would break. Signed-off-by: Arkadi Sharshevsky Acked-by: Jiri Pirko Signed-off-by: Stephen Hemminger --- devlink/devlink.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/devlink/devlink.c b/devlink/devlink.c index 1b15eef8..220b2bb2 100644 --- a/devlink/devlink.c +++ b/devlink/devlink.c @@ -343,7 +343,7 @@ static int attr_cb(const struct nlattr *attr, void *data) int type; if (mnl_attr_type_valid(attr, DEVLINK_ATTR_MAX) < 0) - return MNL_CB_ERROR; + return MNL_CB_OK; type = mnl_attr_get_type(attr); if (mnl_attr_validate(attr, devlink_policy[type]) < 0) From 45d3a6efb20d62cd5c618898a32906dcfd5a08d2 Mon Sep 17 00:00:00 2001 From: Serhey Popovych Date: Thu, 18 Jan 2018 16:04:28 +0200 Subject: [PATCH 26/34] iplink: Use ll_index_to_name() instead of if_indextoname() There are two reasons for switching to cached variant: 1) ll_index_to_name() may return result from cache, eliminating expensive ioctl() to the kernel. Note that most of the code already switched from plain if_indextoname() to ll_index_to_name() to cached variant in print path because in most cases cache populated. 2) It always return name in the form "if%d", even if entry is not in cache and ioctl() fails. This drops "link_index" from JSON output. Signed-off-by: Serhey Popovych Signed-off-by: Stephen Hemminger --- bridge/fdb.c | 5 ++--- bridge/link.c | 19 +++++++------------ ip/iplink_bond.c | 38 ++++++++++++++------------------------ ip/iplink_vxlan.c | 15 ++++++--------- ip/iproute_lwtunnel.c | 7 ++----- ip/link_gre.c | 11 +++++------ ip/link_gre6.c | 11 +++++------ ip/link_ip6tnl.c | 11 +++++------ ip/link_iptnl.c | 11 +++++------ ip/link_vti.c | 14 ++++++-------- ip/link_vti6.c | 13 ++++++------- 11 files changed, 63 insertions(+), 92 deletions(-) diff --git a/bridge/fdb.c b/bridge/fdb.c index 376713b6..4d55fb04 100644 --- a/bridge/fdb.c +++ b/bridge/fdb.c @@ -219,10 +219,9 @@ int print_fdb(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) unsigned int ifindex = rta_getattr_u32(tb[NDA_IFINDEX]); if (ifindex) { - char ifname[IF_NAMESIZE]; + if (!tb[NDA_LINK_NETNSID]) { + const char *ifname = ll_index_to_name(ifindex); - if (!tb[NDA_LINK_NETNSID] && - if_indextoname(ifindex, ifname)) { if (jw_global) jsonw_string_field(jw_global, "viaIf", ifname); diff --git a/bridge/link.c b/bridge/link.c index e2371d0d..870ebe05 100644 --- a/bridge/link.c +++ b/bridge/link.c @@ -26,8 +26,6 @@ static const char *port_states[] = { [BR_STATE_BLOCKING] = "blocking", }; -extern char *if_indextoname(unsigned int __ifindex, char *__ifname); - static void print_link_flags(FILE *fp, unsigned int flags) { fprintf(fp, "<"); @@ -104,7 +102,6 @@ int print_linkinfo(const struct sockaddr_nl *who, int len = n->nlmsg_len; struct ifinfomsg *ifi = NLMSG_DATA(n); struct rtattr *tb[IFLA_MAX+1]; - char b1[IFNAMSIZ]; len -= NLMSG_LENGTH(sizeof(*ifi)); if (len < 0) { @@ -135,14 +132,10 @@ int print_linkinfo(const struct sockaddr_nl *who, print_operstate(fp, rta_getattr_u8(tb[IFLA_OPERSTATE])); if (tb[IFLA_LINK]) { - SPRINT_BUF(b1); int iflink = rta_getattr_u32(tb[IFLA_LINK]); - if (iflink == 0) - fprintf(fp, "@NONE: "); - else - fprintf(fp, "@%s: ", - if_indextoname(iflink, b1)); + fprintf(fp, "@%s: ", + iflink ? ll_index_to_name(iflink) : "NONE"); } else fprintf(fp, ": "); @@ -151,9 +144,11 @@ int print_linkinfo(const struct sockaddr_nl *who, if (tb[IFLA_MTU]) fprintf(fp, "mtu %u ", rta_getattr_u32(tb[IFLA_MTU])); - if (tb[IFLA_MASTER]) - fprintf(fp, "master %s ", - if_indextoname(rta_getattr_u32(tb[IFLA_MASTER]), b1)); + if (tb[IFLA_MASTER]) { + int master = rta_getattr_u32(tb[IFLA_MASTER]); + + fprintf(fp, "master %s ", ll_index_to_name(master)); + } if (tb[IFLA_PROTINFO]) { if (tb[IFLA_PROTINFO]->rta_type & NLA_F_NESTED) { diff --git a/ip/iplink_bond.c b/ip/iplink_bond.c index 2b5cf4f6..f01fd8da 100644 --- a/ip/iplink_bond.c +++ b/ip/iplink_bond.c @@ -369,8 +369,6 @@ static int bond_parse_opt(struct link_util *lu, int argc, char **argv, static void bond_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) { - unsigned int ifindex; - if (!tb) return; @@ -380,21 +378,16 @@ static void bond_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) print_string(PRINT_ANY, "mode", "mode %s ", mode); } - if (tb[IFLA_BOND_ACTIVE_SLAVE] && - (ifindex = rta_getattr_u32(tb[IFLA_BOND_ACTIVE_SLAVE]))) { - char buf[IFNAMSIZ]; - const char *n = if_indextoname(ifindex, buf); + if (tb[IFLA_BOND_ACTIVE_SLAVE]) { + unsigned int ifindex = + rta_getattr_u32(tb[IFLA_BOND_ACTIVE_SLAVE]); - if (n) + if (ifindex) { print_string(PRINT_ANY, "active_slave", "active_slave %s ", - n); - else - print_uint(PRINT_ANY, - "active_slave_index", - "active_slave %u ", - ifindex); + ll_index_to_name(ifindex)); + } } if (tb[IFLA_BOND_MIIMON]) @@ -479,18 +472,15 @@ static void bond_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) arp_all_targets); } - if (tb[IFLA_BOND_PRIMARY] && - (ifindex = rta_getattr_u32(tb[IFLA_BOND_PRIMARY]))) { - char buf[IFNAMSIZ]; - const char *n = if_indextoname(ifindex, buf); + if (tb[IFLA_BOND_PRIMARY]) { + unsigned int ifindex = rta_getattr_u32(tb[IFLA_BOND_PRIMARY]); - if (n) - print_string(PRINT_ANY, "primary", "primary %s ", n); - else - print_uint(PRINT_ANY, - "primary_index", - "primary %u ", - ifindex); + if (ifindex) { + print_string(PRINT_ANY, + "primary", + "primary %s ", + ll_index_to_name(ifindex)); + } } if (tb[IFLA_BOND_PRIMARY_RESELECT]) { diff --git a/ip/iplink_vxlan.c b/ip/iplink_vxlan.c index 661eaa79..ad7ef1c0 100644 --- a/ip/iplink_vxlan.c +++ b/ip/iplink_vxlan.c @@ -394,10 +394,8 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv, static void vxlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) { __u32 vni; - unsigned int link; __u8 tos; __u32 maxaddr; - char s2[64]; if (!tb) return; @@ -467,14 +465,13 @@ static void vxlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) &addr)); } - if (tb[IFLA_VXLAN_LINK] && - (link = rta_getattr_u32(tb[IFLA_VXLAN_LINK]))) { - const char *n = if_indextoname(link, s2); + if (tb[IFLA_VXLAN_LINK]) { + unsigned int link = rta_getattr_u32(tb[IFLA_VXLAN_LINK]); - if (n) - print_string(PRINT_ANY, "link", "dev %s ", n); - else - print_uint(PRINT_ANY, "link_index", "dev %u ", link); + if (link) { + print_string(PRINT_ANY, "link", "dev %s ", + ll_index_to_name(link)); + } } if (tb[IFLA_VXLAN_PORT_RANGE]) { diff --git a/ip/iproute_lwtunnel.c b/ip/iproute_lwtunnel.c index 740da7c6..a8d71714 100644 --- a/ip/iproute_lwtunnel.c +++ b/ip/iproute_lwtunnel.c @@ -196,7 +196,6 @@ static int read_action_type(const char *name) static void print_encap_seg6local(FILE *fp, struct rtattr *encap) { struct rtattr *tb[SEG6_LOCAL_MAX + 1]; - char ifbuf[IFNAMSIZ]; int action; parse_rtattr_nested(tb, SEG6_LOCAL_MAX, encap); @@ -229,15 +228,13 @@ static void print_encap_seg6local(FILE *fp, struct rtattr *encap) if (tb[SEG6_LOCAL_IIF]) { int iif = rta_getattr_u32(tb[SEG6_LOCAL_IIF]); - fprintf(fp, "iif %s ", - if_indextoname(iif, ifbuf) ?: ""); + fprintf(fp, "iif %s ", ll_index_to_name(iif)); } if (tb[SEG6_LOCAL_OIF]) { int oif = rta_getattr_u32(tb[SEG6_LOCAL_OIF]); - fprintf(fp, "oif %s ", - if_indextoname(oif, ifbuf) ?: ""); + fprintf(fp, "oif %s ", ll_index_to_name(oif)); } } diff --git a/ip/link_gre.c b/ip/link_gre.c index 3c0b6d67..7463d7ca 100644 --- a/ip/link_gre.c +++ b/ip/link_gre.c @@ -380,14 +380,13 @@ static void gre_print_direct_opt(FILE *f, struct rtattr *tb[]) print_string(PRINT_ANY, "local", "local %s ", local); - if (tb[IFLA_GRE_LINK] && rta_getattr_u32(tb[IFLA_GRE_LINK])) { + if (tb[IFLA_GRE_LINK]) { unsigned int link = rta_getattr_u32(tb[IFLA_GRE_LINK]); - const char *n = if_indextoname(link, s2); - if (n) - print_string(PRINT_ANY, "link", "dev %s ", n); - else - print_uint(PRINT_ANY, "link_index", "dev %u ", link); + if (link) { + print_string(PRINT_ANY, "link", "dev %s ", + ll_index_to_name(link)); + } } if (tb[IFLA_GRE_TTL]) { diff --git a/ip/link_gre6.c b/ip/link_gre6.c index 55bd1fbb..7d38f47b 100644 --- a/ip/link_gre6.c +++ b/ip/link_gre6.c @@ -414,14 +414,13 @@ static void gre_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) print_string(PRINT_ANY, "local", "local %s ", local); - if (tb[IFLA_GRE_LINK] && rta_getattr_u32(tb[IFLA_GRE_LINK])) { + if (tb[IFLA_GRE_LINK]) { unsigned int link = rta_getattr_u32(tb[IFLA_GRE_LINK]); - const char *n = if_indextoname(link, s2); - if (n) - print_string(PRINT_ANY, "link", "dev %s ", n); - else - print_uint(PRINT_ANY, "link_index", "dev %u ", link); + if (link) { + print_string(PRINT_ANY, "link", "dev %s ", + ll_index_to_name(link)); + } } if (tb[IFLA_GRE_TTL]) { diff --git a/ip/link_ip6tnl.c b/ip/link_ip6tnl.c index bbc7878c..b22e7bc3 100644 --- a/ip/link_ip6tnl.c +++ b/ip/link_ip6tnl.c @@ -377,14 +377,13 @@ static void ip6tunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb rt_addr_n2a_rta(AF_INET6, tb[IFLA_IPTUN_LOCAL])); } - if (tb[IFLA_IPTUN_LINK] && rta_getattr_u32(tb[IFLA_IPTUN_LINK])) { + if (tb[IFLA_IPTUN_LINK]) { unsigned int link = rta_getattr_u32(tb[IFLA_IPTUN_LINK]); - const char *n = if_indextoname(link, s2); - if (n) - print_string(PRINT_ANY, "link", "dev %s ", n); - else - print_uint(PRINT_ANY, "link_index", "dev %u ", link); + if (link) { + print_string(PRINT_ANY, "link", "dev %s ", + ll_index_to_name(link)); + } } if (tb[IFLA_IPTUN_TTL]) { diff --git a/ip/link_iptnl.c b/ip/link_iptnl.c index 24a0f0cd..35ef5c06 100644 --- a/ip/link_iptnl.c +++ b/ip/link_iptnl.c @@ -407,14 +407,13 @@ static void iptunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[ print_string(PRINT_ANY, "local", "local %s ", local); - if (tb[IFLA_IPTUN_LINK] && rta_getattr_u32(tb[IFLA_IPTUN_LINK])) { + if (tb[IFLA_IPTUN_LINK]) { unsigned int link = rta_getattr_u32(tb[IFLA_IPTUN_LINK]); - const char *n = if_indextoname(link, s2); - if (n) - print_string(PRINT_ANY, "link", "dev %s ", n); - else - print_int(PRINT_ANY, "link_index", "dev %u ", link); + if (link) { + print_string(PRINT_ANY, "link", "dev %s ", + ll_index_to_name(link)); + } } if (tb[IFLA_IPTUN_TTL]) { diff --git a/ip/link_vti.c b/ip/link_vti.c index 2b0fab27..554cfcc4 100644 --- a/ip/link_vti.c +++ b/ip/link_vti.c @@ -168,7 +168,6 @@ static void vti_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) const char *local = "any"; const char *remote = "any"; __u32 key; - unsigned int link; char s2[IFNAMSIZ]; if (!tb) @@ -192,14 +191,13 @@ static void vti_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) print_string(PRINT_ANY, "local", "local %s ", local); - if (tb[IFLA_VTI_LINK] && - (link = rta_getattr_u32(tb[IFLA_VTI_LINK]))) { - const char *n = if_indextoname(link, s2); + if (tb[IFLA_VTI_LINK]) { + unsigned int link = rta_getattr_u32(tb[IFLA_VTI_LINK]); - if (n) - print_string(PRINT_ANY, "link", "dev %s ", n); - else - print_uint(PRINT_ANY, "link_index", "dev %u ", link); + if (link) { + print_string(PRINT_ANY, "link", "dev %s ", + ll_index_to_name(link)); + } } if (tb[IFLA_VTI_IKEY] && diff --git a/ip/link_vti6.c b/ip/link_vti6.c index 74c246d3..a63f49fa 100644 --- a/ip/link_vti6.c +++ b/ip/link_vti6.c @@ -168,7 +168,6 @@ static void vti6_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) const char *remote = "any"; struct in6_addr saddr; struct in6_addr daddr; - unsigned int link; char s2[64]; if (!tb) @@ -190,13 +189,13 @@ static void vti6_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) print_string(PRINT_ANY, "local", "local %s ", local); - if (tb[IFLA_VTI_LINK] && (link = rta_getattr_u32(tb[IFLA_VTI_LINK]))) { - const char *n = if_indextoname(link, s2); + if (tb[IFLA_VTI_LINK]) { + unsigned int link = rta_getattr_u32(tb[IFLA_VTI_LINK]); - if (n) - print_string(PRINT_ANY, "link", "dev %s ", n); - else - print_uint(PRINT_ANY, "link_index", "dev %u ", link); + if (link) { + print_string(PRINT_ANY, "link", "dev %s ", + ll_index_to_name(link)); + } } if (tb[IFLA_VTI_IKEY]) { From 375560c4ab61cae567afbb9a64036a009cfeaecc Mon Sep 17 00:00:00 2001 From: Serhey Popovych Date: Thu, 18 Jan 2018 16:04:29 +0200 Subject: [PATCH 27/34] ip/tunnel: Correct and unify ttl/hoplimit printing Both ttl/hoplimit is from 1 to 255. Zero has special meaning: use encapsulated packet value. In ip-link(8) -d output this looks like "ttl/hoplimit inherit". In JSON we have "int" type for ttl and therefore values from 0 (inherit) to 255. To do the best in handling ttl/hoplimit we need to accept both cases: missing attribute in netlink dump and zero value for "inherit"ed case. Last one is broken since JSON output introduction for gre/iptnl versions and was never true for gre6/ip6tnl. For all tunnels, except ip6tnl change JSON type from "int" to "uint" to reflect true nature of the ttl. Signed-off-by: Serhey Popovych Signed-off-by: Stephen Hemminger --- ip/ip6tunnel.c | 5 ++++- ip/iplink_geneve.c | 13 +++++++------ ip/iplink_vxlan.c | 15 +++++++-------- ip/iproute_lwtunnel.c | 4 ++-- ip/iptunnel.c | 2 +- ip/link_gre.c | 15 ++++++--------- ip/link_gre6.c | 15 +++++++-------- ip/link_ip6tnl.c | 13 +++++++------ ip/link_iptnl.c | 15 ++++++--------- 9 files changed, 47 insertions(+), 50 deletions(-) diff --git a/ip/ip6tunnel.c b/ip/ip6tunnel.c index b8db49c9..783e28a6 100644 --- a/ip/ip6tunnel.c +++ b/ip/ip6tunnel.c @@ -92,7 +92,10 @@ static void print_tunnel(struct ip6_tnl_parm2 *p) else printf(" encaplimit %u", p->encap_limit); - printf(" hoplimit %u", p->hop_limit); + if (p->hop_limit) + printf(" hoplimit %u", p->hop_limit); + else + printf(" hoplimit inherit"); if (p->flags & IP6_TNL_F_USE_ORIG_TCLASS) printf(" tclass inherit"); diff --git a/ip/iplink_geneve.c b/ip/iplink_geneve.c index f0f1d1c7..5a0afd4e 100644 --- a/ip/iplink_geneve.c +++ b/ip/iplink_geneve.c @@ -227,6 +227,7 @@ static int geneve_parse_opt(struct link_util *lu, int argc, char **argv, static void geneve_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) { __u32 vni; + __u8 ttl = 0; __u8 tos; if (!tb) @@ -262,12 +263,12 @@ static void geneve_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) } } - if (tb[IFLA_GENEVE_TTL]) { - __u8 ttl = rta_getattr_u8(tb[IFLA_GENEVE_TTL]); - - if (ttl) - print_int(PRINT_ANY, "ttl", "ttl %d ", ttl); - } + if (tb[IFLA_GENEVE_TTL]) + ttl = rta_getattr_u8(tb[IFLA_GENEVE_TTL]); + if (is_json_context() || ttl) + print_uint(PRINT_ANY, "ttl", "ttl %u ", ttl); + else + print_string(PRINT_FP, NULL, "ttl %s ", "inherit"); if (tb[IFLA_GENEVE_TOS] && (tos = rta_getattr_u8(tb[IFLA_GENEVE_TOS]))) { diff --git a/ip/iplink_vxlan.c b/ip/iplink_vxlan.c index ad7ef1c0..b9c335d3 100644 --- a/ip/iplink_vxlan.c +++ b/ip/iplink_vxlan.c @@ -394,6 +394,7 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv, static void vxlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) { __u32 vni; + __u8 ttl = 0; __u8 tos; __u32 maxaddr; @@ -526,14 +527,12 @@ static void vxlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) } } - if (tb[IFLA_VXLAN_TTL]) { - __u8 ttl = rta_getattr_u8(tb[IFLA_VXLAN_TTL]); - - if (ttl) - print_int(PRINT_ANY, "ttl", "ttl %d ", ttl); - else - print_int(PRINT_JSON, "ttl", NULL, ttl); - } + if (tb[IFLA_VXLAN_TTL]) + ttl = rta_getattr_u8(tb[IFLA_VXLAN_TTL]); + if (is_json_context() || ttl) + print_uint(PRINT_ANY, "ttl", "ttl %u ", ttl); + else + print_string(PRINT_FP, NULL, "ttl %s ", "inherit"); if (tb[IFLA_VXLAN_LABEL]) { __u32 label = rta_getattr_u32(tb[IFLA_VXLAN_LABEL]); diff --git a/ip/iproute_lwtunnel.c b/ip/iproute_lwtunnel.c index a8d71714..a1d36ba2 100644 --- a/ip/iproute_lwtunnel.c +++ b/ip/iproute_lwtunnel.c @@ -271,7 +271,7 @@ static void print_encap_ip(FILE *fp, struct rtattr *encap) rt_addr_n2a_rta(AF_INET, tb[LWTUNNEL_IP_DST])); if (tb[LWTUNNEL_IP_TTL]) - fprintf(fp, "ttl %d ", rta_getattr_u8(tb[LWTUNNEL_IP_TTL])); + fprintf(fp, "ttl %u ", rta_getattr_u8(tb[LWTUNNEL_IP_TTL])); if (tb[LWTUNNEL_IP_TOS]) fprintf(fp, "tos %d ", rta_getattr_u8(tb[LWTUNNEL_IP_TOS])); @@ -326,7 +326,7 @@ static void print_encap_ip6(FILE *fp, struct rtattr *encap) rt_addr_n2a_rta(AF_INET6, tb[LWTUNNEL_IP6_DST])); if (tb[LWTUNNEL_IP6_HOPLIMIT]) - fprintf(fp, "hoplimit %d ", + fprintf(fp, "hoplimit %u ", rta_getattr_u8(tb[LWTUNNEL_IP6_HOPLIMIT])); if (tb[LWTUNNEL_IP6_TC]) diff --git a/ip/iptunnel.c b/ip/iptunnel.c index ce610f84..0aa3b332 100644 --- a/ip/iptunnel.c +++ b/ip/iptunnel.c @@ -326,7 +326,7 @@ static void print_tunnel(struct ip_tunnel_parm *p) } if (p->iph.ttl) - printf(" ttl %d", p->iph.ttl); + printf(" ttl %u", p->iph.ttl); else printf(" ttl inherit"); diff --git a/ip/link_gre.c b/ip/link_gre.c index 7463d7ca..1cf7f4e8 100644 --- a/ip/link_gre.c +++ b/ip/link_gre.c @@ -361,6 +361,7 @@ static void gre_print_direct_opt(FILE *f, struct rtattr *tb[]) const char *remote = "any"; unsigned int iflags = 0; unsigned int oflags = 0; + __u8 ttl = 0; if (tb[IFLA_GRE_REMOTE]) { unsigned int addr = rta_getattr_u32(tb[IFLA_GRE_REMOTE]); @@ -389,16 +390,12 @@ static void gre_print_direct_opt(FILE *f, struct rtattr *tb[]) } } - if (tb[IFLA_GRE_TTL]) { - __u8 ttl = rta_getattr_u8(tb[IFLA_GRE_TTL]); - - if (ttl) - print_int(PRINT_ANY, "ttl", "ttl %d ", ttl); - else - print_int(PRINT_JSON, "ttl", NULL, ttl); - } else { + if (tb[IFLA_GRE_TTL]) + ttl = rta_getattr_u8(tb[IFLA_GRE_TTL]); + if (is_json_context() || ttl) + print_uint(PRINT_ANY, "ttl", "ttl %u ", ttl); + else print_string(PRINT_FP, NULL, "ttl %s ", "inherit"); - } if (tb[IFLA_GRE_TOS] && rta_getattr_u8(tb[IFLA_GRE_TOS])) { int tos = rta_getattr_u8(tb[IFLA_GRE_TOS]); diff --git a/ip/link_gre6.c b/ip/link_gre6.c index 7d38f47b..37bc5444 100644 --- a/ip/link_gre6.c +++ b/ip/link_gre6.c @@ -382,6 +382,7 @@ static void gre_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) unsigned int flags = 0; __u32 flowinfo = 0; struct in6_addr in6_addr_any = IN6ADDR_ANY_INIT; + __u8 ttl = 0; if (!tb) return; @@ -423,14 +424,12 @@ static void gre_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) } } - if (tb[IFLA_GRE_TTL]) { - __u8 ttl = rta_getattr_u8(tb[IFLA_GRE_TTL]); - - if (ttl) - print_int(PRINT_ANY, "ttl", "hoplimit %d ", ttl); - else - print_int(PRINT_JSON, "ttl", NULL, ttl); - } + if (tb[IFLA_GRE_TTL]) + ttl = rta_getattr_u8(tb[IFLA_GRE_TTL]); + if (is_json_context() || ttl) + print_uint(PRINT_ANY, "ttl", "hoplimit %u ", ttl); + else + print_string(PRINT_FP, NULL, "hoplimit %s ", "inherit"); if (flags & IP6_TNL_F_IGN_ENCAP_LIMIT) { print_bool(PRINT_ANY, diff --git a/ip/link_ip6tnl.c b/ip/link_ip6tnl.c index b22e7bc3..605bc614 100644 --- a/ip/link_ip6tnl.c +++ b/ip/link_ip6tnl.c @@ -336,6 +336,7 @@ static void ip6tunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb char s2[64]; int flags = 0; __u32 flowinfo = 0; + __u8 ttl = 0; if (!tb) return; @@ -386,12 +387,12 @@ static void ip6tunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb } } - if (tb[IFLA_IPTUN_TTL]) { - print_uint(PRINT_ANY, - "ttl", - "hoplimit %u ", - rta_getattr_u8(tb[IFLA_IPTUN_TTL])); - } + if (tb[IFLA_IPTUN_TTL]) + ttl = rta_getattr_u8(tb[IFLA_IPTUN_TTL]); + if (is_json_context() || ttl) + print_uint(PRINT_ANY, "ttl", "hoplimit %u ", ttl); + else + print_string(PRINT_FP, NULL, "hoplimit %s ", "inherit"); if (flags & IP6_TNL_F_IGN_ENCAP_LIMIT) { print_bool(PRINT_ANY, diff --git a/ip/link_iptnl.c b/ip/link_iptnl.c index 35ef5c06..93e1a1bc 100644 --- a/ip/link_iptnl.c +++ b/ip/link_iptnl.c @@ -365,6 +365,7 @@ static void iptunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[ const char *local = "any"; const char *remote = "any"; __u16 prefixlen, type; + __u8 ttl = 0; if (!tb) return; @@ -416,16 +417,12 @@ static void iptunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[ } } - if (tb[IFLA_IPTUN_TTL]) { - __u8 ttl = rta_getattr_u8(tb[IFLA_IPTUN_TTL]); - - if (ttl) - print_int(PRINT_ANY, "ttl", "ttl %d ", ttl); - else - print_int(PRINT_JSON, "ttl", NULL, ttl); - } else { + if (tb[IFLA_IPTUN_TTL]) + ttl = rta_getattr_u8(tb[IFLA_IPTUN_TTL]); + if (is_json_context() || ttl) + print_uint(PRINT_ANY, "ttl", "ttl %u ", ttl); + else print_string(PRINT_FP, NULL, "ttl %s ", "inherit"); - } if (tb[IFLA_IPTUN_TOS]) { int tos = rta_getattr_u8(tb[IFLA_IPTUN_TOS]); From 3caa526c7b2b0a41b04b4c8278374df0e81e2ad0 Mon Sep 17 00:00:00 2001 From: Serhey Popovych Date: Thu, 18 Jan 2018 16:04:30 +0200 Subject: [PATCH 28/34] ip/tunnel: Simplify and unify tos printing For ip tunnels tos can be 0 when not configured, 1 when inherited from encapsulated packet and rest specifying diffserv (rfc2474) or tos (rfc1349) bits. It is stored in packet tos/diffserv field and returned in tos netlink attribute to userspace. Simplify and unify tos printing by using print_0xhex() and print_string() instead of fprintf() to output values. Signed-off-by: Serhey Popovych Signed-off-by: Stephen Hemminger --- ip/iplink_geneve.c | 23 ++++++++--------------- ip/iplink_vxlan.c | 19 ++++++++----------- ip/link_gre.c | 23 ++++++++--------------- ip/link_iptnl.c | 22 ++++++++-------------- 4 files changed, 32 insertions(+), 55 deletions(-) diff --git a/ip/iplink_geneve.c b/ip/iplink_geneve.c index 5a0afd4e..2d0a0411 100644 --- a/ip/iplink_geneve.c +++ b/ip/iplink_geneve.c @@ -228,7 +228,7 @@ static void geneve_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) { __u32 vni; __u8 ttl = 0; - __u8 tos; + __u8 tos = 0; if (!tb) return; @@ -270,20 +270,13 @@ static void geneve_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) else print_string(PRINT_FP, NULL, "ttl %s ", "inherit"); - if (tb[IFLA_GENEVE_TOS] && - (tos = rta_getattr_u8(tb[IFLA_GENEVE_TOS]))) { - if (is_json_context()) { - print_0xhex(PRINT_JSON, "tos", "%#x", tos); - } else { - if (tos == 1) { - print_string(PRINT_FP, - "tos", - "tos %s ", - "inherit"); - } else { - fprintf(f, "tos %#x ", tos); - } - } + if (tb[IFLA_GENEVE_TOS]) + tos = rta_getattr_u8(tb[IFLA_GENEVE_TOS]); + if (tos) { + if (is_json_context() || tos != 1) + print_0xhex(PRINT_ANY, "tos", "tos 0x%x ", tos); + else + print_string(PRINT_FP, NULL, "tos %s ", "inherit"); } if (tb[IFLA_GENEVE_LABEL]) { diff --git a/ip/iplink_vxlan.c b/ip/iplink_vxlan.c index b9c335d3..88b56625 100644 --- a/ip/iplink_vxlan.c +++ b/ip/iplink_vxlan.c @@ -395,7 +395,7 @@ static void vxlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) { __u32 vni; __u8 ttl = 0; - __u8 tos; + __u8 tos = 0; __u32 maxaddr; if (!tb) @@ -515,16 +515,13 @@ static void vxlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) if (tb[IFLA_VXLAN_L3MISS] && rta_getattr_u8(tb[IFLA_VXLAN_L3MISS])) print_bool(PRINT_ANY, "l3miss", "l3miss ", true); - if (tb[IFLA_VXLAN_TOS] && - (tos = rta_getattr_u8(tb[IFLA_VXLAN_TOS]))) { - if (is_json_context()) { - print_0xhex(PRINT_JSON, "tos", "%#x", tos); - } else { - if (tos == 1) - fprintf(f, "tos %s ", "inherit"); - else - fprintf(f, "tos %#x ", tos); - } + if (tb[IFLA_VXLAN_TOS]) + tos = rta_getattr_u8(tb[IFLA_VXLAN_TOS]); + if (tos) { + if (is_json_context() || tos != 1) + print_0xhex(PRINT_ANY, "tos", "tos 0x%x ", tos); + else + print_string(PRINT_FP, NULL, "tos %s ", "inherit"); } if (tb[IFLA_VXLAN_TTL]) diff --git a/ip/link_gre.c b/ip/link_gre.c index 1cf7f4e8..490d7db8 100644 --- a/ip/link_gre.c +++ b/ip/link_gre.c @@ -362,6 +362,7 @@ static void gre_print_direct_opt(FILE *f, struct rtattr *tb[]) unsigned int iflags = 0; unsigned int oflags = 0; __u8 ttl = 0; + __u8 tos = 0; if (tb[IFLA_GRE_REMOTE]) { unsigned int addr = rta_getattr_u32(tb[IFLA_GRE_REMOTE]); @@ -397,21 +398,13 @@ static void gre_print_direct_opt(FILE *f, struct rtattr *tb[]) else print_string(PRINT_FP, NULL, "ttl %s ", "inherit"); - if (tb[IFLA_GRE_TOS] && rta_getattr_u8(tb[IFLA_GRE_TOS])) { - int tos = rta_getattr_u8(tb[IFLA_GRE_TOS]); - - if (is_json_context()) { - SPRINT_BUF(b1); - - snprintf(b1, sizeof(b1), "0x%x", tos); - print_string(PRINT_JSON, "tos", NULL, b1); - } else { - fputs("tos ", f); - if (tos == 1) - fputs("inherit ", f); - else - fprintf(f, "0x%x ", tos); - } + if (tb[IFLA_GRE_TOS]) + tos = rta_getattr_u8(tb[IFLA_GRE_TOS]); + if (tos) { + if (is_json_context() || tos != 1) + print_0xhex(PRINT_ANY, "tos", "tos 0x%x ", tos); + else + print_string(PRINT_FP, NULL, "tos %s ", "inherit"); } if (tb[IFLA_GRE_PMTUDISC]) { diff --git a/ip/link_iptnl.c b/ip/link_iptnl.c index 93e1a1bc..7fda580f 100644 --- a/ip/link_iptnl.c +++ b/ip/link_iptnl.c @@ -366,6 +366,7 @@ static void iptunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[ const char *remote = "any"; __u16 prefixlen, type; __u8 ttl = 0; + __u8 tos = 0; if (!tb) return; @@ -424,20 +425,13 @@ static void iptunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[ else print_string(PRINT_FP, NULL, "ttl %s ", "inherit"); - if (tb[IFLA_IPTUN_TOS]) { - int tos = rta_getattr_u8(tb[IFLA_IPTUN_TOS]); - - if (tos) { - if (is_json_context()) { - print_0xhex(PRINT_JSON, "tos", "%#x", tos); - } else { - fputs("tos ", f); - if (tos == 1) - fputs("inherit ", f); - else - fprintf(f, "0x%x ", tos); - } - } + if (tb[IFLA_IPTUN_TOS]) + tos = rta_getattr_u8(tb[IFLA_IPTUN_TOS]); + if (tos) { + if (is_json_context() || tos != 1) + print_0xhex(PRINT_ANY, "tos", "tos 0x%x ", tos); + else + print_string(PRINT_FP, NULL, "tos %s ", "inherit"); } if (tb[IFLA_IPTUN_PMTUDISC] && rta_getattr_u8(tb[IFLA_IPTUN_PMTUDISC])) From e97ad3d2483cf417a5ccf8b2e3b106b03bb5547d Mon Sep 17 00:00:00 2001 From: Serhey Popovych Date: Thu, 18 Jan 2018 16:04:31 +0200 Subject: [PATCH 29/34] ip/tunnel: Use print_0xhex() instead of print_string() No need for custom SPRINT_BUF() and snprintf() 0x%x value to this buffer: we can use print_0xhex() instead of print_string(). In link_iptnl.c use s2 instead of s1 buffer and remove s1. While there adjust fwmark option print order in iptnl and ip6tnl to get it match each other. Signed-off-by: Serhey Popovych Signed-off-by: Stephen Hemminger --- ip/link_gre.c | 5 ++--- ip/link_gre6.c | 9 ++++----- ip/link_ip6tnl.c | 18 ++++++++---------- ip/link_iptnl.c | 22 ++++++++++------------ ip/link_vti.c | 6 ++---- ip/link_vti6.c | 5 ++--- 6 files changed, 28 insertions(+), 37 deletions(-) diff --git a/ip/link_gre.c b/ip/link_gre.c index 490d7db8..2462828e 100644 --- a/ip/link_gre.c +++ b/ip/link_gre.c @@ -443,9 +443,8 @@ static void gre_print_direct_opt(FILE *f, struct rtattr *tb[]) __u32 fwmark = rta_getattr_u32(tb[IFLA_GRE_FWMARK]); if (fwmark) { - snprintf(s2, sizeof(s2), "0x%x", fwmark); - - print_string(PRINT_ANY, "fwmark", "fwmark %s ", s2); + print_0xhex(PRINT_ANY, + "fwmark", "fwmark 0x%x ", fwmark); } } } diff --git a/ip/link_gre6.c b/ip/link_gre6.c index 37bc5444..7dcd70de 100644 --- a/ip/link_gre6.c +++ b/ip/link_gre6.c @@ -497,18 +497,17 @@ static void gre_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) if (oflags & GRE_CSUM) print_bool(PRINT_ANY, "ocsum", "ocsum ", true); - if (flags & IP6_TNL_F_USE_ORIG_FWMARK) + if (flags & IP6_TNL_F_USE_ORIG_FWMARK) { print_bool(PRINT_ANY, "ip6_tnl_f_use_orig_fwmark", "fwmark inherit ", true); - else if (tb[IFLA_GRE_FWMARK]) { + } else if (tb[IFLA_GRE_FWMARK]) { __u32 fwmark = rta_getattr_u32(tb[IFLA_GRE_FWMARK]); if (fwmark) { - snprintf(s2, sizeof(s2), "0x%x", fwmark); - - print_string(PRINT_ANY, "fwmark", "fwmark %s ", s2); + print_0xhex(PRINT_ANY, + "fwmark", "fwmark 0x%x ", fwmark); } } diff --git a/ip/link_ip6tnl.c b/ip/link_ip6tnl.c index 605bc614..00bf00a3 100644 --- a/ip/link_ip6tnl.c +++ b/ip/link_ip6tnl.c @@ -438,6 +438,12 @@ static void ip6tunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb if (flags & IP6_TNL_F_MIP6_DEV) print_bool(PRINT_ANY, "ip6_tnl_f_mip6_dev", "mip6 ", true); + if (flags & IP6_TNL_F_ALLOW_LOCAL_REMOTE) + print_bool(PRINT_ANY, + "ip6_tnl_f_allow_local_remote", + "allow-localremote ", + true); + if (flags & IP6_TNL_F_USE_ORIG_FWMARK) { print_bool(PRINT_ANY, "ip6_tnl_f_use_orig_fwmark", @@ -447,19 +453,11 @@ static void ip6tunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb __u32 fwmark = rta_getattr_u32(tb[IFLA_IPTUN_FWMARK]); if (fwmark) { - SPRINT_BUF(b1); - - snprintf(b1, sizeof(b1), "0x%x", fwmark); - print_string(PRINT_ANY, "fwmark", "fwmark %s ", b1); + print_0xhex(PRINT_ANY, + "fwmark", "fwmark 0x%x ", fwmark); } } - if (flags & IP6_TNL_F_ALLOW_LOCAL_REMOTE) - print_bool(PRINT_ANY, - "ip6_tnl_f_allow_local_remote", - "allow-localremote ", - true); - if (tb[IFLA_IPTUN_ENCAP_TYPE] && rta_getattr_u16(tb[IFLA_IPTUN_ENCAP_TYPE]) != TUNNEL_ENCAP_NONE) { __u16 type = rta_getattr_u16(tb[IFLA_IPTUN_ENCAP_TYPE]); diff --git a/ip/link_iptnl.c b/ip/link_iptnl.c index 7fda580f..00a8366c 100644 --- a/ip/link_iptnl.c +++ b/ip/link_iptnl.c @@ -360,7 +360,6 @@ get_failed: static void iptunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) { - char s1[1024]; char s2[64]; const char *local = "any"; const char *remote = "any"; @@ -455,7 +454,7 @@ static void iptunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[ const char *prefix = inet_ntop(AF_INET6, RTA_DATA(tb[IFLA_IPTUN_6RD_PREFIX]), - s1, sizeof(s1)); + s2, sizeof(s2)); if (is_json_context()) { print_string(PRINT_JSON, "prefix", NULL, prefix); @@ -482,6 +481,15 @@ static void iptunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[ } } + if (tb[IFLA_IPTUN_FWMARK]) { + __u32 fwmark = rta_getattr_u32(tb[IFLA_IPTUN_FWMARK]); + + if (fwmark) { + print_0xhex(PRINT_ANY, + "fwmark", "fwmark 0x%x ", fwmark); + } + } + if (tb[IFLA_IPTUN_ENCAP_TYPE] && (type = rta_getattr_u16(tb[IFLA_IPTUN_ENCAP_TYPE])) != TUNNEL_ENCAP_NONE) { __u16 flags = rta_getattr_u16(tb[IFLA_IPTUN_ENCAP_FLAGS]); @@ -545,16 +553,6 @@ static void iptunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[ fputs("noencap-remcsum ", f); } } - - if (tb[IFLA_IPTUN_FWMARK]) { - __u32 fwmark = rta_getattr_u32(tb[IFLA_IPTUN_FWMARK]); - - if (fwmark) { - snprintf(s2, sizeof(s2), "0x%x", fwmark); - - print_string(PRINT_ANY, "fwmark", "fwmark %s ", s2); - } - } } static void iptunnel_print_help(struct link_util *lu, int argc, char **argv, diff --git a/ip/link_vti.c b/ip/link_vti.c index 554cfcc4..baaaf2f2 100644 --- a/ip/link_vti.c +++ b/ip/link_vti.c @@ -213,10 +213,8 @@ static void vti_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) __u32 fwmark = rta_getattr_u32(tb[IFLA_VTI_FWMARK]); if (fwmark) { - SPRINT_BUF(b1); - - snprintf(b1, sizeof(b1), "0x%x", fwmark); - print_string(PRINT_ANY, "fwmark", "fwmark %s ", s2); + print_0xhex(PRINT_ANY, + "fwmark", "fwmark 0x%x ", fwmark); } } } diff --git a/ip/link_vti6.c b/ip/link_vti6.c index a63f49fa..952dbb08 100644 --- a/ip/link_vti6.c +++ b/ip/link_vti6.c @@ -212,9 +212,8 @@ static void vti6_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) __u32 fwmark = rta_getattr_u32(tb[IFLA_VTI_FWMARK]); if (fwmark) { - snprintf(s2, sizeof(s2), "0x%x", fwmark); - - print_string(PRINT_ANY, "fwmark", "fwmark %s ", s2); + print_0xhex(PRINT_ANY, + "fwmark", "fwmark 0x%x ", fwmark); } } } From bad76e6b1f4475caac9f529236c6dbce53e4a18e Mon Sep 17 00:00:00 2001 From: Serhey Popovych Date: Thu, 18 Jan 2018 16:04:32 +0200 Subject: [PATCH 30/34] ip/tunnel: Abstract tunnel encapsulation options printing Get rid of code duplications and consolidate encapsulation options printing in single function - tnl_print_encap(). Introduce and use tnl_encap_str() to format encapsulation option string according to tempate and given values to avoid code duplication and simplify it. Use print_string() instead of fputs() and fprintf() to print encapsulation for !is_json_context(). Print "unknown" parameter for "encap" type in PRINT_FP context using "%s " format specifier and benefit from complite time string merge. Signed-off-by: Serhey Popovych Signed-off-by: Stephen Hemminger --- ip/link_gre.c | 75 +++------------------------------------ ip/link_gre6.c | 64 +++------------------------------- ip/link_ip6tnl.c | 63 +++------------------------------ ip/link_iptnl.c | 70 ++++--------------------------------- ip/tunnel.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++++ ip/tunnel.h | 5 +++ 6 files changed, 117 insertions(+), 251 deletions(-) diff --git a/ip/link_gre.c b/ip/link_gre.c index 2462828e..d403d24a 100644 --- a/ip/link_gre.c +++ b/ip/link_gre.c @@ -468,76 +468,11 @@ static void gre_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) fprintf(f, "erspan_index %u ", erspan_idx); } - if (tb[IFLA_GRE_ENCAP_TYPE] && - rta_getattr_u16(tb[IFLA_GRE_ENCAP_TYPE]) != TUNNEL_ENCAP_NONE) { - __u16 type = rta_getattr_u16(tb[IFLA_GRE_ENCAP_TYPE]); - __u16 flags = rta_getattr_u16(tb[IFLA_GRE_ENCAP_FLAGS]); - __u16 sport = rta_getattr_u16(tb[IFLA_GRE_ENCAP_SPORT]); - __u16 dport = rta_getattr_u16(tb[IFLA_GRE_ENCAP_DPORT]); - - - open_json_object("encap"); - print_string(PRINT_FP, NULL, "encap ", NULL); - - switch (type) { - case TUNNEL_ENCAP_FOU: - print_string(PRINT_ANY, "type", "%s ", "fou"); - break; - case TUNNEL_ENCAP_GUE: - print_string(PRINT_ANY, "type", "%s ", "gue"); - break; - default: - print_null(PRINT_ANY, "type", "%s ", "unknown"); - break; - } - - if (is_json_context()) { - print_uint(PRINT_JSON, - "sport", - NULL, - sport ? ntohs(sport) : 0); - print_uint(PRINT_JSON, "dport", NULL, ntohs(dport)); - - print_bool(PRINT_JSON, - "csum", - NULL, - flags & TUNNEL_ENCAP_FLAG_CSUM); - - print_bool(PRINT_JSON, - "csum6", - NULL, - flags & TUNNEL_ENCAP_FLAG_CSUM6); - - print_bool(PRINT_JSON, - "remcsum", - NULL, - flags & TUNNEL_ENCAP_FLAG_REMCSUM); - - close_json_object(); - } else { - if (sport == 0) - fputs("encap-sport auto ", f); - else - fprintf(f, "encap-sport %u", ntohs(sport)); - - fprintf(f, "encap-dport %u ", ntohs(dport)); - - if (flags & TUNNEL_ENCAP_FLAG_CSUM) - fputs("encap-csum ", f); - else - fputs("noencap-csum ", f); - - if (flags & TUNNEL_ENCAP_FLAG_CSUM6) - fputs("encap-csum6 ", f); - else - fputs("noencap-csum6 ", f); - - if (flags & TUNNEL_ENCAP_FLAG_REMCSUM) - fputs("encap-remcsum ", f); - else - fputs("noencap-remcsum ", f); - } - } + tnl_print_encap(tb, + IFLA_GRE_ENCAP_TYPE, + IFLA_GRE_ENCAP_FLAGS, + IFLA_GRE_ENCAP_SPORT, + IFLA_GRE_ENCAP_DPORT); } static void gre_print_help(struct link_util *lu, int argc, char **argv, diff --git a/ip/link_gre6.c b/ip/link_gre6.c index 7dcd70de..a159b542 100644 --- a/ip/link_gre6.c +++ b/ip/link_gre6.c @@ -516,65 +516,11 @@ static void gre_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) fprintf(f, "erspan_index %u ", erspan_idx); } - if (tb[IFLA_GRE_ENCAP_TYPE] && - rta_getattr_u16(tb[IFLA_GRE_ENCAP_TYPE]) != TUNNEL_ENCAP_NONE) { - __u16 type = rta_getattr_u16(tb[IFLA_GRE_ENCAP_TYPE]); - __u16 flags = rta_getattr_u16(tb[IFLA_GRE_ENCAP_FLAGS]); - __u16 sport = rta_getattr_u16(tb[IFLA_GRE_ENCAP_SPORT]); - __u16 dport = rta_getattr_u16(tb[IFLA_GRE_ENCAP_DPORT]); - - open_json_object("encap"); - - print_string(PRINT_FP, NULL, "encap ", NULL); - switch (type) { - case TUNNEL_ENCAP_FOU: - print_string(PRINT_ANY, "type", "%s ", "fou"); - break; - case TUNNEL_ENCAP_GUE: - print_string(PRINT_ANY, "type", "%s ", "gue"); - break; - default: - print_null(PRINT_ANY, "type", "unknown ", NULL); - break; - } - - if (is_json_context()) { - print_uint(PRINT_JSON, - "sport", - NULL, - sport ? ntohs(sport) : 0); - print_uint(PRINT_JSON, "dport", NULL, ntohs(dport)); - print_bool(PRINT_JSON, "csum", NULL, - flags & TUNNEL_ENCAP_FLAG_CSUM); - print_bool(PRINT_JSON, "csum6", NULL, - flags & TUNNEL_ENCAP_FLAG_CSUM6); - print_bool(PRINT_JSON, "remcsum", NULL, - flags & TUNNEL_ENCAP_FLAG_REMCSUM); - close_json_object(); - } else { - if (sport == 0) - fputs("encap-sport auto ", f); - else - fprintf(f, "encap-sport %u", ntohs(sport)); - - fprintf(f, "encap-dport %u ", ntohs(dport)); - - if (flags & TUNNEL_ENCAP_FLAG_CSUM) - fputs("encap-csum ", f); - else - fputs("noencap-csum ", f); - - if (flags & TUNNEL_ENCAP_FLAG_CSUM6) - fputs("encap-csum6 ", f); - else - fputs("noencap-csum6 ", f); - - if (flags & TUNNEL_ENCAP_FLAG_REMCSUM) - fputs("encap-remcsum ", f); - else - fputs("noencap-remcsum ", f); - } - } + tnl_print_encap(tb, + IFLA_GRE_ENCAP_TYPE, + IFLA_GRE_ENCAP_FLAGS, + IFLA_GRE_ENCAP_SPORT, + IFLA_GRE_ENCAP_DPORT); } static void gre_print_help(struct link_util *lu, int argc, char **argv, diff --git a/ip/link_ip6tnl.c b/ip/link_ip6tnl.c index 00bf00a3..8f5c9bd7 100644 --- a/ip/link_ip6tnl.c +++ b/ip/link_ip6tnl.c @@ -458,64 +458,11 @@ static void ip6tunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb } } - if (tb[IFLA_IPTUN_ENCAP_TYPE] && - rta_getattr_u16(tb[IFLA_IPTUN_ENCAP_TYPE]) != TUNNEL_ENCAP_NONE) { - __u16 type = rta_getattr_u16(tb[IFLA_IPTUN_ENCAP_TYPE]); - __u16 flags = rta_getattr_u16(tb[IFLA_IPTUN_ENCAP_FLAGS]); - __u16 sport = rta_getattr_u16(tb[IFLA_IPTUN_ENCAP_SPORT]); - __u16 dport = rta_getattr_u16(tb[IFLA_IPTUN_ENCAP_DPORT]); - - open_json_object("encap"); - print_string(PRINT_FP, NULL, "encap ", NULL); - switch (type) { - case TUNNEL_ENCAP_FOU: - print_string(PRINT_ANY, "type", "%s ", "fou"); - break; - case TUNNEL_ENCAP_GUE: - print_string(PRINT_ANY, "type", "%s ", "gue"); - break; - default: - print_null(PRINT_ANY, "type", "unknown ", NULL); - break; - } - - if (is_json_context()) { - print_uint(PRINT_JSON, - "sport", - NULL, - sport ? ntohs(sport) : 0); - print_uint(PRINT_JSON, "dport", NULL, ntohs(dport)); - print_bool(PRINT_JSON, "csum", NULL, - flags & TUNNEL_ENCAP_FLAG_CSUM); - print_bool(PRINT_JSON, "csum6", NULL, - flags & TUNNEL_ENCAP_FLAG_CSUM6); - print_bool(PRINT_JSON, "remcsum", NULL, - flags & TUNNEL_ENCAP_FLAG_REMCSUM); - close_json_object(); - } else { - if (sport == 0) - fputs("encap-sport auto ", f); - else - fprintf(f, "encap-sport %u", ntohs(sport)); - - fprintf(f, "encap-dport %u ", ntohs(dport)); - - if (flags & TUNNEL_ENCAP_FLAG_CSUM) - fputs("encap-csum ", f); - else - fputs("noencap-csum ", f); - - if (flags & TUNNEL_ENCAP_FLAG_CSUM6) - fputs("encap-csum6 ", f); - else - fputs("noencap-csum6 ", f); - - if (flags & TUNNEL_ENCAP_FLAG_REMCSUM) - fputs("encap-remcsum ", f); - else - fputs("noencap-remcsum ", f); - } - } + tnl_print_encap(tb, + IFLA_IPTUN_ENCAP_TYPE, + IFLA_IPTUN_ENCAP_FLAGS, + IFLA_IPTUN_ENCAP_SPORT, + IFLA_IPTUN_ENCAP_DPORT); } static void ip6tunnel_print_help(struct link_util *lu, int argc, char **argv, diff --git a/ip/link_iptnl.c b/ip/link_iptnl.c index 00a8366c..ce3855c1 100644 --- a/ip/link_iptnl.c +++ b/ip/link_iptnl.c @@ -363,7 +363,7 @@ static void iptunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[ char s2[64]; const char *local = "any"; const char *remote = "any"; - __u16 prefixlen, type; + __u16 prefixlen; __u8 ttl = 0; __u8 tos = 0; @@ -490,69 +490,11 @@ static void iptunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[ } } - if (tb[IFLA_IPTUN_ENCAP_TYPE] && - (type = rta_getattr_u16(tb[IFLA_IPTUN_ENCAP_TYPE])) != TUNNEL_ENCAP_NONE) { - __u16 flags = rta_getattr_u16(tb[IFLA_IPTUN_ENCAP_FLAGS]); - __u16 sport = rta_getattr_u16(tb[IFLA_IPTUN_ENCAP_SPORT]); - __u16 dport = rta_getattr_u16(tb[IFLA_IPTUN_ENCAP_DPORT]); - - open_json_object("encap"); - print_string(PRINT_FP, NULL, "encap ", NULL); - switch (type) { - case TUNNEL_ENCAP_FOU: - print_string(PRINT_ANY, "type", "%s ", "fou"); - break; - case TUNNEL_ENCAP_GUE: - print_string(PRINT_ANY, "type", "%s ", "gue"); - break; - default: - print_null(PRINT_ANY, "type", "unknown ", NULL); - break; - } - - if (is_json_context()) { - print_uint(PRINT_JSON, - "sport", - NULL, - sport ? ntohs(sport) : 0); - print_uint(PRINT_JSON, "dport", NULL, ntohs(dport)); - print_bool(PRINT_JSON, - "csum", - NULL, - flags & TUNNEL_ENCAP_FLAG_CSUM); - print_bool(PRINT_JSON, - "csum6", - NULL, - flags & TUNNEL_ENCAP_FLAG_CSUM6); - print_bool(PRINT_JSON, - "remcsum", - NULL, - flags & TUNNEL_ENCAP_FLAG_REMCSUM); - close_json_object(); - } else { - if (sport == 0) - fputs("encap-sport auto ", f); - else - fprintf(f, "encap-sport %u", ntohs(sport)); - - fprintf(f, "encap-dport %u ", ntohs(dport)); - - if (flags & TUNNEL_ENCAP_FLAG_CSUM) - fputs("encap-csum ", f); - else - fputs("noencap-csum ", f); - - if (flags & TUNNEL_ENCAP_FLAG_CSUM6) - fputs("encap-csum6 ", f); - else - fputs("noencap-csum6 ", f); - - if (flags & TUNNEL_ENCAP_FLAG_REMCSUM) - fputs("encap-remcsum ", f); - else - fputs("noencap-remcsum ", f); - } - } + tnl_print_encap(tb, + IFLA_IPTUN_ENCAP_TYPE, + IFLA_IPTUN_ENCAP_FLAGS, + IFLA_IPTUN_ENCAP_SPORT, + IFLA_IPTUN_ENCAP_DPORT); } static void iptunnel_print_help(struct link_util *lu, int argc, char **argv, diff --git a/ip/tunnel.c b/ip/tunnel.c index f8601038..42ae70e9 100644 --- a/ip/tunnel.c +++ b/ip/tunnel.c @@ -36,6 +36,7 @@ #include "utils.h" #include "tunnel.h" +#include "json_print.h" const char *tnl_strproto(__u8 proto) { @@ -200,6 +201,96 @@ __be32 tnl_parse_key(const char *name, const char *key) return htonl(uval); } +static const char *tnl_encap_str(const char *name, int enabled, int port) +{ + static const char ne[][sizeof("no")] = { + [0] = "no", + [1] = "", + }; + static char buf[32]; + char b1[16]; + const char *val; + + if (!port) { + val = "auto"; + } else if (port < 0) { + val = ""; + } else { + snprintf(b1, sizeof(b1), "%u", port - 1); + val = b1; + } + + snprintf(buf, sizeof(buf), "%sencap-%s %s", ne[!!enabled], name, val); + return buf; +} + +void tnl_print_encap(struct rtattr *tb[], + int encap_type, int encap_flags, + int encap_sport, int encap_dport) +{ + __u16 type, flags, sport, dport; + + if (!tb[encap_type]) + return; + + type = rta_getattr_u16(tb[encap_type]); + if (type == TUNNEL_ENCAP_NONE) + return; + + flags = rta_getattr_u16(tb[encap_flags]); + sport = rta_getattr_u16(tb[encap_sport]); + dport = rta_getattr_u16(tb[encap_dport]); + + open_json_object("encap"); + print_string(PRINT_FP, NULL, "encap ", NULL); + + switch (type) { + case TUNNEL_ENCAP_FOU: + print_string(PRINT_ANY, "type", "%s ", "fou"); + break; + case TUNNEL_ENCAP_GUE: + print_string(PRINT_ANY, "type", "%s ", "gue"); + break; + default: + print_null(PRINT_ANY, "type", "%s ", "unknown"); + break; + } + + if (is_json_context()) { + print_uint(PRINT_JSON, "sport", NULL, ntohs(sport)); + print_uint(PRINT_JSON, "dport", NULL, ntohs(dport)); + print_bool(PRINT_JSON, "csum", NULL, + flags & TUNNEL_ENCAP_FLAG_CSUM); + print_bool(PRINT_JSON, "csum6", NULL, + flags & TUNNEL_ENCAP_FLAG_CSUM6); + print_bool(PRINT_JSON, "remcsum", NULL, + flags & TUNNEL_ENCAP_FLAG_REMCSUM); + close_json_object(); + } else { + int t; + + t = sport ? ntohs(sport) + 1 : 0; + print_string(PRINT_FP, NULL, "%s", + tnl_encap_str("sport", 1, t)); + + t = ntohs(dport) + 1; + print_string(PRINT_FP, NULL, "%s", + tnl_encap_str("dport", 1, t)); + + t = flags & TUNNEL_ENCAP_FLAG_CSUM; + print_string(PRINT_FP, NULL, "%s", + tnl_encap_str("csum", t, -1)); + + t = flags & TUNNEL_ENCAP_FLAG_CSUM6; + print_string(PRINT_FP, NULL, "%s", + tnl_encap_str("csum6", t, -1)); + + t = flags & TUNNEL_ENCAP_FLAG_REMCSUM; + print_string(PRINT_FP, NULL, "%s", + tnl_encap_str("remcsum", t, -1)); + } +} + /* tnl_print_stats - print tunnel statistics * * @buf - tunnel interface's line in /proc/net/dev, diff --git a/ip/tunnel.h b/ip/tunnel.h index 9a03c0d7..a5c537c1 100644 --- a/ip/tunnel.h +++ b/ip/tunnel.h @@ -23,6 +23,8 @@ #include +struct rtattr; + const char *tnl_strproto(__u8 proto); int tnl_get_ioctl(const char *basedev, void *p); @@ -32,6 +34,9 @@ int tnl_prl_ioctl(int cmd, const char *name, void *p); int tnl_6rd_ioctl(int cmd, const char *name, void *p); int tnl_ioctl_get_6rd(const char *name, void *p); __be32 tnl_parse_key(const char *name, const char *key); +void tnl_print_encap(struct rtattr *tb[], + int encap_type, int encap_flags, + int encap_sport, int encap_dport); void tnl_print_stats(const char *buf); #endif From 2a8d0f6e9c3f4bbea83b76ab2aa8032be5ecf405 Mon Sep 17 00:00:00 2001 From: Serhey Popovych Date: Thu, 18 Jan 2018 16:04:33 +0200 Subject: [PATCH 31/34] gre/tunnel: Print erspan_index using print_uint() One is missing in JSON output because fprintf() is used instead of print_uint(). Signed-off-by: Serhey Popovych Signed-off-by: Stephen Hemminger --- ip/link_gre.c | 3 ++- ip/link_gre6.c | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/ip/link_gre.c b/ip/link_gre.c index d403d24a..6254e887 100644 --- a/ip/link_gre.c +++ b/ip/link_gre.c @@ -465,7 +465,8 @@ static void gre_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) if (tb[IFLA_GRE_ERSPAN_INDEX]) { __u32 erspan_idx = rta_getattr_u32(tb[IFLA_GRE_ERSPAN_INDEX]); - fprintf(f, "erspan_index %u ", erspan_idx); + print_uint(PRINT_ANY, + "erspan_index", "erspan_index %u ", erspan_idx); } tnl_print_encap(tb, diff --git a/ip/link_gre6.c b/ip/link_gre6.c index a159b542..29ca3d13 100644 --- a/ip/link_gre6.c +++ b/ip/link_gre6.c @@ -513,7 +513,9 @@ static void gre_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) if (tb[IFLA_GRE_ERSPAN_INDEX]) { __u32 erspan_idx = rta_getattr_u32(tb[IFLA_GRE_ERSPAN_INDEX]); - fprintf(f, "erspan_index %u ", erspan_idx); + + print_uint(PRINT_ANY, + "erspan_index", "erspan_index %u ", erspan_idx); } tnl_print_encap(tb, From 34a8c54d6d6b4467e8c72b68691e7f22a3819e9a Mon Sep 17 00:00:00 2001 From: Serhey Popovych Date: Thu, 18 Jan 2018 16:04:34 +0200 Subject: [PATCH 32/34] vti/tunnel: Unify ikey/okey printing For vti6 tunnel we print [io]key in dotted-quad notation (ipv4 address) while in vti we do that in hex format. For vti tunnel we print [io]key only if value is not zero while for vti6 we miss such check. Unify vti and vti6 tunnel [io]key output. While here enlarge s2 buffer to the same size as in rest of tunnel support code (64 bytes) and check return from inet_ntop(). Signed-off-by: Serhey Popovych Signed-off-by: Stephen Hemminger --- ip/link_vti.c | 22 ++++++++++++++-------- ip/link_vti6.c | 14 ++++++++++---- 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/ip/link_vti.c b/ip/link_vti.c index baaaf2f2..1439e53c 100644 --- a/ip/link_vti.c +++ b/ip/link_vti.c @@ -167,8 +167,7 @@ static void vti_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) { const char *local = "any"; const char *remote = "any"; - __u32 key; - char s2[IFNAMSIZ]; + char s2[64]; if (!tb) return; @@ -200,14 +199,21 @@ static void vti_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) } } - if (tb[IFLA_VTI_IKEY] && - (key = rta_getattr_u32(tb[IFLA_VTI_IKEY]))) - print_0xhex(PRINT_ANY, "ikey", "ikey %#x ", ntohl(key)); + if (tb[IFLA_VTI_IKEY]) { + struct rtattr *rta = tb[IFLA_VTI_IKEY]; + __u32 key = rta_getattr_u32(rta); + if (key && inet_ntop(AF_INET, RTA_DATA(rta), s2, sizeof(s2))) + print_string(PRINT_ANY, "ikey", "ikey %s ", s2); + } - if (tb[IFLA_VTI_OKEY] && - (key = rta_getattr_u32(tb[IFLA_VTI_OKEY]))) - print_0xhex(PRINT_ANY, "okey", "okey %#x ", ntohl(key)); + if (tb[IFLA_VTI_OKEY]) { + struct rtattr *rta = tb[IFLA_VTI_OKEY]; + __u32 key = rta_getattr_u32(rta); + + if (key && inet_ntop(AF_INET, RTA_DATA(rta), s2, sizeof(s2))) + print_string(PRINT_ANY, "okey", "okey %s ", s2); + } if (tb[IFLA_VTI_FWMARK]) { __u32 fwmark = rta_getattr_u32(tb[IFLA_VTI_FWMARK]); diff --git a/ip/link_vti6.c b/ip/link_vti6.c index 952dbb08..6b61e3d3 100644 --- a/ip/link_vti6.c +++ b/ip/link_vti6.c @@ -199,13 +199,19 @@ static void vti6_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) } if (tb[IFLA_VTI_IKEY]) { - inet_ntop(AF_INET, RTA_DATA(tb[IFLA_VTI_IKEY]), s2, sizeof(s2)); - print_string(PRINT_ANY, "ikey", "ikey %s ", s2); + struct rtattr *rta = tb[IFLA_VTI_IKEY]; + __u32 key = rta_getattr_u32(rta); + + if (key && inet_ntop(AF_INET, RTA_DATA(rta), s2, sizeof(s2))) + print_string(PRINT_ANY, "ikey", "ikey %s ", s2); } if (tb[IFLA_VTI_OKEY]) { - inet_ntop(AF_INET, RTA_DATA(tb[IFLA_VTI_OKEY]), s2, sizeof(s2)); - print_string(PRINT_ANY, "okey", "okey %s ", s2); + struct rtattr *rta = tb[IFLA_VTI_OKEY]; + __u32 key = rta_getattr_u32(rta); + + if (key && inet_ntop(AF_INET, RTA_DATA(rta), s2, sizeof(s2))) + print_string(PRINT_ANY, "okey", "okey %s ", s2); } if (tb[IFLA_VTI_FWMARK]) { From b8dc6c5b0ed397b082334b98641debbbbec34e29 Mon Sep 17 00:00:00 2001 From: Serhey Popovych Date: Thu, 18 Jan 2018 16:04:35 +0200 Subject: [PATCH 33/34] vti6/tunnel: Unify and simplify link type help functions Both of these two changes are missing for link_vti6.c: commit 8b47135474cd ("ip: link: Unify link type help functions a bit") commit 561e650eff67 ("ip link: Shortify printing the usage of link type") Replay them on link_vti6.c to bring link type help functions inline with other tunneling code. Signed-off-by: Serhey Popovych Signed-off-by: Stephen Hemminger --- ip/link_vti6.c | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/ip/link_vti6.c b/ip/link_vti6.c index 6b61e3d3..2a86d592 100644 --- a/ip/link_vti6.c +++ b/ip/link_vti6.c @@ -24,20 +24,25 @@ #include "ip_common.h" #include "tunnel.h" +static void print_usage(FILE *f) +{ + fprintf(f, + "Usage: ... vti6 [ remote ADDR ]\n" + " [ local ADDR ]\n" + " [ [i|o]key KEY ]\n" + " [ dev PHYS_DEV ]\n" + " [ fwmark MARK ]\n" + "\n" + "Where: ADDR := { IPV6_ADDRESS }\n" + " KEY := { DOTTED_QUAD | NUMBER }\n" + " MARK := { 0x0..0xffffffff }\n" + ); +} static void usage(void) __attribute__((noreturn)); static void usage(void) { - fprintf(stderr, "Usage: ip link { add | set | change | replace | del } NAME\n"); - fprintf(stderr, " type { vti6 } [ remote ADDR ] [ local ADDR ]\n"); - fprintf(stderr, " [ [i|o]key KEY ]\n"); - fprintf(stderr, " [ dev PHYS_DEV ]\n"); - fprintf(stderr, " [ fwmark MARK ]\n"); - fprintf(stderr, "\n"); - fprintf(stderr, "Where: NAME := STRING\n"); - fprintf(stderr, " ADDR := { IPV6_ADDRESS }\n"); - fprintf(stderr, " KEY := { DOTTED_QUAD | NUMBER }\n"); - fprintf(stderr, " MARK := { 0x0..0xffffffff }\n"); + print_usage(stderr); exit(-1); } @@ -224,9 +229,16 @@ static void vti6_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) } } +static void vti6_print_help(struct link_util *lu, int argc, char **argv, + FILE *f) +{ + print_usage(f); +} + struct link_util vti6_link_util = { .id = "vti6", .maxattr = IFLA_VTI_MAX, .parse_opt = vti6_parse_opt, .print_opt = vti6_print_opt, + .print_help = vti6_print_help, }; From c9391f120e617118d851ec5c1aff07ce6c681013 Mon Sep 17 00:00:00 2001 From: Serhey Popovych Date: Thu, 18 Jan 2018 16:04:36 +0200 Subject: [PATCH 34/34] tunnel: Return constant string without copying it We return constant string from tnl_strproto(), no need to copy it to temporary buffer and then return such buffer as const: return constant string instead. Signed-off-by: Serhey Popovych Signed-off-by: Stephen Hemminger --- ip/tunnel.c | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/ip/tunnel.c b/ip/tunnel.c index 42ae70e9..04148046 100644 --- a/ip/tunnel.c +++ b/ip/tunnel.c @@ -40,33 +40,22 @@ const char *tnl_strproto(__u8 proto) { - static char buf[16]; - switch (proto) { case IPPROTO_IPIP: - strcpy(buf, "ip"); - break; + return "ip"; case IPPROTO_GRE: - strcpy(buf, "gre"); - break; + return "gre"; case IPPROTO_IPV6: - strcpy(buf, "ipv6"); - break; + return "ipv6"; case IPPROTO_ESP: - strcpy(buf, "esp"); - break; + return "esp"; case IPPROTO_MPLS: - strcpy(buf, "mpls"); - break; + return "mpls"; case 0: - strcpy(buf, "any"); - break; + return "any"; default: - strcpy(buf, "unknown"); - break; + return "unknown"; } - - return buf; } int tnl_get_ioctl(const char *basedev, void *p)