We are relying on netlink notifications for netdev status changes.

However, given we periodically have to send RTM_GETLINK anyways to get
the stats, it seems a good opportunity to double-check the status and
update netdevs if something changed.

Signed-off-by: Adrian Moreno <[email protected]>
---
 lib/netdev-afxdp.c         |  2 +-
 lib/netdev-linux-private.h |  5 ++--
 lib/netdev-linux.c         | 48 ++++++++++++++++++++++++++++++++++----
 3 files changed, 48 insertions(+), 7 deletions(-)

diff --git a/lib/netdev-afxdp.c b/lib/netdev-afxdp.c
index 09f4c5107..9637a62bd 100644
--- a/lib/netdev-afxdp.c
+++ b/lib/netdev-afxdp.c
@@ -1254,7 +1254,7 @@ netdev_afxdp_get_stats(const struct netdev *netdev,
 
     ovs_mutex_lock(&dev->mutex);
 
-    error = get_stats_via_netlink(netdev, &dev_stats);
+    error = get_stats_via_netlink(dev, &dev_stats);
     if (error) {
         VLOG_WARN_RL(&rl, "%s: Error getting AF_XDP statistics.",
                      netdev_get_name(netdev));
diff --git a/lib/netdev-linux-private.h b/lib/netdev-linux-private.h
index cf4a021d3..d7a2620c2 100644
--- a/lib/netdev-linux-private.h
+++ b/lib/netdev-linux-private.h
@@ -36,6 +36,7 @@
 #include "ovs-atomic.h"
 #include "timer.h"
 
+struct netdev_linux;
 struct netdev;
 
 /* The maximum packet length is 16 bits */
@@ -52,10 +53,10 @@ struct netdev_rxq_linux {
 int netdev_linux_construct(struct netdev *);
 int netdev_linux_get_status(const struct netdev *, struct smap *);
 void netdev_linux_run(const struct netdev_class *);
-
-int get_stats_via_netlink(const struct netdev *netdev_,
+int get_stats_via_netlink(struct netdev_linux *netdev,
                           struct netdev_stats *stats);
 
+
 struct netdev_linux {
     struct netdev up;
 
diff --git a/lib/netdev-linux.c b/lib/netdev-linux.c
index c1e1d0f4c..0d3e0354d 100644
--- a/lib/netdev-linux.c
+++ b/lib/netdev-linux.c
@@ -816,6 +816,37 @@ netdev_linux_wait(const struct netdev_class *netdev_class 
OVS_UNUSED)
     }
 }
 
+
+/* Check whether the current state of the netdev is the same as the one
+ * reported by netlink. */
+static bool
+netdev_linux_check(struct netdev_linux *dev,
+                   const struct rtnetlink_change *change)
+    OVS_REQUIRES(dev->mutex)
+{
+    bool result = true;
+
+    if (dev->ifi_flags != change->ifi_flags) {
+        result = false;
+    }
+    if (dev->mtu != change->mtu) {
+        result = false;
+    }
+    if (!eth_addr_is_zero(change->mac) &&
+        !eth_addr_equals(dev->etheraddr, change->mac)) {
+        result = false;
+    }
+    if (dev->ifindex != change->if_index) {
+        result = false;
+    }
+    if (dev->is_lag_primary != (change->primary &&
+        netdev_linux_kind_is_lag(change->primary))) {
+        result = false;
+    }
+
+    return result;
+}
+
 static void
 netdev_linux_changed(struct netdev_linux *dev,
                      unsigned int ifi_flags, unsigned int mask)
@@ -2276,7 +2307,7 @@ netdev_linux_get_stats(const struct netdev *netdev_,
 
     ovs_mutex_lock(&netdev->mutex);
     get_stats_via_vport(netdev_, stats);
-    error = get_stats_via_netlink(netdev_, &dev_stats);
+    error = get_stats_via_netlink(netdev, &dev_stats);
     if (error) {
         if (!netdev->vport_stats_error) {
             error = 0;
@@ -2315,7 +2346,7 @@ netdev_tap_get_stats(const struct netdev *netdev_, struct 
netdev_stats *stats)
 
     ovs_mutex_lock(&netdev->mutex);
     get_stats_via_vport(netdev_, stats);
-    error = get_stats_via_netlink(netdev_, &dev_stats);
+    error = get_stats_via_netlink(netdev, &dev_stats);
     if (error) {
         if (!netdev->vport_stats_error) {
             error = 0;
@@ -6737,7 +6768,9 @@ netdev_stats_from_rtnl_link_stats64(struct netdev_stats 
*dst,
 }
 
 int
-get_stats_via_netlink(const struct netdev *netdev_, struct netdev_stats *stats)
+get_stats_via_netlink(struct netdev_linux *netdev,
+                      struct netdev_stats *stats)
+    OVS_REQUIRES(netdev->mutex)
 {
     struct rtnetlink_change change = {0};
     struct rtnl_link_stats64 _stats64;
@@ -6754,7 +6787,7 @@ get_stats_via_netlink(const struct netdev *netdev_, 
struct netdev_stats *stats)
                         sizeof(struct ifinfomsg) + NL_ATTR_SIZE(IFNAMSIZ),
                         RTM_GETLINK, NLM_F_REQUEST);
     ofpbuf_put_zeros(&request, sizeof(struct ifinfomsg));
-    nl_msg_put_string(&request, IFLA_IFNAME, netdev_get_name(netdev_));
+    nl_msg_put_string(&request, IFLA_IFNAME, netdev_get_name(&netdev->up));
     error = nl_transact(NETLINK_ROUTE, &request, &reply);
     ofpbuf_uninit(&request);
     if (error) {
@@ -6774,6 +6807,13 @@ get_stats_via_netlink(const struct netdev *netdev_, 
struct netdev_stats *stats)
             VLOG_WARN_RL(&rl, "RTM_GETLINK reply lacks stats");
             error = EPROTO;
         }
+
+        /* Verify the internal state of netdevs matches the one given by
+         * netlink. */
+        if (!netdev_linux_check(netdev, &change)) {
+            netdev_linux_update__(netdev, &change);
+        }
+
     } else {
         VLOG_WARN_RL(&rl, "invalid RTM_GETLINK reply");
         error = EPROTO;
-- 
2.52.0

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

Reply via email to