From b0b41bb7cfac613981e3621daa2e4463ae65942d Mon Sep 17 00:00:00 2001 From: Gyorgy Szaszko Date: Fri, 16 Oct 2026 13:10:36 +0200 Subject: [PATCH] common: add: a PACKET_TOO_BIG packet drop reason PacketDropReason had no value for a datagram that is larger than the Maximum Transmission Unit (MTU) of the next link and may not be fragmented, so Ipv4 (Don't Fragment flag set, no reason set) and Mpls (a labeled datagram with that flag, Request for Comments (RFC) 3032 Section 3.4) reported OTHER_PACKET_DROP, and Ipv4 counted these drops in packetDropUndefined together with every drop that sets no reason. PacketDropReason gains PACKET_TOO_BIG = 16, and ResultFilters registers packetDropReasonIsPacketTooBig. Ipv4::fragmentAndSend() and Mpls report the new reason, and Ipv4.ned records packetDropPacketTooBig like its other per-reason statistics. tests/module/IPv4_dont_fragment_drop_reason.test sends three datagrams with a 1000-byte payload with the Don't Fragment flag through a router whose next link has an MTU of 576 bytes, and checks that the router's packetDropPacketTooBig counts 3 and packetDropUndefined 0; before this commit, packetDropUndefined counted 3. No fingerprint changes. Statistical baselines change: every Ipv4 module records the new scalars, and the drops move from packetDropUndefined to packetDropPacketTooBig in examples/inet/tcp_pmtud and examples/quic/dplpmtud. Change: src.common.PacketDropReason | behavior.add | test statistical whatsnew --- WHATSNEW | 6 ++ src/inet/common/ResultFilters.cc | 1 + src/inet/common/Simsignals.msg | 1 + src/inet/networklayer/ipv4/Ipv4.cc | 1 + src/inet/networklayer/ipv4/Ipv4.ned | 1 + src/inet/networklayer/mpls/Mpls.cc | 2 +- .../IPv4_dont_fragment_drop_reason.test | 66 +++++++++++++++++++ 7 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 tests/module/IPv4_dont_fragment_drop_reason.test diff --git a/WHATSNEW b/WHATSNEW index 68c0405dbb7..ca1d684808f 100644 --- a/WHATSNEW +++ b/WHATSNEW @@ -402,6 +402,12 @@ Notable backward incompatible changes are the following: A TCP algorithm implemented outside INET needs a simple module type that extends TcpAlgorithm, and Define_Module() in place of Register_Class(); without the type, the connection stops with an error. Its initialize() is now initializeAlgorithm(), and the cancelEvent() helper of TcpAlgorithmBase is now cancelTimer(). See the migration guide. +50. A packet drop reason for datagrams that are too big + + PacketDropReason gains PACKET_TOO_BIG, for a datagram that is larger than the MTU of the next link and may not be fragmented, with the result filter packetDropReasonIsPacketTooBig. Ipv4 reports it for a datagram with the Don't Fragment flag set, and Mpls for a labeled datagram with that flag; both reported OTHER_PACKET_DROP before. Ipv4 records the new statistic packetDropPacketTooBig. + + Ipv4's packetDropUndefined no longer counts these drops, so its results change in simulations where routers drop such datagrams, for example examples/inet/tcp_pmtud and examples/quic/dplpmtud. A PacketDropVisualizer label that shows the reason now shows 16 or PACKET_TOO_BIG instead of -1 or OTHER_PACKET_DROP. + Notable backward compatible changes are the following: 1. IEEE 802.11 per-station rate statistics diff --git a/src/inet/common/ResultFilters.cc b/src/inet/common/ResultFilters.cc index 507b2cb4c85..93bbfb9637f 100644 --- a/src/inet/common/ResultFilters.cc +++ b/src/inet/common/ResultFilters.cc @@ -1128,6 +1128,7 @@ Register_PacketDropReason_ResultFilter("packetDropReasonIsCongestion", Congestio Register_PacketDropReason_ResultFilter("packetDropReasonIsNoProtocolFound", NoProtocolFoundPacketDropReasonFilter, NO_PROTOCOL_FOUND); Register_PacketDropReason_ResultFilter("packetDropReasonIsNoPortFound", NoPortFoundPacketDropReasonFilter, NO_PORT_FOUND); Register_PacketDropReason_ResultFilter("packetDropReasonIsDuplicateDetected", DuplicateDetectedPacketDropReasonFilter, DUPLICATE_DETECTED); +Register_PacketDropReason_ResultFilter("packetDropReasonIsPacketTooBig", PacketTooBigPacketDropReasonFilter, PACKET_TOO_BIG); Register_PacketDropReason_ResultFilter("packetDropReasonIsOther", OtherPacketDropReasonFilter, OTHER_PACKET_DROP); Register_ResultFilter("minimumSnir", MinimumSnirFromSnirIndFilter); diff --git a/src/inet/common/Simsignals.msg b/src/inet/common/Simsignals.msg index 77cfebc8069..8c3a427baf6 100644 --- a/src/inet/common/Simsignals.msg +++ b/src/inet/common/Simsignals.msg @@ -26,6 +26,7 @@ enum PacketDropReason NO_PROTOCOL_FOUND = 13; NO_PORT_FOUND = 14; DUPLICATE_DETECTED = 15; + PACKET_TOO_BIG = 16; OTHER_PACKET_DROP = -1; } diff --git a/src/inet/networklayer/ipv4/Ipv4.cc b/src/inet/networklayer/ipv4/Ipv4.cc index b7f7fde3e2e..c59584a57db 100644 --- a/src/inet/networklayer/ipv4/Ipv4.cc +++ b/src/inet/networklayer/ipv4/Ipv4.cc @@ -980,6 +980,7 @@ void Ipv4::fragmentAndSend(Packet *packet) // if "don't fragment" bit is set, throw datagram away and send ICMP error message if (ipv4Header->getDontFragment()) { PacketDropDetails details; + details.setReason(PACKET_TOO_BIG); emit(packetDroppedSignal, packet, &details); EV_WARN << "datagram larger than MTU and don't fragment bit set, sending ICMP_DESTINATION_UNREACHABLE\n"; icmp->sendPtbMessage(packet, mtu); diff --git a/src/inet/networklayer/ipv4/Ipv4.ned b/src/inet/networklayer/ipv4/Ipv4.ned index 349a1644a6f..b4815802f64 100644 --- a/src/inet/networklayer/ipv4/Ipv4.ned +++ b/src/inet/networklayer/ipv4/Ipv4.ned @@ -120,6 +120,7 @@ simple Ipv4 extends SimpleModule like IIpv4 @statistic[packetDropLifetimeExpired](title="packet drop: lifetime expired"; source=packetDropReasonIsLifetimeExpired(packetDropped); record=count,sum(packetBytes),vector(packetBytes); interpolationmode=none); @statistic[packetDropNoInterfaceFound](title="packet drop: no interface found"; source=packetDropReasonIsNoInterfaceFound(packetDropped); record=count,sum(packetBytes),vector(packetBytes); interpolationmode=none); @statistic[packetDropNoRouteFound](title="packet drop: no route found"; source=packetDropReasonIsNoRouteFound(packetDropped); record=count,sum(packetBytes),vector(packetBytes); interpolationmode=none); + @statistic[packetDropPacketTooBig](title="packet drop: packet too big"; source=packetDropReasonIsPacketTooBig(packetDropped); record=count,sum(packetBytes),vector(packetBytes); interpolationmode=none); @statistic[packetDropUndefined](title="packet drop: undefined"; source=packetDropReasonIsUndefined(packetDropped); record=count,sum(packetBytes),vector(packetBytes); interpolationmode=none); gates: input transportIn @labels(Ipv4ControlInfo/down,TcpHeader,UdpHeader,SctpHeader); diff --git a/src/inet/networklayer/mpls/Mpls.cc b/src/inet/networklayer/mpls/Mpls.cc index c840625dde2..dd08c7d45a6 100644 --- a/src/inet/networklayer/mpls/Mpls.cc +++ b/src/inet/networklayer/mpls/Mpls.cc @@ -409,7 +409,7 @@ void Mpls::processTooBigDatagram(Packet *packet, const NetworkInterface *network // Destination Unreachable message whose Next-Hop MTU leaves room for the label stack EV_WARN << "discarding a too-big datagram with the DF bit, sending ICMP_DESTINATION_UNREACHABLE" << endl; PacketDropDetails details; - details.setReason(OTHER_PACKET_DROP); + details.setReason(PACKET_TOO_BIG); emit(packetDroppedSignal, packet, &details); if (icmp != nullptr) icmp->sendPtbMessage(packet, maxDatagramLength); diff --git a/tests/module/IPv4_dont_fragment_drop_reason.test b/tests/module/IPv4_dont_fragment_drop_reason.test new file mode 100644 index 00000000000..8ce69bfdeb8 --- /dev/null +++ b/tests/module/IPv4_dont_fragment_drop_reason.test @@ -0,0 +1,66 @@ +%description: +Tests that IPv4 reports a datagram that is larger than the MTU of the next link +and has the Don't Fragment (DF) flag set with the packet drop reason +PACKET_TOO_BIG, so that the packetDropPacketTooBig statistic of Ipv4 counts it +and packetDropUndefined does not. + +hostA sends three UDP datagrams with a 1000-byte payload and DF set to hostB. The router's +link toward hostB has an MTU of 576 bytes, so the router drops all three and +sends ICMP Destination Unreachable (Fragmentation Needed) to hostA. + +%#-------------------------------------------------------------------------------------------------------------- +%file: test.ned +import inet.networklayer.configurator.ipv4.Ipv4NetworkConfigurator; +import inet.node.inet.Router; +import inet.node.inet.StandardHost; +import ned.DatarateChannel; + +network DontFragmentNetwork +{ + types: + channel ethline extends DatarateChannel + { + delay = 0.1us; + datarate = 100Mbps; + } + submodules: + configurator: Ipv4NetworkConfigurator; + hostA: StandardHost; + router: Router; + hostB: StandardHost; + connections: + hostA.ethg++ <--> ethline <--> router.ethg++; + router.ethg++ <--> ethline <--> hostB.ethg++; +} +%#-------------------------------------------------------------------------------------------------------------- +%inifile: omnetpp.ini +[General] +ned-path = ../../../../src +network = DontFragmentNetwork +sim-time-limit = 5s +record-vector-results = false +cmdenv-express-mode = true + +**.router.eth[1].mac.mtu = 576B + +**.hostA.numApps = 1 +**.hostA.app[0].typename = "UdpBasicApp" +**.hostA.app[0].destAddresses = "hostB" +**.hostA.app[0].destPort = 1000 +**.hostA.app[0].messageLength = 1000B +**.hostA.app[0].dontFragment = true +**.hostA.app[0].startTime = 1s +**.hostA.app[0].sendInterval = 1s +**.hostA.app[0].stopTime = 3.5s +%#-------------------------------------------------------------------------------------------------------------- +%postrun-command: gawk '$1 == "scalar" && $2 == "DontFragmentNetwork.router.ipv4.ip" && ($3 == "packetDropPacketTooBig:count" || $3 == "packetDropUndefined:count") { print $3, $4 }' results/*.sca > drops.out +%contains: drops.out +packetDropPacketTooBig:count 3 +%#-------------------------------------------------------------------------------------------------------------- +%contains: drops.out +packetDropUndefined:count 0 +%#-------------------------------------------------------------------------------------------------------------- +%postrun-command: grep "undisposed object:" test.out > test_undisposed.out || true +%not-contains: test_undisposed.out +undisposed object: ( +%#--------------------------------------------------------------------------------------------------------------