diff options
author | Simon Wunderlich <simon@open-mesh.com> | 2013-11-13 13:14:46 -0500 |
---|---|---|
committer | Antonio Quartulli <antonio@meshcoding.com> | 2014-01-12 08:41:10 -0500 |
commit | 89652331c00f43574515059ecbf262d26d885717 (patch) | |
tree | 907828c7834896ef46ad868466cbeb4b87b58583 | |
parent | f6c8b71173ad50e48e6569a1ef5d7d4486268b4d (diff) |
batman-adv: split tq information in neigh_node struct
For the network wide multi interface optimization it is required to save
metrics per outgoing interface in one neighbor. Therefore a new type is
introduced to keep interface-specific information. This also requires
some changes in access and list management.
The compare and equiv_or_better API calls are changed to take the
outgoing interface into consideration.
Signed-off-by: Simon Wunderlich <simon@open-mesh.com>
Signed-off-by: Marek Lindner <mareklindner@neomailbox.ch>
Signed-off-by: Antonio Quartulli <antonio@meshcoding.com>
-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); |