From: wenxu <we...@ucloud.cn>

The tc modify flow put always delete the original flow first and
then add the new flow. If the modfiy flow put operation failed,
the flow put operation will change from modify to create if success
to delete the original flow in tc (which will be always failed with
ENOENT, the flow is already be deleted before add the new flow in tc).
Finally, the modify flow put will failed to add in kernel datapath.

Signed-off-by: wenxu <we...@ucloud.cn>
---
 lib/dpif-netlink.c       | 7 ++++++-
 lib/netdev-tc-offloads.c | 6 +++++-
 lib/netdev.h             | 3 +++
 3 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c
index ab04482..13f2fdc 100644
--- a/lib/dpif-netlink.c
+++ b/lib/dpif-netlink.c
@@ -2029,6 +2029,7 @@ parse_flow_put(struct dpif_netlink *dpif, struct 
dpif_flow_put *put)
 
     info.dpif_class = dpif_class;
     info.tp_dst_port = dst_port;
+    info.tc_modify_flow_deleted = false;
     err = netdev_flow_put(dev, &match,
                           CONST_CAST(struct nlattr *, put->actions),
                           put->actions_len,
@@ -2060,7 +2061,11 @@ parse_flow_put(struct dpif_netlink *dpif, struct 
dpif_flow_put *put)
 out:
     if (err && err != EEXIST && (put->flags & DPIF_FP_MODIFY)) {
         /* Modified rule can't be offloaded, try and delete from HW */
-        int del_err = netdev_flow_del(dev, put->ufid, put->stats);
+        int del_err = 0;
+
+        if (!info.tc_modify_flow_deleted) {
+            del_err = netdev_flow_del(dev, put->ufid, put->stats);
+        }
 
         if (!del_err) {
             /* Delete from hw success, so old flow was offloaded.
diff --git a/lib/netdev-tc-offloads.c b/lib/netdev-tc-offloads.c
index 13a5aa9..8d73a61 100644
--- a/lib/netdev-tc-offloads.c
+++ b/lib/netdev-tc-offloads.c
@@ -1042,8 +1042,12 @@ netdev_tc_flow_put(struct netdev *netdev, struct match 
*match,
 
     handle = get_ufid_tc_mapping(ufid, &prio, NULL);
     if (handle && prio) {
+        bool flow_deleted;
+
         VLOG_DBG_RL(&rl, "updating old handle: %d prio: %d", handle, prio);
-        del_filter_and_ufid_mapping(ifindex, prio, handle, ufid);
+        flow_deleted = !del_filter_and_ufid_mapping(ifindex, prio,
+                                                   handle, ufid);
+        info->tc_modify_flow_deleted = flow_deleted;
     }
 
     if (!prio) {
diff --git a/lib/netdev.h b/lib/netdev.h
index ff1b604..c8b38e5 100644
--- a/lib/netdev.h
+++ b/lib/netdev.h
@@ -188,6 +188,9 @@ void netdev_send_wait(struct netdev *, int qid);
 struct offload_info {
     const struct dpif_class *dpif_class;
     ovs_be16 tp_dst_port; /* Destination port for tunnel in SET action */
+
+    bool tc_modify_flow_deleted; /* Indicate the tc modify flow put success
+                                  * to delete the original flow. */
 };
 struct dpif_class;
 struct netdev_flow_dump;
-- 
1.8.3.1

_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to