aboutsummaryrefslogtreecommitdiffstats
path: root/net/batman-adv
diff options
context:
space:
mode:
Diffstat (limited to 'net/batman-adv')
-rw-r--r--net/batman-adv/network-coding.c232
-rw-r--r--net/batman-adv/soft-interface.c4
-rw-r--r--net/batman-adv/types.h10
3 files changed, 246 insertions, 0 deletions
diff --git a/net/batman-adv/network-coding.c b/net/batman-adv/network-coding.c
index 3d2ed2fe5421..57280797bf4e 100644
--- a/net/batman-adv/network-coding.c
+++ b/net/batman-adv/network-coding.c
@@ -25,11 +25,14 @@
25#include "send.h" 25#include "send.h"
26#include "originator.h" 26#include "originator.h"
27#include "hard-interface.h" 27#include "hard-interface.h"
28#include "routing.h"
28 29
29static struct lock_class_key batadv_nc_coding_hash_lock_class_key; 30static struct lock_class_key batadv_nc_coding_hash_lock_class_key;
30static struct lock_class_key batadv_nc_decoding_hash_lock_class_key; 31static struct lock_class_key batadv_nc_decoding_hash_lock_class_key;
31 32
32static void batadv_nc_worker(struct work_struct *work); 33static void batadv_nc_worker(struct work_struct *work);
34static int batadv_nc_recv_coded_packet(struct sk_buff *skb,
35 struct batadv_hard_iface *recv_if);
33 36
34/** 37/**
35 * batadv_nc_start_timer - initialise the nc periodic worker 38 * batadv_nc_start_timer - initialise the nc periodic worker
@@ -67,6 +70,11 @@ int batadv_nc_init(struct batadv_priv *bat_priv)
67 batadv_hash_set_lock_class(bat_priv->nc.coding_hash, 70 batadv_hash_set_lock_class(bat_priv->nc.coding_hash,
68 &batadv_nc_decoding_hash_lock_class_key); 71 &batadv_nc_decoding_hash_lock_class_key);
69 72
73 /* Register our packet type */
74 if (batadv_recv_handler_register(BATADV_CODED,
75 batadv_nc_recv_coded_packet) < 0)
76 goto err;
77
70 INIT_DELAYED_WORK(&bat_priv->nc.work, batadv_nc_worker); 78 INIT_DELAYED_WORK(&bat_priv->nc.work, batadv_nc_worker);
71 batadv_nc_start_timer(bat_priv); 79 batadv_nc_start_timer(bat_priv);
72 80
@@ -1486,11 +1494,235 @@ void batadv_nc_skb_store_sniffed_unicast(struct batadv_priv *bat_priv,
1486} 1494}
1487 1495
1488/** 1496/**
1497 * batadv_nc_skb_decode_packet - decode given skb using the decode data stored
1498 * in nc_packet
1499 * @skb: unicast skb to decode
1500 * @nc_packet: decode data needed to decode the skb
1501 *
1502 * Returns pointer to decoded unicast packet if the packet was decoded or NULL
1503 * in case of an error.
1504 */
1505static struct batadv_unicast_packet *
1506batadv_nc_skb_decode_packet(struct sk_buff *skb,
1507 struct batadv_nc_packet *nc_packet)
1508{
1509 const int h_size = sizeof(struct batadv_unicast_packet);
1510 const int h_diff = sizeof(struct batadv_coded_packet) - h_size;
1511 struct batadv_unicast_packet *unicast_packet;
1512 struct batadv_coded_packet coded_packet_tmp;
1513 struct ethhdr *ethhdr, ethhdr_tmp;
1514 uint8_t *orig_dest, ttl, ttvn;
1515 unsigned int coding_len;
1516
1517 /* Save headers temporarily */
1518 memcpy(&coded_packet_tmp, skb->data, sizeof(coded_packet_tmp));
1519 memcpy(&ethhdr_tmp, skb_mac_header(skb), sizeof(ethhdr_tmp));
1520
1521 if (skb_cow(skb, 0) < 0)
1522 return NULL;
1523
1524 if (unlikely(!skb_pull_rcsum(skb, h_diff)))
1525 return NULL;
1526
1527 /* Data points to batman header, so set mac header 14 bytes before
1528 * and network to data
1529 */
1530 skb_set_mac_header(skb, -ETH_HLEN);
1531 skb_reset_network_header(skb);
1532
1533 /* Reconstruct original mac header */
1534 ethhdr = (struct ethhdr *)skb_mac_header(skb);
1535 memcpy(ethhdr, &ethhdr_tmp, sizeof(*ethhdr));
1536
1537 /* Select the correct unicast header information based on the location
1538 * of our mac address in the coded_packet header
1539 */
1540 if (batadv_is_my_mac(coded_packet_tmp.second_dest)) {
1541 /* If we are the second destination the packet was overheard,
1542 * so the Ethernet address must be copied to h_dest and
1543 * pkt_type changed from PACKET_OTHERHOST to PACKET_HOST
1544 */
1545 memcpy(ethhdr->h_dest, coded_packet_tmp.second_dest, ETH_ALEN);
1546 skb->pkt_type = PACKET_HOST;
1547
1548 orig_dest = coded_packet_tmp.second_orig_dest;
1549 ttl = coded_packet_tmp.second_ttl;
1550 ttvn = coded_packet_tmp.second_ttvn;
1551 } else {
1552 orig_dest = coded_packet_tmp.first_orig_dest;
1553 ttl = coded_packet_tmp.header.ttl;
1554 ttvn = coded_packet_tmp.first_ttvn;
1555 }
1556
1557 coding_len = ntohs(coded_packet_tmp.coded_len);
1558
1559 if (coding_len > skb->len)
1560 return NULL;
1561
1562 /* Here the magic is reversed:
1563 * extract the missing packet from the received coded packet
1564 */
1565 batadv_nc_memxor(skb->data + h_size,
1566 nc_packet->skb->data + h_size,
1567 coding_len);
1568
1569 /* Resize decoded skb if decoded with larger packet */
1570 if (nc_packet->skb->len > coding_len + h_size)
1571 pskb_trim_rcsum(skb, coding_len + h_size);
1572
1573 /* Create decoded unicast packet */
1574 unicast_packet = (struct batadv_unicast_packet *)skb->data;
1575 unicast_packet->header.packet_type = BATADV_UNICAST;
1576 unicast_packet->header.version = BATADV_COMPAT_VERSION;
1577 unicast_packet->header.ttl = ttl;
1578 memcpy(unicast_packet->dest, orig_dest, ETH_ALEN);
1579 unicast_packet->ttvn = ttvn;
1580
1581 batadv_nc_packet_free(nc_packet);
1582 return unicast_packet;
1583}
1584
1585/**
1586 * batadv_nc_find_decoding_packet - search through buffered decoding data to
1587 * find the data needed to decode the coded packet
1588 * @bat_priv: the bat priv with all the soft interface information
1589 * @ethhdr: pointer to the ethernet header inside the coded packet
1590 * @coded: coded packet we try to find decode data for
1591 *
1592 * Returns pointer to nc packet if the needed data was found or NULL otherwise.
1593 */
1594static struct batadv_nc_packet *
1595batadv_nc_find_decoding_packet(struct batadv_priv *bat_priv,
1596 struct ethhdr *ethhdr,
1597 struct batadv_coded_packet *coded)
1598{
1599 struct batadv_hashtable *hash = bat_priv->nc.decoding_hash;
1600 struct batadv_nc_packet *tmp_nc_packet, *nc_packet = NULL;
1601 struct batadv_nc_path *nc_path, nc_path_key;
1602 uint8_t *dest, *source;
1603 __be32 packet_id;
1604 int index;
1605
1606 if (!hash)
1607 return NULL;
1608
1609 /* Select the correct packet id based on the location of our mac-addr */
1610 dest = ethhdr->h_source;
1611 if (!batadv_is_my_mac(coded->second_dest)) {
1612 source = coded->second_source;
1613 packet_id = coded->second_crc;
1614 } else {
1615 source = coded->first_source;
1616 packet_id = coded->first_crc;
1617 }
1618
1619 batadv_nc_hash_key_gen(&nc_path_key, source, dest);
1620 index = batadv_nc_hash_choose(&nc_path_key, hash->size);
1621
1622 /* Search for matching coding path */
1623 rcu_read_lock();
1624 hlist_for_each_entry_rcu(nc_path, &hash->table[index], hash_entry) {
1625 /* Find matching nc_packet */
1626 spin_lock_bh(&nc_path->packet_list_lock);
1627 list_for_each_entry(tmp_nc_packet,
1628 &nc_path->packet_list, list) {
1629 if (packet_id == tmp_nc_packet->packet_id) {
1630 list_del(&tmp_nc_packet->list);
1631
1632 nc_packet = tmp_nc_packet;
1633 break;
1634 }
1635 }
1636 spin_unlock_bh(&nc_path->packet_list_lock);
1637
1638 if (nc_packet)
1639 break;
1640 }
1641 rcu_read_unlock();
1642
1643 if (!nc_packet)
1644 batadv_dbg(BATADV_DBG_NC, bat_priv,
1645 "No decoding packet found for %u\n", packet_id);
1646
1647 return nc_packet;
1648}
1649
1650/**
1651 * batadv_nc_recv_coded_packet - try to decode coded packet and enqueue the
1652 * resulting unicast packet
1653 * @skb: incoming coded packet
1654 * @recv_if: pointer to interface this packet was received on
1655 */
1656static int batadv_nc_recv_coded_packet(struct sk_buff *skb,
1657 struct batadv_hard_iface *recv_if)
1658{
1659 struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface);
1660 struct batadv_unicast_packet *unicast_packet;
1661 struct batadv_coded_packet *coded_packet;
1662 struct batadv_nc_packet *nc_packet;
1663 struct ethhdr *ethhdr;
1664 int hdr_size = sizeof(*coded_packet);
1665
1666 /* Check if network coding is enabled */
1667 if (!atomic_read(&bat_priv->network_coding))
1668 return NET_RX_DROP;
1669
1670 /* Make sure we can access (and remove) header */
1671 if (unlikely(!pskb_may_pull(skb, hdr_size)))
1672 return NET_RX_DROP;
1673
1674 coded_packet = (struct batadv_coded_packet *)skb->data;
1675 ethhdr = (struct ethhdr *)skb_mac_header(skb);
1676
1677 /* Verify frame is destined for us */
1678 if (!batadv_is_my_mac(ethhdr->h_dest) &&
1679 !batadv_is_my_mac(coded_packet->second_dest))
1680 return NET_RX_DROP;
1681
1682 /* Update stat counter */
1683 if (batadv_is_my_mac(coded_packet->second_dest))
1684 batadv_inc_counter(bat_priv, BATADV_CNT_NC_SNIFFED);
1685
1686 nc_packet = batadv_nc_find_decoding_packet(bat_priv, ethhdr,
1687 coded_packet);
1688 if (!nc_packet) {
1689 batadv_inc_counter(bat_priv, BATADV_CNT_NC_DECODE_FAILED);
1690 return NET_RX_DROP;
1691 }
1692
1693 /* Make skb's linear, because decoding accesses the entire buffer */
1694 if (skb_linearize(skb) < 0)
1695 goto free_nc_packet;
1696
1697 if (skb_linearize(nc_packet->skb) < 0)
1698 goto free_nc_packet;
1699
1700 /* Decode the packet */
1701 unicast_packet = batadv_nc_skb_decode_packet(skb, nc_packet);
1702 if (!unicast_packet) {
1703 batadv_inc_counter(bat_priv, BATADV_CNT_NC_DECODE_FAILED);
1704 goto free_nc_packet;
1705 }
1706
1707 /* Mark packet as decoded to do correct recoding when forwarding */
1708 BATADV_SKB_CB(skb)->decoded = true;
1709 batadv_inc_counter(bat_priv, BATADV_CNT_NC_DECODE);
1710 batadv_add_counter(bat_priv, BATADV_CNT_NC_DECODE_BYTES,
1711 skb->len + ETH_HLEN);
1712 return batadv_recv_unicast_packet(skb, recv_if);
1713
1714free_nc_packet:
1715 batadv_nc_packet_free(nc_packet);
1716 return NET_RX_DROP;
1717}
1718
1719/**
1489 * batadv_nc_free - clean up network coding memory 1720 * batadv_nc_free - clean up network coding memory
1490 * @bat_priv: the bat priv with all the soft interface information 1721 * @bat_priv: the bat priv with all the soft interface information
1491 */ 1722 */
1492void batadv_nc_free(struct batadv_priv *bat_priv) 1723void batadv_nc_free(struct batadv_priv *bat_priv)
1493{ 1724{
1725 batadv_recv_handler_unregister(BATADV_CODED);
1494 cancel_delayed_work_sync(&bat_priv->nc.work); 1726 cancel_delayed_work_sync(&bat_priv->nc.work);
1495 1727
1496 batadv_nc_purge_paths(bat_priv, bat_priv->nc.coding_hash, NULL); 1728 batadv_nc_purge_paths(bat_priv, bat_priv->nc.coding_hash, NULL);
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c
index 75204ec1eee4..f93ae42abb58 100644
--- a/net/batman-adv/soft-interface.c
+++ b/net/batman-adv/soft-interface.c
@@ -671,6 +671,10 @@ static const struct {
671 { "nc_recode" }, 671 { "nc_recode" },
672 { "nc_recode_bytes" }, 672 { "nc_recode_bytes" },
673 { "nc_buffer" }, 673 { "nc_buffer" },
674 { "nc_decode" },
675 { "nc_decode_bytes" },
676 { "nc_decode_failed" },
677 { "nc_sniffed" },
674#endif 678#endif
675}; 679};
676 680
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index 5f3640d15dd2..aba8364c3689 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -280,6 +280,12 @@ struct batadv_bcast_duplist_entry {
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_NC_BUFFER: counter for packets buffered for later nc decoding
283 * @BATADV_CNT_NC_DECODE: received and nc-decoded traffic packet counter
284 * @BATADV_CNT_NC_DECODE_BYTES: received and nc-decoded traffic bytes counter
285 * @BATADV_CNT_NC_DECODE_FAILED: received and decode-failed traffic packet
286 * counter
287 * @BATADV_CNT_NC_SNIFFED: counter for nc-decoded packets received in promisc
288 * mode.
283 * @BATADV_CNT_NUM: number of traffic counters 289 * @BATADV_CNT_NUM: number of traffic counters
284 */ 290 */
285enum batadv_counters { 291enum batadv_counters {
@@ -313,6 +319,10 @@ enum batadv_counters {
313 BATADV_CNT_NC_RECODE, 319 BATADV_CNT_NC_RECODE,
314 BATADV_CNT_NC_RECODE_BYTES, 320 BATADV_CNT_NC_RECODE_BYTES,
315 BATADV_CNT_NC_BUFFER, 321 BATADV_CNT_NC_BUFFER,
322 BATADV_CNT_NC_DECODE,
323 BATADV_CNT_NC_DECODE_BYTES,
324 BATADV_CNT_NC_DECODE_FAILED,
325 BATADV_CNT_NC_SNIFFED,
316#endif 326#endif
317 BATADV_CNT_NUM, 327 BATADV_CNT_NUM,
318}; 328};