[Bridge] RFC: [PATCH] bridge vlan integration
David Kimdon
david.kimdon at devicescape.com
Mon Sep 11 10:57:44 PDT 2006
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;
+}
More information about the Bridge
mailing list