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 /net/batman-adv/bat_iv_ogm.c | |
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>
Diffstat (limited to 'net/batman-adv/bat_iv_ogm.c')
-rw-r--r-- | net/batman-adv/bat_iv_ogm.c | 267 |
1 files changed, 212 insertions, 55 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 = { |