aboutsummaryrefslogtreecommitdiffstats
path: root/net/batman-adv
diff options
context:
space:
mode:
Diffstat (limited to 'net/batman-adv')
-rw-r--r--net/batman-adv/main.h1
-rw-r--r--net/batman-adv/packet.h1
-rw-r--r--net/batman-adv/translation-table.c127
-rw-r--r--net/batman-adv/translation-table.h4
-rw-r--r--net/batman-adv/types.h1
5 files changed, 101 insertions, 33 deletions
diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h
index 574fca1bd434..61a0cfd3ceb4 100644
--- a/net/batman-adv/main.h
+++ b/net/batman-adv/main.h
@@ -43,6 +43,7 @@
43#define BATADV_PURGE_TIMEOUT 200000 /* 200 seconds */ 43#define BATADV_PURGE_TIMEOUT 200000 /* 200 seconds */
44#define BATADV_TT_LOCAL_TIMEOUT 3600000 /* in milliseconds */ 44#define BATADV_TT_LOCAL_TIMEOUT 3600000 /* in milliseconds */
45#define BATADV_TT_CLIENT_ROAM_TIMEOUT 600000 /* in milliseconds */ 45#define BATADV_TT_CLIENT_ROAM_TIMEOUT 600000 /* in milliseconds */
46#define BATADV_TT_CLIENT_TEMP_TIMEOUT 600000 /* in milliseconds */
46/* sliding packet range of received originator messages in sequence numbers 47/* sliding packet range of received originator messages in sequence numbers
47 * (should be a multiple of our word size) 48 * (should be a multiple of our word size)
48 */ 49 */
diff --git a/net/batman-adv/packet.h b/net/batman-adv/packet.h
index eb4593413b73..2d23a14c220e 100644
--- a/net/batman-adv/packet.h
+++ b/net/batman-adv/packet.h
@@ -85,6 +85,7 @@ enum batadv_tt_client_flags {
85 BATADV_TT_CLIENT_DEL = BIT(0), 85 BATADV_TT_CLIENT_DEL = BIT(0),
86 BATADV_TT_CLIENT_ROAM = BIT(1), 86 BATADV_TT_CLIENT_ROAM = BIT(1),
87 BATADV_TT_CLIENT_WIFI = BIT(2), 87 BATADV_TT_CLIENT_WIFI = BIT(2),
88 BATADV_TT_CLIENT_TEMP = BIT(3),
88 BATADV_TT_CLIENT_NOPURGE = BIT(8), 89 BATADV_TT_CLIENT_NOPURGE = BIT(8),
89 BATADV_TT_CLIENT_NEW = BIT(9), 90 BATADV_TT_CLIENT_NEW = BIT(9),
90 BATADV_TT_CLIENT_PENDING = BIT(10), 91 BATADV_TT_CLIENT_PENDING = BIT(10),
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
index cb429d181f4d..112edd371b2f 100644
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@ -34,6 +34,10 @@ static void batadv_send_roam_adv(struct batadv_priv *bat_priv, uint8_t *client,
34static void batadv_tt_purge(struct work_struct *work); 34static void batadv_tt_purge(struct work_struct *work);
35static void 35static void
36batadv_tt_global_del_orig_list(struct batadv_tt_global_entry *tt_global_entry); 36batadv_tt_global_del_orig_list(struct batadv_tt_global_entry *tt_global_entry);
37static void batadv_tt_global_del(struct batadv_priv *bat_priv,
38 struct batadv_orig_node *orig_node,
39 const unsigned char *addr,
40 const char *message, bool roaming);
37 41
38/* returns 1 if they are the same mac addr */ 42/* returns 1 if they are the same mac addr */
39static int batadv_compare_tt(const struct hlist_node *node, const void *data2) 43static int batadv_compare_tt(const struct hlist_node *node, const void *data2)
@@ -268,6 +272,7 @@ void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
268 tt_local_entry->common.flags |= BATADV_TT_CLIENT_WIFI; 272 tt_local_entry->common.flags |= BATADV_TT_CLIENT_WIFI;
269 atomic_set(&tt_local_entry->common.refcount, 2); 273 atomic_set(&tt_local_entry->common.refcount, 2);
270 tt_local_entry->last_seen = jiffies; 274 tt_local_entry->last_seen = jiffies;
275 tt_local_entry->common.added_at = tt_local_entry->last_seen;
271 276
272 /* the batman interface mac address should never be purged */ 277 /* the batman interface mac address should never be purged */
273 if (batadv_compare_eth(addr, soft_iface->dev_addr)) 278 if (batadv_compare_eth(addr, soft_iface->dev_addr))
@@ -682,8 +687,13 @@ batadv_tt_global_orig_entry_add(struct batadv_tt_global_entry *tt_global,
682 struct batadv_tt_orig_list_entry *orig_entry; 687 struct batadv_tt_orig_list_entry *orig_entry;
683 688
684 orig_entry = batadv_tt_global_orig_entry_find(tt_global, orig_node); 689 orig_entry = batadv_tt_global_orig_entry_find(tt_global, orig_node);
685 if (orig_entry) 690 if (orig_entry) {
691 /* refresh the ttvn: the current value could be a bogus one that
692 * was added during a "temporary client detection"
693 */
694 orig_entry->ttvn = ttvn;
686 goto out; 695 goto out;
696 }
687 697
688 orig_entry = kzalloc(sizeof(*orig_entry), GFP_ATOMIC); 698 orig_entry = kzalloc(sizeof(*orig_entry), GFP_ATOMIC);
689 if (!orig_entry) 699 if (!orig_entry)
@@ -729,6 +739,7 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv,
729 common->flags = flags; 739 common->flags = flags;
730 tt_global_entry->roam_at = 0; 740 tt_global_entry->roam_at = 0;
731 atomic_set(&common->refcount, 2); 741 atomic_set(&common->refcount, 2);
742 common->added_at = jiffies;
732 743
733 INIT_HLIST_HEAD(&tt_global_entry->orig_list); 744 INIT_HLIST_HEAD(&tt_global_entry->orig_list);
734 spin_lock_init(&tt_global_entry->list_lock); 745 spin_lock_init(&tt_global_entry->list_lock);
@@ -744,7 +755,19 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv,
744 goto out_remove; 755 goto out_remove;
745 } 756 }
746 } else { 757 } else {
747 /* there is already a global entry, use this one. */ 758 /* If there is already a global entry, we can use this one for
759 * our processing.
760 * But if we are trying to add a temporary client we can exit
761 * directly because the temporary information should never
762 * override any already known client state (whatever it is)
763 */
764 if (flags & BATADV_TT_CLIENT_TEMP)
765 goto out;
766
767 /* if the client was temporary added before receiving the first
768 * OGM announcing it, we have to clear the TEMP flag
769 */
770 tt_global_entry->common.flags &= ~BATADV_TT_CLIENT_TEMP;
748 771
749 /* If there is the BATADV_TT_CLIENT_ROAM flag set, there is only 772 /* If there is the BATADV_TT_CLIENT_ROAM flag set, there is only
750 * one originator left in the list and we previously received a 773 * one originator left in the list and we previously received a
@@ -758,9 +781,8 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv,
758 tt_global_entry->common.flags &= ~BATADV_TT_CLIENT_ROAM; 781 tt_global_entry->common.flags &= ~BATADV_TT_CLIENT_ROAM;
759 tt_global_entry->roam_at = 0; 782 tt_global_entry->roam_at = 0;
760 } 783 }
761
762 } 784 }
763 /* add the new orig_entry (if needed) */ 785 /* add the new orig_entry (if needed) or update it */
764 batadv_tt_global_orig_entry_add(tt_global_entry, orig_node, ttvn); 786 batadv_tt_global_orig_entry_add(tt_global_entry, orig_node, ttvn);
765 787
766 batadv_dbg(BATADV_DBG_TT, bat_priv, 788 batadv_dbg(BATADV_DBG_TT, bat_priv,
@@ -800,11 +822,12 @@ batadv_tt_global_print_entry(struct batadv_tt_global_entry *tt_global_entry,
800 hlist_for_each_entry_rcu(orig_entry, node, head, list) { 822 hlist_for_each_entry_rcu(orig_entry, node, head, list) {
801 flags = tt_common_entry->flags; 823 flags = tt_common_entry->flags;
802 last_ttvn = atomic_read(&orig_entry->orig_node->last_ttvn); 824 last_ttvn = atomic_read(&orig_entry->orig_node->last_ttvn);
803 seq_printf(seq, " * %pM (%3u) via %pM (%3u) [%c%c]\n", 825 seq_printf(seq, " * %pM (%3u) via %pM (%3u) [%c%c%c]\n",
804 tt_global_entry->common.addr, orig_entry->ttvn, 826 tt_global_entry->common.addr, orig_entry->ttvn,
805 orig_entry->orig_node->orig, last_ttvn, 827 orig_entry->orig_node->orig, last_ttvn,
806 (flags & BATADV_TT_CLIENT_ROAM ? 'R' : '.'), 828 (flags & BATADV_TT_CLIENT_ROAM ? 'R' : '.'),
807 (flags & BATADV_TT_CLIENT_WIFI ? 'W' : '.')); 829 (flags & BATADV_TT_CLIENT_WIFI ? 'W' : '.'),
830 (flags & BATADV_TT_CLIENT_TEMP ? 'T' : '.'));
808 } 831 }
809} 832}
810 833
@@ -1059,49 +1082,63 @@ void batadv_tt_global_del_orig(struct batadv_priv *bat_priv,
1059 orig_node->tt_initialised = false; 1082 orig_node->tt_initialised = false;
1060} 1083}
1061 1084
1062static void batadv_tt_global_roam_purge_list(struct batadv_priv *bat_priv, 1085static bool batadv_tt_global_to_purge(struct batadv_tt_global_entry *tt_global,
1063 struct hlist_head *head) 1086 char **msg)
1064{ 1087{
1065 struct batadv_tt_common_entry *tt_common_entry; 1088 bool purge = false;
1066 struct batadv_tt_global_entry *tt_global_entry; 1089 unsigned long roam_timeout = BATADV_TT_CLIENT_ROAM_TIMEOUT;
1067 struct hlist_node *node, *node_tmp; 1090 unsigned long temp_timeout = BATADV_TT_CLIENT_TEMP_TIMEOUT;
1068 1091
1069 hlist_for_each_entry_safe(tt_common_entry, node, node_tmp, head, 1092 if ((tt_global->common.flags & BATADV_TT_CLIENT_ROAM) &&
1070 hash_entry) { 1093 batadv_has_timed_out(tt_global->roam_at, roam_timeout)) {
1071 tt_global_entry = container_of(tt_common_entry, 1094 purge = true;
1072 struct batadv_tt_global_entry, 1095 *msg = "Roaming timeout\n";
1073 common); 1096 }
1074 if (!(tt_global_entry->common.flags & BATADV_TT_CLIENT_ROAM))
1075 continue;
1076 if (!batadv_has_timed_out(tt_global_entry->roam_at,
1077 BATADV_TT_CLIENT_ROAM_TIMEOUT))
1078 continue;
1079
1080 batadv_dbg(BATADV_DBG_TT, bat_priv,
1081 "Deleting global tt entry (%pM): Roaming timeout\n",
1082 tt_global_entry->common.addr);
1083 1097
1084 hlist_del_rcu(node); 1098 if ((tt_global->common.flags & BATADV_TT_CLIENT_TEMP) &&
1085 batadv_tt_global_entry_free_ref(tt_global_entry); 1099 batadv_has_timed_out(tt_global->common.added_at, temp_timeout)) {
1100 purge = true;
1101 *msg = "Temporary client timeout\n";
1086 } 1102 }
1103
1104 return purge;
1087} 1105}
1088 1106
1089static void batadv_tt_global_roam_purge(struct batadv_priv *bat_priv) 1107static void batadv_tt_global_purge(struct batadv_priv *bat_priv)
1090{ 1108{
1091 struct batadv_hashtable *hash = bat_priv->tt.global_hash; 1109 struct batadv_hashtable *hash = bat_priv->tt.global_hash;
1092 struct hlist_head *head; 1110 struct hlist_head *head;
1111 struct hlist_node *node, *node_tmp;
1093 spinlock_t *list_lock; /* protects write access to the hash lists */ 1112 spinlock_t *list_lock; /* protects write access to the hash lists */
1094 uint32_t i; 1113 uint32_t i;
1114 char *msg = NULL;
1115 struct batadv_tt_common_entry *tt_common;
1116 struct batadv_tt_global_entry *tt_global;
1095 1117
1096 for (i = 0; i < hash->size; i++) { 1118 for (i = 0; i < hash->size; i++) {
1097 head = &hash->table[i]; 1119 head = &hash->table[i];
1098 list_lock = &hash->list_locks[i]; 1120 list_lock = &hash->list_locks[i];
1099 1121
1100 spin_lock_bh(list_lock); 1122 spin_lock_bh(list_lock);
1101 batadv_tt_global_roam_purge_list(bat_priv, head); 1123 hlist_for_each_entry_safe(tt_common, node, node_tmp, head,
1124 hash_entry) {
1125 tt_global = container_of(tt_common,
1126 struct batadv_tt_global_entry,
1127 common);
1128
1129 if (!batadv_tt_global_to_purge(tt_global, &msg))
1130 continue;
1131
1132 batadv_dbg(BATADV_DBG_TT, bat_priv,
1133 "Deleting global tt entry (%pM): %s\n",
1134 tt_global->common.addr, msg);
1135
1136 hlist_del_rcu(node);
1137
1138 batadv_tt_global_entry_free_ref(tt_global);
1139 }
1102 spin_unlock_bh(list_lock); 1140 spin_unlock_bh(list_lock);
1103 } 1141 }
1104
1105} 1142}
1106 1143
1107static void batadv_tt_global_table_free(struct batadv_priv *bat_priv) 1144static void batadv_tt_global_table_free(struct batadv_priv *bat_priv)
@@ -1239,6 +1276,12 @@ static uint16_t batadv_tt_global_crc(struct batadv_priv *bat_priv,
1239 */ 1276 */
1240 if (tt_common->flags & BATADV_TT_CLIENT_ROAM) 1277 if (tt_common->flags & BATADV_TT_CLIENT_ROAM)
1241 continue; 1278 continue;
1279 /* Temporary clients have not been announced yet, so
1280 * they have to be skipped while computing the global
1281 * crc
1282 */
1283 if (tt_common->flags & BATADV_TT_CLIENT_TEMP)
1284 continue;
1242 1285
1243 /* find out if this global entry is announced by this 1286 /* find out if this global entry is announced by this
1244 * originator 1287 * originator
@@ -1392,7 +1435,8 @@ static int batadv_tt_global_valid(const void *entry_ptr,
1392 const struct batadv_tt_global_entry *tt_global_entry; 1435 const struct batadv_tt_global_entry *tt_global_entry;
1393 const struct batadv_orig_node *orig_node = data_ptr; 1436 const struct batadv_orig_node *orig_node = data_ptr;
1394 1437
1395 if (tt_common_entry->flags & BATADV_TT_CLIENT_ROAM) 1438 if (tt_common_entry->flags & BATADV_TT_CLIENT_ROAM ||
1439 tt_common_entry->flags & BATADV_TT_CLIENT_TEMP)
1396 return 0; 1440 return 0;
1397 1441
1398 tt_global_entry = container_of(tt_common_entry, 1442 tt_global_entry = container_of(tt_common_entry,
@@ -2125,7 +2169,7 @@ static void batadv_tt_purge(struct work_struct *work)
2125 bat_priv = container_of(priv_tt, struct batadv_priv, tt); 2169 bat_priv = container_of(priv_tt, struct batadv_priv, tt);
2126 2170
2127 batadv_tt_local_purge(bat_priv); 2171 batadv_tt_local_purge(bat_priv);
2128 batadv_tt_global_roam_purge(bat_priv); 2172 batadv_tt_global_purge(bat_priv);
2129 batadv_tt_req_purge(bat_priv); 2173 batadv_tt_req_purge(bat_priv);
2130 batadv_tt_roam_purge(bat_priv); 2174 batadv_tt_roam_purge(bat_priv);
2131 2175
@@ -2399,3 +2443,22 @@ bool batadv_tt_global_client_is_roaming(struct batadv_priv *bat_priv,
2399out: 2443out:
2400 return ret; 2444 return ret;
2401} 2445}
2446
2447bool batadv_tt_add_temporary_global_entry(struct batadv_priv *bat_priv,
2448 struct batadv_orig_node *orig_node,
2449 const unsigned char *addr)
2450{
2451 bool ret = false;
2452
2453 if (!batadv_tt_global_add(bat_priv, orig_node, addr,
2454 BATADV_TT_CLIENT_TEMP,
2455 atomic_read(&orig_node->last_ttvn)))
2456 goto out;
2457
2458 batadv_dbg(BATADV_DBG_TT, bat_priv,
2459 "Added temporary global client (addr: %pM orig: %pM)\n",
2460 addr, orig_node->orig);
2461 ret = true;
2462out:
2463 return ret;
2464}
diff --git a/net/batman-adv/translation-table.h b/net/batman-adv/translation-table.h
index ffa87355096b..811fffd4760c 100644
--- a/net/batman-adv/translation-table.h
+++ b/net/batman-adv/translation-table.h
@@ -59,6 +59,8 @@ int batadv_tt_append_diff(struct batadv_priv *bat_priv,
59 int packet_min_len); 59 int packet_min_len);
60bool batadv_tt_global_client_is_roaming(struct batadv_priv *bat_priv, 60bool batadv_tt_global_client_is_roaming(struct batadv_priv *bat_priv,
61 uint8_t *addr); 61 uint8_t *addr);
62 62bool batadv_tt_add_temporary_global_entry(struct batadv_priv *bat_priv,
63 struct batadv_orig_node *orig_node,
64 const unsigned char *addr);
63 65
64#endif /* _NET_BATMAN_ADV_TRANSLATION_TABLE_H_ */ 66#endif /* _NET_BATMAN_ADV_TRANSLATION_TABLE_H_ */
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index 97c4978dee69..2ed82caacdca 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -284,6 +284,7 @@ struct batadv_tt_common_entry {
284 uint8_t addr[ETH_ALEN]; 284 uint8_t addr[ETH_ALEN];
285 struct hlist_node hash_entry; 285 struct hlist_node hash_entry;
286 uint16_t flags; 286 uint16_t flags;
287 unsigned long added_at;
287 atomic_t refcount; 288 atomic_t refcount;
288 struct rcu_head rcu; 289 struct rcu_head rcu;
289}; 290};