aboutsummaryrefslogtreecommitdiffstats
path: root/net/batman-adv/routing.c
diff options
context:
space:
mode:
authorAntonio Quartulli <ordex@autistici.org>2012-09-23 16:38:34 -0400
committerAntonio Quartulli <ordex@autistici.org>2012-11-14 15:00:35 -0500
commit7c1fd91da5a5eecc91674991199940c05f87cb3a (patch)
tree9195dbbe9ea99a09540166dd571779d9b7fde478 /net/batman-adv/routing.c
parent28709878b6a7d15362ba63bde01d42c38f88be9d (diff)
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>
Diffstat (limited to 'net/batman-adv/routing.c')
-rw-r--r--net/batman-adv/routing.c173
1 files changed, 122 insertions, 51 deletions
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