Skip to content

[protocol] reactive forward ants have no flood bound in dense graphs — PDR 75.8→21.7, NRL 99.9→3071 on large-scale (#169 regression) #173

Description

@danieljoppi

Summary

Since PR #170 (the #169 hop-cap fix) landed on main, a single route discovery in a dense graph cost a combinatorial number of control packets — 30,090 reactive ants in a 7×7 testbench grid. In ns-3 it collapsed the two dense/large scenarios:

scenario PDR before → after NRL before → after
large-scale (100 nodes) 75.8 → 21.7 99.9 → 3071.1 (30×)
heavy-load (40 flows) 85.0 → 51.4 6.1 → 28.6
paper-base 81.7 → 82.2 59.1 → 84.8
high-mobility 82.4 → 85.8 55.9 → 72.2
dense-small 37.4 → 37.3 4.4 → 5.0
sparse-static 83.8 → 93.0 48.3 → 46.5

AODV/OLSR/DSDV were byte-identical across the two runs (untouched code, identical seeds), so this was ours. Source: the per-merge benchmarks refresh, 7835df460ab6ff, the first taxonomy measured after both #167 and #170.

#169's diagnosis was right and was not reverted — the sparse-static row is the proof: 83.8 → 93.0, ahead of AODV's 81.9, with the static/sparse inversion gone. The bug was that removing that bound left reactive forward ants with no flood bound.

Root cause: #96 and #170 each removed one of the two bounds

core/src/ant_router_logic.cpp:

if (config_.enableMultipath && incoming.isForward() &&
    incoming.type == AntType::Reactive) {
    ...
    if (!genQuality_.accept(...)) return {RouteDecision::drop()};
} else if (!history_.record(incoming.src, incoming.seqNum)) {
    return {RouteDecision::drop()};
}

With enableMultipath on (the default), a reactive forward ant took the first branch and so never touched history_ — strict (src,seq) duplicate suppression did not apply to it. GenerationTracker::accept() is not a suppressor: it admits any later same-generation copy within antAcceptanceFactor (1.5) of the best so far. In a dense graph a node receives the same generation from many neighbours at comparable cost, admits repeatedly, and each re-broadcast seeds more admissible copies.

Until PR #170 this was truncated by reactiveMaxBroadcasts = 2. Once that became -1, the only remaining ceiling was maxPathLength = 100 — no bound at all at these node counts. Each change was individually justified; nobody checked the interaction, and #169's own test used a line topology, where nothing can multiply.

Reproduction

core/tests/test_reactive_flood_bound.cpp — an 8-connected grid (dense and with a distant destination; a line shows nothing, a full mesh makes the destination a direct neighbour so discovery never runs):

grid nodes before the fix after (shipped) multipath=off
3×3 9 10 10 10
4×4 16 76 34 18
5×5 25 420 94 28
6×6 36 4,094 152 40
7×7 49 30,090 236 54

Fix (PR #174)

Bound re-broadcasts per (node, generation) instead of per ant-path: GenerationTracker gains a broadcast counter per generation, reactiveMaxBroadcasts is re-specified as that per-node bound (default 2), and a node that exhausts its allowance may still unicast-forward along pheromone, so reach is unaffected — verified by test_reactive_hop_reach.cpp, which still passes at 9 hops.

ns-3 verification

Run 30165318267, PDR / NRL:

scenario v1.0.0 broken main fixed AODV
dense-small 37.4 / 4.4 37.3 / 5.0 37.1 / 5.0 32.8 / 2.3
paper-base 81.7 / 59.1 82.2 / 84.8 83.4 / 56.6 80.5 / 56.6
sparse-static 83.8 / 48.3 93.0 / 46.5 90.7 / 40.7 81.9 / 42.9
high-mobility 82.4 / 55.9 85.8 / 72.2 86.6 / 58.0 85.1 / 56.0
heavy-load 85.0 / 6.1 51.4 / 28.6 80.1 / 8.7 86.6 / 5.5
large-scale 75.8 / 99.9 21.7 / 3071.1 77.9 / 167.8 67.4 / 163.4

Closing as the regression is resolved: large-scale 21.7 → 77.9 with NRL down 18×, and every scenario at or above v1.0.0 except heavy-load.

Two things are explicitly not claimed, and both are carried forward in #177:

  1. heavy-load is not fully recovered — 80.1 vs 85.0 pre-fix(core): stop bounding reactive floods — a broadcast budget is a hop limit (#169) #170, still behind AODV's 86.6. pdr_sd is 4.56 at 2 runs so some is dispersion, but not all of it.
  2. The shipped bound has no basis in either primary source. The 2007 thesis records the authors abandoning band-multipath for precisely this overhead problem, and our factor of 1.5 is looser than the 0.9 base they ran. [protocol] decide the reactive route-setup design on measurement: thesis single-route (A) vs source-parameterised band (B) vs the repo bound (C, shipped) #177 evaluates the thesis's single-route design (A) and the source-parameterised band (B) against the shipped bound (C) at runs=5.

All numbers above are 2-run --quick values and need a runs=5 confirmation before being quoted anywhere.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions