diff options
author | Marek Lindner <lindner_marek@yahoo.de> | 2013-04-23 09:40:02 -0400 |
---|---|---|
committer | Antonio Quartulli <antonio@meshcoding.com> | 2013-10-09 15:22:30 -0400 |
commit | 335fbe0f5d2501b7dd815806aef6fd9bad784eb1 (patch) | |
tree | 6a456167f38f521a58d7fac2fc8a87aec338f0a7 /net/batman-adv/translation-table.c | |
parent | e1bf0c14096f9dc09c7695f42051d178b23d0670 (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.c | 502 |
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 | ||
232 | int 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 | */ | ||
238 | static 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 | ||
237 | static int batadv_tt_local_init(struct batadv_priv *bat_priv) | 243 | static 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 | /** |
1559 | static 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 | */ | ||
1571 | static 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 | ||
1587 | static struct sk_buff * | 1598 | /** |
1588 | batadv_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 | */ | ||
1610 | static struct batadv_tvlv_tt_data * | ||
1611 | batadv_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 | |||
1650 | out: | 1661 | out: |
1651 | return skb; | 1662 | return tvlv_tt_data; |
1652 | } | 1663 | } |
1653 | 1664 | ||
1654 | static int batadv_send_tt_request(struct batadv_priv *bat_priv, | 1665 | static 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 | ||
1707 | out: | 1706 | out: |
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 | ||
1721 | static bool | 1719 | /** |
1722 | batadv_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 | */ | ||
1729 | static 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 | ||
1830 | unlock: | 1818 | unlock: |
@@ -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 | ||
1843 | static bool | 1830 | /** |
1844 | batadv_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 | */ | ||
1839 | static 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 | ||
1946 | unlock: | 1924 | unlock: |
@@ -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 | ||
1959 | bool 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 | */ | ||
1945 | static 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 | ||
1973 | static void _batadv_tt_update_changes(struct batadv_priv *bat_priv, | 1961 | static 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 | ||
2004 | static void batadv_tt_fill_gtable(struct batadv_priv *bat_priv, | 1992 | static 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 | ||
2029 | out: | 2017 | out: |
2030 | if (orig_node) | 2018 | if (orig_node) |
@@ -2034,7 +2022,7 @@ out: | |||
2034 | static void batadv_tt_update_changes(struct batadv_priv *bat_priv, | 2022 | static 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 | ||
2068 | void 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 | */ | ||
2063 | static 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 | */ | ||
2607 | static 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, |