]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/staging/batman-adv/main.c
Staging: batman-adv: Split originator handling parts out of routing.c
[net-next-2.6.git] / drivers / staging / batman-adv / main.c
CommitLineData
5beef3c9
AL
1/*
2 * Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
3 *
4 * Marek Lindner, Simon Wunderlich
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU General Public
8 * License as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301, USA
19 *
20 */
21
22#include "main.h"
23#include "proc.h"
5beef3c9
AL
24#include "routing.h"
25#include "send.h"
8a2e042c 26#include "originator.h"
5beef3c9
AL
27#include "soft-interface.h"
28#include "device.h"
29#include "translation-table.h"
30#include "hard-interface.h"
31#include "types.h"
32#include "vis.h"
33#include "hash.h"
34#include "compat.h"
35
36struct list_head if_list;
37struct hlist_head forw_bat_list;
38struct hlist_head forw_bcast_list;
39struct hashtable_t *orig_hash;
40
41DEFINE_SPINLOCK(orig_hash_lock);
42DEFINE_SPINLOCK(forw_bat_list_lock);
43DEFINE_SPINLOCK(forw_bcast_list_lock);
44
45atomic_t originator_interval;
46atomic_t vis_interval;
47atomic_t aggregation_enabled;
48int16_t num_hna;
49int16_t num_ifs;
50
51struct net_device *soft_device;
52
53static struct task_struct *kthread_task;
54
55unsigned char broadcastAddr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
56atomic_t module_state;
57
58struct workqueue_struct *bat_event_workqueue;
59
bad2239e
AL
60#ifdef CONFIG_BATMAN_DEBUG
61int debug;
62
63module_param(debug, int, 0644);
64
65int bat_debug_type(int type)
66{
67 return debug & type;
68}
69#endif
70
5beef3c9
AL
71int init_module(void)
72{
73 int retval;
74
75 INIT_LIST_HEAD(&if_list);
76 INIT_HLIST_HEAD(&forw_bat_list);
77 INIT_HLIST_HEAD(&forw_bcast_list);
78
79 atomic_set(&module_state, MODULE_INACTIVE);
80
81 atomic_set(&originator_interval, 1000);
82 atomic_set(&vis_interval, 1000);/* TODO: raise this later, this is only
83 * for debugging now. */
84 atomic_set(&aggregation_enabled, 1);
85
86 /* the name should not be longer than 10 chars - see
87 * http://lwn.net/Articles/23634/ */
88 bat_event_workqueue = create_singlethread_workqueue("bat_events");
89
90 if (!bat_event_workqueue)
91 return -ENOMEM;
92
93 retval = setup_procfs();
94 if (retval < 0)
95 return retval;
96
97 bat_device_init();
98
99 /* initialize layer 2 interface */
100 soft_device = alloc_netdev(sizeof(struct bat_priv) , "bat%d",
101 interface_setup);
102
103 if (!soft_device) {
bad2239e 104 printk(KERN_ERR "batman-adv:Unable to allocate the batman interface\n");
5beef3c9
AL
105 goto end;
106 }
107
108 retval = register_netdev(soft_device);
109
110 if (retval < 0) {
bad2239e 111 printk(KERN_ERR "batman-adv:Unable to register the batman interface: %i\n", retval);
5beef3c9
AL
112 goto free_soft_device;
113 }
114
115 register_netdevice_notifier(&hard_if_notifier);
116
bad2239e
AL
117 printk(KERN_INFO "batman-adv:B.A.T.M.A.N. advanced %s%s (compatibility version %i) loaded \n",
118 SOURCE_VERSION, REVISION_VERSION_STR, COMPAT_VERSION);
5beef3c9
AL
119
120 return 0;
121
122free_soft_device:
123 free_netdev(soft_device);
124 soft_device = NULL;
125end:
126 return -ENOMEM;
127}
128
129void cleanup_module(void)
130{
131 shutdown_module();
132
133 if (soft_device) {
134 unregister_netdev(soft_device);
135 soft_device = NULL;
136 }
137
138 unregister_netdevice_notifier(&hard_if_notifier);
139 cleanup_procfs();
140
141 destroy_workqueue(bat_event_workqueue);
142 bat_event_workqueue = NULL;
143}
144
145/* activates the module, creates bat device, starts timer ... */
146void activate_module(void)
147{
148 if (originator_init() < 1)
149 goto err;
150
151 if (hna_local_init() < 1)
152 goto err;
153
154 if (hna_global_init() < 1)
155 goto err;
156
157 hna_local_add(soft_device->dev_addr);
158
159 if (bat_device_setup() < 1)
160 goto end;
161
162 if (vis_init() < 1)
163 goto err;
164
165 /* (re)start kernel thread for packet processing */
166 if (!kthread_task) {
167 kthread_task = kthread_run(packet_recv_thread, NULL, "batman-adv");
168
169 if (IS_ERR(kthread_task)) {
bad2239e 170 printk(KERN_ERR "batman-adv:Unable to start packet receive thread\n");
5beef3c9
AL
171 kthread_task = NULL;
172 }
173 }
174
175 update_min_mtu();
176 atomic_set(&module_state, MODULE_ACTIVE);
177 goto end;
178
179err:
bad2239e 180 printk(KERN_ERR "batman-adv:Unable to allocate memory for mesh information structures: out of mem ?\n");
5beef3c9
AL
181 shutdown_module();
182end:
183 return;
184}
185
186/* shuts down the whole module.*/
187void shutdown_module(void)
188{
189 atomic_set(&module_state, MODULE_DEACTIVATING);
190
191 purge_outstanding_packets();
192 flush_workqueue(bat_event_workqueue);
193
194 vis_quit();
195
196 /* deactivate kernel thread for packet processing (if running) */
197 if (kthread_task) {
198 atomic_set(&exit_cond, 1);
199 wake_up_interruptible(&thread_wait);
200 kthread_stop(kthread_task);
201
202 kthread_task = NULL;
203 }
204
205 originator_free();
206
207 hna_local_free();
208 hna_global_free();
209
210 synchronize_net();
211 bat_device_destroy();
212
213 hardif_remove_interfaces();
214 synchronize_rcu();
215 atomic_set(&module_state, MODULE_INACTIVE);
216}
217
218void inc_module_count(void)
219{
220 try_module_get(THIS_MODULE);
221}
222
223void dec_module_count(void)
224{
225 module_put(THIS_MODULE);
226}
227
228int addr_to_string(char *buff, uint8_t *addr)
229{
230 return sprintf(buff, "%02x:%02x:%02x:%02x:%02x:%02x",
231 addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
232}
233
234/* returns 1 if they are the same originator */
235
236int compare_orig(void *data1, void *data2)
237{
238 return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0);
239}
240
241/* hashfunction to choose an entry in a hash table of given size */
242/* hash algorithm from http://en.wikipedia.org/wiki/Hash_table */
243int choose_orig(void *data, int32_t size)
244{
245 unsigned char *key = data;
246 uint32_t hash = 0;
247 size_t i;
248
249 for (i = 0; i < 6; i++) {
250 hash += key[i];
251 hash += (hash << 10);
252 hash ^= (hash >> 6);
253 }
254
255 hash += (hash << 3);
256 hash ^= (hash >> 11);
257 hash += (hash << 15);
258
259 return hash % size;
260}
261
262int is_my_mac(uint8_t *addr)
263{
264 struct batman_if *batman_if;
265 rcu_read_lock();
266 list_for_each_entry_rcu(batman_if, &if_list, list) {
267 if ((batman_if->net_dev) &&
268 (compare_orig(batman_if->net_dev->dev_addr, addr))) {
269 rcu_read_unlock();
270 return 1;
271 }
272 }
273 rcu_read_unlock();
274 return 0;
275
276}
277
278int is_bcast(uint8_t *addr)
279{
280 return (addr[0] == (uint8_t)0xff) && (addr[1] == (uint8_t)0xff);
281}
282
283int is_mcast(uint8_t *addr)
284{
285 return *addr & 0x01;
286}
287
288MODULE_LICENSE("GPL");
289
290MODULE_AUTHOR(DRIVER_AUTHOR);
291MODULE_DESCRIPTION(DRIVER_DESC);
292MODULE_SUPPORTED_DEVICE(DRIVER_DEVICE);
293#ifdef REVISION_VERSION
294MODULE_VERSION(SOURCE_VERSION "-" REVISION_VERSION);
295#else
296MODULE_VERSION(SOURCE_VERSION);
297#endif