@@ -2038,6 +2038,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.tunnel_csum_on = csum_on;
+ info.tc_modify_flow_deleted = false;
err = netdev_flow_put(dev, &match,
CONST_CAST(struct nlattr *, put->actions),
put->actions_len,
@@ -2088,7 +2089,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.
@@ -1359,9 +1359,12 @@ netdev_tc_flow_put(struct netdev *netdev, struct match *match,
block_id = get_block_id_from_netdev(netdev);
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, block_id, ufid,
- hook);
+ flow_deleted = !del_filter_and_ufid_mapping(ifindex, prio, handle,
+ block_id, ufid, hook);
+ info->tc_modify_flow_deleted = flow_deleted;
}
if (!prio) {
@@ -71,6 +71,9 @@ struct offload_info {
* it will be in the pkt meta data.
*/
uint32_t flow_mark;
+
+ bool tc_modify_flow_deleted; /* Indicate the tc modify flow put success
+ * to delete the original flow. */
};
int netdev_flow_flush(struct netdev *);