diff --git a/WHATSNEW b/WHATSNEW index 97d107800e0..82c565f933b 100644 --- a/WHATSNEW +++ b/WHATSNEW @@ -432,6 +432,12 @@ Notable backward incompatible changes are the following: IPassivePacketSource has two new methods, canPullPacket(gate, filter) and pullPacket(gate, filter). The filter, an IPacketFilterFunction, is the acceptance condition of the sink. The source answers and pulls as if it held only the packets that the filter matches, and the pull has the effects of a normal pull of that packet. This is the pull counterpart of canPushPacket(packet, gate): a sink can now take a packet behind a packet that it cannot accept at the moment. PassivePacketSource and EmptyPacketSource support the filter. PacketQueue offers the first packet in queue order that the filter matches. PriorityScheduler and WrrScheduler decide as if each input held only the accepted packets, and a filtered pull spends the credit of a WrrScheduler as a normal pull does. A compound queue, such as CompoundPendingQueue, passes the filter to its parts. IPacketQueue has the new method dequeuePacket(filter): it dequeues the packet that dequeuePacket() would dequeue if the queue held only the packets that the filter matches. The base classes of the queueing model throw an error for it, so a module that cannot choose among its packets refuses the filtered call. A class outside INET that implements IPassivePacketSource or IPacketQueue directly no longer compiles until it declares the new methods. See the migration guide. Simulation results do not change. +56. 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. + 20. Half-duplex Ethernet drops a frame after 16 collisions, not 17 The two half-duplex Ethernet medium access control (MAC) modules, 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: ( +%#--------------------------------------------------------------------------------------------------------------