@@ -23,6 +23,7 @@
#include "dpif-netdev.h"
#include "dpif-netdev-perf.h"
#include "dpif-netdev-private.h"
+#include "dpif-offload.h"
#include <errno.h>
#include <immintrin.h>
@@ -110,7 +111,7 @@ dp_netdev_input_outer_avx512(struct dp_netdev_pmd_thread *pmd,
in_port);
/* Check if EMC or SMC are enabled. */
struct dfc_cache *cache = &pmd->flow_cache;
- const uint32_t hwol_enabled = netdev_is_flow_api_enabled();
+ const uint32_t hwol_enabled = dpif_offload_is_offload_enabled();
const uint32_t emc_enabled = pmd->ctx.emc_insert_min != 0;
const uint32_t smc_enabled = pmd->ctx.smc_enable_db;
@@ -18,6 +18,7 @@
#include "dpif-netdev.h"
#include "dpif-netdev-private.h"
#include "dpif-netdev-private-dfc.h"
+#include "dpif-offload.h"
#include <ctype.h>
#include <errno.h>
@@ -2993,7 +2994,7 @@ queue_netdev_flow_del(struct dp_netdev_pmd_thread *pmd,
{
struct dp_offload_thread_item *offload;
- if (!netdev_is_flow_api_enabled()) {
+ if (!dpif_offload_is_offload_enabled()) {
return;
}
@@ -3077,7 +3078,7 @@ queue_netdev_flow_put(struct dp_netdev_pmd_thread *pmd,
struct dp_offload_thread_item *item;
struct dp_offload_flow_item *flow_offload;
- if (!netdev_is_flow_api_enabled()) {
+ if (!dpif_offload_is_offload_enabled()) {
return;
}
@@ -3171,7 +3172,7 @@ dp_netdev_offload_flush(struct dp_netdev *dp,
static struct ovs_barrier barrier OVS_GUARDED_BY(flush_mutex);
struct netdev *netdev;
- if (!netdev_is_flow_api_enabled()) {
+ if (!dpif_offload_is_offload_enabled()) {
return;
}
@@ -3700,7 +3701,7 @@ dpif_netdev_get_flow_offload_status(const struct dp_netdev *dp,
int ret = 0;
- if (!netdev_is_flow_api_enabled()) {
+ if (!dpif_offload_is_offload_enabled()) {
return false;
}
@@ -4769,7 +4770,7 @@ dpif_netdev_offload_stats_get(struct dpif *dpif,
unsigned int tid;
size_t i;
- if (!netdev_is_flow_api_enabled()) {
+ if (!dpif_offload_is_offload_enabled()) {
return EINVAL;
}
@@ -8516,7 +8517,7 @@ dfc_processing(struct dp_netdev_pmd_thread *pmd,
size_t *n_flows, uint8_t *index_map,
bool md_is_valid, odp_port_t port_no)
{
- const bool netdev_flow_api = netdev_is_flow_api_enabled();
+ const bool netdev_flow_api = dpif_offload_is_offload_enabled();
const uint32_t recirc_depth = *recirc_depth_get();
const size_t cnt = dp_packet_batch_size(packets_);
size_t n_missed = 0, n_emc_hit = 0, n_phwol_hit = 0;
@@ -34,6 +34,7 @@
#include "bitmap.h"
#include "dpif-netlink-rtnl.h"
+#include "dpif-offload.h"
#include "dpif-provider.h"
#include "fat-rwlock.h"
#include "flow.h"
@@ -1316,7 +1317,7 @@ dpif_netlink_flow_flush(struct dpif *dpif_)
flow.cmd = OVS_FLOW_CMD_DEL;
flow.dp_ifindex = dpif->dp_ifindex;
- if (netdev_is_flow_api_enabled()) {
+ if (dpif_offload_is_offload_enabled()) {
netdev_ports_flow_flush(dpif_type_str);
}
@@ -2323,7 +2324,8 @@ parse_flow_put(struct dpif_netlink *dpif, struct dpif_flow_put *put)
} else if (err != EEXIST) {
struct netdev *oor_netdev = NULL;
enum vlog_level level;
- if (err == ENOSPC && netdev_is_offload_rebalance_policy_enabled()) {
+ if (err == ENOSPC
+ && dpif_offload_is_offload_rebalance_policy_enabled()) {
/*
* We need to set OOR on the input netdev (i.e, 'dev') for the
* flow. But if the flow has a tunnel attribute (i.e, decap action,
@@ -2442,12 +2444,14 @@ dpif_netlink_operate(struct dpif *dpif_, struct dpif_op **ops, size_t n_ops,
int i = 0;
int err = 0;
- if (offload_type == DPIF_OFFLOAD_ALWAYS && !netdev_is_flow_api_enabled()) {
+ if (offload_type == DPIF_OFFLOAD_ALWAYS
+ && !dpif_offload_is_offload_enabled()) {
VLOG_DBG("Invalid offload_type: %d", offload_type);
return;
}
- if (offload_type != DPIF_OFFLOAD_NEVER && netdev_is_flow_api_enabled()) {
+ if (offload_type != DPIF_OFFLOAD_NEVER
+ && dpif_offload_is_offload_enabled()) {
while (n_ops > 0) {
count = 0;
@@ -4237,7 +4241,7 @@ dpif_netlink_meter_set(struct dpif *dpif_, ofproto_meter_id meter_id,
}
err = dpif_netlink_meter_set__(dpif_, meter_id, config);
- if (!err && netdev_is_flow_api_enabled()) {
+ if (!err && dpif_offload_is_offload_enabled()) {
meter_offload_set(meter_id, config);
}
@@ -4344,7 +4348,7 @@ dpif_netlink_meter_get(const struct dpif *dpif, ofproto_meter_id meter_id,
err = dpif_netlink_meter_get_stats(dpif, meter_id, stats, max_bands,
OVS_METER_CMD_GET);
- if (!err && netdev_is_flow_api_enabled()) {
+ if (!err && dpif_offload_is_offload_enabled()) {
meter_offload_get(meter_id, stats);
}
@@ -4359,7 +4363,7 @@ dpif_netlink_meter_del(struct dpif *dpif, ofproto_meter_id meter_id,
err = dpif_netlink_meter_get_stats(dpif, meter_id, stats,
max_bands, OVS_METER_CMD_DEL);
- if (!err && netdev_is_flow_api_enabled()) {
+ if (!err && dpif_offload_is_offload_enabled()) {
meter_offload_del(meter_id, stats);
}
@@ -50,6 +50,8 @@ static const struct dpif_offload_class *base_dpif_offload_classes[] = {
};
static char *dpif_offload_provider_priority_list = "tc,dpdk,dummy,dummy_x";
+static atomic_bool dpif_offload_global_enabled = false;
+static atomic_bool dpif_offload_rebalance_policy = false;
static int
dpif_offload_register_provider__(const struct dpif_offload_class *class)
@@ -370,6 +372,24 @@ dpif_offload_class_type(const struct dpif_offload *offload)
return offload->class->type;
}
+bool
+dpif_offload_is_offload_enabled(void)
+{
+ bool enabled;
+
+ atomic_read_relaxed(&dpif_offload_global_enabled, &enabled);
+ return enabled;
+}
+
+bool
+dpif_offload_is_offload_rebalance_policy_enabled(void)
+{
+ bool enabled;
+
+ atomic_read_relaxed(&dpif_offload_rebalance_policy, &enabled);
+ return enabled;
+}
+
void
dpif_offload_dump_start(struct dpif_offload_dump *dump,
const struct dpif *dpif)
@@ -481,4 +501,23 @@ dpif_offload_set_global_cfg(const struct smap *other_cfg)
"restart required");
}
}
+
+ /* Handle other global configuration settings.
+ *
+ * According to the manual the 'hw-offload' parameter requires a restart
+ * when changed. In practice this is only needed on disable, as it will
+ * not actually disable hw-offload when requested. */
+ if (smap_get_bool(other_cfg, "hw-offload", false)) {
+ static struct ovsthread_once once_enable = OVSTHREAD_ONCE_INITIALIZER;
+
+ if (ovsthread_once_start(&once_enable)) {
+ atomic_store_relaxed(&dpif_offload_global_enabled, true);
+
+ if (smap_get_bool(other_cfg, "offload-rebalance", false)) {
+ atomic_store_relaxed(&dpif_offload_rebalance_policy, true);
+ }
+
+ ovsthread_once_done(&once_enable);
+ }
+ }
}
@@ -33,6 +33,8 @@ struct dpif_offload_dump {
/* Global functions. */
void dpif_offload_set_global_cfg(const struct smap *other_cfg);
+bool dpif_offload_is_offload_enabled(void);
+bool dpif_offload_is_offload_rebalance_policy_enabled(void);
/* Per dpif specific functions. */
@@ -1344,7 +1344,8 @@ void
dpif_operate(struct dpif *dpif, struct dpif_op **ops, size_t n_ops,
enum dpif_offload_type offload_type)
{
- if (offload_type == DPIF_OFFLOAD_ALWAYS && !netdev_is_flow_api_enabled()) {
+ if (offload_type == DPIF_OFFLOAD_ALWAYS
+ && !dpif_offload_is_offload_enabled()) {
size_t i;
for (i = 0; i < n_ops; i++) {
struct dpif_op *op = ops[i];
@@ -1932,7 +1933,7 @@ bool
dpif_may_support_explicit_drop_action(const struct dpif *dpif)
{
/* TC does not support offloading this action. */
- return dpif_is_netdev(dpif) || !netdev_is_flow_api_enabled();
+ return dpif_is_netdev(dpif) || !dpif_offload_is_offload_enabled();
}
bool
@@ -47,6 +47,7 @@
#include "dirs.h"
#include "dp-packet.h"
#include "dpdk.h"
+#include "dpif-offload.h"
#include "dpif-netdev.h"
#include "fatal-signal.h"
#include "if-notifier.h"
@@ -1315,7 +1316,7 @@ dpdk_eth_dev_init(struct netdev_dpdk *dev)
RTE_ETH_RX_OFFLOAD_TCP_CKSUM |
RTE_ETH_RX_OFFLOAD_IPV4_CKSUM;
- if (netdev_is_flow_api_enabled()) {
+ if (dpif_offload_is_offload_enabled()) {
/*
* Full tunnel offload requires that tunnel ID metadata be
* delivered with "miss" packets from the hardware to the
@@ -2268,7 +2269,7 @@ dpdk_set_rx_steer_config(struct netdev *netdev, struct netdev_dpdk *dev,
flags = 0;
}
- if (flags && netdev_is_flow_api_enabled()) {
+ if (flags && dpif_offload_is_offload_enabled()) {
VLOG_WARN_BUF(errp, "%s: options:rx-steering "
"is incompatible with hw-offload",
netdev_get_name(netdev));
@@ -52,6 +52,7 @@
#include "dp-packet.h"
#include "dpif-netlink.h"
#include "dpif-netdev.h"
+#include "dpif-offload.h"
#include "openvswitch/dynamic-string.h"
#include "fatal-signal.h"
#include "hash.h"
@@ -3065,7 +3066,7 @@ netdev_linux_set_policing(struct netdev *netdev_, uint32_t kbits_rate,
COVERAGE_INC(netdev_set_policing);
/* Use matchall for policing when offloadling ovs with tc-flower. */
- if (netdev_is_flow_api_enabled()) {
+ if (dpif_offload_is_offload_enabled()) {
error = tc_del_matchall_policer(netdev_);
if (kbits_rate || kpkts_rate) {
error = tc_add_matchall_policer(netdev_, kbits_rate, kbits_burst,
@@ -29,6 +29,7 @@
#include "cmap.h"
#include "coverage.h"
#include "dpif.h"
+#include "dpif-offload.h"
#include "dp-packet.h"
#include "openvswitch/dynamic-string.h"
#include "fatal-signal.h"
@@ -59,7 +60,6 @@ VLOG_DEFINE_THIS_MODULE(netdev_offload);
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
-static bool netdev_flow_api_enabled = false;
#define DEFAULT_OFFLOAD_THREAD_NB 1
#define MAX_OFFLOAD_THREAD_NB 10
@@ -389,7 +389,7 @@ netdev_flow_get_n_flows(struct netdev *netdev, uint64_t *n_flows)
int
netdev_init_flow_api(struct netdev *netdev)
{
- if (!netdev_is_flow_api_enabled()) {
+ if (!dpif_offload_is_offload_enabled()) {
return EOPNOTSUPP;
}
@@ -527,12 +527,6 @@ netdev_any_oor(void)
return oor;
}
-bool
-netdev_is_flow_api_enabled(void)
-{
- return netdev_flow_api_enabled;
-}
-
unsigned int
netdev_offload_thread_nb(void)
{
@@ -846,14 +840,6 @@ netdev_ifindex_to_odp_port(int ifindex)
return ret;
}
-static bool netdev_offload_rebalance_policy = false;
-
-bool
-netdev_is_offload_rebalance_policy_enabled(void)
-{
- return netdev_offload_rebalance_policy;
-}
-
static void
netdev_ports_flow_init(void)
{
@@ -869,11 +855,10 @@ netdev_ports_flow_init(void)
void
netdev_set_flow_api_enabled(const struct smap *ovs_other_config)
{
- if (smap_get_bool(ovs_other_config, "hw-offload", false)) {
+ if (dpif_offload_is_offload_enabled()) {
static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER;
if (ovsthread_once_start(&once)) {
- netdev_flow_api_enabled = true;
offload_thread_nb = smap_get_ullong(ovs_other_config,
"n-offload-threads",
@@ -897,11 +882,6 @@ netdev_set_flow_api_enabled(const struct smap *ovs_other_config)
tc_set_policy(smap_get_def(ovs_other_config, "tc-policy",
TC_POLICY_DEFAULT));
#endif
-
- if (smap_get_bool(ovs_other_config, "offload-rebalance", false)) {
- netdev_offload_rebalance_policy = true;
- }
-
netdev_ports_flow_init();
ovsthread_once_done(&once);
@@ -123,9 +123,7 @@ uint32_t netdev_get_block_id(struct netdev *);
int netdev_get_hw_info(struct netdev *, int);
void netdev_set_hw_info(struct netdev *, int, int);
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);
int netdev_flow_get_n_flows(struct netdev *netdev, uint64_t *n_flows);
struct dpif_port;
@@ -24,6 +24,7 @@
#include "cmap.h"
#include "lib/dpif-provider.h"
#include "dpif.h"
+#include "dpif-offload.h"
#include "openvswitch/dynamic-string.h"
#include "fail-open.h"
#include "guarded-list.h"
@@ -1070,7 +1071,7 @@ udpif_revalidator(void *arg)
dpif_flow_dump_destroy(udpif->dump);
seq_change(udpif->dump_seq);
- if (netdev_is_offload_rebalance_policy_enabled()) {
+ if (dpif_offload_is_offload_rebalance_policy_enabled()) {
udpif_run_flow_rebalance(udpif);
}
@@ -2963,7 +2964,7 @@ revalidate(struct revalidator *revalidator)
}
ukey->dump_seq = dump_seq;
- if (netdev_is_offload_rebalance_policy_enabled() &&
+ if (dpif_offload_is_offload_rebalance_policy_enabled() &&
result != UKEY_DELETE) {
udpif_update_flow_pps(udpif, ukey, f);
}
@@ -6756,6 +6756,9 @@ ofproto_unixctl_dpif_offload_show(struct unixctl_conn *conn,
struct json *backers = json_object_create();
const struct shash_node *backer;
+ json_object_put(backers, "enabled",
+ json_boolean_create(dpif_offload_is_offload_enabled()));
+
SHASH_FOR_EACH (backer, &all_dpif_backers) {
dpif_offload_show_backer_json(backers, backer->data);
}
@@ -6764,6 +6767,9 @@ ofproto_unixctl_dpif_offload_show(struct unixctl_conn *conn,
const struct shash_node **backers = shash_sort(&all_dpif_backers);
struct ds ds = DS_EMPTY_INITIALIZER;
+ ds_put_format(&ds, "Globally enabled: %s\nDatapaths:\n",
+ dpif_offload_is_offload_enabled() ? "true" : "false");
+
for (int i = 0; i < shash_count(&all_dpif_backers); i++) {
dpif_offload_show_backer_text(backers[i]->data, &ds);
}
@@ -10080,6 +10080,8 @@ AT_KEYWORDS([dpif-offload])
OVS_VSWITCHD_START([add-br br1 -- set bridge br1 datapath-type=dummy])
AT_CHECK([ovs-appctl dpif/offload/show], [0], [dnl
+Globally enabled: false
+Datapaths:
dummy@ovs-dummy:
dummy
dummy_x
@@ -10090,7 +10092,8 @@ AT_CHECK([ovs-appctl --format json --pretty dpif/offload/show], [0], [dnl
"dummy@ovs-dummy": {
"providers": [[
"dummy",
- "dummy_x"]]}}
+ "dummy_x"]]},
+ "enabled": false}
])
OVS_VSWITCHD_STOP
@@ -10115,6 +10118,8 @@ OVS_VSWITCHD_START([add-br br1 -- set bridge br1 datapath-type=dummy], [], [],
[], [-- set Open_vSwitch . other_config:hw-offload-priority=dummy_x,dummy])
AT_CHECK([ovs-appctl dpif/offload/show], [0], [dnl
+Globally enabled: false
+Datapaths:
dummy@ovs-dummy:
dummy_x
dummy
@@ -10125,7 +10130,8 @@ AT_CHECK([ovs-appctl --format json --pretty dpif/offload/show], [0], [dnl
"dummy@ovs-dummy": {
"providers": [[
"dummy_x",
- "dummy"]]}}
+ "dummy"]]},
+ "enabled": false}
])
OVS_TRAFFIC_VSWITCHD_STOP
@@ -950,12 +950,15 @@ OVS_DPDK_START([--no-pci])
AT_CHECK([ovs-vsctl add-br br0 -- set bridge br0 datapath_type=netdev])
AT_CHECK([ovs-appctl dpif/offload/show], [0], [dnl
+Globally enabled: false
+Datapaths:
netdev@ovs-netdev:
dpdk
])
AT_CHECK([ovs-appctl --format json --pretty dpif/offload/show], [0], [dnl
{
+ "enabled": false,
"netdev@ovs-netdev": {
"providers": [[
"dpdk"]]}}
@@ -1173,12 +1173,15 @@ OVS_TRAFFIC_VSWITCHD_START([], [],
[-- set Open_vSwitch . other_config:hw-offload=true])
AT_CHECK([ovs-appctl dpif/offload/show], [0], [dnl
+Globally enabled: true
+Datapaths:
system@ovs-system:
tc
])
AT_CHECK([ovs-appctl --format json --pretty dpif/offload/show], [0], [dnl
{
+ "enabled": true,
"system@ovs-system": {
"providers": [[
"tc"]]}}
We will initially move them to global functions/variables, and later patches will integrate them into the offload provider framework. Signed-off-by: Eelco Chaudron <echaudro@redhat.com> --- lib/dpif-netdev-avx512.c | 3 ++- lib/dpif-netdev.c | 13 ++++++----- lib/dpif-netlink.c | 18 +++++++++------ lib/dpif-offload.c | 39 ++++++++++++++++++++++++++++++++ lib/dpif-offload.h | 2 ++ lib/dpif.c | 5 ++-- lib/netdev-dpdk.c | 5 ++-- lib/netdev-linux.c | 3 ++- lib/netdev-offload.c | 26 +++------------------ lib/netdev-offload.h | 2 -- ofproto/ofproto-dpif-upcall.c | 5 ++-- ofproto/ofproto-dpif.c | 6 +++++ tests/ofproto-dpif.at | 10 ++++++-- tests/system-dpdk.at | 3 +++ tests/system-offloads-traffic.at | 3 +++ 15 files changed, 95 insertions(+), 48 deletions(-)