Hello again nice folks,
I updated today another segment of the network with just 4 nodes, to
batman-adv 2012.2 (the one i compiled yesterday with simon patches for
blaII, marek stability fixes, and debug log enabled , yikes!)
and i couldn't get batman to work over wired ethernet?? (?)
P -(50mts wlan)- D -----(ubnt transparent bridge) 2km -- C
\----eth-------------------/
Node P and D connected by ethernet on eth0 but close enough that could
also see each other through adhoc wlan, with bla …
[View More]enabled, correctly
preferred ethernet connection to communicate between them (iperf
yielded 92mbps), so far so good.
now, node D and C, too far away from each other to communicate over
wlan, but connected by a "loooong eth cable" (mediated by a wds
transparent bridge) wouldn't find each other batman originator.
C originator table was empty, and D only showed P.
I thought the transparent bridge was misbehaving, so I tried in a
simpler setup using P and D, with the wifi off:
but after disabling wlan0 (batctl if del wlan0-2) and adding eth0
(batctl if add eth0) on both nodes, batman could not see each other
anymore :(
i thought i was doing something wrong, so i tried in different ways,
but could not get it to work.
batctl td eth0 shows both outgoing OGMs from local , and incoming OGMs
from remote,
but batctl l only reported outgoing OGMs.
http://pastebin.com/7DDUaXu1
diego is local node ("D"), palmeras is on the other side of the
ethernet cable ("P") (and jure is further away, connected to palmeras
by adhoc wlan, not illustrated in the previous ascii art)
i hope i'm overlooking something really obvious?
Have a nice weekend!
Gui
[View Less]
The roaming re-routing procedure has been slightly revised in order to get rid
of the tt_poss_change variable that was not clearly representing the node/client
states. Now the code directly relies on the TT_CLIENT_ROAM flag that can be
set on the involved local/global clients.
This improvement also allow clients to roam multiple times in the same
originator-interval, because nodes now let packets go to the node that was
originally serving the roamed client which will then reroute the data to …
[View More]the
correct destination at any point in time.
Signed-off-by: Antonio Quartulli <ordex(a)autistici.org>
---
- This patch is based on top of:
"batman-adv: substitute tt_poss_change with a per-tt_entry flag"
translation-table.c | 216 ++++++++++++++++++++++++++++++++++++----------------
1 file changed, 152 insertions(+), 64 deletions(-)
diff --git a/translation-table.c b/translation-table.c
index 21830f5..e5afcee 100644
--- a/translation-table.c
+++ b/translation-table.c
@@ -238,90 +238,138 @@ static int batadv_tt_local_init(struct batadv_priv *bat_priv)
return 0;
}
+static void
+batadv_tt_global_del_struct(struct batadv_priv *bat_priv,
+ struct batadv_tt_global_entry *tt_global_entry,
+ const char *message)
+{
+ batadv_dbg(BATADV_DBG_TT, 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_choose_orig, tt_global_entry->common.addr);
+ batadv_tt_global_entry_free_ref(tt_global_entry);
+
+}
+
void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
int ifindex)
{
struct batadv_priv *bat_priv = netdev_priv(soft_iface);
- struct batadv_tt_local_entry *tt_local_entry = NULL;
- struct batadv_tt_global_entry *tt_global_entry = NULL;
+ struct batadv_tt_local_entry *tt_local = NULL;
+ struct batadv_tt_global_entry *tt_global = NULL;
struct hlist_head *head;
struct hlist_node *node;
struct batadv_tt_orig_list_entry *orig_entry;
int hash_added;
+ bool back_roam = false;
- tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr);
+ tt_local = batadv_tt_local_hash_find(bat_priv, addr);
+ /* look for the global entry so that we can eventually operate on it */
+ tt_global = batadv_tt_global_hash_find(bat_priv, addr);
- if (tt_local_entry) {
- tt_local_entry->last_seen = jiffies;
- /* possibly unset the BATADV_TT_CLIENT_PENDING flag */
- tt_local_entry->common.flags &= ~BATADV_TT_CLIENT_PENDING;
- goto out;
+
+ if (tt_local) {
+ tt_local->last_seen = jiffies;
+ if (tt_local->common.flags & BATADV_TT_CLIENT_PENDING) {
+ /* if this client is marked as pending it means that it
+ * was purged out before.
+ */
+ batadv_dbg(BATADV_DBG_TT, bat_priv,
+ "Readding pending client %pM\n", addr);
+ tt_local->common.flags &= ~BATADV_TT_CLIENT_PENDING;
+ goto add_event;
+ }
+ /* if the entry is marked as NEW, it means that the node is not
+ * the original owner of this client (in this orig-interval),
+ * therefore it does need to eventually send a roaming
+ * advertisement
+ */
+ /*if (tt_local->common.flags & BATADV_TT_CLIENT_NEW)
+ goto out;*/
+
+ if (tt_local->common.flags & BATADV_TT_CLIENT_ROAM) {
+ batadv_dbg(BATADV_DBG_TT, bat_priv,
+ "Roaming client %pM came back to its original location\n",
+ addr);
+ tt_local->common.flags &= ~BATADV_TT_CLIENT_ROAM;
+ back_roam = true;
+ goto check_roaming;
+ }
+ goto check_roaming;
}
- tt_local_entry = kmalloc(sizeof(*tt_local_entry), GFP_ATOMIC);
- if (!tt_local_entry)
+ tt_local = kmalloc(sizeof(*tt_local), GFP_ATOMIC);
+ if (!tt_local)
goto out;
batadv_dbg(BATADV_DBG_TT, bat_priv,
"Creating new local tt entry: %pM (ttvn: %d)\n", addr,
(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;
+ memcpy(tt_local->common.addr, addr, ETH_ALEN);
+ tt_local->common.flags = BATADV_NO_FLAGS;
if (batadv_is_wifi_iface(ifindex))
- 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;
+ tt_local->common.flags |= BATADV_TT_CLIENT_WIFI;
+ atomic_set(&tt_local->common.refcount, 2);
+ tt_local->last_seen = jiffies;
+ tt_local->common.added_at = tt_local->last_seen;
/* the batman interface mac address should never be purged */
if (batadv_compare_eth(addr, soft_iface->dev_addr))
- tt_local_entry->common.flags |= BATADV_TT_CLIENT_NOPURGE;
+ tt_local->common.flags |= BATADV_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 |= BATADV_TT_CLIENT_NEW;
+ tt_local->common.flags |= BATADV_TT_CLIENT_NEW;
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);
+ &tt_local->common,
+ &tt_local->common.hash_entry);
if (unlikely(hash_added != 0)) {
/* remove the reference for the hash */
- batadv_tt_local_entry_free_ref(tt_local_entry);
+ batadv_tt_local_entry_free_ref(tt_local);
goto out;
}
- batadv_tt_local_event(bat_priv, addr, tt_local_entry->common.flags);
-
- /* remove address from global hash if present */
- tt_global_entry = batadv_tt_global_hash_find(bat_priv, addr);
+add_event:
+ batadv_tt_local_event(bat_priv, addr, tt_local->common.flags);
+check_roaming:
/* Check whether it is a roaming! */
- if (tt_global_entry) {
+ if (tt_global) {
/* These node are probably going to update their tt table */
- head = &tt_global_entry->orig_list;
+ head = &tt_global->orig_list;
rcu_read_lock();
hlist_for_each_entry_rcu(orig_entry, node, head, list) {
batadv_send_roam_adv(bat_priv,
- tt_global_entry->common.addr,
+ tt_global->common.addr,
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 |= BATADV_TT_CLIENT_ROAM;
- tt_global_entry->roam_at = jiffies;
+ if (back_roam) {
+ batadv_tt_global_del_struct(bat_priv, tt_global,
+ "Roaming canceled");
+ tt_global = NULL;
+ } else {
+ /* The global entry has to be marked as ROAMING and
+ * has to be kept for consistency purpose
+ */
+ tt_global->common.flags |= BATADV_TT_CLIENT_ROAM;
+ tt_global->roam_at = jiffies;
+ }
}
+
out:
- if (tt_local_entry)
- batadv_tt_local_entry_free_ref(tt_local_entry);
- if (tt_global_entry)
- batadv_tt_global_entry_free_ref(tt_global_entry);
+ if (tt_local)
+ batadv_tt_local_entry_free_ref(tt_local);
+ if (tt_global)
+ batadv_tt_global_entry_free_ref(tt_global);
}
static void batadv_tt_realloc_packet_buff(unsigned char **packet_buff,
@@ -510,13 +558,28 @@ uint16_t batadv_tt_local_remove(struct batadv_priv *bat_priv,
curr_flags = tt_local_entry->common.flags;
flags = BATADV_TT_CLIENT_DEL;
+ /* if this global entry addition is due to a roaming, the node has to
+ * mark the local entry as "roamed" in order to correctly reroute
+ * packets later
+ */
if (roaming) {
flags |= BATADV_TT_CLIENT_ROAM;
/* mark the local client as ROAMed */
tt_local_entry->common.flags |= BATADV_TT_CLIENT_ROAM;
}
- batadv_tt_local_set_pending(bat_priv, tt_local_entry, flags, message);
+ if (!(tt_local_entry->common.flags & BATADV_TT_CLIENT_NEW)) {
+ batadv_tt_local_set_pending(bat_priv, tt_local_entry, flags,
+ message);
+ goto out;
+ }
+ /* if this client has been added right now, it is possible to
+ * immediately purge it
+ */
+ batadv_tt_local_event(bat_priv, tt_local_entry->common.addr,
+ curr_flags | BATADV_TT_CLIENT_DEL);
+ hlist_del_rcu(&tt_local_entry->common.hash_entry);
+ batadv_tt_local_entry_free_ref(tt_local_entry);
out:
if (tt_local_entry)
@@ -726,12 +789,22 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv,
uint8_t ttvn)
{
struct batadv_tt_global_entry *tt_global_entry = NULL;
+ struct batadv_tt_local_entry *tt_local_entry = NULL;
int ret = 0;
int hash_added;
struct batadv_tt_common_entry *common;
uint16_t local_flags;
tt_global_entry = batadv_tt_global_hash_find(bat_priv, tt_addr);
+ tt_local_entry = batadv_tt_local_hash_find(bat_priv, tt_addr);
+
+ /* if the node already has a local client for this entry, it has to wait
+ * for a roaming advertisement instead of manually messing up the global
+ * table
+ */
+ if ((flags & BATADV_TT_CLIENT_TEMP) && tt_local_entry &&
+ !(tt_local_entry->common.flags & BATADV_TT_CLIENT_NEW))
+ goto out;
if (!tt_global_entry) {
tt_global_entry = kzalloc(sizeof(*tt_global_entry), GFP_ATOMIC);
@@ -766,19 +839,39 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv,
goto out_remove;
}
} else {
+ common = &tt_global_entry->common;
/* 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)
+ * But if we are trying to add a temporary client then here are
+ * two options at this point:
+ * 1) the global client is not a temporary client: the global
+ * client has to be left as it is, temporary information
+ * should never override any already known client state
+ * 2) the global client is a temporary client: purge the
+ * originator list and add the new one orig_entry
*/
- if (flags & BATADV_TT_CLIENT_TEMP)
- goto out;
+ if (flags & BATADV_TT_CLIENT_TEMP) {
+ if (!(common->flags & BATADV_TT_CLIENT_TEMP))
+ goto out;
+ if (batadv_tt_global_entry_has_orig(tt_global_entry,
+ orig_node))
+ goto out_remove;
+ batadv_tt_global_del_orig_list(tt_global_entry);
+ goto add_orig_entry;
+ }
/* 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;
+ common->flags &= ~BATADV_TT_CLIENT_TEMP;
+
+ /* if this is a normal add, possibly unset the ROAM flag. This
+ * flag could have been set before because the client was
+ * roaming, but now that the node got the ADD event, the flag
+ * can be unset
+ */
+ if (!(flags & BATADV_TT_CLIENT_ROAM))
+ common->flags &= ~BATADV_TT_CLIENT_ROAM;
/* If there is the BATADV_TT_CLIENT_ROAM flag set, there is only
* one originator left in the list and we previously received a
@@ -787,18 +880,19 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv,
* We should first delete the old originator before adding the
* new one.
*/
- if (tt_global_entry->common.flags & BATADV_TT_CLIENT_ROAM) {
+ if (common->flags & BATADV_TT_CLIENT_ROAM) {
batadv_tt_global_del_orig_list(tt_global_entry);
- tt_global_entry->common.flags &= ~BATADV_TT_CLIENT_ROAM;
+ common->flags &= ~BATADV_TT_CLIENT_ROAM;
tt_global_entry->roam_at = 0;
}
}
+add_orig_entry:
/* 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",
- tt_global_entry->common.addr, orig_node->orig);
+ common->addr, orig_node->orig);
ret = 1;
out_remove:
@@ -806,12 +900,20 @@ out_remove:
/* remove address from local hash if present */
local_flags = batadv_tt_local_remove(bat_priv, tt_addr,
"global tt received",
- flags & BATADV_TT_CLIENT_ROAM);
+ !!(flags & BATADV_TT_CLIENT_ROAM));
tt_global_entry->common.flags |= local_flags & BATADV_TT_CLIENT_WIFI;
+ if (!(flags & BATADV_TT_CLIENT_ROAM))
+ /* this is a normal global add. Therefore the client is not in a
+ * roaming state anymore.
+ */
+ tt_global_entry->common.flags &= ~BATADV_TT_CLIENT_ROAM;
+
out:
if (tt_global_entry)
batadv_tt_global_entry_free_ref(tt_global_entry);
+ if (tt_local_entry)
+ batadv_tt_local_entry_free_ref(tt_local_entry);
return ret;
}
@@ -929,21 +1031,6 @@ batadv_tt_global_del_orig_entry(struct batadv_priv *bat_priv,
spin_unlock_bh(&tt_global_entry->list_lock);
}
-static void
-batadv_tt_global_del_struct(struct batadv_priv *bat_priv,
- struct batadv_tt_global_entry *tt_global_entry,
- const char *message)
-{
- batadv_dbg(BATADV_DBG_TT, 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_choose_orig, tt_global_entry->common.addr);
- batadv_tt_global_entry_free_ref(tt_global_entry);
-
-}
-
/* If the client is to be deleted, we check if it is the last origantor entry
* within tt_global entry. If yes, we set the BATADV_TT_CLIENT_ROAM flag and the
* timer, otherwise we simply remove the originator scheduled for deletion.
@@ -1207,7 +1294,8 @@ struct batadv_orig_node *batadv_transtable_search(struct batadv_priv *bat_priv,
if (src && atomic_read(&bat_priv->ap_isolation)) {
tt_local_entry = batadv_tt_local_hash_find(bat_priv, src);
- if (!tt_local_entry)
+ if (!tt_local_entry ||
+ (tt_local_entry->common.flags & BATADV_TT_CLIENT_PENDING))
goto out;
}
--
1.7.12
[View Less]
in case of client roaming a new global entry is added while a corresponding
local one is still present. In this case the node can safely pass the WIFI flag
from the local to the global entry.
This change is required to let the AP-isolation correctly working in case of
roaming: if a generic WIFI client C roams from node A to B, A adds a global
entry for C without adding any WIFI flag. The latter will be set only later,
once A has received C's advertisement from B. In this time period the
AP-…
[View More]Isolation (if enabled) would not correctly work since C is not marked as
WIFI, so allowing it to communicate with other WIFI clients.
Signed-off-by: Antonio Quartulli <ordex(a)autistici.org>
---
v5:
- reduced code complexity
- batadv_tt_local_remove() now returns the flags set on the removed entry.
translation-table.c | 31 +++++++++++++++++++++++++------
translation-table.h | 6 +++---
2 files changed, 28 insertions(+), 9 deletions(-)
diff --git a/translation-table.c b/translation-table.c
index 42a74e3..255b38e 100644
--- a/translation-table.c
+++ b/translation-table.c
@@ -489,24 +489,39 @@ batadv_tt_local_set_pending(struct batadv_priv *bat_priv,
tt_local_entry->common.addr, message);
}
-void batadv_tt_local_remove(struct batadv_priv *bat_priv, const uint8_t *addr,
- const char *message, bool roaming)
+/**
+ * batadv_tt_local_remove - logically remove an entry from the local table
+ * @bat_priv: the bat priv with all the soft interface information
+ * @addr: the MAC address of the client to remove
+ * @message: message to append to the log on deletion
+ * @roaming: true if the deletion is due to a roaming event
+ *
+ * Returns the flags assigned to the local entry before being deleted
+ */
+uint16_t batadv_tt_local_remove(struct batadv_priv *bat_priv,
+ const uint8_t *addr, const char *message,
+ bool roaming)
{
struct batadv_tt_local_entry *tt_local_entry = NULL;
- uint16_t flags;
+ uint16_t flags, curr_flags = BATADV_NO_FLAGS;
tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr);
if (!tt_local_entry)
goto out;
+ curr_flags = tt_local_entry->common.flags;
+
flags = BATADV_TT_CLIENT_DEL;
if (roaming)
flags |= BATADV_TT_CLIENT_ROAM;
batadv_tt_local_set_pending(bat_priv, tt_local_entry, flags, message);
+
out:
if (tt_local_entry)
batadv_tt_local_entry_free_ref(tt_local_entry);
+
+ return curr_flags;
}
static void batadv_tt_local_purge_list(struct batadv_priv *bat_priv,
@@ -713,6 +728,7 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv,
int ret = 0;
int hash_added;
struct batadv_tt_common_entry *common;
+ uint16_t local_flags;
tt_global_entry = batadv_tt_global_hash_find(bat_priv, tt_addr);
@@ -779,10 +795,13 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv,
ret = 1;
out_remove:
+
/* remove address from local hash if present */
- batadv_tt_local_remove(bat_priv, tt_global_entry->common.addr,
- "global tt received",
- flags & BATADV_TT_CLIENT_ROAM);
+ local_flags = batadv_tt_local_remove(bat_priv, tt_addr,
+ "global tt received",
+ flags & BATADV_TT_CLIENT_ROAM);
+ tt_global_entry->common.flags |= local_flags & BATADV_TT_CLIENT_WIFI;
+
out:
if (tt_global_entry)
batadv_tt_global_entry_free_ref(tt_global_entry);
diff --git a/translation-table.h b/translation-table.h
index 811fffd..9fa4fe4 100644
--- a/translation-table.h
+++ b/translation-table.h
@@ -24,9 +24,9 @@ int batadv_tt_len(int changes_num);
int batadv_tt_init(struct batadv_priv *bat_priv);
void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
int ifindex);
-void batadv_tt_local_remove(struct batadv_priv *bat_priv,
- const uint8_t *addr, const char *message,
- bool roaming);
+uint16_t batadv_tt_local_remove(struct batadv_priv *bat_priv,
+ const uint8_t *addr, const char *message,
+ bool roaming);
int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset);
void batadv_tt_global_add_orig(struct batadv_priv *bat_priv,
struct batadv_orig_node *orig_node,
--
1.7.12
[View Less]
In batadv_check_unicast_ttvn() the code accesses both the unicast header and the
Ethernet header in the payload. For this reason pskb_may_pull() must be invoked
to check for the required space.
Signed-off-by: Antonio Quartulli <ordex(a)autistici.org>
---
routing.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/routing.c b/routing.c
index 784e9cc..44109cc 100644
--- a/routing.c
+++ b/routing.c
@@ -908,8 +908,12 @@ static int batadv_check_unicast_ttvn(struct …
[View More]batadv_priv *bat_priv,
bool tt_poss_change;
int is_old_ttvn;
- /* I could need to modify it */
- if (skb_cow(skb, sizeof(struct batadv_unicast_packet)) < 0)
+ /* check if there is enough data before accessing it */
+ if (pskb_may_pull(skb, sizeof(*unicast_packet) + ETH_HLEN) < 0)
+ return 0;
+
+ /* create a copy of the skb (in case of for re-routing) to modify it. */
+ if (skb_cow(skb, sizeof(*unicast_packet)) < 0)
return 0;
unicast_packet = (struct batadv_unicast_packet *)skb->data;
--
1.7.12
[View Less]