This patch created on earlier patch "v2 netdev-linux: Use get-stats
to check status on linux devices."

--8<--------------------------cut here-------------------------->8-

netdev linux devices uses SIOCGIFMTU ioctl to read MTU for a device.
By caching error code from ioctl we can reduce number of ioctl calls
for device which is unregistered from system.

Signed-off-by: Pravin B Shelar <[email protected]>
---
 lib/netdev-linux.c   |   42 ++++++++++++++++++++++++++++++------------
 lib/netdev.c         |    4 ++--
 lib/rtnetlink-link.c |    5 +++++
 lib/rtnetlink-link.h |    1 +
 4 files changed, 38 insertions(+), 14 deletions(-)

diff --git a/lib/netdev-linux.c b/lib/netdev-linux.c
index 8de037a..501d1de 100644
--- a/lib/netdev-linux.c
+++ b/lib/netdev-linux.c
@@ -368,7 +368,8 @@ struct netdev_dev_linux {
     uint8_t etheraddr[ETH_ADDR_LEN];
     struct in_addr address, netmask;
     struct in6_addr in6;
-    int mtu;
+    int mtu;                    /* Cashed MTU value or error code from
+                                   SIOCGIFMTU. */
     unsigned int ifi_flags;
     long long int carrier_resets;
     uint32_t kbits_rate;        /* Policing data. */
@@ -508,27 +509,30 @@ netdev_linux_get_drvinfo(struct netdev_dev_linux 
*netdev_dev)
 
 static void
 netdev_dev_linux_changed(struct netdev_dev_linux *dev,
-                         unsigned int ifi_flags,
-                         uint16_t change)
+                         const struct rtnetlink_link_change *change)
 {
     dev->change_seq++;
     if (!dev->change_seq) {
         dev->change_seq++;
     }
 
-    if ((dev->ifi_flags ^ ifi_flags) & IFF_RUNNING) {
+    if ((dev->ifi_flags ^ change->ifi_flags) & IFF_RUNNING) {
         dev->carrier_resets++;
     }
-    dev->ifi_flags = ifi_flags;
+    dev->ifi_flags = change->ifi_flags;
 
     /* Always cache driver-info. */
     dev->cache_valid &= VALID_DRVINFO;
 
-    if (change == RTM_NEWLINK) {
+    if (change->nlmsg_type == RTM_NEWLINK) {
         /* Required for internal devices. */
         netdev_linux_get_drvinfo(dev);
     }
 
+    if (change->nlmsg_type != RTM_DELLINK) {
+        dev->mtu = change->mtu;
+        dev->cache_valid |= VALID_MTU;
+    }
 }
 
 static void
@@ -544,12 +548,16 @@ netdev_linux_cache_cb(const struct rtnetlink_link_change 
*change,
 
             if (is_netdev_linux_class(netdev_class)) {
                 dev = netdev_dev_linux_cast(base_dev);
-                netdev_dev_linux_changed(dev, change->ifi_flags, 
change->nlmsg_type);
+                netdev_dev_linux_changed(dev, change);
             }
         }
     } else {
         struct shash device_shash;
         struct shash_node *node;
+        struct rtnetlink_link_change dev_change;
+
+        memset(&dev_change, 0, sizeof(dev_change));
+        dev_change.nlmsg_type = change->nlmsg_type;
 
         shash_init(&device_shash);
         netdev_dev_get_devices(&netdev_linux_class, &device_shash);
@@ -557,9 +565,9 @@ netdev_linux_cache_cb(const struct rtnetlink_link_change 
*change,
             unsigned int flags;
 
             dev = node->data;
-
             get_flags(&dev->netdev_dev, &flags);
-            netdev_dev_linux_changed(dev, flags, change->nlmsg_type);
+            dev_change.ifi_flags = flags;
+            netdev_dev_linux_changed(dev, &dev_change);
         }
         shash_destroy(&device_shash);
     }
@@ -1060,11 +1068,15 @@ 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->mtu = -error;
+        } else {
+            netdev_dev->mtu = ifr.ifr_mtu;
         }
-        netdev_dev->mtu = ifr.ifr_mtu;
         netdev_dev->cache_valid |= VALID_MTU;
     }
+    if (netdev_dev->mtu < 0) {
+        return -netdev_dev->mtu;
+    }
     *mtup = netdev_dev->mtu;
     return 0;
 }
@@ -1221,8 +1233,14 @@ netdev_linux_miimon_run(void)
 
         netdev_linux_get_miimon(dev->netdev_dev.name, &miimon);
         if (miimon != dev->miimon) {
+            struct rtnetlink_link_change dev_change;
+
             dev->miimon = miimon;
-            netdev_dev_linux_changed(dev, dev->ifi_flags, 0);
+
+            memset(&dev_change, 0, sizeof(dev_change));
+            dev_change.ifi_flags = dev->ifi_flags;
+
+            netdev_dev_linux_changed(dev, &dev_change);
         }
 
         timer_set_duration(&dev->miimon_timer, dev->miimon_interval);
diff --git a/lib/netdev.c b/lib/netdev.c
index eff6e4c..407e333 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 retrieve MTU for network device %s: %s",
+        VLOG_DBG_RL(&rl, "failed to retrieve 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

_______________________________________________
dev mailing list
[email protected]
http://openvswitch.org/mailman/listinfo/dev

Reply via email to