From: wenxu <[email protected]> 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 <[email protected]> --- 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 _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
