batman-adv: introduce is_single_hop_neigh variable to increase readability
[linux-block.git] / net / batman-adv / main.c
CommitLineData
c6c8fea2 1/*
567db7b0 2 * Copyright (C) 2007-2012 B.A.T.M.A.N. contributors:
c6c8fea2
SE
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 "bat_sysfs.h"
24#include "bat_debugfs.h"
25#include "routing.h"
26#include "send.h"
27#include "originator.h"
28#include "soft-interface.h"
29#include "icmp_socket.h"
30#include "translation-table.h"
31#include "hard-interface.h"
32#include "gateway_client.h"
23721387 33#include "bridge_loop_avoidance.h"
c6c8fea2
SE
34#include "vis.h"
35#include "hash.h"
1c280471 36#include "bat_algo.h"
c6c8fea2 37
c3caf519
SE
38
39/* List manipulations on hardif_list have to be rtnl_lock()'ed,
40 * list traversals just rcu-locked */
4389e47a 41struct list_head hardif_list;
1c280471
ML
42char bat_routing_algo[20] = "BATMAN IV";
43static struct hlist_head bat_algo_list;
c6c8fea2
SE
44
45unsigned char broadcast_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
46
47struct workqueue_struct *bat_event_workqueue;
48
49static int __init batman_init(void)
50{
4389e47a 51 INIT_LIST_HEAD(&hardif_list);
1c280471
ML
52 INIT_HLIST_HEAD(&bat_algo_list);
53
54 bat_iv_init();
c6c8fea2
SE
55
56 /* the name should not be longer than 10 chars - see
57 * http://lwn.net/Articles/23634/ */
58 bat_event_workqueue = create_singlethread_workqueue("bat_events");
59
60 if (!bat_event_workqueue)
61 return -ENOMEM;
62
63 bat_socket_init();
64 debugfs_init();
65
66 register_netdevice_notifier(&hard_if_notifier);
67
86ceb360
SE
68 pr_info("B.A.T.M.A.N. advanced %s (compatibility version %i) loaded\n",
69 SOURCE_VERSION, COMPAT_VERSION);
c6c8fea2
SE
70
71 return 0;
72}
73
74static void __exit batman_exit(void)
75{
76 debugfs_destroy();
77 unregister_netdevice_notifier(&hard_if_notifier);
78 hardif_remove_interfaces();
79
80 flush_workqueue(bat_event_workqueue);
81 destroy_workqueue(bat_event_workqueue);
82 bat_event_workqueue = NULL;
83
84 rcu_barrier();
85}
86
87int mesh_init(struct net_device *soft_iface)
88{
89 struct bat_priv *bat_priv = netdev_priv(soft_iface);
90
c6c8fea2
SE
91 spin_lock_init(&bat_priv->forw_bat_list_lock);
92 spin_lock_init(&bat_priv->forw_bcast_list_lock);
a73105b8
AQ
93 spin_lock_init(&bat_priv->tt_changes_list_lock);
94 spin_lock_init(&bat_priv->tt_req_list_lock);
cc47f66e 95 spin_lock_init(&bat_priv->tt_roam_list_lock);
a73105b8 96 spin_lock_init(&bat_priv->tt_buff_lock);
c6c8fea2
SE
97 spin_lock_init(&bat_priv->gw_list_lock);
98 spin_lock_init(&bat_priv->vis_hash_lock);
99 spin_lock_init(&bat_priv->vis_list_lock);
c6c8fea2
SE
100
101 INIT_HLIST_HEAD(&bat_priv->forw_bat_list);
102 INIT_HLIST_HEAD(&bat_priv->forw_bcast_list);
103 INIT_HLIST_HEAD(&bat_priv->gw_list);
a73105b8
AQ
104 INIT_LIST_HEAD(&bat_priv->tt_changes_list);
105 INIT_LIST_HEAD(&bat_priv->tt_req_list);
cc47f66e 106 INIT_LIST_HEAD(&bat_priv->tt_roam_list);
c6c8fea2
SE
107
108 if (originator_init(bat_priv) < 1)
109 goto err;
110
a73105b8 111 if (tt_init(bat_priv) < 1)
c6c8fea2
SE
112 goto err;
113
bc279080 114 tt_local_add(soft_iface, soft_iface->dev_addr, NULL_IFINDEX);
c6c8fea2
SE
115
116 if (vis_init(bat_priv) < 1)
117 goto err;
118
23721387
SW
119 if (bla_init(bat_priv) < 1)
120 goto err;
121
2265c141 122 atomic_set(&bat_priv->gw_reselect, 0);
c6c8fea2
SE
123 atomic_set(&bat_priv->mesh_state, MESH_ACTIVE);
124 goto end;
125
126err:
c6c8fea2
SE
127 mesh_free(soft_iface);
128 return -1;
129
130end:
131 return 0;
132}
133
134void mesh_free(struct net_device *soft_iface)
135{
136 struct bat_priv *bat_priv = netdev_priv(soft_iface);
137
138 atomic_set(&bat_priv->mesh_state, MESH_DEACTIVATING);
139
140 purge_outstanding_packets(bat_priv, NULL);
141
142 vis_quit(bat_priv);
143
144 gw_node_purge(bat_priv);
145 originator_free(bat_priv);
146
a73105b8 147 tt_free(bat_priv);
c6c8fea2 148
23721387
SW
149 bla_free(bat_priv);
150
c6c8fea2
SE
151 atomic_set(&bat_priv->mesh_state, MESH_INACTIVE);
152}
153
154void inc_module_count(void)
155{
156 try_module_get(THIS_MODULE);
157}
158
159void dec_module_count(void)
160{
161 module_put(THIS_MODULE);
162}
163
747e4221 164int is_my_mac(const uint8_t *addr)
c6c8fea2 165{
747e4221 166 const struct hard_iface *hard_iface;
c6c8fea2
SE
167
168 rcu_read_lock();
e6c10f43
ML
169 list_for_each_entry_rcu(hard_iface, &hardif_list, list) {
170 if (hard_iface->if_status != IF_ACTIVE)
c6c8fea2
SE
171 continue;
172
e6c10f43 173 if (compare_eth(hard_iface->net_dev->dev_addr, addr)) {
c6c8fea2
SE
174 rcu_read_unlock();
175 return 1;
176 }
177 }
178 rcu_read_unlock();
179 return 0;
c6c8fea2
SE
180}
181
1c280471
ML
182static struct bat_algo_ops *bat_algo_get(char *name)
183{
184 struct bat_algo_ops *bat_algo_ops = NULL, *bat_algo_ops_tmp;
185 struct hlist_node *node;
186
187 hlist_for_each_entry(bat_algo_ops_tmp, node, &bat_algo_list, list) {
188 if (strcmp(bat_algo_ops_tmp->name, name) != 0)
189 continue;
190
191 bat_algo_ops = bat_algo_ops_tmp;
192 break;
193 }
194
195 return bat_algo_ops;
196}
197
198int bat_algo_register(struct bat_algo_ops *bat_algo_ops)
199{
200 struct bat_algo_ops *bat_algo_ops_tmp;
201 int ret = -1;
202
203 bat_algo_ops_tmp = bat_algo_get(bat_algo_ops->name);
204 if (bat_algo_ops_tmp) {
86ceb360
SE
205 pr_info("Trying to register already registered routing algorithm: %s\n",
206 bat_algo_ops->name);
1c280471
ML
207 goto out;
208 }
209
01c4224b 210 /* all algorithms must implement all ops (for now) */
c2aca022 211 if (!bat_algo_ops->bat_iface_enable ||
00a50076 212 !bat_algo_ops->bat_iface_disable ||
cd8b78e7 213 !bat_algo_ops->bat_primary_iface_set ||
01c4224b
ML
214 !bat_algo_ops->bat_ogm_update_mac ||
215 !bat_algo_ops->bat_ogm_schedule ||
216 !bat_algo_ops->bat_ogm_emit ||
217 !bat_algo_ops->bat_ogm_receive) {
218 pr_info("Routing algo '%s' does not implement required ops\n",
219 bat_algo_ops->name);
220 goto out;
221 }
222
1c280471
ML
223 INIT_HLIST_NODE(&bat_algo_ops->list);
224 hlist_add_head(&bat_algo_ops->list, &bat_algo_list);
225 ret = 0;
226
227out:
228 return ret;
229}
230
231int bat_algo_select(struct bat_priv *bat_priv, char *name)
232{
233 struct bat_algo_ops *bat_algo_ops;
234 int ret = -1;
235
236 bat_algo_ops = bat_algo_get(name);
237 if (!bat_algo_ops)
238 goto out;
239
240 bat_priv->bat_algo_ops = bat_algo_ops;
241 ret = 0;
242
243out:
244 return ret;
245}
246
247int bat_algo_seq_print_text(struct seq_file *seq, void *offset)
248{
249 struct bat_algo_ops *bat_algo_ops;
250 struct hlist_node *node;
251
252 seq_printf(seq, "Available routing algorithms:\n");
253
254 hlist_for_each_entry(bat_algo_ops, node, &bat_algo_list, list) {
255 seq_printf(seq, "%s\n", bat_algo_ops->name);
256 }
257
258 return 0;
259}
260
d419be1f
ML
261static int param_set_ra(const char *val, const struct kernel_param *kp)
262{
263 struct bat_algo_ops *bat_algo_ops;
264
265 bat_algo_ops = bat_algo_get((char *)val);
266 if (!bat_algo_ops) {
267 pr_err("Routing algorithm '%s' is not supported\n", val);
268 return -EINVAL;
269 }
270
271 return param_set_copystring(val, kp);
272}
273
274static const struct kernel_param_ops param_ops_ra = {
275 .set = param_set_ra,
276 .get = param_get_string,
277};
278
279static struct kparam_string __param_string_ra = {
280 .maxlen = sizeof(bat_routing_algo),
281 .string = bat_routing_algo,
282};
283
284module_param_cb(routing_algo, &param_ops_ra, &__param_string_ra, 0644);
c6c8fea2
SE
285module_init(batman_init);
286module_exit(batman_exit);
287
288MODULE_LICENSE("GPL");
289
290MODULE_AUTHOR(DRIVER_AUTHOR);
291MODULE_DESCRIPTION(DRIVER_DESC);
292MODULE_SUPPORTED_DEVICE(DRIVER_DEVICE);
c6c8fea2 293MODULE_VERSION(SOURCE_VERSION);