removed ifpps as std tool
[ana-net.git] / src / fb_tee.c
blob5a539c8a5624170377798cb3fad60b9ac5008d9b
1 /*
2 * Lightweight Autonomic Network Architecture
4 * Tee 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_tee_priv {
28 idp_t port[2];
29 idp_t port_clone;
30 seqlock_t lock;
33 static int fb_tee_netrx(const struct fblock * const fb,
34 struct sk_buff * const skb,
35 enum path_type * const dir)
37 idp_t port_clone = 0;
38 int drop = 0;
39 unsigned int seq;
40 struct sk_buff *cloned_skb = NULL;
41 struct fb_tee_priv __percpu *fb_priv_cpu;
43 fb_priv_cpu = this_cpu_ptr(rcu_dereference_raw(fb->private_data));
44 #ifdef __DEBUG
45 printk("Got skb on %p on ppe%d!\n", fb, smp_processor_id());
46 #endif
47 prefetchw(skb->cb);
48 do {
49 seq = read_seqbegin(&fb_priv_cpu->lock);
50 write_next_idp_to_skb(skb, fb->idp, fb_priv_cpu->port[*dir]);
51 if (fb_priv_cpu->port[*dir] == IDP_UNKNOWN)
52 drop = 1;
53 if (fb_priv_cpu->port_clone != IDP_UNKNOWN)
54 port_clone = fb_priv_cpu->port_clone;
55 } while (read_seqretry(&fb_priv_cpu->lock, seq));
57 if (port_clone != 0) {
58 cloned_skb = skb_copy(skb, GFP_ATOMIC);
59 if (cloned_skb) {
60 write_next_idp_to_skb(cloned_skb, fb->idp, port_clone);
61 engine_backlog_tail(cloned_skb, *dir);
64 if (drop) {
65 kfree_skb(skb);
66 return PPE_DROPPED;
68 return PPE_SUCCESS;
71 static int fb_tee_event(struct notifier_block *self, unsigned long cmd,
72 void *args)
74 int ret = NOTIFY_OK;
75 unsigned int cpu;
76 struct fblock *fb;
77 struct fb_tee_priv __percpu *fb_priv;
79 rcu_read_lock();
80 fb = rcu_dereference_raw(container_of(self, struct fblock_notifier, nb)->self);
81 fb_priv = (struct fb_tee_priv __percpu *) rcu_dereference_raw(fb->private_data);
82 rcu_read_unlock();
84 #ifdef __DEBUG
85 printk("Got event %lu on %p!\n", cmd, fb);
86 #endif
88 switch (cmd) {
89 case FBLOCK_BIND_IDP: {
90 int bound = 0;
91 struct fblock_bind_msg *msg = args;
92 get_online_cpus();
93 for_each_online_cpu(cpu) {
94 struct fb_tee_priv *fb_priv_cpu;
95 fb_priv_cpu = per_cpu_ptr(fb_priv, cpu);
96 if (fb_priv_cpu->port[msg->dir] == IDP_UNKNOWN) {
97 write_seqlock(&fb_priv_cpu->lock);
98 fb_priv_cpu->port[msg->dir] = msg->idp;
99 write_sequnlock(&fb_priv_cpu->lock);
100 bound = 1;
101 } else if (fb_priv_cpu->port_clone == IDP_UNKNOWN) {
102 write_seqlock(&fb_priv_cpu->lock);
103 fb_priv_cpu->port_clone = msg->idp;
104 write_sequnlock(&fb_priv_cpu->lock);
105 bound = 1;
106 } else {
107 ret = NOTIFY_BAD;
108 break;
111 put_online_cpus();
112 if (bound)
113 printk(KERN_INFO "[%s::%s] port %s bound to IDP%u\n",
114 fb->name, fb->factory->type,
115 path_names[msg->dir], msg->idp);
116 } break;
117 case FBLOCK_UNBIND_IDP: {
118 int unbound = 0;
119 struct fblock_bind_msg *msg = args;
120 get_online_cpus();
121 for_each_online_cpu(cpu) {
122 struct fb_tee_priv *fb_priv_cpu;
123 fb_priv_cpu = per_cpu_ptr(fb_priv, cpu);
124 if (fb_priv_cpu->port[msg->dir] == msg->idp) {
125 write_seqlock(&fb_priv_cpu->lock);
126 fb_priv_cpu->port[msg->dir] = IDP_UNKNOWN;
127 write_sequnlock(&fb_priv_cpu->lock);
128 unbound = 1;
129 } else if (fb_priv_cpu->port_clone == msg->idp) {
130 write_seqlock(&fb_priv_cpu->lock);
131 fb_priv_cpu->port_clone = IDP_UNKNOWN;
132 write_sequnlock(&fb_priv_cpu->lock);
133 unbound = 1;
134 } else {
135 ret = NOTIFY_BAD;
136 break;
139 put_online_cpus();
140 if (unbound)
141 printk(KERN_INFO "[%s::%s] port %s unbound\n",
142 fb->name, fb->factory->type,
143 path_names[msg->dir]);
144 } break;
145 case FBLOCK_SET_OPT: {
146 struct fblock_opt_msg *msg = args;
147 printk("Set option %s to %s!\n", msg->key, msg->val);
148 } break;
149 default:
150 break;
153 return ret;
156 static struct fblock *fb_tee_ctor(char *name)
158 int ret = 0;
159 unsigned int cpu;
160 struct fblock *fb;
161 struct fb_tee_priv __percpu *fb_priv;
163 fb = alloc_fblock(GFP_ATOMIC);
164 if (!fb)
165 return NULL;
167 fb_priv = alloc_percpu(struct fb_tee_priv);
168 if (!fb_priv)
169 goto err;
171 get_online_cpus();
172 for_each_online_cpu(cpu) {
173 struct fb_tee_priv *fb_priv_cpu;
174 fb_priv_cpu = per_cpu_ptr(fb_priv, cpu);
175 seqlock_init(&fb_priv_cpu->lock);
176 fb_priv_cpu->port[0] = IDP_UNKNOWN;
177 fb_priv_cpu->port[1] = IDP_UNKNOWN;
178 fb_priv_cpu->port_clone = IDP_UNKNOWN;
180 put_online_cpus();
182 ret = init_fblock(fb, name, fb_priv);
183 if (ret)
184 goto err2;
185 fb->netfb_rx = fb_tee_netrx;
186 fb->event_rx = fb_tee_event;
187 ret = register_fblock_namespace(fb);
188 if (ret)
189 goto err3;
190 __module_get(THIS_MODULE);
191 return fb;
192 err3:
193 cleanup_fblock_ctor(fb);
194 err2:
195 free_percpu(fb_priv);
196 err:
197 kfree_fblock(fb);
198 return NULL;
201 static void fb_tee_dtor(struct fblock *fb)
203 free_percpu(rcu_dereference_raw(fb->private_data));
204 module_put(THIS_MODULE);
207 static struct fblock_factory fb_tee_factory = {
208 .type = "tee",
209 .mode = MODE_DUAL,
210 .ctor = fb_tee_ctor,
211 .dtor = fb_tee_dtor,
212 .owner = THIS_MODULE,
215 static int __init init_fb_tee_module(void)
217 return register_fblock_type(&fb_tee_factory);
220 static void __exit cleanup_fb_tee_module(void)
222 unregister_fblock_type(&fb_tee_factory);
225 module_init(init_fb_tee_module);
226 module_exit(cleanup_fb_tee_module);
228 MODULE_LICENSE("GPL");
229 MODULE_AUTHOR("Daniel Borkmann <dborkma@tik.ee.ethz.ch>");
230 MODULE_DESCRIPTION("LANA tee module");