[RFC,v2] batman-adv: prevent TT request storms by not sending inconsistent TT TLVLs

Message ID 20180510144137.32244-1-mareklindner@neomailbox.ch (mailing list archive)
State RFC, archived
Delegated to: Simon Wunderlich
Headers
Series [RFC,v2] batman-adv: prevent TT request storms by not sending inconsistent TT TLVLs |

Commit Message

Marek Lindner May 10, 2018, 2:41 p.m. UTC
  A translation table TVLV changset sent with an OGM consists
of a number of headers (one per VLAN) plus the changeset
itself (addition and/or deletion of entries).

The per-VLAN headers are used by OGM recipients for consistency
checks. Said consistency check might determine that a full
translation table request is needed to restore consistency. If
the TT sender adds per-VLAN headers of empty VLANs into the OGM,
recipients are led to believe to have reached an inconsistent
state and thus request a full table update. The full table does
not contain empty VLANs (due to missing entries) the cycle
restarts when the next OGM is issued.

Consequently, when the translation table TVLV headers are
composed, empty VLANs are to be excluded.

Fixes: 21a57f6e7a3b ("batman-adv: make the TT CRC logic VLAN specific")

Signed-off-by: Marek Lindner <mareklindner@neomailbox.ch>
---

v2:
 * moved changes into batadv_tt_prepare_tvlv_local_data()
 * updated 'fixes' commit id

 net/batman-adv/translation-table.c | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)
  

Comments

Sven Eckelmann May 10, 2018, 3:50 p.m. UTC | #1
On Donnerstag, 10. Mai 2018 16:41:37 CEST Marek Lindner wrote:
>         rcu_read_lock();
>         hlist_for_each_entry_rcu(vlan, &bat_priv->softif_vlan_list, list) {
> +               vlan_entries = atomic_read(&vlan->tt.num_entries);
> +               if (vlan_entries < 1)
> +                       continue;
> +
>                 num_vlan++;
> -               num_entries += atomic_read(&vlan->tt.num_entries);
> +               total_entries += vlan_entries;
>         }

Please submit it on top of the maint branch before submitting it the next 
time. The rcu_read_lock isn't there anymore.

The rest also applies only with some offsets (which sound like you have some 
other modifications in your branch).

Kind regards,
	Sven
  
Marek Lindner May 11, 2018, 3:58 p.m. UTC | #2
On Thursday, May 10, 2018 11:50:48 PM HKT Sven Eckelmann wrote:
> Please submit it on top of the maint branch before submitting it the next
> time. The rcu_read_lock isn't there anymore.

I did not intend this patch to go into maint (hence the missing maint subject 
prefix) as I considered that to be more of a sanity check. The "fix adding 
VLANs with partial state" is the real fix.

Though, I am fine with maint too.

Cheers,
Marek
  

Patch

diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
index 0225616d..b51c034a 100644
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@ -931,15 +931,20 @@  batadv_tt_prepare_tvlv_local_data(struct batadv_priv *bat_priv,
 	struct batadv_tvlv_tt_vlan_data *tt_vlan;
 	struct batadv_softif_vlan *vlan;
 	u16 num_vlan = 0;
-	u16 num_entries = 0;
+	u16 vlan_entries = 0;
+	u16 total_entries = 0;
 	u16 tvlv_len;
 	u8 *tt_change_ptr;
 	int change_offset;
 
 	rcu_read_lock();
 	hlist_for_each_entry_rcu(vlan, &bat_priv->softif_vlan_list, list) {
+		vlan_entries = atomic_read(&vlan->tt.num_entries);
+		if (vlan_entries < 1)
+			continue;
+
 		num_vlan++;
-		num_entries += atomic_read(&vlan->tt.num_entries);
+		total_entries += vlan_entries;
 	}
 
 	change_offset = sizeof(**tt_data);
@@ -947,7 +952,7 @@  batadv_tt_prepare_tvlv_local_data(struct batadv_priv *bat_priv,
 
 	/* if tt_len is negative, allocate the space needed by the full table */
 	if (*tt_len < 0)
-		*tt_len = batadv_tt_len(num_entries);
+		*tt_len = batadv_tt_len(total_entries);
 
 	tvlv_len = *tt_len;
 	tvlv_len += change_offset;
@@ -964,6 +969,10 @@  batadv_tt_prepare_tvlv_local_data(struct batadv_priv *bat_priv,
 
 	tt_vlan = (struct batadv_tvlv_tt_vlan_data *)(*tt_data + 1);
 	hlist_for_each_entry_rcu(vlan, &bat_priv->softif_vlan_list, list) {
+		vlan_entries = atomic_read(&vlan->tt.num_entries);
+		if (vlan_entries < 1)
+			continue;
+
 		tt_vlan->vid = htons(vlan->vid);
 		tt_vlan->crc = htonl(vlan->tt.crc);