All of lore.kernel.org
 help / color / mirror / Atom feed
* [B.A.T.M.A.N.] [PATCH 0/5] batman-adv: tt code fixes and temporary client detection
@ 2012-04-03 21:50 Antonio Quartulli
  2012-04-03 21:50 ` [B.A.T.M.A.N.] [PATCH 1/5] batman-adv: clear ADD+DEL (and viceversa) events in the same orig-interval Antonio Quartulli
                   ` (4 more replies)
  0 siblings, 5 replies; 7+ messages in thread
From: Antonio Quartulli @ 2012-04-03 21:50 UTC (permalink / raw)
  To: b.a.t.m.a.n

This set of patches aims to first clean & fix the code a little bit in order to
prepare it for the temporary client recognition (patch 5/5).

Temporary client recognition: In the current implementation, whenever a client
joins the network it has to wait the next OGM in order to be announced to the
whole network (by means of the known TT mechanism). Before that time, the client
will be unable to communicate to whichever else client, so generating some delay
that usually leads to DHCP (or any other service) timeout. This problem is
amplified is for large originator interval.

Patch 5/5 add a temporary recognition mechanism which make every node in the
network "autodetect" the location (namely the node serving) the node yet
announced client

Known issues: right now, multiple temporary announcement of the same client is
not supported; roaming of temporary client is not supported.
Support for this two features will be added soon.


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [B.A.T.M.A.N.] [PATCH 1/5] batman-adv: clear ADD+DEL (and viceversa) events in the same orig-interval
  2012-04-03 21:50 [B.A.T.M.A.N.] [PATCH 0/5] batman-adv: tt code fixes and temporary client detection Antonio Quartulli
@ 2012-04-03 21:50 ` Antonio Quartulli
  2012-04-03 21:50 ` [B.A.T.M.A.N.] [PATCH 2/5] batman-adv: clear the PENDING flag in case of client re-addition Antonio Quartulli
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: Antonio Quartulli @ 2012-04-03 21:50 UTC (permalink / raw)
  To: b.a.t.m.a.n

During an OGM-interval (time between two different OGM sendings) the same client
could roam away and then roam back to us. In this case the node would add two
events to the events list (that is going to be sent appended to the next OGM). A
DEL one and an ADD one. Obviously they will only increase the overhead (either in
the air and on the receiver side) and eventually trigger wrong states/events
without producing any real effect.

For this reason we can safely delete any ADD event with its related DEL one.

Signed-off-by: Antonio Quartulli <ordex@autistici.org>
---
 translation-table.c |   35 ++++++++++++++++++++++++++++++-----
 1 file changed, 30 insertions(+), 5 deletions(-)

diff --git a/translation-table.c b/translation-table.c
index 934900d..438b786 100644
--- a/translation-table.c
+++ b/translation-table.c
@@ -154,23 +154,48 @@ static void tt_orig_list_entry_free_ref(struct tt_orig_list_entry *orig_entry)
 static void tt_local_event(struct bat_priv *bat_priv, const uint8_t *addr,
 			   uint8_t flags)
 {
-	struct tt_change_node *tt_change_node;
+	struct tt_change_node *tt_change_node, *entry, *safe;
+	bool event_removed = false;
 
 	tt_change_node = kmalloc(sizeof(*tt_change_node), GFP_ATOMIC);
-
 	if (!tt_change_node)
 		return;
-
 	tt_change_node->change.flags = flags;
 	memcpy(tt_change_node->change.addr, addr, ETH_ALEN);
 
+	/* 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,
+				 list) {
+		if (!compare_eth(entry->change.addr, addr))
+			continue;
+		if (!(!(flags & TT_CLIENT_DEL) && /* ADD op */
+		      entry->change.flags & TT_CLIENT_DEL) &&
+		    !(flags & TT_CLIENT_DEL &&
+		      !(entry->change.flags & TT_CLIENT_DEL))) /* ADD op */
+			continue;
+		/* DEL+ADD in the same orig interval have no effect and can be
+		 * removed to avoid silly behaviour on the receiver side. The
+		 * other way around (ADD+DEL) can happen in case of roaming of
+		 * a client still in the NEW state. Roaming of NEW clients is
+		 * now possible due to automatically recognition of "temporary"
+		 * clients */
+		list_del(&entry->list);
+		kfree(entry);
+		event_removed = true;
+		goto unlock;
+	}
+
 	/* track the change in the OGMinterval list */
 	list_add_tail(&tt_change_node->list, &bat_priv->tt_changes_list);
-	atomic_inc(&bat_priv->tt_local_changes);
+
+unlock:
 	spin_unlock_bh(&bat_priv->tt_changes_list_lock);
 
-	atomic_set(&bat_priv->tt_ogm_append_cnt, 0);
+	if (event_removed)
+		atomic_dec(&bat_priv->tt_local_changes);
+	else
+		atomic_inc(&bat_priv->tt_local_changes);
 }
 
 int tt_len(int changes_num)
-- 
1.7.9.4


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [B.A.T.M.A.N.] [PATCH 2/5] batman-adv: clear the PENDING flag in case of client re-addition
  2012-04-03 21:50 [B.A.T.M.A.N.] [PATCH 0/5] batman-adv: tt code fixes and temporary client detection Antonio Quartulli
  2012-04-03 21:50 ` [B.A.T.M.A.N.] [PATCH 1/5] batman-adv: clear ADD+DEL (and viceversa) events in the same orig-interval Antonio Quartulli
@ 2012-04-03 21:50 ` Antonio Quartulli
  2012-04-04 10:09   ` Antonio Quartulli
  2012-04-03 21:50 ` [B.A.T.M.A.N.] [PATCH 3/5] batman-adv: beautify tt_global_add() argument list Antonio Quartulli
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 7+ messages in thread
From: Antonio Quartulli @ 2012-04-03 21:50 UTC (permalink / raw)
  To: b.a.t.m.a.n

During an OGM interval (time between two successive OGM sendings) a client
could be deleted (e.g. due to roaming) and then be re-added immediately after.
After the deletion, the client is marked with the TT_CLIENT_PENDING flag.
Therefore, in case of re-addition, the latter flag has to be reset

Signed-off-by: Antonio Quartulli <ordex@autistici.org>
---
 translation-table.c |   19 +++++++++++++++----
 1 file changed, 15 insertions(+), 4 deletions(-)

diff --git a/translation-table.c b/translation-table.c
index 438b786..fa1ac3a 100644
--- a/translation-table.c
+++ b/translation-table.c
@@ -248,15 +248,26 @@ void tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
 		tt_local_entry->common.flags |= 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 (compare_eth(addr, soft_iface->dev_addr))
 		tt_local_entry->common.flags |= TT_CLIENT_NOPURGE;
 
-	/* The local entry has to be marked as NEW to avoid to send it in
-	 * a full table response going out before the next ttvn increment
-	 * (consistency check) */
-	tt_local_entry->common.flags |= TT_CLIENT_NEW;
+	/* if the client is marked as PENDING means that it has been marked for
+	 * deletion during THIS OGM interval and the event has not been
+	 * announced yet. Therefore we can simply unset the flag. The event from
+	 * the event queue will be automatically be removed from the queue.
+	 * Otherwise we can set the NEW flag */
+	 if (tt_local_entry->common.flags & TT_CLIENT_PENDING)
+		tt_local_entry->common.flags &= ~TT_CLIENT_PENDING;
+	else
+		/* The local entry has to be marked as NEW to avoid to send it
+		 * in a full table response going out before the next ttvn
+		 * increment (consistency check) */
+		tt_local_entry->common.flags |= TT_CLIENT_NEW;
+
 
 	hash_added = hash_add(bat_priv->tt_local_hash, compare_tt, choose_orig,
 			 &tt_local_entry->common,
-- 
1.7.9.4


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [B.A.T.M.A.N.] [PATCH 3/5] batman-adv: beautify tt_global_add() argument list
  2012-04-03 21:50 [B.A.T.M.A.N.] [PATCH 0/5] batman-adv: tt code fixes and temporary client detection Antonio Quartulli
  2012-04-03 21:50 ` [B.A.T.M.A.N.] [PATCH 1/5] batman-adv: clear ADD+DEL (and viceversa) events in the same orig-interval Antonio Quartulli
  2012-04-03 21:50 ` [B.A.T.M.A.N.] [PATCH 2/5] batman-adv: clear the PENDING flag in case of client re-addition Antonio Quartulli
@ 2012-04-03 21:50 ` Antonio Quartulli
  2012-04-03 21:50 ` [B.A.T.M.A.N.] [PATCH 4/5] batman-adv: let tt_global_entry_has_orig() return the orig_entry or NULL instead of 1 or 0 only Antonio Quartulli
  2012-04-03 21:50 ` [B.A.T.M.A.N.] [PATCH 5/5] batman-adv: enable nodes to detect not yet announced clients Antonio Quartulli
  4 siblings, 0 replies; 7+ messages in thread
From: Antonio Quartulli @ 2012-04-03 21:50 UTC (permalink / raw)
  To: b.a.t.m.a.n

Instead of adding a new bool argument each time it is needed, it is better (and
simpler) to pass an 8bit flag argument which contains all the needed flags

Signed-off-by: Antonio Quartulli <ordex@autistici.org>
---
 routing.c           |    2 +-
 translation-table.c |   32 +++++++++++++++++---------------
 translation-table.h |    3 +--
 3 files changed, 19 insertions(+), 18 deletions(-)

diff --git a/routing.c b/routing.c
index 795d3af..2435237 100644
--- a/routing.c
+++ b/routing.c
@@ -683,7 +683,7 @@ int recv_roam_adv(struct sk_buff *skb, struct hard_iface *recv_if)
 		roam_adv_packet->src, roam_adv_packet->client);
 
 	tt_global_add(bat_priv, orig_node, roam_adv_packet->client,
-		      atomic_read(&orig_node->last_ttvn) + 1, true, false);
+		      TT_CLIENT_ROAM, atomic_read(&orig_node->last_ttvn) + 1);
 
 	/* Roaming phase starts: I have new information but the ttvn has not
 	 * been incremented yet. This flag will make me check all the incoming
diff --git a/translation-table.c b/translation-table.c
index fa1ac3a..4898e99 100644
--- a/translation-table.c
+++ b/translation-table.c
@@ -248,7 +248,6 @@ void tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
 		tt_local_entry->common.flags |= 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 */
@@ -597,24 +596,22 @@ static void tt_global_add_orig_entry(struct tt_global_entry *tt_global_entry,
 
 /* caller must hold orig_node refcount */
 int tt_global_add(struct bat_priv *bat_priv, struct orig_node *orig_node,
-		  const unsigned char *tt_addr, uint8_t ttvn, bool roaming,
-		  bool wifi)
+		  const unsigned char *tt_addr, uint8_t flags, uint8_t ttvn)
 {
 	struct tt_global_entry *tt_global_entry = NULL;
+	struct tt_orig_list_entry *orig_entry;
 	int ret = 0;
 	int hash_added;
 
 	tt_global_entry = tt_global_hash_find(bat_priv, tt_addr);
 
 	if (!tt_global_entry) {
-		tt_global_entry = kzalloc(sizeof(*tt_global_entry),
-					  GFP_ATOMIC);
+		tt_global_entry = kzalloc(sizeof(*tt_global_entry), GFP_ATOMIC);
 		if (!tt_global_entry)
 			goto out;
 
 		memcpy(tt_global_entry->common.addr, tt_addr, ETH_ALEN);
-
-		tt_global_entry->common.flags = NO_FLAGS;
+		tt_global_entry->common.flags = flags;
 		tt_global_entry->roam_at = 0;
 		atomic_set(&tt_global_entry->common.refcount, 2);
 
@@ -648,14 +645,19 @@ int tt_global_add(struct bat_priv *bat_priv, struct orig_node *orig_node,
 			tt_global_entry->roam_at = 0;
 		}
 
-		if (!tt_global_entry_has_orig(tt_global_entry, orig_node))
+		orig_entry = tt_global_entry_has_orig(tt_global_entry,
+						      orig_node);
+		if (!orig_entry)
 			tt_global_add_orig_entry(tt_global_entry, orig_node,
 						 ttvn);
+		else
+			/* if we are "adding" global entry, we may want to
+			 * update the ttvn anyway. Perhaps the global entry is
+			 * here with a wrong ttvn because it was temporary added
+			 * before */
+			orig_entry->ttvn = ttvn;
 	}
 
-	if (wifi)
-		tt_global_entry->common.flags |= TT_CLIENT_WIFI;
-
 	bat_dbg(DBG_TT, bat_priv,
 		"Creating new global tt entry: %pM (via %pM)\n",
 		tt_global_entry->common.addr, orig_node->orig);
@@ -663,7 +665,7 @@ int tt_global_add(struct bat_priv *bat_priv, struct orig_node *orig_node,
 out_remove:
 	/* remove address from local hash if present */
 	tt_local_remove(bat_priv, tt_global_entry->common.addr,
-			"global tt received", roaming);
+			"global tt received", flags & TT_CLIENT_ROAM);
 	ret = 1;
 out:
 	if (tt_global_entry)
@@ -1267,7 +1269,7 @@ static int tt_global_valid_entry(const void *entry_ptr, const void *data_ptr)
 	tt_global_entry = container_of(tt_common_entry, struct tt_global_entry,
 				       common);
 
-	return tt_global_entry_has_orig(tt_global_entry, orig_node);
+	return (tt_global_entry_has_orig(tt_global_entry, orig_node) != NULL);
 }
 
 static struct sk_buff *tt_response_fill_table(uint16_t tt_len, uint8_t ttvn,
@@ -1674,9 +1676,9 @@ static void _tt_update_changes(struct bat_priv *bat_priv,
 				      (tt_change + i)->flags & TT_CLIENT_ROAM);
 		else
 			if (!tt_global_add(bat_priv, orig_node,
-					   (tt_change + i)->addr, ttvn, false,
+					   (tt_change + i)->addr,
 					   (tt_change + i)->flags &
-							TT_CLIENT_WIFI))
+							TT_CLIENT_WIFI, ttvn))
 				/* In case of problem while storing a
 				 * global_entry, we stop the updating
 				 * procedure without committing the
diff --git a/translation-table.h b/translation-table.h
index c43374d..3239b72 100644
--- a/translation-table.h
+++ b/translation-table.h
@@ -34,8 +34,7 @@ int tt_local_seq_print_text(struct seq_file *seq, void *offset);
 void tt_global_add_orig(struct bat_priv *bat_priv, struct orig_node *orig_node,
 			const unsigned char *tt_buff, int tt_buff_len);
 int tt_global_add(struct bat_priv *bat_priv, struct orig_node *orig_node,
-		  const unsigned char *addr, uint8_t ttvn, bool roaming,
-		  bool wifi);
+		  const unsigned char *addr, uint8_t flags, uint8_t ttvn);
 int tt_global_seq_print_text(struct seq_file *seq, void *offset);
 void tt_global_del_orig(struct bat_priv *bat_priv,
 			struct orig_node *orig_node, const char *message);
-- 
1.7.9.4


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [B.A.T.M.A.N.] [PATCH 4/5] batman-adv: let tt_global_entry_has_orig() return the orig_entry or NULL instead of 1 or 0 only
  2012-04-03 21:50 [B.A.T.M.A.N.] [PATCH 0/5] batman-adv: tt code fixes and temporary client detection Antonio Quartulli
                   ` (2 preceding siblings ...)
  2012-04-03 21:50 ` [B.A.T.M.A.N.] [PATCH 3/5] batman-adv: beautify tt_global_add() argument list Antonio Quartulli
@ 2012-04-03 21:50 ` Antonio Quartulli
  2012-04-03 21:50 ` [B.A.T.M.A.N.] [PATCH 5/5] batman-adv: enable nodes to detect not yet announced clients Antonio Quartulli
  4 siblings, 0 replies; 7+ messages in thread
From: Antonio Quartulli @ 2012-04-03 21:50 UTC (permalink / raw)
  To: b.a.t.m.a.n

Instead of returning only 1 or 0 this function has to return the found
orig_entry (if any). In this way, operations that have to to modify the
found orig_entry structure will not need to reiterate over the list again to
find the wanted node.

Signed-off-by: Antonio Quartulli <ordex@autistici.org>
---
 translation-table.c |   13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/translation-table.c b/translation-table.c
index 4898e99..82711b8 100644
--- a/translation-table.c
+++ b/translation-table.c
@@ -551,25 +551,26 @@ static void tt_changes_list_free(struct bat_priv *bat_priv)
 }
 
 /* find out if an orig_node is already in the list of a tt_global_entry.
- * returns 1 if found, 0 otherwise */
-static bool tt_global_entry_has_orig(const struct tt_global_entry *entry,
-				     const struct orig_node *orig_node)
+ * returns NULL if not found, the pointer to the orig_entry otherwise */
+static struct tt_orig_list_entry *tt_global_entry_has_orig(
+					const struct tt_global_entry *entry,
+					const struct orig_node *orig_node)
 {
 	struct tt_orig_list_entry *tmp_orig_entry;
 	const struct hlist_head *head;
 	struct hlist_node *node;
-	bool found = false;
+	struct tt_orig_list_entry *orig_entry = NULL;
 
 	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;
+			orig_entry = tmp_orig_entry;
 			break;
 		}
 	}
 	rcu_read_unlock();
-	return found;
+	return orig_entry;
 }
 
 static void tt_global_add_orig_entry(struct tt_global_entry *tt_global_entry,
-- 
1.7.9.4


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [B.A.T.M.A.N.] [PATCH 5/5] batman-adv: enable nodes to detect not yet announced clients
  2012-04-03 21:50 [B.A.T.M.A.N.] [PATCH 0/5] batman-adv: tt code fixes and temporary client detection Antonio Quartulli
                   ` (3 preceding siblings ...)
  2012-04-03 21:50 ` [B.A.T.M.A.N.] [PATCH 4/5] batman-adv: let tt_global_entry_has_orig() return the orig_entry or NULL instead of 1 or 0 only Antonio Quartulli
@ 2012-04-03 21:50 ` Antonio Quartulli
  4 siblings, 0 replies; 7+ messages in thread
From: Antonio Quartulli @ 2012-04-03 21:50 UTC (permalink / raw)
  To: b.a.t.m.a.n

A client that connects to the mesh network is not visible to any node until it
has been announced by its serving node in the next TT diff sent out by means of
the next OGM.

During this period the client is not able to communicate to anyone because no
node has a route towards it yet. This is usually acceptable in networks with
short OGM interval (=the maximum waiting time before the next announcement), but
it is definitely problematic in networks where the OGM interval has been set to
an higher value (e.g. 5 seconds). The client, that probably issued an ARP or
DHCP request upon connection will suffer from several timeouts before being able
to communicate with the rest of the network.

This patch enable nodes to detect such "new born" clients and to add a temporary
route towards them in order to be able to communicate. If the client is not
claimed by any node within a certain amount of time, it will then be deleted.

Roaming operations have been adapted accordingly in order to be let clients
switch serving node even during the first OGM interval (when they have not been
announced yet)

Signed-off-by: Antonio Quartulli <ordex@autistici.org>
---
 main.h              |    2 +
 packet.h            |   15 +++----
 routing.c           |   26 +++++++++---
 soft-interface.c    |    6 ++-
 soft-interface.h    |    2 +-
 translation-table.c |  111 +++++++++++++++++++++++++++++++++++++++++----------
 translation-table.h |    4 +-
 types.h             |    1 +
 8 files changed, 130 insertions(+), 37 deletions(-)

diff --git a/main.h b/main.h
index c8bfe28..7340542 100644
--- a/main.h
+++ b/main.h
@@ -44,6 +44,8 @@
 #define PURGE_TIMEOUT 200000 /* 200 seconds */
 #define TT_LOCAL_TIMEOUT 3600000 /* in miliseconds */
 #define TT_CLIENT_ROAM_TIMEOUT 600000 /* in miliseconds */
+#define TT_CLIENT_TEMP_TIMEOUT_FACT 10 /* multiply factor for the current orig
+					* interval */
 /* sliding packet range of received originator messages in sequence numbers
  * (should be a multiple of our word size) */
 #define TQ_LOCAL_WINDOW_SIZE 64
diff --git a/packet.h b/packet.h
index 3c4c533..496d633 100644
--- a/packet.h
+++ b/packet.h
@@ -91,12 +91,13 @@ enum tt_query_flags {
  * Flags from 1 to 1 << 7 are sent on the wire, while flags from 1 << 8 to
  * 1 << 15 are used for local computation only */
 enum tt_client_flags {
-	TT_CLIENT_DEL     = 1 << 0,
-	TT_CLIENT_ROAM    = 1 << 1,
-	TT_CLIENT_WIFI    = 1 << 2,
-	TT_CLIENT_NOPURGE = 1 << 8,
-	TT_CLIENT_NEW     = 1 << 9,
-	TT_CLIENT_PENDING = 1 << 10
+	TT_CLIENT_DEL		= 1 << 0,
+	TT_CLIENT_ROAM		= 1 << 1,
+	TT_CLIENT_WIFI		= 1 << 2,
+	TT_CLIENT_TEMP		= 1 << 3,
+	TT_CLIENT_NOPURGE	= 1 << 8,
+	TT_CLIENT_NEW		= 1 << 9,
+	TT_CLIENT_PENDING	= 1 << 10,
 };
 
 /* claim frame types for the bridge loop avoidance */
@@ -224,7 +225,7 @@ struct tt_query_packet {
 
 struct roam_adv_packet {
 	struct batman_header header;
-	uint8_t  reserved;
+	uint8_t  flags;
 	uint8_t  dst[ETH_ALEN];
 	uint8_t  src[ETH_ALEN];
 	uint8_t  client[ETH_ALEN];
diff --git a/routing.c b/routing.c
index 2435237..44bd471 100644
--- a/routing.c
+++ b/routing.c
@@ -679,11 +679,13 @@ int recv_roam_adv(struct sk_buff *skb, struct hard_iface *recv_if)
 		goto out;
 
 	bat_dbg(DBG_TT, bat_priv,
-		"Received ROAMING_ADV from %pM (client %pM)\n",
-		roam_adv_packet->src, roam_adv_packet->client);
+		"Received ROAMING_ADV from %pM (client: %pM flags: 0x%.2x)\n",
+		roam_adv_packet->src, roam_adv_packet->client,
+		roam_adv_packet->flags);
 
 	tt_global_add(bat_priv, orig_node, roam_adv_packet->client,
-		      TT_CLIENT_ROAM, atomic_read(&orig_node->last_ttvn) + 1);
+		      roam_adv_packet->flags | TT_CLIENT_ROAM,
+		      atomic_read(&orig_node->last_ttvn) + 1);
 
 	/* Roaming phase starts: I have new information but the ttvn has not
 	 * been incremented yet. This flag will make me check all the incoming
@@ -959,6 +961,7 @@ int recv_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if)
 	struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface);
 	struct unicast_packet *unicast_packet;
 	int hdr_size = sizeof(*unicast_packet);
+	struct orig_node *orig_node = NULL;
 
 	unicast_packet = (struct unicast_packet *)skb->data;
 
@@ -974,7 +977,18 @@ int recv_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if)
 
 	/* packet for me */
 	if (is_my_mac(unicast_packet->dest)) {
-		interface_rx(recv_if->soft_iface, skb, recv_if, hdr_size);
+		/* now we can look at the source field and retrieve the orig
+		 * node */
+		if (unicast_packet->header.packet_type == BAT_UNICAST_4ADDR)
+			orig_node = orig_hash_find(bat_priv,
+			       ((struct unicast_4addr_packet *)skb->data)->src);
+
+		interface_rx(recv_if->soft_iface, skb, recv_if, hdr_size,
+			     orig_node);
+
+		if (orig_node)
+			orig_node_free_ref(orig_node);
+
 		return NET_RX_SUCCESS;
 	}
 
@@ -1010,7 +1024,7 @@ int recv_ucast_frag_packet(struct sk_buff *skb, struct hard_iface *recv_if)
 			return NET_RX_SUCCESS;
 
 		interface_rx(recv_if->soft_iface, new_skb, recv_if,
-			     sizeof(struct unicast_packet));
+			     sizeof(struct unicast_packet), NULL);
 		return NET_RX_SUCCESS;
 	}
 
@@ -1094,7 +1108,7 @@ int recv_bcast_packet(struct sk_buff *skb, struct hard_iface *recv_if)
 		goto out;
 
 	/* broadcast for me */
-	interface_rx(recv_if->soft_iface, skb, recv_if, hdr_size);
+	interface_rx(recv_if->soft_iface, skb, recv_if, hdr_size, orig_node);
 	ret = NET_RX_SUCCESS;
 	goto out;
 
diff --git a/soft-interface.c b/soft-interface.c
index 92137af..9e2781d 100644
--- a/soft-interface.c
+++ b/soft-interface.c
@@ -256,7 +256,7 @@ end:
 
 void interface_rx(struct net_device *soft_iface,
 		  struct sk_buff *skb, struct hard_iface *recv_if,
-		  int hdr_size)
+		  int hdr_size, struct orig_node *orig_node)
 {
 	struct bat_priv *bat_priv = netdev_priv(soft_iface);
 	struct ethhdr *ethhdr;
@@ -307,6 +307,10 @@ void interface_rx(struct net_device *soft_iface,
 
 	soft_iface->last_rx = jiffies;
 
+	if (orig_node)
+		tt_add_temporary_global_entry(bat_priv, orig_node,
+					      ethhdr->h_source);
+
 	if (is_ap_isolated(bat_priv, ethhdr->h_source, ethhdr->h_dest))
 		goto dropped;
 
diff --git a/soft-interface.h b/soft-interface.h
index 0203006..b91d8ff 100644
--- a/soft-interface.h
+++ b/soft-interface.h
@@ -25,7 +25,7 @@
 int my_skb_head_push(struct sk_buff *skb, unsigned int len);
 void interface_rx(struct net_device *soft_iface,
 		  struct sk_buff *skb, struct hard_iface *recv_if,
-		  int hdr_size);
+		  int hdr_size, struct orig_node *orig_node);
 struct net_device *softif_create(const char *name);
 void softif_destroy(struct net_device *soft_iface);
 int softif_is_valid(const struct net_device *net_dev);
diff --git a/translation-table.c b/translation-table.c
index 82711b8..d6ea617 100644
--- a/translation-table.c
+++ b/translation-table.c
@@ -31,10 +31,21 @@
 
 #include <linux/crc16.h>
 
-static void send_roam_adv(struct bat_priv *bat_priv, uint8_t *client,
+/* the temporary client timeout is defined as a multiple of the originator
+ * interval */
+#define TT_CLIENT_TEMP_TIMEOUT (TT_CLIENT_TEMP_TIMEOUT_FACT * \
+				atomic_read(&bat_priv->orig_interval))
+
+
+static void send_roam_adv(struct bat_priv *bat_priv,
+			  struct tt_global_entry *tt_global_entry,
 			  struct orig_node *orig_node);
 static void tt_purge(struct work_struct *work);
 static void tt_global_del_orig_list(struct tt_global_entry *tt_global_entry);
+static void tt_global_del(struct bat_priv *bat_priv,
+			  struct orig_node *orig_node,
+			  const unsigned char *addr,
+			  const char *message, bool roaming);
 
 /* returns 1 if they are the same mac addr */
 static int compare_tt(const struct hlist_node *node, const void *data2)
@@ -248,6 +259,7 @@ void tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
 		tt_local_entry->common.flags |= 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 */
@@ -291,15 +303,25 @@ void tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
 		hlist_for_each_entry_rcu(orig_entry, node, head, list) {
 			orig_entry->orig_node->tt_poss_change = true;
 
-			send_roam_adv(bat_priv, tt_global_entry->common.addr,
+			send_roam_adv(bat_priv, tt_global_entry,
 				      orig_entry->orig_node);
 		}
 		rcu_read_unlock();
-		/* The global entry has to be marked as ROAMING and
-		 * has to be kept for consistency purpose */
 
-		tt_global_entry->common.flags |= TT_CLIENT_ROAM;
-		tt_global_entry->roam_at = jiffies;
+		/* if the global client is marked as TEMP or ROAM we can
+		 * directly delete it because it has never been announced yet
+		 * and we don't need to keep it for consistency purposes */
+		if ((tt_global_entry->common.flags & TT_CLIENT_TEMP) ||
+		    (tt_global_entry->common.flags & TT_CLIENT_ROAM))
+			tt_global_del(bat_priv, NULL, addr,
+				      "Not yet announced global client roamed to us",
+				      true);
+		else {
+			/* The global entry has to be marked as ROAMING and
+			 * has to be kept for consistency purpose */
+			tt_global_entry->common.flags |= TT_CLIENT_ROAM;
+			tt_global_entry->roam_at = jiffies;
+		}
 	}
 out:
 	if (tt_local_entry)
@@ -615,6 +637,8 @@ int tt_global_add(struct bat_priv *bat_priv, struct orig_node *orig_node,
 		tt_global_entry->common.flags = flags;
 		tt_global_entry->roam_at = 0;
 		atomic_set(&tt_global_entry->common.refcount, 2);
+		tt_global_entry->common.added_at = jiffies;
+
 
 		INIT_HLIST_HEAD(&tt_global_entry->orig_list);
 		spin_lock_init(&tt_global_entry->list_lock);
@@ -632,6 +656,14 @@ int tt_global_add(struct bat_priv *bat_priv, struct orig_node *orig_node,
 		tt_global_add_orig_entry(tt_global_entry, orig_node, ttvn);
 	} else {
 		/* there is already a global entry, use this one. */
+		/* if we are trying to add a temporary node, but we found an
+		 * already existent entry, we can exit directly */
+		if (flags & 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 &= ~TT_CLIENT_TEMP;
 
 		/* If there is the TT_CLIENT_ROAM flag set, there is only one
 		 * originator left in the list and we previously received a
@@ -694,11 +726,12 @@ static void tt_global_print_entry(struct 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 & TT_CLIENT_ROAM ? 'R' : '.'),
-			   (flags & TT_CLIENT_WIFI ? 'W' : '.'));
+			   (flags & TT_CLIENT_WIFI ? 'W' : '.'),
+			   (flags & TT_CLIENT_TEMP ? 'T' : '.'));
 	}
 }
 
@@ -949,7 +982,7 @@ void tt_global_del_orig(struct bat_priv *bat_priv,
 	orig_node->tt_initialised = false;
 }
 
-static void tt_global_roam_purge(struct bat_priv *bat_priv)
+static void tt_global_purge(struct bat_priv *bat_priv)
 {
 	struct hashtable_t *hash = bat_priv->tt_global_hash;
 	struct tt_common_entry *tt_common_entry;
@@ -958,6 +991,8 @@ static void tt_global_roam_purge(struct bat_priv *bat_priv)
 	struct hlist_head *head;
 	spinlock_t *list_lock; /* protects write access to the hash lists */
 	uint32_t i;
+	bool purge;
+	char *msg = NULL;
 
 	for (i = 0; i < hash->size; i++) {
 		head = &hash->table[i];
@@ -966,18 +1001,29 @@ static void tt_global_roam_purge(struct bat_priv *bat_priv)
 		spin_lock_bh(list_lock);
 		hlist_for_each_entry_safe(tt_common_entry, node, node_tmp,
 					  head, hash_entry) {
+			purge = false;
 			tt_global_entry = container_of(tt_common_entry,
 						       struct tt_global_entry,
 						       common);
-			if (!(tt_global_entry->common.flags & TT_CLIENT_ROAM))
-				continue;
-			if (!has_timed_out(tt_global_entry->roam_at,
-					   TT_CLIENT_ROAM_TIMEOUT))
+			if ((tt_global_entry->common.flags & TT_CLIENT_ROAM) &&
+			    has_timed_out(tt_global_entry->roam_at,
+					  TT_CLIENT_ROAM_TIMEOUT)) {
+				purge = true;
+				msg = "Roaming timeout\n";
+			}
+
+			if ((tt_global_entry->common.flags & TT_CLIENT_TEMP) &&
+			    has_timed_out(tt_global_entry->common.added_at,
+					  TT_CLIENT_TEMP_TIMEOUT)) {
+				purge = true;
+				msg = "Temporary client timeout\n";
+			}
+
+			if (!purge)
 				continue;
 
-			bat_dbg(DBG_TT, bat_priv,
-				"Deleting global tt entry (%pM): Roaming timeout\n",
-				tt_global_entry->common.addr);
+			bat_dbg(DBG_TT, bat_priv, "Deleting global tt entry (%pM): %s\n",
+				tt_global_entry->common.addr, msg);
 
 			hlist_del_rcu(node);
 			tt_global_entry_free_ref(tt_global_entry);
@@ -1886,7 +1932,8 @@ unlock:
 	return ret;
 }
 
-static void send_roam_adv(struct bat_priv *bat_priv, uint8_t *client,
+static void send_roam_adv(struct bat_priv *bat_priv,
+			  struct tt_global_entry *tt_global_entry,
 			  struct orig_node *orig_node)
 {
 	struct neigh_node *neigh_node = NULL;
@@ -1897,7 +1944,7 @@ static void send_roam_adv(struct bat_priv *bat_priv, uint8_t *client,
 
 	/* before going on we have to check whether the client has
 	 * already roamed to us too many times */
-	if (!tt_check_roam_count(bat_priv, client))
+	if (!tt_check_roam_count(bat_priv, tt_global_entry->common.addr))
 		goto out;
 
 	skb = dev_alloc_skb(sizeof(struct roam_adv_packet) + ETH_HLEN);
@@ -1918,7 +1965,10 @@ static void send_roam_adv(struct bat_priv *bat_priv, uint8_t *client,
 	memcpy(roam_adv_packet->src, primary_if->net_dev->dev_addr, ETH_ALEN);
 	hardif_free_ref(primary_if);
 	memcpy(roam_adv_packet->dst, orig_node->orig, ETH_ALEN);
-	memcpy(roam_adv_packet->client, client, ETH_ALEN);
+	memcpy(roam_adv_packet->client, tt_global_entry->common.addr, ETH_ALEN);
+	roam_adv_packet->flags = NO_FLAGS;
+	if (tt_global_entry->common.flags & TT_CLIENT_TEMP)
+		roam_adv_packet->flags |= TT_CLIENT_TEMP;
 
 	neigh_node = orig_node_get_router(orig_node);
 	if (!neigh_node)
@@ -1926,7 +1976,8 @@ static void send_roam_adv(struct bat_priv *bat_priv, uint8_t *client,
 
 	bat_dbg(DBG_TT, bat_priv,
 		"Sending ROAMING_ADV to %pM (client %pM) via %pM\n",
-		orig_node->orig, client, neigh_node->addr);
+		orig_node->orig, tt_global_entry->common.addr,
+		neigh_node->addr);
 
 	send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
 	ret = 0;
@@ -1947,7 +1998,7 @@ static void tt_purge(struct work_struct *work)
 		container_of(delayed_work, struct bat_priv, tt_work);
 
 	tt_local_purge(bat_priv);
-	tt_global_roam_purge(bat_priv);
+	tt_global_purge(bat_priv);
 	tt_req_purge(bat_priv);
 	tt_roam_purge(bat_priv);
 
@@ -2170,3 +2221,21 @@ bool tt_global_client_is_roaming(struct bat_priv *bat_priv, uint8_t *addr)
 out:
 	return ret;
 }
+
+bool tt_add_temporary_global_entry(struct bat_priv *bat_priv,
+				   struct orig_node *orig_node,
+				   const unsigned char *addr)
+{
+	bool ret = false;
+
+	if (!tt_global_add(bat_priv, orig_node, addr, TT_CLIENT_TEMP,
+			   atomic_read(&orig_node->last_ttvn)))
+		goto out;
+
+	bat_dbg(DBG_TT, bat_priv,
+		"Added temporary global client (addr: %pM orig: %pM)\n",
+		addr, orig_node->orig);
+	ret = true;
+out:
+	return ret;
+}
diff --git a/translation-table.h b/translation-table.h
index 3239b72..9475c44 100644
--- a/translation-table.h
+++ b/translation-table.h
@@ -53,6 +53,8 @@ void tt_update_orig(struct bat_priv *bat_priv, struct orig_node *orig_node,
 		    const unsigned char *tt_buff, uint8_t tt_num_changes,
 		    uint8_t ttvn, uint16_t tt_crc);
 bool tt_global_client_is_roaming(struct bat_priv *bat_priv, uint8_t *addr);
-
+bool tt_add_temporary_global_entry(struct bat_priv *bat_priv,
+				   struct orig_node *orig_node,
+				   const unsigned char *addr);
 
 #endif /* _NET_BATMAN_ADV_TRANSLATION_TABLE_H_ */
diff --git a/types.h b/types.h
index 15f538a..08c51c4 100644
--- a/types.h
+++ b/types.h
@@ -261,6 +261,7 @@ struct tt_common_entry {
 	uint8_t addr[ETH_ALEN];
 	struct hlist_node hash_entry;
 	uint16_t flags;
+	unsigned long added_at;
 	atomic_t refcount;
 	struct rcu_head rcu;
 };
-- 
1.7.9.4


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [B.A.T.M.A.N.] [PATCH 2/5] batman-adv: clear the PENDING flag in case of client re-addition
  2012-04-03 21:50 ` [B.A.T.M.A.N.] [PATCH 2/5] batman-adv: clear the PENDING flag in case of client re-addition Antonio Quartulli
@ 2012-04-04 10:09   ` Antonio Quartulli
  0 siblings, 0 replies; 7+ messages in thread
From: Antonio Quartulli @ 2012-04-04 10:09 UTC (permalink / raw)
  To: b.a.t.m.a.n

[-- Attachment #1: Type: text/plain, Size: 1245 bytes --]

On Tue, Apr 03, 2012 at 11:50:19 +0200, Antonio Quartulli wrote:
> During an OGM interval (time between two successive OGM sendings) a client
> could be deleted (e.g. due to roaming) and then be re-added immediately after.
> After the deletion, the client is marked with the TT_CLIENT_PENDING flag.
> Therefore, in case of re-addition, the latter flag has to be reset
> 
> Signed-off-by: Antonio Quartulli <ordex@autistici.org>
> ---
> +	/* if the client is marked as PENDING means that it has been marked for
> +	 * deletion during THIS OGM interval and the event has not been
> +	 * announced yet. Therefore we can simply unset the flag. The event from
> +	 * the event queue will be automatically be removed from the queue.
> +	 * Otherwise we can set the NEW flag */
> +	 if (tt_local_entry->common.flags & TT_CLIENT_PENDING)
> +		tt_local_entry->common.flags &= ~TT_CLIENT_PENDING;
> 

mh..When I wrote this patch "batman-adv: unset the TT_CLIENT_PENDING flag if
the new local entry already exists" was not applied yet, therefore this patch
must be reviewed.

Please wait before considering committing this patchset.

Cheers,

-- 
Antonio Quartulli

..each of us alone is worth nothing..
Ernesto "Che" Guevara

[-- Attachment #2: Type: application/pgp-signature, Size: 490 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2012-04-04 10:09 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-04-03 21:50 [B.A.T.M.A.N.] [PATCH 0/5] batman-adv: tt code fixes and temporary client detection Antonio Quartulli
2012-04-03 21:50 ` [B.A.T.M.A.N.] [PATCH 1/5] batman-adv: clear ADD+DEL (and viceversa) events in the same orig-interval Antonio Quartulli
2012-04-03 21:50 ` [B.A.T.M.A.N.] [PATCH 2/5] batman-adv: clear the PENDING flag in case of client re-addition Antonio Quartulli
2012-04-04 10:09   ` Antonio Quartulli
2012-04-03 21:50 ` [B.A.T.M.A.N.] [PATCH 3/5] batman-adv: beautify tt_global_add() argument list Antonio Quartulli
2012-04-03 21:50 ` [B.A.T.M.A.N.] [PATCH 4/5] batman-adv: let tt_global_entry_has_orig() return the orig_entry or NULL instead of 1 or 0 only Antonio Quartulli
2012-04-03 21:50 ` [B.A.T.M.A.N.] [PATCH 5/5] batman-adv: enable nodes to detect not yet announced clients Antonio Quartulli

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.