@@ -238,6 +238,20 @@ static int batadv_tt_local_init(struct batadv_priv *bat_priv)
238
238
return 0 ;
239
239
}
240
240
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
+
241
255
void batadv_tt_local_add (struct net_device * soft_iface , const uint8_t * addr ,
242
256
int ifindex )
243
257
{
@@ -248,14 +262,38 @@ void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
248
262
struct hlist_node * node ;
249
263
struct batadv_tt_orig_list_entry * orig_entry ;
250
264
int hash_added ;
265
+ bool roamed_back = false;
251
266
252
267
tt_local = batadv_tt_local_hash_find (bat_priv , addr );
268
+ tt_global = batadv_tt_global_hash_find (bat_priv , addr );
253
269
254
270
if (tt_local ) {
255
271
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 ;
259
297
}
260
298
261
299
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,
294
332
goto out ;
295
333
}
296
334
335
+ add_event :
297
336
batadv_tt_local_event (bat_priv , addr , tt_local -> common .flags );
298
337
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 ) ) {
304
343
/* These node are probably going to update their tt table */
305
344
head = & tt_global -> orig_list ;
306
345
rcu_read_lock ();
@@ -309,12 +348,19 @@ void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
309
348
orig_entry -> orig_node );
310
349
}
311
350
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
+ }
317
362
}
363
+
318
364
out :
319
365
if (tt_local )
320
366
batadv_tt_local_entry_free_ref (tt_local );
@@ -508,13 +554,28 @@ uint16_t batadv_tt_local_remove(struct batadv_priv *bat_priv,
508
554
curr_flags = tt_local_entry -> common .flags ;
509
555
510
556
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
+ */
511
561
if (roaming ) {
512
562
flags |= BATADV_TT_CLIENT_ROAM ;
513
563
/* mark the local client as ROAMed */
514
564
tt_local_entry -> common .flags |= BATADV_TT_CLIENT_ROAM ;
515
565
}
516
566
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 );
518
579
519
580
out :
520
581
if (tt_local_entry )
@@ -724,12 +785,22 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv,
724
785
uint8_t ttvn )
725
786
{
726
787
struct batadv_tt_global_entry * tt_global_entry = NULL ;
788
+ struct batadv_tt_local_entry * tt_local_entry = NULL ;
727
789
int ret = 0 ;
728
790
int hash_added ;
729
791
struct batadv_tt_common_entry * common ;
730
792
uint16_t local_flags ;
731
793
732
794
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 ;
733
804
734
805
if (!tt_global_entry ) {
735
806
tt_global_entry = kzalloc (sizeof (* tt_global_entry ), GFP_ATOMIC );
@@ -764,19 +835,31 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv,
764
835
goto out_remove ;
765
836
}
766
837
} else {
838
+ common = & tt_global_entry -> common ;
767
839
/* If there is already a global entry, we can use this one for
768
840
* 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
772
848
*/
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
+ }
775
858
776
859
/* if the client was temporary added before receiving the first
777
860
* OGM announcing it, we have to clear the TEMP flag
778
861
*/
779
- tt_global_entry -> common . flags &= ~BATADV_TT_CLIENT_TEMP ;
862
+ common -> flags &= ~BATADV_TT_CLIENT_TEMP ;
780
863
781
864
/* If there is the BATADV_TT_CLIENT_ROAM flag set, there is only
782
865
* 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,
785
868
* We should first delete the old originator before adding the
786
869
* new one.
787
870
*/
788
- if (tt_global_entry -> common . flags & BATADV_TT_CLIENT_ROAM ) {
871
+ if (common -> flags & BATADV_TT_CLIENT_ROAM ) {
789
872
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 ;
791
874
tt_global_entry -> roam_at = 0 ;
792
875
}
793
876
}
877
+ add_orig_entry :
794
878
/* add the new orig_entry (if needed) or update it */
795
879
batadv_tt_global_orig_entry_add (tt_global_entry , orig_node , ttvn );
796
880
797
881
batadv_dbg (BATADV_DBG_TT , bat_priv ,
798
882
"Creating new global tt entry: %pM (via %pM)\n" ,
799
- tt_global_entry -> common . addr , orig_node -> orig );
883
+ common -> addr , orig_node -> orig );
800
884
ret = 1 ;
801
885
802
886
out_remove :
803
887
804
888
/* remove address from local hash if present */
805
889
local_flags = batadv_tt_local_remove (bat_priv , tt_addr ,
806
890
"global tt received" ,
807
- flags & BATADV_TT_CLIENT_ROAM );
891
+ !!( flags & BATADV_TT_CLIENT_ROAM ) );
808
892
tt_global_entry -> common .flags |= local_flags & BATADV_TT_CLIENT_WIFI ;
809
893
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
+
810
900
out :
811
901
if (tt_global_entry )
812
902
batadv_tt_global_entry_free_ref (tt_global_entry );
903
+ if (tt_local_entry )
904
+ batadv_tt_local_entry_free_ref (tt_local_entry );
813
905
return ret ;
814
906
}
815
907
@@ -927,20 +1019,6 @@ batadv_tt_global_del_orig_entry(struct batadv_priv *bat_priv,
927
1019
spin_unlock_bh (& tt_global_entry -> list_lock );
928
1020
}
929
1021
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
-
944
1022
/* If the client is to be deleted, we check if it is the last origantor entry
945
1023
* within tt_global entry. If yes, we set the BATADV_TT_CLIENT_ROAM flag and the
946
1024
* 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,
1204
1282
1205
1283
if (src && atomic_read (& bat_priv -> ap_isolation )) {
1206
1284
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 ))
1208
1287
goto out ;
1209
1288
}
1210
1289
0 commit comments