[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