diff options
Diffstat (limited to 'net/batman-adv')
-rw-r--r-- | net/batman-adv/hard-interface.c | 4 | ||||
-rw-r--r-- | net/batman-adv/main.c | 2 | ||||
-rw-r--r-- | net/batman-adv/main.h | 6 | ||||
-rw-r--r-- | net/batman-adv/originator.c | 1 | ||||
-rw-r--r-- | net/batman-adv/packet.h | 13 | ||||
-rw-r--r-- | net/batman-adv/routing.c | 61 | ||||
-rw-r--r-- | net/batman-adv/routing.h | 1 | ||||
-rw-r--r-- | net/batman-adv/send.c | 1 | ||||
-rw-r--r-- | net/batman-adv/soft-interface.c | 3 | ||||
-rw-r--r-- | net/batman-adv/translation-table.c | 241 | ||||
-rw-r--r-- | net/batman-adv/translation-table.h | 8 | ||||
-rw-r--r-- | net/batman-adv/types.h | 26 |
12 files changed, 334 insertions, 33 deletions
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c index d40426cc5e29..55b5def08d5a 100644 --- a/net/batman-adv/hard-interface.c +++ b/net/batman-adv/hard-interface.c | |||
@@ -658,6 +658,10 @@ static int batman_skb_recv(struct sk_buff *skb, struct net_device *dev, | |||
658 | case BAT_TT_QUERY: | 658 | case BAT_TT_QUERY: |
659 | ret = recv_tt_query(skb, hard_iface); | 659 | ret = recv_tt_query(skb, hard_iface); |
660 | break; | 660 | break; |
661 | /* Roaming advertisement */ | ||
662 | case BAT_ROAM_ADV: | ||
663 | ret = recv_roam_adv(skb, hard_iface); | ||
664 | break; | ||
661 | default: | 665 | default: |
662 | ret = NET_RX_DROP; | 666 | ret = NET_RX_DROP; |
663 | } | 667 | } |
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c index 49a5e64b2d4f..3318ee27fe23 100644 --- a/net/batman-adv/main.c +++ b/net/batman-adv/main.c | |||
@@ -88,6 +88,7 @@ int mesh_init(struct net_device *soft_iface) | |||
88 | spin_lock_init(&bat_priv->tt_ghash_lock); | 88 | spin_lock_init(&bat_priv->tt_ghash_lock); |
89 | spin_lock_init(&bat_priv->tt_changes_list_lock); | 89 | spin_lock_init(&bat_priv->tt_changes_list_lock); |
90 | spin_lock_init(&bat_priv->tt_req_list_lock); | 90 | spin_lock_init(&bat_priv->tt_req_list_lock); |
91 | spin_lock_init(&bat_priv->tt_roam_list_lock); | ||
91 | spin_lock_init(&bat_priv->tt_buff_lock); | 92 | spin_lock_init(&bat_priv->tt_buff_lock); |
92 | spin_lock_init(&bat_priv->gw_list_lock); | 93 | spin_lock_init(&bat_priv->gw_list_lock); |
93 | spin_lock_init(&bat_priv->vis_hash_lock); | 94 | spin_lock_init(&bat_priv->vis_hash_lock); |
@@ -101,6 +102,7 @@ int mesh_init(struct net_device *soft_iface) | |||
101 | INIT_HLIST_HEAD(&bat_priv->softif_neigh_vids); | 102 | INIT_HLIST_HEAD(&bat_priv->softif_neigh_vids); |
102 | INIT_LIST_HEAD(&bat_priv->tt_changes_list); | 103 | INIT_LIST_HEAD(&bat_priv->tt_changes_list); |
103 | INIT_LIST_HEAD(&bat_priv->tt_req_list); | 104 | INIT_LIST_HEAD(&bat_priv->tt_req_list); |
105 | INIT_LIST_HEAD(&bat_priv->tt_roam_list); | ||
104 | 106 | ||
105 | if (originator_init(bat_priv) < 1) | 107 | if (originator_init(bat_priv) < 1) |
106 | goto err; | 108 | goto err; |
diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h index 6f53a1de778c..8eae05e4dc1b 100644 --- a/net/batman-adv/main.h +++ b/net/batman-adv/main.h | |||
@@ -42,7 +42,7 @@ | |||
42 | * -> TODO: check influence on TQ_LOCAL_WINDOW_SIZE */ | 42 | * -> TODO: check influence on TQ_LOCAL_WINDOW_SIZE */ |
43 | #define PURGE_TIMEOUT 200 | 43 | #define PURGE_TIMEOUT 200 |
44 | #define TT_LOCAL_TIMEOUT 3600 /* in seconds */ | 44 | #define TT_LOCAL_TIMEOUT 3600 /* in seconds */ |
45 | 45 | #define TT_CLIENT_ROAM_TIMEOUT 600 | |
46 | /* sliding packet range of received originator messages in squence numbers | 46 | /* sliding packet range of received originator messages in squence numbers |
47 | * (should be a multiple of our word size) */ | 47 | * (should be a multiple of our word size) */ |
48 | #define TQ_LOCAL_WINDOW_SIZE 64 | 48 | #define TQ_LOCAL_WINDOW_SIZE 64 |
@@ -55,6 +55,10 @@ | |||
55 | 55 | ||
56 | #define TT_OGM_APPEND_MAX 3 /* number of OGMs sent with the last tt diff */ | 56 | #define TT_OGM_APPEND_MAX 3 /* number of OGMs sent with the last tt diff */ |
57 | 57 | ||
58 | #define ROAMING_MAX_TIME 20 /* Time in which a client can roam at most | ||
59 | * ROAMING_MAX_COUNT times */ | ||
60 | #define ROAMING_MAX_COUNT 5 | ||
61 | |||
58 | #define NO_FLAGS 0 | 62 | #define NO_FLAGS 0 |
59 | 63 | ||
60 | #define NUM_WORDS (TQ_LOCAL_WINDOW_SIZE / WORD_BIT_SIZE) | 64 | #define NUM_WORDS (TQ_LOCAL_WINDOW_SIZE / WORD_BIT_SIZE) |
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c index 25e7e50eef25..338b3c597e4a 100644 --- a/net/batman-adv/originator.c +++ b/net/batman-adv/originator.c | |||
@@ -219,6 +219,7 @@ struct orig_node *get_orig_node(struct bat_priv *bat_priv, const uint8_t *addr) | |||
219 | /* extra reference for return */ | 219 | /* extra reference for return */ |
220 | atomic_set(&orig_node->refcount, 2); | 220 | atomic_set(&orig_node->refcount, 2); |
221 | 221 | ||
222 | orig_node->tt_poss_change = false; | ||
222 | orig_node->bat_priv = bat_priv; | 223 | orig_node->bat_priv = bat_priv; |
223 | memcpy(orig_node->orig, addr, ETH_ALEN); | 224 | memcpy(orig_node->orig, addr, ETH_ALEN); |
224 | orig_node->router = NULL; | 225 | orig_node->router = NULL; |
diff --git a/net/batman-adv/packet.h b/net/batman-adv/packet.h index 407dd2e84aff..c5f081dfc6d1 100644 --- a/net/batman-adv/packet.h +++ b/net/batman-adv/packet.h | |||
@@ -31,7 +31,8 @@ enum bat_packettype { | |||
31 | BAT_BCAST = 0x04, | 31 | BAT_BCAST = 0x04, |
32 | BAT_VIS = 0x05, | 32 | BAT_VIS = 0x05, |
33 | BAT_UNICAST_FRAG = 0x06, | 33 | BAT_UNICAST_FRAG = 0x06, |
34 | BAT_TT_QUERY = 0x07 | 34 | BAT_TT_QUERY = 0x07, |
35 | BAT_ROAM_ADV = 0x08 | ||
35 | }; | 36 | }; |
36 | 37 | ||
37 | /* this file is included by batctl which needs these defines */ | 38 | /* this file is included by batctl which needs these defines */ |
@@ -194,6 +195,16 @@ struct tt_query_packet { | |||
194 | uint16_t tt_data; | 195 | uint16_t tt_data; |
195 | } __packed; | 196 | } __packed; |
196 | 197 | ||
198 | struct roam_adv_packet { | ||
199 | uint8_t packet_type; | ||
200 | uint8_t version; | ||
201 | uint8_t ttl; | ||
202 | uint8_t reserved; | ||
203 | uint8_t dst[ETH_ALEN]; | ||
204 | uint8_t src[ETH_ALEN]; | ||
205 | uint8_t client[ETH_ALEN]; | ||
206 | } __packed; | ||
207 | |||
197 | struct tt_change { | 208 | struct tt_change { |
198 | uint8_t flags; | 209 | uint8_t flags; |
199 | uint8_t addr[ETH_ALEN]; | 210 | uint8_t addr[ETH_ALEN]; |
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 | ||
1258 | int 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); | ||
1301 | out: | ||
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) { |
diff --git a/net/batman-adv/routing.h b/net/batman-adv/routing.h index e77d46440d2d..fb14e9579b19 100644 --- a/net/batman-adv/routing.h +++ b/net/batman-adv/routing.h | |||
@@ -37,6 +37,7 @@ int recv_bcast_packet(struct sk_buff *skb, struct hard_iface *recv_if); | |||
37 | int recv_vis_packet(struct sk_buff *skb, struct hard_iface *recv_if); | 37 | int recv_vis_packet(struct sk_buff *skb, struct hard_iface *recv_if); |
38 | int recv_bat_packet(struct sk_buff *skb, struct hard_iface *recv_if); | 38 | int recv_bat_packet(struct sk_buff *skb, struct hard_iface *recv_if); |
39 | int recv_tt_query(struct sk_buff *skb, struct hard_iface *recv_if); | 39 | int recv_tt_query(struct sk_buff *skb, struct hard_iface *recv_if); |
40 | int recv_roam_adv(struct sk_buff *skb, struct hard_iface *recv_if); | ||
40 | struct neigh_node *find_router(struct bat_priv *bat_priv, | 41 | struct neigh_node *find_router(struct bat_priv *bat_priv, |
41 | struct orig_node *orig_node, | 42 | struct orig_node *orig_node, |
42 | const struct hard_iface *recv_if); | 43 | const struct hard_iface *recv_if); |
diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c index 6b1407570e44..7a2f0823f1c2 100644 --- a/net/batman-adv/send.c +++ b/net/batman-adv/send.c | |||
@@ -303,6 +303,7 @@ void schedule_own_packet(struct hard_iface *hard_iface) | |||
303 | prepare_packet_buffer(bat_priv, hard_iface); | 303 | prepare_packet_buffer(bat_priv, hard_iface); |
304 | /* Increment the TTVN only once per OGM interval */ | 304 | /* Increment the TTVN only once per OGM interval */ |
305 | atomic_inc(&bat_priv->ttvn); | 305 | atomic_inc(&bat_priv->ttvn); |
306 | bat_priv->tt_poss_change = false; | ||
306 | } | 307 | } |
307 | 308 | ||
308 | /* if the changes have been sent enough times */ | 309 | /* if the changes have been sent enough times */ |
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index c288d937a154..3371ece680a2 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c | |||
@@ -534,7 +534,7 @@ static int interface_set_mac_addr(struct net_device *dev, void *p) | |||
534 | /* only modify transtable if it has been initialised before */ | 534 | /* only modify transtable if it has been initialised before */ |
535 | if (atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE) { | 535 | if (atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE) { |
536 | tt_local_remove(bat_priv, dev->dev_addr, | 536 | tt_local_remove(bat_priv, dev->dev_addr, |
537 | "mac address changed"); | 537 | "mac address changed", false); |
538 | tt_local_add(dev, addr->sa_data); | 538 | tt_local_add(dev, addr->sa_data); |
539 | } | 539 | } |
540 | 540 | ||
@@ -836,6 +836,7 @@ struct net_device *softif_create(const char *name) | |||
836 | 836 | ||
837 | bat_priv->tt_buff = NULL; | 837 | bat_priv->tt_buff = NULL; |
838 | bat_priv->tt_buff_len = 0; | 838 | bat_priv->tt_buff_len = 0; |
839 | bat_priv->tt_poss_change = false; | ||
839 | 840 | ||
840 | bat_priv->primary_if = NULL; | 841 | bat_priv->primary_if = NULL; |
841 | bat_priv->num_ifaces = 0; | 842 | bat_priv->num_ifaces = 0; |
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index 597cd1a43058..d516d8591cfc 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c | |||
@@ -126,7 +126,7 @@ static bool is_out_of_time(unsigned long starting_time, unsigned long timeout) | |||
126 | } | 126 | } |
127 | 127 | ||
128 | static void tt_local_event(struct bat_priv *bat_priv, uint8_t op, | 128 | static void tt_local_event(struct bat_priv *bat_priv, uint8_t op, |
129 | const uint8_t *addr) | 129 | const uint8_t *addr, uint8_t roaming) |
130 | { | 130 | { |
131 | struct tt_change_node *tt_change_node; | 131 | struct tt_change_node *tt_change_node; |
132 | 132 | ||
@@ -136,6 +136,9 @@ static void tt_local_event(struct bat_priv *bat_priv, uint8_t op, | |||
136 | return; | 136 | return; |
137 | 137 | ||
138 | tt_change_node->change.flags = op; | 138 | tt_change_node->change.flags = op; |
139 | if (roaming) | ||
140 | tt_change_node->change.flags |= TT_CLIENT_ROAM; | ||
141 | |||
139 | memcpy(tt_change_node->change.addr, addr, ETH_ALEN); | 142 | memcpy(tt_change_node->change.addr, addr, ETH_ALEN); |
140 | 143 | ||
141 | spin_lock_bh(&bat_priv->tt_changes_list_lock); | 144 | spin_lock_bh(&bat_priv->tt_changes_list_lock); |
@@ -170,6 +173,7 @@ void tt_local_add(struct net_device *soft_iface, const uint8_t *addr) | |||
170 | struct bat_priv *bat_priv = netdev_priv(soft_iface); | 173 | struct bat_priv *bat_priv = netdev_priv(soft_iface); |
171 | struct tt_local_entry *tt_local_entry; | 174 | struct tt_local_entry *tt_local_entry; |
172 | struct tt_global_entry *tt_global_entry; | 175 | struct tt_global_entry *tt_global_entry; |
176 | uint8_t roam_addr[ETH_ALEN]; | ||
173 | 177 | ||
174 | spin_lock_bh(&bat_priv->tt_lhash_lock); | 178 | spin_lock_bh(&bat_priv->tt_lhash_lock); |
175 | tt_local_entry = tt_local_hash_find(bat_priv, addr); | 179 | tt_local_entry = tt_local_hash_find(bat_priv, addr); |
@@ -183,7 +187,7 @@ void tt_local_add(struct net_device *soft_iface, const uint8_t *addr) | |||
183 | if (!tt_local_entry) | 187 | if (!tt_local_entry) |
184 | goto unlock; | 188 | goto unlock; |
185 | 189 | ||
186 | tt_local_event(bat_priv, NO_FLAGS, addr); | 190 | tt_local_event(bat_priv, NO_FLAGS, addr, false); |
187 | 191 | ||
188 | bat_dbg(DBG_TT, bat_priv, | 192 | bat_dbg(DBG_TT, bat_priv, |
189 | "Creating new local tt entry: %pM (ttvn: %d)\n", addr, | 193 | "Creating new local tt entry: %pM (ttvn: %d)\n", addr, |
@@ -208,11 +212,19 @@ void tt_local_add(struct net_device *soft_iface, const uint8_t *addr) | |||
208 | 212 | ||
209 | tt_global_entry = tt_global_hash_find(bat_priv, addr); | 213 | tt_global_entry = tt_global_hash_find(bat_priv, addr); |
210 | 214 | ||
211 | if (tt_global_entry) | 215 | /* Check whether it is a roaming! */ |
216 | if (tt_global_entry) { | ||
217 | memcpy(roam_addr, tt_global_entry->addr, ETH_ALEN); | ||
218 | /* This node is probably going to update its tt table */ | ||
219 | tt_global_entry->orig_node->tt_poss_change = true; | ||
212 | _tt_global_del(bat_priv, tt_global_entry, | 220 | _tt_global_del(bat_priv, tt_global_entry, |
213 | "local tt received"); | 221 | "local tt received"); |
222 | spin_unlock_bh(&bat_priv->tt_ghash_lock); | ||
223 | send_roam_adv(bat_priv, tt_global_entry->addr, | ||
224 | tt_global_entry->orig_node); | ||
225 | } else | ||
226 | spin_unlock_bh(&bat_priv->tt_ghash_lock); | ||
214 | 227 | ||
215 | spin_unlock_bh(&bat_priv->tt_ghash_lock); | ||
216 | return; | 228 | return; |
217 | unlock: | 229 | unlock: |
218 | spin_unlock_bh(&bat_priv->tt_lhash_lock); | 230 | spin_unlock_bh(&bat_priv->tt_lhash_lock); |
@@ -367,7 +379,7 @@ static void tt_local_del(struct bat_priv *bat_priv, | |||
367 | } | 379 | } |
368 | 380 | ||
369 | void tt_local_remove(struct bat_priv *bat_priv, const uint8_t *addr, | 381 | void tt_local_remove(struct bat_priv *bat_priv, const uint8_t *addr, |
370 | const char *message) | 382 | const char *message, bool roaming) |
371 | { | 383 | { |
372 | struct tt_local_entry *tt_local_entry; | 384 | struct tt_local_entry *tt_local_entry; |
373 | 385 | ||
@@ -375,7 +387,8 @@ void tt_local_remove(struct bat_priv *bat_priv, const uint8_t *addr, | |||
375 | tt_local_entry = tt_local_hash_find(bat_priv, addr); | 387 | tt_local_entry = tt_local_hash_find(bat_priv, addr); |
376 | 388 | ||
377 | if (tt_local_entry) { | 389 | if (tt_local_entry) { |
378 | tt_local_event(bat_priv, TT_CHANGE_DEL, tt_local_entry->addr); | 390 | tt_local_event(bat_priv, TT_CHANGE_DEL, tt_local_entry->addr, |
391 | roaming); | ||
379 | tt_local_del(bat_priv, tt_local_entry, message); | 392 | tt_local_del(bat_priv, tt_local_entry, message); |
380 | } | 393 | } |
381 | spin_unlock_bh(&bat_priv->tt_lhash_lock); | 394 | spin_unlock_bh(&bat_priv->tt_lhash_lock); |
@@ -404,7 +417,7 @@ static void tt_local_purge(struct bat_priv *bat_priv) | |||
404 | continue; | 417 | continue; |
405 | 418 | ||
406 | tt_local_event(bat_priv, TT_CHANGE_DEL, | 419 | tt_local_event(bat_priv, TT_CHANGE_DEL, |
407 | tt_local_entry->addr); | 420 | tt_local_entry->addr, false); |
408 | tt_local_del(bat_priv, tt_local_entry, | 421 | tt_local_del(bat_priv, tt_local_entry, |
409 | "address timed out"); | 422 | "address timed out"); |
410 | } | 423 | } |
@@ -476,7 +489,7 @@ static void tt_changes_list_free(struct bat_priv *bat_priv) | |||
476 | 489 | ||
477 | /* caller must hold orig_node refcount */ | 490 | /* caller must hold orig_node refcount */ |
478 | int tt_global_add(struct bat_priv *bat_priv, struct orig_node *orig_node, | 491 | int tt_global_add(struct bat_priv *bat_priv, struct orig_node *orig_node, |
479 | const unsigned char *tt_addr, uint8_t ttvn) | 492 | const unsigned char *tt_addr, uint8_t ttvn, bool roaming) |
480 | { | 493 | { |
481 | struct tt_global_entry *tt_global_entry; | 494 | struct tt_global_entry *tt_global_entry; |
482 | struct tt_local_entry *tt_local_entry; | 495 | struct tt_local_entry *tt_local_entry; |
@@ -496,6 +509,8 @@ int tt_global_add(struct bat_priv *bat_priv, struct orig_node *orig_node, | |||
496 | atomic_inc(&orig_node->refcount); | 509 | atomic_inc(&orig_node->refcount); |
497 | tt_global_entry->orig_node = orig_node; | 510 | tt_global_entry->orig_node = orig_node; |
498 | tt_global_entry->ttvn = ttvn; | 511 | tt_global_entry->ttvn = ttvn; |
512 | tt_global_entry->flags = NO_FLAGS; | ||
513 | tt_global_entry->roam_at = 0; | ||
499 | atomic_inc(&orig_node->tt_size); | 514 | atomic_inc(&orig_node->tt_size); |
500 | hash_add(bat_priv->tt_global_hash, compare_gtt, | 515 | hash_add(bat_priv->tt_global_hash, compare_gtt, |
501 | choose_orig, tt_global_entry, | 516 | choose_orig, tt_global_entry, |
@@ -506,10 +521,12 @@ int tt_global_add(struct bat_priv *bat_priv, struct orig_node *orig_node, | |||
506 | orig_node_tmp = tt_global_entry->orig_node; | 521 | orig_node_tmp = tt_global_entry->orig_node; |
507 | atomic_inc(&orig_node->refcount); | 522 | atomic_inc(&orig_node->refcount); |
508 | tt_global_entry->orig_node = orig_node; | 523 | tt_global_entry->orig_node = orig_node; |
509 | tt_global_entry->ttvn = ttvn; | ||
510 | orig_node_free_ref(orig_node_tmp); | 524 | orig_node_free_ref(orig_node_tmp); |
511 | atomic_inc(&orig_node->tt_size); | 525 | atomic_inc(&orig_node->tt_size); |
512 | } | 526 | } |
527 | tt_global_entry->ttvn = ttvn; | ||
528 | tt_global_entry->flags = NO_FLAGS; | ||
529 | tt_global_entry->roam_at = 0; | ||
513 | } | 530 | } |
514 | 531 | ||
515 | spin_unlock_bh(&bat_priv->tt_ghash_lock); | 532 | spin_unlock_bh(&bat_priv->tt_ghash_lock); |
@@ -523,8 +540,9 @@ int tt_global_add(struct bat_priv *bat_priv, struct orig_node *orig_node, | |||
523 | tt_local_entry = tt_local_hash_find(bat_priv, tt_addr); | 540 | tt_local_entry = tt_local_hash_find(bat_priv, tt_addr); |
524 | 541 | ||
525 | if (tt_local_entry) | 542 | if (tt_local_entry) |
526 | tt_local_del(bat_priv, tt_local_entry, | 543 | tt_local_remove(bat_priv, tt_global_entry->addr, |
527 | "global tt received"); | 544 | "global tt received", roaming); |
545 | |||
528 | spin_unlock_bh(&bat_priv->tt_lhash_lock); | 546 | spin_unlock_bh(&bat_priv->tt_lhash_lock); |
529 | return 1; | 547 | return 1; |
530 | unlock: | 548 | unlock: |
@@ -637,7 +655,7 @@ static void _tt_global_del(struct bat_priv *bat_priv, | |||
637 | 655 | ||
638 | void tt_global_del(struct bat_priv *bat_priv, | 656 | void tt_global_del(struct bat_priv *bat_priv, |
639 | struct orig_node *orig_node, const unsigned char *addr, | 657 | struct orig_node *orig_node, const unsigned char *addr, |
640 | const char *message) | 658 | const char *message, bool roaming) |
641 | { | 659 | { |
642 | struct tt_global_entry *tt_global_entry; | 660 | struct tt_global_entry *tt_global_entry; |
643 | 661 | ||
@@ -645,9 +663,15 @@ void tt_global_del(struct bat_priv *bat_priv, | |||
645 | tt_global_entry = tt_global_hash_find(bat_priv, addr); | 663 | tt_global_entry = tt_global_hash_find(bat_priv, addr); |
646 | 664 | ||
647 | if (tt_global_entry && tt_global_entry->orig_node == orig_node) { | 665 | if (tt_global_entry && tt_global_entry->orig_node == orig_node) { |
666 | if (roaming) { | ||
667 | tt_global_entry->flags |= TT_CLIENT_ROAM; | ||
668 | tt_global_entry->roam_at = jiffies; | ||
669 | goto out; | ||
670 | } | ||
648 | atomic_dec(&orig_node->tt_size); | 671 | atomic_dec(&orig_node->tt_size); |
649 | _tt_global_del(bat_priv, tt_global_entry, message); | 672 | _tt_global_del(bat_priv, tt_global_entry, message); |
650 | } | 673 | } |
674 | out: | ||
651 | spin_unlock_bh(&bat_priv->tt_ghash_lock); | 675 | spin_unlock_bh(&bat_priv->tt_ghash_lock); |
652 | } | 676 | } |
653 | 677 | ||
@@ -685,6 +709,35 @@ static void tt_global_entry_free(struct hlist_node *node, void *arg) | |||
685 | kfree(data); | 709 | kfree(data); |
686 | } | 710 | } |
687 | 711 | ||
712 | static void tt_global_roam_purge(struct bat_priv *bat_priv) | ||
713 | { | ||
714 | struct hashtable_t *hash = bat_priv->tt_global_hash; | ||
715 | struct tt_global_entry *tt_global_entry; | ||
716 | struct hlist_node *node, *node_tmp; | ||
717 | struct hlist_head *head; | ||
718 | int i; | ||
719 | |||
720 | spin_lock_bh(&bat_priv->tt_ghash_lock); | ||
721 | |||
722 | for (i = 0; i < hash->size; i++) { | ||
723 | head = &hash->table[i]; | ||
724 | |||
725 | hlist_for_each_entry_safe(tt_global_entry, node, node_tmp, | ||
726 | head, hash_entry) { | ||
727 | if (!(tt_global_entry->flags & TT_CLIENT_ROAM)) | ||
728 | continue; | ||
729 | if (!is_out_of_time(tt_global_entry->roam_at, | ||
730 | TT_CLIENT_ROAM_TIMEOUT * 1000)) | ||
731 | continue; | ||
732 | |||
733 | _tt_global_del(bat_priv, tt_global_entry, | ||
734 | "Roaming timeout"); | ||
735 | } | ||
736 | } | ||
737 | |||
738 | spin_unlock_bh(&bat_priv->tt_ghash_lock); | ||
739 | } | ||
740 | |||
688 | static void tt_global_table_free(struct bat_priv *bat_priv) | 741 | static void tt_global_table_free(struct bat_priv *bat_priv) |
689 | { | 742 | { |
690 | if (!bat_priv->tt_global_hash) | 743 | if (!bat_priv->tt_global_hash) |
@@ -734,6 +787,12 @@ uint16_t tt_global_crc(struct bat_priv *bat_priv, struct orig_node *orig_node) | |||
734 | head, hash_entry) { | 787 | head, hash_entry) { |
735 | if (compare_eth(tt_global_entry->orig_node, | 788 | if (compare_eth(tt_global_entry->orig_node, |
736 | orig_node)) { | 789 | orig_node)) { |
790 | /* Roaming clients are in the global table for | ||
791 | * consistency only. They don't have to be | ||
792 | * taken into account while computing the | ||
793 | * global crc */ | ||
794 | if (tt_global_entry->flags & TT_CLIENT_ROAM) | ||
795 | continue; | ||
737 | total_one = 0; | 796 | total_one = 0; |
738 | for (j = 0; j < ETH_ALEN; j++) | 797 | for (j = 0; j < ETH_ALEN; j++) |
739 | total_one = crc16_byte(total_one, | 798 | total_one = crc16_byte(total_one, |
@@ -858,6 +917,9 @@ static int tt_global_valid_entry(const void *entry_ptr, const void *data_ptr) | |||
858 | const struct tt_global_entry *tt_global_entry = entry_ptr; | 917 | const struct tt_global_entry *tt_global_entry = entry_ptr; |
859 | const struct orig_node *orig_node = data_ptr; | 918 | const struct orig_node *orig_node = data_ptr; |
860 | 919 | ||
920 | if (tt_global_entry->flags & TT_CLIENT_ROAM) | ||
921 | return 0; | ||
922 | |||
861 | return (tt_global_entry->orig_node == orig_node); | 923 | return (tt_global_entry->orig_node == orig_node); |
862 | } | 924 | } |
863 | 925 | ||
@@ -1251,10 +1313,11 @@ static void _tt_update_changes(struct bat_priv *bat_priv, | |||
1251 | if ((tt_change + i)->flags & TT_CHANGE_DEL) | 1313 | if ((tt_change + i)->flags & TT_CHANGE_DEL) |
1252 | tt_global_del(bat_priv, orig_node, | 1314 | tt_global_del(bat_priv, orig_node, |
1253 | (tt_change + i)->addr, | 1315 | (tt_change + i)->addr, |
1254 | "tt removed by changes"); | 1316 | "tt removed by changes", |
1317 | (tt_change + i)->flags & TT_CLIENT_ROAM); | ||
1255 | else | 1318 | else |
1256 | if (!tt_global_add(bat_priv, orig_node, | 1319 | if (!tt_global_add(bat_priv, orig_node, |
1257 | (tt_change + i)->addr, ttvn)) | 1320 | (tt_change + i)->addr, ttvn, false)) |
1258 | /* In case of problem while storing a | 1321 | /* In case of problem while storing a |
1259 | * global_entry, we stop the updating | 1322 | * global_entry, we stop the updating |
1260 | * procedure without committing the | 1323 | * procedure without committing the |
@@ -1356,6 +1419,9 @@ void handle_tt_response(struct bat_priv *bat_priv, | |||
1356 | spin_lock_bh(&bat_priv->tt_ghash_lock); | 1419 | spin_lock_bh(&bat_priv->tt_ghash_lock); |
1357 | orig_node->tt_crc = tt_global_crc(bat_priv, orig_node); | 1420 | orig_node->tt_crc = tt_global_crc(bat_priv, orig_node); |
1358 | spin_unlock_bh(&bat_priv->tt_ghash_lock); | 1421 | spin_unlock_bh(&bat_priv->tt_ghash_lock); |
1422 | /* Roaming phase is over: tables are in sync again. I can | ||
1423 | * unset the flag */ | ||
1424 | orig_node->tt_poss_change = false; | ||
1359 | out: | 1425 | out: |
1360 | if (orig_node) | 1426 | if (orig_node) |
1361 | orig_node_free_ref(orig_node); | 1427 | orig_node_free_ref(orig_node); |
@@ -1374,16 +1440,134 @@ int tt_init(struct bat_priv *bat_priv) | |||
1374 | return 1; | 1440 | return 1; |
1375 | } | 1441 | } |
1376 | 1442 | ||
1377 | void tt_free(struct bat_priv *bat_priv) | 1443 | static void tt_roam_list_free(struct bat_priv *bat_priv) |
1378 | { | 1444 | { |
1379 | cancel_delayed_work_sync(&bat_priv->tt_work); | 1445 | struct tt_roam_node *node, *safe; |
1380 | 1446 | ||
1381 | tt_local_table_free(bat_priv); | 1447 | spin_lock_bh(&bat_priv->tt_roam_list_lock); |
1382 | tt_global_table_free(bat_priv); | ||
1383 | tt_req_list_free(bat_priv); | ||
1384 | tt_changes_list_free(bat_priv); | ||
1385 | 1448 | ||
1386 | kfree(bat_priv->tt_buff); | 1449 | list_for_each_entry_safe(node, safe, &bat_priv->tt_roam_list, list) { |
1450 | list_del(&node->list); | ||
1451 | kfree(node); | ||
1452 | } | ||
1453 | |||
1454 | spin_unlock_bh(&bat_priv->tt_roam_list_lock); | ||
1455 | } | ||
1456 | |||
1457 | static void tt_roam_purge(struct bat_priv *bat_priv) | ||
1458 | { | ||
1459 | struct tt_roam_node *node, *safe; | ||
1460 | |||
1461 | spin_lock_bh(&bat_priv->tt_roam_list_lock); | ||
1462 | list_for_each_entry_safe(node, safe, &bat_priv->tt_roam_list, list) { | ||
1463 | if (!is_out_of_time(node->first_time, | ||
1464 | ROAMING_MAX_TIME * 1000)) | ||
1465 | continue; | ||
1466 | |||
1467 | list_del(&node->list); | ||
1468 | kfree(node); | ||
1469 | } | ||
1470 | spin_unlock_bh(&bat_priv->tt_roam_list_lock); | ||
1471 | } | ||
1472 | |||
1473 | /* This function checks whether the client already reached the | ||
1474 | * maximum number of possible roaming phases. In this case the ROAMING_ADV | ||
1475 | * will not be sent. | ||
1476 | * | ||
1477 | * returns true if the ROAMING_ADV can be sent, false otherwise */ | ||
1478 | static bool tt_check_roam_count(struct bat_priv *bat_priv, | ||
1479 | uint8_t *client) | ||
1480 | { | ||
1481 | struct tt_roam_node *tt_roam_node; | ||
1482 | bool ret = false; | ||
1483 | |||
1484 | spin_lock_bh(&bat_priv->tt_roam_list_lock); | ||
1485 | /* The new tt_req will be issued only if I'm not waiting for a | ||
1486 | * reply from the same orig_node yet */ | ||
1487 | list_for_each_entry(tt_roam_node, &bat_priv->tt_roam_list, list) { | ||
1488 | if (!compare_eth(tt_roam_node->addr, client)) | ||
1489 | continue; | ||
1490 | |||
1491 | if (is_out_of_time(tt_roam_node->first_time, | ||
1492 | ROAMING_MAX_TIME * 1000)) | ||
1493 | continue; | ||
1494 | |||
1495 | if (!atomic_dec_not_zero(&tt_roam_node->counter)) | ||
1496 | /* Sorry, you roamed too many times! */ | ||
1497 | goto unlock; | ||
1498 | ret = true; | ||
1499 | break; | ||
1500 | } | ||
1501 | |||
1502 | if (!ret) { | ||
1503 | tt_roam_node = kmalloc(sizeof(*tt_roam_node), GFP_ATOMIC); | ||
1504 | if (!tt_roam_node) | ||
1505 | goto unlock; | ||
1506 | |||
1507 | tt_roam_node->first_time = jiffies; | ||
1508 | atomic_set(&tt_roam_node->counter, ROAMING_MAX_COUNT - 1); | ||
1509 | memcpy(tt_roam_node->addr, client, ETH_ALEN); | ||
1510 | |||
1511 | list_add(&tt_roam_node->list, &bat_priv->tt_roam_list); | ||
1512 | ret = true; | ||
1513 | } | ||
1514 | |||
1515 | unlock: | ||
1516 | spin_unlock_bh(&bat_priv->tt_roam_list_lock); | ||
1517 | return ret; | ||
1518 | } | ||
1519 | |||
1520 | void send_roam_adv(struct bat_priv *bat_priv, uint8_t *client, | ||
1521 | struct orig_node *orig_node) | ||
1522 | { | ||
1523 | struct neigh_node *neigh_node = NULL; | ||
1524 | struct sk_buff *skb = NULL; | ||
1525 | struct roam_adv_packet *roam_adv_packet; | ||
1526 | int ret = 1; | ||
1527 | struct hard_iface *primary_if; | ||
1528 | |||
1529 | /* before going on we have to check whether the client has | ||
1530 | * already roamed to us too many times */ | ||
1531 | if (!tt_check_roam_count(bat_priv, client)) | ||
1532 | goto out; | ||
1533 | |||
1534 | skb = dev_alloc_skb(sizeof(struct roam_adv_packet) + ETH_HLEN); | ||
1535 | if (!skb) | ||
1536 | goto out; | ||
1537 | |||
1538 | skb_reserve(skb, ETH_HLEN); | ||
1539 | |||
1540 | roam_adv_packet = (struct roam_adv_packet *)skb_put(skb, | ||
1541 | sizeof(struct roam_adv_packet)); | ||
1542 | |||
1543 | roam_adv_packet->packet_type = BAT_ROAM_ADV; | ||
1544 | roam_adv_packet->version = COMPAT_VERSION; | ||
1545 | roam_adv_packet->ttl = TTL; | ||
1546 | primary_if = primary_if_get_selected(bat_priv); | ||
1547 | if (!primary_if) | ||
1548 | goto out; | ||
1549 | memcpy(roam_adv_packet->src, primary_if->net_dev->dev_addr, ETH_ALEN); | ||
1550 | hardif_free_ref(primary_if); | ||
1551 | memcpy(roam_adv_packet->dst, orig_node->orig, ETH_ALEN); | ||
1552 | memcpy(roam_adv_packet->client, client, ETH_ALEN); | ||
1553 | |||
1554 | neigh_node = orig_node_get_router(orig_node); | ||
1555 | if (!neigh_node) | ||
1556 | goto out; | ||
1557 | |||
1558 | bat_dbg(DBG_TT, bat_priv, | ||
1559 | "Sending ROAMING_ADV to %pM (client %pM) via %pM\n", | ||
1560 | orig_node->orig, client, neigh_node->addr); | ||
1561 | |||
1562 | send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); | ||
1563 | ret = 0; | ||
1564 | |||
1565 | out: | ||
1566 | if (neigh_node) | ||
1567 | neigh_node_free_ref(neigh_node); | ||
1568 | if (ret) | ||
1569 | kfree_skb(skb); | ||
1570 | return; | ||
1387 | } | 1571 | } |
1388 | 1572 | ||
1389 | static void tt_purge(struct work_struct *work) | 1573 | static void tt_purge(struct work_struct *work) |
@@ -1394,7 +1578,22 @@ static void tt_purge(struct work_struct *work) | |||
1394 | container_of(delayed_work, struct bat_priv, tt_work); | 1578 | container_of(delayed_work, struct bat_priv, tt_work); |
1395 | 1579 | ||
1396 | tt_local_purge(bat_priv); | 1580 | tt_local_purge(bat_priv); |
1581 | tt_global_roam_purge(bat_priv); | ||
1397 | tt_req_purge(bat_priv); | 1582 | tt_req_purge(bat_priv); |
1583 | tt_roam_purge(bat_priv); | ||
1398 | 1584 | ||
1399 | tt_start_timer(bat_priv); | 1585 | tt_start_timer(bat_priv); |
1400 | } | 1586 | } |
1587 | |||
1588 | void tt_free(struct bat_priv *bat_priv) | ||
1589 | { | ||
1590 | cancel_delayed_work_sync(&bat_priv->tt_work); | ||
1591 | |||
1592 | tt_local_table_free(bat_priv); | ||
1593 | tt_global_table_free(bat_priv); | ||
1594 | tt_req_list_free(bat_priv); | ||
1595 | tt_changes_list_free(bat_priv); | ||
1596 | tt_roam_list_free(bat_priv); | ||
1597 | |||
1598 | kfree(bat_priv->tt_buff); | ||
1599 | } | ||
diff --git a/net/batman-adv/translation-table.h b/net/batman-adv/translation-table.h index 51f7e3060f6f..1cd2d39529fe 100644 --- a/net/batman-adv/translation-table.h +++ b/net/batman-adv/translation-table.h | |||
@@ -28,20 +28,20 @@ int tt_changes_fill_buffer(struct bat_priv *bat_priv, | |||
28 | int tt_init(struct bat_priv *bat_priv); | 28 | int tt_init(struct bat_priv *bat_priv); |
29 | void tt_local_add(struct net_device *soft_iface, const uint8_t *addr); | 29 | void tt_local_add(struct net_device *soft_iface, const uint8_t *addr); |
30 | void tt_local_remove(struct bat_priv *bat_priv, | 30 | void tt_local_remove(struct bat_priv *bat_priv, |
31 | const uint8_t *addr, const char *message); | 31 | const uint8_t *addr, const char *message, bool roaming); |
32 | int tt_local_seq_print_text(struct seq_file *seq, void *offset); | 32 | int tt_local_seq_print_text(struct seq_file *seq, void *offset); |
33 | void tt_global_add_orig(struct bat_priv *bat_priv, | 33 | void tt_global_add_orig(struct bat_priv *bat_priv, |
34 | struct orig_node *orig_node, | 34 | struct orig_node *orig_node, |
35 | const unsigned char *tt_buff, int tt_buff_len); | 35 | const unsigned char *tt_buff, int tt_buff_len); |
36 | int tt_global_add(struct bat_priv *bat_priv, | 36 | int tt_global_add(struct bat_priv *bat_priv, |
37 | struct orig_node *orig_node, const unsigned char *addr, | 37 | struct orig_node *orig_node, const unsigned char *addr, |
38 | uint8_t ttvn); | 38 | uint8_t ttvn, bool roaming); |
39 | int tt_global_seq_print_text(struct seq_file *seq, void *offset); | 39 | int tt_global_seq_print_text(struct seq_file *seq, void *offset); |
40 | void tt_global_del_orig(struct bat_priv *bat_priv, | 40 | void tt_global_del_orig(struct bat_priv *bat_priv, |
41 | struct orig_node *orig_node, const char *message); | 41 | struct orig_node *orig_node, const char *message); |
42 | void tt_global_del(struct bat_priv *bat_priv, | 42 | void tt_global_del(struct bat_priv *bat_priv, |
43 | struct orig_node *orig_node, const unsigned char *addr, | 43 | struct orig_node *orig_node, const unsigned char *addr, |
44 | const char *message); | 44 | const char *message, bool roaming); |
45 | struct orig_node *transtable_search(struct bat_priv *bat_priv, | 45 | struct orig_node *transtable_search(struct bat_priv *bat_priv, |
46 | const uint8_t *addr); | 46 | const uint8_t *addr); |
47 | void tt_save_orig_buffer(struct bat_priv *bat_priv, struct orig_node *orig_node, | 47 | void tt_save_orig_buffer(struct bat_priv *bat_priv, struct orig_node *orig_node, |
@@ -60,5 +60,7 @@ void tt_update_changes(struct bat_priv *bat_priv, struct orig_node *orig_node, | |||
60 | bool is_my_client(struct bat_priv *bat_priv, const uint8_t *addr); | 60 | bool is_my_client(struct bat_priv *bat_priv, const uint8_t *addr); |
61 | void handle_tt_response(struct bat_priv *bat_priv, | 61 | void handle_tt_response(struct bat_priv *bat_priv, |
62 | struct tt_query_packet *tt_response); | 62 | struct tt_query_packet *tt_response); |
63 | void send_roam_adv(struct bat_priv *bat_priv, uint8_t *client, | ||
64 | struct orig_node *orig_node); | ||
63 | 65 | ||
64 | #endif /* _NET_BATMAN_ADV_TRANSLATION_TABLE_H_ */ | 66 | #endif /* _NET_BATMAN_ADV_TRANSLATION_TABLE_H_ */ |
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index 3b642a9e086e..9c84fa9f0968 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h | |||
@@ -81,6 +81,12 @@ struct orig_node { | |||
81 | int16_t tt_buff_len; | 81 | int16_t tt_buff_len; |
82 | spinlock_t tt_buff_lock; /* protects tt_buff */ | 82 | spinlock_t tt_buff_lock; /* protects tt_buff */ |
83 | atomic_t tt_size; | 83 | atomic_t tt_size; |
84 | /* The tt_poss_change flag is used to detect an ongoing roaming phase. | ||
85 | * If true, then I sent a Roaming_adv to this orig_node and I have to | ||
86 | * inspect every packet directed to it to check whether it is still | ||
87 | * the true destination or not. This flag will be reset to false as | ||
88 | * soon as I receive a new TTVN from this orig_node */ | ||
89 | bool tt_poss_change; | ||
84 | uint32_t last_real_seqno; | 90 | uint32_t last_real_seqno; |
85 | uint8_t last_ttl; | 91 | uint8_t last_ttl; |
86 | unsigned long bcast_bits[NUM_WORDS]; | 92 | unsigned long bcast_bits[NUM_WORDS]; |
@@ -153,6 +159,12 @@ struct bat_priv { | |||
153 | atomic_t ttvn; /* tranlation table version number */ | 159 | atomic_t ttvn; /* tranlation table version number */ |
154 | atomic_t tt_ogm_append_cnt; | 160 | atomic_t tt_ogm_append_cnt; |
155 | atomic_t tt_local_changes; /* changes registered in a OGM interval */ | 161 | atomic_t tt_local_changes; /* changes registered in a OGM interval */ |
162 | /* The tt_poss_change flag is used to detect an ongoing roaming phase. | ||
163 | * If true, then I received a Roaming_adv and I have to inspect every | ||
164 | * packet directed to me to check whether I am still the true | ||
165 | * destination or not. This flag will be reset to false as soon as I | ||
166 | * increase my TTVN */ | ||
167 | bool tt_poss_change; | ||
156 | char num_ifaces; | 168 | char num_ifaces; |
157 | struct debug_log *debug_log; | 169 | struct debug_log *debug_log; |
158 | struct kobject *mesh_obj; | 170 | struct kobject *mesh_obj; |
@@ -167,6 +179,7 @@ struct bat_priv { | |||
167 | struct hashtable_t *tt_local_hash; | 179 | struct hashtable_t *tt_local_hash; |
168 | struct hashtable_t *tt_global_hash; | 180 | struct hashtable_t *tt_global_hash; |
169 | struct list_head tt_req_list; /* list of pending tt_requests */ | 181 | struct list_head tt_req_list; /* list of pending tt_requests */ |
182 | struct list_head tt_roam_list; | ||
170 | struct hashtable_t *vis_hash; | 183 | struct hashtable_t *vis_hash; |
171 | spinlock_t forw_bat_list_lock; /* protects forw_bat_list */ | 184 | spinlock_t forw_bat_list_lock; /* protects forw_bat_list */ |
172 | spinlock_t forw_bcast_list_lock; /* protects */ | 185 | spinlock_t forw_bcast_list_lock; /* protects */ |
@@ -174,6 +187,7 @@ struct bat_priv { | |||
174 | spinlock_t tt_lhash_lock; /* protects tt_local_hash */ | 187 | spinlock_t tt_lhash_lock; /* protects tt_local_hash */ |
175 | spinlock_t tt_ghash_lock; /* protects tt_global_hash */ | 188 | spinlock_t tt_ghash_lock; /* protects tt_global_hash */ |
176 | spinlock_t tt_req_list_lock; /* protects tt_req_list */ | 189 | spinlock_t tt_req_list_lock; /* protects tt_req_list */ |
190 | spinlock_t tt_roam_list_lock; /* protects tt_roam_list */ | ||
177 | spinlock_t gw_list_lock; /* protects gw_list and curr_gw */ | 191 | spinlock_t gw_list_lock; /* protects gw_list and curr_gw */ |
178 | spinlock_t vis_hash_lock; /* protects vis_hash */ | 192 | spinlock_t vis_hash_lock; /* protects vis_hash */ |
179 | spinlock_t vis_list_lock; /* protects vis_info::recv_list */ | 193 | spinlock_t vis_list_lock; /* protects vis_info::recv_list */ |
@@ -219,8 +233,9 @@ struct tt_global_entry { | |||
219 | uint8_t addr[ETH_ALEN]; | 233 | uint8_t addr[ETH_ALEN]; |
220 | struct orig_node *orig_node; | 234 | struct orig_node *orig_node; |
221 | uint8_t ttvn; | 235 | uint8_t ttvn; |
222 | /* entry in the global table */ | 236 | uint8_t flags; /* only TT_GLOBAL_ROAM is used */ |
223 | struct hlist_node hash_entry; | 237 | unsigned long roam_at; /* time at which TT_GLOBAL_ROAM was set */ |
238 | struct hlist_node hash_entry; /* entry in the global table */ | ||
224 | }; | 239 | }; |
225 | 240 | ||
226 | struct tt_change_node { | 241 | struct tt_change_node { |
@@ -234,6 +249,13 @@ struct tt_req_node { | |||
234 | struct list_head list; | 249 | struct list_head list; |
235 | }; | 250 | }; |
236 | 251 | ||
252 | struct tt_roam_node { | ||
253 | uint8_t addr[ETH_ALEN]; | ||
254 | atomic_t counter; | ||
255 | unsigned long first_time; | ||
256 | struct list_head list; | ||
257 | }; | ||
258 | |||
237 | /** | 259 | /** |
238 | * forw_packet - structure for forw_list maintaining packets to be | 260 | * forw_packet - structure for forw_list maintaining packets to be |
239 | * send/forwarded | 261 | * send/forwarded |