Commit 7c1fd91da5a5eecc91674991199940c05f87cb3a

Authored by Antonio Quartulli
1 parent 28709878b6

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
... ... @@ -505,7 +505,6 @@
505 505 #endif
506 506 bat_priv->tt.last_changeset = NULL;
507 507 bat_priv->tt.last_changeset_len = 0;
508   - bat_priv->tt.poss_change = false;
509 508  
510 509 bat_priv->primary_if = NULL;
511 510 bat_priv->num_ifaces = 0;
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;