Skip to content

queueing: mark ECN-capable IPv6 packets in a RED queue instead of dropping them - #1250

Open
adamgeorge309 wants to merge 1 commit into
masterfrom
topic/gy/ecn-marker-ipv6
Open

adamgeorge309 wants to merge 1 commit into
masterfrom
topic/gy/ecn-marker-ipv6

Conversation

@adamgeorge309

@adamgeorge309 adamgeorge309 commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

A RedDropper (Random Early Detection, RED) with useEcn = true now sets Congestion Experienced (CE) on an IPv6 packet that is Explicit Congestion Notification (ECN) capable, as it already does on an IPv4 one, instead of dropping it.

Closes #1249

The problem

The RED module decides between marking and dropping with the static helper EcnMarker::getEcn() (src/inet/queueing/filter/RedDropper.cc:111) and marks with EcnMarker::setEcn(). Both helpers (src/inet/queueing/marker/EcnMarker.cc:58 and :92 on master) handled only Protocol::ipv4. For an IPv6 packet getEcn() returned IP_ECN_NOT_ECT (Not ECN-Capable Transport) and setEcn() returned without changing the packet. An ECN-capable IPv6 packet was therefore dropped by RED like a Not-ECT packet, with no warning. The EcnMarker module left an IPv6 packet unchanged whatever its EcnReq tag said.

RFC 3168 section 5: "The IPv4 TOS octet corresponds to the Traffic Class octet in IPv6, and the ECN field is defined identically in both cases." RedDropper.ned documents useEcn as "packets are marked with ECN if applicable", with no IP version restriction.

With the configuration in the issue, run on master 49e1fa0945 and on this branch, a client sends User Datagram Protocol (UDP) packets with the ECN codepoint ECT(0) (ECN-Capable Transport, codepoint 2) into a 10 Mb/s bottleneck: 1000 B every 0.4 ms (20 Mb/s) for 1 s. The Random Early Detection (RED) queue has useEcn = true, minth = 3, maxth = 4, maxp = 1, wq = 1 and packetCapacity = 24. Counts from the server's packet capture and the scalars:

IPv4 IPv6 before IPv6 after
packets received with ECN Congestion Experienced (CE, codepoint 3) 1164 0 1142
packets received with ECN ECT(0) 8 1150 8
bottleneck queue length, maximum 24 4 24
RED droppedPackets:count 1304 1345 1325

UDP does not slow down on a CE mark, so after the fix the queue fills to its capacity of 24 and drops there, as with IPv4; the drop count stays high for both. IPv6 delivers about 2% fewer packets than IPv4 before and after the fix (1150 against 1172), because its header is 20 B longer: 1066 B against 1046 B per frame on the 10 Mb/s link. The IPv4 server capture is byte-identical before and after the fix.

The fix

EcnMarker.cc gains an IPv6 branch in setEcn() (line 76) and in getEcn() (line 115). The ECN field of IPv6 is the low two bits of the Traffic Class, which Ipv6Header exposes as its ecn field. setEcn() updates no checksum for IPv6, because the IPv6 header has none. RedDropper is unchanged.

Architectural surface

  • Behavior of two public static functions: EcnMarker::getEcn() and EcnMarker::setEcn() now handle IPv6 packets. Their signatures do not change. Their callers are EcnMarker::markPacket() and RedDropper (RedDropper.cc:111, 128, 132, 139).
  • Packet content: a Random Early Detection (RED) queue with useEcn = true or an EcnMarker now writes the Explicit Congestion Notification (ECN) bits of the IPv6 Traffic Class.
  • Tag: for an IPv6 packet setEcn() replaces the NetworkProtocolInd tag with one that points to the rewritten header, as it already does for IPv4.
  • EcnMarker.ned: the module description names the IPv6 Traffic Class. No parameter changes.
  • Dependency: EcnMarker.cc already includes the IPv4 and Ethernet headers behind INET_WITH_IPv4 and INET_WITH_ETHERNET. The IPv6 header include and both IPv6 branches follow the same pattern behind INET_WITH_IPv6. doc/project/enforcement/check-architecture.sh src/inet/queueing passes.

No new AV-* or NV-* ledger row. No sealed path is touched.

Verification

tests/module/IPv6_red_ecn_marking.test (new): the client sends five UDP packets, UdpBasicAppData-0 to -4, with the Explicit Congestion Notification (ECN) codepoint ECT(0) through a RedDropperQueue with useEcn = true, minth = 0, maxth = 1, wq = 1. On master Random Early Detection (RED) drops UdpBasicAppData-2 to -4 and the server receives 2 packets. With the fix the server receives all 5, and UdpBasicAppData-2 to -4 arrive with traffic class 3 (ECN Congestion Experienced, CE).

The branch is based on master 49e1fa0945. Both trees were built with make -j4 MODE=release (exit status 0), and the suites were run on both and diffed by test name:

  • cd tests/fingerprint && ./fingerprinttest -s -F tyf: 1711 pass, 0 fail and 63 errors, the same rows as on master. One error is the row ethernet-nonstandardspeed.ini -r '$datarate==5Gbps && $duplex==false', which tests/fingerprint/ethernet.csv:168 expects to error ("5e+09 bps Ethernet only supports full-duplex links"); the other 62 are scenarios of disabled optional features (VoIPStream, TcpLwip, Z3GateScheduleConfigurator, the OSG visualizer).
  • cd tests/fingerprint && ./fingerprinttest -s -F tyf -m 'redmarker|dctcp' examples.csv (exit status 0): the useEcn rows examples/inet/redmarker TcpSender1, examples/inet/dctcp DcTcpIncast and TcpRenoIncast pass.
  • cd tests/module && inet_run_module_tests -m release --no-build -l ERROR: 347 tests, 46 failures, the same 46 by name as on master (346 tests there); IPv6_red_ecn_marking.test passes.
  • cd tests/protocol/ipv6 && inet_run_protocol_tests -m release: 26 of 27 pass; Rfc8200OverlappingFragments.test fails identically on master.
  • cd tests/queueing && inet_run_queueing_tests -m release: 57 tests, 12 failures, the same 12 by name as on master (Gate_1 to _3, MultiTokenBucketClassifier_1, MultiTokenBucketMeter_1, OrdinalBasedDropper_1, OrdinalBasedDuplicator_1, PeriodicGate_1, RedDropper_1, Tagger_1, TokenBucketClassifier_1, TokenBucketMeter_1). RedDropper_1 does not reach the change: its packets carry no IP header and it leaves useEcn false.
  • make -j4 MODE=debug (exit status 0), then cd tests/module && inet_run_module_tests -m debug -f IPv6_red_ecn_marking: pass.
  • Gates in doc/project/enforcement/: check-commits.sh origin/master..HEAD, check-classification.sh origin/master..HEAD, check-architecture.sh src/inet/queueing and check-source-seals.sh pass. The unscoped check-architecture.sh, check-naming.sh --base origin/master and check-interfaces.sh exit 1 with hits that are all outside the files this commit touches.

No fingerprint or statistical baseline moves: apart from the new test, the only configurations in examples/, showcases/, tutorials/ and tests/ that set useEcn are examples/inet/redmarker and examples/inet/dctcp, both IPv4 only, and none uses EcnMarker.

Not addressed here

  • EcnMarker::setEcn() still returns silently for a packet that is neither IPv4 nor IPv6. RedDropper does not call it for such a packet, because getEcn() reports Not-ECT for it.
  • RedDropper declares a packetDropCongestion statistic, but it drops through PacketFilterBase::dropPacket(packet), which uses the reason OTHER_PACKET_DROP (src/inet/queueing/base/PacketFilterBase.cc:256), so the statistic stays 0 in the runs above.

Devin Review

EcnMarker::getEcn() and EcnMarker::setEcn() handled only Protocol::ipv4.
For an IPv6 packet getEcn() returned IP_ECN_NOT_ECT and setEcn() returned
without changing the packet. RedDropper (Random Early Detection, RED)
decides between marking and dropping with getEcn() (RedDropper.cc:111).
With useEcn = true it therefore dropped an IPv6 packet that is Explicit
Congestion Notification (ECN) capable, where it sets Congestion
Experienced (CE) on an ECN-capable IPv4 packet. The EcnMarker module left
an IPv6 packet unchanged whatever its EcnReq tag said.

RFC 3168 section 5: "The IPv4 TOS octet corresponds to the Traffic Class
octet in IPv6, and the ECN field is defined identically in both cases."
RedDropper.ned documents useEcn as "packets are marked with ECN if
applicable", with no IP version restriction.

setEcn() updates no checksum for IPv6, because the IPv6 header has none.

tests/module/IPv6_red_ecn_marking.test reproduces it: the client sends
UdpBasicAppData-0 to -4, five User Datagram Protocol (UDP) packets with
the ECN codepoint ECT(0) (ECN-Capable Transport), through a
RedDropperQueue with useEcn = true, minth = 0, maxth = 1 and wq = 1.
Before this commit Random Early Detection (RED) drops UdpBasicAppData-2
to -4 and the server receives 2 packets. After it the server receives all
5, and UdpBasicAppData-2 to -4 arrive with traffic class 3 (ECN
Congestion Experienced, CE).

No fingerprint or statistical baseline moves: apart from the new test,
the only configurations in examples/, showcases/, tutorials/ and tests/
that set useEcn are examples/inet/redmarker and examples/inet/dctcp, both
IPv4 only, and none uses EcnMarker.

Change: src.queueing.EcnMarker | behavior.change.fix | test whatsnew

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no bugs or issues to report.

Devin Review

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

queueing: EcnMarker handles only IPv4, so RED with useEcn drops ECN-capable IPv6 packets

1 participant