datapath: Support jumbo frames in the datapath device
authorJustin Pettit <jpettit@nicira.com>
Sat, 1 Aug 2009 07:09:56 +0000 (00:09 -0700)
committerJustin Pettit <jpettit@nicira.com>
Mon, 3 Aug 2009 20:29:22 +0000 (13:29 -0700)
The datapath has no problems switching jumbo frames (frames with a payload
greater than 1500 bytes), but it has not supported sending and receiving
them to the device itself.  With this commit, the MTU can be set as large
as the minimum MTU size of the devices that are directly attached, or 1500
bytes if there are none.  This mimics the behavior of the Linux bridge.

Feature #1736

datapath/datapath.c
datapath/datapath.h
datapath/dp_dev.c

index 5e1a352..43d96fb 100644 (file)
@@ -1184,6 +1184,29 @@ get_dp_stats(struct datapath *dp, struct odp_stats __user *statsp)
        return copy_to_user(statsp, &stats, sizeof stats) ? -EFAULT : 0;
 }
 
+/* MTU of the dp pseudo-device: ETH_DATA_LEN or the minimum of the ports */
+int dp_min_mtu(const struct datapath *dp)
+{
+       struct net_bridge_port *p;
+       int mtu = 0;
+
+       ASSERT_RTNL();
+
+       list_for_each_entry_rcu (p, &dp->port_list, node) {
+               struct net_device *dev = p->dev;
+
+               /* Skip any internal ports, since that's what we're trying to
+                * set. */
+               if (is_dp_dev(dev))
+                       continue;
+
+               if (!mtu || dev->mtu < mtu)
+                       mtu = dev->mtu;
+       }
+
+       return mtu ? mtu : ETH_DATA_LEN;
+}
+
 static int
 put_port(const struct net_bridge_port *p, struct odp_port __user *uop)
 {
index 455580f..a03597d 100644 (file)
@@ -122,6 +122,7 @@ int dp_table_foreach(struct dp_table *table,
 void dp_process_received_packet(struct sk_buff *, struct net_bridge_port *);
 int dp_del_port(struct net_bridge_port *);
 int dp_output_control(struct datapath *, struct sk_buff *, int, u32 arg);
+int dp_min_mtu(const struct datapath *dp);
 
 struct datapath *get_dp(int dp_idx);
 
index 3902a8c..422af02 100644 (file)
@@ -130,6 +130,15 @@ static struct ethtool_ops dp_ethtool_ops = {
        .get_tso = ethtool_op_get_tso,
 };
 
+static int dp_dev_change_mtu(struct net_device *dev, int new_mtu)
+{
+       if (new_mtu < 68 || new_mtu > dp_min_mtu(dp_dev_get_dp(dev)))
+               return -EINVAL;
+
+       dev->mtu = new_mtu;
+       return 0;
+}
+
 static int dp_dev_init(struct net_device *netdev)
 {
        struct dp_dev *dp_dev = dp_dev_priv(netdev);
@@ -162,6 +171,7 @@ do_setup(struct net_device *netdev)
        netdev->stop = dp_dev_stop;
        netdev->tx_queue_len = 0;
        netdev->set_mac_address = dp_dev_mac_addr;
+       netdev->change_mtu = dp_dev_change_mtu;
        netdev->init = dp_dev_init;
        netdev->destructor = dp_dev_free;