aboutsummaryrefslogtreecommitdiffstats
path: root/net/batman-adv/bat_iv_ogm.c
diff options
context:
space:
mode:
authorSimon Wunderlich <simon@open-mesh.com>2013-11-13 13:14:46 -0500
committerAntonio Quartulli <antonio@meshcoding.com>2014-01-12 08:41:10 -0500
commit89652331c00f43574515059ecbf262d26d885717 (patch)
tree907828c7834896ef46ad868466cbeb4b87b58583 /net/batman-adv/bat_iv_ogm.c
parentf6c8b71173ad50e48e6569a1ef5d7d4486268b4d (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.c267
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 */
898static void 917static void
899batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv, 918batadv_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 */
1020static int batadv_iv_ogm_calc_tq(struct batadv_orig_node *orig_node, 1077static 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 */
1138static enum batadv_dup_status 1204static enum batadv_dup_status
1139batadv_iv_ogm_update_seqnos(const struct ethhdr *ethhdr, 1205batadv_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 */
1616static void
1617batadv_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,
1535static void batadv_iv_ogm_orig_print(struct batadv_priv *bat_priv, 1642static 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
1584next: 1692next:
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 */
1602static int batadv_iv_ogm_neigh_cmp(struct batadv_neigh_node *neigh1, 1714static 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
1735out:
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 */
1622static bool batadv_iv_ogm_neigh_is_eob(struct batadv_neigh_node *neigh1, 1755static bool
1623 struct batadv_neigh_node *neigh2) 1756batadv_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
1778out:
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
1630static struct batadv_algo_ops batadv_batman_iv __read_mostly = { 1787static struct batadv_algo_ops batadv_batman_iv __read_mostly = {