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