Add flow control API calls to the dummy offload provider, enabling
the re-addition of previously disabled partial offload tests.

Signed-off-by: Eelco Chaudron <[email protected]>
---
 lib/dpif-offload-dummy.c | 369 ++++++++++++++++++++++++++++++++++++---
 lib/dummy.h              |   6 +
 lib/netdev-dummy.c       |   4 +-
 tests/dpif-netdev.at     |  34 ++--
 4 files changed, 368 insertions(+), 45 deletions(-)

diff --git a/lib/dpif-offload-dummy.c b/lib/dpif-offload-dummy.c
index 32360737f..dbd76e7a5 100644
--- a/lib/dpif-offload-dummy.c
+++ b/lib/dpif-offload-dummy.c
@@ -22,10 +22,22 @@
 #include "dpif-offload.h"
 #include "dummy.h"
 #include "netdev-provider.h"
+#include "odp-util.h"
 #include "util.h"
+#include "uuid.h"
 
 #include "openvswitch/json.h"
+#include "openvswitch/match.h"
+#include "openvswitch/vlog.h"
 
+VLOG_DEFINE_THIS_MODULE(dpif_offload_dummy);
+
+struct dummy_offloaded_flow {
+    struct hmap_node node;
+    struct match match;
+    ovs_u128 ufid;
+    uint32_t mark;
+};
 
 struct dpif_offload_dummy {
     struct dpif_offload offload;
@@ -35,12 +47,47 @@ struct dpif_offload_dummy {
     struct ovsthread_once once_enable; /* Track first-time enablement. */
 };
 
+struct dpif_offload_dummy_port {
+    struct dpif_offload_port_mgr_port pm_port;
+
+    struct ovs_mutex port_mutex; /* Protect all below members. */
+    struct hmap offloaded_flows OVS_GUARDED;
+};
+
+static struct dpif_offload_dummy_port *
+dpif_offload_dummy_cast_port(struct dpif_offload_port_mgr_port *port)
+{
+    return CONTAINER_OF(port, struct dpif_offload_dummy_port, pm_port);
+}
+
 static struct dpif_offload_dummy *
 dpif_offload_dummy_cast(const struct dpif_offload *offload)
 {
     return CONTAINER_OF(offload, struct dpif_offload_dummy, offload);
 }
 
+static uint32_t
+dpif_offload_dummy_flow_hash(const ovs_u128 *ufid)
+{
+    return ufid->u32[0];
+}
+
+static struct dummy_offloaded_flow *
+dpif_offload_dummy_find_offloaded_flow(const struct hmap *offloaded_flows,
+                                       const ovs_u128 *ufid)
+{
+    uint32_t hash = dpif_offload_dummy_flow_hash(ufid);
+    struct dummy_offloaded_flow *data;
+
+    HMAP_FOR_EACH_WITH_HASH (data, node, hash, offloaded_flows) {
+        if (ovs_u128_equals(*ufid, data->ufid)) {
+            return data;
+        }
+    }
+
+    return NULL;
+}
+
 static void
 dpif_offload_dummy_enable_offload(struct dpif_offload *dpif_offload,
                                   struct dpif_offload_port_mgr_port *port)
@@ -56,24 +103,45 @@ dpif_offload_dummy_cleanup_offload(
     dpif_offload_set_netdev_offload(port->netdev, NULL);
 }
 
+
+static void
+dpif_offload_dummy_free_port(struct dpif_offload_dummy_port *port)
+{
+    struct dummy_offloaded_flow *off_flow;
+
+    ovs_mutex_lock(&port->port_mutex);
+    HMAP_FOR_EACH_POP (off_flow, node, &port->offloaded_flows) {
+        free(off_flow);
+    }
+    hmap_destroy(&port->offloaded_flows);
+    ovs_mutex_unlock(&port->port_mutex);
+    ovs_mutex_destroy(&port->port_mutex);
+    free(port);
+}
+
 static int
 dpif_offload_dummy_port_add(struct dpif_offload *dpif_offload,
                             struct netdev *netdev, odp_port_t port_no)
 {
-    struct dpif_offload_port_mgr_port *port = xmalloc(sizeof *port);
+    struct dpif_offload_dummy_port *port = xmalloc(sizeof *port);
     struct dpif_offload_dummy *offload_dummy;
 
+    ovs_mutex_init(&port->port_mutex);
+    ovs_mutex_lock(&port->port_mutex);
+    hmap_init(&port->offloaded_flows);
+    ovs_mutex_unlock(&port->port_mutex);
+
     offload_dummy = dpif_offload_dummy_cast(dpif_offload);
-    if (dpif_offload_port_mgr_add(offload_dummy->port_mgr, port, netdev,
-                                  port_no, false)) {
+    if (dpif_offload_port_mgr_add(offload_dummy->port_mgr, &port->pm_port,
+                                  netdev, port_no, false)) {
 
         if (dpif_offload_is_offload_enabled()) {
-            dpif_offload_dummy_enable_offload(dpif_offload, port);
+            dpif_offload_dummy_enable_offload(dpif_offload, &port->pm_port);
         }
         return 0;
     }
 
-    free(port);
+    dpif_offload_dummy_free_port(port);
     return EEXIST;
 }
 
@@ -89,11 +157,15 @@ dpif_offload_dummy_port_del(struct dpif_offload 
*dpif_offload,
     port = dpif_offload_port_mgr_remove(offload_dummy->port_mgr, port_no,
                                         true);
     if (port) {
+        struct dpif_offload_dummy_port *dummy_port;
+
+        dummy_port = dpif_offload_dummy_cast_port(port);
         if (dpif_offload_is_offload_enabled()) {
             dpif_offload_dummy_cleanup_offload(dpif_offload, port);
         }
         netdev_close(port->netdev);
-        ovsrcu_postpone(free, port);
+
+        ovsrcu_postpone(dpif_offload_dummy_free_port, dummy_port);
     }
     return 0;
 }
@@ -298,26 +370,273 @@ dpif_offload_dummy_can_offload(struct dpif_offload 
*dpif_offload OVS_UNUSED,
     return is_dummy_netdev_class(netdev->netdev_class) ? true : false;
 }
 
-#define DEFINE_DPIF_DUMMY_CLASS(NAME, TYPE_STR)                  \
-    struct dpif_offload_class NAME = {                           \
-        .type = TYPE_STR,                                        \
-        .impl_type = DPIF_OFFLOAD_IMPL_HW_ONLY,                  \
-        .supported_dpif_types = (const char *const[]) {          \
-            "dummy",                                             \
-            NULL},                                               \
-        .open = dpif_offload_dummy_open,                         \
-        .close = dpif_offload_dummy_close,                       \
-        .set_config = dpif_offload_dummy_set_config,             \
-        .get_debug = dpif_offload_dummy_get_debug,               \
-        .get_global_stats = dpif_offload_dummy_get_global_stats, \
-        .can_offload = dpif_offload_dummy_can_offload,           \
-        .port_add = dpif_offload_dummy_port_add,                 \
-        .port_del = dpif_offload_dummy_port_del,                 \
-        .port_dump_start = dpif_offload_dummy_port_dump_start,   \
-        .port_dump_next = dpif_offload_dummy_port_dump_next,     \
-        .port_dump_done = dpif_offload_dummy_port_dump_done,     \
-        .get_netdev = dpif_offload_dummy_get_netdev,             \
+static void
+dpif_offload_dummy_log_operation(const char *op, int error,
+                                 const ovs_u128 *ufid)
+{
+    VLOG_DBG("%s to %s netdev flow "UUID_FMT,
+             error == 0 ? "succeed" : "failed", op,
+             UUID_ARGS((struct uuid *) ufid));
+}
+
+static struct dpif_offload_dummy_port *
+dpif_offload_dummy_get_port_by_netdev(const struct dpif_offload *offload_,
+                                      struct netdev *netdev)
+{
+    struct dpif_offload_dummy *offload = dpif_offload_dummy_cast(offload_);
+    struct dpif_offload_port_mgr_port *port;
+
+    port = dpif_offload_port_mgr_find_by_netdev(offload->port_mgr, netdev);
+    if (!port) {
+        return NULL;
+    }
+    return dpif_offload_dummy_cast_port(port);
+}
+
+static int
+dpif_offload_dummy_netdev_flow_put(const struct dpif_offload *offload_,
+                                   struct netdev *netdev,
+                                   struct dpif_offload_flow_put *put,
+                                   uint32_t *flow_mark)
+{
+    struct dummy_offloaded_flow *off_flow;
+    struct dpif_offload_dummy_port *port;
+    bool modify = true;
+    int error = 0;
+
+    *flow_mark = INVALID_FLOW_MARK;
+
+    port = dpif_offload_dummy_get_port_by_netdev(offload_, netdev);
+    if (!port) {
+        error = ENODEV;
+        goto exit;
+    }
+
+    ovs_mutex_lock(&port->port_mutex);
+
+    off_flow = dpif_offload_dummy_find_offloaded_flow(&port->offloaded_flows,
+                                                      put->ufid);
+    if (!off_flow) {
+        /* Create new offloaded flow. */
+        uint32_t mark = dpif_offload_allocate_flow_mark();
+
+        if (mark == INVALID_FLOW_MARK) {
+            error = ENOSPC;
+            goto exit_unlock;
+        }
+
+        off_flow = xzalloc(sizeof *off_flow);
+        off_flow->mark = mark;
+        memcpy(&off_flow->ufid, put->ufid, sizeof *put->ufid);
+        hmap_insert(&port->offloaded_flows, &off_flow->node,
+                    dpif_offload_dummy_flow_hash(put->ufid));
+        modify = false;
+    }
+    memcpy(&off_flow->match, put->match, sizeof *put->match);
+
+    /* As we have per-netdev 'offloaded_flows', we don't need to match
+     * the 'in_port' for received packets.  This will also allow offloading
+     * for packets passed to 'receive' command without specifying the
+     * 'in_port'. */
+    off_flow->match.wc.masks.in_port.odp_port = 0;
+
+    if (VLOG_IS_DBG_ENABLED()) {
+        struct ds ds = DS_EMPTY_INITIALIZER;
+
+        ds_put_format(&ds, "%s: flow put[%s]: ", netdev_get_name(netdev),
+                      modify ? "modify" : "create");
+        odp_format_ufid(put->ufid, &ds);
+        ds_put_cstr(&ds, " flow match: ");
+        match_format(put->match, NULL, &ds, OFP_DEFAULT_PRIORITY);
+        ds_put_format(&ds, ", mark: %"PRIu32, off_flow->mark);
+
+        VLOG_DBG("%s", ds_cstr(&ds));
+        ds_destroy(&ds);
     }
 
+    *flow_mark = off_flow->mark;
+
+exit_unlock:
+    ovs_mutex_unlock(&port->port_mutex);
+
+exit:
+    if (put->stats) {
+        memset(put->stats, 0, sizeof *put->stats);
+    }
+
+    dpif_offload_dummy_log_operation(put->modify ? "modify" : "add", error,
+                                     put->ufid);
+    return error;
+}
+
+static int
+dpif_offload_dummy_netdev_flow_del(const struct dpif_offload *offload_,
+                                   struct netdev *netdev,
+                                   struct dpif_offload_flow_del *del,
+                                   uint32_t *flow_mark)
+{
+    struct dummy_offloaded_flow *off_flow;
+    struct dpif_offload_dummy_port *port;
+    uint32_t mark = INVALID_FLOW_MARK;
+    const char *error = NULL;
+
+    port = dpif_offload_dummy_get_port_by_netdev(offload_, netdev);
+    if (!port) {
+        error = "No such (net)device.";
+        goto exit;
+    }
+
+    ovs_mutex_lock(&port->port_mutex);
+
+    off_flow = dpif_offload_dummy_find_offloaded_flow(&port->offloaded_flows,
+                                                      del->ufid);
+    if (!off_flow) {
+        error = "No such flow.";
+        goto exit_unlock;
+    }
+
+    mark = off_flow->mark;
+    hmap_remove(&port->offloaded_flows, &off_flow->node);
+    free(off_flow);
+
+exit_unlock:
+    ovs_mutex_unlock(&port->port_mutex);
+
+exit:
+    if (error || VLOG_IS_DBG_ENABLED()) {
+        struct ds ds = DS_EMPTY_INITIALIZER;
+
+        ds_put_format(&ds, "%s: ", netdev_get_name(netdev));
+        if (error) {
+            ds_put_cstr(&ds, "failed to ");
+        }
+        ds_put_cstr(&ds, "flow del: ");
+        odp_format_ufid(del->ufid, &ds);
+        if (error) {
+            ds_put_format(&ds, " error: %s", error);
+        } else {
+            ds_put_format(&ds, " mark: %"PRIu32, mark);
+        }
+        VLOG(error ? VLL_WARN : VLL_DBG, "%s", ds_cstr(&ds));
+        ds_destroy(&ds);
+    }
+
+    if (del->stats) {
+        memset(del->stats, 0, sizeof *del->stats);
+    }
+
+    *flow_mark = mark;
+    dpif_offload_dummy_log_operation("delete", error ? -1 : 0, del->ufid);
+    return error ? ENOENT : 0;
+}
+
+static bool
+dpif_offload_dummy_netdev_flow_stats(const struct dpif_offload *offload_,
+                                     struct netdev *netdev,
+                                     const ovs_u128 *ufid,
+                                     struct dpif_flow_stats *stats,
+                                     struct dpif_flow_attrs *attrs)
+{
+    struct dummy_offloaded_flow *off_flow = NULL;
+    struct dpif_offload_dummy_port *port;
+
+    port = dpif_offload_dummy_get_port_by_netdev(offload_, netdev);
+    if (!port) {
+        return false;
+    }
+
+    ovs_mutex_lock(&port->port_mutex);
+    off_flow = dpif_offload_dummy_find_offloaded_flow(&port->offloaded_flows,
+                                                      ufid);
+    ovs_mutex_unlock(&port->port_mutex);
+
+    memset(stats, 0, sizeof *stats);
+    attrs->offloaded = off_flow ? true : false;
+    attrs->dp_layer = "tc";
+    attrs->dp_extra_info = NULL;
+
+    return off_flow ? true : false;
+}
+
+void
+dpif_offload_dummy_netdev_simulate_offload(struct netdev *netdev,
+                                           struct dp_packet *packet,
+                                           struct flow *flow)
+{
+    const struct dpif_offload *offload_ = ovsrcu_get(
+        const struct dpif_offload *, &netdev->dpif_offload);
+    struct dpif_offload_dummy_port *port;
+    struct dummy_offloaded_flow *data;
+    struct flow packet_flow;
+
+    if (!offload_ || strcmp(dpif_offload_class_type(offload_), "dummy")) {
+        return;
+    }
+
+    port = dpif_offload_dummy_get_port_by_netdev(offload_, netdev);
+    if (!port) {
+        return;
+    }
+
+    if (!flow) {
+        flow = &packet_flow;
+        flow_extract(packet, flow);
+    }
+
+    ovs_mutex_lock(&port->port_mutex);
+    HMAP_FOR_EACH (data, node, &port->offloaded_flows) {
+        if (flow_equal_except(flow, &data->match.flow, &data->match.wc)) {
+
+            dp_packet_set_flow_mark(packet, data->mark);
+
+            if (VLOG_IS_DBG_ENABLED()) {
+                struct ds ds = DS_EMPTY_INITIALIZER;
+
+                ds_put_format(&ds, "%s: packet: ",
+                              netdev_get_name(netdev));
+                /* 'flow' does not contain proper port number here.
+                 * Let's just clear it as it's wildcarded anyway. */
+                flow->in_port.ofp_port = 0;
+                flow_format(&ds, flow, NULL);
+
+                ds_put_cstr(&ds, " matches with flow: ");
+                odp_format_ufid(&data->ufid, &ds);
+                ds_put_cstr(&ds, " ");
+                match_format(&data->match, NULL, &ds, OFP_DEFAULT_PRIORITY);
+                ds_put_format(&ds, " with mark: %"PRIu32, data->mark);
+
+                VLOG_DBG("%s", ds_cstr(&ds));
+                ds_destroy(&ds);
+            }
+            break;
+        }
+    }
+    ovs_mutex_unlock(&port->port_mutex);
+}
+
+#define DEFINE_DPIF_DUMMY_CLASS(NAME, TYPE_STR)                    \
+    struct dpif_offload_class NAME = {                             \
+        .type = TYPE_STR,                                          \
+        .impl_type = DPIF_OFFLOAD_IMPL_HW_ONLY,                    \
+        .supported_dpif_types = (const char *const[]){             \
+            "dummy",                                               \
+            NULL},                                                 \
+        .open = dpif_offload_dummy_open,                           \
+        .close = dpif_offload_dummy_close,                         \
+        .set_config = dpif_offload_dummy_set_config,               \
+        .get_debug = dpif_offload_dummy_get_debug,                 \
+        .get_global_stats = dpif_offload_dummy_get_global_stats,   \
+        .can_offload = dpif_offload_dummy_can_offload,             \
+        .port_add = dpif_offload_dummy_port_add,                   \
+        .port_del = dpif_offload_dummy_port_del,                   \
+        .port_dump_start = dpif_offload_dummy_port_dump_start,     \
+        .port_dump_next = dpif_offload_dummy_port_dump_next,       \
+        .port_dump_done = dpif_offload_dummy_port_dump_done,       \
+        .get_netdev = dpif_offload_dummy_get_netdev,               \
+        .netdev_flow_put = dpif_offload_dummy_netdev_flow_put,     \
+        .netdev_flow_del = dpif_offload_dummy_netdev_flow_del,     \
+        .netdev_flow_stats = dpif_offload_dummy_netdev_flow_stats, \
+}
+
 DEFINE_DPIF_DUMMY_CLASS(dpif_offload_dummy_class, "dummy");
 DEFINE_DPIF_DUMMY_CLASS(dpif_offload_dummy_x_class, "dummy_x");
diff --git a/lib/dummy.h b/lib/dummy.h
index f0eb30ee2..266c200c3 100644
--- a/lib/dummy.h
+++ b/lib/dummy.h
@@ -20,6 +20,9 @@
 #include <stdbool.h>
 
 struct netdev_class;
+struct dp_packet;
+struct netdev;
+struct flow;
 
 /* Degree of dummy support.
  *
@@ -41,5 +44,8 @@ void netdev_dummy_register(enum dummy_level);
 void timeval_dummy_register(void);
 void ofpact_dummy_enable(void);
 bool is_dummy_netdev_class(const struct netdev_class *);
+void dpif_offload_dummy_netdev_simulate_offload(struct netdev *,
+                                                struct dp_packet *,
+                                                struct flow *);
 
 #endif /* dummy.h */
diff --git a/lib/netdev-dummy.c b/lib/netdev-dummy.c
index 6a99f4ced..b0eb27383 100644
--- a/lib/netdev-dummy.c
+++ b/lib/netdev-dummy.c
@@ -1808,7 +1808,7 @@ netdev_dummy_queue_packet__(struct netdev_rxq_dummy *rx, 
struct dp_packet *packe
 
 static void
 netdev_dummy_queue_packet(struct netdev_dummy *dummy, struct dp_packet *packet,
-                          struct flow *flow OVS_UNUSED, int queue_id)
+                          struct flow *flow, int queue_id)
     OVS_REQUIRES(dummy->mutex)
 {
     struct netdev_rxq_dummy *rx, *prev;
@@ -1817,6 +1817,8 @@ netdev_dummy_queue_packet(struct netdev_dummy *dummy, 
struct dp_packet *packet,
         ovs_pcap_write(dummy->rxq_pcap, packet);
     }
 
+    dpif_offload_dummy_netdev_simulate_offload(&dummy->up, packet, flow);
+
     prev = NULL;
     LIST_FOR_EACH (rx, node, &dummy->rxes) {
         if (rx->up.queue_id == queue_id &&
diff --git a/tests/dpif-netdev.at b/tests/dpif-netdev.at
index 839648d96..ee9d7dadd 100644
--- a/tests/dpif-netdev.at
+++ b/tests/dpif-netdev.at
@@ -37,15 +37,18 @@ filter_flow_install () {
 }
 
 filter_hw_flow_install () {
-    grep 'netdev_dummy.*flow put\[create\]' | sed 's/.*|DBG|//' | sort | uniq
+    grep 'dpif_offload_dummy.*flow put\[create\]' | sed 's/.*|DBG|//' \
+      | sed -E 's/mark: [0-9]+/mark: 1/' | sort | uniq
 }
 
 filter_hw_flow_del () {
-    grep 'netdev_dummy.*flow del' | sed 's/.*|DBG|//' | sort | uniq
+    grep 'dpif_offload_dummy.*flow del' | sed 's/.*|DBG|//' \
+      | sed -E 's/mark: [0-9]+/mark: 1/' | sort | uniq
 }
 
 filter_hw_packet_netdev_dummy () {
-    grep 'netdev_dummy.*: packet:.*with mark' | sed 's/.*|DBG|//' | sort | uniq
+    grep 'dpif_offload_dummy.*: packet:.*with mark' | sed 's/.*|DBG|//' \
+      | sed -E 's/mark: [0-9]+/mark: 1/' | sort | uniq
 }
 
 filter_flow_dump () {
@@ -411,7 +414,7 @@ m4_define([DPIF_NETDEV_FLOW_HW_OFFLOAD],
       set bridge br0 datapath-type=dummy \
                      other-config:datapath-id=1234 fail-mode=secure], [], [],
       [m4_if([$1], [dummy-pmd], [--dummy-numa="0,0,0,0,1,1,1,1"], [])])
-   AT_CHECK([ovs-appctl vlog/set dpif:file:dbg dpif_netdev:file:dbg 
netdev_dummy:file:dbg])
+   AT_CHECK([ovs-appctl vlog/set dpif:file:dbg dpif_netdev:file:dbg 
dpif_offload_dummy:file:dbg])
 
    AT_CHECK([ovs-vsctl set Open_vSwitch . other_config:hw-offload=true])
    OVS_WAIT_UNTIL([grep "hw-offload API Enabled" ovs-vswitchd.log])
@@ -462,11 +465,8 @@ p1: flow del: mark: 1
    OVS_VSWITCHD_STOP
    AT_CLEANUP])
 
-# XXX: Remove these tests for now as we do not have a dummy implementation
-#      to add flows. See netdev_offload_dummy. We will fix and re-add later.
-# DPIF_NETDEV_FLOW_HW_OFFLOAD([dummy])
-# DPIF_NETDEV_FLOW_HW_OFFLOAD([dummy-pmd])
-
+DPIF_NETDEV_FLOW_HW_OFFLOAD([dummy])
+DPIF_NETDEV_FLOW_HW_OFFLOAD([dummy-pmd])
 
 m4_define([DPIF_NETDEV_FLOW_HW_OFFLOAD_OFFSETS],
   [AT_SETUP([dpif-netdev - partial hw offload with packet modifications - $1])
@@ -476,7 +476,7 @@ m4_define([DPIF_NETDEV_FLOW_HW_OFFLOAD_OFFSETS],
       set bridge br0 datapath-type=dummy \
                      other-config:datapath-id=1234 fail-mode=secure], [], [],
       [m4_if([$1], [dummy-pmd], [--dummy-numa="0,0,0,0,1,1,1,1"], [])])
-   AT_CHECK([ovs-appctl vlog/set dpif:file:dbg dpif_netdev:file:dbg 
netdev_dummy:file:dbg])
+   AT_CHECK([ovs-appctl vlog/set dpif:file:dbg dpif_netdev:file:dbg 
dpif_offload_dummy:file:dbg])
 
    AT_CHECK([ovs-vsctl set Open_vSwitch . other_config:hw-offload=true])
    OVS_WAIT_UNTIL([grep "hw-offload API Enabled" ovs-vswitchd.log])
@@ -542,10 +542,8 @@ 
udp,in_port=ANY,dl_vlan=99,dl_vlan_pcp=7,vlan_tci1=0x0000,dl_src=00:06:07:08:09:
    OVS_VSWITCHD_STOP
    AT_CLEANUP])
 
-# XXX: Remove these tests for now as we do not have a dummy implementation
-#      to add flows. See netdev_offload_dummy. We will fix and re-add later.
-# DPIF_NETDEV_FLOW_HW_OFFLOAD_OFFSETS([dummy])
-# DPIF_NETDEV_FLOW_HW_OFFLOAD_OFFSETS([dummy-pmd])
+DPIF_NETDEV_FLOW_HW_OFFLOAD_OFFSETS([dummy])
+DPIF_NETDEV_FLOW_HW_OFFLOAD_OFFSETS([dummy-pmd])
 
 m4_define([DPIF_NETDEV_FLOW_HW_OFFLOAD_OFFSETS_VID_ARP],
   [AT_SETUP([dpif-netdev - partial hw offload with arp vlan id packet 
modifications - $1])
@@ -555,7 +553,7 @@ m4_define([DPIF_NETDEV_FLOW_HW_OFFLOAD_OFFSETS_VID_ARP],
       set bridge br0 datapath-type=dummy \
                      other-config:datapath-id=1234 fail-mode=secure], [], [],
       [m4_if([$1], [dummy-pmd], [--dummy-numa="0,0,0,0,1,1,1,1"], [])])
-   AT_CHECK([ovs-appctl vlog/set dpif:file:dbg dpif_netdev:file:dbg 
netdev_dummy:file:dbg])
+   AT_CHECK([ovs-appctl vlog/set dpif:file:dbg dpif_netdev:file:dbg 
dpif_offload_dummy:file:dbg])
 
    AT_CHECK([ovs-vsctl set Open_vSwitch . other_config:hw-offload=true])
    OVS_WAIT_UNTIL([grep "hw-offload API Enabled" ovs-vswitchd.log])
@@ -621,10 +619,8 @@ 
arp,in_port=ANY,dl_vlan=11,dl_vlan_pcp=7,vlan_tci1=0x0000,dl_src=00:06:07:08:09:
    OVS_VSWITCHD_STOP
    AT_CLEANUP])
 
-# XXX: Remove these tests for now as we do not have a dummy implementation
-#      to add flows. See netdev_offload_dummy. We will fix and re-add later.
-# DPIF_NETDEV_FLOW_HW_OFFLOAD_OFFSETS_VID_ARP([dummy])
-# DPIF_NETDEV_FLOW_HW_OFFLOAD_OFFSETS_VID_ARP([dummy-pmd])
+DPIF_NETDEV_FLOW_HW_OFFLOAD_OFFSETS_VID_ARP([dummy])
+DPIF_NETDEV_FLOW_HW_OFFLOAD_OFFSETS_VID_ARP([dummy-pmd])
 
 AT_SETUP([dpif-netdev - check dpctl/add-flow in_port exact match])
 OVS_VSWITCHD_START(
-- 
2.50.1

_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to