aboutsummaryrefslogtreecommitdiffstats
path: root/net/batman-adv/translation-table.c
diff options
context:
space:
mode:
authorMarek Lindner <lindner_marek@yahoo.de>2013-04-23 09:40:02 -0400
committerAntonio Quartulli <antonio@meshcoding.com>2013-10-09 15:22:30 -0400
commit335fbe0f5d2501b7dd815806aef6fd9bad784eb1 (patch)
tree6a456167f38f521a58d7fac2fc8a87aec338f0a7 /net/batman-adv/translation-table.c
parente1bf0c14096f9dc09c7695f42051d178b23d0670 (diff)
batman-adv: tvlv - convert tt query packet to use tvlv unicast packets
Instead of generating TT specific packets the TVLV unicast API is used to send translation table data. Signed-off-by: Marek Lindner <lindner_marek@yahoo.de> Signed-off-by: Antonio Quartulli <antonio@meshcoding.com>
Diffstat (limited to 'net/batman-adv/translation-table.c')
-rw-r--r--net/batman-adv/translation-table.c502
1 files changed, 286 insertions, 216 deletions
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
index 3fac67ffd524..22fce8a4793e 100644
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@ -229,9 +229,15 @@ unlock:
229 atomic_inc(&bat_priv->tt.local_changes); 229 atomic_inc(&bat_priv->tt.local_changes);
230} 230}
231 231
232int batadv_tt_len(int changes_num) 232/**
233 * batadv_tt_len - compute length in bytes of given number of tt changes
234 * @changes_num: number of tt changes
235 *
236 * Returns computed length in bytes.
237 */
238static int batadv_tt_len(int changes_num)
233{ 239{
234 return changes_num * sizeof(struct batadv_tt_change); 240 return changes_num * sizeof(struct batadv_tvlv_tt_change);
235} 241}
236 242
237static int batadv_tt_local_init(struct batadv_priv *bat_priv) 243static int batadv_tt_local_init(struct batadv_priv *bat_priv)
@@ -1555,9 +1561,14 @@ unlock:
1555 return tt_req_node; 1561 return tt_req_node;
1556} 1562}
1557 1563
1558/* data_ptr is useless here, but has to be kept to respect the prototype */ 1564/**
1559static int batadv_tt_local_valid_entry(const void *entry_ptr, 1565 * batadv_tt_local_valid - verify that given tt entry is a valid one
1560 const void *data_ptr) 1566 * @entry_ptr: to be checked local tt entry
1567 * @data_ptr: not used but definition required to satisfy the callback prototype
1568 *
1569 * Returns 1 if the entry is a valid, 0 otherwise.
1570 */
1571static int batadv_tt_local_valid(const void *entry_ptr, const void *data_ptr)
1561{ 1572{
1562 const struct batadv_tt_common_entry *tt_common_entry = entry_ptr; 1573 const struct batadv_tt_common_entry *tt_common_entry = entry_ptr;
1563 1574
@@ -1584,41 +1595,45 @@ static int batadv_tt_global_valid(const void *entry_ptr,
1584 return batadv_tt_global_entry_has_orig(tt_global_entry, orig_node); 1595 return batadv_tt_global_entry_has_orig(tt_global_entry, orig_node);
1585} 1596}
1586 1597
1587static struct sk_buff * 1598/**
1588batadv_tt_response_fill_table(uint16_t tt_len, uint8_t ttvn, 1599 * batadv_tt_tvlv_generate - creates tvlv tt data buffer to fill it with the
1589 struct batadv_hashtable *hash, 1600 * tt entries from the specified tt hash
1590 struct batadv_priv *bat_priv, 1601 * @bat_priv: the bat priv with all the soft interface information
1591 int (*valid_cb)(const void *, const void *), 1602 * @hash: hash table containing the tt entries
1592 void *cb_data) 1603 * @tt_len: expected tvlv tt data buffer length in number of bytes
1604 * @valid_cb: function to filter tt change entries
1605 * @cb_data: data passed to the filter function as argument
1606 *
1607 * Returns pointer to allocated tvlv tt data buffer if operation was
1608 * successful or NULL otherwise.
1609 */
1610static struct batadv_tvlv_tt_data *
1611batadv_tt_tvlv_generate(struct batadv_priv *bat_priv,
1612 struct batadv_hashtable *hash, uint16_t tt_len,
1613 int (*valid_cb)(const void *, const void *),
1614 void *cb_data)
1593{ 1615{
1594 struct batadv_tt_common_entry *tt_common_entry; 1616 struct batadv_tt_common_entry *tt_common_entry;
1595 struct batadv_tt_query_packet *tt_response; 1617 struct batadv_tvlv_tt_data *tvlv_tt_data = NULL;
1596 struct batadv_tt_change *tt_change; 1618 struct batadv_tvlv_tt_change *tt_change;
1597 struct hlist_head *head; 1619 struct hlist_head *head;
1598 struct sk_buff *skb = NULL; 1620 uint16_t tt_tot, tt_num_entries = 0;
1599 uint16_t tt_tot, tt_count; 1621 ssize_t tvlv_tt_size = sizeof(struct batadv_tvlv_tt_data);
1600 ssize_t tt_query_size = sizeof(struct batadv_tt_query_packet);
1601 uint32_t i; 1622 uint32_t i;
1602 size_t len;
1603 1623
1604 if (tt_query_size + tt_len > bat_priv->soft_iface->mtu) { 1624 if (tvlv_tt_size + tt_len > bat_priv->soft_iface->mtu) {
1605 tt_len = bat_priv->soft_iface->mtu - tt_query_size; 1625 tt_len = bat_priv->soft_iface->mtu - tvlv_tt_size;
1606 tt_len -= tt_len % sizeof(struct batadv_tt_change); 1626 tt_len -= tt_len % sizeof(struct batadv_tvlv_tt_change);
1607 } 1627 }
1608 tt_tot = tt_len / sizeof(struct batadv_tt_change);
1609 1628
1610 len = tt_query_size + tt_len; 1629 tt_tot = tt_len / sizeof(struct batadv_tvlv_tt_change);
1611 skb = netdev_alloc_skb_ip_align(NULL, len + ETH_HLEN);
1612 if (!skb)
1613 goto out;
1614 1630
1615 skb->priority = TC_PRIO_CONTROL; 1631 tvlv_tt_data = kzalloc(sizeof(*tvlv_tt_data) + tt_len,
1616 skb_reserve(skb, ETH_HLEN); 1632 GFP_ATOMIC);
1617 tt_response = (struct batadv_tt_query_packet *)skb_put(skb, len); 1633 if (!tvlv_tt_data)
1618 tt_response->ttvn = ttvn; 1634 goto out;
1619 1635
1620 tt_change = (struct batadv_tt_change *)(skb->data + tt_query_size); 1636 tt_change = (struct batadv_tvlv_tt_change *)(tvlv_tt_data + 1);
1621 tt_count = 0;
1622 1637
1623 rcu_read_lock(); 1638 rcu_read_lock();
1624 for (i = 0; i < hash->size; i++) { 1639 for (i = 0; i < hash->size; i++) {
@@ -1626,7 +1641,7 @@ batadv_tt_response_fill_table(uint16_t tt_len, uint8_t ttvn,
1626 1641
1627 hlist_for_each_entry_rcu(tt_common_entry, 1642 hlist_for_each_entry_rcu(tt_common_entry,
1628 head, hash_entry) { 1643 head, hash_entry) {
1629 if (tt_count == tt_tot) 1644 if (tt_tot == tt_num_entries)
1630 break; 1645 break;
1631 1646
1632 if ((valid_cb) && (!valid_cb(tt_common_entry, cb_data))) 1647 if ((valid_cb) && (!valid_cb(tt_common_entry, cb_data)))
@@ -1635,20 +1650,16 @@ batadv_tt_response_fill_table(uint16_t tt_len, uint8_t ttvn,
1635 memcpy(tt_change->addr, tt_common_entry->addr, 1650 memcpy(tt_change->addr, tt_common_entry->addr,
1636 ETH_ALEN); 1651 ETH_ALEN);
1637 tt_change->flags = tt_common_entry->flags; 1652 tt_change->flags = tt_common_entry->flags;
1653 tt_change->reserved = 0;
1638 1654
1639 tt_count++; 1655 tt_num_entries++;
1640 tt_change++; 1656 tt_change++;
1641 } 1657 }
1642 } 1658 }
1643 rcu_read_unlock(); 1659 rcu_read_unlock();
1644 1660
1645 /* store in the message the number of entries we have successfully
1646 * copied
1647 */
1648 tt_response->tt_data = htons(tt_count);
1649
1650out: 1661out:
1651 return skb; 1662 return tvlv_tt_data;
1652} 1663}
1653 1664
1654static int batadv_send_tt_request(struct batadv_priv *bat_priv, 1665static int batadv_send_tt_request(struct batadv_priv *bat_priv,
@@ -1656,12 +1667,10 @@ static int batadv_send_tt_request(struct batadv_priv *bat_priv,
1656 uint8_t ttvn, uint16_t tt_crc, 1667 uint8_t ttvn, uint16_t tt_crc,
1657 bool full_table) 1668 bool full_table)
1658{ 1669{
1659 struct sk_buff *skb = NULL; 1670 struct batadv_tvlv_tt_data *tvlv_tt_data = NULL;
1660 struct batadv_tt_query_packet *tt_request;
1661 struct batadv_hard_iface *primary_if; 1671 struct batadv_hard_iface *primary_if;
1662 struct batadv_tt_req_node *tt_req_node = NULL; 1672 struct batadv_tt_req_node *tt_req_node = NULL;
1663 int ret = 1; 1673 bool ret = false;
1664 size_t tt_req_len;
1665 1674
1666 primary_if = batadv_primary_if_get_selected(bat_priv); 1675 primary_if = batadv_primary_if_get_selected(bat_priv);
1667 if (!primary_if) 1676 if (!primary_if)
@@ -1674,157 +1683,136 @@ static int batadv_send_tt_request(struct batadv_priv *bat_priv,
1674 if (!tt_req_node) 1683 if (!tt_req_node)
1675 goto out; 1684 goto out;
1676 1685
1677 skb = netdev_alloc_skb_ip_align(NULL, sizeof(*tt_request) + ETH_HLEN); 1686 tvlv_tt_data = kzalloc(sizeof(*tvlv_tt_data), GFP_ATOMIC);
1678 if (!skb) 1687 if (!tvlv_tt_data)
1679 goto out; 1688 goto out;
1680 1689
1681 skb->priority = TC_PRIO_CONTROL; 1690 tvlv_tt_data->flags = BATADV_TT_REQUEST;
1682 skb_reserve(skb, ETH_HLEN); 1691 tvlv_tt_data->ttvn = ttvn;
1683 1692 tvlv_tt_data->crc = htons(tt_crc);
1684 tt_req_len = sizeof(*tt_request);
1685 tt_request = (struct batadv_tt_query_packet *)skb_put(skb, tt_req_len);
1686
1687 tt_request->header.packet_type = BATADV_TT_QUERY;
1688 tt_request->header.version = BATADV_COMPAT_VERSION;
1689 memcpy(tt_request->src, primary_if->net_dev->dev_addr, ETH_ALEN);
1690 memcpy(tt_request->dst, dst_orig_node->orig, ETH_ALEN);
1691 tt_request->header.ttl = BATADV_TTL;
1692 tt_request->ttvn = ttvn;
1693 tt_request->tt_data = htons(tt_crc);
1694 tt_request->flags = BATADV_TT_REQUEST;
1695 1693
1696 if (full_table) 1694 if (full_table)
1697 tt_request->flags |= BATADV_TT_FULL_TABLE; 1695 tvlv_tt_data->flags |= BATADV_TT_FULL_TABLE;
1698 1696
1699 batadv_dbg(BATADV_DBG_TT, bat_priv, "Sending TT_REQUEST to %pM [%c]\n", 1697 batadv_dbg(BATADV_DBG_TT, bat_priv, "Sending TT_REQUEST to %pM [%c]\n",
1700 dst_orig_node->orig, (full_table ? 'F' : '.')); 1698 dst_orig_node->orig, full_table ? 'F' : '.');
1701 1699
1702 batadv_inc_counter(bat_priv, BATADV_CNT_TT_REQUEST_TX); 1700 batadv_inc_counter(bat_priv, BATADV_CNT_TT_REQUEST_TX);
1703 1701 batadv_tvlv_unicast_send(bat_priv, primary_if->net_dev->dev_addr,
1704 if (batadv_send_skb_to_orig(skb, dst_orig_node, NULL) != NET_XMIT_DROP) 1702 dst_orig_node->orig, BATADV_TVLV_TT, 1,
1705 ret = 0; 1703 tvlv_tt_data, sizeof(*tvlv_tt_data));
1704 ret = true;
1706 1705
1707out: 1706out:
1708 if (primary_if) 1707 if (primary_if)
1709 batadv_hardif_free_ref(primary_if); 1708 batadv_hardif_free_ref(primary_if);
1710 if (ret)
1711 kfree_skb(skb);
1712 if (ret && tt_req_node) { 1709 if (ret && tt_req_node) {
1713 spin_lock_bh(&bat_priv->tt.req_list_lock); 1710 spin_lock_bh(&bat_priv->tt.req_list_lock);
1714 list_del(&tt_req_node->list); 1711 list_del(&tt_req_node->list);
1715 spin_unlock_bh(&bat_priv->tt.req_list_lock); 1712 spin_unlock_bh(&bat_priv->tt.req_list_lock);
1716 kfree(tt_req_node); 1713 kfree(tt_req_node);
1717 } 1714 }
1715 kfree(tvlv_tt_data);
1718 return ret; 1716 return ret;
1719} 1717}
1720 1718
1721static bool 1719/**
1722batadv_send_other_tt_response(struct batadv_priv *bat_priv, 1720 * batadv_send_other_tt_response - send reply to tt request concerning another
1723 struct batadv_tt_query_packet *tt_request) 1721 * node's translation table
1722 * @bat_priv: the bat priv with all the soft interface information
1723 * @tt_data: tt data containing the tt request information
1724 * @req_src: mac address of tt request sender
1725 * @req_dst: mac address of tt request recipient
1726 *
1727 * Returns true if tt request reply was sent, false otherwise.
1728 */
1729static bool batadv_send_other_tt_response(struct batadv_priv *bat_priv,
1730 struct batadv_tvlv_tt_data *tt_data,
1731 uint8_t *req_src, uint8_t *req_dst)
1724{ 1732{
1725 struct batadv_orig_node *req_dst_orig_node; 1733 struct batadv_orig_node *req_dst_orig_node;
1726 struct batadv_orig_node *res_dst_orig_node = NULL; 1734 struct batadv_orig_node *res_dst_orig_node = NULL;
1727 uint8_t orig_ttvn, req_ttvn, ttvn; 1735 struct batadv_tvlv_tt_data *tvlv_tt_data = NULL;
1728 int res, ret = false; 1736 uint8_t orig_ttvn, req_ttvn;
1729 unsigned char *tt_buff; 1737 uint16_t tt_len;
1730 bool full_table; 1738 bool ret = false, full_table;
1731 uint16_t tt_len, tt_tot;
1732 struct sk_buff *skb = NULL;
1733 struct batadv_tt_query_packet *tt_response;
1734 uint8_t *packet_pos;
1735 size_t len;
1736 1739
1737 batadv_dbg(BATADV_DBG_TT, bat_priv, 1740 batadv_dbg(BATADV_DBG_TT, bat_priv,
1738 "Received TT_REQUEST from %pM for ttvn: %u (%pM) [%c]\n", 1741 "Received TT_REQUEST from %pM for ttvn: %u (%pM) [%c]\n",
1739 tt_request->src, tt_request->ttvn, tt_request->dst, 1742 req_src, tt_data->ttvn, req_dst,
1740 (tt_request->flags & BATADV_TT_FULL_TABLE ? 'F' : '.')); 1743 (tt_data->flags & BATADV_TT_FULL_TABLE ? 'F' : '.'));
1741 1744
1742 /* Let's get the orig node of the REAL destination */ 1745 /* Let's get the orig node of the REAL destination */
1743 req_dst_orig_node = batadv_orig_hash_find(bat_priv, tt_request->dst); 1746 req_dst_orig_node = batadv_orig_hash_find(bat_priv, req_dst);
1744 if (!req_dst_orig_node) 1747 if (!req_dst_orig_node)
1745 goto out; 1748 goto out;
1746 1749
1747 res_dst_orig_node = batadv_orig_hash_find(bat_priv, tt_request->src); 1750 res_dst_orig_node = batadv_orig_hash_find(bat_priv, req_src);
1748 if (!res_dst_orig_node) 1751 if (!res_dst_orig_node)
1749 goto out; 1752 goto out;
1750 1753
1751 orig_ttvn = (uint8_t)atomic_read(&req_dst_orig_node->last_ttvn); 1754 orig_ttvn = (uint8_t)atomic_read(&req_dst_orig_node->last_ttvn);
1752 req_ttvn = tt_request->ttvn; 1755 req_ttvn = tt_data->ttvn;
1753 1756
1754 /* I don't have the requested data */ 1757 /* this node doesn't have the requested data */
1755 if (orig_ttvn != req_ttvn || 1758 if (orig_ttvn != req_ttvn ||
1756 tt_request->tt_data != htons(req_dst_orig_node->tt_crc)) 1759 tt_data->crc != htons(req_dst_orig_node->tt_crc))
1757 goto out; 1760 goto out;
1758 1761
1759 /* If the full table has been explicitly requested */ 1762 /* If the full table has been explicitly requested */
1760 if (tt_request->flags & BATADV_TT_FULL_TABLE || 1763 if (tt_data->flags & BATADV_TT_FULL_TABLE ||
1761 !req_dst_orig_node->tt_buff) 1764 !req_dst_orig_node->tt_buff)
1762 full_table = true; 1765 full_table = true;
1763 else 1766 else
1764 full_table = false; 1767 full_table = false;
1765 1768
1766 /* In this version, fragmentation is not implemented, then 1769 /* TT fragmentation hasn't been implemented yet, so send as many
1767 * I'll send only one packet with as much TT entries as I can 1770 * TT entries fit a single packet as possible only
1768 */ 1771 */
1769 if (!full_table) { 1772 if (!full_table) {
1770 spin_lock_bh(&req_dst_orig_node->tt_buff_lock); 1773 spin_lock_bh(&req_dst_orig_node->tt_buff_lock);
1771 tt_len = req_dst_orig_node->tt_buff_len; 1774 tt_len = req_dst_orig_node->tt_buff_len;
1772 tt_tot = tt_len / sizeof(struct batadv_tt_change);
1773 1775
1774 len = sizeof(*tt_response) + tt_len; 1776 tvlv_tt_data = kzalloc(sizeof(*tvlv_tt_data) + tt_len,
1775 skb = netdev_alloc_skb_ip_align(NULL, len + ETH_HLEN); 1777 GFP_ATOMIC);
1776 if (!skb) 1778 if (!tvlv_tt_data)
1777 goto unlock; 1779 goto unlock;
1778 1780
1779 skb->priority = TC_PRIO_CONTROL;
1780 skb_reserve(skb, ETH_HLEN);
1781 packet_pos = skb_put(skb, len);
1782 tt_response = (struct batadv_tt_query_packet *)packet_pos;
1783 tt_response->ttvn = req_ttvn;
1784 tt_response->tt_data = htons(tt_tot);
1785
1786 tt_buff = skb->data + sizeof(*tt_response);
1787 /* Copy the last orig_node's OGM buffer */ 1781 /* Copy the last orig_node's OGM buffer */
1788 memcpy(tt_buff, req_dst_orig_node->tt_buff, 1782 memcpy(tvlv_tt_data + 1, req_dst_orig_node->tt_buff,
1789 req_dst_orig_node->tt_buff_len); 1783 req_dst_orig_node->tt_buff_len);
1790
1791 spin_unlock_bh(&req_dst_orig_node->tt_buff_lock); 1784 spin_unlock_bh(&req_dst_orig_node->tt_buff_lock);
1792 } else { 1785 } else {
1793 tt_len = (uint16_t)atomic_read(&req_dst_orig_node->tt_size); 1786 tt_len = (uint16_t)atomic_read(&req_dst_orig_node->tt_size);
1794 tt_len *= sizeof(struct batadv_tt_change); 1787 tt_len = batadv_tt_len(tt_len);
1795 ttvn = (uint8_t)atomic_read(&req_dst_orig_node->last_ttvn); 1788
1796 1789 tvlv_tt_data = batadv_tt_tvlv_generate(bat_priv,
1797 skb = batadv_tt_response_fill_table(tt_len, ttvn, 1790 bat_priv->tt.global_hash,
1798 bat_priv->tt.global_hash, 1791 tt_len,
1799 bat_priv, 1792 batadv_tt_global_valid,
1800 batadv_tt_global_valid, 1793 req_dst_orig_node);
1801 req_dst_orig_node); 1794 if (!tvlv_tt_data)
1802 if (!skb)
1803 goto out; 1795 goto out;
1804
1805 tt_response = (struct batadv_tt_query_packet *)skb->data;
1806 } 1796 }
1807 1797
1808 tt_response->header.packet_type = BATADV_TT_QUERY; 1798 tvlv_tt_data->flags = BATADV_TT_RESPONSE;
1809 tt_response->header.version = BATADV_COMPAT_VERSION; 1799 tvlv_tt_data->ttvn = req_ttvn;
1810 tt_response->header.ttl = BATADV_TTL;
1811 memcpy(tt_response->src, req_dst_orig_node->orig, ETH_ALEN);
1812 memcpy(tt_response->dst, tt_request->src, ETH_ALEN);
1813 tt_response->flags = BATADV_TT_RESPONSE;
1814 1800
1815 if (full_table) 1801 if (full_table)
1816 tt_response->flags |= BATADV_TT_FULL_TABLE; 1802 tvlv_tt_data->flags |= BATADV_TT_FULL_TABLE;
1817 1803
1818 batadv_dbg(BATADV_DBG_TT, bat_priv, 1804 batadv_dbg(BATADV_DBG_TT, bat_priv,
1819 "Sending TT_RESPONSE %pM for %pM (ttvn: %u)\n", 1805 "Sending TT_RESPONSE %pM for %pM [%c] (ttvn: %u)\n",
1820 res_dst_orig_node->orig, req_dst_orig_node->orig, req_ttvn); 1806 res_dst_orig_node->orig, req_dst_orig_node->orig,
1807 full_table ? 'F' : '.', req_ttvn);
1821 1808
1822 batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_TX); 1809 batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_TX);
1823 1810
1824 res = batadv_send_skb_to_orig(skb, res_dst_orig_node, NULL); 1811 batadv_tvlv_unicast_send(bat_priv, req_dst_orig_node->orig,
1825 if (res != NET_XMIT_DROP) 1812 req_src, BATADV_TVLV_TT, 1,
1826 ret = true; 1813 tvlv_tt_data, sizeof(*tvlv_tt_data) + tt_len);
1827 1814
1815 ret = true;
1828 goto out; 1816 goto out;
1829 1817
1830unlock: 1818unlock:
@@ -1835,37 +1823,40 @@ out:
1835 batadv_orig_node_free_ref(res_dst_orig_node); 1823 batadv_orig_node_free_ref(res_dst_orig_node);
1836 if (req_dst_orig_node) 1824 if (req_dst_orig_node)
1837 batadv_orig_node_free_ref(req_dst_orig_node); 1825 batadv_orig_node_free_ref(req_dst_orig_node);
1838 if (!ret) 1826 kfree(tvlv_tt_data);
1839 kfree_skb(skb);
1840 return ret; 1827 return ret;
1841} 1828}
1842 1829
1843static bool 1830/**
1844batadv_send_my_tt_response(struct batadv_priv *bat_priv, 1831 * batadv_send_my_tt_response - send reply to tt request concerning this node's
1845 struct batadv_tt_query_packet *tt_request) 1832 * translation table
1833 * @bat_priv: the bat priv with all the soft interface information
1834 * @tt_data: tt data containing the tt request information
1835 * @req_src: mac address of tt request sender
1836 *
1837 * Returns true if tt request reply was sent, false otherwise.
1838 */
1839static bool batadv_send_my_tt_response(struct batadv_priv *bat_priv,
1840 struct batadv_tvlv_tt_data *tt_data,
1841 uint8_t *req_src)
1846{ 1842{
1843 struct batadv_tvlv_tt_data *tvlv_tt_data = NULL;
1847 struct batadv_orig_node *orig_node; 1844 struct batadv_orig_node *orig_node;
1848 struct batadv_hard_iface *primary_if = NULL; 1845 struct batadv_hard_iface *primary_if = NULL;
1849 uint8_t my_ttvn, req_ttvn, ttvn; 1846 uint8_t my_ttvn, req_ttvn;
1850 int ret = false;
1851 unsigned char *tt_buff;
1852 bool full_table; 1847 bool full_table;
1853 uint16_t tt_len, tt_tot; 1848 uint16_t tt_len;
1854 struct sk_buff *skb = NULL;
1855 struct batadv_tt_query_packet *tt_response;
1856 uint8_t *packet_pos;
1857 size_t len;
1858 1849
1859 batadv_dbg(BATADV_DBG_TT, bat_priv, 1850 batadv_dbg(BATADV_DBG_TT, bat_priv,
1860 "Received TT_REQUEST from %pM for ttvn: %u (me) [%c]\n", 1851 "Received TT_REQUEST from %pM for ttvn: %u (me) [%c]\n",
1861 tt_request->src, tt_request->ttvn, 1852 req_src, tt_data->ttvn,
1862 (tt_request->flags & BATADV_TT_FULL_TABLE ? 'F' : '.')); 1853 (tt_data->flags & BATADV_TT_FULL_TABLE ? 'F' : '.'));
1863 1854
1864 1855
1865 my_ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn); 1856 my_ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn);
1866 req_ttvn = tt_request->ttvn; 1857 req_ttvn = tt_data->ttvn;
1867 1858
1868 orig_node = batadv_orig_hash_find(bat_priv, tt_request->src); 1859 orig_node = batadv_orig_hash_find(bat_priv, req_src);
1869 if (!orig_node) 1860 if (!orig_node)
1870 goto out; 1861 goto out;
1871 1862
@@ -1876,71 +1867,58 @@ batadv_send_my_tt_response(struct batadv_priv *bat_priv,
1876 /* If the full table has been explicitly requested or the gap 1867 /* If the full table has been explicitly requested or the gap
1877 * is too big send the whole local translation table 1868 * is too big send the whole local translation table
1878 */ 1869 */
1879 if (tt_request->flags & BATADV_TT_FULL_TABLE || my_ttvn != req_ttvn || 1870 if (tt_data->flags & BATADV_TT_FULL_TABLE || my_ttvn != req_ttvn ||
1880 !bat_priv->tt.last_changeset) 1871 !bat_priv->tt.last_changeset)
1881 full_table = true; 1872 full_table = true;
1882 else 1873 else
1883 full_table = false; 1874 full_table = false;
1884 1875
1885 /* In this version, fragmentation is not implemented, then 1876 /* TT fragmentation hasn't been implemented yet, so send as many
1886 * I'll send only one packet with as much TT entries as I can 1877 * TT entries fit a single packet as possible only
1887 */ 1878 */
1888 if (!full_table) { 1879 if (!full_table) {
1889 spin_lock_bh(&bat_priv->tt.last_changeset_lock); 1880 spin_lock_bh(&bat_priv->tt.last_changeset_lock);
1890 tt_len = bat_priv->tt.last_changeset_len; 1881 tt_len = bat_priv->tt.last_changeset_len;
1891 tt_tot = tt_len / sizeof(struct batadv_tt_change);
1892 1882
1893 len = sizeof(*tt_response) + tt_len; 1883 tvlv_tt_data = kzalloc(sizeof(*tvlv_tt_data) + tt_len,
1894 skb = netdev_alloc_skb_ip_align(NULL, len + ETH_HLEN); 1884 GFP_ATOMIC);
1895 if (!skb) 1885 if (!tvlv_tt_data)
1896 goto unlock; 1886 goto unlock;
1897 1887
1898 skb->priority = TC_PRIO_CONTROL; 1888 /* Copy the last orig_node's OGM buffer */
1899 skb_reserve(skb, ETH_HLEN); 1889 memcpy(tvlv_tt_data + 1, bat_priv->tt.last_changeset,
1900 packet_pos = skb_put(skb, len);
1901 tt_response = (struct batadv_tt_query_packet *)packet_pos;
1902 tt_response->ttvn = req_ttvn;
1903 tt_response->tt_data = htons(tt_tot);
1904
1905 tt_buff = skb->data + sizeof(*tt_response);
1906 memcpy(tt_buff, bat_priv->tt.last_changeset,
1907 bat_priv->tt.last_changeset_len); 1890 bat_priv->tt.last_changeset_len);
1908 spin_unlock_bh(&bat_priv->tt.last_changeset_lock); 1891 spin_unlock_bh(&bat_priv->tt.last_changeset_lock);
1909 } else { 1892 } else {
1910 tt_len = (uint16_t)atomic_read(&bat_priv->tt.local_entry_num); 1893 tt_len = (uint16_t)atomic_read(&bat_priv->tt.local_entry_num);
1911 tt_len *= sizeof(struct batadv_tt_change); 1894 tt_len = batadv_tt_len(tt_len);
1912 ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn); 1895 req_ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn);
1913 1896
1914 skb = batadv_tt_response_fill_table(tt_len, ttvn, 1897 tvlv_tt_data = batadv_tt_tvlv_generate(bat_priv,
1915 bat_priv->tt.local_hash, 1898 bat_priv->tt.local_hash,
1916 bat_priv, 1899 tt_len,
1917 batadv_tt_local_valid_entry, 1900 batadv_tt_local_valid,
1918 NULL); 1901 NULL);
1919 if (!skb) 1902 if (!tvlv_tt_data)
1920 goto out; 1903 goto out;
1921
1922 tt_response = (struct batadv_tt_query_packet *)skb->data;
1923 } 1904 }
1924 1905
1925 tt_response->header.packet_type = BATADV_TT_QUERY; 1906 tvlv_tt_data->flags = BATADV_TT_RESPONSE;
1926 tt_response->header.version = BATADV_COMPAT_VERSION; 1907 tvlv_tt_data->ttvn = req_ttvn;
1927 tt_response->header.ttl = BATADV_TTL;
1928 memcpy(tt_response->src, primary_if->net_dev->dev_addr, ETH_ALEN);
1929 memcpy(tt_response->dst, tt_request->src, ETH_ALEN);
1930 tt_response->flags = BATADV_TT_RESPONSE;
1931 1908
1932 if (full_table) 1909 if (full_table)
1933 tt_response->flags |= BATADV_TT_FULL_TABLE; 1910 tvlv_tt_data->flags |= BATADV_TT_FULL_TABLE;
1934 1911
1935 batadv_dbg(BATADV_DBG_TT, bat_priv, 1912 batadv_dbg(BATADV_DBG_TT, bat_priv,
1936 "Sending TT_RESPONSE to %pM [%c]\n", 1913 "Sending TT_RESPONSE to %pM [%c] (ttvn: %u)\n",
1937 orig_node->orig, 1914 orig_node->orig, full_table ? 'F' : '.', req_ttvn);
1938 (tt_response->flags & BATADV_TT_FULL_TABLE ? 'F' : '.'));
1939 1915
1940 batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_TX); 1916 batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_TX);
1941 1917
1942 if (batadv_send_skb_to_orig(skb, orig_node, NULL) != NET_XMIT_DROP) 1918 batadv_tvlv_unicast_send(bat_priv, primary_if->net_dev->dev_addr,
1943 ret = true; 1919 req_src, BATADV_TVLV_TT, 1,
1920 tvlv_tt_data, sizeof(*tvlv_tt_data) + tt_len);
1921
1944 goto out; 1922 goto out;
1945 1923
1946unlock: 1924unlock:
@@ -1950,29 +1928,39 @@ out:
1950 batadv_orig_node_free_ref(orig_node); 1928 batadv_orig_node_free_ref(orig_node);
1951 if (primary_if) 1929 if (primary_if)
1952 batadv_hardif_free_ref(primary_if); 1930 batadv_hardif_free_ref(primary_if);
1953 if (!ret) 1931 kfree(tvlv_tt_data);
1954 kfree_skb(skb); 1932 /* The packet was for this host, so it doesn't need to be re-routed */
1955 /* This packet was for me, so it doesn't need to be re-routed */
1956 return true; 1933 return true;
1957} 1934}
1958 1935
1959bool batadv_send_tt_response(struct batadv_priv *bat_priv, 1936/**
1960 struct batadv_tt_query_packet *tt_request) 1937 * batadv_send_tt_response - send reply to tt request
1938 * @bat_priv: the bat priv with all the soft interface information
1939 * @tt_data: tt data containing the tt request information
1940 * @req_src: mac address of tt request sender
1941 * @req_dst: mac address of tt request recipient
1942 *
1943 * Returns true if tt request reply was sent, false otherwise.
1944 */
1945static bool batadv_send_tt_response(struct batadv_priv *bat_priv,
1946 struct batadv_tvlv_tt_data *tt_data,
1947 uint8_t *req_src, uint8_t *req_dst)
1961{ 1948{
1962 if (batadv_is_my_mac(bat_priv, tt_request->dst)) { 1949 if (batadv_is_my_mac(bat_priv, req_dst)) {
1963 /* don't answer backbone gws! */ 1950 /* don't answer backbone gws! */
1964 if (batadv_bla_is_backbone_gw_orig(bat_priv, tt_request->src)) 1951 if (batadv_bla_is_backbone_gw_orig(bat_priv, req_src))
1965 return true; 1952 return true;
1966 1953
1967 return batadv_send_my_tt_response(bat_priv, tt_request); 1954 return batadv_send_my_tt_response(bat_priv, tt_data, req_src);
1968 } else { 1955 } else {
1969 return batadv_send_other_tt_response(bat_priv, tt_request); 1956 return batadv_send_other_tt_response(bat_priv, tt_data,
1957 req_src, req_dst);
1970 } 1958 }
1971} 1959}
1972 1960
1973static void _batadv_tt_update_changes(struct batadv_priv *bat_priv, 1961static void _batadv_tt_update_changes(struct batadv_priv *bat_priv,
1974 struct batadv_orig_node *orig_node, 1962 struct batadv_orig_node *orig_node,
1975 struct batadv_tt_change *tt_change, 1963 struct batadv_tvlv_tt_change *tt_change,
1976 uint16_t tt_num_changes, uint8_t ttvn) 1964 uint16_t tt_num_changes, uint8_t ttvn)
1977{ 1965{
1978 int i; 1966 int i;
@@ -2002,11 +1990,12 @@ static void _batadv_tt_update_changes(struct batadv_priv *bat_priv,
2002} 1990}
2003 1991
2004static void batadv_tt_fill_gtable(struct batadv_priv *bat_priv, 1992static void batadv_tt_fill_gtable(struct batadv_priv *bat_priv,
2005 struct batadv_tt_query_packet *tt_response) 1993 struct batadv_tvlv_tt_data *tt_data,
1994 uint8_t *resp_src, uint16_t num_entries)
2006{ 1995{
2007 struct batadv_orig_node *orig_node; 1996 struct batadv_orig_node *orig_node;
2008 1997
2009 orig_node = batadv_orig_hash_find(bat_priv, tt_response->src); 1998 orig_node = batadv_orig_hash_find(bat_priv, resp_src);
2010 if (!orig_node) 1999 if (!orig_node)
2011 goto out; 2000 goto out;
2012 2001
@@ -2014,9 +2003,8 @@ static void batadv_tt_fill_gtable(struct batadv_priv *bat_priv,
2014 batadv_tt_global_del_orig(bat_priv, orig_node, "Received full table"); 2003 batadv_tt_global_del_orig(bat_priv, orig_node, "Received full table");
2015 2004
2016 _batadv_tt_update_changes(bat_priv, orig_node, 2005 _batadv_tt_update_changes(bat_priv, orig_node,
2017 (struct batadv_tt_change *)(tt_response + 1), 2006 (struct batadv_tvlv_tt_change *)(tt_data + 1),
2018 ntohs(tt_response->tt_data), 2007 num_entries, tt_data->ttvn);
2019 tt_response->ttvn);
2020 2008
2021 spin_lock_bh(&orig_node->tt_buff_lock); 2009 spin_lock_bh(&orig_node->tt_buff_lock);
2022 kfree(orig_node->tt_buff); 2010 kfree(orig_node->tt_buff);
@@ -2024,7 +2012,7 @@ static void batadv_tt_fill_gtable(struct batadv_priv *bat_priv,
2024 orig_node->tt_buff = NULL; 2012 orig_node->tt_buff = NULL;
2025 spin_unlock_bh(&orig_node->tt_buff_lock); 2013 spin_unlock_bh(&orig_node->tt_buff_lock);
2026 2014
2027 atomic_set(&orig_node->last_ttvn, tt_response->ttvn); 2015 atomic_set(&orig_node->last_ttvn, tt_data->ttvn);
2028 2016
2029out: 2017out:
2030 if (orig_node) 2018 if (orig_node)
@@ -2034,7 +2022,7 @@ out:
2034static void batadv_tt_update_changes(struct batadv_priv *bat_priv, 2022static void batadv_tt_update_changes(struct batadv_priv *bat_priv,
2035 struct batadv_orig_node *orig_node, 2023 struct batadv_orig_node *orig_node,
2036 uint16_t tt_num_changes, uint8_t ttvn, 2024 uint16_t tt_num_changes, uint8_t ttvn,
2037 struct batadv_tt_change *tt_change) 2025 struct batadv_tvlv_tt_change *tt_change)
2038{ 2026{
2039 _batadv_tt_update_changes(bat_priv, orig_node, tt_change, 2027 _batadv_tt_update_changes(bat_priv, orig_node, tt_change,
2040 tt_num_changes, ttvn); 2028 tt_num_changes, ttvn);
@@ -2065,40 +2053,46 @@ out:
2065 return ret; 2053 return ret;
2066} 2054}
2067 2055
2068void batadv_handle_tt_response(struct batadv_priv *bat_priv, 2056/**
2069 struct batadv_tt_query_packet *tt_response) 2057 * batadv_handle_tt_response - process incoming tt reply
2058 * @bat_priv: the bat priv with all the soft interface information
2059 * @tt_data: tt data containing the tt request information
2060 * @resp_src: mac address of tt reply sender
2061 * @num_entries: number of tt change entries appended to the tt data
2062 */
2063static void batadv_handle_tt_response(struct batadv_priv *bat_priv,
2064 struct batadv_tvlv_tt_data *tt_data,
2065 uint8_t *resp_src, uint16_t num_entries)
2070{ 2066{
2071 struct batadv_tt_req_node *node, *safe; 2067 struct batadv_tt_req_node *node, *safe;
2072 struct batadv_orig_node *orig_node = NULL; 2068 struct batadv_orig_node *orig_node = NULL;
2073 struct batadv_tt_change *tt_change; 2069 struct batadv_tvlv_tt_change *tt_change;
2074 2070
2075 batadv_dbg(BATADV_DBG_TT, bat_priv, 2071 batadv_dbg(BATADV_DBG_TT, bat_priv,
2076 "Received TT_RESPONSE from %pM for ttvn %d t_size: %d [%c]\n", 2072 "Received TT_RESPONSE from %pM for ttvn %d t_size: %d [%c]\n",
2077 tt_response->src, tt_response->ttvn, 2073 resp_src, tt_data->ttvn, num_entries,
2078 ntohs(tt_response->tt_data), 2074 (tt_data->flags & BATADV_TT_FULL_TABLE ? 'F' : '.'));
2079 (tt_response->flags & BATADV_TT_FULL_TABLE ? 'F' : '.'));
2080 2075
2081 /* we should have never asked a backbone gw */ 2076 /* we should have never asked a backbone gw */
2082 if (batadv_bla_is_backbone_gw_orig(bat_priv, tt_response->src)) 2077 if (batadv_bla_is_backbone_gw_orig(bat_priv, resp_src))
2083 goto out; 2078 goto out;
2084 2079
2085 orig_node = batadv_orig_hash_find(bat_priv, tt_response->src); 2080 orig_node = batadv_orig_hash_find(bat_priv, resp_src);
2086 if (!orig_node) 2081 if (!orig_node)
2087 goto out; 2082 goto out;
2088 2083
2089 if (tt_response->flags & BATADV_TT_FULL_TABLE) { 2084 if (tt_data->flags & BATADV_TT_FULL_TABLE) {
2090 batadv_tt_fill_gtable(bat_priv, tt_response); 2085 batadv_tt_fill_gtable(bat_priv, tt_data, resp_src, num_entries);
2091 } else { 2086 } else {
2092 tt_change = (struct batadv_tt_change *)(tt_response + 1); 2087 tt_change = (struct batadv_tvlv_tt_change *)(tt_data + 1);
2093 batadv_tt_update_changes(bat_priv, orig_node, 2088 batadv_tt_update_changes(bat_priv, orig_node, num_entries,
2094 ntohs(tt_response->tt_data), 2089 tt_data->ttvn, tt_change);
2095 tt_response->ttvn, tt_change);
2096 } 2090 }
2097 2091
2098 /* Delete the tt_req_node from pending tt_requests list */ 2092 /* Delete the tt_req_node from pending tt_requests list */
2099 spin_lock_bh(&bat_priv->tt.req_list_lock); 2093 spin_lock_bh(&bat_priv->tt.req_list_lock);
2100 list_for_each_entry_safe(node, safe, &bat_priv->tt.req_list, list) { 2094 list_for_each_entry_safe(node, safe, &bat_priv->tt.req_list, list) {
2101 if (!batadv_compare_eth(node->addr, tt_response->src)) 2095 if (!batadv_compare_eth(node->addr, resp_src))
2102 continue; 2096 continue;
2103 list_del(&node->list); 2097 list_del(&node->list);
2104 kfree(node); 2098 kfree(node);
@@ -2437,7 +2431,7 @@ static void batadv_tt_update_orig(struct batadv_priv *bat_priv,
2437{ 2431{
2438 uint8_t orig_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn); 2432 uint8_t orig_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn);
2439 bool full_table = true; 2433 bool full_table = true;
2440 struct batadv_tt_change *tt_change; 2434 struct batadv_tvlv_tt_change *tt_change;
2441 2435
2442 /* don't care about a backbone gateways updates. */ 2436 /* don't care about a backbone gateways updates. */
2443 if (batadv_bla_is_backbone_gw_orig(bat_priv, orig_node->orig)) 2437 if (batadv_bla_is_backbone_gw_orig(bat_priv, orig_node->orig))
@@ -2458,7 +2452,7 @@ static void batadv_tt_update_orig(struct batadv_priv *bat_priv,
2458 goto request_table; 2452 goto request_table;
2459 } 2453 }
2460 2454
2461 tt_change = (struct batadv_tt_change *)tt_buff; 2455 tt_change = (struct batadv_tvlv_tt_change *)tt_buff;
2462 batadv_tt_update_changes(bat_priv, orig_node, tt_num_changes, 2456 batadv_tt_update_changes(bat_priv, orig_node, tt_num_changes,
2463 ttvn, tt_change); 2457 ttvn, tt_change);
2464 2458
@@ -2599,6 +2593,81 @@ static void batadv_tt_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv,
2599} 2593}
2600 2594
2601/** 2595/**
2596 * batadv_tt_tvlv_unicast_handler_v1 - process incoming (unicast) tt tvlv
2597 * container
2598 * @bat_priv: the bat priv with all the soft interface information
2599 * @src: mac address of tt tvlv sender
2600 * @dst: mac address of tt tvlv recipient
2601 * @tvlv_value: tvlv buffer containing the tt data
2602 * @tvlv_value_len: tvlv buffer length
2603 *
2604 * Returns NET_RX_DROP if the tt tvlv is to be re-routed, NET_RX_SUCCESS
2605 * otherwise.
2606 */
2607static int batadv_tt_tvlv_unicast_handler_v1(struct batadv_priv *bat_priv,
2608 uint8_t *src, uint8_t *dst,
2609 void *tvlv_value,
2610 uint16_t tvlv_value_len)
2611{
2612 struct batadv_tvlv_tt_data *tt_data;
2613 uint16_t num_entries;
2614 char tt_flag;
2615 bool ret;
2616
2617 if (tvlv_value_len < sizeof(*tt_data))
2618 return NET_RX_SUCCESS;
2619
2620 tt_data = (struct batadv_tvlv_tt_data *)tvlv_value;
2621 tvlv_value_len -= sizeof(*tt_data);
2622
2623 num_entries = tvlv_value_len / batadv_tt_len(1);
2624
2625 switch (tt_data->flags & BATADV_TT_DATA_TYPE_MASK) {
2626 case BATADV_TT_REQUEST:
2627 batadv_inc_counter(bat_priv, BATADV_CNT_TT_REQUEST_RX);
2628
2629 /* If this node cannot provide a TT response the tt_request is
2630 * forwarded
2631 */
2632 ret = batadv_send_tt_response(bat_priv, tt_data, src, dst);
2633 if (!ret) {
2634 if (tt_data->flags & BATADV_TT_FULL_TABLE)
2635 tt_flag = 'F';
2636 else
2637 tt_flag = '.';
2638
2639 batadv_dbg(BATADV_DBG_TT, bat_priv,
2640 "Routing TT_REQUEST to %pM [%c]\n",
2641 dst, tt_flag);
2642 /* tvlv API will re-route the packet */
2643 return NET_RX_DROP;
2644 }
2645 break;
2646 case BATADV_TT_RESPONSE:
2647 batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_RX);
2648
2649 if (batadv_is_my_mac(bat_priv, dst)) {
2650 batadv_handle_tt_response(bat_priv, tt_data,
2651 src, num_entries);
2652 return NET_RX_SUCCESS;
2653 }
2654
2655 if (tt_data->flags & BATADV_TT_FULL_TABLE)
2656 tt_flag = 'F';
2657 else
2658 tt_flag = '.';
2659
2660 batadv_dbg(BATADV_DBG_TT, bat_priv,
2661 "Routing TT_RESPONSE to %pM [%c]\n", dst, tt_flag);
2662
2663 /* tvlv API will re-route the packet */
2664 return NET_RX_DROP;
2665 }
2666
2667 return NET_RX_SUCCESS;
2668}
2669
2670/**
2602 * batadv_tt_init - initialise the translation table internals 2671 * batadv_tt_init - initialise the translation table internals
2603 * @bat_priv: the bat priv with all the soft interface information 2672 * @bat_priv: the bat priv with all the soft interface information
2604 * 2673 *
@@ -2617,7 +2686,8 @@ int batadv_tt_init(struct batadv_priv *bat_priv)
2617 return ret; 2686 return ret;
2618 2687
2619 batadv_tvlv_handler_register(bat_priv, batadv_tt_tvlv_ogm_handler_v1, 2688 batadv_tvlv_handler_register(bat_priv, batadv_tt_tvlv_ogm_handler_v1,
2620 NULL, BATADV_TVLV_TT, 1, BATADV_NO_FLAGS); 2689 batadv_tt_tvlv_unicast_handler_v1,
2690 BATADV_TVLV_TT, 1, BATADV_NO_FLAGS);
2621 2691
2622 INIT_DELAYED_WORK(&bat_priv->tt.work, batadv_tt_purge); 2692 INIT_DELAYED_WORK(&bat_priv->tt.work, batadv_tt_purge);
2623 queue_delayed_work(batadv_event_workqueue, &bat_priv->tt.work, 2693 queue_delayed_work(batadv_event_workqueue, &bat_priv->tt.work,