From 90a6637d5e7f5f83e3370e05b3716a24fc093fc7 Mon Sep 17 00:00:00 2001 From: Pravin B Shelar Date: Fri, 9 Mar 2012 12:57:48 -0800 Subject: [PATCH] netdev-linux: Cache error code from mtu ioctl. 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 --- 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 87c8832d..7c510acf 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 185d3dfc..37a7d1c2 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 60b71be8..d14f0e3c 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 b6ddb214..cfdb24ba 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. */ }; -- 2.30.2