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

Commit add93b61 authored by Patrick McHardy's avatar Patrick McHardy Committed by David S. Miller
Browse files

[NET_SCHED]: Convert classifiers from rtnetlink to new netlink API

parent 1e90474c
Loading
Loading
Loading
Loading
+5 −5
Original line number Diff line number Diff line
@@ -129,8 +129,8 @@ tcf_exts_exec(struct sk_buff *skb, struct tcf_exts *exts,
	return 0;
}

extern int tcf_exts_validate(struct tcf_proto *tp, struct rtattr **tb,
	                     struct rtattr *rate_tlv, struct tcf_exts *exts,
extern int tcf_exts_validate(struct tcf_proto *tp, struct nlattr **tb,
	                     struct nlattr *rate_tlv, struct tcf_exts *exts,
	                     struct tcf_ext_map *map);
extern void tcf_exts_destroy(struct tcf_proto *tp, struct tcf_exts *exts);
extern void tcf_exts_change(struct tcf_proto *tp, struct tcf_exts *dst,
@@ -247,7 +247,7 @@ struct tcf_ematch_ops

extern int tcf_em_register(struct tcf_ematch_ops *);
extern int tcf_em_unregister(struct tcf_ematch_ops *);
extern int tcf_em_tree_validate(struct tcf_proto *, struct rtattr *,
extern int tcf_em_tree_validate(struct tcf_proto *, struct nlattr *,
				struct tcf_ematch_tree *);
extern void tcf_em_tree_destroy(struct tcf_proto *, struct tcf_ematch_tree *);
extern int tcf_em_tree_dump(struct sk_buff *, struct tcf_ematch_tree *, int);
@@ -338,9 +338,9 @@ static inline int tcf_valid_offset(const struct sk_buff *skb,
#include <net/net_namespace.h>

static inline int
tcf_change_indev(struct tcf_proto *tp, char *indev, struct rtattr *indev_tlv)
tcf_change_indev(struct tcf_proto *tp, char *indev, struct nlattr *indev_tlv)
{
	if (rtattr_strlcpy(indev, indev_tlv, IFNAMSIZ) >= IFNAMSIZ)
	if (nla_strlcpy(indev, indev_tlv, IFNAMSIZ) >= IFNAMSIZ)
		return -EINVAL;
	return 0;
}
+1 −1
Original line number Diff line number Diff line
@@ -126,7 +126,7 @@ struct tcf_proto_ops
	unsigned long		(*get)(struct tcf_proto*, u32 handle);
	void			(*put)(struct tcf_proto*, unsigned long);
	int			(*change)(struct tcf_proto*, unsigned long,
					u32 handle, struct rtattr **,
					u32 handle, struct nlattr **,
					unsigned long *);
	int			(*delete)(struct tcf_proto*, unsigned long);
	void			(*walk)(struct tcf_proto*, struct tcf_walker *arg);
+35 −30
Original line number Diff line number Diff line
@@ -38,14 +38,14 @@ static DEFINE_RWLOCK(cls_mod_lock);

/* Find classifier type by string name */

static struct tcf_proto_ops *tcf_proto_lookup_ops(struct rtattr *kind)
static struct tcf_proto_ops *tcf_proto_lookup_ops(struct nlattr *kind)
{
	struct tcf_proto_ops *t = NULL;

	if (kind) {
		read_lock(&cls_mod_lock);
		for (t = tcf_proto_base; t; t = t->next) {
			if (rtattr_strcmp(kind, t->kind) == 0) {
			if (nla_strcmp(kind, t->kind) == 0) {
				if (!try_module_get(t->owner))
					t = NULL;
				break;
@@ -118,7 +118,7 @@ static inline u32 tcf_auto_prio(struct tcf_proto *tp)
static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
{
	struct net *net = skb->sk->sk_net;
	struct rtattr **tca;
	struct nlattr *tca[TCA_MAX + 1];
	struct tcmsg *t;
	u32 protocol;
	u32 prio;
@@ -138,7 +138,6 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
		return -EINVAL;

replay:
	tca = arg;
	t = NLMSG_DATA(n);
	protocol = TC_H_MIN(t->tcm_info);
	prio = TC_H_MAJ(t->tcm_info);
@@ -160,6 +159,10 @@ replay:
	if (dev == NULL)
		return -ENODEV;

	err = nlmsg_parse(n, sizeof(*t), tca, TCA_MAX, NULL);
	if (err < 0)
		return err;

	/* Find qdisc */
	if (!parent) {
		q = dev->qdisc_sleeping;
@@ -202,7 +205,7 @@ replay:
	if (tp == NULL) {
		/* Proto-tcf does not exist, create new one */

		if (tca[TCA_KIND-1] == NULL || !protocol)
		if (tca[TCA_KIND] == NULL || !protocol)
			goto errout;

		err = -ENOENT;
@@ -217,14 +220,14 @@ replay:
		if (tp == NULL)
			goto errout;
		err = -EINVAL;
		tp_ops = tcf_proto_lookup_ops(tca[TCA_KIND-1]);
		tp_ops = tcf_proto_lookup_ops(tca[TCA_KIND]);
		if (tp_ops == NULL) {
#ifdef CONFIG_KMOD
			struct rtattr *kind = tca[TCA_KIND-1];
			struct nlattr *kind = tca[TCA_KIND];
			char name[IFNAMSIZ];

			if (kind != NULL &&
			    rtattr_strlcpy(name, kind, IFNAMSIZ) < IFNAMSIZ) {
			    nla_strlcpy(name, kind, IFNAMSIZ) < IFNAMSIZ) {
				rtnl_unlock();
				request_module("cls_%s", name);
				rtnl_lock();
@@ -263,7 +266,7 @@ replay:
		*back = tp;
		qdisc_unlock_tree(dev);

	} else if (tca[TCA_KIND-1] && rtattr_strcmp(tca[TCA_KIND-1], tp->ops->kind))
	} else if (tca[TCA_KIND] && nla_strcmp(tca[TCA_KIND], tp->ops->kind))
		goto errout;

	fh = tp->ops->get(tp, t->tcm_handle);
@@ -333,18 +336,18 @@ static int tcf_fill_node(struct sk_buff *skb, struct tcf_proto *tp,
	tcm->tcm_ifindex = tp->q->dev->ifindex;
	tcm->tcm_parent = tp->classid;
	tcm->tcm_info = TC_H_MAKE(tp->prio, tp->protocol);
	RTA_PUT(skb, TCA_KIND, IFNAMSIZ, tp->ops->kind);
	NLA_PUT(skb, TCA_KIND, IFNAMSIZ, tp->ops->kind);
	tcm->tcm_handle = fh;
	if (RTM_DELTFILTER != event) {
		tcm->tcm_handle = 0;
		if (tp->ops->dump && tp->ops->dump(tp, fh, skb, tcm) < 0)
			goto rtattr_failure;
			goto nla_put_failure;
	}
	nlh->nlmsg_len = skb_tail_pointer(skb) - b;
	return skb->len;

nlmsg_failure:
rtattr_failure:
nla_put_failure:
	nlmsg_trim(skb, b);
	return -1;
}
@@ -476,8 +479,8 @@ void tcf_exts_destroy(struct tcf_proto *tp, struct tcf_exts *exts)
}
EXPORT_SYMBOL(tcf_exts_destroy);

int tcf_exts_validate(struct tcf_proto *tp, struct rtattr **tb,
		  struct rtattr *rate_tlv, struct tcf_exts *exts,
int tcf_exts_validate(struct tcf_proto *tp, struct nlattr **tb,
		  struct nlattr *rate_tlv, struct tcf_exts *exts,
		  struct tcf_ext_map *map)
{
	memset(exts, 0, sizeof(*exts));
@@ -487,8 +490,9 @@ int tcf_exts_validate(struct tcf_proto *tp, struct rtattr **tb,
		int err;
		struct tc_action *act;

		if (map->police && tb[map->police-1]) {
			act = tcf_action_init_1(tb[map->police-1], rate_tlv,
		if (map->police && tb[map->police]) {
			act = tcf_action_init_1((struct rtattr *)tb[map->police],
						(struct rtattr *)rate_tlv,
						"police", TCA_ACT_NOREPLACE,
						TCA_ACT_BIND, &err);
			if (act == NULL)
@@ -496,8 +500,9 @@ int tcf_exts_validate(struct tcf_proto *tp, struct rtattr **tb,

			act->type = TCA_OLD_COMPAT;
			exts->action = act;
		} else if (map->action && tb[map->action-1]) {
			act = tcf_action_init(tb[map->action-1], rate_tlv, NULL,
		} else if (map->action && tb[map->action]) {
			act = tcf_action_init((struct rtattr *)tb[map->action],
					      (struct rtattr *)rate_tlv, NULL,
				TCA_ACT_NOREPLACE, TCA_ACT_BIND, &err);
			if (act == NULL)
				return err;
@@ -506,8 +511,8 @@ int tcf_exts_validate(struct tcf_proto *tp, struct rtattr **tb,
		}
	}
#else
	if ((map->action && tb[map->action-1]) ||
	    (map->police && tb[map->police-1]))
	if ((map->action && tb[map->action]) ||
	    (map->police && tb[map->police]))
		return -EOPNOTSUPP;
#endif

@@ -541,23 +546,23 @@ int tcf_exts_dump(struct sk_buff *skb, struct tcf_exts *exts,
		 * to work with both old and new modes of entering
		 * tc data even if iproute2  was newer - jhs
		 */
		struct rtattr *p_rta = (struct rtattr *)skb_tail_pointer(skb);
		struct nlattr *p_rta = (struct nlattr *)skb_tail_pointer(skb);

		if (exts->action->type != TCA_OLD_COMPAT) {
			RTA_PUT(skb, map->action, 0, NULL);
			NLA_PUT(skb, map->action, 0, NULL);
			if (tcf_action_dump(skb, exts->action, 0, 0) < 0)
				goto rtattr_failure;
			p_rta->rta_len = skb_tail_pointer(skb) - (u8 *)p_rta;
				goto nla_put_failure;
			p_rta->nla_len = skb_tail_pointer(skb) - (u8 *)p_rta;
		} else if (map->police) {
			RTA_PUT(skb, map->police, 0, NULL);
			NLA_PUT(skb, map->police, 0, NULL);
			if (tcf_action_dump_old(skb, exts->action, 0, 0) < 0)
				goto rtattr_failure;
			p_rta->rta_len = skb_tail_pointer(skb) - (u8 *)p_rta;
				goto nla_put_failure;
			p_rta->nla_len = skb_tail_pointer(skb) - (u8 *)p_rta;
		}
	}
#endif
	return 0;
rtattr_failure: __attribute__ ((unused))
nla_put_failure: __attribute__ ((unused))
	return -1;
}
EXPORT_SYMBOL(tcf_exts_dump);
@@ -569,10 +574,10 @@ int tcf_exts_dump_stats(struct sk_buff *skb, struct tcf_exts *exts,
#ifdef CONFIG_NET_CLS_ACT
	if (exts->action)
		if (tcf_action_copy_stats(skb, exts->action, 1) < 0)
			goto rtattr_failure;
			goto nla_put_failure;
#endif
	return 0;
rtattr_failure: __attribute__ ((unused))
nla_put_failure: __attribute__ ((unused))
	return -1;
}
EXPORT_SYMBOL(tcf_exts_dump_stats);
+20 −20
Original line number Diff line number Diff line
@@ -130,27 +130,27 @@ static int basic_delete(struct tcf_proto *tp, unsigned long arg)
}

static inline int basic_set_parms(struct tcf_proto *tp, struct basic_filter *f,
				  unsigned long base, struct rtattr **tb,
				  struct rtattr *est)
				  unsigned long base, struct nlattr **tb,
				  struct nlattr *est)
{
	int err = -EINVAL;
	struct tcf_exts e;
	struct tcf_ematch_tree t;

	if (tb[TCA_BASIC_CLASSID-1])
		if (RTA_PAYLOAD(tb[TCA_BASIC_CLASSID-1]) < sizeof(u32))
	if (tb[TCA_BASIC_CLASSID])
		if (nla_len(tb[TCA_BASIC_CLASSID]) < sizeof(u32))
			return err;

	err = tcf_exts_validate(tp, tb, est, &e, &basic_ext_map);
	if (err < 0)
		return err;

	err = tcf_em_tree_validate(tp, tb[TCA_BASIC_EMATCHES-1], &t);
	err = tcf_em_tree_validate(tp, tb[TCA_BASIC_EMATCHES], &t);
	if (err < 0)
		goto errout;

	if (tb[TCA_BASIC_CLASSID-1]) {
		f->res.classid = *(u32*)RTA_DATA(tb[TCA_BASIC_CLASSID-1]);
	if (tb[TCA_BASIC_CLASSID]) {
		f->res.classid = *(u32*)nla_data(tb[TCA_BASIC_CLASSID]);
		tcf_bind_filter(tp, &f->res, base);
	}

@@ -164,23 +164,23 @@ errout:
}

static int basic_change(struct tcf_proto *tp, unsigned long base, u32 handle,
			struct rtattr **tca, unsigned long *arg)
			struct nlattr **tca, unsigned long *arg)
{
	int err = -EINVAL;
	struct basic_head *head = (struct basic_head *) tp->root;
	struct rtattr *tb[TCA_BASIC_MAX];
	struct nlattr *tb[TCA_BASIC_MAX + 1];
	struct basic_filter *f = (struct basic_filter *) *arg;

	if (tca[TCA_OPTIONS-1] == NULL)
	if (tca[TCA_OPTIONS] == NULL)
		return -EINVAL;

	if (rtattr_parse_nested(tb, TCA_BASIC_MAX, tca[TCA_OPTIONS-1]) < 0)
	if (nla_parse_nested(tb, TCA_BASIC_MAX, tca[TCA_OPTIONS], NULL) < 0)
		return -EINVAL;

	if (f != NULL) {
		if (handle && f->handle != handle)
			return -EINVAL;
		return basic_set_parms(tp, f, base, tb, tca[TCA_RATE-1]);
		return basic_set_parms(tp, f, base, tb, tca[TCA_RATE]);
	}

	err = -ENOBUFS;
@@ -206,7 +206,7 @@ static int basic_change(struct tcf_proto *tp, unsigned long base, u32 handle,
		f->handle = head->hgenerator;
	}

	err = basic_set_parms(tp, f, base, tb, tca[TCA_RATE-1]);
	err = basic_set_parms(tp, f, base, tb, tca[TCA_RATE]);
	if (err < 0)
		goto errout;

@@ -246,27 +246,27 @@ static int basic_dump(struct tcf_proto *tp, unsigned long fh,
{
	struct basic_filter *f = (struct basic_filter *) fh;
	unsigned char *b = skb_tail_pointer(skb);
	struct rtattr *rta;
	struct nlattr *nla;

	if (f == NULL)
		return skb->len;

	t->tcm_handle = f->handle;

	rta = (struct rtattr *) b;
	RTA_PUT(skb, TCA_OPTIONS, 0, NULL);
	nla = (struct nlattr *) b;
	NLA_PUT(skb, TCA_OPTIONS, 0, NULL);

	if (f->res.classid)
		RTA_PUT(skb, TCA_BASIC_CLASSID, sizeof(u32), &f->res.classid);
		NLA_PUT(skb, TCA_BASIC_CLASSID, sizeof(u32), &f->res.classid);

	if (tcf_exts_dump(skb, &f->exts, &basic_ext_map) < 0 ||
	    tcf_em_tree_dump(skb, &f->ematches, TCA_BASIC_EMATCHES) < 0)
		goto rtattr_failure;
		goto nla_put_failure;

	rta->rta_len = skb_tail_pointer(skb) - b;
	nla->nla_len = skb_tail_pointer(skb) - b;
	return skb->len;

rtattr_failure:
nla_put_failure:
	nlmsg_trim(skb, b);
	return -1;
}
+27 −27
Original line number Diff line number Diff line
@@ -188,37 +188,37 @@ out:

static int
fw_change_attrs(struct tcf_proto *tp, struct fw_filter *f,
	struct rtattr **tb, struct rtattr **tca, unsigned long base)
	struct nlattr **tb, struct nlattr **tca, unsigned long base)
{
	struct fw_head *head = (struct fw_head *)tp->root;
	struct tcf_exts e;
	u32 mask;
	int err;

	err = tcf_exts_validate(tp, tb, tca[TCA_RATE-1], &e, &fw_ext_map);
	err = tcf_exts_validate(tp, tb, tca[TCA_RATE], &e, &fw_ext_map);
	if (err < 0)
		return err;

	err = -EINVAL;
	if (tb[TCA_FW_CLASSID-1]) {
		if (RTA_PAYLOAD(tb[TCA_FW_CLASSID-1]) != sizeof(u32))
	if (tb[TCA_FW_CLASSID]) {
		if (nla_len(tb[TCA_FW_CLASSID]) != sizeof(u32))
			goto errout;
		f->res.classid = *(u32*)RTA_DATA(tb[TCA_FW_CLASSID-1]);
		f->res.classid = *(u32*)nla_data(tb[TCA_FW_CLASSID]);
		tcf_bind_filter(tp, &f->res, base);
	}

#ifdef CONFIG_NET_CLS_IND
	if (tb[TCA_FW_INDEV-1]) {
		err = tcf_change_indev(tp, f->indev, tb[TCA_FW_INDEV-1]);
	if (tb[TCA_FW_INDEV]) {
		err = tcf_change_indev(tp, f->indev, tb[TCA_FW_INDEV]);
		if (err < 0)
			goto errout;
	}
#endif /* CONFIG_NET_CLS_IND */

	if (tb[TCA_FW_MASK-1]) {
		if (RTA_PAYLOAD(tb[TCA_FW_MASK-1]) != sizeof(u32))
	if (tb[TCA_FW_MASK]) {
		if (nla_len(tb[TCA_FW_MASK]) != sizeof(u32))
			goto errout;
		mask = *(u32*)RTA_DATA(tb[TCA_FW_MASK-1]);
		mask = *(u32*)nla_data(tb[TCA_FW_MASK]);
		if (mask != head->mask)
			goto errout;
	} else if (head->mask != 0xFFFFFFFF)
@@ -234,19 +234,19 @@ errout:

static int fw_change(struct tcf_proto *tp, unsigned long base,
		     u32 handle,
		     struct rtattr **tca,
		     struct nlattr **tca,
		     unsigned long *arg)
{
	struct fw_head *head = (struct fw_head*)tp->root;
	struct fw_filter *f = (struct fw_filter *) *arg;
	struct rtattr *opt = tca[TCA_OPTIONS-1];
	struct rtattr *tb[TCA_FW_MAX];
	struct nlattr *opt = tca[TCA_OPTIONS];
	struct nlattr *tb[TCA_FW_MAX + 1];
	int err;

	if (!opt)
		return handle ? -EINVAL : 0;

	if (rtattr_parse_nested(tb, TCA_FW_MAX, opt) < 0)
	if (nla_parse_nested(tb, TCA_FW_MAX, opt, NULL) < 0)
		return -EINVAL;

	if (f != NULL) {
@@ -260,10 +260,10 @@ static int fw_change(struct tcf_proto *tp, unsigned long base,

	if (head == NULL) {
		u32 mask = 0xFFFFFFFF;
		if (tb[TCA_FW_MASK-1]) {
			if (RTA_PAYLOAD(tb[TCA_FW_MASK-1]) != sizeof(u32))
		if (tb[TCA_FW_MASK]) {
			if (nla_len(tb[TCA_FW_MASK]) != sizeof(u32))
				return -EINVAL;
			mask = *(u32*)RTA_DATA(tb[TCA_FW_MASK-1]);
			mask = *(u32*)nla_data(tb[TCA_FW_MASK]);
		}

		head = kzalloc(sizeof(struct fw_head), GFP_KERNEL);
@@ -333,7 +333,7 @@ static int fw_dump(struct tcf_proto *tp, unsigned long fh,
	struct fw_head *head = (struct fw_head *)tp->root;
	struct fw_filter *f = (struct fw_filter*)fh;
	unsigned char *b = skb_tail_pointer(skb);
	struct rtattr *rta;
	struct nlattr *nla;

	if (f == NULL)
		return skb->len;
@@ -343,29 +343,29 @@ static int fw_dump(struct tcf_proto *tp, unsigned long fh,
	if (!f->res.classid && !tcf_exts_is_available(&f->exts))
		return skb->len;

	rta = (struct rtattr*)b;
	RTA_PUT(skb, TCA_OPTIONS, 0, NULL);
	nla = (struct nlattr*)b;
	NLA_PUT(skb, TCA_OPTIONS, 0, NULL);

	if (f->res.classid)
		RTA_PUT(skb, TCA_FW_CLASSID, 4, &f->res.classid);
		NLA_PUT(skb, TCA_FW_CLASSID, 4, &f->res.classid);
#ifdef CONFIG_NET_CLS_IND
	if (strlen(f->indev))
		RTA_PUT(skb, TCA_FW_INDEV, IFNAMSIZ, f->indev);
		NLA_PUT(skb, TCA_FW_INDEV, IFNAMSIZ, f->indev);
#endif /* CONFIG_NET_CLS_IND */
	if (head->mask != 0xFFFFFFFF)
		RTA_PUT(skb, TCA_FW_MASK, 4, &head->mask);
		NLA_PUT(skb, TCA_FW_MASK, 4, &head->mask);

	if (tcf_exts_dump(skb, &f->exts, &fw_ext_map) < 0)
		goto rtattr_failure;
		goto nla_put_failure;

	rta->rta_len = skb_tail_pointer(skb) - b;
	nla->nla_len = skb_tail_pointer(skb) - b;

	if (tcf_exts_dump_stats(skb, &f->exts, &fw_ext_map) < 0)
		goto rtattr_failure;
		goto nla_put_failure;

	return skb->len;

rtattr_failure:
nla_put_failure:
	nlmsg_trim(skb, b);
	return -1;
}
Loading