Move port manager instances from provider-specific data structures
into the common struct dpif_offload. This removes duplication across
providers and clarifies ownership of port-related state.

With the port manager owned by dpif_offload, offload providers are
required to use the common port management APIs. This simplifies
external port management and eliminates the need for provider-specific
port enumeration logic.

The port dump functions were also simplified using the
CMAP_CURSOR_FOR_EACH_CONTINUE() API.

Signed-off-by: Eelco Chaudron <[email protected]>
---
 lib/dpif-offload-dpdk-netdev.c |   5 +-
 lib/dpif-offload-dpdk.c        | 107 ++++++-----------
 lib/dpif-offload-dummy.c       |  94 +++++----------
 lib/dpif-offload-provider.h    |  73 ++++--------
 lib/dpif-offload-tc-netdev.c   |   5 +-
 lib/dpif-offload-tc.c          | 114 ++++++------------
 lib/dpif-offload.c             | 208 ++++++++++++++++-----------------
 lib/dpif-offload.h             |   5 +-
 8 files changed, 234 insertions(+), 377 deletions(-)

diff --git a/lib/dpif-offload-dpdk-netdev.c b/lib/dpif-offload-dpdk-netdev.c
index d61365ed76..efe99065e4 100644
--- a/lib/dpif-offload-dpdk-netdev.c
+++ b/lib/dpif-offload-dpdk-netdev.c
@@ -2788,8 +2788,9 @@ dpdk_netdev_flow_del(struct dpdk_offload *offload, struct 
netdev *netdev,
     return dpdk_flow_destroy(offload, rte_flow_data, false, false);
 }
 
-int dpdk_netdev_offload_init(struct netdev *netdev,
-                             unsigned int offload_thread_count)
+int
+dpdk_netdev_offload_init(struct netdev *netdev,
+                         unsigned int offload_thread_count)
 {
     int ret = EOPNOTSUPP;
 
diff --git a/lib/dpif-offload-dpdk.c b/lib/dpif-offload-dpdk.c
index 5b58f3be00..8b09244d05 100644
--- a/lib/dpif-offload-dpdk.c
+++ b/lib/dpif-offload-dpdk.c
@@ -93,7 +93,6 @@ struct dpdk_offload_thread_item {
 /* dpif offload interface for the dpdk rte_flow implementation. */
 struct dpdk_offload {
     struct dpif_offload offload;
-    struct dpif_offload_port_mgr *port_mgr;
 
     atomic_count next_offload_thread_id;
     atomic_bool offload_thread_shutdown;
@@ -565,9 +564,9 @@ dpdk_offload_traverse_ports(const struct dpdk_offload 
*offload,
                             bool (*cb)(struct netdev *, odp_port_t, void *),
                             void *aux)
 {
-    struct dpif_offload_port_mgr_port *port;
+    struct dpif_offload_port *port;
 
-    DPIF_OFFLOAD_PORT_MGR_PORT_FOR_EACH (port, offload->port_mgr) {
+    DPIF_OFFLOAD_PORT_MGR_PORT_FOR_EACH (port, &offload->offload) {
         if (cb(port->netdev, port->port_no, aux)) {
             break;
         }
@@ -576,7 +575,7 @@ dpdk_offload_traverse_ports(const struct dpdk_offload 
*offload,
 
 static int
 dpdk_offload_enable(struct dpif_offload *offload_,
-                    struct dpif_offload_port_mgr_port *port)
+                    struct dpif_offload_port *port)
 {
     struct dpdk_offload *offload = dpdk_offload_cast(offload_);
     struct netdev *netdev = port->netdev;
@@ -588,7 +587,7 @@ dpdk_offload_enable(struct dpif_offload *offload_,
 
 static int
 dpdk_offload_cleanup(struct dpif_offload *offload_ OVS_UNUSED,
-                     struct dpif_offload_port_mgr_port *port)
+                     struct dpif_offload_port *port)
 {
     struct netdev *netdev = port->netdev;
 
@@ -598,16 +597,14 @@ dpdk_offload_cleanup(struct dpif_offload *offload_ 
OVS_UNUSED,
 }
 
 static int
-dpdk_offload_port_add(struct dpif_offload *offload_, struct netdev *netdev,
+dpdk_offload_port_add(struct dpif_offload *offload, struct netdev *netdev,
                       odp_port_t port_no)
 {
-    struct dpif_offload_port_mgr_port *port = xmalloc(sizeof *port);
-    struct dpdk_offload *offload = dpdk_offload_cast(offload_);
+    struct dpif_offload_port *port = xmalloc(sizeof *port);
 
-    if (dpif_offload_port_mgr_add(offload->port_mgr, port, netdev,
-                                  port_no, false)) {
+    if (dpif_offload_port_mgr_add(offload, port, netdev, port_no, false)) {
         if (dpif_offload_enabled()) {
-            return dpdk_offload_enable(offload_, port);
+            return dpdk_offload_enable(offload, port);
         }
         return 0;
     }
@@ -617,7 +614,7 @@ dpdk_offload_port_add(struct dpif_offload *offload_, struct 
netdev *netdev,
 }
 
 static void
-dpdk_offload_free_port(struct dpif_offload_port_mgr_port *port)
+dpdk_offload_free_port(struct dpif_offload_port *port)
 {
     netdev_close(port->netdev);
     free(port);
@@ -627,10 +624,10 @@ static int
 dpdk_offload_port_del(struct dpif_offload *offload_, odp_port_t port_no)
 {
     struct dpdk_offload *offload = dpdk_offload_cast(offload_);
-    struct dpif_offload_port_mgr_port *port;
+    struct dpif_offload_port *port;
     int ret = 0;
 
-    port = dpif_offload_port_mgr_find_by_odp_port(offload->port_mgr, port_no);
+    port = dpif_offload_port_mgr_find_by_odp_port(offload_, port_no);
 
     if (dpif_offload_enabled() && port) {
         /* If hardware offload is enabled, we first need to flush (complete)
@@ -640,7 +637,7 @@ dpdk_offload_port_del(struct dpif_offload *offload_, 
odp_port_t port_no)
         dpdk_offload_flush(offload, port->netdev);
     }
 
-    port = dpif_offload_port_mgr_remove(offload->port_mgr, port_no);
+    port = dpif_offload_port_mgr_remove(offload_, port_no);
     if (port) {
         if (dpif_offload_enabled()) {
             ret = dpdk_offload_cleanup(offload_, port);
@@ -650,40 +647,13 @@ dpdk_offload_port_del(struct dpif_offload *offload_, 
odp_port_t port_no)
     return ret;
 }
 
-static int
-dpdk_offload_port_dump_start(const struct dpif_offload *offload_,
-                             void **statep)
-{
-    struct dpdk_offload *offload = dpdk_offload_cast(offload_);
-
-    return dpif_offload_port_mgr_port_dump_start(offload->port_mgr, statep);
-}
-
-static int
-dpdk_offload_port_dump_next(const struct dpif_offload *offload_, void *state,
-                            struct dpif_offload_port *port)
-{
-    struct dpdk_offload *offload = dpdk_offload_cast(offload_);
-
-    return dpif_offload_port_mgr_port_dump_next(offload->port_mgr, state,
-                                                port);
-}
-
-static int
-dpdk_offload_port_dump_done(const struct dpif_offload *offload_, void *state)
-{
-    struct dpdk_offload *offload = dpdk_offload_cast(offload_);
-
-    return dpif_offload_port_mgr_port_dump_done(offload->port_mgr, state);
-}
-
-struct netdev *
-dpdk_offload_get_netdev(const struct dpdk_offload *offload, odp_port_t port_no)
+static struct netdev *
+dpdk_offload_get_netdev__(const struct dpif_offload *offload,
+                          odp_port_t port_no)
 {
-    struct dpif_offload_port_mgr_port *port;
+    struct dpif_offload_port *port;
 
-    port = dpif_offload_port_mgr_find_by_odp_port(offload->port_mgr,
-                                                  port_no);
+    port = dpif_offload_port_mgr_find_by_odp_port(offload, port_no);
     if (!port) {
         return NULL;
     }
@@ -691,12 +661,10 @@ dpdk_offload_get_netdev(const struct dpdk_offload 
*offload, odp_port_t port_no)
     return port->netdev;
 }
 
-static struct netdev *
-dpdk_offload_get_netdev__(struct dpif_offload *offload_, odp_port_t port_no)
+struct netdev *
+dpdk_offload_get_netdev(const struct dpdk_offload *offload, odp_port_t port_no)
 {
-    struct dpdk_offload *offload = dpdk_offload_cast(offload_);
-
-    return dpdk_offload_get_netdev(offload, port_no);
+    return dpdk_offload_get_netdev__(&offload->offload, port_no);
 }
 
 static int
@@ -706,7 +674,6 @@ dpdk_offload_open(const struct dpif_offload_class 
*offload_class,
     struct dpdk_offload *offload = xmalloc(sizeof *offload);
 
     dpif_offload_init(&offload->offload, offload_class, dpif);
-    offload->port_mgr = dpif_offload_port_mgr_init();
     offload->once_enable = (struct ovsthread_once) OVSTHREAD_ONCE_INITIALIZER;
     offload->offload_thread_count = DEFAULT_OFFLOAD_THREAD_COUNT;
     offload->offload_threads = NULL;
@@ -723,9 +690,9 @@ static void
 dpdk_offload_close(struct dpif_offload *offload_)
 {
     struct dpdk_offload *offload = dpdk_offload_cast(offload_);
-    struct dpif_offload_port_mgr_port *port;
+    struct dpif_offload_port *port;
 
-    DPIF_OFFLOAD_PORT_MGR_PORT_FOR_EACH (port, offload->port_mgr) {
+    DPIF_OFFLOAD_PORT_MGR_PORT_FOR_EACH (port, offload_) {
         dpdk_offload_port_del(offload_, port->port_no);
     }
 
@@ -738,13 +705,12 @@ dpdk_offload_close(struct dpif_offload *offload_)
         free(offload->offload_threads);
     }
 
-    dpif_offload_port_mgr_uninit(offload->port_mgr);
-
     if (offload->flow_mark_pool) {
         id_fpool_destroy(offload->flow_mark_pool);
     }
 
     ovsthread_once_destroy(&offload->once_enable);
+    dpif_offload_destroy(offload_);
     free(offload);
 }
 
@@ -756,7 +722,7 @@ dpdk_offload_set_config(struct dpif_offload *offload_,
 
     if (smap_get_bool(other_cfg, "hw-offload", false)) {
         if (ovsthread_once_start(&offload->once_enable)) {
-            struct dpif_offload_port_mgr_port *port;
+            struct dpif_offload_port *port;
 
             unsigned int offload_thread_count = smap_get_uint(
                 other_cfg, "n-offload-threads", DEFAULT_OFFLOAD_THREAD_COUNT);
@@ -774,7 +740,7 @@ dpdk_offload_set_config(struct dpif_offload *offload_,
             offload->offload_thread_count = offload_thread_count;
 
             dpdk_offload_threads_init(offload);
-            DPIF_OFFLOAD_PORT_MGR_PORT_FOR_EACH (port, offload->port_mgr) {
+            DPIF_OFFLOAD_PORT_MGR_PORT_FOR_EACH (port, offload_) {
                 dpdk_offload_enable(offload_, port);
             }
 
@@ -784,16 +750,14 @@ dpdk_offload_set_config(struct dpif_offload *offload_,
 }
 
 static void
-dpdk_offload_get_debug(const struct dpif_offload *offload_, struct ds *ds,
+dpdk_offload_get_debug(const struct dpif_offload *offload, struct ds *ds,
                        struct json *json)
 {
-    struct dpdk_offload *offload = dpdk_offload_cast(offload_);
-
     if (json) {
         struct json *json_ports = json_object_create();
-        struct dpif_offload_port_mgr_port *port;
+        struct dpif_offload_port *port;
 
-        DPIF_OFFLOAD_PORT_MGR_PORT_FOR_EACH (port, offload->port_mgr) {
+        DPIF_OFFLOAD_PORT_MGR_PORT_FOR_EACH (port, offload) {
             struct json *json_port = json_object_create();
 
             json_object_put(json_port, "port_no",
@@ -809,9 +773,9 @@ dpdk_offload_get_debug(const struct dpif_offload *offload_, 
struct ds *ds,
             json_destroy(json_ports);
         }
     } else if (ds) {
-        struct dpif_offload_port_mgr_port *port;
+        struct dpif_offload_port *port;
 
-        DPIF_OFFLOAD_PORT_MGR_PORT_FOR_EACH (port, offload->port_mgr) {
+        DPIF_OFFLOAD_PORT_MGR_PORT_FOR_EACH (port, offload) {
             ds_put_format(ds, "  - %s: port_no: %u\n",
                           netdev_get_name(port->netdev), port->port_no);
         }
@@ -836,14 +800,14 @@ static uint64_t
 dpdk_flow_count(const struct dpif_offload *offload_)
 {
     struct dpdk_offload *offload = dpdk_offload_cast(offload_);
-    struct dpif_offload_port_mgr_port *port;
+    struct dpif_offload_port *port;
     uint64_t total = 0;
 
     if (!dpif_offload_enabled()) {
         return 0;
     }
 
-    DPIF_OFFLOAD_PORT_MGR_PORT_FOR_EACH (port, offload->port_mgr) {
+    DPIF_OFFLOAD_PORT_MGR_PORT_FOR_EACH (port, offload_) {
         total += dpdk_netdev_flow_count(port->netdev,
                                         offload->offload_thread_count);
     }
@@ -854,14 +818,14 @@ dpdk_flow_count(const struct dpif_offload *offload_)
 static uint64_t
 dpdk_flow_count_by_thread(struct dpdk_offload *offload, unsigned int tid)
 {
-    struct dpif_offload_port_mgr_port *port;
+    struct dpif_offload_port *port;
     uint64_t total = 0;
 
     if (!dpif_offload_enabled()) {
         return 0;
     }
 
-    DPIF_OFFLOAD_PORT_MGR_PORT_FOR_EACH (port, offload->port_mgr) {
+    DPIF_OFFLOAD_PORT_MGR_PORT_FOR_EACH (port, &offload->offload) {
         total += dpdk_netdev_flow_count_by_thread(port->netdev, tid);
     }
 
@@ -1077,9 +1041,6 @@ struct dpif_offload_class dpif_offload_dpdk_class = {
     .can_offload = dpdk_can_offload,
     .port_add = dpdk_offload_port_add,
     .port_del = dpdk_offload_port_del,
-    .port_dump_start = dpdk_offload_port_dump_start,
-    .port_dump_next = dpdk_offload_port_dump_next,
-    .port_dump_done = dpdk_offload_port_dump_done,
     .flow_count = dpdk_flow_count,
     .get_netdev = dpdk_offload_get_netdev__,
     .netdev_hw_post_process = dpdk_offload_hw_post_process,
diff --git a/lib/dpif-offload-dummy.c b/lib/dpif-offload-dummy.c
index c2d5b9675b..dec5b7b1ae 100644
--- a/lib/dpif-offload-dummy.c
+++ b/lib/dpif-offload-dummy.c
@@ -51,7 +51,6 @@ struct dummy_offloaded_flow {
 
 struct dummy_offload {
     struct dpif_offload offload;
-    struct dpif_offload_port_mgr *port_mgr;
     struct id_fpool *flow_mark_pool;
     dpif_offload_flow_unreference_cb *unreference_cb;
 
@@ -60,7 +59,7 @@ struct dummy_offload {
 };
 
 struct dummy_offload_port {
-    struct dpif_offload_port_mgr_port pm_port;
+    struct dpif_offload_port pm_port;
 
     struct ovs_mutex port_mutex; /* Protect all below members. */
     struct hmap offloaded_flows OVS_GUARDED;
@@ -97,7 +96,7 @@ dummy_free_flow_mark(struct dummy_offload *offload, uint32_t 
flow_mark)
 }
 
 static struct dummy_offload_port *
-dummy_offload_port_cast(struct dpif_offload_port_mgr_port *port)
+dummy_offload_port_cast(struct dpif_offload_port *port)
 {
     return CONTAINER_OF(port, struct dummy_offload_port, pm_port);
 }
@@ -271,7 +270,7 @@ dummy_find_offloaded_flow_and_update(struct 
dummy_offload_port *port,
 
 static void
 dummy_offload_enable(struct dpif_offload *dpif_offload,
-                     struct dpif_offload_port_mgr_port *port)
+                     struct dpif_offload_port *port)
 {
     atomic_store_relaxed(&port->netdev->hw_info.post_process_api_supported,
                          true);
@@ -279,7 +278,7 @@ dummy_offload_enable(struct dpif_offload *dpif_offload,
 }
 
 static void
-dummy_offload_cleanup(struct dpif_offload_port_mgr_port *port)
+dummy_offload_cleanup(struct dpif_offload_port *port)
 {
     dpif_offload_set_netdev_offload(port->netdev, NULL);
 }
@@ -338,8 +337,8 @@ dummy_offload_port_add(struct dpif_offload *dpif_offload,
     hmap_init(&port->offloaded_flows);
     ovs_mutex_unlock(&port->port_mutex);
 
-    if (dpif_offload_port_mgr_add(offload->port_mgr, &port->pm_port,
-                                  netdev, port_no, false)) {
+    if (dpif_offload_port_mgr_add(dpif_offload, &port->pm_port, netdev,
+                                  port_no, false)) {
 
         if (dpif_offload_enabled()) {
             dummy_offload_enable(dpif_offload, &port->pm_port);
@@ -355,9 +354,9 @@ static int
 dummy_offload_port_del(struct dpif_offload *dpif_offload, odp_port_t port_no)
 {
     struct dummy_offload *offload = dummy_offload_cast(dpif_offload);
-    struct dpif_offload_port_mgr_port *port;
+    struct dpif_offload_port *port;
 
-    port = dpif_offload_port_mgr_remove(offload->port_mgr, port_no);
+    port = dpif_offload_port_mgr_remove(dpif_offload, port_no);
     if (port) {
         struct dummy_offload_port *dummy_port;
 
@@ -370,40 +369,13 @@ dummy_offload_port_del(struct dpif_offload *dpif_offload, 
odp_port_t port_no)
     return 0;
 }
 
-static int
-dummy_offload_port_dump_start(const struct dpif_offload *offload_,
-                              void **statep)
-{
-    struct dummy_offload *offload = dummy_offload_cast(offload_);
-
-    return dpif_offload_port_mgr_port_dump_start(offload->port_mgr, statep);
-}
-
-static int
-dummy_offload_port_dump_next(const struct dpif_offload *offload_, void *state,
-                             struct dpif_offload_port *port)
-{
-    struct dummy_offload *offload = dummy_offload_cast(offload_);
-
-    return dpif_offload_port_mgr_port_dump_next(offload->port_mgr, state,
-                                                port);
-}
-
-static int
-dummy_offload_port_dump_done(const struct dpif_offload *offload_, void *state)
-{
-    struct dummy_offload *offload = dummy_offload_cast(offload_);
-
-    return dpif_offload_port_mgr_port_dump_done(offload->port_mgr, state);
-}
-
 static struct netdev *
-dummy_offload_get_netdev(struct dpif_offload *dpif_offload, odp_port_t port_no)
+dummy_offload_get_netdev(const struct dpif_offload *dpif_offload,
+                         odp_port_t port_no)
 {
-    struct dummy_offload *offload = dummy_offload_cast(dpif_offload);
-    struct dpif_offload_port_mgr_port *port;
+    struct dpif_offload_port *port;
 
-    port = dpif_offload_port_mgr_find_by_odp_port(offload->port_mgr, port_no);
+    port = dpif_offload_port_mgr_find_by_odp_port(dpif_offload, port_no);
     if (!port) {
         return NULL;
     }
@@ -420,7 +392,6 @@ dummy_offload_open(const struct dpif_offload_class 
*offload_class,
     offload = xmalloc(sizeof *offload);
 
     dpif_offload_init(&offload->offload, offload_class, dpif);
-    offload->port_mgr = dpif_offload_port_mgr_init();
     offload->once_enable = (struct ovsthread_once) OVSTHREAD_ONCE_INITIALIZER;
     offload->flow_mark_pool = NULL;
     offload->unreference_cb = NULL;
@@ -433,19 +404,19 @@ static void
 dummy_offload_close(struct dpif_offload *dpif_offload)
 {
     struct dummy_offload *offload = dummy_offload_cast(dpif_offload);
-    struct dpif_offload_port_mgr_port *port;
+    struct dpif_offload_port *port;
 
     /* The ofproto layer may not call dpif_port_del() for all ports,
      * especially internal ones, so we need to clean up any remaining ports. */
-    DPIF_OFFLOAD_PORT_MGR_PORT_FOR_EACH (port, offload->port_mgr) {
+    DPIF_OFFLOAD_PORT_MGR_PORT_FOR_EACH (port, dpif_offload) {
         dummy_offload_port_del(dpif_offload, port->port_no);
     }
 
-    dpif_offload_port_mgr_uninit(offload->port_mgr);
     if (offload->flow_mark_pool) {
         id_fpool_destroy(offload->flow_mark_pool);
     }
     ovsthread_once_destroy(&offload->once_enable);
+    dpif_offload_destroy(dpif_offload);
     free(offload);
 }
 
@@ -457,9 +428,9 @@ dummy_offload_set_config(struct dpif_offload *dpif_offload,
 
     if (smap_get_bool(other_cfg, "hw-offload", false)) {
         if (ovsthread_once_start(&offload->once_enable)) {
-            struct dpif_offload_port_mgr_port *port;
+            struct dpif_offload_port *port;
 
-            DPIF_OFFLOAD_PORT_MGR_PORT_FOR_EACH (port, offload->port_mgr) {
+            DPIF_OFFLOAD_PORT_MGR_PORT_FOR_EACH (port, dpif_offload) {
                 dummy_offload_enable(dpif_offload, port);
             }
 
@@ -469,16 +440,14 @@ dummy_offload_set_config(struct dpif_offload 
*dpif_offload,
 }
 
 static void
-dummy_offload_get_debug(const struct dpif_offload *offload_, struct ds *ds,
+dummy_offload_get_debug(const struct dpif_offload *offload, struct ds *ds,
                         struct json *json)
 {
-    struct dummy_offload *offload = dummy_offload_cast(offload_);
-
     if (json) {
         struct json *json_ports = json_object_create();
-        struct dpif_offload_port_mgr_port *port;
+        struct dpif_offload_port *port;
 
-        DPIF_OFFLOAD_PORT_MGR_PORT_FOR_EACH (port, offload->port_mgr) {
+        DPIF_OFFLOAD_PORT_MGR_PORT_FOR_EACH (port, offload) {
             struct json *json_port = json_object_create();
 
             json_object_put(json_port, "port_no",
@@ -494,9 +463,9 @@ dummy_offload_get_debug(const struct dpif_offload 
*offload_, struct ds *ds,
             json_destroy(json_ports);
         }
     } else if (ds) {
-        struct dpif_offload_port_mgr_port *port;
+        struct dpif_offload_port *port;
 
-        DPIF_OFFLOAD_PORT_MGR_PORT_FOR_EACH (port, offload->port_mgr) {
+        DPIF_OFFLOAD_PORT_MGR_PORT_FOR_EACH (port, offload) {
             ds_put_format(ds, "  - %s: port_no: %u\n",
                           netdev_get_name(port->netdev), port->port_no);
         }
@@ -504,17 +473,14 @@ dummy_offload_get_debug(const struct dpif_offload 
*offload_, struct ds *ds,
 }
 
 static int
-dummy_offload_get_global_stats(const struct dpif_offload *offload_,
+dummy_offload_get_global_stats(const struct dpif_offload *offload,
                                struct netdev_custom_stats *stats)
 {
-    struct dummy_offload *offload = dummy_offload_cast(offload_);
-
     /* Add a single counter telling how many ports we are servicing. */
-    stats->label = xstrdup(dpif_offload_name(offload_));
+    stats->label = xstrdup(dpif_offload_name(offload));
     stats->size = 1;
     stats->counters = xmalloc(sizeof(struct netdev_custom_counter) * 1);
-    stats->counters[0].value = dpif_offload_port_mgr_port_count(
-        offload->port_mgr);
+    stats->counters[0].value = dpif_offload_port_mgr_port_count(offload);
     ovs_strzcpy(stats->counters[0].name, "Offloaded port count",
                 sizeof stats->counters[0].name);
 
@@ -537,13 +503,12 @@ dummy_offload_log_operation(const char *op, int error, 
const ovs_u128 *ufid)
 }
 
 static struct dummy_offload_port *
-dummy_offload_get_port_by_netdev(const struct dpif_offload *offload_,
+dummy_offload_get_port_by_netdev(const struct dpif_offload *offload,
                                  struct netdev *netdev)
 {
-    struct dummy_offload *offload = dummy_offload_cast(offload_);
-    struct dpif_offload_port_mgr_port *port;
+    struct dpif_offload_port *port;
 
-    port = dpif_offload_port_mgr_find_by_netdev(offload->port_mgr, netdev);
+    port = dpif_offload_port_mgr_find_by_netdev(offload, netdev);
     if (!port) {
         return NULL;
     }
@@ -832,9 +797,6 @@ dummy_netdev_simulate_offload(struct netdev *netdev, struct 
dp_packet *packet,
         .can_offload = dummy_can_offload,                                   \
         .port_add = dummy_offload_port_add,                                 \
         .port_del = dummy_offload_port_del,                                 \
-        .port_dump_start = dummy_offload_port_dump_start,                   \
-        .port_dump_next = dummy_offload_port_dump_next,                     \
-        .port_dump_done = dummy_offload_port_dump_done,                     \
         .get_netdev = dummy_offload_get_netdev,                             \
         .netdev_hw_post_process = dummy_offload_hw_post_process,            \
         .netdev_flow_put = dummy_flow_put,                                  \
diff --git a/lib/dpif-offload-provider.h b/lib/dpif-offload-provider.h
index 44e55f27c7..57d42b5d4d 100644
--- a/lib/dpif-offload-provider.h
+++ b/lib/dpif-offload-provider.h
@@ -56,6 +56,7 @@ struct dpif_offload_provider_collection {
 struct dpif_offload {
     const struct dpif_offload_class *class;
     struct ovs_list dpif_list_node;
+    struct dpif_offload_port_mgr *ports;
     char *name;
 };
 
@@ -162,30 +163,6 @@ struct dpif_offload_class {
     void (*port_set_config)(struct dpif_offload *, odp_port_t port_no,
                             const struct smap *cfg);
 
-    /* Attempts to begin dumping the ports in a dpif_offload.  On success,
-     * returns 0 and initializes '*statep' with any data needed for iteration.
-     * On failure, returns a positive errno value. */
-    int (*port_dump_start)(const struct dpif_offload *, void **statep);
-
-    /* Attempts to retrieve another port from 'dpif_offload' for 'state', which
-     * was initialized by a successful call to the 'port_dump_start' function
-     * for 'dpif_offload'.  On success, stores a new dpif_offload_port into
-     * 'port' and returns 0.  Returns EOF if the end of the port table has been
-     * reached, or a positive errno value on error.  This function will not be
-     * called again once it returns nonzero once for a given iteration (but
-     * the 'port_dump_done' function will be called afterward).
-     *
-     * The dpif provider retains ownership of the data stored in 'port'.  It
-     * must remain valid until at least the next call to 'port_dump_next' or
-     * 'port_dump_done' for 'state'. */
-    int (*port_dump_next)(const struct dpif_offload *, void *state,
-                          struct dpif_offload_port *);
-
-    /* Releases resources from 'dpif_offload' for 'state', which was
-     * initialized by a successful call to the 'port_dump_start' function for
-     * 'dpif_offload'. */
-    int (*port_dump_done)(const struct dpif_offload *dpif, void *state);
-
     /* Deletes all offloaded flows for this offload_provider.  Return 0 if
      * successful, otherwise returns a positive errno value. */
     int (*flow_flush)(const struct dpif_offload *);
@@ -274,8 +251,8 @@ struct dpif_offload_class {
      * NOT incremented.  Callers needing to hold a reference must call
      * netdev_ref() on the returned netdev.  Returns NULL if port_no is
      * not found. */
-    struct netdev *(*get_netdev)(struct dpif_offload *, odp_port_t port_no);
-
+    struct netdev *(*get_netdev)(const struct dpif_offload *,
+                                 odp_port_t port_no);
 
     /* These APIs operate directly on the provided netdev for performance
      * reasons.  They are intended for use in fast path processing and should
@@ -336,7 +313,7 @@ extern struct dpif_offload_class dpif_offload_dpdk_class;
 extern struct dpif_offload_class dpif_offload_tc_class;
 
 
-/* Structure used by the common dpif port management library functions. */
+/* Structures used by the common dpif port management library functions. */
 struct dpif_offload_port_mgr {
     struct ovs_mutex cmap_mod_lock;
 
@@ -345,7 +322,7 @@ struct dpif_offload_port_mgr {
     struct cmap ifindex_to_port;
 };
 
-struct dpif_offload_port_mgr_port {
+struct dpif_offload_port {
     struct cmap_node odp_port_node;
     struct cmap_node netdev_node;
     struct cmap_node ifindex_node;
@@ -357,30 +334,28 @@ struct dpif_offload_port_mgr_port {
 
 /* Global dpif port management library functions. */
 struct dpif_offload_port_mgr *dpif_offload_port_mgr_init(void);
-bool dpif_offload_port_mgr_add(struct dpif_offload_port_mgr *,
-                               struct dpif_offload_port_mgr_port *,
+void dpif_offload_port_mgr_destroy(struct dpif_offload *);
+bool dpif_offload_port_mgr_add(struct dpif_offload *,
+                               struct dpif_offload_port *,
                                struct netdev *netdev, odp_port_t,
                                bool need_ifindex);
-struct dpif_offload_port_mgr_port *dpif_offload_port_mgr_remove(
-    struct dpif_offload_port_mgr *, odp_port_t);
-void dpif_offload_port_mgr_uninit(struct dpif_offload_port_mgr *);
-size_t dpif_offload_port_mgr_port_count(struct dpif_offload_port_mgr *);
-struct dpif_offload_port_mgr_port *dpif_offload_port_mgr_find_by_ifindex(
-    struct dpif_offload_port_mgr *, int ifindex);
-struct dpif_offload_port_mgr_port *dpif_offload_port_mgr_find_by_netdev(
-    struct dpif_offload_port_mgr *, struct netdev *);
-struct dpif_offload_port_mgr_port *dpif_offload_port_mgr_find_by_odp_port(
-    struct dpif_offload_port_mgr *, odp_port_t);
-int dpif_offload_port_mgr_port_dump_start(struct dpif_offload_port_mgr *,
+struct dpif_offload_port *dpif_offload_port_mgr_remove(struct dpif_offload *,
+                                                       odp_port_t);
+size_t dpif_offload_port_mgr_port_count(const struct dpif_offload *);
+struct dpif_offload_port *dpif_offload_port_mgr_find_by_ifindex(
+    const struct dpif_offload *, int ifindex);
+struct dpif_offload_port *dpif_offload_port_mgr_find_by_netdev(
+    const struct dpif_offload *, struct netdev *);
+struct dpif_offload_port *dpif_offload_port_mgr_find_by_odp_port(
+    const struct dpif_offload *, odp_port_t);
+int dpif_offload_port_mgr_port_dump_start(const struct dpif_offload *,
                                           void **statep);
-int dpif_offload_port_mgr_port_dump_next(struct dpif_offload_port_mgr *,
-                                         void *state,
-                                         struct dpif_offload_port *);
-int dpif_offload_port_mgr_port_dump_done(struct dpif_offload_port_mgr *,
-                                         void *state);
-
-#define DPIF_OFFLOAD_PORT_MGR_PORT_FOR_EACH(PORT, PORT_MGR) \
-    CMAP_FOR_EACH (PORT, odp_port_node, &(PORT_MGR)->odp_port_to_port)
+int dpif_offload_port_mgr_port_dump_next(void *state,
+                                         struct dpif_offload_port_dump_port *);
+int dpif_offload_port_mgr_port_dump_done(void *state);
+
+#define DPIF_OFFLOAD_PORT_MGR_PORT_FOR_EACH(PORT, OFFLOAD) \
+    CMAP_FOR_EACH (PORT, odp_port_node, &(OFFLOAD)->ports->odp_port_to_port)
 
 /* Global functions, called by the dpif layer or offload providers. */
 void dpif_offload_module_init(void);
diff --git a/lib/dpif-offload-tc-netdev.c b/lib/dpif-offload-tc-netdev.c
index 11a72118a3..a2f4ab8b5d 100644
--- a/lib/dpif-offload-tc-netdev.c
+++ b/lib/dpif-offload-tc-netdev.c
@@ -668,8 +668,9 @@ parse_flower_rewrite_to_netlink_action(struct ofpbuf *buf,
     }
 }
 
-static void parse_tc_flower_geneve_opts(struct tc_action *action,
-                                        struct ofpbuf *buf)
+static void
+parse_tc_flower_geneve_opts(struct tc_action *action,
+                            struct ofpbuf *buf)
 {
     int tun_opt_len = action->encap.data.present.len;
     size_t geneve_off;
diff --git a/lib/dpif-offload-tc.c b/lib/dpif-offload-tc.c
index fca106584a..58d7628a3b 100644
--- a/lib/dpif-offload-tc.c
+++ b/lib/dpif-offload-tc.c
@@ -35,7 +35,6 @@ VLOG_DEFINE_THIS_MODULE(dpif_offload_tc);
 /* dpif offload interface for the tc implementation. */
 struct tc_offload {
     struct dpif_offload offload;
-    struct dpif_offload_port_mgr *port_mgr;
 
     /* Configuration specific variables. */
     struct ovsthread_once once_enable; /* Track first-time enablement. */
@@ -75,7 +74,7 @@ tc_offload_cast(const struct dpif_offload *offload)
 
 static int
 tc_offload_enable(struct dpif_offload *dpif_offload,
-                  struct dpif_offload_port_mgr_port *port)
+                  struct dpif_offload_port *port)
 {
     int ret = tc_netdev_init(port->netdev);
 
@@ -91,7 +90,7 @@ tc_offload_enable(struct dpif_offload *dpif_offload,
 
 static int
 tc_offload_cleanup(struct dpif_offload *dpif_offload OVS_UNUSED,
-                   struct dpif_offload_port_mgr_port *port)
+                   struct dpif_offload_port *port)
 {
     dpif_offload_set_netdev_offload(port->netdev, NULL);
     return 0;
@@ -101,11 +100,9 @@ static int
 tc_port_add(struct dpif_offload *dpif_offload, struct netdev *netdev,
             odp_port_t port_no)
 {
-    struct dpif_offload_port_mgr_port *port = xmalloc(sizeof *port);
-    struct tc_offload *offload = tc_offload_cast(dpif_offload);
+    struct dpif_offload_port *port = xmalloc(sizeof *port);
 
-    if (dpif_offload_port_mgr_add(offload->port_mgr, port, netdev, port_no,
-                                  true)) {
+    if (dpif_offload_port_mgr_add(dpif_offload, port, netdev, port_no, true)) {
         if (dpif_offload_enabled()) {
             return tc_offload_enable(dpif_offload, port);
         }
@@ -117,7 +114,7 @@ tc_port_add(struct dpif_offload *dpif_offload, struct 
netdev *netdev,
 }
 
 static void
-tc_free_port(struct dpif_offload_port_mgr_port *port)
+tc_free_port(struct dpif_offload_port *port)
 {
     netdev_close(port->netdev);
     free(port);
@@ -126,11 +123,10 @@ tc_free_port(struct dpif_offload_port_mgr_port *port)
 static int
 tc_port_del(struct dpif_offload *dpif_offload, odp_port_t port_no)
 {
-    struct tc_offload *offload = tc_offload_cast(dpif_offload);
-    struct dpif_offload_port_mgr_port *port;
+    struct dpif_offload_port *port;
     int ret = 0;
 
-    port = dpif_offload_port_mgr_remove(offload->port_mgr, port_no);
+    port = dpif_offload_port_mgr_remove(dpif_offload, port_no);
     if (port) {
         if (dpif_offload_enabled()) {
             ret = tc_offload_cleanup(dpif_offload, port);
@@ -140,39 +136,12 @@ tc_port_del(struct dpif_offload *dpif_offload, odp_port_t 
port_no)
     return ret;
 }
 
-static int
-tc_port_dump_start(const struct dpif_offload *offload_, void **statep)
-{
-    struct tc_offload *offload = tc_offload_cast(offload_);
-
-    return dpif_offload_port_mgr_port_dump_start(offload->port_mgr, statep);
-}
-
-static int
-tc_port_dump_next(const struct dpif_offload *offload_, void *state,
-                  struct dpif_offload_port *port)
-{
-    struct tc_offload *offload = tc_offload_cast(offload_);
-
-    return dpif_offload_port_mgr_port_dump_next(offload->port_mgr, state,
-                                                port);
-}
-
-static int
-tc_port_dump_done(const struct dpif_offload *offload_, void *state)
-{
-    struct tc_offload *offload = tc_offload_cast(offload_);
-
-    return dpif_offload_port_mgr_port_dump_done(offload->port_mgr, state);
-}
-
 static struct netdev *
-tc_get_netdev(struct dpif_offload *dpif_offload, odp_port_t port_no)
+tc_get_netdev(const struct dpif_offload *dpif_offload, odp_port_t port_no)
 {
-    struct tc_offload *offload = tc_offload_cast(dpif_offload);
-    struct dpif_offload_port_mgr_port *port;
+    struct dpif_offload_port *port;
 
-    port = dpif_offload_port_mgr_find_by_odp_port(offload->port_mgr, port_no);
+    port = dpif_offload_port_mgr_find_by_odp_port(dpif_offload, port_no);
     if (!port) {
         return NULL;
     }
@@ -187,7 +156,6 @@ tc_offload_open(const struct dpif_offload_class 
*offload_class,
     struct tc_offload *offload = xmalloc(sizeof *offload);
 
     dpif_offload_init(&offload->offload, offload_class, dpif);
-    offload->port_mgr = dpif_offload_port_mgr_init();
     offload->once_enable = (struct ovsthread_once) OVSTHREAD_ONCE_INITIALIZER;
     offload->recirc_id_shared = !!(dpif_get_features(dpif)
                                    & OVS_DP_F_TC_RECIRC_SHARING);
@@ -205,14 +173,14 @@ static void
 tc_offload_close(struct dpif_offload *dpif_offload)
 {
     struct tc_offload *offload = tc_offload_cast(dpif_offload);
-    struct dpif_offload_port_mgr_port *port;
+    struct dpif_offload_port *port;
 
-    DPIF_OFFLOAD_PORT_MGR_PORT_FOR_EACH (port, offload->port_mgr) {
+    DPIF_OFFLOAD_PORT_MGR_PORT_FOR_EACH (port, dpif_offload) {
         tc_port_del(dpif_offload, port->port_no);
     }
 
-    dpif_offload_port_mgr_uninit(offload->port_mgr);
     ovsthread_once_destroy(&offload->once_enable);
+    dpif_offload_destroy(dpif_offload);
     free(offload);
 }
 
@@ -224,12 +192,12 @@ tc_offload_set_config(struct dpif_offload *offload_,
 
     if (smap_get_bool(other_cfg, "hw-offload", false)) {
         if (ovsthread_once_start(&offload->once_enable)) {
-            struct dpif_offload_port_mgr_port *port;
+            struct dpif_offload_port *port;
 
             tc_set_policy(smap_get_def(other_cfg, "tc-policy",
                                        TC_POLICY_DEFAULT));
 
-            DPIF_OFFLOAD_PORT_MGR_PORT_FOR_EACH (port, offload->port_mgr) {
+            DPIF_OFFLOAD_PORT_MGR_PORT_FOR_EACH (port, offload_) {
                 tc_offload_enable(offload_, port);
             }
 
@@ -239,16 +207,14 @@ tc_offload_set_config(struct dpif_offload *offload_,
 }
 
 static void
-tc_offload_get_debug(const struct dpif_offload *offload_, struct ds *ds,
+tc_offload_get_debug(const struct dpif_offload *offload, struct ds *ds,
                      struct json *json)
 {
-    struct tc_offload *offload = tc_offload_cast(offload_);
-
     if (json) {
         struct json *json_ports = json_object_create();
-        struct dpif_offload_port_mgr_port *port;
+        struct dpif_offload_port *port;
 
-        DPIF_OFFLOAD_PORT_MGR_PORT_FOR_EACH (port, offload->port_mgr) {
+        DPIF_OFFLOAD_PORT_MGR_PORT_FOR_EACH (port, offload) {
             struct json *json_port = json_object_create();
 
             json_object_put(json_port, "port_no",
@@ -266,9 +232,9 @@ tc_offload_get_debug(const struct dpif_offload *offload_, 
struct ds *ds,
             json_destroy(json_ports);
         }
     } else if (ds) {
-        struct dpif_offload_port_mgr_port *port;
+        struct dpif_offload_port *port;
 
-        DPIF_OFFLOAD_PORT_MGR_PORT_FOR_EACH (port, offload->port_mgr) {
+        DPIF_OFFLOAD_PORT_MGR_PORT_FOR_EACH (port, offload) {
             ds_put_format(ds, "  - %s: port_no: %u, ifindex: %d\n",
                           netdev_get_name(port->netdev),
                           port->port_no, port->ifindex);
@@ -290,13 +256,12 @@ tc_can_offload(struct dpif_offload *dpif_offload 
OVS_UNUSED,
 }
 
 static int
-tc_flow_flush(const struct dpif_offload *offload_)
+tc_flow_flush(const struct dpif_offload *offload)
 {
-    struct tc_offload *offload = tc_offload_cast(offload_);
-    struct dpif_offload_port_mgr_port *port;
+    struct dpif_offload_port *port;
     int error = 0;
 
-    DPIF_OFFLOAD_PORT_MGR_PORT_FOR_EACH (port, offload->port_mgr) {
+    DPIF_OFFLOAD_PORT_MGR_PORT_FOR_EACH (port, offload) {
         int rc = tc_netdev_flow_flush(port->netdev);
 
         if (rc && !error) {
@@ -320,22 +285,21 @@ tc_flow_dump_thread_cast(
 }
 
 static struct dpif_offload_flow_dump *
-tc_flow_dump_create(const struct dpif_offload *offload_, bool terse)
+tc_flow_dump_create(const struct dpif_offload *offload, bool terse)
 {
-    struct tc_offload *offload = tc_offload_cast(offload_);
-    struct dpif_offload_port_mgr_port *port;
+    struct dpif_offload_port *port;
     size_t added_port_count = 0;
     struct tc_flow_dump *dump;
     size_t port_count;
 
-    port_count = dpif_offload_port_mgr_port_count(offload->port_mgr);
+    port_count = dpif_offload_port_mgr_port_count(offload);
 
     dump = xmalloc(sizeof *dump +
                    (port_count * sizeof(struct netdev_tc_flow_dump)));
 
-    dpif_offload_flow_dump_init(&dump->dump, offload_, terse);
+    dpif_offload_flow_dump_init(&dump->dump, offload, terse);
 
-    DPIF_OFFLOAD_PORT_MGR_PORT_FOR_EACH (port, offload->port_mgr) {
+    DPIF_OFFLOAD_PORT_MGR_PORT_FOR_EACH (port, offload) {
         if (added_port_count >= port_count) {
             break;
         }
@@ -526,7 +490,7 @@ tc_parse_flow_put(struct tc_offload *offload_tc, struct 
dpif *dpif,
                   struct dpif_flow_put *put)
 {
     static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 20);
-    struct dpif_offload_port_mgr_port *port;
+    struct dpif_offload_port *port;
     const struct nlattr *nla;
     struct tc_offload_info info;
     struct match match;
@@ -548,7 +512,7 @@ tc_parse_flow_put(struct tc_offload *offload_tc, struct 
dpif *dpif,
     }
 
     in_port = match.flow.in_port.odp_port;
-    port = dpif_offload_port_mgr_find_by_odp_port(offload_tc->port_mgr,
+    port = dpif_offload_port_mgr_find_by_odp_port(&offload_tc->offload,
                                                   in_port);
     if (!port) {
         return EOPNOTSUPP;
@@ -557,12 +521,12 @@ tc_parse_flow_put(struct tc_offload *offload_tc, struct 
dpif *dpif,
     /* Check the output port for a tunnel. */
     NL_ATTR_FOR_EACH (nla, left, put->actions, put->actions_len) {
         if (nl_attr_type(nla) == OVS_ACTION_ATTR_OUTPUT) {
-            struct dpif_offload_port_mgr_port *mgr_port;
+            struct dpif_offload_port *mgr_port;
             odp_port_t out_port;
 
             out_port = nl_attr_get_odp_port(nla);
             mgr_port = dpif_offload_port_mgr_find_by_odp_port(
-                offload_tc->port_mgr, out_port);
+                &offload_tc->offload, out_port);
 
             if (!mgr_port) {
                 err = EOPNOTSUPP;
@@ -650,8 +614,8 @@ out:
 static int
 tc_parse_flow_get(struct tc_offload *offload_tc, struct dpif_flow_get *get)
 {
-    struct dpif_offload_port_mgr_port *port;
     struct dpif_flow *dpif_flow = get->flow;
+    struct dpif_offload_port *port;
     struct odputil_keybuf maskbuf;
     struct odputil_keybuf keybuf;
     struct odputil_keybuf actbuf;
@@ -666,7 +630,7 @@ tc_parse_flow_get(struct tc_offload *offload_tc, struct 
dpif_flow_get *get)
 
     ofpbuf_use_stack(&buf, &act_buf, sizeof act_buf);
 
-    DPIF_OFFLOAD_PORT_MGR_PORT_FOR_EACH (port, offload_tc->port_mgr) {
+    DPIF_OFFLOAD_PORT_MGR_PORT_FOR_EACH (port, &offload_tc->offload) {
         if (!tc_netdev_flow_get(port->netdev, &match, &actions, get->ufid,
                                 &stats, &attrs, &buf)) {
             err = 0;
@@ -751,12 +715,11 @@ tc_operate(struct dpif *dpif, const struct dpif_offload 
*offload_,
 }
 
 odp_port_t
-tc_get_port_id_by_ifindex(const struct dpif_offload *offload_, int ifindex)
+tc_get_port_id_by_ifindex(const struct dpif_offload *offload, int ifindex)
 {
-    struct tc_offload *offload = tc_offload_cast(offload_);
-    struct dpif_offload_port_mgr_port *port;
+    struct dpif_offload_port *port;
 
-    port = dpif_offload_port_mgr_find_by_ifindex(offload->port_mgr, ifindex);
+    port = dpif_offload_port_mgr_find_by_ifindex(offload, ifindex);
     if (port) {
         return port->port_no;
     }
@@ -774,9 +737,6 @@ struct dpif_offload_class dpif_offload_tc_class = {
     .can_offload = tc_can_offload,
     .port_add = tc_port_add,
     .port_del = tc_port_del,
-    .port_dump_start = tc_port_dump_start,
-    .port_dump_next = tc_port_dump_next,
-    .port_dump_done = tc_port_dump_done,
     .flow_flush = tc_flow_flush,
     .flow_dump_create = tc_flow_dump_create,
     .flow_dump_next = tc_flow_dump_next,
diff --git a/lib/dpif-offload.c b/lib/dpif-offload.c
index 6125675b39..b431ce3d0a 100644
--- a/lib/dpif-offload.c
+++ b/lib/dpif-offload.c
@@ -159,9 +159,6 @@ dpif_offload_module_init(void)
                    && base_dpif_offload_classes[i]->can_offload
                    && base_dpif_offload_classes[i]->port_add
                    && base_dpif_offload_classes[i]->port_del
-                   && base_dpif_offload_classes[i]->port_dump_start
-                   && base_dpif_offload_classes[i]->port_dump_next
-                   && base_dpif_offload_classes[i]->port_dump_done
                    && base_dpif_offload_classes[i]->get_netdev);
 
         ovs_assert((base_dpif_offload_classes[i]->flow_dump_create &&
@@ -360,11 +357,8 @@ provider_collection_free_rcu(
     /* We need to use the safe variant here as we removed the entry, and the
      * close API will free() it. */
     LIST_FOR_EACH_SAFE (offload_entry, dpif_list_node, &collection->list) {
-        char *name = offload_entry->name;
-
         ovs_list_remove(&offload_entry->dpif_list_node);
         offload_entry->class->close(offload_entry);
-        free(name);
     }
 
     /* Free remaining resources. */
@@ -434,6 +428,16 @@ dpif_offload_init(struct dpif_offload *offload,
 
     offload->class = class;
     offload->name = xasprintf("%s[%s]", class->type, dpif_name(dpif));
+    offload->ports = dpif_offload_port_mgr_init();
+}
+
+void
+dpif_offload_destroy(struct dpif_offload *offload)
+{
+    ovs_assert(offload);
+
+    dpif_offload_port_mgr_destroy(offload);
+    free(offload->name);
 }
 
 const char *
@@ -460,9 +464,9 @@ dpif_offload_get_debug(const struct dpif_offload *offload, 
struct ds *ds,
     return true;
 }
 
-int dpif_offload_stats_get(struct dpif *dpif,
-                           struct netdev_custom_stats **stats_,
-                           size_t *n_stats)
+int
+dpif_offload_stats_get(struct dpif *dpif, struct netdev_custom_stats **stats_,
+                       size_t *n_stats)
 {
     struct dpif_offload_provider_collection *collection;
     struct netdev_custom_stats *stats;
@@ -1206,27 +1210,23 @@ dpif_offload_port_dump_start(struct 
dpif_offload_port_dump *dump,
     if (!dpif_offload_get_next_offload_for_dump(dump)) {
         dump->error = EOF;
     } else {
-        dump->error = dump->offload->class->port_dump_start(dump->offload,
+        dump->error = dpif_offload_port_mgr_port_dump_start(dump->offload,
                                                             &dump->state);
     }
 }
 
 bool
 dpif_offload_port_dump_next(struct dpif_offload_port_dump *dump,
-                            struct dpif_offload_port *port)
+                            struct dpif_offload_port_dump_port *port)
 {
-    const struct dpif_offload *offload = dump->offload;
-
     while (true) {
-
         if (dump->error) {
             break;
         }
 
-        dump->error = offload->class->port_dump_next(offload, dump->state,
-                                                     port);
+        dump->error = dpif_offload_port_mgr_port_dump_next(dump->state, port);
         if (dump->error) {
-            offload->class->port_dump_done(offload, dump->state);
+            dpif_offload_port_mgr_port_dump_done(dump->state);
 
             if (dump->error != EOF) {
                 /* If the error is not EOF, we stop dumping ports from all
@@ -1235,9 +1235,8 @@ dpif_offload_port_dump_next(struct dpif_offload_port_dump 
*dump,
             }
 
             if (dpif_offload_get_next_offload_for_dump(dump)) {
-                offload = dump->offload;
-                dump->error = offload->class->port_dump_start(offload,
-                                                              &dump->state);
+                dump->error = dpif_offload_port_mgr_port_dump_start(
+                    dump->offload, &dump->state);
                 continue;
             }
         }
@@ -1251,8 +1250,7 @@ int
 dpif_offload_port_dump_done(struct dpif_offload_port_dump *dump)
 {
     if (!dump->error && dump->offload) {
-        dump->error = dump->offload->class->port_dump_done(dump->offload,
-                                                           dump->state);
+        dump->error = dpif_offload_port_mgr_port_dump_done(dump->state);
     }
     return dump->error == EOF ? 0 : dump->error;
 }
@@ -1296,8 +1294,8 @@ bool
 dpif_offload_netdevs_out_of_resources(struct dpif *dpif)
 {
     struct dpif_offload_provider_collection *collection;
+    struct dpif_offload_port_dump_port port;
     struct dpif_offload_port_dump dump;
-    struct dpif_offload_port port;
     bool oor = false;
 
     collection = dpif_get_offload_provider_collection(dpif);
@@ -1575,34 +1573,42 @@ dpif_offload_port_mgr_init(void)
 }
 
 void
-dpif_offload_port_mgr_uninit(struct dpif_offload_port_mgr *mgr)
+dpif_offload_port_mgr_destroy(struct dpif_offload *offload)
 {
-    if (!mgr) {
+    struct dpif_offload_port_mgr *ports;
+
+    if (!offload || !offload->ports) {
         return;
     }
 
-    ovs_assert(cmap_count(&mgr->odp_port_to_port) == 0);
-    ovs_assert(cmap_count(&mgr->netdev_to_port) == 0);
-    ovs_assert(cmap_count(&mgr->ifindex_to_port) == 0);
+    ports = offload->ports;
+    offload->ports = NULL;
+
+    ovs_assert(cmap_count(&ports->odp_port_to_port) == 0);
+    ovs_assert(cmap_count(&ports->netdev_to_port) == 0);
+    ovs_assert(cmap_count(&ports->ifindex_to_port) == 0);
 
-    cmap_destroy(&mgr->odp_port_to_port);
-    cmap_destroy(&mgr->netdev_to_port);
-    cmap_destroy(&mgr->ifindex_to_port);
-    free(mgr);
+    cmap_destroy(&ports->odp_port_to_port);
+    cmap_destroy(&ports->netdev_to_port);
+    cmap_destroy(&ports->ifindex_to_port);
+    free(ports);
 }
 
-struct dpif_offload_port_mgr_port *
-dpif_offload_port_mgr_find_by_ifindex(struct dpif_offload_port_mgr *mgr,
+struct dpif_offload_port *
+dpif_offload_port_mgr_find_by_ifindex(const struct dpif_offload *offload,
                                       int ifindex)
 {
-    struct dpif_offload_port_mgr_port *port;
+    struct dpif_offload_port_mgr *ports = offload->ports;
+    struct dpif_offload_port *port;
+
+    ovs_assert(ports);
 
     if (ifindex < 0) {
         return NULL;
     }
 
     CMAP_FOR_EACH_WITH_HASH (port, ifindex_node, hash_int(ifindex, 0),
-                             &mgr->ifindex_to_port) {
+                             &ports->ifindex_to_port) {
         if (port->ifindex == ifindex) {
             return port;
         }
@@ -1610,18 +1616,21 @@ dpif_offload_port_mgr_find_by_ifindex(struct 
dpif_offload_port_mgr *mgr,
     return NULL;
 }
 
-struct dpif_offload_port_mgr_port *
-dpif_offload_port_mgr_find_by_netdev(struct dpif_offload_port_mgr *mgr,
+struct dpif_offload_port *
+dpif_offload_port_mgr_find_by_netdev(const struct dpif_offload *offload,
                                      struct netdev *netdev)
 {
-    struct dpif_offload_port_mgr_port *port;
+    struct dpif_offload_port_mgr *ports = offload->ports;
+    struct dpif_offload_port *port;
+
+    ovs_assert(ports);
 
     if (!netdev) {
         return NULL;
     }
 
     CMAP_FOR_EACH_WITH_HASH (port, netdev_node, hash_pointer(netdev, 0),
-                             &mgr->netdev_to_port) {
+                             &ports->netdev_to_port) {
         if (port->netdev == netdev) {
             return port;
         }
@@ -1629,15 +1638,18 @@ dpif_offload_port_mgr_find_by_netdev(struct 
dpif_offload_port_mgr *mgr,
     return NULL;
 }
 
-struct dpif_offload_port_mgr_port *
-dpif_offload_port_mgr_find_by_odp_port(struct dpif_offload_port_mgr *mgr,
+struct dpif_offload_port *
+dpif_offload_port_mgr_find_by_odp_port(const struct dpif_offload *offload,
                                        odp_port_t port_no)
 {
-    struct dpif_offload_port_mgr_port *port;
+    struct dpif_offload_port_mgr *ports = offload->ports;
+    struct dpif_offload_port *port;
+
+    ovs_assert(ports);
 
     CMAP_FOR_EACH_WITH_HASH (port, odp_port_node,
                              hash_int(odp_to_u32(port_no), 0),
-                             &mgr->odp_port_to_port) {
+                             &ports->odp_port_to_port) {
         if (port->port_no == port_no) {
             return port;
         }
@@ -1645,145 +1657,129 @@ dpif_offload_port_mgr_find_by_odp_port(struct 
dpif_offload_port_mgr *mgr,
     return NULL;
 }
 
-struct dpif_offload_port_mgr_port *
-dpif_offload_port_mgr_remove(struct dpif_offload_port_mgr *mgr,
-                             odp_port_t port_no)
+struct dpif_offload_port *
+dpif_offload_port_mgr_remove(struct dpif_offload *offload, odp_port_t port_no)
 {
     /* Note that it is the caller's responsibility to release the netdev
      * after port removal.  This should probably be done through the
      * ovsrcu_postpone() API. */
-    struct dpif_offload_port_mgr_port *port;
+    struct dpif_offload_port_mgr *ports = offload->ports;
+    struct dpif_offload_port *port;
 
-    ovs_mutex_lock(&mgr->cmap_mod_lock);
+    ovs_assert(ports);
 
-    port = dpif_offload_port_mgr_find_by_odp_port(mgr, port_no);
+    ovs_mutex_lock(&ports->cmap_mod_lock);
+
+    port = dpif_offload_port_mgr_find_by_odp_port(offload, port_no);
 
     if (port) {
-        cmap_remove(&mgr->odp_port_to_port, &port->odp_port_node,
+        cmap_remove(&ports->odp_port_to_port, &port->odp_port_node,
                     hash_int(odp_to_u32(port_no), 0));
-        cmap_remove(&mgr->netdev_to_port, &port->netdev_node,
+        cmap_remove(&ports->netdev_to_port, &port->netdev_node,
                     hash_pointer(port->netdev, 0));
 
         if (port->ifindex >= 0) {
-            cmap_remove(&mgr->ifindex_to_port, &port->ifindex_node,
+            cmap_remove(&ports->ifindex_to_port, &port->ifindex_node,
                         hash_int(port->ifindex, 0));
         }
     }
 
-    ovs_mutex_unlock(&mgr->cmap_mod_lock);
+    ovs_mutex_unlock(&ports->cmap_mod_lock);
     return port;
 }
 
 bool
-dpif_offload_port_mgr_add(struct dpif_offload_port_mgr *mgr,
-                          struct dpif_offload_port_mgr_port *port,
+dpif_offload_port_mgr_add(struct dpif_offload *offload,
+                          struct dpif_offload_port *port,
                           struct netdev *netdev, odp_port_t port_no,
                           bool need_ifindex)
 {
+    struct dpif_offload_port_mgr *ports;
+
     /* Note that this function takes a reference to the passed-in netdev.
      * However, on port removal it is the caller's responsibility to
      * release this reference. */
-    ovs_assert(netdev);
+    ovs_assert(offload->ports && netdev);
 
+    ports = offload->ports;
     memset(port, 0, sizeof *port);
     port->port_no = port_no;
     port->ifindex = need_ifindex ? netdev_get_ifindex(netdev) : -1;
 
-    ovs_mutex_lock(&mgr->cmap_mod_lock);
+    ovs_mutex_lock(&ports->cmap_mod_lock);
 
-    if (dpif_offload_port_mgr_find_by_odp_port(mgr, port_no)
-        || dpif_offload_port_mgr_find_by_ifindex(mgr, port->ifindex)
-        || dpif_offload_port_mgr_find_by_netdev(mgr, netdev)) {
+    if (dpif_offload_port_mgr_find_by_odp_port(offload, port_no)
+        || dpif_offload_port_mgr_find_by_ifindex(offload, port->ifindex)
+        || dpif_offload_port_mgr_find_by_netdev(offload, netdev)) {
 
-        ovs_mutex_unlock(&mgr->cmap_mod_lock);
+        ovs_mutex_unlock(&ports->cmap_mod_lock);
         return false;
     }
 
     port->netdev = netdev_ref(netdev);
 
-    cmap_insert(&mgr->odp_port_to_port, &port->odp_port_node,
+    cmap_insert(&ports->odp_port_to_port, &port->odp_port_node,
                 hash_int(odp_to_u32(port_no), 0));
 
-    cmap_insert(&mgr->netdev_to_port, &port->netdev_node,
+    cmap_insert(&ports->netdev_to_port, &port->netdev_node,
                 hash_pointer(netdev, 0));
 
     if (port->ifindex >= 0) {
-        cmap_insert(&mgr->ifindex_to_port, &port->ifindex_node,
+        cmap_insert(&ports->ifindex_to_port, &port->ifindex_node,
                     hash_int(port->ifindex, 0));
     }
 
-    ovs_mutex_unlock(&mgr->cmap_mod_lock);
+    ovs_mutex_unlock(&ports->cmap_mod_lock);
     return true;
 }
 
 size_t
-dpif_offload_port_mgr_port_count(struct dpif_offload_port_mgr *mgr)
+dpif_offload_port_mgr_port_count(const struct dpif_offload *offload)
 {
-    return cmap_count(&mgr->odp_port_to_port);
+    ovs_assert(offload && offload->ports);
+
+    return cmap_count(&offload->ports->odp_port_to_port);
 }
 
 struct dpif_offload_port_mgr_dump_state {
     struct netdev *last_netdev;
-    size_t port_index;
-    size_t port_count;
-    odp_port_t ports[];
+    struct cmap_cursor cursor;
 };
 
 int
-dpif_offload_port_mgr_port_dump_start(struct dpif_offload_port_mgr *mgr,
+dpif_offload_port_mgr_port_dump_start(const struct dpif_offload *offload,
                                       void **statep)
 {
-    size_t port_count = dpif_offload_port_mgr_port_count(mgr);
     struct dpif_offload_port_mgr_dump_state *state;
-    struct dpif_offload_port_mgr_port *port;
-    size_t added_port_count = 0;
-
-    state = xmalloc(sizeof *state + (port_count * sizeof(odp_port_t)));
-
-    DPIF_OFFLOAD_PORT_MGR_PORT_FOR_EACH (port, mgr) {
-        if (added_port_count >= port_count) {
-            break;
-        }
 
-        state->ports[added_port_count] = port->port_no;
-        added_port_count++;
-    }
-    state->port_count = added_port_count;
-    state->port_index = 0;
+    state = xmalloc(sizeof *state);
+    state->cursor = cmap_cursor_start(&offload->ports->odp_port_to_port);
     state->last_netdev = NULL;
 
     *statep = state;
     return 0;
 }
 
-int dpif_offload_port_mgr_port_dump_next(struct dpif_offload_port_mgr *mgr,
-                                         void *state_,
-                                         struct dpif_offload_port *port)
+int
+dpif_offload_port_mgr_port_dump_next(void *state_,
+                                     struct dpif_offload_port_dump_port *port)
 {
     struct dpif_offload_port_mgr_dump_state *state = state_;
-    struct dpif_offload_port_mgr_port *mgr_port;
-
-    while (state->port_index < state->port_count) {
-
-        mgr_port = dpif_offload_port_mgr_find_by_odp_port(
-            mgr, state->ports[state->port_index++]);
+    struct dpif_offload_port *mgr_port;
 
-        if (mgr_port) {
-            port->netdev = netdev_ref(mgr_port->netdev);
-            port->port_no = mgr_port->port_no;
-
-            netdev_close(state->last_netdev);
-            state->last_netdev = port->netdev;
-            return 0;
-        }
+    CMAP_CURSOR_FOR_EACH_CONTINUE (mgr_port, odp_port_node, &state->cursor) {
+        port->netdev = netdev_ref(mgr_port->netdev);
+        netdev_close(state->last_netdev);
+        state->last_netdev = port->netdev;
+        port->port_no = mgr_port->port_no;
+        return 0;
     }
 
     return EOF;
 }
 
 int
-dpif_offload_port_mgr_port_dump_done(
-    struct dpif_offload_port_mgr *mgr OVS_UNUSED, void *state_)
+dpif_offload_port_mgr_port_dump_done(void *state_)
 {
     struct dpif_offload_port_mgr_dump_state *state = state_;
 
diff --git a/lib/dpif-offload.h b/lib/dpif-offload.h
index c4e6284a26..fedcc80bc5 100644
--- a/lib/dpif-offload.h
+++ b/lib/dpif-offload.h
@@ -58,6 +58,7 @@ bool dpif_offload_rebalance_policy_enabled(void);
 /* Per dpif specific functions. */
 void dpif_offload_init(struct dpif_offload *,
                        const struct dpif_offload_class *, struct dpif *);
+void dpif_offload_destroy(struct dpif_offload *);
 int dpif_attach_offload_providers(struct dpif *);
 void dpif_detach_offload_providers(struct dpif *);
 const char *dpif_offload_name(const struct dpif_offload *);
@@ -102,7 +103,7 @@ enum dpif_offload_impl_type 
dpif_offload_get_impl_type_by_class(
           : (dpif_offload_dump_done(DUMP), false));      \
         )
 
-struct dpif_offload_port {
+struct dpif_offload_port_dump_port {
     struct netdev *netdev;
     odp_port_t port_no;
 };
@@ -117,7 +118,7 @@ struct dpif_offload_port_dump {
 void dpif_offload_port_dump_start(struct dpif_offload_port_dump *,
                                   const struct dpif *);
 bool dpif_offload_port_dump_next(struct dpif_offload_port_dump *,
-                                 struct dpif_offload_port *);
+                                 struct dpif_offload_port_dump_port *);
 int dpif_offload_port_dump_done(struct dpif_offload_port_dump *);
 
 /* Iterates through each DPIF_OFFLOAD_PORT in DPIF, using DUMP as state.
-- 
2.52.0

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

Reply via email to