aboutsummaryrefslogtreecommitdiffstats
path: root/net/batman-adv
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
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')
-rw-r--r--net/batman-adv/bat_iv_ogm.c267
-rw-r--r--net/batman-adv/gateway_client.c75
-rw-r--r--net/batman-adv/hard-interface.h17
-rw-r--r--net/batman-adv/main.h6
-rw-r--r--net/batman-adv/network-coding.c24
-rw-r--r--net/batman-adv/originator.c229
-rw-r--r--net/batman-adv/originator.h7
-rw-r--r--net/batman-adv/translation-table.c3
-rw-r--r--net/batman-adv/types.h74
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 */
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 = {
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 *
129batadv_gw_get_best_gw_node(struct batadv_priv *bat_priv) 129batadv_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
198next: 204next:
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
305void batadv_gw_check_election(struct batadv_priv *bat_priv, 325void 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);
561out: 601out:
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
804out: 861out:
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);
51void batadv_update_min_mtu(struct net_device *soft_iface); 51void batadv_update_min_mtu(struct net_device *soft_iface);
52void batadv_hardif_free_rcu(struct rcu_head *rcu); 52void 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 */
54static inline void 59static inline void
55batadv_hardif_free_ref(struct batadv_hard_iface *hard_iface) 60batadv_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 */
71static inline void
72batadv_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
61static inline struct batadv_hard_iface * 78static inline struct batadv_hard_iface *
62batadv_primary_if_get_selected(struct batadv_priv *bat_priv) 79batadv_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 */
155static 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 */
172static void
173batadv_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 */
184void 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 */
194static 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 */
216static void
217batadv_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 */
151void batadv_neigh_node_free_ref(struct batadv_neigh_node *neigh_node) 228void 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 */
259struct batadv_neigh_ifinfo *
260batadv_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 */
294struct batadv_neigh_ifinfo *
295batadv_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
322out:
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 */
365static bool 529static bool
366batadv_purge_orig_neighbors(struct batadv_priv *bat_priv, 530batadv_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 */
583static struct batadv_neigh_node *
584batadv_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
422static bool batadv_purge_orig_node(struct batadv_priv *bat_priv, 610static 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,
35void batadv_neigh_node_free_ref(struct batadv_neigh_node *neigh_node); 35void batadv_neigh_node_free_ref(struct batadv_neigh_node *neigh_node);
36struct batadv_neigh_node * 36struct batadv_neigh_node *
37batadv_orig_node_get_router(struct batadv_orig_node *orig_node); 37batadv_orig_node_get_router(struct batadv_orig_node *orig_node);
38struct batadv_neigh_ifinfo *
39batadv_neigh_ifinfo_new(struct batadv_neigh_node *neigh,
40 struct batadv_hard_iface *if_outgoing);
41struct batadv_neigh_ifinfo *
42batadv_neigh_ifinfo_get(struct batadv_neigh_node *neigh,
43 struct batadv_hard_iface *if_outgoing);
44void batadv_neigh_ifinfo_free_ref(struct batadv_neigh_ifinfo *neigh_ifinfo);
38int batadv_orig_seq_print_text(struct seq_file *seq, void *offset); 45int batadv_orig_seq_print_text(struct seq_file *seq, void *offset);
39int batadv_orig_hash_add_if(struct batadv_hard_iface *hard_iface, 46int 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 */
304struct 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 */
302struct batadv_neigh_bat_iv { 325struct 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 */
323struct batadv_neigh_node { 341struct 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);