blob: 7e60466f571844fb757d1bf71913e7a4c34edfd7 [file] [log] [blame]
Sven Eckelmann9cfc7bd2012-05-12 02:09:43 +02001/* Copyright (C) 2011-2012 B.A.T.M.A.N. contributors:
Simon Wunderlich23721382012-01-22 20:00:19 +01002 *
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
Simon Wunderlich23721382012-01-22 20:00:19 +010018 */
19
20#include "main.h"
21#include "hash.h"
22#include "hard-interface.h"
23#include "originator.h"
24#include "bridge_loop_avoidance.h"
Simon Wunderlich20ff9d52012-01-22 20:00:23 +010025#include "translation-table.h"
Simon Wunderlich23721382012-01-22 20:00:19 +010026#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
Sven Eckelmann3b300de2012-05-12 18:33:53 +020034static const uint8_t batadv_announce_mac[4] = {0x43, 0x05, 0x43, 0x05};
Simon Wunderlich23721382012-01-22 20:00:19 +010035
Sven Eckelmann3b300de2012-05-12 18:33:53 +020036static void batadv_bla_periodic_work(struct work_struct *work);
Sven Eckelmann56303d32012-06-05 22:31:31 +020037static void batadv_bla_send_announce(struct batadv_priv *bat_priv,
38 struct batadv_backbone_gw *backbone_gw);
Simon Wunderlich23721382012-01-22 20:00:19 +010039
40/* return the index of the claim */
Sven Eckelmann3b300de2012-05-12 18:33:53 +020041static inline uint32_t batadv_choose_claim(const void *data, uint32_t size)
Simon Wunderlich23721382012-01-22 20:00:19 +010042{
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 */
Sven Eckelmann3b300de2012-05-12 18:33:53 +020061static inline uint32_t batadv_choose_backbone_gw(const void *data,
62 uint32_t size)
Simon Wunderlich23721382012-01-22 20:00:19 +010063{
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 */
Sven Eckelmann3b300de2012-05-12 18:33:53 +020083static int batadv_compare_backbone_gw(const struct hlist_node *node,
84 const void *data2)
Simon Wunderlich23721382012-01-22 20:00:19 +010085{
Sven Eckelmann56303d32012-06-05 22:31:31 +020086 const void *data1 = container_of(node, struct batadv_backbone_gw,
Simon Wunderlich23721382012-01-22 20:00:19 +010087 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 */
Sven Eckelmann3b300de2012-05-12 18:33:53 +020093static int batadv_compare_claim(const struct hlist_node *node,
94 const void *data2)
Simon Wunderlich23721382012-01-22 20:00:19 +010095{
Sven Eckelmann56303d32012-06-05 22:31:31 +020096 const void *data1 = container_of(node, struct batadv_claim,
Simon Wunderlich23721382012-01-22 20:00:19 +010097 hash_entry);
98
99 return (memcmp(data1, data2, ETH_ALEN + sizeof(short)) == 0 ? 1 : 0);
100}
101
102/* free a backbone gw */
Sven Eckelmann56303d32012-06-05 22:31:31 +0200103static void batadv_backbone_gw_free_ref(struct batadv_backbone_gw *backbone_gw)
Simon Wunderlich23721382012-01-22 20:00:19 +0100104{
105 if (atomic_dec_and_test(&backbone_gw->refcount))
106 kfree_rcu(backbone_gw, rcu);
107}
108
109/* finally deinitialize the claim */
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200110static void batadv_claim_free_rcu(struct rcu_head *rcu)
Simon Wunderlich23721382012-01-22 20:00:19 +0100111{
Sven Eckelmann56303d32012-06-05 22:31:31 +0200112 struct batadv_claim *claim;
Simon Wunderlich23721382012-01-22 20:00:19 +0100113
Sven Eckelmann56303d32012-06-05 22:31:31 +0200114 claim = container_of(rcu, struct batadv_claim, rcu);
Simon Wunderlich23721382012-01-22 20:00:19 +0100115
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200116 batadv_backbone_gw_free_ref(claim->backbone_gw);
Simon Wunderlich23721382012-01-22 20:00:19 +0100117 kfree(claim);
118}
119
120/* free a claim, call claim_free_rcu if its the last reference */
Sven Eckelmann56303d32012-06-05 22:31:31 +0200121static void batadv_claim_free_ref(struct batadv_claim *claim)
Simon Wunderlich23721382012-01-22 20:00:19 +0100122{
123 if (atomic_dec_and_test(&claim->refcount))
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200124 call_rcu(&claim->rcu, batadv_claim_free_rcu);
Simon Wunderlich23721382012-01-22 20:00:19 +0100125}
126
Sven Eckelmann9cfc7bd2012-05-12 02:09:43 +0200127/* @bat_priv: the bat priv with all the soft interface information
Simon Wunderlich23721382012-01-22 20:00:19 +0100128 * @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 */
Sven Eckelmann56303d32012-06-05 22:31:31 +0200133static struct batadv_claim *batadv_claim_hash_find(struct batadv_priv *bat_priv,
134 struct batadv_claim *data)
Simon Wunderlich23721382012-01-22 20:00:19 +0100135{
Sven Eckelmann5bf74e92012-06-05 22:31:28 +0200136 struct batadv_hashtable *hash = bat_priv->claim_hash;
Simon Wunderlich23721382012-01-22 20:00:19 +0100137 struct hlist_head *head;
138 struct hlist_node *node;
Sven Eckelmann56303d32012-06-05 22:31:31 +0200139 struct batadv_claim *claim;
140 struct batadv_claim *claim_tmp = NULL;
Simon Wunderlich23721382012-01-22 20:00:19 +0100141 int index;
142
143 if (!hash)
144 return NULL;
145
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200146 index = batadv_choose_claim(data, hash->size);
Simon Wunderlich23721382012-01-22 20:00:19 +0100147 head = &hash->table[index];
148
149 rcu_read_lock();
150 hlist_for_each_entry_rcu(claim, node, head, hash_entry) {
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200151 if (!batadv_compare_claim(&claim->hash_entry, data))
Simon Wunderlich23721382012-01-22 20:00:19 +0100152 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
Ben Hutchings2c530402012-07-10 10:55:09 +0000165/**
166 * batadv_backbone_hash_find - looks for a claim in the hash
167 * @bat_priv: the bat priv with all the soft interface information
Simon Wunderlich23721382012-01-22 20:00:19 +0100168 * @addr: the address of the originator
169 * @vid: the VLAN ID
170 *
Ben Hutchings2c530402012-07-10 10:55:09 +0000171 * Returns claim if found or NULL otherwise.
Simon Wunderlich23721382012-01-22 20:00:19 +0100172 */
Sven Eckelmann56303d32012-06-05 22:31:31 +0200173static struct batadv_backbone_gw *
174batadv_backbone_hash_find(struct batadv_priv *bat_priv,
175 uint8_t *addr, short vid)
Simon Wunderlich23721382012-01-22 20:00:19 +0100176{
Sven Eckelmann5bf74e92012-06-05 22:31:28 +0200177 struct batadv_hashtable *hash = bat_priv->backbone_hash;
Simon Wunderlich23721382012-01-22 20:00:19 +0100178 struct hlist_head *head;
179 struct hlist_node *node;
Sven Eckelmann56303d32012-06-05 22:31:31 +0200180 struct batadv_backbone_gw search_entry, *backbone_gw;
181 struct batadv_backbone_gw *backbone_gw_tmp = NULL;
Simon Wunderlich23721382012-01-22 20:00:19 +0100182 int index;
183
184 if (!hash)
185 return NULL;
186
187 memcpy(search_entry.orig, addr, ETH_ALEN);
188 search_entry.vid = vid;
189
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200190 index = batadv_choose_backbone_gw(&search_entry, hash->size);
Simon Wunderlich23721382012-01-22 20:00:19 +0100191 head = &hash->table[index];
192
193 rcu_read_lock();
194 hlist_for_each_entry_rcu(backbone_gw, node, head, hash_entry) {
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200195 if (!batadv_compare_backbone_gw(&backbone_gw->hash_entry,
196 &search_entry))
Simon Wunderlich23721382012-01-22 20:00:19 +0100197 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 */
Sven Eckelmann56303d32012-06-05 22:31:31 +0200211static void
212batadv_bla_del_backbone_claims(struct batadv_backbone_gw *backbone_gw)
Simon Wunderlich23721382012-01-22 20:00:19 +0100213{
Sven Eckelmann5bf74e92012-06-05 22:31:28 +0200214 struct batadv_hashtable *hash;
Simon Wunderlich23721382012-01-22 20:00:19 +0100215 struct hlist_node *node, *node_tmp;
216 struct hlist_head *head;
Sven Eckelmann56303d32012-06-05 22:31:31 +0200217 struct batadv_claim *claim;
Simon Wunderlich23721382012-01-22 20:00:19 +0100218 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
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200236 batadv_claim_free_ref(claim);
Simon Wunderlich23721382012-01-22 20:00:19 +0100237 hlist_del_rcu(node);
238 }
239 spin_unlock_bh(list_lock);
240 }
241
242 /* all claims gone, intialize CRC */
Sven Eckelmann3964f722012-06-03 22:19:10 +0200243 backbone_gw->crc = BATADV_BLA_CRC_INIT;
Simon Wunderlich23721382012-01-22 20:00:19 +0100244}
245
Ben Hutchings2c530402012-07-10 10:55:09 +0000246/**
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
Simon Wunderlich23721382012-01-22 20:00:19 +0100249 * @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, ...)
Simon Wunderlich23721382012-01-22 20:00:19 +0100252 */
Sven Eckelmann56303d32012-06-05 22:31:31 +0200253static void batadv_bla_send_claim(struct batadv_priv *bat_priv, uint8_t *mac,
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200254 short vid, int claimtype)
Simon Wunderlich23721382012-01-22 20:00:19 +0100255{
256 struct sk_buff *skb;
257 struct ethhdr *ethhdr;
Sven Eckelmann56303d32012-06-05 22:31:31 +0200258 struct batadv_hard_iface *primary_if;
Simon Wunderlich23721382012-01-22 20:00:19 +0100259 struct net_device *soft_iface;
260 uint8_t *hw_src;
Sven Eckelmann96412692012-06-05 22:31:30 +0200261 struct batadv_bla_claim_dst local_claim_dest;
Al Viro3e2f1a12012-04-22 07:47:50 +0100262 __be32 zeroip = 0;
Simon Wunderlich23721382012-01-22 20:00:19 +0100263
Sven Eckelmanne5d89252012-05-12 13:48:54 +0200264 primary_if = batadv_primary_if_get_selected(bat_priv);
Simon Wunderlich23721382012-01-22 20:00:19 +0100265 if (!primary_if)
266 return;
267
Simon Wunderlich38ef3d12012-01-22 20:00:26 +0100268 memcpy(&local_claim_dest, &bat_priv->claim_dest,
269 sizeof(local_claim_dest));
Simon Wunderlich23721382012-01-22 20:00:19 +0100270 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
Simon Wunderlich38ef3d12012-01-22 20:00:26 +0100286 * and YY:YY = group id
Simon Wunderlich23721382012-01-22 20:00:19 +0100287 */
288 (uint8_t *)&local_claim_dest);
289
290 if (!skb)
291 goto out;
292
293 ethhdr = (struct ethhdr *)skb->data;
Antonio Quartulli0d125072012-02-18 11:27:34 +0100294 hw_src = (uint8_t *)ethhdr + ETH_HLEN + sizeof(struct arphdr);
Simon Wunderlich23721382012-01-22 20:00:19 +0100295
296 /* now we pretend that the client would have sent this ... */
297 switch (claimtype) {
Sven Eckelmannacd34af2012-06-03 22:19:21 +0200298 case BATADV_CLAIM_TYPE_ADD:
Simon Wunderlich23721382012-01-22 20:00:19 +0100299 /* normal claim frame
300 * set Ethernet SRC to the clients mac
301 */
302 memcpy(ethhdr->h_source, mac, ETH_ALEN);
Sven Eckelmann39c75a52012-06-03 22:19:22 +0200303 batadv_dbg(BATADV_DBG_BLA, bat_priv,
Sven Eckelmann1eda58b2012-05-12 13:48:58 +0200304 "bla_send_claim(): CLAIM %pM on vid %d\n", mac, vid);
Simon Wunderlich23721382012-01-22 20:00:19 +0100305 break;
Sven Eckelmannacd34af2012-06-03 22:19:21 +0200306 case BATADV_CLAIM_TYPE_DEL:
Simon Wunderlich23721382012-01-22 20:00:19 +0100307 /* unclaim frame
308 * set HW SRC to the clients mac
309 */
310 memcpy(hw_src, mac, ETH_ALEN);
Sven Eckelmann39c75a52012-06-03 22:19:22 +0200311 batadv_dbg(BATADV_DBG_BLA, bat_priv,
Sven Eckelmann1eda58b2012-05-12 13:48:58 +0200312 "bla_send_claim(): UNCLAIM %pM on vid %d\n", mac,
313 vid);
Simon Wunderlich23721382012-01-22 20:00:19 +0100314 break;
Sven Eckelmannacd34af2012-06-03 22:19:21 +0200315 case BATADV_CLAIM_TYPE_ANNOUNCE:
Simon Wunderlich23721382012-01-22 20:00:19 +0100316 /* announcement frame
317 * set HW SRC to the special mac containg the crc
318 */
319 memcpy(hw_src, mac, ETH_ALEN);
Sven Eckelmann39c75a52012-06-03 22:19:22 +0200320 batadv_dbg(BATADV_DBG_BLA, bat_priv,
Sven Eckelmann1eda58b2012-05-12 13:48:58 +0200321 "bla_send_claim(): ANNOUNCE of %pM on vid %d\n",
322 ethhdr->h_source, vid);
Simon Wunderlich23721382012-01-22 20:00:19 +0100323 break;
Sven Eckelmannacd34af2012-06-03 22:19:21 +0200324 case BATADV_CLAIM_TYPE_REQUEST:
Simon Wunderlich23721382012-01-22 20:00:19 +0100325 /* 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);
Sven Eckelmann39c75a52012-06-03 22:19:22 +0200330 batadv_dbg(BATADV_DBG_BLA, bat_priv,
Sven Eckelmann1eda58b2012-05-12 13:48:58 +0200331 "bla_send_claim(): REQUEST of %pM to %pMon vid %d\n",
332 ethhdr->h_source, ethhdr->h_dest, vid);
Simon Wunderlich23721382012-01-22 20:00:19 +0100333 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++;
Antonio Quartulli0d125072012-02-18 11:27:34 +0100343 bat_priv->stats.rx_bytes += skb->len + ETH_HLEN;
Simon Wunderlich23721382012-01-22 20:00:19 +0100344 soft_iface->last_rx = jiffies;
345
346 netif_rx(skb);
347out:
348 if (primary_if)
Sven Eckelmanne5d89252012-05-12 13:48:54 +0200349 batadv_hardif_free_ref(primary_if);
Simon Wunderlich23721382012-01-22 20:00:19 +0100350}
351
Ben Hutchings2c530402012-07-10 10:55:09 +0000352/**
353 * batadv_bla_get_backbone_gw
354 * @bat_priv: the bat priv with all the soft interface information
Simon Wunderlich23721382012-01-22 20:00:19 +0100355 * @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 */
Sven Eckelmann56303d32012-06-05 22:31:31 +0200361static struct batadv_backbone_gw *
362batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv, uint8_t *orig,
363 short vid)
Simon Wunderlich23721382012-01-22 20:00:19 +0100364{
Sven Eckelmann56303d32012-06-05 22:31:31 +0200365 struct batadv_backbone_gw *entry;
366 struct batadv_orig_node *orig_node;
Simon Wunderlich23721382012-01-22 20:00:19 +0100367 int hash_added;
368
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200369 entry = batadv_backbone_hash_find(bat_priv, orig, vid);
Simon Wunderlich23721382012-01-22 20:00:19 +0100370
371 if (entry)
372 return entry;
373
Sven Eckelmann39c75a52012-06-03 22:19:22 +0200374 batadv_dbg(BATADV_DBG_BLA, bat_priv,
Sven Eckelmann1eda58b2012-05-12 13:48:58 +0200375 "bla_get_backbone_gw(): not found (%pM, %d), creating new entry\n",
376 orig, vid);
Simon Wunderlich23721382012-01-22 20:00:19 +0100377
378 entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
379 if (!entry)
380 return NULL;
381
382 entry->vid = vid;
383 entry->lasttime = jiffies;
Sven Eckelmann3964f722012-06-03 22:19:10 +0200384 entry->crc = BATADV_BLA_CRC_INIT;
Simon Wunderlich23721382012-01-22 20:00:19 +0100385 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
Sven Eckelmannc0a55922012-05-12 13:48:55 +0200392 hash_added = batadv_hash_add(bat_priv->backbone_hash,
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200393 batadv_compare_backbone_gw,
394 batadv_choose_backbone_gw, entry,
395 &entry->hash_entry);
Simon Wunderlich23721382012-01-22 20:00:19 +0100396
397 if (unlikely(hash_added != 0)) {
398 /* hash failed, free the structure */
399 kfree(entry);
400 return NULL;
401 }
402
Simon Wunderlich20ff9d52012-01-22 20:00:23 +0100403 /* this is a gateway now, remove any tt entries */
Sven Eckelmannda641192012-05-12 13:48:56 +0200404 orig_node = batadv_orig_hash_find(bat_priv, orig);
Simon Wunderlich20ff9d52012-01-22 20:00:23 +0100405 if (orig_node) {
Sven Eckelmann08c36d32012-05-12 02:09:39 +0200406 batadv_tt_global_del_orig(bat_priv, orig_node,
407 "became a backbone gateway");
Sven Eckelmann7d211ef2012-05-12 02:09:34 +0200408 batadv_orig_node_free_ref(orig_node);
Simon Wunderlich20ff9d52012-01-22 20:00:23 +0100409 }
Simon Wunderlich23721382012-01-22 20:00:19 +0100410 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 */
Sven Eckelmann56303d32012-06-05 22:31:31 +0200416static void
417batadv_bla_update_own_backbone_gw(struct batadv_priv *bat_priv,
418 struct batadv_hard_iface *primary_if,
419 short vid)
Simon Wunderlich23721382012-01-22 20:00:19 +0100420{
Sven Eckelmann56303d32012-06-05 22:31:31 +0200421 struct batadv_backbone_gw *backbone_gw;
Simon Wunderlich23721382012-01-22 20:00:19 +0100422
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200423 backbone_gw = batadv_bla_get_backbone_gw(bat_priv,
424 primary_if->net_dev->dev_addr,
425 vid);
Simon Wunderlich23721382012-01-22 20:00:19 +0100426 if (unlikely(!backbone_gw))
427 return;
428
429 backbone_gw->lasttime = jiffies;
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200430 batadv_backbone_gw_free_ref(backbone_gw);
Simon Wunderlich23721382012-01-22 20:00:19 +0100431}
432
Sven Eckelmann9cfc7bd2012-05-12 02:09:43 +0200433/* @bat_priv: the bat priv with all the soft interface information
Simon Wunderlich23721382012-01-22 20:00:19 +0100434 * @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 */
Sven Eckelmann56303d32012-06-05 22:31:31 +0200439static void batadv_bla_answer_request(struct batadv_priv *bat_priv,
440 struct batadv_hard_iface *primary_if,
441 short vid)
Simon Wunderlich23721382012-01-22 20:00:19 +0100442{
443 struct hlist_node *node;
444 struct hlist_head *head;
Sven Eckelmann5bf74e92012-06-05 22:31:28 +0200445 struct batadv_hashtable *hash;
Sven Eckelmann56303d32012-06-05 22:31:31 +0200446 struct batadv_claim *claim;
447 struct batadv_backbone_gw *backbone_gw;
Simon Wunderlich23721382012-01-22 20:00:19 +0100448 int i;
449
Sven Eckelmann39c75a52012-06-03 22:19:22 +0200450 batadv_dbg(BATADV_DBG_BLA, bat_priv,
Sven Eckelmann1eda58b2012-05-12 13:48:58 +0200451 "bla_answer_request(): received a claim request, send all of our own claims again\n");
Simon Wunderlich23721382012-01-22 20:00:19 +0100452
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200453 backbone_gw = batadv_backbone_hash_find(bat_priv,
454 primary_if->net_dev->dev_addr,
455 vid);
Simon Wunderlich23721382012-01-22 20:00:19 +0100456 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
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200469 batadv_bla_send_claim(bat_priv, claim->addr, claim->vid,
Sven Eckelmannacd34af2012-06-03 22:19:21 +0200470 BATADV_CLAIM_TYPE_ADD);
Simon Wunderlich23721382012-01-22 20:00:19 +0100471 }
472 rcu_read_unlock();
473 }
474
475 /* finally, send an announcement frame */
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200476 batadv_bla_send_announce(bat_priv, backbone_gw);
477 batadv_backbone_gw_free_ref(backbone_gw);
Simon Wunderlich23721382012-01-22 20:00:19 +0100478}
479
Sven Eckelmann9cfc7bd2012-05-12 02:09:43 +0200480/* @backbone_gw: the backbone gateway from whom we are out of sync
Simon Wunderlich23721382012-01-22 20:00:19 +0100481 *
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 */
Sven Eckelmann56303d32012-06-05 22:31:31 +0200486static void batadv_bla_send_request(struct batadv_backbone_gw *backbone_gw)
Simon Wunderlich23721382012-01-22 20:00:19 +0100487{
488 /* first, remove all old entries */
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200489 batadv_bla_del_backbone_claims(backbone_gw);
Simon Wunderlich23721382012-01-22 20:00:19 +0100490
Sven Eckelmann39c75a52012-06-03 22:19:22 +0200491 batadv_dbg(BATADV_DBG_BLA, backbone_gw->bat_priv,
492 "Sending REQUEST to %pM\n", backbone_gw->orig);
Simon Wunderlich23721382012-01-22 20:00:19 +0100493
494 /* send request */
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200495 batadv_bla_send_claim(backbone_gw->bat_priv, backbone_gw->orig,
Sven Eckelmannacd34af2012-06-03 22:19:21 +0200496 backbone_gw->vid, BATADV_CLAIM_TYPE_REQUEST);
Simon Wunderlich23721382012-01-22 20:00:19 +0100497
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
Sven Eckelmann9cfc7bd2012-05-12 02:09:43 +0200505/* @bat_priv: the bat priv with all the soft interface information
Simon Wunderlich23721382012-01-22 20:00:19 +0100506 * @backbone_gw: our backbone gateway which should be announced
507 *
508 * This function sends an announcement. It is called from multiple
509 * places.
510 */
Sven Eckelmann56303d32012-06-05 22:31:31 +0200511static void batadv_bla_send_announce(struct batadv_priv *bat_priv,
512 struct batadv_backbone_gw *backbone_gw)
Simon Wunderlich23721382012-01-22 20:00:19 +0100513{
514 uint8_t mac[ETH_ALEN];
Al Viro3e2f1a12012-04-22 07:47:50 +0100515 __be16 crc;
Simon Wunderlich23721382012-01-22 20:00:19 +0100516
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200517 memcpy(mac, batadv_announce_mac, 4);
Simon Wunderlich23721382012-01-22 20:00:19 +0100518 crc = htons(backbone_gw->crc);
Al Viro1a5852d2012-04-22 07:50:29 +0100519 memcpy(&mac[4], &crc, 2);
Simon Wunderlich23721382012-01-22 20:00:19 +0100520
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200521 batadv_bla_send_claim(bat_priv, mac, backbone_gw->vid,
Sven Eckelmannacd34af2012-06-03 22:19:21 +0200522 BATADV_CLAIM_TYPE_ANNOUNCE);
Simon Wunderlich23721382012-01-22 20:00:19 +0100523
524}
525
Ben Hutchings2c530402012-07-10 10:55:09 +0000526/**
527 * batadv_bla_add_claim - Adds a claim in the claim hash
528 * @bat_priv: the bat priv with all the soft interface information
Simon Wunderlich23721382012-01-22 20:00:19 +0100529 * @mac: the mac address of the claim
530 * @vid: the VLAN ID of the frame
531 * @backbone_gw: the backbone gateway which claims it
Simon Wunderlich23721382012-01-22 20:00:19 +0100532 */
Sven Eckelmann56303d32012-06-05 22:31:31 +0200533static 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)
Simon Wunderlich23721382012-01-22 20:00:19 +0100536{
Sven Eckelmann56303d32012-06-05 22:31:31 +0200537 struct batadv_claim *claim;
538 struct batadv_claim search_claim;
Simon Wunderlich23721382012-01-22 20:00:19 +0100539 int hash_added;
540
541 memcpy(search_claim.addr, mac, ETH_ALEN);
542 search_claim.vid = vid;
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200543 claim = batadv_claim_hash_find(bat_priv, &search_claim);
Simon Wunderlich23721382012-01-22 20:00:19 +0100544
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);
Sven Eckelmann39c75a52012-06-03 22:19:22 +0200557 batadv_dbg(BATADV_DBG_BLA, bat_priv,
Sven Eckelmann1eda58b2012-05-12 13:48:58 +0200558 "bla_add_claim(): adding new entry %pM, vid %d to hash ...\n",
559 mac, vid);
Sven Eckelmannc0a55922012-05-12 13:48:55 +0200560 hash_added = batadv_hash_add(bat_priv->claim_hash,
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200561 batadv_compare_claim,
562 batadv_choose_claim, claim,
563 &claim->hash_entry);
Simon Wunderlich23721382012-01-22 20:00:19 +0100564
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
Sven Eckelmann39c75a52012-06-03 22:19:22 +0200576 batadv_dbg(BATADV_DBG_BLA, bat_priv,
Sven Eckelmann1eda58b2012-05-12 13:48:58 +0200577 "bla_add_claim(): changing ownership for %pM, vid %d\n",
578 mac, vid);
Simon Wunderlich23721382012-01-22 20:00:19 +0100579
580 claim->backbone_gw->crc ^=
581 crc16(0, claim->addr, ETH_ALEN);
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200582 batadv_backbone_gw_free_ref(claim->backbone_gw);
Simon Wunderlich23721382012-01-22 20:00:19 +0100583
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:
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200593 batadv_claim_free_ref(claim);
Simon Wunderlich23721382012-01-22 20:00:19 +0100594}
595
596/* Delete a claim from the claim hash which has the
597 * given mac address and vid.
598 */
Sven Eckelmann56303d32012-06-05 22:31:31 +0200599static void batadv_bla_del_claim(struct batadv_priv *bat_priv,
600 const uint8_t *mac, const short vid)
Simon Wunderlich23721382012-01-22 20:00:19 +0100601{
Sven Eckelmann56303d32012-06-05 22:31:31 +0200602 struct batadv_claim search_claim, *claim;
Simon Wunderlich23721382012-01-22 20:00:19 +0100603
604 memcpy(search_claim.addr, mac, ETH_ALEN);
605 search_claim.vid = vid;
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200606 claim = batadv_claim_hash_find(bat_priv, &search_claim);
Simon Wunderlich23721382012-01-22 20:00:19 +0100607 if (!claim)
608 return;
609
Sven Eckelmann39c75a52012-06-03 22:19:22 +0200610 batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla_del_claim(): %pM, vid %d\n",
611 mac, vid);
Simon Wunderlich23721382012-01-22 20:00:19 +0100612
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200613 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 */
Simon Wunderlich23721382012-01-22 20:00:19 +0100616
617 claim->backbone_gw->crc ^= crc16(0, claim->addr, ETH_ALEN);
618
619 /* don't need the reference from hash_find() anymore */
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200620 batadv_claim_free_ref(claim);
Simon Wunderlich23721382012-01-22 20:00:19 +0100621}
622
623/* check for ANNOUNCE frame, return 1 if handled */
Sven Eckelmann56303d32012-06-05 22:31:31 +0200624static int batadv_handle_announce(struct batadv_priv *bat_priv,
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200625 uint8_t *an_addr, uint8_t *backbone_addr,
626 short vid)
Simon Wunderlich23721382012-01-22 20:00:19 +0100627{
Sven Eckelmann56303d32012-06-05 22:31:31 +0200628 struct batadv_backbone_gw *backbone_gw;
Simon Wunderlich23721382012-01-22 20:00:19 +0100629 uint16_t crc;
630
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200631 if (memcmp(an_addr, batadv_announce_mac, 4) != 0)
Simon Wunderlich23721382012-01-22 20:00:19 +0100632 return 0;
633
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200634 backbone_gw = batadv_bla_get_backbone_gw(bat_priv, backbone_addr, vid);
Simon Wunderlich23721382012-01-22 20:00:19 +0100635
636 if (unlikely(!backbone_gw))
637 return 1;
638
639
640 /* handle as ANNOUNCE frame */
641 backbone_gw->lasttime = jiffies;
Al Viro3e2f1a12012-04-22 07:47:50 +0100642 crc = ntohs(*((__be16 *)(&an_addr[4])));
Simon Wunderlich23721382012-01-22 20:00:19 +0100643
Sven Eckelmann39c75a52012-06-03 22:19:22 +0200644 batadv_dbg(BATADV_DBG_BLA, bat_priv,
Sven Eckelmann1eda58b2012-05-12 13:48:58 +0200645 "handle_announce(): ANNOUNCE vid %d (sent by %pM)... CRC = %04x\n",
646 vid, backbone_gw->orig, crc);
Simon Wunderlich23721382012-01-22 20:00:19 +0100647
648 if (backbone_gw->crc != crc) {
Sven Eckelmann39c75a52012-06-03 22:19:22 +0200649 batadv_dbg(BATADV_DBG_BLA, backbone_gw->bat_priv,
Sven Eckelmann1eda58b2012-05-12 13:48:58 +0200650 "handle_announce(): CRC FAILED for %pM/%d (my = %04x, sent = %04x)\n",
651 backbone_gw->orig, backbone_gw->vid,
652 backbone_gw->crc, crc);
Simon Wunderlich23721382012-01-22 20:00:19 +0100653
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200654 batadv_bla_send_request(backbone_gw);
Simon Wunderlich23721382012-01-22 20:00:19 +0100655 } 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
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200665 batadv_backbone_gw_free_ref(backbone_gw);
Simon Wunderlich23721382012-01-22 20:00:19 +0100666 return 1;
667}
668
669/* check for REQUEST frame, return 1 if handled */
Sven Eckelmann56303d32012-06-05 22:31:31 +0200670static int batadv_handle_request(struct batadv_priv *bat_priv,
671 struct batadv_hard_iface *primary_if,
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200672 uint8_t *backbone_addr,
673 struct ethhdr *ethhdr, short vid)
Simon Wunderlich23721382012-01-22 20:00:19 +0100674{
675 /* check for REQUEST frame */
Sven Eckelmann1eda58b2012-05-12 13:48:58 +0200676 if (!batadv_compare_eth(backbone_addr, ethhdr->h_dest))
Simon Wunderlich23721382012-01-22 20:00:19 +0100677 return 0;
678
679 /* sanity check, this should not happen on a normal switch,
680 * we ignore it in this case.
681 */
Sven Eckelmann1eda58b2012-05-12 13:48:58 +0200682 if (!batadv_compare_eth(ethhdr->h_dest, primary_if->net_dev->dev_addr))
Simon Wunderlich23721382012-01-22 20:00:19 +0100683 return 1;
684
Sven Eckelmann39c75a52012-06-03 22:19:22 +0200685 batadv_dbg(BATADV_DBG_BLA, bat_priv,
Sven Eckelmann1eda58b2012-05-12 13:48:58 +0200686 "handle_request(): REQUEST vid %d (sent by %pM)...\n",
687 vid, ethhdr->h_source);
Simon Wunderlich23721382012-01-22 20:00:19 +0100688
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200689 batadv_bla_answer_request(bat_priv, primary_if, vid);
Simon Wunderlich23721382012-01-22 20:00:19 +0100690 return 1;
691}
692
693/* check for UNCLAIM frame, return 1 if handled */
Sven Eckelmann56303d32012-06-05 22:31:31 +0200694static int batadv_handle_unclaim(struct batadv_priv *bat_priv,
695 struct batadv_hard_iface *primary_if,
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200696 uint8_t *backbone_addr,
697 uint8_t *claim_addr, short vid)
Simon Wunderlich23721382012-01-22 20:00:19 +0100698{
Sven Eckelmann56303d32012-06-05 22:31:31 +0200699 struct batadv_backbone_gw *backbone_gw;
Simon Wunderlich23721382012-01-22 20:00:19 +0100700
701 /* unclaim in any case if it is our own */
Sven Eckelmann1eda58b2012-05-12 13:48:58 +0200702 if (primary_if && batadv_compare_eth(backbone_addr,
703 primary_if->net_dev->dev_addr))
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200704 batadv_bla_send_claim(bat_priv, claim_addr, vid,
Sven Eckelmannacd34af2012-06-03 22:19:21 +0200705 BATADV_CLAIM_TYPE_DEL);
Simon Wunderlich23721382012-01-22 20:00:19 +0100706
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200707 backbone_gw = batadv_backbone_hash_find(bat_priv, backbone_addr, vid);
Simon Wunderlich23721382012-01-22 20:00:19 +0100708
709 if (!backbone_gw)
710 return 1;
711
712 /* this must be an UNCLAIM frame */
Sven Eckelmann39c75a52012-06-03 22:19:22 +0200713 batadv_dbg(BATADV_DBG_BLA, bat_priv,
Sven Eckelmann1eda58b2012-05-12 13:48:58 +0200714 "handle_unclaim(): UNCLAIM %pM on vid %d (sent by %pM)...\n",
715 claim_addr, vid, backbone_gw->orig);
Simon Wunderlich23721382012-01-22 20:00:19 +0100716
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200717 batadv_bla_del_claim(bat_priv, claim_addr, vid);
718 batadv_backbone_gw_free_ref(backbone_gw);
Simon Wunderlich23721382012-01-22 20:00:19 +0100719 return 1;
720}
721
722/* check for CLAIM frame, return 1 if handled */
Sven Eckelmann56303d32012-06-05 22:31:31 +0200723static int batadv_handle_claim(struct batadv_priv *bat_priv,
724 struct batadv_hard_iface *primary_if,
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200725 uint8_t *backbone_addr, uint8_t *claim_addr,
726 short vid)
Simon Wunderlich23721382012-01-22 20:00:19 +0100727{
Sven Eckelmann56303d32012-06-05 22:31:31 +0200728 struct batadv_backbone_gw *backbone_gw;
Simon Wunderlich23721382012-01-22 20:00:19 +0100729
730 /* register the gateway if not yet available, and add the claim. */
731
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200732 backbone_gw = batadv_bla_get_backbone_gw(bat_priv, backbone_addr, vid);
Simon Wunderlich23721382012-01-22 20:00:19 +0100733
734 if (unlikely(!backbone_gw))
735 return 1;
736
737 /* this must be a CLAIM frame */
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200738 batadv_bla_add_claim(bat_priv, claim_addr, vid, backbone_gw);
Sven Eckelmann1eda58b2012-05-12 13:48:58 +0200739 if (batadv_compare_eth(backbone_addr, primary_if->net_dev->dev_addr))
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200740 batadv_bla_send_claim(bat_priv, claim_addr, vid,
Sven Eckelmannacd34af2012-06-03 22:19:21 +0200741 BATADV_CLAIM_TYPE_ADD);
Simon Wunderlich23721382012-01-22 20:00:19 +0100742
743 /* TODO: we could call something like tt_local_del() here. */
744
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200745 batadv_backbone_gw_free_ref(backbone_gw);
Simon Wunderlich23721382012-01-22 20:00:19 +0100746 return 1;
747}
748
Ben Hutchings2c530402012-07-10 10:55:09 +0000749/**
750 * batadv_check_claim_group
751 * @bat_priv: the bat priv with all the soft interface information
Simon Wunderlich38ef3d12012-01-22 20:00:26 +0100752 * @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 */
Sven Eckelmann56303d32012-06-05 22:31:31 +0200765static int batadv_check_claim_group(struct batadv_priv *bat_priv,
766 struct batadv_hard_iface *primary_if,
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200767 uint8_t *hw_src, uint8_t *hw_dst,
768 struct ethhdr *ethhdr)
Simon Wunderlich38ef3d12012-01-22 20:00:26 +0100769{
770 uint8_t *backbone_addr;
Sven Eckelmann56303d32012-06-05 22:31:31 +0200771 struct batadv_orig_node *orig_node;
Sven Eckelmann96412692012-06-05 22:31:30 +0200772 struct batadv_bla_claim_dst *bla_dst, *bla_dst_own;
Simon Wunderlich38ef3d12012-01-22 20:00:26 +0100773
Sven Eckelmann96412692012-06-05 22:31:30 +0200774 bla_dst = (struct batadv_bla_claim_dst *)hw_dst;
Simon Wunderlich38ef3d12012-01-22 20:00:26 +0100775 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) {
Sven Eckelmannacd34af2012-06-03 22:19:21 +0200786 case BATADV_CLAIM_TYPE_ADD:
Simon Wunderlich38ef3d12012-01-22 20:00:26 +0100787 backbone_addr = hw_src;
788 break;
Sven Eckelmannacd34af2012-06-03 22:19:21 +0200789 case BATADV_CLAIM_TYPE_REQUEST:
790 case BATADV_CLAIM_TYPE_ANNOUNCE:
791 case BATADV_CLAIM_TYPE_DEL:
Simon Wunderlich38ef3d12012-01-22 20:00:26 +0100792 backbone_addr = ethhdr->h_source;
793 break;
794 default:
795 return 0;
796 }
797
798 /* don't accept claim frames from ourselves */
Sven Eckelmann1eda58b2012-05-12 13:48:58 +0200799 if (batadv_compare_eth(backbone_addr, primary_if->net_dev->dev_addr))
Simon Wunderlich38ef3d12012-01-22 20:00:26 +0100800 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 */
Sven Eckelmannda641192012-05-12 13:48:56 +0200807 orig_node = batadv_orig_hash_find(bat_priv, backbone_addr);
Simon Wunderlich38ef3d12012-01-22 20:00:26 +0100808
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)) {
Sven Eckelmann39c75a52012-06-03 22:19:22 +0200817 batadv_dbg(BATADV_DBG_BLA, bat_priv,
Sven Eckelmann1eda58b2012-05-12 13:48:58 +0200818 "taking other backbones claim group: %04x\n",
819 ntohs(bla_dst->group));
Simon Wunderlich38ef3d12012-01-22 20:00:26 +0100820 bla_dst_own->group = bla_dst->group;
821 }
822
Sven Eckelmann7d211ef2012-05-12 02:09:34 +0200823 batadv_orig_node_free_ref(orig_node);
Simon Wunderlich38ef3d12012-01-22 20:00:26 +0100824
825 return 2;
826}
827
828
Sven Eckelmann9cfc7bd2012-05-12 02:09:43 +0200829/* @bat_priv: the bat priv with all the soft interface information
Simon Wunderlich23721382012-01-22 20:00:19 +0100830 * @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 */
Sven Eckelmann56303d32012-06-05 22:31:31 +0200837static int batadv_bla_process_claim(struct batadv_priv *bat_priv,
838 struct batadv_hard_iface *primary_if,
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200839 struct sk_buff *skb)
Simon Wunderlich23721382012-01-22 20:00:19 +0100840{
841 struct ethhdr *ethhdr;
842 struct vlan_ethhdr *vhdr;
843 struct arphdr *arphdr;
844 uint8_t *hw_src, *hw_dst;
Sven Eckelmann96412692012-06-05 22:31:30 +0200845 struct batadv_bla_claim_dst *bla_dst;
Simon Wunderlich23721382012-01-22 20:00:19 +0100846 uint16_t proto;
847 int headlen;
848 short vid = -1;
Simon Wunderlich38ef3d12012-01-22 20:00:26 +0100849 int ret;
Simon Wunderlich23721382012-01-22 20:00:19 +0100850
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);
Antonio Quartulli0d125072012-02-18 11:27:34 +0100860 headlen = ETH_HLEN;
Simon Wunderlich23721382012-01-22 20:00:19 +0100861 }
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 */
Simon Wunderlich23721382012-01-22 20:00:19 +0100878 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;
Sven Eckelmann96412692012-06-05 22:31:30 +0200889 bla_dst = (struct batadv_bla_claim_dst *)hw_dst;
Simon Wunderlich23721382012-01-22 20:00:19 +0100890
891 /* check if it is a claim frame. */
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200892 ret = batadv_check_claim_group(bat_priv, primary_if, hw_src, hw_dst,
893 ethhdr);
Simon Wunderlich38ef3d12012-01-22 20:00:26 +0100894 if (ret == 1)
Sven Eckelmann39c75a52012-06-03 22:19:22 +0200895 batadv_dbg(BATADV_DBG_BLA, bat_priv,
Sven Eckelmann1eda58b2012-05-12 13:48:58 +0200896 "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);
Simon Wunderlich38ef3d12012-01-22 20:00:26 +0100898
899 if (ret < 2)
900 return ret;
Simon Wunderlich23721382012-01-22 20:00:19 +0100901
902 /* become a backbone gw ourselves on this vlan if not happened yet */
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200903 batadv_bla_update_own_backbone_gw(bat_priv, primary_if, vid);
Simon Wunderlich23721382012-01-22 20:00:19 +0100904
905 /* check for the different types of claim frames ... */
906 switch (bla_dst->type) {
Sven Eckelmannacd34af2012-06-03 22:19:21 +0200907 case BATADV_CLAIM_TYPE_ADD:
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200908 if (batadv_handle_claim(bat_priv, primary_if, hw_src,
909 ethhdr->h_source, vid))
Simon Wunderlich23721382012-01-22 20:00:19 +0100910 return 1;
911 break;
Sven Eckelmannacd34af2012-06-03 22:19:21 +0200912 case BATADV_CLAIM_TYPE_DEL:
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200913 if (batadv_handle_unclaim(bat_priv, primary_if,
914 ethhdr->h_source, hw_src, vid))
Simon Wunderlich23721382012-01-22 20:00:19 +0100915 return 1;
916 break;
917
Sven Eckelmannacd34af2012-06-03 22:19:21 +0200918 case BATADV_CLAIM_TYPE_ANNOUNCE:
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200919 if (batadv_handle_announce(bat_priv, hw_src, ethhdr->h_source,
920 vid))
Simon Wunderlich23721382012-01-22 20:00:19 +0100921 return 1;
922 break;
Sven Eckelmannacd34af2012-06-03 22:19:21 +0200923 case BATADV_CLAIM_TYPE_REQUEST:
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200924 if (batadv_handle_request(bat_priv, primary_if, hw_src, ethhdr,
925 vid))
Simon Wunderlich23721382012-01-22 20:00:19 +0100926 return 1;
927 break;
928 }
929
Sven Eckelmann39c75a52012-06-03 22:19:22 +0200930 batadv_dbg(BATADV_DBG_BLA, bat_priv,
Sven Eckelmann1eda58b2012-05-12 13:48:58 +0200931 "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);
Simon Wunderlich23721382012-01-22 20:00:19 +0100933 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 */
Sven Eckelmann56303d32012-06-05 22:31:31 +0200939static void batadv_bla_purge_backbone_gw(struct batadv_priv *bat_priv, int now)
Simon Wunderlich23721382012-01-22 20:00:19 +0100940{
Sven Eckelmann56303d32012-06-05 22:31:31 +0200941 struct batadv_backbone_gw *backbone_gw;
Simon Wunderlich23721382012-01-22 20:00:19 +0100942 struct hlist_node *node, *node_tmp;
943 struct hlist_head *head;
Sven Eckelmann5bf74e92012-06-05 22:31:28 +0200944 struct batadv_hashtable *hash;
Simon Wunderlich23721382012-01-22 20:00:19 +0100945 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;
Sven Eckelmann1eda58b2012-05-12 13:48:58 +0200961 if (!batadv_has_timed_out(backbone_gw->lasttime,
Sven Eckelmann42d0b042012-06-03 22:19:17 +0200962 BATADV_BLA_BACKBONE_TIMEOUT))
Simon Wunderlich23721382012-01-22 20:00:19 +0100963 continue;
964
Sven Eckelmann39c75a52012-06-03 22:19:22 +0200965 batadv_dbg(BATADV_DBG_BLA, backbone_gw->bat_priv,
Sven Eckelmann1eda58b2012-05-12 13:48:58 +0200966 "bla_purge_backbone_gw(): backbone gw %pM timed out\n",
967 backbone_gw->orig);
Simon Wunderlich23721382012-01-22 20:00:19 +0100968
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
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200974 batadv_bla_del_backbone_claims(backbone_gw);
Simon Wunderlich23721382012-01-22 20:00:19 +0100975
976 hlist_del_rcu(node);
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200977 batadv_backbone_gw_free_ref(backbone_gw);
Simon Wunderlich23721382012-01-22 20:00:19 +0100978 }
979 spin_unlock_bh(list_lock);
980 }
981}
982
Ben Hutchings2c530402012-07-10 10:55:09 +0000983/**
984 * batadv_bla_purge_claims
985 * @bat_priv: the bat priv with all the soft interface information
Simon Wunderlich23721382012-01-22 20:00:19 +0100986 * @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 */
Sven Eckelmann56303d32012-06-05 22:31:31 +0200992static void batadv_bla_purge_claims(struct batadv_priv *bat_priv,
993 struct batadv_hard_iface *primary_if,
994 int now)
Simon Wunderlich23721382012-01-22 20:00:19 +0100995{
Sven Eckelmann56303d32012-06-05 22:31:31 +0200996 struct batadv_claim *claim;
Simon Wunderlich23721382012-01-22 20:00:19 +0100997 struct hlist_node *node;
998 struct hlist_head *head;
Sven Eckelmann5bf74e92012-06-05 22:31:28 +0200999 struct batadv_hashtable *hash;
Simon Wunderlich23721382012-01-22 20:00:19 +01001000 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;
Sven Eckelmann1eda58b2012-05-12 13:48:58 +02001013 if (!batadv_compare_eth(claim->backbone_gw->orig,
1014 primary_if->net_dev->dev_addr))
Simon Wunderlich23721382012-01-22 20:00:19 +01001015 continue;
Sven Eckelmann1eda58b2012-05-12 13:48:58 +02001016 if (!batadv_has_timed_out(claim->lasttime,
Sven Eckelmann42d0b042012-06-03 22:19:17 +02001017 BATADV_BLA_CLAIM_TIMEOUT))
Simon Wunderlich23721382012-01-22 20:00:19 +01001018 continue;
1019
Sven Eckelmann39c75a52012-06-03 22:19:22 +02001020 batadv_dbg(BATADV_DBG_BLA, bat_priv,
Sven Eckelmann1eda58b2012-05-12 13:48:58 +02001021 "bla_purge_claims(): %pM, vid %d, time out\n",
1022 claim->addr, claim->vid);
Simon Wunderlich23721382012-01-22 20:00:19 +01001023
1024purge_now:
Sven Eckelmann3b300de2012-05-12 18:33:53 +02001025 batadv_handle_unclaim(bat_priv, primary_if,
1026 claim->backbone_gw->orig,
1027 claim->addr, claim->vid);
Simon Wunderlich23721382012-01-22 20:00:19 +01001028 }
1029 rcu_read_unlock();
1030 }
1031}
1032
Ben Hutchings2c530402012-07-10 10:55:09 +00001033/**
1034 * batadv_bla_update_orig_address
1035 * @bat_priv: the bat priv with all the soft interface information
Simon Wunderlich23721382012-01-22 20:00:19 +01001036 * @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.
Simon Wunderlich23721382012-01-22 20:00:19 +01001040 */
Sven Eckelmann56303d32012-06-05 22:31:31 +02001041void batadv_bla_update_orig_address(struct batadv_priv *bat_priv,
1042 struct batadv_hard_iface *primary_if,
1043 struct batadv_hard_iface *oldif)
Simon Wunderlich23721382012-01-22 20:00:19 +01001044{
Sven Eckelmann56303d32012-06-05 22:31:31 +02001045 struct batadv_backbone_gw *backbone_gw;
Simon Wunderlich23721382012-01-22 20:00:19 +01001046 struct hlist_node *node;
1047 struct hlist_head *head;
Sven Eckelmann5bf74e92012-06-05 22:31:28 +02001048 struct batadv_hashtable *hash;
Simon Wunderlich23721382012-01-22 20:00:19 +01001049 int i;
1050
Simon Wunderlich38ef3d12012-01-22 20:00:26 +01001051 /* 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
Simon Wunderlich23721382012-01-22 20:00:19 +01001055 if (!oldif) {
Sven Eckelmann3b300de2012-05-12 18:33:53 +02001056 batadv_bla_purge_claims(bat_priv, NULL, 1);
1057 batadv_bla_purge_backbone_gw(bat_priv, 1);
Simon Wunderlich23721382012-01-22 20:00:19 +01001058 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. */
Sven Eckelmann1eda58b2012-05-12 13:48:58 +02001071 if (!batadv_compare_eth(backbone_gw->orig,
1072 oldif->net_dev->dev_addr))
Simon Wunderlich23721382012-01-22 20:00:19 +01001073 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 */
Sven Eckelmann3b300de2012-05-12 18:33:53 +02001080 batadv_bla_send_announce(bat_priv, backbone_gw);
Simon Wunderlich23721382012-01-22 20:00:19 +01001081 }
1082 rcu_read_unlock();
1083 }
1084}
1085
1086
1087
1088/* (re)start the timer */
Sven Eckelmann56303d32012-06-05 22:31:31 +02001089static void batadv_bla_start_timer(struct batadv_priv *bat_priv)
Simon Wunderlich23721382012-01-22 20:00:19 +01001090{
Sven Eckelmann3b300de2012-05-12 18:33:53 +02001091 INIT_DELAYED_WORK(&bat_priv->bla_work, batadv_bla_periodic_work);
Sven Eckelmann3193e8f2012-05-12 02:09:42 +02001092 queue_delayed_work(batadv_event_workqueue, &bat_priv->bla_work,
Sven Eckelmann42d0b042012-06-03 22:19:17 +02001093 msecs_to_jiffies(BATADV_BLA_PERIOD_LENGTH));
Simon Wunderlich23721382012-01-22 20:00:19 +01001094}
1095
1096/* periodic work to do:
1097 * * purge structures when they are too old
1098 * * send announcements
1099 */
Sven Eckelmann3b300de2012-05-12 18:33:53 +02001100static void batadv_bla_periodic_work(struct work_struct *work)
Simon Wunderlich23721382012-01-22 20:00:19 +01001101{
1102 struct delayed_work *delayed_work =
1103 container_of(work, struct delayed_work, work);
Sven Eckelmann56303d32012-06-05 22:31:31 +02001104 struct batadv_priv *bat_priv;
Simon Wunderlich23721382012-01-22 20:00:19 +01001105 struct hlist_node *node;
1106 struct hlist_head *head;
Sven Eckelmann56303d32012-06-05 22:31:31 +02001107 struct batadv_backbone_gw *backbone_gw;
Sven Eckelmann5bf74e92012-06-05 22:31:28 +02001108 struct batadv_hashtable *hash;
Sven Eckelmann56303d32012-06-05 22:31:31 +02001109 struct batadv_hard_iface *primary_if;
Simon Wunderlich23721382012-01-22 20:00:19 +01001110 int i;
1111
Sven Eckelmann56303d32012-06-05 22:31:31 +02001112 bat_priv = container_of(delayed_work, struct batadv_priv, bla_work);
Sven Eckelmanne5d89252012-05-12 13:48:54 +02001113 primary_if = batadv_primary_if_get_selected(bat_priv);
Simon Wunderlich23721382012-01-22 20:00:19 +01001114 if (!primary_if)
1115 goto out;
1116
Sven Eckelmann3b300de2012-05-12 18:33:53 +02001117 batadv_bla_purge_claims(bat_priv, primary_if, 0);
1118 batadv_bla_purge_backbone_gw(bat_priv, 0);
Simon Wunderlich23721382012-01-22 20:00:19 +01001119
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) {
Sven Eckelmann1eda58b2012-05-12 13:48:58 +02001132 if (!batadv_compare_eth(backbone_gw->orig,
1133 primary_if->net_dev->dev_addr))
Simon Wunderlich23721382012-01-22 20:00:19 +01001134 continue;
1135
1136 backbone_gw->lasttime = jiffies;
1137
Sven Eckelmann3b300de2012-05-12 18:33:53 +02001138 batadv_bla_send_announce(bat_priv, backbone_gw);
Simon Wunderlich23721382012-01-22 20:00:19 +01001139 }
1140 rcu_read_unlock();
1141 }
1142out:
1143 if (primary_if)
Sven Eckelmanne5d89252012-05-12 13:48:54 +02001144 batadv_hardif_free_ref(primary_if);
Simon Wunderlich23721382012-01-22 20:00:19 +01001145
Sven Eckelmann3b300de2012-05-12 18:33:53 +02001146 batadv_bla_start_timer(bat_priv);
Simon Wunderlich23721382012-01-22 20:00:19 +01001147}
1148
Sven Eckelmann5d52dad2012-03-29 12:38:20 +02001149/* 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 */
Sven Eckelmann3b300de2012-05-12 18:33:53 +02001154static struct lock_class_key batadv_claim_hash_lock_class_key;
1155static struct lock_class_key batadv_backbone_hash_lock_class_key;
Sven Eckelmann5d52dad2012-03-29 12:38:20 +02001156
Simon Wunderlich23721382012-01-22 20:00:19 +01001157/* initialize all bla structures */
Sven Eckelmann56303d32012-06-05 22:31:31 +02001158int batadv_bla_init(struct batadv_priv *bat_priv)
Simon Wunderlich23721382012-01-22 20:00:19 +01001159{
Simon Wunderlichfe2da6f2012-01-22 20:00:24 +01001160 int i;
Simon Wunderlich38ef3d12012-01-22 20:00:26 +01001161 uint8_t claim_dest[ETH_ALEN] = {0xff, 0x43, 0x05, 0x00, 0x00, 0x00};
Sven Eckelmann56303d32012-06-05 22:31:31 +02001162 struct batadv_hard_iface *primary_if;
Simon Wunderlichfe2da6f2012-01-22 20:00:24 +01001163
Sven Eckelmann39c75a52012-06-03 22:19:22 +02001164 batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla hash registering\n");
Simon Wunderlich23721382012-01-22 20:00:19 +01001165
Simon Wunderlich38ef3d12012-01-22 20:00:26 +01001166 /* setting claim destination address */
1167 memcpy(&bat_priv->claim_dest.magic, claim_dest, 3);
1168 bat_priv->claim_dest.type = 0;
Sven Eckelmanne5d89252012-05-12 13:48:54 +02001169 primary_if = batadv_primary_if_get_selected(bat_priv);
Simon Wunderlich38ef3d12012-01-22 20:00:26 +01001170 if (primary_if) {
1171 bat_priv->claim_dest.group =
1172 htons(crc16(0, primary_if->net_dev->dev_addr,
1173 ETH_ALEN));
Sven Eckelmanne5d89252012-05-12 13:48:54 +02001174 batadv_hardif_free_ref(primary_if);
Simon Wunderlich38ef3d12012-01-22 20:00:26 +01001175 } else {
1176 bat_priv->claim_dest.group = 0; /* will be set later */
1177 }
1178
Simon Wunderlichfe2da6f2012-01-22 20:00:24 +01001179 /* initialize the duplicate list */
Sven Eckelmann42d0b042012-06-03 22:19:17 +02001180 for (i = 0; i < BATADV_DUPLIST_SIZE; i++)
Simon Wunderlichfe2da6f2012-01-22 20:00:24 +01001181 bat_priv->bcast_duplist[i].entrytime =
Sven Eckelmann42d0b042012-06-03 22:19:17 +02001182 jiffies - msecs_to_jiffies(BATADV_DUPLIST_TIMEOUT);
Simon Wunderlichfe2da6f2012-01-22 20:00:24 +01001183 bat_priv->bcast_duplist_curr = 0;
1184
Simon Wunderlich23721382012-01-22 20:00:19 +01001185 if (bat_priv->claim_hash)
Sven Eckelmann5346c352012-05-05 13:27:28 +02001186 return 0;
Simon Wunderlich23721382012-01-22 20:00:19 +01001187
Sven Eckelmann1a8eaf02012-05-12 02:09:32 +02001188 bat_priv->claim_hash = batadv_hash_new(128);
1189 bat_priv->backbone_hash = batadv_hash_new(32);
Simon Wunderlich23721382012-01-22 20:00:19 +01001190
1191 if (!bat_priv->claim_hash || !bat_priv->backbone_hash)
Sven Eckelmann5346c352012-05-05 13:27:28 +02001192 return -ENOMEM;
Simon Wunderlich23721382012-01-22 20:00:19 +01001193
Sven Eckelmann5d52dad2012-03-29 12:38:20 +02001194 batadv_hash_set_lock_class(bat_priv->claim_hash,
Sven Eckelmann3b300de2012-05-12 18:33:53 +02001195 &batadv_claim_hash_lock_class_key);
Sven Eckelmann5d52dad2012-03-29 12:38:20 +02001196 batadv_hash_set_lock_class(bat_priv->backbone_hash,
Sven Eckelmann3b300de2012-05-12 18:33:53 +02001197 &batadv_backbone_hash_lock_class_key);
Sven Eckelmann5d52dad2012-03-29 12:38:20 +02001198
Sven Eckelmann39c75a52012-06-03 22:19:22 +02001199 batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla hashes initialized\n");
Simon Wunderlich23721382012-01-22 20:00:19 +01001200
Sven Eckelmann3b300de2012-05-12 18:33:53 +02001201 batadv_bla_start_timer(bat_priv);
Sven Eckelmann5346c352012-05-05 13:27:28 +02001202 return 0;
Simon Wunderlich23721382012-01-22 20:00:19 +01001203}
1204
Ben Hutchings2c530402012-07-10 10:55:09 +00001205/**
1206 * batadv_bla_check_bcast_duplist
1207 * @bat_priv: the bat priv with all the soft interface information
Simon Wunderlichfe2da6f2012-01-22 20:00:24 +01001208 * @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.
Sven Eckelmann9cfc7bd2012-05-12 02:09:43 +02001219 */
Sven Eckelmann56303d32012-06-05 22:31:31 +02001220int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
Sven Eckelmann96412692012-06-05 22:31:30 +02001221 struct batadv_bcast_packet *bcast_packet,
Sven Eckelmann08adf152012-05-12 13:38:47 +02001222 int hdr_size)
Simon Wunderlichfe2da6f2012-01-22 20:00:24 +01001223{
1224 int i, length, curr;
1225 uint8_t *content;
1226 uint16_t crc;
Sven Eckelmann56303d32012-06-05 22:31:31 +02001227 struct batadv_bcast_duplist_entry *entry;
Simon Wunderlichfe2da6f2012-01-22 20:00:24 +01001228
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
Sven Eckelmann42d0b042012-06-03 22:19:17 +02001236 for (i = 0; i < BATADV_DUPLIST_SIZE; i++) {
1237 curr = (bat_priv->bcast_duplist_curr + i) % BATADV_DUPLIST_SIZE;
Simon Wunderlichfe2da6f2012-01-22 20:00:24 +01001238 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 */
Sven Eckelmann42d0b042012-06-03 22:19:17 +02001243 if (batadv_has_timed_out(entry->entrytime,
1244 BATADV_DUPLIST_TIMEOUT))
Simon Wunderlichfe2da6f2012-01-22 20:00:24 +01001245 break;
1246
1247 if (entry->crc != crc)
1248 continue;
1249
Sven Eckelmann1eda58b2012-05-12 13:48:58 +02001250 if (batadv_compare_eth(entry->orig, bcast_packet->orig))
Simon Wunderlichfe2da6f2012-01-22 20:00:24 +01001251 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) */
Sven Eckelmann42d0b042012-06-03 22:19:17 +02001259 curr = (bat_priv->bcast_duplist_curr + BATADV_DUPLIST_SIZE - 1);
1260 curr %= BATADV_DUPLIST_SIZE;
Simon Wunderlichfe2da6f2012-01-22 20:00:24 +01001261 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
Sven Eckelmann9cfc7bd2012-05-12 02:09:43 +02001273/* @bat_priv: the bat priv with all the soft interface information
Simon Wunderlich20ff9d52012-01-22 20:00:23 +01001274 * @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
Simon Wunderlich20ff9d52012-01-22 20:00:23 +01001279 */
Sven Eckelmann56303d32012-06-05 22:31:31 +02001280int batadv_bla_is_backbone_gw_orig(struct batadv_priv *bat_priv, uint8_t *orig)
Simon Wunderlich20ff9d52012-01-22 20:00:23 +01001281{
Sven Eckelmann5bf74e92012-06-05 22:31:28 +02001282 struct batadv_hashtable *hash = bat_priv->backbone_hash;
Simon Wunderlich20ff9d52012-01-22 20:00:23 +01001283 struct hlist_head *head;
1284 struct hlist_node *node;
Sven Eckelmann56303d32012-06-05 22:31:31 +02001285 struct batadv_backbone_gw *backbone_gw;
Simon Wunderlich20ff9d52012-01-22 20:00:23 +01001286 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) {
Sven Eckelmann1eda58b2012-05-12 13:48:58 +02001299 if (batadv_compare_eth(backbone_gw->orig, orig)) {
Simon Wunderlich20ff9d52012-01-22 20:00:23 +01001300 rcu_read_unlock();
1301 return 1;
1302 }
1303 }
1304 rcu_read_unlock();
1305 }
1306
1307 return 0;
1308}
1309
1310
Ben Hutchings2c530402012-07-10 10:55:09 +00001311/**
1312 * batadv_bla_is_backbone_gw
1313 * @skb: the frame to be checked
Simon Wunderlich23721382012-01-22 20:00:19 +01001314 * @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.
Simon Wunderlich23721382012-01-22 20:00:19 +01001320 */
Sven Eckelmann08adf152012-05-12 13:38:47 +02001321int batadv_bla_is_backbone_gw(struct sk_buff *skb,
Sven Eckelmann56303d32012-06-05 22:31:31 +02001322 struct batadv_orig_node *orig_node, int hdr_size)
Simon Wunderlich23721382012-01-22 20:00:19 +01001323{
1324 struct ethhdr *ethhdr;
1325 struct vlan_ethhdr *vhdr;
Sven Eckelmann56303d32012-06-05 22:31:31 +02001326 struct batadv_backbone_gw *backbone_gw;
Simon Wunderlich23721382012-01-22 20:00:19 +01001327 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. */
Antonio Quartulli0d125072012-02-18 11:27:34 +01001333 if (!pskb_may_pull(skb, hdr_size + ETH_HLEN))
Simon Wunderlich23721382012-01-22 20:00:19 +01001334 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 */
Sven Eckelmann3b300de2012-05-12 18:33:53 +02001348 backbone_gw = batadv_backbone_hash_find(orig_node->bat_priv,
1349 orig_node->orig, vid);
Simon Wunderlich23721382012-01-22 20:00:19 +01001350 if (!backbone_gw)
1351 return 0;
1352
Sven Eckelmann3b300de2012-05-12 18:33:53 +02001353 batadv_backbone_gw_free_ref(backbone_gw);
Simon Wunderlich23721382012-01-22 20:00:19 +01001354 return 1;
1355}
1356
1357/* free all bla structures (for softinterface free or module unload) */
Sven Eckelmann56303d32012-06-05 22:31:31 +02001358void batadv_bla_free(struct batadv_priv *bat_priv)
Simon Wunderlich23721382012-01-22 20:00:19 +01001359{
Sven Eckelmann56303d32012-06-05 22:31:31 +02001360 struct batadv_hard_iface *primary_if;
Simon Wunderlich23721382012-01-22 20:00:19 +01001361
1362 cancel_delayed_work_sync(&bat_priv->bla_work);
Sven Eckelmanne5d89252012-05-12 13:48:54 +02001363 primary_if = batadv_primary_if_get_selected(bat_priv);
Simon Wunderlich23721382012-01-22 20:00:19 +01001364
1365 if (bat_priv->claim_hash) {
Sven Eckelmann3b300de2012-05-12 18:33:53 +02001366 batadv_bla_purge_claims(bat_priv, primary_if, 1);
Sven Eckelmann1a8eaf02012-05-12 02:09:32 +02001367 batadv_hash_destroy(bat_priv->claim_hash);
Simon Wunderlich23721382012-01-22 20:00:19 +01001368 bat_priv->claim_hash = NULL;
1369 }
1370 if (bat_priv->backbone_hash) {
Sven Eckelmann3b300de2012-05-12 18:33:53 +02001371 batadv_bla_purge_backbone_gw(bat_priv, 1);
Sven Eckelmann1a8eaf02012-05-12 02:09:32 +02001372 batadv_hash_destroy(bat_priv->backbone_hash);
Simon Wunderlich23721382012-01-22 20:00:19 +01001373 bat_priv->backbone_hash = NULL;
1374 }
1375 if (primary_if)
Sven Eckelmanne5d89252012-05-12 13:48:54 +02001376 batadv_hardif_free_ref(primary_if);
Simon Wunderlich23721382012-01-22 20:00:19 +01001377}
1378
Ben Hutchings2c530402012-07-10 10:55:09 +00001379/**
1380 * batadv_bla_rx
1381 * @bat_priv: the bat priv with all the soft interface information
Simon Wunderlich23721382012-01-22 20:00:19 +01001382 * @skb: the frame to be checked
1383 * @vid: the VLAN ID of the frame
Simon Wunderlich2d3f6cc2012-07-04 20:38:19 +02001384 * @is_bcast: the packet came in a broadcast packet type.
Simon Wunderlich23721382012-01-22 20:00:19 +01001385 *
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.
Simon Wunderlich23721382012-01-22 20:00:19 +01001393 */
David S. Miller04c9f412012-07-10 23:56:33 -07001394int batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb, short vid,
1395 bool is_bcast)
Simon Wunderlich23721382012-01-22 20:00:19 +01001396{
1397 struct ethhdr *ethhdr;
Sven Eckelmann56303d32012-06-05 22:31:31 +02001398 struct batadv_claim search_claim, *claim = NULL;
1399 struct batadv_hard_iface *primary_if;
Simon Wunderlich23721382012-01-22 20:00:19 +01001400 int ret;
1401
1402 ethhdr = (struct ethhdr *)skb_mac_header(skb);
1403
Sven Eckelmanne5d89252012-05-12 13:48:54 +02001404 primary_if = batadv_primary_if_get_selected(bat_priv);
Simon Wunderlich23721382012-01-22 20:00:19 +01001405 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 */
Simon Wunderlich2d3f6cc2012-07-04 20:38:19 +02001414 if (is_multicast_ether_addr(ethhdr->h_dest) && is_bcast)
Simon Wunderlich23721382012-01-22 20:00:19 +01001415 goto handled;
1416
1417 memcpy(search_claim.addr, ethhdr->h_source, ETH_ALEN);
1418 search_claim.vid = vid;
Sven Eckelmann3b300de2012-05-12 18:33:53 +02001419 claim = batadv_claim_hash_find(bat_priv, &search_claim);
Simon Wunderlich23721382012-01-22 20:00:19 +01001420
1421 if (!claim) {
1422 /* possible optimization: race for a claim */
1423 /* No claim exists yet, claim it for us!
1424 */
Sven Eckelmann3b300de2012-05-12 18:33:53 +02001425 batadv_handle_claim(bat_priv, primary_if,
1426 primary_if->net_dev->dev_addr,
1427 ethhdr->h_source, vid);
Simon Wunderlich23721382012-01-22 20:00:19 +01001428 goto allow;
1429 }
1430
1431 /* if it is our own claim ... */
Sven Eckelmann1eda58b2012-05-12 13:48:58 +02001432 if (batadv_compare_eth(claim->backbone_gw->orig,
1433 primary_if->net_dev->dev_addr)) {
Simon Wunderlich23721382012-01-22 20:00:19 +01001434 /* ... allow it in any case */
1435 claim->lasttime = jiffies;
1436 goto allow;
1437 }
1438
1439 /* if it is a broadcast ... */
Simon Wunderlich2d3f6cc2012-07-04 20:38:19 +02001440 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 */
Simon Wunderlich23721382012-01-22 20:00:19 +01001447 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 */
Sven Eckelmann3b300de2012-05-12 18:33:53 +02001453 batadv_handle_claim(bat_priv, primary_if,
1454 primary_if->net_dev->dev_addr,
1455 ethhdr->h_source, vid);
Simon Wunderlich23721382012-01-22 20:00:19 +01001456 goto allow;
1457 }
1458allow:
Sven Eckelmann3b300de2012-05-12 18:33:53 +02001459 batadv_bla_update_own_backbone_gw(bat_priv, primary_if, vid);
Simon Wunderlich23721382012-01-22 20:00:19 +01001460 ret = 0;
1461 goto out;
1462
1463handled:
1464 kfree_skb(skb);
1465 ret = 1;
1466
1467out:
1468 if (primary_if)
Sven Eckelmanne5d89252012-05-12 13:48:54 +02001469 batadv_hardif_free_ref(primary_if);
Simon Wunderlich23721382012-01-22 20:00:19 +01001470 if (claim)
Sven Eckelmann3b300de2012-05-12 18:33:53 +02001471 batadv_claim_free_ref(claim);
Simon Wunderlich23721382012-01-22 20:00:19 +01001472 return ret;
1473}
1474
Ben Hutchings2c530402012-07-10 10:55:09 +00001475/**
1476 * batadv_bla_tx
1477 * @bat_priv: the bat priv with all the soft interface information
Simon Wunderlich23721382012-01-22 20:00:19 +01001478 * @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.
Simon Wunderlich23721382012-01-22 20:00:19 +01001488 */
Sven Eckelmann56303d32012-06-05 22:31:31 +02001489int batadv_bla_tx(struct batadv_priv *bat_priv, struct sk_buff *skb, short vid)
Simon Wunderlich23721382012-01-22 20:00:19 +01001490{
1491 struct ethhdr *ethhdr;
Sven Eckelmann56303d32012-06-05 22:31:31 +02001492 struct batadv_claim search_claim, *claim = NULL;
1493 struct batadv_hard_iface *primary_if;
Simon Wunderlich23721382012-01-22 20:00:19 +01001494 int ret = 0;
1495
Sven Eckelmanne5d89252012-05-12 13:48:54 +02001496 primary_if = batadv_primary_if_get_selected(bat_priv);
Simon Wunderlich23721382012-01-22 20:00:19 +01001497 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
Sven Eckelmann3b300de2012-05-12 18:33:53 +02001506 if (batadv_bla_process_claim(bat_priv, primary_if, skb))
Simon Wunderlich23721382012-01-22 20:00:19 +01001507 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
Sven Eckelmann3b300de2012-05-12 18:33:53 +02001519 claim = batadv_claim_hash_find(bat_priv, &search_claim);
Simon Wunderlich23721382012-01-22 20:00:19 +01001520
1521 /* if no claim exists, allow it. */
1522 if (!claim)
1523 goto allow;
1524
1525 /* check if we are responsible. */
Sven Eckelmann1eda58b2012-05-12 13:48:58 +02001526 if (batadv_compare_eth(claim->backbone_gw->orig,
1527 primary_if->net_dev->dev_addr)) {
Simon Wunderlich23721382012-01-22 20:00:19 +01001528 /* if yes, the client has roamed and we have
1529 * to unclaim it.
1530 */
Sven Eckelmann3b300de2012-05-12 18:33:53 +02001531 batadv_handle_unclaim(bat_priv, primary_if,
1532 primary_if->net_dev->dev_addr,
1533 ethhdr->h_source, vid);
Simon Wunderlich23721382012-01-22 20:00:19 +01001534 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:
Sven Eckelmann3b300de2012-05-12 18:33:53 +02001550 batadv_bla_update_own_backbone_gw(bat_priv, primary_if, vid);
Simon Wunderlich23721382012-01-22 20:00:19 +01001551 ret = 0;
1552 goto out;
1553handled:
1554 ret = 1;
1555out:
1556 if (primary_if)
Sven Eckelmanne5d89252012-05-12 13:48:54 +02001557 batadv_hardif_free_ref(primary_if);
Simon Wunderlich23721382012-01-22 20:00:19 +01001558 if (claim)
Sven Eckelmann3b300de2012-05-12 18:33:53 +02001559 batadv_claim_free_ref(claim);
Simon Wunderlich23721382012-01-22 20:00:19 +01001560 return ret;
1561}
Simon Wunderlich9bf8e4d2012-01-22 20:00:21 +01001562
Sven Eckelmann08adf152012-05-12 13:38:47 +02001563int batadv_bla_claim_table_seq_print_text(struct seq_file *seq, void *offset)
Simon Wunderlich9bf8e4d2012-01-22 20:00:21 +01001564{
1565 struct net_device *net_dev = (struct net_device *)seq->private;
Sven Eckelmann56303d32012-06-05 22:31:31 +02001566 struct batadv_priv *bat_priv = netdev_priv(net_dev);
Sven Eckelmann5bf74e92012-06-05 22:31:28 +02001567 struct batadv_hashtable *hash = bat_priv->claim_hash;
Sven Eckelmann56303d32012-06-05 22:31:31 +02001568 struct batadv_claim *claim;
1569 struct batadv_hard_iface *primary_if;
Simon Wunderlich9bf8e4d2012-01-22 20:00:21 +01001570 struct hlist_node *node;
1571 struct hlist_head *head;
1572 uint32_t i;
1573 bool is_own;
1574 int ret = 0;
Sven Eckelmann1eda58b2012-05-12 13:48:58 +02001575 uint8_t *primary_addr;
Simon Wunderlich9bf8e4d2012-01-22 20:00:21 +01001576
Sven Eckelmanne5d89252012-05-12 13:48:54 +02001577 primary_if = batadv_primary_if_get_selected(bat_priv);
Simon Wunderlich9bf8e4d2012-01-22 20:00:21 +01001578 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
Sven Eckelmanne9a4f292012-06-03 22:19:19 +02001585 if (primary_if->if_status != BATADV_IF_ACTIVE) {
Simon Wunderlich9bf8e4d2012-01-22 20:00:21 +01001586 ret = seq_printf(seq,
1587 "BATMAN mesh %s disabled - primary interface not active\n",
1588 net_dev->name);
1589 goto out;
1590 }
1591
Sven Eckelmann1eda58b2012-05-12 13:48:58 +02001592 primary_addr = primary_if->net_dev->dev_addr;
Simon Wunderlich38ef3d12012-01-22 20:00:26 +01001593 seq_printf(seq,
1594 "Claims announced for the mesh %s (orig %pM, group id %04x)\n",
Sven Eckelmann1eda58b2012-05-12 13:48:58 +02001595 net_dev->name, primary_addr,
Simon Wunderlich38ef3d12012-01-22 20:00:26 +01001596 ntohs(bat_priv->claim_dest.group));
Simon Wunderlich9bf8e4d2012-01-22 20:00:21 +01001597 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) {
Sven Eckelmann1eda58b2012-05-12 13:48:58 +02001604 is_own = batadv_compare_eth(claim->backbone_gw->orig,
1605 primary_addr);
Simon Wunderlich9bf8e4d2012-01-22 20:00:21 +01001606 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)
Sven Eckelmanne5d89252012-05-12 13:48:54 +02001616 batadv_hardif_free_ref(primary_if);
Simon Wunderlich9bf8e4d2012-01-22 20:00:21 +01001617 return ret;
1618}
Simon Wunderlich536a23f2012-06-18 18:39:26 +02001619
1620int batadv_bla_backbone_table_seq_print_text(struct seq_file *seq, void *offset)
1621{
1622 struct net_device *net_dev = (struct net_device *)seq->private;
1623 struct batadv_priv *bat_priv = netdev_priv(net_dev);
1624 struct batadv_hashtable *hash = bat_priv->backbone_hash;
1625 struct batadv_backbone_gw *backbone_gw;
1626 struct batadv_hard_iface *primary_if;
1627 struct hlist_node *node;
1628 struct hlist_head *head;
1629 int secs, msecs;
1630 uint32_t i;
1631 bool is_own;
1632 int ret = 0;
1633 uint8_t *primary_addr;
1634
1635 primary_if = batadv_primary_if_get_selected(bat_priv);
1636 if (!primary_if) {
1637 ret = seq_printf(seq,
1638 "BATMAN mesh %s disabled - please specify interfaces to enable it\n",
1639 net_dev->name);
1640 goto out;
1641 }
1642
1643 if (primary_if->if_status != BATADV_IF_ACTIVE) {
1644 ret = seq_printf(seq,
1645 "BATMAN mesh %s disabled - primary interface not active\n",
1646 net_dev->name);
1647 goto out;
1648 }
1649
1650 primary_addr = primary_if->net_dev->dev_addr;
1651 seq_printf(seq,
1652 "Backbones announced for the mesh %s (orig %pM, group id %04x)\n",
1653 net_dev->name, primary_addr,
1654 ntohs(bat_priv->claim_dest.group));
1655 seq_printf(seq, " %-17s %-5s %-9s (%-4s)\n",
1656 "Originator", "VID", "last seen", "CRC");
1657 for (i = 0; i < hash->size; i++) {
1658 head = &hash->table[i];
1659
1660 rcu_read_lock();
1661 hlist_for_each_entry_rcu(backbone_gw, node, head, hash_entry) {
1662 msecs = jiffies_to_msecs(jiffies -
1663 backbone_gw->lasttime);
1664 secs = msecs / 1000;
1665 msecs = msecs % 1000;
1666
1667 is_own = batadv_compare_eth(backbone_gw->orig,
1668 primary_addr);
1669 if (is_own)
1670 continue;
1671
1672 seq_printf(seq,
1673 " * %pM on % 5d % 4i.%03is (%04x)\n",
1674 backbone_gw->orig, backbone_gw->vid,
1675 secs, msecs, backbone_gw->crc);
1676 }
1677 rcu_read_unlock();
1678 }
1679out:
1680 if (primary_if)
1681 batadv_hardif_free_ref(primary_if);
1682 return ret;
1683}