Commit 91bb6f90 authored by Linus Lüssing's avatar Linus Lüssing Committed by Kelsey Skunberg

batman-adv: Fix TT sync flags for intermediate TT responses

BugLink: https://bugs.launchpad.net/bugs/1868629

commit 7072337e upstream.

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: e9c00136 ("batman-adv: fix tt_global_entries flags update")
Reported-by: default avatarLeonardo Mörlein <me@irrelefant.net>
Signed-off-by: default avatarLinus Lüssing <linus.luessing@c0d3.blue>
Signed-off-by: default avatarSven Eckelmann <sven@narfation.org>
Signed-off-by: default avatarSimon Wunderlich <sw@simonwunderlich.de>
Signed-off-by: default avatarSven Eckelmann <sven@narfation.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarKhalid Elmously <khalid.elmously@canonical.com>
Signed-off-by: default avatarKelsey Skunberg <kelsey.skunberg@canonical.com>
parent c5a0c274
...@@ -1249,7 +1249,8 @@ batadv_tt_global_orig_entry_find(const struct batadv_tt_global_entry *entry, ...@@ -1249,7 +1249,8 @@ batadv_tt_global_orig_entry_find(const struct batadv_tt_global_entry *entry,
*/ */
static bool static bool
batadv_tt_global_entry_has_orig(const struct batadv_tt_global_entry *entry, 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; struct batadv_tt_orig_list_entry *orig_entry;
bool found = false; bool found = false;
...@@ -1257,6 +1258,10 @@ batadv_tt_global_entry_has_orig(const struct batadv_tt_global_entry *entry, ...@@ -1257,6 +1258,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); orig_entry = batadv_tt_global_orig_entry_find(entry, orig_node);
if (orig_entry) { if (orig_entry) {
found = true; found = true;
if (flags)
*flags = orig_entry->flags;
batadv_tt_orig_list_entry_free_ref(orig_entry); batadv_tt_orig_list_entry_free_ref(orig_entry);
} }
...@@ -1432,7 +1437,7 @@ static bool batadv_tt_global_add(struct batadv_priv *bat_priv, ...@@ -1432,7 +1437,7 @@ static bool batadv_tt_global_add(struct batadv_priv *bat_priv,
if (!(common->flags & BATADV_TT_CLIENT_TEMP)) if (!(common->flags & BATADV_TT_CLIENT_TEMP))
goto out; goto out;
if (batadv_tt_global_entry_has_orig(tt_global_entry, if (batadv_tt_global_entry_has_orig(tt_global_entry,
orig_node)) orig_node, NULL))
goto out_remove; goto out_remove;
batadv_tt_global_del_orig_list(tt_global_entry); batadv_tt_global_del_orig_list(tt_global_entry);
goto add_orig_entry; goto add_orig_entry;
...@@ -2366,17 +2371,24 @@ batadv_tt_req_node_new(struct batadv_priv *bat_priv, ...@@ -2366,17 +2371,24 @@ batadv_tt_req_node_new(struct batadv_priv *bat_priv,
* *
* Returns 1 if the entry is a valid, 0 otherwise. * Returns 1 if the entry is a valid, 0 otherwise.
*/ */
static int batadv_tt_local_valid(const void *entry_ptr, const void *data_ptr) static int 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; const struct batadv_tt_common_entry *tt_common_entry = entry_ptr;
if (tt_common_entry->flags & BATADV_TT_CLIENT_NEW) if (tt_common_entry->flags & BATADV_TT_CLIENT_NEW)
return 0; return 0;
if (flags)
*flags = tt_common_entry->flags;
return 1; return 1;
} }
static int batadv_tt_global_valid(const void *entry_ptr, static int 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_common_entry *tt_common_entry = entry_ptr;
const struct batadv_tt_global_entry *tt_global_entry; const struct batadv_tt_global_entry *tt_global_entry;
...@@ -2390,7 +2402,8 @@ static int batadv_tt_global_valid(const void *entry_ptr, ...@@ -2390,7 +2402,8 @@ static int batadv_tt_global_valid(const void *entry_ptr,
struct batadv_tt_global_entry, struct batadv_tt_global_entry,
common); 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);
} }
/** /**
...@@ -2406,18 +2419,25 @@ static int batadv_tt_global_valid(const void *entry_ptr, ...@@ -2406,18 +2419,25 @@ static int batadv_tt_global_valid(const void *entry_ptr,
static void batadv_tt_tvlv_generate(struct batadv_priv *bat_priv, static void batadv_tt_tvlv_generate(struct batadv_priv *bat_priv,
struct batadv_hashtable *hash, struct batadv_hashtable *hash,
void *tvlv_buff, u16 tt_len, void *tvlv_buff, u16 tt_len,
int (*valid_cb)(const void *, const void *), int (*valid_cb)(const void *,
const void *,
u8 *flags),
void *cb_data) void *cb_data)
{ {
struct batadv_tt_common_entry *tt_common_entry; struct batadv_tt_common_entry *tt_common_entry;
struct batadv_tvlv_tt_change *tt_change; struct batadv_tvlv_tt_change *tt_change;
struct hlist_head *head; struct hlist_head *head;
u16 tt_tot, tt_num_entries = 0; u16 tt_tot, tt_num_entries = 0;
u8 flags;
bool ret;
u32 i; u32 i;
tt_tot = batadv_tt_entries(tt_len); tt_tot = batadv_tt_entries(tt_len);
tt_change = (struct batadv_tvlv_tt_change *)tvlv_buff; tt_change = (struct batadv_tvlv_tt_change *)tvlv_buff;
if (!valid_cb)
return;
rcu_read_lock(); rcu_read_lock();
for (i = 0; i < hash->size; i++) { for (i = 0; i < hash->size; i++) {
head = &hash->table[i]; head = &hash->table[i];
...@@ -2427,11 +2447,12 @@ static void batadv_tt_tvlv_generate(struct batadv_priv *bat_priv, ...@@ -2427,11 +2447,12 @@ static void batadv_tt_tvlv_generate(struct batadv_priv *bat_priv,
if (tt_tot == tt_num_entries) if (tt_tot == tt_num_entries)
break; break;
if ((valid_cb) && (!valid_cb(tt_common_entry, cb_data))) ret = valid_cb(tt_common_entry, cb_data, &flags);
if (!ret)
continue; continue;
ether_addr_copy(tt_change->addr, tt_common_entry->addr); 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); tt_change->vid = htons(tt_common_entry->vid);
memset(tt_change->reserved, 0, memset(tt_change->reserved, 0,
sizeof(tt_change->reserved)); sizeof(tt_change->reserved));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment