]> git.ipfire.org Git - thirdparty/iproute2.git/commitdiff
bridge: vlan: add support to show global vlan options
authorNikolay Aleksandrov <nikolay@nvidia.com>
Sat, 28 Aug 2021 11:07:50 +0000 (14:07 +0300)
committerDavid Ahern <dsahern@kernel.org>
Wed, 1 Sep 2021 03:21:04 +0000 (21:21 -0600)
Add support for new bridge vlan command grouping called global which
operates on global options. The first command it supports is "show".
To do that we update print_vlan_rtm to recognize the global vlan options
attribute and parse it properly.
Man page and help are also updated with the new command.

Syntax is: $ bridge vlan global show [ vid VID ] [ dev DEV ]

Signed-off-by: Nikolay Aleksandrov <nikolay@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
bridge/br_common.h
bridge/monitor.c
bridge/vlan.c
man/man8/bridge.8

index b9adafd98deaf06a9aad8640a38f45344f0b5a2b..09f42c814918d8bfd12f0590559d0c37d6663bac 100644 (file)
@@ -12,7 +12,8 @@ int print_mdb_mon(struct nlmsghdr *n, void *arg);
 int print_fdb(struct nlmsghdr *n, void *arg);
 void print_stp_state(__u8 state);
 int parse_stp_state(const char *arg);
-int print_vlan_rtm(struct nlmsghdr *n, void *arg, bool monitor);
+int print_vlan_rtm(struct nlmsghdr *n, void *arg, bool monitor,
+                  bool global_only);
 
 int do_fdb(int argc, char **argv);
 int do_mdb(int argc, char **argv);
index 88f52f52f0840fa20d71486e48ef96848051194e..845e221abb49c4fc4125cc2e86710c15e5f143b1 100644 (file)
@@ -71,7 +71,7 @@ static int accept_msg(struct rtnl_ctrl_data *ctrl,
        case RTM_DELVLAN:
                if (prefix_banner)
                        fprintf(fp, "[VLAN]");
-               return print_vlan_rtm(n, arg, true);
+               return print_vlan_rtm(n, arg, true, false);
 
        default:
                return 0;
index 7e425428337310637b9336ef67eea222312f2c26..8a2cc306cb07fe55701aabc198df370c232641fd 100644 (file)
@@ -36,7 +36,8 @@ static void usage(void)
                "                                                     [ self ] [ master ]\n"
                "       bridge vlan { set } vid VLAN_ID dev DEV [ state STP_STATE ]\n"
                "       bridge vlan { show } [ dev DEV ] [ vid VLAN_ID ]\n"
-               "       bridge vlan { tunnelshow } [ dev DEV ] [ vid VLAN_ID ]\n");
+               "       bridge vlan { tunnelshow } [ dev DEV ] [ vid VLAN_ID ]\n"
+               "       bridge vlan global { show } [ dev DEV ] [ vid VLAN_ID ]\n");
        exit(-1);
 }
 
@@ -621,6 +622,25 @@ static int print_vlan_stats(struct nlmsghdr *n, void *arg)
        return 0;
 }
 
+static void print_vlan_global_opts(struct rtattr *a)
+{
+       struct rtattr *vtb[BRIDGE_VLANDB_GOPTS_MAX + 1];
+       __u16 vid, vrange = 0;
+
+       if ((a->rta_type & NLA_TYPE_MASK) != BRIDGE_VLANDB_GLOBAL_OPTIONS)
+               return;
+
+       parse_rtattr_flags(vtb, BRIDGE_VLANDB_GOPTS_MAX, RTA_DATA(a),
+                          RTA_PAYLOAD(a), NLA_F_NESTED);
+       vid = rta_getattr_u16(vtb[BRIDGE_VLANDB_GOPTS_ID]);
+       if (vtb[BRIDGE_VLANDB_GOPTS_RANGE])
+               vrange = rta_getattr_u16(vtb[BRIDGE_VLANDB_GOPTS_RANGE]);
+       else
+               vrange = vid;
+       print_range("vlan", vid, vrange);
+       print_nl();
+}
+
 static void print_vlan_opts(struct rtattr *a)
 {
        struct rtattr *vtb[BRIDGE_VLANDB_ENTRY_MAX + 1];
@@ -680,7 +700,7 @@ static void print_vlan_opts(struct rtattr *a)
                __print_one_vlan_stats(&vstats);
 }
 
-int print_vlan_rtm(struct nlmsghdr *n, void *arg, bool monitor)
+int print_vlan_rtm(struct nlmsghdr *n, void *arg, bool monitor, bool global_only)
 {
        struct br_vlan_msg *bvm = NLMSG_DATA(n);
        int len = n->nlmsg_len;
@@ -722,7 +742,8 @@ int print_vlan_rtm(struct nlmsghdr *n, void *arg, bool monitor)
                unsigned short rta_type = a->rta_type & NLA_TYPE_MASK;
 
                /* skip unknown attributes */
-               if (rta_type > BRIDGE_VLANDB_MAX)
+               if (rta_type > BRIDGE_VLANDB_MAX ||
+                   (global_only && rta_type != BRIDGE_VLANDB_GLOBAL_OPTIONS))
                        continue;
 
                if (vlan_rtm_cur_ifidx != bvm->ifindex) {
@@ -737,6 +758,9 @@ int print_vlan_rtm(struct nlmsghdr *n, void *arg, bool monitor)
                case BRIDGE_VLANDB_ENTRY:
                        print_vlan_opts(a);
                        break;
+               case BRIDGE_VLANDB_GLOBAL_OPTIONS:
+                       print_vlan_global_opts(a);
+                       break;
                }
                close_json_object();
        }
@@ -746,7 +770,12 @@ int print_vlan_rtm(struct nlmsghdr *n, void *arg, bool monitor)
 
 static int print_vlan_rtm_filter(struct nlmsghdr *n, void *arg)
 {
-       return print_vlan_rtm(n, arg, false);
+       return print_vlan_rtm(n, arg, false, false);
+}
+
+static int print_vlan_rtm_global_filter(struct nlmsghdr *n, void *arg)
+{
+       return print_vlan_rtm(n, arg, false, true);
 }
 
 static int vlan_show(int argc, char **argv, int subject)
@@ -864,6 +893,61 @@ out:
        return 0;
 }
 
+static int vlan_global_show(int argc, char **argv)
+{
+       __u32 dump_flags = BRIDGE_VLANDB_DUMPF_GLOBAL;
+       int ret = 0, subject = VLAN_SHOW_VLAN;
+       char *filter_dev = NULL;
+
+       while (argc > 0) {
+               if (strcmp(*argv, "dev") == 0) {
+                       NEXT_ARG();
+                       if (filter_dev)
+                               duparg("dev", *argv);
+                       filter_dev = *argv;
+               } else if (strcmp(*argv, "vid") == 0) {
+                       NEXT_ARG();
+                       if (filter_vlan)
+                               duparg("vid", *argv);
+                       filter_vlan = atoi(*argv);
+               }
+               argc--; argv++;
+       }
+
+       if (filter_dev) {
+               filter_index = ll_name_to_index(filter_dev);
+               if (!filter_index)
+                       return nodev(filter_dev);
+       }
+
+       new_json_obj(json);
+
+       if (rtnl_brvlandump_req(&rth, PF_BRIDGE, dump_flags) < 0) {
+               perror("Cannot send dump request");
+               exit(1);
+       }
+
+       if (!is_json_context()) {
+               printf("%-" __stringify(IFNAMSIZ) "s  %-"
+                      __stringify(VLAN_ID_LEN) "s", "port",
+                      "vlan-id");
+               printf("\n");
+       }
+
+       ret = rtnl_dump_filter(&rth, print_vlan_rtm_global_filter, &subject);
+       if (ret < 0) {
+               fprintf(stderr, "Dump terminated\n");
+               exit(1);
+       }
+
+       if (vlan_rtm_cur_ifidx != -1)
+               close_vlan_port();
+
+       delete_json_obj();
+       fflush(stdout);
+       return 0;
+}
+
 void print_vlan_info(struct rtattr *tb, int ifindex)
 {
        struct rtattr *i, *list = tb;
@@ -908,6 +992,22 @@ void print_vlan_info(struct rtattr *tb, int ifindex)
                close_vlan_port();
 }
 
+static int vlan_global(int argc, char **argv)
+{
+       if (argc > 0) {
+               if (strcmp(*argv, "show") == 0 ||
+                   strcmp(*argv, "lst") == 0 ||
+                   strcmp(*argv, "list") == 0)
+                       return vlan_global_show(argc-1, argv+1);
+               else
+                       usage();
+       } else {
+               return vlan_global_show(0, NULL);
+       }
+
+       return 0;
+}
+
 int do_vlan(int argc, char **argv)
 {
        ll_init_map(&rth);
@@ -926,6 +1026,8 @@ int do_vlan(int argc, char **argv)
                }
                if (matches(*argv, "set") == 0)
                        return vlan_option_set(argc-1, argv+1);
+               if (strcmp(*argv, "global") == 0)
+                       return vlan_global(argc-1, argv+1);
                if (matches(*argv, "help") == 0)
                        usage();
        } else {
index eec7df4383bc96e1eca50bac0089058f333f2a8e..9ec4cb1dec674af3254a72159a0d72d4dbcf3736 100644 (file)
@@ -152,6 +152,13 @@ bridge \- show / manipulate bridge addresses and devices
 .B dev
 .IR DEV " ]"
 
+.ti -8
+.BR "bridge vlan global" " [ " show " ] [ "
+.B dev
+.IR DEV " ] [ "
+.B vid
+.IR VID " ]"
+
 .ti -8
 .BR "bridge monitor" " [ " all " | " neigh " | " link " | " mdb " | " vlan " ]"
 
@@ -895,6 +902,20 @@ option, the command displays per-vlan traffic statistics.
 
 This command displays the current vlan tunnel info mapping.
 
+.SS bridge vlan global show - list global vlan options.
+
+This command displays the global VLAN options for each VLAN entry.
+
+.TP
+.BI dev " DEV"
+the interface only whose VLAN global options should be listed. Default is to list
+all bridge interfaces.
+
+.TP
+.BI vid " VID"
+the VLAN ID only whose global options should be listed. Default is to list
+all vlans.
+
 .SH bridge monitor - state monitoring
 
 The