aboutsummaryrefslogtreecommitdiffstats
path: root/net/batman-adv/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/batman-adv/main.c')
-rw-r--r--net/batman-adv/main.c138
1 files changed, 129 insertions, 9 deletions
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c
index 6d51caaf8cec..083a2993efe4 100644
--- a/net/batman-adv/main.c
+++ b/net/batman-adv/main.c
@@ -30,6 +30,7 @@
30#include "translation-table.h" 30#include "translation-table.h"
31#include "hard-interface.h" 31#include "hard-interface.h"
32#include "gateway_client.h" 32#include "gateway_client.h"
33#include "bridge_loop_avoidance.h"
33#include "vis.h" 34#include "vis.h"
34#include "hash.h" 35#include "hash.h"
35#include "bat_algo.h" 36#include "bat_algo.h"
@@ -38,6 +39,7 @@
38/* List manipulations on hardif_list have to be rtnl_lock()'ed, 39/* List manipulations on hardif_list have to be rtnl_lock()'ed,
39 * list traversals just rcu-locked */ 40 * list traversals just rcu-locked */
40struct list_head hardif_list; 41struct list_head hardif_list;
42static int (*recv_packet_handler[256])(struct sk_buff *, struct hard_iface *);
41char bat_routing_algo[20] = "BATMAN IV"; 43char bat_routing_algo[20] = "BATMAN IV";
42static struct hlist_head bat_algo_list; 44static struct hlist_head bat_algo_list;
43 45
@@ -45,11 +47,15 @@ unsigned char broadcast_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
45 47
46struct workqueue_struct *bat_event_workqueue; 48struct workqueue_struct *bat_event_workqueue;
47 49
50static void recv_handler_init(void);
51
48static int __init batman_init(void) 52static int __init batman_init(void)
49{ 53{
50 INIT_LIST_HEAD(&hardif_list); 54 INIT_LIST_HEAD(&hardif_list);
51 INIT_HLIST_HEAD(&bat_algo_list); 55 INIT_HLIST_HEAD(&bat_algo_list);
52 56
57 recv_handler_init();
58
53 bat_iv_init(); 59 bat_iv_init();
54 60
55 /* the name should not be longer than 10 chars - see 61 /* the name should not be longer than 10 chars - see
@@ -96,13 +102,10 @@ int mesh_init(struct net_device *soft_iface)
96 spin_lock_init(&bat_priv->gw_list_lock); 102 spin_lock_init(&bat_priv->gw_list_lock);
97 spin_lock_init(&bat_priv->vis_hash_lock); 103 spin_lock_init(&bat_priv->vis_hash_lock);
98 spin_lock_init(&bat_priv->vis_list_lock); 104 spin_lock_init(&bat_priv->vis_list_lock);
99 spin_lock_init(&bat_priv->softif_neigh_lock);
100 spin_lock_init(&bat_priv->softif_neigh_vid_lock);
101 105
102 INIT_HLIST_HEAD(&bat_priv->forw_bat_list); 106 INIT_HLIST_HEAD(&bat_priv->forw_bat_list);
103 INIT_HLIST_HEAD(&bat_priv->forw_bcast_list); 107 INIT_HLIST_HEAD(&bat_priv->forw_bcast_list);
104 INIT_HLIST_HEAD(&bat_priv->gw_list); 108 INIT_HLIST_HEAD(&bat_priv->gw_list);
105 INIT_HLIST_HEAD(&bat_priv->softif_neigh_vids);
106 INIT_LIST_HEAD(&bat_priv->tt_changes_list); 109 INIT_LIST_HEAD(&bat_priv->tt_changes_list);
107 INIT_LIST_HEAD(&bat_priv->tt_req_list); 110 INIT_LIST_HEAD(&bat_priv->tt_req_list);
108 INIT_LIST_HEAD(&bat_priv->tt_roam_list); 111 INIT_LIST_HEAD(&bat_priv->tt_roam_list);
@@ -118,6 +121,9 @@ int mesh_init(struct net_device *soft_iface)
118 if (vis_init(bat_priv) < 1) 121 if (vis_init(bat_priv) < 1)
119 goto err; 122 goto err;
120 123
124 if (bla_init(bat_priv) < 1)
125 goto err;
126
121 atomic_set(&bat_priv->gw_reselect, 0); 127 atomic_set(&bat_priv->gw_reselect, 0);
122 atomic_set(&bat_priv->mesh_state, MESH_ACTIVE); 128 atomic_set(&bat_priv->mesh_state, MESH_ACTIVE);
123 goto end; 129 goto end;
@@ -145,7 +151,7 @@ void mesh_free(struct net_device *soft_iface)
145 151
146 tt_free(bat_priv); 152 tt_free(bat_priv);
147 153
148 softif_neigh_purge(bat_priv); 154 bla_free(bat_priv);
149 155
150 atomic_set(&bat_priv->mesh_state, MESH_INACTIVE); 156 atomic_set(&bat_priv->mesh_state, MESH_INACTIVE);
151} 157}
@@ -178,6 +184,120 @@ int is_my_mac(const uint8_t *addr)
178 return 0; 184 return 0;
179} 185}
180 186
187static int recv_unhandled_packet(struct sk_buff *skb,
188 struct hard_iface *recv_if)
189{
190 return NET_RX_DROP;
191}
192
193/* incoming packets with the batman ethertype received on any active hard
194 * interface
195 */
196int batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
197 struct packet_type *ptype, struct net_device *orig_dev)
198{
199 struct bat_priv *bat_priv;
200 struct batman_ogm_packet *batman_ogm_packet;
201 struct hard_iface *hard_iface;
202 uint8_t idx;
203 int ret;
204
205 hard_iface = container_of(ptype, struct hard_iface, batman_adv_ptype);
206 skb = skb_share_check(skb, GFP_ATOMIC);
207
208 /* skb was released by skb_share_check() */
209 if (!skb)
210 goto err_out;
211
212 /* packet should hold at least type and version */
213 if (unlikely(!pskb_may_pull(skb, 2)))
214 goto err_free;
215
216 /* expect a valid ethernet header here. */
217 if (unlikely(skb->mac_len != ETH_HLEN || !skb_mac_header(skb)))
218 goto err_free;
219
220 if (!hard_iface->soft_iface)
221 goto err_free;
222
223 bat_priv = netdev_priv(hard_iface->soft_iface);
224
225 if (atomic_read(&bat_priv->mesh_state) != MESH_ACTIVE)
226 goto err_free;
227
228 /* discard frames on not active interfaces */
229 if (hard_iface->if_status != IF_ACTIVE)
230 goto err_free;
231
232 batman_ogm_packet = (struct batman_ogm_packet *)skb->data;
233
234 if (batman_ogm_packet->header.version != COMPAT_VERSION) {
235 bat_dbg(DBG_BATMAN, bat_priv,
236 "Drop packet: incompatible batman version (%i)\n",
237 batman_ogm_packet->header.version);
238 goto err_free;
239 }
240
241 /* all receive handlers return whether they received or reused
242 * the supplied skb. if not, we have to free the skb.
243 */
244 idx = batman_ogm_packet->header.packet_type;
245 ret = (*recv_packet_handler[idx])(skb, hard_iface);
246
247 if (ret == NET_RX_DROP)
248 kfree_skb(skb);
249
250 /* return NET_RX_SUCCESS in any case as we
251 * most probably dropped the packet for
252 * routing-logical reasons.
253 */
254 return NET_RX_SUCCESS;
255
256err_free:
257 kfree_skb(skb);
258err_out:
259 return NET_RX_DROP;
260}
261
262static void recv_handler_init(void)
263{
264 int i;
265
266 for (i = 0; i < ARRAY_SIZE(recv_packet_handler); i++)
267 recv_packet_handler[i] = recv_unhandled_packet;
268
269 /* batman icmp packet */
270 recv_packet_handler[BAT_ICMP] = recv_icmp_packet;
271 /* unicast packet */
272 recv_packet_handler[BAT_UNICAST] = recv_unicast_packet;
273 /* fragmented unicast packet */
274 recv_packet_handler[BAT_UNICAST_FRAG] = recv_ucast_frag_packet;
275 /* broadcast packet */
276 recv_packet_handler[BAT_BCAST] = recv_bcast_packet;
277 /* vis packet */
278 recv_packet_handler[BAT_VIS] = recv_vis_packet;
279 /* Translation table query (request or response) */
280 recv_packet_handler[BAT_TT_QUERY] = recv_tt_query;
281 /* Roaming advertisement */
282 recv_packet_handler[BAT_ROAM_ADV] = recv_roam_adv;
283}
284
285int recv_handler_register(uint8_t packet_type,
286 int (*recv_handler)(struct sk_buff *,
287 struct hard_iface *))
288{
289 if (recv_packet_handler[packet_type] != &recv_unhandled_packet)
290 return -EBUSY;
291
292 recv_packet_handler[packet_type] = recv_handler;
293 return 0;
294}
295
296void recv_handler_unregister(uint8_t packet_type)
297{
298 recv_packet_handler[packet_type] = recv_unhandled_packet;
299}
300
181static struct bat_algo_ops *bat_algo_get(char *name) 301static struct bat_algo_ops *bat_algo_get(char *name)
182{ 302{
183 struct bat_algo_ops *bat_algo_ops = NULL, *bat_algo_ops_tmp; 303 struct bat_algo_ops *bat_algo_ops = NULL, *bat_algo_ops_tmp;
@@ -207,12 +327,12 @@ int bat_algo_register(struct bat_algo_ops *bat_algo_ops)
207 } 327 }
208 328
209 /* all algorithms must implement all ops (for now) */ 329 /* all algorithms must implement all ops (for now) */
210 if (!bat_algo_ops->bat_ogm_init || 330 if (!bat_algo_ops->bat_iface_enable ||
211 !bat_algo_ops->bat_ogm_init_primary || 331 !bat_algo_ops->bat_iface_disable ||
212 !bat_algo_ops->bat_ogm_update_mac || 332 !bat_algo_ops->bat_iface_update_mac ||
333 !bat_algo_ops->bat_primary_iface_set ||
213 !bat_algo_ops->bat_ogm_schedule || 334 !bat_algo_ops->bat_ogm_schedule ||
214 !bat_algo_ops->bat_ogm_emit || 335 !bat_algo_ops->bat_ogm_emit) {
215 !bat_algo_ops->bat_ogm_receive) {
216 pr_info("Routing algo '%s' does not implement required ops\n", 336 pr_info("Routing algo '%s' does not implement required ops\n",
217 bat_algo_ops->name); 337 bat_algo_ops->name);
218 goto out; 338 goto out;