aboutsummaryrefslogtreecommitdiffstats
path: root/net/batman-adv
diff options
context:
space:
mode:
Diffstat (limited to 'net/batman-adv')
-rw-r--r--net/batman-adv/bat_iv_ogm.c5
-rw-r--r--net/batman-adv/debugfs.c18
-rw-r--r--net/batman-adv/main.h2
-rw-r--r--net/batman-adv/network-coding.c414
-rw-r--r--net/batman-adv/network-coding.h47
-rw-r--r--net/batman-adv/originator.c6
-rw-r--r--net/batman-adv/types.h32
7 files changed, 524 insertions, 0 deletions
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
index a5bb0a769eb9..071f288b77a8 100644
--- a/net/batman-adv/bat_iv_ogm.c
+++ b/net/batman-adv/bat_iv_ogm.c
@@ -27,6 +27,7 @@
27#include "hard-interface.h" 27#include "hard-interface.h"
28#include "send.h" 28#include "send.h"
29#include "bat_algo.h" 29#include "bat_algo.h"
30#include "network-coding.h"
30 31
31static struct batadv_neigh_node * 32static struct batadv_neigh_node *
32batadv_iv_ogm_neigh_new(struct batadv_hard_iface *hard_iface, 33batadv_iv_ogm_neigh_new(struct batadv_hard_iface *hard_iface,
@@ -1185,6 +1186,10 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
1185 if (!orig_neigh_node) 1186 if (!orig_neigh_node)
1186 goto out; 1187 goto out;
1187 1188
1189 /* Update nc_nodes of the originator */
1190 batadv_nc_update_nc_node(bat_priv, orig_node, orig_neigh_node,
1191 batadv_ogm_packet, is_single_hop_neigh);
1192
1188 orig_neigh_router = batadv_orig_node_get_router(orig_neigh_node); 1193 orig_neigh_router = batadv_orig_node_get_router(orig_neigh_node);
1189 1194
1190 /* drop packet if sender is not a direct neighbor and if we 1195 /* drop packet if sender is not a direct neighbor and if we
diff --git a/net/batman-adv/debugfs.c b/net/batman-adv/debugfs.c
index 6ae86516db4d..f186a55b23c3 100644
--- a/net/batman-adv/debugfs.c
+++ b/net/batman-adv/debugfs.c
@@ -32,6 +32,7 @@
32#include "icmp_socket.h" 32#include "icmp_socket.h"
33#include "bridge_loop_avoidance.h" 33#include "bridge_loop_avoidance.h"
34#include "distributed-arp-table.h" 34#include "distributed-arp-table.h"
35#include "network-coding.h"
35 36
36static struct dentry *batadv_debugfs; 37static struct dentry *batadv_debugfs;
37 38
@@ -310,6 +311,14 @@ struct batadv_debuginfo {
310 const struct file_operations fops; 311 const struct file_operations fops;
311}; 312};
312 313
314#ifdef CONFIG_BATMAN_ADV_NC
315static int batadv_nc_nodes_open(struct inode *inode, struct file *file)
316{
317 struct net_device *net_dev = (struct net_device *)inode->i_private;
318 return single_open(file, batadv_nc_nodes_seq_print_text, net_dev);
319}
320#endif
321
313#define BATADV_DEBUGINFO(_name, _mode, _open) \ 322#define BATADV_DEBUGINFO(_name, _mode, _open) \
314struct batadv_debuginfo batadv_debuginfo_##_name = { \ 323struct batadv_debuginfo batadv_debuginfo_##_name = { \
315 .attr = { .name = __stringify(_name), \ 324 .attr = { .name = __stringify(_name), \
@@ -348,6 +357,9 @@ static BATADV_DEBUGINFO(dat_cache, S_IRUGO, batadv_dat_cache_open);
348static BATADV_DEBUGINFO(transtable_local, S_IRUGO, 357static BATADV_DEBUGINFO(transtable_local, S_IRUGO,
349 batadv_transtable_local_open); 358 batadv_transtable_local_open);
350static BATADV_DEBUGINFO(vis_data, S_IRUGO, batadv_vis_data_open); 359static BATADV_DEBUGINFO(vis_data, S_IRUGO, batadv_vis_data_open);
360#ifdef CONFIG_BATMAN_ADV_NC
361static BATADV_DEBUGINFO(nc_nodes, S_IRUGO, batadv_nc_nodes_open);
362#endif
351 363
352static struct batadv_debuginfo *batadv_mesh_debuginfos[] = { 364static struct batadv_debuginfo *batadv_mesh_debuginfos[] = {
353 &batadv_debuginfo_originators, 365 &batadv_debuginfo_originators,
@@ -362,6 +374,9 @@ static struct batadv_debuginfo *batadv_mesh_debuginfos[] = {
362#endif 374#endif
363 &batadv_debuginfo_transtable_local, 375 &batadv_debuginfo_transtable_local,
364 &batadv_debuginfo_vis_data, 376 &batadv_debuginfo_vis_data,
377#ifdef CONFIG_BATMAN_ADV_NC
378 &batadv_debuginfo_nc_nodes,
379#endif
365 NULL, 380 NULL,
366}; 381};
367 382
@@ -431,6 +446,9 @@ int batadv_debugfs_add_meshif(struct net_device *dev)
431 } 446 }
432 } 447 }
433 448
449 if (batadv_nc_init_debugfs(bat_priv) < 0)
450 goto rem_attr;
451
434 return 0; 452 return 0;
435rem_attr: 453rem_attr:
436 debugfs_remove_recursive(bat_priv->debug_dir); 454 debugfs_remove_recursive(bat_priv->debug_dir);
diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h
index 59ba2ff8e252..8a10619ae916 100644
--- a/net/batman-adv/main.h
+++ b/net/batman-adv/main.h
@@ -105,6 +105,8 @@
105#define BATADV_RESET_PROTECTION_MS 30000 105#define BATADV_RESET_PROTECTION_MS 30000
106#define BATADV_EXPECTED_SEQNO_RANGE 65536 106#define BATADV_EXPECTED_SEQNO_RANGE 65536
107 107
108#define BATADV_NC_NODE_TIMEOUT 10000 /* Milliseconds */
109
108enum batadv_mesh_state { 110enum batadv_mesh_state {
109 BATADV_MESH_INACTIVE, 111 BATADV_MESH_INACTIVE,
110 BATADV_MESH_ACTIVE, 112 BATADV_MESH_ACTIVE,
diff --git a/net/batman-adv/network-coding.c b/net/batman-adv/network-coding.c
index 9c2d54bdd2ce..ff4985d84726 100644
--- a/net/batman-adv/network-coding.c
+++ b/net/batman-adv/network-coding.c
@@ -17,8 +17,12 @@
17 * 02110-1301, USA 17 * 02110-1301, USA
18 */ 18 */
19 19
20#include <linux/debugfs.h>
21
20#include "main.h" 22#include "main.h"
21#include "network-coding.h" 23#include "network-coding.h"
24#include "originator.h"
25#include "hard-interface.h"
22 26
23static void batadv_nc_worker(struct work_struct *work); 27static void batadv_nc_worker(struct work_struct *work);
24 28
@@ -51,6 +55,151 @@ int batadv_nc_init(struct batadv_priv *bat_priv)
51void batadv_nc_init_bat_priv(struct batadv_priv *bat_priv) 55void batadv_nc_init_bat_priv(struct batadv_priv *bat_priv)
52{ 56{
53 atomic_set(&bat_priv->network_coding, 1); 57 atomic_set(&bat_priv->network_coding, 1);
58 bat_priv->nc.min_tq = 200;
59}
60
61/**
62 * batadv_nc_init_orig - initialise the nc fields of an orig_node
63 * @orig_node: the orig_node which is going to be initialised
64 */
65void batadv_nc_init_orig(struct batadv_orig_node *orig_node)
66{
67 INIT_LIST_HEAD(&orig_node->in_coding_list);
68 INIT_LIST_HEAD(&orig_node->out_coding_list);
69 spin_lock_init(&orig_node->in_coding_list_lock);
70 spin_lock_init(&orig_node->out_coding_list_lock);
71}
72
73/**
74 * batadv_nc_node_free_rcu - rcu callback to free an nc node and remove
75 * its refcount on the orig_node
76 * @rcu: rcu pointer of the nc node
77 */
78static void batadv_nc_node_free_rcu(struct rcu_head *rcu)
79{
80 struct batadv_nc_node *nc_node;
81
82 nc_node = container_of(rcu, struct batadv_nc_node, rcu);
83 batadv_orig_node_free_ref(nc_node->orig_node);
84 kfree(nc_node);
85}
86
87/**
88 * batadv_nc_node_free_ref - decrements the nc node refcounter and possibly
89 * frees it
90 * @nc_node: the nc node to free
91 */
92static void batadv_nc_node_free_ref(struct batadv_nc_node *nc_node)
93{
94 if (atomic_dec_and_test(&nc_node->refcount))
95 call_rcu(&nc_node->rcu, batadv_nc_node_free_rcu);
96}
97
98/**
99 * batadv_nc_to_purge_nc_node - checks whether an nc node has to be purged
100 * @bat_priv: the bat priv with all the soft interface information
101 * @nc_node: the nc node to check
102 *
103 * Returns true if the entry has to be purged now, false otherwise
104 */
105static bool batadv_nc_to_purge_nc_node(struct batadv_priv *bat_priv,
106 struct batadv_nc_node *nc_node)
107{
108 if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE)
109 return true;
110
111 return batadv_has_timed_out(nc_node->last_seen, BATADV_NC_NODE_TIMEOUT);
112}
113
114/**
115 * batadv_nc_purge_orig_nc_nodes - go through list of nc nodes and purge stale
116 * entries
117 * @bat_priv: the bat priv with all the soft interface information
118 * @list: list of nc nodes
119 * @lock: nc node list lock
120 * @to_purge: function in charge to decide whether an entry has to be purged or
121 * not. This function takes the nc node as argument and has to return
122 * a boolean value: true if the entry has to be deleted, false
123 * otherwise
124 */
125static void
126batadv_nc_purge_orig_nc_nodes(struct batadv_priv *bat_priv,
127 struct list_head *list,
128 spinlock_t *lock,
129 bool (*to_purge)(struct batadv_priv *,
130 struct batadv_nc_node *))
131{
132 struct batadv_nc_node *nc_node, *nc_node_tmp;
133
134 /* For each nc_node in list */
135 spin_lock_bh(lock);
136 list_for_each_entry_safe(nc_node, nc_node_tmp, list, list) {
137 /* if an helper function has been passed as parameter,
138 * ask it if the entry has to be purged or not
139 */
140 if (to_purge && !to_purge(bat_priv, nc_node))
141 continue;
142
143 batadv_dbg(BATADV_DBG_NC, bat_priv,
144 "Removing nc_node %pM -> %pM\n",
145 nc_node->addr, nc_node->orig_node->orig);
146 list_del_rcu(&nc_node->list);
147 batadv_nc_node_free_ref(nc_node);
148 }
149 spin_unlock_bh(lock);
150}
151
152/**
153 * batadv_nc_purge_orig - purges all nc node data attached of the given
154 * originator
155 * @bat_priv: the bat priv with all the soft interface information
156 * @orig_node: orig_node with the nc node entries to be purged
157 * @to_purge: function in charge to decide whether an entry has to be purged or
158 * not. This function takes the nc node as argument and has to return
159 * a boolean value: true is the entry has to be deleted, false
160 * otherwise
161 */
162void batadv_nc_purge_orig(struct batadv_priv *bat_priv,
163 struct batadv_orig_node *orig_node,
164 bool (*to_purge)(struct batadv_priv *,
165 struct batadv_nc_node *))
166{
167 /* Check ingoing nc_node's of this orig_node */
168 batadv_nc_purge_orig_nc_nodes(bat_priv, &orig_node->in_coding_list,
169 &orig_node->in_coding_list_lock,
170 to_purge);
171
172 /* Check outgoing nc_node's of this orig_node */
173 batadv_nc_purge_orig_nc_nodes(bat_priv, &orig_node->out_coding_list,
174 &orig_node->out_coding_list_lock,
175 to_purge);
176}
177
178/**
179 * batadv_nc_purge_orig_hash - traverse entire originator hash to check if they
180 * have timed out nc nodes
181 * @bat_priv: the bat priv with all the soft interface information
182 */
183static void batadv_nc_purge_orig_hash(struct batadv_priv *bat_priv)
184{
185 struct batadv_hashtable *hash = bat_priv->orig_hash;
186 struct hlist_head *head;
187 struct batadv_orig_node *orig_node;
188 uint32_t i;
189
190 if (!hash)
191 return;
192
193 /* For each orig_node */
194 for (i = 0; i < hash->size; i++) {
195 head = &hash->table[i];
196
197 rcu_read_lock();
198 hlist_for_each_entry_rcu(orig_node, head, hash_entry)
199 batadv_nc_purge_orig(bat_priv, orig_node,
200 batadv_nc_to_purge_nc_node);
201 rcu_read_unlock();
202 }
54} 203}
55 204
56/** 205/**
@@ -67,11 +216,197 @@ static void batadv_nc_worker(struct work_struct *work)
67 priv_nc = container_of(delayed_work, struct batadv_priv_nc, work); 216 priv_nc = container_of(delayed_work, struct batadv_priv_nc, work);
68 bat_priv = container_of(priv_nc, struct batadv_priv, nc); 217 bat_priv = container_of(priv_nc, struct batadv_priv, nc);
69 218
219 batadv_nc_purge_orig_hash(bat_priv);
220
70 /* Schedule a new check */ 221 /* Schedule a new check */
71 batadv_nc_start_timer(bat_priv); 222 batadv_nc_start_timer(bat_priv);
72} 223}
73 224
74/** 225/**
226 * batadv_can_nc_with_orig - checks whether the given orig node is suitable for
227 * coding or not
228 * @bat_priv: the bat priv with all the soft interface information
229 * @orig_node: neighboring orig node which may be used as nc candidate
230 * @ogm_packet: incoming ogm packet also used for the checks
231 *
232 * Returns true if:
233 * 1) The OGM must have the most recent sequence number.
234 * 2) The TTL must be decremented by one and only one.
235 * 3) The OGM must be received from the first hop from orig_node.
236 * 4) The TQ value of the OGM must be above bat_priv->nc.min_tq.
237 */
238static bool batadv_can_nc_with_orig(struct batadv_priv *bat_priv,
239 struct batadv_orig_node *orig_node,
240 struct batadv_ogm_packet *ogm_packet)
241{
242 if (orig_node->last_real_seqno != ogm_packet->seqno)
243 return false;
244 if (orig_node->last_ttl != ogm_packet->header.ttl + 1)
245 return false;
246 if (!batadv_compare_eth(ogm_packet->orig, ogm_packet->prev_sender))
247 return false;
248 if (ogm_packet->tq < bat_priv->nc.min_tq)
249 return false;
250
251 return true;
252}
253
254/**
255 * batadv_nc_find_nc_node - search for an existing nc node and return it
256 * @orig_node: orig node originating the ogm packet
257 * @orig_neigh_node: neighboring orig node from which we received the ogm packet
258 * (can be equal to orig_node)
259 * @in_coding: traverse incoming or outgoing network coding list
260 *
261 * Returns the nc_node if found, NULL otherwise.
262 */
263static struct batadv_nc_node
264*batadv_nc_find_nc_node(struct batadv_orig_node *orig_node,
265 struct batadv_orig_node *orig_neigh_node,
266 bool in_coding)
267{
268 struct batadv_nc_node *nc_node, *nc_node_out = NULL;
269 struct list_head *list;
270
271 if (in_coding)
272 list = &orig_neigh_node->in_coding_list;
273 else
274 list = &orig_neigh_node->out_coding_list;
275
276 /* Traverse list of nc_nodes to orig_node */
277 rcu_read_lock();
278 list_for_each_entry_rcu(nc_node, list, list) {
279 if (!batadv_compare_eth(nc_node->addr, orig_node->orig))
280 continue;
281
282 if (!atomic_inc_not_zero(&nc_node->refcount))
283 continue;
284
285 /* Found a match */
286 nc_node_out = nc_node;
287 break;
288 }
289 rcu_read_unlock();
290
291 return nc_node_out;
292}
293
294/**
295 * batadv_nc_get_nc_node - retrieves an nc node or creates the entry if it was
296 * not found
297 * @bat_priv: the bat priv with all the soft interface information
298 * @orig_node: orig node originating the ogm packet
299 * @orig_neigh_node: neighboring orig node from which we received the ogm packet
300 * (can be equal to orig_node)
301 * @in_coding: traverse incoming or outgoing network coding list
302 *
303 * Returns the nc_node if found or created, NULL in case of an error.
304 */
305static struct batadv_nc_node
306*batadv_nc_get_nc_node(struct batadv_priv *bat_priv,
307 struct batadv_orig_node *orig_node,
308 struct batadv_orig_node *orig_neigh_node,
309 bool in_coding)
310{
311 struct batadv_nc_node *nc_node;
312 spinlock_t *lock; /* Used to lock list selected by "int in_coding" */
313 struct list_head *list;
314
315 /* Check if nc_node is already added */
316 nc_node = batadv_nc_find_nc_node(orig_node, orig_neigh_node, in_coding);
317
318 /* Node found */
319 if (nc_node)
320 return nc_node;
321
322 nc_node = kzalloc(sizeof(*nc_node), GFP_ATOMIC);
323 if (!nc_node)
324 return NULL;
325
326 if (!atomic_inc_not_zero(&orig_neigh_node->refcount))
327 goto free;
328
329 /* Initialize nc_node */
330 INIT_LIST_HEAD(&nc_node->list);
331 memcpy(nc_node->addr, orig_node->orig, ETH_ALEN);
332 nc_node->orig_node = orig_neigh_node;
333 atomic_set(&nc_node->refcount, 2);
334
335 /* Select ingoing or outgoing coding node */
336 if (in_coding) {
337 lock = &orig_neigh_node->in_coding_list_lock;
338 list = &orig_neigh_node->in_coding_list;
339 } else {
340 lock = &orig_neigh_node->out_coding_list_lock;
341 list = &orig_neigh_node->out_coding_list;
342 }
343
344 batadv_dbg(BATADV_DBG_NC, bat_priv, "Adding nc_node %pM -> %pM\n",
345 nc_node->addr, nc_node->orig_node->orig);
346
347 /* Add nc_node to orig_node */
348 spin_lock_bh(lock);
349 list_add_tail_rcu(&nc_node->list, list);
350 spin_unlock_bh(lock);
351
352 return nc_node;
353
354free:
355 kfree(nc_node);
356 return NULL;
357}
358
359/**
360 * batadv_nc_update_nc_node - updates stored incoming and outgoing nc node structs
361 * (best called on incoming OGMs)
362 * @bat_priv: the bat priv with all the soft interface information
363 * @orig_node: orig node originating the ogm packet
364 * @orig_neigh_node: neighboring orig node from which we received the ogm packet
365 * (can be equal to orig_node)
366 * @ogm_packet: incoming ogm packet
367 * @is_single_hop_neigh: orig_node is a single hop neighbor
368 */
369void batadv_nc_update_nc_node(struct batadv_priv *bat_priv,
370 struct batadv_orig_node *orig_node,
371 struct batadv_orig_node *orig_neigh_node,
372 struct batadv_ogm_packet *ogm_packet,
373 int is_single_hop_neigh)
374{
375 struct batadv_nc_node *in_nc_node = NULL, *out_nc_node = NULL;
376
377 /* Check if network coding is enabled */
378 if (!atomic_read(&bat_priv->network_coding))
379 goto out;
380
381 /* accept ogms from 'good' neighbors and single hop neighbors */
382 if (!batadv_can_nc_with_orig(bat_priv, orig_node, ogm_packet) &&
383 !is_single_hop_neigh)
384 goto out;
385
386 /* Add orig_node as in_nc_node on hop */
387 in_nc_node = batadv_nc_get_nc_node(bat_priv, orig_node,
388 orig_neigh_node, true);
389 if (!in_nc_node)
390 goto out;
391
392 in_nc_node->last_seen = jiffies;
393
394 /* Add hop as out_nc_node on orig_node */
395 out_nc_node = batadv_nc_get_nc_node(bat_priv, orig_neigh_node,
396 orig_node, false);
397 if (!out_nc_node)
398 goto out;
399
400 out_nc_node->last_seen = jiffies;
401
402out:
403 if (in_nc_node)
404 batadv_nc_node_free_ref(in_nc_node);
405 if (out_nc_node)
406 batadv_nc_node_free_ref(out_nc_node);
407}
408
409/**
75 * batadv_nc_free - clean up network coding memory 410 * batadv_nc_free - clean up network coding memory
76 * @bat_priv: the bat priv with all the soft interface information 411 * @bat_priv: the bat priv with all the soft interface information
77 */ 412 */
@@ -79,3 +414,82 @@ void batadv_nc_free(struct batadv_priv *bat_priv)
79{ 414{
80 cancel_delayed_work_sync(&bat_priv->nc.work); 415 cancel_delayed_work_sync(&bat_priv->nc.work);
81} 416}
417
418/**
419 * batadv_nc_nodes_seq_print_text - print the nc node information
420 * @seq: seq file to print on
421 * @offset: not used
422 */
423int batadv_nc_nodes_seq_print_text(struct seq_file *seq, void *offset)
424{
425 struct net_device *net_dev = (struct net_device *)seq->private;
426 struct batadv_priv *bat_priv = netdev_priv(net_dev);
427 struct batadv_hashtable *hash = bat_priv->orig_hash;
428 struct batadv_hard_iface *primary_if;
429 struct hlist_head *head;
430 struct batadv_orig_node *orig_node;
431 struct batadv_nc_node *nc_node;
432 int i;
433
434 primary_if = batadv_seq_print_text_primary_if_get(seq);
435 if (!primary_if)
436 goto out;
437
438 /* Traverse list of originators */
439 for (i = 0; i < hash->size; i++) {
440 head = &hash->table[i];
441
442 /* For each orig_node in this bin */
443 rcu_read_lock();
444 hlist_for_each_entry_rcu(orig_node, head, hash_entry) {
445 seq_printf(seq, "Node: %pM\n", orig_node->orig);
446
447 seq_printf(seq, " Ingoing: ");
448 /* For each in_nc_node to this orig_node */
449 list_for_each_entry_rcu(nc_node,
450 &orig_node->in_coding_list,
451 list)
452 seq_printf(seq, "%pM ",
453 nc_node->addr);
454 seq_printf(seq, "\n");
455
456 seq_printf(seq, " Outgoing: ");
457 /* For out_nc_node to this orig_node */
458 list_for_each_entry_rcu(nc_node,
459 &orig_node->out_coding_list,
460 list)
461 seq_printf(seq, "%pM ",
462 nc_node->addr);
463 seq_printf(seq, "\n\n");
464 }
465 rcu_read_unlock();
466 }
467
468out:
469 if (primary_if)
470 batadv_hardif_free_ref(primary_if);
471 return 0;
472}
473
474/**
475 * batadv_nc_init_debugfs - create nc folder and related files in debugfs
476 * @bat_priv: the bat priv with all the soft interface information
477 */
478int batadv_nc_init_debugfs(struct batadv_priv *bat_priv)
479{
480 struct dentry *nc_dir, *file;
481
482 nc_dir = debugfs_create_dir("nc", bat_priv->debug_dir);
483 if (!nc_dir)
484 goto out;
485
486 file = debugfs_create_u8("min_tq", S_IRUGO | S_IWUSR, nc_dir,
487 &bat_priv->nc.min_tq);
488 if (!file)
489 goto out;
490
491 return 0;
492
493out:
494 return -ENOMEM;
495}
diff --git a/net/batman-adv/network-coding.h b/net/batman-adv/network-coding.h
index 7483cba4b5d4..4c56cd98d9de 100644
--- a/net/batman-adv/network-coding.h
+++ b/net/batman-adv/network-coding.h
@@ -24,7 +24,19 @@
24 24
25int batadv_nc_init(struct batadv_priv *bat_priv); 25int batadv_nc_init(struct batadv_priv *bat_priv);
26void batadv_nc_free(struct batadv_priv *bat_priv); 26void batadv_nc_free(struct batadv_priv *bat_priv);
27void batadv_nc_update_nc_node(struct batadv_priv *bat_priv,
28 struct batadv_orig_node *orig_node,
29 struct batadv_orig_node *orig_neigh_node,
30 struct batadv_ogm_packet *ogm_packet,
31 int is_single_hop_neigh);
32void batadv_nc_purge_orig(struct batadv_priv *bat_priv,
33 struct batadv_orig_node *orig_node,
34 bool (*to_purge)(struct batadv_priv *,
35 struct batadv_nc_node *));
27void batadv_nc_init_bat_priv(struct batadv_priv *bat_priv); 36void batadv_nc_init_bat_priv(struct batadv_priv *bat_priv);
37void batadv_nc_init_orig(struct batadv_orig_node *orig_node);
38int batadv_nc_nodes_seq_print_text(struct seq_file *seq, void *offset);
39int batadv_nc_init_debugfs(struct batadv_priv *bat_priv);
28 40
29#else /* ifdef CONFIG_BATMAN_ADV_NC */ 41#else /* ifdef CONFIG_BATMAN_ADV_NC */
30 42
@@ -38,11 +50,46 @@ static inline void batadv_nc_free(struct batadv_priv *bat_priv)
38 return; 50 return;
39} 51}
40 52
53static inline void
54batadv_nc_update_nc_node(struct batadv_priv *bat_priv,
55 struct batadv_orig_node *orig_node,
56 struct batadv_orig_node *orig_neigh_node,
57 struct batadv_ogm_packet *ogm_packet,
58 int is_single_hop_neigh)
59{
60 return;
61}
62
63static inline void
64batadv_nc_purge_orig(struct batadv_priv *bat_priv,
65 struct batadv_orig_node *orig_node,
66 bool (*to_purge)(struct batadv_priv *,
67 struct batadv_nc_node *))
68{
69 return;
70}
71
41static inline void batadv_nc_init_bat_priv(struct batadv_priv *bat_priv) 72static inline void batadv_nc_init_bat_priv(struct batadv_priv *bat_priv)
42{ 73{
43 return; 74 return;
44} 75}
45 76
77static inline void batadv_nc_init_orig(struct batadv_orig_node *orig_node)
78{
79 return;
80}
81
82static inline int batadv_nc_nodes_seq_print_text(struct seq_file *seq,
83 void *offset)
84{
85 return 0;
86}
87
88static inline int batadv_nc_init_debugfs(struct batadv_priv *bat_priv)
89{
90 return 0;
91}
92
46#endif /* ifdef CONFIG_BATMAN_ADV_NC */ 93#endif /* ifdef CONFIG_BATMAN_ADV_NC */
47 94
48#endif /* _NET_BATMAN_ADV_NETWORK_CODING_H_ */ 95#endif /* _NET_BATMAN_ADV_NETWORK_CODING_H_ */
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c
index 96fb80b724dc..585e684a380b 100644
--- a/net/batman-adv/originator.c
+++ b/net/batman-adv/originator.c
@@ -28,6 +28,7 @@
28#include "unicast.h" 28#include "unicast.h"
29#include "soft-interface.h" 29#include "soft-interface.h"
30#include "bridge_loop_avoidance.h" 30#include "bridge_loop_avoidance.h"
31#include "network-coding.h"
31 32
32/* hash class keys */ 33/* hash class keys */
33static struct lock_class_key batadv_orig_hash_lock_class_key; 34static struct lock_class_key batadv_orig_hash_lock_class_key;
@@ -142,6 +143,9 @@ static void batadv_orig_node_free_rcu(struct rcu_head *rcu)
142 143
143 spin_unlock_bh(&orig_node->neigh_list_lock); 144 spin_unlock_bh(&orig_node->neigh_list_lock);
144 145
146 /* Free nc_nodes */
147 batadv_nc_purge_orig(orig_node->bat_priv, orig_node, NULL);
148
145 batadv_frag_list_free(&orig_node->frag_list); 149 batadv_frag_list_free(&orig_node->frag_list);
146 batadv_tt_global_del_orig(orig_node->bat_priv, orig_node, 150 batadv_tt_global_del_orig(orig_node->bat_priv, orig_node,
147 "originator timed out"); 151 "originator timed out");
@@ -219,6 +223,8 @@ struct batadv_orig_node *batadv_get_orig_node(struct batadv_priv *bat_priv,
219 spin_lock_init(&orig_node->neigh_list_lock); 223 spin_lock_init(&orig_node->neigh_list_lock);
220 spin_lock_init(&orig_node->tt_buff_lock); 224 spin_lock_init(&orig_node->tt_buff_lock);
221 225
226 batadv_nc_init_orig(orig_node);
227
222 /* extra reference for return */ 228 /* extra reference for return */
223 atomic_set(&orig_node->refcount, 2); 229 atomic_set(&orig_node->refcount, 2);
224 230
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index 83bfe7c38f81..1544ab40bedd 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -128,6 +128,10 @@ struct batadv_hard_iface {
128 * @bond_list: list of bonding candidates 128 * @bond_list: list of bonding candidates
129 * @refcount: number of contexts the object is used 129 * @refcount: number of contexts the object is used
130 * @rcu: struct used for freeing in an RCU-safe manner 130 * @rcu: struct used for freeing in an RCU-safe manner
131 * @in_coding_list: list of nodes this orig can hear
132 * @out_coding_list: list of nodes that can hear this orig
133 * @in_coding_list_lock: protects in_coding_list
134 * @out_coding_list_lock: protects out_coding_list
131 */ 135 */
132struct batadv_orig_node { 136struct batadv_orig_node {
133 uint8_t orig[ETH_ALEN]; 137 uint8_t orig[ETH_ALEN];
@@ -171,6 +175,12 @@ struct batadv_orig_node {
171 struct list_head bond_list; 175 struct list_head bond_list;
172 atomic_t refcount; 176 atomic_t refcount;
173 struct rcu_head rcu; 177 struct rcu_head rcu;
178#ifdef CONFIG_BATMAN_ADV_NC
179 struct list_head in_coding_list;
180 struct list_head out_coding_list;
181 spinlock_t in_coding_list_lock; /* Protects in_coding_list */
182 spinlock_t out_coding_list_lock; /* Protects out_coding_list */
183#endif
174}; 184};
175 185
176/** 186/**
@@ -430,9 +440,13 @@ struct batadv_priv_dat {
430/** 440/**
431 * struct batadv_priv_nc - per mesh interface network coding private data 441 * struct batadv_priv_nc - per mesh interface network coding private data
432 * @work: work queue callback item for cleanup 442 * @work: work queue callback item for cleanup
443 * @debug_dir: dentry for nc subdir in batman-adv directory in debugfs
444 * @min_tq: only consider neighbors for encoding if neigh_tq > min_tq
433 */ 445 */
434struct batadv_priv_nc { 446struct batadv_priv_nc {
435 struct delayed_work work; 447 struct delayed_work work;
448 struct dentry *debug_dir;
449 u8 min_tq;
436}; 450};
437 451
438/** 452/**
@@ -716,6 +730,24 @@ struct batadv_tt_roam_node {
716}; 730};
717 731
718/** 732/**
733 * struct batadv_nc_node - network coding node
734 * @list: next and prev pointer for the list handling
735 * @addr: the node's mac address
736 * @refcount: number of contexts the object is used by
737 * @rcu: struct used for freeing in an RCU-safe manner
738 * @orig_node: pointer to corresponding orig node struct
739 * @last_seen: timestamp of last ogm received from this node
740 */
741struct batadv_nc_node {
742 struct list_head list;
743 uint8_t addr[ETH_ALEN];
744 atomic_t refcount;
745 struct rcu_head rcu;
746 struct batadv_orig_node *orig_node;
747 unsigned long last_seen;
748};
749
750/**
719 * struct batadv_forw_packet - structure for bcast packets to be sent/forwarded 751 * struct batadv_forw_packet - structure for bcast packets to be sent/forwarded
720 * @list: list node for batadv_socket_client::queue_list 752 * @list: list node for batadv_socket_client::queue_list
721 * @send_time: execution time for delayed_work (packet sending) 753 * @send_time: execution time for delayed_work (packet sending)