aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/batman-adv/originator.c1
-rw-r--r--net/batman-adv/routing.c173
-rw-r--r--net/batman-adv/soft-interface.c1
-rw-r--r--net/batman-adv/translation-table.c46
-rw-r--r--net/batman-adv/translation-table.h2
-rw-r--r--net/batman-adv/types.h8
6 files changed, 156 insertions, 75 deletions
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c
index 84930a4f5369..8c32cf1c2dec 100644
--- a/net/batman-adv/originator.c
+++ b/net/batman-adv/originator.c
@@ -221,7 +221,6 @@ struct batadv_orig_node *batadv_get_orig_node(struct batadv_priv *bat_priv,
221 atomic_set(&orig_node->refcount, 2); 221 atomic_set(&orig_node->refcount, 2);
222 222
223 orig_node->tt_initialised = false; 223 orig_node->tt_initialised = false;
224 orig_node->tt_poss_change = false;
225 orig_node->bat_priv = bat_priv; 224 orig_node->bat_priv = bat_priv;
226 memcpy(orig_node->orig, addr, ETH_ALEN); 225 memcpy(orig_node->orig, addr, ETH_ALEN);
227 batadv_dat_init_orig_node_addr(orig_node); 226 batadv_dat_init_orig_node_addr(orig_node);
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c
index 32aa4d460e1f..78d657264cbf 100644
--- a/net/batman-adv/routing.c
+++ b/net/batman-adv/routing.c
@@ -711,12 +711,6 @@ int batadv_recv_roam_adv(struct sk_buff *skb, struct batadv_hard_iface *recv_if)
711 BATADV_TT_CLIENT_ROAM, 711 BATADV_TT_CLIENT_ROAM,
712 atomic_read(&orig_node->last_ttvn) + 1); 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 batadv_orig_node_free_ref(orig_node); 714 batadv_orig_node_free_ref(orig_node);
721out: 715out:
722 /* returning NET_RX_DROP will make the caller function kfree the skb */ 716 /* returning NET_RX_DROP will make the caller function kfree the skb */
@@ -899,14 +893,67 @@ out:
899 return ret; 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 */
908static bool
909batadv_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;
941out:
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
902static int batadv_check_unicast_ttvn(struct batadv_priv *bat_priv, 950static int batadv_check_unicast_ttvn(struct batadv_priv *bat_priv,
903 struct sk_buff *skb) { 951 struct sk_buff *skb) {
904 uint8_t curr_ttvn; 952 uint8_t curr_ttvn, old_ttvn;
905 struct batadv_orig_node *orig_node; 953 struct batadv_orig_node *orig_node;
906 struct ethhdr *ethhdr; 954 struct ethhdr *ethhdr;
907 struct batadv_hard_iface *primary_if; 955 struct batadv_hard_iface *primary_if;
908 struct batadv_unicast_packet *unicast_packet; 956 struct batadv_unicast_packet *unicast_packet;
909 bool tt_poss_change;
910 int is_old_ttvn; 957 int is_old_ttvn;
911 958
912 /* check if there is enough data before accessing it */ 959 /* check if there is enough data before accessing it */
@@ -918,65 +965,89 @@ static int batadv_check_unicast_ttvn(struct batadv_priv *bat_priv,
918 return 0; 965 return 0;
919 966
920 unicast_packet = (struct batadv_unicast_packet *)skb->data; 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)) { 970 /* check if the destination client was served by this node and it is now
923 tt_poss_change = bat_priv->tt.poss_change; 971 * roaming. In this case, it means that the node has got a ROAM_ADV
924 curr_ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn); 972 * message and that it knows the new destination in the mesh to re-route
925 } else { 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 orig_node = batadv_orig_hash_find(bat_priv, 997 orig_node = batadv_orig_hash_find(bat_priv,
927 unicast_packet->dest); 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 if (!orig_node) 1003 if (!orig_node)
930 return 0; 1004 return 0;
931 1005
932 curr_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn); 1006 curr_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn);
933 tt_poss_change = orig_node->tt_poss_change;
934 batadv_orig_node_free_ref(orig_node); 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 is_old_ttvn = batadv_seq_before(unicast_packet->ttvn, curr_ttvn); 1013 is_old_ttvn = batadv_seq_before(unicast_packet->ttvn, curr_ttvn);
939 if (is_old_ttvn || tt_poss_change) { 1014 if (!is_old_ttvn)
940 /* check if there is enough data before accessing it */ 1015 return 1;
941 if (pskb_may_pull(skb, sizeof(struct batadv_unicast_packet) +
942 ETH_HLEN) < 0)
943 return 0;
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 1031 /* the packet has not been re-routed: either the destination is
948 * not try to reroute the packet!! 1032 * currently served by this node or there is no destination at all and
949 */ 1033 * it is possible to drop the packet
950 if (batadv_tt_global_client_is_roaming(bat_priv, 1034 */
951 ethhdr->h_dest)) 1035 if (!batadv_is_my_client(bat_priv, ethhdr->h_dest))
952 return 1; 1036 return 0;
953 1037
954 orig_node = batadv_transtable_search(bat_priv, NULL, 1038 /* update the header in order to let the packet be delivered to this
955 ethhdr->h_dest); 1039 * node's soft interface
956 1040 */
957 if (!orig_node) { 1041 primary_if = batadv_primary_if_get_selected(bat_priv);
958 if (!batadv_is_my_client(bat_priv, ethhdr->h_dest)) 1042 if (!primary_if)
959 return 0; 1043 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 }
972 1044
973 net_ratelimited_function(batadv_dbg, BATADV_DBG_TT, bat_priv, 1045 memcpy(unicast_packet->dest, primary_if->net_dev->dev_addr, ETH_ALEN);
974 "TTVN mismatch (old_ttvn %u new_ttvn %u)! Rerouting unicast packet (for %pM) to %pM\n", 1046
975 unicast_packet->ttvn, curr_ttvn, 1047 batadv_hardif_free_ref(primary_if);
976 ethhdr->h_dest, unicast_packet->dest); 1048
1049 unicast_packet->ttvn = curr_ttvn;
977 1050
978 unicast_packet->ttvn = curr_ttvn;
979 }
980 return 1; 1051 return 1;
981} 1052}
982 1053
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c
index c283d87c4cce..2d1f89517d99 100644
--- a/net/batman-adv/soft-interface.c
+++ b/net/batman-adv/soft-interface.c
@@ -505,7 +505,6 @@ struct net_device *batadv_softif_create(const char *name)
505#endif 505#endif
506 bat_priv->tt.last_changeset = NULL; 506 bat_priv->tt.last_changeset = NULL;
507 bat_priv->tt.last_changeset_len = 0; 507 bat_priv->tt.last_changeset_len = 0;
508 bat_priv->tt.poss_change = false;
509 508
510 bat_priv->primary_if = NULL; 509 bat_priv->primary_if = NULL;
511 bat_priv->num_ifaces = 0; 510 bat_priv->num_ifaces = 0;
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
index f8b9c32c29a5..d7418511448d 100644
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@ -306,8 +306,6 @@ void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
306 head = &tt_global_entry->orig_list; 306 head = &tt_global_entry->orig_list;
307 rcu_read_lock(); 307 rcu_read_lock();
308 hlist_for_each_entry_rcu(orig_entry, node, head, list) { 308 hlist_for_each_entry_rcu(orig_entry, node, head, list) {
309 orig_entry->orig_node->tt_poss_change = true;
310
311 batadv_send_roam_adv(bat_priv, 309 batadv_send_roam_adv(bat_priv,
312 tt_global_entry->common.addr, 310 tt_global_entry->common.addr,
313 orig_entry->orig_node); 311 orig_entry->orig_node);
@@ -512,8 +510,11 @@ uint16_t batadv_tt_local_remove(struct batadv_priv *bat_priv,
512 curr_flags = tt_local_entry->common.flags; 510 curr_flags = tt_local_entry->common.flags;
513 511
514 flags = BATADV_TT_CLIENT_DEL; 512 flags = BATADV_TT_CLIENT_DEL;
515 if (roaming) 513 if (roaming) {
516 flags |= BATADV_TT_CLIENT_ROAM; 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 batadv_tt_local_set_pending(bat_priv, tt_local_entry, flags, message); 519 batadv_tt_local_set_pending(bat_priv, tt_local_entry, flags, message);
519 520
@@ -1945,7 +1946,8 @@ bool batadv_is_my_client(struct batadv_priv *bat_priv, const uint8_t *addr)
1945 /* Check if the client has been logically deleted (but is kept for 1946 /* Check if the client has been logically deleted (but is kept for
1946 * consistency purpose) 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 goto out; 1951 goto out;
1950 ret = true; 1952 ret = true;
1951out: 1953out:
@@ -1996,10 +1998,6 @@ void batadv_handle_tt_response(struct batadv_priv *bat_priv,
1996 1998
1997 /* Recalculate the CRC for this orig_node and store it */ 1999 /* Recalculate the CRC for this orig_node and store it */
1998 orig_node->tt_crc = batadv_tt_global_crc(bat_priv, orig_node); 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;
2003out: 2001out:
2004 if (orig_node) 2002 if (orig_node)
2005 batadv_orig_node_free_ref(orig_node); 2003 batadv_orig_node_free_ref(orig_node);
@@ -2290,7 +2288,6 @@ static int batadv_tt_commit_changes(struct batadv_priv *bat_priv,
2290 batadv_dbg(BATADV_DBG_TT, bat_priv, 2288 batadv_dbg(BATADV_DBG_TT, bat_priv,
2291 "Local changes committed, updating to ttvn %u\n", 2289 "Local changes committed, updating to ttvn %u\n",
2292 (uint8_t)atomic_read(&bat_priv->tt.vn)); 2290 (uint8_t)atomic_read(&bat_priv->tt.vn));
2293 bat_priv->tt.poss_change = false;
2294 2291
2295 /* reset the sending counter */ 2292 /* reset the sending counter */
2296 atomic_set(&bat_priv->tt.ogm_append_cnt, BATADV_TT_OGM_APPEND_MAX); 2293 atomic_set(&bat_priv->tt.ogm_append_cnt, BATADV_TT_OGM_APPEND_MAX);
@@ -2402,11 +2399,6 @@ void batadv_tt_update_orig(struct batadv_priv *bat_priv,
2402 */ 2399 */
2403 if (orig_node->tt_crc != tt_crc) 2400 if (orig_node->tt_crc != tt_crc)
2404 goto request_table; 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 } else { 2402 } else {
2411 /* if we missed more than one change or our tables are not 2403 /* if we missed more than one change or our tables are not
2412 * in sync anymore -> request fresh tt data 2404 * in sync anymore -> request fresh tt data
@@ -2445,6 +2437,32 @@ out:
2445 return ret; 2437 return ret;
2446} 2438}
2447 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 */
2449bool 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);
2461out:
2462 return ret;
2463
2464}
2465
2448bool batadv_tt_add_temporary_global_entry(struct batadv_priv *bat_priv, 2466bool batadv_tt_add_temporary_global_entry(struct batadv_priv *bat_priv,
2449 struct batadv_orig_node *orig_node, 2467 struct batadv_orig_node *orig_node,
2450 const unsigned char *addr) 2468 const unsigned char *addr)
diff --git a/net/batman-adv/translation-table.h b/net/batman-adv/translation-table.h
index 9fa4fe41c868..46d4451a59ee 100644
--- a/net/batman-adv/translation-table.h
+++ b/net/batman-adv/translation-table.h
@@ -59,6 +59,8 @@ int batadv_tt_append_diff(struct batadv_priv *bat_priv,
59 int packet_min_len); 59 int packet_min_len);
60bool batadv_tt_global_client_is_roaming(struct batadv_priv *bat_priv, 60bool batadv_tt_global_client_is_roaming(struct batadv_priv *bat_priv,
61 uint8_t *addr); 61 uint8_t *addr);
62bool batadv_tt_local_client_is_roaming(struct batadv_priv *bat_priv,
63 uint8_t *addr);
62bool batadv_tt_add_temporary_global_entry(struct batadv_priv *bat_priv, 64bool batadv_tt_add_temporary_global_entry(struct batadv_priv *bat_priv,
63 struct batadv_orig_node *orig_node, 65 struct batadv_orig_node *orig_node,
64 const unsigned char *addr); 66 const unsigned char *addr);
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index fa09961652a1..7b3d0d7ef06a 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -101,13 +101,6 @@ struct batadv_orig_node {
101 spinlock_t tt_buff_lock; /* protects tt_buff */ 101 spinlock_t tt_buff_lock; /* protects tt_buff */
102 atomic_t tt_size; 102 atomic_t tt_size;
103 bool tt_initialised; 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 uint32_t last_real_seqno; 104 uint32_t last_real_seqno;
112 uint8_t last_ttl; 105 uint8_t last_ttl;
113 DECLARE_BITMAP(bcast_bits, BATADV_TQ_LOCAL_WINDOW_SIZE); 106 DECLARE_BITMAP(bcast_bits, BATADV_TQ_LOCAL_WINDOW_SIZE);
@@ -212,7 +205,6 @@ struct batadv_priv_tt {
212 atomic_t vn; 205 atomic_t vn;
213 atomic_t ogm_append_cnt; 206 atomic_t ogm_append_cnt;
214 atomic_t local_changes; 207 atomic_t local_changes;
215 bool poss_change;
216 struct list_head changes_list; 208 struct list_head changes_list;
217 struct batadv_hashtable *local_hash; 209 struct batadv_hashtable *local_hash;
218 struct batadv_hashtable *global_hash; 210 struct batadv_hashtable *global_hash;