summaryrefslogtreecommitdiff
path: root/ofproto
diff options
context:
space:
mode:
authorJustin Pettit <jpettit@nicira.com>2011-09-12 22:13:30 -0700
committerJustin Pettit <jpettit@nicira.com>2011-09-15 16:27:15 -0700
commit9197df76b46ff6fbe1f7a522961730ffc55a860d (patch)
tree402b36b11221efbcebef6785db1fb358de483af9 /ofproto
parenta89721b529d83aac3a09d5027a01756771c78187 (diff)
downloadopenvswitch-9197df76b46ff6fbe1f7a522961730ffc55a860d.tar.gz
Set MTU in userspace rather than kernel.
Currently the kernel automatically sets the MTU of any internal interfaces to the minimum of all attached interfaces because the Linux bridge does this. Userspace can do this with more knowledge and flexibility. Feature #7323 Signed-off-by: Justin Pettit <jpettit@nicira.com> Acked-by: Jesse Gross <jesse@nicira.com>
Diffstat (limited to 'ofproto')
-rw-r--r--ofproto/ofproto-provider.h1
-rw-r--r--ofproto/ofproto.c65
2 files changed, 66 insertions, 0 deletions
diff --git a/ofproto/ofproto-provider.h b/ofproto/ofproto-provider.h
index 3037bb2e9..f596abcba 100644
--- a/ofproto/ofproto-provider.h
+++ b/ofproto/ofproto-provider.h
@@ -93,6 +93,7 @@ struct ofport {
struct ofp_phy_port opp;
uint16_t ofp_port; /* OpenFlow port number. */
unsigned int change_seq;
+ int mtu;
};
/* An OpenFlow flow within a "struct ofproto".
diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
index 7748ef1b8..1309b492a 100644
--- a/ofproto/ofproto.c
+++ b/ofproto/ofproto.c
@@ -147,6 +147,7 @@ static int handle_flow_mod__(struct ofproto *, struct ofconn *,
static void update_port(struct ofproto *, const char *devname);
static int init_ports(struct ofproto *);
static void reinit_ports(struct ofproto *);
+static void set_internal_devs_mtu(struct ofproto *);
static void ofproto_unixctl_init(void);
@@ -1193,6 +1194,7 @@ ofport_install(struct ofproto *p,
{
const char *netdev_name = netdev_get_name(netdev);
struct ofport *ofport;
+ int dev_mtu;
int error;
/* Create ofport. */
@@ -1211,6 +1213,13 @@ ofport_install(struct ofproto *p,
hmap_insert(&p->ports, &ofport->hmap_node, hash_int(ofport->ofp_port, 0));
shash_add(&p->port_by_name, netdev_name, ofport);
+ if (!netdev_get_mtu(netdev, &dev_mtu)) {
+ set_internal_devs_mtu(p);
+ ofport->mtu = dev_mtu;
+ } else {
+ ofport->mtu = 0;
+ }
+
/* Let the ofproto_class initialize its private data. */
error = p->ofproto_class->port_construct(ofport);
if (error) {
@@ -1337,12 +1346,22 @@ update_port(struct ofproto *ofproto, const char *name)
port = ofproto_get_port(ofproto, ofproto_port.ofp_port);
if (port && !strcmp(netdev_get_name(port->netdev), name)) {
struct netdev *old_netdev = port->netdev;
+ int dev_mtu;
/* 'name' hasn't changed location. Any properties changed? */
if (!ofport_equal(&port->opp, &opp)) {
ofport_modified(port, &opp);
}
+ /* If this is a non-internal port and the MTU changed, check
+ * if the datapath's MTU needs to be updated. */
+ if (strcmp(netdev_get_type(netdev), "internal")
+ && !netdev_get_mtu(netdev, &dev_mtu)
+ && port->mtu != dev_mtu) {
+ set_internal_devs_mtu(ofproto);
+ port->mtu = dev_mtu;
+ }
+
/* Install the newly opened netdev in case it has changed.
* Don't close the old netdev yet in case port_modified has to
* remove a retained reference to it.*/
@@ -1398,6 +1417,52 @@ init_ports(struct ofproto *p)
return 0;
}
+
+/* Find the minimum MTU of all non-datapath devices attached to 'p'.
+ * Returns ETH_PAYLOAD_MAX or the minimum of the ports. */
+static int
+find_min_mtu(struct ofproto *p)
+{
+ struct ofport *ofport;
+ int mtu = 0;
+
+ HMAP_FOR_EACH (ofport, hmap_node, &p->ports) {
+ struct netdev *netdev = ofport->netdev;
+ int dev_mtu;
+
+ /* Skip any internal ports, since that's what we're trying to
+ * set. */
+ if (!strcmp(netdev_get_type(netdev), "internal")) {
+ continue;
+ }
+
+ if (netdev_get_mtu(netdev, &dev_mtu)) {
+ continue;
+ }
+ if (!mtu || dev_mtu < mtu) {
+ mtu = dev_mtu;
+ }
+ }
+
+ return mtu ? mtu: ETH_PAYLOAD_MAX;
+}
+
+/* Set the MTU of all datapath devices on 'p' to the minimum of the
+ * non-datapath ports. */
+static void
+set_internal_devs_mtu(struct ofproto *p)
+{
+ struct ofport *ofport;
+ int mtu = find_min_mtu(p);
+
+ HMAP_FOR_EACH (ofport, hmap_node, &p->ports) {
+ struct netdev *netdev = ofport->netdev;
+
+ if (!strcmp(netdev_get_type(netdev), "internal")) {
+ netdev_set_mtu(netdev, mtu);
+ }
+ }
+}
static void
ofproto_rule_destroy__(struct rule *rule)