aboutsummaryrefslogtreecommitdiffstats
path: root/net/batman-adv/send.c
diff options
context:
space:
mode:
authorAntonio Quartulli <ordex@autistici.org>2011-04-27 08:27:44 -0400
committerSven Eckelmann <sven@narfation.org>2011-06-20 05:37:24 -0400
commita73105b8d4c765d9ebfb664d0a66802127d8e4c7 (patch)
treeb4b11a4050109d8f042c7ac87a5a6d6d91b5d1d2 /net/batman-adv/send.c
parent3b27ffb00fbe9d9189715ea13ce8712e2f0cb0c5 (diff)
batman-adv: improved client announcement mechanism
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>
Diffstat (limited to 'net/batman-adv/send.c')
-rw-r--r--net/batman-adv/send.c87
1 files changed, 67 insertions, 20 deletions
diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c
index be0d581a62a9..6b1407570e44 100644
--- a/net/batman-adv/send.c
+++ b/net/batman-adv/send.c
@@ -120,7 +120,7 @@ static void send_packet_to_if(struct forw_packet *forw_packet,
120 /* adjust all flags and log packets */ 120 /* adjust all flags and log packets */
121 while (aggregated_packet(buff_pos, 121 while (aggregated_packet(buff_pos,
122 forw_packet->packet_len, 122 forw_packet->packet_len,
123 batman_packet->num_tt)) { 123 batman_packet->tt_num_changes)) {
124 124
125 /* we might have aggregated direct link packets with an 125 /* we might have aggregated direct link packets with an
126 * ordinary base packet */ 126 * ordinary base packet */
@@ -135,17 +135,17 @@ static void send_packet_to_if(struct forw_packet *forw_packet,
135 "Forwarding")); 135 "Forwarding"));
136 bat_dbg(DBG_BATMAN, bat_priv, 136 bat_dbg(DBG_BATMAN, bat_priv,
137 "%s %spacket (originator %pM, seqno %d, TQ %d, TTL %d," 137 "%s %spacket (originator %pM, seqno %d, TQ %d, TTL %d,"
138 " IDF %s) on interface %s [%pM]\n", 138 " IDF %s, hvn %d) on interface %s [%pM]\n",
139 fwd_str, (packet_num > 0 ? "aggregated " : ""), 139 fwd_str, (packet_num > 0 ? "aggregated " : ""),
140 batman_packet->orig, ntohl(batman_packet->seqno), 140 batman_packet->orig, ntohl(batman_packet->seqno),
141 batman_packet->tq, batman_packet->ttl, 141 batman_packet->tq, batman_packet->ttl,
142 (batman_packet->flags & DIRECTLINK ? 142 (batman_packet->flags & DIRECTLINK ?
143 "on" : "off"), 143 "on" : "off"),
144 hard_iface->net_dev->name, 144 batman_packet->ttvn, hard_iface->net_dev->name,
145 hard_iface->net_dev->dev_addr); 145 hard_iface->net_dev->dev_addr);
146 146
147 buff_pos += sizeof(*batman_packet) + 147 buff_pos += sizeof(*batman_packet) +
148 (batman_packet->num_tt * ETH_ALEN); 148 tt_len(batman_packet->tt_num_changes);
149 packet_num++; 149 packet_num++;
150 batman_packet = (struct batman_packet *) 150 batman_packet = (struct batman_packet *)
151 (forw_packet->skb->data + buff_pos); 151 (forw_packet->skb->data + buff_pos);
@@ -213,25 +213,18 @@ static void send_packet(struct forw_packet *forw_packet)
213 rcu_read_unlock(); 213 rcu_read_unlock();
214} 214}
215 215
216static void rebuild_batman_packet(struct bat_priv *bat_priv, 216static void realloc_packet_buffer(struct hard_iface *hard_iface,
217 struct hard_iface *hard_iface) 217 int new_len)
218{ 218{
219 int new_len;
220 unsigned char *new_buff; 219 unsigned char *new_buff;
221 struct batman_packet *batman_packet; 220 struct batman_packet *batman_packet;
222 221
223 new_len = sizeof(*batman_packet) + (bat_priv->num_local_tt * ETH_ALEN);
224 new_buff = kmalloc(new_len, GFP_ATOMIC); 222 new_buff = kmalloc(new_len, GFP_ATOMIC);
225 223
226 /* keep old buffer if kmalloc should fail */ 224 /* keep old buffer if kmalloc should fail */
227 if (new_buff) { 225 if (new_buff) {
228 memcpy(new_buff, hard_iface->packet_buff, 226 memcpy(new_buff, hard_iface->packet_buff,
229 sizeof(*batman_packet)); 227 sizeof(*batman_packet));
230 batman_packet = (struct batman_packet *)new_buff;
231
232 batman_packet->num_tt = tt_local_fill_buffer(bat_priv,
233 new_buff + sizeof(*batman_packet),
234 new_len - sizeof(*batman_packet));
235 228
236 kfree(hard_iface->packet_buff); 229 kfree(hard_iface->packet_buff);
237 hard_iface->packet_buff = new_buff; 230 hard_iface->packet_buff = new_buff;
@@ -239,6 +232,46 @@ static void rebuild_batman_packet(struct bat_priv *bat_priv,
239 } 232 }
240} 233}
241 234
235/* when calling this function (hard_iface == primary_if) has to be true */
236static void prepare_packet_buffer(struct bat_priv *bat_priv,
237 struct hard_iface *hard_iface)
238{
239 int new_len;
240 struct batman_packet *batman_packet;
241
242 new_len = BAT_PACKET_LEN +
243 tt_len((uint8_t)atomic_read(&bat_priv->tt_local_changes));
244
245 /* if we have too many changes for one packet don't send any
246 * and wait for the tt table request which will be fragmented */
247 if (new_len > hard_iface->soft_iface->mtu)
248 new_len = BAT_PACKET_LEN;
249
250 realloc_packet_buffer(hard_iface, new_len);
251 batman_packet = (struct batman_packet *)hard_iface->packet_buff;
252
253 atomic_set(&bat_priv->tt_crc, tt_local_crc(bat_priv));
254
255 /* reset the sending counter */
256 atomic_set(&bat_priv->tt_ogm_append_cnt, TT_OGM_APPEND_MAX);
257
258 batman_packet->tt_num_changes = tt_changes_fill_buffer(bat_priv,
259 hard_iface->packet_buff + BAT_PACKET_LEN,
260 hard_iface->packet_len - BAT_PACKET_LEN);
261
262}
263
264static void reset_packet_buffer(struct bat_priv *bat_priv,
265 struct hard_iface *hard_iface)
266{
267 struct batman_packet *batman_packet;
268
269 realloc_packet_buffer(hard_iface, BAT_PACKET_LEN);
270
271 batman_packet = (struct batman_packet *)hard_iface->packet_buff;
272 batman_packet->tt_num_changes = 0;
273}
274
242void schedule_own_packet(struct hard_iface *hard_iface) 275void schedule_own_packet(struct hard_iface *hard_iface)
243{ 276{
244 struct bat_priv *bat_priv = netdev_priv(hard_iface->soft_iface); 277 struct bat_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
@@ -264,14 +297,22 @@ void schedule_own_packet(struct hard_iface *hard_iface)
264 if (hard_iface->if_status == IF_TO_BE_ACTIVATED) 297 if (hard_iface->if_status == IF_TO_BE_ACTIVATED)
265 hard_iface->if_status = IF_ACTIVE; 298 hard_iface->if_status = IF_ACTIVE;
266 299
267 /* if local tt has changed and interface is a primary interface */ 300 if (hard_iface == primary_if) {
268 if ((atomic_read(&bat_priv->tt_local_changed)) && 301 /* if at least one change happened */
269 (hard_iface == primary_if)) 302 if (atomic_read(&bat_priv->tt_local_changes) > 0) {
270 rebuild_batman_packet(bat_priv, hard_iface); 303 prepare_packet_buffer(bat_priv, hard_iface);
304 /* Increment the TTVN only once per OGM interval */
305 atomic_inc(&bat_priv->ttvn);
306 }
307
308 /* if the changes have been sent enough times */
309 if (!atomic_dec_not_zero(&bat_priv->tt_ogm_append_cnt))
310 reset_packet_buffer(bat_priv, hard_iface);
311 }
271 312
272 /** 313 /**
273 * NOTE: packet_buff might just have been re-allocated in 314 * NOTE: packet_buff might just have been re-allocated in
274 * rebuild_batman_packet() 315 * prepare_packet_buffer() or in reset_packet_buffer()
275 */ 316 */
276 batman_packet = (struct batman_packet *)hard_iface->packet_buff; 317 batman_packet = (struct batman_packet *)hard_iface->packet_buff;
277 318
@@ -279,6 +320,9 @@ void schedule_own_packet(struct hard_iface *hard_iface)
279 batman_packet->seqno = 320 batman_packet->seqno =
280 htonl((uint32_t)atomic_read(&hard_iface->seqno)); 321 htonl((uint32_t)atomic_read(&hard_iface->seqno));
281 322
323 batman_packet->ttvn = atomic_read(&bat_priv->ttvn);
324 batman_packet->tt_crc = htons((uint16_t)atomic_read(&bat_priv->tt_crc));
325
282 if (vis_server == VIS_TYPE_SERVER_SYNC) 326 if (vis_server == VIS_TYPE_SERVER_SYNC)
283 batman_packet->flags |= VIS_SERVER; 327 batman_packet->flags |= VIS_SERVER;
284 else 328 else
@@ -307,13 +351,14 @@ void schedule_own_packet(struct hard_iface *hard_iface)
307void schedule_forward_packet(struct orig_node *orig_node, 351void schedule_forward_packet(struct orig_node *orig_node,
308 const struct ethhdr *ethhdr, 352 const struct ethhdr *ethhdr,
309 struct batman_packet *batman_packet, 353 struct batman_packet *batman_packet,
310 int directlink, int tt_buff_len, 354 int directlink,
311 struct hard_iface *if_incoming) 355 struct hard_iface *if_incoming)
312{ 356{
313 struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface); 357 struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
314 struct neigh_node *router; 358 struct neigh_node *router;
315 uint8_t in_tq, in_ttl, tq_avg = 0; 359 uint8_t in_tq, in_ttl, tq_avg = 0;
316 unsigned long send_time; 360 unsigned long send_time;
361 uint8_t tt_num_changes;
317 362
318 if (batman_packet->ttl <= 1) { 363 if (batman_packet->ttl <= 1) {
319 bat_dbg(DBG_BATMAN, bat_priv, "ttl exceeded\n"); 364 bat_dbg(DBG_BATMAN, bat_priv, "ttl exceeded\n");
@@ -324,6 +369,7 @@ void schedule_forward_packet(struct orig_node *orig_node,
324 369
325 in_tq = batman_packet->tq; 370 in_tq = batman_packet->tq;
326 in_ttl = batman_packet->ttl; 371 in_ttl = batman_packet->ttl;
372 tt_num_changes = batman_packet->tt_num_changes;
327 373
328 batman_packet->ttl--; 374 batman_packet->ttl--;
329 memcpy(batman_packet->prev_sender, ethhdr->h_source, ETH_ALEN); 375 memcpy(batman_packet->prev_sender, ethhdr->h_source, ETH_ALEN);
@@ -356,6 +402,7 @@ void schedule_forward_packet(struct orig_node *orig_node,
356 batman_packet->ttl); 402 batman_packet->ttl);
357 403
358 batman_packet->seqno = htonl(batman_packet->seqno); 404 batman_packet->seqno = htonl(batman_packet->seqno);
405 batman_packet->tt_crc = htons(batman_packet->tt_crc);
359 406
360 /* switch of primaries first hop flag when forwarding */ 407 /* switch of primaries first hop flag when forwarding */
361 batman_packet->flags &= ~PRIMARIES_FIRST_HOP; 408 batman_packet->flags &= ~PRIMARIES_FIRST_HOP;
@@ -367,7 +414,7 @@ void schedule_forward_packet(struct orig_node *orig_node,
367 send_time = forward_send_time(); 414 send_time = forward_send_time();
368 add_bat_packet_to_list(bat_priv, 415 add_bat_packet_to_list(bat_priv,
369 (unsigned char *)batman_packet, 416 (unsigned char *)batman_packet,
370 sizeof(*batman_packet) + tt_buff_len, 417 sizeof(*batman_packet) + tt_len(tt_num_changes),
371 if_incoming, 0, send_time); 418 if_incoming, 0, send_time);
372} 419}
373 420