diff options
-rw-r--r-- | net/batman-adv/network-coding.c | 208 | ||||
-rw-r--r-- | net/batman-adv/network-coding.h | 18 | ||||
-rw-r--r-- | net/batman-adv/routing.c | 13 | ||||
-rw-r--r-- | net/batman-adv/send.c | 5 | ||||
-rw-r--r-- | net/batman-adv/soft-interface.c | 1 | ||||
-rw-r--r-- | net/batman-adv/types.h | 11 |
6 files changed, 253 insertions, 3 deletions
diff --git a/net/batman-adv/network-coding.c b/net/batman-adv/network-coding.c index fce2846e9656..3d2ed2fe5421 100644 --- a/net/batman-adv/network-coding.c +++ b/net/batman-adv/network-coding.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include "hard-interface.h" | 27 | #include "hard-interface.h" |
28 | 28 | ||
29 | static struct lock_class_key batadv_nc_coding_hash_lock_class_key; | 29 | static struct lock_class_key batadv_nc_coding_hash_lock_class_key; |
30 | static struct lock_class_key batadv_nc_decoding_hash_lock_class_key; | ||
30 | 31 | ||
31 | static void batadv_nc_worker(struct work_struct *work); | 32 | static void batadv_nc_worker(struct work_struct *work); |
32 | 33 | ||
@@ -47,8 +48,9 @@ static void batadv_nc_start_timer(struct batadv_priv *bat_priv) | |||
47 | int batadv_nc_init(struct batadv_priv *bat_priv) | 48 | int batadv_nc_init(struct batadv_priv *bat_priv) |
48 | { | 49 | { |
49 | bat_priv->nc.timestamp_fwd_flush = jiffies; | 50 | bat_priv->nc.timestamp_fwd_flush = jiffies; |
51 | bat_priv->nc.timestamp_sniffed_purge = jiffies; | ||
50 | 52 | ||
51 | if (bat_priv->nc.coding_hash) | 53 | if (bat_priv->nc.coding_hash || bat_priv->nc.decoding_hash) |
52 | return 0; | 54 | return 0; |
53 | 55 | ||
54 | bat_priv->nc.coding_hash = batadv_hash_new(128); | 56 | bat_priv->nc.coding_hash = batadv_hash_new(128); |
@@ -58,6 +60,13 @@ int batadv_nc_init(struct batadv_priv *bat_priv) | |||
58 | batadv_hash_set_lock_class(bat_priv->nc.coding_hash, | 60 | batadv_hash_set_lock_class(bat_priv->nc.coding_hash, |
59 | &batadv_nc_coding_hash_lock_class_key); | 61 | &batadv_nc_coding_hash_lock_class_key); |
60 | 62 | ||
63 | bat_priv->nc.decoding_hash = batadv_hash_new(128); | ||
64 | if (!bat_priv->nc.decoding_hash) | ||
65 | goto err; | ||
66 | |||
67 | batadv_hash_set_lock_class(bat_priv->nc.coding_hash, | ||
68 | &batadv_nc_decoding_hash_lock_class_key); | ||
69 | |||
61 | INIT_DELAYED_WORK(&bat_priv->nc.work, batadv_nc_worker); | 70 | INIT_DELAYED_WORK(&bat_priv->nc.work, batadv_nc_worker); |
62 | batadv_nc_start_timer(bat_priv); | 71 | batadv_nc_start_timer(bat_priv); |
63 | 72 | ||
@@ -76,6 +85,7 @@ void batadv_nc_init_bat_priv(struct batadv_priv *bat_priv) | |||
76 | atomic_set(&bat_priv->network_coding, 1); | 85 | atomic_set(&bat_priv->network_coding, 1); |
77 | bat_priv->nc.min_tq = 200; | 86 | bat_priv->nc.min_tq = 200; |
78 | bat_priv->nc.max_fwd_delay = 10; | 87 | bat_priv->nc.max_fwd_delay = 10; |
88 | bat_priv->nc.max_buffer_time = 200; | ||
79 | } | 89 | } |
80 | 90 | ||
81 | /** | 91 | /** |
@@ -176,6 +186,26 @@ static bool batadv_nc_to_purge_nc_path_coding(struct batadv_priv *bat_priv, | |||
176 | } | 186 | } |
177 | 187 | ||
178 | /** | 188 | /** |
189 | * batadv_nc_to_purge_nc_path_decoding - checks whether an nc path has timed out | ||
190 | * @bat_priv: the bat priv with all the soft interface information | ||
191 | * @nc_path: the nc path to check | ||
192 | * | ||
193 | * Returns true if the entry has to be purged now, false otherwise | ||
194 | */ | ||
195 | static bool batadv_nc_to_purge_nc_path_decoding(struct batadv_priv *bat_priv, | ||
196 | struct batadv_nc_path *nc_path) | ||
197 | { | ||
198 | if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE) | ||
199 | return true; | ||
200 | |||
201 | /* purge the path when no packets has been added for 10 times the | ||
202 | * max_buffer time | ||
203 | */ | ||
204 | return batadv_has_timed_out(nc_path->last_valid, | ||
205 | bat_priv->nc.max_buffer_time*10); | ||
206 | } | ||
207 | |||
208 | /** | ||
179 | * batadv_nc_purge_orig_nc_nodes - go through list of nc nodes and purge stale | 209 | * batadv_nc_purge_orig_nc_nodes - go through list of nc nodes and purge stale |
180 | * entries | 210 | * entries |
181 | * @bat_priv: the bat priv with all the soft interface information | 211 | * @bat_priv: the bat priv with all the soft interface information |
@@ -441,6 +471,43 @@ static void batadv_nc_send_packet(struct batadv_nc_packet *nc_packet) | |||
441 | } | 471 | } |
442 | 472 | ||
443 | /** | 473 | /** |
474 | * batadv_nc_sniffed_purge - Checks timestamp of given sniffed nc_packet. | ||
475 | * @bat_priv: the bat priv with all the soft interface information | ||
476 | * @nc_path: the nc path the packet belongs to | ||
477 | * @nc_packet: the nc packet to be checked | ||
478 | * | ||
479 | * Checks whether the given sniffed (overheard) nc_packet has hit its buffering | ||
480 | * timeout. If so, the packet is no longer kept and the entry deleted from the | ||
481 | * queue. Has to be called with the appropriate locks. | ||
482 | * | ||
483 | * Returns false as soon as the entry in the fifo queue has not been timed out | ||
484 | * yet and true otherwise. | ||
485 | */ | ||
486 | static bool batadv_nc_sniffed_purge(struct batadv_priv *bat_priv, | ||
487 | struct batadv_nc_path *nc_path, | ||
488 | struct batadv_nc_packet *nc_packet) | ||
489 | { | ||
490 | unsigned long timeout = bat_priv->nc.max_buffer_time; | ||
491 | bool res = false; | ||
492 | |||
493 | /* Packets are added to tail, so the remaining packets did not time | ||
494 | * out and we can stop processing the current queue | ||
495 | */ | ||
496 | if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_ACTIVE && | ||
497 | !batadv_has_timed_out(nc_packet->timestamp, timeout)) | ||
498 | goto out; | ||
499 | |||
500 | /* purge nc packet */ | ||
501 | list_del(&nc_packet->list); | ||
502 | batadv_nc_packet_free(nc_packet); | ||
503 | |||
504 | res = true; | ||
505 | |||
506 | out: | ||
507 | return res; | ||
508 | } | ||
509 | |||
510 | /** | ||
444 | * batadv_nc_fwd_flush - Checks the timestamp of the given nc packet. | 511 | * batadv_nc_fwd_flush - Checks the timestamp of the given nc packet. |
445 | * @bat_priv: the bat priv with all the soft interface information | 512 | * @bat_priv: the bat priv with all the soft interface information |
446 | * @nc_path: the nc path the packet belongs to | 513 | * @nc_path: the nc path the packet belongs to |
@@ -540,6 +607,8 @@ static void batadv_nc_worker(struct work_struct *work) | |||
540 | batadv_nc_purge_orig_hash(bat_priv); | 607 | batadv_nc_purge_orig_hash(bat_priv); |
541 | batadv_nc_purge_paths(bat_priv, bat_priv->nc.coding_hash, | 608 | batadv_nc_purge_paths(bat_priv, bat_priv->nc.coding_hash, |
542 | batadv_nc_to_purge_nc_path_coding); | 609 | batadv_nc_to_purge_nc_path_coding); |
610 | batadv_nc_purge_paths(bat_priv, bat_priv->nc.decoding_hash, | ||
611 | batadv_nc_to_purge_nc_path_decoding); | ||
543 | 612 | ||
544 | timeout = bat_priv->nc.max_fwd_delay; | 613 | timeout = bat_priv->nc.max_fwd_delay; |
545 | 614 | ||
@@ -549,6 +618,13 @@ static void batadv_nc_worker(struct work_struct *work) | |||
549 | bat_priv->nc.timestamp_fwd_flush = jiffies; | 618 | bat_priv->nc.timestamp_fwd_flush = jiffies; |
550 | } | 619 | } |
551 | 620 | ||
621 | if (batadv_has_timed_out(bat_priv->nc.timestamp_sniffed_purge, | ||
622 | bat_priv->nc.max_buffer_time)) { | ||
623 | batadv_nc_process_nc_paths(bat_priv, bat_priv->nc.decoding_hash, | ||
624 | batadv_nc_sniffed_purge); | ||
625 | bat_priv->nc.timestamp_sniffed_purge = jiffies; | ||
626 | } | ||
627 | |||
552 | /* Schedule a new check */ | 628 | /* Schedule a new check */ |
553 | batadv_nc_start_timer(bat_priv); | 629 | batadv_nc_start_timer(bat_priv); |
554 | } | 630 | } |
@@ -1143,6 +1219,41 @@ batadv_nc_skb_src_search(struct batadv_priv *bat_priv, | |||
1143 | } | 1219 | } |
1144 | 1220 | ||
1145 | /** | 1221 | /** |
1222 | * batadv_nc_skb_store_before_coding - set the ethernet src and dst of the | ||
1223 | * unicast skb before it is stored for use in later decoding | ||
1224 | * @bat_priv: the bat priv with all the soft interface information | ||
1225 | * @skb: data skb to store | ||
1226 | * @eth_dst_new: new destination mac address of skb | ||
1227 | */ | ||
1228 | static void batadv_nc_skb_store_before_coding(struct batadv_priv *bat_priv, | ||
1229 | struct sk_buff *skb, | ||
1230 | uint8_t *eth_dst_new) | ||
1231 | { | ||
1232 | struct ethhdr *ethhdr; | ||
1233 | |||
1234 | /* Copy skb header to change the mac header */ | ||
1235 | skb = pskb_copy(skb, GFP_ATOMIC); | ||
1236 | if (!skb) | ||
1237 | return; | ||
1238 | |||
1239 | /* Set the mac header as if we actually sent the packet uncoded */ | ||
1240 | ethhdr = (struct ethhdr *)skb_mac_header(skb); | ||
1241 | memcpy(ethhdr->h_source, ethhdr->h_dest, ETH_ALEN); | ||
1242 | memcpy(ethhdr->h_dest, eth_dst_new, ETH_ALEN); | ||
1243 | |||
1244 | /* Set data pointer to MAC header to mimic packets from our tx path */ | ||
1245 | skb_push(skb, ETH_HLEN); | ||
1246 | |||
1247 | /* Add the packet to the decoding packet pool */ | ||
1248 | batadv_nc_skb_store_for_decoding(bat_priv, skb); | ||
1249 | |||
1250 | /* batadv_nc_skb_store_for_decoding() clones the skb, so we must free | ||
1251 | * our ref | ||
1252 | */ | ||
1253 | kfree_skb(skb); | ||
1254 | } | ||
1255 | |||
1256 | /** | ||
1146 | * batadv_nc_skb_dst_search - Loops through list of neighboring nodes to dst. | 1257 | * batadv_nc_skb_dst_search - Loops through list of neighboring nodes to dst. |
1147 | * @skb: data skb to forward | 1258 | * @skb: data skb to forward |
1148 | * @neigh_node: next hop to forward packet to | 1259 | * @neigh_node: next hop to forward packet to |
@@ -1181,6 +1292,12 @@ static bool batadv_nc_skb_dst_search(struct sk_buff *skb, | |||
1181 | if (!nc_packet) | 1292 | if (!nc_packet) |
1182 | return false; | 1293 | return false; |
1183 | 1294 | ||
1295 | /* Save packets for later decoding */ | ||
1296 | batadv_nc_skb_store_before_coding(bat_priv, skb, | ||
1297 | neigh_node->addr); | ||
1298 | batadv_nc_skb_store_before_coding(bat_priv, nc_packet->skb, | ||
1299 | nc_packet->neigh_node->addr); | ||
1300 | |||
1184 | /* Code and send packets */ | 1301 | /* Code and send packets */ |
1185 | if (batadv_nc_code_packets(bat_priv, skb, ethhdr, nc_packet, | 1302 | if (batadv_nc_code_packets(bat_priv, skb, ethhdr, nc_packet, |
1186 | neigh_node)) | 1303 | neigh_node)) |
@@ -1288,14 +1405,98 @@ out: | |||
1288 | } | 1405 | } |
1289 | 1406 | ||
1290 | /** | 1407 | /** |
1408 | * batadv_nc_skb_store_for_decoding - save a clone of the skb which can be used | ||
1409 | * when decoding coded packets | ||
1410 | * @bat_priv: the bat priv with all the soft interface information | ||
1411 | * @skb: data skb to store | ||
1412 | */ | ||
1413 | void batadv_nc_skb_store_for_decoding(struct batadv_priv *bat_priv, | ||
1414 | struct sk_buff *skb) | ||
1415 | { | ||
1416 | struct batadv_unicast_packet *packet; | ||
1417 | struct batadv_nc_path *nc_path; | ||
1418 | struct ethhdr *ethhdr = (struct ethhdr *)skb_mac_header(skb); | ||
1419 | __be32 packet_id; | ||
1420 | u8 *payload; | ||
1421 | |||
1422 | /* Check if network coding is enabled */ | ||
1423 | if (!atomic_read(&bat_priv->network_coding)) | ||
1424 | goto out; | ||
1425 | |||
1426 | /* Check for supported packet type */ | ||
1427 | payload = skb_network_header(skb); | ||
1428 | packet = (struct batadv_unicast_packet *)payload; | ||
1429 | if (packet->header.packet_type != BATADV_UNICAST) | ||
1430 | goto out; | ||
1431 | |||
1432 | /* Find existing nc_path or create a new */ | ||
1433 | nc_path = batadv_nc_get_path(bat_priv, | ||
1434 | bat_priv->nc.decoding_hash, | ||
1435 | ethhdr->h_source, | ||
1436 | ethhdr->h_dest); | ||
1437 | |||
1438 | if (!nc_path) | ||
1439 | goto out; | ||
1440 | |||
1441 | /* Clone skb and adjust skb->data to point at batman header */ | ||
1442 | skb = skb_clone(skb, GFP_ATOMIC); | ||
1443 | if (unlikely(!skb)) | ||
1444 | goto free_nc_path; | ||
1445 | |||
1446 | if (unlikely(!pskb_may_pull(skb, ETH_HLEN))) | ||
1447 | goto free_skb; | ||
1448 | |||
1449 | if (unlikely(!skb_pull_rcsum(skb, ETH_HLEN))) | ||
1450 | goto free_skb; | ||
1451 | |||
1452 | /* Add skb to nc_path */ | ||
1453 | packet_id = batadv_skb_crc32(skb, payload + sizeof(*packet)); | ||
1454 | if (!batadv_nc_skb_add_to_path(skb, nc_path, NULL, packet_id)) | ||
1455 | goto free_skb; | ||
1456 | |||
1457 | batadv_inc_counter(bat_priv, BATADV_CNT_NC_BUFFER); | ||
1458 | return; | ||
1459 | |||
1460 | free_skb: | ||
1461 | kfree_skb(skb); | ||
1462 | free_nc_path: | ||
1463 | batadv_nc_path_free_ref(nc_path); | ||
1464 | out: | ||
1465 | return; | ||
1466 | } | ||
1467 | |||
1468 | /** | ||
1469 | * batadv_nc_skb_store_sniffed_unicast - check if a received unicast packet | ||
1470 | * should be saved in the decoding buffer and, if so, store it there | ||
1471 | * @bat_priv: the bat priv with all the soft interface information | ||
1472 | * @skb: unicast skb to store | ||
1473 | */ | ||
1474 | void batadv_nc_skb_store_sniffed_unicast(struct batadv_priv *bat_priv, | ||
1475 | struct sk_buff *skb) | ||
1476 | { | ||
1477 | struct ethhdr *ethhdr = (struct ethhdr *)skb_mac_header(skb); | ||
1478 | |||
1479 | if (batadv_is_my_mac(ethhdr->h_dest)) | ||
1480 | return; | ||
1481 | |||
1482 | /* Set data pointer to MAC header to mimic packets from our tx path */ | ||
1483 | skb_push(skb, ETH_HLEN); | ||
1484 | |||
1485 | batadv_nc_skb_store_for_decoding(bat_priv, skb); | ||
1486 | } | ||
1487 | |||
1488 | /** | ||
1291 | * batadv_nc_free - clean up network coding memory | 1489 | * batadv_nc_free - clean up network coding memory |
1292 | * @bat_priv: the bat priv with all the soft interface information | 1490 | * @bat_priv: the bat priv with all the soft interface information |
1293 | */ | 1491 | */ |
1294 | void batadv_nc_free(struct batadv_priv *bat_priv) | 1492 | void batadv_nc_free(struct batadv_priv *bat_priv) |
1295 | { | 1493 | { |
1296 | cancel_delayed_work_sync(&bat_priv->nc.work); | 1494 | cancel_delayed_work_sync(&bat_priv->nc.work); |
1495 | |||
1297 | batadv_nc_purge_paths(bat_priv, bat_priv->nc.coding_hash, NULL); | 1496 | batadv_nc_purge_paths(bat_priv, bat_priv->nc.coding_hash, NULL); |
1298 | batadv_hash_destroy(bat_priv->nc.coding_hash); | 1497 | batadv_hash_destroy(bat_priv->nc.coding_hash); |
1498 | batadv_nc_purge_paths(bat_priv, bat_priv->nc.decoding_hash, NULL); | ||
1499 | batadv_hash_destroy(bat_priv->nc.decoding_hash); | ||
1299 | } | 1500 | } |
1300 | 1501 | ||
1301 | /** | 1502 | /** |
@@ -1376,6 +1577,11 @@ int batadv_nc_init_debugfs(struct batadv_priv *bat_priv) | |||
1376 | if (!file) | 1577 | if (!file) |
1377 | goto out; | 1578 | goto out; |
1378 | 1579 | ||
1580 | file = debugfs_create_u32("max_buffer_time", S_IRUGO | S_IWUSR, nc_dir, | ||
1581 | &bat_priv->nc.max_buffer_time); | ||
1582 | if (!file) | ||
1583 | goto out; | ||
1584 | |||
1379 | return 0; | 1585 | return 0; |
1380 | 1586 | ||
1381 | out: | 1587 | out: |
diff --git a/net/batman-adv/network-coding.h b/net/batman-adv/network-coding.h index c32602a3939a..4fa6d0caddbd 100644 --- a/net/batman-adv/network-coding.h +++ b/net/batman-adv/network-coding.h | |||
@@ -38,6 +38,10 @@ void batadv_nc_init_orig(struct batadv_orig_node *orig_node); | |||
38 | bool batadv_nc_skb_forward(struct sk_buff *skb, | 38 | bool batadv_nc_skb_forward(struct sk_buff *skb, |
39 | struct batadv_neigh_node *neigh_node, | 39 | struct batadv_neigh_node *neigh_node, |
40 | struct ethhdr *ethhdr); | 40 | struct ethhdr *ethhdr); |
41 | void batadv_nc_skb_store_for_decoding(struct batadv_priv *bat_priv, | ||
42 | struct sk_buff *skb); | ||
43 | void batadv_nc_skb_store_sniffed_unicast(struct batadv_priv *bat_priv, | ||
44 | struct sk_buff *skb); | ||
41 | int batadv_nc_nodes_seq_print_text(struct seq_file *seq, void *offset); | 45 | int batadv_nc_nodes_seq_print_text(struct seq_file *seq, void *offset); |
42 | int batadv_nc_init_debugfs(struct batadv_priv *bat_priv); | 46 | int batadv_nc_init_debugfs(struct batadv_priv *bat_priv); |
43 | 47 | ||
@@ -89,6 +93,20 @@ static inline bool batadv_nc_skb_forward(struct sk_buff *skb, | |||
89 | return false; | 93 | return false; |
90 | } | 94 | } |
91 | 95 | ||
96 | static inline void | ||
97 | batadv_nc_skb_store_for_decoding(struct batadv_priv *bat_priv, | ||
98 | struct sk_buff *skb) | ||
99 | { | ||
100 | return; | ||
101 | } | ||
102 | |||
103 | static inline void | ||
104 | batadv_nc_skb_store_sniffed_unicast(struct batadv_priv *bat_priv, | ||
105 | struct sk_buff *skb) | ||
106 | { | ||
107 | return; | ||
108 | } | ||
109 | |||
92 | static inline int batadv_nc_nodes_seq_print_text(struct seq_file *seq, | 110 | static inline int batadv_nc_nodes_seq_print_text(struct seq_file *seq, |
93 | void *offset) | 111 | void *offset) |
94 | { | 112 | { |
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index 44fda7c6171e..8f88967ff14b 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c | |||
@@ -1047,7 +1047,7 @@ int batadv_recv_unicast_packet(struct sk_buff *skb, | |||
1047 | struct batadv_unicast_4addr_packet *unicast_4addr_packet; | 1047 | struct batadv_unicast_4addr_packet *unicast_4addr_packet; |
1048 | uint8_t *orig_addr; | 1048 | uint8_t *orig_addr; |
1049 | struct batadv_orig_node *orig_node = NULL; | 1049 | struct batadv_orig_node *orig_node = NULL; |
1050 | int hdr_size = sizeof(*unicast_packet); | 1050 | int check, hdr_size = sizeof(*unicast_packet); |
1051 | bool is4addr; | 1051 | bool is4addr; |
1052 | 1052 | ||
1053 | unicast_packet = (struct batadv_unicast_packet *)skb->data; | 1053 | unicast_packet = (struct batadv_unicast_packet *)skb->data; |
@@ -1058,7 +1058,16 @@ int batadv_recv_unicast_packet(struct sk_buff *skb, | |||
1058 | if (is4addr) | 1058 | if (is4addr) |
1059 | hdr_size = sizeof(*unicast_4addr_packet); | 1059 | hdr_size = sizeof(*unicast_4addr_packet); |
1060 | 1060 | ||
1061 | if (batadv_check_unicast_packet(skb, hdr_size) < 0) | 1061 | /* function returns -EREMOTE for promiscuous packets */ |
1062 | check = batadv_check_unicast_packet(skb, hdr_size); | ||
1063 | |||
1064 | /* Even though the packet is not for us, we might save it to use for | ||
1065 | * decoding a later received coded packet | ||
1066 | */ | ||
1067 | if (check == -EREMOTE) | ||
1068 | batadv_nc_skb_store_sniffed_unicast(bat_priv, skb); | ||
1069 | |||
1070 | if (check < 0) | ||
1062 | return NET_RX_DROP; | 1071 | return NET_RX_DROP; |
1063 | 1072 | ||
1064 | if (!batadv_check_unicast_ttvn(bat_priv, skb)) | 1073 | if (!batadv_check_unicast_ttvn(bat_priv, skb)) |
diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c index a67cffde37ae..263cfd1ccee7 100644 --- a/net/batman-adv/send.c +++ b/net/batman-adv/send.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include "vis.h" | 27 | #include "vis.h" |
28 | #include "gateway_common.h" | 28 | #include "gateway_common.h" |
29 | #include "originator.h" | 29 | #include "originator.h" |
30 | #include "network-coding.h" | ||
30 | 31 | ||
31 | #include <linux/if_ether.h> | 32 | #include <linux/if_ether.h> |
32 | 33 | ||
@@ -39,6 +40,7 @@ int batadv_send_skb_packet(struct sk_buff *skb, | |||
39 | struct batadv_hard_iface *hard_iface, | 40 | struct batadv_hard_iface *hard_iface, |
40 | const uint8_t *dst_addr) | 41 | const uint8_t *dst_addr) |
41 | { | 42 | { |
43 | struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface); | ||
42 | struct ethhdr *ethhdr; | 44 | struct ethhdr *ethhdr; |
43 | 45 | ||
44 | if (hard_iface->if_status != BATADV_IF_ACTIVE) | 46 | if (hard_iface->if_status != BATADV_IF_ACTIVE) |
@@ -70,6 +72,9 @@ int batadv_send_skb_packet(struct sk_buff *skb, | |||
70 | 72 | ||
71 | skb->dev = hard_iface->net_dev; | 73 | skb->dev = hard_iface->net_dev; |
72 | 74 | ||
75 | /* Save a clone of the skb to use when decoding coded packets */ | ||
76 | batadv_nc_skb_store_for_decoding(bat_priv, skb); | ||
77 | |||
73 | /* dev_queue_xmit() returns a negative result on error. However on | 78 | /* dev_queue_xmit() returns a negative result on error. However on |
74 | * congestion and traffic shaping, it drops and returns NET_XMIT_DROP | 79 | * congestion and traffic shaping, it drops and returns NET_XMIT_DROP |
75 | * (which is > 0). This will not be treated as an error. | 80 | * (which is > 0). This will not be treated as an error. |
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index 7e463c3ae1d9..75204ec1eee4 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c | |||
@@ -670,6 +670,7 @@ static const struct { | |||
670 | { "nc_code_bytes" }, | 670 | { "nc_code_bytes" }, |
671 | { "nc_recode" }, | 671 | { "nc_recode" }, |
672 | { "nc_recode_bytes" }, | 672 | { "nc_recode_bytes" }, |
673 | { "nc_buffer" }, | ||
673 | #endif | 674 | #endif |
674 | }; | 675 | }; |
675 | 676 | ||
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index 42d743850ec2..5f3640d15dd2 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h | |||
@@ -279,6 +279,7 @@ struct batadv_bcast_duplist_entry { | |||
279 | * @BATADV_CNT_NC_CODE_BYTES: transmitted nc-combined traffic bytes counter | 279 | * @BATADV_CNT_NC_CODE_BYTES: transmitted nc-combined traffic bytes counter |
280 | * @BATADV_CNT_NC_RECODE: transmitted nc-recombined traffic packet counter | 280 | * @BATADV_CNT_NC_RECODE: transmitted nc-recombined traffic packet counter |
281 | * @BATADV_CNT_NC_RECODE_BYTES: transmitted nc-recombined traffic bytes counter | 281 | * @BATADV_CNT_NC_RECODE_BYTES: transmitted nc-recombined traffic bytes counter |
282 | * @BATADV_CNT_NC_BUFFER: counter for packets buffered for later nc decoding | ||
282 | * @BATADV_CNT_NUM: number of traffic counters | 283 | * @BATADV_CNT_NUM: number of traffic counters |
283 | */ | 284 | */ |
284 | enum batadv_counters { | 285 | enum batadv_counters { |
@@ -311,6 +312,7 @@ enum batadv_counters { | |||
311 | BATADV_CNT_NC_CODE_BYTES, | 312 | BATADV_CNT_NC_CODE_BYTES, |
312 | BATADV_CNT_NC_RECODE, | 313 | BATADV_CNT_NC_RECODE, |
313 | BATADV_CNT_NC_RECODE_BYTES, | 314 | BATADV_CNT_NC_RECODE_BYTES, |
315 | BATADV_CNT_NC_BUFFER, | ||
314 | #endif | 316 | #endif |
315 | BATADV_CNT_NUM, | 317 | BATADV_CNT_NUM, |
316 | }; | 318 | }; |
@@ -453,18 +455,27 @@ struct batadv_priv_dat { | |||
453 | * @debug_dir: dentry for nc subdir in batman-adv directory in debugfs | 455 | * @debug_dir: dentry for nc subdir in batman-adv directory in debugfs |
454 | * @min_tq: only consider neighbors for encoding if neigh_tq > min_tq | 456 | * @min_tq: only consider neighbors for encoding if neigh_tq > min_tq |
455 | * @max_fwd_delay: maximum packet forward delay to allow coding of packets | 457 | * @max_fwd_delay: maximum packet forward delay to allow coding of packets |
458 | * @max_buffer_time: buffer time for sniffed packets used to decoding | ||
456 | * @timestamp_fwd_flush: timestamp of last forward packet queue flush | 459 | * @timestamp_fwd_flush: timestamp of last forward packet queue flush |
460 | * @timestamp_sniffed_purge: timestamp of last sniffed packet queue purge | ||
457 | * @coding_hash: Hash table used to buffer skbs while waiting for another | 461 | * @coding_hash: Hash table used to buffer skbs while waiting for another |
458 | * incoming skb to code it with. Skbs are added to the buffer just before being | 462 | * incoming skb to code it with. Skbs are added to the buffer just before being |
459 | * forwarded in routing.c | 463 | * forwarded in routing.c |
464 | * @decoding_hash: Hash table used to buffer skbs that might be needed to decode | ||
465 | * a received coded skb. The buffer is used for 1) skbs arriving on the | ||
466 | * soft-interface; 2) skbs overheard on the hard-interface; and 3) skbs | ||
467 | * forwarded by batman-adv. | ||
460 | */ | 468 | */ |
461 | struct batadv_priv_nc { | 469 | struct batadv_priv_nc { |
462 | struct delayed_work work; | 470 | struct delayed_work work; |
463 | struct dentry *debug_dir; | 471 | struct dentry *debug_dir; |
464 | u8 min_tq; | 472 | u8 min_tq; |
465 | u32 max_fwd_delay; | 473 | u32 max_fwd_delay; |
474 | u32 max_buffer_time; | ||
466 | unsigned long timestamp_fwd_flush; | 475 | unsigned long timestamp_fwd_flush; |
476 | unsigned long timestamp_sniffed_purge; | ||
467 | struct batadv_hashtable *coding_hash; | 477 | struct batadv_hashtable *coding_hash; |
478 | struct batadv_hashtable *decoding_hash; | ||
468 | }; | 479 | }; |
469 | 480 | ||
470 | /** | 481 | /** |