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/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/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/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; } 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; 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