netdev
[Top] [All Lists]

[PATCH 2.6] bridge -- support different MTU sizes

To: "David S. Miller" <davem@xxxxxxxxxx>
Subject: [PATCH 2.6] bridge -- support different MTU sizes
From: Stephen Hemminger <shemminger@xxxxxxxx>
Date: Thu, 8 Jul 2004 10:41:43 -0700
Cc: bridge@xxxxxxxx, netdev@xxxxxxxxxxx
Organization: Open Source Development Lab
Sender: netdev-bounce@xxxxxxxxxxx
This patch adds support for different size MTU's to bridging.
It is useful for bridging Ethernet's with jumbo frames, etc.

The mtu of the bridge pseudo-device is maintained as the minimum
of all the underlying ports.  And when forwarding a frame through
the bridge, it will drop the frame if the outgoing port's MTU
is less than the frame size (as per 802 standard).

Signed-off-by: Stephen Hemminger <shemminger@xxxxxxxx>


diff -Nru a/net/bridge/br_device.c b/net/bridge/br_device.c
--- a/net/bridge/br_device.c    2004-06-30 11:48:01 -07:00
+++ b/net/bridge/br_device.c    2004-06-30 11:48:01 -07:00
@@ -89,6 +89,15 @@
        return 0;
 }
 
+static int br_change_mtu(struct net_device *dev, int new_mtu)
+{
+       if ((new_mtu < 68) || new_mtu > br_min_mtu(dev->priv))
+               return -EINVAL;
+
+       dev->mtu = new_mtu;
+       return 0;
+}
+
 static int br_dev_accept_fastpath(struct net_device *dev, struct dst_entry 
*dst)
 {
        return -1;
@@ -105,6 +114,7 @@
        dev->hard_start_xmit = br_dev_xmit;
        dev->open = br_dev_open;
        dev->set_multicast_list = br_dev_set_multicast_list;
+       dev->change_mtu = br_change_mtu;
        dev->destructor = free_netdev;
        SET_MODULE_OWNER(dev);
        dev->stop = br_dev_stop;
diff -Nru a/net/bridge/br_forward.c b/net/bridge/br_forward.c
--- a/net/bridge/br_forward.c   2004-06-30 11:48:01 -07:00
+++ b/net/bridge/br_forward.c   2004-06-30 11:48:01 -07:00
@@ -22,7 +22,8 @@
 static inline int should_deliver(const struct net_bridge_port *p, 
                                 const struct sk_buff *skb)
 {
-       if (skb->dev == p->dev ||
+       if (skb->dev == p->dev ||
+           skb->len > p->dev->mtu ||
            p->state != BR_STATE_FORWARDING)
                return 0;
 
diff -Nru a/net/bridge/br_if.c b/net/bridge/br_if.c
--- a/net/bridge/br_if.c        2004-06-30 11:48:01 -07:00
+++ b/net/bridge/br_if.c        2004-06-30 11:48:01 -07:00
@@ -295,6 +295,24 @@
        return ret;
 }
 
+int br_min_mtu(const struct net_bridge *br)
+{
+       const struct net_bridge_port *p;
+       int mtu = 0;
+
+       ASSERT_RTNL();
+
+       if (list_empty(&br->port_list))
+               mtu = 1500;
+       else {
+               list_for_each_entry(p, &br->port_list, list) {
+                       if (!mtu  || p->dev->mtu < mtu)
+                               mtu = p->dev->mtu;
+               }
+       }
+       return mtu;
+}
+
 /* called with RTNL */
 int br_add_if(struct net_bridge *br, struct net_device *dev)
 {
@@ -328,6 +346,8 @@
                if ((br->dev->flags & IFF_UP) && (dev->flags & IFF_UP))
                        br_stp_enable_port(p);
                spin_unlock_bh(&br->lock);
+
+               br->dev->mtu = br_min_mtu(br);
        }
 
        return err;
diff -Nru a/net/bridge/br_notify.c b/net/bridge/br_notify.c
--- a/net/bridge/br_notify.c    2004-06-30 11:48:01 -07:00
+++ b/net/bridge/br_notify.c    2004-06-30 11:48:01 -07:00
@@ -47,6 +47,10 @@
                spin_unlock_bh(&br->lock);
                break;
 
+       case NETDEV_CHANGEMTU:
+               br->dev->mtu = br_min_mtu(br);
+               break;
+
        case NETDEV_DOWN:
                if (br->dev->flags & IFF_UP) {
                        spin_lock_bh(&br->lock);
diff -Nru a/net/bridge/br_private.h b/net/bridge/br_private.h
--- a/net/bridge/br_private.h   2004-06-30 11:48:01 -07:00
+++ b/net/bridge/br_private.h   2004-06-30 11:48:01 -07:00
@@ -168,6 +168,7 @@
              struct net_device *dev);
 extern int br_del_if(struct net_bridge *br,
              struct net_device *dev);
+extern int br_min_mtu(const struct net_bridge *br);
 
 /* br_input.c */
 extern int br_handle_frame_finish(struct sk_buff *skb);

<Prev in Thread] Current Thread [Next in Thread>