diff options
Diffstat (limited to 'net')
| -rw-r--r-- | net/batman-adv/bat_iv_ogm.c | 267 | ||||
| -rw-r--r-- | net/batman-adv/gateway_client.c | 75 | ||||
| -rw-r--r-- | net/batman-adv/hard-interface.h | 17 | ||||
| -rw-r--r-- | net/batman-adv/main.h | 6 | ||||
| -rw-r--r-- | net/batman-adv/network-coding.c | 24 | ||||
| -rw-r--r-- | net/batman-adv/originator.c | 229 | ||||
| -rw-r--r-- | net/batman-adv/originator.h | 7 | ||||
| -rw-r--r-- | net/batman-adv/translation-table.c | 3 | ||||
| -rw-r--r-- | net/batman-adv/types.h | 74 |
9 files changed, 588 insertions, 114 deletions
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c index 48f5d3537ee3..157cc1176313 100644 --- a/net/batman-adv/bat_iv_ogm.c +++ b/net/batman-adv/bat_iv_ogm.c | |||
| @@ -272,7 +272,14 @@ batadv_iv_ogm_neigh_new(struct batadv_hard_iface *hard_iface, | |||
| 272 | if (!neigh_node) | 272 | if (!neigh_node) |
| 273 | goto out; | 273 | goto out; |
| 274 | 274 | ||
| 275 | spin_lock_init(&neigh_node->bat_iv.lq_update_lock); | 275 | if (!atomic_inc_not_zero(&hard_iface->refcount)) { |
| 276 | kfree(neigh_node); | ||
| 277 | neigh_node = NULL; | ||
| 278 | goto out; | ||
| 279 | } | ||
| 280 | |||
| 281 | neigh_node->orig_node = orig_neigh; | ||
| 282 | neigh_node->if_incoming = hard_iface; | ||
| 276 | 283 | ||
| 277 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, | 284 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, |
| 278 | "Creating new neighbor %pM for orig_node %pM on interface %s\n", | 285 | "Creating new neighbor %pM for orig_node %pM on interface %s\n", |
| @@ -895,15 +902,30 @@ static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface) | |||
| 895 | batadv_hardif_free_ref(primary_if); | 902 | batadv_hardif_free_ref(primary_if); |
| 896 | } | 903 | } |
| 897 | 904 | ||
| 905 | /** | ||
| 906 | * batadv_iv_ogm_orig_update - use OGM to update corresponding data in an | ||
| 907 | * originator | ||
| 908 | * @bat_priv: the bat priv with all the soft interface information | ||
| 909 | * @orig_node: the orig node who originally emitted the ogm packet | ||
| 910 | * @ethhdr: Ethernet header of the OGM | ||
| 911 | * @batadv_ogm_packet: the ogm packet | ||
| 912 | * @if_incoming: interface where the packet was received | ||
| 913 | * @if_outgoing: interface for which the retransmission should be considered | ||
| 914 | * @tt_buff: pointer to the tt buffer | ||
| 915 | * @dup_status: the duplicate status of this ogm packet. | ||
| 916 | */ | ||
| 898 | static void | 917 | static void |
| 899 | batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv, | 918 | batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv, |
| 900 | struct batadv_orig_node *orig_node, | 919 | struct batadv_orig_node *orig_node, |
| 901 | const struct ethhdr *ethhdr, | 920 | const struct ethhdr *ethhdr, |
| 902 | const struct batadv_ogm_packet *batadv_ogm_packet, | 921 | const struct batadv_ogm_packet *batadv_ogm_packet, |
| 903 | struct batadv_hard_iface *if_incoming, | 922 | struct batadv_hard_iface *if_incoming, |
| 923 | struct batadv_hard_iface *if_outgoing, | ||
| 904 | const unsigned char *tt_buff, | 924 | const unsigned char *tt_buff, |
| 905 | enum batadv_dup_status dup_status) | 925 | enum batadv_dup_status dup_status) |
| 906 | { | 926 | { |
| 927 | struct batadv_neigh_ifinfo *neigh_ifinfo = NULL; | ||
| 928 | struct batadv_neigh_ifinfo *router_ifinfo = NULL; | ||
| 907 | struct batadv_neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL; | 929 | struct batadv_neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL; |
| 908 | struct batadv_neigh_node *router = NULL; | 930 | struct batadv_neigh_node *router = NULL; |
| 909 | struct batadv_orig_node *orig_node_tmp; | 931 | struct batadv_orig_node *orig_node_tmp; |
| @@ -931,12 +953,21 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv, | |||
| 931 | if (dup_status != BATADV_NO_DUP) | 953 | if (dup_status != BATADV_NO_DUP) |
| 932 | continue; | 954 | continue; |
| 933 | 955 | ||
| 934 | spin_lock_bh(&tmp_neigh_node->bat_iv.lq_update_lock); | 956 | /* only update the entry for this outgoing interface */ |
| 935 | batadv_ring_buffer_set(tmp_neigh_node->bat_iv.tq_recv, | 957 | neigh_ifinfo = batadv_neigh_ifinfo_get(tmp_neigh_node, |
| 936 | &tmp_neigh_node->bat_iv.tq_index, 0); | 958 | if_outgoing); |
| 937 | tq_avg = batadv_ring_buffer_avg(tmp_neigh_node->bat_iv.tq_recv); | 959 | if (!neigh_ifinfo) |
| 938 | tmp_neigh_node->bat_iv.tq_avg = tq_avg; | 960 | continue; |
| 939 | spin_unlock_bh(&tmp_neigh_node->bat_iv.lq_update_lock); | 961 | |
| 962 | spin_lock_bh(&tmp_neigh_node->ifinfo_lock); | ||
| 963 | batadv_ring_buffer_set(neigh_ifinfo->bat_iv.tq_recv, | ||
| 964 | &neigh_ifinfo->bat_iv.tq_index, 0); | ||
| 965 | tq_avg = batadv_ring_buffer_avg(neigh_ifinfo->bat_iv.tq_recv); | ||
| 966 | neigh_ifinfo->bat_iv.tq_avg = tq_avg; | ||
| 967 | spin_unlock_bh(&tmp_neigh_node->ifinfo_lock); | ||
| 968 | |||
| 969 | batadv_neigh_ifinfo_free_ref(neigh_ifinfo); | ||
| 970 | neigh_ifinfo = NULL; | ||
| 940 | } | 971 | } |
| 941 | 972 | ||
| 942 | if (!neigh_node) { | 973 | if (!neigh_node) { |
| @@ -958,20 +989,23 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv, | |||
| 958 | "Updating existing last-hop neighbor of originator\n"); | 989 | "Updating existing last-hop neighbor of originator\n"); |
| 959 | 990 | ||
| 960 | rcu_read_unlock(); | 991 | rcu_read_unlock(); |
| 992 | neigh_ifinfo = batadv_neigh_ifinfo_new(neigh_node, if_outgoing); | ||
| 993 | if (!neigh_ifinfo) | ||
| 994 | goto out; | ||
| 961 | 995 | ||
| 962 | neigh_node->last_seen = jiffies; | 996 | neigh_node->last_seen = jiffies; |
| 963 | 997 | ||
| 964 | spin_lock_bh(&neigh_node->bat_iv.lq_update_lock); | 998 | spin_lock_bh(&neigh_node->ifinfo_lock); |
| 965 | batadv_ring_buffer_set(neigh_node->bat_iv.tq_recv, | 999 | batadv_ring_buffer_set(neigh_ifinfo->bat_iv.tq_recv, |
| 966 | &neigh_node->bat_iv.tq_index, | 1000 | &neigh_ifinfo->bat_iv.tq_index, |
| 967 | batadv_ogm_packet->tq); | 1001 | batadv_ogm_packet->tq); |
| 968 | tq_avg = batadv_ring_buffer_avg(neigh_node->bat_iv.tq_recv); | 1002 | tq_avg = batadv_ring_buffer_avg(neigh_ifinfo->bat_iv.tq_recv); |
| 969 | neigh_node->bat_iv.tq_avg = tq_avg; | 1003 | neigh_ifinfo->bat_iv.tq_avg = tq_avg; |
| 970 | spin_unlock_bh(&neigh_node->bat_iv.lq_update_lock); | 1004 | spin_unlock_bh(&neigh_node->ifinfo_lock); |
| 971 | 1005 | ||
| 972 | if (dup_status == BATADV_NO_DUP) { | 1006 | if (dup_status == BATADV_NO_DUP) { |
| 973 | orig_node->last_ttl = batadv_ogm_packet->ttl; | 1007 | orig_node->last_ttl = batadv_ogm_packet->ttl; |
| 974 | neigh_node->last_ttl = batadv_ogm_packet->ttl; | 1008 | neigh_ifinfo->last_ttl = batadv_ogm_packet->ttl; |
| 975 | } | 1009 | } |
| 976 | 1010 | ||
| 977 | /* if this neighbor already is our next hop there is nothing | 1011 | /* if this neighbor already is our next hop there is nothing |
| @@ -981,14 +1015,23 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv, | |||
| 981 | if (router == neigh_node) | 1015 | if (router == neigh_node) |
| 982 | goto out; | 1016 | goto out; |
| 983 | 1017 | ||
| 984 | /* if this neighbor does not offer a better TQ we won't consider it */ | 1018 | if (router) { |
| 985 | if (router && (router->bat_iv.tq_avg > neigh_node->bat_iv.tq_avg)) | 1019 | router_ifinfo = batadv_neigh_ifinfo_get(router, if_outgoing); |
| 986 | goto out; | 1020 | if (!router_ifinfo) |
| 1021 | goto out; | ||
| 1022 | |||
| 1023 | /* if this neighbor does not offer a better TQ we won't | ||
| 1024 | * consider it | ||
| 1025 | */ | ||
| 1026 | if (router_ifinfo->bat_iv.tq_avg > neigh_ifinfo->bat_iv.tq_avg) | ||
| 1027 | goto out; | ||
| 1028 | } | ||
| 987 | 1029 | ||
| 988 | /* if the TQ is the same and the link not more symmetric we | 1030 | /* if the TQ is the same and the link not more symmetric we |
| 989 | * won't consider it either | 1031 | * won't consider it either |
| 990 | */ | 1032 | */ |
| 991 | if (router && (neigh_node->bat_iv.tq_avg == router->bat_iv.tq_avg)) { | 1033 | if (router_ifinfo && |
| 1034 | (neigh_ifinfo->bat_iv.tq_avg == router_ifinfo->bat_iv.tq_avg)) { | ||
| 992 | orig_node_tmp = router->orig_node; | 1035 | orig_node_tmp = router->orig_node; |
| 993 | spin_lock_bh(&orig_node_tmp->bat_iv.ogm_cnt_lock); | 1036 | spin_lock_bh(&orig_node_tmp->bat_iv.ogm_cnt_lock); |
| 994 | if_num = router->if_incoming->if_num; | 1037 | if_num = router->if_incoming->if_num; |
| @@ -1015,15 +1058,31 @@ out: | |||
| 1015 | batadv_neigh_node_free_ref(neigh_node); | 1058 | batadv_neigh_node_free_ref(neigh_node); |
| 1016 | if (router) | 1059 | if (router) |
| 1017 | batadv_neigh_node_free_ref(router); | 1060 | batadv_neigh_node_free_ref(router); |
| 1061 | if (neigh_ifinfo) | ||
| 1062 | batadv_neigh_ifinfo_free_ref(neigh_ifinfo); | ||
| 1063 | if (router_ifinfo) | ||
| 1064 | batadv_neigh_ifinfo_free_ref(router_ifinfo); | ||
| 1018 | } | 1065 | } |
| 1019 | 1066 | ||
| 1067 | /** | ||
| 1068 | * batadv_iv_ogm_calc_tq - calculate tq for current received ogm packet | ||
| 1069 | * @orig_node: the orig node who originally emitted the ogm packet | ||
| 1070 | * @orig_neigh_node: the orig node struct of the neighbor who sent the packet | ||
| 1071 | * @batadv_ogm_packet: the ogm packet | ||
| 1072 | * @if_incoming: interface where the packet was received | ||
| 1073 | * @if_outgoing: interface for which the retransmission should be considered | ||
| 1074 | * | ||
| 1075 | * Returns 1 if the link can be considered bidirectional, 0 otherwise | ||
| 1076 | */ | ||
| 1020 | static int batadv_iv_ogm_calc_tq(struct batadv_orig_node *orig_node, | 1077 | static int batadv_iv_ogm_calc_tq(struct batadv_orig_node *orig_node, |
| 1021 | struct batadv_orig_node *orig_neigh_node, | 1078 | struct batadv_orig_node *orig_neigh_node, |
| 1022 | struct batadv_ogm_packet *batadv_ogm_packet, | 1079 | struct batadv_ogm_packet *batadv_ogm_packet, |
| 1023 | struct batadv_hard_iface *if_incoming) | 1080 | struct batadv_hard_iface *if_incoming, |
| 1081 | struct batadv_hard_iface *if_outgoing) | ||
| 1024 | { | 1082 | { |
| 1025 | struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface); | 1083 | struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface); |
| 1026 | struct batadv_neigh_node *neigh_node = NULL, *tmp_neigh_node; | 1084 | struct batadv_neigh_node *neigh_node = NULL, *tmp_neigh_node; |
| 1085 | struct batadv_neigh_ifinfo *neigh_ifinfo; | ||
| 1027 | uint8_t total_count; | 1086 | uint8_t total_count; |
| 1028 | uint8_t orig_eq_count, neigh_rq_count, neigh_rq_inv, tq_own; | 1087 | uint8_t orig_eq_count, neigh_rq_count, neigh_rq_inv, tq_own; |
| 1029 | unsigned int neigh_rq_inv_cube, neigh_rq_max_cube; | 1088 | unsigned int neigh_rq_inv_cube, neigh_rq_max_cube; |
| @@ -1068,7 +1127,13 @@ static int batadv_iv_ogm_calc_tq(struct batadv_orig_node *orig_node, | |||
| 1068 | spin_lock_bh(&orig_node->bat_iv.ogm_cnt_lock); | 1127 | spin_lock_bh(&orig_node->bat_iv.ogm_cnt_lock); |
| 1069 | if_num = if_incoming->if_num; | 1128 | if_num = if_incoming->if_num; |
| 1070 | orig_eq_count = orig_neigh_node->bat_iv.bcast_own_sum[if_num]; | 1129 | orig_eq_count = orig_neigh_node->bat_iv.bcast_own_sum[if_num]; |
| 1071 | neigh_rq_count = neigh_node->bat_iv.real_packet_count; | 1130 | neigh_ifinfo = batadv_neigh_ifinfo_new(neigh_node, if_outgoing); |
| 1131 | if (neigh_ifinfo) { | ||
| 1132 | neigh_rq_count = neigh_ifinfo->bat_iv.real_packet_count; | ||
| 1133 | batadv_neigh_ifinfo_free_ref(neigh_ifinfo); | ||
| 1134 | } else { | ||
| 1135 | neigh_rq_count = 0; | ||
| 1136 | } | ||
| 1072 | spin_unlock_bh(&orig_node->bat_iv.ogm_cnt_lock); | 1137 | spin_unlock_bh(&orig_node->bat_iv.ogm_cnt_lock); |
| 1073 | 1138 | ||
| 1074 | /* pay attention to not get a value bigger than 100 % */ | 1139 | /* pay attention to not get a value bigger than 100 % */ |
| @@ -1132,17 +1197,20 @@ out: | |||
| 1132 | * @ethhdr: ethernet header of the packet | 1197 | * @ethhdr: ethernet header of the packet |
| 1133 | * @batadv_ogm_packet: OGM packet to be considered | 1198 | * @batadv_ogm_packet: OGM packet to be considered |
| 1134 | * @if_incoming: interface on which the OGM packet was received | 1199 | * @if_incoming: interface on which the OGM packet was received |
| 1200 | * @if_outgoing: interface for which the retransmission should be considered | ||
| 1135 | * | 1201 | * |
| 1136 | * Returns duplicate status as enum batadv_dup_status | 1202 | * Returns duplicate status as enum batadv_dup_status |
| 1137 | */ | 1203 | */ |
| 1138 | static enum batadv_dup_status | 1204 | static enum batadv_dup_status |
| 1139 | batadv_iv_ogm_update_seqnos(const struct ethhdr *ethhdr, | 1205 | batadv_iv_ogm_update_seqnos(const struct ethhdr *ethhdr, |
| 1140 | const struct batadv_ogm_packet *batadv_ogm_packet, | 1206 | const struct batadv_ogm_packet *batadv_ogm_packet, |
| 1141 | const struct batadv_hard_iface *if_incoming) | 1207 | const struct batadv_hard_iface *if_incoming, |
| 1208 | struct batadv_hard_iface *if_outgoing) | ||
| 1142 | { | 1209 | { |
| 1143 | struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface); | 1210 | struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface); |
| 1144 | struct batadv_orig_node *orig_node; | 1211 | struct batadv_orig_node *orig_node; |
| 1145 | struct batadv_neigh_node *tmp_neigh_node; | 1212 | struct batadv_neigh_node *neigh_node; |
| 1213 | struct batadv_neigh_ifinfo *neigh_ifinfo; | ||
| 1146 | int is_dup; | 1214 | int is_dup; |
| 1147 | int32_t seq_diff; | 1215 | int32_t seq_diff; |
| 1148 | int need_update = 0; | 1216 | int need_update = 0; |
| @@ -1169,15 +1237,19 @@ batadv_iv_ogm_update_seqnos(const struct ethhdr *ethhdr, | |||
| 1169 | } | 1237 | } |
| 1170 | 1238 | ||
| 1171 | rcu_read_lock(); | 1239 | rcu_read_lock(); |
| 1172 | hlist_for_each_entry_rcu(tmp_neigh_node, | 1240 | hlist_for_each_entry_rcu(neigh_node, &orig_node->neigh_list, list) { |
| 1173 | &orig_node->neigh_list, list) { | 1241 | neigh_ifinfo = batadv_neigh_ifinfo_new(neigh_node, |
| 1174 | neigh_addr = tmp_neigh_node->addr; | 1242 | if_outgoing); |
| 1175 | is_dup = batadv_test_bit(tmp_neigh_node->bat_iv.real_bits, | 1243 | if (!neigh_ifinfo) |
| 1244 | continue; | ||
| 1245 | |||
| 1246 | neigh_addr = neigh_node->addr; | ||
| 1247 | is_dup = batadv_test_bit(neigh_ifinfo->bat_iv.real_bits, | ||
| 1176 | orig_node->last_real_seqno, | 1248 | orig_node->last_real_seqno, |
| 1177 | seqno); | 1249 | seqno); |
| 1178 | 1250 | ||
| 1179 | if (batadv_compare_eth(neigh_addr, ethhdr->h_source) && | 1251 | if (batadv_compare_eth(neigh_addr, ethhdr->h_source) && |
| 1180 | tmp_neigh_node->if_incoming == if_incoming) { | 1252 | neigh_node->if_incoming == if_incoming) { |
| 1181 | set_mark = 1; | 1253 | set_mark = 1; |
| 1182 | if (is_dup) | 1254 | if (is_dup) |
| 1183 | ret = BATADV_NEIGH_DUP; | 1255 | ret = BATADV_NEIGH_DUP; |
| @@ -1188,13 +1260,14 @@ batadv_iv_ogm_update_seqnos(const struct ethhdr *ethhdr, | |||
| 1188 | } | 1260 | } |
| 1189 | 1261 | ||
| 1190 | /* if the window moved, set the update flag. */ | 1262 | /* if the window moved, set the update flag. */ |
| 1191 | bitmap = tmp_neigh_node->bat_iv.real_bits; | 1263 | bitmap = neigh_ifinfo->bat_iv.real_bits; |
| 1192 | need_update |= batadv_bit_get_packet(bat_priv, bitmap, | 1264 | need_update |= batadv_bit_get_packet(bat_priv, bitmap, |
| 1193 | seq_diff, set_mark); | 1265 | seq_diff, set_mark); |
| 1194 | 1266 | ||
| 1195 | packet_count = bitmap_weight(tmp_neigh_node->bat_iv.real_bits, | 1267 | packet_count = bitmap_weight(bitmap, |
| 1196 | BATADV_TQ_LOCAL_WINDOW_SIZE); | 1268 | BATADV_TQ_LOCAL_WINDOW_SIZE); |
| 1197 | tmp_neigh_node->bat_iv.real_packet_count = packet_count; | 1269 | neigh_ifinfo->bat_iv.real_packet_count = packet_count; |
| 1270 | batadv_neigh_ifinfo_free_ref(neigh_ifinfo); | ||
| 1198 | } | 1271 | } |
| 1199 | rcu_read_unlock(); | 1272 | rcu_read_unlock(); |
| 1200 | 1273 | ||
| @@ -1221,6 +1294,7 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr, | |||
| 1221 | struct batadv_orig_node *orig_neigh_node, *orig_node, *orig_node_tmp; | 1294 | struct batadv_orig_node *orig_neigh_node, *orig_node, *orig_node_tmp; |
| 1222 | struct batadv_neigh_node *router = NULL, *router_router = NULL; | 1295 | struct batadv_neigh_node *router = NULL, *router_router = NULL; |
| 1223 | struct batadv_neigh_node *orig_neigh_router = NULL; | 1296 | struct batadv_neigh_node *orig_neigh_router = NULL; |
| 1297 | struct batadv_neigh_ifinfo *router_ifinfo = NULL; | ||
| 1224 | int has_directlink_flag; | 1298 | int has_directlink_flag; |
| 1225 | int is_my_addr = 0, is_my_orig = 0, is_my_oldorig = 0; | 1299 | int is_my_addr = 0, is_my_orig = 0, is_my_oldorig = 0; |
| 1226 | int is_bidirect; | 1300 | int is_bidirect; |
| @@ -1353,7 +1427,8 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr, | |||
| 1353 | return; | 1427 | return; |
| 1354 | 1428 | ||
| 1355 | dup_status = batadv_iv_ogm_update_seqnos(ethhdr, batadv_ogm_packet, | 1429 | dup_status = batadv_iv_ogm_update_seqnos(ethhdr, batadv_ogm_packet, |
| 1356 | if_incoming); | 1430 | if_incoming, |
| 1431 | BATADV_IF_DEFAULT); | ||
| 1357 | 1432 | ||
| 1358 | if (dup_status == BATADV_PROTECTED) { | 1433 | if (dup_status == BATADV_PROTECTED) { |
| 1359 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, | 1434 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, |
| @@ -1372,9 +1447,11 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr, | |||
| 1372 | if (router) { | 1447 | if (router) { |
| 1373 | orig_node_tmp = router->orig_node; | 1448 | orig_node_tmp = router->orig_node; |
| 1374 | router_router = batadv_orig_node_get_router(orig_node_tmp); | 1449 | router_router = batadv_orig_node_get_router(orig_node_tmp); |
| 1450 | router_ifinfo = batadv_neigh_ifinfo_get(router, | ||
| 1451 | BATADV_IF_DEFAULT); | ||
| 1375 | } | 1452 | } |
| 1376 | 1453 | ||
| 1377 | if ((router && router->bat_iv.tq_avg != 0) && | 1454 | if ((router && router_ifinfo->bat_iv.tq_avg != 0) && |
| 1378 | (batadv_compare_eth(router->addr, ethhdr->h_source))) | 1455 | (batadv_compare_eth(router->addr, ethhdr->h_source))) |
| 1379 | is_from_best_next_hop = true; | 1456 | is_from_best_next_hop = true; |
| 1380 | 1457 | ||
| @@ -1420,7 +1497,8 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr, | |||
| 1420 | } | 1497 | } |
| 1421 | 1498 | ||
| 1422 | is_bidirect = batadv_iv_ogm_calc_tq(orig_node, orig_neigh_node, | 1499 | is_bidirect = batadv_iv_ogm_calc_tq(orig_node, orig_neigh_node, |
| 1423 | batadv_ogm_packet, if_incoming); | 1500 | batadv_ogm_packet, if_incoming, |
| 1501 | BATADV_IF_DEFAULT); | ||
| 1424 | 1502 | ||
| 1425 | /* update ranking if it is not a duplicate or has the same | 1503 | /* update ranking if it is not a duplicate or has the same |
| 1426 | * seqno and similar ttl as the non-duplicate | 1504 | * seqno and similar ttl as the non-duplicate |
| @@ -1431,7 +1509,8 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr, | |||
| 1431 | (sameseq && similar_ttl))) | 1509 | (sameseq && similar_ttl))) |
| 1432 | batadv_iv_ogm_orig_update(bat_priv, orig_node, ethhdr, | 1510 | batadv_iv_ogm_orig_update(bat_priv, orig_node, ethhdr, |
| 1433 | batadv_ogm_packet, if_incoming, | 1511 | batadv_ogm_packet, if_incoming, |
| 1434 | tt_buff, dup_status); | 1512 | BATADV_IF_DEFAULT, tt_buff, |
| 1513 | dup_status); | ||
| 1435 | 1514 | ||
| 1436 | /* is single hop (direct) neighbor */ | 1515 | /* is single hop (direct) neighbor */ |
| 1437 | if (is_single_hop_neigh) { | 1516 | if (is_single_hop_neigh) { |
| @@ -1527,6 +1606,34 @@ static int batadv_iv_ogm_receive(struct sk_buff *skb, | |||
| 1527 | return NET_RX_SUCCESS; | 1606 | return NET_RX_SUCCESS; |
| 1528 | } | 1607 | } |
| 1529 | 1608 | ||
| 1609 | /* batadv_iv_ogm_orig_print_neigh - print neighbors for the originator table | ||
| 1610 | * @orig_node: the orig_node for which the neighbors are printed | ||
| 1611 | * @if_outgoing: outgoing interface for these entries | ||
| 1612 | * @seq: debugfs table seq_file struct | ||
| 1613 | * | ||
| 1614 | * Must be called while holding an rcu lock. | ||
| 1615 | */ | ||
| 1616 | static void | ||
| 1617 | batadv_iv_ogm_orig_print_neigh(struct batadv_orig_node *orig_node, | ||
| 1618 | struct batadv_hard_iface *if_outgoing, | ||
| 1619 | struct seq_file *seq) | ||
| 1620 | { | ||
| 1621 | struct batadv_neigh_node *neigh_node; | ||
| 1622 | struct batadv_neigh_ifinfo *n_ifinfo; | ||
| 1623 | |||
| 1624 | hlist_for_each_entry_rcu(neigh_node, &orig_node->neigh_list, list) { | ||
| 1625 | n_ifinfo = batadv_neigh_ifinfo_get(neigh_node, if_outgoing); | ||
| 1626 | if (!n_ifinfo) | ||
| 1627 | continue; | ||
| 1628 | |||
| 1629 | seq_printf(seq, " %pM (%3i)", | ||
| 1630 | neigh_node->addr, | ||
| 1631 | n_ifinfo->bat_iv.tq_avg); | ||
| 1632 | |||
| 1633 | batadv_neigh_ifinfo_free_ref(n_ifinfo); | ||
| 1634 | } | ||
| 1635 | } | ||
| 1636 | |||
| 1530 | /** | 1637 | /** |
| 1531 | * batadv_iv_ogm_orig_print - print the originator table | 1638 | * batadv_iv_ogm_orig_print - print the originator table |
| 1532 | * @bat_priv: the bat priv with all the soft interface information | 1639 | * @bat_priv: the bat priv with all the soft interface information |
| @@ -1535,10 +1642,11 @@ static int batadv_iv_ogm_receive(struct sk_buff *skb, | |||
| 1535 | static void batadv_iv_ogm_orig_print(struct batadv_priv *bat_priv, | 1642 | static void batadv_iv_ogm_orig_print(struct batadv_priv *bat_priv, |
| 1536 | struct seq_file *seq) | 1643 | struct seq_file *seq) |
| 1537 | { | 1644 | { |
| 1538 | struct batadv_neigh_node *neigh_node, *neigh_node_tmp; | 1645 | struct batadv_neigh_node *neigh_node; |
| 1539 | struct batadv_hashtable *hash = bat_priv->orig_hash; | 1646 | struct batadv_hashtable *hash = bat_priv->orig_hash; |
| 1540 | int last_seen_msecs, last_seen_secs; | 1647 | int last_seen_msecs, last_seen_secs; |
| 1541 | struct batadv_orig_node *orig_node; | 1648 | struct batadv_orig_node *orig_node; |
| 1649 | struct batadv_neigh_ifinfo *n_ifinfo; | ||
| 1542 | unsigned long last_seen_jiffies; | 1650 | unsigned long last_seen_jiffies; |
| 1543 | struct hlist_head *head; | 1651 | struct hlist_head *head; |
| 1544 | int batman_count = 0; | 1652 | int batman_count = 0; |
| @@ -1557,7 +1665,12 @@ static void batadv_iv_ogm_orig_print(struct batadv_priv *bat_priv, | |||
| 1557 | if (!neigh_node) | 1665 | if (!neigh_node) |
| 1558 | continue; | 1666 | continue; |
| 1559 | 1667 | ||
| 1560 | if (neigh_node->bat_iv.tq_avg == 0) | 1668 | n_ifinfo = batadv_neigh_ifinfo_get(neigh_node, |
| 1669 | BATADV_IF_DEFAULT); | ||
| 1670 | if (!n_ifinfo) | ||
| 1671 | goto next; | ||
| 1672 | |||
| 1673 | if (n_ifinfo->bat_iv.tq_avg == 0) | ||
| 1561 | goto next; | 1674 | goto next; |
| 1562 | 1675 | ||
| 1563 | last_seen_jiffies = jiffies - orig_node->last_seen; | 1676 | last_seen_jiffies = jiffies - orig_node->last_seen; |
| @@ -1567,22 +1680,19 @@ static void batadv_iv_ogm_orig_print(struct batadv_priv *bat_priv, | |||
| 1567 | 1680 | ||
| 1568 | seq_printf(seq, "%pM %4i.%03is (%3i) %pM [%10s]:", | 1681 | seq_printf(seq, "%pM %4i.%03is (%3i) %pM [%10s]:", |
| 1569 | orig_node->orig, last_seen_secs, | 1682 | orig_node->orig, last_seen_secs, |
| 1570 | last_seen_msecs, neigh_node->bat_iv.tq_avg, | 1683 | last_seen_msecs, n_ifinfo->bat_iv.tq_avg, |
| 1571 | neigh_node->addr, | 1684 | neigh_node->addr, |
| 1572 | neigh_node->if_incoming->net_dev->name); | 1685 | neigh_node->if_incoming->net_dev->name); |
| 1573 | 1686 | ||
| 1574 | hlist_for_each_entry_rcu(neigh_node_tmp, | 1687 | batadv_iv_ogm_orig_print_neigh(orig_node, |
| 1575 | &orig_node->neigh_list, list) { | 1688 | BATADV_IF_DEFAULT, seq); |
| 1576 | seq_printf(seq, " %pM (%3i)", | ||
| 1577 | neigh_node_tmp->addr, | ||
| 1578 | neigh_node_tmp->bat_iv.tq_avg); | ||
| 1579 | } | ||
| 1580 | |||
| 1581 | seq_puts(seq, "\n"); | 1689 | seq_puts(seq, "\n"); |
| 1582 | batman_count++; | 1690 | batman_count++; |
| 1583 | 1691 | ||
| 1584 | next: | 1692 | next: |
| 1585 | batadv_neigh_node_free_ref(neigh_node); | 1693 | batadv_neigh_node_free_ref(neigh_node); |
| 1694 | if (n_ifinfo) | ||
| 1695 | batadv_neigh_ifinfo_free_ref(n_ifinfo); | ||
| 1586 | } | 1696 | } |
| 1587 | rcu_read_unlock(); | 1697 | rcu_read_unlock(); |
| 1588 | } | 1698 | } |
| @@ -1594,37 +1704,84 @@ next: | |||
| 1594 | /** | 1704 | /** |
| 1595 | * batadv_iv_ogm_neigh_cmp - compare the metrics of two neighbors | 1705 | * batadv_iv_ogm_neigh_cmp - compare the metrics of two neighbors |
| 1596 | * @neigh1: the first neighbor object of the comparison | 1706 | * @neigh1: the first neighbor object of the comparison |
| 1707 | * @if_outgoing1: outgoing interface for the first neighbor | ||
| 1597 | * @neigh2: the second neighbor object of the comparison | 1708 | * @neigh2: the second neighbor object of the comparison |
| 1709 | * @if_outgoing2: outgoing interface for the second neighbor | ||
| 1598 | * | 1710 | * |
| 1599 | * Returns a value less, equal to or greater than 0 if the metric via neigh1 is | 1711 | * Returns a value less, equal to or greater than 0 if the metric via neigh1 is |
| 1600 | * lower, the same as or higher than the metric via neigh2 | 1712 | * lower, the same as or higher than the metric via neigh2 |
| 1601 | */ | 1713 | */ |
| 1602 | static int batadv_iv_ogm_neigh_cmp(struct batadv_neigh_node *neigh1, | 1714 | static int batadv_iv_ogm_neigh_cmp(struct batadv_neigh_node *neigh1, |
| 1603 | struct batadv_neigh_node *neigh2) | 1715 | struct batadv_hard_iface *if_outgoing1, |
| 1716 | struct batadv_neigh_node *neigh2, | ||
| 1717 | struct batadv_hard_iface *if_outgoing2) | ||
| 1604 | { | 1718 | { |
| 1719 | struct batadv_neigh_ifinfo *neigh1_ifinfo, *neigh2_ifinfo; | ||
| 1605 | uint8_t tq1, tq2; | 1720 | uint8_t tq1, tq2; |
| 1721 | int diff; | ||
| 1722 | |||
| 1723 | neigh1_ifinfo = batadv_neigh_ifinfo_get(neigh1, if_outgoing1); | ||
| 1724 | neigh2_ifinfo = batadv_neigh_ifinfo_get(neigh2, if_outgoing2); | ||
| 1606 | 1725 | ||
| 1607 | tq1 = neigh1->bat_iv.tq_avg; | 1726 | if (!neigh1_ifinfo || !neigh2_ifinfo) { |
| 1608 | tq2 = neigh2->bat_iv.tq_avg; | 1727 | diff = 0; |
| 1728 | goto out; | ||
| 1729 | } | ||
| 1609 | 1730 | ||
| 1610 | return tq1 - tq2; | 1731 | tq1 = neigh1_ifinfo->bat_iv.tq_avg; |
| 1732 | tq2 = neigh2_ifinfo->bat_iv.tq_avg; | ||
| 1733 | diff = tq1 - tq2; | ||
| 1734 | |||
| 1735 | out: | ||
| 1736 | if (neigh1_ifinfo) | ||
| 1737 | batadv_neigh_ifinfo_free_ref(neigh1_ifinfo); | ||
| 1738 | if (neigh2_ifinfo) | ||
| 1739 | batadv_neigh_ifinfo_free_ref(neigh2_ifinfo); | ||
| 1740 | |||
| 1741 | return diff; | ||
| 1611 | } | 1742 | } |
| 1612 | 1743 | ||
| 1613 | /** | 1744 | /** |
| 1614 | * batadv_iv_ogm_neigh_is_eob - check if neigh1 is equally good or better than | 1745 | * batadv_iv_ogm_neigh_is_eob - check if neigh1 is equally good or better than |
| 1615 | * neigh2 from the metric prospective | 1746 | * neigh2 from the metric prospective |
| 1616 | * @neigh1: the first neighbor object of the comparison | 1747 | * @neigh1: the first neighbor object of the comparison |
| 1748 | * @if_outgoing: outgoing interface for the first neighbor | ||
| 1617 | * @neigh2: the second neighbor object of the comparison | 1749 | * @neigh2: the second neighbor object of the comparison |
| 1618 | * | 1750 | * @if_outgoing2: outgoing interface for the second neighbor |
| 1619 | * Returns true if the metric via neigh1 is equally good or better than the | 1751 | |
| 1620 | * metric via neigh2, false otherwise. | 1752 | * Returns true if the metric via neigh1 is equally good or better than |
| 1753 | * the metric via neigh2, false otherwise. | ||
| 1621 | */ | 1754 | */ |
| 1622 | static bool batadv_iv_ogm_neigh_is_eob(struct batadv_neigh_node *neigh1, | 1755 | static bool |
| 1623 | struct batadv_neigh_node *neigh2) | 1756 | batadv_iv_ogm_neigh_is_eob(struct batadv_neigh_node *neigh1, |
| 1757 | struct batadv_hard_iface *if_outgoing1, | ||
| 1758 | struct batadv_neigh_node *neigh2, | ||
| 1759 | struct batadv_hard_iface *if_outgoing2) | ||
| 1624 | { | 1760 | { |
| 1625 | int diff = batadv_iv_ogm_neigh_cmp(neigh1, neigh2); | 1761 | struct batadv_neigh_ifinfo *neigh1_ifinfo, *neigh2_ifinfo; |
| 1762 | uint8_t tq1, tq2; | ||
| 1763 | bool ret; | ||
| 1626 | 1764 | ||
| 1627 | return diff > -BATADV_TQ_SIMILARITY_THRESHOLD; | 1765 | neigh1_ifinfo = batadv_neigh_ifinfo_get(neigh1, if_outgoing1); |
| 1766 | neigh2_ifinfo = batadv_neigh_ifinfo_get(neigh2, if_outgoing2); | ||
| 1767 | |||
| 1768 | /* we can't say that the metric is better */ | ||
| 1769 | if (!neigh1_ifinfo || !neigh2_ifinfo) { | ||
| 1770 | ret = false; | ||
| 1771 | goto out; | ||
| 1772 | } | ||
| 1773 | |||
| 1774 | tq1 = neigh1_ifinfo->bat_iv.tq_avg; | ||
| 1775 | tq2 = neigh2_ifinfo->bat_iv.tq_avg; | ||
| 1776 | ret = (tq1 - tq2) > -BATADV_TQ_SIMILARITY_THRESHOLD; | ||
| 1777 | |||
| 1778 | out: | ||
| 1779 | if (neigh1_ifinfo) | ||
| 1780 | batadv_neigh_ifinfo_free_ref(neigh1_ifinfo); | ||
| 1781 | if (neigh2_ifinfo) | ||
| 1782 | batadv_neigh_ifinfo_free_ref(neigh2_ifinfo); | ||
| 1783 | |||
| 1784 | return ret; | ||
| 1628 | } | 1785 | } |
| 1629 | 1786 | ||
| 1630 | static struct batadv_algo_ops batadv_batman_iv __read_mostly = { | 1787 | static struct batadv_algo_ops batadv_batman_iv __read_mostly = { |
diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c index 4150a641c52e..4e8f5b1eedfc 100644 --- a/net/batman-adv/gateway_client.c +++ b/net/batman-adv/gateway_client.c | |||
| @@ -129,6 +129,7 @@ static struct batadv_gw_node * | |||
| 129 | batadv_gw_get_best_gw_node(struct batadv_priv *bat_priv) | 129 | batadv_gw_get_best_gw_node(struct batadv_priv *bat_priv) |
| 130 | { | 130 | { |
| 131 | struct batadv_neigh_node *router; | 131 | struct batadv_neigh_node *router; |
| 132 | struct batadv_neigh_ifinfo *router_ifinfo; | ||
| 132 | struct batadv_gw_node *gw_node, *curr_gw = NULL; | 133 | struct batadv_gw_node *gw_node, *curr_gw = NULL; |
| 133 | uint32_t max_gw_factor = 0, tmp_gw_factor = 0; | 134 | uint32_t max_gw_factor = 0, tmp_gw_factor = 0; |
| 134 | uint32_t gw_divisor; | 135 | uint32_t gw_divisor; |
| @@ -149,10 +150,15 @@ batadv_gw_get_best_gw_node(struct batadv_priv *bat_priv) | |||
| 149 | if (!router) | 150 | if (!router) |
| 150 | continue; | 151 | continue; |
| 151 | 152 | ||
| 153 | router_ifinfo = batadv_neigh_ifinfo_get(router, | ||
| 154 | BATADV_IF_DEFAULT); | ||
| 155 | if (!router_ifinfo) | ||
| 156 | goto next; | ||
| 157 | |||
| 152 | if (!atomic_inc_not_zero(&gw_node->refcount)) | 158 | if (!atomic_inc_not_zero(&gw_node->refcount)) |
| 153 | goto next; | 159 | goto next; |
| 154 | 160 | ||
| 155 | tq_avg = router->bat_iv.tq_avg; | 161 | tq_avg = router_ifinfo->bat_iv.tq_avg; |
| 156 | 162 | ||
| 157 | switch (atomic_read(&bat_priv->gw_sel_class)) { | 163 | switch (atomic_read(&bat_priv->gw_sel_class)) { |
| 158 | case 1: /* fast connection */ | 164 | case 1: /* fast connection */ |
| @@ -197,6 +203,8 @@ batadv_gw_get_best_gw_node(struct batadv_priv *bat_priv) | |||
| 197 | 203 | ||
| 198 | next: | 204 | next: |
| 199 | batadv_neigh_node_free_ref(router); | 205 | batadv_neigh_node_free_ref(router); |
| 206 | if (router_ifinfo) | ||
| 207 | batadv_neigh_ifinfo_free_ref(router_ifinfo); | ||
| 200 | } | 208 | } |
| 201 | rcu_read_unlock(); | 209 | rcu_read_unlock(); |
| 202 | 210 | ||
| @@ -239,6 +247,7 @@ void batadv_gw_election(struct batadv_priv *bat_priv) | |||
| 239 | { | 247 | { |
| 240 | struct batadv_gw_node *curr_gw = NULL, *next_gw = NULL; | 248 | struct batadv_gw_node *curr_gw = NULL, *next_gw = NULL; |
| 241 | struct batadv_neigh_node *router = NULL; | 249 | struct batadv_neigh_node *router = NULL; |
| 250 | struct batadv_neigh_ifinfo *router_ifinfo = NULL; | ||
| 242 | char gw_addr[18] = { '\0' }; | 251 | char gw_addr[18] = { '\0' }; |
| 243 | 252 | ||
| 244 | if (atomic_read(&bat_priv->gw_mode) != BATADV_GW_MODE_CLIENT) | 253 | if (atomic_read(&bat_priv->gw_mode) != BATADV_GW_MODE_CLIENT) |
| @@ -262,6 +271,13 @@ void batadv_gw_election(struct batadv_priv *bat_priv) | |||
| 262 | batadv_gw_reselect(bat_priv); | 271 | batadv_gw_reselect(bat_priv); |
| 263 | goto out; | 272 | goto out; |
| 264 | } | 273 | } |
| 274 | |||
| 275 | router_ifinfo = batadv_neigh_ifinfo_get(router, | ||
| 276 | BATADV_IF_DEFAULT); | ||
| 277 | if (!router_ifinfo) { | ||
| 278 | batadv_gw_reselect(bat_priv); | ||
| 279 | goto out; | ||
| 280 | } | ||
| 265 | } | 281 | } |
| 266 | 282 | ||
| 267 | if ((curr_gw) && (!next_gw)) { | 283 | if ((curr_gw) && (!next_gw)) { |
| @@ -276,7 +292,8 @@ void batadv_gw_election(struct batadv_priv *bat_priv) | |||
| 276 | next_gw->bandwidth_down / 10, | 292 | next_gw->bandwidth_down / 10, |
| 277 | next_gw->bandwidth_down % 10, | 293 | next_gw->bandwidth_down % 10, |
| 278 | next_gw->bandwidth_up / 10, | 294 | next_gw->bandwidth_up / 10, |
| 279 | next_gw->bandwidth_up % 10, router->bat_iv.tq_avg); | 295 | next_gw->bandwidth_up % 10, |
| 296 | router_ifinfo->bat_iv.tq_avg); | ||
| 280 | batadv_throw_uevent(bat_priv, BATADV_UEV_GW, BATADV_UEV_ADD, | 297 | batadv_throw_uevent(bat_priv, BATADV_UEV_GW, BATADV_UEV_ADD, |
| 281 | gw_addr); | 298 | gw_addr); |
| 282 | } else { | 299 | } else { |
| @@ -286,7 +303,8 @@ void batadv_gw_election(struct batadv_priv *bat_priv) | |||
| 286 | next_gw->bandwidth_down / 10, | 303 | next_gw->bandwidth_down / 10, |
| 287 | next_gw->bandwidth_down % 10, | 304 | next_gw->bandwidth_down % 10, |
| 288 | next_gw->bandwidth_up / 10, | 305 | next_gw->bandwidth_up / 10, |
| 289 | next_gw->bandwidth_up % 10, router->bat_iv.tq_avg); | 306 | next_gw->bandwidth_up % 10, |
| 307 | router_ifinfo->bat_iv.tq_avg); | ||
| 290 | batadv_throw_uevent(bat_priv, BATADV_UEV_GW, BATADV_UEV_CHANGE, | 308 | batadv_throw_uevent(bat_priv, BATADV_UEV_GW, BATADV_UEV_CHANGE, |
| 291 | gw_addr); | 309 | gw_addr); |
| 292 | } | 310 | } |
| @@ -300,11 +318,15 @@ out: | |||
| 300 | batadv_gw_node_free_ref(next_gw); | 318 | batadv_gw_node_free_ref(next_gw); |
| 301 | if (router) | 319 | if (router) |
| 302 | batadv_neigh_node_free_ref(router); | 320 | batadv_neigh_node_free_ref(router); |
| 321 | if (router_ifinfo) | ||
| 322 | batadv_neigh_ifinfo_free_ref(router_ifinfo); | ||
| 303 | } | 323 | } |
| 304 | 324 | ||
| 305 | void batadv_gw_check_election(struct batadv_priv *bat_priv, | 325 | void batadv_gw_check_election(struct batadv_priv *bat_priv, |
| 306 | struct batadv_orig_node *orig_node) | 326 | struct batadv_orig_node *orig_node) |
| 307 | { | 327 | { |
| 328 | struct batadv_neigh_ifinfo *router_orig_tq = NULL; | ||
| 329 | struct batadv_neigh_ifinfo *router_gw_tq = NULL; | ||
| 308 | struct batadv_orig_node *curr_gw_orig; | 330 | struct batadv_orig_node *curr_gw_orig; |
| 309 | struct batadv_neigh_node *router_gw = NULL, *router_orig = NULL; | 331 | struct batadv_neigh_node *router_gw = NULL, *router_orig = NULL; |
| 310 | uint8_t gw_tq_avg, orig_tq_avg; | 332 | uint8_t gw_tq_avg, orig_tq_avg; |
| @@ -317,6 +339,11 @@ void batadv_gw_check_election(struct batadv_priv *bat_priv, | |||
| 317 | if (!router_gw) | 339 | if (!router_gw) |
| 318 | goto reselect; | 340 | goto reselect; |
| 319 | 341 | ||
| 342 | router_gw_tq = batadv_neigh_ifinfo_get(router_gw, | ||
| 343 | BATADV_IF_DEFAULT); | ||
| 344 | if (!router_gw_tq) | ||
| 345 | goto reselect; | ||
| 346 | |||
| 320 | /* this node already is the gateway */ | 347 | /* this node already is the gateway */ |
| 321 | if (curr_gw_orig == orig_node) | 348 | if (curr_gw_orig == orig_node) |
| 322 | goto out; | 349 | goto out; |
| @@ -325,8 +352,13 @@ void batadv_gw_check_election(struct batadv_priv *bat_priv, | |||
| 325 | if (!router_orig) | 352 | if (!router_orig) |
| 326 | goto out; | 353 | goto out; |
| 327 | 354 | ||
| 328 | gw_tq_avg = router_gw->bat_iv.tq_avg; | 355 | router_orig_tq = batadv_neigh_ifinfo_get(router_orig, |
| 329 | orig_tq_avg = router_orig->bat_iv.tq_avg; | 356 | BATADV_IF_DEFAULT); |
| 357 | if (!router_orig_tq) | ||
| 358 | goto out; | ||
| 359 | |||
| 360 | gw_tq_avg = router_gw_tq->bat_iv.tq_avg; | ||
| 361 | orig_tq_avg = router_orig_tq->bat_iv.tq_avg; | ||
| 330 | 362 | ||
| 331 | /* the TQ value has to be better */ | 363 | /* the TQ value has to be better */ |
| 332 | if (orig_tq_avg < gw_tq_avg) | 364 | if (orig_tq_avg < gw_tq_avg) |
| @@ -352,6 +384,10 @@ out: | |||
| 352 | batadv_neigh_node_free_ref(router_gw); | 384 | batadv_neigh_node_free_ref(router_gw); |
| 353 | if (router_orig) | 385 | if (router_orig) |
| 354 | batadv_neigh_node_free_ref(router_orig); | 386 | batadv_neigh_node_free_ref(router_orig); |
| 387 | if (router_gw_tq) | ||
| 388 | batadv_neigh_ifinfo_free_ref(router_gw_tq); | ||
| 389 | if (router_orig_tq) | ||
| 390 | batadv_neigh_ifinfo_free_ref(router_orig_tq); | ||
| 355 | 391 | ||
| 356 | return; | 392 | return; |
| 357 | } | 393 | } |
| @@ -537,28 +573,36 @@ static int batadv_write_buffer_text(struct batadv_priv *bat_priv, | |||
| 537 | { | 573 | { |
| 538 | struct batadv_gw_node *curr_gw; | 574 | struct batadv_gw_node *curr_gw; |
| 539 | struct batadv_neigh_node *router; | 575 | struct batadv_neigh_node *router; |
| 576 | struct batadv_neigh_ifinfo *router_ifinfo = NULL; | ||
| 540 | int ret = -1; | 577 | int ret = -1; |
| 541 | 578 | ||
| 542 | router = batadv_orig_node_get_router(gw_node->orig_node); | 579 | router = batadv_orig_node_get_router(gw_node->orig_node); |
| 543 | if (!router) | 580 | if (!router) |
| 544 | goto out; | 581 | goto out; |
| 545 | 582 | ||
| 583 | router_ifinfo = batadv_neigh_ifinfo_get(router, BATADV_IF_DEFAULT); | ||
| 584 | if (!router_ifinfo) | ||
| 585 | goto out; | ||
| 586 | |||
| 546 | curr_gw = batadv_gw_get_selected_gw_node(bat_priv); | 587 | curr_gw = batadv_gw_get_selected_gw_node(bat_priv); |
| 547 | 588 | ||
| 548 | ret = seq_printf(seq, "%s %pM (%3i) %pM [%10s]: %u.%u/%u.%u MBit\n", | 589 | ret = seq_printf(seq, "%s %pM (%3i) %pM [%10s]: %u.%u/%u.%u MBit\n", |
| 549 | (curr_gw == gw_node ? "=>" : " "), | 590 | (curr_gw == gw_node ? "=>" : " "), |
| 550 | gw_node->orig_node->orig, | 591 | gw_node->orig_node->orig, |
| 551 | router->bat_iv.tq_avg, router->addr, | 592 | router_ifinfo->bat_iv.tq_avg, router->addr, |
| 552 | router->if_incoming->net_dev->name, | 593 | router->if_incoming->net_dev->name, |
| 553 | gw_node->bandwidth_down / 10, | 594 | gw_node->bandwidth_down / 10, |
| 554 | gw_node->bandwidth_down % 10, | 595 | gw_node->bandwidth_down % 10, |
| 555 | gw_node->bandwidth_up / 10, | 596 | gw_node->bandwidth_up / 10, |
| 556 | gw_node->bandwidth_up % 10); | 597 | gw_node->bandwidth_up % 10); |
| 557 | 598 | ||
| 558 | batadv_neigh_node_free_ref(router); | ||
| 559 | if (curr_gw) | 599 | if (curr_gw) |
| 560 | batadv_gw_node_free_ref(curr_gw); | 600 | batadv_gw_node_free_ref(curr_gw); |
| 561 | out: | 601 | out: |
| 602 | if (router_ifinfo) | ||
| 603 | batadv_neigh_ifinfo_free_ref(router_ifinfo); | ||
| 604 | if (router) | ||
| 605 | batadv_neigh_node_free_ref(router); | ||
| 562 | return ret; | 606 | return ret; |
| 563 | } | 607 | } |
| 564 | 608 | ||
| @@ -746,6 +790,7 @@ bool batadv_gw_out_of_range(struct batadv_priv *bat_priv, | |||
| 746 | struct batadv_neigh_node *neigh_curr = NULL, *neigh_old = NULL; | 790 | struct batadv_neigh_node *neigh_curr = NULL, *neigh_old = NULL; |
| 747 | struct batadv_orig_node *orig_dst_node = NULL; | 791 | struct batadv_orig_node *orig_dst_node = NULL; |
| 748 | struct batadv_gw_node *gw_node = NULL, *curr_gw = NULL; | 792 | struct batadv_gw_node *gw_node = NULL, *curr_gw = NULL; |
| 793 | struct batadv_neigh_ifinfo *curr_ifinfo, *old_ifinfo; | ||
| 749 | struct ethhdr *ethhdr = (struct ethhdr *)skb->data; | 794 | struct ethhdr *ethhdr = (struct ethhdr *)skb->data; |
| 750 | bool out_of_range = false; | 795 | bool out_of_range = false; |
| 751 | uint8_t curr_tq_avg; | 796 | uint8_t curr_tq_avg; |
| @@ -787,7 +832,14 @@ bool batadv_gw_out_of_range(struct batadv_priv *bat_priv, | |||
| 787 | if (!neigh_curr) | 832 | if (!neigh_curr) |
| 788 | goto out; | 833 | goto out; |
| 789 | 834 | ||
| 790 | curr_tq_avg = neigh_curr->bat_iv.tq_avg; | 835 | curr_ifinfo = batadv_neigh_ifinfo_get(neigh_curr, |
| 836 | BATADV_IF_DEFAULT); | ||
| 837 | if (!curr_ifinfo) | ||
| 838 | goto out; | ||
| 839 | |||
| 840 | curr_tq_avg = curr_ifinfo->bat_iv.tq_avg; | ||
| 841 | batadv_neigh_ifinfo_free_ref(curr_ifinfo); | ||
| 842 | |||
| 791 | break; | 843 | break; |
| 792 | case BATADV_GW_MODE_OFF: | 844 | case BATADV_GW_MODE_OFF: |
| 793 | default: | 845 | default: |
| @@ -798,8 +850,13 @@ bool batadv_gw_out_of_range(struct batadv_priv *bat_priv, | |||
| 798 | if (!neigh_old) | 850 | if (!neigh_old) |
| 799 | goto out; | 851 | goto out; |
| 800 | 852 | ||
| 801 | if (curr_tq_avg - neigh_old->bat_iv.tq_avg > BATADV_GW_THRESHOLD) | 853 | old_ifinfo = batadv_neigh_ifinfo_get(neigh_old, BATADV_IF_DEFAULT); |
| 854 | if (!old_ifinfo) | ||
| 855 | goto out; | ||
| 856 | |||
| 857 | if ((curr_tq_avg - old_ifinfo->bat_iv.tq_avg) > BATADV_GW_THRESHOLD) | ||
| 802 | out_of_range = true; | 858 | out_of_range = true; |
| 859 | batadv_neigh_ifinfo_free_ref(old_ifinfo); | ||
| 803 | 860 | ||
| 804 | out: | 861 | out: |
| 805 | if (orig_dst_node) | 862 | if (orig_dst_node) |
diff --git a/net/batman-adv/hard-interface.h b/net/batman-adv/hard-interface.h index d8ca8ac829c1..8d4304b74b5d 100644 --- a/net/batman-adv/hard-interface.h +++ b/net/batman-adv/hard-interface.h | |||
| @@ -51,6 +51,11 @@ int batadv_hardif_min_mtu(struct net_device *soft_iface); | |||
| 51 | void batadv_update_min_mtu(struct net_device *soft_iface); | 51 | void batadv_update_min_mtu(struct net_device *soft_iface); |
| 52 | void batadv_hardif_free_rcu(struct rcu_head *rcu); | 52 | void batadv_hardif_free_rcu(struct rcu_head *rcu); |
| 53 | 53 | ||
| 54 | /** | ||
| 55 | * batadv_hardif_free_ref - decrement the hard interface refcounter and | ||
| 56 | * possibly free it | ||
| 57 | * @hard_iface: the hard interface to free | ||
| 58 | */ | ||
| 54 | static inline void | 59 | static inline void |
| 55 | batadv_hardif_free_ref(struct batadv_hard_iface *hard_iface) | 60 | batadv_hardif_free_ref(struct batadv_hard_iface *hard_iface) |
| 56 | { | 61 | { |
| @@ -58,6 +63,18 @@ batadv_hardif_free_ref(struct batadv_hard_iface *hard_iface) | |||
| 58 | call_rcu(&hard_iface->rcu, batadv_hardif_free_rcu); | 63 | call_rcu(&hard_iface->rcu, batadv_hardif_free_rcu); |
| 59 | } | 64 | } |
| 60 | 65 | ||
| 66 | /** | ||
| 67 | * batadv_hardif_free_ref_now - decrement the hard interface refcounter and | ||
| 68 | * possibly free it (without rcu callback) | ||
| 69 | * @hard_iface: the hard interface to free | ||
| 70 | */ | ||
| 71 | static inline void | ||
| 72 | batadv_hardif_free_ref_now(struct batadv_hard_iface *hard_iface) | ||
| 73 | { | ||
| 74 | if (atomic_dec_and_test(&hard_iface->refcount)) | ||
| 75 | batadv_hardif_free_rcu(&hard_iface->rcu); | ||
| 76 | } | ||
| 77 | |||
| 61 | static inline struct batadv_hard_iface * | 78 | static inline struct batadv_hard_iface * |
| 62 | batadv_primary_if_get_selected(struct batadv_priv *bat_priv) | 79 | batadv_primary_if_get_selected(struct batadv_priv *bat_priv) |
| 63 | { | 80 | { |
diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h index a468760b11ea..49a2394c78e6 100644 --- a/net/batman-adv/main.h +++ b/net/batman-adv/main.h | |||
| @@ -72,6 +72,12 @@ | |||
| 72 | 72 | ||
| 73 | #define BATADV_NO_MARK 0 | 73 | #define BATADV_NO_MARK 0 |
| 74 | 74 | ||
| 75 | /* default interface for multi interface operation. The default interface is | ||
| 76 | * used for communication which originated locally (i.e. is not forwarded) | ||
| 77 | * or where special forwarding is not desired/necessary. | ||
| 78 | */ | ||
| 79 | #define BATADV_IF_DEFAULT ((struct batadv_hard_iface *)NULL) | ||
| 80 | |||
| 75 | #define BATADV_NUM_WORDS BITS_TO_LONGS(BATADV_TQ_LOCAL_WINDOW_SIZE) | 81 | #define BATADV_NUM_WORDS BITS_TO_LONGS(BATADV_TQ_LOCAL_WINDOW_SIZE) |
| 76 | 82 | ||
| 77 | #define BATADV_LOG_BUF_LEN 8192 /* has to be a power of 2 */ | 83 | #define BATADV_LOG_BUF_LEN 8192 /* has to be a power of 2 */ |
diff --git a/net/batman-adv/network-coding.c b/net/batman-adv/network-coding.c index d6f0be346a3d..aec3fa564027 100644 --- a/net/batman-adv/network-coding.c +++ b/net/batman-adv/network-coding.c | |||
| @@ -1008,6 +1008,8 @@ static bool batadv_nc_code_packets(struct batadv_priv *bat_priv, | |||
| 1008 | struct batadv_coded_packet *coded_packet; | 1008 | struct batadv_coded_packet *coded_packet; |
| 1009 | struct batadv_neigh_node *neigh_tmp, *router_neigh; | 1009 | struct batadv_neigh_node *neigh_tmp, *router_neigh; |
| 1010 | struct batadv_neigh_node *router_coding = NULL; | 1010 | struct batadv_neigh_node *router_coding = NULL; |
| 1011 | struct batadv_neigh_ifinfo *router_neigh_ifinfo = NULL; | ||
| 1012 | struct batadv_neigh_ifinfo *router_coding_ifinfo = NULL; | ||
| 1011 | uint8_t *first_source, *first_dest, *second_source, *second_dest; | 1013 | uint8_t *first_source, *first_dest, *second_source, *second_dest; |
| 1012 | __be32 packet_id1, packet_id2; | 1014 | __be32 packet_id1, packet_id2; |
| 1013 | size_t count; | 1015 | size_t count; |
| @@ -1021,15 +1023,25 @@ static bool batadv_nc_code_packets(struct batadv_priv *bat_priv, | |||
| 1021 | if (!router_neigh) | 1023 | if (!router_neigh) |
| 1022 | goto out; | 1024 | goto out; |
| 1023 | 1025 | ||
| 1026 | router_neigh_ifinfo = batadv_neigh_ifinfo_get(router_neigh, | ||
| 1027 | BATADV_IF_DEFAULT); | ||
| 1028 | if (!router_neigh_ifinfo) | ||
| 1029 | goto out; | ||
| 1030 | |||
| 1024 | neigh_tmp = nc_packet->neigh_node; | 1031 | neigh_tmp = nc_packet->neigh_node; |
| 1025 | router_coding = batadv_orig_node_get_router(neigh_tmp->orig_node); | 1032 | router_coding = batadv_orig_node_get_router(neigh_tmp->orig_node); |
| 1026 | if (!router_coding) | 1033 | if (!router_coding) |
| 1027 | goto out; | 1034 | goto out; |
| 1028 | 1035 | ||
| 1029 | tq_tmp = batadv_nc_random_weight_tq(router_neigh->bat_iv.tq_avg); | 1036 | router_coding_ifinfo = batadv_neigh_ifinfo_get(router_coding, |
| 1030 | tq_weighted_neigh = tq_tmp; | 1037 | BATADV_IF_DEFAULT); |
| 1031 | tq_tmp = batadv_nc_random_weight_tq(router_coding->bat_iv.tq_avg); | 1038 | if (!router_coding_ifinfo) |
| 1032 | tq_weighted_coding = tq_tmp; | 1039 | goto out; |
| 1040 | |||
| 1041 | tq_tmp = router_neigh_ifinfo->bat_iv.tq_avg; | ||
| 1042 | tq_weighted_neigh = batadv_nc_random_weight_tq(tq_tmp); | ||
| 1043 | tq_tmp = router_coding_ifinfo->bat_iv.tq_avg; | ||
| 1044 | tq_weighted_coding = batadv_nc_random_weight_tq(tq_tmp); | ||
| 1033 | 1045 | ||
| 1034 | /* Select one destination for the MAC-header dst-field based on | 1046 | /* Select one destination for the MAC-header dst-field based on |
| 1035 | * weighted TQ-values. | 1047 | * weighted TQ-values. |
| @@ -1153,6 +1165,10 @@ out: | |||
| 1153 | batadv_neigh_node_free_ref(router_neigh); | 1165 | batadv_neigh_node_free_ref(router_neigh); |
| 1154 | if (router_coding) | 1166 | if (router_coding) |
| 1155 | batadv_neigh_node_free_ref(router_coding); | 1167 | batadv_neigh_node_free_ref(router_coding); |
| 1168 | if (router_neigh_ifinfo) | ||
| 1169 | batadv_neigh_ifinfo_free_ref(router_neigh_ifinfo); | ||
| 1170 | if (router_coding_ifinfo) | ||
| 1171 | batadv_neigh_ifinfo_free_ref(router_coding_ifinfo); | ||
| 1156 | return res; | 1172 | return res; |
| 1157 | } | 1173 | } |
| 1158 | 1174 | ||
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c index 03db87fb2ebe..1a4725f5267d 100644 --- a/net/batman-adv/originator.c +++ b/net/batman-adv/originator.c | |||
| @@ -148,10 +148,87 @@ err: | |||
| 148 | return -ENOMEM; | 148 | return -ENOMEM; |
| 149 | } | 149 | } |
| 150 | 150 | ||
| 151 | /** | ||
| 152 | * batadv_neigh_ifinfo_free_rcu - free the neigh_ifinfo object | ||
| 153 | * @rcu: rcu pointer of the neigh_ifinfo object | ||
| 154 | */ | ||
| 155 | static void batadv_neigh_ifinfo_free_rcu(struct rcu_head *rcu) | ||
| 156 | { | ||
| 157 | struct batadv_neigh_ifinfo *neigh_ifinfo; | ||
| 158 | |||
| 159 | neigh_ifinfo = container_of(rcu, struct batadv_neigh_ifinfo, rcu); | ||
| 160 | |||
| 161 | if (neigh_ifinfo->if_outgoing != BATADV_IF_DEFAULT) | ||
| 162 | batadv_hardif_free_ref_now(neigh_ifinfo->if_outgoing); | ||
| 163 | |||
| 164 | kfree(neigh_ifinfo); | ||
| 165 | } | ||
| 166 | |||
| 167 | /** | ||
| 168 | * batadv_neigh_ifinfo_free_now - decrement the refcounter and possibly free | ||
| 169 | * the neigh_ifinfo (without rcu callback) | ||
| 170 | * @neigh_ifinfo: the neigh_ifinfo object to release | ||
| 171 | */ | ||
| 172 | static void | ||
| 173 | batadv_neigh_ifinfo_free_ref_now(struct batadv_neigh_ifinfo *neigh_ifinfo) | ||
| 174 | { | ||
| 175 | if (atomic_dec_and_test(&neigh_ifinfo->refcount)) | ||
| 176 | batadv_neigh_ifinfo_free_rcu(&neigh_ifinfo->rcu); | ||
| 177 | } | ||
| 178 | |||
| 179 | /** | ||
| 180 | * batadv_neigh_ifinfo_free_ref - decrement the refcounter and possibly free | ||
| 181 | * the neigh_ifinfo | ||
| 182 | * @neigh_ifinfo: the neigh_ifinfo object to release | ||
| 183 | */ | ||
| 184 | void batadv_neigh_ifinfo_free_ref(struct batadv_neigh_ifinfo *neigh_ifinfo) | ||
| 185 | { | ||
| 186 | if (atomic_dec_and_test(&neigh_ifinfo->refcount)) | ||
| 187 | call_rcu(&neigh_ifinfo->rcu, batadv_neigh_ifinfo_free_rcu); | ||
| 188 | } | ||
| 189 | |||
| 190 | /** | ||
| 191 | * batadv_neigh_node_free_rcu - free the neigh_node | ||
| 192 | * @rcu: rcu pointer of the neigh_node | ||
| 193 | */ | ||
| 194 | static void batadv_neigh_node_free_rcu(struct rcu_head *rcu) | ||
| 195 | { | ||
| 196 | struct hlist_node *node_tmp; | ||
| 197 | struct batadv_neigh_node *neigh_node; | ||
| 198 | struct batadv_neigh_ifinfo *neigh_ifinfo; | ||
| 199 | |||
| 200 | neigh_node = container_of(rcu, struct batadv_neigh_node, rcu); | ||
| 201 | |||
| 202 | hlist_for_each_entry_safe(neigh_ifinfo, node_tmp, | ||
| 203 | &neigh_node->ifinfo_list, list) { | ||
| 204 | batadv_neigh_ifinfo_free_ref_now(neigh_ifinfo); | ||
| 205 | } | ||
| 206 | batadv_hardif_free_ref_now(neigh_node->if_incoming); | ||
| 207 | |||
| 208 | kfree(neigh_node); | ||
| 209 | } | ||
| 210 | |||
| 211 | /** | ||
| 212 | * batadv_neigh_node_free_ref_now - decrement the neighbors refcounter | ||
| 213 | * and possibly free it (without rcu callback) | ||
| 214 | * @neigh_node: neigh neighbor to free | ||
| 215 | */ | ||
| 216 | static void | ||
| 217 | batadv_neigh_node_free_ref_now(struct batadv_neigh_node *neigh_node) | ||
| 218 | { | ||
| 219 | if (atomic_dec_and_test(&neigh_node->refcount)) | ||
| 220 | batadv_neigh_node_free_rcu(&neigh_node->rcu); | ||
| 221 | } | ||
| 222 | |||
| 223 | /** | ||
| 224 | * batadv_neigh_node_free_ref - decrement the neighbors refcounter | ||
| 225 | * and possibly free it | ||
| 226 | * @neigh_node: neigh neighbor to free | ||
| 227 | */ | ||
| 151 | void batadv_neigh_node_free_ref(struct batadv_neigh_node *neigh_node) | 228 | void batadv_neigh_node_free_ref(struct batadv_neigh_node *neigh_node) |
| 152 | { | 229 | { |
| 153 | if (atomic_dec_and_test(&neigh_node->refcount)) | 230 | if (atomic_dec_and_test(&neigh_node->refcount)) |
| 154 | kfree_rcu(neigh_node, rcu); | 231 | call_rcu(&neigh_node->rcu, batadv_neigh_node_free_rcu); |
| 155 | } | 232 | } |
| 156 | 233 | ||
| 157 | /* increases the refcounter of a found router */ | 234 | /* increases the refcounter of a found router */ |
| @@ -171,6 +248,84 @@ batadv_orig_node_get_router(struct batadv_orig_node *orig_node) | |||
| 171 | } | 248 | } |
| 172 | 249 | ||
| 173 | /** | 250 | /** |
| 251 | * batadv_neigh_ifinfo_get - find the ifinfo from an neigh_node | ||
| 252 | * @neigh_node: the neigh node to be queried | ||
| 253 | * @if_outgoing: the interface for which the ifinfo should be acquired | ||
| 254 | * | ||
| 255 | * The object is returned with refcounter increased by 1. | ||
| 256 | * | ||
| 257 | * Returns the requested neigh_ifinfo or NULL if not found | ||
| 258 | */ | ||
| 259 | struct batadv_neigh_ifinfo * | ||
| 260 | batadv_neigh_ifinfo_get(struct batadv_neigh_node *neigh, | ||
| 261 | struct batadv_hard_iface *if_outgoing) | ||
| 262 | { | ||
| 263 | struct batadv_neigh_ifinfo *neigh_ifinfo = NULL, | ||
| 264 | *tmp_neigh_ifinfo; | ||
| 265 | |||
| 266 | rcu_read_lock(); | ||
| 267 | hlist_for_each_entry_rcu(tmp_neigh_ifinfo, &neigh->ifinfo_list, | ||
| 268 | list) { | ||
| 269 | if (tmp_neigh_ifinfo->if_outgoing != if_outgoing) | ||
| 270 | continue; | ||
| 271 | |||
| 272 | if (!atomic_inc_not_zero(&tmp_neigh_ifinfo->refcount)) | ||
| 273 | continue; | ||
| 274 | |||
| 275 | neigh_ifinfo = tmp_neigh_ifinfo; | ||
| 276 | break; | ||
| 277 | } | ||
| 278 | rcu_read_unlock(); | ||
| 279 | |||
| 280 | return neigh_ifinfo; | ||
| 281 | } | ||
| 282 | |||
| 283 | /** | ||
| 284 | * batadv_neigh_ifinfo_new - search and possibly create an neigh_ifinfo object | ||
| 285 | * @neigh_node: the neigh node to be queried | ||
| 286 | * @if_outgoing: the interface for which the ifinfo should be acquired | ||
| 287 | * | ||
| 288 | * Returns NULL in case of failure or the neigh_ifinfo object for the | ||
| 289 | * if_outgoing interface otherwise. The object is created and added to the list | ||
| 290 | * if it does not exist. | ||
| 291 | * | ||
| 292 | * The object is returned with refcounter increased by 1. | ||
| 293 | */ | ||
| 294 | struct batadv_neigh_ifinfo * | ||
| 295 | batadv_neigh_ifinfo_new(struct batadv_neigh_node *neigh, | ||
| 296 | struct batadv_hard_iface *if_outgoing) | ||
| 297 | { | ||
| 298 | struct batadv_neigh_ifinfo *neigh_ifinfo; | ||
| 299 | |||
| 300 | spin_lock_bh(&neigh->ifinfo_lock); | ||
| 301 | |||
| 302 | neigh_ifinfo = batadv_neigh_ifinfo_get(neigh, if_outgoing); | ||
| 303 | if (neigh_ifinfo) | ||
| 304 | goto out; | ||
| 305 | |||
| 306 | neigh_ifinfo = kzalloc(sizeof(*neigh_ifinfo), GFP_ATOMIC); | ||
| 307 | if (!neigh_ifinfo) | ||
| 308 | goto out; | ||
| 309 | |||
| 310 | if (if_outgoing && !atomic_inc_not_zero(&if_outgoing->refcount)) { | ||
| 311 | kfree(neigh_ifinfo); | ||
| 312 | neigh_ifinfo = NULL; | ||
| 313 | goto out; | ||
| 314 | } | ||
| 315 | |||
| 316 | INIT_HLIST_NODE(&neigh_ifinfo->list); | ||
| 317 | atomic_set(&neigh_ifinfo->refcount, 2); | ||
| 318 | neigh_ifinfo->if_outgoing = if_outgoing; | ||
| 319 | |||
| 320 | hlist_add_head_rcu(&neigh_ifinfo->list, &neigh->ifinfo_list); | ||
| 321 | |||
| 322 | out: | ||
| 323 | spin_unlock_bh(&neigh->ifinfo_lock); | ||
| 324 | |||
| 325 | return neigh_ifinfo; | ||
| 326 | } | ||
| 327 | |||
| 328 | /** | ||
| 174 | * batadv_neigh_node_new - create and init a new neigh_node object | 329 | * batadv_neigh_node_new - create and init a new neigh_node object |
| 175 | * @hard_iface: the interface where the neighbour is connected to | 330 | * @hard_iface: the interface where the neighbour is connected to |
| 176 | * @neigh_addr: the mac address of the neighbour interface | 331 | * @neigh_addr: the mac address of the neighbour interface |
| @@ -191,6 +346,8 @@ batadv_neigh_node_new(struct batadv_hard_iface *hard_iface, | |||
| 191 | goto out; | 346 | goto out; |
| 192 | 347 | ||
| 193 | INIT_HLIST_NODE(&neigh_node->list); | 348 | INIT_HLIST_NODE(&neigh_node->list); |
| 349 | INIT_HLIST_HEAD(&neigh_node->ifinfo_list); | ||
| 350 | spin_lock_init(&neigh_node->ifinfo_lock); | ||
| 194 | 351 | ||
| 195 | memcpy(neigh_node->addr, neigh_addr, ETH_ALEN); | 352 | memcpy(neigh_node->addr, neigh_addr, ETH_ALEN); |
| 196 | neigh_node->if_incoming = hard_iface; | 353 | neigh_node->if_incoming = hard_iface; |
| @@ -217,7 +374,7 @@ static void batadv_orig_node_free_rcu(struct rcu_head *rcu) | |||
| 217 | hlist_for_each_entry_safe(neigh_node, node_tmp, | 374 | hlist_for_each_entry_safe(neigh_node, node_tmp, |
| 218 | &orig_node->neigh_list, list) { | 375 | &orig_node->neigh_list, list) { |
| 219 | hlist_del_rcu(&neigh_node->list); | 376 | hlist_del_rcu(&neigh_node->list); |
| 220 | batadv_neigh_node_free_ref(neigh_node); | 377 | batadv_neigh_node_free_ref_now(neigh_node); |
| 221 | } | 378 | } |
| 222 | 379 | ||
| 223 | spin_unlock_bh(&orig_node->neigh_list_lock); | 380 | spin_unlock_bh(&orig_node->neigh_list_lock); |
| @@ -362,20 +519,23 @@ free_orig_node: | |||
| 362 | return NULL; | 519 | return NULL; |
| 363 | } | 520 | } |
| 364 | 521 | ||
| 522 | /** | ||
| 523 | * batadv_purge_orig_neighbors - purges neighbors from originator | ||
| 524 | * @bat_priv: the bat priv with all the soft interface information | ||
| 525 | * @orig_node: orig node which is to be checked | ||
| 526 | * | ||
| 527 | * Returns true if any neighbor was purged, false otherwise | ||
| 528 | */ | ||
| 365 | static bool | 529 | static bool |
| 366 | batadv_purge_orig_neighbors(struct batadv_priv *bat_priv, | 530 | batadv_purge_orig_neighbors(struct batadv_priv *bat_priv, |
| 367 | struct batadv_orig_node *orig_node, | 531 | struct batadv_orig_node *orig_node) |
| 368 | struct batadv_neigh_node **best_neigh) | ||
| 369 | { | 532 | { |
| 370 | struct batadv_algo_ops *bao = bat_priv->bat_algo_ops; | ||
| 371 | struct hlist_node *node_tmp; | 533 | struct hlist_node *node_tmp; |
| 372 | struct batadv_neigh_node *neigh_node; | 534 | struct batadv_neigh_node *neigh_node; |
| 373 | bool neigh_purged = false; | 535 | bool neigh_purged = false; |
| 374 | unsigned long last_seen; | 536 | unsigned long last_seen; |
| 375 | struct batadv_hard_iface *if_incoming; | 537 | struct batadv_hard_iface *if_incoming; |
| 376 | 538 | ||
| 377 | *best_neigh = NULL; | ||
| 378 | |||
| 379 | spin_lock_bh(&orig_node->neigh_list_lock); | 539 | spin_lock_bh(&orig_node->neigh_list_lock); |
| 380 | 540 | ||
| 381 | /* for all neighbors towards this originator ... */ | 541 | /* for all neighbors towards this originator ... */ |
| @@ -405,13 +565,6 @@ batadv_purge_orig_neighbors(struct batadv_priv *bat_priv, | |||
| 405 | 565 | ||
| 406 | hlist_del_rcu(&neigh_node->list); | 566 | hlist_del_rcu(&neigh_node->list); |
| 407 | batadv_neigh_node_free_ref(neigh_node); | 567 | batadv_neigh_node_free_ref(neigh_node); |
| 408 | } else { | ||
| 409 | /* store the best_neighbour if this is the first | ||
| 410 | * iteration or if a better neighbor has been found | ||
| 411 | */ | ||
| 412 | if (!*best_neigh || | ||
| 413 | bao->bat_neigh_cmp(neigh_node, *best_neigh) > 0) | ||
| 414 | *best_neigh = neigh_node; | ||
| 415 | } | 568 | } |
| 416 | } | 569 | } |
| 417 | 570 | ||
| @@ -419,6 +572,41 @@ batadv_purge_orig_neighbors(struct batadv_priv *bat_priv, | |||
| 419 | return neigh_purged; | 572 | return neigh_purged; |
| 420 | } | 573 | } |
| 421 | 574 | ||
| 575 | /** | ||
| 576 | * batadv_find_best_neighbor - finds the best neighbor after purging | ||
| 577 | * @bat_priv: the bat priv with all the soft interface information | ||
| 578 | * @orig_node: orig node which is to be checked | ||
| 579 | * @if_outgoing: the interface for which the metric should be compared | ||
| 580 | * | ||
| 581 | * Returns the current best neighbor, with refcount increased. | ||
| 582 | */ | ||
| 583 | static struct batadv_neigh_node * | ||
| 584 | batadv_find_best_neighbor(struct batadv_priv *bat_priv, | ||
| 585 | struct batadv_orig_node *orig_node, | ||
| 586 | struct batadv_hard_iface *if_outgoing) | ||
| 587 | { | ||
| 588 | struct batadv_neigh_node *best = NULL, *neigh; | ||
| 589 | struct batadv_algo_ops *bao = bat_priv->bat_algo_ops; | ||
| 590 | |||
| 591 | rcu_read_lock(); | ||
| 592 | hlist_for_each_entry_rcu(neigh, &orig_node->neigh_list, list) { | ||
| 593 | if (best && (bao->bat_neigh_cmp(neigh, if_outgoing, | ||
| 594 | best, if_outgoing) <= 0)) | ||
| 595 | continue; | ||
| 596 | |||
| 597 | if (!atomic_inc_not_zero(&neigh->refcount)) | ||
| 598 | continue; | ||
| 599 | |||
| 600 | if (best) | ||
| 601 | batadv_neigh_node_free_ref(best); | ||
| 602 | |||
| 603 | best = neigh; | ||
| 604 | } | ||
| 605 | rcu_read_unlock(); | ||
| 606 | |||
| 607 | return best; | ||
| 608 | } | ||
| 609 | |||
| 422 | static bool batadv_purge_orig_node(struct batadv_priv *bat_priv, | 610 | static bool batadv_purge_orig_node(struct batadv_priv *bat_priv, |
| 423 | struct batadv_orig_node *orig_node) | 611 | struct batadv_orig_node *orig_node) |
| 424 | { | 612 | { |
| @@ -431,12 +619,15 @@ static bool batadv_purge_orig_node(struct batadv_priv *bat_priv, | |||
| 431 | orig_node->orig, | 619 | orig_node->orig, |
| 432 | jiffies_to_msecs(orig_node->last_seen)); | 620 | jiffies_to_msecs(orig_node->last_seen)); |
| 433 | return true; | 621 | return true; |
| 434 | } else { | ||
| 435 | if (batadv_purge_orig_neighbors(bat_priv, orig_node, | ||
| 436 | &best_neigh_node)) | ||
| 437 | batadv_update_route(bat_priv, orig_node, | ||
| 438 | best_neigh_node); | ||
| 439 | } | 622 | } |
| 623 | if (!batadv_purge_orig_neighbors(bat_priv, orig_node)) | ||
| 624 | return false; | ||
| 625 | |||
| 626 | best_neigh_node = batadv_find_best_neighbor(bat_priv, orig_node, | ||
| 627 | BATADV_IF_DEFAULT); | ||
| 628 | batadv_update_route(bat_priv, orig_node, best_neigh_node); | ||
| 629 | if (best_neigh_node) | ||
| 630 | batadv_neigh_node_free_ref(best_neigh_node); | ||
| 440 | 631 | ||
| 441 | return false; | 632 | return false; |
| 442 | } | 633 | } |
diff --git a/net/batman-adv/originator.h b/net/batman-adv/originator.h index 99ed3c61e4f9..29fa4c428b59 100644 --- a/net/batman-adv/originator.h +++ b/net/batman-adv/originator.h | |||
| @@ -35,6 +35,13 @@ batadv_neigh_node_new(struct batadv_hard_iface *hard_iface, | |||
| 35 | void batadv_neigh_node_free_ref(struct batadv_neigh_node *neigh_node); | 35 | void batadv_neigh_node_free_ref(struct batadv_neigh_node *neigh_node); |
| 36 | struct batadv_neigh_node * | 36 | struct batadv_neigh_node * |
| 37 | batadv_orig_node_get_router(struct batadv_orig_node *orig_node); | 37 | batadv_orig_node_get_router(struct batadv_orig_node *orig_node); |
| 38 | struct batadv_neigh_ifinfo * | ||
| 39 | batadv_neigh_ifinfo_new(struct batadv_neigh_node *neigh, | ||
| 40 | struct batadv_hard_iface *if_outgoing); | ||
| 41 | struct batadv_neigh_ifinfo * | ||
| 42 | batadv_neigh_ifinfo_get(struct batadv_neigh_node *neigh, | ||
| 43 | struct batadv_hard_iface *if_outgoing); | ||
| 44 | void batadv_neigh_ifinfo_free_ref(struct batadv_neigh_ifinfo *neigh_ifinfo); | ||
| 38 | int batadv_orig_seq_print_text(struct seq_file *seq, void *offset); | 45 | int batadv_orig_seq_print_text(struct seq_file *seq, void *offset); |
| 39 | int batadv_orig_hash_add_if(struct batadv_hard_iface *hard_iface, | 46 | int batadv_orig_hash_add_if(struct batadv_hard_iface *hard_iface, |
| 40 | int max_if_num); | 47 | int max_if_num); |
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index 63d25705cec6..22c32ae12e65 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c | |||
| @@ -1405,7 +1405,8 @@ batadv_transtable_best_orig(struct batadv_priv *bat_priv, | |||
| 1405 | continue; | 1405 | continue; |
| 1406 | 1406 | ||
| 1407 | if (best_router && | 1407 | if (best_router && |
| 1408 | bao->bat_neigh_cmp(router, best_router) <= 0) { | 1408 | bao->bat_neigh_cmp(router, BATADV_IF_DEFAULT, |
| 1409 | best_router, BATADV_IF_DEFAULT) <= 0) { | ||
| 1409 | batadv_neigh_node_free_ref(router); | 1410 | batadv_neigh_node_free_ref(router); |
| 1410 | continue; | 1411 | continue; |
| 1411 | } | 1412 | } |
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index 0f6884504a9e..8435d7c83a14 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h | |||
| @@ -289,47 +289,62 @@ struct batadv_gw_node { | |||
| 289 | }; | 289 | }; |
| 290 | 290 | ||
| 291 | /** | 291 | /** |
| 292 | * struct batadv_neigh_bat_iv - B.A.T.M.A.N. IV specific structure for single | 292 | * struct batadv_neigh_node - structure for single hops neighbors |
| 293 | * hop neighbors | 293 | * @list: list node for batadv_orig_node::neigh_list |
| 294 | * @orig_node: pointer to corresponding orig_node | ||
| 295 | * @addr: the MAC address of the neighboring interface | ||
| 296 | * @ifinfo_list: list for routing metrics per outgoing interface | ||
| 297 | * @ifinfo_lock: lock protecting private ifinfo members and list | ||
| 298 | * @if_incoming: pointer to incoming hard interface | ||
| 299 | * @last_seen: when last packet via this neighbor was received | ||
| 300 | * @last_ttl: last received ttl from this neigh node | ||
| 301 | * @rcu: struct used for freeing in an RCU-safe manner | ||
| 302 | * @bat_iv: B.A.T.M.A.N. IV private structure | ||
| 303 | */ | ||
| 304 | struct batadv_neigh_node { | ||
| 305 | struct hlist_node list; | ||
| 306 | struct batadv_orig_node *orig_node; | ||
| 307 | uint8_t addr[ETH_ALEN]; | ||
| 308 | struct hlist_head ifinfo_list; | ||
| 309 | spinlock_t ifinfo_lock; /* protects ifinfo_list and its members */ | ||
| 310 | struct batadv_hard_iface *if_incoming; | ||
| 311 | unsigned long last_seen; | ||
| 312 | atomic_t refcount; | ||
| 313 | struct rcu_head rcu; | ||
| 314 | }; | ||
| 315 | |||
| 316 | /* struct batadv_neigh_node_bat_iv - neighbor information per outgoing | ||
| 317 | * interface for BATMAN IV | ||
| 294 | * @tq_recv: ring buffer of received TQ values from this neigh node | 318 | * @tq_recv: ring buffer of received TQ values from this neigh node |
| 295 | * @tq_index: ring buffer index | 319 | * @tq_index: ring buffer index |
| 296 | * @tq_avg: averaged tq of all tq values in the ring buffer (tq_recv) | 320 | * @tq_avg: averaged tq of all tq values in the ring buffer (tq_recv) |
| 297 | * @real_bits: bitfield containing the number of OGMs received from this neigh | 321 | * @real_bits: bitfield containing the number of OGMs received from this neigh |
| 298 | * node (relative to orig_node->last_real_seqno) | 322 | * node (relative to orig_node->last_real_seqno) |
| 299 | * @real_packet_count: counted result of real_bits | 323 | * @real_packet_count: counted result of real_bits |
| 300 | * @lq_update_lock: lock protecting tq_recv & tq_index | ||
| 301 | */ | 324 | */ |
| 302 | struct batadv_neigh_bat_iv { | 325 | struct batadv_neigh_ifinfo_bat_iv { |
| 303 | uint8_t tq_recv[BATADV_TQ_GLOBAL_WINDOW_SIZE]; | 326 | uint8_t tq_recv[BATADV_TQ_GLOBAL_WINDOW_SIZE]; |
| 304 | uint8_t tq_index; | 327 | uint8_t tq_index; |
| 305 | uint8_t tq_avg; | 328 | uint8_t tq_avg; |
| 306 | DECLARE_BITMAP(real_bits, BATADV_TQ_LOCAL_WINDOW_SIZE); | 329 | DECLARE_BITMAP(real_bits, BATADV_TQ_LOCAL_WINDOW_SIZE); |
| 307 | uint8_t real_packet_count; | 330 | uint8_t real_packet_count; |
| 308 | spinlock_t lq_update_lock; /* protects tq_recv & tq_index */ | ||
| 309 | }; | 331 | }; |
| 310 | 332 | ||
| 311 | /** | 333 | /* struct batadv_neigh_ifinfo - neighbor information per outgoing interface |
| 312 | * struct batadv_neigh_node - structure for single hops neighbors | 334 | * @list: list node for batadv_neigh_node::ifinfo_list |
| 313 | * @list: list node for batadv_orig_node::neigh_list | 335 | * @if_outgoing: pointer to outgoing hard interface |
| 314 | * @orig_node: pointer to corresponding orig_node | 336 | * @bat_iv: B.A.T.M.A.N. IV private structure |
| 315 | * @addr: the MAC address of the neighboring interface | ||
| 316 | * @if_incoming: pointer to incoming hard interface | ||
| 317 | * @last_seen: when last packet via this neighbor was received | ||
| 318 | * @last_ttl: last received ttl from this neigh node | 337 | * @last_ttl: last received ttl from this neigh node |
| 319 | * @refcount: number of contexts the object is used | 338 | * @refcount: number of contexts the object is used |
| 320 | * @rcu: struct used for freeing in an RCU-safe manner | 339 | * @rcu: struct used for freeing in a RCU-safe manner |
| 321 | * @bat_iv: B.A.T.M.A.N. IV private structure | ||
| 322 | */ | 340 | */ |
| 323 | struct batadv_neigh_node { | 341 | struct batadv_neigh_ifinfo { |
| 324 | struct hlist_node list; | 342 | struct hlist_node list; |
| 325 | struct batadv_orig_node *orig_node; | 343 | struct batadv_hard_iface *if_outgoing; |
| 326 | uint8_t addr[ETH_ALEN]; | 344 | struct batadv_neigh_ifinfo_bat_iv bat_iv; |
| 327 | struct batadv_hard_iface *if_incoming; | ||
| 328 | unsigned long last_seen; | ||
| 329 | uint8_t last_ttl; | 345 | uint8_t last_ttl; |
| 330 | atomic_t refcount; | 346 | atomic_t refcount; |
| 331 | struct rcu_head rcu; | 347 | struct rcu_head rcu; |
| 332 | struct batadv_neigh_bat_iv bat_iv; | ||
| 333 | }; | 348 | }; |
| 334 | 349 | ||
| 335 | /** | 350 | /** |
| @@ -1013,9 +1028,11 @@ struct batadv_forw_packet { | |||
| 1013 | * @bat_primary_iface_set: called when primary interface is selected / changed | 1028 | * @bat_primary_iface_set: called when primary interface is selected / changed |
| 1014 | * @bat_ogm_schedule: prepare a new outgoing OGM for the send queue | 1029 | * @bat_ogm_schedule: prepare a new outgoing OGM for the send queue |
| 1015 | * @bat_ogm_emit: send scheduled OGM | 1030 | * @bat_ogm_emit: send scheduled OGM |
| 1016 | * @bat_neigh_cmp: compare the metrics of two neighbors | 1031 | * @bat_neigh_cmp: compare the metrics of two neighbors for their respective |
| 1017 | * @bat_neigh_is_equiv_or_better: check if neigh1 is equally good or | 1032 | * outgoing interfaces |
| 1018 | * better than neigh2 from the metric prospective | 1033 | * @bat_neigh_is_equiv_or_better: check if neigh1 is equally good or better |
| 1034 | * than neigh2 for their respective outgoing interface from the metric | ||
| 1035 | * prospective | ||
| 1019 | * @bat_orig_print: print the originator table (optional) | 1036 | * @bat_orig_print: print the originator table (optional) |
| 1020 | * @bat_orig_free: free the resources allocated by the routing algorithm for an | 1037 | * @bat_orig_free: free the resources allocated by the routing algorithm for an |
| 1021 | * orig_node object | 1038 | * orig_node object |
| @@ -1034,9 +1051,14 @@ struct batadv_algo_ops { | |||
| 1034 | void (*bat_ogm_schedule)(struct batadv_hard_iface *hard_iface); | 1051 | void (*bat_ogm_schedule)(struct batadv_hard_iface *hard_iface); |
| 1035 | void (*bat_ogm_emit)(struct batadv_forw_packet *forw_packet); | 1052 | void (*bat_ogm_emit)(struct batadv_forw_packet *forw_packet); |
| 1036 | int (*bat_neigh_cmp)(struct batadv_neigh_node *neigh1, | 1053 | int (*bat_neigh_cmp)(struct batadv_neigh_node *neigh1, |
| 1037 | struct batadv_neigh_node *neigh2); | 1054 | struct batadv_hard_iface *if_outgoing1, |
| 1038 | bool (*bat_neigh_is_equiv_or_better)(struct batadv_neigh_node *neigh1, | 1055 | struct batadv_neigh_node *neigh2, |
| 1039 | struct batadv_neigh_node *neigh2); | 1056 | struct batadv_hard_iface *if_outgoing2); |
| 1057 | bool (*bat_neigh_is_equiv_or_better) | ||
| 1058 | (struct batadv_neigh_node *neigh1, | ||
| 1059 | struct batadv_hard_iface *if_outgoing1, | ||
| 1060 | struct batadv_neigh_node *neigh2, | ||
| 1061 | struct batadv_hard_iface *if_outgoing2); | ||
| 1040 | /* orig_node handling API */ | 1062 | /* orig_node handling API */ |
| 1041 | void (*bat_orig_print)(struct batadv_priv *priv, struct seq_file *seq); | 1063 | void (*bat_orig_print)(struct batadv_priv *priv, struct seq_file *seq); |
| 1042 | void (*bat_orig_free)(struct batadv_orig_node *orig_node); | 1064 | void (*bat_orig_free)(struct batadv_orig_node *orig_node); |
