[ovs-dev] [PATCH] datapath: Consider tunnels to have no MTU, fixing jumbo frame support.
Ben Pfaff
blp at nicira.com
Tue Feb 1 19:32:14 UTC 2011
On Mon, Jan 31, 2011 at 11:53:06AM -0800, Jesse Gross wrote:
> On Thu, Jan 13, 2011 at 3:58 PM, Ben Pfaff <blp at nicira.com> wrote:
> > diff --git a/datapath/tunnel.c b/datapath/tunnel.c
> > index 46f966b..08d2552 100644
> > --- a/datapath/tunnel.c
> > +++ b/datapath/tunnel.c
> > @@ -720,13 +719,9 @@ static bool check_mtu(struct sk_buff *skb,
> > ? ? ? ?__be16 frag_off;
> >
> > ? ? ? ?frag_off = (mutable->port_config.flags & TNL_F_PMTUD) ? htons(IP_DF) : 0;
> > - ? ? ? if (frag_off)
> > - ? ? ? ? ? ? ? mtu = dst_mtu(&rt_dst(rt))
> > - ? ? ? ? ? ? ? ? ? ? ? - ETH_HLEN
> > - ? ? ? ? ? ? ? ? ? ? ? - mutable->tunnel_hlen
> > - ? ? ? ? ? ? ? ? ? ? ? - (eth_hdr(skb)->h_proto == htons(ETH_P_8021Q) ? VLAN_HLEN : 0);
> > - ? ? ? else
> > - ? ? ? ? ? ? ? mtu = mutable->mtu;
> > + ? ? ? mtu = dst_mtu(&rt_dst(rt)) - ETH_HLEN - mutable->tunnel_hlen;
> > + ? ? ? if (eth_hdr(skb)->h_proto)
> > + ? ? ? ? ? ? ? mtu -= VLAN_HLEN;
> >
> > ? ? ? ?if (skb->protocol == htons(ETH_P_IP)) {
> > ? ? ? ? ? ? ? ?struct iphdr *old_iph = ip_hdr(skb);
>
> I don't think this section is right because it will effectively always
> force PMTUD on inside tunnels. However, I believe that the patch that
> I sent out that touches this area will avoid the problem, as it drops
> usage of mutable->mtu here.
Thanks. I verified that stacking my patch on top of yours, dropping my
changes to check_mtu(), worked OK.
> Also, I think that this was added after the patch was written but just
> so it doesn't get lost: bridge.c now calls netdev_get_mtu() to put the
> MTU in the database. This should probably now check that we have an
> MTU.
Thanks, I made that update.
> Otherwise looks good.
There were lots of conflicts on the rebase, and I can't usefully push
this until you push your change, so here's the new version.
--8<--------------------------cut here-------------------------->8--
From: Ben Pfaff <blp at nicira.com>
Date: Tue, 1 Feb 2011 11:27:44 -0800
Subject: [PATCH] datapath: Consider tunnels to have no MTU, fixing jumbo frame support.
Until now, tunnel vports have had a specific MTU, in the same way that
ordinary network devices have an MTU, but treating them this way does not
always make sense. For example, consider a datapath that has three ports:
the local port, a GRE tunnel to another host, and a physical port. If
the physical port is configured with a jumbo MTU, it should be possible to
send jumbo packets across the tunnel: the tunnel can do fragmentation or
the physical port traversed by the tunnel might have a jumbo MTU.
However, until now, tunnels always had a 1500-byte MTU by default. It
could be adjusted using ODP_VPORT_MTU_SET, but nothing actually did this.
One alternative would be to make ovs-vswitchd able to set the vport's MTU.
This commit, however, takes a different approach, of dropping the concept
of MTU entirely for tunnel vports. This also solves the problem described
above, without making any additional work for anyone.
I tested that, without this change, I could not send 1600-byte "pings"
between two machines whose NICs had 2000-byte MTUs that were connected to
vswitches that were in turn connected over GRE tunnels with the default
1500-byte MTU. With this change, it worked OK, regardless of the MTU of
the network traversed by the GRE tunnel.
This patch also makes "patch" ports MTU-less.
It might make sense to remove vport_set_mtu() and the associated callback
now, since ordinary network devices are the only vports that support it
now.
Signed-off-by: Ben Pfaff <blp at nicira.com>
Suggested-by: Jesse Gross <jesse at nicira.com>
Bug #3728.
---
datapath/datapath.c | 7 ++++++-
datapath/tunnel.c | 25 -------------------------
datapath/tunnel.h | 4 ----
datapath/vport-capwap.c | 2 --
datapath/vport-gre.c | 2 --
datapath/vport-patch.c | 29 -----------------------------
datapath/vport.c | 10 ++++++----
datapath/vport.h | 3 ++-
include/openvswitch/datapath-protocol.h | 3 ++-
lib/dhcp-client.c | 6 ++----
lib/dpif-linux.c | 4 +++-
lib/dpif-netdev.c | 2 +-
lib/netdev-linux.c | 13 ++++++++++++-
lib/netdev-provider.h | 7 +++++--
lib/netdev.c | 7 ++++---
vswitchd/bridge.c | 2 +-
vswitchd/vswitch.xml | 4 ++++
17 files changed, 48 insertions(+), 82 deletions(-)
diff --git a/datapath/datapath.c b/datapath/datapath.c
index 74f276b..ba32e37 100644
--- a/datapath/datapath.c
+++ b/datapath/datapath.c
@@ -773,6 +773,8 @@ int dp_min_mtu(const struct datapath *dp)
continue;
dev_mtu = vport_get_mtu(p);
+ if (!dev_mtu)
+ continue;
if (!mtu || dev_mtu < mtu)
mtu = dev_mtu;
}
@@ -1582,6 +1584,7 @@ static int odp_vport_cmd_fill_info(struct vport *vport, struct sk_buff *skb,
struct odp_header *odp_header;
struct nlattr *nla;
int ifindex, iflink;
+ int mtu;
int err;
odp_header = genlmsg_put(skb, pid, seq, &dp_vport_genl_family,
@@ -1603,7 +1606,9 @@ static int odp_vport_cmd_fill_info(struct vport *vport, struct sk_buff *skb,
NLA_PUT(skb, ODP_VPORT_ATTR_ADDRESS, ETH_ALEN, vport_get_addr(vport));
- NLA_PUT_U32(skb, ODP_VPORT_ATTR_MTU, vport_get_mtu(vport));
+ mtu = vport_get_mtu(vport);
+ if (mtu)
+ NLA_PUT_U32(skb, ODP_VPORT_ATTR_MTU, mtu);
err = vport_get_options(vport, skb);
if (err == -EMSGSIZE)
diff --git a/datapath/tunnel.c b/datapath/tunnel.c
index b06e19e..417b47e 100644
--- a/datapath/tunnel.c
+++ b/datapath/tunnel.c
@@ -663,7 +663,6 @@ bool tnl_frag_needed(struct vport *vport, const struct tnl_mutable_config *mutab
}
#endif
- total_length = min(total_length, mutable->mtu);
payload_length = total_length - header_length;
nskb = dev_alloc_skb(NET_IP_ALIGN + eth_hdr_len + header_length +
@@ -1428,7 +1427,6 @@ struct vport *tnl_create(const struct vport_parms *parms,
}
vport_gen_rand_ether_addr(mutable->eth_addr);
- mutable->mtu = ETH_DATA_LEN;
get_random_bytes(&initial_frag_id, sizeof(int));
atomic_set(&tnl_vport->frag_id, initial_frag_id);
@@ -1477,7 +1475,6 @@ int tnl_set_options(struct vport *vport, struct nlattr *options)
old_mutable = rtnl_dereference(tnl_vport->mutable);
mutable->seq = old_mutable->seq + 1;
memcpy(mutable->eth_addr, old_mutable->eth_addr, ETH_ALEN);
- mutable->mtu = old_mutable->mtu;
/* Parse the others configured by userspace. */
err = tnl_set_config(options, tnl_vport->tnl_ops, vport, mutable);
@@ -1548,22 +1545,6 @@ int tnl_destroy(struct vport *vport)
return 0;
}
-int tnl_set_mtu(struct vport *vport, int mtu)
-{
- struct tnl_vport *tnl_vport = tnl_vport_priv(vport);
- struct tnl_mutable_config *mutable;
-
- mutable = kmemdup(rtnl_dereference(tnl_vport->mutable),
- sizeof(struct tnl_mutable_config), GFP_KERNEL);
- if (!mutable)
- return -ENOMEM;
-
- mutable->mtu = mtu;
- assign_config_rcu(vport, mutable);
-
- return 0;
-}
-
int tnl_set_addr(struct vport *vport, const unsigned char *addr)
{
struct tnl_vport *tnl_vport = tnl_vport_priv(vport);
@@ -1592,12 +1573,6 @@ const unsigned char *tnl_get_addr(const struct vport *vport)
return rcu_dereference_rtnl(tnl_vport->mutable)->eth_addr;
}
-int tnl_get_mtu(const struct vport *vport)
-{
- const struct tnl_vport *tnl_vport = tnl_vport_priv(vport);
- return rcu_dereference_rtnl(tnl_vport->mutable)->mtu;
-}
-
void tnl_free_linked_skbs(struct sk_buff *skb)
{
if (unlikely(!skb))
diff --git a/datapath/tunnel.h b/datapath/tunnel.h
index c3bc8dd..6ce9c46 100644
--- a/datapath/tunnel.h
+++ b/datapath/tunnel.h
@@ -52,7 +52,6 @@
* @tunnel_hlen: Tunnel header length.
* @eth_addr: Source address for packets generated by tunnel itself
* (e.g. ICMP fragmentation needed messages).
- * @mtu: MTU of tunnel.
* @in_key: Key to match on input, 0 for wildcard.
* @out_key: Key to use on output, 0 if this tunnel has no fixed output key.
* @flags: TNL_F_* flags.
@@ -70,7 +69,6 @@ struct tnl_mutable_config {
unsigned tunnel_hlen;
unsigned char eth_addr[ETH_ALEN];
- unsigned mtu;
/* Configured via ODP_TUNNEL_ATTR_* attributes. */
__be64 in_key;
@@ -223,11 +221,9 @@ int tnl_destroy(struct vport *);
int tnl_set_options(struct vport *, struct nlattr *);
int tnl_get_options(const struct vport *, struct sk_buff *);
-int tnl_set_mtu(struct vport *vport, int mtu);
int tnl_set_addr(struct vport *vport, const unsigned char *addr);
const char *tnl_get_name(const struct vport *vport);
const unsigned char *tnl_get_addr(const struct vport *vport);
-int tnl_get_mtu(const struct vport *vport);
int tnl_send(struct vport *vport, struct sk_buff *skb);
void tnl_rcv(struct vport *vport, struct sk_buff *skb);
diff --git a/datapath/vport-capwap.c b/datapath/vport-capwap.c
index 4fb4393..65f1f1b 100644
--- a/datapath/vport-capwap.c
+++ b/datapath/vport-capwap.c
@@ -654,7 +654,6 @@ const struct vport_ops capwap_vport_ops = {
.exit = capwap_exit,
.create = capwap_create,
.destroy = tnl_destroy,
- .set_mtu = tnl_set_mtu,
.set_addr = tnl_set_addr,
.get_name = tnl_get_name,
.get_addr = tnl_get_addr,
@@ -663,7 +662,6 @@ const struct vport_ops capwap_vport_ops = {
.get_dev_flags = vport_gen_get_dev_flags,
.is_running = vport_gen_is_running,
.get_operstate = vport_gen_get_operstate,
- .get_mtu = tnl_get_mtu,
.send = tnl_send,
};
diff --git a/datapath/vport-gre.c b/datapath/vport-gre.c
index fc489e9..0f45f8f 100644
--- a/datapath/vport-gre.c
+++ b/datapath/vport-gre.c
@@ -391,7 +391,6 @@ const struct vport_ops gre_vport_ops = {
.exit = gre_exit,
.create = gre_create,
.destroy = tnl_destroy,
- .set_mtu = tnl_set_mtu,
.set_addr = tnl_set_addr,
.get_name = tnl_get_name,
.get_addr = tnl_get_addr,
@@ -400,6 +399,5 @@ const struct vport_ops gre_vport_ops = {
.get_dev_flags = vport_gen_get_dev_flags,
.is_running = vport_gen_is_running,
.get_operstate = vport_gen_get_operstate,
- .get_mtu = tnl_get_mtu,
.send = tnl_send,
};
diff --git a/datapath/vport-patch.c b/datapath/vport-patch.c
index 7dfea6b..1c4d2c5 100644
--- a/datapath/vport-patch.c
+++ b/datapath/vport-patch.c
@@ -20,7 +20,6 @@ struct patch_config {
char peer_name[IFNAMSIZ];
unsigned char eth_addr[ETH_ALEN];
- unsigned int mtu;
};
struct patch_vport {
@@ -148,10 +147,6 @@ static struct vport *patch_create(const struct vport_parms *parms)
vport_gen_rand_ether_addr(patchconf->eth_addr);
- /* Make the default MTU fairly large so that it doesn't become the
- * bottleneck on systems using jumbo frames. */
- patchconf->mtu = 65535;
-
rcu_assign_pointer(patch_vport->patchconf, patchconf);
peer_name = patchconf->peer_name;
@@ -236,22 +231,6 @@ static void update_peers(const char *name, struct vport *vport)
}
}
-static int patch_set_mtu(struct vport *vport, int mtu)
-{
- struct patch_vport *patch_vport = patch_vport_priv(vport);
- struct patch_config *patchconf;
-
- patchconf = kmemdup(rtnl_dereference(patch_vport->patchconf),
- sizeof(struct patch_config), GFP_KERNEL);
- if (!patchconf)
- return -ENOMEM;
-
- patchconf->mtu = mtu;
- assign_config_rcu(vport, patchconf);
-
- return 0;
-}
-
static int patch_set_addr(struct vport *vport, const unsigned char *addr)
{
struct patch_vport *patch_vport = patch_vport_priv(vport);
@@ -289,12 +268,6 @@ static int patch_get_options(const struct vport *vport, struct sk_buff *skb)
return nla_put_string(skb, ODP_PATCH_ATTR_PEER, patchconf->peer_name);
}
-static int patch_get_mtu(const struct vport *vport)
-{
- const struct patch_vport *patch_vport = patch_vport_priv(vport);
- return rcu_dereference_rtnl(patch_vport->patchconf)->mtu;
-}
-
static int patch_send(struct vport *vport, struct sk_buff *skb)
{
struct patch_vport *patch_vport = patch_vport_priv(vport);
@@ -319,7 +292,6 @@ const struct vport_ops patch_vport_ops = {
.exit = patch_exit,
.create = patch_create,
.destroy = patch_destroy,
- .set_mtu = patch_set_mtu,
.set_addr = patch_set_addr,
.get_name = patch_get_name,
.get_addr = patch_get_addr,
@@ -328,6 +300,5 @@ const struct vport_ops patch_vport_ops = {
.get_dev_flags = vport_gen_get_dev_flags,
.is_running = vport_gen_is_running,
.get_operstate = vport_gen_get_operstate,
- .get_mtu = patch_get_mtu,
.send = patch_send,
};
diff --git a/datapath/vport.c b/datapath/vport.c
index 852a3c6..8ef96f7 100644
--- a/datapath/vport.c
+++ b/datapath/vport.c
@@ -605,12 +605,14 @@ int vport_get_iflink(const struct vport *vport)
*
* @vport: vport from which to retrieve MTU
*
- * Retrieves the MTU of the given device.
- *
- * Must be called with RTNL lock or rcu_read_lock.
+ * Retrieves the MTU of the given device. Returns 0 if @vport does not have an
+ * MTU (as e.g. some tunnels do not). Either RTNL lock or rcu_read_lock must
+ * be held.
*/
int vport_get_mtu(const struct vport *vport)
{
+ if (!vport->ops->get_mtu)
+ return 0;
return vport->ops->get_mtu(vport);
}
@@ -710,7 +712,7 @@ int vport_send(struct vport *vport, struct sk_buff *skb)
int sent;
mtu = vport_get_mtu(vport);
- if (unlikely(packet_length(skb) > mtu && !skb_is_gso(skb))) {
+ if (mtu && unlikely(packet_length(skb) > mtu && !skb_is_gso(skb))) {
if (net_ratelimit())
pr_warn("%s: dropped over-mtu packet: %d > %d\n",
dp_name(vport->dp), packet_length(skb), mtu);
diff --git a/datapath/vport.h b/datapath/vport.h
index ee3b127..8e70762 100644
--- a/datapath/vport.h
+++ b/datapath/vport.h
@@ -175,7 +175,8 @@ struct vport_parms {
* @get_iflink: Get the system interface index associated with the device that
* will be used to send packets (may be different than ifindex for tunnels).
* May be null if the device does not have an iflink.
- * @get_mtu: Get the device's MTU.
+ * @get_mtu: Get the device's MTU. May be %NULL if the device does not have an
+ * MTU (as e.g. some tunnels do not).
* @send: Send a packet on the device. Returns the length of the packet sent.
*/
struct vport_ops {
diff --git a/include/openvswitch/datapath-protocol.h b/include/openvswitch/datapath-protocol.h
index 1fb0bf9..de36194 100644
--- a/include/openvswitch/datapath-protocol.h
+++ b/include/openvswitch/datapath-protocol.h
@@ -237,7 +237,8 @@ enum odp_vport_cmd {
* @ODP_VPORT_ATTR_STATS: A &struct rtnl_link_stats64 giving statistics for
* packets sent or received through the vport.
* @ODP_VPORT_ATTR_ADDRESS: A 6-byte Ethernet address for the vport.
- * @ODP_VPORT_ATTR_MTU: MTU for the vport.
+ * @ODP_VPORT_ATTR_MTU: MTU for the vport. Omitted if the vport does not have
+ * an MTU as, e.g., some tunnels do not.
* @ODP_VPORT_ATTR_IFINDEX: ifindex of the underlying network device, if any.
* @ODP_VPORT_ATTR_IFLINK: ifindex of the device on which packets are sent (for
* tunnels), if any.
diff --git a/lib/dhcp-client.c b/lib/dhcp-client.c
index 74fa44c..605c5df 100644
--- a/lib/dhcp-client.c
+++ b/lib/dhcp-client.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2009, 2010 Nicira Networks.
+ * Copyright (c) 2008, 2009, 2010, 2011 Nicira Networks.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -934,10 +934,8 @@ do_receive_msg(struct dhclient *cli, struct dhcp_msg *msg)
const char *cli_name = dhclient_get_name(cli);
uint8_t cli_mac[ETH_ADDR_LEN];
struct ofpbuf b;
- int mtu;
- netdev_get_mtu(cli->netdev, &mtu);
- ofpbuf_init(&b, mtu + VLAN_ETH_HEADER_LEN);
+ ofpbuf_init(&b, ETH_TOTAL_MAX + VLAN_ETH_HEADER_LEN);
netdev_get_etheraddr(cli->netdev, cli_mac);
for (; cli->received < 50; cli->received++) {
const struct ip_header *ip;
diff --git a/lib/dpif-linux.c b/lib/dpif-linux.c
index f1d42dc..509174c 100644
--- a/lib/dpif-linux.c
+++ b/lib/dpif-linux.c
@@ -1108,6 +1108,8 @@ dpif_linux_vport_from_ofpbuf(struct dpif_linux_vport *vport,
}
if (a[ODP_VPORT_ATTR_MTU]) {
vport->mtu = nl_attr_get_u32(a[ODP_VPORT_ATTR_MTU]);
+ } else {
+ vport->mtu = INT_MAX;
}
if (a[ODP_VPORT_ATTR_OPTIONS]) {
vport->options = nl_attr_get(a[ODP_VPORT_ATTR_OPTIONS]);
@@ -1158,7 +1160,7 @@ dpif_linux_vport_to_ofpbuf(const struct dpif_linux_vport *vport,
vport->address, ETH_ADDR_LEN);
}
- if (vport->mtu) {
+ if (vport->mtu && vport->mtu != INT_MAX) {
nl_msg_put_u32(buf, ODP_VPORT_ATTR_MTU, vport->mtu);
}
diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
index 417ed6e..531493d 100644
--- a/lib/dpif-netdev.c
+++ b/lib/dpif-netdev.c
@@ -375,7 +375,7 @@ do_add_port(struct dp_netdev *dp, const char *devname, const char *type,
port->internal = internal;
netdev_get_mtu(netdev, &mtu);
- if (mtu > max_mtu) {
+ if (mtu != INT_MAX && mtu > max_mtu) {
max_mtu = mtu;
}
diff --git a/lib/netdev-linux.c b/lib/netdev-linux.c
index 9deea57..1428ce6 100644
--- a/lib/netdev-linux.c
+++ b/lib/netdev-linux.c
@@ -2365,6 +2365,11 @@ htb_setup_class__(struct netdev *netdev, unsigned int handle,
int mtu;
netdev_get_mtu(netdev, &mtu);
+ if (mtu == INT_MAX) {
+ VLOG_WARN_RL(&rl, "cannot set up HTB on device %s that lacks MTU",
+ netdev_get_name(netdev));
+ return EINVAL;
+ }
memset(&opt, 0, sizeof opt);
tc_fill_rate(&opt.rate, class->min_rate, mtu);
@@ -2484,6 +2489,13 @@ htb_parse_class_details__(struct netdev *netdev,
const char *priority_s = shash_find_data(details, "priority");
int mtu;
+ netdev_get_mtu(netdev, &mtu);
+ if (mtu == INT_MAX) {
+ VLOG_WARN_RL(&rl, "cannot parse HTB class on device %s that lacks MTU",
+ netdev_get_name(netdev));
+ return EINVAL;
+ }
+
/* min-rate. Don't allow a min-rate below 1500 bytes/s. */
if (!min_rate_s) {
/* min-rate is required. */
@@ -2509,7 +2521,6 @@ htb_parse_class_details__(struct netdev *netdev,
* doesn't include the Ethernet header, we need to add at least 14 (18?) to
* the MTU. We actually add 64, instead of 14, as a guard against
* additional headers get tacked on somewhere that we're not aware of. */
- netdev_get_mtu(netdev, &mtu);
hc->burst = burst_s ? strtoull(burst_s, NULL, 10) / 8 : 0;
hc->burst = MAX(hc->burst, mtu + 64);
diff --git a/lib/netdev-provider.h b/lib/netdev-provider.h
index 4181758..be51c48 100644
--- a/lib/netdev-provider.h
+++ b/lib/netdev-provider.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, 2010 Nicira Networks.
+ * Copyright (c) 2009, 2010, 2011 Nicira Networks.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -237,7 +237,10 @@ struct netdev_class {
*
* The MTU is the maximum size of transmitted (and received) packets, in
* bytes, not including the hardware header; thus, this is typically 1500
- * bytes for Ethernet devices.*/
+ * bytes for Ethernet devices.
+ *
+ * If 'netdev' does not have an MTU (e.g. as some tunnels do not), then
+ * this function should set '*mtup' to INT_MAX. */
int (*get_mtu)(const struct netdev *netdev, int *mtup);
/* Returns the ifindex of 'netdev', if successful, as a positive number.
diff --git a/lib/netdev.c b/lib/netdev.c
index 24b616a..f06742a 100644
--- a/lib/netdev.c
+++ b/lib/netdev.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2009, 2010 Nicira Networks.
+ * Copyright (c) 2008, 2009, 2010, 2011 Nicira Networks.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -521,8 +521,9 @@ netdev_get_name(const struct netdev *netdev)
* (and received) packets, in bytes, not including the hardware header; thus,
* this is typically 1500 bytes for Ethernet devices.
*
- * If successful, returns 0 and stores the MTU size in '*mtup'. On failure,
- * returns a positive errno value and stores ETH_PAYLOAD_MAX (1500) in
+ * If successful, returns 0 and stores the MTU size in '*mtup'. Stores INT_MAX
+ * in '*mtup' if 'netdev' does not have an MTU (as e.g. some tunnels do not).On
+ * failure, returns a positive errno value and stores ETH_PAYLOAD_MAX (1500) in
* '*mtup'. */
int
netdev_get_mtu(const struct netdev *netdev, int *mtup)
diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c
index fab6194..e6cc519 100644
--- a/vswitchd/bridge.c
+++ b/vswitchd/bridge.c
@@ -1165,7 +1165,7 @@ iface_refresh_status(struct iface *iface)
? "up" : "down");
error = netdev_get_mtu(iface->netdev, &mtu);
- if (!error) {
+ if (!error && mtu != INT_MAX) {
mtu_64 = mtu;
ovsrec_interface_set_mtu(iface->cfg, &mtu_64, 1);
}
diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml
index 6565b95..96fc664 100644
--- a/vswitchd/vswitch.xml
+++ b/vswitchd/vswitch.xml
@@ -1025,6 +1025,10 @@
and many kinds of virtual interfaces can be configured with
higher MTUs.
</p>
+ <p>
+ This column will be empty for an interface that does not
+ have an MTU as, for example, some kinds of tunnels do not.
+ </p>
</column>
<column name="status">
--
1.7.1
More information about the dev
mailing list