Commit Graph

569 Commits

Author SHA1 Message Date
Jacob Erlbeck 0a0b5dcb32 pcu: Add pcu_utils.h to Makefile.am
Addresses:
src/gprs_rlcmac_sched.cpp:26:23: error: pcu_utils.h: No such file or directory

Sponsored-by: On-Waves ehf
2015-03-29 13:55:42 +02:00
Jacob Erlbeck 502bd1feea tbf: Poll MS on idle DL TBFs
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-25 12:34:38 +01:00
Jacob Erlbeck e25b5b91f6 tbf: Only create dummy frames if necessary
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-25 12:34:38 +01:00
Jacob Erlbeck 2cbe80b53e tbf/test: Add test for delayed release
This tests checks the implementation of the delayed release of an
downlink TBF.

Ticket: #556
Sponsored-by: On-Waves ehf
2015-03-25 12:34:34 +01:00
Jacob Erlbeck 3bed5d11d2 tbf: Implement delayed release of a downlink TBF
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-25 12:32:35 +01:00
Jacob Erlbeck cbb1e70554 tbf: Insert LLC dummy command if no frame is available
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-25 12:21:55 +01:00
Jacob Erlbeck c495209122 tbf: Use put_frame in append_data if the TBF has no data
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-25 12:12:29 +01:00
Jacob Erlbeck 005ee7f862 tbf: Add frames_since_last_poll method
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-25 12:12:27 +01:00
Jacob Erlbeck 2493c660e9 tbf/test: Fix fn/block_nr in test_tbf_final_ack
Currently fn and block_nr are not incremented correctly. In addition,
the comments around the sending of blocks are not accurate either.

This commit introduces the send_rlc_block helper function which takes
care of the increments, updates the comments to reflect what is
really happening, and adds assertion to verify at least some aspects
of what is now stated in the comments.

Sponsored-by: On-Waves ehf
2015-03-25 12:10:48 +01:00
Jacob Erlbeck a3e4509ff9 tbf/test: Put BTS setup and DL TBF creation into helper functions
Put the generic parts of test_tbf_final_ack into helper functions to
reduce the size of the test and to avoid too much code duplication
when creating new tests.

Sponsored-by: On-Waves ehf
2015-03-25 12:10:48 +01:00
Jacob Erlbeck eceb910fef tbf: Add helper functions for DL TBFs
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-25 12:10:45 +01:00
Jacob Erlbeck 95340242ed tbf: Refactor create_dl_acked_block
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-20 14:32:20 +01:00
Jacob Erlbeck 612e93e360 llc: Add put_dummy_frame to create an LLC dummy command
The LLC dummy command is needed for RLC block stuffing, e.g. when a
TBF should be kept open if no LLC data is available. The RLC block
headers do not support stuffing, only the last block of a TBF can be
used partially. LLC dummy commands are discarded by the receiver
immediately, because the have an invalid FCS checksum.

This commit adds the function put_dummy_frame, which puts a LLC dummy
command into the frame buffer. The requested length is given as an
argument, but the real length might be adjusted according to the
specification (see GSM 44.064, 6.4.2.2).

Sponsored-by: On-Waves ehf
2015-03-20 14:12:28 +01:00
Jacob Erlbeck 39645b824a bssgp: Handle BSSGP STATUS messages
Currently incoming BSSGP STATUS messages are just logged and apart
from that ignored. Since it is possible that the gbproxy can
eventually send both valid replies (from the primary SGSN) and
STATUS(unknown BVCI) messages (from the secondary SGSN). Since the
PCU assumes in this case that the BVC has been successfully reset and
unblocked, it will not send a BVC RESET message after receiving an
NS_UNBLOCK.

This commit changes gprs_bssgp_pcu_rcvmsg to pass BSSGP STATUS
messages to bssgp_rcvmsg() which will in turn call bssgp_prim_cb()
with primitive NM_STATUS. Then the BVC RESET or UNBLOCK procedure
will be started if the IE in the message matches and the PCU assumes
that the BVC should have been successfully reset and unblocked
respectively while the STATUS message tells otherwise.

Note that bssgp_rcvmsg() from libosmocore is otherwise used for the
SGSN side only, albeit it generally just decodes messages, does basic
protocol handling and eventually invokes PRIM indications. The only
exception here is the handling of BVC RESET, which is implemented
specifically for the SGSN.

Ticket: OW#1414
Sponsored-by: On-Waves ehf
2015-03-17 10:44:07 +01:00
Jacob Erlbeck 1e96af6325 bssgp: Set blocking and reset timer to 30s
Currently the timer T1 and T2 are hard-coded to 1s which is pretty
low in consideration of a possible high latency connection to the
SGSN.

This commit introduces macros for the timer values and sets them to
30s.

Sponsored-by: On-Waves ehf
2015-03-17 10:43:42 +01:00
Jacob Erlbeck 7c44415d78 tbf: Fix scheduling for DL Ack/Nack request
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-03-12 18:08:18 +01:00
Jacob Erlbeck 0eabffdc35 sched: Modify DL scheduling to use different priorities
Currently the DL blocks are scheduled round robin to each TBF that is
either in state FLOW or FINISHED and not waiting for an IMM.ASS
confirmation. This way, if single blocks has been NACK'ed by the MS
and the PCU has already resent the missing packets, the PCU starts
retransmitting them until it has received an ACK/NACK even if other
TBF have RLC blocks that need to be transmitted.

This commit changes sched_select_downlink to select the next TBF with
the highest priority, where blocks that are going to be resent again
have a lower priority unless the window is stalling. If there is only
one TBF the old behaviour is kept, since there is no other TBF that
can have a higher priority.

If there is much packet loss on a single phone, this modification can
lead to a higher latency for that MS.

Sponsored-by: On-Waves ehf
2015-03-06 19:28:10 +01:00
Jacob Erlbeck 1842c921b3 tbf: Reduce m_new_tbf logging messages
Currently tbf->m_new_tbf may point to itself if no new TBF is
assigned. But this leads to additional logging messages, since the
code in set_new_tbf and tbf_free assumes, that a real new TBF is
assigned and generates log messages accordingly.

This commit adds checks to avoid those messages in the above case.

Sponsored-by: On-Waves ehf
2015-03-06 19:28:08 +01:00
Jacob Erlbeck adcdf150a6 tbf: Add name() method and put the buf into the tbf
Currently tbf_name() must not be used twice in a printf statement
with different TBFs, since the same baffer will be used for each.

This commit puts the text buffer into struct gprs_rlcmac_tbf to avoid
this problem.

Sponsored-by: On-Waves ehf
2015-03-06 19:25:53 +01:00
Jacob Erlbeck a41a71e2d4 pcu: Fix log message
This commit adds a missing LF to a log message.

Sponsored-by: On-Waves ehf
2015-02-26 16:24:32 +01:00
Jacob Erlbeck 297edf754f tbf: Don't use 'old' DL TBFs after reuse_tbf
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
2015-02-26 16:22:34 +01:00
Jacob Erlbeck 08fe76a893 tbf: Fix dangling m_new_tbf pointer
Currently if a 'new' TBF is freed before the 'old' one (where
old_tbf->m_new_tbf == new_tbf), the old_tbf->m_new_tbf is not cleared
and can be accessed later on. This can lead to inconsistencies or
segmentation faults.

This commit adds m_old_tbf which points back from new_tbf to old_pdf.
m_new_tbf and m_old_tbf are either both set to NULL or one is the
reverse pointer of the other (tbf->m_new_tbf->m_old_tbf == tbf and
tbf->m_old_tbf->m_new_tbf == tbf). It extends set_new_tbf and
tbf_free to update the pointee accordingly.

The TBF test is extended to check this invariant at several places.

Sponsored-by: On-Waves ehf
2015-02-23 15:10:20 +01:00
Jacob Erlbeck 5e9f40d3d9 tbf/test: Modify test to create a dangling TBF pointer
When new_tbf is freed before dl_tbf in test_tbf_final_ack, dl_tbf
still contains a pointer to it in m_new_tbf.

This patch changes the test to accept a test mode parameter and runs
it twice which a different order of tbf_free in each run. Consistency
checks are added, to check for a danglilng m_new_tbf pointer in both
cases.

Sponsored-by: On-Waves ehf
2015-02-23 15:07:06 +01:00
Jacob Erlbeck 18fef10641 tests: Fix library link order
Currently libgprs.la is listed after libosmocore.so which leads to
link errors when compiling under Ubuntu with the system build tools
(no cross compiling).

This patch moves libgprs.la in front of the external libs.

Sponsored-by: On-Waves ehf
2015-02-23 14:17:01 +01:00
Holger Hans Peter Freyther f5c97476de tbf: Fix dereference before null check
m_new_tbf might be NULL. Assign was_releasing _after_ we have
done the NULL check.

Related: Coverity CID#1238847
2014-12-26 18:32:00 +01:00
Holger Hans Peter Freyther 49f26bf6e8 Fix VTY documentation
Documentation error (missing docs):
<command id='show tbf all'>
        <param name='all' doc='(null)' />
2014-12-20 15:22:09 +01:00
Daniel Willmann 07e39302ec tests/tbf: Commit TbfTest.err *with* whitespace "errors"
Otherwise the diff and hence the test will fail...
2014-09-19 12:01:39 +02:00
Daniel Willmann 0f58af6627 tests/tbf: Use correct function to enqueue llc data
The test called the llc enqueue() function directly which didn't take
care of prepending the tv values for the timeout to the data.

Now the test uses dl_tbf.append() which takes care of prepending the tv
values. With this patch make distcheck on jenkins should no longer fail
with "Discarding LLC PDU because lifetime limit reached." messages.
2014-09-19 11:57:21 +02:00
Daniel Willmann 635d47c78c tbf_dl: Fix warnings
Remove unused log argument (cnp bug) and unused variable
2014-09-17 17:59:03 +02:00
Daniel Willmann 1c15573012 poll_controller: Be stricter with the timeout handling
There is no reason to believe that an ACK that was polled for FN X and
has not arrived on the next frame will arrive sometime after.

Ticket: SYS#382
Sponsored-by: On-Waves ehf.
2014-09-10 19:19:58 +02:00
Daniel Willmann efd5dbb168 tbf: Handle DL ACK/NACK poll timeout correctly
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-10 19:19:58 +02:00
Daniel Willmann 510d7d36ed tests/tbf: Test for final ack issue
Ticket: SYS#382
Sponsored-by: On-Waves ehf
2014-09-10 19:19:58 +02:00
Daniel Willmann e481815583 tbf,bts: Keep track of new TBF for dl/ul assignment in m_new_tbf
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-09-10 19:04:46 +02:00
Daniel Willmann 08e57c8366 tbf: Include TBF state in tbf_name output
Sponsored-by: On-Waves ehf
2014-08-15 18:28:45 +02:00
Daniel Willmann 341689d6c5 TbfTest: Make logging more verbose
Sponsored-by: On-Waves ehf
2014-08-15 18:28:45 +02:00
Holger Hans Peter Freyther ad1fcccf60 Merge branch 'sysmocom/tbf-split' 2014-08-12 19:25:32 +02:00
Daniel Willmann ca102af92b tbf: Split out UL/DL TBF methods into separate files
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
2014-08-12 19:24:49 +02:00
Daniel Willmann eb100244b0 tbf, bts: Use tbf set_state method instead of tbf_new_state function
All the function did was add debug output and call the set_state method.
Move the debugging into the method and remove the function.

Ticket: SYS#389
Sponsored by: On-Waves ehf
2014-08-08 14:15:24 +02:00
Daniel Willmann 418a4230e0 tbf, gprs_rlcmac_meas: Move the DL bandwidth variables to the DL TBF
The bandwidth calculation as well as loss report is only done for DL TBF
so move everything related to that in there.

Ticket: SYS#389
Sponsored by: On-Waves ehf
2014-08-08 14:15:24 +02:00
Daniel Willmann cf706b0775 tbf: Make llc_dequeue a method of DL TBF
llc_dequeue is only used in DL TBF to send the data from the BSSGP to
the MS.

Ticket: SYS#389
Sponsored by: On-Waves ehf
2014-08-08 14:15:24 +02:00
Daniel Willmann e2732e2f59 tbf: Make snd_ul_ud() and assemble_forward_llc() methods of UL TBF
They are only called for UL TBF.

Ticket: SYS#389
Sponsored by: On-Waves ehf
2014-08-08 14:15:24 +02:00
Holger Hans Peter Freyther f72fcfe219 Merge remote-tracking branch 'origin/sysmocom/tbf-split'
the TBF handling in osmo-pcu mixes UL and DL TBFs together. They
are quite different, however, and should be treated differently.

This patch series continues the work of splitting up UL and DL TBFs
into their own classes and explicitly using a DL TBF or UL TBF
instead of the base class in those parts of the code that deal
with only one variant.

I didn't test every single commit, but each should compile and
the result passes make check as well as our iperf test against
a GSM modem.

[Text from Daniel's cover mail]
2014-08-08 08:49:03 +02:00
Daniel Willmann 7e994e392d tbf, ...: Make the fields in the dl/ul struct member variables
There is no need for the union/struct anymore. Make the variable members
of the UL/DL class.

As a result gprs_rlc_dl_window gets a reset() method because
memset(&dir.dl, 0, sizeof(dir.dl)) doesn't work anymore in reuse_tbf().

Ticket: SYS#389
Sponsored by: On-Waves ehf
2014-08-07 16:12:05 +02:00
Daniel Willmann 6a8a1dcda2 tbf: Move the dir.dl/ul members out of the base class into DL/UL TBF
Ticket: SYS#389
Sponsored by: On-Waves ehf
2014-08-07 16:12:05 +02:00
Daniel Willmann d1d1633121 tbf: Remove unused function sns()
The current code uses dir.*l.window.sns() directly. The current
implementation only returns the dl.window.sns() which will cause
problems.
Remove now and re-add it as a method of DL/UL TBF if and when it is
needed.

Ticket: SYS#389
Sponsored by: On-Waves ehf
2014-08-07 16:12:05 +02:00
Daniel Willmann cd44ec41c5 gprs_rlcmac_ts_alloc: Be explicit about which TBF is used
Use UL/DL TBFs instead of the base class wherever it is clear that the
code only deals with one kind of TBF.

Ticket: SYS#389
Sponsored by: On-Waves ehf
2014-08-07 16:12:05 +02:00
Daniel Willmann f55e58f5cf encoding: Change function signature to use UL TBFs where it makes sense
encode_rbb() and write_packet_uplink_assignment are only called with UL
TBFs so change the function signature to reflect that.

Ticket: SYS#389
Sponsored by: On-Waves ehf
2014-08-07 16:12:05 +02:00
Daniel Willmann 350f64d9e2 tbf: Move UL TBF methods from base class into UL TBF
The methods create_ul_ack(), rcv_data_block_acknowledged(),
maybe_schedule_uplink_acknack() are only used for UL TBFs so make them
methods of that class instead of the base class.

Ticket: SYS#389
Sponsored by: On-Waves ehf
2014-08-07 16:12:05 +02:00
Daniel Willmann 4f3c420852 gprs_rlcmac_sched: Use UL/DL TBFs in scheduler
Ticket: SYS#389
Sponsored by: On-Waves ehf
2014-08-07 16:12:05 +02:00
Daniel Willmann b2886f1a0d tbf: Split UL and DL TBFs up in create_dl_ass()
Explicitly use UL and DL TBFs where they are needed.

Ticket: SYS#389
Sponsored by: On-Waves ehf
2014-08-07 16:12:05 +02:00