blob: 2e70ec11320502ffd2d3a2396add6eab0e9651e0 [file] [log] [blame]
Sven Eckelmann9cfc7bd2012-05-12 02:09:43 +02001/* Copyright (C) 2008-2012 B.A.T.M.A.N. contributors:
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00002 *
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
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +000018 */
19
20#include "main.h"
21#include "send.h"
22#include "translation-table.h"
23#include "vis.h"
24#include "soft-interface.h"
25#include "hard-interface.h"
26#include "hash.h"
27#include "originator.h"
28
Sven Eckelmann347c80f2012-06-03 22:19:07 +020029#define BATADV_MAX_VIS_PACKET_SIZE 1000
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +000030
Antonio Quartullidec05072012-11-10 11:00:32 +010031/* hash class keys */
32static struct lock_class_key batadv_vis_hash_lock_class_key;
33
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +000034/* free the info */
Sven Eckelmanneaad8ad2012-05-16 20:23:18 +020035static void batadv_free_info(struct kref *ref)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +000036{
Sven Eckelmann56303d32012-06-05 22:31:31 +020037 struct batadv_vis_info *info;
38 struct batadv_priv *bat_priv;
Marek Lindner28500f02012-12-25 17:03:23 +080039 struct batadv_vis_recvlist_node *entry, *tmp;
Sven Eckelmann56303d32012-06-05 22:31:31 +020040
41 info = container_of(ref, struct batadv_vis_info, refcount);
42 bat_priv = info->bat_priv;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +000043
44 list_del_init(&info->send_list);
Sven Eckelmann807736f2012-07-15 22:26:51 +020045 spin_lock_bh(&bat_priv->vis.list_lock);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +000046 list_for_each_entry_safe(entry, tmp, &info->recv_list, list) {
47 list_del(&entry->list);
48 kfree(entry);
49 }
50
Sven Eckelmann807736f2012-07-15 22:26:51 +020051 spin_unlock_bh(&bat_priv->vis.list_lock);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +000052 kfree_skb(info->skb_packet);
Sven Eckelmanndda9fc62011-01-28 18:34:06 +010053 kfree(info);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +000054}
55
56/* Compare two vis packets, used by the hashing algorithm */
Sven Eckelmanneaad8ad2012-05-16 20:23:18 +020057static int batadv_vis_info_cmp(const struct hlist_node *node, const void *data2)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +000058{
Sven Eckelmann56303d32012-06-05 22:31:31 +020059 const struct batadv_vis_info *d1, *d2;
Sven Eckelmann96412692012-06-05 22:31:30 +020060 const struct batadv_vis_packet *p1, *p2;
Marek Lindner7aadf882011-02-18 12:28:09 +000061
Sven Eckelmann56303d32012-06-05 22:31:31 +020062 d1 = container_of(node, struct batadv_vis_info, hash_entry);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +000063 d2 = data2;
Sven Eckelmann96412692012-06-05 22:31:30 +020064 p1 = (struct batadv_vis_packet *)d1->skb_packet->data;
65 p2 = (struct batadv_vis_packet *)d2->skb_packet->data;
Sven Eckelmann1eda58b2012-05-12 13:48:58 +020066 return batadv_compare_eth(p1->vis_orig, p2->vis_orig);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +000067}
68
Sven Eckelmann9cfc7bd2012-05-12 02:09:43 +020069/* hash function to choose an entry in a hash table of given size
70 * hash algorithm from http://en.wikipedia.org/wiki/Hash_table
71 */
Sven Eckelmanneaad8ad2012-05-16 20:23:18 +020072static uint32_t batadv_vis_info_choose(const void *data, uint32_t size)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +000073{
Sven Eckelmann56303d32012-06-05 22:31:31 +020074 const struct batadv_vis_info *vis_info = data;
Sven Eckelmann96412692012-06-05 22:31:30 +020075 const struct batadv_vis_packet *packet;
Sven Eckelmann747e4222011-05-14 23:14:50 +020076 const unsigned char *key;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +000077 uint32_t hash = 0;
78 size_t i;
79
Sven Eckelmann96412692012-06-05 22:31:30 +020080 packet = (struct batadv_vis_packet *)vis_info->skb_packet->data;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +000081 key = packet->vis_orig;
82 for (i = 0; i < ETH_ALEN; i++) {
83 hash += key[i];
84 hash += (hash << 10);
85 hash ^= (hash >> 6);
86 }
87
88 hash += (hash << 3);
89 hash ^= (hash >> 11);
90 hash += (hash << 15);
91
92 return hash % size;
93}
94
Sven Eckelmann56303d32012-06-05 22:31:31 +020095static struct batadv_vis_info *
96batadv_vis_hash_find(struct batadv_priv *bat_priv, const void *data)
Marek Lindner7aadf882011-02-18 12:28:09 +000097{
Sven Eckelmann807736f2012-07-15 22:26:51 +020098 struct batadv_hashtable *hash = bat_priv->vis.hash;
Marek Lindner7aadf882011-02-18 12:28:09 +000099 struct hlist_head *head;
100 struct hlist_node *node;
Sven Eckelmann56303d32012-06-05 22:31:31 +0200101 struct batadv_vis_info *vis_info, *vis_info_tmp = NULL;
Antonio Quartullic90681b2011-10-05 17:05:25 +0200102 uint32_t index;
Marek Lindner7aadf882011-02-18 12:28:09 +0000103
104 if (!hash)
105 return NULL;
106
Sven Eckelmanneaad8ad2012-05-16 20:23:18 +0200107 index = batadv_vis_info_choose(data, hash->size);
Marek Lindner7aadf882011-02-18 12:28:09 +0000108 head = &hash->table[index];
109
110 rcu_read_lock();
111 hlist_for_each_entry_rcu(vis_info, node, head, hash_entry) {
Sven Eckelmanneaad8ad2012-05-16 20:23:18 +0200112 if (!batadv_vis_info_cmp(node, data))
Marek Lindner7aadf882011-02-18 12:28:09 +0000113 continue;
114
115 vis_info_tmp = vis_info;
116 break;
117 }
118 rcu_read_unlock();
119
120 return vis_info_tmp;
121}
122
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000123/* insert interface to the list of interfaces of one originator, if it
Sven Eckelmann9cfc7bd2012-05-12 02:09:43 +0200124 * does not already exist in the list
125 */
Sven Eckelmanneaad8ad2012-05-16 20:23:18 +0200126static void batadv_vis_data_insert_interface(const uint8_t *interface,
127 struct hlist_head *if_list,
128 bool primary)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000129{
Marek Lindner015b4ae2012-12-25 17:03:22 +0800130 struct batadv_vis_if_list_entry *entry;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000131 struct hlist_node *pos;
132
133 hlist_for_each_entry(entry, pos, if_list, list) {
Sven Eckelmann1eda58b2012-05-12 13:48:58 +0200134 if (batadv_compare_eth(entry->addr, interface))
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000135 return;
136 }
137
Antonio Quartulli015758d2011-07-09 17:52:13 +0200138 /* it's a new address, add it to the list */
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000139 entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
140 if (!entry)
141 return;
142 memcpy(entry->addr, interface, ETH_ALEN);
143 entry->primary = primary;
144 hlist_add_head(&entry->list, if_list);
145}
146
Sven Eckelmann28afd3c2012-05-16 20:23:23 +0200147static void batadv_vis_data_read_prim_sec(struct seq_file *seq,
148 const struct hlist_head *if_list)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000149{
Marek Lindner015b4ae2012-12-25 17:03:22 +0800150 struct batadv_vis_if_list_entry *entry;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000151 struct hlist_node *pos;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000152
153 hlist_for_each_entry(entry, pos, if_list, list) {
154 if (entry->primary)
Sven Eckelmann28afd3c2012-05-16 20:23:23 +0200155 seq_printf(seq, "PRIMARY, ");
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000156 else
Sven Eckelmann28afd3c2012-05-16 20:23:23 +0200157 seq_printf(seq, "SEC %pM, ", entry->addr);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000158 }
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000159}
160
161/* read an entry */
Sven Eckelmann56303d32012-06-05 22:31:31 +0200162static ssize_t
163batadv_vis_data_read_entry(struct seq_file *seq,
164 const struct batadv_vis_info_entry *entry,
165 const uint8_t *src, bool primary)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000166{
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000167 if (primary && entry->quality == 0)
Sven Eckelmann28afd3c2012-05-16 20:23:23 +0200168 return seq_printf(seq, "TT %pM, ", entry->dest);
Sven Eckelmann1eda58b2012-05-12 13:48:58 +0200169 else if (batadv_compare_eth(entry->src, src))
Sven Eckelmann28afd3c2012-05-16 20:23:23 +0200170 return seq_printf(seq, "TQ %pM %d, ", entry->dest,
171 entry->quality);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000172
173 return 0;
174}
175
Sven Eckelmann56303d32012-06-05 22:31:31 +0200176static void
177batadv_vis_data_insert_interfaces(struct hlist_head *list,
178 struct batadv_vis_packet *packet,
179 struct batadv_vis_info_entry *entries)
Sven Eckelmann28afd3c2012-05-16 20:23:23 +0200180{
181 int i;
182
183 for (i = 0; i < packet->entries; i++) {
184 if (entries[i].quality == 0)
185 continue;
186
187 if (batadv_compare_eth(entries[i].src, packet->vis_orig))
188 continue;
189
190 batadv_vis_data_insert_interface(entries[i].src, list, false);
191 }
192}
193
194static void batadv_vis_data_read_entries(struct seq_file *seq,
195 struct hlist_head *list,
Sven Eckelmann96412692012-06-05 22:31:30 +0200196 struct batadv_vis_packet *packet,
Sven Eckelmann56303d32012-06-05 22:31:31 +0200197 struct batadv_vis_info_entry *entries)
Sven Eckelmann28afd3c2012-05-16 20:23:23 +0200198{
199 int i;
Marek Lindner015b4ae2012-12-25 17:03:22 +0800200 struct batadv_vis_if_list_entry *entry;
Sven Eckelmann28afd3c2012-05-16 20:23:23 +0200201 struct hlist_node *pos;
202
203 hlist_for_each_entry(entry, pos, list, list) {
204 seq_printf(seq, "%pM,", entry->addr);
205
206 for (i = 0; i < packet->entries; i++)
207 batadv_vis_data_read_entry(seq, &entries[i],
208 entry->addr, entry->primary);
209
210 /* add primary/secondary records */
211 if (batadv_compare_eth(entry->addr, packet->vis_orig))
212 batadv_vis_data_read_prim_sec(seq, list);
213
214 seq_printf(seq, "\n");
215 }
216}
217
218static void batadv_vis_seq_print_text_bucket(struct seq_file *seq,
219 const struct hlist_head *head)
220{
221 struct hlist_node *node;
Sven Eckelmann56303d32012-06-05 22:31:31 +0200222 struct batadv_vis_info *info;
Sven Eckelmann96412692012-06-05 22:31:30 +0200223 struct batadv_vis_packet *packet;
Sven Eckelmann28afd3c2012-05-16 20:23:23 +0200224 uint8_t *entries_pos;
Sven Eckelmann56303d32012-06-05 22:31:31 +0200225 struct batadv_vis_info_entry *entries;
Marek Lindner015b4ae2012-12-25 17:03:22 +0800226 struct batadv_vis_if_list_entry *entry;
Sven Eckelmann28afd3c2012-05-16 20:23:23 +0200227 struct hlist_node *pos, *n;
228
229 HLIST_HEAD(vis_if_list);
230
231 hlist_for_each_entry_rcu(info, node, head, hash_entry) {
Sven Eckelmann96412692012-06-05 22:31:30 +0200232 packet = (struct batadv_vis_packet *)info->skb_packet->data;
Sven Eckelmann28afd3c2012-05-16 20:23:23 +0200233 entries_pos = (uint8_t *)packet + sizeof(*packet);
Sven Eckelmann56303d32012-06-05 22:31:31 +0200234 entries = (struct batadv_vis_info_entry *)entries_pos;
Sven Eckelmann28afd3c2012-05-16 20:23:23 +0200235
236 batadv_vis_data_insert_interface(packet->vis_orig, &vis_if_list,
237 true);
238 batadv_vis_data_insert_interfaces(&vis_if_list, packet,
239 entries);
240 batadv_vis_data_read_entries(seq, &vis_if_list, packet,
241 entries);
242
243 hlist_for_each_entry_safe(entry, pos, n, &vis_if_list, list) {
244 hlist_del(&entry->list);
245 kfree(entry);
246 }
247 }
248}
249
Sven Eckelmannd0f714f2012-05-12 02:09:41 +0200250int batadv_vis_seq_print_text(struct seq_file *seq, void *offset)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000251{
Sven Eckelmann56303d32012-06-05 22:31:31 +0200252 struct batadv_hard_iface *primary_if;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000253 struct hlist_head *head;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000254 struct net_device *net_dev = (struct net_device *)seq->private;
Sven Eckelmann56303d32012-06-05 22:31:31 +0200255 struct batadv_priv *bat_priv = netdev_priv(net_dev);
Sven Eckelmann807736f2012-07-15 22:26:51 +0200256 struct batadv_hashtable *hash = bat_priv->vis.hash;
Antonio Quartullic90681b2011-10-05 17:05:25 +0200257 uint32_t i;
Sven Eckelmann28afd3c2012-05-16 20:23:23 +0200258 int ret = 0;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000259 int vis_server = atomic_read(&bat_priv->vis_mode);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000260
Sven Eckelmanne5d89252012-05-12 13:48:54 +0200261 primary_if = batadv_primary_if_get_selected(bat_priv);
Marek Lindner32ae9b22011-04-20 15:40:58 +0200262 if (!primary_if)
263 goto out;
264
Sven Eckelmannacd34af2012-06-03 22:19:21 +0200265 if (vis_server == BATADV_VIS_TYPE_CLIENT_UPDATE)
Marek Lindner32ae9b22011-04-20 15:40:58 +0200266 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000267
Sven Eckelmann807736f2012-07-15 22:26:51 +0200268 spin_lock_bh(&bat_priv->vis.hash_lock);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000269 for (i = 0; i < hash->size; i++) {
270 head = &hash->table[i];
Sven Eckelmann28afd3c2012-05-16 20:23:23 +0200271 batadv_vis_seq_print_text_bucket(seq, head);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000272 }
Sven Eckelmann807736f2012-07-15 22:26:51 +0200273 spin_unlock_bh(&bat_priv->vis.hash_lock);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000274
Marek Lindner32ae9b22011-04-20 15:40:58 +0200275out:
276 if (primary_if)
Sven Eckelmanne5d89252012-05-12 13:48:54 +0200277 batadv_hardif_free_ref(primary_if);
Marek Lindner32ae9b22011-04-20 15:40:58 +0200278 return ret;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000279}
280
281/* add the info packet to the send list, if it was not
Sven Eckelmann9cfc7bd2012-05-12 02:09:43 +0200282 * already linked in.
283 */
Sven Eckelmann56303d32012-06-05 22:31:31 +0200284static void batadv_send_list_add(struct batadv_priv *bat_priv,
285 struct batadv_vis_info *info)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000286{
287 if (list_empty(&info->send_list)) {
288 kref_get(&info->refcount);
Sven Eckelmann807736f2012-07-15 22:26:51 +0200289 list_add_tail(&info->send_list, &bat_priv->vis.send_list);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000290 }
291}
292
293/* delete the info packet from the send list, if it was
Sven Eckelmann9cfc7bd2012-05-12 02:09:43 +0200294 * linked in.
295 */
Sven Eckelmann56303d32012-06-05 22:31:31 +0200296static void batadv_send_list_del(struct batadv_vis_info *info)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000297{
298 if (!list_empty(&info->send_list)) {
299 list_del_init(&info->send_list);
Sven Eckelmanneaad8ad2012-05-16 20:23:18 +0200300 kref_put(&info->refcount, batadv_free_info);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000301 }
302}
303
304/* tries to add one entry to the receive list. */
Sven Eckelmann56303d32012-06-05 22:31:31 +0200305static void batadv_recv_list_add(struct batadv_priv *bat_priv,
Sven Eckelmanneaad8ad2012-05-16 20:23:18 +0200306 struct list_head *recv_list, const char *mac)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000307{
Marek Lindner28500f02012-12-25 17:03:23 +0800308 struct batadv_vis_recvlist_node *entry;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000309
Sven Eckelmann704509b2011-05-14 23:14:54 +0200310 entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000311 if (!entry)
312 return;
313
314 memcpy(entry->mac, mac, ETH_ALEN);
Sven Eckelmann807736f2012-07-15 22:26:51 +0200315 spin_lock_bh(&bat_priv->vis.list_lock);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000316 list_add_tail(&entry->list, recv_list);
Sven Eckelmann807736f2012-07-15 22:26:51 +0200317 spin_unlock_bh(&bat_priv->vis.list_lock);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000318}
319
320/* returns 1 if this mac is in the recv_list */
Sven Eckelmann56303d32012-06-05 22:31:31 +0200321static int batadv_recv_list_is_in(struct batadv_priv *bat_priv,
Sven Eckelmanneaad8ad2012-05-16 20:23:18 +0200322 const struct list_head *recv_list,
323 const char *mac)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000324{
Marek Lindner28500f02012-12-25 17:03:23 +0800325 const struct batadv_vis_recvlist_node *entry;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000326
Sven Eckelmann807736f2012-07-15 22:26:51 +0200327 spin_lock_bh(&bat_priv->vis.list_lock);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000328 list_for_each_entry(entry, recv_list, list) {
Sven Eckelmann1eda58b2012-05-12 13:48:58 +0200329 if (batadv_compare_eth(entry->mac, mac)) {
Sven Eckelmann807736f2012-07-15 22:26:51 +0200330 spin_unlock_bh(&bat_priv->vis.list_lock);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000331 return 1;
332 }
333 }
Sven Eckelmann807736f2012-07-15 22:26:51 +0200334 spin_unlock_bh(&bat_priv->vis.list_lock);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000335 return 0;
336}
337
338/* try to add the packet to the vis_hash. return NULL if invalid (e.g. too old,
339 * broken.. ). vis hash must be locked outside. is_new is set when the packet
Sven Eckelmann9cfc7bd2012-05-12 02:09:43 +0200340 * is newer than old entries in the hash.
341 */
Sven Eckelmann56303d32012-06-05 22:31:31 +0200342static struct batadv_vis_info *
343batadv_add_packet(struct batadv_priv *bat_priv,
344 struct batadv_vis_packet *vis_packet, int vis_info_len,
345 int *is_new, int make_broadcast)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000346{
Sven Eckelmann56303d32012-06-05 22:31:31 +0200347 struct batadv_vis_info *info, *old_info;
Sven Eckelmann96412692012-06-05 22:31:30 +0200348 struct batadv_vis_packet *search_packet, *old_packet;
Sven Eckelmann56303d32012-06-05 22:31:31 +0200349 struct batadv_vis_info search_elem;
Sven Eckelmann96412692012-06-05 22:31:30 +0200350 struct batadv_vis_packet *packet;
351 struct sk_buff *tmp_skb;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000352 int hash_added;
Sven Eckelmann96412692012-06-05 22:31:30 +0200353 size_t len;
Sven Eckelmann56303d32012-06-05 22:31:31 +0200354 size_t max_entries;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000355
356 *is_new = 0;
357 /* sanity check */
Sven Eckelmann807736f2012-07-15 22:26:51 +0200358 if (!bat_priv->vis.hash)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000359 return NULL;
360
361 /* see if the packet is already in vis_hash */
Sven Eckelmann704509b2011-05-14 23:14:54 +0200362 search_elem.skb_packet = dev_alloc_skb(sizeof(*search_packet));
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000363 if (!search_elem.skb_packet)
364 return NULL;
Sven Eckelmann96412692012-06-05 22:31:30 +0200365 len = sizeof(*search_packet);
366 tmp_skb = search_elem.skb_packet;
367 search_packet = (struct batadv_vis_packet *)skb_put(tmp_skb, len);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000368
369 memcpy(search_packet->vis_orig, vis_packet->vis_orig, ETH_ALEN);
Sven Eckelmanneaad8ad2012-05-16 20:23:18 +0200370 old_info = batadv_vis_hash_find(bat_priv, &search_elem);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000371 kfree_skb(search_elem.skb_packet);
372
373 if (old_info) {
Sven Eckelmann96412692012-06-05 22:31:30 +0200374 tmp_skb = old_info->skb_packet;
375 old_packet = (struct batadv_vis_packet *)tmp_skb->data;
Sven Eckelmann3e348192012-05-16 20:23:22 +0200376 if (!batadv_seq_after(ntohl(vis_packet->seqno),
377 ntohl(old_packet->seqno))) {
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000378 if (old_packet->seqno == vis_packet->seqno) {
Sven Eckelmanneaad8ad2012-05-16 20:23:18 +0200379 batadv_recv_list_add(bat_priv,
380 &old_info->recv_list,
381 vis_packet->sender_orig);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000382 return old_info;
383 } else {
384 /* newer packet is already in hash. */
385 return NULL;
386 }
387 }
388 /* remove old entry */
Sven Eckelmann807736f2012-07-15 22:26:51 +0200389 batadv_hash_remove(bat_priv->vis.hash, batadv_vis_info_cmp,
Sven Eckelmanneaad8ad2012-05-16 20:23:18 +0200390 batadv_vis_info_choose, old_info);
391 batadv_send_list_del(old_info);
392 kref_put(&old_info->refcount, batadv_free_info);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000393 }
394
Sven Eckelmann704509b2011-05-14 23:14:54 +0200395 info = kmalloc(sizeof(*info), GFP_ATOMIC);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000396 if (!info)
397 return NULL;
398
Sven Eckelmann96412692012-06-05 22:31:30 +0200399 len = sizeof(*packet) + vis_info_len;
Sven Eckelmann5b246572012-11-04 17:11:45 +0100400 info->skb_packet = dev_alloc_skb(len + ETH_HLEN + NET_IP_ALIGN);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000401 if (!info->skb_packet) {
402 kfree(info);
403 return NULL;
404 }
Sven Eckelmann5b246572012-11-04 17:11:45 +0100405 skb_reserve(info->skb_packet, ETH_HLEN + NET_IP_ALIGN);
Sven Eckelmann96412692012-06-05 22:31:30 +0200406 packet = (struct batadv_vis_packet *)skb_put(info->skb_packet, len);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000407
408 kref_init(&info->refcount);
409 INIT_LIST_HEAD(&info->send_list);
410 INIT_LIST_HEAD(&info->recv_list);
411 info->first_seen = jiffies;
412 info->bat_priv = bat_priv;
Sven Eckelmann96412692012-06-05 22:31:30 +0200413 memcpy(packet, vis_packet, len);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000414
415 /* initialize and add new packet. */
416 *is_new = 1;
417
418 /* Make it a broadcast packet, if required */
419 if (make_broadcast)
Sven Eckelmann3193e8f2012-05-12 02:09:42 +0200420 memcpy(packet->target_orig, batadv_broadcast_addr, ETH_ALEN);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000421
422 /* repair if entries is longer than packet. */
Sven Eckelmann56303d32012-06-05 22:31:31 +0200423 max_entries = vis_info_len / sizeof(struct batadv_vis_info_entry);
424 if (packet->entries > max_entries)
425 packet->entries = max_entries;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000426
Sven Eckelmanneaad8ad2012-05-16 20:23:18 +0200427 batadv_recv_list_add(bat_priv, &info->recv_list, packet->sender_orig);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000428
429 /* try to add it */
Sven Eckelmann807736f2012-07-15 22:26:51 +0200430 hash_added = batadv_hash_add(bat_priv->vis.hash, batadv_vis_info_cmp,
Sven Eckelmanneaad8ad2012-05-16 20:23:18 +0200431 batadv_vis_info_choose, info,
432 &info->hash_entry);
Antonio Quartulli1a1f37d2011-07-10 00:36:36 +0200433 if (hash_added != 0) {
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000434 /* did not work (for some reason) */
Sven Eckelmanneaad8ad2012-05-16 20:23:18 +0200435 kref_put(&info->refcount, batadv_free_info);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000436 info = NULL;
437 }
438
439 return info;
440}
441
442/* handle the server sync packet, forward if needed. */
Sven Eckelmann56303d32012-06-05 22:31:31 +0200443void batadv_receive_server_sync_packet(struct batadv_priv *bat_priv,
Sven Eckelmann96412692012-06-05 22:31:30 +0200444 struct batadv_vis_packet *vis_packet,
Sven Eckelmannd0f714f2012-05-12 02:09:41 +0200445 int vis_info_len)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000446{
Sven Eckelmann56303d32012-06-05 22:31:31 +0200447 struct batadv_vis_info *info;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000448 int is_new, make_broadcast;
449 int vis_server = atomic_read(&bat_priv->vis_mode);
450
Sven Eckelmannacd34af2012-06-03 22:19:21 +0200451 make_broadcast = (vis_server == BATADV_VIS_TYPE_SERVER_SYNC);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000452
Sven Eckelmann807736f2012-07-15 22:26:51 +0200453 spin_lock_bh(&bat_priv->vis.hash_lock);
Sven Eckelmanneaad8ad2012-05-16 20:23:18 +0200454 info = batadv_add_packet(bat_priv, vis_packet, vis_info_len,
455 &is_new, make_broadcast);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000456 if (!info)
457 goto end;
458
459 /* only if we are server ourselves and packet is newer than the one in
Sven Eckelmann9cfc7bd2012-05-12 02:09:43 +0200460 * hash.
461 */
Sven Eckelmannacd34af2012-06-03 22:19:21 +0200462 if (vis_server == BATADV_VIS_TYPE_SERVER_SYNC && is_new)
Sven Eckelmanneaad8ad2012-05-16 20:23:18 +0200463 batadv_send_list_add(bat_priv, info);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000464end:
Sven Eckelmann807736f2012-07-15 22:26:51 +0200465 spin_unlock_bh(&bat_priv->vis.hash_lock);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000466}
467
468/* handle an incoming client update packet and schedule forward if needed. */
Sven Eckelmann56303d32012-06-05 22:31:31 +0200469void batadv_receive_client_update_packet(struct batadv_priv *bat_priv,
Sven Eckelmann96412692012-06-05 22:31:30 +0200470 struct batadv_vis_packet *vis_packet,
Sven Eckelmannd0f714f2012-05-12 02:09:41 +0200471 int vis_info_len)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000472{
Sven Eckelmann56303d32012-06-05 22:31:31 +0200473 struct batadv_vis_info *info;
Sven Eckelmann96412692012-06-05 22:31:30 +0200474 struct batadv_vis_packet *packet;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000475 int is_new;
476 int vis_server = atomic_read(&bat_priv->vis_mode);
477 int are_target = 0;
478
479 /* clients shall not broadcast. */
480 if (is_broadcast_ether_addr(vis_packet->target_orig))
481 return;
482
483 /* Are we the target for this VIS packet? */
Sven Eckelmannacd34af2012-06-03 22:19:21 +0200484 if (vis_server == BATADV_VIS_TYPE_SERVER_SYNC &&
Sven Eckelmann3193e8f2012-05-12 02:09:42 +0200485 batadv_is_my_mac(vis_packet->target_orig))
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000486 are_target = 1;
487
Sven Eckelmann807736f2012-07-15 22:26:51 +0200488 spin_lock_bh(&bat_priv->vis.hash_lock);
Sven Eckelmanneaad8ad2012-05-16 20:23:18 +0200489 info = batadv_add_packet(bat_priv, vis_packet, vis_info_len,
490 &is_new, are_target);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000491
492 if (!info)
493 goto end;
494 /* note that outdated packets will be dropped at this point. */
495
Sven Eckelmann96412692012-06-05 22:31:30 +0200496 packet = (struct batadv_vis_packet *)info->skb_packet->data;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000497
498 /* send only if we're the target server or ... */
499 if (are_target && is_new) {
Sven Eckelmannacd34af2012-06-03 22:19:21 +0200500 packet->vis_type = BATADV_VIS_TYPE_SERVER_SYNC; /* upgrade! */
Sven Eckelmanneaad8ad2012-05-16 20:23:18 +0200501 batadv_send_list_add(bat_priv, info);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000502
503 /* ... we're not the recipient (and thus need to forward). */
Sven Eckelmann3193e8f2012-05-12 02:09:42 +0200504 } else if (!batadv_is_my_mac(packet->target_orig)) {
Sven Eckelmanneaad8ad2012-05-16 20:23:18 +0200505 batadv_send_list_add(bat_priv, info);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000506 }
507
508end:
Sven Eckelmann807736f2012-07-15 22:26:51 +0200509 spin_unlock_bh(&bat_priv->vis.hash_lock);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000510}
511
512/* Walk the originators and find the VIS server with the best tq. Set the packet
513 * address to its address and return the best_tq.
514 *
Sven Eckelmann9cfc7bd2012-05-12 02:09:43 +0200515 * Must be called with the originator hash locked
516 */
Sven Eckelmann56303d32012-06-05 22:31:31 +0200517static int batadv_find_best_vis_server(struct batadv_priv *bat_priv,
518 struct batadv_vis_info *info)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000519{
Sven Eckelmann5bf74e92012-06-05 22:31:28 +0200520 struct batadv_hashtable *hash = bat_priv->orig_hash;
Sven Eckelmann56303d32012-06-05 22:31:31 +0200521 struct batadv_neigh_node *router;
Marek Lindner7aadf882011-02-18 12:28:09 +0000522 struct hlist_node *node;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000523 struct hlist_head *head;
Sven Eckelmann56303d32012-06-05 22:31:31 +0200524 struct batadv_orig_node *orig_node;
Sven Eckelmann96412692012-06-05 22:31:30 +0200525 struct batadv_vis_packet *packet;
Antonio Quartullic90681b2011-10-05 17:05:25 +0200526 int best_tq = -1;
527 uint32_t i;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000528
Sven Eckelmann96412692012-06-05 22:31:30 +0200529 packet = (struct batadv_vis_packet *)info->skb_packet->data;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000530
531 for (i = 0; i < hash->size; i++) {
532 head = &hash->table[i];
533
Marek Lindnerfb778ea2011-01-19 20:01:40 +0000534 rcu_read_lock();
Marek Lindner7aadf882011-02-18 12:28:09 +0000535 hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) {
Sven Eckelmann7d211ef2012-05-12 02:09:34 +0200536 router = batadv_orig_node_get_router(orig_node);
Linus Lüssinge1a5382f2011-03-14 22:43:37 +0000537 if (!router)
538 continue;
539
Sven Eckelmannacd34af2012-06-03 22:19:21 +0200540 if ((orig_node->flags & BATADV_VIS_SERVER) &&
Linus Lüssinge1a5382f2011-03-14 22:43:37 +0000541 (router->tq_avg > best_tq)) {
542 best_tq = router->tq_avg;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000543 memcpy(packet->target_orig, orig_node->orig,
544 ETH_ALEN);
545 }
Sven Eckelmann7d211ef2012-05-12 02:09:34 +0200546 batadv_neigh_node_free_ref(router);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000547 }
Marek Lindnerfb778ea2011-01-19 20:01:40 +0000548 rcu_read_unlock();
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000549 }
550
551 return best_tq;
552}
553
554/* Return true if the vis packet is full. */
Sven Eckelmann56303d32012-06-05 22:31:31 +0200555static bool batadv_vis_packet_full(const struct batadv_vis_info *info)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000556{
Sven Eckelmann96412692012-06-05 22:31:30 +0200557 const struct batadv_vis_packet *packet;
Sven Eckelmann56303d32012-06-05 22:31:31 +0200558 size_t num;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000559
Sven Eckelmann96412692012-06-05 22:31:30 +0200560 packet = (struct batadv_vis_packet *)info->skb_packet->data;
Sven Eckelmann56303d32012-06-05 22:31:31 +0200561 num = BATADV_MAX_VIS_PACKET_SIZE / sizeof(struct batadv_vis_info_entry);
Sven Eckelmann347c80f2012-06-03 22:19:07 +0200562
Sven Eckelmann56303d32012-06-05 22:31:31 +0200563 if (num < packet->entries + 1)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000564 return true;
565 return false;
566}
567
568/* generates a packet of own vis data,
Sven Eckelmann9cfc7bd2012-05-12 02:09:43 +0200569 * returns 0 on success, -1 if no packet could be generated
570 */
Sven Eckelmann56303d32012-06-05 22:31:31 +0200571static int batadv_generate_vis_packet(struct batadv_priv *bat_priv)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000572{
Sven Eckelmann5bf74e92012-06-05 22:31:28 +0200573 struct batadv_hashtable *hash = bat_priv->orig_hash;
Marek Lindner7aadf882011-02-18 12:28:09 +0000574 struct hlist_node *node;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000575 struct hlist_head *head;
Sven Eckelmann56303d32012-06-05 22:31:31 +0200576 struct batadv_orig_node *orig_node;
577 struct batadv_neigh_node *router;
Sven Eckelmann807736f2012-07-15 22:26:51 +0200578 struct batadv_vis_info *info = bat_priv->vis.my_info;
Sven Eckelmann96412692012-06-05 22:31:30 +0200579 struct batadv_vis_packet *packet;
Sven Eckelmann56303d32012-06-05 22:31:31 +0200580 struct batadv_vis_info_entry *entry;
581 struct batadv_tt_common_entry *tt_common_entry;
Sven Eckelmannc67893d2012-07-08 18:33:51 +0200582 uint8_t *packet_pos;
Antonio Quartullic90681b2011-10-05 17:05:25 +0200583 int best_tq = -1;
584 uint32_t i;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000585
586 info->first_seen = jiffies;
Sven Eckelmann96412692012-06-05 22:31:30 +0200587 packet = (struct batadv_vis_packet *)info->skb_packet->data;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000588 packet->vis_type = atomic_read(&bat_priv->vis_mode);
589
Sven Eckelmann3193e8f2012-05-12 02:09:42 +0200590 memcpy(packet->target_orig, batadv_broadcast_addr, ETH_ALEN);
Sven Eckelmann42d0b042012-06-03 22:19:17 +0200591 packet->header.ttl = BATADV_TTL;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000592 packet->seqno = htonl(ntohl(packet->seqno) + 1);
593 packet->entries = 0;
Sven Eckelmann162d5492012-06-28 11:56:52 +0200594 packet->reserved = 0;
Sven Eckelmann704509b2011-05-14 23:14:54 +0200595 skb_trim(info->skb_packet, sizeof(*packet));
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000596
Sven Eckelmannacd34af2012-06-03 22:19:21 +0200597 if (packet->vis_type == BATADV_VIS_TYPE_CLIENT_UPDATE) {
Sven Eckelmanneaad8ad2012-05-16 20:23:18 +0200598 best_tq = batadv_find_best_vis_server(bat_priv, info);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000599
Marek Lindnerd0072602011-01-19 20:01:44 +0000600 if (best_tq < 0)
Sven Eckelmann5346c352012-05-05 13:27:28 +0200601 return best_tq;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000602 }
603
604 for (i = 0; i < hash->size; i++) {
605 head = &hash->table[i];
606
Marek Lindnerfb778ea2011-01-19 20:01:40 +0000607 rcu_read_lock();
Marek Lindner7aadf882011-02-18 12:28:09 +0000608 hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) {
Sven Eckelmann7d211ef2012-05-12 02:09:34 +0200609 router = batadv_orig_node_get_router(orig_node);
Linus Lüssinge1a5382f2011-03-14 22:43:37 +0000610 if (!router)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000611 continue;
612
Sven Eckelmann1eda58b2012-05-12 13:48:58 +0200613 if (!batadv_compare_eth(router->addr, orig_node->orig))
Linus Lüssinge1a5382f2011-03-14 22:43:37 +0000614 goto next;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000615
Sven Eckelmanne9a4f292012-06-03 22:19:19 +0200616 if (router->if_incoming->if_status != BATADV_IF_ACTIVE)
Linus Lüssinge1a5382f2011-03-14 22:43:37 +0000617 goto next;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000618
Linus Lüssinge1a5382f2011-03-14 22:43:37 +0000619 if (router->tq_avg < 1)
620 goto next;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000621
622 /* fill one entry into buffer. */
Sven Eckelmannc67893d2012-07-08 18:33:51 +0200623 packet_pos = skb_put(info->skb_packet, sizeof(*entry));
624 entry = (struct batadv_vis_info_entry *)packet_pos;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000625 memcpy(entry->src,
Linus Lüssinge1a5382f2011-03-14 22:43:37 +0000626 router->if_incoming->net_dev->dev_addr,
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000627 ETH_ALEN);
628 memcpy(entry->dest, orig_node->orig, ETH_ALEN);
Linus Lüssinge1a5382f2011-03-14 22:43:37 +0000629 entry->quality = router->tq_avg;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000630 packet->entries++;
631
Linus Lüssinge1a5382f2011-03-14 22:43:37 +0000632next:
Sven Eckelmann7d211ef2012-05-12 02:09:34 +0200633 batadv_neigh_node_free_ref(router);
Linus Lüssinge1a5382f2011-03-14 22:43:37 +0000634
Sven Eckelmanneaad8ad2012-05-16 20:23:18 +0200635 if (batadv_vis_packet_full(info))
Marek Lindnerd0072602011-01-19 20:01:44 +0000636 goto unlock;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000637 }
Marek Lindnerfb778ea2011-01-19 20:01:40 +0000638 rcu_read_unlock();
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000639 }
640
Sven Eckelmann807736f2012-07-15 22:26:51 +0200641 hash = bat_priv->tt.local_hash;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000642
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000643 for (i = 0; i < hash->size; i++) {
644 head = &hash->table[i];
645
Antonio Quartulli7683fdc2011-04-27 14:28:07 +0200646 rcu_read_lock();
Antonio Quartulli48100ba2011-10-30 12:17:33 +0100647 hlist_for_each_entry_rcu(tt_common_entry, node, head,
Antonio Quartulli7683fdc2011-04-27 14:28:07 +0200648 hash_entry) {
Sven Eckelmannc67893d2012-07-08 18:33:51 +0200649 packet_pos = skb_put(info->skb_packet, sizeof(*entry));
650 entry = (struct batadv_vis_info_entry *)packet_pos;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000651 memset(entry->src, 0, ETH_ALEN);
Antonio Quartulli48100ba2011-10-30 12:17:33 +0100652 memcpy(entry->dest, tt_common_entry->addr, ETH_ALEN);
Antonio Quartulli2dafb492011-05-05 08:42:45 +0200653 entry->quality = 0; /* 0 means TT */
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000654 packet->entries++;
655
Sven Eckelmanneaad8ad2012-05-16 20:23:18 +0200656 if (batadv_vis_packet_full(info))
Antonio Quartulli7683fdc2011-04-27 14:28:07 +0200657 goto unlock;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000658 }
Antonio Quartulli7683fdc2011-04-27 14:28:07 +0200659 rcu_read_unlock();
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000660 }
661
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000662 return 0;
Marek Lindnerd0072602011-01-19 20:01:44 +0000663
664unlock:
665 rcu_read_unlock();
666 return 0;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000667}
668
669/* free old vis packets. Must be called with this vis_hash_lock
Sven Eckelmann9cfc7bd2012-05-12 02:09:43 +0200670 * held
671 */
Sven Eckelmann56303d32012-06-05 22:31:31 +0200672static void batadv_purge_vis_packets(struct batadv_priv *bat_priv)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000673{
Antonio Quartullic90681b2011-10-05 17:05:25 +0200674 uint32_t i;
Sven Eckelmann807736f2012-07-15 22:26:51 +0200675 struct batadv_hashtable *hash = bat_priv->vis.hash;
Marek Lindner7aadf882011-02-18 12:28:09 +0000676 struct hlist_node *node, *node_tmp;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000677 struct hlist_head *head;
Sven Eckelmann56303d32012-06-05 22:31:31 +0200678 struct batadv_vis_info *info;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000679
680 for (i = 0; i < hash->size; i++) {
681 head = &hash->table[i];
682
Marek Lindner7aadf882011-02-18 12:28:09 +0000683 hlist_for_each_entry_safe(info, node, node_tmp,
684 head, hash_entry) {
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000685 /* never purge own data. */
Sven Eckelmann807736f2012-07-15 22:26:51 +0200686 if (info == bat_priv->vis.my_info)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000687 continue;
688
Sven Eckelmann1eda58b2012-05-12 13:48:58 +0200689 if (batadv_has_timed_out(info->first_seen,
Sven Eckelmannedbf7ff2012-06-03 22:19:16 +0200690 BATADV_VIS_TIMEOUT)) {
Marek Lindner7aadf882011-02-18 12:28:09 +0000691 hlist_del(node);
Sven Eckelmanneaad8ad2012-05-16 20:23:18 +0200692 batadv_send_list_del(info);
693 kref_put(&info->refcount, batadv_free_info);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000694 }
695 }
696 }
697}
698
Sven Eckelmann56303d32012-06-05 22:31:31 +0200699static void batadv_broadcast_vis_packet(struct batadv_priv *bat_priv,
700 struct batadv_vis_info *info)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000701{
Sven Eckelmann5bf74e92012-06-05 22:31:28 +0200702 struct batadv_hashtable *hash = bat_priv->orig_hash;
Marek Lindner7aadf882011-02-18 12:28:09 +0000703 struct hlist_node *node;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000704 struct hlist_head *head;
Sven Eckelmann56303d32012-06-05 22:31:31 +0200705 struct batadv_orig_node *orig_node;
Sven Eckelmann96412692012-06-05 22:31:30 +0200706 struct batadv_vis_packet *packet;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000707 struct sk_buff *skb;
Antonio Quartullic90681b2011-10-05 17:05:25 +0200708 uint32_t i;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000709
710
Sven Eckelmann96412692012-06-05 22:31:30 +0200711 packet = (struct batadv_vis_packet *)info->skb_packet->data;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000712
713 /* send to all routers in range. */
714 for (i = 0; i < hash->size; i++) {
715 head = &hash->table[i];
716
Marek Lindnerfb778ea2011-01-19 20:01:40 +0000717 rcu_read_lock();
Marek Lindner7aadf882011-02-18 12:28:09 +0000718 hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) {
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000719 /* if it's a vis server and reachable, send it. */
Sven Eckelmannacd34af2012-06-03 22:19:21 +0200720 if (!(orig_node->flags & BATADV_VIS_SERVER))
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000721 continue;
Linus Lüssinge1a5382f2011-03-14 22:43:37 +0000722
Linus Lüssinge1a5382f2011-03-14 22:43:37 +0000723 /* don't send it if we already received the packet from
Sven Eckelmann9cfc7bd2012-05-12 02:09:43 +0200724 * this node.
725 */
Sven Eckelmanneaad8ad2012-05-16 20:23:18 +0200726 if (batadv_recv_list_is_in(bat_priv, &info->recv_list,
Martin Hundebøllbb351ba2012-10-16 16:13:48 +0200727 orig_node->orig))
Linus Lüssinge1a5382f2011-03-14 22:43:37 +0000728 continue;
Linus Lüssinge1a5382f2011-03-14 22:43:37 +0000729
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000730 memcpy(packet->target_orig, orig_node->orig, ETH_ALEN);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000731 skb = skb_clone(info->skb_packet, GFP_ATOMIC);
Martin Hundebøllbb351ba2012-10-16 16:13:48 +0200732 if (!skb)
733 continue;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000734
Martin Hundebøllbb351ba2012-10-16 16:13:48 +0200735 if (!batadv_send_skb_to_orig(skb, orig_node, NULL))
736 kfree_skb(skb);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000737 }
Marek Lindnerfb778ea2011-01-19 20:01:40 +0000738 rcu_read_unlock();
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000739 }
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000740}
741
Sven Eckelmann56303d32012-06-05 22:31:31 +0200742static void batadv_unicast_vis_packet(struct batadv_priv *bat_priv,
743 struct batadv_vis_info *info)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000744{
Sven Eckelmann56303d32012-06-05 22:31:31 +0200745 struct batadv_orig_node *orig_node;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000746 struct sk_buff *skb;
Sven Eckelmann96412692012-06-05 22:31:30 +0200747 struct batadv_vis_packet *packet;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000748
Sven Eckelmann96412692012-06-05 22:31:30 +0200749 packet = (struct batadv_vis_packet *)info->skb_packet->data;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000750
Sven Eckelmannda641192012-05-12 13:48:56 +0200751 orig_node = batadv_orig_hash_find(bat_priv, packet->target_orig);
Marek Lindner44524fc2011-02-10 14:33:53 +0000752 if (!orig_node)
Linus Lüssinge1a5382f2011-03-14 22:43:37 +0000753 goto out;
Marek Lindner44524fc2011-02-10 14:33:53 +0000754
Martin Hundebøllbb351ba2012-10-16 16:13:48 +0200755 skb = skb_clone(info->skb_packet, GFP_ATOMIC);
756 if (!skb)
Linus Lüssinge1a5382f2011-03-14 22:43:37 +0000757 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000758
Martin Hundebøllbb351ba2012-10-16 16:13:48 +0200759 if (!batadv_send_skb_to_orig(skb, orig_node, NULL))
760 kfree_skb(skb);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000761
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000762out:
Marek Lindner44524fc2011-02-10 14:33:53 +0000763 if (orig_node)
Sven Eckelmann7d211ef2012-05-12 02:09:34 +0200764 batadv_orig_node_free_ref(orig_node);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000765}
766
Sven Eckelmanneaad8ad2012-05-16 20:23:18 +0200767/* only send one vis packet. called from batadv_send_vis_packets() */
Sven Eckelmann56303d32012-06-05 22:31:31 +0200768static void batadv_send_vis_packet(struct batadv_priv *bat_priv,
769 struct batadv_vis_info *info)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000770{
Sven Eckelmann56303d32012-06-05 22:31:31 +0200771 struct batadv_hard_iface *primary_if;
Sven Eckelmann96412692012-06-05 22:31:30 +0200772 struct batadv_vis_packet *packet;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000773
Sven Eckelmanne5d89252012-05-12 13:48:54 +0200774 primary_if = batadv_primary_if_get_selected(bat_priv);
Marek Lindner32ae9b22011-04-20 15:40:58 +0200775 if (!primary_if)
776 goto out;
777
Sven Eckelmann96412692012-06-05 22:31:30 +0200778 packet = (struct batadv_vis_packet *)info->skb_packet->data;
Sven Eckelmann76543d12011-11-20 15:47:38 +0100779 if (packet->header.ttl < 2) {
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000780 pr_debug("Error - can't send vis packet: ttl exceeded\n");
Marek Lindner32ae9b22011-04-20 15:40:58 +0200781 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000782 }
783
Marek Lindner32ae9b22011-04-20 15:40:58 +0200784 memcpy(packet->sender_orig, primary_if->net_dev->dev_addr, ETH_ALEN);
Sven Eckelmann76543d12011-11-20 15:47:38 +0100785 packet->header.ttl--;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000786
787 if (is_broadcast_ether_addr(packet->target_orig))
Sven Eckelmanneaad8ad2012-05-16 20:23:18 +0200788 batadv_broadcast_vis_packet(bat_priv, info);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000789 else
Sven Eckelmanneaad8ad2012-05-16 20:23:18 +0200790 batadv_unicast_vis_packet(bat_priv, info);
Sven Eckelmann76543d12011-11-20 15:47:38 +0100791 packet->header.ttl++; /* restore TTL */
Marek Lindner32ae9b22011-04-20 15:40:58 +0200792
793out:
794 if (primary_if)
Sven Eckelmanne5d89252012-05-12 13:48:54 +0200795 batadv_hardif_free_ref(primary_if);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000796}
797
798/* called from timer; send (and maybe generate) vis packet. */
Sven Eckelmanneaad8ad2012-05-16 20:23:18 +0200799static void batadv_send_vis_packets(struct work_struct *work)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000800{
Sven Eckelmannbbb1f902012-07-08 17:13:15 +0200801 struct delayed_work *delayed_work;
Sven Eckelmann56303d32012-06-05 22:31:31 +0200802 struct batadv_priv *bat_priv;
Sven Eckelmann807736f2012-07-15 22:26:51 +0200803 struct batadv_priv_vis *priv_vis;
Sven Eckelmann56303d32012-06-05 22:31:31 +0200804 struct batadv_vis_info *info;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000805
Sven Eckelmannbbb1f902012-07-08 17:13:15 +0200806 delayed_work = container_of(work, struct delayed_work, work);
Sven Eckelmann807736f2012-07-15 22:26:51 +0200807 priv_vis = container_of(delayed_work, struct batadv_priv_vis, work);
808 bat_priv = container_of(priv_vis, struct batadv_priv, vis);
809 spin_lock_bh(&bat_priv->vis.hash_lock);
Sven Eckelmanneaad8ad2012-05-16 20:23:18 +0200810 batadv_purge_vis_packets(bat_priv);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000811
Sven Eckelmanneaad8ad2012-05-16 20:23:18 +0200812 if (batadv_generate_vis_packet(bat_priv) == 0) {
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000813 /* schedule if generation was successful */
Sven Eckelmann807736f2012-07-15 22:26:51 +0200814 batadv_send_list_add(bat_priv, bat_priv->vis.my_info);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000815 }
816
Sven Eckelmann807736f2012-07-15 22:26:51 +0200817 while (!list_empty(&bat_priv->vis.send_list)) {
818 info = list_first_entry(&bat_priv->vis.send_list,
Sven Eckelmann1181e1d2011-01-28 18:34:07 +0100819 typeof(*info), send_list);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000820
821 kref_get(&info->refcount);
Sven Eckelmann807736f2012-07-15 22:26:51 +0200822 spin_unlock_bh(&bat_priv->vis.hash_lock);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000823
Sven Eckelmanneaad8ad2012-05-16 20:23:18 +0200824 batadv_send_vis_packet(bat_priv, info);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000825
Sven Eckelmann807736f2012-07-15 22:26:51 +0200826 spin_lock_bh(&bat_priv->vis.hash_lock);
Sven Eckelmanneaad8ad2012-05-16 20:23:18 +0200827 batadv_send_list_del(info);
828 kref_put(&info->refcount, batadv_free_info);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000829 }
Sven Eckelmann807736f2012-07-15 22:26:51 +0200830 spin_unlock_bh(&bat_priv->vis.hash_lock);
Antonio Quartulli72414442012-12-25 13:14:37 +0100831
832 queue_delayed_work(batadv_event_workqueue, &bat_priv->vis.work,
833 msecs_to_jiffies(BATADV_VIS_INTERVAL));
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000834}
835
836/* init the vis server. this may only be called when if_list is already
Sven Eckelmann9cfc7bd2012-05-12 02:09:43 +0200837 * initialized (e.g. bat0 is initialized, interfaces have been added)
838 */
Sven Eckelmann56303d32012-06-05 22:31:31 +0200839int batadv_vis_init(struct batadv_priv *bat_priv)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000840{
Sven Eckelmann96412692012-06-05 22:31:30 +0200841 struct batadv_vis_packet *packet;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000842 int hash_added;
Sven Eckelmann347c80f2012-06-03 22:19:07 +0200843 unsigned int len;
Sven Eckelmann42d0b042012-06-03 22:19:17 +0200844 unsigned long first_seen;
Sven Eckelmann96412692012-06-05 22:31:30 +0200845 struct sk_buff *tmp_skb;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000846
Sven Eckelmann807736f2012-07-15 22:26:51 +0200847 if (bat_priv->vis.hash)
Sven Eckelmann5346c352012-05-05 13:27:28 +0200848 return 0;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000849
Sven Eckelmann807736f2012-07-15 22:26:51 +0200850 spin_lock_bh(&bat_priv->vis.hash_lock);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000851
Sven Eckelmann807736f2012-07-15 22:26:51 +0200852 bat_priv->vis.hash = batadv_hash_new(256);
853 if (!bat_priv->vis.hash) {
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000854 pr_err("Can't initialize vis_hash\n");
855 goto err;
856 }
857
Antonio Quartullidec05072012-11-10 11:00:32 +0100858 batadv_hash_set_lock_class(bat_priv->vis.hash,
859 &batadv_vis_hash_lock_class_key);
860
Sven Eckelmann807736f2012-07-15 22:26:51 +0200861 bat_priv->vis.my_info = kmalloc(BATADV_MAX_VIS_PACKET_SIZE, GFP_ATOMIC);
862 if (!bat_priv->vis.my_info)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000863 goto err;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000864
Sven Eckelmann5b246572012-11-04 17:11:45 +0100865 len = sizeof(*packet) + BATADV_MAX_VIS_PACKET_SIZE;
866 len += ETH_HLEN + NET_IP_ALIGN;
Sven Eckelmann807736f2012-07-15 22:26:51 +0200867 bat_priv->vis.my_info->skb_packet = dev_alloc_skb(len);
868 if (!bat_priv->vis.my_info->skb_packet)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000869 goto free_info;
870
Sven Eckelmann5b246572012-11-04 17:11:45 +0100871 skb_reserve(bat_priv->vis.my_info->skb_packet, ETH_HLEN + NET_IP_ALIGN);
Sven Eckelmann807736f2012-07-15 22:26:51 +0200872 tmp_skb = bat_priv->vis.my_info->skb_packet;
Sven Eckelmann96412692012-06-05 22:31:30 +0200873 packet = (struct batadv_vis_packet *)skb_put(tmp_skb, sizeof(*packet));
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000874
875 /* prefill the vis info */
Sven Eckelmann42d0b042012-06-03 22:19:17 +0200876 first_seen = jiffies - msecs_to_jiffies(BATADV_VIS_INTERVAL);
Sven Eckelmann807736f2012-07-15 22:26:51 +0200877 bat_priv->vis.my_info->first_seen = first_seen;
878 INIT_LIST_HEAD(&bat_priv->vis.my_info->recv_list);
879 INIT_LIST_HEAD(&bat_priv->vis.my_info->send_list);
880 kref_init(&bat_priv->vis.my_info->refcount);
881 bat_priv->vis.my_info->bat_priv = bat_priv;
Sven Eckelmann7e071c72012-06-03 22:19:13 +0200882 packet->header.version = BATADV_COMPAT_VERSION;
Sven Eckelmannacd34af2012-06-03 22:19:21 +0200883 packet->header.packet_type = BATADV_VIS;
Sven Eckelmann42d0b042012-06-03 22:19:17 +0200884 packet->header.ttl = BATADV_TTL;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000885 packet->seqno = 0;
Sven Eckelmann162d5492012-06-28 11:56:52 +0200886 packet->reserved = 0;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000887 packet->entries = 0;
888
Sven Eckelmann807736f2012-07-15 22:26:51 +0200889 INIT_LIST_HEAD(&bat_priv->vis.send_list);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000890
Sven Eckelmann807736f2012-07-15 22:26:51 +0200891 hash_added = batadv_hash_add(bat_priv->vis.hash, batadv_vis_info_cmp,
Sven Eckelmanneaad8ad2012-05-16 20:23:18 +0200892 batadv_vis_info_choose,
Sven Eckelmann807736f2012-07-15 22:26:51 +0200893 bat_priv->vis.my_info,
894 &bat_priv->vis.my_info->hash_entry);
Antonio Quartulli1a1f37d2011-07-10 00:36:36 +0200895 if (hash_added != 0) {
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000896 pr_err("Can't add own vis packet into hash\n");
897 /* not in hash, need to remove it manually. */
Sven Eckelmann807736f2012-07-15 22:26:51 +0200898 kref_put(&bat_priv->vis.my_info->refcount, batadv_free_info);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000899 goto err;
900 }
901
Sven Eckelmann807736f2012-07-15 22:26:51 +0200902 spin_unlock_bh(&bat_priv->vis.hash_lock);
Antonio Quartulli72414442012-12-25 13:14:37 +0100903
904 INIT_DELAYED_WORK(&bat_priv->vis.work, batadv_send_vis_packets);
905 queue_delayed_work(batadv_event_workqueue, &bat_priv->vis.work,
906 msecs_to_jiffies(BATADV_VIS_INTERVAL));
907
Sven Eckelmann5346c352012-05-05 13:27:28 +0200908 return 0;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000909
910free_info:
Sven Eckelmann807736f2012-07-15 22:26:51 +0200911 kfree(bat_priv->vis.my_info);
912 bat_priv->vis.my_info = NULL;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000913err:
Sven Eckelmann807736f2012-07-15 22:26:51 +0200914 spin_unlock_bh(&bat_priv->vis.hash_lock);
Sven Eckelmannd0f714f2012-05-12 02:09:41 +0200915 batadv_vis_quit(bat_priv);
Sven Eckelmann5346c352012-05-05 13:27:28 +0200916 return -ENOMEM;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000917}
918
919/* Decrease the reference count on a hash item info */
Sven Eckelmanneaad8ad2012-05-16 20:23:18 +0200920static void batadv_free_info_ref(struct hlist_node *node, void *arg)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000921{
Sven Eckelmann56303d32012-06-05 22:31:31 +0200922 struct batadv_vis_info *info;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000923
Sven Eckelmann56303d32012-06-05 22:31:31 +0200924 info = container_of(node, struct batadv_vis_info, hash_entry);
Sven Eckelmanneaad8ad2012-05-16 20:23:18 +0200925 batadv_send_list_del(info);
926 kref_put(&info->refcount, batadv_free_info);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000927}
928
929/* shutdown vis-server */
Sven Eckelmann56303d32012-06-05 22:31:31 +0200930void batadv_vis_quit(struct batadv_priv *bat_priv)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000931{
Sven Eckelmann807736f2012-07-15 22:26:51 +0200932 if (!bat_priv->vis.hash)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000933 return;
934
Sven Eckelmann807736f2012-07-15 22:26:51 +0200935 cancel_delayed_work_sync(&bat_priv->vis.work);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000936
Sven Eckelmann807736f2012-07-15 22:26:51 +0200937 spin_lock_bh(&bat_priv->vis.hash_lock);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000938 /* properly remove, kill timers ... */
Sven Eckelmann807736f2012-07-15 22:26:51 +0200939 batadv_hash_delete(bat_priv->vis.hash, batadv_free_info_ref, NULL);
940 bat_priv->vis.hash = NULL;
941 bat_priv->vis.my_info = NULL;
942 spin_unlock_bh(&bat_priv->vis.hash_lock);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000943}