Netdev flags are queried multiple times per poll loop. Sending a GETLINK
command for each can be very inefficient if there is RTNL lock
contention.

Cache the result of the query as we do with other netdev attributes.

Signed-off-by: Adrian Moreno <[email protected]>
---
 lib/netdev-linux.c | 15 ++++++++++++---
 lib/tnl-ports.c    |  2 +-
 2 files changed, 13 insertions(+), 4 deletions(-)

diff --git a/lib/netdev-linux.c b/lib/netdev-linux.c
index c464b24d4..f1a9e5fcd 100644
--- a/lib/netdev-linux.c
+++ b/lib/netdev-linux.c
@@ -264,6 +264,7 @@ enum {
     VALID_DRVINFO           = 1 << 6,
     VALID_FEATURES          = 1 << 7,
     VALID_NUMA_ID           = 1 << 8,
+    VALID_FLAGS             = 1 << 9,
 };
 
 /* Linux 4.4 introduced the ability to skip the internal stats gathering
@@ -829,7 +830,7 @@ netdev_linux_run(const struct netdev_class *netdev_class 
OVS_UNUSED)
 
                 ovs_mutex_lock(&netdev->mutex);
                 update_flags_local(netdev);
-                netdev_linux_changed(netdev, netdev->ifi_flags, 0);
+                netdev_linux_changed(netdev, netdev->ifi_flags, VALID_FLAGS);
                 ovs_mutex_unlock(&netdev->mutex);
 
                 netdev_close(netdev_);
@@ -909,6 +910,7 @@ netdev_linux_update__(struct netdev_linux *dev,
 
             dev->ifindex = change->if_index;
             dev->cache_valid |= VALID_IFINDEX;
+            dev->cache_valid |= VALID_FLAGS;
             dev->get_ifindex_error = 0;
             dev->present = true;
         } else {
@@ -3845,7 +3847,11 @@ static int
 update_flags_local(struct netdev_linux *netdev)
     OVS_REQUIRES(netdev->mutex)
 {
-    return get_flags(&netdev->up, &netdev->ifi_flags);
+    int error = get_flags(&netdev->up, &netdev->ifi_flags);
+    if (!error) {
+        netdev->cache_valid |= VALID_FLAGS;
+    }
+    return error;
 }
 
 static int
@@ -3884,7 +3890,8 @@ netdev_linux_update_flags(struct netdev *netdev_, enum 
netdev_flags off,
         error = modify_flags(netdev, off, on, old_flagsp);
     } else {
         /* Try reading flags over netlink, or fall back to ioctl. */
-        if (netdev_linux_update_via_netlink(netdev)) {
+        if (!(netdev->cache_valid & VALID_FLAGS) &&
+            netdev_linux_update_via_netlink(netdev)) {
             error = update_flags_local(netdev);
         }
         *old_flagsp = iff_to_nd_flags(netdev->ifi_flags);
@@ -6951,6 +6958,8 @@ netdev_linux_update_via_netlink(struct netdev_linux 
*netdev)
             netdev->ifi_flags = change->ifi_flags;
             changed = true;
         }
+        netdev->cache_valid |= VALID_FLAGS;
+
         if (change->mtu && change->mtu != netdev->mtu) {
             netdev->mtu = change->mtu;
             netdev->cache_valid |= VALID_MTU;
diff --git a/lib/tnl-ports.c b/lib/tnl-ports.c
index 56119b300..67b6ebcf7 100644
--- a/lib/tnl-ports.c
+++ b/lib/tnl-ports.c
@@ -402,13 +402,13 @@ insert_ipdev__(struct netdev *dev,
 
     ip_dev = xzalloc(sizeof *ip_dev);
     ip_dev->dev = netdev_ref(dev);
-    ip_dev->change_seq = netdev_get_change_seq(dev);
     error = netdev_get_etheraddr(ip_dev->dev, &ip_dev->mac);
     if (error) {
         goto err_free_ipdev;
     }
     ip_dev->addr = addr;
     ip_dev->n_addr = n_addr;
+    ip_dev->change_seq = netdev_get_change_seq(dev);
     ovs_strlcpy(ip_dev->dev_name, netdev_get_name(dev), sizeof 
ip_dev->dev_name);
     ovs_list_insert(&addr_list, &ip_dev->node);
     map_insert_ipdev(ip_dev);
-- 
2.52.0

_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to