Skip to content

Commit 068ee6e

Browse files
author
Antonio Quartulli
committed
batman-adv: roaming handling mechanism redesign
This patch allows clients to roam multiple times within the same originator-interval. To enable this new feature two key aspects that have been introduced: 1) packets are always directed to the node that was originally serving the roamed client which will then re-route the data to the correct destination at any point in time; 2) the client flags handling mechanism has been properly modified in order to allow multiple roamings withinin the same orig-int. Therefore flags are now set properly even in this scenario. Signed-off-by: Antonio Quartulli <[email protected]>
1 parent be73b48 commit 068ee6e

File tree

1 file changed

+118
-39
lines changed

1 file changed

+118
-39
lines changed

net/batman-adv/translation-table.c

Lines changed: 118 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,20 @@ static int batadv_tt_local_init(struct batadv_priv *bat_priv)
238238
return 0;
239239
}
240240

241+
static void batadv_tt_global_free(struct batadv_priv *bat_priv,
242+
struct batadv_tt_global_entry *tt_global,
243+
const char *message)
244+
{
245+
batadv_dbg(BATADV_DBG_TT, bat_priv,
246+
"Deleting global tt entry %pM: %s\n",
247+
tt_global->common.addr, message);
248+
249+
batadv_hash_remove(bat_priv->tt.global_hash, batadv_compare_tt,
250+
batadv_choose_orig, tt_global->common.addr);
251+
batadv_tt_global_entry_free_ref(tt_global);
252+
253+
}
254+
241255
void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
242256
int ifindex)
243257
{
@@ -248,14 +262,38 @@ void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
248262
struct hlist_node *node;
249263
struct batadv_tt_orig_list_entry *orig_entry;
250264
int hash_added;
265+
bool roamed_back = false;
251266

252267
tt_local = batadv_tt_local_hash_find(bat_priv, addr);
268+
tt_global = batadv_tt_global_hash_find(bat_priv, addr);
253269

254270
if (tt_local) {
255271
tt_local->last_seen = jiffies;
256-
/* possibly unset the BATADV_TT_CLIENT_PENDING flag */
257-
tt_local->common.flags &= ~BATADV_TT_CLIENT_PENDING;
258-
goto out;
272+
if (tt_local->common.flags & BATADV_TT_CLIENT_PENDING) {
273+
batadv_dbg(BATADV_DBG_TT, bat_priv,
274+
"Re-adding pending client %pM\n", addr);
275+
/* whatever the reason why the PENDING flag was set,
276+
* this is a client which was enqueued to be removed in
277+
* this orig_interval. Since it popped up again, the
278+
* flag can be reset like it was never enqueued
279+
*/
280+
tt_local->common.flags &= ~BATADV_TT_CLIENT_PENDING;
281+
goto add_event;
282+
}
283+
284+
if (tt_local->common.flags & BATADV_TT_CLIENT_ROAM) {
285+
batadv_dbg(BATADV_DBG_TT, bat_priv,
286+
"Roaming client %pM came back to its original location\n",
287+
addr);
288+
/* the ROAM flag is set because this client roamed away
289+
* and the node got a roaming_advertisement message. Now
290+
* that the client popped up again at its original
291+
* location such flag can be unset
292+
*/
293+
tt_local->common.flags &= ~BATADV_TT_CLIENT_ROAM;
294+
roamed_back = true;
295+
}
296+
goto check_roaming;
259297
}
260298

261299
tt_local = kmalloc(sizeof(*tt_local), GFP_ATOMIC);
@@ -294,13 +332,14 @@ void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
294332
goto out;
295333
}
296334

335+
add_event:
297336
batadv_tt_local_event(bat_priv, addr, tt_local->common.flags);
298337

299-
/* remove address from global hash if present */
300-
tt_global = batadv_tt_global_hash_find(bat_priv, addr);
301-
302-
/* Check whether it is a roaming! */
303-
if (tt_global) {
338+
check_roaming:
339+
/* Check whether it is a roaming, but don't do anything if the roaming
340+
* process has already been handled
341+
*/
342+
if (tt_global && !(tt_global->common.flags & BATADV_TT_CLIENT_ROAM)) {
304343
/* These node are probably going to update their tt table */
305344
head = &tt_global->orig_list;
306345
rcu_read_lock();
@@ -309,12 +348,19 @@ void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
309348
orig_entry->orig_node);
310349
}
311350
rcu_read_unlock();
312-
/* The global entry has to be marked as ROAMING and
313-
* has to be kept for consistency purpose
314-
*/
315-
tt_global->common.flags |= BATADV_TT_CLIENT_ROAM;
316-
tt_global->roam_at = jiffies;
351+
if (roamed_back) {
352+
batadv_tt_global_free(bat_priv, tt_global,
353+
"Roaming canceled");
354+
tt_global = NULL;
355+
} else {
356+
/* The global entry has to be marked as ROAMING and
357+
* has to be kept for consistency purpose
358+
*/
359+
tt_global->common.flags |= BATADV_TT_CLIENT_ROAM;
360+
tt_global->roam_at = jiffies;
361+
}
317362
}
363+
318364
out:
319365
if (tt_local)
320366
batadv_tt_local_entry_free_ref(tt_local);
@@ -508,13 +554,28 @@ uint16_t batadv_tt_local_remove(struct batadv_priv *bat_priv,
508554
curr_flags = tt_local_entry->common.flags;
509555

510556
flags = BATADV_TT_CLIENT_DEL;
557+
/* if this global entry addition is due to a roaming, the node has to
558+
* mark the local entry as "roamed" in order to correctly reroute
559+
* packets later
560+
*/
511561
if (roaming) {
512562
flags |= BATADV_TT_CLIENT_ROAM;
513563
/* mark the local client as ROAMed */
514564
tt_local_entry->common.flags |= BATADV_TT_CLIENT_ROAM;
515565
}
516566

517-
batadv_tt_local_set_pending(bat_priv, tt_local_entry, flags, message);
567+
if (!(tt_local_entry->common.flags & BATADV_TT_CLIENT_NEW)) {
568+
batadv_tt_local_set_pending(bat_priv, tt_local_entry, flags,
569+
message);
570+
goto out;
571+
}
572+
/* if this client has been added right now, it is possible to
573+
* immediately purge it
574+
*/
575+
batadv_tt_local_event(bat_priv, tt_local_entry->common.addr,
576+
curr_flags | BATADV_TT_CLIENT_DEL);
577+
hlist_del_rcu(&tt_local_entry->common.hash_entry);
578+
batadv_tt_local_entry_free_ref(tt_local_entry);
518579

519580
out:
520581
if (tt_local_entry)
@@ -724,12 +785,22 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv,
724785
uint8_t ttvn)
725786
{
726787
struct batadv_tt_global_entry *tt_global_entry = NULL;
788+
struct batadv_tt_local_entry *tt_local_entry = NULL;
727789
int ret = 0;
728790
int hash_added;
729791
struct batadv_tt_common_entry *common;
730792
uint16_t local_flags;
731793

732794
tt_global_entry = batadv_tt_global_hash_find(bat_priv, tt_addr);
795+
tt_local_entry = batadv_tt_local_hash_find(bat_priv, tt_addr);
796+
797+
/* if the node already has a local client for this entry, it has to wait
798+
* for a roaming advertisement instead of manually messing up the global
799+
* table
800+
*/
801+
if ((flags & BATADV_TT_CLIENT_TEMP) && tt_local_entry &&
802+
!(tt_local_entry->common.flags & BATADV_TT_CLIENT_NEW))
803+
goto out;
733804

734805
if (!tt_global_entry) {
735806
tt_global_entry = kzalloc(sizeof(*tt_global_entry), GFP_ATOMIC);
@@ -764,19 +835,31 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv,
764835
goto out_remove;
765836
}
766837
} else {
838+
common = &tt_global_entry->common;
767839
/* If there is already a global entry, we can use this one for
768840
* our processing.
769-
* But if we are trying to add a temporary client we can exit
770-
* directly because the temporary information should never
771-
* override any already known client state (whatever it is)
841+
* But if we are trying to add a temporary client then here are
842+
* two options at this point:
843+
* 1) the global client is not a temporary client: the global
844+
* client has to be left as it is, temporary information
845+
* should never override any already known client state
846+
* 2) the global client is a temporary client: purge the
847+
* originator list and add the new one orig_entry
772848
*/
773-
if (flags & BATADV_TT_CLIENT_TEMP)
774-
goto out;
849+
if (flags & BATADV_TT_CLIENT_TEMP) {
850+
if (!(common->flags & BATADV_TT_CLIENT_TEMP))
851+
goto out;
852+
if (batadv_tt_global_entry_has_orig(tt_global_entry,
853+
orig_node))
854+
goto out_remove;
855+
batadv_tt_global_del_orig_list(tt_global_entry);
856+
goto add_orig_entry;
857+
}
775858

776859
/* if the client was temporary added before receiving the first
777860
* OGM announcing it, we have to clear the TEMP flag
778861
*/
779-
tt_global_entry->common.flags &= ~BATADV_TT_CLIENT_TEMP;
862+
common->flags &= ~BATADV_TT_CLIENT_TEMP;
780863

781864
/* If there is the BATADV_TT_CLIENT_ROAM flag set, there is only
782865
* one originator left in the list and we previously received a
@@ -785,31 +868,40 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv,
785868
* We should first delete the old originator before adding the
786869
* new one.
787870
*/
788-
if (tt_global_entry->common.flags & BATADV_TT_CLIENT_ROAM) {
871+
if (common->flags & BATADV_TT_CLIENT_ROAM) {
789872
batadv_tt_global_del_orig_list(tt_global_entry);
790-
tt_global_entry->common.flags &= ~BATADV_TT_CLIENT_ROAM;
873+
common->flags &= ~BATADV_TT_CLIENT_ROAM;
791874
tt_global_entry->roam_at = 0;
792875
}
793876
}
877+
add_orig_entry:
794878
/* add the new orig_entry (if needed) or update it */
795879
batadv_tt_global_orig_entry_add(tt_global_entry, orig_node, ttvn);
796880

797881
batadv_dbg(BATADV_DBG_TT, bat_priv,
798882
"Creating new global tt entry: %pM (via %pM)\n",
799-
tt_global_entry->common.addr, orig_node->orig);
883+
common->addr, orig_node->orig);
800884
ret = 1;
801885

802886
out_remove:
803887

804888
/* remove address from local hash if present */
805889
local_flags = batadv_tt_local_remove(bat_priv, tt_addr,
806890
"global tt received",
807-
flags & BATADV_TT_CLIENT_ROAM);
891+
!!(flags & BATADV_TT_CLIENT_ROAM));
808892
tt_global_entry->common.flags |= local_flags & BATADV_TT_CLIENT_WIFI;
809893

894+
if (!(flags & BATADV_TT_CLIENT_ROAM))
895+
/* this is a normal global add. Therefore the client is not in a
896+
* roaming state anymore.
897+
*/
898+
tt_global_entry->common.flags &= ~BATADV_TT_CLIENT_ROAM;
899+
810900
out:
811901
if (tt_global_entry)
812902
batadv_tt_global_entry_free_ref(tt_global_entry);
903+
if (tt_local_entry)
904+
batadv_tt_local_entry_free_ref(tt_local_entry);
813905
return ret;
814906
}
815907

@@ -927,20 +1019,6 @@ batadv_tt_global_del_orig_entry(struct batadv_priv *bat_priv,
9271019
spin_unlock_bh(&tt_global_entry->list_lock);
9281020
}
9291021

930-
static void batadv_tt_global_free(struct batadv_priv *bat_priv,
931-
struct batadv_tt_global_entry *tt_global,
932-
const char *message)
933-
{
934-
batadv_dbg(BATADV_DBG_TT, bat_priv,
935-
"Deleting global tt entry %pM: %s\n",
936-
tt_global->common.addr, message);
937-
938-
batadv_hash_remove(bat_priv->tt.global_hash, batadv_compare_tt,
939-
batadv_choose_orig, tt_global->common.addr);
940-
batadv_tt_global_entry_free_ref(tt_global);
941-
942-
}
943-
9441022
/* If the client is to be deleted, we check if it is the last origantor entry
9451023
* within tt_global entry. If yes, we set the BATADV_TT_CLIENT_ROAM flag and the
9461024
* timer, otherwise we simply remove the originator scheduled for deletion.
@@ -1204,7 +1282,8 @@ struct batadv_orig_node *batadv_transtable_search(struct batadv_priv *bat_priv,
12041282

12051283
if (src && atomic_read(&bat_priv->ap_isolation)) {
12061284
tt_local_entry = batadv_tt_local_hash_find(bat_priv, src);
1207-
if (!tt_local_entry)
1285+
if (!tt_local_entry ||
1286+
(tt_local_entry->common.flags & BATADV_TT_CLIENT_PENDING))
12081287
goto out;
12091288
}
12101289

0 commit comments

Comments
 (0)