Greetings everyone,
The following change (against ppclinux 2.4.18pre2 --sorry that's what I'm
working on right now) removes the bridge driver's global hook and replaces
it with a device-specific function.
With this change, any driver which defines net_device.recv_from_slave()
and calls netdev_set_master(slave, self) has the opportunity to process
the packets received by the slave device.
This method seemed more flexible than adding a global hook for my own
driver. Please let me know what you think. A simple "this looks good" or
"it has the following problems..." would be greatly appreciated.
diff -wbBurN linux-GPL.orig/drivers/net/bonding.c linux-GPL/drivers/net/bonding.c
--- linux-GPL.orig/drivers/net/bonding.c Fri May 3 13:49:25 2002
+++ linux-GPL/drivers/net/bonding.c Wed Jan 29 13:31:21 2003
@@ -504,7 +504,7 @@
}
memset(new_slave, 0, sizeof(slave_t));
- err = netdev_set_master(slave_dev, master_dev);
+ err = netdev_set_master(slave_dev, master_dev, NULL);
if (err) {
#ifdef BONDING_DEBUG
@@ -833,7 +833,7 @@
/* release the slave from its bond */
- netdev_set_master(slave, NULL);
+ netdev_set_master(slave, NULL, NULL);
/* only restore its RUNNING flag if monitoring set it down */
if (slave->flags & IFF_UP) {
diff -wbBurN linux-GPL.orig/include/linux/if_bridge.h
linux-GPL/include/linux/if_bridge.h
--- linux-GPL.orig/include/linux/if_bridge.h Wed Jan 22 13:47:27 2003
+++ linux-GPL/include/linux/if_bridge.h Thu Jan 30 16:16:03 2003
@@ -102,7 +102,6 @@
struct net_bridge_port;
extern int (*br_ioctl_hook)(unsigned long arg);
-extern void (*br_handle_frame_hook)(struct sk_buff *skb);
#endif
diff -wbBurN linux-GPL.orig/include/linux/netdevice.h
linux-GPL/include/linux/netdevice.h
--- linux-GPL.orig/include/linux/netdevice.h Wed Jan 22 13:46:26 2003
+++ linux-GPL/include/linux/netdevice.h Thu Jan 30 16:12:24 2003
@@ -303,6 +303,7 @@
struct net_device *master; /* Pointer to master device of a group,
* which this device is member of.
*/
+ void *master_priv; /* for use by master device */
/* Interface address info. */
unsigned char broadcast[MAX_ADDR_LEN]; /* hw bcast add */
@@ -371,6 +372,7 @@
void *saddr,
unsigned len);
int (*rebuild_header)(struct sk_buff *skb);
+ void (*recv_from_slave)(struct sk_buff *skb);
#define HAVE_MULTICAST
void (*set_multicast_list)(struct net_device *dev);
#define HAVE_SET_MAC_ADDR
@@ -402,9 +404,6 @@
/* open/release and usage marking */
struct module *owner;
- /* bridge stuff */
- struct net_bridge_port *br_port;
-
#ifdef CONFIG_NET_FASTROUTE
#define NETDEV_FASTROUTE_HMASK 0xF
/* Semi-private data. Keep it at the end of device struct. */
@@ -709,7 +708,7 @@
extern int netdev_max_backlog;
extern unsigned long netdev_fc_xoff;
extern atomic_t netdev_dropping;
-extern int netdev_set_master(struct net_device *dev, struct net_device
*master);
+extern int netdev_set_master(struct net_device *dev, struct net_device
+*master, void *master_priv);
extern struct sk_buff * skb_checksum_help(struct sk_buff *skb);
#ifdef CONFIG_NET_FASTROUTE
extern int netdev_fastroute;
diff -wbBurN linux-GPL.orig/net/bridge/br.c linux-GPL/net/bridge/br.c
--- linux-GPL.orig/net/bridge/br.c Fri May 3 13:49:45 2002
+++ linux-GPL/net/bridge/br.c Wed Jan 29 09:42:09 2003
@@ -42,7 +42,6 @@
{
printk(KERN_INFO "NET4: Ethernet Bridge 008 for NET4.0\n");
- br_handle_frame_hook = br_handle_frame;
#ifdef CONFIG_INET
br_ioctl_hook = br_ioctl_deviceless_stub;
#endif
@@ -55,11 +54,6 @@
return 0;
}
-static void __br_clear_frame_hook(void)
-{
- br_handle_frame_hook = NULL;
-}
-
static void __br_clear_ioctl_hook(void)
{
#ifdef CONFIG_INET
@@ -71,7 +65,6 @@
{
unregister_netdevice_notifier(&br_device_notifier);
br_call_ioctl_atomic(__br_clear_ioctl_hook);
- net_call_rx_atomic(__br_clear_frame_hook);
#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
br_fdb_get_hook = NULL;
br_fdb_put_hook = NULL;
diff -wbBurN linux-GPL.orig/net/bridge/br_device.c linux-GPL/net/bridge/br_device.c
--- linux-GPL.orig/net/bridge/br_device.c Fri May 3 13:49:45 2002
+++ linux-GPL/net/bridge/br_device.c Thu Jan 30 13:56:31 2003
@@ -128,6 +128,7 @@
dev->do_ioctl = br_dev_do_ioctl;
dev->get_stats = br_dev_get_stats;
dev->hard_start_xmit = br_dev_xmit;
+ dev->recv_from_slave = br_handle_frame;
dev->open = br_dev_open;
dev->set_multicast_list = br_dev_set_multicast_list;
dev->stop = br_dev_stop;
diff -wbBurN linux-GPL.orig/net/bridge/br_if.c linux-GPL/net/bridge/br_if.c
--- linux-GPL.orig/net/bridge/br_if.c Fri May 3 13:49:45 2002
+++ linux-GPL/net/bridge/br_if.c Fri Jan 31 09:16:14 2003
@@ -43,13 +43,23 @@
struct net_bridge_port *p;
struct net_bridge_port **pptr;
- if ((p = dev->br_port) == NULL)
+ if ((p = dev->master_priv) == NULL)
return -EINVAL;
br_stp_disable_port(p);
dev_set_promiscuity(dev, -1);
- dev->br_port = NULL;
+
+#if 0
+ /* This yields "alloc_skb called nonatomically from interrupt". */
+ netdev_set_master(dev, NULL, NULL);
+#else
+ /* This is the essence of netdev_set_master() but without the locks and
+ * rtmsg_ifinfo(RTM_NEWLINK...) call. */
+ dev->flags &= ~IFF_SLAVE;
+ dev->master = NULL;
+ dev->master_priv = NULL;
+#endif
pptr = &br->port_list;
while (*pptr != NULL) {
@@ -150,8 +160,6 @@
p->path_cost = br_initial_port_cost(dev);
p->priority = 0x80;
- dev->br_port = p;
-
for (i=1;i<255;i++)
if (br_get_port(br, i) == NULL)
break;
@@ -161,6 +169,17 @@
return NULL;
}
+#if 0
+ /* This yields "alloc_skb called nonatomically from interrupt". */
+ netdev_set_master(dev, &br->dev, p);
+#else
+ /* This is the essence of netdev_set_master() but without the locks and
+ * rtmsg_ifinfo(RTM_NEWLINK...) call. */
+ dev->master_priv = p;
+ dev->master = &br->dev;
+ dev->flags |= IFF_SLAVE;
+#endif
+
p->port_no = i;
br_init_port(p);
p->state = BR_STATE_DISABLED;
@@ -220,7 +239,7 @@
{
struct net_bridge_port *p;
- if (dev->br_port != NULL)
+ if (dev->master_priv != NULL)
return -EBUSY;
if (dev->flags & IFF_LOOPBACK || dev->type != ARPHRD_ETHER)
diff -wbBurN linux-GPL.orig/net/bridge/br_input.c linux-GPL/net/bridge/br_input.c
--- linux-GPL.orig/net/bridge/br_input.c Fri May 3 13:49:45 2002
+++ linux-GPL/net/bridge/br_input.c Wed Jan 29 13:28:37 2003
@@ -56,7 +56,7 @@
dest = skb->mac.ethernet->h_dest;
- p = skb->dev->br_port;
+ p = skb->dev->master_priv;
br = p->br;
passedup = 0;
@@ -144,7 +144,7 @@
{
struct net_bridge *br;
- br = skb->dev->br_port->br;
+ br = ((struct net_bridge_port*)skb->dev->master_priv)->br;
read_lock(&br->lock);
__br_handle_frame(skb);
read_unlock(&br->lock);
diff -wbBurN linux-GPL.orig/net/bridge/br_notify.c linux-GPL/net/bridge/br_notify.c
--- linux-GPL.orig/net/bridge/br_notify.c Fri May 3 13:49:45 2002
+++ linux-GPL/net/bridge/br_notify.c Tue Jan 28 15:00:19 2003
@@ -32,7 +32,7 @@
struct net_bridge_port *p;
dev = ptr;
- p = dev->br_port;
+ p = dev->master_priv;
if (p == NULL)
return NOTIFY_DONE;
@@ -53,7 +53,7 @@
case NETDEV_DOWN:
if (p->br->dev.flags & IFF_UP) {
read_lock(&p->br->lock);
- br_stp_disable_port(dev->br_port);
+ br_stp_disable_port(p);
read_unlock(&p->br->lock);
}
break;
@@ -61,13 +61,13 @@
case NETDEV_UP:
if (p->br->dev.flags & IFF_UP) {
read_lock(&p->br->lock);
- br_stp_enable_port(dev->br_port);
+ br_stp_enable_port(p);
read_unlock(&p->br->lock);
}
break;
case NETDEV_UNREGISTER:
- br_del_if(dev->br_port->br, dev);
+ br_del_if(p->br, dev);
break;
}
diff -wbBurN linux-GPL.orig/net/bridge/br_stp_bpdu.c linux-GPL/net/bridge/br_stp_bpdu.c
--- linux-GPL.orig/net/bridge/br_stp_bpdu.c Fri May 3 13:49:45 2002
+++ linux-GPL/net/bridge/br_stp_bpdu.c Tue Jan 28 15:00:55 2003
@@ -139,7 +139,7 @@
struct net_bridge_port *p;
buf = skb->mac.raw + 14;
- p = skb->dev->br_port;
+ p = skb->dev->master_priv;
if (!p->br->stp_enabled || memcmp(buf, header, 6)) {
kfree_skb(skb);
return;
diff -wbBurN linux-GPL.orig/net/core/dev.c linux-GPL/net/core/dev.c
--- linux-GPL.orig/net/core/dev.c Fri May 3 13:49:45 2002
+++ linux-GPL/net/core/dev.c Fri Jan 31 15:46:21 2003
@@ -1307,15 +1307,15 @@
return ret;
}
-/* Reparent skb to master device. This function is called
- * only from net_rx_action under BR_NETPROTO_LOCK. It is misuse
- * of BR_NETPROTO_LOCK, but it is OK for now.
+/* If the master device has no recv_from_slave() handler, just reparent skb to
+ * the master device. This function is called only from net_rx_action under
+ * BR_NETPROTO_LOCK. It is misuse of BR_NETPROTO_LOCK, but it is OK for now.
*/
static __inline__ void skb_bond(struct sk_buff *skb)
{
struct net_device *dev = skb->dev;
- if (dev->master) {
+ if (dev->master && !dev->master->recv_from_slave) {
dev_hold(dev->master);
skb->dev = dev->master;
dev_put(dev);
@@ -1383,11 +1383,7 @@
br_write_unlock_bh(BR_NETPROTO_LOCK);
}
-#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
-void (*br_handle_frame_hook)(struct sk_buff *skb) = NULL;
-#endif
-
-static __inline__ int handle_bridge(struct sk_buff *skb,
+static __inline__ int handle_master_recv(struct sk_buff *skb,
struct packet_type *pt_prev)
{
int ret = NET_RX_DROP;
@@ -1401,7 +1397,7 @@
}
}
- br_handle_frame_hook(skb);
+ skb->dev->master->recv_from_slave(skb);
return ret;
}
@@ -1476,14 +1472,12 @@
#endif /* CONFIG_NET_DIVERT */
-#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
- if (skb->dev->br_port != NULL &&
- br_handle_frame_hook != NULL) {
- handle_bridge(skb, pt_prev);
+ if (skb->dev->master != NULL
+ && skb->dev->master->recv_from_slave != NULL) {
+ handle_master_recv(skb, pt_prev);
dev_put(rx_dev);
continue;
}
-#endif
for (ptype=ptype_base[ntohs(type)&15];ptype;ptype=ptype->next)
{
if (ptype->type == type &&
@@ -1916,6 +1910,7 @@
* netdev_set_master - set up master/slave pair
* @slave: slave device
* @master: new master device
+ * @master_priv: private data for master device
*
* Changes the master device of the slave. Pass %NULL to break the
* bonding. The caller must hold the RTNL semaphore. On a failure
@@ -1924,7 +1919,8 @@
* function returns zero.
*/
-int netdev_set_master(struct net_device *slave, struct net_device *master)
+int netdev_set_master(struct net_device *slave,
+ struct net_device *master, void *master_priv)
{
struct net_device *old = slave->master;
@@ -1938,16 +1934,18 @@
br_write_lock_bh(BR_NETPROTO_LOCK);
slave->master = master;
+ if (master) {
+ slave->master_priv = master_priv;
+ slave->flags |= IFF_SLAVE;
+ } else {
+ slave->master_priv = NULL;
+ slave->flags &= ~IFF_SLAVE;
+ }
br_write_unlock_bh(BR_NETPROTO_LOCK);
if (old)
dev_put(old);
- if (master)
- slave->flags |= IFF_SLAVE;
- else
- slave->flags &= ~IFF_SLAVE;
-
rtmsg_ifinfo(RTM_NEWLINK, slave, IFF_SLAVE);
return 0;
}
diff -wbBurN linux-GPL.orig/net/netsyms.c linux-GPL/net/netsyms.c
--- linux-GPL.orig/net/netsyms.c Thu Sep 5 08:05:15 2002
+++ linux-GPL/net/netsyms.c Wed Jan 29 09:40:44 2003
@@ -227,7 +227,6 @@
EXPORT_SYMBOL(scm_detach_fds);
#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
-EXPORT_SYMBOL(br_handle_frame_hook);
#ifdef CONFIG_INET
EXPORT_SYMBOL(br_ioctl_hook);
#endif
--
Dan Eble <[EMAIL PROTECTED]> _____ .
| _ |/|
Applied Innovation Inc. | |_| | |
http://www.aiinet.com/ |__/|_|_|
_______________________________________________
Bridge mailing list
[EMAIL PROTECTED]
http://www.math.leidenuniv.nl/mailman/listinfo/bridge