Add proper action verification in dpif-netdev and remove
psample verification according to dpif name.

Signed-off-by: Roi Dayan <r...@nvidia.com>
Reviewed-by: Eli Britstein <el...@nvidia.com>
---

Notes:
    v2
    - Fix dpif-netdev checking all actions supported instead of only the first.
    - Refactor dpif-netdev action support to return true for actions
      implemented and query odp-execute for support of the other
      actions not requiring datapath support.

 lib/dpif-netdev.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++
 lib/odp-execute.c |  6 ++++
 lib/odp-execute.h |  2 ++
 3 files changed, 87 insertions(+)

diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
index 87d69c46d5e0..5bb48f2e5c0c 100644
--- a/lib/dpif-netdev.c
+++ b/lib/dpif-netdev.c
@@ -4307,6 +4307,78 @@ exit:
     return error;
 }
 
+static bool
+dpif_netdev_actions_supported(const struct nlattr *actions, size_t actions_len)
+{
+    const struct nlattr *nla;
+    size_t left;
+
+    if (!actions_len) {
+        return true;
+    }
+
+    NL_ATTR_FOR_EACH (nla, left, actions, actions_len) {
+        enum ovs_action_attr type = nl_attr_type(nla);
+
+        switch (type) {
+        /* Supported actions go here in order of definition. */
+        case OVS_ACTION_ATTR_OUTPUT:
+        case OVS_ACTION_ATTR_LB_OUTPUT:
+        case OVS_ACTION_ATTR_TUNNEL_PUSH:
+        case OVS_ACTION_ATTR_TUNNEL_POP:
+        case OVS_ACTION_ATTR_USERSPACE:
+        case OVS_ACTION_ATTR_RECIRC:
+        case OVS_ACTION_ATTR_CT:
+        case OVS_ACTION_ATTR_METER:
+            if (nla->nla_type & NLA_F_NESTED &&
+                !dpif_netdev_actions_supported(nl_attr_get(nla),
+                                               nl_attr_get_size(nla))) {
+                return false;
+            }
+            break;
+            ;;
+        case OVS_ACTION_ATTR_SET:
+        case OVS_ACTION_ATTR_PUSH_VLAN:
+        case OVS_ACTION_ATTR_POP_VLAN:
+        case OVS_ACTION_ATTR_SAMPLE:
+        case OVS_ACTION_ATTR_HASH:
+        case OVS_ACTION_ATTR_PUSH_MPLS:
+        case OVS_ACTION_ATTR_POP_MPLS:
+        case OVS_ACTION_ATTR_SET_MASKED:
+        case OVS_ACTION_ATTR_TRUNC:
+        case OVS_ACTION_ATTR_PUSH_ETH:
+        case OVS_ACTION_ATTR_POP_ETH:
+        case OVS_ACTION_ATTR_CT_CLEAR:
+        case OVS_ACTION_ATTR_PUSH_NSH:
+        case OVS_ACTION_ATTR_POP_NSH:
+        case OVS_ACTION_ATTR_CLONE:
+        case OVS_ACTION_ATTR_CHECK_PKT_LEN:
+        case OVS_ACTION_ATTR_ADD_MPLS:
+        case OVS_ACTION_ATTR_DEC_TTL:
+        case OVS_ACTION_ATTR_DROP:
+            if (!odp_execute_without_datapath_assistance(nla)) {
+                return false;
+            }
+
+            if (nla->nla_type & NLA_F_NESTED &&
+                !dpif_netdev_actions_supported(nl_attr_get(nla),
+                                               nl_attr_get_size(nla))) {
+                return false;
+            }
+            break;
+
+        /* Unsupported actions go here in order of definition. */
+        case OVS_ACTION_ATTR_PSAMPLE:
+            return false;
+
+        case OVS_ACTION_ATTR_UNSPEC:
+        case __OVS_ACTION_ATTR_MAX:
+            OVS_NOT_REACHED();
+        }
+    }
+    return true;
+}
+
 static int
 dpif_netdev_flow_put(struct dpif *dpif, const struct dpif_flow_put *put)
 {
@@ -4367,6 +4439,13 @@ dpif_netdev_flow_put(struct dpif *dpif, const struct 
dpif_flow_put *put)
      * address mask. Installation of the flow will use the match variable. */
     netdev_flow_key_init(&key, &match.flow);
 
+    /* For probe operations, verify if the individual actions are supported.
+     * Otherwise, assume the higher layer, ofproto, manages action support. */
+    if (probe && !dpif_netdev_actions_supported(put->actions,
+                                                put->actions_len)) {
+        return EINVAL;
+    }
+
     if (put->pmd_id == PMD_ID_NULL) {
         if (cmap_count(&dp->poll_threads) == 0) {
             return EINVAL;
diff --git a/lib/odp-execute.c b/lib/odp-execute.c
index 15577d5394fa..cd29ed572bd4 100644
--- a/lib/odp-execute.c
+++ b/lib/odp-execute.c
@@ -995,6 +995,12 @@ odp_execute_init(void)
     }
 }
 
+bool
+odp_execute_without_datapath_assistance(const struct nlattr *a)
+{
+    return !requires_datapath_assistance(a);
+}
+
 /* Executes all of the 'actions_len' bytes of datapath actions in 'actions' on
  * the packets in 'batch'.  If 'steal' is true, possibly modifies and
  * definitely free the packets in 'batch', otherwise leaves 'batch' unchanged.
diff --git a/lib/odp-execute.h b/lib/odp-execute.h
index 2ba1ec5d2a1c..8e145e80c51c 100644
--- a/lib/odp-execute.h
+++ b/lib/odp-execute.h
@@ -38,6 +38,8 @@ typedef void (*odp_execute_action_cb)(struct dp_packet_batch 
*batch,
 typedef void (*odp_execute_cb)(void *dp, struct dp_packet_batch *batch,
                                const struct nlattr *action, bool should_steal);
 
+bool odp_execute_without_datapath_assistance(const struct nlattr *a);
+
 /* Actions that need to be executed in the context of a datapath are handed
  * to 'dp_execute_action', if non-NULL.  Currently this is called only for
  * actions OVS_ACTION_ATTR_OUTPUT and OVS_ACTION_ATTR_USERSPACE so
-- 
2.21.0

_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to