Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions src/inet/networklayer/icmpv6/Ipv6NeighbourDiscovery.cc
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ Ipv6NeighbourDiscovery::~Ipv6NeighbourDiscovery()

for (auto *entry : advIfList) {
cancelAndDelete(entry->raTimeoutMsg);
cancelAndDelete(entry->pendingSolicitedRaMsg);
delete entry;
}

Expand Down Expand Up @@ -1208,7 +1209,18 @@ void Ipv6NeighbourDiscovery::processRsPacket(Packet *packet, const Ipv6RouterSol
// computed time, ignore the random delay and let that advertisement serve
// this solicitation (RFC 4861 Section 6.2.6).
if (scheduledTime < advIfEntry->nextScheduledRATime) {
/*This advertisement becomes the next multicast RA on the interface, so it
supersedes the solicited one that was pending until now: that one was
scheduled to serve the earlier solicitations, and this one, being earlier,
serves them too. Sending both would put two multicast RAs on the link less
than MIN_DELAY_BETWEEN_RAS apart, which RFC 4861 Section 6.2.6 forbids.*/
if (advIfEntry->pendingSolicitedRaMsg) {
EV_DETAIL << "Cancelling the solicited RA scheduled at " << advIfEntry->nextScheduledRATime
<< "; this earlier one supersedes it\n";
cancelAndDelete(advIfEntry->pendingSolicitedRaMsg);
}
scheduleAt(scheduledTime, msg);
advIfEntry->pendingSolicitedRaMsg = msg;
advIfEntry->nextScheduledRATime = scheduledTime;
}
else
Expand Down Expand Up @@ -1727,6 +1739,8 @@ void Ipv6NeighbourDiscovery::sendSolicitedRa(cMessage *msg)
Ipv6Address destAddr = Ipv6Address("FF02::1");
EV_DETAIL << "Testing condition!\n";
createAndSendRaPacket(destAddr, ie);
if (AdvIfEntry *advIfEntry = fetchAdvIfEntry(ie))
advIfEntry->pendingSolicitedRaMsg = nullptr;
Comment on lines +1742 to +1743

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Later solicitations lose timely replies

After a solicited advertisement fires, sendSolicitedRa leaves the next-advertisement time in the past. Later solicitations get no reply until the periodic advertisement.

Prompt for agents
The new pendingSolicitedRaMsg bookkeeping is cleared in Ipv6NeighbourDiscovery::sendSolicitedRa, but AdvIfEntry::nextScheduledRATime still names the solicited message that has just fired. processRsPacket then rejects every new future candidate because it compares against this past timestamp. Track the periodic RA's scheduled time separately from the pending solicited RA, or restore the effective next RA time when the solicited message fires. Preserve the existing overlap cancellation behavior and add a module-test phase where another Router Solicitation arrives after the first solicited RA but well before the periodic timer; it must receive a timely solicited RA.
Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

delete msg;
}

Expand Down Expand Up @@ -2693,6 +2707,7 @@ void Ipv6NeighbourDiscovery::stop()
// cancel and delete all advertising interface entries
for (auto *entry : advIfList) {
cancelAndDelete(entry->raTimeoutMsg);
cancelAndDelete(entry->pendingSolicitedRaMsg);
delete entry;
}
advIfList.clear();
Expand Down
1 change: 1 addition & 0 deletions src/inet/networklayer/icmpv6/Ipv6NeighbourDiscovery.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ class INET_API Ipv6NeighbourDiscovery : public OperationalBase, protected cListe
simtime_t nextScheduledRATime; // stores time when next RA will be sent.
simtime_t lastMulticastRATime = -1; // time the last multicast RA was sent (-1 = none yet); used to rate-limit RAs to MIN_DELAY_BETWEEN_RAS (RFC 4861 Section 6.2.6)
cMessage *raTimeoutMsg; // the message to cancel when resetting RA timer
cMessage *pendingSolicitedRaMsg = nullptr; // solicited RA scheduled on this interface but not yet sent (nullptr = none); cancelled when a solicitation schedules an earlier one
};
typedef std::vector<AdvIfEntry *> AdvIfList;

Expand Down
4 changes: 2 additions & 2 deletions tests/fingerprint/examples.csv
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@

# /examples/inet/hierarchical99/, -f .qtenv.ini -c General -r 0
/examples/inet/hierarchical99/, -f networklayer.ini -c IPv4 -r 0, 10000s, a94d-edae/tplx;1f32-e325/~tNl;b138-ee8b/~tND;66c9-cd73/tyf, PASS, EthernetMac Ipv4
/examples/inet/hierarchical99/, -f networklayer.ini -c IPv6 -r 0, 10000s, 0001-0108/tplx;3960-479e/~tNl;add1-e848/~tND;2c03-abef/tyf, PASS, EthernetMac
/examples/inet/hierarchical99/, -f networklayer.ini -c IPv6 -r 0, 10000s, 6164-8ced/tplx;6b03-6322/~tNl;e7c1-b997/~tND;2c03-abef/tyf, PASS, EthernetMac
/examples/inet/hierarchical99/, -f networklayer.ini -c Generic -r 0, 10000s, 6ae4-6e75/tplx;2209-80ac/~tNl;93bf-6657/tyf, PASS, EthernetMac
/examples/inet/hierarchical99/, -f networklayer.ini -c Flooding -r 0, 10000s, 7ba7-5b91/tplx;b0f0-411e/~tNl;2b94-8906/tyf, PASS, EthernetMac
/examples/inet/hierarchical99/, -f networklayer.ini -c ProbabilisticBroadcast -r 0, 10000s, 5a54-9779/tplx;1165-a70b/~tNl;760b-abfc/tyf, PASS, EthernetMac
Expand Down Expand Up @@ -381,7 +381,7 @@
/examples/manetrouting/multiradio/, -f omnetpp.ini -c SingleRadio -r 0, 20s, 85a0-51b8/tplx;c07a-44e1/~tNl;3aa0-49ed/tyf, PASS, wireless adhoc Ipv4

/examples/ipv6/mipv6/, -f omnetpp.ini -c Handover -r 0, 70s, 19b8-20a4/tplx;b378-071d/~tNl;d358-e3bb/~tND;44ef-1a45/tyf, PASS, wireless EthernetMac
/examples/ipv6/mipv6/, -f omnetpp.ini -c RouteOptimizationTwoCNs -r 0, 60s, 3f0c-078d/tplx;04e1-1f03/~tNl;4199-2b15/~tND;ed3e-17fa/tyf, PASS, wireless EthernetMac
/examples/ipv6/mipv6/, -f omnetpp.ini -c RouteOptimizationTwoCNs -r 0, 60s, 5115-7e10/tplx;a522-3d29/~tNl;5319-39f4/~tND;ed3e-17fa/tyf, PASS, wireless EthernetMac
/examples/ipv6/mipv6roaming/, -f omnetpp.ini -c Roaming -r 0, 70s, 0798-40c2/tplx;a682-8d0e/~tNl;cdb7-1b34/~tND;afae-2b3c/tyf, PASS, wireless EthernetMac
/examples/ipv6/pmipv6/, -f omnetpp.ini -c General -r 0, 60s, f614-da0d/tplx;8b55-7191/~tNl;b490-dc09/~tND;0277-d784/tyf, PASS, wireless EthernetMac

Expand Down
4 changes: 2 additions & 2 deletions tests/fingerprint/mipv6-refactoring.csv
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

# MIPv6 example — the primary test
/examples/ipv6/mipv6/, -f omnetpp.ini -c Handover -r 0, 70s, aa29-a8c5/~tNlb, PASS, wireless EthernetMac
/examples/ipv6/mipv6/, -f omnetpp.ini -c RouteOptimizationTwoCNs -r 0, 60s, 068b-23aa/~tNlb, PASS, wireless EthernetMac
/examples/ipv6/mipv6/, -f omnetpp.ini -c RouteOptimizationTwoCNs -r 0, 60s, b108-5896/~tNlb, PASS, wireless EthernetMac
/examples/ipv6/mipv6roaming/, -f omnetpp.ini -c Roaming -r 0, 70s, 7ed8-bee3/~tNlb, PASS, wireless EthernetMac

# IPv6 examples
Expand All @@ -23,7 +23,7 @@
/examples/ipv6/nclients/, -f omnetpp.ini -c PPP_SCTP -r 0, 100s, 06b9-ff17/~tNlb, PASS,

# IPv6 networking examples
/examples/inet/hierarchical99/, -f networklayer.ini -c IPv6 -r 0, 10000s, f206-a0e2/~tNlb, PASS, EthernetMac
/examples/inet/hierarchical99/, -f networklayer.ini -c IPv6 -r 0, 10000s, 1cbb-1534/~tNlb, PASS, EthernetMac
/examples/inet/udpclientserver/, -f omnetpp.ini -c udp_OK_ipv6 -r 0, 10s, 8feb-3936/~tNlb, PASS,
/examples/inet/udpclientserver/, -f omnetpp.ini -c udp_Port_Unav_ipv6 -r 0, 10s, 9661-c1f5/~tNlb, PASS,
/examples/inet/udpclientserver/, -f omnetpp.ini -c udp_Host_Unav_ipv6 -r 0, 10s, 6360-9ed1/~tNlb, PASS,
Expand Down
85 changes: 85 additions & 0 deletions tests/module/IPv6_RA_min_delay_between_RAs.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
%description:
Tests that consecutive multicast Router Advertisements (RA) sent by an IPv6 router to
the all-nodes address are never closer than MIN_DELAY_BETWEEN_RAS (3 s), even when
several Router Solicitations (RS) arrive while a solicited advertisement is already
pending (RFC 4861 Section 6.2.6).

Six hosts boot at the same time on one link, so their solicitations reach router R
within a fraction of a second of each other, while the advertisement scheduled for the
first of them has not been sent yet. Each solicitation computes its own send time from
a random delay in [0, MAX_RA_DELAY_TIME], so a later solicitation can land earlier than
the pending advertisement. When it does, the router must let that one advertisement
serve them all, not send both.

The scenario depends on the random delays the run draws, so the test also asserts that
the superseding case really occurred. Without that, a change elsewhere that shifts the
random number stream could leave the run with no overlapping solicitations at all, and
the rate-limit assertion would then pass without exercising anything.

%#--------------------------------------------------------------------------------------------------------------
%file: test.ned
import inet.networklayer.configurator.ipv6.Ipv6FlatNetworkConfigurator;
import inet.node.ethernet.EthernetSwitch;
import inet.node.ipv6.Router6;
import inet.node.ipv6.StandardHost6;
import ned.DatarateChannel;

network RaRateLimit
{
types:
channel ethline extends DatarateChannel
{
delay = 0.1us;
datarate = 10Mbps;
}
submodules:
configurator: Ipv6FlatNetworkConfigurator;
switch: EthernetSwitch;
R: Router6;
host[6]: StandardHost6;
connections:
R.ethg++ <--> ethline <--> switch.ethg++;
for i=0..5 {
host[i].ethg++ <--> ethline <--> switch.ethg++;
}
}
%#--------------------------------------------------------------------------------------------------------------
%inifile: omnetpp.ini
[General]
record-vector-results = false
ned-path = ../../../../src
network = RaRateLimit
sim-time-limit = 30s
cmdenv-express-mode = false
**.cmdenv-log-level = detail
cmdenv-log-prefix = "%t %C: "

# RFC 4861 defaults, and also INET's own NED defaults: no periodic advertisement is due
# within the run, so every advertisement seen here is a solicited one
**.R.ipv6.neighbourDiscovery.minIntervalBetweenRAs = 200s
**.R.ipv6.neighbourDiscovery.maxIntervalBetweenRAs = 600s

# all hosts boot together, as after a power failure
**.host[*].ipv6.neighbourDiscovery.hostBootupTime = 0.4s

# Ethernet NIC configuration
**.eth[*].queue.typename = "EthernetQosQueue"
**.eth[*].queue.dataQueue.typename = "DropTailQueue"
**.eth[*].queue.dataQueue.packetCapacity = 10

%#--------------------------------------------------------------------------------------------------------------
%subst: /omnetpp:://
%#--------------------------------------------------------------------------------------------------------------
%postrun-command: awk '/R\.ipv6\.neighbourDiscovery: Create and send RA invoked/ { if (prev != "" && $1 - prev < 3) printf "VIOLATION: two multicast RAs %.6f s apart, at %s and %s\n", $1 - prev, prev, $1; prev = $1 }' test.out > ra_gaps.out
%not-contains: ra_gaps.out
VIOLATION
%#--------------------------------------------------------------------------------------------------------------
%contains: stdout
RaRateLimit.host[5].ipv6.neighbourDiscovery: Assigning new address to: eth0
%#--------------------------------------------------------------------------------------------------------------
%contains: stdout
R.ipv6.neighbourDiscovery: Cancelling the solicited RA scheduled at
%#--------------------------------------------------------------------------------------------------------------
%postrun-command: grep "undisposed object:" test.out > test_undisposed.out || true
%not-contains: test_undisposed.out
undisposed object: (