j = 0;
 #endif
 
+               if (tc_skip_sw(n->flags)) {
+                       n = rcu_dereference_bh(n->next);
+                       goto next_knode;
+               }
+
 #ifdef CONFIG_CLS_U32_MARK
                if ((skb->mark & n->mask) != n->val) {
                        n = rcu_dereference_bh(n->next);
        }
 }
 
-static void u32_replace_hw_hnode(struct tcf_proto *tp,
+static int u32_replace_hw_hnode(struct tcf_proto *tp,
                                 struct tc_u_hnode *h,
                                 u32 flags)
 {
        struct net_device *dev = tp->q->dev_queue->dev;
        struct tc_cls_u32_offload u32_offload = {0};
        struct tc_to_netdev offload;
+       int err;
 
        offload.type = TC_SETUP_CLSU32;
        offload.cls_u32 = &u32_offload;
                offload.cls_u32->hnode.handle = h->handle;
                offload.cls_u32->hnode.prio = h->prio;
 
-               dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle,
-                                             tp->protocol, &offload);
+               err = dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle,
+                                                   tp->protocol, &offload);
+               if (tc_skip_sw(flags))
+                       return err;
        }
+
+       return 0;
 }
 
 static void u32_clear_hw_hnode(struct tcf_proto *tp, struct tc_u_hnode *h)
        }
 }
 
-static void u32_replace_hw_knode(struct tcf_proto *tp,
+static int u32_replace_hw_knode(struct tcf_proto *tp,
                                 struct tc_u_knode *n,
                                 u32 flags)
 {
        struct net_device *dev = tp->q->dev_queue->dev;
        struct tc_cls_u32_offload u32_offload = {0};
        struct tc_to_netdev offload;
+       int err;
 
        offload.type = TC_SETUP_CLSU32;
        offload.cls_u32 = &u32_offload;
                if (n->ht_down)
                        offload.cls_u32->knode.link_handle = n->ht_down->handle;
 
-               dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle,
-                                             tp->protocol, &offload);
+               err = dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle,
+                                                   tp->protocol, &offload);
+               if (tc_skip_sw(flags))
+                       return err;
        }
+
+       return 0;
 }
 
 static void u32_clear_hnode(struct tcf_proto *tp, struct tc_u_hnode *ht)
        if (err < 0)
                return err;
 
-       if (tb[TCA_U32_FLAGS])
+       if (tb[TCA_U32_FLAGS]) {
                flags = nla_get_u32(tb[TCA_U32_FLAGS]);
+               if (!tc_flags_valid(flags))
+                       return err;
+       }
 
        n = (struct tc_u_knode *)*arg;
        if (n) {
                        return err;
                }
 
+               err = u32_replace_hw_knode(tp, new, flags);
+               if (err) {
+                       u32_destroy_key(tp, new, false);
+                       return err;
+               }
+
                u32_replace_knode(tp, tp_c, new);
                tcf_unbind_filter(tp, &n->res);
                call_rcu(&n->rcu, u32_delete_key_rcu);
-               u32_replace_hw_knode(tp, new, flags);
                return 0;
        }
 
                struct tc_u_knode __rcu **ins;
                struct tc_u_knode *pins;
 
+               err = u32_replace_hw_knode(tp, n, flags);
+               if (err)
+                       goto errhw;
+
                ins = &ht->ht[TC_U32_HASH(handle)];
                for (pins = rtnl_dereference(*ins); pins;
                     ins = &pins->next, pins = rtnl_dereference(*ins))
 
                RCU_INIT_POINTER(n->next, pins);
                rcu_assign_pointer(*ins, n);
-               u32_replace_hw_knode(tp, n, flags);
                *arg = (unsigned long)n;
                return 0;
        }
 
+errhw:
 #ifdef CONFIG_CLS_U32_MARK
        free_percpu(n->pcpu_success);
 errout: