]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/staging/batman-adv/main.c
Staging: asus_oled: Add defines for asus vendor_id and device_id to be consistent...
[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"
24#include "log.h"
25#include "routing.h"
26#include "send.h"
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
60int init_module(void)
61{
62 int retval;
63
64 INIT_LIST_HEAD(&if_list);
65 INIT_HLIST_HEAD(&forw_bat_list);
66 INIT_HLIST_HEAD(&forw_bcast_list);
67
68 atomic_set(&module_state, MODULE_INACTIVE);
69
70 atomic_set(&originator_interval, 1000);
71 atomic_set(&vis_interval, 1000);/* TODO: raise this later, this is only
72 * for debugging now. */
73 atomic_set(&aggregation_enabled, 1);
74
75 /* the name should not be longer than 10 chars - see
76 * http://lwn.net/Articles/23634/ */
77 bat_event_workqueue = create_singlethread_workqueue("bat_events");
78
79 if (!bat_event_workqueue)
80 return -ENOMEM;
81
82 retval = setup_procfs();
83 if (retval < 0)
84 return retval;
85
86 bat_device_init();
87
88 /* initialize layer 2 interface */
89 soft_device = alloc_netdev(sizeof(struct bat_priv) , "bat%d",
90 interface_setup);
91
92 if (!soft_device) {
93 debug_log(LOG_TYPE_CRIT, "Unable to allocate the batman interface\n");
94 goto end;
95 }
96
97 retval = register_netdev(soft_device);
98
99 if (retval < 0) {
100 debug_log(LOG_TYPE_CRIT, "Unable to register the batman interface: %i\n", retval);
101 goto free_soft_device;
102 }
103
104 register_netdevice_notifier(&hard_if_notifier);
105
106 debug_log(LOG_TYPE_CRIT, "B.A.T.M.A.N. advanced %s%s (compatibility version %i) loaded \n",
107 SOURCE_VERSION, REVISION_VERSION_STR, COMPAT_VERSION);
108
109 return 0;
110
111free_soft_device:
112 free_netdev(soft_device);
113 soft_device = NULL;
114end:
115 return -ENOMEM;
116}
117
118void cleanup_module(void)
119{
120 shutdown_module();
121
122 if (soft_device) {
123 unregister_netdev(soft_device);
124 soft_device = NULL;
125 }
126
127 unregister_netdevice_notifier(&hard_if_notifier);
128 cleanup_procfs();
129
130 destroy_workqueue(bat_event_workqueue);
131 bat_event_workqueue = NULL;
132}
133
134/* activates the module, creates bat device, starts timer ... */
135void activate_module(void)
136{
137 if (originator_init() < 1)
138 goto err;
139
140 if (hna_local_init() < 1)
141 goto err;
142
143 if (hna_global_init() < 1)
144 goto err;
145
146 hna_local_add(soft_device->dev_addr);
147
148 if (bat_device_setup() < 1)
149 goto end;
150
151 if (vis_init() < 1)
152 goto err;
153
154 /* (re)start kernel thread for packet processing */
155 if (!kthread_task) {
156 kthread_task = kthread_run(packet_recv_thread, NULL, "batman-adv");
157
158 if (IS_ERR(kthread_task)) {
159 debug_log(LOG_TYPE_CRIT, "Unable to start packet receive thread\n");
160 kthread_task = NULL;
161 }
162 }
163
164 update_min_mtu();
165 atomic_set(&module_state, MODULE_ACTIVE);
166 goto end;
167
168err:
169 debug_log(LOG_TYPE_CRIT, "Unable to allocate memory for mesh information structures: out of mem ?\n");
170 shutdown_module();
171end:
172 return;
173}
174
175/* shuts down the whole module.*/
176void shutdown_module(void)
177{
178 atomic_set(&module_state, MODULE_DEACTIVATING);
179
180 purge_outstanding_packets();
181 flush_workqueue(bat_event_workqueue);
182
183 vis_quit();
184
185 /* deactivate kernel thread for packet processing (if running) */
186 if (kthread_task) {
187 atomic_set(&exit_cond, 1);
188 wake_up_interruptible(&thread_wait);
189 kthread_stop(kthread_task);
190
191 kthread_task = NULL;
192 }
193
194 originator_free();
195
196 hna_local_free();
197 hna_global_free();
198
199 synchronize_net();
200 bat_device_destroy();
201
202 hardif_remove_interfaces();
203 synchronize_rcu();
204 atomic_set(&module_state, MODULE_INACTIVE);
205}
206
207void inc_module_count(void)
208{
209 try_module_get(THIS_MODULE);
210}
211
212void dec_module_count(void)
213{
214 module_put(THIS_MODULE);
215}
216
217int addr_to_string(char *buff, uint8_t *addr)
218{
219 return sprintf(buff, "%02x:%02x:%02x:%02x:%02x:%02x",
220 addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
221}
222
223/* returns 1 if they are the same originator */
224
225int compare_orig(void *data1, void *data2)
226{
227 return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0);
228}
229
230/* hashfunction to choose an entry in a hash table of given size */
231/* hash algorithm from http://en.wikipedia.org/wiki/Hash_table */
232int choose_orig(void *data, int32_t size)
233{
234 unsigned char *key = data;
235 uint32_t hash = 0;
236 size_t i;
237
238 for (i = 0; i < 6; i++) {
239 hash += key[i];
240 hash += (hash << 10);
241 hash ^= (hash >> 6);
242 }
243
244 hash += (hash << 3);
245 hash ^= (hash >> 11);
246 hash += (hash << 15);
247
248 return hash % size;
249}
250
251int is_my_mac(uint8_t *addr)
252{
253 struct batman_if *batman_if;
254 rcu_read_lock();
255 list_for_each_entry_rcu(batman_if, &if_list, list) {
256 if ((batman_if->net_dev) &&
257 (compare_orig(batman_if->net_dev->dev_addr, addr))) {
258 rcu_read_unlock();
259 return 1;
260 }
261 }
262 rcu_read_unlock();
263 return 0;
264
265}
266
267int is_bcast(uint8_t *addr)
268{
269 return (addr[0] == (uint8_t)0xff) && (addr[1] == (uint8_t)0xff);
270}
271
272int is_mcast(uint8_t *addr)
273{
274 return *addr & 0x01;
275}
276
277MODULE_LICENSE("GPL");
278
279MODULE_AUTHOR(DRIVER_AUTHOR);
280MODULE_DESCRIPTION(DRIVER_DESC);
281MODULE_SUPPORTED_DEVICE(DRIVER_DEVICE);
282#ifdef REVISION_VERSION
283MODULE_VERSION(SOURCE_VERSION "-" REVISION_VERSION);
284#else
285MODULE_VERSION(SOURCE_VERSION);
286#endif