2 * net/sched/gact.c Generic actions
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
9 * copyright Jamal Hadi Salim (2002-4)
13 #include <asm/uaccess.h>
14 #include <asm/system.h>
15 #include <linux/bitops.h>
16 #include <linux/config.h>
17 #include <linux/types.h>
18 #include <linux/kernel.h>
19 #include <linux/sched.h>
20 #include <linux/string.h>
22 #include <linux/socket.h>
23 #include <linux/sockios.h>
25 #include <linux/errno.h>
26 #include <linux/interrupt.h>
27 #include <linux/netdevice.h>
28 #include <linux/skbuff.h>
29 #include <linux/rtnetlink.h>
30 #include <linux/module.h>
31 #include <linux/init.h>
32 #include <linux/proc_fs.h>
34 #include <net/pkt_sched.h>
35 #include <linux/tc_act/tc_gact.h>
36 #include <net/tc_act/tc_gact.h>
38 /* use generic hash table */
39 #define MY_TAB_SIZE 16
40 #define MY_TAB_MASK 15
43 static struct tcf_gact
*tcf_gact_ht
[MY_TAB_SIZE
];
44 static DEFINE_RWLOCK(gact_lock
);
46 /* ovewrride the defaults */
47 #define tcf_st tcf_gact
49 #define tcf_t_lock gact_lock
50 #define tcf_ht tcf_gact_ht
52 #define CONFIG_NET_ACT_INIT 1
53 #include <net/pkt_act.h>
55 #ifdef CONFIG_GACT_PROB
56 static int gact_net_rand(struct tcf_gact
*p
)
58 if (net_random()%p
->pval
)
63 static int gact_determ(struct tcf_gact
*p
)
65 if (p
->bstats
.packets
%p
->pval
)
70 typedef int (*g_rand
)(struct tcf_gact
*p
);
71 static g_rand gact_rand
[MAX_RAND
]= { NULL
, gact_net_rand
, gact_determ
};
74 static int tcf_gact_init(struct rtattr
*rta
, struct rtattr
*est
,
75 struct tc_action
*a
, int ovr
, int bind
)
77 struct rtattr
*tb
[TCA_GACT_MAX
];
82 if (rta
== NULL
|| rtattr_parse_nested(tb
, TCA_GACT_MAX
, rta
) < 0)
85 if (tb
[TCA_GACT_PARMS
- 1] == NULL
||
86 RTA_PAYLOAD(tb
[TCA_GACT_PARMS
- 1]) < sizeof(*parm
))
88 parm
= RTA_DATA(tb
[TCA_GACT_PARMS
- 1]);
90 if (tb
[TCA_GACT_PROB
-1] != NULL
)
91 #ifdef CONFIG_GACT_PROB
92 if (RTA_PAYLOAD(tb
[TCA_GACT_PROB
-1]) < sizeof(struct tc_gact_p
))
98 p
= tcf_hash_check(parm
->index
, a
, ovr
, bind
);
100 p
= tcf_hash_create(parm
->index
, est
, a
, sizeof(*p
), ovr
, bind
);
106 tcf_hash_release(p
, bind
);
111 spin_lock_bh(&p
->lock
);
112 p
->action
= parm
->action
;
113 #ifdef CONFIG_GACT_PROB
114 if (tb
[TCA_GACT_PROB
-1] != NULL
) {
115 struct tc_gact_p
*p_parm
= RTA_DATA(tb
[TCA_GACT_PROB
-1]);
116 p
->paction
= p_parm
->paction
;
117 p
->pval
= p_parm
->pval
;
118 p
->ptype
= p_parm
->ptype
;
121 spin_unlock_bh(&p
->lock
);
122 if (ret
== ACT_P_CREATED
)
128 tcf_gact_cleanup(struct tc_action
*a
, int bind
)
130 struct tcf_gact
*p
= PRIV(a
, gact
);
133 return tcf_hash_release(p
, bind
);
138 tcf_gact(struct sk_buff
*skb
, struct tc_action
*a
, struct tcf_result
*res
)
140 struct tcf_gact
*p
= PRIV(a
, gact
);
141 int action
= TC_ACT_SHOT
;
144 #ifdef CONFIG_GACT_PROB
145 if (p
->ptype
&& gact_rand
[p
->ptype
] != NULL
)
146 action
= gact_rand
[p
->ptype
](p
);
152 p
->bstats
.bytes
+= skb
->len
;
154 if (action
== TC_ACT_SHOT
)
156 p
->tm
.lastuse
= jiffies
;
157 spin_unlock(&p
->lock
);
163 tcf_gact_dump(struct sk_buff
*skb
, struct tc_action
*a
, int bind
, int ref
)
165 unsigned char *b
= skb
->tail
;
167 struct tcf_gact
*p
= PRIV(a
, gact
);
170 opt
.index
= p
->index
;
171 opt
.refcnt
= p
->refcnt
- ref
;
172 opt
.bindcnt
= p
->bindcnt
- bind
;
173 opt
.action
= p
->action
;
174 RTA_PUT(skb
, TCA_GACT_PARMS
, sizeof(opt
), &opt
);
175 #ifdef CONFIG_GACT_PROB
177 struct tc_gact_p p_opt
;
178 p_opt
.paction
= p
->paction
;
179 p_opt
.pval
= p
->pval
;
180 p_opt
.ptype
= p
->ptype
;
181 RTA_PUT(skb
, TCA_GACT_PROB
, sizeof(p_opt
), &p_opt
);
184 t
.install
= jiffies_to_clock_t(jiffies
- p
->tm
.install
);
185 t
.lastuse
= jiffies_to_clock_t(jiffies
- p
->tm
.lastuse
);
186 t
.expires
= jiffies_to_clock_t(p
->tm
.expires
);
187 RTA_PUT(skb
, TCA_GACT_TM
, sizeof(t
), &t
);
191 skb_trim(skb
, b
- skb
->data
);
195 static struct tc_action_ops act_gact_ops
= {
197 .type
= TCA_ACT_GACT
,
198 .capab
= TCA_CAP_NONE
,
199 .owner
= THIS_MODULE
,
201 .dump
= tcf_gact_dump
,
202 .cleanup
= tcf_gact_cleanup
,
203 .lookup
= tcf_hash_search
,
204 .init
= tcf_gact_init
,
205 .walk
= tcf_generic_walker
208 MODULE_AUTHOR("Jamal Hadi Salim(2002-4)");
209 MODULE_DESCRIPTION("Generic Classifier actions");
210 MODULE_LICENSE("GPL");
213 gact_init_module(void)
215 #ifdef CONFIG_GACT_PROB
216 printk("GACT probability on\n");
218 printk("GACT probability NOT on\n");
220 return tcf_register_action(&act_gact_ops
);
224 gact_cleanup_module(void)
226 tcf_unregister_action(&act_gact_ops
);
229 module_init(gact_init_module
);
230 module_exit(gact_cleanup_module
);