int tcf_exts_validate(struct net *net, struct tcf_proto *tp,
                      struct nlattr **tb, struct nlattr *rate_tlv,
-                     struct tcf_exts *exts, bool ovr);
+                     struct tcf_exts *exts, bool ovr,
+                     struct netlink_ext_ack *extack);
 void tcf_exts_destroy(struct tcf_exts *exts);
 void tcf_exts_change(struct tcf_exts *dst, struct tcf_exts *src);
 int tcf_exts_dump(struct sk_buff *skb, struct tcf_exts *exts);
 
 EXPORT_SYMBOL(tcf_exts_destroy);
 
 int tcf_exts_validate(struct net *net, struct tcf_proto *tp, struct nlattr **tb,
-                     struct nlattr *rate_tlv, struct tcf_exts *exts, bool ovr)
+                     struct nlattr *rate_tlv, struct tcf_exts *exts, bool ovr,
+                     struct netlink_ext_ack *extack)
 {
 #ifdef CONFIG_NET_CLS_ACT
        {
        }
 #else
        if ((exts->action && tb[exts->action]) ||
-           (exts->police && tb[exts->police]))
+           (exts->police && tb[exts->police])) {
+               NL_SET_ERR_MSG(extack, "Classifier actions are not supported per compile options (CONFIG_NET_CLS_ACT)");
                return -EOPNOTSUPP;
+       }
 #endif
 
        return 0;
 
 static int basic_set_parms(struct net *net, struct tcf_proto *tp,
                           struct basic_filter *f, unsigned long base,
                           struct nlattr **tb,
-                          struct nlattr *est, bool ovr)
+                          struct nlattr *est, bool ovr,
+                          struct netlink_ext_ack *extack)
 {
        int err;
 
-       err = tcf_exts_validate(net, tp, tb, est, &f->exts, ovr);
+       err = tcf_exts_validate(net, tp, tb, est, &f->exts, ovr, extack);
        if (err < 0)
                return err;
 
                fnew->handle = idr_index;
        }
 
-       err = basic_set_parms(net, tp, fnew, base, tb, tca[TCA_RATE], ovr);
+       err = basic_set_parms(net, tp, fnew, base, tb, tca[TCA_RATE], ovr,
+                             extack);
        if (err < 0) {
                if (!fold)
                        idr_remove_ext(&head->handle_idr, fnew->handle);
 
 
 static int cls_bpf_set_parms(struct net *net, struct tcf_proto *tp,
                             struct cls_bpf_prog *prog, unsigned long base,
-                            struct nlattr **tb, struct nlattr *est, bool ovr)
+                            struct nlattr **tb, struct nlattr *est, bool ovr,
+                            struct netlink_ext_ack *extack)
 {
        bool is_bpf, is_ebpf, have_exts = false;
        u32 gen_flags = 0;
        if ((!is_bpf && !is_ebpf) || (is_bpf && is_ebpf))
                return -EINVAL;
 
-       ret = tcf_exts_validate(net, tp, tb, est, &prog->exts, ovr);
+       ret = tcf_exts_validate(net, tp, tb, est, &prog->exts, ovr, extack);
        if (ret < 0)
                return ret;
 
                prog->handle = handle;
        }
 
-       ret = cls_bpf_set_parms(net, tp, prog, base, tb, tca[TCA_RATE], ovr);
+       ret = cls_bpf_set_parms(net, tp, prog, base, tb, tca[TCA_RATE], ovr,
+                               extack);
        if (ret < 0)
                goto errout_idr;
 
 
        if (err < 0)
                goto errout;
 
-       err = tcf_exts_validate(net, tp, tb, tca[TCA_RATE], &new->exts, ovr);
+       err = tcf_exts_validate(net, tp, tb, tca[TCA_RATE], &new->exts, ovr,
+                               extack);
        if (err < 0)
                goto errout;
 
 
        if (err < 0)
                goto err2;
 
-       err = tcf_exts_validate(net, tp, tb, tca[TCA_RATE], &fnew->exts, ovr);
+       err = tcf_exts_validate(net, tp, tb, tca[TCA_RATE], &fnew->exts, ovr,
+                               extack);
        if (err < 0)
                goto err2;
 
 
 static int fl_set_parms(struct net *net, struct tcf_proto *tp,
                        struct cls_fl_filter *f, struct fl_flow_mask *mask,
                        unsigned long base, struct nlattr **tb,
-                       struct nlattr *est, bool ovr)
+                       struct nlattr *est, bool ovr,
+                       struct netlink_ext_ack *extack)
 {
        int err;
 
-       err = tcf_exts_validate(net, tp, tb, est, &f->exts, ovr);
+       err = tcf_exts_validate(net, tp, tb, est, &f->exts, ovr, extack);
        if (err < 0)
                return err;
 
                }
        }
 
-       err = fl_set_parms(net, tp, fnew, &mask, base, tb, tca[TCA_RATE], ovr);
+       err = fl_set_parms(net, tp, fnew, &mask, base, tb, tca[TCA_RATE], ovr,
+                          extack);
        if (err)
                goto errout_idr;
 
 
 
 static int fw_set_parms(struct net *net, struct tcf_proto *tp,
                        struct fw_filter *f, struct nlattr **tb,
-                       struct nlattr **tca, unsigned long base, bool ovr)
+                       struct nlattr **tca, unsigned long base, bool ovr,
+                       struct netlink_ext_ack *extack)
 {
        struct fw_head *head = rtnl_dereference(tp->root);
        u32 mask;
        int err;
 
-       err = tcf_exts_validate(net, tp, tb, tca[TCA_RATE], &f->exts, ovr);
+       err = tcf_exts_validate(net, tp, tb, tca[TCA_RATE], &f->exts, ovr,
+                               extack);
        if (err < 0)
                return err;
 
                        return err;
                }
 
-               err = fw_set_parms(net, tp, fnew, tb, tca, base, ovr);
+               err = fw_set_parms(net, tp, fnew, tb, tca, base, ovr, extack);
                if (err < 0) {
                        tcf_exts_destroy(&fnew->exts);
                        kfree(fnew);
        f->id = handle;
        f->tp = tp;
 
-       err = fw_set_parms(net, tp, f, tb, tca, base, ovr);
+       err = fw_set_parms(net, tp, f, tb, tca, base, ovr, extack);
        if (err < 0)
                goto errout;
 
 
 static int mall_set_parms(struct net *net, struct tcf_proto *tp,
                          struct cls_mall_head *head,
                          unsigned long base, struct nlattr **tb,
-                         struct nlattr *est, bool ovr)
+                         struct nlattr *est, bool ovr,
+                         struct netlink_ext_ack *extack)
 {
        int err;
 
-       err = tcf_exts_validate(net, tp, tb, est, &head->exts, ovr);
+       err = tcf_exts_validate(net, tp, tb, est, &head->exts, ovr, extack);
        if (err < 0)
                return err;
 
        new->handle = handle;
        new->flags = flags;
 
-       err = mall_set_parms(net, tp, new, base, tb, tca[TCA_RATE], ovr);
+       err = mall_set_parms(net, tp, new, base, tb, tca[TCA_RATE], ovr,
+                            extack);
        if (err)
                goto err_set_parms;
 
 
                            unsigned long base, struct route4_filter *f,
                            u32 handle, struct route4_head *head,
                            struct nlattr **tb, struct nlattr *est, int new,
-                           bool ovr)
+                           bool ovr, struct netlink_ext_ack *extack)
 {
        u32 id = 0, to = 0, nhandle = 0x8000;
        struct route4_filter *fp;
        struct route4_bucket *b;
        int err;
 
-       err = tcf_exts_validate(net, tp, tb, est, &f->exts, ovr);
+       err = tcf_exts_validate(net, tp, tb, est, &f->exts, ovr, extack);
        if (err < 0)
                return err;
 
        }
 
        err = route4_set_parms(net, tp, base, f, handle, head, tb,
-                              tca[TCA_RATE], new, ovr);
+                              tca[TCA_RATE], new, ovr, extack);
        if (err < 0)
                goto errout;
 
 
        err = tcf_exts_init(&e, TCA_RSVP_ACT, TCA_RSVP_POLICE);
        if (err < 0)
                return err;
-       err = tcf_exts_validate(net, tp, tb, tca[TCA_RATE], &e, ovr);
+       err = tcf_exts_validate(net, tp, tb, tca[TCA_RATE], &e, ovr, extack);
        if (err < 0)
                goto errout2;
 
 
 tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
                  u32 handle, struct tcindex_data *p,
                  struct tcindex_filter_result *r, struct nlattr **tb,
-                 struct nlattr *est, bool ovr)
+                 struct nlattr *est, bool ovr, struct netlink_ext_ack *extack)
 {
        struct tcindex_filter_result new_filter_result, *old_r = r;
        struct tcindex_filter_result cr;
        err = tcf_exts_init(&e, TCA_TCINDEX_ACT, TCA_TCINDEX_POLICE);
        if (err < 0)
                return err;
-       err = tcf_exts_validate(net, tp, tb, est, &e, ovr);
+       err = tcf_exts_validate(net, tp, tb, est, &e, ovr, extack);
        if (err < 0)
                goto errout;
 
                return err;
 
        return tcindex_set_parms(net, tp, base, handle, p, r, tb,
-                                tca[TCA_RATE], ovr);
+                                tca[TCA_RATE], ovr, extack);
 }
 
 static void tcindex_walk(struct tcf_proto *tp, struct tcf_walker *walker)
 
 static int u32_set_parms(struct net *net, struct tcf_proto *tp,
                         unsigned long base, struct tc_u_hnode *ht,
                         struct tc_u_knode *n, struct nlattr **tb,
-                        struct nlattr *est, bool ovr)
+                        struct nlattr *est, bool ovr,
+                        struct netlink_ext_ack *extack)
 {
        int err;
 
-       err = tcf_exts_validate(net, tp, tb, est, &n->exts, ovr);
+       err = tcf_exts_validate(net, tp, tb, est, &n->exts, ovr, extack);
        if (err < 0)
                return err;
 
 
                err = u32_set_parms(net, tp, base,
                                    rtnl_dereference(n->ht_up), new, tb,
-                                   tca[TCA_RATE], ovr);
+                                   tca[TCA_RATE], ovr, extack);
 
                if (err) {
                        u32_destroy_key(tp, new, false);
        }
 #endif
 
-       err = u32_set_parms(net, tp, base, ht, n, tb, tca[TCA_RATE], ovr);
+       err = u32_set_parms(net, tp, base, ht, n, tb, tca[TCA_RATE], ovr,
+                           extack);
        if (err == 0) {
                struct tc_u_knode __rcu **ins;
                struct tc_u_knode *pins;