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

Reply via email to