]> git.proxmox.com Git - mirror_iproute2.git/commitdiff
bridge: add json support for bridge vlan show
authorRoopa Prabhu <roopa@cumulusnetworks.com>
Wed, 22 Jun 2016 13:45:52 +0000 (06:45 -0700)
committerStephen Hemminger <shemming@brocade.com>
Wed, 20 Jul 2016 19:02:02 +0000 (12:02 -0700)
$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@cumulusnetworks.com>
bridge/br_common.h
bridge/bridge.c
bridge/vlan.c

index 5ea45c9e654d78adf716f770a1c1b91b94ca063c..c649e7d9f107115b6c45a8d158cbeceda88c3b38 100644 (file)
@@ -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;
index 72f153f2bd65d42e68db7bf75d99c47abf7b58e1..5ff038d672ad26459f2f8992898e8589bcff0e65 100644 (file)
@@ -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++;
index a8a2e1d953c6e6e7b1011ede87d7fb7ccbd2b8e2..f34e84a2a48f4de70920dfede5005a9bd1e85b7b 100644 (file)
@@ -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,27 @@ static int vlan_show(int argc, char **argv)
                exit(1);
        }
 
-       printf("port\tvlan ids\n");
+       if (json_output) {
+               jw_global = jsonw_new(stdout);
+               if (!jw_global) {
+                       fprintf(stderr, "Error allocation json object\n");
+                       exit(1);
+               }
+               jsonw_start_object(jw_global);
+       } 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_end_object(jw_global);
+               jsonw_destroy(&jw_global);
+       }
+
        return 0;
 }