Re: [ovs-dev] [PATCH v7 08/16] dpif-netdev: Add pmd thread local port cache for transmission.

2016-04-19 Thread Ilya Maximets
On 19.04.2016 00:19, Daniele Di Proietto wrote:
> 
> 
> On 18/04/2016 07:50, "Ilya Maximets"  wrote:
> 
>> On 08.04.2016 06:13, Daniele Di Proietto wrote:
>>> Signed-off-by: Daniele Di Proietto 
>>> ---
>>>  lib/dpif-netdev.c | 243
>>> +++---
>>>  1 file changed, 175 insertions(+), 68 deletions(-)
>>>
>>> diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
>>> index 8c5893d..5d1cc43 100644
>>> --- a/lib/dpif-netdev.c
>>> +++ b/lib/dpif-netdev.c
>>> @@ -185,6 +185,7 @@ static bool dpcls_lookup(const struct dpcls *cls,
>>>   *
>>>   *dp_netdev_mutex (global)
>>>   *port_mutex
>>> + *non_pmd_mutex
>>>   */
>>>  struct dp_netdev {
>>>  const struct dpif_class *const class;
>>> @@ -380,6 +381,13 @@ struct rxq_poll {
>>>  struct ovs_list node;
>>>  };
>>>  
>>> +/* Contained by struct dp_netdev_pmd_thread's 'port_cache' or
>>> 'tx_ports'. */
>>> +struct tx_port {
>>> +odp_port_t port_no;
>>> +struct netdev *netdev;
>>> +struct hmap_node node;
>>> +};
>>> +
>>>  /* PMD: Poll modes drivers.  PMD accesses devices via polling to
>>> eliminate
>>>   * the performance overhead of interrupt processing.  Therefore netdev
>>> can
>>>   * not implement rx-wait for these devices.  dpif-netdev needs to poll
>>> @@ -436,10 +444,18 @@ struct dp_netdev_pmd_thread {
>>>  atomic_int tx_qid;  /* Queue id used by this pmd
>>> thread to
>>>   * send packets on all netdevs */
>>>  
>>> -struct ovs_mutex poll_mutex;/* Mutex for poll_list. */
>>> +struct ovs_mutex port_mutex;/* Mutex for 'poll_list' and
>>> 'tx_ports'. */
>>>  /* List of rx queues to poll. */
>>>  struct ovs_list poll_list OVS_GUARDED;
>>> -int poll_cnt;   /* Number of elemints in
>>> poll_list. */
>>> +/* Number of elements in 'poll_list' */
>>> +int poll_cnt;
>>> +/* Map of 'tx_port's used for transmission.  Written by the main
>>> thread,
>>> + * read by the pmd thread. */
>>> +struct hmap tx_ports OVS_GUARDED;
>>> +
>>> +/* Map of 'tx_port' used in the fast path. This is a thread-local
>>> copy
>>> + * 'tx_ports'. */
>>> +struct hmap port_cache;
>>>  
>>>  /* Only a pmd thread can write on its own 'cycles' and 'stats'.
>>>   * The main thread keeps 'stats_zero' and 'cycles_zero' as base
>>> @@ -495,7 +511,7 @@ dp_netdev_pmd_get_next(struct dp_netdev *dp, struct
>>> cmap_position *pos);
>>>  static void dp_netdev_destroy_all_pmds(struct dp_netdev *dp);
>>>  static void dp_netdev_del_pmds_on_numa(struct dp_netdev *dp, int
>>> numa_id);
>>>  static void dp_netdev_set_pmds_on_numa(struct dp_netdev *dp, int
>>> numa_id);
>>> -static void dp_netdev_pmd_clear_poll_list(struct dp_netdev_pmd_thread
>>> *pmd);
>>> +static void dp_netdev_pmd_clear_ports(struct dp_netdev_pmd_thread
>>> *pmd);
>>>  static void dp_netdev_del_port_from_all_pmds(struct dp_netdev *dp,
>>>   struct dp_netdev_port
>>> *port);
>>>  static void
>>> @@ -509,6 +525,8 @@ static void dp_netdev_reset_pmd_threads(struct
>>> dp_netdev *dp);
>>>  static bool dp_netdev_pmd_try_ref(struct dp_netdev_pmd_thread *pmd);
>>>  static void dp_netdev_pmd_unref(struct dp_netdev_pmd_thread *pmd);
>>>  static void dp_netdev_pmd_flow_flush(struct dp_netdev_pmd_thread *pmd);
>>> +static void pmd_load_cached_ports(struct dp_netdev_pmd_thread *pmd)
>>> +OVS_REQUIRES(pmd->port_mutex);
>>>  
>>>  static inline bool emc_entry_alive(struct emc_entry *ce);
>>>  static void emc_clear_entry(struct emc_entry *ce);
>>> @@ -691,7 +709,7 @@ pmd_info_show_rxq(struct ds *reply, struct
>>> dp_netdev_pmd_thread *pmd)
>>>  ds_put_format(reply, "pmd thread numa_id %d core_id %u:\n",
>>>pmd->numa_id, pmd->core_id);
>>>  
>>> -ovs_mutex_lock(>poll_mutex);
>>> +ovs_mutex_lock(>port_mutex);
>>>  LIST_FOR_EACH (poll, node, >poll_list) {
>>>  const char *name = netdev_get_name(poll->port->netdev);
>>>  
>>> @@ -705,7 +723,7 @@ pmd_info_show_rxq(struct ds *reply, struct
>>> dp_netdev_pmd_thread *pmd)
>>>  ds_put_format(reply, " %d",
>>> netdev_rxq_get_queue_id(poll->rx));
>>>  prev_name = name;
>>>  }
>>> -ovs_mutex_unlock(>poll_mutex);
>>> +ovs_mutex_unlock(>port_mutex);
>>>  ds_put_cstr(reply, "\n");
>>>  }
>>>  }
>>> @@ -1078,6 +1096,11 @@ dp_netdev_reload_pmd__(struct
>>> dp_netdev_pmd_thread *pmd)
>>>  int old_seq;
>>>  
>>>  if (pmd->core_id == NON_PMD_CORE_ID) {
>>> +ovs_mutex_lock(>dp->non_pmd_mutex);
>>> +ovs_mutex_lock(>port_mutex);
>>> +pmd_load_cached_ports(pmd);
>>> +ovs_mutex_unlock(>port_mutex);
>>> +ovs_mutex_unlock(>dp->non_pmd_mutex);
>>>  return;
>>>  }
>>>  
>>> @@ -1200,9 +1223,7 @@ do_add_port(struct dp_netdev *dp, const char
>>> 

Re: [ovs-dev] [PATCH v7 08/16] dpif-netdev: Add pmd thread local port cache for transmission.

2016-04-18 Thread Daniele Di Proietto


On 18/04/2016 07:50, "Ilya Maximets"  wrote:

>On 08.04.2016 06:13, Daniele Di Proietto wrote:
>> Signed-off-by: Daniele Di Proietto 
>> ---
>>  lib/dpif-netdev.c | 243
>>+++---
>>  1 file changed, 175 insertions(+), 68 deletions(-)
>> 
>> diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
>> index 8c5893d..5d1cc43 100644
>> --- a/lib/dpif-netdev.c
>> +++ b/lib/dpif-netdev.c
>> @@ -185,6 +185,7 @@ static bool dpcls_lookup(const struct dpcls *cls,
>>   *
>>   *dp_netdev_mutex (global)
>>   *port_mutex
>> + *non_pmd_mutex
>>   */
>>  struct dp_netdev {
>>  const struct dpif_class *const class;
>> @@ -380,6 +381,13 @@ struct rxq_poll {
>>  struct ovs_list node;
>>  };
>>  
>> +/* Contained by struct dp_netdev_pmd_thread's 'port_cache' or
>>'tx_ports'. */
>> +struct tx_port {
>> +odp_port_t port_no;
>> +struct netdev *netdev;
>> +struct hmap_node node;
>> +};
>> +
>>  /* PMD: Poll modes drivers.  PMD accesses devices via polling to
>>eliminate
>>   * the performance overhead of interrupt processing.  Therefore netdev
>>can
>>   * not implement rx-wait for these devices.  dpif-netdev needs to poll
>> @@ -436,10 +444,18 @@ struct dp_netdev_pmd_thread {
>>  atomic_int tx_qid;  /* Queue id used by this pmd
>>thread to
>>   * send packets on all netdevs */
>>  
>> -struct ovs_mutex poll_mutex;/* Mutex for poll_list. */
>> +struct ovs_mutex port_mutex;/* Mutex for 'poll_list' and
>>'tx_ports'. */
>>  /* List of rx queues to poll. */
>>  struct ovs_list poll_list OVS_GUARDED;
>> -int poll_cnt;   /* Number of elemints in
>>poll_list. */
>> +/* Number of elements in 'poll_list' */
>> +int poll_cnt;
>> +/* Map of 'tx_port's used for transmission.  Written by the main
>>thread,
>> + * read by the pmd thread. */
>> +struct hmap tx_ports OVS_GUARDED;
>> +
>> +/* Map of 'tx_port' used in the fast path. This is a thread-local
>>copy
>> + * 'tx_ports'. */
>> +struct hmap port_cache;
>>  
>>  /* Only a pmd thread can write on its own 'cycles' and 'stats'.
>>   * The main thread keeps 'stats_zero' and 'cycles_zero' as base
>> @@ -495,7 +511,7 @@ dp_netdev_pmd_get_next(struct dp_netdev *dp, struct
>>cmap_position *pos);
>>  static void dp_netdev_destroy_all_pmds(struct dp_netdev *dp);
>>  static void dp_netdev_del_pmds_on_numa(struct dp_netdev *dp, int
>>numa_id);
>>  static void dp_netdev_set_pmds_on_numa(struct dp_netdev *dp, int
>>numa_id);
>> -static void dp_netdev_pmd_clear_poll_list(struct dp_netdev_pmd_thread
>>*pmd);
>> +static void dp_netdev_pmd_clear_ports(struct dp_netdev_pmd_thread
>>*pmd);
>>  static void dp_netdev_del_port_from_all_pmds(struct dp_netdev *dp,
>>   struct dp_netdev_port
>>*port);
>>  static void
>> @@ -509,6 +525,8 @@ static void dp_netdev_reset_pmd_threads(struct
>>dp_netdev *dp);
>>  static bool dp_netdev_pmd_try_ref(struct dp_netdev_pmd_thread *pmd);
>>  static void dp_netdev_pmd_unref(struct dp_netdev_pmd_thread *pmd);
>>  static void dp_netdev_pmd_flow_flush(struct dp_netdev_pmd_thread *pmd);
>> +static void pmd_load_cached_ports(struct dp_netdev_pmd_thread *pmd)
>> +OVS_REQUIRES(pmd->port_mutex);
>>  
>>  static inline bool emc_entry_alive(struct emc_entry *ce);
>>  static void emc_clear_entry(struct emc_entry *ce);
>> @@ -691,7 +709,7 @@ pmd_info_show_rxq(struct ds *reply, struct
>>dp_netdev_pmd_thread *pmd)
>>  ds_put_format(reply, "pmd thread numa_id %d core_id %u:\n",
>>pmd->numa_id, pmd->core_id);
>>  
>> -ovs_mutex_lock(>poll_mutex);
>> +ovs_mutex_lock(>port_mutex);
>>  LIST_FOR_EACH (poll, node, >poll_list) {
>>  const char *name = netdev_get_name(poll->port->netdev);
>>  
>> @@ -705,7 +723,7 @@ pmd_info_show_rxq(struct ds *reply, struct
>>dp_netdev_pmd_thread *pmd)
>>  ds_put_format(reply, " %d",
>>netdev_rxq_get_queue_id(poll->rx));
>>  prev_name = name;
>>  }
>> -ovs_mutex_unlock(>poll_mutex);
>> +ovs_mutex_unlock(>port_mutex);
>>  ds_put_cstr(reply, "\n");
>>  }
>>  }
>> @@ -1078,6 +1096,11 @@ dp_netdev_reload_pmd__(struct
>>dp_netdev_pmd_thread *pmd)
>>  int old_seq;
>>  
>>  if (pmd->core_id == NON_PMD_CORE_ID) {
>> +ovs_mutex_lock(>dp->non_pmd_mutex);
>> +ovs_mutex_lock(>port_mutex);
>> +pmd_load_cached_ports(pmd);
>> +ovs_mutex_unlock(>port_mutex);
>> +ovs_mutex_unlock(>dp->non_pmd_mutex);
>>  return;
>>  }
>>  
>> @@ -1200,9 +1223,7 @@ do_add_port(struct dp_netdev *dp, const char
>>*devname, const char *type,
>>  
>>  cmap_insert(>ports, >node, hash_port_no(port_no));
>>  
>> -if (netdev_is_pmd(port->netdev)) {
>> -dp_netdev_add_port_to_pmds(dp, port);
>> -}
>> +

Re: [ovs-dev] [PATCH v7 08/16] dpif-netdev: Add pmd thread local port cache for transmission.

2016-04-18 Thread Ilya Maximets
On 08.04.2016 06:13, Daniele Di Proietto wrote:
> Signed-off-by: Daniele Di Proietto 
> ---
>  lib/dpif-netdev.c | 243 
> +++---
>  1 file changed, 175 insertions(+), 68 deletions(-)
> 
> diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
> index 8c5893d..5d1cc43 100644
> --- a/lib/dpif-netdev.c
> +++ b/lib/dpif-netdev.c
> @@ -185,6 +185,7 @@ static bool dpcls_lookup(const struct dpcls *cls,
>   *
>   *dp_netdev_mutex (global)
>   *port_mutex
> + *non_pmd_mutex
>   */
>  struct dp_netdev {
>  const struct dpif_class *const class;
> @@ -380,6 +381,13 @@ struct rxq_poll {
>  struct ovs_list node;
>  };
>  
> +/* Contained by struct dp_netdev_pmd_thread's 'port_cache' or 'tx_ports'. */
> +struct tx_port {
> +odp_port_t port_no;
> +struct netdev *netdev;
> +struct hmap_node node;
> +};
> +
>  /* PMD: Poll modes drivers.  PMD accesses devices via polling to eliminate
>   * the performance overhead of interrupt processing.  Therefore netdev can
>   * not implement rx-wait for these devices.  dpif-netdev needs to poll
> @@ -436,10 +444,18 @@ struct dp_netdev_pmd_thread {
>  atomic_int tx_qid;  /* Queue id used by this pmd thread to
>   * send packets on all netdevs */
>  
> -struct ovs_mutex poll_mutex;/* Mutex for poll_list. */
> +struct ovs_mutex port_mutex;/* Mutex for 'poll_list' and 'tx_ports'. 
> */
>  /* List of rx queues to poll. */
>  struct ovs_list poll_list OVS_GUARDED;
> -int poll_cnt;   /* Number of elemints in poll_list. */
> +/* Number of elements in 'poll_list' */
> +int poll_cnt;
> +/* Map of 'tx_port's used for transmission.  Written by the main thread,
> + * read by the pmd thread. */
> +struct hmap tx_ports OVS_GUARDED;
> +
> +/* Map of 'tx_port' used in the fast path. This is a thread-local copy
> + * 'tx_ports'. */
> +struct hmap port_cache;
>  
>  /* Only a pmd thread can write on its own 'cycles' and 'stats'.
>   * The main thread keeps 'stats_zero' and 'cycles_zero' as base
> @@ -495,7 +511,7 @@ dp_netdev_pmd_get_next(struct dp_netdev *dp, struct 
> cmap_position *pos);
>  static void dp_netdev_destroy_all_pmds(struct dp_netdev *dp);
>  static void dp_netdev_del_pmds_on_numa(struct dp_netdev *dp, int numa_id);
>  static void dp_netdev_set_pmds_on_numa(struct dp_netdev *dp, int numa_id);
> -static void dp_netdev_pmd_clear_poll_list(struct dp_netdev_pmd_thread *pmd);
> +static void dp_netdev_pmd_clear_ports(struct dp_netdev_pmd_thread *pmd);
>  static void dp_netdev_del_port_from_all_pmds(struct dp_netdev *dp,
>   struct dp_netdev_port *port);
>  static void
> @@ -509,6 +525,8 @@ static void dp_netdev_reset_pmd_threads(struct dp_netdev 
> *dp);
>  static bool dp_netdev_pmd_try_ref(struct dp_netdev_pmd_thread *pmd);
>  static void dp_netdev_pmd_unref(struct dp_netdev_pmd_thread *pmd);
>  static void dp_netdev_pmd_flow_flush(struct dp_netdev_pmd_thread *pmd);
> +static void pmd_load_cached_ports(struct dp_netdev_pmd_thread *pmd)
> +OVS_REQUIRES(pmd->port_mutex);
>  
>  static inline bool emc_entry_alive(struct emc_entry *ce);
>  static void emc_clear_entry(struct emc_entry *ce);
> @@ -691,7 +709,7 @@ pmd_info_show_rxq(struct ds *reply, struct 
> dp_netdev_pmd_thread *pmd)
>  ds_put_format(reply, "pmd thread numa_id %d core_id %u:\n",
>pmd->numa_id, pmd->core_id);
>  
> -ovs_mutex_lock(>poll_mutex);
> +ovs_mutex_lock(>port_mutex);
>  LIST_FOR_EACH (poll, node, >poll_list) {
>  const char *name = netdev_get_name(poll->port->netdev);
>  
> @@ -705,7 +723,7 @@ pmd_info_show_rxq(struct ds *reply, struct 
> dp_netdev_pmd_thread *pmd)
>  ds_put_format(reply, " %d", netdev_rxq_get_queue_id(poll->rx));
>  prev_name = name;
>  }
> -ovs_mutex_unlock(>poll_mutex);
> +ovs_mutex_unlock(>port_mutex);
>  ds_put_cstr(reply, "\n");
>  }
>  }
> @@ -1078,6 +1096,11 @@ dp_netdev_reload_pmd__(struct dp_netdev_pmd_thread 
> *pmd)
>  int old_seq;
>  
>  if (pmd->core_id == NON_PMD_CORE_ID) {
> +ovs_mutex_lock(>dp->non_pmd_mutex);
> +ovs_mutex_lock(>port_mutex);
> +pmd_load_cached_ports(pmd);
> +ovs_mutex_unlock(>port_mutex);
> +ovs_mutex_unlock(>dp->non_pmd_mutex);
>  return;
>  }
>  
> @@ -1200,9 +1223,7 @@ do_add_port(struct dp_netdev *dp, const char *devname, 
> const char *type,
>  
>  cmap_insert(>ports, >node, hash_port_no(port_no));
>  
> -if (netdev_is_pmd(port->netdev)) {
> -dp_netdev_add_port_to_pmds(dp, port);
> -}
> +dp_netdev_add_port_to_pmds(dp, port);
>  seq_change(dp->port_seq);
>  
>  return 0;
> @@ -1371,6 +1392,9 @@ do_del_port(struct dp_netdev *dp, struct dp_netdev_port 
> *port)
>  {
>  

[ovs-dev] [PATCH v7 08/16] dpif-netdev: Add pmd thread local port cache for transmission.

2016-04-07 Thread Daniele Di Proietto
Signed-off-by: Daniele Di Proietto 
---
 lib/dpif-netdev.c | 243 +++---
 1 file changed, 175 insertions(+), 68 deletions(-)

diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
index 8c5893d..5d1cc43 100644
--- a/lib/dpif-netdev.c
+++ b/lib/dpif-netdev.c
@@ -185,6 +185,7 @@ static bool dpcls_lookup(const struct dpcls *cls,
  *
  *dp_netdev_mutex (global)
  *port_mutex
+ *non_pmd_mutex
  */
 struct dp_netdev {
 const struct dpif_class *const class;
@@ -380,6 +381,13 @@ struct rxq_poll {
 struct ovs_list node;
 };
 
+/* Contained by struct dp_netdev_pmd_thread's 'port_cache' or 'tx_ports'. */
+struct tx_port {
+odp_port_t port_no;
+struct netdev *netdev;
+struct hmap_node node;
+};
+
 /* PMD: Poll modes drivers.  PMD accesses devices via polling to eliminate
  * the performance overhead of interrupt processing.  Therefore netdev can
  * not implement rx-wait for these devices.  dpif-netdev needs to poll
@@ -436,10 +444,18 @@ struct dp_netdev_pmd_thread {
 atomic_int tx_qid;  /* Queue id used by this pmd thread to
  * send packets on all netdevs */
 
-struct ovs_mutex poll_mutex;/* Mutex for poll_list. */
+struct ovs_mutex port_mutex;/* Mutex for 'poll_list' and 'tx_ports'. */
 /* List of rx queues to poll. */
 struct ovs_list poll_list OVS_GUARDED;
-int poll_cnt;   /* Number of elemints in poll_list. */
+/* Number of elements in 'poll_list' */
+int poll_cnt;
+/* Map of 'tx_port's used for transmission.  Written by the main thread,
+ * read by the pmd thread. */
+struct hmap tx_ports OVS_GUARDED;
+
+/* Map of 'tx_port' used in the fast path. This is a thread-local copy
+ * 'tx_ports'. */
+struct hmap port_cache;
 
 /* Only a pmd thread can write on its own 'cycles' and 'stats'.
  * The main thread keeps 'stats_zero' and 'cycles_zero' as base
@@ -495,7 +511,7 @@ dp_netdev_pmd_get_next(struct dp_netdev *dp, struct 
cmap_position *pos);
 static void dp_netdev_destroy_all_pmds(struct dp_netdev *dp);
 static void dp_netdev_del_pmds_on_numa(struct dp_netdev *dp, int numa_id);
 static void dp_netdev_set_pmds_on_numa(struct dp_netdev *dp, int numa_id);
-static void dp_netdev_pmd_clear_poll_list(struct dp_netdev_pmd_thread *pmd);
+static void dp_netdev_pmd_clear_ports(struct dp_netdev_pmd_thread *pmd);
 static void dp_netdev_del_port_from_all_pmds(struct dp_netdev *dp,
  struct dp_netdev_port *port);
 static void
@@ -509,6 +525,8 @@ static void dp_netdev_reset_pmd_threads(struct dp_netdev 
*dp);
 static bool dp_netdev_pmd_try_ref(struct dp_netdev_pmd_thread *pmd);
 static void dp_netdev_pmd_unref(struct dp_netdev_pmd_thread *pmd);
 static void dp_netdev_pmd_flow_flush(struct dp_netdev_pmd_thread *pmd);
+static void pmd_load_cached_ports(struct dp_netdev_pmd_thread *pmd)
+OVS_REQUIRES(pmd->port_mutex);
 
 static inline bool emc_entry_alive(struct emc_entry *ce);
 static void emc_clear_entry(struct emc_entry *ce);
@@ -691,7 +709,7 @@ pmd_info_show_rxq(struct ds *reply, struct 
dp_netdev_pmd_thread *pmd)
 ds_put_format(reply, "pmd thread numa_id %d core_id %u:\n",
   pmd->numa_id, pmd->core_id);
 
-ovs_mutex_lock(>poll_mutex);
+ovs_mutex_lock(>port_mutex);
 LIST_FOR_EACH (poll, node, >poll_list) {
 const char *name = netdev_get_name(poll->port->netdev);
 
@@ -705,7 +723,7 @@ pmd_info_show_rxq(struct ds *reply, struct 
dp_netdev_pmd_thread *pmd)
 ds_put_format(reply, " %d", netdev_rxq_get_queue_id(poll->rx));
 prev_name = name;
 }
-ovs_mutex_unlock(>poll_mutex);
+ovs_mutex_unlock(>port_mutex);
 ds_put_cstr(reply, "\n");
 }
 }
@@ -1078,6 +1096,11 @@ dp_netdev_reload_pmd__(struct dp_netdev_pmd_thread *pmd)
 int old_seq;
 
 if (pmd->core_id == NON_PMD_CORE_ID) {
+ovs_mutex_lock(>dp->non_pmd_mutex);
+ovs_mutex_lock(>port_mutex);
+pmd_load_cached_ports(pmd);
+ovs_mutex_unlock(>port_mutex);
+ovs_mutex_unlock(>dp->non_pmd_mutex);
 return;
 }
 
@@ -1200,9 +1223,7 @@ do_add_port(struct dp_netdev *dp, const char *devname, 
const char *type,
 
 cmap_insert(>ports, >node, hash_port_no(port_no));
 
-if (netdev_is_pmd(port->netdev)) {
-dp_netdev_add_port_to_pmds(dp, port);
-}
+dp_netdev_add_port_to_pmds(dp, port);
 seq_change(dp->port_seq);
 
 return 0;
@@ -1371,6 +1392,9 @@ do_del_port(struct dp_netdev *dp, struct dp_netdev_port 
*port)
 {
 cmap_remove(>ports, >node, hash_odp_port(port->port_no));
 seq_change(dp->port_seq);
+
+dp_netdev_del_port_from_all_pmds(dp, port);
+
 if (netdev_is_pmd(port->netdev)) {
 int numa_id = netdev_get_numa_id(port->netdev);
 
@@ -1380,8 +1404,6 @@ do_del_port(struct dp_netdev *dp,