Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4b981dbc authored by Alexander Aring's avatar Alexander Aring Committed by David S. Miller
Browse files

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@gmail.com>
Signed-off-by: default avatarAlexander Aring <aring@mojatatu.com>
Acked-by: default avatarJiri Pirko <jiri@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 1057c55f
Loading
Loading
Loading
Loading
+44 −14
Original line number Diff line number Diff line
@@ -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;
	}

@@ -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++;
		}

@@ -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)
@@ -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;
@@ -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,
@@ -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;
	}