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)
{
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);
.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);
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;