diff options
Diffstat (limited to 'net/batman-adv')
-rw-r--r-- | net/batman-adv/network-coding.c | 232 | ||||
-rw-r--r-- | net/batman-adv/soft-interface.c | 4 | ||||
-rw-r--r-- | net/batman-adv/types.h | 10 |
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 | ||
29 | static struct lock_class_key batadv_nc_coding_hash_lock_class_key; | 30 | 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; | 31 | static struct lock_class_key batadv_nc_decoding_hash_lock_class_key; |
31 | 32 | ||
32 | static void batadv_nc_worker(struct work_struct *work); | 33 | static void batadv_nc_worker(struct work_struct *work); |
34 | static 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 | */ | ||
1505 | static struct batadv_unicast_packet * | ||
1506 | batadv_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(ðhdr_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, ðhdr_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 | */ | ||
1594 | static struct batadv_nc_packet * | ||
1595 | batadv_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 | */ | ||
1656 | static 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 | |||
1714 | free_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 | */ |
1492 | void batadv_nc_free(struct batadv_priv *bat_priv) | 1723 | void 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 | */ |
285 | enum batadv_counters { | 291 | enum 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 | }; |