aboutsummaryrefslogtreecommitdiffstats
path: root/net/batman-adv
diff options
context:
space:
mode:
authorAntonio Quartulli <ordex@autistici.org>2012-05-24 18:00:42 -0400
committerAntonio Quartulli <ordex@autistici.org>2012-06-28 02:44:50 -0400
commit3b643de541d4051f236f1e422f3329cccb7bd9c5 (patch)
tree2474303023ed04b2eb17532525339463955e69cc /net/batman-adv
parent28afd3c0756e0f052a09710c7daa0b9e27700a02 (diff)
batman-adv: clear ADD+DEL (and viceversa) events in the same orig-interval
During an OGM-interval (time between two different OGM sendings) the same client could roam away and then roam back to us. In this case the node would add two events to the events list (that is going to be sent appended to the next OGM). A DEL one and an ADD one. Obviously they will only increase the overhead (either in the air and on the receiver side) and eventually trigger wrong states/events without producing any real effect. For this reason we can safely delete any ADD event with its related DEL one. Signed-off-by: Antonio Quartulli <ordex@autistici.org> Signed-off-by: Sven Eckelmann <sven@narfation.org>
Diffstat (limited to 'net/batman-adv')
-rw-r--r--net/batman-adv/translation-table.c40
1 files changed, 37 insertions, 3 deletions
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
index 074936f2d30a..d82766bfd264 100644
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@ -157,7 +157,9 @@ batadv_tt_orig_list_entry_free_ref(struct tt_orig_list_entry *orig_entry)
157static void batadv_tt_local_event(struct bat_priv *bat_priv, 157static void batadv_tt_local_event(struct bat_priv *bat_priv,
158 const uint8_t *addr, uint8_t flags) 158 const uint8_t *addr, uint8_t flags)
159{ 159{
160 struct tt_change_node *tt_change_node; 160 struct tt_change_node *tt_change_node, *entry, *safe;
161 bool event_removed = false;
162 bool del_op_requested, del_op_entry;
161 163
162 tt_change_node = kmalloc(sizeof(*tt_change_node), GFP_ATOMIC); 164 tt_change_node = kmalloc(sizeof(*tt_change_node), GFP_ATOMIC);
163 165
@@ -167,13 +169,45 @@ static void batadv_tt_local_event(struct bat_priv *bat_priv,
167 tt_change_node->change.flags = flags; 169 tt_change_node->change.flags = flags;
168 memcpy(tt_change_node->change.addr, addr, ETH_ALEN); 170 memcpy(tt_change_node->change.addr, addr, ETH_ALEN);
169 171
172 del_op_requested = flags & TT_CLIENT_DEL;
173
174 /* check for ADD+DEL or DEL+ADD events */
170 spin_lock_bh(&bat_priv->tt_changes_list_lock); 175 spin_lock_bh(&bat_priv->tt_changes_list_lock);
176 list_for_each_entry_safe(entry, safe, &bat_priv->tt_changes_list,
177 list) {
178 if (!batadv_compare_eth(entry->change.addr, addr))
179 continue;
180
181 /* DEL+ADD in the same orig interval have no effect and can be
182 * removed to avoid silly behaviour on the receiver side. The
183 * other way around (ADD+DEL) can happen in case of roaming of
184 * a client still in the NEW state. Roaming of NEW clients is
185 * now possible due to automatically recognition of "temporary"
186 * clients
187 */
188 del_op_entry = entry->change.flags & TT_CLIENT_DEL;
189 if (!del_op_requested && del_op_entry)
190 goto del;
191 if (del_op_requested && !del_op_entry)
192 goto del;
193 continue;
194del:
195 list_del(&entry->list);
196 kfree(entry);
197 event_removed = true;
198 goto unlock;
199 }
200
171 /* track the change in the OGMinterval list */ 201 /* track the change in the OGMinterval list */
172 list_add_tail(&tt_change_node->list, &bat_priv->tt_changes_list); 202 list_add_tail(&tt_change_node->list, &bat_priv->tt_changes_list);
173 atomic_inc(&bat_priv->tt_local_changes); 203
204unlock:
174 spin_unlock_bh(&bat_priv->tt_changes_list_lock); 205 spin_unlock_bh(&bat_priv->tt_changes_list_lock);
175 206
176 atomic_set(&bat_priv->tt_ogm_append_cnt, 0); 207 if (event_removed)
208 atomic_dec(&bat_priv->tt_local_changes);
209 else
210 atomic_inc(&bat_priv->tt_local_changes);
177} 211}
178 212
179int batadv_tt_len(int changes_num) 213int batadv_tt_len(int changes_num)