diff --git a/SOURCES/openvswitch-3.1.0.patch b/SOURCES/openvswitch-3.1.0.patch
index 74f371b..09ccf2c 100644
--- a/SOURCES/openvswitch-3.1.0.patch
+++ b/SOURCES/openvswitch-3.1.0.patch
@@ -417,7 +417,7 @@ index c576ae620..474344194 100644
 +    }
 +}
 diff --git a/lib/netdev-offload-tc.c b/lib/netdev-offload-tc.c
-index 4c78c4816..c38247423 100644
+index 4c78c4816..09f6393f8 100644
 --- a/lib/netdev-offload-tc.c
 +++ b/lib/netdev-offload-tc.c
 @@ -276,8 +276,9 @@ del_filter_and_ufid_mapping(struct tcf_id *id, const ovs_u128 *ufid,
@@ -431,7 +431,20 @@ index 4c78c4816..c38247423 100644
      }
      return err;
  }
-@@ -871,7 +872,7 @@ parse_tc_flower_to_actions__(struct tc_flower *flower, struct ofpbuf *buf,
+@@ -524,7 +525,11 @@ delete_chains_from_netdev(struct netdev *netdev, struct tcf_id *id)
+          */
+         HMAP_FOR_EACH_POP (chain_node, node, &map) {
+             id->chain = chain_node->chain;
+-            tc_del_flower_filter(id);
++            /* Delete empty chain doesn't seem to work with
++             * tc_del_flower_filter() so use tc_del_filter()
++             * without specifying TCA_KIND.
++             */
++            tc_del_filter(id, NULL);
+             free(chain_node);
+         }
+     }
+@@ -871,7 +876,7 @@ parse_tc_flower_to_actions__(struct tc_flower *flower, struct ofpbuf *buf,
                  outport =
                      netdev_ifindex_to_odp_port(action->out.ifindex_out);
                  if (!outport) {
@@ -440,7 +453,7 @@ index 4c78c4816..c38247423 100644
                  }
              }
              nl_msg_put_u32(buf, OVS_ACTION_ATTR_OUTPUT, odp_to_u32(outport));
-@@ -964,7 +965,7 @@ parse_tc_flower_to_actions__(struct tc_flower *flower, struct ofpbuf *buf,
+@@ -964,7 +969,7 @@ parse_tc_flower_to_actions__(struct tc_flower *flower, struct ofpbuf *buf,
              uint32_t meter_id;
  
              if (police_idx_lookup(action->police.index, &meter_id)) {
@@ -449,7 +462,7 @@ index 4c78c4816..c38247423 100644
              }
              nl_msg_put_u32(buf, OVS_ACTION_ATTR_METER, meter_id);
          }
-@@ -983,6 +984,9 @@ parse_tc_flower_to_actions__(struct tc_flower *flower, struct ofpbuf *buf,
+@@ -983,6 +988,9 @@ parse_tc_flower_to_actions__(struct tc_flower *flower, struct ofpbuf *buf,
                  buf, OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_GREATER);
              i = parse_tc_flower_to_actions__(flower, buf, i + 1,
                                               action->police.result_jump);
@@ -459,7 +472,7 @@ index 4c78c4816..c38247423 100644
              nl_msg_end_nested(buf, act_offset);
  
              act_offset = nl_msg_start_nested(
-@@ -994,6 +998,9 @@ parse_tc_flower_to_actions__(struct tc_flower *flower, struct ofpbuf *buf,
+@@ -994,6 +1002,9 @@ parse_tc_flower_to_actions__(struct tc_flower *flower, struct ofpbuf *buf,
              }
              if (jump != 0) {
                  i = parse_tc_flower_to_actions__(flower, buf, i, jump);
@@ -469,7 +482,7 @@ index 4c78c4816..c38247423 100644
              }
              nl_msg_end_nested(buf, act_offset);
  
-@@ -1013,11 +1020,11 @@ parse_tc_flower_to_actions__(struct tc_flower *flower, struct ofpbuf *buf,
+@@ -1013,11 +1024,11 @@ parse_tc_flower_to_actions__(struct tc_flower *flower, struct ofpbuf *buf,
      return i;
  }
  
@@ -483,7 +496,7 @@ index 4c78c4816..c38247423 100644
  }
  
  static int
-@@ -1030,9 +1037,10 @@ parse_tc_flower_to_match(const struct netdev *netdev,
+@@ -1030,9 +1041,10 @@ parse_tc_flower_to_match(const struct netdev *netdev,
                           struct ofpbuf *buf,
                           bool terse)
  {
@@ -495,7 +508,7 @@ index 4c78c4816..c38247423 100644
  
      if (terse) {
          return parse_tc_flower_terse_to_match(flower, match, stats, attrs);
-@@ -1229,7 +1237,10 @@ parse_tc_flower_to_match(const struct netdev *netdev,
+@@ -1229,7 +1241,10 @@ parse_tc_flower_to_match(const struct netdev *netdev,
      }
  
      act_off = nl_msg_start_nested(buf, OVS_FLOW_ATTR_ACTIONS);
@@ -507,7 +520,7 @@ index 4c78c4816..c38247423 100644
      nl_msg_end_nested(buf, act_off);
  
      *actions = ofpbuf_at_assert(buf, act_off, sizeof(struct nlattr));
-@@ -1272,8 +1283,8 @@ netdev_tc_flow_dump_next(struct netdev_flow_dump *dump,
+@@ -1272,8 +1287,8 @@ netdev_tc_flow_dump_next(struct netdev_flow_dump *dump,
              continue;
          }
  
@@ -518,7 +531,7 @@ index 4c78c4816..c38247423 100644
          } else if (!find_ufid(netdev, &id, ufid)) {
              continue;
          }
-@@ -2490,15 +2501,23 @@ netdev_tc_flow_get(struct netdev *netdev,
+@@ -2490,15 +2505,23 @@ netdev_tc_flow_get(struct netdev *netdev,
  
      err = tc_get_flower(&id, &flower);
      if (err) {
@@ -545,6 +558,18 @@ index 4c78c4816..c38247423 100644
  
      if (stats) {
          struct dpif_flow_stats adjust_stats;
+@@ -2860,8 +2883,9 @@ netdev_tc_init_flow_api(struct netdev *netdev)
+     error = tc_add_del_qdisc(ifindex, true, block_id, hook);
+ 
+     if (error && error != EEXIST) {
+-        VLOG_INFO("failed adding ingress qdisc required for offloading: %s",
+-                  ovs_strerror(error));
++        VLOG_INFO("failed adding ingress qdisc required for offloading "
++                  "on %s: %s",
++                  netdev_get_name(netdev), ovs_strerror(error));
+         return error;
+     }
+ 
 diff --git a/lib/netdev-windows.c b/lib/netdev-windows.c
 index 4ad45ffa1..3fad501e3 100644
 --- a/lib/netdev-windows.c
@@ -610,6 +635,21 @@ index 2d382f1e8..ac5d2c3d0 100644
          last_updated = now;
          cpu_cores = count_cpu_cores__();
      }
+diff --git a/lib/tc.c b/lib/tc.c
+index 4c07e2216..5c32c6f97 100644
+--- a/lib/tc.c
++++ b/lib/tc.c
+@@ -2354,7 +2354,9 @@ tc_del_filter(struct tcf_id *id, const char *kind)
+     struct ofpbuf request;
+ 
+     request_from_tcf_id(id, 0, RTM_DELTFILTER, NLM_F_ACK, &request);
+-    nl_msg_put_string(&request, TCA_KIND, kind);
++    if (kind) {
++        nl_msg_put_string(&request, TCA_KIND, kind);
++    }
+     return tc_transact(&request, NULL);
+ }
+ 
 diff --git a/ofproto/ofproto-dpif-ipfix.c b/ofproto/ofproto-dpif-ipfix.c
 index 742eed399..f13478a88 100644
 --- a/ofproto/ofproto-dpif-ipfix.c
diff --git a/SPECS/openvswitch3.1.spec b/SPECS/openvswitch3.1.spec
index 5a5823f..7f169f0 100644
--- a/SPECS/openvswitch3.1.spec
+++ b/SPECS/openvswitch3.1.spec
@@ -57,7 +57,7 @@ Summary: Open vSwitch
 Group: System Environment/Daemons daemon/database/utilities
 URL: http://www.openvswitch.org/
 Version: 3.1.0
-Release: 20%{?dist}
+Release: 21%{?dist}
 
 # Nearly all of openvswitch is ASL 2.0.  The bugtool is LGPLv2+, and the
 # lib/sflow*.[ch] files are SISSL
@@ -751,6 +751,12 @@ exit 0
 %endif
 
 %changelog
+* Fri Apr 28 2023 Open vSwitch CI <ovs-ci@redhat.com> - 3.1.0-21
+- Merging upstream branch-3.1 [RH git: 1bae2da8f7]
+    Commit list:
+    c6cb828870 tc: Fix cleaning chains.
+
+
 * Thu Apr 27 2023 Open vSwitch CI <ovs-ci@redhat.com> - 3.1.0-20
 - Merging upstream branch-3.1 [RH git: 107636a54b]
     Commit list: