aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Wunderlich <simon@open-mesh.com>2013-11-13 13:14:47 -0500
committerAntonio Quartulli <antonio@meshcoding.com>2014-01-12 08:41:11 -0500
commit7351a4822d42827ba0110677c0cbad88a3d52585 (patch)
treecc3e4200c1f1ff0b27f370c451b6a36493b74d79
parent89652331c00f43574515059ecbf262d26d885717 (diff)
batman-adv: split out router from orig_node
For the network wide multi interface optimization there are different routers for each outgoing interface (outgoing from the OGM perspective, incoming for payload traffic). To reflect this, change the router and associated data to a list of routers. While at it, rename batadv_orig_node_get_router() to batadv_orig_router_get() to follow the new naming scheme. Signed-off-by: Simon Wunderlich <simon@open-mesh.com> Signed-off-by: Marek Lindner <mareklindner@neomailbox.ch> Signed-off-by: Antonio Quartulli <antonio@meshcoding.com>
-rw-r--r--net/batman-adv/bat_iv_ogm.c454
-rw-r--r--net/batman-adv/distributed-arp-table.c3
-rw-r--r--net/batman-adv/gateway_client.c11
-rw-r--r--net/batman-adv/icmp_socket.c3
-rw-r--r--net/batman-adv/network-coding.c25
-rw-r--r--net/batman-adv/originator.c242
-rw-r--r--net/batman-adv/originator.h12
-rw-r--r--net/batman-adv/routing.c38
-rw-r--r--net/batman-adv/routing.h1
-rw-r--r--net/batman-adv/translation-table.c3
-rw-r--r--net/batman-adv/types.h32
11 files changed, 605 insertions, 219 deletions
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
index 157cc1176313..1f9fe4270454 100644
--- a/net/batman-adv/bat_iv_ogm.c
+++ b/net/batman-adv/bat_iv_ogm.c
@@ -907,21 +907,21 @@ static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface)
907 * originator 907 * originator
908 * @bat_priv: the bat priv with all the soft interface information 908 * @bat_priv: the bat priv with all the soft interface information
909 * @orig_node: the orig node who originally emitted the ogm packet 909 * @orig_node: the orig node who originally emitted the ogm packet
910 * @orig_ifinfo: ifinfo for the outgoing interface of the orig_node
910 * @ethhdr: Ethernet header of the OGM 911 * @ethhdr: Ethernet header of the OGM
911 * @batadv_ogm_packet: the ogm packet 912 * @batadv_ogm_packet: the ogm packet
912 * @if_incoming: interface where the packet was received 913 * @if_incoming: interface where the packet was received
913 * @if_outgoing: interface for which the retransmission should be considered 914 * @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. 915 * @dup_status: the duplicate status of this ogm packet.
916 */ 916 */
917static void 917static void
918batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv, 918batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
919 struct batadv_orig_node *orig_node, 919 struct batadv_orig_node *orig_node,
920 struct batadv_orig_ifinfo *orig_ifinfo,
920 const struct ethhdr *ethhdr, 921 const struct ethhdr *ethhdr,
921 const struct batadv_ogm_packet *batadv_ogm_packet, 922 const struct batadv_ogm_packet *batadv_ogm_packet,
922 struct batadv_hard_iface *if_incoming, 923 struct batadv_hard_iface *if_incoming,
923 struct batadv_hard_iface *if_outgoing, 924 struct batadv_hard_iface *if_outgoing,
924 const unsigned char *tt_buff,
925 enum batadv_dup_status dup_status) 925 enum batadv_dup_status dup_status)
926{ 926{
927 struct batadv_neigh_ifinfo *neigh_ifinfo = NULL; 927 struct batadv_neigh_ifinfo *neigh_ifinfo = NULL;
@@ -1004,14 +1004,14 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
1004 spin_unlock_bh(&neigh_node->ifinfo_lock); 1004 spin_unlock_bh(&neigh_node->ifinfo_lock);
1005 1005
1006 if (dup_status == BATADV_NO_DUP) { 1006 if (dup_status == BATADV_NO_DUP) {
1007 orig_node->last_ttl = batadv_ogm_packet->ttl; 1007 orig_ifinfo->last_ttl = batadv_ogm_packet->ttl;
1008 neigh_ifinfo->last_ttl = batadv_ogm_packet->ttl; 1008 neigh_ifinfo->last_ttl = batadv_ogm_packet->ttl;
1009 } 1009 }
1010 1010
1011 /* if this neighbor already is our next hop there is nothing 1011 /* if this neighbor already is our next hop there is nothing
1012 * to change 1012 * to change
1013 */ 1013 */
1014 router = batadv_orig_node_get_router(orig_node); 1014 router = batadv_orig_router_get(orig_node, if_outgoing);
1015 if (router == neigh_node) 1015 if (router == neigh_node)
1016 goto out; 1016 goto out;
1017 1017
@@ -1048,7 +1048,7 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
1048 goto out; 1048 goto out;
1049 } 1049 }
1050 1050
1051 batadv_update_route(bat_priv, orig_node, neigh_node); 1051 batadv_update_route(bat_priv, orig_node, if_outgoing, neigh_node);
1052 goto out; 1052 goto out;
1053 1053
1054unlock: 1054unlock:
@@ -1209,6 +1209,7 @@ batadv_iv_ogm_update_seqnos(const struct ethhdr *ethhdr,
1209{ 1209{
1210 struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface); 1210 struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
1211 struct batadv_orig_node *orig_node; 1211 struct batadv_orig_node *orig_node;
1212 struct batadv_orig_ifinfo *orig_ifinfo = NULL;
1212 struct batadv_neigh_node *neigh_node; 1213 struct batadv_neigh_node *neigh_node;
1213 struct batadv_neigh_ifinfo *neigh_ifinfo; 1214 struct batadv_neigh_ifinfo *neigh_ifinfo;
1214 int is_dup; 1215 int is_dup;
@@ -1225,13 +1226,19 @@ batadv_iv_ogm_update_seqnos(const struct ethhdr *ethhdr,
1225 if (!orig_node) 1226 if (!orig_node)
1226 return BATADV_NO_DUP; 1227 return BATADV_NO_DUP;
1227 1228
1229 orig_ifinfo = batadv_orig_ifinfo_new(orig_node, if_outgoing);
1230 if (WARN_ON(!orig_ifinfo)) {
1231 batadv_orig_node_free_ref(orig_node);
1232 return 0;
1233 }
1234
1228 spin_lock_bh(&orig_node->bat_iv.ogm_cnt_lock); 1235 spin_lock_bh(&orig_node->bat_iv.ogm_cnt_lock);
1229 seq_diff = seqno - orig_node->last_real_seqno; 1236 seq_diff = seqno - orig_ifinfo->last_real_seqno;
1230 1237
1231 /* signalize caller that the packet is to be dropped. */ 1238 /* signalize caller that the packet is to be dropped. */
1232 if (!hlist_empty(&orig_node->neigh_list) && 1239 if (!hlist_empty(&orig_node->neigh_list) &&
1233 batadv_window_protected(bat_priv, seq_diff, 1240 batadv_window_protected(bat_priv, seq_diff,
1234 &orig_node->batman_seqno_reset)) { 1241 &orig_ifinfo->batman_seqno_reset)) {
1235 ret = BATADV_PROTECTED; 1242 ret = BATADV_PROTECTED;
1236 goto out; 1243 goto out;
1237 } 1244 }
@@ -1245,7 +1252,7 @@ batadv_iv_ogm_update_seqnos(const struct ethhdr *ethhdr,
1245 1252
1246 neigh_addr = neigh_node->addr; 1253 neigh_addr = neigh_node->addr;
1247 is_dup = batadv_test_bit(neigh_ifinfo->bat_iv.real_bits, 1254 is_dup = batadv_test_bit(neigh_ifinfo->bat_iv.real_bits,
1248 orig_node->last_real_seqno, 1255 orig_ifinfo->last_real_seqno,
1249 seqno); 1256 seqno);
1250 1257
1251 if (batadv_compare_eth(neigh_addr, ethhdr->h_source) && 1258 if (batadv_compare_eth(neigh_addr, ethhdr->h_source) &&
@@ -1273,163 +1280,65 @@ batadv_iv_ogm_update_seqnos(const struct ethhdr *ethhdr,
1273 1280
1274 if (need_update) { 1281 if (need_update) {
1275 batadv_dbg(BATADV_DBG_BATMAN, bat_priv, 1282 batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
1276 "updating last_seqno: old %u, new %u\n", 1283 "%s updating last_seqno: old %u, new %u\n",
1277 orig_node->last_real_seqno, seqno); 1284 if_outgoing ? if_outgoing->net_dev->name : "DEFAULT",
1278 orig_node->last_real_seqno = seqno; 1285 orig_ifinfo->last_real_seqno, seqno);
1286 orig_ifinfo->last_real_seqno = seqno;
1279 } 1287 }
1280 1288
1281out: 1289out:
1282 spin_unlock_bh(&orig_node->bat_iv.ogm_cnt_lock); 1290 spin_unlock_bh(&orig_node->bat_iv.ogm_cnt_lock);
1283 batadv_orig_node_free_ref(orig_node); 1291 batadv_orig_node_free_ref(orig_node);
1292 if (orig_ifinfo)
1293 batadv_orig_ifinfo_free_ref(orig_ifinfo);
1284 return ret; 1294 return ret;
1285} 1295}
1286 1296
1287static void batadv_iv_ogm_process(const struct ethhdr *ethhdr, 1297
1288 struct batadv_ogm_packet *batadv_ogm_packet, 1298/**
1289 const unsigned char *tt_buff, 1299 * batadv_iv_ogm_process_per_outif - process a batman iv OGM for an outgoing if
1290 struct batadv_hard_iface *if_incoming) 1300 * @skb: the skb containing the OGM
1301 * @orig_node: the (cached) orig node for the originator of this OGM
1302 * @if_incoming: the interface where this packet was received
1303 * @if_outgoing: the interface for which the packet should be considered
1304 */
1305static void
1306batadv_iv_ogm_process_per_outif(const struct sk_buff *skb, int ogm_offset,
1307 struct batadv_orig_node *orig_node,
1308 struct batadv_hard_iface *if_incoming,
1309 struct batadv_hard_iface *if_outgoing)
1291{ 1310{
1292 struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface); 1311 struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
1293 struct batadv_hard_iface *hard_iface;
1294 struct batadv_orig_node *orig_neigh_node, *orig_node, *orig_node_tmp;
1295 struct batadv_neigh_node *router = NULL, *router_router = NULL; 1312 struct batadv_neigh_node *router = NULL, *router_router = NULL;
1313 struct batadv_orig_node *orig_neigh_node;
1314 struct batadv_orig_ifinfo *orig_ifinfo;
1296 struct batadv_neigh_node *orig_neigh_router = NULL; 1315 struct batadv_neigh_node *orig_neigh_router = NULL;
1297 struct batadv_neigh_ifinfo *router_ifinfo = NULL; 1316 struct batadv_neigh_ifinfo *router_ifinfo = NULL;
1298 int has_directlink_flag; 1317 struct batadv_ogm_packet *ogm_packet;
1299 int is_my_addr = 0, is_my_orig = 0, is_my_oldorig = 0;
1300 int is_bidirect;
1301 bool is_single_hop_neigh = false;
1302 bool is_from_best_next_hop = false;
1303 int sameseq, similar_ttl;
1304 enum batadv_dup_status dup_status; 1318 enum batadv_dup_status dup_status;
1305 uint32_t if_incoming_seqno; 1319 bool is_from_best_next_hop = false;
1320 bool is_single_hop_neigh = false;
1321 bool sameseq, similar_ttl;
1322 struct sk_buff *skb_priv;
1323 struct ethhdr *ethhdr;
1306 uint8_t *prev_sender; 1324 uint8_t *prev_sender;
1325 int is_bidirect;
1307 1326
1308 /* Silently drop when the batman packet is actually not a 1327 /* create a private copy of the skb, as some functions change tq value
1309 * correct packet. 1328 * and/or flags.
1310 *
1311 * This might happen if a packet is padded (e.g. Ethernet has a
1312 * minimum frame length of 64 byte) and the aggregation interprets
1313 * it as an additional length.
1314 *
1315 * TODO: A more sane solution would be to have a bit in the
1316 * batadv_ogm_packet to detect whether the packet is the last
1317 * packet in an aggregation. Here we expect that the padding
1318 * is always zero (or not 0x01)
1319 */ 1329 */
1320 if (batadv_ogm_packet->packet_type != BATADV_IV_OGM) 1330 skb_priv = skb_copy(skb, GFP_ATOMIC);
1331 if (!skb_priv)
1321 return; 1332 return;
1322 1333
1323 /* could be changed by schedule_own_packet() */ 1334 ethhdr = eth_hdr(skb_priv);
1324 if_incoming_seqno = atomic_read(&if_incoming->bat_iv.ogm_seqno); 1335 ogm_packet = (struct batadv_ogm_packet *)(skb_priv->data + ogm_offset);
1325
1326 if (batadv_ogm_packet->flags & BATADV_DIRECTLINK)
1327 has_directlink_flag = 1;
1328 else
1329 has_directlink_flag = 0;
1330 1336
1331 if (batadv_compare_eth(ethhdr->h_source, batadv_ogm_packet->orig)) 1337 dup_status = batadv_iv_ogm_update_seqnos(ethhdr, ogm_packet,
1338 if_incoming, if_outgoing);
1339 if (batadv_compare_eth(ethhdr->h_source, ogm_packet->orig))
1332 is_single_hop_neigh = true; 1340 is_single_hop_neigh = true;
1333 1341
1334 batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
1335 "Received BATMAN packet via NB: %pM, IF: %s [%pM] (from OG: %pM, via prev OG: %pM, seqno %u, tq %d, TTL %d, V %d, IDF %d)\n",
1336 ethhdr->h_source, if_incoming->net_dev->name,
1337 if_incoming->net_dev->dev_addr, batadv_ogm_packet->orig,
1338 batadv_ogm_packet->prev_sender,
1339 ntohl(batadv_ogm_packet->seqno), batadv_ogm_packet->tq,
1340 batadv_ogm_packet->ttl,
1341 batadv_ogm_packet->version, has_directlink_flag);
1342
1343 rcu_read_lock();
1344 list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
1345 if (hard_iface->if_status != BATADV_IF_ACTIVE)
1346 continue;
1347
1348 if (hard_iface->soft_iface != if_incoming->soft_iface)
1349 continue;
1350
1351 if (batadv_compare_eth(ethhdr->h_source,
1352 hard_iface->net_dev->dev_addr))
1353 is_my_addr = 1;
1354
1355 if (batadv_compare_eth(batadv_ogm_packet->orig,
1356 hard_iface->net_dev->dev_addr))
1357 is_my_orig = 1;
1358
1359 if (batadv_compare_eth(batadv_ogm_packet->prev_sender,
1360 hard_iface->net_dev->dev_addr))
1361 is_my_oldorig = 1;
1362 }
1363 rcu_read_unlock();
1364
1365 if (is_my_addr) {
1366 batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
1367 "Drop packet: received my own broadcast (sender: %pM)\n",
1368 ethhdr->h_source);
1369 return;
1370 }
1371
1372 if (is_my_orig) {
1373 unsigned long *word;
1374 int offset;
1375 int32_t bit_pos;
1376 int16_t if_num;
1377 uint8_t *weight;
1378
1379 orig_neigh_node = batadv_iv_ogm_orig_get(bat_priv,
1380 ethhdr->h_source);
1381 if (!orig_neigh_node)
1382 return;
1383
1384 /* neighbor has to indicate direct link and it has to
1385 * come via the corresponding interface
1386 * save packet seqno for bidirectional check
1387 */
1388 if (has_directlink_flag &&
1389 batadv_compare_eth(if_incoming->net_dev->dev_addr,
1390 batadv_ogm_packet->orig)) {
1391 if_num = if_incoming->if_num;
1392 offset = if_num * BATADV_NUM_WORDS;
1393
1394 spin_lock_bh(&orig_neigh_node->bat_iv.ogm_cnt_lock);
1395 word = &(orig_neigh_node->bat_iv.bcast_own[offset]);
1396 bit_pos = if_incoming_seqno - 2;
1397 bit_pos -= ntohl(batadv_ogm_packet->seqno);
1398 batadv_set_bit(word, bit_pos);
1399 weight = &orig_neigh_node->bat_iv.bcast_own_sum[if_num];
1400 *weight = bitmap_weight(word,
1401 BATADV_TQ_LOCAL_WINDOW_SIZE);
1402 spin_unlock_bh(&orig_neigh_node->bat_iv.ogm_cnt_lock);
1403 }
1404
1405 batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
1406 "Drop packet: originator packet from myself (via neighbor)\n");
1407 batadv_orig_node_free_ref(orig_neigh_node);
1408 return;
1409 }
1410
1411 if (is_my_oldorig) {
1412 batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
1413 "Drop packet: ignoring all rebroadcast echos (sender: %pM)\n",
1414 ethhdr->h_source);
1415 return;
1416 }
1417
1418 if (batadv_ogm_packet->flags & BATADV_NOT_BEST_NEXT_HOP) {
1419 batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
1420 "Drop packet: ignoring all packets not forwarded from the best next hop (sender: %pM)\n",
1421 ethhdr->h_source);
1422 return;
1423 }
1424
1425 orig_node = batadv_iv_ogm_orig_get(bat_priv, batadv_ogm_packet->orig);
1426 if (!orig_node)
1427 return;
1428
1429 dup_status = batadv_iv_ogm_update_seqnos(ethhdr, batadv_ogm_packet,
1430 if_incoming,
1431 BATADV_IF_DEFAULT);
1432
1433 if (dup_status == BATADV_PROTECTED) { 1342 if (dup_status == BATADV_PROTECTED) {
1434 batadv_dbg(BATADV_DBG_BATMAN, bat_priv, 1343 batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
1435 "Drop packet: packet within seqno protection time (sender: %pM)\n", 1344 "Drop packet: packet within seqno protection time (sender: %pM)\n",
@@ -1437,29 +1346,28 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
1437 goto out; 1346 goto out;
1438 } 1347 }
1439 1348
1440 if (batadv_ogm_packet->tq == 0) { 1349 if (ogm_packet->tq == 0) {
1441 batadv_dbg(BATADV_DBG_BATMAN, bat_priv, 1350 batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
1442 "Drop packet: originator packet with tq equal 0\n"); 1351 "Drop packet: originator packet with tq equal 0\n");
1443 goto out; 1352 goto out;
1444 } 1353 }
1445 1354
1446 router = batadv_orig_node_get_router(orig_node); 1355 router = batadv_orig_router_get(orig_node, if_outgoing);
1447 if (router) { 1356 if (router) {
1448 orig_node_tmp = router->orig_node; 1357 router_router = batadv_orig_router_get(router->orig_node,
1449 router_router = batadv_orig_node_get_router(orig_node_tmp); 1358 if_outgoing);
1450 router_ifinfo = batadv_neigh_ifinfo_get(router, 1359 router_ifinfo = batadv_neigh_ifinfo_get(router, if_outgoing);
1451 BATADV_IF_DEFAULT);
1452 } 1360 }
1453 1361
1454 if ((router && router_ifinfo->bat_iv.tq_avg != 0) && 1362 if ((router_ifinfo && router_ifinfo->bat_iv.tq_avg != 0) &&
1455 (batadv_compare_eth(router->addr, ethhdr->h_source))) 1363 (batadv_compare_eth(router->addr, ethhdr->h_source)))
1456 is_from_best_next_hop = true; 1364 is_from_best_next_hop = true;
1457 1365
1458 prev_sender = batadv_ogm_packet->prev_sender; 1366 prev_sender = ogm_packet->prev_sender;
1459 /* avoid temporary routing loops */ 1367 /* avoid temporary routing loops */
1460 if (router && router_router && 1368 if (router && router_router &&
1461 (batadv_compare_eth(router->addr, prev_sender)) && 1369 (batadv_compare_eth(router->addr, prev_sender)) &&
1462 !(batadv_compare_eth(batadv_ogm_packet->orig, prev_sender)) && 1370 !(batadv_compare_eth(ogm_packet->orig, prev_sender)) &&
1463 (batadv_compare_eth(router->addr, router_router->addr))) { 1371 (batadv_compare_eth(router->addr, router_router->addr))) {
1464 batadv_dbg(BATADV_DBG_BATMAN, bat_priv, 1372 batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
1465 "Drop packet: ignoring all rebroadcast packets that may make me loop (sender: %pM)\n", 1373 "Drop packet: ignoring all rebroadcast packets that may make me loop (sender: %pM)\n",
@@ -1467,7 +1375,8 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
1467 goto out; 1375 goto out;
1468 } 1376 }
1469 1377
1470 batadv_tvlv_ogm_receive(bat_priv, batadv_ogm_packet, orig_node); 1378 if (if_outgoing == BATADV_IF_DEFAULT)
1379 batadv_tvlv_ogm_receive(bat_priv, ogm_packet, orig_node);
1471 1380
1472 /* if sender is a direct neighbor the sender mac equals 1381 /* if sender is a direct neighbor the sender mac equals
1473 * originator mac 1382 * originator mac
@@ -1483,9 +1392,10 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
1483 1392
1484 /* Update nc_nodes of the originator */ 1393 /* Update nc_nodes of the originator */
1485 batadv_nc_update_nc_node(bat_priv, orig_node, orig_neigh_node, 1394 batadv_nc_update_nc_node(bat_priv, orig_node, orig_neigh_node,
1486 batadv_ogm_packet, is_single_hop_neigh); 1395 ogm_packet, is_single_hop_neigh);
1487 1396
1488 orig_neigh_router = batadv_orig_node_get_router(orig_neigh_node); 1397 orig_neigh_router = batadv_orig_router_get(orig_neigh_node,
1398 if_outgoing);
1489 1399
1490 /* drop packet if sender is not a direct neighbor and if we 1400 /* drop packet if sender is not a direct neighbor and if we
1491 * don't route towards it 1401 * don't route towards it
@@ -1497,25 +1407,41 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
1497 } 1407 }
1498 1408
1499 is_bidirect = batadv_iv_ogm_calc_tq(orig_node, orig_neigh_node, 1409 is_bidirect = batadv_iv_ogm_calc_tq(orig_node, orig_neigh_node,
1500 batadv_ogm_packet, if_incoming, 1410 ogm_packet, if_incoming,
1501 BATADV_IF_DEFAULT); 1411 if_outgoing);
1502 1412
1503 /* update ranking if it is not a duplicate or has the same 1413 /* update ranking if it is not a duplicate or has the same
1504 * seqno and similar ttl as the non-duplicate 1414 * seqno and similar ttl as the non-duplicate
1505 */ 1415 */
1506 sameseq = orig_node->last_real_seqno == ntohl(batadv_ogm_packet->seqno); 1416 orig_ifinfo = batadv_orig_ifinfo_new(orig_node, if_outgoing);
1507 similar_ttl = orig_node->last_ttl - 3 <= batadv_ogm_packet->ttl; 1417 if (!orig_ifinfo)
1418 goto out_neigh;
1419
1420 sameseq = orig_ifinfo->last_real_seqno == ntohl(ogm_packet->seqno);
1421 similar_ttl = (orig_ifinfo->last_ttl - 3) <= ogm_packet->ttl;
1422
1508 if (is_bidirect && ((dup_status == BATADV_NO_DUP) || 1423 if (is_bidirect && ((dup_status == BATADV_NO_DUP) ||
1509 (sameseq && similar_ttl))) 1424 (sameseq && similar_ttl))) {
1510 batadv_iv_ogm_orig_update(bat_priv, orig_node, ethhdr, 1425 batadv_iv_ogm_orig_update(bat_priv, orig_node,
1511 batadv_ogm_packet, if_incoming, 1426 orig_ifinfo, ethhdr,
1512 BATADV_IF_DEFAULT, tt_buff, 1427 ogm_packet, if_incoming,
1513 dup_status); 1428 if_outgoing, dup_status);
1429 }
1430 batadv_orig_ifinfo_free_ref(orig_ifinfo);
1514 1431
1515 /* is single hop (direct) neighbor */ 1432 /* is single hop (direct) neighbor */
1516 if (is_single_hop_neigh) { 1433 if (is_single_hop_neigh) {
1434 /* OGMs from secondary interfaces should only scheduled once
1435 * per interface where it has been received, not multiple times
1436 */
1437 if ((ogm_packet->ttl <= 2) &&
1438 (if_incoming != if_outgoing)) {
1439 batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
1440 "Drop packet: OGM from secondary interface and wrong outgoing interface\n");
1441 goto out_neigh;
1442 }
1517 /* mark direct link on incoming interface */ 1443 /* mark direct link on incoming interface */
1518 batadv_iv_ogm_forward(orig_node, ethhdr, batadv_ogm_packet, 1444 batadv_iv_ogm_forward(orig_node, ethhdr, ogm_packet,
1519 is_single_hop_neigh, 1445 is_single_hop_neigh,
1520 is_from_best_next_hop, if_incoming); 1446 is_from_best_next_hop, if_incoming);
1521 1447
@@ -1537,9 +1463,14 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
1537 goto out_neigh; 1463 goto out_neigh;
1538 } 1464 }
1539 1465
1466 /* only forward the packet on the default interface until the
1467 * OGM forwarding has been reworked to send on specific interfaces.
1468 */
1469 if (if_outgoing != BATADV_IF_DEFAULT)
1470 goto out_neigh;
1540 batadv_dbg(BATADV_DBG_BATMAN, bat_priv, 1471 batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
1541 "Forwarding packet: rebroadcast originator packet\n"); 1472 "Forwarding packet: rebroadcast originator packet\n");
1542 batadv_iv_ogm_forward(orig_node, ethhdr, batadv_ogm_packet, 1473 batadv_iv_ogm_forward(orig_node, ethhdr, ogm_packet,
1543 is_single_hop_neigh, is_from_best_next_hop, 1474 is_single_hop_neigh, is_from_best_next_hop,
1544 if_incoming); 1475 if_incoming);
1545 1476
@@ -1554,6 +1485,165 @@ out:
1554 if (orig_neigh_router) 1485 if (orig_neigh_router)
1555 batadv_neigh_node_free_ref(orig_neigh_router); 1486 batadv_neigh_node_free_ref(orig_neigh_router);
1556 1487
1488 kfree_skb(skb_priv);
1489}
1490
1491/**
1492 * batadv_iv_ogm_process - process an incoming batman iv OGM
1493 * @skb: the skb containing the OGM
1494 * @ogm_offset: offset to the OGM which should be processed (for aggregates)
1495 * @if_incoming: the interface where this packet was receved
1496 */
1497static void batadv_iv_ogm_process(const struct sk_buff *skb, int ogm_offset,
1498 struct batadv_hard_iface *if_incoming)
1499{
1500 struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
1501 struct batadv_orig_node *orig_neigh_node, *orig_node;
1502 struct batadv_hard_iface *hard_iface;
1503 struct batadv_ogm_packet *ogm_packet;
1504 uint32_t if_incoming_seqno;
1505 bool has_directlink_flag;
1506 struct ethhdr *ethhdr;
1507 bool is_my_oldorig = false;
1508 bool is_my_addr = false;
1509 bool is_my_orig = false;
1510
1511 ogm_packet = (struct batadv_ogm_packet *)(skb->data + ogm_offset);
1512 ethhdr = eth_hdr(skb);
1513
1514 /* Silently drop when the batman packet is actually not a
1515 * correct packet.
1516 *
1517 * This might happen if a packet is padded (e.g. Ethernet has a
1518 * minimum frame length of 64 byte) and the aggregation interprets
1519 * it as an additional length.
1520 *
1521 * TODO: A more sane solution would be to have a bit in the
1522 * batadv_ogm_packet to detect whether the packet is the last
1523 * packet in an aggregation. Here we expect that the padding
1524 * is always zero (or not 0x01)
1525 */
1526 if (ogm_packet->packet_type != BATADV_IV_OGM)
1527 return;
1528
1529 /* could be changed by schedule_own_packet() */
1530 if_incoming_seqno = atomic_read(&if_incoming->bat_iv.ogm_seqno);
1531
1532 if (ogm_packet->flags & BATADV_DIRECTLINK)
1533 has_directlink_flag = true;
1534 else
1535 has_directlink_flag = false;
1536
1537 batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
1538 "Received BATMAN packet via NB: %pM, IF: %s [%pM] (from OG: %pM, via prev OG: %pM, seqno %u, tq %d, TTL %d, V %d, IDF %d)\n",
1539 ethhdr->h_source, if_incoming->net_dev->name,
1540 if_incoming->net_dev->dev_addr, ogm_packet->orig,
1541 ogm_packet->prev_sender, ntohl(ogm_packet->seqno),
1542 ogm_packet->tq, ogm_packet->ttl,
1543 ogm_packet->version, has_directlink_flag);
1544
1545 rcu_read_lock();
1546 list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
1547 if (hard_iface->if_status != BATADV_IF_ACTIVE)
1548 continue;
1549
1550 if (hard_iface->soft_iface != if_incoming->soft_iface)
1551 continue;
1552
1553 if (batadv_compare_eth(ethhdr->h_source,
1554 hard_iface->net_dev->dev_addr))
1555 is_my_addr = true;
1556
1557 if (batadv_compare_eth(ogm_packet->orig,
1558 hard_iface->net_dev->dev_addr))
1559 is_my_orig = true;
1560
1561 if (batadv_compare_eth(ogm_packet->prev_sender,
1562 hard_iface->net_dev->dev_addr))
1563 is_my_oldorig = true;
1564 }
1565 rcu_read_unlock();
1566
1567 if (is_my_addr) {
1568 batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
1569 "Drop packet: received my own broadcast (sender: %pM)\n",
1570 ethhdr->h_source);
1571 return;
1572 }
1573
1574 if (is_my_orig) {
1575 unsigned long *word;
1576 int offset;
1577 int32_t bit_pos;
1578 int16_t if_num;
1579 uint8_t *weight;
1580
1581 orig_neigh_node = batadv_iv_ogm_orig_get(bat_priv,
1582 ethhdr->h_source);
1583 if (!orig_neigh_node)
1584 return;
1585
1586 /* neighbor has to indicate direct link and it has to
1587 * come via the corresponding interface
1588 * save packet seqno for bidirectional check
1589 */
1590 if (has_directlink_flag &&
1591 batadv_compare_eth(if_incoming->net_dev->dev_addr,
1592 ogm_packet->orig)) {
1593 if_num = if_incoming->if_num;
1594 offset = if_num * BATADV_NUM_WORDS;
1595
1596 spin_lock_bh(&orig_neigh_node->bat_iv.ogm_cnt_lock);
1597 word = &(orig_neigh_node->bat_iv.bcast_own[offset]);
1598 bit_pos = if_incoming_seqno - 2;
1599 bit_pos -= ntohl(ogm_packet->seqno);
1600 batadv_set_bit(word, bit_pos);
1601 weight = &orig_neigh_node->bat_iv.bcast_own_sum[if_num];
1602 *weight = bitmap_weight(word,
1603 BATADV_TQ_LOCAL_WINDOW_SIZE);
1604 spin_unlock_bh(&orig_neigh_node->bat_iv.ogm_cnt_lock);
1605 }
1606
1607 batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
1608 "Drop packet: originator packet from myself (via neighbor)\n");
1609 batadv_orig_node_free_ref(orig_neigh_node);
1610 return;
1611 }
1612
1613 if (is_my_oldorig) {
1614 batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
1615 "Drop packet: ignoring all rebroadcast echos (sender: %pM)\n",
1616 ethhdr->h_source);
1617 return;
1618 }
1619
1620 if (ogm_packet->flags & BATADV_NOT_BEST_NEXT_HOP) {
1621 batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
1622 "Drop packet: ignoring all packets not forwarded from the best next hop (sender: %pM)\n",
1623 ethhdr->h_source);
1624 return;
1625 }
1626
1627 orig_node = batadv_iv_ogm_orig_get(bat_priv, ogm_packet->orig);
1628 if (!orig_node)
1629 return;
1630
1631 batadv_iv_ogm_process_per_outif(skb, ogm_offset, orig_node,
1632 if_incoming, BATADV_IF_DEFAULT);
1633
1634 rcu_read_lock();
1635 list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
1636 if (hard_iface->if_status != BATADV_IF_ACTIVE)
1637 continue;
1638
1639 if (hard_iface->soft_iface != bat_priv->soft_iface)
1640 continue;
1641
1642 batadv_iv_ogm_process_per_outif(skb, ogm_offset, orig_node,
1643 if_incoming, hard_iface);
1644 }
1645 rcu_read_unlock();
1646
1557 batadv_orig_node_free_ref(orig_node); 1647 batadv_orig_node_free_ref(orig_node);
1558} 1648}
1559 1649
@@ -1561,11 +1651,9 @@ static int batadv_iv_ogm_receive(struct sk_buff *skb,
1561 struct batadv_hard_iface *if_incoming) 1651 struct batadv_hard_iface *if_incoming)
1562{ 1652{
1563 struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface); 1653 struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
1564 struct batadv_ogm_packet *batadv_ogm_packet; 1654 struct batadv_ogm_packet *ogm_packet;
1565 struct ethhdr *ethhdr;
1566 int buff_pos = 0, packet_len;
1567 unsigned char *tvlv_buff, *packet_buff;
1568 uint8_t *packet_pos; 1655 uint8_t *packet_pos;
1656 int ogm_offset;
1569 bool ret; 1657 bool ret;
1570 1658
1571 ret = batadv_check_management_packet(skb, if_incoming, BATADV_OGM_HLEN); 1659 ret = batadv_check_management_packet(skb, if_incoming, BATADV_OGM_HLEN);
@@ -1582,24 +1670,19 @@ static int batadv_iv_ogm_receive(struct sk_buff *skb,
1582 batadv_add_counter(bat_priv, BATADV_CNT_MGMT_RX_BYTES, 1670 batadv_add_counter(bat_priv, BATADV_CNT_MGMT_RX_BYTES,
1583 skb->len + ETH_HLEN); 1671 skb->len + ETH_HLEN);
1584 1672
1585 packet_len = skb_headlen(skb); 1673 ogm_offset = 0;
1586 ethhdr = eth_hdr(skb); 1674 ogm_packet = (struct batadv_ogm_packet *)skb->data;
1587 packet_buff = skb->data;
1588 batadv_ogm_packet = (struct batadv_ogm_packet *)packet_buff;
1589 1675
1590 /* unpack the aggregated packets and process them one by one */ 1676 /* unpack the aggregated packets and process them one by one */
1591 while (batadv_iv_ogm_aggr_packet(buff_pos, packet_len, 1677 while (batadv_iv_ogm_aggr_packet(ogm_offset, skb_headlen(skb),
1592 batadv_ogm_packet->tvlv_len)) { 1678 ogm_packet->tvlv_len)) {
1593 tvlv_buff = packet_buff + buff_pos + BATADV_OGM_HLEN; 1679 batadv_iv_ogm_process(skb, ogm_offset, if_incoming);
1594 1680
1595 batadv_iv_ogm_process(ethhdr, batadv_ogm_packet, 1681 ogm_offset += BATADV_OGM_HLEN;
1596 tvlv_buff, if_incoming); 1682 ogm_offset += ntohs(ogm_packet->tvlv_len);
1597 1683
1598 buff_pos += BATADV_OGM_HLEN; 1684 packet_pos = skb->data + ogm_offset;
1599 buff_pos += ntohs(batadv_ogm_packet->tvlv_len); 1685 ogm_packet = (struct batadv_ogm_packet *)packet_pos;
1600
1601 packet_pos = packet_buff + buff_pos;
1602 batadv_ogm_packet = (struct batadv_ogm_packet *)packet_pos;
1603 } 1686 }
1604 1687
1605 kfree_skb(skb); 1688 kfree_skb(skb);
@@ -1661,7 +1744,8 @@ static void batadv_iv_ogm_orig_print(struct batadv_priv *bat_priv,
1661 1744
1662 rcu_read_lock(); 1745 rcu_read_lock();
1663 hlist_for_each_entry_rcu(orig_node, head, hash_entry) { 1746 hlist_for_each_entry_rcu(orig_node, head, hash_entry) {
1664 neigh_node = batadv_orig_node_get_router(orig_node); 1747 neigh_node = batadv_orig_router_get(orig_node,
1748 BATADV_IF_DEFAULT);
1665 if (!neigh_node) 1749 if (!neigh_node)
1666 continue; 1750 continue;
1667 1751
diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c
index 997ae6ac51ff..1d214cd5738e 100644
--- a/net/batman-adv/distributed-arp-table.c
+++ b/net/batman-adv/distributed-arp-table.c
@@ -589,7 +589,8 @@ static bool batadv_dat_send_data(struct batadv_priv *bat_priv,
589 if (cand[i].type == BATADV_DAT_CANDIDATE_NOT_FOUND) 589 if (cand[i].type == BATADV_DAT_CANDIDATE_NOT_FOUND)
590 continue; 590 continue;
591 591
592 neigh_node = batadv_orig_node_get_router(cand[i].orig_node); 592 neigh_node = batadv_orig_router_get(cand[i].orig_node,
593 BATADV_IF_DEFAULT);
593 if (!neigh_node) 594 if (!neigh_node)
594 goto free_orig; 595 goto free_orig;
595 596
diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c
index 4e8f5b1eedfc..9ece204d3a00 100644
--- a/net/batman-adv/gateway_client.c
+++ b/net/batman-adv/gateway_client.c
@@ -146,7 +146,7 @@ batadv_gw_get_best_gw_node(struct batadv_priv *bat_priv)
146 continue; 146 continue;
147 147
148 orig_node = gw_node->orig_node; 148 orig_node = gw_node->orig_node;
149 router = batadv_orig_node_get_router(orig_node); 149 router = batadv_orig_router_get(orig_node, BATADV_IF_DEFAULT);
150 if (!router) 150 if (!router)
151 continue; 151 continue;
152 152
@@ -266,7 +266,8 @@ void batadv_gw_election(struct batadv_priv *bat_priv)
266 if (next_gw) { 266 if (next_gw) {
267 sprintf(gw_addr, "%pM", next_gw->orig_node->orig); 267 sprintf(gw_addr, "%pM", next_gw->orig_node->orig);
268 268
269 router = batadv_orig_node_get_router(next_gw->orig_node); 269 router = batadv_orig_router_get(next_gw->orig_node,
270 BATADV_IF_DEFAULT);
270 if (!router) { 271 if (!router) {
271 batadv_gw_reselect(bat_priv); 272 batadv_gw_reselect(bat_priv);
272 goto out; 273 goto out;
@@ -335,7 +336,7 @@ void batadv_gw_check_election(struct batadv_priv *bat_priv,
335 if (!curr_gw_orig) 336 if (!curr_gw_orig)
336 goto reselect; 337 goto reselect;
337 338
338 router_gw = batadv_orig_node_get_router(curr_gw_orig); 339 router_gw = batadv_orig_router_get(curr_gw_orig, BATADV_IF_DEFAULT);
339 if (!router_gw) 340 if (!router_gw)
340 goto reselect; 341 goto reselect;
341 342
@@ -348,7 +349,7 @@ void batadv_gw_check_election(struct batadv_priv *bat_priv,
348 if (curr_gw_orig == orig_node) 349 if (curr_gw_orig == orig_node)
349 goto out; 350 goto out;
350 351
351 router_orig = batadv_orig_node_get_router(orig_node); 352 router_orig = batadv_orig_router_get(orig_node, BATADV_IF_DEFAULT);
352 if (!router_orig) 353 if (!router_orig)
353 goto out; 354 goto out;
354 355
@@ -576,7 +577,7 @@ static int batadv_write_buffer_text(struct batadv_priv *bat_priv,
576 struct batadv_neigh_ifinfo *router_ifinfo = NULL; 577 struct batadv_neigh_ifinfo *router_ifinfo = NULL;
577 int ret = -1; 578 int ret = -1;
578 579
579 router = batadv_orig_node_get_router(gw_node->orig_node); 580 router = batadv_orig_router_get(gw_node->orig_node, BATADV_IF_DEFAULT);
580 if (!router) 581 if (!router)
581 goto out; 582 goto out;
582 583
diff --git a/net/batman-adv/icmp_socket.c b/net/batman-adv/icmp_socket.c
index 3c08eee1b920..b384cb86f5ea 100644
--- a/net/batman-adv/icmp_socket.c
+++ b/net/batman-adv/icmp_socket.c
@@ -215,7 +215,8 @@ static ssize_t batadv_socket_write(struct file *file, const char __user *buff,
215 if (!orig_node) 215 if (!orig_node)
216 goto dst_unreach; 216 goto dst_unreach;
217 217
218 neigh_node = batadv_orig_node_get_router(orig_node); 218 neigh_node = batadv_orig_router_get(orig_node,
219 BATADV_IF_DEFAULT);
219 if (!neigh_node) 220 if (!neigh_node)
220 goto dst_unreach; 221 goto dst_unreach;
221 222
diff --git a/net/batman-adv/network-coding.c b/net/batman-adv/network-coding.c
index aec3fa564027..6a0b3284219f 100644
--- a/net/batman-adv/network-coding.c
+++ b/net/batman-adv/network-coding.c
@@ -718,9 +718,21 @@ static bool batadv_can_nc_with_orig(struct batadv_priv *bat_priv,
718 struct batadv_orig_node *orig_node, 718 struct batadv_orig_node *orig_node,
719 struct batadv_ogm_packet *ogm_packet) 719 struct batadv_ogm_packet *ogm_packet)
720{ 720{
721 if (orig_node->last_real_seqno != ntohl(ogm_packet->seqno)) 721 struct batadv_orig_ifinfo *orig_ifinfo;
722 uint32_t last_real_seqno;
723 uint8_t last_ttl;
724
725 orig_ifinfo = batadv_orig_ifinfo_get(orig_node, BATADV_IF_DEFAULT);
726 if (!orig_ifinfo)
722 return false; 727 return false;
723 if (orig_node->last_ttl != ogm_packet->ttl + 1) 728
729 last_ttl = orig_ifinfo->last_ttl;
730 last_real_seqno = orig_ifinfo->last_real_seqno;
731 batadv_orig_ifinfo_free_ref(orig_ifinfo);
732
733 if (last_real_seqno != ntohl(ogm_packet->seqno))
734 return false;
735 if (last_ttl != ogm_packet->ttl + 1)
724 return false; 736 return false;
725 if (!batadv_compare_eth(ogm_packet->orig, ogm_packet->prev_sender)) 737 if (!batadv_compare_eth(ogm_packet->orig, ogm_packet->prev_sender))
726 return false; 738 return false;
@@ -1019,7 +1031,11 @@ static bool batadv_nc_code_packets(struct batadv_priv *bat_priv,
1019 int coded_size = sizeof(*coded_packet); 1031 int coded_size = sizeof(*coded_packet);
1020 int header_add = coded_size - unicast_size; 1032 int header_add = coded_size - unicast_size;
1021 1033
1022 router_neigh = batadv_orig_node_get_router(neigh_node->orig_node); 1034 /* TODO: do we need to consider the outgoing interface for
1035 * coded packets?
1036 */
1037 router_neigh = batadv_orig_router_get(neigh_node->orig_node,
1038 BATADV_IF_DEFAULT);
1023 if (!router_neigh) 1039 if (!router_neigh)
1024 goto out; 1040 goto out;
1025 1041
@@ -1029,7 +1045,8 @@ static bool batadv_nc_code_packets(struct batadv_priv *bat_priv,
1029 goto out; 1045 goto out;
1030 1046
1031 neigh_tmp = nc_packet->neigh_node; 1047 neigh_tmp = nc_packet->neigh_node;
1032 router_coding = batadv_orig_node_get_router(neigh_tmp->orig_node); 1048 router_coding = batadv_orig_router_get(neigh_tmp->orig_node,
1049 BATADV_IF_DEFAULT);
1033 if (!router_coding) 1050 if (!router_coding)
1034 goto out; 1051 goto out;
1035 1052
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c
index 1a4725f5267d..b8ef41600166 100644
--- a/net/batman-adv/originator.c
+++ b/net/batman-adv/originator.c
@@ -231,14 +231,31 @@ void batadv_neigh_node_free_ref(struct batadv_neigh_node *neigh_node)
231 call_rcu(&neigh_node->rcu, batadv_neigh_node_free_rcu); 231 call_rcu(&neigh_node->rcu, batadv_neigh_node_free_rcu);
232} 232}
233 233
234/* increases the refcounter of a found router */ 234/**
235 * batadv_orig_node_get_router - router to the originator depending on iface
236 * @orig_node: the orig node for the router
237 * @if_outgoing: the interface where the payload packet has been received or
238 * the OGM should be sent to
239 *
240 * Returns the neighbor which should be router for this orig_node/iface.
241 *
242 * The object is returned with refcounter increased by 1.
243 */
235struct batadv_neigh_node * 244struct batadv_neigh_node *
236batadv_orig_node_get_router(struct batadv_orig_node *orig_node) 245batadv_orig_router_get(struct batadv_orig_node *orig_node,
246 const struct batadv_hard_iface *if_outgoing)
237{ 247{
238 struct batadv_neigh_node *router; 248 struct batadv_orig_ifinfo *orig_ifinfo;
249 struct batadv_neigh_node *router = NULL;
239 250
240 rcu_read_lock(); 251 rcu_read_lock();
241 router = rcu_dereference(orig_node->router); 252 hlist_for_each_entry_rcu(orig_ifinfo, &orig_node->ifinfo_list, list) {
253 if (orig_ifinfo->if_outgoing != if_outgoing)
254 continue;
255
256 router = rcu_dereference(orig_ifinfo->router);
257 break;
258 }
242 259
243 if (router && !atomic_inc_not_zero(&router->refcount)) 260 if (router && !atomic_inc_not_zero(&router->refcount))
244 router = NULL; 261 router = NULL;
@@ -248,6 +265,86 @@ batadv_orig_node_get_router(struct batadv_orig_node *orig_node)
248} 265}
249 266
250/** 267/**
268 * batadv_orig_ifinfo_get - find the ifinfo from an orig_node
269 * @orig_node: the orig node to be queried
270 * @if_outgoing: the interface for which the ifinfo should be acquired
271 *
272 * Returns the requested orig_ifinfo or NULL if not found.
273 *
274 * The object is returned with refcounter increased by 1.
275 */
276struct batadv_orig_ifinfo *
277batadv_orig_ifinfo_get(struct batadv_orig_node *orig_node,
278 struct batadv_hard_iface *if_outgoing)
279{
280 struct batadv_orig_ifinfo *tmp, *orig_ifinfo = NULL;
281
282 rcu_read_lock();
283 hlist_for_each_entry_rcu(tmp, &orig_node->ifinfo_list,
284 list) {
285 if (tmp->if_outgoing != if_outgoing)
286 continue;
287
288 if (!atomic_inc_not_zero(&tmp->refcount))
289 continue;
290
291 orig_ifinfo = tmp;
292 break;
293 }
294 rcu_read_unlock();
295
296 return orig_ifinfo;
297}
298
299/**
300 * batadv_orig_ifinfo_new - search and possibly create an orig_ifinfo object
301 * @orig_node: the orig node to be queried
302 * @if_outgoing: the interface for which the ifinfo should be acquired
303 *
304 * Returns NULL in case of failure or the orig_ifinfo object for the if_outgoing
305 * interface otherwise. The object is created and added to the list
306 * if it does not exist.
307 *
308 * The object is returned with refcounter increased by 1.
309 */
310struct batadv_orig_ifinfo *
311batadv_orig_ifinfo_new(struct batadv_orig_node *orig_node,
312 struct batadv_hard_iface *if_outgoing)
313{
314 struct batadv_orig_ifinfo *orig_ifinfo = NULL;
315 unsigned long reset_time;
316
317 spin_lock_bh(&orig_node->neigh_list_lock);
318
319 orig_ifinfo = batadv_orig_ifinfo_get(orig_node, if_outgoing);
320 if (orig_ifinfo)
321 goto out;
322
323 orig_ifinfo = kzalloc(sizeof(*orig_ifinfo), GFP_ATOMIC);
324 if (!orig_ifinfo)
325 goto out;
326
327 if (if_outgoing != BATADV_IF_DEFAULT &&
328 !atomic_inc_not_zero(&if_outgoing->refcount)) {
329 kfree(orig_ifinfo);
330 orig_ifinfo = NULL;
331 goto out;
332 }
333
334 reset_time = jiffies - 1;
335 reset_time -= msecs_to_jiffies(BATADV_RESET_PROTECTION_MS);
336 orig_ifinfo->batman_seqno_reset = reset_time;
337 orig_ifinfo->if_outgoing = if_outgoing;
338 INIT_HLIST_NODE(&orig_ifinfo->list);
339 atomic_set(&orig_ifinfo->refcount, 2);
340 hlist_add_head_rcu(&orig_ifinfo->list,
341 &orig_node->ifinfo_list);
342out:
343 spin_unlock_bh(&orig_node->neigh_list_lock);
344 return orig_ifinfo;
345}
346
347/**
251 * batadv_neigh_ifinfo_get - find the ifinfo from an neigh_node 348 * batadv_neigh_ifinfo_get - find the ifinfo from an neigh_node
252 * @neigh_node: the neigh node to be queried 349 * @neigh_node: the neigh node to be queried
253 * @if_outgoing: the interface for which the ifinfo should be acquired 350 * @if_outgoing: the interface for which the ifinfo should be acquired
@@ -360,11 +457,51 @@ out:
360 return neigh_node; 457 return neigh_node;
361} 458}
362 459
460/**
461 * batadv_orig_ifinfo_free_rcu - free the orig_ifinfo object
462 * @rcu: rcu pointer of the orig_ifinfo object
463 */
464static void batadv_orig_ifinfo_free_rcu(struct rcu_head *rcu)
465{
466 struct batadv_orig_ifinfo *orig_ifinfo;
467
468 orig_ifinfo = container_of(rcu, struct batadv_orig_ifinfo, rcu);
469
470 if (orig_ifinfo->if_outgoing != BATADV_IF_DEFAULT)
471 batadv_hardif_free_ref_now(orig_ifinfo->if_outgoing);
472
473 kfree(orig_ifinfo);
474}
475
476/**
477 * batadv_orig_ifinfo_free_ref - decrement the refcounter and possibly free
478 * the orig_ifinfo (without rcu callback)
479 * @orig_ifinfo: the orig_ifinfo object to release
480 */
481static void
482batadv_orig_ifinfo_free_ref_now(struct batadv_orig_ifinfo *orig_ifinfo)
483{
484 if (atomic_dec_and_test(&orig_ifinfo->refcount))
485 batadv_orig_ifinfo_free_rcu(&orig_ifinfo->rcu);
486}
487
488/**
489 * batadv_orig_ifinfo_free_ref - decrement the refcounter and possibly free
490 * the orig_ifinfo
491 * @orig_ifinfo: the orig_ifinfo object to release
492 */
493void batadv_orig_ifinfo_free_ref(struct batadv_orig_ifinfo *orig_ifinfo)
494{
495 if (atomic_dec_and_test(&orig_ifinfo->refcount))
496 call_rcu(&orig_ifinfo->rcu, batadv_orig_ifinfo_free_rcu);
497}
498
363static void batadv_orig_node_free_rcu(struct rcu_head *rcu) 499static void batadv_orig_node_free_rcu(struct rcu_head *rcu)
364{ 500{
365 struct hlist_node *node_tmp; 501 struct hlist_node *node_tmp;
366 struct batadv_neigh_node *neigh_node; 502 struct batadv_neigh_node *neigh_node;
367 struct batadv_orig_node *orig_node; 503 struct batadv_orig_node *orig_node;
504 struct batadv_orig_ifinfo *orig_ifinfo;
368 505
369 orig_node = container_of(rcu, struct batadv_orig_node, rcu); 506 orig_node = container_of(rcu, struct batadv_orig_node, rcu);
370 507
@@ -377,6 +514,11 @@ static void batadv_orig_node_free_rcu(struct rcu_head *rcu)
377 batadv_neigh_node_free_ref_now(neigh_node); 514 batadv_neigh_node_free_ref_now(neigh_node);
378 } 515 }
379 516
517 hlist_for_each_entry_safe(orig_ifinfo, node_tmp,
518 &orig_node->ifinfo_list, list) {
519 hlist_del_rcu(&orig_ifinfo->list);
520 batadv_orig_ifinfo_free_ref_now(orig_ifinfo);
521 }
380 spin_unlock_bh(&orig_node->neigh_list_lock); 522 spin_unlock_bh(&orig_node->neigh_list_lock);
381 523
382 /* Free nc_nodes */ 524 /* Free nc_nodes */
@@ -474,6 +616,7 @@ struct batadv_orig_node *batadv_orig_node_new(struct batadv_priv *bat_priv,
474 616
475 INIT_HLIST_HEAD(&orig_node->neigh_list); 617 INIT_HLIST_HEAD(&orig_node->neigh_list);
476 INIT_LIST_HEAD(&orig_node->vlan_list); 618 INIT_LIST_HEAD(&orig_node->vlan_list);
619 INIT_HLIST_HEAD(&orig_node->ifinfo_list);
477 spin_lock_init(&orig_node->bcast_seqno_lock); 620 spin_lock_init(&orig_node->bcast_seqno_lock);
478 spin_lock_init(&orig_node->neigh_list_lock); 621 spin_lock_init(&orig_node->neigh_list_lock);
479 spin_lock_init(&orig_node->tt_buff_lock); 622 spin_lock_init(&orig_node->tt_buff_lock);
@@ -489,13 +632,11 @@ struct batadv_orig_node *batadv_orig_node_new(struct batadv_priv *bat_priv,
489 orig_node->bat_priv = bat_priv; 632 orig_node->bat_priv = bat_priv;
490 memcpy(orig_node->orig, addr, ETH_ALEN); 633 memcpy(orig_node->orig, addr, ETH_ALEN);
491 batadv_dat_init_orig_node_addr(orig_node); 634 batadv_dat_init_orig_node_addr(orig_node);
492 orig_node->router = NULL;
493 atomic_set(&orig_node->last_ttvn, 0); 635 atomic_set(&orig_node->last_ttvn, 0);
494 orig_node->tt_buff = NULL; 636 orig_node->tt_buff = NULL;
495 orig_node->tt_buff_len = 0; 637 orig_node->tt_buff_len = 0;
496 reset_time = jiffies - 1 - msecs_to_jiffies(BATADV_RESET_PROTECTION_MS); 638 reset_time = jiffies - 1 - msecs_to_jiffies(BATADV_RESET_PROTECTION_MS);
497 orig_node->bcast_seqno_reset = reset_time; 639 orig_node->bcast_seqno_reset = reset_time;
498 orig_node->batman_seqno_reset = reset_time;
499 640
500 /* create a vlan object for the "untagged" LAN */ 641 /* create a vlan object for the "untagged" LAN */
501 vlan = batadv_orig_node_vlan_new(orig_node, BATADV_NO_FLAGS); 642 vlan = batadv_orig_node_vlan_new(orig_node, BATADV_NO_FLAGS);
@@ -520,6 +661,55 @@ free_orig_node:
520} 661}
521 662
522/** 663/**
664 * batadv_purge_orig_ifinfo - purge obsolete ifinfo entries from originator
665 * @bat_priv: the bat priv with all the soft interface information
666 * @orig_node: orig node which is to be checked
667 *
668 * Returns true if any ifinfo entry was purged, false otherwise.
669 */
670static bool
671batadv_purge_orig_ifinfo(struct batadv_priv *bat_priv,
672 struct batadv_orig_node *orig_node)
673{
674 struct batadv_orig_ifinfo *orig_ifinfo;
675 struct batadv_hard_iface *if_outgoing;
676 struct hlist_node *node_tmp;
677 bool ifinfo_purged = false;
678
679 spin_lock_bh(&orig_node->neigh_list_lock);
680
681 /* for all ifinfo objects for this originator */
682 hlist_for_each_entry_safe(orig_ifinfo, node_tmp,
683 &orig_node->ifinfo_list, list) {
684 if_outgoing = orig_ifinfo->if_outgoing;
685
686 /* always keep the default interface */
687 if (if_outgoing == BATADV_IF_DEFAULT)
688 continue;
689
690 /* don't purge if the interface is not (going) down */
691 if ((if_outgoing->if_status != BATADV_IF_INACTIVE) &&
692 (if_outgoing->if_status != BATADV_IF_NOT_IN_USE) &&
693 (if_outgoing->if_status != BATADV_IF_TO_BE_REMOVED))
694 continue;
695
696 batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
697 "router/ifinfo purge: originator %pM, iface: %s\n",
698 orig_node->orig, if_outgoing->net_dev->name);
699
700 ifinfo_purged = true;
701
702 hlist_del_rcu(&orig_ifinfo->list);
703 batadv_orig_ifinfo_free_ref(orig_ifinfo);
704 }
705
706 spin_unlock_bh(&orig_node->neigh_list_lock);
707
708 return ifinfo_purged;
709}
710
711
712/**
523 * batadv_purge_orig_neighbors - purges neighbors from originator 713 * batadv_purge_orig_neighbors - purges neighbors from originator
524 * @bat_priv: the bat priv with all the soft interface information 714 * @bat_priv: the bat priv with all the soft interface information
525 * @orig_node: orig node which is to be checked 715 * @orig_node: orig node which is to be checked
@@ -607,10 +797,22 @@ batadv_find_best_neighbor(struct batadv_priv *bat_priv,
607 return best; 797 return best;
608} 798}
609 799
800/**
801 * batadv_purge_orig_node - purges obsolete information from an orig_node
802 * @bat_priv: the bat priv with all the soft interface information
803 * @orig_node: orig node which is to be checked
804 *
805 * This function checks if the orig_node or substructures of it have become
806 * obsolete, and purges this information if that's the case.
807 *
808 * Returns true if the orig_node is to be removed, false otherwise.
809 */
610static bool batadv_purge_orig_node(struct batadv_priv *bat_priv, 810static bool batadv_purge_orig_node(struct batadv_priv *bat_priv,
611 struct batadv_orig_node *orig_node) 811 struct batadv_orig_node *orig_node)
612{ 812{
613 struct batadv_neigh_node *best_neigh_node; 813 struct batadv_neigh_node *best_neigh_node;
814 struct batadv_hard_iface *hard_iface;
815 bool changed;
614 816
615 if (batadv_has_timed_out(orig_node->last_seen, 817 if (batadv_has_timed_out(orig_node->last_seen,
616 2 * BATADV_PURGE_TIMEOUT)) { 818 2 * BATADV_PURGE_TIMEOUT)) {
@@ -620,15 +822,39 @@ static bool batadv_purge_orig_node(struct batadv_priv *bat_priv,
620 jiffies_to_msecs(orig_node->last_seen)); 822 jiffies_to_msecs(orig_node->last_seen));
621 return true; 823 return true;
622 } 824 }
623 if (!batadv_purge_orig_neighbors(bat_priv, orig_node)) 825 changed = batadv_purge_orig_ifinfo(bat_priv, orig_node);
826 changed = changed || batadv_purge_orig_neighbors(bat_priv, orig_node);
827
828 if (!changed)
624 return false; 829 return false;
625 830
831 /* first for NULL ... */
626 best_neigh_node = batadv_find_best_neighbor(bat_priv, orig_node, 832 best_neigh_node = batadv_find_best_neighbor(bat_priv, orig_node,
627 BATADV_IF_DEFAULT); 833 BATADV_IF_DEFAULT);
628 batadv_update_route(bat_priv, orig_node, best_neigh_node); 834 batadv_update_route(bat_priv, orig_node, BATADV_IF_DEFAULT,
835 best_neigh_node);
629 if (best_neigh_node) 836 if (best_neigh_node)
630 batadv_neigh_node_free_ref(best_neigh_node); 837 batadv_neigh_node_free_ref(best_neigh_node);
631 838
839 /* ... then for all other interfaces. */
840 rcu_read_lock();
841 list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
842 if (hard_iface->if_status != BATADV_IF_ACTIVE)
843 continue;
844
845 if (hard_iface->soft_iface != bat_priv->soft_iface)
846 continue;
847
848 best_neigh_node = batadv_find_best_neighbor(bat_priv,
849 orig_node,
850 hard_iface);
851 batadv_update_route(bat_priv, orig_node, hard_iface,
852 best_neigh_node);
853 if (best_neigh_node)
854 batadv_neigh_node_free_ref(best_neigh_node);
855 }
856 rcu_read_unlock();
857
632 return false; 858 return false;
633} 859}
634 860
diff --git a/net/batman-adv/originator.h b/net/batman-adv/originator.h
index 29fa4c428b59..75a4d7bad620 100644
--- a/net/batman-adv/originator.h
+++ b/net/batman-adv/originator.h
@@ -34,7 +34,8 @@ batadv_neigh_node_new(struct batadv_hard_iface *hard_iface,
34 struct batadv_orig_node *orig_node); 34 struct batadv_orig_node *orig_node);
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_router_get(struct batadv_orig_node *orig_node,
38 const struct batadv_hard_iface *if_outgoing);
38struct batadv_neigh_ifinfo * 39struct batadv_neigh_ifinfo *
39batadv_neigh_ifinfo_new(struct batadv_neigh_node *neigh, 40batadv_neigh_ifinfo_new(struct batadv_neigh_node *neigh,
40 struct batadv_hard_iface *if_outgoing); 41 struct batadv_hard_iface *if_outgoing);
@@ -42,6 +43,15 @@ struct batadv_neigh_ifinfo *
42batadv_neigh_ifinfo_get(struct batadv_neigh_node *neigh, 43batadv_neigh_ifinfo_get(struct batadv_neigh_node *neigh,
43 struct batadv_hard_iface *if_outgoing); 44 struct batadv_hard_iface *if_outgoing);
44void batadv_neigh_ifinfo_free_ref(struct batadv_neigh_ifinfo *neigh_ifinfo); 45void batadv_neigh_ifinfo_free_ref(struct batadv_neigh_ifinfo *neigh_ifinfo);
46
47struct batadv_orig_ifinfo *
48batadv_orig_ifinfo_get(struct batadv_orig_node *orig_node,
49 struct batadv_hard_iface *if_outgoing);
50struct batadv_orig_ifinfo *
51batadv_orig_ifinfo_new(struct batadv_orig_node *orig_node,
52 struct batadv_hard_iface *if_outgoing);
53void batadv_orig_ifinfo_free_ref(struct batadv_orig_ifinfo *orig_ifinfo);
54
45int batadv_orig_seq_print_text(struct seq_file *seq, void *offset); 55int batadv_orig_seq_print_text(struct seq_file *seq, void *offset);
46int batadv_orig_hash_add_if(struct batadv_hard_iface *hard_iface, 56int batadv_orig_hash_add_if(struct batadv_hard_iface *hard_iface,
47 int max_if_num); 57 int max_if_num);
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c
index 4fd2687b88c2..55e9aebcbc80 100644
--- a/net/batman-adv/routing.c
+++ b/net/batman-adv/routing.c
@@ -33,13 +33,32 @@
33static int batadv_route_unicast_packet(struct sk_buff *skb, 33static int batadv_route_unicast_packet(struct sk_buff *skb,
34 struct batadv_hard_iface *recv_if); 34 struct batadv_hard_iface *recv_if);
35 35
36/**
37 * _batadv_update_route - set the router for this originator
38 * @bat_priv: the bat priv with all the soft interface information
39 * @orig_node: orig node which is to be configured
40 * @recv_if: the receive interface for which this route is set
41 * @neigh_node: neighbor which should be the next router
42 *
43 * This function does not perform any error checks
44 */
36static void _batadv_update_route(struct batadv_priv *bat_priv, 45static void _batadv_update_route(struct batadv_priv *bat_priv,
37 struct batadv_orig_node *orig_node, 46 struct batadv_orig_node *orig_node,
47 struct batadv_hard_iface *recv_if,
38 struct batadv_neigh_node *neigh_node) 48 struct batadv_neigh_node *neigh_node)
39{ 49{
50 struct batadv_orig_ifinfo *orig_ifinfo;
40 struct batadv_neigh_node *curr_router; 51 struct batadv_neigh_node *curr_router;
41 52
42 curr_router = batadv_orig_node_get_router(orig_node); 53 orig_ifinfo = batadv_orig_ifinfo_get(orig_node, recv_if);
54 if (!orig_ifinfo)
55 return;
56
57 rcu_read_lock();
58 curr_router = rcu_dereference(orig_ifinfo->router);
59 if (curr_router && !atomic_inc_not_zero(&curr_router->refcount))
60 curr_router = NULL;
61 rcu_read_unlock();
43 62
44 /* route deleted */ 63 /* route deleted */
45 if ((curr_router) && (!neigh_node)) { 64 if ((curr_router) && (!neigh_node)) {
@@ -69,16 +88,25 @@ static void _batadv_update_route(struct batadv_priv *bat_priv,
69 neigh_node = NULL; 88 neigh_node = NULL;
70 89
71 spin_lock_bh(&orig_node->neigh_list_lock); 90 spin_lock_bh(&orig_node->neigh_list_lock);
72 rcu_assign_pointer(orig_node->router, neigh_node); 91 rcu_assign_pointer(orig_ifinfo->router, neigh_node);
73 spin_unlock_bh(&orig_node->neigh_list_lock); 92 spin_unlock_bh(&orig_node->neigh_list_lock);
93 batadv_orig_ifinfo_free_ref(orig_ifinfo);
74 94
75 /* decrease refcount of previous best neighbor */ 95 /* decrease refcount of previous best neighbor */
76 if (curr_router) 96 if (curr_router)
77 batadv_neigh_node_free_ref(curr_router); 97 batadv_neigh_node_free_ref(curr_router);
78} 98}
79 99
100/**
101 * batadv_update_route - set the router for this originator
102 * @bat_priv: the bat priv with all the soft interface information
103 * @orig_node: orig node which is to be configured
104 * @recv_if: the receive interface for which this route is set
105 * @neigh_node: neighbor which should be the next router
106 */
80void batadv_update_route(struct batadv_priv *bat_priv, 107void batadv_update_route(struct batadv_priv *bat_priv,
81 struct batadv_orig_node *orig_node, 108 struct batadv_orig_node *orig_node,
109 struct batadv_hard_iface *recv_if,
82 struct batadv_neigh_node *neigh_node) 110 struct batadv_neigh_node *neigh_node)
83{ 111{
84 struct batadv_neigh_node *router = NULL; 112 struct batadv_neigh_node *router = NULL;
@@ -86,10 +114,10 @@ void batadv_update_route(struct batadv_priv *bat_priv,
86 if (!orig_node) 114 if (!orig_node)
87 goto out; 115 goto out;
88 116
89 router = batadv_orig_node_get_router(orig_node); 117 router = batadv_orig_router_get(orig_node, recv_if);
90 118
91 if (router != neigh_node) 119 if (router != neigh_node)
92 _batadv_update_route(bat_priv, orig_node, neigh_node); 120 _batadv_update_route(bat_priv, orig_node, recv_if, neigh_node);
93 121
94out: 122out:
95 if (router) 123 if (router)
@@ -406,7 +434,7 @@ batadv_find_router(struct batadv_priv *bat_priv,
406 if (!orig_node) 434 if (!orig_node)
407 return NULL; 435 return NULL;
408 436
409 router = batadv_orig_node_get_router(orig_node); 437 router = batadv_orig_router_get(orig_node, recv_if);
410 438
411 /* TODO: fill this later with new bonding mechanism */ 439 /* TODO: fill this later with new bonding mechanism */
412 440
diff --git a/net/batman-adv/routing.h b/net/batman-adv/routing.h
index 192f0aab7a2b..8920d0b1056c 100644
--- a/net/batman-adv/routing.h
+++ b/net/batman-adv/routing.h
@@ -23,6 +23,7 @@ bool batadv_check_management_packet(struct sk_buff *skb,
23 int header_len); 23 int header_len);
24void batadv_update_route(struct batadv_priv *bat_priv, 24void batadv_update_route(struct batadv_priv *bat_priv,
25 struct batadv_orig_node *orig_node, 25 struct batadv_orig_node *orig_node,
26 struct batadv_hard_iface *recv_if,
26 struct batadv_neigh_node *neigh_node); 27 struct batadv_neigh_node *neigh_node);
27int batadv_recv_icmp_packet(struct sk_buff *skb, 28int batadv_recv_icmp_packet(struct sk_buff *skb,
28 struct batadv_hard_iface *recv_if); 29 struct batadv_hard_iface *recv_if);
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
index 22c32ae12e65..ec89a1b9fc06 100644
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@ -1400,7 +1400,8 @@ batadv_transtable_best_orig(struct batadv_priv *bat_priv,
1400 1400
1401 head = &tt_global_entry->orig_list; 1401 head = &tt_global_entry->orig_list;
1402 hlist_for_each_entry_rcu(orig_entry, head, list) { 1402 hlist_for_each_entry_rcu(orig_entry, head, list) {
1403 router = batadv_orig_node_get_router(orig_entry->orig_node); 1403 router = batadv_orig_router_get(orig_entry->orig_node,
1404 BATADV_IF_DEFAULT);
1404 if (!router) 1405 if (!router)
1405 continue; 1406 continue;
1406 1407
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index 8435d7c83a14..d3e2bf486ec0 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -101,6 +101,28 @@ struct batadv_hard_iface {
101}; 101};
102 102
103/** 103/**
104 * struct batadv_orig_ifinfo - originator info per outgoing interface
105 * @list: list node for orig_node::ifinfo_list
106 * @if_outgoing: pointer to outgoing hard interface
107 * @router: router that should be used to reach this originator
108 * @last_real_seqno: last and best known sequence number
109 * @last_ttl: ttl of last received packet
110 * @batman_seqno_reset: time when the batman seqno window was reset
111 * @refcount: number of contexts the object is used
112 * @rcu: struct used for freeing in an RCU-safe manner
113 */
114struct batadv_orig_ifinfo {
115 struct hlist_node list;
116 struct batadv_hard_iface *if_outgoing;
117 struct batadv_neigh_node __rcu *router; /* rcu protected pointer */
118 uint32_t last_real_seqno;
119 uint8_t last_ttl;
120 unsigned long batman_seqno_reset;
121 atomic_t refcount;
122 struct rcu_head rcu;
123};
124
125/**
104 * struct batadv_frag_table_entry - head in the fragment buffer table 126 * struct batadv_frag_table_entry - head in the fragment buffer table
105 * @head: head of list with fragments 127 * @head: head of list with fragments
106 * @lock: lock to protect the list of fragments 128 * @lock: lock to protect the list of fragments
@@ -175,11 +197,10 @@ struct batadv_orig_bat_iv {
175 * struct batadv_orig_node - structure for orig_list maintaining nodes of mesh 197 * struct batadv_orig_node - structure for orig_list maintaining nodes of mesh
176 * @orig: originator ethernet address 198 * @orig: originator ethernet address
177 * @primary_addr: hosts primary interface address 199 * @primary_addr: hosts primary interface address
178 * @router: router that should be used to reach this originator 200 * @ifinfo_list: list for routers per outgoing interface
179 * @batadv_dat_addr_t: address of the orig node in the distributed hash 201 * @batadv_dat_addr_t: address of the orig node in the distributed hash
180 * @last_seen: time when last packet from this node was received 202 * @last_seen: time when last packet from this node was received
181 * @bcast_seqno_reset: time when the broadcast seqno window was reset 203 * @bcast_seqno_reset: time when the broadcast seqno window was reset
182 * @batman_seqno_reset: time when the batman seqno window was reset
183 * @capabilities: announced capabilities of this originator 204 * @capabilities: announced capabilities of this originator
184 * @last_ttvn: last seen translation table version number 205 * @last_ttvn: last seen translation table version number
185 * @tt_buff: last tt changeset this node received from the orig node 206 * @tt_buff: last tt changeset this node received from the orig node
@@ -192,8 +213,6 @@ struct batadv_orig_bat_iv {
192 * made up by two operations (data structure update and metdata -CRC/TTVN- 213 * made up by two operations (data structure update and metdata -CRC/TTVN-
193 * recalculation) and they have to be executed atomically in order to avoid 214 * recalculation) and they have to be executed atomically in order to avoid
194 * another thread to read the table/metadata between those. 215 * another thread to read the table/metadata between those.
195 * @last_real_seqno: last and best known sequence number
196 * @last_ttl: ttl of last received packet
197 * @bcast_bits: bitfield containing the info which payload broadcast originated 216 * @bcast_bits: bitfield containing the info which payload broadcast originated
198 * from this orig node this host already has seen (relative to 217 * from this orig node this host already has seen (relative to
199 * last_bcast_seqno) 218 * last_bcast_seqno)
@@ -218,13 +237,12 @@ struct batadv_orig_bat_iv {
218struct batadv_orig_node { 237struct batadv_orig_node {
219 uint8_t orig[ETH_ALEN]; 238 uint8_t orig[ETH_ALEN];
220 uint8_t primary_addr[ETH_ALEN]; 239 uint8_t primary_addr[ETH_ALEN];
221 struct batadv_neigh_node __rcu *router; /* rcu protected pointer */ 240 struct hlist_head ifinfo_list;
222#ifdef CONFIG_BATMAN_ADV_DAT 241#ifdef CONFIG_BATMAN_ADV_DAT
223 batadv_dat_addr_t dat_addr; 242 batadv_dat_addr_t dat_addr;
224#endif 243#endif
225 unsigned long last_seen; 244 unsigned long last_seen;
226 unsigned long bcast_seqno_reset; 245 unsigned long bcast_seqno_reset;
227 unsigned long batman_seqno_reset;
228 uint8_t capabilities; 246 uint8_t capabilities;
229 atomic_t last_ttvn; 247 atomic_t last_ttvn;
230 unsigned char *tt_buff; 248 unsigned char *tt_buff;
@@ -233,8 +251,6 @@ struct batadv_orig_node {
233 bool tt_initialised; 251 bool tt_initialised;
234 /* prevents from changing the table while reading it */ 252 /* prevents from changing the table while reading it */
235 spinlock_t tt_lock; 253 spinlock_t tt_lock;
236 uint32_t last_real_seqno;
237 uint8_t last_ttl;
238 DECLARE_BITMAP(bcast_bits, BATADV_TQ_LOCAL_WINDOW_SIZE); 254 DECLARE_BITMAP(bcast_bits, BATADV_TQ_LOCAL_WINDOW_SIZE);
239 uint32_t last_bcast_seqno; 255 uint32_t last_bcast_seqno;
240 struct hlist_head neigh_list; 256 struct hlist_head neigh_list;