Re: [ovs-dev] [PATCH v7 08/16] dpif-netdev: Add pmd thread local port cache for transmission.
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.
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.
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.
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,