[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <20180829080453.0026d52b@xeon-e3>
Date: Wed, 29 Aug 2018 08:04:53 -0700
From: Stephen Hemminger <stephen@...workplumber.org>
To: Roopa Prabhu <roopa@...ulusnetworks.com>
Cc: netdev <netdev@...r.kernel.org>,
Stephen Hemminger <sthemmin@...rosoft.com>,
Julien Fortin <julien@...ulusnetworks.com>,
David Ahern <dsahern@...il.com>
Subject: Re: [PATCH v2 iproute2-next 2/5] bridge: colorize output and use
JSON print library
On Sat, 14 Jul 2018 18:41:03 -0700
Roopa Prabhu <roopa@...ulusnetworks.com> wrote:
> On Tue, Feb 20, 2018 at 11:24 AM, Stephen Hemminger
> <stephen@...workplumber.org> wrote:
> > From: Stephen Hemminger <sthemmin@...rosoft.com>
> >
> > Use new functions from json_print to simplify code.
> > Provide standard flag for colorizing output.
> >
> > The shortened -c flag is ambiguous it could mean color or
> > compressvlan; it is now changed to mean color for consistency
> > with other iproute2 commands.
> >
> > Signed-off-by: Stephen Hemminger <stephen@...workplumber.org>
> > ---
> > bridge/br_common.h | 2 +-
> > bridge/bridge.c | 10 +-
> > bridge/fdb.c | 281 +++++++++++++++--------------------------
> > bridge/mdb.c | 362 ++++++++++++++++++++++-------------------------------
> > bridge/vlan.c | 276 +++++++++++++++-------------------------
> > 5 files changed, 363 insertions(+), 568 deletions(-)
> >
> > diff --git a/bridge/br_common.h b/bridge/br_common.h
> > index b25f61e50e05..2f1cb8fd9f3d 100644
> > --- a/bridge/br_common.h
> > +++ b/bridge/br_common.h
> > @@ -6,7 +6,7 @@
> > #define MDB_RTR_RTA(r) \
> > ((struct rtattr *)(((char *)(r)) + RTA_ALIGN(sizeof(__u32))))
> >
> > -extern void print_vlan_info(FILE *fp, struct rtattr *tb, int ifindex);
> > +extern void print_vlan_info(FILE *fp, struct rtattr *tb);
> > extern int print_linkinfo(const struct sockaddr_nl *who,
> > struct nlmsghdr *n,
> > void *arg);
> > diff --git a/bridge/bridge.c b/bridge/bridge.c
> > index 4b112e3b8da9..e5b4c3c2198f 100644
> > --- a/bridge/bridge.c
> > +++ b/bridge/bridge.c
> > @@ -16,12 +16,15 @@
> > #include "utils.h"
> > #include "br_common.h"
> > #include "namespace.h"
> > +#include "color.h"
> >
> > struct rtnl_handle rth = { .fd = -1 };
> > int preferred_family = AF_UNSPEC;
> > int oneline;
> > int show_stats;
> > int show_details;
> > +int show_pretty;
> > +int color;
> > int compress_vlans;
> > int json;
> > int timestamp;
> > @@ -39,7 +42,7 @@ static void usage(void)
> > "where OBJECT := { link | fdb | mdb | vlan | monitor }\n"
> > " OPTIONS := { -V[ersion] | -s[tatistics] | -d[etails] |\n"
> > " -o[neline] | -t[imestamp] | -n[etns] name |\n"
> > -" -c[ompressvlans] -p[retty] -j{son} }\n");
> > +" -c[ompressvlans] -color -p[retty] -j{son} }\n");
> > exit(-1);
> > }
> >
> > @@ -170,6 +173,8 @@ main(int argc, char **argv)
> > NEXT_ARG();
> > if (netns_switch(argv[1]))
> > exit(-1);
> > + } else if (matches(opt, "-color") == 0) {
> > + enable_color();
> > } else if (matches(opt, "-compressvlans") == 0) {
> > ++compress_vlans;
> > } else if (matches(opt, "-force") == 0) {
> > @@ -195,6 +200,9 @@ main(int argc, char **argv)
> >
> > _SL_ = oneline ? "\\" : "\n";
> >
> > + if (json)
> > + check_if_color_enabled();
> > +
> > if (batch_file)
> > return batch(batch_file);
> >
> > diff --git a/bridge/fdb.c b/bridge/fdb.c
> > index 93b5b2e694e3..b4f6e8b3a01b 100644
> > --- a/bridge/fdb.c
> > +++ b/bridge/fdb.c
> > @@ -22,9 +22,9 @@
> > #include <linux/neighbour.h>
> > #include <string.h>
> > #include <limits.h>
> > -#include <json_writer.h>
> > #include <stdbool.h>
> >
> > +#include "json_print.h"
> > #include "libnetlink.h"
> > #include "br_common.h"
> > #include "rt_names.h"
> > @@ -32,8 +32,6 @@
> >
> > static unsigned int filter_index, filter_vlan, filter_state;
> >
> > -json_writer_t *jw_global;
> > -
> > static void usage(void)
> > {
> > fprintf(stderr,
> > @@ -83,13 +81,46 @@ static int state_a2n(unsigned int *s, const char *arg)
> > return 0;
> > }
> >
> > -static void start_json_fdb_flags_array(bool *fdb_flags)
> > +static void fdb_print_flags(FILE *fp, unsigned int flags)
> > +{
> > + open_json_array(PRINT_JSON,
> > + is_json_context() ? "flags" : "");
> > +
> > + if (flags & NTF_SELF)
> > + print_string(PRINT_ANY, NULL, "%s ", "self");
> > +
> > + if (flags & NTF_ROUTER)
> > + print_string(PRINT_ANY, NULL, "%s ", "router");
> > +
> > + if (flags & NTF_EXT_LEARNED)
> > + print_string(PRINT_ANY, NULL, "%s ", "extern_learn");
> > +
> > + if (flags & NTF_OFFLOADED)
> > + print_string(PRINT_ANY, NULL, "%s ", "offload");
> > +
> > + if (flags & NTF_MASTER)
> > + print_string(PRINT_ANY, NULL, "%s ", "master");
> > +
> > + close_json_array(PRINT_JSON, NULL);
> > +}
> > +
> > +static void fdb_print_stats(FILE *fp, const struct nda_cacheinfo *ci)
> > {
> > - if (*fdb_flags)
> > - return;
> > - jsonw_name(jw_global, "flags");
> > - jsonw_start_array(jw_global);
> > - *fdb_flags = true;
> > + static int hz;
> > +
> > + if (!hz)
> > + hz = get_user_hz();
> > +
> > + if (is_json_context()) {
> > + print_uint(PRINT_JSON, "used", NULL,
> > + ci->ndm_used / hz);
> > + print_uint(PRINT_JSON, "updated", NULL,
> > + ci->ndm_updated / hz);
> > + } else {
> > + fprintf(fp, "used %d/%d ", ci->ndm_used / hz,
> > + ci->ndm_updated / hz);
> > +
> > + }
> > }
> >
> > int print_fdb(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
> > @@ -99,8 +130,6 @@ int print_fdb(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
> > int len = n->nlmsg_len;
> > struct rtattr *tb[NDA_MAX+1];
> > __u16 vid = 0;
> > - bool fdb_flags = false;
> > - const char *state_s;
> >
> > if (n->nlmsg_type != RTM_NEWNEIGH && n->nlmsg_type != RTM_DELNEIGH) {
> > fprintf(stderr, "Not RTM_NEWNEIGH: %08x %08x %08x\n",
> > @@ -132,189 +161,98 @@ int print_fdb(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
> > if (filter_vlan && filter_vlan != vid)
> > return 0;
> >
> > - if (jw_global)
> > - jsonw_start_object(jw_global);
> > -
> > - if (n->nlmsg_type == RTM_DELNEIGH) {
> > - if (jw_global)
> > - jsonw_string_field(jw_global, "opCode", "deleted");
> > - else
> > - fprintf(fp, "Deleted ");
> > - }
> > + open_json_object(NULL);
> > + if (n->nlmsg_type == RTM_DELNEIGH)
> > + print_bool(PRINT_ANY, "deleted", "Deleted ", true);
> >
> > if (tb[NDA_LLADDR]) {
> > + const char *lladdr;
> > SPRINT_BUF(b1);
> > - ll_addr_n2a(RTA_DATA(tb[NDA_LLADDR]),
> > - RTA_PAYLOAD(tb[NDA_LLADDR]),
> > - ll_index_to_type(r->ndm_ifindex),
> > - b1, sizeof(b1));
> > - if (jw_global)
> > - jsonw_string_field(jw_global, "mac", b1);
> > - else
> > - fprintf(fp, "%s ", b1);
> > +
> > + lladdr = ll_addr_n2a(RTA_DATA(tb[NDA_LLADDR]),
> > + RTA_PAYLOAD(tb[NDA_LLADDR]),
> > + ll_index_to_type(r->ndm_ifindex),
> > + b1, sizeof(b1));
> > +
> > + print_color_string(PRINT_ANY, COLOR_MAC,
> > + "mac", "%s ", lladdr);
> > }
> >
> > if (!filter_index && r->ndm_ifindex) {
> > - if (jw_global)
> > - jsonw_string_field(jw_global, "dev",
> > - ll_index_to_name(r->ndm_ifindex));
> > - else
> > - fprintf(fp, "dev %s ",
> > - ll_index_to_name(r->ndm_ifindex));
> > + if (!is_json_context())
> > + fprintf(fp, "dev ");
> > + print_color_string(PRINT_ANY, COLOR_IFNAME,
> > + "ifname", "%s ",
> > + ll_index_to_name(r->ndm_ifindex));
> > }
> >
> > if (tb[NDA_DST]) {
> > int family = AF_INET;
> > - const char *abuf_s;
> > + const char *dst;
> >
> > if (RTA_PAYLOAD(tb[NDA_DST]) == sizeof(struct in6_addr))
> > family = AF_INET6;
> >
> > - abuf_s = format_host(family,
> > - RTA_PAYLOAD(tb[NDA_DST]),
> > - RTA_DATA(tb[NDA_DST]));
> > - if (jw_global)
> > - jsonw_string_field(jw_global, "dst", abuf_s);
> > - else
> > - fprintf(fp, "dst %s ", abuf_s);
> > - }
> > + dst = format_host(family,
> > + RTA_PAYLOAD(tb[NDA_DST]),
> > + RTA_DATA(tb[NDA_DST]));
> >
> > - if (vid) {
> > - if (jw_global)
> > - jsonw_uint_field(jw_global, "vlan", vid);
> > - else
> > - fprintf(fp, "vlan %hu ", vid);
> > + print_color_string(PRINT_ANY,
> > + ifa_family_color(family),
> > + "dst", "%s ", dst);
> > }
> >
> > - if (tb[NDA_PORT]) {
> > - if (jw_global)
> > - jsonw_uint_field(jw_global, "port",
> > - rta_getattr_be16(tb[NDA_PORT]));
> > - else
> > - fprintf(fp, "port %d ",
> > - rta_getattr_be16(tb[NDA_PORT]));
> > - }
> > + if (vid)
> > + print_uint(PRINT_ANY,
> > + "vlan", "vlan %hu ", vid);
> >
> > - if (tb[NDA_VNI]) {
> > - if (jw_global)
> > - jsonw_uint_field(jw_global, "vni",
> > - rta_getattr_u32(tb[NDA_VNI]));
> > - else
> > - fprintf(fp, "vni %d ",
> > - rta_getattr_u32(tb[NDA_VNI]));
> > - }
> > + if (tb[NDA_PORT])
> > + print_uint(PRINT_ANY,
> > + "port", "port %u ",
> > + rta_getattr_be16(tb[NDA_PORT]));
> >
> > - if (tb[NDA_SRC_VNI]) {
> > - if (jw_global)
> > - jsonw_uint_field(jw_global, "src_vni",
> > - rta_getattr_u32(tb[NDA_SRC_VNI]));
> > - else
> > - fprintf(fp, "src_vni %d ",
> > + if (tb[NDA_VNI])
> > + print_uint(PRINT_ANY,
> > + "vni", "vni %u ",
> > + rta_getattr_u32(tb[NDA_VNI]));
> > +
> > + if (tb[NDA_SRC_VNI])
> > + print_uint(PRINT_ANY,
> > + "src_vni", "src_vni %u ",
> > rta_getattr_u32(tb[NDA_SRC_VNI]));
> > - }
> >
> > if (tb[NDA_IFINDEX]) {
> > unsigned int ifindex = rta_getattr_u32(tb[NDA_IFINDEX]);
> >
> > - if (ifindex) {
> > - if (!tb[NDA_LINK_NETNSID]) {
> > - const char *ifname = ll_index_to_name(ifindex);
> > -
> > - if (jw_global)
> > - jsonw_string_field(jw_global, "viaIf",
> > - ifname);
> > - else
> > - fprintf(fp, "via %s ", ifname);
> > - } else {
> > - if (jw_global)
> > - jsonw_uint_field(jw_global, "viaIfIndex",
> > - ifindex);
> > - else
> > - fprintf(fp, "via ifindex %u ", ifindex);
> > - }
> > - }
> > - }
> > -
> > - if (tb[NDA_LINK_NETNSID]) {
> > - if (jw_global)
> > - jsonw_uint_field(jw_global, "linkNetNsId",
> > - rta_getattr_u32(tb[NDA_LINK_NETNSID]));
> > + if (tb[NDA_LINK_NETNSID])
> > + print_uint(PRINT_ANY,
> > + "viaIfIndex", "via ifindex %u ",
> > + ifindex);
> > else
> > - fprintf(fp, "link-netnsid %d ",
> > - rta_getattr_u32(tb[NDA_LINK_NETNSID]));
> > + print_string(PRINT_ANY,
> > + "viaIf", "via %s ",
> > + ll_index_to_name(ifindex));
> > }
> >
> > - if (show_stats && tb[NDA_CACHEINFO]) {
> > - struct nda_cacheinfo *ci = RTA_DATA(tb[NDA_CACHEINFO]);
> > - int hz = get_user_hz();
> > + if (tb[NDA_LINK_NETNSID])
> > + print_uint(PRINT_ANY,
> > + "linkNetNsId", "link-netnsid %d ",
> > + rta_getattr_u32(tb[NDA_LINK_NETNSID]));
> >
> > - if (jw_global) {
> > - jsonw_uint_field(jw_global, "used",
> > - ci->ndm_used/hz);
> > - jsonw_uint_field(jw_global, "updated",
> > - ci->ndm_updated/hz);
> > - } else {
> > - fprintf(fp, "used %d/%d ", ci->ndm_used/hz,
> > - ci->ndm_updated/hz);
> > - }
> > - }
> > + if (show_stats && tb[NDA_CACHEINFO])
> > + fdb_print_stats(fp, RTA_DATA(tb[NDA_CACHEINFO]));
> >
> > - if (jw_global) {
> > - if (r->ndm_flags & NTF_SELF) {
> > - start_json_fdb_flags_array(&fdb_flags);
> > - jsonw_string(jw_global, "self");
> > - }
> > - if (r->ndm_flags & NTF_ROUTER) {
> > - start_json_fdb_flags_array(&fdb_flags);
> > - jsonw_string(jw_global, "router");
> > - }
> > - if (r->ndm_flags & NTF_EXT_LEARNED) {
> > - start_json_fdb_flags_array(&fdb_flags);
> > - jsonw_string(jw_global, "extern_learn");
> > - }
> > - if (r->ndm_flags & NTF_OFFLOADED) {
> > - start_json_fdb_flags_array(&fdb_flags);
> > - jsonw_string(jw_global, "offload");
> > - }
> > - if (r->ndm_flags & NTF_MASTER)
> > - jsonw_string(jw_global, "master");
> > - if (fdb_flags)
> > - jsonw_end_array(jw_global);
> > + fdb_print_flags(fp, r->ndm_flags);
> >
> > - if (tb[NDA_MASTER])
> > - jsonw_string_field(jw_global,
> > - "master",
> > - ll_index_to_name(rta_getattr_u32(tb[NDA_MASTER])));
> >
> > - } else {
> > - if (r->ndm_flags & NTF_SELF)
> > - fprintf(fp, "self ");
> > - if (r->ndm_flags & NTF_ROUTER)
> > - fprintf(fp, "router ");
> > - if (r->ndm_flags & NTF_EXT_LEARNED)
> > - fprintf(fp, "extern_learn ");
> > - if (r->ndm_flags & NTF_OFFLOADED)
> > - fprintf(fp, "offload ");
> > - if (tb[NDA_MASTER]) {
> > - fprintf(fp, "master %s ",
> > - ll_index_to_name(rta_getattr_u32(tb[NDA_MASTER])));
> > - } else if (r->ndm_flags & NTF_MASTER) {
> > - fprintf(fp, "master ");
> > - }
> > - }
> > -
> > - state_s = state_n2a(r->ndm_state);
> > - if (jw_global) {
> > - if (state_s[0])
> > - jsonw_string_field(jw_global, "state", state_s);
> > -
> > - jsonw_end_object(jw_global);
> > - } else {
> > - fprintf(fp, "%s\n", state_s);
> > -
> > - fflush(fp);
> > - }
> > + if (tb[NDA_MASTER])
> > + print_string(PRINT_ANY, "master", "%s ",
> > + ll_index_to_name(rta_getattr_u32(tb[NDA_MASTER])));
> >
> > + print_string(PRINT_ANY, "state", "%s\n",
> > + state_n2a(r->ndm_state));
> > + close_json_object();
> > + fflush(fp);
> > return 0;
> > }
> >
> > @@ -386,26 +324,13 @@ static int fdb_show(int argc, char **argv)
> > exit(1);
> > }
> >
> > - if (json) {
> > - jw_global = jsonw_new(stdout);
> > - if (!jw_global) {
> > - fprintf(stderr, "Error allocation json object\n");
> > - exit(1);
> > - }
> > - if (pretty)
> > - jsonw_pretty(jw_global, 1);
> > -
> > - jsonw_start_array(jw_global);
> > - }
> > -
> > + new_json_obj(json);
> > if (rtnl_dump_filter(&rth, print_fdb, stdout) < 0) {
> > fprintf(stderr, "Dump terminated\n");
> > exit(1);
> > }
> > - if (jw_global) {
> > - jsonw_end_array(jw_global);
> > - jsonw_destroy(&jw_global);
> > - }
> > + delete_json_obj();
> > + fflush(stdout);
> >
> > return 0;
> > }
> > diff --git a/bridge/mdb.c b/bridge/mdb.c
> > index da0282fdc91c..8c08baf570ec 100644
> > --- a/bridge/mdb.c
> > +++ b/bridge/mdb.c
> > @@ -14,12 +14,12 @@
> > #include <linux/if_ether.h>
> > #include <string.h>
> > #include <arpa/inet.h>
> > -#include <json_writer.h>
> >
> > #include "libnetlink.h"
> > #include "br_common.h"
> > #include "rt_names.h"
> > #include "utils.h"
> > +#include "json_print.h"
> >
> > #ifndef MDBA_RTA
> > #define MDBA_RTA(r) \
> > @@ -27,9 +27,6 @@
> > #endif
> >
> > static unsigned int filter_index, filter_vlan;
> > -json_writer_t *jw_global;
> > -static bool print_mdb_entries = true;
> > -static bool print_mdb_router = true;
> >
> > static void usage(void)
> > {
> > @@ -43,162 +40,131 @@ static bool is_temp_mcast_rtr(__u8 type)
> > return type == MDB_RTR_TYPE_TEMP_QUERY || type == MDB_RTR_TYPE_TEMP;
> > }
> >
> > +static const char *format_timer(__u32 ticks)
> > +{
> > + struct timeval tv;
> > + static char tbuf[32];
> > +
> > + __jiffies_to_tv(&tv, ticks);
> > + snprintf(tbuf, sizeof(tbuf), "%4lu.%.2lu",
> > + (unsigned long)tv.tv_sec,
> > + (unsigned long)tv.tv_usec / 10000);
> > +
> > + return tbuf;
> > +}
> > +
> > static void __print_router_port_stats(FILE *f, struct rtattr *pattr)
> > {
> > struct rtattr *tb[MDBA_ROUTER_PATTR_MAX + 1];
> > - struct timeval tv;
> > - __u8 type;
> >
> > parse_rtattr(tb, MDBA_ROUTER_PATTR_MAX, MDB_RTR_RTA(RTA_DATA(pattr)),
> > RTA_PAYLOAD(pattr) - RTA_ALIGN(sizeof(uint32_t)));
> > +
> > if (tb[MDBA_ROUTER_PATTR_TIMER]) {
> > - __jiffies_to_tv(&tv,
> > - rta_getattr_u32(tb[MDBA_ROUTER_PATTR_TIMER]));
> > - if (jw_global) {
> > - char formatted_time[9];
> > -
> > - snprintf(formatted_time, sizeof(formatted_time),
> > - "%4i.%.2i", (int)tv.tv_sec,
> > - (int)tv.tv_usec/10000);
> > - jsonw_string_field(jw_global, "timer", formatted_time);
> > - } else {
> > - fprintf(f, " %4i.%.2i",
> > - (int)tv.tv_sec, (int)tv.tv_usec/10000);
> > - }
> > + __u32 timer = rta_getattr_u32(tb[MDBA_ROUTER_PATTR_TIMER]);
> > +
> > + print_string(PRINT_ANY, "timer", " %s",
> > + format_timer(timer));
> > }
> > +
> > if (tb[MDBA_ROUTER_PATTR_TYPE]) {
> > - type = rta_getattr_u8(tb[MDBA_ROUTER_PATTR_TYPE]);
> > - if (jw_global)
> > - jsonw_string_field(jw_global, "type",
> > - is_temp_mcast_rtr(type) ? "temp" : "permanent");
> > - else
> > - fprintf(f, " %s",
> > - is_temp_mcast_rtr(type) ? "temp" : "permanent");
> > + __u8 type = rta_getattr_u8(tb[MDBA_ROUTER_PATTR_TYPE]);
> > +
> > + print_string(PRINT_ANY, "type", " %s",
> > + is_temp_mcast_rtr(type) ? "temp" : "permanent");
> > }
> > }
> >
> > -static void br_print_router_ports(FILE *f, struct rtattr *attr, __u32 brifidx)
> > +static void br_print_router_ports(FILE *f, struct rtattr *attr,
> > + const char *brifname)
> > {
> > - uint32_t *port_ifindex;
> > + int rem = RTA_PAYLOAD(attr);
> > struct rtattr *i;
> > - int rem;
> >
> > - rem = RTA_PAYLOAD(attr);
> > - if (jw_global) {
> > - jsonw_name(jw_global, ll_index_to_name(brifidx));
> > - jsonw_start_array(jw_global);
> > - for (i = RTA_DATA(attr); RTA_OK(i, rem); i = RTA_NEXT(i, rem)) {
> > - port_ifindex = RTA_DATA(i);
> > - jsonw_start_object(jw_global);
> > - jsonw_string_field(jw_global,
> > - "port",
> > - ll_index_to_name(*port_ifindex));
> > + if (is_json_context())
> > + open_json_array(PRINT_JSON, brifname);
> > + else if (!show_stats)
> > + fprintf(f, "router ports on %s: ", brifname);
> > +
> > + for (i = RTA_DATA(attr); RTA_OK(i, rem); i = RTA_NEXT(i, rem)) {
> > + uint32_t *port_ifindex = RTA_DATA(i);
> > + const char *port_ifname = ll_index_to_name(*port_ifindex);
> > +
> > + if (is_json_context()) {
> > + open_json_object(NULL);
> > + print_string(PRINT_JSON, "port", NULL, port_ifname);
> > +
> > if (show_stats)
> > __print_router_port_stats(f, i);
> > - jsonw_end_object(jw_global);
> > - }
> > - jsonw_end_array(jw_global);
> > - } else {
> > - if (!show_stats)
> > - fprintf(f, "router ports on %s: ",
> > - ll_index_to_name(brifidx));
> > - for (i = RTA_DATA(attr); RTA_OK(i, rem); i = RTA_NEXT(i, rem)) {
> > - port_ifindex = RTA_DATA(i);
> > - if (show_stats) {
> > - fprintf(f, "router ports on %s: %s",
> > - ll_index_to_name(brifidx),
> > - ll_index_to_name(*port_ifindex));
> > - __print_router_port_stats(f, i);
> > - fprintf(f, "\n");
> > - } else{
> > - fprintf(f, "%s ",
> > - ll_index_to_name(*port_ifindex));
> > - }
> > - }
> > - if (!show_stats)
> > + close_json_object();
> > + } else if (show_stats) {
> > + fprintf(f, "router ports on %s: %s",
> > + brifname, port_ifname);
> > +
> > + __print_router_port_stats(f, i);
> > fprintf(f, "\n");
> > + } else {
> > + fprintf(f, "%s ", port_ifname);
> > + }
> > }
> > + close_json_array(PRINT_JSON, NULL);
> > }
> >
> > -static void start_json_mdb_flags_array(bool *mdb_flags)
> > -{
> > - if (*mdb_flags)
> > - return;
> > - jsonw_name(jw_global, "flags");
> > - jsonw_start_array(jw_global);
> > - *mdb_flags = true;
> > -}
> > -
> > -static void print_mdb_entry(FILE *f, int ifindex, struct br_mdb_entry *e,
> > +static void print_mdb_entry(FILE *f, int ifindex, const struct br_mdb_entry *e,
> > struct nlmsghdr *n, struct rtattr **tb)
> > {
> > SPRINT_BUF(abuf);
> > + const char *dev;
> > const void *src;
> > int af;
> > - bool mdb_flags = false;
> >
> > if (filter_vlan && e->vid != filter_vlan)
> > return;
> > +
> > af = e->addr.proto == htons(ETH_P_IP) ? AF_INET : AF_INET6;
> > src = af == AF_INET ? (const void *)&e->addr.u.ip4 :
> > (const void *)&e->addr.u.ip6;
> > - if (jw_global)
> > - jsonw_start_object(jw_global);
> > - if (n->nlmsg_type == RTM_DELMDB) {
> > - if (jw_global)
> > - jsonw_string_field(jw_global, "opCode", "deleted");
> > - else
> > - fprintf(f, "Deleted ");
> > - }
> > - if (jw_global) {
> > - jsonw_string_field(jw_global, "dev", ll_index_to_name(ifindex));
> > - jsonw_string_field(jw_global,
> > - "port",
> > - ll_index_to_name(e->ifindex));
> > - jsonw_string_field(jw_global, "grp", inet_ntop(af, src,
> > - abuf, sizeof(abuf)));
> > - jsonw_string_field(jw_global, "state",
> > - (e->state & MDB_PERMANENT) ? "permanent" : "temp");
> > - if (e->flags & MDB_FLAGS_OFFLOAD) {
> > - start_json_mdb_flags_array(&mdb_flags);
> > - jsonw_string(jw_global, "offload");
> > - }
> > - if (mdb_flags)
> > - jsonw_end_array(jw_global);
> > - } else{
> > - fprintf(f, "dev %s port %s grp %s %s %s",
> > - ll_index_to_name(ifindex),
> > - ll_index_to_name(e->ifindex),
> > - inet_ntop(af, src, abuf, sizeof(abuf)),
> > - (e->state & MDB_PERMANENT) ? "permanent" : "temp",
> > - (e->flags & MDB_FLAGS_OFFLOAD) ? "offload" : "");
> > - }
> > - if (e->vid) {
> > - if (jw_global)
> > - jsonw_uint_field(jw_global, "vid", e->vid);
> > - else
> > - fprintf(f, " vid %hu", e->vid);
> > + dev = ll_index_to_name(ifindex);
> > +
> > + open_json_object(NULL);
> > +
> > + if (n->nlmsg_type == RTM_DELMDB)
> > + print_bool(PRINT_ANY, "deleted", "Deleted ", true);
> > +
> > +
> > + if (is_json_context()) {
> > + print_int(PRINT_JSON, "index", NULL, ifindex);
> > + print_string(PRINT_JSON, "dev", NULL, dev);
> > + } else {
> > + fprintf(f, "%u: ", ifindex);
> > + color_fprintf(f, COLOR_IFNAME, "%s ", dev);
> > }
> > - if (show_stats && tb && tb[MDBA_MDB_EATTR_TIMER]) {
> > - struct timeval tv;
> >
> > - __jiffies_to_tv(&tv, rta_getattr_u32(tb[MDBA_MDB_EATTR_TIMER]));
> > - if (jw_global) {
> > - char formatted_time[9];
> > + print_string(PRINT_ANY, "port", " %s ",
> > + ll_index_to_name(e->ifindex));
> >
> > - snprintf(formatted_time, sizeof(formatted_time),
> > - "%4i.%.2i", (int)tv.tv_sec,
> > - (int)tv.tv_usec/10000);
> > - jsonw_string_field(jw_global, "timer", formatted_time);
> > - } else {
> > - fprintf(f, "%4i.%.2i", (int)tv.tv_sec,
> > - (int)tv.tv_usec/10000);
> > - }
> > + print_color_string(PRINT_ANY, ifa_family_color(af),
> > + "grp", " %s ",
> > + inet_ntop(af, src, abuf, sizeof(abuf)));
> > +
> > + print_string(PRINT_ANY, "state", " %s ",
> > + (e->state & MDB_PERMANENT) ? "permanent" : "temp");
> > +
> > + open_json_array(PRINT_JSON, "flags");
> > + if (e->flags & MDB_FLAGS_OFFLOAD)
> > + print_string(PRINT_ANY, NULL, "%s ", "offload");
> > + close_json_array(PRINT_JSON, NULL);
> > +
> > + if (e->vid)
> > + print_uint(PRINT_ANY, "vid", " vid %u", e->vid);
> > +
> > + if (show_stats && tb && tb[MDBA_MDB_EATTR_TIMER]) {
> > + __u32 timer = rta_getattr_u32(tb[MDBA_MDB_EATTR_TIMER]);
> > +
> > + print_string(PRINT_ANY, "timer", " %s",
> > + format_timer(timer));
> > }
> > - if (jw_global)
> > - jsonw_end_object(jw_global);
> > - else
> > - fprintf(f, "\n");
> > + close_json_object();
> > }
> >
> > static void br_print_mdb_entry(FILE *f, int ifindex, struct rtattr *attr,
> > @@ -218,15 +184,60 @@ static void br_print_mdb_entry(FILE *f, int ifindex, struct rtattr *attr,
> > }
> > }
> >
> > +static void print_mdb_entries(FILE *fp, struct nlmsghdr *n,
> > + int ifindex, struct rtattr *mdb)
> > +{
> > + int rem = RTA_PAYLOAD(mdb);
> > + struct rtattr *i;
> > +
> > + open_json_array(PRINT_JSON, "mdb");
> > + for (i = RTA_DATA(mdb); RTA_OK(i, rem); i = RTA_NEXT(i, rem))
> > + br_print_mdb_entry(fp, ifindex, i, n);
> > + close_json_array(PRINT_JSON, NULL);
> > +}
> > +
> > +static void print_router_entries(FILE *fp, struct nlmsghdr *n,
> > + int ifindex, struct rtattr *router)
> > +{
> > + const char *brifname = ll_index_to_name(ifindex);
> > +
> > + open_json_array(PRINT_JSON, "router");
> > + if (n->nlmsg_type == RTM_GETMDB) {
> > + if (show_details)
> > + br_print_router_ports(fp, router, brifname);
> > + } else {
> > + struct rtattr *i = RTA_DATA(router);
> > + uint32_t *port_ifindex = RTA_DATA(i);
> > +
> > + if (is_json_context()) {
> > + open_json_array(PRINT_JSON, brifname);
> > + open_json_object(NULL);
> > +
> > + print_string(PRINT_JSON, "port", NULL,
> > + ll_index_to_name(*port_ifindex));
> > + close_json_object();
> > + close_json_array(PRINT_JSON, NULL);
> > + } else {
> > + fprintf(fp, "router port dev %s master %s\n",
> > + ll_index_to_name(*port_ifindex),
> > + brifname);
> > + }
> > + }
> > + close_json_array(PRINT_JSON, NULL);
> > +}
> > +
> > int print_mdb(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
> > {
> > FILE *fp = arg;
> > struct br_port_msg *r = NLMSG_DATA(n);
> > int len = n->nlmsg_len;
> > - struct rtattr *tb[MDBA_MAX+1], *i;
> > + struct rtattr *tb[MDBA_MAX+1];
> >
> > - if (n->nlmsg_type != RTM_GETMDB && n->nlmsg_type != RTM_NEWMDB && n->nlmsg_type != RTM_DELMDB) {
> > - fprintf(stderr, "Not RTM_GETMDB, RTM_NEWMDB or RTM_DELMDB: %08x %08x %08x\n",
> > + if (n->nlmsg_type != RTM_GETMDB &&
> > + n->nlmsg_type != RTM_NEWMDB &&
> > + n->nlmsg_type != RTM_DELMDB) {
> > + fprintf(stderr,
> > + "Not RTM_GETMDB, RTM_NEWMDB or RTM_DELMDB: %08x %08x %08x\n",
> > n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags);
> >
> > return 0;
> > @@ -243,50 +254,14 @@ int print_mdb(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
> >
> > parse_rtattr(tb, MDBA_MAX, MDBA_RTA(r), n->nlmsg_len - NLMSG_LENGTH(sizeof(*r)));
> >
> > - if (tb[MDBA_MDB] && print_mdb_entries) {
> > - int rem = RTA_PAYLOAD(tb[MDBA_MDB]);
> > + if (n->nlmsg_type == RTM_DELMDB)
> > + print_bool(PRINT_ANY, "deleted", "Deleted ", true);
> >
> > - for (i = RTA_DATA(tb[MDBA_MDB]); RTA_OK(i, rem); i = RTA_NEXT(i, rem))
> > - br_print_mdb_entry(fp, r->ifindex, i, n);
> > - }
> > + if (tb[MDBA_MDB])
> > + print_mdb_entries(fp, n, r->ifindex, tb[MDBA_MDB]);
> >
> > - if (tb[MDBA_ROUTER] && print_mdb_router) {
> > - if (n->nlmsg_type == RTM_GETMDB) {
> > - if (show_details)
> > - br_print_router_ports(fp, tb[MDBA_ROUTER],
> > - r->ifindex);
> > - } else {
> > - uint32_t *port_ifindex;
> > -
> > - i = RTA_DATA(tb[MDBA_ROUTER]);
> > - port_ifindex = RTA_DATA(i);
> > - if (n->nlmsg_type == RTM_DELMDB) {
> > - if (jw_global)
> > - jsonw_string_field(jw_global,
> > - "opCode",
> > - "deleted");
> > - else
> > - fprintf(fp, "Deleted ");
> > - }
> > - if (jw_global) {
> > - jsonw_name(jw_global,
> > - ll_index_to_name(r->ifindex));
> > - jsonw_start_array(jw_global);
> > - jsonw_start_object(jw_global);
> > - jsonw_string_field(jw_global, "port",
> > - ll_index_to_name(*port_ifindex));
> > - jsonw_end_object(jw_global);
> > - jsonw_end_array(jw_global);
> > - } else {
> > - fprintf(fp, "router port dev %s master %s\n",
> > - ll_index_to_name(*port_ifindex),
> > - ll_index_to_name(r->ifindex));
> > - }
> > - }
> > - }
> > -
> > - if (!jw_global)
> > - fflush(fp);
> > + if (tb[MDBA_ROUTER])
> > + print_router_entries(fp, n, r->ifindex, tb[MDBA_ROUTER]);
> >
> > return 0;
> > }
> > @@ -319,62 +294,21 @@ static int mdb_show(int argc, char **argv)
> > }
> > }
> >
> > + new_json_obj(json);
> > +
> > /* get mdb entries*/
> > if (rtnl_wilddump_request(&rth, PF_BRIDGE, RTM_GETMDB) < 0) {
> > perror("Cannot send dump request");
> > return -1;
> > }
> >
> > - if (!json) {
> > - /* Normal output */
> > - if (rtnl_dump_filter(&rth, print_mdb, stdout) < 0) {
> > - fprintf(stderr, "Dump terminated\n");
> > - return -1;
> > - }
> > - return 0;
> > - }
> > -
> > - /* Json output */
> > - jw_global = jsonw_new(stdout);
> > - if (!jw_global) {
> > - fprintf(stderr, "Error allocation json object\n");
> > - exit(1);
> > - }
> > -
> > - if (pretty)
> > - jsonw_pretty(jw_global, 1);
> > -
> > - jsonw_start_object(jw_global);
> > - jsonw_name(jw_global, "mdb");
> > - jsonw_start_array(jw_global);
> > -
> > - /* print mdb entries */
> > - print_mdb_entries = true;
> > - print_mdb_router = false;
> > if (rtnl_dump_filter(&rth, print_mdb, stdout) < 0) {
> > fprintf(stderr, "Dump terminated\n");
> > return -1;
> > }
> > - jsonw_end_array(jw_global);
> > -
> > - /* get router ports */
> > - if (rtnl_wilddump_request(&rth, PF_BRIDGE, RTM_GETMDB) < 0) {
> > - perror("Cannot send dump request");
> > - return -1;
> > - }
> > - jsonw_name(jw_global, "router");
> > - jsonw_start_object(jw_global);
> >
> > - /* print router ports */
> > - print_mdb_entries = false;
> > - print_mdb_router = true;
> > - if (rtnl_dump_filter(&rth, print_mdb, stdout) < 0) {
> > - fprintf(stderr, "Dump terminated\n");
> > - return -1;
> > - }
> > - jsonw_end_object(jw_global);
> > - jsonw_end_object(jw_global);
> > - jsonw_destroy(&jw_global);
> > + delete_json_obj();
> > + fflush(stdout);
> >
> > return 0;
> > }
> > diff --git a/bridge/vlan.c b/bridge/vlan.c
> > index 7c8b3ad54857..9f4a7a2be55c 100644
> > --- a/bridge/vlan.c
> > +++ b/bridge/vlan.c
> > @@ -8,19 +8,16 @@
> > #include <netinet/in.h>
> > #include <linux/if_bridge.h>
> > #include <linux/if_ether.h>
> > -#include <json_writer.h>
> > #include <string.h>
> >
> > +#include "json_print.h"
> > #include "libnetlink.h"
> > #include "br_common.h"
> > #include "utils.h"
> >
> > static unsigned int filter_index, filter_vlan;
> > -static int last_ifidx = -1;
> > static int show_vlan_tunnel_info = 0;
> >
> > -json_writer_t *jw_global;
> > -
> > static void usage(void)
> > {
> > fprintf(stderr,
> > @@ -257,38 +254,33 @@ static int filter_vlan_check(__u16 vid, __u16 flags)
> >
> > static void print_vlan_port(FILE *fp, int ifi_index)
> > {
> > - if (jw_global) {
> > - jsonw_name(jw_global,
> > - ll_index_to_name(ifi_index));
> > - jsonw_start_array(jw_global);
> > - } else {
> > - fprintf(fp, "%s",
> > - ll_index_to_name(ifi_index));
> > - }
> > + print_string(PRINT_ANY, NULL, "%s",
> > + ll_index_to_name(ifi_index));
> > }
> >
>
> Stephen, this seems to have broken both json and non-json output.
>
> Here is some output before and after the patch (same thing for tunnelshow):
>
> before:
> $bridge vlan show
> port vlan ids
> hostbond4 1000
> 1001 PVID Egress Untagged
> 1002
> 1003
> 1004
>
> hostbond3 1000 PVID Egress Untagged
> 1001
> 1002
> 1003
> 1004
>
> bridge 1 PVID Egress Untagged
> 1000
> 1001
> 1002
> 1003
> 1004
>
> vxlan0 1 PVID Egress Untagged
> 1000
> 1001
> 1002
> 1003
> 1004
>
>
> $ bridge -j -c vlan show
> {
> "hostbond4": [{
> "vlan": 1000
> },{
> "vlan": 1001,
> "flags": ["PVID","Egress Untagged"
> ]
> },{
> "vlan": 1002,
> "vlanEnd": 1004
> }
> ],
> "hostbond3": [{
> "vlan": 1000,
> "flags": ["PVID","Egress Untagged"
> ]
> },{
> "vlan": 1001,
> "vlanEnd": 1004
> }
> ],
> "bridge": [{
> "vlan": 1,
> "flags": ["PVID","Egress Untagged"
> ]
> },{
> "vlan": 1000,
> "vlanEnd": 1004
> }
> ],
> "vxlan0": [{
> "vlan": 1,
> "flags": ["PVID","Egress Untagged"
> ]
> },{
> "vlan": 1000,
> "vlanEnd": 1004
> }
> ]
> }
>
>
> after:
> ====
>
> $bridge vlan show
> port vlan ids
> hostbond4
> 1000 1001 PVID untagged 1002 1003 1004
> hostbond3
> 1000 PVID untagged 1001 1002 1003 1004
> bridge
> 1 PVID untagged 1000 1001 1002 1003 1004
> vxlan0
> 1 PVID untagged 1000 1001 1002 1003 1004
>
> $bridge -j -c vlan show
> ["hostbond4","vlan":[{"vlan":1000},{"vlan":1001,"pvid":null,"untagged":null},{"vlan":1002},{"vlan":1003},{"vlan":1004}],"hostbond3","vlan":[{"vlan":1000,"pvid":null,"untagged":null},{"vlan":1001},{"vlan":1002},{"vlan":1003},{"vlan":1004}],"bridge","vlan":[{"vlan":1,"pvid":null,"untagged":null},{"vlan":1000},{"vlan":1001},{"vlan":1002},{"vlan":1003},{"vlan":1004}],"vxlan0","vlan":[{"vlan":1,"pvid":null,"untagged":null},{"vlan":1000},{"vlan":1001},{"vlan":1002},{"vlan":1003},{"vlan":1004}]]
I can fix it.
Powered by blists - more mailing lists