Commit 4a886482 authored by David S. Miller's avatar David S. Miller

Merge branch 'net-sched-act-add-extack-support'

Alexander Aring says:

====================
net: sched: act: add extack support

this patch series adds extack support for the TC action subsystem.
As example I for the extack support in a TC action I choosed mirred
action.

- Alex

Cc: David Ahern <dsahern@gmail.com>

changes since v3:
- adapt recommended changes from Davide Caratti, please check if
  I catch everything. Thanks.

changes since v2:

- remove newline in extack of generic walker handling
  Thanks to Davide Caratti
- add kernel@mojatatu.com in cc
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 80c6d2b8 1d4760c7
...@@ -87,12 +87,15 @@ struct tc_action_ops { ...@@ -87,12 +87,15 @@ struct tc_action_ops {
struct tcf_result *); struct tcf_result *);
int (*dump)(struct sk_buff *, struct tc_action *, int, int); int (*dump)(struct sk_buff *, struct tc_action *, int, int);
void (*cleanup)(struct tc_action *); void (*cleanup)(struct tc_action *);
int (*lookup)(struct net *, struct tc_action **, u32); int (*lookup)(struct net *net, struct tc_action **a, u32 index,
struct netlink_ext_ack *extack);
int (*init)(struct net *net, struct nlattr *nla, int (*init)(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action **act, int ovr, struct nlattr *est, struct tc_action **act, int ovr,
int bind); int bind, struct netlink_ext_ack *extack);
int (*walk)(struct net *, struct sk_buff *, int (*walk)(struct net *, struct sk_buff *,
struct netlink_callback *, int, const struct tc_action_ops *); struct netlink_callback *, int,
const struct tc_action_ops *,
struct netlink_ext_ack *);
void (*stats_update)(struct tc_action *, u64, u32, u64); void (*stats_update)(struct tc_action *, u64, u32, u64);
struct net_device *(*get_dev)(const struct tc_action *a); struct net_device *(*get_dev)(const struct tc_action *a);
}; };
...@@ -137,7 +140,8 @@ static inline void tc_action_net_exit(struct list_head *net_list, ...@@ -137,7 +140,8 @@ static inline void tc_action_net_exit(struct list_head *net_list,
int tcf_generic_walker(struct tc_action_net *tn, struct sk_buff *skb, int tcf_generic_walker(struct tc_action_net *tn, struct sk_buff *skb,
struct netlink_callback *cb, int type, struct netlink_callback *cb, int type,
const struct tc_action_ops *ops); const struct tc_action_ops *ops,
struct netlink_ext_ack *extack);
int tcf_idr_search(struct tc_action_net *tn, struct tc_action **a, u32 index); int tcf_idr_search(struct tc_action_net *tn, struct tc_action **a, u32 index);
bool tcf_idr_check(struct tc_action_net *tn, u32 index, struct tc_action **a, bool tcf_idr_check(struct tc_action_net *tn, u32 index, struct tc_action **a,
int bind); int bind);
...@@ -162,10 +166,11 @@ int tcf_action_exec(struct sk_buff *skb, struct tc_action **actions, ...@@ -162,10 +166,11 @@ int tcf_action_exec(struct sk_buff *skb, struct tc_action **actions,
int nr_actions, struct tcf_result *res); int nr_actions, struct tcf_result *res);
int tcf_action_init(struct net *net, struct tcf_proto *tp, struct nlattr *nla, int tcf_action_init(struct net *net, struct tcf_proto *tp, struct nlattr *nla,
struct nlattr *est, char *name, int ovr, int bind, struct nlattr *est, char *name, int ovr, int bind,
struct list_head *actions); struct list_head *actions, struct netlink_ext_ack *extack);
struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp, struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp,
struct nlattr *nla, struct nlattr *est, struct nlattr *nla, struct nlattr *est,
char *name, int ovr, int bind); char *name, int ovr, int bind,
struct netlink_ext_ack *extack);
int tcf_action_dump(struct sk_buff *skb, struct list_head *, int, int); int tcf_action_dump(struct sk_buff *skb, struct list_head *, int, int);
int tcf_action_dump_old(struct sk_buff *skb, struct tc_action *a, int, int); int tcf_action_dump_old(struct sk_buff *skb, struct tc_action *a, int, int);
int tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int, int); int tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int, int);
......
...@@ -202,7 +202,8 @@ static int tcf_del_walker(struct tcf_idrinfo *idrinfo, struct sk_buff *skb, ...@@ -202,7 +202,8 @@ static int tcf_del_walker(struct tcf_idrinfo *idrinfo, struct sk_buff *skb,
int tcf_generic_walker(struct tc_action_net *tn, struct sk_buff *skb, int tcf_generic_walker(struct tc_action_net *tn, struct sk_buff *skb,
struct netlink_callback *cb, int type, struct netlink_callback *cb, int type,
const struct tc_action_ops *ops) const struct tc_action_ops *ops,
struct netlink_ext_ack *extack)
{ {
struct tcf_idrinfo *idrinfo = tn->idrinfo; struct tcf_idrinfo *idrinfo = tn->idrinfo;
...@@ -211,7 +212,8 @@ int tcf_generic_walker(struct tc_action_net *tn, struct sk_buff *skb, ...@@ -211,7 +212,8 @@ int tcf_generic_walker(struct tc_action_net *tn, struct sk_buff *skb,
} else if (type == RTM_GETACTION) { } else if (type == RTM_GETACTION) {
return tcf_dump_walker(idrinfo, skb, cb); return tcf_dump_walker(idrinfo, skb, cb);
} else { } else {
WARN(1, "tcf_generic_walker: unknown action %d\n", type); WARN(1, "tcf_generic_walker: unknown command %d\n", type);
NL_SET_ERR_MSG(extack, "tcf_generic_walker: unknown command");
return -EINVAL; return -EINVAL;
} }
} }
...@@ -605,7 +607,8 @@ static struct tc_cookie *nla_memdup_cookie(struct nlattr **tb) ...@@ -605,7 +607,8 @@ static struct tc_cookie *nla_memdup_cookie(struct nlattr **tb)
struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp, struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp,
struct nlattr *nla, struct nlattr *est, struct nlattr *nla, struct nlattr *est,
char *name, int ovr, int bind) char *name, int ovr, int bind,
struct netlink_ext_ack *extack)
{ {
struct tc_action *a; struct tc_action *a;
struct tc_action_ops *a_o; struct tc_action_ops *a_o;
...@@ -616,31 +619,40 @@ struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp, ...@@ -616,31 +619,40 @@ struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp,
int err; int err;
if (name == NULL) { if (name == NULL) {
err = nla_parse_nested(tb, TCA_ACT_MAX, nla, NULL, NULL); err = nla_parse_nested(tb, TCA_ACT_MAX, nla, NULL, extack);
if (err < 0) if (err < 0)
goto err_out; goto err_out;
err = -EINVAL; err = -EINVAL;
kind = tb[TCA_ACT_KIND]; kind = tb[TCA_ACT_KIND];
if (kind == NULL) if (!kind) {
NL_SET_ERR_MSG(extack, "TC action kind must be specified");
goto err_out; goto err_out;
if (nla_strlcpy(act_name, kind, IFNAMSIZ) >= IFNAMSIZ) }
if (nla_strlcpy(act_name, kind, IFNAMSIZ) >= IFNAMSIZ) {
NL_SET_ERR_MSG(extack, "TC action name too long");
goto err_out; goto err_out;
}
if (tb[TCA_ACT_COOKIE]) { if (tb[TCA_ACT_COOKIE]) {
int cklen = nla_len(tb[TCA_ACT_COOKIE]); int cklen = nla_len(tb[TCA_ACT_COOKIE]);
if (cklen > TC_COOKIE_MAX_SIZE) if (cklen > TC_COOKIE_MAX_SIZE) {
NL_SET_ERR_MSG(extack, "TC cookie size above the maximum");
goto err_out; goto err_out;
}
cookie = nla_memdup_cookie(tb); cookie = nla_memdup_cookie(tb);
if (!cookie) { if (!cookie) {
NL_SET_ERR_MSG(extack, "No memory to generate TC cookie");
err = -ENOMEM; err = -ENOMEM;
goto err_out; goto err_out;
} }
} }
} else { } else {
err = -EINVAL; if (strlcpy(act_name, name, IFNAMSIZ) >= IFNAMSIZ) {
if (strlcpy(act_name, name, IFNAMSIZ) >= IFNAMSIZ) NL_SET_ERR_MSG(extack, "TC action name too long");
err = -EINVAL;
goto err_out; goto err_out;
}
} }
a_o = tc_lookup_action_n(act_name); a_o = tc_lookup_action_n(act_name);
...@@ -663,15 +675,17 @@ struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp, ...@@ -663,15 +675,17 @@ struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp,
goto err_mod; goto err_mod;
} }
#endif #endif
NL_SET_ERR_MSG(extack, "Failed to load TC action module");
err = -ENOENT; err = -ENOENT;
goto err_out; goto err_out;
} }
/* backward compatibility for policer */ /* backward compatibility for policer */
if (name == NULL) if (name == NULL)
err = a_o->init(net, tb[TCA_ACT_OPTIONS], est, &a, ovr, bind); err = a_o->init(net, tb[TCA_ACT_OPTIONS], est, &a, ovr, bind,
extack);
else else
err = a_o->init(net, nla, est, &a, ovr, bind); err = a_o->init(net, nla, est, &a, ovr, bind, extack);
if (err < 0) if (err < 0)
goto err_mod; goto err_mod;
...@@ -697,6 +711,7 @@ struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp, ...@@ -697,6 +711,7 @@ struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp,
list_add_tail(&a->list, &actions); list_add_tail(&a->list, &actions);
tcf_action_destroy(&actions, bind); tcf_action_destroy(&actions, bind);
NL_SET_ERR_MSG(extack, "Failed to init TC action chain");
return ERR_PTR(err); return ERR_PTR(err);
} }
} }
...@@ -726,19 +741,20 @@ static void cleanup_a(struct list_head *actions, int ovr) ...@@ -726,19 +741,20 @@ static void cleanup_a(struct list_head *actions, int ovr)
int tcf_action_init(struct net *net, struct tcf_proto *tp, struct nlattr *nla, int tcf_action_init(struct net *net, struct tcf_proto *tp, struct nlattr *nla,
struct nlattr *est, char *name, int ovr, int bind, struct nlattr *est, char *name, int ovr, int bind,
struct list_head *actions) struct list_head *actions, struct netlink_ext_ack *extack)
{ {
struct nlattr *tb[TCA_ACT_MAX_PRIO + 1]; struct nlattr *tb[TCA_ACT_MAX_PRIO + 1];
struct tc_action *act; struct tc_action *act;
int err; int err;
int i; int i;
err = nla_parse_nested(tb, TCA_ACT_MAX_PRIO, nla, NULL, NULL); err = nla_parse_nested(tb, TCA_ACT_MAX_PRIO, nla, NULL, extack);
if (err < 0) if (err < 0)
return err; return err;
for (i = 1; i <= TCA_ACT_MAX_PRIO && tb[i]; i++) { for (i = 1; i <= TCA_ACT_MAX_PRIO && tb[i]; i++) {
act = tcf_action_init_1(net, tp, tb[i], est, name, ovr, bind); act = tcf_action_init_1(net, tp, tb[i], est, name, ovr, bind,
extack);
if (IS_ERR(act)) { if (IS_ERR(act)) {
err = PTR_ERR(act); err = PTR_ERR(act);
goto err; goto err;
...@@ -822,7 +838,7 @@ static int tca_get_fill(struct sk_buff *skb, struct list_head *actions, ...@@ -822,7 +838,7 @@ static int tca_get_fill(struct sk_buff *skb, struct list_head *actions,
t->tca__pad2 = 0; t->tca__pad2 = 0;
nest = nla_nest_start(skb, TCA_ACT_TAB); nest = nla_nest_start(skb, TCA_ACT_TAB);
if (nest == NULL) if (!nest)
goto out_nlmsg_trim; goto out_nlmsg_trim;
if (tcf_action_dump(skb, actions, bind, ref) < 0) if (tcf_action_dump(skb, actions, bind, ref) < 0)
...@@ -840,7 +856,8 @@ static int tca_get_fill(struct sk_buff *skb, struct list_head *actions, ...@@ -840,7 +856,8 @@ static int tca_get_fill(struct sk_buff *skb, struct list_head *actions,
static int static int
tcf_get_notify(struct net *net, u32 portid, struct nlmsghdr *n, tcf_get_notify(struct net *net, u32 portid, struct nlmsghdr *n,
struct list_head *actions, int event) struct list_head *actions, int event,
struct netlink_ext_ack *extack)
{ {
struct sk_buff *skb; struct sk_buff *skb;
...@@ -849,6 +866,7 @@ tcf_get_notify(struct net *net, u32 portid, struct nlmsghdr *n, ...@@ -849,6 +866,7 @@ tcf_get_notify(struct net *net, u32 portid, struct nlmsghdr *n,
return -ENOBUFS; return -ENOBUFS;
if (tca_get_fill(skb, actions, portid, n->nlmsg_seq, 0, event, if (tca_get_fill(skb, actions, portid, n->nlmsg_seq, 0, event,
0, 0) <= 0) { 0, 0) <= 0) {
NL_SET_ERR_MSG(extack, "Failed to fill netlink attributes while adding TC action");
kfree_skb(skb); kfree_skb(skb);
return -EINVAL; return -EINVAL;
} }
...@@ -857,7 +875,8 @@ tcf_get_notify(struct net *net, u32 portid, struct nlmsghdr *n, ...@@ -857,7 +875,8 @@ tcf_get_notify(struct net *net, u32 portid, struct nlmsghdr *n,
} }
static struct tc_action *tcf_action_get_1(struct net *net, struct nlattr *nla, static struct tc_action *tcf_action_get_1(struct net *net, struct nlattr *nla,
struct nlmsghdr *n, u32 portid) struct nlmsghdr *n, u32 portid,
struct netlink_ext_ack *extack)
{ {
struct nlattr *tb[TCA_ACT_MAX + 1]; struct nlattr *tb[TCA_ACT_MAX + 1];
const struct tc_action_ops *ops; const struct tc_action_ops *ops;
...@@ -865,22 +884,26 @@ static struct tc_action *tcf_action_get_1(struct net *net, struct nlattr *nla, ...@@ -865,22 +884,26 @@ static struct tc_action *tcf_action_get_1(struct net *net, struct nlattr *nla,
int index; int index;
int err; int err;
err = nla_parse_nested(tb, TCA_ACT_MAX, nla, NULL, NULL); err = nla_parse_nested(tb, TCA_ACT_MAX, nla, NULL, extack);
if (err < 0) if (err < 0)
goto err_out; goto err_out;
err = -EINVAL; err = -EINVAL;
if (tb[TCA_ACT_INDEX] == NULL || if (tb[TCA_ACT_INDEX] == NULL ||
nla_len(tb[TCA_ACT_INDEX]) < sizeof(index)) nla_len(tb[TCA_ACT_INDEX]) < sizeof(index)) {
NL_SET_ERR_MSG(extack, "Invalid TC action index value");
goto err_out; goto err_out;
}
index = nla_get_u32(tb[TCA_ACT_INDEX]); index = nla_get_u32(tb[TCA_ACT_INDEX]);
err = -EINVAL; err = -EINVAL;
ops = tc_lookup_action(tb[TCA_ACT_KIND]); ops = tc_lookup_action(tb[TCA_ACT_KIND]);
if (!ops) /* could happen in batch of actions */ if (!ops) { /* could happen in batch of actions */
NL_SET_ERR_MSG(extack, "Specified TC action not found");
goto err_out; goto err_out;
}
err = -ENOENT; err = -ENOENT;
if (ops->lookup(net, &a, index) == 0) if (ops->lookup(net, &a, index, extack) == 0)
goto err_mod; goto err_mod;
module_put(ops->owner); module_put(ops->owner);
...@@ -893,7 +916,8 @@ static struct tc_action *tcf_action_get_1(struct net *net, struct nlattr *nla, ...@@ -893,7 +916,8 @@ static struct tc_action *tcf_action_get_1(struct net *net, struct nlattr *nla,
} }
static int tca_action_flush(struct net *net, struct nlattr *nla, static int tca_action_flush(struct net *net, struct nlattr *nla,
struct nlmsghdr *n, u32 portid) struct nlmsghdr *n, u32 portid,
struct netlink_ext_ack *extack)
{ {
struct sk_buff *skb; struct sk_buff *skb;
unsigned char *b; unsigned char *b;
...@@ -907,37 +931,41 @@ static int tca_action_flush(struct net *net, struct nlattr *nla, ...@@ -907,37 +931,41 @@ static int tca_action_flush(struct net *net, struct nlattr *nla,
int err = -ENOMEM; int err = -ENOMEM;
skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
if (!skb) { if (!skb)
pr_debug("tca_action_flush: failed skb alloc\n");
return err; return err;
}
b = skb_tail_pointer(skb); b = skb_tail_pointer(skb);
err = nla_parse_nested(tb, TCA_ACT_MAX, nla, NULL, NULL); err = nla_parse_nested(tb, TCA_ACT_MAX, nla, NULL, extack);
if (err < 0) if (err < 0)
goto err_out; goto err_out;
err = -EINVAL; err = -EINVAL;
kind = tb[TCA_ACT_KIND]; kind = tb[TCA_ACT_KIND];
ops = tc_lookup_action(kind); ops = tc_lookup_action(kind);
if (!ops) /*some idjot trying to flush unknown action */ if (!ops) { /*some idjot trying to flush unknown action */
NL_SET_ERR_MSG(extack, "Cannot flush unknown TC action");
goto err_out; goto err_out;
}
nlh = nlmsg_put(skb, portid, n->nlmsg_seq, RTM_DELACTION, nlh = nlmsg_put(skb, portid, n->nlmsg_seq, RTM_DELACTION,
sizeof(*t), 0); sizeof(*t), 0);
if (!nlh) if (!nlh) {
NL_SET_ERR_MSG(extack, "Failed to create TC action flush notification");
goto out_module_put; goto out_module_put;
}
t = nlmsg_data(nlh); t = nlmsg_data(nlh);
t->tca_family = AF_UNSPEC; t->tca_family = AF_UNSPEC;
t->tca__pad1 = 0; t->tca__pad1 = 0;
t->tca__pad2 = 0; t->tca__pad2 = 0;
nest = nla_nest_start(skb, TCA_ACT_TAB); nest = nla_nest_start(skb, TCA_ACT_TAB);
if (nest == NULL) if (!nest) {
NL_SET_ERR_MSG(extack, "Failed to add new netlink message");
goto out_module_put; goto out_module_put;
}
err = ops->walk(net, skb, &dcb, RTM_DELACTION, ops); err = ops->walk(net, skb, &dcb, RTM_DELACTION, ops, extack);
if (err <= 0) { if (err <= 0) {
nla_nest_cancel(skb, nest); nla_nest_cancel(skb, nest);
goto out_module_put; goto out_module_put;
...@@ -952,6 +980,8 @@ static int tca_action_flush(struct net *net, struct nlattr *nla, ...@@ -952,6 +980,8 @@ static int tca_action_flush(struct net *net, struct nlattr *nla,
n->nlmsg_flags & NLM_F_ECHO); n->nlmsg_flags & NLM_F_ECHO);
if (err > 0) if (err > 0)
return 0; return 0;
if (err < 0)
NL_SET_ERR_MSG(extack, "Failed to send TC action flush notification");
return err; return err;
...@@ -964,7 +994,7 @@ static int tca_action_flush(struct net *net, struct nlattr *nla, ...@@ -964,7 +994,7 @@ static int tca_action_flush(struct net *net, struct nlattr *nla,
static int static int
tcf_del_notify(struct net *net, struct nlmsghdr *n, struct list_head *actions, tcf_del_notify(struct net *net, struct nlmsghdr *n, struct list_head *actions,
u32 portid) u32 portid, struct netlink_ext_ack *extack)
{ {
int ret; int ret;
struct sk_buff *skb; struct sk_buff *skb;
...@@ -975,6 +1005,7 @@ tcf_del_notify(struct net *net, struct nlmsghdr *n, struct list_head *actions, ...@@ -975,6 +1005,7 @@ tcf_del_notify(struct net *net, struct nlmsghdr *n, struct list_head *actions,
if (tca_get_fill(skb, actions, portid, n->nlmsg_seq, 0, RTM_DELACTION, if (tca_get_fill(skb, actions, portid, n->nlmsg_seq, 0, RTM_DELACTION,
0, 1) <= 0) { 0, 1) <= 0) {
NL_SET_ERR_MSG(extack, "Failed to fill netlink TC action attributes");
kfree_skb(skb); kfree_skb(skb);
return -EINVAL; return -EINVAL;
} }
...@@ -982,6 +1013,7 @@ tcf_del_notify(struct net *net, struct nlmsghdr *n, struct list_head *actions, ...@@ -982,6 +1013,7 @@ tcf_del_notify(struct net *net, struct nlmsghdr *n, struct list_head *actions,
/* now do the delete */ /* now do the delete */
ret = tcf_action_destroy(actions, 0); ret = tcf_action_destroy(actions, 0);
if (ret < 0) { if (ret < 0) {
NL_SET_ERR_MSG(extack, "Failed to delete TC action");
kfree_skb(skb); kfree_skb(skb);
return ret; return ret;
} }
...@@ -995,26 +1027,27 @@ tcf_del_notify(struct net *net, struct nlmsghdr *n, struct list_head *actions, ...@@ -995,26 +1027,27 @@ tcf_del_notify(struct net *net, struct nlmsghdr *n, struct list_head *actions,
static int static int
tca_action_gd(struct net *net, struct nlattr *nla, struct nlmsghdr *n, tca_action_gd(struct net *net, struct nlattr *nla, struct nlmsghdr *n,
u32 portid, int event) u32 portid, int event, struct netlink_ext_ack *extack)
{ {
int i, ret; int i, ret;
struct nlattr *tb[TCA_ACT_MAX_PRIO + 1]; struct nlattr *tb[TCA_ACT_MAX_PRIO + 1];
struct tc_action *act; struct tc_action *act;
LIST_HEAD(actions); LIST_HEAD(actions);
ret = nla_parse_nested(tb, TCA_ACT_MAX_PRIO, nla, NULL, NULL); ret = nla_parse_nested(tb, TCA_ACT_MAX_PRIO, nla, NULL, extack);
if (ret < 0) if (ret < 0)
return ret; return ret;
if (event == RTM_DELACTION && n->nlmsg_flags & NLM_F_ROOT) { if (event == RTM_DELACTION && n->nlmsg_flags & NLM_F_ROOT) {
if (tb[1] != NULL) if (tb[1])
return tca_action_flush(net, tb[1], n, portid); return tca_action_flush(net, tb[1], n, portid, extack);
else
return -EINVAL; NL_SET_ERR_MSG(extack, "Invalid netlink attributes while flushing TC action");
return -EINVAL;
} }
for (i = 1; i <= TCA_ACT_MAX_PRIO && tb[i]; i++) { for (i = 1; i <= TCA_ACT_MAX_PRIO && tb[i]; i++) {
act = tcf_action_get_1(net, tb[i], n, portid); act = tcf_action_get_1(net, tb[i], n, portid, extack);
if (IS_ERR(act)) { if (IS_ERR(act)) {
ret = PTR_ERR(act); ret = PTR_ERR(act);
goto err; goto err;
...@@ -1024,9 +1057,9 @@ tca_action_gd(struct net *net, struct nlattr *nla, struct nlmsghdr *n, ...@@ -1024,9 +1057,9 @@ tca_action_gd(struct net *net, struct nlattr *nla, struct nlmsghdr *n,
} }
if (event == RTM_GETACTION) if (event == RTM_GETACTION)
ret = tcf_get_notify(net, portid, n, &actions, event); ret = tcf_get_notify(net, portid, n, &actions, event, extack);
else { /* delete */ else { /* delete */
ret = tcf_del_notify(net, n, &actions, portid); ret = tcf_del_notify(net, n, &actions, portid, extack);
if (ret) if (ret)
goto err; goto err;
return ret; return ret;
...@@ -1039,7 +1072,7 @@ tca_action_gd(struct net *net, struct nlattr *nla, struct nlmsghdr *n, ...@@ -1039,7 +1072,7 @@ tca_action_gd(struct net *net, struct nlattr *nla, struct nlmsghdr *n,
static int static int
tcf_add_notify(struct net *net, struct nlmsghdr *n, struct list_head *actions, tcf_add_notify(struct net *net, struct nlmsghdr *n, struct list_head *actions,
u32 portid) u32 portid, struct netlink_ext_ack *extack)
{ {
struct sk_buff *skb; struct sk_buff *skb;
int err = 0; int err = 0;
...@@ -1050,6 +1083,7 @@ tcf_add_notify(struct net *net, struct nlmsghdr *n, struct list_head *actions, ...@@ -1050,6 +1083,7 @@ tcf_add_notify(struct net *net, struct nlmsghdr *n, struct list_head *actions,
if (tca_get_fill(skb, actions, portid, n->nlmsg_seq, n->nlmsg_flags, if (tca_get_fill(skb, actions, portid, n->nlmsg_seq, n->nlmsg_flags,
RTM_NEWACTION, 0, 0) <= 0) { RTM_NEWACTION, 0, 0) <= 0) {
NL_SET_ERR_MSG(extack, "Failed to fill netlink attributes while deleting TC action");
kfree_skb(skb); kfree_skb(skb);
return -EINVAL; return -EINVAL;
} }
...@@ -1062,16 +1096,18 @@ tcf_add_notify(struct net *net, struct nlmsghdr *n, struct list_head *actions, ...@@ -1062,16 +1096,18 @@ tcf_add_notify(struct net *net, struct nlmsghdr *n, struct list_head *actions,
} }
static int tcf_action_add(struct net *net, struct nlattr *nla, static int tcf_action_add(struct net *net, struct nlattr *nla,
struct nlmsghdr *n, u32 portid, int ovr) struct nlmsghdr *n, u32 portid, int ovr,
struct netlink_ext_ack *extack)
{ {
int ret = 0; int ret = 0;
LIST_HEAD(actions); LIST_HEAD(actions);
ret = tcf_action_init(net, NULL, nla, NULL, NULL, ovr, 0, &actions); ret = tcf_action_init(net, NULL, nla, NULL, NULL, ovr, 0, &actions,
extack);
if (ret) if (ret)
return ret; return ret;
return tcf_add_notify(net, n, &actions, portid); return tcf_add_notify(net, n, &actions, portid, extack);
} }
static u32 tcaa_root_flags_allowed = TCA_FLAG_LARGE_DUMP_ON; static u32 tcaa_root_flags_allowed = TCA_FLAG_LARGE_DUMP_ON;
...@@ -1099,7 +1135,7 @@ static int tc_ctl_action(struct sk_buff *skb, struct nlmsghdr *n, ...@@ -1099,7 +1135,7 @@ static int tc_ctl_action(struct sk_buff *skb, struct nlmsghdr *n,
return ret; return ret;
if (tca[TCA_ACT_TAB] == NULL) { if (tca[TCA_ACT_TAB] == NULL) {
pr_notice("tc_ctl_action: received NO action attribs\n"); NL_SET_ERR_MSG(extack, "Netlink action attributes missing");
return -EINVAL; return -EINVAL;
} }
...@@ -1115,17 +1151,18 @@ static int tc_ctl_action(struct sk_buff *skb, struct nlmsghdr *n, ...@@ -1115,17 +1151,18 @@ static int tc_ctl_action(struct sk_buff *skb, struct nlmsghdr *n,
if (n->nlmsg_flags & NLM_F_REPLACE) if (n->nlmsg_flags & NLM_F_REPLACE)
ovr = 1; ovr = 1;
replay: replay:
ret = tcf_action_add(net, tca[TCA_ACT_TAB], n, portid, ovr); ret = tcf_action_add(net, tca[TCA_ACT_TAB], n, portid, ovr,
extack);
if (ret == -EAGAIN) if (ret == -EAGAIN)
goto replay; goto replay;
break; break;
case RTM_DELACTION: case RTM_DELACTION:
ret = tca_action_gd(net, tca[TCA_ACT_TAB], n, ret = tca_action_gd(net, tca[TCA_ACT_TAB], n,
portid, RTM_DELACTION); portid, RTM_DELACTION, extack);
break; break;
case RTM_GETACTION: case RTM_GETACTION:
ret = tca_action_gd(net, tca[TCA_ACT_TAB], n, ret = tca_action_gd(net, tca[TCA_ACT_TAB], n,
portid, RTM_GETACTION); portid, RTM_GETACTION, extack);
break; break;
default: default:
BUG(); BUG();
...@@ -1220,7 +1257,7 @@ static int tc_dump_action(struct sk_buff *skb, struct netlink_callback *cb) ...@@ -1220,7 +1257,7 @@ static int tc_dump_action(struct sk_buff *skb, struct netlink_callback *cb)
if (nest == NULL) if (nest == NULL)
goto out_module_put; goto out_module_put;
ret = a_o->walk(net, skb, cb, RTM_GETACTION, a_o); ret = a_o->walk(net, skb, cb, RTM_GETACTION, a_o, NULL);
if (ret < 0) if (ret < 0)
goto out_module_put; goto out_module_put;
......
...@@ -272,7 +272,7 @@ static void tcf_bpf_prog_fill_cfg(const struct tcf_bpf *prog, ...@@ -272,7 +272,7 @@ static void tcf_bpf_prog_fill_cfg(const struct tcf_bpf *prog,
static int tcf_bpf_init(struct net *net, struct nlattr *nla, static int tcf_bpf_init(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action **act, struct nlattr *est, struct tc_action **act,
int replace, int bind) int replace, int bind, struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, bpf_net_id); struct tc_action_net *tn = net_generic(net, bpf_net_id);
struct nlattr *tb[TCA_ACT_BPF_MAX + 1]; struct nlattr *tb[TCA_ACT_BPF_MAX + 1];
...@@ -367,14 +367,16 @@ static void tcf_bpf_cleanup(struct tc_action *act) ...@@ -367,14 +367,16 @@ static void tcf_bpf_cleanup(struct tc_action *act)
static int tcf_bpf_walker(struct net *net, struct sk_buff *skb, static int tcf_bpf_walker(struct net *net, struct sk_buff *skb,
struct netlink_callback *cb, int type, struct netlink_callback *cb, int type,
const struct tc_action_ops *ops) const struct tc_action_ops *ops,
struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, bpf_net_id); struct tc_action_net *tn = net_generic(net, bpf_net_id);
return tcf_generic_walker(tn, skb, cb, type, ops); return tcf_generic_walker(tn, skb, cb, type, ops, extack);
} }
static int tcf_bpf_search(struct net *net, struct tc_action **a, u32 index) static int tcf_bpf_search(struct net *net, struct tc_action **a, u32 index,
struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, bpf_net_id); struct tc_action_net *tn = net_generic(net, bpf_net_id);
......
...@@ -96,7 +96,8 @@ static const struct nla_policy connmark_policy[TCA_CONNMARK_MAX + 1] = { ...@@ -96,7 +96,8 @@ static const struct nla_policy connmark_policy[TCA_CONNMARK_MAX + 1] = {
static int tcf_connmark_init(struct net *net, struct nlattr *nla, static int tcf_connmark_init(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action **a, struct nlattr *est, struct tc_action **a,
int ovr, int bind) int ovr, int bind,
struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, connmark_net_id); struct tc_action_net *tn = net_generic(net, connmark_net_id);
struct nlattr *tb[TCA_CONNMARK_MAX + 1]; struct nlattr *tb[TCA_CONNMARK_MAX + 1];
...@@ -176,14 +177,16 @@ static inline int tcf_connmark_dump(struct sk_buff *skb, struct tc_action *a, ...@@ -176,14 +177,16 @@ static inline int tcf_connmark_dump(struct sk_buff *skb, struct tc_action *a,
static int tcf_connmark_walker(struct net *net, struct sk_buff *skb, static int tcf_connmark_walker(struct net *net, struct sk_buff *skb,
struct netlink_callback *cb, int type, struct netlink_callback *cb, int type,
const struct tc_action_ops *ops) const struct tc_action_ops *ops,
struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, connmark_net_id); struct tc_action_net *tn = net_generic(net, connmark_net_id);
return tcf_generic_walker(tn, skb, cb, type, ops); return tcf_generic_walker(tn, skb, cb, type, ops, extack);
} }
static int tcf_connmark_search(struct net *net, struct tc_action **a, u32 index) static int tcf_connmark_search(struct net *net, struct tc_action **a, u32 index,
struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, connmark_net_id); struct tc_action_net *tn = net_generic(net, connmark_net_id);
......
...@@ -46,7 +46,7 @@ static struct tc_action_ops act_csum_ops; ...@@ -46,7 +46,7 @@ static struct tc_action_ops act_csum_ops;
static int tcf_csum_init(struct net *net, struct nlattr *nla, static int tcf_csum_init(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action **a, int ovr, struct nlattr *est, struct tc_action **a, int ovr,
int bind) int bind, struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, csum_net_id); struct tc_action_net *tn = net_generic(net, csum_net_id);
struct tcf_csum_params *params_old, *params_new; struct tcf_csum_params *params_old, *params_new;
...@@ -631,14 +631,16 @@ static void tcf_csum_cleanup(struct tc_action *a) ...@@ -631,14 +631,16 @@ static void tcf_csum_cleanup(struct tc_action *a)
static int tcf_csum_walker(struct net *net, struct sk_buff *skb, static int tcf_csum_walker(struct net *net, struct sk_buff *skb,
struct netlink_callback *cb, int type, struct netlink_callback *cb, int type,
const struct tc_action_ops *ops) const struct tc_action_ops *ops,
struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, csum_net_id); struct tc_action_net *tn = net_generic(net, csum_net_id);
return tcf_generic_walker(tn, skb, cb, type, ops); return tcf_generic_walker(tn, skb, cb, type, ops, extack);
} }
static int tcf_csum_search(struct net *net, struct tc_action **a, u32 index) static int tcf_csum_search(struct net *net, struct tc_action **a, u32 index,
struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, csum_net_id); struct tc_action_net *tn = net_generic(net, csum_net_id);
......
...@@ -56,7 +56,7 @@ static const struct nla_policy gact_policy[TCA_GACT_MAX + 1] = { ...@@ -56,7 +56,7 @@ static const struct nla_policy gact_policy[TCA_GACT_MAX + 1] = {
static int tcf_gact_init(struct net *net, struct nlattr *nla, static int tcf_gact_init(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action **a, struct nlattr *est, struct tc_action **a,
int ovr, int bind) int ovr, int bind, struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, gact_net_id); struct tc_action_net *tn = net_generic(net, gact_net_id);
struct nlattr *tb[TCA_GACT_MAX + 1]; struct nlattr *tb[TCA_GACT_MAX + 1];
...@@ -201,14 +201,16 @@ static int tcf_gact_dump(struct sk_buff *skb, struct tc_action *a, ...@@ -201,14 +201,16 @@ static int tcf_gact_dump(struct sk_buff *skb, struct tc_action *a,
static int tcf_gact_walker(struct net *net, struct sk_buff *skb, static int tcf_gact_walker(struct net *net, struct sk_buff *skb,
struct netlink_callback *cb, int type, struct netlink_callback *cb, int type,
const struct tc_action_ops *ops) const struct tc_action_ops *ops,
struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, gact_net_id); struct tc_action_net *tn = net_generic(net, gact_net_id);
return tcf_generic_walker(tn, skb, cb, type, ops); return tcf_generic_walker(tn, skb, cb, type, ops, extack);
} }
static int tcf_gact_search(struct net *net, struct tc_action **a, u32 index) static int tcf_gact_search(struct net *net, struct tc_action **a, u32 index,
struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, gact_net_id); struct tc_action_net *tn = net_generic(net, gact_net_id);
......
...@@ -447,7 +447,7 @@ static int populate_metalist(struct tcf_ife_info *ife, struct nlattr **tb, ...@@ -447,7 +447,7 @@ static int populate_metalist(struct tcf_ife_info *ife, struct nlattr **tb,
static int tcf_ife_init(struct net *net, struct nlattr *nla, static int tcf_ife_init(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action **a, struct nlattr *est, struct tc_action **a,
int ovr, int bind) int ovr, int bind, struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, ife_net_id); struct tc_action_net *tn = net_generic(net, ife_net_id);
struct nlattr *tb[TCA_IFE_MAX + 1]; struct nlattr *tb[TCA_IFE_MAX + 1];
...@@ -824,14 +824,16 @@ static int tcf_ife_act(struct sk_buff *skb, const struct tc_action *a, ...@@ -824,14 +824,16 @@ static int tcf_ife_act(struct sk_buff *skb, const struct tc_action *a,
static int tcf_ife_walker(struct net *net, struct sk_buff *skb, static int tcf_ife_walker(struct net *net, struct sk_buff *skb,
struct netlink_callback *cb, int type, struct netlink_callback *cb, int type,
const struct tc_action_ops *ops) const struct tc_action_ops *ops,
struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, ife_net_id); struct tc_action_net *tn = net_generic(net, ife_net_id);
return tcf_generic_walker(tn, skb, cb, type, ops); return tcf_generic_walker(tn, skb, cb, type, ops, extack);
} }
static int tcf_ife_search(struct net *net, struct tc_action **a, u32 index) static int tcf_ife_search(struct net *net, struct tc_action **a, u32 index,
struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, ife_net_id); struct tc_action_net *tn = net_generic(net, ife_net_id);
......
...@@ -193,7 +193,7 @@ static int __tcf_ipt_init(struct net *net, unsigned int id, struct nlattr *nla, ...@@ -193,7 +193,7 @@ static int __tcf_ipt_init(struct net *net, unsigned int id, struct nlattr *nla,
static int tcf_ipt_init(struct net *net, struct nlattr *nla, static int tcf_ipt_init(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action **a, int ovr, struct nlattr *est, struct tc_action **a, int ovr,
int bind) int bind, struct netlink_ext_ack *extack)
{ {
return __tcf_ipt_init(net, ipt_net_id, nla, est, a, &act_ipt_ops, ovr, return __tcf_ipt_init(net, ipt_net_id, nla, est, a, &act_ipt_ops, ovr,
bind); bind);
...@@ -201,7 +201,7 @@ static int tcf_ipt_init(struct net *net, struct nlattr *nla, ...@@ -201,7 +201,7 @@ static int tcf_ipt_init(struct net *net, struct nlattr *nla,
static int tcf_xt_init(struct net *net, struct nlattr *nla, static int tcf_xt_init(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action **a, int ovr, struct nlattr *est, struct tc_action **a, int ovr,
int bind) int bind, struct netlink_ext_ack *extack)
{ {
return __tcf_ipt_init(net, xt_net_id, nla, est, a, &act_xt_ops, ovr, return __tcf_ipt_init(net, xt_net_id, nla, est, a, &act_xt_ops, ovr,
bind); bind);
...@@ -303,14 +303,16 @@ static int tcf_ipt_dump(struct sk_buff *skb, struct tc_action *a, int bind, ...@@ -303,14 +303,16 @@ static int tcf_ipt_dump(struct sk_buff *skb, struct tc_action *a, int bind,
static int tcf_ipt_walker(struct net *net, struct sk_buff *skb, static int tcf_ipt_walker(struct net *net, struct sk_buff *skb,
struct netlink_callback *cb, int type, struct netlink_callback *cb, int type,
const struct tc_action_ops *ops) const struct tc_action_ops *ops,
struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, ipt_net_id); struct tc_action_net *tn = net_generic(net, ipt_net_id);
return tcf_generic_walker(tn, skb, cb, type, ops); return tcf_generic_walker(tn, skb, cb, type, ops, extack);
} }
static int tcf_ipt_search(struct net *net, struct tc_action **a, u32 index) static int tcf_ipt_search(struct net *net, struct tc_action **a, u32 index,
struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, ipt_net_id); struct tc_action_net *tn = net_generic(net, ipt_net_id);
...@@ -351,14 +353,16 @@ static struct pernet_operations ipt_net_ops = { ...@@ -351,14 +353,16 @@ static struct pernet_operations ipt_net_ops = {
static int tcf_xt_walker(struct net *net, struct sk_buff *skb, static int tcf_xt_walker(struct net *net, struct sk_buff *skb,
struct netlink_callback *cb, int type, struct netlink_callback *cb, int type,
const struct tc_action_ops *ops) const struct tc_action_ops *ops,
struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, xt_net_id); struct tc_action_net *tn = net_generic(net, xt_net_id);
return tcf_generic_walker(tn, skb, cb, type, ops); return tcf_generic_walker(tn, skb, cb, type, ops, extack);
} }
static int tcf_xt_search(struct net *net, struct tc_action **a, u32 index) static int tcf_xt_search(struct net *net, struct tc_action **a, u32 index,
struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, xt_net_id); struct tc_action_net *tn = net_generic(net, xt_net_id);
......
...@@ -69,7 +69,7 @@ static struct tc_action_ops act_mirred_ops; ...@@ -69,7 +69,7 @@ static struct tc_action_ops act_mirred_ops;
static int tcf_mirred_init(struct net *net, struct nlattr *nla, static int tcf_mirred_init(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action **a, int ovr, struct nlattr *est, struct tc_action **a, int ovr,
int bind) int bind, struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, mirred_net_id); struct tc_action_net *tn = net_generic(net, mirred_net_id);
struct nlattr *tb[TCA_MIRRED_MAX + 1]; struct nlattr *tb[TCA_MIRRED_MAX + 1];
...@@ -80,13 +80,17 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla, ...@@ -80,13 +80,17 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
bool exists = false; bool exists = false;
int ret; int ret;
if (nla == NULL) if (!nla) {
NL_SET_ERR_MSG_MOD(extack, "Mirred requires attributes to be passed");
return -EINVAL; return -EINVAL;
ret = nla_parse_nested(tb, TCA_MIRRED_MAX, nla, mirred_policy, NULL); }
ret = nla_parse_nested(tb, TCA_MIRRED_MAX, nla, mirred_policy, extack);
if (ret < 0) if (ret < 0)
return ret; return ret;
if (tb[TCA_MIRRED_PARMS] == NULL) if (!tb[TCA_MIRRED_PARMS]) {
NL_SET_ERR_MSG_MOD(extack, "Missing required mirred parameters");
return -EINVAL; return -EINVAL;
}
parm = nla_data(tb[TCA_MIRRED_PARMS]); parm = nla_data(tb[TCA_MIRRED_PARMS]);
exists = tcf_idr_check(tn, parm->index, a, bind); exists = tcf_idr_check(tn, parm->index, a, bind);
...@@ -102,6 +106,7 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla, ...@@ -102,6 +106,7 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
default: default:
if (exists) if (exists)
tcf_idr_release(*a, bind); tcf_idr_release(*a, bind);
NL_SET_ERR_MSG_MOD(extack, "Unknown mirred option");
return -EINVAL; return -EINVAL;
} }
if (parm->ifindex) { if (parm->ifindex) {
...@@ -117,8 +122,10 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla, ...@@ -117,8 +122,10 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
} }
if (!exists) { if (!exists) {
if (dev == NULL) if (!dev) {
NL_SET_ERR_MSG_MOD(extack, "Specified device does not exist");
return -EINVAL; return -EINVAL;
}
ret = tcf_idr_create(tn, parm->index, est, a, ret = tcf_idr_create(tn, parm->index, est, a,
&act_mirred_ops, bind, true); &act_mirred_ops, bind, true);
if (ret) if (ret)
...@@ -265,14 +272,16 @@ static int tcf_mirred_dump(struct sk_buff *skb, struct tc_action *a, int bind, ...@@ -265,14 +272,16 @@ static int tcf_mirred_dump(struct sk_buff *skb, struct tc_action *a, int bind,
static int tcf_mirred_walker(struct net *net, struct sk_buff *skb, static int tcf_mirred_walker(struct net *net, struct sk_buff *skb,
struct netlink_callback *cb, int type, struct netlink_callback *cb, int type,
const struct tc_action_ops *ops) const struct tc_action_ops *ops,
struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, mirred_net_id); struct tc_action_net *tn = net_generic(net, mirred_net_id);
return tcf_generic_walker(tn, skb, cb, type, ops); return tcf_generic_walker(tn, skb, cb, type, ops, extack);
} }
static int tcf_mirred_search(struct net *net, struct tc_action **a, u32 index) static int tcf_mirred_search(struct net *net, struct tc_action **a, u32 index,
struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, mirred_net_id); struct tc_action_net *tn = net_generic(net, mirred_net_id);
......
...@@ -37,7 +37,8 @@ static const struct nla_policy nat_policy[TCA_NAT_MAX + 1] = { ...@@ -37,7 +37,8 @@ static const struct nla_policy nat_policy[TCA_NAT_MAX + 1] = {
}; };
static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est, static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est,
struct tc_action **a, int ovr, int bind) struct tc_action **a, int ovr, int bind,
struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, nat_net_id); struct tc_action_net *tn = net_generic(net, nat_net_id);
struct nlattr *tb[TCA_NAT_MAX + 1]; struct nlattr *tb[TCA_NAT_MAX + 1];
...@@ -277,14 +278,16 @@ static int tcf_nat_dump(struct sk_buff *skb, struct tc_action *a, ...@@ -277,14 +278,16 @@ static int tcf_nat_dump(struct sk_buff *skb, struct tc_action *a,
static int tcf_nat_walker(struct net *net, struct sk_buff *skb, static int tcf_nat_walker(struct net *net, struct sk_buff *skb,
struct netlink_callback *cb, int type, struct netlink_callback *cb, int type,
const struct tc_action_ops *ops) const struct tc_action_ops *ops,
struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, nat_net_id); struct tc_action_net *tn = net_generic(net, nat_net_id);
return tcf_generic_walker(tn, skb, cb, type, ops); return tcf_generic_walker(tn, skb, cb, type, ops, extack);
} }
static int tcf_nat_search(struct net *net, struct tc_action **a, u32 index) static int tcf_nat_search(struct net *net, struct tc_action **a, u32 index,
struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, nat_net_id); struct tc_action_net *tn = net_generic(net, nat_net_id);
......
...@@ -132,7 +132,7 @@ static int tcf_pedit_key_ex_dump(struct sk_buff *skb, ...@@ -132,7 +132,7 @@ static int tcf_pedit_key_ex_dump(struct sk_buff *skb,
static int tcf_pedit_init(struct net *net, struct nlattr *nla, static int tcf_pedit_init(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action **a, struct nlattr *est, struct tc_action **a,
int ovr, int bind) int ovr, int bind, struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, pedit_net_id); struct tc_action_net *tn = net_generic(net, pedit_net_id);
struct nlattr *tb[TCA_PEDIT_MAX + 1]; struct nlattr *tb[TCA_PEDIT_MAX + 1];
...@@ -419,14 +419,16 @@ static int tcf_pedit_dump(struct sk_buff *skb, struct tc_action *a, ...@@ -419,14 +419,16 @@ static int tcf_pedit_dump(struct sk_buff *skb, struct tc_action *a,
static int tcf_pedit_walker(struct net *net, struct sk_buff *skb, static int tcf_pedit_walker(struct net *net, struct sk_buff *skb,
struct netlink_callback *cb, int type, struct netlink_callback *cb, int type,
const struct tc_action_ops *ops) const struct tc_action_ops *ops,
struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, pedit_net_id); struct tc_action_net *tn = net_generic(net, pedit_net_id);
return tcf_generic_walker(tn, skb, cb, type, ops); return tcf_generic_walker(tn, skb, cb, type, ops, extack);
} }
static int tcf_pedit_search(struct net *net, struct tc_action **a, u32 index) static int tcf_pedit_search(struct net *net, struct tc_action **a, u32 index,
struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, pedit_net_id); struct tc_action_net *tn = net_generic(net, pedit_net_id);
......
...@@ -58,11 +58,12 @@ static struct tc_action_ops act_police_ops; ...@@ -58,11 +58,12 @@ static struct tc_action_ops act_police_ops;
static int tcf_act_police_walker(struct net *net, struct sk_buff *skb, static int tcf_act_police_walker(struct net *net, struct sk_buff *skb,
struct netlink_callback *cb, int type, struct netlink_callback *cb, int type,
const struct tc_action_ops *ops) const struct tc_action_ops *ops,
struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, police_net_id); struct tc_action_net *tn = net_generic(net, police_net_id);
return tcf_generic_walker(tn, skb, cb, type, ops); return tcf_generic_walker(tn, skb, cb, type, ops, extack);
} }
static const struct nla_policy police_policy[TCA_POLICE_MAX + 1] = { static const struct nla_policy police_policy[TCA_POLICE_MAX + 1] = {
...@@ -74,7 +75,8 @@ static const struct nla_policy police_policy[TCA_POLICE_MAX + 1] = { ...@@ -74,7 +75,8 @@ static const struct nla_policy police_policy[TCA_POLICE_MAX + 1] = {
static int tcf_act_police_init(struct net *net, struct nlattr *nla, static int tcf_act_police_init(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action **a, struct nlattr *est, struct tc_action **a,
int ovr, int bind) int ovr, int bind,
struct netlink_ext_ack *extack)
{ {
int ret = 0, err; int ret = 0, err;
struct nlattr *tb[TCA_POLICE_MAX + 1]; struct nlattr *tb[TCA_POLICE_MAX + 1];
...@@ -304,7 +306,8 @@ static int tcf_act_police_dump(struct sk_buff *skb, struct tc_action *a, ...@@ -304,7 +306,8 @@ static int tcf_act_police_dump(struct sk_buff *skb, struct tc_action *a,
return -1; return -1;
} }
static int tcf_police_search(struct net *net, struct tc_action **a, u32 index) static int tcf_police_search(struct net *net, struct tc_action **a, u32 index,
struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, police_net_id); struct tc_action_net *tn = net_generic(net, police_net_id);
......
...@@ -37,7 +37,7 @@ static const struct nla_policy sample_policy[TCA_SAMPLE_MAX + 1] = { ...@@ -37,7 +37,7 @@ static const struct nla_policy sample_policy[TCA_SAMPLE_MAX + 1] = {
static int tcf_sample_init(struct net *net, struct nlattr *nla, static int tcf_sample_init(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action **a, int ovr, struct nlattr *est, struct tc_action **a, int ovr,
int bind) int bind, struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, sample_net_id); struct tc_action_net *tn = net_generic(net, sample_net_id);
struct nlattr *tb[TCA_SAMPLE_MAX + 1]; struct nlattr *tb[TCA_SAMPLE_MAX + 1];
...@@ -202,14 +202,16 @@ static int tcf_sample_dump(struct sk_buff *skb, struct tc_action *a, ...@@ -202,14 +202,16 @@ static int tcf_sample_dump(struct sk_buff *skb, struct tc_action *a,
static int tcf_sample_walker(struct net *net, struct sk_buff *skb, static int tcf_sample_walker(struct net *net, struct sk_buff *skb,
struct netlink_callback *cb, int type, struct netlink_callback *cb, int type,
const struct tc_action_ops *ops) const struct tc_action_ops *ops,
struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, sample_net_id); struct tc_action_net *tn = net_generic(net, sample_net_id);
return tcf_generic_walker(tn, skb, cb, type, ops); return tcf_generic_walker(tn, skb, cb, type, ops, extack);
} }
static int tcf_sample_search(struct net *net, struct tc_action **a, u32 index) static int tcf_sample_search(struct net *net, struct tc_action **a, u32 index,
struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, sample_net_id); struct tc_action_net *tn = net_generic(net, sample_net_id);
......
...@@ -79,7 +79,7 @@ static const struct nla_policy simple_policy[TCA_DEF_MAX + 1] = { ...@@ -79,7 +79,7 @@ static const struct nla_policy simple_policy[TCA_DEF_MAX + 1] = {
static int tcf_simp_init(struct net *net, struct nlattr *nla, static int tcf_simp_init(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action **a, struct nlattr *est, struct tc_action **a,
int ovr, int bind) int ovr, int bind, struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, simp_net_id); struct tc_action_net *tn = net_generic(net, simp_net_id);
struct nlattr *tb[TCA_DEF_MAX + 1]; struct nlattr *tb[TCA_DEF_MAX + 1];
...@@ -170,14 +170,16 @@ static int tcf_simp_dump(struct sk_buff *skb, struct tc_action *a, ...@@ -170,14 +170,16 @@ static int tcf_simp_dump(struct sk_buff *skb, struct tc_action *a,
static int tcf_simp_walker(struct net *net, struct sk_buff *skb, static int tcf_simp_walker(struct net *net, struct sk_buff *skb,
struct netlink_callback *cb, int type, struct netlink_callback *cb, int type,
const struct tc_action_ops *ops) const struct tc_action_ops *ops,
struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, simp_net_id); struct tc_action_net *tn = net_generic(net, simp_net_id);
return tcf_generic_walker(tn, skb, cb, type, ops); return tcf_generic_walker(tn, skb, cb, type, ops, extack);
} }
static int tcf_simp_search(struct net *net, struct tc_action **a, u32 index) static int tcf_simp_search(struct net *net, struct tc_action **a, u32 index,
struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, simp_net_id); struct tc_action_net *tn = net_generic(net, simp_net_id);
......
...@@ -66,7 +66,7 @@ static const struct nla_policy skbedit_policy[TCA_SKBEDIT_MAX + 1] = { ...@@ -66,7 +66,7 @@ static const struct nla_policy skbedit_policy[TCA_SKBEDIT_MAX + 1] = {
static int tcf_skbedit_init(struct net *net, struct nlattr *nla, static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action **a, struct nlattr *est, struct tc_action **a,
int ovr, int bind) int ovr, int bind, struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, skbedit_net_id); struct tc_action_net *tn = net_generic(net, skbedit_net_id);
struct nlattr *tb[TCA_SKBEDIT_MAX + 1]; struct nlattr *tb[TCA_SKBEDIT_MAX + 1];
...@@ -208,14 +208,16 @@ static int tcf_skbedit_dump(struct sk_buff *skb, struct tc_action *a, ...@@ -208,14 +208,16 @@ static int tcf_skbedit_dump(struct sk_buff *skb, struct tc_action *a,
static int tcf_skbedit_walker(struct net *net, struct sk_buff *skb, static int tcf_skbedit_walker(struct net *net, struct sk_buff *skb,
struct netlink_callback *cb, int type, struct netlink_callback *cb, int type,
const struct tc_action_ops *ops) const struct tc_action_ops *ops,
struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, skbedit_net_id); struct tc_action_net *tn = net_generic(net, skbedit_net_id);
return tcf_generic_walker(tn, skb, cb, type, ops); return tcf_generic_walker(tn, skb, cb, type, ops, extack);
} }
static int tcf_skbedit_search(struct net *net, struct tc_action **a, u32 index) static int tcf_skbedit_search(struct net *net, struct tc_action **a, u32 index,
struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, skbedit_net_id); struct tc_action_net *tn = net_generic(net, skbedit_net_id);
......
...@@ -84,7 +84,7 @@ static const struct nla_policy skbmod_policy[TCA_SKBMOD_MAX + 1] = { ...@@ -84,7 +84,7 @@ static const struct nla_policy skbmod_policy[TCA_SKBMOD_MAX + 1] = {
static int tcf_skbmod_init(struct net *net, struct nlattr *nla, static int tcf_skbmod_init(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action **a, struct nlattr *est, struct tc_action **a,
int ovr, int bind) int ovr, int bind, struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, skbmod_net_id); struct tc_action_net *tn = net_generic(net, skbmod_net_id);
struct nlattr *tb[TCA_SKBMOD_MAX + 1]; struct nlattr *tb[TCA_SKBMOD_MAX + 1];
...@@ -232,14 +232,16 @@ static int tcf_skbmod_dump(struct sk_buff *skb, struct tc_action *a, ...@@ -232,14 +232,16 @@ static int tcf_skbmod_dump(struct sk_buff *skb, struct tc_action *a,
static int tcf_skbmod_walker(struct net *net, struct sk_buff *skb, static int tcf_skbmod_walker(struct net *net, struct sk_buff *skb,
struct netlink_callback *cb, int type, struct netlink_callback *cb, int type,
const struct tc_action_ops *ops) const struct tc_action_ops *ops,
struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, skbmod_net_id); struct tc_action_net *tn = net_generic(net, skbmod_net_id);
return tcf_generic_walker(tn, skb, cb, type, ops); return tcf_generic_walker(tn, skb, cb, type, ops, extack);
} }
static int tcf_skbmod_search(struct net *net, struct tc_action **a, u32 index) static int tcf_skbmod_search(struct net *net, struct tc_action **a, u32 index,
struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, skbmod_net_id); struct tc_action_net *tn = net_generic(net, skbmod_net_id);
......
...@@ -70,7 +70,7 @@ static const struct nla_policy tunnel_key_policy[TCA_TUNNEL_KEY_MAX + 1] = { ...@@ -70,7 +70,7 @@ static const struct nla_policy tunnel_key_policy[TCA_TUNNEL_KEY_MAX + 1] = {
static int tunnel_key_init(struct net *net, struct nlattr *nla, static int tunnel_key_init(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action **a, struct nlattr *est, struct tc_action **a,
int ovr, int bind) int ovr, int bind, struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, tunnel_key_net_id); struct tc_action_net *tn = net_generic(net, tunnel_key_net_id);
struct nlattr *tb[TCA_TUNNEL_KEY_MAX + 1]; struct nlattr *tb[TCA_TUNNEL_KEY_MAX + 1];
...@@ -291,14 +291,16 @@ static int tunnel_key_dump(struct sk_buff *skb, struct tc_action *a, ...@@ -291,14 +291,16 @@ static int tunnel_key_dump(struct sk_buff *skb, struct tc_action *a,
static int tunnel_key_walker(struct net *net, struct sk_buff *skb, static int tunnel_key_walker(struct net *net, struct sk_buff *skb,
struct netlink_callback *cb, int type, struct netlink_callback *cb, int type,
const struct tc_action_ops *ops) const struct tc_action_ops *ops,
struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, tunnel_key_net_id); struct tc_action_net *tn = net_generic(net, tunnel_key_net_id);
return tcf_generic_walker(tn, skb, cb, type, ops); return tcf_generic_walker(tn, skb, cb, type, ops, extack);
} }
static int tunnel_key_search(struct net *net, struct tc_action **a, u32 index) static int tunnel_key_search(struct net *net, struct tc_action **a, u32 index,
struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, tunnel_key_net_id); struct tc_action_net *tn = net_generic(net, tunnel_key_net_id);
......
...@@ -109,7 +109,7 @@ static const struct nla_policy vlan_policy[TCA_VLAN_MAX + 1] = { ...@@ -109,7 +109,7 @@ static const struct nla_policy vlan_policy[TCA_VLAN_MAX + 1] = {
static int tcf_vlan_init(struct net *net, struct nlattr *nla, static int tcf_vlan_init(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action **a, struct nlattr *est, struct tc_action **a,
int ovr, int bind) int ovr, int bind, struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, vlan_net_id); struct tc_action_net *tn = net_generic(net, vlan_net_id);
struct nlattr *tb[TCA_VLAN_MAX + 1]; struct nlattr *tb[TCA_VLAN_MAX + 1];
...@@ -267,14 +267,16 @@ static int tcf_vlan_dump(struct sk_buff *skb, struct tc_action *a, ...@@ -267,14 +267,16 @@ static int tcf_vlan_dump(struct sk_buff *skb, struct tc_action *a,
static int tcf_vlan_walker(struct net *net, struct sk_buff *skb, static int tcf_vlan_walker(struct net *net, struct sk_buff *skb,
struct netlink_callback *cb, int type, struct netlink_callback *cb, int type,
const struct tc_action_ops *ops) const struct tc_action_ops *ops,
struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, vlan_net_id); struct tc_action_net *tn = net_generic(net, vlan_net_id);
return tcf_generic_walker(tn, skb, cb, type, ops); return tcf_generic_walker(tn, skb, cb, type, ops, extack);
} }
static int tcf_vlan_search(struct net *net, struct tc_action **a, u32 index) static int tcf_vlan_search(struct net *net, struct tc_action **a, u32 index,
struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, vlan_net_id); struct tc_action_net *tn = net_generic(net, vlan_net_id);
......
...@@ -1434,7 +1434,7 @@ int tcf_exts_validate(struct net *net, struct tcf_proto *tp, struct nlattr **tb, ...@@ -1434,7 +1434,7 @@ int tcf_exts_validate(struct net *net, struct tcf_proto *tp, struct nlattr **tb,
if (exts->police && tb[exts->police]) { if (exts->police && tb[exts->police]) {
act = tcf_action_init_1(net, tp, tb[exts->police], act = tcf_action_init_1(net, tp, tb[exts->police],
rate_tlv, "police", ovr, rate_tlv, "police", ovr,
TCA_ACT_BIND); TCA_ACT_BIND, extack);
if (IS_ERR(act)) if (IS_ERR(act))
return PTR_ERR(act); return PTR_ERR(act);
...@@ -1447,7 +1447,7 @@ int tcf_exts_validate(struct net *net, struct tcf_proto *tp, struct nlattr **tb, ...@@ -1447,7 +1447,7 @@ int tcf_exts_validate(struct net *net, struct tcf_proto *tp, struct nlattr **tb,
err = tcf_action_init(net, tp, tb[exts->action], err = tcf_action_init(net, tp, tb[exts->action],
rate_tlv, NULL, ovr, TCA_ACT_BIND, rate_tlv, NULL, ovr, TCA_ACT_BIND,
&actions); &actions, extack);
if (err) if (err)
return err; return err;
list_for_each_entry(act, &actions, list) list_for_each_entry(act, &actions, list)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment