Compare commits

...

290 Commits

Author SHA1 Message Date
Keith
9192c6c6c2 Merging parts of commit 653e974fec00414ba85baf258ccc46ea778a53bd
from branch nrw/litecell15
Original Author: Minh-Quang Nguyen <minh-quang.nguyen@nutaq.com>
 LC15: Implementation of LC15 specific features

Made some modifications to this commit
based on d8cd756da4
 Get rid of 'struct gsm_bts_role_bts'

Only compile tested.
This is just to get a start on this branch.
I have not yet looked at all other commits in the
nuran branch that may be related.

This one however, does seem to be important
as it implements a larger cell radius than
is currently possible with osmo master.

Change-Id: I79416faaa3ba328c9c2dabcd695a1b880fe666da
2020-03-31 22:06:37 -05:00
Oliver Smith
ae4d85d891 VTY: add "test send-failure-event-report"
Send test failure event report OML message to the BSC. I found this
useful while manually testing related handling code in OsmoBSC.

Related: OS#1605
Change-Id: I0c4eba1636d8faf5012db26643bdf1d9fb6bfa1e
2020-03-24 08:01:05 +00:00
Philipp Maier
dbb5addf7d osmo-bts-trx: do not set rx-gain to 1 by default
The sample configs supplied within the doc/trx directory set the
rx-gain parameter to 1. A low value like this may cause a noticeable
degration of rx performance (For an USRP B200 an rx-gain of 38dbm is
recommended). Lets remove this seting from the sample configuration to
allow the default settings in osmo-trx to be applied.

Change-Id: I76be1739b638b3c1b0de5ac667eed53397631caa
Related: OS#4467
2020-03-23 17:18:51 +00:00
Harld Welte
e2f9d0eabe trx: Use NOPE indications on SDCCH
Without using the NOPE indication it might happen that we get
into the following situation:
* bursts 0,1,2 of a given block are received
* burst 3 is lost on the radio interface, OsmoTRX sends NOPE
* osmo-bts-trx doesn't pass the NOPE the the rx_tch*_fn()
* we never detect the end of the block, never perform decoding
  and even if the burst could be fully decoded, we loose the block

Related: OS#4661
Related: OS#2975
Change-Id: Idfc5c9a23db808c5f87ef5646c7e1d1cd3127371
2020-03-22 14:06:56 +01:00
Harld Welte
4e07b83a64 trx: Use NOPE indications from OsmoTRX for TCH/F and TCH/H
Without using the NOPE indication it might happen that we get
into the following situation:
* bursts 0,1,2 of a given block are received
* burst 3 is lost on the radio interface, OsmoTRX sends NOPE
* osmo-bts-trx doesn't pass the NOPE the the rx_tch*_fn()
* we never detect the end of the block, never perform decoding
  and even if the burst could be fully decoded, we loose the block

For voice, it can lead to lost RTP frames in uplink, which is also
problematic.

Let's deal with burst_len=0 in rx_tch*_fn() and use it as nope_fn.

Closes: OS#4661
Related: OS#2975
Change-Id: I0fbf4617daf24bd8aecfd9cfe1efd66cf73a277a
2020-03-22 14:06:47 +01:00
Harld Welte
f1efd727fb trx: Fix reported BER for TCH/H
This fixes a regression introduced in I710d0b7cf193afa8515807836ee69b8b7db84a84

We (obviously!) cannot compute the BER before performing convolutional
decoding.

Change-Id: I4e57f45d49cb513e4843e56f50c8de6980958fdc
Related: OS#2977
Related: OS#4667
2020-03-22 14:06:47 +01:00
Harald Welte
e36fbca15f osmo-bts-virtual: Fix "virtual-um net-device NETDEV"
The VTY option to bind the virtual Um multicast to a specific
network interface has existed ever since osmo-bts-virtual was
first merged to the repo.   However, embarrassingly, until today
it never did anything, i.e. the code to actually perform the bind
was missing.

Depends: libosmocore.git Ib52d22710020b56965aefcef09bde8247ace4a9c
Change-Id: I303f2e616d2d32b5a8005c3dcf0f5fad19ad3445
Related: OS#2966
2020-03-10 21:36:00 +01:00
Harald Welte
5914d76d5c osmo-bts-virtual: Add "virtual-um ttl <0-255>" VTY option
This can be used to determine the multicast TTL packet and hence
how far the packet will propagate in the network.  If you want to
operate the virtual Um only on your own machine, a TTL of 0 would
prevent the packets from ever being transmitted on your local
ethernet segment.

Change-Id: I18a9f93b764aee4e1dc68a1c6ac4d078e52ca61d
Related: OS#2966
2020-03-10 21:35:56 +01:00
Oliver Smith
cb4340b8a4 rsl: make IP DSCP configurable
Related: OS#4438
Depends: libosmo-abis I41603db8c1286660ad57ac1c78a8fb393a2b080b
Change-Id: Icdef5d40243fefdeae23f3bcf9c6702e8487928a
2020-03-08 17:56:52 +01:00
Harald Welte
58d79e88ad osmo-bts-virtual: implement GSMTAP_CHANNEL_VOICE
GSMTAP_CHANNEL_VOICE is the mechanism by which GSMTAP can [finally!]
be used to transport circuit-switched voice codec payload, and not
just signalling.

Original patch by Neels Hofmeyr, heavily extended by Harald Welte.

Depends: libosmocore.git I952044a17334f35712e087dc41781805000aebc1
Change-Id: I1cd9a251ce0b87181a0822d7940bbfc9f1428543
2020-03-08 17:56:52 +01:00
Harald Welte
6a5039674f l1sap: Use msgb_pull_l2() and unify l1sap_tch_ind + l1sap_ph_data_ind
In l1sap_ph_data_ind() we can use msgb_pull_l2() which is an exact
implementation of the functionality there.

In l1sap_tch_ind(), the existing code is actually wrong by making the
assumption that the msgb contains exactly an entire osmo_phsap_prim.
Better to also dynamically compute the number of bytes to ensure
we only pull those ahead of the L2 header, no matter what their exact
count.

Change-Id: I13f7f8ba93795e40b1fb4a306fe765e059f642cf
2020-03-08 17:12:15 +01:00
Vadim Yanitskiy
3f35ab258d osmo-bts-virtual: do not log GSMTAP message sending failure twice
Change-Id: I39e9edf35240ef31e3432412b459c2b8fb0de054
2020-03-04 20:43:02 +07:00
Vadim Yanitskiy
f9e7ccce27 osmo-bts-virtual: do not print redundant info in tx_to_virt_um()
LOGL1S() already prints enough context information.

Change-Id: I29adf9360b96544b7f58766d5cd26d97117884d9
2020-03-02 00:26:33 +07:00
Vadim Yanitskiy
2b948a3d17 osmo-bts-virtual: fix wrong endianness in gsmtap_hdr_stringify()
Change-Id: Ic9e84dc4adc44df735cba102bdace2fb1993ac8e
2020-02-29 18:09:46 +07:00
Vadim Yanitskiy
1f932689fc common/sysinfo: reduce criticality of a logging message
During the process of bootstrapping, it may happen that System
Information Type 3 is not yet received from the BSC, while the
BTS already needs to transmit a block on AGCH or PCH.

Since the RSL link is established later than the OML link, it's
kind of expected, so we should not log it as error.

Change-Id: I41aa3dbe375cf42c39032bafa80dba94d6219d35
2020-02-29 14:29:27 +07:00
Vadim Yanitskiy
7364ef15d9 vty: fix left shift by 31 cannot be represented in type 'int'
Change-Id: I3e5940e8f360bf6563f4c1b5ebd09579f9108c81
2020-02-27 23:35:09 +07:00
Harald Welte
24f98a0df9 virtual: Fix VTY commands to specify GSMTAP multicast groups
osmo-bts-virtual uses GSMTAP over multicast groups to communicate
with one or more virtphy instances.  There are some well-known default
multicast groups, but those can also be overridden via the VTY.

The problem is: If you actually try that, osmo-bts-virtual will abort,
as we try to talloc_free() when using osmo_talloc_replace_string()
on the constant default string.

The proper solution is to talloc_strdup() the constant default string
when setting the default value in bts_model_phy_link_set_defaults().

Change-Id: Ia96fea891a22e5a3c47ce658eda130ba8d4fc411
2020-02-26 14:36:58 +01:00
Pau Espin Pedrol
6ea3b28321 cosmetic: Fix some typos with codespell
Change-Id: I1bbb4871f764816dcbba86d833194be601fa9228
2020-02-25 18:51:15 +01:00
Pau Espin Pedrol
eba074e081 bts-trx: trx_if.c: Fix some printf formats
Compiler from raspberrypi4 warns/errors about those.

Change-Id: I4f973eb4ffdf8869b522d14e25853357fcd1e984
2020-02-25 18:28:52 +01:00
Philipp Maier
5184576572 osmo-bts-sysmo: merge measurement data and payload
For osmo-bts-sysmo the MPH INFO MEAS IND indication is still sent
separately. Lets merge the measurement information into the PH DATA

Change-Id: Iffe7865727fbf9bca8eb32a96e8ea05cf718a948
Related: OS#2977
2020-02-17 12:40:07 +01:00
Philipp Maier
ac61baed2e Do not depend on pcu_direct flag when populating ph_data_ind
The struct members ber10k, ta_offs_256bits and lqual_cb in ph_data_ind
are only populated when the pcu_direct flag is not set.

The pcu_direct flag is set when the pcu is directly attached to the phy
and all pcu related traffic (pdtch) is handled without sending it through
osmo-bts-sysmo. For those cases osmo_bts_sysmo will not make use of
those struct members, even if they were populated. When the PCU is not
directly attached the data is needed because it is sent through the
pcu_sock to the PCU.

Lets remove the check because it is not required. Also in future patches
where measurement indications and data / tch indicatins are merged the
struct members are also needed to carry the measurement information for
SACCH as well.

Change-Id: Iaa37bb62af4f5eb4b6e684cb754e68d11e6fd676
2020-02-17 12:11:43 +01:00
Pau Espin Pedrol
aea29c7249 l1sap: Change loglevel of Rx TCH.ind INFO->DEBUG
This line appears tens of times per second when a call is ongoing,
making it impossible to follow logs on INFO level.

Change-Id: Iadb1baf55df2f6d96f85260f2e8d03627fef7e66
2020-02-12 16:01:47 +01:00
Pau Espin Pedrol
52d7eafcea l1_if: Fix strange formatting of Meas info logging
Some use LOGPC, but were used after a LOGP with a trailing newline.
Let's simply add some defines/macros to be able to include it into a
normal LOGP easily insted of having a function.

Change-Id: Ie082b11c9d6d00ff2206184f03f6e3647c3da18c
2020-02-12 14:29:38 +01:00
Vadim Yanitskiy
cb69d607c9 osmo-bts-sysmo/Makefile.am: fix: do not overwrite bin_PROGRAMS
src/osmo-bts-sysmo/Makefile.am:25: warning: bin_PROGRAMS was already
				   defined in condition TRUE, which
				   includes condition ENABLE_SYSMOBTS_CALIB
src/osmo-bts-sysmo/Makefile.am:10: ... 'bin_PROGRAMS' previously defined here

Change-Id: Ib2334dccefd507eaaa6d33e58d4c1e029d7fd540
2020-01-21 18:52:08 +07:00
Philipp Maier
d4f67591c7 l1sap: merge MEAS IND into PRIM PH DATA / PRIM TCH
The MPH INFO MEAS IND indication, which contains the uplink measurement
data is sent in parallel to the PH DATA and TCH indications as a
separate indications. This makes the overall uplink measurement data
processing unnecessarly complex. So lets put the data that is relevant
for measurement into the PH DATA and TCH indications directly.

This change only affects osmo-bts-trx at the moment. In order to keep
the upper layers (l1sap.c) compatible we add an autodection to switch
between separate measurement indications and included measurement data.

Related: OS#2977
Depends: libosmocore I2c34b02d329f9df190c5035c396403ca0a4f9c42
Change-Id: I710d0b7cf193afa8515807836ee69b8b7db84a84
2020-01-20 14:35:19 +00:00
Philipp Maier
8969adc5d9 measurment: write irssi_full_sum variable correctly
The variable irssi_full_sum is not populated with a dummy value when we
are not able to compute irssi_full_sum. Instead we mistakenly write
MEASUREMENT_DUMMY_IRSSI to ber_full_sum, which is wrong

Change-Id: I44d7cb48e3c68ab1b48c78cceb9381ce3e39d7e8
Related: OS#2987
2020-01-20 14:33:51 +00:00
Philipp Maier
a0403d3769 ta_control: move timing advance code from osmo-bts-trx to common
The timing advance controller that is implemented in loops.c of
osmo-bts-trx only works for osmo-bts-trx and not for any of the phy
based bts. Lets move the timing advance controller into the common part
and make it available for every bts. Also lets add a unit-test.

Change-Id: If7ddf74db3abc9b9872abe620a0aeebe3327e70a
Related: SYS#4567
2020-01-20 14:33:49 +00:00
Vadim Yanitskiy
e7d835ca8c L1SAP: use LOGL_DEBUG for logging from rach_pass_filter()
Due to relatively small training sequence of Access Bursts, there
can be frequent false-positives (basically noise). Fortunately,
we can distinguish them from the real Access Bursts by checking
the signal measurements attached to them (BER, ToA and C/I).

Let's reduce verbosity of logging messages as they are mostly
useful for debugging and may confuse the users / operators.

Change-Id: I7ab6727ffff00140a7f9e762b299b711481393f1
2020-01-14 03:51:08 +07:00
Harald Welte
113712c728 rsl.c: Fix compiler error on gcc-9.2.1
rsl.c: In function ‘rsl_rx_ipac_XXcx’:
rsl.c:2147:39: error: ‘%s’ directive output may be truncated writing up to 255 bytes into a region of size 28 [-Werror=format-truncation=]
 2147 |   snprintf(cname, sizeof(cname), "bts@%s", ipstr);
      |                                       ^~
rsl.c:2147:3: note: ‘snprintf’ output between 5 and 260 bytes into a destination of size 32
 2147 |   snprintf(cname, sizeof(cname), "bts@%s", ipstr);
      |   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Change-Id: Id982a814f401e304327d25c77666f039bc156c1f
2020-01-12 16:11:12 +01:00
Vadim Yanitskiy
e5711efbb5 common/abis.c: make use of RSL TEI from OML IPA RSL Connect
Change-Id: I5927f59a49724170a63e87be604973f7c9d5d8be
2020-01-11 00:51:43 +01:00
Vadim Yanitskiy
f9115ae67a common/vty.c: get rid of generic exit / end commands
Those commands are now handled by libosmovty itself.

Change-Id: I425f9058ae15de929e2ba0283d4057bdf767aeeb
2020-01-11 00:17:10 +01:00
Michael McTernan
b54f1bf122 measurement: use signed integer for division of ta256b_sum
The variable ta256b_sum is int32_t and num_ul_meas_actual is unsigned
int. When ta256b_sum is negative the division produces the wrong result.

This is beacuse the division is performed unsigned as the usual
arithmetic conversions promote to unsigned where both both operands are
the same width.

Lets fix this by casting num_ul_meas_actual to signed.

(Note that in the same function there are various other averages
computed in the same pattern, but they have unsigned operands and so are
correct.)

Related: SYS#4728
Change-Id: I37e3f69109c5ca2948bd4cdb7aa017bf2fcb8172
2020-01-06 12:07:23 +01:00
Pau Espin Pedrol
ee8f4b0a91 Bump version: 1.1.0.95-24e7-dirty → 1.2.0
Change-Id: Id132c615f7398402ac20d179e5917bea58ef3334
2020-01-03 17:18:44 +01:00
Philipp Maier
24e702b7d0 l1sap.c: ensure ms power control loop is running
When a bad SACCH frame is received the processing of the frame is ended
early and lchan_ms_pwr_ctrl() is not called. This means that the power
control loop does not get informed about a situation where the signal
level is very weak and increasing the ms power would make sense. In
order to ensure that the power control keeps working on lost SACCH
frames, lets call lchan_ms_pwr_ctrl() with the current RSSI and the
requested (BSC) power setting.

Related: OS#4281
Change-Id: I4fb85754b1a69376b02da7f4b175c6e8ec9cc35c
2020-01-03 13:03:49 +01:00
Philipp Maier
66c17cfc2d rsl: ensure measurement reports are sent
osmo-bts currently does not generate a measurement report in case the
SACCH of the related traffic channel is lost. This is a problem because
the moment when reception gets bad measurmenet reporting is crucial to
carry out handover decisions effectively.

The presence of a SACCH block controls the conclusion of the measurement
interval and the sending of the RSL measurement report. The latter one
not only requires a measurmenet indication, it also requires a fully
intact SACCH block.

Lets use the NOPE / IDLE indications from V1 of the TRXD protocol to
ensure a SACCH block is always reported up to l1sap.c. In cases where
the SACCH is bad, trigger the sending of the RSL measurement report
manually without attaching the measurmenet data from the MS (which we do
not have in this case)

Related: OS#2975
Depends: osmo-ttcn3-hacks Ib2f511991349ab15e02db9c5e45f0df3645835a4
Change-Id: Idfa8ef94e8cf131ff234dac8f93f337051663ae2
2020-01-03 12:56:00 +01:00
Vadim Yanitskiy
a2392f0f9e osmo-bts-trx/vty: ensure backwards compatibility with older config files
osmo-bts-trx used to have its own (low-level) MS Power Control loop,
but recently it has been ripped out. Since [1], the process fails to
start if the configuration file still contains 'ms-power-control dsp'.

Let's be more tolerant: override 'dsp' by 'osmo' and print a warning.

[1] I49706926b1e962b18791174627bc3cc0cd0cd9d5

Change-Id: I4facd21bca3d8cb80d21e83ea267bc013e474533
2019-12-31 17:03:38 +00:00
Pau Espin Pedrol
e1766f1b7d l1sap: is_fille_frame(): verify len of data compared
Change-Id: Id3d1725ff36091ed5c57927caad09a8baea6f52e
2019-12-23 18:27:47 +01:00
Pau Espin Pedrol
7544f5a45b power_control.c: Clarify loop algo vars and use correct ones during log
Rename some variables so that:
* Variables containing power control levels end up with "_lvl".
* Variables containing power levels end up with _dbm.
* Move old current_dbm var to be ms_dbm, to match its power control
level counterpart ms_power_lvl, and add current_dbm to match its
counterpart ns_power_ctrl.current.

Now that variables are more clear, it also becomes clear that old "diff >
0" condition, apart from difficult, was currently wrong, since in order
to print the raise/low verb we want to compare between old and new
values, not between received and new values. Let's fix that in this same
commit.

Change-Id: I4e279a6b93fbcc5da25bf8c9213310939fd493ce
2019-12-05 12:58:08 +01:00
Pau Espin Pedrol
99ba515985 power_control.c: Log maximum allowed MS Power Level
Change-Id: I983ff824ef6f54f1e800819d622158d5e2a51f04
2019-12-05 11:22:09 +00:00
Pau Espin Pedrol
397a43c38a rsl: Clarify when autnonoums MS Power Ctrl Loop is used
Simplify when the fixed field is set in rsl_rx_chan_activ.

Comment talks about enabling autonoumous control loop, but it is
actually describing it when disabling it, which is confusing.

Change-Id: Id6b444a33ab062f6dab11a0ce62d8aecaea87591
2019-12-05 11:22:09 +00:00
Harald Welte
e571fd60e6 rach_pass_filter(): Add information about channel type
When logging about filtering access bursts, let's indicate if this is
on a CCCH, PDCH or handover related.

Change-Id: I03f21f2b54cbe5aad36ac71a614d5df98867df80
2019-12-04 16:40:30 +01:00
Pau Espin Pedrol
80f9b84a64 rsl_rx_chan_act: Apply bitmask when parsing IE MS_POWER
Change-Id: I99c6a4d353f405582d5e4f9d12c01c25c7bb4dff
2019-12-03 18:34:40 +01:00
Vadim Yanitskiy
bd3eabc13e common/abis.c: use tall_bts_ctx as talloc-context for libosmo_abis_init()
This way it's much easier to introspect the library internal
talloc allocations from the VTY interface.

Change-Id: Ic8d9fc7ce3da8abf0ea73d2b20366133cd801c37
2019-12-02 23:21:27 +00:00
Vadim Yanitskiy
6bb700e9d2 common/abis.c: pass gsm_bts_trx to e1inp_sign_link_create()
Change-Id: I8a6242d3e02f9bd19d287ecad18e001a5991175f
2019-12-02 08:46:43 +00:00
Pau Espin Pedrol
e3a4530919 bts-trx: Drop low layer MS Power Control Loop algo
Let's drop it instead of having code duplication from common code in a
lower layer, and maintain only the one in l1sap for all BTS models.
As a result, osmo-bts-trx loses feature BTS_FEAT_MS_PWR_CTRL_DSP and
will only be able to use "ms-power-control osmo" in VTY, which will be
enabled by default (meaning: change of behavior, now MS Power Control is
enabled by default in osmo-bts-trx and can only by disabled by BSC).
Old bts-trx specific VTY command "(no) osmotrx ms-power-loop" is marked
as deprecated but still working for more usual case (1 TRX configured)
to avoid breaking backward compatibility.

TA low level loop is still kept in loops.c and will be moved to l1sap at
some point too.

Related: OS#1851
Change-Id: I0d8b0c981d9ead91d93999df6e45fb06e426aeb9
2019-11-30 18:50:04 +00:00
Pau Espin Pedrol
0d8cd8ce39 scheduler_trx.c: cast ptrdiff value to fix printf format
On an ARM toolchain:
scheduler_trx.c:294:3: warning: format '%ld' expects argument of type 'long int', but argument 10 has type 'int'

Let's cast it to long int to make sure correct size is applied in all
platforms.

Change-Id: I701b3dbc4e84db21cf02305d374b0df731e70313
2019-11-27 00:19:30 +00:00
Vadim Yanitskiy
3cb61d902c common/vty.c: fix: properly assert() the result of get_string_value()
Change-Id: I6ecd46371e601ad0fb629f9756b36c9c4758a958
Fixes: CID#205067, CID#205068
2019-11-26 17:14:39 +07:00
Vadim Yanitskiy
a070e863e2 pcuif_proto.h: extend RACH.ind with TRX and timeslot number fields
Since there can be multiple PDCH channels configured on different
timeslots, different TRXes, and BTSes, the PTCCH/U handling code
in OsmoPCU needs to know the exact origin of a given RACH.ind.

Otherwise, it is not known which subscriber originated a given
PTCCH/U indication, and hence it is impossible to send PTCCH/D
Timing Advance notification properly.

Fortunately, we can extend the RACH.ind message without even
bumping the protocol version, because every single PDU has a
fixed size defined by the largest message - INFO.ind. In case
if the actual message payload is smaller, the rest is filled
with a constant padding byte (0x00).

Older versions of OsmoPCU will consider the new fields as padding,
while the messages from older OsmoBTS versions will always have
both fields set to 0x00. Since C0/TS0 cannot be configured to
PDCH, this can be easily detected on the other end.

Change-Id: Iff38934a108b6b1cd298669834263a7d5296c3f6
Related: OS#4102, OS#1545
2019-11-22 17:38:07 +00:00
Pau Espin Pedrol
1d9f6efccb power_control.c: Limit speed of announced MS Power Level value changes
It's not a good idea to request big changes in MS Power based on
sporadic bad signal received, let's instead change announced MS power
levels more smoothly to avoid possible big signal strength fluctations,
similar to what is already done in osmo-bts-trx specific loop (loops.c).

Related: OS#1851
Change-Id: Iecc4ec7e21471ec853ad2d5659af4052aba5444c
2019-11-20 20:27:04 +01:00
Pau Espin Pedrol
522fc939e0 power_control.c: Don't use announced MS Power level as input for loop calculations
Use instead the received MS Power currently in use by the MS matching
the measured signal. This way there's no need to wait for the MS to
reach the announced MS power level or add checks in case the MS doesn't
support that specific power level. Furthermore, more fine grained
announced power level value can be obtained faster due to more input
iterations not being dropped while waiting.

osmo-bts-trx specific algo was not following this approach and using
announced MS power instead because it's wowrking at a lower level and
henche was not using the transmitted MS Power level value by the MS as
input for the calculation.

The "if (diff < 2 && diff > -2))" condition is dropped since equal
signal strength may still result in a different MS power level announced
(the one currently used by the MS during tx of last SACCH block).

Related: OS#1851
Change-Id: I4494dc27a295a3dca1d3331d4ff712d486643e13
2019-11-20 19:35:08 +01:00
Vadim Yanitskiy
595eb576fc osmo-bts-trx/trx_if.c: fix: NOPE.ind also contains C/I field
Change-Id: I201b72d2a6f5307ede252d5d707f1ebadafe6a4b
2019-11-20 13:43:37 +00:00
Philipp Maier
5c5ad3cb4a scheduler_trx.c: avoid division by zero when calculating BER
There is theoretical risk that when calculating the BER that a division
by zero occurrs. Lets add a check to avoid n_errors / n_bits_total when
n_bits_total is zero.

Change-Id: I1c0731b9a60be4b8c0c84b85b4403168120ceacd
Fixes: CID#205696
2019-11-20 13:35:02 +00:00
Oliver Smith
ae5e1d7110 osmo-bts-virtual.cfg: ms-power-control dsp -> osmo
Fix error while starting osmo-bts-virtual with the example config:
"This BTS model has no DSP/HW MS Power Control support"

Fixes: c693067b7e ("Introduce BTS feature BTS_FEAT_MS_PWR_CTRL_DSP")
Change-Id: I4f9a06e85d58294719a24197eb1c42a69fbd03d6
2019-11-19 18:28:32 +00:00
Vadim Yanitskiy
19857fbdaa osmo-bts-trx/trx_if.c: also print both RSSI and ToA256 for NOPE.ind
Change-Id: I36586ac33757705df16e14cfdd92becb96c8cf70
2019-11-19 13:54:40 +07:00
Vadim Yanitskiy
8a98255fb5 osmo-bts-trx/trx_if.c: fix: always initialize bi->burst_len for NOPE.ind
A NOPE.ind indicates absence of an Uplink burst, thus it does not
carry a burst. Let's init the burst length to avoid uninitialized
memory access in the scheduler code.

Change-Id: I77f686bf7df385215892e71733a28ff0d90d7222
Fixes: CID#205857
2019-11-19 13:54:36 +07:00
Vadim Yanitskiy
b37b3263a9 osmo-bts-trx: general handling of NOPE / IDLE indications
Each logical channel can now optionally have an additional handler,
that will be called when a NOPE / IDLE indication is received from
the transceiver. The aim of that handler is to keep the logical
channel state updated in case if one or more Uplink bursts are lost.

Change-Id: I71c552f44c25e56e9779d8b8ef5d4de9f8475637
Related: OS#3428
2019-11-19 01:01:45 +00:00
Pau Espin Pedrol
c693067b7e Introduce BTS feature BTS_FEAT_MS_PWR_CTRL_DSP
It indicates whether BTS model supports managing an MS Power Control
Loop over HW/DSP instead of using the software based osmocom algorithm
present in osmo-bts.
osmo-bts-trx own loop implementation is considered to be a "DSP/HW" one
since it acts on lower layers and interferes with osmocom algorithm
since it controls the same end variable "lchan->ms_power_ctrl.current",
this way we make sure both aren't enabled at the same time.
Old behavior in kept: if common upper-layer algo is not enabled
explicitly in VTY (ms-power-control osmo) and bts-trx specific lower
layer algo is neither enabled (osmotrx ms-power-loop <xyz>), then no
power control is done at all.

Related: OS#1851
Change-Id: I49706926b1e962b18791174627bc3cc0cd0cd9d5
2019-11-14 20:02:45 +01:00
Pau Espin Pedrol
d0a2caa021 power_control.c: Fix ms pwr ctrl skipped if MS doesn't support announced MS Power Level
Related: OS#1851
Change-Id: I1a9c00fe4eb3fa1eaa7997a9ec20716ddfe180a7
2019-11-14 20:02:45 +01:00
Pau Espin Pedrol
38c12e9df9 power_control.c: Log rx current and target signal levels
Change-Id: I31ce7930a1daa20a2ff81f31a37df94298c877d6
2019-11-14 20:02:45 +01:00
Pau Espin Pedrol
2149b0ff47 power_control.c: Apply latests improvements from loops.c
Several improvements have been made lately to MS Power Control loop from
osmo-bts-trx in loops.c. Let's port these to the common algorithm.

Related: OS#1851
Change-Id: I579967cc8bb69dc76a315c6c9d3a351f5961d92f
2019-11-14 20:01:58 +01:00
Pau Espin Pedrol
f0e66d90f8 bts-trx: loops.c: Avoid always clamping MS power to MS power class 1
The affirmation written there is not true, since actually it depends on
the band. For instance, for DCS1800 the maximum MS power is provided by
class 3. Let ms_pwr_ctl_lvl() take care of campling instead.

Change-Id: I744e7c315b818a1e7d3dd2579cd483c693d89b73
2019-11-14 16:36:00 +01:00
Pau Espin Pedrol
e717aec2f7 Move and rename gsm_lchan.ms_power field
Make it clear that it contains the maximum MS power level (TS 05.05) and
not the one to be used. The one aimed at is in ms_power_ctrl.current.
Since it's used in related code, move it inside the ms_power_ctrl struct
too.

Related: OS#1851
Change-Id: Ib264ec7dac87355cef6415461ed74bd8e9c8ca52
2019-11-14 16:36:00 +01:00
Pau Espin Pedrol
869091011c rsl: Remove unneeded duplicate reset on some lchan fields
Both ms_power and ms_power_ctrl are reset to 0 again further below.

Change-Id: Ia2a5da068d440232361d57bd5ac33eddebf05ebe
2019-11-14 16:36:00 +01:00
Pau Espin Pedrol
18bfa91a26 Change gsm_lchan field fixed to bool
Change-Id: I715ef151b67a21e325c574585a257e71b4b0ce2a
2019-11-14 16:36:00 +01:00
Pau Espin Pedrol
e5e1226301 Change gsm_bts_trx field to bool and rename it
Thies field is used to store and retrieve whether MS power needs to be
calculated and updated by osmo-bts software or autonomously by lower
layers. Previous name was not clear
and may have been understood as indicating whether MS Power Control loop
is done or not in general, and the responsible for that is located under
lchan's ms_power_ctrl.fixed.

Related: OS#1851
Change-Id: Ic690ab69866a7377f1597e24aa7b0214831c1cbe
2019-11-14 16:36:00 +01:00
Pau Espin Pedrol
d8d459c7e2 cosmetic: Fix trailing whitespace
Change-Id: I7b9a091226e3c7dd60b3921ab0d53688f42d1a4d
2019-11-14 16:36:00 +01:00
Pau Espin Pedrol
d93669289b rsl: Fix logged value in rx MS Power Control
The interesting value in this case is the incoming new ms max power.

Change-Id: Ib6fcb21b1b4bdbc8b749a1b8543d97331699ef3b
2019-11-12 17:46:38 +01:00
Pau Espin Pedrol
80f2bc4855 bts-trx: Implement MS Power control loop calculations using dBm instead of ctl levels
Some bands, such as DCS1800, contain power levels such as 29, 30 and 31 not following same
unified sequence other power levels follow regarding conversion to dBm
values.
This makes extremly complex and prone to error comparing different power
levels. Let's instead use dBm values to calculate and crop desired new
value, and then convert it back to TS 05.05 ms power control level
value.

With this commit the control loop should be able to manage correctly the MS power
levels explained above.

Related: OS#4244
Change-Id: I0160637c5ffa606ee3081ad30be8e6f2a42b725b
2019-11-12 14:19:08 +01:00
Pau Espin Pedrol
000b13ef52 rsl: Assign recv pwr to lchan's max ms power
Otherwise older ms_power value will be kept and used as a maximum.

From TS 08.58 sec 4.8 "MS power control":
"""
If power control is supported by BTS and it is to be used,
this is indicated by optional parameters in the MS POWER CONTROL
message (or the CHANNEL ACTIVATION message). Based on the
measurements performed on the uplink, TRX then attempts to keep
the power control parameters within the limits set by the
MS POWER CONTROL message (or by the CHANNEL ACTIVATION message).
"""

Change-Id: I0583eef477c33279ee5bfcda80141f365413a276
2019-11-12 14:17:24 +01:00
Philipp Maier
a9d88af594 scheduler_trx: initalize n_errors, n_bursts_bits, n_bits_total
Make sure the variables n_errors, n_bursts_bits, n_bits_total are always
initalized. For example in rx_tchh_fn() the value for n_errors is
defined in a switch statement, where the default lets n_errors
uninitalized, which is in that particular case a theoretical problem,
however, lets make sure that the variables n_errors, n_bursts_bits and
n_bits_total are always initalized with 0

Related: CID#205452
Related: CID#205451
Change-Id: If28ea11cc111c7d73ca47b25e65ce399e5baa4c1
2019-10-31 13:08:57 +01:00
Philipp Maier
132987daf4 scheduler_trx: use gsm0502_fn_remap() to calculate frame number
When sched_compose_tch_ind, sched_compose_ph_data_ind or l1if_process_meas_res
is called from rx_tchf_fn or rx_tchh_fn the frame number of the beginning of
the block is required. At the moment this frame number is calculated
wrongly using strange formulas. Lets use gsm0502_fn_remap() to calculate
the beginning of the block properly

Change-Id: I37601ddd85e4287dd9e41ad4a8cb7d314de1a83d
Depends: libosmocore I3d71c66f8c401f5afbad9b1c86c24580dab9e0ce
Related: OS#3803
2019-10-29 10:16:56 +00:00
Pau Espin Pedrol
3533c3f6ad cosmetic: l1sap.c: Fix typo
Change-Id: I9fee7be915546cfd11810c74d511beb8ec10d044
2019-10-28 18:28:33 +00:00
Pau Espin Pedrol
725b3158e2 power_control.c: Take into account RSL CHAN ACT ms power level limits
This is similar commit to Ifda92155bd9c277ac150a327a7ab63c854087788,
which previously fixed same issue for osmo-bts-trx specific power
control loop code.

TS 48.058 sec 4.8 MS power control:
"""
TRX then attempts to keep the power control parameters within the limits
set by the MS POWER CONTROL message (or by the CHANNEL ACTIVATION message)
by changing the MS Power Level field of the L1 header sent to MS in each
SACCH block.
"""

Should fix TTCN3 BTS_Tests.TC_rsl_ms_pwr_dyn_max for non-bts-trx BTS
models.

Related: OS#1622
Change-Id: I376b52d7bee44132993a69cf532bd418171d0ca2
2019-10-28 16:59:42 +01:00
Pau Espin Pedrol
5a60287e44 loops.h: Fix missing include for struct l1sched_trx
Change-Id: I67b63367e46bd43807f61e8f7e63924b8c2427e4
2019-10-28 11:05:47 +01:00
Pau Espin Pedrol
1e9d4feba5 bts-trx: loops.c: Take into account RSL CHAN ACT ms power level limits
TS 48.058 sec 4.8 MS power control:
"""
TRX then attempts to keep the power control parameters within the limits
set by the MS POWER CONTROL message (or by the CHANNEL ACTIVATION message)
by changing the MS Power Level field of the L1 header sent to MS in each
SACCH block.
"""

Fixes TTCN3 BTS_Tests.TC_rsl_ms_pwr_dyn_max

Change-Id: Ifda92155bd9c277ac150a327a7ab63c854087788
2019-10-28 11:05:29 +01:00
Pau Espin Pedrol
a456f2bd15 cosmetic: bts-trx: document variable power level
Change-Id: Ia4bc291c8213dd6cfe3b13a99b3108532b6907b1
2019-10-28 10:51:49 +01:00
Vadim Yanitskiy
be1651bb51 osmo-bts-trx/scheduler: fix: print the last frame number in rx_data_fn()
All other Uplink burst handlers print frame number of the last
(currently received) burst. Let's make rx_data_fn() consistent.

Change-Id: Ie5762a132326be3ef4e4e38cc126f05d51098a20
2019-10-21 11:21:55 +00:00
Oliver Smith
e4abc63e42 vty.c: avoid coverity BAD_SHIFT issues
Make it obvious for compilers and for coverity, that the sapi value used
to shift a bit for the sapi_mask is always <= 31. The sapi value is an
index of the value string l1sap_common_sapi_names, which has 24 entries.

Fixes: CID#205067, CID#205068
Change-Id: Id8be0ab67479b1f76a4f624bd3a5242e4fe59f4b
2019-10-21 11:09:08 +02:00
Oliver Smith
583f2b86c9 vty.c: don't ignore get_string_value() errors
Change uint8_t sapi to int, so we can properly assert on errors from
get_string_value().

Fixes: CID#205066, CID#205069
Change-Id: I4d30afacfab93051868ae8f462cee9ad3dbc7fd0
2019-10-21 11:08:50 +02:00
Martin Hauke
fc5f20a713 Rename variable: CALIB_SUCESS -> CALIB_SUCCESS
Correct the name of this variable.

Change-Id: I75cb6404d772b79933d1d9d694abf8eff1fad020
2019-10-17 08:05:35 +00:00
Martin Hauke
b378fccef1 Fix common misspellings and typos
Change-Id: I403b9029f57fec3fdec2c1e2cbeac0f6eab53f24
2019-10-17 08:05:35 +00:00
Oliver Smith
b58fb35754 vty: add "logging filter l1-sapi"
Add VTY commands to filter by L1 SAPI. Allow to filter by multiple SAPIs
by running the filter command multiple times:

OsmoBTS> logging filter l1-sapi agch
OsmoBTS> logging filter l1-sapi pch

Related: OS#2356
Change-Id: I32d86d3d34757135b4cce59919c2fc2b67f0a889
2019-10-17 08:04:27 +00:00
Pau Espin Pedrol
8ff35d3c91 bts-trx: Time out if no clock ind recvd after RSP POWERON
Before this patch, if due to whatever reason the TRX started fine (RSP
POWERON 0) and sockets were created but no CLOCK IND was ever received
by the BTS, it wouldn't notice since the timerfd timeouts
(bts_shutdown("no clock")) are only checked after the first CLOCK IND is
sent by the TRX.
As a result, the BTS would be kept on forever saying everything is fine
but it would be sending no DL burst at all to the TRX (tested with a
modfied osmo-trx dropping clock indication).
With this patch, new APIs are added to indicate the scheduler_trx code
the timeframes where clock ind are expected (between RSP POWERON 0 and
RSP POWEROFF 0); if TRX sends clock indications out of that timeframe,
BTs lower layers will drop them (controlled by "powered" bool).
Hence, the scheduler_trx can now place a timeout (reusing same timerfd
because its new use is exclusive in time with its other previous use)
when it is told that CLOCK IND should start appearing, and if none
arrives in considerable time, then the BTS can be shut down to notify
the rest of the network.

Related: OS#4215
Change-Id: Iba5dbe867aff10e70ec73dbf1f7aeeecb15c0a4d
2019-10-16 11:13:21 +00:00
Oliver Smith
5fee4d1ff5 log: set L1 SAPI log context
Add a new common L1 SAPI enum, to unify all the BTS specific SAPIs.
Translate to this enum, and set the context for uplink messages in
each BTS specific implementation.

Set the context for downlink messages in the common l1sap code, by
converting the osmo_phsap_prim back to the SAPI value (mostly looking at
chan_nr). The new functions for doing this conversion,
get_common_sapi_by_trx_prim() and get_common_sapi_ph_data(), are based
on the existing to_gsmtap() and gsmtap_ph_data() functions.

Note that we can't set the uplink SAPI context in the common code,
because then we can't set it as early as possible. In this patch, the
SAPI context is set for the PHYs where the SAPI is readily available.
With additional conversion from the RSL channel, the SAPI context could
be set for osmo-bts-trx in a follow up patch.

Related: OS#2356
Depends: (libosmocore) I814cb3328d99faca9220adb5a80ffb934f219d7d
Change-Id: I6b7bb2e1d61502b61214f854a4ec5cbb7267545b
2019-10-11 10:46:02 +00:00
Vadim Yanitskiy
a4c54b531c README.md: update osmo-bts-trx specific limitations
The ticket has been closed, BER and C/I measurements are now being
sent to OsmoPCU (see Ia58043bd2381a4d34d604522e02899ae64ee0d26).

Change-Id: I1909a70b82421802f32c1bc4f69a2e4210db5b2d
2019-10-10 01:50:00 +07:00
Vadim Yanitskiy
df51be6329 L1SAP: there can be no DATA.ind primitives on PTCCH/U, reject them
Change-Id: Ib846a9b8e619c7da56b5f0a54d16f629913af80d
2019-10-09 16:45:48 +00:00
Vadim Yanitskiy
d73832bc35 L1SAP: use GSMTAP_CHANNEL_PDTCH for PDTCH blocks by default
We don't know whether a data block on PDCH belongs to PDTCH or PACCH
without parsing it, because the latter one is being allocated on
demand. Let's use GSMTAP_CHANNEL_PDTCH by default, rather than
GSMTAP_CHANNEL_PACCH.

Change-Id: I7639215ef936a8ac05ca417a91f4e12755f318d4
2019-10-09 16:45:48 +00:00
Vadim Yanitskiy
2cbdeba5cf L1SAP: fix gsmtap_pdch(): there can be no DATA.ind on PTCCH/U
Change-Id: Id69010ffa8c697e8c01bbb21509253c330f95343
2019-10-09 16:45:48 +00:00
Vadim Yanitskiy
43a8ed2b55 L1SAP: use the actual ARFCN for outgoing PCUIF messages
Change-Id: I07b3aac97603d85fb6cf077d3a342b12b0643171
2019-10-09 16:45:48 +00:00
Pau Espin Pedrol
d8284eec63 bts-trx: Log TRXC and TRXD socket recv()/send() failures
Related: OS#4215
Change-Id: Ic3e41d82b43459495d45873d612a3bd349ac174a
2019-10-09 11:57:37 +00:00
Vadim Yanitskiy
eb43c947c1 L1SAP: properly handle 11-bit encoded RACH.ind in gsmtap_ph_rach()
Change-Id: Id263c2b716fd282d37d705a1c5f430ce7c0edaf0
2019-10-09 03:18:30 +07:00
Vadim Yanitskiy
29e47ffc20 L1SAP: refactor handling of Access Bursts on PDCH
First of all, we also need to apply the same filtering to Access
Bursts on PDCH as for the normal ones on RACH, i.e. filter them
by ToA (Timing of Arrival) and BER (Bit Error Rate).

Secondly, we shall not interpret Access Bursts on PDTCH/U as
handover related ones. Instead, let's print a warning and
ignore them since they are not (yet) supported by OsmoBTS.

Finally, in gsmtap_pdch() we need to set a proper channel type
for Access Bursts received on PDCH (PDTCH/U or PTCCH/U).

Change-Id: I461fde9f4543c45c42b591cd3fd0ff3d98673cec
2019-10-09 03:13:31 +07:00
Vadim Yanitskiy
d7103f9172 L1SAP: do not pass unused parameter to l1sap_handover_rach()
Change-Id: I7f2d909f1bde09cbec106240df290381b3418e46
2019-10-09 03:01:58 +07:00
Vadim Yanitskiy
91fc2b9e30 L1SAP: clarify debug messages in rach_pass_filter()
RACH stands for Random Access CHannel, while in rach_pass_filter()
we're dealing with Access Bursts, that may be received on other
logical channels too (e.g. PTCCH, PDTCH or any other).

Change-Id: I1e5ca9930ab491a6916c972865154d54530cbf51
2019-10-09 03:01:43 +07:00
Vadim Yanitskiy
e83c1196b8 L1SAP: also consider RSL_CHAN_OSMO_CBCH8 as CBCH
Currently we don't distinguish between CBCH on BCCH+SDCCH/4 and
CBCH on SDCCH/8, but in libosmogsm we have two independent
(non-standard) RSL channel number values for them. Maybe some day
we will, so let's extend the definition of L1SAP_IS_CHAN_CBCH.

Change-Id: I2f6d501a29edaf89dfb17d5d64f930cdb1943630
2019-10-09 03:01:35 +07:00
Vadim Yanitskiy
1c6a56fb97 L1SAP: use RSL_CHAN_* definitions from libosmogsm
Change-Id: I2708b5d5bb6b92f90766ac752bafd28cff2549b0
2019-10-09 03:01:19 +07:00
Oliver Smith
dc4d36d7bb gitignore: add oc2g generated files
Change-Id: I3e7af6d290988099535bab63bbc53a901d16b55f
2019-10-07 09:33:17 +00:00
Pau Espin Pedrol
b6be055e6b bts-trx: Drop unused func check_transceiver_availability()
After getting rid of transceiver_available, this function is not used
anymore by any code, since its per-trx counterpart
l1if_provision_transceiver_trx() is the one used by other
code.

Change-Id: If5a988eb14658a78dd46234dccc052dc12fb872a
2019-10-05 20:50:13 +00:00
Pau Espin Pedrol
ca574b19d3 bts-trx: Get rid of messy transceiver_available state handler
This variable meaning has been changing its exact meaning over time
until finally not being really clear which kind of state it holds.
Initially it seemed to be used to identfy whether CLOCK IND were being
received. However, over time both osmo-bts and osmo-trx have evolved and
were fixed so that clock indications are only sent by osmo-trx after
POWERON command is sent. As a result, this state can be checked simply by
looking at the "powered" phy_link variable, which is only set to true
once the TRX has confirmed the POWERON command, and hence it is sending
CLOCK IND.
On the other hand, at some point in time "available" started to be set to 1
in bts_model_phy_link_open(), which means available is nowadays almost
always 1 from startup until the end (only dropped during bts_shutdown(),
when we are already exiting the process anyway).
As a result, !available condition in scheduler_trx.c:trx_fn_timer_cb can
almost never happen, because available is set to true already. Only
possibility would be if an old process of osmo-trx (not set up by this
BTS process) is still sending CLOCK INDs, but in that case we for sure
don't want to configure the BTS based on that, but ignore them until
this BTS process has again configured the TRX. So that whole check can
be dropped. We are better checking for "powered" state, which is far
more accurate, and we better do that in trx_if.c before calling
trx_fn_timer_cb().

Other uses of "transceiver_available" being used can be changed to use
plink->state!= PHY_LINK_SHUTDOWN, since available was already being set
to 1 at the same time the plink->state was being set to
PHY_LINK_CONNECTING.

As a result of this state handling re-arrangement, OS#4215 is fixed
since trx_if_powered() is used instead of previous state condition to
check whether data frames should be sent.

Related: OS#4215
Change-Id: I35f4697bd33dbe8a4c76c9500b82c16589c701d4
2019-10-05 20:50:13 +00:00
Pau Espin Pedrol
9e1f0e1a13 bts-trx: Don't reset transceiver_available in scheduler_trx.c
It can be dropped since bts_shutdown() ends up calling immediatelly
bts_model_trx_close() which in turn calls bts_model_trx_close() which
sets enabled = false and calls l1if_provision_transceiver_trx() to
power off the TRX.

Related: OS#4215
Change-Id: If8b3d2379d7ae102e1c338f4558ac1352de761cc
2019-10-05 20:50:13 +00:00
Pau Espin Pedrol
96cb0c54a9 bts-trx: Rework code handling poweron state
Use of variables in each code is confusing and mixing configuration with
POWERON/POWEROFF state (which is at least per phy inst and not per TRX,
since those commands are only expected on the 1st phy inst).

* field "poweron" becomes "enabled", and is used as an indicator for
actions to take during TRX provisioning (hether to power it on and
configure it or to power it off).
* poweron/poweroff state becomes "powered", and it is shared by all trx
in same phy_link, and is updated only after confirmation by TRX.
* poweron_set becomes poweronoff_set (because it's used by both POWERON
and POWEROFF), and becomes shared by all trx in same phy_link, since
those CMDs are usually sent by first phy instance of the link (the first
trx).

Related: OS#4215
Change-Id: Icd0b482f1454236432e1952220bbec9d178b8607
2019-10-05 20:50:13 +00:00
Pau Espin Pedrol
4b72ee924c bts-trx: trx_set_bts(): Avoid double loop by checking current trx
check_transceiver_availability() is a loop over every trx, same to what
trx_set_bts() does, so let's call the per-trx version directly.

Change-Id: I8843c1438c6af700631aba7b7e72aae0bdb7ec3a
2019-10-05 20:50:13 +00:00
Pau Espin Pedrol
520954cd93 bts-trx: vty: Print phy link state in cmd 'show transceiver'
Change-Id: I8e49f8edad9f9c68d110dbb7faeea5143aa91022
2019-10-05 20:50:13 +00:00
Pau Espin Pedrol
accbf5bc73 bts-trx: Allocate struct osmo_trx_clock_state as part of bts-trx private data
Related: OS#4215
Change-Id: I9b7ffb51423ada74b8be347c57eade08f307f88f
2019-10-05 20:50:13 +00:00
Pau Espin Pedrol
972c243146 struct gsm_bts: Add model_priv pointer handing bts_model specific data
Currently there's bts-virtual specific fields in gsm_bts which is not used
by other models and are always allocated.
An alternative would be having a union with different structs inside,
one per model, but since we already have the bts_model abstraction, in this
case it makes more sense to use that abstraction instead of filling code
with preprocessor ifdefs to guard against non-defined types, etc.

Existing model specific data is moved there.

This new infra will be user further in forthcoming commits.

Related: OS#4215
Change-Id: Ib17a752cdbaa7d5eb8c5dfa0b197f80a4f38b38e
2019-10-05 20:50:13 +00:00
Vadim Yanitskiy
41c7b05283 common/l1sap: increase ToA precision for packet Access Bursts
QTA is a Timing Advance value in units of 1/4 of a symbol. Let's
use ToA256 (1/256 of a symbol) field of L1SAP RACH.ind as a base
for QTA calculation in order to achieve better precision.

Change-Id: I6e6fa7985c430a9bdbd12af2a8b2a5a66f11a41c
2019-10-04 15:53:53 +00:00
Vadim Yanitskiy
0772cd0460 osmo-bts-trx/scheduler: also detect TSC for Access Bursts on PDCH
If a logical channel, on which an Access Burst has been received,
is not either of RACH, PDTCH or PTCCH, then this is a handover
Access Burst, which is always encoded as 8-bit and shall contain
the generic training sequence (TS0).

Access Bursts on a PDCH time-slot are not related to handover.

Change-Id: If7d6135d6c4d7f9bd71d9fab6f8adc3f8cfd10ea
2019-10-04 15:53:53 +00:00
Vadim Yanitskiy
df5b813c0f scheduler: fix handling of PTCCH/U and PTCCH/D logical channels
According to 3GPP TS 45.010, section 5.6.2, for packet-switched
channels the BTS shall monitor the delay of the Access Bursts
sent by the MS on PTCCH and respond with timing advance values
for all MS performing the procedure on that PDCH.

According to 3GPP TS 45.002, section 3.3.4.2, PTCCH (Packet Timing
advance control channel) is a packet dedicated channel, that is
used for continuous Timing Advance control (mentioned above).

There are two sub-types of that logical channel:

  - PTCCH/U (Uplink): used to transmit random Access Bursts
    to allow estimation of the Timing Advance for one MS in
    packet transfer mode.

  - PTCCH/D (Downlink): used by the network to transmit
    Timing Advance updates for several MS.

As per 3GPP TS 45.003, section 5.2, the coding scheme used for
PTCCH/U is the same as for PRACH as specified in subclause 5.3,
while the coding scheme used for PTCCH/D is the same as for
CS-1 as specified in subclause 5.1.1.

The way we used to handle both PTCCH/U and PTCCH/D is absolutely
wrong - they have nothing to do with xCCH coding. Instead, we
need to use tx_pdtch_fn() for Downlink and rx_rach_fn() for Uplink.

In l1sap_ph_rach_ind() we need to check if an Access Burst was
received on PTCCH/U and forward it to OsmoPCU with proper SAPI
value (PCU_IF_SAPI_PTCCH). To be able to specify a SAPI, a new
parameter is introduced to pcu_tx_rach_ind().

Change-Id: I232e5f514fbad2c51daaa59ff516004aba97c8a3
Related: OS#4102
2019-10-04 15:53:53 +00:00
Pau Espin Pedrol
76837bddb7 l1sap: Log conn dropped due to radio link counter timeout
Change-Id: I78c5ff00be8d2c870ed0277294a8e499ba8a8d95
2019-10-02 19:03:41 +02:00
Pau Espin Pedrol
16da58d0c0 scheduler: Use OSMO_ASSERT instead of abort
Change-Id: I594842b08cdb97a473273ba7097a05502f5751b8
2019-10-02 19:01:07 +02:00
Pau Espin Pedrol
ccf9498865 scheduler.c: Move some message log level to DEBUG
Otherwise using "logging level set-all info" makes it impossible to see
anything in VTY due to tons of those two lines appearing.

Change-Id: I9c7500c1e56db0c4dcb474f93c882a9c7c004d55
2019-10-02 17:52:24 +02:00
Pau Espin Pedrol
35d4291a5e bts.h: Remove non-existent function definitions
Change-Id: I4d06e1cdea5970cbb493f29980b1c04e01c0e8a4
2019-09-27 14:57:05 +02:00
Pau Espin Pedrol
c91997b2cc bts-trx: vty: Use API to get poweron state
Change-Id: I8b78e1ad34f19d8fe348b9c975742fc0f7112da2
2019-09-27 13:38:51 +02:00
Pau Espin Pedrol
474eeed78d doc: bts-models.adoc: Fix typos in rts-advance section
Change-Id: I37ba104ec0538f8eb9345ff880660aefbdaa44ca
2019-09-19 10:07:32 +00:00
Pau Espin Pedrol
a1f2b6931b bts-trx: Change super verbose IDLE ind not-supported line to DEBUG
It's impossible to see other logging otherwise.

Change-Id: I64ee83b734ecff593ff2a1cf97b192db93228e22
2019-09-19 10:07:32 +00:00
Vadim Yanitskiy
b86e9260e8 osmo-bts-trx/scheduler: fix: check rc of osmo_ecu_frame_out()
Change-Id: I32d244f5ddef46c8b8719f5ec27b7456514d407a
Fixes: CID#204005 (CID#204007), CID#204006 (CID#204004)
2019-09-12 22:59:31 +02:00
Pau Espin Pedrol
3061e1d14a bts-trx: Log case where no SETFORMAT is sent
If VTY cmd "osmotrx trxd-max-version 0" is used, max version 0 is used
(default starting one) and hence no need to send SETFORMAT (this is
useful in order to avoid sending SETFORMAT to old TRX implementations
not supporting the command). In this case, let's inform the user that
indeed osmo-bts won't send SETFORMAT because version 0 is assumed.

Change-Id: I7136ea6745c2275278bc400676b58fb4b10da966
2019-09-10 14:48:19 +00:00
Harald Welte
ec228cc08c osmo-bts-trx: migrate to new generic ECU abstraction
libosmocodec has recently introduced a generic ECU abstraction layer
which supports (pluggable) Error Concealment Units for not only the
FR codec, but potentially any other codec, too.

Change-Id: I001005aae6de76d4e045b8dc572239f057bb150d
Depends: libosmocore I4d33c9c7c2d4c7462ff38a49c178b65accae1915
2019-09-10 12:26:21 +00:00
Vadim Yanitskiy
e6a72c2b80 osmo-bts-trx/scheduler: add FIXME note about FACCH/H and BFI
Change-Id: Ie006cd46cb574d272fbe3b38595a3087617c79d1
2019-09-07 23:09:09 +00:00
Vadim Yanitskiy
454b034521 osmo-bts-trx/scheduler: fix tx_tch_common(): do not send AMR BFI twice
We call _sched_compose_tch_ind() after the switch statement, so
there is no need to send it from case 'GSM48_CMODE_SPEECH_AMR'.

Change-Id: I0488082494120157ac438d7763b52e3998f0eac7
2019-09-07 23:05:22 +00:00
Harald Welte
9d5acaad5c osmo-bts-trx/scheduler: prevent uninitialized memory access
When sending an AMR BFI, we need to call osmo_amr_rtp_enc() with
AMR_BAD as the last parameter. This function returns the length
of encoded payload, which needs to be at least 2 octets long.

If osmo_amr_rtp_enc() returns a length value lower than 2 octets
(what should not happen in general), we should neither call
memset() on it, nor call _sched_compose_tch_ind().

Change-Id: I70ce98c5697b9ce6fac7ab57a5d70f3201db29d9
Fixes: CID#178648, CID#178637, CID#178651
2019-09-07 23:05:22 +00:00
Vadim Yanitskiy
af2a8a6c81 common/rsl.c: fix possible NULL-pointer dereference
Change-Id: I11a35a8f500fafa7b3c93d2f2244cc4d42f09f1b
Fixes: CID#203810
2019-09-07 23:05:22 +00:00
Harald Welte
faf861b881 doc: Update Abis manual RSL section with ETWS related infomration
Change-Id: I969153a204c167783ba394c9a911ff4484ded759
2019-09-07 11:31:23 +02:00
Harald Welte
2588b2abf6 pcu_interface: Forward ETWS Primary Notification to PCU
All MS/UE must be notified of ETWS Primary Notifiations.

Depending on their state, the notification goes different paths:
* CS dedicated mode: BSC sends it as L3 message over LAPDm / DCCH
* CS/PS idle mode: BTS sends paging messages on PCH
* PS TBF active: PCU send Packet Application Info

This enables the last of the three methods by passing any
ETWS Primary Notifications received over RSL via the PCU socket into
the PCU.

Change-Id: Ic0b3f38b400a0ca7e4089061ceb6548b0695faa6
Related: OS#4047, OS#4048
2019-09-06 11:57:37 +02:00
Harald Welte
f53fde91a3 ETWS Primary Notification via P1 Rest Octets
The ETWS (Earthquake and Tsunami Warning System) uses a so-called
ETWS Primary Notification which is sent
* to phones in dedicated mode (via DCCH from the BSC)
* to phones in idle mode (via P1 Rest Octets on PCH/CCCH)

This patch implements the second part of the functionality, i.e.
transmitting the related ETWS Primary Notification via PCH.  As
3GPP doesn't specify how this is communicated over Abis, we use
a new, vendor-specific RSL message type.

Closes: OS#4047
Depends: libosmocore I89c24a81ada6627694a9632e87485a61cbd3e680
Depends: libosmocore I36fc2ffc22728887d1cb8768c7fcd9739a8ec0fc

Change-Id: I18c60cdb86b9c19e09f5ec06d66e9b91608880e6
2019-09-05 14:30:17 +02:00
Oliver Smith
cb57028d52 pcu_sock: fix endian-swapped CellID
Convert the cell identity to LE when sending it to the PCU via unix
socket, just like we do it with the location area code.

In the Osmocom stack, the CellID is configured in OsmoBSC, sent as BE
via RSL to OsmoBTS, then with a socket to OsmoPCU (where OsmoPCU expects
it to be LE in a LE system). OsmoBTS was always sending the CellID as
BE to OsmoPCU. In March 2018, a regression in OsmoPCU [1] caused an
endianness swap in the CellID on LE systems, resulting by chance in the
correct, LE encoded, CellID as it should have been sent from OsmoBSC
(for LE systems). This regression was fixed in March 2019 [2].

I've verified this fix with a TTCN3 test [3].

[1] I787fed84a7b613158a5618dd5cffafe4e4927234 (osmo-pcu)
[2] I2f6cc930c5dbf8dac386b24b0756df2efe8199e4 (osmo-pcu)
[3] I6516808f4b9e9a2301f9ccc1e55ded14e7334c33 (osmo-ttcn3-hacks)

Related: OS#3854
Change-Id: I68faf4558f0686fb2a3db24077dceaae05bf0262
2019-08-29 15:44:37 +02:00
Oliver Smith
fc917d91bf virtual: set link quality for GSMTAP_CHANNEL_RACH
Don't ignore all incoming RACH requests anymore:
000881/00/23/14/09 Ignoring RACH request: link quality (0) below the minimum (50)

Related: OS#3925
Fixes: b777c0f3ec ("Move Access Burst link quality handling to L1SAP")
Change-Id: Ifcd576fed84346688e711a26a05c6d350588e83d
2019-08-23 12:34:48 +02:00
Oliver Smith
258856b329 Cosmetic: virtual: l1sap.c: fix typos
Change-Id: Id24e75812bda17e99f17a37b367462533a5607f9
2019-08-23 11:58:19 +02:00
Pau Espin Pedrol
ca8aa07127 Bump version: 1.0.1 → 1.1.0
Change-Id: I708f6a63b51459d77368c48e115f64aaa6646bfd
2019-08-07 15:59:03 +02:00
Pau Espin Pedrol
f9e67f44d4 configure.ac: Require libosmocore 1.2.0
Some commits started using libosmocore APIs
osmo_gsm48_rest_octets_si3_encode() and lapdm_channel_init2(), which are
only available in latest libosmocore release 1.2.0. Let's update
configure.ac accordingly.

Fixes: 1e96e31c10
Fixes: 46d62b984a
Change-Id: If84c53d8192e8db98eb9439b898d83e94c5e5476
2019-08-07 15:51:29 +02:00
Pau Espin Pedrol
b4d8f5cf13 Remove undefined param passed to {logging,osmo_stats}_vty_add_cmds
Since March 15th 2017, libosmocore API logging_vty_add_cmds() had its
parameter removed (c65c5b4ea075ef6cef11fff9442ae0b15c1d6af7). However,
definition in C file doesn't contain "(void)", which means number of
parameters is undefined and thus compiler doesn't complain. Let's remove
parameters from all callers before enforcing "(void)" on it.
API osmo_stats_vty_add_cmds never had a param list but has seem problem
(no "void"), so some users decided to pass a parameter to it.

Change-Id: Ia4d1a7914308d1481fe31fe0986265ead339e61e
Related: OS#4138
2019-08-05 16:13:09 +02:00
Harald Welte
cb0cb897ad scheduler_trx: Handle negative return of gsm0503_tch_hr_decode()
If gsm0503_tch_hr_decode() returns a negative error, we shouldn't
set the marker bit or pass the negative value as length value into
osmo_hr_check_sid().

Change-Id: If49ca6926c576a2b17507b6a95b6f3ca17877d66
Closes: CID#187645
2019-08-02 07:30:58 +00:00
Harald Welte
e8e864b219 osmo-bts-trx: Don't attemtp to adjust MS power if fixed
If the BSC has instructed the BTS via RSL to not autonomously perform
MS power control, we are storing this in lchan->ms_power_ctrl.fixed.

However, osmo-bts-trx would simply ignore that flag in loops.c and
continue to compute new MS power values based on measurement results.

Change-Id: I628d1f4f1094c22248d372c11c2ecc504135b757
2019-07-31 12:10:39 +02:00
Harald Welte
89f06e6c54 osmo-bts-trx: Don't increment rssi_valid_count twice
In the ms_power_val() function, don't increment the number of
valid RSSI values counter twice.

Change-Id: I19d9d933a69f7ad6252cbe51751d5db41790c698
2019-07-31 12:10:12 +02:00
Pau Espin Pedrol
160b624da8 trx: Use LOGPPHI instead of LOGP in some more messages
This allows to clearly identify the phy instance owning those messages.

Change-Id: I90990e4dbcbb2fb4a3fcb24658bdf53e57030bcf
2019-07-24 19:28:56 +00:00
Daniel Willmann
291468694b manuals: Update vty documentation
This documentation only includes commands for osmo-bts-virtual

Change-Id: Icc0c96d173f31f2eb5fcb6385525a17f94ead852
Related: OS#1700
2019-07-24 19:27:43 +00:00
Pau Espin Pedrol
e6372cff1b bts-trx: Introduce VTY command osmotrx trxd-max-version
This command allows setting a maximum TRXD format version to negotiate
with TRX. osmo-bts-trx will hence end up using that version if supported
by TRX, or a lower one otherwise (or fail if TRX doesn't support any of
them).
Since now the maximum version can be 0, avoid going through SETFORMAT
negotiation in that case, since 0 is the default version. This way we
keep backward compatibility with TRX implementations that exit upon
receival of unknown commands (such as SC5 current one).

The VTY command is located in the "phy" node instead of the "phy
instance" node because instances of same phy are expected to use same
host with same implementation, so TRXD version to use should be the same
for both.

Related: OS#4006
Change-Id: I5eb1fdc002f9d7f4acf475356d8fc998dc8f6326
2019-07-23 17:21:40 +02:00
Vadim Yanitskiy
aa54224e56 osmo-bts-trx/scheduler: rx_data_fn(): provide actual C/I ratio to L1SAP
Change-Id: Iea0dad65e9bc511f99375fd3ee2eb44e47a6168f
2019-07-21 21:55:51 +07:00
Vadim Yanitskiy
4ff47ff39a osmo-bts-trx/scheduler: rx_rach_fn(): provide actual C/I ratio to L1SAP
Change-Id: I8d86dec7ebc039cbfd038c4342ff328b11281865
2019-07-21 21:55:51 +07:00
Vadim Yanitskiy
b777c0f3ec Move Access Burst link quality handling to L1SAP
Change-Id: I893ec9c6c2ebad71ea68b2dc5f9f5094dfc43b78
Depends: (libosmocore) Ie2a66ebd040b61d6daf49e04bf8a84d3d64764ee
2019-07-21 21:55:51 +07:00
Vadim Yanitskiy
9649a42d5a Clarify and refactor link quality (C/I) handling
The radio link quality is defined by C/I (Carrier-to-Interference
ratio), which is computed from the training sequence of each
received burst, by comparing the "ideal" training sequence with
the actual (received) one.

Link quality measurements are used by L1SAP to filter out "ghost"
Access Bursts, and by the link quality adaptation algorithms. One
can define minimum link quality values using the VTY interface.

On the VTY interface we expect integer C/I values in centiBels
(cB, 10e-2 B), while the internal structures are using float
values in deciBels (dB, 10e-1 B). Some PHYs (sysmo, octphy,
oc2g, and litecell15) expose C/I measurements in deciBels,
while on the L1SAP interface we finally send then in centiBels.

Let's avoid this confusion and stick to a single format, that
will be used by the internal logic of OsmoBTS - integer values
(int16_t) in centiBels. This will give us the range of:

  -32768  .. 32767  centiBels, or
  -3276.8 .. 3276.7 deciBels,

which is certainly sufficient.

Change-Id: If624d6fdc0270e6813af8700d95f1345903c8a01
2019-07-21 13:51:57 +00:00
Harald Welte
db6c786350 sysmo/l1_if.c: Annotate fall-through in switch statement
Change-Id: I72937e087288fe7681fafe4099e49849657924bd
Closes: CID#162019
2019-07-21 10:30:32 +00:00
Daniel Willmann
37ea11e072 manuals: Add counter documentation
Change-Id: I994ad6aae7f409e0f15ff1d388127e16243b378a
Related: OS#1700
2019-07-18 19:54:33 +02:00
Vadim Yanitskiy
33ed0f8876 common/rsl.c: fix: properly handle SI3 Rest Octets
It was noticed with old Sony Ericsson phones (like W595 and K510i)
that the service provided by Osmocom network becomes unreliable
from time to time. The RSSI indicator on those phones shows that
the signal is lost, so neither CS nor PS services are working.

As it then turned out, System Information 3 broadcasted on the
Um interface is different than the one received from the BSC.
In particular, the content of SI3 Rest Octets IE is different.

Among with the 'GPRS Indicator', which is actually expected to
indicate whether the PCU is connected or not, SI3 Rest Octets
on the Um interface contain both 'Optional Power Offset' and
'Scheduling if and where' IEs, which are not present in the
original messages from the BSC.

Moreover, as soon as the PCU is connected, 'GPRS Indicator' IE
contains different 'GPRS RA Colour' value, and informs the MS
that System Information 13 is sent on extended BCCH, which
is not even supported by OsmoBTS!

The culprit is in rsl_rx_bcch_info(), where we pass a pointer
to osmo_gsm48_rest_octets_si3_decode(). Instead of passing a
pointer to the beginning of SI3 buffer, we actually need to
shift it to the beginning of the SI3 Rest Octets IE.

This change makes my Sony Ericsson phones happy ;)

Change-Id: Ia962cf21903ba674057cf52746996dd3254bc1c6
2019-07-18 08:17:36 +00:00
Thorsten Alteholz
2131a7931e fix spelling stuff mentioned by lintian
Change-Id: I3d6cb6fc1b182d8520ba60e431ab9b74e71d5e3c
2019-07-17 10:58:57 +00:00
Vadim Yanitskiy
af6f39025f osmo-bts-trx/scheduler: rx_rach_fn(): enrich debug message
Change-Id: I1cb28a9d6c98993705b73937409276994f375dc0
2019-07-16 04:16:13 +00:00
Vadim Yanitskiy
1ea7fd0609 osmo-bts-trx/scheduler: rx_rach_fn(): clarify handover RACH handling
Change-Id: I3da39d48052af1759297f4ad75c220b3046c0691
2019-07-16 04:16:13 +00:00
Vadim Yanitskiy
dc48fd8810 osmo-bts-trx/scheduler: rx_rach_fn(): use optional TSC info from TRX
TSC (Training Sequence Code) is an optional parameter of the UL burst
indication. We need this information in order to decide whether an
Access Burst is 11-bit encoded or not (see OS#1854).

If this information is absent, we try to correlate the received synch.
sequence with the known ones (3GPP TS 05.02, section 5.2.7), and
fall-back to the default TS0 if it fails.

Since the new TRXD header version, the training sequence code is
indicated by the transceiver. Let's use it!

Change-Id: I1e654a2e49cb83c5f1e6249c0de688f99bc466b0
Related: OS#1854, OS#4006
2019-07-16 04:16:13 +00:00
Vadim Yanitskiy
54e104496a osmo-bts/scheduler: provide actual C/I values to OsmoPCU
C/I (Carrier-to-Interference ratio) is a value in cB (centiBels),
computed from the training sequence of each received burst,
by comparing the "ideal" training sequence with the actual one.

So far, there was no way to expose more measurements from OsmoTRX,
excluding both RSSI and ToA. Since the new version of TRXD header,
we can receive C/I indications and send the averaged (per 4 bursts)
values to OsmoPCU (as a part of PCUIF_DATA.ind).

Please note that we also need to attach C/I measurements
to the following L1SAP primitives:

  - PRIM_PH_RACH.ind,
  - PRIM_PH_DATA.ind,
  - PRIM_TCH.ind,

but this will be done in the follow up changes.

Change-Id: Ia58043bd2381a4d34d604522e02899ae64ee0d26
Fixes: OS#1855
2019-07-16 04:16:13 +00:00
Vadim Yanitskiy
01cc8c0d21 osmo-bts-trx/scheduler: pass trx_ul_burst_ind to lchan handlers
This change needs to be done in order avoid adding more and more
arguments to the UL logical channel handlers (such as rx_rach_fn).

Since we have different versions of the TRXD header, and may have
other burst-based PHYs in the future, some fields of an Uplink
burst indication have conditional presence.

Change-Id: Iae6b78bafa4b86d0c681684de47320d641d3f7c0
Related: OS#4006, OS#1855
2019-07-16 04:16:13 +00:00
Vadim Yanitskiy
55dbafc497 osmo-bts-trx/trx_if.c: encode actual TRXD header version
Both TRX2L1 (Uplink) and L12TRX (Downlink) messages should use
the same TRXD header format (and version) as was negotiated.

Change-Id: Idbc598ef7c1871ee8da830f3fbe0a5cc386f873d
Related: OS#4006
2019-07-16 04:16:13 +00:00
Vadim Yanitskiy
139b8caa79 osmo-bts-trx/trx_if.c: add TRXD header version negotiation
This change introduces a new command for TRXD header format
negotiation - SETFORMAT. If the transceiver does not support
the format negotiation, it would reject this command with
'RSP ERR 1'. If the requested version is not supported by
the transceiver, status code of the response message should
indicate a preferred (basically, the latest) version.

The format of SETFORMAT command is the following:

  L1 -> TRX: CMD SETFORMAT VER_REQ
  L1 <- TRX: RSP SETFORMAT VER_RSP VER_REQ

where:

  - VER_REQ is the requested version (suggested by the L1),
  - VER_RSP is either the applied version if matches VER_REQ,
    or a preferred version if VER_REQ is not supported.

If the transceiver indicates VER_RSP different than VER_REQ,
OsmoBTS is supposed to reinitiate the version negotiation
using the suggested VER_RSP. For example:

  L1 -> TRX: CMD SETFORMAT 2
  L1 <- TRX: RSP SETFORMAT 1 2

  L1 -> TRX: CMD SETFORMAT 1
  L1 <- TRX: RSP SETFORMAT 1 1

If no suitable VER_RSP is found, or the VER_REQ is incorrect,
the status code in the response would be -1.

As soon as VER_RSP matches VER_REQ in the response, the process
of negotiation is complete. Changing the header version is
supposed to be done before POWERON.

Change-Id: I8afe950bd1ec2afaf3347ff848ee46e69c4f5011
Related: OS#4006
2019-07-16 04:16:13 +00:00
Eric Wild
e059aa3db7 RSL: Fix fixed MS power control in RSL CHAN ACTIV
Dynamic MS power control should only be active if a power parameters IE
was supplied.

Change-Id: I0bbe171a287b10d71fc853cd721f66e4c84db8c5
2019-07-16 04:05:54 +00:00
Oliver Smith
04e980dd10 contrib/jenkins.sh: run "make maintainer-clean"
Related: OS#3047
Change-Id: I9d9b2412f005e4bda0ed35ba715cfb4dca1b04c1
2019-07-10 13:36:11 +02:00
Vadim Yanitskiy
7d1d294807 osmo-bts-trx/trx_if.c: properly describe TRXD messages in logs
Since we may have different versions of the TRXD header, some new
fields of an Uplink burst indication have conditional presence.
Therefore we need a smart function to print them conditionally.

Change-Id: I68729dc98a1840d2aa9e091153d176a103d5a228
Related: OS#4006
2019-07-04 13:37:33 +07:00
Vadim Yanitskiy
3f2283cd3c osmo-bts-trx/trx_if.c: drop RSSI / ToA debugging code
This kind of debugging can be done using trx_sniff.py tool from
the TRX Toolkit [1]. Probably, this code was needed during the
initial development and testing.

[1] https://git.osmocom.org/osmocom-bb/tree/src/target/trx_toolkit

Change-Id: I50e0e5feeba4c3028f55209dd8e41e09ed5f70b1
2019-07-04 01:37:53 +07:00
Vadim Yanitskiy
a99c41bac5 osmo-bts-trx/trx_if.c: introduce TRXD header version 0x01 support
The new version adds the following fields to the TRX2L1 message,
keeping the L12TRX message unchanged:

  +------+-----+-----+-----+--------------------+
  | RSSI | ToA | MTS | C/I | soft-bits (254..0) |
  +------+-----+-----+-----+--------------------+

  - MTS (1 octet)  - Modulation and Training Sequence info, and
  - C/I (2 octets) - Carrier-to-Interference ratio (big endian).

== Coding of MTS: Modulation and Training Sequence info

3GPP TS 45.002 version 15.1.0 defines several modulation types,
and a few sets of training sequences for each type. The most
common are GMSK and 8-PSK (which is used in EDGE).

  +-----------------+---------------------------------------+
  | 7 6 5 4 3 2 1 0 | bit numbers (value range)             |
  +-----------------+---------------------------------------+
  | . . . . . X X X | Training Sequence Code (0..7)         |
  +-----------------+---------------------------------------+
  | . X X X X . . . | Modulation, TS set number (see below) |
  +-----------------+---------------------------------------+
  | X . . . . . . . | IDLE / nope frame indication (0 or 1) |
  +-----------------+---------------------------------------+

The bit number 7 (MSB) is set to high when either nothing has been
detected, or during IDLE frames, so we can deliver noise levels,
and avoid clock gaps on the L1 side. Other bits are ignored,
and should be set to low (0) in this case.

== Coding of modulation and TS set number

GMSK has 4 sets of training sequences (see tables 5.2.3a-d),
while 8-PSK (see tables 5.2.3f-g) and the others have 2 sets.
Access and Synchronization bursts also have several synch.
sequences.

  +-----------------+---------------------------------------+
  | 7 6 5 4 3 2 1 0 | bit numbers (value range)             |
  +-----------------+---------------------------------------+
  | . 0 0 X X . . . | GMSK, 4 TS sets (0..3)                |
  +-----------------+---------------------------------------+
  | . 0 1 0 X . . . | 8-PSK, 2 TS sets (0..1)               |
  +-----------------+---------------------------------------+
  | . 0 1 1 X . . . | AQPSK, 2 TS sets (0..1)               |
  +-----------------+---------------------------------------+
  | . 1 0 0 X . . . | 16QAM, 2 TS sets (0..1)               |
  +-----------------+---------------------------------------+
  | . 1 0 1 X . . . | 32QAM, 2 TS sets (0..1)               |
  +-----------------+---------------------------------------+
  | . 1 1 1 X . . . | RESERVED (0)                          |
  +-----------------+---------------------------------------+

== C/I: Carrier-to-Interference ratio

The C/I value is computed from the training sequence of each burst,
where we can compare the "ideal" training sequence with the actual
training sequence, and then express that difference in centiBels.

== Limitations

  - The only supported modulation types are GMSK and 8-PSK.
    Messages with other modulation types will be rejected.

  - IDLE / NOPE indications are not (yet) handled.

  - The logical channel handlers do not (yet) handle optional
    fields, such as TSC and C/I. This will be implemented
    in the follow-up changes.

Change-Id: If61c71d20d590bf07bfd019afb33000a0b6135bd
Related: OS#4006
2019-07-04 01:28:50 +07:00
Vadim Yanitskiy
b06cd9f439 osmo-bts-trx/trx_if.c: introduce TRXD header version handling
It may be necessary to extend the message specific header with
more information. Since this is not a TLV-based protocol, we
need to include the header format version.

  +-----------------+---------------------------+
  | 7 6 5 4 3 2 1 0 | bit numbers (value range) |
  +-----------------+---------------------------+
  | X X X X . . . . | header version (0..15)    |
  +-----------------+---------------------------+
  | . . . . . X X X | TDMA TN (0..7)            |
  +-----------------+---------------------------+
  | . . . . X . . . | RESERVED (0)              |
  +-----------------+---------------------------+

Instead of prepending an additional byte, it was decided to use
4 MSB bits of the first octet, which used to be zero-initialized
due to the value range of TDMA TN (0..7). Therefore the current
header format has implicit version 0.

Otherwise Wireshark (or trx_sniff.py) would have to guess the
header version, or alternatively follow the control channel
looking for the version setting command.

This change introduces a new structure 'trx_ul_burst_ind', which
represents an Uplink burst and the corresponding meta info. The
purpose of this structure is to avoid overloading the existing
functions, such as trx_sched_ul_burst(), with more and more
arguments every time we bump the version.

On receipt of a TRXD message, trx_data_read_cb() now parses
the header version, and calls the corresponding dissector
functions, e.g. trx_data_handle_(hdr|burst)_v0().

Change-Id: I171c18229ca3e5cab70de0064a31e47c78602c0c
Related: OS#4006
2019-06-27 12:51:02 +07:00
Vadim Yanitskiy
d1e7d0dafa osmo-bts-trx/trx_if.c: rename and clarify TRX_MAX_BURST_LEN
This constant actually defines the maximum TRXD message length,
which includes the header and burst bits, not just burst.

Change-Id: I383125e1c4df039fc6b554833bc8736deacbe731
2019-06-27 05:50:17 +00:00
Vadim Yanitskiy
b5c23092c7 osmo-bts-trx/trx_if.c: use osmo_loadXXbe() for TDMA FN and ToA256
Change-Id: Iec0d86f9be7243578ddc1ab322fc313cb5ac5d0b
2019-06-27 05:50:17 +00:00
Pau Espin Pedrol
f2271d0888 bts: Bypass T200 DCCH values for CCCH
Otherwise t200_ms_dcch array values are left uninitialized with random
values, and passed later on to lapdm_channel_init2().

lapdm_channel_init2() will anyways fail during initial check on
get_n200_dcch() and return -EINVAL, so let's not print garbage or call a
function which will anyways simply return an error.

Catched due to some strange values seen in log (see D0 and D3):
osmo-bts/src/common/bts.c:421 (bts=0,trx=0,ts=0,ss=4) Setting T200 D0=1028672, D3=2, S0=520, S3=520 (all in ms)

Related: OS#4066
Change-Id: I3d7e1883811acf97aac97325739f2ff97fc2aa08
2019-06-25 15:56:09 +02:00
Eric Wild
5b9212d6c5 revert changes to T200
The timers are unfortunately completely broken, so let's go back to the
long default timeout values from 1ff0a2addd

See related issues OS#4066 and OS#4074



Change-Id: Ia44310245a348675dbbf3ffc3dc5b6d207fd62d3
2019-06-21 17:00:04 +00:00
Daniel Willmann
876edd5e35 manuals: Add script to regenerate counter/vty documentation
This will generate the VTY/counter documentation for osmo-bts-virtual so
it will be missing documentation for device-specific commands/counters.

Change-Id: Idebb099b69924d6212db119f7a2f2861d4150d7e
Related: OS#1700
2019-06-19 12:46:01 +02:00
Pau Espin Pedrol
5a3eb6470d gsm_data_shared.h: Remove unused loc_list from struct gsm_bts
Change-Id: I52880962dfb0399c613048aa7ddfd828d3c6c933
2019-06-13 17:42:05 +00:00
Harald Welte
46d62b984a lapdm: Use new libosmocore API to ensure per-channel-type N200 values
By using new libosmocore LAPDm API we can specify the GSM channel type
and hence enable the LAPDm code to use a per-channel-type specific N200
value.

At the same time, this new API also allows us to specify T200 values
when initializing the LAPDm channel, so we don't have to fiddle with
low-level lapdm data structures in what used to be oml_set_lchan_t200().

Change-Id: I0e814fbae13e0feddd148c47255dcc38cb718f48
Depends: libosmocore I90fdc4dd4720d4e02213197c894eb0a55a39158c
Closes: OS#4037
2019-06-13 15:38:01 +00:00
Harald Welte
1ff0a2addd Update T200 timer default values
The default values of 1s were *very* long, particularly for fast
channels such as FACCH.  Let's use much more aggressive values
that are more in-line with various recommendations that cold be
found online, such as
https://pcstelconext.wordpress.com/2011/05/02/2g-timer-explanations/
https://www.erlang.com/forum/erlang/thread.htx?thread=2844
https://www.erlang.com/forum/erlang/thread.htx?thread=7180
https://de.slideshare.net/BisiAdebambo/138078380-gsmtimers-59637131

Change-Id: Ic1268ae2d769b12da6cdd4ac8375e4bc033a9e3e
2019-06-13 15:38:01 +00:00
Harald Welte
8ea9ba6af8 [correctly] use the LAPDm T200 values received via OML
As per GSM TS 12.21, the LAPDm timers (T200) of the LAPDm instances
in the BTS are configured via OML from the BSC.  While OsmoBSC
is sending them and OsmoBTS is parsing them, OsmoBTS stopped to
make use of them from commit 3ca59512d2
(January 2016) onwards.

The cause for this has been documented and discovered in May 2017
in https://osmocom.org/issues/2294 and it is quite obvious:  LAPDm
timers are supposed to start when a given frame is actually transmitted
on the radio interface.  PH-RTS.ind and PH-DATA.req are suppsed to be
used over a synchronous interface in some deeply embedded processor.

With OsmoBTS however, we have an asynchronous L1/L2 interface between
a DSP (osmo-bts-{sysmo,lc15,oc2g,octphy}) or OsmoTRX (osmo-bts-trx)
and we receive PH-RTS.ind quite some time ahead.  So if we start T200
at that point, then it will start running way before it has been sent
or before the MS has had a chance to receive the message.

The "correct" way to handle this is to actually measure the difference
between frame numbers in PH-RTS.ind (uplink, advanced) and PH-DATA.ind
(downlink) or PH-TIME.ind, and then add that amount to the actual
timeout value.  This ensures that the timers will time-out the
user-specified amount of time after the actual transmit.

Change-Id: If8babda9e3e5e219908911ddd9c0756b5ea0bca4
Closes: OS#2294
Closes: OS#3906
2019-06-13 15:38:01 +00:00
Harald Welte
b24ef23570 l1sap: Compute statistics on FN advance in PH-RTS.ind
Let's keep some statistics about the min/max/average frame number
advance that we're observing above L1SAP when comparing the time in the
PH-RTS.ind and the frame number we observe in PH-DATA.ind of data
that was received on the uplink.

The statistics are currently only shown in the VTY, but this is a
precursor to using them to correctly advance the LAPDm timers in a
follow-up patch.

Change-Id: I8f739fdb808a614f080afbc4654641ec3df19eb2
Related: OS#2294
Related: OS#3906
2019-06-13 15:37:13 +00:00
Vadim Yanitskiy
01c539284e common/scheduler.c: refactor description of TRXC_* lchans
Let's avoid fancy alignment in the description of logical channels
for the benefits of having better readability, the ability to add
more comments and fields without making it look ugly.

Get rid of value-string array 'trx_chan_type_names', since each
logical channel has its name defined in 'trx_chan_desc'.

Get rid of field 'chan' of 'trx_lchan_desc' structure since it's
not used anywhere, and not actually needed because the position
of each lchan description is defined by its TRXC_* type.

Replace both 'pdch' and 'auto_active' fields with more generic
bitmask field called 'flags', and define the following flags:

  - TRX_CHAN_FLAG_AUTO_ACTIVE,
  - TRX_CHAN_FLAG_PDCH.

Use RSL channel mode #defines from libosmogsm instead of having
hard-coded numbers. This increases readability.

As a bonus, let's add a human readable description to each lchan
definition, so it can be printed in the VTY some day.

Change-Id: I9d5d49ec569f133d37b8164b22607d4700474315
Backported from: I2fc61e1cdca4690a34e2861b9ee3b7c64ea64843
		 I7ab4958801b3422973b67ff0452b90afa8a3f501
2019-06-08 10:09:42 +00:00
Vadim Yanitskiy
2dec9fff1c Use #define RSL_CHAN_RACH for RSL Channel Number of RACH
Change-Id: I7f54fccdae6799e5f4d956a101e11c2d6f998546
2019-06-05 21:06:10 +07:00
Pau Espin Pedrol
8576477de1 bts-trx: trx_if.c: Introduce logging macro LOGPPHI
This way we unify format. We take the chance to add related information
to some log messages which were not printing that information (and was
confusing when using more than one phy instance).

Change-Id: I5b17a01638ade9a6c41da73e550d5947fa92f568
2019-06-04 17:58:46 +02:00
Vadim Yanitskiy
a52c78dd3e common/bts.c: bts_supports_cm(): take care about GSM48_CMODE_SIGN
At the moment, bts_supports_cm() is only called on reception of
RSL Channel MODE MODIFY from the BSC. The idea is to check whether
the indicated RSL channel mode is supported by a BTS model.

RSL Channel MODE MODIFY message may indicate a channel in signalling
mode, i.e. GSM48_CMODE_SIGN, which has always been rejected so far.

Let's assume that signalling is always supported, as there is
no special BTS_FEAT_* definition to check that.

This change should make BTS_Tests.TC_rsl_modify_encr pass.

Change-Id: I8ea98a3eb9dc15a04f665596ee276883eb824b9a
2019-06-03 15:08:11 +00:00
Harald Welte
f6b6c48c8b trx: Update documentation for fn-advance and rts-advance
Change-Id: I83eff296bfb7acff9d8560b5346bd9791fe6e7d9
Related: OS#4036
2019-06-03 07:18:51 +00:00
Vadim Yanitskiy
aaca1217be common/rsl.c: RSL_IE_HANDO_REF is mandatory for handover CHAN ACT
According to 3GPP TS 48.058, section 8.4.1, the Handover Reference
element must be included if channel activation type is 'handover'.
Let's properly reject CHANnel ACTivation messages with missing
RSL_IE_HANDO_REF. Otherwise such requests are misinterpreted
as regular (non-handover) channel requests.

Found using TC_ho_rach() TTCN-3 test case.

Change-Id: I9c50e1dbeb54c5470560adcdfb2bdf5abbe47993
2019-06-01 19:23:42 +00:00
Vadim Yanitskiy
8ec940ce9a osmo-bts/scheduler.h: cosmetic: use bool for ho_rach_detect
Change-Id: Id357e4ed38cbdca2082322da12b93d556056e916
2019-06-01 23:10:02 +07:00
Vadim Yanitskiy
9d083ab236 osmo-bts-trx/l1_if.h: drop unused ho_rach_detect from trx_l1h
Change-Id: I90b6d7fb1bb7ba2f8b1f500043635b0ae5cb4495
2019-06-01 23:10:02 +07:00
Vadim Yanitskiy
e50903df9d osmo-bts-trx/trx_if.c: dropping Tx bursts is a noticeable event
Change-Id: Ia954b797a9bb90660b6548ec0ffb218a1dcff37a
2019-06-01 13:43:21 +07:00
Oliver Smith
e05279a296 debian: create -doc subpackage with pdf manuals
I have verified, that the resulting debian packages build in my own OBS
namespace (see the -doc packages):
https://download.opensuse.org/repositories/home:/osmith42/Debian_9.0/all/
https://build.opensuse.org/project/show/home:osmith42

Depends: Ib7251cca9116151e473798879375cd5eb48ff3ad (osmo-ci)
Related: OS#3899
Change-Id: I6d7a182d0a668693a5014aca0edc50ada9ac0d0f
2019-05-31 14:23:59 +00:00
Daniel Willmann
5abae93dad osmo-bts-lc15: Change LED behaviour to be the same as oc2g
It looks like the status LED on the sysmobts2100 never worked correctly
since lc15bts-mgr expects osmo-bts-lc15 to create and manage
/var/run/osmo-bts/state, but there is nothing to do so in osmo-bts.

This patch copies the functions from oc2g to manage the state file in
lc15.

Change-Id: Iad32a22fc72e2aba45e4f1b9ae585f6e0b8757ed
Related: SYS#4493
2019-05-29 17:35:57 +02:00
Daniel Willmann
34711de016 osmo-bts-oc2g: Fix status LED responsibilities
osmo-bts-oc2g no longer modifies the status LED and instead leaves that
to the bts manager. The service file now also creates a directory in
/var/run needed for osmo-bts to communicate with oc2gbts-mgr. This
status file is used by oc2gbts-mgr to figure out when the bts is
operational.

Related: SYS#4493
Change-Id: Ifae634c6c2ecec7d32298c0f266f91f3e81308f5
2019-05-29 17:35:57 +02:00
Harald Welte
1e96e31c10 clear GPRS indicator in SI3 while PCU is disconnected
osmo-bts cannot provide GPRS service while osmo-pcu is not connected.
The BSC has no knowledge of the PCU connection state. Prevent MSs
from trying to register for GPRS while the PCU is disconnected by
erasing the GPRS Indicator in SI3.

Change-Id: I1a6f5c636c0fe098ee31c280d4572a3f8122b44b
Depends: I690cf308311f910005a325d50f5d5d825678d2b2 (libosmocore.git)
Depends: I08e0ca9a8d13c7aa40b9d90f34f0e13adb87d4e0 (libosmocore.git)
Depends: I8b1ee2405f6338507e9dfb5f1f437c4c2db2e330 (libosmocore.git)
Related: OS#3075
2019-05-28 19:59:07 +02:00
Neels Hofmeyr
347fea69a0 lc15,sysmo,oc2g: fix dsp-trace-flag command
Remove the '~' from '|= flag', it is plain wrong.

This affects the correct parsing of DSP trace flags from the config
file only.  The bug is not present in the interactive VTY command
at runtime.

Change-Id: I915971f49642967c969f5dd475e8faa960ef3960
2019-05-28 19:55:48 +02:00
Harald Welte
9ef6fa0798 Fix passing of RR SUSPEND REQ from DCCH to PCU socket
The existing code ssumed that the RR SUSPEND REQ would be a
LAPDm/RSL unitdata request.  I couldn't find any spec reference
that would support this.  Rather, the message is sent via the normal
main dedicated channel, which is operated in ABM mode.

As the somewhat similar check for diverting measurement results
is in fact looking for UNITDATA, we have to untangle this slightly.

Change-Id: Ic75486f8edaefa9c07bd92515ba1832b1c482fa6
Related: OS#2249
Related: OS#4023
2019-05-27 15:47:15 +00:00
Vadim Yanitskiy
0cb2829f17 common/rsl.c: fix NULL-pointer dereference in rsl_rx_rll()
Change-Id: I07e39e69a42dd09841f5d03608ec0d0b2345139a
Fixes: CID#198663 Null pointer dereferences
2019-05-26 17:59:37 +00:00
Harald Welte
dfa3bb8a10 Add severity to OML FAILURE EVENT REPORT
Example: The fact that the PCU has connected with a given version is not
a *failure* in the first place, particularly not a MAJOR one.  Let's
allow callers of oml_tx_failure_event_rep() specify the serverity of the
event that they're reporting to the BSC.

Change-Id: I49af04212568892648e0e8704ba1cc6de8c8ae89
2019-05-25 10:24:13 +02:00
Harald Welte
b8265c63cc oml: Have one generic log message for all transmitted messages
Rather than open-coding "Tx foobar..." in various functions (and
forgetting it in half of them), let's add a generic message into
oml_mo_send_msg().

Change-Id: I5dd4b1749e68fb7fc74cb2e3a778d2418f46b770
2019-05-24 11:08:20 +02:00
Harald Welte
7f1b61df5f oml: Print more context from FOM Header or using MO
Some of our OML log lines were missing any context.  Try making more
sense by printing any context information about the given managed
object, TRX, ... as we have it.

Change-Id: I60d1660c6d574f206d7b8cc10082b413142365dd
2019-05-24 11:08:20 +02:00
Harald Welte
f2419bf8c3 l1sap: Fix calculation of expired RACH slots in case of missing frame numbers
In case of a Combined CCCH (with SDCCH/4), the number of RACH slots
depends on the frame number.  So in case of lost/skipped frame numbers,
we cannot simply compute the value for the current fn and then multiply
it by the number of frame numbers expired.  Rather, we have to 'replay'
all missed frame numbers and individually determine how many RACH
slots happened in that frame.

Related: OS#3750
Change-Id: If4f8d2ea55fc722c64c330cde09e833b67ee98fe
2019-05-24 11:08:20 +02:00
Harald Welte
03e3fae639 l1sap: Correctly count RACH slots in calc_exprd_rach_frames()
We used a bogus multiplication factor of four when computing the number
of expired RACH slots.  While there are four RACH slots per block (i.e.
4 times more RACH received than normal MAC blocks), that multiplier
doesn't apply here:  We are calling this function per *frame* and not
per *block*.  So the maximum number of RACH slots per *frame* is (in
most suual cases with a single CCCH) at maximum 1. Only some obscure
configurations with multiple CCCHs in a single cell would render higher
values.  In any case, *blocks* never even enter this equation.

This wrong multiplier resulted in rather weird RACH load reports to the
BSC.

Related: OS#3750
Change-Id: I6b14fd6e7819f9164fb4a09b432a9f419e3b6e5c
2019-05-24 11:06:42 +02:00
Harald Welte
095654d361 load_indication: Fix missing re-set of RACH parameters
While we re-set the PCH load counters after every report, we never
actually re-set the RACH load counters.  This meant that the
period/window for RACH load averaging would always grow, rather than
being reset every load indication period.

Related: OS#3750
Change-Id: Icd9150ba56d77d031c3cf496c5936c2de52b364c
2019-05-24 11:03:37 +02:00
Harald Welte
b1a9a77727 rsl: MS POWER COCNTROL isn't (only) about "forcing" power levels
...so let's have a more neutral error message

Change-Id: I1ffa336b18347c2fcedfeb398b255dc517245d7a
2019-05-24 11:03:37 +02:00
Harald Welte
839b0f264f rsl: Implement parsing of BS Power Control message
Change-Id: Id144a7e468f730e3cdaefa4cf2ad51c6106310a2
2019-05-24 11:03:37 +02:00
Harald Welte
bf5d8eed11 RSL: Fix logic about fixed/dynamic MS power control in MS POWER COMMAND
The spec is quite clear: If the MS Power Parameters IE is present, then
the BTS shall perform autonomous MS power control.  If it's absent,
then the MS power shall be fied.  Let's adjust our code accordingly.

Change-Id: Ie43a1fc9cc658677c8c945ae82d03b7bffbe52d5
Related: OS#1622
2019-05-24 00:02:35 +02:00
Harald Welte
29aee05f75 rsl.adoc: DELETE INDICATION is implemented since Feb '18
In the following commit, we introduced transmitting the
RSL DELETE INDICATION on AGCH overflow:

	commit 19da7fdea8
	Author: Harald Welte <laforge@gnumonks.org>
	Date:   Sat Feb 24 04:32:29 2018 +0100

So let's sync the manual with the code.

Change-Id: I988778bdb83271355dc11b1a30a59e1a5dba5fb2
Related: OS#2990
2019-05-24 00:02:34 +02:00
Harald Welte
b07e271994 Use LOGPLCHAN whenever possible
There's no point in open-coding what LOGPLCHAN was created to do:
Log some event while stating the name of the logical channel.

Change-Id: I6913ac8fb543811126b85a54118333155c03bc03
2019-05-24 00:02:34 +02:00
Harald Welte
482564b422 cbch: Improve verbosity and extend logging; Always indicate BASIC/EXTD CBCH
Change-Id: I6c8f9fc6215b616371e46c1f4ca4e44b8c7ac096
2019-05-23 19:16:11 +00:00
Harald Welte
590b23ce3c cbch: Add counters; queue length limits and CBCH LOAD reporting
This adds the final missing part to full CBCH support:
* keep a tab on the current queue length for basic + extended CBCH
* keep rate counters about the number of sent / transmitted SMSCB
* send CBCH LOAD information via RSL to the BSC

Change-Id: I7068c7937a60a900c40439115bb84dc3ee0d061f
2019-05-23 19:16:11 +00:00
Harald Welte
d7be09caf8 sysmo: Fix "nominal power" / BS power display in VTY
The function get_p_max_out_mdBm() returns a value in 1/1000th of dBm,
"milli-dBm", while trx->nominal_power is only whole dBm.  We were
missing the required divider of 1000 ever since Change-Id
Ieff75d5becaa80a2097b6e744c75c2d16259c9a4 was merged in February 2017.

The good news is that this really only affected the VTY output and
not any actual operational aspect of the system.

Change-Id: If92d0b15c48dafc63776b82c7ff5f3c2b3505f68
Closes: SYS#4570
2019-05-22 22:38:38 +02:00
Harald Welte
57f9a279e0 README.md: Mention LimeSDR as SDR device
Change-Id: I0ab5b5721861d7e29c66e849d9e0f4eec2e047e6
2019-05-21 20:34:52 +02:00
Harald Welte
519f588715 manual: SMSCB BROADCAST COMMAND has no limitations anymore
We meanwhile support the SMSCB Channel Indicator IE and hence
can send SMSCB on both BASIC as well as EXTENDED CBCH

Change-Id: I63cc9c8c4c8c80440a61a0687e1f0cb97cc723b7
2019-05-21 20:34:52 +02:00
Harald Welte
396dc59ae8 manual: We now support RSL CBCH LOAD INDICATION
Change-Id: Iad7c364863b4de34bcded9f3c1e737ae0ed8e407
2019-05-21 20:34:52 +02:00
Harald Welte
0f9595f462 cbch: Keep SMSCB queue length counter
This avoids having to iterate the list to count the number of elements.

Change-Id: I72c47affeb87c9b898bc2290dc7ed113945f1805
2019-05-21 02:42:00 +02:00
Harald Welte
067824841f cbch: Support Extended CBCH
The logic for Extended CBCH are the same as for the Basic CBCH, we just
need to
* duplicate our related state
* parse the optional RSL_IE_SMSCB_CHAN_INDICATOR IE
* start to send data on the Extended CBCH (TB=4..7)

Change-Id: If2c6dc7da1e2185ab75fc957f8d305ad8db22429
Closes: OS#3535
2019-05-21 00:31:11 +02:00
Harald Welte
89bfea63c9 cbch: Fix memory leak and send error message on invalid SMSCB command
Change-Id: I411d1fb3693a2f7cf7bba3d38b1aaf276a4137ba
Related: OS#4011
2019-05-21 00:31:11 +02:00
Harald Welte
5567d71d39 cbch: Implement support for DEFAULT message
The BSC can not only send us each to-be-sent message separately, but
it can also configure a DEFAULT message, which is then to be sent
instead of the NULL message.  Let's add support for this

Change-Id: I65a79215b54155d128c26d2ca11ff9ff3ed2cdba
Closes: OS#4013
2019-05-21 00:31:11 +02:00
Harald Welte
0b682f4997 cbch: Log every RSL SMSCB COMMAND with type and number of blocks
Change-Id: I20efe0aa5a67f011d6b6bead57236366c2f45ecf
2019-05-21 00:31:11 +02:00
Harald Welte
dde2f1d5cf cbch: Refactor get_smscb_block() / remove smscb_msg.next_seg
There's no need to keep around a pointer to the next segment
in a SMSCB message.  The way how the multiframe structure is
laid out (and how the tb number works), we can use the result
of a modulo-division on the frame number to determine which
of the segments/blocks inside a SMSCB message (page) we have
to transmit.

This also acts as a simplification in preparation of support
for the SMSCB DEFAULT type.

Change-Id: I48faa19fec4a0852e6112ca2faa98960c678d4c5
Related: OS#4013
2019-05-21 00:31:11 +02:00
Harald Welte
8294368b23 cbch: Implement handling of "Schedule" message
The first block of "schedule" messages must be advertised with
a special sequence number coding, see Table 1 of 3GPP TS 44.012.

Change-Id: I473edf698eba7ff5008f2fd1ec1776f0aa013858
Closes: OS#4012
2019-05-21 00:31:11 +02:00
Harald Welte
7240062b75 RSL: Fix off-by-one error when parsing SACCH INFO IE in RSL CHAN ACT
This off-by-one error in length verification caused all SACCH INFO IE
to be deemed invalid and hence any RSL CHAN ACT with that IE to be
rejected.

Change-Id: I6436caf5c2caefbf7c089d66e37d8d1babe1c24e
Related: OS#3750
2019-05-21 00:31:11 +02:00
Harald Welte
1873a30a4a RSL: Reject RLL messages for lchans that are not active yet
The Radio Link Layer (RLL) messages only make sense when a given
logical channel is active.  If it isn't active, let's reject the
messages with an RSL ERROR REPORT with cause "Message sequence error",
wich according to spec means:

"A message with an existing message type which is not possible according
 to the specification and to the state of the BTS is erroneous."

Related: OS#3750
Change-Id: I68dbb622aeaee657471664cdc0b69c2ac316d77e
2019-05-21 00:31:07 +02:00
Harald Welte
bac9224b3b rsl: Include Channel Nr and Link ID in Error reports whenever possible
While the CHAN_NR and LINK_ID IEs in ERROR REPORRT are optional, we
still should include it whenever possible to help error analysis.

Related: OS#3750
Change-Id: I8155e0d37096bd7bf3563e4f7853171ca4b3aa58
2019-05-20 14:39:17 +02:00
Harald Welte
d96fd011d6 rsl: Send RSL Error Report in case of unknown/unsupported msg_type
Send an RSL Error Report in case of unknown/unsupported msg_type,
as describedi in section 7.3 of 3GPP TS 48.058.

Related: OS#3750
Change-Id: Ib2918007410e635b144a7535cec30b9f3378c755
2019-05-20 14:39:17 +02:00
Oliver Smith
2f251843f9 Revert "debian: create -doc subpackage with pdf manuals"
This reverts commit ad7b8bee71.

Unfortunately the osmo-gsm-manuals-dev package isn't working properly
yet, therefore osmo-bts fails to build on nightly OBS now. My apologies
for not testing enough in my own OBS namespace, before merging. I'll do
that in the future. I'm reverting the patch now, so osmo-bts isn't
missing from the nightly repository until I've fixed the
osmo-gsm-manuals package.

Change-Id: I89c2b92c8ae6331d6fff95a378fb58d82059af13
2019-05-20 13:51:51 +02:00
Oliver Smith
ad7b8bee71 debian: create -doc subpackage with pdf manuals
Related: OS#3899
Depends: I7edb5093e5b58eb3b0f7af2376476db4026db735 (osmo-gsm-manuals.git)
Depends: Ideeae4f7846fa5626fe2c1f5a77e07a3c6e626fe (osmo-ci.git)
Change-Id: I4c184c62804c0b805a0a2425a5bd0312e94e49ab
2019-05-20 10:28:45 +00:00
Vadim Yanitskiy
c6c2aa9ecd README.md: remove OS#1865 from 'Known limitations'
Neither the bug has been reproduced, nor the bug reporter
did respond to request for configuration files.

Change-Id: Ibc9db360be1380abaa9eef4bdf6e9a6d251670da
2019-05-10 07:09:07 +00:00
Alexander Huemer
a7ee918284 Remove 11-bit RACH support from 'Known Limitations'
Support for extended (11-bit) RACH has been implemented:

  - in libosmocoding: I85a34a82d5cd39a594ee89d91a2338226066ab5d,
  - and OsmoBTS: Ia28741603636406744e5e22ffff1fb7a9689955a.

We also have a TTCN-3 test case called TC_pcu_ext_rach_content,
see I8fe156aeac9de3dc1e71a4950821d4942ba9a253.

Change-Id: I091f4fbd52c29c7d56ca392b8a1b872609829d81
2019-05-10 07:09:07 +00:00
Vadim Yanitskiy
5b1c1b2184 osmo-bts-sysmo: fix: indicate BTS_FEAT_CBCH support on OML
It seems osmo-bts-sysmo does support CBCH (Cell Broadcast), but
for some reason it doesn't report BTS_FEAT_CBCH to the BSC.

Change-Id: I42dd3f84c44c210d9255e17153372bf252f897a1
2019-05-10 03:48:04 +07:00
Vadim Yanitskiy
5f9e42a891 osmo-bts-trx: distinguish 11-bit Access Bursts by synch. sequence
Thanks to both TC_rach_content and TC_rach_count TTCN-3 test cases,
it was discovered that there are possible collisions when trying
to decode a regular 8-bit Access Burst as an 11-bit one. This is
exactly what we are doing in rx_rach_fn():

  - calling gsm0503_rach_ext_decode_ber() first,
  - if it failed, falling-back to gsm0503_rach_decode_ber().

With default BSIC=63, the following 8-bit RA values are being
misinterpreted as 11-bit Access Bursts:

  Successfully decoded 8-bit (0x00) RACH as 11-bit (0x0000): bsic=0x3f
  Successfully decoded 8-bit (0xbe) RACH as 11-bit (0x0388): bsic=0x3f
  Successfully decoded 8-bit (0xcf) RACH as 11-bit (0x0036): bsic=0x3f

According to 3GPP TS 05.02, section 5.2.7, there are two alternative
synch. (training) sequences for Access Bursts: TS1 & TS2. By default,
TS0 synch. sequence is used, unless explicitly stated otherwise
(see 3GPP TS 04.60).

According to 3GPP TS 04.60, section 11.2.5a, the EGPRS capability
can be indicated by the MS using one of the alternative training
sequences (i.e. TS1 or TS2) and the 11-bit RACH coding scheme.

In other words, knowing the synch. sequence of a received Access
Burst would allow to decide whether it's extended (11-bit)
or a regular (8-bit) one. As a result, we would avoid possible
collisions and save some CPU power.

Unfortunately, due to the limitations of the current TRXD protocol,
there is no easy way to expose such information from the transceiver.
A proper solution would be to extend the TRX protocol, but for now,
let's do the synch. sequence detection in rx_rach_fn(). As soon as
the TRX protocol is extended with info about the synch. sequence,
this code would serve for the backwards-compatibility.

This change makes the both TC_rach_content and TC_rach_count happy,
as well as the new TC_pcu_ext_rach_content() test case aimed to
verify extended (11-bit) Access Burst decoding.

Related (TTCN-3) I8fe156aeac9de3dc1e71a4950821d4942ba9a253
Change-Id: Ibb6d27c6589965c8b59a6d2598a7c43fd860f284
Related: OS#1854
2019-05-09 16:22:20 +00:00
Harald Welte
9354474b0f handle NULL return from rate_ctr_group_alloc()
Change-Id: I2170e400e47369e9171af4c7361aa2177fea1174
Related: OS#3701
2019-05-08 14:03:36 +02:00
Vadim Yanitskiy
27ee75e4c0 common/oml.c: fix: properly encode NM_ATT_SW_CONFIG
According to 3GPP TS 52.021, sections 9.4.61-62, 'SW Configuration'
shall contain a list of 'SW Descriptions' related to the MO. In
other words, all 'NM_ATT_SW_DESCR' blobs shall be encapsulated
into a single NM_ATT_SW_CONFIG attribute.

For some reason, they were not encapsulated properly, so
OsmoBSC were unable to parse the 'SW Descriptions'.

However, unlike OsmoBSC the old OpenBSC does not expect this
encapsulation, thus after this change it will be unable to
parse the 'SW Descriptions'.

Change-Id: Id26104719891944f3e2151df362bd45bb057a9c5
Related: OS#3938
2019-05-07 00:40:14 +07:00
Vadim Yanitskiy
038a1fa047 common/oml.c: refactor Get Attribute Response message generation
Instead of allocating two transitional buffers (one static,
another dynamic), we can use the existing message buffer.

Both handle_attrs_bts() and handle_attrs_trx() can put (append)
the reported attributes, and push (prepend) non-reported ones
as per 3GPP TS 52.021, 9.4.64 "Get Attribute Response Info".

Change-Id: I349447a43bce360f59e0c6b435906c65167d158b
2019-05-07 00:30:09 +07:00
Vadim Yanitskiy
5efbd4e862 common/oml.c: fix broken debug print in down_mom()
Change-Id: Ideac59946d50c6e06052a9590e02cfcfbf23d003
2019-05-05 16:47:49 +03:00
Vadim Yanitskiy
40b1b4b20d common/oml.c: use proper format specifier for uint16_t
Change-Id: I8f372a689b3c1cc2cf925654b2db44a0f4ee7603
2019-05-05 16:46:20 +03:00
Vadim Yanitskiy
57e26c3e16 common/oml.c: introduce and use both LOGPFOH and DEBUGPFOH
Change-Id: I9e9d6ccb88c9c9d35b2ce5778fa2580382704089
2019-05-05 16:45:06 +03:00
Vadim Yanitskiy
ab5eff60e1 common/paging.c: fix unaligned pointer access
Passing a pointer to a packed structure to tmsi_mi_to_uint() may
result in unaligned pointer value. Found with clang-8.

Change-Id: Ief69854973a098e6da7c05f4417dc11988edd777
2019-04-24 15:57:06 +07:00
Vadim Yanitskiy
19bd4f818d common/rsl.c: fix unaligned pointers in rsl_add_rtp_stats()
Found using clang-8:

  rsl.c:1646:7: warning: taking address of packed member 'packets_sent'
		of class or structure 'ipa_stats' may result in an
		unaligned pointer value
  rsl.c:1646:28: warning: taking address of packed member 'octets_sent'
		 of class or structure 'ipa_stats' may result in an
		 unaligned pointer value
  rsl.c:1647:7: warning: taking address of packed member 'packets_recv'
		of class or structure 'ipa_stats' may result in an
		unaligned pointer value
  rsl.c:1647:28: warning: taking address of packed member 'octets_recv'
		 of class or structure 'ipa_stats' may result in an
		 unaligned pointer value
  rsl.c:1648:7: warning: taking address of packed member 'packets_lost'
		of class or structure 'ipa_stats' may result in an
		unaligned pointer value
  rsl.c:1648:28: warning: taking address of packed member 'arrival_jitter'
		 of class or structure 'ipa_stats' may result in an
		 unaligned pointer value

Change-Id: Ifba33cfd8edeccc99a21c7d076db7119c29d4f40
2019-04-24 14:34:10 +07:00
Vadim Yanitskiy
d16b69f29e common/rsl.c: fix size argument in memcmp() call
Found using clang-8:

  rsl.c:1607:93: warning: size argument in 'memcmp' call
                          is a comparison [-Wmemsize-comparison]
  rsl.c:1607:7: note: did you mean to compare the result of 'memcmp' instead?

It looks more logical to compare the result of memcmp() against
zero instead of passing 'sizeof(sysinfo_buf_t) != 0' as size.

Change-Id: Ia8b95b017dbbfeb058d479fbaaf4861930569bb5
2019-04-23 15:17:01 +07:00
Vadim Yanitskiy
43033e6923 common/l1sap.c: fix: add missing new line to a debug message
Change-Id: I7c0dab255289a5847d1a0af009e8962e4410e5ca
2019-04-21 13:50:21 +00:00
Vadim Yanitskiy
d16322f5ed common/oml.c: fix total length calculation in cleanup_attr_msg()
Both callers of cleanup_attr_msg(), i.e. handle_attrs_trx() and
handle_attrs_bts(), always pass out_offset >= 1, so the length
of the unsupported attributes counter is already accounted.

Otherwise, both callers would copy an additional garbage byte
from uninitialized memory. Discovered using Valgrind:

DOML DEBUG oml.c:539 OC=BTS(01) INST=(ff,ff,ff) Rx GET ATTR
DOML INFO oml.c:265 BTS Tx Get Attribute Response
==25467== Syscall param socketcall.sendto(msg) points to uninitialised byte(s)
==25467==    at 0x623E0BD: send (send.c:27)
==25467==    by 0x5685846: __handle_ts1_write (ipaccess.c:358)
==25467==    by 0x5683F8B: ipa_client_write (ipa.c:79)
==25467==    by 0x5683F8B: ipa_client_fd_cb (ipa.c:140)
==25467==    by 0x5F1DC23: osmo_fd_disp_fds (select.c:223)
==25467==    by 0x5F1DC23: osmo_select_main (select.c:263)
==25467==    by 0x42980B: bts_main (main.c:354)
==25467==    by 0x6160F44: (below main) (libc-start.c:287)
==25467==  Address 0x7d83895 is 23,669 bytes inside a block of size 102,528 alloc'd
==25467==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==25467==    by 0x589A6B4: talloc_pool (in /usr/lib/x86_64-linux-gnu/libtalloc.so.2.1.5)
==25467==    by 0x5F1E28B: msgb_talloc_ctx_init (msgb.c:316)
==25467==    by 0x4293D0: bts_main (main.c:234)
==25467==    by 0x6160F44: (below main) (libc-start.c:287)
==25467==  Uninitialised value was created by a stack allocation
==25467==    at 0x415FE5: oml_tx_attr_resp (oml.c:259)
==25467==    by 0x415FE5: oml_rx_get_attr (oml.c:561)
==25467==

Change-Id: Ic7c2c4e54e9f99b60aaf70604044933978be945c
Related: OS#3938
2019-04-19 20:22:29 +07:00
Vadim Yanitskiy
77b98d4a16 common/oml.c: use proper OML object for Get Attribute Response
It was noticed that the Get Attribute Response message always
indicates BTS(00,ff,ff) as the addressed OML entity, even if
e.g. Baseband Transceiver(00,00,ff) was requested by the BSC.

Despite neither OsmoBSC nor OpenBSC does complain about this,
such behaviour violates 3GPP TS 52.021. Let's fix this.

Change-Id: Icb1ee75d4bf680deb6365288d8c2053816a12217
Related: OS#3938
2019-04-19 20:22:26 +07:00
Vadim Yanitskiy
d1e9ded94d common/oml.c: use proper NACK reason in oml_tx_attr_resp()
Change-Id: I482caa0747f81da2979bfbdbd22bd6962af728cd
2019-04-19 20:20:47 +07:00
Vadim Yanitskiy
b873b91c5f common/oml.c: constify argument 'trx' of handle_attrs_trx()
Change-Id: Id476d492b3c1d0c728fca9eb0fb2254512bdef72
2019-04-19 20:20:47 +07:00
Philipp Maier
ac3924e093 pcu_sock: use %zu conversion specifier for printing sizeof() result
When using %lu and sizeof() for printing the compiler may throw a
warning. Lets prevent this by using %zu instead of %lu as conversion
specifier.

Change-Id: If5cb656537b1b73b9361a132801ab47ab7f8a709
2019-04-16 10:07:34 +02:00
Philipp Maier
73d174e35f oc2gbts_mgr: use osmo_init_logging2() instead of osmo_init_logging()
The function osmo_init_logging() is deprecated, lets use
osmo_init_logging2() as suggested.

Change-Id: Iebc80cd1f77f10a879d4536d788377f522dd853f
2019-04-15 11:57:35 +00:00
Vadim Yanitskiy
720971c6a0 common/pcu_sock.c: fix possible memleaks in pcu_sock_read()
Change-Id: I58352e5f2b5715361c7089d0e134a42975171022
2019-04-12 21:29:43 +07:00
Philipp Maier
620c74b7fe oc2gbts_mgr_calib: do not return NULL on integer function
The functions oc2gbts_par_get_uptime() and oc2gbts_par_set_uptime() try
to return with NULL, but both functions are declared as int. Lets return
-EINVAL instead.

Change-Id: I63b61be2940c59b221089d3d1501371b0116d89a
2019-04-08 11:23:39 +02:00
Philipp Maier
a89581b22d oc2gbts_mgr_calib: don't use fsync() on *FILE pointer
fsync() takes an integer file descriptor but we have a *FILE pointer
here. Lets use fileno() first to convert the integer file descriptor to
a FILE pointer.

Change-Id: I46ffd8c680ba0b445cbbd133d5ce92b79e3d8d87
2019-04-08 11:23:39 +02:00
Philipp Maier
668d20cc1d l1_if: add include for missing header file
the function bts_cbch_get() is used in l1_if.c. The function is
declared in cbch.h. Lets include this header file in order to be
complete.

Change-Id: I95d7e89eed969dd5b3ccff0eebcc6c568196a97d
2019-04-08 11:23:39 +02:00
Vadim Yanitskiy
45a8d4b2be common/oml.c: fix: properly push abis_nm_ipa_magic
In oml_send_msg() we optionally push the A-bis IPA magic string
("com.ipaccess") to a given message buffer as LV (Length Value),
including the terminating null byte ('\0').

There was a mix of both sizeof() and strlen() calls, and worse
luck, memcpy() has been used in a wrong way, skipping the '\0':

  memcpy(dest, src, strlen(src));

In general, this is not critical because the headroom of a given
message buffer would most likely be zero-initialized, so the '\0'
is already there. However, msgb_push() gives no such guarantee.

Let's use the libosmocore's TLV API (in particular, lv_put()),
and stick to sizeof(), so the null byte will always be included.

Change-Id: I0c7f8776d0caec40f9ed992db541f43b732e47ae
Closes: OS#3022
2019-04-01 07:18:32 +07:00
Harald Welte
41723e1508 Forward GPRS SUSPEND REQ from DCCH to PCU socket
As specified in 3GPP TS 03.60 Section 16.2.1 and 44.018 Section 3.4.15,
a Class B MS is sending a "RR GPRS SUSPEND REQ" via a DCCH to the BTS if
it wants to suspend GPRS services.  The BSS is now responsible to
somehow forward this to the SGSN.  As the Gs interface between BSC and
SGSN is both optional and doesn't have any provision to forward this
message, we have to send it over to the PCU so it can use regular BSSGP
signaling to inform the SGSN of the SUSPEND REQUEST.

This patch requires libosmocore Change-Id
I90113044460a6c511ced14f588876c4280d1cac7 for the related definition of
struct gsm48_gprs_susp_req.

Change-Id: I3c1af662c8f0d3d22da200638480f6ef05c3ed1f
Closes: OS#2249
2019-03-27 11:19:11 +00:00
Philipp Maier
945c09381d oml: use oml_tx_failure_event_rep() instead of signals to SS_FAIL
At some locations in the code a signal to SS_FAIL is dispatched in order
to trigger the sending of an OML failure event report in oml.c. This is
a bit overcomplicated for the task. Lets use oml_tx_failure_event_rep()
to send the failure event reports and lets remove the signal handler for
SS_FAIL.

Change-Id: Ie4fce1273a19cc14f37ff6fc7582b2945c7e7c47
Related: OS#3843
2019-03-27 11:10:57 +00:00
Philipp Maier
a5a03d6b35 oml: use oml_tx_failure_event_rep() instead of oml_fail_rep()
The function oml_tx_failure_event_rep() replaces oml_fail_rep(), so lets
use only oml_tx_failure_event_rep() and remove oml_fail_rep()

Change-Id: I83c4fa9ebd519299fd54b37b5d95d6d7c1da24f6
Related: OS#3843
2019-03-27 11:10:57 +00:00
Philipp Maier
891ba1568a main: remove wrong call to oml_fail_rep() on SIGUSR1/2 and SIGABRT
SIGUSR1/2 and SIGABRT should not trigger a failure event report on
OML since we only use it to get an intermediate talloc report. (In
case of SIGUSR1/2 without leaving the process.)

Change-Id: I99e637496afff2530425b89c6e9befc76db24906
2019-03-27 11:10:47 +00:00
Philipp Maier
c49df5d144 vty: add function gsmnet_from_vty() to vty.h
The function gsmnet_from_vty() is used in oc2gbts_vty.c, but it is not
declared in vty.h. Lets add the declaration to vty.h, so that
gsmnet_from_vty() can be used properly by other modules.

Change-Id: I8cf63c6fabdb1f2dc67ca8193704ce4d1d4882d9
2019-03-27 10:09:17 +00:00
Pau Espin Pedrol
749b878eb1 contrib: Remove deprecated screen script helpers
Nowadays only known users (OE images) use systemd and don't require this
kind of screen setup.
In any case, this kind of file belongs to scpeific setup and are not
needed here.

Change-Id: I65b0eee44336e4627620443861092b8988f2e01d
2019-03-27 09:57:41 +00:00
Harald Welte
2f5e7093bf rsl.c: Add missing #include of gsm0808.h
This fixes the below compile error:

rsl.c:900:43: error: ‘gsm0808_chosen_enc_alg_names’ undeclared (first use in this function)

Change-Id: I4aed0242737602e61b785862e3c37c963bf48455
2019-03-27 10:50:28 +01:00
Philipp Maier
dd7cc3cc7c oc2g: change log level for calibration file errors to FATAL
The log level of the messages that notify calibration file loading
problems is NOTICE, but since it is a severe problem when calibration
can not be loaded lets change it to FATAL

Change-Id: I32aed25ca7925f1c776f00b37f404a58a85ddbc7
Related: OS#3823
2019-03-27 07:58:56 +00:00
Philipp Maier
7b96b8832f oc2g: generate failure event report in case of bad calibration
When the TX/RX calibration files can not be loaded a failure event
report should be sent to the BSC. Lets send a failure event report when
calbration data is either bad or can not be loaded (see also remvoed TODOs).

Change-Id: I3318470518b34807a443f7cb78c7091b4a3d4481
Related OS#3823
2019-03-27 07:58:56 +00:00
Philipp Maier
eac4d23421 oc2gbts_mgr: use msgb_talloc_ctx_init() instead of msgb_set_talloc_ctx()
The function msgb_set_talloc_ctx() is deprecated. Lets use
msgb_talloc_ctx_init() as suggested.

Change-Id: I61f80a7b11e9117e8b71c49b7d81d2f959f3150d
2019-03-20 14:48:00 +00:00
Philipp Maier
a4332be9e9 oc2g: l1if: delay trx initialization to avoid race condition
On links with high latency it can happen that RADIO CARRIER OPSTART is
carried out to early, even before SET BTS ATTRIBUTES is carried out.
This means that important parameters for the initalization are not yet
set and the TRX initalization failed. Lets delay the TRX initalization a
bit in order to be sure that all BTS attributes are set before the
initalization is carried out.

Change-Id: Id3bdc88d28417e422d2c0c33b03be06f1a4706c2
Related: OS#3782
2019-03-19 13:56:12 +00:00
Max
6bc6d78b36 Constify pcu_rx_*() parameters
Use const for data parameter where appropriate.

Change-Id: Ia228c001ca07cfde61b540bec6257b62aec93517
2019-03-18 16:28:33 +00:00
Max
965b911583 Make gsm_pchan2chan_nr() static
It's only used inside of gsm_data_shared.c so let's mark it as such.

Change-Id: I83f1783efe9dc07c8bf9901ebc94774aef1cd472
2019-03-18 11:39:07 +00:00
Philipp Maier
708adf1a1f oc2gbts_mgr_vty: remove calls to vty_install_default()
The function vty_install_default() is deprecated and throws a compiler
warning that suggests to remove it, so lets remove it.

Change-Id: I1a4afb6e352bed9a5af794b39b984a7ddef36e08
2019-03-18 10:40:18 +00:00
Philipp Maier
3dd90a09e4 oml: make oml_tx_failure_event_rep() public
The static function oml_tx_failure_event_rep() is a lot easier to use
than the currently implemented signal scheme. Lets make it public so
that we can quickly generate failure event reports.

Change-Id: I9c4601840a06119f35cfe4da453fff3b293fe615
Related: OS#3823
2019-03-18 09:20:58 +01:00
Philipp Maier
fc17dc763f lc15: remove unused define constant FACTORY_ROM_PATH
Change-Id: I76d47471a8480da5a7cb4a11655d5150d4f33508
Related: OS#3823
2019-03-18 08:06:21 +00:00
Philipp Maier
f748c4530c oc2g: remove unused define constant FACTORY_ROM_PATH
Change-Id: I5eb12332568c85bfd2dd83eb5ef1d9c1c9bbfd27
Related: OS#3823
2019-03-18 08:06:12 +00:00
Harald Welte
b509023d34 OC-2G: Nominal transmit power is 25 dBm, not 40
According to the OC-2G product specifiacation, the maximum output power
is 25 dBm.  This should be reflected in the code, there's no point in
claiming to be able to trnasmit 40 dBm - which just creates confusion on
all levels (such as the logs, where Tx power is claimed to be ramped up
to 40 dBm right now).

Closes: OS#3823
Change-Id: Ia6b3476ab2f9279f8905b8c7cfd07ef7b0a939ed
2019-03-05 21:34:08 +01:00
Harald Welte
de3262fd27 OML: Don't advertise baseband transceiver as UNLOCKED at startup
For some strange historical reason, the baseband transceiver MO was
brought up in state "UNLOCKED".

The object should come up in "locked" state until it's explicitly
unlocked by the BSC.

See Section 6.8.2 of TS 12.21: "If there is yet no administrative state
value explicitly set by the BSC (e.g., at an initialization time), the
object shall be presumed to be administratively locked by default"

Change-Id: Id505594b9f224567566caac84dae2e2ae4477fae
Closes: OS#3790
2019-02-23 15:59:18 +01:00
Harald Welte
5eddf98dfc OML: Store merged attributes of IPA OML Managed Objects
For the TS 12.21 standard OML attributes, we store a copy of the
most-recently set value for each attribute in "mo->nm_attr".  This
somehow was missed when adding support for the IPA specific MOs like
those relevant for GPRS.

Change-Id: I75ebda46da9c1fcecc484311bf3833f31c536ee1
2019-02-23 15:59:10 +01:00
Pau Espin Pedrol
b3fb33adea oc2g: vty: Compilation error fixes due to commented code
Change-Id: Id2b16b9acd15d0c80085fac0fdc2a57173ebb0a0
2019-02-20 00:04:51 +01:00
Pau Espin Pedrol
d8afcc143a oc2g: Remove unused static function
Change-Id: I4d0a476f84bc9e92e02f94c3990daddeeaa3c5d5
2019-02-20 00:03:33 +01:00
Pau Espin Pedrol
6b5bbee25f oc2g: Remove unused variables
Change-Id: I6738adb6b0ae50905351c67c259d7a77cb250624
2019-02-20 00:02:34 +01:00
Pau Espin Pedrol
546056c9c8 oc2g: fsync requires fd instead of file stream
Similar fix was done for lc15 in a8041edb.

Change-Id: Idcd9dc48ea2e1f80bfdf5cf8b6bf55d8150fe0d2
2019-02-19 23:47:41 +01:00
Pau Espin Pedrol
f3fa1d384d oc2g: led_sleep_cb: pass correct ptr to llist_move_tail
Fix compilation warning. At runtime it's not a big issue because the
"list" field is the first field of the led_list (struct
lc15bts_led_timer_list) variable. Hence, the address passed is the same.

Similar to commit fixing same issue in lc15 in 080302f8.

Change-Id: Ie393a21bc3a725520343c70941cb4f591b313420
2019-02-19 23:43:23 +01:00
Pau Espin Pedrol
45b9021eb8 oc2g: Cleanup of get_hwversion_desc
Remove unused variables, wrong return type values, etc.

Change-Id: I5565b904c72a9ac1775818416f05c64722d366b2
2019-02-19 23:42:44 +01:00
Pau Espin Pedrol
b3e7a888c9 oc2g: Add get_hwversion_desc to header file
it's used in oc2g/main.c and it needs to be in a header file.

Similar as previously done for lc15 in 19795c5a.

Change-Id: Ic6826d8c8ff5c648158493454a80704bb956b51d
2019-02-19 23:30:11 +01:00
Pau Espin Pedrol
3713b59368 oc2g: Fix compilation error (comment mark inside comment)
Change-Id: Ib27b31825744ea397b5b4eb258da78f5f834895c
2019-02-19 23:21:07 +01:00
Max
f788aefe6f Enable statsd support
Change-Id: I9112d9fd527cdc29d89868df40c6845a751c4865
2019-02-18 13:40:03 +01:00
Philipp Maier
12d362fe09 scheduler_trx: use stored fn for pdtch data indications
When the ph-data indications for the PDTCH are passed up to l1sap,
then a forumla is used to calculate the frame number of the beginning of
the block that is just passed up. This is not necessary since the start
frame number of the block is stored in *first_fn when the block arrives.
We should use this frame number instead. (For the measurement indication
it is already done this way).

Change-Id: I6c01987be78203acfa689c6decb2c806f8fff3d6
Related: OS#2977
2019-02-15 17:52:07 +01:00
Max
fa8b9e2aa3 Log lchan kind on PCU-related error
Change-Id: Iadb464e7040dd11e4a8cabfc96d6d90f32594109
2019-02-14 21:46:34 +00:00
Max
de9e2092c9 osmo-bts-trx: add extended (11-bit) RACH support
Attempt to decode incoming RACH burst as 11-bit first
and fallback to 8-bit if unsuccessful.

Change-Id: Ia28741603636406744e5e22ffff1fb7a9689955a
Related: OS#1854
2019-02-14 15:48:08 +00:00
Harald Welte
3933e930c3 OML: Work around OsmoBSC sending "GET ATTRIBUTES" with short length
OsmoBSC used to have a bug in encoding the "GET ATTRIBUTES" OML message,
resulting in the actual message length being three bytes longer than the
encoded length value.

As in Ib98f0d7c2cff9172714ed18667c02564540d65d7 we have introduced
proper consistency checks on length values, all "GET ATTRIBUTES" from
OsmoBSC version suntil today will fail.  This patch introduces a
work-around to remain compatible with old OsmoBSC while still keeping
the consistency checks for all other messages.

Change-Id: Ifa24e9e2c71feb2c597557807d675438c2825b2d
Related: OS#3799
2019-02-12 20:29:50 +01:00
Harald Welte
906357c5e2 OML: Properly reject short messages and truncate over-long messages
For OML, what matters is the length indicated in the OML message header.

If we don't have sufficient bytes, reject the message and send a failure
event report.

If we have more bytes, truncate the message at the number of bytes
indicated in the OML length header.

Change-Id: Ib98f0d7c2cff9172714ed18667c02564540d65d7
2019-02-12 20:28:49 +01:00
Harald Welte
e160ac6ea5 OML: Reject segmented OML messages
TS 12.21 describes segmenting of OML messages using placement
fist/middle/last and the "sequence' number of the OML header. We don't
implement this and hence must ignore or reject any related messages.

Before this patch however, we simply treated such segments as if they
were a complete OML message.  Let's fix that.

Change-Id: Idd42cf4edc1bf9ab366853bd9b0f7afd9c060910
Closes: OS#3795
2019-02-12 20:08:56 +01:00
Harald Welte
96bded3ebd OML: Use 'const struct abis_oml_mo *' whenever users only read
Try to constrain the code a bit further by making all read-only
accesses use 'const *'.

Change-Id: I5a61e6d1b4e5e083bb24017166186dc87d035cd0
2019-02-12 20:08:18 +01:00
Harald Welte
ccc7ba17c0 OML: Report short messages even for invalid TRX numbers in down_fom()
Change-Id: I65b57d3fc714814db3ae3fd34398f307413fece8
2019-02-12 20:08:18 +01:00
Harald Welte
055c29bc6b OML: Reduce code duplication in down_mom/down_fom
Simply use a "mo" variable on the stack rather than having duplicate
but otherwise identical calls to oml_tx_failure_event_rep()

Change-Id: Ibe6c79e95405b13d041047549d2ffa39aa355eb2
2019-02-12 20:08:18 +01:00
Harald Welte
e57a62deee OML: send proper OML alerts in case of errors
Change-Id: I5b19b82a4874617c7c584cf3eac55eb9c756710a
2019-02-12 20:08:08 +01:00
Harald Welte
268ba55a6e OML: remove double-logging on oml_tx_failure_event_rep()
When we send an OML failure event report using
oml_tx_failure_event_rep(), the function itself will not only send
the report to the BSC but also log it.  So there's no need to both
have an explicit LOGP() and a call to oml_tx_failure_event_rep().

Change-Id: Ib3fd06b3266d896aebeed4ebe42ac71ff173bb5c
2019-02-09 09:08:27 +01:00
Harald Welte
742dad5b69 OML: Don't overwrite MO instance before oml_tx_failure_event_rep()
In Change-Id Ic163bcfb6361a8ebd39e0bc0f238ef51e2cb214e we introduced
several additional calls to oml_tx_failure_event_rep() during OML
messaeg processing.  However, for some reason, we *overwrite* the
bts_nt/trx_nr/ts_nr of the TRX MO.  This is clearly wrong.  The
"address" of a managed object doesn't change at runtime!

Change-Id: Idfb80ccd6dd485d52dc006867fae3dde3fb005f3
2019-02-09 09:08:27 +01:00
Harald Welte
02231177a9 OML: Ensure MOs are initialized with valid "Administrative State'
When osmo-bts connects to the BSC, it sends a ton of "State Change Event
Report" messages indicating the Operational State (NULL), Availability
status (power off) and [as an osmocom extension] also the Administrative
State. However, the value of the administrative state is "0", which is
not defined in TS 12.21 Section 9.4.4

Change-Id: I03f8a4b08b266cd40036076c76f9dc7e8bf08da2
Closes: OS#3785
2019-02-09 09:08:27 +01:00
Harald Welte
893e499e0c OML: Return attributes in ACK/NACK messages
As per 3GPP TS 12.21 Section 8.2 "ACK messages shall return all the
attributes in the original message". OsmoBTS fails to do so but simply
sends no attributes at all in the ACK.

TS 12.21 is a bit vague whether or not the attributes shall also be
achoed in the NACK.  Let's do it and append the CAUSE in this case.

Closes: OS#3788
Change-Id: Ifb305fe75f8305bb04872f26492b8b1bb8c27f49
2019-02-09 09:08:22 +01:00
Harald Welte
3c89e2c36a OML: some more comments on what functions do
Change-Id: I5f30f6c556968fab60283ff1948966af28dc6e83
2019-02-08 22:09:29 +01:00
Harald Welte
9c9232c993 scheduler_trx: Fix erroneous multiply-by-four
Commit acefd0586e introduced the "toa256"
resolution change.

Before the change, _sched_compose_ph_data_ind() used quarter-bits as
units, so multiplying the old "toa" value by four made sense.

However, after said change, the value is in 1/256th of bits, and hence
we need to report the toa256 value without any multiply-by-four.

Change-Id: I9f980236ea1cd635cb229290e187747cc8c86d8d
Related: OS#2977
2019-02-05 17:46:25 +01:00
Daniel Willmann
5c205639f1 doc/examples: Install OC2G config files with autotools
Change-Id: I2fd587e91b5e0e4cd1b8ffa781f65dbfd4484f19
2019-01-30 10:35:13 +01:00
Daniel Willmann
3bf27cefbb systemd: Install OC2G service files with autotools
Change-Id: Ifd37b6a01ad9007a9e887fe3dd208dc74047b4d8
2019-01-30 09:40:52 +01:00
Vadim Yanitskiy
e8ebbe300c common/vty.c: fix 'cfg_phy_no_inst_cmd' command description
A comma is needed to separate a command definition from its
description, not the parts of description. Let's fix this.

Before this patch:

  OsmoBTS# configure terminal
  OsmoBTS(config)# phy 0
  OsmoBTS(phy)# no?

    no  PHY Instance number

  OsmoBTS(phy)# no ?

    instance
    osmotrx   OsmoTRX Transceiver configuration

After this patch:

  OsmoBTS# configure terminal
  OsmoBTS(config)# phy 0
  OsmoBTS(phy)# no?

    no  Negate a command or set its defaults

  OsmoBTS(phy)# no ?

    instance  Select a PHY instance to remove
    osmotrx   OsmoTRX Transceiver configuration

Change-Id: If10d85abc6506118ba08c37e8101f423d6f838ea
2019-01-27 15:31:01 +03:00
Harald Welte
e1dade0471 Bump version: 0.8.1.199-5c93-dirty → 1.0.0
Change-Id: Ie33252aef4144f9bb825d7c234970fd4e6083bb2
2019-01-20 20:38:25 +00:00
Daniel Willmann
5a266511bf dump_docs: Use new config file naming scheme
Change-Id: I05723ef50deb918ed1131c1d30f8e613351b3be5
2019-01-17 17:07:44 +01:00
Daniel Willmann
a4649308eb Rename oc2g config file to match new naming scheme
examples/oc2g/osmo-bts.cfg->examples/oc2g/osmo-bts-oc2g.cfg

Change-Id: Ie49d5695ea78da2995252c56c75ce42e6cec0e9c
Related: SYS#4444
2019-01-17 17:07:43 +01:00
153 changed files with 8506 additions and 4196 deletions

6
.gitignore vendored
View File

@@ -47,6 +47,11 @@ src/osmo-bts-octphy/osmo-bts-octphy
src/osmo-bts-virtual/osmo-bts-virtual
src/osmo-bts-omldummy/osmo-bts-omldummy
src/osmo-bts-oc2g/osmo-bts-oc2g
src/osmo-bts-oc2g/oc2gbts-mgr
src/osmo-bts-oc2g/oc2gbts-util
src/osmo-bts-oc2g/misc/.dirstamp
tests/atconfig
tests/package.m4
tests/agch/agch_test
@@ -57,6 +62,7 @@ tests/meas/meas_test
tests/misc/misc_test
tests/handover/handover_test
tests/tx_power/tx_power_test
tests/ta_control/ta_control_test
tests/testsuite
tests/testsuite.log

View File

@@ -5,8 +5,7 @@ SUBDIRS = include src tests doc contrib
# package the contrib and doc
EXTRA_DIST = \
contrib/dump_docs.py contrib/screenrc-l1fwd \
contrib/l1fwd.init contrib/screenrc-sysmobts contrib/respawn.sh \
contrib/dump_docs.py \
git-version-gen .version \
README.md

View File

@@ -20,7 +20,7 @@ Several kinds of BTS hardware are supported:
* sysmocom sysmoBTS
* Octasic octphy
* Nutaq litecell 1.5
* software-defined radio based osmo-bts-trx (e.g. USRP B210, UmTRX)
* software-defined radio based osmo-bts-trx (e.g. USRP B210, UmTRX, LimeSDR)
Homepage
--------
@@ -45,7 +45,7 @@ We provide a
as well as a
[VTY Reference Manual](http://ftp.osmocom.org/docs/latest/osmobsc-vty-reference.pdf)
and a
[Abis refrence MAnual](http://ftp.osmocom.org/docs/latest/osmobts-abis.pdf)
[Abis reference MAnual](http://ftp.osmocom.org/docs/latest/osmobts-abis.pdf)
describing the OsmoBTS specific A-bis dialect.
Mailing List
@@ -117,10 +117,3 @@ osmo-bts-octphy
* no clear indication of nominal transmit power, various power related
computations are likely off
* no OML attribute validation during bts_model_check_oml()
osmo-bts-trx
------------
* TCH/F_PDCH cannel not working as voice (https://osmocom.org/issues/1865)
* No BER value delivered to OsmoPCU (https://osmocom.org/issues/1855)
* No 11bit RACH support (https://osmocom.org/issues/1854)

View File

@@ -62,14 +62,14 @@ then
fi
dnl checks for libraries
PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 0.12.0)
PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 0.12.0)
PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 0.12.0)
PKG_CHECK_MODULES(LIBOSMOCTRL, libosmoctrl >= 0.12.0)
PKG_CHECK_MODULES(LIBOSMOCODEC, libosmocodec >= 0.12.0)
PKG_CHECK_MODULES(LIBOSMOCODING, libosmocoding >= 0.12.0)
PKG_CHECK_MODULES(LIBOSMOABIS, libosmoabis >= 0.5.0)
PKG_CHECK_MODULES(LIBOSMOTRAU, libosmotrau >= 0.5.0)
PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 1.3.0)
PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 1.3.0)
PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 1.3.0)
PKG_CHECK_MODULES(LIBOSMOCTRL, libosmoctrl >= 1.3.0)
PKG_CHECK_MODULES(LIBOSMOCODEC, libosmocodec >= 1.3.0)
PKG_CHECK_MODULES(LIBOSMOCODING, libosmocoding >= 1.3.0)
PKG_CHECK_MODULES(LIBOSMOABIS, libosmoabis >= 0.6.0)
PKG_CHECK_MODULES(LIBOSMOTRAU, libosmotrau >= 0.6.0)
AC_MSG_CHECKING([whether to enable support for sysmobts calibration tool])
AC_ARG_ENABLE(sysmobts-calib,
@@ -382,6 +382,7 @@ AC_OUTPUT(
tests/sysmobts/Makefile
tests/misc/Makefile
tests/handover/Makefile
tests/ta_control/Makefile
tests/tx_power/Makefile
tests/power/Makefile
tests/meas/Makefile

View File

@@ -10,7 +10,7 @@ env = os.environ
env['L1FWD_BTS_HOST'] = '127.0.0.1'
bts_proc = subprocess.Popen(["./src/osmo-bts-sysmo/sysmobts-remote",
"-c", "./doc/examples/sysmo/osmo-bts.cfg"], env = env,
"-c", "./doc/examples/sysmo/osmo-bts-sysmo.cfg"], env = env,
stdin=None, stdout=None)
time.sleep(1)

View File

@@ -57,4 +57,6 @@ build_bts() {
if [ "$WITH_MANUALS" = "1" ] && [ "$PUBLISH" = "1" ]; then
$MAKE -C "$base/doc/manuals" publish
fi
$MAKE maintainer-clean
}

View File

@@ -1,31 +0,0 @@
#!/bin/sh
### BEGIN INIT INFO
# Provides: l1fwd
# Required-Start:
# Required-Stop: $local_fs
# Default-Start: 5
# Default-Stop: 0 6
# Short-Description: Start screen session with l1fwd software
# Description:
### END INIT INFO
. /etc/default/rcS
case "$1" in
start)
/usr/bin/screen -d -m -c /etc/osmocom/screenrc-l1fwd
;;
stop)
echo "This script doesn't support stop"
exit 1
;;
restart|reload|force-reload)
exit 0
;;
show)
;;
*)
echo "Usage: sysmobts {start|stop|show|reload|restart}" >&2
exit 1
;;
esac

View File

@@ -1,13 +0,0 @@
#!/bin/sh
PID=$$
echo "-1000" > /proc/$PID/oom_score_adj
trap "{ kill 0; kill -2 0; }" EXIT
while [ -f $1 ]; do
(echo "0" > /proc/self/oom_score_adj && exec nice -n -20 $*) &
LAST_PID=$!
wait $LAST_PID
sleep 10s
done

View File

@@ -1,18 +0,0 @@
#!/bin/sh
PID=$$
echo "-1000" > /proc/$PID/oom_score_adj
trap "kill 0" EXIT
while [ -e /etc/passwd ]; do
cat /lib/firmware/sysmobts-v?.bit > /dev/fpgadl_par0
sleep 2s
cat /lib/firmware/sysmobts-v?.out > /dev/dspdl_dm644x_0
sleep 1s
echo "0" > /sys/class/leds/activity_led/brightness
(echo "0" > /proc/self/oom_score_adj && exec nice -n -20 $*) &
LAST_PID=$!
wait $LAST_PID
sleep 10s
done

View File

@@ -1,3 +0,0 @@
chdir /tmp
screen -t BTS 0 /etc/osmocom/respawn.sh /usr/bin/l1fwd-proxy
detach

View File

@@ -1,5 +0,0 @@
chdir /tmp
screen -t BTS 0 /etc/osmocom/respawn.sh /usr/bin/osmo-bts-sysmo -c /etc/osmocom/osmo-bts.cfg -r 1 -M
screen -t PCU 1 /etc/osmocom/respawn-only.sh /usr/bin/osmo-pcu -c /etc/osmocom/osmo-pcu.cfg -e
screen -t MGR 2 /etc/osmocom/respawn-only.sh /usr/bin/sysmobts-mgr -n -c /etc/osmocom/sysmobts-mgr.cfg
detach

View File

@@ -24,5 +24,9 @@ if ENABLE_LC15BTS
SYSTEMD_SERVICES += osmo-bts-lc15.service lc15bts-mgr.service
endif
if ENABLE_OC2GBTS
SYSTEMD_SERVICES += osmo-bts-oc2g.service oc2gbts-mgr.service
endif
systemdsystemunit_DATA = $(SYSTEMD_SERVICES)
endif # HAVE_SYSTEMD

View File

@@ -3,11 +3,8 @@ Description=osmo-bts for LC15 / sysmoBTS 2100
[Service]
Type=simple
ExecStartPre=/bin/sh -c 'echo 1 > /sys/class/leds/usr0/brightness'
ExecStartPre=/bin/sh -c 'echo 1 > /sys/class/leds/usr1/brightness'
ExecStart=/usr/bin/osmo-bts-lc15 -t 2 -s -c /etc/osmocom/osmo-bts-lc15.cfg -M
ExecStopPost=/bin/sh -c 'echo 1 > /sys/class/leds/usr0/brightness'
ExecStopPost=/bin/sh -c 'echo 0 > /sys/class/leds/usr1/brightness'
RuntimeDirectory=osmo-bts
Restart=always
RestartSec=2
RestartPreventExitStatus=1

View File

@@ -3,11 +3,8 @@ Description=osmo-bts for OC-2G
[Service]
Type=simple
ExecStartPre=/bin/sh -c 'echo 1 > /sys/class/leds/usr0/brightness'
ExecStartPre=/bin/sh -c 'echo 1 > /sys/class/leds/usr1/brightness'
ExecStart=/usr/bin/osmo-bts-oc2g -s -c /etc/osmocom/osmo-bts.cfg -M
ExecStopPost=/bin/sh -c 'echo 1 > /sys/class/leds/usr0/brightness'
ExecStopPost=/bin/sh -c 'echo 0 > /sys/class/leds/usr1/brightness'
ExecStart=/usr/bin/osmo-bts-oc2g -s -c /etc/osmocom/osmo-bts-oc2g.cfg -M
RuntimeDirectory=osmo-bts
Restart=always
RestartSec=2
RestartPreventExitStatus=1

532
debian/changelog vendored
View File

@@ -1,3 +1,535 @@
osmo-bts (1.2.0) unstable; urgency=medium
[ Oliver Smith ]
* Cosmetic: virtual: l1sap.c: fix typos
* virtual: set link quality for GSMTAP_CHANNEL_RACH
* pcu_sock: fix endian-swapped CellID
* gitignore: add oc2g generated files
* log: set L1 SAPI log context
* vty: add "logging filter l1-sapi"
* vty.c: don't ignore get_string_value() errors
* vty.c: avoid coverity BAD_SHIFT issues
* osmo-bts-virtual.cfg: ms-power-control dsp -> osmo
[ Harald Welte ]
* ETWS Primary Notification via P1 Rest Octets
* pcu_interface: Forward ETWS Primary Notification to PCU
* doc: Update Abis manual RSL section with ETWS related infomration
* osmo-bts-trx/scheduler: prevent uninitialized memory access
* osmo-bts-trx: migrate to new generic ECU abstraction
* rach_pass_filter(): Add information about channel type
[ Vadim Yanitskiy ]
* common/rsl.c: fix possible NULL-pointer dereference
* osmo-bts-trx/scheduler: fix tx_tch_common(): do not send AMR BFI twice
* osmo-bts-trx/scheduler: add FIXME note about FACCH/H and BFI
* osmo-bts-trx/scheduler: fix: check rc of osmo_ecu_frame_out()
* scheduler: fix handling of PTCCH/U and PTCCH/D logical channels
* osmo-bts-trx/scheduler: also detect TSC for Access Bursts on PDCH
* common/l1sap: increase ToA precision for packet Access Bursts
* L1SAP: use RSL_CHAN_* definitions from libosmogsm
* L1SAP: also consider RSL_CHAN_OSMO_CBCH8 as CBCH
* L1SAP: clarify debug messages in rach_pass_filter()
* L1SAP: do not pass unused parameter to l1sap_handover_rach()
* L1SAP: refactor handling of Access Bursts on PDCH
* L1SAP: properly handle 11-bit encoded RACH.ind in gsmtap_ph_rach()
* L1SAP: use the actual ARFCN for outgoing PCUIF messages
* L1SAP: fix gsmtap_pdch(): there can be no DATA.ind on PTCCH/U
* L1SAP: use GSMTAP_CHANNEL_PDTCH for PDTCH blocks by default
* L1SAP: there can be no DATA.ind primitives on PTCCH/U, reject them
* README.md: update osmo-bts-trx specific limitations
* osmo-bts-trx/scheduler: fix: print the last frame number in rx_data_fn()
* osmo-bts-trx: general handling of NOPE / IDLE indications
* osmo-bts-trx/trx_if.c: fix: always initialize bi->burst_len for NOPE.ind
* osmo-bts-trx/trx_if.c: also print both RSSI and ToA256 for NOPE.ind
* osmo-bts-trx/trx_if.c: fix: NOPE.ind also contains C/I field
* pcuif_proto.h: extend RACH.ind with TRX and timeslot number fields
* common/vty.c: fix: properly assert() the result of get_string_value()
* common/abis.c: pass gsm_bts_trx to e1inp_sign_link_create()
* common/abis.c: use tall_bts_ctx as talloc-context for libosmo_abis_init()
* osmo-bts-trx/vty: ensure backwards compatibility with older config files
[ Pau Espin Pedrol ]
* bts-trx: Log case where no SETFORMAT is sent
* bts-trx: Change super verbose IDLE ind not-supported line to DEBUG
* doc: bts-models.adoc: Fix typos in rts-advance section
* bts-trx: vty: Use API to get poweron state
* bts.h: Remove non-existent function definitions
* scheduler.c: Move some message log level to DEBUG
* scheduler: Use OSMO_ASSERT instead of abort
* l1sap: Log conn dropped due to radio link counter timeout
* struct gsm_bts: Add model_priv pointer handing bts_model specific data
* bts-trx: Allocate struct osmo_trx_clock_state as part of bts-trx private data
* bts-trx: vty: Print phy link state in cmd 'show transceiver'
* bts-trx: trx_set_bts(): Avoid double loop by checking current trx
* bts-trx: Rework code handling poweron state
* bts-trx: Don't reset transceiver_available in scheduler_trx.c
* bts-trx: Get rid of messy transceiver_available state handler
* bts-trx: Drop unused func check_transceiver_availability()
* bts-trx: Log TRXC and TRXD socket recv()/send() failures
* bts-trx: Time out if no clock ind recvd after RSP POWERON
* cosmetic: bts-trx: document variable power level
* bts-trx: loops.c: Take into account RSL CHAN ACT ms power level limits
* loops.h: Fix missing include for struct l1sched_trx
* power_control.c: Take into account RSL CHAN ACT ms power level limits
* cosmetic: l1sap.c: Fix typo
* rsl: Assign recv pwr to lchan's max ms power
* bts-trx: Implement MS Power control loop calculations using dBm instead of ctl levels
* rsl: Fix logged value in rx MS Power Control
* cosmetic: Fix trailing whitespace
* Change gsm_bts_trx field to bool and rename it
* Change gsm_lchan field fixed to bool
* rsl: Remove unneeded duplicate reset on some lchan fields
* Move and rename gsm_lchan.ms_power field
* bts-trx: loops.c: Avoid always clamping MS power to MS power class 1
* power_control.c: Apply latests improvements from loops.c
* power_control.c: Log rx current and target signal levels
* power_control.c: Fix ms pwr ctrl skipped if MS doesn't support announced MS Power Level
* Introduce BTS feature BTS_FEAT_MS_PWR_CTRL_DSP
* power_control.c: Don't use announced MS Power level as input for loop calculations
* power_control.c: Limit speed of announced MS Power Level value changes
* scheduler_trx.c: cast ptrdiff value to fix printf format
* bts-trx: Drop low layer MS Power Control Loop algo
* rsl_rx_chan_act: Apply bitmask when parsing IE MS_POWER
* rsl: Clarify when autnonoums MS Power Ctrl Loop is used
* power_control.c: Log maximum allowed MS Power Level
* power_control.c: Clarify loop algo vars and use correct ones during log
* l1sap: is_fille_frame(): verify len of data compared
[ Martin Hauke ]
* Fix common misspellings and typos
* Rename variable: CALIB_SUCESS -> CALIB_SUCCESS
[ Philipp Maier ]
* scheduler_trx: use gsm0502_fn_remap() to calculate frame number
* scheduler_trx: initalize n_errors, n_bursts_bits, n_bits_total
* scheduler_trx.c: avoid division by zero when calculating BER
* rsl: ensure measurement reports are sent
* l1sap.c: ensure ms power control loop is running
-- Pau Espin Pedrol <pespin@sysmocom.de> Fri, 03 Jan 2020 17:18:44 +0100
osmo-bts (1.1.0) unstable; urgency=medium
[ Daniel Willmann ]
* Rename oc2g config file to match new naming scheme
* dump_docs: Use new config file naming scheme
* systemd: Install OC2G service files with autotools
* doc/examples: Install OC2G config files with autotools
* osmo-bts-oc2g: Fix status LED responsibilities
* osmo-bts-lc15: Change LED behaviour to be the same as oc2g
* manuals: Add script to regenerate counter/vty documentation
* manuals: Add counter documentation
* manuals: Update vty documentation
[ Harald Welte ]
* Bump version: 0.8.1.199-5c93-dirty → 1.0.0
* scheduler_trx: Fix erroneous multiply-by-four
* OML: some more comments on what functions do
* OML: Return attributes in ACK/NACK messages
* OML: Ensure MOs are initialized with valid "Administrative State'
* OML: Don't overwrite MO instance before oml_tx_failure_event_rep()
* OML: remove double-logging on oml_tx_failure_event_rep()
* OML: send proper OML alerts in case of errors
* OML: Reduce code duplication in down_mom/down_fom
* OML: Report short messages even for invalid TRX numbers in down_fom()
* OML: Use 'const struct abis_oml_mo *' whenever users only read
* OML: Reject segmented OML messages
* OML: Properly reject short messages and truncate over-long messages
* OML: Work around OsmoBSC sending "GET ATTRIBUTES" with short length
* OML: Store merged attributes of IPA OML Managed Objects
* OML: Don't advertise baseband transceiver as UNLOCKED at startup
* OC-2G: Nominal transmit power is 25 dBm, not 40
* rsl.c: Add missing #include of gsm0808.h
* Forward GPRS SUSPEND REQ from DCCH to PCU socket
* handle NULL return from rate_ctr_group_alloc()
* rsl: Send RSL Error Report in case of unknown/unsupported msg_type
* rsl: Include Channel Nr and Link ID in Error reports whenever possible
* RSL: Reject RLL messages for lchans that are not active yet
* RSL: Fix off-by-one error when parsing SACCH INFO IE in RSL CHAN ACT
* cbch: Implement handling of "Schedule" message
* cbch: Refactor get_smscb_block() / remove smscb_msg.next_seg
* cbch: Log every RSL SMSCB COMMAND with type and number of blocks
* cbch: Implement support for DEFAULT message
* cbch: Fix memory leak and send error message on invalid SMSCB command
* cbch: Support Extended CBCH
* cbch: Keep SMSCB queue length counter
* manual: We now support RSL CBCH LOAD INDICATION
* manual: SMSCB BROADCAST COMMAND has no limitations anymore
* README.md: Mention LimeSDR as SDR device
* sysmo: Fix "nominal power" / BS power display in VTY
* cbch: Add counters; queue length limits and CBCH LOAD reporting
* cbch: Improve verbosity and extend logging; Always indicate BASIC/EXTD CBCH
* Use LOGPLCHAN whenever possible
* rsl.adoc: DELETE INDICATION is implemented since Feb '18
* RSL: Fix logic about fixed/dynamic MS power control in MS POWER COMMAND
* rsl: Implement parsing of BS Power Control message
* rsl: MS POWER COCNTROL isn't (only) about "forcing" power levels
* load_indication: Fix missing re-set of RACH parameters
* l1sap: Correctly count RACH slots in calc_exprd_rach_frames()
* l1sap: Fix calculation of expired RACH slots in case of missing frame numbers
* oml: Print more context from FOM Header or using MO
* oml: Have one generic log message for all transmitted messages
* Add severity to OML FAILURE EVENT REPORT
* Fix passing of RR SUSPEND REQ from DCCH to PCU socket
* clear GPRS indicator in SI3 while PCU is disconnected
* trx: Update documentation for fn-advance and rts-advance
* l1sap: Compute statistics on FN advance in PH-RTS.ind
* [correctly] use the LAPDm T200 values received via OML
* Update T200 timer default values
* lapdm: Use new libosmocore API to ensure per-channel-type N200 values
* sysmo/l1_if.c: Annotate fall-through in switch statement
* osmo-bts-trx: Don't increment rssi_valid_count twice
* osmo-bts-trx: Don't attemtp to adjust MS power if fixed
* scheduler_trx: Handle negative return of gsm0503_tch_hr_decode()
[ Vadim Yanitskiy ]
* common/vty.c: fix 'cfg_phy_no_inst_cmd' command description
* common/oml.c: fix: properly push abis_nm_ipa_magic
* common/pcu_sock.c: fix possible memleaks in pcu_sock_read()
* common/oml.c: constify argument 'trx' of handle_attrs_trx()
* common/oml.c: use proper NACK reason in oml_tx_attr_resp()
* common/oml.c: use proper OML object for Get Attribute Response
* common/oml.c: fix total length calculation in cleanup_attr_msg()
* common/l1sap.c: fix: add missing new line to a debug message
* common/rsl.c: fix size argument in memcmp() call
* common/rsl.c: fix unaligned pointers in rsl_add_rtp_stats()
* common/paging.c: fix unaligned pointer access
* common/oml.c: introduce and use both LOGPFOH and DEBUGPFOH
* common/oml.c: use proper format specifier for uint16_t
* common/oml.c: fix broken debug print in down_mom()
* common/oml.c: refactor Get Attribute Response message generation
* common/oml.c: fix: properly encode NM_ATT_SW_CONFIG
* osmo-bts-trx: distinguish 11-bit Access Bursts by synch. sequence
* osmo-bts-sysmo: fix: indicate BTS_FEAT_CBCH support on OML
* README.md: remove OS#1865 from 'Known limitations'
* common/rsl.c: fix NULL-pointer dereference in rsl_rx_rll()
* osmo-bts-trx/trx_if.c: dropping Tx bursts is a noticeable event
* osmo-bts-trx/l1_if.h: drop unused ho_rach_detect from trx_l1h
* osmo-bts/scheduler.h: cosmetic: use bool for ho_rach_detect
* common/rsl.c: RSL_IE_HANDO_REF is mandatory for handover CHAN ACT
* common/bts.c: bts_supports_cm(): take care about GSM48_CMODE_SIGN
* Use #define RSL_CHAN_RACH for RSL Channel Number of RACH
* common/scheduler.c: refactor description of TRXC_* lchans
* osmo-bts-trx/trx_if.c: use osmo_loadXXbe() for TDMA FN and ToA256
* osmo-bts-trx/trx_if.c: rename and clarify TRX_MAX_BURST_LEN
* osmo-bts-trx/trx_if.c: introduce TRXD header version handling
* osmo-bts-trx/trx_if.c: introduce TRXD header version 0x01 support
* osmo-bts-trx/trx_if.c: drop RSSI / ToA debugging code
* osmo-bts-trx/trx_if.c: properly describe TRXD messages in logs
* osmo-bts-trx/trx_if.c: add TRXD header version negotiation
* osmo-bts-trx/trx_if.c: encode actual TRXD header version
* osmo-bts-trx/scheduler: pass trx_ul_burst_ind to lchan handlers
* osmo-bts/scheduler: provide actual C/I values to OsmoPCU
* osmo-bts-trx/scheduler: rx_rach_fn(): use optional TSC info from TRX
* osmo-bts-trx/scheduler: rx_rach_fn(): clarify handover RACH handling
* osmo-bts-trx/scheduler: rx_rach_fn(): enrich debug message
* common/rsl.c: fix: properly handle SI3 Rest Octets
* Clarify and refactor link quality (C/I) handling
* Move Access Burst link quality handling to L1SAP
* osmo-bts-trx/scheduler: rx_rach_fn(): provide actual C/I ratio to L1SAP
* osmo-bts-trx/scheduler: rx_data_fn(): provide actual C/I ratio to L1SAP
[ Max ]
* osmo-bts-trx: add extended (11-bit) RACH support
* Log lchan kind on PCU-related error
* Enable statsd support
* Make gsm_pchan2chan_nr() static
* Constify pcu_rx_*() parameters
[ Philipp Maier ]
* scheduler_trx: use stored fn for pdtch data indications
* oc2g: remove unused define constant FACTORY_ROM_PATH
* lc15: remove unused define constant FACTORY_ROM_PATH
* oml: make oml_tx_failure_event_rep() public
* oc2gbts_mgr_vty: remove calls to vty_install_default()
* oc2g: l1if: delay trx initialization to avoid race condition
* oc2gbts_mgr: use msgb_talloc_ctx_init() instead of msgb_set_talloc_ctx()
* oc2g: generate failure event report in case of bad calibration
* oc2g: change log level for calibration file errors to FATAL
* vty: add function gsmnet_from_vty() to vty.h
* main: remove wrong call to oml_fail_rep() on SIGUSR1/2 and SIGABRT
* oml: use oml_tx_failure_event_rep() instead of oml_fail_rep()
* oml: use oml_tx_failure_event_rep() instead of signals to SS_FAIL
* l1_if: add include for missing header file
* oc2gbts_mgr_calib: don't use fsync() on *FILE pointer
* oc2gbts_mgr_calib: do not return NULL on integer function
* oc2gbts_mgr: use osmo_init_logging2() instead of osmo_init_logging()
* pcu_sock: use %zu conversion specifier for printing sizeof() result
[ Pau Espin Pedrol ]
* oc2g: Fix compilation error (comment mark inside comment)
* oc2g: Add get_hwversion_desc to header file
* oc2g: Cleanup of get_hwversion_desc
* oc2g: led_sleep_cb: pass correct ptr to llist_move_tail
* oc2g: fsync requires fd instead of file stream
* oc2g: Remove unused variables
* oc2g: Remove unused static function
* oc2g: vty: Compilation error fixes due to commented code
* contrib: Remove deprecated screen script helpers
* bts-trx: trx_if.c: Introduce logging macro LOGPPHI
* gsm_data_shared.h: Remove unused loc_list from struct gsm_bts
* bts: Bypass T200 DCCH values for CCCH
* bts-trx: Introduce VTY command osmotrx trxd-max-version
* trx: Use LOGPPHI instead of LOGP in some more messages
* Remove undefined param passed to {logging,osmo_stats}_vty_add_cmds
* configure.ac: Require libosmocore 1.2.0
[ Alexander Huemer ]
* Remove 11-bit RACH support from 'Known Limitations'
[ Oliver Smith ]
* debian: create -doc subpackage with pdf manuals
* Revert "debian: create -doc subpackage with pdf manuals"
* debian: create -doc subpackage with pdf manuals
* contrib/jenkins.sh: run "make maintainer-clean"
[ Neels Hofmeyr ]
* lc15,sysmo,oc2g: fix dsp-trace-flag command
[ Eric Wild ]
* revert changes to T200
* RSL: Fix fixed MS power control in RSL CHAN ACTIV
[ Thorsten Alteholz ]
* fix spelling stuff mentioned by lintian
-- Pau Espin Pedrol <pespin@sysmocom.de> Wed, 07 Aug 2019 15:59:02 +0200
osmo-bts (1.0.0) unstable; urgency=medium
[ Stefan Sperling ]
* let osmo-bts log a special notice if OML connection is closed early
* log reception of PCU_IF_MSG_PAG_REQ messages from osmo-pcu
* update sysinfo copies in all lchans upon SACCH FILL
* preserve lchan-specific SI overrides on SACCH FILL
* fix timespec subtraction in compute_elapsed_us()
* fix conditions for sending fill frames during RTS IND
* send TCH/F fill frames in DTX mode (WIP)
* Revert "send TCH/F fill frames in DTX mode (WIP)"
* prevent potential NULL dereference in virtbts's tx_tchh_fn
* properly initialize si3 in test_is_ccch_for_agch_setup()
* add missing check of osmo_wqueue_enqueue() return value
[ Harald Welte ]
* scheduler_trx: Add reminders to use libosmocore functions
* cosmetic: it's n_r in check_for_first_ciphrd(), not n_s
* Add min/max/std-dev measurement reporting for TOA256
* debian/rules: Don't overwrite .tarball-version
* CBCH: Fix rejecting SMS-CB related RSL messages
* [sysmo,lc15]: Consider CBCH channel combinations in chan_nr_by_sapi()
* CBCH: Move processing via L1SAP
* CBCH: Implement CBCH support for osmo-bts-{trx,virtual}
* CBCH: Use llist_first_entry_or_null() instead of reinventing it
* l1sap/scheduler: Consistently print chan_nr as hex number
* CBCH: Fix CBCH via L1SAP for osmo-bts-{sysmo,octphy,litecell15}
* get_lchan_by_chan_nr(): Fix resolution of CBCH
* CBCH: Add FIXME comments on queue overflow/underflow handling
* CBCH: sprinkle some OMSO_ASSERT() and guard against talloc failure
* CBCH: Fix CBCH implementation for osmo-bts-trx
* CBCH: Some more scheduler_mframe cleanup
* ensure all config file examples are well-formed
* lc15bts_mgr_vty: Ensure writing well-formed config files
* paging_test: Fix AGCH/PCH split test for second half of 102 multiframe
* Fix computing CCCH block number from frame number
* sysmo, virtual: properly handle BS-AG-BLKS-RES as received from BSC
* scheduler_trx.c: Switch to osmo_timerfd() of libosmocore >= 0.12.0
* initial checkin of manuals to public repo
* Add link to Asciidoc source code of manual
* spelling: message discriminator, not descriminator
* osmobts-abis: Add Revision log regarding dynamic cannels
* Documentation on AMR RTP in case of DTX
* rtp-amr.adoc: TCH/AFS Uplink
* rtp-amr.adoc: TCH/AFS Downlink: Inhibiting
* rtp-amr: TCH/AHS Uplink: FACCH/H During DTX
* rtp-amr.adoc: New TCH/AHS downlink chapters
* rtp-amr.adoc: Fixes to Message Sequence Charts
* update osmo-bts-virtual documentation, now that code is merged
* vty-ref: Update URI of docbook 5.0 schema
* osmo-bts-trx/loops.c: Add comments documenting TA + MS power control loop
* osmo-bts-trx/loops.[ch]: Make functions "void" if they always return 0
* osmo-bts-trx/loops.c: Use lchan name based logging
* osmo-bts-trx/loops.c: Make code control flow more readable
[ Philipp Maier ]
* rtp: make port range configurable, assign correct port numbers
* octphy: add support for 16x oversampling mode
* cosmetic: separate measurement testcase definitions
* cosmetic: unify measurement sample handling in one function
* measurement: make sure state is reset on chan act.
* measurement: make sure measurement interval end is detected
* measurement: fix measurement interval end detection
* osmo_mcast_sock: make sure SO_REUSEADDR is applied
* cosmetic: fix sourcecode formatting
* cosmetic: remove wrong comment
* measurement: add unit tests for is_meas_complete()
* measurement: fix sub frame table for TCH/H, SS1
* measurement: add unit tests for ts45008_83_is_sub()
* measurement: fix is_meas_overdue() and increase testcoverage
* cosmetic: rename *_meas_rep_fn10* to *_meas_rep_fn10*_by_*s
* cosmetic: test_is_meas_overdue() does not test is_meas_complete()
* measurement: substitue missing measurements
* measurement: add SUB measurements in test_lchan_meas_process_measurement
* paging: add unit-test to check different bs_ag_blks_res settings
* measurement: display fn_mod when measuremnet is added
* cosmetic: fix typo in comment
* measurement: remove missed interval end detection
* measurement: fix unit-test test_lchan_meas_process_measurement
[ Pau Espin Pedrol ]
* bts.c: Log name of RR msg type instead of value
* bts.c: Add missing include for gsm48_rr_msg_name
* bts_agch_enqueue: Decrease queue len hard_limit from 1000 to 100
* compact AGCH queue: Drop too msg diff than IMM_ASS_REJ
* Send DELETE_IND when dropping Imm Assign pending message
* lc15: Use correct type for hLayer1 field
* lc15: Fix incorrect cast of hLayer1
* pcu_sock: Log event pcu_sock created
* l1_if.c: Move decl of vars used in conditional macro
* sysmo: vty: Add missing include for lchan_deactivate
* sysmo: Fix memcmp in RF-MUTE.req for superfemto < 3.6.0
* sysmo: l1if_mute_rf: Declare vars inside ifdef section
* sysmo: l1_if.c: Avoid decl of unused vars and funcs with femtobts_v2.7 build
* sysmo: calib_file.c: Avoid decl of unused vars and funcs with femtobts_v2.7 build
* jenkins_*.sh: add --enable-werror to configure flags
* doc: Move calypsoBTS example into trx subdir
* build: Install example cfg files
* debian: Package installed example doc files
* Remove unneeded direct libortp dependency
* debian: Make osmo-bts-* packages conflict with old osmo-bts package
* debian: Create dbg package for osm-bts-virtual
* rsl: Use value_string to print encryption algo name
* l1sap: add_l1sap_header: Compact msgb_push ret assignment
* sched: Log RX->RTP packet like we do in add_l1sap_header
* scheduler: Log error on fn jump
* trx: scheduler: Keep RTP clock up to date while in DTXu pause
* Move systemd service to contrib/systemd
* Install systemd services with autotools
* Install sample cfg file to /etc/osmocom
* doc/examples/Makefile: Install bts-mgr cfg files used by systemd services
* lc15: vty: Add missing include for lchan_deactivate
* lc15: fsync requires fd instead of file stream
* lc15: rewrite and refactor code to print hwversion description
* lc15: led_sleep_cb: pass correct ptr to llist_move_tail
* abis: inp_s_cbfn: Improve logging signal related information
* lchan_meas_check_compute: Log value during incorrect num of SUB measurementes detected
* l1sap: Log name of chan_nr instead of hex value
* rsl_rx_chan-activ: Improve logging information
* gsm_pchan2chan_nr: Fix conversion of CCCH_LCHAN
* Convert lchan CCCH_LCHAN to chan_nr BCCH and viceversa
* {oc2g,sysmo}-mgr-calib: Fix build against gpsd >= 3.18
* bts: Allocate TRX for BTS dynamically, deprecate -t
* bts-trx: trx_if: Use struct to store CTRL msg parsed responses
* bts-trx: setup timer once at creation time
* common: Implement OML for trx_set_available(1)
* bts-trx: Allow re-try without exit if POWERON fails in osmo-trx
* bts: Fix TRX0 param initialization
* rsl: Log lchan state during dynts PDCH->TCH
* rsl: Avoid sending ipa PDCH DEACT NACK followed by ACK
* bts-trx: early return on POWERON success
* cosmetic: fix whitespace
* bts_model: Allow TS connect to be processed asynchronously
* OsmoBTS/chapters/configuration.adoc: Add bts index in example
* OsmoBTS: Update osmotrx ip to diff between local and remote
* rtp-amr: Describe requirement to recieve all PH-DATA.ind events
* rtp-amr: Fix typo and trailing whitespace
* Allow easily disabling GFDL references
* OsmoBTS: bts-models: Add Lime Microsystems devices as supported osmo-trx
* Introduce chapter trx_if.adoc and add it to OsmoTRX and OsmoBTS
* bts: Fix typo
* oc2g: Fix headers missing during make distcheck
* bts-trx: (n)ack PDCH DEACT only after TRX answered SETSLOT
* sysmobts_mgr: Prepare code for gpsd < 2.96 support
* sysmobts_mgr: Add support for gpsd < 2.96
* rsl: Send PDCH ACT NACK if TCH chan is still active
[ Vadim Yanitskiy ]
* Clarify frame loss counter for l1sched_chan_state
* osmo-bts-trx/l1_if.c: cosmetic: fix typo in debug msg
* common/rsl.c: tweak log message in lapdm_rll_tx_cb()
* contrib/jenkins_*.sh: drop rudimentary '--with-osmo-pcu'
* common/pcu_sock.c: cosmetic: explicitly address lchan
* common/scheduler.c: track TDMA frame loss per logical channels
* common/vty.c: fix deprecated osmo_str2lower() usage
* Fix deprecated gsm_arfcn2band(), use gsm_arfcn2band_rc()
[ Neels Hofmeyr ]
* cosmetic: abis.c: typo "exixt"
* fix ip.access dyn TS for osmo-bts-trx
* fix RSL Chan Mode Modif for dyn TS
* vty: mark 'rtp bind-ip' deprecated, not hidden
* Importing history from osmo-gsm-manuals
* OsmoBTS: typo x2 ('Objects Classes' -> 'Object Classes')
* OsmoBTS: fix typos, streamline language style
* OsmoBTS: s/content of this attribute/this attribute/
* OsmoBTS: explain IEs marked 'ignored' *and* 'Received'
* abis/oml.doc: remove duplicate sentence part
* OsmoBTS: typos
* OsmoBTS: wording tweak
* OsmoBTS: hardware support: remove dup, tweak wording
* Document dynamic channels on Abis, both IPA and Osmocom style
* OsmoBTS/abis/rsl: fix subtitle for ladder diagram of osmo dyn switchover
* OsmoBTS/abis/dyn_ts_osmocom_style.msc: adjust PDCH Act ack
* OsmoBTS/abis/rsl.adoc: fix missing section header
* OsmoBTS/chapters/dynamic-timeslots.adoc: Remove obsolete links
* osmobts-usermanual.adoc: fix link to abis.adoc chapter
* OsmoBTS/chapters/configuration.adoc: fix index numbering
* OsmoBTS/abis/rsl: cosmetic: 'IPA style'
* OsmoBTS/abis/rsl: add missing info for Osmocom Dyn Channels
* make clean: also remove generated image files
* add 'make check' target
* OsmoBTS/abis/rsl: combine separate dyn ts sections
* fix 'make clean': shell glob, ignore failure
* OsmoBTS/abis/rsl: split dyn TS ladder diagrams to fit on page
* fix build: abis: re-add dependencies
* dynamic timeslots: add BSC level config instructions
* refactor Makefile build rules, don't use the FORCE
[ Keith Whyte ]
* log: add error log for RSL Chan Mode Modif
* fix handling of odd pchans in bts_supports_cm()
[ Omar Ramadan ]
* Add OC-2G BTS sources
[ Max ]
* osmo-bts-trx: print TRX socket addresses in 'show transceiver'
* Fix type mismatch
* Drop unused function
* Add OsmoBTS control interface description
* Move RTP AMR doc to top level
* Add DTX implementation details to RTP AMR
* Sync DTX FSM with OsmoBTS code
[ Holger Hans Peter Freyther ]
* OsmoBTS: Fix the author name and mail address
[ Jonathan Brielmaier ]
* fix various typos across all manuals
[ Daniel Willmann ]
* Add section about configuring power-ramping
* OsmoBTS: Print VTY command in fixed-width font
* OsmoBTS: Fix typo
[ Alexander Couzens ]
* OsmoBTS: add vty reference documentation
* OsmoBTS: generate osmobts-abis.pdf again
[ Ivaylo Kostov ]
* BSC,BTS: add diagrams of PCU-BTS-NITB-SGSN relationships
[ Philipp ]
* Describe how to run multiple instances of osmo-nitb and osmo-bts
[ Oliver Smith ]
* build manuals moved here from osmo-gsm-manuals.git
* Fix DISTCHECK_CONFIGURE_FLAGS override
* contrib/jenkins_*.sh: build and publish manuals
* contrib: fix makedistcheck with disabled systemd
-- Harald Welte <laforge@gnumonks.org> Sun, 20 Jan 2019 21:13:37 +0100
osmo-bts (0.8.1) unstable; urgency=medium
[ Neels Hofmeyr ]

12
debian/control vendored
View File

@@ -11,7 +11,8 @@ Build-Depends: debhelper (>= 9),
libosmocore-dev,
libosmo-abis-dev,
libgps-dev,
txt2man
txt2man,
osmo-gsm-manuals-dev
Standards-Version: 3.9.8
Vcs-Browser: http://git.osmocom.org/osmo-bts/
Vcs-Git: git://git.osmocom.org/osmo-bts
@@ -48,3 +49,12 @@ Priority: extra
Depends: osmo-bts-virtual (= ${binary:Version}), ${misc:Depends}
Description: Debug symbols for the osmo-bts-virtual
Make debugging possible
Package: osmo-bts-doc
Architecture: all
Section: doc
Priority: optional
Depends: ${misc:Depends}
Description: ${misc:Package} PDF documentation
Various manuals: user manual, VTY reference manual and/or
protocol/interface manuals.

1
debian/osmo-bts-doc.install vendored Normal file
View File

@@ -0,0 +1 @@
usr/share/doc/osmo-bts-doc/*.pdf

6
debian/rules vendored
View File

@@ -16,7 +16,7 @@ override_dh_strip:
dh_strip --package=osmo-bts-trx --dbg-package=osmo-bts-trx-dbg
override_dh_auto_configure:
dh_auto_configure -- --enable-trx --with-systemdsystemunitdir=/lib/systemd/system
dh_auto_configure -- --enable-trx --with-systemdsystemunitdir=/lib/systemd/system --enable-manuals
override_dh_clean:
dh_clean
@@ -26,3 +26,7 @@ override_dh_clean:
# Print test results in case of a failure
override_dh_auto_test:
dh_auto_test || (find . -name testsuite.log -exec cat {} \; ; false)
# Don't create .pdf.gz files (barely saves space and they can't be opened directly by most pdf readers)
override_dh_compress:
dh_compress -X.pdf

View File

@@ -4,7 +4,7 @@ h2. generic
h3. trx.0.thermal-attenuation
The idea of this paramter is to attenuate the system output power as part of
The idea of this parameter is to attenuate the system output power as part of
thermal management. In some cases the PA might be passing a critical level,
so an external control process can use this attribute to reduce the system
output power.

View File

@@ -42,5 +42,14 @@ EXTRA_DIST += $(doc_lc15_DATA)
OSMOCONF_FILES += litecell15/osmo-bts-lc15.cfg litecell15/lc15bts-mgr.cfg
endif
if ENABLE_OC2GBTS
doc_oc2gdir = $(docdir)/examples/osmo-bts-oc2g
doc_oc2g_DATA = \
oc2g/osmo-bts-oc2g.cfg \
oc2g/oc2gbts-mgr.cfg
EXTRA_DIST += $(doc_oc2g_DATA)
OSMOCONF_FILES += oc2g/osmo-bts-oc2g.cfg oc2g/oc2gbts-mgr.cfg
endif
osmoconfdir = $(sysconfdir)/osmocom
osmoconf_DATA = $(OSMOCONF_FILES)

View File

@@ -22,7 +22,6 @@ line vty
!
phy 0
instance 0
osmotrx rx-gain 1
osmotrx ip local 127.0.0.1
osmotrx ip remote 127.0.0.1
osmotrx timing-advance-loop

View File

@@ -21,7 +21,6 @@ line vty
!
phy 0
instance 0
osmotrx rx-gain 1
osmotrx ip local 127.0.0.1
osmotrx ip remote 127.0.0.1
bts 0

View File

@@ -57,5 +57,5 @@ bts 0
power-ramp max-initial 23000 mdBm
power-ramp step-size 2000 mdB
power-ramp step-interval 1
ms-power-control dsp
ms-power-control osmo
phy 0 instance 0

View File

@@ -6,6 +6,7 @@ EXTRA_DIST = dtx.dot \
osmobts-vty-reference.xml \
rtp-amr.adoc \
rtp-amr-docinfo.xml \
regen_doc.sh \
abis \
chapters \
vty
@@ -20,5 +21,6 @@ if BUILD_MANUALS
VTY_REFERENCE = osmobts-vty-reference.xml
include $(OSMO_GSM_MANUALS_DIR)/build/Makefile.vty-reference.inc
OSMO_REPOSITORY = osmo-bts
include $(OSMO_GSM_MANUALS_DIR)/build/Makefile.common.inc
endif

View File

@@ -39,15 +39,18 @@ Specific additions and limitations apply, see the linked sections.
| 8.4.11 | - | MODE MODIFY NEGATIVE ACKNOWLEDGE | -> | Sent
| 8.4.14 | - | RF CHANNEL RELEASE | <- | Received
| 8.4.15 | <<MS_POWER_CONTROL>> | MS POWER CONTROL | <- | Received
| 8.4.16 | - | BS POWER CONTROL | <- | Received
| 8.4.19 | - | RF CHANNEL RELEASE ACKNOWLEDGE | -> | Sent
| 8.4.20 | <<SACCH_INFO_MODIFY>> | SACCH INFO MODIFY | <- | Received
5+<| *COMMON CHANNEL MANAGEMENT MESSAGES*
| 8.5.1 | <<BCCH_INFORMATION>> | BCCH INFORMATION | <- | Received
| 8.5.2 | - | CCCH LOAD INDICATION | -> | Sent
| 8.5.3 | <<CHANNEL_REQUIRED>> | CHANNEL REQUIRED | -> | Sent
| 8.5.4 | - | DELETE INDICATION | -> | Sent
| 8.5.5 | <<PAGING_COMMAND>> | PAGING COMMAND | <- | Received
| 8.5.6 | - | IMMEDIATE ASSIGN COMMAND | <- | Received
| 8.5.8 | <<SMS_BROADCAST_COMMAND>> | SMS BROADCAST COMMAND | <- | Received
| 8.5.8 | - | SMS BROADCAST COMMAND | <- | Received
| 8.5.9 | - | CBCH LOAD INDICATION | -> | Sent
5+<| *TRX MANAGEMENT MESSAGES*
| 8.6.1 | <<RF_RESOURCE_INDICATION>> | RF RESOURCE INDICATION | -> | Sent
| 8.6.2 | <<SACCH_FILLING>> | SACCH FILLING | <- | Received
@@ -78,6 +81,8 @@ Specific additions and limitations apply, see the linked sections.
.3+.| <<pdch_deact>> | <<rsl_pdch_deact>> | RSL PDCH Deactivation | <- | Received
| <<rsl_pdch_deact_ack>> | RSL PDCH Deactivation ACK | -> | Sent
| <<rsl_pdch_deact_nack>> | RSL PDCH Deactivation NACK | -> | Sent
5+<| *COMMON CHANNEL MANAGEMENT MESSAGES*
.3+.| <<etws>> | <<OSMO_ETWS_CMD>> | Osmocom ETWS Command | <- | Received
|===
==== Messages Not Implemented by OsmoBTS
@@ -89,7 +94,6 @@ Specific additions and limitations apply, see the linked sections.
2+<| *DEDICATED CHANNEL MANAGEMENT MESSAGES*
| 8.4.12 | PHYSICAL CONTEXT REQUEST
| 8.4.13 | PHYSICAL CONTEXT CONFIRM
| 8.4.16 | BS POWER CONTROL
| 8.4.17 | PREPROCESS CONFIGURE
| 8.4.18 | PREPROCESSED MEASUREMENT RESULT
| 8.4.21 | TALKER DETECTION
@@ -104,9 +108,7 @@ Specific additions and limitations apply, see the linked sections.
| 8.4.30 | TFO REPORT
| 8.4.31 | TFO MODIFICATION REQUEST
2+<| *COMMON CHANNEL MANAGEMENT MESSAGES*
| 8.5.4 | DELETE INDICATION
| 8.5.7 | SMS BROADCAST REQUEST
| 8.5.9 | CBCH LOAD INDICATION
| 8.5.10 | NOTIFICATION COMMAND
2+<| *TRX MANAGEMENT MESSAGES*
| 8.6.3 | OVERLOAD
@@ -238,18 +240,6 @@ Conforms to 3GPP TS 08.58 § 8.5.5, with these limitations:
NOTE: If adding the identity to the paging queue fails, the BSC is not notified
in any way.
[[SMS_BROADCAST_COMMAND]]
=== SMS Broadcast Command
Conforms to 3GPP TS 08.58 § 8.5.8, with these limitations:
._Broadcast Command_ message IE details
[options="header",cols="10%,30%,60%"]
|===
| TS 08.58 § | IE Name | Handling
| 9.3.44 | SMSCB Channel Indicator | _ignored_
|===
[[RF_RESOURCE_INDICATION]]
==== RF Resource Indication
@@ -356,7 +346,7 @@ See <<rsl_dlcx_ind_msg>>
In the classic data model established by ETSI/3GPP for A-bis, each
timeslot (channel) is configured using a static channel combination by
means of A-bis OML. Particularly in presence of GPRS services, this
is very unflexible and leads to inefficient use of air interface
is very inflexible and leads to inefficient use of air interface
resources.
As such, several methods have been implemented to overcome this
@@ -433,9 +423,9 @@ The activation of PDCH is performed by using the regular 'RSL CHANNEL ACTIVATE'
procedure according to <<CHANNEL_ACTIVATION>>, with these modifications:
* The 'C-bits' part of the 'Channel Number' IE take the non-standard binary
value 11000 (C5 thru C1 as seen in 3GPP TS 08.58 § 9.3.1).
value 11000 (C5 through C1 as seen in 3GPP TS 08.58 § 9.3.1).
* The 'A-bits' part of the 'Activation Type' IE take the non-standard binary
value 1111, with an additional fourth bit (add A4 to A3 thru A1 as seen in
value 1111, with an additional fourth bit (add A4 to A3 through A1 as seen in
3GPP TS 08.58 § 9.3.3; all remaining reserved bits as well as the 'R' bit are
coded as zero).
* The normally mandatory 'Channel Mode' IE is omitted; none of the optional IEs
@@ -467,6 +457,25 @@ include::dyn_ts_osmocom_style1.msc[]
include::dyn_ts_osmocom_style2.msc[]
----
[[etws]]
=== ETWS (Earthquake and Tsunami Warning System)
ETWS as specified in 3GPP TS 23.041 includes not only notification via
SMSCB, but also so-called Primary Notifications (PN). The ETWS PN are
transmitted
* by the BSC to all subscribers with active dedicated channels
* by the BTS on the PCH to all subscribers in idle mode
* by the PCU on the PACCH to all subscribers with active TBF
Unfortunately, 3GPP forgot to update their specifications with any
information as to how the ETWS PN is transmitted from BSC to BTS in
a portable way, and Osmocom had to invent their own non-standard
signaling for it.
See <<OSMO_ETWS_CMD>> for the Osmocom implementation.
=== Message Formats and Contents
[[rsl_crcx_msg]]
@@ -766,6 +775,32 @@ on a IPA style dynamic TCH/F+PDCH channel.
NOTE:: This message is *not* used by Osmocom style dynamic channels
[[OSMO_ETWS_CMD]]
==== Osmocom ETWS Command
This message is sent by the BSC to transfer the ETWS Primary Notification (PN)
from BSC to BTS and enable/disable transmission of ETWS PN by the BTS. For more
information about ETWS, see 3GPP TS 23.041.
If the ETWS PN length is > 0, the BTS will immediately start transmission
of the received ETWS PN on the PCH using P1 Rest Octets. It will also forward
he ETWS PN to the PCU to enable the PCU to transmit it via PACCH on active TBF.
If the ETWS PN length is 0, the BTS will stop any ETWS PN broadcast via the PCH.
The Channel Number IE is set to the Downlink CCCH (PCH).
[options="header"]
[cols="30%,25%,15%,15%,15%"]
|===
| INFORMATION ELEMENT | REFERENCE | PRESENCE | FORMAT | LENGTH
| Message discriminator | 08.58 9.1 | M | V | 1
| Message type | <<own_msg_types>> | M | V | 1
| Channel number | 08.58 9.3.1 | M | TV | 2
| SMSCB Message | 08.58 9.3.42 | M | TLV | 2-58
|===
=== Information Element Codings
[[own_msg_types]]
@@ -788,6 +823,7 @@ indicated in 3GPP TS 08.58 Section 9.1:
| 0x77 | Delete Connection (DLCX) | <<rsl_dlcx_msg>>
| 0x78 | Delete Connection (DLCX) ACK | <<rsl_dlcx_msg_ack>>
| 0x79 | Delete Connection (DLCX) NACK | <<rsl_dlcx_msg_nack>>
| 0x7f | Osmocom ETWS Command | <<OSMO_ETWS_CMD>>
| 0x48 | PDCH Activate | <<rsl_pdch_act>>
| 0x49 | PDCH Activate ACK | <<rsl_pdch_act_ack>>
| 0x4a | PDCH Activate NACK | <<rsl_pdch_act_nack>>

View File

@@ -245,10 +245,53 @@ local (OsmoBTS) or remote (OsmoTRX) side of the UDP flows.
Set the number of frames to be transmitted to transceiver in advance of
current GSM frame number.
GSM is a TDMA (time division multiple access) system on the radio
interface. OsmoTRX is the "clock master" of that in the Osmocom
implementation. It informs OsmoBTS of the current GSM frame
number. However, as there is non-zero delays (UDP packet trnsmission
delay, operating system scheduler delay on both OsmoTRX and OsmoBTS
side, ...), OsmoBTS must compensate for that delay by "advancing"
the clock a certain amount of time.
In other words, if OsmoTRX informs us that the current frame number is N,
we advance it by `fn-advance` and transmit burst data for
`N + fn-advance` towards OsmoTRX.
The fn-advance should be kept as low as possible to avoid additional
delays to the user voice plane as well as to improve the performance
of the control plane (LAPDm) as well as GPRS.
However, fn-advance must be kept sufficiently high to ensure no
underruns on the OsmoTRX side.
The detailed value will depend on your underlying computer systems,
operating system and related tuning parameters. Running OsmoTRX
on a remote host will inevitably require a higher fn-advance then
running it on the same machine, where the UDP packetes are just passed
over the loopback device.
The default value for `fn-advance` is 20 (corresponding to 92
milliseconds).
===== `osmotrx rts-advance <0-30>`
Set the number of frames to be requested from PCU in advance of current
frame number. Do not change this unless you have a good reason!
Set the number of frames to be requested from L1SAP in advance of current
frame number and fn-advance.
The value specified as `rts-advance` is added to the current GSM frame
number as reported by OsmoTRX *and* the `osmotrx fn-advance` in order
to generate the PH-RTS.ind (ready to send indications) across the L1SAP
interface inside osmo-bts. This will trigger the Layer 2 (LAPDm for
the control plane, RTP for the voice plane, and OsmoPCU for GPRS) to
generate a MAC block and input it into the osmo-bts-trx TDMA scheduler.
If OsmoTRX reported N as the current frame number, the actual frame number
reported on L1SAP to higher layers will be computed as follows:
N + fn-advance + rts-advance
The default value of `rts-advance` is 5 (corresponding to 23 milliseconds).
Do not change this unless you have a good reason!
===== `osmotrx rx-gain <0-50>`
@@ -400,7 +443,7 @@ configuration at the BTS configuration file is (as always) very minimal,
as in the GSM network architecture provides almost all relevant
configuration to the BTS from the BSC.
An example configuratin file is provided as part of the osmo-bts source
An example configuration file is provided as part of the osmo-bts source
code: `doc/examples/virtual/osmobts-virtual.cfg`
For more information see

View File

@@ -14,7 +14,7 @@ OsmoBTS software.
=== Command Line Options
Ths OsmoBTS executables (`osmo-bts-sysmo`, `osmo-bts-trx`,
The OsmoBTS executables (`osmo-bts-sysmo`, `osmo-bts-trx`,
`osmo-bts-octphy`, `osmo-bts-litecell15`, ...) share the following
generic command line options:

View File

@@ -0,0 +1,4 @@
[[counters]]
== Counters
include::./counters_generated.adoc[]

View File

@@ -0,0 +1,64 @@
// autogenerated by show asciidoc counters
These counters and their description based on OsmoBTS 0.8.1.346-33ed (OsmoBTS).
=== Rate Counters
// generating tables for rate_ctr_group
// rate_ctr_group table E1 Input subsystem
.e1inp - E1 Input subsystem
[options="header"]
|===
| Name | Reference | Description
| hdlc:abort | <<e1inp_hdlc:abort>> | HDLC abort
| hdlc:bad_fcs | <<e1inp_hdlc:bad_fcs>> | HLDC Bad FCS
| hdlc:overrun | <<e1inp_hdlc:overrun>> | HDLC Overrun
| alarm | <<e1inp_alarm>> | Alarm
| removed | <<e1inp_removed>> | Line removed
|===
// rate_ctr_group table cell broadcast channel
.cbch - cell broadcast channel
[options="header"]
|===
| Name | Reference | Description
| cbch:rcvd_queued | <<cbch_cbch:rcvd_queued>> | Received + queued CBCH messages (Abis)
| cbch:rcvd_dropped | <<cbch_cbch:rcvd_dropped>> | Received + dropped CBCH messages (Abis)
| cbch:sent_single | <<cbch_cbch:sent_single>> | Sent single CBCH messages (Um)
| cbch:sent_default | <<cbch_cbch:sent_default>> | Sent default CBCH messages (Um)
| cbch:sent_null | <<cbch_cbch:sent_null>> | Sent NULL CBCH messages (Um)
|===
// rate_ctr_group table cell broadcast channel
.cbch - cell broadcast channel
[options="header"]
|===
| Name | Reference | Description
| cbch:rcvd_queued | <<cbch_cbch:rcvd_queued>> | Received + queued CBCH messages (Abis)
| cbch:rcvd_dropped | <<cbch_cbch:rcvd_dropped>> | Received + dropped CBCH messages (Abis)
| cbch:sent_single | <<cbch_cbch:sent_single>> | Sent single CBCH messages (Um)
| cbch:sent_default | <<cbch_cbch:sent_default>> | Sent default CBCH messages (Um)
| cbch:sent_null | <<cbch_cbch:sent_null>> | Sent NULL CBCH messages (Um)
|===
// rate_ctr_group table base transceiver station
.bts - base transceiver station
[options="header"]
|===
| Name | Reference | Description
| paging:rcvd | <<bts_paging:rcvd>> | Received paging requests (Abis)
| paging:drop | <<bts_paging:drop>> | Dropped paging requests (Abis)
| paging:sent | <<bts_paging:sent>> | Sent paging requests (Um)
| rach:rcvd | <<bts_rach:rcvd>> | Received RACH requests (Um)
| rach:drop | <<bts_rach:drop>> | Dropped RACH requests (Um)
| rach:handover | <<bts_rach:handover>> | Received RACH requests (Handover)
| rach:cs | <<bts_rach:cs>> | Received RACH requests (CS/Abis)
| rach:ps | <<bts_rach:ps>> | Received RACH requests (PS/PCU)
| agch:rcvd | <<bts_agch:rcvd>> | Received AGCH requests (Abis)
| agch:sent | <<bts_agch:sent>> | Sent AGCH requests (Abis)
| agch:delete | <<bts_agch:delete>> | Sent AGCH DELETE IND (Abis)
|===
== Osmo Stat Items
// generating tables for osmo_stat_items
== Osmo Counters
// generating tables for osmo_counters
// there are no ungrouped osmo_counters

View File

@@ -38,7 +38,7 @@ Typical configurations either use OsmoBTS with OsmoBSC, or with
OsmoNITB, as can be seen in the following figures.
[[fig-gsm-classic]]
.Classic GSM archtiecture using OsmoBTS with OsmoBTS components
.Classic GSM architecture using OsmoBTS with OsmoBTS components
[graphviz]
----
digraph G {

View File

@@ -14,6 +14,10 @@ include::{srcdir}/chapters/interfaces.adoc[]
include::{srcdir}/chapters/control.adoc[]
include::./common/chapters/counters-overview.adoc[]
include::{srcdir}/chapters/counters.adoc[]
include::./common/chapters/vty.adoc[]
include::./common/chapters/logging.adoc[]

17
doc/manuals/regen_doc.sh Executable file
View File

@@ -0,0 +1,17 @@
#!/bin/sh -x
if [ -z "$DOCKER_PLAYGROUND" ]; then
echo "You need to set DOCKER_PLAYGROUND"
exit 1
fi
SCRIPT=$(realpath "$0")
MANUAL_DIR=$(dirname "$SCRIPT")
COMMIT=${COMMIT:-$(git log -1 --format=format:%H)}
cd "$DOCKER_PLAYGROUND/scripts" || exit 1
OSMO_BTS_BRANCH=$COMMIT ./regen_doc.sh osmo-bts 4241 \
"$MANUAL_DIR/chapters/counters_generated.adoc" \
"$MANUAL_DIR/vty/bts_vty_reference.xml"

View File

@@ -95,10 +95,10 @@ msc {
phy => bts [label="PH-DATA.ind GsmL1_TchPlType_Amr (SID_FIRST)"];
bts => mgw [label="RTP (AMR FT=SID,Q=1)"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
phy => bts [label="PH-DATA.ind with empty payload"];
bts -x mgw [label="Suppressed RTP frame"];
@@ -110,10 +110,10 @@ msc {
bts -x mgw [label="Suppressed RTP frame"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
phy => bts [label="PH-DATA.ind GsmL1_TchPlType_Amr (SID_UPDATE)"];
bts => mgw [label="RTP (AMR FT=SID,Q=1)"];
}
@@ -123,7 +123,7 @@ ULSF2:: As per 3GPP TS 05.03 section 3.9.2.4 The last 4 bursts shall not be tran
the SID_FIRST frame is immediately followed by a speech frame. It has been observed that some phone
does not transmit the last 4 bursts even if it is not followed by a speech frame.
ULSU2:: There must be exactly two supressed voice frames between the
ULSU2:: There must be exactly two suppressed voice frames between the
SID_FIRST and the SID_UPDATE, i.e. there's 60ms between SID_FIRST and
SID_UPDATE.
@@ -152,52 +152,52 @@ msc {
phy => bts [label="PH-DATA.ind with empty payload"];
bts -x mgw [label="Suppressed RTP frame"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
phy => bts [label="PH-DATA.ind GsmL1_TchPlType_Amr (SID_UPDATE)"];
bts => mgw [label="RTP (AMR FT=SID,Q=1)"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
phy => bts [label="PH-DATA.ind with empty payload"];
bts -x mgw [label="Suppressed RTP frame"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
phy => bts [label="PH-DATA.ind with empty payload"];
bts -x mgw [label="Suppressed RTP frame"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
phy => bts [label="PH-DATA.ind with empty payload"];
bts -x mgw [label="Suppressed RTP frame"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
phy => bts [label="PH-DATA.ind with empty payload"];
bts -x mgw [label="Suppressed RTP frame"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
phy => bts [label="PH-DATA.ind with empty payload"];
bts -x mgw [label="Suppressed RTP frame"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
phy => bts [label="PH-DATA.ind with empty payload"];
bts -x mgw [label="Suppressed RTP frame"];
@@ -208,10 +208,10 @@ msc {
phy => bts [label="PH-DATA.ind with empty payload"];
bts -x mgw [label="Suppressed RTP frame"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
phy => bts [label="PH-DATA.ind GsmL1_TchPlType_Amr (SID_UPDATE)"];
bts => mgw [label="RTP (AMR FT=SID,Q=1)"];
}
@@ -254,10 +254,10 @@ msc {
...;
--- [label="Once voice is active again"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
phy => bts [label="PH-DATA.ind with empty payload"];
bts -x mgw [label="Suppressed RTP frame"];
@@ -345,10 +345,10 @@ msc {
...;
--- [label="FACCH/F Frame During DTX"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
phy => bts [label="PH-DATA.ind with empty payload"];
bts -x mgw [label="Suppressed RTP frame"];
@@ -368,10 +368,10 @@ msc {
phy => bts [label="PH-DATA.ind FACCH/F"];
bts => mgw [label="FACCH/F"];
ms -x phy [label="Supressed L1 burst", id="ULSF2"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Suppressed L1 burst", id="ULSF2"];
ms -x phy [label="Suppressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
phy => bts [label="PH-DATA.ind GsmL1_TchPlType_Amr (SID_FIRST)"];
bts => mgw [label="RTP (AMR FT=SID,Q=1)"];
...;
@@ -382,7 +382,7 @@ ULSF2:: The sub-blocks 5-8 of SID_FIRST are not transmitted, as all
information bits are contained in sub-blocks 1-4 only
Note:: It has been observed with some phones that the SID_FIRST is not sent following the FACCH/F
frame. If this case occures the No Data Frame and SID_UPDATE order resumes.
frame. If this case occurs the No Data Frame and SID_UPDATE order resumes.
=== TCH/AFS Downlink (Network to MS)
@@ -660,10 +660,10 @@ msc {
phy => bts [label="PH-RTS.ind (TCH)"];
phy <= bts [label="PH-EMPTY-FRAME.req (FACCH/F)"];
phy <= bts [label="PH-EMPTY-FRAME.req (TCH/F)"];
ms x- phy [label="Supressed burst"];
ms x- phy [label="Supressed burst"];
ms x- phy [label="Supressed burst"];
ms x- phy [label="Supressed burst"];
ms x- phy [label="Suppressed burst"];
ms x- phy [label="Suppressed burst"];
ms x- phy [label="Suppressed burst"];
ms x- phy [label="Suppressed burst"];
}
----
@@ -738,8 +738,8 @@ msc {
phy => bts [label="PH-DATA.ind GsmL1_TchPlType_Amr (N)"];
bts => mgw [label="RTP (AMR FT=0..7,Q=1)"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
phy => bts [label="PH-DATA.ind GsmL1_TchPlType_Amr_SidFirstP1", id="ULSF1"];
bts => mgw [label="RTP (AMR FT=SID,Q=1)"];
@@ -753,8 +753,8 @@ msc {
phy => bts [label="PH-DATA.ind with empty payload"];
bts -x mgw [label="Suppressed RTP frame"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
phy => bts [label="PH-DATA.ind GsmL1_TchPlType_Amr (SID_UPDATE)"];
bts => mgw [label="RTP (AMR FT=SID,Q=1)"];
}
@@ -764,7 +764,7 @@ ULSF1:: Only SID_FIRST_P1 contains information so it must be the only one transm
NOTE:: It has been observed that not all phones transmit SID_FIRST_P2 so the PH-DATA.ind GsmL1_TchPlType_Amr_SidFirstP2 is not guaranteed to be sent to the BTS.
ULSU1:: There must be exactly two supressed voice frames between the
ULSU1:: There must be exactly two suppressed voice frames between the
SID_FIRST and the SID_UPDATE, i.e. there's 60ms between SID_FIRST and
SID_UPDATE.
@@ -795,33 +795,33 @@ msc {
phy => bts [label="PH-DATA.ind with empty payload"];
bts -x mgw [label="Suppressed RTP frame"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
phy => bts [label="PH-DATA.ind GsmL1_TchPlType_Amr (SID_UPDATE)"];
bts => mgw [label="RTP (AMR FT=SID,Q=1)"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
phy => bts [label="PH-DATA.ind with empty payload"];
bts -x mgw [label="Suppressed RTP frame"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
phy => bts [label="PH-DATA.ind with empty payload"];
bts -x mgw [label="Suppressed RTP frame"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
phy => bts [label="PH-DATA.ind with empty payload"];
bts -x mgw [label="Suppressed RTP frame"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
phy => bts [label="PH-DATA.ind with empty payload"];
bts -x mgw [label="Suppressed RTP frame"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
phy => bts [label="PH-DATA.ind with empty payload"];
bts -x mgw [label="Suppressed RTP frame"];
@@ -834,8 +834,8 @@ msc {
phy => bts [label="PH-DATA.ind with empty payload"];
bts -x mgw [label="Suppressed RTP frame"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
phy => bts [label="PH-DATA.ind GsmL1_TchPlType_Amr (SID_UPDATE)"];
bts => mgw [label="RTP (AMR FT=SID,Q=1)"];
}
@@ -999,8 +999,8 @@ msc {
...;
ms .. mgw [label="FACCH/H during DTX operation"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
phy => bts [label="PH-DATA.ind with empty payload"];
bts -x mgw [label="Suppressed RTP frame"];
@@ -1026,8 +1026,8 @@ msc {
phy => bts [label="PH-DATA.ind with empty payload"];
bts -x mgw [label="Suppressed RTP frame"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Supressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
ms -x phy [label="Suppressed L1 burst"];
phy => bts [label="PH-DATA.ind GsmL1_TchPlType_Amr_SidFirstP1"];
bts => mgw [label="RTP (AMR FT=SID,Q=1)"];
}

File diff suppressed because it is too large Load Diff

View File

@@ -22,7 +22,7 @@ The start-up procedure of OsmoBTS can be described as follows:
| common | bts_controlif_setup() | Initialization of Control Interface
| bts-specific | bts_model_ctrl_cmds_install()
| common | telnet_init() | Initialization of telnet interface
| common | pcu_sock_init() | Initializaiton of PCU socket
| common | pcu_sock_init() | Initialization of PCU socket
| common | main() | Installation of signal handlers
| common | abis_open() | Start of the A-bis connection to BSC
| common | phy_links_open() | Iterate over list of configured PHY links

View File

@@ -2,4 +2,4 @@ noinst_HEADERS = abis.h bts.h bts_model.h gsm_data.h gsm_data_shared.h logging.h
oml.h paging.h rsl.h signal.h vty.h amr.h pcu_if.h pcuif_proto.h \
handover.h msg_utils.h tx_power.h control_if.h cbch.h l1sap.h \
power_control.h scheduler.h scheduler_backend.h phy_link.h \
dtx_dl_amr_fsm.h
dtx_dl_amr_fsm.h ta_control.h

View File

@@ -30,16 +30,9 @@ int bts_init(struct gsm_bts *bts);
int bts_trx_init(struct gsm_bts_trx *trx);
void bts_shutdown(struct gsm_bts *bts, const char *reason);
struct gsm_bts *create_bts(uint8_t num_trx, char *id);
int create_ms(struct gsm_bts_trx *trx, int maskc, uint8_t *maskv_tx,
uint8_t *maskv_rx);
void destroy_bts(struct gsm_bts *bts);
int work_bts(struct gsm_bts *bts);
int bts_link_estab(struct gsm_bts *bts);
int trx_link_estab(struct gsm_bts_trx *trx);
int trx_set_available(struct gsm_bts_trx *trx, int avail);
void bts_new_si(void *arg);
void bts_setup_slot(struct gsm_bts_trx_ts *slot, uint8_t comb);
int bts_agch_enqueue(struct gsm_bts *bts, struct msgb *msg);
struct msgb *bts_agch_dequeue(struct gsm_bts *bts);
@@ -48,6 +41,7 @@ int bts_ccch_copy_msg(struct gsm_bts *bts, uint8_t *out_buf, struct gsm_time *gt
int is_ag_res);
uint8_t *bts_sysinfo_get(struct gsm_bts *bts, const struct gsm_time *g_time);
void regenerate_si3_restoctets(struct gsm_bts *bts);
uint8_t *lchan_sacch_get(struct gsm_lchan *lchan);
int lchan_init_lapdm(struct gsm_lchan *lchan);
@@ -55,7 +49,7 @@ void load_timer_start(struct gsm_bts *bts);
uint8_t num_agch(struct gsm_bts_trx *trx, const char * arg);
void bts_update_status(enum bts_global_status which, int on);
int trx_ms_pwr_ctrl_is_osmo(struct gsm_bts_trx *trx);
bool trx_ms_pwr_ctrl_is_osmo(struct gsm_bts_trx *trx);
struct gsm_time *get_time(struct gsm_bts *bts);
@@ -64,5 +58,6 @@ int bts_main(int argc, char **argv);
int bts_supports_cm(struct gsm_bts *bts, enum gsm_phys_chan_config pchan,
enum gsm48_chan_mode cm);
#endif /* _BTS_H */
int32_t bts_get_avg_fn_advance(struct gsm_bts *bts);
#endif /* _BTS_H */

View File

@@ -6,10 +6,17 @@
#include <osmo-bts/gsm_data.h>
#include <osmo-bts/bts.h>
enum {
CBCH_CTR_RCVD_QUEUED,
CBCH_CTR_RCVD_DROPPED,
CBCH_CTR_SENT_SINGLE,
CBCH_CTR_SENT_DEFAULT,
CBCH_CTR_SENT_NULL,
};
/* incoming SMS broadcast command from RSL */
int bts_process_smscb_cmd(struct gsm_bts *bts,
struct rsl_ie_cb_cmd_type cmd_type,
uint8_t msg_len, const uint8_t *msg);
int bts_process_smscb_cmd(struct gsm_bts *bts, struct rsl_ie_cb_cmd_type cmd_type,
bool extended_cbch, uint8_t msg_len, const uint8_t *msg);
/* call-back from bts model specific code when it wants to obtain a CBCH
* block for a given gsm_time. outbuf must have 23 bytes of space. */

View File

@@ -15,6 +15,7 @@
#include <osmocom/gsm/rxlev_stat.h>
#include <osmocom/gsm/sysinfo.h>
#include <osmocom/gsm/meas_rep.h>
#include <osmocom/gsm/gsm48_rest_octets.h>
#include <osmocom/gsm/protocol/gsm_04_08.h>
#include <osmocom/gsm/protocol/gsm_08_58.h>
#include <osmocom/gsm/protocol/gsm_12_21.h>
@@ -198,9 +199,6 @@ struct gsm_lchan {
/* State */
enum gsm_lchan_state state;
const char *broken_reason;
/* Power levels for MS and BTS */
uint8_t bs_power;
uint8_t ms_power;
/* Encryption information */
struct {
uint8_t alg_id;
@@ -249,7 +247,7 @@ struct gsm_lchan {
} si;
struct {
uint8_t flags;
/* RSL measurment result number, 0 at lchan_act */
/* RSL measurement result number, 0 at lchan_act */
uint8_t res_nr;
/* current Tx power level of the BTS */
uint8_t bts_tx_pwr;
@@ -322,15 +320,16 @@ struct gsm_lchan {
/* power handling */
struct {
uint8_t current;
uint8_t fixed;
uint8_t max;
bool fixed;
} ms_power_ctrl;
/* Power levels for BTS */
uint8_t bs_power;
struct msgb *pending_rel_ind_msg;
/* ECU (Error Concealment Unit) state */
union {
struct osmo_ecu_fr_state fr;
} ecu_state;
struct osmo_ecu_state *ecu_state;
};
static inline uint8_t lchan_get_ta(const struct gsm_lchan *lchan)
@@ -418,7 +417,7 @@ struct gsm_bts_trx {
struct trx_power_params power_params;
int ms_power_control;
bool ms_pwr_ctl_soft; /* is power control loop done by osmocom software? */
struct {
void *l1h;
@@ -478,6 +477,13 @@ enum gsm_bts_features {
BTS_FEAT_SPEECH_F_EFR,
BTS_FEAT_SPEECH_F_AMR,
BTS_FEAT_SPEECH_H_AMR,
BTS_FEAT_ETWS_PN,
BTS_FEAT_MS_PWR_CTRL_DSP,
/* When the feature is set then the measurement data is included in
* (PRIM_PH_DATA) and struct ph_tch_param (PRIM_TCH). Otherwise the
* measurement data is passed using a separate MPH INFO MEAS IND.
* (See also ticket: OS#2977) */
BTS_FEAT_MEAS_PAYLOAD_COMB,
_NUM_BTS_FEAT
};
@@ -539,6 +545,14 @@ struct gprs_rlc_cfg {
uint8_t initial_mcs;
};
struct bts_smscb_state {
struct llist_head queue; /* list of struct smscb_msg */
int queue_len;
struct rate_ctr_group *ctrs;
struct smscb_msg *cur_msg; /* current SMS-CB */
struct smscb_msg *default_msg; /* default broadcast message; NULL if none */
};
/* The amount of time within which a sudden disconnect of a newly established
* OML connection will cause a special warning to be logged. */
#define OSMO_BTS_OML_CONN_EARLY_DISCONNECT 10 /* in seconds */
@@ -548,10 +562,7 @@ struct gsm_bts {
/* list header in net->bts_list */
struct llist_head list;
/* Geographical location of the BTS */
struct llist_head loc_list;
/* number of ths BTS in network */
/* number of the BTS in network */
uint8_t nr;
/* human readable name / description */
char *description;
@@ -612,8 +623,12 @@ struct gsm_bts {
/* offsets used while generating SI2quater */
size_t e_offset;
size_t u_offset;
/* decoded SI3 rest octets - *unmodified* as received from BSC */
struct osmo_gsm48_si_ro_info si3_ro_decoded;
/* is SI3 GPRS Indicator currently disabled due to lack of PCU connection? */
bool si3_gprs_ind_disabled;
/* ip.accesss Unit ID's have Site/BTS/TRX layout */
/* ip.access Unit ID's have Site/BTS/TRX layout */
union {
struct {
uint16_t site_id;
@@ -708,6 +723,15 @@ struct gsm_bts {
uint64_t pch_msgs;
} agch_queue;
struct {
uint8_t *prim_notif; /* ETWS primary notification (NULL if none) */
ssize_t prim_notif_len; /* Length of prim_notif; expected 56 bytes */
uint8_t page_size;
uint8_t num_pages; /* total number of pages */
uint8_t next_page; /* next page number to be sent */
bool pni; /* Primary Notification Identifier */
} etws;
struct paging_state *paging_state;
char *bsc_oml_host;
struct llist_head oml_queue;
@@ -717,6 +741,7 @@ struct gsm_bts {
uint16_t rtp_port_range_start;
uint16_t rtp_port_range_end;
uint16_t rtp_port_range_next;
int rtp_ip_dscp;
struct {
uint8_t ciphers; /* flags A5/1==0x1, A5/2==0x2, A5/3==0x4 */
@@ -725,6 +750,14 @@ struct gsm_bts {
uint8_t tc4_ctr;
} si;
struct gsm_time gsm_time;
/* frame number statistics (FN in PH-RTS.ind vs. PH-DATA.ind */
struct {
int32_t min; /* minimum observed */
int32_t max; /* maximum observed */
int32_t avg256; /* accumulator */
uint32_t avg_count; /* number of samples accumulated in avg256 */
uint32_t avg_window; /* number of averages in avg_count */
} fn_stats;
/* Radio Link Timeout counter. -1 disables timeout for
* lab/measurement purpose */
int radio_link_timeout;
@@ -734,31 +767,29 @@ struct gsm_bts {
/* used by the sysmoBTS to adjust band */
uint8_t auto_band;
struct {
struct llist_head queue; /* list of struct smscb_msg */
struct smscb_msg *cur_msg; /* current SMS-CB */
} smscb_state;
/* State for SMSCB (Cell Broadcast) for BASIC and EXTENDED channel */
struct bts_smscb_state smscb_basic;
struct bts_smscb_state smscb_extended;
int smscb_queue_tgt_len; /* ideal/target queue length */
int smscb_queue_max_len; /* maximum queue length */
int smscb_queue_hyst; /* hysteresis for CBCH load indications */
float min_qual_rach; /* minimum quality for RACH bursts */
float min_qual_norm; /* minimum quality for normal daata */
int16_t min_qual_rach; /* minimum link quality (in centiBels) for Access Bursts */
int16_t min_qual_norm; /* minimum link quality (in centiBels) for Normal Bursts */
uint16_t max_ber10k_rach; /* Maximum permitted RACH BER in 0.01% */
struct {
char *sock_path;
} pcu;
void *model_priv; /* Allocated by bts_model, contains model specific data pointer */
#ifdef ENABLE_LC15BTS
/* specific to LC15 BTS */
struct {
uint32_t last_fn;
struct timeval tv_clock;
struct osmo_timer_list fn_timer;
} vbts;
#ifdef ENABLE_OC2GBTS
/* specific to Open Cellular 2G BTS */
struct {
uint8_t led_ctrl_mode; /* 0: control by BTS, 1: not control by BTS */
struct llist_head ceased_alarm_list; /* ceased alarm list*/
unsigned int rtp_drift_thres_ms; /* RTP timestamp drift detection threshold */
} oc2g;
uint8_t led_ctrl_mode; /* 0: control by BTS, 1: not control by BTS */
struct llist_head ceased_alarm_list; /* ceased alarm list*/
unsigned int rtp_drift_thres_ms; /* RTP timestamp drift detection threshold */
} lc15;
#endif
};
@@ -818,8 +849,6 @@ void *
gsm_objclass2obj(struct gsm_bts *bts, uint8_t obj_class,
const struct abis_om_obj_inst *obj_inst);
uint8_t gsm_pchan2chan_nr(enum gsm_phys_chan_config pchan,
uint8_t ts_nr, uint8_t lchan_nr);
uint8_t gsm_lchan2chan_nr(const struct gsm_lchan *lchan);
uint8_t gsm_lchan_as_pchan2chan_nr(const struct gsm_lchan *lchan,
enum gsm_phys_chan_config as_pchan);
@@ -851,4 +880,6 @@ uint8_t ts_subslots(struct gsm_bts_trx_ts *ts);
bool ts_is_tch(struct gsm_bts_trx_ts *ts);
const char *gsm_trx_unit_id(struct gsm_bts_trx *trx);
int lchan2ecu_codec(const struct gsm_lchan *lchan);
#endif

View File

@@ -2,6 +2,7 @@
#define L1SAP_H
#include <osmocom/gsm/protocol/gsm_04_08.h>
#include <osmocom/gsm/protocol/gsm_08_58.h>
/* lchan link ID */
#define LID_SACCH 0x40
@@ -15,16 +16,27 @@
#define L1SAP_CHAN2SS_BCCH(chan_nr) (CCCH_LCHAN)
/* logical channel from chan_nr + link_id */
#define L1SAP_IS_LINK_SACCH(link_id) ((link_id & 0xC0) == LID_SACCH)
#define L1SAP_IS_CHAN_TCHF(chan_nr) ((chan_nr & 0xf8) == 0x08)
#define L1SAP_IS_CHAN_TCHH(chan_nr) ((chan_nr & 0xf0) == 0x10)
#define L1SAP_IS_CHAN_SDCCH4(chan_nr) ((chan_nr & 0xe0) == 0x20)
#define L1SAP_IS_CHAN_SDCCH8(chan_nr) ((chan_nr & 0xc0) == 0x40)
#define L1SAP_IS_CHAN_BCCH(chan_nr) ((chan_nr & 0xf8) == 0x80)
#define L1SAP_IS_CHAN_RACH(chan_nr) ((chan_nr & 0xf8) == 0x88)
#define L1SAP_IS_CHAN_AGCH_PCH(chan_nr) ((chan_nr & 0xf8) == 0x90)
#define L1SAP_IS_CHAN_PDCH(chan_nr) ((chan_nr & 0xf8) == 0xc0)
#define L1SAP_IS_CHAN_CBCH(chan_nr) ((chan_nr & 0xf8) == 0xc8)
#define L1SAP_IS_LINK_SACCH(link_id) \
((link_id & 0xC0) == LID_SACCH)
#define L1SAP_IS_CHAN_TCHF(chan_nr) \
((chan_nr & 0xf8) == RSL_CHAN_Bm_ACCHs)
#define L1SAP_IS_CHAN_TCHH(chan_nr) \
((chan_nr & 0xf0) == RSL_CHAN_Lm_ACCHs)
#define L1SAP_IS_CHAN_SDCCH4(chan_nr) \
((chan_nr & 0xe0) == RSL_CHAN_SDCCH4_ACCH)
#define L1SAP_IS_CHAN_SDCCH8(chan_nr) \
((chan_nr & 0xc0) == RSL_CHAN_SDCCH8_ACCH)
#define L1SAP_IS_CHAN_BCCH(chan_nr) \
((chan_nr & 0xf8) == RSL_CHAN_BCCH)
#define L1SAP_IS_CHAN_RACH(chan_nr) \
((chan_nr & 0xf8) == RSL_CHAN_RACH)
#define L1SAP_IS_CHAN_AGCH_PCH(chan_nr) \
((chan_nr & 0xf8) == RSL_CHAN_PCH_AGCH)
#define L1SAP_IS_CHAN_PDCH(chan_nr) \
((chan_nr & 0xf8) == RSL_CHAN_OSMO_PDCH)
#define L1SAP_IS_CHAN_CBCH(chan_nr) \
((chan_nr & 0xf8) == RSL_CHAN_OSMO_CBCH4) \
|| ((chan_nr & 0xf8) == RSL_CHAN_OSMO_CBCH8)
/* rach type from ra */
#define L1SAP_IS_PACKET_RACH(ra) ((ra & 0xf0) == 0x70 && (ra & 0x0f) != 0x0f)
@@ -71,7 +83,7 @@ int l1sap_up(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap);
/* pcu (socket interface) sends us a data request primitive */
int l1sap_pdch_req(struct gsm_bts_trx_ts *ts, int is_ptcch, uint32_t fn,
uint16_t arfcn, uint8_t block_nr, uint8_t *data, uint8_t len);
uint16_t arfcn, uint8_t block_nr, const uint8_t *data, uint8_t len);
/* call-back function for incoming RTP */
void l1sap_rtp_rx_cb(struct osmo_rtp_socket *rs, const uint8_t *rtp_pl,
@@ -84,6 +96,37 @@ int l1sap_chan_rel(struct gsm_bts_trx *trx, uint8_t chan_nr);
int l1sap_chan_deact_sacch(struct gsm_bts_trx *trx, uint8_t chan_nr);
int l1sap_chan_modify(struct gsm_bts_trx *trx, uint8_t chan_nr);
enum l1sap_common_sapi {
L1SAP_COMMON_SAPI_UNKNOWN,
/* alphabetic order */
L1SAP_COMMON_SAPI_AGCH,
L1SAP_COMMON_SAPI_BCCH,
L1SAP_COMMON_SAPI_CBCH,
L1SAP_COMMON_SAPI_FACCH_F,
L1SAP_COMMON_SAPI_FACCH_H,
L1SAP_COMMON_SAPI_FCCH,
L1SAP_COMMON_SAPI_IDLE,
L1SAP_COMMON_SAPI_NCH,
L1SAP_COMMON_SAPI_PACCH,
L1SAP_COMMON_SAPI_PAGCH,
L1SAP_COMMON_SAPI_PBCCH,
L1SAP_COMMON_SAPI_PCH,
L1SAP_COMMON_SAPI_PDTCH,
L1SAP_COMMON_SAPI_PNCH,
L1SAP_COMMON_SAPI_PPCH,
L1SAP_COMMON_SAPI_PRACH,
L1SAP_COMMON_SAPI_PTCCH,
L1SAP_COMMON_SAPI_RACH,
L1SAP_COMMON_SAPI_SACCH,
L1SAP_COMMON_SAPI_SCH,
L1SAP_COMMON_SAPI_SDCCH,
L1SAP_COMMON_SAPI_TCH_F,
L1SAP_COMMON_SAPI_TCH_H,
};
extern uint16_t l1sap_log_ctx_sapi;
extern const struct value_string l1sap_common_sapi_names[];
extern const struct value_string gsmtap_sapi_names[];
extern struct gsmtap_inst *gsmtap;
extern uint32_t gsmtap_sapi_mask;
@@ -91,7 +134,8 @@ extern uint8_t gsmtap_sapi_acch;
int add_l1sap_header(struct gsm_bts_trx *trx, struct msgb *rmsg,
struct gsm_lchan *lchan, uint8_t chan_nr, uint32_t fn,
uint16_t ber10k, int16_t lqual_cb);
uint16_t ber10k, int16_t lqual_cb, int8_t rssi,
int16_t ta_offs, uint8_t is_sub);
#define msgb_l1sap_prim(msg) ((struct osmo_phsap_prim *)(msg)->l1h)

View File

@@ -14,11 +14,11 @@ int down_oml(struct gsm_bts *bts, struct msgb *msg);
struct msgb *oml_msgb_alloc(void);
int oml_send_msg(struct msgb *msg, int is_mauf);
int oml_mo_send_msg(struct gsm_abis_mo *mo, struct msgb *msg, uint8_t msg_type);
int oml_mo_opstart_ack(struct gsm_abis_mo *mo);
int oml_mo_opstart_nack(struct gsm_abis_mo *mo, uint8_t nack_cause);
int oml_mo_statechg_ack(struct gsm_abis_mo *mo);
int oml_mo_statechg_nack(struct gsm_abis_mo *mo, uint8_t nack_cause);
int oml_mo_send_msg(const struct gsm_abis_mo *mo, struct msgb *msg, uint8_t msg_type);
int oml_mo_opstart_ack(const struct gsm_abis_mo *mo);
int oml_mo_opstart_nack(const struct gsm_abis_mo *mo, uint8_t nack_cause);
int oml_mo_statechg_ack(const struct gsm_abis_mo *mo);
int oml_mo_statechg_nack(const struct gsm_abis_mo *mo, uint8_t nack_cause);
/* Change the state and send STATE CHG REP */
int oml_mo_state_chg(struct gsm_abis_mo *mo, int op_state, int avail_state);
@@ -31,20 +31,19 @@ int oml_mo_rf_lock_chg(struct gsm_abis_mo *mo, uint8_t mute_state[8],
int success);
/* Transmit STATE CHG REP even if there was no state change */
int oml_tx_state_changed(struct gsm_abis_mo *mo);
int oml_tx_state_changed(const struct gsm_abis_mo *mo);
int oml_mo_tx_sw_act_rep(struct gsm_abis_mo *mo);
int oml_mo_tx_sw_act_rep(const struct gsm_abis_mo *mo);
int oml_fom_ack_nack(struct msgb *old_msg, uint8_t cause);
int oml_mo_fom_ack_nack(struct gsm_abis_mo *mo, uint8_t orig_msg_type,
int oml_mo_fom_ack_nack(const struct gsm_abis_mo *mo, uint8_t orig_msg_type,
uint8_t cause);
/* Configure LAPDm T200 timers for this lchan according to OML */
int oml_set_lchan_t200(struct gsm_lchan *lchan);
extern const unsigned int oml_default_t200_ms[7];
/* Transmit failure event report */
void oml_fail_rep(uint16_t cause_value, const char *fmt, ...);
int oml_tx_failure_event_rep(const struct gsm_abis_mo *mo, enum abis_nm_severity severity,
uint16_t cause_value, const char *fmt, ...);
#endif // _OML_H */

View File

@@ -5,16 +5,19 @@ extern int pcu_direct;
int pcu_tx_info_ind(void);
int pcu_tx_si13(const struct gsm_bts *bts, bool enable);
int pcu_tx_app_info_req(struct gsm_bts *bts, uint8_t app_type, uint8_t len, const uint8_t *app_data);
int pcu_tx_rts_req(struct gsm_bts_trx_ts *ts, uint8_t is_ptcch, uint32_t fn,
uint16_t arfcn, uint8_t block_nr);
int pcu_tx_data_ind(struct gsm_bts_trx_ts *ts, uint8_t is_ptcch, uint32_t fn,
uint16_t arfcn, uint8_t block_nr, uint8_t *data, uint8_t len,
int8_t rssi, uint16_t ber10k, int16_t bto, int16_t lqual);
int pcu_tx_rach_ind(struct gsm_bts *bts, int16_t qta, uint16_t ra, uint32_t fn,
uint8_t is_11bit, enum ph_burst_type burst_type);
int pcu_tx_rach_ind(uint8_t bts_nr, uint8_t trx_nr, uint8_t ts_nr,
int16_t qta, uint16_t ra, uint32_t fn, uint8_t is_11bit,
enum ph_burst_type burst_type, uint8_t sapi);
int pcu_tx_time_ind(uint32_t fn);
int pcu_tx_pag_req(const uint8_t *identity_lv, uint8_t chan_needed);
int pcu_tx_pch_data_cnf(uint32_t fn, uint8_t *data, uint8_t len);
int pcu_tx_susp_req(struct gsm_lchan *lchan, uint32_t tlli, const uint8_t *ra_id, uint8_t cause);
int pcu_sock_init(const char *path);
void pcu_sock_exit(void);

View File

@@ -12,6 +12,8 @@
#define PCU_IF_MSG_DATA_REQ 0x00 /* send data to given channel */
#define PCU_IF_MSG_DATA_CNF 0x01 /* confirm (e.g. transmission on PCH) */
#define PCU_IF_MSG_DATA_IND 0x02 /* receive data from given channel */
#define PCU_IF_MSG_SUSP_REQ 0x03 /* BTS forwards GPRS SUSP REQ to PCU */
#define PCU_IF_MSG_APP_INFO_REQ 0x04 /* BTS asks PCU to tranmit APP INFO via PACCH */
#define PCU_IF_MSG_RTS_REQ 0x10 /* ready to send request */
#define PCU_IF_MSG_DATA_CNF_DT 0x11 /* confirm (with direct tlli) */
#define PCU_IF_MSG_RACH_IND 0x22 /* receive RACH */
@@ -106,6 +108,8 @@ struct gsm_pcu_if_rach_ind {
uint16_t arfcn;
uint8_t is_11bit;
uint8_t burst_type;
uint8_t trx_nr;
uint8_t ts_nr;
} __attribute__ ((packed));
struct gsm_pcu_if_info_trx {
@@ -171,6 +175,20 @@ struct gsm_pcu_if_pag_req {
uint8_t identity_lv[9];
} __attribute__ ((packed));
/* BTS tells PCU to [once] send given application data via PACCH to all UE with active TBF */
struct gsm_pcu_if_app_info_req {
uint8_t application_type; /* 4bit field, see TS 44.060 11.2.47 */
uint8_t len; /* length of data */
uint8_t data[162]; /* random size choice; ETWS needs 56 bytes */
} __attribute__ ((packed));
/* BTS tells PCU about a GPRS SUSPENSION REQUEST received on DCCH */
struct gsm_pcu_if_susp_req {
uint32_t tlli;
uint8_t ra_id[6];
uint8_t cause;
} __attribute__ ((packed));
struct gsm_pcu_if {
/* context based information */
uint8_t msg_type; /* message type */
@@ -182,6 +200,7 @@ struct gsm_pcu_if {
struct gsm_pcu_if_data data_cnf;
struct gsm_pcu_if_data_cnf_dt data_cnf_dt;
struct gsm_pcu_if_data data_ind;
struct gsm_pcu_if_susp_req susp_req;
struct gsm_pcu_if_rts_req rts_req;
struct gsm_pcu_if_rach_ind rach_ind;
struct gsm_pcu_if_txt_ind txt_ind;
@@ -189,6 +208,7 @@ struct gsm_pcu_if {
struct gsm_pcu_if_act_req act_req;
struct gsm_pcu_if_time_ind time_ind;
struct gsm_pcu_if_pag_req pag_req;
struct gsm_pcu_if_app_info_req app_info_req;
} u;
} __attribute__ ((packed));

View File

@@ -44,15 +44,16 @@ struct phy_link {
uint16_t base_port_local;
uint16_t base_port_remote;
struct osmo_fd trx_ofd_clk;
bool trx_ta_loop;
bool trx_ms_power_loop;
int8_t trx_target_rssi;
uint32_t clock_advance;
uint32_t rts_advance;
bool use_legacy_setbsic;
uint8_t trxd_hdr_ver_max; /* Maximum TRXD header version to negotiate */
bool powered; /* last POWERON (true) or POWEROFF (false) confirmed */
bool poweronoff_sent; /* is there a POWERON/POWEROFF in transit? (one or the other based on ->powered) */
} osmotrx;
struct {
char *mcast_dev; /* Network device for multicast */
int ttl; /* TTL of transmitted udp multicast */
char *bts_mcast_group; /* BTS are listening to this group */
uint16_t bts_mcast_port;
char *ms_mcast_group; /* MS are listening to this group */
@@ -156,6 +157,8 @@ struct phy_link *phy_link_by_num(int num);
struct phy_link *phy_link_create(void *ctx, int num);
void phy_link_destroy(struct phy_link *plink);
void phy_link_state_set(struct phy_link *plink, enum phy_link_state state);
enum phy_link_state phy_link_state_get(struct phy_link *plink);
const char *phy_link_state_name(enum phy_link_state state);
int phy_links_open(void);
struct phy_instance *phy_instance_by_num(struct phy_link *plink, int num);
@@ -166,10 +169,12 @@ const char *phy_instance_name(struct phy_instance *pinst);
void phy_user_statechg_notif(struct phy_instance *pinst, enum phy_link_state link_state);
static inline struct phy_instance *trx_phy_instance(struct gsm_bts_trx *trx)
static inline struct phy_instance *trx_phy_instance(const struct gsm_bts_trx *trx)
{
OSMO_ASSERT(trx);
return trx->role_bts.l1h;
}
int bts_model_phy_link_open(struct phy_link *plink);
#define LOGPPHI(pinst, section, lvl, fmt, args...) LOGP(section, lvl, "%s: " fmt, phy_instance_name(pinst), ##args)

View File

@@ -43,4 +43,8 @@ void cb_ts_disconnected(struct gsm_bts_trx_ts *ts);
void cb_ts_connected(struct gsm_bts_trx_ts *ts, int rc);
void ipacc_dyn_pdch_complete(struct gsm_bts_trx_ts *ts, int rc);
int rsl_tx_cbch_load_indication(struct gsm_bts *bts, bool ext_cbch, bool overflow, uint8_t amount);
int rsl_tx_meas_res(struct gsm_lchan *lchan, uint8_t *l3, int l3_len, const struct lapdm_entity *le);
#endif // _RSL_H */

View File

@@ -5,6 +5,15 @@
#include <osmo-bts/gsm_data.h>
/* Whether a logical channel must be activated automatically */
#define TRX_CHAN_FLAG_AUTO_ACTIVE (1 << 0)
/* Whether a logical channel belongs to PDCH (packet switched data) */
#define TRX_CHAN_FLAG_PDCH (1 << 1)
/* FIXME: we should actually activate 'auto-active' channels */
#define TRX_CHAN_IS_ACTIVE(state, chan) \
(trx_chan_desc[chan].flags & TRX_CHAN_FLAG_AUTO_ACTIVE || (state)->active)
/* These types define the different channels on a multiframe.
* Each channel has queues and can be activated individually.
*/
@@ -51,8 +60,6 @@ enum trx_chan_type {
_TRX_CHAN_MAX
};
extern const struct value_string trx_chan_type_names[];
#define GSM_BURST_LEN 148
#define GPRS_BURST_LEN GSM_BURST_LEN
#define EGPRS_BURST_LEN 444
@@ -72,11 +79,13 @@ struct l1sched_chan_state {
uint32_t ul_first_fn; /* fn of first burst */
uint8_t ul_mask; /* mask of received bursts */
/* RSSI / TOA */
/* measurements */
uint8_t rssi_num; /* number of RSSI values */
float rssi_sum; /* sum of RSSI values */
uint8_t toa_num; /* number of TOA values */
int32_t toa256_sum; /* sum of TOA values (1/256 symbol) */
uint8_t ci_cb_num; /* number of C/I values */
int32_t ci_cb_sum; /* sum of C/I values (in centiBels) */
/* loss detection */
uint8_t lost_frames; /* how many L2 frames were lost */
@@ -112,17 +121,12 @@ struct l1sched_chan_state {
/* measurements */
struct {
uint8_t clock; /* cyclic clock counter */
int8_t rssi[32]; /* last RSSI values */
int rssi_count; /* received RSSI values */
int rssi_valid_count; /* number of stored value */
int rssi_got_burst; /* any burst received so far */
int32_t toa256_sum; /* sum of TOA values (1/256 symbol) */
int toa_num; /* number of TOA value */
} meas;
/* handover */
uint8_t ho_rach_detect; /* if rach detection is on */
bool ho_rach_detect; /* if rach detection is on */
};
struct l1sched_ts {
@@ -166,9 +170,11 @@ int trx_sched_tch_req(struct l1sched_trx *l1t, struct osmo_phsap_prim *l1sap);
/*! \brief PHY informs us of new (current) GSM frame number */
int trx_sched_clock(struct gsm_bts *bts, uint32_t fn);
/*! \brief handle an UL burst received by PHY */
int trx_sched_ul_burst(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
sbit_t *bits, uint16_t nbits, int8_t rssi, int16_t toa);
/*! \brief PHY informs us clock indications should start to be received */
int trx_sched_clock_started(struct gsm_bts *bts);
/*! \brief PHY informs us no more clock indications should be received anymore */
int trx_sched_clock_stopped(struct gsm_bts *bts);
/*! \brief set multiframe scheduler to given physical channel config */
int trx_sched_set_pchan(struct l1sched_trx *l1t, uint8_t tn,
@@ -224,4 +230,34 @@ int find_sched_mframe_idx(enum gsm_phys_chan_config pchan, uint8_t tn);
bool trx_sched_is_sacch_fn(struct gsm_bts_trx_ts *ts, uint32_t fn, bool uplink);
extern const struct trx_sched_multiframe trx_sched_multiframes[];
#define TRX_BI_F_NOPE_IND (1 << 0)
#define TRX_BI_F_MOD_TYPE (1 << 1)
#define TRX_BI_F_TS_INFO (1 << 2)
#define TRX_BI_F_CI_CB (1 << 3)
/*! UL burst indication with the corresponding meta info */
struct trx_ul_burst_ind {
/* Field presence bitmask (see TRX_BI_F_*) */
uint8_t flags;
/* Mandatory fields */
uint32_t fn; /*!< TDMA frame number */
uint8_t tn; /*!< TDMA time-slot number */
int16_t toa256; /*!< Timing of Arrival in units of 1/256 of symbol */
int8_t rssi; /*!< Received Signal Strength Indication */
/* Optional fields (defined by flags) */
enum trx_burst_type bt; /*!< Modulation type */
uint8_t tsc_set; /*!< Training Sequence Set */
uint8_t tsc; /*!< Training Sequence Code */
int16_t ci_cb; /*!< Carrier-to-Interference ratio (in centiBels) */
/*! Burst soft-bits buffer */
sbit_t burst[EGPRS_BURST_LEN];
size_t burst_len;
};
/*! Handle an UL burst received by PHY */
int trx_sched_ul_burst(struct l1sched_trx *l1t, struct trx_ul_burst_ind *bi);
#endif /* TRX_SCHEDULER_H */

View File

@@ -13,30 +13,28 @@ typedef ubit_t *trx_sched_dl_func(struct l1sched_trx *l1t, uint8_t tn,
uint32_t fn, enum trx_chan_type chan,
uint8_t bid, uint16_t *nbits);
typedef int trx_sched_ul_func(struct l1sched_trx *l1t, uint8_t tn,
uint32_t fn, enum trx_chan_type chan,
uint8_t bid, sbit_t *bits, uint16_t nbits,
int8_t rssi, int16_t toa256);
typedef int trx_sched_ul_func(struct l1sched_trx *l1t, enum trx_chan_type chan,
uint8_t bid, const struct trx_ul_burst_ind *bi);
struct trx_chan_desc {
/*! \brief Is this on a PDCH (PS) ? */
int pdch;
/*! \brief TRX Channel Type */
enum trx_chan_type chan;
/*! \brief Human-readable name */
const char *name;
/*! \brief Human-readable description */
const char *desc;
/*! \brief Channel Number (like in RSL) */
uint8_t chan_nr;
/*! \brief Link ID (like in RSL) */
uint8_t link_id;
/*! \brief Human-readable name */
const char *name;
/*! \brief function to call when we want to generate RTS.req to L2 */
trx_sched_rts_func *rts_fn;
/*! \brief function to call when DATA.req received from L2 */
trx_sched_dl_func *dl_fn;
/*! \brief function to call when burst received from PHY */
trx_sched_ul_func *ul_fn;
/*! \brief is this channel automatically active at start? */
int auto_active;
/*! \brief function to call when NOPE.ind received from PHY */
trx_sched_ul_func *nope_fn;
/*! \brief channel flags, see TRX_CHAN_FLAG_* */
uint8_t flags;
};
extern const struct trx_chan_desc trx_chan_desc[_TRX_CHAN_MAX];
@@ -56,7 +54,8 @@ int _sched_compose_ph_data_ind(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
enum osmo_ph_pres_info_type presence_info);
int _sched_compose_tch_ind(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
enum trx_chan_type chan, uint8_t *tch, uint8_t tch_len);
enum trx_chan_type chan, uint8_t *tch, uint8_t tch_len,
int16_t ta_offs_256bits, uint16_t ber10k, float rssi);
ubit_t *tx_idle_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
enum trx_chan_type chan, uint8_t bid, uint16_t *nbits);
@@ -72,21 +71,16 @@ ubit_t *tx_tchf_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
enum trx_chan_type chan, uint8_t bid, uint16_t *nbits);
ubit_t *tx_tchh_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
enum trx_chan_type chan, uint8_t bid, uint16_t *nbits);
int rx_rach_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
enum trx_chan_type chan, uint8_t bid, sbit_t *bits, uint16_t nbits,
int8_t rssi, int16_t toa256);
int rx_data_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
enum trx_chan_type chan, uint8_t bid, sbit_t *bits, uint16_t nbits,
int8_t rssi, int16_t toa256);
int rx_pdtch_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
enum trx_chan_type chan, uint8_t bid, sbit_t *bits, uint16_t nbits,
int8_t rssi, int16_t toa256);
int rx_tchf_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
enum trx_chan_type chan, uint8_t bid, sbit_t *bits, uint16_t nbits,
int8_t rssi, int16_t toa256);
int rx_tchh_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
enum trx_chan_type chan, uint8_t bid, sbit_t *bits, uint16_t nbits,
int8_t rssi, int16_t toa256);
int rx_rach_fn(struct l1sched_trx *l1t, enum trx_chan_type chan,
uint8_t bid, const struct trx_ul_burst_ind *bi);
int rx_data_fn(struct l1sched_trx *l1t, enum trx_chan_type chan,
uint8_t bid, const struct trx_ul_burst_ind *bi);
int rx_pdtch_fn(struct l1sched_trx *l1t, enum trx_chan_type chan,
uint8_t bid, const struct trx_ul_burst_ind *bi);
int rx_tchf_fn(struct l1sched_trx *l1t, enum trx_chan_type chan,
uint8_t bid, const struct trx_ul_burst_ind *bi);
int rx_tchh_fn(struct l1sched_trx *l1t, enum trx_chan_type chan,
uint8_t bid, const struct trx_ul_burst_ind *bi);
const ubit_t *_sched_dl_burst(struct l1sched_trx *l1t, uint8_t tn,
uint32_t fn, uint16_t *nbits);

View File

@@ -5,7 +5,6 @@
enum sig_subsys {
SS_GLOBAL,
SS_FAIL,
};
enum signals_global {

View File

@@ -0,0 +1,5 @@
#pragma once
#include <osmo-bts/gsm_data.h>
void lchan_ms_ta_ctrl(struct gsm_lchan *lchan);

View File

@@ -25,7 +25,9 @@ struct phy_instance *vty_get_phy_instance(struct vty *vty, int phy_nr, int inst_
int bts_vty_go_parent(struct vty *vty);
int bts_vty_is_config_node(struct vty *vty, int node);
int bts_vty_init(struct gsm_bts *bts, const struct log_info *cat);
int bts_vty_init(struct gsm_bts *bts);
struct gsm_network *gsmnet_from_vty(struct vty *v);
extern struct vty_app_info bts_vty_info;

View File

@@ -6,12 +6,16 @@ if ENABLE_LC15BTS
AM_CFLAGS += -DENABLE_LC15BTS
endif
if ENABLE_LC15BTS
AM_CFLAGS += -DENABLE_LC15BTS
endif
noinst_LIBRARIES = libbts.a libl1sched.a
libbts_a_SOURCES = gsm_data_shared.c sysinfo.c logging.c abis.c oml.c bts.c \
rsl.c vty.c paging.c measurement.c amr.c lchan.c \
load_indication.c pcu_sock.c handover.c msg_utils.c \
tx_power.c bts_ctrl_commands.c bts_ctrl_lookup.c \
l1sap.c cbch.c power_control.c main.c phy_link.c \
dtx_dl_amr_fsm.c scheduler_mframe.c
dtx_dl_amr_fsm.c scheduler_mframe.c ta_control.c
libl1sched_a_SOURCES = scheduler.c

View File

@@ -108,12 +108,11 @@ static struct e1inp_sign_link *sign_link_up(void *unit, struct e1inp_line *line,
e1inp_ts_config_sign(&line->ts[E1INP_SIGN_OML-1], line);
sign_link = g_bts->oml_link =
e1inp_sign_link_create(&line->ts[E1INP_SIGN_OML-1],
E1INP_SIGN_OML, NULL, 255, 0);
E1INP_SIGN_OML, g_bts->c0, 255, 0);
if (clock_gettime(CLOCK_MONOTONIC, &g_bts->oml_conn_established_timestamp) != 0)
memset(&g_bts->oml_conn_established_timestamp, 0,
sizeof(g_bts->oml_conn_established_timestamp));
drain_oml_queue(g_bts);
sign_link->trx = g_bts->c0;
bts_link_estab(g_bts);
break;
default:
@@ -129,8 +128,8 @@ static struct e1inp_sign_link *sign_link_up(void *unit, struct e1inp_line *line,
e1inp_ts_config_sign(&line->ts[type-1], line);
sign_link = trx->rsl_link =
e1inp_sign_link_create(&line->ts[type-1],
E1INP_SIGN_RSL, NULL, 0, 0);
sign_link->trx = trx;
E1INP_SIGN_RSL, trx,
trx->rsl_tei, 0);
trx_link_estab(trx);
break;
}
@@ -173,7 +172,7 @@ static void sign_link_down(struct e1inp_line *line)
}
/* callback for incoming mesages from A-bis/IP */
/* callback for incoming messages from A-bis/IP */
static int sign_link_cb(struct msgb *msg)
{
struct e1inp_sign_link *link = msg->dst;
@@ -212,7 +211,7 @@ uint32_t get_signlink_remote_ip(struct e1inp_sign_link *link)
return 0;
}
/* we assume that the soket is AF_INET. As Abis/IP contains
/* we assume that the socket is AF_INET. As Abis/IP contains
* lots of hard-coded IPv4 addresses, this safe */
OSMO_ASSERT(sin.sin_family == AF_INET);
@@ -260,7 +259,7 @@ void abis_init(struct gsm_bts *bts)
g_bts = bts;
oml_init(&bts->mo);
libosmo_abis_init(NULL);
libosmo_abis_init(tall_bts_ctx);
osmo_signal_register_handler(SS_L_INPUT, &inp_s_cbfn, bts);
}
@@ -270,7 +269,7 @@ struct e1inp_line *abis_open(struct gsm_bts *bts, char *dst_host,
{
struct e1inp_line *line;
/* patch in various data from VTY and othe sources */
/* patch in various data from VTY and other sources */
line_ops.cfg.ipa.addr = dst_host;
osmo_get_macaddr(bts_dev_info.mac_addr, "eth0");
bts_dev_info.site_id = bts->ip_access.site_id;

View File

@@ -49,9 +49,10 @@
#include <osmo-bts/oml.h>
#include <osmo-bts/signal.h>
#include <osmo-bts/dtx_dl_amr_fsm.h>
#include <osmo-bts/cbch.h>
#define MIN_QUAL_RACH 5.0f /* at least 5 dB C/I */
#define MIN_QUAL_NORM -0.5f /* at least -1 dB C/I */
#define MIN_QUAL_RACH 50 /* minimum link quality (in centiBels) for Access Bursts */
#define MIN_QUAL_NORM -5 /* minimum link quality (in centiBels) for Normal Bursts */
static void bts_update_agch_max_queue_length(struct gsm_bts *bts);
@@ -105,6 +106,22 @@ static const struct rate_ctr_group_desc bts_ctrg_desc = {
bts_ctr_desc
};
static const struct rate_ctr_desc cbch_ctr_desc[] = {
[CBCH_CTR_RCVD_QUEUED] = {"cbch:rcvd_queued", "Received + queued CBCH messages (Abis)" },
[CBCH_CTR_RCVD_DROPPED] = {"cbch:rcvd_dropped", "Received + dropped CBCH messages (Abis)" },
[CBCH_CTR_SENT_SINGLE] = {"cbch:sent_single", "Sent single CBCH messages (Um)" },
[CBCH_CTR_SENT_DEFAULT] = {"cbch:sent_default", "Sent default CBCH messages (Um)" },
[CBCH_CTR_SENT_NULL] = {"cbch:sent_null", "Sent NULL CBCH messages (Um)" },
};
static const struct rate_ctr_group_desc cbch_ctrg_desc = {
"cbch",
"cell broadcast channel",
OSMO_STATS_CLASS_GLOBAL,
ARRAY_SIZE(cbch_ctr_desc),
cbch_ctr_desc
};
/* Initialize the BTS data structures, called before config
* file reading */
int bts_init(struct gsm_bts *bts)
@@ -122,6 +139,10 @@ int bts_init(struct gsm_bts *bts)
bts->agch_queue.length = 0;
bts->ctrs = rate_ctr_group_alloc(bts, &bts_ctrg_desc, bts->nr);
if (!bts->ctrs) {
llist_del(&bts->list);
return -1;
}
/* enable management with default levels,
* raise threshold to GSM_BTS_AGCH_QUEUE_THRESH_LEVEL_DISABLE to
@@ -138,6 +159,7 @@ int bts_init(struct gsm_bts *bts)
bts->rtp_port_range_start = 16384;
bts->rtp_port_range_end = 17407;
bts->rtp_port_range_next = bts->rtp_port_range_start;
bts->rtp_ip_dscp = -1;
/* configurable via OML */
bts->load.ccch.load_ind_period = 112;
@@ -171,6 +193,9 @@ int bts_init(struct gsm_bts *bts)
tall_rtp_ctx = talloc_pool(tall_bts_ctx, 262144);
osmo_rtp_init(tall_rtp_ctx);
/* features implemented in 'common', available for all models */
gsm_bts_set_feature(bts, BTS_FEAT_ETWS_PN);
rc = bts_model_init(bts);
if (rc < 0) {
llist_del(&bts->list);
@@ -186,13 +211,27 @@ int bts_init(struct gsm_bts *bts)
initialized = 1;
}
INIT_LLIST_HEAD(&bts->smscb_state.queue);
INIT_LLIST_HEAD(&bts->smscb_basic.queue);
bts->smscb_basic.ctrs = rate_ctr_group_alloc(bts, &cbch_ctrg_desc, 0);
OSMO_ASSERT(bts->smscb_basic.ctrs);
INIT_LLIST_HEAD(&bts->smscb_extended.queue);
bts->smscb_extended.ctrs = rate_ctr_group_alloc(bts, &cbch_ctrg_desc, 1);
OSMO_ASSERT(bts->smscb_extended.ctrs);
bts->smscb_queue_max_len = 15;
bts->smscb_queue_tgt_len = 2;
bts->smscb_queue_hyst = 2;
INIT_LLIST_HEAD(&bts->oml_queue);
/* register DTX DL FSM */
rc = osmo_fsm_register(&dtx_dl_amr_fsm);
OSMO_ASSERT(rc == 0);
bts->fn_stats.min = INT32_MAX;
bts->fn_stats.max = INT32_MIN;
bts->fn_stats.avg_count = 0;
bts->fn_stats.avg_window = 256;
return rc;
}
@@ -218,6 +257,10 @@ int bts_trx_init(struct gsm_bts_trx *trx)
tpp->ramp.step_size_mdB = to_mdB(2);
tpp->ramp.step_interval_sec = 1;
/* IF BTS model doesn't DSP/HW support MS Power Control Loop, enable osmo algo by default: */
if (!gsm_bts_has_feature(trx->bts, BTS_FEAT_MS_PWR_CTRL_DSP))
trx->ms_pwr_ctl_soft = true;
rc = bts_model_trx_init(trx);
if (rc < 0) {
llist_del(&trx->list);
@@ -254,7 +297,7 @@ void bts_shutdown(struct gsm_bts *bts, const char *reason)
bts_model_trx_close(trx);
}
/* shedule a timer to make sure select loop logic can run again
/* schedule a timer to make sure select loop logic can run again
* to dispatch any pending primitives */
osmo_timer_schedule(&shutdown_timer, 3, 0);
}
@@ -309,10 +352,13 @@ int trx_link_estab(struct gsm_bts_trx *trx)
rc = rsl_tx_rf_res(trx);
else
rc = bts_model_trx_deact_rf(trx);
if (rc < 0)
oml_fail_rep(OSMO_EVT_MAJ_RSL_FAIL,
link ? "Failed to establish RSL link (%d)" :
"Failed to deactivate RF (%d)", rc);
if (rc < 0) {
oml_tx_failure_event_rep(&trx->bb_transc.mo, NM_SEVER_MAJOR, OSMO_EVT_MAJ_RSL_FAIL,
link ?
"Failed to establish RSL link (%d)" :
"Failed to deactivate RF (%d)", rc);
}
return 0;
}
@@ -339,15 +385,56 @@ int trx_set_available(struct gsm_bts_trx *trx, int avail)
return 0;
}
/* prepare the per-SAPI T200 arrays for a given lchan */
static int t200_by_lchan(int *t200_ms_dcch, int *t200_ms_acch, struct gsm_lchan *lchan)
{
struct gsm_bts *bts = lchan->ts->trx->bts;
/* we have to compensate for the "RTS advance" due to the asynchronous interface between
* the BTS (LAPDm) and the PHY/L1 (OsmoTRX or DSP in case of osmo-bts-{sysmo,lc15,oc2g,octphy} */
int32_t fn_advance = bts_get_avg_fn_advance(bts);
int32_t fn_advance_us = fn_advance * 4615;
int fn_advance_ms = fn_advance_us / 1000;
t200_ms_acch[DL_SAPI0] = bts->t200_ms[T200_SACCH_SDCCH] + fn_advance_ms;
t200_ms_acch[DL_SAPI3] = bts->t200_ms[T200_SACCH_SDCCH] + fn_advance_ms;
switch (lchan->type) {
case GSM_LCHAN_SDCCH:
t200_ms_dcch[DL_SAPI0] = bts->t200_ms[T200_SDCCH] + fn_advance_ms;
t200_ms_dcch[DL_SAPI3] = bts->t200_ms[T200_SDCCH_SAPI3] + fn_advance_ms;
break;
case GSM_LCHAN_TCH_F:
t200_ms_dcch[DL_SAPI0] = bts->t200_ms[T200_FACCH_F] + fn_advance_ms;
t200_ms_dcch[DL_SAPI3] = bts->t200_ms[T200_FACCH_F] + fn_advance_ms;
break;
case GSM_LCHAN_TCH_H:
t200_ms_dcch[DL_SAPI0] = bts->t200_ms[T200_FACCH_H] + fn_advance_ms;
t200_ms_dcch[DL_SAPI3] = bts->t200_ms[T200_FACCH_H] + fn_advance_ms;
break;
default:
/* Channels such as CCCH don't use lapdm DL, and hence no T200 is needed */
return -1;
}
return 0;
}
int lchan_init_lapdm(struct gsm_lchan *lchan)
{
struct lapdm_channel *lc = &lchan->lapdm_ch;
int t200_ms_dcch[_NR_DL_SAPI], t200_ms_acch[_NR_DL_SAPI];
lapdm_channel_init(lc, LAPDM_MODE_BTS);
lapdm_channel_set_flags(lc, LAPDM_ENT_F_POLLING_ONLY);
lapdm_channel_set_l1(lc, NULL, lchan);
if (t200_by_lchan(t200_ms_dcch, t200_ms_acch, lchan) == 0) {
LOGPLCHAN(lchan, DLLAPD, LOGL_DEBUG,
"Setting T200 D0=%u, D3=%u, S0=%u, S3=%u (all in ms)\n",
t200_ms_dcch[DL_SAPI0], t200_ms_dcch[DL_SAPI3],
t200_ms_acch[DL_SAPI0], t200_ms_acch[DL_SAPI3]);
lapdm_channel_init2(lc, LAPDM_MODE_BTS, t200_ms_dcch, t200_ms_acch, lchan->type);
lapdm_channel_set_flags(lc, LAPDM_ENT_F_POLLING_ONLY);
lapdm_channel_set_l1(lc, NULL, lchan);
}
/* We still need to set Rx callback to receive RACH requests: */
lapdm_channel_set_l3(lc, lapdm_rll_tx_cb, lchan);
oml_set_lchan_t200(lchan);
return 0;
}
@@ -509,7 +596,7 @@ static int try_merge_imm_ass_rej(struct gsm48_imm_ass_rej *old_rej,
return 0;
/* GSM 08.58, 5.7
* -> The BTS may combine serveral IMM.ASS.REJ messages
* -> The BTS may combine several IMM.ASS.REJ messages
* -> Identical request refs in one message may be squeezed
*
* GSM 04.08, 9.1.20.2
@@ -587,7 +674,7 @@ struct msgb *bts_agch_dequeue(struct gsm_bts *bts)
/*
* Remove lower prio messages if the queue has grown too long.
*
* \return 0 iff the number of messages in the queue would fit into the AGCH
* \return 0 if the number of messages in the queue would fit into the AGCH
* reserved part of the CCCH.
*/
static void compact_agch_queue(struct gsm_bts *bts)
@@ -696,9 +783,9 @@ int bts_supports_cipher(struct gsm_bts *bts, int rsl_cipher)
return sup > 0;
}
int trx_ms_pwr_ctrl_is_osmo(struct gsm_bts_trx *trx)
bool trx_ms_pwr_ctrl_is_osmo(struct gsm_bts_trx *trx)
{
return trx->ms_power_control == 1;
return trx->ms_pwr_ctl_soft;
}
struct gsm_time *get_time(struct gsm_bts *bts)
@@ -711,6 +798,11 @@ int bts_supports_cm(struct gsm_bts *bts, enum gsm_phys_chan_config pchan,
{
enum gsm_bts_features feature = _NUM_BTS_FEAT;
/* We assume that signalling support is mandatory,
* there is no BTS_FEAT_* definition to check that. */
if (cm == GSM48_CMODE_SIGN)
return 1;
/* Before the requested pchan/cm combination can be checked, we need to
* convert it to a feature identifier we can check */
switch (pchan) {

View File

@@ -34,6 +34,8 @@
#include <osmo-bts/oml.h>
#include <osmo-bts/bts.h>
static struct gsm_bts *g_bts;
CTRL_CMD_DEFINE(therm_att, "thermal-attenuation");
static int get_therm_att(struct ctrl_cmd *cmd, void *data)
{
@@ -75,7 +77,7 @@ CTRL_CMD_DEFINE_WO_NOVRF(oml_alert, "oml-alert");
static int set_oml_alert(struct ctrl_cmd *cmd, void *data)
{
/* Note: we expect signal dispatch to be synchronous */
osmo_signal_dispatch(SS_FAIL, OSMO_EVT_EXT_ALARM, cmd->value);
oml_tx_failure_event_rep(&g_bts->mo, NM_SEVER_INDETERMINATE, OSMO_EVT_EXT_ALARM, cmd->value);
cmd->reply = "OK";
@@ -88,6 +90,7 @@ int bts_ctrl_cmds_install(struct gsm_bts *bts)
rc |= ctrl_cmd_install(CTRL_NODE_TRX, &cmd_therm_att);
rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_oml_alert);
g_bts = bts;
return rc;
}

View File

@@ -1,6 +1,6 @@
/* Cell Broadcast routines */
/* (C) 2014 by Harald Welte <laforge@gnumonks.org>
/* (C) 2014,2018-2019 by Harald Welte <laforge@gnumonks.org>
*
* All Rights Reserved
*
@@ -26,16 +26,60 @@
#include <osmo-bts/bts.h>
#include <osmo-bts/cbch.h>
#include <osmo-bts/rsl.h>
#include <osmo-bts/logging.h>
/* internal representation of one SMS-CB message (e.g. in the pending queue */
struct smscb_msg {
struct llist_head list; /* list in smscb_state.queue */
bool is_schedule; /* is this a schedule message? */
uint8_t msg[GSM412_MSG_LEN]; /* message buffer */
uint8_t next_seg; /* next segment number */
uint8_t num_segs; /* total number of segments */
};
/* determine if current queue length differs more than permitted hysteresis from target
* queue length. If it does, send CBCH LOAD IND */
static void check_and_send_cbch_load(struct gsm_bts *bts, struct bts_smscb_state *bts_ss)
{
int delta = bts_ss->queue_len - bts->smscb_queue_tgt_len;
bool extended_cbch = false;
if (bts_ss == &bts->smscb_extended)
extended_cbch = true;
if (abs(delta) < bts->smscb_queue_hyst)
return;
if (delta < 0) {
/* Underrun */
rsl_tx_cbch_load_indication(bts, extended_cbch, false, OSMO_MIN(15, -delta));
} else {
/* Overrun */
rsl_tx_cbch_load_indication(bts, extended_cbch, true, OSMO_MIN(15, delta));
}
}
/* determine SMSCB state by tb number */
static struct bts_smscb_state *bts_smscb_state(struct gsm_bts *bts, uint8_t tb)
{
if (tb < 4)
return &bts->smscb_basic;
else if (tb < 8)
return &bts->smscb_extended;
else
OSMO_ASSERT(0);
}
static const char *tb_to_chan_str(uint8_t tb)
{
if (tb < 4)
return "CBCH-BASIC";
else
return "CBCH-EXTENDED";
}
/* construct a SMSCB NULL block in the user-provided output buffer at 'out' */
static int get_smscb_null_block(uint8_t *out)
{
struct gsm412_block_type *block_type = (struct gsm412_block_type *) out;
@@ -50,17 +94,28 @@ static int get_smscb_null_block(uint8_t *out)
}
/* get the next block of the current CB message */
static int get_smscb_block(struct gsm_bts *bts, uint8_t *out)
static int get_smscb_block(struct bts_smscb_state *bts_ss, uint8_t *out, uint8_t tb,
const struct gsm_time *g_time)
{
int to_copy;
struct gsm412_block_type *block_type;
struct smscb_msg *msg = bts->smscb_state.cur_msg;
struct smscb_msg *msg = bts_ss->cur_msg;
uint8_t block_nr = tb % 4;
const char *chan_name = tb_to_chan_str(tb);
if (!msg) {
/* No message: Send NULL mesage */
/* No message: Send NULL block */
DEBUGPGT(DLSMS, g_time, "%s: No cur_msg; requesting NULL block\n", chan_name);
return get_smscb_null_block(out);
}
OSMO_ASSERT(block_nr < 4);
if (block_nr >= msg->num_segs) {
/* Higher block number than this message has blocks: Send NULL block */
DEBUGPGT(DLSMS, g_time, "%s: cur_msg has only %u blocks; requesting NULL block\n",
chan_name, msg->num_segs);
return get_smscb_null_block(out);
}
OSMO_ASSERT(msg->next_seg < 4);
block_type = (struct gsm412_block_type *) out++;
@@ -69,27 +124,37 @@ static int get_smscb_block(struct gsm_bts *bts, uint8_t *out)
block_type->lpd = 1;
/* determine how much data to copy */
to_copy = GSM412_MSG_LEN - (msg->next_seg * GSM412_BLOCK_LEN);
to_copy = GSM412_MSG_LEN - (block_nr * GSM412_BLOCK_LEN);
if (to_copy > GSM412_BLOCK_LEN)
to_copy = GSM412_BLOCK_LEN;
to_copy = GSM412_BLOCK_LEN;
OSMO_ASSERT(to_copy >= 0);
/* copy data and increment index */
memcpy(out, &msg->msg[msg->next_seg * GSM412_BLOCK_LEN], to_copy);
memcpy(out, &msg->msg[block_nr * GSM412_BLOCK_LEN], to_copy);
/* set + increment sequence number */
block_type->seq_nr = msg->next_seg++;
if (block_nr == 0 && msg->is_schedule)
block_type->seq_nr = 8; /* first schedule block */
else
block_type->seq_nr = block_nr;
/* determine if this is the last block */
if (block_type->seq_nr + 1 == msg->num_segs)
if (block_nr + 1 == msg->num_segs)
block_type->lb = 1;
else
block_type->lb = 0;
if (block_type->lb == 1) {
/* remove/release the message memory */
talloc_free(bts->smscb_state.cur_msg);
bts->smscb_state.cur_msg = NULL;
if (block_nr == 4) {
if (msg != bts_ss->default_msg) {
DEBUGPGT(DLSMS, g_time, "%s: deleting fully-transmitted message %p\n",
chan_name, msg);
/* delete any fully-transmitted normal message (or superseded default) */
talloc_free(bts_ss->cur_msg);
bts_ss->cur_msg = NULL;
} else {
DEBUGPGT(DLSMS, g_time, "%s: keeping fully-transmitted default message %p\n",
chan_name, msg);
}
}
return block_type->lb;
@@ -102,18 +167,34 @@ static const uint8_t last_block_rsl2um[4] = {
[RSL_CB_CMD_LASTBLOCK_3] = 3,
};
static const struct value_string rsl_cb_cmd_names[] = {
{ RSL_CB_CMD_TYPE_NORMAL, "NORMAL" },
{ RSL_CB_CMD_TYPE_SCHEDULE, "SCHEDULE" },
{ RSL_CB_CMD_TYPE_DEFAULT, "DEFAULT" },
{ RSL_CB_CMD_TYPE_NULL, "NULL" },
{ 0, NULL }
};
/* incoming SMS broadcast command from RSL */
int bts_process_smscb_cmd(struct gsm_bts *bts,
struct rsl_ie_cb_cmd_type cmd_type,
uint8_t msg_len, const uint8_t *msg)
int bts_process_smscb_cmd(struct gsm_bts *bts, struct rsl_ie_cb_cmd_type cmd_type,
bool extended_cbch, uint8_t msg_len, const uint8_t *msg)
{
struct smscb_msg *scm;
struct bts_smscb_state *bts_ss;
const char *chan_name;
if (extended_cbch) {
chan_name = tb_to_chan_str(4);
bts_ss = &bts->smscb_extended;
} else {
chan_name = tb_to_chan_str(0);
bts_ss = &bts->smscb_basic;
}
if (msg_len > sizeof(scm->msg)) {
LOGP(DLSMS, LOGL_ERROR,
"Cannot process SMSCB of %u bytes (max %zu)\n",
msg_len, sizeof(scm->msg));
LOGP(DLSMS, LOGL_ERROR, "%s: Cannot process SMSCB of %u bytes (max %zu)\n",
chan_name, msg_len, sizeof(scm->msg));
return -EINVAL;
}
@@ -123,42 +204,86 @@ int bts_process_smscb_cmd(struct gsm_bts *bts,
/* initialize entire message with default padding */
memset(scm->msg, GSM_MACBLOCK_PADDING, sizeof(scm->msg));
/* next segment is first segment */
scm->next_seg = 0;
if (cmd_type.command == RSL_CB_CMD_TYPE_SCHEDULE)
scm->is_schedule = true;
scm->num_segs = last_block_rsl2um[cmd_type.last_block&3];
memcpy(scm->msg, msg, msg_len);
LOGP(DLSMS, LOGL_INFO, "RSL SMSCB COMMAND (chan=%s, type=%s, num_blocks=%u)\n",
chan_name, get_value_string(rsl_cb_cmd_names, cmd_type.command), scm->num_segs);
switch (cmd_type.command) {
case RSL_CB_CMD_TYPE_NORMAL:
case RSL_CB_CMD_TYPE_SCHEDULE:
case RSL_CB_CMD_TYPE_NULL:
scm->num_segs = last_block_rsl2um[cmd_type.last_block&3];
memcpy(scm->msg, msg, msg_len);
/* def_bcast is ignored */
/* def_bcast is ignored as per Section 9.3.41 of 3GPP TS 48.058 */
/* limit queue size and optionally send CBCH LOAD Information (overflow) via RSL */
if (bts_ss->queue_len >= bts->smscb_queue_max_len) {
LOGP(DLSMS, LOGL_NOTICE, "RSL SMSCB COMMAND (chan=%s, type=%s): OVERFLOW\n",
chan_name, get_value_string(rsl_cb_cmd_names, cmd_type.command));
rate_ctr_inc2(bts_ss->ctrs, CBCH_CTR_RCVD_DROPPED);
talloc_free(scm);
break;
}
llist_add_tail(&scm->list, &bts_ss->queue);
bts_ss->queue_len++;
check_and_send_cbch_load(bts, bts_ss);
rate_ctr_inc2(bts_ss->ctrs, CBCH_CTR_RCVD_QUEUED);
break;
case RSL_CB_CMD_TYPE_DEFAULT:
/* use def_bcast, ignore command */
/* def_bcast == 0: normal mess */
/* old default msg will be free'd in get_smscb_block() if it is currently in transit
* and we set a new default_msg here */
if (bts_ss->cur_msg && bts_ss->cur_msg == bts_ss->default_msg)
talloc_free(bts_ss->cur_msg);
if (cmd_type.def_bcast == RSL_CB_CMD_DEFBCAST_NORMAL)
/* def_bcast == 0: normal message */
bts_ss->default_msg = scm;
else {
/* def_bcast == 1: NULL message */
bts_ss->default_msg = NULL;
talloc_free(scm);
}
break;
default:
talloc_free(scm);
return -EINVAL;
}
llist_add_tail(&scm->list, &bts->smscb_state.queue);
/* FIXME: limit queue size and optionally send CBCH LOAD Information (overflow) via RSL */
return 0;
}
static struct smscb_msg *select_next_smscb(struct gsm_bts *bts)
static struct smscb_msg *select_next_smscb(struct gsm_bts *bts, uint8_t tb)
{
struct bts_smscb_state *bts_ss = bts_smscb_state(bts, tb);
const char *chan_name = tb_to_chan_str(tb);
struct smscb_msg *msg;
msg = llist_first_entry_or_null(&bts->smscb_state.queue, struct smscb_msg, list);
if (!msg) {
/* FIXME: send CBCH LOAD Information (underflow) via RSL */
return NULL;
msg = llist_first_entry_or_null(&bts_ss->queue, struct smscb_msg, list);
if (msg) {
llist_del(&msg->list);
bts_ss->queue_len--;
check_and_send_cbch_load(bts, bts_ss);
DEBUGP(DLSMS, "%s: %s: Dequeued msg\n", __func__, chan_name);
rate_ctr_inc2(bts_ss->ctrs, CBCH_CTR_SENT_SINGLE);
return msg;
}
llist_del(&msg->list);
/* send CBCH LOAD Information (underflow) via RSL */
check_and_send_cbch_load(bts, bts_ss);
return msg;
/* choose the default message, if any */
msg = bts_ss->default_msg;
if (msg) {
DEBUGP(DLSMS, "%s: %s: Using default msg\n", __func__, chan_name);
rate_ctr_inc2(bts_ss->ctrs, CBCH_CTR_SENT_DEFAULT);
return msg;
}
DEBUGP(DLSMS, "%s: %s: No queued msg nor default\n", __func__, chan_name);
rate_ctr_inc2(bts_ss->ctrs, CBCH_CTR_SENT_NULL);
return NULL;
}
/* call-back from bts model specific code when it wants to obtain a CBCH
@@ -166,10 +291,13 @@ static struct smscb_msg *select_next_smscb(struct gsm_bts *bts)
int bts_cbch_get(struct gsm_bts *bts, uint8_t *outbuf, struct gsm_time *g_time)
{
uint32_t fn = gsm_gsmtime2fn(g_time);
struct bts_smscb_state *bts_ss;
/* According to 05.02 Section 6.5.4 */
uint32_t tb = (fn / 51) % 8;
int rc = 0;
bts_ss = bts_smscb_state(bts, tb);
/* The multiframes used for the basic cell broadcast channel
* shall be those in * which TB = 0,1,2 and 3. The multiframes
* used for the extended cell broadcast channel shall be those
@@ -181,16 +309,14 @@ int bts_cbch_get(struct gsm_bts *bts, uint8_t *outbuf, struct gsm_time *g_time)
switch (tb) {
case 0:
case 4:
/* select a new SMSCB message */
bts->smscb_state.cur_msg = select_next_smscb(bts);
rc = get_smscb_block(bts, outbuf);
bts_ss->cur_msg = select_next_smscb(bts, tb);
rc = get_smscb_block(bts_ss, outbuf, tb, g_time);
break;
case 1: case 2: case 3:
rc = get_smscb_block(bts, outbuf);
break;
case 4: case 5: case 6: case 7:
/* always send NULL frame in extended CBCH for now */
rc = get_smscb_null_block(outbuf);
case 5: case 6: case 7:
rc = get_smscb_block(bts_ss, outbuf, tb, g_time);
break;
}

View File

@@ -31,6 +31,7 @@
#include <osmocom/gsm/gsm_utils.h>
#include <osmocom/gsm/abis_nm.h>
#include <osmocom/core/statistics.h>
#include <osmocom/codec/ecu.h>
#include <osmo-bts/gsm_data.h>
@@ -38,6 +39,7 @@ void gsm_abis_mo_reset(struct gsm_abis_mo *mo)
{
mo->nm_state.operational = NM_OPSTATE_NULL;
mo->nm_state.availability = NM_AVSTATE_POWER_OFF;
mo->nm_state.administrative = NM_STATE_LOCKED;
}
static void gsm_mo_init(struct gsm_abis_mo *mo, struct gsm_bts *bts,
@@ -105,6 +107,9 @@ const struct value_string gsm_bts_features_descs[] = {
{ BTS_FEAT_SPEECH_F_EFR, "Fullrate speech EFR" },
{ BTS_FEAT_SPEECH_F_AMR, "Fullrate speech AMR" },
{ BTS_FEAT_SPEECH_H_AMR, "Halfrate speech AMR" },
{ BTS_FEAT_ETWS_PN, "ETWS Primary Notification on PCH" },
{ BTS_FEAT_MS_PWR_CTRL_DSP, "DSP/HW based MS Power Control Loop" },
{ BTS_FEAT_MEAS_PAYLOAD_COMB, "Measurement and Payload data combined"},
{ 0, NULL }
};
@@ -222,10 +227,10 @@ struct gsm_bts_trx *gsm_bts_trx_alloc(struct gsm_bts *bts)
trx->bts = bts;
trx->nr = bts->num_trx++;
trx->mo.nm_state.administrative = NM_STATE_UNLOCKED;
gsm_mo_init(&trx->mo, bts, NM_OC_RADIO_CARRIER,
bts->nr, trx->nr, 0xff);
gsm_mo_init(&trx->bb_transc.mo, bts, NM_OC_BASEB_TRANSC,
bts->nr, trx->nr, 0xff);
@@ -569,7 +574,7 @@ gsm_objclass2obj(struct gsm_bts *bts, uint8_t obj_class,
}
/* See Table 10.5.25 of GSM04.08 */
uint8_t gsm_pchan2chan_nr(enum gsm_phys_chan_config pchan,
static uint8_t gsm_pchan2chan_nr(enum gsm_phys_chan_config pchan,
uint8_t ts_nr, uint8_t lchan_nr)
{
uint8_t cbits, chan_nr;
@@ -691,7 +696,7 @@ struct gsm_lchan *rsl_lchan_lookup(struct gsm_bts_trx *trx, uint8_t chan_nr,
*rc = -EINVAL;
if (cbits == 0x01) {
lch_idx = 0; /* TCH/F */
lch_idx = 0; /* TCH/F */
if (ts->pchan != GSM_PCHAN_TCH_F &&
ts->pchan != GSM_PCHAN_PDCH &&
ts->pchan != GSM_PCHAN_TCH_F_PDCH &&
@@ -805,3 +810,24 @@ const struct value_string lchan_ciph_state_names[] = {
{ LCHAN_CIPH_RXTX_CONF, "RXTX_CONF" },
{ 0, NULL }
};
/* determine the ECU codec constant for the codec used by given lchan */
int lchan2ecu_codec(const struct gsm_lchan *lchan)
{
struct gsm_bts_trx_ts *ts = lchan->ts;
switch (lchan->tch_mode) {
case GSM48_CMODE_SPEECH_V1:
if (ts_pchan(ts) == GSM_PCHAN_TCH_H)
return OSMO_ECU_CODEC_HR;
else
return OSMO_ECU_CODEC_FR;
break;
case GSM48_CMODE_SPEECH_EFR:
return OSMO_ECU_CODEC_EFR;
case GSM48_CMODE_SPEECH_AMR:
return OSMO_ECU_CODEC_AMR;
default:
return -1;
}
}

View File

@@ -44,9 +44,7 @@ static int ho_tx_phys_info(struct gsm_lchan *lchan)
if (!msg)
return -ENOMEM;
LOGP(DHO, LOGL_INFO,
"%s Sending PHYSICAL INFORMATION to MS.\n",
gsm_lchan_name(lchan));
LOGPLCHAN(lchan, DHO, LOGL_INFO, "Sending PHYSICAL INFORMATION to MS.\n");
/* Build RSL UNITDATA REQUEST message with 04.08 PHYS INFO */
msg->l3h = msg->data;
@@ -68,20 +66,18 @@ static void ho_t3105_cb(void *data)
struct gsm_lchan *lchan = data;
struct gsm_bts *bts = lchan->ts->trx->bts;
LOGP(DHO, LOGL_INFO, "%s T3105 timeout (%d resends left)\n",
gsm_lchan_name(lchan), bts->ny1 - lchan->ho.phys_info_count);
LOGPLCHAN(lchan, DHO, LOGL_INFO, "T3105 timeout (%d resends left)\n",
bts->ny1 - lchan->ho.phys_info_count);
if (lchan->state != LCHAN_S_ACTIVE) {
LOGP(DHO, LOGL_NOTICE,
"%s is in not active. It is in state %s. Ignoring\n",
gsm_lchan_name(lchan), gsm_lchans_name(lchan->state));
LOGPLCHAN(lchan, DHO, LOGL_NOTICE, "is in not active. It is in state %s. Ignoring\n",
gsm_lchans_name(lchan->state));
return;
}
if (lchan->ho.phys_info_count >= bts->ny1) {
/* HO Abort */
LOGP(DHO, LOGL_NOTICE, "%s NY1 reached, sending CONNection "
"FAILure to BSC.\n", gsm_lchan_name(lchan));
LOGPLCHAN(lchan, DHO, LOGL_NOTICE, "NY1 reached, sending CONNection FAILure to BSC.\n");
rsl_tx_conn_fail(lchan, RSL_ERR_HANDOVER_ACC_FAIL);
return;
}
@@ -98,23 +94,21 @@ void handover_rach(struct gsm_lchan *lchan, uint8_t ra, uint8_t acc_delay)
/* Ignore invalid handover ref */
if (lchan->ho.ref != ra) {
LOGP(DHO, LOGL_INFO, "%s RACH on dedicated channel received, but "
"ra=0x%02x != expected ref=0x%02x. (This is no bug)\n",
gsm_lchan_name(lchan), ra, lchan->ho.ref);
LOGPLCHAN(lchan, DHO, LOGL_INFO, "RACH on dedicated channel received, but "
"ra=0x%02x != expected ref=0x%02x. (This is no bug)\n", ra, lchan->ho.ref);
return;
}
/* Ignore handover on channels other than DCCH and SACCH */
if (lchan->type != GSM_LCHAN_SDCCH && lchan->type != GSM_LCHAN_TCH_H &&
lchan->type != GSM_LCHAN_TCH_F) {
LOGP(DHO, LOGL_ERROR, "%s handover RACH received on %s?!\n",
gsm_lchan_name(lchan), gsm_lchant_name(lchan->type));
LOGPLCHAN(lchan, DHO, LOGL_ERROR, "handover RACH received on %s?!\n",
gsm_lchant_name(lchan->type));
return;
}
LOGP(DHO, LOGL_NOTICE,
"%s RACH on dedicated channel type %s received with TA=%u, ref=%u\n",
gsm_lchan_name(lchan), gsm_lchant_name(lchan->type), acc_delay, ra);
LOGPLCHAN(lchan, DHO, LOGL_NOTICE, "RACH on dedicated channel type %s received with "
"TA=%u, ref=%u\n", gsm_lchant_name(lchan->type), acc_delay, ra);
/* Set timing advance */
lchan->rqd_ta = acc_delay;
@@ -122,9 +116,7 @@ void handover_rach(struct gsm_lchan *lchan, uint8_t ra, uint8_t acc_delay)
/* Stop handover detection, wait for valid frame */
lchan->ho.active = HANDOVER_WAIT_FRAME;
if (l1sap_chan_modify(lchan->ts->trx, gsm_lchan2chan_nr(lchan)) != 0) {
LOGP(DHO, LOGL_ERROR,
"%s failed to modify channel after handover\n",
gsm_lchan_name(lchan));
LOGPLCHAN(lchan, DHO, LOGL_ERROR, "failed to modify channel after handover\n");
rsl_tx_conn_fail(lchan, RSL_ERR_HANDOVER_ACC_FAIL);
return;
}
@@ -137,19 +129,16 @@ void handover_rach(struct gsm_lchan *lchan, uint8_t ra, uint8_t acc_delay)
ho_tx_phys_info(lchan);
/* Start T3105 */
LOGP(DHO, LOGL_DEBUG,
"%s Starting T3105 with %u ms\n",
gsm_lchan_name(lchan), bts->t3105_ms);
LOGPLCHAN(lchan, DHO, LOGL_DEBUG, "Starting T3105 with %u ms\n", bts->t3105_ms);
lchan->ho.t3105.cb = ho_t3105_cb;
lchan->ho.t3105.data = lchan;
osmo_timer_schedule(&lchan->ho.t3105, 0, bts->t3105_ms * 1000);
}
/* received frist valid data frame on dedicated channel */
/* received first valid data frame on dedicated channel */
void handover_frame(struct gsm_lchan *lchan)
{
LOGP(DHO, LOGL_INFO,
"%s First valid frame detected\n", gsm_lchan_name(lchan));
LOGPLCHAN(lchan, DHO, LOGL_INFO, "First valid frame detected\n");
handover_reset(lchan);
}

View File

@@ -114,9 +114,8 @@ get_active_lchan_by_chan_nr(struct gsm_bts_trx *trx, unsigned int chan_nr)
struct gsm_lchan *lchan = get_lchan_by_chan_nr(trx, chan_nr);
if (lchan && lchan->state != LCHAN_S_ACTIVE) {
LOGP(DL1P, LOGL_NOTICE, "%s: assuming active lchan, but "
"state is %s\n", gsm_lchan_name(lchan),
gsm_lchans_name(lchan->state));
LOGPLCHAN(lchan, DL1P, LOGL_NOTICE, "assuming active lchan, but state is %s\n",
gsm_lchans_name(lchan->state));
return NULL;
}
return lchan;
@@ -139,9 +138,9 @@ static uint32_t fn_ms_adj(uint32_t fn, const struct gsm_lchan *lchan)
r -= r % GSM_RTP_DURATION;
if (r != GSM_RTP_DURATION)
LOGP(DRTP, LOGL_ERROR, "RTP clock out of sync with lower layer:"
" %"PRIu32" vs %d (%"PRIu32"->%"PRIu32")\n",
r, GSM_RTP_DURATION, lchan->tch.last_fn, fn);
LOGPLCHAN(lchan, DRTP, LOGL_ERROR, "RTP clock out of sync with lower layer:"
" %"PRIu32" vs %d (%"PRIu32"->%"PRIu32")\n",
r, GSM_RTP_DURATION, lchan->tch.last_fn, fn);
}
return GSM_RTP_DURATION;
}
@@ -161,7 +160,7 @@ static void queue_limit_to(const char *prefix, struct llist_head *queue, unsigne
}
/* allocate a msgb containing a osmo_phsap_prim + optional l2 data
* in order to wrap femtobts header arround l2 data, there must be enough space
* in order to wrap femtobts header around l2 data, there must be enough space
* in front and behind data pointer */
struct msgb *l1sap_msgb_alloc(unsigned int l2_len)
{
@@ -177,14 +176,19 @@ struct msgb *l1sap_msgb_alloc(unsigned int l2_len)
return msg;
}
/* Enclose rmsg into an osmo_phsap primitive and hand it over to the higher
* layers. The phsap primitive also contains measurement information. The
* parameters rssi, ta_offs and is_sub are only needed when the measurement
* information is passed along with the TCH data. When separate measurement
* indications are used, those last three parameters may be set to zero. */
int add_l1sap_header(struct gsm_bts_trx *trx, struct msgb *rmsg,
struct gsm_lchan *lchan, uint8_t chan_nr, uint32_t fn,
uint16_t ber10k, int16_t lqual_cb)
uint16_t ber10k, int16_t lqual_cb, int8_t rssi,
int16_t ta_offs, uint8_t is_sub)
{
struct osmo_phsap_prim *l1sap;
LOGP(DL1P, LOGL_DEBUG, "%s Rx -> RTP: %s\n",
gsm_lchan_name(lchan), osmo_hexdump(rmsg->data, rmsg->len));
LOGPLCHAN(lchan, DL1P, LOGL_DEBUG, "Rx -> RTP: %s\n", osmo_hexdump(rmsg->data, rmsg->len));
rmsg->l2h = rmsg->data;
rmsg->l1h = msgb_push(rmsg, sizeof(*l1sap));
@@ -196,6 +200,10 @@ int add_l1sap_header(struct gsm_bts_trx *trx, struct msgb *rmsg,
l1sap->u.tch.ber10k = ber10k;
l1sap->u.tch.lqual_cb = lqual_cb;
l1sap->u.tch.rssi = rssi;
l1sap->u.tch.ta_offs_256bits = ta_offs;
l1sap->u.tch.is_sub = is_sub;
return l1sap_up(trx, l1sap);
}
@@ -259,6 +267,85 @@ int bts_check_for_ciph_cmd(struct msgb *msg, struct gsm_lchan *lchan,
return check_for_ciph_cmd(msg, lchan, chan_nr);
}
uint16_t l1sap_log_ctx_sapi;
const struct value_string l1sap_common_sapi_names[] = {
{ L1SAP_COMMON_SAPI_UNKNOWN, "UNKNOWN" },
/* alphabetic order */
{ L1SAP_COMMON_SAPI_AGCH, "AGCH" },
{ L1SAP_COMMON_SAPI_BCCH, "BCCH" },
{ L1SAP_COMMON_SAPI_CBCH, "CBCH" },
{ L1SAP_COMMON_SAPI_FACCH_F, "FACCH/F" },
{ L1SAP_COMMON_SAPI_FACCH_H, "FACCH/H" },
{ L1SAP_COMMON_SAPI_FCCH, "FCCH" },
{ L1SAP_COMMON_SAPI_IDLE, "IDLE" },
{ L1SAP_COMMON_SAPI_NCH, "NCH" },
{ L1SAP_COMMON_SAPI_PACCH, "PACCH" },
{ L1SAP_COMMON_SAPI_PAGCH, "PAGCH" },
{ L1SAP_COMMON_SAPI_PBCCH, "PBCCH" },
{ L1SAP_COMMON_SAPI_PCH, "PCH" },
{ L1SAP_COMMON_SAPI_PDTCH, "PDTCH" },
{ L1SAP_COMMON_SAPI_PNCH, "PNCH" },
{ L1SAP_COMMON_SAPI_PPCH, "PPCH" },
{ L1SAP_COMMON_SAPI_PRACH, "PRACH" },
{ L1SAP_COMMON_SAPI_PTCCH, "PTCCH" },
{ L1SAP_COMMON_SAPI_RACH, "RACH" },
{ L1SAP_COMMON_SAPI_SACCH, "SACCH" },
{ L1SAP_COMMON_SAPI_SCH, "SCH" },
{ L1SAP_COMMON_SAPI_SDCCH, "SDCCH" },
{ L1SAP_COMMON_SAPI_TCH_F, "TCH/F" },
{ L1SAP_COMMON_SAPI_TCH_H, "TCH/H" },
{ 0, NULL }
};
static enum l1sap_common_sapi get_common_sapi_ph_data(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap)
{
uint8_t link_id = l1sap->u.data.link_id;
uint8_t chan_nr = l1sap->u.data.chan_nr;
uint32_t u32Fn = l1sap->u.data.fn;
if (L1SAP_IS_CHAN_TCHF(chan_nr))
return L1SAP_COMMON_SAPI_TCH_F;
if (L1SAP_IS_CHAN_TCHH(chan_nr))
return L1SAP_COMMON_SAPI_TCH_H;
if (L1SAP_IS_CHAN_SDCCH4(chan_nr) || L1SAP_IS_CHAN_SDCCH8(chan_nr))
return L1SAP_COMMON_SAPI_SDCCH;
if (L1SAP_IS_CHAN_BCCH(chan_nr))
return L1SAP_COMMON_SAPI_BCCH;
if (L1SAP_IS_CHAN_AGCH_PCH(chan_nr))
/* The sapi depends on DSP configuration, not on the actual SYSTEM INFORMATION 3. */
return ((l1sap_fn2ccch_block(u32Fn) >= num_agch(trx, "PH-DATA-REQ"))
? L1SAP_COMMON_SAPI_PCH
: L1SAP_COMMON_SAPI_AGCH);
if (L1SAP_IS_CHAN_CBCH(chan_nr))
return L1SAP_COMMON_SAPI_CBCH;
if (L1SAP_IS_LINK_SACCH(link_id))
return L1SAP_COMMON_SAPI_SACCH;
return L1SAP_COMMON_SAPI_UNKNOWN;
}
static enum l1sap_common_sapi get_common_sapi_by_trx_prim(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap)
{
/* Only downlink prims are relevant */
switch (OSMO_PRIM_HDR(&l1sap->oph)) {
case OSMO_PRIM(PRIM_PH_DATA, PRIM_OP_REQUEST):
if (ts_is_pdch(&trx->ts[L1SAP_CHAN2TS(l1sap->u.data.chan_nr)]))
return ((L1SAP_IS_PTCCH(l1sap->u.data.fn))
? L1SAP_COMMON_SAPI_PTCCH
: L1SAP_COMMON_SAPI_PDTCH);
return get_common_sapi_ph_data(trx, l1sap);
default:
return L1SAP_COMMON_SAPI_UNKNOWN;
}
}
struct gsmtap_inst *gsmtap = NULL;
uint32_t gsmtap_sapi_mask = 0;
uint8_t gsmtap_sapi_acch = 0;
@@ -335,15 +422,10 @@ static int gsmtap_pdch(struct osmo_phsap_prim *l1sap, uint8_t *chan_type,
if (L1SAP_IS_PTCCH(fn)) {
*chan_type = GSMTAP_CHANNEL_PTCCH;
*ss = L1SAP_FN2PTCCHBLOCK(fn);
if (l1sap->oph.primitive == PRIM_OP_INDICATION) {
OSMO_ASSERT(len > 0);
if ((*data[0]) == 7)
return -EINVAL;
(*data)++;
(*len)--;
}
} else
*chan_type = GSMTAP_CHANNEL_PACCH;
} else {
/* TODO: distinguish PACCH */
*chan_type = GSMTAP_CHANNEL_PDTCH;
}
return 0;
}
@@ -351,20 +433,29 @@ static int gsmtap_pdch(struct osmo_phsap_prim *l1sap, uint8_t *chan_type,
static int gsmtap_ph_rach(struct osmo_phsap_prim *l1sap, uint8_t *chan_type,
uint8_t *tn, uint8_t *ss, uint32_t *fn, uint8_t **data, unsigned int *len)
{
uint8_t chan_nr;
uint8_t chan_nr = l1sap->u.rach_ind.chan_nr;
*chan_type = GSMTAP_CHANNEL_RACH;
*fn = l1sap->u.rach_ind.fn;
*tn = L1SAP_CHAN2TS(l1sap->u.rach_ind.chan_nr);
chan_nr = l1sap->u.rach_ind.chan_nr;
*tn = L1SAP_CHAN2TS(chan_nr);
if (L1SAP_IS_CHAN_TCHH(chan_nr))
*ss = L1SAP_CHAN2SS_TCHH(chan_nr);
else if (L1SAP_IS_CHAN_SDCCH4(chan_nr))
*ss = L1SAP_CHAN2SS_SDCCH4(chan_nr);
else if (L1SAP_IS_CHAN_SDCCH8(chan_nr))
*ss = L1SAP_CHAN2SS_SDCCH8(chan_nr);
else if (L1SAP_IS_CHAN_PDCH(chan_nr)) {
if (L1SAP_IS_PTCCH(*fn)) {
/* TODO: calculate sub-slot from frame-number */
*chan_type = GSMTAP_CHANNEL_PTCCH;
} else {
*chan_type = GSMTAP_CHANNEL_PDTCH;
}
}
*data = (uint8_t *)&l1sap->u.rach_ind.ra;
*len = 1;
*len = (l1sap->u.rach_ind.is_11bit) ? 2 : 1;
return 0;
}
@@ -377,6 +468,9 @@ static const uint8_t paging_fill[GSM_MACBLOCK_LEN] = {
static bool is_fill_frame(uint8_t chan_type, const uint8_t *data, unsigned int len)
{
if (len != GSM_MACBLOCK_LEN)
return false;
switch (chan_type) {
case GSMTAP_CHANNEL_AGCH:
if (!memcmp(data, fill_frame, GSM_MACBLOCK_LEN))
@@ -486,10 +580,7 @@ static unsigned int calc_exprd_rach_frames(struct gsm_bts *bts, uint32_t fn)
rach_frames_expired = 1;
}
/* Each Frame has room for 4 RACH slots, since RACH
* slots are short enough to fit into a single radio
* burst, so we need to multiply the final result by 4 */
return rach_frames_expired * 4;
return rach_frames_expired;
}
/* time information received from bts model */
@@ -498,6 +589,7 @@ static int l1sap_info_time_ind(struct gsm_bts *bts,
struct info_time_ind_param *info_time_ind)
{
int frames_expired;
int i;
DEBUGPFN(DL1P, info_time_ind->fn, "Rx MPH_INFO time ind\n");
@@ -518,8 +610,10 @@ static int l1sap_info_time_ind(struct gsm_bts *bts,
/* increment number of RACH slots that have passed by since the
* last time indication */
bts->load.rach.total +=
calc_exprd_rach_frames(bts, info_time_ind->fn) * frames_expired;
for (i = 0; i < frames_expired; i++) {
uint32_t fn = (info_time_ind->fn + GSM_HYPERFRAME - i) % GSM_HYPERFRAME;
bts->load.rach.total += calc_exprd_rach_frames(bts, fn);
}
return 0;
}
@@ -530,8 +624,8 @@ static inline void set_ms_to_data(struct gsm_lchan *lchan, int16_t data, bool se
return;
if (data + 63 > 255) { /* According to 3GPP TS 48.058 §9.3.37 Timing Offset field cannot exceed 255 */
LOGP(DL1P, LOGL_ERROR, "Attempting to set invalid Timing Offset value %d (MS TO = %u)!\n",
data, set_ms_to);
LOGPLCHAN(lchan, DL1P, LOGL_ERROR, "Attempting to set invalid Timing Offset value "
"%d (MS TO = %u)!\n", data, set_ms_to);
return;
}
@@ -545,45 +639,96 @@ static inline void set_ms_to_data(struct gsm_lchan *lchan, int16_t data, bool se
}
/* measurement information received from bts model */
static int l1sap_info_meas_ind(struct gsm_bts_trx *trx,
struct osmo_phsap_prim *l1sap,
struct info_meas_ind_param *info_meas_ind)
static void process_l1sap_meas_data(struct gsm_bts_trx *trx,
struct osmo_phsap_prim *l1sap,
enum osmo_ph_prim ind_type)
{
struct bts_ul_meas ulm;
struct gsm_lchan *lchan;
struct info_meas_ind_param *info_meas_ind;
struct ph_data_param *ph_data_ind;
struct ph_tch_param *ph_tch_ind;
uint8_t chan_nr;
uint32_t fn;
uint8_t inv_rssi;
uint8_t is_sub;
int16_t ta_offs_256bits;
uint16_t ber10k;
const char *ind_name;
lchan = get_active_lchan_by_chan_nr(trx, info_meas_ind->chan_nr);
if (!lchan) {
LOGPFN(DL1P, LOGL_ERROR, info_meas_ind->fn,
"No lchan for MPH INFO MEAS IND (chan_nr=%s)\n", rsl_chan_nr_str(info_meas_ind->chan_nr));
return 0;
switch (ind_type) {
case PRIM_MPH_INFO:
/* (legacy way, see also OS#2977) */
info_meas_ind = &l1sap->u.info.u.meas_ind;
chan_nr = info_meas_ind->chan_nr;
fn = info_meas_ind->fn;
inv_rssi = info_meas_ind->inv_rssi;
is_sub = info_meas_ind->is_sub;
ta_offs_256bits = info_meas_ind->ta_offs_256bits;
ber10k = info_meas_ind->ber10k;
ind_name = "MPH INFO";
break;
case PRIM_TCH:
ph_tch_ind = &l1sap->u.tch;
if (ph_tch_ind->rssi == 0)
return;
chan_nr = ph_tch_ind->chan_nr;
fn = ph_tch_ind->fn;
inv_rssi = abs(ph_tch_ind->rssi);
is_sub = ph_tch_ind->is_sub;
ta_offs_256bits = ph_tch_ind->ta_offs_256bits;
ber10k = ph_tch_ind->ber10k;
ind_name = "TCH";
break;
case PRIM_PH_DATA:
ph_data_ind = &l1sap->u.data;
if (ph_data_ind->rssi == 0)
return;
chan_nr = ph_data_ind->chan_nr;
fn = ph_data_ind->fn;
inv_rssi = abs(ph_data_ind->rssi);
is_sub = ph_data_ind->is_sub;
ta_offs_256bits = ph_data_ind->ta_offs_256bits;
ber10k = ph_data_ind->ber10k;
ind_name = "DATA";
break;
default:
OSMO_ASSERT(false);
}
DEBUGPFN(DL1P, info_meas_ind->fn,
"%s MPH_INFO meas ind, ta_offs_256bits=%d, ber10k=%d, inv_rssi=%u\n",
gsm_lchan_name(lchan), info_meas_ind->ta_offs_256bits,
info_meas_ind->ber10k, info_meas_ind->inv_rssi);
lchan = get_active_lchan_by_chan_nr(trx, chan_nr);
if (!lchan) {
LOGPFN(DL1P, LOGL_ERROR, fn,
"No lchan for %s MEAS IND (chan_nr=%s)\n",
ind_name, rsl_chan_nr_str(chan_nr));
return;
}
DEBUGPFN(DL1P, fn,
"%s %s meas ind, ta_offs_256bits=%d, ber10k=%d, inv_rssi=%u\n",
gsm_lchan_name(lchan), ind_name, ta_offs_256bits, ber10k,
inv_rssi);
/* in the GPRS case we are not interested in measurement
* processing. The PCU will take care of it */
if (lchan->type == GSM_LCHAN_PDTCH)
return 0;
return;
memset(&ulm, 0, sizeof(ulm));
ulm.ta_offs_256bits = info_meas_ind->ta_offs_256bits;
ulm.ber10k = info_meas_ind->ber10k;
ulm.inv_rssi = info_meas_ind->inv_rssi;
ulm.is_sub = info_meas_ind->is_sub;
ulm.ta_offs_256bits = ta_offs_256bits;
ulm.ber10k = ber10k;
ulm.inv_rssi = inv_rssi;
ulm.is_sub = is_sub;
/* we assume that symbol period is 1 bit: */
set_ms_to_data(lchan, info_meas_ind->ta_offs_256bits / 256, true);
set_ms_to_data(lchan, ta_offs_256bits / 256, true);
lchan_meas_process_measurement(lchan, &ulm, info_meas_ind->fn);
lchan_meas_process_measurement(lchan, &ulm, fn);
return 0;
return;
}
/* any L1 MPH_INFO indication prim recevied from bts model */
/* any L1 MPH_INFO indication prim received from bts model */
static int l1sap_mph_info_ind(struct gsm_bts_trx *trx,
struct osmo_phsap_prim *l1sap, struct mph_info_param *info)
{
@@ -601,7 +746,12 @@ static int l1sap_mph_info_ind(struct gsm_bts_trx *trx,
&info->u.time_ind);
break;
case PRIM_INFO_MEAS:
rc = l1sap_info_meas_ind(trx, l1sap, &info->u.meas_ind);
/* We should never get an INFO_IND with PRIM_INFO_MEAS
* when BTS_FEAT_MEAS_PAYLOAD_COMB is enabled */
if (gsm_bts_has_feature(trx->bts, BTS_FEAT_MEAS_PAYLOAD_COMB))
OSMO_ASSERT(false);
process_l1sap_meas_data(trx, l1sap, PRIM_MPH_INFO);
break;
default:
LOGP(DL1P, LOGL_NOTICE, "unknown MPH_INFO ind type %d\n",
@@ -617,12 +767,10 @@ static int l1sap_info_act_cnf(struct gsm_bts_trx *trx,
struct osmo_phsap_prim *l1sap,
struct info_act_cnf_param *info_act_cnf)
{
struct gsm_lchan *lchan;
struct gsm_lchan *lchan = get_lchan_by_chan_nr(trx, info_act_cnf->chan_nr);
LOGP(DL1C, LOGL_INFO, "activate confirm chan_nr=%s trx=%d\n",
rsl_chan_nr_str(info_act_cnf->chan_nr), trx->nr);
lchan = get_lchan_by_chan_nr(trx, info_act_cnf->chan_nr);
LOGPLCHAN(lchan, DL1C, LOGL_INFO, "activate confirm chan_nr=%s trx=%d\n",
rsl_chan_nr_str(info_act_cnf->chan_nr), trx->nr);
rsl_tx_chan_act_acknack(lchan, info_act_cnf->cause);
@@ -642,12 +790,10 @@ static int l1sap_info_rel_cnf(struct gsm_bts_trx *trx,
struct osmo_phsap_prim *l1sap,
struct info_act_cnf_param *info_act_cnf)
{
struct gsm_lchan *lchan;
struct gsm_lchan *lchan = get_lchan_by_chan_nr(trx, info_act_cnf->chan_nr);
LOGP(DL1C, LOGL_INFO, "deactivate confirm chan_nr=%s trx=%d\n",
rsl_chan_nr_str(info_act_cnf->chan_nr), trx->nr);
lchan = get_lchan_by_chan_nr(trx, info_act_cnf->chan_nr);
LOGPLCHAN(lchan, DL1C, LOGL_INFO, "deactivate confirm chan_nr=%s trx=%d\n",
rsl_chan_nr_str(info_act_cnf->chan_nr), trx->nr);
rsl_tx_rf_rel_ack(lchan);
@@ -661,7 +807,7 @@ static int l1sap_info_rel_cnf(struct gsm_bts_trx *trx,
return 0;
}
/* any L1 MPH_INFO confirm prim recevied from bts model */
/* any L1 MPH_INFO confirm prim received from bts model */
static int l1sap_mph_info_cnf(struct gsm_bts_trx *trx,
struct osmo_phsap_prim *l1sap, struct mph_info_param *info)
{
@@ -721,10 +867,37 @@ static int lchan_pdtch_ph_rts_ind_loop(struct gsm_lchan *lchan,
int is_ccch_for_agch(struct gsm_bts_trx *trx, uint32_t fn) {
/* Note: The number of available access grant channels is set by the
* parameter BS_AG_BLKS_RES via system information type 3. This SI is
* transfered to osmo-bts via RSL */
* transferred to osmo-bts via RSL */
return l1sap_fn2ccch_block(fn) < num_agch(trx, "PH-RTS-IND");
}
/* return the measured average of frame numbers that the RTS clock is running in advance */
int32_t bts_get_avg_fn_advance(struct gsm_bts *bts)
{
if (bts->fn_stats.avg_count == 0)
return 0;
return bts->fn_stats.avg256 / bts->fn_stats.avg_count;
}
static void l1sap_update_fnstats(struct gsm_bts *bts, uint32_t rts_fn)
{
int32_t delta = (rts_fn + GSM_HYPERFRAME - bts->gsm_time.fn) % GSM_HYPERFRAME;
if (delta < bts->fn_stats.min)
bts->fn_stats.min = delta;
if (delta > bts->fn_stats.max)
bts->fn_stats.max = delta;
if (bts->fn_stats.avg_count > bts->fn_stats.avg_window) {
/* reset and start old average and new sample */
bts->fn_stats.avg256 = (bts->fn_stats.avg256 / bts->fn_stats.avg_count) + delta;
bts->fn_stats.avg_count = 2;
} else {
bts->fn_stats.avg256 += delta;
bts->fn_stats.avg_count++;
}
}
/* PH-RTS-IND prim received from bts model */
static int l1sap_ph_rts_ind(struct gsm_bts_trx *trx,
struct osmo_phsap_prim *l1sap, struct ph_data_param *rts_ind)
@@ -751,6 +924,8 @@ static int l1sap_ph_rts_ind(struct gsm_bts_trx *trx,
DEBUGPGT(DL1P, &g_time, "Rx PH-RTS.ind chan_nr=%s link_id=0x%02xd\n", rsl_chan_nr_str(chan_nr), link_id);
l1sap_update_fnstats(trx->bts, fn);
/* reuse PH-RTS.ind for PH-DATA.req */
if (!msg) {
LOGPGT(DL1P, LOGL_FATAL, &g_time, "RTS without msg to be reused. Please fix!\n");
@@ -770,10 +945,10 @@ static int l1sap_ph_rts_ind(struct gsm_bts_trx *trx,
} else {
/* forward RTS.ind to PCU */
if (L1SAP_IS_PTCCH(rts_ind->fn)) {
pcu_tx_rts_req(&trx->ts[tn], 1, fn, 1 /* ARFCN */,
pcu_tx_rts_req(&trx->ts[tn], 1, fn, trx->arfcn,
L1SAP_FN2PTCCHBLOCK(fn));
} else {
pcu_tx_rts_req(&trx->ts[tn], 0, fn, 0 /* ARFCN */,
pcu_tx_rts_req(&trx->ts[tn], 0, fn, trx->arfcn,
L1SAP_FN2MACBLOCK(fn));
}
/* return early, PCU takes care of rest */
@@ -894,15 +1069,15 @@ static bool rtppayload_is_valid(struct gsm_lchan *lchan, struct msgb *resp_msg)
* don't support it. */
if(lchan->tch_mode == GSM48_CMODE_SPEECH_AMR &&
!rtppayload_is_octet_aligned(resp_msg->data, resp_msg->len)) {
LOGP(DL1P, LOGL_NOTICE,
"%s RTP->L1: Dropping unexpected AMR encoding (bw-efficient?) %s\n",
gsm_lchan_name(lchan), osmo_hexdump(resp_msg->data, resp_msg->len));
LOGPLCHAN(lchan, DL1P, LOGL_NOTICE,
"RTP->L1: Dropping unexpected AMR encoding (bw-efficient?) %s\n",
osmo_hexdump(resp_msg->data, resp_msg->len));
return false;
}
return true;
}
/* TCH-RTS-IND prim recevied from bts model */
/* TCH-RTS-IND prim received from bts model */
static int l1sap_tch_rts_ind(struct gsm_bts_trx *trx,
struct osmo_phsap_prim *l1sap, struct ph_tch_param *rts_ind)
{
@@ -1003,8 +1178,12 @@ static void radio_link_timeout(struct gsm_lchan *lchan, int bad_frame)
lchan->s--;
DEBUGP(DMEAS, "%s counting down radio link counter S=%d\n",
gsm_lchan_name(lchan), lchan->s);
if (lchan->s == 0)
if (lchan->s == 0) {
LOGPLCHAN(lchan, DMEAS, LOGL_NOTICE,
"radio link counter timeout S=%d, dropping conn\n",
lchan->s);
rsl_tx_conn_fail(lchan, RSL_ERR_RADIO_LINK_FAIL);
}
return;
}
@@ -1078,11 +1257,26 @@ static int l1sap_ph_data_ind(struct gsm_bts_trx *trx,
DEBUGPGT(DL1P, &g_time, "Rx PH-DATA.ind chan_nr=%s link_id=0x%02x len=%d\n",
rsl_chan_nr_str(chan_nr), link_id, len);
/* Actually, there can be no DATA.ind on PTCCH/U (rather RACH.ind instead),
* but some BTS models with buggy implementation may still be sending them
* to us. Let's keep this for backwards compatibility. */
if (L1SAP_IS_CHAN_PDCH(chan_nr) && L1SAP_IS_PTCCH(fn)) {
LOGPGT(DL1P, LOGL_NOTICE, &g_time, "There can be no DATA.ind on PTCCH/U. "
"This is probably a bug of the BTS model you're using, please fix!\n");
return -EINVAL;
}
/* The ph_data_param contained in the l1sap primitive may contain
* measurement data. If this data is present, forward it for
* processing */
if (gsm_bts_has_feature(trx->bts, BTS_FEAT_MEAS_PAYLOAD_COMB))
process_l1sap_meas_data(trx, l1sap, PRIM_PH_DATA);
if (ts_is_pdch(&trx->ts[tn])) {
lchan = get_lchan_by_chan_nr(trx, chan_nr);
if (!lchan)
LOGPGT(DL1P, LOGL_ERROR, &g_time, "No lchan for chan_nr=%s\n", rsl_chan_nr_str(chan_nr));
if (lchan && lchan->loopback && !L1SAP_IS_PTCCH(fn)) {
if (lchan && lchan->loopback) {
/* we are in loopback mode (for BER testing)
* mode and need to enqeue the frame to be
* returned in downlink */
@@ -1097,21 +1291,14 @@ static int l1sap_ph_data_ind(struct gsm_bts_trx *trx,
/* don't send bad frames to PCU */
if (len == 0)
return -EINVAL;
if (L1SAP_IS_PTCCH(fn)) {
pcu_tx_data_ind(&trx->ts[tn], PCU_IF_SAPI_PTCCH, fn,
0 /* ARFCN */, L1SAP_FN2PTCCHBLOCK(fn),
data, len, rssi, data_ind->ber10k,
data_ind->ta_offs_256bits/64,
data_ind->lqual_cb);
} else {
/* drop incomplete UL block */
if (pr_info != PRES_INFO_BOTH)
return 0;
/* PDTCH / PACCH frame handling */
pcu_tx_data_ind(&trx->ts[tn], PCU_IF_SAPI_PDTCH, fn, 0 /* ARFCN */,
L1SAP_FN2MACBLOCK(fn), data, len, rssi, data_ind->ber10k,
data_ind->ta_offs_256bits/64, data_ind->lqual_cb);
}
/* drop incomplete UL block */
if (pr_info != PRES_INFO_BOTH)
return 0;
/* PDTCH / PACCH frame handling */
pcu_tx_data_ind(&trx->ts[tn], PCU_IF_SAPI_PDTCH, fn, trx->arfcn,
L1SAP_FN2MACBLOCK(fn), data, len, rssi, data_ind->ber10k,
data_ind->ta_offs_256bits/64, data_ind->lqual_cb);
return 0;
}
@@ -1123,8 +1310,19 @@ static int l1sap_ph_data_ind(struct gsm_bts_trx *trx,
/* bad frame */
if (len == 0) {
if (L1SAP_IS_LINK_SACCH(link_id))
if (L1SAP_IS_LINK_SACCH(link_id)) {
/* In case we loose a SACCH block, we must take care
* that the related measurement report is sent via RSL.
* This is a fallback method. The report will also
* lack the measurement report from the MS side. See
* also rsl.c:lapdm_rll_tx_cb() */
LOGPGT(DL1P, LOGL_INFO, &g_time, "Lost SACCH block, faking meas reports and ms pwr\n");
le = &lchan->lapdm_ch.lapdm_acch;
rsl_tx_meas_res(lchan, NULL, 0, le);
radio_link_timeout(lchan, 1);
lchan_ms_pwr_ctrl(lchan, lchan->ms_power_ctrl.current, data_ind->rssi);
}
return -EINVAL;
}
@@ -1142,7 +1340,7 @@ static int l1sap_ph_data_ind(struct gsm_bts_trx *trx,
}
/* Some brilliant engineer decided that the ordering of
* fields on the Um interface is different from the
* order of fields in RLS. See TS 04.04 (Chapter 7.2)
* order of fields in RSL. See TS 04.04 (Chapter 7.2)
* vs. TS 08.58 (Chapter 9.3.10). */
lchan->meas.l1_info[0] = data[0] << 3;
lchan->meas.l1_info[0] |= ((data[0] >> 5) & 1) << 2;
@@ -1157,8 +1355,7 @@ static int l1sap_ph_data_ind(struct gsm_bts_trx *trx,
l1sap_tx_ciph_req(lchan->ts->trx, chan_nr, 1, 0);
/* SDCCH, SACCH and FACCH all go to LAPDm */
msgb_pull(msg, (msg->l2h - msg->data));
msg->l1h = NULL;
msgb_pull_to_l2(msg);
lapdm_phsap_up(&l1sap->oph, le);
/* don't free, because we forwarded data */
@@ -1181,7 +1378,7 @@ static int l1sap_tch_ind(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap,
gsm_fn2gsmtime(&g_time, fn);
LOGPGT(DL1P, LOGL_INFO, &g_time, "Rx TCH.ind chan_nr=%s\n", rsl_chan_nr_str(chan_nr));
LOGPGT(DL1P, LOGL_DEBUG, &g_time, "Rx TCH.ind chan_nr=%s\n", rsl_chan_nr_str(chan_nr));
lchan = get_active_lchan_by_chan_nr(trx, chan_nr);
if (!lchan) {
@@ -1189,13 +1386,19 @@ static int l1sap_tch_ind(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap,
return 0;
}
msgb_pull(msg, sizeof(*l1sap));
/* The ph_tch_param contained in the l1sap primitive may contain
* measurement data. If this data is present, forward it for
* processing */
if (gsm_bts_has_feature(trx->bts, BTS_FEAT_MEAS_PAYLOAD_COMB))
process_l1sap_meas_data(trx, l1sap, PRIM_TCH);
msgb_pull_to_l2(msg);
/* Low level layers always call us when TCH content is expected, even if
* the content is not available due to decoding issues. Content not
* available is expected as empty payload. We also check if quality is
* good enough. */
if (msg->len && tch_ind->lqual_cb / 10 >= bts->min_qual_norm) {
if (msg->len && tch_ind->lqual_cb >= bts->min_qual_norm) {
/* hand msg to RTP code for transmission */
if (lchan->abis_ip.rtp_socket)
osmo_rtp_send_frame_ext(lchan->abis_ip.rtp_socket,
@@ -1225,14 +1428,15 @@ static int l1sap_tch_ind(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap,
#define RACH_MIN_TOA256 -2 * 256
static bool rach_pass_filter(struct ph_rach_ind_param *rach_ind, struct gsm_bts *bts)
static bool rach_pass_filter(struct ph_rach_ind_param *rach_ind, struct gsm_bts *bts,
const char *chan_name)
{
int16_t toa256 = rach_ind->acc_delay_256bits;
/* Check for RACH exceeding BER threshold (ghost RACH) */
if (rach_ind->ber10k > bts->max_ber10k_rach) {
LOGPFN(DL1C, LOGL_INFO, rach_ind->fn, "Ignoring RACH request: "
"BER10k(%u) > BER10k_MAX(%u)\n",
LOGPFN(DL1C, LOGL_DEBUG, rach_ind->fn, "Ignoring an Access Burst on %s: "
"BER10k(%u) > BER10k_MAX(%u)\n", chan_name,
rach_ind->ber10k, bts->max_ber10k_rach);
return false;
}
@@ -1243,21 +1447,28 @@ static bool rach_pass_filter(struct ph_rach_ind_param *rach_ind, struct gsm_bts
* according to maximal allowed Timing Advance value.
*/
if (toa256 < RACH_MIN_TOA256 || toa256 > bts->max_ta * 256) {
LOGPFN(DL1C, LOGL_INFO, rach_ind->fn, "Ignoring RACH request: "
"ToA(%d) exceeds the allowed range (%d..%d)\n",
LOGPFN(DL1C, LOGL_DEBUG, rach_ind->fn, "Ignoring an Access Burst on %s: "
"ToA(%d) exceeds the allowed range (%d..%d)\n", chan_name,
toa256, RACH_MIN_TOA256, bts->max_ta * 256);
return false;
}
/* Link quality defined by C/I (Carrier-to-Interference ratio) */
if (rach_ind->lqual_cb < bts->min_qual_rach) {
LOGPFN(DL1C, LOGL_DEBUG, rach_ind->fn, "Ignoring an Access Burst on %s: "
"link quality (%d) below the minimum (%d)\n", chan_name,
rach_ind->lqual_cb, bts->min_qual_rach);
return false;
}
return true;
}
/* Special case where handover RACH is detected */
static int l1sap_handover_rach(struct gsm_bts_trx *trx,
struct osmo_phsap_prim *l1sap, struct ph_rach_ind_param *rach_ind)
static int l1sap_handover_rach(struct gsm_bts_trx *trx, struct ph_rach_ind_param *rach_ind)
{
/* Filter out noise / interference / ghosts */
if (!rach_pass_filter(rach_ind, trx->bts)) {
if (!rach_pass_filter(rach_ind, trx->bts, "handover")) {
rate_ctr_inc2(trx->bts->ctrs, BTS_CTR_RACH_DROP);
return 0;
}
@@ -1269,6 +1480,33 @@ static int l1sap_handover_rach(struct gsm_bts_trx *trx,
return 0;
}
/* Special case for Access Bursts on PDTCH/U or PTCCH/U */
static int l1sap_pdch_rach(struct gsm_bts_trx *trx, struct ph_rach_ind_param *rach_ind)
{
/* Filter out noise / interference / ghosts */
if (!rach_pass_filter(rach_ind, trx->bts, "PDCH"))
return -EAGAIN;
/* PTCCH/U (Packet Timing Advance Control Channel) */
if (L1SAP_IS_PTCCH(rach_ind->fn)) {
LOGPFN(DL1P, LOGL_DEBUG, rach_ind->fn,
/* TODO: calculate and print Timing Advance Index */
"Access Burst for continuous Timing Advance control (toa256=%d)\n",
rach_ind->acc_delay_256bits);
/* QTA: Timing Advance in units of 1/4 of a symbol */
pcu_tx_rach_ind(trx->bts->nr, trx->nr, rach_ind->chan_nr & 0x07,
rach_ind->acc_delay_256bits >> 6,
rach_ind->ra, rach_ind->fn, rach_ind->is_11bit,
rach_ind->burst_type, PCU_IF_SAPI_PTCCH);
return 0;
} else { /* The MS may acknowledge DL data by 4 consequent Access Bursts */
LOGPFN(DL1P, LOGL_NOTICE, rach_ind->fn,
"Access Bursts on PDTCH/U are not (yet) supported\n");
return -ENOTSUP;
}
}
/* RACH received from bts model */
static int l1sap_ph_rach_ind(struct gsm_bts_trx *trx,
struct osmo_phsap_prim *l1sap, struct ph_rach_ind_param *rach_ind)
@@ -1276,12 +1514,19 @@ static int l1sap_ph_rach_ind(struct gsm_bts_trx *trx,
struct gsm_bts *bts = trx->bts;
struct lapdm_channel *lc;
DEBUGPFN(DL1P, rach_ind->fn, "Rx PH-RA.ind");
DEBUGPFN(DL1P, rach_ind->fn, "Rx PH-RA.ind\n");
/* check for handover access burst on dedicated channels */
if (!L1SAP_IS_CHAN_RACH(rach_ind->chan_nr)) {
/* Check the origin of an Access Burst */
switch (rach_ind->chan_nr & 0xf8) {
case RSL_CHAN_RACH:
/* CS or PS RACH, to be handled in this function */
break;
case RSL_CHAN_OSMO_PDCH:
/* TODO: do we need to count Access Bursts on PDCH? */
return l1sap_pdch_rach(trx, rach_ind);
default:
rate_ctr_inc2(trx->bts->ctrs, BTS_CTR_RACH_HO);
return l1sap_handover_rach(trx, l1sap, rach_ind);
return l1sap_handover_rach(trx, rach_ind);
}
rate_ctr_inc2(trx->bts->ctrs, BTS_CTR_RACH_RCVD);
@@ -1291,7 +1536,7 @@ static int l1sap_ph_rach_ind(struct gsm_bts_trx *trx,
bts->load.rach.busy++;
/* Filter out noise / interference / ghosts */
if (!rach_pass_filter(rach_ind, bts)) {
if (!rach_pass_filter(rach_ind, bts, "CCCH")) {
rate_ctr_inc2(trx->bts->ctrs, BTS_CTR_RACH_DROP);
return 0;
}
@@ -1313,9 +1558,11 @@ static int l1sap_ph_rach_ind(struct gsm_bts_trx *trx,
LOGPFN(DL1P, LOGL_INFO, rach_ind->fn, "RACH for packet access (toa=%d, ra=%d)\n",
rach_ind->acc_delay, rach_ind->ra);
pcu_tx_rach_ind(bts, rach_ind->acc_delay << 2,
rach_ind->ra, rach_ind->fn,
rach_ind->is_11bit, rach_ind->burst_type);
/* QTA: Timing Advance in units of 1/4 of a symbol */
pcu_tx_rach_ind(bts->nr, trx->nr, rach_ind->chan_nr & 0x07,
rach_ind->acc_delay_256bits >> 6,
rach_ind->ra, rach_ind->fn, rach_ind->is_11bit,
rach_ind->burst_type, PCU_IF_SAPI_RACH);
return 0;
}
@@ -1364,8 +1611,10 @@ int l1sap_up(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap)
default:
LOGP(DL1P, LOGL_NOTICE, "unknown prim %d op %d\n",
l1sap->oph.primitive, l1sap->oph.operation);
oml_fail_rep(OSMO_EVT_MAJ_UKWN_MSG, "unknown prim %d op %d",
l1sap->oph.primitive, l1sap->oph.operation);
oml_tx_failure_event_rep(&trx->mo, NM_SEVER_MAJOR, OSMO_EVT_MAJ_UKWN_MSG,
"unknown prim %d op %d",
l1sap->oph.primitive,
l1sap->oph.operation);
break;
}
@@ -1379,6 +1628,9 @@ int l1sap_up(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap)
/* any L1 prim sent to bts model */
static int l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap)
{
l1sap_log_ctx_sapi = get_common_sapi_by_trx_prim(trx, l1sap);
log_set_context(LOG_CTX_L1_SAPI, &l1sap_log_ctx_sapi);
if (OSMO_PRIM_HDR(&l1sap->oph) ==
OSMO_PRIM(PRIM_PH_DATA, PRIM_OP_REQUEST))
to_gsmtap(trx, l1sap);
@@ -1388,7 +1640,7 @@ static int l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap)
/* pcu (socket interface) sends us a data request primitive */
int l1sap_pdch_req(struct gsm_bts_trx_ts *ts, int is_ptcch, uint32_t fn,
uint16_t arfcn, uint8_t block_nr, uint8_t *data, uint8_t len)
uint16_t arfcn, uint8_t block_nr, const uint8_t *data, uint8_t len)
{
struct msgb *msg;
struct osmo_phsap_prim *l1sap;
@@ -1467,8 +1719,8 @@ int l1sap_chan_act(struct gsm_bts_trx *trx, uint8_t chan_nr, struct tlv_parsed *
struct gsm48_chan_desc *cd;
int rc;
LOGP(DL1C, LOGL_INFO, "activating channel chan_nr=%s trx=%d\n",
rsl_chan_nr_str(chan_nr), trx->nr);
LOGPLCHAN(lchan, DL1C, LOGL_INFO, "activating channel chan_nr=%s trx=%d\n",
rsl_chan_nr_str(chan_nr), trx->nr);
/* osmo-pcu calls this without a valid 'tp' parameter, so we
* need to make sure ew don't crash here */
@@ -1481,8 +1733,8 @@ int l1sap_chan_act(struct gsm_bts_trx *trx, uint8_t chan_nr, struct tlv_parsed *
* one one TRX, so we need to make sure not to activate
* channels with a different TSC!! */
if (cd->h0.tsc != (lchan->ts->trx->bts->bsic & 7)) {
LOGP(DL1C, LOGL_ERROR, "lchan TSC %u != BSIC-TSC %u\n",
cd->h0.tsc, lchan->ts->trx->bts->bsic & 7);
LOGPLCHAN(lchan, DL1C, LOGL_ERROR, "lchan TSC %u != BSIC-TSC %u\n",
cd->h0.tsc, lchan->ts->trx->bts->bsic & 7);
return -RSL_ERR_SERV_OPT_UNIMPL;
}
}
@@ -1515,8 +1767,8 @@ int l1sap_chan_act(struct gsm_bts_trx *trx, uint8_t chan_nr, struct tlv_parsed *
int l1sap_chan_rel(struct gsm_bts_trx *trx, uint8_t chan_nr)
{
struct gsm_lchan *lchan = get_lchan_by_chan_nr(trx, chan_nr);
LOGP(DL1C, LOGL_INFO, "deactivating channel chan_nr=%s trx=%d\n",
rsl_chan_nr_str(chan_nr), trx->nr);
LOGPLCHAN(lchan, DL1C, LOGL_INFO, "deactivating channel chan_nr=%s trx=%d\n",
rsl_chan_nr_str(chan_nr), trx->nr);
if (lchan->tch.dtx.dl_amr_fsm) {
osmo_fsm_inst_free(lchan->tch.dtx.dl_amr_fsm);
@@ -1531,8 +1783,8 @@ int l1sap_chan_deact_sacch(struct gsm_bts_trx *trx, uint8_t chan_nr)
{
struct gsm_lchan *lchan = get_lchan_by_chan_nr(trx, chan_nr);
LOGP(DL1C, LOGL_INFO, "deactivating sacch chan_nr=%s trx=%d\n",
rsl_chan_nr_str(chan_nr), trx->nr);
LOGPLCHAN(lchan, DL1C, LOGL_INFO, "deactivating sacch chan_nr=%s trx=%d\n",
rsl_chan_nr_str(chan_nr), trx->nr);
lchan->sacch_deact = 1;

View File

@@ -32,6 +32,7 @@ static void reset_load_counters(struct gsm_bts *bts)
{
/* re-set the counters */
bts->load.ccch.pch_used = bts->load.ccch.pch_total = 0;
bts->load.rach.busy = bts->load.rach.access = bts->load.rach.total = 0;
}
static void load_timer_cb(void *data)
@@ -51,7 +52,7 @@ static void load_timer_cb(void *data)
uint16_t buffer_space = paging_buffer_space(bts->paging_state);
rsl_tx_ccch_load_ind_pch(bts, buffer_space);
} else {
/* This is an extenstion of TS 08.58. We don't only
/* This is an extension of TS 08.58. We don't only
* send load indications if the load is above threshold,
* but we also explicitly indicate that we are below
* threshold by using the magic value 0xffff */

View File

@@ -144,7 +144,21 @@ static struct log_info_cat bts_log_info_cat[] = {
},
};
static int osmo_bts_filter_fn(const struct log_context *ctx, struct log_target *tgt)
{
uint8_t *sapi = ctx->ctx[LOG_CTX_L1_SAPI];
uint16_t *sapi_mask = tgt->filter_data[LOG_FLT_L1_SAPI];
if ((tgt->filter_map & (1 << LOG_FLT_L1_SAPI)) != 0
&& sapi_mask && sapi
&& (*sapi_mask & (1 << *sapi)) != 0)
return 1;
return 0;
}
const struct log_info bts_log_info = {
.filter_fn = osmo_bts_filter_fn,
.cat = bts_log_info_cat,
.num_cat = ARRAY_SIZE(bts_log_info_cat),
};

View File

@@ -33,6 +33,7 @@
#include <netinet/in.h>
#include <arpa/inet.h>
#include <osmocom/core/stats.h>
#include <osmocom/core/talloc.h>
#include <osmocom/core/application.h>
#include <osmocom/vty/telnet_interface.h>
@@ -182,8 +183,9 @@ static void signal_handler(int signal)
case SIGINT:
case SIGTERM:
if (!quit) {
oml_fail_rep(OSMO_EVT_CRIT_PROC_STOP,
"BTS: SIGINT received -> shutdown");
oml_tx_failure_event_rep(&bts->mo,
NM_SEVER_CRITICAL, OSMO_EVT_CRIT_PROC_STOP,
"BTS: SIGINT received -> shutdown");
bts_shutdown(bts, "SIGINT");
}
quit++;
@@ -191,9 +193,6 @@ static void signal_handler(int signal)
case SIGABRT:
case SIGUSR1:
case SIGUSR2:
oml_fail_rep(OSMO_EVT_CRIT_PROC_STOP,
"BTS: signal %d (%s) received", signal,
strsignal(signal));
talloc_report_full(tall_bts_ctx, stderr);
break;
default:
@@ -236,6 +235,7 @@ int bts_main(int argc, char **argv)
bts_vty_info.tall_ctx = tall_bts_ctx;
osmo_init_logging2(tall_bts_ctx, &bts_log_info);
osmo_stats_init(tall_bts_ctx);
vty_init(&bts_vty_info);
ctrl_vty_init(tall_bts_ctx);
rate_ctr_init(tall_bts_ctx);
@@ -249,7 +249,7 @@ int bts_main(int argc, char **argv)
}
e1inp_vty_init();
bts_vty_init(bts, &bts_log_info);
bts_vty_init(bts);
/* enable realtime priority for us */
if (rt_prio != -1) {

View File

@@ -10,6 +10,7 @@
#include <osmo-bts/measurement.h>
#include <osmo-bts/scheduler.h>
#include <osmo-bts/rsl.h>
#include <osmo-bts/ta_control.h>
/* Tables as per TS 45.008 Section 8.3 */
static const uint8_t ts45008_83_tch_f[] = { 52, 53, 54, 55, 56, 57, 58, 59 };
@@ -340,7 +341,7 @@ int lchan_new_ul_meas(struct gsm_lchan *lchan, struct bts_ul_meas *ulm, uint32_t
}
/* We expect the lower layers to mark AMR SID_UPDATE frames already as such.
* In this function, we only deal with the comon logic as per the TS 45.008 tables */
* In this function, we only deal with the common logic as per the TS 45.008 tables */
if (!ulm->is_sub)
ulm->is_sub = ts45008_83_is_sub(lchan, fn, false);
@@ -655,14 +656,14 @@ int lchan_meas_check_compute(struct gsm_lchan *lchan, uint32_t fn)
ber_full_sum = ber_full_sum / num_ul_meas;
if (!irssi_full_sum)
ber_full_sum = MEASUREMENT_DUMMY_IRSSI;
irssi_full_sum = MEASUREMENT_DUMMY_IRSSI;
else
irssi_full_sum = irssi_full_sum / num_ul_meas_actual;
if (!num_ul_meas_actual)
ta256b_sum = lchan->meas.ms_toa256;
else
ta256b_sum = ta256b_sum / num_ul_meas_actual;
ta256b_sum = ta256b_sum / (signed)num_ul_meas_actual;
if (!num_meas_sub)
ber_sub_sum = MEASUREMENT_DUMMY_BER;
@@ -696,9 +697,14 @@ int lchan_meas_check_compute(struct gsm_lchan *lchan, uint32_t fn)
lchan_meas_compute_extended(lchan);
/* Compute new ta_req value. This has to be done here since the value
* in lchan->meas.num_ul_meas together with lchan->meas.ms_toa256
* is needed for the computation. */
lchan_ms_ta_ctrl(lchan);
lchan->meas.num_ul_meas = 0;
/* return 1 to indicte that the computation has been done and the next
/* return 1 to indicate that the computation has been done and the next
* interval begins. */
return 1;
}

View File

@@ -203,8 +203,8 @@ int dtx_dl_amr_fsm_step(struct gsm_lchan *lchan, const uint8_t *rtp_pl,
rc = osmo_amr_rtp_dec(rtp_pl, rtp_pl_len, &cmr, &cmi, &ft, &bfi, &sti);
if (rc < 0) {
LOGP(DRTP, LOGL_ERROR, "failed to decode AMR RTP (length %zu, "
"%p)\n", rtp_pl_len, rtp_pl);
LOGPLCHAN(lchan, DRTP, LOGL_ERROR, "failed to decode AMR RTP (length %zu, "
"%p)\n", rtp_pl_len, rtp_pl);
return rc;
}
@@ -274,7 +274,7 @@ int dtx_dl_amr_fsm_step(struct gsm_lchan *lchan, const uint8_t *rtp_pl,
}
if (ft != AMR_NO_DATA) {
LOGP(DRTP, LOGL_ERROR, "unsupported AMR FT 0x%02x\n", ft);
LOGPLCHAN(lchan, DRTP, LOGL_ERROR, "unsupported AMR FT 0x%02x\n", ft);
return -ENOTSUP;
}
@@ -505,9 +505,9 @@ uint8_t repeat_last_sid(struct gsm_lchan *lchan, uint8_t *dst, uint32_t fn)
return lchan->tch.dtx.len + 1;
}
LOGP(DL1C, LOGL_DEBUG, "Have to send %s frame on TCH but SID buffer "
"is empty - sent nothing\n",
get_value_string(gsm48_chan_mode_names, lchan->tch_mode));
LOGPLCHAN(lchan, DL1C, LOGL_DEBUG, "Have to send %s frame on TCH but SID buffer "
"is empty - sent nothing\n",
get_value_string(gsm48_chan_mode_names, lchan->tch_mode));
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@@ -21,7 +21,7 @@
/* TODO:
* eMLPP priprity
* add P1/P2/P3 rest octets
* add P2/P3 rest octets
*/
#include <stdlib.h>
@@ -274,11 +274,86 @@ int paging_add_imm_ass(struct paging_state *ps, const uint8_t *data,
#define L2_PLEN(len) (((len - 1) << 2) | 0x01)
/* abstract representation of P1 rest octets; we only implement those parts we need for now */
struct p1_rest_octets {
bool packet_page_ind[2];
bool r8_present;
struct {
bool prio_ul_access;
bool etws_present;
struct {
bool is_first;
uint8_t page_nr;
const uint8_t *page;
size_t page_bytes;
} etws;
} r8;
};
/* 3GPP TS 44.018 10.5.2.23 append a segment/page of an ETWS primary notification to given bitvec */
static void append_etws_prim_notif(struct bitvec *bv, bool is_first, uint8_t page_nr,
const uint8_t *etws, ssize_t etws_len)
{
OSMO_ASSERT(etws_len < 128/8);
/* ETWS primary Notification struct
* 0 NNNN / 1 NNNN
* PNI n
* LEN nnnnnnn (at least 13 bits before paylod)
* number of bits (LEN; up to 128) */
if (is_first)
bitvec_set_bit(bv, 0);
else
bitvec_set_bit(bv, 1);
bitvec_set_uint(bv, page_nr, 4); /* Segment Number / Total Number */
bitvec_set_bit(bv, 0); /* PNI to distinguish different ETWS */
bitvec_set_uint(bv, etws_len*8, 7); /* length of payload in number of bits */
bitvec_set_bytes(bv, etws, etws_len);
/* 17 bytes = 136bit - (11+13) = 112 bits = 14 bytes per PT1
* => at least 4x PT1 RO for complete primary notification (56 bytes) */
}
/* 3GPP TS 44.018 10.5.2.23 append P1 Rest Octets to given bit-vector */
static void append_p1_rest_octets(struct bitvec *bv, const struct p1_rest_octets *p1ro)
{
/* Paging 1 RO (at least 10 bits before ETWS struct) */
bitvec_set_bit(bv, L); /* no NLN */
bitvec_set_bit(bv, L); /* no Priority1 */
bitvec_set_bit(bv, L); /* no Priority2 */
bitvec_set_bit(bv, L); /* no Group Call Info */
if (p1ro->packet_page_ind[0])
bitvec_set_bit(bv, H); /* Packet Page Indication 1 */
else
bitvec_set_bit(bv, L); /* Packet Page Indication 1 */
if (p1ro->packet_page_ind[1])
bitvec_set_bit(bv, H); /* Packet Page Indication 2 */
else
bitvec_set_bit(bv, L); /* Packet Page Indication 2 */
bitvec_set_bit(bv, L); /* No Release 6 additions */
bitvec_set_bit(bv, L); /* No Release 7 additions */
if (p1ro->r8_present) {
bitvec_set_bit(bv, H); /* Release 8 */
bitvec_set_bit(bv, p1ro->r8.prio_ul_access); /* Priority Uplink Access */
if (p1ro->r8.etws_present) {
bitvec_set_bit(bv, 1); /* ETWS present */
append_etws_prim_notif(bv, p1ro->r8.etws.is_first, p1ro->r8.etws.page_nr,
p1ro->r8.etws.page, p1ro->r8.etws.page_bytes);
} else
bitvec_set_bit(bv, 0);
}
}
static int fill_paging_type_1(uint8_t *out_buf, const uint8_t *identity1_lv,
uint8_t chan1, const uint8_t *identity2_lv,
uint8_t chan2)
uint8_t chan2, const struct p1_rest_octets *p1ro)
{
struct gsm48_paging1 *pt1 = (struct gsm48_paging1 *) out_buf;
struct bitvec bv;
unsigned int paging_len;
uint8_t *cur;
memset(out_buf, 0, sizeof(*pt1));
@@ -294,7 +369,19 @@ static int fill_paging_type_1(uint8_t *out_buf, const uint8_t *identity1_lv,
pt1->l2_plen = L2_PLEN(cur - out_buf);
return cur - out_buf;
paging_len = cur - out_buf;
memset(&bv, 0, sizeof(bv));
bv.data = cur;
bv.data_len = GSM_MACBLOCK_LEN - paging_len;
if (p1ro)
append_p1_rest_octets(&bv, p1ro);
/* pad to the end of the MAC block */
bitvec_spare_padding(&bv, bv.data_len *8);
return GSM_MACBLOCK_LEN;
}
static int fill_paging_type_2(uint8_t *out_buf, const uint8_t *tmsi1_lv,
@@ -302,7 +389,9 @@ static int fill_paging_type_2(uint8_t *out_buf, const uint8_t *tmsi1_lv,
uint8_t cneed2, const uint8_t *identity3_lv)
{
struct gsm48_paging2 *pt2 = (struct gsm48_paging2 *) out_buf;
uint32_t tmsi;
uint8_t *cur;
int rc;
memset(out_buf, 0, sizeof(*pt2));
@@ -311,8 +400,12 @@ static int fill_paging_type_2(uint8_t *out_buf, const uint8_t *tmsi1_lv,
pt2->pag_mode = GSM48_PM_NORMAL;
pt2->cneed1 = cneed1;
pt2->cneed2 = cneed2;
tmsi_mi_to_uint(&pt2->tmsi1, tmsi1_lv);
tmsi_mi_to_uint(&pt2->tmsi2, tmsi2_lv);
rc = tmsi_mi_to_uint(&tmsi, tmsi1_lv);
if (rc == 0)
pt2->tmsi1 = tmsi;
rc = tmsi_mi_to_uint(&tmsi, tmsi2_lv);
if (rc == 0)
pt2->tmsi2 = tmsi;
cur = out_buf + sizeof(*pt2);
if (identity3_lv)
@@ -329,6 +422,8 @@ static int fill_paging_type_3(uint8_t *out_buf, const uint8_t *tmsi1_lv, uint8_t
const uint8_t *tmsi4_lv, uint8_t cneed4)
{
struct gsm48_paging3 *pt3 = (struct gsm48_paging3 *) out_buf;
uint32_t tmsi;
int rc;
memset(out_buf, 0, sizeof(*pt3));
@@ -337,10 +432,18 @@ static int fill_paging_type_3(uint8_t *out_buf, const uint8_t *tmsi1_lv, uint8_t
pt3->pag_mode = GSM48_PM_NORMAL;
pt3->cneed1 = cneed1;
pt3->cneed2 = cneed2;
tmsi_mi_to_uint(&pt3->tmsi1, tmsi1_lv);
tmsi_mi_to_uint(&pt3->tmsi2, tmsi2_lv);
tmsi_mi_to_uint(&pt3->tmsi3, tmsi3_lv);
tmsi_mi_to_uint(&pt3->tmsi4, tmsi4_lv);
rc = tmsi_mi_to_uint(&tmsi, tmsi1_lv);
if (rc == 0)
pt3->tmsi1 = tmsi;
rc = tmsi_mi_to_uint(&tmsi, tmsi2_lv);
if (rc == 0)
pt3->tmsi2 = tmsi;
rc = tmsi_mi_to_uint(&tmsi, tmsi3_lv);
if (rc == 0)
pt3->tmsi3 = tmsi;
rc = tmsi_mi_to_uint(&tmsi, tmsi4_lv);
if (rc == 0)
pt3->tmsi4 = tmsi;
/* The structure definition in libosmocore is wrong. It includes as last
* byte some invalid definition of chneed3/chneed4, so we must do this by hand
@@ -390,16 +493,43 @@ static void sort_pr_tmsi_imsi(struct paging_record *pr[], unsigned int n)
}
}
static void build_p1_rest_octets(struct p1_rest_octets *p1ro, struct gsm_bts *bts)
{
memset(p1ro, 0, sizeof(*p1ro));
p1ro->packet_page_ind[0] = false;
p1ro->packet_page_ind[1] = false;
p1ro->r8_present = true;
p1ro->r8.prio_ul_access = false;
p1ro->r8.etws_present = true;
unsigned int offset = bts->etws.page_size * bts->etws.next_page;
if (bts->etws.next_page == 0) {
p1ro->r8.etws.is_first = true;
p1ro->r8.etws.page_nr = bts->etws.num_pages;
} else {
p1ro->r8.etws.is_first = false;
p1ro->r8.etws.page_nr = bts->etws.next_page + 1;
}
p1ro->r8.etws.page = bts->etws.prim_notif + offset;
/* last page may be smaller than first pages */
if (bts->etws.next_page < bts->etws.num_pages-1)
p1ro->r8.etws.page_bytes = bts->etws.page_size;
else
p1ro->r8.etws.page_bytes = bts->etws.prim_notif_len - offset;
bts->etws.next_page = (bts->etws.next_page + 1) % bts->etws.num_pages;
}
/* generate paging message for given gsm time */
int paging_gen_msg(struct paging_state *ps, uint8_t *out_buf, struct gsm_time *gt,
int *is_empty)
{
struct llist_head *group_q;
struct gsm_bts *bts = ps->bts;
int group;
int len;
*is_empty = 0;
ps->bts->load.ccch.pch_total += 1;
bts->load.ccch.pch_total += 1;
group = get_pag_subch_nr(ps, gt);
if (group < 0) {
@@ -411,11 +541,15 @@ int paging_gen_msg(struct paging_state *ps, uint8_t *out_buf, struct gsm_time *g
group_q = &ps->paging_queue[group];
/* There is nobody to be paged, send Type1 with two empty ID */
if (llist_empty(group_q)) {
if (ps->bts->etws.prim_notif) {
struct p1_rest_octets p1ro;
build_p1_rest_octets(&p1ro, bts);
len = fill_paging_type_1(out_buf, empty_id_lv, 0, NULL, 0, &p1ro);
} else if (llist_empty(group_q)) {
/* There is nobody to be paged, send Type1 with two empty ID */
//DEBUGP(DPAG, "Tx PAGING TYPE 1 (empty)\n");
len = fill_paging_type_1(out_buf, empty_id_lv, 0,
NULL, 0);
NULL, 0, NULL);
*is_empty = 1;
} else {
struct paging_record *pr[4];
@@ -423,7 +557,7 @@ int paging_gen_msg(struct paging_state *ps, uint8_t *out_buf, struct gsm_time *g
time_t now = time(NULL);
unsigned int i, num_imsi = 0;
ps->bts->load.ccch.pch_used += 1;
bts->load.ccch.pch_used += 1;
/* get (if we have) up to four paging records */
for (i = 0; i < ARRAY_SIZE(pr); i++) {
@@ -493,7 +627,7 @@ int paging_gen_msg(struct paging_state *ps, uint8_t *out_buf, struct gsm_time *g
len = fill_paging_type_1(out_buf,
pr[0]->u.paging.identity_lv,
pr[0]->u.paging.chan_needed,
NULL, 0);
NULL, 0, NULL);
} else {
/* 2 (any type) or
* 3 or 4, of which only 2 will be sent */
@@ -502,7 +636,7 @@ int paging_gen_msg(struct paging_state *ps, uint8_t *out_buf, struct gsm_time *g
pr[0]->u.paging.identity_lv,
pr[0]->u.paging.chan_needed,
pr[1]->u.paging.identity_lv,
pr[1]->u.paging.chan_needed);
pr[1]->u.paging.chan_needed, NULL);
if (num_pr >= 3) {
/* re-add #4 for next time */
llist_add(&pr[2]->list, group_q);
@@ -519,7 +653,7 @@ int paging_gen_msg(struct paging_state *ps, uint8_t *out_buf, struct gsm_time *g
/* skip those that we might have re-added above */
if (pr[i] == NULL)
continue;
rate_ctr_inc2(ps->bts->ctrs, BTS_CTR_PAGING_SENT);
rate_ctr_inc2(bts->ctrs, BTS_CTR_PAGING_SENT);
/* check if we can expire the paging record,
* or if we need to re-queue it */
if (pr[i]->u.paging.expiration_time <= now) {

View File

@@ -1,6 +1,6 @@
/* pcu_sock.c: Connect from PCU via unix domain socket */
/* (C) 2008-2010 by Harald Welte <laforge@gnumonks.org>
/* (C) 2008-2019 by Harald Welte <laforge@gnumonks.org>
* (C) 2009-2012 by Andreas Eversberg <jolly@eversberg.eu>
* (C) 2012 by Holger Hans Peter Freyther
* All Rights Reserved
@@ -43,6 +43,7 @@
#include <osmo-bts/rsl.h>
#include <osmo-bts/signal.h>
#include <osmo-bts/l1sap.h>
#include <osmo-bts/oml.h>
uint32_t trx_get_hlayer1(struct gsm_bts_trx *trx);
@@ -258,7 +259,7 @@ static int pcu_if_signal_cb(unsigned int subsys, unsigned int signal,
bts->si_buf[SYSINFO_TYPE_3];
osmo_plmn_from_bcd(si3->lai.digits, &net->plmn);
bts->location_area_code = ntohs(si3->lai.lac);
bts->cell_identity = si3->cell_identity;
bts->cell_identity = ntohs(si3->cell_identity);
avail_lai = 1;
break;
case S_NEW_NSE_ATTR:
@@ -289,6 +290,27 @@ static int pcu_if_signal_cb(unsigned int subsys, unsigned int signal,
return 0;
}
int pcu_tx_app_info_req(struct gsm_bts *bts, uint8_t app_type, uint8_t len, const uint8_t *app_data)
{
struct gsm_pcu_if_app_info_req *ai_req;
struct gsm_pcu_if *pcu_prim;
struct msgb *msg;
if (app_type & 0xF0 || len > sizeof(ai_req->data))
return -EINVAL;
msg = pcu_msgb_alloc(PCU_IF_MSG_APP_INFO_REQ, bts->nr);
if (!msg)
return -ENOMEM;
pcu_prim = (struct gsm_pcu_if *) msg->data;
ai_req = &pcu_prim->u.app_info_req;
ai_req->application_type = app_type;
ai_req->len = len;
memcpy(ai_req->data, app_data, ai_req->len);
return pcu_sock_send(&bts_gsmnet, msg);
}
int pcu_tx_rts_req(struct gsm_bts_trx_ts *ts, uint8_t is_ptcch, uint32_t fn,
uint16_t arfcn, uint8_t block_nr)
@@ -329,8 +351,8 @@ int pcu_tx_data_ind(struct gsm_bts_trx_ts *ts, uint8_t sapi, uint32_t fn,
LOGP(DPCU, LOGL_DEBUG, "Sending data indication: sapi=%s arfcn=%d block=%d data=%s\n",
sapi_string[sapi], arfcn, block_nr, osmo_hexdump(data, len));
if (lqual / 10 < bts->min_qual_norm) {
LOGP(DPCU, LOGL_DEBUG, "Link quality %"PRId16" is below threshold %f, dropping packet\n",
if (lqual < bts->min_qual_norm) {
LOGP(DPCU, LOGL_DEBUG, "Link quality %"PRId16" is below threshold %d, dropping packet\n",
lqual, bts->min_qual_norm);
return 0;
}
@@ -357,8 +379,9 @@ int pcu_tx_data_ind(struct gsm_bts_trx_ts *ts, uint8_t sapi, uint32_t fn,
return pcu_sock_send(&bts_gsmnet, msg);
}
int pcu_tx_rach_ind(struct gsm_bts *bts, int16_t qta, uint16_t ra, uint32_t fn,
uint8_t is_11bit, enum ph_burst_type burst_type)
int pcu_tx_rach_ind(uint8_t bts_nr, uint8_t trx_nr, uint8_t ts_nr,
int16_t qta, uint16_t ra, uint32_t fn, uint8_t is_11bit,
enum ph_burst_type burst_type, uint8_t sapi)
{
struct msgb *msg;
struct gsm_pcu_if *pcu_prim;
@@ -367,18 +390,20 @@ int pcu_tx_rach_ind(struct gsm_bts *bts, int16_t qta, uint16_t ra, uint32_t fn,
LOGP(DPCU, LOGL_INFO, "Sending RACH indication: qta=%d, ra=%d, "
"fn=%d\n", qta, ra, fn);
msg = pcu_msgb_alloc(PCU_IF_MSG_RACH_IND, bts->nr);
msg = pcu_msgb_alloc(PCU_IF_MSG_RACH_IND, bts_nr);
if (!msg)
return -ENOMEM;
pcu_prim = (struct gsm_pcu_if *) msg->data;
rach_ind = &pcu_prim->u.rach_ind;
rach_ind->sapi = PCU_IF_SAPI_RACH;
rach_ind->sapi = sapi;
rach_ind->ra = ra;
rach_ind->qta = qta;
rach_ind->fn = fn;
rach_ind->is_11bit = is_11bit;
rach_ind->burst_type = burst_type;
rach_ind->trx_nr = trx_nr;
rach_ind->ts_nr = ts_nr;
return pcu_sock_send(&bts_gsmnet, msg);
}
@@ -465,8 +490,25 @@ int pcu_tx_pch_data_cnf(uint32_t fn, uint8_t *data, uint8_t len)
return pcu_sock_send(&bts_gsmnet, msg);
}
/* forward data from a RR GPRS SUSPEND REQ towards PCU */
int pcu_tx_susp_req(struct gsm_lchan *lchan, uint32_t tlli, const uint8_t *ra_id, uint8_t cause)
{
struct msgb *msg;
struct gsm_pcu_if *pcu_prim;
msg = pcu_msgb_alloc(PCU_IF_MSG_SUSP_REQ, lchan->ts->trx->bts->nr);
if (!msg)
return -ENOMEM;
pcu_prim = (struct gsm_pcu_if *) msg->data;
pcu_prim->u.susp_req.tlli = tlli;
memcpy(pcu_prim->u.susp_req.ra_id, ra_id, sizeof(pcu_prim->u.susp_req.ra_id));
pcu_prim->u.susp_req.cause = cause;
return pcu_sock_send(&bts_gsmnet, msg);
}
static int pcu_rx_data_req(struct gsm_bts *bts, uint8_t msg_type,
struct gsm_pcu_if_data *data_req)
const struct gsm_pcu_if_data *data_req)
{
uint8_t is_ptcch;
struct gsm_bts_trx *trx;
@@ -538,7 +580,7 @@ static int pcu_rx_data_req(struct gsm_bts *bts, uint8_t msg_type,
}
static int pcu_rx_pag_req(struct gsm_bts *bts, uint8_t msg_type,
struct gsm_pcu_if_pag_req *pag_req)
const struct gsm_pcu_if_pag_req *pag_req)
{
int rc = 0;
@@ -577,16 +619,20 @@ static int pcu_rx_txt_ind(struct gsm_bts *bts,
case PCU_VERSION:
LOGP(DPCU, LOGL_INFO, "OsmoPCU version %s connected\n",
txt->text);
osmo_signal_dispatch(SS_FAIL, OSMO_EVT_PCU_VERS, txt->text);
oml_tx_failure_event_rep(&bts->gprs.cell.mo, NM_SEVER_CEASED, OSMO_EVT_PCU_VERS, txt->text);
osmo_strlcpy(bts->pcu_version, txt->text, MAX_VERSION_LENGTH);
/* patch SI3 to advertise GPRS, *if* the SI3 sent by BSC said so */
regenerate_si3_restoctets(bts);
if (GSM_BTS_HAS_SI(bts, SYSINFO_TYPE_13))
return pcu_tx_si13(bts, true);
LOGP(DPCU, LOGL_INFO, "SI13 is not available on PCU connection\n");
break;
case PCU_OML_ALERT:
osmo_signal_dispatch(SS_FAIL, OSMO_EVT_EXT_ALARM, txt->text);
oml_tx_failure_event_rep(&bts->gprs.cell.mo, NM_SEVER_INDETERMINATE, OSMO_EVT_EXT_ALARM,
txt->text);
break;
default:
LOGP(DPCU, LOGL_ERROR, "Unknown TXT_IND type %u received\n",
@@ -598,7 +644,7 @@ static int pcu_rx_txt_ind(struct gsm_bts *bts,
}
static int pcu_rx_act_req(struct gsm_bts *bts,
struct gsm_pcu_if_act_req *act_req)
const struct gsm_pcu_if_act_req *act_req)
{
struct gsm_bts_trx *trx;
struct gsm_lchan *lchan;
@@ -655,7 +701,7 @@ static int pcu_rx(struct gsm_network *net, uint8_t msg_type,
rc = pcu_rx_txt_ind(bts, &pcu_prim->u.txt_ind);
break;
default:
LOGP(DPCU, LOGL_ERROR, "Received unknwon PCU msg type %d\n",
LOGP(DPCU, LOGL_ERROR, "Received unknown PCU msg type %d\n",
msg_type);
rc = -EINVAL;
}
@@ -713,13 +759,18 @@ static void pcu_sock_close(struct pcu_sock_state *state)
bts = llist_entry(state->net->bts_list.next, struct gsm_bts, list);
LOGP(DPCU, LOGL_NOTICE, "PCU socket has LOST connection\n");
osmo_signal_dispatch(SS_FAIL, OSMO_EVT_PCU_VERS, NULL);
oml_tx_failure_event_rep(&bts->gprs.cell.mo, NM_SEVER_MAJOR, OSMO_EVT_PCU_VERS,
"PCU socket has LOST connection");
bts->pcu_version[0] = '\0';
close(bfd->fd);
bfd->fd = -1;
osmo_fd_unregister(bfd);
/* patch SI3 to remove GPRS indicator */
regenerate_si3_restoctets(bts);
/* re-enable the generation of ACCEPT for new connections */
state->listen_bfd.when |= BSC_FD_READ;
@@ -770,14 +821,17 @@ static int pcu_sock_read(struct osmo_fd *bfd)
goto close;
if (rc < 0) {
if (errno == EAGAIN)
if (errno == EAGAIN) {
msgb_free(msg);
return 0;
}
goto close;
}
if (rc < sizeof(*pcu_prim)) {
LOGP(DPCU, LOGL_ERROR, "Received %d bytes on PCU Socket, but primitive size "
"is %lu, discarding\n", rc, sizeof(*pcu_prim));
"is %zu, discarding\n", rc, sizeof(*pcu_prim));
msgb_free(msg);
return 0;
}
@@ -858,7 +912,7 @@ static int pcu_sock_cb(struct osmo_fd *bfd, unsigned int flags)
return rc;
}
/* accept connection comming from PCU */
/* accept connection coming from PCU */
static int pcu_sock_accept(struct osmo_fd *bfd, unsigned int flags)
{
struct pcu_sock_state *state = (struct pcu_sock_state *)bfd->data;

View File

@@ -81,6 +81,16 @@ void phy_link_state_set(struct phy_link *plink, enum phy_link_state state)
plink->state = state;
}
enum phy_link_state phy_link_state_get(struct phy_link *plink)
{
return plink->state;
}
const char *phy_link_state_name(enum phy_link_state state)
{
return get_value_string(phy_link_state_vals, state);
}
struct phy_instance *phy_instance_by_num(struct phy_link *plink, int num)
{
struct phy_instance *pinst;

View File

@@ -22,6 +22,7 @@
#include <stdint.h>
#include <unistd.h>
#include <errno.h>
#include <inttypes.h>
#include <osmo-bts/logging.h>
#include <osmo-bts/bts.h>
@@ -29,61 +30,98 @@
#include <osmo-bts/measurement.h>
#include <osmo-bts/bts_model.h>
#include <osmo-bts/l1sap.h>
#include <osmo-bts/power_control.h>
/*
* Check if manual power control is needed
* Check if fixed power was selected
* Check if the MS is already using our level if not
* the value is bogus..
* TODO: Add a timeout.. e.g. if the ms is not capable of reaching
* the value we have set.
*/
/* how many dB do we raise/lower as maximum (1 ms power level = 2 dB) */
#define MS_RAISE_MAX_DB 4
#define MS_LOWER_MAX_DB 8
/*! compute the new MS POWER LEVEL communicated to the MS and store it in lchan.
* \param lchan logical channel for which to compute (and in which to store) new power value.
* \param[in] ms_power_lvl MS Power Level received from Uplink L1 SACCH Header in SACCH block.
* \param[in] rxLevel Signal level of the received SACCH block, in dBm.
*/
int lchan_ms_pwr_ctrl(struct gsm_lchan *lchan,
const uint8_t ms_power, const int rxLevel)
const uint8_t ms_power_lvl, const int rxLevel)
{
int rx;
int cur_dBm, new_dBm, new_pwr;
struct gsm_bts *bts = lchan->ts->trx->bts;
const enum gsm_band band = bts->band;
int diff;
struct gsm_bts_trx *trx = lchan->ts->trx;
struct gsm_bts *bts = trx->bts;
enum gsm_band band = bts->band;
int8_t new_power_lvl; /* TS 05.05 power level */
int8_t ms_dbm, new_dbm, current_dbm, bsc_max_dbm;
if (!trx_ms_pwr_ctrl_is_osmo(lchan->ts->trx))
return 0;
if (lchan->ms_power_ctrl.fixed)
return 0;
/* The phone hasn't reached the power level yet */
if (lchan->ms_power_ctrl.current != ms_power)
ms_dbm = ms_pwr_dbm(band, ms_power_lvl);
if (ms_dbm < 0) {
LOGPLCHAN(lchan, DLOOP, LOGL_NOTICE,
"Failed to calculate dBm for power ctl level %" PRIu8 " on band %s\n",
ms_power_lvl, gsm_band_name(band));
return 0;
}
bsc_max_dbm = ms_pwr_dbm(band, lchan->ms_power_ctrl.max);
if (bsc_max_dbm < 0) {
LOGPLCHAN(lchan, DLOOP, LOGL_NOTICE,
"Failed to calculate dBm for power ctl level %" PRIu8 " on band %s\n",
lchan->ms_power_ctrl.max, gsm_band_name(band));
return 0;
/* What is the difference between what we want and received? */
rx = bts->ul_power_target - rxLevel;
cur_dBm = ms_pwr_dbm(band, ms_power);
new_dBm = cur_dBm + rx;
/* Clamp negative values and do it depending on the band */
if (new_dBm < 0)
new_dBm = 0;
switch (band) {
case GSM_BAND_1800:
/* If MS_TX_PWR_MAX_CCH is set the values 29,
* 30, 31 are not used. Avoid specifying a dBm
* that would lead to these power levels. The
* phone might not be able to reach them. */
if (new_dBm > 30)
new_dBm = 30;
break;
default:
break;
}
new_pwr = ms_pwr_ctl_lvl(band, new_dBm);
if (lchan->ms_power_ctrl.current != new_pwr) {
lchan->ms_power_ctrl.current = new_pwr;
bts_model_adjst_ms_pwr(lchan);
return 1;
/* How many dBs measured power should be increased (+) or decreased (-)
to reach expected power. */
diff = bts->ul_power_target - rxLevel;
/* don't ever change more than MS_{LOWER,RAISE}_MAX_DBM during one loop
iteration, i.e. reduce the speed at which the MS transmit power can
change. A higher value means a lower level (and vice versa) */
if (diff > MS_RAISE_MAX_DB)
diff = MS_RAISE_MAX_DB;
else if (diff < -MS_LOWER_MAX_DB)
diff = -MS_LOWER_MAX_DB;
new_dbm = ms_dbm + diff;
/* Make sure new_dbm is never negative. ms_pwr_ctl_lvl() can later on
cope with any unsigned dbm value, regardless of band minimal value. */
if (new_dbm < 0)
new_dbm = 0;
/* Don't ask for smaller ms power level than the one set by BSC upon RSL CHAN ACT */
if (new_dbm > bsc_max_dbm)
new_dbm = bsc_max_dbm;
new_power_lvl = ms_pwr_ctl_lvl(band, new_dbm);
if (new_power_lvl < 0) {
LOGPLCHAN(lchan, DLOOP, LOGL_NOTICE,
"Failed to retrieve power level for %" PRId8 " dBm on band %d\n",
new_dbm, band);
return 0;
}
return 0;
if (lchan->ms_power_ctrl.current == new_power_lvl) {
LOGPLCHAN(lchan, DLOOP, LOGL_INFO, "Keeping MS power at control level %d, %d dBm "
"(rx-ms-pwr-lvl %" PRIu8 ", max-ms-pwr-lvl %" PRIu8 ", rx-current %d dBm, rx-target %d dBm)\n",
new_power_lvl, new_dbm,
ms_power_lvl, lchan->ms_power_ctrl.max,
rxLevel, bts->ul_power_target);
return 0;
}
current_dbm = ms_pwr_dbm(band, lchan->ms_power_ctrl.current);
LOGPLCHAN(lchan, DLOOP, LOGL_INFO, "%s MS power from control level %d (%d dBm) to %d, %d dBm "
"(rx-ms-pwr-lvl %" PRIu8 ", max-ms-pwr-lvl %" PRIu8 ", rx-current %d dBm, rx-target %d dBm)\n",
(new_dbm > current_dbm) ? "Raising" : "Lowering",
lchan->ms_power_ctrl.current, current_dbm, new_power_lvl, new_dbm,
ms_power_lvl, lchan->ms_power_ctrl.max,
rxLevel, bts->ul_power_target);
/* store the resulting new MS power level in the lchan */
lchan->ms_power_ctrl.current = new_power_lvl;
bts_model_adjst_ms_pwr(lchan);
return 1;
}

File diff suppressed because it is too large Load Diff

View File

@@ -29,6 +29,9 @@
#include <osmocom/core/msgb.h>
#include <osmocom/core/talloc.h>
#include <osmocom/core/bits.h>
#include <osmocom/core/utils.h>
#include <osmocom/gsm/protocol/gsm_08_58.h>
#include <osmocom/gsm/a5.h>
#include <osmo-bts/gsm_data.h>
@@ -111,95 +114,482 @@ const ubit_t _sched_sch_train[64] = {
0,0,1,0,1,1,0,1,0,1,0,0,0,1,0,1,0,1,1,1,0,1,1,0,0,0,0,1,1,0,1,1,
};
/*
* subchannel description structure
*/
/* Logical channel (TRXC_*) description */
const struct trx_chan_desc trx_chan_desc[_TRX_CHAN_MAX] = {
/* is_pdch chan_type chan_nr link_id name rts_fn dl_fn ul_fn auto_active */
{ 0, TRXC_IDLE, 0, LID_DEDIC, "IDLE", NULL, tx_idle_fn, NULL, 1 },
{ 0, TRXC_FCCH, 0, LID_DEDIC, "FCCH", NULL, tx_fcch_fn, NULL, 1 },
{ 0, TRXC_SCH, 0, LID_DEDIC, "SCH", NULL, tx_sch_fn, NULL, 1 },
{ 0, TRXC_BCCH, 0x80, LID_DEDIC, "BCCH", rts_data_fn, tx_data_fn, NULL, 1 },
{ 0, TRXC_RACH, 0x88, LID_DEDIC, "RACH", NULL, NULL, rx_rach_fn, 1 },
{ 0, TRXC_CCCH, 0x90, LID_DEDIC, "CCCH", rts_data_fn, tx_data_fn, NULL, 1 },
{ 0, TRXC_TCHF, 0x08, LID_DEDIC, "TCH/F", rts_tchf_fn, tx_tchf_fn, rx_tchf_fn, 0 },
{ 0, TRXC_TCHH_0, 0x10, LID_DEDIC, "TCH/H(0)", rts_tchh_fn, tx_tchh_fn, rx_tchh_fn, 0 },
{ 0, TRXC_TCHH_1, 0x18, LID_DEDIC, "TCH/H(1)", rts_tchh_fn, tx_tchh_fn, rx_tchh_fn, 0 },
{ 0, TRXC_SDCCH4_0, 0x20, LID_DEDIC, "SDCCH/4(0)", rts_data_fn, tx_data_fn, rx_data_fn, 0 },
{ 0, TRXC_SDCCH4_1, 0x28, LID_DEDIC, "SDCCH/4(1)", rts_data_fn, tx_data_fn, rx_data_fn, 0 },
{ 0, TRXC_SDCCH4_2, 0x30, LID_DEDIC, "SDCCH/4(2)", rts_data_fn, tx_data_fn, rx_data_fn, 0 },
{ 0, TRXC_SDCCH4_3, 0x38, LID_DEDIC, "SDCCH/4(3)", rts_data_fn, tx_data_fn, rx_data_fn, 0 },
{ 0, TRXC_SDCCH8_0, 0x40, LID_DEDIC, "SDCCH/8(0)", rts_data_fn, tx_data_fn, rx_data_fn, 0 },
{ 0, TRXC_SDCCH8_1, 0x48, LID_DEDIC, "SDCCH/8(1)", rts_data_fn, tx_data_fn, rx_data_fn, 0 },
{ 0, TRXC_SDCCH8_2, 0x50, LID_DEDIC, "SDCCH/8(2)", rts_data_fn, tx_data_fn, rx_data_fn, 0 },
{ 0, TRXC_SDCCH8_3, 0x58, LID_DEDIC, "SDCCH/8(3)", rts_data_fn, tx_data_fn, rx_data_fn, 0 },
{ 0, TRXC_SDCCH8_4, 0x60, LID_DEDIC, "SDCCH/8(4)", rts_data_fn, tx_data_fn, rx_data_fn, 0 },
{ 0, TRXC_SDCCH8_5, 0x68, LID_DEDIC, "SDCCH/8(5)", rts_data_fn, tx_data_fn, rx_data_fn, 0 },
{ 0, TRXC_SDCCH8_6, 0x70, LID_DEDIC, "SDCCH/8(6)", rts_data_fn, tx_data_fn, rx_data_fn, 0 },
{ 0, TRXC_SDCCH8_7, 0x78, LID_DEDIC, "SDCCH/8(7)", rts_data_fn, tx_data_fn, rx_data_fn, 0 },
{ 0, TRXC_SACCHTF, 0x08, LID_SACCH, "SACCH/TF", rts_data_fn, tx_data_fn, rx_data_fn, 0 },
{ 0, TRXC_SACCHTH_0, 0x10, LID_SACCH, "SACCH/TH(0)", rts_data_fn, tx_data_fn, rx_data_fn, 0 },
{ 0, TRXC_SACCHTH_1, 0x18, LID_SACCH, "SACCH/TH(1)", rts_data_fn, tx_data_fn, rx_data_fn, 0 },
{ 0, TRXC_SACCH4_0, 0x20, LID_SACCH, "SACCH/4(0)", rts_data_fn, tx_data_fn, rx_data_fn, 0 },
{ 0, TRXC_SACCH4_1, 0x28, LID_SACCH, "SACCH/4(1)", rts_data_fn, tx_data_fn, rx_data_fn, 0 },
{ 0, TRXC_SACCH4_2, 0x30, LID_SACCH, "SACCH/4(2)", rts_data_fn, tx_data_fn, rx_data_fn, 0 },
{ 0, TRXC_SACCH4_3, 0x38, LID_SACCH, "SACCH/4(3)", rts_data_fn, tx_data_fn, rx_data_fn, 0 },
{ 0, TRXC_SACCH8_0, 0x40, LID_SACCH, "SACCH/8(0)", rts_data_fn, tx_data_fn, rx_data_fn, 0 },
{ 0, TRXC_SACCH8_1, 0x48, LID_SACCH, "SACCH/8(1)", rts_data_fn, tx_data_fn, rx_data_fn, 0 },
{ 0, TRXC_SACCH8_2, 0x50, LID_SACCH, "SACCH/8(2)", rts_data_fn, tx_data_fn, rx_data_fn, 0 },
{ 0, TRXC_SACCH8_3, 0x58, LID_SACCH, "SACCH/8(3)", rts_data_fn, tx_data_fn, rx_data_fn, 0 },
{ 0, TRXC_SACCH8_4, 0x60, LID_SACCH, "SACCH/8(4)", rts_data_fn, tx_data_fn, rx_data_fn, 0 },
{ 0, TRXC_SACCH8_5, 0x68, LID_SACCH, "SACCH/8(5)", rts_data_fn, tx_data_fn, rx_data_fn, 0 },
{ 0, TRXC_SACCH8_6, 0x70, LID_SACCH, "SACCH/8(6)", rts_data_fn, tx_data_fn, rx_data_fn, 0 },
{ 0, TRXC_SACCH8_7, 0x78, LID_SACCH, "SACCH/8(7)", rts_data_fn, tx_data_fn, rx_data_fn, 0 },
{ 1, TRXC_PDTCH, 0xc0, LID_DEDIC, "PDTCH", rts_data_fn, tx_pdtch_fn, rx_pdtch_fn, 0 },
{ 1, TRXC_PTCCH, 0xc0, LID_DEDIC, "PTCCH", rts_data_fn, tx_data_fn, rx_data_fn, 0 },
{ 0, TRXC_CBCH, 0xc8, LID_DEDIC, "CBCH", rts_data_fn, tx_data_fn, NULL, 1 },
};
[TRXC_IDLE] = {
.name = "IDLE",
.desc = "Idle channel",
const struct value_string trx_chan_type_names[] = {
OSMO_VALUE_STRING(TRXC_IDLE),
OSMO_VALUE_STRING(TRXC_FCCH),
OSMO_VALUE_STRING(TRXC_SCH),
OSMO_VALUE_STRING(TRXC_BCCH),
OSMO_VALUE_STRING(TRXC_RACH),
OSMO_VALUE_STRING(TRXC_CCCH),
OSMO_VALUE_STRING(TRXC_TCHF),
OSMO_VALUE_STRING(TRXC_TCHH_0),
OSMO_VALUE_STRING(TRXC_TCHH_1),
OSMO_VALUE_STRING(TRXC_SDCCH4_0),
OSMO_VALUE_STRING(TRXC_SDCCH4_1),
OSMO_VALUE_STRING(TRXC_SDCCH4_2),
OSMO_VALUE_STRING(TRXC_SDCCH4_3),
OSMO_VALUE_STRING(TRXC_SDCCH8_0),
OSMO_VALUE_STRING(TRXC_SDCCH8_1),
OSMO_VALUE_STRING(TRXC_SDCCH8_2),
OSMO_VALUE_STRING(TRXC_SDCCH8_3),
OSMO_VALUE_STRING(TRXC_SDCCH8_4),
OSMO_VALUE_STRING(TRXC_SDCCH8_5),
OSMO_VALUE_STRING(TRXC_SDCCH8_6),
OSMO_VALUE_STRING(TRXC_SDCCH8_7),
OSMO_VALUE_STRING(TRXC_SACCHTF),
OSMO_VALUE_STRING(TRXC_SACCHTH_0),
OSMO_VALUE_STRING(TRXC_SACCHTH_1),
OSMO_VALUE_STRING(TRXC_SACCH4_0),
OSMO_VALUE_STRING(TRXC_SACCH4_1),
OSMO_VALUE_STRING(TRXC_SACCH4_2),
OSMO_VALUE_STRING(TRXC_SACCH4_3),
OSMO_VALUE_STRING(TRXC_SACCH8_0),
OSMO_VALUE_STRING(TRXC_SACCH8_1),
OSMO_VALUE_STRING(TRXC_SACCH8_2),
OSMO_VALUE_STRING(TRXC_SACCH8_3),
OSMO_VALUE_STRING(TRXC_SACCH8_4),
OSMO_VALUE_STRING(TRXC_SACCH8_5),
OSMO_VALUE_STRING(TRXC_SACCH8_6),
OSMO_VALUE_STRING(TRXC_SACCH8_7),
OSMO_VALUE_STRING(TRXC_PDTCH),
OSMO_VALUE_STRING(TRXC_PTCCH),
OSMO_VALUE_STRING(TRXC_CBCH),
OSMO_VALUE_STRING(_TRX_CHAN_MAX),
{ 0, NULL }
/* On C0, BTS needs to ensure discontinuous burst transmission.
* Therefore we need to send dummy bursts on IDLE slots. */
.flags = TRX_CHAN_FLAG_AUTO_ACTIVE,
.dl_fn = tx_idle_fn,
},
[TRXC_FCCH] = {
.name = "FCCH", /* 3GPP TS 05.02, section 3.3.2.1 */
.desc = "Frequency correction channel",
/* Tx only, frequency correction bursts */
.flags = TRX_CHAN_FLAG_AUTO_ACTIVE,
.dl_fn = tx_fcch_fn,
},
[TRXC_SCH] = {
.name = "SCH", /* 3GPP TS 05.02, section 3.3.2.2 */
.desc = "Synchronization channel",
/* Tx only, synchronization bursts */
.flags = TRX_CHAN_FLAG_AUTO_ACTIVE,
.dl_fn = tx_sch_fn,
},
[TRXC_BCCH] = {
.name = "BCCH", /* 3GPP TS 05.02, section 3.3.2.3 */
.desc = "Broadcast control channel",
.chan_nr = RSL_CHAN_BCCH,
/* Tx only, xCCH convolutional coding (3GPP TS 05.03, section 4.4),
* regular interleaving (3GPP TS 05.02, clause 7, table 3):
* a L2 frame is interleaved over 4 consecutive bursts. */
.flags = TRX_CHAN_FLAG_AUTO_ACTIVE,
.rts_fn = rts_data_fn,
.dl_fn = tx_data_fn,
},
[TRXC_RACH] = {
.name = "RACH", /* 3GPP TS 05.02, section 3.3.3.1 */
.desc = "Random access channel",
.chan_nr = RSL_CHAN_RACH,
/* Rx only, RACH convolutional coding (3GPP TS 05.03, section 4.6). */
.flags = TRX_CHAN_FLAG_AUTO_ACTIVE,
.ul_fn = rx_rach_fn,
},
[TRXC_CCCH] = {
.name = "CCCH", /* 3GPP TS 05.02, section 3.3.3.1 */
.desc = "Common control channel",
.chan_nr = RSL_CHAN_PCH_AGCH,
/* Tx only, xCCH convolutional coding (3GPP TS 05.03, section 4.4),
* regular interleaving (3GPP TS 05.02, clause 7, table 3):
* a L2 frame is interleaved over 4 consecutive bursts. */
.flags = TRX_CHAN_FLAG_AUTO_ACTIVE,
.rts_fn = rts_data_fn,
.dl_fn = tx_data_fn,
},
[TRXC_TCHF] = {
.name = "TCH/F", /* 3GPP TS 05.02, section 3.2 */
.desc = "Full Rate traffic channel",
.chan_nr = RSL_CHAN_Bm_ACCHs,
.link_id = LID_DEDIC,
/* Rx and Tx, multiple convolutional coding types (3GPP TS 05.03,
* chapter 3), block diagonal interleaving (3GPP TS 05.02, clause 7):
*
* - a traffic frame is interleaved over 8 consecutive bursts
* using the even numbered bits of the first 4 bursts
* and odd numbered bits of the last 4 bursts;
* - a FACCH/F frame 'steals' (replaces) one traffic frame,
* interleaving is done in the same way. */
.rts_fn = rts_tchf_fn,
.dl_fn = tx_tchf_fn,
.ul_fn = rx_tchf_fn,
.nope_fn = rx_tchf_fn,
},
[TRXC_TCHH_0] = {
.name = "TCH/H(0)", /* 3GPP TS 05.02, section 3.2 */
.desc = "Half Rate traffic channel (sub-channel 0)",
.chan_nr = RSL_CHAN_Lm_ACCHs + (0 << 3),
.link_id = LID_DEDIC,
/* Rx and Tx, multiple convolutional coding types (3GPP TS 05.03,
* chapter 3), block diagonal interleaving (3GPP TS 05.02, clause 7):
*
* - a traffic frame is interleaved over 6 consecutive bursts
* using the even numbered bits of the first 2 bursts,
* all bits of the middle two 2 bursts,
* and odd numbered bits of the last 2 bursts;
* - a FACCH/H frame 'steals' (replaces) two traffic frames,
* interleaving is done over 4 consecutive bursts,
* the same as given for a TCH/FS. */
.rts_fn = rts_tchh_fn,
.dl_fn = tx_tchh_fn,
.ul_fn = rx_tchh_fn,
.nope_fn = rx_tchh_fn,
},
[TRXC_TCHH_1] = {
.name = "TCH/H(1)", /* 3GPP TS 05.02, section 3.2 */
.desc = "Half Rate traffic channel (sub-channel 1)",
.chan_nr = RSL_CHAN_Lm_ACCHs + (1 << 3),
.link_id = LID_DEDIC,
/* Same as for TRXC_TCHH_0, see above. */
.rts_fn = rts_tchh_fn,
.dl_fn = tx_tchh_fn,
.ul_fn = rx_tchh_fn,
.nope_fn = rx_tchh_fn,
},
[TRXC_SDCCH4_0] = {
.name = "SDCCH/4(0)", /* 3GPP TS 05.02, section 3.3.4.1 */
.desc = "Stand-alone dedicated control channel (sub-channel 0)",
.chan_nr = RSL_CHAN_SDCCH4_ACCH + (0 << 3),
.link_id = LID_DEDIC,
/* Same as for TRXC_BCCH (xCCH), see above. */
.rts_fn = rts_data_fn,
.dl_fn = tx_data_fn,
.ul_fn = rx_data_fn,
.nope_fn = rx_data_fn,
},
[TRXC_SDCCH4_1] = {
.name = "SDCCH/4(1)", /* 3GPP TS 05.02, section 3.3.4.1 */
.desc = "Stand-alone dedicated control channel (sub-channel 1)",
.chan_nr = RSL_CHAN_SDCCH4_ACCH + (1 << 3),
.link_id = LID_DEDIC,
/* Same as for TRXC_BCCH (xCCH), see above. */
.rts_fn = rts_data_fn,
.dl_fn = tx_data_fn,
.ul_fn = rx_data_fn,
.nope_fn = rx_data_fn,
},
[TRXC_SDCCH4_2] = {
.name = "SDCCH/4(2)", /* 3GPP TS 05.02, section 3.3.4.1 */
.desc = "Stand-alone dedicated control channel (sub-channel 2)",
.chan_nr = RSL_CHAN_SDCCH4_ACCH + (2 << 3),
.link_id = LID_DEDIC,
/* Same as for TRXC_BCCH (xCCH), see above. */
.rts_fn = rts_data_fn,
.dl_fn = tx_data_fn,
.ul_fn = rx_data_fn,
.nope_fn = rx_data_fn,
},
[TRXC_SDCCH4_3] = {
.name = "SDCCH/4(3)", /* 3GPP TS 05.02, section 3.3.4.1 */
.desc = "Stand-alone dedicated control channel (sub-channel 3)",
.chan_nr = RSL_CHAN_SDCCH4_ACCH + (3 << 3),
.link_id = LID_DEDIC,
/* Same as for TRXC_BCCH (xCCH), see above. */
.rts_fn = rts_data_fn,
.dl_fn = tx_data_fn,
.ul_fn = rx_data_fn,
.nope_fn = rx_data_fn,
},
[TRXC_SDCCH8_0] = {
.name = "SDCCH/8(0)", /* 3GPP TS 05.02, section 3.3.4.1 */
.desc = "Stand-alone dedicated control channel (sub-channel 0)",
.chan_nr = RSL_CHAN_SDCCH8_ACCH + (0 << 3),
.link_id = LID_DEDIC,
/* Same as for TRXC_BCCH and TRXC_SDCCH4_* (xCCH), see above. */
.rts_fn = rts_data_fn,
.dl_fn = tx_data_fn,
.ul_fn = rx_data_fn,
.nope_fn = rx_data_fn,
},
[TRXC_SDCCH8_1] = {
.name = "SDCCH/8(1)", /* 3GPP TS 05.02, section 3.3.4.1 */
.desc = "Stand-alone dedicated control channel (sub-channel 1)",
.chan_nr = RSL_CHAN_SDCCH8_ACCH + (1 << 3),
.link_id = LID_DEDIC,
/* Same as for TRXC_BCCH and TRXC_SDCCH4_* (xCCH), see above. */
.rts_fn = rts_data_fn,
.dl_fn = tx_data_fn,
.ul_fn = rx_data_fn,
.nope_fn = rx_data_fn,
},
[TRXC_SDCCH8_2] = {
.name = "SDCCH/8(2)", /* 3GPP TS 05.02, section 3.3.4.1 */
.desc = "Stand-alone dedicated control channel (sub-channel 2)",
.chan_nr = RSL_CHAN_SDCCH8_ACCH + (2 << 3),
.link_id = LID_DEDIC,
/* Same as for TRXC_BCCH and TRXC_SDCCH4_* (xCCH), see above. */
.rts_fn = rts_data_fn,
.dl_fn = tx_data_fn,
.ul_fn = rx_data_fn,
.nope_fn = rx_data_fn,
},
[TRXC_SDCCH8_3] = {
.name = "SDCCH/8(3)", /* 3GPP TS 05.02, section 3.3.4.1 */
.desc = "Stand-alone dedicated control channel (sub-channel 3)",
.chan_nr = RSL_CHAN_SDCCH8_ACCH + (3 << 3),
.link_id = LID_DEDIC,
/* Same as for TRXC_BCCH and TRXC_SDCCH4_* (xCCH), see above. */
.rts_fn = rts_data_fn,
.dl_fn = tx_data_fn,
.ul_fn = rx_data_fn,
.nope_fn = rx_data_fn,
},
[TRXC_SDCCH8_4] = {
.name = "SDCCH/8(4)", /* 3GPP TS 05.02, section 3.3.4.1 */
.desc = "Stand-alone dedicated control channel (sub-channel 4)",
.chan_nr = RSL_CHAN_SDCCH8_ACCH + (4 << 3),
.link_id = LID_DEDIC,
/* Same as for TRXC_BCCH and TRXC_SDCCH4_* (xCCH), see above. */
.rts_fn = rts_data_fn,
.dl_fn = tx_data_fn,
.ul_fn = rx_data_fn,
.nope_fn = rx_data_fn,
},
[TRXC_SDCCH8_5] = {
.name = "SDCCH/8(5)", /* 3GPP TS 05.02, section 3.3.4.1 */
.desc = "Stand-alone dedicated control channel (sub-channel 5)",
.chan_nr = RSL_CHAN_SDCCH8_ACCH + (5 << 3),
.link_id = LID_DEDIC,
/* Same as for TRXC_BCCH and TRXC_SDCCH4_* (xCCH), see above. */
.rts_fn = rts_data_fn,
.dl_fn = tx_data_fn,
.ul_fn = rx_data_fn,
.nope_fn = rx_data_fn,
},
[TRXC_SDCCH8_6] = {
.name = "SDCCH/8(6)", /* 3GPP TS 05.02, section 3.3.4.1 */
.desc = "Stand-alone dedicated control channel (sub-channel 6)",
.chan_nr = RSL_CHAN_SDCCH8_ACCH + (6 << 3),
.link_id = LID_DEDIC,
/* Same as for TRXC_BCCH and TRXC_SDCCH4_* (xCCH), see above. */
.rts_fn = rts_data_fn,
.dl_fn = tx_data_fn,
.ul_fn = rx_data_fn,
.nope_fn = rx_data_fn,
},
[TRXC_SDCCH8_7] = {
.name = "SDCCH/8(7)", /* 3GPP TS 05.02, section 3.3.4.1 */
.desc = "Stand-alone dedicated control channel (sub-channel 7)",
.chan_nr = RSL_CHAN_SDCCH8_ACCH + (7 << 3),
.link_id = LID_DEDIC,
/* Same as for TRXC_BCCH and TRXC_SDCCH4_* (xCCH), see above. */
.rts_fn = rts_data_fn,
.dl_fn = tx_data_fn,
.ul_fn = rx_data_fn,
.nope_fn = rx_data_fn,
},
[TRXC_SACCHTF] = {
.name = "SACCH/TF", /* 3GPP TS 05.02, section 3.3.4.1 */
.desc = "Slow TCH/F associated control channel",
.chan_nr = RSL_CHAN_Bm_ACCHs,
.link_id = LID_SACCH,
/* Same as for TRXC_BCCH (xCCH), see above. */
.rts_fn = rts_data_fn,
.dl_fn = tx_data_fn,
.ul_fn = rx_data_fn,
.nope_fn = rx_data_fn,
},
[TRXC_SACCHTH_0] = {
.name = "SACCH/TH(0)", /* 3GPP TS 05.02, section 3.3.4.1 */
.desc = "Slow TCH/H associated control channel (sub-channel 0)",
.chan_nr = RSL_CHAN_Lm_ACCHs + (0 << 3),
.link_id = LID_SACCH,
/* Same as for TRXC_BCCH (xCCH), see above. */
.rts_fn = rts_data_fn,
.dl_fn = tx_data_fn,
.ul_fn = rx_data_fn,
.nope_fn = rx_data_fn,
},
[TRXC_SACCHTH_1] = {
.name = "SACCH/TH(1)", /* 3GPP TS 05.02, section 3.3.4.1 */
.desc = "Slow TCH/H associated control channel (sub-channel 1)",
.chan_nr = RSL_CHAN_Lm_ACCHs + (1 << 3),
.link_id = LID_SACCH,
/* Same as for TRXC_BCCH (xCCH), see above. */
.rts_fn = rts_data_fn,
.dl_fn = tx_data_fn,
.ul_fn = rx_data_fn,
.nope_fn = rx_data_fn,
},
[TRXC_SACCH4_0] = {
.name = "SACCH/4(0)", /* 3GPP TS 05.02, section 3.3.4.1 */
.desc = "Slow SDCCH/4 associated control channel (sub-channel 0)",
.chan_nr = RSL_CHAN_SDCCH4_ACCH + (0 << 3),
.link_id = LID_SACCH,
/* Same as for TRXC_BCCH and TRXC_SDCCH4_* (xCCH), see above. */
.rts_fn = rts_data_fn,
.dl_fn = tx_data_fn,
.ul_fn = rx_data_fn,
.nope_fn = rx_data_fn,
},
[TRXC_SACCH4_1] = {
.name = "SACCH/4(1)", /* 3GPP TS 05.02, section 3.3.4.1 */
.desc = "Slow SDCCH/4 associated control channel (sub-channel 1)",
.chan_nr = RSL_CHAN_SDCCH4_ACCH + (1 << 3),
.link_id = LID_SACCH,
/* Same as for TRXC_BCCH and TRXC_SDCCH4_* (xCCH), see above. */
.rts_fn = rts_data_fn,
.dl_fn = tx_data_fn,
.ul_fn = rx_data_fn,
.nope_fn = rx_data_fn,
},
[TRXC_SACCH4_2] = {
.name = "SACCH/4(2)", /* 3GPP TS 05.02, section 3.3.4.1 */
.desc = "Slow SDCCH/4 associated control channel (sub-channel 2)",
.chan_nr = RSL_CHAN_SDCCH4_ACCH + (2 << 3),
.link_id = LID_SACCH,
/* Same as for TRXC_BCCH and TRXC_SDCCH4_* (xCCH), see above. */
.rts_fn = rts_data_fn,
.dl_fn = tx_data_fn,
.ul_fn = rx_data_fn,
.nope_fn = rx_data_fn,
},
[TRXC_SACCH4_3] = {
.name = "SACCH/4(3)", /* 3GPP TS 05.02, section 3.3.4.1 */
.desc = "Slow SDCCH/4 associated control channel (sub-channel 3)",
.chan_nr = RSL_CHAN_SDCCH4_ACCH + (3 << 3),
.link_id = LID_SACCH,
/* Same as for TRXC_BCCH and TRXC_SDCCH4_* (xCCH), see above. */
.rts_fn = rts_data_fn,
.dl_fn = tx_data_fn,
.ul_fn = rx_data_fn,
.nope_fn = rx_data_fn,
},
[TRXC_SACCH8_0] = {
.name = "SACCH/8(0)", /* 3GPP TS 05.02, section 3.3.4.1 */
.desc = "Slow SDCCH/8 associated control channel (sub-channel 0)",
.chan_nr = RSL_CHAN_SDCCH8_ACCH + (0 << 3),
.link_id = LID_SACCH,
/* Same as for TRXC_BCCH and TRXC_SDCCH8_* (xCCH), see above. */
.rts_fn = rts_data_fn,
.dl_fn = tx_data_fn,
.ul_fn = rx_data_fn,
.nope_fn = rx_data_fn,
},
[TRXC_SACCH8_1] = {
.name = "SACCH/8(1)", /* 3GPP TS 05.02, section 3.3.4.1 */
.desc = "Slow SDCCH/8 associated control channel (sub-channel 1)",
.chan_nr = RSL_CHAN_SDCCH8_ACCH + (1 << 3),
.link_id = LID_SACCH,
/* Same as for TRXC_BCCH and TRXC_SDCCH8_* (xCCH), see above. */
.rts_fn = rts_data_fn,
.dl_fn = tx_data_fn,
.ul_fn = rx_data_fn,
.nope_fn = rx_data_fn,
},
[TRXC_SACCH8_2] = {
.name = "SACCH/8(2)", /* 3GPP TS 05.02, section 3.3.4.1 */
.desc = "Slow SDCCH/8 associated control channel (sub-channel 2)",
.chan_nr = RSL_CHAN_SDCCH8_ACCH + (2 << 3),
.link_id = LID_SACCH,
/* Same as for TRXC_BCCH and TRXC_SDCCH8_* (xCCH), see above. */
.rts_fn = rts_data_fn,
.dl_fn = tx_data_fn,
.ul_fn = rx_data_fn,
.nope_fn = rx_data_fn,
},
[TRXC_SACCH8_3] = {
.name = "SACCH/8(3)", /* 3GPP TS 05.02, section 3.3.4.1 */
.desc = "Slow SDCCH/8 associated control channel (sub-channel 3)",
.chan_nr = RSL_CHAN_SDCCH8_ACCH + (3 << 3),
.link_id = LID_SACCH,
/* Same as for TRXC_BCCH and TRXC_SDCCH8_* (xCCH), see above. */
.rts_fn = rts_data_fn,
.dl_fn = tx_data_fn,
.ul_fn = rx_data_fn,
.nope_fn = rx_data_fn,
},
[TRXC_SACCH8_4] = {
.name = "SACCH/8(4)", /* 3GPP TS 05.02, section 3.3.4.1 */
.desc = "Slow SDCCH/8 associated control channel (sub-channel 4)",
.chan_nr = RSL_CHAN_SDCCH8_ACCH + (4 << 3),
.link_id = LID_SACCH,
/* Same as for TRXC_BCCH and TRXC_SDCCH8_* (xCCH), see above. */
.rts_fn = rts_data_fn,
.dl_fn = tx_data_fn,
.ul_fn = rx_data_fn,
.nope_fn = rx_data_fn,
},
[TRXC_SACCH8_5] = {
.name = "SACCH/8(5)", /* 3GPP TS 05.02, section 3.3.4.1 */
.desc = "Slow SDCCH/8 associated control channel (sub-channel 5)",
.chan_nr = RSL_CHAN_SDCCH8_ACCH + (5 << 3),
.link_id = LID_SACCH,
/* Same as for TRXC_BCCH and TRXC_SDCCH8_* (xCCH), see above. */
.rts_fn = rts_data_fn,
.dl_fn = tx_data_fn,
.ul_fn = rx_data_fn,
.nope_fn = rx_data_fn,
},
[TRXC_SACCH8_6] = {
.name = "SACCH/8(6)", /* 3GPP TS 05.02, section 3.3.4.1 */
.desc = "Slow SDCCH/8 associated control channel (sub-channel 6)",
.chan_nr = RSL_CHAN_SDCCH8_ACCH + (6 << 3),
.link_id = LID_SACCH,
/* Same as for TRXC_BCCH and TRXC_SDCCH8_* (xCCH), see above. */
.rts_fn = rts_data_fn,
.dl_fn = tx_data_fn,
.ul_fn = rx_data_fn,
.nope_fn = rx_data_fn,
},
[TRXC_SACCH8_7] = {
.name = "SACCH/8(7)", /* 3GPP TS 05.02, section 3.3.4.1 */
.desc = "Slow SDCCH/8 associated control channel (sub-channel 7)",
.chan_nr = RSL_CHAN_SDCCH8_ACCH + (7 << 3),
.link_id = LID_SACCH,
/* Same as for TRXC_BCCH and TRXC_SDCCH8_* (xCCH), see above. */
.rts_fn = rts_data_fn,
.dl_fn = tx_data_fn,
.ul_fn = rx_data_fn,
.nope_fn = rx_data_fn,
},
[TRXC_PDTCH] = {
.name = "PDTCH", /* 3GPP TS 05.02, sections 3.2.4, 3.3.2.4 */
.desc = "Packet data traffic & control channel",
.chan_nr = RSL_CHAN_OSMO_PDCH,
/* Rx and Tx, multiple coding schemes: CS-2..4 and MCS-1..9 (3GPP TS
* 05.03, chapter 5), regular interleaving as specified for xCCH.
* NOTE: the burst buffer is three times bigger because the
* payload of EDGE bursts is three times longer. */
.flags = TRX_CHAN_FLAG_PDCH,
.rts_fn = rts_data_fn,
.dl_fn = tx_pdtch_fn,
.ul_fn = rx_pdtch_fn,
},
[TRXC_PTCCH] = {
.name = "PTCCH", /* 3GPP TS 05.02, section 3.3.4.2 */
.desc = "Packet Timing advance control channel",
.chan_nr = RSL_CHAN_OSMO_PDCH,
/* On the Uplink, mobile stations transmit random Access Bursts
* to allow estimation of the timing advance for one MS in packet
* transfer mode. On Downlink, the network sends timing advance
* updates for several mobile stations. The coding scheme used
* for PTCCH/D messages is the same as for PDTCH CS-1. */
.flags = TRX_CHAN_FLAG_PDCH,
.rts_fn = rts_data_fn,
.dl_fn = tx_pdtch_fn,
.ul_fn = rx_rach_fn,
},
[TRXC_CBCH] = {
/* TODO: distinguish CBCH on SDCCH/4 and SDCCH/8 */
.name = "CBCH", /* 3GPP TS 05.02, section 3.3.5 */
.desc = "Cell Broadcast channel",
.chan_nr = RSL_CHAN_OSMO_CBCH4,
/* Tx only, same as for TRXC_BCCH (xCCH), see above. */
.flags = TRX_CHAN_FLAG_AUTO_ACTIVE,
.rts_fn = rts_data_fn,
.dl_fn = tx_data_fn,
},
};
/*
@@ -311,7 +701,7 @@ free_msg:
"type %s is already disabled. If this happens in "
"conjunction with PCU, increase 'rts-advance' by 5.\n",
prim_fn, get_lchan_by_chan_nr(l1t->trx, chan_nr)->name,
get_value_string(trx_chan_type_names, chan));
trx_chan_desc[chan].name);
/* unlink and free message */
llist_del(&msg->list);
msgb_free(msg);
@@ -378,7 +768,8 @@ int _sched_compose_ph_data_ind(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
}
int _sched_compose_tch_ind(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
enum trx_chan_type chan, uint8_t *tch, uint8_t tch_len)
enum trx_chan_type chan, uint8_t *tch, uint8_t tch_len,
int16_t ta_offs_256bits, uint16_t ber10k, float rssi)
{
struct msgb *msg;
struct osmo_phsap_prim *l1sap;
@@ -394,6 +785,10 @@ int _sched_compose_tch_ind(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
PRIM_OP_INDICATION, msg);
l1sap->u.tch.chan_nr = chan_nr;
l1sap->u.tch.fn = fn;
l1sap->u.tch.rssi = (int8_t) (rssi);
l1sap->u.tch.ber10k = ber10k;
l1sap->u.tch.ta_offs_256bits = ta_offs_256bits;
msg->l2h = msgb_put(msg, tch_len);
if (tch_len)
memcpy(msg->l2h, tch, tch_len);
@@ -421,12 +816,11 @@ int trx_sched_ph_data_req(struct l1sched_trx *l1t, struct osmo_phsap_prim *l1sap
uint8_t tn = l1sap->u.data.chan_nr & 7;
struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn);
LOGL1S(DL1P, LOGL_INFO, l1t, tn, -1, l1sap->u.data.fn,
LOGL1S(DL1P, LOGL_DEBUG, l1t, tn, -1, l1sap->u.data.fn,
"PH-DATA.req: chan_nr=0x%02x link_id=0x%02x\n",
l1sap->u.data.chan_nr, l1sap->u.data.link_id);
if (!l1sap->oph.msg)
abort();
OSMO_ASSERT(l1sap->oph.msg);
/* ignore empty frame */
if (!msgb_l2len(l1sap->oph.msg)) {
@@ -444,11 +838,10 @@ int trx_sched_tch_req(struct l1sched_trx *l1t, struct osmo_phsap_prim *l1sap)
uint8_t tn = l1sap->u.tch.chan_nr & 7;
struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn);
LOGL1S(DL1P, LOGL_INFO, l1t, tn, -1, l1sap->u.tch.fn, "TCH.req: chan_nr=0x%02x\n",
LOGL1S(DL1P, LOGL_DEBUG, l1t, tn, -1, l1sap->u.tch.fn, "TCH.req: chan_nr=0x%02x\n",
l1sap->u.tch.chan_nr);
if (!l1sap->oph.msg)
abort();
OSMO_ASSERT(l1sap->oph.msg);
/* ignore empty frame */
if (!msgb_l2len(l1sap->oph.msg)) {
@@ -484,7 +877,7 @@ static int rts_data_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
return -ENODEV;
}
LOGL1S(DL1P, LOGL_INFO, l1t, tn, chan, fn,
LOGL1S(DL1P, LOGL_DEBUG, l1t, tn, chan, fn,
"PH-RTS.ind: chan_nr=0x%02x link_id=0x%02x\n", chan_nr, link_id);
/* generate prim */
@@ -520,7 +913,7 @@ static int rts_tch_common(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
return -ENODEV;
}
LOGL1S(DL1P, LOGL_INFO, l1t, tn, chan, fn, "TCH RTS.ind: chan_nr=0x%02x\n", chan_nr);
LOGL1S(DL1P, LOGL_DEBUG, l1t, tn, chan, fn, "TCH RTS.ind: chan_nr=0x%02x\n", chan_nr);
/* only send, if FACCH is selected */
if (facch) {
@@ -538,7 +931,7 @@ static int rts_tch_common(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
rc = l1sap_up(l1t->trx, l1sap);
}
/* dont send, if TCH is in signalling only mode */
/* don't send, if TCH is in signalling only mode */
if (l1ts->chan_state[chan].rsl_cmode != RSL_CMOD_SPD_SIGN) {
/* generate prim */
msg = l1sap_msgb_alloc(200);
@@ -608,10 +1001,10 @@ int trx_sched_set_lchan(struct l1sched_trx *l1t, uint8_t chan_nr, uint8_t link_i
for (i = 0; i < _TRX_CHAN_MAX; i++) {
struct l1sched_chan_state *chan_state;
chan_state = &l1ts->chan_state[i];
/* skip if pchan type does not match pdch flag */
if ((trx_sched_multiframes[l1ts->mf_index].pchan
== GSM_PCHAN_PDCH)
!= trx_chan_desc[i].pdch)
/* Skip if pchan type does not match pdch flag.
* FIXME: Is it possible at all? Clarify if so. */
if ((trx_sched_multiframes[l1ts->mf_index].pchan == GSM_PCHAN_PDCH)
&& !(trx_chan_desc[i].flags & TRX_CHAN_FLAG_PDCH))
continue;
if (trx_chan_desc[i].chan_nr == (chan_nr & 0xf8)
&& trx_chan_desc[i].link_id == link_id) {
@@ -727,7 +1120,7 @@ int trx_sched_set_cipher(struct l1sched_trx *l1t, uint8_t chan_nr, int downlink,
/* look for all matching chan_nr */
for (i = 0; i < _TRX_CHAN_MAX; i++) {
/* skip if pchan type */
if (trx_chan_desc[i].pdch)
if (trx_chan_desc[i].flags & TRX_CHAN_FLAG_PDCH)
continue;
if (trx_chan_desc[i].chan_nr == (chan_nr & 0xf8)) {
chan_state = &l1ts->chan_state[i];
@@ -782,8 +1175,7 @@ int _sched_rts(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn)
return 0;
/* check if channel is active */
if (!trx_chan_desc[chan].auto_active
&& !l1ts->chan_state[chan].active)
if (!TRX_CHAN_IS_ACTIVE(&l1ts->chan_state[chan], chan))
return -EINVAL;
return func(l1t, tn, fn, frame->dl_chan);
@@ -816,7 +1208,7 @@ const ubit_t *_sched_dl_burst(struct l1sched_trx *l1t, uint8_t tn,
l1cs = &l1ts->chan_state[chan];
/* check if channel is active */
if (!trx_chan_desc[chan].auto_active && !l1cs->active) {
if (!TRX_CHAN_IS_ACTIVE(l1cs, chan)) {
if (nbits)
*nbits = GSM_BURST_LEN;
goto no_data;
@@ -909,7 +1301,7 @@ static int trx_sched_calc_frame_loss(struct l1sched_trx *l1t,
* There are several TDMA frames between the last processed
* frame and currently received one. Let's walk through this
* path and count potentially lost frames, i.e. for which
* we didn't receive the corresponsing UL bursts.
* we didn't receive the corresponding UL bursts.
*
* Start counting from the last_fn + 1.
*/
@@ -933,9 +1325,19 @@ static int trx_sched_calc_frame_loss(struct l1sched_trx *l1t,
* Instead of doing this, it makes sense to use the
* amount of lost frames in measurement calculations.
*/
static sbit_t zero_burst[GSM_BURST_LEN] = { 0 };
trx_sched_ul_func *func;
/* Prepare dummy burst indication */
struct trx_ul_burst_ind bi = {
.flags = TRX_BI_F_NOPE_IND,
.burst_len = GSM_BURST_LEN,
.burst = { 0 },
.rssi = -128,
.toa256 = 0,
/* TDMA FN is set below */
.tn = tn,
};
for (i = 1; i < elapsed_fs; i++) {
fn_i = TDMA_FN_SUM(l1cs->last_tdma_fn, i);
offset = fn_i % l1ts->mf_period;
@@ -949,8 +1351,8 @@ static int trx_sched_calc_frame_loss(struct l1sched_trx *l1t,
"Substituting lost TDMA frame=%u by all-zero "
"dummy burst\n", fn_i);
func(l1t, tn, fn_i, frame->ul_chan, frame->ul_bid,
zero_burst, GSM_BURST_LEN, -128, 0);
bi.fn = fn_i;
func(l1t, frame->ul_chan, frame->ul_bid, &bi);
l1cs->lost_tdma_fs--;
}
@@ -959,11 +1361,10 @@ static int trx_sched_calc_frame_loss(struct l1sched_trx *l1t,
return 0;
}
/* process uplink burst */
int trx_sched_ul_burst(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
sbit_t *bits, uint16_t nbits, int8_t rssi, int16_t toa256)
/* Process an Uplink burst indication */
int trx_sched_ul_burst(struct l1sched_trx *l1t, struct trx_ul_burst_ind *bi)
{
struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn);
struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, bi->tn);
struct l1sched_chan_state *l1cs;
const struct trx_sched_frame *frame;
uint8_t offset, period, bid;
@@ -975,7 +1376,7 @@ int trx_sched_ul_burst(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
/* get frame from multiframe */
period = l1ts->mf_period;
offset = fn % period;
offset = bi->fn % period;
frame = l1ts->mf_frames + offset;
chan = frame->ul_chan;
@@ -983,8 +1384,15 @@ int trx_sched_ul_burst(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
l1cs = &l1ts->chan_state[chan];
func = trx_chan_desc[chan].ul_fn;
/* TODO: handle noise measurements */
if (chan == TRXC_IDLE && bi->flags & TRX_BI_F_NOPE_IND) {
LOGL1S(DL1P, LOGL_DEBUG, l1t, bi->tn, chan, bi->fn,
"Rx noise measurement (%d)\n", bi->rssi);
return -ENOTSUP;
}
/* check if channel is active */
if (!trx_chan_desc[chan].auto_active && !l1cs->active)
if (!TRX_CHAN_IS_ACTIVE(l1cs, chan))
return -EINVAL;
/* omit bursts which have no handler, like IDLE bursts */
@@ -992,28 +1400,36 @@ int trx_sched_ul_burst(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
return -EINVAL;
/* calculate how many TDMA frames were potentially lost */
trx_sched_calc_frame_loss(l1t, l1cs, tn, fn);
trx_sched_calc_frame_loss(l1t, l1cs, bi->tn, bi->fn);
/* update TDMA frame counters */
l1cs->last_tdma_fn = fn;
l1cs->last_tdma_fn = bi->fn;
l1cs->proc_tdma_fs++;
/* handle NOPE indications (if the handler is present) */
if (bi->flags & TRX_BI_F_NOPE_IND) {
func = trx_chan_desc[chan].nope_fn;
if (!func)
return 0;
return func(l1t, chan, bid, bi);
}
/* decrypt */
if (bits && l1cs->ul_encr_algo) {
if (bi->burst_len && l1cs->ul_encr_algo) {
ubit_t ks[114];
int i;
osmo_a5(l1cs->ul_encr_algo, l1cs->ul_encr_key, fn, NULL, ks);
osmo_a5(l1cs->ul_encr_algo, l1cs->ul_encr_key, bi->fn, NULL, ks);
for (i = 0; i < 57; i++) {
if (ks[i])
bits[i + 3] = - bits[i + 3];
bi->burst[i + 3] = - bi->burst[i + 3];
if (ks[i + 57])
bits[i + 88] = - bits[i + 88];
bi->burst[i + 88] = - bi->burst[i + 88];
}
}
/* put burst to function */
func(l1t, tn, fn, chan, bid, bits, nbits, rssi, toa256);
/* Invoke the logical channel handler */
func(l1t, chan, bid, bi);
return 0;
}

View File

@@ -1,4 +1,4 @@
/* (C) 2011 by Harald Welte <laforge@gnumonks.org>
/* (C) 2011-2019 by Harald Welte <laforge@gnumonks.org>
*
* All Rights Reserved
*
@@ -24,6 +24,7 @@
#include <osmo-bts/logging.h>
#include <osmo-bts/gsm_data.h>
#include <osmo-bts/pcu_if.h>
/* properly increment SI2q index and return SI2q data for scheduling */
static inline uint8_t *get_si2q_inc_index(struct gsm_bts *bts)
@@ -155,7 +156,7 @@ uint8_t num_agch(struct gsm_bts_trx *trx, const char * arg)
si3 = GSM_BTS_SI(b, SYSINFO_TYPE_3);
return si3->control_channel_desc.bs_ag_blks_res;
}
LOGP(DL1P, LOGL_ERROR, "%s: Unable to determine actual BS_AG_BLKS_RES "
LOGP(DL1P, LOGL_NOTICE, "%s: Unable to determine actual BS_AG_BLKS_RES "
"value as SI3 is not available yet, fallback to 1\n", arg);
return 1;
}
@@ -172,6 +173,39 @@ uint8_t *lchan_sacch_get(struct gsm_lchan *lchan)
lchan->si.last = tmp;
return GSM_LCHAN_SI(lchan, tmp);
}
LOGP(DL1P, LOGL_NOTICE, "%s SACCH no SI available\n", gsm_lchan_name(lchan));
LOGPLCHAN(lchan, DL1P, LOGL_NOTICE, "SACCH no SI available\n");
return NULL;
}
/* re-generate SI3 restoctets with GPRS indicator depending on the PCU socket connection state */
void regenerate_si3_restoctets(struct gsm_bts *bts)
{
uint8_t *si3_buf = GSM_BTS_SI(bts, SYSINFO_TYPE_3);
size_t si3_size = offsetof(struct gsm48_system_information_type_3, rest_octets);
struct osmo_gsm48_si_ro_info si3ro_tmp;
/* If BSC has never set SI3, there's nothing to patch */
if (!GSM_BTS_HAS_SI(bts, SYSINFO_TYPE_3))
return;
/* If SI3 from BSC doesn't have a GPRS indicator, we won't have anything to patch */
if (!bts->si3_ro_decoded.gprs_ind.present)
return;
/* Create a temporary copy and patch that, if no PCU is around */
si3ro_tmp = bts->si3_ro_decoded;
if (!pcu_connected()) {
if (!bts->si3_gprs_ind_disabled)
LOGP(DPCU, LOGL_NOTICE, "Disabling GPRS Indicator in SI3 (No PCU connected)\n");
bts->si3_gprs_ind_disabled = true;
si3ro_tmp.gprs_ind.present = 0;
} else {
if (bts->si3_gprs_ind_disabled)
LOGP(DPCU, LOGL_NOTICE, "Enabling GPRS Indicator in SI3 (PCU connected)\n");
bts->si3_gprs_ind_disabled = false;
si3ro_tmp.gprs_ind.present = 1; /* is a no-op as we copy from bts->si3_ro_decoded */
}
/* re-generate the binary SI3 rest octets */
osmo_gsm48_rest_octets_si3_encode(si3_buf + si3_size, &si3ro_tmp);
}

55
src/common/ta_control.c Normal file
View File

@@ -0,0 +1,55 @@
/* Loop control for Timing Advance */
/* (C) 2013 by Andreas Eversberg <jolly@eversberg.eu>
*
* All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <osmo-bts/gsm_data.h>
#include <osmo-bts/logging.h>
/* 90% of one bit duration in 1/256 symbols: 256*0.9 */
#define TOA256_9OPERCENT 230
/* rqd_ta value range */
#define TOA_MIN 0
#define TOA_MAX 63
void lchan_ms_ta_ctrl(struct gsm_lchan *lchan)
{
int16_t toa256 = lchan->meas.ms_toa256;
/* Do not perform any computation when the amount of measurement
* results is too little. */
if (lchan->meas.num_ul_meas < 4)
return;
if (toa256 < -TOA256_9OPERCENT && lchan->rqd_ta > TOA_MIN) {
LOGPLCHAN(lchan, DLOOP, LOGL_INFO,
"TOA is too early (%d), now lowering TA from %d to %d\n",
toa256, lchan->rqd_ta, lchan->rqd_ta - 1);
lchan->rqd_ta--;
} else if (toa256 > TOA256_9OPERCENT && lchan->rqd_ta < TOA_MAX) {
LOGPLCHAN(lchan, DLOOP, LOGL_INFO,
"TOA is too late (%d), now raising TA from %d to %d\n",
toa256, lchan->rqd_ta, lchan->rqd_ta + 1);
lchan->rqd_ta++;
} else
LOGPLCHAN(lchan, DLOOP, LOGL_DEBUG,
"TOA is correct (%d), keeping current TA of %d\n",
toa256, lchan->rqd_ta);
}

View File

@@ -26,11 +26,13 @@
#include <netinet/in.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <errno.h>
#include <osmocom/core/talloc.h>
#include <osmocom/gsm/abis_nm.h>
#include <osmocom/gsm/protocol/gsm_04_08.h>
#include <osmocom/vty/vty.h>
#include <osmocom/vty/stats.h>
#include <osmocom/vty/command.h>
#include <osmocom/vty/logging.h>
#include <osmocom/vty/misc.h>
@@ -123,48 +125,6 @@ int bts_vty_is_config_node(struct vty *vty, int node)
}
}
gDEFUN(ournode_exit, ournode_exit_cmd, "exit",
"Exit current node, go down to provious node")
{
switch (vty->node) {
case PHY_INST_NODE:
vty->node = PHY_NODE;
{
struct phy_instance *pinst = vty->index;
vty->index = pinst->phy_link;
}
break;
case PHY_NODE:
vty->node = CONFIG_NODE;
vty->index = NULL;
break;
case TRX_NODE:
vty->node = BTS_NODE;
{
struct gsm_bts_trx *trx = vty->index;
vty->index = trx->bts;
}
break;
default:
break;
}
return CMD_SUCCESS;
}
gDEFUN(ournode_end, ournode_end_cmd, "end",
"End current mode and change to enable mode")
{
switch (vty->node) {
default:
vty_config_unlock(vty);
vty->node = ENABLE_NODE;
vty->index = NULL;
vty->index_sub = NULL;
break;
}
return CMD_SUCCESS;
}
static const char osmobts_copyright[] =
"Copyright (C) 2010, 2011 by Harald Welte, Andreas Eversberg and On-Waves\r\n"
"License AGPLv3+: GNU AGPL version 3 or later <http://gnu.org/licenses/agpl-3.0.html>\r\n"
@@ -277,6 +237,8 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts)
vty_out(vty, "%s", VTY_NEWLINE);
vty_out(vty, " rtp port-range %u %u%s", bts->rtp_port_range_start,
bts->rtp_port_range_end, VTY_NEWLINE);
if (bts->rtp_ip_dscp != -1)
vty_out(vty, " rtp ip-dscp %i%s", bts->rtp_ip_dscp, VTY_NEWLINE);
vty_out(vty, " paging queue-size %u%s", paging_get_queue_max(bts->paging_state),
VTY_NEWLINE);
vty_out(vty, " paging lifetime %u%s", paging_get_lifetime(bts->paging_state),
@@ -290,7 +252,7 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts)
bts->agch_queue.high_level, VTY_NEWLINE);
for (i = 0; i < 32; i++) {
if (gsmtap_sapi_mask & (1 << i)) {
if (gsmtap_sapi_mask & ((uint32_t) 1 << i)) {
sapi_buf = osmo_str_tolower(get_value_string(gsmtap_sapi_names, i));
vty_out(vty, " gsmtap-sapi %s%s", sapi_buf, VTY_NEWLINE);
}
@@ -299,9 +261,9 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts)
sapi_buf = osmo_str_tolower(get_value_string(gsmtap_sapi_names, GSMTAP_CHANNEL_ACCH));
vty_out(vty, " gsmtap-sapi %s%s", sapi_buf, VTY_NEWLINE);
}
vty_out(vty, " min-qual-rach %.0f%s", bts->min_qual_rach * 10.0f,
vty_out(vty, " min-qual-rach %d%s", bts->min_qual_rach,
VTY_NEWLINE);
vty_out(vty, " min-qual-norm %.0f%s", bts->min_qual_norm * 10.0f,
vty_out(vty, " min-qual-norm %d%s", bts->min_qual_norm,
VTY_NEWLINE);
vty_out(vty, " max-ber10k-rach %u%s", bts->max_ber10k_rach,
VTY_NEWLINE);
@@ -309,6 +271,9 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts)
vty_out(vty, " pcu-socket %s%s", bts->pcu.sock_path, VTY_NEWLINE);
if (bts->supp_meas_toa256)
vty_out(vty, " supp-meas-info toa256%s", VTY_NEWLINE);
vty_out(vty, " smscb queue-max-length %d%s", bts->smscb_queue_max_len, VTY_NEWLINE);
vty_out(vty, " smscb queue-target-length %d%s", bts->smscb_queue_tgt_len, VTY_NEWLINE);
vty_out(vty, " smscb queue-hysteresis %d%s", bts->smscb_queue_hyst, VTY_NEWLINE);
bts_model_config_write_bts(vty, bts);
@@ -327,7 +292,7 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts)
vty_out(vty, " power-ramp step-interval %d%s",
tpp->ramp.step_interval_sec, VTY_NEWLINE);
vty_out(vty, " ms-power-control %s%s",
trx->ms_power_control == 0 ? "dsp" : "osmo",
trx->ms_pwr_ctl_soft ? "osmo" : "dsp",
VTY_NEWLINE);
vty_out(vty, " phy %u instance %u%s", pinst->phy_link->num,
pinst->num, VTY_NEWLINE);
@@ -538,6 +503,19 @@ DEFUN(cfg_bts_rtp_port_range,
return CMD_SUCCESS;
}
DEFUN(cfg_bts_rtp_ip_dscp,
cfg_bts_rtp_ip_dscp_cmd,
"rtp ip-dscp <0-63>",
RTP_STR "Specify DSCP for RTP/IP packets\n" "The DSCP value (upper 6 bits of TOS)\n")
{
struct gsm_bts *bts = vty->index;
int dscp = atoi(argv[0]);
bts->rtp_ip_dscp = dscp;
return CMD_SUCCESS;
}
#define PAG_STR "Paging related parameters\n"
DEFUN(cfg_bts_paging_queue_size,
@@ -614,24 +592,24 @@ DEFUN(cfg_bts_ul_power_target, cfg_bts_ul_power_target_cmd,
DEFUN(cfg_bts_min_qual_rach, cfg_bts_min_qual_rach_cmd,
"min-qual-rach <-100-100>",
"Set the minimum quality level of RACH burst to be accpeted\n"
"C/I level in tenth of dB\n")
"Set the minimum link quality level of Access Bursts to be accepted\n"
"C/I (Carrier-to-Interference) ratio in centiBels (10e-2 B or 10e-1 dB)\n")
{
struct gsm_bts *bts = vty->index;
bts->min_qual_rach = strtof(argv[0], NULL) / 10.0f;
bts->min_qual_rach = atoi(argv[0]);
return CMD_SUCCESS;
}
DEFUN(cfg_bts_min_qual_norm, cfg_bts_min_qual_norm_cmd,
"min-qual-norm <-100-100>",
"Set the minimum quality level of normal burst to be accpeted\n"
"C/I level in tenth of dB\n")
"Set the minimum link quality level of Normal Bursts to be accepted\n"
"C/I (Carrier-to-Interference) ratio in centiBels (10e-2 B or 10e-1 dB)\n")
{
struct gsm_bts *bts = vty->index;
bts->min_qual_norm = strtof(argv[0], NULL) / 10.0f;
bts->min_qual_norm = atoi(argv[0]);
return CMD_SUCCESS;
}
@@ -686,6 +664,33 @@ DEFUN(cfg_bts_no_supp_meas_toa256, cfg_bts_no_supp_meas_toa256_cmd,
return CMD_SUCCESS;
}
DEFUN(cfg_bts_smscb_max_qlen, cfg_bts_smscb_max_qlen_cmd,
"smscb queue-max-length <1-60>",
"Maximum queue length for SMSCB (CBCH) queue. In count of messages/pages (Default: 15)")
{
struct gsm_bts *bts = vty->index;
bts->smscb_queue_max_len = atoi(argv[0]);
return CMD_SUCCESS;
}
DEFUN(cfg_bts_smscb_tgt_qlen, cfg_bts_smscb_tgt_qlen_cmd,
"smscb queue-target-length <1-30>",
"Target queue length for SMSCB (CBCH) queue. In count of messages/pages (Default: 2)")
{
struct gsm_bts *bts = vty->index;
bts->smscb_queue_tgt_len = atoi(argv[0]);
return CMD_SUCCESS;
}
DEFUN(cfg_bts_smscb_qhyst, cfg_bts_smscb_qhyst_cmd,
"smscb queue-hysteresis <0-30>",
"Hysteresis for SMSCB (CBCH) queue. In count of messages/pages (Default: 2)")
{
struct gsm_bts *bts = vty->index;
bts->smscb_queue_hyst = atoi(argv[0]);
return CMD_SUCCESS;
}
#define DB_DBM_STR \
"Unit is dB (decibels)\n" \
@@ -757,8 +762,23 @@ DEFUN(cfg_trx_ms_power_control, cfg_trx_ms_power_control_cmd,
"Handled by DSP\n" "Handled by OsmoBTS\n")
{
struct gsm_bts_trx *trx = vty->index;
bool soft = !strcmp(argv[0], "osmo");
trx->ms_power_control = argv[0][0] == 'd' ? 0 : 1;
if (!soft && !gsm_bts_has_feature(trx->bts, BTS_FEAT_MS_PWR_CTRL_DSP)) {
/* NOTE: osmo-bts-trx used to have its own (low-level) MS Power Control loop, which
* has been ripped out in favour of the common implementation. Configuration files
* may still contain 'dsp', so let's be tolerant and override 'dsp' by 'osmo'. */
if (trx->bts->variant == BTS_OSMO_TRX && vty->type == VTY_FILE) {
vty_out(vty, "BTS model 'osmo-bts-trx' has no DSP/HW MS Power Control support, "
"consider updating your configuration file!%s", VTY_NEWLINE);
soft = true; /* override */
} else {
vty_out(vty, "This BTS model has no DSP/HW MS Power Control support%s", VTY_NEWLINE);
return CMD_WARNING;
}
}
trx->ms_pwr_ctl_soft = soft;
return CMD_SUCCESS;
}
@@ -802,17 +822,6 @@ static void net_dump_nmstate(struct vty *vty, struct gsm_nm_state *nms)
abis_nm_avail_name(nms->availability), VTY_NEWLINE);
}
static unsigned int llist_length(struct llist_head *list)
{
unsigned int len = 0;
struct llist_head *pos;
llist_for_each(pos, list)
len++;
return len;
}
static void bts_dump_vty_features(struct vty *vty, struct gsm_bts *bts)
{
unsigned int i;
@@ -864,13 +873,19 @@ static void bts_dump_vty(struct vty *vty, struct gsm_bts *bts)
bts->agch_queue.rejected_msgs, bts->agch_queue.agch_msgs,
bts->agch_queue.pch_msgs,
VTY_NEWLINE);
vty_out(vty, " CBCH backlog queue length: %u%s",
llist_length(&bts->smscb_state.queue), VTY_NEWLINE);
vty_out(vty, " CBCH queue target: %d, hysteresis: %d, maximum: %d%s",
bts->smscb_queue_tgt_len, bts->smscb_queue_max_len, bts->smscb_queue_hyst, VTY_NEWLINE);
vty_out(vty, " CBCH backlog queue length (BASIC): %d%s",
bts->smscb_basic.queue_len, VTY_NEWLINE);
vty_out(vty, " CBCH backlog queue length (EXTENDED): %u%s",
bts->smscb_extended.queue_len, VTY_NEWLINE);
vty_out(vty, " Paging: queue length %d, buffer space %d%s",
paging_queue_length(bts->paging_state), paging_buffer_space(bts->paging_state),
VTY_NEWLINE);
vty_out(vty, " OML Link state: %s.%s",
bts->oml_link ? "connected" : "disconnected", VTY_NEWLINE);
vty_out(vty, " PH-RTS.ind FN advance average: %d, min: %d, max: %d%s",
bts_get_avg_fn_advance(bts), bts->fn_stats.min, bts->fn_stats.max, VTY_NEWLINE);
llist_for_each_entry(trx, &bts->trx_list, list) {
struct phy_instance *pinst = trx_phy_instance(trx);
@@ -913,6 +928,25 @@ DEFUN(show_bts, show_bts_cmd, "show bts <0-255>",
return CMD_SUCCESS;
}
DEFUN(test_send_failure_event_report, test_send_failure_event_report_cmd, "test send-failure-event-report <0-255>",
"Various testing commands\n"
"Send a test OML failure event report to the BSC\n" BTS_NR_STR)
{
struct gsm_network *net = gsmnet_from_vty(vty);
int bts_nr = atoi(argv[0]);
struct gsm_bts *bts;
if (bts_nr >= net->num_bts) {
vty_out(vty, "%% can't find BTS '%s'%s", argv[0], VTY_NEWLINE);
return CMD_WARNING;
}
bts = gsm_bts_num(net, bts_nr);
oml_tx_failure_event_rep(&bts->mo, NM_SEVER_MINOR, OSMO_EVT_WARN_SW_WARN, "test message sent from VTY");
return CMD_SUCCESS;
}
static void trx_dump_vty(struct vty *vty, struct gsm_bts_trx *trx)
{
vty_out(vty, "TRX %u of BTS %u is on ARFCN %u%s",
@@ -1146,7 +1180,7 @@ static void lchan_dump_full_vty(struct vty *vty, struct gsm_lchan *lchan)
vty_out(vty, " BS Power: %d dBm, MS Power: %u dBm%s",
lchan->ts->trx->nominal_power - lchan->ts->trx->max_power_red
- lchan->bs_power*2,
ms_pwr_dbm(lchan->ts->trx->bts->band, lchan->ms_power),
ms_pwr_dbm(lchan->ts->trx->bts->band, lchan->ms_power_ctrl.max),
VTY_NEWLINE);
vty_out(vty, " Channel Mode / Codec: %s%s",
get_value_string(gsm48_cmode_names, lchan->tch_mode),
@@ -1463,8 +1497,8 @@ DEFUN(cfg_phy_inst, cfg_phy_inst_cmd,
}
DEFUN(cfg_phy_no_inst, cfg_phy_no_inst_cmd,
"no instance <0-255>"
NO_STR "Select a PHY instance to remove\n", "PHY Instance number\n")
"no instance <0-255>",
NO_STR "Select a PHY instance to remove\n" "PHY Instance number\n")
{
int inst_nr = atoi(argv[0]);
struct phy_link *plink = vty->index;
@@ -1574,7 +1608,48 @@ DEFUN(no_bts_t_t_l_loopback,
return CMD_SUCCESS;
}
int bts_vty_init(struct gsm_bts *bts, const struct log_info *cat)
DEFUN(logging_fltr_l1_sapi, logging_fltr_l1_sapi_cmd, "HIDDEN", "HIDDEN")
{
int sapi = get_string_value(l1sap_common_sapi_names, argv[0]);
struct log_target *tgt = osmo_log_vty2tgt(vty);
uint16_t **sapi_mask;
OSMO_ASSERT(sapi >= 0);
if (!tgt)
return CMD_WARNING;
sapi_mask = (uint16_t **)&tgt->filter_data[LOG_FLT_L1_SAPI];
if (!*sapi_mask)
*sapi_mask = talloc(tgt, uint16_t);
OSMO_ASSERT(sapi <= 31);
**sapi_mask |= (1 << sapi);
tgt->filter_map |= (1 << LOG_FLT_L1_SAPI);
return CMD_SUCCESS;
}
DEFUN(no_logging_fltr_l1_sapi, no_logging_fltr_l1_sapi_cmd, "HIDDEN", "HIDDEN")
{
int sapi = get_string_value(l1sap_common_sapi_names, argv[0]);
struct log_target *tgt = osmo_log_vty2tgt(vty);
uint16_t *sapi_mask;
OSMO_ASSERT(sapi >= 0);
if (!tgt)
return CMD_WARNING;
if (!tgt->filter_data[LOG_FLT_L1_SAPI])
return CMD_SUCCESS;
OSMO_ASSERT(sapi <= 31);
sapi_mask = (uint16_t *)tgt->filter_data[LOG_FLT_L1_SAPI];
*sapi_mask &= ~(1 << sapi);
return CMD_SUCCESS;
}
int bts_vty_init(struct gsm_bts *bts)
{
cfg_trx_gsmtap_sapi_cmd.string = vty_cmd_string_from_valstr(bts, gsmtap_sapi_names,
"gsmtap-sapi (",
@@ -1590,14 +1665,31 @@ int bts_vty_init(struct gsm_bts *bts, const struct log_info *cat)
NO_STR "GSMTAP SAPI\n",
"\n", "", 0);
logging_fltr_l1_sapi_cmd.string = vty_cmd_string_from_valstr(bts, l1sap_common_sapi_names,
"logging filter l1-sapi (",
"|", ")", VTY_DO_LOWER);
logging_fltr_l1_sapi_cmd.doc = vty_cmd_string_from_valstr(bts, l1sap_common_sapi_names,
LOGGING_STR FILTER_STR "L1 SAPI\n",
"\n", "", 0);
no_logging_fltr_l1_sapi_cmd.string = vty_cmd_string_from_valstr(bts, l1sap_common_sapi_names,
"no logging filter l1-sapi (",
"|", ")", VTY_DO_LOWER);
no_logging_fltr_l1_sapi_cmd.doc = vty_cmd_string_from_valstr(bts, l1sap_common_sapi_names,
NO_STR LOGGING_STR FILTER_STR "L1 SAPI\n",
"\n", "", 0);
install_element_ve(&show_bts_cmd);
install_element_ve(&show_trx_cmd);
install_element_ve(&show_ts_cmd);
install_element_ve(&show_lchan_cmd);
install_element_ve(&show_lchan_summary_cmd);
install_element_ve(&logging_fltr_l1_sapi_cmd);
install_element_ve(&no_logging_fltr_l1_sapi_cmd);
logging_vty_add_cmds(cat);
logging_vty_add_cmds();
osmo_talloc_vty_add_cmds();
osmo_stats_vty_add_cmds();
install_node(&bts_node, config_write_bts);
install_element(CONFIG_NODE, &cfg_bts_cmd);
@@ -1607,6 +1699,7 @@ int bts_vty_init(struct gsm_bts *bts, const struct log_info *cat)
install_element(BTS_NODE, &cfg_bts_rtp_bind_ip_cmd);
install_element(BTS_NODE, &cfg_bts_rtp_jitbuf_cmd);
install_element(BTS_NODE, &cfg_bts_rtp_port_range_cmd);
install_element(BTS_NODE, &cfg_bts_rtp_ip_dscp_cmd);
install_element(BTS_NODE, &cfg_bts_band_cmd);
install_element(BTS_NODE, &cfg_description_cmd);
install_element(BTS_NODE, &cfg_no_description_cmd);
@@ -1621,6 +1714,9 @@ int bts_vty_init(struct gsm_bts *bts, const struct log_info *cat)
install_element(BTS_NODE, &cfg_bts_pcu_sock_cmd);
install_element(BTS_NODE, &cfg_bts_supp_meas_toa256_cmd);
install_element(BTS_NODE, &cfg_bts_no_supp_meas_toa256_cmd);
install_element(BTS_NODE, &cfg_bts_smscb_max_qlen_cmd);
install_element(BTS_NODE, &cfg_bts_smscb_tgt_qlen_cmd);
install_element(BTS_NODE, &cfg_bts_smscb_qhyst_cmd);
install_element(BTS_NODE, &cfg_trx_gsmtap_sapi_cmd);
install_element(BTS_NODE, &cfg_trx_no_gsmtap_sapi_cmd);
@@ -1639,6 +1735,7 @@ int bts_vty_init(struct gsm_bts *bts, const struct log_info *cat)
install_element(ENABLE_NODE, &bts_t_t_l_jitter_buf_cmd);
install_element(ENABLE_NODE, &bts_t_t_l_loopback_cmd);
install_element(ENABLE_NODE, &no_bts_t_t_l_loopback_cmd);
install_element(ENABLE_NODE, &test_send_failure_event_report_cmd);
install_element(CONFIG_NODE, &cfg_phy_cmd);
install_node(&phy_node, config_write_phy);

View File

@@ -317,7 +317,7 @@ static int calib_verify(struct lc15l1_hdl *fl1h, const struct calib_file_desc *d
fseek(st->fp, 0L, SEEK_END);
sz = ftell(st->fp);
/* rewind read poiner */
/* rewind read pointer */
fseek(st->fp, 0L, SEEK_SET);
/* read file */

View File

@@ -795,6 +795,45 @@ static uint8_t chan_nr_by_sapi(struct gsm_bts_trx_ts *ts,
return (cbits << 3) | u8Tn;
}
static const enum l1sap_common_sapi common_sapi_by_sapi_t[] = {
[GsmL1_Sapi_Idle] = L1SAP_COMMON_SAPI_IDLE,
[GsmL1_Sapi_Fcch] = L1SAP_COMMON_SAPI_FCCH,
[GsmL1_Sapi_Sch] = L1SAP_COMMON_SAPI_SCH,
[GsmL1_Sapi_Sacch] = L1SAP_COMMON_SAPI_SACCH,
[GsmL1_Sapi_Sdcch] = L1SAP_COMMON_SAPI_SDCCH,
[GsmL1_Sapi_Bcch] = L1SAP_COMMON_SAPI_BCCH,
[GsmL1_Sapi_Pch] = L1SAP_COMMON_SAPI_PCH,
[GsmL1_Sapi_Agch] = L1SAP_COMMON_SAPI_AGCH,
[GsmL1_Sapi_Cbch] = L1SAP_COMMON_SAPI_CBCH,
[GsmL1_Sapi_Rach] = L1SAP_COMMON_SAPI_RACH,
[GsmL1_Sapi_TchF] = L1SAP_COMMON_SAPI_TCH_F,
[GsmL1_Sapi_FacchF] = L1SAP_COMMON_SAPI_FACCH_F,
[GsmL1_Sapi_TchH] = L1SAP_COMMON_SAPI_TCH_H,
[GsmL1_Sapi_FacchH] = L1SAP_COMMON_SAPI_FACCH_H,
[GsmL1_Sapi_Nch] = L1SAP_COMMON_SAPI_NCH,
[GsmL1_Sapi_Pdtch] = L1SAP_COMMON_SAPI_PDTCH,
[GsmL1_Sapi_Pacch] = L1SAP_COMMON_SAPI_PACCH,
[GsmL1_Sapi_Pbcch] = L1SAP_COMMON_SAPI_PBCCH,
[GsmL1_Sapi_Pagch] = L1SAP_COMMON_SAPI_PAGCH,
[GsmL1_Sapi_Ppch] = L1SAP_COMMON_SAPI_PPCH,
[GsmL1_Sapi_Pnch] = L1SAP_COMMON_SAPI_PNCH,
[GsmL1_Sapi_Ptcch] = L1SAP_COMMON_SAPI_PTCCH,
[GsmL1_Sapi_Prach] = L1SAP_COMMON_SAPI_PRACH,
};
static enum l1sap_common_sapi get_common_sapi(GsmL1_Sapi_t sapi)
{
if (sapi >= GsmL1_Sapi_NUM)
return L1SAP_COMMON_SAPI_UNKNOWN;
return common_sapi_by_sapi_t[sapi];
}
static void set_log_ctx_sapi(GsmL1_Sapi_t sapi)
{
l1sap_log_ctx_sapi = get_common_sapi(sapi);
log_set_context(LOG_CTX_L1_SAPI, &l1sap_log_ctx_sapi);
}
static int handle_ph_readytosend_ind(struct lc15l1_hdl *fl1,
GsmL1_PhReadyToSendInd_t *rts_ind,
struct msgb *l1p_msg)
@@ -811,6 +850,8 @@ static int handle_ph_readytosend_ind(struct lc15l1_hdl *fl1,
uint8_t chan_nr, link_id;
uint32_t fn;
set_log_ctx_sapi(rts_ind->sapi);
/* check if primitive should be handled by common part */
chan_nr = chan_nr_by_sapi(&trx->ts[rts_ind->u8Tn], rts_ind->sapi,
rts_ind->subCh, rts_ind->u8Tn, rts_ind->u32Fn);
@@ -895,12 +936,8 @@ empty_frame:
goto tx;
}
static void dump_meas_res(int ll, GsmL1_MeasParam_t *m)
{
LOGPC(DL1C, ll, ", Meas: RSSI %-3.2f dBm, Qual %-3.2f dB, "
"BER %-3.2f, Timing %d\n", m->fRssi, m->fLinkQuality,
m->fBer, m->i16BurstTiming);
}
#define LOG_FMT_MEAS "Meas: RSSI %-3.2f dBm, Qual %-3.2f dB, BER %-3.2f, Timing %d"
#define LOG_PARAM_MEAS(meas_param) (meas_param)->fRssi, (meas_param)->fLinkQuality, (meas_param)->fBer, (meas_param)->i16BurstTiming
static int process_meas_res(struct gsm_bts_trx *trx, uint8_t chan_nr,
GsmL1_MeasParam_t *m, uint32_t fn)
@@ -933,6 +970,8 @@ static int handle_ph_data_ind(struct lc15l1_hdl *fl1, GsmL1_PhDataInd_t *data_in
int rc = 0;
int8_t rssi;
set_log_ctx_sapi(data_ind->sapi);
chan_nr = chan_nr_by_sapi(&trx->ts[data_ind->u8Tn], data_ind->sapi,
data_ind->subCh, data_ind->u8Tn, data_ind->u32Fn);
fn = data_ind->u32Fn;
@@ -949,10 +988,10 @@ static int handle_ph_data_ind(struct lc15l1_hdl *fl1, GsmL1_PhDataInd_t *data_in
process_meas_res(trx, chan_nr, &data_ind->measParam, fn);
DEBUGPGT(DL1P, &g_time, "Rx PH-DATA.ind %s (hL2 %08x): %s\n",
DEBUGPGT(DL1P, &g_time, "Rx PH-DATA.ind %s (hL2 %08x): %s, " LOG_FMT_MEAS "\n",
get_value_string(lc15bts_l1sapi_names, data_ind->sapi), (uint32_t)data_ind->hLayer2,
osmo_hexdump(data_ind->msgUnitParam.u8Buffer, data_ind->msgUnitParam.u8Size));
dump_meas_res(LOGL_DEBUG, &data_ind->measParam);
osmo_hexdump(data_ind->msgUnitParam.u8Buffer, data_ind->msgUnitParam.u8Size),
LOG_PARAM_MEAS(&data_ind->measParam));
/* check for TCH */
if (data_ind->sapi == GsmL1_Sapi_TchF
@@ -985,11 +1024,10 @@ static int handle_ph_data_ind(struct lc15l1_hdl *fl1, GsmL1_PhDataInd_t *data_in
l1sap->u.data.chan_nr = chan_nr;
l1sap->u.data.fn = fn;
l1sap->u.data.rssi = rssi;
if (!pcu_direct) {
l1sap->u.data.ber10k = data_ind->measParam.fBer * 10000;
l1sap->u.data.ta_offs_256bits = data_ind->measParam.i16BurstTiming*64;
l1sap->u.data.lqual_cb = data_ind->measParam.fLinkQuality * 10;
}
l1sap->u.data.ber10k = data_ind->measParam.fBer * 10000;
l1sap->u.data.ta_offs_256bits = data_ind->measParam.i16BurstTiming*64;
l1sap->u.data.lqual_cb = data_ind->measParam.fLinkQuality * 10;
return l1sap_up(trx, l1sap);
}
@@ -997,19 +1035,14 @@ static int handle_ph_ra_ind(struct lc15l1_hdl *fl1, GsmL1_PhRaInd_t *ra_ind,
struct msgb *l1p_msg)
{
struct gsm_bts_trx *trx = lc15l1_hdl_trx(fl1);
struct gsm_bts *bts = trx->bts;
struct gsm_lchan *lchan;
struct osmo_phsap_prim *l1sap;
int rc;
struct ph_rach_ind_param rach_ind_param;
/* FIXME: this should be deprecated/obsoleted as it bypasses rach.busy counting */
if (ra_ind->measParam.fLinkQuality < bts->min_qual_rach) {
msgb_free(l1p_msg);
return 0;
}
dump_meas_res(LOGL_DEBUG, &ra_ind->measParam);
set_log_ctx_sapi(ra_ind->sapi);
LOGPFN(DL1C, LOGL_DEBUG, ra_ind->u32Fn, "Rx PH-RA.ind, " LOG_FMT_MEAS "\n",
LOG_PARAM_MEAS(&ra_ind->measParam));
if ((ra_ind->msgUnitParam.u8Size != 1) &&
(ra_ind->msgUnitParam.u8Size != 2)) {
@@ -1029,13 +1062,14 @@ static int handle_ph_ra_ind(struct lc15l1_hdl *fl1, GsmL1_PhRaInd_t *ra_ind,
.rssi = (int8_t) ra_ind->measParam.fRssi,
.ber10k = (unsigned int) (ra_ind->measParam.fBer * 10000.0),
.acc_delay_256bits = ra_ind->measParam.i16BurstTiming * 64,
.lqual_cb = (int16_t) ra_ind->measParam.fLinkQuality * 10, /* centiBels */
};
lchan = l1if_hLayer_to_lchan(trx, (uint32_t)ra_ind->hLayer2);
if (!lchan || lchan->ts->pchan == GSM_PCHAN_CCCH ||
lchan->ts->pchan == GSM_PCHAN_CCCH_SDCCH4 ||
lchan->ts->pchan == GSM_PCHAN_CCCH_SDCCH4_CBCH)
rach_ind_param.chan_nr = 0x88;
rach_ind_param.chan_nr = RSL_CHAN_RACH;
else
rach_ind_param.chan_nr = gsm_lchan2chan_nr(lchan);
@@ -1229,8 +1263,10 @@ static int activate_rf_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp,
LOGP(DL1C, LOGL_FATAL, "RF-ACT.conf with status %s\n",
get_value_string(lc15bts_l1status_names, status));
bts_shutdown(trx->bts, "RF-ACT failure");
} else
bts_update_status(BTS_STATUS_RF_ACTIVE, 1);
} else {
if(trx->bts->lc15.led_ctrl_mode == LC15_LED_CONTROL_BTS)
bts_update_status(BTS_STATUS_RF_ACTIVE, 1);
}
/* signal availability */
oml_mo_state_chg(&trx->mo, NM_OPSTATE_DISABLED, NM_AVSTATE_OK);
@@ -1241,7 +1277,8 @@ static int activate_rf_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp,
for (i = 0; i < ARRAY_SIZE(trx->ts); i++)
oml_mo_state_chg(&trx->ts[i].mo, NM_OPSTATE_DISABLED, NM_AVSTATE_DEPENDENCY);
} else {
bts_update_status(BTS_STATUS_RF_ACTIVE, 0);
if(trx->bts->lc15.led_ctrl_mode == LC15_LED_CONTROL_BTS)
bts_update_status(BTS_STATUS_RF_ACTIVE, 0);
oml_mo_state_chg(&trx->mo, NM_OPSTATE_DISABLED, NM_AVSTATE_OFF_LINE);
oml_mo_state_chg(&trx->bb_transc.mo, NM_OPSTATE_DISABLED, NM_AVSTATE_OFF_LINE);
}
@@ -1256,17 +1293,27 @@ int l1if_activate_rf(struct lc15l1_hdl *hdl, int on)
{
struct msgb *msg = sysp_msgb_alloc();
Litecell15_Prim_t *sysp = msgb_sysprim(msg);
struct phy_instance *pinst = hdl->phy_inst;
if (on) {
sysp->id = Litecell15_PrimId_ActivateRfReq;
sysp->u.activateRfReq.msgq.u8UseTchMsgq = 0;
sysp->u.activateRfReq.msgq.u8UsePdtchMsgq = pcu_direct;
sysp->u.activateRfReq.u8UnusedTsMode = 0;
sysp->u.activateRfReq.u8UnusedTsMode = pinst->u.lc15.pedestal_mode;
sysp->u.activateRfReq.u8McCorrMode = 0;
/* diversity mode: 0: SISO-A, 1: SISO-B, 2: MRC */
sysp->u.activateRfReq.u8DiversityMode = pinst->u.lc15.diversity_mode;
/* maximum cell size in quarter-bits, 90 == 12.456 km */
sysp->u.activateRfReq.u8MaxCellSize = 90;
sysp->u.activateRfReq.u8MaxCellSize = pinst->u.lc15.max_cell_size;
/* auto tx power adjustment mode 0:none, 1: automatic*/
sysp->u.activateRfReq.autoPowerAdjust.u8EnAutoPowerAdjust = pinst->u.lc15.tx_pwr_adj_mode;
/* PSK modulation scheme maximum power level */
sysp->u.activateRfReq.autoPowerAdjust.u8PowerReduction8Psk = pinst->u.lc15.tx_pwr_red_8psk;
} else {
sysp->id = Litecell15_PrimId_DeactivateRfReq;
}
@@ -1319,7 +1366,8 @@ static int mute_rf_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp,
LOGP(DL1C, LOGL_INFO, "Rx RF-MUTE.conf with status=%s\n",
get_value_string(lc15bts_l1status_names, status));
bts_update_status(BTS_STATUS_RF_MUTE, fl1h->last_rf_mute[0]);
if(trx->bts->lc15.led_ctrl_mode == LC15_LED_CONTROL_BTS)
bts_update_status(BTS_STATUS_RF_MUTE, fl1h->last_rf_mute[0]);
oml_mo_rf_lock_chg(&trx->mo, fl1h->last_rf_mute, 1);
osmo_static_assert(
@@ -1555,6 +1603,53 @@ int l1if_close(struct lc15l1_hdl *fl1h)
return 0;
}
static void dsp_alive_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp, void *data)
{
Litecell15_Prim_t *sysp = msgb_sysprim(resp);
Litecell15_IsAliveCnf_t *sac = &sysp->u.IsAliveCnf;
struct lc15l1_hdl *fl1h = trx_lc15l1_hdl(trx);
fl1h->hw_alive.dsp_alive_cnt++;
LOGP(DL1C, LOGL_NOTICE, "Rx SYS prim %s, status=%d (%d)\n",
get_value_string(lc15bts_sysprim_names, sysp->id), sac->status, trx->nr);
msgb_free(resp);
}
static int dsp_alive_timer_cb(void *data)
{
struct lc15l1_hdl *fl1h = data;
struct gsm_bts_trx *trx = fl1h->phy_inst->trx;
struct msgb *msg = sysp_msgb_alloc();
int rc;
Litecell15_Prim_t *sys_prim = msgb_sysprim(msg);
sys_prim->id = Litecell15_PrimId_IsAliveReq;
if (fl1h->hw_alive.dsp_alive_cnt == 0) {
LOGP(DL1C, LOGL_ERROR, "Timeout waiting for SYS prim %s primitive (%d)\n",
get_value_string(lc15bts_sysprim_names, sys_prim->id + 1), trx->nr);
exit(23);
}
LOGP(DL1C, LOGL_NOTICE, "Tx SYS prim %s (%d)\n",
get_value_string(lc15bts_sysprim_names, sys_prim->id), trx->nr);
rc = l1if_req_compl(fl1h, msg, dsp_alive_compl_cb, NULL);
if (rc < 0) {
LOGP(DL1C, LOGL_FATAL, "Failed to send %s primitive\n", get_value_string(lc15bts_sysprim_names, sys_prim->id));
return -EIO;
}
/* restart timer */
fl1h->hw_alive.dsp_alive_cnt = 0;
osmo_timer_schedule(&fl1h->hw_alive.dsp_alive_timer, fl1h->hw_alive.dsp_alive_period, 0);
return 0;
}
int bts_model_phy_link_open(struct phy_link *plink)
{
struct phy_instance *pinst = phy_instance_by_num(plink, 0);
@@ -1574,6 +1669,24 @@ int bts_model_phy_link_open(struct phy_link *plink)
return -EIO;
}
/* Set default PHY parameters */
if (!pinst->u.lc15.max_cell_size)
pinst->u.lc15.max_cell_size = LC15_BTS_MAX_CELL_SIZE_DEFAULT;
if (!pinst->u.lc15.diversity_mode)
pinst->u.lc15.diversity_mode = LC15_BTS_DIVERSITY_MODE_DEFAULT;
if (!pinst->u.lc15.pedestal_mode)
pinst->u.lc15.pedestal_mode = LC15_BTS_PEDESTAL_MODE_DEFAULT;
if (!pinst->u.lc15.dsp_alive_period)
pinst->u.lc15.dsp_alive_period = LC15_BTS_DSP_ALIVE_TMR_DEFAULT;
if (!pinst->u.lc15.tx_pwr_adj_mode)
pinst->u.lc15.tx_pwr_adj_mode = LC15_BTS_TX_PWR_ADJ_DEFAULT;
if (!pinst->u.lc15.tx_pwr_red_8psk)
pinst->u.lc15.tx_pwr_red_8psk = LC15_BTS_TX_RED_PWR_8PSK_DEFAULT;
struct lc15l1_hdl *fl1h = pinst->u.lc15.hdl;
fl1h->dsp_trace_f = dsp_trace;
@@ -1582,5 +1695,24 @@ int bts_model_phy_link_open(struct phy_link *plink)
phy_link_state_set(plink, PHY_LINK_CONNECTED);
/* Send first IS_ALIVE primitive */
struct msgb *msg = sysp_msgb_alloc();
int rc;
Litecell15_Prim_t *sys_prim = msgb_sysprim(msg);
sys_prim->id = Litecell15_PrimId_IsAliveReq;
rc = l1if_req_compl(fl1h, msg, dsp_alive_compl_cb, NULL);
if (rc < 0) {
LOGP(DL1C, LOGL_FATAL, "Failed to send %s primitive\n", get_value_string(lc15bts_sysprim_names, sys_prim->id));
return -EIO;
}
/* initialize DSP heart beat alive timer */
fl1h->hw_alive.dsp_alive_timer.cb = dsp_alive_timer_cb;
fl1h->hw_alive.dsp_alive_timer.data = fl1h;
fl1h->hw_alive.dsp_alive_cnt = 0;
fl1h->hw_alive.dsp_alive_period = pinst->u.lc15.dsp_alive_period;
osmo_timer_schedule(&fl1h->hw_alive.dsp_alive_timer, fl1h->hw_alive.dsp_alive_period, 0);
return 0;
}

View File

@@ -62,6 +62,12 @@ struct lc15l1_hdl {
struct calib_send_state st;
uint8_t last_rf_mute[8];
struct {
struct osmo_timer_list dsp_alive_timer;
unsigned int dsp_alive_cnt;
uint8_t dsp_alive_period;
} hw_alive;
};
#define msgb_l1prim(msg) ((GsmL1_Prim_t *)(msg)->l1h)

View File

@@ -121,6 +121,8 @@ enum l1prim_type lc15bts_get_sysprim_type(Litecell15_PrimId_t id)
case Litecell15_PrimId_MuteRfCnf: return L1P_T_CONF;
case Litecell15_PrimId_SetRxAttenReq: return L1P_T_REQ;
case Litecell15_PrimId_SetRxAttenCnf: return L1P_T_CONF;
case Litecell15_PrimId_IsAliveReq: return L1P_T_REQ;
case Litecell15_PrimId_IsAliveCnf: return L1P_T_CONF;
default: return L1P_T_INVALID;
}
}
@@ -142,6 +144,8 @@ const struct value_string lc15bts_sysprim_names[Litecell15_PrimId_NUM+1] = {
{ Litecell15_PrimId_MuteRfCnf, "MUTE-RF.cnf" },
{ Litecell15_PrimId_SetRxAttenReq, "SET-RX-ATTEN.req" },
{ Litecell15_PrimId_SetRxAttenCnf, "SET-RX-ATTEN-CNF.cnf" },
{ Litecell15_PrimId_IsAliveReq, "IS-ALIVE.req" },
{ Litecell15_PrimId_IsAliveCnf, "IS-ALIVE-CNF.cnf" },
{ 0, NULL }
};
@@ -155,6 +159,7 @@ Litecell15_PrimId_t lc15bts_get_sysprim_conf(Litecell15_PrimId_t id)
case Litecell15_PrimId_SetCalibTblReq: return Litecell15_PrimId_SetCalibTblCnf;
case Litecell15_PrimId_MuteRfReq: return Litecell15_PrimId_MuteRfCnf;
case Litecell15_PrimId_SetRxAttenReq: return Litecell15_PrimId_SetRxAttenCnf;
case Litecell15_PrimId_IsAliveReq: return Litecell15_PrimId_IsAliveCnf;
default: return -1; // Weak
}
}

View File

@@ -22,6 +22,27 @@ enum l1prim_type {
L1P_T_IND,
};
enum lc15_diversity_mode{
LC15_DIVERSITY_SISO_A = 0,
LC15_DIVERSITY_SISO_B,
LC15_DIVERSITY_MRC,
};
enum lc15_pedestal_mode{
LC15_PEDESTAL_OFF = 0,
LC15_PEDESTAL_ON,
};
enum lc15_led_control_mode{
LC15_LED_CONTROL_BTS = 0,
LC15_LED_CONTROL_EXT,
};
enum lc15_auto_pwr_adjust_mode{
LC15_TX_PWR_ADJ_NONE = 0,
LC15_TX_PWR_ADJ_AUTO,
};
enum l1prim_type lc15bts_get_l1prim_type(GsmL1_PrimId_t id);
const struct value_string lc15bts_l1prim_names[GsmL1_PrimId_NUM+1];
GsmL1_PrimId_t lc15bts_get_l1prim_conf(GsmL1_PrimId_t id);
@@ -61,4 +82,13 @@ enum pdch_cs {
const uint8_t pdch_msu_size[_NUM_PDCH_CS];
/* LC15 default parameters */
#define LC15_BTS_MAX_CELL_SIZE_DEFAULT 166 /* 166 qbits is default value */
#define LC15_BTS_DIVERSITY_MODE_DEFAULT 0 /* SISO-A is default mode */
#define LC15_BTS_PEDESTAL_MODE_DEFAULT 0 /* Unused TS is off by default */
#define LC15_BTS_LED_CTRL_MODE_DEFAULT 0 /* LED is controlled by BTS by default */
#define LC15_BTS_DSP_ALIVE_TMR_DEFAULT 5 /* Default DSP alive timer is 5 seconds */
#define LC15_BTS_TX_PWR_ADJ_DEFAULT 0 /* Default Tx power auto adjustment is none */
#define LC15_BTS_TX_RED_PWR_8PSK_DEFAULT 0 /* Default 8-PSK maximum power level is 0 dB */
#endif /* LC15BTS_H */

View File

@@ -65,6 +65,31 @@ extern int lchan_activate(struct gsm_lchan *lchan);
static struct gsm_bts *vty_bts;
static const struct value_string lc15_diversity_mode_strs[] = {
{ LC15_DIVERSITY_SISO_A, "siso-a" },
{ LC15_DIVERSITY_SISO_B, "siso-b" },
{ LC15_DIVERSITY_MRC, "mrc" },
{ 0, NULL }
};
static const struct value_string lc15_pedestal_mode_strs[] = {
{ LC15_PEDESTAL_OFF, "off" },
{ LC15_PEDESTAL_ON, "on" },
{ 0, NULL }
};
static const struct value_string lc15_led_mode_strs[] = {
{ LC15_LED_CONTROL_BTS, "bts" },
{ LC15_LED_CONTROL_EXT, "external" },
{ 0, NULL }
};
static const struct value_string lc15_auto_adj_pwr_strs[] = {
{ LC15_TX_PWR_ADJ_NONE, "none" },
{ LC15_TX_PWR_ADJ_AUTO, "auto" },
{ 0, NULL }
};
/* configuration */
DEFUN(cfg_phy_cal_path, cfg_phy_cal_path_cmd,
@@ -88,7 +113,7 @@ DEFUN(cfg_phy_dsp_trace_f, cfg_phy_dsp_trace_f_cmd,
unsigned int flag;
flag = get_string_value(lc15bts_tracef_names, argv[1]);
pinst->u.lc15.dsp_trace_f |= ~flag;
pinst->u.lc15.dsp_trace_f |= flag;
return CMD_SUCCESS;
}
@@ -321,8 +346,130 @@ DEFUN(cfg_trx_nominal_power, cfg_trx_nominal_power_cmd,
return CMD_SUCCESS;
}
DEFUN(cfg_phy_max_cell_size, cfg_phy_max_cell_size_cmd,
"max-cell-size <0-166>",
"Set the maximum cell size in qbits\n")
{
struct phy_instance *pinst = vty->index;
int cell_size = (uint8_t)atoi(argv[0]);
if (( cell_size > 166 ) || ( cell_size < 0 )) {
vty_out(vty, "Max cell size must be between 0 and 166 qbits (%d) %s",
cell_size, VTY_NEWLINE);
return CMD_WARNING;
}
pinst->u.lc15.max_cell_size = (uint8_t)cell_size;
return CMD_SUCCESS;
}
DEFUN(cfg_phy_diversity_mode, cfg_phy_diversity_mode_cmd,
"diversity-mode (siso-a|siso-b|mrc)",
"Set reception diversity mode \n"
"Reception diversity mode can be (siso-a, siso-b, mrc)\n")
{
struct phy_instance *pinst = vty->index;
int val = get_string_value(lc15_diversity_mode_strs, argv[0]);
if((val < LC15_DIVERSITY_SISO_A) || (val > LC15_DIVERSITY_MRC)) {
vty_out(vty, "Invalid reception diversity mode %d%s", val, VTY_NEWLINE);
return CMD_WARNING;
}
pinst->u.lc15.diversity_mode = (uint8_t)val;
return CMD_SUCCESS;
}
DEFUN(cfg_phy_pedestal_mode, cfg_phy_pedestal_mode_cmd,
"pedestal-mode (on|off)",
"Set unused time-slot transmission in pedestal mode\n"
"Transmission pedestal mode can be (off, on)\n")
{
struct phy_instance *pinst = vty->index;
int val = get_string_value(lc15_pedestal_mode_strs, argv[0]);
if((val < LC15_PEDESTAL_OFF) || (val > LC15_PEDESTAL_ON)) {
vty_out(vty, "Invalid unused time-slot transmission mode %d%s", val, VTY_NEWLINE);
return CMD_WARNING;
}
pinst->u.lc15.pedestal_mode = (uint8_t)val;
return CMD_SUCCESS;
}
DEFUN(cfg_bts_led_mode, cfg_bts_led_mode_cmd,
"led-control-mode (bts|external)",
"Set LED controlled by BTS or external software\n"
"LED can be controlled by (bts, external)\n")
{
struct gsm_bts *bts = vty->index;
int val = get_string_value(lc15_led_mode_strs, argv[0]);
if((val < LC15_LED_CONTROL_BTS) || (val > LC15_LED_CONTROL_EXT)) {
vty_out(vty, "Invalid LED control mode %d%s", val, VTY_NEWLINE);
return CMD_WARNING;
}
bts->lc15.led_ctrl_mode = (uint8_t)val;
return CMD_SUCCESS;
}
DEFUN(cfg_phy_dsp_alive_timer, cfg_phy_dsp_alive_timer_cmd,
"dsp-alive-period <0-60>",
"Set DSP alive timer period in second\n")
{
struct phy_instance *pinst = vty->index;
uint8_t period = (uint8_t)atoi(argv[0]);
if (( period > 60 ) || ( period < 0 )) {
vty_out(vty, "DSP heart beat alive timer period must be between 0 and 60 seconds (%d) %s",
period, VTY_NEWLINE);
return CMD_WARNING;
}
pinst->u.lc15.dsp_alive_period = period;
return CMD_SUCCESS;
}
DEFUN(cfg_phy_auto_tx_pwr_adj, cfg_phy_auto_tx_pwr_adj_cmd,
"pwr-adj-mode (none|auto)",
"Set output power adjustment mode\n")
{
struct phy_instance *pinst = vty->index;
int val = get_string_value(lc15_auto_adj_pwr_strs, argv[0]);
if((val < LC15_TX_PWR_ADJ_NONE) || (val > LC15_TX_PWR_ADJ_AUTO)) {
vty_out(vty, "Invalid output power adjustment mode %d%s", val, VTY_NEWLINE);
return CMD_WARNING;
}
pinst->u.lc15.tx_pwr_adj_mode = (uint8_t)val;
return CMD_SUCCESS;
}
DEFUN(cfg_phy_tx_red_pwr_8psk, cfg_phy_tx_red_pwr_8psk_cmd,
"tx-red-pwr-8psk <0-40>",
"Set reduction output power for 8-PSK scheme in dB unit\n")
{
struct phy_instance *pinst = vty->index;
int val = atoi(argv[0]);
if ((val > 40) || (val < 0)) {
vty_out(vty, "Reduction Tx power level must be between 0 and 40 dB (%d) %s",
val, VTY_NEWLINE);
return CMD_WARNING;
}
pinst->u.lc15.tx_pwr_red_8psk = (uint8_t)val;
return CMD_SUCCESS;
}
void bts_model_config_write_bts(struct vty *vty, struct gsm_bts *bts)
{
vty_out(vty, " led-control-mode %s%s",
get_value_string(lc15_led_mode_strs, bts->lc15.led_ctrl_mode), VTY_NEWLINE);
}
void bts_model_config_write_trx(struct vty *vty, struct gsm_bts_trx *trx)
@@ -347,8 +494,27 @@ void bts_model_config_write_phy_inst(struct vty *vty, struct phy_instance *pinst
}
}
if (pinst->u.lc15.calib_path)
vty_out(vty, " trx-calibration-path %s%s",
vty_out(vty, " trx-calibration-path %s%s",
pinst->u.lc15.calib_path, VTY_NEWLINE);
vty_out(vty, " max-cell-size %d%s",
pinst->u.lc15.max_cell_size, VTY_NEWLINE);
vty_out(vty, " diversity-mode %s%s",
get_value_string(lc15_diversity_mode_strs, pinst->u.lc15.diversity_mode), VTY_NEWLINE);
vty_out(vty, " pedestal-mode %s%s",
get_value_string(lc15_pedestal_mode_strs, pinst->u.lc15.pedestal_mode) , VTY_NEWLINE);
vty_out(vty, " dsp-alive-period %d%s",
pinst->u.lc15.dsp_alive_period, VTY_NEWLINE);
vty_out(vty, " pwr-adj-mode %s%s",
get_value_string(lc15_auto_adj_pwr_strs, pinst->u.lc15.tx_pwr_adj_mode), VTY_NEWLINE);
vty_out(vty, " tx-red-pwr-8psk %d%s",
pinst->u.lc15.tx_pwr_red_8psk, VTY_NEWLINE);
}
int bts_model_vty_init(struct gsm_bts *bts)
@@ -401,12 +567,20 @@ int bts_model_vty_init(struct gsm_bts *bts)
install_element(BTS_NODE, &cfg_bts_auto_band_cmd);
install_element(BTS_NODE, &cfg_bts_no_auto_band_cmd);
install_element(BTS_NODE, &cfg_bts_led_mode_cmd);
install_element(TRX_NODE, &cfg_trx_nominal_power_cmd);
install_element(PHY_INST_NODE, &cfg_phy_dsp_trace_f_cmd);
install_element(PHY_INST_NODE, &cfg_phy_no_dsp_trace_f_cmd);
install_element(PHY_INST_NODE, &cfg_phy_cal_path_cmd);
install_element(PHY_INST_NODE, &cfg_phy_diversity_mode_cmd);
install_element(PHY_INST_NODE, &cfg_phy_pedestal_mode_cmd);
install_element(PHY_INST_NODE, &cfg_phy_max_cell_size_cmd);
install_element(PHY_INST_NODE, &cfg_phy_dsp_alive_timer_cmd);
install_element(PHY_INST_NODE, &cfg_phy_auto_tx_pwr_adj_cmd);
install_element(PHY_INST_NODE, &cfg_phy_tx_red_pwr_8psk_cmd);
return 0;
}

View File

@@ -2,7 +2,7 @@
/* Copyright (C) 2015 by Yves Godin <support@nuranwireless.com>
* Copyright (C) 2016 by Harald Welte <laforge@gnumonks.org>
*
*
* Based on sysmoBTS:
* (C) 2011-2013 by Harald Welte <laforge@gnumonks.org>
*
@@ -51,6 +51,25 @@
#include <osmo-bts/pcu_if.h>
#include <osmo-bts/l1sap.h>
static int write_status_file(char *status_file, char *status_str)
{
FILE *outf;
char tmp[PATH_MAX+1];
snprintf(tmp, sizeof(tmp)-1, "/var/run/osmo-bts/%s", status_file);
tmp[PATH_MAX-1] = '\0';
outf = fopen(tmp, "w");
if (!outf)
return -1;
fprintf(outf, "%s\n", status_str);
fclose(outf);
return 0;
}
/*NTQD: Change how rx_nr is handle in multi-trx*/
#define LC15BTS_RF_LOCK_PATH "/var/lock/bts_rf_lock"
@@ -71,7 +90,8 @@ int bts_model_init(struct gsm_bts *bts)
bts->variant = BTS_OSMO_LITECELL15;
bts->support.ciphers = CIPHER_A5(1) | CIPHER_A5(2) | CIPHER_A5(3);
/* specific default values for LC15 platform */
bts->lc15.led_ctrl_mode = LC15_BTS_LED_CTRL_MODE_DEFAULT;
rc = oml_router_init(bts, OML_ROUTER_PATH, &accept_fd, &read_fd);
if (rc < 0) {
fprintf(stderr, "Error creating the OML router: %s rc=%d\n",
@@ -93,6 +113,7 @@ int bts_model_init(struct gsm_bts *bts)
gsm_bts_set_feature(bts, BTS_FEAT_SPEECH_F_EFR);
gsm_bts_set_feature(bts, BTS_FEAT_SPEECH_F_AMR);
gsm_bts_set_feature(bts, BTS_FEAT_SPEECH_H_AMR);
gsm_bts_set_feature(bts, BTS_FEAT_MS_PWR_CTRL_DSP);
bts_model_vty_init(bts);
@@ -116,6 +137,9 @@ void bts_model_phy_instance_set_defaults(struct phy_instance *pinst)
int bts_model_oml_estab(struct gsm_bts *bts)
{
/* update status file */
write_status_file("state", "");
return 0;
}
@@ -123,24 +147,16 @@ void bts_update_status(enum bts_global_status which, int on)
{
static uint64_t states = 0;
uint64_t old_states = states;
int led_rf_active_on;
if (on)
states |= (1ULL << which);
else
states &= ~(1ULL << which);
led_rf_active_on =
(states & (1ULL << BTS_STATUS_RF_ACTIVE)) &&
!(states & (1ULL << BTS_STATUS_RF_MUTE));
LOGP(DL1C, LOGL_INFO,
"Set global status #%d to %d (%04llx -> %04llx), LEDs: ACT %d\n",
"Set global status #%d to %d (%04llx -> %04llx)",
which, on,
(long long)old_states, (long long)states,
led_rf_active_on);
lc15bts_led_set(led_rf_active_on ? LED_GREEN : LED_OFF);
(long long)old_states, (long long)states);
}
void bts_model_print_help()
@@ -197,11 +213,17 @@ int bts_model_handle_options(int argc, char **argv)
void bts_model_abis_close(struct gsm_bts *bts)
{
/* write to status file */
write_status_file("state", "ABIS DOWN");
/* for now, we simply terminate the program and re-spawn */
bts_shutdown(bts, "Abis close");
}
int main(int argc, char **argv)
{
/* create status file with initial state */
write_status_file("state", "ABIS DOWN");
return bts_main(argc, argv);
}

View File

@@ -301,7 +301,7 @@ int main(int argc, char **argv)
exit(2);
lc15bts_mgr_vty_init();
logging_vty_add_cmds(&mgr_log_info);
logging_vty_add_cmds();
rc = lc15bts_mgr_parse_config(&manager);
if (rc < 0) {
LOGP(DFIND, LOGL_FATAL, "Cannot parse config file\n");

View File

@@ -584,39 +584,39 @@ DEFUN(show_mgr, show_mgr_cmd, "show manager",
lc15bts_mgr_sensor_get_state(s_mgr->state.state), VTY_NEWLINE);
vty_out(vty, "Current Temperatures%s", VTY_NEWLINE);
lc15bts_temp_get(LC15BTS_TEMP_SUPPLY, &temp);
vty_out(vty, " Main Supply : %4.2f Celcius%s",
vty_out(vty, " Main Supply : %4.2f Celsius%s",
temp/ 1000.0f,
VTY_NEWLINE);
lc15bts_temp_get(LC15BTS_TEMP_SOC, &temp);
vty_out(vty, " SoC : %4.2f Celcius%s",
vty_out(vty, " SoC : %4.2f Celsius%s",
temp / 1000.0f,
VTY_NEWLINE);
lc15bts_temp_get(LC15BTS_TEMP_FPGA, &temp);
vty_out(vty, " FPGA : %4.2f Celcius%s",
vty_out(vty, " FPGA : %4.2f Celsius%s",
temp / 1000.0f,
VTY_NEWLINE);
lc15bts_temp_get(LC15BTS_TEMP_RMSDET, &temp);
vty_out(vty, " RMSDet : %4.2f Celcius%s",
vty_out(vty, " RMSDet : %4.2f Celsius%s",
temp / 1000.0f,
VTY_NEWLINE);
lc15bts_temp_get(LC15BTS_TEMP_OCXO, &temp);
vty_out(vty, " OCXO : %4.2f Celcius%s",
vty_out(vty, " OCXO : %4.2f Celsius%s",
temp / 1000.0f,
VTY_NEWLINE);
lc15bts_temp_get(LC15BTS_TEMP_TX0, &temp);
vty_out(vty, " TX 0 : %4.2f Celcius%s",
vty_out(vty, " TX 0 : %4.2f Celsius%s",
temp / 1000.0f,
VTY_NEWLINE);
lc15bts_temp_get(LC15BTS_TEMP_TX1, &temp);
vty_out(vty, " TX 1 : %4.2f Celcius%s",
vty_out(vty, " TX 1 : %4.2f Celsius%s",
temp / 1000.0f,
VTY_NEWLINE);
lc15bts_temp_get(LC15BTS_TEMP_PA0, &temp);
vty_out(vty, " Power Amp #0: %4.2f Celcius%s",
vty_out(vty, " Power Amp #0: %4.2f Celsius%s",
temp / 1000.0f,
VTY_NEWLINE);
lc15bts_temp_get(LC15BTS_TEMP_PA1, &temp);
vty_out(vty, " Power Amp #1: %4.2f Celcius%s",
vty_out(vty, " Power Amp #1: %4.2f Celsius%s",
temp / 1000.0f,
VTY_NEWLINE);

View File

@@ -363,7 +363,7 @@ int lc15bts_firmware_reload(enum lc15bts_firmware_type type)
case LC15BTS_FW_DSP1:
fd = open(fw_sysfs[type], O_WRONLY);
if (fd < 0) {
LOGP(DFW, LOGL_ERROR, "unable ot open firmware device %s: %s\n",
LOGP(DFW, LOGL_ERROR, "unable to open firmware device %s: %s\n",
fw_sysfs[type], strerror(errno));
close(fd);
return fd;

View File

@@ -3,7 +3,6 @@
#include <osmocom/core/utils.h>
#define FACTORY_ROM_PATH "/mnt/rom/factory"
#define USER_ROM_PATH "/mnt/storage/var/run/lc15bts-mgr"
enum lc15bts_par {

View File

@@ -161,7 +161,7 @@ int lc15bts_swd_init(struct lc15bts_mgr_instance *mgr, int swd_num_events)
the value must be in the range of [0,'swd_num_events'[ (see lc15bts_swd_init).
For example, if 'swd_num_events' was 64, 'swd_event' events are numbered 0 to 63.
WARNING: if this function can be used from multiple threads at the same time,
it must be protected with a kind of mutex to avoid loosing event notification.
it must be protected with a kind of mutex to avoid losing event notification.
*/
int lc15bts_swd_event(struct lc15bts_mgr_instance *mgr, enum mgr_swd_events swd_event)
{

View File

@@ -1724,7 +1724,7 @@ int bts_model_apply_oml(struct gsm_bts *bts, struct msgb *msg,
power_ramp_start(trx, get_p_target_mdBm(trx, 0), 0);
}
/* FIXME: we actaully need to send a ACK or NACK for the OML message */
/* FIXME: we actually need to send a ACK or NACK for the OML message */
return oml_fom_ack_nack(msg, 0);
}

View File

@@ -373,7 +373,7 @@ int l1if_tch_rx(struct gsm_bts_trx *trx, uint8_t chan_nr, struct msgb *l1p_msg)
rmsg = msgb_alloc_headroom(256, 128, "L1P-to-RTP");
return add_l1sap_header(trx, rmsg, lchan, chan_nr, data_ind->u32Fn,
data_ind->measParam.fBer * 10000,
data_ind->measParam.fLinkQuality * 10);
data_ind->measParam.fLinkQuality * 10, 0, 0, 0);
}
payload_type = data_ind->msgUnitParam.u8Buffer[0];
@@ -463,7 +463,7 @@ int l1if_tch_rx(struct gsm_bts_trx *trx, uint8_t chan_nr, struct msgb *l1p_msg)
if (rmsg)
return add_l1sap_header(trx, rmsg, lchan, chan_nr, data_ind->u32Fn,
data_ind->measParam.fBer * 10000,
data_ind->measParam.fLinkQuality * 10);
data_ind->measParam.fLinkQuality * 10, 0, 0, 0);
return 0;

View File

@@ -34,6 +34,7 @@
#include <osmo-bts/gsm_data.h>
#include <osmo-bts/logging.h>
#include <osmo-bts/bts.h>
#include <nrw/oc2g/oc2g.h>
#include <nrw/oc2g/gsml1const.h>
@@ -132,17 +133,9 @@ static int calib_file_open(struct oc2gl1_hdl *fl1h,
st->fp = fopen(fname, "rb");
if (!st->fp) {
LOGP(DL1C, LOGL_NOTICE, "Failed to open '%s' for calibration data.\n", fname);
/* TODO (oramadan): Fix OML alarms
if( fl1h->phy_inst->trx ){
fl1h->phy_inst->trx->mo.obj_inst.trx_nr = fl1h->phy_inst->trx->nr;
alarm_sig_data.mo = &fl1h->phy_inst->trx->mo;
alarm_sig_data.add_text = (char*)&fname[0];
osmo_signal_dispatch(SS_NM, S_NM_OML_BTS_FAIL_OPEN_CALIB_ALARM, &alarm_sig_data);
}
*/
LOGP(DL1C, LOGL_FATAL, "Failed to open '%s' for calibration data.\n", fname);
oml_tx_failure_event_rep(&fl1h->phy_inst->trx->mo, NM_SEVER_MAJOR, OSMO_EVT_WARN_SW_WARN,
"Failed to open '%s' for calibration data", fname);
return -1;
}
return 0;
@@ -227,18 +220,9 @@ static int calib_file_send(struct oc2gl1_hdl *fl1h,
rc = calib_verify(fl1h, desc);
if (rc < 0) {
LOGP(DL1C, LOGL_NOTICE,"Verify L1 calibration table %s -> failed (%d)\n", desc->fname, rc);
/* TODO (oramadan): Fix OML alarms
if (fl1h->phy_inst->trx) {
fl1h->phy_inst->trx->mo.obj_inst.trx_nr = fl1h->phy_inst->trx->nr;
alarm_sig_data.mo = &fl1h->phy_inst->trx->mo;
alarm_sig_data.add_text = (char*)&desc->fname[0];
memcpy(alarm_sig_data.spare, &rc, sizeof(int));
osmo_signal_dispatch(SS_NM, S_NM_OML_BTS_FAIL_VERIFY_CALIB_ALARM, &alarm_sig_data);
}
*/
LOGP(DL1C, LOGL_FATAL, "Verify L1 calibration table %s -> failed (%d)\n", desc->fname, rc);
oml_tx_failure_event_rep(&fl1h->phy_inst->trx->mo, NM_SEVER_MAJOR, OSMO_EVT_WARN_SW_WARN,
"Verify L1 calibration table %s -> failed (%d)", desc->fname, rc);
st->last_file_idx = get_next_calib_file_idx(fl1h, st->last_file_idx);
@@ -293,16 +277,9 @@ int calib_load(struct oc2gl1_hdl *fl1h)
char *calib_path = fl1h->phy_inst->u.oc2g.calib_path;
if (!calib_path) {
LOGP(DL1C, LOGL_NOTICE, "Calibration file path not specified\n");
/* TODO (oramadan): Fix OML alarms
if( fl1h->phy_inst->trx ){
fl1h->phy_inst->trx->mo.obj_inst.trx_nr = fl1h->phy_inst->trx->nr;
alarm_sig_data.mo = &fl1h->phy_inst->trx->mo;
osmo_signal_dispatch(SS_NM, S_NM_OML_BTS_NO_CALIB_PATH_ALARM, &alarm_sig_data);
}
*/
LOGP(DL1C, LOGL_FATAL, "Calibration file path not specified\n");
oml_tx_failure_event_rep(&fl1h->phy_inst->trx->mo, NM_SEVER_MAJOR, OSMO_EVT_WARN_SW_WARN,
"Calibration file path not specified");
return -1;
}
@@ -330,7 +307,7 @@ static int calib_verify(struct oc2gl1_hdl *fl1h, const struct calib_file_desc *d
fseek(st->fp, 0L, SEEK_END);
sz = ftell(st->fp);
/* rewind read poiner */
/* rewind read pointer */
fseek(st->fp, 0L, SEEK_SET);
/* read file */

View File

@@ -54,6 +54,7 @@
#include <osmo-bts/l1sap.h>
#include <osmo-bts/msg_utils.h>
#include <osmo-bts/dtx_dl_amr_fsm.h>
#include <osmo-bts/cbch.h>
#include <nrw/oc2g/oc2g.h>
#include <nrw/oc2g/gsml1prim.h>
@@ -846,6 +847,45 @@ static uint8_t chan_nr_by_sapi(struct gsm_bts_trx_ts *ts,
return (cbits << 3) | u8Tn;
}
static const enum l1sap_common_sapi common_sapi_by_sapi_t[] = {
[GsmL1_Sapi_Idle] = L1SAP_COMMON_SAPI_IDLE,
[GsmL1_Sapi_Fcch] = L1SAP_COMMON_SAPI_FCCH,
[GsmL1_Sapi_Sch] = L1SAP_COMMON_SAPI_SCH,
[GsmL1_Sapi_Sacch] = L1SAP_COMMON_SAPI_SACCH,
[GsmL1_Sapi_Sdcch] = L1SAP_COMMON_SAPI_SDCCH,
[GsmL1_Sapi_Bcch] = L1SAP_COMMON_SAPI_BCCH,
[GsmL1_Sapi_Pch] = L1SAP_COMMON_SAPI_PCH,
[GsmL1_Sapi_Agch] = L1SAP_COMMON_SAPI_AGCH,
[GsmL1_Sapi_Cbch] = L1SAP_COMMON_SAPI_CBCH,
[GsmL1_Sapi_Rach] = L1SAP_COMMON_SAPI_RACH,
[GsmL1_Sapi_TchF] = L1SAP_COMMON_SAPI_TCH_F,
[GsmL1_Sapi_FacchF] = L1SAP_COMMON_SAPI_FACCH_F,
[GsmL1_Sapi_TchH] = L1SAP_COMMON_SAPI_TCH_H,
[GsmL1_Sapi_FacchH] = L1SAP_COMMON_SAPI_FACCH_H,
[GsmL1_Sapi_Nch] = L1SAP_COMMON_SAPI_NCH,
[GsmL1_Sapi_Pdtch] = L1SAP_COMMON_SAPI_PDTCH,
[GsmL1_Sapi_Pacch] = L1SAP_COMMON_SAPI_PACCH,
[GsmL1_Sapi_Pbcch] = L1SAP_COMMON_SAPI_PBCCH,
[GsmL1_Sapi_Pagch] = L1SAP_COMMON_SAPI_PAGCH,
[GsmL1_Sapi_Ppch] = L1SAP_COMMON_SAPI_PPCH,
[GsmL1_Sapi_Pnch] = L1SAP_COMMON_SAPI_PNCH,
[GsmL1_Sapi_Ptcch] = L1SAP_COMMON_SAPI_PTCCH,
[GsmL1_Sapi_Prach] = L1SAP_COMMON_SAPI_PRACH,
};
static enum l1sap_common_sapi get_common_sapi(GsmL1_Sapi_t sapi)
{
if (sapi >= GsmL1_Sapi_NUM)
return L1SAP_COMMON_SAPI_UNKNOWN;
return common_sapi_by_sapi_t[sapi];
}
static void set_log_ctx_sapi(GsmL1_Sapi_t sapi)
{
l1sap_log_ctx_sapi = get_common_sapi(sapi);
log_set_context(LOG_CTX_L1_SAPI, &l1sap_log_ctx_sapi);
}
static int handle_ph_readytosend_ind(struct oc2gl1_hdl *fl1,
GsmL1_PhReadyToSendInd_t *rts_ind,
struct msgb *l1p_msg)
@@ -862,6 +902,8 @@ static int handle_ph_readytosend_ind(struct oc2gl1_hdl *fl1,
uint8_t chan_nr, link_id;
uint32_t fn;
set_log_ctx_sapi(rts_ind->sapi);
/* check if primitive should be handled by common part */
chan_nr = chan_nr_by_sapi(&trx->ts[rts_ind->u8Tn], rts_ind->sapi,
rts_ind->subCh, rts_ind->u8Tn, rts_ind->u32Fn);
@@ -950,12 +992,9 @@ empty_frame:
goto tx;
}
static void dump_meas_res(int ll, GsmL1_MeasParam_t *m)
{
LOGPC(DL1C, ll, ", Meas: RSSI %-3.2f dBm, Qual %-3.2f dB, "
"BER %-3.2f, Timing %d\n", m->fRssi, m->fLinkQuality,
m->fBer, m->i16BurstTiming);
}
#define LOG_FMT_MEAS "Meas: RSSI %-3.2f dBm, Qual %-3.2f dB, BER %-3.2f, Timing %d"
#define LOG_PARAM_MEAS(meas_param) (meas_param)->fRssi, (meas_param)->fLinkQuality, (meas_param)->fBer, (meas_param)->i16BurstTiming
static int process_meas_res(struct gsm_bts_trx *trx, uint8_t chan_nr,
GsmL1_MeasParam_t *m, uint32_t fn)
@@ -988,6 +1027,8 @@ static int handle_ph_data_ind(struct oc2gl1_hdl *fl1, GsmL1_PhDataInd_t *data_in
int rc = 0;
int8_t rssi;
set_log_ctx_sapi(data_ind->sapi);
chan_nr = chan_nr_by_sapi(&trx->ts[data_ind->u8Tn], data_ind->sapi,
data_ind->subCh, data_ind->u8Tn, data_ind->u32Fn);
fn = data_ind->u32Fn;
@@ -1004,10 +1045,10 @@ static int handle_ph_data_ind(struct oc2gl1_hdl *fl1, GsmL1_PhDataInd_t *data_in
process_meas_res(trx, chan_nr, &data_ind->measParam, fn);
DEBUGPGT(DL1P, &g_time, "Rx PH-DATA.ind %s (hL2 %08x): %s\n",
DEBUGPGT(DL1P, &g_time, "Rx PH-DATA.ind %s (hL2 %08x): %s, " LOG_FMT_MEAS "\n",
get_value_string(oc2gbts_l1sapi_names, data_ind->sapi), (uint32_t)data_ind->hLayer2,
osmo_hexdump(data_ind->msgUnitParam.u8Buffer, data_ind->msgUnitParam.u8Size));
dump_meas_res(LOGL_DEBUG, &data_ind->measParam);
osmo_hexdump(data_ind->msgUnitParam.u8Buffer, data_ind->msgUnitParam.u8Size),
LOG_PARAM_MEAS(&data_ind->measParam));
/* check for TCH */
if (data_ind->sapi == GsmL1_Sapi_TchF
@@ -1040,11 +1081,10 @@ static int handle_ph_data_ind(struct oc2gl1_hdl *fl1, GsmL1_PhDataInd_t *data_in
l1sap->u.data.chan_nr = chan_nr;
l1sap->u.data.fn = fn;
l1sap->u.data.rssi = rssi;
if (!pcu_direct) {
l1sap->u.data.ber10k = data_ind->measParam.fBer * 10000;
l1sap->u.data.ta_offs_256bits = data_ind->measParam.i16BurstTiming*64;
l1sap->u.data.lqual_cb = data_ind->measParam.fLinkQuality * 10;
}
l1sap->u.data.ber10k = data_ind->measParam.fBer * 10000;
l1sap->u.data.ta_offs_256bits = data_ind->measParam.i16BurstTiming*64;
l1sap->u.data.lqual_cb = data_ind->measParam.fLinkQuality * 10;
return l1sap_up(trx, l1sap);
}
@@ -1052,19 +1092,14 @@ static int handle_ph_ra_ind(struct oc2gl1_hdl *fl1, GsmL1_PhRaInd_t *ra_ind,
struct msgb *l1p_msg)
{
struct gsm_bts_trx *trx = oc2gl1_hdl_trx(fl1);
struct gsm_bts *bts = trx->bts;
struct gsm_lchan *lchan;
struct osmo_phsap_prim *l1sap;
int rc;
struct ph_rach_ind_param rach_ind_param;
/* FIXME: this should be deprecated/obsoleted as it bypasses rach.busy counting */
if (ra_ind->measParam.fLinkQuality < bts->min_qual_rach) {
msgb_free(l1p_msg);
return 0;
}
dump_meas_res(LOGL_DEBUG, &ra_ind->measParam);
set_log_ctx_sapi(ra_ind->sapi);
LOGPFN(DL1C, LOGL_DEBUG, ra_ind->u32Fn, "Rx PH-RA.ind, " LOG_FMT_MEAS "\n",
LOG_PARAM_MEAS(&ra_ind->measParam));
if ((ra_ind->msgUnitParam.u8Size != 1) &&
(ra_ind->msgUnitParam.u8Size != 2)) {
@@ -1084,13 +1119,14 @@ static int handle_ph_ra_ind(struct oc2gl1_hdl *fl1, GsmL1_PhRaInd_t *ra_ind,
.rssi = (int8_t) ra_ind->measParam.fRssi,
.ber10k = (unsigned int) (ra_ind->measParam.fBer * 10000.0),
.acc_delay_256bits = ra_ind->measParam.i16BurstTiming * 64,
.lqual_cb = (int16_t) ra_ind->measParam.fLinkQuality * 10, /* centiBels */
};
lchan = l1if_hLayer_to_lchan(trx, (uint32_t)ra_ind->hLayer2);
if (!lchan || lchan->ts->pchan == GSM_PCHAN_CCCH ||
lchan->ts->pchan == GSM_PCHAN_CCCH_SDCCH4 ||
lchan->ts->pchan == GSM_PCHAN_CCCH_SDCCH4_CBCH)
rach_ind_param.chan_nr = 0x88;
rach_ind_param.chan_nr = RSL_CHAN_RACH;
else
rach_ind_param.chan_nr = gsm_lchan2chan_nr(lchan);
@@ -1266,7 +1302,6 @@ static int activate_rf_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp,
GsmL1_Status_t status;
int on = 0;
unsigned int i;
struct gsm_bts *bts = trx->bts;
if (sysp->id == Oc2g_PrimId_ActivateRfCnf)
on = 1;
@@ -1495,13 +1530,25 @@ static int reset_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp,
return 0;
}
int l1if_reset(struct oc2gl1_hdl *hdl)
/* FIXME: This delays the TRX initialization by 5 sec in order to avoid the
* occurrence of a race condition in the OML bringup. This a work around and
* should be fixed properly. See also OS#3782, OS#2470 and OS#2469 */
void l1if_reset_cb(void *arg)
{
struct oc2gl1_hdl *hdl = arg;
struct msgb *msg = sysp_msgb_alloc();
Oc2g_Prim_t *sysp = msgb_sysprim(msg);
sysp->id = Oc2g_PrimId_Layer1ResetReq;
return l1if_req_compl(hdl, msg, reset_compl_cb, NULL);
l1if_req_compl(hdl, msg, reset_compl_cb, NULL);
}
int l1if_reset(struct oc2gl1_hdl *hdl)
{
static struct osmo_timer_list T_l1if_reset;
osmo_timer_setup(&T_l1if_reset, l1if_reset_cb, hdl);
osmo_timer_schedule(&T_l1if_reset, 5, 0);
return 0;
}
/* set the trace flags within the DSP */
@@ -1745,7 +1792,7 @@ int bts_model_phy_link_open(struct phy_link *plink)
return -EIO;
}
/* initialize DSP heart beat alive timer * /
/ * initialize DSP heart beat alive timer * /
fl1h->hw_alive.dsp_alive_timer.cb = dsp_alive_timer_cb;
fl1h->hw_alive.dsp_alive_timer.data = fl1h;
fl1h->hw_alive.dsp_alive_cnt = 0;

View File

@@ -30,6 +30,13 @@ enum {
_NUM_MQ_WRITE
};
/* gsm_bts->model_priv, specific to Open Cellular 2G BTS */
struct bts_oc2g_priv {
uint8_t led_ctrl_mode; /* 0: control by BTS, 1: not control by BTS */
struct llist_head ceased_alarm_list; /* ceased alarm list*/
unsigned int rtp_drift_thres_ms; /* RTP timestamp drift detection threshold */
};
struct calib_send_state {
FILE *fp;
const char *path;

View File

@@ -2,7 +2,7 @@
/* Copyright (C) 2015 by Yves Godin <support@nuranwireless.com>
* Copyright (C) 2016 by Harald Welte <laforge@gnumonks.org>
*
*
* Based on sysmoBTS:
* (C) 2011-2013 by Harald Welte <laforge@gnumonks.org>
*
@@ -83,20 +83,21 @@ unsigned int dsp_trace = 0x00000000;
int bts_model_init(struct gsm_bts *bts)
{
struct gsm_bts_trx *trx;
struct stat st;
static struct osmo_fd accept_fd, read_fd;
int rc;
struct bts_oc2g_priv *bts_oc2g = talloc(bts, struct bts_oc2g_priv);
bts->model_priv = bts_oc2g;
bts->variant = BTS_OSMO_OC2G;
bts->support.ciphers = CIPHER_A5(1) | CIPHER_A5(2) | CIPHER_A5(3);
/* specific default values for OC2G platform */
/* TODO(oramadan) MERGE
bts->oc2g.led_ctrl_mode = OC2G_BTS_LED_CTRL_MODE_DEFAULT;
/* RTP drift threshold default * /
bts->oc2g.rtp_drift_thres_ms = OC2G_BTS_RTP_DRIFT_THRES_DEFAULT;
bts_oc2g->led_ctrl_mode = OC2G_BTS_LED_CTRL_MODE_DEFAULT;
*/
/* RTP drift threshold default */
/* bts_oc2g->rtp_drift_thres_ms = OC2G_BTS_RTP_DRIFT_THRES_DEFAULT; */
rc = oml_router_init(bts, OML_ROUTER_PATH, &accept_fd, &read_fd);
if (rc < 0) {
@@ -119,6 +120,7 @@ int bts_model_init(struct gsm_bts *bts)
gsm_bts_set_feature(bts, BTS_FEAT_SPEECH_F_EFR);
gsm_bts_set_feature(bts, BTS_FEAT_SPEECH_F_AMR);
gsm_bts_set_feature(bts, BTS_FEAT_SPEECH_H_AMR);
gsm_bts_set_feature(bts, BTS_FEAT_MS_PWR_CTRL_DSP);
bts_model_vty_init(bts);
@@ -127,7 +129,7 @@ int bts_model_init(struct gsm_bts *bts)
int bts_model_trx_init(struct gsm_bts_trx *trx)
{
trx->nominal_power = 40;
trx->nominal_power = 25;
trx->power_params.trx_p_max_out_mdBm = to_mdB(trx->bts->c0->nominal_power);
return 0;
}
@@ -152,24 +154,16 @@ void bts_update_status(enum bts_global_status which, int on)
{
static uint64_t states = 0;
uint64_t old_states = states;
int led_rf_active_on;
if (on)
states |= (1ULL << which);
else
states &= ~(1ULL << which);
led_rf_active_on =
(states & (1ULL << BTS_STATUS_RF_ACTIVE)) &&
!(states & (1ULL << BTS_STATUS_RF_MUTE));
LOGP(DL1C, LOGL_INFO,
"Set global status #%d to %d (%04llx -> %04llx), LEDs: ACT %d\n",
"Set global status #%d to %d (%04llx -> %04llx)\n",
which, on,
(long long)old_states, (long long)states,
led_rf_active_on);
oc2gbts_led_set(led_rf_active_on ? LED_GREEN : LED_OFF);
(long long)old_states, (long long)states);
}
void bts_model_print_help()

View File

@@ -24,6 +24,7 @@
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include "oc2gbts_bid.h"
@@ -106,7 +107,6 @@ void oc2gbts_rev_get(char *rev_maj, char *rev_min)
const char* get_hwversion_desc()
{
int rev;
int model;
size_t len;
static char model_name[64] = {0, };
@@ -114,14 +114,9 @@ const char* get_hwversion_desc()
char rev_maj = 0, rev_min = 0;
int rc = 0;
oc2gbts_rev_get(&rev_maj, &rev_min);
if (rc < 0)
return rc;
if (rev >= 0) {
len += snprintf(model_name + len, sizeof(model_name) - len,
" Rev %d.%d", (uint8_t)rev_maj, (uint8_t)rev_min);
}
len += snprintf(model_name + len, sizeof(model_name) - len,
" Rev %" PRIu8 ".%" PRIu8, (uint8_t)rev_maj, (uint8_t)rev_min);
model = oc2gbts_model_get();
if (model >= 0) {

View File

@@ -43,5 +43,6 @@ enum oc2gbts_gsm_band {
void oc2gbts_rev_get(char *rev_maj, char *rev_min);
int oc2gbts_model_get(void);
int oc2gbts_option_get(enum oc2gbts_option_type type);
const char* get_hwversion_desc();
#endif

View File

@@ -100,8 +100,6 @@ static int sysfs_write_str(int fd, const char *str)
int oc2gbts_clock_err_open(void)
{
int rc;
int fault;
if (clkerr_fd_err < 0) {
clkerr_fd_err = open(CLKERR_ERR_SYSFS, O_RDONLY);

View File

@@ -150,7 +150,7 @@ static void led_sleep_cb(void *_data) {
/* Delete current timer */
osmo_timer_del(&led_list->led_timer.timer);
/* Rotate the timer list */
llist_move_tail(led_list, &mgr->oc2gbts_leds.list);
llist_move_tail(&led_list->list, &mgr->oc2gbts_leds.list);
break;
}
}

View File

@@ -261,9 +261,9 @@ static const struct log_info mgr_log_info = {
.num_cat = ARRAY_SIZE(mgr_log_info_cat),
};
static int mgr_log_init(void)
static int mgr_log_init(void *ctx)
{
osmo_init_logging(&mgr_log_info);
osmo_init_logging2(ctx, &mgr_log_info);
return 0;
}
@@ -271,13 +271,12 @@ int main(int argc, char **argv)
{
void *tall_msgb_ctx;
int rc;
pthread_t tid;
tall_mgr_ctx = talloc_named_const(NULL, 1, "bts manager");
tall_msgb_ctx = talloc_named_const(tall_mgr_ctx, 1, "msgb");
msgb_set_talloc_ctx(tall_msgb_ctx);
msgb_talloc_ctx_init(tall_msgb_ctx, 0);
mgr_log_init();
mgr_log_init(tall_mgr_ctx);
osmo_init_ignore_signals();
signal(SIGINT, &signal_handler);
@@ -289,7 +288,7 @@ int main(int argc, char **argv)
exit(2);
oc2gbts_mgr_vty_init();
logging_vty_add_cmds(&mgr_log_info);
logging_vty_add_cmds();
rc = oc2gbts_mgr_parse_config(&manager);
if (rc < 0) {
LOGP(DFIND, LOGL_FATAL, "Cannot parse config file\n");

View File

@@ -87,7 +87,7 @@ static int oc2gbts_par_get_uptime(void *ctx, int *ret)
fpath = talloc_asprintf(ctx, "%s", UPTIME_TMP_PATH);
if (!fpath)
return NULL;
return -EINVAL;
fp = fopen(fpath, "r");
if (!fp)
@@ -117,7 +117,7 @@ static int oc2gbts_par_set_uptime(void *ctx, int val)
fpath = talloc_asprintf(ctx, "%s", UPTIME_TMP_PATH);
if (!fpath)
return NULL;
return -EINVAL;
fp = fopen(fpath, "w");
if (!fp)
@@ -134,7 +134,7 @@ static int oc2gbts_par_set_uptime(void *ctx, int val)
fclose(fp);
return -EIO;
}
fsync(fp);
fsync(fileno(fp));
fclose(fp);
return 0;
@@ -245,18 +245,6 @@ static void send_ctrl_cmd(struct oc2gbts_mgr_instance *mgr, struct msgb *msg)
ipa_client_conn_send(mgr->oc2gbts_ctrl.bts_conn, msg);
}
static void send_set_ctrl_cmd_int(struct oc2gbts_mgr_instance *mgr, const char *key, const int val)
{
struct msgb *msg;
int ret;
msg = msgb_alloc_headroom(1024, 128, "CTRL SET");
ret = snprintf((char *) msg->data, 4096, "SET %u %s %d",
mgr->oc2gbts_ctrl.last_seqno++, key, val);
msg->l2h = msgb_put(msg, ret);
return send_ctrl_cmd(mgr, msg);
}
static void send_set_ctrl_cmd(struct oc2gbts_mgr_instance *mgr, const char *key, const int val, const char *text)
{
struct msgb *msg;

View File

@@ -512,35 +512,35 @@ DEFUN(show_mgr, show_mgr_cmd, "show manager",
oc2gbts_mgr_sensor_get_state(s_mgr->state.state), VTY_NEWLINE);
vty_out(vty, "Current Temperatures%s", VTY_NEWLINE);
oc2gbts_temp_get(OC2GBTS_TEMP_SUPPLY, &temp);
vty_out(vty, " Main Supply : %4.2f Celcius%s",
vty_out(vty, " Main Supply : %4.2f Celsius%s",
temp/ 1000.0f,
VTY_NEWLINE);
oc2gbts_temp_get(OC2GBTS_TEMP_SOC, &temp);
vty_out(vty, " SoC : %4.2f Celcius%s",
vty_out(vty, " SoC : %4.2f Celsius%s",
temp / 1000.0f,
VTY_NEWLINE);
oc2gbts_temp_get(OC2GBTS_TEMP_FPGA, &temp);
vty_out(vty, " FPGA : %4.2f Celcius%s",
vty_out(vty, " FPGA : %4.2f Celsius%s",
temp / 1000.0f,
VTY_NEWLINE);
if (oc2gbts_option_get(OC2GBTS_OPTION_RMS_FWD) ||
oc2gbts_option_get(OC2GBTS_OPTION_RMS_REFL)) {
oc2gbts_temp_get(OC2GBTS_TEMP_RMSDET, &temp);
vty_out(vty, " RMSDet : %4.2f Celcius%s",
vty_out(vty, " RMSDet : %4.2f Celsius%s",
temp / 1000.0f,
VTY_NEWLINE);
}
oc2gbts_temp_get(OC2GBTS_TEMP_OCXO, &temp);
vty_out(vty, " OCXO : %4.2f Celcius%s",
vty_out(vty, " OCXO : %4.2f Celsius%s",
temp / 1000.0f,
VTY_NEWLINE);
oc2gbts_temp_get(OC2GBTS_TEMP_TX, &temp);
vty_out(vty, " TX : %4.2f Celcius%s",
vty_out(vty, " TX : %4.2f Celsius%s",
temp / 1000.0f,
VTY_NEWLINE);
if (oc2gbts_option_get(OC2GBTS_OPTION_PA_TEMP)) {
oc2gbts_temp_get(OC2GBTS_TEMP_PA, &temp);
vty_out(vty, " Power Amp : %4.2f Celcius%s",
vty_out(vty, " Power Amp : %4.2f Celsius%s",
temp / 1000.0f,
VTY_NEWLINE);
}
@@ -878,46 +878,37 @@ int oc2gbts_mgr_vty_init(void)
install_node(&mgr_node, config_write_mgr);
install_element(CONFIG_NODE, &cfg_mgr_cmd);
vty_install_default(MGR_NODE);
/* install the limit nodes */
install_node(&limit_supply_temp_node, config_write_dummy);
install_element(MGR_NODE, &cfg_limit_supply_temp_cmd);
vty_install_default(LIMIT_SUPPLY_TEMP_NODE);
install_node(&limit_soc_node, config_write_dummy);
install_element(MGR_NODE, &cfg_limit_soc_temp_cmd);
vty_install_default(LIMIT_SOC_NODE);
install_node(&limit_fpga_node, config_write_dummy);
install_element(MGR_NODE, &cfg_limit_fpga_temp_cmd);
vty_install_default(LIMIT_FPGA_NODE);
if (oc2gbts_option_get(OC2GBTS_OPTION_RMS_FWD) ||
oc2gbts_option_get(OC2GBTS_OPTION_RMS_REFL)) {
install_node(&limit_rmsdet_node, config_write_dummy);
install_element(MGR_NODE, &cfg_limit_rmsdet_temp_cmd);
vty_install_default(LIMIT_RMSDET_NODE);
}
install_node(&limit_ocxo_node, config_write_dummy);
install_element(MGR_NODE, &cfg_limit_ocxo_temp_cmd);
vty_install_default(LIMIT_OCXO_NODE);
install_node(&limit_tx_temp_node, config_write_dummy);
install_element(MGR_NODE, &cfg_limit_tx_temp_cmd);
vty_install_default(LIMIT_TX_TEMP_NODE);
if (oc2gbts_option_get(OC2GBTS_OPTION_PA_TEMP)) {
install_node(&limit_pa_temp_node, config_write_dummy);
install_element(MGR_NODE, &cfg_limit_pa_temp_cmd);
vty_install_default(LIMIT_PA_TEMP_NODE);
}
install_node(&limit_supply_volt_node, config_write_dummy);
install_element(MGR_NODE, &cfg_limit_supply_volt_cmd);
register_limit(LIMIT_SUPPLY_VOLT_NODE, MGR_LIMIT_TYPE_VOLT);
vty_install_default(LIMIT_SUPPLY_VOLT_NODE);
if (oc2gbts_option_get(OC2GBTS_OPTION_PA) &&
oc2gbts_option_get(OC2GBTS_OPTION_RMS_FWD) &&
@@ -925,23 +916,19 @@ int oc2gbts_mgr_vty_init(void)
install_node(&limit_vswr_node, config_write_dummy);
install_element(MGR_NODE, &cfg_limit_vswr_cmd);
register_limit(LIMIT_VSWR_NODE, MGR_LIMIT_TYPE_VSWR);
vty_install_default(LIMIT_VSWR_NODE);
}
install_node(&limit_supply_pwr_node, config_write_dummy);
install_element(MGR_NODE, &cfg_limit_supply_pwr_cmd);
register_limit(LIMIT_SUPPLY_PWR_NODE, MGR_LIMIT_TYPE_PWR);
vty_install_default(LIMIT_SUPPLY_PWR_NODE);
if (oc2gbts_option_get(OC2GBTS_OPTION_PA)) {
install_node(&limit_pa_pwr_node, config_write_dummy);
install_element(MGR_NODE, &cfg_limit_pa_pwr_cmd);
vty_install_default(LIMIT_PA_PWR_NODE);
}
install_node(&limit_gps_fix_node, config_write_dummy);
install_element(MGR_NODE, &cfg_limit_gps_fix_cmd);
vty_install_default(LIMIT_GPS_FIX_NODE);
/* install the normal node */
install_node(&act_norm_node, config_write_dummy);
@@ -952,12 +939,10 @@ int oc2gbts_mgr_vty_init(void)
install_node(&act_warn_node, config_write_dummy);
install_element(MGR_NODE, &cfg_action_warn_cmd);
register_action(ACT_WARN_NODE);
vty_install_default(ACT_WARN_NODE);
install_node(&act_crit_node, config_write_dummy);
install_element(MGR_NODE, &cfg_action_critical_cmd);
register_action(ACT_CRIT_NODE);
vty_install_default(ACT_CRIT_NODE);
/* install LED pattern command for debugging purpose */
install_element_ve(&set_led_pattern_cmd);

View File

@@ -361,7 +361,7 @@ int oc2gbts_firmware_reload(enum oc2gbts_firmware_type type)
case OC2GBTS_FW_DSP:
fd = open(fw_sysfs[type], O_WRONLY);
if (fd < 0) {
LOGP(DFW, LOGL_ERROR, "unable ot open firmware device %s: %s\n",
LOGP(DFW, LOGL_ERROR, "unable to open firmware device %s: %s\n",
fw_sysfs[type], strerror(errno));
close(fd);
return fd;

Some files were not shown because too many files have changed in this diff Show More