aboutsummaryrefslogtreecommitdiffstats
path: root/net/batman-adv/routing.c
diff options
context:
space:
mode:
authorAntonio Quartulli <ordex@autistici.org>2011-04-27 08:27:57 -0400
committerSven Eckelmann <sven@narfation.org>2011-06-20 05:37:27 -0400
commitcc47f66e6b9ec7e7d465f74739a6fc9844593894 (patch)
tree8fbda7f59267bca45f9e887d09ba1de2f3c62f8d /net/batman-adv/routing.c
parenta73105b8d4c765d9ebfb664d0a66802127d8e4c7 (diff)
batman-adv: improved roaming mechanism
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>
Diffstat (limited to 'net/batman-adv/routing.c')
-rw-r--r--net/batman-adv/routing.c61
1 files changed, 57 insertions, 4 deletions
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c
index 8b0f8330b06d..05d50ca3c4db 100644
--- a/net/batman-adv/routing.c
+++ b/net/batman-adv/routing.c
@@ -93,6 +93,9 @@ static void update_transtable(struct bat_priv *bat_priv,
93 spin_lock_bh(&bat_priv->tt_ghash_lock); 93 spin_lock_bh(&bat_priv->tt_ghash_lock);
94 orig_node->tt_crc = tt_global_crc(bat_priv, orig_node); 94 orig_node->tt_crc = tt_global_crc(bat_priv, orig_node);
95 spin_unlock_bh(&bat_priv->tt_ghash_lock); 95 spin_unlock_bh(&bat_priv->tt_ghash_lock);
96 /* Roaming phase is over: tables are in sync again. I can
97 * unset the flag */
98 orig_node->tt_poss_change = false;
96 } else { 99 } else {
97 /* if we missed more than one change or our tables are not 100 /* if we missed more than one change or our tables are not
98 * in sync anymore -> request fresh tt data */ 101 * in sync anymore -> request fresh tt data */
@@ -1252,6 +1255,54 @@ out:
1252 return NET_RX_DROP; 1255 return NET_RX_DROP;
1253} 1256}
1254 1257
1258int recv_roam_adv(struct sk_buff *skb, struct hard_iface *recv_if)
1259{
1260 struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface);
1261 struct roam_adv_packet *roam_adv_packet;
1262 struct orig_node *orig_node;
1263 struct ethhdr *ethhdr;
1264
1265 /* drop packet if it has not necessary minimum size */
1266 if (unlikely(!pskb_may_pull(skb, sizeof(struct roam_adv_packet))))
1267 goto out;
1268
1269 ethhdr = (struct ethhdr *)skb_mac_header(skb);
1270
1271 /* packet with unicast indication but broadcast recipient */
1272 if (is_broadcast_ether_addr(ethhdr->h_dest))
1273 goto out;
1274
1275 /* packet with broadcast sender address */
1276 if (is_broadcast_ether_addr(ethhdr->h_source))
1277 goto out;
1278
1279 roam_adv_packet = (struct roam_adv_packet *)skb->data;
1280
1281 if (!is_my_mac(roam_adv_packet->dst))
1282 return route_unicast_packet(skb, recv_if);
1283
1284 orig_node = orig_hash_find(bat_priv, roam_adv_packet->src);
1285 if (!orig_node)
1286 goto out;
1287
1288 bat_dbg(DBG_TT, bat_priv, "Received ROAMING_ADV from %pM "
1289 "(client %pM)\n", roam_adv_packet->src,
1290 roam_adv_packet->client);
1291
1292 tt_global_add(bat_priv, orig_node, roam_adv_packet->client,
1293 atomic_read(&orig_node->last_ttvn) + 1, true);
1294
1295 /* Roaming phase starts: I have new information but the ttvn has not
1296 * been incremented yet. This flag will make me check all the incoming
1297 * packets for the correct destination. */
1298 bat_priv->tt_poss_change = true;
1299
1300 orig_node_free_ref(orig_node);
1301out:
1302 /* returning NET_RX_DROP will make the caller function kfree the skb */
1303 return NET_RX_DROP;
1304}
1305
1255/* find a suitable router for this originator, and use 1306/* find a suitable router for this originator, and use
1256 * bonding if possible. increases the found neighbors 1307 * bonding if possible. increases the found neighbors
1257 * refcount.*/ 1308 * refcount.*/
@@ -1445,6 +1496,7 @@ static int check_unicast_ttvn(struct bat_priv *bat_priv,
1445 struct ethhdr *ethhdr; 1496 struct ethhdr *ethhdr;
1446 struct hard_iface *primary_if; 1497 struct hard_iface *primary_if;
1447 struct unicast_packet *unicast_packet; 1498 struct unicast_packet *unicast_packet;
1499 bool tt_poss_change;
1448 1500
1449 /* I could need to modify it */ 1501 /* I could need to modify it */
1450 if (skb_cow(skb, sizeof(struct unicast_packet)) < 0) 1502 if (skb_cow(skb, sizeof(struct unicast_packet)) < 0)
@@ -1452,27 +1504,28 @@ static int check_unicast_ttvn(struct bat_priv *bat_priv,
1452 1504
1453 unicast_packet = (struct unicast_packet *)skb->data; 1505 unicast_packet = (struct unicast_packet *)skb->data;
1454 1506
1455 if (is_my_mac(unicast_packet->dest)) 1507 if (is_my_mac(unicast_packet->dest)) {
1508 tt_poss_change = bat_priv->tt_poss_change;
1456 curr_ttvn = (uint8_t)atomic_read(&bat_priv->ttvn); 1509 curr_ttvn = (uint8_t)atomic_read(&bat_priv->ttvn);
1457 else { 1510 } else {
1458 orig_node = orig_hash_find(bat_priv, unicast_packet->dest); 1511 orig_node = orig_hash_find(bat_priv, unicast_packet->dest);
1459 1512
1460 if (!orig_node) 1513 if (!orig_node)
1461 return 0; 1514 return 0;
1462 1515
1463 curr_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn); 1516 curr_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn);
1517 tt_poss_change = orig_node->tt_poss_change;
1464 orig_node_free_ref(orig_node); 1518 orig_node_free_ref(orig_node);
1465 } 1519 }
1466 1520
1467 /* Check whether I have to reroute the packet */ 1521 /* Check whether I have to reroute the packet */
1468 if (seq_before(unicast_packet->ttvn, curr_ttvn)) { 1522 if (seq_before(unicast_packet->ttvn, curr_ttvn) || tt_poss_change) {
1469 /* Linearize the skb before accessing it */ 1523 /* Linearize the skb before accessing it */
1470 if (skb_linearize(skb) < 0) 1524 if (skb_linearize(skb) < 0)
1471 return 0; 1525 return 0;
1472 1526
1473 ethhdr = (struct ethhdr *)(skb->data + 1527 ethhdr = (struct ethhdr *)(skb->data +
1474 sizeof(struct unicast_packet)); 1528 sizeof(struct unicast_packet));
1475
1476 orig_node = transtable_search(bat_priv, ethhdr->h_dest); 1529 orig_node = transtable_search(bat_priv, ethhdr->h_dest);
1477 1530
1478 if (!orig_node) { 1531 if (!orig_node) {