[ovs-dev] [PATCH] netdev-offload: add offload-delay option to delay offload the datapath flows

wenxu at ucloud.cn wenxu at ucloud.cn
Mon Oct 12 08:48:40 UTC 2020


From: wenxu <wenxu at ucloud.cn>

Add offload-delay option to delay offload the datapath flow.
Sometimes there is no need for offload the short connection flows which
overload the add/del flows in the HW. It is better to offload persistent
connection.

enable it as following:
ovs-vsctl set Open_Vswitch . other-config:offload-delay=10000

Signed-off-by: wenxu <wenxu at ucloud.cn>
---
 lib/dpif-netlink.c            |  8 ++++++++
 lib/dpif.h                    |  4 +++-
 lib/netdev-offload.c          | 18 ++++++++++++++++++
 lib/netdev-offload.h          |  1 +
 ofproto/ofproto-dpif-upcall.c | 33 +++++++++++++++++++++++++++------
 vswitchd/vswitch.xml          | 21 +++++++++++++++++++++
 6 files changed, 78 insertions(+), 7 deletions(-)

diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c
index 2f881e4..094a015 100644
--- a/lib/dpif-netlink.c
+++ b/lib/dpif-netlink.c
@@ -2060,6 +2060,10 @@ parse_flow_put(struct dpif_netlink *dpif, struct dpif_flow_put *put)
         return EOPNOTSUPP;
     }
 
+    if (put->flags & DPIF_FP_NO_OFFLOAD) {
+        return EOPNOTSUPP;
+    }
+
     err = parse_key_and_mask_to_match(put->key, put->key_len, put->mask,
                                       put->mask_len, &match);
     if (err) {
@@ -2148,6 +2152,10 @@ parse_flow_put(struct dpif_netlink *dpif, struct dpif_flow_put *put)
                 (oor_netdev ? oor_netdev->name : dev->name));
     }
 
+    if (put->flags & DPIF_FP_TRY_OFFLOAD) {
+        return 0;
+    }
+
 out:
     if (err && err != EEXIST && (put->flags & DPIF_FP_MODIFY)) {
         /* Modified rule can't be offloaded, try and delete from HW */
diff --git a/lib/dpif.h b/lib/dpif.h
index 2d52f01..95d4693 100644
--- a/lib/dpif.h
+++ b/lib/dpif.h
@@ -529,7 +529,9 @@ enum dpif_flow_put_flags {
     DPIF_FP_CREATE = 1 << 0,    /* Allow creating a new flow. */
     DPIF_FP_MODIFY = 1 << 1,    /* Allow modifying an existing flow. */
     DPIF_FP_ZERO_STATS = 1 << 2, /* Zero the stats of an existing flow. */
-    DPIF_FP_PROBE = 1 << 3      /* Suppress error messages, if any. */
+    DPIF_FP_PROBE = 1 << 3,     /* Suppress error messages, if any. */
+    DPIF_FP_NO_OFFLOAD = 1 << 4,  /* Don't try send to netdev */
+    DPIF_FP_TRY_OFFLOAD = 1 << 5  /* Only try send to netdev */
 };
 
 bool dpif_probe_feature(struct dpif *, const char *name,
diff --git a/lib/netdev-offload.c b/lib/netdev-offload.c
index 2da3bc7..731141b 100644
--- a/lib/netdev-offload.c
+++ b/lib/netdev-offload.c
@@ -621,6 +621,7 @@ netdev_ifindex_to_odp_port(int ifindex)
 }
 
 static bool netdev_offload_rebalance_policy = false;
+static unsigned netdev_offload_delay = 0;
 
 bool
 netdev_is_offload_rebalance_policy_enabled(void)
@@ -628,6 +629,20 @@ netdev_is_offload_rebalance_policy_enabled(void)
     return netdev_offload_rebalance_policy;
 }
 
+unsigned
+netdev_is_offload_delay(void)
+{
+    return netdev_offload_delay;
+}
+
+static void
+netdev_set_offload_delay(unsigned delay)
+{
+    if (delay >= 10000 && delay <= 60000) {
+        netdev_offload_delay = delay;
+    }
+}
+
 static void
 netdev_ports_flow_init(void)
 {
@@ -660,6 +675,9 @@ netdev_set_flow_api_enabled(const struct smap *ovs_other_config)
                 netdev_offload_rebalance_policy = true;
             }
 
+            netdev_set_offload_delay(smap_get_int(ovs_other_config,
+                                                  "offload-delay", 0));
+
             netdev_ports_flow_init();
 
             ovsthread_once_done(&once);
diff --git a/lib/netdev-offload.h b/lib/netdev-offload.h
index 4c0ed2a..9d0dd00 100644
--- a/lib/netdev-offload.h
+++ b/lib/netdev-offload.h
@@ -103,6 +103,7 @@ bool netdev_any_oor(void);
 bool netdev_is_flow_api_enabled(void);
 void netdev_set_flow_api_enabled(const struct smap *ovs_other_config);
 bool netdev_is_offload_rebalance_policy_enabled(void);
+unsigned netdev_is_offload_delay(void);
 
 struct dpif_port;
 int netdev_ports_insert(struct netdev *, const char *dpif_type,
diff --git a/ofproto/ofproto-dpif-upcall.c b/ofproto/ofproto-dpif-upcall.c
index e022fde..e873dd7 100644
--- a/ofproto/ofproto-dpif-upcall.c
+++ b/ofproto/ofproto-dpif-upcall.c
@@ -310,6 +310,7 @@ struct udpif_key {
 
     uint32_t key_recirc_id;   /* Non-zero if reference is held by the ukey. */
     struct recirc_refs recircs;  /* Action recirc IDs with references held. */
+    bool try_offload;         /* Delay offload flags for flow */
 
 #define OFFL_REBAL_INTVL_MSEC  3000	/* dynamic offload rebalance freq */
     struct netdev *in_netdev;		/* in_odp_port's netdev */
@@ -1582,8 +1583,13 @@ handle_upcalls(struct udpif *udpif, struct upcall *upcalls,
             struct udpif_key *ukey = upcall->ukey;
 
             if (ukey_install(udpif, ukey)) {
+                enum dpif_flow_put_flags flags = DPIF_FP_CREATE;
+
                 upcall->ukey_persists = true;
-                put_op_init(&ops[n_ops++], ukey, DPIF_FP_CREATE);
+                if (netdev_is_offload_delay()) {
+                    flags |= DPIF_FP_NO_OFFLOAD;
+                }
+                put_op_init(&ops[n_ops++], ukey, flags);
             }
         }
 
@@ -1706,6 +1712,7 @@ ukey_create__(const struct nlattr *key, size_t key_len,
     ukey->stats.used = used;
     ukey->xcache = NULL;
 
+    ukey->try_offload = false;
     ukey->offloaded = false;
     ukey->in_netdev = NULL;
     ukey->flow_packets = ukey->flow_backlog_packets = 0;
@@ -2469,7 +2476,8 @@ log_unexpected_flow(const struct dpif_flow *flow, int error)
 static void
 reval_op_init(struct ukey_op *op, enum reval_result result,
               struct udpif *udpif, struct udpif_key *ukey,
-              struct recirc_refs *recircs, struct ofpbuf *odp_actions)
+              struct recirc_refs *recircs, struct ofpbuf *odp_actions,
+              enum dpif_flow_put_flags flags)
     OVS_REQUIRES(ukey->mutex)
 {
     if (result == UKEY_DELETE) {
@@ -2483,7 +2491,7 @@ reval_op_init(struct ukey_op *op, enum reval_result result,
         /* ukey->key_recirc_id remains, as the key is the same as before. */
 
         ukey_set_actions(ukey, odp_actions);
-        put_op_init(op, ukey, DPIF_FP_MODIFY);
+        put_op_init(op, ukey, DPIF_FP_MODIFY | flags);
     }
 }
 
@@ -2679,6 +2687,7 @@ revalidate(struct revalidator *revalidator)
             struct dpif_flow_stats stats = f->stats;
             enum reval_result result;
             struct udpif_key *ukey;
+            unsigned delay_offload;
             bool already_dumped;
             int error;
 
@@ -2737,10 +2746,22 @@ revalidate(struct revalidator *revalidator)
                 udpif_update_flow_pps(udpif, ukey, f);
             }
 
-            if (result != UKEY_KEEP) {
+            delay_offload = netdev_is_offload_delay();
+            if (delay_offload && result == UKEY_KEEP && !ukey->try_offload) {
+                if (used - ukey->created > delay_offload
+                    && now - used < 2000) {
+                    reval_op_init(&ops[n_ops++], UKEY_MODIFY, udpif,
+                                  ukey, &recircs,
+                                  ovsrcu_get(struct ofpbuf *, &ukey->actions),
+                                  DPIF_FP_TRY_OFFLOAD);
+                    ukey->try_offload = true;
+                    ukey->stats.n_packets = 0;
+                    ukey->stats.n_bytes = 0;
+                }
+            } else if (result != UKEY_KEEP) {
                 /* Takes ownership of 'recircs'. */
                 reval_op_init(&ops[n_ops++], result, udpif, ukey, &recircs,
-                              &odp_actions);
+                              &odp_actions, 0);
             }
             ovs_mutex_unlock(&ukey->mutex);
         }
@@ -2818,7 +2839,7 @@ revalidator_sweep__(struct revalidator *revalidator, bool purge)
                 if (result != UKEY_KEEP) {
                     /* Clears 'recircs' if filled by revalidate_ukey(). */
                     reval_op_init(&ops[n_ops++], result, udpif, ukey, &recircs,
-                                  &odp_actions);
+                                  &odp_actions, 0);
                 }
             }
             ovs_mutex_unlock(&ukey->mutex);
diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml
index 07da2ee..2dda283 100644
--- a/vswitchd/vswitch.xml
+++ b/vswitchd/vswitch.xml
@@ -649,6 +649,27 @@
             be set to 'skip_sw'.
         </p>
       </column>
+
+      <column name="other_config" key="offload-delay"
+              type='{"type": "integer",
+                     "minInteger": 10000, "maxInteger": 60000}'>
+        <p>
+            Configures HW offload delay, that allows delay some time to
+            offload the flows. This can be used to only offload flow of
+            persistent connection.
+        </p>
+        <p>
+          Set this value to <code>10000-60000</code> to enable this option.
+        </p>
+        <p>
+          The default value is <code>0</code>. Changing this value requires
+          restarting the daemon.
+        </p>
+        <p>
+            This is only relevant if HW offloading is enabled (hw-offload).
+            When this policy is enabled.
+        </p>
+      </column>
       <column name="other_config" key="pmd-auto-lb"
               type='{"type": "boolean"}'>
         <p>
-- 
1.8.3.1



More information about the dev mailing list