diff options
author | David S. Miller <davem@davemloft.net> | 2017-08-03 12:23:11 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2017-08-03 12:23:11 -0400 |
commit | 4d2bbb0ef88ffd4bc91e3d39917d2dd49dddf054 (patch) | |
tree | 5efc9de0fd3007c145712ee6b02d0dac4b447f29 | |
parent | ed254971edea92c3ac5c67c6a05247a92aa6075e (diff) | |
parent | 54e22f265e872ae140755b3318521d400a094605 (diff) |
Merge tag 'batadv-net-for-davem-20170802' of git://git.open-mesh.org/linux-merge
Simon Wunderlich says:
====================
Here is a batman-adv bugfix:
- fix TT sync flag inconsistency problems, which can lead to excess packets,
by Linus Luessing
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/batman-adv/translation-table.c | 60 | ||||
-rw-r--r-- | net/batman-adv/types.h | 2 |
2 files changed, 53 insertions, 9 deletions
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index e1133bc634b5..8a3ce79b1307 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c | |||
@@ -1549,9 +1549,41 @@ batadv_tt_global_entry_has_orig(const struct batadv_tt_global_entry *entry, | |||
1549 | return found; | 1549 | return found; |
1550 | } | 1550 | } |
1551 | 1551 | ||
1552 | /** | ||
1553 | * batadv_tt_global_sync_flags - update TT sync flags | ||
1554 | * @tt_global: the TT global entry to update sync flags in | ||
1555 | * | ||
1556 | * Updates the sync flag bits in the tt_global flag attribute with a logical | ||
1557 | * OR of all sync flags from any of its TT orig entries. | ||
1558 | */ | ||
1559 | static void | ||
1560 | batadv_tt_global_sync_flags(struct batadv_tt_global_entry *tt_global) | ||
1561 | { | ||
1562 | struct batadv_tt_orig_list_entry *orig_entry; | ||
1563 | const struct hlist_head *head; | ||
1564 | u16 flags = BATADV_NO_FLAGS; | ||
1565 | |||
1566 | rcu_read_lock(); | ||
1567 | head = &tt_global->orig_list; | ||
1568 | hlist_for_each_entry_rcu(orig_entry, head, list) | ||
1569 | flags |= orig_entry->flags; | ||
1570 | rcu_read_unlock(); | ||
1571 | |||
1572 | flags |= tt_global->common.flags & (~BATADV_TT_SYNC_MASK); | ||
1573 | tt_global->common.flags = flags; | ||
1574 | } | ||
1575 | |||
1576 | /** | ||
1577 | * batadv_tt_global_orig_entry_add - add or update a TT orig entry | ||
1578 | * @tt_global: the TT global entry to add an orig entry in | ||
1579 | * @orig_node: the originator to add an orig entry for | ||
1580 | * @ttvn: translation table version number of this changeset | ||
1581 | * @flags: TT sync flags | ||
1582 | */ | ||
1552 | static void | 1583 | static void |
1553 | batadv_tt_global_orig_entry_add(struct batadv_tt_global_entry *tt_global, | 1584 | batadv_tt_global_orig_entry_add(struct batadv_tt_global_entry *tt_global, |
1554 | struct batadv_orig_node *orig_node, int ttvn) | 1585 | struct batadv_orig_node *orig_node, int ttvn, |
1586 | u8 flags) | ||
1555 | { | 1587 | { |
1556 | struct batadv_tt_orig_list_entry *orig_entry; | 1588 | struct batadv_tt_orig_list_entry *orig_entry; |
1557 | 1589 | ||
@@ -1561,7 +1593,8 @@ batadv_tt_global_orig_entry_add(struct batadv_tt_global_entry *tt_global, | |||
1561 | * was added during a "temporary client detection" | 1593 | * was added during a "temporary client detection" |
1562 | */ | 1594 | */ |
1563 | orig_entry->ttvn = ttvn; | 1595 | orig_entry->ttvn = ttvn; |
1564 | goto out; | 1596 | orig_entry->flags = flags; |
1597 | goto sync_flags; | ||
1565 | } | 1598 | } |
1566 | 1599 | ||
1567 | orig_entry = kmem_cache_zalloc(batadv_tt_orig_cache, GFP_ATOMIC); | 1600 | orig_entry = kmem_cache_zalloc(batadv_tt_orig_cache, GFP_ATOMIC); |
@@ -1573,6 +1606,7 @@ batadv_tt_global_orig_entry_add(struct batadv_tt_global_entry *tt_global, | |||
1573 | batadv_tt_global_size_inc(orig_node, tt_global->common.vid); | 1606 | batadv_tt_global_size_inc(orig_node, tt_global->common.vid); |
1574 | orig_entry->orig_node = orig_node; | 1607 | orig_entry->orig_node = orig_node; |
1575 | orig_entry->ttvn = ttvn; | 1608 | orig_entry->ttvn = ttvn; |
1609 | orig_entry->flags = flags; | ||
1576 | kref_init(&orig_entry->refcount); | 1610 | kref_init(&orig_entry->refcount); |
1577 | 1611 | ||
1578 | spin_lock_bh(&tt_global->list_lock); | 1612 | spin_lock_bh(&tt_global->list_lock); |
@@ -1582,6 +1616,8 @@ batadv_tt_global_orig_entry_add(struct batadv_tt_global_entry *tt_global, | |||
1582 | spin_unlock_bh(&tt_global->list_lock); | 1616 | spin_unlock_bh(&tt_global->list_lock); |
1583 | atomic_inc(&tt_global->orig_list_count); | 1617 | atomic_inc(&tt_global->orig_list_count); |
1584 | 1618 | ||
1619 | sync_flags: | ||
1620 | batadv_tt_global_sync_flags(tt_global); | ||
1585 | out: | 1621 | out: |
1586 | if (orig_entry) | 1622 | if (orig_entry) |
1587 | batadv_tt_orig_list_entry_put(orig_entry); | 1623 | batadv_tt_orig_list_entry_put(orig_entry); |
@@ -1703,10 +1739,10 @@ static bool batadv_tt_global_add(struct batadv_priv *bat_priv, | |||
1703 | } | 1739 | } |
1704 | 1740 | ||
1705 | /* the change can carry possible "attribute" flags like the | 1741 | /* the change can carry possible "attribute" flags like the |
1706 | * TT_CLIENT_WIFI, therefore they have to be copied in the | 1742 | * TT_CLIENT_TEMP, therefore they have to be copied in the |
1707 | * client entry | 1743 | * client entry |
1708 | */ | 1744 | */ |
1709 | common->flags |= flags; | 1745 | common->flags |= flags & (~BATADV_TT_SYNC_MASK); |
1710 | 1746 | ||
1711 | /* If there is the BATADV_TT_CLIENT_ROAM flag set, there is only | 1747 | /* If there is the BATADV_TT_CLIENT_ROAM flag set, there is only |
1712 | * one originator left in the list and we previously received a | 1748 | * one originator left in the list and we previously received a |
@@ -1723,7 +1759,8 @@ static bool batadv_tt_global_add(struct batadv_priv *bat_priv, | |||
1723 | } | 1759 | } |
1724 | add_orig_entry: | 1760 | add_orig_entry: |
1725 | /* add the new orig_entry (if needed) or update it */ | 1761 | /* add the new orig_entry (if needed) or update it */ |
1726 | batadv_tt_global_orig_entry_add(tt_global_entry, orig_node, ttvn); | 1762 | batadv_tt_global_orig_entry_add(tt_global_entry, orig_node, ttvn, |
1763 | flags & BATADV_TT_SYNC_MASK); | ||
1727 | 1764 | ||
1728 | batadv_dbg(BATADV_DBG_TT, bat_priv, | 1765 | batadv_dbg(BATADV_DBG_TT, bat_priv, |
1729 | "Creating new global tt entry: %pM (vid: %d, via %pM)\n", | 1766 | "Creating new global tt entry: %pM (vid: %d, via %pM)\n", |
@@ -1946,6 +1983,7 @@ batadv_tt_global_dump_subentry(struct sk_buff *msg, u32 portid, u32 seq, | |||
1946 | struct batadv_tt_orig_list_entry *orig, | 1983 | struct batadv_tt_orig_list_entry *orig, |
1947 | bool best) | 1984 | bool best) |
1948 | { | 1985 | { |
1986 | u16 flags = (common->flags & (~BATADV_TT_SYNC_MASK)) | orig->flags; | ||
1949 | void *hdr; | 1987 | void *hdr; |
1950 | struct batadv_orig_node_vlan *vlan; | 1988 | struct batadv_orig_node_vlan *vlan; |
1951 | u8 last_ttvn; | 1989 | u8 last_ttvn; |
@@ -1975,7 +2013,7 @@ batadv_tt_global_dump_subentry(struct sk_buff *msg, u32 portid, u32 seq, | |||
1975 | nla_put_u8(msg, BATADV_ATTR_TT_LAST_TTVN, last_ttvn) || | 2013 | nla_put_u8(msg, BATADV_ATTR_TT_LAST_TTVN, last_ttvn) || |
1976 | nla_put_u32(msg, BATADV_ATTR_TT_CRC32, crc) || | 2014 | nla_put_u32(msg, BATADV_ATTR_TT_CRC32, crc) || |
1977 | nla_put_u16(msg, BATADV_ATTR_TT_VID, common->vid) || | 2015 | nla_put_u16(msg, BATADV_ATTR_TT_VID, common->vid) || |
1978 | nla_put_u32(msg, BATADV_ATTR_TT_FLAGS, common->flags)) | 2016 | nla_put_u32(msg, BATADV_ATTR_TT_FLAGS, flags)) |
1979 | goto nla_put_failure; | 2017 | goto nla_put_failure; |
1980 | 2018 | ||
1981 | if (best && nla_put_flag(msg, BATADV_ATTR_FLAG_BEST)) | 2019 | if (best && nla_put_flag(msg, BATADV_ATTR_FLAG_BEST)) |
@@ -2589,6 +2627,7 @@ static u32 batadv_tt_global_crc(struct batadv_priv *bat_priv, | |||
2589 | unsigned short vid) | 2627 | unsigned short vid) |
2590 | { | 2628 | { |
2591 | struct batadv_hashtable *hash = bat_priv->tt.global_hash; | 2629 | struct batadv_hashtable *hash = bat_priv->tt.global_hash; |
2630 | struct batadv_tt_orig_list_entry *tt_orig; | ||
2592 | struct batadv_tt_common_entry *tt_common; | 2631 | struct batadv_tt_common_entry *tt_common; |
2593 | struct batadv_tt_global_entry *tt_global; | 2632 | struct batadv_tt_global_entry *tt_global; |
2594 | struct hlist_head *head; | 2633 | struct hlist_head *head; |
@@ -2627,8 +2666,9 @@ static u32 batadv_tt_global_crc(struct batadv_priv *bat_priv, | |||
2627 | /* find out if this global entry is announced by this | 2666 | /* find out if this global entry is announced by this |
2628 | * originator | 2667 | * originator |
2629 | */ | 2668 | */ |
2630 | if (!batadv_tt_global_entry_has_orig(tt_global, | 2669 | tt_orig = batadv_tt_global_orig_entry_find(tt_global, |
2631 | orig_node)) | 2670 | orig_node); |
2671 | if (!tt_orig) | ||
2632 | continue; | 2672 | continue; |
2633 | 2673 | ||
2634 | /* use network order to read the VID: this ensures that | 2674 | /* use network order to read the VID: this ensures that |
@@ -2640,10 +2680,12 @@ static u32 batadv_tt_global_crc(struct batadv_priv *bat_priv, | |||
2640 | /* compute the CRC on flags that have to be kept in sync | 2680 | /* compute the CRC on flags that have to be kept in sync |
2641 | * among nodes | 2681 | * among nodes |
2642 | */ | 2682 | */ |
2643 | flags = tt_common->flags & BATADV_TT_SYNC_MASK; | 2683 | flags = tt_orig->flags; |
2644 | crc_tmp = crc32c(crc_tmp, &flags, sizeof(flags)); | 2684 | crc_tmp = crc32c(crc_tmp, &flags, sizeof(flags)); |
2645 | 2685 | ||
2646 | crc ^= crc32c(crc_tmp, tt_common->addr, ETH_ALEN); | 2686 | crc ^= crc32c(crc_tmp, tt_common->addr, ETH_ALEN); |
2687 | |||
2688 | batadv_tt_orig_list_entry_put(tt_orig); | ||
2647 | } | 2689 | } |
2648 | rcu_read_unlock(); | 2690 | rcu_read_unlock(); |
2649 | } | 2691 | } |
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index ea43a6449247..a62795868794 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h | |||
@@ -1260,6 +1260,7 @@ struct batadv_tt_global_entry { | |||
1260 | * struct batadv_tt_orig_list_entry - orig node announcing a non-mesh client | 1260 | * struct batadv_tt_orig_list_entry - orig node announcing a non-mesh client |
1261 | * @orig_node: pointer to orig node announcing this non-mesh client | 1261 | * @orig_node: pointer to orig node announcing this non-mesh client |
1262 | * @ttvn: translation table version number which added the non-mesh client | 1262 | * @ttvn: translation table version number which added the non-mesh client |
1263 | * @flags: per orig entry TT sync flags | ||
1263 | * @list: list node for batadv_tt_global_entry::orig_list | 1264 | * @list: list node for batadv_tt_global_entry::orig_list |
1264 | * @refcount: number of contexts the object is used | 1265 | * @refcount: number of contexts the object is used |
1265 | * @rcu: struct used for freeing in an RCU-safe manner | 1266 | * @rcu: struct used for freeing in an RCU-safe manner |
@@ -1267,6 +1268,7 @@ struct batadv_tt_global_entry { | |||
1267 | struct batadv_tt_orig_list_entry { | 1268 | struct batadv_tt_orig_list_entry { |
1268 | struct batadv_orig_node *orig_node; | 1269 | struct batadv_orig_node *orig_node; |
1269 | u8 ttvn; | 1270 | u8 ttvn; |
1271 | u8 flags; | ||
1270 | struct hlist_node list; | 1272 | struct hlist_node list; |
1271 | struct kref refcount; | 1273 | struct kref refcount; |
1272 | struct rcu_head rcu; | 1274 | struct rcu_head rcu; |