Repository navigation
Expand file tree
/
Copy pathWHATSNEW
More file actions
6764 lines (4891 loc) · 348 KB
/
Copy pathWHATSNEW
File metadata and controls
6764 lines (4891 loc) · 348 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
Recent changes in the INET Framework
====================================
INET-4.7.x (in development)
---------------------------
Notable backward incompatible changes are the following:
1. IEEE 802.11 rate control per receiver
IEEE 802.11 rate control now selects and adapts the transmission rate separately for each peer a station transmits to. The rate controls previously kept a single set of adaptive state per module, so the feedback of all peers was blended into one rate.
To make this possible, the getRate() method of the IRateControl C++ interface, implemented by AarfRateControl and OnoeRateControl, now takes the MAC address of the receiver. This change requires the modification of rate control models implemented outside INET, which no longer compile until their getRate() is given the new argument. Simulation models that only configure a rate control are unaffected.
Rate selection no longer consults the rate control for group-addressed frames, which are never acknowledged and so could never have their rate corrected by feedback. They now take a mandatory rate, as they already did when no rate control was configured.
These changes may change the statistical results of simulations that use an adaptive rate control, either where a station transmits to several peers or where it sends group-addressed traffic.
2. IEEE 802.11 wire and reception corrections
QoS Control fields now use the standard bit positions. Non-QoS Data no longer aliases the QoS TID-0 duplicate cache. OFDM radios generate and check SIGNAL parity and reject undefined RATE codes; HR/DSSS and ERP transmissions carry their specific PHY protocol identities.
AP beacon intervals are rounded down to whole 1024-us TUs for both target scheduling and advertisement (100ms becomes 99.328ms). Configured intervals must be between 1 and 65535 TUs. Beacon and Probe Response frames now encode the DSSS Current Channel for 2.4 GHz operation. Their channelNumber field is a standard channel number, with -1 for an absent element, rather than an internal channel index. Radio channel parameters and scan results remain internal indices. Custom frame producers should follow the migration guide.
The mesh no-forwarding-information reason code is corrected from 60 to 62. These corrections change affected packet bytes and may change Wi-Fi simulation trajectories and fingerprints.
Noncompliant layered OFDM retains its configured mode and RATE-0 placeholder; SIGNAL parity is checked in both compliant and noncompliant operation.
3. UDP no longer reports a received datagram twice
The Udp module emitted packetReceivedFromLower a second time for every datagram it received from the network layer. Its base class, LayeredProtocolBase, already emits the signal before it calls handleLowerPacket, and Udp emitted it again in processUDPPacket. Every other protocol module emits it once.
No statistic changes, because Udp.ned declares the signal and sources no statistic from it. Code that subscribes to the signal on a UDP module is affected: it now runs once per datagram instead of twice, so a listener that counted arrivals or summed bytes reported twice the true value and now reports the true one.
4. Resending accepts the packets that a producer offers
The canPushPacket() method of the Resending protocol element tested its packet argument instead of the packet that the module holds, so it refused every packet that a producer asked about. An active producer that asks before it pushes, for example a PacketServer after a queue, therefore never passed a packet to Resending. Resending now accepts a packet whenever it holds none, as its canPushSomePacket() method already did.
This changes the results of simulations that feed Resending from such a producer. Inside INET, the client in the Network6 and Network7 steps of tutorials/protocol now sends its packet; before, it sent none.
5. An unrecognized ICMP or ICMPv6 type is discarded, not thrown
Icmp::processIcmpMessage and the ICMPv6 type switch each had a default branch for a message type they do not know, and each branch threw a cRuntimeError. Any peer could therefore end a simulation with one packet.
RFC 1122 section 3.2.2 and RFC 4443 section 2.4(b) both require a silent discard. Both branches now emit packetDropped and delete the packet. A simulation that used to stop with "Unknown ICMP type" carries on.
No baseline moves. A scenario that reached either branch aborted, so it cannot be in a passing fingerprint or statistical baseline.
6. IPv6 reassembly writes the payload length of the reassembled datagram
Ipv6FragBuf::addFragment rebuilt the datagram from the base header of the first fragment and left its Payload Length field untouched, so the field described that fragment and not the datagram.
Where the field exceeded the reassembled data, Ipv6::decapsulate asserted and the run stopped. Where it fell short, which is the ordinary two-fragment case, the same function truncated the datagram silently to the first fragment's length. Every IPv6 reassembly was affected. The field now counts every octet after the base header, extension headers included, as RFC 8200 section 3 requires.
The same function also erased a stale end() iterator when one fragment completed a datagram, which aborted the run on an atomic fragment.
Simulations that reassemble IPv6 fragments deliver whole datagrams now, so their trajectories and fingerprints may change.
7. ICMPv6 drops an error report for a protocol nothing registered
Icmpv6 handed the error indication up to the protocol the quoted datagram names without asking whether anything on the node had registered it. The MessageDispatcher then knew no route and stopped the run, so any node could be halted by an ICMPv6 error about a protocol it does not run.
Icmpv6 already kept the set of registered transport protocols and never read it. It reads it now and drops the report, as Icmp has always done for IPv4.
8. No ICMP or ICMPv6 error about a link-layer broadcast or multicast
Icmp::maySendErrorMessage and Icmpv6::validateDatagramPromptingError each suppressed an error report for four conditions, and every condition read an IP address. RFC 1122 section 3.2.2 and RFC 4443 section 2.4(e) also forbid a report about a datagram that arrived in a link-layer broadcast or multicast frame, which no IP address records.
Both functions read the MacAddressInd tag of the arriving frame now. A node that receives a unicast-addressed datagram inside a broadcast frame, for a closed port or an unknown protocol, stays silent instead of answering the address in the source field.
Simulations where that happens send fewer ICMP messages, so their trajectories and fingerprints may change.
9. IPv6 fills in two length fields it used to leave wrong
A Packet Too Big report carried an MTU of zero. Icmpv6::sendErrorMessage took no MTU and handed createPacketTooBigMsg a literal 0, under a bare "TODO implement MTU support". It takes one now, and Ipv6 passes the MTU it has already read from the outgoing interface two lines above the call, as RFC 4443 section 3.2 requires. A source that receives the report can act on it.
Every fragment of a fragmented datagram carried the Payload Length of the whole datagram, because Ipv6::fragmentAndSend builds each fragment from a copy of the base header. Each fragment now carries its own: the fragment header plus that fragment's share.
Simulations that fragment IPv6 datagrams or report a too-big packet put different bytes on the wire, so their fingerprints may change.
10. IPv4 verifies the header checksum, and reassembly reads the protocol
Ipv4 dropped a datagram whose header checksum failed only when the header was also structurally incorrect: the guard read "!isCorrect() && !verifyChecksum()" and an AND short-circuits, so a well-formed header never reached the checksum test and a wrong checksum was accepted. The guard is an OR now, which is what RFC 1122 section 3.2.1.2 requires.
Ipv4FragBuf::Key, the reassembly key, carried three of the four fields RFC 791 names: source, destination and identification, but not the protocol. Fragments of two datagrams that shared an identification but used different protocols reassembled into each other. The key carries the protocol now.
Simulations with header bit errors drop more datagrams than before, and simulations that fragment two protocols at once reassemble them apart, so fingerprints for those scenarios may change.
11. An ARP packet a host cannot process is discarded, not thrown
Arp::processArpPacket stopped the run in two places a neighbour controls. Its opcode switch threw on any operation the model does not implement, and RFC 5494 section 3 makes 24 and 25 legal values a neighbour may put on a link. And it peeked the packet with the default flags, which turns an incorrect chunk into an error; the serializer marks a packet incorrect when its hardware space is not Ethernet or its protocol space is not IPv4, so nothing ever read that mark.
Both now end processing, as RFC 826 states: the unknown opcode breaks out of the switch after the table step, and the unsupported space is dropped with a packetDropped signal. The two RARP branches still throw, which the model means as a statement that it does not implement RARP.
12. TCP takes its first round-trip measurement as RFC 6298 states
rttMeasurementComplete folded the first measurement into the recurrence of RFC 6298 section 2.3, starting from srtt = 0 and rttvar = 3/4. The first smoothed value was therefore one eighth of the measurement and the first timeout described the initial guess rather than the path.
Section 2.2 gives the first measurement a case of its own: SRTT = R and RTTVAR = R/2. The estimator now does that, and a new rttMeasured flag in the algorithm state tells the two cases apart.
Every TCP connection's early retransmission timeout changes, so trajectories and fingerprints of TCP simulations move with it.
13. QUIC closes the connection on an unknown frame type, and a server pads its Initial datagram
A frame of a type the model does not know threw a cRuntimeError, so any peer could stop a run with one frame. RFC 9000 section 12.4 makes it a connection error of type FRAME_ENCODING_ERROR, and the model now sends CONNECTION_CLOSE with that code. Two further stops sat behind it: the frame loop read on past the error into bytes that are no frame header, and the datagram loop then read those bytes as a packet header. Both stop when a connection error is raised.
PacketBuilder::buildServerInitialPacket did not pad. RFC 9000 section 14.1 requires a server to expand a datagram carrying an ack-eliciting Initial packet to at least 1200 octets, which the client's builder has always done.
14. DHCP corrects seven defects in its client and server
The client drew a new transaction identifier for every DHCPREQUEST, so a request never carried the identifier of the offer it answered, against RFC 2131 section 4.4.1. It keeps the identifier of the exchange now, and a new transaction draws its own.
The server wrote three field values it had no right to write. It put the gateway address into the giaddr of a DHCPOFFER, where RFC 2131 table 3 wants the giaddr of the client's DHCPDISCOVER; it put the leased address into the ciaddr of a DHCPACK, where the table allows only the client's ciaddr or zero; and it wrote a constant false into the flags of every reply, where the table wants the flags of the message it answers. It also returned a domain name server option holding 0.0.0.0, because nothing in the model ever assigns that field.
The server stayed silent for a DHCPREQUEST naming an address of a foreign subnet, because it asked its lease table before it asked about the subnet and a foreign address is in no table. RFC 2131 section 4.3.2 wants a DHCPNAK.
The client's retransmission delay was a constant 60 seconds, and it never repeated a DHCPREQUEST at all: it abandoned the transaction at the first timeout. RFC 2131 section 4.1 asks for a randomized exponential backoff, 4 seconds doubling to 64, and section 3.1 asks for the request to be repeated. Both are there now, for the initial exchange only: RENEWING and REBINDING keep the schedule of section 4.4.5.
DHCP exchanges now take different times and put different bytes on the wire, so trajectories and fingerprints of simulations that use DHCP move.
15. A DHCP client checks the granted address before it takes it
RFC 2131 section 4.4.1 asks a client to check that the address it was granted is not already in use, and RFC 5227 section 2.1.1 makes that check an ARP Probe. The client now sends one, waits probeWait (1s by default; 0s turns the check off), and takes the address only if nobody answers. If somebody does, it sends a DHCPDECLINE and starts again. It probes only an address it is about to start using, after REQUESTING or REBOOTING, and only on a link that uses ARP.
Three of the four pieces this needed were already written and unreachable. Arp::sendArpProbe had no caller, DhcpClient::sendDecline had no caller, and Arp::processArpPacket threw "wrong ARP packet: source IPv4 address is empty" on the very packet a probe is, so a neighbour's lawful probe stopped the run. An all-zero sender protocol address marks a probe: it claims nothing, so the table steps are skipped for it and the target question still gets its answer.
Arp gained an arpAddressConflictDetected signal. A reply to a probe is addressed to the all-zero sender address, so the target question cannot recognize it; Arp remembers what it is probing and matches the reply by its sender protocol address instead.
IArp gained a pure virtual sendArpProbe, which DhcpClient calls. An IArp implementation outside INET must override it; the migration guide says how. GlobalArp overrides it with an empty body, because it has nobody to ask.
DhcpClient gained an arpModule parameter and a probeWait parameter. DHCPDECLINE now carries the server identifier, which RFC 2131 table 5 requires.
DhcpServer marks a declined address unavailable, which RFC 2131 section 4.3.3 makes a MUST. Without it the server offered the same address again and the client declined again for the whole run.
Every DHCP client now spends probeWait between the acknowledgement and taking the address. The lease timers T1 and T2 are armed when the acknowledgement arrives, so renewal timing does not move; traffic from the client starts one probeWait later.
16. IEEE 802.11 management recovery belongs to each EDCAF
Management failures and completion now update the contention window and retry state of the affected access category. Previously the shared recovery procedure changed the best-effort window even for voice management frames.
The hcf.edca.mgmtAndNonQoSRecoveryProcedure module moves beneath each edcaf[i], and its C++ getter moves from Edca to Edcaf. Update configuration, signal subscriptions and result paths as described in the migration guide. Management-recovery trajectories may change, including Block Ack agreement negotiation. The MacQosWithBlockAck example fingerprints are updated; the QoS and NonQos showcase fingerprint controls remain unchanged.
17. IEEE 802.11 PHY mode properties for response-rate selection
The physical layer (PHY) mode interface now exposes the mode family, legacy preamble type, and non-HT reference rate. Custom rate selectors can query these properties without a dependency on a concrete mode class. HT means High Throughput; VHT means Very High Throughput. The reference rate for HT and VHT modes depends on the modulation and code rate of stream 1. An unsupported reference-rate mapping returns bps(NaN), where NaN means not a number.
IIeee80211Mode gains three pure virtual methods: getModulationClass(), getLegacyPreambleType(), and getNonHtReferenceRate(). Direct implementations outside INET must implement these methods before they compile again. Ieee80211ModeBase supplies default unknown values for custom subclasses. The migration guide explains the return values and required overrides.
18. IEEE 802.11 radio commands wait for an accepted frame
Tx is the component that transmits frames for medium access control (MAC). Radio reconfiguration now waits until Tx completes an accepted transmission. This includes the short interframe space (SIFS) before a response. The MAC previously used only the medium state, which cannot identify that wait.
For example, a radio command arrives while Tx waits to transmit an acknowledgment (ACK) frame. The MAC keeps the command until the ACK completes. This prevents radio reconfiguration before the accepted response completes. The change affects event order and the event fingerprints of IEEE 802.11 simulations.
Custom implementations of ITx must implement hasTransmission() before they compile again. The method identifies both the wait before transmission and the transmission itself. The migration guide explains the return values and the order of the completion callback.
19. IEEE 802.11 recipient responses do not extend their local NAV
Tx requires an explicit local NAV choice in both transmitFrame() overloads. The NAV records a reservation of the medium. Custom C++ implementations and callers must add updateLocalNav. DCF holder frames use true. HCF holder frames and recipient responses use false. The migration guide supplies the signatures and completion rules.
CTS, ACK, and Basic Block Ack responses retain their duration fields without extending the recipient's local NAV. Received reservations still control channel access. For example, a recipient can answer another RTS from the same holder when its own previous CTS would otherwise leave the medium busy.
HCF clamps response durations to zero and applies ceiling to whole microseconds before transmission. These shared changes can change Wi-Fi simulation results.
20. Every transmission and reception in progress of a radio
IRadio gained getTransmissionsInProgress() and getReceptionsInProgress(), which return every transmission the radio is transmitting and every reception it is attempting, in no particular order. ReceiverBase and the canvas visualizers use them instead of getTransmissionInProgress() and getReceptionInProgress(), so that they also work for a radio that has several signals in progress at once (see the next item). For Radio, NoiseSource and ShortcutRadio, which have at most one in each direction, the vectors hold at most one element, and nothing else changes.
This change requires the modification of C++ code that implements IRadio without deriving from Radio: the two methods are pure virtual.
21. Radio: concurrent transmissions and receptions
Radio can now transmit any number of signals at the same time, and attempt any number of receptions at the same time, as a technology with concurrent per-user transmissions (e.g. a cellular base station) needs. Both are allowed by new Radio parameters, allowConcurrentTransmissions and allowConcurrentReceptions, which default to false. With allowConcurrentReceptions set, every reception the receiver's computeIsReceptionAttempted() accepts is attempted alongside the ones in progress; the receivers shipped with INET attempt one reception at a time either way, so the switch only matters with a receiver that attempts more.
The behavior with the defaults is unchanged, but the C++ API of Radio subclasses changed: the protected receptionTimer and transmissionTimer members were replaced by the attemptedReceptionTimers and transmissionTimers vectors, and continueTransmission(), endTransmission() and abortTransmission() take the transmission timer as an argument. A subclass that dropped the attempted reception on a reconfiguration by resetting receptionTimer calls abandonAttemptedReceptions() instead. getTransmissionInProgress(), getReceptionInProgress(), getTransmittedSignalPart() and getReceivedSignalPart() answer as before while at most one signal is in progress in their direction, and throw an error while several are. A model that relies on them, such as the StateBasedEpEnergyConsumer and StateBasedCcEnergyConsumer energy consumers, therefore cannot be used with a radio that has several signals in progress at once.
This change requires the modification of C++ code that derives from Radio and accesses these members or overrides these methods.
22. Interference for a listening of the caller's making
IRadioMedium gained computeInterference(receiver, listening), formerly a protected member of RadioMedium: the background noise plus the receptions, at the receiver, of the transmissions on the medium that overlap the listening, for a listening that need not belong to any transmission. The result is not cached, but the receptions in it come from the medium's reception cache: the ones not computed yet are computed at the call, and draw their random numbers, if any, then. Together with the propagation, the receiver's createListening() and the analog model, it lets a radio compute a hypothetical SNIR (e.g. for link-quality estimation) from public API.
This change requires the modification of C++ code that implements IRadioMedium without deriving from RadioMedium.
23. IEEE 802.11 single protection and shared TXNAV
HCF now checks complete continuation costs under single protection with Block Ack support disabled. Before the next SIFS, the exchange cost must be strictly less than remaining TXNAV. The initial SIFS plus exchange cost must fit the positive TXOP limit. This separation permits bursts whose preceding ACK's propagation delay consumes part of the initial SIFS budget. For example, a 238 us exchange proceeds with 246.67 us TXNAV and sufficient TXOP time, after 10 us SIFS.
A refused frame remains available for a fresh grant without a retry increment or failed-rate feedback. HCF retains the admitted DATA mode through RTS/CTS. Forecasts preserve the retained successor's mode and ACK policy.
When the next exchange needs RTS/CTS, the preceding field's successor term contains RTS airtime, one SIFS, and CTS airtime. It excludes the protected DATA and its response. The complete RTS/CTS/DATA/response cost exceeds the remaining TXNAV with unchanged estimates. Single protection therefore refuses that continuation before RTS.
For example, after DATA A and its ACK, queued DATA B needs RTS/CTS. B waits for a fresh grant after TXNAV expires. An initial exchange can still use RTS/CTS.
The first exchange retains a compatibility fallback, including under an insufficient positive limit. TXOP-based fragmentation remains unsupported. A zero limit permits no additional exchange. Block Ack support disables the new admission check even without an agreement. Multiple protection retains its separate admission policy.
Rx now owns shared TXNAV separately from received NAV. Successful holder frames replace TXNAV from their PPDU end and encoded Duration/ID. TXNAV persists after TXOP end and blocks contention, but it does not itself prevent an eligible CTS response. DCF retains its local NAV behavior.
HCF also blocks local contention through its active sequence. This prevents a second grant during an initial ACK wait before successful TXNAV exists. Normal AIFS and backoff follow channel release.
Single protection now excludes the current ACK estimate for group management and non-QoS DATA, with Block Ack support enabled or disabled. With support enabled, the legacy forecast can still reserve an ineligible group successor.
TxOpFs publishes the ACK policy before RTS. If Block Ack replaces a stale Normal Ack policy, the single protection RTS field omits the unnecessary ACK and its SIFS. These field and contention changes can change Wi-Fi simulation results and fingerprints. The separate expiry event and corrected sequence observations can also change fingerprints.
Custom IRx implementations need the TXNAV operations. Sequence callbacks need the start notification and Boolean submission result. Custom ACK policies must not depend on HCF's removed second policy query. See the migration guide.
24. The distance form of the path loss is computeDistancePathLoss()
IPathLoss::computePathLoss(propagationSpeed, frequency, distance) was renamed to computeDistancePathLoss(), so that it is no longer an overload of the method that computes the path loss of a reception (see the next item): a model that overrode one of the overloads hid the other. Its documentation now states that the value is independent of the transmitter and the receiver, and may be NaN when the model cannot tell the loss from the distance alone (TwoRayInterference).
This change requires the modification of C++ code that implements or calls computePathLoss(propagationSpeed, frequency, distance): every path loss model derived from PathLossBase overrides it.
25. The path loss of a reception knows its receiver
IPathLoss::computePathLoss(transmission, arrival) was replaced by computeReceptionPathLoss(receiverRadio, transmission, arrival). It returns an IReceptionPathLoss, the path loss of that one reception, whose computePathLoss(frequency) gives the loss factor at any frequency, the way IAntenna::getGain() returns an IAntennaGain. Together with the transmission's transmitter radio, the receiver radio identifies the link, so a path loss can now keep per-link state (for example a shadowing that is correlated over distance). Both medium analog models call it once per reception: ScalarMediumAnalogModel evaluates the result at the center frequency, DimensionalMediumAnalogModel across the band, in place of the computeDistancePathLoss() it called before. A path loss with per-link state resolves that state in the call, and the returned object holds values only, so the value of a reception does not depend on when or how often the dimensional model evaluates it. The PathLossBase default evaluates computeDistancePathLoss() for the link's distance, so the results of models that only implement that form are unchanged. The FrequencyDependentAttenuationFunction constructor takes the reception's path loss as its second argument.
TwoRayGroundReflection and TwoRayInterference now take the geometry of the link into account under DimensionalMediumAnalogModel too: before, the former acted as FreeSpacePathLoss there, and the latter returned NaN.
This change requires the modification of C++ code that implements or calls computePathLoss(transmission, arrival), or constructs FrequencyDependentAttenuationFunction objects.
26. MPLS follows the TTL rules of RFC 3032
The TTL field of every label stack entry was 0. A pushed entry now copies the TTL of the entry below it, or of the IPv4 header when it is the first label, and each LSR forwards a labeled packet with the incoming TTL minus one, as RFC 3032 section 2.4 and the Uniform Model of RFC 3443 state.
The IPv4 TTL also counts the LSRs now. The ingress decrements it before it labels a datagram, and leaves a datagram with TTL 1 to IPv4, which reports it; a pop that empties the label stack writes the outgoing TTL into the IPv4 header. Before, a datagram left an LSP with the TTL it had at the ingress. An LSR now discards a labeled packet whose outgoing TTL is zero, with a packetDropped signal; before, no LSR looked at the TTL.
27. MPLS works on Ethernet links
An MPLS router with an Ethernet interface stopped the simulation at the first ARP packet, because the MPLS module threw on every protocol other than MPLS and IPv4. Such a packet now goes to the network layer. A labeled packet now also goes through the Ethernet encapsulation, with the ethertype 8847 hex. A LIB entry holds no next hop, so the frame goes to the broadcast address of the link; on a point-to-point link that is the one neighbor.
28. MPLS knows the IPv4 Explicit NULL and the Implicit NULL labels
An LSR now pops the label 0 at the bottom of the stack with no binding and forwards the datagram by its IPv4 header, and pops the stack where a swap would give the label 3, as RFC 3032 section 2.1 states. The LIB accepts these values as outgoing labels; before, a debug build refused the label 0, and the label 3 went onto the wire. The LIB now allocates labels from 16, after the reserved values; before, RSVP-TE and LDP got labels from 1.
29. MPLS fragments a labeled datagram that is too big for the next link
An LSR sent a labeled packet of any length, also onto a link with a smaller MTU. It now compares the length with the MTU of the outgoing interface, as RFC 3032 section 3 states. It fragments an IPv4 datagram with the DF bit clear, and each fragment carries the label stack; for a datagram with the DF bit set, it sends an ICMP Destination Unreachable message whose Next-Hop MTU is the MTU minus the label stack. The new parameter icmpModule of Mpls names the ICMP module, by default the one of the node's IPv4 layer.
30. IPsec corrections to the AH and ESP packets
The first packet of an SA now carries the Sequence Number 1, as RFC 4302 and RFC 4303 state; before, it carried 0. The C++ method SecurityAssociation::getAndIncSeqNum() is now incrementAndGetSeqNum(), and returns the incremented value.
The AH header now has the layout of RFC 4302: its Payload Length holds the length of the header in 32-bit words minus 2 (before, 0), and the ICV field ends the header, before the payload (before, the ICV followed the payload). In IPv6 the ICV field has the padding that makes the header a multiple of 8 octets, so an AH packet over IPv6 is 4 octets longer with a 16-octet ICV. The payload of AH is no longer an EncryptedChunk, because AH does not encrypt, and the AH dissector reads the new layout.
The padding of an ESP packet now holds the octets 1, 2, 3 and so on, as RFC 4303 section 2.4 states; before, every octet held the default 63 of a ByteCountChunk.
After AH or ESP processing, the receiver now checks that the packet matches the selectors of the SA that protected it, and discards it if not (RFC 4301 section 5.2). Before, an SA accepted every packet with its SPI, so a sender could reach any port of the receiver through one SA.
A packet that matches a PROTECT entry, and no SA of it, is now discarded (RFC 4301 section 5.1); before, it left the host in clear.
One policy can now protect a packet with ESP and AH together. The new Protection element of a SecurityAssociation overrides the Protection of its SecurityPolicy, so an ESP policy can hold an AH SA as well. The sender applies ESP first and AH around it, whatever the order of the SAs, and the receiver processes the ESP header that follows an AH header. Before, the documentation named a Protection AH_ESP that the configuration refused.
An SA can now have a hard lifetime (RFC 4301 section 4.4.2.1): the new elements HardLifetimeSeconds and HardLifetimeBytes of a SecurityAssociation or of its SecurityPolicy. With no key management to replace it, an SA whose lifetime has ended is not used any more, and its packets are discarded.
An SA can now have a set of DSCP values, the new DSCP element of a SecurityAssociation (RFC 4301 section 4.4.2.1). Of the SAs of one policy, the sender uses the first whose set holds the DSCP of the packet, so that classes of traffic can have SAs of their own. Before, the first matching SA carried every packet.
An outbound ESP SA can now send dummy packets (RFC 4303 section 2.6), with the new DummyPacketInterval element of a SecurityAssociation: ESP packets with Next Header 59 and an empty payload, to the peer of the last packet that the SA protected. The receiver discards them without an error. For this, the IPsec module has the new gates ipIn and ipOut, which the IPv4 and IPv6 network layers connect to their dispatcher.
31. IEEE 802.11 response queries require an explicit caller role
Sender estimates now query the recipient's HT capabilities instead of the sender's own peer address. This correction can change response reservations, timeout estimates, and TXOP admission in existing HT simulations.
External IRateSelection and IQosRateSelection implementations and callers must add ResponseQueryRole to their response queries. Use PREDICT for sender estimates. Use RESPOND for recipient responses. The migration guide supplies the signatures and links to the prediction limits.
32. IEEE 802.11 ac interfaces also expose current HT support
ac interfaces now use existing HT capability and management support alongside VHT and legacy OFDM. Advertised and negotiated HT operation remains limited to 20 MHz and four spatial streams. Added HT modes can change ACK/CTS candidates and adaptive rate steps, including steps between equal nominal rates.
ac APs require a band with standard channel conversion, including simplified management. The supplied ac configurations now use "5 GHz (mapped 20 MHz)" at 5180 MHz. This frequency change can affect propagation results and fingerprints. See the migration guide for configuration changes and the IEEE 802.11 user guide for radio requirements and model limits.
33. IEEE 802.11 Block Ack recipients preserve delivery order
Basic Block Ack recipients now count sequence positions as buffer capacity. All fragments of one MSDU occupy one position. A one-position buffer can therefore accept both fragments and deliver the complete MSDU.
DATA that fills a gap releases all consecutive complete units in the same operation. DATA beyond the window moves the window and releases older complete units. A valid BAR for an accepted agreement also creates and advances an empty reorder record before DATA arrives. Delivery follows cyclic sequence order, including 4095 before 0. These repairs can change delivery times, simulation results, and fingerprints in affected Block Ack scenarios.
Custom C++ consumers must use the ordered ReleasedFrames return type from BlockAckReordering. Preserve its order through reassembly and deaggregation. The migration guide gives the required change. Basic frame formats and fragment bitmaps remain available.
The protected getEarliestCompleteMsduOrAMsduIfExists() helper remains available for one release but is deprecated. External subclasses retain its lookup behavior during that period. Delivery code must use the ordered release results instead. The migration guide explains the different ownership contracts.
34. TCP takes the defaults of the RFCs, and gains LinuxTcp and LegacyTcp
The TCP model was reworked. A flavour is now a choice of congestion control (ITcpCongestionControl) and of loss recovery (ITcpRecovery). The model gained CUBIC (TcpCubic), RACK-TLP loss detection, Proportional Rate Reduction, F-RTO, the undo of a spurious loss, Accurate ECN, TCP Fast Open, keepalive probes, the path MTU search of RFC 4821, and many parameters that select a behavior of Linux. The documentation of the Tcp module lists each RFC, what the model implements, and where it departs from the RFC.
The defaults of Tcp now follow the RFCs. This changes each simulation that uses TCP without setting these parameters (INET 4.7 -> now):
sackSupport false -> true
timestampSupport false -> true
windowScalingSupport false -> true
delayedAcksEnabled false -> true
limitedTransmitEnabled false -> true
advertisedWindow 14 * this.mss -> 65535
mss 536 -> -1 (1460 for IPv4, 1440
for IPv6)
initial window one segment -> initialWindow = "rfc3390"
(RFC 5681 section 3.1)
tcpAlgorithmClass "TcpReno" -> "TcpNewReno"
initial RTO 3 s -> initialRto = 1s
loss detection three duplicates -> RACK-TLP (lossDetectionMode,
tlpEnabled)
recovery window halved at once -> PRR (prrEnabled)
PSH never set -> on the last buffered segment
(pushLastBufferedSegment)
ECN off -> answers a request
(tcpEcnMode = "passive")
pmtudEnabled false -> true (DF on IPv4 segments)
The results of TCP simulations differ from INET 4.7 in any case, also because many defects were repaired. To keep the old defaults, select LegacyTcp, which extends Tcp and changes only defaults:
**.tcp.typename = "LegacyTcp"
LinuxTcp extends Tcp in the same way, with the defaults of Linux 7.1: CUBIC with the hybrid slow start, an initial window of ten segments, the timers and the delayed ACK of Linux, and the other behaviors of Linux that parameters select. A parameter that the ini file sets takes precedence over the defaults of the selected module.
Two parameters are deprecated: increasedIWEnabled (use initialWindow = "rfc3390") and ecnWillingness (use tcpEcnMode = "rfc3168"). They still work in this release.
Two C++ base classes were renamed: TcpBaseAlg is now TcpAlgorithmBase, and TcpTahoeRenoFamily is now TcpClassicAlgorithmBase. The old names remain as deprecated aliases in this release. A TCP algorithm implemented outside INET needs more than the rename, however: the split into congestion control and recovery moved much of the protected interface that a flavour overrides, so such an algorithm must be written against ITcpCongestionControl and ITcpRecovery.
The connection has the new signals sndMax, delivered and deliveredCe.
35. Packet classifiers answer a query without a change of state
PacketClassifierBase::classifyPacket() is now a const function. The base class calls it from queries, such as canPushPacket() and canPullPacket(), and again from the operation that moves the packet, so it must not change the state of the module. The base class calls the new function handlePacketClassified() one time for each packet that goes through the module, and one time for each packet stream, before the packet leaves the module. A classifier that keeps state changes it there.
This change requires the modification of classifiers implemented outside INET, which no longer compile until their classifyPacket() is const. See the migration guide.
A pull stream through a classifier now classifies its packet one time, at the start of the stream. Before, each call of the stream classified it.
36. A token bucket classifier takes the tokens of a packet one time
TokenBucketClassifier and MultiTokenBucketClassifier, and the classifiers that extend them in NED (SingleRateTwoColorClassifier, SingleRateThreeColorClassifier and DualRateThreeColorClassifier), removed the tokens of a packet in each query about the packet, and again when the packet went through. For example, a PacketServer asks canPushPacket() before it pushes a packet. In pull mode, each peek removed tokens. The classifier now removes the tokens one time, when the packet goes through. This can change the results of simulations in which a module asks a token bucket classifier about a packet before it pushes the packet.
37. A weighted round-robin classifier moves its round only for a packet
WrrClassifier moved its round forward in each query about a packet, for example when a module asked canPushPacket() before it pushed the packet. The packets then went to other consumers than the weights state. The classifier now moves its round only when a packet goes through. This can change the results of simulations in which a module asks a WrrClassifier about a packet before it pushes the packet.
38. A dynamic classifier creates a branch only for a packet
DynamicClassifier creates the branch of a class when the first packet of the class goes through, or when a module asks canPushPacket() about such a packet, because the answer depends on the branch. Before, its other queries created branches too. The classifier now refuses the reverseOrder parameter, because it creates its output gates in the order in which the classes appear. With reverseOrder = true, it created more branches than classes, and it sent packets of different classes into one branch.
39. Packet schedulers answer a query without a change of state
PacketSchedulerBase::schedulePacket() is now a const function. The base class calls it from queries, such as canPushSomePacket(), and again from the operation that moves the packet, so it must not change the state of the module. The base class calls the new function handlePacketScheduled() one time for each packet that goes through the module, and one time for each packet stream, when the module holds the packet and before the packet leaves the module. A scheduler that keeps state changes it there.
This change requires the modification of schedulers implemented outside INET, which no longer compile until their schedulePacket() is const. See the migration guide.
40. A label scheduler skips an empty input
LabelScheduler read the labels of the packet that each input offered, and it crashed when an input had no packet. It now skips an empty input.
41. A packet scheduler offers the packet that it serves
canPullPacket() of PacketSchedulerBase returned the packet of the first input that had a packet, and pullPacket() served the input that schedulePacket() selected. The two agreed only for a PriorityScheduler without reverseOrder. A module that reads the offered packet before it pulls, such as TokenBasedServer, then acted on another packet than the one it pulled. Now canPullPacket() returns the packet of the input that schedulePacket() selects, and canPullSomePacket() asks whether that input has a packet. This affects WrrScheduler, ContentBasedScheduler, LabelScheduler, PacketScheduler, MarkovScheduler and PriorityScheduler with reverseOrder. The scheduler function of a PacketScheduler must not change any state, because the base class now calls it from queries too. This can change the results of simulations in which a module reads the packet that such a scheduler offers.
42. Packet filters decide one time for each packet
PacketFilterBase called matchesPacket() and processPacket() again on each call of a push stream, so its verdict could change in the middle of a stream. It now decides at the start of the stream and keeps the verdict for the stream; processPacket() still runs for each packet instance of the stream. The base class calls the new function handlePacketFiltered() one time for each packet that goes through the filter or that the filter drops, and one time for each packet stream. A filter that keeps state, such as a dropper that counts packets, changes that state there, not in matchesPacket(), processPacket() or dropPacket(). See the migration guide.
43. A filter in pull mode drops a packet in its own operations
In pull mode, PacketFilterBase::canPullPacket(), a query, pulled and dropped each packet of its provider that did not match. The filter now drops such packets when they become available: when its provider reports a packet, and after each pull. canPullPacket() returns the packet of the provider if it matches. This can change the time of a drop in simulations that pull packets through a filter. ReceiveWithLifetime and EligibilityTimeFilter no longer support pull mode, because their verdict about a packet changes with time without an event of the module.
44. An ordinal based dropper counts a streamed packet one time
OrdinalBasedDropper counted a packet in processPacket() and dropPacket(), which the filter base class calls for each packet instance of a packet stream. So it counted a streamed packet more than one time, and it dropped other packets than its dropsVector names. It now counts each packet one time, in handlePacketFiltered().
45. A stream merger records a streamed packet one time
StreamMerger recorded the sequence number of a passing packet in processPacket(), which the filter base class calls for each packet instance of a packet stream. It now records the number one time, in handlePacketFiltered().
46. A random early detection dropper draws its random number in advance
RedDropper updated its average queue length and drew a random number in matchesPacket(), so each query about a packet, such as canPushPacket(), changed the state of the dropper. It now decides with a stored random number, and it updates its state in handlePacketFiltered() when a packet goes through or is dropped; after a decision that used the stored number, it draws the next one. The dropper draws one more random number at initialization. Simulations with a RedDropper therefore give other results, with the same statistical behavior.
47. A statistical rate limiter draws its random number in advance
StatisticalRateLimiter drew a random number in matchesPacket(), so in pull mode each query, such as canPullPacket(), drew a number and could give another answer. It now decides with a stored random number, and it draws the next one in handlePacketFiltered() after a decision that used the stored one. The limiter draws one more random number at initialization. Simulations with a StatisticalRateLimiter therefore give other results, with the same statistical behavior.
48. IEEE 802.11 QoS DATA lifetime
HCF now discards QoS DATA when its finite lifetime expires, with Block Ack support enabled or disabled. Each access category uses mac.hcf.edca.edcaf[*].msduLifetime, with a default of 0.512 seconds. The timer starts at MAC acceptance, so DATA can expire in the queue before transmission. Users can select another positive, finite lifetime for congestion and compatibility studies. A-MSDU construction restarts the aggregate timer; fragmentation, retransmission, and ACK-policy changes preserve the applicable deadline. Accepted exchanges retain their DATA until safe completion and permit no later attempt after expiration.
Congested QoS simulations can transmit newer DATA because older queued or in-progress DATA expires. Recorded trajectories change in the Block Ack fragmentation showcase, the QoS showcase, and the wireless and ad hoc MacQos examples. The approved fingerprint baselines reflect these lifetime changes.
HCF records lifetime drops separately in packetDropLifetimeExpired. Its count and byte sum separate lifetime disposal from queue overflow and retry-limit disposal. Aggregation with qOsCheck=false still accepts non-QoS or mixed sources. The resulting QoS aggregate starts its own lifetime at construction, even when its sources have no lifetime entries.
49. The algorithm of a TCP connection is its submodule
Each TCP connection now creates its congestion control algorithm (TcpNewReno, TcpCubic, DcTcp and the others) as its submodule algorithm, for example tcp.conn-3.algorithm, of the NED type that tcpAlgorithmClass names. Each algorithm has a simple module type of the same name in inet.transportlayer.tcp.flavours, which extends the new TcpAlgorithm and holds the parameters of the algorithm. Qtenv shows the algorithm of a running connection with its parameters and its state variables. The connection keeps the timers and the signals of the algorithm, so the results do not change.
The parameters that only one algorithm reads moved from Tcp to the type of that algorithm, so their ini keys change:
**.tcp.cubicBeta -> **.tcp.conn-*.algorithm.beta
**.tcp.cubicC -> **.tcp.conn-*.algorithm.c
**.tcp.cubicFastConvergence -> **.tcp.conn-*.algorithm.fastConvergence
**.tcp.cubicTcpFriendliness -> **.tcp.conn-*.algorithm.tcpFriendliness
**.tcp.cubicCntClamp -> **.tcp.conn-*.algorithm.cntClamp
**.tcp.cubicDelta -> **.tcp.conn-*.algorithm.delta
**.tcp.hystart... -> **.tcp.conn-*.algorithm.hystart...
**.tcp.dctcpGamma -> **.tcp.conn-*.algorithm.g
dctcpGamma was a parameter of INET 4.7, and Tcp no longer has it. The parameters of CUBIC and HyStart were not in a release. LinuxTcp and LegacyTcp turn HyStart on with a pattern assignment for the algorithms of their connections. TcpVegas has the new parameters alpha, beta and gamma, with the values of its former constants as defaults.
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 TCP connection setup lasts as long as its SYN retransmissions
An active open of Tcp no longer fails after 75 s, and a passive open no longer leaves SYN_RCVD after 75 s. The SYN and SYN-ACK retransmissions alone limit the setup (the synRetries parameter, or TcpSocket::setSynRetries() for one connection), as in Linux. With the defaults of Tcp, 12 retransmissions take about 24 minutes; RFC 9293 section 3.8.3 asks for at least 3 minutes (MUST-23). LinuxTcp keeps the 11 s of Linux. Simulations in which a SYN or a SYN-ACK gets no answer for more than 75 s change.
When the retransmissions run out, the setup now times out: an active open tells the application with TCP_I_TIMED_OUT, as connect() of Linux fails with ETIMEDOUT, and a passive open returns to LISTEN, or closes if it was forked. Before, the connection aborted without an indication to the application, and a listener that does not fork closed.
The timer that waits for the SEND of a deferred Fast Open SYN is now TcpConnection::deferredSynTimer, with the constant TCP_TIMEOUT_DEFERRED_SYN. See the migration guide.
51. LinuxTcp drops the data of a SYN without Fast Open
A TCP listener keeps the data of a SYN that carries no Fast Open option and delivers it after the handshake, as RFC 9293 section 3.10.7.2 allows. A Linux listener drops such data, and the client sends it again after the SYN-ACK. The new parameter dropSynData selects the behavior of Linux; LinuxTcp sets it, and Tcp keeps the data. Simulations with LinuxTcp in which a client sends data on a SYN without Fast Open change. The data of a SYN with an invalid Fast Open cookie is dropped in each mode, as RFC 7413 section 4.2.2 asks, as before.
52. Dynamic Right-Sizing of the TCP receive buffer, as Linux
With windowAutoTuning and a receive buffer (receiveBufferSize), a TCP receiver now grows its buffer in a long transfer as Linux does (Dynamic Right-Sizing). At each read of the application after one receive RTT, the bytes read in that RTT become the receive space when they are more, and the buffer grows to twice the space, more during slow start, up to the new parameter receiveBufferMax (32 MiB, as tcp_rmem[2] of Linux). In the autoRead mode, each delivery to the application is a read. The new parameter receiveBufferLowRtt (1 ms, as tcp_rcvbuf_low_rtt) selects a smaller growth for small RTTs. The receiver estimates the receive RTT as Linux, with and without timestamps, and the status of a connection reports it with the receive space (rcvRtt, rcvSpace of TcpStatusInfo). Simulations that turn windowAutoTuning on with a receive buffer change, and LinuxTcp has a receive buffer by default (entry 53).
53. LinuxTcp has the receive buffer of Linux, and the window scale covers auto-tuning
LinuxTcp now has a receive buffer of 131072 bytes (receiveBufferSize), the tcp_rmem[1] that Linux gives each socket, so its window auto-tuning and Dynamic Right-Sizing act with its defaults. Before, LinuxTcp set no receive buffer, and its offered window stayed at advertisedWindow. Tcp keeps no receive buffer apart from the window.
With windowScalingFactor = -1, windowAutoTuning and a receive buffer that SO_RCVBUF does not lock, the window scale now also represents receiveBufferMax, as Linux tcp_select_initial_window() represents tcp_rmem[2]: with the default of 32 MiB, the shift is 10. Before, the shift represented only the window at the time of the SYN: a buffer of 131072 bytes got a shift of 1, and the offered window could not grow above 131070 bytes, although the buffer grew. A buffer that SO_RCVBUF locks keeps the shift of its own window. Simulations with LinuxTcp, and simulations that turn windowAutoTuning on with a receive buffer, change.
54. The out-of-band byte of received TCP urgent data, as Linux
The new parameter urgentOutOfBand, which LinuxTcp sets, gives the receive side of urgent data of Linux without SO_OOBINLINE: the last byte of urgent data leaves the stream, and a read stops before it. INET does not deliver that byte, which Linux gives to recv(MSG_OOB), and it sends no urgent data. Tcp keeps treating URG-marked bytes as ordinary data. Simulations change only where a peer sends urgent data to LinuxTcp.
55. A sink can pull a packet that it accepts
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.
Notable backward compatible changes are the following:
1. IEEE 802.11 per-station rate statistics
The datarateChanged signal of the rate controls is now emitted with the name of the receiving station as a named details object, and a new dataratePerStation statistic demultiplexes it into one data rate vector per peer. The datarateSelected signal of Dcf and Hcf is tagged the same way, which also covers fixed and configured rates. The declaration of the aggregate datarateChanged statistic is unchanged and it still ignores the details, but the values it records move: the rate control no longer reports a rate when the mode set changes, and reports one per station when that station is first seen instead.
2. IEEE 802.11 per-receiver configured data frame rates
RateSelection and QosRateSelection gained a dataFrameBitratePerReceiver parameter, a map from peer interface module path to bitrate, which fixes the rate of originated unicast data frames separately for each peer. It is empty by default, so it changes nothing unless it is configured. The dataFrameBitrate parameter, which fixes one rate for the whole interface, is unchanged.
3. Naming the host owning a MAC address
A new L3AddressResolver::getHostNameWithMacAddress() method names the host that owns a MAC address, by the host's path relative to the network, and falls back to the MAC address string when no host owns the address.
4. Type-aware field chunk serializers
FieldsChunkSerializer gained two protected hooks, serializeFields() and deserializeFields(). The deserializeFields() hook receives the concrete chunk type that was requested from ChunkSerializerRegistry, so a serializer that is registered for several chunk types can build the exact requested type. The old hooks, serialize(stream, chunk) and deserialize(stream), are deprecated but still work: they are no longer pure virtual, and the new hooks call them by default. Serializers written against an earlier INET version need no source change. See the migration guide for the new signatures.
5. Region tag removal by type
The removeTagsWherePresent() method of SharingRegionTagSet removed the region tags of every type in the given range, and not only the tags of the requested type. It now removes only the requested type, as its documentation always stated. The same correction reaches Chunk::removeTagsWherePresent() and Packet::removeRegionTagsWherePresent(), which forward to it. The clearTags() method gained an optional predicate that selects the tags to clear, and clears all of them by default, so its own behavior is unchanged.
This may change the results of a simulation that removes the region tags of one type while the region tags of another type cover the same range. Inside INET this happens when ResidenceTimeMeasurer ends a measurement: it removed the ResidenceTimeTag and, with it, the FlowTag and the PacketEventTag of the packet. Those two tags now survive the measurement.
6. IEEE 802.11 MIB rate state and notifications
The Management Information Base (MIB) now stores supported, basic, and operational rate sets for the local station, Basic Service Set (BSS), and individual peers. A rate set distinguishes unknown information from a known empty set. Rate-set setters validate the input before they commit it. A combined BSS and peer update installs both records before one notification.
The rateStateChanged signal reports a committed rate, High Throughput (HT) capability, or channel-operation change. Its value is true, with no details object. Listeners query the MIB for current state. Equal rate-set updates emit no signal. The migration guide explains state access and listener use.
Association release and bulk teardown remove both peer HT capabilities and rate sets before one notification. A listener can install replacement peer state from the callback; teardown does not remove that replacement. Direct HT or rate removal still emits its own notification if state changes. Empty teardown emits no signal. Existing configuration parameters stay unchanged.
7. IEEE 802.11 selectable multiple protection in EDCA TXOPs
EDCA TXOPs support selectable multiple protection. Single protection remains the default. Nominal timing uses the mode set's short interframe space (SIFS) unchanged after the first transmission step. The first step adds no interframe space. Multiple protection stops normally when another exchange cannot use a legal duration field.
For example, a 200 us PPDU within a 1024 us TXOP advertises 824 us of reservation. A TXOP is a transmission opportunity; a PPDU is one PHY transmission.
The user guide explains nominal timing, zero-limit estimates, unused reservation time, and support limits. Multiple protection uses shared TXNAV. It does not check a complete exchange against the remaining budget.
8. Radio medium purge without a timer
RadioMedium has a new transmissionPurgeMode parameter. The default, "timer", removes transmissions that can no longer interfere with a self-message scheduled at the interference end time of the oldest transmission that can still interfere, as before. "onTransmission" removes them whenever a new transmission is added instead, so the medium schedules no events of its own; this keeps the medium out of the event sequence entirely, which matters for a model whose fingerprints must not depend on the medium's bookkeeping. Interference is computed identically in both modes.
The protected removeNonInterferingTransmissions() of RadioMedium now only removes; it no longer reschedules the timer, which the timer handler does by calling the new scheduleRemoveNonInterferingTransmissionsTimer() after it. A subclass that calls or overrides removeNonInterferingTransmissions() and relied on the rescheduling must call that method itself.
9. Correlated log-normal shadowing
LogNormalShadowing has a new correlationDistance parameter. By default (NaN) every path loss computation draws a new shadowing value, as before. With a distance, the value is kept per pair of radios, the same in both directions, and drawn again only when either radio has moved farther than that distance from where it was when the value was drawn, which is how shadowing behaves physically. The value is resolved once per reception, so with DimensionalMediumAnalogModel the whole band of a reception has the same shadowing. The values of a radio's links are dropped when the radio is removed from the medium.
10. Log-normal shadowing once per reception
Without a correlation distance, LogNormalShadowing draws one shadowing value per reception. With DimensionalMediumAnalogModel it drew one per evaluation of the attenuation, so the frequencies of one reception had independent values, and an evaluation repeated later gave a different one. With ScalarMediumAnalogModel, or with the dimensional model attenuating with the center frequency (the default), nothing changes.
11. IEEE 802.11 mapped 5 GHz channel subset
The new "5 GHz (mapped 20 MHz)" band supplies standard channels 36, 40, 44, and 48 for HT management. The IEEE 802.11 user guide describes its indices, frequencies, and HT40 pair validation. The subset does not enable 40 MHz HT operation or provide a complete regulatory-domain model.
12. IEEE 802.11 MIB state commit operations
The MIB now supplies combined operations for peer HT state, BSS rates, and peer rates. Each operation completes its mutations before notification. AP cleanup can also clear station and association-ID tables in the same transition. Standalone setters retain their existing behavior. Local records remain available after cleanup.
13. IEEE 802.11 management publishes legacy rate state
Full and simplified management now populate the existing MIB rate records from local advertisements and accepted associations. Associated-AP Beacons refresh the STA's BSS and peer rates. Peer departure, association loss, and management stop clear the corresponding records. External models can query these records after rateStateChanged notifications. Current built-in rate selectors retain their existing behavior.
STA teardown clears BSS rates and peer HT and rate state before one notification. Management clears its association snapshot and Beacon timer first. Listeners see complete cleanup, and the local rate record remains available.
Association and valid associated-AP Beacons commit HT state and rate records before one notification. AP management clears its pending transaction first. STA management sets its Beacon timer first. Listeners can query the complete state from the callback.
Full AP departure completes the station downgrade before peer cleanup notification. Full AP stop clears station and association-ID tables, peer state, and BSS rates before one notification. Rate publication excludes BSS membership selectors from legacy rate records. Selector-based join checks remain outside this change.
Management rejects nonfinite numeric rates in abstract frames before ordered-set insertion. Previously, a NaN after a valid rate could escape validation and replace committed records. Malformed rate elements now preserve committed records and emit no rate notification. Wire-decoded rate octets cannot produce these nonfinite values.
14. Explicit historical Basic Block Ack selection
HCF adds blockAckVariant = "basic" for historical compatibility. Existing Block Ack, TXOP, QoS, and fragmentation demonstrations select it explicitly. Basic remains the default. HCF rejects unknown values and the reserved "compressed" value during initialization until Compressed exchanges exist. These checks also apply when Block Ack support is disabled. Basic originated in IEEE Std 802.11e-2005; IEEE Std 802.11-2024 reserves its type value.
15. IEEE 802.11 retry counters for each receiver
QoS recovery now keeps separate retry counters for each receiver. Frames with equal TID, sequence number, and fragment number no longer share a counter across receivers. An acknowledgment or retry-limit disposal for one receiver preserves the other receiver's counter. This repair applies before DATA lifetime expiration.
Notable bug fixes are the following:
1. IEEE 802.11 HT modes preserve the requested band and preamble
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
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
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
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
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.
TcpVegas decided once per RTT to grow or to shrink cwnd by one segment, but it applied the step again at each later ACK until the next decision. So in congestion avoidance, cwnd moved by more than one segment per RTT, and alpha and beta did not hold the number of extra segments between them. TcpVegas now applies the step once per RTT, as the Vegas paper and Linux tcp_vegas_cong_avoid() do. TcpVegas and TcpWestwood also ignored initialSsthresh and ended slow start at 64 KiB; now they take initialSsthresh, as the other algorithms do.
After a retransmission timeout, TcpReno, TcpNewReno and DcTcp restarted slow start with a cwnd of the MSS. With the timestamp option, a segment carries 12 bytes less data, so a segment of 12 bytes went out after the retransmission. The loss window is now one full-sized segment of data, as RFC 5681 section 3.1 says. Also as RFC 5681 says, only the first timeout of a segment sets ssthresh now; the value of these algorithms stays the same, but their ssthresh statistic no longer records it a second time.
A receiver with delayedAcksEnabled acknowledged at once only after two segments of the length of its own send MSS. When the segments of the peer were shorter, for example after the path MTU discovery of the sender, each ACK waited for the delayed ACK timeout. Now the ACK also goes at once when the unacknowledged data reach 2*RMSS bytes, as RFC 9293 SHLD-19 says. RMSS is the MSS that the receiver announced.
With windowScalingSupport and an advertisedWindow above 65535, a SYN-ACK wrote the window into its 16-bit field without a limit, so 131072 became 0. The SYN and the SYN-ACK now carry at most 65535, because RFC 7323 section 2.2 says that their window is never scaled.
A receiver with classic ECN echoed a CE mark only on a pure ACK, and only for the last segment that arrived. A delayed ACK lost the echo when a segment without CE came after the marked one, and data and FIN segments never had ECE. Now each segment that acknowledges has ECE in the echo state, as RFC 3168 section 6.1.3 says.
Values without a meaning now stop the simulation with an error that names the parameter and its range: an mss below 88, other than -1; a dupthresh or an initialSsthresh below 1; and a gain g of DcTcp (formerly dctcpGamma) that is not in the range 0 < g <= 1. Before, mss = 0 stalled the connection, dupthresh = 0 gave contradictory loss detection, and a g out of its range moved alpha out of the range 0 to 1. The new parameters of Tcp and TcpCubic check their ranges in the same way.
INET-4.7 (July 2026) — feature release
--------------------------------------
This is a new feature release in the INET 4.x branch. The central theme of this
release is the maturation of the IPv6 protocol family, bringing it substantially
closer to feature parity with IPv4. Highlights include a new declarative IPv6
network configurator, IPv6 multicast routing (MLD, and PIM-DM/PIM-SM over IPv6),
node lifecycle support, Duplicate Address Detection, a modernized Mobile IPv6
(MIPv6) model with new Proxy Mobile IPv6 (PMIPv6) support, and IPv6 support in
BGP (MP-BGP) and IPsec. Outside the IPv6 area, the release brings satellite and
GNSS track mobility models with geographic visualization, a substantial overhaul
of the STP and RSTP spanning tree models, major BGP improvements, TCP Path MTU
Discovery, and a configurable RNG grouping mechanism. The release also contains
numerous smaller improvements and bug fixes. Requires OMNeT++ 6.4 or later.
For a complete list of all added, removed, and changed folders, NED modules,
packet chunks, packet tags, statistics, C++ classes, and signals, please refer to
the ChangeLog file in the src folder.
Notable backward incompatible changes are the following:
1. Mobile IPv6 (MIPv6) modernization
The Mobile IPv6 model was substantially modernized and aligned with the rest of
the IPv6 stack. The module previously named xMIPv6 was renamed to Mipv6, and the
xMIPv6Support wrapper was flattened into Ipv6NetworkLayer, with Mobile IPv6 now
enabled by a hasMipv6 switch.
IPv6 tunneling was reworked to follow the same model as IPv4: a tunnel is now
represented as a virtual network interface rather than a dedicated mechanism,
and the former Ipv6Tunneling module was removed. MIPv6-specific per-interface
state was moved out of Ipv6InterfaceData into a separate Mipv6InterfaceData
class.
Several new roaming scenarios were added, and a number of latent correctness
bugs in binding management, return routability, and route optimization were
fixed along the way.
This change requires the modification of simulation models that reference the
xMIPv6 module type, the Ipv6Tunneling module, or the xMIPv6Support submodule
path, as well as C++ code that accesses MIPv6 fields through Ipv6InterfaceData.
2. STP and RSTP overhaul
The Spanning Tree Protocol (STP) and Rapid Spanning Tree Protocol (RSTP) models
were substantially reworked for correctness and standards compliance. RSTP now
implements the full Proposal/Agreement handshake for rapid, timer-free
transition to the forwarding state. Several long-standing defects were fixed,
including a topology-change (TCN) BPDU storm, a hold-timer violation, and
incorrect timer interval assignments. The nonstandard ALTERNATE port role, which
had been backported from RSTP, was removed from STP.
A number of NED parameters and packet types were renamed for clarity and
consistency. Notably, the RSTP helloTime parameter was renamed to helloInterval,
and the STP maxAge parameter was renamed to configuredMaxAge (with the former
currentMaxAge becoming maxAge). The BPDU packet type names were also reworked
(e.g. stp-hello, rstp-hello).
In addition, when the port path cost is not explicitly configured,
L2NetworkConfigurator now derives the default from the link speed, following
the recommendation of IEEE 802.1D-2004.
This change requires the modification of simulation models that configure the
renamed parameters, and it may significantly change the statistical results of
spanning tree simulations due to the corrected protocol behavior.
3. IPv6 Router Advertisement interval defaults
The default Router Advertisement interval was changed to follow RFC 4861.
Previously, the minIntervalBetweenRAs and maxIntervalBetweenRAs parameters
defaulted to very short, Mobile-IPv6-tuned values (30 ms and 70 ms) and were
additionally overridden for wireless interfaces. They now default to the
standard RFC 4861 values, and the wireless special-casing was removed.
This change doesn't require the modification of simulation models, but it may
significantly change the statistical results of IPv6 simulations that relied on
the previous fast Router Advertisement timing, particularly those involving
wireless or mobile nodes.
4. IPsec generalization to IPv6
The IPsec model, introduced in the previous release for IPv4, was generalized
to be address family independent, and now supports IPv6 as well. Traffic
selectors and the security association and policy databases operate on
generic L3 addresses, each IPsec instance serves the address family of its
enclosing network layer, and Ipv6NetworkLayer gained a hasIpsec switch
analogous to the IPv4 one. AH and ESP headers are treated as terminal headers
in the IPv6 extension header chain. Two latent bugs in AH protection (a
zero-length header on egress, and a double header removal on ingress) were
fixed, and a new example demonstrates ESP over IPv6.
As part of this change, the model was moved from the networklayer/ipv4/ipsec
folder to networklayer/ipsec, with the NED package changing accordingly. This
change requires the modification of simulation models and C++ code that
reference the old package or include paths.
5. BGP timer configuration
The BGP timers, previously configured via the <TimerParams> element of the
bgpConfig XML file, are now parameters of the Bgp module (connectRetryTime,
holdTime, keepAliveTime, startDelay). A <TimerParams> element in the XML
configuration is now rejected with an error message that explains how to
migrate.
This change requires the modification of simulation models that configure
BGP timers in the XML configuration file.
6. ICMP error indication refactoring
The handling of ICMP error indications was refactored into a properly layered
architecture in which each protocol layer processes only its own header. As part
of this, the IcmpErrorInd indication and the IcmpErrorTag tag were each split
into IPv4-specific and IPv6-specific variants (Icmpv4ErrorInd / Icmpv6ErrorInd
and Icmpv4ErrorTag / Icmpv6ErrorTag).
These changes are backward incompatible for C++ code that directly references
the old combined ICMP error indication or tag types.
Notable backward compatible changes are the following:
1. IPv6 network configurator
A new Ipv6NetworkConfigurator, with a companion Ipv6NodeConfigurator, was added,
bringing the declarative, IPv4-style network configuration approach to IPv6.
Like its IPv4 counterpart, it assigns addresses and sets up routing tables
automatically based on the network topology, while allowing fine-grained control
through an XML configuration. Explicit per-interface addresses can be assigned
(e.g. using a prefix::interface-id form), overriding the default EUI-64 interface
identifier. Both the IPv4 and IPv6 configurators now also accept CIDR
"address/prefixlen" notation in static route specifications, and gained
addRemoteRoutes and addManualRoutes parameters that allow the individual
route generation steps to be enabled or disabled separately. The simpler
Ipv6FlatNetworkConfigurator remains available.
2. IPv6 lifecycle and multicast forwarding
The IPv6 protocol stack gained node lifecycle support, so that IPv6 nodes now
correctly handle shutdown, restart, and crash operations the same way IPv4 nodes
do. In addition, IPv6 multicast packet forwarding was implemented, including a
multicast routing information base and forwarding information base with reverse
path forwarding (RPF) checks. Together with the multicast routing protocols
described below, this enables IPv6 multicast scenarios that were previously only
possible with IPv4.
3. Multicast Listener Discovery (MLD)
IPv6 multicast group membership is now managed using the Multicast Listener
Discovery protocol. The MLDv1 router-side behavior was completed, and a new Mldv2
module implementing MLDv2 (RFC 3810) was added, including the corresponding
message set, serializer, packet dissector, and printer; the MLD version is
selected by module typename. Source-specific multicast (SSM) membership state was
added to Ipv6InterfaceData. The IPv4 IGMPv3 model was brought to lockstep parity
with MLDv2 (query and report retransmission, interoperation with older versions),
so that the IPv4 and IPv6 multicast membership implementations now mirror each
other.
4. PIM over IPv6
The PIM-DM and PIM-SM multicast routing protocols were generalized to be address
family independent, operating on generic L3 addresses, and can now run over IPv6
in addition to IPv4, while the existing IPv4 PIM behavior is preserved unchanged.
The new MulticastRouter6 node type provides a ready-to-use pure-IPv6 multicast
router. PIM-SM can also derive the rendezvous point per group from embedded-RP
IPv6 addresses (RFC 3956). Source-specific multicast (SSM, RFC 4607) is now
fully supported on both address families: source-list memberships from
IGMPv3 (IPv4) and MLDv2 (IPv6) drive PIM-SM to build RP-less, source-rooted
(S,G) trees for groups in the SSM range, using INCLUDE-only semantics and
requiring no rendezvous point. The PIM packet serializer was extended to support
the IPv6 encoded-address forms.
5. IPv6 Neighbor Discovery
IPv6 Neighbor Discovery was extended in several backward compatible ways.
Duplicate Address Detection (DAD) is now performed for autoconfigured global
addresses in accordance with RFC 4862, and ICMPv6 Redirect message sending and
processing was implemented (RFC 4861). Further Router Advertisement and Neighbor
Discovery parameters were exposed as NED parameters and XML configuration
attributes, and node bootstrap delays became configurable. A new sendRedirects
parameter on the Ipv6 module allows suppressing Redirect messages, which is
useful on wireless ad-hoc networks.
6. Proxy Mobile IPv6
Support for Proxy Mobile IPv6 (PMIPv6, RFC 5213) was added. PMIPv6 provides
network-based mobility management: the network tracks the movements of a
mobile node and keeps its IPv6 address stable across handovers, without
requiring any mobility support in the mobile node itself. The new Pmipv6
module implements both the Local Mobility Anchor (LMA) and the Mobile Access
Gateway (MAG) roles, using Proxy Binding Update / Acknowledgement signaling
based on the Mobile IPv6 message formats, and tunneling between the MAGs and
the LMA. A new example demonstrates a handover in a PMIPv6 domain, with the
mobile node keeping its address across the move.
7. IPv6 netfilter hooks
The Ipv6 module now provides the same set of netfilter-style hooks as its
IPv4 counterpart: the LOCALIN hook is now invoked on local delivery, the
FORWARD hook was added, and packets can be reinjected at all five hook points
after asynchronous processing. This allows C++ modules such as reactive
routing protocols to interpose on the IPv6 datapath in the same way as with
IPv4.
8. BGP improvements
The BGP model received major improvements in several areas. BGP now supports
IPv6: sessions can be established over IPv6 TCP connections, and IPv6 routes
are exchanged using the multiprotocol extensions (MP-BGP, RFC 4760),
including multiprotocol capability negotiation in the OPEN message (RFC 5492)
and serialization of the MP_REACH_NLRI and MP_UNREACH_NLRI path attributes.
Related fixes make iBGP work over a multi-hop IGP with IPv6, and new examples
demonstrate EBGP over IPv6 and BGP running on top of an OSPFv3-based IGP.
BGP is now lifecycle-aware: node shutdown, restart, and crash operations are
handled properly, with sessions re-established and routes re-learned after a
restart. A new Adj-RIB-In data structure stores all routes learned from
peers, and the decision process is re-run when a route is withdrawn, so that
an alternative route can take its place. New examples demonstrate route
withdrawal and failover scenarios.
Session management robustness was also improved: routers now use a single
shared listening socket, connection collision detection was implemented
according to RFC 4271, several errors in connection retry and reconnection
handling were fixed, and BGP sessions are shut down gracefully on node
shutdown.
The BGP lifecycle support and the Adj-RIB-In extension were contributed by
Giovanni Nardini.
9. Satellite mobility and geographic visualization
New mobility models and visualizers support simulating satellite networks
and other scenarios placed on the Earth's surface. The new SatelliteMobility
module computes satellite positions from standard TLE (two-line element)
orbital data using the SGP4 propagation model, and GnssTrackMobility replays
position tracks recorded by GNSS (GPS) receivers. The underlying geometry
library was extended with WGS84 geodesy, Earth-centered (ECEF) coordinate
systems, and an equirectangular map projection.
On the visualization side, the new GeoMapCanvasVisualizer draws a world map
with a graticule as the scene background, GeoHorizonCanvasVisualizer draws
the visibility footprint of satellites on the map, and
GeoSkyViewCanvasVisualizer displays an azimuth/elevation sky view plot next
to observer nodes. The mobility visualizer was extended with 3D orientation
display and direction projection modes, movement trails handle the
antimeridian correctly, and several visualizers now clip their drawings to
the map area. Mobile nodes can display their geographic position using the
{geo_position} directive of displayStringTextFormat. A new example
demonstrates satellites moving above a map of the Earth.
10. TCP Path MTU Discovery
The TCP model now implements Path MTU Discovery (RFC 1191 and RFC 1981), allowing
connections to discover and adapt to the largest packet size that can traverse
the path without fragmentation. In addition, TCP now forwards ICMPv4 and ICMPv6
error indications to the application as soft notifications, and aborts
connections in the SYN_SENT state on hard ICMP errors.
11. RNG grouping
A new GroupedRngManager was added, providing a flexible way to share random
number generators among simulation components. It supports grouping components by
module (the default, one RNG set per module), by node (a node-wide shared RNG
set), or network-wide (a single global RNG set), selectable via the rng-grouping
configuration option.
12. OSPFv3 packet serializer
A packet serializer was added for OSPFv3, enabling OSPFv3 packets to be
recorded into PCAP files, sent through emulation interfaces, and verified
byte by byte in fingerprint tests. Several packet format errors (incorrect
packet and LSA length fields) were fixed in the process, and the Ospfv3
module gained a checksumMode parameter for RFC-correct checksums.
13. STP/RSTP tutorial
A new tutorial introduces the Spanning Tree Protocol and Rapid Spanning Tree
Protocol through a progression of examples, demonstrating root bridge election,
port roles and states, topology change handling, and the rapid transitions
provided by RSTP.
14. Documentation refinements
The IPv6 chapter of the User's Guide was substantially rewritten to reflect the
modernized IPv6 stack, including documentation of the new Ipv6NetworkConfigurator
and the XML routing configuration format. New User's Guide chapters describe
satellite mobility and geographic visualization, and the BGP documentation
was extended with the configuration file format and the new IPv6 (MP-BGP)
support. NED documentation for many IPv6 and Mobile IPv6 modules was expanded
and brought up to date, and several example simulations (e.g. the PIM
examples) received README files.
15. Notable bug fixes and other changes
Most modules were migrated to the displayStringTextFormat mechanism for their
Qtenv display strings, replacing custom refreshDisplay() overrides; the old
WATCH_xxx() macros were replaced with the unified WATCH() macro, and additional
watches were added for computed values. This affects only the graphical runtime
and has no effect on results.
The LdpMplsRouter and RsvpMplsRouter modules were refactored to share a common
MplsRouterBase base, eliminating duplicated code. This changes the module
initialization order and therefore the random number draw order, so MPLS
simulation results may change.
Fixed two IPsec ESP correctness bugs: an incorrect block size unit in payload
padding, and an incorrect total length computation during decryption.
Fixed a UDP payload padding removal bug that could misdetect trailing data, and a
crash that occurred when combining multicast traffic with VLANs.
Fixed a memory leak in MessageDispatcher that occurred when packet delivery
failed.
Standardized many internal integer types in the SCTP model and across the
codebase, improving consistency.
A new STAGE_NETWORK_INTERFACE_CONFIGURATION stage was inserted into the
lifecycle start and stop operations, so that network interfaces are
configured before IPv6 addresses are assigned. This fixes network interfaces
not re-obtaining their global IPv6 address after a node restart.
Fixed L2NetworkConfigurator to configure all ports in the network instead of
just the first one, and added a dumpConfiguration parameter for debugging.
Fixed visualizers to subscribe to the signals of their subject module rather
than the visualization target module, so that the two can be fully decoupled.
The InfoVisualizer now supports the %N directive for displaying the display
name of a module.
Fixed crashes that occurred when running GPSR over IPv6.
IPv6 Neighbor Discovery packets are now created with descriptive names,
making logs and packet traces easier to read.
Removed several low-value or redundant IPv6 example simulations (demonetworketh,
ipv6bulk, and ipv6nclients).
Several additional issues reported on GitHub have also been fixed.
INET-4.6 (February 2026) — feature release
------------------------------------------
This is a new feature release in the INET 4.x branch. Highlights include new
protocol implementations for QUIC, Ethernet 10BASE-T1S, IPsec, and MRP; major
refinements to the clock model; a reimplementation of IEEE 802.1AS (gPTP); and
an important refactoring of the wireless physical layer's analog domain. The
release continues to focus on improving correctness, accuracy, modularity, and
long-term maintainability while addressing several long-standing limitations.
Requires OMNeT++ 6.2 or later.
For the full list of additions, removals, and changes (features, modules, packet
chunks/tags, signals, statistics, and C++ classes), see ChangeLog in the src
folder.
For further questions, detailed explanations, and guided exploration of INET
concepts and features, a dedicated AI-powered wiki is now available at
https://deepwiki.com/inet-framework/inet
Notable backward-incompatible changes include the following:
1. Clock model refinement
The clock and oscillator models were substantially reworked to improve
accuracy, correctness, and robustness. Clock time to simulation time mapping
and clock-interval to oscillator-tick conversions were rewritten for
mathematical correctness, with stricter consistency checks. Accuracy was
improved using precise arithmetic and new scaling utilities (e.g.,
NumberNear1 and SimTimeScale). The design anticipates future 128-bit
simulation time support.
The updated model now accumulates fractional oscillator compensation for more
accurate timing. The clock's nominal tick interval must be explicitly
configured, as it no longer defaults to the simulation time resolution. The
drifting oscillator model was extended with a configurable frequency
compensation factor, distinct from the clock's step-based compensation
mechanism.
The architecture was modularized to allow multiple clocks to share a single
physical oscillator via the clock's oscillatorModule parameter. SettableClock
now includes an underlying free-running clock submodule to support
simulations that mix synchronized and unsynchronized time. A clock servo
model was added, including the IClockServo module interface and the
StepClockServo module for implementation.
Clock event handling was also refined: overdue events are now processed
immediately, in clock-time order, and newly scheduled events are inserted at
the lower bound of the corresponding simulation-time interval, preserving
stable ordering. Clock time to simulation time conversion methods now accept
explicit lower-bound arguments to ensure robust tie-breaking between adjacent
ticks.
Clock and oscillator documentation was significantly expanded and formalized
to reflect the stricter semantics of the new implementation.
This change is backward incompatible in that clock-based simulations may
produce slightly different statistical results due to the improved
correctness and accuracy of the model.
2. IEEE 802.1AS (gPTP) protocol reimplementation
Large parts of the protocol were reimplemented using formal state machines
for both peer delay measurement and time synchronization. Standards
conformance was improved, including correct handling of grandmaster and
neighbor rate ratios. The peer delay and time synchronization processes now
maintain separate state for requester/responder and sender/receiver roles.
The new model introduces a dedicated clock servo submodule for updating local
time. Peer delay measurements now use an exponential moving average for
improved stability and are performed using the unsynchronized local clock to
avoid interference during active time synchronization.
For improved standards compliance, message timestamping now occurs at
transmission start and reception start rather than at completion. As a
result, simulations must use physical layer modules that emit explicit
start-of-transmission and start-of-reception signals, such as the
StreamingTransmitter and DestreamingReceiver modules.
Due to the high precision required for time synchronization, accurately
modeling a 1 ppm clock drift with a nominal 10 ns tick interval requires very
fine time granularity. gPTP simulations therefore typically require
femtosecond (fs) simulation time resolution, which can be enabled via the
simtime-resolution configuration option.
This change is backward incompatible in that simulations using gPTP may
produce slightly different statistical results due to the improved
correctness and accuracy of the model.
3. Ethernet module renames
Existing Ethernet MAC modules were renamed to use the MacPhy suffix (e.g.
EthernetMacPhy, EthernetCsmaMacPhy) to reflect that they combine MAC and PHY
functionality in a single module. This resolves naming conflicts introduced
by the new dedicated EthernetCsmaMac and EthernetCsmaPhy modules, which
provide a modern, state-machine-based implementation of the individual layers
and are primarily used by the new Ethernet 10BASE-T1S model.
These changes are backward incompatible for simulations that directly
reference the old module names.
4. Wireless physical layer refactoring
The wireless physical layer was significantly refactored to simplify how the
analog representation of radio signals is selected. Instead of using separate
module types, radio and medium modules now use a signalAnalogRepresentation
parameter (unitDisk, scalar, or dimensional) to control their behavior.
Responsibility for computing reception success was partially moved from
receiver modules to their analog model submodules. To reflect broader