removed ifpps as std tool
[ana-net.git] / src / fb_dummy.c
blobf820ed9945dfec3a8d0d7a6ef47aca3d73817b9d
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[2];
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 int bound = 0;
78 struct fblock_bind_msg *msg = args;
79 get_online_cpus();
80 for_each_online_cpu(cpu) {
81 struct fb_dummy_priv *fb_priv_cpu;
82 fb_priv_cpu = per_cpu_ptr(fb_priv, cpu);
83 if (fb_priv_cpu->port[msg->dir] == IDP_UNKNOWN) {
84 write_seqlock(&fb_priv_cpu->lock);
85 fb_priv_cpu->port[msg->dir] = msg->idp;
86 write_sequnlock(&fb_priv_cpu->lock);
87 bound = 1;
88 } else {
89 ret = NOTIFY_BAD;
90 break;
93 put_online_cpus();
94 if (bound)
95 printk(KERN_INFO "[%s::%s] port %s bound to IDP%u\n",
96 fb->name, fb->factory->type,
97 path_names[msg->dir], msg->idp);
98 } break;
99 case FBLOCK_UNBIND_IDP: {
100 int unbound = 0;
101 struct fblock_bind_msg *msg = args;
102 get_online_cpus();
103 for_each_online_cpu(cpu) {
104 struct fb_dummy_priv *fb_priv_cpu;
105 fb_priv_cpu = per_cpu_ptr(fb_priv, cpu);
106 if (fb_priv_cpu->port[msg->dir] == msg->idp) {
107 write_seqlock(&fb_priv_cpu->lock);
108 fb_priv_cpu->port[msg->dir] = IDP_UNKNOWN;
109 write_sequnlock(&fb_priv_cpu->lock);
110 unbound = 1;
111 } else {
112 ret = NOTIFY_BAD;
113 break;
116 put_online_cpus();
117 if (unbound)
118 printk(KERN_INFO "[%s::%s] port %s unbound\n",
119 fb->name, fb->factory->type,
120 path_names[msg->dir]);
121 } break;
122 case FBLOCK_SET_OPT: {
123 struct fblock_opt_msg *msg = args;
124 printk("Set option %s to %s!\n", msg->key, msg->val);
125 } break;
126 default:
127 break;
130 return ret;
133 static struct fblock *fb_dummy_ctor(char *name)
135 int ret = 0;
136 unsigned int cpu;
137 struct fblock *fb;
138 struct fb_dummy_priv __percpu *fb_priv;
140 fb = alloc_fblock(GFP_ATOMIC);
141 if (!fb)
142 return NULL;
144 fb_priv = alloc_percpu(struct fb_dummy_priv);
145 if (!fb_priv)
146 goto err;
148 get_online_cpus();
149 for_each_online_cpu(cpu) {
150 struct fb_dummy_priv *fb_priv_cpu;
151 fb_priv_cpu = per_cpu_ptr(fb_priv, cpu);
152 seqlock_init(&fb_priv_cpu->lock);
153 fb_priv_cpu->port[0] = IDP_UNKNOWN;
154 fb_priv_cpu->port[1] = IDP_UNKNOWN;
156 put_online_cpus();
158 ret = init_fblock(fb, name, fb_priv);
159 if (ret)
160 goto err2;
161 fb->netfb_rx = fb_dummy_netrx;
162 fb->event_rx = fb_dummy_event;
163 ret = register_fblock_namespace(fb);
164 if (ret)
165 goto err3;
166 __module_get(THIS_MODULE);
167 return fb;
168 err3:
169 cleanup_fblock_ctor(fb);
170 err2:
171 free_percpu(fb_priv);
172 err:
173 kfree_fblock(fb);
174 return NULL;
177 static void fb_dummy_dtor(struct fblock *fb)
179 free_percpu(rcu_dereference_raw(fb->private_data));
180 module_put(THIS_MODULE);
183 static struct fblock_factory fb_dummy_factory = {
184 .type = "dummy",
185 .mode = MODE_DUAL,
186 .ctor = fb_dummy_ctor,
187 .dtor = fb_dummy_dtor,
188 .owner = THIS_MODULE,
191 static int __init init_fb_dummy_module(void)
193 return register_fblock_type(&fb_dummy_factory);
196 static void __exit cleanup_fb_dummy_module(void)
198 unregister_fblock_type(&fb_dummy_factory);
201 module_init(init_fb_dummy_module);
202 module_exit(cleanup_fb_dummy_module);
204 MODULE_LICENSE("GPL");
205 MODULE_AUTHOR("Daniel Borkmann <dborkma@tik.ee.ethz.ch>");
206 MODULE_DESCRIPTION("LANA dummy/test module");