aboutsummaryrefslogtreecommitdiffstats
path: root/net/batman-adv/bat_iv_ogm.c
diff options
context:
space:
mode:
authorSimon Wunderlich <simon@open-mesh.com>2013-11-13 13:14:47 -0500
committerAntonio Quartulli <antonio@meshcoding.com>2014-01-12 08:41:11 -0500
commit7351a4822d42827ba0110677c0cbad88a3d52585 (patch)
treecc3e4200c1f1ff0b27f370c451b6a36493b74d79 /net/batman-adv/bat_iv_ogm.c
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>
Diffstat (limited to 'net/batman-adv/bat_iv_ogm.c')
-rw-r--r--net/batman-adv/bat_iv_ogm.c454
1 files changed, 269 insertions, 185 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