[ovs-dev] [fd leak 4/4] dpif-linux: Fix fd leak for vports that disappear from the datapath.

Ben Pfaff blp at nicira.com
Thu May 2 00:15:58 UTC 2013


When ovs-vswitchd deletes a port with dpif_linux_port_del(), that function
uses del_channel() to delete the corresponding channel, including closing
its Netlink socket fd.  However, if the vport gets removed by some other
process (e.g. "ip link delete" for veths) then this function never gets
called and thus the channel never gets deleted.

This commit fixes the problem by resynchronizing channels with the
datapath whenever a vport gets deleted.

Bug #16784.
Reported-by: Paul Ingram <paul at nicira.com>
Signed-off-by: Ben Pfaff <blp at nicira.com>
---
 lib/dpif-linux.c |   11 +++++++++++
 1 files changed, 11 insertions(+), 0 deletions(-)

diff --git a/lib/dpif-linux.c b/lib/dpif-linux.c
index 69383f0..8470ca3 100644
--- a/lib/dpif-linux.c
+++ b/lib/dpif-linux.c
@@ -149,6 +149,7 @@ struct dpif_linux {
     struct sset changed_ports;  /* Ports that have changed. */
     struct nln_notifier *port_notifier;
     bool change_error;
+    bool refresh_channels;
 };
 
 static struct vlog_rate_limit error_rl = VLOG_RATE_LIMIT_INIT(9999, 5);
@@ -165,6 +166,7 @@ static struct nln *nln = NULL;
 
 static int dpif_linux_init(void);
 static void open_dpif(const struct dpif_linux_dp *, struct dpif **);
+static int dpif_linux_refresh_channels(struct dpif *);
 static bool dpif_linux_nln_parse(struct ofpbuf *, void *);
 static void dpif_linux_port_changed(const void *vport, void *dpif);
 static uint32_t dpif_linux_port_get_pid(const struct dpif *, uint32_t port_no);
@@ -391,9 +393,14 @@ dpif_linux_destroy(struct dpif *dpif_)
 static void
 dpif_linux_run(struct dpif *dpif_ OVS_UNUSED)
 {
+    struct dpif_linux *dpif = dpif_linux_cast(dpif_);
     if (nln) {
         nln_run(nln);
     }
+    if (dpif->refresh_channels) {
+        dpif->refresh_channels = false;
+        dpif_linux_refresh_channels(dpif_);
+    }
 }
 
 static void
@@ -1573,6 +1580,10 @@ dpif_linux_port_changed(const void *vport_, void *dpif_)
             VLOG_DBG("port_changed: dpif:%s vport:%s cmd:%"PRIu8,
                      dpif->dpif.full_name, vport->name, vport->cmd);
             sset_add(&dpif->changed_ports, vport->name);
+
+            if (vport->cmd == OVS_VPORT_CMD_DEL) {
+                dpif->refresh_channels = true;
+            }
         }
     } else {
         dpif->change_error = true;
-- 
1.7.2.5




More information about the dev mailing list