mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-11-03 03:48:20 +00:00
Merge commit 'c263ce2f41e27c99bba611763279cf434b893ed9' as 'software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts'
This commit is contained in:
@@ -0,0 +1,82 @@
|
|||||||
|
*.o
|
||||||
|
*.a
|
||||||
|
Makefile.in
|
||||||
|
Makefile
|
||||||
|
.deps
|
||||||
|
|
||||||
|
btsconfig.h
|
||||||
|
btsconfig.h.in
|
||||||
|
|
||||||
|
aclocal.m4
|
||||||
|
autom4te.cache
|
||||||
|
config.log
|
||||||
|
config.status
|
||||||
|
config.guess
|
||||||
|
config.sub
|
||||||
|
configure
|
||||||
|
compile
|
||||||
|
depcomp
|
||||||
|
install-sh
|
||||||
|
missing
|
||||||
|
stamp-h1
|
||||||
|
libtool
|
||||||
|
ltmain.sh
|
||||||
|
core
|
||||||
|
core.*
|
||||||
|
|
||||||
|
# git-version-gen magic
|
||||||
|
.tarball-version
|
||||||
|
.version
|
||||||
|
|
||||||
|
src/osmo-bts-sysmo/sysmobts-calib
|
||||||
|
src/osmo-bts-sysmo/l1fwd-proxy
|
||||||
|
src/osmo-bts-sysmo/osmo-bts-sysmo
|
||||||
|
src/osmo-bts-sysmo/osmo-bts-sysmo-remote
|
||||||
|
src/osmo-bts-sysmo/sysmobts-mgr
|
||||||
|
src/osmo-bts-sysmo/sysmobts-util
|
||||||
|
|
||||||
|
src/osmo-bts-litecell15/lc15bts-mgr
|
||||||
|
src/osmo-bts-litecell15/lc15bts-util
|
||||||
|
src/osmo-bts-litecell15/misc/.dirstamp
|
||||||
|
src/osmo-bts-litecell15/osmo-bts-lc15
|
||||||
|
|
||||||
|
src/osmo-bts-trx/osmo-bts-trx
|
||||||
|
|
||||||
|
src/osmo-bts-octphy/osmo-bts-octphy
|
||||||
|
|
||||||
|
src/osmo-bts-virtual/osmo-bts-virtual
|
||||||
|
src/osmo-bts-omldummy/osmo-bts-omldummy
|
||||||
|
|
||||||
|
tests/atconfig
|
||||||
|
tests/package.m4
|
||||||
|
tests/agch/agch_test
|
||||||
|
tests/paging/paging_test
|
||||||
|
tests/cipher/cipher_test
|
||||||
|
tests/sysmobts/sysmobts_test
|
||||||
|
tests/meas/meas_test
|
||||||
|
tests/misc/misc_test
|
||||||
|
tests/handover/handover_test
|
||||||
|
tests/tx_power/tx_power_test
|
||||||
|
tests/testsuite
|
||||||
|
tests/testsuite.log
|
||||||
|
|
||||||
|
# Possible generated file
|
||||||
|
doc/vty_reference.xml
|
||||||
|
|
||||||
|
# Backups, vi, merges
|
||||||
|
*~
|
||||||
|
*.sw?
|
||||||
|
*.orig
|
||||||
|
*.sav
|
||||||
|
|
||||||
|
# debian
|
||||||
|
.tarball-version
|
||||||
|
debian/autoreconf.after
|
||||||
|
debian/autoreconf.before
|
||||||
|
debian/files
|
||||||
|
debian/*.debhelper.log
|
||||||
|
debian/*.substvars
|
||||||
|
debian/osmo-bts-trx-dbg/
|
||||||
|
debian/osmo-bts-trx/
|
||||||
|
debian/tmp/
|
||||||
|
/tests/power/power_test
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
[gerrit]
|
||||||
|
host=gerrit.osmocom.org
|
||||||
|
project=osmo-bts
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
Harald Welte <laforge@gnumonks.org>
|
||||||
|
Harald Welte <laforge@gnumonks.org> <laflocal@hanuman.gnumonks.org>
|
||||||
|
Harald Welte <laforge@gnumonks.org> <laflocal@goeller.de.gnumonks.org>
|
||||||
|
Holger Hans Peter Freyther <holger@moiji-mobile.com> <zecke@selfish.org>
|
||||||
|
Holger Hans Peter Freyther <holger@moiji-mobile.com> <ich@tamarin.(none)>
|
||||||
|
Holger Hans Peter Freyther <holgre@moiji-mobile.com> <holger@freyther.de>
|
||||||
|
Andreas Eversberg <jolly@eversberg.eu>
|
||||||
|
Andreas Eversberg <jolly@eversberg.eu> <Andreas.Eversberg@versatel.de>
|
||||||
|
Andreas Eversberg <jolly@eversberg.eu> <root@nuedel.(none)>
|
||||||
|
Pablo Neira Ayuso <pablo@soleta.eu> <pablo@gnumonks.org>
|
||||||
|
Max Suraev <msuraev@sysmocom.de>
|
||||||
|
Tom Tsou <tom.tsou@ettus.com> <tom@tsou.cc>
|
||||||
@@ -0,0 +1,661 @@
|
|||||||
|
GNU AFFERO GENERAL PUBLIC LICENSE
|
||||||
|
Version 3, 19 November 2007
|
||||||
|
|
||||||
|
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The GNU Affero General Public License is a free, copyleft license for
|
||||||
|
software and other kinds of works, specifically designed to ensure
|
||||||
|
cooperation with the community in the case of network server software.
|
||||||
|
|
||||||
|
The licenses for most software and other practical works are designed
|
||||||
|
to take away your freedom to share and change the works. By contrast,
|
||||||
|
our General Public Licenses are intended to guarantee your freedom to
|
||||||
|
share and change all versions of a program--to make sure it remains free
|
||||||
|
software for all its users.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
them if you wish), that you receive source code or can get it if you
|
||||||
|
want it, that you can change the software or use pieces of it in new
|
||||||
|
free programs, and that you know you can do these things.
|
||||||
|
|
||||||
|
Developers that use our General Public Licenses protect your rights
|
||||||
|
with two steps: (1) assert copyright on the software, and (2) offer
|
||||||
|
you this License which gives you legal permission to copy, distribute
|
||||||
|
and/or modify the software.
|
||||||
|
|
||||||
|
A secondary benefit of defending all users' freedom is that
|
||||||
|
improvements made in alternate versions of the program, if they
|
||||||
|
receive widespread use, become available for other developers to
|
||||||
|
incorporate. Many developers of free software are heartened and
|
||||||
|
encouraged by the resulting cooperation. However, in the case of
|
||||||
|
software used on network servers, this result may fail to come about.
|
||||||
|
The GNU General Public License permits making a modified version and
|
||||||
|
letting the public access it on a server without ever releasing its
|
||||||
|
source code to the public.
|
||||||
|
|
||||||
|
The GNU Affero General Public License is designed specifically to
|
||||||
|
ensure that, in such cases, the modified source code becomes available
|
||||||
|
to the community. It requires the operator of a network server to
|
||||||
|
provide the source code of the modified version running there to the
|
||||||
|
users of that server. Therefore, public use of a modified version, on
|
||||||
|
a publicly accessible server, gives the public access to the source
|
||||||
|
code of the modified version.
|
||||||
|
|
||||||
|
An older license, called the Affero General Public License and
|
||||||
|
published by Affero, was designed to accomplish similar goals. This is
|
||||||
|
a different license, not a version of the Affero GPL, but Affero has
|
||||||
|
released a new version of the Affero GPL which permits relicensing under
|
||||||
|
this license.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
0. Definitions.
|
||||||
|
|
||||||
|
"This License" refers to version 3 of the GNU Affero General Public License.
|
||||||
|
|
||||||
|
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||||
|
works, such as semiconductor masks.
|
||||||
|
|
||||||
|
"The Program" refers to any copyrightable work licensed under this
|
||||||
|
License. Each licensee is addressed as "you". "Licensees" and
|
||||||
|
"recipients" may be individuals or organizations.
|
||||||
|
|
||||||
|
To "modify" a work means to copy from or adapt all or part of the work
|
||||||
|
in a fashion requiring copyright permission, other than the making of an
|
||||||
|
exact copy. The resulting work is called a "modified version" of the
|
||||||
|
earlier work or a work "based on" the earlier work.
|
||||||
|
|
||||||
|
A "covered work" means either the unmodified Program or a work based
|
||||||
|
on the Program.
|
||||||
|
|
||||||
|
To "propagate" a work means to do anything with it that, without
|
||||||
|
permission, would make you directly or secondarily liable for
|
||||||
|
infringement under applicable copyright law, except executing it on a
|
||||||
|
computer or modifying a private copy. Propagation includes copying,
|
||||||
|
distribution (with or without modification), making available to the
|
||||||
|
public, and in some countries other activities as well.
|
||||||
|
|
||||||
|
To "convey" a work means any kind of propagation that enables other
|
||||||
|
parties to make or receive copies. Mere interaction with a user through
|
||||||
|
a computer network, with no transfer of a copy, is not conveying.
|
||||||
|
|
||||||
|
An interactive user interface displays "Appropriate Legal Notices"
|
||||||
|
to the extent that it includes a convenient and prominently visible
|
||||||
|
feature that (1) displays an appropriate copyright notice, and (2)
|
||||||
|
tells the user that there is no warranty for the work (except to the
|
||||||
|
extent that warranties are provided), that licensees may convey the
|
||||||
|
work under this License, and how to view a copy of this License. If
|
||||||
|
the interface presents a list of user commands or options, such as a
|
||||||
|
menu, a prominent item in the list meets this criterion.
|
||||||
|
|
||||||
|
1. Source Code.
|
||||||
|
|
||||||
|
The "source code" for a work means the preferred form of the work
|
||||||
|
for making modifications to it. "Object code" means any non-source
|
||||||
|
form of a work.
|
||||||
|
|
||||||
|
A "Standard Interface" means an interface that either is an official
|
||||||
|
standard defined by a recognized standards body, or, in the case of
|
||||||
|
interfaces specified for a particular programming language, one that
|
||||||
|
is widely used among developers working in that language.
|
||||||
|
|
||||||
|
The "System Libraries" of an executable work include anything, other
|
||||||
|
than the work as a whole, that (a) is included in the normal form of
|
||||||
|
packaging a Major Component, but which is not part of that Major
|
||||||
|
Component, and (b) serves only to enable use of the work with that
|
||||||
|
Major Component, or to implement a Standard Interface for which an
|
||||||
|
implementation is available to the public in source code form. A
|
||||||
|
"Major Component", in this context, means a major essential component
|
||||||
|
(kernel, window system, and so on) of the specific operating system
|
||||||
|
(if any) on which the executable work runs, or a compiler used to
|
||||||
|
produce the work, or an object code interpreter used to run it.
|
||||||
|
|
||||||
|
The "Corresponding Source" for a work in object code form means all
|
||||||
|
the source code needed to generate, install, and (for an executable
|
||||||
|
work) run the object code and to modify the work, including scripts to
|
||||||
|
control those activities. However, it does not include the work's
|
||||||
|
System Libraries, or general-purpose tools or generally available free
|
||||||
|
programs which are used unmodified in performing those activities but
|
||||||
|
which are not part of the work. For example, Corresponding Source
|
||||||
|
includes interface definition files associated with source files for
|
||||||
|
the work, and the source code for shared libraries and dynamically
|
||||||
|
linked subprograms that the work is specifically designed to require,
|
||||||
|
such as by intimate data communication or control flow between those
|
||||||
|
subprograms and other parts of the work.
|
||||||
|
|
||||||
|
The Corresponding Source need not include anything that users
|
||||||
|
can regenerate automatically from other parts of the Corresponding
|
||||||
|
Source.
|
||||||
|
|
||||||
|
The Corresponding Source for a work in source code form is that
|
||||||
|
same work.
|
||||||
|
|
||||||
|
2. Basic Permissions.
|
||||||
|
|
||||||
|
All rights granted under this License are granted for the term of
|
||||||
|
copyright on the Program, and are irrevocable provided the stated
|
||||||
|
conditions are met. This License explicitly affirms your unlimited
|
||||||
|
permission to run the unmodified Program. The output from running a
|
||||||
|
covered work is covered by this License only if the output, given its
|
||||||
|
content, constitutes a covered work. This License acknowledges your
|
||||||
|
rights of fair use or other equivalent, as provided by copyright law.
|
||||||
|
|
||||||
|
You may make, run and propagate covered works that you do not
|
||||||
|
convey, without conditions so long as your license otherwise remains
|
||||||
|
in force. You may convey covered works to others for the sole purpose
|
||||||
|
of having them make modifications exclusively for you, or provide you
|
||||||
|
with facilities for running those works, provided that you comply with
|
||||||
|
the terms of this License in conveying all material for which you do
|
||||||
|
not control copyright. Those thus making or running the covered works
|
||||||
|
for you must do so exclusively on your behalf, under your direction
|
||||||
|
and control, on terms that prohibit them from making any copies of
|
||||||
|
your copyrighted material outside their relationship with you.
|
||||||
|
|
||||||
|
Conveying under any other circumstances is permitted solely under
|
||||||
|
the conditions stated below. Sublicensing is not allowed; section 10
|
||||||
|
makes it unnecessary.
|
||||||
|
|
||||||
|
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||||
|
|
||||||
|
No covered work shall be deemed part of an effective technological
|
||||||
|
measure under any applicable law fulfilling obligations under article
|
||||||
|
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||||
|
similar laws prohibiting or restricting circumvention of such
|
||||||
|
measures.
|
||||||
|
|
||||||
|
When you convey a covered work, you waive any legal power to forbid
|
||||||
|
circumvention of technological measures to the extent such circumvention
|
||||||
|
is effected by exercising rights under this License with respect to
|
||||||
|
the covered work, and you disclaim any intention to limit operation or
|
||||||
|
modification of the work as a means of enforcing, against the work's
|
||||||
|
users, your or third parties' legal rights to forbid circumvention of
|
||||||
|
technological measures.
|
||||||
|
|
||||||
|
4. Conveying Verbatim Copies.
|
||||||
|
|
||||||
|
You may convey verbatim copies of the Program's source code as you
|
||||||
|
receive it, in any medium, provided that you conspicuously and
|
||||||
|
appropriately publish on each copy an appropriate copyright notice;
|
||||||
|
keep intact all notices stating that this License and any
|
||||||
|
non-permissive terms added in accord with section 7 apply to the code;
|
||||||
|
keep intact all notices of the absence of any warranty; and give all
|
||||||
|
recipients a copy of this License along with the Program.
|
||||||
|
|
||||||
|
You may charge any price or no price for each copy that you convey,
|
||||||
|
and you may offer support or warranty protection for a fee.
|
||||||
|
|
||||||
|
5. Conveying Modified Source Versions.
|
||||||
|
|
||||||
|
You may convey a work based on the Program, or the modifications to
|
||||||
|
produce it from the Program, in the form of source code under the
|
||||||
|
terms of section 4, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) The work must carry prominent notices stating that you modified
|
||||||
|
it, and giving a relevant date.
|
||||||
|
|
||||||
|
b) The work must carry prominent notices stating that it is
|
||||||
|
released under this License and any conditions added under section
|
||||||
|
7. This requirement modifies the requirement in section 4 to
|
||||||
|
"keep intact all notices".
|
||||||
|
|
||||||
|
c) You must license the entire work, as a whole, under this
|
||||||
|
License to anyone who comes into possession of a copy. This
|
||||||
|
License will therefore apply, along with any applicable section 7
|
||||||
|
additional terms, to the whole of the work, and all its parts,
|
||||||
|
regardless of how they are packaged. This License gives no
|
||||||
|
permission to license the work in any other way, but it does not
|
||||||
|
invalidate such permission if you have separately received it.
|
||||||
|
|
||||||
|
d) If the work has interactive user interfaces, each must display
|
||||||
|
Appropriate Legal Notices; however, if the Program has interactive
|
||||||
|
interfaces that do not display Appropriate Legal Notices, your
|
||||||
|
work need not make them do so.
|
||||||
|
|
||||||
|
A compilation of a covered work with other separate and independent
|
||||||
|
works, which are not by their nature extensions of the covered work,
|
||||||
|
and which are not combined with it such as to form a larger program,
|
||||||
|
in or on a volume of a storage or distribution medium, is called an
|
||||||
|
"aggregate" if the compilation and its resulting copyright are not
|
||||||
|
used to limit the access or legal rights of the compilation's users
|
||||||
|
beyond what the individual works permit. Inclusion of a covered work
|
||||||
|
in an aggregate does not cause this License to apply to the other
|
||||||
|
parts of the aggregate.
|
||||||
|
|
||||||
|
6. Conveying Non-Source Forms.
|
||||||
|
|
||||||
|
You may convey a covered work in object code form under the terms
|
||||||
|
of sections 4 and 5, provided that you also convey the
|
||||||
|
machine-readable Corresponding Source under the terms of this License,
|
||||||
|
in one of these ways:
|
||||||
|
|
||||||
|
a) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by the
|
||||||
|
Corresponding Source fixed on a durable physical medium
|
||||||
|
customarily used for software interchange.
|
||||||
|
|
||||||
|
b) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by a
|
||||||
|
written offer, valid for at least three years and valid for as
|
||||||
|
long as you offer spare parts or customer support for that product
|
||||||
|
model, to give anyone who possesses the object code either (1) a
|
||||||
|
copy of the Corresponding Source for all the software in the
|
||||||
|
product that is covered by this License, on a durable physical
|
||||||
|
medium customarily used for software interchange, for a price no
|
||||||
|
more than your reasonable cost of physically performing this
|
||||||
|
conveying of source, or (2) access to copy the
|
||||||
|
Corresponding Source from a network server at no charge.
|
||||||
|
|
||||||
|
c) Convey individual copies of the object code with a copy of the
|
||||||
|
written offer to provide the Corresponding Source. This
|
||||||
|
alternative is allowed only occasionally and noncommercially, and
|
||||||
|
only if you received the object code with such an offer, in accord
|
||||||
|
with subsection 6b.
|
||||||
|
|
||||||
|
d) Convey the object code by offering access from a designated
|
||||||
|
place (gratis or for a charge), and offer equivalent access to the
|
||||||
|
Corresponding Source in the same way through the same place at no
|
||||||
|
further charge. You need not require recipients to copy the
|
||||||
|
Corresponding Source along with the object code. If the place to
|
||||||
|
copy the object code is a network server, the Corresponding Source
|
||||||
|
may be on a different server (operated by you or a third party)
|
||||||
|
that supports equivalent copying facilities, provided you maintain
|
||||||
|
clear directions next to the object code saying where to find the
|
||||||
|
Corresponding Source. Regardless of what server hosts the
|
||||||
|
Corresponding Source, you remain obligated to ensure that it is
|
||||||
|
available for as long as needed to satisfy these requirements.
|
||||||
|
|
||||||
|
e) Convey the object code using peer-to-peer transmission, provided
|
||||||
|
you inform other peers where the object code and Corresponding
|
||||||
|
Source of the work are being offered to the general public at no
|
||||||
|
charge under subsection 6d.
|
||||||
|
|
||||||
|
A separable portion of the object code, whose source code is excluded
|
||||||
|
from the Corresponding Source as a System Library, need not be
|
||||||
|
included in conveying the object code work.
|
||||||
|
|
||||||
|
A "User Product" is either (1) a "consumer product", which means any
|
||||||
|
tangible personal property which is normally used for personal, family,
|
||||||
|
or household purposes, or (2) anything designed or sold for incorporation
|
||||||
|
into a dwelling. In determining whether a product is a consumer product,
|
||||||
|
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||||
|
product received by a particular user, "normally used" refers to a
|
||||||
|
typical or common use of that class of product, regardless of the status
|
||||||
|
of the particular user or of the way in which the particular user
|
||||||
|
actually uses, or expects or is expected to use, the product. A product
|
||||||
|
is a consumer product regardless of whether the product has substantial
|
||||||
|
commercial, industrial or non-consumer uses, unless such uses represent
|
||||||
|
the only significant mode of use of the product.
|
||||||
|
|
||||||
|
"Installation Information" for a User Product means any methods,
|
||||||
|
procedures, authorization keys, or other information required to install
|
||||||
|
and execute modified versions of a covered work in that User Product from
|
||||||
|
a modified version of its Corresponding Source. The information must
|
||||||
|
suffice to ensure that the continued functioning of the modified object
|
||||||
|
code is in no case prevented or interfered with solely because
|
||||||
|
modification has been made.
|
||||||
|
|
||||||
|
If you convey an object code work under this section in, or with, or
|
||||||
|
specifically for use in, a User Product, and the conveying occurs as
|
||||||
|
part of a transaction in which the right of possession and use of the
|
||||||
|
User Product is transferred to the recipient in perpetuity or for a
|
||||||
|
fixed term (regardless of how the transaction is characterized), the
|
||||||
|
Corresponding Source conveyed under this section must be accompanied
|
||||||
|
by the Installation Information. But this requirement does not apply
|
||||||
|
if neither you nor any third party retains the ability to install
|
||||||
|
modified object code on the User Product (for example, the work has
|
||||||
|
been installed in ROM).
|
||||||
|
|
||||||
|
The requirement to provide Installation Information does not include a
|
||||||
|
requirement to continue to provide support service, warranty, or updates
|
||||||
|
for a work that has been modified or installed by the recipient, or for
|
||||||
|
the User Product in which it has been modified or installed. Access to a
|
||||||
|
network may be denied when the modification itself materially and
|
||||||
|
adversely affects the operation of the network or violates the rules and
|
||||||
|
protocols for communication across the network.
|
||||||
|
|
||||||
|
Corresponding Source conveyed, and Installation Information provided,
|
||||||
|
in accord with this section must be in a format that is publicly
|
||||||
|
documented (and with an implementation available to the public in
|
||||||
|
source code form), and must require no special password or key for
|
||||||
|
unpacking, reading or copying.
|
||||||
|
|
||||||
|
7. Additional Terms.
|
||||||
|
|
||||||
|
"Additional permissions" are terms that supplement the terms of this
|
||||||
|
License by making exceptions from one or more of its conditions.
|
||||||
|
Additional permissions that are applicable to the entire Program shall
|
||||||
|
be treated as though they were included in this License, to the extent
|
||||||
|
that they are valid under applicable law. If additional permissions
|
||||||
|
apply only to part of the Program, that part may be used separately
|
||||||
|
under those permissions, but the entire Program remains governed by
|
||||||
|
this License without regard to the additional permissions.
|
||||||
|
|
||||||
|
When you convey a copy of a covered work, you may at your option
|
||||||
|
remove any additional permissions from that copy, or from any part of
|
||||||
|
it. (Additional permissions may be written to require their own
|
||||||
|
removal in certain cases when you modify the work.) You may place
|
||||||
|
additional permissions on material, added by you to a covered work,
|
||||||
|
for which you have or can give appropriate copyright permission.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, for material you
|
||||||
|
add to a covered work, you may (if authorized by the copyright holders of
|
||||||
|
that material) supplement the terms of this License with terms:
|
||||||
|
|
||||||
|
a) Disclaiming warranty or limiting liability differently from the
|
||||||
|
terms of sections 15 and 16 of this License; or
|
||||||
|
|
||||||
|
b) Requiring preservation of specified reasonable legal notices or
|
||||||
|
author attributions in that material or in the Appropriate Legal
|
||||||
|
Notices displayed by works containing it; or
|
||||||
|
|
||||||
|
c) Prohibiting misrepresentation of the origin of that material, or
|
||||||
|
requiring that modified versions of such material be marked in
|
||||||
|
reasonable ways as different from the original version; or
|
||||||
|
|
||||||
|
d) Limiting the use for publicity purposes of names of licensors or
|
||||||
|
authors of the material; or
|
||||||
|
|
||||||
|
e) Declining to grant rights under trademark law for use of some
|
||||||
|
trade names, trademarks, or service marks; or
|
||||||
|
|
||||||
|
f) Requiring indemnification of licensors and authors of that
|
||||||
|
material by anyone who conveys the material (or modified versions of
|
||||||
|
it) with contractual assumptions of liability to the recipient, for
|
||||||
|
any liability that these contractual assumptions directly impose on
|
||||||
|
those licensors and authors.
|
||||||
|
|
||||||
|
All other non-permissive additional terms are considered "further
|
||||||
|
restrictions" within the meaning of section 10. If the Program as you
|
||||||
|
received it, or any part of it, contains a notice stating that it is
|
||||||
|
governed by this License along with a term that is a further
|
||||||
|
restriction, you may remove that term. If a license document contains
|
||||||
|
a further restriction but permits relicensing or conveying under this
|
||||||
|
License, you may add to a covered work material governed by the terms
|
||||||
|
of that license document, provided that the further restriction does
|
||||||
|
not survive such relicensing or conveying.
|
||||||
|
|
||||||
|
If you add terms to a covered work in accord with this section, you
|
||||||
|
must place, in the relevant source files, a statement of the
|
||||||
|
additional terms that apply to those files, or a notice indicating
|
||||||
|
where to find the applicable terms.
|
||||||
|
|
||||||
|
Additional terms, permissive or non-permissive, may be stated in the
|
||||||
|
form of a separately written license, or stated as exceptions;
|
||||||
|
the above requirements apply either way.
|
||||||
|
|
||||||
|
8. Termination.
|
||||||
|
|
||||||
|
You may not propagate or modify a covered work except as expressly
|
||||||
|
provided under this License. Any attempt otherwise to propagate or
|
||||||
|
modify it is void, and will automatically terminate your rights under
|
||||||
|
this License (including any patent licenses granted under the third
|
||||||
|
paragraph of section 11).
|
||||||
|
|
||||||
|
However, if you cease all violation of this License, then your
|
||||||
|
license from a particular copyright holder is reinstated (a)
|
||||||
|
provisionally, unless and until the copyright holder explicitly and
|
||||||
|
finally terminates your license, and (b) permanently, if the copyright
|
||||||
|
holder fails to notify you of the violation by some reasonable means
|
||||||
|
prior to 60 days after the cessation.
|
||||||
|
|
||||||
|
Moreover, your license from a particular copyright holder is
|
||||||
|
reinstated permanently if the copyright holder notifies you of the
|
||||||
|
violation by some reasonable means, this is the first time you have
|
||||||
|
received notice of violation of this License (for any work) from that
|
||||||
|
copyright holder, and you cure the violation prior to 30 days after
|
||||||
|
your receipt of the notice.
|
||||||
|
|
||||||
|
Termination of your rights under this section does not terminate the
|
||||||
|
licenses of parties who have received copies or rights from you under
|
||||||
|
this License. If your rights have been terminated and not permanently
|
||||||
|
reinstated, you do not qualify to receive new licenses for the same
|
||||||
|
material under section 10.
|
||||||
|
|
||||||
|
9. Acceptance Not Required for Having Copies.
|
||||||
|
|
||||||
|
You are not required to accept this License in order to receive or
|
||||||
|
run a copy of the Program. Ancillary propagation of a covered work
|
||||||
|
occurring solely as a consequence of using peer-to-peer transmission
|
||||||
|
to receive a copy likewise does not require acceptance. However,
|
||||||
|
nothing other than this License grants you permission to propagate or
|
||||||
|
modify any covered work. These actions infringe copyright if you do
|
||||||
|
not accept this License. Therefore, by modifying or propagating a
|
||||||
|
covered work, you indicate your acceptance of this License to do so.
|
||||||
|
|
||||||
|
10. Automatic Licensing of Downstream Recipients.
|
||||||
|
|
||||||
|
Each time you convey a covered work, the recipient automatically
|
||||||
|
receives a license from the original licensors, to run, modify and
|
||||||
|
propagate that work, subject to this License. You are not responsible
|
||||||
|
for enforcing compliance by third parties with this License.
|
||||||
|
|
||||||
|
An "entity transaction" is a transaction transferring control of an
|
||||||
|
organization, or substantially all assets of one, or subdividing an
|
||||||
|
organization, or merging organizations. If propagation of a covered
|
||||||
|
work results from an entity transaction, each party to that
|
||||||
|
transaction who receives a copy of the work also receives whatever
|
||||||
|
licenses to the work the party's predecessor in interest had or could
|
||||||
|
give under the previous paragraph, plus a right to possession of the
|
||||||
|
Corresponding Source of the work from the predecessor in interest, if
|
||||||
|
the predecessor has it or can get it with reasonable efforts.
|
||||||
|
|
||||||
|
You may not impose any further restrictions on the exercise of the
|
||||||
|
rights granted or affirmed under this License. For example, you may
|
||||||
|
not impose a license fee, royalty, or other charge for exercise of
|
||||||
|
rights granted under this License, and you may not initiate litigation
|
||||||
|
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||||
|
any patent claim is infringed by making, using, selling, offering for
|
||||||
|
sale, or importing the Program or any portion of it.
|
||||||
|
|
||||||
|
11. Patents.
|
||||||
|
|
||||||
|
A "contributor" is a copyright holder who authorizes use under this
|
||||||
|
License of the Program or a work on which the Program is based. The
|
||||||
|
work thus licensed is called the contributor's "contributor version".
|
||||||
|
|
||||||
|
A contributor's "essential patent claims" are all patent claims
|
||||||
|
owned or controlled by the contributor, whether already acquired or
|
||||||
|
hereafter acquired, that would be infringed by some manner, permitted
|
||||||
|
by this License, of making, using, or selling its contributor version,
|
||||||
|
but do not include claims that would be infringed only as a
|
||||||
|
consequence of further modification of the contributor version. For
|
||||||
|
purposes of this definition, "control" includes the right to grant
|
||||||
|
patent sublicenses in a manner consistent with the requirements of
|
||||||
|
this License.
|
||||||
|
|
||||||
|
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||||
|
patent license under the contributor's essential patent claims, to
|
||||||
|
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||||
|
propagate the contents of its contributor version.
|
||||||
|
|
||||||
|
In the following three paragraphs, a "patent license" is any express
|
||||||
|
agreement or commitment, however denominated, not to enforce a patent
|
||||||
|
(such as an express permission to practice a patent or covenant not to
|
||||||
|
sue for patent infringement). To "grant" such a patent license to a
|
||||||
|
party means to make such an agreement or commitment not to enforce a
|
||||||
|
patent against the party.
|
||||||
|
|
||||||
|
If you convey a covered work, knowingly relying on a patent license,
|
||||||
|
and the Corresponding Source of the work is not available for anyone
|
||||||
|
to copy, free of charge and under the terms of this License, through a
|
||||||
|
publicly available network server or other readily accessible means,
|
||||||
|
then you must either (1) cause the Corresponding Source to be so
|
||||||
|
available, or (2) arrange to deprive yourself of the benefit of the
|
||||||
|
patent license for this particular work, or (3) arrange, in a manner
|
||||||
|
consistent with the requirements of this License, to extend the patent
|
||||||
|
license to downstream recipients. "Knowingly relying" means you have
|
||||||
|
actual knowledge that, but for the patent license, your conveying the
|
||||||
|
covered work in a country, or your recipient's use of the covered work
|
||||||
|
in a country, would infringe one or more identifiable patents in that
|
||||||
|
country that you have reason to believe are valid.
|
||||||
|
|
||||||
|
If, pursuant to or in connection with a single transaction or
|
||||||
|
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||||
|
covered work, and grant a patent license to some of the parties
|
||||||
|
receiving the covered work authorizing them to use, propagate, modify
|
||||||
|
or convey a specific copy of the covered work, then the patent license
|
||||||
|
you grant is automatically extended to all recipients of the covered
|
||||||
|
work and works based on it.
|
||||||
|
|
||||||
|
A patent license is "discriminatory" if it does not include within
|
||||||
|
the scope of its coverage, prohibits the exercise of, or is
|
||||||
|
conditioned on the non-exercise of one or more of the rights that are
|
||||||
|
specifically granted under this License. You may not convey a covered
|
||||||
|
work if you are a party to an arrangement with a third party that is
|
||||||
|
in the business of distributing software, under which you make payment
|
||||||
|
to the third party based on the extent of your activity of conveying
|
||||||
|
the work, and under which the third party grants, to any of the
|
||||||
|
parties who would receive the covered work from you, a discriminatory
|
||||||
|
patent license (a) in connection with copies of the covered work
|
||||||
|
conveyed by you (or copies made from those copies), or (b) primarily
|
||||||
|
for and in connection with specific products or compilations that
|
||||||
|
contain the covered work, unless you entered into that arrangement,
|
||||||
|
or that patent license was granted, prior to 28 March 2007.
|
||||||
|
|
||||||
|
Nothing in this License shall be construed as excluding or limiting
|
||||||
|
any implied license or other defenses to infringement that may
|
||||||
|
otherwise be available to you under applicable patent law.
|
||||||
|
|
||||||
|
12. No Surrender of Others' Freedom.
|
||||||
|
|
||||||
|
If conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot convey a
|
||||||
|
covered work so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you may
|
||||||
|
not convey it at all. For example, if you agree to terms that obligate you
|
||||||
|
to collect a royalty for further conveying from those to whom you convey
|
||||||
|
the Program, the only way you could satisfy both those terms and this
|
||||||
|
License would be to refrain entirely from conveying the Program.
|
||||||
|
|
||||||
|
13. Remote Network Interaction; Use with the GNU General Public License.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, if you modify the
|
||||||
|
Program, your modified version must prominently offer all users
|
||||||
|
interacting with it remotely through a computer network (if your version
|
||||||
|
supports such interaction) an opportunity to receive the Corresponding
|
||||||
|
Source of your version by providing access to the Corresponding Source
|
||||||
|
from a network server at no charge, through some standard or customary
|
||||||
|
means of facilitating copying of software. This Corresponding Source
|
||||||
|
shall include the Corresponding Source for any work covered by version 3
|
||||||
|
of the GNU General Public License that is incorporated pursuant to the
|
||||||
|
following paragraph.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, you have
|
||||||
|
permission to link or combine any covered work with a work licensed
|
||||||
|
under version 3 of the GNU General Public License into a single
|
||||||
|
combined work, and to convey the resulting work. The terms of this
|
||||||
|
License will continue to apply to the part which is the covered work,
|
||||||
|
but the work with which it is combined will remain governed by version
|
||||||
|
3 of the GNU General Public License.
|
||||||
|
|
||||||
|
14. Revised Versions of this License.
|
||||||
|
|
||||||
|
The Free Software Foundation may publish revised and/or new versions of
|
||||||
|
the GNU Affero General Public License from time to time. Such new versions
|
||||||
|
will be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the
|
||||||
|
Program specifies that a certain numbered version of the GNU Affero General
|
||||||
|
Public License "or any later version" applies to it, you have the
|
||||||
|
option of following the terms and conditions either of that numbered
|
||||||
|
version or of any later version published by the Free Software
|
||||||
|
Foundation. If the Program does not specify a version number of the
|
||||||
|
GNU Affero General Public License, you may choose any version ever published
|
||||||
|
by the Free Software Foundation.
|
||||||
|
|
||||||
|
If the Program specifies that a proxy can decide which future
|
||||||
|
versions of the GNU Affero General Public License can be used, that proxy's
|
||||||
|
public statement of acceptance of a version permanently authorizes you
|
||||||
|
to choose that version for the Program.
|
||||||
|
|
||||||
|
Later license versions may give you additional or different
|
||||||
|
permissions. However, no additional obligations are imposed on any
|
||||||
|
author or copyright holder as a result of your choosing to follow a
|
||||||
|
later version.
|
||||||
|
|
||||||
|
15. Disclaimer of Warranty.
|
||||||
|
|
||||||
|
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||||
|
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||||
|
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||||
|
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||||
|
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||||
|
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
16. Limitation of Liability.
|
||||||
|
|
||||||
|
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||||
|
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||||
|
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||||
|
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||||
|
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||||
|
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||||
|
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||||
|
SUCH DAMAGES.
|
||||||
|
|
||||||
|
17. Interpretation of Sections 15 and 16.
|
||||||
|
|
||||||
|
If the disclaimer of warranty and limitation of liability provided
|
||||||
|
above cannot be given local legal effect according to their terms,
|
||||||
|
reviewing courts shall apply local law that most closely approximates
|
||||||
|
an absolute waiver of all civil liability in connection with the
|
||||||
|
Program, unless a warranty or assumption of liability accompanies a
|
||||||
|
copy of the Program in return for a fee.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
state the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
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 Affero 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/>.
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If your software can interact with users remotely through a computer
|
||||||
|
network, you should also make sure that it provides a way for users to
|
||||||
|
get its source. For example, if your program is a web application, its
|
||||||
|
interface could display a "Source" link that leads users to an archive
|
||||||
|
of the code. There are many ways you could offer source, and different
|
||||||
|
solutions will be better for different programs; see section 13 for the
|
||||||
|
specific requirements.
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or school,
|
||||||
|
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||||
|
For more information on this, and how to apply and follow the GNU AGPL, see
|
||||||
|
<http://www.gnu.org/licenses/>.
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
AUTOMAKE_OPTIONS = foreign dist-bzip2 1.6
|
||||||
|
|
||||||
|
SUBDIRS = include src tests
|
||||||
|
|
||||||
|
|
||||||
|
# package the contrib and doc
|
||||||
|
EXTRA_DIST = \
|
||||||
|
contrib/dump_docs.py contrib/screenrc-l1fwd contrib/osmo-bts-sysmo.service \
|
||||||
|
contrib/l1fwd.init contrib/screenrc-sysmobts contrib/respawn.sh \
|
||||||
|
doc/examples/sysmo/osmo-bts.cfg \
|
||||||
|
doc/examples/sysmo/sysmobts-mgr.cfg \
|
||||||
|
doc/examples/virtual/openbsc-virtual.cfg \
|
||||||
|
doc/examples/virtual/osmobts-virtual.cfg \
|
||||||
|
git-version-gen .version \
|
||||||
|
README.md
|
||||||
|
|
||||||
|
@RELMAKE@
|
||||||
|
|
||||||
|
BUILT_SOURCES = $(top_srcdir)/.version
|
||||||
|
|
||||||
|
$(top_srcdir)/.version:
|
||||||
|
echo $(VERSION) > $@-t && mv $@-t $@
|
||||||
|
dist-hook:
|
||||||
|
echo $(VERSION) > $(distdir)/.tarball-version
|
||||||
@@ -0,0 +1,127 @@
|
|||||||
|
osmo-bts - Osmocom BTS Implementation
|
||||||
|
====================================
|
||||||
|
|
||||||
|
This repository contains a C-language implementation of a GSM Base
|
||||||
|
Transceiver Station (BTS). It is part of the
|
||||||
|
[Osmocom](https://osmocom.org/) Open Source Mobile Communications
|
||||||
|
project.
|
||||||
|
|
||||||
|
This code implements Layer 2 and higher of a more or less conventional GSM BTS
|
||||||
|
(Base Transceiver Station) - however, using an Abis/IP interface, rather than
|
||||||
|
the old-fashioned E1/T1.
|
||||||
|
|
||||||
|
Specifically, this includes
|
||||||
|
* BTS-side implementation of TS 08.58 (RSL) and TS 12.21 (OML)
|
||||||
|
* BTS-side implementation of LAPDm (using libosmocore/libosmogsm)
|
||||||
|
* A somewhat separated interface between those higher layer parts and the
|
||||||
|
Layer1 interface.
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
Homepage
|
||||||
|
--------
|
||||||
|
|
||||||
|
The official homepage of the project is
|
||||||
|
https://osmocom.org/projects/osmobts/wiki
|
||||||
|
|
||||||
|
GIT Repository
|
||||||
|
--------------
|
||||||
|
|
||||||
|
You can clone from the official osmo-bts.git repository using
|
||||||
|
|
||||||
|
git clone git://git.osmocom.org/osmo-bts.git
|
||||||
|
|
||||||
|
There is a cgit interface at http://git.osmocom.org/osmo-bts/
|
||||||
|
|
||||||
|
Documentation
|
||||||
|
-------------
|
||||||
|
|
||||||
|
We provide a
|
||||||
|
[User Manual](http://ftp.osmocom.org/docs/latest/osmobts-usermanual.pdf)
|
||||||
|
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)
|
||||||
|
describing the OsmoBTS specific A-bis dialect.
|
||||||
|
|
||||||
|
Mailing List
|
||||||
|
------------
|
||||||
|
|
||||||
|
Discussions related to osmo-bts are happening on the
|
||||||
|
openbsc@lists.osmocom.org mailing list, please see
|
||||||
|
https://lists.osmocom.org/mailman/listinfo/openbsc for subscription
|
||||||
|
options and the list archive.
|
||||||
|
|
||||||
|
Please observe the [Osmocom Mailing List
|
||||||
|
Rules](https://osmocom.org/projects/cellular-infrastructure/wiki/Mailing_List_Rules)
|
||||||
|
when posting.
|
||||||
|
|
||||||
|
Contributing
|
||||||
|
------------
|
||||||
|
|
||||||
|
Our coding standards are described at
|
||||||
|
https://osmocom.org/projects/cellular-infrastructure/wiki/Coding_standards
|
||||||
|
|
||||||
|
We us a gerrit based patch submission/review process for managing
|
||||||
|
contributions. Please see
|
||||||
|
https://osmocom.org/projects/cellular-infrastructure/wiki/Gerrit for
|
||||||
|
more details
|
||||||
|
|
||||||
|
The current patch queue for osmo-bts can be seen at
|
||||||
|
https://gerrit.osmocom.org/#/q/project:osmo-bts+status:open
|
||||||
|
|
||||||
|
Known Limitations
|
||||||
|
=================
|
||||||
|
|
||||||
|
As of March 17, 2017, the following known limitations exist in this
|
||||||
|
implementation:
|
||||||
|
|
||||||
|
Common Core
|
||||||
|
-----------
|
||||||
|
|
||||||
|
* No Extended BCCH support
|
||||||
|
* System Information limited to 1,2,2bis,2ter,2quater,3,4,5,6,9,13
|
||||||
|
* No RATSCCH in AMR
|
||||||
|
* Will reject TS 12.21 STARTING TIME in SET BTS ATTR / SET CHAN ATTR
|
||||||
|
* No support for frequency hopping
|
||||||
|
* No reporting of interference levels as part of TS 08.58 RF RES IND
|
||||||
|
* No error reporting in case PAGING COMMAND fails due to queue overflow
|
||||||
|
* No use of TS 08.58 BS Power and MS Power parameters
|
||||||
|
* No support of TS 08.58 MultiRate Control
|
||||||
|
* No support of TS 08.58 Supported Codec Types
|
||||||
|
* No support of Bter frame / ENHANCED MEASUREMENT REPORT
|
||||||
|
|
||||||
|
osmo-bts-sysmo
|
||||||
|
--------------
|
||||||
|
|
||||||
|
* No CSD / ECSD support (not planned)
|
||||||
|
* GSM-R frequency band supported, but no NCH/ASCI/SoLSA
|
||||||
|
* All timeslots on one TRX have to use same training sequence (TSC)
|
||||||
|
* No multi-TRX support yet, though hardware+L1 support stacking
|
||||||
|
* Makes no use of 12.21 Intave Parameters and Interference
|
||||||
|
Level Boundaries
|
||||||
|
* MphConfig.CNF can be returned to the wrong callback. E.g. with Tx Power
|
||||||
|
and ciphering. The dispatch should take a look at the hLayer3.
|
||||||
|
|
||||||
|
osmo-bts-octphy
|
||||||
|
---------------
|
||||||
|
|
||||||
|
* No support of EFR, HR voice codec (lack of PHY support?)
|
||||||
|
* No re-transmission of PHY primitives in case of time-out
|
||||||
|
* Link Quality / Measurement processing incomplete
|
||||||
|
* impossible to modify encryption parameters using RSL MODE MODIFY
|
||||||
|
* 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)
|
||||||
|
* No CBCH support (https://osmocom.org/issues/1617)
|
||||||
@@ -0,0 +1,302 @@
|
|||||||
|
dnl Process this file with autoconf to produce a configure script
|
||||||
|
AC_INIT([osmo-bts],
|
||||||
|
m4_esyscmd([./git-version-gen .tarball-version]),
|
||||||
|
[openbsc@lists.osmocom.org])
|
||||||
|
|
||||||
|
dnl *This* is the root dir, even if an install-sh exists in ../ or ../../
|
||||||
|
AC_CONFIG_AUX_DIR([.])
|
||||||
|
|
||||||
|
AM_INIT_AUTOMAKE([dist-bzip2])
|
||||||
|
AC_CONFIG_TESTDIR(tests)
|
||||||
|
|
||||||
|
dnl kernel style compile messages
|
||||||
|
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
|
||||||
|
|
||||||
|
dnl include release helper
|
||||||
|
RELMAKE='-include osmo-release.mk'
|
||||||
|
AC_SUBST([RELMAKE])
|
||||||
|
|
||||||
|
dnl checks for programs
|
||||||
|
AC_PROG_MAKE_SET
|
||||||
|
AC_PROG_CC
|
||||||
|
AC_PROG_INSTALL
|
||||||
|
LT_INIT
|
||||||
|
|
||||||
|
dnl check for pkg-config (explained in detail in libosmocore/configure.ac)
|
||||||
|
AC_PATH_PROG(PKG_CONFIG_INSTALLED, pkg-config, no)
|
||||||
|
if test "x$PKG_CONFIG_INSTALLED" = "xno"; then
|
||||||
|
AC_MSG_WARN([You need to install pkg-config])
|
||||||
|
fi
|
||||||
|
PKG_PROG_PKG_CONFIG([0.20])
|
||||||
|
|
||||||
|
dnl checks for header files
|
||||||
|
AC_HEADER_STDC
|
||||||
|
|
||||||
|
dnl Checks for typedefs, structures and compiler characteristics
|
||||||
|
|
||||||
|
AC_ARG_ENABLE(sanitize,
|
||||||
|
[AS_HELP_STRING([--enable-sanitize], [Compile with address sanitizer enabled], )],
|
||||||
|
[sanitize=$enableval], [sanitize="no"])
|
||||||
|
if test x"$sanitize" = x"yes"
|
||||||
|
then
|
||||||
|
CFLAGS="$CFLAGS -fsanitize=address -fsanitize=undefined"
|
||||||
|
CPPFLAGS="$CPPFLAGS -fsanitize=address -fsanitize=undefined"
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_ARG_ENABLE(werror,
|
||||||
|
[AS_HELP_STRING(
|
||||||
|
[--enable-werror],
|
||||||
|
[Turn all compiler warnings into errors, with exceptions:
|
||||||
|
a) deprecation (allow upstream to mark deprecation without breaking builds);
|
||||||
|
b) "#warning" pragmas (allow to remind ourselves of errors without breaking builds)
|
||||||
|
]
|
||||||
|
)],
|
||||||
|
[werror=$enableval], [werror="no"])
|
||||||
|
if test x"$werror" = x"yes"
|
||||||
|
then
|
||||||
|
WERROR_FLAGS="-Werror"
|
||||||
|
WERROR_FLAGS+=" -Wno-error=deprecated -Wno-error=deprecated-declarations"
|
||||||
|
WERROR_FLAGS+=" -Wno-error=cpp" # "#warning"
|
||||||
|
CFLAGS="$CFLAGS $WERROR_FLAGS"
|
||||||
|
CPPFLAGS="$CPPFLAGS $WERROR_FLAGS"
|
||||||
|
fi
|
||||||
|
|
||||||
|
dnl checks for libraries
|
||||||
|
PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 0.11.0)
|
||||||
|
PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 0.11.0)
|
||||||
|
PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 0.11.0)
|
||||||
|
PKG_CHECK_MODULES(LIBOSMOCTRL, libosmoctrl >= 0.11.0)
|
||||||
|
PKG_CHECK_MODULES(LIBOSMOCODEC, libosmocodec >= 0.11.0)
|
||||||
|
PKG_CHECK_MODULES(LIBOSMOCODING, libosmocoding >= 0.11.0)
|
||||||
|
PKG_CHECK_MODULES(LIBOSMOABIS, libosmoabis >= 0.5.0)
|
||||||
|
PKG_CHECK_MODULES(LIBOSMOTRAU, libosmotrau >= 0.5.0)
|
||||||
|
PKG_CHECK_MODULES(ORTP, ortp)
|
||||||
|
|
||||||
|
AC_MSG_CHECKING([whether to enable support for sysmobts calibration tool])
|
||||||
|
AC_ARG_ENABLE(sysmobts-calib,
|
||||||
|
AC_HELP_STRING([--enable-sysmobts-calib],
|
||||||
|
[enable code for sysmobts calibration tool [default=no]]),
|
||||||
|
[enable_sysmobts_calib="yes"],[enable_sysmobts_calib="no"])
|
||||||
|
AC_MSG_RESULT([$enable_sysmobts_calib])
|
||||||
|
AM_CONDITIONAL(ENABLE_SYSMOBTS_CALIB, test "x$enable_sysmobts_calib" = "xyes")
|
||||||
|
|
||||||
|
AC_MSG_CHECKING([whether to enable support for sysmoBTS L1/PHY support])
|
||||||
|
AC_ARG_ENABLE(sysmocom-bts,
|
||||||
|
AC_HELP_STRING([--enable-sysmocom-bts],
|
||||||
|
[enable code for sysmoBTS L1/PHY [default=no]]),
|
||||||
|
[enable_sysmocom_bts="yes"],[enable_sysmocom_bts="no"])
|
||||||
|
AC_ARG_WITH([sysmobts], [AS_HELP_STRING([--with-sysmobts=INCLUDE_DIR], [Location of the sysmobts API header files, implies --enable-sysmocom-bts])],
|
||||||
|
[sysmobts_incdir="$withval"],[sysmobts_incdir="$incdir"])
|
||||||
|
if test "x$sysmobts_incdir" != "x"; then
|
||||||
|
# --with-sysmobts was passed, imply enable_sysmocom_bts
|
||||||
|
enable_sysmocom_bts="yes"
|
||||||
|
fi
|
||||||
|
AC_SUBST([SYSMOBTS_INCDIR], -I$sysmobts_incdir)
|
||||||
|
AC_MSG_RESULT([$enable_sysmocom_bts])
|
||||||
|
AM_CONDITIONAL(ENABLE_SYSMOBTS, test "x$enable_sysmocom_bts" = "xyes")
|
||||||
|
if test "$enable_sysmocom_bts" = "yes"; then
|
||||||
|
oldCPPFLAGS=$CPPFLAGS
|
||||||
|
CPPFLAGS="$CPPFLAGS $SYSMOBTS_INCDIR -I$srcdir/include"
|
||||||
|
AC_CHECK_HEADER([sysmocom/femtobts/superfemto.h],[],
|
||||||
|
[AC_MSG_ERROR([sysmocom/femtobts/superfemto.h can not be found in $sysmobts_incdir])],
|
||||||
|
[#include <sysmocom/femtobts/superfemto.h>])
|
||||||
|
|
||||||
|
# Check for the sbts2050_header.h that was added after the 3.6 release
|
||||||
|
AC_CHECK_HEADER([sysmocom/femtobts/sbts2050_header.h], [sysmo_uc_header="yes"], [])
|
||||||
|
if test "$sysmo_uc_header" = "yes" ; then
|
||||||
|
AC_DEFINE(BUILD_SBTS2050, 1, [Define if we want to build SBTS2050])
|
||||||
|
fi
|
||||||
|
|
||||||
|
PKG_CHECK_MODULES(LIBGPS, libgps)
|
||||||
|
CPPFLAGS=$oldCPPFLAGS
|
||||||
|
fi
|
||||||
|
AM_CONDITIONAL(BUILD_SBTS2050, test "x$sysmo_uc_header" = "xyes")
|
||||||
|
|
||||||
|
AC_MSG_CHECKING([whether to enable support for osmo-trx based L1/PHY support])
|
||||||
|
AC_ARG_ENABLE(trx,
|
||||||
|
AC_HELP_STRING([--enable-trx],
|
||||||
|
[enable code for osmo-trx L1/PHY [default=no]]),
|
||||||
|
[enable_trx="yes"],[enable_trx="no"])
|
||||||
|
AC_MSG_RESULT([$enable_trx])
|
||||||
|
AM_CONDITIONAL(ENABLE_TRX, test "x$enable_trx" = "xyes")
|
||||||
|
|
||||||
|
AC_MSG_CHECKING([whether to enable support for Octasic OCTPHY-2G])
|
||||||
|
AC_ARG_ENABLE(octphy,
|
||||||
|
AC_HELP_STRING([--enable-octphy],
|
||||||
|
[enable code for Octasic OCTPHY-2G [default=no]]),
|
||||||
|
[enable_octphy="yes"],[enable_octphy="no"])
|
||||||
|
AC_ARG_WITH([octsdr-2g], [AS_HELP_STRING([--with-octsdr-2g], [Location of the OCTSDR-2G API header files])],
|
||||||
|
[octsdr2g_incdir="$withval"],[octsdr2g_incdir="`cd $srcdir; pwd`/src/osmo-bts-octphy/"])
|
||||||
|
AC_SUBST([OCTSDR2G_INCDIR], -I$octsdr2g_incdir)
|
||||||
|
AC_MSG_RESULT([$enable_octphy])
|
||||||
|
AM_CONDITIONAL(ENABLE_OCTPHY, test "x$enable_octphy" = "xyes")
|
||||||
|
if test "$enable_octphy" = "yes" ; then
|
||||||
|
oldCPPFLAGS=$CPPFLAGS
|
||||||
|
CPPFLAGS="$CPPFLAGS $OCTSDR2G_INCDIR -I$srcdir/include"
|
||||||
|
|
||||||
|
AC_CHECK_HEADER([octphy/octvc1/gsm/octvc1_gsm_default.h],[],
|
||||||
|
[AC_MSG_ERROR([octphy/octvc1/gsm/octvc1_gsm_default.h can not be found in $octsdr2g_incdir])],
|
||||||
|
[#include <octphy/octvc1/gsm/octvc1_gsm_default.h>])
|
||||||
|
|
||||||
|
AC_CHECK_MEMBER([tOCTVC1_GSM_TRX_CONFIG.usCentreArfcn],
|
||||||
|
AC_DEFINE([OCTPHY_MULTI_TRX],
|
||||||
|
[1],
|
||||||
|
[Define to 1 if your octphy header files support multi-trx]),
|
||||||
|
[],
|
||||||
|
[#include <octphy/octvc1/gsm/octvc1_gsm_api.h>])
|
||||||
|
|
||||||
|
AC_CHECK_MEMBER([tOCTVC1_HW_RF_PORT_RX_STATS.Frequency],
|
||||||
|
AC_DEFINE([OCTPHY_USE_FREQUENCY],
|
||||||
|
[1],
|
||||||
|
[Define to 1 if your octphy header files support tOCTVC1_RADIO_FREQUENCY_VALUE type]),
|
||||||
|
[],
|
||||||
|
[#include <octphy/octvc1/hw/octvc1_hw_api.h>])
|
||||||
|
|
||||||
|
AC_CHECK_MEMBER([tOCTVC1_HW_MSG_RF_PORT_INFO_ANTENNA_TX_CONFIG_RSP.TxConfig],
|
||||||
|
AC_DEFINE([OCTPHY_USE_TX_CONFIG],
|
||||||
|
[1],
|
||||||
|
[Define to 1 if your octphy header files support tOCTVC1_HW_RF_PORT_ANTENNA_TX_CONFIG type]),
|
||||||
|
[],
|
||||||
|
[#include <octphy/octvc1/hw/octvc1_hw_api.h>])
|
||||||
|
|
||||||
|
AC_CHECK_MEMBER([tOCTVC1_HW_MSG_RF_PORT_INFO_ANTENNA_RX_CONFIG_RSP.RxConfig],
|
||||||
|
AC_DEFINE([OCTPHY_USE_RX_CONFIG],
|
||||||
|
[1],
|
||||||
|
[Define to 1 if your octphy header files support tOCTVC1_HW_RF_PORT_ANTENNA_RX_CONFIG type]),
|
||||||
|
[],
|
||||||
|
[#include <octphy/octvc1/hw/octvc1_hw_api.h>])
|
||||||
|
|
||||||
|
AC_CHECK_MEMBER([tOCTVC1_GSM_RF_CONFIG.ulTxAntennaId],
|
||||||
|
AC_DEFINE([OCTPHY_USE_ANTENNA_ID],
|
||||||
|
[1],
|
||||||
|
[Define to 1 if your octphy header files support antenna ids in tOCTVC1_GSM_RF_CONFIG]),
|
||||||
|
[],
|
||||||
|
[#include <octphy/octvc1/gsm/octvc1_gsm_api.h>])
|
||||||
|
|
||||||
|
AC_CHECK_MEMBER([tOCTVC1_HW_MSG_CLOCK_SYNC_MGR_INFO_RSP.ulClkSourceSelection],
|
||||||
|
AC_DEFINE([OCTPHY_USE_CLK_SOURCE_SELECTION],
|
||||||
|
[1],
|
||||||
|
[Define to 1 if your octphy header files supports ulClkSourceSelection in tOCTVC1_HW_MSG_CLOCK_SYNC_MGR_INFO_RSP]),
|
||||||
|
[],
|
||||||
|
[#include <octphy/octvc1/hw/octvc1_hw_api.h>])
|
||||||
|
|
||||||
|
AC_CHECK_MEMBER([tOCTVC1_HW_MSG_CLOCK_SYNC_MGR_STATS_RSP.lClockError],
|
||||||
|
AC_DEFINE([OCTPHY_USE_CLOCK_SYNC_MGR_STATS_CLOCK_ERROR],
|
||||||
|
[1],
|
||||||
|
[Define to 1 if your octphy header files supports lClockError in tOCTVC1_HW_MSG_CLOCK_SYNC_MGR_STATS_RSP]),
|
||||||
|
[],
|
||||||
|
[#include <octphy/octvc1/hw/octvc1_hw_api.h>])
|
||||||
|
|
||||||
|
AC_CHECK_MEMBER([tOCTVC1_HW_MSG_CLOCK_SYNC_MGR_STATS_RSP.lDroppedCycles],
|
||||||
|
AC_DEFINE([OCTPHY_USE_CLOCK_SYNC_MGR_STATS_DROPPED_CYCLES],
|
||||||
|
[1],
|
||||||
|
[Define to 1 if your octphy header files supports lDroppedCycles in tOCTVC1_HW_MSG_CLOCK_SYNC_MGR_STATS_RSP]),
|
||||||
|
[],
|
||||||
|
[#include <octphy/octvc1/hw/octvc1_hw_api.h>])
|
||||||
|
|
||||||
|
AC_CHECK_MEMBER([tOCTVC1_HW_MSG_CLOCK_SYNC_MGR_STATS_RSP.ulPllFreqHz],
|
||||||
|
AC_DEFINE([OCTPHY_USE_CLOCK_SYNC_MGR_STATS_PLL_FREQ_HZ],
|
||||||
|
[1],
|
||||||
|
[Define to 1 if your octphy header files supports ulPllFreqHz in tOCTVC1_HW_MSG_CLOCK_SYNC_MGR_STATS_RSP]),
|
||||||
|
[],
|
||||||
|
[#include <octphy/octvc1/hw/octvc1_hw_api.h>])
|
||||||
|
|
||||||
|
AC_CHECK_MEMBER([tOCTVC1_HW_MSG_CLOCK_SYNC_MGR_STATS_RSP.ulPllFractionalFreqHz],
|
||||||
|
AC_DEFINE([OCTPHY_USE_CLOCK_SYNC_MGR_STATS_PLL_FRACTIONAL_FREQ_HZ],
|
||||||
|
[1],
|
||||||
|
[Define to 1 if your octphy header files supports ulPllFractionalFreqHz in tOCTVC1_HW_MSG_CLOCK_SYNC_MGR_STATS_RSP]),
|
||||||
|
[],
|
||||||
|
[#include <octphy/octvc1/hw/octvc1_hw_api.h>])
|
||||||
|
|
||||||
|
AC_CHECK_MEMBER([tOCTVC1_HW_MSG_CLOCK_SYNC_MGR_STATS_RSP.ulSlipCnt],
|
||||||
|
AC_DEFINE([OCTPHY_USE_CLOCK_SYNC_MGR_STATS_SLIP_CNT],
|
||||||
|
[1],
|
||||||
|
[Define to 1 if your octphy header files supports ulSlipCnt in tOCTVC1_HW_MSG_CLOCK_SYNC_MGR_STATS_RSP]),
|
||||||
|
[],
|
||||||
|
[#include <octphy/octvc1/hw/octvc1_hw_api.h>])
|
||||||
|
|
||||||
|
AC_CHECK_MEMBER([tOCTVC1_HW_MSG_CLOCK_SYNC_MGR_STATS_RSP.ulSyncLosseCnt],
|
||||||
|
AC_DEFINE([OCTPHY_USE_CLOCK_SYNC_MGR_STATS_SYNC_LOSSE_CNT],
|
||||||
|
[1],
|
||||||
|
[Define to 1 if your octphy header files supports ulSyncLosseCnt in tOCTVC1_HW_MSG_CLOCK_SYNC_MGR_STATS_RSP]),
|
||||||
|
[],
|
||||||
|
[#include <octphy/octvc1/hw/octvc1_hw_api.h>])
|
||||||
|
|
||||||
|
AC_CHECK_MEMBER([tOCTVC1_HW_MSG_CLOCK_SYNC_MGR_STATS_RSP.ulSyncLossCnt],
|
||||||
|
AC_DEFINE([OCTPHY_USE_CLOCK_SYNC_MGR_STATS_SYNC_LOSS_CNT],
|
||||||
|
[1],
|
||||||
|
[Define to 1 if your octphy header files supports ulSyncLossCnt in tOCTVC1_HW_MSG_CLOCK_SYNC_MGR_STATS_RSP]),
|
||||||
|
[],
|
||||||
|
[#include <octphy/octvc1/hw/octvc1_hw_api.h>])
|
||||||
|
|
||||||
|
AC_CHECK_MEMBER([tOCTVC1_HW_MSG_CLOCK_SYNC_MGR_STATS_RSP.ulSourceState],
|
||||||
|
AC_DEFINE([OCTPHY_USE_CLOCK_SYNC_MGR_STATS_SOURCE_STATE],
|
||||||
|
[1],
|
||||||
|
[Define to 1 if your octphy header files supports ulSourceState in tOCTVC1_HW_MSG_CLOCK_SYNC_MGR_STATS_RSP]),
|
||||||
|
[],
|
||||||
|
[#include <octphy/octvc1/hw/octvc1_hw_api.h>])
|
||||||
|
|
||||||
|
AC_CHECK_MEMBER([tOCTVC1_HW_MSG_CLOCK_SYNC_MGR_STATS_RSP.ulDacState],
|
||||||
|
AC_DEFINE([OCTPHY_USE_CLOCK_SYNC_MGR_STATS_DAC_STATE],
|
||||||
|
[1],
|
||||||
|
[Define to 1 if your octphy header files supports ulDacState in tOCTVC1_HW_MSG_CLOCK_SYNC_MGR_STATS_RSP]),
|
||||||
|
[],
|
||||||
|
[#include <octphy/octvc1/hw/octvc1_hw_api.h>])
|
||||||
|
|
||||||
|
AC_CHECK_MEMBER([tOCTVC1_HW_MSG_CLOCK_SYNC_MGR_STATS_RSP.ulDriftElapseTimeUs],
|
||||||
|
AC_DEFINE([OCTPHY_USE_CLOCK_SYNC_MGR_STATS_DRIFT_ELAPSE_TIME_US],
|
||||||
|
[1],
|
||||||
|
[Define to 1 if your octphy header files supports ulDriftElapseTimeUs in tOCTVC1_HW_MSG_CLOCK_SYNC_MGR_STATS_RSP]),
|
||||||
|
[],
|
||||||
|
[#include <octphy/octvc1/hw/octvc1_hw_api.h>])
|
||||||
|
|
||||||
|
CPPFLAGS=$oldCPPFLAGS
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_MSG_CHECKING([whether to enable NuRAN Wireless Litecell 1.5 hardware support])
|
||||||
|
AC_ARG_ENABLE(litecell15,
|
||||||
|
AC_HELP_STRING([--enable-litecell15],
|
||||||
|
[enable code for NuRAN Wireless Litecell15 bts [default=no]]),
|
||||||
|
[enable_litecell15="yes"],[enable_litecell15="no"])
|
||||||
|
AC_ARG_WITH([litecell15], [AS_HELP_STRING([--with-litecell15=INCLUDE_DIR], [Location of the litecell 1.5 API header files])],
|
||||||
|
[litecell15_incdir="$withval"],[litecell15_incdir="$incdir"])
|
||||||
|
AC_SUBST([LITECELL15_INCDIR], -I$litecell15_incdir)
|
||||||
|
AC_MSG_RESULT([$enable_litecell15])
|
||||||
|
AM_CONDITIONAL(ENABLE_LC15BTS, test "x$enable_litecell15" = "xyes")
|
||||||
|
if test "$enable_litecell15" = "yes"; then
|
||||||
|
oldCPPFLAGS=$CPPFLAGS
|
||||||
|
CPPFLAGS="$CPPFLAGS $LITECELL15_INCDIR -I$srcdir/include"
|
||||||
|
AC_CHECK_HEADER([nrw/litecell15/litecell15.h],[],
|
||||||
|
[AC_MSG_ERROR([nrw/litecell15/litecell15.h can not be found in $litecell15_incdir])],
|
||||||
|
[#include <nrw/litecell15/litecell15.h>])
|
||||||
|
PKG_CHECK_MODULES(LIBSYSTEMD, libsystemd)
|
||||||
|
CPPFLAGS=$oldCPPFLAGS
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_MSG_RESULT([CFLAGS="$CFLAGS"])
|
||||||
|
AC_MSG_RESULT([CPPFLAGS="$CPPFLAGS"])
|
||||||
|
|
||||||
|
AM_CONFIG_HEADER(btsconfig.h)
|
||||||
|
|
||||||
|
AC_OUTPUT(
|
||||||
|
src/Makefile
|
||||||
|
src/common/Makefile
|
||||||
|
src/osmo-bts-virtual/Makefile
|
||||||
|
src/osmo-bts-omldummy/Makefile
|
||||||
|
src/osmo-bts-sysmo/Makefile
|
||||||
|
src/osmo-bts-litecell15/Makefile
|
||||||
|
src/osmo-bts-trx/Makefile
|
||||||
|
src/osmo-bts-octphy/Makefile
|
||||||
|
include/Makefile
|
||||||
|
include/osmo-bts/Makefile
|
||||||
|
tests/Makefile
|
||||||
|
tests/paging/Makefile
|
||||||
|
tests/agch/Makefile
|
||||||
|
tests/cipher/Makefile
|
||||||
|
tests/sysmobts/Makefile
|
||||||
|
tests/misc/Makefile
|
||||||
|
tests/handover/Makefile
|
||||||
|
tests/tx_power/Makefile
|
||||||
|
tests/power/Makefile
|
||||||
|
tests/meas/Makefile
|
||||||
|
Makefile)
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
#!/usr/bin/gawk -f
|
||||||
|
|
||||||
|
# Expected input format: FN TYPE
|
||||||
|
|
||||||
|
BEGIN {
|
||||||
|
DELTA = 0
|
||||||
|
ERR = 0
|
||||||
|
FORCE = 0
|
||||||
|
FN = 0
|
||||||
|
SILENCE = 0
|
||||||
|
TYPE = ""
|
||||||
|
CHK = ""
|
||||||
|
U_MAX = 8 * 20 + 120 / 26
|
||||||
|
U_MIN = 8 * 20 - 120 / 26
|
||||||
|
F_MAX = 3 * 20 + 120 / 26
|
||||||
|
F_MIN = 3 * 20 - 120 / 26
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
if (NR > 2) { # we have data from previous record to compare to
|
||||||
|
DELTA = ($1 - FN) * 120 / 26
|
||||||
|
CHK = "OK"
|
||||||
|
if ("FACCH" == $2 && "ONSET" == TYPE) { # ONSET due to FACCH is NOT a talkspurt
|
||||||
|
SILENCE = 1
|
||||||
|
}
|
||||||
|
if (("UPDATE" == TYPE || "FIRST" == TYPE) && ("FACCH" == $2 || "SPEECH" == $2)) { # check for missing ONSET:
|
||||||
|
CHK = "FAIL: missing ONSET (" $2 ") after " TYPE "."
|
||||||
|
ERR++
|
||||||
|
}
|
||||||
|
if ("SID_P1" == $2) {
|
||||||
|
CHK = "FAIL: regular AMR payload with FT SID and STI=0 (should be either pyaload Update or STI=1)."
|
||||||
|
ERR++
|
||||||
|
}
|
||||||
|
if ("FORCED_FIRST" == $2 || "FORCED_NODATA" == $2 || "FORCED_F_P2" == $2 || "FORCED_F_INH" == $2 || "FORCED_U_INH" == $2) {
|
||||||
|
CHK = "FAIL: event " $2 " inserted by DSP."
|
||||||
|
FORCE++
|
||||||
|
ERR++
|
||||||
|
}
|
||||||
|
if ("FIRST_P2" != $2 && "FIRST_P1" == TYPE) {
|
||||||
|
CHK = "FAIL: " TYPE " followed by " $2 " instead of P2."
|
||||||
|
ERR++
|
||||||
|
}
|
||||||
|
if ("FIRST" == $2 && "FIRST" == TYPE) {
|
||||||
|
CHK = "FAIL: multiple SID FIRST in a row."
|
||||||
|
ERR++
|
||||||
|
}
|
||||||
|
if ("OK" == CHK && "ONSET" != $2) { # check inter-SID distances:
|
||||||
|
if ("UPDATE" == TYPE) {
|
||||||
|
if (DELTA > U_MAX) {
|
||||||
|
CHK = "FAIL: delta (" $1 - FN "fn) from previous SID UPDATE (@" FN ") too big " DELTA "ms > " U_MAX "ms."
|
||||||
|
ERR++
|
||||||
|
}
|
||||||
|
if ("UPDATE" == $2 && DELTA < U_MIN) {
|
||||||
|
CHK = "FAIL: delta (" $1 - FN "fn) from previous SID UPDATE (@" FN ") too small " DELTA "ms < " U_MIN "ms."
|
||||||
|
ERR++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ("FIRST" == TYPE) {
|
||||||
|
if (DELTA > F_MAX) {
|
||||||
|
CHK = "FAIL: delta (" $1 - FN "fn) from previous SID FIRST (@" FN ") too big " DELTA "ms > " F_MAX "ms."
|
||||||
|
ERR++
|
||||||
|
}
|
||||||
|
if ("UPDATE" == $2 && DELTA < F_MIN) {
|
||||||
|
CHK = "FAIL: delta (" $1 - FN "fn) from previous SID UPDATE (@" FN ") too small " DELTA "ms < " F_MIN "ms."
|
||||||
|
ERR++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ("FACCH" == TYPE && "FIRST" != $2 && "FACCH" != $2 && 1 == SILENCE) { # check FACCH handling
|
||||||
|
CHK = "FAIL: incorrect silence resume with " $2 " after FACCH."
|
||||||
|
ERR++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ("SPEECH" == $2 || "ONSET" == $2) { # talkspurt
|
||||||
|
SILENCE = 0
|
||||||
|
}
|
||||||
|
if ("UPDATE" == $2 || "FIRST" == $2) { # silence
|
||||||
|
SILENCE = 1
|
||||||
|
}
|
||||||
|
print $1, $2, CHK
|
||||||
|
if ($2 != "EMPTY") { # skip over EMPTY records
|
||||||
|
TYPE = $2
|
||||||
|
FN = $1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
END {
|
||||||
|
print "Check completed: found " ERR " errors (" FORCE " events inserted by DSP) in " NR " records."
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
"""
|
||||||
|
Start the process and dump the documentation to the doc dir
|
||||||
|
"""
|
||||||
|
|
||||||
|
import socket, subprocess, time,os
|
||||||
|
|
||||||
|
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,
|
||||||
|
stdin=None, stdout=None)
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
try:
|
||||||
|
sck = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
sck.setblocking(1)
|
||||||
|
sck.connect(("localhost", 4241))
|
||||||
|
sck.recv(4096)
|
||||||
|
|
||||||
|
# Now send the command
|
||||||
|
sck.send("show online-help\r")
|
||||||
|
xml = ""
|
||||||
|
while True:
|
||||||
|
data = sck.recv(4096)
|
||||||
|
xml = "%s%s" % (xml, data)
|
||||||
|
if data.endswith('\r\nOsmoBTS> '):
|
||||||
|
break
|
||||||
|
|
||||||
|
# Now write everything until the end to the file
|
||||||
|
out = open('doc/vty_reference.xml', 'w')
|
||||||
|
out.write(xml[18:-11])
|
||||||
|
out.close()
|
||||||
|
finally:
|
||||||
|
# Clean-up
|
||||||
|
bts_proc.kill()
|
||||||
|
bts_proc.wait()
|
||||||
|
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
/* GPLv3+ to read sysmobts-v2 revD or later EEPROM from userspace */
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
|
||||||
|
#include <linux/i2c.h>
|
||||||
|
#include <linux/i2c-dev.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
|
/* Can read a 16bit at24 eeprom with 8192 byte in storage (24c64) */
|
||||||
|
static int dump_eeprom(int fd, int out)
|
||||||
|
{
|
||||||
|
#define STEP 8192
|
||||||
|
#define SIZE 8192
|
||||||
|
uint8_t buf[STEP + 2];
|
||||||
|
int rc = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < SIZE; i += STEP) {
|
||||||
|
/* write the address */
|
||||||
|
buf[0] = i >> 8;
|
||||||
|
buf[1] = i;
|
||||||
|
rc = write(fd, buf, 2);
|
||||||
|
if (rc != 2) {
|
||||||
|
fprintf(stderr, "writing address failed: %d/%d/%s\n", rc, errno, strerror(errno));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* execute step amount of reads */
|
||||||
|
rc = read(fd, buf, STEP);
|
||||||
|
if (rc != STEP) {
|
||||||
|
fprintf(stderr, "Failed to read: %d/%d/%s\n", rc, errno, strerror(errno));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
write(out, buf, STEP);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int i2c_fd, out_fd;
|
||||||
|
char *filename = "/dev/i2c-1";
|
||||||
|
char *out_file = "eeprom.out";
|
||||||
|
int addr = 0x50;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
i2c_fd = open(filename, O_RDWR);
|
||||||
|
if (i2c_fd < 0) {
|
||||||
|
fprintf(stderr, "Failed to open i2c device %d/%d/%s\n",
|
||||||
|
i2c_fd, errno, strerror(errno));
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* force using that address it is already bound with a driver */
|
||||||
|
rc = ioctl(i2c_fd, I2C_SLAVE_FORCE, addr);
|
||||||
|
if (rc < 0) {
|
||||||
|
fprintf(stderr, "Failed to claim i2c device %d/%d/%s\n",
|
||||||
|
rc, errno, strerror(errno));
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argc >= 2)
|
||||||
|
out_file = argv[1];
|
||||||
|
out_fd = open(out_file, O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
||||||
|
if (out_fd < 0) {
|
||||||
|
fprintf(stderr, "Failed to open out device %s %d/%d/%s\n",
|
||||||
|
out_file, rc, errno, strerror(errno));
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dump_eeprom(i2c_fd, out_fd) != 0) {
|
||||||
|
unlink(out_file);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# this is a dispatcher script which will call the bts-model-specific
|
||||||
|
# script based on the bts model specified as command line argument
|
||||||
|
|
||||||
|
bts_model="$1"
|
||||||
|
|
||||||
|
if [ "x$bts_model" = "x" ]; then
|
||||||
|
echo "Error: You have to specify the BTS model as first argument, e.g. $0 sysmo"
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -d "./contrib" ]; then
|
||||||
|
echo "Run ./contrib/jenkins_bts_model.sh from the root of the osmo-bts tree"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
set -x -e
|
||||||
|
|
||||||
|
case "$bts_model" in
|
||||||
|
|
||||||
|
sysmo)
|
||||||
|
./contrib/jenkins_sysmobts.sh
|
||||||
|
;;
|
||||||
|
|
||||||
|
oct)
|
||||||
|
./contrib/jenkins_oct.sh
|
||||||
|
;;
|
||||||
|
|
||||||
|
lc15)
|
||||||
|
./contrib/jenkins_lc15.sh
|
||||||
|
;;
|
||||||
|
|
||||||
|
trx)
|
||||||
|
./contrib/jenkins_bts_trx.sh
|
||||||
|
;;
|
||||||
|
|
||||||
|
oct+trx)
|
||||||
|
./contrib/jenkins_oct_and_bts_trx.sh
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
set +x
|
||||||
|
echo "Unknown BTS model '$bts_model'"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# jenkins build helper script for osmo-bts-trx
|
||||||
|
|
||||||
|
# shellcheck source=contrib/jenkins_common.sh
|
||||||
|
. $(dirname "$0")/jenkins_common.sh
|
||||||
|
|
||||||
|
export PKG_CONFIG_PATH="$inst/lib/pkgconfig:$PKG_CONFIG_PATH"
|
||||||
|
export LD_LIBRARY_PATH="$inst/lib"
|
||||||
|
|
||||||
|
osmo-build-dep.sh libosmocore "" --disable-doxygen
|
||||||
|
|
||||||
|
osmo-build-dep.sh libosmo-abis
|
||||||
|
|
||||||
|
cd "$deps"
|
||||||
|
|
||||||
|
configure_flags="\
|
||||||
|
--with-osmo-pcu=$deps/osmo-pcu/include \
|
||||||
|
--enable-trx \
|
||||||
|
--enable-sanitize \
|
||||||
|
"
|
||||||
|
|
||||||
|
build_bts "osmo-bts-trx" "$configure_flags"
|
||||||
|
|
||||||
|
osmo-clean-workspace.sh
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# this is a common helper script that is shared among all BTS model
|
||||||
|
# specific helper scripts like jenkins_sysmobts.sh. You shouldn't call
|
||||||
|
# this directly, but rather indirectly via the bts-specific scripts
|
||||||
|
|
||||||
|
if ! [ -x "$(command -v osmo-deps.sh)" ]; then
|
||||||
|
echo "Error: We need to have scripts/osmo-deps.sh from http://git.osmocom.org/osmo-ci/ in PATH !"
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
set -ex
|
||||||
|
|
||||||
|
base="$PWD"
|
||||||
|
deps="$base/deps"
|
||||||
|
inst="$deps/install"
|
||||||
|
|
||||||
|
export deps inst
|
||||||
|
|
||||||
|
osmo-clean-workspace.sh
|
||||||
|
|
||||||
|
mkdir -p "$deps"
|
||||||
|
|
||||||
|
verify_value_string_arrays_are_terminated.py $(find . -name "*.[hc]")
|
||||||
|
|
||||||
|
# generic project build function, usage:
|
||||||
|
# build "PROJECT-NAME" "CONFIGURE OPTIONS"
|
||||||
|
build_bts() {
|
||||||
|
set +x
|
||||||
|
echo
|
||||||
|
echo
|
||||||
|
echo
|
||||||
|
echo " =============================== $1 ==============================="
|
||||||
|
echo
|
||||||
|
set -x
|
||||||
|
|
||||||
|
cd $deps
|
||||||
|
osmo-deps.sh libosmocore
|
||||||
|
cd $base
|
||||||
|
shift
|
||||||
|
conf_flags="$*"
|
||||||
|
autoreconf --install --force
|
||||||
|
./configure $conf_flags
|
||||||
|
$MAKE $PARALLEL_MAKE
|
||||||
|
$MAKE check || cat-testlogs.sh
|
||||||
|
DISTCHECK_CONFIGURE_FLAGS="$conf_flags" $MAKE distcheck || cat-testlogs.sh
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# jenkins build helper script for osmo-bts-lc15
|
||||||
|
|
||||||
|
# shellcheck source=contrib/jenkins_common.sh
|
||||||
|
. $(dirname "$0")/jenkins_common.sh
|
||||||
|
|
||||||
|
osmo-build-dep.sh libosmocore "" --disable-doxygen
|
||||||
|
|
||||||
|
export PKG_CONFIG_PATH="$inst/lib/pkgconfig:$PKG_CONFIG_PATH"
|
||||||
|
export LD_LIBRARY_PATH="$inst/lib"
|
||||||
|
|
||||||
|
osmo-build-dep.sh libosmo-abis
|
||||||
|
|
||||||
|
cd "$deps"
|
||||||
|
osmo-layer1-headers.sh lc15 "$FIRMWARE_VERSION"
|
||||||
|
|
||||||
|
configure_flags="--enable-sanitize --with-litecell15=$deps/layer1-headers/inc/ --enable-litecell15"
|
||||||
|
|
||||||
|
build_bts "osmo-bts-lc15" "$configure_flags"
|
||||||
|
|
||||||
|
osmo-clean-workspace.sh
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# jenkins build helper script for osmo-bts-octphy
|
||||||
|
|
||||||
|
# shellcheck source=contrib/jenkins_common.sh
|
||||||
|
. $(dirname "$0")/jenkins_common.sh
|
||||||
|
|
||||||
|
osmo-build-dep.sh libosmocore "" --disable-doxygen
|
||||||
|
|
||||||
|
export PKG_CONFIG_PATH="$inst/lib/pkgconfig:$PKG_CONFIG_PATH"
|
||||||
|
export LD_LIBRARY_PATH="$inst/lib"
|
||||||
|
|
||||||
|
osmo-build-dep.sh libosmo-abis
|
||||||
|
|
||||||
|
cd "$deps"
|
||||||
|
osmo-layer1-headers.sh oct "$FIRMWARE_VERSION"
|
||||||
|
|
||||||
|
configure_flags="--enable-sanitize --with-octsdr-2g=$deps/layer1-headers/ --enable-octphy"
|
||||||
|
|
||||||
|
build_bts "osmo-bts-octphy" "$configure_flags"
|
||||||
|
|
||||||
|
osmo-clean-workspace.sh
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# jenkins build helper script for osmo-bts-octphy + osmo-bts-trx
|
||||||
|
|
||||||
|
# shellcheck source=contrib/jenkins_common.sh
|
||||||
|
. $(dirname "$0")/jenkins_common.sh
|
||||||
|
|
||||||
|
export PKG_CONFIG_PATH="$inst/lib/pkgconfig:$PKG_CONFIG_PATH"
|
||||||
|
export LD_LIBRARY_PATH="$inst/lib"
|
||||||
|
|
||||||
|
osmo-build-dep.sh libosmocore "" --disable-doxygen
|
||||||
|
|
||||||
|
osmo-build-dep.sh libosmo-abis
|
||||||
|
|
||||||
|
cd "$deps"
|
||||||
|
|
||||||
|
osmo-layer1-headers.sh oct "$FIRMWARE_VERSION"
|
||||||
|
|
||||||
|
configure_flags="\
|
||||||
|
--with-osmo-pcu=$deps/osmo-pcu/include \
|
||||||
|
--with-octsdr-2g=$deps/layer1-headers/ \
|
||||||
|
--enable-octphy \
|
||||||
|
--enable-trx \
|
||||||
|
"
|
||||||
|
|
||||||
|
build_bts "osmo-bts-octphy+trx" "$configure_flags"
|
||||||
|
|
||||||
|
osmo-clean-workspace.sh
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# jenkins build helper script for osmo-bts-sysmo
|
||||||
|
|
||||||
|
# shellcheck source=contrib/jenkins_common.sh
|
||||||
|
. $(dirname "$0")/jenkins_common.sh
|
||||||
|
|
||||||
|
osmo-build-dep.sh libosmocore "" --disable-doxygen
|
||||||
|
|
||||||
|
export PKG_CONFIG_PATH="$inst/lib/pkgconfig:$PKG_CONFIG_PATH"
|
||||||
|
export LD_LIBRARY_PATH="$inst/lib"
|
||||||
|
|
||||||
|
osmo-build-dep.sh libosmo-abis
|
||||||
|
|
||||||
|
cd "$deps"
|
||||||
|
osmo-layer1-headers.sh sysmo "$FIRMWARE_VERSION"
|
||||||
|
mkdir -p "$inst/include/sysmocom/femtobts"
|
||||||
|
ln -s $deps/layer1-headers/include/* "$inst/include/sysmocom/femtobts/"
|
||||||
|
|
||||||
|
configure_flags="--enable-sanitize --enable-sysmocom-bts --with-sysmobts=$inst/include/"
|
||||||
|
|
||||||
|
# This will not work for the femtobts
|
||||||
|
if [ $FIRMWARE_VERSION != "femtobts_v2.7" ]; then
|
||||||
|
configure_flags="$configure_flags --enable-sysmobts-calib"
|
||||||
|
fi
|
||||||
|
|
||||||
|
build_bts "osmo-bts-sysmo" "$configure_flags"
|
||||||
|
|
||||||
|
osmo-clean-workspace.sh
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
#!/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
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=osmo-bts manager for LC15 / sysmoBTS 2100
|
||||||
|
After=lc15-sysdev-remap.service
|
||||||
|
Wants=lc15-sysdev-remap.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
NotifyAccess=all
|
||||||
|
WatchdogSec=21780s
|
||||||
|
Restart=always
|
||||||
|
RestartSec=2
|
||||||
|
|
||||||
|
# Make sure directories and symbolic link exist
|
||||||
|
ExecStartPre=/bin/sh -c 'test -d /mnt/storage/var/run/lc15bts-mgr || mkdir -p /mnt/storage/var/run/lc15bts-mgr ; test -d /var/run/lc15bts-mgr || ln -sf /mnt/storage/var/run/lc15bts-mgr/ /var/run'
|
||||||
|
# Make sure BTS operation hour exist
|
||||||
|
ExecStartPre=/bin/sh -c 'test -f /mnt/storage/var/run/lc15bts-mgr/hours-running || echo 0 > /mnt/storage/var/run/lc15bts-mgr/hours-running'
|
||||||
|
# Shutdown all PA correctly
|
||||||
|
ExecStartPre=/bin/sh -c 'echo disabled > /var/lc15/pa-state/pa0/state; echo disabled > /var/lc15/pa-state/pa1/state'
|
||||||
|
ExecStartPre=/bin/sh -c 'echo 0 > /var/lc15/pa-supply/max_microvolts; echo 0 > /var/lc15/pa-supply/min_microvolts'
|
||||||
|
|
||||||
|
ExecStart=/usr/bin/lc15bts-mgr -s -c /etc/osmocom/lc15bts-mgr.cfg
|
||||||
|
|
||||||
|
# Shutdown all PA correctly
|
||||||
|
ExecStopPost=/bin/sh -c 'echo disabled > /var/lc15/pa-state/pa0/state; echo disabled > /var/lc15/pa-state/pa1/state'
|
||||||
|
ExecStopPost=/bin/sh -c 'echo 0 > /var/lc15/pa-supply/max_microvolts; echo 0 > /var/lc15/pa-supply/min_microvolts'
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
Alias=osmo-bts-mgr.service
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
[Unit]
|
||||||
|
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.cfg -M
|
||||||
|
ExecStopPost=/bin/sh -c 'echo 1 > /sys/class/leds/usr0/brightness'
|
||||||
|
ExecStopPost=/bin/sh -c 'echo 0 > /sys/class/leds/usr1/brightness'
|
||||||
|
Restart=always
|
||||||
|
RestartSec=2
|
||||||
|
RestartPreventExitStatus=1
|
||||||
|
|
||||||
|
# The msg queues must be read fast enough
|
||||||
|
CPUSchedulingPolicy=rr
|
||||||
|
CPUSchedulingPriority=1
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
Alias=osmo-bts.service
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=osmo-bts for sysmocom sysmoBTS
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
ExecStartPre=/bin/sh -c 'echo 0 > /sys/class/leds/activity_led/brightness'
|
||||||
|
ExecStart=/usr/bin/osmo-bts-sysmo -s -c /etc/osmocom/osmo-bts.cfg -M
|
||||||
|
ExecStopPost=/bin/sh -c 'echo 0 > /sys/class/leds/activity_led/brightness'
|
||||||
|
ExecStopPost=/bin/sh -c 'cat /lib/firmware/sysmobts-v?.bit > /dev/fpgadl_par0 ; sleep 3s; cat /lib/firmware/sysmobts-v?.out > /dev/dspdl_dm644x_0; sleep 1s'
|
||||||
|
Restart=always
|
||||||
|
RestartSec=2
|
||||||
|
RestartPreventExitStatus=1
|
||||||
|
|
||||||
|
# The msg queues must be read fast enough
|
||||||
|
CPUSchedulingPolicy=rr
|
||||||
|
CPUSchedulingPriority=1
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
Alias=sysmobts.service
|
||||||
|
Alias=osmo-bts.service
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
#!/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
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
#!/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
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
chdir /tmp
|
||||||
|
screen -t BTS 0 /etc/osmocom/respawn.sh /usr/bin/l1fwd-proxy
|
||||||
|
detach
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
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
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
#!/usr/bin/gawk -f
|
||||||
|
|
||||||
|
# Usage example:
|
||||||
|
# tshark -2 -t r -E 'header=n' -E 'separator=,' -E 'quote=n' -T fields -e gsmtap.frame_nr -e gsmtap.ts -e gsmtap.arfcn -e _ws.col.Info -Y 'gsmtap' -r test.pcapng.gz | grep Information | env ARFCN=878 ./si_check.gawk
|
||||||
|
# read summary on number of bis/ter messages and adjust BT_BOTH and BT_NONE environment variables accordingly
|
||||||
|
|
||||||
|
BEGIN {
|
||||||
|
FS = ","
|
||||||
|
FAILED = 0
|
||||||
|
IGNORE = 0
|
||||||
|
BIS = 0
|
||||||
|
TER = 0
|
||||||
|
QUA = 0
|
||||||
|
BT_BOTH = ENVIRON["BOTH"]
|
||||||
|
BT_NONE = ENVIRON["NONE"]
|
||||||
|
TC_INDEX = 0
|
||||||
|
TC4[4] = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
{ # expected .csv input as follows: gsmtap.frame_nr,gsmtap.ts,gsmtap.arfcn,_ws.col.Info
|
||||||
|
if ("ARFCN" in ENVIRON) { # ARFCN filtering is enabled
|
||||||
|
if (ENVIRON["ARFCN"] != $3) { # ignore other ARFCNs
|
||||||
|
IGNORE++
|
||||||
|
next
|
||||||
|
}
|
||||||
|
}
|
||||||
|
type = get_si_type($4)
|
||||||
|
tc = get_tc($1)
|
||||||
|
result = "FAIL"
|
||||||
|
|
||||||
|
if (1 == check_si_tc(tc, type)) { result = "OK" }
|
||||||
|
else { FAILED++ }
|
||||||
|
|
||||||
|
if (4 == tc) {
|
||||||
|
TC4[TC_INDEX] = type
|
||||||
|
TC_INDEX = int((TC_INDEX + 1) % 4)
|
||||||
|
if (0 == check_tc4c(type) && "OK" == result) {
|
||||||
|
result = "FAIL"
|
||||||
|
FAILED++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (type == "2bis") { BIS++ }
|
||||||
|
if (type == "2ter") { TER++ }
|
||||||
|
if (type == "2quater") { QUA++ }
|
||||||
|
# for (i in TC4) print TC4[i] # debugging
|
||||||
|
printf "ARFCN=%d FN=%d TS=%d TC=%d TYPE=%s %s\n", $3, $1, $2, tc, type, result
|
||||||
|
}
|
||||||
|
|
||||||
|
END {
|
||||||
|
printf "check completed: total %d, failed %d, ignored %d, ok %d\nSI2bis = %d, SI2ter = %d, SI2quater = %d\n", NR, FAILED, IGNORE, NR - FAILED - IGNORE, BIS, TER, QUA
|
||||||
|
if ((BIS > 0 || TER > 0) && BT_NONE) { printf "please re-run with correct environment: unset 'NONE' variable\n" }
|
||||||
|
if ((BIS > 0 && TER > 0) && !BT_BOTH) { printf "please re-run with correct environment: set 'BOTH' variable\n" }
|
||||||
|
}
|
||||||
|
|
||||||
|
func get_si_type(s, x) { # we rely on format of Info column in wireshark output - if it's changed we're screwed
|
||||||
|
return x[split(s, x, " ")]
|
||||||
|
}
|
||||||
|
|
||||||
|
func get_tc(f) { # N. B: all numbers in awk are float
|
||||||
|
return int(int(f / 51) % 8)
|
||||||
|
}
|
||||||
|
|
||||||
|
func check_tc4c(si, count) { # check for "once in 4 consecutive occurrences" rule
|
||||||
|
count = 0
|
||||||
|
if ("2quater" != si || "2ter" != si) { return 1 } # rules is not applicable to other types
|
||||||
|
if (BT_NONE && "2quater" == si) { return 0 } # should be on TC=5 instead
|
||||||
|
if (!BT_BOTH && "2ter" == si) { return 0 } # should be on TC=5 instead
|
||||||
|
if (0 in TC4 && 1 in TC4 && 2 in TC4 && 3 in TC4) { # only check if we have 4 consecutive occurrences already
|
||||||
|
if (si == TC4[0]) { count++ }
|
||||||
|
if (si == TC4[1]) { count++ }
|
||||||
|
if (si == TC4[2]) { count++ }
|
||||||
|
if (si == TC4[3]) { count++ }
|
||||||
|
if (0 == count) { return 0 }
|
||||||
|
}
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func check_si_tc(tc, si) { # check that SI scheduling on BCCH Norm is matching rules from 3GPP TS 05.02 § 6.3.1.3
|
||||||
|
switch (si) {
|
||||||
|
case "1": return (0 == tc) ? 1 : 0
|
||||||
|
case "2": return (1 == tc) ? 1 : 0
|
||||||
|
case "2bis": return (5 == tc) ? 1 : 0
|
||||||
|
case "13": return (4 == tc) ? 1 : 0
|
||||||
|
case "9": return (4 == tc) ? 1 : 0
|
||||||
|
case "2ter": if (BT_BOTH) { return (4 == tc) ? 1 : 0 } else { return (5 == tc) ? 1 : 0 }
|
||||||
|
case "2quater": if (BT_NONE) { return (5 == tc) ? 1 : 0 } else { return (4 == tc) ? 1 : 0 }
|
||||||
|
case "3": return (2 == tc || 6 == tc) ? 1 : 0
|
||||||
|
case "4": return (3 == tc || 7 == tc) ? 1 : 0
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
@@ -0,0 +1,110 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Split common DSP call log file (produced by superfemto-compatible firmware) into 4 separate call leg files (MO/MT & DL/UL) with events in format "FN EVENT_TYPE":
|
||||||
|
# MO Mobile Originated
|
||||||
|
# MT Mobile Terminated
|
||||||
|
# DL DownLink (BTS -> L1)
|
||||||
|
# UL UpLink (L1 -> BTS)
|
||||||
|
|
||||||
|
if [ -z $1 ]; then
|
||||||
|
echo "expecting DSP log file name as parameter"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# MO handle appear 1st in the logs
|
||||||
|
MO=$(grep 'h=' $1 | head -n 1 | cut -f2 -d',' | cut -f2 -d= | cut -f1 -d']')
|
||||||
|
|
||||||
|
# direction markers:
|
||||||
|
DLST="_CodeBurst"
|
||||||
|
ULST="_DecodeAndIdentify"
|
||||||
|
|
||||||
|
# DL sed filters:
|
||||||
|
D_EMP='s/ Empty frame request!/EMPTY/i'
|
||||||
|
D_FAC='s/ Coding a FACCH\/. frame !!/FACCH/i'
|
||||||
|
D_FST='s/ Coding a RTP SID First frame !!/FIRST/i'
|
||||||
|
D_FS1='s/ Coding a SID First P1 frame !!/FIRST_P1/i'
|
||||||
|
D_FS2='s/ Coding a SID First P2 frame !!/FIRST_P2/i'
|
||||||
|
D_RP1='s/ Coding a RTP SID P1 frame !!/SID_P1/i'
|
||||||
|
D_UPD='s/ Coding a RTP SID Update frame !!/UPDATE/i'
|
||||||
|
D_SPE='s/ Coding a RTP Speech frame !!/SPEECH/i'
|
||||||
|
D_ONS='s/ Coding a Onset frame !!/ONSET/i'
|
||||||
|
D_FO1='s/ A speech frame is following a NoData or SID First without an Onset./FORCED_FIRST/i'
|
||||||
|
D_FO2='s/ A speech frame is following a NoData without an Onset./FORCED_NODATA/i'
|
||||||
|
D_FP2='s/ A speech frame is following a NoData or SID_FIRST_P2 without an Onset./FORCED_F_P2/i'
|
||||||
|
D_FIN='s/ A speech frame is following a SID_FIRST without inhibit. A SID_FIRST_INH will be inserted./FORCED_F_INH/i'
|
||||||
|
D_UIN='s/ A speech frame is following a SID_UPDATE without inhibit. A SID_UPDATE_INH will be inserted./FORCED_U_INH/i'
|
||||||
|
|
||||||
|
# UL sed filters:
|
||||||
|
U_NOD='s/ It is a No Data frame !!/NODATA/i'
|
||||||
|
U_ONS='s/ It is an ONSET frame !!/ONSET/i'
|
||||||
|
U_UPD='s/ It is a SID UPDATE frame !!/UPDATE/i'
|
||||||
|
U_FST='s/ It is a SID FIRST frame !!/FIRST/i'
|
||||||
|
U_FP1='s/ It is a SID-First P1 frame !!/FIRST_P1/i'
|
||||||
|
U_FP2='s/ It is a SID-First P2 frame !!/FIRST_P2/i'
|
||||||
|
U_SPE='s/ It is a SPEECH frame *!!/SPEECH/i'
|
||||||
|
U_UIN='s/ It is a SID update InH frame !!/UPD_INH/i'
|
||||||
|
U_FIN='s/ It is a SID-First InH frame !!/FST_INH/i'
|
||||||
|
U_RAT='s/ It is a RATSCCH data frame !!/RATSCCH/i'
|
||||||
|
|
||||||
|
DL () { # filter downlink-related entries
|
||||||
|
grep $DLST $1 > $1.DL.tmp
|
||||||
|
}
|
||||||
|
|
||||||
|
UL () { # uplink does not require special fix
|
||||||
|
grep $ULST $1 > $1.UL.tmp.fix
|
||||||
|
}
|
||||||
|
|
||||||
|
DL $1
|
||||||
|
UL $1
|
||||||
|
|
||||||
|
FIX() { # add MO/MT marker from preceding line to inserted ONSETs so filtering works as expected
|
||||||
|
cat $1.DL.tmp | awk 'BEGIN{ FS=" h="; H="" } { if (NF > 1) { H = $2; print $1 "h=" $2 } else { print $1 ", h=" H } }' > $1.DL.tmp.fix
|
||||||
|
}
|
||||||
|
|
||||||
|
FIX $1
|
||||||
|
|
||||||
|
MO() { # filter MO call DL or UL logs
|
||||||
|
grep "h=$MO" $1.tmp.fix > $1.MO.raw
|
||||||
|
}
|
||||||
|
|
||||||
|
MT() { # filter MT call DL or UL logs
|
||||||
|
grep -v "h=$MO" $1.tmp.fix > $1.MT.raw
|
||||||
|
}
|
||||||
|
|
||||||
|
MO $1.DL
|
||||||
|
MT $1.DL
|
||||||
|
MO $1.UL
|
||||||
|
MT $1.UL
|
||||||
|
|
||||||
|
PREP() { # prepare logs for reformatting
|
||||||
|
cat $1.raw | cut -f2 -d')' | cut -f1 -d',' | cut -f2 -d'>' | sed 's/\[u32Fn/fn/' | sed 's/\[ u32Fn/fn/' | sed 's/fn = /fn=/' | sed 's/fn=//' | sed 's/\[Fn=//' | sed 's/ An Onset will be inserted.//' > $1.tmp1
|
||||||
|
}
|
||||||
|
|
||||||
|
PREP "$1.DL.MT"
|
||||||
|
PREP "$1.DL.MO"
|
||||||
|
PREP "$1.UL.MT"
|
||||||
|
PREP "$1.UL.MO"
|
||||||
|
|
||||||
|
RD() { # reformat DL logs for consistency checks
|
||||||
|
cat $1.tmp1 | sed "$D_FST" | sed "$D_SPE" | sed "$D_FS1" | sed "$D_FS2" | sed "$D_UIN" | sed "$D_FIN" | sed "$D_UPD" | sed "$D_INH" | sed "$D_RP1" | sed "$D_ONS" | sed "$D_EMP" | sed "$D_FAC" | sed "$D_FO1" | sed "$D_FO2" | sed "$D_FP2" > $1.tmp2
|
||||||
|
}
|
||||||
|
|
||||||
|
RU() { # reformat UL logs for consistency checks
|
||||||
|
cat $1.tmp1 | sed "$U_FST" | sed "$U_SPE" | sed "$U_FP1" | sed "$U_FP2" | sed "$U_UPD" | sed "$U_ONS" | sed "$U_NOD" | sed "$U_UIN" | sed "$U_FIN" | sed "$U_RAT" > $1.tmp2
|
||||||
|
}
|
||||||
|
|
||||||
|
RD "$1.DL.MT"
|
||||||
|
RD "$1.DL.MO"
|
||||||
|
RU "$1.UL.MT"
|
||||||
|
RU "$1.UL.MO"
|
||||||
|
|
||||||
|
SW() { # swap fields
|
||||||
|
cat $1.tmp2 | awk '{ print $2, $1 }' > $1
|
||||||
|
}
|
||||||
|
|
||||||
|
SW "$1.DL.MT"
|
||||||
|
SW "$1.DL.MO"
|
||||||
|
SW "$1.UL.MT"
|
||||||
|
SW "$1.UL.MO"
|
||||||
|
|
||||||
|
rm $1.*.tmp*
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=osmo-bts manager for sysmoBTS
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
ExecStart=/usr/bin/sysmobts-mgr -ns -c /etc/osmocom/sysmobts-mgr.cfg
|
||||||
|
Restart=always
|
||||||
|
RestartSec=2
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
Alias=osmo-bts-mgr.service
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
### BEGIN INIT INFO
|
||||||
|
# Provides: sysmobts
|
||||||
|
# Required-Start:
|
||||||
|
# Required-Stop: $local_fs
|
||||||
|
# Default-Start: 5
|
||||||
|
# Default-Stop: 0 6
|
||||||
|
# Short-Description: Start screen session with sysmobts software
|
||||||
|
# Description:
|
||||||
|
### END INIT INFO
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
start)
|
||||||
|
/usr/bin/screen -d -m -c /etc/osmocom/screenrc-sysmobts -S sysmobts
|
||||||
|
;;
|
||||||
|
stop)
|
||||||
|
/usr/bin/screen -d -r sysmobts -X quit
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
restart|reload|force-reload)
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
show)
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Usage: sysmobts {start|stop|show|reload|restart}" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=sysmocom sysmoBTS
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
ExecStartPre=/bin/sh -c 'echo 0 > /sys/class/leds/activity_led/brightness'
|
||||||
|
ExecStart=/usr/bin/osmo-bts-sysmo -s -c /etc/osmocom/osmo-bts.cfg -M
|
||||||
|
ExecStopPost=/bin/sh -c 'echo 0 > /sys/class/leds/activity_led/brightness'
|
||||||
|
ExecStopPost=/bin/sh -c 'cat /lib/firmware/sysmobts-v?.bit > /dev/fpgadl_par0 ; sleep 3s; cat /lib/firmware/sysmobts-v?.out > /dev/dspdl_dm644x_0; sleep 1s'
|
||||||
|
Restart=always
|
||||||
|
RestartSec=2
|
||||||
|
RestartPreventExitStatus=1
|
||||||
|
|
||||||
|
# The msg queues must be read fast enough
|
||||||
|
CPUSchedulingPolicy=rr
|
||||||
|
CPUSchedulingPriority=1
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
Alias=osmo-bts-sysmo.service
|
||||||
@@ -0,0 +1,755 @@
|
|||||||
|
osmo-bts (0.8.1) unstable; urgency=medium
|
||||||
|
|
||||||
|
[ Neels Hofmeyr ]
|
||||||
|
* cosmetic: dyn TS: clarify rsl_tx_rf_rel_ack() with a switch
|
||||||
|
* dyn TS: fix TCH/F_TCH/H_PDCH: properly record release of PDCH TS
|
||||||
|
* dyn TS: rx_rf_chan_rel: properly mark PDCH rel when no PCU, clarify
|
||||||
|
* dyn TS: clear TCH state upon reconnecting as PDCH
|
||||||
|
* cosmetic: dyn TS: clarify chan_nr composition
|
||||||
|
* ignore RSL RF CHAN REL for inactive lchans
|
||||||
|
* fix RSL Chan Activ Nack messages
|
||||||
|
* ip.access dyn ts: properly NACK a PDCH ACT on a still active lchan
|
||||||
|
* add/improve various logging around dyn ts
|
||||||
|
* dyn TS: be less strict on chan_nr, to allow arbitrary pchan switches
|
||||||
|
|
||||||
|
[ Stefan Sperling ]
|
||||||
|
* send a State Changed Event Report when rf is locked/unlocked
|
||||||
|
|
||||||
|
[ Harald Welte ]
|
||||||
|
* rsl: log errors when parsing of encryption information fails
|
||||||
|
* rsl: Make channel activation fail if encryption algorithm not supported
|
||||||
|
* rsl: Properly NACK CHAN_ACKT / MODE_MODIFY
|
||||||
|
* rsl: If CHAN ACT or MODE MODIF fails, send respective NACK
|
||||||
|
* osmo-bts-trx: Enable A5/3 cipher support
|
||||||
|
|
||||||
|
-- Pau Espin Pedrol <pespin@sysmocom.de> Tue, 15 May 2018 14:08:47 +0200
|
||||||
|
|
||||||
|
osmo-bts (0.8.0) unstable; urgency=medium
|
||||||
|
|
||||||
|
[ Neels Hofmeyr ]
|
||||||
|
* vty: skip installing cmds now always installed by default
|
||||||
|
* jenkins_common.sh: fix build_bts distcheck for more than one conf_flag
|
||||||
|
* fix build: tests/sysmobts: add missing -I$(SYSMOBTS_INCDIR)
|
||||||
|
* fix handover: handle_ph_ra_ind(): evaluate ra_ind before msgb_trim()
|
||||||
|
* implement support for 3-digit MNC with leading zeros
|
||||||
|
* configure: add --enable-werror
|
||||||
|
* use osmo_init_logging2() with proper talloc ctx
|
||||||
|
|
||||||
|
[ Pau Espin Pedrol ]
|
||||||
|
* lc15: Fix cfg indentation
|
||||||
|
* l1sap: Fix abort on big RTP packet received
|
||||||
|
* bts-trx: trx_ctrl_cmd: Simplify var assignment logic
|
||||||
|
* bts-trx: Avoid enqueueing consecutive duplicate messages to TRX
|
||||||
|
* Fix malformed Resource Indication packet
|
||||||
|
* debian/control: Remove uneeded dep libosmo-netif-dev
|
||||||
|
* jenkins.sh: Disable building doxygen for deps
|
||||||
|
* oml.c: Fix use of htons instead of ntohs
|
||||||
|
* bts-trx: trx_if.c: Log timedout+retransmitted CMD
|
||||||
|
* bts-trx: trx_if.c: trx_ctrl_read_cb: Move error handling to end of func
|
||||||
|
* bts-trx: trx_if.c: Improve parsing of received RSP messages from TRX
|
||||||
|
* bts-trx: Detect duplicated responses for retransmitted commands
|
||||||
|
* gsm_pchan2chan_nr: move warning to pragma message and track issue
|
||||||
|
* Remove unused variables
|
||||||
|
* bts-trx: scheduler_trx.c: Fix missing header
|
||||||
|
* l1sap.c: l1sap_tch_rts_ind: Remove unused variables
|
||||||
|
* octphy: octpkt.c: Remove unused static functions
|
||||||
|
* vty.c: Remove warning message
|
||||||
|
* virtual: l1_if.c: Remove unneeded warning message
|
||||||
|
* main.c: bts_main: fix typo in error message
|
||||||
|
* l1sap: Validate incoming RTP payload, drop bw-efficient AMR
|
||||||
|
* l1sap: Avoid assumption that l1sap is at head of msgb
|
||||||
|
* contrib: jenkins_bts_model: Fix bashism expr
|
||||||
|
* Include missing headers for osmo_init_logging2
|
||||||
|
* common/sysinfo.c: Fix no return on on-void function
|
||||||
|
* gsm_data_shared.h: Remove unused enum gsm_paging_event
|
||||||
|
* scheduler_trx: Fix signed integer overflow in clock calculations
|
||||||
|
|
||||||
|
[ Harald Welte ]
|
||||||
|
* trx: Better be safe than sorry before calling strlen
|
||||||
|
* trx: Avoid NULL+1 dereference in trx_ctrl_read_cb()
|
||||||
|
* trx: Don't call osmo_fr_check_sid with negative 'rc'
|
||||||
|
* trx: Don't assume phy_instance_by_num() returns non-NULL
|
||||||
|
* l1sap: fix wrong return value of is_fill_frame()
|
||||||
|
* measurement.c: Fix various typos in comments
|
||||||
|
* Comments on individual members of struct gsm_abis_mo
|
||||||
|
* scheduler: Harmonize log line format; Always print TS name + decoded FN
|
||||||
|
* scheduler_trx: L1P is for PH (data), L1M for MPH (control)
|
||||||
|
* l1sap: Fix log subsystem: Use DRTP for RTP related bits, L1C for MPH
|
||||||
|
* measurment.c: Introduce INFO category for DMEAS logging
|
||||||
|
* osmo-bts-octphy: Remove bogus warning about BS_AG_BLKS_RES
|
||||||
|
* rsl.c: Log RTP socket related errors as DRTP, not DRSL
|
||||||
|
* Put useful information in RTCP SDES.
|
||||||
|
* osmo-bts-trx: Fix reported frame number during PRIM_INFO_MEAS
|
||||||
|
* DTX: avoid illegal character contained in DTX FSM allocation which causes BTS crash
|
||||||
|
* gsm_lchan: remove unused member fields
|
||||||
|
* Add 'show (bts|trx|ts|lchan)' commands
|
||||||
|
* Print much more information during 'show lchan'
|
||||||
|
* vty: don't print "Bound IP / Port" if it isn't bound [yet]
|
||||||
|
* osmo-bts: Add talloc context introspection via VTY
|
||||||
|
* sysmo: Fix compiler warnings in eeprom.c
|
||||||
|
* sysmo+lc15: Add missign include for readv/writev
|
||||||
|
* trx: make l1if_fill_meas_res() static
|
||||||
|
* RSL: Properly reject RSL CHAN_NR IE for incompatible PCHAN
|
||||||
|
* RSL: Ensure we don't accept DCHAN messages for CCHAN
|
||||||
|
* osmo-bts-virtual: Shut down gracefully on socket creation failure
|
||||||
|
* osmo-bts-virtual: Generate PRIM_INFO_MEAS (with bogus values)
|
||||||
|
* Introduce + use LOG/DEBUGP with frame number prefixing/printing
|
||||||
|
* osmo-bts-virtual: Make use of LOGL1S() macro for context
|
||||||
|
* osmo-bts-virtual: Make sure PRIM_INFO_MEAS have non-zero frame number
|
||||||
|
* scheduler.c: Factor out find_sched_mframe_idx() function
|
||||||
|
* scheduler: add trx_sched_is_sacch_fn() function
|
||||||
|
* Revert "measurement: fix measurement computation"
|
||||||
|
* measurement.c: Hand Frame Number into measurement computation
|
||||||
|
* l1sap: Pass is_sub from L1 primitive into the Uplink Measurement
|
||||||
|
* osmo-bts-trx: Add missing frame number to l1if_process_meas_res()
|
||||||
|
* scheduler.c: Print message when burst substitution happens
|
||||||
|
* load_indication: Fix start of load indication timer
|
||||||
|
* RSL: Implement DELETE INDICATION on AGCH overflow
|
||||||
|
* RSL: Send ERROR REPORT on too short/truncated messages + wrong discriminator
|
||||||
|
* BTS: add rate_ctr about CCCH (paging, agch, pch)
|
||||||
|
* paging: Drop + Log paging requests for non-existant paging groups
|
||||||
|
* paging.c: Fix encoding of optional Mobile ID RR PAGING TYPE 1 / 2
|
||||||
|
* rsl: Improve ERROR REPORTing
|
||||||
|
* paging: Fix encoding of PAGING TYPE 3 Rest Octets
|
||||||
|
* RSL IPA DLCX: Avoid null-pointer dereference
|
||||||
|
* RSL: Fix encoding of ConnectionID in IPA_DLCX_ACK
|
||||||
|
* RSL IPA DLCX: Avoid another null-pointer dereference
|
||||||
|
* measurement.c: Fix sdcch4_meas_rep_fn102 / sdcch8_meas_rep_fn102
|
||||||
|
* counters: split rach:sent into rach:drop, rach:ho, rach:cs and rach:ps
|
||||||
|
* octphy: Remove code duplication for BER / RSSI conversion
|
||||||
|
* {sysmo,lc15}: Correctly report BER to L1SAP in INFO_MEAS_IND
|
||||||
|
* {sysmo,lc15}: Fix RACH reporting in combined CBCH case
|
||||||
|
* split scheduler_mframe.c from scheduler.c
|
||||||
|
* measurement: Compute RX{LEV,QUAL}-SUB for SDCCH and non-AMR TCH
|
||||||
|
* measurement.c: Don't silently copy "FULL" measurements to "SUB"
|
||||||
|
* scheduler: Add missing \n at end of LOG statement
|
||||||
|
* Move rach_busy counting above L1SAP
|
||||||
|
* RACH decoding: Use BER threshold for RACH ghost detection
|
||||||
|
* trx/scheduler: Use integer math for TOA (Timing of Arrival)
|
||||||
|
* measurement.c: higher-precision TA/TOA math
|
||||||
|
* L1SAP: Increase resolution of reported burst timing
|
||||||
|
* measurement: Keep average of high-accurate ToA value in lchan
|
||||||
|
* Add high-accuracy ToA value to Uplink Measurement Reports
|
||||||
|
* pcu_sock: Discard messages that are too short
|
||||||
|
* pcu_sock: Don't overflow the timeslot array
|
||||||
|
* pcu_sock: Log an error message and discard PCU primitives for BTS != 0
|
||||||
|
* pcu_sock: LOG + drop DATA.req from PCU for non-PDCH timeslot
|
||||||
|
* pcu_sock: LOG + drop PCU DATA.req for inactive lchan
|
||||||
|
* sysinfo.c: SI1 is optional; Send SI2 at TC=0 if no SI1 exists
|
||||||
|
* sysmobts: Compatibility with older firmware versions
|
||||||
|
* cosmetic: Document some SI scheduling related function API
|
||||||
|
* sysinfo: Fix scheduling of downlink SACCH information
|
||||||
|
* gsm_data_shared: Remove unused definitions/members/functions
|
||||||
|
* cosmetic: Move agch_queue to sub-structure of gsm_bts_role_bts
|
||||||
|
* Get rid of 'struct gsm_bts_role_bts'
|
||||||
|
* virtual: Correctly set+report BTS variant in OML attributes
|
||||||
|
* Add 'osmo-bts-omldummy' to bring up only OML without RSL
|
||||||
|
* fix inverted logic bug in omldummy patch
|
||||||
|
* omldummy: Suppress RSL transmission errors
|
||||||
|
* debian: Split osmo-bts-virtual from osmo-bts-trx
|
||||||
|
* fox chan_nr_is_dchan() for RSL_CHAN_OSMO_PDCH
|
||||||
|
* rsl_tx_dyn_pdch_ack: Add missing FRAME_NR information element
|
||||||
|
* fix activation of osmocom-style dynamic PDCH as TCH/F or TCH/H
|
||||||
|
|
||||||
|
[ Philipp Maier ]
|
||||||
|
* octphy: override firmware version check
|
||||||
|
* cosmetic: meas_test: fix section comment
|
||||||
|
* cosmetic: tests/Makefile.am: remove excess whitespace
|
||||||
|
* cosmetic: tests/power: remove unused var "ret"
|
||||||
|
* cosmetic: tests/agch: remove unused var "static_ilv"
|
||||||
|
* octphy: l1_oml: check returncode of trx_by_l1h()
|
||||||
|
* meas_test: fix header file references
|
||||||
|
* rsl: fix double-free in rsl_rx_mode_modif()
|
||||||
|
* fix nullpointer deref in rsl_tx_mode_modif_nack()
|
||||||
|
* rsl: do not allow MODE MODIFY request with unsupp. codec/rate
|
||||||
|
* gsm_data_shared: extend bts feature list with speech codecs
|
||||||
|
* octphy: ensure all BTS models set features
|
||||||
|
* vty: display bts features in vty command show bts
|
||||||
|
* bts: use feature list instead of speech codec table
|
||||||
|
* octphy: replace #warning with #pragma message
|
||||||
|
* ipac: fix log output
|
||||||
|
* rsl: remove unused variable
|
||||||
|
* l1_tch: remove dead code
|
||||||
|
* cosmetic: remove dead code
|
||||||
|
* cosmetic: remove unused variable
|
||||||
|
* cosmetic: remove unused variable in osmo-bts-omldummy/main.c
|
||||||
|
* octphy: integrate octasics latest header release
|
||||||
|
* osmo-bts-trx: perform error concealment for FR frames
|
||||||
|
|
||||||
|
[ Max ]
|
||||||
|
* Remove leftover comments and checks
|
||||||
|
* Log filenames on L1 errors
|
||||||
|
* Add --enable-sanitize configure option
|
||||||
|
* Use existing function to obtain TSC
|
||||||
|
* Remove BSC-specific parts
|
||||||
|
* Print FN delta on L1 errors
|
||||||
|
* Move sysmobts-calib into osmo-bts-sysmo
|
||||||
|
* Allow specifying sysmocom headers explicitly
|
||||||
|
* fix build: tests/misc: missing libosmo-abis and -trau flags
|
||||||
|
* Enable optional static builds
|
||||||
|
* Remove unneeded LIBOSMOCORE_CFLAGS from tests
|
||||||
|
* sysmobts: use proper includes for sbts2050 test
|
||||||
|
* Move -I inside *INCDIR variable
|
||||||
|
* sysmobts: remove weird default header location
|
||||||
|
* sysmobts: move header check to appropriate place
|
||||||
|
* CI: drop unused OsmoPCU dependency
|
||||||
|
* Enable sanitize for CI tests
|
||||||
|
* Add helper to get BCC from BSIC
|
||||||
|
* osmo-bts-trx: init nbits to know value
|
||||||
|
* osmo-bts-trx: ignore frame offset error on startup
|
||||||
|
|
||||||
|
[ Vadim Yanitskiy ]
|
||||||
|
* doc/examples: add CalypsoBTS configuration example
|
||||||
|
* common/pcu_sock.c: fix double field assignment
|
||||||
|
* scheduler_trx.c: remove ToA (Time of Arrival) hack
|
||||||
|
* common/l1sap.c: increase the BTS_CTR_RACH_DROP in RACH BER check
|
||||||
|
* common/l1sap.c: increment valid RACH counter after all checks
|
||||||
|
* common/l1sap.c: clean up noise / ghost RACH filtering
|
||||||
|
* common/l1sap.c: perform noise / ghost filtering for handover RACH
|
||||||
|
* common/l1sap.c: limit the minimal ToA for RACH bursts
|
||||||
|
* common/vty.c: remove unused variables
|
||||||
|
* common/main.c: track talloc NULL contexts by default
|
||||||
|
|
||||||
|
[ Alexander Huemer ]
|
||||||
|
* cosmetic: Makefile.am whitespace
|
||||||
|
* various Makefile.am: add missing CFLAGS
|
||||||
|
* gitignore: add missing entries
|
||||||
|
|
||||||
|
[ Stefan Sperling ]
|
||||||
|
* Cosmetic fixes for power ramping code.
|
||||||
|
* respond with NACK for non-hopping BTS with multiple ARFCN
|
||||||
|
* cosmetic: fix typos in src/common/oml.c
|
||||||
|
* return NACK codes instead of errno values from oml_tx_attr_resp()
|
||||||
|
|
||||||
|
[ Alexander Couzens ]
|
||||||
|
* pcuif_proto: correct indention of gsm_pcu_if_data
|
||||||
|
* pcu_if: move definition PCU_SOCK_DEFAULT into pcuif_proto.h
|
||||||
|
* pcuif_proto: add version 8 features
|
||||||
|
|
||||||
|
[ Keith ]
|
||||||
|
* osmo-bts-sysmo eeprom.c Restore ability to read/write EEPROM
|
||||||
|
|
||||||
|
-- Pau Espin Pedrol <pespin@sysmocom.de> Thu, 03 May 2018 17:02:19 +0200
|
||||||
|
|
||||||
|
osmo-bts (0.7.0) unstable; urgency=medium
|
||||||
|
|
||||||
|
[ Max ]
|
||||||
|
* Use value string check from osmo-ci
|
||||||
|
* Support sending SI13 to PCU
|
||||||
|
* Support removing SI13 from PCU
|
||||||
|
* trx: avoid deactivating lchan on LCHAN_REL_ACT_REACT
|
||||||
|
* Check readv() return value to prevent crash
|
||||||
|
* OML: print actual type of report sent to BSC
|
||||||
|
* Replace dead code
|
||||||
|
* vty: print version and description for each phy
|
||||||
|
* Remove build dependency on legacy OpenBSC
|
||||||
|
* Fix multiple SI2q reception
|
||||||
|
* jenkins: remove openbsc dependency
|
||||||
|
* sysmo: use clock calibration source wrapper
|
||||||
|
* sysmo: don't override clock source with defaults
|
||||||
|
* Fix race condition in attribute reporting
|
||||||
|
* Move power loop to generic tests
|
||||||
|
* Make power test more verbose
|
||||||
|
|
||||||
|
[ Neels Hofmeyr ]
|
||||||
|
* vty: mgr: sysmobts, lc15: install default commands for ACT_NORM_NODE
|
||||||
|
* osmo-bts-trx: vty: various fixes of 'write file' and doc
|
||||||
|
* jenkins: use osmo-clean-workspace.sh before and after build
|
||||||
|
|
||||||
|
[ Pau Espin Pedrol ]
|
||||||
|
* l1sap: Improve log msg when frame diff >1
|
||||||
|
* vty: Print string for Administrative state
|
||||||
|
|
||||||
|
[ Harald Welte ]
|
||||||
|
* Fix Downlink AMR FSM name to avoid illegal space character
|
||||||
|
* update dependencies to latest libosmo-*
|
||||||
|
* configure.ac: Fix Mailing list address
|
||||||
|
|
||||||
|
-- Harald Welte <laforge@gnumonks.org> Sat, 28 Oct 2017 20:53:21 +0200
|
||||||
|
|
||||||
|
osmo-bts (0.6.0) unstable; urgency=medium
|
||||||
|
|
||||||
|
[ Holger Hans Peter Freyther ]
|
||||||
|
* Initial release.
|
||||||
|
* misc: Ignore files generated by a debian packaging build
|
||||||
|
* jenkins: Add the build script from jenkins here
|
||||||
|
* jenkins: Add the build script from jenkins here
|
||||||
|
* sysmobts: Add the barebox boot state reservation
|
||||||
|
* sysmobts: Fix eeprom padding before gpg key
|
||||||
|
* ci/spatch: Remove the "static" analysis handling
|
||||||
|
* oct: Attempt to enable the Octphy for the osmo-bts-oct build
|
||||||
|
* debian: Use the header files installed by openbsc-dev
|
||||||
|
* build: Do not require more headers from OpenBSC
|
||||||
|
* sysmobts: Make reservation for mode/netmask/ip and suc
|
||||||
|
* sysmobts: Store a simple network config in the EEPROM as well
|
||||||
|
|
||||||
|
[ Max ]
|
||||||
|
* Ensure TRX invariant
|
||||||
|
* Use libosmocore function for uplink measurements
|
||||||
|
* Fix debug output
|
||||||
|
* Fix RTP timestamps in case of DTX
|
||||||
|
* Add DTXd support for sysmoBTS and LC15
|
||||||
|
* Use libosmocodec for AMR RTP
|
||||||
|
* octphy: Use the app. info. defaults as base
|
||||||
|
* Fix debug output
|
||||||
|
* DTXd: store/repeat last SID
|
||||||
|
* DTXd: store/repeat last SID
|
||||||
|
* DTXu: mark beginning of speech burst in RTP
|
||||||
|
* Fix OML activation
|
||||||
|
* TRX: Add vty command to power on/off transceiver
|
||||||
|
* TRX: add configuration example
|
||||||
|
* Add .gitreview
|
||||||
|
* DTX: add support for AMR/HR
|
||||||
|
* Move copy-pasted code into common part
|
||||||
|
* Use libosmocodec functions for AMR
|
||||||
|
* Use error values instead of number for RSL error
|
||||||
|
* Clarify logging message
|
||||||
|
* Make get_lchan_by_chan_nr globally available
|
||||||
|
* DTXu: move copy-pasted code to common part
|
||||||
|
* Remove duplicated nibble shift code
|
||||||
|
* TRX: add Uplink DTX support for FR/HR
|
||||||
|
* Mark array as static const
|
||||||
|
* sysmobts: dump PRACH and PTCCH parameters
|
||||||
|
* Activate PTCCH UL
|
||||||
|
* Fix dsp tracing at phy config
|
||||||
|
* octphy: fix build
|
||||||
|
* Fill measurements data for L1SAP
|
||||||
|
* sysmo: ts_connect: log channel combination name instead of number
|
||||||
|
* DTX: fix last SID saving
|
||||||
|
* DTX: fix SID repeat scheduling
|
||||||
|
* DTX: fix SID logic
|
||||||
|
* lc15, sysmo: Use SID_FIRST_P1 to initiate DTX
|
||||||
|
* DTX: check Marker bit to send ONSET to L1
|
||||||
|
* DTX: remove misleading comment
|
||||||
|
* LC15: Clarify msgb ownership / fix memory leaks
|
||||||
|
* DTX: move scheduling check inside repeat_last_sid
|
||||||
|
* DTX: further AMR SID cache fixes (lc15, sysmo)
|
||||||
|
* DTX: move ONSET detection into separate function
|
||||||
|
* DTX: send AMR voice alongside with ONSET
|
||||||
|
* DTX: fix conversion from fn to ms
|
||||||
|
* Move copy-pasted array into shared header
|
||||||
|
* DTX DL: use FSM for AMR
|
||||||
|
* TRX: fix building with latest DTX changes
|
||||||
|
* DTX: fix array size calculation
|
||||||
|
* DTX AMR - fix buffer length check
|
||||||
|
* Replace magic number with define
|
||||||
|
* Fix lc15 build
|
||||||
|
* Extend RTP RX callback parameters
|
||||||
|
* DTX HR - fix array size calculation
|
||||||
|
* Fix DTX DL AMR SIDscheduling logic
|
||||||
|
* Add tools to check DTX operation
|
||||||
|
* DTX DL: split ONSET state handling
|
||||||
|
* Remove obsolete define
|
||||||
|
* DTX DL: add AMR HR support to scheduling check
|
||||||
|
* DTX fix ONSET handling
|
||||||
|
* dtx_check.gawk: Fix false-positives in DTX check
|
||||||
|
* Fix tests linking with libosmocodec
|
||||||
|
* DTX DL: tighten check for enabled operation
|
||||||
|
* DTX: wrap FSM signal dispatching
|
||||||
|
* Add libosmocodec for octphy build
|
||||||
|
* dtx_check.gawk: add check for repetitive SID FIRST
|
||||||
|
* Remove duplicated code
|
||||||
|
* Replace link_id constant with define
|
||||||
|
* DTX DL AMR: rewrite FSM recursion
|
||||||
|
* Remove duplicated code
|
||||||
|
* Fix AGCH/PCH proportional allocation
|
||||||
|
* TRX: prevent segfault upon phy init
|
||||||
|
* DTX: add explicit check if DTX enabled
|
||||||
|
* Save RTP metadata in Control Buffer
|
||||||
|
* osmo-bts-trx: fix lchan deactivation
|
||||||
|
* DTX: fix TS adjustment for ONSET
|
||||||
|
* Optionally use adaptive RTP jitter buffering
|
||||||
|
* Integrate Debian packaging changes
|
||||||
|
* DTX AMR HR: fix inhibition
|
||||||
|
* Add copyright for .deb packages
|
||||||
|
* Move code to libosmocore
|
||||||
|
* Log socket path on error
|
||||||
|
* Add Abis OML failure event reporting
|
||||||
|
* Alarm on various errors
|
||||||
|
* Remove obsolete define TLVP_PRES_LEN
|
||||||
|
* scheduler: log lchan on which prim error occured
|
||||||
|
* deb: use gsm_data_shared.* from openbsc-dev
|
||||||
|
* OML: internalize failure reporting
|
||||||
|
* Add ctrl command to send OML alert
|
||||||
|
* Fix typo in TCH/H interleaving table
|
||||||
|
* Use oml-alert CTRL command for temp report
|
||||||
|
* Remove code duplication
|
||||||
|
* Handle ctrl cmd allocation failures
|
||||||
|
* Check for suitable lchan type when detecting HO
|
||||||
|
* osmo-bts-trx: fix scheduling of broken frames
|
||||||
|
* Sync protocol with OsmoPCU
|
||||||
|
* vty: reduce code duplication
|
||||||
|
* Handle TXT indication from OsmoPCU
|
||||||
|
* Add MS TO to RSL measurements
|
||||||
|
* Signal to BSC when PCU disconnects
|
||||||
|
* Prepare for extended SI2quater support
|
||||||
|
* Set BTS variant while initializing BTS model
|
||||||
|
* Prepare for BTS attribute reporting via OML
|
||||||
|
* osmo-bts-trx: use libosmocoding
|
||||||
|
* Remove redundant test
|
||||||
|
* Implement basic Get Attribute responder
|
||||||
|
* Add version to phy_instance
|
||||||
|
* OML: fix Coverity-reported issues
|
||||||
|
* Re-add version to phy_instance
|
||||||
|
* Use systemd template specifiers
|
||||||
|
* Place *-mgr config examples according to BTS model
|
||||||
|
* lc15: add example systemd service file
|
||||||
|
* Extend Get Attribute responder
|
||||||
|
* Set and report BTS features
|
||||||
|
* Cleanup SI scheduling
|
||||||
|
* RSL: receive and send multiple SI2q messages
|
||||||
|
* RSL: check for abnormal SI2q values
|
||||||
|
* lc15bts-mgr: use extended config file example
|
||||||
|
* Move parameter file opening into separate function
|
||||||
|
* Move common steps into common jenkins helper
|
||||||
|
* lc15: add jenkins helper
|
||||||
|
* Use generic L1 headers helper
|
||||||
|
* Copy sysmobts.service to osmo-bts-sysmo
|
||||||
|
* OML: move BTS number check into separate function
|
||||||
|
* lc15: make jenkins helper executable
|
||||||
|
* lc15: fix jenkins build
|
||||||
|
* Add missing include for abis.h header file
|
||||||
|
* RSL: receive and send multiple SI2q messages
|
||||||
|
* Use release helper from libosmocore
|
||||||
|
* si2q: do not consider count update as error
|
||||||
|
* Cleanup example config files
|
||||||
|
* Fix .deb build
|
||||||
|
* Unify *.service files
|
||||||
|
* lc15: cleanup board parameters reading
|
||||||
|
* lc15-mgr: update parameter read/write
|
||||||
|
* lc15: fix BTS revision and hw options
|
||||||
|
* lc15: make default config usable
|
||||||
|
* lc15: port lc15bts-mgr changes
|
||||||
|
* lc15bts-mgr: separate service file
|
||||||
|
* lc15: port lc15bts-mgr dependency changes
|
||||||
|
* Simplify jenkins build scripts
|
||||||
|
* OML: use fom_hdr while handling attr. request
|
||||||
|
* osmo-bts-trx: fix 'osmotrx legacy-setbsic'
|
||||||
|
* osmo-bts-trx: remove global variables from loops
|
||||||
|
|
||||||
|
[ Daniel Laszlo Sitzer ]
|
||||||
|
* octphy: Update outdated config param name in error message.
|
||||||
|
|
||||||
|
[ Jason DSouza ]
|
||||||
|
* Close TRX session before opening new one
|
||||||
|
|
||||||
|
[ Minh-Quang Nguyen ]
|
||||||
|
* l1sap.h: fix wrong L1SAP_FN2PTCCHBLOCK calculation according to TS 45.002 Table 6
|
||||||
|
* common/abis.c: fix 100% CPU usage after disconnecting OML/RSL link (Bug #1703)
|
||||||
|
* LC15: Bring back DSP trace argument
|
||||||
|
* LC15: Hardware changes
|
||||||
|
* LC15: TRX nominal TX power can be used from EEPROM or from BTS configuration
|
||||||
|
* rsl: Fix dropping of LAPDm UA message.
|
||||||
|
* LC15: properly handle BS-AG-BLKS-RES as received from BSC
|
||||||
|
|
||||||
|
[ Neels Hofmeyr ]
|
||||||
|
* sysmo: add L3 handle to l1prim messages
|
||||||
|
* pcu_sock: add pcu_connected() to query PCU availability
|
||||||
|
* tests/stubs.c: remove unused stubs
|
||||||
|
* fix typo in error message ('at lEast')
|
||||||
|
* oml, Set Chan Attr: treat unknown PCHAN types as error
|
||||||
|
* dyn PDCH: rsl rx dchan: also log ip.access message names
|
||||||
|
* doc: add ladder diagram on dynamic PDCH, add msc-README
|
||||||
|
* add missing DSUM entry to bts_log_info_cat
|
||||||
|
* fix compiler warning: printf format for sizeof()
|
||||||
|
* fix compiler warning: add missing case (PHY_LINK_CONNECTING)
|
||||||
|
* fix two compiler warnings: add two opaque struct declarations
|
||||||
|
* dyn PDCH: add bts_model_ts_connect() and _disconnect() stubs
|
||||||
|
* dyn PDCH: conf_lchans_for_pchan(): handle TCH/F_PDCH
|
||||||
|
* dyn PDCH: pcu_tx_info_ind(): handle TCH/F_PDCH in PDCH mode
|
||||||
|
* dyn PDCH: chan_nr_by_sapi(): handle TCH/F_PDCH according to ts->flags
|
||||||
|
* dyn PDCH: implement main dyn PDCH logic in common/
|
||||||
|
* dyn PDCH: sysmo-bts/oml.c: add ts_connect_as(), absorbing ts_connect() guts
|
||||||
|
* dyn PDCH: sysmo: handle TCH/F_PDCH init like TCH/F
|
||||||
|
* dyn PDCH: complete for sysmo-bts: implement bts_model_ts_*()
|
||||||
|
* error log: two minor clarifications
|
||||||
|
* debug log: log lchan state transitions
|
||||||
|
* debug log: log TS pchan type on connect
|
||||||
|
* fix lc15 build: put src/common/libbts.a left of -losmogsm
|
||||||
|
* lc15: add L3 handle to l1prim messages
|
||||||
|
* dyn PDCH: lc15: chan_nr_by_sapi(): handle TCH/F_PDCH according to ts->flags
|
||||||
|
* dyn PDCH: lc15: add ts_connect_as(), absorbing ts_connect() guts
|
||||||
|
* dyn PDCH: lc15: handle TCH/F_PDCH init like TCH/F
|
||||||
|
* dyn PDCH: lc15: complete for litecell15-bts: implement bts_model_ts_*()
|
||||||
|
* dyn PDCH: safeguard: exit if nothing pending in dyn_pdch_ts_disconnected()
|
||||||
|
* vty: install orphaned trx nominal power command
|
||||||
|
* fix compiler warnings: include bts_model.h in phy_link.c
|
||||||
|
* fix compiler warning: remove useless 'static' storage class for struct decl
|
||||||
|
* fix compiler warning: remove unused variable 'i' in calib_verify()
|
||||||
|
* log: osmo-bts-trx: change access burst logs to DEBUG level
|
||||||
|
* log: osmo-bts-trx: change PDTCH block logs to DEBUG level
|
||||||
|
* osmo-bts-trx: init OML only once by sending AVSTATE_OK with OPSTATE_ENABLED
|
||||||
|
* doc: move dyn_pdch.msc to osmo-gsm-manuals.git
|
||||||
|
* error log: rsl.c: typo x2
|
||||||
|
* info log: l1sap.c: add '0x' to hex output
|
||||||
|
* fix compiler warning: msg_utils.c: fn_chk() constify arg
|
||||||
|
* fix compiler warning: msg_utils.c: fn_chk() constify arg
|
||||||
|
* info log: l1sap.c: add '0x' to hex output
|
||||||
|
* error log: rsl.c: typo x2
|
||||||
|
* dyn PDCH: code dup: use conf_lchans_as_pchan()
|
||||||
|
* prepare dyn TS: split/replace conf_lchans_for_pchan()
|
||||||
|
* code dup: join [rsl_]lchan_lookup() from libbsc and osmo-bts
|
||||||
|
* dyn TS: common TCH/F_TCH/H_PDCH implementation
|
||||||
|
* sysmo/oml.c: rename ts_connect() to ts_opstart()
|
||||||
|
* dyn TS: implement SysmoBTS specifics
|
||||||
|
* lc15/oml.c: rename ts_connect() to ts_opstart()
|
||||||
|
* dyn TS: implement litecell15 specifics
|
||||||
|
* comment typo: common/l1sap.c
|
||||||
|
* log typo: trx_sched_set_pchan()
|
||||||
|
* dyn TS: sysmo,lc15: chan_nr_by_sapi(): add missing assertion
|
||||||
|
* fix comment in common/l1sap.c, function name changed
|
||||||
|
* dyn TS, dyn PDCH: common/l1sap.c: properly notice PDCH
|
||||||
|
* dyn PDCH: trx l1_if.c: factor out trx_set_ts_as_pchan() from trx_set_ts()
|
||||||
|
* dyn PDCH: complete for trx: implement bts_model_ts_[dis]connect()
|
||||||
|
* dyn PDCH: trx l1_if.c: drop fixme, add comment
|
||||||
|
* dyn TS: complete for TRX
|
||||||
|
* dyn TS: measurement.c: replace fixme with comment
|
||||||
|
* sysmo,lc15: ts_connect_as(): log error also for pchan_as == TCH/F_PDCH
|
||||||
|
* sysmo: fix dyn TS: Revert "Activate PTCCH UL" [in sysmobts]
|
||||||
|
* log: l1sap: add 0x to hex output of chan_nr, 5 times
|
||||||
|
* dyn TS: measurement: use correct nr of subslots, rm code dup
|
||||||
|
* dyn TS: sysmo,lc15: ph_data_req: fix PDCH mode detection
|
||||||
|
* Fix ip.access style dyn PDCH, broken in 37af36e85eca546595081246aec010fa7f6fd0be
|
||||||
|
* common/rsl: move decision whether to chan act ack/nack to common function
|
||||||
|
* octphy: fix build: Revert "octphy: fix for multiple trx with more than 1 dsp"
|
||||||
|
* octphy: fix build: Revert "octphy: add support for multiple trx ids"
|
||||||
|
* octphy: fix build with OCTSDR-OPENBSC-02.07.00-B708: name changed
|
||||||
|
* dyn TS: if PCU is not connected, allow operation as TCH
|
||||||
|
* log: sysmo,lc15: tweak log about sapi_cmds queue
|
||||||
|
* log causing rx event for lchan_lookup errors
|
||||||
|
* heed VTY 'line vty'/'bind' command
|
||||||
|
* sysmobts_mgr, lc15bts_mgr: fix tall context for telnet vty
|
||||||
|
* build: be robust against install-sh files above the root dir
|
||||||
|
* configure: check for pkg-config presence
|
||||||
|
* jenkins.sh: use osmo-build-dep.sh, log test failures
|
||||||
|
* msgb ctx: use new msgb_talloc_ctx_init() in various main()s
|
||||||
|
* jenkins-oct.sh: fix build: typo in deps path
|
||||||
|
* fix 'osmo-bts-* --version' segfault
|
||||||
|
* osmo-bts-trx: remove obsolete include of netif/rtp.h
|
||||||
|
* add jenkins_bts_trx.sh
|
||||||
|
* add jenkins_oct_and_bts_trx.sh
|
||||||
|
* jenkins: add jenkins_bts_model.sh
|
||||||
|
* bursts test: test_pdtch: pre-init result mem
|
||||||
|
* fix: dyn ts: uplink measurement report
|
||||||
|
* fix missing ~ in bit logic for lchan->si.valid in rsl_rx_sacch_inf_mod()
|
||||||
|
* SACCH: fix sending of SI with an enum value > 7
|
||||||
|
* SACCH SI: assert that SI enum vals fit in bit mask
|
||||||
|
* all models: fix vty write: bts_model_config_write_phy
|
||||||
|
* jenkins: add value_string termination check
|
||||||
|
* Revert "Add version to phy_instance"
|
||||||
|
* Revert "RSL: check for abnormal SI2q values"
|
||||||
|
* Revert "RSL: receive and send multiple SI2q messages"
|
||||||
|
|
||||||
|
[ Harald Welte ]
|
||||||
|
* sysmobts: screnrc/systemd-service: Use osmo-bts-sysmo instead of sysmobts
|
||||||
|
* Add .mailmap for mapping mail addresses in shortlog
|
||||||
|
* vty: Ensure to not use negative (error) sapi value
|
||||||
|
* sysmobts: Add correct nominal transmit power for sysmoBTS 1020
|
||||||
|
* sysmobts_eeprom.h: Fix/extend model number definitions
|
||||||
|
* Revert "sysmobts: Add correct nominal transmit power for sysmoBTS 1020"
|
||||||
|
* tx_power: Change PA calibration tables to use delta vales
|
||||||
|
* Add new unit-test for transmit power computation code
|
||||||
|
* sysmobts: fully support trx_power_params
|
||||||
|
* README: Add general project information and convert to markdown
|
||||||
|
* README: update some of the limitations
|
||||||
|
* sysmobts: Don't start with 0dBm TRX output power before ramping
|
||||||
|
* Remove unusued left-over gsm0503_conv.c
|
||||||
|
* scheduler_trx.c: Avoid code duplication for BER10k computation
|
||||||
|
* scheduler_trx: Avoid copy+pasting determining CMR from FN
|
||||||
|
* rx_tchh_fn(): Avoid copy+pasting formula to determine odd-ness of fn
|
||||||
|
* Consistently check for minimum attribute/TLV length in RSL and OML
|
||||||
|
* l1sap.c: Add spec reference to link timeout implementation
|
||||||
|
* osmo-bts-trx: Remove duplicate parsing of NM_ATT_CONN_FAIL_CRIT
|
||||||
|
* vty: Remove command for manual channel activation/deactivation
|
||||||
|
* l1_if: Add inline functions to check dsp/fgpa version at runtime
|
||||||
|
* sysmobts: Re-order the bit-endianness of every HR codec parameter
|
||||||
|
* OML Add osmocom-specific way to deactivate radio link timeout
|
||||||
|
* measurement: Remove dead code
|
||||||
|
* l1sap.c: Factor out function to limit message queue
|
||||||
|
* osmo-bts-sysmo/l1_if.c: PH-DATA.ind belongs to L1P, not L1C
|
||||||
|
* l1sap: if lchan is in loopback, don't accept incoming RTP
|
||||||
|
* TRX: Use timerfd and CLOCK_MONOTONIC for GSM frame timer (Closes: #2325)
|
||||||
|
* Add loopback support for PDTCH
|
||||||
|
* TRX: trx_if: Improve code description / comments
|
||||||
|
* trx_if: Improve error handling
|
||||||
|
* TRX: Rename trx_if_data() -> trx_if_send_burst()
|
||||||
|
* TRX: merge/simplify l1_if and trx_if code
|
||||||
|
* TRX: don't free l1h in trx_phy_inst_close()
|
||||||
|
* l1sap: Don't enqueue PTCCH blocks for loopback
|
||||||
|
* TRX: permit transmission of all-zero loopback frames
|
||||||
|
* jenkins helpers: some minimal documentation/comments + print errors
|
||||||
|
* VIRT-PHY: Initial check-in of a new virtual BTS
|
||||||
|
* VIRT-PHY: Fix handling of default values for vty configuration
|
||||||
|
* VIRT-PHY: Use IPv4 multicast groups for private / local scope
|
||||||
|
* VIRT-PHY: cause BTS to terminate in case of recv()/send() on udp socket returns 0
|
||||||
|
* Ensure we don't send dummy UI frames on BCCH for TC=5
|
||||||
|
* virt: Don't print NOTICE log message if ARFCN doesn't match
|
||||||
|
* VIRT-PHY: Report virtual RACH bursts with plausible burst type
|
||||||
|
* scheduler: Fix wrong log subsystem: L1C is L1 *control* not user data
|
||||||
|
* VIRT-PHY: Print NOTICE log message from unimplemented stubs
|
||||||
|
* TRX / VIRT-PHY: Make check for BCCH/CCCH more specific
|
||||||
|
* L1SAP: Print chan_nr and link_id always as hex
|
||||||
|
* VIRT-BTS: Support for GPRS
|
||||||
|
* L1SAP: Use RSL_CHAN_OSMO_PDCH across L1SAP
|
||||||
|
* GSMTAP: Don't log fill frames via GSMTAP
|
||||||
|
* TRX: Remove bogus extern global variable declarations
|
||||||
|
* l1sap/osmo-bts-sysmo: Improve logging
|
||||||
|
* TRX: Remove global variables, move SETBSIC/SETTSC handling into phy_link
|
||||||
|
* Fix build after recent gsm_bts_alloc() change
|
||||||
|
* Treat SIGTERM just like SIGINT in our programs
|
||||||
|
|
||||||
|
[ Tom Tsou ]
|
||||||
|
* trx: Add EGPRS tables, sequences, and mappings
|
||||||
|
* trx: Add EGPRS coding and decoding procedures
|
||||||
|
* trx: Enable EGPRS handling through burst lengths
|
||||||
|
* trx: Fix coverity BER calculation NULL dereference
|
||||||
|
|
||||||
|
[ Vadim Yanitskiy ]
|
||||||
|
* pcu_sock: use osmo_sock_unix_init() from libosmocore
|
||||||
|
* osmo-bts-trx/l1_if.c: use channel combination III for TCH/H
|
||||||
|
* scheduler_trx.c: strip unused variable
|
||||||
|
|
||||||
|
[ Mike McTernan ]
|
||||||
|
* osmo-bts-trx: Fix PCS1900 operation
|
||||||
|
* osmo-bts-trx: log decoder bit errors as DEBUG, not NOTICE
|
||||||
|
|
||||||
|
[ bhargava ]
|
||||||
|
* Change interface in osmo-bts for 11 bit RACH
|
||||||
|
* Update parameters in osmo-bts-sysmo for 11bit RACH
|
||||||
|
* 11bit RACH support for osmo-bts-litecell15
|
||||||
|
* Initialize parameters in osmo-trx for 11bit RACH
|
||||||
|
|
||||||
|
[ Philipp ]
|
||||||
|
* octphy: Fixing missing payload type in ph. chan. activation
|
||||||
|
* octphy: Fixing band selection for ARFCN 0
|
||||||
|
* octphy: reintroducing multi-trx support
|
||||||
|
* octopy: fixing renamed constant
|
||||||
|
* octphy: prevent mismatch between dsp-firmware and octphy headers
|
||||||
|
* rsl: improving the log output
|
||||||
|
* octphy: multi-trx support: fix AC_CHECK order
|
||||||
|
* RSL: drop obsolete NULL check
|
||||||
|
* RSL: add assertions to check args of public API
|
||||||
|
* OML: fix possible segfault: add NULL check in oml_ipa_set_attr()
|
||||||
|
* CTRL: make the CTRL-Interface IP address configurable
|
||||||
|
* l1sap: Fix expired rach slot counting
|
||||||
|
* l1sap: fix missing 'else's causing wrong rach frame expiry counts
|
||||||
|
* octphy: set tx attenuation via VTY
|
||||||
|
* octphy: Improve OML ADM state handling
|
||||||
|
|
||||||
|
[ Yves Godin ]
|
||||||
|
* DTX: fix 1st RTP packet drop
|
||||||
|
|
||||||
|
[ Alexander Chemeris ]
|
||||||
|
* l1sap: Fix use-after-free in loopback mode.
|
||||||
|
* vty: Add commands to manually activate/deactivate a channel.
|
||||||
|
* trx: Add "maxdlynb" VTY command to control max TA for Normal Bursts.
|
||||||
|
* rsl: Output RTP stats before closing the socket.
|
||||||
|
* osmo-bts-trx: Fix MS power control loop.
|
||||||
|
* osmo-bts-trx: Remove an unused variable. Resolves a compiler warning.
|
||||||
|
* osmo-bts-trx: Increase a maximum allowed MS power reduction step from 2dB to 4dB.
|
||||||
|
* Fix static build of osmo-bts-trx and osmo-bts-virtual.
|
||||||
|
|
||||||
|
[ Jean-Francois Dionne ]
|
||||||
|
* DTX: don't always perform AMR HR specific check
|
||||||
|
* DTX: fix SID-FIRST detection
|
||||||
|
* lc15,sysmobts l1_if: fix memleak in handle_mph_time_ind()
|
||||||
|
* sysmo,lc15: fix memory leak at each call placed
|
||||||
|
* DTX: fix "unexpected burst" error
|
||||||
|
* Fix AMR HR DTX FSM logic.
|
||||||
|
* Fix SACCH channel release indication not sent to BSC after location update.
|
||||||
|
* Fix RTP duration adjustment not done when speech resumes in DTX mode.
|
||||||
|
|
||||||
|
[ Ruben Undheim ]
|
||||||
|
* Fix some spelling errors
|
||||||
|
|
||||||
|
[ Holger Freyther ]
|
||||||
|
* Revert "deb: use gsm_data_shared.* from openbsc-dev"
|
||||||
|
|
||||||
|
[ Philipp Maier ]
|
||||||
|
* octphy VTY: fix vty write output for octphy's phy section
|
||||||
|
* octphy: Fix VTY commands
|
||||||
|
* l1sap: fix rach reason (ra) parsing
|
||||||
|
* l1sap: fix PTCCH detection
|
||||||
|
* octphy: fix usage of wrong define constant
|
||||||
|
* octphy: add CBCH support
|
||||||
|
* l1sap: improve log output
|
||||||
|
* octphy: print log message for multi-trx support
|
||||||
|
* octphy: display hint in case of wrongly configured transceiver number
|
||||||
|
* octphy: add conditional compilation to support latest octasic header release
|
||||||
|
* octphy: set tx/rx antenne IDs via VTY
|
||||||
|
* bts: revert trx shutdown order
|
||||||
|
* octphy: activate CBCH after all physical channels are activated
|
||||||
|
* octphy: align frame number for new firmware versions
|
||||||
|
* octphy: ensure that 11 bit rach flag is not set
|
||||||
|
* measurement: fix measurement reporting period
|
||||||
|
* measurement: make lchan_meas_check_compute() available to l1sap.c
|
||||||
|
* measurement: Compute measurement results on measurement idication
|
||||||
|
* measurement: exclude idle channels from uplink measurement
|
||||||
|
* octphy: integrate channel measurement handling
|
||||||
|
* octphy: remove old event control code
|
||||||
|
* osmo-bts-sysmo: Include frame number in MEAS IND
|
||||||
|
* measurement: fix measurement computation
|
||||||
|
* octphy: fix segfault
|
||||||
|
* Revert "measurement: exclude idle channels from uplink measurement"
|
||||||
|
* sysmobts: normalize frame number in measurement indication
|
||||||
|
* measurement: Improve log output
|
||||||
|
* measurement: improve log output
|
||||||
|
* octphy: improve log output
|
||||||
|
* octphy: initalize l1msg and only when needed
|
||||||
|
* octphy: initalize nmsg only when needed
|
||||||
|
* octphy: remove log output
|
||||||
|
* Revert "sysmobts: normalize frame number in measurement indication"
|
||||||
|
* osmo-bts-trx: fix missing frame number in MEAS IND
|
||||||
|
* osmo-bts-litecell15: Fix missing frame number in MEAS IND
|
||||||
|
* Revert "osmo-bts-sysmo: Include frame number in MEAS IND"
|
||||||
|
* octphy: complete value strings (octphy_cid_vals)
|
||||||
|
* octphy: do not send empty frames to phy
|
||||||
|
* osmo-bts-sysmo: Include frame number in MEAS IND
|
||||||
|
* measurement: fix measurment report
|
||||||
|
* octphy: remap frame number in MEAS_IND
|
||||||
|
* octphy: implement support for dynamic timeslots
|
||||||
|
|
||||||
|
[ Ivan Klyuchnikov ]
|
||||||
|
* osmo-trx-bts: Fix incorrect setting of RXGAIN and POWER parameters on second channel (TRX1) of osmo-trx
|
||||||
|
* osmo-trx-bts: Fix osmo-bts-trx crash on startup during reading phy instance parameters from config file
|
||||||
|
* osmo-trx-bts: Fix incorrect bts shutdown procedure in case of abis connection closure
|
||||||
|
* osmo-trx-bts: Fix incorrect bts shutdown procedure in case of clock loss from osmo-trx
|
||||||
|
|
||||||
|
[ Ivan Kluchnikov ]
|
||||||
|
* oml: Fix incorrect usage of const variable abis_nm_att_tlvdef_ipa
|
||||||
|
|
||||||
|
[ Pau Espin Pedrol ]
|
||||||
|
* phy_link: Fix typo in state being printed
|
||||||
|
* trx: Allow BTS and TRX to be on different IPs
|
||||||
|
* trx: Save osmotrx base-port vty properties
|
||||||
|
* sysmo/tch.c: Clean up use of empty buffer
|
||||||
|
* litecell15/tch.c: Clean up use of empty buffer
|
||||||
|
* Use L1P instead of L1C for TCH logging and allocation
|
||||||
|
* Fix annoying trailing whitespace
|
||||||
|
* sysmo, litecell15: Make sure all TCH events are triggered
|
||||||
|
* sysmo: Remove non longer valid -p option from help
|
||||||
|
* Allow passing low link quality buffers to upper layers
|
||||||
|
* l1sap.c: Avoid sending RTP frame with empty payload
|
||||||
|
* l1sap.c: fn_ms_adj: Add err logging and always return GSM_RTP_DURATION
|
||||||
|
* Move dump_gsmtime to libosmocore as osmo_dump_gsmtime
|
||||||
|
* Use osmo_dump_gsmtime to log fn across different layers
|
||||||
|
* lc15bts-mgr.cfg: Set default vswr to a value inside valid range
|
||||||
|
* litecell15: Register in vty limits for paX_pwr
|
||||||
|
* lc15: Tweak led colors used in service file
|
||||||
|
* lc-15, sysmo: l1_if: print name on PH-DATA.ind unknwon sapi
|
||||||
|
* lc15bts-mgr.service: Prepare dirs and sysctls for the process
|
||||||
|
* osmo-bts-trx: Enable osmotrx tx-attenuation oml by default
|
||||||
|
* osmo-bts-trx: Relax validation to allow TRX data bursts without padding
|
||||||
|
|
||||||
|
[ Sebastian Stumpf ]
|
||||||
|
* VIRT-PHY: Added example configurations for openbsc and osmobts.
|
||||||
|
* VIRT-PHY: Fixed timeslot in gsmtap-msg on downlink which was always 0.
|
||||||
|
* VIRT-PHY: Added test option for fast hyperframe repeat.
|
||||||
|
|
||||||
|
-- Max <msuraev@sysmocom.de> Fri, 25 Aug 2017 15:16:56 +0200
|
||||||
|
|
||||||
|
osmo-bts (0.5.0) unstable; urgency=medium
|
||||||
|
|
||||||
|
* Initial release.
|
||||||
|
|
||||||
|
-- Holger Hans Peter Freyther <holger@moiji-mobile.com> Fri, 01 Apr 2016 16:13:40 +0200
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
9
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
Source: osmo-bts
|
||||||
|
Maintainer: Holger Hans Peter Freyther <holger@moiji-mobile.com>
|
||||||
|
Section: net
|
||||||
|
Priority: optional
|
||||||
|
Build-Depends: debhelper (>= 9),
|
||||||
|
pkg-config,
|
||||||
|
dh-autoreconf,
|
||||||
|
dh-systemd (>= 1.5),
|
||||||
|
autotools-dev,
|
||||||
|
pkg-config,
|
||||||
|
libosmocore-dev,
|
||||||
|
libosmo-abis-dev,
|
||||||
|
libgps-dev,
|
||||||
|
libortp-dev,
|
||||||
|
txt2man
|
||||||
|
Standards-Version: 3.9.8
|
||||||
|
Vcs-Browser: http://git.osmocom.org/osmo-bts/
|
||||||
|
Vcs-Git: git://git.osmocom.org/osmo-bts
|
||||||
|
Homepage: https://projects.osmocom.org/projects/osmobts
|
||||||
|
|
||||||
|
Package: osmo-bts-trx
|
||||||
|
Architecture: any
|
||||||
|
Depends: ${shlibs:Depends}, ${misc:Depends}
|
||||||
|
Description: osmo-bts-trx GSM BTS with osmo-trx
|
||||||
|
osmo-bts-trx to be used with the osmo-trx application
|
||||||
|
|
||||||
|
Package: osmo-bts-trx-dbg
|
||||||
|
Architecture: any
|
||||||
|
Section: debug
|
||||||
|
Priority: extra
|
||||||
|
Depends: osmo-bts-trx (= ${binary:Version}), ${misc:Depends}
|
||||||
|
Description: Debug symbols for the osmo-bts-trx
|
||||||
|
Make debugging possible
|
||||||
|
|
||||||
|
Package: osmo-bts-virtual
|
||||||
|
Architecture: any
|
||||||
|
Depends: ${shlibs:Depends}, ${misc:Depends}
|
||||||
|
Description: Virtual Osmocom GSM BTS (no RF hardware; GSMTAP/UDP)
|
||||||
|
This version of OsmoBTS doesn't use actual GSM PHY/Hardware/RF, but
|
||||||
|
utilizes GSMTAP-over-UDP frames for the Um interface. This is useful
|
||||||
|
in fully virtualized setups e.g. in combination with OsmocomBB virt_phy.
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||||
|
Upstream-Name: osmo-bts
|
||||||
|
Source: http://cgit.osmocom.org/osmo-bts/
|
||||||
|
|
||||||
|
Files: *
|
||||||
|
Copyright: 2008-2014 Harald Welte <laforge@gnumonks.org>
|
||||||
|
2009,2011,2013 Andreas Eversberg <jolly@eversberg.eu>
|
||||||
|
2010,2011 On-Waves
|
||||||
|
2012-2015 Holger Hans Peter Freyther
|
||||||
|
2014 sysmocom s.f.m.c. Gmbh
|
||||||
|
2015 Alexander Chemeris <Alexander.Chemeris@fairwaves.co>
|
||||||
|
License: AGPL-3+
|
||||||
|
|
||||||
|
Files: src/osmo-bts-sysmo/eeprom.c
|
||||||
|
src/osmo-bts-sysmo/eeprom.h
|
||||||
|
Copyright: 2012 Nutaq
|
||||||
|
License: MIT
|
||||||
|
Comment: Yves Godin is the author
|
||||||
|
|
||||||
|
Files: src/common/pcu_sock.c
|
||||||
|
Copyright: 2008-2010 Harald Welte <laforge@gnumonks.org>
|
||||||
|
2009-2012 Andreas Eversberg <jolly@eversberg.eu>
|
||||||
|
2012 Holger Hans Peter Freyther
|
||||||
|
License: GPL-2+
|
||||||
|
|
||||||
|
Files: debian/*
|
||||||
|
Copyright: 2015-2016 Ruben Undheim <ruben.undheim@gmail.com>
|
||||||
|
License: AGPL-3+
|
||||||
|
|
||||||
|
|
||||||
|
License: AGPL-3+
|
||||||
|
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/>.
|
||||||
|
|
||||||
|
|
||||||
|
License: GPL-2+
|
||||||
|
This package is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 2 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 General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
.
|
||||||
|
On Debian systems, the complete text of the GNU General
|
||||||
|
Public License version 2 can be found in "/usr/share/common-licenses/GPL-2".
|
||||||
|
|
||||||
|
|
||||||
|
License: MIT
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
of the Software, and to permit persons to whom the Software is furnished to do
|
||||||
|
so, subject to the following conditions:
|
||||||
|
.
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
.
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
usr/bin/osmo-bts-trx
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Osmocom osmo-bts for osmo-trx
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
ExecStart=/usr/bin/osmo-bts-trx -s -c /etc/osmocom/osmo-bts.cfg
|
||||||
|
Restart=always
|
||||||
|
RestartSec=2
|
||||||
|
|
||||||
|
# Let it process messages quickly enough
|
||||||
|
CPUSchedulingPolicy=rr
|
||||||
|
CPUSchedulingPriority=1
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
usr/bin/osmo-bts-virtual
|
||||||
|
usr/bin/osmo-bts-omldummy
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Osmocom GSM BTS for virtual Um layer based on GSMTAP/UDP
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
ExecStart=/usr/bin/osmo-bts-virtual -s -c /etc/osmocom/osmo-bts-virtual.cfg
|
||||||
|
Restart=always
|
||||||
|
RestartSec=2
|
||||||
|
|
||||||
|
# Let it process messages quickly enough
|
||||||
|
CPUSchedulingPolicy=rr
|
||||||
|
CPUSchedulingPriority=1
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
#!/usr/bin/make -f
|
||||||
|
|
||||||
|
DEBIAN := $(shell dpkg-parsechangelog | grep ^Version: | cut -d' ' -f2)
|
||||||
|
DEBVERS := $(shell echo '$(DEBIAN)' | cut -d- -f1)
|
||||||
|
VERSION := $(shell echo '$(DEBVERS)' | sed -e 's/[+-].*//' -e 's/~//g')
|
||||||
|
|
||||||
|
#export DH_VERBOSE=1
|
||||||
|
export DEB_BUILD_MAINT_OPTIONS = hardening=+all
|
||||||
|
|
||||||
|
|
||||||
|
%:
|
||||||
|
dh $@ --with=systemd --with autoreconf --fail-missing
|
||||||
|
|
||||||
|
override_dh_strip:
|
||||||
|
dh_strip --dbg-package=osmo-bts-trx-dbg
|
||||||
|
|
||||||
|
override_dh_autoreconf:
|
||||||
|
echo $(VERSION) > .tarball-version
|
||||||
|
dh_autoreconf
|
||||||
|
|
||||||
|
override_dh_auto_configure:
|
||||||
|
dh_auto_configure -- --enable-trx
|
||||||
|
|
||||||
|
override_dh_clean:
|
||||||
|
dh_clean
|
||||||
|
$(RM) tests/package.m4
|
||||||
|
$(RM) tests/testsuite
|
||||||
|
|
||||||
|
# Print test results in case of a failure
|
||||||
|
override_dh_auto_test:
|
||||||
|
dh_auto_test || (find . -name testsuite.log -exec cat {} \; ; false)
|
||||||
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
3.0 (native)
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
The osmo-bts control interface is currently supporting the following operations:
|
||||||
|
|
||||||
|
h2. generic
|
||||||
|
|
||||||
|
h3. trx.0.thermal-attenuation
|
||||||
|
|
||||||
|
The idea of this paramter 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.
|
||||||
|
|
||||||
|
Please note that all values in the context of transmit power calculation
|
||||||
|
are integers in milli-dB (1/10000 bel), so the below example is setting
|
||||||
|
the attenuation at 3 dB:
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
bsc_control.py -d localhost -p 4238 -s trx.0.thermal-attenuation 3000
|
||||||
|
Got message: SET_REPLY 1 trx.0.thermal-attenuation 3000
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
bsc_control.py -d localhost -p 4238 -g trx.0.thermal-attenuation
|
||||||
|
Got message: GET_REPLY 1 trx.0.thermal-attenuation 3000
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
|
||||||
|
h2. sysmobts specific
|
||||||
|
|
||||||
|
h3. trx.0.clock-info
|
||||||
|
|
||||||
|
obtain information on the current clock status:
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
bsc_control.py -d localhost -p 4238 -g trx.0.clock-info
|
||||||
|
Got message: GET_REPLY 1 trx.0.clock-info -100,ocxo,0,0,gps
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
which is to be interpreted as:
|
||||||
|
* current clock correction value is -100 ppb
|
||||||
|
* current clock source is OCXO
|
||||||
|
* deviation between clock source and calibration source is 0 ppb
|
||||||
|
* resolution of clock error measurement is 0 ppt (0 means no result yet)
|
||||||
|
* current calibration source is GPS
|
||||||
|
|
||||||
|
When this attribute is set, any value passed on is discarded, but the clock
|
||||||
|
calibration process is re-started.
|
||||||
|
|
||||||
|
|
||||||
|
h3. trx.0.clock-correction
|
||||||
|
|
||||||
|
This attribute can get and set the current clock correction value:
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
bsc_control.py -d localhost -p 4238 -g trx.0.clock-correction
|
||||||
|
Got message: GET_REPLY 1 trx.0.clock-correction -100
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
bsc_control.py -d localhost -p 4238 -s trx.0.clock-correction -- -99
|
||||||
|
Got message: SET_REPLY 1 trx.0.clock-correction success
|
||||||
|
</pre>
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
!
|
||||||
|
! OsmoBTS configuration example for CalypsoBTS
|
||||||
|
! http://osmocom.org/projects/baseband/wiki/CalypsoBTS
|
||||||
|
!!
|
||||||
|
!
|
||||||
|
log stderr
|
||||||
|
logging color 1
|
||||||
|
logging timestamp 0
|
||||||
|
logging level rsl notice
|
||||||
|
logging level oml notice
|
||||||
|
logging level rll notice
|
||||||
|
logging level rr notice
|
||||||
|
logging level meas error
|
||||||
|
logging level pag error
|
||||||
|
logging level l1c error
|
||||||
|
logging level l1p error
|
||||||
|
logging level dsp error
|
||||||
|
logging level abis error
|
||||||
|
!
|
||||||
|
line vty
|
||||||
|
no login
|
||||||
|
!
|
||||||
|
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
|
||||||
|
osmotrx ms-power-loop -65
|
||||||
|
osmotrx legacy-setbsic
|
||||||
|
bts 0
|
||||||
|
oml remote-ip 127.0.0.1
|
||||||
|
ipa unit-id 1801 0
|
||||||
|
gsmtap-sapi pdtch
|
||||||
|
gsmtap-sapi ccch
|
||||||
|
band 900
|
||||||
|
trx 0
|
||||||
|
phy 0 instance 0
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
!
|
||||||
|
! lc15bts-mgr (0.3.0.284-a7c2-dirty) configuration saved from vty
|
||||||
|
!!
|
||||||
|
!
|
||||||
|
log stderr
|
||||||
|
logging filter all 1
|
||||||
|
logging color 1
|
||||||
|
logging print category 0
|
||||||
|
logging timestamp 0
|
||||||
|
logging level temp info
|
||||||
|
logging level fw info
|
||||||
|
logging level find info
|
||||||
|
logging level calib info
|
||||||
|
logging level lglobal notice
|
||||||
|
logging level llapd notice
|
||||||
|
logging level linp notice
|
||||||
|
logging level lmux notice
|
||||||
|
logging level lmi notice
|
||||||
|
logging level lmib notice
|
||||||
|
logging level lsms notice
|
||||||
|
logging level lctrl notice
|
||||||
|
logging level lgtp notice
|
||||||
|
!
|
||||||
|
line vty
|
||||||
|
no login
|
||||||
|
!
|
||||||
|
lc15bts-mgr
|
||||||
|
limits supply_volt
|
||||||
|
threshold warning min 17500
|
||||||
|
threshold critical min 19000
|
||||||
|
limits tx0_vswr
|
||||||
|
threshold warning max 1000
|
||||||
|
limits tx1_vswr
|
||||||
|
threshold warning max 1000
|
||||||
|
limits supply_pwr
|
||||||
|
threshold warning max 110
|
||||||
|
threshold critical max 120
|
||||||
|
limits pa0_pwr
|
||||||
|
threshold warning max 50
|
||||||
|
threshold critical max 60
|
||||||
|
limits pa1_pwr
|
||||||
|
threshold warning max 50
|
||||||
|
threshold critical max 60
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
!
|
||||||
|
! OsmoBTS (0.0.1.100-0455-dirty) configuration saved from vty
|
||||||
|
!!
|
||||||
|
!
|
||||||
|
log stderr
|
||||||
|
logging color 1
|
||||||
|
logging timestamp 0
|
||||||
|
logging level rsl info
|
||||||
|
logging level oml info
|
||||||
|
logging level rll notice
|
||||||
|
logging level rr notice
|
||||||
|
logging level meas notice
|
||||||
|
logging level pag info
|
||||||
|
logging level l1c info
|
||||||
|
logging level l1p info
|
||||||
|
logging level dsp debug
|
||||||
|
logging level abis notice
|
||||||
|
logging level rtp notice
|
||||||
|
logging level lglobal notice
|
||||||
|
logging level llapd notice
|
||||||
|
logging level linp notice
|
||||||
|
logging level lmux notice
|
||||||
|
logging level lmi notice
|
||||||
|
logging level lmib notice
|
||||||
|
logging level lsms notice
|
||||||
|
!
|
||||||
|
line vty
|
||||||
|
no login
|
||||||
|
!
|
||||||
|
phy 0
|
||||||
|
instance 0
|
||||||
|
trx-calibration-path /mnt/rom/factory/calib
|
||||||
|
phy 1
|
||||||
|
instance 0
|
||||||
|
trx-calibration-path /mnt/rom/factory/calib
|
||||||
|
bts 0
|
||||||
|
band 900
|
||||||
|
ipa unit-id 1500 0
|
||||||
|
oml remote-ip 192.168.234.185
|
||||||
|
trx 0
|
||||||
|
phy 0 instance 0
|
||||||
|
trx 1
|
||||||
|
phy 1 instance 0
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
!
|
||||||
|
! OsmoBTS () configuration saved from vty
|
||||||
|
!!
|
||||||
|
!
|
||||||
|
log stderr
|
||||||
|
logging color 1
|
||||||
|
logging timestamp 0
|
||||||
|
logging level rsl info
|
||||||
|
logging level oml info
|
||||||
|
logging level rll notice
|
||||||
|
logging level rr notice
|
||||||
|
logging level meas notice
|
||||||
|
logging level pag info
|
||||||
|
logging level l1c info
|
||||||
|
logging level l1p info
|
||||||
|
logging level dsp info
|
||||||
|
logging level abis notice
|
||||||
|
!
|
||||||
|
line vty
|
||||||
|
no login
|
||||||
|
!
|
||||||
|
phy 0
|
||||||
|
octphy hw-addr 00:0c:de:ad:fa:ce
|
||||||
|
octphy net-device eth2
|
||||||
|
instance 0
|
||||||
|
instance 1
|
||||||
|
bts 0
|
||||||
|
band 1800
|
||||||
|
ipa unit-id 1234 0
|
||||||
|
oml remote-ip 127.0.0.1
|
||||||
|
trx 0
|
||||||
|
phy 0 instance 0
|
||||||
|
trx 1
|
||||||
|
phy 0 instance 1
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
!
|
||||||
|
! OsmoBTS () configuration saved from vty
|
||||||
|
!!
|
||||||
|
!
|
||||||
|
log stderr
|
||||||
|
logging color 1
|
||||||
|
logging timestamp 0
|
||||||
|
logging level rsl info
|
||||||
|
logging level oml info
|
||||||
|
logging level rll notice
|
||||||
|
logging level rr notice
|
||||||
|
logging level meas notice
|
||||||
|
logging level pag info
|
||||||
|
logging level l1c info
|
||||||
|
logging level l1p info
|
||||||
|
logging level dsp info
|
||||||
|
logging level abis notice
|
||||||
|
!
|
||||||
|
line vty
|
||||||
|
no login
|
||||||
|
!
|
||||||
|
phy 0
|
||||||
|
octphy hw-addr 00:0C:90:2e:80:1e
|
||||||
|
octphy net-device eth0.2342
|
||||||
|
instance 0
|
||||||
|
bts 0
|
||||||
|
band 1800
|
||||||
|
ipa unit-id 1234 0
|
||||||
|
oml remote-ip 127.0.0.1
|
||||||
|
trx 0
|
||||||
|
phy 0 instance 0
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
!
|
||||||
|
! OsmoBTS () configuration saved from vty
|
||||||
|
!!
|
||||||
|
!
|
||||||
|
log stderr
|
||||||
|
logging color 1
|
||||||
|
logging timestamp 0
|
||||||
|
logging level rsl info
|
||||||
|
logging level oml info
|
||||||
|
logging level rll notice
|
||||||
|
logging level rr notice
|
||||||
|
logging level meas notice
|
||||||
|
logging level pag info
|
||||||
|
logging level l1c info
|
||||||
|
logging level l1p info
|
||||||
|
logging level dsp info
|
||||||
|
logging level abis notice
|
||||||
|
!
|
||||||
|
line vty
|
||||||
|
no login
|
||||||
|
!
|
||||||
|
phy 0
|
||||||
|
instance 0
|
||||||
|
bts 0
|
||||||
|
band 1800
|
||||||
|
ipa unit-id 666 0
|
||||||
|
oml remote-ip 10.1.2.3
|
||||||
|
trx 0
|
||||||
|
phy 0 instance 0
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
!
|
||||||
|
! SysmoMgr (0.3.0.141-33e5) configuration saved from vty
|
||||||
|
!!
|
||||||
|
!
|
||||||
|
log stderr
|
||||||
|
logging filter all 1
|
||||||
|
logging color 1
|
||||||
|
logging timestamp 0
|
||||||
|
logging level temp info
|
||||||
|
logging level fw info
|
||||||
|
logging level find info
|
||||||
|
logging level lglobal notice
|
||||||
|
logging level llapd notice
|
||||||
|
logging level linp notice
|
||||||
|
logging level lmux notice
|
||||||
|
logging level lmi notice
|
||||||
|
logging level lmib notice
|
||||||
|
logging level lsms notice
|
||||||
|
!
|
||||||
|
line vty
|
||||||
|
no login
|
||||||
|
!
|
||||||
|
sysmobts-mgr
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
!
|
||||||
|
! OsmoBTS () configuration saved from vty
|
||||||
|
!!
|
||||||
|
!
|
||||||
|
log stderr
|
||||||
|
logging color 1
|
||||||
|
logging timestamp 0
|
||||||
|
logging level rsl notice
|
||||||
|
logging level oml notice
|
||||||
|
logging level rll notice
|
||||||
|
logging level rr notice
|
||||||
|
logging level meas error
|
||||||
|
logging level pag error
|
||||||
|
logging level l1c error
|
||||||
|
logging level l1p error
|
||||||
|
logging level dsp error
|
||||||
|
logging level abis error
|
||||||
|
!
|
||||||
|
line vty
|
||||||
|
no login
|
||||||
|
!
|
||||||
|
phy 0
|
||||||
|
instance 0
|
||||||
|
osmotrx rx-gain 1
|
||||||
|
osmotrx ip local 127.0.0.1
|
||||||
|
osmotrx ip remote 127.0.0.1
|
||||||
|
bts 0
|
||||||
|
band 1800
|
||||||
|
ipa unit-id 6969 0
|
||||||
|
oml remote-ip 192.168.122.1
|
||||||
|
gsmtap-sapi ccch
|
||||||
|
gsmtap-sapi pdtch
|
||||||
|
trx 0
|
||||||
|
phy 0 instance 0
|
||||||
@@ -0,0 +1,151 @@
|
|||||||
|
!
|
||||||
|
! OpenBSC (0.15.0.629-34f0-dirty) configuration saved from vty
|
||||||
|
!!
|
||||||
|
!
|
||||||
|
log stderr
|
||||||
|
logging filter all 1
|
||||||
|
logging color 0
|
||||||
|
logging print category 1
|
||||||
|
logging timestamp 1
|
||||||
|
logging level all info
|
||||||
|
logging level rll notice
|
||||||
|
logging level cc notice
|
||||||
|
logging level mm debug
|
||||||
|
logging level rr notice
|
||||||
|
logging level rsl notice
|
||||||
|
logging level nm info
|
||||||
|
logging level mncc notice
|
||||||
|
logging level pag notice
|
||||||
|
logging level meas notice
|
||||||
|
logging level sccp notice
|
||||||
|
logging level msc notice
|
||||||
|
logging level mgcp notice
|
||||||
|
logging level ho notice
|
||||||
|
logging level db notice
|
||||||
|
logging level ref notice
|
||||||
|
logging level gprs debug
|
||||||
|
logging level ns info
|
||||||
|
logging level bssgp debug
|
||||||
|
logging level llc debug
|
||||||
|
logging level sndcp debug
|
||||||
|
logging level nat notice
|
||||||
|
logging level ctrl notice
|
||||||
|
logging level smpp debug
|
||||||
|
logging level filter debug
|
||||||
|
logging level ranap debug
|
||||||
|
logging level sua debug
|
||||||
|
logging level lglobal notice
|
||||||
|
logging level llapd notice
|
||||||
|
logging level linp notice
|
||||||
|
logging level lmux notice
|
||||||
|
logging level lmi notice
|
||||||
|
logging level lmib notice
|
||||||
|
logging level lsms notice
|
||||||
|
logging level lctrl notice
|
||||||
|
logging level lgtp notice
|
||||||
|
logging level lstats notice
|
||||||
|
logging level lgsup notice
|
||||||
|
logging level loap notice
|
||||||
|
!
|
||||||
|
stats interval 5
|
||||||
|
!
|
||||||
|
line vty
|
||||||
|
no login
|
||||||
|
!
|
||||||
|
e1_input
|
||||||
|
e1_line 0 driver ipa
|
||||||
|
e1_line 0 port 0
|
||||||
|
no e1_line 0 keepalive
|
||||||
|
network
|
||||||
|
network country code 262
|
||||||
|
mobile network code 42
|
||||||
|
short name OpenBSC
|
||||||
|
long name OpenBSC
|
||||||
|
auth policy accept-all
|
||||||
|
authorized-regexp .*
|
||||||
|
location updating reject cause 13
|
||||||
|
encryption a5 0
|
||||||
|
neci 1
|
||||||
|
paging any use tch 0
|
||||||
|
rrlp mode ms-based
|
||||||
|
mm info 1
|
||||||
|
handover 0
|
||||||
|
handover window rxlev averaging 10
|
||||||
|
handover window rxqual averaging 1
|
||||||
|
handover window rxlev neighbor averaging 10
|
||||||
|
handover power budget interval 6
|
||||||
|
handover power budget hysteresis 3
|
||||||
|
handover maximum distance 9999
|
||||||
|
timer t3101 10
|
||||||
|
timer t3103 0
|
||||||
|
timer t3105 0
|
||||||
|
timer t3107 0
|
||||||
|
timer t3109 4
|
||||||
|
timer t3111 0
|
||||||
|
timer t3113 60
|
||||||
|
timer t3115 0
|
||||||
|
timer t3117 0
|
||||||
|
timer t3119 0
|
||||||
|
timer t3122 10
|
||||||
|
timer t3141 0
|
||||||
|
subscriber-keep-in-ram 0
|
||||||
|
bts 0
|
||||||
|
type sysmobts
|
||||||
|
band DCS1800
|
||||||
|
cell_identity 6969
|
||||||
|
location_area_code 1
|
||||||
|
base_station_id_code 63
|
||||||
|
ms max power 0
|
||||||
|
cell reselection hysteresis 4
|
||||||
|
rxlev access min 0
|
||||||
|
periodic location update 30
|
||||||
|
radio-link-timeout 32
|
||||||
|
channel allocator descending
|
||||||
|
rach tx integer 9
|
||||||
|
rach max transmission 7
|
||||||
|
channel-descrption attach 1
|
||||||
|
channel-descrption bs-pa-mfrms 5
|
||||||
|
channel-descrption bs-ag-blks-res 1
|
||||||
|
ip.access unit_id 6969 0
|
||||||
|
oml ip.access stream_id 255 line 0
|
||||||
|
neighbor-list mode automatic
|
||||||
|
codec-support fr
|
||||||
|
gprs mode none
|
||||||
|
no force-combined-si
|
||||||
|
trx 0
|
||||||
|
rf_locked 0
|
||||||
|
arfcn 666
|
||||||
|
nominal power 0
|
||||||
|
max_power_red 0
|
||||||
|
rsl e1 tei 0
|
||||||
|
timeslot 0
|
||||||
|
phys_chan_config CCCH+SDCCH4
|
||||||
|
hopping enabled 0
|
||||||
|
timeslot 1
|
||||||
|
phys_chan_config SDCCH8
|
||||||
|
hopping enabled 0
|
||||||
|
timeslot 2
|
||||||
|
phys_chan_config TCH/F
|
||||||
|
hopping enabled 0
|
||||||
|
timeslot 3
|
||||||
|
phys_chan_config TCH/F
|
||||||
|
hopping enabled 0
|
||||||
|
timeslot 4
|
||||||
|
phys_chan_config TCH/F
|
||||||
|
hopping enabled 0
|
||||||
|
timeslot 5
|
||||||
|
phys_chan_config TCH/F
|
||||||
|
hopping enabled 0
|
||||||
|
timeslot 6
|
||||||
|
phys_chan_config TCH/F
|
||||||
|
hopping enabled 0
|
||||||
|
timeslot 7
|
||||||
|
phys_chan_config TCH/F
|
||||||
|
hopping enabled 0
|
||||||
|
mncc-int
|
||||||
|
default-codec tch-f fr
|
||||||
|
default-codec tch-h hr
|
||||||
|
nitb
|
||||||
|
subscriber-create-on-demand
|
||||||
|
subscriber-create-on-demand random 1 24
|
||||||
|
assign-tmsi
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
!
|
||||||
|
! OsmoBTS (0.4.0.216-bc49-dirty) configuration saved from vty
|
||||||
|
!!
|
||||||
|
!
|
||||||
|
log stderr
|
||||||
|
logging filter all 0
|
||||||
|
logging color 0
|
||||||
|
logging print category 1
|
||||||
|
logging timestamp 0
|
||||||
|
logging level rsl info
|
||||||
|
logging level oml info
|
||||||
|
logging level rll notice
|
||||||
|
logging level rr notice
|
||||||
|
logging level meas notice
|
||||||
|
logging level pag info
|
||||||
|
logging level l1c info
|
||||||
|
logging level l1p info
|
||||||
|
logging level dsp error
|
||||||
|
logging level pcu notice
|
||||||
|
logging level ho debug
|
||||||
|
logging level trx notice
|
||||||
|
logging level loop notice
|
||||||
|
logging level abis debug
|
||||||
|
logging level rtp notice
|
||||||
|
logging level sum error
|
||||||
|
logging level lglobal notice
|
||||||
|
logging level llapd notice
|
||||||
|
logging level linp notice
|
||||||
|
logging level lmux notice
|
||||||
|
logging level lmi notice
|
||||||
|
logging level lmib notice
|
||||||
|
logging level lsms notice
|
||||||
|
logging level lctrl notice
|
||||||
|
logging level lgtp notice
|
||||||
|
logging level lstats error
|
||||||
|
!
|
||||||
|
line vty
|
||||||
|
no login
|
||||||
|
!
|
||||||
|
e1_input
|
||||||
|
e1_line 0 driver ipa
|
||||||
|
e1_line 0 port 0
|
||||||
|
no e1_line 0 keepalive
|
||||||
|
phy 0
|
||||||
|
instance 0
|
||||||
|
bts 0
|
||||||
|
band DCS1800
|
||||||
|
ipa unit-id 6969 0
|
||||||
|
oml remote-ip 127.0.0.1
|
||||||
|
rtp jitter-buffer 100
|
||||||
|
paging queue-size 200
|
||||||
|
paging lifetime 0
|
||||||
|
uplink-power-target -75
|
||||||
|
min-qual-rach 50
|
||||||
|
min-qual-norm -5
|
||||||
|
trx 0
|
||||||
|
power-ramp max-initial 23000 mdBm
|
||||||
|
power-ramp step-size 2000 mdB
|
||||||
|
power-ramp step-interval 1
|
||||||
|
ms-power-control dsp
|
||||||
|
phy 0 instance 0
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
|
||||||
|
== OsmoBTS PHY interface abstraction
|
||||||
|
|
||||||
|
The OsmoBTS PHY interface serves as an abstraction layer between given
|
||||||
|
PHY hardware and the actual logical transceivers (TRXs) of a BTS inside
|
||||||
|
the OsmoBTS code base.
|
||||||
|
|
||||||
|
|
||||||
|
=== PHY link
|
||||||
|
|
||||||
|
A PHY link is a physical connection / link towards a given PHY. This
|
||||||
|
might be, for example,
|
||||||
|
|
||||||
|
* a set of file descriptors to device nodes in the /dev/ directory
|
||||||
|
(sysmobts, litecell15)
|
||||||
|
* a packet socket for sending raw Ethernet frames to an OCTPHY
|
||||||
|
* a set of UDP sockets for interacting with OsmoTRX
|
||||||
|
|
||||||
|
Each PHY interface has a set of attribute/parameters and a list of 1 to
|
||||||
|
n PHY instances.
|
||||||
|
|
||||||
|
PHY links are numbered 0..n globally inside OsmoBTS.
|
||||||
|
|
||||||
|
Each PHY link is configured via the VTY using its individual top-level
|
||||||
|
vty node. Given the different bts-model / phy specific properties, the
|
||||||
|
VTY configuration options (if any) of the PHY instance differ between
|
||||||
|
BTS models.
|
||||||
|
|
||||||
|
The PHY links and instances must be configured above the BTS/TRX nodes
|
||||||
|
in the configuration file. If the file is saved via the VTY, the code
|
||||||
|
automatically ensures this.
|
||||||
|
|
||||||
|
|
||||||
|
=== PHY instance
|
||||||
|
|
||||||
|
A PHY instance is an instance of a PHY, accessed via a PHY link.
|
||||||
|
|
||||||
|
In the case of osmo-bts-sysmo and osmo-bts-trx, there is only one
|
||||||
|
instance in every PHY link. This is due to the fact that the API inside
|
||||||
|
that PHY link does not permit for distinguishing multiple different
|
||||||
|
logical TRXs.
|
||||||
|
|
||||||
|
Other PHY implementations like the OCTPHY however do support addressing
|
||||||
|
multiple PHY instances via a single PHY link.
|
||||||
|
|
||||||
|
PHY instances are numbered 0..n inside each PHY link.
|
||||||
|
|
||||||
|
Each PHY instance is configured via the VTY as a separate node beneath each
|
||||||
|
PHY link. Given the different bts-model / phy specific properties, the
|
||||||
|
VTY configuration options (if any) of the PHY instance differ between
|
||||||
|
BTS models.
|
||||||
|
|
||||||
|
|
||||||
|
=== Mapping PHY instances to TRXs
|
||||||
|
|
||||||
|
Each TRX node in the VTY must use the 'phy N instance M' command in
|
||||||
|
order to specify which PHY instance is allocated to this specific TRX.
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
|
||||||
|
== start-up / sequencing during OsmoBTS start
|
||||||
|
|
||||||
|
The start-up procedure of OsmoBTS can be described as follows:
|
||||||
|
|
||||||
|
|===
|
||||||
|
| bts-specific | main() |
|
||||||
|
| common | bts_main() | initialization of talloc contexts
|
||||||
|
| common | osmo_init_logging2() | initialization of logging
|
||||||
|
| common | handle_options() | common option parsing
|
||||||
|
| bts-specific | bts_model_handle_options() | model-specific option parsing
|
||||||
|
| common | gsm_bts_alloc() | allocation of BTS/TRX/TS data structures
|
||||||
|
| common | vty_init() | Initialziation of VTY core, libosmo-abis and osmo-bts VTY
|
||||||
|
| common | main() | Setting of scheduler RR priority (if configured)
|
||||||
|
| common | main() | Initialization of GSMTAP (if configured)
|
||||||
|
| common | bts_init() | configuration of defaults in bts/trx/s object
|
||||||
|
| bts-specific | bts_model_init | ?
|
||||||
|
| common | abis_init() | Initialization of libosmo-abis
|
||||||
|
| common | vty_read_config_file() | Reading of configuration file
|
||||||
|
| bts-specific | bts_model_phy_link_set_defaults() | Called for every PHY link created
|
||||||
|
| bts-specific | bts_model_phy_instance_set_defaults() | Called for every PHY Instance created
|
||||||
|
| 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 | 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
|
||||||
|
| bts-specific | bts_model_phy_link_open() | Open each of the configured PHY links
|
||||||
|
| common | write_pid_file() | Generate the pid file
|
||||||
|
| common | osmo_daemonize() | Fork as daemon in background (if configured)
|
||||||
|
| common | bts_main() | Run main loop until global variable quit >= 2
|
||||||
|
| bts-specific | bts_model_oml_estab() | Called by core once OML link is established
|
||||||
|
| bts-specific | bts_model_check_oml() | called each time OML sets some attributes on a MO, checks if attributes are valid
|
||||||
|
| bts-specific | bts_model_apply_oml() | called each time OML sets some attributes on a MO, stores attribute contents in data structures
|
||||||
|
| bts-specific | bts_model_opstart() | for NM_OC_BTS, NM_OC_SITE_MANAGER, NM_OC_GPRS_NSE, NM_OC_GPRS_CELL, NMO_OC_GPRS_NSVC
|
||||||
|
| bts-specific | bts_model_opstart() | for NM_OC_RADIO_CARRIER for each trx
|
||||||
|
| bts-specific | bts_model_opstart() | for NM_OC_BASEB_TRANSC for each trx
|
||||||
|
| bts-specific | bts_model_opstart() | for NM_OC_CHANNEL for each timeslot on each trx
|
||||||
|
| bts-specific | bts_model_change_power() | change transmit power for each trx (power ramp-up/ramp-down
|
||||||
|
|
||||||
|
| bts-specific | bts_model_abis_close() | called when either one of the RSL links or the OML link are down
|
||||||
@@ -0,0 +1,151 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Print a version string.
|
||||||
|
scriptversion=2010-01-28.01
|
||||||
|
|
||||||
|
# Copyright (C) 2007-2010 Free Software Foundation, Inc.
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU 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 General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# This script is derived from GIT-VERSION-GEN from GIT: http://git.or.cz/.
|
||||||
|
# It may be run two ways:
|
||||||
|
# - from a git repository in which the "git describe" command below
|
||||||
|
# produces useful output (thus requiring at least one signed tag)
|
||||||
|
# - from a non-git-repo directory containing a .tarball-version file, which
|
||||||
|
# presumes this script is invoked like "./git-version-gen .tarball-version".
|
||||||
|
|
||||||
|
# In order to use intra-version strings in your project, you will need two
|
||||||
|
# separate generated version string files:
|
||||||
|
#
|
||||||
|
# .tarball-version - present only in a distribution tarball, and not in
|
||||||
|
# a checked-out repository. Created with contents that were learned at
|
||||||
|
# the last time autoconf was run, and used by git-version-gen. Must not
|
||||||
|
# be present in either $(srcdir) or $(builddir) for git-version-gen to
|
||||||
|
# give accurate answers during normal development with a checked out tree,
|
||||||
|
# but must be present in a tarball when there is no version control system.
|
||||||
|
# Therefore, it cannot be used in any dependencies. GNUmakefile has
|
||||||
|
# hooks to force a reconfigure at distribution time to get the value
|
||||||
|
# correct, without penalizing normal development with extra reconfigures.
|
||||||
|
#
|
||||||
|
# .version - present in a checked-out repository and in a distribution
|
||||||
|
# tarball. Usable in dependencies, particularly for files that don't
|
||||||
|
# want to depend on config.h but do want to track version changes.
|
||||||
|
# Delete this file prior to any autoconf run where you want to rebuild
|
||||||
|
# files to pick up a version string change; and leave it stale to
|
||||||
|
# minimize rebuild time after unrelated changes to configure sources.
|
||||||
|
#
|
||||||
|
# It is probably wise to add these two files to .gitignore, so that you
|
||||||
|
# don't accidentally commit either generated file.
|
||||||
|
#
|
||||||
|
# Use the following line in your configure.ac, so that $(VERSION) will
|
||||||
|
# automatically be up-to-date each time configure is run (and note that
|
||||||
|
# since configure.ac no longer includes a version string, Makefile rules
|
||||||
|
# should not depend on configure.ac for version updates).
|
||||||
|
#
|
||||||
|
# AC_INIT([GNU project],
|
||||||
|
# m4_esyscmd([build-aux/git-version-gen .tarball-version]),
|
||||||
|
# [bug-project@example])
|
||||||
|
#
|
||||||
|
# Then use the following lines in your Makefile.am, so that .version
|
||||||
|
# will be present for dependencies, and so that .tarball-version will
|
||||||
|
# exist in distribution tarballs.
|
||||||
|
#
|
||||||
|
# BUILT_SOURCES = $(top_srcdir)/.version
|
||||||
|
# $(top_srcdir)/.version:
|
||||||
|
# echo $(VERSION) > $@-t && mv $@-t $@
|
||||||
|
# dist-hook:
|
||||||
|
# echo $(VERSION) > $(distdir)/.tarball-version
|
||||||
|
|
||||||
|
case $# in
|
||||||
|
1) ;;
|
||||||
|
*) echo 1>&2 "Usage: $0 \$srcdir/.tarball-version"; exit 1;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
tarball_version_file=$1
|
||||||
|
nl='
|
||||||
|
'
|
||||||
|
|
||||||
|
# First see if there is a tarball-only version file.
|
||||||
|
# then try "git describe", then default.
|
||||||
|
if test -f $tarball_version_file
|
||||||
|
then
|
||||||
|
v=`cat $tarball_version_file` || exit 1
|
||||||
|
case $v in
|
||||||
|
*$nl*) v= ;; # reject multi-line output
|
||||||
|
[0-9]*) ;;
|
||||||
|
*) v= ;;
|
||||||
|
esac
|
||||||
|
test -z "$v" \
|
||||||
|
&& echo "$0: WARNING: $tarball_version_file seems to be damaged" 1>&2
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test -n "$v"
|
||||||
|
then
|
||||||
|
: # use $v
|
||||||
|
elif
|
||||||
|
v=`git describe --abbrev=4 --match='v*' HEAD 2>/dev/null \
|
||||||
|
|| git describe --abbrev=4 HEAD 2>/dev/null` \
|
||||||
|
&& case $v in
|
||||||
|
[0-9]*) ;;
|
||||||
|
v[0-9]*) ;;
|
||||||
|
*) (exit 1) ;;
|
||||||
|
esac
|
||||||
|
then
|
||||||
|
# Is this a new git that lists number of commits since the last
|
||||||
|
# tag or the previous older version that did not?
|
||||||
|
# Newer: v6.10-77-g0f8faeb
|
||||||
|
# Older: v6.10-g0f8faeb
|
||||||
|
case $v in
|
||||||
|
*-*-*) : git describe is okay three part flavor ;;
|
||||||
|
*-*)
|
||||||
|
: git describe is older two part flavor
|
||||||
|
# Recreate the number of commits and rewrite such that the
|
||||||
|
# result is the same as if we were using the newer version
|
||||||
|
# of git describe.
|
||||||
|
vtag=`echo "$v" | sed 's/-.*//'`
|
||||||
|
numcommits=`git rev-list "$vtag"..HEAD | wc -l`
|
||||||
|
v=`echo "$v" | sed "s/\(.*\)-\(.*\)/\1-$numcommits-\2/"`;
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Change the first '-' to a '.', so version-comparing tools work properly.
|
||||||
|
# Remove the "g" in git describe's output string, to save a byte.
|
||||||
|
v=`echo "$v" | sed 's/-/./;s/\(.*\)-g/\1-/'`;
|
||||||
|
else
|
||||||
|
v=UNKNOWN
|
||||||
|
fi
|
||||||
|
|
||||||
|
v=`echo "$v" |sed 's/^v//'`
|
||||||
|
|
||||||
|
# Don't declare a version "dirty" merely because a time stamp has changed.
|
||||||
|
git status > /dev/null 2>&1
|
||||||
|
|
||||||
|
dirty=`sh -c 'git diff-index --name-only HEAD' 2>/dev/null` || dirty=
|
||||||
|
case "$dirty" in
|
||||||
|
'') ;;
|
||||||
|
*) # Append the suffix only if there isn't one already.
|
||||||
|
case $v in
|
||||||
|
*-dirty) ;;
|
||||||
|
*) v="$v-dirty" ;;
|
||||||
|
esac ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Omit the trailing newline, so that m4_esyscmd can use the result directly.
|
||||||
|
echo "$v" | tr -d '\012'
|
||||||
|
|
||||||
|
# Local variables:
|
||||||
|
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||||
|
# time-stamp-start: "scriptversion="
|
||||||
|
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||||
|
# time-stamp-end: "$"
|
||||||
|
# End:
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
SUBDIRS = osmo-bts
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
noinst_HEADERS = abis.h bts.h bts_model.h gsm_data.h gsm_data_shared.h logging.h measurement.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
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
#ifndef _ABIS_H
|
||||||
|
#define _ABIS_H
|
||||||
|
|
||||||
|
#include <osmocom/core/select.h>
|
||||||
|
#include <osmocom/core/timer.h>
|
||||||
|
|
||||||
|
#include <osmo-bts/gsm_data.h>
|
||||||
|
|
||||||
|
#define OML_RETRY_TIMER 5
|
||||||
|
#define OML_PING_TIMER 20
|
||||||
|
|
||||||
|
enum {
|
||||||
|
LINK_STATE_IDLE = 0,
|
||||||
|
LINK_STATE_RETRYING,
|
||||||
|
LINK_STATE_CONNECTING,
|
||||||
|
LINK_STATE_CONNECT,
|
||||||
|
};
|
||||||
|
|
||||||
|
void abis_init(struct gsm_bts *bts);
|
||||||
|
struct e1inp_line *abis_open(struct gsm_bts *bts, char *dst_host,
|
||||||
|
char *model_name);
|
||||||
|
|
||||||
|
|
||||||
|
int abis_oml_sendmsg(struct msgb *msg);
|
||||||
|
int abis_bts_rsl_sendmsg(struct msgb *msg);
|
||||||
|
|
||||||
|
uint32_t get_signlink_remote_ip(struct e1inp_sign_link *link);
|
||||||
|
|
||||||
|
#endif /* _ABIS_H */
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
#ifndef _OSMO_BTS_AMR_H
|
||||||
|
#define _OSMO_BTS_AMR_H
|
||||||
|
|
||||||
|
#include <osmo-bts/gsm_data.h>
|
||||||
|
|
||||||
|
#define AMR_TOC_QBIT 0x04
|
||||||
|
#define AMR_CMR_NONE 0xF
|
||||||
|
|
||||||
|
void amr_log_mr_conf(int ss, int logl, const char *pfx,
|
||||||
|
struct amr_multirate_conf *amr_mrc);
|
||||||
|
|
||||||
|
int amr_parse_mr_conf(struct amr_multirate_conf *amr_mrc,
|
||||||
|
const uint8_t *mr_conf, unsigned int len);
|
||||||
|
void amr_set_mode_pref(uint8_t *data, const struct amr_multirate_conf *amr_mrc,
|
||||||
|
uint8_t cmi, uint8_t cmr);
|
||||||
|
unsigned int amr_get_initial_mode(struct gsm_lchan *lchan);
|
||||||
|
|
||||||
|
#endif /* _OSMO_BTS_AMR_H */
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
#ifndef _BTS_H
|
||||||
|
#define _BTS_H
|
||||||
|
|
||||||
|
#include <osmocom/core/rate_ctr.h>
|
||||||
|
#include <osmo-bts/gsm_data.h>
|
||||||
|
|
||||||
|
enum bts_global_status {
|
||||||
|
BTS_STATUS_RF_ACTIVE,
|
||||||
|
BTS_STATUS_RF_MUTE,
|
||||||
|
BTS_STATUS_LAST,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
BTS_CTR_PAGING_RCVD,
|
||||||
|
BTS_CTR_PAGING_DROP,
|
||||||
|
BTS_CTR_PAGING_SENT,
|
||||||
|
BTS_CTR_RACH_RCVD,
|
||||||
|
BTS_CTR_RACH_DROP,
|
||||||
|
BTS_CTR_RACH_HO,
|
||||||
|
BTS_CTR_RACH_CS,
|
||||||
|
BTS_CTR_RACH_PS,
|
||||||
|
BTS_CTR_AGCH_RCVD,
|
||||||
|
BTS_CTR_AGCH_SENT,
|
||||||
|
BTS_CTR_AGCH_DELETED,
|
||||||
|
};
|
||||||
|
|
||||||
|
extern void *tall_bts_ctx;
|
||||||
|
|
||||||
|
int bts_init(struct gsm_bts *bts);
|
||||||
|
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);
|
||||||
|
int bts_agch_max_queue_length(int T, int bcch_conf);
|
||||||
|
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);
|
||||||
|
uint8_t *lchan_sacch_get(struct gsm_lchan *lchan);
|
||||||
|
int lchan_init_lapdm(struct gsm_lchan *lchan);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
struct gsm_time *get_time(struct gsm_bts *bts);
|
||||||
|
|
||||||
|
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 */
|
||||||
|
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
#ifndef BTS_MODEL_H
|
||||||
|
#define BTS_MODEL_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <osmocom/gsm/tlv.h>
|
||||||
|
#include <osmocom/gsm/gsm_utils.h>
|
||||||
|
|
||||||
|
#include <osmo-bts/gsm_data.h>
|
||||||
|
|
||||||
|
struct phy_link;
|
||||||
|
struct phy_instance;
|
||||||
|
|
||||||
|
/* BTS model specific functions needed by the common code */
|
||||||
|
|
||||||
|
int bts_model_init(struct gsm_bts *bts);
|
||||||
|
|
||||||
|
int bts_model_check_oml(struct gsm_bts *bts, uint8_t msg_type,
|
||||||
|
struct tlv_parsed *old_attr, struct tlv_parsed *new_attr,
|
||||||
|
void *obj);
|
||||||
|
|
||||||
|
int bts_model_apply_oml(struct gsm_bts *bts, struct msgb *msg,
|
||||||
|
struct tlv_parsed *new_attr, int obj_kind, void *obj);
|
||||||
|
|
||||||
|
int bts_model_opstart(struct gsm_bts *bts, struct gsm_abis_mo *mo,
|
||||||
|
void *obj);
|
||||||
|
|
||||||
|
int bts_model_chg_adm_state(struct gsm_bts *bts, struct gsm_abis_mo *mo,
|
||||||
|
void *obj, uint8_t adm_state);
|
||||||
|
|
||||||
|
int bts_model_trx_deact_rf(struct gsm_bts_trx *trx);
|
||||||
|
int bts_model_trx_close(struct gsm_bts_trx *trx);
|
||||||
|
|
||||||
|
int bts_model_vty_init(struct gsm_bts *bts);
|
||||||
|
|
||||||
|
void bts_model_config_write_bts(struct vty *vty, struct gsm_bts *bts);
|
||||||
|
void bts_model_config_write_trx(struct vty *vty, struct gsm_bts_trx *trx);
|
||||||
|
void bts_model_config_write_phy(struct vty *vty, struct phy_link *plink);
|
||||||
|
void bts_model_config_write_phy_inst(struct vty *vty, struct phy_instance *pinst);
|
||||||
|
|
||||||
|
int bts_model_oml_estab(struct gsm_bts *bts);
|
||||||
|
|
||||||
|
int bts_model_change_power(struct gsm_bts_trx *trx, int p_trxout_mdBm);
|
||||||
|
int bts_model_adjst_ms_pwr(struct gsm_lchan *lchan);
|
||||||
|
|
||||||
|
int bts_model_l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap);
|
||||||
|
|
||||||
|
int bts_model_lchan_deactivate(struct gsm_lchan *lchan);
|
||||||
|
int bts_model_lchan_deactivate_sacch(struct gsm_lchan *lchan);
|
||||||
|
|
||||||
|
void bts_model_abis_close(struct gsm_bts *bts);
|
||||||
|
|
||||||
|
int bts_model_ctrl_cmds_install(struct gsm_bts *bts);
|
||||||
|
|
||||||
|
int bts_model_handle_options(int argc, char **argv);
|
||||||
|
void bts_model_print_help();
|
||||||
|
|
||||||
|
void bts_model_phy_link_set_defaults(struct phy_link *plink);
|
||||||
|
void bts_model_phy_instance_set_defaults(struct phy_instance *pinst);
|
||||||
|
|
||||||
|
int bts_model_ts_disconnect(struct gsm_bts_trx_ts *ts);
|
||||||
|
int bts_model_ts_connect(struct gsm_bts_trx_ts *ts, enum gsm_phys_chan_config as_pchan);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <osmocom/gsm/gsm_utils.h>
|
||||||
|
#include <osmocom/gsm/protocol/gsm_08_58.h>
|
||||||
|
|
||||||
|
#include <osmo-bts/gsm_data.h>
|
||||||
|
#include <osmo-bts/bts.h>
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
|
||||||
|
/* 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. */
|
||||||
|
int bts_cbch_get(struct gsm_bts *bts, uint8_t *outbuf, struct gsm_time *g_time);
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
int bts_ctrl_cmds_install(struct gsm_bts *bts);
|
||||||
|
struct ctrl_handle *bts_controlif_setup(struct gsm_bts *bts,
|
||||||
|
const char *bind_addr, uint16_t port);
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <osmocom/core/fsm.h>
|
||||||
|
#include <osmocom/core/utils.h>
|
||||||
|
#include <osmocom/core/logging.h>
|
||||||
|
|
||||||
|
/* DTX DL AMR FSM */
|
||||||
|
|
||||||
|
#define X(s) (1 << (s))
|
||||||
|
|
||||||
|
enum dtx_dl_amr_fsm_states {
|
||||||
|
ST_VOICE,
|
||||||
|
ST_SID_F1,
|
||||||
|
ST_SID_F2,
|
||||||
|
ST_F1_INH_V,
|
||||||
|
ST_F1_INH_F,
|
||||||
|
ST_U_INH_V,
|
||||||
|
ST_U_INH_F,
|
||||||
|
ST_U_NOINH,
|
||||||
|
ST_F1_INH_V_REC,
|
||||||
|
ST_F1_INH_F_REC,
|
||||||
|
ST_U_INH_V_REC,
|
||||||
|
ST_U_INH_F_REC,
|
||||||
|
ST_SID_U,
|
||||||
|
ST_ONSET_V,
|
||||||
|
ST_ONSET_F,
|
||||||
|
ST_ONSET_V_REC,
|
||||||
|
ST_ONSET_F_REC,
|
||||||
|
ST_FACCH,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum dtx_dl_amr_fsm_events {
|
||||||
|
E_VOICE,
|
||||||
|
E_ONSET,
|
||||||
|
E_FACCH,
|
||||||
|
E_COMPL,
|
||||||
|
E_FIRST,
|
||||||
|
E_INHIB,
|
||||||
|
E_SID_F,
|
||||||
|
E_SID_U,
|
||||||
|
};
|
||||||
|
|
||||||
|
extern const struct value_string dtx_dl_amr_fsm_event_names[];
|
||||||
|
extern struct osmo_fsm dtx_dl_amr_fsm;
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
#ifndef _GSM_DATA_H
|
||||||
|
#define _GSM_DATA_H
|
||||||
|
|
||||||
|
#include <osmocom/core/timer.h>
|
||||||
|
#include <osmocom/core/linuxlist.h>
|
||||||
|
#include <osmocom/gsm/lapdm.h>
|
||||||
|
#include <osmocom/gsm/gsm23003.h>
|
||||||
|
|
||||||
|
#include <osmo-bts/paging.h>
|
||||||
|
#include <osmo-bts/tx_power.h>
|
||||||
|
|
||||||
|
#define GSM_FR_BITS 260
|
||||||
|
#define GSM_EFR_BITS 244
|
||||||
|
|
||||||
|
#define GSM_FR_BYTES 33 /* TS 101318 Chapter 5.1: 260 bits + 4bit sig */
|
||||||
|
#define GSM_HR_BYTES 14 /* TS 101318 Chapter 5.2: 112 bits, no sig */
|
||||||
|
#define GSM_EFR_BYTES 31 /* TS 101318 Chapter 5.3: 244 bits + 4bit sig */
|
||||||
|
|
||||||
|
#define GSM_SUPERFRAME (26*51) /* 1326 TDMA frames */
|
||||||
|
#define GSM_HYPERFRAME (2048*GSM_SUPERFRAME) /* GSM_HYPERFRAME frames */
|
||||||
|
|
||||||
|
#define GSM_BTS_AGCH_QUEUE_THRESH_LEVEL_DEFAULT 41
|
||||||
|
#define GSM_BTS_AGCH_QUEUE_THRESH_LEVEL_DISABLE 999999
|
||||||
|
#define GSM_BTS_AGCH_QUEUE_LOW_LEVEL_DEFAULT 41
|
||||||
|
#define GSM_BTS_AGCH_QUEUE_HIGH_LEVEL_DEFAULT 91
|
||||||
|
|
||||||
|
struct gsm_network {
|
||||||
|
struct llist_head bts_list;
|
||||||
|
unsigned int num_bts;
|
||||||
|
struct osmo_plmn_id plmn;
|
||||||
|
struct pcu_sock_state *pcu_state;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum lchan_ciph_state {
|
||||||
|
LCHAN_CIPH_NONE,
|
||||||
|
LCHAN_CIPH_RX_REQ,
|
||||||
|
LCHAN_CIPH_RX_CONF,
|
||||||
|
LCHAN_CIPH_RXTX_REQ,
|
||||||
|
LCHAN_CIPH_RX_CONF_TX_REQ,
|
||||||
|
LCHAN_CIPH_RXTX_CONF,
|
||||||
|
};
|
||||||
|
|
||||||
|
#include <osmo-bts/gsm_data_shared.h>
|
||||||
|
|
||||||
|
void lchan_set_state(struct gsm_lchan *lchan, enum gsm_lchan_state state);
|
||||||
|
int conf_lchans_as_pchan(struct gsm_bts_trx_ts *ts,
|
||||||
|
enum gsm_phys_chan_config pchan);
|
||||||
|
|
||||||
|
/* cipher code */
|
||||||
|
#define CIPHER_A5(x) (1 << (x-1))
|
||||||
|
|
||||||
|
int bts_supports_cipher(struct gsm_bts *bts, int rsl_cipher);
|
||||||
|
|
||||||
|
bool ts_is_pdch(const struct gsm_bts_trx_ts *ts);
|
||||||
|
|
||||||
|
int bts_model_check_cm_mode(enum gsm_phys_chan_config pchan, enum gsm48_chan_mode cm);
|
||||||
|
|
||||||
|
#endif /* _GSM_DATA_H */
|
||||||
@@ -0,0 +1,815 @@
|
|||||||
|
#ifndef _GSM_DATA_SHAREDH
|
||||||
|
#define _GSM_DATA_SHAREDH
|
||||||
|
|
||||||
|
#include <regex.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <osmocom/codec/ecu.h>
|
||||||
|
#include <osmocom/core/timer.h>
|
||||||
|
#include <osmocom/core/bitvec.h>
|
||||||
|
#include <osmocom/core/statistics.h>
|
||||||
|
#include <osmocom/core/utils.h>
|
||||||
|
#include <osmocom/gsm/gsm_utils.h>
|
||||||
|
#include <osmocom/gsm/tlv.h>
|
||||||
|
#include <osmocom/gsm/rxlev_stat.h>
|
||||||
|
#include <osmocom/gsm/sysinfo.h>
|
||||||
|
#include <osmocom/gsm/meas_rep.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>
|
||||||
|
|
||||||
|
#include <osmocom/abis/e1_input.h>
|
||||||
|
#include <osmocom/gsm/lapdm.h>
|
||||||
|
|
||||||
|
/* 16 is the max. number of SI2quater messages according to 3GPP TS 44.018 Table 10.5.2.33b.1:
|
||||||
|
4-bit index is used (2#1111 = 10#15) */
|
||||||
|
#define SI2Q_MAX_NUM 16
|
||||||
|
/* length in bits (for single SI2quater message) */
|
||||||
|
#define SI2Q_MAX_LEN 160
|
||||||
|
#define SI2Q_MIN_LEN 18
|
||||||
|
|
||||||
|
/* Channel Request reason */
|
||||||
|
enum gsm_chreq_reason_t {
|
||||||
|
GSM_CHREQ_REASON_EMERG,
|
||||||
|
GSM_CHREQ_REASON_PAG,
|
||||||
|
GSM_CHREQ_REASON_CALL,
|
||||||
|
GSM_CHREQ_REASON_LOCATION_UPD,
|
||||||
|
GSM_CHREQ_REASON_OTHER,
|
||||||
|
GSM_CHREQ_REASON_PDCH,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* lchans 0..3 are SDCCH in combined channel configuration,
|
||||||
|
use 4 as magic number for BCCH hack - see osmo-bts-../oml.c:opstart_compl() */
|
||||||
|
#define CCCH_LCHAN 4
|
||||||
|
|
||||||
|
#define TRX_NR_TS 8
|
||||||
|
#define TS_MAX_LCHAN 8
|
||||||
|
|
||||||
|
#define HARDCODED_ARFCN 123
|
||||||
|
#define HARDCODED_BSIC 0x3f /* NCC = 7 / BCC = 7 */
|
||||||
|
|
||||||
|
/* for multi-drop config */
|
||||||
|
#define HARDCODED_BTS0_TS 1
|
||||||
|
#define HARDCODED_BTS1_TS 6
|
||||||
|
#define HARDCODED_BTS2_TS 11
|
||||||
|
|
||||||
|
#define MAX_VERSION_LENGTH 64
|
||||||
|
|
||||||
|
#define MAX_BTS_FEATURES 128
|
||||||
|
|
||||||
|
enum gsm_hooks {
|
||||||
|
GSM_HOOK_NM_SWLOAD,
|
||||||
|
GSM_HOOK_RR_PAGING,
|
||||||
|
GSM_HOOK_RR_SECURITY,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum bts_gprs_mode {
|
||||||
|
BTS_GPRS_NONE = 0,
|
||||||
|
BTS_GPRS_GPRS = 1,
|
||||||
|
BTS_GPRS_EGPRS = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct gsm_lchan;
|
||||||
|
struct osmo_rtp_socket;
|
||||||
|
struct pcu_sock_state;
|
||||||
|
struct smscb_msg;
|
||||||
|
|
||||||
|
/* Network Management State */
|
||||||
|
struct gsm_nm_state {
|
||||||
|
uint8_t operational;
|
||||||
|
uint8_t administrative;
|
||||||
|
uint8_t availability;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct gsm_abis_mo {
|
||||||
|
/* A-bis OML Object Class */
|
||||||
|
uint8_t obj_class;
|
||||||
|
/* is there still some procedure pending? */
|
||||||
|
uint8_t procedure_pending;
|
||||||
|
/* A-bis OML Object Instance */
|
||||||
|
struct abis_om_obj_inst obj_inst;
|
||||||
|
/* human-readable name */
|
||||||
|
const char *name;
|
||||||
|
/* NM State */
|
||||||
|
struct gsm_nm_state nm_state;
|
||||||
|
/* Attributes configured in this MO */
|
||||||
|
struct tlv_parsed *nm_attr;
|
||||||
|
/* BTS to which this MO belongs */
|
||||||
|
struct gsm_bts *bts;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define MAX_A5_KEY_LEN (128/8)
|
||||||
|
#define A38_XOR_MIN_KEY_LEN 12
|
||||||
|
#define A38_XOR_MAX_KEY_LEN 16
|
||||||
|
#define A38_COMP128_KEY_LEN 16
|
||||||
|
#define RSL_ENC_ALG_A5(x) (x+1)
|
||||||
|
#define MAX_EARFCN_LIST 32
|
||||||
|
|
||||||
|
/* is the data link established? who established it? */
|
||||||
|
#define LCHAN_SAPI_UNUSED 0
|
||||||
|
#define LCHAN_SAPI_MS 1
|
||||||
|
#define LCHAN_SAPI_NET 2
|
||||||
|
#define LCHAN_SAPI_REL 3
|
||||||
|
|
||||||
|
/* state of a logical channel */
|
||||||
|
enum gsm_lchan_state {
|
||||||
|
LCHAN_S_NONE, /* channel is not active */
|
||||||
|
LCHAN_S_ACT_REQ, /* channel activation requested */
|
||||||
|
LCHAN_S_ACTIVE, /* channel is active and operational */
|
||||||
|
LCHAN_S_REL_REQ, /* channel release has been requested */
|
||||||
|
LCHAN_S_REL_ERR, /* channel is in an error state */
|
||||||
|
LCHAN_S_BROKEN, /* channel is somehow unusable */
|
||||||
|
LCHAN_S_INACTIVE, /* channel is set inactive */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* BTS ONLY */
|
||||||
|
#define MAX_NUM_UL_MEAS 104
|
||||||
|
#define LC_UL_M_F_L1_VALID (1 << 0)
|
||||||
|
#define LC_UL_M_F_RES_VALID (1 << 1)
|
||||||
|
|
||||||
|
struct bts_ul_meas {
|
||||||
|
/* BER in units of 0.01%: 10.000 == 100% ber, 0 == 0% ber */
|
||||||
|
uint16_t ber10k;
|
||||||
|
/* timing advance offset (in 1/256 bits) */
|
||||||
|
int16_t ta_offs_256bits;
|
||||||
|
/* C/I ratio in dB */
|
||||||
|
float c_i;
|
||||||
|
/* flags */
|
||||||
|
uint8_t is_sub:1;
|
||||||
|
/* RSSI in dBm * -1 */
|
||||||
|
uint8_t inv_rssi;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct bts_codec_conf {
|
||||||
|
uint8_t hr;
|
||||||
|
uint8_t efr;
|
||||||
|
uint8_t amr;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct amr_mode {
|
||||||
|
uint8_t mode;
|
||||||
|
uint8_t threshold;
|
||||||
|
uint8_t hysteresis;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct amr_multirate_conf {
|
||||||
|
uint8_t gsm48_ie[2];
|
||||||
|
struct amr_mode ms_mode[4];
|
||||||
|
struct amr_mode bts_mode[4];
|
||||||
|
uint8_t num_modes;
|
||||||
|
};
|
||||||
|
/* /BTS ONLY */
|
||||||
|
|
||||||
|
enum lchan_csd_mode {
|
||||||
|
LCHAN_CSD_M_NT,
|
||||||
|
LCHAN_CSD_M_T_1200_75,
|
||||||
|
LCHAN_CSD_M_T_600,
|
||||||
|
LCHAN_CSD_M_T_1200,
|
||||||
|
LCHAN_CSD_M_T_2400,
|
||||||
|
LCHAN_CSD_M_T_9600,
|
||||||
|
LCHAN_CSD_M_T_14400,
|
||||||
|
LCHAN_CSD_M_T_29000,
|
||||||
|
LCHAN_CSD_M_T_32000,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* State of the SAPIs in the lchan */
|
||||||
|
enum lchan_sapi_state {
|
||||||
|
LCHAN_SAPI_S_NONE,
|
||||||
|
LCHAN_SAPI_S_REQ,
|
||||||
|
LCHAN_SAPI_S_ASSIGNED,
|
||||||
|
LCHAN_SAPI_S_REL,
|
||||||
|
LCHAN_SAPI_S_ERROR,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct gsm_lchan {
|
||||||
|
/* The TS that we're part of */
|
||||||
|
struct gsm_bts_trx_ts *ts;
|
||||||
|
/* The logical subslot number in the TS */
|
||||||
|
uint8_t nr;
|
||||||
|
/* The logical channel type */
|
||||||
|
enum gsm_chan_t type;
|
||||||
|
/* RSL channel mode */
|
||||||
|
enum rsl_cmod_spd rsl_cmode;
|
||||||
|
/* If TCH, traffic channel mode */
|
||||||
|
enum gsm48_chan_mode tch_mode;
|
||||||
|
enum lchan_csd_mode csd_mode;
|
||||||
|
/* 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;
|
||||||
|
uint8_t key_len;
|
||||||
|
uint8_t key[MAX_A5_KEY_LEN];
|
||||||
|
} encr;
|
||||||
|
|
||||||
|
/* AMR bits */
|
||||||
|
uint8_t mr_bts_lv[7];
|
||||||
|
|
||||||
|
/* Established data link layer services */
|
||||||
|
int sacch_deact;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
uint32_t bound_ip;
|
||||||
|
uint32_t connect_ip;
|
||||||
|
uint16_t bound_port;
|
||||||
|
uint16_t connect_port;
|
||||||
|
uint16_t conn_id;
|
||||||
|
uint8_t rtp_payload;
|
||||||
|
uint8_t rtp_payload2;
|
||||||
|
uint8_t speech_mode;
|
||||||
|
struct osmo_rtp_socket *rtp_socket;
|
||||||
|
} abis_ip;
|
||||||
|
|
||||||
|
uint8_t rqd_ta;
|
||||||
|
|
||||||
|
char *name;
|
||||||
|
|
||||||
|
/* Number of different GsmL1_Sapi_t used in osmo_bts_sysmo is 23.
|
||||||
|
* Currently we don't share these headers so this is a magic number. */
|
||||||
|
struct llist_head sapi_cmds;
|
||||||
|
uint8_t sapis_dl[23];
|
||||||
|
uint8_t sapis_ul[23];
|
||||||
|
struct lapdm_channel lapdm_ch;
|
||||||
|
struct llist_head dl_tch_queue;
|
||||||
|
struct {
|
||||||
|
/* bitmask of all SI that are present/valid in si_buf */
|
||||||
|
uint32_t valid;
|
||||||
|
uint32_t last;
|
||||||
|
/* buffers where we put the pre-computed SI:
|
||||||
|
SI2Q_MAX_NUM is the max number of SI2quater messages (see 3GPP TS 44.018) */
|
||||||
|
sysinfo_buf_t buf[_MAX_SYSINFO_TYPE][SI2Q_MAX_NUM];
|
||||||
|
} si;
|
||||||
|
struct {
|
||||||
|
uint8_t flags;
|
||||||
|
/* RSL measurment result number, 0 at lchan_act */
|
||||||
|
uint8_t res_nr;
|
||||||
|
/* current Tx power level of the BTS */
|
||||||
|
uint8_t bts_tx_pwr;
|
||||||
|
/* number of measurements stored in array below */
|
||||||
|
uint8_t num_ul_meas;
|
||||||
|
struct bts_ul_meas uplink[MAX_NUM_UL_MEAS];
|
||||||
|
/* last L1 header from the MS */
|
||||||
|
uint8_t l1_info[2];
|
||||||
|
struct gsm_meas_rep_unidir ul_res;
|
||||||
|
int16_t ms_toa256;
|
||||||
|
} meas;
|
||||||
|
struct {
|
||||||
|
struct amr_multirate_conf amr_mr;
|
||||||
|
struct {
|
||||||
|
struct osmo_fsm_inst *dl_amr_fsm;
|
||||||
|
/* TCH cache */
|
||||||
|
uint8_t cache[20];
|
||||||
|
/* FACCH cache */
|
||||||
|
uint8_t facch[GSM_MACBLOCK_LEN];
|
||||||
|
uint8_t len;
|
||||||
|
uint32_t fn;
|
||||||
|
bool is_update;
|
||||||
|
/* set for each SID frame to detect talkspurt for codecs
|
||||||
|
without explicit ONSET event */
|
||||||
|
bool ul_sid;
|
||||||
|
/* indicates if DTXd was active during DL measurement
|
||||||
|
period */
|
||||||
|
bool dl_active;
|
||||||
|
} dtx;
|
||||||
|
uint8_t last_cmr;
|
||||||
|
uint32_t last_fn;
|
||||||
|
} tch;
|
||||||
|
|
||||||
|
/* 3GPP TS 48.058 § 9.3.37: [0; 255] ok, -1 means invalid*/
|
||||||
|
int16_t ms_t_offs;
|
||||||
|
/* 3GPP TS 45.010 § 1.2 round trip propagation delay (in symbols) or -1 */
|
||||||
|
int16_t p_offs;
|
||||||
|
|
||||||
|
/* BTS-side ciphering state (rx only, bi-directional, ...) */
|
||||||
|
uint8_t ciph_state;
|
||||||
|
uint8_t ciph_ns;
|
||||||
|
uint8_t loopback;
|
||||||
|
struct {
|
||||||
|
uint8_t active;
|
||||||
|
uint8_t ref;
|
||||||
|
/* T3105: PHYS INF retransmission */
|
||||||
|
struct osmo_timer_list t3105;
|
||||||
|
/* counts up to Ny1 */
|
||||||
|
unsigned int phys_info_count;
|
||||||
|
} ho;
|
||||||
|
/* S counter for link loss */
|
||||||
|
int s;
|
||||||
|
/* Kind of the release/activation. E.g. RSL or PCU */
|
||||||
|
int rel_act_kind;
|
||||||
|
/* RTP header Marker bit to indicate beginning of speech after pause */
|
||||||
|
bool rtp_tx_marker;
|
||||||
|
/* power handling */
|
||||||
|
struct {
|
||||||
|
uint8_t current;
|
||||||
|
uint8_t fixed;
|
||||||
|
} ms_power_ctrl;
|
||||||
|
|
||||||
|
struct msgb *pending_rel_ind_msg;
|
||||||
|
|
||||||
|
/* ECU (Error Concealment Unit) state */
|
||||||
|
union {
|
||||||
|
struct osmo_ecu_fr_state fr;
|
||||||
|
} ecu_state;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern const struct value_string lchan_ciph_state_names[];
|
||||||
|
static inline const char *lchan_ciph_state_name(uint8_t state) {
|
||||||
|
return get_value_string(lchan_ciph_state_names, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
enum {
|
||||||
|
TS_F_PDCH_ACTIVE = 0x1000,
|
||||||
|
TS_F_PDCH_ACT_PENDING = 0x2000,
|
||||||
|
TS_F_PDCH_DEACT_PENDING = 0x4000,
|
||||||
|
TS_F_PDCH_PENDING_MASK = 0x6000 /*<
|
||||||
|
TS_F_PDCH_ACT_PENDING | TS_F_PDCH_DEACT_PENDING */
|
||||||
|
} gsm_bts_trx_ts_flags;
|
||||||
|
|
||||||
|
/* One Timeslot in a TRX */
|
||||||
|
struct gsm_bts_trx_ts {
|
||||||
|
struct gsm_bts_trx *trx;
|
||||||
|
/* number of this timeslot at the TRX */
|
||||||
|
uint8_t nr;
|
||||||
|
|
||||||
|
enum gsm_phys_chan_config pchan;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
enum gsm_phys_chan_config pchan_is;
|
||||||
|
enum gsm_phys_chan_config pchan_want;
|
||||||
|
struct msgb *pending_chan_activ;
|
||||||
|
} dyn;
|
||||||
|
|
||||||
|
unsigned int flags;
|
||||||
|
struct gsm_abis_mo mo;
|
||||||
|
struct tlv_parsed nm_attr;
|
||||||
|
uint8_t nm_chan_comb;
|
||||||
|
int tsc; /* -1 == use BTS TSC */
|
||||||
|
|
||||||
|
struct {
|
||||||
|
/* Parameters below are configured by VTY */
|
||||||
|
int enabled;
|
||||||
|
uint8_t maio;
|
||||||
|
uint8_t hsn;
|
||||||
|
struct bitvec arfcns;
|
||||||
|
uint8_t arfcns_data[1024/8];
|
||||||
|
/* This is the pre-computed MA for channel assignments */
|
||||||
|
struct bitvec ma;
|
||||||
|
uint8_t ma_len; /* part of ma_data that is used */
|
||||||
|
uint8_t ma_data[8]; /* 10.5.2.21: max 8 bytes value part */
|
||||||
|
} hopping;
|
||||||
|
|
||||||
|
struct gsm_lchan lchan[TS_MAX_LCHAN];
|
||||||
|
};
|
||||||
|
|
||||||
|
/* One TRX in a BTS */
|
||||||
|
struct gsm_bts_trx {
|
||||||
|
/* list header in bts->trx_list */
|
||||||
|
struct llist_head list;
|
||||||
|
|
||||||
|
struct gsm_bts *bts;
|
||||||
|
/* number of this TRX in the BTS */
|
||||||
|
uint8_t nr;
|
||||||
|
/* human readable name / description */
|
||||||
|
char *description;
|
||||||
|
/* how do we talk RSL with this TRX? */
|
||||||
|
uint8_t rsl_tei;
|
||||||
|
struct e1inp_sign_link *rsl_link;
|
||||||
|
|
||||||
|
/* Some BTS (specifically Ericsson RBS) have a per-TRX OML Link */
|
||||||
|
struct e1inp_sign_link *oml_link;
|
||||||
|
|
||||||
|
struct gsm_abis_mo mo;
|
||||||
|
struct tlv_parsed nm_attr;
|
||||||
|
struct {
|
||||||
|
struct gsm_abis_mo mo;
|
||||||
|
} bb_transc;
|
||||||
|
|
||||||
|
uint16_t arfcn;
|
||||||
|
int nominal_power; /* in dBm */
|
||||||
|
unsigned int max_power_red; /* in actual dB */
|
||||||
|
|
||||||
|
struct trx_power_params power_params;
|
||||||
|
int ms_power_control;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
void *l1h;
|
||||||
|
} role_bts;
|
||||||
|
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
unsigned int test_state;
|
||||||
|
uint8_t test_nr;
|
||||||
|
struct rxlev_stats rxlev_stat;
|
||||||
|
} ipaccess;
|
||||||
|
};
|
||||||
|
struct gsm_bts_trx_ts ts[TRX_NR_TS];
|
||||||
|
};
|
||||||
|
|
||||||
|
#define GSM_BTS_SI2Q(bts, i) (struct gsm48_system_information_type_2quater *)((bts)->si_buf[SYSINFO_TYPE_2quater][i])
|
||||||
|
#define GSM_BTS_HAS_SI(bts, i) ((bts)->si_valid & (1 << i))
|
||||||
|
#define GSM_BTS_SI(bts, i) (void *)((bts)->si_buf[i][0])
|
||||||
|
#define GSM_LCHAN_SI(lchan, i) (void *)((lchan)->si.buf[i][0])
|
||||||
|
|
||||||
|
enum gsm_bts_type_variant {
|
||||||
|
BTS_UNKNOWN,
|
||||||
|
BTS_OSMO_LITECELL15,
|
||||||
|
BTS_OSMO_OCTPHY,
|
||||||
|
BTS_OSMO_SYSMO,
|
||||||
|
BTS_OSMO_TRX,
|
||||||
|
BTS_OSMO_VIRTUAL,
|
||||||
|
BTS_OSMO_OMLDUMMY,
|
||||||
|
_NUM_BTS_VARIANT
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Used by OML layer for BTS Attribute reporting */
|
||||||
|
enum bts_attribute {
|
||||||
|
BTS_TYPE_VARIANT,
|
||||||
|
BTS_SUB_MODEL,
|
||||||
|
TRX_PHY_VERSION,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct vty;
|
||||||
|
|
||||||
|
/* N. B: always add new features to the end of the list (right before _NUM_BTS_FEAT) to avoid breaking compatibility
|
||||||
|
with BTS compiled against earlier version of this header. Also make sure that the description strings
|
||||||
|
gsm_bts_features_descs[] in gsm_data_shared.c are also updated accordingly! */
|
||||||
|
enum gsm_bts_features {
|
||||||
|
BTS_FEAT_HSCSD,
|
||||||
|
BTS_FEAT_GPRS,
|
||||||
|
BTS_FEAT_EGPRS,
|
||||||
|
BTS_FEAT_ECSD,
|
||||||
|
BTS_FEAT_HOPPING,
|
||||||
|
BTS_FEAT_MULTI_TSC,
|
||||||
|
BTS_FEAT_OML_ALERTS,
|
||||||
|
BTS_FEAT_AGCH_PCH_PROP,
|
||||||
|
BTS_FEAT_CBCH,
|
||||||
|
BTS_FEAT_SPEECH_F_V1,
|
||||||
|
BTS_FEAT_SPEECH_H_V1,
|
||||||
|
BTS_FEAT_SPEECH_F_EFR,
|
||||||
|
BTS_FEAT_SPEECH_F_AMR,
|
||||||
|
BTS_FEAT_SPEECH_H_AMR,
|
||||||
|
_NUM_BTS_FEAT
|
||||||
|
};
|
||||||
|
|
||||||
|
extern const struct value_string gsm_bts_features_descs[];
|
||||||
|
|
||||||
|
struct gsm_bts_gprs_nsvc {
|
||||||
|
struct gsm_bts *bts;
|
||||||
|
/* data read via VTY config file, to configure the BTS
|
||||||
|
* via OML from BSC */
|
||||||
|
int id;
|
||||||
|
uint16_t nsvci;
|
||||||
|
uint16_t local_port; /* on the BTS */
|
||||||
|
uint16_t remote_port; /* on the SGSN */
|
||||||
|
uint32_t remote_ip; /* on the SGSN */
|
||||||
|
|
||||||
|
struct gsm_abis_mo mo;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum gprs_rlc_par {
|
||||||
|
RLC_T3142,
|
||||||
|
RLC_T3169,
|
||||||
|
RLC_T3191,
|
||||||
|
RLC_T3193,
|
||||||
|
RLC_T3195,
|
||||||
|
RLC_N3101,
|
||||||
|
RLC_N3103,
|
||||||
|
RLC_N3105,
|
||||||
|
CV_COUNTDOWN,
|
||||||
|
T_DL_TBF_EXT, /* ms */
|
||||||
|
T_UL_TBF_EXT, /* ms */
|
||||||
|
_NUM_RLC_PAR
|
||||||
|
};
|
||||||
|
|
||||||
|
enum gprs_cs {
|
||||||
|
GPRS_CS1,
|
||||||
|
GPRS_CS2,
|
||||||
|
GPRS_CS3,
|
||||||
|
GPRS_CS4,
|
||||||
|
GPRS_MCS1,
|
||||||
|
GPRS_MCS2,
|
||||||
|
GPRS_MCS3,
|
||||||
|
GPRS_MCS4,
|
||||||
|
GPRS_MCS5,
|
||||||
|
GPRS_MCS6,
|
||||||
|
GPRS_MCS7,
|
||||||
|
GPRS_MCS8,
|
||||||
|
GPRS_MCS9,
|
||||||
|
_NUM_GRPS_CS
|
||||||
|
};
|
||||||
|
|
||||||
|
struct gprs_rlc_cfg {
|
||||||
|
uint16_t parameter[_NUM_RLC_PAR];
|
||||||
|
struct {
|
||||||
|
uint16_t repeat_time; /* ms */
|
||||||
|
uint8_t repeat_count;
|
||||||
|
} paging;
|
||||||
|
uint32_t cs_mask; /* bitmask of gprs_cs */
|
||||||
|
uint8_t initial_cs;
|
||||||
|
uint8_t initial_mcs;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* One BTS */
|
||||||
|
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 */
|
||||||
|
uint8_t nr;
|
||||||
|
/* human readable name / description */
|
||||||
|
char *description;
|
||||||
|
/* Cell Identity */
|
||||||
|
uint16_t cell_identity;
|
||||||
|
/* location area code of this BTS */
|
||||||
|
uint16_t location_area_code;
|
||||||
|
/* Base Station Identification Code (BSIC), lower 3 bits is BCC,
|
||||||
|
* which is used as TSC for the CCCH */
|
||||||
|
uint8_t bsic;
|
||||||
|
/* type of BTS */
|
||||||
|
enum gsm_bts_type_variant variant;
|
||||||
|
enum gsm_band band;
|
||||||
|
char version[MAX_VERSION_LENGTH];
|
||||||
|
char sub_model[MAX_VERSION_LENGTH];
|
||||||
|
|
||||||
|
/* features of a given BTS set/reported via OML */
|
||||||
|
struct bitvec features;
|
||||||
|
uint8_t _features_data[MAX_BTS_FEATURES/8];
|
||||||
|
|
||||||
|
/* Connected PCU version (if any) */
|
||||||
|
char pcu_version[MAX_VERSION_LENGTH];
|
||||||
|
|
||||||
|
/* maximum Tx power that the MS is permitted to use in this cell */
|
||||||
|
int ms_max_power;
|
||||||
|
|
||||||
|
/* how do we talk OML with this TRX? */
|
||||||
|
uint8_t oml_tei;
|
||||||
|
struct e1inp_sign_link *oml_link;
|
||||||
|
|
||||||
|
/* Abis network management O&M handle */
|
||||||
|
struct abis_nm_h *nmh;
|
||||||
|
|
||||||
|
struct gsm_abis_mo mo;
|
||||||
|
|
||||||
|
/* number of this BTS on given E1 link */
|
||||||
|
uint8_t bts_nr;
|
||||||
|
|
||||||
|
/* DTX features of this BTS */
|
||||||
|
enum gsm48_dtx_mode dtxu;
|
||||||
|
bool dtxd;
|
||||||
|
|
||||||
|
/* CCCH is on C0 */
|
||||||
|
struct gsm_bts_trx *c0;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
struct gsm_abis_mo mo;
|
||||||
|
} site_mgr;
|
||||||
|
|
||||||
|
/* bitmask of all SI that are present/valid in si_buf */
|
||||||
|
uint32_t si_valid;
|
||||||
|
/* 3GPP TS 44.018 Table 10.5.2.33b.1 INDEX and COUNT for SI2quater */
|
||||||
|
uint8_t si2q_index; /* distinguish individual SI2quater messages */
|
||||||
|
uint8_t si2q_count; /* si2q_index for the last (highest indexed) individual SI2quater message */
|
||||||
|
/* buffers where we put the pre-computed SI */
|
||||||
|
sysinfo_buf_t si_buf[_MAX_SYSINFO_TYPE][SI2Q_MAX_NUM];
|
||||||
|
/* offsets used while generating SI2quater */
|
||||||
|
size_t e_offset;
|
||||||
|
size_t u_offset;
|
||||||
|
|
||||||
|
/* ip.accesss Unit ID's have Site/BTS/TRX layout */
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
uint16_t site_id;
|
||||||
|
uint16_t bts_id;
|
||||||
|
uint32_t flags;
|
||||||
|
uint32_t rsl_ip;
|
||||||
|
} ip_access;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Not entirely sure how ip.access specific this is */
|
||||||
|
struct {
|
||||||
|
uint8_t supports_egprs_11bit_rach;
|
||||||
|
enum bts_gprs_mode mode;
|
||||||
|
struct {
|
||||||
|
struct gsm_abis_mo mo;
|
||||||
|
uint16_t nsei;
|
||||||
|
uint8_t timer[7];
|
||||||
|
} nse;
|
||||||
|
struct {
|
||||||
|
struct gsm_abis_mo mo;
|
||||||
|
uint16_t bvci;
|
||||||
|
uint8_t timer[11];
|
||||||
|
struct gprs_rlc_cfg rlc_cfg;
|
||||||
|
} cell;
|
||||||
|
struct gsm_bts_gprs_nsvc nsvc[2];
|
||||||
|
uint8_t rac;
|
||||||
|
uint8_t net_ctrl_ord;
|
||||||
|
bool ctrl_ack_type_use_block;
|
||||||
|
} gprs;
|
||||||
|
|
||||||
|
/* RACH NM values */
|
||||||
|
int rach_b_thresh;
|
||||||
|
int rach_ldavg_slots;
|
||||||
|
|
||||||
|
/* transceivers */
|
||||||
|
int num_trx;
|
||||||
|
struct llist_head trx_list;
|
||||||
|
|
||||||
|
/* SI related items */
|
||||||
|
int force_combined_si;
|
||||||
|
int bcch_change_mark;
|
||||||
|
|
||||||
|
struct rate_ctr_group *ctrs;
|
||||||
|
bool supp_meas_toa256;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
/* Interference Boundaries for OML */
|
||||||
|
int16_t boundary[6];
|
||||||
|
uint8_t intave;
|
||||||
|
} interference;
|
||||||
|
unsigned int t200_ms[7];
|
||||||
|
unsigned int t3105_ms;
|
||||||
|
struct {
|
||||||
|
uint8_t overload_period;
|
||||||
|
struct {
|
||||||
|
/* Input parameters from OML */
|
||||||
|
uint8_t load_ind_thresh; /* percent */
|
||||||
|
uint8_t load_ind_period; /* seconds */
|
||||||
|
/* Internal data */
|
||||||
|
struct osmo_timer_list timer;
|
||||||
|
unsigned int pch_total;
|
||||||
|
unsigned int pch_used;
|
||||||
|
} ccch;
|
||||||
|
struct {
|
||||||
|
/* Input parameters from OML */
|
||||||
|
int16_t busy_thresh; /* in dBm */
|
||||||
|
uint16_t averaging_slots;
|
||||||
|
/* Internal data */
|
||||||
|
unsigned int total; /* total nr */
|
||||||
|
unsigned int busy; /* above busy_thresh */
|
||||||
|
unsigned int access; /* access bursts */
|
||||||
|
} rach;
|
||||||
|
} load;
|
||||||
|
uint8_t ny1;
|
||||||
|
uint8_t max_ta;
|
||||||
|
|
||||||
|
/* AGCH queuing */
|
||||||
|
struct {
|
||||||
|
struct llist_head queue;
|
||||||
|
int length;
|
||||||
|
int max_length;
|
||||||
|
|
||||||
|
int thresh_level; /* Cleanup threshold in percent of max len */
|
||||||
|
int low_level; /* Low water mark in percent of max len */
|
||||||
|
int high_level; /* High water mark in percent of max len */
|
||||||
|
|
||||||
|
/* TODO: Use a rate counter group instead */
|
||||||
|
uint64_t dropped_msgs;
|
||||||
|
uint64_t merged_msgs;
|
||||||
|
uint64_t rejected_msgs;
|
||||||
|
uint64_t agch_msgs;
|
||||||
|
uint64_t pch_msgs;
|
||||||
|
} agch_queue;
|
||||||
|
|
||||||
|
struct paging_state *paging_state;
|
||||||
|
char *bsc_oml_host;
|
||||||
|
struct llist_head oml_queue;
|
||||||
|
unsigned int rtp_jitter_buf_ms;
|
||||||
|
bool rtp_jitter_adaptive;
|
||||||
|
struct {
|
||||||
|
uint8_t ciphers; /* flags A5/1==0x1, A5/2==0x2, A5/3==0x4 */
|
||||||
|
} support;
|
||||||
|
struct {
|
||||||
|
uint8_t tc4_ctr;
|
||||||
|
} si;
|
||||||
|
struct gsm_time gsm_time;
|
||||||
|
/* Radio Link Timeout counter. -1 disables timeout for
|
||||||
|
* lab/measurement purpose */
|
||||||
|
int radio_link_timeout;
|
||||||
|
|
||||||
|
int ul_power_target; /* Uplink Rx power target */
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
|
||||||
|
float min_qual_rach; /* minimum quality for RACH bursts */
|
||||||
|
float min_qual_norm; /* minimum quality for normal daata */
|
||||||
|
uint16_t max_ber10k_rach; /* Maximum permitted RACH BER in 0.01% */
|
||||||
|
|
||||||
|
struct {
|
||||||
|
char *sock_path;
|
||||||
|
} pcu;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
uint32_t last_fn;
|
||||||
|
struct timeval tv_clock;
|
||||||
|
struct osmo_timer_list fn_timer;
|
||||||
|
} vbts;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct gsm_bts *gsm_bts_alloc(void *talloc_ctx, uint8_t bts_num);
|
||||||
|
struct gsm_bts *gsm_bts_num(struct gsm_network *net, int num);
|
||||||
|
|
||||||
|
struct gsm_bts_trx *gsm_bts_trx_alloc(struct gsm_bts *bts);
|
||||||
|
struct gsm_bts_trx *gsm_bts_trx_num(const struct gsm_bts *bts, int num);
|
||||||
|
|
||||||
|
enum bts_attribute str2btsattr(const char *s);
|
||||||
|
const char *btsatttr2str(enum bts_attribute v);
|
||||||
|
|
||||||
|
enum gsm_bts_type_variant str2btsvariant(const char *arg);
|
||||||
|
const char *btsvariant2str(enum gsm_bts_type_variant v);
|
||||||
|
|
||||||
|
extern const struct value_string gsm_chreq_descs[];
|
||||||
|
const struct value_string gsm_pchant_names[13];
|
||||||
|
const struct value_string gsm_pchant_descs[13];
|
||||||
|
const char *gsm_pchan_name(enum gsm_phys_chan_config c);
|
||||||
|
enum gsm_phys_chan_config gsm_pchan_parse(const char *name);
|
||||||
|
const char *gsm_lchant_name(enum gsm_chan_t c);
|
||||||
|
const char *gsm_chreq_name(enum gsm_chreq_reason_t c);
|
||||||
|
char *gsm_trx_name(const struct gsm_bts_trx *trx);
|
||||||
|
char *gsm_ts_name(const struct gsm_bts_trx_ts *ts);
|
||||||
|
char *gsm_ts_and_pchan_name(const struct gsm_bts_trx_ts *ts);
|
||||||
|
char *gsm_lchan_name_compute(const struct gsm_lchan *lchan);
|
||||||
|
const char *gsm_lchans_name(enum gsm_lchan_state s);
|
||||||
|
|
||||||
|
static inline char *gsm_lchan_name(const struct gsm_lchan *lchan)
|
||||||
|
{
|
||||||
|
return lchan->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int gsm_bts_set_feature(struct gsm_bts *bts, enum gsm_bts_features feat)
|
||||||
|
{
|
||||||
|
OSMO_ASSERT(_NUM_BTS_FEAT < MAX_BTS_FEATURES);
|
||||||
|
return bitvec_set_bit_pos(&bts->features, feat, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool gsm_bts_has_feature(const struct gsm_bts *bts, enum gsm_bts_features feat)
|
||||||
|
{
|
||||||
|
OSMO_ASSERT(_NUM_BTS_FEAT < MAX_BTS_FEATURES);
|
||||||
|
return bitvec_get_bit_pos(&bts->features, feat);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gsm_abis_mo_reset(struct gsm_abis_mo *mo);
|
||||||
|
|
||||||
|
struct gsm_abis_mo *
|
||||||
|
gsm_objclass2mo(struct gsm_bts *bts, uint8_t obj_class,
|
||||||
|
const struct abis_om_obj_inst *obj_inst);
|
||||||
|
|
||||||
|
struct gsm_nm_state *
|
||||||
|
gsm_objclass2nmstate(struct gsm_bts *bts, uint8_t obj_class,
|
||||||
|
const struct abis_om_obj_inst *obj_inst);
|
||||||
|
void *
|
||||||
|
gsm_objclass2obj(struct gsm_bts *bts, uint8_t obj_class,
|
||||||
|
const struct abis_om_obj_inst *obj_inst);
|
||||||
|
|
||||||
|
/* reset the state of all MO in the BTS */
|
||||||
|
void gsm_bts_mo_reset(struct gsm_bts *bts);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
/* return the gsm_lchan for the CBCH (if it exists at all) */
|
||||||
|
struct gsm_lchan *gsm_bts_get_cbch(struct gsm_bts *bts);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* help with parsing regexps
|
||||||
|
*/
|
||||||
|
int gsm_parse_reg(void *ctx, regex_t *reg, char **str,
|
||||||
|
int argc, const char **argv) __attribute__ ((warn_unused_result));
|
||||||
|
|
||||||
|
#define BSIC2BCC(bsic) ((bsic) & 0x3)
|
||||||
|
|
||||||
|
static inline uint8_t gsm_ts_tsc(const struct gsm_bts_trx_ts *ts)
|
||||||
|
{
|
||||||
|
if (ts->tsc != -1)
|
||||||
|
return ts->tsc;
|
||||||
|
else
|
||||||
|
return ts->trx->bts->bsic & 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct gsm_lchan *rsl_lchan_lookup(struct gsm_bts_trx *trx, uint8_t chan_nr,
|
||||||
|
int *rc);
|
||||||
|
|
||||||
|
enum gsm_phys_chan_config ts_pchan(struct gsm_bts_trx_ts *ts);
|
||||||
|
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);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
enum {
|
||||||
|
HANDOVER_NONE = 0,
|
||||||
|
HANDOVER_ENABLED,
|
||||||
|
HANDOVER_WAIT_FRAME,
|
||||||
|
};
|
||||||
|
|
||||||
|
void handover_rach(struct gsm_lchan *lchan, uint8_t ra, uint8_t acc_delay);
|
||||||
|
void handover_frame(struct gsm_lchan *lchan);
|
||||||
|
void handover_reset(struct gsm_lchan *lchan);
|
||||||
|
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
#ifndef L1SAP_H
|
||||||
|
#define L1SAP_H
|
||||||
|
|
||||||
|
#include <osmocom/gsm/protocol/gsm_04_08.h>
|
||||||
|
|
||||||
|
/* lchan link ID */
|
||||||
|
#define LID_SACCH 0x40
|
||||||
|
#define LID_DEDIC 0x00
|
||||||
|
|
||||||
|
/* timeslot and subslot from chan_nr */
|
||||||
|
#define L1SAP_CHAN2TS(chan_nr) (chan_nr & 7)
|
||||||
|
#define L1SAP_CHAN2SS_TCHH(chan_nr) ((chan_nr >> 3) & 1)
|
||||||
|
#define L1SAP_CHAN2SS_SDCCH4(chan_nr) ((chan_nr >> 3) & 3)
|
||||||
|
#define L1SAP_CHAN2SS_SDCCH8(chan_nr) ((chan_nr >> 3) & 7)
|
||||||
|
|
||||||
|
/* 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)
|
||||||
|
|
||||||
|
/* rach type from ra */
|
||||||
|
#define L1SAP_IS_PACKET_RACH(ra) ((ra & 0xf0) == 0x70 && (ra & 0x0f) != 0x0f)
|
||||||
|
|
||||||
|
/* CCCH block from frame number */
|
||||||
|
#define L1SAP_FN2CCCHBLOCK(fn) ((fn % 51) / 5 - 1)
|
||||||
|
|
||||||
|
/* PTCH layout from frame number */
|
||||||
|
#define L1SAP_FN2MACBLOCK(fn) ((fn % 52) / 4)
|
||||||
|
#define L1SAP_FN2PTCCHBLOCK(fn) ((fn / 104) & 3)
|
||||||
|
|
||||||
|
/* Calculate PTCCH occurrence, See also 3GPP TS 05.02, Clause 7, Table 6 of 9 */
|
||||||
|
#define L1SAP_IS_PTCCH(fn) (((fn % 52) == 12) || ((fn % 52) == 38))
|
||||||
|
|
||||||
|
|
||||||
|
static const uint8_t fill_frame[GSM_MACBLOCK_LEN] = {
|
||||||
|
0x03, 0x03, 0x01, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B,
|
||||||
|
0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B,
|
||||||
|
0x2B, 0x2B, 0x2B
|
||||||
|
};
|
||||||
|
|
||||||
|
/* subslot from any chan_nr */
|
||||||
|
static inline uint8_t l1sap_chan2ss(uint8_t chan_nr)
|
||||||
|
{
|
||||||
|
if (L1SAP_IS_CHAN_SDCCH8(chan_nr))
|
||||||
|
return L1SAP_CHAN2SS_SDCCH8(chan_nr);
|
||||||
|
if (L1SAP_IS_CHAN_SDCCH4(chan_nr))
|
||||||
|
return L1SAP_CHAN2SS_SDCCH4(chan_nr);
|
||||||
|
if (L1SAP_IS_CHAN_TCHH(chan_nr))
|
||||||
|
return L1SAP_CHAN2SS_TCHH(chan_nr);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct gsm_lchan *get_lchan_by_chan_nr(struct gsm_bts_trx *trx,
|
||||||
|
unsigned int chan_nr);
|
||||||
|
|
||||||
|
/* allocate a msgb containing a osmo_phsap_prim + optional l2 data */
|
||||||
|
struct msgb *l1sap_msgb_alloc(unsigned int l2_len);
|
||||||
|
|
||||||
|
/* any L1 prim received from bts model */
|
||||||
|
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);
|
||||||
|
|
||||||
|
/* call-back function for incoming RTP */
|
||||||
|
void l1sap_rtp_rx_cb(struct osmo_rtp_socket *rs, const uint8_t *rtp_pl,
|
||||||
|
unsigned int rtp_pl_len, uint16_t seq_number,
|
||||||
|
uint32_t timestamp, bool marker);
|
||||||
|
|
||||||
|
/* channel control */
|
||||||
|
int l1sap_chan_act(struct gsm_bts_trx *trx, uint8_t chan_nr, struct tlv_parsed *tp);
|
||||||
|
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);
|
||||||
|
|
||||||
|
extern const struct value_string gsmtap_sapi_names[];
|
||||||
|
extern struct gsmtap_inst *gsmtap;
|
||||||
|
extern uint32_t gsmtap_sapi_mask;
|
||||||
|
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);
|
||||||
|
|
||||||
|
#define msgb_l1sap_prim(msg) ((struct osmo_phsap_prim *)(msg)->l1h)
|
||||||
|
|
||||||
|
int bts_check_for_first_ciphrd(struct gsm_lchan *lchan,
|
||||||
|
uint8_t *data, int len);
|
||||||
|
#endif /* L1SAP_H */
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
#ifndef _LOGGING_H
|
||||||
|
#define _LOGGING_H
|
||||||
|
|
||||||
|
#define DEBUG
|
||||||
|
#include <osmocom/core/logging.h>
|
||||||
|
|
||||||
|
enum {
|
||||||
|
DRSL,
|
||||||
|
DOML,
|
||||||
|
DRLL,
|
||||||
|
DRR,
|
||||||
|
DMEAS,
|
||||||
|
DPAG,
|
||||||
|
DL1C,
|
||||||
|
DL1P,
|
||||||
|
DDSP,
|
||||||
|
DPCU,
|
||||||
|
DHO,
|
||||||
|
DTRX,
|
||||||
|
DLOOP,
|
||||||
|
DABIS,
|
||||||
|
DRTP,
|
||||||
|
DSUM,
|
||||||
|
};
|
||||||
|
|
||||||
|
extern const struct log_info bts_log_info;
|
||||||
|
|
||||||
|
/* LOGP with gsm_time prefix */
|
||||||
|
#define LOGPGT(ss, lvl, gt, fmt, args...) \
|
||||||
|
LOGP(ss, lvl, "%s " fmt, osmo_dump_gsmtime(gt), ## args)
|
||||||
|
#define DEBUGPGT(ss, gt, fmt, args...) \
|
||||||
|
LOGP(ss, LOGL_DEBUG, "%s " fmt, osmo_dump_gsmtime(gt), ## args)
|
||||||
|
|
||||||
|
/* LOGP with frame number prefix */
|
||||||
|
#define LOGPFN(ss, lvl, fn, fmt, args...) \
|
||||||
|
LOGP(ss, lvl, "%s " fmt, gsm_fn_as_gsmtime_str(fn), ## args)
|
||||||
|
#define DEBUGPFN(ss, fn, fmt, args...) \
|
||||||
|
LOGP(ss, LOGL_DEBUG, "%s " fmt, gsm_fn_as_gsmtime_str(fn), ## args)
|
||||||
|
|
||||||
|
#endif /* _LOGGING_H */
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
#ifndef OSMO_BTS_MEAS_H
|
||||||
|
#define OSMO_BTS_MEAS_H
|
||||||
|
|
||||||
|
#define MEAS_MAX_TIMING_ADVANCE 63
|
||||||
|
#define MEAS_MIN_TIMING_ADVANCE 0
|
||||||
|
|
||||||
|
int lchan_new_ul_meas(struct gsm_lchan *lchan, struct bts_ul_meas *ulm, uint32_t fn);
|
||||||
|
|
||||||
|
int lchan_meas_check_compute(struct gsm_lchan *lchan, uint32_t fn);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* Routines to check the structurally integrity of messages
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <osmo-bts/gsm_data.h>
|
||||||
|
#include <osmo-bts/dtx_dl_amr_fsm.h>
|
||||||
|
|
||||||
|
#include <osmocom/codec/codec.h>
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
struct msgb;
|
||||||
|
|
||||||
|
/* Access 1st part of msgb control buffer */
|
||||||
|
#define rtpmsg_marker_bit(x) ((x)->cb[0])
|
||||||
|
|
||||||
|
/* Access 2nd part of msgb control buffer */
|
||||||
|
#define rtpmsg_seq(x) ((x)->cb[1])
|
||||||
|
|
||||||
|
/* Access 3rd part of msgb control buffer */
|
||||||
|
#define rtpmsg_ts(x) ((x)->cb[2])
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Classification of OML message. ETSI for plain GSM 12.21
|
||||||
|
* messages and IPA/Osmo for manufacturer messages.
|
||||||
|
*/
|
||||||
|
enum {
|
||||||
|
OML_MSG_TYPE_ETSI,
|
||||||
|
OML_MSG_TYPE_IPA,
|
||||||
|
OML_MSG_TYPE_OSMO,
|
||||||
|
};
|
||||||
|
|
||||||
|
void lchan_set_marker(bool t, struct gsm_lchan *lchan);
|
||||||
|
bool dtx_dl_amr_enabled(const struct gsm_lchan *lchan);
|
||||||
|
void dtx_dispatch(struct gsm_lchan *lchan, enum dtx_dl_amr_fsm_events e);
|
||||||
|
bool dtx_recursion(const struct gsm_lchan *lchan);
|
||||||
|
void dtx_int_signal(struct gsm_lchan *lchan);
|
||||||
|
bool dtx_is_first_p1(const struct gsm_lchan *lchan);
|
||||||
|
void dtx_cache_payload(struct gsm_lchan *lchan, const uint8_t *l1_payload,
|
||||||
|
size_t length, uint32_t fn, int update);
|
||||||
|
int dtx_dl_amr_fsm_step(struct gsm_lchan *lchan, const uint8_t *rtp_pl,
|
||||||
|
size_t rtp_pl_len, uint32_t fn, uint8_t *l1_payload,
|
||||||
|
bool marker, uint8_t *len, uint8_t *ft_out);
|
||||||
|
uint8_t repeat_last_sid(struct gsm_lchan *lchan, uint8_t *dst, uint32_t fn);
|
||||||
|
int msg_verify_ipa_structure(struct msgb *msg);
|
||||||
|
int msg_verify_oml_structure(struct msgb *msg);
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
#ifndef _OML_H
|
||||||
|
#define _OML_H
|
||||||
|
|
||||||
|
#include <osmocom/gsm/protocol/gsm_12_21.h>
|
||||||
|
|
||||||
|
struct gsm_bts;
|
||||||
|
struct gsm_abis_mo;
|
||||||
|
struct msgb;
|
||||||
|
struct gsm_lchan;
|
||||||
|
|
||||||
|
|
||||||
|
int oml_init(struct gsm_abis_mo *mo);
|
||||||
|
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);
|
||||||
|
|
||||||
|
/* Change the state and send STATE CHG REP */
|
||||||
|
int oml_mo_state_chg(struct gsm_abis_mo *mo, int op_state, int avail_state);
|
||||||
|
|
||||||
|
/* First initialization of MO, does _not_ generate state changes */
|
||||||
|
void oml_mo_state_init(struct gsm_abis_mo *mo, int op_state, int avail_state);
|
||||||
|
|
||||||
|
/* Update admin state and send ACK/NACK */
|
||||||
|
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_mo_tx_sw_act_rep(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,
|
||||||
|
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, ...);
|
||||||
|
|
||||||
|
#endif // _OML_H */
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
#ifndef OSMO_BTS_PAGING_H
|
||||||
|
#define OSMO_BTS_PAGING_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <osmocom/gsm/gsm_utils.h>
|
||||||
|
#include <osmocom/gsm/protocol/gsm_04_08.h>
|
||||||
|
|
||||||
|
struct paging_state;
|
||||||
|
struct gsm_bts;
|
||||||
|
|
||||||
|
/* initialize paging code */
|
||||||
|
struct paging_state *paging_init(struct gsm_bts *bts,
|
||||||
|
unsigned int num_paging_max,
|
||||||
|
unsigned int paging_lifetime);
|
||||||
|
|
||||||
|
/* (re) configure paging code */
|
||||||
|
void paging_config(struct paging_state *ps,
|
||||||
|
unsigned int num_paging_max,
|
||||||
|
unsigned int paging_lifetime);
|
||||||
|
|
||||||
|
void paging_reset(struct paging_state *ps);
|
||||||
|
|
||||||
|
/* The max number of paging entries */
|
||||||
|
unsigned int paging_get_queue_max(struct paging_state *ps);
|
||||||
|
void paging_set_queue_max(struct paging_state *ps, unsigned int queue_max);
|
||||||
|
|
||||||
|
/* The lifetime of a paging entry */
|
||||||
|
unsigned int paging_get_lifetime(struct paging_state *ps);
|
||||||
|
void paging_set_lifetime(struct paging_state *ps, unsigned int lifetime);
|
||||||
|
|
||||||
|
/* update with new SYSTEM INFORMATION parameters */
|
||||||
|
int paging_si_update(struct paging_state *ps, struct gsm48_control_channel_descr *chan_desc);
|
||||||
|
|
||||||
|
/* Add an identity to the paging queue */
|
||||||
|
int paging_add_identity(struct paging_state *ps, uint8_t paging_group,
|
||||||
|
const uint8_t *identity_lv, uint8_t chan_needed);
|
||||||
|
|
||||||
|
/* Add an IMM.ASS message to the paging queue */
|
||||||
|
int paging_add_imm_ass(struct paging_state *ps, const uint8_t *data,
|
||||||
|
uint8_t len);
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
|
||||||
|
|
||||||
|
/* inspection methods below */
|
||||||
|
int paging_group_queue_empty(struct paging_state *ps, uint8_t group);
|
||||||
|
int paging_queue_length(struct paging_state *ps);
|
||||||
|
int paging_buffer_space(struct paging_state *ps);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
#ifndef _PCU_IF_H
|
||||||
|
#define _PCU_IF_H
|
||||||
|
|
||||||
|
extern int pcu_direct;
|
||||||
|
|
||||||
|
int pcu_tx_info_ind(void);
|
||||||
|
int pcu_tx_si13(const struct gsm_bts *bts, bool enable);
|
||||||
|
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_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_sock_init(const char *path);
|
||||||
|
void pcu_sock_exit(void);
|
||||||
|
|
||||||
|
bool pcu_connected(void);
|
||||||
|
|
||||||
|
#endif /* _PCU_IF_H */
|
||||||
@@ -0,0 +1,195 @@
|
|||||||
|
#ifndef _PCUIF_PROTO_H
|
||||||
|
#define _PCUIF_PROTO_H
|
||||||
|
|
||||||
|
#include <osmocom/gsm/l1sap.h>
|
||||||
|
|
||||||
|
#define PCU_SOCK_DEFAULT "/tmp/pcu_bts"
|
||||||
|
|
||||||
|
#define PCU_IF_VERSION 0x09
|
||||||
|
#define TXT_MAX_LEN 128
|
||||||
|
|
||||||
|
/* msg_type */
|
||||||
|
#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_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 */
|
||||||
|
#define PCU_IF_MSG_INFO_IND 0x32 /* retrieve BTS info */
|
||||||
|
#define PCU_IF_MSG_ACT_REQ 0x40 /* activate/deactivate PDCH */
|
||||||
|
#define PCU_IF_MSG_TIME_IND 0x52 /* GSM time indication */
|
||||||
|
#define PCU_IF_MSG_PAG_REQ 0x60 /* paging request */
|
||||||
|
#define PCU_IF_MSG_TXT_IND 0x70 /* Text indication for BTS */
|
||||||
|
|
||||||
|
/* sapi */
|
||||||
|
#define PCU_IF_SAPI_RACH 0x01 /* channel request on CCCH */
|
||||||
|
#define PCU_IF_SAPI_AGCH 0x02 /* assignment on AGCH */
|
||||||
|
#define PCU_IF_SAPI_PCH 0x03 /* paging/assignment on PCH */
|
||||||
|
#define PCU_IF_SAPI_BCCH 0x04 /* SI on BCCH */
|
||||||
|
#define PCU_IF_SAPI_PDTCH 0x05 /* packet data/control/ccch block */
|
||||||
|
#define PCU_IF_SAPI_PRACH 0x06 /* packet random access channel */
|
||||||
|
#define PCU_IF_SAPI_PTCCH 0x07 /* packet TA control channel */
|
||||||
|
#define PCU_IF_SAPI_AGCH_DT 0x08 /* assignment on AGCH but with additional TLLI */
|
||||||
|
|
||||||
|
/* flags */
|
||||||
|
#define PCU_IF_FLAG_ACTIVE (1 << 0)/* BTS is active */
|
||||||
|
#define PCU_IF_FLAG_SYSMO (1 << 1)/* access PDCH of sysmoBTS directly */
|
||||||
|
#define PCU_IF_FLAG_CS1 (1 << 16)
|
||||||
|
#define PCU_IF_FLAG_CS2 (1 << 17)
|
||||||
|
#define PCU_IF_FLAG_CS3 (1 << 18)
|
||||||
|
#define PCU_IF_FLAG_CS4 (1 << 19)
|
||||||
|
#define PCU_IF_FLAG_MCS1 (1 << 20)
|
||||||
|
#define PCU_IF_FLAG_MCS2 (1 << 21)
|
||||||
|
#define PCU_IF_FLAG_MCS3 (1 << 22)
|
||||||
|
#define PCU_IF_FLAG_MCS4 (1 << 23)
|
||||||
|
#define PCU_IF_FLAG_MCS5 (1 << 24)
|
||||||
|
#define PCU_IF_FLAG_MCS6 (1 << 25)
|
||||||
|
#define PCU_IF_FLAG_MCS7 (1 << 26)
|
||||||
|
#define PCU_IF_FLAG_MCS8 (1 << 27)
|
||||||
|
#define PCU_IF_FLAG_MCS9 (1 << 28)
|
||||||
|
|
||||||
|
enum gsm_pcu_if_text_type {
|
||||||
|
PCU_VERSION,
|
||||||
|
PCU_OML_ALERT,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct gsm_pcu_if_txt_ind {
|
||||||
|
uint8_t type; /* gsm_pcu_if_text_type */
|
||||||
|
char text[TXT_MAX_LEN]; /* Text to be transmitted to BTS */
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
struct gsm_pcu_if_data {
|
||||||
|
uint8_t sapi;
|
||||||
|
uint8_t len;
|
||||||
|
uint8_t data[162];
|
||||||
|
uint32_t fn;
|
||||||
|
uint16_t arfcn;
|
||||||
|
uint8_t trx_nr;
|
||||||
|
uint8_t ts_nr;
|
||||||
|
uint8_t block_nr;
|
||||||
|
int8_t rssi;
|
||||||
|
uint16_t ber10k; /* !< \brief BER in units of 0.01% */
|
||||||
|
int16_t ta_offs_qbits; /* !< \brief Burst TA Offset in quarter bits */
|
||||||
|
int16_t lqual_cb; /* !< \brief Link quality in centiBel */
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
/* data confirmation with direct tlli (instead of raw mac block with tlli) */
|
||||||
|
struct gsm_pcu_if_data_cnf_dt {
|
||||||
|
uint8_t sapi;
|
||||||
|
uint32_t tlli;
|
||||||
|
uint32_t fn;
|
||||||
|
uint16_t arfcn;
|
||||||
|
uint8_t trx_nr;
|
||||||
|
uint8_t ts_nr;
|
||||||
|
uint8_t block_nr;
|
||||||
|
int8_t rssi;
|
||||||
|
uint16_t ber10k; /* !< \brief BER in units of 0.01% */
|
||||||
|
int16_t ta_offs_qbits; /* !< \brief Burst TA Offset in quarter bits */
|
||||||
|
int16_t lqual_cb; /* !< \brief Link quality in centiBel */
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
struct gsm_pcu_if_rts_req {
|
||||||
|
uint8_t sapi;
|
||||||
|
uint8_t spare[3];
|
||||||
|
uint32_t fn;
|
||||||
|
uint16_t arfcn;
|
||||||
|
uint8_t trx_nr;
|
||||||
|
uint8_t ts_nr;
|
||||||
|
uint8_t block_nr;
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
struct gsm_pcu_if_rach_ind {
|
||||||
|
uint8_t sapi;
|
||||||
|
uint16_t ra;
|
||||||
|
int16_t qta;
|
||||||
|
uint32_t fn;
|
||||||
|
uint16_t arfcn;
|
||||||
|
uint8_t is_11bit;
|
||||||
|
uint8_t burst_type;
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
struct gsm_pcu_if_info_trx {
|
||||||
|
uint16_t arfcn;
|
||||||
|
uint8_t pdch_mask; /* PDCH channels per TS */
|
||||||
|
uint8_t spare;
|
||||||
|
uint8_t tsc[8]; /* TSC per channel */
|
||||||
|
uint32_t hlayer1;
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
struct gsm_pcu_if_info_ind {
|
||||||
|
uint32_t version;
|
||||||
|
uint32_t flags;
|
||||||
|
struct gsm_pcu_if_info_trx trx[8]; /* TRX infos per BTS */
|
||||||
|
uint8_t bsic;
|
||||||
|
/* RAI */
|
||||||
|
uint16_t mcc, mnc;
|
||||||
|
uint8_t mnc_3_digits;
|
||||||
|
uint16_t lac, rac;
|
||||||
|
/* NSE */
|
||||||
|
uint16_t nsei;
|
||||||
|
uint8_t nse_timer[7];
|
||||||
|
uint8_t cell_timer[11];
|
||||||
|
/* cell */
|
||||||
|
uint16_t cell_id;
|
||||||
|
uint16_t repeat_time;
|
||||||
|
uint8_t repeat_count;
|
||||||
|
uint16_t bvci;
|
||||||
|
uint8_t t3142;
|
||||||
|
uint8_t t3169;
|
||||||
|
uint8_t t3191;
|
||||||
|
uint8_t t3193_10ms;
|
||||||
|
uint8_t t3195;
|
||||||
|
uint8_t n3101;
|
||||||
|
uint8_t n3103;
|
||||||
|
uint8_t n3105;
|
||||||
|
uint8_t cv_countdown;
|
||||||
|
uint16_t dl_tbf_ext;
|
||||||
|
uint16_t ul_tbf_ext;
|
||||||
|
uint8_t initial_cs;
|
||||||
|
uint8_t initial_mcs;
|
||||||
|
/* NSVC */
|
||||||
|
uint16_t nsvci[2];
|
||||||
|
uint16_t local_port[2];
|
||||||
|
uint16_t remote_port[2];
|
||||||
|
uint32_t remote_ip[2];
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
struct gsm_pcu_if_act_req {
|
||||||
|
uint8_t activate;
|
||||||
|
uint8_t trx_nr;
|
||||||
|
uint8_t ts_nr;
|
||||||
|
uint8_t spare;
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
struct gsm_pcu_if_time_ind {
|
||||||
|
uint32_t fn;
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
struct gsm_pcu_if_pag_req {
|
||||||
|
uint8_t sapi;
|
||||||
|
uint8_t chan_needed;
|
||||||
|
uint8_t identity_lv[9];
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
struct gsm_pcu_if {
|
||||||
|
/* context based information */
|
||||||
|
uint8_t msg_type; /* message type */
|
||||||
|
uint8_t bts_nr; /* bts number */
|
||||||
|
uint8_t spare[2];
|
||||||
|
|
||||||
|
union {
|
||||||
|
struct gsm_pcu_if_data data_req;
|
||||||
|
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_rts_req rts_req;
|
||||||
|
struct gsm_pcu_if_rach_ind rach_ind;
|
||||||
|
struct gsm_pcu_if_txt_ind txt_ind;
|
||||||
|
struct gsm_pcu_if_info_ind info_ind;
|
||||||
|
struct gsm_pcu_if_act_req act_req;
|
||||||
|
struct gsm_pcu_if_time_ind time_ind;
|
||||||
|
struct gsm_pcu_if_pag_req pag_req;
|
||||||
|
} u;
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
#endif /* _PCUIF_PROTO_H */
|
||||||
@@ -0,0 +1,160 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <osmocom/core/linuxlist.h>
|
||||||
|
|
||||||
|
#include <osmo-bts/scheduler.h>
|
||||||
|
|
||||||
|
#include <linux/if_packet.h>
|
||||||
|
#include "btsconfig.h"
|
||||||
|
|
||||||
|
struct gsm_bts_trx;
|
||||||
|
struct virt_um_inst;
|
||||||
|
|
||||||
|
enum phy_link_type {
|
||||||
|
PHY_LINK_T_NONE,
|
||||||
|
PHY_LINK_T_SYSMOBTS,
|
||||||
|
PHY_LINK_T_OSMOTRX,
|
||||||
|
PHY_LINK_T_VIRTUAL,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum phy_link_state {
|
||||||
|
PHY_LINK_SHUTDOWN,
|
||||||
|
PHY_LINK_CONNECTING,
|
||||||
|
PHY_LINK_CONNECTED,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* A PHY link represents the connection to a given PHYsical layer
|
||||||
|
* implementation. That PHY link contains 1...N PHY instances, one for
|
||||||
|
* each TRX */
|
||||||
|
struct phy_link {
|
||||||
|
struct llist_head list;
|
||||||
|
int num;
|
||||||
|
enum phy_link_type type;
|
||||||
|
enum phy_link_state state;
|
||||||
|
struct llist_head instances;
|
||||||
|
char *description;
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
} sysmobts;
|
||||||
|
struct {
|
||||||
|
char *local_ip;
|
||||||
|
char *remote_ip;
|
||||||
|
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;
|
||||||
|
} osmotrx;
|
||||||
|
struct {
|
||||||
|
char *mcast_dev; /* Network device for 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 */
|
||||||
|
uint16_t ms_mcast_port;
|
||||||
|
struct virt_um_inst *virt_um;
|
||||||
|
} virt;
|
||||||
|
struct {
|
||||||
|
/* MAC address of the PHY */
|
||||||
|
struct sockaddr_ll phy_addr;
|
||||||
|
/* Network device name */
|
||||||
|
char *netdev_name;
|
||||||
|
|
||||||
|
/* configuration */
|
||||||
|
uint32_t rf_port_index;
|
||||||
|
#if OCTPHY_USE_ANTENNA_ID == 1
|
||||||
|
uint32_t rx_ant_id;
|
||||||
|
uint32_t tx_ant_id;
|
||||||
|
#endif
|
||||||
|
uint32_t rx_gain_db;
|
||||||
|
bool tx_atten_flag;
|
||||||
|
uint32_t tx_atten_db;
|
||||||
|
#if OCTPHY_MULTI_TRX == 1
|
||||||
|
/* arfcn used by TRX with id 0 */
|
||||||
|
uint16_t center_arfcn;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct octphy_hdl *hdl;
|
||||||
|
} octphy;
|
||||||
|
} u;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct phy_instance {
|
||||||
|
/* liked inside phy_link.linstances */
|
||||||
|
struct llist_head list;
|
||||||
|
int num;
|
||||||
|
char *description;
|
||||||
|
char version[MAX_VERSION_LENGTH];
|
||||||
|
/* pointer to the PHY link to which we belong */
|
||||||
|
struct phy_link *phy_link;
|
||||||
|
|
||||||
|
/* back-pointer to the TRX to which we're associated */
|
||||||
|
struct gsm_bts_trx *trx;
|
||||||
|
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
/* configuration */
|
||||||
|
uint8_t clk_use_eeprom;
|
||||||
|
uint32_t dsp_trace_f;
|
||||||
|
int clk_cal;
|
||||||
|
uint8_t clk_src;
|
||||||
|
char *calib_path;
|
||||||
|
|
||||||
|
struct femtol1_hdl *hdl;
|
||||||
|
} sysmobts;
|
||||||
|
struct {
|
||||||
|
struct trx_l1h *hdl;
|
||||||
|
bool sw_act_reported;
|
||||||
|
} osmotrx;
|
||||||
|
struct {
|
||||||
|
struct l1sched_trx sched;
|
||||||
|
} virt;
|
||||||
|
struct {
|
||||||
|
/* logical transceiver number within one PHY */
|
||||||
|
uint32_t trx_id;
|
||||||
|
/* trx lock state variable */
|
||||||
|
int trx_locked;
|
||||||
|
} octphy;
|
||||||
|
struct {
|
||||||
|
/* configuration */
|
||||||
|
uint32_t dsp_trace_f;
|
||||||
|
char *calib_path;
|
||||||
|
int minTxPower;
|
||||||
|
int maxTxPower;
|
||||||
|
struct lc15l1_hdl *hdl;
|
||||||
|
uint8_t max_cell_size; /* 0:166 qbits*/
|
||||||
|
uint8_t diversity_mode; /* 0: SISO A, 1: SISO B, 2: MRC */
|
||||||
|
uint8_t pedestal_mode; /* 0: unused TS is OFF, 1: unused TS is in minimum Tx power */
|
||||||
|
uint8_t dsp_alive_period; /* DSP alive timer period */
|
||||||
|
uint8_t tx_pwr_adj_mode; /* 0: no auto adjust power, 1: auto adjust power using RMS detector */
|
||||||
|
uint8_t tx_pwr_red_8psk; /* 8-PSK maximum Tx power reduction level in dB */
|
||||||
|
} lc15;
|
||||||
|
} u;
|
||||||
|
};
|
||||||
|
|
||||||
|
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);
|
||||||
|
int phy_links_open(void);
|
||||||
|
|
||||||
|
struct phy_instance *phy_instance_by_num(struct phy_link *plink, int num);
|
||||||
|
struct phy_instance *phy_instance_create(struct phy_link *plink, int num);
|
||||||
|
void phy_instance_link_to_trx(struct phy_instance *pinst, struct gsm_bts_trx *trx);
|
||||||
|
void phy_instance_destroy(struct phy_instance *pinst);
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
OSMO_ASSERT(trx);
|
||||||
|
return trx->role_bts.l1h;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bts_model_phy_link_open(struct phy_link *plink);
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <osmo-bts/gsm_data.h>
|
||||||
|
|
||||||
|
int lchan_ms_pwr_ctrl(struct gsm_lchan *lchan,
|
||||||
|
const uint8_t ms_power, const int rxLevel);
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
#ifndef _RSL_H
|
||||||
|
#define _RSL_H
|
||||||
|
|
||||||
|
/**
|
||||||
|
* What kind of release/activation is done? A silent one for
|
||||||
|
* the PDCH or one triggered through RSL?
|
||||||
|
*/
|
||||||
|
enum {
|
||||||
|
LCHAN_REL_ACT_RSL,
|
||||||
|
LCHAN_REL_ACT_PCU,
|
||||||
|
LCHAN_REL_ACT_OML,
|
||||||
|
LCHAN_REL_ACT_REACT, /* remove once auto-activation hack is removed from opstart_compl() */
|
||||||
|
};
|
||||||
|
|
||||||
|
#define LCHAN_FN_DUMMY 0xFFFFFFFF
|
||||||
|
#define LCHAN_FN_WAIT 0xFFFFFFFE
|
||||||
|
|
||||||
|
int msgb_queue_flush(struct llist_head *list);
|
||||||
|
|
||||||
|
int down_rsl(struct gsm_bts_trx *trx, struct msgb *msg);
|
||||||
|
int rsl_tx_rf_res(struct gsm_bts_trx *trx);
|
||||||
|
int rsl_tx_chan_rqd(struct gsm_bts_trx *trx, struct gsm_time *gtime,
|
||||||
|
uint8_t ra, uint8_t acc_delay);
|
||||||
|
int rsl_tx_est_ind(struct gsm_lchan *lchan, uint8_t link_id, uint8_t *data, int len);
|
||||||
|
|
||||||
|
int rsl_tx_chan_act_acknack(struct gsm_lchan *lchan, uint8_t cause);
|
||||||
|
int rsl_tx_conn_fail(struct gsm_lchan *lchan, uint8_t cause);
|
||||||
|
int rsl_tx_rf_rel_ack(struct gsm_lchan *lchan);
|
||||||
|
int rsl_tx_hando_det(struct gsm_lchan *lchan, uint8_t *ho_delay);
|
||||||
|
|
||||||
|
int lchan_deactivate(struct gsm_lchan *lchan);
|
||||||
|
|
||||||
|
/* call-back for LAPDm code, called when it wants to send msgs UP */
|
||||||
|
int lapdm_rll_tx_cb(struct msgb *msg, struct lapdm_entity *le, void *ctx);
|
||||||
|
|
||||||
|
int rsl_tx_ipac_dlcx_ind(struct gsm_lchan *lchan, uint8_t cause);
|
||||||
|
int rsl_tx_ccch_load_ind_pch(struct gsm_bts *bts, uint16_t paging_avail);
|
||||||
|
int rsl_tx_ccch_load_ind_rach(struct gsm_bts *bts, uint16_t total,
|
||||||
|
uint16_t busy, uint16_t access);
|
||||||
|
|
||||||
|
void cb_ts_disconnected(struct gsm_bts_trx_ts *ts);
|
||||||
|
void cb_ts_connected(struct gsm_bts_trx_ts *ts);
|
||||||
|
void ipacc_dyn_pdch_complete(struct gsm_bts_trx_ts *ts, int rc);
|
||||||
|
|
||||||
|
#endif // _RSL_H */
|
||||||
|
|
||||||
@@ -0,0 +1,224 @@
|
|||||||
|
#ifndef TRX_SCHEDULER_H
|
||||||
|
#define TRX_SCHEDULER_H
|
||||||
|
|
||||||
|
#include <osmocom/core/utils.h>
|
||||||
|
|
||||||
|
#include <osmo-bts/gsm_data.h>
|
||||||
|
|
||||||
|
/* These types define the different channels on a multiframe.
|
||||||
|
* Each channel has queues and can be activated individually.
|
||||||
|
*/
|
||||||
|
enum trx_chan_type {
|
||||||
|
TRXC_IDLE = 0,
|
||||||
|
TRXC_FCCH,
|
||||||
|
TRXC_SCH,
|
||||||
|
TRXC_BCCH,
|
||||||
|
TRXC_RACH,
|
||||||
|
TRXC_CCCH,
|
||||||
|
TRXC_TCHF,
|
||||||
|
TRXC_TCHH_0,
|
||||||
|
TRXC_TCHH_1,
|
||||||
|
TRXC_SDCCH4_0,
|
||||||
|
TRXC_SDCCH4_1,
|
||||||
|
TRXC_SDCCH4_2,
|
||||||
|
TRXC_SDCCH4_3,
|
||||||
|
TRXC_SDCCH8_0,
|
||||||
|
TRXC_SDCCH8_1,
|
||||||
|
TRXC_SDCCH8_2,
|
||||||
|
TRXC_SDCCH8_3,
|
||||||
|
TRXC_SDCCH8_4,
|
||||||
|
TRXC_SDCCH8_5,
|
||||||
|
TRXC_SDCCH8_6,
|
||||||
|
TRXC_SDCCH8_7,
|
||||||
|
TRXC_SACCHTF,
|
||||||
|
TRXC_SACCHTH_0,
|
||||||
|
TRXC_SACCHTH_1,
|
||||||
|
TRXC_SACCH4_0,
|
||||||
|
TRXC_SACCH4_1,
|
||||||
|
TRXC_SACCH4_2,
|
||||||
|
TRXC_SACCH4_3,
|
||||||
|
TRXC_SACCH8_0,
|
||||||
|
TRXC_SACCH8_1,
|
||||||
|
TRXC_SACCH8_2,
|
||||||
|
TRXC_SACCH8_3,
|
||||||
|
TRXC_SACCH8_4,
|
||||||
|
TRXC_SACCH8_5,
|
||||||
|
TRXC_SACCH8_6,
|
||||||
|
TRXC_SACCH8_7,
|
||||||
|
TRXC_PDTCH,
|
||||||
|
TRXC_PTCCH,
|
||||||
|
_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
|
||||||
|
|
||||||
|
enum trx_burst_type {
|
||||||
|
TRX_BURST_GMSK,
|
||||||
|
TRX_BURST_8PSK,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* States each channel on a multiframe */
|
||||||
|
struct l1sched_chan_state {
|
||||||
|
/* scheduler */
|
||||||
|
uint8_t active; /* Channel is active */
|
||||||
|
ubit_t *dl_bursts; /* burst buffer for TX */
|
||||||
|
enum trx_burst_type dl_burst_type; /* GMSK or 8PSK burst type */
|
||||||
|
sbit_t *ul_bursts; /* burst buffer for RX */
|
||||||
|
uint32_t ul_first_fn; /* fn of first burst */
|
||||||
|
uint8_t ul_mask; /* mask of received bursts */
|
||||||
|
|
||||||
|
/* RSSI / TOA */
|
||||||
|
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) */
|
||||||
|
|
||||||
|
/* loss detection */
|
||||||
|
uint8_t lost; /* (SACCH) loss detection */
|
||||||
|
|
||||||
|
/* mode */
|
||||||
|
uint8_t rsl_cmode, tch_mode; /* mode for TCH channels */
|
||||||
|
|
||||||
|
/* AMR */
|
||||||
|
uint8_t codec[4]; /* 4 possible codecs for amr */
|
||||||
|
int codecs; /* number of possible codecs */
|
||||||
|
float ber_sum; /* sum of bit error rates */
|
||||||
|
int ber_num; /* number of bit error rates */
|
||||||
|
uint8_t ul_ft; /* current uplink FT index */
|
||||||
|
uint8_t dl_ft; /* current downlink FT index */
|
||||||
|
uint8_t ul_cmr; /* current uplink CMR index */
|
||||||
|
uint8_t dl_cmr; /* current downlink CMR index */
|
||||||
|
uint8_t amr_loop; /* if AMR loop is enabled */
|
||||||
|
|
||||||
|
/* TCH/H */
|
||||||
|
uint8_t dl_ongoing_facch; /* FACCH/H on downlink */
|
||||||
|
uint8_t ul_ongoing_facch; /* FACCH/H on uplink */
|
||||||
|
|
||||||
|
/* encryption */
|
||||||
|
int ul_encr_algo; /* A5/x encry algo downlink */
|
||||||
|
int dl_encr_algo; /* A5/x encry algo uplink */
|
||||||
|
int ul_encr_key_len;
|
||||||
|
int dl_encr_key_len;
|
||||||
|
uint8_t ul_encr_key[MAX_A5_KEY_LEN];
|
||||||
|
uint8_t dl_encr_key[MAX_A5_KEY_LEN];
|
||||||
|
|
||||||
|
/* 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 */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct l1sched_ts {
|
||||||
|
uint8_t mf_index; /* selected multiframe index */
|
||||||
|
uint32_t mf_last_fn; /* last received frame number */
|
||||||
|
uint8_t mf_period; /* period of multiframe */
|
||||||
|
const struct trx_sched_frame *mf_frames; /* pointer to frame layout */
|
||||||
|
|
||||||
|
struct llist_head dl_prims; /* Queue primitives for TX */
|
||||||
|
|
||||||
|
/* Channel states for all logical channels */
|
||||||
|
struct l1sched_chan_state chan_state[_TRX_CHAN_MAX];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct l1sched_trx {
|
||||||
|
struct gsm_bts_trx *trx;
|
||||||
|
struct l1sched_ts ts[TRX_NR_TS];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct l1sched_ts *l1sched_trx_get_ts(struct l1sched_trx *l1t, uint8_t tn);
|
||||||
|
|
||||||
|
/*! \brief how many frame numbers in advance we should send bursts to PHY */
|
||||||
|
extern uint32_t trx_clock_advance;
|
||||||
|
/*! \brief advance RTS.ind to L2 by that many clocks */
|
||||||
|
extern uint32_t trx_rts_advance;
|
||||||
|
/*! \brief last frame number as received from PHY */
|
||||||
|
extern uint32_t transceiver_last_fn;
|
||||||
|
|
||||||
|
|
||||||
|
/*! \brief Initialize the scheduler data structures */
|
||||||
|
int trx_sched_init(struct l1sched_trx *l1t, struct gsm_bts_trx *trx);
|
||||||
|
|
||||||
|
/*! \brief De-initialize the scheduler data structures */
|
||||||
|
void trx_sched_exit(struct l1sched_trx *l1t);
|
||||||
|
|
||||||
|
/*! \brief Handle a PH-DATA.req from L2 down to L1 */
|
||||||
|
int trx_sched_ph_data_req(struct l1sched_trx *l1t, struct osmo_phsap_prim *l1sap);
|
||||||
|
|
||||||
|
/*! \brief Handle a PH-TCH.req from L2 down to L1 */
|
||||||
|
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 set multiframe scheduler to given physical channel config */
|
||||||
|
int trx_sched_set_pchan(struct l1sched_trx *l1t, uint8_t tn,
|
||||||
|
enum gsm_phys_chan_config pchan);
|
||||||
|
|
||||||
|
/*! \brief set all matching logical channels active/inactive */
|
||||||
|
int trx_sched_set_lchan(struct l1sched_trx *l1t, uint8_t chan_nr, uint8_t link_id,
|
||||||
|
int active);
|
||||||
|
|
||||||
|
/*! \brief set mode of all matching logical channels to given mode(s) */
|
||||||
|
int trx_sched_set_mode(struct l1sched_trx *l1t, uint8_t chan_nr, uint8_t rsl_cmode,
|
||||||
|
uint8_t tch_mode, int codecs, uint8_t codec0, uint8_t codec1,
|
||||||
|
uint8_t codec2, uint8_t codec3, uint8_t initial_codec,
|
||||||
|
uint8_t handover);
|
||||||
|
|
||||||
|
/*! \brief set ciphering on given logical channels */
|
||||||
|
int trx_sched_set_cipher(struct l1sched_trx *l1t, uint8_t chan_nr, int downlink,
|
||||||
|
int algo, uint8_t *key, int key_len);
|
||||||
|
|
||||||
|
/* \brief close all logical channels and reset timeslots */
|
||||||
|
void trx_sched_reset(struct l1sched_trx *l1t);
|
||||||
|
|
||||||
|
|
||||||
|
/* frame structures */
|
||||||
|
struct trx_sched_frame {
|
||||||
|
/*! \brief downlink TRX channel type */
|
||||||
|
enum trx_chan_type dl_chan;
|
||||||
|
/*! \brief downlink block ID */
|
||||||
|
uint8_t dl_bid;
|
||||||
|
/*! \brief uplink TRX channel type */
|
||||||
|
enum trx_chan_type ul_chan;
|
||||||
|
/*! \brief uplink block ID */
|
||||||
|
uint8_t ul_bid;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* multiframe structure */
|
||||||
|
struct trx_sched_multiframe {
|
||||||
|
/*! \brief physical channel config (channel combination) */
|
||||||
|
enum gsm_phys_chan_config pchan;
|
||||||
|
/*! \brief applies to which timeslots? */
|
||||||
|
uint8_t slotmask;
|
||||||
|
/*! \brief repeats how many frames */
|
||||||
|
uint8_t period;
|
||||||
|
/*! \brief pointer to scheduling structure */
|
||||||
|
const struct trx_sched_frame *frames;
|
||||||
|
/*! \brief human-readable name */
|
||||||
|
const char *name;
|
||||||
|
};
|
||||||
|
|
||||||
|
int find_sched_mframe_idx(enum gsm_phys_chan_config pchan, uint8_t tn);
|
||||||
|
|
||||||
|
/*! Determine if given frame number contains SACCH (true) or other (false) burst */
|
||||||
|
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[];
|
||||||
|
|
||||||
|
#endif /* TRX_SCHEDULER_H */
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define LOGL1S(subsys, level, l1t, tn, chan, fn, fmt, args ...) \
|
||||||
|
LOGP(subsys, level, "%s %s %s: " fmt, \
|
||||||
|
gsm_fn_as_gsmtime_str(fn), \
|
||||||
|
gsm_ts_name(&(l1t)->trx->ts[tn]), \
|
||||||
|
chan >=0 ? trx_chan_desc[chan].name : "", ## args)
|
||||||
|
|
||||||
|
typedef int trx_sched_rts_func(struct l1sched_trx *l1t, uint8_t tn,
|
||||||
|
uint32_t fn, enum trx_chan_type chan);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
struct trx_chan_desc {
|
||||||
|
/*! \brief Is this on a PDCH (PS) ? */
|
||||||
|
int pdch;
|
||||||
|
/*! \brief TRX Channel Type */
|
||||||
|
enum trx_chan_type chan;
|
||||||
|
/*! \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;
|
||||||
|
};
|
||||||
|
extern const struct trx_chan_desc trx_chan_desc[_TRX_CHAN_MAX];
|
||||||
|
|
||||||
|
extern const ubit_t _sched_tsc[8][26];
|
||||||
|
extern const ubit_t _sched_egprs_tsc[8][78];
|
||||||
|
const ubit_t _sched_fcch_burst[148];
|
||||||
|
const ubit_t _sched_sch_train[64];
|
||||||
|
|
||||||
|
struct msgb *_sched_dequeue_prim(struct l1sched_trx *l1t, int8_t tn, uint32_t fn,
|
||||||
|
enum trx_chan_type chan);
|
||||||
|
|
||||||
|
int _sched_compose_ph_data_ind(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||||
|
enum trx_chan_type chan, uint8_t *l2,
|
||||||
|
uint8_t l2_len, float rssi,
|
||||||
|
int16_t ta_offs_256bits, int16_t link_qual_cb,
|
||||||
|
uint16_t ber10k,
|
||||||
|
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);
|
||||||
|
|
||||||
|
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);
|
||||||
|
ubit_t *tx_fcch_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_sch_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_data_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_pdtch_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_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);
|
||||||
|
|
||||||
|
const ubit_t *_sched_dl_burst(struct l1sched_trx *l1t, uint8_t tn,
|
||||||
|
uint32_t fn, uint16_t *nbits);
|
||||||
|
int _sched_rts(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn);
|
||||||
|
void _sched_act_rach_det(struct l1sched_trx *l1t, uint8_t tn, uint8_t ss, int activate);
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
#ifndef OSMO_BTS_SIGNAL_H
|
||||||
|
#define OSMO_BTS_SIGNAL_H
|
||||||
|
|
||||||
|
#include <osmocom/core/signal.h>
|
||||||
|
|
||||||
|
enum sig_subsys {
|
||||||
|
SS_GLOBAL,
|
||||||
|
SS_FAIL,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum signals_global {
|
||||||
|
S_NEW_SYSINFO,
|
||||||
|
S_NEW_OP_STATE,
|
||||||
|
S_NEW_NSE_ATTR,
|
||||||
|
S_NEW_CELL_ATTR,
|
||||||
|
S_NEW_NSVC_ATTR,
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <osmocom/core/timer.h>
|
||||||
|
|
||||||
|
/* our unit is 'milli dB" or "milli dBm", i.e. 1/1000 of a dB(m) */
|
||||||
|
#define to_mdB(x) (x * 1000)
|
||||||
|
|
||||||
|
/* PA calibration table */
|
||||||
|
struct pa_calibration {
|
||||||
|
int delta_mdB[1024]; /* gain delta at given ARFCN */
|
||||||
|
/* FIXME: thermal calibration */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* representation of a RF power amplifier */
|
||||||
|
struct power_amp {
|
||||||
|
/* nominal gain of the PA */
|
||||||
|
int nominal_gain_mdB;
|
||||||
|
/* table with calibrated actual gain for each ARFCN */
|
||||||
|
struct pa_calibration calib;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Transmit power related parameters of a transceiver */
|
||||||
|
struct trx_power_params {
|
||||||
|
/* specified maximum output of TRX at full power, has to be
|
||||||
|
* initialized by BTS model at startup*/
|
||||||
|
int trx_p_max_out_mdBm;
|
||||||
|
|
||||||
|
/* intended current total system output power */
|
||||||
|
int p_total_tgt_mdBm;
|
||||||
|
|
||||||
|
/* actual current total system output power, filled in by tx_power code */
|
||||||
|
int p_total_cur_mdBm;
|
||||||
|
|
||||||
|
/* current temporary attenuation due to thermal management,
|
||||||
|
* set by thermal management code via control interface */
|
||||||
|
int thermal_attenuation_mdB;
|
||||||
|
|
||||||
|
/* external gain (+) or attenuation (-) added by the user, configured
|
||||||
|
* by the user via VTY */
|
||||||
|
int user_gain_mdB;
|
||||||
|
|
||||||
|
/* calibration table of internal PA */
|
||||||
|
struct power_amp pa;
|
||||||
|
|
||||||
|
/* calibration table of user PA */
|
||||||
|
struct power_amp user_pa;
|
||||||
|
|
||||||
|
/* power ramping related data */
|
||||||
|
struct {
|
||||||
|
/* maximum initial Pout including all PAs */
|
||||||
|
int max_initial_pout_mdBm;
|
||||||
|
/* temporary attenuation due to power ramping */
|
||||||
|
int attenuation_mdB;
|
||||||
|
unsigned int step_size_mdB;
|
||||||
|
unsigned int step_interval_sec;
|
||||||
|
struct osmo_timer_list step_timer;
|
||||||
|
} ramp;
|
||||||
|
};
|
||||||
|
|
||||||
|
int get_p_max_out_mdBm(struct gsm_bts_trx *trx);
|
||||||
|
|
||||||
|
int get_p_nominal_mdBm(struct gsm_bts_trx *trx);
|
||||||
|
|
||||||
|
int get_p_target_mdBm(struct gsm_bts_trx *trx, uint8_t bs_power_ie);
|
||||||
|
int get_p_target_mdBm_lchan(struct gsm_lchan *lchan);
|
||||||
|
|
||||||
|
int get_p_trxout_target_mdBm(struct gsm_bts_trx *trx, uint8_t bs_power_ie);
|
||||||
|
int get_p_trxout_target_mdBm_lchan(struct gsm_lchan *lchan);
|
||||||
|
|
||||||
|
int get_p_trxout_actual_mdBm(struct gsm_bts_trx *trx, uint8_t bs_power_ie);
|
||||||
|
int get_p_trxout_actual_mdBm_lchan(struct gsm_lchan *lchan);
|
||||||
|
|
||||||
|
int power_ramp_start(struct gsm_bts_trx *trx, int p_total_tgt_mdBm, int bypass);
|
||||||
|
|
||||||
|
void power_trx_change_compl(struct gsm_bts_trx *trx, int p_trxout_cur_mdBm);
|
||||||
|
|
||||||
|
int power_ramp_initial_power_mdBm(struct gsm_bts_trx *trx);
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
#ifndef OSMOBTS_VTY_H
|
||||||
|
#define OSMOBTS_VTY_H
|
||||||
|
|
||||||
|
#include <osmocom/vty/vty.h>
|
||||||
|
#include <osmocom/vty/command.h>
|
||||||
|
|
||||||
|
enum bts_vty_node {
|
||||||
|
/* PHY_NODE must come before BTS node to ensure the phy
|
||||||
|
* instances are created at the time the TRX nodes want to refer
|
||||||
|
* to them */
|
||||||
|
PHY_NODE = _LAST_OSMOVTY_NODE + 1,
|
||||||
|
PHY_INST_NODE,
|
||||||
|
BTS_NODE,
|
||||||
|
TRX_NODE,
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct cmd_element ournode_exit_cmd;
|
||||||
|
extern struct cmd_element ournode_end_cmd;
|
||||||
|
|
||||||
|
extern struct cmd_element cfg_bts_auto_band_cmd;
|
||||||
|
extern struct cmd_element cfg_bts_no_auto_band_cmd;
|
||||||
|
|
||||||
|
struct phy_instance *vty_get_phy_instance(struct vty *vty, int phy_nr, int inst_nr);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
extern struct vty_app_info bts_vty_info;
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
SUBDIRS = common osmo-bts-virtual osmo-bts-omldummy
|
||||||
|
|
||||||
|
if ENABLE_SYSMOBTS
|
||||||
|
SUBDIRS += osmo-bts-sysmo
|
||||||
|
endif
|
||||||
|
|
||||||
|
if ENABLE_TRX
|
||||||
|
SUBDIRS += osmo-bts-trx
|
||||||
|
endif
|
||||||
|
|
||||||
|
if ENABLE_OCTPHY
|
||||||
|
SUBDIRS += osmo-bts-octphy
|
||||||
|
endif
|
||||||
|
|
||||||
|
if ENABLE_LC15BTS
|
||||||
|
SUBDIRS += osmo-bts-litecell15
|
||||||
|
endif
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include
|
||||||
|
AM_CFLAGS = -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOTRAU_CFLAGS) $(LIBOSMOCODEC_CFLAGS)
|
||||||
|
LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOTRAU_LIBS) $(LIBOSMOCODEC_LIBS)
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
libl1sched_a_SOURCES = scheduler.c
|
||||||
@@ -0,0 +1,276 @@
|
|||||||
|
/* Abis/IP interface routines utilizing libosmo-abis (Pablo) */
|
||||||
|
|
||||||
|
/* (C) 2011 by Andreas Eversberg <jolly@eversberg.eu>
|
||||||
|
* (C) 2011-2013 by Harald Welte <laforge@gnumonks.org>
|
||||||
|
*
|
||||||
|
* 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 "btsconfig.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <osmocom/core/select.h>
|
||||||
|
#include <osmocom/core/timer.h>
|
||||||
|
#include <osmocom/core/msgb.h>
|
||||||
|
#include <osmocom/core/signal.h>
|
||||||
|
#include <osmocom/core/macaddr.h>
|
||||||
|
#include <osmocom/abis/abis.h>
|
||||||
|
#include <osmocom/abis/e1_input.h>
|
||||||
|
#include <osmocom/abis/ipaccess.h>
|
||||||
|
#include <osmocom/gsm/ipa.h>
|
||||||
|
|
||||||
|
#include <osmo-bts/logging.h>
|
||||||
|
#include <osmo-bts/gsm_data.h>
|
||||||
|
#include <osmo-bts/bts.h>
|
||||||
|
#include <osmo-bts/rsl.h>
|
||||||
|
#include <osmo-bts/oml.h>
|
||||||
|
#include <osmo-bts/bts_model.h>
|
||||||
|
|
||||||
|
static struct gsm_bts *g_bts;
|
||||||
|
|
||||||
|
int abis_oml_sendmsg(struct msgb *msg)
|
||||||
|
{
|
||||||
|
struct gsm_bts *bts = msg->trx->bts;
|
||||||
|
|
||||||
|
if (!bts->oml_link) {
|
||||||
|
llist_add_tail(&msg->list, &bts->oml_queue);
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
/* osmo-bts uses msg->trx internally, but libosmo-abis uses
|
||||||
|
* the signalling link at msg->dst */
|
||||||
|
msg->dst = bts->oml_link;
|
||||||
|
return abis_sendmsg(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void drain_oml_queue(struct gsm_bts *bts)
|
||||||
|
{
|
||||||
|
struct msgb *msg, *msg2;
|
||||||
|
|
||||||
|
llist_for_each_entry_safe(msg, msg2, &bts->oml_queue, list) {
|
||||||
|
/* osmo-bts uses msg->trx internally, but libosmo-abis uses
|
||||||
|
* the signalling link at msg->dst */
|
||||||
|
llist_del(&msg->list);
|
||||||
|
msg->dst = bts->oml_link;
|
||||||
|
abis_sendmsg(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int abis_bts_rsl_sendmsg(struct msgb *msg)
|
||||||
|
{
|
||||||
|
OSMO_ASSERT(msg->trx);
|
||||||
|
|
||||||
|
if (msg->trx->bts->variant == BTS_OSMO_OMLDUMMY) {
|
||||||
|
msgb_free(msg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* osmo-bts uses msg->trx internally, but libosmo-abis uses
|
||||||
|
* the signalling link at msg->dst */
|
||||||
|
msg->dst = msg->trx->rsl_link;
|
||||||
|
return abis_sendmsg(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct e1inp_sign_link *sign_link_up(void *unit, struct e1inp_line *line,
|
||||||
|
enum e1inp_sign_type type)
|
||||||
|
{
|
||||||
|
struct e1inp_sign_link *sign_link = NULL;
|
||||||
|
struct gsm_bts_trx *trx;
|
||||||
|
int trx_nr;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case E1INP_SIGN_OML:
|
||||||
|
LOGP(DABIS, LOGL_INFO, "OML Signalling link up\n");
|
||||||
|
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);
|
||||||
|
drain_oml_queue(g_bts);
|
||||||
|
sign_link->trx = g_bts->c0;
|
||||||
|
bts_link_estab(g_bts);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
trx_nr = type - E1INP_SIGN_RSL;
|
||||||
|
LOGP(DABIS, LOGL_INFO, "RSL Signalling link for TRX%d up\n",
|
||||||
|
trx_nr);
|
||||||
|
trx = gsm_bts_trx_num(g_bts, trx_nr);
|
||||||
|
if (!trx) {
|
||||||
|
LOGP(DABIS, LOGL_ERROR, "TRX%d does not exixt!\n",
|
||||||
|
trx_nr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
trx_link_estab(trx);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sign_link;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sign_link_down(struct e1inp_line *line)
|
||||||
|
{
|
||||||
|
struct gsm_bts_trx *trx;
|
||||||
|
LOGP(DABIS, LOGL_ERROR, "Signalling link down\n");
|
||||||
|
|
||||||
|
/* First remove the OML signalling link */
|
||||||
|
if (g_bts->oml_link)
|
||||||
|
e1inp_sign_link_destroy(g_bts->oml_link);
|
||||||
|
g_bts->oml_link = NULL;
|
||||||
|
|
||||||
|
/* Then iterate over the RSL signalling links */
|
||||||
|
llist_for_each_entry(trx, &g_bts->trx_list, list) {
|
||||||
|
if (trx->rsl_link) {
|
||||||
|
e1inp_sign_link_destroy(trx->rsl_link);
|
||||||
|
trx->rsl_link = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bts_model_abis_close(g_bts);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* callback for incoming mesages from A-bis/IP */
|
||||||
|
static int sign_link_cb(struct msgb *msg)
|
||||||
|
{
|
||||||
|
struct e1inp_sign_link *link = msg->dst;
|
||||||
|
|
||||||
|
/* osmo-bts code assumes msg->trx is set, but libosmo-abis works
|
||||||
|
* with the sign_link stored in msg->dst, so we have to convert
|
||||||
|
* here */
|
||||||
|
msg->trx = link->trx;
|
||||||
|
|
||||||
|
switch (link->type) {
|
||||||
|
case E1INP_SIGN_OML:
|
||||||
|
down_oml(link->trx->bts, msg);
|
||||||
|
break;
|
||||||
|
case E1INP_SIGN_RSL:
|
||||||
|
down_rsl(link->trx, msg);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
msgb_free(msg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t get_signlink_remote_ip(struct e1inp_sign_link *link)
|
||||||
|
{
|
||||||
|
int fd = link->ts->driver.ipaccess.fd.fd;
|
||||||
|
struct sockaddr_in sin;
|
||||||
|
socklen_t slen = sizeof(sin);
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = getpeername(fd, (struct sockaddr *)&sin, &slen);
|
||||||
|
if (rc < 0) {
|
||||||
|
LOGP(DOML, LOGL_ERROR, "Cannot determine remote IP Addr: %s\n",
|
||||||
|
strerror(errno));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* we assume that the soket is AF_INET. As Abis/IP contains
|
||||||
|
* lots of hard-coded IPv4 addresses, this safe */
|
||||||
|
OSMO_ASSERT(sin.sin_family == AF_INET);
|
||||||
|
|
||||||
|
return ntohl(sin.sin_addr.s_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int inp_s_cbfn(unsigned int subsys, unsigned int signal,
|
||||||
|
void *hdlr_data, void *signal_data)
|
||||||
|
{
|
||||||
|
if (subsys != SS_L_INPUT)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
DEBUGP(DABIS, "Input Signal %u received\n", signal);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct ipaccess_unit bts_dev_info = {
|
||||||
|
.unit_name = "sysmoBTS",
|
||||||
|
.equipvers = "", /* FIXME: read this from hw */
|
||||||
|
.swversion = PACKAGE_VERSION,
|
||||||
|
.location1 = "",
|
||||||
|
.location2 = "",
|
||||||
|
.serno = "",
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct e1inp_line_ops line_ops = {
|
||||||
|
.cfg = {
|
||||||
|
.ipa = {
|
||||||
|
.role = E1INP_LINE_R_BTS,
|
||||||
|
.dev = &bts_dev_info,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
.sign_link_up = sign_link_up,
|
||||||
|
.sign_link_down = sign_link_down,
|
||||||
|
.sign_link = sign_link_cb,
|
||||||
|
};
|
||||||
|
|
||||||
|
void abis_init(struct gsm_bts *bts)
|
||||||
|
{
|
||||||
|
g_bts = bts;
|
||||||
|
|
||||||
|
oml_init(&bts->mo);
|
||||||
|
libosmo_abis_init(NULL);
|
||||||
|
|
||||||
|
osmo_signal_register_handler(SS_L_INPUT, &inp_s_cbfn, bts);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct e1inp_line *abis_open(struct gsm_bts *bts, char *dst_host,
|
||||||
|
char *model_name)
|
||||||
|
{
|
||||||
|
struct e1inp_line *line;
|
||||||
|
|
||||||
|
/* patch in various data from VTY and othe 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;
|
||||||
|
bts_dev_info.bts_id = bts->ip_access.bts_id;
|
||||||
|
bts_dev_info.unit_name = model_name;
|
||||||
|
if (bts->description)
|
||||||
|
bts_dev_info.unit_name = bts->description;
|
||||||
|
bts_dev_info.location2 = model_name;
|
||||||
|
|
||||||
|
line = e1inp_line_find(0);
|
||||||
|
if (!line)
|
||||||
|
line = e1inp_line_create(0, "ipa");
|
||||||
|
if (!line)
|
||||||
|
return NULL;
|
||||||
|
e1inp_line_bind_ops(line, &line_ops);
|
||||||
|
|
||||||
|
/* This will open the OML connection now */
|
||||||
|
if (e1inp_line_update(line) < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return line;
|
||||||
|
}
|
||||||
@@ -0,0 +1,170 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <osmocom/core/logging.h>
|
||||||
|
|
||||||
|
#include <osmo-bts/logging.h>
|
||||||
|
#include <osmo-bts/amr.h>
|
||||||
|
|
||||||
|
void amr_log_mr_conf(int ss, int logl, const char *pfx,
|
||||||
|
struct amr_multirate_conf *amr_mrc)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
LOGP(ss, logl, "%s AMR MR Conf: num_modes=%u",
|
||||||
|
pfx, amr_mrc->num_modes);
|
||||||
|
|
||||||
|
for (i = 0; i < amr_mrc->num_modes; i++)
|
||||||
|
LOGPC(ss, logl, ", mode[%u] = %u/%u/%u",
|
||||||
|
i, amr_mrc->bts_mode[i].mode,
|
||||||
|
amr_mrc->bts_mode[i].threshold,
|
||||||
|
amr_mrc->bts_mode[i].hysteresis);
|
||||||
|
LOGPC(ss, logl, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int get_amr_mode_idx(const struct amr_multirate_conf *amr_mrc,
|
||||||
|
uint8_t cmi)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
for (i = 0; i < amr_mrc->num_modes; i++) {
|
||||||
|
if (amr_mrc->bts_mode[i].mode == cmi)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint8_t set_cmr_mode_idx(const struct amr_multirate_conf *amr_mrc,
|
||||||
|
uint8_t cmr)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
/* Codec Mode Request is in upper 4 bits of RTP payload header,
|
||||||
|
* and we simply copy the CMR into the CMC */
|
||||||
|
if (cmr == 0xF) {
|
||||||
|
/* FIXME: we need some state about the last codec mode */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = get_amr_mode_idx(amr_mrc, cmr);
|
||||||
|
if (rc < 0) {
|
||||||
|
/* FIXME: we need some state about the last codec mode */
|
||||||
|
LOGP(DRTP, LOGL_INFO, "RTP->L1: overriding CMR %u\n", cmr);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint8_t set_cmi_mode_idx(const struct amr_multirate_conf *amr_mrc,
|
||||||
|
uint8_t cmi)
|
||||||
|
{
|
||||||
|
int rc = get_amr_mode_idx(amr_mrc, cmi);
|
||||||
|
if (rc < 0) {
|
||||||
|
LOGP(DRTP, LOGL_ERROR, "AMR CMI %u not part of AMR MR set\n",
|
||||||
|
cmi);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void amr_set_mode_pref(uint8_t *data, const struct amr_multirate_conf *amr_mrc,
|
||||||
|
uint8_t cmi, uint8_t cmr)
|
||||||
|
{
|
||||||
|
data[0] = set_cmi_mode_idx(amr_mrc, cmi);
|
||||||
|
data[1] = set_cmr_mode_idx(amr_mrc, cmr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* parse a GSM 04.08 MultiRate Config IE (10.5.2.21aa) in a more
|
||||||
|
* comfortable internal data structure */
|
||||||
|
int amr_parse_mr_conf(struct amr_multirate_conf *amr_mrc,
|
||||||
|
const uint8_t *mr_conf, unsigned int len)
|
||||||
|
{
|
||||||
|
uint8_t mr_version = mr_conf[0] >> 5;
|
||||||
|
uint8_t num_codecs = 0;
|
||||||
|
int i, j = 0;
|
||||||
|
|
||||||
|
if (mr_version != 1) {
|
||||||
|
LOGP(DRSL, LOGL_ERROR, "AMR Multirate Version %u unknown\n",
|
||||||
|
mr_version);
|
||||||
|
goto ret_einval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check number of active codecs */
|
||||||
|
for (i = 0; i < 8; i++) {
|
||||||
|
if (mr_conf[1] & (1 << i))
|
||||||
|
num_codecs++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check for minimum length */
|
||||||
|
if (num_codecs == 0 ||
|
||||||
|
(num_codecs == 1 && len < 2) ||
|
||||||
|
(num_codecs == 2 && len < 4) ||
|
||||||
|
(num_codecs == 3 && len < 5) ||
|
||||||
|
(num_codecs == 4 && len < 6) ||
|
||||||
|
(num_codecs > 4)) {
|
||||||
|
LOGP(DRSL, LOGL_ERROR, "AMR Multirate with %u modes len=%u "
|
||||||
|
"not possible\n", num_codecs, len);
|
||||||
|
goto ret_einval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* copy the first two octets of the IE */
|
||||||
|
amr_mrc->gsm48_ie[0] = mr_conf[0];
|
||||||
|
amr_mrc->gsm48_ie[1] = mr_conf[1];
|
||||||
|
|
||||||
|
amr_mrc->num_modes = num_codecs;
|
||||||
|
|
||||||
|
for (i = 0; i < 8; i++) {
|
||||||
|
if (mr_conf[1] & (1 << i)) {
|
||||||
|
amr_mrc->bts_mode[j++].mode = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (num_codecs >= 2) {
|
||||||
|
amr_mrc->bts_mode[0].threshold = mr_conf[1] & 0x3F;
|
||||||
|
amr_mrc->bts_mode[0].hysteresis = mr_conf[2] >> 4;
|
||||||
|
}
|
||||||
|
if (num_codecs >= 3) {
|
||||||
|
amr_mrc->bts_mode[1].threshold =
|
||||||
|
((mr_conf[2] & 0xF) << 2) | (mr_conf[3] >> 6);
|
||||||
|
amr_mrc->bts_mode[1].hysteresis = (mr_conf[3] >> 2) & 0xF;
|
||||||
|
}
|
||||||
|
if (num_codecs >= 4) {
|
||||||
|
amr_mrc->bts_mode[2].threshold =
|
||||||
|
((mr_conf[3] & 0x3) << 4) | (mr_conf[4] >> 4);
|
||||||
|
amr_mrc->bts_mode[2].hysteresis = mr_conf[4] & 0xF;
|
||||||
|
}
|
||||||
|
|
||||||
|
return num_codecs;
|
||||||
|
|
||||||
|
ret_einval:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! \brief determine AMR initial codec mode for given logical channel
|
||||||
|
* \returns integer between 0..3 for AMR codce mode 1..4 */
|
||||||
|
unsigned int amr_get_initial_mode(struct gsm_lchan *lchan)
|
||||||
|
{
|
||||||
|
struct amr_multirate_conf *amr_mrc = &lchan->tch.amr_mr;
|
||||||
|
struct gsm48_multi_rate_conf *mr_conf =
|
||||||
|
(struct gsm48_multi_rate_conf *) amr_mrc->gsm48_ie;
|
||||||
|
|
||||||
|
if (mr_conf->icmi) {
|
||||||
|
/* initial mode given, coding in TS 05.09 3.4.1 */
|
||||||
|
return mr_conf->smod;
|
||||||
|
} else {
|
||||||
|
/* implicit rule according to TS 05.09 Chapter 3.4.3 */
|
||||||
|
switch (amr_mrc->num_modes) {
|
||||||
|
case 2:
|
||||||
|
case 3:
|
||||||
|
/* return the most robust */
|
||||||
|
return 0;
|
||||||
|
case 4:
|
||||||
|
/* return the second-most robust */
|
||||||
|
return 1;
|
||||||
|
case 1:
|
||||||
|
default:
|
||||||
|
/* return the only mode we have */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,740 @@
|
|||||||
|
/* BTS support code common to all supported BTS models */
|
||||||
|
|
||||||
|
/* (C) 2011 by Andreas Eversberg <jolly@eversberg.eu>
|
||||||
|
* (C) 2011 by Harald Welte <laforge@gnumonks.org>
|
||||||
|
*
|
||||||
|
* 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 <errno.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
|
||||||
|
#include <osmocom/core/select.h>
|
||||||
|
#include <osmocom/core/timer.h>
|
||||||
|
#include <osmocom/core/msgb.h>
|
||||||
|
#include <osmocom/core/talloc.h>
|
||||||
|
#include <osmocom/core/stats.h>
|
||||||
|
#include <osmocom/core/rate_ctr.h>
|
||||||
|
#include <osmocom/gsm/protocol/gsm_12_21.h>
|
||||||
|
#include <osmocom/gsm/lapdm.h>
|
||||||
|
#include <osmocom/trau/osmo_ortp.h>
|
||||||
|
|
||||||
|
#include <osmo-bts/logging.h>
|
||||||
|
#include <osmo-bts/abis.h>
|
||||||
|
#include <osmo-bts/bts.h>
|
||||||
|
#include <osmo-bts/bts_model.h>
|
||||||
|
#include <osmo-bts/dtx_dl_amr_fsm.h>
|
||||||
|
#include <osmo-bts/pcuif_proto.h>
|
||||||
|
#include <osmo-bts/rsl.h>
|
||||||
|
#include <osmo-bts/oml.h>
|
||||||
|
#include <osmo-bts/signal.h>
|
||||||
|
#include <osmo-bts/dtx_dl_amr_fsm.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 */
|
||||||
|
|
||||||
|
static void bts_update_agch_max_queue_length(struct gsm_bts *bts);
|
||||||
|
|
||||||
|
struct gsm_network bts_gsmnet = {
|
||||||
|
.bts_list = { &bts_gsmnet.bts_list, &bts_gsmnet.bts_list },
|
||||||
|
.num_bts = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
void *tall_bts_ctx;
|
||||||
|
|
||||||
|
/* Table 3.1 TS 04.08: Values of parameter S */
|
||||||
|
static const uint8_t tx_integer[] = {
|
||||||
|
3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16, 20, 25, 32, 50,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint8_t s_values[][2] = {
|
||||||
|
{ 55, 41 }, { 76, 52 }, { 109, 58 }, { 163, 86 }, { 217, 115 },
|
||||||
|
};
|
||||||
|
|
||||||
|
static int bts_signal_cbfn(unsigned int subsys, unsigned int signal,
|
||||||
|
void *hdlr_data, void *signal_data)
|
||||||
|
{
|
||||||
|
if (subsys == SS_GLOBAL && signal == S_NEW_SYSINFO) {
|
||||||
|
struct gsm_bts *bts = signal_data;
|
||||||
|
|
||||||
|
bts_update_agch_max_queue_length(bts);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct rate_ctr_desc bts_ctr_desc[] = {
|
||||||
|
[BTS_CTR_PAGING_RCVD] = {"paging:rcvd", "Received paging requests (Abis)"},
|
||||||
|
[BTS_CTR_PAGING_DROP] = {"paging:drop", "Dropped paging requests (Abis)"},
|
||||||
|
[BTS_CTR_PAGING_SENT] = {"paging:sent", "Sent paging requests (Um)"},
|
||||||
|
|
||||||
|
[BTS_CTR_RACH_RCVD] = {"rach:rcvd", "Received RACH requests (Um)"},
|
||||||
|
[BTS_CTR_RACH_DROP] = {"rach:drop", "Dropped RACH requests (Um)"},
|
||||||
|
[BTS_CTR_RACH_HO] = {"rach:handover", "Received RACH requests (Handover)"},
|
||||||
|
[BTS_CTR_RACH_CS] = {"rach:cs", "Received RACH requests (CS/Abis)"},
|
||||||
|
[BTS_CTR_RACH_PS] = {"rach:ps", "Received RACH requests (PS/PCU)"},
|
||||||
|
|
||||||
|
[BTS_CTR_AGCH_RCVD] = {"agch:rcvd", "Received AGCH requests (Abis)"},
|
||||||
|
[BTS_CTR_AGCH_SENT] = {"agch:sent", "Sent AGCH requests (Abis)"},
|
||||||
|
[BTS_CTR_AGCH_DELETED] = {"agch:delete", "Sent AGCH DELETE IND (Abis)"},
|
||||||
|
};
|
||||||
|
static const struct rate_ctr_group_desc bts_ctrg_desc = {
|
||||||
|
"bts",
|
||||||
|
"base transceiver station",
|
||||||
|
OSMO_STATS_CLASS_GLOBAL,
|
||||||
|
ARRAY_SIZE(bts_ctr_desc),
|
||||||
|
bts_ctr_desc
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Initialize the BTS (and TRX) data structures, called before config
|
||||||
|
* file reading */
|
||||||
|
int bts_init(struct gsm_bts *bts)
|
||||||
|
{
|
||||||
|
struct gsm_bts_trx *trx;
|
||||||
|
int rc, i;
|
||||||
|
static int initialized = 0;
|
||||||
|
void *tall_rtp_ctx;
|
||||||
|
|
||||||
|
/* add to list of BTSs */
|
||||||
|
llist_add_tail(&bts->list, &bts_gsmnet.bts_list);
|
||||||
|
|
||||||
|
bts->band = GSM_BAND_1800;
|
||||||
|
|
||||||
|
INIT_LLIST_HEAD(&bts->agch_queue.queue);
|
||||||
|
bts->agch_queue.length = 0;
|
||||||
|
|
||||||
|
bts->ctrs = rate_ctr_group_alloc(bts, &bts_ctrg_desc, bts->nr);
|
||||||
|
|
||||||
|
/* enable management with default levels,
|
||||||
|
* raise threshold to GSM_BTS_AGCH_QUEUE_THRESH_LEVEL_DISABLE to
|
||||||
|
* disable this feature.
|
||||||
|
*/
|
||||||
|
bts->agch_queue.low_level = GSM_BTS_AGCH_QUEUE_LOW_LEVEL_DEFAULT;
|
||||||
|
bts->agch_queue.high_level = GSM_BTS_AGCH_QUEUE_HIGH_LEVEL_DEFAULT;
|
||||||
|
bts->agch_queue.thresh_level = GSM_BTS_AGCH_QUEUE_THRESH_LEVEL_DEFAULT;
|
||||||
|
|
||||||
|
/* configurable via VTY */
|
||||||
|
bts->paging_state = paging_init(bts, 200, 0);
|
||||||
|
bts->ul_power_target = -75; /* dBm default */
|
||||||
|
bts->rtp_jitter_adaptive = false;
|
||||||
|
|
||||||
|
/* configurable via OML */
|
||||||
|
bts->load.ccch.load_ind_period = 112;
|
||||||
|
load_timer_start(bts);
|
||||||
|
bts->rtp_jitter_buf_ms = 100;
|
||||||
|
bts->max_ta = 63;
|
||||||
|
bts->ny1 = 4;
|
||||||
|
bts->t3105_ms = 300;
|
||||||
|
bts->min_qual_rach = MIN_QUAL_RACH;
|
||||||
|
bts->min_qual_norm = MIN_QUAL_NORM;
|
||||||
|
bts->max_ber10k_rach = 1707; /* 7 of 41 bits is Eb/N0 of 0 dB = 0.1707 */
|
||||||
|
bts->pcu.sock_path = talloc_strdup(bts, PCU_SOCK_DEFAULT);
|
||||||
|
for (i = 0; i < ARRAY_SIZE(bts->t200_ms); i++)
|
||||||
|
bts->t200_ms[i] = oml_default_t200_ms[i];
|
||||||
|
|
||||||
|
/* default RADIO_LINK_TIMEOUT */
|
||||||
|
bts->radio_link_timeout = 32;
|
||||||
|
|
||||||
|
/* Start with the site manager */
|
||||||
|
oml_mo_state_init(&bts->site_mgr.mo, NM_OPSTATE_ENABLED, NM_AVSTATE_OK);
|
||||||
|
|
||||||
|
/* set BTS to dependency */
|
||||||
|
oml_mo_state_init(&bts->mo, -1, NM_AVSTATE_DEPENDENCY);
|
||||||
|
oml_mo_state_init(&bts->gprs.nse.mo, -1, NM_AVSTATE_DEPENDENCY);
|
||||||
|
oml_mo_state_init(&bts->gprs.cell.mo, -1, NM_AVSTATE_DEPENDENCY);
|
||||||
|
oml_mo_state_init(&bts->gprs.nsvc[0].mo, -1, NM_AVSTATE_DEPENDENCY);
|
||||||
|
oml_mo_state_init(&bts->gprs.nsvc[1].mo, NM_OPSTATE_DISABLED, NM_AVSTATE_OFF_LINE);
|
||||||
|
|
||||||
|
/* initialize bts data structure */
|
||||||
|
llist_for_each_entry(trx, &bts->trx_list, list) {
|
||||||
|
struct trx_power_params *tpp = &trx->power_params;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(trx->ts); i++) {
|
||||||
|
struct gsm_bts_trx_ts *ts = &trx->ts[i];
|
||||||
|
int k;
|
||||||
|
|
||||||
|
for (k = 0; k < ARRAY_SIZE(ts->lchan); k++) {
|
||||||
|
struct gsm_lchan *lchan = &ts->lchan[k];
|
||||||
|
INIT_LLIST_HEAD(&lchan->dl_tch_queue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Default values for the power adjustments */
|
||||||
|
tpp->ramp.max_initial_pout_mdBm = to_mdB(0);
|
||||||
|
tpp->ramp.step_size_mdB = to_mdB(2);
|
||||||
|
tpp->ramp.step_interval_sec = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* allocate a talloc pool for ORTP to ensure it doesn't have to go back
|
||||||
|
* to the libc malloc all the time */
|
||||||
|
tall_rtp_ctx = talloc_pool(tall_bts_ctx, 262144);
|
||||||
|
osmo_rtp_init(tall_rtp_ctx);
|
||||||
|
|
||||||
|
rc = bts_model_init(bts);
|
||||||
|
if (rc < 0) {
|
||||||
|
llist_del(&bts->list);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
bts_gsmnet.num_bts++;
|
||||||
|
|
||||||
|
if (!initialized) {
|
||||||
|
osmo_signal_register_handler(SS_GLOBAL, bts_signal_cbfn, NULL);
|
||||||
|
initialized = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
INIT_LLIST_HEAD(&bts->smscb_state.queue);
|
||||||
|
INIT_LLIST_HEAD(&bts->oml_queue);
|
||||||
|
|
||||||
|
/* register DTX DL FSM */
|
||||||
|
rc = osmo_fsm_register(&dtx_dl_amr_fsm);
|
||||||
|
OSMO_ASSERT(rc == 0);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void shutdown_timer_cb(void *data)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Shutdown timer expired\n");
|
||||||
|
exit(42);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct osmo_timer_list shutdown_timer = {
|
||||||
|
.cb = &shutdown_timer_cb,
|
||||||
|
};
|
||||||
|
|
||||||
|
void bts_shutdown(struct gsm_bts *bts, const char *reason)
|
||||||
|
{
|
||||||
|
struct gsm_bts_trx *trx;
|
||||||
|
|
||||||
|
if (osmo_timer_pending(&shutdown_timer)) {
|
||||||
|
LOGP(DOML, LOGL_NOTICE,
|
||||||
|
"BTS is already being shutdown.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGP(DOML, LOGL_NOTICE, "Shutting down BTS %u, Reason %s\n",
|
||||||
|
bts->nr, reason);
|
||||||
|
|
||||||
|
llist_for_each_entry_reverse(trx, &bts->trx_list, list) {
|
||||||
|
bts_model_trx_deact_rf(trx);
|
||||||
|
bts_model_trx_close(trx);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* shedule a timer to make sure select loop logic can run again
|
||||||
|
* to dispatch any pending primitives */
|
||||||
|
osmo_timer_schedule(&shutdown_timer, 3, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* main link is established, send status report */
|
||||||
|
int bts_link_estab(struct gsm_bts *bts)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
LOGP(DSUM, LOGL_INFO, "Main link established, sending Status'.\n");
|
||||||
|
|
||||||
|
/* BTS and SITE MGR are EANBLED, BTS is DEPENDENCY */
|
||||||
|
oml_tx_state_changed(&bts->site_mgr.mo);
|
||||||
|
oml_tx_state_changed(&bts->mo);
|
||||||
|
|
||||||
|
/* those should all be in DEPENDENCY */
|
||||||
|
oml_tx_state_changed(&bts->gprs.nse.mo);
|
||||||
|
oml_tx_state_changed(&bts->gprs.cell.mo);
|
||||||
|
oml_tx_state_changed(&bts->gprs.nsvc[0].mo);
|
||||||
|
oml_tx_state_changed(&bts->gprs.nsvc[1].mo);
|
||||||
|
|
||||||
|
/* All other objects start off-line until the BTS Model code says otherwise */
|
||||||
|
for (i = 0; i < bts->num_trx; i++) {
|
||||||
|
struct gsm_bts_trx *trx = gsm_bts_trx_num(bts, i);
|
||||||
|
|
||||||
|
oml_tx_state_changed(&trx->mo);
|
||||||
|
oml_tx_state_changed(&trx->bb_transc.mo);
|
||||||
|
|
||||||
|
for (j = 0; j < ARRAY_SIZE(trx->ts); j++) {
|
||||||
|
struct gsm_bts_trx_ts *ts = &trx->ts[j];
|
||||||
|
|
||||||
|
oml_tx_state_changed(&ts->mo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return bts_model_oml_estab(bts);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* RSL link is established, send status report */
|
||||||
|
int trx_link_estab(struct gsm_bts_trx *trx)
|
||||||
|
{
|
||||||
|
struct e1inp_sign_link *link = trx->rsl_link;
|
||||||
|
uint8_t radio_state = link ? NM_OPSTATE_ENABLED : NM_OPSTATE_DISABLED;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
LOGP(DSUM, LOGL_INFO, "RSL link (TRX %02x) state changed to %s, sending Status'.\n",
|
||||||
|
trx->nr, link ? "up" : "down");
|
||||||
|
|
||||||
|
oml_mo_state_chg(&trx->mo, radio_state, NM_AVSTATE_OK);
|
||||||
|
|
||||||
|
if (link)
|
||||||
|
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);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set the availability of the TRX (used by PHY driver) */
|
||||||
|
int trx_set_available(struct gsm_bts_trx *trx, int avail)
|
||||||
|
{
|
||||||
|
int tn;
|
||||||
|
|
||||||
|
LOGP(DSUM, LOGL_INFO, "TRX(%d): Setting available = %d\n",
|
||||||
|
trx->nr, avail);
|
||||||
|
if (avail) {
|
||||||
|
/* FIXME: This needs to be sorted out */
|
||||||
|
#if 0
|
||||||
|
oml_mo_state_chg(&trx->mo, NM_OPSTATE_DISABLED, NM_AVSTATE_OFF_LINE);
|
||||||
|
oml_mo_state_chg(&trx->bb_transc.mo, -1, NM_AVSTATE_OFF_LINE);
|
||||||
|
for (tn = 0; tn < ARRAY_SIZE(trx->ts); tn++)
|
||||||
|
oml_mo_state_chg(&trx->ts[tn].mo, NM_OPSTATE_DISABLED, NM_AVSTATE_DEPENDENCY);
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
oml_mo_state_chg(&trx->mo, NM_OPSTATE_DISABLED, NM_AVSTATE_NOT_INSTALLED);
|
||||||
|
oml_mo_state_chg(&trx->bb_transc.mo, -1, NM_AVSTATE_NOT_INSTALLED);
|
||||||
|
|
||||||
|
for (tn = 0; tn < ARRAY_SIZE(trx->ts); tn++)
|
||||||
|
oml_mo_state_chg(&trx->ts[tn].mo, NM_OPSTATE_DISABLED, NM_AVSTATE_NOT_INSTALLED);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int lchan_init_lapdm(struct gsm_lchan *lchan)
|
||||||
|
{
|
||||||
|
struct lapdm_channel *lc = &lchan->lapdm_ch;
|
||||||
|
|
||||||
|
lapdm_channel_init(lc, LAPDM_MODE_BTS);
|
||||||
|
lapdm_channel_set_flags(lc, LAPDM_ENT_F_POLLING_ONLY);
|
||||||
|
lapdm_channel_set_l1(lc, NULL, lchan);
|
||||||
|
lapdm_channel_set_l3(lc, lapdm_rll_tx_cb, lchan);
|
||||||
|
oml_set_lchan_t200(lchan);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define CCCH_RACH_RATIO_COMBINED256 (256*1/9)
|
||||||
|
#define CCCH_RACH_RATIO_SEPARATE256 (256*10/55)
|
||||||
|
|
||||||
|
int bts_agch_max_queue_length(int T, int bcch_conf)
|
||||||
|
{
|
||||||
|
int S, ccch_rach_ratio256, i;
|
||||||
|
int T_group = 0;
|
||||||
|
int is_ccch_comb = 0;
|
||||||
|
|
||||||
|
if (bcch_conf == RSL_BCCH_CCCH_CONF_1_C)
|
||||||
|
is_ccch_comb = 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The calculation is based on the ratio of the number RACH slots and
|
||||||
|
* CCCH blocks per time:
|
||||||
|
* Lmax = (T + 2*S) / R_RACH * R_CCCH
|
||||||
|
* where
|
||||||
|
* T3126_min = (T + 2*S) / R_RACH, as defined in GSM 04.08, 11.1.1
|
||||||
|
* R_RACH is the RACH slot rate (e.g. RACHs per multiframe)
|
||||||
|
* R_CCCH is the CCCH block rate (same time base like R_RACH)
|
||||||
|
* S and T are defined in GSM 04.08, 3.3.1.1.2
|
||||||
|
* The ratio is mainly influenced by the downlink only channels
|
||||||
|
* (BCCH, FCCH, SCH, CBCH) that can not be used for CCCH.
|
||||||
|
* An estimation with an error of < 10% is used:
|
||||||
|
* ~ 1/9 if CCCH is combined with SDCCH, and
|
||||||
|
* ~ 1/5.5 otherwise.
|
||||||
|
*/
|
||||||
|
ccch_rach_ratio256 = is_ccch_comb ?
|
||||||
|
CCCH_RACH_RATIO_COMBINED256 :
|
||||||
|
CCCH_RACH_RATIO_SEPARATE256;
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(tx_integer); i++) {
|
||||||
|
if (tx_integer[i] == T) {
|
||||||
|
T_group = i % 5;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
S = s_values[T_group][is_ccch_comb];
|
||||||
|
|
||||||
|
return (T + 2 * S) * ccch_rach_ratio256 / 256;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bts_update_agch_max_queue_length(struct gsm_bts *bts)
|
||||||
|
{
|
||||||
|
struct gsm48_system_information_type_3 *si3;
|
||||||
|
int old_max_length = bts->agch_queue.max_length;
|
||||||
|
|
||||||
|
if (!(bts->si_valid & (1<<SYSINFO_TYPE_3)))
|
||||||
|
return;
|
||||||
|
|
||||||
|
si3 = GSM_BTS_SI(bts, SYSINFO_TYPE_3);
|
||||||
|
|
||||||
|
bts->agch_queue.max_length =
|
||||||
|
bts_agch_max_queue_length(si3->rach_control.tx_integer,
|
||||||
|
si3->control_channel_desc.ccch_conf);
|
||||||
|
|
||||||
|
if (bts->agch_queue.max_length != old_max_length)
|
||||||
|
LOGP(DRSL, LOGL_INFO, "Updated AGCH max queue length to %d\n",
|
||||||
|
bts->agch_queue.max_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define REQ_REFS_PER_IMM_ASS_REJ 4
|
||||||
|
static int store_imm_ass_rej_refs(struct gsm48_imm_ass_rej *rej,
|
||||||
|
struct gsm48_req_ref *req_refs,
|
||||||
|
uint8_t *wait_inds,
|
||||||
|
int count)
|
||||||
|
{
|
||||||
|
switch (count) {
|
||||||
|
case 0:
|
||||||
|
/* TODO: Warning ? */
|
||||||
|
return 0;
|
||||||
|
default:
|
||||||
|
count = 4;
|
||||||
|
rej->req_ref4 = req_refs[3];
|
||||||
|
rej->wait_ind4 = wait_inds[3];
|
||||||
|
/* fall through */
|
||||||
|
case 3:
|
||||||
|
rej->req_ref3 = req_refs[2];
|
||||||
|
rej->wait_ind3 = wait_inds[2];
|
||||||
|
/* fall through */
|
||||||
|
case 2:
|
||||||
|
rej->req_ref2 = req_refs[1];
|
||||||
|
rej->wait_ind2 = wait_inds[1];
|
||||||
|
/* fall through */
|
||||||
|
case 1:
|
||||||
|
rej->req_ref1 = req_refs[0];
|
||||||
|
rej->wait_ind1 = wait_inds[0];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (count) {
|
||||||
|
case 1:
|
||||||
|
rej->req_ref2 = req_refs[0];
|
||||||
|
rej->wait_ind2 = wait_inds[0];
|
||||||
|
/* fall through */
|
||||||
|
case 2:
|
||||||
|
rej->req_ref3 = req_refs[0];
|
||||||
|
rej->wait_ind3 = wait_inds[0];
|
||||||
|
/* fall through */
|
||||||
|
case 3:
|
||||||
|
rej->req_ref4 = req_refs[0];
|
||||||
|
rej->wait_ind4 = wait_inds[0];
|
||||||
|
/* fall through */
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int extract_imm_ass_rej_refs(struct gsm48_imm_ass_rej *rej,
|
||||||
|
struct gsm48_req_ref *req_refs,
|
||||||
|
uint8_t *wait_inds)
|
||||||
|
{
|
||||||
|
int count = 0;
|
||||||
|
req_refs[count] = rej->req_ref1;
|
||||||
|
wait_inds[count] = rej->wait_ind1;
|
||||||
|
count++;
|
||||||
|
|
||||||
|
if (memcmp(&rej->req_ref1, &rej->req_ref2, sizeof(rej->req_ref2))) {
|
||||||
|
req_refs[count] = rej->req_ref2;
|
||||||
|
wait_inds[count] = rej->wait_ind2;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (memcmp(&rej->req_ref1, &rej->req_ref3, sizeof(rej->req_ref3)) &&
|
||||||
|
memcmp(&rej->req_ref2, &rej->req_ref3, sizeof(rej->req_ref3))) {
|
||||||
|
req_refs[count] = rej->req_ref3;
|
||||||
|
wait_inds[count] = rej->wait_ind3;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (memcmp(&rej->req_ref1, &rej->req_ref4, sizeof(rej->req_ref4)) &&
|
||||||
|
memcmp(&rej->req_ref2, &rej->req_ref4, sizeof(rej->req_ref4)) &&
|
||||||
|
memcmp(&rej->req_ref3, &rej->req_ref4, sizeof(rej->req_ref4))) {
|
||||||
|
req_refs[count] = rej->req_ref4;
|
||||||
|
wait_inds[count] = rej->wait_ind4;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int try_merge_imm_ass_rej(struct gsm48_imm_ass_rej *old_rej,
|
||||||
|
struct gsm48_imm_ass_rej *new_rej)
|
||||||
|
{
|
||||||
|
struct gsm48_req_ref req_refs[2 * REQ_REFS_PER_IMM_ASS_REJ];
|
||||||
|
uint8_t wait_inds[2 * REQ_REFS_PER_IMM_ASS_REJ];
|
||||||
|
int count = 0;
|
||||||
|
int stored = 0;
|
||||||
|
|
||||||
|
if (new_rej->msg_type != GSM48_MT_RR_IMM_ASS_REJ)
|
||||||
|
return 0;
|
||||||
|
if (old_rej->msg_type != GSM48_MT_RR_IMM_ASS_REJ)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* GSM 08.58, 5.7
|
||||||
|
* -> The BTS may combine serveral IMM.ASS.REJ messages
|
||||||
|
* -> Identical request refs in one message may be squeezed
|
||||||
|
*
|
||||||
|
* GSM 04.08, 9.1.20.2
|
||||||
|
* -> Request ref and wait ind are duplicated to fill the message
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Extract all entries */
|
||||||
|
count = extract_imm_ass_rej_refs(old_rej,
|
||||||
|
&req_refs[count], &wait_inds[count]);
|
||||||
|
if (count == REQ_REFS_PER_IMM_ASS_REJ)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
count += extract_imm_ass_rej_refs(new_rej,
|
||||||
|
&req_refs[count], &wait_inds[count]);
|
||||||
|
|
||||||
|
/* Store entries into old message */
|
||||||
|
stored = store_imm_ass_rej_refs(old_rej,
|
||||||
|
&req_refs[stored], &wait_inds[stored],
|
||||||
|
count);
|
||||||
|
count -= stored;
|
||||||
|
if (count == 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/* Store remaining entries into new message */
|
||||||
|
stored += store_imm_ass_rej_refs(new_rej,
|
||||||
|
&req_refs[stored], &wait_inds[stored],
|
||||||
|
count);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bts_agch_enqueue(struct gsm_bts *bts, struct msgb *msg)
|
||||||
|
{
|
||||||
|
int hard_limit = 1000;
|
||||||
|
struct gsm48_imm_ass_rej *imm_ass_cmd = msgb_l3(msg);
|
||||||
|
|
||||||
|
if (bts->agch_queue.length > hard_limit) {
|
||||||
|
LOGP(DSUM, LOGL_ERROR,
|
||||||
|
"AGCH: too many messages in queue, "
|
||||||
|
"refusing message type 0x%02x, length = %d/%d\n",
|
||||||
|
((struct gsm48_imm_ass *)msgb_l3(msg))->msg_type,
|
||||||
|
bts->agch_queue.length, bts->agch_queue.max_length);
|
||||||
|
|
||||||
|
bts->agch_queue.rejected_msgs++;
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bts->agch_queue.length > 0) {
|
||||||
|
struct msgb *last_msg =
|
||||||
|
llist_entry(bts->agch_queue.queue.prev, struct msgb, list);
|
||||||
|
struct gsm48_imm_ass_rej *last_imm_ass_rej = msgb_l3(last_msg);
|
||||||
|
|
||||||
|
if (try_merge_imm_ass_rej(last_imm_ass_rej, imm_ass_cmd)) {
|
||||||
|
bts->agch_queue.merged_msgs++;
|
||||||
|
msgb_free(msg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
msgb_enqueue(&bts->agch_queue.queue, msg);
|
||||||
|
bts->agch_queue.length++;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct msgb *bts_agch_dequeue(struct gsm_bts *bts)
|
||||||
|
{
|
||||||
|
struct msgb *msg = msgb_dequeue(&bts->agch_queue.queue);
|
||||||
|
if (!msg)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
bts->agch_queue.length--;
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
* reserved part of the CCCH.
|
||||||
|
*/
|
||||||
|
static void compact_agch_queue(struct gsm_bts *bts)
|
||||||
|
{
|
||||||
|
struct msgb *msg, *msg2;
|
||||||
|
int max_len, slope, offs;
|
||||||
|
int level_low = bts->agch_queue.low_level;
|
||||||
|
int level_high = bts->agch_queue.high_level;
|
||||||
|
int level_thres = bts->agch_queue.thresh_level;
|
||||||
|
|
||||||
|
max_len = bts->agch_queue.max_length;
|
||||||
|
|
||||||
|
if (max_len == 0)
|
||||||
|
max_len = 1;
|
||||||
|
|
||||||
|
if (bts->agch_queue.length < max_len * level_thres / 100)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* p^
|
||||||
|
* 1+ /'''''
|
||||||
|
* | /
|
||||||
|
* | /
|
||||||
|
* 0+---/--+----+--> Q length
|
||||||
|
* low high max_len
|
||||||
|
*/
|
||||||
|
|
||||||
|
offs = max_len * level_low / 100;
|
||||||
|
if (level_high > level_low)
|
||||||
|
slope = 0x10000 * 100 / (level_high - level_low);
|
||||||
|
else
|
||||||
|
slope = 0x10000 * max_len; /* p_drop >= 1 if len > offs */
|
||||||
|
|
||||||
|
llist_for_each_entry_safe(msg, msg2, &bts->agch_queue.queue, list) {
|
||||||
|
struct gsm48_imm_ass *imm_ass_cmd = msgb_l3(msg);
|
||||||
|
int p_drop;
|
||||||
|
|
||||||
|
if (imm_ass_cmd->msg_type != GSM48_MT_RR_IMM_ASS_REJ)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* IMMEDIATE ASSIGN REJECT */
|
||||||
|
|
||||||
|
p_drop = (bts->agch_queue.length - offs) * slope / max_len;
|
||||||
|
|
||||||
|
if ((random() & 0xffff) >= p_drop)
|
||||||
|
return;
|
||||||
|
|
||||||
|
llist_del(&msg->list);
|
||||||
|
bts->agch_queue.length--;
|
||||||
|
msgb_free(msg);
|
||||||
|
|
||||||
|
bts->agch_queue.dropped_msgs++;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bts_ccch_copy_msg(struct gsm_bts *bts, uint8_t *out_buf, struct gsm_time *gt,
|
||||||
|
int is_ag_res)
|
||||||
|
{
|
||||||
|
struct msgb *msg = NULL;
|
||||||
|
int rc = 0;
|
||||||
|
int is_empty = 1;
|
||||||
|
|
||||||
|
/* Do queue house keeping.
|
||||||
|
* This needs to be done every time a CCCH message is requested, since
|
||||||
|
* the queue max length is calculated based on the CCCH block rate and
|
||||||
|
* PCH messages also reduce the drain of the AGCH queue.
|
||||||
|
*/
|
||||||
|
compact_agch_queue(bts);
|
||||||
|
|
||||||
|
/* Check for paging messages first if this is PCH */
|
||||||
|
if (!is_ag_res)
|
||||||
|
rc = paging_gen_msg(bts->paging_state, out_buf, gt, &is_empty);
|
||||||
|
|
||||||
|
/* Check whether the block may be overwritten */
|
||||||
|
if (!is_empty)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
msg = bts_agch_dequeue(bts);
|
||||||
|
if (!msg)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
rate_ctr_inc2(bts->ctrs, BTS_CTR_AGCH_SENT);
|
||||||
|
|
||||||
|
/* Copy AGCH message */
|
||||||
|
memcpy(out_buf, msgb_l3(msg), msgb_l3len(msg));
|
||||||
|
rc = msgb_l3len(msg);
|
||||||
|
msgb_free(msg);
|
||||||
|
|
||||||
|
if (is_ag_res)
|
||||||
|
bts->agch_queue.agch_msgs++;
|
||||||
|
else
|
||||||
|
bts->agch_queue.pch_msgs++;
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bts_supports_cipher(struct gsm_bts *bts, int rsl_cipher)
|
||||||
|
{
|
||||||
|
int sup;
|
||||||
|
|
||||||
|
if (rsl_cipher < 1 || rsl_cipher > 8)
|
||||||
|
return -ENOTSUP;
|
||||||
|
|
||||||
|
/* No encryption is always supported */
|
||||||
|
if (rsl_cipher == 1)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
sup = (1 << (rsl_cipher - 2)) & bts->support.ciphers;
|
||||||
|
return sup > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int trx_ms_pwr_ctrl_is_osmo(struct gsm_bts_trx *trx)
|
||||||
|
{
|
||||||
|
return trx->ms_power_control == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct gsm_time *get_time(struct gsm_bts *bts)
|
||||||
|
{
|
||||||
|
return &bts->gsm_time;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bts_supports_cm(struct gsm_bts *bts, enum gsm_phys_chan_config pchan,
|
||||||
|
enum gsm48_chan_mode cm)
|
||||||
|
{
|
||||||
|
enum gsm_bts_features feature = _NUM_BTS_FEAT;
|
||||||
|
|
||||||
|
/* Before the requested pchan/cm combination can be checked, we need to
|
||||||
|
* convert it to a feature identifier we can check */
|
||||||
|
if (pchan == GSM_PCHAN_TCH_F) {
|
||||||
|
switch(cm) {
|
||||||
|
case GSM48_CMODE_SPEECH_V1:
|
||||||
|
feature = BTS_FEAT_SPEECH_F_V1;
|
||||||
|
break;
|
||||||
|
case GSM48_CMODE_SPEECH_EFR:
|
||||||
|
feature = BTS_FEAT_SPEECH_F_EFR;
|
||||||
|
break;
|
||||||
|
case GSM48_CMODE_SPEECH_AMR:
|
||||||
|
feature = BTS_FEAT_SPEECH_F_AMR;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* Invalid speech codec type => Not supported! */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} else if (pchan == GSM_PCHAN_TCH_H) {
|
||||||
|
switch(cm) {
|
||||||
|
case GSM48_CMODE_SPEECH_V1:
|
||||||
|
feature = BTS_FEAT_SPEECH_H_V1;
|
||||||
|
break;
|
||||||
|
case GSM48_CMODE_SPEECH_AMR:
|
||||||
|
feature = BTS_FEAT_SPEECH_H_AMR;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* Invalid speech codec type => Not supported! */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if the feature is supported by this BTS */
|
||||||
|
if (gsm_bts_has_feature(bts, feature))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
/* Control Interface for osmo-bts */
|
||||||
|
|
||||||
|
/* (C) 2014 by Harald Welte <laforge@gnumonks.org>
|
||||||
|
*
|
||||||
|
* 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 <stdint.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#include <osmocom/gsm/protocol/gsm_12_21.h>
|
||||||
|
#include <osmocom/ctrl/control_cmd.h>
|
||||||
|
|
||||||
|
#include <osmo-bts/logging.h>
|
||||||
|
#include <osmo-bts/gsm_data.h>
|
||||||
|
#include <osmo-bts/tx_power.h>
|
||||||
|
#include <osmo-bts/signal.h>
|
||||||
|
#include <osmo-bts/oml.h>
|
||||||
|
#include <osmo-bts/bts.h>
|
||||||
|
|
||||||
|
CTRL_CMD_DEFINE(therm_att, "thermal-attenuation");
|
||||||
|
static int get_therm_att(struct ctrl_cmd *cmd, void *data)
|
||||||
|
{
|
||||||
|
struct gsm_bts_trx *trx = cmd->node;
|
||||||
|
struct trx_power_params *tpp = &trx->power_params;
|
||||||
|
|
||||||
|
cmd->reply = talloc_asprintf(cmd, "%d", tpp->thermal_attenuation_mdB);
|
||||||
|
|
||||||
|
return CTRL_CMD_REPLY;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int set_therm_att(struct ctrl_cmd *cmd, void *data)
|
||||||
|
{
|
||||||
|
struct gsm_bts_trx *trx = cmd->node;
|
||||||
|
struct trx_power_params *tpp = &trx->power_params;
|
||||||
|
int val = atoi(cmd->value);
|
||||||
|
|
||||||
|
printf("set_therm_att(trx=%p, tpp=%p)\n", trx, tpp);
|
||||||
|
|
||||||
|
tpp->thermal_attenuation_mdB = val;
|
||||||
|
|
||||||
|
power_ramp_start(trx, tpp->p_total_cur_mdBm, 0);
|
||||||
|
|
||||||
|
return get_therm_att(cmd, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int verify_therm_att(struct ctrl_cmd *cmd, const char *value, void *data)
|
||||||
|
{
|
||||||
|
int val = atoi(value);
|
||||||
|
|
||||||
|
/* permit between 0 to 40 dB attenuation */
|
||||||
|
if (val < 0 || val > to_mdB(40))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
cmd->reply = "OK";
|
||||||
|
|
||||||
|
return CTRL_CMD_REPLY;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bts_ctrl_cmds_install(struct gsm_bts *bts)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
rc |= ctrl_cmd_install(CTRL_NODE_TRX, &cmd_therm_att);
|
||||||
|
rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_oml_alert);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
@@ -0,0 +1,115 @@
|
|||||||
|
/* Control Interface for osmo-bts */
|
||||||
|
|
||||||
|
/* (C) 2014 by Harald Welte <laforge@gnumonks.org>
|
||||||
|
*
|
||||||
|
* 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 <errno.h>
|
||||||
|
|
||||||
|
#include <osmocom/vty/command.h>
|
||||||
|
#include <osmocom/ctrl/control_if.h>
|
||||||
|
#include <osmocom/ctrl/ports.h>
|
||||||
|
#include <osmo-bts/bts_model.h>
|
||||||
|
#include <osmo-bts/logging.h>
|
||||||
|
#include <osmo-bts/gsm_data.h>
|
||||||
|
#include <osmo-bts/control_if.h>
|
||||||
|
|
||||||
|
extern vector ctrl_node_vec;
|
||||||
|
|
||||||
|
/*! \brief control interface lookup function for bsc/bts gsm_data
|
||||||
|
* \param[in] data Private data passed to controlif_setup()
|
||||||
|
* \param[in] vline Vector of the line holding the command string
|
||||||
|
* \param[out] node_type type (CTRL_NODE_) that was determined
|
||||||
|
* \param[out] node_data private dta of node that was determined
|
||||||
|
* \param i Current index into vline, up to which it is parsed
|
||||||
|
*/
|
||||||
|
static int bts_ctrl_node_lookup(void *data, vector vline, int *node_type,
|
||||||
|
void **node_data, int *i)
|
||||||
|
{
|
||||||
|
struct gsm_bts *bts = data;
|
||||||
|
struct gsm_bts_trx *trx = NULL;
|
||||||
|
struct gsm_bts_trx_ts *ts = NULL;
|
||||||
|
char *token = vector_slot(vline, *i);
|
||||||
|
long num;
|
||||||
|
|
||||||
|
/* TODO: We need to make sure that the following chars are digits
|
||||||
|
* and/or use strtol to check if number conversion was successful
|
||||||
|
* Right now something like net.bts_stats will not work */
|
||||||
|
if (!strcmp(token, "trx")) {
|
||||||
|
if (*node_type != CTRL_NODE_ROOT || !*node_data)
|
||||||
|
goto err_missing;
|
||||||
|
bts = *node_data;
|
||||||
|
(*i)++;
|
||||||
|
if (!ctrl_parse_get_num(vline, *i, &num))
|
||||||
|
goto err_index;
|
||||||
|
|
||||||
|
trx = gsm_bts_trx_num(bts, num);
|
||||||
|
if (!trx)
|
||||||
|
goto err_missing;
|
||||||
|
*node_data = trx;
|
||||||
|
*node_type = CTRL_NODE_TRX;
|
||||||
|
} else if (!strcmp(token, "ts")) {
|
||||||
|
if (*node_type != CTRL_NODE_TRX || !*node_data)
|
||||||
|
goto err_missing;
|
||||||
|
trx = *node_data;
|
||||||
|
(*i)++;
|
||||||
|
if (!ctrl_parse_get_num(vline, *i, &num))
|
||||||
|
goto err_index;
|
||||||
|
|
||||||
|
if ((num >= 0) && (num < TRX_NR_TS))
|
||||||
|
ts = &trx->ts[num];
|
||||||
|
if (!ts)
|
||||||
|
goto err_missing;
|
||||||
|
*node_data = ts;
|
||||||
|
*node_type = CTRL_NODE_TS;
|
||||||
|
} else
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
err_missing:
|
||||||
|
return -ENODEV;
|
||||||
|
err_index:
|
||||||
|
return -ERANGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ctrl_handle *bts_controlif_setup(struct gsm_bts *bts,
|
||||||
|
const char *bind_addr, uint16_t port)
|
||||||
|
{
|
||||||
|
struct ctrl_handle *hdl;
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
hdl = ctrl_interface_setup_dynip(bts, bind_addr, port,
|
||||||
|
bts_ctrl_node_lookup);
|
||||||
|
if (!hdl)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
rc = bts_ctrl_cmds_install(bts);
|
||||||
|
if (rc) {
|
||||||
|
/* FIXME: close control interface */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = bts_model_ctrl_cmds_install(bts);
|
||||||
|
if (rc) {
|
||||||
|
/* FIXME: cleanup generic control commands */
|
||||||
|
/* FIXME: close control interface */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return hdl;
|
||||||
|
}
|
||||||
@@ -0,0 +1,192 @@
|
|||||||
|
/* Cell Broadcast routines */
|
||||||
|
|
||||||
|
/* (C) 2014 by Harald Welte <laforge@gnumonks.org>
|
||||||
|
*
|
||||||
|
* 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 <errno.h>
|
||||||
|
|
||||||
|
#include <osmocom/core/linuxlist.h>
|
||||||
|
#include <osmocom/gsm/protocol/gsm_04_12.h>
|
||||||
|
|
||||||
|
#include <osmo-bts/bts.h>
|
||||||
|
#include <osmo-bts/cbch.h>
|
||||||
|
#include <osmo-bts/logging.h>
|
||||||
|
|
||||||
|
struct smscb_msg {
|
||||||
|
struct llist_head list; /* list in smscb_state.queue */
|
||||||
|
|
||||||
|
uint8_t msg[GSM412_MSG_LEN]; /* message buffer */
|
||||||
|
uint8_t next_seg; /* next segment number */
|
||||||
|
uint8_t num_segs; /* total number of segments */
|
||||||
|
};
|
||||||
|
|
||||||
|
static int get_smscb_null_block(uint8_t *out)
|
||||||
|
{
|
||||||
|
struct gsm412_block_type *block_type = (struct gsm412_block_type *) out;
|
||||||
|
|
||||||
|
block_type->spare = 0;
|
||||||
|
block_type->lpd = 1;
|
||||||
|
block_type->seq_nr = GSM412_SEQ_NULL_MSG;
|
||||||
|
block_type->lb = 0;
|
||||||
|
memset(out+1, GSM_MACBLOCK_PADDING, GSM412_BLOCK_LEN);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get the next block of the current CB message */
|
||||||
|
static int get_smscb_block(struct gsm_bts *bts, uint8_t *out)
|
||||||
|
{
|
||||||
|
int to_copy;
|
||||||
|
struct gsm412_block_type *block_type;
|
||||||
|
struct smscb_msg *msg = bts->smscb_state.cur_msg;
|
||||||
|
|
||||||
|
if (!msg) {
|
||||||
|
/* No message: Send NULL mesage */
|
||||||
|
return get_smscb_null_block(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
block_type = (struct gsm412_block_type *) out++;
|
||||||
|
|
||||||
|
/* LPD is always 01 */
|
||||||
|
block_type->spare = 0;
|
||||||
|
block_type->lpd = 1;
|
||||||
|
|
||||||
|
/* determine how much data to copy */
|
||||||
|
to_copy = GSM412_MSG_LEN - (msg->next_seg * GSM412_BLOCK_LEN);
|
||||||
|
if (to_copy > GSM412_BLOCK_LEN)
|
||||||
|
to_copy = GSM412_BLOCK_LEN;
|
||||||
|
|
||||||
|
/* copy data and increment index */
|
||||||
|
memcpy(out, &msg->msg[msg->next_seg * GSM412_BLOCK_LEN], to_copy);
|
||||||
|
|
||||||
|
/* set + increment sequence number */
|
||||||
|
block_type->seq_nr = msg->next_seg++;
|
||||||
|
|
||||||
|
/* determine if this is the last block */
|
||||||
|
if (block_type->seq_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
return block_type->lb;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const uint8_t last_block_rsl2um[4] = {
|
||||||
|
[RSL_CB_CMD_LASTBLOCK_4] = 4,
|
||||||
|
[RSL_CB_CMD_LASTBLOCK_1] = 1,
|
||||||
|
[RSL_CB_CMD_LASTBLOCK_2] = 2,
|
||||||
|
[RSL_CB_CMD_LASTBLOCK_3] = 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* 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)
|
||||||
|
{
|
||||||
|
struct smscb_msg *scm;
|
||||||
|
|
||||||
|
if (msg_len > sizeof(scm->msg)) {
|
||||||
|
LOGP(DLSMS, LOGL_ERROR,
|
||||||
|
"Cannot process SMSCB of %u bytes (max %zu)\n",
|
||||||
|
msg_len, sizeof(scm->msg));
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
scm = talloc_zero_size(bts, sizeof(*scm));
|
||||||
|
|
||||||
|
/* initialize entire message with default padding */
|
||||||
|
memset(scm->msg, GSM_MACBLOCK_PADDING, sizeof(scm->msg));
|
||||||
|
/* next segment is first segment */
|
||||||
|
scm->next_seg = 0;
|
||||||
|
|
||||||
|
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 */
|
||||||
|
break;
|
||||||
|
case RSL_CB_CMD_TYPE_DEFAULT:
|
||||||
|
/* use def_bcast, ignore command */
|
||||||
|
/* def_bcast == 0: normal mess */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
llist_add_tail(&scm->list, &bts->smscb_state.queue);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct smscb_msg *select_next_smscb(struct gsm_bts *bts)
|
||||||
|
{
|
||||||
|
struct smscb_msg *msg;
|
||||||
|
|
||||||
|
if (llist_empty(&bts->smscb_state.queue))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
msg = llist_entry(bts->smscb_state.queue.next,
|
||||||
|
struct smscb_msg, list);
|
||||||
|
|
||||||
|
llist_del(&msg->list);
|
||||||
|
|
||||||
|
return 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. */
|
||||||
|
int bts_cbch_get(struct gsm_bts *bts, uint8_t *outbuf, struct gsm_time *g_time)
|
||||||
|
{
|
||||||
|
uint32_t fn = gsm_gsmtime2fn(g_time);
|
||||||
|
/* According to 05.02 Section 6.5.4 */
|
||||||
|
uint32_t tb = (fn / 51) % 8;
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
* in which TB = 4, 5, 6 and 7 */
|
||||||
|
|
||||||
|
/* The SMSCB header shall be sent in the multiframe in which TB
|
||||||
|
* = 0 for the basic, and TB = 4 for the extended cell
|
||||||
|
* broadcast channel. */
|
||||||
|
|
||||||
|
switch (tb) {
|
||||||
|
case 0:
|
||||||
|
/* select a new SMSCB message */
|
||||||
|
bts->smscb_state.cur_msg = select_next_smscb(bts);
|
||||||
|
rc = get_smscb_block(bts, outbuf);
|
||||||
|
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);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
@@ -0,0 +1,477 @@
|
|||||||
|
/* DTX DL AMR FSM */
|
||||||
|
|
||||||
|
/* (C) 2016 by sysmocom s.f.m.c. GmbH
|
||||||
|
*
|
||||||
|
* 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/dtx_dl_amr_fsm.h>
|
||||||
|
#include <osmo-bts/logging.h>
|
||||||
|
|
||||||
|
void dtx_fsm_voice(struct osmo_fsm_inst *fi, uint32_t event, void *data)
|
||||||
|
{
|
||||||
|
switch (event) {
|
||||||
|
case E_VOICE:
|
||||||
|
case E_FACCH:
|
||||||
|
break;
|
||||||
|
case E_SID_F:
|
||||||
|
osmo_fsm_inst_state_chg(fi, ST_SID_F1, 0, 0);
|
||||||
|
break;
|
||||||
|
case E_SID_U:
|
||||||
|
osmo_fsm_inst_state_chg(fi, ST_U_NOINH, 0, 0);
|
||||||
|
break;
|
||||||
|
case E_INHIB:
|
||||||
|
osmo_fsm_inst_state_chg(fi, ST_F1_INH_V, 0, 0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOGP(DL1P, LOGL_ERROR, "Inexpected event %d\n", event);
|
||||||
|
OSMO_ASSERT(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dtx_fsm_sid_f1(struct osmo_fsm_inst *fi, uint32_t event, void *data)
|
||||||
|
{
|
||||||
|
switch (event) {
|
||||||
|
case E_SID_F:
|
||||||
|
/* FIXME: what shall we do if we get SID-FIRST _again_ (twice in a row)?
|
||||||
|
Was observed during testing, let's just ignore it for now */
|
||||||
|
break;
|
||||||
|
case E_SID_U:
|
||||||
|
osmo_fsm_inst_state_chg(fi, ST_U_NOINH, 0, 0);
|
||||||
|
break;
|
||||||
|
case E_FACCH:
|
||||||
|
osmo_fsm_inst_state_chg(fi, ST_F1_INH_F, 0, 0);
|
||||||
|
break;
|
||||||
|
case E_FIRST:
|
||||||
|
osmo_fsm_inst_state_chg(fi, ST_SID_F2, 0, 0);
|
||||||
|
break;
|
||||||
|
case E_ONSET:
|
||||||
|
osmo_fsm_inst_state_chg(fi, ST_ONSET_V, 0, 0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOGP(DL1P, LOGL_ERROR, "Unexpected event %d\n", event);
|
||||||
|
OSMO_ASSERT(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dtx_fsm_sid_f2(struct osmo_fsm_inst *fi, uint32_t event, void *data)
|
||||||
|
{
|
||||||
|
switch (event) {
|
||||||
|
case E_COMPL:
|
||||||
|
osmo_fsm_inst_state_chg(fi, ST_U_NOINH, 0, 0);
|
||||||
|
break;
|
||||||
|
case E_FACCH:
|
||||||
|
osmo_fsm_inst_state_chg(fi, ST_ONSET_F, 0, 0);
|
||||||
|
break;
|
||||||
|
case E_ONSET:
|
||||||
|
osmo_fsm_inst_state_chg(fi, ST_ONSET_V, 0, 0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOGP(DL1P, LOGL_ERROR, "Unexpected event %d\n", event);
|
||||||
|
OSMO_ASSERT(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dtx_fsm_f1_inh_v(struct osmo_fsm_inst *fi, uint32_t event, void *data)
|
||||||
|
{
|
||||||
|
switch (event) {
|
||||||
|
case E_COMPL:
|
||||||
|
osmo_fsm_inst_state_chg(fi, ST_F1_INH_V_REC, 0, 0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOGP(DL1P, LOGL_ERROR, "Unexpected event %d\n", event);
|
||||||
|
OSMO_ASSERT(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dtx_fsm_f1_inh_f(struct osmo_fsm_inst *fi, uint32_t event, void *data)
|
||||||
|
{
|
||||||
|
switch (event) {
|
||||||
|
case E_COMPL:
|
||||||
|
osmo_fsm_inst_state_chg(fi, ST_F1_INH_F_REC, 0, 0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOGP(DL1P, LOGL_ERROR, "Unexpected event %d\n", event);
|
||||||
|
OSMO_ASSERT(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dtx_fsm_u_inh_v(struct osmo_fsm_inst *fi, uint32_t event, void *data)
|
||||||
|
{
|
||||||
|
switch (event) {
|
||||||
|
case E_COMPL:
|
||||||
|
osmo_fsm_inst_state_chg(fi, ST_U_INH_V_REC, 0, 0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOGP(DL1P, LOGL_ERROR, "Unexpected event %d\n", event);
|
||||||
|
OSMO_ASSERT(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dtx_fsm_u_inh_f(struct osmo_fsm_inst *fi, uint32_t event, void *data)
|
||||||
|
{
|
||||||
|
switch (event) {
|
||||||
|
case E_COMPL:
|
||||||
|
osmo_fsm_inst_state_chg(fi, ST_U_INH_F_REC, 0, 0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOGP(DL1P, LOGL_ERROR, "Unexpected event %d\n", event);
|
||||||
|
OSMO_ASSERT(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dtx_fsm_f1_inh_v_rec(struct osmo_fsm_inst *fi, uint32_t event, void *data)
|
||||||
|
{
|
||||||
|
switch (event) {
|
||||||
|
case E_VOICE:
|
||||||
|
case E_COMPL:
|
||||||
|
osmo_fsm_inst_state_chg(fi, ST_VOICE, 0, 0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOGP(DL1P, LOGL_ERROR, "Unexpected event %d\n", event);
|
||||||
|
OSMO_ASSERT(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dtx_fsm_f1_inh_f_rec(struct osmo_fsm_inst *fi, uint32_t event, void *data)
|
||||||
|
{
|
||||||
|
switch (event) {
|
||||||
|
case E_FACCH:
|
||||||
|
case E_COMPL:
|
||||||
|
osmo_fsm_inst_state_chg(fi, ST_FACCH, 0, 0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOGP(DL1P, LOGL_ERROR, "Unexpected event %d\n", event);
|
||||||
|
OSMO_ASSERT(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dtx_fsm_u_inh_v_rec(struct osmo_fsm_inst *fi, uint32_t event, void *data)
|
||||||
|
{
|
||||||
|
switch (event) {
|
||||||
|
case E_VOICE:
|
||||||
|
case E_COMPL:
|
||||||
|
osmo_fsm_inst_state_chg(fi, ST_VOICE, 0, 0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOGP(DL1P, LOGL_ERROR, "Unexpected event %d\n", event);
|
||||||
|
OSMO_ASSERT(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dtx_fsm_u_inh_f_rec(struct osmo_fsm_inst *fi, uint32_t event, void *data)
|
||||||
|
{
|
||||||
|
switch (event) {
|
||||||
|
case E_FACCH:
|
||||||
|
case E_COMPL:
|
||||||
|
osmo_fsm_inst_state_chg(fi, ST_FACCH, 0, 0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOGP(DL1P, LOGL_ERROR, "Unexpected event %d\n", event);
|
||||||
|
OSMO_ASSERT(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dtx_fsm_u_noinh(struct osmo_fsm_inst *fi, uint32_t event, void *data)
|
||||||
|
{
|
||||||
|
switch (event) {
|
||||||
|
case E_FACCH:
|
||||||
|
osmo_fsm_inst_state_chg(fi, ST_ONSET_F, 0, 0);
|
||||||
|
break;
|
||||||
|
case E_VOICE:
|
||||||
|
osmo_fsm_inst_state_chg(fi, ST_VOICE, 0, 0);
|
||||||
|
break;
|
||||||
|
case E_COMPL:
|
||||||
|
osmo_fsm_inst_state_chg(fi, ST_SID_U, 0, 0);
|
||||||
|
break;
|
||||||
|
case E_SID_U:
|
||||||
|
case E_SID_F:
|
||||||
|
/* FIXME: what shall we do if we get SID-FIRST _after_ sending SID-UPDATE?
|
||||||
|
Was observed during testing, let's just ignore it for now */
|
||||||
|
break;
|
||||||
|
case E_ONSET:
|
||||||
|
osmo_fsm_inst_state_chg(fi, ST_ONSET_V, 0, 0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOGP(DL1P, LOGL_ERROR, "Unexpected event %d\n", event);
|
||||||
|
OSMO_ASSERT(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dtx_fsm_sid_upd(struct osmo_fsm_inst *fi, uint32_t event, void *data)
|
||||||
|
{
|
||||||
|
switch (event) {
|
||||||
|
case E_FACCH:
|
||||||
|
osmo_fsm_inst_state_chg(fi, ST_U_INH_F, 0, 0);
|
||||||
|
break;
|
||||||
|
case E_VOICE:
|
||||||
|
osmo_fsm_inst_state_chg(fi, ST_VOICE, 0, 0);
|
||||||
|
break;
|
||||||
|
case E_INHIB:
|
||||||
|
osmo_fsm_inst_state_chg(fi, ST_U_INH_V, 0, 0);
|
||||||
|
break;
|
||||||
|
case E_SID_U:
|
||||||
|
case E_SID_F:
|
||||||
|
osmo_fsm_inst_state_chg(fi, ST_U_NOINH, 0, 0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOGP(DL1P, LOGL_ERROR, "Unexpected event %d\n", event);
|
||||||
|
OSMO_ASSERT(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dtx_fsm_onset_v(struct osmo_fsm_inst *fi, uint32_t event, void *data)
|
||||||
|
{
|
||||||
|
switch (event) {
|
||||||
|
case E_COMPL:
|
||||||
|
osmo_fsm_inst_state_chg(fi, ST_ONSET_V_REC, 0, 0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOGP(DL1P, LOGL_ERROR, "Unexpected event %d\n", event);
|
||||||
|
OSMO_ASSERT(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dtx_fsm_onset_f(struct osmo_fsm_inst *fi, uint32_t event, void *data)
|
||||||
|
{
|
||||||
|
switch (event) {
|
||||||
|
case E_COMPL:
|
||||||
|
osmo_fsm_inst_state_chg(fi, ST_ONSET_F_REC, 0, 0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOGP(DL1P, LOGL_ERROR, "Unexpected event %d\n", event);
|
||||||
|
OSMO_ASSERT(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dtx_fsm_onset_v_rec(struct osmo_fsm_inst *fi, uint32_t event, void *data)
|
||||||
|
{
|
||||||
|
switch (event) {
|
||||||
|
case E_COMPL:
|
||||||
|
osmo_fsm_inst_state_chg(fi, ST_VOICE, 0, 0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOGP(DL1P, LOGL_ERROR, "Unexpected event %d\n", event);
|
||||||
|
OSMO_ASSERT(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dtx_fsm_onset_f_rec(struct osmo_fsm_inst *fi, uint32_t event, void *data)
|
||||||
|
{
|
||||||
|
switch (event) {
|
||||||
|
case E_COMPL:
|
||||||
|
osmo_fsm_inst_state_chg(fi, ST_FACCH, 0, 0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOGP(DL1P, LOGL_ERROR, "Unexpected event %d\n", event);
|
||||||
|
OSMO_ASSERT(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dtx_fsm_facch(struct osmo_fsm_inst *fi, uint32_t event, void *data)
|
||||||
|
{
|
||||||
|
switch (event) {
|
||||||
|
case E_SID_U:
|
||||||
|
case E_SID_F:
|
||||||
|
case E_FACCH:
|
||||||
|
break;
|
||||||
|
case E_VOICE:
|
||||||
|
osmo_fsm_inst_state_chg(fi, ST_VOICE, 0, 0);
|
||||||
|
break;
|
||||||
|
case E_COMPL:
|
||||||
|
osmo_fsm_inst_state_chg(fi, ST_SID_F1, 0, 0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOGP(DL1P, LOGL_ERROR, "Unexpected event %d\n", event);
|
||||||
|
OSMO_ASSERT(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct osmo_fsm_state dtx_dl_amr_fsm_states[] = {
|
||||||
|
/* default state for non-DTX and DTX when SPEECH is in progress */
|
||||||
|
[ST_VOICE] = {
|
||||||
|
.in_event_mask = X(E_SID_F) | X(E_SID_U) | X(E_VOICE) | X(E_FACCH) | X(E_INHIB),
|
||||||
|
.out_state_mask = X(ST_SID_F1) | X(ST_U_NOINH) | X(ST_F1_INH_V),
|
||||||
|
.name = "Voice",
|
||||||
|
.action = dtx_fsm_voice,
|
||||||
|
},
|
||||||
|
/* SID-FIRST or SID-FIRST-P1 in case of AMR HR:
|
||||||
|
start of silence period (might be interrupted in case of AMR HR) */
|
||||||
|
[ST_SID_F1]= {
|
||||||
|
.in_event_mask = X(E_SID_F) | X(E_SID_U) | X(E_FACCH) | X(E_FIRST) | X(E_ONSET),
|
||||||
|
.out_state_mask = X(ST_U_NOINH) | X(ST_ONSET_F) | X(ST_SID_F2) | X(ST_ONSET_V),
|
||||||
|
.name = "SID-FIRST (P1)",
|
||||||
|
.action = dtx_fsm_sid_f1,
|
||||||
|
},
|
||||||
|
/* SID-FIRST P2 (only for AMR HR):
|
||||||
|
actual start of silence period in case of AMR HR */
|
||||||
|
[ST_SID_F2]= {
|
||||||
|
.in_event_mask = X(E_COMPL) | X(E_FACCH) | X(E_ONSET),
|
||||||
|
.out_state_mask = X(ST_U_NOINH) | X(ST_ONSET_F) | X(ST_ONSET_V),
|
||||||
|
.name = "SID-FIRST (P2)",
|
||||||
|
.action = dtx_fsm_sid_f2,
|
||||||
|
},
|
||||||
|
/* SID-FIRST Inhibited: incoming SPEECH (only for AMR HR) */
|
||||||
|
[ST_F1_INH_V]= {
|
||||||
|
.in_event_mask = X(E_COMPL),
|
||||||
|
.out_state_mask = X(ST_F1_INH_V_REC),
|
||||||
|
.name = "SID-FIRST (Inh, SPEECH)",
|
||||||
|
.action = dtx_fsm_f1_inh_v,
|
||||||
|
},
|
||||||
|
/* SID-FIRST Inhibited: incoming FACCH frame (only for AMR HR) */
|
||||||
|
[ST_F1_INH_F]= {
|
||||||
|
.in_event_mask = X(E_COMPL),
|
||||||
|
.out_state_mask = X(ST_F1_INH_F_REC),
|
||||||
|
.name = "SID-FIRST (Inh, FACCH)",
|
||||||
|
.action = dtx_fsm_f1_inh_f,
|
||||||
|
},
|
||||||
|
/* SID-UPDATE Inhibited: incoming SPEECH (only for AMR HR) */
|
||||||
|
[ST_U_INH_V]= {
|
||||||
|
.in_event_mask = X(E_COMPL),
|
||||||
|
.out_state_mask = X(ST_U_INH_V_REC),
|
||||||
|
.name = "SID-UPDATE (Inh, SPEECH)",
|
||||||
|
.action = dtx_fsm_u_inh_v,
|
||||||
|
},
|
||||||
|
/* SID-UPDATE Inhibited: incoming FACCH frame (only for AMR HR) */
|
||||||
|
[ST_U_INH_F]= {
|
||||||
|
.in_event_mask = X(E_COMPL),
|
||||||
|
.out_state_mask = X(ST_U_INH_F_REC),
|
||||||
|
.name = "SID-UPDATE (Inh, FACCH)",
|
||||||
|
.action = dtx_fsm_u_inh_f,
|
||||||
|
},
|
||||||
|
/* SID-UPDATE: Inhibited not allowed (only for AMR HR) */
|
||||||
|
[ST_U_NOINH]= {
|
||||||
|
.in_event_mask = X(E_FACCH) | X(E_VOICE) | X(E_COMPL) | X(E_SID_U) | X(E_SID_F) | X(E_ONSET),
|
||||||
|
.out_state_mask = X(ST_ONSET_F) | X(ST_VOICE) | X(ST_SID_U) | X(ST_ONSET_V),
|
||||||
|
.name = "SID-UPDATE (NoInh)",
|
||||||
|
.action = dtx_fsm_u_noinh,
|
||||||
|
},
|
||||||
|
/* SID-FIRST Inhibition recursion in progress:
|
||||||
|
Inhibit itself was already sent, now have to send the voice that caused it */
|
||||||
|
[ST_F1_INH_V_REC]= {
|
||||||
|
.in_event_mask = X(E_COMPL) | X(E_VOICE),
|
||||||
|
.out_state_mask = X(ST_VOICE),
|
||||||
|
.name = "SID-FIRST (Inh, SPEECH, Rec)",
|
||||||
|
.action = dtx_fsm_f1_inh_v_rec,
|
||||||
|
},
|
||||||
|
/* SID-FIRST Inhibition recursion in progress:
|
||||||
|
Inhibit itself was already sent, now have to send the data that caused it */
|
||||||
|
[ST_F1_INH_F_REC]= {
|
||||||
|
.in_event_mask = X(E_COMPL) | X(E_FACCH),
|
||||||
|
.out_state_mask = X(ST_FACCH),
|
||||||
|
.name = "SID-FIRST (Inh, FACCH, Rec)",
|
||||||
|
.action = dtx_fsm_f1_inh_f_rec,
|
||||||
|
},
|
||||||
|
/* SID-UPDATE Inhibition recursion in progress:
|
||||||
|
Inhibit itself was already sent, now have to send the voice that caused it */
|
||||||
|
[ST_U_INH_V_REC]= {
|
||||||
|
.in_event_mask = X(E_COMPL) | X(E_VOICE),
|
||||||
|
.out_state_mask = X(ST_VOICE),
|
||||||
|
.name = "SID-UPDATE (Inh, SPEECH, Rec)",
|
||||||
|
.action = dtx_fsm_u_inh_v_rec,
|
||||||
|
},
|
||||||
|
/* SID-UPDATE Inhibition recursion in progress:
|
||||||
|
Inhibit itself was already sent, now have to send the data that caused it */
|
||||||
|
[ST_U_INH_F_REC]= {
|
||||||
|
.in_event_mask = X(E_COMPL) | X(E_FACCH),
|
||||||
|
.out_state_mask = X(ST_FACCH),
|
||||||
|
.name = "SID-UPDATE (Inh, FACCH, Rec)",
|
||||||
|
.action = dtx_fsm_u_inh_f_rec,
|
||||||
|
},
|
||||||
|
/* Silence period with periodic comfort noise data updates */
|
||||||
|
[ST_SID_U]= {
|
||||||
|
.in_event_mask = X(E_FACCH) | X(E_VOICE) | X(E_INHIB) | X(E_SID_U) | X(E_SID_F),
|
||||||
|
.out_state_mask = X(ST_ONSET_F) | X(ST_VOICE) | X(ST_U_INH_V) | X(ST_U_INH_F) | X(ST_U_NOINH),
|
||||||
|
.name = "SID-UPDATE (AMR/HR)",
|
||||||
|
.action = dtx_fsm_sid_upd,
|
||||||
|
},
|
||||||
|
/* ONSET - end of silent period due to incoming SPEECH frame */
|
||||||
|
[ST_ONSET_V]= {
|
||||||
|
.in_event_mask = X(E_COMPL),
|
||||||
|
.out_state_mask = X(ST_ONSET_V_REC),
|
||||||
|
.name = "ONSET (SPEECH)",
|
||||||
|
.action = dtx_fsm_onset_v,
|
||||||
|
},
|
||||||
|
/* ONSET - end of silent period due to incoming FACCH frame */
|
||||||
|
[ST_ONSET_F]= {
|
||||||
|
.in_event_mask = X(E_COMPL),
|
||||||
|
.out_state_mask = X(ST_ONSET_F_REC),
|
||||||
|
.name = "ONSET (FACCH)",
|
||||||
|
.action = dtx_fsm_onset_f,
|
||||||
|
},
|
||||||
|
/* ONSET recursion in progress:
|
||||||
|
ONSET itself was already sent, now have to send the voice that caused it */
|
||||||
|
[ST_ONSET_V_REC]= {
|
||||||
|
.in_event_mask = X(E_COMPL),
|
||||||
|
.out_state_mask = X(ST_VOICE),
|
||||||
|
.name = "ONSET (SPEECH, Rec)",
|
||||||
|
.action = dtx_fsm_onset_v_rec,
|
||||||
|
},
|
||||||
|
/* ONSET recursion in progress:
|
||||||
|
ONSET itself was already sent, now have to send the data that caused it */
|
||||||
|
[ST_ONSET_F_REC]= {
|
||||||
|
.in_event_mask = X(E_COMPL),
|
||||||
|
.out_state_mask = X(ST_FACCH),
|
||||||
|
.name = "ONSET (FACCH, Rec)",
|
||||||
|
.action = dtx_fsm_onset_f_rec,
|
||||||
|
},
|
||||||
|
/* FACCH sending state */
|
||||||
|
[ST_FACCH]= {
|
||||||
|
.in_event_mask = X(E_FACCH) | X(E_VOICE) | X(E_COMPL) | X(E_SID_U) | X(E_SID_F),
|
||||||
|
.out_state_mask = X(ST_VOICE) | X(ST_SID_F1),
|
||||||
|
.name = "FACCH",
|
||||||
|
.action = dtx_fsm_facch,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct value_string dtx_dl_amr_fsm_event_names[] = {
|
||||||
|
{ E_VOICE, "Voice" },
|
||||||
|
{ E_ONSET, "ONSET" },
|
||||||
|
{ E_FACCH, "FACCH" },
|
||||||
|
{ E_COMPL, "Complete" },
|
||||||
|
{ E_FIRST, "FIRST P1->P2" },
|
||||||
|
{ E_INHIB, "Inhibit" },
|
||||||
|
{ E_SID_F, "SID-FIRST" },
|
||||||
|
{ E_SID_U, "SID-UPDATE" },
|
||||||
|
{ 0, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct osmo_fsm dtx_dl_amr_fsm = {
|
||||||
|
.name = "DTX_DL_AMR_FSM",
|
||||||
|
.states = dtx_dl_amr_fsm_states,
|
||||||
|
.num_states = ARRAY_SIZE(dtx_dl_amr_fsm_states),
|
||||||
|
.event_names = dtx_dl_amr_fsm_event_names,
|
||||||
|
.log_subsys = DL1C,
|
||||||
|
};
|
||||||
@@ -0,0 +1,829 @@
|
|||||||
|
/* (C) 2008-2010 by Harald Welte <laforge@gnumonks.org>
|
||||||
|
*
|
||||||
|
* 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 Affero 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 <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#include <netinet/in.h>
|
||||||
|
|
||||||
|
#include <osmocom/core/linuxlist.h>
|
||||||
|
#include <osmocom/core/talloc.h>
|
||||||
|
#include <osmocom/gsm/gsm_utils.h>
|
||||||
|
#include <osmocom/gsm/abis_nm.h>
|
||||||
|
#include <osmocom/core/statistics.h>
|
||||||
|
|
||||||
|
#include <osmo-bts/gsm_data.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gsm_mo_init(struct gsm_abis_mo *mo, struct gsm_bts *bts,
|
||||||
|
uint8_t obj_class, uint8_t p1, uint8_t p2, uint8_t p3)
|
||||||
|
{
|
||||||
|
mo->bts = bts;
|
||||||
|
mo->obj_class = obj_class;
|
||||||
|
mo->obj_inst.bts_nr = p1;
|
||||||
|
mo->obj_inst.trx_nr = p2;
|
||||||
|
mo->obj_inst.ts_nr = p3;
|
||||||
|
gsm_abis_mo_reset(mo);
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct value_string bts_attribute_names[] = {
|
||||||
|
OSMO_VALUE_STRING(BTS_TYPE_VARIANT),
|
||||||
|
OSMO_VALUE_STRING(BTS_SUB_MODEL),
|
||||||
|
OSMO_VALUE_STRING(TRX_PHY_VERSION),
|
||||||
|
{ 0, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
enum bts_attribute str2btsattr(const char *s)
|
||||||
|
{
|
||||||
|
return get_string_value(bts_attribute_names, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *btsatttr2str(enum bts_attribute v)
|
||||||
|
{
|
||||||
|
return get_value_string(bts_attribute_names, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct value_string osmo_bts_variant_names[_NUM_BTS_VARIANT + 1] = {
|
||||||
|
{ BTS_UNKNOWN, "unknown" },
|
||||||
|
{ BTS_OSMO_LITECELL15, "osmo-bts-lc15" },
|
||||||
|
{ BTS_OSMO_OCTPHY, "osmo-bts-octphy" },
|
||||||
|
{ BTS_OSMO_SYSMO, "osmo-bts-sysmo" },
|
||||||
|
{ BTS_OSMO_TRX, "omso-bts-trx" },
|
||||||
|
{ BTS_OSMO_VIRTUAL, "omso-bts-virtual" },
|
||||||
|
{ BTS_OSMO_OMLDUMMY, "omso-bts-omldummy" },
|
||||||
|
{ 0, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
enum gsm_bts_type_variant str2btsvariant(const char *arg)
|
||||||
|
{
|
||||||
|
return get_string_value(osmo_bts_variant_names, arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *btsvariant2str(enum gsm_bts_type_variant v)
|
||||||
|
{
|
||||||
|
return get_value_string(osmo_bts_variant_names, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct value_string gsm_bts_features_descs[] = {
|
||||||
|
{ BTS_FEAT_HSCSD, "HSCSD" },
|
||||||
|
{ BTS_FEAT_GPRS, "GPRS" },
|
||||||
|
{ BTS_FEAT_EGPRS, "EGPRS" },
|
||||||
|
{ BTS_FEAT_ECSD, "ECSD" },
|
||||||
|
{ BTS_FEAT_HOPPING, "Frequency Hopping" },
|
||||||
|
{ BTS_FEAT_MULTI_TSC, "Multi-TSC" },
|
||||||
|
{ BTS_FEAT_OML_ALERTS, "OML Alerts" },
|
||||||
|
{ BTS_FEAT_AGCH_PCH_PROP, "AGCH/PCH proportional allocation" },
|
||||||
|
{ BTS_FEAT_CBCH, "CBCH" },
|
||||||
|
{ BTS_FEAT_SPEECH_F_V1, "Fullrate speech V1" },
|
||||||
|
{ BTS_FEAT_SPEECH_H_V1, "Halfrate speech V1" },
|
||||||
|
{ BTS_FEAT_SPEECH_F_EFR, "Fullrate speech EFR" },
|
||||||
|
{ BTS_FEAT_SPEECH_F_AMR, "Fullrate speech AMR" },
|
||||||
|
{ BTS_FEAT_SPEECH_H_AMR, "Halfrate speech AMR" },
|
||||||
|
{ 0, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct value_string gsm_chreq_descs[] = {
|
||||||
|
{ GSM_CHREQ_REASON_EMERG, "emergency call" },
|
||||||
|
{ GSM_CHREQ_REASON_PAG, "answer to paging" },
|
||||||
|
{ GSM_CHREQ_REASON_CALL, "call re-establishment" },
|
||||||
|
{ GSM_CHREQ_REASON_LOCATION_UPD,"Location updating" },
|
||||||
|
{ GSM_CHREQ_REASON_PDCH, "one phase packet access" },
|
||||||
|
{ GSM_CHREQ_REASON_OTHER, "other" },
|
||||||
|
{ 0, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct value_string gsm_pchant_names[13] = {
|
||||||
|
{ GSM_PCHAN_NONE, "NONE" },
|
||||||
|
{ GSM_PCHAN_CCCH, "CCCH" },
|
||||||
|
{ GSM_PCHAN_CCCH_SDCCH4,"CCCH+SDCCH4" },
|
||||||
|
{ GSM_PCHAN_TCH_F, "TCH/F" },
|
||||||
|
{ GSM_PCHAN_TCH_H, "TCH/H" },
|
||||||
|
{ GSM_PCHAN_SDCCH8_SACCH8C, "SDCCH8" },
|
||||||
|
{ GSM_PCHAN_PDCH, "PDCH" },
|
||||||
|
{ GSM_PCHAN_TCH_F_PDCH, "TCH/F_PDCH" },
|
||||||
|
{ GSM_PCHAN_UNKNOWN, "UNKNOWN" },
|
||||||
|
{ GSM_PCHAN_CCCH_SDCCH4_CBCH, "CCCH+SDCCH4+CBCH" },
|
||||||
|
{ GSM_PCHAN_SDCCH8_SACCH8C_CBCH, "SDCCH8+CBCH" },
|
||||||
|
{ GSM_PCHAN_TCH_F_TCH_H_PDCH, "TCH/F_TCH/H_PDCH" },
|
||||||
|
{ 0, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct value_string gsm_pchant_descs[13] = {
|
||||||
|
{ GSM_PCHAN_NONE, "Physical Channel not configured" },
|
||||||
|
{ GSM_PCHAN_CCCH, "FCCH + SCH + BCCH + CCCH (Comb. IV)" },
|
||||||
|
{ GSM_PCHAN_CCCH_SDCCH4,
|
||||||
|
"FCCH + SCH + BCCH + CCCH + 4 SDCCH + 2 SACCH (Comb. V)" },
|
||||||
|
{ GSM_PCHAN_TCH_F, "TCH/F + FACCH/F + SACCH (Comb. I)" },
|
||||||
|
{ GSM_PCHAN_TCH_H, "2 TCH/H + 2 FACCH/H + 2 SACCH (Comb. II)" },
|
||||||
|
{ GSM_PCHAN_SDCCH8_SACCH8C, "8 SDCCH + 4 SACCH (Comb. VII)" },
|
||||||
|
{ GSM_PCHAN_PDCH, "Packet Data Channel for GPRS/EDGE" },
|
||||||
|
{ GSM_PCHAN_TCH_F_PDCH, "Dynamic TCH/F or GPRS PDCH" },
|
||||||
|
{ GSM_PCHAN_UNKNOWN, "Unknown / Unsupported channel combination" },
|
||||||
|
{ GSM_PCHAN_CCCH_SDCCH4_CBCH, "FCCH + SCH + BCCH + CCCH + CBCH + 3 SDCCH + 2 SACCH (Comb. V)" },
|
||||||
|
{ GSM_PCHAN_SDCCH8_SACCH8C_CBCH, "7 SDCCH + 4 SACCH + CBCH (Comb. VII)" },
|
||||||
|
{ GSM_PCHAN_TCH_F_TCH_H_PDCH, "Dynamic TCH/F or TCH/H or GPRS PDCH" },
|
||||||
|
{ 0, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
const char *gsm_pchan_name(enum gsm_phys_chan_config c)
|
||||||
|
{
|
||||||
|
return get_value_string(gsm_pchant_names, c);
|
||||||
|
}
|
||||||
|
|
||||||
|
enum gsm_phys_chan_config gsm_pchan_parse(const char *name)
|
||||||
|
{
|
||||||
|
return get_string_value(gsm_pchant_names, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: move to libosmocore, next to gsm_chan_t_names? */
|
||||||
|
const char *gsm_lchant_name(enum gsm_chan_t c)
|
||||||
|
{
|
||||||
|
return get_value_string(gsm_chan_t_names, c);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct value_string lchan_s_names[] = {
|
||||||
|
{ LCHAN_S_NONE, "NONE" },
|
||||||
|
{ LCHAN_S_ACT_REQ, "ACTIVATION REQUESTED" },
|
||||||
|
{ LCHAN_S_ACTIVE, "ACTIVE" },
|
||||||
|
{ LCHAN_S_INACTIVE, "INACTIVE" },
|
||||||
|
{ LCHAN_S_REL_REQ, "RELEASE REQUESTED" },
|
||||||
|
{ LCHAN_S_REL_ERR, "RELEASE DUE ERROR" },
|
||||||
|
{ LCHAN_S_BROKEN, "BROKEN UNUSABLE" },
|
||||||
|
{ 0, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
const char *gsm_lchans_name(enum gsm_lchan_state s)
|
||||||
|
{
|
||||||
|
return get_value_string(lchan_s_names, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct value_string chreq_names[] = {
|
||||||
|
{ GSM_CHREQ_REASON_EMERG, "EMERGENCY" },
|
||||||
|
{ GSM_CHREQ_REASON_PAG, "PAGING" },
|
||||||
|
{ GSM_CHREQ_REASON_CALL, "CALL" },
|
||||||
|
{ GSM_CHREQ_REASON_LOCATION_UPD,"LOCATION_UPDATE" },
|
||||||
|
{ GSM_CHREQ_REASON_OTHER, "OTHER" },
|
||||||
|
{ 0, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
const char *gsm_chreq_name(enum gsm_chreq_reason_t c)
|
||||||
|
{
|
||||||
|
return get_value_string(chreq_names, c);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct gsm_bts *gsm_bts_num(struct gsm_network *net, int num)
|
||||||
|
{
|
||||||
|
struct gsm_bts *bts;
|
||||||
|
|
||||||
|
if (num >= net->num_bts)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
llist_for_each_entry(bts, &net->bts_list, list) {
|
||||||
|
if (bts->nr == num)
|
||||||
|
return bts;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct gsm_bts_trx *gsm_bts_trx_alloc(struct gsm_bts *bts)
|
||||||
|
{
|
||||||
|
struct gsm_bts_trx *trx = talloc_zero(bts, struct gsm_bts_trx);
|
||||||
|
int k;
|
||||||
|
|
||||||
|
if (!trx)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
for (k = 0; k < TRX_NR_TS; k++) {
|
||||||
|
struct gsm_bts_trx_ts *ts = &trx->ts[k];
|
||||||
|
int l;
|
||||||
|
|
||||||
|
ts->trx = trx;
|
||||||
|
ts->nr = k;
|
||||||
|
ts->pchan = GSM_PCHAN_NONE;
|
||||||
|
ts->dyn.pchan_is = GSM_PCHAN_NONE;
|
||||||
|
ts->dyn.pchan_want = GSM_PCHAN_NONE;
|
||||||
|
ts->tsc = -1;
|
||||||
|
|
||||||
|
gsm_mo_init(&ts->mo, bts, NM_OC_CHANNEL,
|
||||||
|
bts->nr, trx->nr, ts->nr);
|
||||||
|
|
||||||
|
ts->hopping.arfcns.data_len = sizeof(ts->hopping.arfcns_data);
|
||||||
|
ts->hopping.arfcns.data = ts->hopping.arfcns_data;
|
||||||
|
ts->hopping.ma.data_len = sizeof(ts->hopping.ma_data);
|
||||||
|
ts->hopping.ma.data = ts->hopping.ma_data;
|
||||||
|
|
||||||
|
for (l = 0; l < TS_MAX_LCHAN; l++) {
|
||||||
|
struct gsm_lchan *lchan;
|
||||||
|
char *name;
|
||||||
|
lchan = &ts->lchan[l];
|
||||||
|
|
||||||
|
lchan->ts = ts;
|
||||||
|
lchan->nr = l;
|
||||||
|
lchan->type = GSM_LCHAN_NONE;
|
||||||
|
|
||||||
|
name = gsm_lchan_name_compute(lchan);
|
||||||
|
lchan->name = talloc_strdup(trx, name);
|
||||||
|
INIT_LLIST_HEAD(&lchan->sapi_cmds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (trx->nr != 0)
|
||||||
|
trx->nominal_power = bts->c0->nominal_power;
|
||||||
|
|
||||||
|
llist_add_tail(&trx->list, &bts->trx_list);
|
||||||
|
|
||||||
|
return trx;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static const uint8_t bts_nse_timer_default[] = { 3, 3, 3, 3, 30, 3, 10 };
|
||||||
|
static const uint8_t bts_cell_timer_default[] =
|
||||||
|
{ 3, 3, 3, 3, 3, 10, 3, 10, 3, 10, 3 };
|
||||||
|
static const struct gprs_rlc_cfg rlc_cfg_default = {
|
||||||
|
.parameter = {
|
||||||
|
[RLC_T3142] = 20,
|
||||||
|
[RLC_T3169] = 5,
|
||||||
|
[RLC_T3191] = 5,
|
||||||
|
[RLC_T3193] = 160, /* 10ms */
|
||||||
|
[RLC_T3195] = 5,
|
||||||
|
[RLC_N3101] = 10,
|
||||||
|
[RLC_N3103] = 4,
|
||||||
|
[RLC_N3105] = 8,
|
||||||
|
[CV_COUNTDOWN] = 15,
|
||||||
|
[T_DL_TBF_EXT] = 250 * 10, /* ms */
|
||||||
|
[T_UL_TBF_EXT] = 250 * 10, /* ms */
|
||||||
|
},
|
||||||
|
.paging = {
|
||||||
|
.repeat_time = 5 * 50, /* ms */
|
||||||
|
.repeat_count = 3,
|
||||||
|
},
|
||||||
|
.cs_mask = 0x1fff,
|
||||||
|
.initial_cs = 2,
|
||||||
|
.initial_mcs = 6,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct gsm_bts *gsm_bts_alloc(void *ctx, uint8_t bts_num)
|
||||||
|
{
|
||||||
|
struct gsm_bts *bts = talloc_zero(ctx, struct gsm_bts);
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!bts)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
bts->nr = bts_num;
|
||||||
|
bts->num_trx = 0;
|
||||||
|
INIT_LLIST_HEAD(&bts->trx_list);
|
||||||
|
bts->ms_max_power = 15; /* dBm */
|
||||||
|
|
||||||
|
gsm_mo_init(&bts->mo, bts, NM_OC_BTS,
|
||||||
|
bts->nr, 0xff, 0xff);
|
||||||
|
gsm_mo_init(&bts->site_mgr.mo, bts, NM_OC_SITE_MANAGER,
|
||||||
|
0xff, 0xff, 0xff);
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(bts->gprs.nsvc); i++) {
|
||||||
|
bts->gprs.nsvc[i].bts = bts;
|
||||||
|
bts->gprs.nsvc[i].id = i;
|
||||||
|
gsm_mo_init(&bts->gprs.nsvc[i].mo, bts, NM_OC_GPRS_NSVC,
|
||||||
|
bts->nr, i, 0xff);
|
||||||
|
}
|
||||||
|
memcpy(&bts->gprs.nse.timer, bts_nse_timer_default,
|
||||||
|
sizeof(bts->gprs.nse.timer));
|
||||||
|
gsm_mo_init(&bts->gprs.nse.mo, bts, NM_OC_GPRS_NSE,
|
||||||
|
bts->nr, 0xff, 0xff);
|
||||||
|
memcpy(&bts->gprs.cell.timer, bts_cell_timer_default,
|
||||||
|
sizeof(bts->gprs.cell.timer));
|
||||||
|
gsm_mo_init(&bts->gprs.cell.mo, bts, NM_OC_GPRS_CELL,
|
||||||
|
bts->nr, 0xff, 0xff);
|
||||||
|
memcpy(&bts->gprs.cell.rlc_cfg, &rlc_cfg_default,
|
||||||
|
sizeof(bts->gprs.cell.rlc_cfg));
|
||||||
|
|
||||||
|
/* create our primary TRX */
|
||||||
|
bts->c0 = gsm_bts_trx_alloc(bts);
|
||||||
|
if (!bts->c0) {
|
||||||
|
talloc_free(bts);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
bts->c0->ts[0].pchan = GSM_PCHAN_CCCH_SDCCH4;
|
||||||
|
|
||||||
|
bts->rach_b_thresh = -1;
|
||||||
|
bts->rach_ldavg_slots = -1;
|
||||||
|
bts->features.data = &bts->_features_data[0];
|
||||||
|
bts->features.data_len = sizeof(bts->_features_data);
|
||||||
|
|
||||||
|
/* si handling */
|
||||||
|
bts->bcch_change_mark = 1;
|
||||||
|
|
||||||
|
return bts;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* reset the state of all MO in the BTS */
|
||||||
|
void gsm_bts_mo_reset(struct gsm_bts *bts)
|
||||||
|
{
|
||||||
|
struct gsm_bts_trx *trx;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
gsm_abis_mo_reset(&bts->mo);
|
||||||
|
gsm_abis_mo_reset(&bts->site_mgr.mo);
|
||||||
|
for (i = 0; i < ARRAY_SIZE(bts->gprs.nsvc); i++)
|
||||||
|
gsm_abis_mo_reset(&bts->gprs.nsvc[i].mo);
|
||||||
|
gsm_abis_mo_reset(&bts->gprs.nse.mo);
|
||||||
|
gsm_abis_mo_reset(&bts->gprs.cell.mo);
|
||||||
|
|
||||||
|
llist_for_each_entry(trx, &bts->trx_list, list) {
|
||||||
|
gsm_abis_mo_reset(&trx->mo);
|
||||||
|
gsm_abis_mo_reset(&trx->bb_transc.mo);
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(trx->ts); i++) {
|
||||||
|
struct gsm_bts_trx_ts *ts = &trx->ts[i];
|
||||||
|
gsm_abis_mo_reset(&ts->mo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct gsm_bts_trx *gsm_bts_trx_num(const struct gsm_bts *bts, int num)
|
||||||
|
{
|
||||||
|
struct gsm_bts_trx *trx;
|
||||||
|
|
||||||
|
if (num >= bts->num_trx)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
llist_for_each_entry(trx, &bts->trx_list, list) {
|
||||||
|
if (trx->nr == num)
|
||||||
|
return trx;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char ts2str[255];
|
||||||
|
|
||||||
|
char *gsm_trx_name(const struct gsm_bts_trx *trx)
|
||||||
|
{
|
||||||
|
if (!trx)
|
||||||
|
snprintf(ts2str, sizeof(ts2str), "(trx=NULL)");
|
||||||
|
else
|
||||||
|
snprintf(ts2str, sizeof(ts2str), "(bts=%d,trx=%d)",
|
||||||
|
trx->bts->nr, trx->nr);
|
||||||
|
|
||||||
|
return ts2str;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char *gsm_ts_name(const struct gsm_bts_trx_ts *ts)
|
||||||
|
{
|
||||||
|
snprintf(ts2str, sizeof(ts2str), "(bts=%d,trx=%d,ts=%d)",
|
||||||
|
ts->trx->bts->nr, ts->trx->nr, ts->nr);
|
||||||
|
|
||||||
|
return ts2str;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Log timeslot number with full pchan information */
|
||||||
|
char *gsm_ts_and_pchan_name(const struct gsm_bts_trx_ts *ts)
|
||||||
|
{
|
||||||
|
switch (ts->pchan) {
|
||||||
|
case GSM_PCHAN_TCH_F_TCH_H_PDCH:
|
||||||
|
if (ts->dyn.pchan_is == ts->dyn.pchan_want)
|
||||||
|
snprintf(ts2str, sizeof(ts2str),
|
||||||
|
"(bts=%d,trx=%d,ts=%d,pchan=%s as %s)",
|
||||||
|
ts->trx->bts->nr, ts->trx->nr, ts->nr,
|
||||||
|
gsm_pchan_name(ts->pchan),
|
||||||
|
gsm_pchan_name(ts->dyn.pchan_is));
|
||||||
|
else
|
||||||
|
snprintf(ts2str, sizeof(ts2str),
|
||||||
|
"(bts=%d,trx=%d,ts=%d,pchan=%s"
|
||||||
|
" switching %s -> %s)",
|
||||||
|
ts->trx->bts->nr, ts->trx->nr, ts->nr,
|
||||||
|
gsm_pchan_name(ts->pchan),
|
||||||
|
gsm_pchan_name(ts->dyn.pchan_is),
|
||||||
|
gsm_pchan_name(ts->dyn.pchan_want));
|
||||||
|
break;
|
||||||
|
case GSM_PCHAN_TCH_F_PDCH:
|
||||||
|
if ((ts->flags & TS_F_PDCH_PENDING_MASK) == 0)
|
||||||
|
snprintf(ts2str, sizeof(ts2str),
|
||||||
|
"(bts=%d,trx=%d,ts=%d,pchan=%s as %s)",
|
||||||
|
ts->trx->bts->nr, ts->trx->nr, ts->nr,
|
||||||
|
gsm_pchan_name(ts->pchan),
|
||||||
|
(ts->flags & TS_F_PDCH_ACTIVE)? "PDCH"
|
||||||
|
: "TCH/F");
|
||||||
|
else
|
||||||
|
snprintf(ts2str, sizeof(ts2str),
|
||||||
|
"(bts=%d,trx=%d,ts=%d,pchan=%s"
|
||||||
|
" switching %s -> %s)",
|
||||||
|
ts->trx->bts->nr, ts->trx->nr, ts->nr,
|
||||||
|
gsm_pchan_name(ts->pchan),
|
||||||
|
(ts->flags & TS_F_PDCH_ACTIVE)? "PDCH"
|
||||||
|
: "TCH/F",
|
||||||
|
(ts->flags & TS_F_PDCH_ACT_PENDING)? "PDCH"
|
||||||
|
: "TCH/F");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
snprintf(ts2str, sizeof(ts2str), "(bts=%d,trx=%d,ts=%d,pchan=%s)",
|
||||||
|
ts->trx->bts->nr, ts->trx->nr, ts->nr,
|
||||||
|
gsm_pchan_name(ts->pchan));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ts2str;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *gsm_lchan_name_compute(const struct gsm_lchan *lchan)
|
||||||
|
{
|
||||||
|
struct gsm_bts_trx_ts *ts = lchan->ts;
|
||||||
|
|
||||||
|
snprintf(ts2str, sizeof(ts2str), "(bts=%d,trx=%d,ts=%d,ss=%d)",
|
||||||
|
ts->trx->bts->nr, ts->trx->nr, ts->nr, lchan->nr);
|
||||||
|
|
||||||
|
return ts2str;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* obtain the MO structure for a given object instance */
|
||||||
|
struct gsm_abis_mo *
|
||||||
|
gsm_objclass2mo(struct gsm_bts *bts, uint8_t obj_class,
|
||||||
|
const struct abis_om_obj_inst *obj_inst)
|
||||||
|
{
|
||||||
|
struct gsm_bts_trx *trx;
|
||||||
|
struct gsm_abis_mo *mo = NULL;
|
||||||
|
|
||||||
|
switch (obj_class) {
|
||||||
|
case NM_OC_BTS:
|
||||||
|
mo = &bts->mo;
|
||||||
|
break;
|
||||||
|
case NM_OC_RADIO_CARRIER:
|
||||||
|
if (obj_inst->trx_nr >= bts->num_trx) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
trx = gsm_bts_trx_num(bts, obj_inst->trx_nr);
|
||||||
|
mo = &trx->mo;
|
||||||
|
break;
|
||||||
|
case NM_OC_BASEB_TRANSC:
|
||||||
|
if (obj_inst->trx_nr >= bts->num_trx) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
trx = gsm_bts_trx_num(bts, obj_inst->trx_nr);
|
||||||
|
mo = &trx->bb_transc.mo;
|
||||||
|
break;
|
||||||
|
case NM_OC_CHANNEL:
|
||||||
|
if (obj_inst->trx_nr >= bts->num_trx) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
trx = gsm_bts_trx_num(bts, obj_inst->trx_nr);
|
||||||
|
if (obj_inst->ts_nr >= TRX_NR_TS)
|
||||||
|
return NULL;
|
||||||
|
mo = &trx->ts[obj_inst->ts_nr].mo;
|
||||||
|
break;
|
||||||
|
case NM_OC_SITE_MANAGER:
|
||||||
|
mo = &bts->site_mgr.mo;
|
||||||
|
break;
|
||||||
|
case NM_OC_GPRS_NSE:
|
||||||
|
mo = &bts->gprs.nse.mo;
|
||||||
|
break;
|
||||||
|
case NM_OC_GPRS_CELL:
|
||||||
|
mo = &bts->gprs.cell.mo;
|
||||||
|
break;
|
||||||
|
case NM_OC_GPRS_NSVC:
|
||||||
|
if (obj_inst->trx_nr >= ARRAY_SIZE(bts->gprs.nsvc))
|
||||||
|
return NULL;
|
||||||
|
mo = &bts->gprs.nsvc[obj_inst->trx_nr].mo;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return mo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* obtain the gsm_nm_state data structure for a given object instance */
|
||||||
|
struct gsm_nm_state *
|
||||||
|
gsm_objclass2nmstate(struct gsm_bts *bts, uint8_t obj_class,
|
||||||
|
const struct abis_om_obj_inst *obj_inst)
|
||||||
|
{
|
||||||
|
struct gsm_abis_mo *mo;
|
||||||
|
|
||||||
|
mo = gsm_objclass2mo(bts, obj_class, obj_inst);
|
||||||
|
if (!mo)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return &mo->nm_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* obtain the in-memory data structure of a given object instance */
|
||||||
|
void *
|
||||||
|
gsm_objclass2obj(struct gsm_bts *bts, uint8_t obj_class,
|
||||||
|
const struct abis_om_obj_inst *obj_inst)
|
||||||
|
{
|
||||||
|
struct gsm_bts_trx *trx;
|
||||||
|
void *obj = NULL;
|
||||||
|
|
||||||
|
switch (obj_class) {
|
||||||
|
case NM_OC_BTS:
|
||||||
|
obj = bts;
|
||||||
|
break;
|
||||||
|
case NM_OC_RADIO_CARRIER:
|
||||||
|
if (obj_inst->trx_nr >= bts->num_trx) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
trx = gsm_bts_trx_num(bts, obj_inst->trx_nr);
|
||||||
|
obj = trx;
|
||||||
|
break;
|
||||||
|
case NM_OC_BASEB_TRANSC:
|
||||||
|
if (obj_inst->trx_nr >= bts->num_trx) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
trx = gsm_bts_trx_num(bts, obj_inst->trx_nr);
|
||||||
|
obj = &trx->bb_transc;
|
||||||
|
break;
|
||||||
|
case NM_OC_CHANNEL:
|
||||||
|
if (obj_inst->trx_nr >= bts->num_trx) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
trx = gsm_bts_trx_num(bts, obj_inst->trx_nr);
|
||||||
|
if (obj_inst->ts_nr >= TRX_NR_TS)
|
||||||
|
return NULL;
|
||||||
|
obj = &trx->ts[obj_inst->ts_nr];
|
||||||
|
break;
|
||||||
|
case NM_OC_SITE_MANAGER:
|
||||||
|
obj = &bts->site_mgr;
|
||||||
|
break;
|
||||||
|
case NM_OC_GPRS_NSE:
|
||||||
|
obj = &bts->gprs.nse;
|
||||||
|
break;
|
||||||
|
case NM_OC_GPRS_CELL:
|
||||||
|
obj = &bts->gprs.cell;
|
||||||
|
break;
|
||||||
|
case NM_OC_GPRS_NSVC:
|
||||||
|
if (obj_inst->trx_nr >= ARRAY_SIZE(bts->gprs.nsvc))
|
||||||
|
return NULL;
|
||||||
|
obj = &bts->gprs.nsvc[obj_inst->trx_nr];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* See Table 10.5.25 of GSM04.08 */
|
||||||
|
uint8_t gsm_pchan2chan_nr(enum gsm_phys_chan_config pchan,
|
||||||
|
uint8_t ts_nr, uint8_t lchan_nr)
|
||||||
|
{
|
||||||
|
uint8_t cbits, chan_nr;
|
||||||
|
|
||||||
|
OSMO_ASSERT(pchan != GSM_PCHAN_TCH_F_TCH_H_PDCH);
|
||||||
|
OSMO_ASSERT(pchan != GSM_PCHAN_TCH_F_PDCH);
|
||||||
|
|
||||||
|
switch (pchan) {
|
||||||
|
case GSM_PCHAN_TCH_F:
|
||||||
|
OSMO_ASSERT(lchan_nr == 0);
|
||||||
|
cbits = 0x01;
|
||||||
|
break;
|
||||||
|
case GSM_PCHAN_PDCH:
|
||||||
|
OSMO_ASSERT(lchan_nr == 0);
|
||||||
|
cbits = RSL_CHAN_OSMO_PDCH >> 3;
|
||||||
|
break;
|
||||||
|
case GSM_PCHAN_TCH_H:
|
||||||
|
OSMO_ASSERT(lchan_nr < 2);
|
||||||
|
cbits = 0x02;
|
||||||
|
cbits += lchan_nr;
|
||||||
|
break;
|
||||||
|
case GSM_PCHAN_CCCH_SDCCH4:
|
||||||
|
case GSM_PCHAN_CCCH_SDCCH4_CBCH:
|
||||||
|
/*
|
||||||
|
* As a special hack for BCCH, lchan_nr == 4 may be passed
|
||||||
|
* here. This should never be sent in an RSL message.
|
||||||
|
* See osmo-bts-xxx/oml.c:opstart_compl().
|
||||||
|
*/
|
||||||
|
if (lchan_nr == CCCH_LCHAN)
|
||||||
|
chan_nr = 0;
|
||||||
|
else
|
||||||
|
OSMO_ASSERT(lchan_nr < 4);
|
||||||
|
cbits = 0x04;
|
||||||
|
cbits += lchan_nr;
|
||||||
|
break;
|
||||||
|
case GSM_PCHAN_SDCCH8_SACCH8C:
|
||||||
|
case GSM_PCHAN_SDCCH8_SACCH8C_CBCH:
|
||||||
|
OSMO_ASSERT(lchan_nr < 8);
|
||||||
|
cbits = 0x08;
|
||||||
|
cbits += lchan_nr;
|
||||||
|
break;
|
||||||
|
case GSM_PCHAN_CCCH:
|
||||||
|
default:
|
||||||
|
/* OSMO_ASSERT(lchan_nr == 0);
|
||||||
|
* FIXME: On octphy and litecell, we hit above assertion (see
|
||||||
|
* Max's comment at https://gerrit.osmocom.org/589 ); disabled
|
||||||
|
* for BTS until this is clarified; remove the #ifdef when it
|
||||||
|
* is fixed. Tracked in OS#2906.
|
||||||
|
*/
|
||||||
|
#pragma message "fix caller that passes lchan_nr != 0"
|
||||||
|
cbits = 0x10;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
chan_nr = (cbits << 3) | (ts_nr & 0x7);
|
||||||
|
|
||||||
|
return chan_nr;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t gsm_lchan2chan_nr(const struct gsm_lchan *lchan)
|
||||||
|
{
|
||||||
|
switch (lchan->ts->pchan) {
|
||||||
|
case GSM_PCHAN_TCH_F_TCH_H_PDCH:
|
||||||
|
/* Return chan_nr reflecting the current TS pchan, either a standard TCH kind, or the
|
||||||
|
* nonstandard value reflecting PDCH for Osmocom style dyn TS. */
|
||||||
|
return gsm_lchan_as_pchan2chan_nr(lchan,
|
||||||
|
lchan->ts->dyn.pchan_is);
|
||||||
|
case GSM_PCHAN_TCH_F_PDCH:
|
||||||
|
/* For ip.access style dyn TS, we always want to use the chan_nr as if it was TCH/F.
|
||||||
|
* We're using custom PDCH ACT and DEACT messages that use the usual chan_nr values. */
|
||||||
|
return gsm_lchan_as_pchan2chan_nr(lchan, GSM_PCHAN_TCH_F);
|
||||||
|
default:
|
||||||
|
return gsm_pchan2chan_nr(lchan->ts->pchan, lchan->ts->nr, lchan->nr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t gsm_lchan_as_pchan2chan_nr(const struct gsm_lchan *lchan,
|
||||||
|
enum gsm_phys_chan_config as_pchan)
|
||||||
|
{
|
||||||
|
if (lchan->ts->pchan == GSM_PCHAN_TCH_F_TCH_H_PDCH
|
||||||
|
&& as_pchan == GSM_PCHAN_PDCH)
|
||||||
|
return RSL_CHAN_OSMO_PDCH | (lchan->ts->nr & ~RSL_CHAN_NR_MASK);
|
||||||
|
return gsm_pchan2chan_nr(as_pchan, lchan->ts->nr, lchan->nr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* return the gsm_lchan for the CBCH (if it exists at all) */
|
||||||
|
struct gsm_lchan *gsm_bts_get_cbch(struct gsm_bts *bts)
|
||||||
|
{
|
||||||
|
struct gsm_lchan *lchan = NULL;
|
||||||
|
struct gsm_bts_trx *trx = bts->c0;
|
||||||
|
|
||||||
|
if (trx->ts[0].pchan == GSM_PCHAN_CCCH_SDCCH4_CBCH)
|
||||||
|
lchan = &trx->ts[0].lchan[2];
|
||||||
|
else {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < 8; i++) {
|
||||||
|
if (trx->ts[i].pchan == GSM_PCHAN_SDCCH8_SACCH8C_CBCH) {
|
||||||
|
lchan = &trx->ts[i].lchan[2];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return lchan;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* determine logical channel based on TRX and channel number IE */
|
||||||
|
struct gsm_lchan *rsl_lchan_lookup(struct gsm_bts_trx *trx, uint8_t chan_nr,
|
||||||
|
int *rc)
|
||||||
|
{
|
||||||
|
uint8_t ts_nr = chan_nr & 0x07;
|
||||||
|
uint8_t cbits = chan_nr >> 3;
|
||||||
|
uint8_t lch_idx;
|
||||||
|
struct gsm_bts_trx_ts *ts = &trx->ts[ts_nr];
|
||||||
|
bool ok = true;
|
||||||
|
|
||||||
|
if (rc)
|
||||||
|
*rc = -EINVAL;
|
||||||
|
|
||||||
|
if (cbits == 0x01) {
|
||||||
|
lch_idx = 0; /* TCH/F */
|
||||||
|
if (ts->pchan != GSM_PCHAN_TCH_F &&
|
||||||
|
ts->pchan != GSM_PCHAN_PDCH &&
|
||||||
|
ts->pchan != GSM_PCHAN_TCH_F_PDCH &&
|
||||||
|
ts->pchan != GSM_PCHAN_TCH_F_TCH_H_PDCH)
|
||||||
|
ok = false;
|
||||||
|
} else if ((cbits & 0x1e) == 0x02) {
|
||||||
|
lch_idx = cbits & 0x1; /* TCH/H */
|
||||||
|
if (ts->pchan != GSM_PCHAN_TCH_H &&
|
||||||
|
ts->pchan != GSM_PCHAN_TCH_F_TCH_H_PDCH)
|
||||||
|
ok = false;
|
||||||
|
} else if ((cbits & 0x1c) == 0x04) {
|
||||||
|
lch_idx = cbits & 0x3; /* SDCCH/4 */
|
||||||
|
if (ts->pchan != GSM_PCHAN_CCCH_SDCCH4 &&
|
||||||
|
ts->pchan != GSM_PCHAN_CCCH_SDCCH4_CBCH)
|
||||||
|
ok = false;
|
||||||
|
} else if ((cbits & 0x18) == 0x08) {
|
||||||
|
lch_idx = cbits & 0x7; /* SDCCH/8 */
|
||||||
|
if (ts->pchan != GSM_PCHAN_SDCCH8_SACCH8C &&
|
||||||
|
ts->pchan != GSM_PCHAN_SDCCH8_SACCH8C_CBCH)
|
||||||
|
ok = false;
|
||||||
|
} else if (cbits == 0x10 || cbits == 0x11 || cbits == 0x12) {
|
||||||
|
lch_idx = 0;
|
||||||
|
if (ts->pchan != GSM_PCHAN_CCCH &&
|
||||||
|
ts->pchan != GSM_PCHAN_CCCH_SDCCH4 &&
|
||||||
|
ts->pchan != GSM_PCHAN_CCCH_SDCCH4_CBCH)
|
||||||
|
ok = false;
|
||||||
|
/* FIXME: we should not return first sdcch4 !!! */
|
||||||
|
} else if ((chan_nr & RSL_CHAN_NR_MASK) == RSL_CHAN_OSMO_PDCH) {
|
||||||
|
lch_idx = 0;
|
||||||
|
if (ts->pchan != GSM_PCHAN_TCH_F_TCH_H_PDCH)
|
||||||
|
ok = false;
|
||||||
|
} else
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (rc && ok)
|
||||||
|
*rc = 0;
|
||||||
|
|
||||||
|
return &ts->lchan[lch_idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
static const uint8_t subslots_per_pchan[] = {
|
||||||
|
[GSM_PCHAN_NONE] = 0,
|
||||||
|
[GSM_PCHAN_CCCH] = 0,
|
||||||
|
[GSM_PCHAN_PDCH] = 0,
|
||||||
|
[GSM_PCHAN_CCCH_SDCCH4] = 4,
|
||||||
|
[GSM_PCHAN_TCH_F] = 1,
|
||||||
|
[GSM_PCHAN_TCH_H] = 2,
|
||||||
|
[GSM_PCHAN_SDCCH8_SACCH8C] = 8,
|
||||||
|
[GSM_PCHAN_CCCH_SDCCH4_CBCH] = 4,
|
||||||
|
[GSM_PCHAN_SDCCH8_SACCH8C_CBCH] = 8,
|
||||||
|
/*
|
||||||
|
* GSM_PCHAN_TCH_F_PDCH and GSM_PCHAN_TCH_F_TCH_H_PDCH should not be
|
||||||
|
* part of this, those TS are handled according to their dynamic state.
|
||||||
|
*/
|
||||||
|
};
|
||||||
|
|
||||||
|
/*! Return the actual pchan type, also heeding dynamic TS. */
|
||||||
|
enum gsm_phys_chan_config ts_pchan(struct gsm_bts_trx_ts *ts)
|
||||||
|
{
|
||||||
|
switch (ts->pchan) {
|
||||||
|
case GSM_PCHAN_TCH_F_TCH_H_PDCH:
|
||||||
|
return ts->dyn.pchan_is;
|
||||||
|
case GSM_PCHAN_TCH_F_PDCH:
|
||||||
|
if (ts->flags & TS_F_PDCH_ACTIVE)
|
||||||
|
return GSM_PCHAN_PDCH;
|
||||||
|
else
|
||||||
|
return GSM_PCHAN_TCH_F;
|
||||||
|
default:
|
||||||
|
return ts->pchan;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! According to ts->pchan and possibly ts->dyn_pchan, return the number of
|
||||||
|
* logical channels available in the timeslot. */
|
||||||
|
uint8_t ts_subslots(struct gsm_bts_trx_ts *ts)
|
||||||
|
{
|
||||||
|
return subslots_per_pchan[ts_pchan(ts)];
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool pchan_is_tch(enum gsm_phys_chan_config pchan)
|
||||||
|
{
|
||||||
|
switch (pchan) {
|
||||||
|
case GSM_PCHAN_TCH_F:
|
||||||
|
case GSM_PCHAN_TCH_H:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ts_is_tch(struct gsm_bts_trx_ts *ts)
|
||||||
|
{
|
||||||
|
return pchan_is_tch(ts_pchan(ts));
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *gsm_trx_unit_id(struct gsm_bts_trx *trx)
|
||||||
|
{
|
||||||
|
static char buf[23];
|
||||||
|
|
||||||
|
snprintf(buf, sizeof(buf), "%u/%u/%u", trx->bts->ip_access.site_id,
|
||||||
|
trx->bts->ip_access.bts_id, trx->nr);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct value_string lchan_ciph_state_names[] = {
|
||||||
|
{ LCHAN_CIPH_NONE, "NONE" },
|
||||||
|
{ LCHAN_CIPH_RX_REQ, "RX_REQ" },
|
||||||
|
{ LCHAN_CIPH_RX_CONF, "RX_CONF" },
|
||||||
|
{ LCHAN_CIPH_RXTX_REQ, "RXTX_REQ" },
|
||||||
|
{ LCHAN_CIPH_RX_CONF_TX_REQ, "RX_CONF_TX_REQ" },
|
||||||
|
{ LCHAN_CIPH_RXTX_CONF, "RXTX_CONF" },
|
||||||
|
{ 0, NULL }
|
||||||
|
};
|
||||||
@@ -0,0 +1,164 @@
|
|||||||
|
/* Paging message encoding + queue management */
|
||||||
|
|
||||||
|
/* (C) 2012-2013 by Harald Welte <laforge@gnumonks.org>
|
||||||
|
* Andreas Eversberg <jolly@eversberg.eu>
|
||||||
|
* (C) 2014 by Holger Hans Peter Freyther
|
||||||
|
*
|
||||||
|
* 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 <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <osmocom/gsm/protocol/gsm_04_08.h>
|
||||||
|
#include <osmocom/gsm/rsl.h>
|
||||||
|
|
||||||
|
#include <osmo-bts/bts.h>
|
||||||
|
#include <osmo-bts/bts_model.h>
|
||||||
|
#include <osmo-bts/rsl.h>
|
||||||
|
#include <osmo-bts/logging.h>
|
||||||
|
#include <osmo-bts/handover.h>
|
||||||
|
#include <osmo-bts/l1sap.h>
|
||||||
|
|
||||||
|
/* Transmit a handover related PHYS INFO on given lchan */
|
||||||
|
static int ho_tx_phys_info(struct gsm_lchan *lchan)
|
||||||
|
{
|
||||||
|
struct msgb *msg = msgb_alloc_headroom(1024, 128, "PHYS INFO");
|
||||||
|
struct gsm48_hdr *gh;
|
||||||
|
|
||||||
|
if (!msg)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
LOGP(DHO, LOGL_INFO,
|
||||||
|
"%s Sending PHYSICAL INFORMATION to MS.\n",
|
||||||
|
gsm_lchan_name(lchan));
|
||||||
|
|
||||||
|
/* Build RSL UNITDATA REQUEST message with 04.08 PHYS INFO */
|
||||||
|
msg->l3h = msg->data;
|
||||||
|
gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
|
||||||
|
gh->proto_discr = GSM48_PDISC_RR;
|
||||||
|
gh->msg_type = GSM48_MT_RR_HANDO_INFO;
|
||||||
|
msgb_put_u8(msg, lchan->rqd_ta);
|
||||||
|
|
||||||
|
rsl_rll_push_l3(msg, RSL_MT_UNIT_DATA_REQ, gsm_lchan2chan_nr(lchan),
|
||||||
|
0x00, 0);
|
||||||
|
|
||||||
|
lapdm_rslms_recvmsg(msg, &lchan->lapdm_ch);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* timer call-back for T3105 (handover PHYS INFO re-transmit) */
|
||||||
|
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);
|
||||||
|
|
||||||
|
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));
|
||||||
|
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));
|
||||||
|
rsl_tx_conn_fail(lchan, RSL_ERR_HANDOVER_ACC_FAIL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ho_tx_phys_info(lchan);
|
||||||
|
lchan->ho.phys_info_count++;
|
||||||
|
osmo_timer_schedule(&lchan->ho.t3105, 0, bts->t3105_ms * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* received random access on dedicated channel */
|
||||||
|
void handover_rach(struct gsm_lchan *lchan, uint8_t ra, uint8_t acc_delay)
|
||||||
|
{
|
||||||
|
struct gsm_bts *bts = lchan->ts->trx->bts;
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
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));
|
||||||
|
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);
|
||||||
|
|
||||||
|
/* Set timing advance */
|
||||||
|
lchan->rqd_ta = 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));
|
||||||
|
rsl_tx_conn_fail(lchan, RSL_ERR_HANDOVER_ACC_FAIL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Send HANDover DETect to BSC */
|
||||||
|
rsl_tx_hando_det(lchan, &lchan->rqd_ta);
|
||||||
|
|
||||||
|
/* Send PHYS INFO */
|
||||||
|
lchan->ho.phys_info_count = 1;
|
||||||
|
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);
|
||||||
|
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 */
|
||||||
|
void handover_frame(struct gsm_lchan *lchan)
|
||||||
|
{
|
||||||
|
LOGP(DHO, LOGL_INFO,
|
||||||
|
"%s First valid frame detected\n", gsm_lchan_name(lchan));
|
||||||
|
handover_reset(lchan);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* release handover state */
|
||||||
|
void handover_reset(struct gsm_lchan *lchan)
|
||||||
|
{
|
||||||
|
/* Stop T3105 */
|
||||||
|
osmo_timer_del(&lchan->ho.t3105);
|
||||||
|
|
||||||
|
/* Handover process is done */
|
||||||
|
lchan->ho.active = HANDOVER_NONE;
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,49 @@
|
|||||||
|
/* OsmoBTS lchan interface */
|
||||||
|
|
||||||
|
/* (C) 2012 by Holger Hans Peter Freyther
|
||||||
|
*
|
||||||
|
* 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 <osmocom/core/logging.h>
|
||||||
|
#include <osmo-bts/logging.h>
|
||||||
|
#include <osmo-bts/gsm_data.h>
|
||||||
|
|
||||||
|
void lchan_set_state(struct gsm_lchan *lchan, enum gsm_lchan_state state)
|
||||||
|
{
|
||||||
|
DEBUGP(DL1C, "%s state %s -> %s\n",
|
||||||
|
gsm_lchan_name(lchan),
|
||||||
|
gsm_lchans_name(lchan->state),
|
||||||
|
gsm_lchans_name(state));
|
||||||
|
lchan->state = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ts_is_pdch(const struct gsm_bts_trx_ts *ts)
|
||||||
|
{
|
||||||
|
switch (ts->pchan) {
|
||||||
|
case GSM_PCHAN_PDCH:
|
||||||
|
return true;
|
||||||
|
case GSM_PCHAN_TCH_F_PDCH:
|
||||||
|
return (ts->flags & TS_F_PDCH_ACTIVE)
|
||||||
|
&& !(ts->flags & TS_F_PDCH_PENDING_MASK);
|
||||||
|
case GSM_PCHAN_TCH_F_TCH_H_PDCH:
|
||||||
|
return ts->dyn.pchan_is == GSM_PCHAN_PDCH
|
||||||
|
&& ts->dyn.pchan_want == ts->dyn.pchan_is;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
/* Support for generating RSL Load Indication */
|
||||||
|
|
||||||
|
/* (C) 2011 by Harald Welte <laforge@gnumonks.org>
|
||||||
|
*
|
||||||
|
* 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 <stdint.h>
|
||||||
|
|
||||||
|
#include <osmocom/core/timer.h>
|
||||||
|
#include <osmocom/core/msgb.h>
|
||||||
|
|
||||||
|
#include <osmo-bts/gsm_data.h>
|
||||||
|
#include <osmo-bts/rsl.h>
|
||||||
|
#include <osmo-bts/paging.h>
|
||||||
|
|
||||||
|
static void reset_load_counters(struct gsm_bts *bts)
|
||||||
|
{
|
||||||
|
/* re-set the counters */
|
||||||
|
bts->load.ccch.pch_used = bts->load.ccch.pch_total = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void load_timer_cb(void *data)
|
||||||
|
{
|
||||||
|
struct gsm_bts *bts = data;
|
||||||
|
unsigned int pch_percent, rach_percent;
|
||||||
|
|
||||||
|
/* compute percentages */
|
||||||
|
if (bts->load.ccch.pch_total == 0)
|
||||||
|
pch_percent = 0;
|
||||||
|
else
|
||||||
|
pch_percent = (bts->load.ccch.pch_used * 100) /
|
||||||
|
bts->load.ccch.pch_total;
|
||||||
|
|
||||||
|
if (pch_percent >= bts->load.ccch.load_ind_thresh) {
|
||||||
|
/* send RSL load indication message to BSC */
|
||||||
|
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
|
||||||
|
* 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 */
|
||||||
|
rsl_tx_ccch_load_ind_pch(bts, 0xffff);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bts->load.rach.total == 0)
|
||||||
|
rach_percent = 0;
|
||||||
|
else
|
||||||
|
rach_percent = (bts->load.rach.busy * 100) /
|
||||||
|
bts->load.rach.total;
|
||||||
|
|
||||||
|
if (rach_percent >= bts->load.ccch.load_ind_thresh) {
|
||||||
|
/* send RSL load indication message to BSC */
|
||||||
|
rsl_tx_ccch_load_ind_rach(bts, bts->load.rach.total,
|
||||||
|
bts->load.rach.busy,
|
||||||
|
bts->load.rach.access);
|
||||||
|
}
|
||||||
|
|
||||||
|
reset_load_counters(bts);
|
||||||
|
|
||||||
|
/* re-schedule the timer */
|
||||||
|
osmo_timer_schedule(&bts->load.ccch.timer,
|
||||||
|
bts->load.ccch.load_ind_period, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void load_timer_start(struct gsm_bts *bts)
|
||||||
|
{
|
||||||
|
if (!bts->load.ccch.timer.data) {
|
||||||
|
bts->load.ccch.timer.data = bts;
|
||||||
|
bts->load.ccch.timer.cb = load_timer_cb;
|
||||||
|
reset_load_counters(bts);
|
||||||
|
}
|
||||||
|
osmo_timer_schedule(&bts->load.ccch.timer, bts->load.ccch.load_ind_period, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void load_timer_stop(struct gsm_bts *bts)
|
||||||
|
{
|
||||||
|
osmo_timer_del(&bts->load.ccch.timer);
|
||||||
|
}
|
||||||
@@ -0,0 +1,150 @@
|
|||||||
|
/* libosmocore logging support */
|
||||||
|
|
||||||
|
/* (C) 2011 by Andreas Eversberg <jolly@eversberg.eu>
|
||||||
|
* (C) 2011 by Harald Welte <laforge@gnumonks.org>
|
||||||
|
*
|
||||||
|
* 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 <errno.h>
|
||||||
|
|
||||||
|
#include <osmocom/core/logging.h>
|
||||||
|
#include <osmocom/core/application.h>
|
||||||
|
#include <osmocom/core/utils.h>
|
||||||
|
|
||||||
|
#include <osmo-bts/bts.h>
|
||||||
|
#include <osmo-bts/logging.h>
|
||||||
|
|
||||||
|
static struct log_info_cat bts_log_info_cat[] = {
|
||||||
|
[DRSL] = {
|
||||||
|
.name = "DRSL",
|
||||||
|
.description = "A-bis Radio Siganlling Link (RSL)",
|
||||||
|
.color = "\033[1;35m",
|
||||||
|
.enabled = 1, .loglevel = LOGL_INFO,
|
||||||
|
},
|
||||||
|
[DOML] = {
|
||||||
|
.name = "DOML",
|
||||||
|
.description = "A-bis Network Management / O&M (NM/OML)",
|
||||||
|
.color = "\033[1;36m",
|
||||||
|
.enabled = 1, .loglevel = LOGL_INFO,
|
||||||
|
},
|
||||||
|
[DRLL] = {
|
||||||
|
.name = "DRLL",
|
||||||
|
.description = "A-bis Radio Link Layer (RLL)",
|
||||||
|
.color = "\033[1;31m",
|
||||||
|
.enabled = 1, .loglevel = LOGL_NOTICE,
|
||||||
|
},
|
||||||
|
[DRR] = {
|
||||||
|
.name = "DRR",
|
||||||
|
.description = "Layer3 Radio Resource (RR)",
|
||||||
|
.color = "\033[1;34m",
|
||||||
|
.enabled = 1, .loglevel = LOGL_NOTICE,
|
||||||
|
},
|
||||||
|
[DMEAS] = {
|
||||||
|
.name = "DMEAS",
|
||||||
|
.description = "Radio Measurement Processing",
|
||||||
|
.enabled = 1, .loglevel = LOGL_NOTICE,
|
||||||
|
},
|
||||||
|
[DPAG] = {
|
||||||
|
.name = "DPAG",
|
||||||
|
.description = "Paging Subsystem",
|
||||||
|
.color = "\033[1;38m",
|
||||||
|
.enabled = 1, .loglevel = LOGL_INFO,
|
||||||
|
},
|
||||||
|
[DL1C] = {
|
||||||
|
.name = "DL1C",
|
||||||
|
.description = "Layer 1 Control (MPH)",
|
||||||
|
.loglevel = LOGL_INFO,
|
||||||
|
.enabled = 1,
|
||||||
|
},
|
||||||
|
[DL1P] = {
|
||||||
|
.name = "DL1P",
|
||||||
|
.description = "Layer 1 Primitives (PH)",
|
||||||
|
.loglevel = LOGL_INFO,
|
||||||
|
.enabled = 0,
|
||||||
|
},
|
||||||
|
[DDSP] = {
|
||||||
|
.name = "DDSP",
|
||||||
|
.description = "DSP Trace Messages",
|
||||||
|
.loglevel = LOGL_DEBUG,
|
||||||
|
.enabled = 1,
|
||||||
|
},
|
||||||
|
[DABIS] = {
|
||||||
|
.name = "DABIS",
|
||||||
|
.description = "A-bis Intput Subsystem",
|
||||||
|
.enabled = 1, .loglevel = LOGL_NOTICE,
|
||||||
|
},
|
||||||
|
[DRTP] = {
|
||||||
|
.name = "DRTP",
|
||||||
|
.description = "Realtime Transfer Protocol",
|
||||||
|
.loglevel = LOGL_NOTICE,
|
||||||
|
.enabled = 1,
|
||||||
|
},
|
||||||
|
[DPCU] = {
|
||||||
|
.name = "DPCU",
|
||||||
|
.description = "PCU interface",
|
||||||
|
.loglevel = LOGL_NOTICE,
|
||||||
|
.enabled = 1,
|
||||||
|
},
|
||||||
|
[DHO] = {
|
||||||
|
.name = "DHO",
|
||||||
|
.description = "Handover",
|
||||||
|
.color = "\033[0;37m",
|
||||||
|
.enabled = 1, .loglevel = LOGL_NOTICE,
|
||||||
|
},
|
||||||
|
[DTRX] = {
|
||||||
|
.name = "DTRX",
|
||||||
|
.description = "TRX interface",
|
||||||
|
.color = "\033[1;33m",
|
||||||
|
.enabled = 1, .loglevel = LOGL_NOTICE,
|
||||||
|
},
|
||||||
|
[DLOOP] = {
|
||||||
|
.name = "DLOOP",
|
||||||
|
.description = "Control loops",
|
||||||
|
.color = "\033[0;34m",
|
||||||
|
.enabled = 1, .loglevel = LOGL_NOTICE,
|
||||||
|
},
|
||||||
|
#if 0
|
||||||
|
[DNS] = {
|
||||||
|
.name = "DNS",
|
||||||
|
.description = "GPRS Network Service (NS)",
|
||||||
|
.enabled = 1, .loglevel = LOGL_INFO,
|
||||||
|
},
|
||||||
|
[DBSSGP] = {
|
||||||
|
.name = "DBSSGP",
|
||||||
|
.description = "GPRS BSS Gateway Protocol (BSSGP)",
|
||||||
|
.enabled = 1, .loglevel = LOGL_DEBUG,
|
||||||
|
},
|
||||||
|
[DLLC] = {
|
||||||
|
.name = "DLLC",
|
||||||
|
.description = "GPRS Logical Link Control Protocol (LLC)",
|
||||||
|
.enabled = 1, .loglevel = LOGL_DEBUG,
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
[DSUM] = {
|
||||||
|
.name = "DSUM",
|
||||||
|
.description = "DSUM",
|
||||||
|
.loglevel = LOGL_NOTICE,
|
||||||
|
.enabled = 1,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct log_info bts_log_info = {
|
||||||
|
.cat = bts_log_info_cat,
|
||||||
|
.num_cat = ARRAY_SIZE(bts_log_info_cat),
|
||||||
|
};
|
||||||
@@ -0,0 +1,368 @@
|
|||||||
|
/* Main program for Osmocom BTS */
|
||||||
|
|
||||||
|
/* (C) 2011-2016 by Harald Welte <laforge@gnumonks.org>
|
||||||
|
*
|
||||||
|
* 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 <stdint.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <sys/signal.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sched.h>
|
||||||
|
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
#include <osmocom/core/talloc.h>
|
||||||
|
#include <osmocom/core/application.h>
|
||||||
|
#include <osmocom/vty/telnet_interface.h>
|
||||||
|
#include <osmocom/vty/logging.h>
|
||||||
|
#include <osmocom/core/gsmtap_util.h>
|
||||||
|
#include <osmocom/core/gsmtap.h>
|
||||||
|
|
||||||
|
#include <osmo-bts/gsm_data.h>
|
||||||
|
#include <osmo-bts/phy_link.h>
|
||||||
|
#include <osmo-bts/logging.h>
|
||||||
|
#include <osmo-bts/abis.h>
|
||||||
|
#include <osmo-bts/bts.h>
|
||||||
|
#include <osmo-bts/vty.h>
|
||||||
|
#include <osmo-bts/l1sap.h>
|
||||||
|
#include <osmo-bts/bts_model.h>
|
||||||
|
#include <osmo-bts/pcu_if.h>
|
||||||
|
#include <osmo-bts/control_if.h>
|
||||||
|
#include <osmocom/ctrl/control_if.h>
|
||||||
|
#include <osmocom/ctrl/ports.h>
|
||||||
|
#include <osmocom/ctrl/control_vty.h>
|
||||||
|
#include <osmo-bts/oml.h>
|
||||||
|
|
||||||
|
int quit = 0;
|
||||||
|
static const char *config_file = "osmo-bts.cfg";
|
||||||
|
static int daemonize = 0;
|
||||||
|
static int rt_prio = -1;
|
||||||
|
static int trx_num = 1;
|
||||||
|
static char *gsmtap_ip = 0;
|
||||||
|
extern int g_vty_port_num;
|
||||||
|
|
||||||
|
static void print_help()
|
||||||
|
{
|
||||||
|
printf( "Some useful options:\n"
|
||||||
|
" -h --help this text\n"
|
||||||
|
" -d --debug MASK Enable debugging (e.g. -d DRSL:DOML:DLAPDM)\n"
|
||||||
|
" -D --daemonize For the process into a background daemon\n"
|
||||||
|
" -c --config-file Specify the filename of the config file\n"
|
||||||
|
" -s --disable-color Don't use colors in stderr log output\n"
|
||||||
|
" -T --timestamp Prefix every log line with a timestamp\n"
|
||||||
|
" -V --version Print version information and exit\n"
|
||||||
|
" -e --log-level Set a global log-level\n"
|
||||||
|
" -r --realtime PRIO Use SCHED_RR with the specified priority\n"
|
||||||
|
" -i --gsmtap-ip The destination IP used for GSMTAP.\n"
|
||||||
|
" -t --trx-num Set number of TRX (default=%d)\n",
|
||||||
|
trx_num
|
||||||
|
);
|
||||||
|
bts_model_print_help();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME: finally get some option parsing code into libosmocore */
|
||||||
|
static void handle_options(int argc, char **argv)
|
||||||
|
{
|
||||||
|
char *argv_out[argc];
|
||||||
|
int argc_out = 0;
|
||||||
|
|
||||||
|
argv_out[argc_out++] = argv[0];
|
||||||
|
|
||||||
|
/* disable generation of error messages on encountering unknown
|
||||||
|
* options */
|
||||||
|
opterr = 0;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
int option_idx = 0, c;
|
||||||
|
static const struct option long_options[] = {
|
||||||
|
/* FIXME: all those are generic Osmocom app options */
|
||||||
|
{ "help", 0, 0, 'h' },
|
||||||
|
{ "debug", 1, 0, 'd' },
|
||||||
|
{ "daemonize", 0, 0, 'D' },
|
||||||
|
{ "config-file", 1, 0, 'c' },
|
||||||
|
{ "disable-color", 0, 0, 's' },
|
||||||
|
{ "timestamp", 0, 0, 'T' },
|
||||||
|
{ "version", 0, 0, 'V' },
|
||||||
|
{ "log-level", 1, 0, 'e' },
|
||||||
|
/* FIXME: generic BTS app options */
|
||||||
|
{ "gsmtap-ip", 1, 0, 'i' },
|
||||||
|
{ "trx-num", 1, 0, 't' },
|
||||||
|
{ "realtime", 1, 0, 'r' },
|
||||||
|
{ 0, 0, 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
c = getopt_long(argc, argv, "-hc:d:Dc:sTVe:i:t:r:",
|
||||||
|
long_options, &option_idx);
|
||||||
|
if (c == -1)
|
||||||
|
break;
|
||||||
|
|
||||||
|
switch (c) {
|
||||||
|
case 'h':
|
||||||
|
print_help();
|
||||||
|
exit(0);
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
log_set_use_color(osmo_stderr_target, 0);
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
log_parse_category_mask(osmo_stderr_target, optarg);
|
||||||
|
break;
|
||||||
|
case 'D':
|
||||||
|
daemonize = 1;
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
config_file = optarg;
|
||||||
|
break;
|
||||||
|
case 'T':
|
||||||
|
log_set_print_timestamp(osmo_stderr_target, 1);
|
||||||
|
break;
|
||||||
|
case 'V':
|
||||||
|
print_version(1);
|
||||||
|
exit(0);
|
||||||
|
break;
|
||||||
|
case 'e':
|
||||||
|
log_set_log_level(osmo_stderr_target, atoi(optarg));
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
rt_prio = atoi(optarg);
|
||||||
|
break;
|
||||||
|
case 'i':
|
||||||
|
gsmtap_ip = optarg;
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
trx_num = atoi(optarg);
|
||||||
|
if (trx_num < 1)
|
||||||
|
trx_num = 1;
|
||||||
|
break;
|
||||||
|
case '?':
|
||||||
|
case 1:
|
||||||
|
/* prepare argv[] for bts_model */
|
||||||
|
argv_out[argc_out++] = argv[optind-1];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* re-set opt-ind for new parsig round */
|
||||||
|
optind = 1;
|
||||||
|
/* enable error-checking for the following getopt call */
|
||||||
|
opterr = 1;
|
||||||
|
if (bts_model_handle_options(argc_out, argv_out)) {
|
||||||
|
print_help();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct gsm_bts *bts;
|
||||||
|
|
||||||
|
static void signal_handler(int signal)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "signal %u received\n", signal);
|
||||||
|
|
||||||
|
switch (signal) {
|
||||||
|
case SIGINT:
|
||||||
|
case SIGTERM:
|
||||||
|
if (!quit) {
|
||||||
|
oml_fail_rep(OSMO_EVT_CRIT_PROC_STOP,
|
||||||
|
"BTS: SIGINT received -> shutdown");
|
||||||
|
bts_shutdown(bts, "SIGINT");
|
||||||
|
}
|
||||||
|
quit++;
|
||||||
|
break;
|
||||||
|
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:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int write_pid_file(char *procname)
|
||||||
|
{
|
||||||
|
FILE *outf;
|
||||||
|
char tmp[PATH_MAX+1];
|
||||||
|
|
||||||
|
snprintf(tmp, sizeof(tmp)-1, "/var/run/%s.pid", procname);
|
||||||
|
tmp[PATH_MAX-1] = '\0';
|
||||||
|
|
||||||
|
outf = fopen(tmp, "w");
|
||||||
|
if (!outf)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
fprintf(outf, "%d\n", getpid());
|
||||||
|
|
||||||
|
fclose(outf);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bts_main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
struct gsm_bts_trx *trx;
|
||||||
|
struct e1inp_line *line;
|
||||||
|
int rc, i;
|
||||||
|
|
||||||
|
printf("((*))\n |\n / \\ OsmoBTS\n");
|
||||||
|
|
||||||
|
/* Track the use of talloc NULL memory contexts */
|
||||||
|
talloc_enable_null_tracking();
|
||||||
|
|
||||||
|
tall_bts_ctx = talloc_named_const(NULL, 1, "OsmoBTS context");
|
||||||
|
msgb_talloc_ctx_init(tall_bts_ctx, 100*1024);
|
||||||
|
bts_vty_info.tall_ctx = tall_bts_ctx;
|
||||||
|
|
||||||
|
osmo_init_logging2(tall_bts_ctx, &bts_log_info);
|
||||||
|
vty_init(&bts_vty_info);
|
||||||
|
ctrl_vty_init(tall_bts_ctx);
|
||||||
|
rate_ctr_init(tall_bts_ctx);
|
||||||
|
|
||||||
|
handle_options(argc, argv);
|
||||||
|
|
||||||
|
bts = gsm_bts_alloc(tall_bts_ctx, 0);
|
||||||
|
if (!bts) {
|
||||||
|
fprintf(stderr, "Failed to create BTS structure\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
for (i = 1; i < trx_num; i++) {
|
||||||
|
trx = gsm_bts_trx_alloc(bts);
|
||||||
|
if (!trx) {
|
||||||
|
fprintf(stderr, "Failed to create TRX structure\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
e1inp_vty_init();
|
||||||
|
bts_vty_init(bts, &bts_log_info);
|
||||||
|
|
||||||
|
/* enable realtime priority for us */
|
||||||
|
if (rt_prio != -1) {
|
||||||
|
struct sched_param param;
|
||||||
|
|
||||||
|
memset(¶m, 0, sizeof(param));
|
||||||
|
param.sched_priority = rt_prio;
|
||||||
|
rc = sched_setscheduler(getpid(), SCHED_RR, ¶m);
|
||||||
|
if (rc != 0) {
|
||||||
|
fprintf(stderr, "Setting SCHED_RR priority(%d) failed: %s\n",
|
||||||
|
param.sched_priority, strerror(errno));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gsmtap_ip) {
|
||||||
|
gsmtap = gsmtap_source_init(gsmtap_ip, GSMTAP_UDP_PORT, 1);
|
||||||
|
if (!gsmtap) {
|
||||||
|
fprintf(stderr, "Failed during gsmtap_init()\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
gsmtap_source_add_sink(gsmtap);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bts_init(bts) < 0) {
|
||||||
|
fprintf(stderr, "unable to open bts\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
abis_init(bts);
|
||||||
|
|
||||||
|
rc = vty_read_config_file(config_file, NULL);
|
||||||
|
if (rc < 0) {
|
||||||
|
fprintf(stderr, "Failed to parse the config file: '%s'\n",
|
||||||
|
config_file);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!phy_link_by_num(0)) {
|
||||||
|
fprintf(stderr, "You need to configure at least phy0\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
llist_for_each_entry(trx, &bts->trx_list, list) {
|
||||||
|
if (!trx->role_bts.l1h) {
|
||||||
|
fprintf(stderr, "TRX %u has no associated PHY instance\n",
|
||||||
|
trx->nr);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
write_pid_file("osmo-bts");
|
||||||
|
|
||||||
|
bts_controlif_setup(bts, ctrl_vty_get_bind_addr(), OSMO_CTRL_PORT_BTS);
|
||||||
|
|
||||||
|
rc = telnet_init_dynif(tall_bts_ctx, NULL, vty_get_bind_addr(),
|
||||||
|
g_vty_port_num);
|
||||||
|
if (rc < 0) {
|
||||||
|
fprintf(stderr, "Error initializing telnet\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pcu_sock_init(bts->pcu.sock_path)) {
|
||||||
|
fprintf(stderr, "PCU L1 socket failed\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
signal(SIGINT, &signal_handler);
|
||||||
|
signal(SIGTERM, &signal_handler);
|
||||||
|
//signal(SIGABRT, &signal_handler);
|
||||||
|
signal(SIGUSR1, &signal_handler);
|
||||||
|
signal(SIGUSR2, &signal_handler);
|
||||||
|
osmo_init_ignore_signals();
|
||||||
|
|
||||||
|
if (!bts->bsc_oml_host) {
|
||||||
|
fprintf(stderr, "Cannot start BTS without knowing BSC OML IP\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
line = abis_open(bts, bts->bsc_oml_host, "sysmoBTS");
|
||||||
|
if (!line) {
|
||||||
|
fprintf(stderr, "unable to connect to BSC\n");
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = phy_links_open();
|
||||||
|
if (rc < 0) {
|
||||||
|
fprintf(stderr, "unable to open PHY link(s)\n");
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (daemonize) {
|
||||||
|
rc = osmo_daemonize();
|
||||||
|
if (rc < 0) {
|
||||||
|
perror("Error during daemonize");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (quit < 2) {
|
||||||
|
log_reset_context();
|
||||||
|
osmo_select_main(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
@@ -0,0 +1,418 @@
|
|||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <osmocom/gsm/gsm_utils.h>
|
||||||
|
|
||||||
|
#include <osmo-bts/gsm_data.h>
|
||||||
|
#include <osmo-bts/logging.h>
|
||||||
|
#include <osmo-bts/measurement.h>
|
||||||
|
#include <osmo-bts/scheduler.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 };
|
||||||
|
static const uint8_t ts45008_83_tch_hs0[] = { 0, 2, 4, 6, 52, 54, 56, 58 };
|
||||||
|
static const uint8_t ts45008_83_tch_hs1[] = { 14, 16, 18, 29, 66, 68, 70, 72 };
|
||||||
|
|
||||||
|
/* find out if an array contains a given key as element */
|
||||||
|
#define ARRAY_CONTAINS(arr, val) array_contains(arr, ARRAY_SIZE(arr), val)
|
||||||
|
static bool array_contains(const uint8_t *arr, unsigned int len, uint8_t val) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
if (arr[i] == val)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Decide if a given frame number is part of the "-SUB" measurements (true) or not (false) */
|
||||||
|
static bool ts45008_83_is_sub(struct gsm_lchan *lchan, uint32_t fn, bool is_amr_sid_update)
|
||||||
|
{
|
||||||
|
uint32_t fn104 = fn % 104;
|
||||||
|
|
||||||
|
/* See TS 45.008 Sections 8.3 and 8.4 for a detailed descriptions of the rules
|
||||||
|
* implemented here. We only implement the logic for Voice, not CSD */
|
||||||
|
|
||||||
|
switch (lchan->type) {
|
||||||
|
case GSM_LCHAN_TCH_F:
|
||||||
|
switch (lchan->tch_mode) {
|
||||||
|
case GSM48_CMODE_SIGN:
|
||||||
|
case GSM48_CMODE_SPEECH_V1:
|
||||||
|
case GSM48_CMODE_SPEECH_EFR:
|
||||||
|
if (trx_sched_is_sacch_fn(lchan->ts, fn, true))
|
||||||
|
return true;
|
||||||
|
if (ARRAY_CONTAINS(ts45008_83_tch_f, fn104))
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
|
case GSM48_CMODE_SPEECH_AMR:
|
||||||
|
if (trx_sched_is_sacch_fn(lchan->ts, fn, true))
|
||||||
|
return true;
|
||||||
|
if (is_amr_sid_update)
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOGPFN(DMEAS, LOGL_ERROR, fn, "%s: Unsupported lchan->tch_mode %u\n",
|
||||||
|
gsm_lchan_name(lchan), lchan->tch_mode);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case GSM_LCHAN_TCH_H:
|
||||||
|
switch (lchan->tch_mode) {
|
||||||
|
case GSM48_CMODE_SPEECH_V1:
|
||||||
|
if (trx_sched_is_sacch_fn(lchan->ts, fn, true))
|
||||||
|
return true;
|
||||||
|
switch (lchan->nr) {
|
||||||
|
case 0:
|
||||||
|
if (ARRAY_CONTAINS(ts45008_83_tch_hs0, fn104))
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
if (ARRAY_CONTAINS(ts45008_83_tch_hs1, fn104))
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
OSMO_ASSERT(0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case GSM48_CMODE_SPEECH_AMR:
|
||||||
|
if (trx_sched_is_sacch_fn(lchan->ts, fn, true))
|
||||||
|
return true;
|
||||||
|
if (is_amr_sid_update)
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
|
case GSM48_CMODE_SIGN:
|
||||||
|
/* No DTX allowed; SUB=FULL, therefore measurements at all frame numbers are
|
||||||
|
* SUB */
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
LOGPFN(DMEAS, LOGL_ERROR, fn, "%s: Unsupported lchan->tch_mode %u\n",
|
||||||
|
gsm_lchan_name(lchan), lchan->tch_mode);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case GSM_LCHAN_SDCCH:
|
||||||
|
/* No DTX allowed; SUB=FULL, therefore measurements at all frame numbers are SUB */
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Measurement reporting period and mapping of SACCH message block for TCHF
|
||||||
|
* and TCHH chan As per in 3GPP TS 45.008, section 8.4.1.
|
||||||
|
*
|
||||||
|
* Timeslot number (TN) TDMA frame number (FN) modulo 104
|
||||||
|
* Half rate, Half rate, Reporting SACCH
|
||||||
|
* Full Rate subch.0 subch.1 period Message block
|
||||||
|
* 0 0 and 1 0 to 103 12, 38, 64, 90
|
||||||
|
* 1 0 and 1 13 to 12 25, 51, 77, 103
|
||||||
|
* 2 2 and 3 26 to 25 38, 64, 90, 12
|
||||||
|
* 3 2 and 3 39 to 38 51, 77, 103, 25
|
||||||
|
* 4 4 and 5 52 to 51 64, 90, 12, 38
|
||||||
|
* 5 4 and 5 65 to 64 77, 103, 25, 51
|
||||||
|
* 6 6 and 7 78 to 77 90, 12, 38, 64
|
||||||
|
* 7 6 and 7 91 to 90 103, 25, 51, 77 */
|
||||||
|
|
||||||
|
static const uint8_t tchf_meas_rep_fn104[] = {
|
||||||
|
[0] = 90,
|
||||||
|
[1] = 103,
|
||||||
|
[2] = 12,
|
||||||
|
[3] = 25,
|
||||||
|
[4] = 38,
|
||||||
|
[5] = 51,
|
||||||
|
[6] = 64,
|
||||||
|
[7] = 77,
|
||||||
|
};
|
||||||
|
static const uint8_t tchh0_meas_rep_fn104[] = {
|
||||||
|
[0] = 90,
|
||||||
|
[1] = 90,
|
||||||
|
[2] = 12,
|
||||||
|
[3] = 12,
|
||||||
|
[4] = 38,
|
||||||
|
[5] = 38,
|
||||||
|
[6] = 64,
|
||||||
|
[7] = 64,
|
||||||
|
};
|
||||||
|
static const uint8_t tchh1_meas_rep_fn104[] = {
|
||||||
|
[0] = 103,
|
||||||
|
[1] = 103,
|
||||||
|
[2] = 25,
|
||||||
|
[3] = 25,
|
||||||
|
[4] = 51,
|
||||||
|
[5] = 51,
|
||||||
|
[6] = 77,
|
||||||
|
[7] = 77,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Measurement reporting period for SDCCH8 and SDCCH4 chan
|
||||||
|
* As per in 3GPP TS 45.008, section 8.4.2.
|
||||||
|
*
|
||||||
|
* Logical Chan TDMA frame number
|
||||||
|
* (FN) modulo 102
|
||||||
|
*
|
||||||
|
* SDCCH/8 12 to 11
|
||||||
|
* SDCCH/4 37 to 36
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* FN of the first burst whose block completes before reaching fn%102=11 */
|
||||||
|
static const uint8_t sdcch8_meas_rep_fn102[] = {
|
||||||
|
[0] = 66, /* 15(SDCCH), 47(SACCH), 66(SDCCH) */
|
||||||
|
[1] = 70, /* 19(SDCCH), 51(SACCH), 70(SDCCH) */
|
||||||
|
[2] = 74, /* 23(SDCCH), 55(SACCH), 74(SDCCH) */
|
||||||
|
[3] = 78, /* 27(SDCCH), 59(SACCH), 78(SDCCH) */
|
||||||
|
[4] = 98, /* 31(SDCCH), 98(SACCH), 82(SDCCH) */
|
||||||
|
[5] = 0, /* 35(SDCCH), 0(SACCH), 86(SDCCH) */
|
||||||
|
[6] = 4, /* 39(SDCCH), 4(SACCH), 90(SDCCH) */
|
||||||
|
[7] = 8, /* 43(SDCCH), 8(SACCH), 94(SDCCH) */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* FN of the first burst whose block completes before reaching fn%102=37 */
|
||||||
|
static const uint8_t sdcch4_meas_rep_fn102[] = {
|
||||||
|
[0] = 88, /* 37(SDCCH), 57(SACCH), 88(SDCCH) */
|
||||||
|
[1] = 92, /* 41(SDCCH), 61(SACCH), 92(SDCCH) */
|
||||||
|
[2] = 6, /* 6(SACCH), 47(SDCCH), 98(SDCCH) */
|
||||||
|
[3] = 10 /* 10(SACCH), 0(SDCCH), 51(SDCCH) */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Note: The reporting of the measurement results is done via the SACCH channel.
|
||||||
|
* The measurement interval is not aligned with the interval in which the
|
||||||
|
* SACCH is transmitted. When we receive the measurement indication with the
|
||||||
|
* SACCH block, the corresponding measurement interval will already have ended
|
||||||
|
* and we will get the results late, but on spot with the beginning of the
|
||||||
|
* next measurement interval.
|
||||||
|
*
|
||||||
|
* For example: We get a measurement indication on FN%104=38 in TS=2. Then we
|
||||||
|
* will have to look at 3GPP TS 45.008, section 8.4.1 (or 3GPP TS 05.02 Clause 7
|
||||||
|
* Table 1 of 9) what value we need to feed into the lookup tables in order to
|
||||||
|
* detect the measurement period ending. In this example the "real" ending
|
||||||
|
* was on FN%104=12. This is the value we have to look for in
|
||||||
|
* tchf_meas_rep_fn104 to know that a measurement period has just ended. */
|
||||||
|
|
||||||
|
/* See also 3GPP TS 05.02 Clause 7 Table 1 of 9:
|
||||||
|
* Mapping of logical channels onto physical channels (see subclauses 6.3, 6.4, 6.5) */
|
||||||
|
static uint8_t translate_tch_meas_rep_fn104(uint8_t fn_mod)
|
||||||
|
{
|
||||||
|
switch (fn_mod) {
|
||||||
|
case 25:
|
||||||
|
return 103;
|
||||||
|
case 38:
|
||||||
|
return 12;
|
||||||
|
case 51:
|
||||||
|
return 25;
|
||||||
|
case 64:
|
||||||
|
return 38;
|
||||||
|
case 77:
|
||||||
|
return 51;
|
||||||
|
case 90:
|
||||||
|
return 64;
|
||||||
|
case 103:
|
||||||
|
return 77;
|
||||||
|
case 12:
|
||||||
|
return 90;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Invalid / not of interest */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* determine if a measurement period ends at the given frame number */
|
||||||
|
static int is_meas_complete(struct gsm_lchan *lchan, uint32_t fn)
|
||||||
|
{
|
||||||
|
unsigned int fn_mod = -1;
|
||||||
|
const uint8_t *tbl;
|
||||||
|
int rc = 0;
|
||||||
|
enum gsm_phys_chan_config pchan = ts_pchan(lchan->ts);
|
||||||
|
|
||||||
|
if (lchan->ts->nr >= 8)
|
||||||
|
return -EINVAL;
|
||||||
|
if (pchan >= _GSM_PCHAN_MAX)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
switch (pchan) {
|
||||||
|
case GSM_PCHAN_TCH_F:
|
||||||
|
fn_mod = translate_tch_meas_rep_fn104(fn % 104);
|
||||||
|
if (tchf_meas_rep_fn104[lchan->ts->nr] == fn_mod)
|
||||||
|
rc = 1;
|
||||||
|
break;
|
||||||
|
case GSM_PCHAN_TCH_H:
|
||||||
|
fn_mod = translate_tch_meas_rep_fn104(fn % 104);
|
||||||
|
if (lchan->nr == 0)
|
||||||
|
tbl = tchh0_meas_rep_fn104;
|
||||||
|
else
|
||||||
|
tbl = tchh1_meas_rep_fn104;
|
||||||
|
if (tbl[lchan->ts->nr] == fn_mod)
|
||||||
|
rc = 1;
|
||||||
|
break;
|
||||||
|
case GSM_PCHAN_SDCCH8_SACCH8C:
|
||||||
|
case GSM_PCHAN_SDCCH8_SACCH8C_CBCH:
|
||||||
|
fn_mod = fn % 102;
|
||||||
|
if (sdcch8_meas_rep_fn102[lchan->nr] == fn_mod)
|
||||||
|
rc = 1;
|
||||||
|
break;
|
||||||
|
case GSM_PCHAN_CCCH_SDCCH4:
|
||||||
|
case GSM_PCHAN_CCCH_SDCCH4_CBCH:
|
||||||
|
fn_mod = fn % 102;
|
||||||
|
if (sdcch4_meas_rep_fn102[lchan->nr] == fn_mod)
|
||||||
|
rc = 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
rc = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rc == 1) {
|
||||||
|
DEBUGP(DMEAS,
|
||||||
|
"%s meas period end fn:%u, fn_mod:%i, status:%d, pchan:%s\n",
|
||||||
|
gsm_lchan_name(lchan), fn, fn_mod, rc, gsm_pchan_name(pchan));
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* receive a L1 uplink measurement from L1 */
|
||||||
|
int lchan_new_ul_meas(struct gsm_lchan *lchan, struct bts_ul_meas *ulm, uint32_t fn)
|
||||||
|
{
|
||||||
|
if (lchan->state != LCHAN_S_ACTIVE) {
|
||||||
|
LOGPFN(DMEAS, LOGL_NOTICE, fn,
|
||||||
|
"%s measurement during state: %s, num_ul_meas=%d\n",
|
||||||
|
gsm_lchan_name(lchan), gsm_lchans_name(lchan->state),
|
||||||
|
lchan->meas.num_ul_meas);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lchan->meas.num_ul_meas >= ARRAY_SIZE(lchan->meas.uplink)) {
|
||||||
|
LOGPFN(DMEAS, LOGL_NOTICE, fn,
|
||||||
|
"%s no space for uplink measurement, num_ul_meas=%d\n",
|
||||||
|
gsm_lchan_name(lchan), lchan->meas.num_ul_meas);
|
||||||
|
return -ENOSPC;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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 */
|
||||||
|
if (!ulm->is_sub)
|
||||||
|
ulm->is_sub = ts45008_83_is_sub(lchan, fn, false);
|
||||||
|
|
||||||
|
DEBUGPFN(DMEAS, fn, "%s adding measurement (is_sub=%u), num_ul_meas=%d\n",
|
||||||
|
gsm_lchan_name(lchan), ulm->is_sub, lchan->meas.num_ul_meas);
|
||||||
|
|
||||||
|
memcpy(&lchan->meas.uplink[lchan->meas.num_ul_meas++], ulm,
|
||||||
|
sizeof(*ulm));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* input: BER in steps of .01%, i.e. percent/100 */
|
||||||
|
static uint8_t ber10k_to_rxqual(uint32_t ber10k)
|
||||||
|
{
|
||||||
|
/* Eight levels of Rx quality are defined and are mapped to the
|
||||||
|
* equivalent BER before channel decoding, as per in 3GPP TS 45.008,
|
||||||
|
* secton 8.2.4.
|
||||||
|
*
|
||||||
|
* RxQual: BER Range:
|
||||||
|
* RXQUAL_0 BER < 0,2 % Assumed value = 0,14 %
|
||||||
|
* RXQUAL_1 0,2 % < BER < 0,4 % Assumed value = 0,28 %
|
||||||
|
* RXQUAL_2 0,4 % < BER < 0,8 % Assumed value = 0,57 %
|
||||||
|
* RXQUAL_3 0,8 % < BER < 1,6 % Assumed value = 1,13 %
|
||||||
|
* RXQUAL_4 1,6 % < BER < 3,2 % Assumed value = 2,26 %
|
||||||
|
* RXQUAL_5 3,2 % < BER < 6,4 % Assumed value = 4,53 %
|
||||||
|
* RXQUAL_6 6,4 % < BER < 12,8 % Assumed value = 9,05 %
|
||||||
|
* RXQUAL_7 12,8 % < BER Assumed value = 18,10 % */
|
||||||
|
|
||||||
|
if (ber10k < 20)
|
||||||
|
return 0;
|
||||||
|
if (ber10k < 40)
|
||||||
|
return 1;
|
||||||
|
if (ber10k < 80)
|
||||||
|
return 2;
|
||||||
|
if (ber10k < 160)
|
||||||
|
return 3;
|
||||||
|
if (ber10k < 320)
|
||||||
|
return 4;
|
||||||
|
if (ber10k < 640)
|
||||||
|
return 5;
|
||||||
|
if (ber10k < 1280)
|
||||||
|
return 6;
|
||||||
|
return 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
int lchan_meas_check_compute(struct gsm_lchan *lchan, uint32_t fn)
|
||||||
|
{
|
||||||
|
struct gsm_meas_rep_unidir *mru;
|
||||||
|
uint32_t ber_full_sum = 0;
|
||||||
|
uint32_t irssi_full_sum = 0;
|
||||||
|
uint32_t ber_sub_sum = 0;
|
||||||
|
uint32_t irssi_sub_sum = 0;
|
||||||
|
int32_t ta256b_sum = 0;
|
||||||
|
unsigned int num_meas_sub = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* if measurement period is not complete, abort */
|
||||||
|
if (!is_meas_complete(lchan, fn))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* if there are no measurements, skip computation */
|
||||||
|
if (lchan->meas.num_ul_meas == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* compute the actual measurements */
|
||||||
|
|
||||||
|
/* step 1: add up */
|
||||||
|
for (i = 0; i < lchan->meas.num_ul_meas; i++) {
|
||||||
|
struct bts_ul_meas *m = &lchan->meas.uplink[i];
|
||||||
|
|
||||||
|
ber_full_sum += m->ber10k;
|
||||||
|
irssi_full_sum += m->inv_rssi;
|
||||||
|
ta256b_sum += m->ta_offs_256bits;
|
||||||
|
|
||||||
|
if (m->is_sub) {
|
||||||
|
num_meas_sub++;
|
||||||
|
ber_sub_sum += m->ber10k;
|
||||||
|
irssi_sub_sum += m->inv_rssi;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* step 2: divide */
|
||||||
|
ber_full_sum = ber_full_sum / lchan->meas.num_ul_meas;
|
||||||
|
irssi_full_sum = irssi_full_sum / lchan->meas.num_ul_meas;
|
||||||
|
ta256b_sum = ta256b_sum / lchan->meas.num_ul_meas;
|
||||||
|
|
||||||
|
if (num_meas_sub) {
|
||||||
|
ber_sub_sum = ber_sub_sum / num_meas_sub;
|
||||||
|
irssi_sub_sum = irssi_sub_sum / num_meas_sub;
|
||||||
|
} else {
|
||||||
|
LOGP(DMEAS, LOGL_ERROR, "%s No measurements for SUB!!!\n", gsm_lchan_name(lchan));
|
||||||
|
/* The only situation in which this can occur is if the related uplink burst/block was
|
||||||
|
* missing, so let's set BER to 100% and level to lowest possible. */
|
||||||
|
ber_sub_sum = 10000; /* 100% */
|
||||||
|
irssi_sub_sum = 120; /* -120 dBm */
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGP(DMEAS, LOGL_INFO, "%s Computed TA256(% 4d) BER-FULL(%2u.%02u%%), RSSI-FULL(-%3udBm), "
|
||||||
|
"BER-SUB(%2u.%02u%%), RSSI-SUB(-%3udBm)\n", gsm_lchan_name(lchan),
|
||||||
|
ta256b_sum, ber_full_sum/100,
|
||||||
|
ber_full_sum%100, irssi_full_sum, ber_sub_sum/100, ber_sub_sum%100,
|
||||||
|
irssi_sub_sum);
|
||||||
|
|
||||||
|
/* store results */
|
||||||
|
mru = &lchan->meas.ul_res;
|
||||||
|
mru->full.rx_lev = dbm2rxlev((int)irssi_full_sum * -1);
|
||||||
|
mru->sub.rx_lev = dbm2rxlev((int)irssi_sub_sum * -1);
|
||||||
|
mru->full.rx_qual = ber10k_to_rxqual(ber_full_sum);
|
||||||
|
mru->sub.rx_qual = ber10k_to_rxqual(ber_sub_sum);
|
||||||
|
lchan->meas.ms_toa256 = ta256b_sum;
|
||||||
|
|
||||||
|
LOGP(DMEAS, LOGL_INFO, "%s UL MEAS RXLEV_FULL(%u), RXLEV_SUB(%u),"
|
||||||
|
"RXQUAL_FULL(%u), RXQUAL_SUB(%u), num_meas_sub(%u), num_ul_meas(%u) \n",
|
||||||
|
gsm_lchan_name(lchan),
|
||||||
|
mru->full.rx_lev,
|
||||||
|
mru->sub.rx_lev,
|
||||||
|
mru->full.rx_qual,
|
||||||
|
mru->sub.rx_qual, num_meas_sub, lchan->meas.num_ul_meas);
|
||||||
|
|
||||||
|
lchan->meas.flags |= LC_UL_M_F_RES_VALID;
|
||||||
|
lchan->meas.num_ul_meas = 0;
|
||||||
|
|
||||||
|
/* send a signal indicating computation is complete */
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
@@ -0,0 +1,603 @@
|
|||||||
|
/* (C) 2014 by sysmocom s.f.m.c. GmbH
|
||||||
|
*
|
||||||
|
* 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/dtx_dl_amr_fsm.h>
|
||||||
|
#include <osmo-bts/msg_utils.h>
|
||||||
|
#include <osmo-bts/logging.h>
|
||||||
|
#include <osmo-bts/oml.h>
|
||||||
|
#include <osmo-bts/amr.h>
|
||||||
|
#include <osmo-bts/rsl.h>
|
||||||
|
|
||||||
|
#include <osmocom/gsm/protocol/ipaccess.h>
|
||||||
|
#include <osmocom/gsm/protocol/gsm_12_21.h>
|
||||||
|
#include <osmocom/gsm/abis_nm.h>
|
||||||
|
#include <osmocom/core/msgb.h>
|
||||||
|
#include <osmocom/core/fsm.h>
|
||||||
|
#include <osmocom/trau/osmo_ortp.h>
|
||||||
|
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#define STI_BIT_MASK 16
|
||||||
|
|
||||||
|
static int check_fom(struct abis_om_hdr *omh, size_t len)
|
||||||
|
{
|
||||||
|
if (omh->length != len) {
|
||||||
|
LOGP(DL1C, LOGL_ERROR, "Incorrect OM hdr length value %d %zu\n",
|
||||||
|
omh->length, len);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len < sizeof(struct abis_om_fom_hdr)) {
|
||||||
|
LOGP(DL1C, LOGL_ERROR, "FOM header insufficient space %zu %zu\n",
|
||||||
|
len, sizeof(struct abis_om_fom_hdr));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int check_manuf(struct msgb *msg, struct abis_om_hdr *omh, size_t msg_size)
|
||||||
|
{
|
||||||
|
int type;
|
||||||
|
size_t size;
|
||||||
|
|
||||||
|
if (msg_size < 1) {
|
||||||
|
LOGP(DL1C, LOGL_ERROR, "No ManId Length Indicator %zu\n",
|
||||||
|
msg_size);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (omh->data[0] >= msg_size - 1) {
|
||||||
|
LOGP(DL1C, LOGL_ERROR,
|
||||||
|
"Insufficient message space for this ManId Length %d %zu\n",
|
||||||
|
omh->data[0], msg_size - 1);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (omh->data[0] == sizeof(abis_nm_ipa_magic) &&
|
||||||
|
strncmp(abis_nm_ipa_magic, (const char *)omh->data + 1,
|
||||||
|
sizeof(abis_nm_ipa_magic)) == 0) {
|
||||||
|
type = OML_MSG_TYPE_IPA;
|
||||||
|
size = sizeof(abis_nm_ipa_magic) + 1;
|
||||||
|
} else if (omh->data[0] == sizeof(abis_nm_osmo_magic) &&
|
||||||
|
strncmp(abis_nm_osmo_magic, (const char *) omh->data + 1,
|
||||||
|
sizeof(abis_nm_osmo_magic)) == 0) {
|
||||||
|
type = OML_MSG_TYPE_OSMO;
|
||||||
|
size = sizeof(abis_nm_osmo_magic) + 1;
|
||||||
|
} else {
|
||||||
|
LOGP(DL1C, LOGL_ERROR, "Manuf Label Unknown\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* we have verified that the vendor string fits */
|
||||||
|
msg->l3h = omh->data + size;
|
||||||
|
if (check_fom(omh, msgb_l3len(msg)) != 0)
|
||||||
|
return -1;
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check that DTX is in the middle of silence */
|
||||||
|
static inline bool dtx_is_update(const struct gsm_lchan *lchan)
|
||||||
|
{
|
||||||
|
if (!dtx_dl_amr_enabled(lchan))
|
||||||
|
return false;
|
||||||
|
if (lchan->tch.dtx.dl_amr_fsm->state == ST_SID_U ||
|
||||||
|
lchan->tch.dtx.dl_amr_fsm->state == ST_U_NOINH)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check that DTX is in the beginning of silence for AMR HR */
|
||||||
|
bool dtx_is_first_p1(const struct gsm_lchan *lchan)
|
||||||
|
{
|
||||||
|
if (!dtx_dl_amr_enabled(lchan))
|
||||||
|
return false;
|
||||||
|
if ((lchan->type == GSM_LCHAN_TCH_H &&
|
||||||
|
lchan->tch.dtx.dl_amr_fsm->state == ST_SID_F1))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* update lchan SID status */
|
||||||
|
void lchan_set_marker(bool t, struct gsm_lchan *lchan)
|
||||||
|
{
|
||||||
|
if (t)
|
||||||
|
lchan->tch.dtx.ul_sid = true;
|
||||||
|
else if (lchan->tch.dtx.ul_sid) {
|
||||||
|
lchan->tch.dtx.ul_sid = false;
|
||||||
|
lchan->rtp_tx_marker = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Store the last SID frame in lchan context
|
||||||
|
* \param[in] lchan Logical channel on which we check scheduling
|
||||||
|
* \param[in] l1_payload buffer with SID data
|
||||||
|
* \param[in] length length of l1_payload
|
||||||
|
* \param[in] fn Frame Number for which we check scheduling
|
||||||
|
* \param[in] update 0 if SID_FIRST, 1 if SID_UPDATE, -1 if not AMR SID
|
||||||
|
*/
|
||||||
|
void dtx_cache_payload(struct gsm_lchan *lchan, const uint8_t *l1_payload,
|
||||||
|
size_t length, uint32_t fn, int update)
|
||||||
|
{
|
||||||
|
size_t amr = (update < 0) ? 0 : 2,
|
||||||
|
copy_len = OSMO_MIN(length,
|
||||||
|
ARRAY_SIZE(lchan->tch.dtx.cache) - amr);
|
||||||
|
|
||||||
|
lchan->tch.dtx.len = copy_len + amr;
|
||||||
|
/* SID FIRST is special because it's both sent and cached: */
|
||||||
|
if (update == 0) {
|
||||||
|
lchan->tch.dtx.is_update = false; /* Mark SID FIRST explicitly */
|
||||||
|
/* for non-AMR case - always update FN for incoming SID FIRST */
|
||||||
|
if (!amr || !dtx_is_update(lchan))
|
||||||
|
lchan->tch.dtx.fn = fn;
|
||||||
|
/* for AMR case - do not update FN if SID FIRST arrives in a
|
||||||
|
middle of silence: this should not be happening according to
|
||||||
|
the spec */
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(lchan->tch.dtx.cache + amr, l1_payload, copy_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Check current state of DTX DL AMR FSM and dispatch necessary events
|
||||||
|
* \param[in] lchan Logical channel on which we check scheduling
|
||||||
|
* \param[in] rtp_pl buffer with RTP data
|
||||||
|
* \param[in] rtp_pl_len length of rtp_pl
|
||||||
|
* \param[in] fn Frame Number for which we check scheduling
|
||||||
|
* \param[in] l1_payload buffer where CMR and CMI prefix should be added
|
||||||
|
* \param[in] marker RTP Marker bit
|
||||||
|
* \param[out] len Length of expected L1 payload
|
||||||
|
* \param[out] ft_out Frame Type to be populated after decoding
|
||||||
|
* \returns 0 in case of success; negative on error
|
||||||
|
*/
|
||||||
|
int dtx_dl_amr_fsm_step(struct gsm_lchan *lchan, const uint8_t *rtp_pl,
|
||||||
|
size_t rtp_pl_len, uint32_t fn, uint8_t *l1_payload,
|
||||||
|
bool marker, uint8_t *len, uint8_t *ft_out)
|
||||||
|
{
|
||||||
|
uint8_t cmr;
|
||||||
|
enum osmo_amr_type ft;
|
||||||
|
enum osmo_amr_quality bfi;
|
||||||
|
int8_t sti, cmi;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if (dtx_dl_amr_enabled(lchan)) {
|
||||||
|
if (lchan->type == GSM_LCHAN_TCH_H && !rtp_pl) {
|
||||||
|
/* we're called by gen_empty_tch_msg() to handle states
|
||||||
|
specific to AMR HR DTX */
|
||||||
|
switch (lchan->tch.dtx.dl_amr_fsm->state) {
|
||||||
|
case ST_SID_F2:
|
||||||
|
*len = 3; /* SID-FIRST P1 -> P2 completion */
|
||||||
|
memcpy(l1_payload, lchan->tch.dtx.cache, 2);
|
||||||
|
rc = 0;
|
||||||
|
dtx_dispatch(lchan, E_COMPL);
|
||||||
|
break;
|
||||||
|
case ST_SID_U:
|
||||||
|
rc = -EBADMSG;
|
||||||
|
dtx_dispatch(lchan, E_SID_U);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
rc = -EBADMSG;
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!rtp_pl_len)
|
||||||
|
return -EBADMSG;
|
||||||
|
|
||||||
|
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);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* only needed for old sysmo firmware: */
|
||||||
|
*ft_out = ft;
|
||||||
|
|
||||||
|
/* CMI in downlink tells the L1 encoder which encoding function
|
||||||
|
* it will use, so we have to use the frame type */
|
||||||
|
if (osmo_amr_is_speech(ft))
|
||||||
|
cmi = ft;
|
||||||
|
|
||||||
|
/* populate L1 payload with CMR/CMI - might be ignored by caller: */
|
||||||
|
amr_set_mode_pref(l1_payload, &lchan->tch.amr_mr, cmi, cmr);
|
||||||
|
|
||||||
|
/* populate DTX cache with CMR/CMI - overwrite cache which will be
|
||||||
|
either updated or invalidated by caller anyway: */
|
||||||
|
amr_set_mode_pref(lchan->tch.dtx.cache, &lchan->tch.amr_mr, cmi, cmr);
|
||||||
|
*len = 3 + rtp_pl_len;
|
||||||
|
|
||||||
|
/* DTX DL is not enabled, move along */
|
||||||
|
if (!lchan->ts->trx->bts->dtxd)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (osmo_amr_is_speech(ft)) {
|
||||||
|
/* AMR HR - SID-FIRST_P1 Inhibition */
|
||||||
|
if (marker && lchan->tch.dtx.dl_amr_fsm->state == ST_VOICE)
|
||||||
|
return osmo_fsm_inst_dispatch(lchan->tch.dtx.dl_amr_fsm,
|
||||||
|
E_INHIB, (void *)lchan);
|
||||||
|
|
||||||
|
/* AMR HR - SID-UPDATE Inhibition */
|
||||||
|
if (marker && lchan->type == GSM_LCHAN_TCH_H &&
|
||||||
|
lchan->tch.dtx.dl_amr_fsm->state == ST_SID_U)
|
||||||
|
return osmo_fsm_inst_dispatch(lchan->tch.dtx.dl_amr_fsm,
|
||||||
|
E_INHIB, (void *)lchan);
|
||||||
|
|
||||||
|
/* AMR FR & HR - generic */
|
||||||
|
if (marker && (lchan->tch.dtx.dl_amr_fsm->state == ST_SID_F1 ||
|
||||||
|
lchan->tch.dtx.dl_amr_fsm->state == ST_SID_F2 ||
|
||||||
|
lchan->tch.dtx.dl_amr_fsm->state == ST_U_NOINH))
|
||||||
|
return osmo_fsm_inst_dispatch(lchan->tch.dtx.dl_amr_fsm,
|
||||||
|
E_ONSET, (void *)lchan);
|
||||||
|
|
||||||
|
if (lchan->tch.dtx.dl_amr_fsm->state != ST_VOICE)
|
||||||
|
return osmo_fsm_inst_dispatch(lchan->tch.dtx.dl_amr_fsm,
|
||||||
|
E_VOICE, (void *)lchan);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ft == AMR_SID) {
|
||||||
|
if (lchan->tch.dtx.dl_amr_fsm->state == ST_VOICE) {
|
||||||
|
/* SID FIRST/UPDATE scheduling logic relies on SID FIRST
|
||||||
|
being sent first hence we have to force caching of SID
|
||||||
|
as FIRST regardless of actually decoded type */
|
||||||
|
dtx_cache_payload(lchan, rtp_pl, rtp_pl_len, fn, false);
|
||||||
|
return osmo_fsm_inst_dispatch(lchan->tch.dtx.dl_amr_fsm,
|
||||||
|
sti ? E_SID_U : E_SID_F,
|
||||||
|
(void *)lchan);
|
||||||
|
} else if (lchan->tch.dtx.dl_amr_fsm->state != ST_FACCH)
|
||||||
|
dtx_cache_payload(lchan, rtp_pl, rtp_pl_len, fn, sti);
|
||||||
|
if (lchan->tch.dtx.dl_amr_fsm->state == ST_SID_F2)
|
||||||
|
return osmo_fsm_inst_dispatch(lchan->tch.dtx.dl_amr_fsm,
|
||||||
|
E_COMPL, (void *)lchan);
|
||||||
|
return osmo_fsm_inst_dispatch(lchan->tch.dtx.dl_amr_fsm,
|
||||||
|
sti ? E_SID_U : E_SID_F,
|
||||||
|
(void *)lchan);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ft != AMR_NO_DATA) {
|
||||||
|
LOGP(DRTP, LOGL_ERROR, "unsupported AMR FT 0x%02x\n", ft);
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (marker)
|
||||||
|
osmo_fsm_inst_dispatch(lchan->tch.dtx.dl_amr_fsm, E_VOICE,
|
||||||
|
(void *)lchan);
|
||||||
|
*len = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* STI is located in payload byte 6, cache contains 2 byte prefix (CMR/CMI)
|
||||||
|
* STI set = SID UPDATE, STI unset = SID FIRST
|
||||||
|
*/
|
||||||
|
static inline void dtx_sti_set(struct gsm_lchan *lchan)
|
||||||
|
{
|
||||||
|
lchan->tch.dtx.cache[6 + 2] |= STI_BIT_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void dtx_sti_unset(struct gsm_lchan *lchan)
|
||||||
|
{
|
||||||
|
lchan->tch.dtx.cache[6 + 2] &= ~STI_BIT_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Check if enough time has passed since last SID (if any) to repeat it
|
||||||
|
* \param[in] lchan Logical channel on which we check scheduling
|
||||||
|
* \param[in] fn Frame Number for which we check scheduling
|
||||||
|
* \returns true if transmission can be omitted, false otherwise
|
||||||
|
*/
|
||||||
|
static inline bool dtx_amr_sid_optional(struct gsm_lchan *lchan, uint32_t fn)
|
||||||
|
{
|
||||||
|
if (!dtx_dl_amr_enabled(lchan))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
/* Compute approx. time delta x26 based on Fn duration */
|
||||||
|
uint32_t dx26 = 120 * (fn - lchan->tch.dtx.fn);
|
||||||
|
|
||||||
|
/* We're resuming after FACCH interruption */
|
||||||
|
if (lchan->tch.dtx.dl_amr_fsm->state == ST_FACCH) {
|
||||||
|
/* force STI bit to 0 so cache is treated as SID FIRST */
|
||||||
|
dtx_sti_unset(lchan);
|
||||||
|
lchan->tch.dtx.is_update = false;
|
||||||
|
/* check that this FN has not been used for FACCH message
|
||||||
|
already: we rely here on the order of RTS arrival from L1 - we
|
||||||
|
expect that PH-DATA.req ALWAYS comes before PH-TCH.req for the
|
||||||
|
same FN */
|
||||||
|
if(lchan->type == GSM_LCHAN_TCH_H) {
|
||||||
|
if (lchan->tch.dtx.fn != LCHAN_FN_DUMMY &&
|
||||||
|
lchan->tch.dtx.fn != LCHAN_FN_WAIT) {
|
||||||
|
/* FACCH interruption is over */
|
||||||
|
dtx_dispatch(lchan, E_COMPL);
|
||||||
|
return false;
|
||||||
|
} else if(lchan->tch.dtx.fn == LCHAN_FN_DUMMY) {
|
||||||
|
lchan->tch.dtx.fn = LCHAN_FN_WAIT;
|
||||||
|
} else
|
||||||
|
lchan->tch.dtx.fn = fn;
|
||||||
|
} else if(lchan->type == GSM_LCHAN_TCH_F) {
|
||||||
|
if (lchan->tch.dtx.fn != LCHAN_FN_DUMMY) {
|
||||||
|
/* FACCH interruption is over */
|
||||||
|
dtx_dispatch(lchan, E_COMPL);
|
||||||
|
return false;
|
||||||
|
} else
|
||||||
|
lchan->tch.dtx.fn = fn;
|
||||||
|
}
|
||||||
|
/* this FN was already used for FACCH or ONSET message so we just
|
||||||
|
prepare things for next one */
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lchan->tch.dtx.dl_amr_fsm->state == ST_VOICE)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
/* according to 3GPP TS 26.093 A.5.1.1:
|
||||||
|
(*26) to avoid float math, add 1 FN tolerance (-120) */
|
||||||
|
if (lchan->tch.dtx.is_update) { /* SID UPDATE: every 8th RTP frame */
|
||||||
|
if (dx26 < GSM_RTP_FRAME_DURATION_MS * 8 * 26 - 120)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
/* 3rd frame after SID FIRST should be SID UPDATE */
|
||||||
|
if (dx26 < GSM_RTP_FRAME_DURATION_MS * 3 * 26 - 120)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool fn_chk(const uint8_t *t, uint32_t fn, uint8_t len)
|
||||||
|
{
|
||||||
|
uint8_t i;
|
||||||
|
for (i = 0; i < len; i++)
|
||||||
|
if (fn % 104 == t[i])
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Check if TX scheduling is optional for a given FN in case of DTX
|
||||||
|
* \param[in] lchan Logical channel on which we check scheduling
|
||||||
|
* \param[in] fn Frame Number for which we check scheduling
|
||||||
|
* \returns true if transmission can be omitted, false otherwise
|
||||||
|
*/
|
||||||
|
static inline bool dtx_sched_optional(struct gsm_lchan *lchan, uint32_t fn)
|
||||||
|
{
|
||||||
|
/* According to 3GPP TS 45.008 § 8.3: */
|
||||||
|
static const uint8_t f[] = { 52, 53, 54, 55, 56, 57, 58, 59 },
|
||||||
|
h0[] = { 0, 2, 4, 6, 52, 54, 56, 58 },
|
||||||
|
h1[] = { 14, 16, 18, 20, 66, 68, 70, 72 };
|
||||||
|
if (lchan->tch_mode == GSM48_CMODE_SPEECH_V1) {
|
||||||
|
if (lchan->type == GSM_LCHAN_TCH_F)
|
||||||
|
return fn_chk(f, fn, ARRAY_SIZE(f));
|
||||||
|
else
|
||||||
|
return fn_chk(lchan->nr ? h1 : h0, fn,
|
||||||
|
lchan->nr ? ARRAY_SIZE(h1) :
|
||||||
|
ARRAY_SIZE(h0));
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Check if DTX DL AMR is enabled for a given lchan (it have proper type,
|
||||||
|
* FSM is allocated etc.)
|
||||||
|
* \param[in] lchan Logical channel on which we check scheduling
|
||||||
|
* \returns true if DTX DL AMR is enabled, false otherwise
|
||||||
|
*/
|
||||||
|
bool dtx_dl_amr_enabled(const struct gsm_lchan *lchan)
|
||||||
|
{
|
||||||
|
if (lchan->ts->trx->bts->dtxd &&
|
||||||
|
lchan->tch.dtx.dl_amr_fsm &&
|
||||||
|
lchan->tch_mode == GSM48_CMODE_SPEECH_AMR)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Check if DTX DL AMR FSM state is recursive: requires secondary
|
||||||
|
* response to a single RTS request from L1.
|
||||||
|
* \param[in] lchan Logical channel on which we check scheduling
|
||||||
|
* \returns true if DTX DL AMR FSM state is recursive, false otherwise
|
||||||
|
*/
|
||||||
|
bool dtx_recursion(const struct gsm_lchan *lchan)
|
||||||
|
{
|
||||||
|
if (!dtx_dl_amr_enabled(lchan))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (lchan->tch.dtx.dl_amr_fsm->state == ST_U_INH_V ||
|
||||||
|
lchan->tch.dtx.dl_amr_fsm->state == ST_U_INH_F ||
|
||||||
|
lchan->tch.dtx.dl_amr_fsm->state == ST_U_INH_V_REC ||
|
||||||
|
lchan->tch.dtx.dl_amr_fsm->state == ST_U_INH_F_REC ||
|
||||||
|
lchan->tch.dtx.dl_amr_fsm->state == ST_F1_INH_V ||
|
||||||
|
lchan->tch.dtx.dl_amr_fsm->state == ST_F1_INH_F ||
|
||||||
|
lchan->tch.dtx.dl_amr_fsm->state == ST_F1_INH_V_REC ||
|
||||||
|
lchan->tch.dtx.dl_amr_fsm->state == ST_F1_INH_F_REC ||
|
||||||
|
lchan->tch.dtx.dl_amr_fsm->state == ST_ONSET_F ||
|
||||||
|
lchan->tch.dtx.dl_amr_fsm->state == ST_ONSET_V ||
|
||||||
|
lchan->tch.dtx.dl_amr_fsm->state == ST_ONSET_F_REC ||
|
||||||
|
lchan->tch.dtx.dl_amr_fsm->state == ST_ONSET_V_REC)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Send signal to FSM: with proper check if DIX is enabled for this lchan
|
||||||
|
* \param[in] lchan Logical channel on which we check scheduling
|
||||||
|
* \param[in] e DTX DL AMR FSM Event
|
||||||
|
*/
|
||||||
|
void dtx_dispatch(struct gsm_lchan *lchan, enum dtx_dl_amr_fsm_events e)
|
||||||
|
{
|
||||||
|
if (dtx_dl_amr_enabled(lchan))
|
||||||
|
osmo_fsm_inst_dispatch(lchan->tch.dtx.dl_amr_fsm, e,
|
||||||
|
(void *)lchan);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Send internal signal to FSM: check that DTX is enabled for this chan,
|
||||||
|
* check that current FSM and lchan states are permitting such signal.
|
||||||
|
* Note: this should be the only way to dispatch E_COMPL to FSM from
|
||||||
|
* BTS code.
|
||||||
|
* \param[in] lchan Logical channel on which we check scheduling
|
||||||
|
*/
|
||||||
|
void dtx_int_signal(struct gsm_lchan *lchan)
|
||||||
|
{
|
||||||
|
if (!dtx_dl_amr_enabled(lchan))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (dtx_is_first_p1(lchan) || dtx_recursion(lchan))
|
||||||
|
dtx_dispatch(lchan, E_COMPL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Repeat last SID if possible in case of DTX
|
||||||
|
* \param[in] lchan Logical channel on which we check scheduling
|
||||||
|
* \param[in] dst Buffer to copy last SID into
|
||||||
|
* \returns Number of bytes copied + 1 (to accommodate for extra byte with
|
||||||
|
* payload type), 0 if there's nothing to copy
|
||||||
|
*/
|
||||||
|
uint8_t repeat_last_sid(struct gsm_lchan *lchan, uint8_t *dst, uint32_t fn)
|
||||||
|
{
|
||||||
|
/* FIXME: add EFR support */
|
||||||
|
if (lchan->tch_mode == GSM48_CMODE_SPEECH_EFR)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (lchan->tch_mode != GSM48_CMODE_SPEECH_AMR) {
|
||||||
|
if (dtx_sched_optional(lchan, fn))
|
||||||
|
return 0;
|
||||||
|
} else
|
||||||
|
if (dtx_amr_sid_optional(lchan, fn))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (lchan->tch.dtx.len) {
|
||||||
|
if (dtx_dl_amr_enabled(lchan)) {
|
||||||
|
if ((lchan->type == GSM_LCHAN_TCH_H &&
|
||||||
|
lchan->tch.dtx.dl_amr_fsm->state == ST_SID_F2) ||
|
||||||
|
(lchan->type == GSM_LCHAN_TCH_F &&
|
||||||
|
lchan->tch.dtx.dl_amr_fsm->state == ST_SID_F1)) {
|
||||||
|
/* advance FSM in case we've just sent SID FIRST
|
||||||
|
to restore silence after FACCH interruption */
|
||||||
|
osmo_fsm_inst_dispatch(lchan->tch.dtx.dl_amr_fsm,
|
||||||
|
E_SID_U, (void *)lchan);
|
||||||
|
dtx_sti_unset(lchan);
|
||||||
|
} else if (dtx_is_update(lchan)) {
|
||||||
|
/* enforce SID UPDATE for next repetition: it
|
||||||
|
might have been altered by FACCH handling */
|
||||||
|
dtx_sti_set(lchan);
|
||||||
|
if (lchan->type == GSM_LCHAN_TCH_H &&
|
||||||
|
lchan->tch.dtx.dl_amr_fsm->state ==
|
||||||
|
ST_U_NOINH)
|
||||||
|
osmo_fsm_inst_dispatch(lchan->tch.dtx.dl_amr_fsm,
|
||||||
|
E_COMPL,
|
||||||
|
(void *)lchan);
|
||||||
|
lchan->tch.dtx.is_update = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
memcpy(dst, lchan->tch.dtx.cache, lchan->tch.dtx.len);
|
||||||
|
lchan->tch.dtx.fn = 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));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return 0 in case the IPA structure is okay and in this
|
||||||
|
* case the l2h will be set to the beginning of the data.
|
||||||
|
*/
|
||||||
|
int msg_verify_ipa_structure(struct msgb *msg)
|
||||||
|
{
|
||||||
|
struct ipaccess_head *hh;
|
||||||
|
|
||||||
|
if (msgb_l1len(msg) < sizeof(struct ipaccess_head)) {
|
||||||
|
LOGP(DL1C, LOGL_ERROR,
|
||||||
|
"Ipa header insufficient space %d %zu\n",
|
||||||
|
msgb_l1len(msg), sizeof(struct ipaccess_head));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
hh = (struct ipaccess_head *) msg->l1h;
|
||||||
|
|
||||||
|
if (ntohs(hh->len) != msgb_l1len(msg) - sizeof(struct ipaccess_head)) {
|
||||||
|
LOGP(DL1C, LOGL_ERROR,
|
||||||
|
"Incorrect ipa header msg size %d %zu\n",
|
||||||
|
ntohs(hh->len), msgb_l1len(msg) - sizeof(struct ipaccess_head));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hh->proto == IPAC_PROTO_OSMO) {
|
||||||
|
struct ipaccess_head_ext *hh_ext = (struct ipaccess_head_ext *) hh->data;
|
||||||
|
if (ntohs(hh->len) < sizeof(*hh_ext)) {
|
||||||
|
LOGP(DL1C, LOGL_ERROR, "IPA length shorter than OSMO header\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
msg->l2h = hh_ext->data;
|
||||||
|
} else
|
||||||
|
msg->l2h = hh->data;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Verify the structure of the OML message and set l3h
|
||||||
|
*
|
||||||
|
* This function verifies that the data in \param in msg is a proper
|
||||||
|
* OML message. This code assumes that msg->l2h points to the
|
||||||
|
* beginning of the OML message. In the successful case the msg->l3h
|
||||||
|
* will be set and will point to the FOM header. The value is undefined
|
||||||
|
* in all other cases.
|
||||||
|
*
|
||||||
|
* \param msg The message to analyze starting from msg->l2h.
|
||||||
|
* \return In case the structure is correct a positive number will be
|
||||||
|
* returned and msg->l3h will point to the FOM. The number is a
|
||||||
|
* classification of the vendor type of the message.
|
||||||
|
*/
|
||||||
|
int msg_verify_oml_structure(struct msgb *msg)
|
||||||
|
{
|
||||||
|
struct abis_om_hdr *omh;
|
||||||
|
|
||||||
|
if (msgb_l2len(msg) < sizeof(*omh)) {
|
||||||
|
LOGP(DL1C, LOGL_ERROR, "Om header insufficient space %d %zu\n",
|
||||||
|
msgb_l2len(msg), sizeof(*omh));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
omh = (struct abis_om_hdr *) msg->l2h;
|
||||||
|
if (omh->mdisc != ABIS_OM_MDISC_FOM &&
|
||||||
|
omh->mdisc != ABIS_OM_MDISC_MANUF) {
|
||||||
|
LOGP(DL1C, LOGL_ERROR, "Incorrect om mdisc value %x\n",
|
||||||
|
omh->mdisc);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (omh->placement != ABIS_OM_PLACEMENT_ONLY) {
|
||||||
|
LOGP(DL1C, LOGL_ERROR, "Incorrect om placement value %x %x\n",
|
||||||
|
omh->placement, ABIS_OM_PLACEMENT_ONLY);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (omh->sequence != 0) {
|
||||||
|
LOGP(DL1C, LOGL_ERROR, "Incorrect om sequence value %d\n",
|
||||||
|
omh->sequence);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (omh->mdisc == ABIS_OM_MDISC_MANUF)
|
||||||
|
return check_manuf(msg, omh, msgb_l2len(msg) - sizeof(*omh));
|
||||||
|
|
||||||
|
msg->l3h = omh->data;
|
||||||
|
if (check_fom(omh, msgb_l3len(msg)) != 0)
|
||||||
|
return -1;
|
||||||
|
return OML_MSG_TYPE_ETSI;
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user