|
@@ -34,6 +34,10 @@ static void batadv_send_roam_adv(struct batadv_priv *bat_priv, uint8_t *client,
|
|
|
static void batadv_tt_purge(struct work_struct *work);
|
|
|
static void
|
|
|
batadv_tt_global_del_orig_list(struct batadv_tt_global_entry *tt_global_entry);
|
|
|
+static void batadv_tt_global_del(struct batadv_priv *bat_priv,
|
|
|
+ struct batadv_orig_node *orig_node,
|
|
|
+ const unsigned char *addr,
|
|
|
+ const char *message, bool roaming);
|
|
|
|
|
|
/* returns 1 if they are the same mac addr */
|
|
|
static int batadv_compare_tt(const struct hlist_node *node, const void *data2)
|
|
@@ -46,8 +50,8 @@ static int batadv_compare_tt(const struct hlist_node *node, const void *data2)
|
|
|
|
|
|
static void batadv_tt_start_timer(struct batadv_priv *bat_priv)
|
|
|
{
|
|
|
- INIT_DELAYED_WORK(&bat_priv->tt_work, batadv_tt_purge);
|
|
|
- queue_delayed_work(batadv_event_workqueue, &bat_priv->tt_work,
|
|
|
+ INIT_DELAYED_WORK(&bat_priv->tt.work, batadv_tt_purge);
|
|
|
+ queue_delayed_work(batadv_event_workqueue, &bat_priv->tt.work,
|
|
|
msecs_to_jiffies(5000));
|
|
|
}
|
|
|
|
|
@@ -88,7 +92,7 @@ batadv_tt_local_hash_find(struct batadv_priv *bat_priv, const void *data)
|
|
|
struct batadv_tt_common_entry *tt_common_entry;
|
|
|
struct batadv_tt_local_entry *tt_local_entry = NULL;
|
|
|
|
|
|
- tt_common_entry = batadv_tt_hash_find(bat_priv->tt_local_hash, data);
|
|
|
+ tt_common_entry = batadv_tt_hash_find(bat_priv->tt.local_hash, data);
|
|
|
if (tt_common_entry)
|
|
|
tt_local_entry = container_of(tt_common_entry,
|
|
|
struct batadv_tt_local_entry,
|
|
@@ -102,7 +106,7 @@ batadv_tt_global_hash_find(struct batadv_priv *bat_priv, const void *data)
|
|
|
struct batadv_tt_common_entry *tt_common_entry;
|
|
|
struct batadv_tt_global_entry *tt_global_entry = NULL;
|
|
|
|
|
|
- tt_common_entry = batadv_tt_hash_find(bat_priv->tt_global_hash, data);
|
|
|
+ tt_common_entry = batadv_tt_hash_find(bat_priv->tt.global_hash, data);
|
|
|
if (tt_common_entry)
|
|
|
tt_global_entry = container_of(tt_common_entry,
|
|
|
struct batadv_tt_global_entry,
|
|
@@ -152,6 +156,8 @@ static void batadv_tt_orig_list_entry_free_rcu(struct rcu_head *rcu)
|
|
|
static void
|
|
|
batadv_tt_orig_list_entry_free_ref(struct batadv_tt_orig_list_entry *orig_entry)
|
|
|
{
|
|
|
+ if (!atomic_dec_and_test(&orig_entry->refcount))
|
|
|
+ return;
|
|
|
/* to avoid race conditions, immediately decrease the tt counter */
|
|
|
atomic_dec(&orig_entry->orig_node->tt_size);
|
|
|
call_rcu(&orig_entry->rcu, batadv_tt_orig_list_entry_free_rcu);
|
|
@@ -175,8 +181,8 @@ static void batadv_tt_local_event(struct batadv_priv *bat_priv,
|
|
|
del_op_requested = flags & BATADV_TT_CLIENT_DEL;
|
|
|
|
|
|
/* check for ADD+DEL or DEL+ADD events */
|
|
|
- spin_lock_bh(&bat_priv->tt_changes_list_lock);
|
|
|
- list_for_each_entry_safe(entry, safe, &bat_priv->tt_changes_list,
|
|
|
+ spin_lock_bh(&bat_priv->tt.changes_list_lock);
|
|
|
+ list_for_each_entry_safe(entry, safe, &bat_priv->tt.changes_list,
|
|
|
list) {
|
|
|
if (!batadv_compare_eth(entry->change.addr, addr))
|
|
|
continue;
|
|
@@ -203,15 +209,15 @@ del:
|
|
|
}
|
|
|
|
|
|
/* track the change in the OGMinterval list */
|
|
|
- list_add_tail(&tt_change_node->list, &bat_priv->tt_changes_list);
|
|
|
+ list_add_tail(&tt_change_node->list, &bat_priv->tt.changes_list);
|
|
|
|
|
|
unlock:
|
|
|
- spin_unlock_bh(&bat_priv->tt_changes_list_lock);
|
|
|
+ spin_unlock_bh(&bat_priv->tt.changes_list_lock);
|
|
|
|
|
|
if (event_removed)
|
|
|
- atomic_dec(&bat_priv->tt_local_changes);
|
|
|
+ atomic_dec(&bat_priv->tt.local_changes);
|
|
|
else
|
|
|
- atomic_inc(&bat_priv->tt_local_changes);
|
|
|
+ atomic_inc(&bat_priv->tt.local_changes);
|
|
|
}
|
|
|
|
|
|
int batadv_tt_len(int changes_num)
|
|
@@ -221,12 +227,12 @@ int batadv_tt_len(int changes_num)
|
|
|
|
|
|
static int batadv_tt_local_init(struct batadv_priv *bat_priv)
|
|
|
{
|
|
|
- if (bat_priv->tt_local_hash)
|
|
|
+ if (bat_priv->tt.local_hash)
|
|
|
return 0;
|
|
|
|
|
|
- bat_priv->tt_local_hash = batadv_hash_new(1024);
|
|
|
+ bat_priv->tt.local_hash = batadv_hash_new(1024);
|
|
|
|
|
|
- if (!bat_priv->tt_local_hash)
|
|
|
+ if (!bat_priv->tt.local_hash)
|
|
|
return -ENOMEM;
|
|
|
|
|
|
return 0;
|
|
@@ -258,7 +264,7 @@ void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
|
|
|
|
|
|
batadv_dbg(BATADV_DBG_TT, bat_priv,
|
|
|
"Creating new local tt entry: %pM (ttvn: %d)\n", addr,
|
|
|
- (uint8_t)atomic_read(&bat_priv->ttvn));
|
|
|
+ (uint8_t)atomic_read(&bat_priv->tt.vn));
|
|
|
|
|
|
memcpy(tt_local_entry->common.addr, addr, ETH_ALEN);
|
|
|
tt_local_entry->common.flags = BATADV_NO_FLAGS;
|
|
@@ -266,6 +272,7 @@ void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
|
|
|
tt_local_entry->common.flags |= BATADV_TT_CLIENT_WIFI;
|
|
|
atomic_set(&tt_local_entry->common.refcount, 2);
|
|
|
tt_local_entry->last_seen = jiffies;
|
|
|
+ tt_local_entry->common.added_at = tt_local_entry->last_seen;
|
|
|
|
|
|
/* the batman interface mac address should never be purged */
|
|
|
if (batadv_compare_eth(addr, soft_iface->dev_addr))
|
|
@@ -277,7 +284,7 @@ void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
|
|
|
*/
|
|
|
tt_local_entry->common.flags |= BATADV_TT_CLIENT_NEW;
|
|
|
|
|
|
- hash_added = batadv_hash_add(bat_priv->tt_local_hash, batadv_compare_tt,
|
|
|
+ hash_added = batadv_hash_add(bat_priv->tt.local_hash, batadv_compare_tt,
|
|
|
batadv_choose_orig,
|
|
|
&tt_local_entry->common,
|
|
|
&tt_local_entry->common.hash_entry);
|
|
@@ -348,7 +355,7 @@ static void batadv_tt_prepare_packet_buff(struct batadv_priv *bat_priv,
|
|
|
primary_if = batadv_primary_if_get_selected(bat_priv);
|
|
|
|
|
|
req_len = min_packet_len;
|
|
|
- req_len += batadv_tt_len(atomic_read(&bat_priv->tt_local_changes));
|
|
|
+ req_len += batadv_tt_len(atomic_read(&bat_priv->tt.local_changes));
|
|
|
|
|
|
/* if we have too many changes for one packet don't send any
|
|
|
* and wait for the tt table request which will be fragmented
|
|
@@ -381,10 +388,10 @@ static int batadv_tt_changes_fill_buff(struct batadv_priv *bat_priv,
|
|
|
if (new_len > 0)
|
|
|
tot_changes = new_len / batadv_tt_len(1);
|
|
|
|
|
|
- spin_lock_bh(&bat_priv->tt_changes_list_lock);
|
|
|
- atomic_set(&bat_priv->tt_local_changes, 0);
|
|
|
+ spin_lock_bh(&bat_priv->tt.changes_list_lock);
|
|
|
+ atomic_set(&bat_priv->tt.local_changes, 0);
|
|
|
|
|
|
- list_for_each_entry_safe(entry, safe, &bat_priv->tt_changes_list,
|
|
|
+ list_for_each_entry_safe(entry, safe, &bat_priv->tt.changes_list,
|
|
|
list) {
|
|
|
if (count < tot_changes) {
|
|
|
memcpy(tt_buff + batadv_tt_len(count),
|
|
@@ -394,25 +401,25 @@ static int batadv_tt_changes_fill_buff(struct batadv_priv *bat_priv,
|
|
|
list_del(&entry->list);
|
|
|
kfree(entry);
|
|
|
}
|
|
|
- spin_unlock_bh(&bat_priv->tt_changes_list_lock);
|
|
|
+ spin_unlock_bh(&bat_priv->tt.changes_list_lock);
|
|
|
|
|
|
/* Keep the buffer for possible tt_request */
|
|
|
- spin_lock_bh(&bat_priv->tt_buff_lock);
|
|
|
- kfree(bat_priv->tt_buff);
|
|
|
- bat_priv->tt_buff_len = 0;
|
|
|
- bat_priv->tt_buff = NULL;
|
|
|
+ spin_lock_bh(&bat_priv->tt.last_changeset_lock);
|
|
|
+ kfree(bat_priv->tt.last_changeset);
|
|
|
+ bat_priv->tt.last_changeset_len = 0;
|
|
|
+ bat_priv->tt.last_changeset = NULL;
|
|
|
/* check whether this new OGM has no changes due to size problems */
|
|
|
if (new_len > 0) {
|
|
|
/* if kmalloc() fails we will reply with the full table
|
|
|
* instead of providing the diff
|
|
|
*/
|
|
|
- bat_priv->tt_buff = kmalloc(new_len, GFP_ATOMIC);
|
|
|
- if (bat_priv->tt_buff) {
|
|
|
- memcpy(bat_priv->tt_buff, tt_buff, new_len);
|
|
|
- bat_priv->tt_buff_len = new_len;
|
|
|
+ bat_priv->tt.last_changeset = kmalloc(new_len, GFP_ATOMIC);
|
|
|
+ if (bat_priv->tt.last_changeset) {
|
|
|
+ memcpy(bat_priv->tt.last_changeset, tt_buff, new_len);
|
|
|
+ bat_priv->tt.last_changeset_len = new_len;
|
|
|
}
|
|
|
}
|
|
|
- spin_unlock_bh(&bat_priv->tt_buff_lock);
|
|
|
+ spin_unlock_bh(&bat_priv->tt.last_changeset_lock);
|
|
|
|
|
|
return count;
|
|
|
}
|
|
@@ -421,7 +428,7 @@ int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset)
|
|
|
{
|
|
|
struct net_device *net_dev = (struct net_device *)seq->private;
|
|
|
struct batadv_priv *bat_priv = netdev_priv(net_dev);
|
|
|
- struct batadv_hashtable *hash = bat_priv->tt_local_hash;
|
|
|
+ struct batadv_hashtable *hash = bat_priv->tt.local_hash;
|
|
|
struct batadv_tt_common_entry *tt_common_entry;
|
|
|
struct batadv_hard_iface *primary_if;
|
|
|
struct hlist_node *node;
|
|
@@ -446,7 +453,7 @@ int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset)
|
|
|
|
|
|
seq_printf(seq,
|
|
|
"Locally retrieved addresses (from %s) announced via TT (TTVN: %u):\n",
|
|
|
- net_dev->name, (uint8_t)atomic_read(&bat_priv->ttvn));
|
|
|
+ net_dev->name, (uint8_t)atomic_read(&bat_priv->tt.vn));
|
|
|
|
|
|
for (i = 0; i < hash->size; i++) {
|
|
|
head = &hash->table[i];
|
|
@@ -544,7 +551,7 @@ static void batadv_tt_local_purge_list(struct batadv_priv *bat_priv,
|
|
|
|
|
|
static void batadv_tt_local_purge(struct batadv_priv *bat_priv)
|
|
|
{
|
|
|
- struct batadv_hashtable *hash = bat_priv->tt_local_hash;
|
|
|
+ struct batadv_hashtable *hash = bat_priv->tt.local_hash;
|
|
|
struct hlist_head *head;
|
|
|
spinlock_t *list_lock; /* protects write access to the hash lists */
|
|
|
uint32_t i;
|
|
@@ -570,10 +577,10 @@ static void batadv_tt_local_table_free(struct batadv_priv *bat_priv)
|
|
|
struct hlist_head *head;
|
|
|
uint32_t i;
|
|
|
|
|
|
- if (!bat_priv->tt_local_hash)
|
|
|
+ if (!bat_priv->tt.local_hash)
|
|
|
return;
|
|
|
|
|
|
- hash = bat_priv->tt_local_hash;
|
|
|
+ hash = bat_priv->tt.local_hash;
|
|
|
|
|
|
for (i = 0; i < hash->size; i++) {
|
|
|
head = &hash->table[i];
|
|
@@ -593,17 +600,17 @@ static void batadv_tt_local_table_free(struct batadv_priv *bat_priv)
|
|
|
|
|
|
batadv_hash_destroy(hash);
|
|
|
|
|
|
- bat_priv->tt_local_hash = NULL;
|
|
|
+ bat_priv->tt.local_hash = NULL;
|
|
|
}
|
|
|
|
|
|
static int batadv_tt_global_init(struct batadv_priv *bat_priv)
|
|
|
{
|
|
|
- if (bat_priv->tt_global_hash)
|
|
|
+ if (bat_priv->tt.global_hash)
|
|
|
return 0;
|
|
|
|
|
|
- bat_priv->tt_global_hash = batadv_hash_new(1024);
|
|
|
+ bat_priv->tt.global_hash = batadv_hash_new(1024);
|
|
|
|
|
|
- if (!bat_priv->tt_global_hash)
|
|
|
+ if (!bat_priv->tt.global_hash)
|
|
|
return -ENOMEM;
|
|
|
|
|
|
return 0;
|
|
@@ -613,62 +620,99 @@ static void batadv_tt_changes_list_free(struct batadv_priv *bat_priv)
|
|
|
{
|
|
|
struct batadv_tt_change_node *entry, *safe;
|
|
|
|
|
|
- spin_lock_bh(&bat_priv->tt_changes_list_lock);
|
|
|
+ spin_lock_bh(&bat_priv->tt.changes_list_lock);
|
|
|
|
|
|
- list_for_each_entry_safe(entry, safe, &bat_priv->tt_changes_list,
|
|
|
+ list_for_each_entry_safe(entry, safe, &bat_priv->tt.changes_list,
|
|
|
list) {
|
|
|
list_del(&entry->list);
|
|
|
kfree(entry);
|
|
|
}
|
|
|
|
|
|
- atomic_set(&bat_priv->tt_local_changes, 0);
|
|
|
- spin_unlock_bh(&bat_priv->tt_changes_list_lock);
|
|
|
+ atomic_set(&bat_priv->tt.local_changes, 0);
|
|
|
+ spin_unlock_bh(&bat_priv->tt.changes_list_lock);
|
|
|
}
|
|
|
|
|
|
-/* find out if an orig_node is already in the list of a tt_global_entry.
|
|
|
- * returns 1 if found, 0 otherwise
|
|
|
+/* retrieves the orig_tt_list_entry belonging to orig_node from the
|
|
|
+ * batadv_tt_global_entry list
|
|
|
+ *
|
|
|
+ * returns it with an increased refcounter, NULL if not found
|
|
|
*/
|
|
|
-static bool
|
|
|
-batadv_tt_global_entry_has_orig(const struct batadv_tt_global_entry *entry,
|
|
|
- const struct batadv_orig_node *orig_node)
|
|
|
+static struct batadv_tt_orig_list_entry *
|
|
|
+batadv_tt_global_orig_entry_find(const struct batadv_tt_global_entry *entry,
|
|
|
+ const struct batadv_orig_node *orig_node)
|
|
|
{
|
|
|
- struct batadv_tt_orig_list_entry *tmp_orig_entry;
|
|
|
+ struct batadv_tt_orig_list_entry *tmp_orig_entry, *orig_entry = NULL;
|
|
|
const struct hlist_head *head;
|
|
|
struct hlist_node *node;
|
|
|
- bool found = false;
|
|
|
|
|
|
rcu_read_lock();
|
|
|
head = &entry->orig_list;
|
|
|
hlist_for_each_entry_rcu(tmp_orig_entry, node, head, list) {
|
|
|
- if (tmp_orig_entry->orig_node == orig_node) {
|
|
|
- found = true;
|
|
|
- break;
|
|
|
- }
|
|
|
+ if (tmp_orig_entry->orig_node != orig_node)
|
|
|
+ continue;
|
|
|
+ if (!atomic_inc_not_zero(&tmp_orig_entry->refcount))
|
|
|
+ continue;
|
|
|
+
|
|
|
+ orig_entry = tmp_orig_entry;
|
|
|
+ break;
|
|
|
}
|
|
|
rcu_read_unlock();
|
|
|
+
|
|
|
+ return orig_entry;
|
|
|
+}
|
|
|
+
|
|
|
+/* find out if an orig_node is already in the list of a tt_global_entry.
|
|
|
+ * returns true if found, false otherwise
|
|
|
+ */
|
|
|
+static bool
|
|
|
+batadv_tt_global_entry_has_orig(const struct batadv_tt_global_entry *entry,
|
|
|
+ const struct batadv_orig_node *orig_node)
|
|
|
+{
|
|
|
+ struct batadv_tt_orig_list_entry *orig_entry;
|
|
|
+ bool found = false;
|
|
|
+
|
|
|
+ orig_entry = batadv_tt_global_orig_entry_find(entry, orig_node);
|
|
|
+ if (orig_entry) {
|
|
|
+ found = true;
|
|
|
+ batadv_tt_orig_list_entry_free_ref(orig_entry);
|
|
|
+ }
|
|
|
+
|
|
|
return found;
|
|
|
}
|
|
|
|
|
|
static void
|
|
|
-batadv_tt_global_add_orig_entry(struct batadv_tt_global_entry *tt_global_entry,
|
|
|
+batadv_tt_global_orig_entry_add(struct batadv_tt_global_entry *tt_global,
|
|
|
struct batadv_orig_node *orig_node, int ttvn)
|
|
|
{
|
|
|
struct batadv_tt_orig_list_entry *orig_entry;
|
|
|
|
|
|
+ orig_entry = batadv_tt_global_orig_entry_find(tt_global, orig_node);
|
|
|
+ if (orig_entry) {
|
|
|
+ /* refresh the ttvn: the current value could be a bogus one that
|
|
|
+ * was added during a "temporary client detection"
|
|
|
+ */
|
|
|
+ orig_entry->ttvn = ttvn;
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+
|
|
|
orig_entry = kzalloc(sizeof(*orig_entry), GFP_ATOMIC);
|
|
|
if (!orig_entry)
|
|
|
- return;
|
|
|
+ goto out;
|
|
|
|
|
|
INIT_HLIST_NODE(&orig_entry->list);
|
|
|
atomic_inc(&orig_node->refcount);
|
|
|
atomic_inc(&orig_node->tt_size);
|
|
|
orig_entry->orig_node = orig_node;
|
|
|
orig_entry->ttvn = ttvn;
|
|
|
+ atomic_set(&orig_entry->refcount, 2);
|
|
|
|
|
|
- spin_lock_bh(&tt_global_entry->list_lock);
|
|
|
+ spin_lock_bh(&tt_global->list_lock);
|
|
|
hlist_add_head_rcu(&orig_entry->list,
|
|
|
- &tt_global_entry->orig_list);
|
|
|
- spin_unlock_bh(&tt_global_entry->list_lock);
|
|
|
+ &tt_global->orig_list);
|
|
|
+ spin_unlock_bh(&tt_global->list_lock);
|
|
|
+out:
|
|
|
+ if (orig_entry)
|
|
|
+ batadv_tt_orig_list_entry_free_ref(orig_entry);
|
|
|
}
|
|
|
|
|
|
/* caller must hold orig_node refcount */
|
|
@@ -695,11 +739,12 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv,
|
|
|
common->flags = flags;
|
|
|
tt_global_entry->roam_at = 0;
|
|
|
atomic_set(&common->refcount, 2);
|
|
|
+ common->added_at = jiffies;
|
|
|
|
|
|
INIT_HLIST_HEAD(&tt_global_entry->orig_list);
|
|
|
spin_lock_init(&tt_global_entry->list_lock);
|
|
|
|
|
|
- hash_added = batadv_hash_add(bat_priv->tt_global_hash,
|
|
|
+ hash_added = batadv_hash_add(bat_priv->tt.global_hash,
|
|
|
batadv_compare_tt,
|
|
|
batadv_choose_orig, common,
|
|
|
&common->hash_entry);
|
|
@@ -709,11 +754,20 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv,
|
|
|
batadv_tt_global_entry_free_ref(tt_global_entry);
|
|
|
goto out_remove;
|
|
|
}
|
|
|
-
|
|
|
- batadv_tt_global_add_orig_entry(tt_global_entry, orig_node,
|
|
|
- ttvn);
|
|
|
} else {
|
|
|
- /* there is already a global entry, use this one. */
|
|
|
+ /* If there is already a global entry, we can use this one for
|
|
|
+ * our processing.
|
|
|
+ * But if we are trying to add a temporary client we can exit
|
|
|
+ * directly because the temporary information should never
|
|
|
+ * override any already known client state (whatever it is)
|
|
|
+ */
|
|
|
+ if (flags & BATADV_TT_CLIENT_TEMP)
|
|
|
+ goto out;
|
|
|
+
|
|
|
+ /* if the client was temporary added before receiving the first
|
|
|
+ * OGM announcing it, we have to clear the TEMP flag
|
|
|
+ */
|
|
|
+ tt_global_entry->common.flags &= ~BATADV_TT_CLIENT_TEMP;
|
|
|
|
|
|
/* If there is the BATADV_TT_CLIENT_ROAM flag set, there is only
|
|
|
* one originator left in the list and we previously received a
|
|
@@ -727,12 +781,9 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv,
|
|
|
tt_global_entry->common.flags &= ~BATADV_TT_CLIENT_ROAM;
|
|
|
tt_global_entry->roam_at = 0;
|
|
|
}
|
|
|
-
|
|
|
- if (!batadv_tt_global_entry_has_orig(tt_global_entry,
|
|
|
- orig_node))
|
|
|
- batadv_tt_global_add_orig_entry(tt_global_entry,
|
|
|
- orig_node, ttvn);
|
|
|
}
|
|
|
+ /* add the new orig_entry (if needed) or update it */
|
|
|
+ batadv_tt_global_orig_entry_add(tt_global_entry, orig_node, ttvn);
|
|
|
|
|
|
batadv_dbg(BATADV_DBG_TT, bat_priv,
|
|
|
"Creating new global tt entry: %pM (via %pM)\n",
|
|
@@ -771,11 +822,12 @@ batadv_tt_global_print_entry(struct batadv_tt_global_entry *tt_global_entry,
|
|
|
hlist_for_each_entry_rcu(orig_entry, node, head, list) {
|
|
|
flags = tt_common_entry->flags;
|
|
|
last_ttvn = atomic_read(&orig_entry->orig_node->last_ttvn);
|
|
|
- seq_printf(seq, " * %pM (%3u) via %pM (%3u) [%c%c]\n",
|
|
|
+ seq_printf(seq, " * %pM (%3u) via %pM (%3u) [%c%c%c]\n",
|
|
|
tt_global_entry->common.addr, orig_entry->ttvn,
|
|
|
orig_entry->orig_node->orig, last_ttvn,
|
|
|
(flags & BATADV_TT_CLIENT_ROAM ? 'R' : '.'),
|
|
|
- (flags & BATADV_TT_CLIENT_WIFI ? 'W' : '.'));
|
|
|
+ (flags & BATADV_TT_CLIENT_WIFI ? 'W' : '.'),
|
|
|
+ (flags & BATADV_TT_CLIENT_TEMP ? 'T' : '.'));
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -783,7 +835,7 @@ int batadv_tt_global_seq_print_text(struct seq_file *seq, void *offset)
|
|
|
{
|
|
|
struct net_device *net_dev = (struct net_device *)seq->private;
|
|
|
struct batadv_priv *bat_priv = netdev_priv(net_dev);
|
|
|
- struct batadv_hashtable *hash = bat_priv->tt_global_hash;
|
|
|
+ struct batadv_hashtable *hash = bat_priv->tt.global_hash;
|
|
|
struct batadv_tt_common_entry *tt_common_entry;
|
|
|
struct batadv_tt_global_entry *tt_global;
|
|
|
struct batadv_hard_iface *primary_if;
|
|
@@ -884,7 +936,7 @@ batadv_tt_global_del_struct(struct batadv_priv *bat_priv,
|
|
|
"Deleting global tt entry %pM: %s\n",
|
|
|
tt_global_entry->common.addr, message);
|
|
|
|
|
|
- batadv_hash_remove(bat_priv->tt_global_hash, batadv_compare_tt,
|
|
|
+ batadv_hash_remove(bat_priv->tt.global_hash, batadv_compare_tt,
|
|
|
batadv_choose_orig, tt_global_entry->common.addr);
|
|
|
batadv_tt_global_entry_free_ref(tt_global_entry);
|
|
|
|
|
@@ -995,7 +1047,7 @@ void batadv_tt_global_del_orig(struct batadv_priv *bat_priv,
|
|
|
struct batadv_tt_global_entry *tt_global;
|
|
|
struct batadv_tt_common_entry *tt_common_entry;
|
|
|
uint32_t i;
|
|
|
- struct batadv_hashtable *hash = bat_priv->tt_global_hash;
|
|
|
+ struct batadv_hashtable *hash = bat_priv->tt.global_hash;
|
|
|
struct hlist_node *node, *safe;
|
|
|
struct hlist_head *head;
|
|
|
spinlock_t *list_lock; /* protects write access to the hash lists */
|
|
@@ -1030,49 +1082,63 @@ void batadv_tt_global_del_orig(struct batadv_priv *bat_priv,
|
|
|
orig_node->tt_initialised = false;
|
|
|
}
|
|
|
|
|
|
-static void batadv_tt_global_roam_purge_list(struct batadv_priv *bat_priv,
|
|
|
- struct hlist_head *head)
|
|
|
+static bool batadv_tt_global_to_purge(struct batadv_tt_global_entry *tt_global,
|
|
|
+ char **msg)
|
|
|
{
|
|
|
- struct batadv_tt_common_entry *tt_common_entry;
|
|
|
- struct batadv_tt_global_entry *tt_global_entry;
|
|
|
- struct hlist_node *node, *node_tmp;
|
|
|
-
|
|
|
- hlist_for_each_entry_safe(tt_common_entry, node, node_tmp, head,
|
|
|
- hash_entry) {
|
|
|
- tt_global_entry = container_of(tt_common_entry,
|
|
|
- struct batadv_tt_global_entry,
|
|
|
- common);
|
|
|
- if (!(tt_global_entry->common.flags & BATADV_TT_CLIENT_ROAM))
|
|
|
- continue;
|
|
|
- if (!batadv_has_timed_out(tt_global_entry->roam_at,
|
|
|
- BATADV_TT_CLIENT_ROAM_TIMEOUT))
|
|
|
- continue;
|
|
|
+ bool purge = false;
|
|
|
+ unsigned long roam_timeout = BATADV_TT_CLIENT_ROAM_TIMEOUT;
|
|
|
+ unsigned long temp_timeout = BATADV_TT_CLIENT_TEMP_TIMEOUT;
|
|
|
|
|
|
- batadv_dbg(BATADV_DBG_TT, bat_priv,
|
|
|
- "Deleting global tt entry (%pM): Roaming timeout\n",
|
|
|
- tt_global_entry->common.addr);
|
|
|
+ if ((tt_global->common.flags & BATADV_TT_CLIENT_ROAM) &&
|
|
|
+ batadv_has_timed_out(tt_global->roam_at, roam_timeout)) {
|
|
|
+ purge = true;
|
|
|
+ *msg = "Roaming timeout\n";
|
|
|
+ }
|
|
|
|
|
|
- hlist_del_rcu(node);
|
|
|
- batadv_tt_global_entry_free_ref(tt_global_entry);
|
|
|
+ if ((tt_global->common.flags & BATADV_TT_CLIENT_TEMP) &&
|
|
|
+ batadv_has_timed_out(tt_global->common.added_at, temp_timeout)) {
|
|
|
+ purge = true;
|
|
|
+ *msg = "Temporary client timeout\n";
|
|
|
}
|
|
|
+
|
|
|
+ return purge;
|
|
|
}
|
|
|
|
|
|
-static void batadv_tt_global_roam_purge(struct batadv_priv *bat_priv)
|
|
|
+static void batadv_tt_global_purge(struct batadv_priv *bat_priv)
|
|
|
{
|
|
|
- struct batadv_hashtable *hash = bat_priv->tt_global_hash;
|
|
|
+ struct batadv_hashtable *hash = bat_priv->tt.global_hash;
|
|
|
struct hlist_head *head;
|
|
|
+ struct hlist_node *node, *node_tmp;
|
|
|
spinlock_t *list_lock; /* protects write access to the hash lists */
|
|
|
uint32_t i;
|
|
|
+ char *msg = NULL;
|
|
|
+ struct batadv_tt_common_entry *tt_common;
|
|
|
+ struct batadv_tt_global_entry *tt_global;
|
|
|
|
|
|
for (i = 0; i < hash->size; i++) {
|
|
|
head = &hash->table[i];
|
|
|
list_lock = &hash->list_locks[i];
|
|
|
|
|
|
spin_lock_bh(list_lock);
|
|
|
- batadv_tt_global_roam_purge_list(bat_priv, head);
|
|
|
+ hlist_for_each_entry_safe(tt_common, node, node_tmp, head,
|
|
|
+ hash_entry) {
|
|
|
+ tt_global = container_of(tt_common,
|
|
|
+ struct batadv_tt_global_entry,
|
|
|
+ common);
|
|
|
+
|
|
|
+ if (!batadv_tt_global_to_purge(tt_global, &msg))
|
|
|
+ continue;
|
|
|
+
|
|
|
+ batadv_dbg(BATADV_DBG_TT, bat_priv,
|
|
|
+ "Deleting global tt entry (%pM): %s\n",
|
|
|
+ tt_global->common.addr, msg);
|
|
|
+
|
|
|
+ hlist_del_rcu(node);
|
|
|
+
|
|
|
+ batadv_tt_global_entry_free_ref(tt_global);
|
|
|
+ }
|
|
|
spin_unlock_bh(list_lock);
|
|
|
}
|
|
|
-
|
|
|
}
|
|
|
|
|
|
static void batadv_tt_global_table_free(struct batadv_priv *bat_priv)
|
|
@@ -1085,10 +1151,10 @@ static void batadv_tt_global_table_free(struct batadv_priv *bat_priv)
|
|
|
struct hlist_head *head;
|
|
|
uint32_t i;
|
|
|
|
|
|
- if (!bat_priv->tt_global_hash)
|
|
|
+ if (!bat_priv->tt.global_hash)
|
|
|
return;
|
|
|
|
|
|
- hash = bat_priv->tt_global_hash;
|
|
|
+ hash = bat_priv->tt.global_hash;
|
|
|
|
|
|
for (i = 0; i < hash->size; i++) {
|
|
|
head = &hash->table[i];
|
|
@@ -1108,7 +1174,7 @@ static void batadv_tt_global_table_free(struct batadv_priv *bat_priv)
|
|
|
|
|
|
batadv_hash_destroy(hash);
|
|
|
|
|
|
- bat_priv->tt_global_hash = NULL;
|
|
|
+ bat_priv->tt.global_hash = NULL;
|
|
|
}
|
|
|
|
|
|
static bool
|
|
@@ -1187,7 +1253,7 @@ static uint16_t batadv_tt_global_crc(struct batadv_priv *bat_priv,
|
|
|
struct batadv_orig_node *orig_node)
|
|
|
{
|
|
|
uint16_t total = 0, total_one;
|
|
|
- struct batadv_hashtable *hash = bat_priv->tt_global_hash;
|
|
|
+ struct batadv_hashtable *hash = bat_priv->tt.global_hash;
|
|
|
struct batadv_tt_common_entry *tt_common;
|
|
|
struct batadv_tt_global_entry *tt_global;
|
|
|
struct hlist_node *node;
|
|
@@ -1210,6 +1276,12 @@ static uint16_t batadv_tt_global_crc(struct batadv_priv *bat_priv,
|
|
|
*/
|
|
|
if (tt_common->flags & BATADV_TT_CLIENT_ROAM)
|
|
|
continue;
|
|
|
+ /* Temporary clients have not been announced yet, so
|
|
|
+ * they have to be skipped while computing the global
|
|
|
+ * crc
|
|
|
+ */
|
|
|
+ if (tt_common->flags & BATADV_TT_CLIENT_TEMP)
|
|
|
+ continue;
|
|
|
|
|
|
/* find out if this global entry is announced by this
|
|
|
* originator
|
|
@@ -1234,7 +1306,7 @@ static uint16_t batadv_tt_global_crc(struct batadv_priv *bat_priv,
|
|
|
static uint16_t batadv_tt_local_crc(struct batadv_priv *bat_priv)
|
|
|
{
|
|
|
uint16_t total = 0, total_one;
|
|
|
- struct batadv_hashtable *hash = bat_priv->tt_local_hash;
|
|
|
+ struct batadv_hashtable *hash = bat_priv->tt.local_hash;
|
|
|
struct batadv_tt_common_entry *tt_common;
|
|
|
struct hlist_node *node;
|
|
|
struct hlist_head *head;
|
|
@@ -1267,14 +1339,14 @@ static void batadv_tt_req_list_free(struct batadv_priv *bat_priv)
|
|
|
{
|
|
|
struct batadv_tt_req_node *node, *safe;
|
|
|
|
|
|
- spin_lock_bh(&bat_priv->tt_req_list_lock);
|
|
|
+ spin_lock_bh(&bat_priv->tt.req_list_lock);
|
|
|
|
|
|
- list_for_each_entry_safe(node, safe, &bat_priv->tt_req_list, list) {
|
|
|
+ list_for_each_entry_safe(node, safe, &bat_priv->tt.req_list, list) {
|
|
|
list_del(&node->list);
|
|
|
kfree(node);
|
|
|
}
|
|
|
|
|
|
- spin_unlock_bh(&bat_priv->tt_req_list_lock);
|
|
|
+ spin_unlock_bh(&bat_priv->tt.req_list_lock);
|
|
|
}
|
|
|
|
|
|
static void batadv_tt_save_orig_buffer(struct batadv_priv *bat_priv,
|
|
@@ -1304,15 +1376,15 @@ static void batadv_tt_req_purge(struct batadv_priv *bat_priv)
|
|
|
{
|
|
|
struct batadv_tt_req_node *node, *safe;
|
|
|
|
|
|
- spin_lock_bh(&bat_priv->tt_req_list_lock);
|
|
|
- list_for_each_entry_safe(node, safe, &bat_priv->tt_req_list, list) {
|
|
|
+ spin_lock_bh(&bat_priv->tt.req_list_lock);
|
|
|
+ list_for_each_entry_safe(node, safe, &bat_priv->tt.req_list, list) {
|
|
|
if (batadv_has_timed_out(node->issued_at,
|
|
|
BATADV_TT_REQUEST_TIMEOUT)) {
|
|
|
list_del(&node->list);
|
|
|
kfree(node);
|
|
|
}
|
|
|
}
|
|
|
- spin_unlock_bh(&bat_priv->tt_req_list_lock);
|
|
|
+ spin_unlock_bh(&bat_priv->tt.req_list_lock);
|
|
|
}
|
|
|
|
|
|
/* returns the pointer to the new tt_req_node struct if no request
|
|
@@ -1324,8 +1396,8 @@ batadv_new_tt_req_node(struct batadv_priv *bat_priv,
|
|
|
{
|
|
|
struct batadv_tt_req_node *tt_req_node_tmp, *tt_req_node = NULL;
|
|
|
|
|
|
- spin_lock_bh(&bat_priv->tt_req_list_lock);
|
|
|
- list_for_each_entry(tt_req_node_tmp, &bat_priv->tt_req_list, list) {
|
|
|
+ spin_lock_bh(&bat_priv->tt.req_list_lock);
|
|
|
+ list_for_each_entry(tt_req_node_tmp, &bat_priv->tt.req_list, list) {
|
|
|
if (batadv_compare_eth(tt_req_node_tmp, orig_node) &&
|
|
|
!batadv_has_timed_out(tt_req_node_tmp->issued_at,
|
|
|
BATADV_TT_REQUEST_TIMEOUT))
|
|
@@ -1339,9 +1411,9 @@ batadv_new_tt_req_node(struct batadv_priv *bat_priv,
|
|
|
memcpy(tt_req_node->addr, orig_node->orig, ETH_ALEN);
|
|
|
tt_req_node->issued_at = jiffies;
|
|
|
|
|
|
- list_add(&tt_req_node->list, &bat_priv->tt_req_list);
|
|
|
+ list_add(&tt_req_node->list, &bat_priv->tt.req_list);
|
|
|
unlock:
|
|
|
- spin_unlock_bh(&bat_priv->tt_req_list_lock);
|
|
|
+ spin_unlock_bh(&bat_priv->tt.req_list_lock);
|
|
|
return tt_req_node;
|
|
|
}
|
|
|
|
|
@@ -1363,7 +1435,8 @@ static int batadv_tt_global_valid(const void *entry_ptr,
|
|
|
const struct batadv_tt_global_entry *tt_global_entry;
|
|
|
const struct batadv_orig_node *orig_node = data_ptr;
|
|
|
|
|
|
- if (tt_common_entry->flags & BATADV_TT_CLIENT_ROAM)
|
|
|
+ if (tt_common_entry->flags & BATADV_TT_CLIENT_ROAM ||
|
|
|
+ tt_common_entry->flags & BATADV_TT_CLIENT_TEMP)
|
|
|
return 0;
|
|
|
|
|
|
tt_global_entry = container_of(tt_common_entry,
|
|
@@ -1507,9 +1580,9 @@ out:
|
|
|
if (ret)
|
|
|
kfree_skb(skb);
|
|
|
if (ret && tt_req_node) {
|
|
|
- spin_lock_bh(&bat_priv->tt_req_list_lock);
|
|
|
+ spin_lock_bh(&bat_priv->tt.req_list_lock);
|
|
|
list_del(&tt_req_node->list);
|
|
|
- spin_unlock_bh(&bat_priv->tt_req_list_lock);
|
|
|
+ spin_unlock_bh(&bat_priv->tt.req_list_lock);
|
|
|
kfree(tt_req_node);
|
|
|
}
|
|
|
return ret;
|
|
@@ -1530,6 +1603,7 @@ batadv_send_other_tt_response(struct batadv_priv *bat_priv,
|
|
|
uint16_t tt_len, tt_tot;
|
|
|
struct sk_buff *skb = NULL;
|
|
|
struct batadv_tt_query_packet *tt_response;
|
|
|
+ uint8_t *packet_pos;
|
|
|
size_t len;
|
|
|
|
|
|
batadv_dbg(BATADV_DBG_TT, bat_priv,
|
|
@@ -1583,8 +1657,8 @@ batadv_send_other_tt_response(struct batadv_priv *bat_priv,
|
|
|
goto unlock;
|
|
|
|
|
|
skb_reserve(skb, ETH_HLEN);
|
|
|
- tt_response = (struct batadv_tt_query_packet *)skb_put(skb,
|
|
|
- len);
|
|
|
+ packet_pos = skb_put(skb, len);
|
|
|
+ tt_response = (struct batadv_tt_query_packet *)packet_pos;
|
|
|
tt_response->ttvn = req_ttvn;
|
|
|
tt_response->tt_data = htons(tt_tot);
|
|
|
|
|
@@ -1600,7 +1674,7 @@ batadv_send_other_tt_response(struct batadv_priv *bat_priv,
|
|
|
ttvn = (uint8_t)atomic_read(&req_dst_orig_node->last_ttvn);
|
|
|
|
|
|
skb = batadv_tt_response_fill_table(tt_len, ttvn,
|
|
|
- bat_priv->tt_global_hash,
|
|
|
+ bat_priv->tt.global_hash,
|
|
|
primary_if,
|
|
|
batadv_tt_global_valid,
|
|
|
req_dst_orig_node);
|
|
@@ -1663,6 +1737,7 @@ batadv_send_my_tt_response(struct batadv_priv *bat_priv,
|
|
|
uint16_t tt_len, tt_tot;
|
|
|
struct sk_buff *skb = NULL;
|
|
|
struct batadv_tt_query_packet *tt_response;
|
|
|
+ uint8_t *packet_pos;
|
|
|
size_t len;
|
|
|
|
|
|
batadv_dbg(BATADV_DBG_TT, bat_priv,
|
|
@@ -1671,7 +1746,7 @@ batadv_send_my_tt_response(struct batadv_priv *bat_priv,
|
|
|
(tt_request->flags & BATADV_TT_FULL_TABLE ? 'F' : '.'));
|
|
|
|
|
|
|
|
|
- my_ttvn = (uint8_t)atomic_read(&bat_priv->ttvn);
|
|
|
+ my_ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn);
|
|
|
req_ttvn = tt_request->ttvn;
|
|
|
|
|
|
orig_node = batadv_orig_hash_find(bat_priv, tt_request->src);
|
|
@@ -1690,7 +1765,7 @@ batadv_send_my_tt_response(struct batadv_priv *bat_priv,
|
|
|
* is too big send the whole local translation table
|
|
|
*/
|
|
|
if (tt_request->flags & BATADV_TT_FULL_TABLE || my_ttvn != req_ttvn ||
|
|
|
- !bat_priv->tt_buff)
|
|
|
+ !bat_priv->tt.last_changeset)
|
|
|
full_table = true;
|
|
|
else
|
|
|
full_table = false;
|
|
@@ -1699,8 +1774,8 @@ batadv_send_my_tt_response(struct batadv_priv *bat_priv,
|
|
|
* I'll send only one packet with as much TT entries as I can
|
|
|
*/
|
|
|
if (!full_table) {
|
|
|
- spin_lock_bh(&bat_priv->tt_buff_lock);
|
|
|
- tt_len = bat_priv->tt_buff_len;
|
|
|
+ spin_lock_bh(&bat_priv->tt.last_changeset_lock);
|
|
|
+ tt_len = bat_priv->tt.last_changeset_len;
|
|
|
tt_tot = tt_len / sizeof(struct batadv_tt_change);
|
|
|
|
|
|
len = sizeof(*tt_response) + tt_len;
|
|
@@ -1709,22 +1784,22 @@ batadv_send_my_tt_response(struct batadv_priv *bat_priv,
|
|
|
goto unlock;
|
|
|
|
|
|
skb_reserve(skb, ETH_HLEN);
|
|
|
- tt_response = (struct batadv_tt_query_packet *)skb_put(skb,
|
|
|
- len);
|
|
|
+ packet_pos = skb_put(skb, len);
|
|
|
+ tt_response = (struct batadv_tt_query_packet *)packet_pos;
|
|
|
tt_response->ttvn = req_ttvn;
|
|
|
tt_response->tt_data = htons(tt_tot);
|
|
|
|
|
|
tt_buff = skb->data + sizeof(*tt_response);
|
|
|
- memcpy(tt_buff, bat_priv->tt_buff,
|
|
|
- bat_priv->tt_buff_len);
|
|
|
- spin_unlock_bh(&bat_priv->tt_buff_lock);
|
|
|
+ memcpy(tt_buff, bat_priv->tt.last_changeset,
|
|
|
+ bat_priv->tt.last_changeset_len);
|
|
|
+ spin_unlock_bh(&bat_priv->tt.last_changeset_lock);
|
|
|
} else {
|
|
|
- tt_len = (uint16_t)atomic_read(&bat_priv->num_local_tt);
|
|
|
+ tt_len = (uint16_t)atomic_read(&bat_priv->tt.local_entry_num);
|
|
|
tt_len *= sizeof(struct batadv_tt_change);
|
|
|
- ttvn = (uint8_t)atomic_read(&bat_priv->ttvn);
|
|
|
+ ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn);
|
|
|
|
|
|
skb = batadv_tt_response_fill_table(tt_len, ttvn,
|
|
|
- bat_priv->tt_local_hash,
|
|
|
+ bat_priv->tt.local_hash,
|
|
|
primary_if,
|
|
|
batadv_tt_local_valid_entry,
|
|
|
NULL);
|
|
@@ -1756,7 +1831,7 @@ batadv_send_my_tt_response(struct batadv_priv *bat_priv,
|
|
|
goto out;
|
|
|
|
|
|
unlock:
|
|
|
- spin_unlock_bh(&bat_priv->tt_buff_lock);
|
|
|
+ spin_unlock_bh(&bat_priv->tt.last_changeset_lock);
|
|
|
out:
|
|
|
if (orig_node)
|
|
|
batadv_orig_node_free_ref(orig_node);
|
|
@@ -1909,14 +1984,14 @@ void batadv_handle_tt_response(struct batadv_priv *bat_priv,
|
|
|
}
|
|
|
|
|
|
/* Delete the tt_req_node from pending tt_requests list */
|
|
|
- spin_lock_bh(&bat_priv->tt_req_list_lock);
|
|
|
- list_for_each_entry_safe(node, safe, &bat_priv->tt_req_list, list) {
|
|
|
+ spin_lock_bh(&bat_priv->tt.req_list_lock);
|
|
|
+ list_for_each_entry_safe(node, safe, &bat_priv->tt.req_list, list) {
|
|
|
if (!batadv_compare_eth(node->addr, tt_response->src))
|
|
|
continue;
|
|
|
list_del(&node->list);
|
|
|
kfree(node);
|
|
|
}
|
|
|
- spin_unlock_bh(&bat_priv->tt_req_list_lock);
|
|
|
+ spin_unlock_bh(&bat_priv->tt.req_list_lock);
|
|
|
|
|
|
/* Recalculate the CRC for this orig_node and store it */
|
|
|
orig_node->tt_crc = batadv_tt_global_crc(bat_priv, orig_node);
|
|
@@ -1950,22 +2025,22 @@ static void batadv_tt_roam_list_free(struct batadv_priv *bat_priv)
|
|
|
{
|
|
|
struct batadv_tt_roam_node *node, *safe;
|
|
|
|
|
|
- spin_lock_bh(&bat_priv->tt_roam_list_lock);
|
|
|
+ spin_lock_bh(&bat_priv->tt.roam_list_lock);
|
|
|
|
|
|
- list_for_each_entry_safe(node, safe, &bat_priv->tt_roam_list, list) {
|
|
|
+ list_for_each_entry_safe(node, safe, &bat_priv->tt.roam_list, list) {
|
|
|
list_del(&node->list);
|
|
|
kfree(node);
|
|
|
}
|
|
|
|
|
|
- spin_unlock_bh(&bat_priv->tt_roam_list_lock);
|
|
|
+ spin_unlock_bh(&bat_priv->tt.roam_list_lock);
|
|
|
}
|
|
|
|
|
|
static void batadv_tt_roam_purge(struct batadv_priv *bat_priv)
|
|
|
{
|
|
|
struct batadv_tt_roam_node *node, *safe;
|
|
|
|
|
|
- spin_lock_bh(&bat_priv->tt_roam_list_lock);
|
|
|
- list_for_each_entry_safe(node, safe, &bat_priv->tt_roam_list, list) {
|
|
|
+ spin_lock_bh(&bat_priv->tt.roam_list_lock);
|
|
|
+ list_for_each_entry_safe(node, safe, &bat_priv->tt.roam_list, list) {
|
|
|
if (!batadv_has_timed_out(node->first_time,
|
|
|
BATADV_ROAMING_MAX_TIME))
|
|
|
continue;
|
|
@@ -1973,7 +2048,7 @@ static void batadv_tt_roam_purge(struct batadv_priv *bat_priv)
|
|
|
list_del(&node->list);
|
|
|
kfree(node);
|
|
|
}
|
|
|
- spin_unlock_bh(&bat_priv->tt_roam_list_lock);
|
|
|
+ spin_unlock_bh(&bat_priv->tt.roam_list_lock);
|
|
|
}
|
|
|
|
|
|
/* This function checks whether the client already reached the
|
|
@@ -1988,11 +2063,11 @@ static bool batadv_tt_check_roam_count(struct batadv_priv *bat_priv,
|
|
|
struct batadv_tt_roam_node *tt_roam_node;
|
|
|
bool ret = false;
|
|
|
|
|
|
- spin_lock_bh(&bat_priv->tt_roam_list_lock);
|
|
|
+ spin_lock_bh(&bat_priv->tt.roam_list_lock);
|
|
|
/* The new tt_req will be issued only if I'm not waiting for a
|
|
|
* reply from the same orig_node yet
|
|
|
*/
|
|
|
- list_for_each_entry(tt_roam_node, &bat_priv->tt_roam_list, list) {
|
|
|
+ list_for_each_entry(tt_roam_node, &bat_priv->tt.roam_list, list) {
|
|
|
if (!batadv_compare_eth(tt_roam_node->addr, client))
|
|
|
continue;
|
|
|
|
|
@@ -2017,12 +2092,12 @@ static bool batadv_tt_check_roam_count(struct batadv_priv *bat_priv,
|
|
|
BATADV_ROAMING_MAX_COUNT - 1);
|
|
|
memcpy(tt_roam_node->addr, client, ETH_ALEN);
|
|
|
|
|
|
- list_add(&tt_roam_node->list, &bat_priv->tt_roam_list);
|
|
|
+ list_add(&tt_roam_node->list, &bat_priv->tt.roam_list);
|
|
|
ret = true;
|
|
|
}
|
|
|
|
|
|
unlock:
|
|
|
- spin_unlock_bh(&bat_priv->tt_roam_list_lock);
|
|
|
+ spin_unlock_bh(&bat_priv->tt.roam_list_lock);
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
@@ -2086,13 +2161,15 @@ out:
|
|
|
static void batadv_tt_purge(struct work_struct *work)
|
|
|
{
|
|
|
struct delayed_work *delayed_work;
|
|
|
+ struct batadv_priv_tt *priv_tt;
|
|
|
struct batadv_priv *bat_priv;
|
|
|
|
|
|
delayed_work = container_of(work, struct delayed_work, work);
|
|
|
- bat_priv = container_of(delayed_work, struct batadv_priv, tt_work);
|
|
|
+ priv_tt = container_of(delayed_work, struct batadv_priv_tt, work);
|
|
|
+ bat_priv = container_of(priv_tt, struct batadv_priv, tt);
|
|
|
|
|
|
batadv_tt_local_purge(bat_priv);
|
|
|
- batadv_tt_global_roam_purge(bat_priv);
|
|
|
+ batadv_tt_global_purge(bat_priv);
|
|
|
batadv_tt_req_purge(bat_priv);
|
|
|
batadv_tt_roam_purge(bat_priv);
|
|
|
|
|
@@ -2101,7 +2178,7 @@ static void batadv_tt_purge(struct work_struct *work)
|
|
|
|
|
|
void batadv_tt_free(struct batadv_priv *bat_priv)
|
|
|
{
|
|
|
- cancel_delayed_work_sync(&bat_priv->tt_work);
|
|
|
+ cancel_delayed_work_sync(&bat_priv->tt.work);
|
|
|
|
|
|
batadv_tt_local_table_free(bat_priv);
|
|
|
batadv_tt_global_table_free(bat_priv);
|
|
@@ -2109,7 +2186,7 @@ void batadv_tt_free(struct batadv_priv *bat_priv)
|
|
|
batadv_tt_changes_list_free(bat_priv);
|
|
|
batadv_tt_roam_list_free(bat_priv);
|
|
|
|
|
|
- kfree(bat_priv->tt_buff);
|
|
|
+ kfree(bat_priv->tt.last_changeset);
|
|
|
}
|
|
|
|
|
|
/* This function will enable or disable the specified flags for all the entries
|
|
@@ -2153,7 +2230,7 @@ out:
|
|
|
/* Purge out all the tt local entries marked with BATADV_TT_CLIENT_PENDING */
|
|
|
static void batadv_tt_local_purge_pending_clients(struct batadv_priv *bat_priv)
|
|
|
{
|
|
|
- struct batadv_hashtable *hash = bat_priv->tt_local_hash;
|
|
|
+ struct batadv_hashtable *hash = bat_priv->tt.local_hash;
|
|
|
struct batadv_tt_common_entry *tt_common;
|
|
|
struct batadv_tt_local_entry *tt_local;
|
|
|
struct hlist_node *node, *node_tmp;
|
|
@@ -2178,7 +2255,7 @@ static void batadv_tt_local_purge_pending_clients(struct batadv_priv *bat_priv)
|
|
|
"Deleting local tt entry (%pM): pending\n",
|
|
|
tt_common->addr);
|
|
|
|
|
|
- atomic_dec(&bat_priv->num_local_tt);
|
|
|
+ atomic_dec(&bat_priv->tt.local_entry_num);
|
|
|
hlist_del_rcu(node);
|
|
|
tt_local = container_of(tt_common,
|
|
|
struct batadv_tt_local_entry,
|
|
@@ -2196,26 +2273,26 @@ static int batadv_tt_commit_changes(struct batadv_priv *bat_priv,
|
|
|
{
|
|
|
uint16_t changed_num = 0;
|
|
|
|
|
|
- if (atomic_read(&bat_priv->tt_local_changes) < 1)
|
|
|
+ if (atomic_read(&bat_priv->tt.local_changes) < 1)
|
|
|
return -ENOENT;
|
|
|
|
|
|
- changed_num = batadv_tt_set_flags(bat_priv->tt_local_hash,
|
|
|
+ changed_num = batadv_tt_set_flags(bat_priv->tt.local_hash,
|
|
|
BATADV_TT_CLIENT_NEW, false);
|
|
|
|
|
|
/* all reset entries have to be counted as local entries */
|
|
|
- atomic_add(changed_num, &bat_priv->num_local_tt);
|
|
|
+ atomic_add(changed_num, &bat_priv->tt.local_entry_num);
|
|
|
batadv_tt_local_purge_pending_clients(bat_priv);
|
|
|
- bat_priv->tt_crc = batadv_tt_local_crc(bat_priv);
|
|
|
+ bat_priv->tt.local_crc = batadv_tt_local_crc(bat_priv);
|
|
|
|
|
|
/* Increment the TTVN only once per OGM interval */
|
|
|
- atomic_inc(&bat_priv->ttvn);
|
|
|
+ atomic_inc(&bat_priv->tt.vn);
|
|
|
batadv_dbg(BATADV_DBG_TT, bat_priv,
|
|
|
"Local changes committed, updating to ttvn %u\n",
|
|
|
- (uint8_t)atomic_read(&bat_priv->ttvn));
|
|
|
- bat_priv->tt_poss_change = false;
|
|
|
+ (uint8_t)atomic_read(&bat_priv->tt.vn));
|
|
|
+ bat_priv->tt.poss_change = false;
|
|
|
|
|
|
/* reset the sending counter */
|
|
|
- atomic_set(&bat_priv->tt_ogm_append_cnt, BATADV_TT_OGM_APPEND_MAX);
|
|
|
+ atomic_set(&bat_priv->tt.ogm_append_cnt, BATADV_TT_OGM_APPEND_MAX);
|
|
|
|
|
|
return batadv_tt_changes_fill_buff(bat_priv, packet_buff,
|
|
|
packet_buff_len, packet_min_len);
|
|
@@ -2235,7 +2312,7 @@ int batadv_tt_append_diff(struct batadv_priv *bat_priv,
|
|
|
|
|
|
/* if the changes have been sent often enough */
|
|
|
if ((tt_num_changes < 0) &&
|
|
|
- (!batadv_atomic_dec_not_zero(&bat_priv->tt_ogm_append_cnt))) {
|
|
|
+ (!batadv_atomic_dec_not_zero(&bat_priv->tt.ogm_append_cnt))) {
|
|
|
batadv_tt_realloc_packet_buff(packet_buff, packet_buff_len,
|
|
|
packet_min_len, packet_min_len);
|
|
|
tt_num_changes = 0;
|
|
@@ -2366,3 +2443,22 @@ bool batadv_tt_global_client_is_roaming(struct batadv_priv *bat_priv,
|
|
|
out:
|
|
|
return ret;
|
|
|
}
|
|
|
+
|
|
|
+bool batadv_tt_add_temporary_global_entry(struct batadv_priv *bat_priv,
|
|
|
+ struct batadv_orig_node *orig_node,
|
|
|
+ const unsigned char *addr)
|
|
|
+{
|
|
|
+ bool ret = false;
|
|
|
+
|
|
|
+ if (!batadv_tt_global_add(bat_priv, orig_node, addr,
|
|
|
+ BATADV_TT_CLIENT_TEMP,
|
|
|
+ atomic_read(&orig_node->last_ttvn)))
|
|
|
+ goto out;
|
|
|
+
|
|
|
+ batadv_dbg(BATADV_DBG_TT, bat_priv,
|
|
|
+ "Added temporary global client (addr: %pM orig: %pM)\n",
|
|
|
+ addr, orig_node->orig);
|
|
|
+ ret = true;
|
|
|
+out:
|
|
|
+ return ret;
|
|
|
+}
|