Skip to content

Commit 33be627

Browse files
congwangdavem330
authored andcommitted
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 <[email protected]> Cc: David S. Miller <[email protected]> Signed-off-by: Cong Wang <[email protected]> Signed-off-by: Jamal Hadi Salim <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent d84231d commit 33be627

File tree

13 files changed

+101
-99
lines changed

13 files changed

+101
-99
lines changed

include/net/act_api.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ struct tc_action {
6060
const struct tc_action_ops *ops;
6161
__u32 type; /* for backward compat(TCA_OLD_COMPAT) */
6262
__u32 order;
63-
struct tc_action *next;
63+
struct list_head list;
6464
};
6565

6666
#define TCA_CAP_NONE 0
@@ -99,16 +99,16 @@ void tcf_hash_insert(struct tcf_common *p, struct tcf_hashinfo *hinfo);
9999

100100
int tcf_register_action(struct tc_action_ops *a);
101101
int tcf_unregister_action(struct tc_action_ops *a);
102-
void tcf_action_destroy(struct tc_action *a, int bind);
103-
int tcf_action_exec(struct sk_buff *skb, const struct tc_action *a,
102+
void tcf_action_destroy(struct list_head *actions, int bind);
103+
int tcf_action_exec(struct sk_buff *skb, const struct list_head *actions,
104104
struct tcf_result *res);
105-
struct tc_action *tcf_action_init(struct net *net, struct nlattr *nla,
105+
int tcf_action_init(struct net *net, struct nlattr *nla,
106106
struct nlattr *est, char *n, int ovr,
107-
int bind);
107+
int bind, struct list_head *);
108108
struct tc_action *tcf_action_init_1(struct net *net, struct nlattr *nla,
109109
struct nlattr *est, char *n, int ovr,
110110
int bind);
111-
int tcf_action_dump(struct sk_buff *skb, struct tc_action *a, int, int);
111+
int tcf_action_dump(struct sk_buff *skb, struct list_head *, int, int);
112112
int tcf_action_dump_old(struct sk_buff *skb, struct tc_action *a, int, int);
113113
int tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int, int);
114114
int tcf_action_copy_stats(struct sk_buff *, struct tc_action *, int);

include/net/pkt_cls.h

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,8 @@ tcf_unbind_filter(struct tcf_proto *tp, struct tcf_result *r)
6262

6363
struct tcf_exts {
6464
#ifdef CONFIG_NET_CLS_ACT
65-
struct tc_action *action;
65+
__u32 type; /* for backward compat(TCA_OLD_COMPAT) */
66+
struct list_head actions;
6667
#endif
6768
};
6869

@@ -74,6 +75,13 @@ struct tcf_ext_map {
7475
int police;
7576
};
7677

78+
static inline void tcf_exts_init(struct tcf_exts *exts)
79+
{
80+
#ifdef CONFIG_NET_CLS_ACT
81+
INIT_LIST_HEAD(&exts->actions);
82+
#endif
83+
}
84+
7785
/**
7886
* tcf_exts_is_predicative - check if a predicative extension is present
7987
* @exts: tc filter extensions handle
@@ -85,7 +93,7 @@ static inline int
8593
tcf_exts_is_predicative(struct tcf_exts *exts)
8694
{
8795
#ifdef CONFIG_NET_CLS_ACT
88-
return !!exts->action;
96+
return !list_empty(&exts->actions);
8997
#else
9098
return 0;
9199
#endif
@@ -120,8 +128,8 @@ tcf_exts_exec(struct sk_buff *skb, struct tcf_exts *exts,
120128
struct tcf_result *res)
121129
{
122130
#ifdef CONFIG_NET_CLS_ACT
123-
if (exts->action)
124-
return tcf_action_exec(skb, exts->action, res);
131+
if (!list_empty(&exts->actions))
132+
return tcf_action_exec(skb, &exts->actions, res);
125133
#endif
126134
return 0;
127135
}

net/sched/act_api.c

Lines changed: 45 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -379,7 +379,7 @@ static struct tc_action_ops *tc_lookup_action_id(u32 type)
379379
}
380380
#endif
381381

382-
int tcf_action_exec(struct sk_buff *skb, const struct tc_action *act,
382+
int tcf_action_exec(struct sk_buff *skb, const struct list_head *actions,
383383
struct tcf_result *res)
384384
{
385385
const struct tc_action *a;
@@ -390,7 +390,7 @@ int tcf_action_exec(struct sk_buff *skb, const struct tc_action *act,
390390
ret = TC_ACT_OK;
391391
goto exec_done;
392392
}
393-
while ((a = act) != NULL) {
393+
list_for_each_entry(a, actions, list) {
394394
repeat:
395395
if (a->ops) {
396396
ret = a->ops->act(skb, a, res);
@@ -404,27 +404,26 @@ int tcf_action_exec(struct sk_buff *skb, const struct tc_action *act,
404404
if (ret != TC_ACT_PIPE)
405405
goto exec_done;
406406
}
407-
act = a->next;
408407
}
409408
exec_done:
410409
return ret;
411410
}
412411
EXPORT_SYMBOL(tcf_action_exec);
413412

414-
void tcf_action_destroy(struct tc_action *act, int bind)
413+
void tcf_action_destroy(struct list_head *actions, int bind)
415414
{
416-
struct tc_action *a;
415+
struct tc_action *a, *tmp;
417416

418-
for (a = act; a; a = act) {
417+
list_for_each_entry_safe(a, tmp, actions, list) {
419418
if (a->ops) {
420419
if (a->ops->cleanup(a, bind) == ACT_P_DELETED)
421420
module_put(a->ops->owner);
422-
act = act->next;
421+
list_del(&a->list);
423422
kfree(a);
424423
} else {
425424
/*FIXME: Remove later - catch insertion bugs*/
426425
WARN(1, "tcf_action_destroy: BUG? destroying NULL ops\n");
427-
act = act->next;
426+
list_del(&a->list);
428427
kfree(a);
429428
}
430429
}
@@ -470,14 +469,13 @@ tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
470469
EXPORT_SYMBOL(tcf_action_dump_1);
471470

472471
int
473-
tcf_action_dump(struct sk_buff *skb, struct tc_action *act, int bind, int ref)
472+
tcf_action_dump(struct sk_buff *skb, struct list_head *actions, int bind, int ref)
474473
{
475474
struct tc_action *a;
476475
int err = -EINVAL;
477476
struct nlattr *nest;
478477

479-
while ((a = act) != NULL) {
480-
act = a->next;
478+
list_for_each_entry(a, actions, list) {
481479
nest = nla_nest_start(skb, a->order);
482480
if (nest == NULL)
483481
goto nla_put_failure;
@@ -552,6 +550,7 @@ struct tc_action *tcf_action_init_1(struct net *net, struct nlattr *nla,
552550
if (a == NULL)
553551
goto err_mod;
554552

553+
INIT_LIST_HEAD(&a->list);
555554
/* backward compatibility for policer */
556555
if (name == NULL)
557556
err = a_o->init(net, tb[TCA_ACT_OPTIONS], est, a, ovr, bind);
@@ -578,37 +577,33 @@ struct tc_action *tcf_action_init_1(struct net *net, struct nlattr *nla,
578577
return ERR_PTR(err);
579578
}
580579

581-
struct tc_action *tcf_action_init(struct net *net, struct nlattr *nla,
580+
int tcf_action_init(struct net *net, struct nlattr *nla,
582581
struct nlattr *est, char *name, int ovr,
583-
int bind)
582+
int bind, struct list_head *actions)
584583
{
585584
struct nlattr *tb[TCA_ACT_MAX_PRIO + 1];
586-
struct tc_action *head = NULL, *act, *act_prev = NULL;
585+
struct tc_action *act;
587586
int err;
588587
int i;
589588

590589
err = nla_parse_nested(tb, TCA_ACT_MAX_PRIO, nla, NULL);
591590
if (err < 0)
592-
return ERR_PTR(err);
591+
return err;
593592

594593
for (i = 1; i <= TCA_ACT_MAX_PRIO && tb[i]; i++) {
595594
act = tcf_action_init_1(net, tb[i], est, name, ovr, bind);
596-
if (IS_ERR(act))
595+
if (IS_ERR(act)) {
596+
err = PTR_ERR(act);
597597
goto err;
598+
}
598599
act->order = i;
599-
600-
if (head == NULL)
601-
head = act;
602-
else
603-
act_prev->next = act;
604-
act_prev = act;
600+
list_add_tail(&act->list, actions);
605601
}
606-
return head;
602+
return 0;
607603

608604
err:
609-
if (head != NULL)
610-
tcf_action_destroy(head, bind);
611-
return act;
605+
tcf_action_destroy(actions, bind);
606+
return err;
612607
}
613608

614609
int tcf_action_copy_stats(struct sk_buff *skb, struct tc_action *a,
@@ -653,7 +648,7 @@ int tcf_action_copy_stats(struct sk_buff *skb, struct tc_action *a,
653648
}
654649

655650
static int
656-
tca_get_fill(struct sk_buff *skb, struct tc_action *a, u32 portid, u32 seq,
651+
tca_get_fill(struct sk_buff *skb, struct list_head *actions, u32 portid, u32 seq,
657652
u16 flags, int event, int bind, int ref)
658653
{
659654
struct tcamsg *t;
@@ -673,7 +668,7 @@ tca_get_fill(struct sk_buff *skb, struct tc_action *a, u32 portid, u32 seq,
673668
if (nest == NULL)
674669
goto out_nlmsg_trim;
675670

676-
if (tcf_action_dump(skb, a, bind, ref) < 0)
671+
if (tcf_action_dump(skb, actions, bind, ref) < 0)
677672
goto out_nlmsg_trim;
678673

679674
nla_nest_end(skb, nest);
@@ -688,14 +683,14 @@ tca_get_fill(struct sk_buff *skb, struct tc_action *a, u32 portid, u32 seq,
688683

689684
static int
690685
act_get_notify(struct net *net, u32 portid, struct nlmsghdr *n,
691-
struct tc_action *a, int event)
686+
struct list_head *actions, int event)
692687
{
693688
struct sk_buff *skb;
694689

695690
skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
696691
if (!skb)
697692
return -ENOBUFS;
698-
if (tca_get_fill(skb, a, portid, n->nlmsg_seq, 0, event, 0, 0) <= 0) {
693+
if (tca_get_fill(skb, actions, portid, n->nlmsg_seq, 0, event, 0, 0) <= 0) {
699694
kfree_skb(skb);
700695
return -EINVAL;
701696
}
@@ -726,6 +721,7 @@ tcf_action_get_1(struct nlattr *nla, struct nlmsghdr *n, u32 portid)
726721
if (a == NULL)
727722
goto err_out;
728723

724+
INIT_LIST_HEAD(&a->list);
729725
err = -EINVAL;
730726
a->ops = tc_lookup_action(tb[TCA_ACT_KIND]);
731727
if (a->ops == NULL)
@@ -745,12 +741,12 @@ tcf_action_get_1(struct nlattr *nla, struct nlmsghdr *n, u32 portid)
745741
return ERR_PTR(err);
746742
}
747743

748-
static void cleanup_a(struct tc_action *act)
744+
static void cleanup_a(struct list_head *actions)
749745
{
750-
struct tc_action *a;
746+
struct tc_action *a, *tmp;
751747

752-
for (a = act; a; a = act) {
753-
act = a->next;
748+
list_for_each_entry_safe(a, tmp, actions, list) {
749+
list_del(&a->list);
754750
kfree(a);
755751
}
756752
}
@@ -765,6 +761,7 @@ static struct tc_action *create_a(int i)
765761
return NULL;
766762
}
767763
act->order = i;
764+
INIT_LIST_HEAD(&act->list);
768765
return act;
769766
}
770767

@@ -852,7 +849,8 @@ tca_action_gd(struct net *net, struct nlattr *nla, struct nlmsghdr *n,
852849
{
853850
int i, ret;
854851
struct nlattr *tb[TCA_ACT_MAX_PRIO + 1];
855-
struct tc_action *head = NULL, *act, *act_prev = NULL;
852+
struct tc_action *act;
853+
LIST_HEAD(actions);
856854

857855
ret = nla_parse_nested(tb, TCA_ACT_MAX_PRIO, nla, NULL);
858856
if (ret < 0)
@@ -872,16 +870,11 @@ tca_action_gd(struct net *net, struct nlattr *nla, struct nlmsghdr *n,
872870
goto err;
873871
}
874872
act->order = i;
875-
876-
if (head == NULL)
877-
head = act;
878-
else
879-
act_prev->next = act;
880-
act_prev = act;
873+
list_add_tail(&act->list, &actions);
881874
}
882875

883876
if (event == RTM_GETACTION)
884-
ret = act_get_notify(net, portid, n, head, event);
877+
ret = act_get_notify(net, portid, n, &actions, event);
885878
else { /* delete */
886879
struct sk_buff *skb;
887880

@@ -891,27 +884,27 @@ tca_action_gd(struct net *net, struct nlattr *nla, struct nlmsghdr *n,
891884
goto err;
892885
}
893886

894-
if (tca_get_fill(skb, head, portid, n->nlmsg_seq, 0, event,
887+
if (tca_get_fill(skb, &actions, portid, n->nlmsg_seq, 0, event,
895888
0, 1) <= 0) {
896889
kfree_skb(skb);
897890
ret = -EINVAL;
898891
goto err;
899892
}
900893

901894
/* now do the delete */
902-
tcf_action_destroy(head, 0);
895+
tcf_action_destroy(&actions, 0);
903896
ret = rtnetlink_send(skb, net, portid, RTNLGRP_TC,
904897
n->nlmsg_flags & NLM_F_ECHO);
905898
if (ret > 0)
906899
return 0;
907900
return ret;
908901
}
909902
err:
910-
cleanup_a(head);
903+
cleanup_a(&actions);
911904
return ret;
912905
}
913906

914-
static int tcf_add_notify(struct net *net, struct tc_action *a,
907+
static int tcf_add_notify(struct net *net, struct list_head *actions,
915908
u32 portid, u32 seq, int event, u16 flags)
916909
{
917910
struct tcamsg *t;
@@ -939,7 +932,7 @@ static int tcf_add_notify(struct net *net, struct tc_action *a,
939932
if (nest == NULL)
940933
goto out_kfree_skb;
941934

942-
if (tcf_action_dump(skb, a, 0, 0) < 0)
935+
if (tcf_action_dump(skb, actions, 0, 0) < 0)
943936
goto out_kfree_skb;
944937

945938
nla_nest_end(skb, nest);
@@ -963,26 +956,18 @@ tcf_action_add(struct net *net, struct nlattr *nla, struct nlmsghdr *n,
963956
u32 portid, int ovr)
964957
{
965958
int ret = 0;
966-
struct tc_action *act;
967-
struct tc_action *a;
959+
LIST_HEAD(actions);
968960
u32 seq = n->nlmsg_seq;
969961

970-
act = tcf_action_init(net, nla, NULL, NULL, ovr, 0);
971-
if (act == NULL)
972-
goto done;
973-
if (IS_ERR(act)) {
974-
ret = PTR_ERR(act);
962+
ret = tcf_action_init(net, nla, NULL, NULL, ovr, 0, &actions);
963+
if (ret)
975964
goto done;
976-
}
977965

978966
/* dump then free all the actions after update; inserted policy
979967
* stays intact
980968
*/
981-
ret = tcf_add_notify(net, act, portid, seq, RTM_NEWACTION, n->nlmsg_flags);
982-
for (a = act; a; a = act) {
983-
act = a->next;
984-
kfree(a);
985-
}
969+
ret = tcf_add_notify(net, &actions, portid, seq, RTM_NEWACTION, n->nlmsg_flags);
970+
cleanup_a(&actions);
986971
done:
987972
return ret;
988973
}

0 commit comments

Comments
 (0)