diff --git a/include/net/act_api.h b/include/net/act_api.h
index 1d71644..0692458 100644
--- a/include/net/act_api.h
+++ b/include/net/act_api.h
@@ -41,6 +41,7 @@ struct tc_action {
struct rcu_head tcfa_rcu;
struct gnet_stats_basic_cpu __percpu *cpu_bstats;
struct gnet_stats_queue __percpu *cpu_qstats;
+ struct tc_cookie *act_ck;
};
#define tcf_head common.tcfa_head
#define tcf_index common.tcfa_indexdiff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h
index f0a0514..f2fafeb 100644
--- a/include/net/pkt_cls.h
+++ b/include/net/pkt_cls.h
@@ -24,15 +24,15 @@ struct tcf_walker {
}
static inline unsigned long
-cls_set_class(struct tcf_proto *tp, unsigned long *clp,
+cls_set_class(struct tcf_proto *tp, unsigned long *clp,
unsigned long cl)
{
unsigned long old_cl;
-
+
tcf_tree_lock(tp);
old_cl = __cls_set_class(clp, cl);
tcf_tree_unlock(tp);
-
+
return old_cl;
}
@@ -237,7 +237,7 @@ static inline int tcf_em_early_end(struct tcf_ematch *em, int result)
return 0;
}
-
+
/**
* struct tcf_ematch_tree - ematch tree handle
*
@@ -246,8 +246,7 @@ static inline int tcf_em_early_end(struct tcf_ematch *em, int result)
*/
struct tcf_ematch_tree {
struct tcf_ematch_tree_hdr hdr;
- struct tcf_ematch * matches;
-
+ struct tcf_ematch *matches;
};
/**@@ -515,4 +514,12 @@ struct tc_cls_bpf_offload {
u32 gen_flags;
};
+
+/* This structure holds cookie structure that is passed from user
+ * to the kernel for actions and classifiers
+ */
+struct tc_cookie {
+ unsigned char ck[TC_COOKIE_MAX_SIZE];
+ unsigned char ck_len;
+};
#endifdiff --git a/include/uapi/linux/pkt_cls.h b/include/uapi/linux/pkt_cls.h
index 1e5e1dd..2d2414e 100644
--- a/include/uapi/linux/pkt_cls.h
+++ b/include/uapi/linux/pkt_cls.h
@@ -4,6 +4,8 @@
#include <linux/types.h>
#include <linux/pkt_sched.h>
+#define TC_COOKIE_MAX_SIZE 16
+
/* Action attributes */
enum {
TCA_ACT_UNSPEC,@@ -12,6 +14,7 @@ enum {
TCA_ACT_INDEX,
TCA_ACT_STATS,
TCA_ACT_PAD,
+ TCA_ACT_COOKIE,
__TCA_ACT_MAX
};
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index f04715a..9d05b70 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -24,6 +24,7 @@
#include <net/net_namespace.h>
#include <net/sock.h>
#include <net/sch_generic.h>
+#include <net/pkt_cls.h>
#include <net/act_api.h>
#include <net/netlink.h>
@@ -33,6 +34,7 @@ static void free_tcf(struct rcu_head *head)
free_percpu(p->cpu_bstats);
free_percpu(p->cpu_qstats);
+ kfree(p->act_ck);
kfree(p);
}
@@ -464,8 +466,8 @@ int tcf_action_destroy(struct list_head *actions, int bind)
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 tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int bind,
+ int ref)
{
int err = -EINVAL;
unsigned char *b = skb_tail_pointer(skb);@@ -475,6 +477,12 @@ int tcf_action_destroy(struct list_head *actions, int bind)
goto nla_put_failure;
if (tcf_action_copy_stats(skb, a, 0))
goto nla_put_failure;
+ if (a->act_ck) {
+ if (nla_put(skb, TCA_ACT_COOKIE, a->act_ck->ck_len,
+ a->act_ck))
+ goto nla_put_failure;
+ }
+
nest = nla_nest_start(skb, TCA_OPTIONS);
if (nest == NULL)
goto nla_put_failure;@@ -575,6 +583,23 @@ struct tc_action *tcf_action_init_1(struct net *net, struct nlattr *nla,
if (err < 0)
goto err_mod;
+ if (tb[TCA_ACT_COOKIE]) {
+ if (nla_len(tb[TCA_ACT_COOKIE]) > TC_COOKIE_MAX_SIZE) {
+ err = -EINVAL;
+ goto err_mod;
+ }
+
+ a->act_ck = kzalloc(sizeof(*a->act_ck), GFP_KERNEL);
+ if (unlikely(!a->act_ck)) {
+ err = -ENOMEM;
+ goto err_mod;
+ }
+
+ memcpy(a->act_ck->ck, nla_data(tb[TCA_ACT_COOKIE]),
+ nla_len(tb[TCA_ACT_COOKIE]));
+ a->act_ck->ck_len = nla_len(tb[TCA_ACT_COOKIE]);
+ }
+
/* module count goes up only when brand new policy is created
* if it exists and is only bound to in a_o->init() then
* ACT_P_CREATED is not returned (a zero is).--
1.9.1