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
));
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
)
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
);
57 write_next_idp_to_skb(cloned_skb
, fb
->idp
, port_clone
);
58 engine_backlog_tail(cloned_skb
, *dir
);
68 static int fb_tee_event(struct notifier_block
*self
, unsigned long cmd
,
74 struct fb_tee_priv __percpu
*fb_priv
;
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
);
82 case FBLOCK_BIND_IDP
: {
84 struct fblock_bind_msg
*msg
= args
;
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
);
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
);
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
);
110 case FBLOCK_UNBIND_IDP
: {
112 struct fblock_bind_msg
*msg
= args
;
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
);
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
);
134 printk(KERN_INFO
"[%s::%s] port %s unbound\n",
135 fb
->name
, fb
->factory
->type
,
136 path_names
[msg
->dir
]);
138 case FBLOCK_SET_OPT
: {
139 struct fblock_opt_msg
*msg
= args
;
140 printk("Set option %s to %s!\n", msg
->key
, msg
->val
);
149 static struct fblock
*fb_tee_ctor(char *name
)
154 struct fb_tee_priv __percpu
*fb_priv
;
156 fb
= alloc_fblock(GFP_ATOMIC
);
160 fb_priv
= alloc_percpu(struct fb_tee_priv
);
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
;
175 ret
= init_fblock(fb
, name
, fb_priv
);
178 fb
->netfb_rx
= fb_tee_netrx
;
179 fb
->event_rx
= fb_tee_event
;
180 ret
= register_fblock_namespace(fb
);
183 __module_get(THIS_MODULE
);
186 cleanup_fblock_ctor(fb
);
188 free_percpu(fb_priv
);
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
= {
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)
216 unregister_fblock_type(&fb_tee_factory
);
219 module_init(init_fb_tee_module
);
220 module_exit(cleanup_fb_tee_module
);
222 MODULE_LICENSE("GPL");
223 MODULE_AUTHOR("Daniel Borkmann <dborkma@tik.ee.ethz.ch>");
224 MODULE_DESCRIPTION("LANA tee module");