Skip to content

Commit

Permalink
batman-adv: improved roaming mechanism
Browse files Browse the repository at this point in the history
With the current client announcement implementation, in case of roaming,
an update is triggered on the new AP serving the client. At that point
the new information is spread around by means of the OGM broadcasting
mechanism. Until this operations is not executed, no node is able to
correctly route traffic towards the client. This obviously causes packet
drops and introduces a delay in the time needed by the client to recover
its connections.

A new packet type called ROAMING_ADVERTISEMENT is added to account this
issue.

This message is sent in case of roaming from the new AP serving the
client to the old one and will contain the client MAC address. In this
way an out-of-OGM update is immediately committed, so that the old node
can update its global translation table. Traffic reaching this node will
then be redirected to the correct destination utilising the fresher
information. Thus reducing the packet drops and the connection recovery
delay.

Signed-off-by: Antonio Quartulli <ordex@autistici.org>
Signed-off-by: Sven Eckelmann <sven@narfation.org>
  • Loading branch information
Antonio Quartulli authored and Sven Eckelmann committed Jun 20, 2011
1 parent a73105b commit cc47f66
Show file tree
Hide file tree
Showing 12 changed files with 334 additions and 33 deletions.
4 changes: 4 additions & 0 deletions net/batman-adv/hard-interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -658,6 +658,10 @@ static int batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
case BAT_TT_QUERY:
ret = recv_tt_query(skb, hard_iface);
break;
/* Roaming advertisement */
case BAT_ROAM_ADV:
ret = recv_roam_adv(skb, hard_iface);
break;
default:
ret = NET_RX_DROP;
}
Expand Down
2 changes: 2 additions & 0 deletions net/batman-adv/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ int mesh_init(struct net_device *soft_iface)
spin_lock_init(&bat_priv->tt_ghash_lock);
spin_lock_init(&bat_priv->tt_changes_list_lock);
spin_lock_init(&bat_priv->tt_req_list_lock);
spin_lock_init(&bat_priv->tt_roam_list_lock);
spin_lock_init(&bat_priv->tt_buff_lock);
spin_lock_init(&bat_priv->gw_list_lock);
spin_lock_init(&bat_priv->vis_hash_lock);
Expand All @@ -101,6 +102,7 @@ int mesh_init(struct net_device *soft_iface)
INIT_HLIST_HEAD(&bat_priv->softif_neigh_vids);
INIT_LIST_HEAD(&bat_priv->tt_changes_list);
INIT_LIST_HEAD(&bat_priv->tt_req_list);
INIT_LIST_HEAD(&bat_priv->tt_roam_list);

if (originator_init(bat_priv) < 1)
goto err;
Expand Down
6 changes: 5 additions & 1 deletion net/batman-adv/main.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
* -> TODO: check influence on TQ_LOCAL_WINDOW_SIZE */
#define PURGE_TIMEOUT 200
#define TT_LOCAL_TIMEOUT 3600 /* in seconds */

#define TT_CLIENT_ROAM_TIMEOUT 600
/* sliding packet range of received originator messages in squence numbers
* (should be a multiple of our word size) */
#define TQ_LOCAL_WINDOW_SIZE 64
Expand All @@ -55,6 +55,10 @@

#define TT_OGM_APPEND_MAX 3 /* number of OGMs sent with the last tt diff */

#define ROAMING_MAX_TIME 20 /* Time in which a client can roam at most
* ROAMING_MAX_COUNT times */
#define ROAMING_MAX_COUNT 5

#define NO_FLAGS 0

#define NUM_WORDS (TQ_LOCAL_WINDOW_SIZE / WORD_BIT_SIZE)
Expand Down
1 change: 1 addition & 0 deletions net/batman-adv/originator.c
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,7 @@ struct orig_node *get_orig_node(struct bat_priv *bat_priv, const uint8_t *addr)
/* extra reference for return */
atomic_set(&orig_node->refcount, 2);

orig_node->tt_poss_change = false;
orig_node->bat_priv = bat_priv;
memcpy(orig_node->orig, addr, ETH_ALEN);
orig_node->router = NULL;
Expand Down
13 changes: 12 additions & 1 deletion net/batman-adv/packet.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ enum bat_packettype {
BAT_BCAST = 0x04,
BAT_VIS = 0x05,
BAT_UNICAST_FRAG = 0x06,
BAT_TT_QUERY = 0x07
BAT_TT_QUERY = 0x07,
BAT_ROAM_ADV = 0x08
};

/* this file is included by batctl which needs these defines */
Expand Down Expand Up @@ -194,6 +195,16 @@ struct tt_query_packet {
uint16_t tt_data;
} __packed;

struct roam_adv_packet {
uint8_t packet_type;
uint8_t version;
uint8_t ttl;
uint8_t reserved;
uint8_t dst[ETH_ALEN];
uint8_t src[ETH_ALEN];
uint8_t client[ETH_ALEN];
} __packed;

struct tt_change {
uint8_t flags;
uint8_t addr[ETH_ALEN];
Expand Down
61 changes: 57 additions & 4 deletions net/batman-adv/routing.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,9 @@ static void update_transtable(struct bat_priv *bat_priv,
spin_lock_bh(&bat_priv->tt_ghash_lock);
orig_node->tt_crc = tt_global_crc(bat_priv, orig_node);
spin_unlock_bh(&bat_priv->tt_ghash_lock);
/* Roaming phase is over: tables are in sync again. I can
* unset the flag */
orig_node->tt_poss_change = false;
} else {
/* if we missed more than one change or our tables are not
* in sync anymore -> request fresh tt data */
Expand Down Expand Up @@ -1252,6 +1255,54 @@ int recv_tt_query(struct sk_buff *skb, struct hard_iface *recv_if)
return NET_RX_DROP;
}

int recv_roam_adv(struct sk_buff *skb, struct hard_iface *recv_if)
{
struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface);
struct roam_adv_packet *roam_adv_packet;
struct orig_node *orig_node;
struct ethhdr *ethhdr;

/* drop packet if it has not necessary minimum size */
if (unlikely(!pskb_may_pull(skb, sizeof(struct roam_adv_packet))))
goto out;

ethhdr = (struct ethhdr *)skb_mac_header(skb);

/* packet with unicast indication but broadcast recipient */
if (is_broadcast_ether_addr(ethhdr->h_dest))
goto out;

/* packet with broadcast sender address */
if (is_broadcast_ether_addr(ethhdr->h_source))
goto out;

roam_adv_packet = (struct roam_adv_packet *)skb->data;

if (!is_my_mac(roam_adv_packet->dst))
return route_unicast_packet(skb, recv_if);

orig_node = orig_hash_find(bat_priv, roam_adv_packet->src);
if (!orig_node)
goto out;

bat_dbg(DBG_TT, bat_priv, "Received ROAMING_ADV from %pM "
"(client %pM)\n", 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);

/* Roaming phase starts: I have new information but the ttvn has not
* been incremented yet. This flag will make me check all the incoming
* packets for the correct destination. */
bat_priv->tt_poss_change = true;

orig_node_free_ref(orig_node);
out:
/* returning NET_RX_DROP will make the caller function kfree the skb */
return NET_RX_DROP;
}

/* find a suitable router for this originator, and use
* bonding if possible. increases the found neighbors
* refcount.*/
Expand Down Expand Up @@ -1445,34 +1496,36 @@ static int check_unicast_ttvn(struct bat_priv *bat_priv,
struct ethhdr *ethhdr;
struct hard_iface *primary_if;
struct unicast_packet *unicast_packet;
bool tt_poss_change;

/* I could need to modify it */
if (skb_cow(skb, sizeof(struct unicast_packet)) < 0)
return 0;

unicast_packet = (struct unicast_packet *)skb->data;

if (is_my_mac(unicast_packet->dest))
if (is_my_mac(unicast_packet->dest)) {
tt_poss_change = bat_priv->tt_poss_change;
curr_ttvn = (uint8_t)atomic_read(&bat_priv->ttvn);
else {
} else {
orig_node = orig_hash_find(bat_priv, unicast_packet->dest);

if (!orig_node)
return 0;

curr_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn);
tt_poss_change = orig_node->tt_poss_change;
orig_node_free_ref(orig_node);
}

/* Check whether I have to reroute the packet */
if (seq_before(unicast_packet->ttvn, curr_ttvn)) {
if (seq_before(unicast_packet->ttvn, curr_ttvn) || tt_poss_change) {
/* Linearize the skb before accessing it */
if (skb_linearize(skb) < 0)
return 0;

ethhdr = (struct ethhdr *)(skb->data +
sizeof(struct unicast_packet));

orig_node = transtable_search(bat_priv, ethhdr->h_dest);

if (!orig_node) {
Expand Down
1 change: 1 addition & 0 deletions net/batman-adv/routing.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ int recv_bcast_packet(struct sk_buff *skb, struct hard_iface *recv_if);
int recv_vis_packet(struct sk_buff *skb, struct hard_iface *recv_if);
int recv_bat_packet(struct sk_buff *skb, struct hard_iface *recv_if);
int recv_tt_query(struct sk_buff *skb, struct hard_iface *recv_if);
int recv_roam_adv(struct sk_buff *skb, struct hard_iface *recv_if);
struct neigh_node *find_router(struct bat_priv *bat_priv,
struct orig_node *orig_node,
const struct hard_iface *recv_if);
Expand Down
1 change: 1 addition & 0 deletions net/batman-adv/send.c
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,7 @@ void schedule_own_packet(struct hard_iface *hard_iface)
prepare_packet_buffer(bat_priv, hard_iface);
/* Increment the TTVN only once per OGM interval */
atomic_inc(&bat_priv->ttvn);
bat_priv->tt_poss_change = false;
}

/* if the changes have been sent enough times */
Expand Down
3 changes: 2 additions & 1 deletion net/batman-adv/soft-interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -534,7 +534,7 @@ static int interface_set_mac_addr(struct net_device *dev, void *p)
/* only modify transtable if it has been initialised before */
if (atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE) {
tt_local_remove(bat_priv, dev->dev_addr,
"mac address changed");
"mac address changed", false);
tt_local_add(dev, addr->sa_data);
}

Expand Down Expand Up @@ -836,6 +836,7 @@ struct net_device *softif_create(const char *name)

bat_priv->tt_buff = NULL;
bat_priv->tt_buff_len = 0;
bat_priv->tt_poss_change = false;

bat_priv->primary_if = NULL;
bat_priv->num_ifaces = 0;
Expand Down
Loading

0 comments on commit cc47f66

Please sign in to comment.