Skip to content

Commit

Permalink
Merge branch 'net-sched-cls-add-extack-support'
Browse files Browse the repository at this point in the history
Alexander Aring says:

====================
net: sched: cls: add extack support

this patch adds extack support for TC classifier subsystem. The first
patch fixes some code style issues for this patch series pointed out
by checkpatch. The other patches until the last one prepares extack
handling for the TC classifier subsystem and handle generic extack
errors.

The last patch is an example for u32 classifier to add extack support
inside the callbacks delete and change. There exists a init callback as
well, but most classifier implementation run a kalloc() once to allocate
something. Not necessary _yet_ to add extack support now.

- Alex

Cc: David Ahern <dsahern@gmail.com>

changes since v3:
 - fix accidentally move of config option mismatch message in PATCH 2/8
   correct one is 4/8, detected by kbuildbot (Thank you)
 - Removed patch "net: sched: cls: add extack support for tc_setup_cb_call"
   PATCH 7/8 in version v2 as suggested by Jakub Kicinski (Thank you)
 - changed NL_SET_ERR_MSG to NL_SET_ERR_MSG_MOD as suggested by Jakub Kicinski
   in u32 cls (Thank You)
 - Removed text from cover letter that I was waiting for Jiri's Patches as
   detected by Jamal Hadi Salim (Thank you).

changes since v2:
 - rebased on Jiri's patches (Thank you)
 - several spelling fixes pointed out by Cong Wang (Thank you)
 - several spelling fixes pointed out by David Ahern (Thank you)
 - use David Ahern recommendation if config option is mismatch, but
   combine it with Cong Wang recommendation to put config name into it
   (Thank you)
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Jan 19, 2018
2 parents fd5204c + 4b981db commit 7677fd0
Show file tree
Hide file tree
Showing 14 changed files with 194 additions and 92 deletions.
10 changes: 7 additions & 3 deletions include/net/pkt_cls.h
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,8 @@ tcf_exts_exec(struct sk_buff *skb, struct tcf_exts *exts,

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);
Expand Down Expand Up @@ -556,13 +557,16 @@ static inline int tcf_valid_offset(const struct sk_buff *skb,
#include <net/net_namespace.h>

static inline int
tcf_change_indev(struct net *net, struct nlattr *indev_tlv)
tcf_change_indev(struct net *net, struct nlattr *indev_tlv,
struct netlink_ext_ack *extack)
{
char indev[IFNAMSIZ];
struct net_device *dev;

if (nla_strlcpy(indev, indev_tlv, IFNAMSIZ) >= IFNAMSIZ)
if (nla_strlcpy(indev, indev_tlv, IFNAMSIZ) >= IFNAMSIZ) {
NL_SET_ERR_MSG(extack, "Interface name too long");
return -EINVAL;
}
dev = __dev_get_by_name(net, indev);
if (!dev)
return -ENODEV;
Expand Down
7 changes: 5 additions & 2 deletions include/net/sch_generic.h
Original file line number Diff line number Diff line change
Expand Up @@ -239,8 +239,11 @@ struct tcf_proto_ops {
int (*change)(struct net *net, struct sk_buff *,
struct tcf_proto*, unsigned long,
u32 handle, struct nlattr **,
void **, bool);
int (*delete)(struct tcf_proto*, void *, bool*);
void **, bool,
struct netlink_ext_ack *);
int (*delete)(struct tcf_proto *tp, void *arg,
bool *last,
struct netlink_ext_ack *);
void (*walk)(struct tcf_proto*, struct tcf_walker *arg);
void (*bind_class)(void *, u32, unsigned long);

Expand Down
64 changes: 49 additions & 15 deletions net/sched/cls_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,8 @@ static inline u32 tcf_auto_prio(struct tcf_proto *tp)
}

static struct tcf_proto *tcf_proto_create(const char *kind, u32 protocol,
u32 prio, struct tcf_chain *chain)
u32 prio, struct tcf_chain *chain,
struct netlink_ext_ack *extack)
{
struct tcf_proto *tp;
int err;
Expand All @@ -148,6 +149,7 @@ static struct tcf_proto *tcf_proto_create(const char *kind, u32 protocol,
module_put(tp->ops->owner);
err = -EAGAIN;
} else {
NL_SET_ERR_MSG(extack, "TC classifier not found");
err = -ENOENT;
}
goto errout;
Expand Down Expand Up @@ -935,7 +937,8 @@ static int tfilter_notify(struct net *net, struct sk_buff *oskb,
static int tfilter_del_notify(struct net *net, struct sk_buff *oskb,
struct nlmsghdr *n, struct tcf_proto *tp,
struct tcf_block *block, struct Qdisc *q,
u32 parent, void *fh, bool unicast, bool *last)
u32 parent, void *fh, bool unicast, bool *last,
struct netlink_ext_ack *extack)
{
struct sk_buff *skb;
u32 portid = oskb ? NETLINK_CB(oskb).portid : 0;
Expand All @@ -947,11 +950,12 @@ static int tfilter_del_notify(struct net *net, struct sk_buff *oskb,

if (tcf_fill_node(net, skb, tp, block, q, parent, fh, portid,
n->nlmsg_seq, n->nlmsg_flags, RTM_DELTFILTER) <= 0) {
NL_SET_ERR_MSG(extack, "Failed to build del event notification");
kfree_skb(skb);
return -EINVAL;
}

err = tp->ops->delete(tp, fh, last);
err = tp->ops->delete(tp, fh, last, extack);
if (err) {
kfree_skb(skb);
return err;
Expand All @@ -960,8 +964,11 @@ static int tfilter_del_notify(struct net *net, struct sk_buff *oskb,
if (unicast)
return netlink_unicast(net->rtnl, skb, portid, MSG_DONTWAIT);

return rtnetlink_send(skb, net, portid, RTNLGRP_TC,
n->nlmsg_flags & NLM_F_ECHO);
err = rtnetlink_send(skb, net, portid, RTNLGRP_TC,
n->nlmsg_flags & NLM_F_ECHO);
if (err < 0)
NL_SET_ERR_MSG(extack, "Failed to send filter delete notification");
return err;
}

static void tfilter_notify_chain(struct net *net, struct sk_buff *oskb,
Expand Down Expand Up @@ -1021,8 +1028,10 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n,
if (prio == 0) {
switch (n->nlmsg_type) {
case RTM_DELTFILTER:
if (protocol || t->tcm_handle || tca[TCA_KIND])
if (protocol || t->tcm_handle || tca[TCA_KIND]) {
NL_SET_ERR_MSG(extack, "Cannot flush filters with protocol, handle or kind set");
return -ENOENT;
}
break;
case RTM_NEWTFILTER:
/* If no priority is provided by the user,
Expand All @@ -1035,6 +1044,7 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n,
}
/* fall-through */
default:
NL_SET_ERR_MSG(extack, "Invalid filter command with priority of zero");
return -ENOENT;
}
}
Expand Down Expand Up @@ -1063,23 +1073,31 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n,
parent = q->handle;
} else {
q = qdisc_lookup(dev, TC_H_MAJ(t->tcm_parent));
if (!q)
if (!q) {
NL_SET_ERR_MSG(extack, "Parent Qdisc doesn't exists");
return -EINVAL;
}
}

/* Is it classful? */
cops = q->ops->cl_ops;
if (!cops)
if (!cops) {
NL_SET_ERR_MSG(extack, "Qdisc not classful");
return -EINVAL;
}

if (!cops->tcf_block)
if (!cops->tcf_block) {
NL_SET_ERR_MSG(extack, "Class doesn't support blocks");
return -EOPNOTSUPP;
}

/* Do we search for filter, attached to class? */
if (TC_H_MIN(parent)) {
cl = cops->find(q, parent);
if (cl == 0)
if (cl == 0) {
NL_SET_ERR_MSG(extack, "Specified class doesn't exist");
return -ENOENT;
}
}

/* And the last stroke */
Expand All @@ -1097,12 +1115,14 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n,

chain_index = tca[TCA_CHAIN] ? nla_get_u32(tca[TCA_CHAIN]) : 0;
if (chain_index > TC_ACT_EXT_VAL_MASK) {
NL_SET_ERR_MSG(extack, "Specified chain index exceeds upper limit");
err = -EINVAL;
goto errout;
}
chain = tcf_chain_get(block, chain_index,
n->nlmsg_type == RTM_NEWTFILTER);
if (!chain) {
NL_SET_ERR_MSG(extack, "Cannot find specified filter chain");
err = n->nlmsg_type == RTM_NEWTFILTER ? -ENOMEM : -EINVAL;
goto errout;
}
Expand All @@ -1118,6 +1138,7 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n,
tp = tcf_chain_tp_find(chain, &chain_info, protocol,
prio, prio_allocate);
if (IS_ERR(tp)) {
NL_SET_ERR_MSG(extack, "Filter with specified priority/protocol not found");
err = PTR_ERR(tp);
goto errout;
}
Expand All @@ -1126,12 +1147,14 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n,
/* Proto-tcf does not exist, create new one */

if (tca[TCA_KIND] == NULL || !protocol) {
NL_SET_ERR_MSG(extack, "Filter kind and protocol must be specified");
err = -EINVAL;
goto errout;
}

if (n->nlmsg_type != RTM_NEWTFILTER ||
!(n->nlmsg_flags & NLM_F_CREATE)) {
NL_SET_ERR_MSG(extack, "Need both RTM_NEWTFILTER and NLM_F_CREATE to create a new filter");
err = -ENOENT;
goto errout;
}
Expand All @@ -1140,13 +1163,14 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n,
prio = tcf_auto_prio(tcf_chain_tp_prev(&chain_info));

tp = tcf_proto_create(nla_data(tca[TCA_KIND]),
protocol, prio, chain);
protocol, prio, chain, extack);
if (IS_ERR(tp)) {
err = PTR_ERR(tp);
goto errout;
}
tp_created = 1;
} else if (tca[TCA_KIND] && nla_strcmp(tca[TCA_KIND], tp->ops->kind)) {
NL_SET_ERR_MSG(extack, "Specified filter kind does not match existing one");
err = -EINVAL;
goto errout;
}
Expand All @@ -1165,6 +1189,7 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n,

if (n->nlmsg_type != RTM_NEWTFILTER ||
!(n->nlmsg_flags & NLM_F_CREATE)) {
NL_SET_ERR_MSG(extack, "Need both RTM_NEWTFILTER and NLM_F_CREATE to create a new filter");
err = -ENOENT;
goto errout;
}
Expand All @@ -1176,13 +1201,15 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n,
if (n->nlmsg_flags & NLM_F_EXCL) {
if (tp_created)
tcf_proto_destroy(tp);
NL_SET_ERR_MSG(extack, "Filter already exists");
err = -EEXIST;
goto errout;
}
break;
case RTM_DELTFILTER:
err = tfilter_del_notify(net, skb, n, tp, block,
q, parent, fh, false, &last);
q, parent, fh, false, &last,
extack);
if (err)
goto errout;
if (last) {
Expand All @@ -1193,15 +1220,19 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n,
case RTM_GETTFILTER:
err = tfilter_notify(net, skb, n, tp, block, q, parent,
fh, RTM_NEWTFILTER, true);
if (err < 0)
NL_SET_ERR_MSG(extack, "Failed to send filter notify message");
goto errout;
default:
NL_SET_ERR_MSG(extack, "Invalid netlink message type");
err = -EINVAL;
goto errout;
}
}

err = tp->ops->change(net, skb, tp, cl, t->tcm_handle, tca, &fh,
n->nlmsg_flags & NLM_F_CREATE ? TCA_ACT_NOREPLACE : TCA_ACT_REPLACE);
n->nlmsg_flags & NLM_F_CREATE ? TCA_ACT_NOREPLACE : TCA_ACT_REPLACE,
extack);
if (err == 0) {
if (tp_created)
tcf_chain_tp_insert(chain, &chain_info, tp);
Expand Down Expand Up @@ -1392,7 +1423,8 @@ void tcf_exts_destroy(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
{
Expand Down Expand Up @@ -1425,8 +1457,10 @@ int tcf_exts_validate(struct net *net, struct tcf_proto *tp, struct nlattr **tb,
}
#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;
Expand Down
14 changes: 9 additions & 5 deletions net/sched/cls_basic.c
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,8 @@ static void basic_destroy(struct tcf_proto *tp)
kfree_rcu(head, rcu);
}

static int basic_delete(struct tcf_proto *tp, void *arg, bool *last)
static int basic_delete(struct tcf_proto *tp, void *arg, bool *last,
struct netlink_ext_ack *extack)
{
struct basic_head *head = rtnl_dereference(tp->root);
struct basic_filter *f = arg;
Expand All @@ -152,11 +153,12 @@ static const struct nla_policy basic_policy[TCA_BASIC_MAX + 1] = {
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;

Expand All @@ -175,7 +177,8 @@ static int basic_set_parms(struct net *net, struct tcf_proto *tp,

static int basic_change(struct net *net, struct sk_buff *in_skb,
struct tcf_proto *tp, unsigned long base, u32 handle,
struct nlattr **tca, void **arg, bool ovr)
struct nlattr **tca, void **arg, bool ovr,
struct netlink_ext_ack *extack)
{
int err;
struct basic_head *head = rtnl_dereference(tp->root);
Expand Down Expand Up @@ -221,7 +224,8 @@ static int basic_change(struct net *net, struct sk_buff *in_skb,
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);
Expand Down
13 changes: 8 additions & 5 deletions net/sched/cls_bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,8 @@ static void __cls_bpf_delete(struct tcf_proto *tp, struct cls_bpf_prog *prog)
__cls_bpf_delete_prog(prog);
}

static int cls_bpf_delete(struct tcf_proto *tp, void *arg, bool *last)
static int cls_bpf_delete(struct tcf_proto *tp, void *arg, bool *last,
struct netlink_ext_ack *extack)
{
struct cls_bpf_head *head = rtnl_dereference(tp->root);

Expand Down Expand Up @@ -403,7 +404,8 @@ static int cls_bpf_prog_from_efd(struct nlattr **tb, struct cls_bpf_prog *prog,

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;
Expand All @@ -414,7 +416,7 @@ static int cls_bpf_set_parms(struct net *net, struct tcf_proto *tp,
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;

Expand Down Expand Up @@ -452,7 +454,7 @@ static int cls_bpf_set_parms(struct net *net, struct tcf_proto *tp,
static int cls_bpf_change(struct net *net, struct sk_buff *in_skb,
struct tcf_proto *tp, unsigned long base,
u32 handle, struct nlattr **tca,
void **arg, bool ovr)
void **arg, bool ovr, struct netlink_ext_ack *extack)
{
struct cls_bpf_head *head = rtnl_dereference(tp->root);
struct cls_bpf_prog *oldprog = *arg;
Expand Down Expand Up @@ -500,7 +502,8 @@ static int cls_bpf_change(struct net *net, struct sk_buff *in_skb,
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;

Expand Down
9 changes: 6 additions & 3 deletions net/sched/cls_cgroup.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,8 @@ static void cls_cgroup_destroy_rcu(struct rcu_head *root)
static int cls_cgroup_change(struct net *net, struct sk_buff *in_skb,
struct tcf_proto *tp, unsigned long base,
u32 handle, struct nlattr **tca,
void **arg, bool ovr)
void **arg, bool ovr,
struct netlink_ext_ack *extack)
{
struct nlattr *tb[TCA_CGROUP_MAX + 1];
struct cls_cgroup_head *head = rtnl_dereference(tp->root);
Expand Down Expand Up @@ -121,7 +122,8 @@ static int cls_cgroup_change(struct net *net, struct sk_buff *in_skb,
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;

Expand Down Expand Up @@ -154,7 +156,8 @@ static void cls_cgroup_destroy(struct tcf_proto *tp)
}
}

static int cls_cgroup_delete(struct tcf_proto *tp, void *arg, bool *last)
static int cls_cgroup_delete(struct tcf_proto *tp, void *arg, bool *last,
struct netlink_ext_ack *extack)
{
return -EOPNOTSUPP;
}
Expand Down
Loading

0 comments on commit 7677fd0

Please sign in to comment.