The MTU of the local port should be no larger than the minimum of
the MTUs of the ports attached to the bridge, overwise packets may be
dropped. We already prevent changes to the MTU that would violate
this constraint but don't actuallly proactively set the MTU. This
changes makes everything consistent and matches the behavior of
the bridge.
+ set_dp_devs_mtu(dp, dev);
dp_sysfs_add_if(dp->ports[port_no]);
err = __put_user(port_no, &port.port);
dp_sysfs_add_if(dp->ports[port_no]);
err = __put_user(port_no, &port.port);
return mtu ? mtu : ETH_DATA_LEN;
}
return mtu ? mtu : ETH_DATA_LEN;
}
+/* Sets the MTU of all datapath devices to the minimum of the ports. 'dev'
+ * is the device whose MTU may have changed. Must be called with RTNL lock
+ * and dp_mutex. */
+void set_dp_devs_mtu(const struct datapath *dp, struct net_device *dev)
+{
+ struct net_bridge_port *p;
+ int mtu;
+
+ ASSERT_RTNL();
+
+ if (is_dp_dev(dev))
+ return;
+
+ mtu = dp_min_mtu(dp);
+
+ list_for_each_entry_rcu (p, &dp->port_list, node) {
+ struct net_device *br_dev = p->dev;
+
+ if (is_dp_dev(br_dev))
+ dev_set_mtu(br_dev, mtu);
+ }
+}
+
static int
put_port(const struct net_bridge_port *p, struct odp_port __user *uop)
{
static int
put_port(const struct net_bridge_port *p, struct odp_port __user *uop)
{
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);
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);
+void set_dp_devs_mtu(const struct datapath *dp, struct net_device *dev);
struct datapath *get_dp(int dp_idx);
struct datapath *get_dp(int dp_idx);
mutex_unlock(&dp->mutex);
}
break;
mutex_unlock(&dp->mutex);
}
break;
+
+ case NETDEV_CHANGEMTU:
+ if (!is_dp_dev(dev)) {
+ mutex_lock(&dp->mutex);
+ set_dp_devs_mtu(dp, dev);
+ mutex_unlock(&dp->mutex);
+ }
+ break;