Skip to content

Commit

Permalink
net: sched: cls_u32: add extack support
Browse files Browse the repository at this point in the history
This patch adds extack support for the u32 classifier as example for
delete and init callback.

Cc: David Ahern <dsahern@gmail.com>
Signed-off-by: Alexander Aring <aring@mojatatu.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Alexander Aring authored and David S. Miller committed Jan 19, 2018
1 parent 1057c55 commit 4b981db
Showing 1 changed file with 44 additions and 14 deletions.
58 changes: 44 additions & 14 deletions net/sched/cls_u32.c
Original file line number Diff line number Diff line change
Expand Up @@ -689,13 +689,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_MOD(extack, "Not allowed to delete root node");
return -EINVAL;
}

if (ht->refcnt == 1) {
ht->refcnt--;
u32_destroy_hnode(tp, ht);
} else {
NL_SET_ERR_MSG_MOD(extack, "Can not delete in-use filter");
return -EBUSY;
}

Expand Down Expand Up @@ -779,14 +782,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_MOD(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_MOD(extack, "Link hash table not found");
return -EINVAL;
}
ht_down->refcnt++;
}

Expand Down Expand Up @@ -910,28 +917,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_MOD(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_MOD(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_MOD(extack, "Key node id cannot be zero");
return -EINVAL;
}

if (n->flags != flags)
if (n->flags != flags) {
NL_SET_ERR_MSG_MOD(extack, "Key node flags do not match passed flags");
return -EINVAL;
}

new = u32_init_knode(tp, n);
if (!new)
Expand Down Expand Up @@ -965,10 +984,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_MOD(extack, "Exceeded maximum 256 hash buckets");
return -EINVAL;
if (TC_U32_KEY(handle))
}
if (TC_U32_KEY(handle)) {
NL_SET_ERR_MSG_MOD(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;
Expand Down Expand Up @@ -1014,20 +1037,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_MOD(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_MOD(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_MOD(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,
Expand All @@ -1038,6 +1067,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_MOD(extack, "Selector not specified");
err = -EINVAL;
goto erridr;
}
Expand Down

0 comments on commit 4b981db

Please sign in to comment.