For ports on non-system (i.e. userspace) datapaths, the dpif_netlink_vport_get()
call in netdev_linux_netnsid_update() is meaningless, these ports are not
kernel vports.

Generalize the tap class check in netdev_linux_netnsid_update() with a
dpif_type check: when dpif_type is set and is not "system", assume the
device is local without attempting the vport lookup.  This change will
cover all device types on userspace datapaths (e.g. veth pairs).

Additionally, bypass the nsid equality check in netdev_linux_update()
for non-system datapaths.  When NETLINK_LISTEN_ALL_NSID is enabled,
local RTM events carry the kernel-assigned namespace ID rather than
NETNSID_LOCAL, causing a mismatch with the locally-assumed nsid.  For
non-system datapaths, process all RTM events unconditionally (the
interface name lookup already ensures only OVS-managed devices are
affected).

Together, these changes ensure RTM events (including RTM_DELLINK on
device removal) are properly processed for system devices on userspace
datapaths, enabling cache invalidation and stale value detection.

Signed-off-by: Matteo Perin <[email protected]>
---
 lib/netdev-linux.c | 17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/lib/netdev-linux.c b/lib/netdev-linux.c
index 47faea8c6..c6ea21d35 100644
--- a/lib/netdev-linux.c
+++ b/lib/netdev-linux.c
@@ -614,7 +614,12 @@ static int
 netdev_linux_netnsid_update(struct netdev_linux *netdev)
 {
     if (netnsid_is_unset(netdev->netnsid)) {
-        if (netdev_get_class(&netdev->up) == &netdev_tap_class) {
+        const char *dpif_type = netdev_get_dpif_type(&netdev->up);
+
+        if (netdev_get_class(&netdev->up) == &netdev_tap_class
+            || (dpif_type && strcmp(dpif_type, "system"))) {
+            /* vport netlink lookup makes no sense for
+             * non-system dpif types, set nsid to local. */
             netnsid_set_local(&netdev->netnsid);
         } else {
             return netdev_linux_netnsid_update__(netdev);
@@ -931,7 +936,15 @@ netdev_linux_update(struct netdev_linux *dev, int nsid,
                     const struct rtnetlink_change *change)
     OVS_REQUIRES(dev->mutex)
 {
-    if (netdev_linux_netnsid_is_eq(dev, nsid)) {
+    const char *dpif_type = netdev_get_dpif_type(&dev->up);
+
+    /* With NETLINK_LISTEN_ALL_NSID, local RTM events carry the kernel-assigned
+     * nsid, not NETNSID_LOCAL.  In netdev_linux_netnsid_update() non-system
+     * devices have their nsid forced to NETNSID_LOCAL (no vport lookup),
+     * so the equality check would always fail and events would be dropped.
+     * The nsid equality check for these devices is, therefore, skipped. */
+    if ((dpif_type && strcmp(dpif_type, "system"))
+        || netdev_linux_netnsid_is_eq(dev, nsid)) {
         netdev_linux_update__(dev, change);
     }
 }
-- 
2.43.0

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

Reply via email to