Skip to content
Merged
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
12 changes: 8 additions & 4 deletions WHATSNEW
Original file line number Diff line number Diff line change
Expand Up @@ -532,19 +532,23 @@ Notable bug fixes are the following:

The HT mode factory now includes band and preamble format in its cache key. A 5 GHz request after an equivalent 2.4 GHz request therefore receives the requested band and timing. Previously, that request could receive the earlier mode. Identical complete requests still reuse one object.

2. TCP Limited Transmit sends only new data
2. Random Early Detection (RED) reports its early drops as congestion

RedDropper emitted every drop with reason OTHER_PACKET_DROP, so its packetDropCongestion statistic always read 0. An early drop is now reported with reason CONGESTION and a drop at the packet capacity with QUEUE_OVERFLOW. Which packets are dropped does not change; the packetDropCongestion scalars and vectors of RED queues that make early drops, including those in EthernetQosRedQueue and AFxyQueue, become non-zero.

3. TCP Limited Transmit sends only new data

With SACK and lossDetectionMode = "dupthresh", the first duplicate ACK of a flight with no more new data retransmitted the first hole: Limited Transmit took its segment from NextSeg(), whose rule 3 returns an old segment. The fast retransmit then sent the hole again, and the receiver reported a D-SACK. Limited Transmit now sends only previously unsent data, as RFC 3042 and step (3.3) of RFC 6675 say, in both loss detection modes. No fingerprint or statistical baseline of INET moves; simulations that select the dupthresh mode with SACK can change.

3. DumbTcp no longer sends an acknowledged FIN again
4. DumbTcp no longer sends an acknowledged FIN again

The retransmission timer of DumbTcp restarted at each expiry, also when nothing was outstanding, so DumbTcp sent an acknowledged FIN again every 2 seconds until the connection closed; with a peer that does not close, it went on to the end of the simulation. The timer now stops when all data, the FIN included, is acknowledged, as RFC 6298 section 5.2 says. Simulations that select DumbTcp can change.

4. Nagle no longer holds a TCP retransmission
5. Nagle no longer holds a TCP retransmission

Nagle's algorithm counted data as unacknowledged up to the highest sequence number sent. After a go-back, after a retransmission timeout or after a SYN-ACK that did not acknowledge the data of a Fast Open SYN, the partial segment at the end is a retransmission, and Nagle held it until the next retransmission timeout. Nagle now holds only new data, as RFC 9293 section 3.7.4 says and as Linux does. Simulations with losses and Nagle on (the default of Tcp and LegacyTcp) can change; 27 fingerprints and 11 statistical results of the INET examples moved. LinuxTcp, with the Nagle variant of Minshall, was not affected in the packetdrill suite.

5. TCP repairs that reach the algorithms of INET 4.7
6. TCP repairs that reach the algorithms of INET 4.7

A review of all TCP parameters found defects. Most of their repairs concern features that are new in this release (entry 34), but the repairs below also reach the algorithms and the parameters of INET 4.7. Simulations that use them can change; 30 fingerprints and 20 statistical results of the INET examples moved.

Expand Down
13 changes: 13 additions & 0 deletions src/inet/queueing/filter/RedDropper.cc
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ void RedDropper::handlePacketFiltered(Packet *packet, bool matches)
avg = decision.avg;
count = decision.count;
q_time = decision.q_time;
lastResult = decision.result;
switch (decision.result) {
case QUEUE_FULL:
EV_DEBUG << "Queue length >= capacity" << EV_FIELD(packetCapacity) << EV_ENDL;
Expand Down Expand Up @@ -167,6 +168,18 @@ void RedDropper::handlePacketFiltered(Packet *packet, bool matches)
}
}

void RedDropper::dropPacket(Packet *packet)
{
// an early drop is the congestion signal RED exists to give, a drop at the packet
// capacity is a buffer overflow, as in PacketQueue
if (lastResult == QUEUE_FULL)
PacketFilterBase::dropPacket(packet, QUEUE_OVERFLOW);
else if (lastResult == RANDOMLY_ABOVE_LIMIT || lastResult == ABOVE_MAX_LIMIT)
PacketFilterBase::dropPacket(packet, CONGESTION);
else
PacketFilterBase::dropPacket(packet, OTHER_PACKET_DROP);
}

void RedDropper::receiveSignal(cComponent *source, simsignal_t signalID, cObject *obj, cObject *details)
{
Enter_Method("%s", cComponent::getSignalName(signalID));
Expand Down
2 changes: 2 additions & 0 deletions src/inet/queueing/filter/RedDropper.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ class INET_API RedDropper : public PacketFilterBase, public cListener
bool useEcn = false;
bool markNext = false;
double randomValue = NaN; // drawn before the decision that uses it, so that a query draws nothing
RedResult lastResult = BELOW_MIN_LIMIT; // of the last decision, for the reason of a drop

ModuleRef<IPacketCollection> collection;

Expand All @@ -58,6 +59,7 @@ class INET_API RedDropper : public PacketFilterBase, public cListener
virtual bool matchesResult(RedResult result, const Packet *packet) const;

virtual void handlePacketFiltered(Packet *packet, bool matches) override;
virtual void dropPacket(Packet *packet) override;

// cListener:
virtual void receiveSignal(cComponent *source, simsignal_t signalID, cObject *obj, cObject *details) override;
Expand Down
67 changes: 67 additions & 0 deletions tests/module/RedDropper_congestion_drop_reason.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
%description:
A Random Early Detection (RED) early drop is reported with reason CONGESTION, so the
packetDropCongestion statistic of RedDropper counts it.

Topology: client --100Mbps-- router --10Mbps-- server

client sends 20 Mb/s of UDP into the router's 10 Mb/s link. The router's queue on that
link is a RedDropperQueue with maxth = 4 and a packet capacity of 24, so RED drops
packets once its average queue length reaches 4, long before the queue is full. Such
drops must be emitted with reason CONGESTION, so packetDropCongestion must count at
least one.

%#--------------------------------------------------------------------------------------------------------------
%file: test.ned

import inet.networklayer.configurator.ipv4.Ipv4NetworkConfigurator;
import inet.node.inet.Router;
import inet.node.inet.StandardHost;
import ned.DatarateChannel;

network RedDropperCongestionTest
{
submodules:
configurator: Ipv4NetworkConfigurator;
client: StandardHost;
router: Router;
server: StandardHost;
connections:
client.ethg++ <--> DatarateChannel { datarate = 100Mbps; delay = 1us; } <--> router.ethg++;
router.ethg++ <--> DatarateChannel { datarate = 10Mbps; delay = 1us; } <--> server.ethg++;
}

%#--------------------------------------------------------------------------------------------------------------
%inifile: omnetpp.ini

[General]
network = RedDropperCongestionTest
ned-path = .;../../../../src
sim-time-limit = 1.5s
record-vector-results = false
cmdenv-express-mode = true

**.router.eth[1].queue.typename = "RedDropperQueue"
**.router.eth[1].queue.red.minth = 3
**.router.eth[1].queue.red.maxth = 4
**.router.eth[1].queue.red.maxp = 1
**.router.eth[1].queue.red.wq = 1
**.router.eth[1].queue.red.packetCapacity = 24

**.client.numApps = 1
**.client.app[0].typename = "UdpBasicApp"
**.client.app[0].destAddresses = "server"
**.client.app[0].destPort = 1000
**.client.app[0].messageLength = 1000B
**.client.app[0].sendInterval = 0.4ms
**.client.app[0].startTime = 1s
**.server.numApps = 1
**.server.app[0].typename = "UdpSink"
**.server.app[0].localPort = 1000

%#--------------------------------------------------------------------------------------------------------------
%contains-regex: results/General-#0.sca
scalar RedDropperCongestionTest\.router\.eth\[1\]\.queue\.red packetDropCongestion:count [1-9][0-9]*
%#--------------------------------------------------------------------------------------------------------------
%not-contains: stdout
<!> Error
%#--------------------------------------------------------------------------------------------------------------
Loading