> >Hi Mark, > >thanks for your comment, I replied inline > >On 24/03/2016 10:17, "Kavanagh, Mark B" <mark.b.kavan...@intel.com> wrote: > >>Hi Daniele, >> >>One comment inline. >> >>Cheers, >>Mark >> >>>-----Original Message----- >>>From: Daniele Di Proietto [mailto:diproiet...@vmware.com] >>>Sent: Wednesday, March 23, 2016 6:37 PM >>>To: dev@openvswitch.org >>>Cc: Ben Pfaff; Kavanagh, Mark B; Ilya Maximets; Daniele Di Proietto >>>Subject: [PATCH v5 08/12] dpif-netdev: Change pmd thread configuration >>>in dpif_netdev_run(). >>> >>>Signed-off-by: Daniele Di Proietto <diproiet...@vmware.com> >>>Tested-by: Ilya Maximets <i.maxim...@samsung.com> >>>Acked-by: Ilya Maximets <i.maxim...@samsung.com> >>>--- >>> lib/dpif-netdev.c | 140 >>>++++++++++++++++++++++++++++++---------------------- >>> lib/dpif-provider.h | 3 +- >>> 2 files changed, 83 insertions(+), 60 deletions(-) >>> >>>diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c >>>index 66c0b19..6aaeaeb 100644 >>>--- a/lib/dpif-netdev.c >>>+++ b/lib/dpif-netdev.c >>>@@ -223,7 +223,9 @@ struct dp_netdev { >>> ovsthread_key_t per_pmd_key; >>> >>> /* Cpu mask for pin of pmd threads. */ >>>+ char *requested_pmd_cmask; >>> char *pmd_cmask; >>>+ >>> uint64_t last_tnl_conf_seq; >>> }; >>> >>>@@ -2447,82 +2449,44 @@ dpif_netdev_operate(struct dpif *dpif, struct >>>dpif_op **ops, size_t >>>n_ops) >>> } >>> } >>> >>>-/* Returns true if the configuration for rx queues or cpu mask >>>- * is changed. */ >>>+/* Returns true if the configuration for rx queues is changed. */ >>> static bool >>>-pmd_config_changed(const struct dp_netdev *dp, const char *cmask) >>>+pmd_n_rxq_changed(const struct dp_netdev *dp) >>> { >>> struct dp_netdev_port *port; >>> >>> CMAP_FOR_EACH (port, node, &dp->ports) { >>>- struct netdev *netdev = port->netdev; >>>- int requested_n_rxq = netdev_requested_n_rxq(netdev); >>>- if (netdev_is_pmd(netdev) >>>+ int requested_n_rxq = netdev_requested_n_rxq(port->netdev); >>>+ >>>+ if (netdev_is_pmd(port->netdev) >>> && port->latest_requested_n_rxq != requested_n_rxq) { >>> return true; >>> } >>> } >>> >>>- if (dp->pmd_cmask != NULL && cmask != NULL) { >>>- return strcmp(dp->pmd_cmask, cmask); >>>- } else { >>>- return (dp->pmd_cmask != NULL || cmask != NULL); >>>+ return false; >>>+} >>>+ >>>+static bool >>>+cmask_equals(const char *a, const char *b) >>>+{ >>>+ if (a && b) { >>>+ return !strcmp(a, b); >>> } >>>+ >>>+ return a == NULL && b == NULL; >>> } >>> >>>-/* Resets pmd threads if the configuration for 'rxq's or cpu mask >>>changes. */ >>>+/* Changes the number or the affinity of pmd threads. The changes are >>>actually >>>+ * applied in dpif_netdev_run(). */ >>> static int >>> dpif_netdev_pmd_set(struct dpif *dpif, const char *cmask) >>> { >>> struct dp_netdev *dp = get_dp_netdev(dpif); >>> >>>- if (pmd_config_changed(dp, cmask)) { >>>- struct dp_netdev_port *port; >>>- >>>- dp_netdev_destroy_all_pmds(dp); >>>- >>>- CMAP_FOR_EACH (port, node, &dp->ports) { >>>- struct netdev *netdev = port->netdev; >>>- int requested_n_rxq = netdev_requested_n_rxq(netdev); >>>- if (netdev_is_pmd(port->netdev) >>>- && port->latest_requested_n_rxq != requested_n_rxq) { >>>- int i, err; >>>- >>>- /* Closes the existing 'rxq's. */ >>>- for (i = 0; i < netdev_n_rxq(port->netdev); i++) { >>>- netdev_rxq_close(port->rxq[i]); >>>- port->rxq[i] = NULL; >>>- } >>>- port->n_rxq = 0; >>>- >>>- /* Sets the new rx queue config. */ >>>- err = netdev_set_multiq(port->netdev, >>>- ovs_numa_get_n_cores() + 1, >>>- requested_n_rxq); >>>- if (err && (err != EOPNOTSUPP)) { >>>- VLOG_ERR("Failed to set dpdk interface %s rx_queue >>>to:" >>>- " %u", netdev_get_name(port->netdev), >>>- requested_n_rxq); >>>- return err; >>>- } >>>- port->latest_requested_n_rxq = requested_n_rxq; >>>- /* If the set_multiq() above succeeds, reopens the >>>'rxq's. */ >>>- port->n_rxq = netdev_n_rxq(port->netdev); >>>- port->rxq = xrealloc(port->rxq, sizeof *port->rxq * >>>port->n_rxq); >>>- for (i = 0; i < port->n_rxq; i++) { >>>- netdev_rxq_open(port->netdev, &port->rxq[i], i); >>>- } >>>- } >>>- } >>>- /* Reconfigures the cpu mask. */ >>>- ovs_numa_set_cpu_mask(cmask); >>>- free(dp->pmd_cmask); >>>- dp->pmd_cmask = cmask ? xstrdup(cmask) : NULL; >>>- >>>- /* Restores the non-pmd. */ >>>- dp_netdev_set_nonpmd(dp); >>>- /* Restores all pmd threads. */ >>>- dp_netdev_reset_pmd_threads(dp); >>>+ if (!cmask_equals(dp->requested_pmd_cmask, cmask)) { >>>+ free(dp->requested_pmd_cmask); >>>+ dp->requested_pmd_cmask = cmask ? xstrdup(cmask) : NULL; >>> } >>> >>> return 0; >>>@@ -2622,6 +2586,58 @@ dp_netdev_process_rxq_port(struct >>>dp_netdev_pmd_thread *pmd, >>> } >>> } >>> >>>+static void >>>+reconfigure_pmd_threads(struct dp_netdev *dp) >>>+{ >>>+ struct dp_netdev_port *port; >>>+ >>>+ dp_netdev_destroy_all_pmds(dp); >>>+ >>>+ CMAP_FOR_EACH (port, node, &dp->ports) { >>>+ struct netdev *netdev = port->netdev; >>>+ int requested_n_rxq = netdev_requested_n_rxq(netdev); >>>+ if (netdev_is_pmd(port->netdev) >>>+ && port->latest_requested_n_rxq != requested_n_rxq) { >>>+ int i, err; >>>+ >>>+ /* Closes the existing 'rxq's. */ >>>+ for (i = 0; i < port->n_rxq; i++) { >>>+ netdev_rxq_close(port->rxq[i]); >>>+ port->rxq[i] = NULL; >>>+ } >>>+ port->n_rxq = 0; >>>+ >>>+ /* Sets the new rx queue config. */ >>>+ err = netdev_set_multiq(port->netdev, >>>ovs_numa_get_n_cores() + 1, >>>+ requested_n_rxq); >>>+ if (err && (err != EOPNOTSUPP)) { >>>+ VLOG_ERR("Failed to set dpdk interface %s rx_queue to: >>>%u", >>>+ netdev_get_name(port->netdev), >>>+ requested_n_rxq); >>>+ return; >>>+ } >>>+ port->latest_requested_n_rxq = requested_n_rxq; >>>+ /* If the set_multiq() above succeeds, reopens the 'rxq's. >>>*/ >>>+ port->n_rxq = netdev_n_rxq(port->netdev); >>>+ port->rxq = xrealloc(port->rxq, sizeof *port->rxq * >>>port->n_rxq); >>>+ for (i = 0; i < port->n_rxq; i++) { >>>+ netdev_rxq_open(port->netdev, &port->rxq[i], i); >> >>What happens if this fails? i.e. if port->rxq[i] is NULL? >> >>Presumably this could lead to a segfault later on when attempting to >>reference the queue's 'queue_id' field? > >That's true, we have to check the return value, even though it is unlikely >to fail. > >The problem is not introduced by this patch, but it is also on current >master.
Yup - I noticed it while reviewing v5 of your patch, and thought to mention it, seeing as you're working in this general area :) > >I've introduced a fix in patch 10("dpif-netdev: Fix >reconfigure_pmd_threads()."), >which fixes other similar problems in reconfigure_pmd_threads(). > Awesome - thanks! >Thanks for spotting this! > >> >>>+ } >>>+ } >>>+ } >>>+ /* Reconfigures the cpu mask. */ >>>+ ovs_numa_set_cpu_mask(dp->requested_pmd_cmask); >>>+ free(dp->pmd_cmask); >>>+ dp->pmd_cmask = dp->requested_pmd_cmask >>>+ ? xstrdup(dp->requested_pmd_cmask) >>>+ : NULL; >>>+ >>>+ /* Restores the non-pmd. */ >>>+ dp_netdev_set_nonpmd(dp); >>>+ /* Restores all pmd threads. */ >>>+ dp_netdev_reset_pmd_threads(dp); >>>+} >>>+ >>> /* Return true if needs to revalidate datapath flows. */ >>> static bool >>> dpif_netdev_run(struct dpif *dpif) >>>@@ -2642,8 +2658,14 @@ dpif_netdev_run(struct dpif *dpif) >>> } >>> } >>> } >>>- ovs_mutex_unlock(&dp->non_pmd_mutex); >>>+ >>> dp_netdev_pmd_unref(non_pmd); >>>+ ovs_mutex_unlock(&dp->non_pmd_mutex); >>>+ >>>+ if (!cmask_equals(dp->pmd_cmask, dp->requested_pmd_cmask) >>>+ || pmd_n_rxq_changed(dp)) { >>>+ reconfigure_pmd_threads(dp); >>>+ } >>> >>> tnl_neigh_cache_run(); >>> tnl_port_map_run(); >>>diff --git a/lib/dpif-provider.h b/lib/dpif-provider.h >>>index fbd370f..25f4280 100644 >>>--- a/lib/dpif-provider.h >>>+++ b/lib/dpif-provider.h >>>@@ -319,7 +319,8 @@ struct dpif_class { >>> >>> /* If 'dpif' creates its own I/O polling threads, refreshes poll >>>threads >>> * configuration. 'cmask' configures the cpu mask for setting the >>>polling >>>- * threads' cpu affinity. */ >>>+ * threads' cpu affinity. The implementation might postpone >>>applying the >>>+ * changes until run() is called. */ >>> int (*poll_threads_set)(struct dpif *dpif, const char *cmask); >>> >>> /* Translates OpenFlow queue ID 'queue_id' (in host byte order) >>>into a >>>-- >>>2.1.4 >> _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev