Stephen Hemminger
2007-Apr-18 12:33 UTC
[Bridge] [PATCH 2.6.5] (1/9) bridge - include file cleanup
Cleanup some of the include file's in the bridge code. * if_bridge.h defines net_bridge, but not needed as part of the API. * get rid of places that include if_bridge.h and uaccess.h but don't actually do API work. diff -Nru a/include/linux/if_bridge.h b/include/linux/if_bridge.h --- a/include/linux/if_bridge.h Tue Apr 13 14:44:58 2004 +++ b/include/linux/if_bridge.h Tue Apr 13 14:44:58 2004 @@ -99,9 +99,6 @@ #include <linux/netdevice.h> -struct net_bridge; -struct net_bridge_port; - extern void brioctl_set(int (*ioctl_hook)(unsigned long)); extern int (*br_handle_frame_hook)(struct sk_buff *skb); extern int (*br_should_route_hook)(struct sk_buff **pskb); diff -Nru a/net/bridge/br.c b/net/bridge/br.c --- a/net/bridge/br.c Tue Apr 13 14:44:58 2004 +++ b/net/bridge/br.c Tue Apr 13 14:44:58 2004 @@ -20,8 +20,7 @@ #include <linux/netdevice.h> #include <linux/etherdevice.h> #include <linux/init.h> -#include <linux/if_bridge.h> -#include <asm/uaccess.h> + #include "br_private.h" #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) diff -Nru a/net/bridge/br_device.c b/net/bridge/br_device.c --- a/net/bridge/br_device.c Tue Apr 13 14:44:58 2004 +++ b/net/bridge/br_device.c Tue Apr 13 14:44:58 2004 @@ -15,7 +15,6 @@ #include <linux/kernel.h> #include <linux/netdevice.h> -#include <linux/if_bridge.h> #include <linux/module.h> #include <asm/uaccess.h> #include "br_private.h" diff -Nru a/net/bridge/br_forward.c b/net/bridge/br_forward.c --- a/net/bridge/br_forward.c Tue Apr 13 14:44:58 2004 +++ b/net/bridge/br_forward.c Tue Apr 13 14:44:58 2004 @@ -15,9 +15,7 @@ #include <linux/kernel.h> #include <linux/netdevice.h> -#include <linux/inetdevice.h> #include <linux/skbuff.h> -#include <linux/if_bridge.h> #include <linux/netfilter_bridge.h> #include "br_private.h" diff -Nru a/net/bridge/br_if.c b/net/bridge/br_if.c --- a/net/bridge/br_if.c Tue Apr 13 14:44:58 2004 +++ b/net/bridge/br_if.c Tue Apr 13 14:44:58 2004 @@ -15,13 +15,11 @@ #include <linux/kernel.h> #include <linux/if_arp.h> -#include <linux/if_bridge.h> -#include <linux/inetdevice.h> #include <linux/module.h> #include <linux/init.h> #include <linux/rtnetlink.h> #include <net/sock.h> -#include <asm/uaccess.h> + #include "br_private.h" /* Limited to 256 ports because of STP protocol pdu */ diff -Nru a/net/bridge/br_input.c b/net/bridge/br_input.c --- a/net/bridge/br_input.c Tue Apr 13 14:44:58 2004 +++ b/net/bridge/br_input.c Tue Apr 13 14:44:58 2004 @@ -16,7 +16,6 @@ #include <linux/kernel.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> -#include <linux/if_bridge.h> #include <linux/netfilter_bridge.h> #include "br_private.h" diff -Nru a/net/bridge/br_ioctl.c b/net/bridge/br_ioctl.c --- a/net/bridge/br_ioctl.c Tue Apr 13 14:44:58 2004 +++ b/net/bridge/br_ioctl.c Tue Apr 13 14:44:58 2004 @@ -15,7 +15,7 @@ #include <linux/kernel.h> #include <linux/if_bridge.h> -#include <linux/inetdevice.h> +#include <linux/netdevice.h> #include <asm/uaccess.h> #include "br_private.h" diff -Nru a/net/bridge/br_notify.c b/net/bridge/br_notify.c --- a/net/bridge/br_notify.c Tue Apr 13 14:44:58 2004 +++ b/net/bridge/br_notify.c Tue Apr 13 14:44:58 2004 @@ -14,7 +14,7 @@ */ #include <linux/kernel.h> -#include <linux/if_bridge.h> + #include "br_private.h" static int br_device_event(struct notifier_block *unused, unsigned long event, void *ptr); diff -Nru a/net/bridge/br_stp.c b/net/bridge/br_stp.c --- a/net/bridge/br_stp.c Tue Apr 13 14:44:58 2004 +++ b/net/bridge/br_stp.c Tue Apr 13 14:44:58 2004 @@ -13,9 +13,8 @@ * 2 of the License, or (at your option) any later version. */ #include <linux/kernel.h> -#include <linux/if_bridge.h> #include <linux/smp_lock.h> -#include <asm/uaccess.h> + #include "br_private.h" #include "br_private_stp.h" diff -Nru a/net/bridge/br_stp_bpdu.c b/net/bridge/br_stp_bpdu.c --- a/net/bridge/br_stp_bpdu.c Tue Apr 13 14:44:58 2004 +++ b/net/bridge/br_stp_bpdu.c Tue Apr 13 14:44:58 2004 @@ -14,9 +14,8 @@ */ #include <linux/kernel.h> -#include <linux/if_ether.h> -#include <linux/if_bridge.h> #include <linux/netfilter_bridge.h> + #include "br_private.h" #include "br_private_stp.h" 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 14:44:58 2004 +++ b/net/bridge/br_stp_if.c Tue Apr 13 14:44:58 2004 @@ -14,9 +14,8 @@ */ #include <linux/kernel.h> -#include <linux/if_bridge.h> #include <linux/smp_lock.h> -#include <asm/uaccess.h> + #include "br_private.h" #include "br_private_stp.h" diff -Nru a/net/bridge/br_stp_timer.c b/net/bridge/br_stp_timer.c --- a/net/bridge/br_stp_timer.c Tue Apr 13 14:44:58 2004 +++ b/net/bridge/br_stp_timer.c Tue Apr 13 14:44:58 2004 @@ -14,9 +14,8 @@ */ #include <linux/kernel.h> -#include <linux/if_bridge.h> #include <linux/smp_lock.h> -#include <asm/uaccess.h> + #include "br_private.h" #include "br_private_stp.h"
Fix observed race between removing bridge module and ip packets in flight. Need to remove the hook last, after all bridges are gone not the other way around. diff -Nru a/net/bridge/br.c b/net/bridge/br.c --- a/net/bridge/br.c Mon Apr 12 16:09:56 2004 +++ b/net/bridge/br.c Mon Apr 12 16:09:56 2004 @@ -54,16 +54,17 @@ #endif unregister_netdevice_notifier(&br_device_notifier); brioctl_set(NULL); - br_handle_frame_hook = NULL; + + br_cleanup_bridges(); + + synchronize_net(); #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) br_fdb_get_hook = NULL; br_fdb_put_hook = NULL; #endif - br_cleanup_bridges(); - - synchronize_net(); + br_handle_frame_hook = NULL; } EXPORT_SYMBOL(br_should_route_hook);
Stephen Hemminger
2007-Apr-18 12:33 UTC
[Bridge] [PATCH 2.6.5] (7/9) bridge - STP unsigned fields
Use correct types for fields related to spanning tree protocols.
* costs are 32 bit unsigned
* ports are 16 bit unsigned
* booleans are bytes rather than bitfield
* arrange for better packing
diff -Nru a/net/bridge/br_private.h b/net/bridge/br_private.h
--- a/net/bridge/br_private.h Mon Apr 12 16:11:03 2004
+++ b/net/bridge/br_private.h Mon Apr 12 16:11:03 2004
@@ -56,19 +56,19 @@
struct net_bridge *br;
struct net_device *dev;
struct list_head list;
- __u8 port_no;
- __u8 priority;
/* STP */
+ u8 priority;
+ u8 state;
+ u16 port_no;
+ unsigned char topology_change_ack;
+ unsigned char config_pending;
port_id port_id;
- int state;
- int path_cost;
+ port_id designated_port;
bridge_id designated_root;
- int designated_cost;
bridge_id designated_bridge;
- port_id designated_port;
- unsigned topology_change_ack:1;
- unsigned config_pending:1;
+ u32 path_cost;
+ u32 designated_cost;
struct timer_list forward_delay_timer;
struct timer_list hold_timer;
@@ -88,25 +88,25 @@
/* STP */
bridge_id designated_root;
- int root_path_cost;
- int root_port;
- int max_age;
- int hello_time;
- int forward_delay;
bridge_id bridge_id;
- int bridge_max_age;
- int bridge_hello_time;
- int bridge_forward_delay;
- unsigned stp_enabled:1;
- unsigned topology_change:1;
- unsigned topology_change_detected:1;
+ u32 root_path_cost;
+ unsigned long max_age;
+ unsigned long hello_time;
+ unsigned long forward_delay;
+ unsigned long bridge_max_age;
+ unsigned long ageing_time;
+ unsigned long bridge_hello_time;
+ unsigned long bridge_forward_delay;
+
+ u16 root_port;
+ unsigned char stp_enabled;
+ unsigned char topology_change;
+ unsigned char topology_change_detected;
struct timer_list hello_timer;
struct timer_list tcn_timer;
struct timer_list topology_change_timer;
struct timer_list gc_timer;
-
- int ageing_time;
};
extern struct notifier_block br_device_notifier;
@@ -185,7 +185,7 @@
/* br_stp.c */
extern void br_log_state(const struct net_bridge_port *p);
extern struct net_bridge_port *br_get_port(struct net_bridge *br,
- int port_no);
+ u16 port_no);
extern void br_init_port(struct net_bridge_port *p);
extern void br_become_designated_port(struct net_bridge_port *p);
@@ -196,11 +196,11 @@
extern void br_stp_disable_port(struct net_bridge_port *p);
extern void br_stp_recalculate_bridge_id(struct net_bridge *br);
extern void br_stp_set_bridge_priority(struct net_bridge *br,
- int newprio);
+ u16 newprio);
extern void br_stp_set_port_priority(struct net_bridge_port *p,
- int newprio);
+ u8 newprio);
extern void br_stp_set_path_cost(struct net_bridge_port *p,
- int path_cost);
+ u32 path_cost);
/* br_stp_bpdu.c */
extern int br_stp_handle_bpdu(struct sk_buff *skb);
diff -Nru a/net/bridge/br_stp.c b/net/bridge/br_stp.c
--- a/net/bridge/br_stp.c Mon Apr 12 16:11:03 2004
+++ b/net/bridge/br_stp.c Mon Apr 12 16:11:03 2004
@@ -35,7 +35,7 @@
}
/* called under bridge lock */
-struct net_bridge_port *br_get_port(struct net_bridge *br, int port_no)
+struct net_bridge_port *br_get_port(struct net_bridge *br, u16 port_no)
{
struct net_bridge_port *p;
@@ -49,7 +49,7 @@
/* called under bridge lock */
static int br_should_become_root_port(const struct net_bridge_port *p,
- int root_port)
+ u16 root_port)
{
struct net_bridge *br;
struct net_bridge_port *rp;
@@ -102,9 +102,7 @@
static void br_root_selection(struct net_bridge *br)
{
struct net_bridge_port *p;
- int root_port;
-
- root_port = 0;
+ u16 root_port = 0;
list_for_each_entry(p, &br->port_list, list) {
if (br_should_become_root_port(p, root_port))
diff -Nru a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c
--- a/net/bridge/br_stp_if.c Mon Apr 12 16:11:03 2004
+++ b/net/bridge/br_stp_if.c Mon Apr 12 16:11:03 2004
@@ -158,7 +158,7 @@
}
/* called under bridge lock */
-void br_stp_set_bridge_priority(struct net_bridge *br, int newprio)
+void br_stp_set_bridge_priority(struct net_bridge *br, u16 newprio)
{
struct net_bridge_port *p;
int wasroot;
@@ -183,7 +183,7 @@
}
/* called under bridge lock */
-void br_stp_set_port_priority(struct net_bridge_port *p, int newprio)
+void br_stp_set_port_priority(struct net_bridge_port *p, u8 newprio)
{
__u16 new_port_id;
@@ -202,7 +202,7 @@
}
/* called under bridge lock */
-void br_stp_set_path_cost(struct net_bridge_port *p, int path_cost)
+void br_stp_set_path_cost(struct net_bridge_port *p, u32 path_cost)
{
p->path_cost = path_cost;
br_configuration_update(p->br);
David S. Miller
2007-Apr-18 12:33 UTC
[Bridge] Re: [PATCH 2.6.5] (1/9) bridge - include file cleanup
On Tue, 13 Apr 2004 15:16:30 -0700 Stephen Hemminger <shemminger@osdl.org> wrote:> Cleanup some of the include file's in the bridge code. > * if_bridge.h defines net_bridge, but not needed as part of the API. > * get rid of places that include if_bridge.h and uaccess.h but don't > actually do API work.Applied.
Stephen Hemminger
2007-Apr-18 12:33 UTC
[Bridge] [PATCH 2.6.5] (4/9) bridge - use ethtool to get port speed
The bridge code needs to keep track of a cost estimate for each
port in the bridge. Instead of a hack based on device name, try
and use ethtool to get port speed from device. This has been tested
on e100 (uses ethtool_ops) and e1000 (does ethtool the hard way)
and dummy (no ethtool).
Need to export dev_ethtool() to allow bridge module to get to
it easily.
Code takes care to maintain same locking and semantics as if ioctl
was being done from application.
diff -Nru a/net/bridge/br_if.c b/net/bridge/br_if.c
--- a/net/bridge/br_if.c Mon Apr 12 16:10:23 2004
+++ b/net/bridge/br_if.c Mon Apr 12 16:10:23 2004
@@ -14,6 +14,8 @@
*/
#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <linux/ethtool.h>
#include <linux/if_arp.h>
#include <linux/module.h>
#include <linux/init.h>
@@ -25,18 +27,55 @@
/* 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
+ *
+ * Need to simulate user ioctl because not all device's that support
+ * ethtool, use ethtool_ops. Also, since driver might sleep need to
+ * not be holding any locks.
+ */
static int br_initial_port_cost(struct net_device *dev)
{
+
+ struct ethtool_cmd ecmd = { ETHTOOL_GSET };
+ struct ifreq ifr;
+ mm_segment_t old_fs;
+ int err;
+
+ strncpy(ifr.ifr_name, dev->name, IFNAMSIZ);
+ ifr.ifr_data = (void *) &ecmd;
+
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+ err = dev_ethtool(&ifr);
+ set_fs(old_fs);
+
+ if (!err) {
+ switch(ecmd.speed) {
+ case SPEED_100:
+ return 19;
+ case SPEED_1000:
+ return 4;
+ case SPEED_10000:
+ return 2;
+ case SPEED_10:
+ return 100;
+ default:
+ pr_info("bridge: can't decode speed from %s: %d\n",
+ dev->name, ecmd.speed);
+ return 100;
+ }
+ }
+
+ /* Old silly heuristics based on name */
if (!strncmp(dev->name, "lec", 3))
return 7;
- if (!strncmp(dev->name, "eth", 3))
- return 100; /* FIXME handle 100Mbps */
-
if (!strncmp(dev->name, "plip", 4))
return 2500;
- return 100;
+ return 100; /* assume old 10Mbps */
}
static void destroy_nbp(void *arg)
@@ -147,7 +186,9 @@
}
/* called under bridge lock */
-static struct net_bridge_port *new_nbp(struct net_bridge *br, struct net_device
*dev)
+static struct net_bridge_port *new_nbp(struct net_bridge *br,
+ struct net_device *dev,
+ unsigned long cost)
{
int index;
struct net_bridge_port *p;
@@ -162,16 +203,15 @@
memset(p, 0, sizeof(*p));
p->br = br;
+ dev_hold(dev);
p->dev = dev;
- p->path_cost = br_initial_port_cost(dev);
+ p->path_cost = cost;
p->priority = 0x80;
dev->br_port = p;
p->port_no = index;
br_init_port(p);
p->state = BR_STATE_DISABLED;
- list_add_rcu(&p->list, &br->port_list);
-
return p;
}
@@ -216,13 +256,11 @@
return ret;
}
-/* called under bridge lock */
int br_add_if(struct net_bridge *br, struct net_device *dev)
{
struct net_bridge_port *p;
-
- if (dev->br_port != NULL)
- return -EBUSY;
+ unsigned long cost;
+ int err = 0;
if (dev->flags & IFF_LOOPBACK || dev->type != ARPHRD_ETHER)
return -EINVAL;
@@ -230,34 +268,46 @@
if (dev->hard_start_xmit == br_dev_xmit)
return -ELOOP;
- dev_hold(dev);
- p = new_nbp(br, dev);
- if (IS_ERR(p)) {
- dev_put(dev);
- return PTR_ERR(p);
- }
+ cost = br_initial_port_cost(dev);
- dev_set_promiscuity(dev, 1);
+ spin_lock_bh(&br->lock);
+ if (dev->br_port != NULL)
+ err = -EBUSY;
+
+ else if (IS_ERR(p = new_nbp(br, dev, cost)))
+ err = PTR_ERR(p);
- br_stp_recalculate_bridge_id(br);
- br_fdb_insert(br, p, dev->dev_addr, 1);
- if ((br->dev->flags & IFF_UP) && (dev->flags &
IFF_UP))
- br_stp_enable_port(p);
+ else {
+ dev_set_promiscuity(dev, 1);
- return 0;
+ list_add_rcu(&p->list, &br->port_list);
+
+ br_stp_recalculate_bridge_id(br);
+ br_fdb_insert(br, p, dev->dev_addr, 1);
+ if ((br->dev->flags & IFF_UP) && (dev->flags &
IFF_UP))
+ br_stp_enable_port(p);
+
+ }
+ spin_unlock_bh(&br->lock);
+ return err;
}
-/* called under bridge lock */
int br_del_if(struct net_bridge *br, struct net_device *dev)
{
struct net_bridge_port *p;
+ int err = 0;
- if ((p = dev->br_port) == NULL || p->br != br)
- return -EINVAL;
+ spin_lock_bh(&br->lock);
+ p = dev->br_port;
+ if (!p || p->br != br)
+ err = -EINVAL;
+ else {
+ del_nbp(p);
+ br_stp_recalculate_bridge_id(br);
+ }
+ spin_unlock_bh(&br->lock);
- del_nbp(p);
- br_stp_recalculate_bridge_id(br);
- return 0;
+ return err;
}
int br_get_bridge_ifindices(int *indices, int num)
diff -Nru a/net/bridge/br_ioctl.c b/net/bridge/br_ioctl.c
--- a/net/bridge/br_ioctl.c Mon Apr 12 16:10:23 2004
+++ b/net/bridge/br_ioctl.c Mon Apr 12 16:10:23 2004
@@ -48,12 +48,10 @@
if (dev == NULL)
return -EINVAL;
- spin_lock_bh(&br->lock);
if (cmd == BRCTL_ADD_IF)
ret = br_add_if(br, dev);
else
ret = br_del_if(br, dev);
- spin_unlock_bh(&br->lock);
dev_put(dev);
return ret;
diff -Nru a/net/core/ethtool.c b/net/core/ethtool.c
--- a/net/core/ethtool.c Mon Apr 12 16:10:23 2004
+++ b/net/core/ethtool.c Mon Apr 12 16:10:23 2004
@@ -740,6 +740,7 @@
return -EOPNOTSUPP;
}
+EXPORT_SYMBOL(dev_ethtool);
EXPORT_SYMBOL(ethtool_op_get_link);
EXPORT_SYMBOL(ethtool_op_get_sg);
EXPORT_SYMBOL(ethtool_op_get_tso);
Stephen Hemminger
2007-Apr-18 12:33 UTC
[Bridge] [PATCH 2.6.5] (6/9) bridge - forwarding database changes
Make forwarding database more robust.
+ Don't insert invalid ether address,
+ Report errors back so adding an interface to bridge can fail
+ get rid of unneeded explicit pads in data structure
+ replace bitfields with byte's for simple booleans.
diff -Nru a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
--- a/net/bridge/br_fdb.c Mon Apr 12 16:10:50 2004
+++ b/net/bridge/br_fdb.c Mon Apr 12 16:10:50 2004
@@ -17,6 +17,7 @@
#include <linux/spinlock.h>
#include <linux/if_bridge.h>
#include <linux/times.h>
+#include <linux/etherdevice.h>
#include <asm/atomic.h>
#include <asm/uaccess.h>
#include "br_private.h"
@@ -243,12 +244,16 @@
return num;
}
-void br_fdb_insert(struct net_bridge *br, struct net_bridge_port *source,
- const unsigned char *addr, int is_local)
+int br_fdb_insert(struct net_bridge *br, struct net_bridge_port *source,
+ const unsigned char *addr, int is_local)
{
struct hlist_node *h;
struct net_bridge_fdb_entry *fdb;
int hash = br_mac_hash(addr);
+ int ret = 0;
+
+ if (!is_valid_ether_addr(addr))
+ return -EADDRNOTAVAIL;
write_lock_bh(&br->hash_lock);
hlist_for_each(h, &br->hash[hash]) {
@@ -264,6 +269,7 @@
printk(KERN_WARNING "%s: received packet with "
" own address as source address\n",
source->dev->name);
+ ret = -EEXIST;
goto out;
}
@@ -278,8 +284,10 @@
}
fdb = kmalloc(sizeof(*fdb), GFP_ATOMIC);
- if (fdb == NULL)
+ if (unlikely(fdb == NULL)) {
+ ret = -ENOMEM;
goto out;
+ }
memcpy(fdb->addr.addr, addr, ETH_ALEN);
atomic_set(&fdb->use_count, 1);
@@ -298,4 +306,6 @@
list_add_tail(&fdb->age_list, &br->age_list);
out:
write_unlock_bh(&br->hash_lock);
+
+ return ret;
}
diff -Nru a/net/bridge/br_if.c b/net/bridge/br_if.c
--- a/net/bridge/br_if.c Mon Apr 12 16:10:50 2004
+++ b/net/bridge/br_if.c Mon Apr 12 16:10:50 2004
@@ -277,13 +277,15 @@
else if (IS_ERR(p = new_nbp(br, dev, cost)))
err = PTR_ERR(p);
+ else if ((err = br_fdb_insert(br, p, dev->dev_addr, 1)))
+ destroy_nbp(p);
+
else {
dev_set_promiscuity(dev, 1);
list_add_rcu(&p->list, &br->port_list);
br_stp_recalculate_bridge_id(br);
- br_fdb_insert(br, p, dev->dev_addr, 1);
if ((br->dev->flags & IFF_UP) && (dev->flags &
IFF_UP))
br_stp_enable_port(p);
diff -Nru a/net/bridge/br_private.h b/net/bridge/br_private.h
--- a/net/bridge/br_private.h Mon Apr 12 16:10:50 2004
+++ b/net/bridge/br_private.h Mon Apr 12 16:10:50 2004
@@ -37,7 +37,6 @@
struct mac_addr
{
unsigned char addr[6];
- unsigned char pad[2];
};
struct net_bridge_fdb_entry
@@ -48,8 +47,8 @@
atomic_t use_count;
unsigned long ageing_timer;
mac_addr addr;
- unsigned is_local:1;
- unsigned is_static:1;
+ unsigned char is_local;
+ unsigned char is_static;
};
struct net_bridge_port
@@ -135,10 +134,10 @@
extern void br_fdb_put(struct net_bridge_fdb_entry *ent);
extern int br_fdb_get_entries(struct net_bridge *br, void __user *buf,
int maxnum, int offset);
-extern void br_fdb_insert(struct net_bridge *br,
- struct net_bridge_port *source,
- const unsigned char *addr,
- int is_local);
+extern int br_fdb_insert(struct net_bridge *br,
+ struct net_bridge_port *source,
+ const unsigned char *addr,
+ int is_local);
/* br_forward.c */
extern void br_deliver(const struct net_bridge_port *to,
Stephen Hemminger
2007-Apr-18 12:33 UTC
[Bridge] [PATCH 2.6.5] bridge - replace CLEAR_BITMAP with memset
It looks like a recent patch to 2.6.5 got rid of CLEAR_BITMAP.
diff -Nru a/net/bridge/br_if.c b/net/bridge/br_if.c
--- a/net/bridge/br_if.c Wed Apr 14 12:01:21 2004
+++ b/net/bridge/br_if.c Wed Apr 14 12:01:21 2004
@@ -175,7 +175,7 @@
if (!inuse)
return -ENOMEM;
- CLEAR_BITMAP(inuse, BR_MAX_PORTS);
+ memset(inuse, 0, BITS_TO_LONGS(BR_MAX_PORTS)*sizeof(unsigned long));
set_bit(0, inuse); /* zero is reserved */
list_for_each_entry(p, &br->port_list, list) {
set_bit(p->port_no, inuse);
Stephen Hemminger
2007-Apr-18 12:33 UTC
[Bridge] [PATCH 2.6.5] (3/9) bridge - jiffies_to_clock
Rather than doing the math directly, use jiffies_to_clock functions
to convert from user hz to jiffies.
diff -Nru a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
--- a/net/bridge/br_fdb.c Mon Apr 12 16:10:09 2004
+++ b/net/bridge/br_fdb.c Mon Apr 12 16:10:09 2004
@@ -16,6 +16,7 @@
#include <linux/kernel.h>
#include <linux/spinlock.h>
#include <linux/if_bridge.h>
+#include <linux/times.h>
#include <asm/atomic.h>
#include <asm/uaccess.h>
#include "br_private.h"
@@ -48,7 +49,7 @@
ent->compat_port_no = ent->port_no;
ent->is_local = f->is_local;
ent->ageing_timer_value = f->is_static ? 0
- : ((jiffies - f->ageing_timer) * USER_HZ) / HZ;
+ : jiffies_to_clock_t(jiffies - f->ageing_timer);
}
static __inline__ int br_mac_hash(const unsigned char *mac)
diff -Nru a/net/bridge/br_ioctl.c b/net/bridge/br_ioctl.c
--- a/net/bridge/br_ioctl.c Mon Apr 12 16:10:09 2004
+++ b/net/bridge/br_ioctl.c Mon Apr 12 16:10:09 2004
@@ -16,26 +16,15 @@
#include <linux/kernel.h>
#include <linux/if_bridge.h>
#include <linux/netdevice.h>
+#include <linux/times.h>
#include <asm/uaccess.h>
#include "br_private.h"
-/* import values in USER_HZ */
-static inline unsigned long user_to_ticks(unsigned long utick)
-{
- return (utick * HZ) / USER_HZ;
-}
-
-/* export values in USER_HZ */
-static inline unsigned long ticks_to_user(unsigned long tick)
-{
- return (tick * USER_HZ) / HZ;
-}
-
/* Report time remaining in user HZ */
static unsigned long timer_residue(const struct timer_list *timer)
{
- return ticks_to_user(timer_pending(timer)
- ? (timer->expires - jiffies) : 0);
+ return timer_pending(timer)
+ ? jiffies_to_clock_t(timer->expires - jiffies) : 0;
}
int br_ioctl_device(struct net_bridge *br, unsigned int cmd,
@@ -79,17 +68,17 @@
memcpy(&b.designated_root, &br->designated_root, 8);
memcpy(&b.bridge_id, &br->bridge_id, 8);
b.root_path_cost = br->root_path_cost;
- b.max_age = ticks_to_user(br->max_age);
- b.hello_time = ticks_to_user(br->hello_time);
+ b.max_age = jiffies_to_clock_t(br->max_age);
+ b.hello_time = jiffies_to_clock_t(br->hello_time);
b.forward_delay = br->forward_delay;
b.bridge_max_age = br->bridge_max_age;
b.bridge_hello_time = br->bridge_hello_time;
- b.bridge_forward_delay = ticks_to_user(br->bridge_forward_delay);
+ b.bridge_forward_delay = jiffies_to_clock_t(br->bridge_forward_delay);
b.topology_change = br->topology_change;
b.topology_change_detected = br->topology_change_detected;
b.root_port = br->root_port;
b.stp_enabled = br->stp_enabled;
- b.ageing_time = ticks_to_user(br->ageing_time);
+ b.ageing_time = jiffies_to_clock_t(br->ageing_time);
b.hello_timer_value = timer_residue(&br->hello_timer);
b.tcn_timer_value = timer_residue(&br->tcn_timer);
b.topology_change_timer_value =
timer_residue(&br->topology_change_timer);
@@ -126,7 +115,7 @@
return -EPERM;
spin_lock_bh(&br->lock);
- br->bridge_forward_delay = user_to_ticks(arg0);
+ br->bridge_forward_delay = clock_t_to_jiffies(arg0);
if (br_is_root_bridge(br))
br->forward_delay = br->bridge_forward_delay;
spin_unlock_bh(&br->lock);
@@ -137,7 +126,7 @@
return -EPERM;
spin_lock_bh(&br->lock);
- br->bridge_hello_time = user_to_ticks(arg0);
+ br->bridge_hello_time = clock_t_to_jiffies(arg0);
if (br_is_root_bridge(br))
br->hello_time = br->bridge_hello_time;
spin_unlock_bh(&br->lock);
@@ -148,7 +137,7 @@
return -EPERM;
spin_lock_bh(&br->lock);
- br->bridge_max_age = user_to_ticks(arg0);
+ br->bridge_max_age = clock_t_to_jiffies(arg0);
if (br_is_root_bridge(br))
br->max_age = br->bridge_max_age;
spin_unlock_bh(&br->lock);
@@ -158,7 +147,7 @@
if (!capable(CAP_NET_ADMIN))
return -EPERM;
- br->ageing_time = user_to_ticks(arg0);
+ br->ageing_time = clock_t_to_jiffies(arg0);
return 0;
case BRCTL_GET_PORT_INFO:
Stephen Hemminger
2007-Apr-18 12:33 UTC
[Bridge] [PATCH 2.6.5] (5/9) bridge - multicast address as const
Trivial change. For places where bridge multicast address is defined,
or compared use constant.
diff -Nru a/net/bridge/br_input.c b/net/bridge/br_input.c
--- a/net/bridge/br_input.c Mon Apr 12 16:10:36 2004
+++ b/net/bridge/br_input.c Mon Apr 12 16:10:36 2004
@@ -19,7 +19,7 @@
#include <linux/netfilter_bridge.h>
#include "br_private.h"
-unsigned char bridge_ula[6] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 };
+const unsigned char bridge_ula[6] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 };
static int br_pass_frame_up_finish(struct sk_buff *skb)
{
diff -Nru a/net/bridge/br_private.h b/net/bridge/br_private.h
--- a/net/bridge/br_private.h Mon Apr 12 16:10:36 2004
+++ b/net/bridge/br_private.h Mon Apr 12 16:10:36 2004
@@ -111,7 +111,7 @@
};
extern struct notifier_block br_device_notifier;
-extern unsigned char bridge_ula[6];
+extern const unsigned char bridge_ula[6];
/* called under bridge lock */
static inline int br_is_root_bridge(const struct net_bridge *br)
diff -Nru a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c
--- a/net/bridge/br_stp_if.c Mon Apr 12 16:10:36 2004
+++ b/net/bridge/br_stp_if.c Mon Apr 12 16:10:36 2004
@@ -110,7 +110,8 @@
}
/* called under bridge lock */
-static void br_stp_change_bridge_id(struct net_bridge *br, unsigned char *addr)
+static void br_stp_change_bridge_id(struct net_bridge *br,
+ const unsigned char *addr)
{
unsigned char oldaddr[6];
struct net_bridge_port *p;
@@ -137,15 +138,13 @@
br_become_root_bridge(br);
}
-static unsigned char br_mac_zero[6];
+static const unsigned char br_mac_zero[6];
/* called under bridge lock */
void br_stp_recalculate_bridge_id(struct net_bridge *br)
{
- unsigned char *addr;
+ const unsigned char *addr = br_mac_zero;
struct net_bridge_port *p;
-
- addr = br_mac_zero;
list_for_each_entry(p, &br->port_list, list) {
if (addr == br_mac_zero ||
Stephen Hemminger
2007-Apr-18 12:33 UTC
[Bridge] [PATCH 2.6.5] (9/9) bridge - fdb cache alloc
Since forwarding database gets a lot of memory alloc/free on a busy
bridge, use kmem_cache_alloc to provide cache and better stats.
diff -Nru a/net/bridge/br.c b/net/bridge/br.c
--- a/net/bridge/br.c Tue Apr 13 13:17:16 2004
+++ b/net/bridge/br.c Tue Apr 13 13:17:16 2004
@@ -31,6 +31,8 @@
static int __init br_init(void)
{
+ br_fdb_init();
+
#ifdef CONFIG_BRIDGE_NETFILTER
if (br_netfilter_init())
return 1;
@@ -65,6 +67,7 @@
#endif
br_handle_frame_hook = NULL;
+ br_fdb_fini();
}
EXPORT_SYMBOL(br_should_route_hook);
diff -Nru a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
--- a/net/bridge/br_fdb.c Tue Apr 13 13:17:16 2004
+++ b/net/bridge/br_fdb.c Tue Apr 13 13:17:16 2004
@@ -22,6 +22,22 @@
#include <asm/uaccess.h>
#include "br_private.h"
+static kmem_cache_t *br_fdb_cache;
+
+void __init br_fdb_init(void)
+{
+ br_fdb_cache = kmem_cache_create("bridge_fdb_cache",
+ sizeof(struct net_bridge_fdb_entry),
+ 0,
+ SLAB_HWCACHE_ALIGN, NULL, NULL);
+}
+
+void __exit br_fdb_fini(void)
+{
+ kmem_cache_destroy(br_fdb_cache);
+}
+
+
/* if topology_changing then use forward_delay (default 15 sec)
* otherwise keep longer (default 5 minutes)
*/
@@ -37,7 +53,7 @@
&& time_before_eq(fdb->ageing_timer + hold_time(br), jiffies);
}
-static __inline__ void copy_fdb(struct __fdb_entry *ent,
+static inline void copy_fdb(struct __fdb_entry *ent,
const struct net_bridge_fdb_entry *f)
{
memset(ent, 0, sizeof(struct __fdb_entry));
@@ -180,7 +196,7 @@
void br_fdb_put(struct net_bridge_fdb_entry *ent)
{
if (atomic_dec_and_test(&ent->use_count))
- kfree(ent);
+ kmem_cache_free(br_fdb_cache, ent);
}
int br_fdb_get_entries(struct net_bridge *br, void __user *buf,
@@ -224,7 +240,7 @@
/* entry was deleted during copy_to_user */
if (atomic_dec_and_test(&f->use_count)) {
- kfree(f);
+ kmem_cache_free(br_fdb_cache, f);
num = -EAGAIN;
goto out;
}
@@ -283,7 +299,7 @@
}
}
- fdb = kmalloc(sizeof(*fdb), GFP_ATOMIC);
+ fdb = kmem_cache_alloc(br_fdb_cache, GFP_ATOMIC);
if (unlikely(fdb == NULL)) {
ret = -ENOMEM;
goto out;
diff -Nru a/net/bridge/br_private.h b/net/bridge/br_private.h
--- a/net/bridge/br_private.h Tue Apr 13 13:17:16 2004
+++ b/net/bridge/br_private.h Tue Apr 13 13:17:16 2004
@@ -127,6 +127,8 @@
extern int br_dev_xmit(struct sk_buff *skb, struct net_device *dev);
/* br_fdb.c */
+extern void br_fdb_init(void);
+extern void br_fdb_fini(void);
extern void br_fdb_changeaddr(struct net_bridge_port *p,
const unsigned char *newaddr);
extern void br_fdb_cleanup(unsigned long arg);
Stephen Hemminger
2007-Apr-18 12:33 UTC
[Bridge] [PATCH 2.6.5] (8/9) bridge - support lots of 1k ports
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);