[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <1466491187-8536-3-git-send-email-roopa@cumulusnetworks.com>
Date: Mon, 20 Jun 2016 23:39:44 -0700
From: Roopa Prabhu <roopa@...ulusnetworks.com>
To: stephen@...workplumber.org, netdev@...r.kernel.org
Cc: anuradhak@...ulusnetworks.com, nikolay@...ulusnetworks.com,
julien@...ulusnetworks.com
Subject: [PATCH iproute2 net-next v3 2/5] bridge: add json support for bridge vlan show
From: Roopa Prabhu <roopa@...ulusnetworks.com>
$bridge -c vlan show
port vlan ids
swp1 1 PVID Egress Untagged
10-13
swp2 1 PVID Egress Untagged
10-13
br0 1 PVID Egress Untagged
$bridge -json vlan show
{
"swp1": [{
"vlan": 1,
"flags": ["PVID","Egress Untagged"
]
},{
"vlan": 10
},{
"vlan": 11
},{
"vlan": 12
},{
"vlan": 13
}
],
"swp2": [{
"vlan": 1,
"flags": ["PVID","Egress Untagged"
]
},{
"vlan": 10
},{
"vlan": 11
},{
"vlan": 12
},{
"vlan": 13
}
],
"br0": [{
"vlan": 1,
"flags": ["PVID","Egress Untagged"
]
}
]
}
$bridge -c -json vlan show
{
"swp1": [{
"vlan": 1,
"flags": ["PVID","Egress Untagged"
]
},{
"vlan": 10,
"vlanEnd": 13
}
],
"swp2": [{
"vlan": 1,
"flags": ["PVID","Egress Untagged"
]
},{
"vlan": 10,
"vlanEnd": 13
}
],
"br0": [{
"vlan": 1,
"flags": ["PVID","Egress Untagged"
]
}
]
}
Signed-off-by: Roopa Prabhu <roopa@...ulusnetworks.com>
---
bridge/br_common.h | 1 +
bridge/bridge.c | 5 ++-
bridge/vlan.c | 106 ++++++++++++++++++++++++++++++++++++++++++++++-------
3 files changed, 97 insertions(+), 15 deletions(-)
diff --git a/bridge/br_common.h b/bridge/br_common.h
index 5ea45c9..c649e7d 100644
--- a/bridge/br_common.h
+++ b/bridge/br_common.h
@@ -23,4 +23,5 @@ extern int show_stats;
extern int show_details;
extern int timestamp;
extern int compress_vlans;
+extern int json_output;
extern struct rtnl_handle rth;
diff --git a/bridge/bridge.c b/bridge/bridge.c
index 72f153f..5ff038d 100644
--- a/bridge/bridge.c
+++ b/bridge/bridge.c
@@ -23,6 +23,7 @@ int oneline;
int show_stats;
int show_details;
int compress_vlans;
+int json_output;
int timestamp;
char *batch_file;
int force;
@@ -38,7 +39,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] }\n");
+" -c[ompressvlans] -j{son} }\n");
exit(-1);
}
@@ -173,6 +174,8 @@ main(int argc, char **argv)
++compress_vlans;
} else if (matches(opt, "-force") == 0) {
++force;
+ } else if (matches(opt, "-json") == 0) {
+ ++json_output;
} else if (matches(opt, "-batch") == 0) {
argc--;
argv++;
diff --git a/bridge/vlan.c b/bridge/vlan.c
index 717025a..fbf14c8 100644
--- a/bridge/vlan.c
+++ b/bridge/vlan.c
@@ -7,6 +7,7 @@
#include <netinet/in.h>
#include <linux/if_bridge.h>
#include <linux/if_ether.h>
+#include <json_writer.h>
#include <string.h>
#include "libnetlink.h"
@@ -15,6 +16,8 @@
static unsigned int filter_index, filter_vlan;
+json_writer_t *jw_global = NULL;
+
static void usage(void)
{
fprintf(stderr, "Usage: bridge vlan { add | del } vid VLAN_ID dev DEV [ pvid] [ untagged ]\n");
@@ -158,6 +161,28 @@ static int filter_vlan_check(struct bridge_vlan_info *vinfo)
return 1;
}
+static void print_vlan_port(FILE *fp, int ifi_index)
+{
+ if (jw_global) {
+ jsonw_pretty(jw_global, 1);
+ 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));
+ }
+}
+
+static void start_json_vlan_flags_array(bool *vlan_flags)
+{
+ if (*vlan_flags)
+ return;
+ jsonw_name(jw_global, "flags");
+ jsonw_start_array(jw_global);
+ *vlan_flags = true;
+}
+
static int print_vlan(const struct sockaddr_nl *who,
struct nlmsghdr *n,
void *arg)
@@ -166,6 +191,8 @@ static int print_vlan(const struct sockaddr_nl *who,
struct ifinfomsg *ifm = NLMSG_DATA(n);
int len = n->nlmsg_len;
struct rtattr *tb[IFLA_MAX+1];
+ bool vlan_flags;
+ char flags[80];
if (n->nlmsg_type != RTM_NEWLINK) {
fprintf(stderr, "Not RTM_NEWLINK: %08x %08x %08x\n",
@@ -199,7 +226,8 @@ static int print_vlan(const struct sockaddr_nl *who,
__u16 last_vid_start = 0;
if (!filter_vlan)
- fprintf(fp, "%s", ll_index_to_name(ifm->ifi_index));
+ print_vlan_port(fp, ifm->ifi_index);
+
for (i = RTA_DATA(list); RTA_OK(i, rem); i = RTA_NEXT(i, rem)) {
struct bridge_vlan_info *vinfo;
int vcheck_ret;
@@ -218,20 +246,58 @@ static int print_vlan(const struct sockaddr_nl *who,
continue;
if (filter_vlan)
- fprintf(fp, "%s",
- ll_index_to_name(ifm->ifi_index));
- fprintf(fp, "\t %hu", last_vid_start);
- if (last_vid_start != vinfo->vid)
- fprintf(fp, "-%hu", vinfo->vid);
- if (vinfo->flags & BRIDGE_VLAN_INFO_PVID)
- fprintf(fp, " PVID");
- if (vinfo->flags & BRIDGE_VLAN_INFO_UNTAGGED)
- fprintf(fp, " Egress Untagged");
- fprintf(fp, "\n");
+ print_vlan_port(fp, ifm->ifi_index);
+ if (jw_global) {
+ jsonw_start_object(jw_global);
+ jsonw_uint_field(jw_global, "vlan",
+ last_vid_start);
+ if (vinfo->flags & BRIDGE_VLAN_INFO_RANGE_BEGIN)
+ continue;
+ } else {
+ fprintf(fp, "\t %hu", last_vid_start);
+ }
+ if (last_vid_start != vinfo->vid) {
+ if (jw_global)
+ jsonw_uint_field(jw_global, "vlanEnd",
+ vinfo->vid);
+ else
+ fprintf(fp, "-%hu", vinfo->vid);
+ }
+ if (vinfo->flags & BRIDGE_VLAN_INFO_PVID) {
+ if (jw_global) {
+ start_json_vlan_flags_array(&vlan_flags);
+ jsonw_string(jw_global, "PVID");
+ } else {
+ fprintf(fp, " PVID");
+ }
+ }
+ if (vinfo->flags & BRIDGE_VLAN_INFO_UNTAGGED) {
+ if (jw_global) {
+ start_json_vlan_flags_array(&vlan_flags);
+ jsonw_string(jw_global,
+ "Egress Untagged");
+ } else {
+ fprintf(fp, " Egress Untagged");
+ }
+ }
+ if (vlan_flags) {
+ jsonw_end_array(jw_global);
+ vlan_flags = false;
+ }
+
+ if (jw_global)
+ jsonw_end_object(jw_global);
+ else
+ fprintf(fp, "\n");
}
}
- if (!filter_vlan)
- fprintf(fp, "\n");
+ if (!filter_vlan) {
+ if (jw_global)
+ jsonw_end_array(jw_global);
+ else
+ fprintf(fp, "\n");
+
+ }
fflush(fp);
return 0;
}
@@ -271,12 +337,24 @@ static int vlan_show(int argc, char **argv)
exit(1);
}
- printf("port\tvlan ids\n");
+ if (json_output) {
+ jw_global = jsonw_new_object(stdout);
+ if (!jw_global) {
+ fprintf(stderr, "Error allocation json object\n");
+ exit(1);
+ }
+ } else {
+ printf("port\tvlan ids\n");
+ }
+
if (rtnl_dump_filter(&rth, print_vlan, stdout) < 0) {
fprintf(stderr, "Dump ternminated\n");
exit(1);
}
+ if (jw_global)
+ jsonw_destroy(&jw_global);
+
return 0;
}
--
1.9.1
Powered by blists - more mailing lists