made singleton
[ana-net.git] / src / fb_dummy.c
blobabb2a17070736906095c6e65faabc8ed4c6c66d6
1 /*
2 * Lightweight Autonomic Network Architecture
4 * Dummy test module.
6 * Copyright 2011 Daniel Borkmann <dborkma@tik.ee.ethz.ch>,
7 * Swiss federal institute of technology (ETH Zurich)
8 * Subject to the GPL.
9 */
11 #include <linux/kernel.h>
12 #include <linux/module.h>
13 #include <linux/spinlock.h>
14 #include <linux/notifier.h>
15 #include <linux/rcupdate.h>
16 #include <linux/seqlock.h>
17 #include <linux/percpu.h>
18 #include <linux/prefetch.h>
20 #include "xt_fblock.h"
21 #include "xt_builder.h"
22 #include "xt_idp.h"
23 #include "xt_skb.h"
24 #include "xt_engine.h"
25 #include "xt_builder.h"
27 struct fb_dummy_priv {
28 idp_t port[NUM_TYPES];
29 seqlock_t lock;
32 static int fb_dummy_netrx(const struct fblock * const fb,
33 struct sk_buff * const skb,
34 enum path_type * const dir)
36 int drop = 0;
37 unsigned int seq;
38 struct fb_dummy_priv __percpu *fb_priv_cpu;
40 fb_priv_cpu = this_cpu_ptr(rcu_dereference_raw(fb->private_data));
41 #ifdef __DEBUG
42 printk("Got skb on %p on ppe%d!\n", fb, smp_processor_id());
43 #endif
44 prefetchw(skb->cb);
45 do {
46 seq = read_seqbegin(&fb_priv_cpu->lock);
47 write_next_idp_to_skb(skb, fb->idp, fb_priv_cpu->port[*dir]);
48 if (fb_priv_cpu->port[*dir] == IDP_UNKNOWN)
49 drop = 1;
50 } while (read_seqretry(&fb_priv_cpu->lock, seq));
51 if (drop) {
52 kfree_skb(skb);
53 return PPE_DROPPED;
55 return PPE_SUCCESS;
58 static int fb_dummy_event(struct notifier_block *self, unsigned long cmd,
59 void *args)
61 int ret = NOTIFY_OK;
62 unsigned int cpu;
63 struct fblock *fb;
64 struct fb_dummy_priv __percpu *fb_priv;
66 rcu_read_lock();
67 fb = rcu_dereference_raw(container_of(self, struct fblock_notifier, nb)->self);
68 fb_priv = (struct fb_dummy_priv __percpu *) rcu_dereference_raw(fb->private_data);
69 rcu_read_unlock();
71 #ifdef __DEBUG
72 printk("Got event %lu on %p!\n", cmd, fb);
73 #endif
75 switch (cmd) {
76 case FBLOCK_BIND_IDP: {
77 struct fblock_bind_msg *msg = args;
78 get_online_cpus();
79 for_each_online_cpu(cpu) {
80 struct fb_dummy_priv *fb_priv_cpu;
81 fb_priv_cpu = per_cpu_ptr(fb_priv, cpu);
82 if (fb_priv_cpu->port[msg->dir] == IDP_UNKNOWN) {
83 write_seqlock(&fb_priv_cpu->lock);
84 fb_priv_cpu->port[msg->dir] = msg->idp;
85 write_sequnlock(&fb_priv_cpu->lock);
86 } else {
87 ret = NOTIFY_BAD;
88 break;
91 put_online_cpus();
92 } break;
93 case FBLOCK_UNBIND_IDP: {
94 struct fblock_bind_msg *msg = args;
95 get_online_cpus();
96 for_each_online_cpu(cpu) {
97 struct fb_dummy_priv *fb_priv_cpu;
98 fb_priv_cpu = per_cpu_ptr(fb_priv, cpu);
99 if (fb_priv_cpu->port[msg->dir] == msg->idp) {
100 write_seqlock(&fb_priv_cpu->lock);
101 fb_priv_cpu->port[msg->dir] = IDP_UNKNOWN;
102 write_sequnlock(&fb_priv_cpu->lock);
103 } else {
104 ret = NOTIFY_BAD;
105 break;
107 put_online_cpus();
109 put_online_cpus();
110 } break;
111 case FBLOCK_SET_OPT: {
112 struct fblock_opt_msg *msg = args;
113 printk("Set option %s to %s!\n", msg->key, msg->val);
114 } break;
115 default:
116 break;
119 return ret;
122 static struct fblock *fb_dummy_ctor(char *name)
124 int i, ret = 0;
125 unsigned int cpu;
126 struct fblock *fb;
127 struct fb_dummy_priv __percpu *fb_priv;
129 fb = alloc_fblock(GFP_ATOMIC);
130 if (!fb)
131 return NULL;
133 fb_priv = alloc_percpu(struct fb_dummy_priv);
134 if (!fb_priv)
135 goto err;
137 get_online_cpus();
138 for_each_online_cpu(cpu) {
139 struct fb_dummy_priv *fb_priv_cpu;
140 fb_priv_cpu = per_cpu_ptr(fb_priv, cpu);
141 seqlock_init(&fb_priv_cpu->lock);
142 for (i = 0; i < NUM_TYPES; ++i)
143 fb_priv_cpu->port[i] = IDP_UNKNOWN;
145 put_online_cpus();
147 ret = init_fblock(fb, name, fb_priv);
148 if (ret)
149 goto err2;
150 fb->netfb_rx = fb_dummy_netrx;
151 fb->event_rx = fb_dummy_event;
152 ret = register_fblock_namespace(fb);
153 if (ret)
154 goto err3;
155 __module_get(THIS_MODULE);
156 return fb;
157 err3:
158 cleanup_fblock_ctor(fb);
159 err2:
160 free_percpu(fb_priv);
161 err:
162 kfree_fblock(fb);
163 return NULL;
166 static void fb_dummy_dtor(struct fblock *fb)
168 free_percpu(rcu_dereference_raw(fb->private_data));
169 module_put(THIS_MODULE);
172 static struct fblock_factory fb_dummy_factory = {
173 .type = "dummy",
174 .mode = MODE_DUAL,
175 .ctor = fb_dummy_ctor,
176 .dtor = fb_dummy_dtor,
177 .owner = THIS_MODULE,
180 static int __init init_fb_dummy_module(void)
182 return register_fblock_type(&fb_dummy_factory);
185 static void __exit cleanup_fb_dummy_module(void)
187 unregister_fblock_type(&fb_dummy_factory);
190 module_init(init_fb_dummy_module);
191 module_exit(cleanup_fb_dummy_module);
193 MODULE_LICENSE("GPL");
194 MODULE_AUTHOR("Daniel Borkmann <dborkma@tik.ee.ethz.ch>");
195 MODULE_DESCRIPTION("LANA dummy/test module");