aboutsummaryrefslogtreecommitdiffstats
path: root/net/sched/cls_api.c
diff options
context:
space:
mode:
authorWANG Cong <xiyou.wangcong@gmail.com>2013-12-15 23:15:05 -0500
committerDavid S. Miller <davem@davemloft.net>2013-12-18 12:52:07 -0500
commit33be627159913b094bb578e83e9a7fdc66c10208 (patch)
tree387945e9391082d0b78890b176111a53b8897bf3 /net/sched/cls_api.c
parentd84231d3a2b20bea26327d9b83c8bd8ba55dc68c (diff)
net_sched: act: use standard struct list_head
Currently actions are chained by a singly linked list, therefore it is a bit hard to add and remove a specific entry. Convert it to struct list_head so that in the latter patch we can remove an action without finding its head. Cc: Jamal Hadi Salim <jhs@mojatatu.com> Cc: David S. Miller <davem@davemloft.net> Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com> Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sched/cls_api.c')
-rw-r--r--net/sched/cls_api.c54
1 files changed, 26 insertions, 28 deletions
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index 8e118af90973..3c056d73d394 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -500,10 +500,8 @@ out:
500void tcf_exts_destroy(struct tcf_proto *tp, struct tcf_exts *exts) 500void tcf_exts_destroy(struct tcf_proto *tp, struct tcf_exts *exts)
501{ 501{
502#ifdef CONFIG_NET_CLS_ACT 502#ifdef CONFIG_NET_CLS_ACT
503 if (exts->action) { 503 tcf_action_destroy(&exts->actions, TCA_ACT_UNBIND);
504 tcf_action_destroy(exts->action, TCA_ACT_UNBIND); 504 INIT_LIST_HEAD(&exts->actions);
505 exts->action = NULL;
506 }
507#endif 505#endif
508} 506}
509EXPORT_SYMBOL(tcf_exts_destroy); 507EXPORT_SYMBOL(tcf_exts_destroy);
@@ -518,6 +516,7 @@ int tcf_exts_validate(struct net *net, struct tcf_proto *tp, struct nlattr **tb,
518 { 516 {
519 struct tc_action *act; 517 struct tc_action *act;
520 518
519 INIT_LIST_HEAD(&exts->actions);
521 if (map->police && tb[map->police]) { 520 if (map->police && tb[map->police]) {
522 act = tcf_action_init_1(net, tb[map->police], rate_tlv, 521 act = tcf_action_init_1(net, tb[map->police], rate_tlv,
523 "police", TCA_ACT_NOREPLACE, 522 "police", TCA_ACT_NOREPLACE,
@@ -525,16 +524,15 @@ int tcf_exts_validate(struct net *net, struct tcf_proto *tp, struct nlattr **tb,
525 if (IS_ERR(act)) 524 if (IS_ERR(act))
526 return PTR_ERR(act); 525 return PTR_ERR(act);
527 526
528 act->type = TCA_OLD_COMPAT; 527 act->type = exts->type = TCA_OLD_COMPAT;
529 exts->action = act; 528 list_add(&act->list, &exts->actions);
530 } else if (map->action && tb[map->action]) { 529 } else if (map->action && tb[map->action]) {
531 act = tcf_action_init(net, tb[map->action], rate_tlv, 530 int err;
531 err = tcf_action_init(net, tb[map->action], rate_tlv,
532 NULL, TCA_ACT_NOREPLACE, 532 NULL, TCA_ACT_NOREPLACE,
533 TCA_ACT_BIND); 533 TCA_ACT_BIND, &exts->actions);
534 if (IS_ERR(act)) 534 if (err)
535 return PTR_ERR(act); 535 return err;
536
537 exts->action = act;
538 } 536 }
539 } 537 }
540#else 538#else
@@ -551,43 +549,45 @@ void tcf_exts_change(struct tcf_proto *tp, struct tcf_exts *dst,
551 struct tcf_exts *src) 549 struct tcf_exts *src)
552{ 550{
553#ifdef CONFIG_NET_CLS_ACT 551#ifdef CONFIG_NET_CLS_ACT
554 if (src->action) { 552 if (!list_empty(&src->actions)) {
555 struct tc_action *act; 553 LIST_HEAD(tmp);
556 tcf_tree_lock(tp); 554 tcf_tree_lock(tp);
557 act = dst->action; 555 list_splice_init(&dst->actions, &tmp);
558 dst->action = src->action; 556 list_splice(&src->actions, &dst->actions);
559 tcf_tree_unlock(tp); 557 tcf_tree_unlock(tp);
560 if (act) 558 tcf_action_destroy(&tmp, TCA_ACT_UNBIND);
561 tcf_action_destroy(act, TCA_ACT_UNBIND);
562 } 559 }
563#endif 560#endif
564} 561}
565EXPORT_SYMBOL(tcf_exts_change); 562EXPORT_SYMBOL(tcf_exts_change);
566 563
564#define tcf_exts_first_act(ext) \
565 list_first_entry(&(exts)->actions, struct tc_action, list)
566
567int tcf_exts_dump(struct sk_buff *skb, struct tcf_exts *exts, 567int tcf_exts_dump(struct sk_buff *skb, struct tcf_exts *exts,
568 const struct tcf_ext_map *map) 568 const struct tcf_ext_map *map)
569{ 569{
570#ifdef CONFIG_NET_CLS_ACT 570#ifdef CONFIG_NET_CLS_ACT
571 if (map->action && exts->action) { 571 if (map->action && !list_empty(&exts->actions)) {
572 /* 572 /*
573 * again for backward compatible mode - we want 573 * again for backward compatible mode - we want
574 * to work with both old and new modes of entering 574 * to work with both old and new modes of entering
575 * tc data even if iproute2 was newer - jhs 575 * tc data even if iproute2 was newer - jhs
576 */ 576 */
577 struct nlattr *nest; 577 struct nlattr *nest;
578 578 if (exts->type != TCA_OLD_COMPAT) {
579 if (exts->action->type != TCA_OLD_COMPAT) {
580 nest = nla_nest_start(skb, map->action); 579 nest = nla_nest_start(skb, map->action);
581 if (nest == NULL) 580 if (nest == NULL)
582 goto nla_put_failure; 581 goto nla_put_failure;
583 if (tcf_action_dump(skb, exts->action, 0, 0) < 0) 582 if (tcf_action_dump(skb, &exts->actions, 0, 0) < 0)
584 goto nla_put_failure; 583 goto nla_put_failure;
585 nla_nest_end(skb, nest); 584 nla_nest_end(skb, nest);
586 } else if (map->police) { 585 } else if (map->police) {
586 struct tc_action *act = tcf_exts_first_act(exts);
587 nest = nla_nest_start(skb, map->police); 587 nest = nla_nest_start(skb, map->police);
588 if (nest == NULL) 588 if (nest == NULL)
589 goto nla_put_failure; 589 goto nla_put_failure;
590 if (tcf_action_dump_old(skb, exts->action, 0, 0) < 0) 590 if (tcf_action_dump_old(skb, act, 0, 0) < 0)
591 goto nla_put_failure; 591 goto nla_put_failure;
592 nla_nest_end(skb, nest); 592 nla_nest_end(skb, nest);
593 } 593 }
@@ -604,13 +604,11 @@ int tcf_exts_dump_stats(struct sk_buff *skb, struct tcf_exts *exts,
604 const struct tcf_ext_map *map) 604 const struct tcf_ext_map *map)
605{ 605{
606#ifdef CONFIG_NET_CLS_ACT 606#ifdef CONFIG_NET_CLS_ACT
607 if (exts->action) 607 struct tc_action *a = tcf_exts_first_act(exts);
608 if (tcf_action_copy_stats(skb, exts->action, 1) < 0) 608 if (tcf_action_copy_stats(skb, a, 1) < 0)
609 goto nla_put_failure; 609 return -1;
610#endif 610#endif
611 return 0; 611 return 0;
612nla_put_failure: __attribute__ ((unused))
613 return -1;
614} 612}
615EXPORT_SYMBOL(tcf_exts_dump_stats); 613EXPORT_SYMBOL(tcf_exts_dump_stats);
616 614