changeset 339:b394a6b57a75

Update switchctl to get/set port based VLAN bits.
author ray@terran.dlink.ua
date Sun, 12 Feb 2012 16:48:16 +0200
parents 7dbf1516e36b
children 23478a9ef9b5
files head/sbin/switchctl/switchctl.c
diffstat 1 files changed, 213 insertions(+), 166 deletions(-) [+]
line wrap: on
line diff
--- a/head/sbin/switchctl/switchctl.c	Sun Feb 12 16:47:12 2012 +0200
+++ b/head/sbin/switchctl/switchctl.c	Sun Feb 12 16:48:16 2012 +0200
@@ -22,53 +22,12 @@
 
 int	get_vlan_config(struct info *, int fd, int argc, char **argv);
 int	set_vlan_config(struct info *, int fd, int argc, char **argv);
+int	get_pbvlan_config(struct info *, int fd, int argc, char **argv);
+int	set_pbvlan_config(struct info *, int fd, int argc, char **argv);
 int	get_port(struct info *, int fd, int argc, char **argv);
 int	set_port(struct info *, int fd, int argc, char **argv);
 int	get_reg(struct info *info, int fd, int argc, char **argv);
 int	set_reg(struct info *info, int fd, int argc, char **argv);
-#if 0
-		    case 'I': /* IngressCheck */
-		    case 'Q': /* Q-in-Q */
-		    case 'L': /* LAN */
-		    case 'W': /* WAN */
-		    case 'T': /* Global Tagged */
-		    case 'U': /* Global Untagged */
-
-
-get reg 0x100
-set reg 0x100 0x1230 
-get port 7
-set port 7 pvid 17 flags WAN Q-in-Q IngressCheck
-set vlan 7 add port 3 t/u/f
-set vlan 7 del port 3
-get vlan 7
-
-
-set	 - can be placed anywhere before value
-get/show - ------- << --------
-
-reg	N	+ N
-----------------+------------------------------------
-port	NRANGE	+ pvid	N
-----------------+------------------------------------
-		+ flags	WAN
-		+	Q-in-Q
-		+	IngressCheck
-----------------+------------------------------------
-vlan	N	+ vid	N
-		+ add	port	NRANGE	tagged
-		+			untagged
-		+			forbidden
-		+ del	port	NRANGE
-
-struct sm {
-	int		action;	/* get - 0, set - 1 */
-	uint32_t	reg;
-	uint32_t	ports;	/* ports bitmap, so "add port" will OR this value, "delete port" will MASK it */
-	uint16_t	vlan;
-} *sm_p;
-
-#endif
 
 int
 main(int argc, char **argv)
@@ -168,6 +127,9 @@
 		if (argc >= 4 && strcasecmp(argv[3], "vlan") == 0) {
 			get_vlan_config(&info, fd, argc, argv);
 		}
+		if (argc >= 4 && strcasecmp(argv[3], "pbvlan") == 0) {
+			get_pbvlan_config(&info, fd, argc, argv);
+		}
 		if (argc >= 4 && strcasecmp(argv[3], "port") == 0) {
 			get_port(&info, fd, argc, argv);
 		}
@@ -178,6 +140,9 @@
 		if (argc >= 4 && strcasecmp(argv[3], "vlan") == 0) {
 			set_vlan_config(&info, fd, argc, argv);
 		}
+		if (argc >= 4 && strcasecmp(argv[3], "pbvlan") == 0) {
+			set_pbvlan_config(&info, fd, argc, argv);
+		}
 		if (argc >= 4 && strcasecmp(argv[3], "port") == 0) {
 			set_port(&info, fd, argc, argv);
 		}
@@ -328,12 +293,16 @@
 	return (1);
 }
 
+/* Shortcuts */
+#define	DVPF_DOUBLE_TAG DOT1Q_VLAN_PORT_FLAG_DOUBLE_TAG
+#define	DVPF_UNTAGGED DOT1Q_VLAN_PORT_FLAG_UNTAGGED
+
 int
 set_port(struct info *info, int fd, int argc, char **argv)
 {
 	struct vlan_port_config vlan_port;
 	uint32_t port_flags;
-	int i, port_flags_set;
+	int i, idx, port_flags_set;
 
 	port_flags = 0;
 	port_flags_set = 0;
@@ -342,84 +311,100 @@
 	vlan_port.vlan_type = VLAN_TYPE_DOT1Q;
 
 	/* set port 7 pvid 17 flags WAN Q-in-Q IngressCheck */
-	if (argc >= 5) {
-		int idx = strtoul(argv[4], 0, 0);
-		vlan_port.index = idx;
+	if (argc < 5)
+		return (0);
 
-		vlan_port.cmd = 0;
-		/* Get current port config */
-		if (ioctl(fd, IOCTL_VLAN_PORT_CONFIG,	&vlan_port) == -1)
-		    err(1, "error from IOCTL_VLAN_PORT_CONFIG");
+	idx = strtoul(argv[4], 0, 0);
+	vlan_port.index = idx;
 
+	vlan_port.cmd = 0;
+	/* Get current port config */
+	if (ioctl(fd, IOCTL_VLAN_PORT_CONFIG,	&vlan_port) == -1)
+	    err(1, "error from IOCTL_VLAN_PORT_CONFIG");
 
-		for (i = 5; i < argc; i++) {
-			if (argv[i] && argv[i+1] && strcasecmp(argv[i], "pvid") == 0 && strtoul(argv[i+1], 0, 0)) {
-				i ++; /* Skip to argument */
-				vlan_port.d.dot1q.vid = strtoul(argv[i], 0, 0);
-				/* XXX check parsing error */
-			} else if (argv[i] && argv[i+1] && strcasecmp(argv[i], "flags") == 0) {
-				i ++; /* Skip to argument */
-				while (i < argc && argv[i]) {
-					switch (argv[i][0]) {
-					case 'I': /* IngressCheck */
+	for (i = 5; i < argc; i++) {
+		if (argv[i] && argv[i+1] &&
+		    strcasecmp(argv[i], "pvid") == 0 &&
+		    strtoul(argv[i+1], 0, 0)) {
+			i ++; /* Skip to argument */
+			vlan_port.d.dot1q.vid = strtoul(argv[i], 0, 0);
+			/* XXX check parsing error */
+		} else if (argv[i] && argv[i+1] &&
+			   strcasecmp(argv[i], "flags") == 0) {
+			i ++; /* Skip to argument */
+			while (i < argc && argv[i]) {
+				switch (argv[i][0]) {
+				case 'I': /* IngressCheck */
+					port_flags_set++;
+					port_flags |=
+					   DOT1Q_VLAN_PORT_FLAG_INGRESS;
+					break;
+				case 'Q': /* Q-in-Q */
+					if (info->cap->vlan &
+					    SWITCH_CAPS_VLAN_DOUBLE_TAG) {
+						port_flags_set++;
+						port_flags |= DVPF_DOUBLE_TAG;
+					} else
+						printf("This switch don`t "
+						    "support Q-in-Q\n");
+					break;
+				case 'L': /* LAN */
+					if (info->cap->vlan &
+					    SWITCH_CAPS_VLAN_LAN_WAN) {
 						port_flags_set++;
-						port_flags |= DOT1Q_VLAN_PORT_FLAG_INGRESS;
-						break;
-					case 'Q': /* Q-in-Q */
-						if (info->cap->vlan & SWITCH_CAPS_VLAN_DOUBLE_TAG) {
-							port_flags_set++;
-							port_flags |= DOT1Q_VLAN_PORT_FLAG_DOUBLE_TAG;
-						} else
-						    printf("This switch can`t do Q-in-Q\n");
-						break;
-					case 'L': /* LAN */
-						if (info->cap->vlan & SWITCH_CAPS_VLAN_LAN_WAN) {
-							port_flags_set++;
-							port_flags |= DOT1Q_VLAN_PORT_FLAG_LAN;
-						} else
-						    printf("This switch can`t split ports for WAN/LAN\n");
-						break;
-					case 'W': /* WAN */
-						if (info->cap->vlan & SWITCH_CAPS_VLAN_LAN_WAN) {
-							port_flags_set++;
-							port_flags |= DOT1Q_VLAN_PORT_FLAG_WAN;
-						} else
-						    printf("This switch can`t split ports for WAN/LAN\n");
-						break;
-					case 'T': /* Global Tagged */
-						if (info->cap->vlan & SWITCH_CAPS_VLAN_GLBL_UNTG) {
-							port_flags_set++;
-							port_flags |= DOT1Q_VLAN_PORT_FLAG_TAGGED;
-							printf("Set to Tagged\n");
-						} else
-						    printf("This switch can`t do global tagging\n");
-						break;
-					case 'U': /* Global Untagged */
-						if (info->cap->vlan & SWITCH_CAPS_VLAN_GLBL_UNTG) {
-							port_flags_set++;
-							port_flags |= DOT1Q_VLAN_PORT_FLAG_UNTAGGED;
-							printf("Set to UnTagged\n");
-						} else
-						    printf("This switch can`t do global tagging\n");
-						break;
-					default:
-						err(1, "Illegal flag %s\n", argv[i]);
-					}
-					i++;
+						port_flags |=
+						    DOT1Q_VLAN_PORT_FLAG_LAN;
+					} else
+						printf("This switch can`t split"
+						    " ports for WAN/LAN\n");
+					break;
+				case 'W': /* WAN */
+					if (info->cap->vlan &
+					    SWITCH_CAPS_VLAN_LAN_WAN) {
+						port_flags_set++;
+						port_flags |=
+						    DOT1Q_VLAN_PORT_FLAG_WAN;
+					} else
+						printf("This switch can`t "
+						    "split ports for "
+						    "WAN/LAN\n");
+					break;
+				case 'T': /* Global Tagged */
+					if (info->cap->vlan &
+					    SWITCH_CAPS_VLAN_GLBL_UNTG) {
+						port_flags_set++;
+						port_flags |=
+						    DOT1Q_VLAN_PORT_FLAG_TAGGED;
+						printf("Set to Tagged\n");
+					} else
+						printf("This switch can`t do "
+						    "global tagging\n");
+					break;
+				case 'U': /* Global Untagged */
+					if (info->cap->vlan &
+					    SWITCH_CAPS_VLAN_GLBL_UNTG) {
+						port_flags_set++;
+						port_flags |= DVPF_UNTAGGED;
+						printf("Set to UnTagged\n");
+					} else
+						printf("This switch can`t do "
+						    "global tagging\n");
+					break;
+				default:
+					err(1, "Illegal flag %s\n", argv[i]);
 				}
-			} else {
-				err(1, "Unknown field \"%s\"\n", argv[i]);
+				i++;
 			}
+		} else {
+			err(1, "Unknown field \"%s\"\n", argv[i]);
 		}
+	}
 
-		vlan_port.cmd = 1;
-		if (port_flags_set > 0)
-			vlan_port.d.dot1q.flags = port_flags;
-		if (ioctl(fd, IOCTL_VLAN_PORT_CONFIG,	&vlan_port) == -1)
-			err(1, "error from IOCTL_VLAN_PORT_CONFIG");
-
-
-	}
+	vlan_port.cmd = 1;
+	if (port_flags_set > 0)
+		vlan_port.d.dot1q.flags = port_flags;
+	if (ioctl(fd, IOCTL_VLAN_PORT_CONFIG,	&vlan_port) == -1)
+		err(1, "error from IOCTL_VLAN_PORT_CONFIG");
 
 	return (0);
 }
@@ -429,7 +414,7 @@
 {
 	struct vlan_vlan_config vlan;
 	char *check;
-	int i;
+	int i, idx;
 
 	bzero(&vlan, sizeof(vlan));
 	vlan.version = 0;
@@ -439,72 +424,134 @@
 	/* vlan 7 add port 3 t/u/f */
 	/* vlan 7 del port 3 */
 
-	if (argc >= 5) {
-		int idx = strtoul(argv[4], &check, 0);
-
-		if (check != (argv[4] + strlen(argv[4])))
-			return (1);
-
-		vlan.index = idx;
+	if (argc < 5)
+		return (1);
+	idx = strtoul(argv[4], &check, 0);
 
-		if (ioctl(fd, IOCTL_VLAN_VLAN_CONFIG,	&vlan) == -1) {
-			warn("error from IOCTL_VLAN_VLAN_CONFIG");
-		}
+	if (check != (argv[4] + strlen(argv[4])))
+		return (1);
 
-		if (argc >= 7) {
-			if (strncasecmp(argv[5], "ad", 2) == 0) {
-				/*  */
-				int port = strtoul(argv[6], &check, 0);
-				if (check != (argv[6] + strlen(argv[6])))
-					return (1);
+	vlan.index = idx;
+
+	if (ioctl(fd, IOCTL_VLAN_VLAN_CONFIG,	&vlan) == -1) {
+		warn("error from IOCTL_VLAN_VLAN_CONFIG");
+	}
 
-				if (argc >= 8 && tolower(argv[7][0]) == 'u') {
-					vlan.d.dot1q.port_config[port] = DOT1Q_PORT_VLAN_CONFIG_VLAN_UNTAGGED;
-				} else if (argc >= 8 && tolower(argv[7][0]) == 't') {
-					vlan.d.dot1q.port_config[port] = DOT1Q_PORT_VLAN_CONFIG_VLAN_TAGGED;
-				} else if (argc >= 8 && tolower(argv[7][0]) == 'f') {
-					vlan.d.dot1q.port_config[port] = DOT1Q_PORT_VLAN_CONFIG_VLAN_FORBIDDEN;
-				} else {
-					printf("Only tagged/untagged/forbidden allowed (wrong '%s')\n", argv[7]);
-					return (1);
-				}
-			} else if (strncasecmp(argv[5], "de", 2) == 0) {
-				/*  */
-				int port = strtoul(argv[6], &check, 0);
-				if (check != (argv[6] + strlen(argv[6])))
-					return (1);
-				vlan.d.dot1q.port_config[port] = DOT1Q_PORT_VLAN_CONFIG_VLAN_NONE;
-			} else if (strncasecmp(argv[5], "vi", 2) == 0) {
-				/*  */
-				int vid = strtoul(argv[6], &check, 0);
-				if (check != (argv[6] + strlen(argv[6])))
-					return (1);
-				vlan.d.dot1q.vid = vid;
+	if (argc >= 7) {
+		if (strncasecmp(argv[5], "ad", 2) == 0) {
+			/*  */
+			int port = strtoul(argv[6], &check, 0);
+			if (check != (argv[6] + strlen(argv[6])))
+				return (1);
+
+			if (argc >= 8 && tolower(argv[7][0]) == 'u') {
+				vlan.d.dot1q.port_config[port] =
+				    DOT1Q_PORT_VLAN_CONFIG_VLAN_UNTAGGED;
+			} else if (argc >= 8 && tolower(argv[7][0]) == 't') {
+				vlan.d.dot1q.port_config[port] =
+				    DOT1Q_PORT_VLAN_CONFIG_VLAN_TAGGED;
+			} else if (argc >= 8 && tolower(argv[7][0]) == 'f') {
+				vlan.d.dot1q.port_config[port] =
+				    DOT1Q_PORT_VLAN_CONFIG_VLAN_FORBIDDEN;
 			} else {
-				printf("Only add/delete/vid allowed (wrong '%s')\n", argv[5]);
+				printf("Only tagged/untagged/forbidden "
+				    "allowed (wrong '%s')\n", argv[7]);
 				return (1);
 			}
+		} else if (strncasecmp(argv[5], "de", 2) == 0) {
+			/*  */
+			int port = strtoul(argv[6], &check, 0);
+			if (check != (argv[6] + strlen(argv[6])))
+				return (1);
+			vlan.d.dot1q.port_config[port] =
+			    DOT1Q_PORT_VLAN_CONFIG_VLAN_NONE;
+		} else if (strncasecmp(argv[5], "vi", 2) == 0) {
+			/*  */
+			int vid = strtoul(argv[6], &check, 0);
+			if (check != (argv[6] + strlen(argv[6])))
+				return (1);
+			vlan.d.dot1q.vid = vid;
+		} else {
+			printf("Only add/delete/vid allowed (wrong '%s')\n",
+			    argv[5]);
+			return (1);
 		}
+	}
+
+	vlan.index = idx;
+	vlan.cmd = 1; /* Set */
+
+	if (ioctl(fd, IOCTL_VLAN_VLAN_CONFIG,	&vlan) == -1)
+		err(1, "error from IOCTL_VLAN_VLAN_CONFIG");
+
+	printf("Index %d VID%d:\n", idx, vlan.d.dot1q.vid);
 
+	for (i = 0; i < info->cap->ports; i++)
+		printf("%02d ", i);
+	printf("\n");
+	for (i = 0; i < info->cap->ports; i++) {
+		printf(" %s ",
+		    (vlan.d.dot1q.port_config[i] ==
+			DOT1Q_PORT_VLAN_CONFIG_VLAN_TAGGED) ? "T" :
+		    (vlan.d.dot1q.port_config[i] ==
+			DOT1Q_PORT_VLAN_CONFIG_VLAN_UNTAGGED) ? "U" :
+		    (vlan.d.dot1q.port_config[i] ==
+			DOT1Q_PORT_VLAN_CONFIG_VLAN_FORBIDDEN) ? "F" :
+		    "N");
+	}
+	printf("\n");
+	return (1);
+}
+
+int
+get_pbvlan_config(struct info *info, int fd, int argc, char **argv)
+{
+	struct vlan_vlan_config vlan;
+	int idx;
+
+	bzero(&vlan, sizeof(vlan));
+	vlan.version = 0;
+	vlan.cmd = 0;
+	vlan.vlan_type = VLAN_TYPE_PORT;
+
+	if (argc >= 5) {
+		idx = strtoul(argv[4], 0, 0);
 		vlan.index = idx;
-		vlan.cmd = 1; /* Set */
 
 		if (ioctl(fd, IOCTL_VLAN_VLAN_CONFIG,	&vlan) == -1)
 			err(1, "error from IOCTL_VLAN_VLAN_CONFIG");
 
-		printf("Index %d VID%d:\n", idx, vlan.d.dot1q.vid);
+		printf("Port %d allowed to send to ports %#08x\n", idx,
+		    vlan.d.port.allowed);
+	}
+	return (1);
+}
+
+int
+set_pbvlan_config(struct info *info, int fd, int argc, char **argv)
+{
+	struct vlan_vlan_config vlan;
+	uint32_t allowed;
+	int idx;
 
-		for (i = 0; i < info->cap->ports; i++)
-			printf("%02d ", i);
-		printf("\n");
-		for (i = 0; i < info->cap->ports; i++) {
-			printf(" %s ",
-			    (vlan.d.dot1q.port_config[i] == DOT1Q_PORT_VLAN_CONFIG_VLAN_TAGGED)?"T":
-			    (vlan.d.dot1q.port_config[i] == DOT1Q_PORT_VLAN_CONFIG_VLAN_UNTAGGED)?"U":
-			    (vlan.d.dot1q.port_config[i] == DOT1Q_PORT_VLAN_CONFIG_VLAN_FORBIDDEN)?"F":
-			    "N");
+	bzero(&vlan, sizeof(vlan));
+	vlan.version = 0;
+	vlan.cmd = 1;
+	vlan.vlan_type = VLAN_TYPE_PORT;
+
+	if (argc >= 5) {
+		idx = strtoul(argv[4], 0, 0);
+		vlan.index = idx;
+
+		if (argc >= 6) {
+			allowed = strtoul(argv[5], 0, 0);
+			/* TODO: Check strtoul error and value */
+			vlan.d.port.allowed = allowed;
+		} else {
+			err(1, "error, [PBVLAN] no allowed ports specified");
 		}
-		printf("\n");
+		if (ioctl(fd, IOCTL_VLAN_VLAN_CONFIG,	&vlan) == -1)
+			err(1, "error from IOCTL_VLAN_VLAN_CONFIG");
 	}
 	return (1);
 }