blob: e84629ece9b7cfb0a06a0baf856474173f02a144 [file] [log] [blame]
Martin Hundebølld353d8d2013-01-25 11:12:38 +01001/* Copyright (C) 2012-2013 B.A.T.M.A.N. contributors:
2 *
3 * Martin Hundebøll, Jeppe Ledet-Pedersen
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
18 */
19
Martin Hundebølld56b1702013-01-25 11:12:39 +010020#include <linux/debugfs.h>
21
Martin Hundebølld353d8d2013-01-25 11:12:38 +010022#include "main.h"
Martin Hundebøll95332472013-01-25 11:12:40 +010023#include "hash.h"
Martin Hundebølld353d8d2013-01-25 11:12:38 +010024#include "network-coding.h"
Martin Hundebøll95332472013-01-25 11:12:40 +010025#include "send.h"
Martin Hundebølld56b1702013-01-25 11:12:39 +010026#include "originator.h"
27#include "hard-interface.h"
Martin Hundebøll2df52782013-01-25 11:12:43 +010028#include "routing.h"
Martin Hundebølld353d8d2013-01-25 11:12:38 +010029
Martin Hundebøll95332472013-01-25 11:12:40 +010030static struct lock_class_key batadv_nc_coding_hash_lock_class_key;
Martin Hundebøll612d2b42013-01-25 11:12:42 +010031static struct lock_class_key batadv_nc_decoding_hash_lock_class_key;
Martin Hundebøll95332472013-01-25 11:12:40 +010032
Martin Hundebølld353d8d2013-01-25 11:12:38 +010033static void batadv_nc_worker(struct work_struct *work);
Martin Hundebøll2df52782013-01-25 11:12:43 +010034static int batadv_nc_recv_coded_packet(struct sk_buff *skb,
35 struct batadv_hard_iface *recv_if);
Martin Hundebølld353d8d2013-01-25 11:12:38 +010036
37/**
38 * batadv_nc_start_timer - initialise the nc periodic worker
39 * @bat_priv: the bat priv with all the soft interface information
40 */
41static void batadv_nc_start_timer(struct batadv_priv *bat_priv)
42{
43 queue_delayed_work(batadv_event_workqueue, &bat_priv->nc.work,
44 msecs_to_jiffies(10));
45}
46
47/**
48 * batadv_nc_init - initialise coding hash table and start house keeping
49 * @bat_priv: the bat priv with all the soft interface information
50 */
51int batadv_nc_init(struct batadv_priv *bat_priv)
52{
Martin Hundebøll95332472013-01-25 11:12:40 +010053 bat_priv->nc.timestamp_fwd_flush = jiffies;
Martin Hundebøll612d2b42013-01-25 11:12:42 +010054 bat_priv->nc.timestamp_sniffed_purge = jiffies;
Martin Hundebøll95332472013-01-25 11:12:40 +010055
Martin Hundebøll612d2b42013-01-25 11:12:42 +010056 if (bat_priv->nc.coding_hash || bat_priv->nc.decoding_hash)
Martin Hundebøll95332472013-01-25 11:12:40 +010057 return 0;
58
59 bat_priv->nc.coding_hash = batadv_hash_new(128);
60 if (!bat_priv->nc.coding_hash)
61 goto err;
62
63 batadv_hash_set_lock_class(bat_priv->nc.coding_hash,
64 &batadv_nc_coding_hash_lock_class_key);
65
Martin Hundebøll612d2b42013-01-25 11:12:42 +010066 bat_priv->nc.decoding_hash = batadv_hash_new(128);
67 if (!bat_priv->nc.decoding_hash)
68 goto err;
69
70 batadv_hash_set_lock_class(bat_priv->nc.coding_hash,
71 &batadv_nc_decoding_hash_lock_class_key);
72
Martin Hundebøll2df52782013-01-25 11:12:43 +010073 /* Register our packet type */
74 if (batadv_recv_handler_register(BATADV_CODED,
75 batadv_nc_recv_coded_packet) < 0)
76 goto err;
77
Martin Hundebølld353d8d2013-01-25 11:12:38 +010078 INIT_DELAYED_WORK(&bat_priv->nc.work, batadv_nc_worker);
79 batadv_nc_start_timer(bat_priv);
80
81 return 0;
Martin Hundebøll95332472013-01-25 11:12:40 +010082
83err:
84 return -ENOMEM;
Martin Hundebølld353d8d2013-01-25 11:12:38 +010085}
86
87/**
88 * batadv_nc_init_bat_priv - initialise the nc specific bat_priv variables
89 * @bat_priv: the bat priv with all the soft interface information
90 */
91void batadv_nc_init_bat_priv(struct batadv_priv *bat_priv)
92{
93 atomic_set(&bat_priv->network_coding, 1);
Martin Hundebølld56b1702013-01-25 11:12:39 +010094 bat_priv->nc.min_tq = 200;
Martin Hundebøll95332472013-01-25 11:12:40 +010095 bat_priv->nc.max_fwd_delay = 10;
Martin Hundebøll612d2b42013-01-25 11:12:42 +010096 bat_priv->nc.max_buffer_time = 200;
Martin Hundebølld56b1702013-01-25 11:12:39 +010097}
98
99/**
100 * batadv_nc_init_orig - initialise the nc fields of an orig_node
101 * @orig_node: the orig_node which is going to be initialised
102 */
103void batadv_nc_init_orig(struct batadv_orig_node *orig_node)
104{
105 INIT_LIST_HEAD(&orig_node->in_coding_list);
106 INIT_LIST_HEAD(&orig_node->out_coding_list);
107 spin_lock_init(&orig_node->in_coding_list_lock);
108 spin_lock_init(&orig_node->out_coding_list_lock);
109}
110
111/**
112 * batadv_nc_node_free_rcu - rcu callback to free an nc node and remove
113 * its refcount on the orig_node
114 * @rcu: rcu pointer of the nc node
115 */
116static void batadv_nc_node_free_rcu(struct rcu_head *rcu)
117{
118 struct batadv_nc_node *nc_node;
119
120 nc_node = container_of(rcu, struct batadv_nc_node, rcu);
121 batadv_orig_node_free_ref(nc_node->orig_node);
122 kfree(nc_node);
123}
124
125/**
126 * batadv_nc_node_free_ref - decrements the nc node refcounter and possibly
127 * frees it
128 * @nc_node: the nc node to free
129 */
130static void batadv_nc_node_free_ref(struct batadv_nc_node *nc_node)
131{
132 if (atomic_dec_and_test(&nc_node->refcount))
133 call_rcu(&nc_node->rcu, batadv_nc_node_free_rcu);
134}
135
136/**
Martin Hundebøll95332472013-01-25 11:12:40 +0100137 * batadv_nc_path_free_ref - decrements the nc path refcounter and possibly
138 * frees it
139 * @nc_path: the nc node to free
140 */
141static void batadv_nc_path_free_ref(struct batadv_nc_path *nc_path)
142{
143 if (atomic_dec_and_test(&nc_path->refcount))
144 kfree_rcu(nc_path, rcu);
145}
146
147/**
148 * batadv_nc_packet_free - frees nc packet
149 * @nc_packet: the nc packet to free
150 */
151static void batadv_nc_packet_free(struct batadv_nc_packet *nc_packet)
152{
153 if (nc_packet->skb)
154 kfree_skb(nc_packet->skb);
155
156 batadv_nc_path_free_ref(nc_packet->nc_path);
157 kfree(nc_packet);
158}
159
160/**
Martin Hundebølld56b1702013-01-25 11:12:39 +0100161 * batadv_nc_to_purge_nc_node - checks whether an nc node has to be purged
162 * @bat_priv: the bat priv with all the soft interface information
163 * @nc_node: the nc node to check
164 *
165 * Returns true if the entry has to be purged now, false otherwise
166 */
167static bool batadv_nc_to_purge_nc_node(struct batadv_priv *bat_priv,
168 struct batadv_nc_node *nc_node)
169{
170 if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE)
171 return true;
172
173 return batadv_has_timed_out(nc_node->last_seen, BATADV_NC_NODE_TIMEOUT);
174}
175
176/**
Martin Hundebøll95332472013-01-25 11:12:40 +0100177 * batadv_nc_to_purge_nc_path_coding - checks whether an nc path has timed out
178 * @bat_priv: the bat priv with all the soft interface information
179 * @nc_path: the nc path to check
180 *
181 * Returns true if the entry has to be purged now, false otherwise
182 */
183static bool batadv_nc_to_purge_nc_path_coding(struct batadv_priv *bat_priv,
184 struct batadv_nc_path *nc_path)
185{
186 if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE)
187 return true;
188
189 /* purge the path when no packets has been added for 10 times the
190 * max_fwd_delay time
191 */
192 return batadv_has_timed_out(nc_path->last_valid,
193 bat_priv->nc.max_fwd_delay * 10);
194}
195
196/**
Martin Hundebøll612d2b42013-01-25 11:12:42 +0100197 * batadv_nc_to_purge_nc_path_decoding - checks whether an nc path has timed out
198 * @bat_priv: the bat priv with all the soft interface information
199 * @nc_path: the nc path to check
200 *
201 * Returns true if the entry has to be purged now, false otherwise
202 */
203static bool batadv_nc_to_purge_nc_path_decoding(struct batadv_priv *bat_priv,
204 struct batadv_nc_path *nc_path)
205{
206 if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE)
207 return true;
208
209 /* purge the path when no packets has been added for 10 times the
210 * max_buffer time
211 */
212 return batadv_has_timed_out(nc_path->last_valid,
213 bat_priv->nc.max_buffer_time*10);
214}
215
216/**
Martin Hundebølld56b1702013-01-25 11:12:39 +0100217 * batadv_nc_purge_orig_nc_nodes - go through list of nc nodes and purge stale
218 * entries
219 * @bat_priv: the bat priv with all the soft interface information
220 * @list: list of nc nodes
221 * @lock: nc node list lock
222 * @to_purge: function in charge to decide whether an entry has to be purged or
223 * not. This function takes the nc node as argument and has to return
224 * a boolean value: true if the entry has to be deleted, false
225 * otherwise
226 */
227static void
228batadv_nc_purge_orig_nc_nodes(struct batadv_priv *bat_priv,
229 struct list_head *list,
230 spinlock_t *lock,
231 bool (*to_purge)(struct batadv_priv *,
232 struct batadv_nc_node *))
233{
234 struct batadv_nc_node *nc_node, *nc_node_tmp;
235
236 /* For each nc_node in list */
237 spin_lock_bh(lock);
238 list_for_each_entry_safe(nc_node, nc_node_tmp, list, list) {
239 /* if an helper function has been passed as parameter,
240 * ask it if the entry has to be purged or not
241 */
242 if (to_purge && !to_purge(bat_priv, nc_node))
243 continue;
244
245 batadv_dbg(BATADV_DBG_NC, bat_priv,
246 "Removing nc_node %pM -> %pM\n",
247 nc_node->addr, nc_node->orig_node->orig);
248 list_del_rcu(&nc_node->list);
249 batadv_nc_node_free_ref(nc_node);
250 }
251 spin_unlock_bh(lock);
252}
253
254/**
255 * batadv_nc_purge_orig - purges all nc node data attached of the given
256 * originator
257 * @bat_priv: the bat priv with all the soft interface information
258 * @orig_node: orig_node with the nc node entries to be purged
259 * @to_purge: function in charge to decide whether an entry has to be purged or
260 * not. This function takes the nc node as argument and has to return
261 * a boolean value: true is the entry has to be deleted, false
262 * otherwise
263 */
264void batadv_nc_purge_orig(struct batadv_priv *bat_priv,
265 struct batadv_orig_node *orig_node,
266 bool (*to_purge)(struct batadv_priv *,
267 struct batadv_nc_node *))
268{
269 /* Check ingoing nc_node's of this orig_node */
270 batadv_nc_purge_orig_nc_nodes(bat_priv, &orig_node->in_coding_list,
271 &orig_node->in_coding_list_lock,
272 to_purge);
273
274 /* Check outgoing nc_node's of this orig_node */
275 batadv_nc_purge_orig_nc_nodes(bat_priv, &orig_node->out_coding_list,
276 &orig_node->out_coding_list_lock,
277 to_purge);
278}
279
280/**
281 * batadv_nc_purge_orig_hash - traverse entire originator hash to check if they
282 * have timed out nc nodes
283 * @bat_priv: the bat priv with all the soft interface information
284 */
285static void batadv_nc_purge_orig_hash(struct batadv_priv *bat_priv)
286{
287 struct batadv_hashtable *hash = bat_priv->orig_hash;
288 struct hlist_head *head;
289 struct batadv_orig_node *orig_node;
290 uint32_t i;
291
292 if (!hash)
293 return;
294
295 /* For each orig_node */
296 for (i = 0; i < hash->size; i++) {
297 head = &hash->table[i];
298
299 rcu_read_lock();
300 hlist_for_each_entry_rcu(orig_node, head, hash_entry)
301 batadv_nc_purge_orig(bat_priv, orig_node,
302 batadv_nc_to_purge_nc_node);
303 rcu_read_unlock();
304 }
Martin Hundebølld353d8d2013-01-25 11:12:38 +0100305}
306
307/**
Martin Hundebøll95332472013-01-25 11:12:40 +0100308 * batadv_nc_purge_paths - traverse all nc paths part of the hash and remove
309 * unused ones
310 * @bat_priv: the bat priv with all the soft interface information
311 * @hash: hash table containing the nc paths to check
312 * @to_purge: function in charge to decide whether an entry has to be purged or
313 * not. This function takes the nc node as argument and has to return
314 * a boolean value: true is the entry has to be deleted, false
315 * otherwise
316 */
317static void batadv_nc_purge_paths(struct batadv_priv *bat_priv,
318 struct batadv_hashtable *hash,
319 bool (*to_purge)(struct batadv_priv *,
320 struct batadv_nc_path *))
321{
322 struct hlist_head *head;
323 struct hlist_node *node_tmp;
324 struct batadv_nc_path *nc_path;
325 spinlock_t *lock; /* Protects lists in hash */
326 uint32_t i;
327
328 for (i = 0; i < hash->size; i++) {
329 head = &hash->table[i];
330 lock = &hash->list_locks[i];
331
332 /* For each nc_path in this bin */
333 spin_lock_bh(lock);
334 hlist_for_each_entry_safe(nc_path, node_tmp, head, hash_entry) {
335 /* if an helper function has been passed as parameter,
336 * ask it if the entry has to be purged or not
337 */
338 if (to_purge && !to_purge(bat_priv, nc_path))
339 continue;
340
341 /* purging an non-empty nc_path should never happen, but
342 * is observed under high CPU load. Delay the purging
343 * until next iteration to allow the packet_list to be
344 * emptied first.
345 */
346 if (!unlikely(list_empty(&nc_path->packet_list))) {
347 net_ratelimited_function(printk,
348 KERN_WARNING
349 "Skipping free of non-empty nc_path (%pM -> %pM)!\n",
350 nc_path->prev_hop,
351 nc_path->next_hop);
352 continue;
353 }
354
355 /* nc_path is unused, so remove it */
356 batadv_dbg(BATADV_DBG_NC, bat_priv,
357 "Remove nc_path %pM -> %pM\n",
358 nc_path->prev_hop, nc_path->next_hop);
359 hlist_del_rcu(&nc_path->hash_entry);
360 batadv_nc_path_free_ref(nc_path);
361 }
362 spin_unlock_bh(lock);
363 }
364}
365
366/**
367 * batadv_nc_hash_key_gen - computes the nc_path hash key
368 * @key: buffer to hold the final hash key
369 * @src: source ethernet mac address going into the hash key
370 * @dst: destination ethernet mac address going into the hash key
371 */
372static void batadv_nc_hash_key_gen(struct batadv_nc_path *key, const char *src,
373 const char *dst)
374{
375 memcpy(key->prev_hop, src, sizeof(key->prev_hop));
376 memcpy(key->next_hop, dst, sizeof(key->next_hop));
377}
378
379/**
380 * batadv_nc_hash_choose - compute the hash value for an nc path
381 * @data: data to hash
382 * @size: size of the hash table
383 *
384 * Returns the selected index in the hash table for the given data.
385 */
386static uint32_t batadv_nc_hash_choose(const void *data, uint32_t size)
387{
388 const struct batadv_nc_path *nc_path = data;
389 uint32_t hash = 0;
390
391 hash = batadv_hash_bytes(hash, &nc_path->prev_hop,
392 sizeof(nc_path->prev_hop));
393 hash = batadv_hash_bytes(hash, &nc_path->next_hop,
394 sizeof(nc_path->next_hop));
395
396 hash += (hash << 3);
397 hash ^= (hash >> 11);
398 hash += (hash << 15);
399
400 return hash % size;
401}
402
403/**
404 * batadv_nc_hash_compare - comparing function used in the network coding hash
405 * tables
406 * @node: node in the local table
407 * @data2: second object to compare the node to
408 *
409 * Returns 1 if the two entry are the same, 0 otherwise
410 */
411static int batadv_nc_hash_compare(const struct hlist_node *node,
412 const void *data2)
413{
414 const struct batadv_nc_path *nc_path1, *nc_path2;
415
416 nc_path1 = container_of(node, struct batadv_nc_path, hash_entry);
417 nc_path2 = data2;
418
419 /* Return 1 if the two keys are identical */
420 if (memcmp(nc_path1->prev_hop, nc_path2->prev_hop,
421 sizeof(nc_path1->prev_hop)) != 0)
422 return 0;
423
424 if (memcmp(nc_path1->next_hop, nc_path2->next_hop,
425 sizeof(nc_path1->next_hop)) != 0)
426 return 0;
427
428 return 1;
429}
430
431/**
432 * batadv_nc_hash_find - search for an existing nc path and return it
433 * @hash: hash table containing the nc path
434 * @data: search key
435 *
436 * Returns the nc_path if found, NULL otherwise.
437 */
438static struct batadv_nc_path *
439batadv_nc_hash_find(struct batadv_hashtable *hash,
440 void *data)
441{
442 struct hlist_head *head;
443 struct batadv_nc_path *nc_path, *nc_path_tmp = NULL;
444 int index;
445
446 if (!hash)
447 return NULL;
448
449 index = batadv_nc_hash_choose(data, hash->size);
450 head = &hash->table[index];
451
452 rcu_read_lock();
453 hlist_for_each_entry_rcu(nc_path, head, hash_entry) {
454 if (!batadv_nc_hash_compare(&nc_path->hash_entry, data))
455 continue;
456
457 if (!atomic_inc_not_zero(&nc_path->refcount))
458 continue;
459
460 nc_path_tmp = nc_path;
461 break;
462 }
463 rcu_read_unlock();
464
465 return nc_path_tmp;
466}
467
468/**
469 * batadv_nc_send_packet - send non-coded packet and free nc_packet struct
470 * @nc_packet: the nc packet to send
471 */
472static void batadv_nc_send_packet(struct batadv_nc_packet *nc_packet)
473{
474 batadv_send_skb_packet(nc_packet->skb,
475 nc_packet->neigh_node->if_incoming,
476 nc_packet->nc_path->next_hop);
477 nc_packet->skb = NULL;
478 batadv_nc_packet_free(nc_packet);
479}
480
481/**
Martin Hundebøll612d2b42013-01-25 11:12:42 +0100482 * batadv_nc_sniffed_purge - Checks timestamp of given sniffed nc_packet.
483 * @bat_priv: the bat priv with all the soft interface information
484 * @nc_path: the nc path the packet belongs to
485 * @nc_packet: the nc packet to be checked
486 *
487 * Checks whether the given sniffed (overheard) nc_packet has hit its buffering
488 * timeout. If so, the packet is no longer kept and the entry deleted from the
489 * queue. Has to be called with the appropriate locks.
490 *
491 * Returns false as soon as the entry in the fifo queue has not been timed out
492 * yet and true otherwise.
493 */
494static bool batadv_nc_sniffed_purge(struct batadv_priv *bat_priv,
495 struct batadv_nc_path *nc_path,
496 struct batadv_nc_packet *nc_packet)
497{
498 unsigned long timeout = bat_priv->nc.max_buffer_time;
499 bool res = false;
500
501 /* Packets are added to tail, so the remaining packets did not time
502 * out and we can stop processing the current queue
503 */
504 if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_ACTIVE &&
505 !batadv_has_timed_out(nc_packet->timestamp, timeout))
506 goto out;
507
508 /* purge nc packet */
509 list_del(&nc_packet->list);
510 batadv_nc_packet_free(nc_packet);
511
512 res = true;
513
514out:
515 return res;
516}
517
518/**
Martin Hundebøll95332472013-01-25 11:12:40 +0100519 * batadv_nc_fwd_flush - Checks the timestamp of the given nc packet.
520 * @bat_priv: the bat priv with all the soft interface information
521 * @nc_path: the nc path the packet belongs to
522 * @nc_packet: the nc packet to be checked
523 *
524 * Checks whether the given nc packet has hit its forward timeout. If so, the
525 * packet is no longer delayed, immediately sent and the entry deleted from the
526 * queue. Has to be called with the appropriate locks.
527 *
528 * Returns false as soon as the entry in the fifo queue has not been timed out
529 * yet and true otherwise.
530 */
531static bool batadv_nc_fwd_flush(struct batadv_priv *bat_priv,
532 struct batadv_nc_path *nc_path,
533 struct batadv_nc_packet *nc_packet)
534{
535 unsigned long timeout = bat_priv->nc.max_fwd_delay;
536
537 /* Packets are added to tail, so the remaining packets did not time
538 * out and we can stop processing the current queue
539 */
540 if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_ACTIVE &&
541 !batadv_has_timed_out(nc_packet->timestamp, timeout))
542 return false;
543
544 /* Send packet */
545 batadv_inc_counter(bat_priv, BATADV_CNT_FORWARD);
546 batadv_add_counter(bat_priv, BATADV_CNT_FORWARD_BYTES,
547 nc_packet->skb->len + ETH_HLEN);
548 list_del(&nc_packet->list);
549 batadv_nc_send_packet(nc_packet);
550
551 return true;
552}
553
554/**
555 * batadv_nc_process_nc_paths - traverse given nc packet pool and free timed out
556 * nc packets
557 * @bat_priv: the bat priv with all the soft interface information
558 * @hash: to be processed hash table
559 * @process_fn: Function called to process given nc packet. Should return true
560 * to encourage this function to proceed with the next packet.
561 * Otherwise the rest of the current queue is skipped.
562 */
563static void
564batadv_nc_process_nc_paths(struct batadv_priv *bat_priv,
565 struct batadv_hashtable *hash,
566 bool (*process_fn)(struct batadv_priv *,
567 struct batadv_nc_path *,
568 struct batadv_nc_packet *))
569{
570 struct hlist_head *head;
571 struct batadv_nc_packet *nc_packet, *nc_packet_tmp;
572 struct batadv_nc_path *nc_path;
573 bool ret;
574 int i;
575
576 if (!hash)
577 return;
578
579 /* Loop hash table bins */
580 for (i = 0; i < hash->size; i++) {
581 head = &hash->table[i];
582
583 /* Loop coding paths */
584 rcu_read_lock();
585 hlist_for_each_entry_rcu(nc_path, head, hash_entry) {
586 /* Loop packets */
587 spin_lock_bh(&nc_path->packet_list_lock);
588 list_for_each_entry_safe(nc_packet, nc_packet_tmp,
589 &nc_path->packet_list, list) {
590 ret = process_fn(bat_priv, nc_path, nc_packet);
591 if (!ret)
592 break;
593 }
594 spin_unlock_bh(&nc_path->packet_list_lock);
595 }
596 rcu_read_unlock();
597 }
598}
599
600/**
Martin Hundebølld353d8d2013-01-25 11:12:38 +0100601 * batadv_nc_worker - periodic task for house keeping related to network coding
602 * @work: kernel work struct
603 */
604static void batadv_nc_worker(struct work_struct *work)
605{
606 struct delayed_work *delayed_work;
607 struct batadv_priv_nc *priv_nc;
608 struct batadv_priv *bat_priv;
Martin Hundebøll95332472013-01-25 11:12:40 +0100609 unsigned long timeout;
Martin Hundebølld353d8d2013-01-25 11:12:38 +0100610
611 delayed_work = container_of(work, struct delayed_work, work);
612 priv_nc = container_of(delayed_work, struct batadv_priv_nc, work);
613 bat_priv = container_of(priv_nc, struct batadv_priv, nc);
614
Martin Hundebølld56b1702013-01-25 11:12:39 +0100615 batadv_nc_purge_orig_hash(bat_priv);
Martin Hundebøll95332472013-01-25 11:12:40 +0100616 batadv_nc_purge_paths(bat_priv, bat_priv->nc.coding_hash,
617 batadv_nc_to_purge_nc_path_coding);
Martin Hundebøll612d2b42013-01-25 11:12:42 +0100618 batadv_nc_purge_paths(bat_priv, bat_priv->nc.decoding_hash,
619 batadv_nc_to_purge_nc_path_decoding);
Martin Hundebøll95332472013-01-25 11:12:40 +0100620
621 timeout = bat_priv->nc.max_fwd_delay;
622
623 if (batadv_has_timed_out(bat_priv->nc.timestamp_fwd_flush, timeout)) {
624 batadv_nc_process_nc_paths(bat_priv, bat_priv->nc.coding_hash,
625 batadv_nc_fwd_flush);
626 bat_priv->nc.timestamp_fwd_flush = jiffies;
627 }
Martin Hundebølld56b1702013-01-25 11:12:39 +0100628
Martin Hundebøll612d2b42013-01-25 11:12:42 +0100629 if (batadv_has_timed_out(bat_priv->nc.timestamp_sniffed_purge,
630 bat_priv->nc.max_buffer_time)) {
631 batadv_nc_process_nc_paths(bat_priv, bat_priv->nc.decoding_hash,
632 batadv_nc_sniffed_purge);
633 bat_priv->nc.timestamp_sniffed_purge = jiffies;
634 }
635
Martin Hundebølld353d8d2013-01-25 11:12:38 +0100636 /* Schedule a new check */
637 batadv_nc_start_timer(bat_priv);
638}
639
640/**
Martin Hundebølld56b1702013-01-25 11:12:39 +0100641 * batadv_can_nc_with_orig - checks whether the given orig node is suitable for
642 * coding or not
643 * @bat_priv: the bat priv with all the soft interface information
644 * @orig_node: neighboring orig node which may be used as nc candidate
645 * @ogm_packet: incoming ogm packet also used for the checks
646 *
647 * Returns true if:
648 * 1) The OGM must have the most recent sequence number.
649 * 2) The TTL must be decremented by one and only one.
650 * 3) The OGM must be received from the first hop from orig_node.
651 * 4) The TQ value of the OGM must be above bat_priv->nc.min_tq.
652 */
653static bool batadv_can_nc_with_orig(struct batadv_priv *bat_priv,
654 struct batadv_orig_node *orig_node,
655 struct batadv_ogm_packet *ogm_packet)
656{
Martin Hundebølle6a0b492013-03-14 21:30:21 +0100657 if (orig_node->last_real_seqno != ntohl(ogm_packet->seqno))
Martin Hundebølld56b1702013-01-25 11:12:39 +0100658 return false;
659 if (orig_node->last_ttl != ogm_packet->header.ttl + 1)
660 return false;
661 if (!batadv_compare_eth(ogm_packet->orig, ogm_packet->prev_sender))
662 return false;
663 if (ogm_packet->tq < bat_priv->nc.min_tq)
664 return false;
665
666 return true;
667}
668
669/**
670 * batadv_nc_find_nc_node - search for an existing nc node and return it
671 * @orig_node: orig node originating the ogm packet
672 * @orig_neigh_node: neighboring orig node from which we received the ogm packet
673 * (can be equal to orig_node)
674 * @in_coding: traverse incoming or outgoing network coding list
675 *
676 * Returns the nc_node if found, NULL otherwise.
677 */
678static struct batadv_nc_node
679*batadv_nc_find_nc_node(struct batadv_orig_node *orig_node,
680 struct batadv_orig_node *orig_neigh_node,
681 bool in_coding)
682{
683 struct batadv_nc_node *nc_node, *nc_node_out = NULL;
684 struct list_head *list;
685
686 if (in_coding)
687 list = &orig_neigh_node->in_coding_list;
688 else
689 list = &orig_neigh_node->out_coding_list;
690
691 /* Traverse list of nc_nodes to orig_node */
692 rcu_read_lock();
693 list_for_each_entry_rcu(nc_node, list, list) {
694 if (!batadv_compare_eth(nc_node->addr, orig_node->orig))
695 continue;
696
697 if (!atomic_inc_not_zero(&nc_node->refcount))
698 continue;
699
700 /* Found a match */
701 nc_node_out = nc_node;
702 break;
703 }
704 rcu_read_unlock();
705
706 return nc_node_out;
707}
708
709/**
710 * batadv_nc_get_nc_node - retrieves an nc node or creates the entry if it was
711 * not found
712 * @bat_priv: the bat priv with all the soft interface information
713 * @orig_node: orig node originating the ogm packet
714 * @orig_neigh_node: neighboring orig node from which we received the ogm packet
715 * (can be equal to orig_node)
716 * @in_coding: traverse incoming or outgoing network coding list
717 *
718 * Returns the nc_node if found or created, NULL in case of an error.
719 */
720static struct batadv_nc_node
721*batadv_nc_get_nc_node(struct batadv_priv *bat_priv,
722 struct batadv_orig_node *orig_node,
723 struct batadv_orig_node *orig_neigh_node,
724 bool in_coding)
725{
726 struct batadv_nc_node *nc_node;
727 spinlock_t *lock; /* Used to lock list selected by "int in_coding" */
728 struct list_head *list;
729
730 /* Check if nc_node is already added */
731 nc_node = batadv_nc_find_nc_node(orig_node, orig_neigh_node, in_coding);
732
733 /* Node found */
734 if (nc_node)
735 return nc_node;
736
737 nc_node = kzalloc(sizeof(*nc_node), GFP_ATOMIC);
738 if (!nc_node)
739 return NULL;
740
741 if (!atomic_inc_not_zero(&orig_neigh_node->refcount))
742 goto free;
743
744 /* Initialize nc_node */
745 INIT_LIST_HEAD(&nc_node->list);
746 memcpy(nc_node->addr, orig_node->orig, ETH_ALEN);
747 nc_node->orig_node = orig_neigh_node;
748 atomic_set(&nc_node->refcount, 2);
749
750 /* Select ingoing or outgoing coding node */
751 if (in_coding) {
752 lock = &orig_neigh_node->in_coding_list_lock;
753 list = &orig_neigh_node->in_coding_list;
754 } else {
755 lock = &orig_neigh_node->out_coding_list_lock;
756 list = &orig_neigh_node->out_coding_list;
757 }
758
759 batadv_dbg(BATADV_DBG_NC, bat_priv, "Adding nc_node %pM -> %pM\n",
760 nc_node->addr, nc_node->orig_node->orig);
761
762 /* Add nc_node to orig_node */
763 spin_lock_bh(lock);
764 list_add_tail_rcu(&nc_node->list, list);
765 spin_unlock_bh(lock);
766
767 return nc_node;
768
769free:
770 kfree(nc_node);
771 return NULL;
772}
773
774/**
775 * batadv_nc_update_nc_node - updates stored incoming and outgoing nc node structs
776 * (best called on incoming OGMs)
777 * @bat_priv: the bat priv with all the soft interface information
778 * @orig_node: orig node originating the ogm packet
779 * @orig_neigh_node: neighboring orig node from which we received the ogm packet
780 * (can be equal to orig_node)
781 * @ogm_packet: incoming ogm packet
782 * @is_single_hop_neigh: orig_node is a single hop neighbor
783 */
784void batadv_nc_update_nc_node(struct batadv_priv *bat_priv,
785 struct batadv_orig_node *orig_node,
786 struct batadv_orig_node *orig_neigh_node,
787 struct batadv_ogm_packet *ogm_packet,
788 int is_single_hop_neigh)
789{
790 struct batadv_nc_node *in_nc_node = NULL, *out_nc_node = NULL;
791
792 /* Check if network coding is enabled */
793 if (!atomic_read(&bat_priv->network_coding))
794 goto out;
795
796 /* accept ogms from 'good' neighbors and single hop neighbors */
797 if (!batadv_can_nc_with_orig(bat_priv, orig_node, ogm_packet) &&
798 !is_single_hop_neigh)
799 goto out;
800
801 /* Add orig_node as in_nc_node on hop */
802 in_nc_node = batadv_nc_get_nc_node(bat_priv, orig_node,
803 orig_neigh_node, true);
804 if (!in_nc_node)
805 goto out;
806
807 in_nc_node->last_seen = jiffies;
808
809 /* Add hop as out_nc_node on orig_node */
810 out_nc_node = batadv_nc_get_nc_node(bat_priv, orig_neigh_node,
811 orig_node, false);
812 if (!out_nc_node)
813 goto out;
814
815 out_nc_node->last_seen = jiffies;
816
817out:
818 if (in_nc_node)
819 batadv_nc_node_free_ref(in_nc_node);
820 if (out_nc_node)
821 batadv_nc_node_free_ref(out_nc_node);
822}
823
824/**
Martin Hundebøll95332472013-01-25 11:12:40 +0100825 * batadv_nc_get_path - get existing nc_path or allocate a new one
826 * @bat_priv: the bat priv with all the soft interface information
827 * @hash: hash table containing the nc path
828 * @src: ethernet source address - first half of the nc path search key
829 * @dst: ethernet destination address - second half of the nc path search key
830 *
831 * Returns pointer to nc_path if the path was found or created, returns NULL
832 * on error.
833 */
834static struct batadv_nc_path *batadv_nc_get_path(struct batadv_priv *bat_priv,
835 struct batadv_hashtable *hash,
836 uint8_t *src,
837 uint8_t *dst)
838{
839 int hash_added;
840 struct batadv_nc_path *nc_path, nc_path_key;
841
842 batadv_nc_hash_key_gen(&nc_path_key, src, dst);
843
844 /* Search for existing nc_path */
845 nc_path = batadv_nc_hash_find(hash, (void *)&nc_path_key);
846
847 if (nc_path) {
848 /* Set timestamp to delay removal of nc_path */
849 nc_path->last_valid = jiffies;
850 return nc_path;
851 }
852
853 /* No existing nc_path was found; create a new */
854 nc_path = kzalloc(sizeof(*nc_path), GFP_ATOMIC);
855
856 if (!nc_path)
857 return NULL;
858
859 /* Initialize nc_path */
860 INIT_LIST_HEAD(&nc_path->packet_list);
861 spin_lock_init(&nc_path->packet_list_lock);
862 atomic_set(&nc_path->refcount, 2);
863 nc_path->last_valid = jiffies;
864 memcpy(nc_path->next_hop, dst, ETH_ALEN);
865 memcpy(nc_path->prev_hop, src, ETH_ALEN);
866
867 batadv_dbg(BATADV_DBG_NC, bat_priv, "Adding nc_path %pM -> %pM\n",
868 nc_path->prev_hop,
869 nc_path->next_hop);
870
871 /* Add nc_path to hash table */
872 hash_added = batadv_hash_add(hash, batadv_nc_hash_compare,
873 batadv_nc_hash_choose, &nc_path_key,
874 &nc_path->hash_entry);
875
876 if (hash_added < 0) {
877 kfree(nc_path);
878 return NULL;
879 }
880
881 return nc_path;
882}
883
884/**
Martin Hundebøll3c12de92013-01-25 11:12:41 +0100885 * batadv_nc_random_weight_tq - scale the receivers TQ-value to avoid unfair
886 * selection of a receiver with slightly lower TQ than the other
887 * @tq: to be weighted tq value
888 */
889static uint8_t batadv_nc_random_weight_tq(uint8_t tq)
890{
891 uint8_t rand_val, rand_tq;
892
893 get_random_bytes(&rand_val, sizeof(rand_val));
894
895 /* randomize the estimated packet loss (max TQ - estimated TQ) */
896 rand_tq = rand_val * (BATADV_TQ_MAX_VALUE - tq);
897
898 /* normalize the randomized packet loss */
899 rand_tq /= BATADV_TQ_MAX_VALUE;
900
901 /* convert to (randomized) estimated tq again */
902 return BATADV_TQ_MAX_VALUE - rand_tq;
903}
904
905/**
906 * batadv_nc_memxor - XOR destination with source
907 * @dst: byte array to XOR into
908 * @src: byte array to XOR from
909 * @len: length of destination array
910 */
911static void batadv_nc_memxor(char *dst, const char *src, unsigned int len)
912{
913 unsigned int i;
914
915 for (i = 0; i < len; ++i)
916 dst[i] ^= src[i];
917}
918
919/**
920 * batadv_nc_code_packets - code a received unicast_packet with an nc packet
921 * into a coded_packet and send it
922 * @bat_priv: the bat priv with all the soft interface information
923 * @skb: data skb to forward
924 * @ethhdr: pointer to the ethernet header inside the skb
925 * @nc_packet: structure containing the packet to the skb can be coded with
926 * @neigh_node: next hop to forward packet to
927 *
928 * Returns true if both packets are consumed, false otherwise.
929 */
930static bool batadv_nc_code_packets(struct batadv_priv *bat_priv,
931 struct sk_buff *skb,
932 struct ethhdr *ethhdr,
933 struct batadv_nc_packet *nc_packet,
934 struct batadv_neigh_node *neigh_node)
935{
936 uint8_t tq_weighted_neigh, tq_weighted_coding;
937 struct sk_buff *skb_dest, *skb_src;
938 struct batadv_unicast_packet *packet1;
939 struct batadv_unicast_packet *packet2;
940 struct batadv_coded_packet *coded_packet;
941 struct batadv_neigh_node *neigh_tmp, *router_neigh;
942 struct batadv_neigh_node *router_coding = NULL;
943 uint8_t *first_source, *first_dest, *second_source, *second_dest;
944 __be32 packet_id1, packet_id2;
945 size_t count;
946 bool res = false;
947 int coding_len;
948 int unicast_size = sizeof(*packet1);
949 int coded_size = sizeof(*coded_packet);
950 int header_add = coded_size - unicast_size;
951
952 router_neigh = batadv_orig_node_get_router(neigh_node->orig_node);
953 if (!router_neigh)
954 goto out;
955
956 neigh_tmp = nc_packet->neigh_node;
957 router_coding = batadv_orig_node_get_router(neigh_tmp->orig_node);
958 if (!router_coding)
959 goto out;
960
961 tq_weighted_neigh = batadv_nc_random_weight_tq(router_neigh->tq_avg);
962 tq_weighted_coding = batadv_nc_random_weight_tq(router_coding->tq_avg);
963
964 /* Select one destination for the MAC-header dst-field based on
965 * weighted TQ-values.
966 */
967 if (tq_weighted_neigh >= tq_weighted_coding) {
968 /* Destination from nc_packet is selected for MAC-header */
969 first_dest = nc_packet->nc_path->next_hop;
970 first_source = nc_packet->nc_path->prev_hop;
971 second_dest = neigh_node->addr;
972 second_source = ethhdr->h_source;
973 packet1 = (struct batadv_unicast_packet *)nc_packet->skb->data;
974 packet2 = (struct batadv_unicast_packet *)skb->data;
975 packet_id1 = nc_packet->packet_id;
976 packet_id2 = batadv_skb_crc32(skb,
977 skb->data + sizeof(*packet2));
978 } else {
979 /* Destination for skb is selected for MAC-header */
980 first_dest = neigh_node->addr;
981 first_source = ethhdr->h_source;
982 second_dest = nc_packet->nc_path->next_hop;
983 second_source = nc_packet->nc_path->prev_hop;
984 packet1 = (struct batadv_unicast_packet *)skb->data;
985 packet2 = (struct batadv_unicast_packet *)nc_packet->skb->data;
986 packet_id1 = batadv_skb_crc32(skb,
987 skb->data + sizeof(*packet1));
988 packet_id2 = nc_packet->packet_id;
989 }
990
991 /* Instead of zero padding the smallest data buffer, we
992 * code into the largest.
993 */
994 if (skb->len <= nc_packet->skb->len) {
995 skb_dest = nc_packet->skb;
996 skb_src = skb;
997 } else {
998 skb_dest = skb;
999 skb_src = nc_packet->skb;
1000 }
1001
1002 /* coding_len is used when decoding the packet shorter packet */
1003 coding_len = skb_src->len - unicast_size;
1004
1005 if (skb_linearize(skb_dest) < 0 || skb_linearize(skb_src) < 0)
1006 goto out;
1007
1008 skb_push(skb_dest, header_add);
1009
1010 coded_packet = (struct batadv_coded_packet *)skb_dest->data;
1011 skb_reset_mac_header(skb_dest);
1012
1013 coded_packet->header.packet_type = BATADV_CODED;
1014 coded_packet->header.version = BATADV_COMPAT_VERSION;
1015 coded_packet->header.ttl = packet1->header.ttl;
1016
1017 /* Info about first unicast packet */
1018 memcpy(coded_packet->first_source, first_source, ETH_ALEN);
1019 memcpy(coded_packet->first_orig_dest, packet1->dest, ETH_ALEN);
1020 coded_packet->first_crc = packet_id1;
1021 coded_packet->first_ttvn = packet1->ttvn;
1022
1023 /* Info about second unicast packet */
1024 memcpy(coded_packet->second_dest, second_dest, ETH_ALEN);
1025 memcpy(coded_packet->second_source, second_source, ETH_ALEN);
1026 memcpy(coded_packet->second_orig_dest, packet2->dest, ETH_ALEN);
1027 coded_packet->second_crc = packet_id2;
1028 coded_packet->second_ttl = packet2->header.ttl;
1029 coded_packet->second_ttvn = packet2->ttvn;
1030 coded_packet->coded_len = htons(coding_len);
1031
1032 /* This is where the magic happens: Code skb_src into skb_dest */
1033 batadv_nc_memxor(skb_dest->data + coded_size,
1034 skb_src->data + unicast_size, coding_len);
1035
1036 /* Update counters accordingly */
1037 if (BATADV_SKB_CB(skb_src)->decoded &&
1038 BATADV_SKB_CB(skb_dest)->decoded) {
1039 /* Both packets are recoded */
1040 count = skb_src->len + ETH_HLEN;
1041 count += skb_dest->len + ETH_HLEN;
1042 batadv_add_counter(bat_priv, BATADV_CNT_NC_RECODE, 2);
1043 batadv_add_counter(bat_priv, BATADV_CNT_NC_RECODE_BYTES, count);
1044 } else if (!BATADV_SKB_CB(skb_src)->decoded &&
1045 !BATADV_SKB_CB(skb_dest)->decoded) {
1046 /* Both packets are newly coded */
1047 count = skb_src->len + ETH_HLEN;
1048 count += skb_dest->len + ETH_HLEN;
1049 batadv_add_counter(bat_priv, BATADV_CNT_NC_CODE, 2);
1050 batadv_add_counter(bat_priv, BATADV_CNT_NC_CODE_BYTES, count);
1051 } else if (BATADV_SKB_CB(skb_src)->decoded &&
1052 !BATADV_SKB_CB(skb_dest)->decoded) {
1053 /* skb_src recoded and skb_dest is newly coded */
1054 batadv_inc_counter(bat_priv, BATADV_CNT_NC_RECODE);
1055 batadv_add_counter(bat_priv, BATADV_CNT_NC_RECODE_BYTES,
1056 skb_src->len + ETH_HLEN);
1057 batadv_inc_counter(bat_priv, BATADV_CNT_NC_CODE);
1058 batadv_add_counter(bat_priv, BATADV_CNT_NC_CODE_BYTES,
1059 skb_dest->len + ETH_HLEN);
1060 } else if (!BATADV_SKB_CB(skb_src)->decoded &&
1061 BATADV_SKB_CB(skb_dest)->decoded) {
1062 /* skb_src is newly coded and skb_dest is recoded */
1063 batadv_inc_counter(bat_priv, BATADV_CNT_NC_CODE);
1064 batadv_add_counter(bat_priv, BATADV_CNT_NC_CODE_BYTES,
1065 skb_src->len + ETH_HLEN);
1066 batadv_inc_counter(bat_priv, BATADV_CNT_NC_RECODE);
1067 batadv_add_counter(bat_priv, BATADV_CNT_NC_RECODE_BYTES,
1068 skb_dest->len + ETH_HLEN);
1069 }
1070
1071 /* skb_src is now coded into skb_dest, so free it */
1072 kfree_skb(skb_src);
1073
1074 /* avoid duplicate free of skb from nc_packet */
1075 nc_packet->skb = NULL;
1076 batadv_nc_packet_free(nc_packet);
1077
1078 /* Send the coded packet and return true */
1079 batadv_send_skb_packet(skb_dest, neigh_node->if_incoming, first_dest);
1080 res = true;
1081out:
1082 if (router_neigh)
1083 batadv_neigh_node_free_ref(router_neigh);
1084 if (router_coding)
1085 batadv_neigh_node_free_ref(router_coding);
1086 return res;
1087}
1088
1089/**
1090 * batadv_nc_skb_coding_possible - true if a decoded skb is available at dst.
1091 * @skb: data skb to forward
1092 * @dst: destination mac address of the other skb to code with
1093 * @src: source mac address of skb
1094 *
1095 * Whenever we network code a packet we have to check whether we received it in
1096 * a network coded form. If so, we may not be able to use it for coding because
1097 * some neighbors may also have received (overheard) the packet in the network
1098 * coded form without being able to decode it. It is hard to know which of the
1099 * neighboring nodes was able to decode the packet, therefore we can only
1100 * re-code the packet if the source of the previous encoded packet is involved.
1101 * Since the source encoded the packet we can be certain it has all necessary
1102 * decode information.
1103 *
1104 * Returns true if coding of a decoded packet is allowed.
1105 */
1106static bool batadv_nc_skb_coding_possible(struct sk_buff *skb,
1107 uint8_t *dst, uint8_t *src)
1108{
1109 if (BATADV_SKB_CB(skb)->decoded && !batadv_compare_eth(dst, src))
1110 return false;
1111 else
1112 return true;
1113}
1114
1115/**
1116 * batadv_nc_path_search - Find the coding path matching in_nc_node and
1117 * out_nc_node to retrieve a buffered packet that can be used for coding.
1118 * @bat_priv: the bat priv with all the soft interface information
1119 * @in_nc_node: pointer to skb next hop's neighbor nc node
1120 * @out_nc_node: pointer to skb source's neighbor nc node
1121 * @skb: data skb to forward
1122 * @eth_dst: next hop mac address of skb
1123 *
1124 * Returns true if coding of a decoded skb is allowed.
1125 */
1126static struct batadv_nc_packet *
1127batadv_nc_path_search(struct batadv_priv *bat_priv,
1128 struct batadv_nc_node *in_nc_node,
1129 struct batadv_nc_node *out_nc_node,
1130 struct sk_buff *skb,
1131 uint8_t *eth_dst)
1132{
1133 struct batadv_nc_path *nc_path, nc_path_key;
1134 struct batadv_nc_packet *nc_packet_out = NULL;
1135 struct batadv_nc_packet *nc_packet, *nc_packet_tmp;
1136 struct batadv_hashtable *hash = bat_priv->nc.coding_hash;
1137 int idx;
1138
1139 if (!hash)
1140 return NULL;
1141
1142 /* Create almost path key */
1143 batadv_nc_hash_key_gen(&nc_path_key, in_nc_node->addr,
1144 out_nc_node->addr);
1145 idx = batadv_nc_hash_choose(&nc_path_key, hash->size);
1146
1147 /* Check for coding opportunities in this nc_path */
1148 rcu_read_lock();
1149 hlist_for_each_entry_rcu(nc_path, &hash->table[idx], hash_entry) {
1150 if (!batadv_compare_eth(nc_path->prev_hop, in_nc_node->addr))
1151 continue;
1152
1153 if (!batadv_compare_eth(nc_path->next_hop, out_nc_node->addr))
1154 continue;
1155
1156 spin_lock_bh(&nc_path->packet_list_lock);
1157 if (list_empty(&nc_path->packet_list)) {
1158 spin_unlock_bh(&nc_path->packet_list_lock);
1159 continue;
1160 }
1161
1162 list_for_each_entry_safe(nc_packet, nc_packet_tmp,
1163 &nc_path->packet_list, list) {
1164 if (!batadv_nc_skb_coding_possible(nc_packet->skb,
1165 eth_dst,
1166 in_nc_node->addr))
1167 continue;
1168
1169 /* Coding opportunity is found! */
1170 list_del(&nc_packet->list);
1171 nc_packet_out = nc_packet;
1172 break;
1173 }
1174
1175 spin_unlock_bh(&nc_path->packet_list_lock);
1176 break;
1177 }
1178 rcu_read_unlock();
1179
1180 return nc_packet_out;
1181}
1182
1183/**
1184 * batadv_nc_skb_src_search - Loops through the list of neighoring nodes of the
1185 * skb's sender (may be equal to the originator).
1186 * @bat_priv: the bat priv with all the soft interface information
1187 * @skb: data skb to forward
1188 * @eth_dst: next hop mac address of skb
1189 * @eth_src: source mac address of skb
1190 * @in_nc_node: pointer to skb next hop's neighbor nc node
1191 *
1192 * Returns an nc packet if a suitable coding packet was found, NULL otherwise.
1193 */
1194static struct batadv_nc_packet *
1195batadv_nc_skb_src_search(struct batadv_priv *bat_priv,
1196 struct sk_buff *skb,
1197 uint8_t *eth_dst,
1198 uint8_t *eth_src,
1199 struct batadv_nc_node *in_nc_node)
1200{
1201 struct batadv_orig_node *orig_node;
1202 struct batadv_nc_node *out_nc_node;
1203 struct batadv_nc_packet *nc_packet = NULL;
1204
1205 orig_node = batadv_orig_hash_find(bat_priv, eth_src);
1206 if (!orig_node)
1207 return NULL;
1208
1209 rcu_read_lock();
1210 list_for_each_entry_rcu(out_nc_node,
1211 &orig_node->out_coding_list, list) {
1212 /* Check if the skb is decoded and if recoding is possible */
1213 if (!batadv_nc_skb_coding_possible(skb,
1214 out_nc_node->addr, eth_src))
1215 continue;
1216
1217 /* Search for an opportunity in this nc_path */
1218 nc_packet = batadv_nc_path_search(bat_priv, in_nc_node,
1219 out_nc_node, skb, eth_dst);
1220 if (nc_packet)
1221 break;
1222 }
1223 rcu_read_unlock();
1224
1225 batadv_orig_node_free_ref(orig_node);
1226 return nc_packet;
1227}
1228
1229/**
Martin Hundebøll612d2b42013-01-25 11:12:42 +01001230 * batadv_nc_skb_store_before_coding - set the ethernet src and dst of the
1231 * unicast skb before it is stored for use in later decoding
1232 * @bat_priv: the bat priv with all the soft interface information
1233 * @skb: data skb to store
1234 * @eth_dst_new: new destination mac address of skb
1235 */
1236static void batadv_nc_skb_store_before_coding(struct batadv_priv *bat_priv,
1237 struct sk_buff *skb,
1238 uint8_t *eth_dst_new)
1239{
1240 struct ethhdr *ethhdr;
1241
1242 /* Copy skb header to change the mac header */
1243 skb = pskb_copy(skb, GFP_ATOMIC);
1244 if (!skb)
1245 return;
1246
1247 /* Set the mac header as if we actually sent the packet uncoded */
1248 ethhdr = (struct ethhdr *)skb_mac_header(skb);
1249 memcpy(ethhdr->h_source, ethhdr->h_dest, ETH_ALEN);
1250 memcpy(ethhdr->h_dest, eth_dst_new, ETH_ALEN);
1251
1252 /* Set data pointer to MAC header to mimic packets from our tx path */
1253 skb_push(skb, ETH_HLEN);
1254
1255 /* Add the packet to the decoding packet pool */
1256 batadv_nc_skb_store_for_decoding(bat_priv, skb);
1257
1258 /* batadv_nc_skb_store_for_decoding() clones the skb, so we must free
1259 * our ref
1260 */
1261 kfree_skb(skb);
1262}
1263
1264/**
Martin Hundebøll3c12de92013-01-25 11:12:41 +01001265 * batadv_nc_skb_dst_search - Loops through list of neighboring nodes to dst.
1266 * @skb: data skb to forward
1267 * @neigh_node: next hop to forward packet to
1268 * @ethhdr: pointer to the ethernet header inside the skb
1269 *
1270 * Loops through list of neighboring nodes the next hop has a good connection to
1271 * (receives OGMs with a sufficient quality). We need to find a neighbor of our
1272 * next hop that potentially sent a packet which our next hop also received
1273 * (overheard) and has stored for later decoding.
1274 *
1275 * Returns true if the skb was consumed (encoded packet sent) or false otherwise
1276 */
1277static bool batadv_nc_skb_dst_search(struct sk_buff *skb,
1278 struct batadv_neigh_node *neigh_node,
1279 struct ethhdr *ethhdr)
1280{
1281 struct net_device *netdev = neigh_node->if_incoming->soft_iface;
1282 struct batadv_priv *bat_priv = netdev_priv(netdev);
1283 struct batadv_orig_node *orig_node = neigh_node->orig_node;
1284 struct batadv_nc_node *nc_node;
1285 struct batadv_nc_packet *nc_packet = NULL;
1286
1287 rcu_read_lock();
1288 list_for_each_entry_rcu(nc_node, &orig_node->in_coding_list, list) {
1289 /* Search for coding opportunity with this in_nc_node */
1290 nc_packet = batadv_nc_skb_src_search(bat_priv, skb,
1291 neigh_node->addr,
1292 ethhdr->h_source, nc_node);
1293
1294 /* Opportunity was found, so stop searching */
1295 if (nc_packet)
1296 break;
1297 }
1298 rcu_read_unlock();
1299
1300 if (!nc_packet)
1301 return false;
1302
Martin Hundebøll612d2b42013-01-25 11:12:42 +01001303 /* Save packets for later decoding */
1304 batadv_nc_skb_store_before_coding(bat_priv, skb,
1305 neigh_node->addr);
1306 batadv_nc_skb_store_before_coding(bat_priv, nc_packet->skb,
1307 nc_packet->neigh_node->addr);
1308
Martin Hundebøll3c12de92013-01-25 11:12:41 +01001309 /* Code and send packets */
1310 if (batadv_nc_code_packets(bat_priv, skb, ethhdr, nc_packet,
1311 neigh_node))
1312 return true;
1313
1314 /* out of mem ? Coding failed - we have to free the buffered packet
1315 * to avoid memleaks. The skb passed as argument will be dealt with
1316 * by the calling function.
1317 */
1318 batadv_nc_send_packet(nc_packet);
1319 return false;
1320}
1321
1322/**
Martin Hundebøll95332472013-01-25 11:12:40 +01001323 * batadv_nc_skb_add_to_path - buffer skb for later encoding / decoding
1324 * @skb: skb to add to path
1325 * @nc_path: path to add skb to
1326 * @neigh_node: next hop to forward packet to
1327 * @packet_id: checksum to identify packet
1328 *
1329 * Returns true if the packet was buffered or false in case of an error.
1330 */
1331static bool batadv_nc_skb_add_to_path(struct sk_buff *skb,
1332 struct batadv_nc_path *nc_path,
1333 struct batadv_neigh_node *neigh_node,
1334 __be32 packet_id)
1335{
1336 struct batadv_nc_packet *nc_packet;
1337
1338 nc_packet = kzalloc(sizeof(*nc_packet), GFP_ATOMIC);
1339 if (!nc_packet)
1340 return false;
1341
1342 /* Initialize nc_packet */
1343 nc_packet->timestamp = jiffies;
1344 nc_packet->packet_id = packet_id;
1345 nc_packet->skb = skb;
1346 nc_packet->neigh_node = neigh_node;
1347 nc_packet->nc_path = nc_path;
1348
1349 /* Add coding packet to list */
1350 spin_lock_bh(&nc_path->packet_list_lock);
1351 list_add_tail(&nc_packet->list, &nc_path->packet_list);
1352 spin_unlock_bh(&nc_path->packet_list_lock);
1353
1354 return true;
1355}
1356
1357/**
1358 * batadv_nc_skb_forward - try to code a packet or add it to the coding packet
1359 * buffer
1360 * @skb: data skb to forward
1361 * @neigh_node: next hop to forward packet to
1362 * @ethhdr: pointer to the ethernet header inside the skb
1363 *
1364 * Returns true if the skb was consumed (encoded packet sent) or false otherwise
1365 */
1366bool batadv_nc_skb_forward(struct sk_buff *skb,
1367 struct batadv_neigh_node *neigh_node,
1368 struct ethhdr *ethhdr)
1369{
1370 const struct net_device *netdev = neigh_node->if_incoming->soft_iface;
1371 struct batadv_priv *bat_priv = netdev_priv(netdev);
1372 struct batadv_unicast_packet *packet;
1373 struct batadv_nc_path *nc_path;
1374 __be32 packet_id;
1375 u8 *payload;
1376
1377 /* Check if network coding is enabled */
1378 if (!atomic_read(&bat_priv->network_coding))
1379 goto out;
1380
1381 /* We only handle unicast packets */
1382 payload = skb_network_header(skb);
1383 packet = (struct batadv_unicast_packet *)payload;
1384 if (packet->header.packet_type != BATADV_UNICAST)
1385 goto out;
1386
Martin Hundebøll3c12de92013-01-25 11:12:41 +01001387 /* Try to find a coding opportunity and send the skb if one is found */
1388 if (batadv_nc_skb_dst_search(skb, neigh_node, ethhdr))
1389 return true;
1390
Martin Hundebøll95332472013-01-25 11:12:40 +01001391 /* Find or create a nc_path for this src-dst pair */
1392 nc_path = batadv_nc_get_path(bat_priv,
1393 bat_priv->nc.coding_hash,
1394 ethhdr->h_source,
1395 neigh_node->addr);
1396
1397 if (!nc_path)
1398 goto out;
1399
1400 /* Add skb to nc_path */
1401 packet_id = batadv_skb_crc32(skb, payload + sizeof(*packet));
1402 if (!batadv_nc_skb_add_to_path(skb, nc_path, neigh_node, packet_id))
1403 goto free_nc_path;
1404
1405 /* Packet is consumed */
1406 return true;
1407
1408free_nc_path:
1409 batadv_nc_path_free_ref(nc_path);
1410out:
1411 /* Packet is not consumed */
1412 return false;
1413}
1414
1415/**
Martin Hundebøll612d2b42013-01-25 11:12:42 +01001416 * batadv_nc_skb_store_for_decoding - save a clone of the skb which can be used
1417 * when decoding coded packets
1418 * @bat_priv: the bat priv with all the soft interface information
1419 * @skb: data skb to store
1420 */
1421void batadv_nc_skb_store_for_decoding(struct batadv_priv *bat_priv,
1422 struct sk_buff *skb)
1423{
1424 struct batadv_unicast_packet *packet;
1425 struct batadv_nc_path *nc_path;
1426 struct ethhdr *ethhdr = (struct ethhdr *)skb_mac_header(skb);
1427 __be32 packet_id;
1428 u8 *payload;
1429
1430 /* Check if network coding is enabled */
1431 if (!atomic_read(&bat_priv->network_coding))
1432 goto out;
1433
1434 /* Check for supported packet type */
1435 payload = skb_network_header(skb);
1436 packet = (struct batadv_unicast_packet *)payload;
1437 if (packet->header.packet_type != BATADV_UNICAST)
1438 goto out;
1439
1440 /* Find existing nc_path or create a new */
1441 nc_path = batadv_nc_get_path(bat_priv,
1442 bat_priv->nc.decoding_hash,
1443 ethhdr->h_source,
1444 ethhdr->h_dest);
1445
1446 if (!nc_path)
1447 goto out;
1448
1449 /* Clone skb and adjust skb->data to point at batman header */
1450 skb = skb_clone(skb, GFP_ATOMIC);
1451 if (unlikely(!skb))
1452 goto free_nc_path;
1453
1454 if (unlikely(!pskb_may_pull(skb, ETH_HLEN)))
1455 goto free_skb;
1456
1457 if (unlikely(!skb_pull_rcsum(skb, ETH_HLEN)))
1458 goto free_skb;
1459
1460 /* Add skb to nc_path */
1461 packet_id = batadv_skb_crc32(skb, payload + sizeof(*packet));
1462 if (!batadv_nc_skb_add_to_path(skb, nc_path, NULL, packet_id))
1463 goto free_skb;
1464
1465 batadv_inc_counter(bat_priv, BATADV_CNT_NC_BUFFER);
1466 return;
1467
1468free_skb:
1469 kfree_skb(skb);
1470free_nc_path:
1471 batadv_nc_path_free_ref(nc_path);
1472out:
1473 return;
1474}
1475
1476/**
1477 * batadv_nc_skb_store_sniffed_unicast - check if a received unicast packet
1478 * should be saved in the decoding buffer and, if so, store it there
1479 * @bat_priv: the bat priv with all the soft interface information
1480 * @skb: unicast skb to store
1481 */
1482void batadv_nc_skb_store_sniffed_unicast(struct batadv_priv *bat_priv,
1483 struct sk_buff *skb)
1484{
1485 struct ethhdr *ethhdr = (struct ethhdr *)skb_mac_header(skb);
1486
David S. Miller6e0895c2013-04-22 20:32:51 -04001487 if (batadv_is_my_mac(bat_priv, ethhdr->h_dest))
Martin Hundebøll612d2b42013-01-25 11:12:42 +01001488 return;
1489
1490 /* Set data pointer to MAC header to mimic packets from our tx path */
1491 skb_push(skb, ETH_HLEN);
1492
1493 batadv_nc_skb_store_for_decoding(bat_priv, skb);
1494}
1495
1496/**
Martin Hundebøll2df52782013-01-25 11:12:43 +01001497 * batadv_nc_skb_decode_packet - decode given skb using the decode data stored
1498 * in nc_packet
David S. Miller6e0895c2013-04-22 20:32:51 -04001499 * @bat_priv: the bat priv with all the soft interface information
Martin Hundebøll2df52782013-01-25 11:12:43 +01001500 * @skb: unicast skb to decode
1501 * @nc_packet: decode data needed to decode the skb
1502 *
1503 * Returns pointer to decoded unicast packet if the packet was decoded or NULL
1504 * in case of an error.
1505 */
1506static struct batadv_unicast_packet *
David S. Miller6e0895c2013-04-22 20:32:51 -04001507batadv_nc_skb_decode_packet(struct batadv_priv *bat_priv, struct sk_buff *skb,
Martin Hundebøll2df52782013-01-25 11:12:43 +01001508 struct batadv_nc_packet *nc_packet)
1509{
1510 const int h_size = sizeof(struct batadv_unicast_packet);
1511 const int h_diff = sizeof(struct batadv_coded_packet) - h_size;
1512 struct batadv_unicast_packet *unicast_packet;
1513 struct batadv_coded_packet coded_packet_tmp;
1514 struct ethhdr *ethhdr, ethhdr_tmp;
1515 uint8_t *orig_dest, ttl, ttvn;
1516 unsigned int coding_len;
Marek Lindner7da19972013-05-07 19:25:02 +08001517 int err;
Martin Hundebøll2df52782013-01-25 11:12:43 +01001518
1519 /* Save headers temporarily */
1520 memcpy(&coded_packet_tmp, skb->data, sizeof(coded_packet_tmp));
1521 memcpy(&ethhdr_tmp, skb_mac_header(skb), sizeof(ethhdr_tmp));
1522
1523 if (skb_cow(skb, 0) < 0)
1524 return NULL;
1525
1526 if (unlikely(!skb_pull_rcsum(skb, h_diff)))
1527 return NULL;
1528
1529 /* Data points to batman header, so set mac header 14 bytes before
1530 * and network to data
1531 */
1532 skb_set_mac_header(skb, -ETH_HLEN);
1533 skb_reset_network_header(skb);
1534
1535 /* Reconstruct original mac header */
1536 ethhdr = (struct ethhdr *)skb_mac_header(skb);
1537 memcpy(ethhdr, &ethhdr_tmp, sizeof(*ethhdr));
1538
1539 /* Select the correct unicast header information based on the location
1540 * of our mac address in the coded_packet header
1541 */
David S. Miller6e0895c2013-04-22 20:32:51 -04001542 if (batadv_is_my_mac(bat_priv, coded_packet_tmp.second_dest)) {
Martin Hundebøll2df52782013-01-25 11:12:43 +01001543 /* If we are the second destination the packet was overheard,
1544 * so the Ethernet address must be copied to h_dest and
1545 * pkt_type changed from PACKET_OTHERHOST to PACKET_HOST
1546 */
1547 memcpy(ethhdr->h_dest, coded_packet_tmp.second_dest, ETH_ALEN);
1548 skb->pkt_type = PACKET_HOST;
1549
1550 orig_dest = coded_packet_tmp.second_orig_dest;
1551 ttl = coded_packet_tmp.second_ttl;
1552 ttvn = coded_packet_tmp.second_ttvn;
1553 } else {
1554 orig_dest = coded_packet_tmp.first_orig_dest;
1555 ttl = coded_packet_tmp.header.ttl;
1556 ttvn = coded_packet_tmp.first_ttvn;
1557 }
1558
1559 coding_len = ntohs(coded_packet_tmp.coded_len);
1560
1561 if (coding_len > skb->len)
1562 return NULL;
1563
1564 /* Here the magic is reversed:
1565 * extract the missing packet from the received coded packet
1566 */
1567 batadv_nc_memxor(skb->data + h_size,
1568 nc_packet->skb->data + h_size,
1569 coding_len);
1570
1571 /* Resize decoded skb if decoded with larger packet */
Marek Lindner7da19972013-05-07 19:25:02 +08001572 if (nc_packet->skb->len > coding_len + h_size) {
1573 err = pskb_trim_rcsum(skb, coding_len + h_size);
1574 if (err)
1575 return NULL;
1576 }
Martin Hundebøll2df52782013-01-25 11:12:43 +01001577
1578 /* Create decoded unicast packet */
1579 unicast_packet = (struct batadv_unicast_packet *)skb->data;
1580 unicast_packet->header.packet_type = BATADV_UNICAST;
1581 unicast_packet->header.version = BATADV_COMPAT_VERSION;
1582 unicast_packet->header.ttl = ttl;
1583 memcpy(unicast_packet->dest, orig_dest, ETH_ALEN);
1584 unicast_packet->ttvn = ttvn;
1585
1586 batadv_nc_packet_free(nc_packet);
1587 return unicast_packet;
1588}
1589
1590/**
1591 * batadv_nc_find_decoding_packet - search through buffered decoding data to
1592 * find the data needed to decode the coded packet
1593 * @bat_priv: the bat priv with all the soft interface information
1594 * @ethhdr: pointer to the ethernet header inside the coded packet
1595 * @coded: coded packet we try to find decode data for
1596 *
1597 * Returns pointer to nc packet if the needed data was found or NULL otherwise.
1598 */
1599static struct batadv_nc_packet *
1600batadv_nc_find_decoding_packet(struct batadv_priv *bat_priv,
1601 struct ethhdr *ethhdr,
1602 struct batadv_coded_packet *coded)
1603{
1604 struct batadv_hashtable *hash = bat_priv->nc.decoding_hash;
1605 struct batadv_nc_packet *tmp_nc_packet, *nc_packet = NULL;
1606 struct batadv_nc_path *nc_path, nc_path_key;
1607 uint8_t *dest, *source;
1608 __be32 packet_id;
1609 int index;
1610
1611 if (!hash)
1612 return NULL;
1613
1614 /* Select the correct packet id based on the location of our mac-addr */
1615 dest = ethhdr->h_source;
David S. Miller6e0895c2013-04-22 20:32:51 -04001616 if (!batadv_is_my_mac(bat_priv, coded->second_dest)) {
Martin Hundebøll2df52782013-01-25 11:12:43 +01001617 source = coded->second_source;
1618 packet_id = coded->second_crc;
1619 } else {
1620 source = coded->first_source;
1621 packet_id = coded->first_crc;
1622 }
1623
1624 batadv_nc_hash_key_gen(&nc_path_key, source, dest);
1625 index = batadv_nc_hash_choose(&nc_path_key, hash->size);
1626
1627 /* Search for matching coding path */
1628 rcu_read_lock();
1629 hlist_for_each_entry_rcu(nc_path, &hash->table[index], hash_entry) {
1630 /* Find matching nc_packet */
1631 spin_lock_bh(&nc_path->packet_list_lock);
1632 list_for_each_entry(tmp_nc_packet,
1633 &nc_path->packet_list, list) {
1634 if (packet_id == tmp_nc_packet->packet_id) {
1635 list_del(&tmp_nc_packet->list);
1636
1637 nc_packet = tmp_nc_packet;
1638 break;
1639 }
1640 }
1641 spin_unlock_bh(&nc_path->packet_list_lock);
1642
1643 if (nc_packet)
1644 break;
1645 }
1646 rcu_read_unlock();
1647
1648 if (!nc_packet)
1649 batadv_dbg(BATADV_DBG_NC, bat_priv,
1650 "No decoding packet found for %u\n", packet_id);
1651
1652 return nc_packet;
1653}
1654
1655/**
1656 * batadv_nc_recv_coded_packet - try to decode coded packet and enqueue the
1657 * resulting unicast packet
1658 * @skb: incoming coded packet
1659 * @recv_if: pointer to interface this packet was received on
1660 */
1661static int batadv_nc_recv_coded_packet(struct sk_buff *skb,
1662 struct batadv_hard_iface *recv_if)
1663{
1664 struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface);
1665 struct batadv_unicast_packet *unicast_packet;
1666 struct batadv_coded_packet *coded_packet;
1667 struct batadv_nc_packet *nc_packet;
1668 struct ethhdr *ethhdr;
1669 int hdr_size = sizeof(*coded_packet);
1670
1671 /* Check if network coding is enabled */
1672 if (!atomic_read(&bat_priv->network_coding))
1673 return NET_RX_DROP;
1674
1675 /* Make sure we can access (and remove) header */
1676 if (unlikely(!pskb_may_pull(skb, hdr_size)))
1677 return NET_RX_DROP;
1678
1679 coded_packet = (struct batadv_coded_packet *)skb->data;
1680 ethhdr = (struct ethhdr *)skb_mac_header(skb);
1681
1682 /* Verify frame is destined for us */
David S. Miller6e0895c2013-04-22 20:32:51 -04001683 if (!batadv_is_my_mac(bat_priv, ethhdr->h_dest) &&
1684 !batadv_is_my_mac(bat_priv, coded_packet->second_dest))
Martin Hundebøll2df52782013-01-25 11:12:43 +01001685 return NET_RX_DROP;
1686
1687 /* Update stat counter */
David S. Miller6e0895c2013-04-22 20:32:51 -04001688 if (batadv_is_my_mac(bat_priv, coded_packet->second_dest))
Martin Hundebøll2df52782013-01-25 11:12:43 +01001689 batadv_inc_counter(bat_priv, BATADV_CNT_NC_SNIFFED);
1690
1691 nc_packet = batadv_nc_find_decoding_packet(bat_priv, ethhdr,
1692 coded_packet);
1693 if (!nc_packet) {
1694 batadv_inc_counter(bat_priv, BATADV_CNT_NC_DECODE_FAILED);
1695 return NET_RX_DROP;
1696 }
1697
1698 /* Make skb's linear, because decoding accesses the entire buffer */
1699 if (skb_linearize(skb) < 0)
1700 goto free_nc_packet;
1701
1702 if (skb_linearize(nc_packet->skb) < 0)
1703 goto free_nc_packet;
1704
1705 /* Decode the packet */
David S. Miller6e0895c2013-04-22 20:32:51 -04001706 unicast_packet = batadv_nc_skb_decode_packet(bat_priv, skb, nc_packet);
Martin Hundebøll2df52782013-01-25 11:12:43 +01001707 if (!unicast_packet) {
1708 batadv_inc_counter(bat_priv, BATADV_CNT_NC_DECODE_FAILED);
1709 goto free_nc_packet;
1710 }
1711
1712 /* Mark packet as decoded to do correct recoding when forwarding */
1713 BATADV_SKB_CB(skb)->decoded = true;
1714 batadv_inc_counter(bat_priv, BATADV_CNT_NC_DECODE);
1715 batadv_add_counter(bat_priv, BATADV_CNT_NC_DECODE_BYTES,
1716 skb->len + ETH_HLEN);
1717 return batadv_recv_unicast_packet(skb, recv_if);
1718
1719free_nc_packet:
1720 batadv_nc_packet_free(nc_packet);
1721 return NET_RX_DROP;
1722}
1723
1724/**
Martin Hundebølld353d8d2013-01-25 11:12:38 +01001725 * batadv_nc_free - clean up network coding memory
1726 * @bat_priv: the bat priv with all the soft interface information
1727 */
1728void batadv_nc_free(struct batadv_priv *bat_priv)
1729{
Martin Hundebøll2df52782013-01-25 11:12:43 +01001730 batadv_recv_handler_unregister(BATADV_CODED);
Martin Hundebølld353d8d2013-01-25 11:12:38 +01001731 cancel_delayed_work_sync(&bat_priv->nc.work);
Martin Hundebøll612d2b42013-01-25 11:12:42 +01001732
Martin Hundebøll95332472013-01-25 11:12:40 +01001733 batadv_nc_purge_paths(bat_priv, bat_priv->nc.coding_hash, NULL);
1734 batadv_hash_destroy(bat_priv->nc.coding_hash);
Martin Hundebøll612d2b42013-01-25 11:12:42 +01001735 batadv_nc_purge_paths(bat_priv, bat_priv->nc.decoding_hash, NULL);
1736 batadv_hash_destroy(bat_priv->nc.decoding_hash);
Martin Hundebølld353d8d2013-01-25 11:12:38 +01001737}
Martin Hundebølld56b1702013-01-25 11:12:39 +01001738
1739/**
1740 * batadv_nc_nodes_seq_print_text - print the nc node information
1741 * @seq: seq file to print on
1742 * @offset: not used
1743 */
1744int batadv_nc_nodes_seq_print_text(struct seq_file *seq, void *offset)
1745{
1746 struct net_device *net_dev = (struct net_device *)seq->private;
1747 struct batadv_priv *bat_priv = netdev_priv(net_dev);
1748 struct batadv_hashtable *hash = bat_priv->orig_hash;
1749 struct batadv_hard_iface *primary_if;
1750 struct hlist_head *head;
1751 struct batadv_orig_node *orig_node;
1752 struct batadv_nc_node *nc_node;
1753 int i;
1754
1755 primary_if = batadv_seq_print_text_primary_if_get(seq);
1756 if (!primary_if)
1757 goto out;
1758
1759 /* Traverse list of originators */
1760 for (i = 0; i < hash->size; i++) {
1761 head = &hash->table[i];
1762
1763 /* For each orig_node in this bin */
1764 rcu_read_lock();
1765 hlist_for_each_entry_rcu(orig_node, head, hash_entry) {
1766 seq_printf(seq, "Node: %pM\n", orig_node->orig);
1767
Antonio Quartulli0c814652013-03-21 09:23:29 +01001768 seq_puts(seq, " Ingoing: ");
Martin Hundebølld56b1702013-01-25 11:12:39 +01001769 /* For each in_nc_node to this orig_node */
1770 list_for_each_entry_rcu(nc_node,
1771 &orig_node->in_coding_list,
1772 list)
1773 seq_printf(seq, "%pM ",
1774 nc_node->addr);
Antonio Quartulli0c814652013-03-21 09:23:29 +01001775 seq_puts(seq, "\n");
Martin Hundebølld56b1702013-01-25 11:12:39 +01001776
Antonio Quartulli0c814652013-03-21 09:23:29 +01001777 seq_puts(seq, " Outgoing: ");
Martin Hundebølld56b1702013-01-25 11:12:39 +01001778 /* For out_nc_node to this orig_node */
1779 list_for_each_entry_rcu(nc_node,
1780 &orig_node->out_coding_list,
1781 list)
1782 seq_printf(seq, "%pM ",
1783 nc_node->addr);
Antonio Quartulli0c814652013-03-21 09:23:29 +01001784 seq_puts(seq, "\n\n");
Martin Hundebølld56b1702013-01-25 11:12:39 +01001785 }
1786 rcu_read_unlock();
1787 }
1788
1789out:
1790 if (primary_if)
1791 batadv_hardif_free_ref(primary_if);
1792 return 0;
1793}
1794
1795/**
1796 * batadv_nc_init_debugfs - create nc folder and related files in debugfs
1797 * @bat_priv: the bat priv with all the soft interface information
1798 */
1799int batadv_nc_init_debugfs(struct batadv_priv *bat_priv)
1800{
1801 struct dentry *nc_dir, *file;
1802
1803 nc_dir = debugfs_create_dir("nc", bat_priv->debug_dir);
1804 if (!nc_dir)
1805 goto out;
1806
1807 file = debugfs_create_u8("min_tq", S_IRUGO | S_IWUSR, nc_dir,
1808 &bat_priv->nc.min_tq);
1809 if (!file)
1810 goto out;
1811
Martin Hundebøll95332472013-01-25 11:12:40 +01001812 file = debugfs_create_u32("max_fwd_delay", S_IRUGO | S_IWUSR, nc_dir,
1813 &bat_priv->nc.max_fwd_delay);
1814 if (!file)
1815 goto out;
1816
Martin Hundebøll612d2b42013-01-25 11:12:42 +01001817 file = debugfs_create_u32("max_buffer_time", S_IRUGO | S_IWUSR, nc_dir,
1818 &bat_priv->nc.max_buffer_time);
1819 if (!file)
1820 goto out;
1821
Martin Hundebølld56b1702013-01-25 11:12:39 +01001822 return 0;
1823
1824out:
1825 return -ENOMEM;
1826}