batman-adv: make batadv_test_bit() return 0 or 1 only
[deliverable/linux.git] / net / batman-adv / bridge_loop_avoidance.c
CommitLineData
9cfc7bd6 1/* Copyright (C) 2011-2012 B.A.T.M.A.N. contributors:
23721387
SW
2 *
3 * Simon Wunderlich
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of version 2 of the GNU General Public
7 * License as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA
23721387
SW
18 */
19
20#include "main.h"
21#include "hash.h"
22#include "hard-interface.h"
23#include "originator.h"
24#include "bridge_loop_avoidance.h"
20ff9d59 25#include "translation-table.h"
23721387
SW
26#include "send.h"
27
28#include <linux/etherdevice.h>
29#include <linux/crc16.h>
30#include <linux/if_arp.h>
31#include <net/arp.h>
32#include <linux/if_vlan.h>
33
3b300de3 34static const uint8_t batadv_announce_mac[4] = {0x43, 0x05, 0x43, 0x05};
23721387 35
3b300de3 36static void batadv_bla_periodic_work(struct work_struct *work);
56303d34
SE
37static void batadv_bla_send_announce(struct batadv_priv *bat_priv,
38 struct batadv_backbone_gw *backbone_gw);
23721387
SW
39
40/* return the index of the claim */
3b300de3 41static inline uint32_t batadv_choose_claim(const void *data, uint32_t size)
23721387
SW
42{
43 const unsigned char *key = data;
44 uint32_t hash = 0;
45 size_t i;
46
47 for (i = 0; i < ETH_ALEN + sizeof(short); i++) {
48 hash += key[i];
49 hash += (hash << 10);
50 hash ^= (hash >> 6);
51 }
52
53 hash += (hash << 3);
54 hash ^= (hash >> 11);
55 hash += (hash << 15);
56
57 return hash % size;
58}
59
60/* return the index of the backbone gateway */
3b300de3
SE
61static inline uint32_t batadv_choose_backbone_gw(const void *data,
62 uint32_t size)
23721387
SW
63{
64 const unsigned char *key = data;
65 uint32_t hash = 0;
66 size_t i;
67
68 for (i = 0; i < ETH_ALEN + sizeof(short); i++) {
69 hash += key[i];
70 hash += (hash << 10);
71 hash ^= (hash >> 6);
72 }
73
74 hash += (hash << 3);
75 hash ^= (hash >> 11);
76 hash += (hash << 15);
77
78 return hash % size;
79}
80
81
82/* compares address and vid of two backbone gws */
3b300de3
SE
83static int batadv_compare_backbone_gw(const struct hlist_node *node,
84 const void *data2)
23721387 85{
56303d34 86 const void *data1 = container_of(node, struct batadv_backbone_gw,
23721387
SW
87 hash_entry);
88
89 return (memcmp(data1, data2, ETH_ALEN + sizeof(short)) == 0 ? 1 : 0);
90}
91
92/* compares address and vid of two claims */
3b300de3
SE
93static int batadv_compare_claim(const struct hlist_node *node,
94 const void *data2)
23721387 95{
56303d34 96 const void *data1 = container_of(node, struct batadv_claim,
23721387
SW
97 hash_entry);
98
99 return (memcmp(data1, data2, ETH_ALEN + sizeof(short)) == 0 ? 1 : 0);
100}
101
102/* free a backbone gw */
56303d34 103static void batadv_backbone_gw_free_ref(struct batadv_backbone_gw *backbone_gw)
23721387
SW
104{
105 if (atomic_dec_and_test(&backbone_gw->refcount))
106 kfree_rcu(backbone_gw, rcu);
107}
108
109/* finally deinitialize the claim */
3b300de3 110static void batadv_claim_free_rcu(struct rcu_head *rcu)
23721387 111{
56303d34 112 struct batadv_claim *claim;
23721387 113
56303d34 114 claim = container_of(rcu, struct batadv_claim, rcu);
23721387 115
3b300de3 116 batadv_backbone_gw_free_ref(claim->backbone_gw);
23721387
SW
117 kfree(claim);
118}
119
120/* free a claim, call claim_free_rcu if its the last reference */
56303d34 121static void batadv_claim_free_ref(struct batadv_claim *claim)
23721387
SW
122{
123 if (atomic_dec_and_test(&claim->refcount))
3b300de3 124 call_rcu(&claim->rcu, batadv_claim_free_rcu);
23721387
SW
125}
126
9cfc7bd6 127/* @bat_priv: the bat priv with all the soft interface information
23721387
SW
128 * @data: search data (may be local/static data)
129 *
130 * looks for a claim in the hash, and returns it if found
131 * or NULL otherwise.
132 */
56303d34
SE
133static struct batadv_claim *batadv_claim_hash_find(struct batadv_priv *bat_priv,
134 struct batadv_claim *data)
23721387 135{
5bf74e9c 136 struct batadv_hashtable *hash = bat_priv->claim_hash;
23721387
SW
137 struct hlist_head *head;
138 struct hlist_node *node;
56303d34
SE
139 struct batadv_claim *claim;
140 struct batadv_claim *claim_tmp = NULL;
23721387
SW
141 int index;
142
143 if (!hash)
144 return NULL;
145
3b300de3 146 index = batadv_choose_claim(data, hash->size);
23721387
SW
147 head = &hash->table[index];
148
149 rcu_read_lock();
150 hlist_for_each_entry_rcu(claim, node, head, hash_entry) {
3b300de3 151 if (!batadv_compare_claim(&claim->hash_entry, data))
23721387
SW
152 continue;
153
154 if (!atomic_inc_not_zero(&claim->refcount))
155 continue;
156
157 claim_tmp = claim;
158 break;
159 }
160 rcu_read_unlock();
161
162 return claim_tmp;
163}
164
2c53040f
BH
165/**
166 * batadv_backbone_hash_find - looks for a claim in the hash
167 * @bat_priv: the bat priv with all the soft interface information
23721387
SW
168 * @addr: the address of the originator
169 * @vid: the VLAN ID
170 *
2c53040f 171 * Returns claim if found or NULL otherwise.
23721387 172 */
56303d34
SE
173static struct batadv_backbone_gw *
174batadv_backbone_hash_find(struct batadv_priv *bat_priv,
175 uint8_t *addr, short vid)
23721387 176{
5bf74e9c 177 struct batadv_hashtable *hash = bat_priv->backbone_hash;
23721387
SW
178 struct hlist_head *head;
179 struct hlist_node *node;
56303d34
SE
180 struct batadv_backbone_gw search_entry, *backbone_gw;
181 struct batadv_backbone_gw *backbone_gw_tmp = NULL;
23721387
SW
182 int index;
183
184 if (!hash)
185 return NULL;
186
187 memcpy(search_entry.orig, addr, ETH_ALEN);
188 search_entry.vid = vid;
189
3b300de3 190 index = batadv_choose_backbone_gw(&search_entry, hash->size);
23721387
SW
191 head = &hash->table[index];
192
193 rcu_read_lock();
194 hlist_for_each_entry_rcu(backbone_gw, node, head, hash_entry) {
3b300de3
SE
195 if (!batadv_compare_backbone_gw(&backbone_gw->hash_entry,
196 &search_entry))
23721387
SW
197 continue;
198
199 if (!atomic_inc_not_zero(&backbone_gw->refcount))
200 continue;
201
202 backbone_gw_tmp = backbone_gw;
203 break;
204 }
205 rcu_read_unlock();
206
207 return backbone_gw_tmp;
208}
209
210/* delete all claims for a backbone */
56303d34
SE
211static void
212batadv_bla_del_backbone_claims(struct batadv_backbone_gw *backbone_gw)
23721387 213{
5bf74e9c 214 struct batadv_hashtable *hash;
23721387
SW
215 struct hlist_node *node, *node_tmp;
216 struct hlist_head *head;
56303d34 217 struct batadv_claim *claim;
23721387
SW
218 int i;
219 spinlock_t *list_lock; /* protects write access to the hash lists */
220
221 hash = backbone_gw->bat_priv->claim_hash;
222 if (!hash)
223 return;
224
225 for (i = 0; i < hash->size; i++) {
226 head = &hash->table[i];
227 list_lock = &hash->list_locks[i];
228
229 spin_lock_bh(list_lock);
230 hlist_for_each_entry_safe(claim, node, node_tmp,
231 head, hash_entry) {
232
233 if (claim->backbone_gw != backbone_gw)
234 continue;
235
3b300de3 236 batadv_claim_free_ref(claim);
23721387
SW
237 hlist_del_rcu(node);
238 }
239 spin_unlock_bh(list_lock);
240 }
241
242 /* all claims gone, intialize CRC */
3964f728 243 backbone_gw->crc = BATADV_BLA_CRC_INIT;
23721387
SW
244}
245
2c53040f
BH
246/**
247 * batadv_bla_send_claim - sends a claim frame according to the provided info
248 * @bat_priv: the bat priv with all the soft interface information
23721387
SW
249 * @orig: the mac address to be announced within the claim
250 * @vid: the VLAN ID
251 * @claimtype: the type of the claim (CLAIM, UNCLAIM, ANNOUNCE, ...)
23721387 252 */
56303d34 253static void batadv_bla_send_claim(struct batadv_priv *bat_priv, uint8_t *mac,
3b300de3 254 short vid, int claimtype)
23721387
SW
255{
256 struct sk_buff *skb;
257 struct ethhdr *ethhdr;
56303d34 258 struct batadv_hard_iface *primary_if;
23721387
SW
259 struct net_device *soft_iface;
260 uint8_t *hw_src;
96412690 261 struct batadv_bla_claim_dst local_claim_dest;
3e2f1a1b 262 __be32 zeroip = 0;
23721387 263
e5d89254 264 primary_if = batadv_primary_if_get_selected(bat_priv);
23721387
SW
265 if (!primary_if)
266 return;
267
38ef3d1d
SW
268 memcpy(&local_claim_dest, &bat_priv->claim_dest,
269 sizeof(local_claim_dest));
23721387
SW
270 local_claim_dest.type = claimtype;
271
272 soft_iface = primary_if->soft_iface;
273
274 skb = arp_create(ARPOP_REPLY, ETH_P_ARP,
275 /* IP DST: 0.0.0.0 */
276 zeroip,
277 primary_if->soft_iface,
278 /* IP SRC: 0.0.0.0 */
279 zeroip,
280 /* Ethernet DST: Broadcast */
281 NULL,
282 /* Ethernet SRC/HW SRC: originator mac */
283 primary_if->net_dev->dev_addr,
284 /* HW DST: FF:43:05:XX:00:00
285 * with XX = claim type
38ef3d1d 286 * and YY:YY = group id
23721387
SW
287 */
288 (uint8_t *)&local_claim_dest);
289
290 if (!skb)
291 goto out;
292
293 ethhdr = (struct ethhdr *)skb->data;
0d125074 294 hw_src = (uint8_t *)ethhdr + ETH_HLEN + sizeof(struct arphdr);
23721387
SW
295
296 /* now we pretend that the client would have sent this ... */
297 switch (claimtype) {
acd34afa 298 case BATADV_CLAIM_TYPE_ADD:
23721387
SW
299 /* normal claim frame
300 * set Ethernet SRC to the clients mac
301 */
302 memcpy(ethhdr->h_source, mac, ETH_ALEN);
39c75a51 303 batadv_dbg(BATADV_DBG_BLA, bat_priv,
1eda58bf 304 "bla_send_claim(): CLAIM %pM on vid %d\n", mac, vid);
23721387 305 break;
acd34afa 306 case BATADV_CLAIM_TYPE_DEL:
23721387
SW
307 /* unclaim frame
308 * set HW SRC to the clients mac
309 */
310 memcpy(hw_src, mac, ETH_ALEN);
39c75a51 311 batadv_dbg(BATADV_DBG_BLA, bat_priv,
1eda58bf
SE
312 "bla_send_claim(): UNCLAIM %pM on vid %d\n", mac,
313 vid);
23721387 314 break;
acd34afa 315 case BATADV_CLAIM_TYPE_ANNOUNCE:
23721387
SW
316 /* announcement frame
317 * set HW SRC to the special mac containg the crc
318 */
319 memcpy(hw_src, mac, ETH_ALEN);
39c75a51 320 batadv_dbg(BATADV_DBG_BLA, bat_priv,
1eda58bf
SE
321 "bla_send_claim(): ANNOUNCE of %pM on vid %d\n",
322 ethhdr->h_source, vid);
23721387 323 break;
acd34afa 324 case BATADV_CLAIM_TYPE_REQUEST:
23721387
SW
325 /* request frame
326 * set HW SRC to the special mac containg the crc
327 */
328 memcpy(hw_src, mac, ETH_ALEN);
329 memcpy(ethhdr->h_dest, mac, ETH_ALEN);
39c75a51 330 batadv_dbg(BATADV_DBG_BLA, bat_priv,
1eda58bf
SE
331 "bla_send_claim(): REQUEST of %pM to %pMon vid %d\n",
332 ethhdr->h_source, ethhdr->h_dest, vid);
23721387
SW
333 break;
334
335 }
336
337 if (vid != -1)
338 skb = vlan_insert_tag(skb, vid);
339
340 skb_reset_mac_header(skb);
341 skb->protocol = eth_type_trans(skb, soft_iface);
342 bat_priv->stats.rx_packets++;
0d125074 343 bat_priv->stats.rx_bytes += skb->len + ETH_HLEN;
23721387
SW
344 soft_iface->last_rx = jiffies;
345
346 netif_rx(skb);
347out:
348 if (primary_if)
e5d89254 349 batadv_hardif_free_ref(primary_if);
23721387
SW
350}
351
2c53040f
BH
352/**
353 * batadv_bla_get_backbone_gw
354 * @bat_priv: the bat priv with all the soft interface information
23721387
SW
355 * @orig: the mac address of the originator
356 * @vid: the VLAN ID
357 *
358 * searches for the backbone gw or creates a new one if it could not
359 * be found.
360 */
56303d34
SE
361static struct batadv_backbone_gw *
362batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv, uint8_t *orig,
363 short vid)
23721387 364{
56303d34
SE
365 struct batadv_backbone_gw *entry;
366 struct batadv_orig_node *orig_node;
23721387
SW
367 int hash_added;
368
3b300de3 369 entry = batadv_backbone_hash_find(bat_priv, orig, vid);
23721387
SW
370
371 if (entry)
372 return entry;
373
39c75a51 374 batadv_dbg(BATADV_DBG_BLA, bat_priv,
1eda58bf
SE
375 "bla_get_backbone_gw(): not found (%pM, %d), creating new entry\n",
376 orig, vid);
23721387
SW
377
378 entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
379 if (!entry)
380 return NULL;
381
382 entry->vid = vid;
383 entry->lasttime = jiffies;
3964f728 384 entry->crc = BATADV_BLA_CRC_INIT;
23721387
SW
385 entry->bat_priv = bat_priv;
386 atomic_set(&entry->request_sent, 0);
387 memcpy(entry->orig, orig, ETH_ALEN);
388
389 /* one for the hash, one for returning */
390 atomic_set(&entry->refcount, 2);
391
c0a55929 392 hash_added = batadv_hash_add(bat_priv->backbone_hash,
3b300de3
SE
393 batadv_compare_backbone_gw,
394 batadv_choose_backbone_gw, entry,
395 &entry->hash_entry);
23721387
SW
396
397 if (unlikely(hash_added != 0)) {
398 /* hash failed, free the structure */
399 kfree(entry);
400 return NULL;
401 }
402
20ff9d59 403 /* this is a gateway now, remove any tt entries */
da641193 404 orig_node = batadv_orig_hash_find(bat_priv, orig);
20ff9d59 405 if (orig_node) {
08c36d3e
SE
406 batadv_tt_global_del_orig(bat_priv, orig_node,
407 "became a backbone gateway");
7d211efc 408 batadv_orig_node_free_ref(orig_node);
20ff9d59 409 }
23721387
SW
410 return entry;
411}
412
413/* update or add the own backbone gw to make sure we announce
414 * where we receive other backbone gws
415 */
56303d34
SE
416static void
417batadv_bla_update_own_backbone_gw(struct batadv_priv *bat_priv,
418 struct batadv_hard_iface *primary_if,
419 short vid)
23721387 420{
56303d34 421 struct batadv_backbone_gw *backbone_gw;
23721387 422
3b300de3
SE
423 backbone_gw = batadv_bla_get_backbone_gw(bat_priv,
424 primary_if->net_dev->dev_addr,
425 vid);
23721387
SW
426 if (unlikely(!backbone_gw))
427 return;
428
429 backbone_gw->lasttime = jiffies;
3b300de3 430 batadv_backbone_gw_free_ref(backbone_gw);
23721387
SW
431}
432
9cfc7bd6 433/* @bat_priv: the bat priv with all the soft interface information
23721387
SW
434 * @vid: the vid where the request came on
435 *
436 * Repeat all of our own claims, and finally send an ANNOUNCE frame
437 * to allow the requester another check if the CRC is correct now.
438 */
56303d34
SE
439static void batadv_bla_answer_request(struct batadv_priv *bat_priv,
440 struct batadv_hard_iface *primary_if,
441 short vid)
23721387
SW
442{
443 struct hlist_node *node;
444 struct hlist_head *head;
5bf74e9c 445 struct batadv_hashtable *hash;
56303d34
SE
446 struct batadv_claim *claim;
447 struct batadv_backbone_gw *backbone_gw;
23721387
SW
448 int i;
449
39c75a51 450 batadv_dbg(BATADV_DBG_BLA, bat_priv,
1eda58bf 451 "bla_answer_request(): received a claim request, send all of our own claims again\n");
23721387 452
3b300de3
SE
453 backbone_gw = batadv_backbone_hash_find(bat_priv,
454 primary_if->net_dev->dev_addr,
455 vid);
23721387
SW
456 if (!backbone_gw)
457 return;
458
459 hash = bat_priv->claim_hash;
460 for (i = 0; i < hash->size; i++) {
461 head = &hash->table[i];
462
463 rcu_read_lock();
464 hlist_for_each_entry_rcu(claim, node, head, hash_entry) {
465 /* only own claims are interesting */
466 if (claim->backbone_gw != backbone_gw)
467 continue;
468
3b300de3 469 batadv_bla_send_claim(bat_priv, claim->addr, claim->vid,
acd34afa 470 BATADV_CLAIM_TYPE_ADD);
23721387
SW
471 }
472 rcu_read_unlock();
473 }
474
475 /* finally, send an announcement frame */
3b300de3
SE
476 batadv_bla_send_announce(bat_priv, backbone_gw);
477 batadv_backbone_gw_free_ref(backbone_gw);
23721387
SW
478}
479
9cfc7bd6 480/* @backbone_gw: the backbone gateway from whom we are out of sync
23721387
SW
481 *
482 * When the crc is wrong, ask the backbone gateway for a full table update.
483 * After the request, it will repeat all of his own claims and finally
484 * send an announcement claim with which we can check again.
485 */
56303d34 486static void batadv_bla_send_request(struct batadv_backbone_gw *backbone_gw)
23721387
SW
487{
488 /* first, remove all old entries */
3b300de3 489 batadv_bla_del_backbone_claims(backbone_gw);
23721387 490
39c75a51
SE
491 batadv_dbg(BATADV_DBG_BLA, backbone_gw->bat_priv,
492 "Sending REQUEST to %pM\n", backbone_gw->orig);
23721387
SW
493
494 /* send request */
3b300de3 495 batadv_bla_send_claim(backbone_gw->bat_priv, backbone_gw->orig,
acd34afa 496 backbone_gw->vid, BATADV_CLAIM_TYPE_REQUEST);
23721387
SW
497
498 /* no local broadcasts should be sent or received, for now. */
499 if (!atomic_read(&backbone_gw->request_sent)) {
500 atomic_inc(&backbone_gw->bat_priv->bla_num_requests);
501 atomic_set(&backbone_gw->request_sent, 1);
502 }
503}
504
9cfc7bd6 505/* @bat_priv: the bat priv with all the soft interface information
23721387
SW
506 * @backbone_gw: our backbone gateway which should be announced
507 *
508 * This function sends an announcement. It is called from multiple
509 * places.
510 */
56303d34
SE
511static void batadv_bla_send_announce(struct batadv_priv *bat_priv,
512 struct batadv_backbone_gw *backbone_gw)
23721387
SW
513{
514 uint8_t mac[ETH_ALEN];
3e2f1a1b 515 __be16 crc;
23721387 516
3b300de3 517 memcpy(mac, batadv_announce_mac, 4);
23721387 518 crc = htons(backbone_gw->crc);
1a5852d8 519 memcpy(&mac[4], &crc, 2);
23721387 520
3b300de3 521 batadv_bla_send_claim(bat_priv, mac, backbone_gw->vid,
acd34afa 522 BATADV_CLAIM_TYPE_ANNOUNCE);
23721387
SW
523
524}
525
2c53040f
BH
526/**
527 * batadv_bla_add_claim - Adds a claim in the claim hash
528 * @bat_priv: the bat priv with all the soft interface information
23721387
SW
529 * @mac: the mac address of the claim
530 * @vid: the VLAN ID of the frame
531 * @backbone_gw: the backbone gateway which claims it
23721387 532 */
56303d34
SE
533static void batadv_bla_add_claim(struct batadv_priv *bat_priv,
534 const uint8_t *mac, const short vid,
535 struct batadv_backbone_gw *backbone_gw)
23721387 536{
56303d34
SE
537 struct batadv_claim *claim;
538 struct batadv_claim search_claim;
23721387
SW
539 int hash_added;
540
541 memcpy(search_claim.addr, mac, ETH_ALEN);
542 search_claim.vid = vid;
3b300de3 543 claim = batadv_claim_hash_find(bat_priv, &search_claim);
23721387
SW
544
545 /* create a new claim entry if it does not exist yet. */
546 if (!claim) {
547 claim = kzalloc(sizeof(*claim), GFP_ATOMIC);
548 if (!claim)
549 return;
550
551 memcpy(claim->addr, mac, ETH_ALEN);
552 claim->vid = vid;
553 claim->lasttime = jiffies;
554 claim->backbone_gw = backbone_gw;
555
556 atomic_set(&claim->refcount, 2);
39c75a51 557 batadv_dbg(BATADV_DBG_BLA, bat_priv,
1eda58bf
SE
558 "bla_add_claim(): adding new entry %pM, vid %d to hash ...\n",
559 mac, vid);
c0a55929 560 hash_added = batadv_hash_add(bat_priv->claim_hash,
3b300de3
SE
561 batadv_compare_claim,
562 batadv_choose_claim, claim,
563 &claim->hash_entry);
23721387
SW
564
565 if (unlikely(hash_added != 0)) {
566 /* only local changes happened. */
567 kfree(claim);
568 return;
569 }
570 } else {
571 claim->lasttime = jiffies;
572 if (claim->backbone_gw == backbone_gw)
573 /* no need to register a new backbone */
574 goto claim_free_ref;
575
39c75a51 576 batadv_dbg(BATADV_DBG_BLA, bat_priv,
1eda58bf
SE
577 "bla_add_claim(): changing ownership for %pM, vid %d\n",
578 mac, vid);
23721387
SW
579
580 claim->backbone_gw->crc ^=
581 crc16(0, claim->addr, ETH_ALEN);
3b300de3 582 batadv_backbone_gw_free_ref(claim->backbone_gw);
23721387
SW
583
584 }
585 /* set (new) backbone gw */
586 atomic_inc(&backbone_gw->refcount);
587 claim->backbone_gw = backbone_gw;
588
589 backbone_gw->crc ^= crc16(0, claim->addr, ETH_ALEN);
590 backbone_gw->lasttime = jiffies;
591
592claim_free_ref:
3b300de3 593 batadv_claim_free_ref(claim);
23721387
SW
594}
595
596/* Delete a claim from the claim hash which has the
597 * given mac address and vid.
598 */
56303d34
SE
599static void batadv_bla_del_claim(struct batadv_priv *bat_priv,
600 const uint8_t *mac, const short vid)
23721387 601{
56303d34 602 struct batadv_claim search_claim, *claim;
23721387
SW
603
604 memcpy(search_claim.addr, mac, ETH_ALEN);
605 search_claim.vid = vid;
3b300de3 606 claim = batadv_claim_hash_find(bat_priv, &search_claim);
23721387
SW
607 if (!claim)
608 return;
609
39c75a51
SE
610 batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla_del_claim(): %pM, vid %d\n",
611 mac, vid);
23721387 612
3b300de3
SE
613 batadv_hash_remove(bat_priv->claim_hash, batadv_compare_claim,
614 batadv_choose_claim, claim);
615 batadv_claim_free_ref(claim); /* reference from the hash is gone */
23721387
SW
616
617 claim->backbone_gw->crc ^= crc16(0, claim->addr, ETH_ALEN);
618
619 /* don't need the reference from hash_find() anymore */
3b300de3 620 batadv_claim_free_ref(claim);
23721387
SW
621}
622
623/* check for ANNOUNCE frame, return 1 if handled */
56303d34 624static int batadv_handle_announce(struct batadv_priv *bat_priv,
3b300de3
SE
625 uint8_t *an_addr, uint8_t *backbone_addr,
626 short vid)
23721387 627{
56303d34 628 struct batadv_backbone_gw *backbone_gw;
23721387
SW
629 uint16_t crc;
630
3b300de3 631 if (memcmp(an_addr, batadv_announce_mac, 4) != 0)
23721387
SW
632 return 0;
633
3b300de3 634 backbone_gw = batadv_bla_get_backbone_gw(bat_priv, backbone_addr, vid);
23721387
SW
635
636 if (unlikely(!backbone_gw))
637 return 1;
638
639
640 /* handle as ANNOUNCE frame */
641 backbone_gw->lasttime = jiffies;
3e2f1a1b 642 crc = ntohs(*((__be16 *)(&an_addr[4])));
23721387 643
39c75a51 644 batadv_dbg(BATADV_DBG_BLA, bat_priv,
1eda58bf
SE
645 "handle_announce(): ANNOUNCE vid %d (sent by %pM)... CRC = %04x\n",
646 vid, backbone_gw->orig, crc);
23721387
SW
647
648 if (backbone_gw->crc != crc) {
39c75a51 649 batadv_dbg(BATADV_DBG_BLA, backbone_gw->bat_priv,
1eda58bf
SE
650 "handle_announce(): CRC FAILED for %pM/%d (my = %04x, sent = %04x)\n",
651 backbone_gw->orig, backbone_gw->vid,
652 backbone_gw->crc, crc);
23721387 653
3b300de3 654 batadv_bla_send_request(backbone_gw);
23721387
SW
655 } else {
656 /* if we have sent a request and the crc was OK,
657 * we can allow traffic again.
658 */
659 if (atomic_read(&backbone_gw->request_sent)) {
660 atomic_dec(&backbone_gw->bat_priv->bla_num_requests);
661 atomic_set(&backbone_gw->request_sent, 0);
662 }
663 }
664
3b300de3 665 batadv_backbone_gw_free_ref(backbone_gw);
23721387
SW
666 return 1;
667}
668
669/* check for REQUEST frame, return 1 if handled */
56303d34
SE
670static int batadv_handle_request(struct batadv_priv *bat_priv,
671 struct batadv_hard_iface *primary_if,
3b300de3
SE
672 uint8_t *backbone_addr,
673 struct ethhdr *ethhdr, short vid)
23721387
SW
674{
675 /* check for REQUEST frame */
1eda58bf 676 if (!batadv_compare_eth(backbone_addr, ethhdr->h_dest))
23721387
SW
677 return 0;
678
679 /* sanity check, this should not happen on a normal switch,
680 * we ignore it in this case.
681 */
1eda58bf 682 if (!batadv_compare_eth(ethhdr->h_dest, primary_if->net_dev->dev_addr))
23721387
SW
683 return 1;
684
39c75a51 685 batadv_dbg(BATADV_DBG_BLA, bat_priv,
1eda58bf
SE
686 "handle_request(): REQUEST vid %d (sent by %pM)...\n",
687 vid, ethhdr->h_source);
23721387 688
3b300de3 689 batadv_bla_answer_request(bat_priv, primary_if, vid);
23721387
SW
690 return 1;
691}
692
693/* check for UNCLAIM frame, return 1 if handled */
56303d34
SE
694static int batadv_handle_unclaim(struct batadv_priv *bat_priv,
695 struct batadv_hard_iface *primary_if,
3b300de3
SE
696 uint8_t *backbone_addr,
697 uint8_t *claim_addr, short vid)
23721387 698{
56303d34 699 struct batadv_backbone_gw *backbone_gw;
23721387
SW
700
701 /* unclaim in any case if it is our own */
1eda58bf
SE
702 if (primary_if && batadv_compare_eth(backbone_addr,
703 primary_if->net_dev->dev_addr))
3b300de3 704 batadv_bla_send_claim(bat_priv, claim_addr, vid,
acd34afa 705 BATADV_CLAIM_TYPE_DEL);
23721387 706
3b300de3 707 backbone_gw = batadv_backbone_hash_find(bat_priv, backbone_addr, vid);
23721387
SW
708
709 if (!backbone_gw)
710 return 1;
711
712 /* this must be an UNCLAIM frame */
39c75a51 713 batadv_dbg(BATADV_DBG_BLA, bat_priv,
1eda58bf
SE
714 "handle_unclaim(): UNCLAIM %pM on vid %d (sent by %pM)...\n",
715 claim_addr, vid, backbone_gw->orig);
23721387 716
3b300de3
SE
717 batadv_bla_del_claim(bat_priv, claim_addr, vid);
718 batadv_backbone_gw_free_ref(backbone_gw);
23721387
SW
719 return 1;
720}
721
722/* check for CLAIM frame, return 1 if handled */
56303d34
SE
723static int batadv_handle_claim(struct batadv_priv *bat_priv,
724 struct batadv_hard_iface *primary_if,
3b300de3
SE
725 uint8_t *backbone_addr, uint8_t *claim_addr,
726 short vid)
23721387 727{
56303d34 728 struct batadv_backbone_gw *backbone_gw;
23721387
SW
729
730 /* register the gateway if not yet available, and add the claim. */
731
3b300de3 732 backbone_gw = batadv_bla_get_backbone_gw(bat_priv, backbone_addr, vid);
23721387
SW
733
734 if (unlikely(!backbone_gw))
735 return 1;
736
737 /* this must be a CLAIM frame */
3b300de3 738 batadv_bla_add_claim(bat_priv, claim_addr, vid, backbone_gw);
1eda58bf 739 if (batadv_compare_eth(backbone_addr, primary_if->net_dev->dev_addr))
3b300de3 740 batadv_bla_send_claim(bat_priv, claim_addr, vid,
acd34afa 741 BATADV_CLAIM_TYPE_ADD);
23721387
SW
742
743 /* TODO: we could call something like tt_local_del() here. */
744
3b300de3 745 batadv_backbone_gw_free_ref(backbone_gw);
23721387
SW
746 return 1;
747}
748
2c53040f
BH
749/**
750 * batadv_check_claim_group
751 * @bat_priv: the bat priv with all the soft interface information
38ef3d1d
SW
752 * @hw_src: the Hardware source in the ARP Header
753 * @hw_dst: the Hardware destination in the ARP Header
754 * @ethhdr: pointer to the Ethernet header of the claim frame
755 *
756 * checks if it is a claim packet and if its on the same group.
757 * This function also applies the group ID of the sender
758 * if it is in the same mesh.
759 *
760 * returns:
761 * 2 - if it is a claim packet and on the same group
762 * 1 - if is a claim packet from another group
763 * 0 - if it is not a claim packet
764 */
56303d34
SE
765static int batadv_check_claim_group(struct batadv_priv *bat_priv,
766 struct batadv_hard_iface *primary_if,
3b300de3
SE
767 uint8_t *hw_src, uint8_t *hw_dst,
768 struct ethhdr *ethhdr)
38ef3d1d
SW
769{
770 uint8_t *backbone_addr;
56303d34 771 struct batadv_orig_node *orig_node;
96412690 772 struct batadv_bla_claim_dst *bla_dst, *bla_dst_own;
38ef3d1d 773
96412690 774 bla_dst = (struct batadv_bla_claim_dst *)hw_dst;
38ef3d1d
SW
775 bla_dst_own = &bat_priv->claim_dest;
776
777 /* check if it is a claim packet in general */
778 if (memcmp(bla_dst->magic, bla_dst_own->magic,
779 sizeof(bla_dst->magic)) != 0)
780 return 0;
781
782 /* if announcement packet, use the source,
783 * otherwise assume it is in the hw_src
784 */
785 switch (bla_dst->type) {
acd34afa 786 case BATADV_CLAIM_TYPE_ADD:
38ef3d1d
SW
787 backbone_addr = hw_src;
788 break;
acd34afa
SE
789 case BATADV_CLAIM_TYPE_REQUEST:
790 case BATADV_CLAIM_TYPE_ANNOUNCE:
791 case BATADV_CLAIM_TYPE_DEL:
38ef3d1d
SW
792 backbone_addr = ethhdr->h_source;
793 break;
794 default:
795 return 0;
796 }
797
798 /* don't accept claim frames from ourselves */
1eda58bf 799 if (batadv_compare_eth(backbone_addr, primary_if->net_dev->dev_addr))
38ef3d1d
SW
800 return 0;
801
802 /* if its already the same group, it is fine. */
803 if (bla_dst->group == bla_dst_own->group)
804 return 2;
805
806 /* lets see if this originator is in our mesh */
da641193 807 orig_node = batadv_orig_hash_find(bat_priv, backbone_addr);
38ef3d1d
SW
808
809 /* dont accept claims from gateways which are not in
810 * the same mesh or group.
811 */
812 if (!orig_node)
813 return 1;
814
815 /* if our mesh friends mac is bigger, use it for ourselves. */
816 if (ntohs(bla_dst->group) > ntohs(bla_dst_own->group)) {
39c75a51 817 batadv_dbg(BATADV_DBG_BLA, bat_priv,
1eda58bf
SE
818 "taking other backbones claim group: %04x\n",
819 ntohs(bla_dst->group));
38ef3d1d
SW
820 bla_dst_own->group = bla_dst->group;
821 }
822
7d211efc 823 batadv_orig_node_free_ref(orig_node);
38ef3d1d
SW
824
825 return 2;
826}
827
828
9cfc7bd6 829/* @bat_priv: the bat priv with all the soft interface information
23721387
SW
830 * @skb: the frame to be checked
831 *
832 * Check if this is a claim frame, and process it accordingly.
833 *
834 * returns 1 if it was a claim frame, otherwise return 0 to
835 * tell the callee that it can use the frame on its own.
836 */
56303d34
SE
837static int batadv_bla_process_claim(struct batadv_priv *bat_priv,
838 struct batadv_hard_iface *primary_if,
3b300de3 839 struct sk_buff *skb)
23721387
SW
840{
841 struct ethhdr *ethhdr;
842 struct vlan_ethhdr *vhdr;
843 struct arphdr *arphdr;
844 uint8_t *hw_src, *hw_dst;
96412690 845 struct batadv_bla_claim_dst *bla_dst;
23721387
SW
846 uint16_t proto;
847 int headlen;
848 short vid = -1;
38ef3d1d 849 int ret;
23721387
SW
850
851 ethhdr = (struct ethhdr *)skb_mac_header(skb);
852
853 if (ntohs(ethhdr->h_proto) == ETH_P_8021Q) {
854 vhdr = (struct vlan_ethhdr *)ethhdr;
855 vid = ntohs(vhdr->h_vlan_TCI) & VLAN_VID_MASK;
856 proto = ntohs(vhdr->h_vlan_encapsulated_proto);
857 headlen = sizeof(*vhdr);
858 } else {
859 proto = ntohs(ethhdr->h_proto);
0d125074 860 headlen = ETH_HLEN;
23721387
SW
861 }
862
863 if (proto != ETH_P_ARP)
864 return 0; /* not a claim frame */
865
866 /* this must be a ARP frame. check if it is a claim. */
867
868 if (unlikely(!pskb_may_pull(skb, headlen + arp_hdr_len(skb->dev))))
869 return 0;
870
871 /* pskb_may_pull() may have modified the pointers, get ethhdr again */
872 ethhdr = (struct ethhdr *)skb_mac_header(skb);
873 arphdr = (struct arphdr *)((uint8_t *)ethhdr + headlen);
874
875 /* Check whether the ARP frame carries a valid
876 * IP information
877 */
23721387
SW
878 if (arphdr->ar_hrd != htons(ARPHRD_ETHER))
879 return 0;
880 if (arphdr->ar_pro != htons(ETH_P_IP))
881 return 0;
882 if (arphdr->ar_hln != ETH_ALEN)
883 return 0;
884 if (arphdr->ar_pln != 4)
885 return 0;
886
887 hw_src = (uint8_t *)arphdr + sizeof(struct arphdr);
888 hw_dst = hw_src + ETH_ALEN + 4;
96412690 889 bla_dst = (struct batadv_bla_claim_dst *)hw_dst;
23721387
SW
890
891 /* check if it is a claim frame. */
3b300de3
SE
892 ret = batadv_check_claim_group(bat_priv, primary_if, hw_src, hw_dst,
893 ethhdr);
38ef3d1d 894 if (ret == 1)
39c75a51 895 batadv_dbg(BATADV_DBG_BLA, bat_priv,
1eda58bf
SE
896 "bla_process_claim(): received a claim frame from another group. From: %pM on vid %d ...(hw_src %pM, hw_dst %pM)\n",
897 ethhdr->h_source, vid, hw_src, hw_dst);
38ef3d1d
SW
898
899 if (ret < 2)
900 return ret;
23721387
SW
901
902 /* become a backbone gw ourselves on this vlan if not happened yet */
3b300de3 903 batadv_bla_update_own_backbone_gw(bat_priv, primary_if, vid);
23721387
SW
904
905 /* check for the different types of claim frames ... */
906 switch (bla_dst->type) {
acd34afa 907 case BATADV_CLAIM_TYPE_ADD:
3b300de3
SE
908 if (batadv_handle_claim(bat_priv, primary_if, hw_src,
909 ethhdr->h_source, vid))
23721387
SW
910 return 1;
911 break;
acd34afa 912 case BATADV_CLAIM_TYPE_DEL:
3b300de3
SE
913 if (batadv_handle_unclaim(bat_priv, primary_if,
914 ethhdr->h_source, hw_src, vid))
23721387
SW
915 return 1;
916 break;
917
acd34afa 918 case BATADV_CLAIM_TYPE_ANNOUNCE:
3b300de3
SE
919 if (batadv_handle_announce(bat_priv, hw_src, ethhdr->h_source,
920 vid))
23721387
SW
921 return 1;
922 break;
acd34afa 923 case BATADV_CLAIM_TYPE_REQUEST:
3b300de3
SE
924 if (batadv_handle_request(bat_priv, primary_if, hw_src, ethhdr,
925 vid))
23721387
SW
926 return 1;
927 break;
928 }
929
39c75a51 930 batadv_dbg(BATADV_DBG_BLA, bat_priv,
1eda58bf
SE
931 "bla_process_claim(): ERROR - this looks like a claim frame, but is useless. eth src %pM on vid %d ...(hw_src %pM, hw_dst %pM)\n",
932 ethhdr->h_source, vid, hw_src, hw_dst);
23721387
SW
933 return 1;
934}
935
936/* Check when we last heard from other nodes, and remove them in case of
937 * a time out, or clean all backbone gws if now is set.
938 */
56303d34 939static void batadv_bla_purge_backbone_gw(struct batadv_priv *bat_priv, int now)
23721387 940{
56303d34 941 struct batadv_backbone_gw *backbone_gw;
23721387
SW
942 struct hlist_node *node, *node_tmp;
943 struct hlist_head *head;
5bf74e9c 944 struct batadv_hashtable *hash;
23721387
SW
945 spinlock_t *list_lock; /* protects write access to the hash lists */
946 int i;
947
948 hash = bat_priv->backbone_hash;
949 if (!hash)
950 return;
951
952 for (i = 0; i < hash->size; i++) {
953 head = &hash->table[i];
954 list_lock = &hash->list_locks[i];
955
956 spin_lock_bh(list_lock);
957 hlist_for_each_entry_safe(backbone_gw, node, node_tmp,
958 head, hash_entry) {
959 if (now)
960 goto purge_now;
1eda58bf 961 if (!batadv_has_timed_out(backbone_gw->lasttime,
42d0b044 962 BATADV_BLA_BACKBONE_TIMEOUT))
23721387
SW
963 continue;
964
39c75a51 965 batadv_dbg(BATADV_DBG_BLA, backbone_gw->bat_priv,
1eda58bf
SE
966 "bla_purge_backbone_gw(): backbone gw %pM timed out\n",
967 backbone_gw->orig);
23721387
SW
968
969purge_now:
970 /* don't wait for the pending request anymore */
971 if (atomic_read(&backbone_gw->request_sent))
972 atomic_dec(&bat_priv->bla_num_requests);
973
3b300de3 974 batadv_bla_del_backbone_claims(backbone_gw);
23721387
SW
975
976 hlist_del_rcu(node);
3b300de3 977 batadv_backbone_gw_free_ref(backbone_gw);
23721387
SW
978 }
979 spin_unlock_bh(list_lock);
980 }
981}
982
2c53040f
BH
983/**
984 * batadv_bla_purge_claims
985 * @bat_priv: the bat priv with all the soft interface information
23721387
SW
986 * @primary_if: the selected primary interface, may be NULL if now is set
987 * @now: whether the whole hash shall be wiped now
988 *
989 * Check when we heard last time from our own claims, and remove them in case of
990 * a time out, or clean all claims if now is set
991 */
56303d34
SE
992static void batadv_bla_purge_claims(struct batadv_priv *bat_priv,
993 struct batadv_hard_iface *primary_if,
994 int now)
23721387 995{
56303d34 996 struct batadv_claim *claim;
23721387
SW
997 struct hlist_node *node;
998 struct hlist_head *head;
5bf74e9c 999 struct batadv_hashtable *hash;
23721387
SW
1000 int i;
1001
1002 hash = bat_priv->claim_hash;
1003 if (!hash)
1004 return;
1005
1006 for (i = 0; i < hash->size; i++) {
1007 head = &hash->table[i];
1008
1009 rcu_read_lock();
1010 hlist_for_each_entry_rcu(claim, node, head, hash_entry) {
1011 if (now)
1012 goto purge_now;
1eda58bf
SE
1013 if (!batadv_compare_eth(claim->backbone_gw->orig,
1014 primary_if->net_dev->dev_addr))
23721387 1015 continue;
1eda58bf 1016 if (!batadv_has_timed_out(claim->lasttime,
42d0b044 1017 BATADV_BLA_CLAIM_TIMEOUT))
23721387
SW
1018 continue;
1019
39c75a51 1020 batadv_dbg(BATADV_DBG_BLA, bat_priv,
1eda58bf
SE
1021 "bla_purge_claims(): %pM, vid %d, time out\n",
1022 claim->addr, claim->vid);
23721387
SW
1023
1024purge_now:
3b300de3
SE
1025 batadv_handle_unclaim(bat_priv, primary_if,
1026 claim->backbone_gw->orig,
1027 claim->addr, claim->vid);
23721387
SW
1028 }
1029 rcu_read_unlock();
1030 }
1031}
1032
2c53040f
BH
1033/**
1034 * batadv_bla_update_orig_address
1035 * @bat_priv: the bat priv with all the soft interface information
23721387
SW
1036 * @primary_if: the new selected primary_if
1037 * @oldif: the old primary interface, may be NULL
1038 *
1039 * Update the backbone gateways when the own orig address changes.
23721387 1040 */
56303d34
SE
1041void batadv_bla_update_orig_address(struct batadv_priv *bat_priv,
1042 struct batadv_hard_iface *primary_if,
1043 struct batadv_hard_iface *oldif)
23721387 1044{
56303d34 1045 struct batadv_backbone_gw *backbone_gw;
23721387
SW
1046 struct hlist_node *node;
1047 struct hlist_head *head;
5bf74e9c 1048 struct batadv_hashtable *hash;
23721387
SW
1049 int i;
1050
38ef3d1d
SW
1051 /* reset bridge loop avoidance group id */
1052 bat_priv->claim_dest.group =
1053 htons(crc16(0, primary_if->net_dev->dev_addr, ETH_ALEN));
1054
23721387 1055 if (!oldif) {
3b300de3
SE
1056 batadv_bla_purge_claims(bat_priv, NULL, 1);
1057 batadv_bla_purge_backbone_gw(bat_priv, 1);
23721387
SW
1058 return;
1059 }
1060
1061 hash = bat_priv->backbone_hash;
1062 if (!hash)
1063 return;
1064
1065 for (i = 0; i < hash->size; i++) {
1066 head = &hash->table[i];
1067
1068 rcu_read_lock();
1069 hlist_for_each_entry_rcu(backbone_gw, node, head, hash_entry) {
1070 /* own orig still holds the old value. */
1eda58bf
SE
1071 if (!batadv_compare_eth(backbone_gw->orig,
1072 oldif->net_dev->dev_addr))
23721387
SW
1073 continue;
1074
1075 memcpy(backbone_gw->orig,
1076 primary_if->net_dev->dev_addr, ETH_ALEN);
1077 /* send an announce frame so others will ask for our
1078 * claims and update their tables.
1079 */
3b300de3 1080 batadv_bla_send_announce(bat_priv, backbone_gw);
23721387
SW
1081 }
1082 rcu_read_unlock();
1083 }
1084}
1085
1086
1087
1088/* (re)start the timer */
56303d34 1089static void batadv_bla_start_timer(struct batadv_priv *bat_priv)
23721387 1090{
3b300de3 1091 INIT_DELAYED_WORK(&bat_priv->bla_work, batadv_bla_periodic_work);
3193e8fd 1092 queue_delayed_work(batadv_event_workqueue, &bat_priv->bla_work,
42d0b044 1093 msecs_to_jiffies(BATADV_BLA_PERIOD_LENGTH));
23721387
SW
1094}
1095
1096/* periodic work to do:
1097 * * purge structures when they are too old
1098 * * send announcements
1099 */
3b300de3 1100static void batadv_bla_periodic_work(struct work_struct *work)
23721387
SW
1101{
1102 struct delayed_work *delayed_work =
1103 container_of(work, struct delayed_work, work);
56303d34 1104 struct batadv_priv *bat_priv;
23721387
SW
1105 struct hlist_node *node;
1106 struct hlist_head *head;
56303d34 1107 struct batadv_backbone_gw *backbone_gw;
5bf74e9c 1108 struct batadv_hashtable *hash;
56303d34 1109 struct batadv_hard_iface *primary_if;
23721387
SW
1110 int i;
1111
56303d34 1112 bat_priv = container_of(delayed_work, struct batadv_priv, bla_work);
e5d89254 1113 primary_if = batadv_primary_if_get_selected(bat_priv);
23721387
SW
1114 if (!primary_if)
1115 goto out;
1116
3b300de3
SE
1117 batadv_bla_purge_claims(bat_priv, primary_if, 0);
1118 batadv_bla_purge_backbone_gw(bat_priv, 0);
23721387
SW
1119
1120 if (!atomic_read(&bat_priv->bridge_loop_avoidance))
1121 goto out;
1122
1123 hash = bat_priv->backbone_hash;
1124 if (!hash)
1125 goto out;
1126
1127 for (i = 0; i < hash->size; i++) {
1128 head = &hash->table[i];
1129
1130 rcu_read_lock();
1131 hlist_for_each_entry_rcu(backbone_gw, node, head, hash_entry) {
1eda58bf
SE
1132 if (!batadv_compare_eth(backbone_gw->orig,
1133 primary_if->net_dev->dev_addr))
23721387
SW
1134 continue;
1135
1136 backbone_gw->lasttime = jiffies;
1137
3b300de3 1138 batadv_bla_send_announce(bat_priv, backbone_gw);
23721387
SW
1139 }
1140 rcu_read_unlock();
1141 }
1142out:
1143 if (primary_if)
e5d89254 1144 batadv_hardif_free_ref(primary_if);
23721387 1145
3b300de3 1146 batadv_bla_start_timer(bat_priv);
23721387
SW
1147}
1148
5d52dad2
SE
1149/* The hash for claim and backbone hash receive the same key because they
1150 * are getting initialized by hash_new with the same key. Reinitializing
1151 * them with to different keys to allow nested locking without generating
1152 * lockdep warnings
1153 */
3b300de3
SE
1154static struct lock_class_key batadv_claim_hash_lock_class_key;
1155static struct lock_class_key batadv_backbone_hash_lock_class_key;
5d52dad2 1156
23721387 1157/* initialize all bla structures */
56303d34 1158int batadv_bla_init(struct batadv_priv *bat_priv)
23721387 1159{
fe2da6ff 1160 int i;
38ef3d1d 1161 uint8_t claim_dest[ETH_ALEN] = {0xff, 0x43, 0x05, 0x00, 0x00, 0x00};
56303d34 1162 struct batadv_hard_iface *primary_if;
fe2da6ff 1163
39c75a51 1164 batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla hash registering\n");
23721387 1165
38ef3d1d
SW
1166 /* setting claim destination address */
1167 memcpy(&bat_priv->claim_dest.magic, claim_dest, 3);
1168 bat_priv->claim_dest.type = 0;
e5d89254 1169 primary_if = batadv_primary_if_get_selected(bat_priv);
38ef3d1d
SW
1170 if (primary_if) {
1171 bat_priv->claim_dest.group =
1172 htons(crc16(0, primary_if->net_dev->dev_addr,
1173 ETH_ALEN));
e5d89254 1174 batadv_hardif_free_ref(primary_if);
38ef3d1d
SW
1175 } else {
1176 bat_priv->claim_dest.group = 0; /* will be set later */
1177 }
1178
fe2da6ff 1179 /* initialize the duplicate list */
42d0b044 1180 for (i = 0; i < BATADV_DUPLIST_SIZE; i++)
fe2da6ff 1181 bat_priv->bcast_duplist[i].entrytime =
42d0b044 1182 jiffies - msecs_to_jiffies(BATADV_DUPLIST_TIMEOUT);
fe2da6ff
SW
1183 bat_priv->bcast_duplist_curr = 0;
1184
23721387 1185 if (bat_priv->claim_hash)
5346c35e 1186 return 0;
23721387 1187
1a8eaf07
SE
1188 bat_priv->claim_hash = batadv_hash_new(128);
1189 bat_priv->backbone_hash = batadv_hash_new(32);
23721387
SW
1190
1191 if (!bat_priv->claim_hash || !bat_priv->backbone_hash)
5346c35e 1192 return -ENOMEM;
23721387 1193
5d52dad2 1194 batadv_hash_set_lock_class(bat_priv->claim_hash,
3b300de3 1195 &batadv_claim_hash_lock_class_key);
5d52dad2 1196 batadv_hash_set_lock_class(bat_priv->backbone_hash,
3b300de3 1197 &batadv_backbone_hash_lock_class_key);
5d52dad2 1198
39c75a51 1199 batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla hashes initialized\n");
23721387 1200
3b300de3 1201 batadv_bla_start_timer(bat_priv);
5346c35e 1202 return 0;
23721387
SW
1203}
1204
2c53040f
BH
1205/**
1206 * batadv_bla_check_bcast_duplist
1207 * @bat_priv: the bat priv with all the soft interface information
fe2da6ff
SW
1208 * @bcast_packet: originator mac address
1209 * @hdr_size: maximum length of the frame
1210 *
1211 * check if it is on our broadcast list. Another gateway might
1212 * have sent the same packet because it is connected to the same backbone,
1213 * so we have to remove this duplicate.
1214 *
1215 * This is performed by checking the CRC, which will tell us
1216 * with a good chance that it is the same packet. If it is furthermore
1217 * sent by another host, drop it. We allow equal packets from
1218 * the same host however as this might be intended.
9cfc7bd6 1219 */
56303d34 1220int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
96412690 1221 struct batadv_bcast_packet *bcast_packet,
08adf151 1222 int hdr_size)
fe2da6ff
SW
1223{
1224 int i, length, curr;
1225 uint8_t *content;
1226 uint16_t crc;
56303d34 1227 struct batadv_bcast_duplist_entry *entry;
fe2da6ff
SW
1228
1229 length = hdr_size - sizeof(*bcast_packet);
1230 content = (uint8_t *)bcast_packet;
1231 content += sizeof(*bcast_packet);
1232
1233 /* calculate the crc ... */
1234 crc = crc16(0, content, length);
1235
42d0b044
SE
1236 for (i = 0; i < BATADV_DUPLIST_SIZE; i++) {
1237 curr = (bat_priv->bcast_duplist_curr + i) % BATADV_DUPLIST_SIZE;
fe2da6ff
SW
1238 entry = &bat_priv->bcast_duplist[curr];
1239
1240 /* we can stop searching if the entry is too old ;
1241 * later entries will be even older
1242 */
42d0b044
SE
1243 if (batadv_has_timed_out(entry->entrytime,
1244 BATADV_DUPLIST_TIMEOUT))
fe2da6ff
SW
1245 break;
1246
1247 if (entry->crc != crc)
1248 continue;
1249
1eda58bf 1250 if (batadv_compare_eth(entry->orig, bcast_packet->orig))
fe2da6ff
SW
1251 continue;
1252
1253 /* this entry seems to match: same crc, not too old,
1254 * and from another gw. therefore return 1 to forbid it.
1255 */
1256 return 1;
1257 }
1258 /* not found, add a new entry (overwrite the oldest entry) */
42d0b044
SE
1259 curr = (bat_priv->bcast_duplist_curr + BATADV_DUPLIST_SIZE - 1);
1260 curr %= BATADV_DUPLIST_SIZE;
fe2da6ff
SW
1261 entry = &bat_priv->bcast_duplist[curr];
1262 entry->crc = crc;
1263 entry->entrytime = jiffies;
1264 memcpy(entry->orig, bcast_packet->orig, ETH_ALEN);
1265 bat_priv->bcast_duplist_curr = curr;
1266
1267 /* allow it, its the first occurence. */
1268 return 0;
1269}
1270
1271
1272
9cfc7bd6 1273/* @bat_priv: the bat priv with all the soft interface information
20ff9d59
SW
1274 * @orig: originator mac address
1275 *
1276 * check if the originator is a gateway for any VLAN ID.
1277 *
1278 * returns 1 if it is found, 0 otherwise
20ff9d59 1279 */
56303d34 1280int batadv_bla_is_backbone_gw_orig(struct batadv_priv *bat_priv, uint8_t *orig)
20ff9d59 1281{
5bf74e9c 1282 struct batadv_hashtable *hash = bat_priv->backbone_hash;
20ff9d59
SW
1283 struct hlist_head *head;
1284 struct hlist_node *node;
56303d34 1285 struct batadv_backbone_gw *backbone_gw;
20ff9d59
SW
1286 int i;
1287
1288 if (!atomic_read(&bat_priv->bridge_loop_avoidance))
1289 return 0;
1290
1291 if (!hash)
1292 return 0;
1293
1294 for (i = 0; i < hash->size; i++) {
1295 head = &hash->table[i];
1296
1297 rcu_read_lock();
1298 hlist_for_each_entry_rcu(backbone_gw, node, head, hash_entry) {
1eda58bf 1299 if (batadv_compare_eth(backbone_gw->orig, orig)) {
20ff9d59
SW
1300 rcu_read_unlock();
1301 return 1;
1302 }
1303 }
1304 rcu_read_unlock();
1305 }
1306
1307 return 0;
1308}
1309
1310
2c53040f
BH
1311/**
1312 * batadv_bla_is_backbone_gw
1313 * @skb: the frame to be checked
23721387
SW
1314 * @orig_node: the orig_node of the frame
1315 * @hdr_size: maximum length of the frame
1316 *
1317 * bla_is_backbone_gw inspects the skb for the VLAN ID and returns 1
1318 * if the orig_node is also a gateway on the soft interface, otherwise it
1319 * returns 0.
23721387 1320 */
08adf151 1321int batadv_bla_is_backbone_gw(struct sk_buff *skb,
56303d34 1322 struct batadv_orig_node *orig_node, int hdr_size)
23721387
SW
1323{
1324 struct ethhdr *ethhdr;
1325 struct vlan_ethhdr *vhdr;
56303d34 1326 struct batadv_backbone_gw *backbone_gw;
23721387
SW
1327 short vid = -1;
1328
1329 if (!atomic_read(&orig_node->bat_priv->bridge_loop_avoidance))
1330 return 0;
1331
1332 /* first, find out the vid. */
0d125074 1333 if (!pskb_may_pull(skb, hdr_size + ETH_HLEN))
23721387
SW
1334 return 0;
1335
1336 ethhdr = (struct ethhdr *)(((uint8_t *)skb->data) + hdr_size);
1337
1338 if (ntohs(ethhdr->h_proto) == ETH_P_8021Q) {
1339 if (!pskb_may_pull(skb, hdr_size + sizeof(struct vlan_ethhdr)))
1340 return 0;
1341
1342 vhdr = (struct vlan_ethhdr *)(((uint8_t *)skb->data) +
1343 hdr_size);
1344 vid = ntohs(vhdr->h_vlan_TCI) & VLAN_VID_MASK;
1345 }
1346
1347 /* see if this originator is a backbone gw for this VLAN */
3b300de3
SE
1348 backbone_gw = batadv_backbone_hash_find(orig_node->bat_priv,
1349 orig_node->orig, vid);
23721387
SW
1350 if (!backbone_gw)
1351 return 0;
1352
3b300de3 1353 batadv_backbone_gw_free_ref(backbone_gw);
23721387
SW
1354 return 1;
1355}
1356
1357/* free all bla structures (for softinterface free or module unload) */
56303d34 1358void batadv_bla_free(struct batadv_priv *bat_priv)
23721387 1359{
56303d34 1360 struct batadv_hard_iface *primary_if;
23721387
SW
1361
1362 cancel_delayed_work_sync(&bat_priv->bla_work);
e5d89254 1363 primary_if = batadv_primary_if_get_selected(bat_priv);
23721387
SW
1364
1365 if (bat_priv->claim_hash) {
3b300de3 1366 batadv_bla_purge_claims(bat_priv, primary_if, 1);
1a8eaf07 1367 batadv_hash_destroy(bat_priv->claim_hash);
23721387
SW
1368 bat_priv->claim_hash = NULL;
1369 }
1370 if (bat_priv->backbone_hash) {
3b300de3 1371 batadv_bla_purge_backbone_gw(bat_priv, 1);
1a8eaf07 1372 batadv_hash_destroy(bat_priv->backbone_hash);
23721387
SW
1373 bat_priv->backbone_hash = NULL;
1374 }
1375 if (primary_if)
e5d89254 1376 batadv_hardif_free_ref(primary_if);
23721387
SW
1377}
1378
2c53040f
BH
1379/**
1380 * batadv_bla_rx
1381 * @bat_priv: the bat priv with all the soft interface information
23721387
SW
1382 * @skb: the frame to be checked
1383 * @vid: the VLAN ID of the frame
2d3f6ccc 1384 * @is_bcast: the packet came in a broadcast packet type.
23721387
SW
1385 *
1386 * bla_rx avoidance checks if:
1387 * * we have to race for a claim
1388 * * if the frame is allowed on the LAN
1389 *
1390 * in these cases, the skb is further handled by this function and
1391 * returns 1, otherwise it returns 0 and the caller shall further
1392 * process the skb.
23721387 1393 */
04c9f416
DM
1394int batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb, short vid,
1395 bool is_bcast)
23721387
SW
1396{
1397 struct ethhdr *ethhdr;
56303d34
SE
1398 struct batadv_claim search_claim, *claim = NULL;
1399 struct batadv_hard_iface *primary_if;
23721387
SW
1400 int ret;
1401
1402 ethhdr = (struct ethhdr *)skb_mac_header(skb);
1403
e5d89254 1404 primary_if = batadv_primary_if_get_selected(bat_priv);
23721387
SW
1405 if (!primary_if)
1406 goto handled;
1407
1408 if (!atomic_read(&bat_priv->bridge_loop_avoidance))
1409 goto allow;
1410
1411
1412 if (unlikely(atomic_read(&bat_priv->bla_num_requests)))
1413 /* don't allow broadcasts while requests are in flight */
2d3f6ccc 1414 if (is_multicast_ether_addr(ethhdr->h_dest) && is_bcast)
23721387
SW
1415 goto handled;
1416
1417 memcpy(search_claim.addr, ethhdr->h_source, ETH_ALEN);
1418 search_claim.vid = vid;
3b300de3 1419 claim = batadv_claim_hash_find(bat_priv, &search_claim);
23721387
SW
1420
1421 if (!claim) {
1422 /* possible optimization: race for a claim */
1423 /* No claim exists yet, claim it for us!
1424 */
3b300de3
SE
1425 batadv_handle_claim(bat_priv, primary_if,
1426 primary_if->net_dev->dev_addr,
1427 ethhdr->h_source, vid);
23721387
SW
1428 goto allow;
1429 }
1430
1431 /* if it is our own claim ... */
1eda58bf
SE
1432 if (batadv_compare_eth(claim->backbone_gw->orig,
1433 primary_if->net_dev->dev_addr)) {
23721387
SW
1434 /* ... allow it in any case */
1435 claim->lasttime = jiffies;
1436 goto allow;
1437 }
1438
1439 /* if it is a broadcast ... */
2d3f6ccc
SW
1440 if (is_multicast_ether_addr(ethhdr->h_dest) && is_bcast) {
1441 /* ... drop it. the responsible gateway is in charge.
1442 *
1443 * We need to check is_bcast because with the gateway
1444 * feature, broadcasts (like DHCP requests) may be sent
1445 * using a unicast packet type.
1446 */
23721387
SW
1447 goto handled;
1448 } else {
1449 /* seems the client considers us as its best gateway.
1450 * send a claim and update the claim table
1451 * immediately.
1452 */
3b300de3
SE
1453 batadv_handle_claim(bat_priv, primary_if,
1454 primary_if->net_dev->dev_addr,
1455 ethhdr->h_source, vid);
23721387
SW
1456 goto allow;
1457 }
1458allow:
3b300de3 1459 batadv_bla_update_own_backbone_gw(bat_priv, primary_if, vid);
23721387
SW
1460 ret = 0;
1461 goto out;
1462
1463handled:
1464 kfree_skb(skb);
1465 ret = 1;
1466
1467out:
1468 if (primary_if)
e5d89254 1469 batadv_hardif_free_ref(primary_if);
23721387 1470 if (claim)
3b300de3 1471 batadv_claim_free_ref(claim);
23721387
SW
1472 return ret;
1473}
1474
2c53040f
BH
1475/**
1476 * batadv_bla_tx
1477 * @bat_priv: the bat priv with all the soft interface information
23721387
SW
1478 * @skb: the frame to be checked
1479 * @vid: the VLAN ID of the frame
1480 *
1481 * bla_tx checks if:
1482 * * a claim was received which has to be processed
1483 * * the frame is allowed on the mesh
1484 *
1485 * in these cases, the skb is further handled by this function and
1486 * returns 1, otherwise it returns 0 and the caller shall further
1487 * process the skb.
23721387 1488 */
56303d34 1489int batadv_bla_tx(struct batadv_priv *bat_priv, struct sk_buff *skb, short vid)
23721387
SW
1490{
1491 struct ethhdr *ethhdr;
56303d34
SE
1492 struct batadv_claim search_claim, *claim = NULL;
1493 struct batadv_hard_iface *primary_if;
23721387
SW
1494 int ret = 0;
1495
e5d89254 1496 primary_if = batadv_primary_if_get_selected(bat_priv);
23721387
SW
1497 if (!primary_if)
1498 goto out;
1499
1500 if (!atomic_read(&bat_priv->bridge_loop_avoidance))
1501 goto allow;
1502
1503 /* in VLAN case, the mac header might not be set. */
1504 skb_reset_mac_header(skb);
1505
3b300de3 1506 if (batadv_bla_process_claim(bat_priv, primary_if, skb))
23721387
SW
1507 goto handled;
1508
1509 ethhdr = (struct ethhdr *)skb_mac_header(skb);
1510
1511 if (unlikely(atomic_read(&bat_priv->bla_num_requests)))
1512 /* don't allow broadcasts while requests are in flight */
1513 if (is_multicast_ether_addr(ethhdr->h_dest))
1514 goto handled;
1515
1516 memcpy(search_claim.addr, ethhdr->h_source, ETH_ALEN);
1517 search_claim.vid = vid;
1518
3b300de3 1519 claim = batadv_claim_hash_find(bat_priv, &search_claim);
23721387
SW
1520
1521 /* if no claim exists, allow it. */
1522 if (!claim)
1523 goto allow;
1524
1525 /* check if we are responsible. */
1eda58bf
SE
1526 if (batadv_compare_eth(claim->backbone_gw->orig,
1527 primary_if->net_dev->dev_addr)) {
23721387
SW
1528 /* if yes, the client has roamed and we have
1529 * to unclaim it.
1530 */
3b300de3
SE
1531 batadv_handle_unclaim(bat_priv, primary_if,
1532 primary_if->net_dev->dev_addr,
1533 ethhdr->h_source, vid);
23721387
SW
1534 goto allow;
1535 }
1536
1537 /* check if it is a multicast/broadcast frame */
1538 if (is_multicast_ether_addr(ethhdr->h_dest)) {
1539 /* drop it. the responsible gateway has forwarded it into
1540 * the backbone network.
1541 */
1542 goto handled;
1543 } else {
1544 /* we must allow it. at least if we are
1545 * responsible for the DESTINATION.
1546 */
1547 goto allow;
1548 }
1549allow:
3b300de3 1550 batadv_bla_update_own_backbone_gw(bat_priv, primary_if, vid);
23721387
SW
1551 ret = 0;
1552 goto out;
1553handled:
1554 ret = 1;
1555out:
1556 if (primary_if)
e5d89254 1557 batadv_hardif_free_ref(primary_if);
23721387 1558 if (claim)
3b300de3 1559 batadv_claim_free_ref(claim);
23721387
SW
1560 return ret;
1561}
9bf8e4d4 1562
08adf151 1563int batadv_bla_claim_table_seq_print_text(struct seq_file *seq, void *offset)
9bf8e4d4
SW
1564{
1565 struct net_device *net_dev = (struct net_device *)seq->private;
56303d34 1566 struct batadv_priv *bat_priv = netdev_priv(net_dev);
5bf74e9c 1567 struct batadv_hashtable *hash = bat_priv->claim_hash;
56303d34
SE
1568 struct batadv_claim *claim;
1569 struct batadv_hard_iface *primary_if;
9bf8e4d4
SW
1570 struct hlist_node *node;
1571 struct hlist_head *head;
1572 uint32_t i;
1573 bool is_own;
1574 int ret = 0;
1eda58bf 1575 uint8_t *primary_addr;
9bf8e4d4 1576
e5d89254 1577 primary_if = batadv_primary_if_get_selected(bat_priv);
9bf8e4d4
SW
1578 if (!primary_if) {
1579 ret = seq_printf(seq,
1580 "BATMAN mesh %s disabled - please specify interfaces to enable it\n",
1581 net_dev->name);
1582 goto out;
1583 }
1584
e9a4f295 1585 if (primary_if->if_status != BATADV_IF_ACTIVE) {
9bf8e4d4
SW
1586 ret = seq_printf(seq,
1587 "BATMAN mesh %s disabled - primary interface not active\n",
1588 net_dev->name);
1589 goto out;
1590 }
1591
1eda58bf 1592 primary_addr = primary_if->net_dev->dev_addr;
38ef3d1d
SW
1593 seq_printf(seq,
1594 "Claims announced for the mesh %s (orig %pM, group id %04x)\n",
1eda58bf 1595 net_dev->name, primary_addr,
38ef3d1d 1596 ntohs(bat_priv->claim_dest.group));
9bf8e4d4
SW
1597 seq_printf(seq, " %-17s %-5s %-17s [o] (%-4s)\n",
1598 "Client", "VID", "Originator", "CRC");
1599 for (i = 0; i < hash->size; i++) {
1600 head = &hash->table[i];
1601
1602 rcu_read_lock();
1603 hlist_for_each_entry_rcu(claim, node, head, hash_entry) {
1eda58bf
SE
1604 is_own = batadv_compare_eth(claim->backbone_gw->orig,
1605 primary_addr);
9bf8e4d4
SW
1606 seq_printf(seq, " * %pM on % 5d by %pM [%c] (%04x)\n",
1607 claim->addr, claim->vid,
1608 claim->backbone_gw->orig,
1609 (is_own ? 'x' : ' '),
1610 claim->backbone_gw->crc);
1611 }
1612 rcu_read_unlock();
1613 }
1614out:
1615 if (primary_if)
e5d89254 1616 batadv_hardif_free_ref(primary_if);
9bf8e4d4
SW
1617 return ret;
1618}
This page took 0.194019 seconds and 5 git commands to generate.