act_police.c 15.2 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
/*
 * net/sched/police.c	Input police filter.
 *
 *		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.
 *
 * Authors:	Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
 * 		J Hadi Salim (action changes)
 */

#include <asm/uaccess.h>
#include <asm/system.h>
#include <linux/bitops.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/socket.h>
#include <linux/sockios.h>
#include <linux/in.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <linux/module.h>
#include <linux/rtnetlink.h>
#include <linux/init.h>
#include <net/sock.h>
#include <net/act_api.h>

34 35
#define L2T(p,L)   ((p)->tcfp_R_tab->data[(L)>>(p)->tcfp_R_tab->rate.cell_log])
#define L2T_P(p,L) ((p)->tcfp_P_tab->data[(L)>>(p)->tcfp_P_tab->rate.cell_log])
L
Linus Torvalds 已提交
36

37 38 39 40
#define POL_TAB_MASK     15
static struct tcf_common *tcf_police_ht[POL_TAB_MASK + 1];
static u32 police_idx_gen;
static DEFINE_RWLOCK(police_lock);
L
Linus Torvalds 已提交
41

42 43 44 45 46
static struct tcf_hashinfo police_hash_info = {
	.htab	=	tcf_police_ht,
	.hmask	=	POL_TAB_MASK,
	.lock	=	&police_lock,
};
L
Linus Torvalds 已提交
47

48 49 50 51 52 53 54 55 56 57 58 59
/* old policer structure from before tc actions */
struct tc_police_compat
{
	u32			index;
	int			action;
	u32			limit;
	u32			burst;
	u32			mtu;
	struct tc_ratespec	rate;
	struct tc_ratespec	peakrate;
};

60
/* Each policer is serialized by its individual spinlock */
L
Linus Torvalds 已提交
61 62

#ifdef CONFIG_NET_CLS_ACT
63
static int tcf_act_police_walker(struct sk_buff *skb, struct netlink_callback *cb,
64
			      int type, struct tc_action *a)
L
Linus Torvalds 已提交
65
{
66
	struct tcf_common *p;
L
Linus Torvalds 已提交
67 68 69 70 71 72 73
	int err = 0, index = -1, i = 0, s_i = 0, n_i = 0;
	struct rtattr *r;

	read_lock(&police_lock);

	s_i = cb->args[0];

74 75
	for (i = 0; i < (POL_TAB_MASK + 1); i++) {
		p = tcf_police_ht[tcf_hash(i, POL_TAB_MASK)];
L
Linus Torvalds 已提交
76

77
		for (; p; p = p->tcfc_next) {
L
Linus Torvalds 已提交
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
			index++;
			if (index < s_i)
				continue;
			a->priv = p;
			a->order = index;
			r = (struct rtattr*) skb->tail;
			RTA_PUT(skb, a->order, 0, NULL);
			if (type == RTM_DELACTION)
				err = tcf_action_dump_1(skb, a, 0, 1);
			else
				err = tcf_action_dump_1(skb, a, 0, 0);
			if (err < 0) {
				index--;
				skb_trim(skb, (u8*)r - skb->data);
				goto done;
			}
			r->rta_len = skb->tail - (u8*)r;
			n_i++;
		}
	}
done:
	read_unlock(&police_lock);
	if (n_i)
		cb->args[0] += n_i;
	return n_i;

rtattr_failure:
	skb_trim(skb, (u8*)r - skb->data);
	goto done;
}
#endif

void tcf_police_destroy(struct tcf_police *p)
{
112 113
	unsigned int h = tcf_hash(p->tcf_index, POL_TAB_MASK);
	struct tcf_common **p1p;
114

115 116
	for (p1p = &tcf_police_ht[h]; *p1p; p1p = &(*p1p)->tcfc_next) {
		if (*p1p == &p->common) {
L
Linus Torvalds 已提交
117
			write_lock_bh(&police_lock);
118
			*p1p = p->tcf_next;
L
Linus Torvalds 已提交
119 120
			write_unlock_bh(&police_lock);
#ifdef CONFIG_NET_ESTIMATOR
121 122
			gen_kill_estimator(&p->tcf_bstats,
					   &p->tcf_rate_est);
L
Linus Torvalds 已提交
123
#endif
124 125 126 127
			if (p->tcfp_R_tab)
				qdisc_put_rtab(p->tcfp_R_tab);
			if (p->tcfp_P_tab)
				qdisc_put_rtab(p->tcfp_P_tab);
L
Linus Torvalds 已提交
128 129 130 131 132 133 134 135 136
			kfree(p);
			return;
		}
	}
	BUG_TRAP(0);
}

#ifdef CONFIG_NET_CLS_ACT
static int tcf_act_police_locate(struct rtattr *rta, struct rtattr *est,
137
				 struct tc_action *a, int ovr, int bind)
L
Linus Torvalds 已提交
138 139 140 141 142
{
	unsigned h;
	int ret = 0, err;
	struct rtattr *tb[TCA_POLICE_MAX];
	struct tc_police *parm;
143
	struct tcf_police *police;
L
Linus Torvalds 已提交
144
	struct qdisc_rate_table *R_tab = NULL, *P_tab = NULL;
145
	int size;
L
Linus Torvalds 已提交
146 147 148 149

	if (rta == NULL || rtattr_parse_nested(tb, TCA_POLICE_MAX, rta) < 0)
		return -EINVAL;

150 151 152 153
	if (tb[TCA_POLICE_TBF-1] == NULL)
		return -EINVAL;
	size = RTA_PAYLOAD(tb[TCA_POLICE_TBF-1]);
	if (size != sizeof(*parm) && size != sizeof(struct tc_police_compat))
L
Linus Torvalds 已提交
154 155 156 157 158 159 160 161 162 163
		return -EINVAL;
	parm = RTA_DATA(tb[TCA_POLICE_TBF-1]);

	if (tb[TCA_POLICE_RESULT-1] != NULL &&
	    RTA_PAYLOAD(tb[TCA_POLICE_RESULT-1]) != sizeof(u32))
		return -EINVAL;
	if (tb[TCA_POLICE_RESULT-1] != NULL &&
	    RTA_PAYLOAD(tb[TCA_POLICE_RESULT-1]) != sizeof(u32))
		return -EINVAL;

164 165 166 167 168 169 170 171 172 173 174 175 176 177
	if (parm->index) {
		struct tcf_common *pc;

		pc = tcf_hash_lookup(parm->index, &police_hash_info);
		if (pc != NULL) {
			a->priv = pc;
			police = to_police(pc);
			if (bind) {
				police->tcf_bindcnt += 1;
				police->tcf_refcnt += 1;
			}
			if (ovr)
				goto override;
			return ret;
L
Linus Torvalds 已提交
178 179 180
		}
	}

181 182
	police = kzalloc(sizeof(*police), GFP_KERNEL);
	if (police == NULL)
L
Linus Torvalds 已提交
183 184
		return -ENOMEM;
	ret = ACT_P_CREATED;
185 186 187
	police->tcf_refcnt = 1;
	spin_lock_init(&police->tcf_lock);
	police->tcf_stats_lock = &police->tcf_lock;
L
Linus Torvalds 已提交
188
	if (bind)
189
		police->tcf_bindcnt = 1;
L
Linus Torvalds 已提交
190 191 192 193 194 195 196 197 198
override:
	if (parm->rate.rate) {
		err = -ENOMEM;
		R_tab = qdisc_get_rtab(&parm->rate, tb[TCA_POLICE_RATE-1]);
		if (R_tab == NULL)
			goto failure;
		if (parm->peakrate.rate) {
			P_tab = qdisc_get_rtab(&parm->peakrate,
					       tb[TCA_POLICE_PEAKRATE-1]);
199
			if (P_tab == NULL) {
L
Linus Torvalds 已提交
200 201 202 203 204 205
				qdisc_put_rtab(R_tab);
				goto failure;
			}
		}
	}
	/* No failure allowed after this point */
206
	spin_lock_bh(&police->tcf_lock);
L
Linus Torvalds 已提交
207
	if (R_tab != NULL) {
208 209
		qdisc_put_rtab(police->tcfp_R_tab);
		police->tcfp_R_tab = R_tab;
L
Linus Torvalds 已提交
210 211
	}
	if (P_tab != NULL) {
212 213
		qdisc_put_rtab(police->tcfp_P_tab);
		police->tcfp_P_tab = P_tab;
L
Linus Torvalds 已提交
214 215 216
	}

	if (tb[TCA_POLICE_RESULT-1])
217 218 219 220 221 222 223
		police->tcfp_result = *(u32*)RTA_DATA(tb[TCA_POLICE_RESULT-1]);
	police->tcfp_toks = police->tcfp_burst = parm->burst;
	police->tcfp_mtu = parm->mtu;
	if (police->tcfp_mtu == 0) {
		police->tcfp_mtu = ~0;
		if (police->tcfp_R_tab)
			police->tcfp_mtu = 255<<police->tcfp_R_tab->rate.cell_log;
L
Linus Torvalds 已提交
224
	}
225 226 227
	if (police->tcfp_P_tab)
		police->tcfp_ptoks = L2T_P(police, police->tcfp_mtu);
	police->tcf_action = parm->action;
L
Linus Torvalds 已提交
228 229 230

#ifdef CONFIG_NET_ESTIMATOR
	if (tb[TCA_POLICE_AVRATE-1])
231 232
		police->tcfp_ewma_rate =
			*(u32*)RTA_DATA(tb[TCA_POLICE_AVRATE-1]);
L
Linus Torvalds 已提交
233
	if (est)
234 235 236
		gen_replace_estimator(&police->tcf_bstats,
				      &police->tcf_rate_est,
				      police->tcf_stats_lock, est);
L
Linus Torvalds 已提交
237 238
#endif

239
	spin_unlock_bh(&police->tcf_lock);
L
Linus Torvalds 已提交
240 241 242
	if (ret != ACT_P_CREATED)
		return ret;

243 244 245 246
	PSCHED_GET_TIME(police->tcfp_t_c);
	police->tcf_index = parm->index ? parm->index :
		tcf_hash_new_index(&police_idx_gen, &police_hash_info);
	h = tcf_hash(police->tcf_index, POL_TAB_MASK);
L
Linus Torvalds 已提交
247
	write_lock_bh(&police_lock);
248 249
	police->tcf_next = tcf_police_ht[h];
	tcf_police_ht[h] = &police->common;
L
Linus Torvalds 已提交
250 251
	write_unlock_bh(&police_lock);

252
	a->priv = police;
L
Linus Torvalds 已提交
253 254 255 256
	return ret;

failure:
	if (ret == ACT_P_CREATED)
257
		kfree(police);
L
Linus Torvalds 已提交
258 259 260 261 262
	return err;
}

static int tcf_act_police_cleanup(struct tc_action *a, int bind)
{
263
	struct tcf_police *p = a->priv;
L
Linus Torvalds 已提交
264 265 266 267 268 269

	if (p != NULL)
		return tcf_police_release(p, bind);
	return 0;
}

270
static int tcf_act_police(struct sk_buff *skb, struct tc_action *a,
271
			  struct tcf_result *res)
L
Linus Torvalds 已提交
272
{
273
	struct tcf_police *police = a->priv;
L
Linus Torvalds 已提交
274 275 276 277
	psched_time_t now;
	long toks;
	long ptoks = 0;

278
	spin_lock(&police->tcf_lock);
L
Linus Torvalds 已提交
279

280 281
	police->tcf_bstats.bytes += skb->len;
	police->tcf_bstats.packets++;
L
Linus Torvalds 已提交
282 283

#ifdef CONFIG_NET_ESTIMATOR
284 285 286 287 288
	if (police->tcfp_ewma_rate &&
	    police->tcf_rate_est.bps >= police->tcfp_ewma_rate) {
		police->tcf_qstats.overlimits++;
		spin_unlock(&police->tcf_lock);
		return police->tcf_action;
L
Linus Torvalds 已提交
289 290 291
	}
#endif

292 293 294 295
	if (skb->len <= police->tcfp_mtu) {
		if (police->tcfp_R_tab == NULL) {
			spin_unlock(&police->tcf_lock);
			return police->tcfp_result;
L
Linus Torvalds 已提交
296 297 298 299
		}

		PSCHED_GET_TIME(now);

300 301 302 303 304 305 306
		toks = PSCHED_TDIFF_SAFE(now, police->tcfp_t_c,
					 police->tcfp_burst);
		if (police->tcfp_P_tab) {
			ptoks = toks + police->tcfp_ptoks;
			if (ptoks > (long)L2T_P(police, police->tcfp_mtu))
				ptoks = (long)L2T_P(police, police->tcfp_mtu);
			ptoks -= L2T_P(police, skb->len);
L
Linus Torvalds 已提交
307
		}
308 309 310 311
		toks += police->tcfp_toks;
		if (toks > (long)police->tcfp_burst)
			toks = police->tcfp_burst;
		toks -= L2T(police, skb->len);
L
Linus Torvalds 已提交
312
		if ((toks|ptoks) >= 0) {
313 314 315 316 317
			police->tcfp_t_c = now;
			police->tcfp_toks = toks;
			police->tcfp_ptoks = ptoks;
			spin_unlock(&police->tcf_lock);
			return police->tcfp_result;
L
Linus Torvalds 已提交
318 319 320
		}
	}

321 322 323
	police->tcf_qstats.overlimits++;
	spin_unlock(&police->tcf_lock);
	return police->tcf_action;
L
Linus Torvalds 已提交
324 325 326 327 328 329
}

static int
tcf_act_police_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
{
	unsigned char	 *b = skb->tail;
330
	struct tcf_police *police = a->priv;
L
Linus Torvalds 已提交
331
	struct tc_police opt;
332 333 334 335 336 337 338 339 340

	opt.index = police->tcf_index;
	opt.action = police->tcf_action;
	opt.mtu = police->tcfp_mtu;
	opt.burst = police->tcfp_burst;
	opt.refcnt = police->tcf_refcnt - ref;
	opt.bindcnt = police->tcf_bindcnt - bind;
	if (police->tcfp_R_tab)
		opt.rate = police->tcfp_R_tab->rate;
L
Linus Torvalds 已提交
341 342
	else
		memset(&opt.rate, 0, sizeof(opt.rate));
343 344
	if (police->tcfp_P_tab)
		opt.peakrate = police->tcfp_P_tab->rate;
L
Linus Torvalds 已提交
345 346 347
	else
		memset(&opt.peakrate, 0, sizeof(opt.peakrate));
	RTA_PUT(skb, TCA_POLICE_TBF, sizeof(opt), &opt);
348 349 350
	if (police->tcfp_result)
		RTA_PUT(skb, TCA_POLICE_RESULT, sizeof(int),
			&police->tcfp_result);
L
Linus Torvalds 已提交
351
#ifdef CONFIG_NET_ESTIMATOR
352 353
	if (police->tcfp_ewma_rate)
		RTA_PUT(skb, TCA_POLICE_AVRATE, 4, &police->tcfp_ewma_rate);
L
Linus Torvalds 已提交
354 355 356 357 358 359 360 361 362 363 364 365 366 367
#endif
	return skb->len;

rtattr_failure:
	skb_trim(skb, b - skb->data);
	return -1;
}

MODULE_AUTHOR("Alexey Kuznetsov");
MODULE_DESCRIPTION("Policing actions");
MODULE_LICENSE("GPL");

static struct tc_action_ops act_police_ops = {
	.kind		=	"police",
368
	.hinfo		=	&police_hash_info,
L
Linus Torvalds 已提交
369 370 371 372 373 374
	.type		=	TCA_ID_POLICE,
	.capab		=	TCA_CAP_NONE,
	.owner		=	THIS_MODULE,
	.act		=	tcf_act_police,
	.dump		=	tcf_act_police_dump,
	.cleanup	=	tcf_act_police_cleanup,
375
	.lookup		=	tcf_hash_search,
L
Linus Torvalds 已提交
376
	.init		=	tcf_act_police_locate,
377
	.walk		=	tcf_act_police_walker
L
Linus Torvalds 已提交
378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394
};

static int __init
police_init_module(void)
{
	return tcf_register_action(&act_police_ops);
}

static void __exit
police_cleanup_module(void)
{
	tcf_unregister_action(&act_police_ops);
}

module_init(police_init_module);
module_exit(police_cleanup_module);

395
#else /* CONFIG_NET_CLS_ACT */
L
Linus Torvalds 已提交
396

397
static struct tcf_common *tcf_police_lookup(u32 index)
L
Linus Torvalds 已提交
398
{
399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429
	struct tcf_hashinfo *hinfo = &police_hash_info;
	struct tcf_common *p;

	read_lock(hinfo->lock);
	for (p = hinfo->htab[tcf_hash(index, hinfo->hmask)]; p;
	     p = p->tcfc_next) {
		if (p->tcfc_index == index)
			break;
	}
	read_unlock(hinfo->lock);

	return p;
}

static u32 tcf_police_new_index(void)
{
	u32 *idx_gen = &police_idx_gen;
	u32 val = *idx_gen;

	do {
		if (++val == 0)
			val = 1;
	} while (tcf_police_lookup(val));

	return (*idx_gen = val);
}

struct tcf_police *tcf_police_locate(struct rtattr *rta, struct rtattr *est)
{
	unsigned int h;
	struct tcf_police *police;
L
Linus Torvalds 已提交
430 431
	struct rtattr *tb[TCA_POLICE_MAX];
	struct tc_police *parm;
432
	int size;
L
Linus Torvalds 已提交
433 434 435 436

	if (rtattr_parse_nested(tb, TCA_POLICE_MAX, rta) < 0)
		return NULL;

437 438 439 440
	if (tb[TCA_POLICE_TBF-1] == NULL)
		return NULL;
	size = RTA_PAYLOAD(tb[TCA_POLICE_TBF-1]);
	if (size != sizeof(*parm) && size != sizeof(struct tc_police_compat))
L
Linus Torvalds 已提交
441 442 443 444
		return NULL;

	parm = RTA_DATA(tb[TCA_POLICE_TBF-1]);

445 446
	if (parm->index) {
		struct tcf_common *pc;
L
Linus Torvalds 已提交
447

448 449 450 451 452 453 454 455 456
		pc = tcf_police_lookup(parm->index);
		if (pc) {
			police = to_police(pc);
			police->tcf_refcnt++;
			return police;
		}
	}
	police = kzalloc(sizeof(*police), GFP_KERNEL);
	if (unlikely(!police))
L
Linus Torvalds 已提交
457 458
		return NULL;

459 460 461
	police->tcf_refcnt = 1;
	spin_lock_init(&police->tcf_lock);
	police->tcf_stats_lock = &police->tcf_lock;
L
Linus Torvalds 已提交
462
	if (parm->rate.rate) {
463 464 465
		police->tcfp_R_tab =
			qdisc_get_rtab(&parm->rate, tb[TCA_POLICE_RATE-1]);
		if (police->tcfp_R_tab == NULL)
L
Linus Torvalds 已提交
466 467
			goto failure;
		if (parm->peakrate.rate) {
468 469 470 471
			police->tcfp_P_tab =
				qdisc_get_rtab(&parm->peakrate,
					       tb[TCA_POLICE_PEAKRATE-1]);
			if (police->tcfp_P_tab == NULL)
L
Linus Torvalds 已提交
472 473 474 475 476 477
				goto failure;
		}
	}
	if (tb[TCA_POLICE_RESULT-1]) {
		if (RTA_PAYLOAD(tb[TCA_POLICE_RESULT-1]) != sizeof(u32))
			goto failure;
478
		police->tcfp_result = *(u32*)RTA_DATA(tb[TCA_POLICE_RESULT-1]);
L
Linus Torvalds 已提交
479 480 481 482 483
	}
#ifdef CONFIG_NET_ESTIMATOR
	if (tb[TCA_POLICE_AVRATE-1]) {
		if (RTA_PAYLOAD(tb[TCA_POLICE_AVRATE-1]) != sizeof(u32))
			goto failure;
484 485
		police->tcfp_ewma_rate =
			*(u32*)RTA_DATA(tb[TCA_POLICE_AVRATE-1]);
L
Linus Torvalds 已提交
486 487
	}
#endif
488 489 490 491 492 493
	police->tcfp_toks = police->tcfp_burst = parm->burst;
	police->tcfp_mtu = parm->mtu;
	if (police->tcfp_mtu == 0) {
		police->tcfp_mtu = ~0;
		if (police->tcfp_R_tab)
			police->tcfp_mtu = 255<<police->tcfp_R_tab->rate.cell_log;
L
Linus Torvalds 已提交
494
	}
495 496 497 498 499 500
	if (police->tcfp_P_tab)
		police->tcfp_ptoks = L2T_P(police, police->tcfp_mtu);
	PSCHED_GET_TIME(police->tcfp_t_c);
	police->tcf_index = parm->index ? parm->index :
		tcf_police_new_index();
	police->tcf_action = parm->action;
L
Linus Torvalds 已提交
501 502
#ifdef CONFIG_NET_ESTIMATOR
	if (est)
503 504
		gen_new_estimator(&police->tcf_bstats, &police->tcf_rate_est,
				  police->tcf_stats_lock, est);
L
Linus Torvalds 已提交
505
#endif
506
	h = tcf_hash(police->tcf_index, POL_TAB_MASK);
L
Linus Torvalds 已提交
507
	write_lock_bh(&police_lock);
508 509
	police->tcf_next = tcf_police_ht[h];
	tcf_police_ht[h] = &police->common;
L
Linus Torvalds 已提交
510
	write_unlock_bh(&police_lock);
511
	return police;
L
Linus Torvalds 已提交
512 513

failure:
514 515 516
	if (police->tcfp_R_tab)
		qdisc_put_rtab(police->tcfp_R_tab);
	kfree(police);
L
Linus Torvalds 已提交
517 518 519
	return NULL;
}

520
int tcf_police(struct sk_buff *skb, struct tcf_police *police)
L
Linus Torvalds 已提交
521 522 523 524 525
{
	psched_time_t now;
	long toks;
	long ptoks = 0;

526
	spin_lock(&police->tcf_lock);
L
Linus Torvalds 已提交
527

528 529
	police->tcf_bstats.bytes += skb->len;
	police->tcf_bstats.packets++;
L
Linus Torvalds 已提交
530 531

#ifdef CONFIG_NET_ESTIMATOR
532 533 534 535 536
	if (police->tcfp_ewma_rate &&
	    police->tcf_rate_est.bps >= police->tcfp_ewma_rate) {
		police->tcf_qstats.overlimits++;
		spin_unlock(&police->tcf_lock);
		return police->tcf_action;
L
Linus Torvalds 已提交
537 538
	}
#endif
539 540 541 542
	if (skb->len <= police->tcfp_mtu) {
		if (police->tcfp_R_tab == NULL) {
			spin_unlock(&police->tcf_lock);
			return police->tcfp_result;
L
Linus Torvalds 已提交
543 544 545
		}

		PSCHED_GET_TIME(now);
546 547 548 549 550 551 552
		toks = PSCHED_TDIFF_SAFE(now, police->tcfp_t_c,
					 police->tcfp_burst);
		if (police->tcfp_P_tab) {
			ptoks = toks + police->tcfp_ptoks;
			if (ptoks > (long)L2T_P(police, police->tcfp_mtu))
				ptoks = (long)L2T_P(police, police->tcfp_mtu);
			ptoks -= L2T_P(police, skb->len);
L
Linus Torvalds 已提交
553
		}
554 555 556 557
		toks += police->tcfp_toks;
		if (toks > (long)police->tcfp_burst)
			toks = police->tcfp_burst;
		toks -= L2T(police, skb->len);
L
Linus Torvalds 已提交
558
		if ((toks|ptoks) >= 0) {
559 560 561 562 563
			police->tcfp_t_c = now;
			police->tcfp_toks = toks;
			police->tcfp_ptoks = ptoks;
			spin_unlock(&police->tcf_lock);
			return police->tcfp_result;
L
Linus Torvalds 已提交
564 565 566
		}
	}

567 568 569
	police->tcf_qstats.overlimits++;
	spin_unlock(&police->tcf_lock);
	return police->tcf_action;
L
Linus Torvalds 已提交
570
}
571
EXPORT_SYMBOL(tcf_police);
L
Linus Torvalds 已提交
572

573
int tcf_police_dump(struct sk_buff *skb, struct tcf_police *police)
L
Linus Torvalds 已提交
574
{
575
	unsigned char *b = skb->tail;
L
Linus Torvalds 已提交
576 577
	struct tc_police opt;

578 579 580 581 582 583
	opt.index = police->tcf_index;
	opt.action = police->tcf_action;
	opt.mtu = police->tcfp_mtu;
	opt.burst = police->tcfp_burst;
	if (police->tcfp_R_tab)
		opt.rate = police->tcfp_R_tab->rate;
L
Linus Torvalds 已提交
584 585
	else
		memset(&opt.rate, 0, sizeof(opt.rate));
586 587
	if (police->tcfp_P_tab)
		opt.peakrate = police->tcfp_P_tab->rate;
L
Linus Torvalds 已提交
588 589 590
	else
		memset(&opt.peakrate, 0, sizeof(opt.peakrate));
	RTA_PUT(skb, TCA_POLICE_TBF, sizeof(opt), &opt);
591 592 593
	if (police->tcfp_result)
		RTA_PUT(skb, TCA_POLICE_RESULT, sizeof(int),
			&police->tcfp_result);
L
Linus Torvalds 已提交
594
#ifdef CONFIG_NET_ESTIMATOR
595 596
	if (police->tcfp_ewma_rate)
		RTA_PUT(skb, TCA_POLICE_AVRATE, 4, &police->tcfp_ewma_rate);
L
Linus Torvalds 已提交
597 598 599 600 601 602 603 604
#endif
	return skb->len;

rtattr_failure:
	skb_trim(skb, b - skb->data);
	return -1;
}

605
int tcf_police_dump_stats(struct sk_buff *skb, struct tcf_police *police)
L
Linus Torvalds 已提交
606 607
{
	struct gnet_dump d;
608

L
Linus Torvalds 已提交
609
	if (gnet_stats_start_copy_compat(skb, TCA_STATS2, TCA_STATS,
610 611
					 TCA_XSTATS, police->tcf_stats_lock,
					 &d) < 0)
L
Linus Torvalds 已提交
612
		goto errout;
613

614
	if (gnet_stats_copy_basic(&d, &police->tcf_bstats) < 0 ||
L
Linus Torvalds 已提交
615
#ifdef CONFIG_NET_ESTIMATOR
616
	    gnet_stats_copy_rate_est(&d, &police->tcf_rate_est) < 0 ||
L
Linus Torvalds 已提交
617
#endif
618
	    gnet_stats_copy_queue(&d, &police->tcf_qstats) < 0)
L
Linus Torvalds 已提交
619 620 621 622 623 624 625 626 627 628 629
		goto errout;

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

	return 0;

errout:
	return -1;
}

630
#endif /* CONFIG_NET_CLS_ACT */