@@ -2177,7 +2177,8 @@ parse_flow_put(struct dpif_netlink *dpif, struct dpif_flow_put *put)
VLOG_DBG("added flow");
} else if (err != EEXIST) {
- if (outdev && dev && (err == ENOSPC)) {
+ if (netdev_is_offload_rebalance_policy_enabled() && outdev &&
+ dev && (err == ENOSPC)) {
tunnel_netdev = flow_get_tunnel_netdev(&match.flow.tunnel);
if (tunnel_netdev) {
oor_netdev = tunnel_netdev;
@@ -2474,6 +2474,43 @@ netdev_free_custom_stats_counters(struct netdev_custom_stats *custom_stats)
#ifdef __linux__
+enum offload_rebalance_policy {
+ OFFLOAD_REBALANCE_POLICY_DISABLE,
+ OFFLOAD_REBALANCE_POLICY_PPS_RATE
+};
+
+static enum
+offload_rebalance_policy netdev_offload_rebalance_policy =
+ OFFLOAD_REBALANCE_POLICY_DISABLE;
+
+static void
+netdev_offload_rebalance_set_policy(const char *policy)
+{
+ if (!policy) {
+ return;
+ }
+
+ if (!strcmp(policy, "pps-rate")) {
+ netdev_offload_rebalance_policy = OFFLOAD_REBALANCE_POLICY_PPS_RATE;
+ } else if (!strcmp(policy, "disable")) {
+ netdev_offload_rebalance_policy = OFFLOAD_REBALANCE_POLICY_DISABLE;
+ } else {
+ VLOG_WARN("netdev: Invalid policy '%s'", policy);
+ return;
+ }
+
+ VLOG_INFO("netdev: Using policy '%s'", policy);
+}
+
+bool
+netdev_is_offload_rebalance_policy_enabled(void)
+{
+ if (netdev_offload_rebalance_policy == OFFLOAD_REBALANCE_POLICY_PPS_RATE) {
+ return true;
+ }
+ return false;
+}
+
static void
netdev_ports_flow_init(void)
{
@@ -2494,12 +2531,18 @@ netdev_set_flow_api_enabled(const struct smap *ovs_other_config)
if (ovsthread_once_start(&once)) {
netdev_flow_api_enabled = true;
+ const char *offl_rebal_policy = NULL;
VLOG_INFO("netdev: Flow API Enabled");
tc_set_policy(smap_get_def(ovs_other_config, "tc-policy",
TC_POLICY_DEFAULT));
+ offl_rebal_policy = smap_get_def(ovs_other_config,
+ "offload-rebalance",
+ OFFLOAD_REBALANCE_POLICY_DEFAULT);
+ netdev_offload_rebalance_set_policy(offl_rebal_policy);
+
netdev_ports_flow_init();
ovsthread_once_done(&once);
@@ -223,6 +223,8 @@ int netdev_init_flow_api(struct netdev *);
uint32_t netdev_get_block_id(struct netdev *);
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);
+#define OFFLOAD_REBALANCE_POLICY_DEFAULT "disable"
struct dpif_port;
int netdev_ports_insert(struct netdev *, const struct dpif_class *,
@@ -967,7 +967,9 @@ udpif_revalidator(void *arg)
dpif_flow_dump_destroy(udpif->dump);
seq_change(udpif->dump_seq);
- udpif_run_flow_rebalance(udpif);
+ if (netdev_is_offload_rebalance_policy_enabled()) {
+ udpif_run_flow_rebalance(udpif);
+ }
duration = MAX(time_msec() - start_time, 1);
udpif->dump_duration = duration;
@@ -2741,7 +2743,8 @@ revalidate(struct revalidator *revalidator)
}
ukey->dump_seq = dump_seq;
- if (result != UKEY_DELETE) {
+ if (netdev_is_offload_rebalance_policy_enabled() &&
+ result != UKEY_DELETE) {
udpif_update_flow_pps(udpif, ukey, f);
}
@@ -475,6 +475,28 @@
</p>
</column>
+ <column name="other_config" key="offload-rebalance"
+ type='{"type": "string"}'>
+ <p>
+ Configures HW offload rebalancing, that allows to dynamically
+ offload and un-offload flows while an offload-device is out of
+ resources (OOR). The value specifies the criteria used to
+ select flows for offloading. The default value of 'disable',
+ disables this policy. To enable packets-per-second rate based
+ offload policy, set the value to 'pps-rate'.
+ Options:
+ <code>disable</code> - No offload rebalancing
+ <code>pps-rate</code> - Packets-per-second rate based policy
+ </p>
+ <p>
+ This is only relevant if HW offloading is enabled (hw-offload).
+ When this policy is enabled, it also requires 'tc-policy' to
+ be set to 'skip_sw'.
+ </p>
+ <p>
+ The default value is <code>disable</code>.
+ </p>
+ </column>
</group>
<group title="Status">