From mboxrd@z Thu Jan 1 00:00:00 1970 From: Alexander Aring Subject: [PATCH net-next 8/8] net: sched: cls_u32: add extack support Date: Tue, 16 Jan 2018 12:20:27 -0500 Message-ID: <20180116172027.22128-9-aring@mojatatu.com> References: <20180116172027.22128-1-aring@mojatatu.com> Cc: xiyou.wangcong@gmail.com, jiri@resnulli.us, davem@davemloft.net, netdev@vger.kernel.org, kernel@mojatatu.com, Alexander Aring , David Ahern To: jhs@mojatatu.com Return-path: Received: from mail-it0-f67.google.com ([209.85.214.67]:33195 "EHLO mail-it0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751118AbeAPRU7 (ORCPT ); Tue, 16 Jan 2018 12:20:59 -0500 Received: by mail-it0-f67.google.com with SMTP id c102so12112645itd.0 for ; Tue, 16 Jan 2018 09:20:59 -0800 (PST) In-Reply-To: <20180116172027.22128-1-aring@mojatatu.com> Sender: netdev-owner@vger.kernel.org List-ID: This patch adds extack support for the u32 classifier as example for delete and init callback. Cc: David Ahern Signed-off-by: Alexander Aring --- 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