diff options
Diffstat (limited to 'net/batman-adv/network-coding.c')
-rw-r--r-- | net/batman-adv/network-coding.c | 401 |
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 | */ | ||
805 | static 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 | */ | ||
827 | static 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 | */ | ||
846 | static 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; | ||
997 | out: | ||
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 | */ | ||
1022 | static 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 | */ | ||
1042 | static struct batadv_nc_packet * | ||
1043 | batadv_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 | */ | ||
1110 | static struct batadv_nc_packet * | ||
1111 | batadv_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 | */ | ||
1158 | static 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, |