blob: c4b7ae9380ef056256e7ff2e28ae494328e3969d [file] [log] [blame]
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001/*
Sven Eckelmann64afe352011-01-27 10:38:15 +01002 * Copyright (C) 2007-2011 B.A.T.M.A.N. contributors:
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00003 *
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 "routing.h"
24#include "send.h"
25#include "hash.h"
26#include "soft-interface.h"
27#include "hard-interface.h"
28#include "icmp_socket.h"
29#include "translation-table.h"
30#include "originator.h"
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +000031#include "ring_buffer.h"
32#include "vis.h"
33#include "aggregation.h"
34#include "gateway_common.h"
35#include "gateway_client.h"
36#include "unicast.h"
37
38void slide_own_bcast_window(struct batman_if *batman_if)
39{
40 struct bat_priv *bat_priv = netdev_priv(batman_if->soft_iface);
41 struct hashtable_t *hash = bat_priv->orig_hash;
Marek Lindner7aadf882011-02-18 12:28:09 +000042 struct hlist_node *node;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +000043 struct hlist_head *head;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +000044 struct orig_node *orig_node;
45 unsigned long *word;
46 int i;
47 size_t word_index;
48
49 spin_lock_bh(&bat_priv->orig_hash_lock);
50
51 for (i = 0; i < hash->size; i++) {
52 head = &hash->table[i];
53
Marek Lindnerfb778ea2011-01-19 20:01:40 +000054 rcu_read_lock();
Marek Lindner7aadf882011-02-18 12:28:09 +000055 hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) {
Marek Lindner2ae2daf2011-01-19 20:01:42 +000056 spin_lock_bh(&orig_node->ogm_cnt_lock);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +000057 word_index = batman_if->if_num * NUM_WORDS;
58 word = &(orig_node->bcast_own[word_index]);
59
60 bit_get_packet(bat_priv, word, 1, 0);
61 orig_node->bcast_own_sum[batman_if->if_num] =
62 bit_packet_count(word);
Marek Lindner2ae2daf2011-01-19 20:01:42 +000063 spin_unlock_bh(&orig_node->ogm_cnt_lock);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +000064 }
Marek Lindnerfb778ea2011-01-19 20:01:40 +000065 rcu_read_unlock();
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +000066 }
67
68 spin_unlock_bh(&bat_priv->orig_hash_lock);
69}
70
71static void update_HNA(struct bat_priv *bat_priv, struct orig_node *orig_node,
72 unsigned char *hna_buff, int hna_buff_len)
73{
74 if ((hna_buff_len != orig_node->hna_buff_len) ||
75 ((hna_buff_len > 0) &&
76 (orig_node->hna_buff_len > 0) &&
77 (memcmp(orig_node->hna_buff, hna_buff, hna_buff_len) != 0))) {
78
79 if (orig_node->hna_buff_len > 0)
80 hna_global_del_orig(bat_priv, orig_node,
81 "originator changed hna");
82
83 if ((hna_buff_len > 0) && (hna_buff))
84 hna_global_add_orig(bat_priv, orig_node,
85 hna_buff, hna_buff_len);
86 }
87}
88
89static void update_route(struct bat_priv *bat_priv,
90 struct orig_node *orig_node,
91 struct neigh_node *neigh_node,
92 unsigned char *hna_buff, int hna_buff_len)
93{
Marek Lindnera8e7f4b2010-12-12 21:57:10 +000094 struct neigh_node *neigh_node_tmp;
95
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +000096 /* route deleted */
97 if ((orig_node->router) && (!neigh_node)) {
98
99 bat_dbg(DBG_ROUTES, bat_priv, "Deleting route towards: %pM\n",
100 orig_node->orig);
101 hna_global_del_orig(bat_priv, orig_node,
102 "originator timed out");
103
104 /* route added */
105 } else if ((!orig_node->router) && (neigh_node)) {
106
107 bat_dbg(DBG_ROUTES, bat_priv,
108 "Adding route towards: %pM (via %pM)\n",
109 orig_node->orig, neigh_node->addr);
110 hna_global_add_orig(bat_priv, orig_node,
111 hna_buff, hna_buff_len);
112
113 /* route changed */
114 } else {
115 bat_dbg(DBG_ROUTES, bat_priv,
116 "Changing route towards: %pM "
117 "(now via %pM - was via %pM)\n",
118 orig_node->orig, neigh_node->addr,
119 orig_node->router->addr);
120 }
121
Marek Lindner44524fc2011-02-10 14:33:53 +0000122 if (neigh_node && !atomic_inc_not_zero(&neigh_node->refcount))
123 neigh_node = NULL;
Marek Lindnera8e7f4b2010-12-12 21:57:10 +0000124 neigh_node_tmp = orig_node->router;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000125 orig_node->router = neigh_node;
Marek Lindnera8e7f4b2010-12-12 21:57:10 +0000126 if (neigh_node_tmp)
Marek Lindner44524fc2011-02-10 14:33:53 +0000127 neigh_node_free_ref(neigh_node_tmp);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000128}
129
130
131void update_routes(struct bat_priv *bat_priv, struct orig_node *orig_node,
132 struct neigh_node *neigh_node, unsigned char *hna_buff,
133 int hna_buff_len)
134{
135
136 if (!orig_node)
137 return;
138
139 if (orig_node->router != neigh_node)
140 update_route(bat_priv, orig_node, neigh_node,
141 hna_buff, hna_buff_len);
142 /* may be just HNA changed */
143 else
144 update_HNA(bat_priv, orig_node, hna_buff, hna_buff_len);
145}
146
147static int is_bidirectional_neigh(struct orig_node *orig_node,
148 struct orig_node *orig_neigh_node,
149 struct batman_packet *batman_packet,
150 struct batman_if *if_incoming)
151{
152 struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
Marek Lindner1605d0d2011-02-18 12:28:11 +0000153 struct neigh_node *neigh_node = NULL, *tmp_neigh_node;
Marek Lindner9591a792010-12-12 21:57:11 +0000154 struct hlist_node *node;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000155 unsigned char total_count;
Marek Lindner0ede9f42011-01-25 21:52:10 +0000156 uint8_t orig_eq_count, neigh_rq_count, tq_own;
157 int tq_asym_penalty, ret = 0;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000158
159 if (orig_node == orig_neigh_node) {
Marek Lindnerf987ed62010-12-12 21:57:12 +0000160 rcu_read_lock();
161 hlist_for_each_entry_rcu(tmp_neigh_node, node,
162 &orig_node->neigh_list, list) {
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000163
Marek Lindner1605d0d2011-02-18 12:28:11 +0000164 if (!compare_eth(tmp_neigh_node->addr,
165 orig_neigh_node->orig))
166 continue;
167
168 if (tmp_neigh_node->if_incoming != if_incoming)
169 continue;
170
171 if (!atomic_inc_not_zero(&tmp_neigh_node->refcount))
172 continue;
173
174 neigh_node = tmp_neigh_node;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000175 }
Marek Lindner1605d0d2011-02-18 12:28:11 +0000176 rcu_read_unlock();
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000177
178 if (!neigh_node)
179 neigh_node = create_neighbor(orig_node,
180 orig_neigh_node,
181 orig_neigh_node->orig,
182 if_incoming);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000183 if (!neigh_node)
Marek Lindner1605d0d2011-02-18 12:28:11 +0000184 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000185
186 neigh_node->last_valid = jiffies;
187 } else {
188 /* find packet count of corresponding one hop neighbor */
Marek Lindnerf987ed62010-12-12 21:57:12 +0000189 rcu_read_lock();
190 hlist_for_each_entry_rcu(tmp_neigh_node, node,
191 &orig_neigh_node->neigh_list, list) {
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000192
Marek Lindner1605d0d2011-02-18 12:28:11 +0000193 if (!compare_eth(tmp_neigh_node->addr,
194 orig_neigh_node->orig))
195 continue;
196
197 if (tmp_neigh_node->if_incoming != if_incoming)
198 continue;
199
200 if (!atomic_inc_not_zero(&tmp_neigh_node->refcount))
201 continue;
202
203 neigh_node = tmp_neigh_node;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000204 }
Marek Lindner1605d0d2011-02-18 12:28:11 +0000205 rcu_read_unlock();
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000206
207 if (!neigh_node)
208 neigh_node = create_neighbor(orig_neigh_node,
209 orig_neigh_node,
210 orig_neigh_node->orig,
211 if_incoming);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000212 if (!neigh_node)
Marek Lindner1605d0d2011-02-18 12:28:11 +0000213 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000214 }
215
216 orig_node->last_valid = jiffies;
217
Marek Lindner0ede9f42011-01-25 21:52:10 +0000218 spin_lock_bh(&orig_node->ogm_cnt_lock);
219 orig_eq_count = orig_neigh_node->bcast_own_sum[if_incoming->if_num];
220 neigh_rq_count = neigh_node->real_packet_count;
221 spin_unlock_bh(&orig_node->ogm_cnt_lock);
222
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000223 /* pay attention to not get a value bigger than 100 % */
Marek Lindner0ede9f42011-01-25 21:52:10 +0000224 total_count = (orig_eq_count > neigh_rq_count ?
225 neigh_rq_count : orig_eq_count);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000226
227 /* if we have too few packets (too less data) we set tq_own to zero */
228 /* if we receive too few packets it is not considered bidirectional */
229 if ((total_count < TQ_LOCAL_BIDRECT_SEND_MINIMUM) ||
Marek Lindner0ede9f42011-01-25 21:52:10 +0000230 (neigh_rq_count < TQ_LOCAL_BIDRECT_RECV_MINIMUM))
231 tq_own = 0;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000232 else
233 /* neigh_node->real_packet_count is never zero as we
234 * only purge old information when getting new
235 * information */
Marek Lindner0ede9f42011-01-25 21:52:10 +0000236 tq_own = (TQ_MAX_VALUE * total_count) / neigh_rq_count;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000237
238 /*
239 * 1 - ((1-x) ** 3), normalized to TQ_MAX_VALUE this does
240 * affect the nearly-symmetric links only a little, but
241 * punishes asymmetric links more. This will give a value
242 * between 0 and TQ_MAX_VALUE
243 */
Marek Lindner0ede9f42011-01-25 21:52:10 +0000244 tq_asym_penalty = TQ_MAX_VALUE - (TQ_MAX_VALUE *
245 (TQ_LOCAL_WINDOW_SIZE - neigh_rq_count) *
246 (TQ_LOCAL_WINDOW_SIZE - neigh_rq_count) *
247 (TQ_LOCAL_WINDOW_SIZE - neigh_rq_count)) /
248 (TQ_LOCAL_WINDOW_SIZE *
249 TQ_LOCAL_WINDOW_SIZE *
250 TQ_LOCAL_WINDOW_SIZE);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000251
Marek Lindner0ede9f42011-01-25 21:52:10 +0000252 batman_packet->tq = ((batman_packet->tq * tq_own * tq_asym_penalty) /
253 (TQ_MAX_VALUE * TQ_MAX_VALUE));
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000254
255 bat_dbg(DBG_BATMAN, bat_priv,
256 "bidirectional: "
257 "orig = %-15pM neigh = %-15pM => own_bcast = %2i, "
258 "real recv = %2i, local tq: %3i, asym_penalty: %3i, "
259 "total tq: %3i\n",
260 orig_node->orig, orig_neigh_node->orig, total_count,
Marek Lindner0ede9f42011-01-25 21:52:10 +0000261 neigh_rq_count, tq_own, tq_asym_penalty, batman_packet->tq);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000262
263 /* if link has the minimum required transmission quality
264 * consider it bidirectional */
265 if (batman_packet->tq >= TQ_TOTAL_BIDRECT_LIMIT)
Marek Lindnera775eb82011-01-19 20:01:39 +0000266 ret = 1;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000267
Marek Lindnera775eb82011-01-19 20:01:39 +0000268out:
269 if (neigh_node)
Marek Lindner44524fc2011-02-10 14:33:53 +0000270 neigh_node_free_ref(neigh_node);
Marek Lindnera775eb82011-01-19 20:01:39 +0000271 return ret;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000272}
273
Simon Wunderlicha4c135c2011-01-19 20:01:43 +0000274/* caller must hold the neigh_list_lock */
275void bonding_candidate_del(struct orig_node *orig_node,
276 struct neigh_node *neigh_node)
277{
278 /* this neighbor is not part of our candidate list */
279 if (list_empty(&neigh_node->bonding_list))
280 goto out;
281
282 list_del_rcu(&neigh_node->bonding_list);
Simon Wunderlicha4c135c2011-01-19 20:01:43 +0000283 INIT_LIST_HEAD(&neigh_node->bonding_list);
Marek Lindner44524fc2011-02-10 14:33:53 +0000284 neigh_node_free_ref(neigh_node);
Simon Wunderlicha4c135c2011-01-19 20:01:43 +0000285 atomic_dec(&orig_node->bond_candidates);
286
287out:
288 return;
289}
290
291static void bonding_candidate_add(struct orig_node *orig_node,
292 struct neigh_node *neigh_node)
293{
294 struct hlist_node *node;
295 struct neigh_node *tmp_neigh_node;
296 uint8_t best_tq, interference_candidate = 0;
297
298 spin_lock_bh(&orig_node->neigh_list_lock);
299
300 /* only consider if it has the same primary address ... */
Marek Lindner39901e72011-02-18 12:28:08 +0000301 if (!compare_eth(orig_node->orig,
302 neigh_node->orig_node->primary_addr))
Simon Wunderlicha4c135c2011-01-19 20:01:43 +0000303 goto candidate_del;
304
305 if (!orig_node->router)
306 goto candidate_del;
307
308 best_tq = orig_node->router->tq_avg;
309
310 /* ... and is good enough to be considered */
311 if (neigh_node->tq_avg < best_tq - BONDING_TQ_THRESHOLD)
312 goto candidate_del;
313
314 /**
315 * check if we have another candidate with the same mac address or
316 * interface. If we do, we won't select this candidate because of
317 * possible interference.
318 */
319 hlist_for_each_entry_rcu(tmp_neigh_node, node,
320 &orig_node->neigh_list, list) {
321
322 if (tmp_neigh_node == neigh_node)
323 continue;
324
325 /* we only care if the other candidate is even
326 * considered as candidate. */
327 if (list_empty(&tmp_neigh_node->bonding_list))
328 continue;
329
330 if ((neigh_node->if_incoming == tmp_neigh_node->if_incoming) ||
Marek Lindner39901e72011-02-18 12:28:08 +0000331 (compare_eth(neigh_node->addr, tmp_neigh_node->addr))) {
Simon Wunderlicha4c135c2011-01-19 20:01:43 +0000332 interference_candidate = 1;
333 break;
334 }
335 }
336
337 /* don't care further if it is an interference candidate */
338 if (interference_candidate)
339 goto candidate_del;
340
341 /* this neighbor already is part of our candidate list */
342 if (!list_empty(&neigh_node->bonding_list))
343 goto out;
344
Marek Lindner44524fc2011-02-10 14:33:53 +0000345 if (!atomic_inc_not_zero(&neigh_node->refcount))
346 goto out;
347
Simon Wunderlicha4c135c2011-01-19 20:01:43 +0000348 list_add_rcu(&neigh_node->bonding_list, &orig_node->bond_list);
Simon Wunderlicha4c135c2011-01-19 20:01:43 +0000349 atomic_inc(&orig_node->bond_candidates);
350 goto out;
351
352candidate_del:
353 bonding_candidate_del(orig_node, neigh_node);
354
355out:
356 spin_unlock_bh(&orig_node->neigh_list_lock);
357 return;
358}
359
360/* copy primary address for bonding */
361static void bonding_save_primary(struct orig_node *orig_node,
362 struct orig_node *orig_neigh_node,
363 struct batman_packet *batman_packet)
364{
365 if (!(batman_packet->flags & PRIMARIES_FIRST_HOP))
366 return;
367
368 memcpy(orig_neigh_node->primary_addr, orig_node->orig, ETH_ALEN);
369}
370
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000371static void update_orig(struct bat_priv *bat_priv,
372 struct orig_node *orig_node,
373 struct ethhdr *ethhdr,
374 struct batman_packet *batman_packet,
375 struct batman_if *if_incoming,
376 unsigned char *hna_buff, int hna_buff_len,
377 char is_duplicate)
378{
379 struct neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL;
Marek Lindner2ae2daf2011-01-19 20:01:42 +0000380 struct orig_node *orig_node_tmp;
Marek Lindner9591a792010-12-12 21:57:11 +0000381 struct hlist_node *node;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000382 int tmp_hna_buff_len;
Marek Lindner2ae2daf2011-01-19 20:01:42 +0000383 uint8_t bcast_own_sum_orig, bcast_own_sum_neigh;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000384
385 bat_dbg(DBG_BATMAN, bat_priv, "update_originator(): "
386 "Searching and updating originator entry of received packet\n");
387
Marek Lindnerf987ed62010-12-12 21:57:12 +0000388 rcu_read_lock();
389 hlist_for_each_entry_rcu(tmp_neigh_node, node,
390 &orig_node->neigh_list, list) {
Marek Lindner39901e72011-02-18 12:28:08 +0000391 if (compare_eth(tmp_neigh_node->addr, ethhdr->h_source) &&
Marek Lindner44524fc2011-02-10 14:33:53 +0000392 (tmp_neigh_node->if_incoming == if_incoming) &&
393 atomic_inc_not_zero(&tmp_neigh_node->refcount)) {
394 if (neigh_node)
395 neigh_node_free_ref(neigh_node);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000396 neigh_node = tmp_neigh_node;
397 continue;
398 }
399
400 if (is_duplicate)
401 continue;
402
403 ring_buffer_set(tmp_neigh_node->tq_recv,
404 &tmp_neigh_node->tq_index, 0);
405 tmp_neigh_node->tq_avg =
406 ring_buffer_avg(tmp_neigh_node->tq_recv);
407 }
408
409 if (!neigh_node) {
410 struct orig_node *orig_tmp;
411
412 orig_tmp = get_orig_node(bat_priv, ethhdr->h_source);
413 if (!orig_tmp)
Marek Lindnera775eb82011-01-19 20:01:39 +0000414 goto unlock;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000415
416 neigh_node = create_neighbor(orig_node, orig_tmp,
417 ethhdr->h_source, if_incoming);
Marek Lindner16b1aba2011-01-19 20:01:42 +0000418
Marek Lindner7b36e8e2011-02-18 12:28:10 +0000419 orig_node_free_ref(orig_tmp);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000420 if (!neigh_node)
Marek Lindnera775eb82011-01-19 20:01:39 +0000421 goto unlock;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000422 } else
423 bat_dbg(DBG_BATMAN, bat_priv,
424 "Updating existing last-hop neighbor of originator\n");
425
Marek Lindnera775eb82011-01-19 20:01:39 +0000426 rcu_read_unlock();
427
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000428 orig_node->flags = batman_packet->flags;
429 neigh_node->last_valid = jiffies;
430
431 ring_buffer_set(neigh_node->tq_recv,
432 &neigh_node->tq_index,
433 batman_packet->tq);
434 neigh_node->tq_avg = ring_buffer_avg(neigh_node->tq_recv);
435
436 if (!is_duplicate) {
437 orig_node->last_ttl = batman_packet->ttl;
438 neigh_node->last_ttl = batman_packet->ttl;
439 }
440
Simon Wunderlicha4c135c2011-01-19 20:01:43 +0000441 bonding_candidate_add(orig_node, neigh_node);
442
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000443 tmp_hna_buff_len = (hna_buff_len > batman_packet->num_hna * ETH_ALEN ?
444 batman_packet->num_hna * ETH_ALEN : hna_buff_len);
445
446 /* if this neighbor already is our next hop there is nothing
447 * to change */
448 if (orig_node->router == neigh_node)
449 goto update_hna;
450
451 /* if this neighbor does not offer a better TQ we won't consider it */
452 if ((orig_node->router) &&
453 (orig_node->router->tq_avg > neigh_node->tq_avg))
454 goto update_hna;
455
456 /* if the TQ is the same and the link not more symetric we
457 * won't consider it either */
458 if ((orig_node->router) &&
Marek Lindner2ae2daf2011-01-19 20:01:42 +0000459 (neigh_node->tq_avg == orig_node->router->tq_avg)) {
460 orig_node_tmp = orig_node->router->orig_node;
461 spin_lock_bh(&orig_node_tmp->ogm_cnt_lock);
462 bcast_own_sum_orig =
463 orig_node_tmp->bcast_own_sum[if_incoming->if_num];
464 spin_unlock_bh(&orig_node_tmp->ogm_cnt_lock);
465
466 orig_node_tmp = neigh_node->orig_node;
467 spin_lock_bh(&orig_node_tmp->ogm_cnt_lock);
468 bcast_own_sum_neigh =
469 orig_node_tmp->bcast_own_sum[if_incoming->if_num];
470 spin_unlock_bh(&orig_node_tmp->ogm_cnt_lock);
471
472 if (bcast_own_sum_orig >= bcast_own_sum_neigh)
473 goto update_hna;
474 }
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000475
476 update_routes(bat_priv, orig_node, neigh_node,
477 hna_buff, tmp_hna_buff_len);
478 goto update_gw;
479
480update_hna:
481 update_routes(bat_priv, orig_node, orig_node->router,
482 hna_buff, tmp_hna_buff_len);
483
484update_gw:
485 if (orig_node->gw_flags != batman_packet->gw_flags)
486 gw_node_update(bat_priv, orig_node, batman_packet->gw_flags);
487
488 orig_node->gw_flags = batman_packet->gw_flags;
489
490 /* restart gateway selection if fast or late switching was enabled */
491 if ((orig_node->gw_flags) &&
492 (atomic_read(&bat_priv->gw_mode) == GW_MODE_CLIENT) &&
493 (atomic_read(&bat_priv->gw_sel_class) > 2))
494 gw_check_election(bat_priv, orig_node);
Marek Lindnera775eb82011-01-19 20:01:39 +0000495
496 goto out;
497
498unlock:
499 rcu_read_unlock();
500out:
501 if (neigh_node)
Marek Lindner44524fc2011-02-10 14:33:53 +0000502 neigh_node_free_ref(neigh_node);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000503}
504
505/* checks whether the host restarted and is in the protection time.
506 * returns:
507 * 0 if the packet is to be accepted
508 * 1 if the packet is to be ignored.
509 */
510static int window_protected(struct bat_priv *bat_priv,
511 int32_t seq_num_diff,
512 unsigned long *last_reset)
513{
514 if ((seq_num_diff <= -TQ_LOCAL_WINDOW_SIZE)
515 || (seq_num_diff >= EXPECTED_SEQNO_RANGE)) {
516 if (time_after(jiffies, *last_reset +
517 msecs_to_jiffies(RESET_PROTECTION_MS))) {
518
519 *last_reset = jiffies;
520 bat_dbg(DBG_BATMAN, bat_priv,
521 "old packet received, start protection\n");
522
523 return 0;
524 } else
525 return 1;
526 }
527 return 0;
528}
529
530/* processes a batman packet for all interfaces, adjusts the sequence number and
531 * finds out whether it is a duplicate.
532 * returns:
533 * 1 the packet is a duplicate
534 * 0 the packet has not yet been received
535 * -1 the packet is old and has been received while the seqno window
536 * was protected. Caller should drop it.
537 */
538static char count_real_packets(struct ethhdr *ethhdr,
539 struct batman_packet *batman_packet,
540 struct batman_if *if_incoming)
541{
542 struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
543 struct orig_node *orig_node;
544 struct neigh_node *tmp_neigh_node;
Marek Lindner9591a792010-12-12 21:57:11 +0000545 struct hlist_node *node;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000546 char is_duplicate = 0;
547 int32_t seq_diff;
548 int need_update = 0;
Marek Lindner0ede9f42011-01-25 21:52:10 +0000549 int set_mark, ret = -1;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000550
551 orig_node = get_orig_node(bat_priv, batman_packet->orig);
552 if (!orig_node)
553 return 0;
554
Marek Lindner0ede9f42011-01-25 21:52:10 +0000555 spin_lock_bh(&orig_node->ogm_cnt_lock);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000556 seq_diff = batman_packet->seqno - orig_node->last_real_seqno;
557
558 /* signalize caller that the packet is to be dropped. */
559 if (window_protected(bat_priv, seq_diff,
560 &orig_node->batman_seqno_reset))
Marek Lindner0ede9f42011-01-25 21:52:10 +0000561 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000562
Marek Lindnerf987ed62010-12-12 21:57:12 +0000563 rcu_read_lock();
564 hlist_for_each_entry_rcu(tmp_neigh_node, node,
565 &orig_node->neigh_list, list) {
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000566
567 is_duplicate |= get_bit_status(tmp_neigh_node->real_bits,
568 orig_node->last_real_seqno,
569 batman_packet->seqno);
570
Marek Lindner39901e72011-02-18 12:28:08 +0000571 if (compare_eth(tmp_neigh_node->addr, ethhdr->h_source) &&
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000572 (tmp_neigh_node->if_incoming == if_incoming))
573 set_mark = 1;
574 else
575 set_mark = 0;
576
577 /* if the window moved, set the update flag. */
578 need_update |= bit_get_packet(bat_priv,
579 tmp_neigh_node->real_bits,
580 seq_diff, set_mark);
581
582 tmp_neigh_node->real_packet_count =
583 bit_packet_count(tmp_neigh_node->real_bits);
584 }
Marek Lindnerf987ed62010-12-12 21:57:12 +0000585 rcu_read_unlock();
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000586
587 if (need_update) {
588 bat_dbg(DBG_BATMAN, bat_priv,
589 "updating last_seqno: old %d, new %d\n",
590 orig_node->last_real_seqno, batman_packet->seqno);
591 orig_node->last_real_seqno = batman_packet->seqno;
592 }
593
Marek Lindner0ede9f42011-01-25 21:52:10 +0000594 ret = is_duplicate;
Marek Lindner16b1aba2011-01-19 20:01:42 +0000595
Marek Lindner0ede9f42011-01-25 21:52:10 +0000596out:
597 spin_unlock_bh(&orig_node->ogm_cnt_lock);
Marek Lindner7b36e8e2011-02-18 12:28:10 +0000598 orig_node_free_ref(orig_node);
Marek Lindner0ede9f42011-01-25 21:52:10 +0000599 return ret;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000600}
601
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000602void receive_bat_packet(struct ethhdr *ethhdr,
Simon Wunderlicha4c135c2011-01-19 20:01:43 +0000603 struct batman_packet *batman_packet,
604 unsigned char *hna_buff, int hna_buff_len,
605 struct batman_if *if_incoming)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000606{
607 struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
608 struct batman_if *batman_if;
609 struct orig_node *orig_neigh_node, *orig_node;
610 char has_directlink_flag;
611 char is_my_addr = 0, is_my_orig = 0, is_my_oldorig = 0;
612 char is_broadcast = 0, is_bidirectional, is_single_hop_neigh;
613 char is_duplicate;
614 uint32_t if_incoming_seqno;
615
616 /* Silently drop when the batman packet is actually not a
617 * correct packet.
618 *
619 * This might happen if a packet is padded (e.g. Ethernet has a
620 * minimum frame length of 64 byte) and the aggregation interprets
621 * it as an additional length.
622 *
623 * TODO: A more sane solution would be to have a bit in the
624 * batman_packet to detect whether the packet is the last
625 * packet in an aggregation. Here we expect that the padding
626 * is always zero (or not 0x01)
627 */
628 if (batman_packet->packet_type != BAT_PACKET)
629 return;
630
631 /* could be changed by schedule_own_packet() */
632 if_incoming_seqno = atomic_read(&if_incoming->seqno);
633
634 has_directlink_flag = (batman_packet->flags & DIRECTLINK ? 1 : 0);
635
Marek Lindner39901e72011-02-18 12:28:08 +0000636 is_single_hop_neigh = (compare_eth(ethhdr->h_source,
637 batman_packet->orig) ? 1 : 0);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000638
639 bat_dbg(DBG_BATMAN, bat_priv,
640 "Received BATMAN packet via NB: %pM, IF: %s [%pM] "
641 "(from OG: %pM, via prev OG: %pM, seqno %d, tq %d, "
642 "TTL %d, V %d, IDF %d)\n",
643 ethhdr->h_source, if_incoming->net_dev->name,
644 if_incoming->net_dev->dev_addr, batman_packet->orig,
645 batman_packet->prev_sender, batman_packet->seqno,
646 batman_packet->tq, batman_packet->ttl, batman_packet->version,
647 has_directlink_flag);
648
649 rcu_read_lock();
650 list_for_each_entry_rcu(batman_if, &if_list, list) {
651 if (batman_if->if_status != IF_ACTIVE)
652 continue;
653
654 if (batman_if->soft_iface != if_incoming->soft_iface)
655 continue;
656
Marek Lindner39901e72011-02-18 12:28:08 +0000657 if (compare_eth(ethhdr->h_source,
658 batman_if->net_dev->dev_addr))
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000659 is_my_addr = 1;
660
Marek Lindner39901e72011-02-18 12:28:08 +0000661 if (compare_eth(batman_packet->orig,
662 batman_if->net_dev->dev_addr))
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000663 is_my_orig = 1;
664
Marek Lindner39901e72011-02-18 12:28:08 +0000665 if (compare_eth(batman_packet->prev_sender,
666 batman_if->net_dev->dev_addr))
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000667 is_my_oldorig = 1;
668
Marek Lindner39901e72011-02-18 12:28:08 +0000669 if (compare_eth(ethhdr->h_source, broadcast_addr))
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000670 is_broadcast = 1;
671 }
672 rcu_read_unlock();
673
674 if (batman_packet->version != COMPAT_VERSION) {
675 bat_dbg(DBG_BATMAN, bat_priv,
676 "Drop packet: incompatible batman version (%i)\n",
677 batman_packet->version);
678 return;
679 }
680
681 if (is_my_addr) {
682 bat_dbg(DBG_BATMAN, bat_priv,
683 "Drop packet: received my own broadcast (sender: %pM"
684 ")\n",
685 ethhdr->h_source);
686 return;
687 }
688
689 if (is_broadcast) {
690 bat_dbg(DBG_BATMAN, bat_priv, "Drop packet: "
691 "ignoring all packets with broadcast source addr (sender: %pM"
692 ")\n", ethhdr->h_source);
693 return;
694 }
695
696 if (is_my_orig) {
697 unsigned long *word;
698 int offset;
699
700 orig_neigh_node = get_orig_node(bat_priv, ethhdr->h_source);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000701 if (!orig_neigh_node)
702 return;
703
704 /* neighbor has to indicate direct link and it has to
705 * come via the corresponding interface */
706 /* if received seqno equals last send seqno save new
707 * seqno for bidirectional check */
708 if (has_directlink_flag &&
Marek Lindner39901e72011-02-18 12:28:08 +0000709 compare_eth(if_incoming->net_dev->dev_addr,
710 batman_packet->orig) &&
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000711 (batman_packet->seqno - if_incoming_seqno + 2 == 0)) {
712 offset = if_incoming->if_num * NUM_WORDS;
Marek Lindner2ae2daf2011-01-19 20:01:42 +0000713
714 spin_lock_bh(&orig_neigh_node->ogm_cnt_lock);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000715 word = &(orig_neigh_node->bcast_own[offset]);
716 bit_mark(word, 0);
717 orig_neigh_node->bcast_own_sum[if_incoming->if_num] =
718 bit_packet_count(word);
Marek Lindner2ae2daf2011-01-19 20:01:42 +0000719 spin_unlock_bh(&orig_neigh_node->ogm_cnt_lock);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000720 }
721
722 bat_dbg(DBG_BATMAN, bat_priv, "Drop packet: "
723 "originator packet from myself (via neighbor)\n");
Marek Lindner7b36e8e2011-02-18 12:28:10 +0000724 orig_node_free_ref(orig_neigh_node);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000725 return;
726 }
727
728 if (is_my_oldorig) {
729 bat_dbg(DBG_BATMAN, bat_priv,
730 "Drop packet: ignoring all rebroadcast echos (sender: "
731 "%pM)\n", ethhdr->h_source);
732 return;
733 }
734
735 orig_node = get_orig_node(bat_priv, batman_packet->orig);
736 if (!orig_node)
737 return;
738
739 is_duplicate = count_real_packets(ethhdr, batman_packet, if_incoming);
740
741 if (is_duplicate == -1) {
742 bat_dbg(DBG_BATMAN, bat_priv,
743 "Drop packet: packet within seqno protection time "
744 "(sender: %pM)\n", ethhdr->h_source);
Marek Lindner16b1aba2011-01-19 20:01:42 +0000745 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000746 }
747
748 if (batman_packet->tq == 0) {
749 bat_dbg(DBG_BATMAN, bat_priv,
750 "Drop packet: originator packet with tq equal 0\n");
Marek Lindner16b1aba2011-01-19 20:01:42 +0000751 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000752 }
753
754 /* avoid temporary routing loops */
755 if ((orig_node->router) &&
756 (orig_node->router->orig_node->router) &&
Marek Lindner39901e72011-02-18 12:28:08 +0000757 (compare_eth(orig_node->router->addr,
758 batman_packet->prev_sender)) &&
759 !(compare_eth(batman_packet->orig, batman_packet->prev_sender)) &&
760 (compare_eth(orig_node->router->addr,
761 orig_node->router->orig_node->router->addr))) {
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000762 bat_dbg(DBG_BATMAN, bat_priv,
763 "Drop packet: ignoring all rebroadcast packets that "
764 "may make me loop (sender: %pM)\n", ethhdr->h_source);
Marek Lindner16b1aba2011-01-19 20:01:42 +0000765 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000766 }
767
768 /* if sender is a direct neighbor the sender mac equals
769 * originator mac */
770 orig_neigh_node = (is_single_hop_neigh ?
771 orig_node :
772 get_orig_node(bat_priv, ethhdr->h_source));
773 if (!orig_neigh_node)
Marek Lindner16b1aba2011-01-19 20:01:42 +0000774 goto out_neigh;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000775
776 /* drop packet if sender is not a direct neighbor and if we
777 * don't route towards it */
778 if (!is_single_hop_neigh && (!orig_neigh_node->router)) {
779 bat_dbg(DBG_BATMAN, bat_priv,
780 "Drop packet: OGM via unknown neighbor!\n");
Marek Lindner16b1aba2011-01-19 20:01:42 +0000781 goto out_neigh;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000782 }
783
784 is_bidirectional = is_bidirectional_neigh(orig_node, orig_neigh_node,
785 batman_packet, if_incoming);
786
Simon Wunderlicha4c135c2011-01-19 20:01:43 +0000787 bonding_save_primary(orig_node, orig_neigh_node, batman_packet);
788
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000789 /* update ranking if it is not a duplicate or has the same
790 * seqno and similar ttl as the non-duplicate */
791 if (is_bidirectional &&
792 (!is_duplicate ||
793 ((orig_node->last_real_seqno == batman_packet->seqno) &&
794 (orig_node->last_ttl - 3 <= batman_packet->ttl))))
795 update_orig(bat_priv, orig_node, ethhdr, batman_packet,
796 if_incoming, hna_buff, hna_buff_len, is_duplicate);
797
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000798 /* is single hop (direct) neighbor */
799 if (is_single_hop_neigh) {
800
801 /* mark direct link on incoming interface */
802 schedule_forward_packet(orig_node, ethhdr, batman_packet,
803 1, hna_buff_len, if_incoming);
804
805 bat_dbg(DBG_BATMAN, bat_priv, "Forwarding packet: "
806 "rebroadcast neighbor packet with direct link flag\n");
Marek Lindner16b1aba2011-01-19 20:01:42 +0000807 goto out_neigh;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000808 }
809
810 /* multihop originator */
811 if (!is_bidirectional) {
812 bat_dbg(DBG_BATMAN, bat_priv,
813 "Drop packet: not received via bidirectional link\n");
Marek Lindner16b1aba2011-01-19 20:01:42 +0000814 goto out_neigh;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000815 }
816
817 if (is_duplicate) {
818 bat_dbg(DBG_BATMAN, bat_priv,
819 "Drop packet: duplicate packet received\n");
Marek Lindner16b1aba2011-01-19 20:01:42 +0000820 goto out_neigh;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000821 }
822
823 bat_dbg(DBG_BATMAN, bat_priv,
824 "Forwarding packet: rebroadcast originator packet\n");
825 schedule_forward_packet(orig_node, ethhdr, batman_packet,
826 0, hna_buff_len, if_incoming);
Marek Lindner16b1aba2011-01-19 20:01:42 +0000827
828out_neigh:
Marek Lindner7b36e8e2011-02-18 12:28:10 +0000829 if ((orig_neigh_node) && (!is_single_hop_neigh))
830 orig_node_free_ref(orig_neigh_node);
Marek Lindner16b1aba2011-01-19 20:01:42 +0000831out:
Marek Lindner7b36e8e2011-02-18 12:28:10 +0000832 orig_node_free_ref(orig_node);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000833}
834
835int recv_bat_packet(struct sk_buff *skb, struct batman_if *batman_if)
836{
837 struct bat_priv *bat_priv = netdev_priv(batman_if->soft_iface);
838 struct ethhdr *ethhdr;
839
840 /* drop packet if it has not necessary minimum size */
841 if (unlikely(!pskb_may_pull(skb, sizeof(struct batman_packet))))
842 return NET_RX_DROP;
843
844 ethhdr = (struct ethhdr *)skb_mac_header(skb);
845
846 /* packet with broadcast indication but unicast recipient */
847 if (!is_broadcast_ether_addr(ethhdr->h_dest))
848 return NET_RX_DROP;
849
850 /* packet with broadcast sender address */
851 if (is_broadcast_ether_addr(ethhdr->h_source))
852 return NET_RX_DROP;
853
854 /* create a copy of the skb, if needed, to modify it. */
855 if (skb_cow(skb, 0) < 0)
856 return NET_RX_DROP;
857
858 /* keep skb linear */
859 if (skb_linearize(skb) < 0)
860 return NET_RX_DROP;
861
862 ethhdr = (struct ethhdr *)skb_mac_header(skb);
863
864 spin_lock_bh(&bat_priv->orig_hash_lock);
865 receive_aggr_bat_packet(ethhdr,
866 skb->data,
867 skb_headlen(skb),
868 batman_if);
869 spin_unlock_bh(&bat_priv->orig_hash_lock);
870
871 kfree_skb(skb);
872 return NET_RX_SUCCESS;
873}
874
875static int recv_my_icmp_packet(struct bat_priv *bat_priv,
876 struct sk_buff *skb, size_t icmp_len)
877{
Marek Lindner44524fc2011-02-10 14:33:53 +0000878 struct orig_node *orig_node = NULL;
879 struct neigh_node *neigh_node = NULL;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000880 struct icmp_packet_rr *icmp_packet;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000881 struct batman_if *batman_if;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000882 uint8_t dstaddr[ETH_ALEN];
Marek Lindner44524fc2011-02-10 14:33:53 +0000883 int ret = NET_RX_DROP;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000884
885 icmp_packet = (struct icmp_packet_rr *)skb->data;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000886
887 /* add data to device queue */
888 if (icmp_packet->msg_type != ECHO_REQUEST) {
889 bat_socket_receive_packet(icmp_packet, icmp_len);
Marek Lindner44524fc2011-02-10 14:33:53 +0000890 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000891 }
892
893 if (!bat_priv->primary_if)
Marek Lindner44524fc2011-02-10 14:33:53 +0000894 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000895
896 /* answer echo request (ping) */
897 /* get routing information */
898 spin_lock_bh(&bat_priv->orig_hash_lock);
Marek Lindnerfb778ea2011-01-19 20:01:40 +0000899 rcu_read_lock();
Marek Lindner7aadf882011-02-18 12:28:09 +0000900 orig_node = orig_hash_find(bat_priv, icmp_packet->orig);
Marek Lindner44524fc2011-02-10 14:33:53 +0000901
902 if (!orig_node)
903 goto unlock;
904
Marek Lindner44524fc2011-02-10 14:33:53 +0000905 neigh_node = orig_node->router;
906
907 if (!neigh_node)
908 goto unlock;
909
910 if (!atomic_inc_not_zero(&neigh_node->refcount)) {
911 neigh_node = NULL;
912 goto unlock;
913 }
914
Marek Lindnerfb778ea2011-01-19 20:01:40 +0000915 rcu_read_unlock();
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000916
Marek Lindner44524fc2011-02-10 14:33:53 +0000917 /* don't lock while sending the packets ... we therefore
918 * copy the required data before sending */
919 batman_if = orig_node->router->if_incoming;
920 memcpy(dstaddr, orig_node->router->addr, ETH_ALEN);
921 spin_unlock_bh(&bat_priv->orig_hash_lock);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000922
Marek Lindner44524fc2011-02-10 14:33:53 +0000923 /* create a copy of the skb, if needed, to modify it. */
924 if (skb_cow(skb, sizeof(struct ethhdr)) < 0)
925 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000926
Marek Lindner44524fc2011-02-10 14:33:53 +0000927 icmp_packet = (struct icmp_packet_rr *)skb->data;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000928
Marek Lindner44524fc2011-02-10 14:33:53 +0000929 memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN);
930 memcpy(icmp_packet->orig,
931 bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN);
932 icmp_packet->msg_type = ECHO_REPLY;
933 icmp_packet->ttl = TTL;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000934
Marek Lindner44524fc2011-02-10 14:33:53 +0000935 send_skb_packet(skb, batman_if, dstaddr);
936 ret = NET_RX_SUCCESS;
937 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000938
Marek Lindner44524fc2011-02-10 14:33:53 +0000939unlock:
940 rcu_read_unlock();
941 spin_unlock_bh(&bat_priv->orig_hash_lock);
942out:
943 if (neigh_node)
944 neigh_node_free_ref(neigh_node);
945 if (orig_node)
Marek Lindner7b36e8e2011-02-18 12:28:10 +0000946 orig_node_free_ref(orig_node);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000947 return ret;
948}
949
950static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv,
Simon Wunderlich74ef1152010-12-29 16:15:19 +0000951 struct sk_buff *skb)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000952{
Marek Lindner44524fc2011-02-10 14:33:53 +0000953 struct orig_node *orig_node = NULL;
954 struct neigh_node *neigh_node = NULL;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000955 struct icmp_packet *icmp_packet;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000956 struct batman_if *batman_if;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000957 uint8_t dstaddr[ETH_ALEN];
Marek Lindner44524fc2011-02-10 14:33:53 +0000958 int ret = NET_RX_DROP;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000959
960 icmp_packet = (struct icmp_packet *)skb->data;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000961
962 /* send TTL exceeded if packet is an echo request (traceroute) */
963 if (icmp_packet->msg_type != ECHO_REQUEST) {
964 pr_debug("Warning - can't forward icmp packet from %pM to "
965 "%pM: ttl exceeded\n", icmp_packet->orig,
966 icmp_packet->dst);
Marek Lindner44524fc2011-02-10 14:33:53 +0000967 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000968 }
969
970 if (!bat_priv->primary_if)
Marek Lindner44524fc2011-02-10 14:33:53 +0000971 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000972
973 /* get routing information */
974 spin_lock_bh(&bat_priv->orig_hash_lock);
Marek Lindnerfb778ea2011-01-19 20:01:40 +0000975 rcu_read_lock();
Marek Lindner7aadf882011-02-18 12:28:09 +0000976 orig_node = orig_hash_find(bat_priv, icmp_packet->orig);
Marek Lindner44524fc2011-02-10 14:33:53 +0000977
978 if (!orig_node)
979 goto unlock;
980
Marek Lindner44524fc2011-02-10 14:33:53 +0000981 neigh_node = orig_node->router;
982
983 if (!neigh_node)
984 goto unlock;
985
986 if (!atomic_inc_not_zero(&neigh_node->refcount)) {
987 neigh_node = NULL;
988 goto unlock;
989 }
990
Marek Lindnerfb778ea2011-01-19 20:01:40 +0000991 rcu_read_unlock();
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000992
Marek Lindner44524fc2011-02-10 14:33:53 +0000993 /* don't lock while sending the packets ... we therefore
994 * copy the required data before sending */
995 batman_if = orig_node->router->if_incoming;
996 memcpy(dstaddr, orig_node->router->addr, ETH_ALEN);
997 spin_unlock_bh(&bat_priv->orig_hash_lock);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000998
Marek Lindner44524fc2011-02-10 14:33:53 +0000999 /* create a copy of the skb, if needed, to modify it. */
1000 if (skb_cow(skb, sizeof(struct ethhdr)) < 0)
1001 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001002
Marek Lindner44524fc2011-02-10 14:33:53 +00001003 icmp_packet = (struct icmp_packet *)skb->data;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001004
Marek Lindner44524fc2011-02-10 14:33:53 +00001005 memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN);
1006 memcpy(icmp_packet->orig,
1007 bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN);
1008 icmp_packet->msg_type = TTL_EXCEEDED;
1009 icmp_packet->ttl = TTL;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001010
Marek Lindner44524fc2011-02-10 14:33:53 +00001011 send_skb_packet(skb, batman_if, dstaddr);
1012 ret = NET_RX_SUCCESS;
1013 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001014
Marek Lindner44524fc2011-02-10 14:33:53 +00001015unlock:
1016 rcu_read_unlock();
1017 spin_unlock_bh(&bat_priv->orig_hash_lock);
1018out:
1019 if (neigh_node)
1020 neigh_node_free_ref(neigh_node);
1021 if (orig_node)
Marek Lindner7b36e8e2011-02-18 12:28:10 +00001022 orig_node_free_ref(orig_node);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001023 return ret;
1024}
1025
1026
1027int recv_icmp_packet(struct sk_buff *skb, struct batman_if *recv_if)
1028{
1029 struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface);
1030 struct icmp_packet_rr *icmp_packet;
1031 struct ethhdr *ethhdr;
Marek Lindner44524fc2011-02-10 14:33:53 +00001032 struct orig_node *orig_node = NULL;
1033 struct neigh_node *neigh_node = NULL;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001034 struct batman_if *batman_if;
1035 int hdr_size = sizeof(struct icmp_packet);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001036 uint8_t dstaddr[ETH_ALEN];
Marek Lindner44524fc2011-02-10 14:33:53 +00001037 int ret = NET_RX_DROP;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001038
1039 /**
1040 * we truncate all incoming icmp packets if they don't match our size
1041 */
1042 if (skb->len >= sizeof(struct icmp_packet_rr))
1043 hdr_size = sizeof(struct icmp_packet_rr);
1044
1045 /* drop packet if it has not necessary minimum size */
1046 if (unlikely(!pskb_may_pull(skb, hdr_size)))
Marek Lindner44524fc2011-02-10 14:33:53 +00001047 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001048
1049 ethhdr = (struct ethhdr *)skb_mac_header(skb);
1050
1051 /* packet with unicast indication but broadcast recipient */
1052 if (is_broadcast_ether_addr(ethhdr->h_dest))
Marek Lindner44524fc2011-02-10 14:33:53 +00001053 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001054
1055 /* packet with broadcast sender address */
1056 if (is_broadcast_ether_addr(ethhdr->h_source))
Marek Lindner44524fc2011-02-10 14:33:53 +00001057 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001058
1059 /* not for me */
1060 if (!is_my_mac(ethhdr->h_dest))
Marek Lindner44524fc2011-02-10 14:33:53 +00001061 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001062
1063 icmp_packet = (struct icmp_packet_rr *)skb->data;
1064
1065 /* add record route information if not full */
1066 if ((hdr_size == sizeof(struct icmp_packet_rr)) &&
1067 (icmp_packet->rr_cur < BAT_RR_LEN)) {
1068 memcpy(&(icmp_packet->rr[icmp_packet->rr_cur]),
1069 ethhdr->h_dest, ETH_ALEN);
1070 icmp_packet->rr_cur++;
1071 }
1072
1073 /* packet for me */
1074 if (is_my_mac(icmp_packet->dst))
1075 return recv_my_icmp_packet(bat_priv, skb, hdr_size);
1076
1077 /* TTL exceeded */
1078 if (icmp_packet->ttl < 2)
Simon Wunderlich74ef1152010-12-29 16:15:19 +00001079 return recv_icmp_ttl_exceeded(bat_priv, skb);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001080
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001081 /* get routing information */
1082 spin_lock_bh(&bat_priv->orig_hash_lock);
Marek Lindnerfb778ea2011-01-19 20:01:40 +00001083 rcu_read_lock();
Marek Lindner7aadf882011-02-18 12:28:09 +00001084 orig_node = orig_hash_find(bat_priv, icmp_packet->dst);
1085
Marek Lindner44524fc2011-02-10 14:33:53 +00001086 if (!orig_node)
1087 goto unlock;
1088
Marek Lindner44524fc2011-02-10 14:33:53 +00001089 neigh_node = orig_node->router;
1090
1091 if (!neigh_node)
1092 goto unlock;
1093
1094 if (!atomic_inc_not_zero(&neigh_node->refcount)) {
1095 neigh_node = NULL;
1096 goto unlock;
1097 }
1098
Marek Lindnerfb778ea2011-01-19 20:01:40 +00001099 rcu_read_unlock();
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001100
Marek Lindner44524fc2011-02-10 14:33:53 +00001101 /* don't lock while sending the packets ... we therefore
1102 * copy the required data before sending */
1103 batman_if = orig_node->router->if_incoming;
1104 memcpy(dstaddr, orig_node->router->addr, ETH_ALEN);
1105 spin_unlock_bh(&bat_priv->orig_hash_lock);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001106
Marek Lindner44524fc2011-02-10 14:33:53 +00001107 /* create a copy of the skb, if needed, to modify it. */
1108 if (skb_cow(skb, sizeof(struct ethhdr)) < 0)
1109 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001110
Marek Lindner44524fc2011-02-10 14:33:53 +00001111 icmp_packet = (struct icmp_packet_rr *)skb->data;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001112
Marek Lindner44524fc2011-02-10 14:33:53 +00001113 /* decrement ttl */
1114 icmp_packet->ttl--;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001115
Marek Lindner44524fc2011-02-10 14:33:53 +00001116 /* route it */
1117 send_skb_packet(skb, batman_if, dstaddr);
1118 ret = NET_RX_SUCCESS;
1119 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001120
Marek Lindner44524fc2011-02-10 14:33:53 +00001121unlock:
1122 rcu_read_unlock();
1123 spin_unlock_bh(&bat_priv->orig_hash_lock);
1124out:
1125 if (neigh_node)
1126 neigh_node_free_ref(neigh_node);
1127 if (orig_node)
Marek Lindner7b36e8e2011-02-18 12:28:10 +00001128 orig_node_free_ref(orig_node);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001129 return ret;
1130}
1131
1132/* find a suitable router for this originator, and use
Simon Wunderlicha4c135c2011-01-19 20:01:43 +00001133 * bonding if possible. increases the found neighbors
1134 * refcount.*/
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001135struct neigh_node *find_router(struct bat_priv *bat_priv,
1136 struct orig_node *orig_node,
1137 struct batman_if *recv_if)
1138{
1139 struct orig_node *primary_orig_node;
1140 struct orig_node *router_orig;
Simon Wunderlicha4c135c2011-01-19 20:01:43 +00001141 struct neigh_node *router, *first_candidate, *tmp_neigh_node;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001142 static uint8_t zero_mac[ETH_ALEN] = {0, 0, 0, 0, 0, 0};
1143 int bonding_enabled;
1144
1145 if (!orig_node)
1146 return NULL;
1147
1148 if (!orig_node->router)
1149 return NULL;
1150
1151 /* without bonding, the first node should
1152 * always choose the default router. */
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001153 bonding_enabled = atomic_read(&bat_priv->bonding);
1154
Simon Wunderlicha4c135c2011-01-19 20:01:43 +00001155 rcu_read_lock();
1156 /* select default router to output */
1157 router = orig_node->router;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001158 router_orig = orig_node->router->orig_node;
Marek Lindner44524fc2011-02-10 14:33:53 +00001159 if (!router_orig || !atomic_inc_not_zero(&router->refcount)) {
Simon Wunderlicha4c135c2011-01-19 20:01:43 +00001160 rcu_read_unlock();
1161 return NULL;
1162 }
1163
Simon Wunderlicha4c135c2011-01-19 20:01:43 +00001164 if ((!recv_if) && (!bonding_enabled))
1165 goto return_router;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001166
1167 /* if we have something in the primary_addr, we can search
1168 * for a potential bonding candidate. */
Marek Lindner39901e72011-02-18 12:28:08 +00001169 if (compare_eth(router_orig->primary_addr, zero_mac))
Simon Wunderlicha4c135c2011-01-19 20:01:43 +00001170 goto return_router;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001171
1172 /* find the orig_node which has the primary interface. might
1173 * even be the same as our router_orig in many cases */
1174
Marek Lindner39901e72011-02-18 12:28:08 +00001175 if (compare_eth(router_orig->primary_addr, router_orig->orig)) {
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001176 primary_orig_node = router_orig;
1177 } else {
Marek Lindner7aadf882011-02-18 12:28:09 +00001178 primary_orig_node = orig_hash_find(bat_priv,
1179 router_orig->primary_addr);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001180 if (!primary_orig_node)
Simon Wunderlicha4c135c2011-01-19 20:01:43 +00001181 goto return_router;
Marek Lindner7aadf882011-02-18 12:28:09 +00001182
Marek Lindner7b36e8e2011-02-18 12:28:10 +00001183 orig_node_free_ref(primary_orig_node);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001184 }
1185
1186 /* with less than 2 candidates, we can't do any
1187 * bonding and prefer the original router. */
Simon Wunderlicha4c135c2011-01-19 20:01:43 +00001188 if (atomic_read(&primary_orig_node->bond_candidates) < 2)
1189 goto return_router;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001190
1191
1192 /* all nodes between should choose a candidate which
1193 * is is not on the interface where the packet came
1194 * in. */
Simon Wunderlicha4c135c2011-01-19 20:01:43 +00001195
Marek Lindner44524fc2011-02-10 14:33:53 +00001196 neigh_node_free_ref(router);
Simon Wunderlicha4c135c2011-01-19 20:01:43 +00001197 first_candidate = NULL;
1198 router = NULL;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001199
1200 if (bonding_enabled) {
1201 /* in the bonding case, send the packets in a round
1202 * robin fashion over the remaining interfaces. */
Simon Wunderlicha4c135c2011-01-19 20:01:43 +00001203
1204 list_for_each_entry_rcu(tmp_neigh_node,
1205 &primary_orig_node->bond_list, bonding_list) {
1206 if (!first_candidate)
1207 first_candidate = tmp_neigh_node;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001208 /* recv_if == NULL on the first node. */
Marek Lindner44524fc2011-02-10 14:33:53 +00001209 if (tmp_neigh_node->if_incoming != recv_if &&
1210 atomic_inc_not_zero(&tmp_neigh_node->refcount)) {
Simon Wunderlicha4c135c2011-01-19 20:01:43 +00001211 router = tmp_neigh_node;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001212 break;
Simon Wunderlicha4c135c2011-01-19 20:01:43 +00001213 }
1214 }
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001215
Simon Wunderlicha4c135c2011-01-19 20:01:43 +00001216 /* use the first candidate if nothing was found. */
Marek Lindner44524fc2011-02-10 14:33:53 +00001217 if (!router && first_candidate &&
1218 atomic_inc_not_zero(&first_candidate->refcount))
Simon Wunderlicha4c135c2011-01-19 20:01:43 +00001219 router = first_candidate;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001220
Marek Lindner44524fc2011-02-10 14:33:53 +00001221 if (!router) {
1222 rcu_read_unlock();
1223 return NULL;
1224 }
1225
Simon Wunderlicha4c135c2011-01-19 20:01:43 +00001226 /* selected should point to the next element
1227 * after the current router */
1228 spin_lock_bh(&primary_orig_node->neigh_list_lock);
1229 /* this is a list_move(), which unfortunately
1230 * does not exist as rcu version */
1231 list_del_rcu(&primary_orig_node->bond_list);
1232 list_add_rcu(&primary_orig_node->bond_list,
1233 &router->bonding_list);
1234 spin_unlock_bh(&primary_orig_node->neigh_list_lock);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001235
1236 } else {
1237 /* if bonding is disabled, use the best of the
1238 * remaining candidates which are not using
1239 * this interface. */
Simon Wunderlicha4c135c2011-01-19 20:01:43 +00001240 list_for_each_entry_rcu(tmp_neigh_node,
1241 &primary_orig_node->bond_list, bonding_list) {
1242 if (!first_candidate)
1243 first_candidate = tmp_neigh_node;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001244
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001245 /* recv_if == NULL on the first node. */
Marek Lindner44524fc2011-02-10 14:33:53 +00001246 if (tmp_neigh_node->if_incoming == recv_if)
1247 continue;
1248
1249 if (!atomic_inc_not_zero(&tmp_neigh_node->refcount))
1250 continue;
1251
1252 /* if we don't have a router yet
1253 * or this one is better, choose it. */
1254 if ((!router) ||
1255 (tmp_neigh_node->tq_avg > router->tq_avg)) {
1256 /* decrement refcount of
1257 * previously selected router */
1258 if (router)
1259 neigh_node_free_ref(router);
1260
1261 router = tmp_neigh_node;
1262 atomic_inc_not_zero(&router->refcount);
1263 }
1264
1265 neigh_node_free_ref(tmp_neigh_node);
Simon Wunderlicha4c135c2011-01-19 20:01:43 +00001266 }
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001267
Simon Wunderlicha4c135c2011-01-19 20:01:43 +00001268 /* use the first candidate if nothing was found. */
Marek Lindner44524fc2011-02-10 14:33:53 +00001269 if (!router && first_candidate &&
1270 atomic_inc_not_zero(&first_candidate->refcount))
Simon Wunderlicha4c135c2011-01-19 20:01:43 +00001271 router = first_candidate;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001272 }
Simon Wunderlicha4c135c2011-01-19 20:01:43 +00001273return_router:
Simon Wunderlicha4c135c2011-01-19 20:01:43 +00001274 rcu_read_unlock();
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001275 return router;
1276}
1277
1278static int check_unicast_packet(struct sk_buff *skb, int hdr_size)
1279{
1280 struct ethhdr *ethhdr;
1281
1282 /* drop packet if it has not necessary minimum size */
1283 if (unlikely(!pskb_may_pull(skb, hdr_size)))
1284 return -1;
1285
1286 ethhdr = (struct ethhdr *)skb_mac_header(skb);
1287
1288 /* packet with unicast indication but broadcast recipient */
1289 if (is_broadcast_ether_addr(ethhdr->h_dest))
1290 return -1;
1291
1292 /* packet with broadcast sender address */
1293 if (is_broadcast_ether_addr(ethhdr->h_source))
1294 return -1;
1295
1296 /* not for me */
1297 if (!is_my_mac(ethhdr->h_dest))
1298 return -1;
1299
1300 return 0;
1301}
1302
1303int route_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if,
1304 int hdr_size)
1305{
1306 struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface);
Marek Lindner44524fc2011-02-10 14:33:53 +00001307 struct orig_node *orig_node = NULL;
1308 struct neigh_node *neigh_node = NULL;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001309 struct batman_if *batman_if;
1310 uint8_t dstaddr[ETH_ALEN];
1311 struct unicast_packet *unicast_packet;
1312 struct ethhdr *ethhdr = (struct ethhdr *)skb_mac_header(skb);
Marek Lindner44524fc2011-02-10 14:33:53 +00001313 int ret = NET_RX_DROP;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001314 struct sk_buff *new_skb;
1315
1316 unicast_packet = (struct unicast_packet *)skb->data;
1317
1318 /* TTL exceeded */
1319 if (unicast_packet->ttl < 2) {
1320 pr_debug("Warning - can't forward unicast packet from %pM to "
1321 "%pM: ttl exceeded\n", ethhdr->h_source,
1322 unicast_packet->dest);
Marek Lindner44524fc2011-02-10 14:33:53 +00001323 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001324 }
1325
1326 /* get routing information */
1327 spin_lock_bh(&bat_priv->orig_hash_lock);
Marek Lindnerfb778ea2011-01-19 20:01:40 +00001328 rcu_read_lock();
Marek Lindner7aadf882011-02-18 12:28:09 +00001329 orig_node = orig_hash_find(bat_priv, unicast_packet->dest);
1330
Marek Lindner44524fc2011-02-10 14:33:53 +00001331 if (!orig_node)
1332 goto unlock;
1333
Marek Lindnerfb778ea2011-01-19 20:01:40 +00001334 rcu_read_unlock();
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001335
Simon Wunderlicha4c135c2011-01-19 20:01:43 +00001336 /* find_router() increases neigh_nodes refcount if found. */
Marek Lindner44524fc2011-02-10 14:33:53 +00001337 neigh_node = find_router(bat_priv, orig_node, recv_if);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001338
Marek Lindner44524fc2011-02-10 14:33:53 +00001339 if (!neigh_node) {
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001340 spin_unlock_bh(&bat_priv->orig_hash_lock);
Marek Lindner44524fc2011-02-10 14:33:53 +00001341 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001342 }
1343
1344 /* don't lock while sending the packets ... we therefore
1345 * copy the required data before sending */
Marek Lindner44524fc2011-02-10 14:33:53 +00001346 batman_if = neigh_node->if_incoming;
1347 memcpy(dstaddr, neigh_node->addr, ETH_ALEN);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001348 spin_unlock_bh(&bat_priv->orig_hash_lock);
1349
1350 /* create a copy of the skb, if needed, to modify it. */
1351 if (skb_cow(skb, sizeof(struct ethhdr)) < 0)
Marek Lindner44524fc2011-02-10 14:33:53 +00001352 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001353
1354 unicast_packet = (struct unicast_packet *)skb->data;
1355
1356 if (unicast_packet->packet_type == BAT_UNICAST &&
1357 atomic_read(&bat_priv->fragmentation) &&
1358 skb->len > batman_if->net_dev->mtu)
1359 return frag_send_skb(skb, bat_priv, batman_if,
1360 dstaddr);
1361
1362 if (unicast_packet->packet_type == BAT_UNICAST_FRAG &&
Sven Eckelmannae361ce2011-01-25 22:02:31 +00001363 frag_can_reassemble(skb, batman_if->net_dev->mtu)) {
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001364
1365 ret = frag_reassemble_skb(skb, bat_priv, &new_skb);
1366
1367 if (ret == NET_RX_DROP)
Marek Lindner44524fc2011-02-10 14:33:53 +00001368 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001369
1370 /* packet was buffered for late merge */
Marek Lindner44524fc2011-02-10 14:33:53 +00001371 if (!new_skb) {
1372 ret = NET_RX_SUCCESS;
1373 goto out;
1374 }
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001375
1376 skb = new_skb;
1377 unicast_packet = (struct unicast_packet *)skb->data;
1378 }
1379
1380 /* decrement ttl */
1381 unicast_packet->ttl--;
1382
1383 /* route it */
1384 send_skb_packet(skb, batman_if, dstaddr);
Marek Lindner44524fc2011-02-10 14:33:53 +00001385 ret = NET_RX_SUCCESS;
1386 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001387
Marek Lindner44524fc2011-02-10 14:33:53 +00001388unlock:
1389 rcu_read_unlock();
1390 spin_unlock_bh(&bat_priv->orig_hash_lock);
1391out:
1392 if (neigh_node)
1393 neigh_node_free_ref(neigh_node);
1394 if (orig_node)
Marek Lindner7b36e8e2011-02-18 12:28:10 +00001395 orig_node_free_ref(orig_node);
Marek Lindner44524fc2011-02-10 14:33:53 +00001396 return ret;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001397}
1398
1399int recv_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if)
1400{
1401 struct unicast_packet *unicast_packet;
1402 int hdr_size = sizeof(struct unicast_packet);
1403
1404 if (check_unicast_packet(skb, hdr_size) < 0)
1405 return NET_RX_DROP;
1406
1407 unicast_packet = (struct unicast_packet *)skb->data;
1408
1409 /* packet for me */
1410 if (is_my_mac(unicast_packet->dest)) {
1411 interface_rx(recv_if->soft_iface, skb, recv_if, hdr_size);
1412 return NET_RX_SUCCESS;
1413 }
1414
1415 return route_unicast_packet(skb, recv_if, hdr_size);
1416}
1417
1418int recv_ucast_frag_packet(struct sk_buff *skb, struct batman_if *recv_if)
1419{
1420 struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface);
1421 struct unicast_frag_packet *unicast_packet;
1422 int hdr_size = sizeof(struct unicast_frag_packet);
1423 struct sk_buff *new_skb = NULL;
1424 int ret;
1425
1426 if (check_unicast_packet(skb, hdr_size) < 0)
1427 return NET_RX_DROP;
1428
1429 unicast_packet = (struct unicast_frag_packet *)skb->data;
1430
1431 /* packet for me */
1432 if (is_my_mac(unicast_packet->dest)) {
1433
1434 ret = frag_reassemble_skb(skb, bat_priv, &new_skb);
1435
1436 if (ret == NET_RX_DROP)
1437 return NET_RX_DROP;
1438
1439 /* packet was buffered for late merge */
1440 if (!new_skb)
1441 return NET_RX_SUCCESS;
1442
1443 interface_rx(recv_if->soft_iface, new_skb, recv_if,
1444 sizeof(struct unicast_packet));
1445 return NET_RX_SUCCESS;
1446 }
1447
1448 return route_unicast_packet(skb, recv_if, hdr_size);
1449}
1450
1451
1452int recv_bcast_packet(struct sk_buff *skb, struct batman_if *recv_if)
1453{
1454 struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface);
Marek Lindnerf3e00082011-01-25 21:52:11 +00001455 struct orig_node *orig_node = NULL;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001456 struct bcast_packet *bcast_packet;
1457 struct ethhdr *ethhdr;
1458 int hdr_size = sizeof(struct bcast_packet);
Marek Lindnerf3e00082011-01-25 21:52:11 +00001459 int ret = NET_RX_DROP;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001460 int32_t seq_diff;
1461
1462 /* drop packet if it has not necessary minimum size */
1463 if (unlikely(!pskb_may_pull(skb, hdr_size)))
Marek Lindnerf3e00082011-01-25 21:52:11 +00001464 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001465
1466 ethhdr = (struct ethhdr *)skb_mac_header(skb);
1467
1468 /* packet with broadcast indication but unicast recipient */
1469 if (!is_broadcast_ether_addr(ethhdr->h_dest))
Marek Lindnerf3e00082011-01-25 21:52:11 +00001470 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001471
1472 /* packet with broadcast sender address */
1473 if (is_broadcast_ether_addr(ethhdr->h_source))
Marek Lindnerf3e00082011-01-25 21:52:11 +00001474 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001475
1476 /* ignore broadcasts sent by myself */
1477 if (is_my_mac(ethhdr->h_source))
Marek Lindnerf3e00082011-01-25 21:52:11 +00001478 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001479
1480 bcast_packet = (struct bcast_packet *)skb->data;
1481
1482 /* ignore broadcasts originated by myself */
1483 if (is_my_mac(bcast_packet->orig))
Marek Lindnerf3e00082011-01-25 21:52:11 +00001484 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001485
1486 if (bcast_packet->ttl < 2)
Marek Lindnerf3e00082011-01-25 21:52:11 +00001487 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001488
1489 spin_lock_bh(&bat_priv->orig_hash_lock);
Marek Lindnerfb778ea2011-01-19 20:01:40 +00001490 rcu_read_lock();
Marek Lindner7aadf882011-02-18 12:28:09 +00001491 orig_node = orig_hash_find(bat_priv, bcast_packet->orig);
Marek Lindnerf3e00082011-01-25 21:52:11 +00001492
1493 if (!orig_node)
1494 goto rcu_unlock;
1495
Marek Lindnerfb778ea2011-01-19 20:01:40 +00001496 rcu_read_unlock();
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001497
Marek Lindnerf3e00082011-01-25 21:52:11 +00001498 spin_lock_bh(&orig_node->bcast_seqno_lock);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001499
1500 /* check whether the packet is a duplicate */
Marek Lindnerf3e00082011-01-25 21:52:11 +00001501 if (get_bit_status(orig_node->bcast_bits, orig_node->last_bcast_seqno,
1502 ntohl(bcast_packet->seqno)))
1503 goto spin_unlock;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001504
1505 seq_diff = ntohl(bcast_packet->seqno) - orig_node->last_bcast_seqno;
1506
1507 /* check whether the packet is old and the host just restarted. */
1508 if (window_protected(bat_priv, seq_diff,
Marek Lindnerf3e00082011-01-25 21:52:11 +00001509 &orig_node->bcast_seqno_reset))
1510 goto spin_unlock;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001511
1512 /* mark broadcast in flood history, update window position
1513 * if required. */
1514 if (bit_get_packet(bat_priv, orig_node->bcast_bits, seq_diff, 1))
1515 orig_node->last_bcast_seqno = ntohl(bcast_packet->seqno);
1516
Marek Lindnerf3e00082011-01-25 21:52:11 +00001517 spin_unlock_bh(&orig_node->bcast_seqno_lock);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001518 spin_unlock_bh(&bat_priv->orig_hash_lock);
Marek Lindnerf3e00082011-01-25 21:52:11 +00001519
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001520 /* rebroadcast packet */
1521 add_bcast_packet_to_list(bat_priv, skb);
1522
1523 /* broadcast for me */
1524 interface_rx(recv_if->soft_iface, skb, recv_if, hdr_size);
Marek Lindnerf3e00082011-01-25 21:52:11 +00001525 ret = NET_RX_SUCCESS;
1526 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001527
Marek Lindnerf3e00082011-01-25 21:52:11 +00001528rcu_unlock:
1529 rcu_read_unlock();
1530 spin_unlock_bh(&bat_priv->orig_hash_lock);
1531 goto out;
1532spin_unlock:
1533 spin_unlock_bh(&orig_node->bcast_seqno_lock);
1534 spin_unlock_bh(&bat_priv->orig_hash_lock);
1535out:
1536 if (orig_node)
Marek Lindner7b36e8e2011-02-18 12:28:10 +00001537 orig_node_free_ref(orig_node);
Marek Lindnerf3e00082011-01-25 21:52:11 +00001538 return ret;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001539}
1540
1541int recv_vis_packet(struct sk_buff *skb, struct batman_if *recv_if)
1542{
1543 struct vis_packet *vis_packet;
1544 struct ethhdr *ethhdr;
1545 struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface);
1546 int hdr_size = sizeof(struct vis_packet);
1547
1548 /* keep skb linear */
1549 if (skb_linearize(skb) < 0)
1550 return NET_RX_DROP;
1551
1552 if (unlikely(!pskb_may_pull(skb, hdr_size)))
1553 return NET_RX_DROP;
1554
1555 vis_packet = (struct vis_packet *)skb->data;
1556 ethhdr = (struct ethhdr *)skb_mac_header(skb);
1557
1558 /* not for me */
1559 if (!is_my_mac(ethhdr->h_dest))
1560 return NET_RX_DROP;
1561
1562 /* ignore own packets */
1563 if (is_my_mac(vis_packet->vis_orig))
1564 return NET_RX_DROP;
1565
1566 if (is_my_mac(vis_packet->sender_orig))
1567 return NET_RX_DROP;
1568
1569 switch (vis_packet->vis_type) {
1570 case VIS_TYPE_SERVER_SYNC:
1571 receive_server_sync_packet(bat_priv, vis_packet,
1572 skb_headlen(skb));
1573 break;
1574
1575 case VIS_TYPE_CLIENT_UPDATE:
1576 receive_client_update_packet(bat_priv, vis_packet,
1577 skb_headlen(skb));
1578 break;
1579
1580 default: /* ignore unknown packet */
1581 break;
1582 }
1583
1584 /* We take a copy of the data in the packet, so we should
1585 always free the skbuf. */
1586 return NET_RX_DROP;
1587}