diff mbox series

[ovs-dev,v6,6/8] dpif-netdev: Support partial offload of PUSH_VLAN action

Message ID 20200712192625.7359-7-sriharsha.basavapatna@broadcom.com
State New
Headers show
Series netdev datapath: Partial action offload | expand

Commit Message

Sriharsha Basavapatna July 12, 2020, 7:26 p.m. UTC
If the input-port is a vhost-user port and the action is PUSH_VLAN,
offload the action on the egress device if it is offload capable.

Signed-off-by: Sriharsha Basavapatna <sriharsha.basavapatna@broadcom.com>
---
 lib/dpif-netdev.c         | 32 ++++++++++++++++++++++++++--
 lib/dpif.c                |  2 +-
 lib/netdev-offload-dpdk.c | 44 +++++++++++++++++++++++----------------
 lib/odp-execute.c         | 25 ++++++++++++++++------
 lib/odp-execute.h         |  5 ++++-
 5 files changed, 80 insertions(+), 28 deletions(-)
diff mbox series

Patch

diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
index a0bb5d4e1..53f07fc44 100644
--- a/lib/dpif-netdev.c
+++ b/lib/dpif-netdev.c
@@ -114,6 +114,7 @@  COVERAGE_DEFINE(datapath_drop_invalid_bond);
 COVERAGE_DEFINE(datapath_drop_invalid_tnl_port);
 COVERAGE_DEFINE(datapath_drop_rx_invalid_packet);
 COVERAGE_DEFINE(datapath_skip_tunnel_push);
+COVERAGE_DEFINE(datapath_skip_vlan_push);
 
 /* Protects against changes to 'dp_netdevs'. */
 static struct ovs_mutex dp_netdev_mutex = OVS_MUTEX_INITIALIZER;
@@ -7521,6 +7522,19 @@  dp_execute_output_action(struct dp_netdev_pmd_thread *pmd,
     return true;
 }
 
+static bool
+dp_netdev_assist_cb(void *dp OVS_UNUSED, const struct nlattr *a)
+{
+    enum ovs_action_attr type = nl_attr_type(a);
+
+    switch (type) {
+    case OVS_ACTION_ATTR_PUSH_VLAN:
+        return true;
+    default:
+        return false;
+    }
+}
+
 static void
 dp_execute_lb_output_action(struct dp_netdev_pmd_thread *pmd,
                             struct dp_packet_batch *packets_,
@@ -7874,7 +7888,21 @@  dp_execute_cb(void *aux_, struct dp_packet_batch *packets_,
                             pmd->ctx.now);
         break;
 
-    case OVS_ACTION_ATTR_PUSH_VLAN:
+    case OVS_ACTION_ATTR_PUSH_VLAN: {
+        const struct ovs_action_push_vlan *vlan = nl_attr_get(a);
+        struct dp_packet *packet;
+
+        if (!dp_flow || !dp_flow->partial_actions_offloaded) {
+            DP_PACKET_BATCH_FOR_EACH (i, packet, packets_) {
+                eth_push_vlan(packet, vlan->vlan_tpid, vlan->vlan_tci);
+            }
+        } else {
+            packet_count = dp_packet_batch_size(packets_);
+            COVERAGE_ADD(datapath_skip_vlan_push, packet_count);
+        }
+        break;
+    }
+
     case OVS_ACTION_ATTR_POP_VLAN:
     case OVS_ACTION_ATTR_PUSH_MPLS:
     case OVS_ACTION_ATTR_POP_MPLS:
@@ -7909,7 +7937,7 @@  dp_netdev_execute_actions(struct dp_netdev_pmd_thread *pmd,
     struct dp_netdev_execute_aux aux = { pmd, flow, dp_flow };
 
     odp_execute_actions(&aux, packets, should_steal, actions,
-                        actions_len, dp_execute_cb);
+                        actions_len, dp_execute_cb, dp_netdev_assist_cb);
 }
 
 struct dp_netdev_ct_dump {
diff --git a/lib/dpif.c b/lib/dpif.c
index 7cac3a629..23c481f70 100644
--- a/lib/dpif.c
+++ b/lib/dpif.c
@@ -1294,7 +1294,7 @@  dpif_execute_with_help(struct dpif *dpif, struct dpif_execute *execute)
 
     dp_packet_batch_init_packet(&pb, execute->packet);
     odp_execute_actions(&aux, &pb, false, execute->actions,
-                        execute->actions_len, dpif_execute_helper_cb);
+                        execute->actions_len, dpif_execute_helper_cb, NULL);
     return aux.error;
 }
 
diff --git a/lib/netdev-offload-dpdk.c b/lib/netdev-offload-dpdk.c
index 78a71f84a..449333248 100644
--- a/lib/netdev-offload-dpdk.c
+++ b/lib/netdev-offload-dpdk.c
@@ -1622,15 +1622,18 @@  struct action_attr {
 };
 
 /*
- * Maxium number of actions to be parsed while selecting a flow for partial
- * action offload. This number is currently based on the minimum number of
- * attributes seen with the tunnel encap action (clone, tunnel_push, output).
- * This number includes output action to a single egress device (uplink) and
- * supports neither multiple clone() actions nor multiple output actions.
- * This number could change if and when we support other actions or
- * combinations of actions for partial offload.
+ * Maxium number of actions to be parsed while selecting a flow for egress
+ * partial action offload. This number is currently based on the minimum
+ * number of attributes seen with the tunnel encap action (clone, tunnel_push,
+ * output). This number includes output action to a single egress device
+ * (uplink) and supports neither multiple clone() actions nor multiple output
+ * actions.
  */
-#define MAX_ACTION_ATTRS    3 /* Max # action attributes supported */
+enum num_action_attr_egress {
+    VLAN_PUSH_ATTRS = 2,        /* vlan_push, output */
+    TUNNEL_PUSH_ATTRS = 3,      /* clone, tunnel_push, output */
+    MAX_ACTION_ATTRS_EGRESS = TUNNEL_PUSH_ATTRS
+};
 
 /*
  * This function parses the list of OVS "actions" of length "actions_len",
@@ -1690,7 +1693,7 @@  netdev_offload_dpdk_egress_partial(struct netdev *netdev, struct match *match,
                                    struct netdev **egress_netdev,
                                    odp_port_t *egress_port)
 {
-    struct action_attr attrs[MAX_ACTION_ATTRS];
+    struct action_attr attrs[MAX_ACTION_ATTRS_EGRESS];
     odp_port_t out_port = ODPP_NONE;
     struct netdev *out_netdev;
     int num_attrs = 0;
@@ -1702,27 +1705,32 @@  netdev_offload_dpdk_egress_partial(struct netdev *netdev, struct match *match,
         return false;
     }
 
-    rc = parse_nlattr_actions(actions, actions_len, attrs, MAX_ACTION_ATTRS,
-                              &num_attrs);
+    rc = parse_nlattr_actions(actions, actions_len, attrs,
+                              MAX_ACTION_ATTRS_EGRESS, &num_attrs);
     if (rc == E2BIG) {
         /* Action list too big; decline partial offload */
         return false;
     }
 
-    /* Number of attrs expected with tunnel encap action */
-    if (num_attrs < MAX_ACTION_ATTRS) {
+    /* Minimum number of attrs expected (push_vlan) */
+    if (num_attrs < VLAN_PUSH_ATTRS) {
         return false;
     }
 
-    /* Only support clone sub-actions for now, tnl-push specifically. */
-    if (attrs[0].type != OVS_ACTION_ATTR_CLONE ||
-        attrs[1].type != OVS_ACTION_ATTR_TUNNEL_PUSH ||
-        attrs[2].type != OVS_ACTION_ATTR_OUTPUT) {
+    /* Only support clone(tnl-push) or push_vlan actions for now. */
+    if (num_attrs == TUNNEL_PUSH_ATTRS &&
+        (attrs[0].type != OVS_ACTION_ATTR_CLONE ||
+         attrs[1].type != OVS_ACTION_ATTR_TUNNEL_PUSH ||
+         attrs[2].type != OVS_ACTION_ATTR_OUTPUT)) {
+        return false;
+    } else if (num_attrs == VLAN_PUSH_ATTRS &&
+               (attrs[0].type != OVS_ACTION_ATTR_PUSH_VLAN ||
+                attrs[1].type != OVS_ACTION_ATTR_OUTPUT)) {
         return false;
     }
 
     /* Egress partial-offload needs an output action at the end. */
-    out_port = nl_attr_get_odp_port(attrs[2].action);
+    out_port = nl_attr_get_odp_port(attrs[num_attrs - 1].action);
     if (out_port == ODPP_NONE) {
         return false;
     }
diff --git a/lib/odp-execute.c b/lib/odp-execute.c
index 6eeda2a61..bd3769034 100644
--- a/lib/odp-execute.c
+++ b/lib/odp-execute.c
@@ -716,7 +716,7 @@  odp_execute_sample(void *dp, struct dp_packet *packet, bool steal,
     }
     dp_packet_batch_init_packet(&pb, packet);
     odp_execute_actions(dp, &pb, true, nl_attr_get(subactions),
-                        nl_attr_get_size(subactions), dp_execute_action);
+                        nl_attr_get_size(subactions), dp_execute_action, NULL);
 }
 
 static void
@@ -734,11 +734,12 @@  odp_execute_clone(void *dp, struct dp_packet_batch *batch, bool steal,
         dp_packet_batch_clone(&clone_pkt_batch, batch);
         dp_packet_batch_reset_cutlen(batch);
         odp_execute_actions(dp, &clone_pkt_batch, true, nl_attr_get(actions),
-                        nl_attr_get_size(actions), dp_execute_action);
+                        nl_attr_get_size(actions), dp_execute_action, NULL);
     }
     else {
         odp_execute_actions(dp, batch, true, nl_attr_get(actions),
-                            nl_attr_get_size(actions), dp_execute_action);
+                            nl_attr_get_size(actions), dp_execute_action,
+                            NULL);
     }
 }
 
@@ -783,7 +784,7 @@  odp_execute_check_pkt_len(void *dp, struct dp_packet *packet, bool steal,
      * odp_execute_actions. */
     dp_packet_batch_init_packet(&pb, packet);
     odp_execute_actions(dp, &pb, true, nl_attr_get(a), nl_attr_get_size(a),
-                        dp_execute_action);
+                        dp_execute_action, NULL);
 }
 
 static bool
@@ -830,6 +831,16 @@  requires_datapath_assistance(const struct nlattr *a)
     return false;
 }
 
+static bool
+requires_datapath_class_assistance(void *dp, odp_dp_class_assistance_cb
+                                   dp_cl_assist_cb, const struct nlattr *a)
+{
+    if (!dp || !dp_cl_assist_cb) {
+        return false;
+    }
+    return dp_cl_assist_cb(dp, 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.
@@ -846,7 +857,8 @@  requires_datapath_assistance(const struct nlattr *a)
 void
 odp_execute_actions(void *dp, struct dp_packet_batch *batch, bool steal,
                     const struct nlattr *actions, size_t actions_len,
-                    odp_execute_cb dp_execute_action)
+                    odp_execute_cb dp_execute_action,
+                    odp_dp_class_assistance_cb dp_cl_assist_cb)
 {
     struct dp_packet *packet;
     const struct nlattr *a;
@@ -856,7 +868,8 @@  odp_execute_actions(void *dp, struct dp_packet_batch *batch, bool steal,
         int type = nl_attr_type(a);
         bool last_action = (left <= NLA_ALIGN(a->nla_len));
 
-        if (requires_datapath_assistance(a)) {
+        if (requires_datapath_assistance(a) ||
+            requires_datapath_class_assistance(dp, dp_cl_assist_cb, a)) {
             if (dp_execute_action) {
                 /* Allow 'dp_execute_action' to steal the packet data if we do
                  * not need it any more. */
diff --git a/lib/odp-execute.h b/lib/odp-execute.h
index a3578a575..92e035f0e 100644
--- a/lib/odp-execute.h
+++ b/lib/odp-execute.h
@@ -30,6 +30,8 @@  struct dp_packet_batch;
 
 typedef void (*odp_execute_cb)(void *dp, struct dp_packet_batch *batch,
                                const struct nlattr *action, bool should_steal);
+typedef bool (*odp_dp_class_assistance_cb)(void *dp,
+                                           const struct nlattr *action);
 
 /* 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
@@ -38,5 +40,6 @@  typedef void (*odp_execute_cb)(void *dp, struct dp_packet_batch *batch,
 void odp_execute_actions(void *dp, struct dp_packet_batch *batch,
                          bool steal,
                          const struct nlattr *actions, size_t actions_len,
-                         odp_execute_cb dp_execute_action);
+                         odp_execute_cb dp_execute_action,
+                         odp_dp_class_assistance_cb dp_cl_assist_cb);
 #endif