batman-adv: network coding - code and transmit packets if possible
[deliverable/linux.git] / net / batman-adv / network-coding.c
CommitLineData
d353d8d4
MH
1/* 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
d56b1705
MH
20#include <linux/debugfs.h>
21
d353d8d4 22#include "main.h"
95332477 23#include "hash.h"
d353d8d4 24#include "network-coding.h"
95332477 25#include "send.h"
d56b1705
MH
26#include "originator.h"
27#include "hard-interface.h"
d353d8d4 28
95332477
MH
29static struct lock_class_key batadv_nc_coding_hash_lock_class_key;
30
d353d8d4
MH
31static void batadv_nc_worker(struct work_struct *work);
32
33/**
34 * batadv_nc_start_timer - initialise the nc periodic worker
35 * @bat_priv: the bat priv with all the soft interface information
36 */
37static void batadv_nc_start_timer(struct batadv_priv *bat_priv)
38{
39 queue_delayed_work(batadv_event_workqueue, &bat_priv->nc.work,
40 msecs_to_jiffies(10));
41}
42
43/**
44 * batadv_nc_init - initialise coding hash table and start house keeping
45 * @bat_priv: the bat priv with all the soft interface information
46 */
47int batadv_nc_init(struct batadv_priv *bat_priv)
48{
95332477
MH
49 bat_priv->nc.timestamp_fwd_flush = jiffies;
50
51 if (bat_priv->nc.coding_hash)
52 return 0;
53
54 bat_priv->nc.coding_hash = batadv_hash_new(128);
55 if (!bat_priv->nc.coding_hash)
56 goto err;
57
58 batadv_hash_set_lock_class(bat_priv->nc.coding_hash,
59 &batadv_nc_coding_hash_lock_class_key);
60
d353d8d4
MH
61 INIT_DELAYED_WORK(&bat_priv->nc.work, batadv_nc_worker);
62 batadv_nc_start_timer(bat_priv);
63
64 return 0;
95332477
MH
65
66err:
67 return -ENOMEM;
d353d8d4
MH
68}
69
70/**
71 * batadv_nc_init_bat_priv - initialise the nc specific bat_priv variables
72 * @bat_priv: the bat priv with all the soft interface information
73 */
74void batadv_nc_init_bat_priv(struct batadv_priv *bat_priv)
75{
76 atomic_set(&bat_priv->network_coding, 1);
d56b1705 77 bat_priv->nc.min_tq = 200;
95332477 78 bat_priv->nc.max_fwd_delay = 10;
d56b1705
MH
79}
80
81/**
82 * batadv_nc_init_orig - initialise the nc fields of an orig_node
83 * @orig_node: the orig_node which is going to be initialised
84 */
85void batadv_nc_init_orig(struct batadv_orig_node *orig_node)
86{
87 INIT_LIST_HEAD(&orig_node->in_coding_list);
88 INIT_LIST_HEAD(&orig_node->out_coding_list);
89 spin_lock_init(&orig_node->in_coding_list_lock);
90 spin_lock_init(&orig_node->out_coding_list_lock);
91}
92
93/**
94 * batadv_nc_node_free_rcu - rcu callback to free an nc node and remove
95 * its refcount on the orig_node
96 * @rcu: rcu pointer of the nc node
97 */
98static void batadv_nc_node_free_rcu(struct rcu_head *rcu)
99{
100 struct batadv_nc_node *nc_node;
101
102 nc_node = container_of(rcu, struct batadv_nc_node, rcu);
103 batadv_orig_node_free_ref(nc_node->orig_node);
104 kfree(nc_node);
105}
106
107/**
108 * batadv_nc_node_free_ref - decrements the nc node refcounter and possibly
109 * frees it
110 * @nc_node: the nc node to free
111 */
112static void batadv_nc_node_free_ref(struct batadv_nc_node *nc_node)
113{
114 if (atomic_dec_and_test(&nc_node->refcount))
115 call_rcu(&nc_node->rcu, batadv_nc_node_free_rcu);
116}
117
95332477
MH
118/**
119 * batadv_nc_path_free_ref - decrements the nc path refcounter and possibly
120 * frees it
121 * @nc_path: the nc node to free
122 */
123static void batadv_nc_path_free_ref(struct batadv_nc_path *nc_path)
124{
125 if (atomic_dec_and_test(&nc_path->refcount))
126 kfree_rcu(nc_path, rcu);
127}
128
129/**
130 * batadv_nc_packet_free - frees nc packet
131 * @nc_packet: the nc packet to free
132 */
133static void batadv_nc_packet_free(struct batadv_nc_packet *nc_packet)
134{
135 if (nc_packet->skb)
136 kfree_skb(nc_packet->skb);
137
138 batadv_nc_path_free_ref(nc_packet->nc_path);
139 kfree(nc_packet);
140}
141
d56b1705
MH
142/**
143 * batadv_nc_to_purge_nc_node - checks whether an nc node has to be purged
144 * @bat_priv: the bat priv with all the soft interface information
145 * @nc_node: the nc node to check
146 *
147 * Returns true if the entry has to be purged now, false otherwise
148 */
149static bool batadv_nc_to_purge_nc_node(struct batadv_priv *bat_priv,
150 struct batadv_nc_node *nc_node)
151{
152 if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE)
153 return true;
154
155 return batadv_has_timed_out(nc_node->last_seen, BATADV_NC_NODE_TIMEOUT);
156}
157
95332477
MH
158/**
159 * batadv_nc_to_purge_nc_path_coding - checks whether an nc path has timed out
160 * @bat_priv: the bat priv with all the soft interface information
161 * @nc_path: the nc path to check
162 *
163 * Returns true if the entry has to be purged now, false otherwise
164 */
165static bool batadv_nc_to_purge_nc_path_coding(struct batadv_priv *bat_priv,
166 struct batadv_nc_path *nc_path)
167{
168 if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE)
169 return true;
170
171 /* purge the path when no packets has been added for 10 times the
172 * max_fwd_delay time
173 */
174 return batadv_has_timed_out(nc_path->last_valid,
175 bat_priv->nc.max_fwd_delay * 10);
176}
177
d56b1705
MH
178/**
179 * batadv_nc_purge_orig_nc_nodes - go through list of nc nodes and purge stale
180 * entries
181 * @bat_priv: the bat priv with all the soft interface information
182 * @list: list of nc nodes
183 * @lock: nc node list lock
184 * @to_purge: function in charge to decide whether an entry has to be purged or
185 * not. This function takes the nc node as argument and has to return
186 * a boolean value: true if the entry has to be deleted, false
187 * otherwise
188 */
189static void
190batadv_nc_purge_orig_nc_nodes(struct batadv_priv *bat_priv,
191 struct list_head *list,
192 spinlock_t *lock,
193 bool (*to_purge)(struct batadv_priv *,
194 struct batadv_nc_node *))
195{
196 struct batadv_nc_node *nc_node, *nc_node_tmp;
197
198 /* For each nc_node in list */
199 spin_lock_bh(lock);
200 list_for_each_entry_safe(nc_node, nc_node_tmp, list, list) {
201 /* if an helper function has been passed as parameter,
202 * ask it if the entry has to be purged or not
203 */
204 if (to_purge && !to_purge(bat_priv, nc_node))
205 continue;
206
207 batadv_dbg(BATADV_DBG_NC, bat_priv,
208 "Removing nc_node %pM -> %pM\n",
209 nc_node->addr, nc_node->orig_node->orig);
210 list_del_rcu(&nc_node->list);
211 batadv_nc_node_free_ref(nc_node);
212 }
213 spin_unlock_bh(lock);
214}
215
216/**
217 * batadv_nc_purge_orig - purges all nc node data attached of the given
218 * originator
219 * @bat_priv: the bat priv with all the soft interface information
220 * @orig_node: orig_node with the nc node entries to be purged
221 * @to_purge: function in charge to decide whether an entry has to be purged or
222 * not. This function takes the nc node as argument and has to return
223 * a boolean value: true is the entry has to be deleted, false
224 * otherwise
225 */
226void batadv_nc_purge_orig(struct batadv_priv *bat_priv,
227 struct batadv_orig_node *orig_node,
228 bool (*to_purge)(struct batadv_priv *,
229 struct batadv_nc_node *))
230{
231 /* Check ingoing nc_node's of this orig_node */
232 batadv_nc_purge_orig_nc_nodes(bat_priv, &orig_node->in_coding_list,
233 &orig_node->in_coding_list_lock,
234 to_purge);
235
236 /* Check outgoing nc_node's of this orig_node */
237 batadv_nc_purge_orig_nc_nodes(bat_priv, &orig_node->out_coding_list,
238 &orig_node->out_coding_list_lock,
239 to_purge);
240}
241
242/**
243 * batadv_nc_purge_orig_hash - traverse entire originator hash to check if they
244 * have timed out nc nodes
245 * @bat_priv: the bat priv with all the soft interface information
246 */
247static void batadv_nc_purge_orig_hash(struct batadv_priv *bat_priv)
248{
249 struct batadv_hashtable *hash = bat_priv->orig_hash;
250 struct hlist_head *head;
251 struct batadv_orig_node *orig_node;
252 uint32_t i;
253
254 if (!hash)
255 return;
256
257 /* For each orig_node */
258 for (i = 0; i < hash->size; i++) {
259 head = &hash->table[i];
260
261 rcu_read_lock();
262 hlist_for_each_entry_rcu(orig_node, head, hash_entry)
263 batadv_nc_purge_orig(bat_priv, orig_node,
264 batadv_nc_to_purge_nc_node);
265 rcu_read_unlock();
266 }
d353d8d4
MH
267}
268
95332477
MH
269/**
270 * batadv_nc_purge_paths - traverse all nc paths part of the hash and remove
271 * unused ones
272 * @bat_priv: the bat priv with all the soft interface information
273 * @hash: hash table containing the nc paths to check
274 * @to_purge: function in charge to decide whether an entry has to be purged or
275 * not. This function takes the nc node as argument and has to return
276 * a boolean value: true is the entry has to be deleted, false
277 * otherwise
278 */
279static void batadv_nc_purge_paths(struct batadv_priv *bat_priv,
280 struct batadv_hashtable *hash,
281 bool (*to_purge)(struct batadv_priv *,
282 struct batadv_nc_path *))
283{
284 struct hlist_head *head;
285 struct hlist_node *node_tmp;
286 struct batadv_nc_path *nc_path;
287 spinlock_t *lock; /* Protects lists in hash */
288 uint32_t i;
289
290 for (i = 0; i < hash->size; i++) {
291 head = &hash->table[i];
292 lock = &hash->list_locks[i];
293
294 /* For each nc_path in this bin */
295 spin_lock_bh(lock);
296 hlist_for_each_entry_safe(nc_path, node_tmp, head, hash_entry) {
297 /* if an helper function has been passed as parameter,
298 * ask it if the entry has to be purged or not
299 */
300 if (to_purge && !to_purge(bat_priv, nc_path))
301 continue;
302
303 /* purging an non-empty nc_path should never happen, but
304 * is observed under high CPU load. Delay the purging
305 * until next iteration to allow the packet_list to be
306 * emptied first.
307 */
308 if (!unlikely(list_empty(&nc_path->packet_list))) {
309 net_ratelimited_function(printk,
310 KERN_WARNING
311 "Skipping free of non-empty nc_path (%pM -> %pM)!\n",
312 nc_path->prev_hop,
313 nc_path->next_hop);
314 continue;
315 }
316
317 /* nc_path is unused, so remove it */
318 batadv_dbg(BATADV_DBG_NC, bat_priv,
319 "Remove nc_path %pM -> %pM\n",
320 nc_path->prev_hop, nc_path->next_hop);
321 hlist_del_rcu(&nc_path->hash_entry);
322 batadv_nc_path_free_ref(nc_path);
323 }
324 spin_unlock_bh(lock);
325 }
326}
327
328/**
329 * batadv_nc_hash_key_gen - computes the nc_path hash key
330 * @key: buffer to hold the final hash key
331 * @src: source ethernet mac address going into the hash key
332 * @dst: destination ethernet mac address going into the hash key
333 */
334static void batadv_nc_hash_key_gen(struct batadv_nc_path *key, const char *src,
335 const char *dst)
336{
337 memcpy(key->prev_hop, src, sizeof(key->prev_hop));
338 memcpy(key->next_hop, dst, sizeof(key->next_hop));
339}
340
341/**
342 * batadv_nc_hash_choose - compute the hash value for an nc path
343 * @data: data to hash
344 * @size: size of the hash table
345 *
346 * Returns the selected index in the hash table for the given data.
347 */
348static uint32_t batadv_nc_hash_choose(const void *data, uint32_t size)
349{
350 const struct batadv_nc_path *nc_path = data;
351 uint32_t hash = 0;
352
353 hash = batadv_hash_bytes(hash, &nc_path->prev_hop,
354 sizeof(nc_path->prev_hop));
355 hash = batadv_hash_bytes(hash, &nc_path->next_hop,
356 sizeof(nc_path->next_hop));
357
358 hash += (hash << 3);
359 hash ^= (hash >> 11);
360 hash += (hash << 15);
361
362 return hash % size;
363}
364
365/**
366 * batadv_nc_hash_compare - comparing function used in the network coding hash
367 * tables
368 * @node: node in the local table
369 * @data2: second object to compare the node to
370 *
371 * Returns 1 if the two entry are the same, 0 otherwise
372 */
373static int batadv_nc_hash_compare(const struct hlist_node *node,
374 const void *data2)
375{
376 const struct batadv_nc_path *nc_path1, *nc_path2;
377
378 nc_path1 = container_of(node, struct batadv_nc_path, hash_entry);
379 nc_path2 = data2;
380
381 /* Return 1 if the two keys are identical */
382 if (memcmp(nc_path1->prev_hop, nc_path2->prev_hop,
383 sizeof(nc_path1->prev_hop)) != 0)
384 return 0;
385
386 if (memcmp(nc_path1->next_hop, nc_path2->next_hop,
387 sizeof(nc_path1->next_hop)) != 0)
388 return 0;
389
390 return 1;
391}
392
393/**
394 * batadv_nc_hash_find - search for an existing nc path and return it
395 * @hash: hash table containing the nc path
396 * @data: search key
397 *
398 * Returns the nc_path if found, NULL otherwise.
399 */
400static struct batadv_nc_path *
401batadv_nc_hash_find(struct batadv_hashtable *hash,
402 void *data)
403{
404 struct hlist_head *head;
405 struct batadv_nc_path *nc_path, *nc_path_tmp = NULL;
406 int index;
407
408 if (!hash)
409 return NULL;
410
411 index = batadv_nc_hash_choose(data, hash->size);
412 head = &hash->table[index];
413
414 rcu_read_lock();
415 hlist_for_each_entry_rcu(nc_path, head, hash_entry) {
416 if (!batadv_nc_hash_compare(&nc_path->hash_entry, data))
417 continue;
418
419 if (!atomic_inc_not_zero(&nc_path->refcount))
420 continue;
421
422 nc_path_tmp = nc_path;
423 break;
424 }
425 rcu_read_unlock();
426
427 return nc_path_tmp;
428}
429
430/**
431 * batadv_nc_send_packet - send non-coded packet and free nc_packet struct
432 * @nc_packet: the nc packet to send
433 */
434static void batadv_nc_send_packet(struct batadv_nc_packet *nc_packet)
435{
436 batadv_send_skb_packet(nc_packet->skb,
437 nc_packet->neigh_node->if_incoming,
438 nc_packet->nc_path->next_hop);
439 nc_packet->skb = NULL;
440 batadv_nc_packet_free(nc_packet);
441}
442
443/**
444 * batadv_nc_fwd_flush - Checks the timestamp of the given nc packet.
445 * @bat_priv: the bat priv with all the soft interface information
446 * @nc_path: the nc path the packet belongs to
447 * @nc_packet: the nc packet to be checked
448 *
449 * Checks whether the given nc packet has hit its forward timeout. If so, the
450 * packet is no longer delayed, immediately sent and the entry deleted from the
451 * queue. Has to be called with the appropriate locks.
452 *
453 * Returns false as soon as the entry in the fifo queue has not been timed out
454 * yet and true otherwise.
455 */
456static bool batadv_nc_fwd_flush(struct batadv_priv *bat_priv,
457 struct batadv_nc_path *nc_path,
458 struct batadv_nc_packet *nc_packet)
459{
460 unsigned long timeout = bat_priv->nc.max_fwd_delay;
461
462 /* Packets are added to tail, so the remaining packets did not time
463 * out and we can stop processing the current queue
464 */
465 if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_ACTIVE &&
466 !batadv_has_timed_out(nc_packet->timestamp, timeout))
467 return false;
468
469 /* Send packet */
470 batadv_inc_counter(bat_priv, BATADV_CNT_FORWARD);
471 batadv_add_counter(bat_priv, BATADV_CNT_FORWARD_BYTES,
472 nc_packet->skb->len + ETH_HLEN);
473 list_del(&nc_packet->list);
474 batadv_nc_send_packet(nc_packet);
475
476 return true;
477}
478
479/**
480 * batadv_nc_process_nc_paths - traverse given nc packet pool and free timed out
481 * nc packets
482 * @bat_priv: the bat priv with all the soft interface information
483 * @hash: to be processed hash table
484 * @process_fn: Function called to process given nc packet. Should return true
485 * to encourage this function to proceed with the next packet.
486 * Otherwise the rest of the current queue is skipped.
487 */
488static void
489batadv_nc_process_nc_paths(struct batadv_priv *bat_priv,
490 struct batadv_hashtable *hash,
491 bool (*process_fn)(struct batadv_priv *,
492 struct batadv_nc_path *,
493 struct batadv_nc_packet *))
494{
495 struct hlist_head *head;
496 struct batadv_nc_packet *nc_packet, *nc_packet_tmp;
497 struct batadv_nc_path *nc_path;
498 bool ret;
499 int i;
500
501 if (!hash)
502 return;
503
504 /* Loop hash table bins */
505 for (i = 0; i < hash->size; i++) {
506 head = &hash->table[i];
507
508 /* Loop coding paths */
509 rcu_read_lock();
510 hlist_for_each_entry_rcu(nc_path, head, hash_entry) {
511 /* Loop packets */
512 spin_lock_bh(&nc_path->packet_list_lock);
513 list_for_each_entry_safe(nc_packet, nc_packet_tmp,
514 &nc_path->packet_list, list) {
515 ret = process_fn(bat_priv, nc_path, nc_packet);
516 if (!ret)
517 break;
518 }
519 spin_unlock_bh(&nc_path->packet_list_lock);
520 }
521 rcu_read_unlock();
522 }
523}
524
d353d8d4
MH
525/**
526 * batadv_nc_worker - periodic task for house keeping related to network coding
527 * @work: kernel work struct
528 */
529static void batadv_nc_worker(struct work_struct *work)
530{
531 struct delayed_work *delayed_work;
532 struct batadv_priv_nc *priv_nc;
533 struct batadv_priv *bat_priv;
95332477 534 unsigned long timeout;
d353d8d4
MH
535
536 delayed_work = container_of(work, struct delayed_work, work);
537 priv_nc = container_of(delayed_work, struct batadv_priv_nc, work);
538 bat_priv = container_of(priv_nc, struct batadv_priv, nc);
539
d56b1705 540 batadv_nc_purge_orig_hash(bat_priv);
95332477
MH
541 batadv_nc_purge_paths(bat_priv, bat_priv->nc.coding_hash,
542 batadv_nc_to_purge_nc_path_coding);
543
544 timeout = bat_priv->nc.max_fwd_delay;
545
546 if (batadv_has_timed_out(bat_priv->nc.timestamp_fwd_flush, timeout)) {
547 batadv_nc_process_nc_paths(bat_priv, bat_priv->nc.coding_hash,
548 batadv_nc_fwd_flush);
549 bat_priv->nc.timestamp_fwd_flush = jiffies;
550 }
d56b1705 551
d353d8d4
MH
552 /* Schedule a new check */
553 batadv_nc_start_timer(bat_priv);
554}
555
d56b1705
MH
556/**
557 * batadv_can_nc_with_orig - checks whether the given orig node is suitable for
558 * coding or not
559 * @bat_priv: the bat priv with all the soft interface information
560 * @orig_node: neighboring orig node which may be used as nc candidate
561 * @ogm_packet: incoming ogm packet also used for the checks
562 *
563 * Returns true if:
564 * 1) The OGM must have the most recent sequence number.
565 * 2) The TTL must be decremented by one and only one.
566 * 3) The OGM must be received from the first hop from orig_node.
567 * 4) The TQ value of the OGM must be above bat_priv->nc.min_tq.
568 */
569static bool batadv_can_nc_with_orig(struct batadv_priv *bat_priv,
570 struct batadv_orig_node *orig_node,
571 struct batadv_ogm_packet *ogm_packet)
572{
573 if (orig_node->last_real_seqno != ogm_packet->seqno)
574 return false;
575 if (orig_node->last_ttl != ogm_packet->header.ttl + 1)
576 return false;
577 if (!batadv_compare_eth(ogm_packet->orig, ogm_packet->prev_sender))
578 return false;
579 if (ogm_packet->tq < bat_priv->nc.min_tq)
580 return false;
581
582 return true;
583}
584
585/**
586 * batadv_nc_find_nc_node - search for an existing nc node and return it
587 * @orig_node: orig node originating the ogm packet
588 * @orig_neigh_node: neighboring orig node from which we received the ogm packet
589 * (can be equal to orig_node)
590 * @in_coding: traverse incoming or outgoing network coding list
591 *
592 * Returns the nc_node if found, NULL otherwise.
593 */
594static struct batadv_nc_node
595*batadv_nc_find_nc_node(struct batadv_orig_node *orig_node,
596 struct batadv_orig_node *orig_neigh_node,
597 bool in_coding)
598{
599 struct batadv_nc_node *nc_node, *nc_node_out = NULL;
600 struct list_head *list;
601
602 if (in_coding)
603 list = &orig_neigh_node->in_coding_list;
604 else
605 list = &orig_neigh_node->out_coding_list;
606
607 /* Traverse list of nc_nodes to orig_node */
608 rcu_read_lock();
609 list_for_each_entry_rcu(nc_node, list, list) {
610 if (!batadv_compare_eth(nc_node->addr, orig_node->orig))
611 continue;
612
613 if (!atomic_inc_not_zero(&nc_node->refcount))
614 continue;
615
616 /* Found a match */
617 nc_node_out = nc_node;
618 break;
619 }
620 rcu_read_unlock();
621
622 return nc_node_out;
623}
624
625/**
626 * batadv_nc_get_nc_node - retrieves an nc node or creates the entry if it was
627 * not found
628 * @bat_priv: the bat priv with all the soft interface information
629 * @orig_node: orig node originating the ogm packet
630 * @orig_neigh_node: neighboring orig node from which we received the ogm packet
631 * (can be equal to orig_node)
632 * @in_coding: traverse incoming or outgoing network coding list
633 *
634 * Returns the nc_node if found or created, NULL in case of an error.
635 */
636static struct batadv_nc_node
637*batadv_nc_get_nc_node(struct batadv_priv *bat_priv,
638 struct batadv_orig_node *orig_node,
639 struct batadv_orig_node *orig_neigh_node,
640 bool in_coding)
641{
642 struct batadv_nc_node *nc_node;
643 spinlock_t *lock; /* Used to lock list selected by "int in_coding" */
644 struct list_head *list;
645
646 /* Check if nc_node is already added */
647 nc_node = batadv_nc_find_nc_node(orig_node, orig_neigh_node, in_coding);
648
649 /* Node found */
650 if (nc_node)
651 return nc_node;
652
653 nc_node = kzalloc(sizeof(*nc_node), GFP_ATOMIC);
654 if (!nc_node)
655 return NULL;
656
657 if (!atomic_inc_not_zero(&orig_neigh_node->refcount))
658 goto free;
659
660 /* Initialize nc_node */
661 INIT_LIST_HEAD(&nc_node->list);
662 memcpy(nc_node->addr, orig_node->orig, ETH_ALEN);
663 nc_node->orig_node = orig_neigh_node;
664 atomic_set(&nc_node->refcount, 2);
665
666 /* Select ingoing or outgoing coding node */
667 if (in_coding) {
668 lock = &orig_neigh_node->in_coding_list_lock;
669 list = &orig_neigh_node->in_coding_list;
670 } else {
671 lock = &orig_neigh_node->out_coding_list_lock;
672 list = &orig_neigh_node->out_coding_list;
673 }
674
675 batadv_dbg(BATADV_DBG_NC, bat_priv, "Adding nc_node %pM -> %pM\n",
676 nc_node->addr, nc_node->orig_node->orig);
677
678 /* Add nc_node to orig_node */
679 spin_lock_bh(lock);
680 list_add_tail_rcu(&nc_node->list, list);
681 spin_unlock_bh(lock);
682
683 return nc_node;
684
685free:
686 kfree(nc_node);
687 return NULL;
688}
689
690/**
691 * batadv_nc_update_nc_node - updates stored incoming and outgoing nc node structs
692 * (best called on incoming OGMs)
693 * @bat_priv: the bat priv with all the soft interface information
694 * @orig_node: orig node originating the ogm packet
695 * @orig_neigh_node: neighboring orig node from which we received the ogm packet
696 * (can be equal to orig_node)
697 * @ogm_packet: incoming ogm packet
698 * @is_single_hop_neigh: orig_node is a single hop neighbor
699 */
700void batadv_nc_update_nc_node(struct batadv_priv *bat_priv,
701 struct batadv_orig_node *orig_node,
702 struct batadv_orig_node *orig_neigh_node,
703 struct batadv_ogm_packet *ogm_packet,
704 int is_single_hop_neigh)
705{
706 struct batadv_nc_node *in_nc_node = NULL, *out_nc_node = NULL;
707
708 /* Check if network coding is enabled */
709 if (!atomic_read(&bat_priv->network_coding))
710 goto out;
711
712 /* accept ogms from 'good' neighbors and single hop neighbors */
713 if (!batadv_can_nc_with_orig(bat_priv, orig_node, ogm_packet) &&
714 !is_single_hop_neigh)
715 goto out;
716
717 /* Add orig_node as in_nc_node on hop */
718 in_nc_node = batadv_nc_get_nc_node(bat_priv, orig_node,
719 orig_neigh_node, true);
720 if (!in_nc_node)
721 goto out;
722
723 in_nc_node->last_seen = jiffies;
724
725 /* Add hop as out_nc_node on orig_node */
726 out_nc_node = batadv_nc_get_nc_node(bat_priv, orig_neigh_node,
727 orig_node, false);
728 if (!out_nc_node)
729 goto out;
730
731 out_nc_node->last_seen = jiffies;
732
733out:
734 if (in_nc_node)
735 batadv_nc_node_free_ref(in_nc_node);
736 if (out_nc_node)
737 batadv_nc_node_free_ref(out_nc_node);
738}
739
95332477
MH
740/**
741 * batadv_nc_get_path - get existing nc_path or allocate a new one
742 * @bat_priv: the bat priv with all the soft interface information
743 * @hash: hash table containing the nc path
744 * @src: ethernet source address - first half of the nc path search key
745 * @dst: ethernet destination address - second half of the nc path search key
746 *
747 * Returns pointer to nc_path if the path was found or created, returns NULL
748 * on error.
749 */
750static struct batadv_nc_path *batadv_nc_get_path(struct batadv_priv *bat_priv,
751 struct batadv_hashtable *hash,
752 uint8_t *src,
753 uint8_t *dst)
754{
755 int hash_added;
756 struct batadv_nc_path *nc_path, nc_path_key;
757
758 batadv_nc_hash_key_gen(&nc_path_key, src, dst);
759
760 /* Search for existing nc_path */
761 nc_path = batadv_nc_hash_find(hash, (void *)&nc_path_key);
762
763 if (nc_path) {
764 /* Set timestamp to delay removal of nc_path */
765 nc_path->last_valid = jiffies;
766 return nc_path;
767 }
768
769 /* No existing nc_path was found; create a new */
770 nc_path = kzalloc(sizeof(*nc_path), GFP_ATOMIC);
771
772 if (!nc_path)
773 return NULL;
774
775 /* Initialize nc_path */
776 INIT_LIST_HEAD(&nc_path->packet_list);
777 spin_lock_init(&nc_path->packet_list_lock);
778 atomic_set(&nc_path->refcount, 2);
779 nc_path->last_valid = jiffies;
780 memcpy(nc_path->next_hop, dst, ETH_ALEN);
781 memcpy(nc_path->prev_hop, src, ETH_ALEN);
782
783 batadv_dbg(BATADV_DBG_NC, bat_priv, "Adding nc_path %pM -> %pM\n",
784 nc_path->prev_hop,
785 nc_path->next_hop);
786
787 /* Add nc_path to hash table */
788 hash_added = batadv_hash_add(hash, batadv_nc_hash_compare,
789 batadv_nc_hash_choose, &nc_path_key,
790 &nc_path->hash_entry);
791
792 if (hash_added < 0) {
793 kfree(nc_path);
794 return NULL;
795 }
796
797 return nc_path;
798}
799
3c12de9a
MH
800/**
801 * batadv_nc_random_weight_tq - scale the receivers TQ-value to avoid unfair
802 * selection of a receiver with slightly lower TQ than the other
803 * @tq: to be weighted tq value
804 */
805static uint8_t batadv_nc_random_weight_tq(uint8_t tq)
806{
807 uint8_t rand_val, rand_tq;
808
809 get_random_bytes(&rand_val, sizeof(rand_val));
810
811 /* randomize the estimated packet loss (max TQ - estimated TQ) */
812 rand_tq = rand_val * (BATADV_TQ_MAX_VALUE - tq);
813
814 /* normalize the randomized packet loss */
815 rand_tq /= BATADV_TQ_MAX_VALUE;
816
817 /* convert to (randomized) estimated tq again */
818 return BATADV_TQ_MAX_VALUE - rand_tq;
819}
820
821/**
822 * batadv_nc_memxor - XOR destination with source
823 * @dst: byte array to XOR into
824 * @src: byte array to XOR from
825 * @len: length of destination array
826 */
827static void batadv_nc_memxor(char *dst, const char *src, unsigned int len)
828{
829 unsigned int i;
830
831 for (i = 0; i < len; ++i)
832 dst[i] ^= src[i];
833}
834
835/**
836 * batadv_nc_code_packets - code a received unicast_packet with an nc packet
837 * into a coded_packet and send it
838 * @bat_priv: the bat priv with all the soft interface information
839 * @skb: data skb to forward
840 * @ethhdr: pointer to the ethernet header inside the skb
841 * @nc_packet: structure containing the packet to the skb can be coded with
842 * @neigh_node: next hop to forward packet to
843 *
844 * Returns true if both packets are consumed, false otherwise.
845 */
846static bool batadv_nc_code_packets(struct batadv_priv *bat_priv,
847 struct sk_buff *skb,
848 struct ethhdr *ethhdr,
849 struct batadv_nc_packet *nc_packet,
850 struct batadv_neigh_node *neigh_node)
851{
852 uint8_t tq_weighted_neigh, tq_weighted_coding;
853 struct sk_buff *skb_dest, *skb_src;
854 struct batadv_unicast_packet *packet1;
855 struct batadv_unicast_packet *packet2;
856 struct batadv_coded_packet *coded_packet;
857 struct batadv_neigh_node *neigh_tmp, *router_neigh;
858 struct batadv_neigh_node *router_coding = NULL;
859 uint8_t *first_source, *first_dest, *second_source, *second_dest;
860 __be32 packet_id1, packet_id2;
861 size_t count;
862 bool res = false;
863 int coding_len;
864 int unicast_size = sizeof(*packet1);
865 int coded_size = sizeof(*coded_packet);
866 int header_add = coded_size - unicast_size;
867
868 router_neigh = batadv_orig_node_get_router(neigh_node->orig_node);
869 if (!router_neigh)
870 goto out;
871
872 neigh_tmp = nc_packet->neigh_node;
873 router_coding = batadv_orig_node_get_router(neigh_tmp->orig_node);
874 if (!router_coding)
875 goto out;
876
877 tq_weighted_neigh = batadv_nc_random_weight_tq(router_neigh->tq_avg);
878 tq_weighted_coding = batadv_nc_random_weight_tq(router_coding->tq_avg);
879
880 /* Select one destination for the MAC-header dst-field based on
881 * weighted TQ-values.
882 */
883 if (tq_weighted_neigh >= tq_weighted_coding) {
884 /* Destination from nc_packet is selected for MAC-header */
885 first_dest = nc_packet->nc_path->next_hop;
886 first_source = nc_packet->nc_path->prev_hop;
887 second_dest = neigh_node->addr;
888 second_source = ethhdr->h_source;
889 packet1 = (struct batadv_unicast_packet *)nc_packet->skb->data;
890 packet2 = (struct batadv_unicast_packet *)skb->data;
891 packet_id1 = nc_packet->packet_id;
892 packet_id2 = batadv_skb_crc32(skb,
893 skb->data + sizeof(*packet2));
894 } else {
895 /* Destination for skb is selected for MAC-header */
896 first_dest = neigh_node->addr;
897 first_source = ethhdr->h_source;
898 second_dest = nc_packet->nc_path->next_hop;
899 second_source = nc_packet->nc_path->prev_hop;
900 packet1 = (struct batadv_unicast_packet *)skb->data;
901 packet2 = (struct batadv_unicast_packet *)nc_packet->skb->data;
902 packet_id1 = batadv_skb_crc32(skb,
903 skb->data + sizeof(*packet1));
904 packet_id2 = nc_packet->packet_id;
905 }
906
907 /* Instead of zero padding the smallest data buffer, we
908 * code into the largest.
909 */
910 if (skb->len <= nc_packet->skb->len) {
911 skb_dest = nc_packet->skb;
912 skb_src = skb;
913 } else {
914 skb_dest = skb;
915 skb_src = nc_packet->skb;
916 }
917
918 /* coding_len is used when decoding the packet shorter packet */
919 coding_len = skb_src->len - unicast_size;
920
921 if (skb_linearize(skb_dest) < 0 || skb_linearize(skb_src) < 0)
922 goto out;
923
924 skb_push(skb_dest, header_add);
925
926 coded_packet = (struct batadv_coded_packet *)skb_dest->data;
927 skb_reset_mac_header(skb_dest);
928
929 coded_packet->header.packet_type = BATADV_CODED;
930 coded_packet->header.version = BATADV_COMPAT_VERSION;
931 coded_packet->header.ttl = packet1->header.ttl;
932
933 /* Info about first unicast packet */
934 memcpy(coded_packet->first_source, first_source, ETH_ALEN);
935 memcpy(coded_packet->first_orig_dest, packet1->dest, ETH_ALEN);
936 coded_packet->first_crc = packet_id1;
937 coded_packet->first_ttvn = packet1->ttvn;
938
939 /* Info about second unicast packet */
940 memcpy(coded_packet->second_dest, second_dest, ETH_ALEN);
941 memcpy(coded_packet->second_source, second_source, ETH_ALEN);
942 memcpy(coded_packet->second_orig_dest, packet2->dest, ETH_ALEN);
943 coded_packet->second_crc = packet_id2;
944 coded_packet->second_ttl = packet2->header.ttl;
945 coded_packet->second_ttvn = packet2->ttvn;
946 coded_packet->coded_len = htons(coding_len);
947
948 /* This is where the magic happens: Code skb_src into skb_dest */
949 batadv_nc_memxor(skb_dest->data + coded_size,
950 skb_src->data + unicast_size, coding_len);
951
952 /* Update counters accordingly */
953 if (BATADV_SKB_CB(skb_src)->decoded &&
954 BATADV_SKB_CB(skb_dest)->decoded) {
955 /* Both packets are recoded */
956 count = skb_src->len + ETH_HLEN;
957 count += skb_dest->len + ETH_HLEN;
958 batadv_add_counter(bat_priv, BATADV_CNT_NC_RECODE, 2);
959 batadv_add_counter(bat_priv, BATADV_CNT_NC_RECODE_BYTES, count);
960 } else if (!BATADV_SKB_CB(skb_src)->decoded &&
961 !BATADV_SKB_CB(skb_dest)->decoded) {
962 /* Both packets are newly coded */
963 count = skb_src->len + ETH_HLEN;
964 count += skb_dest->len + ETH_HLEN;
965 batadv_add_counter(bat_priv, BATADV_CNT_NC_CODE, 2);
966 batadv_add_counter(bat_priv, BATADV_CNT_NC_CODE_BYTES, count);
967 } else if (BATADV_SKB_CB(skb_src)->decoded &&
968 !BATADV_SKB_CB(skb_dest)->decoded) {
969 /* skb_src recoded and skb_dest is newly coded */
970 batadv_inc_counter(bat_priv, BATADV_CNT_NC_RECODE);
971 batadv_add_counter(bat_priv, BATADV_CNT_NC_RECODE_BYTES,
972 skb_src->len + ETH_HLEN);
973 batadv_inc_counter(bat_priv, BATADV_CNT_NC_CODE);
974 batadv_add_counter(bat_priv, BATADV_CNT_NC_CODE_BYTES,
975 skb_dest->len + ETH_HLEN);
976 } else if (!BATADV_SKB_CB(skb_src)->decoded &&
977 BATADV_SKB_CB(skb_dest)->decoded) {
978 /* skb_src is newly coded and skb_dest is recoded */
979 batadv_inc_counter(bat_priv, BATADV_CNT_NC_CODE);
980 batadv_add_counter(bat_priv, BATADV_CNT_NC_CODE_BYTES,
981 skb_src->len + ETH_HLEN);
982 batadv_inc_counter(bat_priv, BATADV_CNT_NC_RECODE);
983 batadv_add_counter(bat_priv, BATADV_CNT_NC_RECODE_BYTES,
984 skb_dest->len + ETH_HLEN);
985 }
986
987 /* skb_src is now coded into skb_dest, so free it */
988 kfree_skb(skb_src);
989
990 /* avoid duplicate free of skb from nc_packet */
991 nc_packet->skb = NULL;
992 batadv_nc_packet_free(nc_packet);
993
994 /* Send the coded packet and return true */
995 batadv_send_skb_packet(skb_dest, neigh_node->if_incoming, first_dest);
996 res = true;
997out:
998 if (router_neigh)
999 batadv_neigh_node_free_ref(router_neigh);
1000 if (router_coding)
1001 batadv_neigh_node_free_ref(router_coding);
1002 return res;
1003}
1004
1005/**
1006 * batadv_nc_skb_coding_possible - true if a decoded skb is available at dst.
1007 * @skb: data skb to forward
1008 * @dst: destination mac address of the other skb to code with
1009 * @src: source mac address of skb
1010 *
1011 * Whenever we network code a packet we have to check whether we received it in
1012 * a network coded form. If so, we may not be able to use it for coding because
1013 * some neighbors may also have received (overheard) the packet in the network
1014 * coded form without being able to decode it. It is hard to know which of the
1015 * neighboring nodes was able to decode the packet, therefore we can only
1016 * re-code the packet if the source of the previous encoded packet is involved.
1017 * Since the source encoded the packet we can be certain it has all necessary
1018 * decode information.
1019 *
1020 * Returns true if coding of a decoded packet is allowed.
1021 */
1022static bool batadv_nc_skb_coding_possible(struct sk_buff *skb,
1023 uint8_t *dst, uint8_t *src)
1024{
1025 if (BATADV_SKB_CB(skb)->decoded && !batadv_compare_eth(dst, src))
1026 return false;
1027 else
1028 return true;
1029}
1030
1031/**
1032 * batadv_nc_path_search - Find the coding path matching in_nc_node and
1033 * out_nc_node to retrieve a buffered packet that can be used for coding.
1034 * @bat_priv: the bat priv with all the soft interface information
1035 * @in_nc_node: pointer to skb next hop's neighbor nc node
1036 * @out_nc_node: pointer to skb source's neighbor nc node
1037 * @skb: data skb to forward
1038 * @eth_dst: next hop mac address of skb
1039 *
1040 * Returns true if coding of a decoded skb is allowed.
1041 */
1042static struct batadv_nc_packet *
1043batadv_nc_path_search(struct batadv_priv *bat_priv,
1044 struct batadv_nc_node *in_nc_node,
1045 struct batadv_nc_node *out_nc_node,
1046 struct sk_buff *skb,
1047 uint8_t *eth_dst)
1048{
1049 struct batadv_nc_path *nc_path, nc_path_key;
1050 struct batadv_nc_packet *nc_packet_out = NULL;
1051 struct batadv_nc_packet *nc_packet, *nc_packet_tmp;
1052 struct batadv_hashtable *hash = bat_priv->nc.coding_hash;
1053 int idx;
1054
1055 if (!hash)
1056 return NULL;
1057
1058 /* Create almost path key */
1059 batadv_nc_hash_key_gen(&nc_path_key, in_nc_node->addr,
1060 out_nc_node->addr);
1061 idx = batadv_nc_hash_choose(&nc_path_key, hash->size);
1062
1063 /* Check for coding opportunities in this nc_path */
1064 rcu_read_lock();
1065 hlist_for_each_entry_rcu(nc_path, &hash->table[idx], hash_entry) {
1066 if (!batadv_compare_eth(nc_path->prev_hop, in_nc_node->addr))
1067 continue;
1068
1069 if (!batadv_compare_eth(nc_path->next_hop, out_nc_node->addr))
1070 continue;
1071
1072 spin_lock_bh(&nc_path->packet_list_lock);
1073 if (list_empty(&nc_path->packet_list)) {
1074 spin_unlock_bh(&nc_path->packet_list_lock);
1075 continue;
1076 }
1077
1078 list_for_each_entry_safe(nc_packet, nc_packet_tmp,
1079 &nc_path->packet_list, list) {
1080 if (!batadv_nc_skb_coding_possible(nc_packet->skb,
1081 eth_dst,
1082 in_nc_node->addr))
1083 continue;
1084
1085 /* Coding opportunity is found! */
1086 list_del(&nc_packet->list);
1087 nc_packet_out = nc_packet;
1088 break;
1089 }
1090
1091 spin_unlock_bh(&nc_path->packet_list_lock);
1092 break;
1093 }
1094 rcu_read_unlock();
1095
1096 return nc_packet_out;
1097}
1098
1099/**
1100 * batadv_nc_skb_src_search - Loops through the list of neighoring nodes of the
1101 * skb's sender (may be equal to the originator).
1102 * @bat_priv: the bat priv with all the soft interface information
1103 * @skb: data skb to forward
1104 * @eth_dst: next hop mac address of skb
1105 * @eth_src: source mac address of skb
1106 * @in_nc_node: pointer to skb next hop's neighbor nc node
1107 *
1108 * Returns an nc packet if a suitable coding packet was found, NULL otherwise.
1109 */
1110static struct batadv_nc_packet *
1111batadv_nc_skb_src_search(struct batadv_priv *bat_priv,
1112 struct sk_buff *skb,
1113 uint8_t *eth_dst,
1114 uint8_t *eth_src,
1115 struct batadv_nc_node *in_nc_node)
1116{
1117 struct batadv_orig_node *orig_node;
1118 struct batadv_nc_node *out_nc_node;
1119 struct batadv_nc_packet *nc_packet = NULL;
1120
1121 orig_node = batadv_orig_hash_find(bat_priv, eth_src);
1122 if (!orig_node)
1123 return NULL;
1124
1125 rcu_read_lock();
1126 list_for_each_entry_rcu(out_nc_node,
1127 &orig_node->out_coding_list, list) {
1128 /* Check if the skb is decoded and if recoding is possible */
1129 if (!batadv_nc_skb_coding_possible(skb,
1130 out_nc_node->addr, eth_src))
1131 continue;
1132
1133 /* Search for an opportunity in this nc_path */
1134 nc_packet = batadv_nc_path_search(bat_priv, in_nc_node,
1135 out_nc_node, skb, eth_dst);
1136 if (nc_packet)
1137 break;
1138 }
1139 rcu_read_unlock();
1140
1141 batadv_orig_node_free_ref(orig_node);
1142 return nc_packet;
1143}
1144
1145/**
1146 * batadv_nc_skb_dst_search - Loops through list of neighboring nodes to dst.
1147 * @skb: data skb to forward
1148 * @neigh_node: next hop to forward packet to
1149 * @ethhdr: pointer to the ethernet header inside the skb
1150 *
1151 * Loops through list of neighboring nodes the next hop has a good connection to
1152 * (receives OGMs with a sufficient quality). We need to find a neighbor of our
1153 * next hop that potentially sent a packet which our next hop also received
1154 * (overheard) and has stored for later decoding.
1155 *
1156 * Returns true if the skb was consumed (encoded packet sent) or false otherwise
1157 */
1158static bool batadv_nc_skb_dst_search(struct sk_buff *skb,
1159 struct batadv_neigh_node *neigh_node,
1160 struct ethhdr *ethhdr)
1161{
1162 struct net_device *netdev = neigh_node->if_incoming->soft_iface;
1163 struct batadv_priv *bat_priv = netdev_priv(netdev);
1164 struct batadv_orig_node *orig_node = neigh_node->orig_node;
1165 struct batadv_nc_node *nc_node;
1166 struct batadv_nc_packet *nc_packet = NULL;
1167
1168 rcu_read_lock();
1169 list_for_each_entry_rcu(nc_node, &orig_node->in_coding_list, list) {
1170 /* Search for coding opportunity with this in_nc_node */
1171 nc_packet = batadv_nc_skb_src_search(bat_priv, skb,
1172 neigh_node->addr,
1173 ethhdr->h_source, nc_node);
1174
1175 /* Opportunity was found, so stop searching */
1176 if (nc_packet)
1177 break;
1178 }
1179 rcu_read_unlock();
1180
1181 if (!nc_packet)
1182 return false;
1183
1184 /* Code and send packets */
1185 if (batadv_nc_code_packets(bat_priv, skb, ethhdr, nc_packet,
1186 neigh_node))
1187 return true;
1188
1189 /* out of mem ? Coding failed - we have to free the buffered packet
1190 * to avoid memleaks. The skb passed as argument will be dealt with
1191 * by the calling function.
1192 */
1193 batadv_nc_send_packet(nc_packet);
1194 return false;
1195}
1196
95332477
MH
1197/**
1198 * batadv_nc_skb_add_to_path - buffer skb for later encoding / decoding
1199 * @skb: skb to add to path
1200 * @nc_path: path to add skb to
1201 * @neigh_node: next hop to forward packet to
1202 * @packet_id: checksum to identify packet
1203 *
1204 * Returns true if the packet was buffered or false in case of an error.
1205 */
1206static bool batadv_nc_skb_add_to_path(struct sk_buff *skb,
1207 struct batadv_nc_path *nc_path,
1208 struct batadv_neigh_node *neigh_node,
1209 __be32 packet_id)
1210{
1211 struct batadv_nc_packet *nc_packet;
1212
1213 nc_packet = kzalloc(sizeof(*nc_packet), GFP_ATOMIC);
1214 if (!nc_packet)
1215 return false;
1216
1217 /* Initialize nc_packet */
1218 nc_packet->timestamp = jiffies;
1219 nc_packet->packet_id = packet_id;
1220 nc_packet->skb = skb;
1221 nc_packet->neigh_node = neigh_node;
1222 nc_packet->nc_path = nc_path;
1223
1224 /* Add coding packet to list */
1225 spin_lock_bh(&nc_path->packet_list_lock);
1226 list_add_tail(&nc_packet->list, &nc_path->packet_list);
1227 spin_unlock_bh(&nc_path->packet_list_lock);
1228
1229 return true;
1230}
1231
1232/**
1233 * batadv_nc_skb_forward - try to code a packet or add it to the coding packet
1234 * buffer
1235 * @skb: data skb to forward
1236 * @neigh_node: next hop to forward packet to
1237 * @ethhdr: pointer to the ethernet header inside the skb
1238 *
1239 * Returns true if the skb was consumed (encoded packet sent) or false otherwise
1240 */
1241bool batadv_nc_skb_forward(struct sk_buff *skb,
1242 struct batadv_neigh_node *neigh_node,
1243 struct ethhdr *ethhdr)
1244{
1245 const struct net_device *netdev = neigh_node->if_incoming->soft_iface;
1246 struct batadv_priv *bat_priv = netdev_priv(netdev);
1247 struct batadv_unicast_packet *packet;
1248 struct batadv_nc_path *nc_path;
1249 __be32 packet_id;
1250 u8 *payload;
1251
1252 /* Check if network coding is enabled */
1253 if (!atomic_read(&bat_priv->network_coding))
1254 goto out;
1255
1256 /* We only handle unicast packets */
1257 payload = skb_network_header(skb);
1258 packet = (struct batadv_unicast_packet *)payload;
1259 if (packet->header.packet_type != BATADV_UNICAST)
1260 goto out;
1261
3c12de9a
MH
1262 /* Try to find a coding opportunity and send the skb if one is found */
1263 if (batadv_nc_skb_dst_search(skb, neigh_node, ethhdr))
1264 return true;
1265
95332477
MH
1266 /* Find or create a nc_path for this src-dst pair */
1267 nc_path = batadv_nc_get_path(bat_priv,
1268 bat_priv->nc.coding_hash,
1269 ethhdr->h_source,
1270 neigh_node->addr);
1271
1272 if (!nc_path)
1273 goto out;
1274
1275 /* Add skb to nc_path */
1276 packet_id = batadv_skb_crc32(skb, payload + sizeof(*packet));
1277 if (!batadv_nc_skb_add_to_path(skb, nc_path, neigh_node, packet_id))
1278 goto free_nc_path;
1279
1280 /* Packet is consumed */
1281 return true;
1282
1283free_nc_path:
1284 batadv_nc_path_free_ref(nc_path);
1285out:
1286 /* Packet is not consumed */
1287 return false;
1288}
1289
d353d8d4
MH
1290/**
1291 * batadv_nc_free - clean up network coding memory
1292 * @bat_priv: the bat priv with all the soft interface information
1293 */
1294void batadv_nc_free(struct batadv_priv *bat_priv)
1295{
1296 cancel_delayed_work_sync(&bat_priv->nc.work);
95332477
MH
1297 batadv_nc_purge_paths(bat_priv, bat_priv->nc.coding_hash, NULL);
1298 batadv_hash_destroy(bat_priv->nc.coding_hash);
d353d8d4 1299}
d56b1705
MH
1300
1301/**
1302 * batadv_nc_nodes_seq_print_text - print the nc node information
1303 * @seq: seq file to print on
1304 * @offset: not used
1305 */
1306int batadv_nc_nodes_seq_print_text(struct seq_file *seq, void *offset)
1307{
1308 struct net_device *net_dev = (struct net_device *)seq->private;
1309 struct batadv_priv *bat_priv = netdev_priv(net_dev);
1310 struct batadv_hashtable *hash = bat_priv->orig_hash;
1311 struct batadv_hard_iface *primary_if;
1312 struct hlist_head *head;
1313 struct batadv_orig_node *orig_node;
1314 struct batadv_nc_node *nc_node;
1315 int i;
1316
1317 primary_if = batadv_seq_print_text_primary_if_get(seq);
1318 if (!primary_if)
1319 goto out;
1320
1321 /* Traverse list of originators */
1322 for (i = 0; i < hash->size; i++) {
1323 head = &hash->table[i];
1324
1325 /* For each orig_node in this bin */
1326 rcu_read_lock();
1327 hlist_for_each_entry_rcu(orig_node, head, hash_entry) {
1328 seq_printf(seq, "Node: %pM\n", orig_node->orig);
1329
1330 seq_printf(seq, " Ingoing: ");
1331 /* For each in_nc_node to this orig_node */
1332 list_for_each_entry_rcu(nc_node,
1333 &orig_node->in_coding_list,
1334 list)
1335 seq_printf(seq, "%pM ",
1336 nc_node->addr);
1337 seq_printf(seq, "\n");
1338
1339 seq_printf(seq, " Outgoing: ");
1340 /* For out_nc_node to this orig_node */
1341 list_for_each_entry_rcu(nc_node,
1342 &orig_node->out_coding_list,
1343 list)
1344 seq_printf(seq, "%pM ",
1345 nc_node->addr);
1346 seq_printf(seq, "\n\n");
1347 }
1348 rcu_read_unlock();
1349 }
1350
1351out:
1352 if (primary_if)
1353 batadv_hardif_free_ref(primary_if);
1354 return 0;
1355}
1356
1357/**
1358 * batadv_nc_init_debugfs - create nc folder and related files in debugfs
1359 * @bat_priv: the bat priv with all the soft interface information
1360 */
1361int batadv_nc_init_debugfs(struct batadv_priv *bat_priv)
1362{
1363 struct dentry *nc_dir, *file;
1364
1365 nc_dir = debugfs_create_dir("nc", bat_priv->debug_dir);
1366 if (!nc_dir)
1367 goto out;
1368
1369 file = debugfs_create_u8("min_tq", S_IRUGO | S_IWUSR, nc_dir,
1370 &bat_priv->nc.min_tq);
1371 if (!file)
1372 goto out;
1373
95332477
MH
1374 file = debugfs_create_u32("max_fwd_delay", S_IRUGO | S_IWUSR, nc_dir,
1375 &bat_priv->nc.max_fwd_delay);
1376 if (!file)
1377 goto out;
1378
d56b1705
MH
1379 return 0;
1380
1381out:
1382 return -ENOMEM;
1383}
This page took 0.077398 seconds and 5 git commands to generate.