Skip to content

Commit

Permalink
batman-adv: improved client announcement mechanism
Browse files Browse the repository at this point in the history
The client announcement mechanism informs every mesh node in the network
of any connected non-mesh client, in order to find the path towards that
client from any given point in the mesh.

The old implementation was based on the simple idea of appending a data
buffer to each OGM containing all the client MAC addresses the node is
serving. All other nodes can populate their global translation tables
(table which links client MAC addresses to node addresses) using this
MAC address buffer and linking it to the node's address contained in the
OGM. A node that wants to contact a client has to lookup the node the
client is connected to and its address in the global translation table.

It is easy to understand that this implementation suffers from several
issues:
 - big overhead (each and every OGM contains the entire list of
   connected clients)
 - high latencies for client route updates due to long OGM trip time and
   OGM losses

The new implementation addresses these issues by appending client
changes (new client joined or a client left) to the OGM instead of
filling it with all the client addresses each time. In this way nodes
can modify their global tables by means of "updates", thus reducing the
overhead within the OGMs.

To keep the entire network in sync each node maintains a translation
table version number (ttvn) and a translation table checksum. These
values are spread with the OGM to allow all the network participants to
determine whether or not they need to update their translation table
information.

When a translation table lookup is performed in order to send a packet
to a client attached to another node, the destination's ttvn is added to
the payload packet. Forwarding nodes can compare the packet's ttvn with
their destination's ttvn (this node could have a fresher information
than the source) and re-route the packet if necessary. This greatly
reduces the packet loss of clients roaming from one AP to the next.

Signed-off-by: Antonio Quartulli <ordex@autistici.org>
Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
Signed-off-by: Sven Eckelmann <sven@narfation.org>
  • Loading branch information
Antonio Quartulli authored and Sven Eckelmann committed Jun 20, 2011
1 parent 3b27ffb commit a73105b
Show file tree
Hide file tree
Showing 18 changed files with 1,381 additions and 305 deletions.
1 change: 1 addition & 0 deletions net/batman-adv/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
config BATMAN_ADV
tristate "B.A.T.M.A.N. Advanced Meshing Protocol"
depends on NET
select CRC16
default n
---help---

Expand Down
23 changes: 10 additions & 13 deletions net/batman-adv/aggregation.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,12 @@
*/

#include "main.h"
#include "translation-table.h"
#include "aggregation.h"
#include "send.h"
#include "routing.h"
#include "hard-interface.h"

/* calculate the size of the tt information for a given packet */
static int tt_len(const struct batman_packet *batman_packet)
{
return batman_packet->num_tt * ETH_ALEN;
}

/* return true if new_packet can be aggregated with forw_packet */
static bool can_aggregate_with(const struct batman_packet *new_batman_packet,
int packet_len,
Expand Down Expand Up @@ -264,18 +259,20 @@ void receive_aggr_bat_packet(const struct ethhdr *ethhdr,
batman_packet = (struct batman_packet *)packet_buff;

do {
/* network to host order for our 32bit seqno, and the
orig_interval. */
/* network to host order for our 32bit seqno and the
orig_interval */
batman_packet->seqno = ntohl(batman_packet->seqno);
batman_packet->tt_crc = ntohs(batman_packet->tt_crc);

tt_buff = packet_buff + buff_pos + BAT_PACKET_LEN;
receive_bat_packet(ethhdr, batman_packet,
tt_buff, tt_len(batman_packet),
if_incoming);

buff_pos += BAT_PACKET_LEN + tt_len(batman_packet);
receive_bat_packet(ethhdr, batman_packet, tt_buff, if_incoming);

buff_pos += BAT_PACKET_LEN +
tt_len(batman_packet->tt_num_changes);

batman_packet = (struct batman_packet *)
(packet_buff + buff_pos);
} while (aggregated_packet(buff_pos, packet_len,
batman_packet->num_tt));
batman_packet->tt_num_changes));
}
6 changes: 4 additions & 2 deletions net/batman-adv/aggregation.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,11 @@
#include "main.h"

/* is there another aggregated packet here? */
static inline int aggregated_packet(int buff_pos, int packet_len, int num_tt)
static inline int aggregated_packet(int buff_pos, int packet_len,
int tt_num_changes)
{
int next_buff_pos = buff_pos + BAT_PACKET_LEN + (num_tt * ETH_ALEN);
int next_buff_pos = buff_pos + BAT_PACKET_LEN + (tt_num_changes *
sizeof(struct tt_change));

return (next_buff_pos <= packet_len) &&
(next_buff_pos <= MAX_AGGREGATION_BYTES);
Expand Down
2 changes: 1 addition & 1 deletion net/batman-adv/bat_sysfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,7 @@ BAT_ATTR_UINT(gw_sel_class, S_IRUGO | S_IWUSR, 1, TQ_MAX_VALUE,
static BAT_ATTR(gw_bandwidth, S_IRUGO | S_IWUSR, show_gw_bwidth,
store_gw_bwidth);
#ifdef CONFIG_BATMAN_ADV_DEBUG
BAT_ATTR_UINT(log_level, S_IRUGO | S_IWUSR, 0, 3, NULL);
BAT_ATTR_UINT(log_level, S_IRUGO | S_IWUSR, 0, 7, NULL);
#endif

static struct bat_attribute *mesh_attrs[] = {
Expand Down
13 changes: 6 additions & 7 deletions net/batman-adv/hard-interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -152,12 +152,6 @@ static void primary_if_select(struct bat_priv *bat_priv,
batman_packet->ttl = TTL;

primary_if_update_addr(bat_priv);

/***
* hacky trick to make sure that we send the TT information via
* our new primary interface
*/
atomic_set(&bat_priv->tt_local_changed, 1);
}

static bool hardif_is_iface_up(const struct hard_iface *hard_iface)
Expand Down Expand Up @@ -340,7 +334,8 @@ int hardif_enable_interface(struct hard_iface *hard_iface,
batman_packet->flags = NO_FLAGS;
batman_packet->ttl = 2;
batman_packet->tq = TQ_MAX_VALUE;
batman_packet->num_tt = 0;
batman_packet->tt_num_changes = 0;
batman_packet->ttvn = 0;

hard_iface->if_num = bat_priv->num_ifaces;
bat_priv->num_ifaces++;
Expand Down Expand Up @@ -659,6 +654,10 @@ static int batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
case BAT_VIS:
ret = recv_vis_packet(skb, hard_iface);
break;
/* Translation table query (request or response) */
case BAT_TT_QUERY:
ret = recv_tt_query(skb, hard_iface);
break;
default:
ret = NET_RX_DROP;
}
Expand Down
13 changes: 7 additions & 6 deletions net/batman-adv/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ int mesh_init(struct net_device *soft_iface)
spin_lock_init(&bat_priv->forw_bcast_list_lock);
spin_lock_init(&bat_priv->tt_lhash_lock);
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_buff_lock);
spin_lock_init(&bat_priv->gw_list_lock);
spin_lock_init(&bat_priv->vis_hash_lock);
spin_lock_init(&bat_priv->vis_list_lock);
Expand All @@ -96,14 +99,13 @@ int mesh_init(struct net_device *soft_iface)
INIT_HLIST_HEAD(&bat_priv->forw_bcast_list);
INIT_HLIST_HEAD(&bat_priv->gw_list);
INIT_HLIST_HEAD(&bat_priv->softif_neigh_vids);
INIT_LIST_HEAD(&bat_priv->tt_changes_list);
INIT_LIST_HEAD(&bat_priv->tt_req_list);

if (originator_init(bat_priv) < 1)
goto err;

if (tt_local_init(bat_priv) < 1)
goto err;

if (tt_global_init(bat_priv) < 1)
if (tt_init(bat_priv) < 1)
goto err;

tt_local_add(soft_iface, soft_iface->dev_addr);
Expand Down Expand Up @@ -137,8 +139,7 @@ void mesh_free(struct net_device *soft_iface)
gw_node_purge(bat_priv);
originator_free(bat_priv);

tt_local_free(bat_priv);
tt_global_free(bat_priv);
tt_free(bat_priv);

softif_neigh_purge(bat_priv);

Expand Down
7 changes: 6 additions & 1 deletion net/batman-adv/main.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,15 @@
/* sliding packet range of received originator messages in squence numbers
* (should be a multiple of our word size) */
#define TQ_LOCAL_WINDOW_SIZE 64
#define TT_REQUEST_TIMEOUT 3 /* seconds we have to keep pending tt_req */

#define TQ_GLOBAL_WINDOW_SIZE 5
#define TQ_LOCAL_BIDRECT_SEND_MINIMUM 1
#define TQ_LOCAL_BIDRECT_RECV_MINIMUM 1
#define TQ_TOTAL_BIDRECT_LIMIT 1

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

#define NO_FLAGS 0

#define NUM_WORDS (TQ_LOCAL_WINDOW_SIZE / WORD_BIT_SIZE)
Expand Down Expand Up @@ -96,7 +100,8 @@ enum mesh_state {
enum dbg_level {
DBG_BATMAN = 1 << 0,
DBG_ROUTES = 1 << 1, /* route added / changed / deleted */
DBG_ALL = 3
DBG_TT = 1 << 2, /* translation table operations */
DBG_ALL = 7
};


Expand Down
8 changes: 5 additions & 3 deletions net/batman-adv/originator.c
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ static void orig_node_free_rcu(struct rcu_head *rcu)
tt_global_del_orig(orig_node->bat_priv, orig_node,
"originator timed out");

kfree(orig_node->tt_buff);
kfree(orig_node->bcast_own);
kfree(orig_node->bcast_own_sum);
kfree(orig_node);
Expand Down Expand Up @@ -213,6 +214,7 @@ struct orig_node *get_orig_node(struct bat_priv *bat_priv, const uint8_t *addr)
spin_lock_init(&orig_node->ogm_cnt_lock);
spin_lock_init(&orig_node->bcast_seqno_lock);
spin_lock_init(&orig_node->neigh_list_lock);
spin_lock_init(&orig_node->tt_buff_lock);

/* extra reference for return */
atomic_set(&orig_node->refcount, 2);
Expand All @@ -221,6 +223,8 @@ struct orig_node *get_orig_node(struct bat_priv *bat_priv, const uint8_t *addr)
memcpy(orig_node->orig, addr, ETH_ALEN);
orig_node->router = NULL;
orig_node->tt_buff = NULL;
orig_node->tt_buff_len = 0;
atomic_set(&orig_node->tt_size, 0);
orig_node->bcast_seqno_reset = jiffies - 1
- msecs_to_jiffies(RESET_PROTECTION_MS);
orig_node->batman_seqno_reset = jiffies - 1
Expand Down Expand Up @@ -330,9 +334,7 @@ static bool purge_orig_node(struct bat_priv *bat_priv,
if (purge_orig_neighbors(bat_priv, orig_node,
&best_neigh_node)) {
update_routes(bat_priv, orig_node,
best_neigh_node,
orig_node->tt_buff,
orig_node->tt_buff_len);
best_neigh_node);
}
}

Expand Down
59 changes: 54 additions & 5 deletions net/batman-adv/packet.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ enum bat_packettype {
BAT_UNICAST = 0x03,
BAT_BCAST = 0x04,
BAT_VIS = 0x05,
BAT_UNICAST_FRAG = 0x06
BAT_UNICAST_FRAG = 0x06,
BAT_TT_QUERY = 0x07
};

/* this file is included by batctl which needs these defines */
Expand Down Expand Up @@ -63,6 +64,25 @@ enum unicast_frag_flags {
UNI_FRAG_LARGETAIL = 1 << 1
};

/* TT_QUERY subtypes */
#define TT_QUERY_TYPE_MASK 0x3

enum tt_query_packettype {
TT_REQUEST = 0,
TT_RESPONSE = 1
};

/* TT_QUERY flags */
enum tt_query_flags {
TT_FULL_TABLE = 1 << 2
};

/* TT_CHANGE flags */
enum tt_change_flags {
TT_CHANGE_DEL = 0x01,
TT_CLIENT_ROAM = 0x02
};

struct batman_packet {
uint8_t packet_type;
uint8_t version; /* batman version field */
Expand All @@ -73,8 +93,9 @@ struct batman_packet {
uint8_t prev_sender[6];
uint8_t gw_flags; /* flags related to gateway class */
uint8_t tq;
uint8_t num_tt;
uint8_t reserved;
uint8_t tt_num_changes;
uint8_t ttvn; /* translation table version number */
uint16_t tt_crc;
} __packed;

#define BAT_PACKET_LEN sizeof(struct batman_packet)
Expand Down Expand Up @@ -112,15 +133,15 @@ struct unicast_packet {
uint8_t packet_type;
uint8_t version; /* batman version field */
uint8_t ttl;
uint8_t reserved;
uint8_t ttvn; /* destination translation table version number */
uint8_t dest[6];
} __packed;

struct unicast_frag_packet {
uint8_t packet_type;
uint8_t version; /* batman version field */
uint8_t ttl;
uint8_t reserved;
uint8_t ttvn; /* destination translation table version number */
uint8_t dest[6];
uint8_t flags;
uint8_t align;
Expand Down Expand Up @@ -150,4 +171,32 @@ struct vis_packet {
uint8_t sender_orig[6]; /* who sent or rebroadcasted this packet */
} __packed;

struct tt_query_packet {
uint8_t packet_type;
uint8_t version; /* batman version field */
uint8_t ttl;
/* the flag field is a combination of:
* - TT_REQUEST or TT_RESPONSE
* - TT_FULL_TABLE */
uint8_t flags;
uint8_t dst[ETH_ALEN];
uint8_t src[ETH_ALEN];
/* the ttvn field is:
* if TT_REQUEST: ttvn that triggered the
* request
* if TT_RESPONSE: new ttvn for the src
* orig_node */
uint8_t ttvn;
/* tt_data field is:
* if TT_REQUEST: crc associated with the
* ttvn
* if TT_RESPONSE: table_size */
uint16_t tt_data;
} __packed;

struct tt_change {
uint8_t flags;
uint8_t addr[ETH_ALEN];
} __packed;

#endif /* _NET_BATMAN_ADV_PACKET_H_ */
Loading

0 comments on commit a73105b

Please sign in to comment.