Blame view

net/sched/act_gact.c 7.43 KB
2874c5fd2   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-or-later
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
  /*
0c6965dd3   Jiri Pirko   sched: fix act fi...
3
   * net/sched/act_gact.c		Generic actions
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5
   * copyright 	Jamal Hadi Salim (2002-4)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
7
8
  #include <linux/types.h>
  #include <linux/kernel.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
9
  #include <linux/string.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
10
  #include <linux/errno.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
11
12
13
14
  #include <linux/skbuff.h>
  #include <linux/rtnetlink.h>
  #include <linux/module.h>
  #include <linux/init.h>
dc5fc579b   Arnaldo Carvalho de Melo   [NETLINK]: Use nl...
15
  #include <net/netlink.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
16
  #include <net/pkt_sched.h>
0da2dbd60   Davide Caratti   net/sched: act_ga...
17
  #include <net/pkt_cls.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
18
19
  #include <linux/tc_act/tc_gact.h>
  #include <net/tc_act/tc_gact.h>
c7d03a00b   Alexey Dobriyan   netns: make struc...
20
  static unsigned int gact_net_id;
a85a970af   WANG Cong   net_sched: move t...
21
  static struct tc_action_ops act_gact_ops;
ddf97ccdd   WANG Cong   net_sched: add ne...
22

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
23
  #ifdef CONFIG_GACT_PROB
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
24
  static int gact_net_rand(struct tcf_gact *gact)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
25
  {
cef5ecf96   Eric Dumazet   net_sched: act_ga...
26
27
  	smp_rmb(); /* coupled with smp_wmb() in tcf_gact_init() */
  	if (prandom_u32() % gact->tcfg_pval)
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
28
29
  		return gact->tcf_action;
  	return gact->tcfg_paction;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
30
  }
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
31
  static int gact_determ(struct tcf_gact *gact)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
32
  {
cc6510a95   Eric Dumazet   net_sched: act_ga...
33
  	u32 pack = atomic_inc_return(&gact->packets);
cef5ecf96   Eric Dumazet   net_sched: act_ga...
34
  	smp_rmb(); /* coupled with smp_wmb() in tcf_gact_init() */
cc6510a95   Eric Dumazet   net_sched: act_ga...
35
  	if (pack % gact->tcfg_pval)
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
36
37
  		return gact->tcf_action;
  	return gact->tcfg_paction;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
38
  }
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
39
  typedef int (*g_rand)(struct tcf_gact *gact);
cc7ec456f   Eric Dumazet   net_sched: cleanups
40
  static g_rand gact_rand[MAX_RAND] = { NULL, gact_net_rand, gact_determ };
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
41
  #endif /* CONFIG_GACT_PROB */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
42

53b2bf3f8   Patrick McHardy   [NET_SCHED]: Use ...
43
44
45
46
  static const struct nla_policy gact_policy[TCA_GACT_MAX + 1] = {
  	[TCA_GACT_PARMS]	= { .len = sizeof(struct tc_gact) },
  	[TCA_GACT_PROB]		= { .len = sizeof(struct tc_gact_p) },
  };
c1b52739e   Benjamin LaHaise   pkt_sched: namesp...
47
  static int tcf_gact_init(struct net *net, struct nlattr *nla,
a85a970af   WANG Cong   net_sched: move t...
48
  			 struct nlattr *est, struct tc_action **a,
789871bb2   Vlad Buslov   net: sched: imple...
49
  			 int ovr, int bind, bool rtnl_held,
abbb0d336   Vlad Buslov   net: sched: exten...
50
51
  			 struct tcf_proto *tp, u32 flags,
  			 struct netlink_ext_ack *extack)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
52
  {
ddf97ccdd   WANG Cong   net_sched: add ne...
53
  	struct tc_action_net *tn = net_generic(net, gact_net_id);
7ba699c60   Patrick McHardy   [NET_SCHED]: Conv...
54
  	struct nlattr *tb[TCA_GACT_MAX + 1];
0da2dbd60   Davide Caratti   net/sched: act_ga...
55
  	struct tcf_chain *goto_ch = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
56
  	struct tc_gact *parm;
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
57
  	struct tcf_gact *gact;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
58
  	int ret = 0;
7be8ef2cd   Dmytro Linkin   net: sched: use t...
59
  	u32 index;
cee63723b   Patrick McHardy   [NET_SCHED]: Prop...
60
  	int err;
696ecdc10   Hiroaki SHIMODA   net_sched: gact: ...
61
62
63
  #ifdef CONFIG_GACT_PROB
  	struct tc_gact_p *p_parm = NULL;
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
64

cee63723b   Patrick McHardy   [NET_SCHED]: Prop...
65
  	if (nla == NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
66
  		return -EINVAL;
8cb081746   Johannes Berg   netlink: make val...
67
68
  	err = nla_parse_nested_deprecated(tb, TCA_GACT_MAX, nla, gact_policy,
  					  NULL);
cee63723b   Patrick McHardy   [NET_SCHED]: Prop...
69
70
  	if (err < 0)
  		return err;
53b2bf3f8   Patrick McHardy   [NET_SCHED]: Use ...
71
  	if (tb[TCA_GACT_PARMS] == NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
72
  		return -EINVAL;
7ba699c60   Patrick McHardy   [NET_SCHED]: Conv...
73
  	parm = nla_data(tb[TCA_GACT_PARMS]);
7be8ef2cd   Dmytro Linkin   net: sched: use t...
74
  	index = parm->index;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
75

53b2bf3f8   Patrick McHardy   [NET_SCHED]: Use ...
76
  #ifndef CONFIG_GACT_PROB
7ba699c60   Patrick McHardy   [NET_SCHED]: Conv...
77
  	if (tb[TCA_GACT_PROB] != NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
78
  		return -EOPNOTSUPP;
696ecdc10   Hiroaki SHIMODA   net_sched: gact: ...
79
80
81
82
83
  #else
  	if (tb[TCA_GACT_PROB]) {
  		p_parm = nla_data(tb[TCA_GACT_PROB]);
  		if (p_parm->ptype >= MAX_RAND)
  			return -EINVAL;
9469f375a   Davide Caratti   net/sched: act_ga...
84
85
86
87
88
  		if (TC_ACT_EXT_CMP(p_parm->paction, TC_ACT_GOTO_CHAIN)) {
  			NL_SET_ERR_MSG(extack,
  				       "goto chain not allowed on fallback");
  			return -EINVAL;
  		}
696ecdc10   Hiroaki SHIMODA   net_sched: gact: ...
89
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
90
  #endif
7be8ef2cd   Dmytro Linkin   net: sched: use t...
91
  	err = tcf_idr_check_alloc(tn, &index, a, bind);
0190c1d45   Vlad Buslov   net: sched: atomi...
92
  	if (!err) {
e38226786   Vlad Buslov   net: sched: updat...
93
94
  		ret = tcf_idr_create_from_flags(tn, index, est, a,
  						&act_gact_ops, bind, flags);
0190c1d45   Vlad Buslov   net: sched: atomi...
95
  		if (ret) {
7be8ef2cd   Dmytro Linkin   net: sched: use t...
96
  			tcf_idr_cleanup(tn, index);
86062033f   WANG Cong   net_sched: act: h...
97
  			return ret;
0190c1d45   Vlad Buslov   net: sched: atomi...
98
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
99
  		ret = ACT_P_CREATED;
0190c1d45   Vlad Buslov   net: sched: atomi...
100
  	} else if (err > 0) {
1a29321ed   Jamal Hadi Salim   net_sched: act: D...
101
102
  		if (bind)/* dont override defaults */
  			return 0;
4e8ddd7f1   Vlad Buslov   net: sched: don't...
103
104
  		if (!ovr) {
  			tcf_idr_release(*a, bind);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
105
  			return -EEXIST;
4e8ddd7f1   Vlad Buslov   net: sched: don't...
106
  		}
0190c1d45   Vlad Buslov   net: sched: atomi...
107
108
  	} else {
  		return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
109
  	}
0da2dbd60   Davide Caratti   net/sched: act_ga...
110
111
112
  	err = tcf_action_check_ctrlact(parm->action, tp, &goto_ch, extack);
  	if (err < 0)
  		goto release_idr;
a85a970af   WANG Cong   net_sched: move t...
113
  	gact = to_gact(*a);
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
114

653cd284a   Vlad Buslov   net: sched: alway...
115
  	spin_lock_bh(&gact->tcf_lock);
0da2dbd60   Davide Caratti   net/sched: act_ga...
116
  	goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
117
  #ifdef CONFIG_GACT_PROB
696ecdc10   Hiroaki SHIMODA   net_sched: gact: ...
118
  	if (p_parm) {
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
119
  		gact->tcfg_paction = p_parm->paction;
cef5ecf96   Eric Dumazet   net_sched: act_ga...
120
121
122
123
124
  		gact->tcfg_pval    = max_t(u16, 1, p_parm->pval);
  		/* Make sure tcfg_pval is written before tcfg_ptype
  		 * coupled with smp_rmb() in gact_net_rand() & gact_determ()
  		 */
  		smp_wmb();
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
125
  		gact->tcfg_ptype   = p_parm->ptype;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
126
127
  	}
  #endif
653cd284a   Vlad Buslov   net: sched: alway...
128
  	spin_unlock_bh(&gact->tcf_lock);
e8917f437   Vlad Buslov   net: sched: act_g...
129

0da2dbd60   Davide Caratti   net/sched: act_ga...
130
131
  	if (goto_ch)
  		tcf_chain_put_by_act(goto_ch);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
132
  	return ret;
0da2dbd60   Davide Caratti   net/sched: act_ga...
133
134
135
  release_idr:
  	tcf_idr_release(*a, bind);
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
136
  }
1740005e2   Jamal Hadi Salim   net: sched: act_g...
137
138
  static int tcf_gact_act(struct sk_buff *skb, const struct tc_action *a,
  			struct tcf_result *res)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
139
  {
a85a970af   WANG Cong   net_sched: move t...
140
  	struct tcf_gact *gact = to_gact(a);
56e5d1ca1   Eric Dumazet   net_sched: act_ga...
141
  	int action = READ_ONCE(gact->tcf_action);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
142

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
143
  #ifdef CONFIG_GACT_PROB
8f2ae965b   Eric Dumazet   net_sched: act_ga...
144
145
146
147
148
149
  	{
  	u32 ptype = READ_ONCE(gact->tcfg_ptype);
  
  	if (ptype)
  		action = gact_rand[ptype](gact);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
150
  #endif
5e1ad95b6   Vlad Buslov   net: sched: extra...
151
  	tcf_action_update_bstats(&gact->common, skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
152
  	if (action == TC_ACT_SHOT)
26b537a88   Vlad Buslov   net: sched: extra...
153
  		tcf_action_inc_drop_qstats(&gact->common);
56e5d1ca1   Eric Dumazet   net_sched: act_ga...
154
155
  
  	tcf_lastuse_update(&gact->tcf_tm);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
156
157
158
  
  	return action;
  }
4b61d3e8d   Po Liu   net: qos offload ...
159
160
  static void tcf_gact_stats_update(struct tc_action *a, u64 bytes, u64 packets,
  				  u64 drops, u64 lastuse, bool hw)
9fea47d93   Amir Vadai   net/sched: act_ga...
161
  {
a85a970af   WANG Cong   net_sched: move t...
162
  	struct tcf_gact *gact = to_gact(a);
9fea47d93   Amir Vadai   net/sched: act_ga...
163
164
  	int action = READ_ONCE(gact->tcf_action);
  	struct tcf_t *tm = &gact->tcf_tm;
4b61d3e8d   Po Liu   net: qos offload ...
165
166
  	tcf_action_update_stats(a, bytes, packets,
  				action == TC_ACT_SHOT ? packets : drops, hw);
3bb23421a   Roi Dayan   net/sched: Fix up...
167
  	tm->lastuse = max_t(u64, tm->lastuse, lastuse);
9fea47d93   Amir Vadai   net/sched: act_ga...
168
  }
0b0f43fe2   Jamal Hadi Salim   net sched: indent...
169
170
  static int tcf_gact_dump(struct sk_buff *skb, struct tc_action *a,
  			 int bind, int ref)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
171
  {
27a884dc3   Arnaldo Carvalho de Melo   [SK_BUFF]: Conver...
172
  	unsigned char *b = skb_tail_pointer(skb);
a85a970af   WANG Cong   net_sched: move t...
173
  	struct tcf_gact *gact = to_gact(a);
1c40be12f   Eric Dumazet   net sched: fix so...
174
175
  	struct tc_gact opt = {
  		.index   = gact->tcf_index,
036bb4432   Vlad Buslov   net: sched: chang...
176
177
  		.refcnt  = refcount_read(&gact->tcf_refcnt) - ref,
  		.bindcnt = atomic_read(&gact->tcf_bindcnt) - bind,
1c40be12f   Eric Dumazet   net sched: fix so...
178
  	};
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
179
  	struct tcf_t t;
653cd284a   Vlad Buslov   net: sched: alway...
180
  	spin_lock_bh(&gact->tcf_lock);
e8917f437   Vlad Buslov   net: sched: act_g...
181
  	opt.action = gact->tcf_action;
1b34ec43c   David S. Miller   pkt_sched: Stop u...
182
183
  	if (nla_put(skb, TCA_GACT_PARMS, sizeof(opt), &opt))
  		goto nla_put_failure;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
184
  #ifdef CONFIG_GACT_PROB
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
185
  	if (gact->tcfg_ptype) {
1c40be12f   Eric Dumazet   net sched: fix so...
186
187
188
189
190
  		struct tc_gact_p p_opt = {
  			.paction = gact->tcfg_paction,
  			.pval    = gact->tcfg_pval,
  			.ptype   = gact->tcfg_ptype,
  		};
1b34ec43c   David S. Miller   pkt_sched: Stop u...
191
192
  		if (nla_put(skb, TCA_GACT_PROB, sizeof(p_opt), &p_opt))
  			goto nla_put_failure;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
193
194
  	}
  #endif
48d8ee169   Jamal Hadi Salim   net sched actions...
195
  	tcf_tm_dump(&t, &gact->tcf_tm);
9854518ea   Nicolas Dichtel   sched: align nlat...
196
  	if (nla_put_64bit(skb, TCA_GACT_TM, sizeof(t), &t, TCA_GACT_PAD))
1b34ec43c   David S. Miller   pkt_sched: Stop u...
197
  		goto nla_put_failure;
653cd284a   Vlad Buslov   net: sched: alway...
198
  	spin_unlock_bh(&gact->tcf_lock);
e8917f437   Vlad Buslov   net: sched: act_g...
199

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
200
  	return skb->len;
7ba699c60   Patrick McHardy   [NET_SCHED]: Conv...
201
  nla_put_failure:
653cd284a   Vlad Buslov   net: sched: alway...
202
  	spin_unlock_bh(&gact->tcf_lock);
dc5fc579b   Arnaldo Carvalho de Melo   [NETLINK]: Use nl...
203
  	nlmsg_trim(skb, b);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
204
205
  	return -1;
  }
ddf97ccdd   WANG Cong   net_sched: add ne...
206
207
  static int tcf_gact_walker(struct net *net, struct sk_buff *skb,
  			   struct netlink_callback *cb, int type,
417801055   Alexander Aring   net: sched: act: ...
208
209
  			   const struct tc_action_ops *ops,
  			   struct netlink_ext_ack *extack)
ddf97ccdd   WANG Cong   net_sched: add ne...
210
211
  {
  	struct tc_action_net *tn = net_generic(net, gact_net_id);
b36201455   Alexander Aring   net: sched: act: ...
212
  	return tcf_generic_walker(tn, skb, cb, type, ops, extack);
ddf97ccdd   WANG Cong   net_sched: add ne...
213
  }
f061b48c1   Cong Wang   Revert "net: sche...
214
  static int tcf_gact_search(struct net *net, struct tc_action **a, u32 index)
ddf97ccdd   WANG Cong   net_sched: add ne...
215
216
  {
  	struct tc_action_net *tn = net_generic(net, gact_net_id);
65a206c01   Chris Mi   net/sched: Change...
217
  	return tcf_idr_search(tn, a, index);
ddf97ccdd   WANG Cong   net_sched: add ne...
218
  }
9c5c9c573   Roman Mashak   net sched actions...
219
220
221
222
223
224
225
226
227
228
229
230
  static size_t tcf_gact_get_fill_size(const struct tc_action *act)
  {
  	size_t sz = nla_total_size(sizeof(struct tc_gact)); /* TCA_GACT_PARMS */
  
  #ifdef CONFIG_GACT_PROB
  	if (to_gact(act)->tcfg_ptype)
  		/* TCA_GACT_PROB */
  		sz += nla_total_size(sizeof(struct tc_gact_p));
  #endif
  
  	return sz;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
231
232
  static struct tc_action_ops act_gact_ops = {
  	.kind		=	"gact",
eddd2cf19   Eli Cohen   net: Change TCA_A...
233
  	.id		=	TCA_ID_GACT,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
234
  	.owner		=	THIS_MODULE,
1740005e2   Jamal Hadi Salim   net: sched: act_g...
235
  	.act		=	tcf_gact_act,
9fea47d93   Amir Vadai   net/sched: act_ga...
236
  	.stats_update	=	tcf_gact_stats_update,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
237
  	.dump		=	tcf_gact_dump,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
238
  	.init		=	tcf_gact_init,
ddf97ccdd   WANG Cong   net_sched: add ne...
239
240
  	.walk		=	tcf_gact_walker,
  	.lookup		=	tcf_gact_search,
9c5c9c573   Roman Mashak   net sched actions...
241
  	.get_fill_size	=	tcf_gact_get_fill_size,
a85a970af   WANG Cong   net_sched: move t...
242
  	.size		=	sizeof(struct tcf_gact),
ddf97ccdd   WANG Cong   net_sched: add ne...
243
244
245
246
247
  };
  
  static __net_init int gact_init_net(struct net *net)
  {
  	struct tc_action_net *tn = net_generic(net, gact_net_id);
981471bd3   Cong Wang   net_sched: fix a ...
248
  	return tc_action_net_init(net, tn, &act_gact_ops);
ddf97ccdd   WANG Cong   net_sched: add ne...
249
  }
039af9c66   Cong Wang   net_sched: switch...
250
  static void __net_exit gact_exit_net(struct list_head *net_list)
ddf97ccdd   WANG Cong   net_sched: add ne...
251
  {
039af9c66   Cong Wang   net_sched: switch...
252
  	tc_action_net_exit(net_list, gact_net_id);
ddf97ccdd   WANG Cong   net_sched: add ne...
253
254
255
256
  }
  
  static struct pernet_operations gact_net_ops = {
  	.init = gact_init_net,
039af9c66   Cong Wang   net_sched: switch...
257
  	.exit_batch = gact_exit_net,
ddf97ccdd   WANG Cong   net_sched: add ne...
258
259
  	.id   = &gact_net_id,
  	.size = sizeof(struct tc_action_net),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
260
261
262
263
264
  };
  
  MODULE_AUTHOR("Jamal Hadi Salim(2002-4)");
  MODULE_DESCRIPTION("Generic Classifier actions");
  MODULE_LICENSE("GPL");
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
265
  static int __init gact_init_module(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
266
267
  {
  #ifdef CONFIG_GACT_PROB
cc7ec456f   Eric Dumazet   net_sched: cleanups
268
269
  	pr_info("GACT probability on
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
270
  #else
cc7ec456f   Eric Dumazet   net_sched: cleanups
271
272
  	pr_info("GACT probability NOT on
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
273
  #endif
ddf97ccdd   WANG Cong   net_sched: add ne...
274
275
  
  	return tcf_register_action(&act_gact_ops, &gact_net_ops);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
276
  }
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
277
  static void __exit gact_cleanup_module(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
278
  {
ddf97ccdd   WANG Cong   net_sched: add ne...
279
  	tcf_unregister_action(&act_gact_ops, &gact_net_ops);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
280
281
282
283
  }
  
  module_init(gact_init_module);
  module_exit(gact_cleanup_module);