aboutsummaryrefslogtreecommitdiffstats
path: root/src/tbf_dl.cpp
AgeCommit message (Collapse)AuthorFilesLines
2015-06-22tbf: Fix downlink packet lossJacob Erlbeck1-65/+68
When the MS is pinged with a longer interval, many packets get lost even if the GprsMs object is kept. If the interval is above the time where the DL TBF is in state FLOW (mainly influenced be the dl-tbf-idle-time command), an new TBF must be requested via AGCH for each ICMP PING message. Currently the LLC frame containing the PING is immediately stored in the TBF and gets lost, if TBF establishment fails for some reason. This commit moves all calls to put_frame() to schedule_next_frame(), where the data is moved from the LLC queue to the frame storage within the TBF object. This method is only called from within create_new_bsn() when the TBF is in the FLOW state and the frame is going to be encoded immediately. At all other places, where put_frame() has been called before, the LLC message is just appended to the LLC queue in the GprsMs object. This change effectively simplifies the related code parts, since date/len information and discard notifications is no longer needed there. Ticket: #1759 Sponsored-by: On-Waves ehf
2015-06-22tbf: Include CS into create_new_bsn log messageJacob Erlbeck1-3/+3
This change lets the test suite fail, so it get its own commit. Sponsored-by: On-Waves ehf
2015-06-08tbf: Ignore lost+recv == 1Jacob Erlbeck1-1/+1
Currently the CS level gets changed quickly if single RLC/MAC blocks are sent (e.g. LLC dummy commands), since the rate is either 0% or 100%. This commit ignores measurements which are based on a single block only. Sponsored-by: On-Waves ehf
2015-06-08tbf: Add debugging output to analyse_errors()Jacob Erlbeck1-6/+22
To help with the debugging, optimisation, and understanding of this method, this commit adds an info string containing a flag character per RLC/MAC data block in the current window. Note that the blocks are shown in reversed order (highest BSN first) in comparison to other logging output. Sponsored-by: On-Waves ehf
2015-06-08tbf: Add adaptive DL CS adjustmentJacob Erlbeck1-0/+54
To cope with transmission failures due to bad radio conditions, a different coding scheme with more redundance can be used. This commit adds an implemenation that is based on the Ack/Nack ratio per PACKET DOWNLINK ACK/NACK message received from the MS. Basically the CS level is decreased, if the block error rate goes above cs_adj_upper_limit (default 33%), and it is increased, if the rate drops below cs_adj_lower_limit (default 10%). Only blocks that have been encoded with the current CS are taken into account. Note that this approach doesn't measure the MS->BTS conditions and that the measurement values reported by the MS are not taken into account. Ticket: #1739 Sponsored-by: On-Waves ehf
2015-06-08tbf: Move the current CS field to GprsMsJacob Erlbeck1-6/+6
Currently the current CS value is stored in the cs field of gprs_rlcmac_tbf and initialised when it is used the first time. This commit adds separate fields for UL and DL CS values to the GprsMs class and provides corresponding getter methods for GprsMs and gprs_rlcmac_tbf. Ticket: #1739 Sponsored-by: On-Waves ehf
2015-06-08tbf: Store MS class in GprsMs objectsJacob Erlbeck1-3/+3
The ms_class value is a property of the MS and thus belongs to the GprsMs class. Nevertheless the MS object is created after the TLLI gets known, so the value still has to be stored in the TBF initially. This commit add the ms_class value to the GprsMs class and introduces TBF accessor functions which either access that object or, if that is not available, the value stored locally. Ticket: #1674 Sponsored-by: On-Waves ehf
2015-06-08tbf: Move the LLC queue to GprsMsJacob Erlbeck1-6/+3
Currently the enqueued DL LLC messages which have not yet passed to RLC/MAC encoding are eventually copied from one TBF to the next one (see gprs_rlcmac_dl_tbf::reuse_tbf). Since the enqueued LLC messages are related to a specific MS, they should be stored at that layer. This commit moves the gprs_llc_queue object to GprsMs and changes the TBF's accessor methods accordingly. The LLC copying code is removed from gprs_rlcmac_dl_tbf::reuse_tbf(). Sponsored-by: On-Waves ehf
2015-06-08llc: Separate LLC queue handling from gprs_llcJacob Erlbeck1-10/+10
Currently the gprs_llc class handles both LLC queueing and the partition into smaller pieces for RLC/MAC encapsulation. This hinders the separation of TBF and MS related data, since LLC queueing belongs to the MS related code while the RLC/MAC encoding/decoding belongs to the TBF layer. This commits takes the LLC queueing related methods and members and puts them into a new class gprs_llc_queue. It puts the queueing object into gprs_rlcmac_tbf and adds accessor functions. The implementation in tbf.cpp and tbf_dl.cpp is adapted accordingly. Ticket: #1674 Sponsored-by: On-Waves ehf
2015-05-28tbf: Store the timing advance (TA) value in the GprsMs objectJacob Erlbeck1-19/+6
The TA value rather relates to an MS and not to a single TBF. So all TBFs share the same TA value. Currently the TA value is stored per TBF and eventually copied from an old TBF to a new one. It is in general only passed with an RACH request when the TLLI and thus the MS is not yet known. This commit adds a TA member to the GprsMs class and uses that one when the TBF is associated to an MS object. Since the TBF is not always associated with an MS object (after RACH or when it has been replaced by another TBF), the TA value is still stored in each TBF and that value is used as long as no MS object is being associated. Sponsored-by: On-Waves ehf
2015-05-28tbf: Remove IMSI handling from trigger_dl_assJacob Erlbeck1-2/+2
Currently the BTS::trigger_dl_ass() method assigns the IMSI to the MS object. This should be (and is already) done earlier where the MS object is retrieved/created. This commit removes the corresponding code along with the 'imsi' parameter from trigger_dl_ass. Sponsored-by: On-Waves ehf
2015-05-28tbf: Move IMSI to MS objectJacob Erlbeck1-1/+0
Currently the IMSI is stored in the TBFs. Since it directly refers to an MS, it should rather be stored in an MS object. This patch move the m_imsi field from gprs_rlcmac_tbf to GprsMs, changes gprs_rlcmac_tbf::imsi() to get the IMSI from the associated MS object, and adds getter and setter to GprsMs. Before changing the IMSI of the associated MS object, assign_imsi() checks if there is already another MS object with the same IMSI and eventually resets the IMSI of that one. So using update_ms() and assign_imsi() ensures that there are not two MS object entries is the storage with the same TLLI or the same IMSI. Ticket: #1674 Sponsored-by: On-Waves ehf
2015-05-27tbf: Remove the TLLI from the TBFsJacob Erlbeck1-9/+2
Currently the TLLI is stored in each TBF. Since each MS is now represented by a GprsMs object which takes care of TLLI updating, and each TBF that has been associated with an TLLI also contains a reference to a GprsMs object, per TBF TLLI handling is no longer needed. Keeping all TBF m_tlli members up to date is complex and doesn't currently work correctly in all circumstances. This commit removes m_tlli and related members from the TBF class and the tbf_by_tlli functions from the BTS class. Ticket: #1674 Sponsored-by: On-Waves ehf
2015-05-21tbf: Just pass the MS object in reuse_tbfJacob Erlbeck1-1/+1
Currently the MS will be searched based on the TLLI in resue_tbf(). Since the MS object is already known in the TBF when the TLLI is set, it can just be passed to the new TBF. This commit removes the call to update_ms() and just adds new_tbf->set_ms(ms()) which will also work as expected if ms() == NULL. Sponsored-by: On-Waves ehf
2015-05-21tbf: Explicitly pass the direction to update_ms()Jacob Erlbeck1-2/+2
The type of the TBF update_ms() is being called on does not always reflect whether the TLLI has been signaled by the MS or the SGSN. This commit adds an additional parameter to tell the method, in which direction the TLLI has been passed. Sponsored-by: On-Waves ehf
2015-05-21ms: Support new and old TLLIsJacob Erlbeck1-7/+12
According to the specification (GSM 04.08/24.008, 4.7.1.5) after a new P-TMSI has been assigned, the old P-TMSI must be kept basically until it has been used by both sides. Since the TLLI will be derived from the P-TMSI, the old TLLI must also be kept until the new TLLI has been used by both MS and SGSN. This commit modifies the TLLI handling of GprsMs accordingly. set_tlli() is only used with TLLIs derived from MS messages, confirm_tlli() is used with TLLIs derived from messages received from the SGSN. tlli() returns the value set by the MS. check_tlli() matches each of the TLLI used by either MS or SGSN as well as the old TLLI until it has been confirmed. Sponsored-by: On-Waves ehf
2015-05-20ms: Integrate the MS storageJacob Erlbeck1-4/+11
Use the MS storage to find a MS object for a given TLLI instead of searching the TBF lists. The TBFs are then taken from the MS object, if one has been found. If all TBF might be temporarily detached from the MS object, a GprsMs::Guard is added to prevent the deletion of the object, in case another TBF gets attached later on in the scope. Ticket: #1674 Sponsored-by: On-Waves ehf
2015-05-20tbf: Add MS object management to TBF codeJacob Erlbeck1-0/+2
This commit adds MS object creation and cleanup to the TBF related code. MS objects are created when a TBF that has been "anonymous" so far gets associated with a TLLI. When a TBF is replaced by another, the old TBF is detached and the new one is attached to the MS. When all TBFs have been detached, the MS object gets deleted. The TBF related code should not call attach_tbf/detach_tbf directly but use set_ms instead to make sure, that the references are updated properly. GprsMs::detach_tbf also calls set_ms(NULL) on the detached TBF object. The MS object is not really used yet, the focus is still on object creation, TBF association, and cleanup. Ticket: #1674 Sponsored-by: On-Waves ehf
2015-05-06bssgp: Compute and transmit queue delayJacob Erlbeck1-6/+10
The specification 28.018, allows to transmit the average LLC downlink queueing delay in FLOW CONTROL BVC messages (BVC Measurement IE, see GSM 28.018, 10.4.4 and 11.3.7). This commit extends gprs_bssgp_pcu.cpp to compute the average delay time between two subsequent FLOW CONTROL BVC messages. The average is implemented as an arithmetic average without any weighting. Ticket: OW#1432 Sponsored-by: On-Waves ehf
2015-05-06tbf: Added calls to llc_dropped_frameJacob Erlbeck1-0/+3
Currently this function which increments the corresponding counter is just called in gprs_llc::clear(). It is not called on places where LLC DISCARDED messages are sent. This commit adds calls to llc_dropped_frame() at these places. Sponsored-by: On-Waves ehf
2015-04-30tbf: Remove double assigment to m_last_dl_drained_fnJacob Erlbeck1-1/+0
Currently the value -1 is assigned twice to m_last_dl_drained_fn within append_data(). This commit removes the first of these assigments. Sponsored-by: On-Waves ehf
2015-04-09tbf: Send BSSGP LLC discarded on TBI exhaustionJacob Erlbeck1-17/+14
Currently the PCU silently discard LLC frames from the SGSN if a DL TBF cannot be allocated. This commit changes tbf_new_dl_assignment and reuse_tbf to send an LLC discarded message to the SGSN in this case. Ticket: #607 Sponsored-by: On-Waves ehf
2015-04-02tbf: Force ACK after the last DL LCC frame has been receivedJacob Erlbeck1-0/+35
If the protocol layers above LLC (e.g. TCP) need an acknowledgement to continue, it can take up to 400ms (single TS) until the MS is polled for Ack/Nack which it can use to request an uplink TBF quickly. The 400ms result from requesting an DL Ack/Nack every 20 RLC blocks until all pending LLC frames have been sent. Especially TCP's slow start mechanism can lead to a high delay at the start of the connection, since the sender will eventually stop after having sent the first packets (up to 4 (RFC2581) or 10 (RFC6928)). This commit modifies append_data() to (re-)start a timer every time it handles an LLC packet and to request an Ack/Nack every time it expires. So if the server ceases to send IP packets, the MS is polled in the assumption, that the server is waiting for an ACK. The following VTY commands are added (pcu node): - queue idle-ack-delay <1-65535> timeout in centiseconds - no queue idle-ack-delay disable this feature (default) A sensible value is 10 (100ms) that at gave promising results when testing locally. Sponsored-by: On-Waves ehf
2015-04-02tbf: Use a hysteresis when discarding DL LLC framesJacob Erlbeck1-11/+39
Currently single LLC blocks are discarded when the PDU lifetime expires. If an IP packet has been fragmented either on the IP or on the LLC layer and is therefore distributed over several LLC frames, the kept fragments are transmitted and then discarded by the MS because of the missing PDU. This can cause massive IP packet loss when there are many fragmented packets (e.g. when trying 'ping -s1800' or if the GGSN chops downlink IP packets into several SNDCP packets). On the other hand, discarding too many packets might disturb the congestion handling of TCP. Dropping plain TCP ACKs might also hinder flow control and congestion avoidance. This commit adds a hysteresis algorithm to the LLC discard loop. If an LLC message's age reaches the high water mark, further message's with an age above the low water mark are discarded, too. This is aborted, if a GMM, a non-UI, or a small message is detected. In these cases, that message is kept. The following VTY commands are added (pcu config node): - queue hysteresis <1-65535> set the difference between high (lifetime) and low watermark in centiseconds - no queue hysteresis disable this feature (default) Since the SGSN will most probably send all fragments of a single N-PDU without much delay between them, a value slightly above the average transmission delay jitter between SGSN and PCU is probably a sensible value to discard all fragments of a single IP packet. This is an experimental feature that might be replaced by more advanced means of active queue management in the future. Sponsored-by: On-Waves ehf
2015-03-25tbf: Poll MS on idle DL TBFsJacob Erlbeck1-0/+1
If an MS wants to open a new UL TBF, it can either use (P)RACH or request one in a Ack/Nack message for a DL TBF (PACCH). When a TBF becomes idle (LCC queue is empty but the TBF is kept open), there aren't any Ack/Nack requests that can be used by the MS to ask for an UL TBF, therefore it has to use the RACH. This leads to many RACH requests even for a single HTTP transaction, so it takes some time to retrieve even a simple web page. This commit modifies the scheduler to regularly send Ack/Nack requests on idle DL TBFs. It does so by extending the priority based scheduling algorithm to have 5 priority levels (highest priority first): - Control block is pending - High age (100%) threshold reached (-> request Ack/Nack) - Data is waiting or there are pending Nacks - Low age (200ms) threshold reached (-> request Ack/Nack) - Pending Nacks that have been resent already - None of the above (-> send DL dummy control block) The 'age' refers to the time since since the last control block has been sent on the TBF. This high age threshold is set to dl-tbf-idle-time or to 50% of T3190 (whichever is smaller), aiming for at least a poll (and TBF shutdown) after the TBF has expired and to safely prevent expiry of T3190. So if dl-tbf-idle-time > 200ms, there will be a poll every 200ms and a final poll after dl-tbf-idle-time. On high load, the interval between polls can get higher, but the 'high age' poll should be in place. This commit implements the scheduling with respect to GSM 44.060, 9.3.1a ("Delayed release of downlink TBF"). Ticket: #556 Sponsored-by: On-Waves ehf
2015-03-25tbf: Only create dummy frames if necessaryJacob Erlbeck1-1/+9
Currently a lot of LLC dummy commands will be generated while waiting for an ACK for the DL TBF, even if there are blocks that could be resent instead. This patch modifies create_dl_acked_block to only call create_new_bsn() if there is unsent LLC data or m_window is empty. If the TBF is in state FLOW, no unsent LLC data is left, but there are blocks left in m_window, those are resent instead. Sponsored-by: On-Waves ehf
2015-03-25tbf: Implement delayed release of a downlink TBFJacob Erlbeck1-5/+41
Currently a DL TBF is immediately closed, when the LLC queue is drained. This will lead to a new DL assignment if data is received afterwards. In addition, it is not possible to keep the PACCH open to poll the MS for UL establishment requests there. GSM 44.060, 9.3.1a suggests to delay the release of an inactive TBF for some time (max 5s). This commit mainly changes create_new_bsn() to send LLC dummy commands as filler if no LLC data is available until keep_open() returns false. The keep_open() functions returns true unless a configurable time has passed after the LLC data store drained. By default, that time is not set which causes keep_open() to always return false, so that delayed release is effectively disabled. The following VTY commands are added: - dl-tbf-idle-time <1-5000> to set the delay in ms - no dl-tbf-idle-time to disable delayed release Ticket: #556 Sponsored-by: On-Waves ehf
2015-03-25tbf: Insert LLC dummy command if no frame is availableJacob Erlbeck1-0/+16
If a BSN is going to be created but there is no frame stored in m_llc, an empty LLC message would be created. This shouldn't happen currently, but this will be a common case, when delayed TBF release is implemented. This commit changes create_new_bsn() to create an LLC dummy command in that case and to put it into the frame buffer. Sponsored-by: On-Waves ehf
2015-03-25tbf: Use put_frame in append_data if the TBF has no dataJacob Erlbeck1-0/+4
Currently if append_data() is used when there is no LLC data in the DL TBF, it will either call reuse_tbf() which in turn will call put_frame(), or it will append the LLC message to the queue, even if the queue and the frame buffer are empty. This only happens with the test case so far, but this would change when idle DL TBFs are kept open for some time. It results in empty LLC message being sent to the MS (see log below). This commit changes append_data to check for this case and to eventually use put_frame() instead of appending the LLC data to the queue. Addresses: TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=FLOW) downlink (V(A)==0 .. V(S)==0) - Sending new block at BSN 0 -- Chunk with length 0 is less than remaining space (20): add length header to to delimit LLC frame Complete DL frame for TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=FLOW)len=0 - Dequeue next LLC for TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=FLOW) (len=200) Sponsored-by: On-Waves ehf
2015-03-25tbf: Add frames_since_last_poll methodJacob Erlbeck1-0/+21
This functions calculates the number of frames that have passed since the last DL poll (RRBP flag set) has been sent. It returns a value less than zero (fn_now - fn_sched) if the block has been scheduled but not yet sent. If the function is called before the first data block has been sent it will return -1. If the function is called before the first DL poll is sent, it returns the number of frames since the first data block has been sent. Sponsored-by: On-Waves ehf
2015-03-25tbf: Add helper functions for DL TBFsJacob Erlbeck1-5/+19
Some properties of a DL TBF are explicitly calculated within modules using DL TBFs. This commit introduces the methods need_control_ts(), have_data(), is_control_ts() to hide internals of the DL TBF implementation. Sponsored-by: On-Waves ehf
2015-03-20tbf: Refactor create_dl_acked_blockJacob Erlbeck1-42/+42
Turn the big nested if statement into a sequence of smaller ones. The call to create_new_bsn is moved upwards. Sponsored-by: On-Waves ehf
2015-03-12tbf: Fix scheduling for DL Ack/Nack requestJacob Erlbeck1-12/+19
Currently the DL Ack/Nack is not requested, if the last chunk of the final LLC frame in the TBF fits exactly into the remaining space of the RLC block. It is also not requested, if the RRBP flag cannot be set due to scheduling issues (single block allocation, polling already pending for this TBF, ...). So up to POLL_ACK_AFTER_FRAMES (20) RLC data blocks will have to be resent, before requesting the Ack/Nack will be retried. This commit removes the first_fin_ack parameter of create_dl_acked_block entirely and adds a request_dl_ack() method that should be called, when the TBF's state changes to FINISHED. This request will be reset, when the block has been scheduled successfully. Since the first_fin_ack hasn't been set if chunk == space, calling request_dl_ack() on both places in create_new_bsn() when the state is changed to FINISHED will also fix the first issue described above. Note that DL scheduling might not be fair concerning access to first_ts when multiple TS are used for a TBF. In theory, a TBF might never get access to first_ts in the worst case. Sponsored-by: On-Waves ehf
2015-02-26tbf: Don't use 'old' DL TBFs after reuse_tbfJacob Erlbeck1-0/+3
Currently two DL TBF objects with the same TLLI exist after reuse_tbf which make the result of tbf_by_tlli undefined. This leads to several DL TBFs belonging to the same TLLI. This commit extends tbf_by_tlli to check the m_tlli_valid flag for DL, too. That flag is set to 0 in reuse_tbf to mark the 'old' DL TBF as invalid after its LLC data has been copied to the new one. Sponsored-by: On-Waves ehf
2014-09-17tbf_dl: Fix warningsDaniel Willmann1-3/+1
Remove unused log argument (cnp bug) and unused variable
2014-09-10tbf: Handle DL ACK/NACK poll timeout correctlyDaniel Willmann1-1/+11
If the PCU didn't receive the downlink ack/nack when it was polled there is no reason to assume it will arrive at a later time. In that case N3105 is already increased, but the next block sent should have a valid RRBP set as well to poll again. This can happen if either the BSN with the valid RRBP gets lost on the downlink or the DL ACK/NACK gets lost on the uplink path. Ticket: SYS#382 Sponsored-by: On-Waves ehf
2014-09-10tbf,bts: Keep track of new TBF for dl/ul assignment in m_new_tbfDaniel Willmann1-2/+31
There are a couple of possibilities where one TBF is used to assign a new one: 1. Assign a DL TBF from a UL TBF 2. Assign a UL TBF from a DL TBF 3. Assign a DL TBF from a DL TBF which is in wait-release state (T3193 is running) In these cases the assignment is sent on the existing TBF and triggers the assignement of the new TBF (with different TFI/direction). The current code detects these situations by looking at dl/ul_ass_state and then chosing the TBF with the opposite direction (DL/UL) that has the same TLLI. This does not work in the case 3 above where a new DL TBF is triggered for a DL TBF. The current code reuses the old TBF (and TFI), but this violates the spec. This patch introduces a m_new_tbf member which is set to the new TBF to be assigned. When receiving a control ack the code looks up the n_new_tbf member of the tbf that requested the control ack and completes the ul/dl assignment. If the old TBF was in the wait release state (T3193 is running) it is released. From 3GPP TS 04.60 9.3.2.6: """ If the network has received the PACKET DOWNLINK ACK/NACK message with the Final Ack Indicator bit set to '1' and has new data to transmit for the mobile station, the network may establish a new downlink TBF for the mobile station by sending the PACKET DOWNLINK ASSIGNMENT or PACKET TIMESLOT RECONFIGURE message with the Control Ack bit set to '1' on PACCH. In case the network establishes a new downlink TBF for the mobile station, the network shall stop timer T3193. """ reuse_tbf() is modified to allocate a new TBF with a new TFI and trigger a dl assignment for that TBF on the old TBF. All pending data is moved to the new TBF. Ticket: SYS#382 Sponsored-by: On-Waves ehf
2014-08-12tbf: Split out UL/DL TBF methods into separate filesDaniel Willmann1-0/+671
tbf_ul.cpp for UL TBF methods tbf_dl.cpp for DL TBF methods This commit contains no code changes. Ticket: SYS#389 Sponsored by: On-Waves ehf