Commit 7c1fd91da5a5eecc91674991199940c05f87cb3a
1 parent
28709878b6
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
batman-adv: substitute tt_poss_change with a per-tt_entry flag
tt_poss_change is a node-wide flag which tells whether the node is in a roaming state (a client recently moved to/away from it) in order to let it apply special re-routing rules. However this flag does not give a clear idea of the current state because it is not possible to understand *which client* is actually involved in the roaming. For this reason a better approach has been chosen: instead of using a node-wide variable, the roaming state is now given by a per-tt_entry ROAM flag which, in case of packet coming through the node, tells the node whether the real destination is in roaming state or not. With this flag change, batadv_check_unicast_ttvn() has also been rearranged in order to better fit the new re-routing logic and to be much more readable. Signed-off-by: Antonio Quartulli <ordex@autistici.org>
Showing 6 changed files with 156 additions and 75 deletions Side-by-side Diff
net/batman-adv/originator.c
... | ... | @@ -221,7 +221,6 @@ |
221 | 221 | atomic_set(&orig_node->refcount, 2); |
222 | 222 | |
223 | 223 | orig_node->tt_initialised = false; |
224 | - orig_node->tt_poss_change = false; | |
225 | 224 | orig_node->bat_priv = bat_priv; |
226 | 225 | memcpy(orig_node->orig, addr, ETH_ALEN); |
227 | 226 | batadv_dat_init_orig_node_addr(orig_node); |
net/batman-adv/routing.c
... | ... | @@ -711,12 +711,6 @@ |
711 | 711 | BATADV_TT_CLIENT_ROAM, |
712 | 712 | atomic_read(&orig_node->last_ttvn) + 1); |
713 | 713 | |
714 | - /* Roaming phase starts: I have new information but the ttvn has not | |
715 | - * been incremented yet. This flag will make me check all the incoming | |
716 | - * packets for the correct destination. | |
717 | - */ | |
718 | - bat_priv->tt.poss_change = true; | |
719 | - | |
720 | 714 | batadv_orig_node_free_ref(orig_node); |
721 | 715 | out: |
722 | 716 | /* returning NET_RX_DROP will make the caller function kfree the skb */ |
723 | 717 | |
724 | 718 | |
... | ... | @@ -899,14 +893,67 @@ |
899 | 893 | return ret; |
900 | 894 | } |
901 | 895 | |
896 | +/** | |
897 | + * batadv_reroute_unicast_packet - update the unicast header for re-routing | |
898 | + * @bat_priv: the bat priv with all the soft interface information | |
899 | + * @unicast_packet: the unicast header to be updated | |
900 | + * @dst_addr: the payload destination | |
901 | + * | |
902 | + * Search the translation table for dst_addr and update the unicast header with | |
903 | + * the new corresponding information (originator address where the destination | |
904 | + * client currently is and its known TTVN) | |
905 | + * | |
906 | + * Returns true if the packet header has been updated, false otherwise | |
907 | + */ | |
908 | +static bool | |
909 | +batadv_reroute_unicast_packet(struct batadv_priv *bat_priv, | |
910 | + struct batadv_unicast_packet *unicast_packet, | |
911 | + uint8_t *dst_addr) | |
912 | +{ | |
913 | + struct batadv_orig_node *orig_node = NULL; | |
914 | + struct batadv_hard_iface *primary_if = NULL; | |
915 | + bool ret = false; | |
916 | + uint8_t *orig_addr, orig_ttvn; | |
917 | + | |
918 | + if (batadv_is_my_client(bat_priv, dst_addr)) { | |
919 | + primary_if = batadv_primary_if_get_selected(bat_priv); | |
920 | + if (!primary_if) | |
921 | + goto out; | |
922 | + orig_addr = primary_if->net_dev->dev_addr; | |
923 | + orig_ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn); | |
924 | + } else { | |
925 | + orig_node = batadv_transtable_search(bat_priv, NULL, dst_addr); | |
926 | + if (!orig_node) | |
927 | + goto out; | |
928 | + | |
929 | + if (batadv_compare_eth(orig_node->orig, unicast_packet->dest)) | |
930 | + goto out; | |
931 | + | |
932 | + orig_addr = orig_node->orig; | |
933 | + orig_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn); | |
934 | + } | |
935 | + | |
936 | + /* update the packet header */ | |
937 | + memcpy(unicast_packet->dest, orig_addr, ETH_ALEN); | |
938 | + unicast_packet->ttvn = orig_ttvn; | |
939 | + | |
940 | + ret = true; | |
941 | +out: | |
942 | + if (primary_if) | |
943 | + batadv_hardif_free_ref(primary_if); | |
944 | + if (orig_node) | |
945 | + batadv_orig_node_free_ref(orig_node); | |
946 | + | |
947 | + return ret; | |
948 | +} | |
949 | + | |
902 | 950 | static int batadv_check_unicast_ttvn(struct batadv_priv *bat_priv, |
903 | 951 | struct sk_buff *skb) { |
904 | - uint8_t curr_ttvn; | |
952 | + uint8_t curr_ttvn, old_ttvn; | |
905 | 953 | struct batadv_orig_node *orig_node; |
906 | 954 | struct ethhdr *ethhdr; |
907 | 955 | struct batadv_hard_iface *primary_if; |
908 | 956 | struct batadv_unicast_packet *unicast_packet; |
909 | - bool tt_poss_change; | |
910 | 957 | int is_old_ttvn; |
911 | 958 | |
912 | 959 | /* check if there is enough data before accessing it */ |
913 | 960 | |
914 | 961 | |
915 | 962 | |
916 | 963 | |
917 | 964 | |
918 | 965 | |
919 | 966 | |
920 | 967 | |
921 | 968 | |
922 | 969 | |
923 | 970 | |
... | ... | @@ -918,65 +965,89 @@ |
918 | 965 | return 0; |
919 | 966 | |
920 | 967 | unicast_packet = (struct batadv_unicast_packet *)skb->data; |
968 | + ethhdr = (struct ethhdr *)(skb->data + sizeof(*unicast_packet)); | |
921 | 969 | |
922 | - if (batadv_is_my_mac(unicast_packet->dest)) { | |
923 | - tt_poss_change = bat_priv->tt.poss_change; | |
924 | - curr_ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn); | |
925 | - } else { | |
970 | + /* check if the destination client was served by this node and it is now | |
971 | + * roaming. In this case, it means that the node has got a ROAM_ADV | |
972 | + * message and that it knows the new destination in the mesh to re-route | |
973 | + * the packet to | |
974 | + */ | |
975 | + if (batadv_tt_local_client_is_roaming(bat_priv, ethhdr->h_dest)) { | |
976 | + if (batadv_reroute_unicast_packet(bat_priv, unicast_packet, | |
977 | + ethhdr->h_dest)) | |
978 | + net_ratelimited_function(batadv_dbg, BATADV_DBG_TT, | |
979 | + bat_priv, | |
980 | + "Rerouting unicast packet to %pM (dst=%pM): Local Roaming\n", | |
981 | + unicast_packet->dest, | |
982 | + ethhdr->h_dest); | |
983 | + /* at this point the mesh destination should have been | |
984 | + * substituted with the originator address found in the global | |
985 | + * table. If not, let the packet go untouched anyway because | |
986 | + * there is nothing the node can do | |
987 | + */ | |
988 | + return 1; | |
989 | + } | |
990 | + | |
991 | + /* retrieve the TTVN known by this node for the packet destination. This | |
992 | + * value is used later to check if the node which sent (or re-routed | |
993 | + * last time) the packet had an updated information or not | |
994 | + */ | |
995 | + curr_ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn); | |
996 | + if (!batadv_is_my_mac(unicast_packet->dest)) { | |
926 | 997 | orig_node = batadv_orig_hash_find(bat_priv, |
927 | 998 | unicast_packet->dest); |
928 | - | |
999 | + /* if it is not possible to find the orig_node representing the | |
1000 | + * destination, the packet can immediately be dropped as it will | |
1001 | + * not be possible to deliver it | |
1002 | + */ | |
929 | 1003 | if (!orig_node) |
930 | 1004 | return 0; |
931 | 1005 | |
932 | 1006 | curr_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn); |
933 | - tt_poss_change = orig_node->tt_poss_change; | |
934 | 1007 | batadv_orig_node_free_ref(orig_node); |
935 | 1008 | } |
936 | 1009 | |
937 | - /* Check whether I have to reroute the packet */ | |
1010 | + /* check if the TTVN contained in the packet is fresher than what the | |
1011 | + * node knows | |
1012 | + */ | |
938 | 1013 | is_old_ttvn = batadv_seq_before(unicast_packet->ttvn, curr_ttvn); |
939 | - if (is_old_ttvn || tt_poss_change) { | |
940 | - /* check if there is enough data before accessing it */ | |
941 | - if (pskb_may_pull(skb, sizeof(struct batadv_unicast_packet) + | |
942 | - ETH_HLEN) < 0) | |
943 | - return 0; | |
1014 | + if (!is_old_ttvn) | |
1015 | + return 1; | |
944 | 1016 | |
945 | - ethhdr = (struct ethhdr *)(skb->data + sizeof(*unicast_packet)); | |
1017 | + old_ttvn = unicast_packet->ttvn; | |
1018 | + /* the packet was forged based on outdated network information. Its | |
1019 | + * destination can possibly be updated and forwarded towards the new | |
1020 | + * target host | |
1021 | + */ | |
1022 | + if (batadv_reroute_unicast_packet(bat_priv, unicast_packet, | |
1023 | + ethhdr->h_dest)) { | |
1024 | + net_ratelimited_function(batadv_dbg, BATADV_DBG_TT, bat_priv, | |
1025 | + "Rerouting unicast packet to %pM (dst=%pM): TTVN mismatch old_ttvn=%u new_ttvn=%u\n", | |
1026 | + unicast_packet->dest, ethhdr->h_dest, | |
1027 | + old_ttvn, curr_ttvn); | |
1028 | + return 1; | |
1029 | + } | |
946 | 1030 | |
947 | - /* we don't have an updated route for this client, so we should | |
948 | - * not try to reroute the packet!! | |
949 | - */ | |
950 | - if (batadv_tt_global_client_is_roaming(bat_priv, | |
951 | - ethhdr->h_dest)) | |
952 | - return 1; | |
1031 | + /* the packet has not been re-routed: either the destination is | |
1032 | + * currently served by this node or there is no destination at all and | |
1033 | + * it is possible to drop the packet | |
1034 | + */ | |
1035 | + if (!batadv_is_my_client(bat_priv, ethhdr->h_dest)) | |
1036 | + return 0; | |
953 | 1037 | |
954 | - orig_node = batadv_transtable_search(bat_priv, NULL, | |
955 | - ethhdr->h_dest); | |
1038 | + /* update the header in order to let the packet be delivered to this | |
1039 | + * node's soft interface | |
1040 | + */ | |
1041 | + primary_if = batadv_primary_if_get_selected(bat_priv); | |
1042 | + if (!primary_if) | |
1043 | + return 0; | |
956 | 1044 | |
957 | - if (!orig_node) { | |
958 | - if (!batadv_is_my_client(bat_priv, ethhdr->h_dest)) | |
959 | - return 0; | |
960 | - primary_if = batadv_primary_if_get_selected(bat_priv); | |
961 | - if (!primary_if) | |
962 | - return 0; | |
963 | - memcpy(unicast_packet->dest, | |
964 | - primary_if->net_dev->dev_addr, ETH_ALEN); | |
965 | - batadv_hardif_free_ref(primary_if); | |
966 | - } else { | |
967 | - memcpy(unicast_packet->dest, orig_node->orig, | |
968 | - ETH_ALEN); | |
969 | - curr_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn); | |
970 | - batadv_orig_node_free_ref(orig_node); | |
971 | - } | |
1045 | + memcpy(unicast_packet->dest, primary_if->net_dev->dev_addr, ETH_ALEN); | |
972 | 1046 | |
973 | - net_ratelimited_function(batadv_dbg, BATADV_DBG_TT, bat_priv, | |
974 | - "TTVN mismatch (old_ttvn %u new_ttvn %u)! Rerouting unicast packet (for %pM) to %pM\n", | |
975 | - unicast_packet->ttvn, curr_ttvn, | |
976 | - ethhdr->h_dest, unicast_packet->dest); | |
1047 | + batadv_hardif_free_ref(primary_if); | |
977 | 1048 | |
978 | - unicast_packet->ttvn = curr_ttvn; | |
979 | - } | |
1049 | + unicast_packet->ttvn = curr_ttvn; | |
1050 | + | |
980 | 1051 | return 1; |
981 | 1052 | } |
982 | 1053 |
net/batman-adv/soft-interface.c
net/batman-adv/translation-table.c
... | ... | @@ -306,8 +306,6 @@ |
306 | 306 | head = &tt_global_entry->orig_list; |
307 | 307 | rcu_read_lock(); |
308 | 308 | hlist_for_each_entry_rcu(orig_entry, node, head, list) { |
309 | - orig_entry->orig_node->tt_poss_change = true; | |
310 | - | |
311 | 309 | batadv_send_roam_adv(bat_priv, |
312 | 310 | tt_global_entry->common.addr, |
313 | 311 | orig_entry->orig_node); |
314 | 312 | |
... | ... | @@ -512,8 +510,11 @@ |
512 | 510 | curr_flags = tt_local_entry->common.flags; |
513 | 511 | |
514 | 512 | flags = BATADV_TT_CLIENT_DEL; |
515 | - if (roaming) | |
513 | + if (roaming) { | |
516 | 514 | flags |= BATADV_TT_CLIENT_ROAM; |
515 | + /* mark the local client as ROAMed */ | |
516 | + tt_local_entry->common.flags |= BATADV_TT_CLIENT_ROAM; | |
517 | + } | |
517 | 518 | |
518 | 519 | batadv_tt_local_set_pending(bat_priv, tt_local_entry, flags, message); |
519 | 520 | |
... | ... | @@ -1945,7 +1946,8 @@ |
1945 | 1946 | /* Check if the client has been logically deleted (but is kept for |
1946 | 1947 | * consistency purpose) |
1947 | 1948 | */ |
1948 | - if (tt_local_entry->common.flags & BATADV_TT_CLIENT_PENDING) | |
1949 | + if ((tt_local_entry->common.flags & BATADV_TT_CLIENT_PENDING) || | |
1950 | + (tt_local_entry->common.flags & BATADV_TT_CLIENT_ROAM)) | |
1949 | 1951 | goto out; |
1950 | 1952 | ret = true; |
1951 | 1953 | out: |
... | ... | @@ -1996,10 +1998,6 @@ |
1996 | 1998 | |
1997 | 1999 | /* Recalculate the CRC for this orig_node and store it */ |
1998 | 2000 | orig_node->tt_crc = batadv_tt_global_crc(bat_priv, orig_node); |
1999 | - /* Roaming phase is over: tables are in sync again. I can | |
2000 | - * unset the flag | |
2001 | - */ | |
2002 | - orig_node->tt_poss_change = false; | |
2003 | 2001 | out: |
2004 | 2002 | if (orig_node) |
2005 | 2003 | batadv_orig_node_free_ref(orig_node); |
... | ... | @@ -2290,7 +2288,6 @@ |
2290 | 2288 | batadv_dbg(BATADV_DBG_TT, bat_priv, |
2291 | 2289 | "Local changes committed, updating to ttvn %u\n", |
2292 | 2290 | (uint8_t)atomic_read(&bat_priv->tt.vn)); |
2293 | - bat_priv->tt.poss_change = false; | |
2294 | 2291 | |
2295 | 2292 | /* reset the sending counter */ |
2296 | 2293 | atomic_set(&bat_priv->tt.ogm_append_cnt, BATADV_TT_OGM_APPEND_MAX); |
... | ... | @@ -2402,11 +2399,6 @@ |
2402 | 2399 | */ |
2403 | 2400 | if (orig_node->tt_crc != tt_crc) |
2404 | 2401 | goto request_table; |
2405 | - | |
2406 | - /* Roaming phase is over: tables are in sync again. I can | |
2407 | - * unset the flag | |
2408 | - */ | |
2409 | - orig_node->tt_poss_change = false; | |
2410 | 2402 | } else { |
2411 | 2403 | /* if we missed more than one change or our tables are not |
2412 | 2404 | * in sync anymore -> request fresh tt data |
... | ... | @@ -2443,6 +2435,32 @@ |
2443 | 2435 | batadv_tt_global_entry_free_ref(tt_global_entry); |
2444 | 2436 | out: |
2445 | 2437 | return ret; |
2438 | +} | |
2439 | + | |
2440 | +/** | |
2441 | + * batadv_tt_local_client_is_roaming - tells whether the client is roaming | |
2442 | + * @bat_priv: the bat priv with all the soft interface information | |
2443 | + * @addr: the MAC address of the local client to query | |
2444 | + * | |
2445 | + * Returns true if the local client is known to be roaming (it is not served by | |
2446 | + * this node anymore) or not. If yes, the client is still present in the table | |
2447 | + * to keep the latter consistent with the node TTVN | |
2448 | + */ | |
2449 | +bool batadv_tt_local_client_is_roaming(struct batadv_priv *bat_priv, | |
2450 | + uint8_t *addr) | |
2451 | +{ | |
2452 | + struct batadv_tt_local_entry *tt_local_entry; | |
2453 | + bool ret = false; | |
2454 | + | |
2455 | + tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr); | |
2456 | + if (!tt_local_entry) | |
2457 | + goto out; | |
2458 | + | |
2459 | + ret = tt_local_entry->common.flags & BATADV_TT_CLIENT_ROAM; | |
2460 | + batadv_tt_local_entry_free_ref(tt_local_entry); | |
2461 | +out: | |
2462 | + return ret; | |
2463 | + | |
2446 | 2464 | } |
2447 | 2465 | |
2448 | 2466 | bool batadv_tt_add_temporary_global_entry(struct batadv_priv *bat_priv, |
net/batman-adv/translation-table.h
... | ... | @@ -59,6 +59,8 @@ |
59 | 59 | int packet_min_len); |
60 | 60 | bool batadv_tt_global_client_is_roaming(struct batadv_priv *bat_priv, |
61 | 61 | uint8_t *addr); |
62 | +bool batadv_tt_local_client_is_roaming(struct batadv_priv *bat_priv, | |
63 | + uint8_t *addr); | |
62 | 64 | bool batadv_tt_add_temporary_global_entry(struct batadv_priv *bat_priv, |
63 | 65 | struct batadv_orig_node *orig_node, |
64 | 66 | const unsigned char *addr); |
net/batman-adv/types.h
... | ... | @@ -101,13 +101,6 @@ |
101 | 101 | spinlock_t tt_buff_lock; /* protects tt_buff */ |
102 | 102 | atomic_t tt_size; |
103 | 103 | bool tt_initialised; |
104 | - /* The tt_poss_change flag is used to detect an ongoing roaming phase. | |
105 | - * If true, then I sent a Roaming_adv to this orig_node and I have to | |
106 | - * inspect every packet directed to it to check whether it is still | |
107 | - * the true destination or not. This flag will be reset to false as | |
108 | - * soon as I receive a new TTVN from this orig_node | |
109 | - */ | |
110 | - bool tt_poss_change; | |
111 | 104 | uint32_t last_real_seqno; |
112 | 105 | uint8_t last_ttl; |
113 | 106 | DECLARE_BITMAP(bcast_bits, BATADV_TQ_LOCAL_WINDOW_SIZE); |
... | ... | @@ -212,7 +205,6 @@ |
212 | 205 | atomic_t vn; |
213 | 206 | atomic_t ogm_append_cnt; |
214 | 207 | atomic_t local_changes; |
215 | - bool poss_change; | |
216 | 208 | struct list_head changes_list; |
217 | 209 | struct batadv_hashtable *local_hash; |
218 | 210 | struct batadv_hashtable *global_hash; |