From 0b4b35e1e82dcb950e5972b93ff32f4a5380182e Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Thu, 21 Sep 2017 10:42:28 +0200 Subject: [PATCH 1/3] json: move json printer to common library Move the json printer which is based on json writer into the iproute2 library, so it can be used by library code and tools other than ip. Should probably have been done from the beginning like that given json writer is in the library already anyway. No functional changes. Signed-off-by: Daniel Borkmann Acked-by: Julien Fortin --- include/json_print.h | 71 +++++++++++++++++++++++++++++++ ip/Makefile | 2 +- ip/ip_common.h | 65 ++++------------------------ lib/Makefile | 2 +- ip/ip_print.c => lib/json_print.c | 6 +-- 5 files changed, 83 insertions(+), 63 deletions(-) create mode 100644 include/json_print.h rename ip/ip_print.c => lib/json_print.c (97%) diff --git a/include/json_print.h b/include/json_print.h new file mode 100644 index 00000000..44cf5ac5 --- /dev/null +++ b/include/json_print.h @@ -0,0 +1,71 @@ +/* + * json_print.h "print regular or json output, based on json_writer". + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * Authors: Julien Fortin, + */ + +#ifndef _JSON_PRINT_H_ +#define _JSON_PRINT_H_ + +#include "json_writer.h" +#include "color.h" + +json_writer_t *get_json_writer(void); + +/* + * use: + * - PRINT_ANY for context based output + * - PRINT_FP for non json specific output + * - PRINT_JSON for json specific output + */ +enum output_type { + PRINT_FP = 1, + PRINT_JSON = 2, + PRINT_ANY = 4, +}; + +void new_json_obj(int json, FILE *fp); +void delete_json_obj(void); + +bool is_json_context(void); + +void set_current_fp(FILE *fp); + +void fflush_fp(void); + +void open_json_object(const char *str); +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); + +#define _PRINT_FUNC(type_name, type) \ + void print_color_##type_name(enum output_type t, \ + enum color_attr color, \ + const char *key, \ + const char *fmt, \ + type value); \ + \ + static inline void print_##type_name(enum output_type t, \ + const char *key, \ + const char *fmt, \ + type value) \ + { \ + print_color_##type_name(t, -1, key, fmt, value); \ + } +_PRINT_FUNC(int, int); +_PRINT_FUNC(bool, bool); +_PRINT_FUNC(null, const char*); +_PRINT_FUNC(string, const char*); +_PRINT_FUNC(uint, uint64_t); +_PRINT_FUNC(hu, unsigned short); +_PRINT_FUNC(hex, unsigned int); +_PRINT_FUNC(0xhex, unsigned int); +_PRINT_FUNC(lluint, unsigned long long int); +#undef _PRINT_FUNC + +#endif /* _JSON_PRINT_H_ */ diff --git a/ip/Makefile b/ip/Makefile index 52c9a2e5..5a1c7ad2 100644 --- a/ip/Makefile +++ b/ip/Makefile @@ -9,7 +9,7 @@ IPOBJ=ip.o ipaddress.o ipaddrlabel.o iproute.o iprule.o ipnetns.o \ link_iptnl.o link_gre6.o iplink_bond.o iplink_bond_slave.o iplink_hsr.o \ iplink_bridge.o iplink_bridge_slave.o ipfou.o iplink_ipvlan.o \ iplink_geneve.o iplink_vrf.o iproute_lwtunnel.o ipmacsec.o ipila.o \ - ipvrf.o iplink_xstats.o ipseg6.o ip_print.o + ipvrf.o iplink_xstats.o ipseg6.o RTMONOBJ=rtmon.o diff --git a/ip/ip_common.h b/ip/ip_common.h index efc789cb..4b8b0a71 100644 --- a/ip/ip_common.h +++ b/ip/ip_common.h @@ -1,3 +1,10 @@ +#ifndef _IP_COMMON_H_ +#define _IP_COMMON_H_ + +#include + +#include "json_print.h" + struct link_filter { int ifindex; int family; @@ -101,8 +108,6 @@ static inline int rtm_get_table(struct rtmsg *r, struct rtattr **tb) extern struct rtnl_handle rth; -#include - struct link_util { struct link_util *next; const char *id; @@ -141,58 +146,4 @@ int name_is_vrf(const char *name); void print_num(FILE *fp, unsigned int width, uint64_t count); -#include "json_writer.h" - -json_writer_t *get_json_writer(void); -/* - * use: - * - PRINT_ANY for context based output - * - PRINT_FP for non json specific output - * - PRINT_JSON for json specific output - */ -enum output_type { - PRINT_FP = 1, - PRINT_JSON = 2, - PRINT_ANY = 4, -}; - -void new_json_obj(int json, FILE *fp); -void delete_json_obj(void); - -bool is_json_context(void); - -void set_current_fp(FILE *fp); - -void fflush_fp(void); - -void open_json_object(const char *str); -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); - -#include "color.h" - -#define _PRINT_FUNC(type_name, type) \ - void print_color_##type_name(enum output_type t, \ - enum color_attr color, \ - const char *key, \ - const char *fmt, \ - type value); \ - \ - static inline void print_##type_name(enum output_type t, \ - const char *key, \ - const char *fmt, \ - type value) \ - { \ - print_color_##type_name(t, -1, key, fmt, value); \ - } -_PRINT_FUNC(int, int); -_PRINT_FUNC(bool, bool); -_PRINT_FUNC(null, const char*); -_PRINT_FUNC(string, const char*); -_PRINT_FUNC(uint, uint64_t); -_PRINT_FUNC(hu, unsigned short); -_PRINT_FUNC(hex, unsigned int); -_PRINT_FUNC(0xhex, unsigned int); -_PRINT_FUNC(lluint, unsigned long long int); -#undef _PRINT_FUNC +#endif /* _IP_COMMON_H_ */ diff --git a/lib/Makefile b/lib/Makefile index 5e9f72fa..0fbdf4c3 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -3,7 +3,7 @@ include ../config.mk CFLAGS += -fPIC UTILOBJ = utils.o rt_names.o ll_types.o ll_proto.o ll_addr.o \ - inet_proto.o namespace.o json_writer.o \ + inet_proto.o namespace.o json_writer.o json_print.o \ names.o color.o bpf.o exec.o fs.o NLOBJ=libgenl.o ll_map.o libnetlink.o diff --git a/ip/ip_print.c b/lib/json_print.c similarity index 97% rename from ip/ip_print.c rename to lib/json_print.c index 4cd6a0bc..93b4119d 100644 --- a/ip/ip_print.c +++ b/lib/json_print.c @@ -1,5 +1,5 @@ /* - * ip_print.c "ip print regular or json output". + * json_print.c "print regular or json output, based on json_writer". * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -7,15 +7,13 @@ * 2 of the License, or (at your option) any later version. * * Authors: Julien Fortin, - * */ #include #include #include "utils.h" -#include "ip_common.h" -#include "json_writer.h" +#include "json_print.h" static json_writer_t *_jw; static FILE *_fp; From bc2d4d838ff717f4003b039725df454a4a75109e Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Thu, 21 Sep 2017 10:42:29 +0200 Subject: [PATCH 2/3] bpf: properly output json for xdp After merging net-next branch into master, Stephen asked to fix up json dump for XDP. Thus, rework the json dump a bit, such that 'ip -json l' looks as below. [{ "ifindex": 1, "ifname": "lo", "flags": ["LOOPBACK","UP","LOWER_UP"], "mtu": 65536, "xdp": { "mode": 2, "prog": { "id": 5, "tag": "e1e9d0ec0f55d638", "jited": 1 } }, "qdisc": "noqueue", "operstate": "UNKNOWN", "linkmode": "DEFAULT", "group": "default", "txqlen": 1000, "link_type": "loopback", "address": "00:00:00:00:00:00", "broadcast": "00:00:00:00:00:00" },[...] ] Signed-off-by: Daniel Borkmann --- ip/iplink_xdp.c | 70 +++++++++++++++++++++++++++++-------------------- lib/bpf.c | 19 +++++++++----- 2 files changed, 55 insertions(+), 34 deletions(-) diff --git a/ip/iplink_xdp.c b/ip/iplink_xdp.c index 71f77982..2d2953aa 100644 --- a/ip/iplink_xdp.c +++ b/ip/iplink_xdp.c @@ -14,9 +14,9 @@ #include +#include "json_print.h" #include "xdp.h" #include "bpf_util.h" -#include "ip_common.h" extern int force; @@ -82,6 +82,22 @@ int xdp_parse(int *argc, char ***argv, struct iplink_req *req, bool generic, return 0; } +static void xdp_dump_json(struct rtattr *tb[IFLA_XDP_MAX + 1]) +{ + __u32 prog_id = 0; + __u8 mode; + + mode = rta_getattr_u8(tb[IFLA_XDP_ATTACHED]); + if (tb[IFLA_XDP_PROG_ID]) + prog_id = rta_getattr_u32(tb[IFLA_XDP_PROG_ID]); + + open_json_object("xdp"); + print_uint(PRINT_JSON, "mode", NULL, mode); + if (prog_id) + bpf_dump_prog_info(NULL, prog_id); + close_json_object(); +} + void xdp_dump(FILE *fp, struct rtattr *xdp, bool link, bool details) { struct rtattr *tb[IFLA_XDP_MAX + 1]; @@ -94,34 +110,32 @@ void xdp_dump(FILE *fp, struct rtattr *xdp, bool link, bool details) return; mode = rta_getattr_u8(tb[IFLA_XDP_ATTACHED]); - if (is_json_context()) { - print_uint(PRINT_JSON, "attached", NULL, mode); - } else { - if (mode == XDP_ATTACHED_NONE) - return; - else if (details && link) - fprintf(fp, "%s prog/xdp", _SL_); - else if (mode == XDP_ATTACHED_DRV) - fprintf(fp, "xdp"); - else if (mode == XDP_ATTACHED_SKB) - fprintf(fp, "xdpgeneric"); - else if (mode == XDP_ATTACHED_HW) - fprintf(fp, "xdpoffload"); - else - fprintf(fp, "xdp[%u]", mode); + if (mode == XDP_ATTACHED_NONE) + return; + else if (is_json_context()) + return details ? (void)0 : xdp_dump_json(tb); + else if (details && link) + fprintf(fp, "%s prog/xdp", _SL_); + else if (mode == XDP_ATTACHED_DRV) + fprintf(fp, "xdp"); + else if (mode == XDP_ATTACHED_SKB) + fprintf(fp, "xdpgeneric"); + else if (mode == XDP_ATTACHED_HW) + fprintf(fp, "xdpoffload"); + else + fprintf(fp, "xdp[%u]", mode); - if (tb[IFLA_XDP_PROG_ID]) - prog_id = rta_getattr_u32(tb[IFLA_XDP_PROG_ID]); - if (!details) { - if (prog_id && !link) - fprintf(fp, "/id:%u", prog_id); - fprintf(fp, " "); - return; - } + if (tb[IFLA_XDP_PROG_ID]) + prog_id = rta_getattr_u32(tb[IFLA_XDP_PROG_ID]); + if (!details) { + if (prog_id && !link) + fprintf(fp, "/id:%u", prog_id); + fprintf(fp, " "); + return; + } - if (prog_id) { - fprintf(fp, " "); - bpf_dump_prog_info(fp, prog_id); - } + if (prog_id) { + fprintf(fp, " "); + bpf_dump_prog_info(fp, prog_id); } } diff --git a/lib/bpf.c b/lib/bpf.c index cfa1f79a..10ea23a4 100644 --- a/lib/bpf.c +++ b/lib/bpf.c @@ -40,6 +40,7 @@ #include #include "utils.h" +#include "json_print.h" #include "bpf_util.h" #include "bpf_elf.h" @@ -186,23 +187,29 @@ int bpf_dump_prog_info(FILE *f, uint32_t id) int fd, ret, dump_ok = 0; SPRINT_BUF(tmp); - fprintf(f, "id %u ", id); + open_json_object("prog"); + print_uint(PRINT_ANY, "id", "id %u ", id); fd = bpf_prog_fd_by_id(id); if (fd < 0) - return dump_ok; + goto out; ret = bpf_prog_info_by_fd(fd, &info, &len); if (!ret && len) { - fprintf(f, "tag %s ", - hexstring_n2a(info.tag, sizeof(info.tag), - tmp, sizeof(tmp))); - if (info.jited_prog_len) + int jited = !!info.jited_prog_len; + + print_string(PRINT_ANY, "tag", "tag %s ", + hexstring_n2a(info.tag, sizeof(info.tag), + tmp, sizeof(tmp))); + print_uint(PRINT_JSON, "jited", NULL, jited); + if (jited && !is_json_context()) fprintf(f, "jited "); dump_ok = 1; } close(fd); +out: + close_json_object(); return dump_ok; } From 01777e055d7171f233ff3f6d89725387975e4c77 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Fri, 22 Sep 2017 13:28:54 +0200 Subject: [PATCH 3/3] man: fix documentation for range of route table ID Signed-off-by: Thomas Haller --- man/man8/ip-route.8.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/man/man8/ip-route.8.in b/man/man8/ip-route.8.in index 803de3b9..705ceb20 100644 --- a/man/man8/ip-route.8.in +++ b/man/man8/ip-route.8.in @@ -322,7 +322,7 @@ normal routing tables. .P .B Route tables: Linux-2.x can pack routes into several routing tables identified -by a number in the range from 1 to 2^31 or by name from the file +by a number in the range from 1 to 2^32-1 or by name from the file .B @SYSCONFDIR@/rt_tables By default all normal routes are inserted into the .B main