[ovs-dev] [PATCH] dpif-linux: Choose port numbers more prudently.

Ben Pfaff blp at nicira.com
Wed Apr 6 03:29:21 UTC 2011


On Tue, Apr 05, 2011 at 06:09:04PM -0700, Ethan Jackson wrote:
> Before this patch the kernel chose the lowest available number for
> newly created datapath ports.  This patch moves the port number
> choosing responsibility to user space, and implements a least
> recently used port number queue in an attempt to avoid reuse.
> 
> Bug #2140.

I think you should add a check for port > ODPP_LOCAL && port <
LRU_MAX_PORTS in dpif_linux_push_port().

Alternatively, here's an incremental that adds a bitmap:

diff --git a/lib/dpif-linux.c b/lib/dpif-linux.c
index 464ac88..10ddd51 100644
--- a/lib/dpif-linux.c
+++ b/lib/dpif-linux.c
@@ -32,6 +32,7 @@
 #include <sys/stat.h>
 #include <unistd.h>
 
+#include "bitmap.h"
 #include "dpif-provider.h"
 #include "netdev.h"
 #include "netdev-vport.h"
@@ -134,6 +135,7 @@ struct dpif_linux {
     bool change_error;
 
     /* Queue of unused ports. */
+    unsigned long *lru_bitmap;
     uint16_t lru_ports[LRU_MAX_PORTS];
     size_t lru_head;
     size_t lru_tail;
@@ -170,31 +172,24 @@ dpif_linux_cast(const struct dpif *dpif)
 static void
 dpif_linux_push_port(struct dpif_linux *dp, uint16_t port)
 {
-    size_t i;
-
-    if (dp->lru_head - dp->lru_tail >= LRU_MAX_PORTS) {
-        return;
-    }
-
-    /* XXX: Replace this loop with a bitmap indicating which ports are in the
-     * queue. */
-    for (i = dp->lru_tail; i != dp->lru_head; i++) {
-        if (dp->lru_ports[i & LRU_MASK] == port) {
-            return;
-        }
+    if (port < LRU_MAX_PORTS && !bitmap_is_set(dp->lru_bitmap, port)) {
+        bitmap_set1(dp->lru_bitmap, port);
+        dp->lru_ports[dp->lru_head++ & LRU_MASK] = port;
     }
-
-    dp->lru_ports[dp->lru_head++ & LRU_MASK] = port;
 }
 
 static uint32_t
 dpif_linux_pop_port(struct dpif_linux *dp)
 {
+    uint16_t port;
+
     if (dp->lru_head == dp->lru_tail) {
         return UINT32_MAX;
     }
 
-    return dp->lru_ports[dp->lru_tail++ & LRU_MASK];
+    port = dp->lru_ports[dp->lru_tail++ & LRU_MASK];
+    bitmap_set0(dp->lru_bitmap, port);
+    return port;
 }
 
 static int
@@ -275,6 +270,8 @@ open_dpif(const struct dpif_linux_dp *dp, struct dpif **dpifp)
     *dpifp = &dpif->dpif;
 
     dpif->lru_head = dpif->lru_tail = 0;
+    dpif->lru_bitmap = bitmap_allocate(LRU_MAX_PORTS);
+    bitmap_set1(dpif->lru_bitmap, ODPP_LOCAL);
     for (i = 1; i < LRU_MAX_PORTS; i++) {
         dpif_linux_push_port(dpif, i);
     }
@@ -291,6 +288,7 @@ dpif_linux_close(struct dpif *dpif_)
     struct dpif_linux *dpif = dpif_linux_cast(dpif_);
     rtnetlink_link_notifier_unregister(&dpif->port_notifier);
     sset_destroy(&dpif->changed_ports);
+    free(dpif->lru_bitmap);
     free(dpif);
 }
 



More information about the dev mailing list