blob: 05d50ca3c4dbf552d247f74246b263b2bfccf4cf [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
Marek Lindnere6c10f42011-02-18 12:33:20 +000038void slide_own_bcast_window(struct hard_iface *hard_iface)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +000039{
Marek Lindnere6c10f42011-02-18 12:33:20 +000040 struct bat_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +000041 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
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +000049 for (i = 0; i < hash->size; i++) {
50 head = &hash->table[i];
51
Marek Lindnerfb778ea2011-01-19 20:01:40 +000052 rcu_read_lock();
Marek Lindner7aadf882011-02-18 12:28:09 +000053 hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) {
Marek Lindner2ae2daf2011-01-19 20:01:42 +000054 spin_lock_bh(&orig_node->ogm_cnt_lock);
Marek Lindnere6c10f42011-02-18 12:33:20 +000055 word_index = hard_iface->if_num * NUM_WORDS;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +000056 word = &(orig_node->bcast_own[word_index]);
57
58 bit_get_packet(bat_priv, word, 1, 0);
Marek Lindnere6c10f42011-02-18 12:33:20 +000059 orig_node->bcast_own_sum[hard_iface->if_num] =
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +000060 bit_packet_count(word);
Marek Lindner2ae2daf2011-01-19 20:01:42 +000061 spin_unlock_bh(&orig_node->ogm_cnt_lock);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +000062 }
Marek Lindnerfb778ea2011-01-19 20:01:40 +000063 rcu_read_unlock();
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +000064 }
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +000065}
66
Antonio Quartullia73105b2011-04-27 14:27:44 +020067static void update_transtable(struct bat_priv *bat_priv,
68 struct orig_node *orig_node,
69 const unsigned char *tt_buff,
70 uint8_t tt_num_changes, uint8_t ttvn,
71 uint16_t tt_crc)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +000072{
Antonio Quartullia73105b2011-04-27 14:27:44 +020073 uint8_t orig_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn);
74 bool full_table = true;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +000075
Antonio Quartullia73105b2011-04-27 14:27:44 +020076 /* the ttvn increased by one -> we can apply the attached changes */
77 if (ttvn - orig_ttvn == 1) {
78 /* the OGM could not contain the changes because they were too
79 * many to fit in one frame or because they have already been
80 * sent TT_OGM_APPEND_MAX times. In this case send a tt
81 * request */
82 if (!tt_num_changes) {
83 full_table = false;
84 goto request_table;
85 }
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +000086
Antonio Quartullia73105b2011-04-27 14:27:44 +020087 tt_update_changes(bat_priv, orig_node, tt_num_changes, ttvn,
88 (struct tt_change *)tt_buff);
89
90 /* Even if we received the crc into the OGM, we prefer
91 * to recompute it to spot any possible inconsistency
92 * in the global table */
93 spin_lock_bh(&bat_priv->tt_ghash_lock);
94 orig_node->tt_crc = tt_global_crc(bat_priv, orig_node);
95 spin_unlock_bh(&bat_priv->tt_ghash_lock);
Antonio Quartullicc47f662011-04-27 14:27:57 +020096 /* Roaming phase is over: tables are in sync again. I can
97 * unset the flag */
98 orig_node->tt_poss_change = false;
Antonio Quartullia73105b2011-04-27 14:27:44 +020099 } else {
100 /* if we missed more than one change or our tables are not
101 * in sync anymore -> request fresh tt data */
102 if (ttvn != orig_ttvn || orig_node->tt_crc != tt_crc) {
103request_table:
104 bat_dbg(DBG_TT, bat_priv, "TT inconsistency for %pM. "
105 "Need to retrieve the correct information "
106 "(ttvn: %u last_ttvn: %u crc: %u last_crc: "
107 "%u num_changes: %u)\n", orig_node->orig, ttvn,
108 orig_ttvn, tt_crc, orig_node->tt_crc,
109 tt_num_changes);
110 send_tt_request(bat_priv, orig_node, ttvn, tt_crc,
111 full_table);
112 return;
113 }
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000114 }
115}
116
Antonio Quartullia73105b2011-04-27 14:27:44 +0200117static void update_route(struct bat_priv *bat_priv,
118 struct orig_node *orig_node,
119 struct neigh_node *neigh_node)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000120{
Linus Lüssinge1a5382f2011-03-14 22:43:37 +0000121 struct neigh_node *curr_router;
122
123 curr_router = orig_node_get_router(orig_node);
Marek Lindnera8e7f4b2010-12-12 21:57:10 +0000124
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000125 /* route deleted */
Linus Lüssinge1a5382f2011-03-14 22:43:37 +0000126 if ((curr_router) && (!neigh_node)) {
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000127 bat_dbg(DBG_ROUTES, bat_priv, "Deleting route towards: %pM\n",
128 orig_node->orig);
Antonio Quartulli2dafb492011-05-05 08:42:45 +0200129 tt_global_del_orig(bat_priv, orig_node,
Antonio Quartullia73105b2011-04-27 14:27:44 +0200130 "Deleted route towards originator");
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000131
Linus Lüssinge1a5382f2011-03-14 22:43:37 +0000132 /* route added */
133 } else if ((!curr_router) && (neigh_node)) {
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000134
135 bat_dbg(DBG_ROUTES, bat_priv,
136 "Adding route towards: %pM (via %pM)\n",
137 orig_node->orig, neigh_node->addr);
Linus Lüssinge1a5382f2011-03-14 22:43:37 +0000138 /* route changed */
Sven Eckelmannbb899b82011-05-10 11:22:37 +0200139 } else if (neigh_node && curr_router) {
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000140 bat_dbg(DBG_ROUTES, bat_priv,
141 "Changing route towards: %pM "
142 "(now via %pM - was via %pM)\n",
143 orig_node->orig, neigh_node->addr,
Linus Lüssinge1a5382f2011-03-14 22:43:37 +0000144 curr_router->addr);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000145 }
146
Linus Lüssinge1a5382f2011-03-14 22:43:37 +0000147 if (curr_router)
148 neigh_node_free_ref(curr_router);
149
150 /* increase refcount of new best neighbor */
Marek Lindner44524fc2011-02-10 14:33:53 +0000151 if (neigh_node && !atomic_inc_not_zero(&neigh_node->refcount))
152 neigh_node = NULL;
Linus Lüssinge1a5382f2011-03-14 22:43:37 +0000153
154 spin_lock_bh(&orig_node->neigh_list_lock);
155 rcu_assign_pointer(orig_node->router, neigh_node);
156 spin_unlock_bh(&orig_node->neigh_list_lock);
157
158 /* decrease refcount of previous best neighbor */
159 if (curr_router)
160 neigh_node_free_ref(curr_router);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000161}
162
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000163void update_routes(struct bat_priv *bat_priv, struct orig_node *orig_node,
Antonio Quartullia73105b2011-04-27 14:27:44 +0200164 struct neigh_node *neigh_node)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000165{
Linus Lüssinge1a5382f2011-03-14 22:43:37 +0000166 struct neigh_node *router = NULL;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000167
168 if (!orig_node)
Linus Lüssinge1a5382f2011-03-14 22:43:37 +0000169 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000170
Linus Lüssinge1a5382f2011-03-14 22:43:37 +0000171 router = orig_node_get_router(orig_node);
172
173 if (router != neigh_node)
Antonio Quartullia73105b2011-04-27 14:27:44 +0200174 update_route(bat_priv, orig_node, neigh_node);
Linus Lüssinge1a5382f2011-03-14 22:43:37 +0000175
176out:
177 if (router)
178 neigh_node_free_ref(router);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000179}
180
181static int is_bidirectional_neigh(struct orig_node *orig_node,
182 struct orig_node *orig_neigh_node,
183 struct batman_packet *batman_packet,
Marek Lindnere6c10f42011-02-18 12:33:20 +0000184 struct hard_iface *if_incoming)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000185{
186 struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
Marek Lindner1605d0d2011-02-18 12:28:11 +0000187 struct neigh_node *neigh_node = NULL, *tmp_neigh_node;
Marek Lindner9591a792010-12-12 21:57:11 +0000188 struct hlist_node *node;
Sven Eckelmannb4e17052011-06-15 09:41:37 +0200189 uint8_t total_count;
Marek Lindner0ede9f42011-01-25 21:52:10 +0000190 uint8_t orig_eq_count, neigh_rq_count, tq_own;
191 int tq_asym_penalty, ret = 0;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000192
Daniele Furlan27aea212011-05-07 22:45:19 +0200193 /* find corresponding one hop neighbor */
194 rcu_read_lock();
195 hlist_for_each_entry_rcu(tmp_neigh_node, node,
196 &orig_neigh_node->neigh_list, list) {
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000197
Daniele Furlan27aea212011-05-07 22:45:19 +0200198 if (!compare_eth(tmp_neigh_node->addr, orig_neigh_node->orig))
199 continue;
Marek Lindner1605d0d2011-02-18 12:28:11 +0000200
Daniele Furlan27aea212011-05-07 22:45:19 +0200201 if (tmp_neigh_node->if_incoming != if_incoming)
202 continue;
Marek Lindner1605d0d2011-02-18 12:28:11 +0000203
Daniele Furlan27aea212011-05-07 22:45:19 +0200204 if (!atomic_inc_not_zero(&tmp_neigh_node->refcount))
205 continue;
Marek Lindner1605d0d2011-02-18 12:28:11 +0000206
Daniele Furlan27aea212011-05-07 22:45:19 +0200207 neigh_node = tmp_neigh_node;
208 break;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000209 }
Daniele Furlan27aea212011-05-07 22:45:19 +0200210 rcu_read_unlock();
211
212 if (!neigh_node)
213 neigh_node = create_neighbor(orig_neigh_node,
214 orig_neigh_node,
215 orig_neigh_node->orig,
216 if_incoming);
217
218 if (!neigh_node)
219 goto out;
220
221 /* if orig_node is direct neighbour update neigh_node last_valid */
222 if (orig_node == orig_neigh_node)
223 neigh_node->last_valid = jiffies;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000224
225 orig_node->last_valid = jiffies;
226
Daniele Furlan27aea212011-05-07 22:45:19 +0200227 /* find packet count of corresponding one hop neighbor */
Marek Lindner0ede9f42011-01-25 21:52:10 +0000228 spin_lock_bh(&orig_node->ogm_cnt_lock);
229 orig_eq_count = orig_neigh_node->bcast_own_sum[if_incoming->if_num];
230 neigh_rq_count = neigh_node->real_packet_count;
231 spin_unlock_bh(&orig_node->ogm_cnt_lock);
232
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000233 /* pay attention to not get a value bigger than 100 % */
Marek Lindner0ede9f42011-01-25 21:52:10 +0000234 total_count = (orig_eq_count > neigh_rq_count ?
235 neigh_rq_count : orig_eq_count);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000236
237 /* if we have too few packets (too less data) we set tq_own to zero */
238 /* if we receive too few packets it is not considered bidirectional */
239 if ((total_count < TQ_LOCAL_BIDRECT_SEND_MINIMUM) ||
Marek Lindner0ede9f42011-01-25 21:52:10 +0000240 (neigh_rq_count < TQ_LOCAL_BIDRECT_RECV_MINIMUM))
241 tq_own = 0;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000242 else
243 /* neigh_node->real_packet_count is never zero as we
244 * only purge old information when getting new
245 * information */
Marek Lindner0ede9f42011-01-25 21:52:10 +0000246 tq_own = (TQ_MAX_VALUE * total_count) / neigh_rq_count;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000247
248 /*
249 * 1 - ((1-x) ** 3), normalized to TQ_MAX_VALUE this does
250 * affect the nearly-symmetric links only a little, but
251 * punishes asymmetric links more. This will give a value
252 * between 0 and TQ_MAX_VALUE
253 */
Marek Lindner0ede9f42011-01-25 21:52:10 +0000254 tq_asym_penalty = TQ_MAX_VALUE - (TQ_MAX_VALUE *
255 (TQ_LOCAL_WINDOW_SIZE - neigh_rq_count) *
256 (TQ_LOCAL_WINDOW_SIZE - neigh_rq_count) *
257 (TQ_LOCAL_WINDOW_SIZE - neigh_rq_count)) /
258 (TQ_LOCAL_WINDOW_SIZE *
259 TQ_LOCAL_WINDOW_SIZE *
260 TQ_LOCAL_WINDOW_SIZE);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000261
Marek Lindner0ede9f42011-01-25 21:52:10 +0000262 batman_packet->tq = ((batman_packet->tq * tq_own * tq_asym_penalty) /
263 (TQ_MAX_VALUE * TQ_MAX_VALUE));
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000264
265 bat_dbg(DBG_BATMAN, bat_priv,
266 "bidirectional: "
267 "orig = %-15pM neigh = %-15pM => own_bcast = %2i, "
268 "real recv = %2i, local tq: %3i, asym_penalty: %3i, "
269 "total tq: %3i\n",
270 orig_node->orig, orig_neigh_node->orig, total_count,
Marek Lindner0ede9f42011-01-25 21:52:10 +0000271 neigh_rq_count, tq_own, tq_asym_penalty, batman_packet->tq);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000272
273 /* if link has the minimum required transmission quality
274 * consider it bidirectional */
275 if (batman_packet->tq >= TQ_TOTAL_BIDRECT_LIMIT)
Marek Lindnera775eb82011-01-19 20:01:39 +0000276 ret = 1;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000277
Marek Lindnera775eb82011-01-19 20:01:39 +0000278out:
279 if (neigh_node)
Marek Lindner44524fc2011-02-10 14:33:53 +0000280 neigh_node_free_ref(neigh_node);
Marek Lindnera775eb82011-01-19 20:01:39 +0000281 return ret;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000282}
283
Simon Wunderlicha4c135c2011-01-19 20:01:43 +0000284/* caller must hold the neigh_list_lock */
285void bonding_candidate_del(struct orig_node *orig_node,
286 struct neigh_node *neigh_node)
287{
288 /* this neighbor is not part of our candidate list */
289 if (list_empty(&neigh_node->bonding_list))
290 goto out;
291
292 list_del_rcu(&neigh_node->bonding_list);
Simon Wunderlicha4c135c2011-01-19 20:01:43 +0000293 INIT_LIST_HEAD(&neigh_node->bonding_list);
Marek Lindner44524fc2011-02-10 14:33:53 +0000294 neigh_node_free_ref(neigh_node);
Simon Wunderlicha4c135c2011-01-19 20:01:43 +0000295 atomic_dec(&orig_node->bond_candidates);
296
297out:
298 return;
299}
300
301static void bonding_candidate_add(struct orig_node *orig_node,
302 struct neigh_node *neigh_node)
303{
304 struct hlist_node *node;
Linus Lüssinge1a5382f2011-03-14 22:43:37 +0000305 struct neigh_node *tmp_neigh_node, *router = NULL;
306 uint8_t interference_candidate = 0;
Simon Wunderlicha4c135c2011-01-19 20:01:43 +0000307
308 spin_lock_bh(&orig_node->neigh_list_lock);
309
310 /* only consider if it has the same primary address ... */
Marek Lindner39901e72011-02-18 12:28:08 +0000311 if (!compare_eth(orig_node->orig,
312 neigh_node->orig_node->primary_addr))
Simon Wunderlicha4c135c2011-01-19 20:01:43 +0000313 goto candidate_del;
314
Linus Lüssinge1a5382f2011-03-14 22:43:37 +0000315 router = orig_node_get_router(orig_node);
316 if (!router)
Simon Wunderlicha4c135c2011-01-19 20:01:43 +0000317 goto candidate_del;
318
Simon Wunderlicha4c135c2011-01-19 20:01:43 +0000319 /* ... and is good enough to be considered */
Linus Lüssinge1a5382f2011-03-14 22:43:37 +0000320 if (neigh_node->tq_avg < router->tq_avg - BONDING_TQ_THRESHOLD)
Simon Wunderlicha4c135c2011-01-19 20:01:43 +0000321 goto candidate_del;
322
323 /**
324 * check if we have another candidate with the same mac address or
325 * interface. If we do, we won't select this candidate because of
326 * possible interference.
327 */
328 hlist_for_each_entry_rcu(tmp_neigh_node, node,
329 &orig_node->neigh_list, list) {
330
331 if (tmp_neigh_node == neigh_node)
332 continue;
333
334 /* we only care if the other candidate is even
335 * considered as candidate. */
336 if (list_empty(&tmp_neigh_node->bonding_list))
337 continue;
338
339 if ((neigh_node->if_incoming == tmp_neigh_node->if_incoming) ||
Marek Lindner39901e72011-02-18 12:28:08 +0000340 (compare_eth(neigh_node->addr, tmp_neigh_node->addr))) {
Simon Wunderlicha4c135c2011-01-19 20:01:43 +0000341 interference_candidate = 1;
342 break;
343 }
344 }
345
346 /* don't care further if it is an interference candidate */
347 if (interference_candidate)
348 goto candidate_del;
349
350 /* this neighbor already is part of our candidate list */
351 if (!list_empty(&neigh_node->bonding_list))
352 goto out;
353
Marek Lindner44524fc2011-02-10 14:33:53 +0000354 if (!atomic_inc_not_zero(&neigh_node->refcount))
355 goto out;
356
Simon Wunderlicha4c135c2011-01-19 20:01:43 +0000357 list_add_rcu(&neigh_node->bonding_list, &orig_node->bond_list);
Simon Wunderlicha4c135c2011-01-19 20:01:43 +0000358 atomic_inc(&orig_node->bond_candidates);
359 goto out;
360
361candidate_del:
362 bonding_candidate_del(orig_node, neigh_node);
363
364out:
365 spin_unlock_bh(&orig_node->neigh_list_lock);
Linus Lüssinge1a5382f2011-03-14 22:43:37 +0000366
367 if (router)
368 neigh_node_free_ref(router);
Simon Wunderlicha4c135c2011-01-19 20:01:43 +0000369}
370
371/* copy primary address for bonding */
Sven Eckelmann747e4222011-05-14 23:14:50 +0200372static void bonding_save_primary(const struct orig_node *orig_node,
Simon Wunderlicha4c135c2011-01-19 20:01:43 +0000373 struct orig_node *orig_neigh_node,
Sven Eckelmann747e4222011-05-14 23:14:50 +0200374 const struct batman_packet *batman_packet)
Simon Wunderlicha4c135c2011-01-19 20:01:43 +0000375{
376 if (!(batman_packet->flags & PRIMARIES_FIRST_HOP))
377 return;
378
379 memcpy(orig_neigh_node->primary_addr, orig_node->orig, ETH_ALEN);
380}
381
Sven Eckelmann747e4222011-05-14 23:14:50 +0200382static void update_orig(struct bat_priv *bat_priv, struct orig_node *orig_node,
383 const struct ethhdr *ethhdr,
384 const struct batman_packet *batman_packet,
Marek Lindnere6c10f42011-02-18 12:33:20 +0000385 struct hard_iface *if_incoming,
Antonio Quartullia73105b2011-04-27 14:27:44 +0200386 const unsigned char *tt_buff, int is_duplicate)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000387{
388 struct neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL;
Linus Lüssinge1a5382f2011-03-14 22:43:37 +0000389 struct neigh_node *router = NULL;
Marek Lindner2ae2daf2011-01-19 20:01:42 +0000390 struct orig_node *orig_node_tmp;
Marek Lindner9591a792010-12-12 21:57:11 +0000391 struct hlist_node *node;
Marek Lindner2ae2daf2011-01-19 20:01:42 +0000392 uint8_t bcast_own_sum_orig, bcast_own_sum_neigh;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000393
394 bat_dbg(DBG_BATMAN, bat_priv, "update_originator(): "
395 "Searching and updating originator entry of received packet\n");
396
Marek Lindnerf987ed62010-12-12 21:57:12 +0000397 rcu_read_lock();
398 hlist_for_each_entry_rcu(tmp_neigh_node, node,
399 &orig_node->neigh_list, list) {
Marek Lindner39901e72011-02-18 12:28:08 +0000400 if (compare_eth(tmp_neigh_node->addr, ethhdr->h_source) &&
Marek Lindner44524fc2011-02-10 14:33:53 +0000401 (tmp_neigh_node->if_incoming == if_incoming) &&
402 atomic_inc_not_zero(&tmp_neigh_node->refcount)) {
403 if (neigh_node)
404 neigh_node_free_ref(neigh_node);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000405 neigh_node = tmp_neigh_node;
406 continue;
407 }
408
409 if (is_duplicate)
410 continue;
411
Linus Lüssing68003902011-03-14 22:43:40 +0000412 spin_lock_bh(&tmp_neigh_node->tq_lock);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000413 ring_buffer_set(tmp_neigh_node->tq_recv,
414 &tmp_neigh_node->tq_index, 0);
415 tmp_neigh_node->tq_avg =
416 ring_buffer_avg(tmp_neigh_node->tq_recv);
Linus Lüssing68003902011-03-14 22:43:40 +0000417 spin_unlock_bh(&tmp_neigh_node->tq_lock);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000418 }
419
420 if (!neigh_node) {
421 struct orig_node *orig_tmp;
422
423 orig_tmp = get_orig_node(bat_priv, ethhdr->h_source);
424 if (!orig_tmp)
Marek Lindnera775eb82011-01-19 20:01:39 +0000425 goto unlock;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000426
427 neigh_node = create_neighbor(orig_node, orig_tmp,
428 ethhdr->h_source, if_incoming);
Marek Lindner16b1aba2011-01-19 20:01:42 +0000429
Marek Lindner7b36e8e2011-02-18 12:28:10 +0000430 orig_node_free_ref(orig_tmp);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000431 if (!neigh_node)
Marek Lindnera775eb82011-01-19 20:01:39 +0000432 goto unlock;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000433 } else
434 bat_dbg(DBG_BATMAN, bat_priv,
435 "Updating existing last-hop neighbor of originator\n");
436
Marek Lindnera775eb82011-01-19 20:01:39 +0000437 rcu_read_unlock();
438
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000439 orig_node->flags = batman_packet->flags;
440 neigh_node->last_valid = jiffies;
441
Linus Lüssing68003902011-03-14 22:43:40 +0000442 spin_lock_bh(&neigh_node->tq_lock);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000443 ring_buffer_set(neigh_node->tq_recv,
444 &neigh_node->tq_index,
445 batman_packet->tq);
446 neigh_node->tq_avg = ring_buffer_avg(neigh_node->tq_recv);
Linus Lüssing68003902011-03-14 22:43:40 +0000447 spin_unlock_bh(&neigh_node->tq_lock);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000448
449 if (!is_duplicate) {
450 orig_node->last_ttl = batman_packet->ttl;
451 neigh_node->last_ttl = batman_packet->ttl;
452 }
453
Simon Wunderlicha4c135c2011-01-19 20:01:43 +0000454 bonding_candidate_add(orig_node, neigh_node);
455
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000456 /* if this neighbor already is our next hop there is nothing
457 * to change */
Linus Lüssinge1a5382f2011-03-14 22:43:37 +0000458 router = orig_node_get_router(orig_node);
459 if (router == neigh_node)
Antonio Quartulli2dafb492011-05-05 08:42:45 +0200460 goto update_tt;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000461
462 /* if this neighbor does not offer a better TQ we won't consider it */
Linus Lüssinge1a5382f2011-03-14 22:43:37 +0000463 if (router && (router->tq_avg > neigh_node->tq_avg))
Antonio Quartulli2dafb492011-05-05 08:42:45 +0200464 goto update_tt;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000465
466 /* if the TQ is the same and the link not more symetric we
467 * won't consider it either */
Linus Lüssinge1a5382f2011-03-14 22:43:37 +0000468 if (router && (neigh_node->tq_avg == router->tq_avg)) {
469 orig_node_tmp = router->orig_node;
Marek Lindner2ae2daf2011-01-19 20:01:42 +0000470 spin_lock_bh(&orig_node_tmp->ogm_cnt_lock);
471 bcast_own_sum_orig =
472 orig_node_tmp->bcast_own_sum[if_incoming->if_num];
473 spin_unlock_bh(&orig_node_tmp->ogm_cnt_lock);
474
475 orig_node_tmp = neigh_node->orig_node;
476 spin_lock_bh(&orig_node_tmp->ogm_cnt_lock);
477 bcast_own_sum_neigh =
478 orig_node_tmp->bcast_own_sum[if_incoming->if_num];
479 spin_unlock_bh(&orig_node_tmp->ogm_cnt_lock);
480
481 if (bcast_own_sum_orig >= bcast_own_sum_neigh)
Antonio Quartulli2dafb492011-05-05 08:42:45 +0200482 goto update_tt;
Marek Lindner2ae2daf2011-01-19 20:01:42 +0000483 }
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000484
Antonio Quartullia73105b2011-04-27 14:27:44 +0200485 update_routes(bat_priv, orig_node, neigh_node);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000486
Antonio Quartulli2dafb492011-05-05 08:42:45 +0200487update_tt:
Antonio Quartullia73105b2011-04-27 14:27:44 +0200488 /* I have to check for transtable changes only if the OGM has been
489 * sent through a primary interface */
490 if (((batman_packet->orig != ethhdr->h_source) &&
491 (batman_packet->ttl > 2)) ||
492 (batman_packet->flags & PRIMARIES_FIRST_HOP))
493 update_transtable(bat_priv, orig_node, tt_buff,
494 batman_packet->tt_num_changes,
495 batman_packet->ttvn,
496 batman_packet->tt_crc);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000497
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000498 if (orig_node->gw_flags != batman_packet->gw_flags)
499 gw_node_update(bat_priv, orig_node, batman_packet->gw_flags);
500
501 orig_node->gw_flags = batman_packet->gw_flags;
502
503 /* restart gateway selection if fast or late switching was enabled */
504 if ((orig_node->gw_flags) &&
505 (atomic_read(&bat_priv->gw_mode) == GW_MODE_CLIENT) &&
506 (atomic_read(&bat_priv->gw_sel_class) > 2))
507 gw_check_election(bat_priv, orig_node);
Marek Lindnera775eb82011-01-19 20:01:39 +0000508
509 goto out;
510
511unlock:
512 rcu_read_unlock();
513out:
514 if (neigh_node)
Marek Lindner44524fc2011-02-10 14:33:53 +0000515 neigh_node_free_ref(neigh_node);
Linus Lüssinge1a5382f2011-03-14 22:43:37 +0000516 if (router)
517 neigh_node_free_ref(router);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000518}
519
520/* checks whether the host restarted and is in the protection time.
521 * returns:
522 * 0 if the packet is to be accepted
523 * 1 if the packet is to be ignored.
524 */
525static int window_protected(struct bat_priv *bat_priv,
526 int32_t seq_num_diff,
527 unsigned long *last_reset)
528{
529 if ((seq_num_diff <= -TQ_LOCAL_WINDOW_SIZE)
530 || (seq_num_diff >= EXPECTED_SEQNO_RANGE)) {
531 if (time_after(jiffies, *last_reset +
532 msecs_to_jiffies(RESET_PROTECTION_MS))) {
533
534 *last_reset = jiffies;
535 bat_dbg(DBG_BATMAN, bat_priv,
536 "old packet received, start protection\n");
537
538 return 0;
539 } else
540 return 1;
541 }
542 return 0;
543}
544
545/* processes a batman packet for all interfaces, adjusts the sequence number and
546 * finds out whether it is a duplicate.
547 * returns:
548 * 1 the packet is a duplicate
549 * 0 the packet has not yet been received
550 * -1 the packet is old and has been received while the seqno window
551 * was protected. Caller should drop it.
552 */
David Howellsb2c44a52011-06-15 09:41:36 +0200553static int count_real_packets(const struct ethhdr *ethhdr,
Sven Eckelmann747e4222011-05-14 23:14:50 +0200554 const struct batman_packet *batman_packet,
555 const struct hard_iface *if_incoming)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000556{
557 struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
558 struct orig_node *orig_node;
559 struct neigh_node *tmp_neigh_node;
Marek Lindner9591a792010-12-12 21:57:11 +0000560 struct hlist_node *node;
David Howellsb2c44a52011-06-15 09:41:36 +0200561 int is_duplicate = 0;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000562 int32_t seq_diff;
563 int need_update = 0;
Marek Lindner0ede9f42011-01-25 21:52:10 +0000564 int set_mark, ret = -1;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000565
566 orig_node = get_orig_node(bat_priv, batman_packet->orig);
567 if (!orig_node)
568 return 0;
569
Marek Lindner0ede9f42011-01-25 21:52:10 +0000570 spin_lock_bh(&orig_node->ogm_cnt_lock);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000571 seq_diff = batman_packet->seqno - orig_node->last_real_seqno;
572
573 /* signalize caller that the packet is to be dropped. */
574 if (window_protected(bat_priv, seq_diff,
575 &orig_node->batman_seqno_reset))
Marek Lindner0ede9f42011-01-25 21:52:10 +0000576 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000577
Marek Lindnerf987ed62010-12-12 21:57:12 +0000578 rcu_read_lock();
579 hlist_for_each_entry_rcu(tmp_neigh_node, node,
580 &orig_node->neigh_list, list) {
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000581
582 is_duplicate |= get_bit_status(tmp_neigh_node->real_bits,
583 orig_node->last_real_seqno,
584 batman_packet->seqno);
585
Marek Lindner39901e72011-02-18 12:28:08 +0000586 if (compare_eth(tmp_neigh_node->addr, ethhdr->h_source) &&
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000587 (tmp_neigh_node->if_incoming == if_incoming))
588 set_mark = 1;
589 else
590 set_mark = 0;
591
592 /* if the window moved, set the update flag. */
593 need_update |= bit_get_packet(bat_priv,
594 tmp_neigh_node->real_bits,
595 seq_diff, set_mark);
596
597 tmp_neigh_node->real_packet_count =
598 bit_packet_count(tmp_neigh_node->real_bits);
599 }
Marek Lindnerf987ed62010-12-12 21:57:12 +0000600 rcu_read_unlock();
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000601
602 if (need_update) {
603 bat_dbg(DBG_BATMAN, bat_priv,
604 "updating last_seqno: old %d, new %d\n",
605 orig_node->last_real_seqno, batman_packet->seqno);
606 orig_node->last_real_seqno = batman_packet->seqno;
607 }
608
Marek Lindner0ede9f42011-01-25 21:52:10 +0000609 ret = is_duplicate;
Marek Lindner16b1aba2011-01-19 20:01:42 +0000610
Marek Lindner0ede9f42011-01-25 21:52:10 +0000611out:
612 spin_unlock_bh(&orig_node->ogm_cnt_lock);
Marek Lindner7b36e8e2011-02-18 12:28:10 +0000613 orig_node_free_ref(orig_node);
Marek Lindner0ede9f42011-01-25 21:52:10 +0000614 return ret;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000615}
616
Sven Eckelmann747e4222011-05-14 23:14:50 +0200617void receive_bat_packet(const struct ethhdr *ethhdr,
Simon Wunderlicha4c135c2011-01-19 20:01:43 +0000618 struct batman_packet *batman_packet,
Antonio Quartullia73105b2011-04-27 14:27:44 +0200619 const unsigned char *tt_buff,
Marek Lindnere6c10f42011-02-18 12:33:20 +0000620 struct hard_iface *if_incoming)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000621{
622 struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
Marek Lindnere6c10f42011-02-18 12:33:20 +0000623 struct hard_iface *hard_iface;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000624 struct orig_node *orig_neigh_node, *orig_node;
Linus Lüssinge1a5382f2011-03-14 22:43:37 +0000625 struct neigh_node *router = NULL, *router_router = NULL;
626 struct neigh_node *orig_neigh_router = NULL;
Sven Eckelmannb4e17052011-06-15 09:41:37 +0200627 int has_directlink_flag;
628 int is_my_addr = 0, is_my_orig = 0, is_my_oldorig = 0;
629 int is_broadcast = 0, is_bidirectional, is_single_hop_neigh;
David Howellsb2c44a52011-06-15 09:41:36 +0200630 int is_duplicate;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000631 uint32_t if_incoming_seqno;
632
633 /* Silently drop when the batman packet is actually not a
634 * correct packet.
635 *
636 * This might happen if a packet is padded (e.g. Ethernet has a
637 * minimum frame length of 64 byte) and the aggregation interprets
638 * it as an additional length.
639 *
640 * TODO: A more sane solution would be to have a bit in the
641 * batman_packet to detect whether the packet is the last
642 * packet in an aggregation. Here we expect that the padding
643 * is always zero (or not 0x01)
644 */
645 if (batman_packet->packet_type != BAT_PACKET)
646 return;
647
648 /* could be changed by schedule_own_packet() */
649 if_incoming_seqno = atomic_read(&if_incoming->seqno);
650
651 has_directlink_flag = (batman_packet->flags & DIRECTLINK ? 1 : 0);
652
Marek Lindner39901e72011-02-18 12:28:08 +0000653 is_single_hop_neigh = (compare_eth(ethhdr->h_source,
654 batman_packet->orig) ? 1 : 0);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000655
656 bat_dbg(DBG_BATMAN, bat_priv,
657 "Received BATMAN packet via NB: %pM, IF: %s [%pM] "
Antonio Quartullia73105b2011-04-27 14:27:44 +0200658 "(from OG: %pM, via prev OG: %pM, seqno %d, ttvn %u, "
659 "crc %u, changes %u, td %d, TTL %d, V %d, IDF %d)\n",
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000660 ethhdr->h_source, if_incoming->net_dev->name,
661 if_incoming->net_dev->dev_addr, batman_packet->orig,
662 batman_packet->prev_sender, batman_packet->seqno,
Antonio Quartullia73105b2011-04-27 14:27:44 +0200663 batman_packet->ttvn, batman_packet->tt_crc,
664 batman_packet->tt_num_changes, batman_packet->tq,
665 batman_packet->ttl, batman_packet->version,
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000666 has_directlink_flag);
667
668 rcu_read_lock();
Marek Lindnere6c10f42011-02-18 12:33:20 +0000669 list_for_each_entry_rcu(hard_iface, &hardif_list, list) {
670 if (hard_iface->if_status != IF_ACTIVE)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000671 continue;
672
Marek Lindnere6c10f42011-02-18 12:33:20 +0000673 if (hard_iface->soft_iface != if_incoming->soft_iface)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000674 continue;
675
Marek Lindner39901e72011-02-18 12:28:08 +0000676 if (compare_eth(ethhdr->h_source,
Marek Lindnere6c10f42011-02-18 12:33:20 +0000677 hard_iface->net_dev->dev_addr))
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000678 is_my_addr = 1;
679
Marek Lindner39901e72011-02-18 12:28:08 +0000680 if (compare_eth(batman_packet->orig,
Marek Lindnere6c10f42011-02-18 12:33:20 +0000681 hard_iface->net_dev->dev_addr))
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000682 is_my_orig = 1;
683
Marek Lindner39901e72011-02-18 12:28:08 +0000684 if (compare_eth(batman_packet->prev_sender,
Marek Lindnere6c10f42011-02-18 12:33:20 +0000685 hard_iface->net_dev->dev_addr))
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000686 is_my_oldorig = 1;
687
Antonio Quartulli44e92bc2011-05-21 01:33:07 +0200688 if (is_broadcast_ether_addr(ethhdr->h_source))
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000689 is_broadcast = 1;
690 }
691 rcu_read_unlock();
692
693 if (batman_packet->version != COMPAT_VERSION) {
694 bat_dbg(DBG_BATMAN, bat_priv,
695 "Drop packet: incompatible batman version (%i)\n",
696 batman_packet->version);
697 return;
698 }
699
700 if (is_my_addr) {
701 bat_dbg(DBG_BATMAN, bat_priv,
702 "Drop packet: received my own broadcast (sender: %pM"
703 ")\n",
704 ethhdr->h_source);
705 return;
706 }
707
708 if (is_broadcast) {
709 bat_dbg(DBG_BATMAN, bat_priv, "Drop packet: "
710 "ignoring all packets with broadcast source addr (sender: %pM"
711 ")\n", ethhdr->h_source);
712 return;
713 }
714
715 if (is_my_orig) {
716 unsigned long *word;
717 int offset;
718
719 orig_neigh_node = get_orig_node(bat_priv, ethhdr->h_source);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000720 if (!orig_neigh_node)
721 return;
722
723 /* neighbor has to indicate direct link and it has to
724 * come via the corresponding interface */
Daniele Furland1829fa2011-06-07 00:45:55 +0200725 /* save packet seqno for bidirectional check */
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000726 if (has_directlink_flag &&
Marek Lindner39901e72011-02-18 12:28:08 +0000727 compare_eth(if_incoming->net_dev->dev_addr,
Daniele Furland1829fa2011-06-07 00:45:55 +0200728 batman_packet->orig)) {
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000729 offset = if_incoming->if_num * NUM_WORDS;
Marek Lindner2ae2daf2011-01-19 20:01:42 +0000730
731 spin_lock_bh(&orig_neigh_node->ogm_cnt_lock);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000732 word = &(orig_neigh_node->bcast_own[offset]);
Daniele Furland1829fa2011-06-07 00:45:55 +0200733 bit_mark(word,
734 if_incoming_seqno - batman_packet->seqno - 2);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000735 orig_neigh_node->bcast_own_sum[if_incoming->if_num] =
736 bit_packet_count(word);
Marek Lindner2ae2daf2011-01-19 20:01:42 +0000737 spin_unlock_bh(&orig_neigh_node->ogm_cnt_lock);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000738 }
739
740 bat_dbg(DBG_BATMAN, bat_priv, "Drop packet: "
741 "originator packet from myself (via neighbor)\n");
Marek Lindner7b36e8e2011-02-18 12:28:10 +0000742 orig_node_free_ref(orig_neigh_node);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000743 return;
744 }
745
746 if (is_my_oldorig) {
747 bat_dbg(DBG_BATMAN, bat_priv,
748 "Drop packet: ignoring all rebroadcast echos (sender: "
749 "%pM)\n", ethhdr->h_source);
750 return;
751 }
752
753 orig_node = get_orig_node(bat_priv, batman_packet->orig);
754 if (!orig_node)
755 return;
756
757 is_duplicate = count_real_packets(ethhdr, batman_packet, if_incoming);
758
759 if (is_duplicate == -1) {
760 bat_dbg(DBG_BATMAN, bat_priv,
761 "Drop packet: packet within seqno protection time "
762 "(sender: %pM)\n", ethhdr->h_source);
Marek Lindner16b1aba2011-01-19 20:01:42 +0000763 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000764 }
765
766 if (batman_packet->tq == 0) {
767 bat_dbg(DBG_BATMAN, bat_priv,
768 "Drop packet: originator packet with tq equal 0\n");
Marek Lindner16b1aba2011-01-19 20:01:42 +0000769 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000770 }
771
Linus Lüssinge1a5382f2011-03-14 22:43:37 +0000772 router = orig_node_get_router(orig_node);
773 if (router)
774 router_router = orig_node_get_router(router->orig_node);
775
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000776 /* avoid temporary routing loops */
Linus Lüssinge1a5382f2011-03-14 22:43:37 +0000777 if (router && router_router &&
778 (compare_eth(router->addr, batman_packet->prev_sender)) &&
Marek Lindner39901e72011-02-18 12:28:08 +0000779 !(compare_eth(batman_packet->orig, batman_packet->prev_sender)) &&
Linus Lüssinge1a5382f2011-03-14 22:43:37 +0000780 (compare_eth(router->addr, router_router->addr))) {
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000781 bat_dbg(DBG_BATMAN, bat_priv,
782 "Drop packet: ignoring all rebroadcast packets that "
783 "may make me loop (sender: %pM)\n", ethhdr->h_source);
Marek Lindner16b1aba2011-01-19 20:01:42 +0000784 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000785 }
786
787 /* if sender is a direct neighbor the sender mac equals
788 * originator mac */
789 orig_neigh_node = (is_single_hop_neigh ?
790 orig_node :
791 get_orig_node(bat_priv, ethhdr->h_source));
792 if (!orig_neigh_node)
Marek Lindnerd0072602011-01-19 20:01:44 +0000793 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000794
Linus Lüssinge1a5382f2011-03-14 22:43:37 +0000795 orig_neigh_router = orig_node_get_router(orig_neigh_node);
796
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000797 /* drop packet if sender is not a direct neighbor and if we
798 * don't route towards it */
Linus Lüssinge1a5382f2011-03-14 22:43:37 +0000799 if (!is_single_hop_neigh && (!orig_neigh_router)) {
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000800 bat_dbg(DBG_BATMAN, bat_priv,
801 "Drop packet: OGM via unknown neighbor!\n");
Marek Lindner16b1aba2011-01-19 20:01:42 +0000802 goto out_neigh;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000803 }
804
805 is_bidirectional = is_bidirectional_neigh(orig_node, orig_neigh_node,
806 batman_packet, if_incoming);
807
Simon Wunderlicha4c135c2011-01-19 20:01:43 +0000808 bonding_save_primary(orig_node, orig_neigh_node, batman_packet);
809
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000810 /* update ranking if it is not a duplicate or has the same
811 * seqno and similar ttl as the non-duplicate */
812 if (is_bidirectional &&
813 (!is_duplicate ||
814 ((orig_node->last_real_seqno == batman_packet->seqno) &&
815 (orig_node->last_ttl - 3 <= batman_packet->ttl))))
816 update_orig(bat_priv, orig_node, ethhdr, batman_packet,
Antonio Quartullia73105b2011-04-27 14:27:44 +0200817 if_incoming, tt_buff, is_duplicate);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000818
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000819 /* is single hop (direct) neighbor */
820 if (is_single_hop_neigh) {
821
822 /* mark direct link on incoming interface */
823 schedule_forward_packet(orig_node, ethhdr, batman_packet,
Antonio Quartullia73105b2011-04-27 14:27:44 +0200824 1, if_incoming);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000825
826 bat_dbg(DBG_BATMAN, bat_priv, "Forwarding packet: "
827 "rebroadcast neighbor packet with direct link flag\n");
Marek Lindner16b1aba2011-01-19 20:01:42 +0000828 goto out_neigh;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000829 }
830
831 /* multihop originator */
832 if (!is_bidirectional) {
833 bat_dbg(DBG_BATMAN, bat_priv,
834 "Drop packet: not received via bidirectional link\n");
Marek Lindner16b1aba2011-01-19 20:01:42 +0000835 goto out_neigh;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000836 }
837
838 if (is_duplicate) {
839 bat_dbg(DBG_BATMAN, bat_priv,
840 "Drop packet: duplicate packet received\n");
Marek Lindner16b1aba2011-01-19 20:01:42 +0000841 goto out_neigh;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000842 }
843
844 bat_dbg(DBG_BATMAN, bat_priv,
845 "Forwarding packet: rebroadcast originator packet\n");
846 schedule_forward_packet(orig_node, ethhdr, batman_packet,
Antonio Quartullia73105b2011-04-27 14:27:44 +0200847 0, if_incoming);
Marek Lindner16b1aba2011-01-19 20:01:42 +0000848
849out_neigh:
Marek Lindner7b36e8e2011-02-18 12:28:10 +0000850 if ((orig_neigh_node) && (!is_single_hop_neigh))
851 orig_node_free_ref(orig_neigh_node);
Marek Lindner16b1aba2011-01-19 20:01:42 +0000852out:
Linus Lüssinge1a5382f2011-03-14 22:43:37 +0000853 if (router)
854 neigh_node_free_ref(router);
855 if (router_router)
856 neigh_node_free_ref(router_router);
857 if (orig_neigh_router)
858 neigh_node_free_ref(orig_neigh_router);
859
Marek Lindner7b36e8e2011-02-18 12:28:10 +0000860 orig_node_free_ref(orig_node);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000861}
862
Marek Lindnere6c10f42011-02-18 12:33:20 +0000863int recv_bat_packet(struct sk_buff *skb, struct hard_iface *hard_iface)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000864{
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000865 struct ethhdr *ethhdr;
866
867 /* drop packet if it has not necessary minimum size */
868 if (unlikely(!pskb_may_pull(skb, sizeof(struct batman_packet))))
869 return NET_RX_DROP;
870
871 ethhdr = (struct ethhdr *)skb_mac_header(skb);
872
873 /* packet with broadcast indication but unicast recipient */
874 if (!is_broadcast_ether_addr(ethhdr->h_dest))
875 return NET_RX_DROP;
876
877 /* packet with broadcast sender address */
878 if (is_broadcast_ether_addr(ethhdr->h_source))
879 return NET_RX_DROP;
880
881 /* create a copy of the skb, if needed, to modify it. */
882 if (skb_cow(skb, 0) < 0)
883 return NET_RX_DROP;
884
885 /* keep skb linear */
886 if (skb_linearize(skb) < 0)
887 return NET_RX_DROP;
888
889 ethhdr = (struct ethhdr *)skb_mac_header(skb);
890
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000891 receive_aggr_bat_packet(ethhdr,
892 skb->data,
893 skb_headlen(skb),
Marek Lindnere6c10f42011-02-18 12:33:20 +0000894 hard_iface);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000895
896 kfree_skb(skb);
897 return NET_RX_SUCCESS;
898}
899
900static int recv_my_icmp_packet(struct bat_priv *bat_priv,
901 struct sk_buff *skb, size_t icmp_len)
902{
Marek Lindner32ae9b22011-04-20 15:40:58 +0200903 struct hard_iface *primary_if = NULL;
Marek Lindner44524fc2011-02-10 14:33:53 +0000904 struct orig_node *orig_node = NULL;
Linus Lüssinge1a5382f2011-03-14 22:43:37 +0000905 struct neigh_node *router = NULL;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000906 struct icmp_packet_rr *icmp_packet;
Marek Lindner44524fc2011-02-10 14:33:53 +0000907 int ret = NET_RX_DROP;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000908
909 icmp_packet = (struct icmp_packet_rr *)skb->data;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000910
911 /* add data to device queue */
912 if (icmp_packet->msg_type != ECHO_REQUEST) {
913 bat_socket_receive_packet(icmp_packet, icmp_len);
Marek Lindner44524fc2011-02-10 14:33:53 +0000914 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000915 }
916
Marek Lindner32ae9b22011-04-20 15:40:58 +0200917 primary_if = primary_if_get_selected(bat_priv);
918 if (!primary_if)
Marek Lindner44524fc2011-02-10 14:33:53 +0000919 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000920
921 /* answer echo request (ping) */
922 /* get routing information */
Marek Lindner7aadf882011-02-18 12:28:09 +0000923 orig_node = orig_hash_find(bat_priv, icmp_packet->orig);
Marek Lindner44524fc2011-02-10 14:33:53 +0000924 if (!orig_node)
Linus Lüssinge1a5382f2011-03-14 22:43:37 +0000925 goto out;
Marek Lindner44524fc2011-02-10 14:33:53 +0000926
Linus Lüssinge1a5382f2011-03-14 22:43:37 +0000927 router = orig_node_get_router(orig_node);
928 if (!router)
929 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000930
Marek Lindner44524fc2011-02-10 14:33:53 +0000931 /* create a copy of the skb, if needed, to modify it. */
932 if (skb_cow(skb, sizeof(struct ethhdr)) < 0)
933 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000934
Marek Lindner44524fc2011-02-10 14:33:53 +0000935 icmp_packet = (struct icmp_packet_rr *)skb->data;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000936
Marek Lindner44524fc2011-02-10 14:33:53 +0000937 memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN);
Marek Lindner32ae9b22011-04-20 15:40:58 +0200938 memcpy(icmp_packet->orig, primary_if->net_dev->dev_addr, ETH_ALEN);
Marek Lindner44524fc2011-02-10 14:33:53 +0000939 icmp_packet->msg_type = ECHO_REPLY;
940 icmp_packet->ttl = TTL;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000941
Linus Lüssinge1a5382f2011-03-14 22:43:37 +0000942 send_skb_packet(skb, router->if_incoming, router->addr);
Marek Lindner44524fc2011-02-10 14:33:53 +0000943 ret = NET_RX_SUCCESS;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000944
Marek Lindner44524fc2011-02-10 14:33:53 +0000945out:
Marek Lindner32ae9b22011-04-20 15:40:58 +0200946 if (primary_if)
947 hardif_free_ref(primary_if);
Linus Lüssinge1a5382f2011-03-14 22:43:37 +0000948 if (router)
949 neigh_node_free_ref(router);
Marek Lindner44524fc2011-02-10 14:33:53 +0000950 if (orig_node)
Marek Lindner7b36e8e2011-02-18 12:28:10 +0000951 orig_node_free_ref(orig_node);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000952 return ret;
953}
954
955static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv,
Simon Wunderlich74ef1152010-12-29 16:15:19 +0000956 struct sk_buff *skb)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000957{
Marek Lindner32ae9b22011-04-20 15:40:58 +0200958 struct hard_iface *primary_if = NULL;
Marek Lindner44524fc2011-02-10 14:33:53 +0000959 struct orig_node *orig_node = NULL;
Linus Lüssinge1a5382f2011-03-14 22:43:37 +0000960 struct neigh_node *router = NULL;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000961 struct icmp_packet *icmp_packet;
Marek Lindner44524fc2011-02-10 14:33:53 +0000962 int ret = NET_RX_DROP;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000963
964 icmp_packet = (struct icmp_packet *)skb->data;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000965
966 /* send TTL exceeded if packet is an echo request (traceroute) */
967 if (icmp_packet->msg_type != ECHO_REQUEST) {
968 pr_debug("Warning - can't forward icmp packet from %pM to "
969 "%pM: ttl exceeded\n", icmp_packet->orig,
970 icmp_packet->dst);
Marek Lindner44524fc2011-02-10 14:33:53 +0000971 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000972 }
973
Marek Lindner32ae9b22011-04-20 15:40:58 +0200974 primary_if = primary_if_get_selected(bat_priv);
975 if (!primary_if)
Marek Lindner44524fc2011-02-10 14:33:53 +0000976 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000977
978 /* get routing information */
Marek Lindner7aadf882011-02-18 12:28:09 +0000979 orig_node = orig_hash_find(bat_priv, icmp_packet->orig);
Marek Lindner44524fc2011-02-10 14:33:53 +0000980 if (!orig_node)
Linus Lüssinge1a5382f2011-03-14 22:43:37 +0000981 goto out;
Marek Lindner44524fc2011-02-10 14:33:53 +0000982
Linus Lüssinge1a5382f2011-03-14 22:43:37 +0000983 router = orig_node_get_router(orig_node);
984 if (!router)
985 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000986
Marek Lindner44524fc2011-02-10 14:33:53 +0000987 /* create a copy of the skb, if needed, to modify it. */
988 if (skb_cow(skb, sizeof(struct ethhdr)) < 0)
989 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000990
Marek Lindner44524fc2011-02-10 14:33:53 +0000991 icmp_packet = (struct icmp_packet *)skb->data;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000992
Marek Lindner44524fc2011-02-10 14:33:53 +0000993 memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN);
Marek Lindner32ae9b22011-04-20 15:40:58 +0200994 memcpy(icmp_packet->orig, primary_if->net_dev->dev_addr, ETH_ALEN);
Marek Lindner44524fc2011-02-10 14:33:53 +0000995 icmp_packet->msg_type = TTL_EXCEEDED;
996 icmp_packet->ttl = TTL;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000997
Linus Lüssinge1a5382f2011-03-14 22:43:37 +0000998 send_skb_packet(skb, router->if_incoming, router->addr);
Marek Lindner44524fc2011-02-10 14:33:53 +0000999 ret = NET_RX_SUCCESS;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001000
Marek Lindner44524fc2011-02-10 14:33:53 +00001001out:
Marek Lindner32ae9b22011-04-20 15:40:58 +02001002 if (primary_if)
1003 hardif_free_ref(primary_if);
Linus Lüssinge1a5382f2011-03-14 22:43:37 +00001004 if (router)
1005 neigh_node_free_ref(router);
Marek Lindner44524fc2011-02-10 14:33:53 +00001006 if (orig_node)
Marek Lindner7b36e8e2011-02-18 12:28:10 +00001007 orig_node_free_ref(orig_node);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001008 return ret;
1009}
1010
1011
Marek Lindnere6c10f42011-02-18 12:33:20 +00001012int recv_icmp_packet(struct sk_buff *skb, struct hard_iface *recv_if)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001013{
1014 struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface);
1015 struct icmp_packet_rr *icmp_packet;
1016 struct ethhdr *ethhdr;
Marek Lindner44524fc2011-02-10 14:33:53 +00001017 struct orig_node *orig_node = NULL;
Linus Lüssinge1a5382f2011-03-14 22:43:37 +00001018 struct neigh_node *router = NULL;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001019 int hdr_size = sizeof(struct icmp_packet);
Marek Lindner44524fc2011-02-10 14:33:53 +00001020 int ret = NET_RX_DROP;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001021
1022 /**
1023 * we truncate all incoming icmp packets if they don't match our size
1024 */
1025 if (skb->len >= sizeof(struct icmp_packet_rr))
1026 hdr_size = sizeof(struct icmp_packet_rr);
1027
1028 /* drop packet if it has not necessary minimum size */
1029 if (unlikely(!pskb_may_pull(skb, hdr_size)))
Marek Lindner44524fc2011-02-10 14:33:53 +00001030 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001031
1032 ethhdr = (struct ethhdr *)skb_mac_header(skb);
1033
1034 /* packet with unicast indication but broadcast recipient */
1035 if (is_broadcast_ether_addr(ethhdr->h_dest))
Marek Lindner44524fc2011-02-10 14:33:53 +00001036 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001037
1038 /* packet with broadcast sender address */
1039 if (is_broadcast_ether_addr(ethhdr->h_source))
Marek Lindner44524fc2011-02-10 14:33:53 +00001040 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001041
1042 /* not for me */
1043 if (!is_my_mac(ethhdr->h_dest))
Marek Lindner44524fc2011-02-10 14:33:53 +00001044 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001045
1046 icmp_packet = (struct icmp_packet_rr *)skb->data;
1047
1048 /* add record route information if not full */
1049 if ((hdr_size == sizeof(struct icmp_packet_rr)) &&
1050 (icmp_packet->rr_cur < BAT_RR_LEN)) {
1051 memcpy(&(icmp_packet->rr[icmp_packet->rr_cur]),
1052 ethhdr->h_dest, ETH_ALEN);
1053 icmp_packet->rr_cur++;
1054 }
1055
1056 /* packet for me */
1057 if (is_my_mac(icmp_packet->dst))
1058 return recv_my_icmp_packet(bat_priv, skb, hdr_size);
1059
1060 /* TTL exceeded */
1061 if (icmp_packet->ttl < 2)
Simon Wunderlich74ef1152010-12-29 16:15:19 +00001062 return recv_icmp_ttl_exceeded(bat_priv, skb);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001063
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001064 /* get routing information */
Marek Lindner7aadf882011-02-18 12:28:09 +00001065 orig_node = orig_hash_find(bat_priv, icmp_packet->dst);
Marek Lindner44524fc2011-02-10 14:33:53 +00001066 if (!orig_node)
Linus Lüssinge1a5382f2011-03-14 22:43:37 +00001067 goto out;
Marek Lindner44524fc2011-02-10 14:33:53 +00001068
Linus Lüssinge1a5382f2011-03-14 22:43:37 +00001069 router = orig_node_get_router(orig_node);
1070 if (!router)
1071 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001072
Marek Lindner44524fc2011-02-10 14:33:53 +00001073 /* create a copy of the skb, if needed, to modify it. */
1074 if (skb_cow(skb, sizeof(struct ethhdr)) < 0)
1075 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001076
Marek Lindner44524fc2011-02-10 14:33:53 +00001077 icmp_packet = (struct icmp_packet_rr *)skb->data;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001078
Marek Lindner44524fc2011-02-10 14:33:53 +00001079 /* decrement ttl */
1080 icmp_packet->ttl--;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001081
Marek Lindner44524fc2011-02-10 14:33:53 +00001082 /* route it */
Linus Lüssinge1a5382f2011-03-14 22:43:37 +00001083 send_skb_packet(skb, router->if_incoming, router->addr);
Marek Lindner44524fc2011-02-10 14:33:53 +00001084 ret = NET_RX_SUCCESS;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001085
Marek Lindner44524fc2011-02-10 14:33:53 +00001086out:
Linus Lüssinge1a5382f2011-03-14 22:43:37 +00001087 if (router)
1088 neigh_node_free_ref(router);
Marek Lindner44524fc2011-02-10 14:33:53 +00001089 if (orig_node)
Marek Lindner7b36e8e2011-02-18 12:28:10 +00001090 orig_node_free_ref(orig_node);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001091 return ret;
1092}
1093
Linus Lüssing55158622011-03-14 22:43:27 +00001094/* In the bonding case, send the packets in a round
1095 * robin fashion over the remaining interfaces.
1096 *
1097 * This method rotates the bonding list and increases the
1098 * returned router's refcount. */
1099static struct neigh_node *find_bond_router(struct orig_node *primary_orig,
Sven Eckelmann747e4222011-05-14 23:14:50 +02001100 const struct hard_iface *recv_if)
Linus Lüssing55158622011-03-14 22:43:27 +00001101{
1102 struct neigh_node *tmp_neigh_node;
1103 struct neigh_node *router = NULL, *first_candidate = NULL;
1104
1105 rcu_read_lock();
1106 list_for_each_entry_rcu(tmp_neigh_node, &primary_orig->bond_list,
1107 bonding_list) {
1108 if (!first_candidate)
1109 first_candidate = tmp_neigh_node;
1110
1111 /* recv_if == NULL on the first node. */
1112 if (tmp_neigh_node->if_incoming == recv_if)
1113 continue;
1114
1115 if (!atomic_inc_not_zero(&tmp_neigh_node->refcount))
1116 continue;
1117
1118 router = tmp_neigh_node;
1119 break;
1120 }
1121
1122 /* use the first candidate if nothing was found. */
1123 if (!router && first_candidate &&
1124 atomic_inc_not_zero(&first_candidate->refcount))
1125 router = first_candidate;
1126
1127 if (!router)
1128 goto out;
1129
1130 /* selected should point to the next element
1131 * after the current router */
1132 spin_lock_bh(&primary_orig->neigh_list_lock);
1133 /* this is a list_move(), which unfortunately
1134 * does not exist as rcu version */
1135 list_del_rcu(&primary_orig->bond_list);
1136 list_add_rcu(&primary_orig->bond_list,
1137 &router->bonding_list);
1138 spin_unlock_bh(&primary_orig->neigh_list_lock);
1139
1140out:
1141 rcu_read_unlock();
1142 return router;
1143}
1144
1145/* Interface Alternating: Use the best of the
1146 * remaining candidates which are not using
1147 * this interface.
1148 *
1149 * Increases the returned router's refcount */
1150static struct neigh_node *find_ifalter_router(struct orig_node *primary_orig,
Sven Eckelmann747e4222011-05-14 23:14:50 +02001151 const struct hard_iface *recv_if)
Linus Lüssing55158622011-03-14 22:43:27 +00001152{
1153 struct neigh_node *tmp_neigh_node;
1154 struct neigh_node *router = NULL, *first_candidate = NULL;
1155
1156 rcu_read_lock();
1157 list_for_each_entry_rcu(tmp_neigh_node, &primary_orig->bond_list,
1158 bonding_list) {
1159 if (!first_candidate)
1160 first_candidate = tmp_neigh_node;
1161
1162 /* recv_if == NULL on the first node. */
1163 if (tmp_neigh_node->if_incoming == recv_if)
1164 continue;
1165
1166 if (!atomic_inc_not_zero(&tmp_neigh_node->refcount))
1167 continue;
1168
1169 /* if we don't have a router yet
1170 * or this one is better, choose it. */
1171 if ((!router) ||
1172 (tmp_neigh_node->tq_avg > router->tq_avg)) {
1173 /* decrement refcount of
1174 * previously selected router */
1175 if (router)
1176 neigh_node_free_ref(router);
1177
1178 router = tmp_neigh_node;
1179 atomic_inc_not_zero(&router->refcount);
1180 }
1181
1182 neigh_node_free_ref(tmp_neigh_node);
1183 }
1184
1185 /* use the first candidate if nothing was found. */
1186 if (!router && first_candidate &&
1187 atomic_inc_not_zero(&first_candidate->refcount))
1188 router = first_candidate;
1189
1190 rcu_read_unlock();
1191 return router;
1192}
1193
Antonio Quartullia73105b2011-04-27 14:27:44 +02001194int recv_tt_query(struct sk_buff *skb, struct hard_iface *recv_if)
1195{
1196 struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface);
1197 struct tt_query_packet *tt_query;
1198 struct ethhdr *ethhdr;
1199
1200 /* drop packet if it has not necessary minimum size */
1201 if (unlikely(!pskb_may_pull(skb, sizeof(struct tt_query_packet))))
1202 goto out;
1203
1204 /* I could need to modify it */
1205 if (skb_cow(skb, sizeof(struct tt_query_packet)) < 0)
1206 goto out;
1207
1208 ethhdr = (struct ethhdr *)skb_mac_header(skb);
1209
1210 /* packet with unicast indication but broadcast recipient */
1211 if (is_broadcast_ether_addr(ethhdr->h_dest))
1212 goto out;
1213
1214 /* packet with broadcast sender address */
1215 if (is_broadcast_ether_addr(ethhdr->h_source))
1216 goto out;
1217
1218 tt_query = (struct tt_query_packet *)skb->data;
1219
1220 tt_query->tt_data = ntohs(tt_query->tt_data);
1221
1222 switch (tt_query->flags & TT_QUERY_TYPE_MASK) {
1223 case TT_REQUEST:
1224 /* If we cannot provide an answer the tt_request is
1225 * forwarded */
1226 if (!send_tt_response(bat_priv, tt_query)) {
1227 bat_dbg(DBG_TT, bat_priv,
1228 "Routing TT_REQUEST to %pM [%c]\n",
1229 tt_query->dst,
1230 (tt_query->flags & TT_FULL_TABLE ? 'F' : '.'));
1231 tt_query->tt_data = htons(tt_query->tt_data);
1232 return route_unicast_packet(skb, recv_if);
1233 }
1234 break;
1235 case TT_RESPONSE:
1236 /* packet needs to be linearised to access the TT changes */
1237 if (skb_linearize(skb) < 0)
1238 goto out;
1239
1240 if (is_my_mac(tt_query->dst))
1241 handle_tt_response(bat_priv, tt_query);
1242 else {
1243 bat_dbg(DBG_TT, bat_priv,
1244 "Routing TT_RESPONSE to %pM [%c]\n",
1245 tt_query->dst,
1246 (tt_query->flags & TT_FULL_TABLE ? 'F' : '.'));
1247 tt_query->tt_data = htons(tt_query->tt_data);
1248 return route_unicast_packet(skb, recv_if);
1249 }
1250 break;
1251 }
1252
1253out:
1254 /* returning NET_RX_DROP will make the caller function kfree the skb */
1255 return NET_RX_DROP;
1256}
1257
Antonio Quartullicc47f662011-04-27 14:27:57 +02001258int recv_roam_adv(struct sk_buff *skb, struct hard_iface *recv_if)
1259{
1260 struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface);
1261 struct roam_adv_packet *roam_adv_packet;
1262 struct orig_node *orig_node;
1263 struct ethhdr *ethhdr;
1264
1265 /* drop packet if it has not necessary minimum size */
1266 if (unlikely(!pskb_may_pull(skb, sizeof(struct roam_adv_packet))))
1267 goto out;
1268
1269 ethhdr = (struct ethhdr *)skb_mac_header(skb);
1270
1271 /* packet with unicast indication but broadcast recipient */
1272 if (is_broadcast_ether_addr(ethhdr->h_dest))
1273 goto out;
1274
1275 /* packet with broadcast sender address */
1276 if (is_broadcast_ether_addr(ethhdr->h_source))
1277 goto out;
1278
1279 roam_adv_packet = (struct roam_adv_packet *)skb->data;
1280
1281 if (!is_my_mac(roam_adv_packet->dst))
1282 return route_unicast_packet(skb, recv_if);
1283
1284 orig_node = orig_hash_find(bat_priv, roam_adv_packet->src);
1285 if (!orig_node)
1286 goto out;
1287
1288 bat_dbg(DBG_TT, bat_priv, "Received ROAMING_ADV from %pM "
1289 "(client %pM)\n", roam_adv_packet->src,
1290 roam_adv_packet->client);
1291
1292 tt_global_add(bat_priv, orig_node, roam_adv_packet->client,
1293 atomic_read(&orig_node->last_ttvn) + 1, true);
1294
1295 /* Roaming phase starts: I have new information but the ttvn has not
1296 * been incremented yet. This flag will make me check all the incoming
1297 * packets for the correct destination. */
1298 bat_priv->tt_poss_change = true;
1299
1300 orig_node_free_ref(orig_node);
1301out:
1302 /* returning NET_RX_DROP will make the caller function kfree the skb */
1303 return NET_RX_DROP;
1304}
1305
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001306/* find a suitable router for this originator, and use
Simon Wunderlicha4c135c2011-01-19 20:01:43 +00001307 * bonding if possible. increases the found neighbors
1308 * refcount.*/
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001309struct neigh_node *find_router(struct bat_priv *bat_priv,
1310 struct orig_node *orig_node,
Sven Eckelmann747e4222011-05-14 23:14:50 +02001311 const struct hard_iface *recv_if)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001312{
1313 struct orig_node *primary_orig_node;
1314 struct orig_node *router_orig;
Linus Lüssing55158622011-03-14 22:43:27 +00001315 struct neigh_node *router;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001316 static uint8_t zero_mac[ETH_ALEN] = {0, 0, 0, 0, 0, 0};
1317 int bonding_enabled;
1318
1319 if (!orig_node)
1320 return NULL;
1321
Linus Lüssinge1a5382f2011-03-14 22:43:37 +00001322 router = orig_node_get_router(orig_node);
1323 if (!router)
Marek Lindner01df2b62011-05-05 14:14:46 +02001324 goto err;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001325
1326 /* without bonding, the first node should
1327 * always choose the default router. */
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001328 bonding_enabled = atomic_read(&bat_priv->bonding);
1329
Simon Wunderlicha4c135c2011-01-19 20:01:43 +00001330 rcu_read_lock();
1331 /* select default router to output */
Linus Lüssinge1a5382f2011-03-14 22:43:37 +00001332 router_orig = router->orig_node;
Marek Lindner01df2b62011-05-05 14:14:46 +02001333 if (!router_orig)
1334 goto err_unlock;
Simon Wunderlicha4c135c2011-01-19 20:01:43 +00001335
Simon Wunderlicha4c135c2011-01-19 20:01:43 +00001336 if ((!recv_if) && (!bonding_enabled))
1337 goto return_router;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001338
1339 /* if we have something in the primary_addr, we can search
1340 * for a potential bonding candidate. */
Marek Lindner39901e72011-02-18 12:28:08 +00001341 if (compare_eth(router_orig->primary_addr, zero_mac))
Simon Wunderlicha4c135c2011-01-19 20:01:43 +00001342 goto return_router;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001343
1344 /* find the orig_node which has the primary interface. might
1345 * even be the same as our router_orig in many cases */
1346
Marek Lindner39901e72011-02-18 12:28:08 +00001347 if (compare_eth(router_orig->primary_addr, router_orig->orig)) {
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001348 primary_orig_node = router_orig;
1349 } else {
Marek Lindner7aadf882011-02-18 12:28:09 +00001350 primary_orig_node = orig_hash_find(bat_priv,
1351 router_orig->primary_addr);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001352 if (!primary_orig_node)
Simon Wunderlicha4c135c2011-01-19 20:01:43 +00001353 goto return_router;
Marek Lindner7aadf882011-02-18 12:28:09 +00001354
Marek Lindner7b36e8e2011-02-18 12:28:10 +00001355 orig_node_free_ref(primary_orig_node);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001356 }
1357
1358 /* with less than 2 candidates, we can't do any
1359 * bonding and prefer the original router. */
Simon Wunderlicha4c135c2011-01-19 20:01:43 +00001360 if (atomic_read(&primary_orig_node->bond_candidates) < 2)
1361 goto return_router;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001362
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001363 /* all nodes between should choose a candidate which
1364 * is is not on the interface where the packet came
1365 * in. */
Simon Wunderlicha4c135c2011-01-19 20:01:43 +00001366
Marek Lindner44524fc2011-02-10 14:33:53 +00001367 neigh_node_free_ref(router);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001368
Linus Lüssing55158622011-03-14 22:43:27 +00001369 if (bonding_enabled)
1370 router = find_bond_router(primary_orig_node, recv_if);
1371 else
1372 router = find_ifalter_router(primary_orig_node, recv_if);
Simon Wunderlicha4c135c2011-01-19 20:01:43 +00001373
Simon Wunderlicha4c135c2011-01-19 20:01:43 +00001374return_router:
Antonio Quartullie2cbc112011-05-08 20:52:57 +02001375 if (router && router->if_incoming->if_status != IF_ACTIVE)
1376 goto err_unlock;
1377
Simon Wunderlicha4c135c2011-01-19 20:01:43 +00001378 rcu_read_unlock();
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001379 return router;
Marek Lindner01df2b62011-05-05 14:14:46 +02001380err_unlock:
1381 rcu_read_unlock();
1382err:
1383 if (router)
1384 neigh_node_free_ref(router);
1385 return NULL;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001386}
1387
1388static int check_unicast_packet(struct sk_buff *skb, int hdr_size)
1389{
1390 struct ethhdr *ethhdr;
1391
1392 /* drop packet if it has not necessary minimum size */
1393 if (unlikely(!pskb_may_pull(skb, hdr_size)))
1394 return -1;
1395
1396 ethhdr = (struct ethhdr *)skb_mac_header(skb);
1397
1398 /* packet with unicast indication but broadcast recipient */
1399 if (is_broadcast_ether_addr(ethhdr->h_dest))
1400 return -1;
1401
1402 /* packet with broadcast sender address */
1403 if (is_broadcast_ether_addr(ethhdr->h_source))
1404 return -1;
1405
1406 /* not for me */
1407 if (!is_my_mac(ethhdr->h_dest))
1408 return -1;
1409
1410 return 0;
1411}
1412
Linus Lüssing7cefb142011-03-02 17:39:31 +00001413int route_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001414{
1415 struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface);
Marek Lindner44524fc2011-02-10 14:33:53 +00001416 struct orig_node *orig_node = NULL;
1417 struct neigh_node *neigh_node = NULL;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001418 struct unicast_packet *unicast_packet;
1419 struct ethhdr *ethhdr = (struct ethhdr *)skb_mac_header(skb);
Marek Lindner44524fc2011-02-10 14:33:53 +00001420 int ret = NET_RX_DROP;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001421 struct sk_buff *new_skb;
1422
1423 unicast_packet = (struct unicast_packet *)skb->data;
1424
1425 /* TTL exceeded */
1426 if (unicast_packet->ttl < 2) {
1427 pr_debug("Warning - can't forward unicast packet from %pM to "
1428 "%pM: ttl exceeded\n", ethhdr->h_source,
1429 unicast_packet->dest);
Marek Lindner44524fc2011-02-10 14:33:53 +00001430 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001431 }
1432
1433 /* get routing information */
Marek Lindner7aadf882011-02-18 12:28:09 +00001434 orig_node = orig_hash_find(bat_priv, unicast_packet->dest);
1435
Marek Lindner44524fc2011-02-10 14:33:53 +00001436 if (!orig_node)
Antonio Quartullib5a6f692011-04-16 11:30:57 +02001437 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001438
Simon Wunderlicha4c135c2011-01-19 20:01:43 +00001439 /* find_router() increases neigh_nodes refcount if found. */
Marek Lindner44524fc2011-02-10 14:33:53 +00001440 neigh_node = find_router(bat_priv, orig_node, recv_if);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001441
Marek Lindnerd0072602011-01-19 20:01:44 +00001442 if (!neigh_node)
Marek Lindner44524fc2011-02-10 14:33:53 +00001443 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001444
1445 /* create a copy of the skb, if needed, to modify it. */
1446 if (skb_cow(skb, sizeof(struct ethhdr)) < 0)
Marek Lindner44524fc2011-02-10 14:33:53 +00001447 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001448
1449 unicast_packet = (struct unicast_packet *)skb->data;
1450
1451 if (unicast_packet->packet_type == BAT_UNICAST &&
1452 atomic_read(&bat_priv->fragmentation) &&
Marek Lindnerd0072602011-01-19 20:01:44 +00001453 skb->len > neigh_node->if_incoming->net_dev->mtu) {
1454 ret = frag_send_skb(skb, bat_priv,
1455 neigh_node->if_incoming, neigh_node->addr);
1456 goto out;
1457 }
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001458
1459 if (unicast_packet->packet_type == BAT_UNICAST_FRAG &&
Marek Lindnerd0072602011-01-19 20:01:44 +00001460 frag_can_reassemble(skb, neigh_node->if_incoming->net_dev->mtu)) {
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001461
1462 ret = frag_reassemble_skb(skb, bat_priv, &new_skb);
1463
1464 if (ret == NET_RX_DROP)
Marek Lindner44524fc2011-02-10 14:33:53 +00001465 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001466
1467 /* packet was buffered for late merge */
Marek Lindner44524fc2011-02-10 14:33:53 +00001468 if (!new_skb) {
1469 ret = NET_RX_SUCCESS;
1470 goto out;
1471 }
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001472
1473 skb = new_skb;
1474 unicast_packet = (struct unicast_packet *)skb->data;
1475 }
1476
1477 /* decrement ttl */
1478 unicast_packet->ttl--;
1479
1480 /* route it */
Marek Lindnerd0072602011-01-19 20:01:44 +00001481 send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
Marek Lindner44524fc2011-02-10 14:33:53 +00001482 ret = NET_RX_SUCCESS;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001483
Marek Lindner44524fc2011-02-10 14:33:53 +00001484out:
1485 if (neigh_node)
1486 neigh_node_free_ref(neigh_node);
1487 if (orig_node)
Marek Lindner7b36e8e2011-02-18 12:28:10 +00001488 orig_node_free_ref(orig_node);
Marek Lindner44524fc2011-02-10 14:33:53 +00001489 return ret;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001490}
1491
Antonio Quartullia73105b2011-04-27 14:27:44 +02001492static int check_unicast_ttvn(struct bat_priv *bat_priv,
1493 struct sk_buff *skb) {
1494 uint8_t curr_ttvn;
1495 struct orig_node *orig_node;
1496 struct ethhdr *ethhdr;
1497 struct hard_iface *primary_if;
1498 struct unicast_packet *unicast_packet;
Antonio Quartullicc47f662011-04-27 14:27:57 +02001499 bool tt_poss_change;
Antonio Quartullia73105b2011-04-27 14:27:44 +02001500
1501 /* I could need to modify it */
1502 if (skb_cow(skb, sizeof(struct unicast_packet)) < 0)
1503 return 0;
1504
1505 unicast_packet = (struct unicast_packet *)skb->data;
1506
Antonio Quartullicc47f662011-04-27 14:27:57 +02001507 if (is_my_mac(unicast_packet->dest)) {
1508 tt_poss_change = bat_priv->tt_poss_change;
Antonio Quartullia73105b2011-04-27 14:27:44 +02001509 curr_ttvn = (uint8_t)atomic_read(&bat_priv->ttvn);
Antonio Quartullicc47f662011-04-27 14:27:57 +02001510 } else {
Antonio Quartullia73105b2011-04-27 14:27:44 +02001511 orig_node = orig_hash_find(bat_priv, unicast_packet->dest);
1512
1513 if (!orig_node)
1514 return 0;
1515
1516 curr_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn);
Antonio Quartullicc47f662011-04-27 14:27:57 +02001517 tt_poss_change = orig_node->tt_poss_change;
Antonio Quartullia73105b2011-04-27 14:27:44 +02001518 orig_node_free_ref(orig_node);
1519 }
1520
1521 /* Check whether I have to reroute the packet */
Antonio Quartullicc47f662011-04-27 14:27:57 +02001522 if (seq_before(unicast_packet->ttvn, curr_ttvn) || tt_poss_change) {
Antonio Quartullia73105b2011-04-27 14:27:44 +02001523 /* Linearize the skb before accessing it */
1524 if (skb_linearize(skb) < 0)
1525 return 0;
1526
1527 ethhdr = (struct ethhdr *)(skb->data +
1528 sizeof(struct unicast_packet));
Antonio Quartullia73105b2011-04-27 14:27:44 +02001529 orig_node = transtable_search(bat_priv, ethhdr->h_dest);
1530
1531 if (!orig_node) {
1532 if (!is_my_client(bat_priv, ethhdr->h_dest))
1533 return 0;
1534 primary_if = primary_if_get_selected(bat_priv);
1535 if (!primary_if)
1536 return 0;
1537 memcpy(unicast_packet->dest,
1538 primary_if->net_dev->dev_addr, ETH_ALEN);
1539 hardif_free_ref(primary_if);
1540 } else {
1541 memcpy(unicast_packet->dest, orig_node->orig,
1542 ETH_ALEN);
1543 curr_ttvn = (uint8_t)
1544 atomic_read(&orig_node->last_ttvn);
1545 orig_node_free_ref(orig_node);
1546 }
1547
1548 bat_dbg(DBG_ROUTES, bat_priv, "TTVN mismatch (old_ttvn %u "
1549 "new_ttvn %u)! Rerouting unicast packet (for %pM) to "
1550 "%pM\n", unicast_packet->ttvn, curr_ttvn,
1551 ethhdr->h_dest, unicast_packet->dest);
1552
1553 unicast_packet->ttvn = curr_ttvn;
1554 }
1555 return 1;
1556}
1557
Marek Lindnere6c10f42011-02-18 12:33:20 +00001558int recv_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001559{
Antonio Quartullia73105b2011-04-27 14:27:44 +02001560 struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001561 struct unicast_packet *unicast_packet;
Sven Eckelmann704509b2011-05-14 23:14:54 +02001562 int hdr_size = sizeof(*unicast_packet);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001563
1564 if (check_unicast_packet(skb, hdr_size) < 0)
1565 return NET_RX_DROP;
1566
Antonio Quartullia73105b2011-04-27 14:27:44 +02001567 if (!check_unicast_ttvn(bat_priv, skb))
1568 return NET_RX_DROP;
1569
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001570 unicast_packet = (struct unicast_packet *)skb->data;
1571
1572 /* packet for me */
1573 if (is_my_mac(unicast_packet->dest)) {
1574 interface_rx(recv_if->soft_iface, skb, recv_if, hdr_size);
1575 return NET_RX_SUCCESS;
1576 }
1577
Linus Lüssing7cefb142011-03-02 17:39:31 +00001578 return route_unicast_packet(skb, recv_if);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001579}
1580
Marek Lindnere6c10f42011-02-18 12:33:20 +00001581int recv_ucast_frag_packet(struct sk_buff *skb, struct hard_iface *recv_if)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001582{
1583 struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface);
1584 struct unicast_frag_packet *unicast_packet;
Sven Eckelmann704509b2011-05-14 23:14:54 +02001585 int hdr_size = sizeof(*unicast_packet);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001586 struct sk_buff *new_skb = NULL;
1587 int ret;
1588
1589 if (check_unicast_packet(skb, hdr_size) < 0)
1590 return NET_RX_DROP;
1591
Antonio Quartullia73105b2011-04-27 14:27:44 +02001592 if (!check_unicast_ttvn(bat_priv, skb))
1593 return NET_RX_DROP;
1594
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001595 unicast_packet = (struct unicast_frag_packet *)skb->data;
1596
1597 /* packet for me */
1598 if (is_my_mac(unicast_packet->dest)) {
1599
1600 ret = frag_reassemble_skb(skb, bat_priv, &new_skb);
1601
1602 if (ret == NET_RX_DROP)
1603 return NET_RX_DROP;
1604
1605 /* packet was buffered for late merge */
1606 if (!new_skb)
1607 return NET_RX_SUCCESS;
1608
1609 interface_rx(recv_if->soft_iface, new_skb, recv_if,
1610 sizeof(struct unicast_packet));
1611 return NET_RX_SUCCESS;
1612 }
1613
Linus Lüssing7cefb142011-03-02 17:39:31 +00001614 return route_unicast_packet(skb, recv_if);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001615}
1616
1617
Marek Lindnere6c10f42011-02-18 12:33:20 +00001618int recv_bcast_packet(struct sk_buff *skb, struct hard_iface *recv_if)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001619{
1620 struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface);
Marek Lindnerf3e00082011-01-25 21:52:11 +00001621 struct orig_node *orig_node = NULL;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001622 struct bcast_packet *bcast_packet;
1623 struct ethhdr *ethhdr;
Sven Eckelmann704509b2011-05-14 23:14:54 +02001624 int hdr_size = sizeof(*bcast_packet);
Marek Lindnerf3e00082011-01-25 21:52:11 +00001625 int ret = NET_RX_DROP;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001626 int32_t seq_diff;
1627
1628 /* drop packet if it has not necessary minimum size */
1629 if (unlikely(!pskb_may_pull(skb, hdr_size)))
Marek Lindnerf3e00082011-01-25 21:52:11 +00001630 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001631
1632 ethhdr = (struct ethhdr *)skb_mac_header(skb);
1633
1634 /* packet with broadcast indication but unicast recipient */
1635 if (!is_broadcast_ether_addr(ethhdr->h_dest))
Marek Lindnerf3e00082011-01-25 21:52:11 +00001636 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001637
1638 /* packet with broadcast sender address */
1639 if (is_broadcast_ether_addr(ethhdr->h_source))
Marek Lindnerf3e00082011-01-25 21:52:11 +00001640 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001641
1642 /* ignore broadcasts sent by myself */
1643 if (is_my_mac(ethhdr->h_source))
Marek Lindnerf3e00082011-01-25 21:52:11 +00001644 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001645
1646 bcast_packet = (struct bcast_packet *)skb->data;
1647
1648 /* ignore broadcasts originated by myself */
1649 if (is_my_mac(bcast_packet->orig))
Marek Lindnerf3e00082011-01-25 21:52:11 +00001650 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001651
1652 if (bcast_packet->ttl < 2)
Marek Lindnerf3e00082011-01-25 21:52:11 +00001653 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001654
Marek Lindner7aadf882011-02-18 12:28:09 +00001655 orig_node = orig_hash_find(bat_priv, bcast_packet->orig);
Marek Lindnerf3e00082011-01-25 21:52:11 +00001656
1657 if (!orig_node)
Antonio Quartullib5a6f692011-04-16 11:30:57 +02001658 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001659
Marek Lindnerf3e00082011-01-25 21:52:11 +00001660 spin_lock_bh(&orig_node->bcast_seqno_lock);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001661
1662 /* check whether the packet is a duplicate */
Marek Lindnerf3e00082011-01-25 21:52:11 +00001663 if (get_bit_status(orig_node->bcast_bits, orig_node->last_bcast_seqno,
1664 ntohl(bcast_packet->seqno)))
1665 goto spin_unlock;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001666
1667 seq_diff = ntohl(bcast_packet->seqno) - orig_node->last_bcast_seqno;
1668
1669 /* check whether the packet is old and the host just restarted. */
1670 if (window_protected(bat_priv, seq_diff,
Marek Lindnerf3e00082011-01-25 21:52:11 +00001671 &orig_node->bcast_seqno_reset))
1672 goto spin_unlock;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001673
1674 /* mark broadcast in flood history, update window position
1675 * if required. */
1676 if (bit_get_packet(bat_priv, orig_node->bcast_bits, seq_diff, 1))
1677 orig_node->last_bcast_seqno = ntohl(bcast_packet->seqno);
1678
Marek Lindnerf3e00082011-01-25 21:52:11 +00001679 spin_unlock_bh(&orig_node->bcast_seqno_lock);
Marek Lindnerf3e00082011-01-25 21:52:11 +00001680
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001681 /* rebroadcast packet */
1682 add_bcast_packet_to_list(bat_priv, skb);
1683
1684 /* broadcast for me */
1685 interface_rx(recv_if->soft_iface, skb, recv_if, hdr_size);
Marek Lindnerf3e00082011-01-25 21:52:11 +00001686 ret = NET_RX_SUCCESS;
1687 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001688
Marek Lindnerf3e00082011-01-25 21:52:11 +00001689spin_unlock:
1690 spin_unlock_bh(&orig_node->bcast_seqno_lock);
Marek Lindnerf3e00082011-01-25 21:52:11 +00001691out:
1692 if (orig_node)
Marek Lindner7b36e8e2011-02-18 12:28:10 +00001693 orig_node_free_ref(orig_node);
Marek Lindnerf3e00082011-01-25 21:52:11 +00001694 return ret;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001695}
1696
Marek Lindnere6c10f42011-02-18 12:33:20 +00001697int recv_vis_packet(struct sk_buff *skb, struct hard_iface *recv_if)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001698{
1699 struct vis_packet *vis_packet;
1700 struct ethhdr *ethhdr;
1701 struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface);
Sven Eckelmann704509b2011-05-14 23:14:54 +02001702 int hdr_size = sizeof(*vis_packet);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001703
1704 /* keep skb linear */
1705 if (skb_linearize(skb) < 0)
1706 return NET_RX_DROP;
1707
1708 if (unlikely(!pskb_may_pull(skb, hdr_size)))
1709 return NET_RX_DROP;
1710
1711 vis_packet = (struct vis_packet *)skb->data;
1712 ethhdr = (struct ethhdr *)skb_mac_header(skb);
1713
1714 /* not for me */
1715 if (!is_my_mac(ethhdr->h_dest))
1716 return NET_RX_DROP;
1717
1718 /* ignore own packets */
1719 if (is_my_mac(vis_packet->vis_orig))
1720 return NET_RX_DROP;
1721
1722 if (is_my_mac(vis_packet->sender_orig))
1723 return NET_RX_DROP;
1724
1725 switch (vis_packet->vis_type) {
1726 case VIS_TYPE_SERVER_SYNC:
1727 receive_server_sync_packet(bat_priv, vis_packet,
1728 skb_headlen(skb));
1729 break;
1730
1731 case VIS_TYPE_CLIENT_UPDATE:
1732 receive_client_update_packet(bat_priv, vis_packet,
1733 skb_headlen(skb));
1734 break;
1735
1736 default: /* ignore unknown packet */
1737 break;
1738 }
1739
1740 /* We take a copy of the data in the packet, so we should
1741 always free the skbuf. */
1742 return NET_RX_DROP;
1743}