On 1/27/26 12:02 PM, Eelco Chaudron wrote:
> 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);

nit: All the port_mgr_port_dump functions can be static and not exported here.
     Providers can iterate ports directly with the macro below.

But also, do we need this API at all?  AFAICT, the only user of the
dpif_offload_port_dump_start/next() is the DPIF_OFFLOAD_PORT_FOR_EACH()
macro, for which the only user is dpif_offload_netdevs_out_of_resources(),
that can actually just iterate over all the ports directly, since the
port manager is now directly accessible from the dpif-offload main module.

> +
> +#define DPIF_OFFLOAD_PORT_MGR_PORT_FOR_EACH(PORT, OFFLOAD) \
> +    CMAP_FOR_EACH (PORT, odp_port_node, &(OFFLOAD)->ports->odp_port_to_port)

Would be great if we could rename all common functions removing the port_mgr
part from them, e.g.
  dpif_offload_port_mgr_find_by_ifindex() -> 
dpif_offload_port_find_by_ifindex().

But unfortunately, it will conflict with the top-level 
dpif_offload_port_add/del()
API.  So, probably should keep the naming for the functions as-is.

However, maybe it's worth renaming the macro?  i.e.
  DPIF_OFFLOAD_PORT_MGR_PORT_FOR_EACH -> DPIF_OFFLOAD_PORT_FOR_EACH
in case we don't actually need the port dump API.

WDYT?

>  
>  /* 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);

nit: While we're here, may shift the line 16 spaces to the right?

>  
>              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);

nit: Same here.

>                  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.

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

Reply via email to