Incorrect behaviour of Segmentation/Reassembly mechanism after dropped PDU
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
openWNS Library |
Fix Committed
|
Medium
|
Boyan Lazarov |
Bug Description
Hello,
I'm trying to use the SegAndConcat FU (wns::ldk:
Setup:
A base station (BS) in a scenario with multiple cells and BSs is transmitting data to a subscriber station (SS). Data comes in the form of IP Packets from the constanze generators. Packet size is 1024 Bit data + 48 Bit overhead = 1072 Bit. The SegAndConcat FU is setup with isSegmenting = False as segmentation is performed by the SegmentingQueue in the scheduler. The FU thus only handles reassembly. There is also a CRC present bellow the SegAndConcat FU, which is set to "Dropping". Furthermore, there are no retransmissions in the system (no HARQ nor ARQ). The following situation arises:
After transmitting for some time, a PDU is discarded by the CRC because the ErrorModeling calculated a high error probability. The PDU has a SN = 189. As described in the protocol, the reordering timer is started. In the mean time, further transmissions occur, and PDUs with SN = 190 to 205 are transmitted and correctly received until the timer expires. The VR variables at the time the timer fires look the following way:
vrUH_ = 206
vrUR_=189
vrUX_ = 191
TS 36.322 5.1.2.2.4 defines the following actions when the timer expires:
- vrUR is set to the SN of the first not received PDU with SN > vrUX, in this case 206
- From the received PDUs with SN < this new vrUR ( SN < 206), SDUs are reassembled and passed to the FUs above.If an SDU cannot be reassembled due to missing PDUs, it should discarded.
- Finally, if vrUH is still larger than vrUR, the t-Reordering timer is restarted and vrUX is set equal to vrUH
The following happens in the simulator:
- Timer fires and ReorderingWindo
- vrUR is correctly updated to 206
- updateReassembl
- this function iterates over all PDUs in the reordering window (in this case, from SN 190 to 205) and attempts to pass them to the reassembly buffer
- this results in a call to onReorderedPDU() with the current PDU as a parameter
- this method first checks if this PDU is the nextExpectedPDU (which is not the case, the next expected is 189 which was lost)
- Because this is not the expected PDU, the reassembly buffer is emptied.
- It is then checked whether the current PDU can be accepted from the buffer - This is where the problem occurs:
- the function called is ReassemblyBuffe
After this point, no more SDUs are reassemled by the SegAndConcat, even though there are multiple correct transmissions until the end of the simulation. Bellow is some output from the problem:
( 0.2559987) [ WNS] L2.SegAndConcat
( 0.2559987) [ WNS] L2.SegAndConcat
( 0.2559987) [ WNS] L2.SegAndConcat
( 0.2559987) [ WNS] L2.SegAndConcat
( 0.2559987) [ WNS] L2.SegAndConcat
( 0.2559987) [ WNS] L2.SegAndConcat
( 0.2559987) [ WNS] L2.SegAndConcat
( 0.2559987) [ WNS] L2.SegAndConcat
( 0.2559987) [ WNS] L2.SegAndConcat
( 0.2559987) [ WNS] L2.SegAndConcat
( 0.2559987) [ WNS] L2.SegAndConcat
( 0.2559987) [ WNS] L2.SegAndConcat
( 0.2559987) [ WNS] L2.SegAndConcat
( 0.2559987) [ WNS] L2.SegAndConcat
( 0.2559987) [ WNS] L2.SegAndConcat
( 0.2559987) [ WNS] L2.SegAndConcat
( 0.2559987) [ WNS] L2.SegAndConcat
( 0.2559987) [ WNS] L2.SegAndConcat
( 0.2559987) [ WNS] L2.SegAndConcat onReorderedPDU(
( 0.2559987) [ WNS] L2.SegAndConcat onReorderedPDU: PDU 189 is missing. Clearing reassembly buffer.
( 0.2559987) [ WNS] L2.SegAndConcat onReorderedPDU: Dropping PDU 190. isBegin=False.
( 0.2559987) [ WNS] L2.SegAndConcat
( 0.2559987) [ WNS] L2.SegAndConcat reassemble: getReassembledS
( 0.2559987) [ WNS] L2.SegAndConcat
( 0.2559987) [ WNS] L2.SegAndConcat onReorderedPDU(
( 0.2559987) [ WNS] L2.SegAndConcat onReorderedPDU: PDU -1 is missing. Clearing reassembly buffer.
( 0.2559987) [ WNS] L2.SegAndConcat onReorderedPDU: Dropping PDU 191. isBegin=False
... and so on up to PDU 205
I therefore have the following questions:
- Could this be a configuration issue which prevents the SegAndConcat unit from working correctly, or could this be a bug?
- In general, is it possible to use the combination of SegAndConcat and a Segmenting queue without any retransmission mechanism (HARQ), leaving aside the potentially higher packet loss?
Thank you for your time, any ideas would be greatly appreciated!
Best regards,
Boyan Lazarov, B.Sc
TU Muenchen
Related branches
- Daniel Bültmann: Approve
-
Diff: 413 lines (+326/-3)3 files modifiedsrc/ldk/sar/reassembly/ReassemblyBuffer.cpp (+14/-2)
src/ldk/sar/reassembly/ReorderingWindow.cpp (+7/-1)
src/ldk/sar/tests/SACSegmentingQueueIntegrationTest.cpp (+305/-0)
Changed in openwns-library: | |
status: | Confirmed → In Progress |
Changed in openwns-library: | |
status: | In Progress → Fix Committed |
Dear Boyan,
thank you for your good work. I also agree with you that you have found
a bug. Unfortunately, I do not have time at the moment to fix it myself,
but maybe you can contribute a fix if you like. I would propose the
following way forward:
1. Convert this question/answer thread to a bug report of openwns-library. (You have already done that, thanks!)
2. Extend the testcase src/ldk/ sar/tests/ SACSegmentingQu eueIntegrationT est.cpp to actually provoke the error. It is quite easy to do. If you have a look at the source code you will find a test setup with the SegmentingQueue and the SegAndConcatFU. You can execute the test suite by:
cd tests/unit/ unitTests
./openwns -t -v
or only execute the test above with:
cd tests/unit/ unitTests :sar::tests: :SACSegmentingQ ueueIntegration Test
./openwns -t -v -T wns::ldk:
3. Fix the bug ;) I think the following would be reasonable, but feel free to propose a better solution:
The starting point is void SegAndConcat: :onReorderedPDU (). Probably you need to modify ReassemblyBuffe r::isNextExpect edSegment( ) to accept a segment
if (isEmpty() && (readCommand( c)->getBeginFla g() || readCommand( c)->peer. pdus_.size( ) > 1))
So, if the buffer is empty a new segment is accepted if the getBeginFlag
is set or if more than one sdu is contained within.
You will need to do the same with ReassemblyBuffe r::accepts( )
Furthermore, you will need to modify ReassemblyBuffe r::insert( ), such c)->peer. pdus_.size( ) > 1 c)->peer. pdus_.pop_ front() c)->setBeginFla g()
that if the buffer is empty and the isBegin flag is not set:
1) Assure that readCommand(
2) Remove the head element of the pdus_ list,i.e. readCommand(
3) Set the begin flag: readCommand(
4) Put the segment into the buffer
4. Check if this fixes the error and does not introduce new ones by executing the test suite.
5. Push your branch with the bugifx to launchpad and propose a merge. Me or Maciej will then merge it to the trunk.
Let me know if this is OK with you.
Thanks a lot,
Daniel