Some minor cleanups, and fixed hrtimer
[ana-net.git] / src / fb_tee.c
blobe70a0b9b3b96bcc1cd9d7d5255f316a4027e7d72
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 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 if (fb_priv_cpu->port_clone != IDP_UNKNOWN)
51 port_clone = fb_priv_cpu->port_clone;
52 } while (read_seqretry(&fb_priv_cpu->lock, seq));
54 if (port_clone != 0) {
55 cloned_skb = skb_copy(skb, GFP_ATOMIC);
56 if (cloned_skb) {
57 write_next_idp_to_skb(cloned_skb, fb->idp, port_clone);
58 engine_backlog_tail(cloned_skb, *dir);
61 if (drop) {
62 kfree_skb(skb);
63 return PPE_DROPPED;
65 return PPE_SUCCESS;
68 static int fb_tee_event(struct notifier_block *self, unsigned long cmd,
69 void *args)
71 int ret = NOTIFY_OK;
72 unsigned int cpu;
73 struct fblock *fb;
74 struct fb_tee_priv __percpu *fb_priv;
76 rcu_read_lock();
77 fb = rcu_dereference_raw(container_of(self, struct fblock_notifier, nb)->self);
78 fb_priv = (struct fb_tee_priv __percpu *) rcu_dereference_raw(fb->private_data);
79 rcu_read_unlock();
81 switch (cmd) {
82 case FBLOCK_BIND_IDP: {
83 int bound = 0;
84 struct fblock_bind_msg *msg = args;
85 get_online_cpus();
86 for_each_online_cpu(cpu) {
87 struct fb_tee_priv *fb_priv_cpu;
88 fb_priv_cpu = per_cpu_ptr(fb_priv, cpu);
89 if (fb_priv_cpu->port[msg->dir] == IDP_UNKNOWN) {
90 write_seqlock(&fb_priv_cpu->lock);
91 fb_priv_cpu->port[msg->dir] = msg->idp;
92 write_sequnlock(&fb_priv_cpu->lock);
93 bound = 1;
94 } else if (fb_priv_cpu->port_clone == IDP_UNKNOWN) {
95 write_seqlock(&fb_priv_cpu->lock);
96 fb_priv_cpu->port_clone = msg->idp;
97 write_sequnlock(&fb_priv_cpu->lock);
98 bound = 1;
99 } else {
100 ret = NOTIFY_BAD;
101 break;
104 put_online_cpus();
105 if (bound)
106 printk(KERN_INFO "[%s::%s] port %s bound to IDP%u\n",
107 fb->name, fb->factory->type,
108 path_names[msg->dir], msg->idp);
109 } break;
110 case FBLOCK_UNBIND_IDP: {
111 int unbound = 0;
112 struct fblock_bind_msg *msg = args;
113 get_online_cpus();
114 for_each_online_cpu(cpu) {
115 struct fb_tee_priv *fb_priv_cpu;
116 fb_priv_cpu = per_cpu_ptr(fb_priv, cpu);
117 if (fb_priv_cpu->port[msg->dir] == msg->idp) {
118 write_seqlock(&fb_priv_cpu->lock);
119 fb_priv_cpu->port[msg->dir] = IDP_UNKNOWN;
120 write_sequnlock(&fb_priv_cpu->lock);
121 unbound = 1;
122 } else if (fb_priv_cpu->port_clone == msg->idp) {
123 write_seqlock(&fb_priv_cpu->lock);
124 fb_priv_cpu->port_clone = IDP_UNKNOWN;
125 write_sequnlock(&fb_priv_cpu->lock);
126 unbound = 1;
127 } else {
128 ret = NOTIFY_BAD;
129 break;
132 put_online_cpus();
133 if (unbound)
134 printk(KERN_INFO "[%s::%s] port %s unbound\n",
135 fb->name, fb->factory->type,
136 path_names[msg->dir]);
137 } break;
138 case FBLOCK_SET_OPT: {
139 struct fblock_opt_msg *msg = args;
140 printk("Set option %s to %s!\n", msg->key, msg->val);
141 } break;
142 default:
143 break;
146 return ret;
149 static struct fblock *fb_tee_ctor(char *name)
151 int ret = 0;
152 unsigned int cpu;
153 struct fblock *fb;
154 struct fb_tee_priv __percpu *fb_priv;
156 fb = alloc_fblock(GFP_ATOMIC);
157 if (!fb)
158 return NULL;
160 fb_priv = alloc_percpu(struct fb_tee_priv);
161 if (!fb_priv)
162 goto err;
164 get_online_cpus();
165 for_each_online_cpu(cpu) {
166 struct fb_tee_priv *fb_priv_cpu;
167 fb_priv_cpu = per_cpu_ptr(fb_priv, cpu);
168 seqlock_init(&fb_priv_cpu->lock);
169 fb_priv_cpu->port[0] = IDP_UNKNOWN;
170 fb_priv_cpu->port[1] = IDP_UNKNOWN;
171 fb_priv_cpu->port_clone = IDP_UNKNOWN;
173 put_online_cpus();
175 ret = init_fblock(fb, name, fb_priv);
176 if (ret)
177 goto err2;
178 fb->netfb_rx = fb_tee_netrx;
179 fb->event_rx = fb_tee_event;
180 ret = register_fblock_namespace(fb);
181 if (ret)
182 goto err3;
183 __module_get(THIS_MODULE);
184 return fb;
185 err3:
186 cleanup_fblock_ctor(fb);
187 err2:
188 free_percpu(fb_priv);
189 err:
190 kfree_fblock(fb);
191 return NULL;
194 static void fb_tee_dtor(struct fblock *fb)
196 free_percpu(rcu_dereference_raw(fb->private_data));
197 module_put(THIS_MODULE);
200 static struct fblock_factory fb_tee_factory = {
201 .type = "tee",
202 .mode = MODE_DUAL,
203 .ctor = fb_tee_ctor,
204 .dtor = fb_tee_dtor,
205 .owner = THIS_MODULE,
208 static int __init init_fb_tee_module(void)
210 return register_fblock_type(&fb_tee_factory);
213 static void __exit cleanup_fb_tee_module(void)
215 unregister_fblock_type(&fb_tee_factory);
218 module_init(init_fb_tee_module);
219 module_exit(cleanup_fb_tee_module);
221 MODULE_LICENSE("GPL");
222 MODULE_AUTHOR("Daniel Borkmann <dborkma@tik.ee.ethz.ch>");
223 MODULE_DESCRIPTION("LANA tee module");