-From: Linus Lüssing <linus.luessing@c0d3.blue>
-Date: Thu, 10 May 2018 19:44:28 +0200
-Subject: [PATCH] batman-adv: Fix TT sync flags for intermediate TT responses
-
-The previous TT sync fix so far only fixed TT responses issued by the
-target node directly. So far, TT responses issued by intermediate nodes
-still lead to the wrong flags being added, leading to CRC mismatches.
-
-This behaviour was observed at Freifunk Hannover in a 800 nodes setup
-where a considerable amount of nodes were still infected with 'WI'
-TT flags even with (most) nodes having the previous TT sync fix applied.
-
-I was able to reproduce the issue with intermediate TT responses in a
-four node test setup and this patch fixes this issue by ensuring to
-use the per originator instead of the summarized, OR'd ones.
-
-Fixes: fa614fd04692 ("batman-adv: fix tt_global_entries flags update")
-Signed-off-by: Linus Lüssing <linus.luessing@c0d3.blue>
-Signed-off-by: Sven Eckelmann <sven@narfation.org>
-
-Origin: upstream, https://git.open-mesh.org/batman-adv.git/commit/d65daee8617b29c1ddcc949ce3a5ec24f7a1e1af
----
- net/batman-adv/translation-table.c | 61 +++++++++++++++++++++++++-----
- 1 file changed, 51 insertions(+), 10 deletions(-)
-
-diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
-index 7fa3a0a0524a1da63e92d081b443c302900bf0c3..23f9c212ab1e27be429645a85f7b5d6a02585de9 100644
---- a/net/batman-adv/translation-table.c
-+++ b/net/batman-adv/translation-table.c
-@@ -1538,6 +1538,8 @@ batadv_tt_global_orig_entry_find(const struct batadv_tt_global_entry *entry,
- * handled by a given originator
- * @entry: the TT global entry to check
- * @orig_node: the originator to search in the list
-+ * @flags: a pointer to store TT flags for the given @entry received
-+ * from @orig_node
- *
- * find out if an orig_node is already in the list of a tt_global_entry.
- *
-@@ -1545,7 +1547,8 @@ batadv_tt_global_orig_entry_find(const struct batadv_tt_global_entry *entry,
- */
- static bool
- batadv_tt_global_entry_has_orig(const struct batadv_tt_global_entry *entry,
-- const struct batadv_orig_node *orig_node)
-+ const struct batadv_orig_node *orig_node,
-+ u8 *flags)
- {
- struct batadv_tt_orig_list_entry *orig_entry;
- bool found = false;
-@@ -1553,6 +1556,10 @@ batadv_tt_global_entry_has_orig(const struct batadv_tt_global_entry *entry,
- orig_entry = batadv_tt_global_orig_entry_find(entry, orig_node);
- if (orig_entry) {
- found = true;
-+
-+ if (flags)
-+ *flags = orig_entry->flags;
-+
- batadv_tt_orig_list_entry_put(orig_entry);
- }
-
-@@ -1731,7 +1738,7 @@ static bool batadv_tt_global_add(struct batadv_priv *bat_priv,
- if (!(common->flags & BATADV_TT_CLIENT_TEMP))
- goto out;
- if (batadv_tt_global_entry_has_orig(tt_global_entry,
-- orig_node))
-+ orig_node, NULL))
- goto out_remove;
- batadv_tt_global_del_orig_list(tt_global_entry);
- goto add_orig_entry;
-@@ -2880,23 +2887,46 @@ batadv_tt_req_node_new(struct batadv_priv *bat_priv,
- }
-
- /**
-- * batadv_tt_local_valid() - verify that given tt entry is a valid one
-+ * batadv_tt_local_valid() - verify local tt entry and get flags
- * @entry_ptr: to be checked local tt entry
- * @data_ptr: not used but definition required to satisfy the callback prototype
-+ * @flags: a pointer to store TT flags for this client to
-+ *
-+ * Checks the validity of the given local TT entry. If it is, then the provided
-+ * flags pointer is updated.
- *
- * Return: true if the entry is a valid, false otherwise.
- */
--static bool batadv_tt_local_valid(const void *entry_ptr, const void *data_ptr)
-+static bool batadv_tt_local_valid(const void *entry_ptr,
-+ const void *data_ptr,
-+ u8 *flags)
- {
- const struct batadv_tt_common_entry *tt_common_entry = entry_ptr;
-
- if (tt_common_entry->flags & BATADV_TT_CLIENT_NEW)
- return false;
-+
-+ if (flags)
-+ *flags = tt_common_entry->flags;
-+
- return true;
- }
-
-+/**
-+ * batadv_tt_global_valid() - verify global tt entry and get flags
-+ * @entry_ptr: to be checked global tt entry
-+ * @data_ptr: an orig_node object (may be NULL)
-+ * @flags: a pointer to store TT flags for this client to
-+ *
-+ * Checks the validity of the given global TT entry. If it is, then the provided
-+ * flags pointer is updated either with the common (summed) TT flags if data_ptr
-+ * is NULL or the specific, per originator TT flags otherwise.
-+ *
-+ * Return: true if the entry is a valid, false otherwise.
-+ */
- static bool batadv_tt_global_valid(const void *entry_ptr,
-- const void *data_ptr)
-+ const void *data_ptr,
-+ u8 *flags)
- {
- const struct batadv_tt_common_entry *tt_common_entry = entry_ptr;
- const struct batadv_tt_global_entry *tt_global_entry;
-@@ -2910,7 +2940,8 @@ static bool batadv_tt_global_valid(const void *entry_ptr,
- struct batadv_tt_global_entry,
- common);
-
-- return batadv_tt_global_entry_has_orig(tt_global_entry, orig_node);
-+ return batadv_tt_global_entry_has_orig(tt_global_entry, orig_node,
-+ flags);
- }
-
- /**
-@@ -2920,25 +2951,34 @@ static bool batadv_tt_global_valid(const void *entry_ptr,
- * @hash: hash table containing the tt entries
- * @tt_len: expected tvlv tt data buffer length in number of bytes
- * @tvlv_buff: pointer to the buffer to fill with the TT data
-- * @valid_cb: function to filter tt change entries
-+ * @valid_cb: function to filter tt change entries and to return TT flags
- * @cb_data: data passed to the filter function as argument
-+ *
-+ * Fills the tvlv buff with the tt entries from the specified hash. If valid_cb
-+ * is not provided then this becomes a no-op.
- */
- static void batadv_tt_tvlv_generate(struct batadv_priv *bat_priv,
- struct batadv_hashtable *hash,
- void *tvlv_buff, u16 tt_len,
- bool (*valid_cb)(const void *,
-- const void *),
-+ const void *,
-+ u8 *flags),
- void *cb_data)
- {
- struct batadv_tt_common_entry *tt_common_entry;
- struct batadv_tvlv_tt_change *tt_change;
- struct hlist_head *head;
- u16 tt_tot, tt_num_entries = 0;
-+ u8 flags;
-+ bool ret;
- u32 i;
-
- tt_tot = batadv_tt_entries(tt_len);
- tt_change = (struct batadv_tvlv_tt_change *)tvlv_buff;
-
-+ if (!valid_cb)
-+ return;
-+
- rcu_read_lock();
- for (i = 0; i < hash->size; i++) {
- head = &hash->table[i];
-@@ -2948,11 +2988,12 @@ static void batadv_tt_tvlv_generate(struct batadv_priv *bat_priv,
- if (tt_tot == tt_num_entries)
- break;
-
-- if ((valid_cb) && (!valid_cb(tt_common_entry, cb_data)))
-+ ret = valid_cb(tt_common_entry, cb_data, &flags);
-+ if (!ret)
- continue;
-
- ether_addr_copy(tt_change->addr, tt_common_entry->addr);
-- tt_change->flags = tt_common_entry->flags;
-+ tt_change->flags = flags;
- tt_change->vid = htons(tt_common_entry->vid);
- memset(tt_change->reserved, 0,
- sizeof(tt_change->reserved));