aboutsummaryrefslogtreecommitdiffstats
path: root/net/batman-adv/translation-table.c
diff options
context:
space:
mode:
authorAntonio Quartulli <ordex@autistici.org>2012-09-23 16:38:37 -0400
committerAntonio Quartulli <ordex@autistici.org>2012-11-14 15:00:37 -0500
commit068ee6e204e1f48ba24ec91ce40f5ca833a57a81 (patch)
tree0aa52811822469811fe5f887c9b2ec7823e9359b /net/batman-adv/translation-table.c
parentbe73b488d1e2993fe92b5ec02347c3f7c08307b8 (diff)
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 <ordex@autistici.org>
Diffstat (limited to 'net/batman-adv/translation-table.c')
-rw-r--r--net/batman-adv/translation-table.c157
1 files changed, 118 insertions, 39 deletions
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
index cb8433aceed8..dd2c2545cfef 100644
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@ -238,6 +238,20 @@ static int batadv_tt_local_init(struct batadv_priv *bat_priv)
238 return 0; 238 return 0;
239} 239}
240 240
241static 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
241void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr, 255void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
242 int ifindex) 256 int ifindex)
243{ 257{
@@ -248,14 +262,38 @@ void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
248 struct hlist_node *node; 262 struct hlist_node *node;
249 struct batadv_tt_orig_list_entry *orig_entry; 263 struct batadv_tt_orig_list_entry *orig_entry;
250 int hash_added; 264 int hash_added;
265 bool roamed_back = false;
251 266
252 tt_local = batadv_tt_local_hash_find(bat_priv, addr); 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 if (tt_local) { 270 if (tt_local) {
255 tt_local->last_seen = jiffies; 271 tt_local->last_seen = jiffies;
256 /* possibly unset the BATADV_TT_CLIENT_PENDING flag */ 272 if (tt_local->common.flags & BATADV_TT_CLIENT_PENDING) {
257 tt_local->common.flags &= ~BATADV_TT_CLIENT_PENDING; 273 batadv_dbg(BATADV_DBG_TT, bat_priv,
258 goto out; 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 tt_local = kmalloc(sizeof(*tt_local), GFP_ATOMIC); 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 goto out; 332 goto out;
295 } 333 }
296 334
335add_event:
297 batadv_tt_local_event(bat_priv, addr, tt_local->common.flags); 336 batadv_tt_local_event(bat_priv, addr, tt_local->common.flags);
298 337
299 /* remove address from global hash if present */ 338check_roaming:
300 tt_global = batadv_tt_global_hash_find(bat_priv, addr); 339 /* Check whether it is a roaming, but don't do anything if the roaming
301 340 * process has already been handled
302 /* Check whether it is a roaming! */ 341 */
303 if (tt_global) { 342 if (tt_global && !(tt_global->common.flags & BATADV_TT_CLIENT_ROAM)) {
304 /* These node are probably going to update their tt table */ 343 /* These node are probably going to update their tt table */
305 head = &tt_global->orig_list; 344 head = &tt_global->orig_list;
306 rcu_read_lock(); 345 rcu_read_lock();
@@ -309,12 +348,19 @@ void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
309 orig_entry->orig_node); 348 orig_entry->orig_node);
310 } 349 }
311 rcu_read_unlock(); 350 rcu_read_unlock();
312 /* The global entry has to be marked as ROAMING and 351 if (roamed_back) {
313 * has to be kept for consistency purpose 352 batadv_tt_global_free(bat_priv, tt_global,
314 */ 353 "Roaming canceled");
315 tt_global->common.flags |= BATADV_TT_CLIENT_ROAM; 354 tt_global = NULL;
316 tt_global->roam_at = jiffies; 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
318out: 364out:
319 if (tt_local) 365 if (tt_local)
320 batadv_tt_local_entry_free_ref(tt_local); 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 curr_flags = tt_local_entry->common.flags; 554 curr_flags = tt_local_entry->common.flags;
509 555
510 flags = BATADV_TT_CLIENT_DEL; 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 if (roaming) { 561 if (roaming) {
512 flags |= BATADV_TT_CLIENT_ROAM; 562 flags |= BATADV_TT_CLIENT_ROAM;
513 /* mark the local client as ROAMed */ 563 /* mark the local client as ROAMed */
514 tt_local_entry->common.flags |= BATADV_TT_CLIENT_ROAM; 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
519out: 580out:
520 if (tt_local_entry) 581 if (tt_local_entry)
@@ -724,12 +785,22 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv,
724 uint8_t ttvn) 785 uint8_t ttvn)
725{ 786{
726 struct batadv_tt_global_entry *tt_global_entry = NULL; 787 struct batadv_tt_global_entry *tt_global_entry = NULL;
788 struct batadv_tt_local_entry *tt_local_entry = NULL;
727 int ret = 0; 789 int ret = 0;
728 int hash_added; 790 int hash_added;
729 struct batadv_tt_common_entry *common; 791 struct batadv_tt_common_entry *common;
730 uint16_t local_flags; 792 uint16_t local_flags;
731 793
732 tt_global_entry = batadv_tt_global_hash_find(bat_priv, tt_addr); 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 if (!tt_global_entry) { 805 if (!tt_global_entry) {
735 tt_global_entry = kzalloc(sizeof(*tt_global_entry), GFP_ATOMIC); 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 goto out_remove; 835 goto out_remove;
765 } 836 }
766 } else { 837 } else {
838 common = &tt_global_entry->common;
767 /* If there is already a global entry, we can use this one for 839 /* If there is already a global entry, we can use this one for
768 * our processing. 840 * our processing.
769 * But if we are trying to add a temporary client we can exit 841 * But if we are trying to add a temporary client then here are
770 * directly because the temporary information should never 842 * two options at this point:
771 * override any already known client state (whatever it is) 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) 849 if (flags & BATADV_TT_CLIENT_TEMP) {
774 goto out; 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 /* if the client was temporary added before receiving the first 859 /* if the client was temporary added before receiving the first
777 * OGM announcing it, we have to clear the TEMP flag 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 /* If there is the BATADV_TT_CLIENT_ROAM flag set, there is only 864 /* If there is the BATADV_TT_CLIENT_ROAM flag set, there is only
782 * one originator left in the list and we previously received a 865 * one originator left in the list and we previously received a
@@ -785,18 +868,19 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv,
785 * We should first delete the old originator before adding the 868 * We should first delete the old originator before adding the
786 * new one. 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 batadv_tt_global_del_orig_list(tt_global_entry); 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 tt_global_entry->roam_at = 0; 874 tt_global_entry->roam_at = 0;
792 } 875 }
793 } 876 }
877add_orig_entry:
794 /* add the new orig_entry (if needed) or update it */ 878 /* add the new orig_entry (if needed) or update it */
795 batadv_tt_global_orig_entry_add(tt_global_entry, orig_node, ttvn); 879 batadv_tt_global_orig_entry_add(tt_global_entry, orig_node, ttvn);
796 880
797 batadv_dbg(BATADV_DBG_TT, bat_priv, 881 batadv_dbg(BATADV_DBG_TT, bat_priv,
798 "Creating new global tt entry: %pM (via %pM)\n", 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 ret = 1; 884 ret = 1;
801 885
802out_remove: 886out_remove:
@@ -804,12 +888,20 @@ out_remove:
804 /* remove address from local hash if present */ 888 /* remove address from local hash if present */
805 local_flags = batadv_tt_local_remove(bat_priv, tt_addr, 889 local_flags = batadv_tt_local_remove(bat_priv, tt_addr,
806 "global tt received", 890 "global tt received",
807 flags & BATADV_TT_CLIENT_ROAM); 891 !!(flags & BATADV_TT_CLIENT_ROAM));
808 tt_global_entry->common.flags |= local_flags & BATADV_TT_CLIENT_WIFI; 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
810out: 900out:
811 if (tt_global_entry) 901 if (tt_global_entry)
812 batadv_tt_global_entry_free_ref(tt_global_entry); 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 return ret; 905 return ret;
814} 906}
815 907
@@ -927,20 +1019,6 @@ batadv_tt_global_del_orig_entry(struct batadv_priv *bat_priv,
927 spin_unlock_bh(&tt_global_entry->list_lock); 1019 spin_unlock_bh(&tt_global_entry->list_lock);
928} 1020}
929 1021
930static 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/* If the client is to be deleted, we check if it is the last origantor entry 1022/* If the client is to be deleted, we check if it is the last origantor entry
945 * within tt_global entry. If yes, we set the BATADV_TT_CLIENT_ROAM flag and the 1023 * within tt_global entry. If yes, we set the BATADV_TT_CLIENT_ROAM flag and the
946 * timer, otherwise we simply remove the originator scheduled for deletion. 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 if (src && atomic_read(&bat_priv->ap_isolation)) { 1283 if (src && atomic_read(&bat_priv->ap_isolation)) {
1206 tt_local_entry = batadv_tt_local_hash_find(bat_priv, src); 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 goto out; 1287 goto out;
1209 } 1288 }
1210 1289