Stephen Hemminger
2007-Apr-18 12:33 UTC
[Bridge] [PATCH] bridge (2.6.5) -- correctl handle up to 256 ports per bridge
Bridge code is limited to 256 ports per bridge because the Spanning Tree Protocol has limit of one octet for port number. This code fixes: * bogus unlock in error path when port list is full. * passes different error status for out of memory, vs port list full. * O(n) vs O(n^2) lookup for free port number * since port and priority are both limited to one byte don't store them as int's * makes limit explicit in code diff -Nru a/net/bridge/br_if.c b/net/bridge/br_if.c --- a/net/bridge/br_if.c Thu Apr 1 12:55:31 2004 +++ b/net/bridge/br_if.c Thu Apr 1 12:55:31 2004 @@ -24,6 +24,9 @@ #include <asm/uaccess.h> #include "br_private.h" +/* Limited to 256 ports because of STP protocol pdu */ +#define BR_MAX_PORTS 256 + static int br_initial_port_cost(struct net_device *dev) { if (!strncmp(dev->name, "lec", 3)) @@ -126,34 +129,46 @@ return br; } +static int free_port(struct net_bridge *br) +{ + int index; + struct net_bridge_port *p; + long inuse[BR_MAX_PORTS/(sizeof(long)*8)]; + + /* find free port number */ + memset(inuse, 0, sizeof(inuse)); + 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; + + return index; +} + /* called under bridge lock */ static struct net_bridge_port *new_nbp(struct net_bridge *br, struct net_device *dev) { - int i; + int index; struct net_bridge_port *p; + + index = free_port(br); + if (index < 0) + return ERR_PTR(index); p = kmalloc(sizeof(*p), GFP_ATOMIC); if (p == NULL) - return p; + return ERR_PTR(-ENOMEM); memset(p, 0, sizeof(*p)); p->br = br; p->dev = dev; p->path_cost = br_initial_port_cost(dev); p->priority = 0x80; - - for (i=1;i<255;i++) - if (br_get_port(br, i) == NULL) - break; - - if (i == 255) { - kfree(p); - return NULL; - } - dev->br_port = p; - - p->port_no = i; + p->port_no = index; br_init_port(p); p->state = BR_STATE_DISABLED; @@ -218,10 +233,10 @@ return -ELOOP; dev_hold(dev); - if ((p = new_nbp(br, dev)) == NULL) { - spin_unlock_bh(&br->lock); + p = new_nbp(br, dev); + if (IS_ERR(p)) { dev_put(dev); - return -EXFULL; + return PTR_ERR(p); } dev_set_promiscuity(dev, 1); diff -Nru a/net/bridge/br_private.h b/net/bridge/br_private.h --- a/net/bridge/br_private.h Thu Apr 1 12:55:31 2004 +++ b/net/bridge/br_private.h Thu Apr 1 12:55:31 2004 @@ -57,7 +57,8 @@ struct net_bridge *br; struct net_device *dev; struct list_head list; - int port_no; + __u8 port_no; + __u8 priority; /* STP */ port_id port_id; @@ -69,7 +70,6 @@ port_id designated_port; unsigned topology_change_ack:1; unsigned config_pending:1; - int priority; struct timer_list forward_delay_timer; struct timer_list hold_timer;
David S. Miller
2007-Apr-18 12:33 UTC
[Bridge] Re: [PATCH] bridge (2.6.5) -- correctl handle up to 256 ports per bridge
On Thu, 1 Apr 2004 13:57:46 -0800 Stephen Hemminger <shemminger@osdl.org> wrote:> Bridge code is limited to 256 ports per bridge because the Spanning > Tree Protocol has limit of one octet for port number. This code > fixes: > * bogus unlock in error path when port list is full. > * passes different error status for out of memory, vs > port list full. > * O(n) vs O(n^2) lookup for free port number > * since port and priority are both limited to one byte > don't store them as int's > * makes limit explicit in codeApplied, thanks Stephen.