Skip to content

Commit db50514

Browse files
jpirkodavem330
authored andcommitted
net: sched: add termination action to allow goto chain
Introduce new type of termination action called "goto_chain". This allows user to specify a chain to be processed. This action type is then processed as a return value in tcf_classify loop in similar way as "reclassify" is, only it does not reset to the first filter in chain but rather reset to the first filter of the desired chain. Signed-off-by: Jiri Pirko <[email protected]> Acked-by: Jamal Hadi Salim <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 9fb9f25 commit db50514

File tree

5 files changed

+54
-3
lines changed

5 files changed

+54
-3
lines changed

include/net/act_api.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ struct tc_action {
4242
struct gnet_stats_basic_cpu __percpu *cpu_bstats;
4343
struct gnet_stats_queue __percpu *cpu_qstats;
4444
struct tc_cookie *act_cookie;
45+
struct tcf_chain *goto_chain;
4546
};
4647
#define tcf_head common.tcfa_head
4748
#define tcf_index common.tcfa_index

include/net/sch_generic.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -193,8 +193,13 @@ struct Qdisc_ops {
193193

194194

195195
struct tcf_result {
196-
unsigned long class;
197-
u32 classid;
196+
union {
197+
struct {
198+
unsigned long class;
199+
u32 classid;
200+
};
201+
const struct tcf_proto *goto_tp;
202+
};
198203
};
199204

200205
struct tcf_proto_ops {

include/uapi/linux/pkt_cls.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ enum {
5151
(((combined) & (~TC_ACT_EXT_VAL_MASK)) == opcode)
5252

5353
#define TC_ACT_JUMP __TC_ACT_EXT(1)
54+
#define TC_ACT_GOTO_CHAIN __TC_ACT_EXT(2)
5455

5556
/* Action type identifiers*/
5657
enum {

net/sched/act_api.c

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,31 @@
2828
#include <net/act_api.h>
2929
#include <net/netlink.h>
3030

31+
static int tcf_action_goto_chain_init(struct tc_action *a, struct tcf_proto *tp)
32+
{
33+
u32 chain_index = a->tcfa_action & TC_ACT_EXT_VAL_MASK;
34+
35+
if (!tp)
36+
return -EINVAL;
37+
a->goto_chain = tcf_chain_get(tp->chain->block, chain_index);
38+
if (!a->goto_chain)
39+
return -ENOMEM;
40+
return 0;
41+
}
42+
43+
static void tcf_action_goto_chain_fini(struct tc_action *a)
44+
{
45+
tcf_chain_put(a->goto_chain);
46+
}
47+
48+
static void tcf_action_goto_chain_exec(const struct tc_action *a,
49+
struct tcf_result *res)
50+
{
51+
const struct tcf_chain *chain = a->goto_chain;
52+
53+
res->goto_tp = rcu_dereference_bh(chain->filter_chain);
54+
}
55+
3156
static void free_tcf(struct rcu_head *head)
3257
{
3358
struct tc_action *p = container_of(head, struct tc_action, tcfa_rcu);
@@ -39,6 +64,8 @@ static void free_tcf(struct rcu_head *head)
3964
kfree(p->act_cookie->data);
4065
kfree(p->act_cookie);
4166
}
67+
if (p->goto_chain)
68+
tcf_action_goto_chain_fini(p);
4269

4370
kfree(p);
4471
}
@@ -465,6 +492,8 @@ int tcf_action_exec(struct sk_buff *skb, struct tc_action **actions,
465492
else /* faulty graph, stop pipeline */
466493
return TC_ACT_OK;
467494
}
495+
} else if (TC_ACT_EXT_CMP(ret, TC_ACT_GOTO_CHAIN)) {
496+
tcf_action_goto_chain_exec(a, res);
468497
}
469498

470499
if (ret != TC_ACT_PIPE)
@@ -657,6 +686,17 @@ struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp,
657686
if (err != ACT_P_CREATED)
658687
module_put(a_o->owner);
659688

689+
if (TC_ACT_EXT_CMP(a->tcfa_action, TC_ACT_GOTO_CHAIN)) {
690+
err = tcf_action_goto_chain_init(a, tp);
691+
if (err) {
692+
LIST_HEAD(actions);
693+
694+
list_add_tail(&a->list, &actions);
695+
tcf_action_destroy(&actions, bind);
696+
return ERR_PTR(err);
697+
}
698+
}
699+
660700
return a;
661701

662702
err_mod:

net/sched/cls_api.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -307,8 +307,12 @@ int tcf_classify(struct sk_buff *skb, const struct tcf_proto *tp,
307307

308308
err = tp->classify(skb, tp, res);
309309
#ifdef CONFIG_NET_CLS_ACT
310-
if (unlikely(err == TC_ACT_RECLASSIFY && !compat_mode))
310+
if (unlikely(err == TC_ACT_RECLASSIFY && !compat_mode)) {
311311
goto reset;
312+
} else if (unlikely(TC_ACT_EXT_CMP(err, TC_ACT_GOTO_CHAIN))) {
313+
old_tp = res->goto_tp;
314+
goto reset;
315+
}
312316
#endif
313317
if (err >= 0)
314318
return err;

0 commit comments

Comments
 (0)