[Bridge] [PATCH 2.6.5] (8/9) bridge - support lots of 1k ports

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Support >256 ports on a bridge.  Use the suggestion of reducing
the number of bits of priority and increasing the number of bits
for port number.

Easy to increase to even larger if necessary.

diff -Nru a/net/bridge/br_if.c b/net/bridge/br_if.c
--- a/net/bridge/br_if.c	Tue Apr 13 13:16:56 2004
+++ b/net/bridge/br_if.c	Tue Apr 13 13:16:56 2004
@@ -24,9 +24,6 @@
 
 #include "br_private.h"
 
-/* Limited to 256 ports because of STP protocol pdu */
-#define  BR_MAX_PORTS	256
-
 /*
  * Determine initial path cost based on speed.
  * using recommendations from 802.1d standard
@@ -166,23 +163,27 @@
 	return br;
 }
 
-static int free_port(struct net_bridge *br)
+/* find an available port number */
+static int find_portno(struct net_bridge *br)
 {
 	int index;
 	struct net_bridge_port *p;
-	long inuse[BR_MAX_PORTS/(sizeof(long)*8)];
+	unsigned long *inuse;
+
+	inuse = kmalloc(BITS_TO_LONGS(BR_MAX_PORTS)*sizeof(unsigned long),
+			GFP_ATOMIC);
+	if (!inuse)
+		return -ENOMEM;
 
-	/* find free port number */
-	memset(inuse, 0, sizeof(inuse));
+	CLEAR_BITMAP(inuse, BR_MAX_PORTS);
+	set_bit(0, inuse);	/* zero is reserved */
 	list_for_each_entry(p, &br->port_list, list) {
 		set_bit(p->port_no, inuse);
 	}
-
 	index = find_first_zero_bit(inuse, BR_MAX_PORTS);
-	if (index >= BR_MAX_PORTS)
-		return -EXFULL;
+	kfree(inuse);
 
-	return index;
+	return (index >= BR_MAX_PORTS) ? -EXFULL : index;
 }
 
 /* called under bridge lock */
@@ -193,7 +194,7 @@
 	int index;
 	struct net_bridge_port *p;
 	
-	index = free_port(br);
+	index = find_portno(br);
 	if (index < 0)
 		return ERR_PTR(index);
 
@@ -206,7 +207,7 @@
 	dev_hold(dev);
 	p->dev = dev;
 	p->path_cost = cost;
-	p->priority = 0x80;
+ 	p->priority = 0x8000 >> BR_PORT_BITS;
 	dev->br_port = p;
 	p->port_no = index;
 	br_init_port(p);
diff -Nru a/net/bridge/br_ioctl.c b/net/bridge/br_ioctl.c
--- a/net/bridge/br_ioctl.c	Tue Apr 13 13:16:56 2004
+++ b/net/bridge/br_ioctl.c	Tue Apr 13 13:16:56 2004
@@ -91,9 +91,15 @@
 
 	case BRCTL_GET_PORT_LIST:
 	{
-		int num = arg1 ? arg1 : 256;	/* compatiablity */
-		int ret = 0;
-		int *indices;
+		int num, *indices;
+
+		num = arg1;
+		if (num < 0)
+			return -EINVAL;
+		if (num == 0)
+			num = 256;
+		if (num > BR_MAX_PORTS)
+			num = BR_MAX_PORTS;
 
 		indices = kmalloc(num*sizeof(int), GFP_KERNEL);
 		if (indices == NULL)
@@ -103,9 +109,9 @@
 
 		br_get_port_ifindices(br, indices, num);
 		if (copy_to_user((void *)arg0, indices, num*sizeof(int)))
-			ret =  -EFAULT;
+			num =  -EFAULT;
 		kfree(indices);
-		return ret;
+		return num;
 	}
 
 	case BRCTL_SET_BRIDGE_FORWARD_DELAY:
@@ -204,6 +210,9 @@
 
 		if (!capable(CAP_NET_ADMIN))
 			return -EPERM;
+
+		if (arg1 >= (1<<(16-BR_PORT_BITS)))
+			return -ERANGE;
 
 		spin_lock_bh(&br->lock);
 		if ((p = br_get_port(br, arg0)) == NULL) 
diff -Nru a/net/bridge/br_private.h b/net/bridge/br_private.h
--- a/net/bridge/br_private.h	Tue Apr 13 13:16:56 2004
+++ b/net/bridge/br_private.h	Tue Apr 13 13:16:56 2004
@@ -24,6 +24,9 @@
 
 #define BR_HOLD_TIME (1*HZ)
 
+#define BR_PORT_BITS	10
+#define BR_MAX_PORTS	(1<<BR_PORT_BITS)
+
 typedef struct bridge_id bridge_id;
 typedef struct mac_addr mac_addr;
 typedef __u16 port_id;
diff -Nru a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c
--- a/net/bridge/br_stp_if.c	Tue Apr 13 13:16:56 2004
+++ b/net/bridge/br_stp_if.c	Tue Apr 13 13:16:56 2004
@@ -19,15 +19,21 @@
 #include "br_private.h"
 #include "br_private_stp.h"
 
-static inline __u16 br_make_port_id(const struct net_bridge_port *p)
+
+/* Port id is composed of priority and port number.
+ * NB: least significant bits of priority are dropped to
+ *     make room for more ports.
+ */
+static inline port_id br_make_port_id(__u8 priority, __u16 port_no)
 {
-	return (p->priority << 8) | p->port_no;
+	return ((u16)priority << BR_PORT_BITS) 
+		| (port_no & ((1<<BR_PORT_BITS)-1));
 }
 
 /* called under bridge lock */
 void br_init_port(struct net_bridge_port *p)
 {
-	p->port_id = br_make_port_id(p);
+	p->port_id = br_make_port_id(p->priority, p->port_no);
 	br_become_designated_port(p);
 	p->state = BR_STATE_BLOCKING;
 	p->topology_change_ack = 0;
@@ -185,15 +191,13 @@
 /* called under bridge lock */
 void br_stp_set_port_priority(struct net_bridge_port *p, u8 newprio)
 {
-	__u16 new_port_id;
-
-	p->priority = newprio & 0xFF;
-	new_port_id = br_make_port_id(p);
+	port_id new_port_id = br_make_port_id(newprio, p->port_no);
 
 	if (br_is_designated_port(p))
 		p->designated_port = new_port_id;
 
 	p->port_id = new_port_id;
+	p->priority = newprio;
 	if (!memcmp(&p->br->bridge_id, &p->designated_bridge, 8) &&
 	    p->port_id < p->designated_port) {
 		br_become_designated_port(p);


[Index of Archives]     [Netdev]     [AoE Tools]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]     [Video 4 Linux]

  Powered by Linux