summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorIlya Maximets <i.maximets@samsung.com>2016-05-27 16:32:50 +0300
committerDaniele Di Proietto <diproiettod@vmware.com>2016-06-06 18:10:22 -0700
commitc673049c79aa9b79c4318f5092f373740a81c5be (patch)
treecf61a413a94db964d1ba83c1b454ebb3a931fa82 /lib
parentf9176a3a7f805b04f721ea9a88a48a5d2b881730 (diff)
downloadopenvswitch-c673049c79aa9b79c4318f5092f373740a81c5be.tar.gz
dpctl: Implement dpctl/flow-get for dpif-netdev.
Currently 'dpctl/flow-get' doesn't work for flows installed by PMD threads. Fix that by implementing search across all PMD threads. Will be returned flow from first PMD thread with match. Signed-off-by: Ilya Maximets <i.maximets@samsung.com> Signed-off-by: Daniele Di Proietto <diproiettod@vmware.com>
Diffstat (limited to 'lib')
-rw-r--r--lib/dpctl.c3
-rw-r--r--lib/dpif-netdev.c50
2 files changed, 37 insertions, 16 deletions
diff --git a/lib/dpctl.c b/lib/dpctl.c
index ffe702e73..b870e30fd 100644
--- a/lib/dpctl.c
+++ b/lib/dpctl.c
@@ -1089,8 +1089,7 @@ dpctl_get_flow(int argc, const char *argv[], struct dpctl_params *dpctl_p)
goto out;
}
- /* Does not work for DPDK, since do not know which 'pmd' to apply the
- * operation. So, just uses PMD_ID_NULL. */
+ /* In case of PMD will be returned flow from first PMD thread with match. */
error = dpif_flow_get(dpif, NULL, 0, &ufid, PMD_ID_NULL, &buf, &flow);
if (error) {
dpctl_error(dpctl_p, error, "getting flow");
diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
index 119e16916..61a939aca 100644
--- a/lib/dpif-netdev.c
+++ b/lib/dpif-netdev.c
@@ -2045,26 +2045,48 @@ dpif_netdev_flow_get(const struct dpif *dpif, const struct dpif_flow_get *get)
struct dp_netdev *dp = get_dp_netdev(dpif);
struct dp_netdev_flow *netdev_flow;
struct dp_netdev_pmd_thread *pmd;
- unsigned pmd_id = get->pmd_id == PMD_ID_NULL
- ? NON_PMD_CORE_ID : get->pmd_id;
- int error = 0;
+ struct hmapx to_find = HMAPX_INITIALIZER(&to_find);
+ struct hmapx_node *node;
+ int error = EINVAL;
- pmd = dp_netdev_get_pmd(dp, pmd_id);
- if (!pmd) {
- return EINVAL;
+ if (get->pmd_id == PMD_ID_NULL) {
+ CMAP_FOR_EACH (pmd, node, &dp->poll_threads) {
+ if (dp_netdev_pmd_try_ref(pmd) && !hmapx_add(&to_find, pmd)) {
+ dp_netdev_pmd_unref(pmd);
+ }
+ }
+ } else {
+ pmd = dp_netdev_get_pmd(dp, get->pmd_id);
+ if (!pmd) {
+ goto out;
+ }
+ hmapx_add(&to_find, pmd);
}
- netdev_flow = dp_netdev_pmd_find_flow(pmd, get->ufid, get->key,
- get->key_len);
- if (netdev_flow) {
- dp_netdev_flow_to_dpif_flow(netdev_flow, get->buffer, get->buffer,
- get->flow, false);
- } else {
- error = ENOENT;
+ if (!hmapx_count(&to_find)) {
+ goto out;
}
- dp_netdev_pmd_unref(pmd);
+ HMAPX_FOR_EACH (node, &to_find) {
+ pmd = (struct dp_netdev_pmd_thread *) node->data;
+ netdev_flow = dp_netdev_pmd_find_flow(pmd, get->ufid, get->key,
+ get->key_len);
+ if (netdev_flow) {
+ dp_netdev_flow_to_dpif_flow(netdev_flow, get->buffer, get->buffer,
+ get->flow, false);
+ error = 0;
+ break;
+ } else {
+ error = ENOENT;
+ }
+ }
+ HMAPX_FOR_EACH (node, &to_find) {
+ pmd = (struct dp_netdev_pmd_thread *) node->data;
+ dp_netdev_pmd_unref(pmd);
+ }
+out:
+ hmapx_destroy(&to_find);
return error;
}