Hi,

Here is the corresponding patch to brctl.

-David

Index: bridge-utils-1.1/brctl/brctl_cmd.c
===================================================================
--- bridge-utils-1.1.orig/brctl/brctl_cmd.c
+++ bridge-utils-1.1/brctl/brctl_cmd.c
@@ -390,6 +390,105 @@ static int br_cmd_showmacs(int argc, cha
        return 0;
 }
 
+static int br_cmd_setuntagged(int argc, char*const* argv)
+{
+       int vlan_id, err;
+
+       if (!strcmp(argv[3], "none"))
+               vlan_id = 0;
+       else    if (sscanf(argv[3], "%i", &vlan_id) != 1 ||
+                       vlan_id < 1 || vlan_id > 4094) {
+               fprintf(stderr, "vlan id must be 'none' or from 1 to 4094\n");
+               return 1;
+       }
+
+       if (!strcmp(argv[2], "local"))
+               err = br_set_port_untagged_vlan(argv[1], 0, vlan_id);
+       else
+               err = br_set_port_untagged_vlan(argv[1], argv[2], vlan_id);
+
+       if (err)
+               fprintf(stderr, "set untagged vlan failed: %s\n",
+                       strerror(err));
+       return err != 0;
+}
+
+static int br_cmd_vlanfilter(char*const* argv, int (*func)(const char *, const 
char *, unsigned int))
+{
+       int vlan_id, err;
+
+       if (!strcmp(argv[3], "all"))
+               vlan_id = 0;
+       else    if (sscanf(argv[3], "%i", &vlan_id) != 1 ||
+                       vlan_id < 1 || vlan_id > 4094) {
+               fprintf(stderr, "vlan id must be 'all' or from 1 to 4094\n");
+               return 1;
+       }
+
+       err = func(argv[1], strcmp(argv[2], "local")?argv[2]:0, vlan_id);
+       if (err)
+               fprintf(stderr, "set vlan filter failed: %s\n",
+                       strerror(err));
+       return err != 0;
+}
+
+static int br_cmd_addvlan(int argc, char*const* argv)
+{
+       return br_cmd_vlanfilter(argv, br_add_vlan);
+}
+
+static int br_cmd_delvlan(int argc, char*const* argv)
+{
+       return br_cmd_vlanfilter(argv, br_del_vlan);
+}
+
+int show_port_vlan(const char *brname, const char *port,
+                                          void *arg )
+{
+       int err, count = 0, i;
+       struct vlan_info v;
+
+       err = br_get_port_vlan_info(brname, port, &v);
+       if (err)
+               fprintf(stderr, "get single vlan failed: %s\n",
+                       strerror(err));
+
+       printf("%s\t", port?port:brname);
+
+       if (v.untagged)
+               printf("%d\t\t", v.untagged);
+       else
+               printf("none\t\t");
+
+       for(i = 1; i < 4095; i++)
+               if (v.filter[i / 8] & (1 << (i & 7)))
+                       count++;
+
+       if (count == 4094)
+               printf("all\n");
+       else if (count == 0)
+               printf("none\n");
+       else {
+               int first = 1;
+
+               for(i = 1; i < 4095; i++)
+                       if (v.filter[i / 8] & (1 << (i & 7))) {
+                               printf("%s%d", first?"":", ", i);
+                               first = 0;
+                       }
+               printf("\n");
+       }
+
+       return err != 0;
+}
+
+static int br_cmd_showvlans(int argc, char*const* argv)
+{
+       printf("Port\tUntagged vlan\tEnabled Vlans\n");
+       show_port_vlan(argv[1], 0, 0);
+       return br_foreach_port(argv[1], show_port_vlan, 0);
+}
+
 static const struct command commands[] = {
        { 1, "addbr", br_cmd_addbr, "<bridge>\t\tadd bridge" },
        { 1, "delbr", br_cmd_delbr, "<bridge>\t\tdelete bridge" },
@@ -418,6 +517,14 @@ static const struct command commands[] =
          "<bridge>\t\tshow bridge stp info"},
        { 2, "stp", br_cmd_stp,
          "<bridge> {on|off}\tturn stp on/off" },
+       { 3, "setuntagged", br_cmd_setuntagged,
+         "<bridge> <port>|local <vlan_id>|none\tset untagged vlan id" },
+       { 3, "addvlan", br_cmd_addvlan,
+         "<bridge> <port>|local <vlan_id>|all\tenable specific or all vlans" },
+       { 3, "delvlan", br_cmd_delvlan,
+         "<bridge> <port>|local <vlan_id>|all\tdisable specific or all vlans" 
},
+       { 1, "showvlans", br_cmd_showvlans,
+         "<bridge>\t\tshow vlan info"},
 };
 
 const struct command *command_lookup(const char *cmd)
Index: bridge-utils-1.1/libbridge/libbridge.h
===================================================================
--- bridge-utils-1.1.orig/libbridge/libbridge.h
+++ bridge-utils-1.1/libbridge/libbridge.h
@@ -76,6 +76,12 @@ struct port_info
        struct timeval hold_timer_value;
 };
 
+struct vlan_info
+{
+       unsigned untagged;
+       unsigned char filter[4096/8];
+};
+
 extern int br_init(void);
 extern int br_refresh(void);
 extern void br_shutdown(void);
@@ -107,4 +113,13 @@ extern int br_set_path_cost(const char *
                            int path_cost);
 extern int br_read_fdb(const char *br, struct fdb_entry *fdbs, 
                       unsigned long skip, int num);
+
+int br_set_port_untagged_vlan(const char *brname, const char *port,
+                    unsigned int vlan_id);
+int br_add_vlan(const char *brname, const char *port,
+                    unsigned int vlan_id);
+int br_del_vlan(const char *brname, const char *port,
+                    unsigned int vlan_id);
+int br_get_port_vlan_info(const char *brname, const char *port,
+                    struct vlan_info *info);
 #endif
Index: bridge-utils-1.1/libbridge/libbridge_devif.c
===================================================================
--- bridge-utils-1.1.orig/libbridge/libbridge_devif.c
+++ bridge-utils-1.1/libbridge/libbridge_devif.c
@@ -506,3 +506,129 @@ int br_read_fdb(const char *bridge, stru
        
        return n;
 }
+
+static int br_dev_ioctl(const char *br_name, unsigned long cmd,
+       unsigned long arg0, unsigned long arg1, unsigned long arg2)
+{
+       int fd;
+       struct ifreq ifr;
+       unsigned long args[4];
+       int rv;
+
+       if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+               perror("socket[AF_INET,SOCK_STREAM]");
+               return -1;
+       }
+
+       args[0] = cmd;
+       args[1] = arg0;
+       args[2] = arg1;
+       args[3] = arg2;
+
+       strncpy(ifr.ifr_name, br_name, sizeof(ifr.ifr_name));
+       ifr.ifr_data = (__caddr_t) args;
+
+       rv = ioctl(fd, SIOCDEVPRIVATE, &ifr);
+
+       if (rv) {
+               perror("ioctl[SIOCDEVPRIVATE]");
+               close(fd);
+               return -1;
+       }
+
+       close(fd);
+       return 0;
+}
+
+int br_set_port_untagged_vlan(const char *brname, const char *port,
+                    unsigned int vlan_id)
+{
+       int index;
+
+       if (port) {
+               index = get_portno(brname, port);
+               if (index < 1)
+                       return errno;
+       } else
+               index = 0;
+
+       if (br_dev_ioctl(brname, BRCTL_SET_PORT_UNTAGGED_VLAN,
+               index, vlan_id, 0)) {
+               dprintf("can't set port %s(%d) untagged vlan %s\n",
+                       brname, index, strerror(errno));
+               return errno;
+       }
+
+       return 0;
+}
+
+int br_add_vlan(const char *brname, const char *port,
+                    unsigned int vlan_id)
+{
+       int index;
+
+       if (port) {
+               index = get_portno(brname, port);
+               if (index < 1)
+                       return errno;
+       } else
+               index = 0;
+
+       if (br_dev_ioctl(brname, BRCTL_ADD_PORT_VLAN,
+               index, vlan_id, 0)) {
+               dprintf("can't add vlan %d on port %s(%d)  %s\n",
+                       vlan_id, brname, index, strerror(errno));
+               return errno;
+       }
+
+       return 0;
+}
+
+int br_del_vlan(const char *brname, const char *port,
+                    unsigned int vlan_id)
+{
+       int index;
+
+       if (port) {
+               index = get_portno(brname, port);
+               if (index < 1)
+                       return errno;
+       } else
+               index = 0;
+
+       if (br_dev_ioctl(brname, BRCTL_DEL_PORT_VLAN,
+               index, vlan_id, 0)) {
+               dprintf("can't delete vlan %d on port %s(%d)  %s\n",
+                       vlan_id, brname, index, strerror(errno));
+               return errno;
+       }
+
+       return 0;
+}
+
+int br_get_port_vlan_info(const char *brname, const char *port,
+                    struct vlan_info *info)
+{
+       struct __vlan_info i;
+       int index = 0;
+
+       memset(info, 0, sizeof(*info));
+
+       if (port) {
+               index = get_portno(brname, port);
+               if (index < 1)
+                       return errno;
+       } else
+               index = 0;
+
+       if (br_dev_ioctl(brname, BRCTL_GET_PORT_VLAN_INFO,
+               (unsigned long) &i, index, 0)) {
+               dprintf("old can't get port %s(%d) info %s\n",
+                       brname, index, strerror(errno));
+               return errno;
+       }
+
+       info->untagged = i.untagged;
+       memcpy(&info->filter, &i.filter, 4096/8);
+       return 0;
+}
_______________________________________________
Bridge mailing list
[email protected]
https://lists.osdl.org/mailman/listinfo/bridge

Reply via email to