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.

I've introduced a fix in patch 10("dpif-netdev: Fix
reconfigure_pmd_threads()."),
which fixes other similar problems in reconfigure_pmd_threads().

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

Reply via email to