[ovs-dev] [PATCH v3 2/6] netdev-linux: Cache error code from mtu ioctl.
Pravin B Shelar
pshelar at nicira.com
Fri Mar 9 20:02:23 UTC 2012
Fixed according to comments from Ben.
v2-v3:
- Only cache ENODEV from set-mtu ioctl.
v1-v2:
- Fixed check for MTU in notifier so that mtu is not set to zero.
- Changed check for VALID_MTU.
--8<--------------------------cut here-------------------------->8--
netdev linux devices uses mtu ioctl to get and set MTU for a device.
By caching error code from ioctl we can reduce number of ioctl calls
for device which is unregistered from system.
netdev notification is used to update mtu which saves get-mtu-ioctl.
Signed-off-by: Pravin B Shelar <pshelar at nicira.com>
---
lib/netdev-linux.c | 43 +++++++++++++++++++++++++++++--------------
lib/netdev.c | 4 ++--
lib/rtnetlink-link.c | 5 +++++
lib/rtnetlink-link.h | 1 +
4 files changed, 37 insertions(+), 16 deletions(-)
diff --git a/lib/netdev-linux.c b/lib/netdev-linux.c
index 4122324..2d5a976 100644
--- a/lib/netdev-linux.c
+++ b/lib/netdev-linux.c
@@ -376,6 +376,8 @@ struct netdev_dev_linux {
uint32_t kbits_burst;
int vport_stats_error; /* Cached error code from vport_get_stats().
0 or an errno value. */
+ int netdev_mtu_error; /* Cached error code from SIOCGIFMTU or SIOCSIFMTU. */
+
struct ethtool_drvinfo drvinfo; /* Cached from ETHTOOL_GDRVINFO. */
struct tc *tc;
@@ -532,6 +534,13 @@ netdev_dev_linux_update(struct netdev_dev_linux *dev,
if (change->nlmsg_type == RTM_NEWLINK) {
/* Keep drv-info */
netdev_dev_linux_changed(dev, change->ifi_flags, VALID_DRVINFO);
+
+ if (change->mtu) {
+ dev->mtu = change->mtu;
+ dev->cache_valid |= VALID_MTU;
+ dev->netdev_mtu_error = 0;
+ }
+
} else {
netdev_dev_linux_changed(dev, change->ifi_flags, 0);
}
@@ -1046,14 +1055,16 @@ netdev_linux_get_mtu(const struct netdev *netdev_, int *mtup)
error = netdev_linux_do_ioctl(netdev_get_name(netdev_), &ifr,
SIOCGIFMTU, "SIOCGIFMTU");
- if (error) {
- return error;
- }
+
+ netdev_dev->netdev_mtu_error = error;
netdev_dev->mtu = ifr.ifr_mtu;
netdev_dev->cache_valid |= VALID_MTU;
}
- *mtup = netdev_dev->mtu;
- return 0;
+
+ if (!netdev_dev->netdev_mtu_error) {
+ *mtup = netdev_dev->mtu;
+ }
+ return netdev_dev->netdev_mtu_error;
}
/* Sets the maximum size of transmitted (MTU) for given device using linux
@@ -1067,20 +1078,24 @@ netdev_linux_set_mtu(const struct netdev *netdev_, int mtu)
struct ifreq ifr;
int error;
- if (netdev_dev->cache_valid & VALID_MTU &&
- netdev_dev->mtu == mtu) {
- return 0;
+ if (netdev_dev->cache_valid & VALID_MTU) {
+ if (netdev_dev->netdev_mtu_error) {
+ return netdev_dev->netdev_mtu_error;
+ }
+ if (netdev_dev->mtu == mtu) {
+ return 0;
+ }
+ netdev_dev->cache_valid &= ~VALID_MTU;
}
ifr.ifr_mtu = mtu;
error = netdev_linux_do_ioctl(netdev_get_name(netdev_), &ifr,
SIOCSIFMTU, "SIOCSIFMTU");
- if (error) {
- return error;
+ if (!error || error == ENODEV) {
+ netdev_dev->netdev_mtu_error = error;
+ netdev_dev->mtu = ifr.ifr_mtu;
+ netdev_dev->cache_valid |= VALID_MTU;
}
-
- netdev_dev->mtu = ifr.ifr_mtu;
- netdev_dev->cache_valid |= VALID_MTU;
- return 0;
+ return error;
}
/* Returns the ifindex of 'netdev', if successful, as a positive number.
diff --git a/lib/netdev.c b/lib/netdev.c
index 185d3df..37a7d1c 100644
--- a/lib/netdev.c
+++ b/lib/netdev.c
@@ -516,7 +516,7 @@ netdev_get_mtu(const struct netdev *netdev, int *mtup)
if (error) {
*mtup = 0;
if (error != EOPNOTSUPP) {
- VLOG_WARN_RL(&rl, "failed to retrieve MTU for network device %s: "
+ VLOG_DBG_RL(&rl, "failed to retrieve MTU for network device %s: "
"%s", netdev_get_name(netdev), strerror(error));
}
}
@@ -537,7 +537,7 @@ netdev_set_mtu(const struct netdev *netdev, int mtu)
error = class->set_mtu ? class->set_mtu(netdev, mtu) : EOPNOTSUPP;
if (error && error != EOPNOTSUPP) {
- VLOG_WARN_RL(&rl, "failed to set MTU for network device %s: %s",
+ VLOG_DBG_RL(&rl, "failed to set MTU for network device %s: %s",
netdev_get_name(netdev), strerror(error));
}
diff --git a/lib/rtnetlink-link.c b/lib/rtnetlink-link.c
index 60b71be..d14f0e3 100644
--- a/lib/rtnetlink-link.c
+++ b/lib/rtnetlink-link.c
@@ -45,6 +45,7 @@ rtnetlink_link_parse(struct ofpbuf *buf,
static const struct nl_policy policy[] = {
[IFLA_IFNAME] = { .type = NL_A_STRING, .optional = false },
[IFLA_MASTER] = { .type = NL_A_U32, .optional = true },
+ [IFLA_MTU] = { .type = NL_A_U32, .optional = true },
};
static struct nlattr *attrs[ARRAY_SIZE(policy)];
@@ -67,6 +68,10 @@ rtnetlink_link_parse(struct ofpbuf *buf,
change->master_ifindex = (attrs[IFLA_MASTER]
? nl_attr_get_u32(attrs[IFLA_MASTER])
: 0);
+ change->mtu = (attrs[IFLA_MTU]
+ ? nl_attr_get_u32(attrs[IFLA_MTU])
+ : 0);
+
}
return parsed;
diff --git a/lib/rtnetlink-link.h b/lib/rtnetlink-link.h
index b6ddb21..cfdb24b 100644
--- a/lib/rtnetlink-link.h
+++ b/lib/rtnetlink-link.h
@@ -37,6 +37,7 @@ struct rtnetlink_link_change {
/* Extracted from Netlink attributes. */
const char *ifname; /* Name of network device. */
int master_ifindex; /* Ifindex of datapath master (0 if none). */
+ int mtu; /* Current MTU. */
unsigned int ifi_flags; /* Flags of network device. */
};
--
1.7.1
More information about the dev
mailing list