we can leave out subscribe/unsubscribe, since this has no relevance in pratice yet...
[ana-net.git] / src / xt_fblock.h
blobef3d60cb16ce8a41c73528b24990806e0a585b94
1 /*
2 * Lightweight Autonomic Network Architecture
4 * Copyright 2011 Daniel Borkmann <dborkma@tik.ee.ethz.ch>,
5 * Swiss federal institute of technology (ETH Zurich)
6 * Subject to the GPL.
7 */
9 #ifndef XT_FBLOCK_H
10 #define XT_FBLOCK_H
12 #ifdef __KERNEL__
14 #include <linux/proc_fs.h>
15 #include <linux/if.h>
16 #include <linux/cpu.h>
17 #include <linux/module.h>
18 #include <linux/spinlock.h>
19 #include <linux/skbuff.h>
20 #include <linux/notifier.h>
21 #include <linux/radix-tree.h>
23 #include "xt_idp.h"
25 enum path_type {
26 TYPE_INGRESS = 0,
27 #define TYPE_INGRESS TYPE_INGRESS
28 TYPE_EGRESS,
29 #define TYPE_EGRESS TYPE_EGRESS
30 _TYPE_MAX,
33 extern const char *path_names[];
35 enum fblock_mode {
36 MODE_SOURCE = 0,
37 #define MODE_SOURCE MODE_SOURCE
38 MODE_SINK,
39 #define MODE_SINK MODE_SINK
40 MODE_DUAL,
41 #define MODE_DUAL MODE_DUAL
44 #define NUM_TYPES _TYPE_MAX
46 #define FBLOCK_BIND_IDP 0x0001
47 #define FBLOCK_UNBIND_IDP 0x0002
48 #define FBLOCK_SET_OPT 0x0003
49 #define FBLOCK_DOWN_PREPARE 0x0004
50 #define FBLOCK_DOWN 0x0005
52 #endif /* __KERNEL__ */
54 #define FBNAMSIZ IFNAMSIZ
55 #define TYPNAMSIZ FBNAMSIZ
57 #ifdef __KERNEL__
59 extern struct proc_dir_entry *fblock_proc_dir;
61 struct fblock_bind_msg {
62 enum path_type dir;
63 idp_t idp;
66 struct fblock_opt_msg {
67 char *key;
68 char *val;
71 struct fblock;
73 struct fblock_factory {
74 char type[TYPNAMSIZ];
75 enum fblock_mode mode;
76 struct module *owner;
77 struct fblock *(*ctor)(char *name);
78 void (*dtor)(struct fblock *fb);
79 void (*dtor_outside_rcu)(struct fblock *fb);
80 } ____cacheline_aligned;
82 struct fblock_notifier {
83 struct fblock *self;
84 struct notifier_block nb;
85 struct fblock_notifier *next;
86 idp_t remote;
89 struct fblock_subscrib {
90 struct atomic_notifier_head subscribers;
93 struct fblock {
94 char name[FBNAMSIZ];
95 void __percpu *private_data;
96 int (*netfb_rx)(const struct fblock * const fb,
97 struct sk_buff * const skb,
98 enum path_type * const dir);
99 int (*event_rx)(struct notifier_block *self, unsigned long cmd,
100 void *args);
101 struct fblock_factory *factory;
102 struct fblock_notifier *notifiers;
103 struct fblock_subscrib *others;
104 struct rcu_head rcu;
105 atomic_t refcnt;
106 idp_t idp;
107 spinlock_t lock; /* Used in notifiers */
108 } ____cacheline_aligned;
110 extern void free_fblock_rcu(struct rcu_head *rp);
112 static inline void get_fblock(struct fblock *fb)
114 atomic_inc(&fb->refcnt);
117 static inline void put_fblock(struct fblock *fb)
119 if (likely(!atomic_dec_and_test(&fb->refcnt)))
120 return;
121 if (fb->factory->dtor_outside_rcu)
122 fb->factory->dtor_outside_rcu(fb);
123 call_rcu(&fb->rcu, free_fblock_rcu);
127 * Note: __* variants do not hold the rcu_read_lock!
130 /* Allocate/free a new fblock object. */
131 extern struct fblock *alloc_fblock(gfp_t flags);
132 extern void kfree_fblock(struct fblock *p);
134 /* Initialize/cleanup a fblock object. */
135 extern int init_fblock(struct fblock *fb, char *name, void __percpu *priv);
136 extern void cleanup_fblock(struct fblock *fb);
137 extern void cleanup_fblock_ctor(struct fblock *fb);
140 * Registers a fblock object to the stack. Latter variant allocates
141 * a new unused idp, former uses a given _free_ idp.
143 extern int register_fblock(struct fblock *p, idp_t idp);
144 extern int register_fblock_namespace(struct fblock *p);
147 * Unregisters a fblock object from the stack. Former variant does not
148 * release the idp to name mapping, latter variant frees it, too.
150 extern void unregister_fblock(struct fblock *p);
151 extern void unregister_fblock_namespace(struct fblock *p);
152 extern void unregister_fblock_namespace_no_rcu(struct fblock *p);
154 extern struct radix_tree_root fblmap;
156 /* Caller needs to do a put_fblock() after his work is done! */
157 /* Called within RCU read lock! */
158 #define __search_fblock(idp) \
159 ({ \
160 struct fblock *ret = radix_tree_lookup(&fblmap, idp); \
161 if (likely(ret)) \
162 get_fblock(ret); \
163 ret; \
166 /* Returns fblock object specified by idp or name. */
167 extern struct fblock *search_fblock(idp_t idp);
168 extern struct fblock *search_fblock_n(char *name);
170 /* Migrate state from src to dst and drop of dst states */
171 extern void fblock_migrate_p(struct fblock *dst, struct fblock *src);
172 extern void fblock_migrate_r(struct fblock *dst, struct fblock *src);
174 /* Notify fblock of new option. */
175 extern int fblock_set_option(struct fblock *fb, char *opt_string);
176 extern int __fblock_set_option(struct fblock *fb, char *opt_string);
178 /* Binds two fblock objects, increments refcount each. */
179 extern int fblock_bind(struct fblock *fb1, struct fblock *fb2);
180 extern int __fblock_bind(struct fblock *fb1, struct fblock *fb2);
182 /* Unbinds two fblock objects, decrements refcount each. */
183 extern int fblock_unbind(struct fblock *fb1, struct fblock *fb2);
184 extern int __fblock_unbind(struct fblock *fb1, struct fblock *fb2);
186 /* Lookup idp by fblock name. */
187 extern idp_t get_fblock_namespace_mapping(char *name);
188 extern idp_t __get_fblock_namespace_mapping(char *name);
191 * Maps existing fblock name to a new idp, can be used if object has been
192 * removed via unregister_fblock.
194 extern int change_fblock_namespace_mapping(char *name, idp_t new);
195 extern int __change_fblock_namespace_mapping(char *name, idp_t new);
197 extern int subscribe_to_remote_fblock(struct fblock *us,
198 struct fblock *remote);
199 extern void unsubscribe_from_remote_fblock(struct fblock *us,
200 struct fblock *remote);
202 static inline void init_fblock_subscriber(struct fblock *fb,
203 struct notifier_block *nb)
205 nb->priority = 0;
206 nb->notifier_call = fb->event_rx;
207 nb->next = NULL;
210 static inline int
211 fblock_register_foreign_subscriber(struct fblock *us,
212 struct notifier_block *remote)
214 return atomic_notifier_chain_register(&rcu_dereference_raw(us->others)->subscribers,
215 remote);
218 static inline void
219 fblock_unregister_foreign_subscriber(struct fblock *us,
220 struct notifier_block *remote)
222 atomic_notifier_chain_unregister(&rcu_dereference_raw(us->others)->subscribers,
223 remote);
226 static inline int notify_fblock_subscribers(struct fblock *us,
227 unsigned long cmd, void *arg)
229 if (unlikely(!rcu_dereference_raw(us->others)))
230 return -ENOENT;
231 return atomic_notifier_call_chain(&rcu_dereference_raw(us->others)->subscribers,
232 cmd, arg);
235 extern int init_fblock_tables(void);
236 extern void cleanup_fblock_tables(void);
238 /* here is the address, e.g. __builtin_return_address(0) */
239 static inline void fblock_over_panic(struct fblock *fb, void *here)
241 printk(KERN_EMERG "fblock_over_panic: text:%p ptr:%p idp:%u refs:%d "
242 "name:%s priv:%p fac:%p not:%p others: %p\n",
243 here, fb, fb->idp, atomic_read(&fb->refcnt), fb->name,
244 fb->private_data, fb->factory, fb->notifiers, fb->others);
245 BUG();
248 #endif /* __KERNEL__ */
249 #endif /* XT_FBLOCK_H */