2 * Lightweight Autonomic Network Architecture
6 * Copyright 2011 Daniel Borkmann <dborkma@tik.ee.ethz.ch>,
7 * Swiss federal institute of technology (ETH Zurich)
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"
24 #include "xt_engine.h"
25 #include "xt_builder.h"
33 static int fb_tee_netrx(const struct fblock
* const fb
,
34 struct sk_buff
* const skb
,
35 enum path_type
* const dir
)
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
));
45 printk("Got skb on %p on ppe%d!\n", fb
, smp_processor_id());
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
)
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
);
60 write_next_idp_to_skb(cloned_skb
, fb
->idp
, port_clone
);
61 engine_backlog_tail(cloned_skb
, *dir
);
71 static int fb_tee_event(struct notifier_block
*self
, unsigned long cmd
,
77 struct fb_tee_priv __percpu
*fb_priv
;
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
);
85 printk("Got event %lu on %p!\n", cmd
, fb
);
89 case FBLOCK_BIND_IDP
: {
91 struct fblock_bind_msg
*msg
= args
;
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
);
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
);
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
);
117 case FBLOCK_UNBIND_IDP
: {
119 struct fblock_bind_msg
*msg
= args
;
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
);
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
);
141 printk(KERN_INFO
"[%s::%s] port %s unbound\n",
142 fb
->name
, fb
->factory
->type
,
143 path_names
[msg
->dir
]);
145 case FBLOCK_SET_OPT
: {
146 struct fblock_opt_msg
*msg
= args
;
147 printk("Set option %s to %s!\n", msg
->key
, msg
->val
);
156 static struct fblock
*fb_tee_ctor(char *name
)
161 struct fb_tee_priv __percpu
*fb_priv
;
163 fb
= alloc_fblock(GFP_ATOMIC
);
167 fb_priv
= alloc_percpu(struct fb_tee_priv
);
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
;
182 ret
= init_fblock(fb
, name
, fb_priv
);
185 fb
->netfb_rx
= fb_tee_netrx
;
186 fb
->event_rx
= fb_tee_event
;
187 ret
= register_fblock_namespace(fb
);
190 __module_get(THIS_MODULE
);
193 cleanup_fblock_ctor(fb
);
195 free_percpu(fb_priv
);
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
= {
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");