[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20180116172027.22128-9-aring@mojatatu.com>
Date: Tue, 16 Jan 2018 12:20:27 -0500
From: Alexander Aring <aring@...atatu.com>
To: jhs@...atatu.com
Cc: xiyou.wangcong@...il.com, jiri@...nulli.us, davem@...emloft.net,
netdev@...r.kernel.org, kernel@...atatu.com,
Alexander Aring <aring@...atatu.com>,
David Ahern <dsahern@...il.com>
Subject: [PATCH net-next 8/8] net: sched: cls_u32: add extack support
This patch adds extack support for the u32 classifier as example for
delete and init callback.
Cc: David Ahern <dsahern@...il.com>
Signed-off-by: Alexander Aring <aring@...atatu.com>
---
net/sched/cls_u32.c | 66 ++++++++++++++++++++++++++++++++++++++++-------------
1 file changed, 50 insertions(+), 16 deletions(-)
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index 03dc08ab3cf1..69c2fbafd0a3 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -524,8 +524,10 @@ static int u32_replace_hw_hnode(struct tcf_proto *tp, struct tc_u_hnode *h,
offloaded = true;
}
- if (skip_sw && !offloaded)
+ if (skip_sw && !offloaded) {
+ NL_SET_ERR_MSG(extack, "Failed to offload filter requested with skip sw");
return -EINVAL;
+ }
return 0;
}
@@ -575,8 +577,10 @@ static int u32_replace_hw_knode(struct tcf_proto *tp, struct tc_u_knode *n,
n->flags |= TCA_CLS_FLAGS_IN_HW;
}
- if (skip_sw && !(n->flags & TCA_CLS_FLAGS_IN_HW))
+ if (skip_sw && !(n->flags & TCA_CLS_FLAGS_IN_HW)) {
+ NL_SET_ERR_MSG(extack, "Failed to offload filter requested with skip sw");
return -EINVAL;
+ }
return 0;
}
@@ -690,13 +694,16 @@ static int u32_delete(struct tcf_proto *tp, void *arg, bool *last,
goto out;
}
- if (root_ht == ht)
+ if (root_ht == ht) {
+ NL_SET_ERR_MSG(extack, "Not allowd to delete root node");
return -EINVAL;
+ }
if (ht->refcnt == 1) {
ht->refcnt--;
u32_destroy_hnode(tp, ht);
} else {
+ NL_SET_ERR_MSG(extack, "Can not delete in-use filter");
return -EBUSY;
}
@@ -780,14 +787,18 @@ static int u32_set_parms(struct net *net, struct tcf_proto *tp,
u32 handle = nla_get_u32(tb[TCA_U32_LINK]);
struct tc_u_hnode *ht_down = NULL, *ht_old;
- if (TC_U32_KEY(handle))
+ if (TC_U32_KEY(handle)) {
+ NL_SET_ERR_MSG(extack, "u32 Link handle must be a hash table");
return -EINVAL;
+ }
if (handle) {
ht_down = u32_lookup_ht(ht->tp_c, handle);
- if (!ht_down)
+ if (!ht_down) {
+ NL_SET_ERR_MSG(extack, "Link hash table not found");
return -EINVAL;
+ }
ht_down->refcnt++;
}
@@ -911,28 +922,40 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
size_t size;
#endif
- if (!opt)
- return handle ? -EINVAL : 0;
+ if (!opt) {
+ if (handle) {
+ NL_SET_ERR_MSG(extack, "Filter handle requires options");
+ return -EINVAL;
+ } else {
+ return 0;
+ }
+ }
- err = nla_parse_nested(tb, TCA_U32_MAX, opt, u32_policy, NULL);
+ err = nla_parse_nested(tb, TCA_U32_MAX, opt, u32_policy, extack);
if (err < 0)
return err;
if (tb[TCA_U32_FLAGS]) {
flags = nla_get_u32(tb[TCA_U32_FLAGS]);
- if (!tc_flags_valid(flags))
+ if (!tc_flags_valid(flags)) {
+ NL_SET_ERR_MSG(extack, "Invalid filter flags");
return -EINVAL;
+ }
}
n = *arg;
if (n) {
struct tc_u_knode *new;
- if (TC_U32_KEY(n->handle) == 0)
+ if (TC_U32_KEY(n->handle) == 0) {
+ NL_SET_ERR_MSG(extack, "Key node id cannot be zero");
return -EINVAL;
+ }
- if (n->flags != flags)
+ if (n->flags != flags) {
+ NL_SET_ERR_MSG(extack, "Key node flags do not match passed flags");
return -EINVAL;
+ }
new = u32_init_knode(tp, n);
if (!new)
@@ -966,10 +989,14 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
if (tb[TCA_U32_DIVISOR]) {
unsigned int divisor = nla_get_u32(tb[TCA_U32_DIVISOR]);
- if (--divisor > 0x100)
+ if (--divisor > 0x100) {
+ NL_SET_ERR_MSG(extack, "Exceeded maximum 256 hash buckets");
return -EINVAL;
- if (TC_U32_KEY(handle))
+ }
+ if (TC_U32_KEY(handle)) {
+ NL_SET_ERR_MSG(extack, "Divisor can only be used on a hash table");
return -EINVAL;
+ }
ht = kzalloc(sizeof(*ht) + divisor*sizeof(void *), GFP_KERNEL);
if (ht == NULL)
return -ENOBUFS;
@@ -1015,20 +1042,26 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
htid = ht->handle;
} else {
ht = u32_lookup_ht(tp->data, TC_U32_HTID(htid));
- if (!ht)
+ if (!ht) {
+ NL_SET_ERR_MSG(extack, "Specified hash table not found");
return -EINVAL;
+ }
}
} else {
ht = rtnl_dereference(tp->root);
htid = ht->handle;
}
- if (ht->divisor < TC_U32_HASH(htid))
+ if (ht->divisor < TC_U32_HASH(htid)) {
+ NL_SET_ERR_MSG(extack, "Specified hash table buckets exceed configured value");
return -EINVAL;
+ }
if (handle) {
- if (TC_U32_HTID(handle) && TC_U32_HTID(handle ^ htid))
+ if (TC_U32_HTID(handle) && TC_U32_HTID(handle ^ htid)) {
+ NL_SET_ERR_MSG(extack, "Handle specified hash table address mismatch");
return -EINVAL;
+ }
handle = htid | TC_U32_NODE(handle);
err = idr_alloc_ext(&ht->handle_idr, NULL, NULL,
handle, handle + 1,
@@ -1039,6 +1072,7 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
handle = gen_new_kid(ht, htid);
if (tb[TCA_U32_SEL] == NULL) {
+ NL_SET_ERR_MSG(extack, "Selector not specified");
err = -EINVAL;
goto erridr;
}
--
2.11.0
Powered by blists - more mailing lists