act_api.c 38.4 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
/*
 * net/sched/act_api.c	Packet action API.
 *
 *		This program is free software; you can redistribute it and/or
 *		modify it under the terms of the GNU General Public License
 *		as published by the Free Software Foundation; either version
 *		2 of the License, or (at your option) any later version.
 *
 * Author:	Jamal Hadi Salim
 *
 *
 */

#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/errno.h>
18
#include <linux/slab.h>
L
Linus Torvalds 已提交
19 20 21
#include <linux/skbuff.h>
#include <linux/init.h>
#include <linux/kmod.h>
22
#include <linux/err.h>
23
#include <linux/module.h>
24 25
#include <linux/rhashtable.h>
#include <linux/list.h>
26 27
#include <net/net_namespace.h>
#include <net/sock.h>
L
Linus Torvalds 已提交
28
#include <net/sch_generic.h>
29
#include <net/pkt_cls.h>
L
Linus Torvalds 已提交
30
#include <net/act_api.h>
31
#include <net/netlink.h>
L
Linus Torvalds 已提交
32

33 34 35 36 37 38
static int tcf_action_goto_chain_init(struct tc_action *a, struct tcf_proto *tp)
{
	u32 chain_index = a->tcfa_action & TC_ACT_EXT_VAL_MASK;

	if (!tp)
		return -EINVAL;
39
	a->goto_chain = tcf_chain_get(tp->chain->block, chain_index, true);
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
	if (!a->goto_chain)
		return -ENOMEM;
	return 0;
}

static void tcf_action_goto_chain_fini(struct tc_action *a)
{
	tcf_chain_put(a->goto_chain);
}

static void tcf_action_goto_chain_exec(const struct tc_action *a,
				       struct tcf_result *res)
{
	const struct tcf_chain *chain = a->goto_chain;

	res->goto_tp = rcu_dereference_bh(chain->filter_chain);
}

58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
static void tcf_free_cookie_rcu(struct rcu_head *p)
{
	struct tc_cookie *cookie = container_of(p, struct tc_cookie, rcu);

	kfree(cookie->data);
	kfree(cookie);
}

static void tcf_set_action_cookie(struct tc_cookie __rcu **old_cookie,
				  struct tc_cookie *new_cookie)
{
	struct tc_cookie *old;

	old = xchg(old_cookie, new_cookie);
	if (old)
		call_rcu(&old->rcu, tcf_free_cookie_rcu);
}

C
Cong Wang 已提交
76 77 78 79 80 81
/* XXX: For standalone actions, we don't need a RCU grace period either, because
 * actions are always connected to filters and filters are already destroyed in
 * RCU callbacks, so after a RCU grace period actions are already disconnected
 * from filters. Readers later can not find us.
 */
static void free_tcf(struct tc_action *p)
82 83 84
{
	free_percpu(p->cpu_bstats);
	free_percpu(p->cpu_qstats);
85

86
	tcf_set_action_cookie(&p->act_cookie, NULL);
87 88
	if (p->goto_chain)
		tcf_action_goto_chain_fini(p);
89

90 91 92
	kfree(p);
}

93
static void tcf_action_cleanup(struct tc_action *p)
94
{
95 96 97
	if (p->ops->cleanup)
		p->ops->cleanup(p);

98
	gen_kill_estimator(&p->tcfa_rate_est);
C
Cong Wang 已提交
99
	free_tcf(p);
100 101
}

102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
static int __tcf_action_put(struct tc_action *p, bool bind)
{
	struct tcf_idrinfo *idrinfo = p->idrinfo;

	if (refcount_dec_and_lock(&p->tcfa_refcnt, &idrinfo->lock)) {
		if (bind)
			atomic_dec(&p->tcfa_bindcnt);
		idr_remove(&idrinfo->action_idr, p->tcfa_index);
		spin_unlock(&idrinfo->lock);

		tcf_action_cleanup(p);
		return 1;
	}

	if (bind)
		atomic_dec(&p->tcfa_bindcnt);

	return 0;
}

122
int __tcf_idr_release(struct tc_action *p, bool bind, bool strict)
123 124 125
{
	int ret = 0;

126 127 128 129 130 131 132 133 134 135 136 137
	/* Release with strict==1 and bind==0 is only called through act API
	 * interface (classifiers always bind). Only case when action with
	 * positive reference count and zero bind count can exist is when it was
	 * also created with act API (unbinding last classifier will destroy the
	 * action if it was created by classifier). So only case when bind count
	 * can be changed after initial check is when unbound action is
	 * destroyed by act API while classifier binds to action with same id
	 * concurrently. This result either creation of new action(same behavior
	 * as before), or reusing existing action if concurrent process
	 * increments reference count before action is deleted. Both scenarios
	 * are acceptable.
	 */
138
	if (p) {
139
		if (!bind && strict && atomic_read(&p->tcfa_bindcnt) > 0)
140
			return -EPERM;
141

142
		if (__tcf_action_put(p, bind))
143
			ret = ACT_P_DELETED;
144
	}
145

146 147
	return ret;
}
148
EXPORT_SYMBOL(__tcf_idr_release);
149

150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
static size_t tcf_action_shared_attrs_size(const struct tc_action *act)
{
	u32 cookie_len = 0;

	if (act->act_cookie)
		cookie_len = nla_total_size(act->act_cookie->len);

	return  nla_total_size(0) /* action number nested */
		+ nla_total_size(IFNAMSIZ) /* TCA_ACT_KIND */
		+ cookie_len /* TCA_ACT_COOKIE */
		+ nla_total_size(0) /* TCA_ACT_STATS nested */
		/* TCA_STATS_BASIC */
		+ nla_total_size_64bit(sizeof(struct gnet_stats_basic))
		/* TCA_STATS_QUEUE */
		+ nla_total_size_64bit(sizeof(struct gnet_stats_queue))
		+ nla_total_size(0) /* TCA_OPTIONS nested */
		+ nla_total_size(sizeof(struct tcf_t)); /* TCA_GACT_TM */
}

static size_t tcf_action_full_attrs_size(size_t sz)
{
	return NLMSG_HDRLEN                     /* struct nlmsghdr */
		+ sizeof(struct tcamsg)
		+ nla_total_size(0)             /* TCA_ACT_TAB nested */
		+ sz;
}

static size_t tcf_action_fill_size(const struct tc_action *act)
{
	size_t sz = tcf_action_shared_attrs_size(act);

	if (act->ops->get_fill_size)
		return act->ops->get_fill_size(act) + sz;
	return sz;
}

186
static int tcf_dump_walker(struct tcf_idrinfo *idrinfo, struct sk_buff *skb,
187
			   struct netlink_callback *cb)
188
{
189
	int err = 0, index = -1, s_i = 0, n_i = 0;
190
	u32 act_flags = cb->args[2];
191
	unsigned long jiffy_since = cb->args[3];
192
	struct nlattr *nest;
193 194 195
	struct idr *idr = &idrinfo->action_idr;
	struct tc_action *p;
	unsigned long id = 1;
196

197
	spin_lock(&idrinfo->lock);
198 199 200

	s_i = cb->args[0];

201
	idr_for_each_entry_ul(idr, p, id) {
202 203 204 205 206 207 208 209 210 211
		index++;
		if (index < s_i)
			continue;

		if (jiffy_since &&
		    time_after(jiffy_since,
			       (unsigned long)p->tcfa_tm.lastuse))
			continue;

		nest = nla_nest_start(skb, n_i);
212 213
		if (!nest) {
			index--;
214
			goto nla_put_failure;
215
		}
216 217 218 219 220
		err = tcf_action_dump_1(skb, p, 0, 0);
		if (err < 0) {
			index--;
			nlmsg_trim(skb, nest);
			goto done;
221
		}
222 223 224 225 226
		nla_nest_end(skb, nest);
		n_i++;
		if (!(act_flags & TCA_FLAG_LARGE_DUMP_ON) &&
		    n_i >= TCA_ACT_MAX_PRIO)
			goto done;
227 228
	}
done:
229 230 231
	if (index >= 0)
		cb->args[0] = index + 1;

232
	spin_unlock(&idrinfo->lock);
233 234 235 236
	if (n_i) {
		if (act_flags & TCA_FLAG_LARGE_DUMP_ON)
			cb->args[1] = n_i;
	}
237 238
	return n_i;

239
nla_put_failure:
240
	nla_nest_cancel(skb, nest);
241 242 243
	goto done;
}

244
static int tcf_del_walker(struct tcf_idrinfo *idrinfo, struct sk_buff *skb,
245
			  const struct tc_action_ops *ops)
246
{
247
	struct nlattr *nest;
248
	int n_i = 0;
249
	int ret = -EINVAL;
250 251 252
	struct idr *idr = &idrinfo->action_idr;
	struct tc_action *p;
	unsigned long id = 1;
253

254
	nest = nla_nest_start(skb, 0);
255 256
	if (nest == NULL)
		goto nla_put_failure;
257
	if (nla_put_string(skb, TCA_KIND, ops->kind))
258
		goto nla_put_failure;
259

260
	idr_for_each_entry_ul(idr, p, id) {
261 262
		ret = __tcf_idr_release(p, false, true);
		if (ret == ACT_P_DELETED) {
263
			module_put(ops->owner);
264 265 266
			n_i++;
		} else if (ret < 0) {
			goto nla_put_failure;
267 268
		}
	}
269 270
	if (nla_put_u32(skb, TCA_FCNT, n_i))
		goto nla_put_failure;
271
	nla_nest_end(skb, nest);
272 273

	return n_i;
274
nla_put_failure:
275
	nla_nest_cancel(skb, nest);
276
	return ret;
277 278
}

279 280
int tcf_generic_walker(struct tc_action_net *tn, struct sk_buff *skb,
		       struct netlink_callback *cb, int type,
281 282
		       const struct tc_action_ops *ops,
		       struct netlink_ext_ack *extack)
283
{
284
	struct tcf_idrinfo *idrinfo = tn->idrinfo;
285

286
	if (type == RTM_DELACTION) {
287
		return tcf_del_walker(idrinfo, skb, ops);
288
	} else if (type == RTM_GETACTION) {
289
		return tcf_dump_walker(idrinfo, skb, cb);
290
	} else {
291 292
		WARN(1, "tcf_generic_walker: unknown command %d\n", type);
		NL_SET_ERR_MSG(extack, "tcf_generic_walker: unknown command");
293 294 295
		return -EINVAL;
	}
}
296
EXPORT_SYMBOL(tcf_generic_walker);
297

298 299
static bool __tcf_idr_check(struct tc_action_net *tn, u32 index,
			    struct tc_action **a, int bind)
300
{
301 302
	struct tcf_idrinfo *idrinfo = tn->idrinfo;
	struct tc_action *p;
303

304
	spin_lock(&idrinfo->lock);
305
	p = idr_find(&idrinfo->action_idr, index);
306 307 308 309 310
	if (p) {
		refcount_inc(&p->tcfa_refcnt);
		if (bind)
			atomic_inc(&p->tcfa_bindcnt);
	}
311
	spin_unlock(&idrinfo->lock);
312

313 314 315 316 317
	if (p) {
		*a = p;
		return true;
	}
	return false;
318 319
}

320
int tcf_idr_search(struct tc_action_net *tn, struct tc_action **a, u32 index)
321
{
322
	return __tcf_idr_check(tn, index, a, 0);
323
}
324
EXPORT_SYMBOL(tcf_idr_search);
325

326 327
bool tcf_idr_check(struct tc_action_net *tn, u32 index, struct tc_action **a,
		   int bind)
328
{
329
	return __tcf_idr_check(tn, index, a, bind);
330
}
331
EXPORT_SYMBOL(tcf_idr_check);
332

333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353
int tcf_idr_delete_index(struct tc_action_net *tn, u32 index)
{
	struct tcf_idrinfo *idrinfo = tn->idrinfo;
	struct tc_action *p;
	int ret = 0;

	spin_lock(&idrinfo->lock);
	p = idr_find(&idrinfo->action_idr, index);
	if (!p) {
		spin_unlock(&idrinfo->lock);
		return -ENOENT;
	}

	if (!atomic_read(&p->tcfa_bindcnt)) {
		if (refcount_dec_and_test(&p->tcfa_refcnt)) {
			struct module *owner = p->ops->owner;

			WARN_ON(p != idr_remove(&idrinfo->action_idr,
						p->tcfa_index));
			spin_unlock(&idrinfo->lock);

354
			tcf_action_cleanup(p);
355 356 357 358 359 360 361 362 363 364 365 366 367
			module_put(owner);
			return 0;
		}
		ret = 0;
	} else {
		ret = -EPERM;
	}

	spin_unlock(&idrinfo->lock);
	return ret;
}
EXPORT_SYMBOL(tcf_idr_delete_index);

368 369 370
int tcf_idr_create(struct tc_action_net *tn, u32 index, struct nlattr *est,
		   struct tc_action **a, const struct tc_action_ops *ops,
		   int bind, bool cpustats)
371
{
372
	struct tc_action *p = kzalloc(ops->size, GFP_KERNEL);
373 374
	struct tcf_idrinfo *idrinfo = tn->idrinfo;
	struct idr *idr = &idrinfo->action_idr;
375
	int err = -ENOMEM;
376 377

	if (unlikely(!p))
378
		return -ENOMEM;
379
	refcount_set(&p->tcfa_refcnt, 1);
380
	if (bind)
381
		atomic_set(&p->tcfa_bindcnt, 1);
382

383 384
	if (cpustats) {
		p->cpu_bstats = netdev_alloc_pcpu_stats(struct gnet_stats_basic_cpu);
385
		if (!p->cpu_bstats)
386
			goto err1;
387 388 389
		p->cpu_qstats = alloc_percpu(struct gnet_stats_queue);
		if (!p->cpu_qstats)
			goto err2;
390
	}
391
	spin_lock_init(&p->tcfa_lock);
392
	idr_preload(GFP_KERNEL);
393
	spin_lock(&idrinfo->lock);
394 395
	/* user doesn't specify an index */
	if (!index) {
396 397
		index = 1;
		err = idr_alloc_u32(idr, NULL, &index, UINT_MAX, GFP_ATOMIC);
398
	} else {
399
		err = idr_alloc_u32(idr, NULL, &index, index, GFP_ATOMIC);
400
	}
401
	spin_unlock(&idrinfo->lock);
402 403 404
	idr_preload_end();
	if (err)
		goto err3;
405

406
	p->tcfa_index = index;
407 408 409
	p->tcfa_tm.install = jiffies;
	p->tcfa_tm.lastuse = jiffies;
	p->tcfa_tm.firstuse = 0;
410
	if (est) {
411 412 413
		err = gen_new_estimator(&p->tcfa_bstats, p->cpu_bstats,
					&p->tcfa_rate_est,
					&p->tcfa_lock, NULL, est);
414 415
		if (err)
			goto err4;
416 417
	}

418
	p->idrinfo = idrinfo;
419 420 421
	p->ops = ops;
	INIT_LIST_HEAD(&p->list);
	*a = p;
422
	return 0;
423 424 425 426 427 428 429 430 431
err4:
	idr_remove(idr, index);
err3:
	free_percpu(p->cpu_qstats);
err2:
	free_percpu(p->cpu_bstats);
err1:
	kfree(p);
	return err;
432
}
433
EXPORT_SYMBOL(tcf_idr_create);
434

435
void tcf_idr_insert(struct tc_action_net *tn, struct tc_action *a)
436
{
437
	struct tcf_idrinfo *idrinfo = tn->idrinfo;
438

439
	spin_lock(&idrinfo->lock);
440
	idr_replace(&idrinfo->action_idr, a, a->tcfa_index);
441
	spin_unlock(&idrinfo->lock);
442
}
443
EXPORT_SYMBOL(tcf_idr_insert);
L
Linus Torvalds 已提交
444

445 446
void tcf_idrinfo_destroy(const struct tc_action_ops *ops,
			 struct tcf_idrinfo *idrinfo)
447
{
448 449 450 451
	struct idr *idr = &idrinfo->action_idr;
	struct tc_action *p;
	int ret;
	unsigned long id = 1;
452

453
	idr_for_each_entry_ul(idr, p, id) {
454 455 456 457 458
		ret = __tcf_idr_release(p, false, true);
		if (ret == ACT_P_DELETED)
			module_put(ops->owner);
		else if (ret < 0)
			return;
459
	}
460
	idr_destroy(&idrinfo->action_idr);
461
}
462
EXPORT_SYMBOL(tcf_idrinfo_destroy);
463

464
static LIST_HEAD(act_base);
L
Linus Torvalds 已提交
465 466
static DEFINE_RWLOCK(act_mod_lock);

467 468
int tcf_register_action(struct tc_action_ops *act,
			struct pernet_operations *ops)
L
Linus Torvalds 已提交
469
{
470
	struct tc_action_ops *a;
471
	int ret;
L
Linus Torvalds 已提交
472

473
	if (!act->act || !act->dump || !act->init || !act->walk || !act->lookup)
474 475
		return -EINVAL;

476 477 478 479 480 481 482 483
	/* We have to register pernet ops before making the action ops visible,
	 * otherwise tcf_action_init_1() could get a partially initialized
	 * netns.
	 */
	ret = register_pernet_subsys(ops);
	if (ret)
		return ret;

L
Linus Torvalds 已提交
484
	write_lock(&act_mod_lock);
485
	list_for_each_entry(a, &act_base, head) {
L
Linus Torvalds 已提交
486 487
		if (act->type == a->type || (strcmp(act->kind, a->kind) == 0)) {
			write_unlock(&act_mod_lock);
488
			unregister_pernet_subsys(ops);
L
Linus Torvalds 已提交
489 490 491
			return -EEXIST;
		}
	}
492
	list_add_tail(&act->head, &act_base);
L
Linus Torvalds 已提交
493
	write_unlock(&act_mod_lock);
494

L
Linus Torvalds 已提交
495 496
	return 0;
}
497
EXPORT_SYMBOL(tcf_register_action);
L
Linus Torvalds 已提交
498

499 500
int tcf_unregister_action(struct tc_action_ops *act,
			  struct pernet_operations *ops)
L
Linus Torvalds 已提交
501
{
502
	struct tc_action_ops *a;
L
Linus Torvalds 已提交
503 504 505
	int err = -ENOENT;

	write_lock(&act_mod_lock);
506 507 508 509
	list_for_each_entry(a, &act_base, head) {
		if (a == act) {
			list_del(&act->head);
			err = 0;
L
Linus Torvalds 已提交
510
			break;
511
		}
L
Linus Torvalds 已提交
512 513
	}
	write_unlock(&act_mod_lock);
514 515
	if (!err)
		unregister_pernet_subsys(ops);
L
Linus Torvalds 已提交
516 517
	return err;
}
518
EXPORT_SYMBOL(tcf_unregister_action);
L
Linus Torvalds 已提交
519 520 521 522

/* lookup by name */
static struct tc_action_ops *tc_lookup_action_n(char *kind)
{
523
	struct tc_action_ops *a, *res = NULL;
L
Linus Torvalds 已提交
524 525 526

	if (kind) {
		read_lock(&act_mod_lock);
527
		list_for_each_entry(a, &act_base, head) {
L
Linus Torvalds 已提交
528
			if (strcmp(kind, a->kind) == 0) {
529 530
				if (try_module_get(a->owner))
					res = a;
L
Linus Torvalds 已提交
531 532 533 534 535
				break;
			}
		}
		read_unlock(&act_mod_lock);
	}
536
	return res;
L
Linus Torvalds 已提交
537 538
}

539 540
/* lookup by nlattr */
static struct tc_action_ops *tc_lookup_action(struct nlattr *kind)
L
Linus Torvalds 已提交
541
{
542
	struct tc_action_ops *a, *res = NULL;
L
Linus Torvalds 已提交
543 544 545

	if (kind) {
		read_lock(&act_mod_lock);
546
		list_for_each_entry(a, &act_base, head) {
547
			if (nla_strcmp(kind, a->kind) == 0) {
548 549
				if (try_module_get(a->owner))
					res = a;
L
Linus Torvalds 已提交
550 551 552 553 554
				break;
			}
		}
		read_unlock(&act_mod_lock);
	}
555
	return res;
L
Linus Torvalds 已提交
556 557
}

558 559
/*TCA_ACT_MAX_PRIO is 32, there count upto 32 */
#define TCA_ACT_MAX_PRIO_MASK 0x1FF
560 561
int tcf_action_exec(struct sk_buff *skb, struct tc_action **actions,
		    int nr_actions, struct tcf_result *res)
L
Linus Torvalds 已提交
562
{
563 564
	u32 jmp_prgcnt = 0;
	u32 jmp_ttl = TCA_ACT_MAX_PRIO; /*matches actions per filter */
565 566
	int i;
	int ret = TC_ACT_OK;
L
Linus Torvalds 已提交
567

568 569 570
	if (skb_skip_tc_classify(skb))
		return TC_ACT_OK;

571
restart_act_graph:
572 573 574
	for (i = 0; i < nr_actions; i++) {
		const struct tc_action *a = actions[i];

575 576 577 578
		if (jmp_prgcnt > 0) {
			jmp_prgcnt -= 1;
			continue;
		}
L
Linus Torvalds 已提交
579
repeat:
580 581 582
		ret = a->ops->act(skb, a, res);
		if (ret == TC_ACT_REPEAT)
			goto repeat;	/* we need a ttl - JHS */
583

584
		if (TC_ACT_EXT_CMP(ret, TC_ACT_JUMP)) {
585 586 587 588 589 590 591 592 593 594 595
			jmp_prgcnt = ret & TCA_ACT_MAX_PRIO_MASK;
			if (!jmp_prgcnt || (jmp_prgcnt > nr_actions)) {
				/* faulty opcode, stop pipeline */
				return TC_ACT_OK;
			} else {
				jmp_ttl -= 1;
				if (jmp_ttl > 0)
					goto restart_act_graph;
				else /* faulty graph, stop pipeline */
					return TC_ACT_OK;
			}
596 597
		} else if (TC_ACT_EXT_CMP(ret, TC_ACT_GOTO_CHAIN)) {
			tcf_action_goto_chain_exec(a, res);
598 599
		}

600
		if (ret != TC_ACT_PIPE)
601
			break;
L
Linus Torvalds 已提交
602
	}
603

L
Linus Torvalds 已提交
604 605
	return ret;
}
606
EXPORT_SYMBOL(tcf_action_exec);
L
Linus Torvalds 已提交
607

608
int tcf_action_destroy(struct list_head *actions, int bind)
L
Linus Torvalds 已提交
609
{
610
	const struct tc_action_ops *ops;
611
	struct tc_action *a, *tmp;
612
	int ret = 0;
L
Linus Torvalds 已提交
613

614
	list_for_each_entry_safe(a, tmp, actions, list) {
615
		ops = a->ops;
616
		ret = __tcf_idr_release(a, bind, true);
617
		if (ret == ACT_P_DELETED)
618
			module_put(ops->owner);
619 620
		else if (ret < 0)
			return ret;
L
Linus Torvalds 已提交
621
	}
622
	return ret;
L
Linus Torvalds 已提交
623 624
}

625 626 627 628 629
static int tcf_action_put(struct tc_action *p)
{
	return __tcf_action_put(p, false);
}

L
Linus Torvalds 已提交
630 631 632 633 634 635 636 637 638 639
int
tcf_action_dump_old(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
{
	return a->ops->dump(skb, a, bind, ref);
}

int
tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
{
	int err = -EINVAL;
640
	unsigned char *b = skb_tail_pointer(skb);
641
	struct nlattr *nest;
642
	struct tc_cookie *cookie;
L
Linus Torvalds 已提交
643

644 645
	if (nla_put_string(skb, TCA_KIND, a->ops->kind))
		goto nla_put_failure;
L
Linus Torvalds 已提交
646
	if (tcf_action_copy_stats(skb, a, 0))
647
		goto nla_put_failure;
648 649 650 651 652 653

	rcu_read_lock();
	cookie = rcu_dereference(a->act_cookie);
	if (cookie) {
		if (nla_put(skb, TCA_ACT_COOKIE, cookie->len, cookie->data)) {
			rcu_read_unlock();
654
			goto nla_put_failure;
655
		}
656
	}
657
	rcu_read_unlock();
658

659 660 661
	nest = nla_nest_start(skb, TCA_OPTIONS);
	if (nest == NULL)
		goto nla_put_failure;
E
Eric Dumazet 已提交
662 663
	err = tcf_action_dump_old(skb, a, bind, ref);
	if (err > 0) {
664
		nla_nest_end(skb, nest);
L
Linus Torvalds 已提交
665 666 667
		return err;
	}

668
nla_put_failure:
669
	nlmsg_trim(skb, b);
L
Linus Torvalds 已提交
670 671
	return -1;
}
672
EXPORT_SYMBOL(tcf_action_dump_1);
L
Linus Torvalds 已提交
673

674 675
int tcf_action_dump(struct sk_buff *skb, struct list_head *actions,
		    int bind, int ref)
L
Linus Torvalds 已提交
676 677 678
{
	struct tc_action *a;
	int err = -EINVAL;
679
	struct nlattr *nest;
L
Linus Torvalds 已提交
680

681
	list_for_each_entry(a, actions, list) {
682 683 684
		nest = nla_nest_start(skb, a->order);
		if (nest == NULL)
			goto nla_put_failure;
L
Linus Torvalds 已提交
685 686
		err = tcf_action_dump_1(skb, a, bind, ref);
		if (err < 0)
687
			goto errout;
688
		nla_nest_end(skb, nest);
L
Linus Torvalds 已提交
689 690 691 692
	}

	return 0;

693
nla_put_failure:
694 695
	err = -EINVAL;
errout:
696
	nla_nest_cancel(skb, nest);
697
	return err;
L
Linus Torvalds 已提交
698 699
}

700
static struct tc_cookie *nla_memdup_cookie(struct nlattr **tb)
701
{
702 703 704 705 706 707 708 709
	struct tc_cookie *c = kzalloc(sizeof(*c), GFP_KERNEL);
	if (!c)
		return NULL;

	c->data = nla_memdup(tb[TCA_ACT_COOKIE], GFP_KERNEL);
	if (!c->data) {
		kfree(c);
		return NULL;
710
	}
711
	c->len = nla_len(tb[TCA_ACT_COOKIE]);
712

713
	return c;
714 715
}

716 717
struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp,
				    struct nlattr *nla, struct nlattr *est,
718
				    char *name, int ovr, int bind,
719
				    bool rtnl_held,
720
				    struct netlink_ext_ack *extack)
L
Linus Torvalds 已提交
721 722 723
{
	struct tc_action *a;
	struct tc_action_ops *a_o;
724
	struct tc_cookie *cookie = NULL;
L
Linus Torvalds 已提交
725
	char act_name[IFNAMSIZ];
E
Eric Dumazet 已提交
726
	struct nlattr *tb[TCA_ACT_MAX + 1];
727
	struct nlattr *kind;
728
	int err;
L
Linus Torvalds 已提交
729 730

	if (name == NULL) {
731
		err = nla_parse_nested(tb, TCA_ACT_MAX, nla, NULL, extack);
732
		if (err < 0)
L
Linus Torvalds 已提交
733
			goto err_out;
734
		err = -EINVAL;
735
		kind = tb[TCA_ACT_KIND];
736 737
		if (!kind) {
			NL_SET_ERR_MSG(extack, "TC action kind must be specified");
L
Linus Torvalds 已提交
738
			goto err_out;
739 740 741
		}
		if (nla_strlcpy(act_name, kind, IFNAMSIZ) >= IFNAMSIZ) {
			NL_SET_ERR_MSG(extack, "TC action name too long");
L
Linus Torvalds 已提交
742
			goto err_out;
743
		}
744 745 746
		if (tb[TCA_ACT_COOKIE]) {
			int cklen = nla_len(tb[TCA_ACT_COOKIE]);

747 748
			if (cklen > TC_COOKIE_MAX_SIZE) {
				NL_SET_ERR_MSG(extack, "TC cookie size above the maximum");
749
				goto err_out;
750
			}
751 752 753

			cookie = nla_memdup_cookie(tb);
			if (!cookie) {
754
				NL_SET_ERR_MSG(extack, "No memory to generate TC cookie");
755 756 757 758
				err = -ENOMEM;
				goto err_out;
			}
		}
L
Linus Torvalds 已提交
759
	} else {
760 761 762
		if (strlcpy(act_name, name, IFNAMSIZ) >= IFNAMSIZ) {
			NL_SET_ERR_MSG(extack, "TC action name too long");
			err = -EINVAL;
L
Linus Torvalds 已提交
763
			goto err_out;
764
		}
L
Linus Torvalds 已提交
765 766 767 768
	}

	a_o = tc_lookup_action_n(act_name);
	if (a_o == NULL) {
769
#ifdef CONFIG_MODULES
770 771
		if (rtnl_held)
			rtnl_unlock();
772
		request_module("act_%s", act_name);
773 774
		if (rtnl_held)
			rtnl_lock();
L
Linus Torvalds 已提交
775 776 777 778 779 780 781 782 783 784

		a_o = tc_lookup_action_n(act_name);

		/* We dropped the RTNL semaphore in order to
		 * perform the module load.  So, even if we
		 * succeeded in loading the module we have to
		 * tell the caller to replay the request.  We
		 * indicate this using -EAGAIN.
		 */
		if (a_o != NULL) {
785
			err = -EAGAIN;
L
Linus Torvalds 已提交
786 787 788
			goto err_mod;
		}
#endif
789
		NL_SET_ERR_MSG(extack, "Failed to load TC action module");
790
		err = -ENOENT;
L
Linus Torvalds 已提交
791 792 793 794 795
		goto err_out;
	}

	/* backward compatibility for policer */
	if (name == NULL)
796
		err = a_o->init(net, tb[TCA_ACT_OPTIONS], est, &a, ovr, bind,
797
				rtnl_held, extack);
L
Linus Torvalds 已提交
798
	else
799 800
		err = a_o->init(net, nla, est, &a, ovr, bind, rtnl_held,
				extack);
801
	if (err < 0)
802
		goto err_mod;
L
Linus Torvalds 已提交
803

804 805
	if (!name && tb[TCA_ACT_COOKIE])
		tcf_set_action_cookie(&a->act_cookie, cookie);
806

L
Linus Torvalds 已提交
807
	/* module count goes up only when brand new policy is created
E
Eric Dumazet 已提交
808 809 810
	 * if it exists and is only bound to in a_o->init() then
	 * ACT_P_CREATED is not returned (a zero is).
	 */
811
	if (err != ACT_P_CREATED)
L
Linus Torvalds 已提交
812 813
		module_put(a_o->owner);

814 815 816 817 818 819 820
	if (TC_ACT_EXT_CMP(a->tcfa_action, TC_ACT_GOTO_CHAIN)) {
		err = tcf_action_goto_chain_init(a, tp);
		if (err) {
			LIST_HEAD(actions);

			list_add_tail(&a->list, &actions);
			tcf_action_destroy(&actions, bind);
821
			NL_SET_ERR_MSG(extack, "Failed to init TC action chain");
822 823 824 825
			return ERR_PTR(err);
		}
	}

L
Linus Torvalds 已提交
826 827 828 829 830
	return a;

err_mod:
	module_put(a_o->owner);
err_out:
831 832 833 834
	if (cookie) {
		kfree(cookie->data);
		kfree(cookie);
	}
835
	return ERR_PTR(err);
L
Linus Torvalds 已提交
836 837
}

838 839 840 841 842 843 844 845
static void cleanup_a(struct list_head *actions, int ovr)
{
	struct tc_action *a;

	if (!ovr)
		return;

	list_for_each_entry(a, actions, list)
846
		refcount_dec(&a->tcfa_refcnt);
847 848
}

849 850
int tcf_action_init(struct net *net, struct tcf_proto *tp, struct nlattr *nla,
		    struct nlattr *est, char *name, int ovr, int bind,
851
		    struct list_head *actions, size_t *attr_size,
852
		    bool rtnl_held, struct netlink_ext_ack *extack)
L
Linus Torvalds 已提交
853
{
E
Eric Dumazet 已提交
854
	struct nlattr *tb[TCA_ACT_MAX_PRIO + 1];
855
	struct tc_action *act;
856
	size_t sz = 0;
857
	int err;
L
Linus Torvalds 已提交
858 859
	int i;

860
	err = nla_parse_nested(tb, TCA_ACT_MAX_PRIO, nla, NULL, extack);
861
	if (err < 0)
862
		return err;
L
Linus Torvalds 已提交
863

864
	for (i = 1; i <= TCA_ACT_MAX_PRIO && tb[i]; i++) {
865
		act = tcf_action_init_1(net, tp, tb[i], est, name, ovr, bind,
866
					rtnl_held, extack);
867 868
		if (IS_ERR(act)) {
			err = PTR_ERR(act);
L
Linus Torvalds 已提交
869
			goto err;
870
		}
871
		act->order = i;
872
		sz += tcf_action_fill_size(act);
873
		if (ovr)
874
			refcount_inc(&act->tcfa_refcnt);
875
		list_add_tail(&act->list, actions);
L
Linus Torvalds 已提交
876
	}
877

878 879
	*attr_size = tcf_action_full_attrs_size(sz);

880 881 882 883
	/* Remove the temp refcnt which was necessary to protect against
	 * destroying an existing action which was being replaced
	 */
	cleanup_a(actions, ovr);
884
	return 0;
L
Linus Torvalds 已提交
885 886

err:
887 888
	tcf_action_destroy(actions, bind);
	return err;
L
Linus Torvalds 已提交
889 890
}

891
int tcf_action_copy_stats(struct sk_buff *skb, struct tc_action *p,
L
Linus Torvalds 已提交
892 893 894 895
			  int compat_mode)
{
	int err = 0;
	struct gnet_dump d;
896

897
	if (p == NULL)
L
Linus Torvalds 已提交
898 899 900
		goto errout;

	/* compat_mode being true specifies a call that is supposed
901
	 * to add additional backward compatibility statistic TLVs.
L
Linus Torvalds 已提交
902 903
	 */
	if (compat_mode) {
904
		if (p->type == TCA_OLD_COMPAT)
L
Linus Torvalds 已提交
905
			err = gnet_stats_start_copy_compat(skb, 0,
906 907
							   TCA_STATS,
							   TCA_XSTATS,
908
							   &p->tcfa_lock, &d,
909
							   TCA_PAD);
L
Linus Torvalds 已提交
910 911 912 913
		else
			return 0;
	} else
		err = gnet_stats_start_copy(skb, TCA_ACT_STATS,
914
					    &p->tcfa_lock, &d, TCA_ACT_PAD);
L
Linus Torvalds 已提交
915 916 917 918

	if (err < 0)
		goto errout;

919
	if (gnet_stats_copy_basic(NULL, &d, p->cpu_bstats, &p->tcfa_bstats) < 0 ||
920
	    gnet_stats_copy_rate_est(&d, &p->tcfa_rate_est) < 0 ||
921
	    gnet_stats_copy_queue(&d, p->cpu_qstats,
922 923
				  &p->tcfa_qstats,
				  p->tcfa_qstats.qlen) < 0)
L
Linus Torvalds 已提交
924 925 926 927 928 929 930 931 932 933 934
		goto errout;

	if (gnet_stats_finish_copy(&d) < 0)
		goto errout;

	return 0;

errout:
	return -1;
}

935 936 937
static int tca_get_fill(struct sk_buff *skb, struct list_head *actions,
			u32 portid, u32 seq, u16 flags, int event, int bind,
			int ref)
L
Linus Torvalds 已提交
938 939 940
{
	struct tcamsg *t;
	struct nlmsghdr *nlh;
941
	unsigned char *b = skb_tail_pointer(skb);
942
	struct nlattr *nest;
L
Linus Torvalds 已提交
943

944
	nlh = nlmsg_put(skb, portid, seq, event, sizeof(*t), flags);
945 946 947
	if (!nlh)
		goto out_nlmsg_trim;
	t = nlmsg_data(nlh);
L
Linus Torvalds 已提交
948
	t->tca_family = AF_UNSPEC;
949 950
	t->tca__pad1 = 0;
	t->tca__pad2 = 0;
951

952
	nest = nla_nest_start(skb, TCA_ACT_TAB);
953
	if (!nest)
954
		goto out_nlmsg_trim;
L
Linus Torvalds 已提交
955

956
	if (tcf_action_dump(skb, actions, bind, ref) < 0)
957
		goto out_nlmsg_trim;
L
Linus Torvalds 已提交
958

959
	nla_nest_end(skb, nest);
960

961
	nlh->nlmsg_len = skb_tail_pointer(skb) - b;
L
Linus Torvalds 已提交
962 963
	return skb->len;

964
out_nlmsg_trim:
965
	nlmsg_trim(skb, b);
L
Linus Torvalds 已提交
966 967 968 969
	return -1;
}

static int
970
tcf_get_notify(struct net *net, u32 portid, struct nlmsghdr *n,
971 972
	       struct list_head *actions, int event,
	       struct netlink_ext_ack *extack)
L
Linus Torvalds 已提交
973 974 975 976 977 978
{
	struct sk_buff *skb;

	skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
	if (!skb)
		return -ENOBUFS;
979
	if (tca_get_fill(skb, actions, portid, n->nlmsg_seq, 0, event,
980
			 0, 1) <= 0) {
981
		NL_SET_ERR_MSG(extack, "Failed to fill netlink attributes while adding TC action");
L
Linus Torvalds 已提交
982 983 984
		kfree_skb(skb);
		return -EINVAL;
	}
985

986
	return rtnl_unicast(skb, net, portid);
L
Linus Torvalds 已提交
987 988
}

989
static struct tc_action *tcf_action_get_1(struct net *net, struct nlattr *nla,
990 991
					  struct nlmsghdr *n, u32 portid,
					  struct netlink_ext_ack *extack)
L
Linus Torvalds 已提交
992
{
E
Eric Dumazet 已提交
993
	struct nlattr *tb[TCA_ACT_MAX + 1];
994
	const struct tc_action_ops *ops;
L
Linus Torvalds 已提交
995 996
	struct tc_action *a;
	int index;
997
	int err;
L
Linus Torvalds 已提交
998

999
	err = nla_parse_nested(tb, TCA_ACT_MAX, nla, NULL, extack);
1000
	if (err < 0)
1001
		goto err_out;
L
Linus Torvalds 已提交
1002

1003
	err = -EINVAL;
1004
	if (tb[TCA_ACT_INDEX] == NULL ||
1005 1006
	    nla_len(tb[TCA_ACT_INDEX]) < sizeof(index)) {
		NL_SET_ERR_MSG(extack, "Invalid TC action index value");
1007
		goto err_out;
1008
	}
1009
	index = nla_get_u32(tb[TCA_ACT_INDEX]);
L
Linus Torvalds 已提交
1010

1011
	err = -EINVAL;
1012
	ops = tc_lookup_action(tb[TCA_ACT_KIND]);
1013 1014
	if (!ops) { /* could happen in batch of actions */
		NL_SET_ERR_MSG(extack, "Specified TC action not found");
1015
		goto err_out;
1016
	}
1017
	err = -ENOENT;
1018
	if (ops->lookup(net, &a, index, extack) == 0)
L
Linus Torvalds 已提交
1019 1020
		goto err_mod;

1021
	module_put(ops->owner);
L
Linus Torvalds 已提交
1022
	return a;
1023

L
Linus Torvalds 已提交
1024
err_mod:
1025
	module_put(ops->owner);
1026 1027
err_out:
	return ERR_PTR(err);
L
Linus Torvalds 已提交
1028 1029
}

1030
static int tca_action_flush(struct net *net, struct nlattr *nla,
1031 1032
			    struct nlmsghdr *n, u32 portid,
			    struct netlink_ext_ack *extack)
L
Linus Torvalds 已提交
1033 1034 1035 1036 1037 1038
{
	struct sk_buff *skb;
	unsigned char *b;
	struct nlmsghdr *nlh;
	struct tcamsg *t;
	struct netlink_callback dcb;
1039
	struct nlattr *nest;
E
Eric Dumazet 已提交
1040
	struct nlattr *tb[TCA_ACT_MAX + 1];
1041
	const struct tc_action_ops *ops;
1042
	struct nlattr *kind;
1043
	int err = -ENOMEM;
L
Linus Torvalds 已提交
1044 1045

	skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
1046
	if (!skb)
1047
		return err;
L
Linus Torvalds 已提交
1048

1049
	b = skb_tail_pointer(skb);
L
Linus Torvalds 已提交
1050

1051
	err = nla_parse_nested(tb, TCA_ACT_MAX, nla, NULL, extack);
1052
	if (err < 0)
L
Linus Torvalds 已提交
1053 1054
		goto err_out;

1055
	err = -EINVAL;
1056
	kind = tb[TCA_ACT_KIND];
1057
	ops = tc_lookup_action(kind);
1058 1059
	if (!ops) { /*some idjot trying to flush unknown action */
		NL_SET_ERR_MSG(extack, "Cannot flush unknown TC action");
L
Linus Torvalds 已提交
1060
		goto err_out;
1061
	}
L
Linus Torvalds 已提交
1062

1063 1064
	nlh = nlmsg_put(skb, portid, n->nlmsg_seq, RTM_DELACTION,
			sizeof(*t), 0);
1065 1066
	if (!nlh) {
		NL_SET_ERR_MSG(extack, "Failed to create TC action flush notification");
1067
		goto out_module_put;
1068
	}
1069
	t = nlmsg_data(nlh);
L
Linus Torvalds 已提交
1070
	t->tca_family = AF_UNSPEC;
1071 1072
	t->tca__pad1 = 0;
	t->tca__pad2 = 0;
L
Linus Torvalds 已提交
1073

1074
	nest = nla_nest_start(skb, TCA_ACT_TAB);
1075 1076
	if (!nest) {
		NL_SET_ERR_MSG(extack, "Failed to add new netlink message");
1077
		goto out_module_put;
1078
	}
L
Linus Torvalds 已提交
1079

1080
	err = ops->walk(net, skb, &dcb, RTM_DELACTION, ops, extack);
1081 1082
	if (err <= 0) {
		nla_nest_cancel(skb, nest);
1083
		goto out_module_put;
1084
	}
L
Linus Torvalds 已提交
1085

1086
	nla_nest_end(skb, nest);
L
Linus Torvalds 已提交
1087

1088
	nlh->nlmsg_len = skb_tail_pointer(skb) - b;
L
Linus Torvalds 已提交
1089
	nlh->nlmsg_flags |= NLM_F_ROOT;
1090
	module_put(ops->owner);
1091
	err = rtnetlink_send(skb, net, portid, RTNLGRP_TC,
E
Eric Dumazet 已提交
1092
			     n->nlmsg_flags & NLM_F_ECHO);
L
Linus Torvalds 已提交
1093 1094
	if (err > 0)
		return 0;
1095 1096
	if (err < 0)
		NL_SET_ERR_MSG(extack, "Failed to send TC action flush notification");
L
Linus Torvalds 已提交
1097 1098 1099

	return err;

1100
out_module_put:
1101
	module_put(ops->owner);
L
Linus Torvalds 已提交
1102 1103 1104 1105 1106
err_out:
	kfree_skb(skb);
	return err;
}

1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135
static int tcf_action_delete(struct net *net, struct list_head *actions,
			     struct netlink_ext_ack *extack)
{
	struct tc_action *a, *tmp;
	u32 act_index;
	int ret;

	list_for_each_entry_safe(a, tmp, actions, list) {
		const struct tc_action_ops *ops = a->ops;

		/* Actions can be deleted concurrently so we must save their
		 * type and id to search again after reference is released.
		 */
		act_index = a->tcfa_index;

		list_del(&a->list);
		if (tcf_action_put(a)) {
			/* last reference, action was deleted concurrently */
			module_put(ops->owner);
		} else  {
			/* now do the delete */
			ret = ops->delete(net, act_index);
			if (ret < 0)
				return ret;
		}
	}
	return 0;
}

1136 1137
static int
tcf_del_notify(struct net *net, struct nlmsghdr *n, struct list_head *actions,
1138
	       u32 portid, size_t attr_size, struct netlink_ext_ack *extack)
1139 1140 1141 1142
{
	int ret;
	struct sk_buff *skb;

1143 1144
	skb = alloc_skb(attr_size <= NLMSG_GOODSIZE ? NLMSG_GOODSIZE : attr_size,
			GFP_KERNEL);
1145 1146 1147 1148
	if (!skb)
		return -ENOBUFS;

	if (tca_get_fill(skb, actions, portid, n->nlmsg_seq, 0, RTM_DELACTION,
1149
			 0, 2) <= 0) {
1150
		NL_SET_ERR_MSG(extack, "Failed to fill netlink TC action attributes");
1151 1152 1153 1154 1155
		kfree_skb(skb);
		return -EINVAL;
	}

	/* now do the delete */
1156
	ret = tcf_action_delete(net, actions, extack);
1157
	if (ret < 0) {
1158
		NL_SET_ERR_MSG(extack, "Failed to delete TC action");
1159 1160 1161
		kfree_skb(skb);
		return ret;
	}
1162 1163 1164 1165 1166 1167 1168 1169

	ret = rtnetlink_send(skb, net, portid, RTNLGRP_TC,
			     n->nlmsg_flags & NLM_F_ECHO);
	if (ret > 0)
		return 0;
	return ret;
}

L
Linus Torvalds 已提交
1170
static int
1171
tca_action_gd(struct net *net, struct nlattr *nla, struct nlmsghdr *n,
1172
	      u32 portid, int event, struct netlink_ext_ack *extack)
L
Linus Torvalds 已提交
1173
{
1174
	int i, ret;
E
Eric Dumazet 已提交
1175
	struct nlattr *tb[TCA_ACT_MAX_PRIO + 1];
1176
	struct tc_action *act;
1177
	size_t attr_size = 0;
1178
	LIST_HEAD(actions);
L
Linus Torvalds 已提交
1179

1180
	ret = nla_parse_nested(tb, TCA_ACT_MAX_PRIO, nla, NULL, extack);
1181 1182
	if (ret < 0)
		return ret;
L
Linus Torvalds 已提交
1183

E
Eric Dumazet 已提交
1184
	if (event == RTM_DELACTION && n->nlmsg_flags & NLM_F_ROOT) {
1185
		if (tb[1])
1186
			return tca_action_flush(net, tb[1], n, portid, extack);
1187

1188
		NL_SET_ERR_MSG(extack, "Invalid netlink attributes while flushing TC action");
1189
		return -EINVAL;
L
Linus Torvalds 已提交
1190 1191
	}

1192
	for (i = 1; i <= TCA_ACT_MAX_PRIO && tb[i]; i++) {
1193
		act = tcf_action_get_1(net, tb[i], n, portid, extack);
1194 1195
		if (IS_ERR(act)) {
			ret = PTR_ERR(act);
L
Linus Torvalds 已提交
1196
			goto err;
1197
		}
1198
		act->order = i;
1199
		attr_size += tcf_action_fill_size(act);
1200
		list_add_tail(&act->list, &actions);
L
Linus Torvalds 已提交
1201
	}
1202 1203

	attr_size = tcf_action_full_attrs_size(attr_size);
L
Linus Torvalds 已提交
1204 1205

	if (event == RTM_GETACTION)
1206
		ret = tcf_get_notify(net, portid, n, &actions, event, extack);
L
Linus Torvalds 已提交
1207
	else { /* delete */
1208
		ret = tcf_del_notify(net, n, &actions, portid, attr_size, extack);
1209
		if (ret)
L
Linus Torvalds 已提交
1210 1211 1212 1213
			goto err;
		return ret;
	}
err:
1214
	tcf_action_destroy(&actions, 0);
L
Linus Torvalds 已提交
1215 1216 1217
	return ret;
}

1218 1219
static int
tcf_add_notify(struct net *net, struct nlmsghdr *n, struct list_head *actions,
1220
	       u32 portid, size_t attr_size, struct netlink_ext_ack *extack)
L
Linus Torvalds 已提交
1221 1222 1223 1224
{
	struct sk_buff *skb;
	int err = 0;

1225 1226
	skb = alloc_skb(attr_size <= NLMSG_GOODSIZE ? NLMSG_GOODSIZE : attr_size,
			GFP_KERNEL);
L
Linus Torvalds 已提交
1227 1228 1229
	if (!skb)
		return -ENOBUFS;

1230 1231
	if (tca_get_fill(skb, actions, portid, n->nlmsg_seq, n->nlmsg_flags,
			 RTM_NEWACTION, 0, 0) <= 0) {
1232
		NL_SET_ERR_MSG(extack, "Failed to fill netlink attributes while adding TC action");
1233 1234 1235
		kfree_skb(skb);
		return -EINVAL;
	}
1236

1237 1238
	err = rtnetlink_send(skb, net, portid, RTNLGRP_TC,
			     n->nlmsg_flags & NLM_F_ECHO);
L
Linus Torvalds 已提交
1239 1240 1241 1242 1243
	if (err > 0)
		err = 0;
	return err;
}

J
Jamal Hadi Salim 已提交
1244
static int tcf_action_add(struct net *net, struct nlattr *nla,
1245 1246
			  struct nlmsghdr *n, u32 portid, int ovr,
			  struct netlink_ext_ack *extack)
L
Linus Torvalds 已提交
1247
{
1248
	size_t attr_size = 0;
L
Linus Torvalds 已提交
1249
	int ret = 0;
1250
	LIST_HEAD(actions);
L
Linus Torvalds 已提交
1251

1252
	ret = tcf_action_init(net, NULL, nla, NULL, NULL, ovr, 0, &actions,
1253
			      &attr_size, true, extack);
1254
	if (ret)
1255
		return ret;
L
Linus Torvalds 已提交
1256

1257
	return tcf_add_notify(net, n, &actions, portid, attr_size, extack);
L
Linus Torvalds 已提交
1258 1259
}

1260 1261 1262 1263
static u32 tcaa_root_flags_allowed = TCA_FLAG_LARGE_DUMP_ON;
static const struct nla_policy tcaa_policy[TCA_ROOT_MAX + 1] = {
	[TCA_ROOT_FLAGS] = { .type = NLA_BITFIELD32,
			     .validation_data = &tcaa_root_flags_allowed },
1264
	[TCA_ROOT_TIME_DELTA]      = { .type = NLA_U32 },
1265 1266
};

1267 1268
static int tc_ctl_action(struct sk_buff *skb, struct nlmsghdr *n,
			 struct netlink_ext_ack *extack)
L
Linus Torvalds 已提交
1269
{
1270
	struct net *net = sock_net(skb->sk);
1271
	struct nlattr *tca[TCA_ROOT_MAX + 1];
1272
	u32 portid = skb ? NETLINK_CB(skb).portid : 0;
L
Linus Torvalds 已提交
1273 1274
	int ret = 0, ovr = 0;

1275 1276
	if ((n->nlmsg_type != RTM_GETACTION) &&
	    !netlink_capable(skb, CAP_NET_ADMIN))
1277 1278
		return -EPERM;

1279
	ret = nlmsg_parse(n, sizeof(struct tcamsg), tca, TCA_ROOT_MAX, NULL,
1280
			  extack);
1281 1282 1283 1284
	if (ret < 0)
		return ret;

	if (tca[TCA_ACT_TAB] == NULL) {
1285
		NL_SET_ERR_MSG(extack, "Netlink action attributes missing");
L
Linus Torvalds 已提交
1286 1287 1288
		return -EINVAL;
	}

E
Eric Dumazet 已提交
1289
	/* n->nlmsg_flags & NLM_F_CREATE */
L
Linus Torvalds 已提交
1290 1291 1292
	switch (n->nlmsg_type) {
	case RTM_NEWACTION:
		/* we are going to assume all other flags
L
Lucas De Marchi 已提交
1293
		 * imply create only if it doesn't exist
L
Linus Torvalds 已提交
1294 1295 1296 1297
		 * Note that CREATE | EXCL implies that
		 * but since we want avoid ambiguity (eg when flags
		 * is zero) then just set this
		 */
E
Eric Dumazet 已提交
1298
		if (n->nlmsg_flags & NLM_F_REPLACE)
L
Linus Torvalds 已提交
1299 1300
			ovr = 1;
replay:
1301 1302
		ret = tcf_action_add(net, tca[TCA_ACT_TAB], n, portid, ovr,
				     extack);
L
Linus Torvalds 已提交
1303 1304 1305 1306
		if (ret == -EAGAIN)
			goto replay;
		break;
	case RTM_DELACTION:
1307
		ret = tca_action_gd(net, tca[TCA_ACT_TAB], n,
1308
				    portid, RTM_DELACTION, extack);
L
Linus Torvalds 已提交
1309 1310
		break;
	case RTM_GETACTION:
1311
		ret = tca_action_gd(net, tca[TCA_ACT_TAB], n,
1312
				    portid, RTM_GETACTION, extack);
L
Linus Torvalds 已提交
1313 1314 1315 1316 1317 1318 1319 1320
		break;
	default:
		BUG();
	}

	return ret;
}

1321
static struct nlattr *find_dump_kind(struct nlattr **nla)
L
Linus Torvalds 已提交
1322
{
E
Eric Dumazet 已提交
1323
	struct nlattr *tb1, *tb2[TCA_ACT_MAX + 1];
1324 1325
	struct nlattr *tb[TCA_ACT_MAX_PRIO + 1];
	struct nlattr *kind;
L
Linus Torvalds 已提交
1326

1327
	tb1 = nla[TCA_ACT_TAB];
L
Linus Torvalds 已提交
1328 1329 1330
	if (tb1 == NULL)
		return NULL;

1331
	if (nla_parse(tb, TCA_ACT_MAX_PRIO, nla_data(tb1),
1332
		      NLMSG_ALIGN(nla_len(tb1)), NULL, NULL) < 0)
L
Linus Torvalds 已提交
1333 1334
		return NULL;

1335 1336
	if (tb[1] == NULL)
		return NULL;
1337
	if (nla_parse_nested(tb2, TCA_ACT_MAX, tb[1], NULL, NULL) < 0)
L
Linus Torvalds 已提交
1338
		return NULL;
1339
	kind = tb2[TCA_ACT_KIND];
L
Linus Torvalds 已提交
1340

1341
	return kind;
L
Linus Torvalds 已提交
1342 1343
}

J
Jamal Hadi Salim 已提交
1344
static int tc_dump_action(struct sk_buff *skb, struct netlink_callback *cb)
L
Linus Torvalds 已提交
1345
{
1346
	struct net *net = sock_net(skb->sk);
L
Linus Torvalds 已提交
1347
	struct nlmsghdr *nlh;
1348
	unsigned char *b = skb_tail_pointer(skb);
1349
	struct nlattr *nest;
L
Linus Torvalds 已提交
1350 1351
	struct tc_action_ops *a_o;
	int ret = 0;
1352
	struct tcamsg *t = (struct tcamsg *) nlmsg_data(cb->nlh);
1353 1354
	struct nlattr *tb[TCA_ROOT_MAX + 1];
	struct nlattr *count_attr = NULL;
1355
	unsigned long jiffy_since = 0;
1356 1357
	struct nlattr *kind = NULL;
	struct nla_bitfield32 bf;
1358
	u32 msecs_since = 0;
1359 1360 1361 1362 1363 1364
	u32 act_count = 0;

	ret = nlmsg_parse(cb->nlh, sizeof(struct tcamsg), tb, TCA_ROOT_MAX,
			  tcaa_policy, NULL);
	if (ret < 0)
		return ret;
L
Linus Torvalds 已提交
1365

1366
	kind = find_dump_kind(tb);
L
Linus Torvalds 已提交
1367
	if (kind == NULL) {
1368
		pr_info("tc_dump_action: action bad kind\n");
L
Linus Torvalds 已提交
1369 1370 1371
		return 0;
	}

1372
	a_o = tc_lookup_action(kind);
E
Eric Dumazet 已提交
1373
	if (a_o == NULL)
L
Linus Torvalds 已提交
1374 1375
		return 0;

1376 1377 1378 1379 1380 1381
	cb->args[2] = 0;
	if (tb[TCA_ROOT_FLAGS]) {
		bf = nla_get_bitfield32(tb[TCA_ROOT_FLAGS]);
		cb->args[2] = bf.value;
	}

1382 1383 1384 1385
	if (tb[TCA_ROOT_TIME_DELTA]) {
		msecs_since = nla_get_u32(tb[TCA_ROOT_TIME_DELTA]);
	}

1386
	nlh = nlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
1387 1388 1389
			cb->nlh->nlmsg_type, sizeof(*t), 0);
	if (!nlh)
		goto out_module_put;
1390

1391 1392 1393
	if (msecs_since)
		jiffy_since = jiffies - msecs_to_jiffies(msecs_since);

1394
	t = nlmsg_data(nlh);
L
Linus Torvalds 已提交
1395
	t->tca_family = AF_UNSPEC;
1396 1397
	t->tca__pad1 = 0;
	t->tca__pad2 = 0;
1398
	cb->args[3] = jiffy_since;
1399 1400 1401
	count_attr = nla_reserve(skb, TCA_ROOT_COUNT, sizeof(u32));
	if (!count_attr)
		goto out_module_put;
L
Linus Torvalds 已提交
1402

1403 1404
	nest = nla_nest_start(skb, TCA_ACT_TAB);
	if (nest == NULL)
1405
		goto out_module_put;
L
Linus Torvalds 已提交
1406

1407
	ret = a_o->walk(net, skb, cb, RTM_GETACTION, a_o, NULL);
L
Linus Torvalds 已提交
1408
	if (ret < 0)
1409
		goto out_module_put;
L
Linus Torvalds 已提交
1410 1411

	if (ret > 0) {
1412
		nla_nest_end(skb, nest);
L
Linus Torvalds 已提交
1413
		ret = skb->len;
1414 1415 1416
		act_count = cb->args[1];
		memcpy(nla_data(count_attr), &act_count, sizeof(u32));
		cb->args[1] = 0;
L
Linus Torvalds 已提交
1417
	} else
1418
		nlmsg_trim(skb, b);
L
Linus Torvalds 已提交
1419

1420
	nlh->nlmsg_len = skb_tail_pointer(skb) - b;
1421
	if (NETLINK_CB(cb->skb).portid && ret)
L
Linus Torvalds 已提交
1422 1423 1424 1425
		nlh->nlmsg_flags |= NLM_F_MULTI;
	module_put(a_o->owner);
	return skb->len;

1426
out_module_put:
L
Linus Torvalds 已提交
1427
	module_put(a_o->owner);
1428
	nlmsg_trim(skb, b);
L
Linus Torvalds 已提交
1429 1430 1431
	return skb->len;
}

1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480
struct tcf_action_net {
	struct rhashtable egdev_ht;
};

static unsigned int tcf_action_net_id;

struct tcf_action_egdev_cb {
	struct list_head list;
	tc_setup_cb_t *cb;
	void *cb_priv;
};

struct tcf_action_egdev {
	struct rhash_head ht_node;
	const struct net_device *dev;
	unsigned int refcnt;
	struct list_head cb_list;
};

static const struct rhashtable_params tcf_action_egdev_ht_params = {
	.key_offset = offsetof(struct tcf_action_egdev, dev),
	.head_offset = offsetof(struct tcf_action_egdev, ht_node),
	.key_len = sizeof(const struct net_device *),
};

static struct tcf_action_egdev *
tcf_action_egdev_lookup(const struct net_device *dev)
{
	struct net *net = dev_net(dev);
	struct tcf_action_net *tan = net_generic(net, tcf_action_net_id);

	return rhashtable_lookup_fast(&tan->egdev_ht, &dev,
				      tcf_action_egdev_ht_params);
}

static struct tcf_action_egdev *
tcf_action_egdev_get(const struct net_device *dev)
{
	struct tcf_action_egdev *egdev;
	struct tcf_action_net *tan;

	egdev = tcf_action_egdev_lookup(dev);
	if (egdev)
		goto inc_ref;

	egdev = kzalloc(sizeof(*egdev), GFP_KERNEL);
	if (!egdev)
		return NULL;
	INIT_LIST_HEAD(&egdev->cb_list);
1481
	egdev->dev = dev;
1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644
	tan = net_generic(dev_net(dev), tcf_action_net_id);
	rhashtable_insert_fast(&tan->egdev_ht, &egdev->ht_node,
			       tcf_action_egdev_ht_params);

inc_ref:
	egdev->refcnt++;
	return egdev;
}

static void tcf_action_egdev_put(struct tcf_action_egdev *egdev)
{
	struct tcf_action_net *tan;

	if (--egdev->refcnt)
		return;
	tan = net_generic(dev_net(egdev->dev), tcf_action_net_id);
	rhashtable_remove_fast(&tan->egdev_ht, &egdev->ht_node,
			       tcf_action_egdev_ht_params);
	kfree(egdev);
}

static struct tcf_action_egdev_cb *
tcf_action_egdev_cb_lookup(struct tcf_action_egdev *egdev,
			   tc_setup_cb_t *cb, void *cb_priv)
{
	struct tcf_action_egdev_cb *egdev_cb;

	list_for_each_entry(egdev_cb, &egdev->cb_list, list)
		if (egdev_cb->cb == cb && egdev_cb->cb_priv == cb_priv)
			return egdev_cb;
	return NULL;
}

static int tcf_action_egdev_cb_call(struct tcf_action_egdev *egdev,
				    enum tc_setup_type type,
				    void *type_data, bool err_stop)
{
	struct tcf_action_egdev_cb *egdev_cb;
	int ok_count = 0;
	int err;

	list_for_each_entry(egdev_cb, &egdev->cb_list, list) {
		err = egdev_cb->cb(type, type_data, egdev_cb->cb_priv);
		if (err) {
			if (err_stop)
				return err;
		} else {
			ok_count++;
		}
	}
	return ok_count;
}

static int tcf_action_egdev_cb_add(struct tcf_action_egdev *egdev,
				   tc_setup_cb_t *cb, void *cb_priv)
{
	struct tcf_action_egdev_cb *egdev_cb;

	egdev_cb = tcf_action_egdev_cb_lookup(egdev, cb, cb_priv);
	if (WARN_ON(egdev_cb))
		return -EEXIST;
	egdev_cb = kzalloc(sizeof(*egdev_cb), GFP_KERNEL);
	if (!egdev_cb)
		return -ENOMEM;
	egdev_cb->cb = cb;
	egdev_cb->cb_priv = cb_priv;
	list_add(&egdev_cb->list, &egdev->cb_list);
	return 0;
}

static void tcf_action_egdev_cb_del(struct tcf_action_egdev *egdev,
				    tc_setup_cb_t *cb, void *cb_priv)
{
	struct tcf_action_egdev_cb *egdev_cb;

	egdev_cb = tcf_action_egdev_cb_lookup(egdev, cb, cb_priv);
	if (WARN_ON(!egdev_cb))
		return;
	list_del(&egdev_cb->list);
	kfree(egdev_cb);
}

static int __tc_setup_cb_egdev_register(const struct net_device *dev,
					tc_setup_cb_t *cb, void *cb_priv)
{
	struct tcf_action_egdev *egdev = tcf_action_egdev_get(dev);
	int err;

	if (!egdev)
		return -ENOMEM;
	err = tcf_action_egdev_cb_add(egdev, cb, cb_priv);
	if (err)
		goto err_cb_add;
	return 0;

err_cb_add:
	tcf_action_egdev_put(egdev);
	return err;
}
int tc_setup_cb_egdev_register(const struct net_device *dev,
			       tc_setup_cb_t *cb, void *cb_priv)
{
	int err;

	rtnl_lock();
	err = __tc_setup_cb_egdev_register(dev, cb, cb_priv);
	rtnl_unlock();
	return err;
}
EXPORT_SYMBOL_GPL(tc_setup_cb_egdev_register);

static void __tc_setup_cb_egdev_unregister(const struct net_device *dev,
					   tc_setup_cb_t *cb, void *cb_priv)
{
	struct tcf_action_egdev *egdev = tcf_action_egdev_lookup(dev);

	if (WARN_ON(!egdev))
		return;
	tcf_action_egdev_cb_del(egdev, cb, cb_priv);
	tcf_action_egdev_put(egdev);
}
void tc_setup_cb_egdev_unregister(const struct net_device *dev,
				  tc_setup_cb_t *cb, void *cb_priv)
{
	rtnl_lock();
	__tc_setup_cb_egdev_unregister(dev, cb, cb_priv);
	rtnl_unlock();
}
EXPORT_SYMBOL_GPL(tc_setup_cb_egdev_unregister);

int tc_setup_cb_egdev_call(const struct net_device *dev,
			   enum tc_setup_type type, void *type_data,
			   bool err_stop)
{
	struct tcf_action_egdev *egdev = tcf_action_egdev_lookup(dev);

	if (!egdev)
		return 0;
	return tcf_action_egdev_cb_call(egdev, type, type_data, err_stop);
}
EXPORT_SYMBOL_GPL(tc_setup_cb_egdev_call);

static __net_init int tcf_action_net_init(struct net *net)
{
	struct tcf_action_net *tan = net_generic(net, tcf_action_net_id);

	return rhashtable_init(&tan->egdev_ht, &tcf_action_egdev_ht_params);
}

static void __net_exit tcf_action_net_exit(struct net *net)
{
	struct tcf_action_net *tan = net_generic(net, tcf_action_net_id);

	rhashtable_destroy(&tan->egdev_ht);
}

static struct pernet_operations tcf_action_net_ops = {
	.init = tcf_action_net_init,
	.exit = tcf_action_net_exit,
	.id = &tcf_action_net_id,
	.size = sizeof(struct tcf_action_net),
};

L
Linus Torvalds 已提交
1645 1646
static int __init tc_action_init(void)
{
1647 1648 1649 1650 1651 1652
	int err;

	err = register_pernet_subsys(&tcf_action_net_ops);
	if (err)
		return err;

1653 1654
	rtnl_register(PF_UNSPEC, RTM_NEWACTION, tc_ctl_action, NULL, 0);
	rtnl_register(PF_UNSPEC, RTM_DELACTION, tc_ctl_action, NULL, 0);
1655
	rtnl_register(PF_UNSPEC, RTM_GETACTION, tc_ctl_action, tc_dump_action,
1656
		      0);
L
Linus Torvalds 已提交
1657 1658 1659 1660 1661

	return 0;
}

subsys_initcall(tc_action_init);