aboutsummaryrefslogtreecommitdiffstats
path: root/net/batman-adv/network-coding.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/batman-adv/network-coding.c')
-rw-r--r--net/batman-adv/network-coding.c401
1 files changed, 401 insertions, 0 deletions
diff --git a/net/batman-adv/network-coding.c b/net/batman-adv/network-coding.c
index 2c38c540c6db..fce2846e9656 100644
--- a/net/batman-adv/network-coding.c
+++ b/net/batman-adv/network-coding.c
@@ -798,6 +798,403 @@ static struct batadv_nc_path *batadv_nc_get_path(struct batadv_priv *bat_priv,
798} 798}
799 799
800/** 800/**
801 * batadv_nc_random_weight_tq - scale the receivers TQ-value to avoid unfair
802 * selection of a receiver with slightly lower TQ than the other
803 * @tq: to be weighted tq value
804 */
805static uint8_t batadv_nc_random_weight_tq(uint8_t tq)
806{
807 uint8_t rand_val, rand_tq;
808
809 get_random_bytes(&rand_val, sizeof(rand_val));
810
811 /* randomize the estimated packet loss (max TQ - estimated TQ) */
812 rand_tq = rand_val * (BATADV_TQ_MAX_VALUE - tq);
813
814 /* normalize the randomized packet loss */
815 rand_tq /= BATADV_TQ_MAX_VALUE;
816
817 /* convert to (randomized) estimated tq again */
818 return BATADV_TQ_MAX_VALUE - rand_tq;
819}
820
821/**
822 * batadv_nc_memxor - XOR destination with source
823 * @dst: byte array to XOR into
824 * @src: byte array to XOR from
825 * @len: length of destination array
826 */
827static void batadv_nc_memxor(char *dst, const char *src, unsigned int len)
828{
829 unsigned int i;
830
831 for (i = 0; i < len; ++i)
832 dst[i] ^= src[i];
833}
834
835/**
836 * batadv_nc_code_packets - code a received unicast_packet with an nc packet
837 * into a coded_packet and send it
838 * @bat_priv: the bat priv with all the soft interface information
839 * @skb: data skb to forward
840 * @ethhdr: pointer to the ethernet header inside the skb
841 * @nc_packet: structure containing the packet to the skb can be coded with
842 * @neigh_node: next hop to forward packet to
843 *
844 * Returns true if both packets are consumed, false otherwise.
845 */
846static bool batadv_nc_code_packets(struct batadv_priv *bat_priv,
847 struct sk_buff *skb,
848 struct ethhdr *ethhdr,
849 struct batadv_nc_packet *nc_packet,
850 struct batadv_neigh_node *neigh_node)
851{
852 uint8_t tq_weighted_neigh, tq_weighted_coding;
853 struct sk_buff *skb_dest, *skb_src;
854 struct batadv_unicast_packet *packet1;
855 struct batadv_unicast_packet *packet2;
856 struct batadv_coded_packet *coded_packet;
857 struct batadv_neigh_node *neigh_tmp, *router_neigh;
858 struct batadv_neigh_node *router_coding = NULL;
859 uint8_t *first_source, *first_dest, *second_source, *second_dest;
860 __be32 packet_id1, packet_id2;
861 size_t count;
862 bool res = false;
863 int coding_len;
864 int unicast_size = sizeof(*packet1);
865 int coded_size = sizeof(*coded_packet);
866 int header_add = coded_size - unicast_size;
867
868 router_neigh = batadv_orig_node_get_router(neigh_node->orig_node);
869 if (!router_neigh)
870 goto out;
871
872 neigh_tmp = nc_packet->neigh_node;
873 router_coding = batadv_orig_node_get_router(neigh_tmp->orig_node);
874 if (!router_coding)
875 goto out;
876
877 tq_weighted_neigh = batadv_nc_random_weight_tq(router_neigh->tq_avg);
878 tq_weighted_coding = batadv_nc_random_weight_tq(router_coding->tq_avg);
879
880 /* Select one destination for the MAC-header dst-field based on
881 * weighted TQ-values.
882 */
883 if (tq_weighted_neigh >= tq_weighted_coding) {
884 /* Destination from nc_packet is selected for MAC-header */
885 first_dest = nc_packet->nc_path->next_hop;
886 first_source = nc_packet->nc_path->prev_hop;
887 second_dest = neigh_node->addr;
888 second_source = ethhdr->h_source;
889 packet1 = (struct batadv_unicast_packet *)nc_packet->skb->data;
890 packet2 = (struct batadv_unicast_packet *)skb->data;
891 packet_id1 = nc_packet->packet_id;
892 packet_id2 = batadv_skb_crc32(skb,
893 skb->data + sizeof(*packet2));
894 } else {
895 /* Destination for skb is selected for MAC-header */
896 first_dest = neigh_node->addr;
897 first_source = ethhdr->h_source;
898 second_dest = nc_packet->nc_path->next_hop;
899 second_source = nc_packet->nc_path->prev_hop;
900 packet1 = (struct batadv_unicast_packet *)skb->data;
901 packet2 = (struct batadv_unicast_packet *)nc_packet->skb->data;
902 packet_id1 = batadv_skb_crc32(skb,
903 skb->data + sizeof(*packet1));
904 packet_id2 = nc_packet->packet_id;
905 }
906
907 /* Instead of zero padding the smallest data buffer, we
908 * code into the largest.
909 */
910 if (skb->len <= nc_packet->skb->len) {
911 skb_dest = nc_packet->skb;
912 skb_src = skb;
913 } else {
914 skb_dest = skb;
915 skb_src = nc_packet->skb;
916 }
917
918 /* coding_len is used when decoding the packet shorter packet */
919 coding_len = skb_src->len - unicast_size;
920
921 if (skb_linearize(skb_dest) < 0 || skb_linearize(skb_src) < 0)
922 goto out;
923
924 skb_push(skb_dest, header_add);
925
926 coded_packet = (struct batadv_coded_packet *)skb_dest->data;
927 skb_reset_mac_header(skb_dest);
928
929 coded_packet->header.packet_type = BATADV_CODED;
930 coded_packet->header.version = BATADV_COMPAT_VERSION;
931 coded_packet->header.ttl = packet1->header.ttl;
932
933 /* Info about first unicast packet */
934 memcpy(coded_packet->first_source, first_source, ETH_ALEN);
935 memcpy(coded_packet->first_orig_dest, packet1->dest, ETH_ALEN);
936 coded_packet->first_crc = packet_id1;
937 coded_packet->first_ttvn = packet1->ttvn;
938
939 /* Info about second unicast packet */
940 memcpy(coded_packet->second_dest, second_dest, ETH_ALEN);
941 memcpy(coded_packet->second_source, second_source, ETH_ALEN);
942 memcpy(coded_packet->second_orig_dest, packet2->dest, ETH_ALEN);
943 coded_packet->second_crc = packet_id2;
944 coded_packet->second_ttl = packet2->header.ttl;
945 coded_packet->second_ttvn = packet2->ttvn;
946 coded_packet->coded_len = htons(coding_len);
947
948 /* This is where the magic happens: Code skb_src into skb_dest */
949 batadv_nc_memxor(skb_dest->data + coded_size,
950 skb_src->data + unicast_size, coding_len);
951
952 /* Update counters accordingly */
953 if (BATADV_SKB_CB(skb_src)->decoded &&
954 BATADV_SKB_CB(skb_dest)->decoded) {
955 /* Both packets are recoded */
956 count = skb_src->len + ETH_HLEN;
957 count += skb_dest->len + ETH_HLEN;
958 batadv_add_counter(bat_priv, BATADV_CNT_NC_RECODE, 2);
959 batadv_add_counter(bat_priv, BATADV_CNT_NC_RECODE_BYTES, count);
960 } else if (!BATADV_SKB_CB(skb_src)->decoded &&
961 !BATADV_SKB_CB(skb_dest)->decoded) {
962 /* Both packets are newly coded */
963 count = skb_src->len + ETH_HLEN;
964 count += skb_dest->len + ETH_HLEN;
965 batadv_add_counter(bat_priv, BATADV_CNT_NC_CODE, 2);
966 batadv_add_counter(bat_priv, BATADV_CNT_NC_CODE_BYTES, count);
967 } else if (BATADV_SKB_CB(skb_src)->decoded &&
968 !BATADV_SKB_CB(skb_dest)->decoded) {
969 /* skb_src recoded and skb_dest is newly coded */
970 batadv_inc_counter(bat_priv, BATADV_CNT_NC_RECODE);
971 batadv_add_counter(bat_priv, BATADV_CNT_NC_RECODE_BYTES,
972 skb_src->len + ETH_HLEN);
973 batadv_inc_counter(bat_priv, BATADV_CNT_NC_CODE);
974 batadv_add_counter(bat_priv, BATADV_CNT_NC_CODE_BYTES,
975 skb_dest->len + ETH_HLEN);
976 } else if (!BATADV_SKB_CB(skb_src)->decoded &&
977 BATADV_SKB_CB(skb_dest)->decoded) {
978 /* skb_src is newly coded and skb_dest is recoded */
979 batadv_inc_counter(bat_priv, BATADV_CNT_NC_CODE);
980 batadv_add_counter(bat_priv, BATADV_CNT_NC_CODE_BYTES,
981 skb_src->len + ETH_HLEN);
982 batadv_inc_counter(bat_priv, BATADV_CNT_NC_RECODE);
983 batadv_add_counter(bat_priv, BATADV_CNT_NC_RECODE_BYTES,
984 skb_dest->len + ETH_HLEN);
985 }
986
987 /* skb_src is now coded into skb_dest, so free it */
988 kfree_skb(skb_src);
989
990 /* avoid duplicate free of skb from nc_packet */
991 nc_packet->skb = NULL;
992 batadv_nc_packet_free(nc_packet);
993
994 /* Send the coded packet and return true */
995 batadv_send_skb_packet(skb_dest, neigh_node->if_incoming, first_dest);
996 res = true;
997out:
998 if (router_neigh)
999 batadv_neigh_node_free_ref(router_neigh);
1000 if (router_coding)
1001 batadv_neigh_node_free_ref(router_coding);
1002 return res;
1003}
1004
1005/**
1006 * batadv_nc_skb_coding_possible - true if a decoded skb is available at dst.
1007 * @skb: data skb to forward
1008 * @dst: destination mac address of the other skb to code with
1009 * @src: source mac address of skb
1010 *
1011 * Whenever we network code a packet we have to check whether we received it in
1012 * a network coded form. If so, we may not be able to use it for coding because
1013 * some neighbors may also have received (overheard) the packet in the network
1014 * coded form without being able to decode it. It is hard to know which of the
1015 * neighboring nodes was able to decode the packet, therefore we can only
1016 * re-code the packet if the source of the previous encoded packet is involved.
1017 * Since the source encoded the packet we can be certain it has all necessary
1018 * decode information.
1019 *
1020 * Returns true if coding of a decoded packet is allowed.
1021 */
1022static bool batadv_nc_skb_coding_possible(struct sk_buff *skb,
1023 uint8_t *dst, uint8_t *src)
1024{
1025 if (BATADV_SKB_CB(skb)->decoded && !batadv_compare_eth(dst, src))
1026 return false;
1027 else
1028 return true;
1029}
1030
1031/**
1032 * batadv_nc_path_search - Find the coding path matching in_nc_node and
1033 * out_nc_node to retrieve a buffered packet that can be used for coding.
1034 * @bat_priv: the bat priv with all the soft interface information
1035 * @in_nc_node: pointer to skb next hop's neighbor nc node
1036 * @out_nc_node: pointer to skb source's neighbor nc node
1037 * @skb: data skb to forward
1038 * @eth_dst: next hop mac address of skb
1039 *
1040 * Returns true if coding of a decoded skb is allowed.
1041 */
1042static struct batadv_nc_packet *
1043batadv_nc_path_search(struct batadv_priv *bat_priv,
1044 struct batadv_nc_node *in_nc_node,
1045 struct batadv_nc_node *out_nc_node,
1046 struct sk_buff *skb,
1047 uint8_t *eth_dst)
1048{
1049 struct batadv_nc_path *nc_path, nc_path_key;
1050 struct batadv_nc_packet *nc_packet_out = NULL;
1051 struct batadv_nc_packet *nc_packet, *nc_packet_tmp;
1052 struct batadv_hashtable *hash = bat_priv->nc.coding_hash;
1053 int idx;
1054
1055 if (!hash)
1056 return NULL;
1057
1058 /* Create almost path key */
1059 batadv_nc_hash_key_gen(&nc_path_key, in_nc_node->addr,
1060 out_nc_node->addr);
1061 idx = batadv_nc_hash_choose(&nc_path_key, hash->size);
1062
1063 /* Check for coding opportunities in this nc_path */
1064 rcu_read_lock();
1065 hlist_for_each_entry_rcu(nc_path, &hash->table[idx], hash_entry) {
1066 if (!batadv_compare_eth(nc_path->prev_hop, in_nc_node->addr))
1067 continue;
1068
1069 if (!batadv_compare_eth(nc_path->next_hop, out_nc_node->addr))
1070 continue;
1071
1072 spin_lock_bh(&nc_path->packet_list_lock);
1073 if (list_empty(&nc_path->packet_list)) {
1074 spin_unlock_bh(&nc_path->packet_list_lock);
1075 continue;
1076 }
1077
1078 list_for_each_entry_safe(nc_packet, nc_packet_tmp,
1079 &nc_path->packet_list, list) {
1080 if (!batadv_nc_skb_coding_possible(nc_packet->skb,
1081 eth_dst,
1082 in_nc_node->addr))
1083 continue;
1084
1085 /* Coding opportunity is found! */
1086 list_del(&nc_packet->list);
1087 nc_packet_out = nc_packet;
1088 break;
1089 }
1090
1091 spin_unlock_bh(&nc_path->packet_list_lock);
1092 break;
1093 }
1094 rcu_read_unlock();
1095
1096 return nc_packet_out;
1097}
1098
1099/**
1100 * batadv_nc_skb_src_search - Loops through the list of neighoring nodes of the
1101 * skb's sender (may be equal to the originator).
1102 * @bat_priv: the bat priv with all the soft interface information
1103 * @skb: data skb to forward
1104 * @eth_dst: next hop mac address of skb
1105 * @eth_src: source mac address of skb
1106 * @in_nc_node: pointer to skb next hop's neighbor nc node
1107 *
1108 * Returns an nc packet if a suitable coding packet was found, NULL otherwise.
1109 */
1110static struct batadv_nc_packet *
1111batadv_nc_skb_src_search(struct batadv_priv *bat_priv,
1112 struct sk_buff *skb,
1113 uint8_t *eth_dst,
1114 uint8_t *eth_src,
1115 struct batadv_nc_node *in_nc_node)
1116{
1117 struct batadv_orig_node *orig_node;
1118 struct batadv_nc_node *out_nc_node;
1119 struct batadv_nc_packet *nc_packet = NULL;
1120
1121 orig_node = batadv_orig_hash_find(bat_priv, eth_src);
1122 if (!orig_node)
1123 return NULL;
1124
1125 rcu_read_lock();
1126 list_for_each_entry_rcu(out_nc_node,
1127 &orig_node->out_coding_list, list) {
1128 /* Check if the skb is decoded and if recoding is possible */
1129 if (!batadv_nc_skb_coding_possible(skb,
1130 out_nc_node->addr, eth_src))
1131 continue;
1132
1133 /* Search for an opportunity in this nc_path */
1134 nc_packet = batadv_nc_path_search(bat_priv, in_nc_node,
1135 out_nc_node, skb, eth_dst);
1136 if (nc_packet)
1137 break;
1138 }
1139 rcu_read_unlock();
1140
1141 batadv_orig_node_free_ref(orig_node);
1142 return nc_packet;
1143}
1144
1145/**
1146 * batadv_nc_skb_dst_search - Loops through list of neighboring nodes to dst.
1147 * @skb: data skb to forward
1148 * @neigh_node: next hop to forward packet to
1149 * @ethhdr: pointer to the ethernet header inside the skb
1150 *
1151 * Loops through list of neighboring nodes the next hop has a good connection to
1152 * (receives OGMs with a sufficient quality). We need to find a neighbor of our
1153 * next hop that potentially sent a packet which our next hop also received
1154 * (overheard) and has stored for later decoding.
1155 *
1156 * Returns true if the skb was consumed (encoded packet sent) or false otherwise
1157 */
1158static bool batadv_nc_skb_dst_search(struct sk_buff *skb,
1159 struct batadv_neigh_node *neigh_node,
1160 struct ethhdr *ethhdr)
1161{
1162 struct net_device *netdev = neigh_node->if_incoming->soft_iface;
1163 struct batadv_priv *bat_priv = netdev_priv(netdev);
1164 struct batadv_orig_node *orig_node = neigh_node->orig_node;
1165 struct batadv_nc_node *nc_node;
1166 struct batadv_nc_packet *nc_packet = NULL;
1167
1168 rcu_read_lock();
1169 list_for_each_entry_rcu(nc_node, &orig_node->in_coding_list, list) {
1170 /* Search for coding opportunity with this in_nc_node */
1171 nc_packet = batadv_nc_skb_src_search(bat_priv, skb,
1172 neigh_node->addr,
1173 ethhdr->h_source, nc_node);
1174
1175 /* Opportunity was found, so stop searching */
1176 if (nc_packet)
1177 break;
1178 }
1179 rcu_read_unlock();
1180
1181 if (!nc_packet)
1182 return false;
1183
1184 /* Code and send packets */
1185 if (batadv_nc_code_packets(bat_priv, skb, ethhdr, nc_packet,
1186 neigh_node))
1187 return true;
1188
1189 /* out of mem ? Coding failed - we have to free the buffered packet
1190 * to avoid memleaks. The skb passed as argument will be dealt with
1191 * by the calling function.
1192 */
1193 batadv_nc_send_packet(nc_packet);
1194 return false;
1195}
1196
1197/**
801 * batadv_nc_skb_add_to_path - buffer skb for later encoding / decoding 1198 * batadv_nc_skb_add_to_path - buffer skb for later encoding / decoding
802 * @skb: skb to add to path 1199 * @skb: skb to add to path
803 * @nc_path: path to add skb to 1200 * @nc_path: path to add skb to
@@ -862,6 +1259,10 @@ bool batadv_nc_skb_forward(struct sk_buff *skb,
862 if (packet->header.packet_type != BATADV_UNICAST) 1259 if (packet->header.packet_type != BATADV_UNICAST)
863 goto out; 1260 goto out;
864 1261
1262 /* Try to find a coding opportunity and send the skb if one is found */
1263 if (batadv_nc_skb_dst_search(skb, neigh_node, ethhdr))
1264 return true;
1265
865 /* Find or create a nc_path for this src-dst pair */ 1266 /* Find or create a nc_path for this src-dst pair */
866 nc_path = batadv_nc_get_path(bat_priv, 1267 nc_path = batadv_nc_get_path(bat_priv,
867 bat_priv->nc.coding_hash, 1268 bat_priv->nc.coding_hash,