mirror of
https://gitea.osmocom.org/cellular-infrastructure/osmo-mgw.git
synced 2025-11-02 13:03:33 +00:00
Compare commits
403 Commits
openbsc/0.
...
openbsc/0.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
955c3d1894 | ||
|
|
afb883956d | ||
|
|
6990687f4c | ||
|
|
44016fee14 | ||
|
|
1f0c5b4742 | ||
|
|
74e61110e5 | ||
|
|
6ea7e777f5 | ||
|
|
cdba04978d | ||
|
|
0e939fec42 | ||
|
|
ab3bb9d444 | ||
|
|
d011c91512 | ||
|
|
88ad7723b4 | ||
|
|
dfdf8d929a | ||
|
|
9212d9d636 | ||
|
|
9ec030d32d | ||
|
|
a9e9331285 | ||
|
|
7b07b2dcff | ||
|
|
86c1db6338 | ||
|
|
ed500e3877 | ||
|
|
7e0cc50e44 | ||
|
|
867d69bbcb | ||
|
|
ec1921dfa3 | ||
|
|
b62b12398b | ||
|
|
11762459e8 | ||
|
|
00c805f213 | ||
|
|
37ac420254 | ||
|
|
6a458eac2c | ||
|
|
6c79a68103 | ||
|
|
ca8f3b59c1 | ||
|
|
21bbda242e | ||
|
|
4d54d0b883 | ||
|
|
5ec26fe983 | ||
|
|
f358964fb2 | ||
|
|
91fa850791 | ||
|
|
4446b3bf34 | ||
|
|
6e1a676e21 | ||
|
|
8dcebd3e7f | ||
|
|
64c07d213c | ||
|
|
b01bf33ad4 | ||
|
|
e925205c28 | ||
|
|
da87154093 | ||
|
|
ebec58e8ba | ||
|
|
59eee42b05 | ||
|
|
face7edc62 | ||
|
|
a0fe72de6f | ||
|
|
fdb71949db | ||
|
|
d88a3878cc | ||
|
|
9c0958bf4c | ||
|
|
a02085dab0 | ||
|
|
a8e6a652ca | ||
|
|
b7eebf8699 | ||
|
|
c4989a8e5e | ||
|
|
9f0866c2a3 | ||
|
|
bd3137c2dd | ||
|
|
15ccc77f62 | ||
|
|
82b03a1f2b | ||
|
|
cca849a825 | ||
|
|
0896b50197 | ||
|
|
909212fc87 | ||
|
|
c834b70d04 | ||
|
|
174a51a761 | ||
|
|
b3d70fd0bd | ||
|
|
dcf42e6cd2 | ||
|
|
334c5ab2e6 | ||
|
|
b0ec9e3dae | ||
|
|
8bcb1a0a99 | ||
|
|
0741ffe69f | ||
|
|
56ee6b8075 | ||
|
|
563d316106 | ||
|
|
8024d8ff58 | ||
|
|
8d4a472cc4 | ||
|
|
810e32394d | ||
|
|
6fec79da18 | ||
|
|
51c8238024 | ||
|
|
e1d5eca916 | ||
|
|
7354107946 | ||
|
|
bc867d9a17 | ||
|
|
9a311ec25e | ||
|
|
b80e14e567 | ||
|
|
03cc8a810b | ||
|
|
db44f6012d | ||
|
|
09cefee4db | ||
|
|
a4898a868b | ||
|
|
1a00d823b3 | ||
|
|
00ee4b78db | ||
|
|
44f04da379 | ||
|
|
95aa5c4ae3 | ||
|
|
f27d043032 | ||
|
|
f338a03b0c | ||
|
|
f3956cbb20 | ||
|
|
fb9e06f310 | ||
|
|
c471d3d8a2 | ||
|
|
5e106d7765 | ||
|
|
36f98d9c53 | ||
|
|
b63c3639eb | ||
|
|
62d460301b | ||
|
|
4ee2eaf3c4 | ||
|
|
8fc66a0c4d | ||
|
|
1458ec6571 | ||
|
|
d38f10593a | ||
|
|
0ae575536a | ||
|
|
716d2a47b2 | ||
|
|
0abc11a0d0 | ||
|
|
50d369e1a9 | ||
|
|
ca17ef88f5 | ||
|
|
1dd68c3d0f | ||
|
|
ba0db5b7f3 | ||
|
|
d273529a8d | ||
|
|
e1de69af7e | ||
|
|
7e859bc17c | ||
|
|
30fe64165b | ||
|
|
cd8b86f124 | ||
|
|
69245a0496 | ||
|
|
cc2bc35f2c | ||
|
|
17289eda65 | ||
|
|
b1cb8eb7a6 | ||
|
|
d105e2048a | ||
|
|
bc6649e942 | ||
|
|
b5ddc184ff | ||
|
|
f933de97ba | ||
|
|
98c98547d0 | ||
|
|
07bb0daaff | ||
|
|
889f16eac3 | ||
|
|
fefb52361a | ||
|
|
3016d9f299 | ||
|
|
5455243306 | ||
|
|
a61c709ef0 | ||
|
|
6e94d6d10d | ||
|
|
3fbd244187 | ||
|
|
b549ddfb04 | ||
|
|
05bbec7227 | ||
|
|
91f587ed98 | ||
|
|
1761d02ddb | ||
|
|
934676e158 | ||
|
|
7bbaefb349 | ||
|
|
64bb754b40 | ||
|
|
da0a99ab0d | ||
|
|
95932e7bd0 | ||
|
|
aace9fc9b9 | ||
|
|
7a69cf0a98 | ||
|
|
4bf40c090d | ||
|
|
18b590de4a | ||
|
|
32c0962b10 | ||
|
|
9b5f1d7b43 | ||
|
|
3b0fd2b0b9 | ||
|
|
8e3f0e7185 | ||
|
|
cdfcbee53b | ||
|
|
c464491b0b | ||
|
|
368a0a73d4 | ||
|
|
45c2184c7e | ||
|
|
f43f2fce82 | ||
|
|
9f239a2a0f | ||
|
|
6adac17a10 | ||
|
|
49b3ed2226 | ||
|
|
182c81f04e | ||
|
|
90c0aff174 | ||
|
|
52ffb922c4 | ||
|
|
451eb29e37 | ||
|
|
763b42a92a | ||
|
|
68c3bf6de8 | ||
|
|
c02b12086c | ||
|
|
fc857414ae | ||
|
|
ebdd3cbd89 | ||
|
|
ffccb77df0 | ||
|
|
f72b3d51fc | ||
|
|
c29043ea24 | ||
|
|
701076e9d3 | ||
|
|
96e9f08101 | ||
|
|
79eff7eeff | ||
|
|
583e9aef33 | ||
|
|
dc53af6721 | ||
|
|
725966d9b4 | ||
|
|
8e3eb584a8 | ||
|
|
b56a6bbc55 | ||
|
|
50c5ff7b94 | ||
|
|
ebd50a6fd2 | ||
|
|
f1ba09b2e6 | ||
|
|
1cc7184bc9 | ||
|
|
02d45c00f5 | ||
|
|
f4152d1025 | ||
|
|
54146271b6 | ||
|
|
913bc032b9 | ||
|
|
59234a3eb2 | ||
|
|
6c4d2443b4 | ||
|
|
04d362f79d | ||
|
|
6349b7f15e | ||
|
|
624e89d3f7 | ||
|
|
b854b29e32 | ||
|
|
f0901f0067 | ||
|
|
91c59c8cb5 | ||
|
|
eb76c7a93f | ||
|
|
0d6f930785 | ||
|
|
02d9966053 | ||
|
|
ea057d9350 | ||
|
|
29b64e9708 | ||
|
|
04dc88fb9d | ||
|
|
371efe5955 | ||
|
|
49a2ddeec0 | ||
|
|
e8e432dd59 | ||
|
|
fea236e27c | ||
|
|
31bbbf4e52 | ||
|
|
76556376c3 | ||
|
|
3e6376d20d | ||
|
|
081e14d071 | ||
|
|
e6da14fde4 | ||
|
|
54209c2dce | ||
|
|
9af6ddfcec | ||
|
|
08eebd59b7 | ||
|
|
9ae7b29e3a | ||
|
|
59f787a4c1 | ||
|
|
8ce8d3a00d | ||
|
|
cfcf7e84bd | ||
|
|
f64a20f2e8 | ||
|
|
9d3e2ec698 | ||
|
|
c839667324 | ||
|
|
019d0167b6 | ||
|
|
c728eeaf9b | ||
|
|
a9b473a3c2 | ||
|
|
3357add225 | ||
|
|
c407ba5ed2 | ||
|
|
5479fc80d5 | ||
|
|
203845730f | ||
|
|
f7e2389eb6 | ||
|
|
a37e3bc39a | ||
|
|
a3a659ba5c | ||
|
|
445e615d03 | ||
|
|
994dcbb201 | ||
|
|
7e59c83d66 | ||
|
|
4dcc5e5f8a | ||
|
|
3c6f6c25a6 | ||
|
|
7a0e166fb0 | ||
|
|
81c0e2582f | ||
|
|
17164061a6 | ||
|
|
11b28f9c26 | ||
|
|
04144c1905 | ||
|
|
0eb7666efa | ||
|
|
41c5aaf62c | ||
|
|
69ac83dd54 | ||
|
|
9d277d3b33 | ||
|
|
e3018c7ad6 | ||
|
|
dd715bd2ee | ||
|
|
73b878a85a | ||
|
|
812dad0ff7 | ||
|
|
e25445b864 | ||
|
|
3d76e44968 | ||
|
|
d3baf415b1 | ||
|
|
ee139e7253 | ||
|
|
abd0cac0c5 | ||
|
|
c577ca1822 | ||
|
|
ae9006aeed | ||
|
|
f694d5f47a | ||
|
|
daee5ca7c1 | ||
|
|
a29e43a26f | ||
|
|
75e2defc7f | ||
|
|
eafe22ca72 | ||
|
|
2cafc4b309 | ||
|
|
3a3c277b70 | ||
|
|
b29cea1d9c | ||
|
|
712ddbcd72 | ||
|
|
85bded8b50 | ||
|
|
cd103a9a5d | ||
|
|
026b4cab36 | ||
|
|
127af34eea | ||
|
|
274d015cbb | ||
|
|
f6bd340df6 | ||
|
|
985263e55f | ||
|
|
082b01f18e | ||
|
|
c9f499f7d3 | ||
|
|
86dda08762 | ||
|
|
2862dcac58 | ||
|
|
d0d2b0b605 | ||
|
|
53cd7ac44c | ||
|
|
d4e6872d6c | ||
|
|
434bb3f39f | ||
|
|
7ce5e259c9 | ||
|
|
f93e8fabd8 | ||
|
|
6003d6b928 | ||
|
|
28dcbc5ee5 | ||
|
|
c5faf66b82 | ||
|
|
3547045c73 | ||
|
|
e2fee354cf | ||
|
|
c7782dec4a | ||
|
|
ceeddf87f5 | ||
|
|
d49fc5ae24 | ||
|
|
d85642a1a7 | ||
|
|
6f615551a4 | ||
|
|
39e6ba09c2 | ||
|
|
c7a1a1fd2e | ||
|
|
d9cdd056ff | ||
|
|
2391b4c474 | ||
|
|
90cdd28e6f | ||
|
|
63dbfc6a2b | ||
|
|
f604bba026 | ||
|
|
ec073e9f5b | ||
|
|
230cd6a720 | ||
|
|
5f5189e658 | ||
|
|
f751a10018 | ||
|
|
7e72fa0250 | ||
|
|
df30d40b98 | ||
|
|
98b53cba06 | ||
|
|
81a8bf1039 | ||
|
|
12e373c218 | ||
|
|
3f16da2032 | ||
|
|
8a31a3fcee | ||
|
|
5a86e06eb3 | ||
|
|
0fbfd1bb52 | ||
|
|
567c8dc7c9 | ||
|
|
c7ff2572a7 | ||
|
|
1e24550d3d | ||
|
|
67706df7c2 | ||
|
|
e0b06b0293 | ||
|
|
6d42dbe35c | ||
|
|
db2c28aef6 | ||
|
|
318105d58d | ||
|
|
a36f0ede25 | ||
|
|
0326cd5ac9 | ||
|
|
3b71247cd0 | ||
|
|
fbceea4f0f | ||
|
|
414bc4a1f4 | ||
|
|
cf6f71aa7f | ||
|
|
70c232f75a | ||
|
|
bb62b3f053 | ||
|
|
625b6e4dab | ||
|
|
d283db496f | ||
|
|
e17c030b76 | ||
|
|
dab8e27755 | ||
|
|
e19d6fc1ee | ||
|
|
09a925b117 | ||
|
|
e9f7a0d3b9 | ||
|
|
b4e72f881c | ||
|
|
16e958dc68 | ||
|
|
9c838ae069 | ||
|
|
b79c3c97a2 | ||
|
|
620c2e678a | ||
|
|
dbc698aef0 | ||
|
|
50c579b8c5 | ||
|
|
fae3c65938 | ||
|
|
f1f57a84c1 | ||
|
|
863a55d44d | ||
|
|
890dfc58ed | ||
|
|
3485feb49b | ||
|
|
cf256d678f | ||
|
|
933daaa016 | ||
|
|
af4b5fb13e | ||
|
|
57d304871e | ||
|
|
00f4cc22c8 | ||
|
|
ca5c022a32 | ||
|
|
c97d9b4df1 | ||
|
|
7e9010892d | ||
|
|
b8781d2cd5 | ||
|
|
9b17c769b9 | ||
|
|
2a8675e49a | ||
|
|
52d42abdb7 | ||
|
|
a54732d19d | ||
|
|
d65305f5b4 | ||
|
|
5bb874d2f5 | ||
|
|
cc48fb8083 | ||
|
|
46c5ab3624 | ||
|
|
e46f1d6cc4 | ||
|
|
c2b3270e93 | ||
|
|
c8166f3a91 | ||
|
|
58f2cf6494 | ||
|
|
da488ae343 | ||
|
|
2d2c910f2c | ||
|
|
4582586e24 | ||
|
|
7225fd18e0 | ||
|
|
1999cf11b9 | ||
|
|
77cd95d5b5 | ||
|
|
f05750ca24 | ||
|
|
abf962b096 | ||
|
|
8d216c7756 | ||
|
|
a2e5cb8601 | ||
|
|
a2828fa4bc | ||
|
|
088dde8173 | ||
|
|
7e50c8140b | ||
|
|
8d380dcadd | ||
|
|
2603c1f545 | ||
|
|
4be7d41a50 | ||
|
|
2f169d64dd | ||
|
|
45b575fd94 | ||
|
|
66dcd925c6 | ||
|
|
46caa3048d | ||
|
|
b094171c9f | ||
|
|
e1996f013c | ||
|
|
6c199e7d99 | ||
|
|
fce9307553 | ||
|
|
05c68841a8 | ||
|
|
85334f1309 | ||
|
|
8dfd241bc6 | ||
|
|
d740b688dc | ||
|
|
928ca743db | ||
|
|
8cc59036e6 | ||
|
|
ecd94a4b45 | ||
|
|
0b369c582b | ||
|
|
5652cfc0e8 | ||
|
|
1406977e7e | ||
|
|
f3d1ae7072 | ||
|
|
0425c38feb | ||
|
|
7bf66c5a6e | ||
|
|
fe16622bf5 | ||
|
|
45f9e69ac5 | ||
|
|
4de1116356 | ||
|
|
5b848f37cf |
2
openbsc/.gitignore
vendored
2
openbsc/.gitignore
vendored
@@ -9,6 +9,7 @@ openbsc.pc
|
||||
bsc_hack
|
||||
bsc_msc_ip
|
||||
bsc_mgcp
|
||||
src/bsc/osmo-bsc
|
||||
*.*~
|
||||
*.sw?
|
||||
|
||||
@@ -49,3 +50,4 @@ tests/sccp/sccp_test
|
||||
tests/sms/sms_test
|
||||
tests/timer/timer_test
|
||||
|
||||
src/openbsc.cfg*
|
||||
|
||||
850
openbsc/COPYING
850
openbsc/COPYING
@@ -1,285 +1,624 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
GNU AFFERO GENERAL PUBLIC LICENSE
|
||||
Version 3, 19 November 2007
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
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
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
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
|
||||
this service 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.
|
||||
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.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
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.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
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.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
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.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
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.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
0. Definitions.
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
"This License" refers to version 3 of the GNU Affero General Public License.
|
||||
|
||||
1. You may copy and distribute 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 and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
"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.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
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) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
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.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
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.
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
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.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
1. Source Code.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
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.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
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.
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
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.
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
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.
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
2. Basic Permissions.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
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.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
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.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
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.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
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
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
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.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
13. Remote Network Interaction; Use with the GNU General Public License.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
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.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
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.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
14. Revised Versions of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the 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
|
||||
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 a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
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.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
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.
|
||||
|
||||
NO WARRANTY
|
||||
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.
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 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.
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE 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.
|
||||
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.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
16. Limitation of Liability.
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
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
|
||||
@@ -287,53 +626,36 @@ 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
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
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 General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
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.
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
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 the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
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.
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
||||
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/>.
|
||||
|
||||
@@ -44,10 +44,12 @@ AC_ARG_ENABLE([osmo-bsc], [AS_HELP_STRING([--enable-osmo-bsc], [Build the Osmo B
|
||||
AM_CONDITIONAL(BUILD_BSC, test "x$osmo_ac_build_bsc" = "xyes")
|
||||
|
||||
PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 0.1.27)
|
||||
PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 0.1.19)
|
||||
PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 0.1.28)
|
||||
|
||||
dnl checks for header files
|
||||
AC_HEADER_STDC
|
||||
AC_CHECK_HEADERS(dahdi/user.h,,AC_MSG_WARN(DAHDI input driver will not be built))
|
||||
|
||||
|
||||
dnl Checks for typedefs, structures and compiler characteristics
|
||||
|
||||
@@ -62,6 +64,20 @@ AC_COMPILE_IFELSE([char foo;],
|
||||
CFLAGS="$saved_CFLAGS"
|
||||
AC_SUBST(SYMBOL_VISIBILITY)
|
||||
|
||||
# Coverage build taken from WebKit's configure.in
|
||||
AC_MSG_CHECKING([whether to enable code coverage support])
|
||||
AC_ARG_ENABLE(coverage,
|
||||
AC_HELP_STRING([--enable-coverage],
|
||||
[enable code coverage support [default=no]]),
|
||||
[],[enable_coverage="no"])
|
||||
AC_MSG_RESULT([$enable_coverage])
|
||||
if test "$enable_coverage" = "yes"; then
|
||||
COVERAGE_CFLAGS="-ftest-coverage -fprofile-arcs"
|
||||
COVERAGE_LDFLAGS="-ftest-coverage -fprofile-arcs"
|
||||
AC_SUBST([COVERAGE_CFLAGS])
|
||||
AC_SUBST([COVERAGE_LDFLAGS])
|
||||
fi
|
||||
|
||||
|
||||
dnl Generate the output
|
||||
AM_CONFIG_HEADER(bscconfig.h)
|
||||
@@ -81,4 +97,5 @@ AC_OUTPUT(
|
||||
tests/db/Makefile
|
||||
tests/channel/Makefile
|
||||
tests/bsc-nat/Makefile
|
||||
tests/mgcp/Makefile
|
||||
Makefile)
|
||||
|
||||
1
openbsc/contrib/bsc-test/README
Normal file
1
openbsc/contrib/bsc-test/README
Normal file
@@ -0,0 +1 @@
|
||||
Some crazy scripts call testing... and MSC link failure simulation
|
||||
8
openbsc/contrib/bsc-test/all_dial
Normal file
8
openbsc/contrib/bsc-test/all_dial
Normal file
@@ -0,0 +1,8 @@
|
||||
ABORT BUSY
|
||||
ABORT 'NO CARRIER'
|
||||
ABORT 'OK'
|
||||
|
||||
'' AT
|
||||
SAY "Dialing a number\n"
|
||||
'OK' ATD05660066;
|
||||
|
||||
11
openbsc/contrib/bsc-test/dial.sh
Executable file
11
openbsc/contrib/bsc-test/dial.sh
Executable file
@@ -0,0 +1,11 @@
|
||||
#!/bin/sh
|
||||
# Evil dial script..
|
||||
|
||||
while true;
|
||||
do
|
||||
chat -v -f all_dial < /dev/ttyACM0 > /dev/ttyACM0
|
||||
sleep 5s
|
||||
chat -v -f hangup < /dev/ttyACM0 > /dev/ttyACM0
|
||||
sleep 2s
|
||||
done
|
||||
|
||||
6
openbsc/contrib/bsc-test/drop-oml.sh
Executable file
6
openbsc/contrib/bsc-test/drop-oml.sh
Executable file
@@ -0,0 +1,6 @@
|
||||
#!/bin/sh
|
||||
sleep 3
|
||||
echo "enable"
|
||||
sleep 1
|
||||
echo "drop bts connection 0 oml"
|
||||
sleep 1
|
||||
8
openbsc/contrib/bsc-test/drop.sh
Executable file
8
openbsc/contrib/bsc-test/drop.sh
Executable file
@@ -0,0 +1,8 @@
|
||||
#!/bin/sh
|
||||
|
||||
while true;
|
||||
do
|
||||
echo "Going to drop the OML connection"
|
||||
./drop-oml.sh | telnet 127.0.0.1 4242
|
||||
sleep 58m
|
||||
done
|
||||
4
openbsc/contrib/bsc-test/hangup
Normal file
4
openbsc/contrib/bsc-test/hangup
Normal file
@@ -0,0 +1,4 @@
|
||||
TIMEOUT 10
|
||||
'' ^Z
|
||||
SAY "Waiting for hangup confirm\n"
|
||||
'' ATH;
|
||||
8
openbsc/contrib/bsc-test/msc.sh
Executable file
8
openbsc/contrib/bsc-test/msc.sh
Executable file
@@ -0,0 +1,8 @@
|
||||
#!/bin/sh
|
||||
|
||||
while true;
|
||||
do
|
||||
echo "Kill the osmo-bsc"
|
||||
/usr/bin/kill -s SIGUSR2 `pidof osmo-bsc`
|
||||
sleep 58s
|
||||
done
|
||||
66
openbsc/contrib/sms/fill-hlr.st
Normal file
66
openbsc/contrib/sms/fill-hlr.st
Normal file
@@ -0,0 +1,66 @@
|
||||
"I create output for some simple SQL statements for the HLR db"
|
||||
|
||||
|
||||
Eval [
|
||||
|
||||
"Create tables if they don't exist"
|
||||
Transcript show: 'CREATE TABLE SMS (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
created TIMESTAMP NOT NULL,
|
||||
sent TIMESTAMP,
|
||||
sender_id INTEGER NOT NULL,
|
||||
receiver_id INTEGER NOT NULL,
|
||||
deliver_attempts INTEGER NOT NULL DEFAULT 0,
|
||||
valid_until TIMESTAMP,
|
||||
reply_path_req INTEGER NOT NULL,
|
||||
status_rep_req INTEGER NOT NULL,
|
||||
protocol_id INTEGER NOT NULL,
|
||||
data_coding_scheme INTEGER NOT NULL,
|
||||
ud_hdr_ind INTEGER NOT NULL,
|
||||
dest_addr TEXT,
|
||||
user_data BLOB,
|
||||
header BLOB,
|
||||
text TEXT);'; nl;
|
||||
show: 'CREATE TABLE Subscriber (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
created TIMESTAMP NOT NULL,
|
||||
updated TIMESTAMP NOT NULL,
|
||||
imsi NUMERIC UNIQUE NOT NULL,
|
||||
name TEXT,
|
||||
extension TEXT UNIQUE,
|
||||
authorized INTEGER NOT NULL DEFAULT 0,
|
||||
tmsi TEXT UNIQUE,
|
||||
lac INTEGER NOT NULL DEFAULT 0);'; nl.
|
||||
|
||||
"Create some dummy subscribers"
|
||||
num_sub := 1000.
|
||||
num_sms := 30.
|
||||
lac := 1.
|
||||
|
||||
Transcript show: 'BEGIN;'; nl.
|
||||
|
||||
1 to: num_sub do: [:each |
|
||||
Transcript show: 'INSERT INTO Subscriber
|
||||
(imsi, created, updated, authorized, lac, extension)
|
||||
VALUES
|
||||
(%1, datetime(''now''), datetime(''now''), 1, %2, %3);' %
|
||||
{(274090000000000 + each). lac. each}; nl.
|
||||
].
|
||||
|
||||
1 to: num_sms do: [:sms |
|
||||
1 to: num_sub do: [:sub |
|
||||
Transcript show: 'INSERT INTO SMS
|
||||
(created, sender_id, receiver_id, valid_until,
|
||||
reply_path_req, status_rep_req, protocol_id,
|
||||
data_coding_scheme, ud_hdr_ind, dest_addr,
|
||||
text) VALUES
|
||||
(datetime(''now''), 1, %1, ''2222-2-2'',
|
||||
0, 0, 0,
|
||||
0, 0, ''123456'',
|
||||
''abc'');' % {sub}; nl.
|
||||
]
|
||||
].
|
||||
|
||||
Transcript show: 'COMMIT;'; nl.
|
||||
|
||||
]
|
||||
10
openbsc/contrib/sms/hlr-query.st
Normal file
10
openbsc/contrib/sms/hlr-query.st
Normal file
@@ -0,0 +1,10 @@
|
||||
"Query for one SMS"
|
||||
|
||||
Eval [
|
||||
1 to: 100 do: [:each |
|
||||
Transcript show: 'SELECT SMS.* FROM SMS
|
||||
JOIN Subscriber ON SMS.receiver_id = Subscriber.id
|
||||
WHERE SMS.id >= 1 AND SMS.sent IS NULL AND Subscriber.lac > 0
|
||||
ORDER BY SMS.id LIMIT 1;'; nl.
|
||||
].
|
||||
]
|
||||
5
openbsc/contrib/sms/sqlite-probe.tap.d
Normal file
5
openbsc/contrib/sms/sqlite-probe.tap.d
Normal file
@@ -0,0 +1,5 @@
|
||||
probe process("/usr/lib/libsqlite3.so.0.8.6").function("sqlite3_get_table")
|
||||
{
|
||||
a = user_string($zSql);
|
||||
printf("sqlite3_get_table called '%s'\n", a);
|
||||
}
|
||||
@@ -1,2 +1,2 @@
|
||||
/usr/sbin/bs11_config
|
||||
/usr/sbin/isdnsync
|
||||
/usr/bin/bs11_config
|
||||
/usr/bin/isdnsync
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
/usr/sbin/bsc_mgcp
|
||||
/usr/bin/bsc_mgcp
|
||||
/usr/bin/osmo-bsc
|
||||
|
||||
@@ -1 +1 @@
|
||||
/usr/sbin/osmo-gbproxy
|
||||
/usr/bin/osmo-gbproxy
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
/usr/sbin/ipaccess-config
|
||||
/usr/sbin/ipaccess-find
|
||||
/usr/sbin/ipaccess-proxy
|
||||
/usr/bin/ipaccess-config
|
||||
/usr/bin/ipaccess-find
|
||||
/usr/bin/ipaccess-proxy
|
||||
|
||||
@@ -1 +1 @@
|
||||
/usr/sbin/bsc_hack
|
||||
/usr/bin/bsc_hack
|
||||
|
||||
@@ -1 +1 @@
|
||||
/usr/sbin/osmo-sgsn
|
||||
/usr/bin/osmo-sgsn
|
||||
|
||||
@@ -11,7 +11,7 @@ noinst_HEADERS = abis_nm.h abis_rsl.h db.h gsm_04_08.h gsm_data.h \
|
||||
gb_proxy.h gprs_sgsn.h gsm_04_08_gprs.h sgsn.h \
|
||||
gprs_ns_frgre.h auth.h osmo_msc.h bsc_msc.h bsc_nat.h \
|
||||
osmo_bsc_rf.h osmo_bsc.h network_listen.h bsc_nat_sccp.h \
|
||||
osmo_msc_data.h osmo_bsc_grace.h
|
||||
osmo_msc_data.h osmo_bsc_grace.h sms_queue.h abis_om2000.h
|
||||
|
||||
openbsc_HEADERS = gsm_04_08.h meas_rep.h bsc_api.h
|
||||
openbscdir = $(includedir)/openbsc
|
||||
|
||||
@@ -5,18 +5,17 @@
|
||||
* All Rights Reserved
|
||||
*
|
||||
* 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 2 of the License, or
|
||||
* 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.
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -138,6 +137,7 @@ int abis_nm_bs11_get_state(struct gsm_bts *bts);
|
||||
int abis_nm_bs11_load_swl(struct gsm_bts *bts, const char *fname,
|
||||
u_int8_t win_size, int forced, gsm_cbfn *cbfn);
|
||||
int abis_nm_bs11_set_ext_time(struct gsm_bts *bts);
|
||||
int abis_nm_bs11_get_bport_line_cfg(struct gsm_bts *bts, u_int8_t bport);
|
||||
int abis_nm_bs11_set_bport_line_cfg(struct gsm_bts *bts, u_int8_t bport, enum abis_bs11_line_cfg line_cfg);
|
||||
int abis_nm_bs11_bsc_disconnect(struct gsm_bts *bts, int reconnect);
|
||||
int abis_nm_bs11_restart(struct gsm_bts *bts);
|
||||
@@ -160,18 +160,13 @@ int ipac_parse_bcch_info(struct ipac_bcch_info *binf, u_int8_t *buf);
|
||||
const char *ipacc_testres_name(u_int8_t res);
|
||||
|
||||
/* Functions calling into other code parts */
|
||||
enum nm_evt {
|
||||
EVT_STATECHG_OPER,
|
||||
EVT_STATECHG_ADM,
|
||||
};
|
||||
int nm_state_event(enum nm_evt evt, u_int8_t obj_class, void *obj,
|
||||
struct gsm_nm_state *old_state, struct gsm_nm_state *new_state,
|
||||
struct abis_om_obj_inst *obj_inst);
|
||||
|
||||
const char *nm_opstate_name(u_int8_t os);
|
||||
const char *nm_avail_name(u_int8_t avail);
|
||||
int nm_is_running(struct gsm_nm_state *s);
|
||||
|
||||
int abis_nm_vty_init(void);
|
||||
|
||||
void abis_nm_clear_queue(struct gsm_bts *bts);
|
||||
|
||||
|
||||
#endif /* _NM_H */
|
||||
|
||||
62
openbsc/include/openbsc/abis_om2000.h
Normal file
62
openbsc/include/openbsc/abis_om2000.h
Normal file
@@ -0,0 +1,62 @@
|
||||
#ifndef OPENBSC_ABIS_OM2K_H
|
||||
#define OPENBSC_ABIS_OM2K_H
|
||||
/* Ericsson RBS 2xxx GSM O&M (OM2000) messages on the A-bis interface
|
||||
* implemented based on protocol trace analysis, no formal documentation */
|
||||
|
||||
/* (C) 2010-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 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
struct abis_om2k_mo {
|
||||
uint8_t class;
|
||||
uint8_t bts;
|
||||
uint8_t assoc_so;
|
||||
uint8_t inst;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct om2k_is_conn_grp {
|
||||
uint16_t icp1;
|
||||
uint16_t icp2;
|
||||
uint8_t cont_idx;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
extern const struct value_string om2k_mo_class_short_vals[];
|
||||
|
||||
int abis_om2k_rcvmsg(struct msgb *msg);
|
||||
|
||||
extern const struct abis_om2k_mo om2k_mo_cf;
|
||||
|
||||
int abis_om2k_tx_reset_cmd(struct gsm_bts *bts, const struct abis_om2k_mo *mo);
|
||||
int abis_om2k_tx_start_req(struct gsm_bts *bts, const struct abis_om2k_mo *mo);
|
||||
int abis_om2k_tx_status_req(struct gsm_bts *bts, const struct abis_om2k_mo *mo);
|
||||
int abis_om2k_tx_connect_cmd(struct gsm_bts *bts, const struct abis_om2k_mo *mo);
|
||||
int abis_om2k_tx_disconnect_cmd(struct gsm_bts *bts, const struct abis_om2k_mo *mo);
|
||||
int abis_om2k_tx_enable_req(struct gsm_bts *bts, const struct abis_om2k_mo *mo);
|
||||
int abis_om2k_tx_disable_req(struct gsm_bts *bts, const struct abis_om2k_mo *mo);
|
||||
int abis_om2k_tx_test_req(struct gsm_bts *bts, const struct abis_om2k_mo *mo);
|
||||
int abis_om2k_tx_op_info(struct gsm_bts *bts, const struct abis_om2k_mo *mo,
|
||||
uint8_t operational);
|
||||
int abis_om2k_tx_is_conf_req(struct gsm_bts *bts, struct om2k_is_conn_grp *cg,
|
||||
unsigned int num_cg);
|
||||
|
||||
int abis_om2k_vty_init(void);
|
||||
|
||||
struct vty;
|
||||
void abis_om2k_config_write_bts(struct vty *vty, struct gsm_bts *bts);
|
||||
|
||||
#endif /* OPENBCS_ABIS_OM2K_H */
|
||||
@@ -5,18 +5,17 @@
|
||||
* All Rights Reserved
|
||||
*
|
||||
* 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 2 of the License, or
|
||||
* 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.
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -27,6 +26,12 @@
|
||||
|
||||
#include <osmocore/msgb.h>
|
||||
|
||||
struct gsm_bts;
|
||||
struct gsm_lchan;
|
||||
struct gsm_subscriber;
|
||||
struct gsm_bts_trx_ts;
|
||||
|
||||
|
||||
int rsl_bcch_info(struct gsm_bts_trx *trx, u_int8_t type,
|
||||
const u_int8_t *data, int len);
|
||||
int rsl_sacch_filling(struct gsm_bts_trx *trx, u_int8_t type,
|
||||
@@ -43,8 +48,6 @@ int rsl_chan_mode_modify_req(struct gsm_lchan *ts);
|
||||
int rsl_encryption_cmd(struct msgb *msg);
|
||||
int rsl_paging_cmd(struct gsm_bts *bts, u_int8_t paging_group, u_int8_t len,
|
||||
u_int8_t *ms_ident, u_int8_t chan_needed);
|
||||
int rsl_paging_cmd_subscr(struct gsm_bts *bts, u_int8_t chan_needed,
|
||||
struct gsm_subscriber *subscr);
|
||||
int rsl_imm_assign_cmd(struct gsm_bts *bts, u_int8_t len, u_int8_t *val);
|
||||
|
||||
int rsl_data_request(struct msgb *msg, u_int8_t link_id);
|
||||
@@ -59,7 +62,7 @@ int rsl_ipacc_crcx(struct gsm_lchan *lchan);
|
||||
int rsl_ipacc_mdcx(struct gsm_lchan *lchan, u_int32_t ip,
|
||||
u_int16_t port, u_int8_t rtp_payload2);
|
||||
int rsl_ipacc_mdcx_to_rtpsock(struct gsm_lchan *lchan);
|
||||
int rsl_ipacc_pdch_activate(struct gsm_lchan *lchan, int act);
|
||||
int rsl_ipacc_pdch_activate(struct gsm_bts_trx_ts *ts, int act);
|
||||
|
||||
int abis_rsl_rcvmsg(struct msgb *msg);
|
||||
|
||||
@@ -82,6 +85,9 @@ int rsl_ccch_conf_to_bs_cc_chans(int ccch_conf);
|
||||
int rsl_ccch_conf_to_bs_ccch_sdcch_comb(int ccch_conf);
|
||||
int rsl_number_of_paging_subchannels(struct gsm_bts *bts);
|
||||
|
||||
int rsl_sacch_info_modify(struct gsm_lchan *lchan, u_int8_t type,
|
||||
const u_int8_t *data, int len);
|
||||
|
||||
int rsl_chan_bs_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int db);
|
||||
int rsl_chan_ms_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int dbm);
|
||||
|
||||
|
||||
@@ -4,6 +4,13 @@
|
||||
struct gsm_auth_tuple;
|
||||
struct gsm_subscriber;
|
||||
|
||||
enum auth_action {
|
||||
AUTH_NOT_AVAIL = 0, /* No auth tuple available */
|
||||
AUTH_DO_AUTH_THAN_CIPH = 1, /* Firsth authenticate, then cipher */
|
||||
AUTH_DO_CIPH = 2, /* Only ciphering */
|
||||
AUTH_DO_AUTH = 3, /* Only authentication, no ciphering */
|
||||
};
|
||||
|
||||
int auth_get_tuple_for_subscr(struct gsm_auth_tuple *atuple,
|
||||
struct gsm_subscriber *subscr, int key_seq);
|
||||
|
||||
|
||||
@@ -12,25 +12,24 @@ struct bsc_api {
|
||||
void (*sapi_n_reject)(struct gsm_subscriber_connection *conn, int dlci);
|
||||
void (*cipher_mode_compl)(struct gsm_subscriber_connection *conn,
|
||||
struct msgb *msg, uint8_t chosen_encr);
|
||||
void (*cipher_mode_reject)(struct gsm_subscriber_connection *conn,
|
||||
struct msgb *msg, uint16_t reason);
|
||||
int (*compl_l3)(struct gsm_subscriber_connection *conn,
|
||||
struct msgb *msg, uint16_t chosen_channel);
|
||||
void (*dtap)(struct gsm_subscriber_connection *conn, struct msgb *msg);
|
||||
void (*dtap)(struct gsm_subscriber_connection *conn, uint8_t link_id,
|
||||
struct msgb *msg);
|
||||
void (*assign_compl)(struct gsm_subscriber_connection *conn,
|
||||
uint16_t rr_cause);
|
||||
uint8_t rr_cause, uint8_t chosen_channel,
|
||||
uint8_t encr_alg_id, uint8_t speech_mode);
|
||||
void (*assign_fail)(struct gsm_subscriber_connection *conn,
|
||||
uint16_t rr_cause);
|
||||
void (*clear_request)(struct gsm_subscriber_connection *conn,
|
||||
uint8_t cause, uint8_t *rr_cause);
|
||||
int (*clear_request)(struct gsm_subscriber_connection *conn,
|
||||
uint32_t cause);
|
||||
void (*clear_compl)(struct gsm_subscriber_connection *conn);
|
||||
};
|
||||
|
||||
int bsc_api_init(struct gsm_network *network, struct bsc_api *api);
|
||||
int gsm0808_submit_dtap(struct gsm_subscriber_connection *conn, struct msgb *msg, int link_id);
|
||||
int gsm0808_assign_req(struct gsm_subscriber_connection *conn, int chan_type, int audio);
|
||||
int gsm0808_submit_dtap(struct gsm_subscriber_connection *conn, struct msgb *msg, int link_id, int allow_sach);
|
||||
int gsm0808_assign_req(struct gsm_subscriber_connection *conn, int chan_mode, int full_rate);
|
||||
int gsm0808_cipher_mode(struct gsm_subscriber_connection *conn, int cipher,
|
||||
uint8_t *key, int len);
|
||||
const uint8_t *key, int len, int include_imeisv);
|
||||
int gsm0808_page(struct gsm_bts *bts, unsigned int page_group,
|
||||
unsigned int mi_len, uint8_t *mi, int chan_type);
|
||||
int gsm0808_clear(struct gsm_subscriber_connection *conn);
|
||||
|
||||
@@ -5,18 +5,17 @@
|
||||
* All Rights Reserved
|
||||
*
|
||||
* 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 2 of the License, or
|
||||
* 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.
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
@@ -4,18 +4,17 @@
|
||||
* All Rights Reserved
|
||||
*
|
||||
* 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 2 of the License, or
|
||||
* 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.
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -79,7 +78,9 @@ struct bsc_connection {
|
||||
struct timer_list pong_timeout;
|
||||
|
||||
/* mgcp related code */
|
||||
int endpoint_status[32];
|
||||
char *_endpoint_status;
|
||||
int number_multiplexes;
|
||||
int max_endpoints;
|
||||
int last_endpoint;
|
||||
|
||||
/* a back pointer */
|
||||
@@ -125,6 +126,9 @@ struct bsc_config {
|
||||
|
||||
int forbid_paging;
|
||||
|
||||
/* audio handling */
|
||||
int max_endpoints;
|
||||
|
||||
/* backpointer */
|
||||
struct bsc_nat *nat;
|
||||
|
||||
@@ -257,6 +261,7 @@ struct bsc_nat {
|
||||
/* create and init the structures */
|
||||
struct bsc_config *bsc_config_alloc(struct bsc_nat *nat, const char *token);
|
||||
struct bsc_config *bsc_config_num(struct bsc_nat *nat, int num);
|
||||
void bsc_config_free(struct bsc_config *);
|
||||
void bsc_config_add_lac(struct bsc_config *cfg, int lac);
|
||||
void bsc_config_del_lac(struct bsc_config *cfg, int lac);
|
||||
int bsc_config_handles_lac(struct bsc_config *cfg, int lac);
|
||||
@@ -303,6 +308,7 @@ struct sccp_connections *bsc_nat_find_con_by_bsc(struct bsc_nat *, struct sccp_s
|
||||
/**
|
||||
* MGCP/Audio handling
|
||||
*/
|
||||
int bsc_mgcp_nr_multiplexes(int max_endpoints);
|
||||
int bsc_write_mgcp(struct bsc_connection *bsc, const uint8_t *data, unsigned int length);
|
||||
int bsc_mgcp_assign_patch(struct sccp_connections *, struct msgb *msg);
|
||||
void bsc_mgcp_init(struct sccp_connections *);
|
||||
|
||||
@@ -5,18 +5,17 @@
|
||||
* All Rights Reserved
|
||||
*
|
||||
* 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 2 of the License, or
|
||||
* 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.
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
@@ -4,24 +4,23 @@
|
||||
* All Rights Reserved
|
||||
*
|
||||
* 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 2 of the License, or
|
||||
* 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.
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
#ifndef _CHAN_ALLOC_H
|
||||
#define _CHAN_ALLOC_H
|
||||
|
||||
#include "gsm_subscriber.h"
|
||||
#include "gsm_data.h"
|
||||
|
||||
struct gsm_subscriber_connection;
|
||||
|
||||
|
||||
@@ -3,18 +3,17 @@
|
||||
* All Rights Reserved
|
||||
*
|
||||
* 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 2 of the License, or
|
||||
* 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.
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -23,7 +22,14 @@
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <openbsc/gsm_subscriber.h>
|
||||
struct gsm_equipment;
|
||||
struct gsm_network;
|
||||
struct gsm_auth_info;
|
||||
struct gsm_auth_tuple;
|
||||
struct gsm_sms;
|
||||
struct gsm_subscriber;
|
||||
|
||||
enum gsm_subscriber_field;
|
||||
|
||||
/* one time initialisation */
|
||||
int db_init(const char *name);
|
||||
@@ -42,6 +48,7 @@ int db_subscriber_alloc_exten(struct gsm_subscriber *subscriber);
|
||||
int db_subscriber_alloc_token(struct gsm_subscriber *subscriber, u_int32_t* token);
|
||||
int db_subscriber_assoc_imei(struct gsm_subscriber *subscriber, char *imei);
|
||||
int db_sync_equipment(struct gsm_equipment *equip);
|
||||
int db_subscriber_update(struct gsm_subscriber *subscriber);
|
||||
|
||||
/* auth info */
|
||||
int db_get_authinfo_for_subscr(struct gsm_auth_info *ainfo,
|
||||
@@ -55,8 +62,9 @@ int db_sync_lastauthtuple_for_subscr(struct gsm_auth_tuple *atuple,
|
||||
|
||||
/* SMS store-and-forward */
|
||||
int db_sms_store(struct gsm_sms *sms);
|
||||
struct gsm_sms *db_sms_get(struct gsm_network *net, unsigned long long id);
|
||||
struct gsm_sms *db_sms_get_unsent(struct gsm_network *net, unsigned long long min_id);
|
||||
struct gsm_sms *db_sms_get_unsent_by_subscr(struct gsm_network *net, unsigned long long min_subscr_id);
|
||||
struct gsm_sms *db_sms_get_unsent_by_subscr(struct gsm_network *net, unsigned long long min_subscr_id, unsigned int failed);
|
||||
struct gsm_sms *db_sms_get_unsent_for_subscr(struct gsm_subscriber *subscr);
|
||||
int db_sms_mark_sent(struct gsm_sms *sms);
|
||||
int db_sms_inc_deliver_attempts(struct gsm_sms *sms);
|
||||
|
||||
@@ -66,6 +66,8 @@ struct e1inp_ts {
|
||||
struct {
|
||||
/* list of all signalling links on this TS */
|
||||
struct llist_head sign_links;
|
||||
/* delay for the queue */
|
||||
int delay;
|
||||
/* timer when to dequeue next frame */
|
||||
struct timer_list tx_timer;
|
||||
} sign;
|
||||
@@ -85,7 +87,11 @@ struct e1inp_ts {
|
||||
/* ip.access driver has one fd for each ts */
|
||||
struct bsc_fd fd;
|
||||
} ipaccess;
|
||||
|
||||
struct {
|
||||
/* DAHDI driver has one fd for each ts */
|
||||
struct bsc_fd fd;
|
||||
struct lapd_instance *lapd;
|
||||
} dahdi;
|
||||
} driver;
|
||||
};
|
||||
|
||||
@@ -93,6 +99,8 @@ struct e1inp_driver {
|
||||
struct llist_head list;
|
||||
const char *name;
|
||||
int (*want_write)(struct e1inp_ts *ts);
|
||||
int (*line_update)(struct e1inp_line *line);
|
||||
int default_delay;
|
||||
};
|
||||
|
||||
struct e1inp_line {
|
||||
@@ -110,11 +118,17 @@ struct e1inp_line {
|
||||
/* register a driver with the E1 core */
|
||||
int e1inp_driver_register(struct e1inp_driver *drv);
|
||||
|
||||
/* fine a previously registered driver */
|
||||
struct e1inp_driver *e1inp_driver_find(const char *name);
|
||||
|
||||
/* register a line with the E1 core */
|
||||
int e1inp_line_register(struct e1inp_line *line);
|
||||
|
||||
/* ensure a certain line exists, return pointer to it */
|
||||
struct e1inp_line *e1inp_line_get_create(u_int8_t e1_nr);
|
||||
/* get a line by its ID */
|
||||
struct e1inp_line *e1inp_line_get(u_int8_t e1_nr);
|
||||
|
||||
/* create a line in the E1 input core */
|
||||
struct e1inp_line *e1inp_line_create(u_int8_t e1_nr, const char *driver_name);
|
||||
|
||||
/* find a sign_link for given TEI and SAPI in a TS */
|
||||
struct e1inp_sign_link *
|
||||
@@ -165,4 +179,9 @@ int ipaccess_setup(struct gsm_network *gsmnet);
|
||||
extern struct llist_head e1inp_driver_list;
|
||||
extern struct llist_head e1inp_line_list;
|
||||
|
||||
int e1inp_vty_init(void);
|
||||
void e1inp_init(void);
|
||||
|
||||
int _abis_nm_sendmsg(struct msgb *msg, int to_trx_oml);
|
||||
|
||||
#endif /* _E1_INPUT_H */
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <osmocore/msgb.h>
|
||||
#include <openbsc/gprs_sgsn.h>
|
||||
|
||||
int gsm48_tx_gsm_deact_pdp_req(struct sgsn_pdp_ctx *pdp, uint8_t sm_cause);
|
||||
int gsm48_tx_gsm_act_pdp_rej(struct sgsn_mm_ctx *mm, uint8_t tid,
|
||||
uint8_t cause, uint8_t pco_len, uint8_t *pco_v);
|
||||
int gsm48_tx_gsm_act_pdp_acc(struct sgsn_pdp_ctx *pdp);
|
||||
|
||||
@@ -119,12 +119,17 @@ struct sgsn_mm_ctx *sgsn_mm_ctx_by_imsi(const char *imsi);
|
||||
/* Allocate a new SGSN MM context */
|
||||
struct sgsn_mm_ctx *sgsn_mm_ctx_alloc(uint32_t tlli,
|
||||
const struct gprs_ra_id *raid);
|
||||
void sgsn_mm_ctx_free(struct sgsn_mm_ctx *mm);
|
||||
|
||||
|
||||
enum pdp_ctx_state {
|
||||
PDP_STATE_NONE,
|
||||
PDP_STATE_CR_REQ,
|
||||
PDP_STATE_CR_CONF,
|
||||
|
||||
/* 04.08 / Figure 6.2 / 6.1.2.2 */
|
||||
PDP_STATE_INACT_PEND,
|
||||
PDP_STATE_INACTIVE = PDP_STATE_NONE,
|
||||
};
|
||||
|
||||
enum pdp_type {
|
||||
@@ -162,6 +167,10 @@ struct sgsn_pdp_ctx {
|
||||
uint32_t rx_gtp_snu;
|
||||
//uint32_t charging_id;
|
||||
int reordering_reqd;
|
||||
|
||||
struct timer_list timer;
|
||||
unsigned int T; /* Txxxx number */
|
||||
unsigned int num_T_exp; /* number of consecutive T expirations */
|
||||
};
|
||||
|
||||
|
||||
@@ -182,10 +191,12 @@ struct sgsn_ggsn_ctx {
|
||||
uint32_t id;
|
||||
unsigned int gtp_version;
|
||||
struct in_addr remote_addr;
|
||||
int remote_restart_ctr;
|
||||
struct gsn_t *gsn;
|
||||
};
|
||||
struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_alloc(uint32_t id);
|
||||
struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_by_id(uint32_t id);
|
||||
struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_by_addr(struct in_addr *addr);
|
||||
struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_find_alloc(uint32_t id);
|
||||
|
||||
struct apn_ctx {
|
||||
@@ -202,4 +213,8 @@ extern struct llist_head sgsn_pdp_ctxts;
|
||||
|
||||
uint32_t sgsn_alloc_ptmsi(void);
|
||||
|
||||
/* High-level function to be called in case a GGSN has disappeared or
|
||||
* ottherwise lost state (recovery procedure) */
|
||||
int drop_all_pdp_for_ggsn(struct sgsn_ggsn_ctx *ggsn);
|
||||
|
||||
#endif /* _GPRS_SGSN_H */
|
||||
|
||||
@@ -13,8 +13,8 @@ struct gsm_network;
|
||||
struct gsm_trans;
|
||||
struct gsm_subscriber_connection;
|
||||
|
||||
#define GSM48_ALLOC_SIZE 1024
|
||||
#define GSM48_ALLOC_HEADROOM 128
|
||||
#define GSM48_ALLOC_SIZE 2048
|
||||
#define GSM48_ALLOC_HEADROOM 256
|
||||
|
||||
static inline struct msgb *gsm48_msgb_alloc(void)
|
||||
{
|
||||
@@ -25,6 +25,7 @@ static inline struct msgb *gsm48_msgb_alloc(void)
|
||||
/* config options controlling the behaviour of the lower leves */
|
||||
void gsm0408_allow_everyone(int allow);
|
||||
void gsm0408_clear_request(struct gsm_subscriber_connection *conn, uint32_t cause);
|
||||
void gsm0408_clear_all_trans(struct gsm_network *net, int protocol);
|
||||
int gsm0408_dispatch(struct gsm_subscriber_connection *conn, struct msgb *msg);
|
||||
|
||||
int gsm0408_rcvmsg(struct msgb *msg, u_int8_t link_id);
|
||||
@@ -44,9 +45,7 @@ int gsm48_send_rr_ass_cmd(struct gsm_lchan *dest_lchan, struct gsm_lchan *lchan,
|
||||
int gsm48_send_ho_cmd(struct gsm_lchan *old_lchan, struct gsm_lchan *new_lchan,
|
||||
u_int8_t power_command, u_int8_t ho_ref);
|
||||
|
||||
int bsc_upqueue(struct gsm_network *net);
|
||||
|
||||
int mncc_send(struct gsm_network *net, int msg_type, void *arg);
|
||||
int mncc_tx_to_cc(struct gsm_network *net, int msg_type, void *arg);
|
||||
|
||||
/* convert a ASCII phone number to call-control BCD */
|
||||
int encode_bcd_number(u_int8_t *bcd_lv, u_int8_t max_len,
|
||||
|
||||
@@ -29,9 +29,12 @@ int gsm0411_rcv_sms(struct gsm_subscriber_connection *conn, struct msgb *msg);
|
||||
|
||||
struct gsm_sms *sms_alloc(void);
|
||||
void sms_free(struct gsm_sms *sms);
|
||||
struct gsm_sms *sms_from_text(struct gsm_subscriber *receiver, int dcs, const char *text);
|
||||
|
||||
void _gsm411_sms_trans_free(struct gsm_trans *trans);
|
||||
int gsm411_send_sms_subscr(struct gsm_subscriber *subscr,
|
||||
struct gsm_sms *sms);
|
||||
int gsm411_send_sms(struct gsm_subscriber_connection *conn,
|
||||
struct gsm_sms *sms);
|
||||
void gsm411_sapi_n_reject(struct gsm_subscriber_connection *conn);
|
||||
#endif
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
struct osmo_msc_data;
|
||||
struct osmo_bsc_sccp_con;
|
||||
struct gsm_sms_queue;
|
||||
|
||||
enum gsm_phys_chan_config {
|
||||
GSM_PCHAN_NONE,
|
||||
@@ -44,9 +45,8 @@ enum gsm_chreq_reason_t {
|
||||
};
|
||||
|
||||
#include <osmocore/timer.h>
|
||||
#include <openbsc/gsm_04_08.h>
|
||||
#include <openbsc/abis_rsl.h>
|
||||
#include <openbsc/system_information.h>
|
||||
#include <openbsc/rest_octets.h>
|
||||
#include <openbsc/mncc.h>
|
||||
|
||||
#include <osmocore/tlv.h>
|
||||
@@ -56,6 +56,9 @@ enum gsm_chreq_reason_t {
|
||||
#include <osmocore/utils.h>
|
||||
#include <osmocore/rxlev_stat.h>
|
||||
|
||||
#include <osmocore/protocol/gsm_08_58.h>
|
||||
|
||||
|
||||
#define TRX_NR_TS 8
|
||||
#define TS_MAX_LCHAN 8
|
||||
|
||||
@@ -68,6 +71,9 @@ enum gsm_chreq_reason_t {
|
||||
#define HARDCODED_BTS1_TS 6
|
||||
#define HARDCODED_BTS2_TS 11
|
||||
|
||||
/* reserved according to GSM 03.03 § 2.4 */
|
||||
#define GSM_RESERVED_TMSI 0xFFFFFFFF
|
||||
|
||||
enum gsm_hooks {
|
||||
GSM_HOOK_NM_SWLOAD,
|
||||
GSM_HOOK_RR_PAGING,
|
||||
@@ -78,6 +84,7 @@ enum gsm_paging_event {
|
||||
GSM_PAGING_SUCCEEDED,
|
||||
GSM_PAGING_EXPIRED,
|
||||
GSM_PAGING_OOM,
|
||||
GSM_PAGING_BUSY,
|
||||
};
|
||||
|
||||
enum bts_gprs_mode {
|
||||
@@ -86,6 +93,8 @@ enum bts_gprs_mode {
|
||||
BTS_GPRS_EGPRS = 2,
|
||||
};
|
||||
|
||||
#define OBSC_NM_W_ACK_CB(__msgb) (__msgb)->cb[3]
|
||||
|
||||
/* the data structure stored in msgb->cb for openbsc apps */
|
||||
struct openbsc_msgb_cb {
|
||||
unsigned char *bssgph;
|
||||
@@ -243,6 +252,7 @@ struct gsm_subscriber_connection {
|
||||
|
||||
/* Are we part of a special "silent" call */
|
||||
int silent_call;
|
||||
int put_channel;
|
||||
|
||||
/* bsc structures */
|
||||
struct osmo_bsc_sccp_con *sccp_con;
|
||||
@@ -252,6 +262,11 @@ struct gsm_subscriber_connection {
|
||||
struct gsm_lchan *lchan;
|
||||
struct gsm_lchan *ho_lchan;
|
||||
struct gsm_bts *bts;
|
||||
|
||||
/* for assignment handling */
|
||||
struct timer_list T10;
|
||||
struct gsm_lchan *secondary_lchan;
|
||||
|
||||
};
|
||||
|
||||
struct gsm_lchan {
|
||||
@@ -371,6 +386,8 @@ struct gsm_bts_trx {
|
||||
struct gsm_e1_subslot rsl_e1_link;
|
||||
u_int8_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_nm_state nm_state;
|
||||
struct tlv_parsed nm_attr;
|
||||
@@ -406,14 +423,23 @@ enum gsm_bts_type {
|
||||
GSM_BTS_TYPE_UNKNOWN,
|
||||
GSM_BTS_TYPE_BS11,
|
||||
GSM_BTS_TYPE_NANOBTS,
|
||||
GSM_BTS_TYPE_RBS2000,
|
||||
};
|
||||
|
||||
struct vty;
|
||||
|
||||
struct gsm_bts_model {
|
||||
struct llist_head list;
|
||||
|
||||
enum gsm_bts_type type;
|
||||
const char *name;
|
||||
|
||||
int (*oml_rcvmsg)(struct msgb *msg);
|
||||
|
||||
void (*config_write_bts)(struct vty *vty, struct gsm_bts *bts);
|
||||
void (*config_write_trx)(struct vty *vty, struct gsm_bts_trx *trx);
|
||||
void (*config_write_ts)(struct vty *vty, struct gsm_bts_trx_ts *ts);
|
||||
|
||||
struct tlv_definition nm_att_tlvdef;
|
||||
|
||||
struct bitvec features;
|
||||
@@ -428,28 +454,6 @@ enum gsm_bts_features {
|
||||
BTS_FEAT_HOPPING,
|
||||
};
|
||||
|
||||
/**
|
||||
* A pending paging request
|
||||
*/
|
||||
struct gsm_paging_request {
|
||||
/* list_head for list of all paging requests */
|
||||
struct llist_head entry;
|
||||
/* the subscriber which we're paging. Later gsm_paging_request
|
||||
* should probably become a part of the gsm_subscriber struct? */
|
||||
struct gsm_subscriber *subscr;
|
||||
/* back-pointer to the BTS on which we are paging */
|
||||
struct gsm_bts *bts;
|
||||
/* what kind of channel type do we ask the MS to establish */
|
||||
int chan_type;
|
||||
|
||||
/* Timer 3113: how long do we try to page? */
|
||||
struct timer_list T3113;
|
||||
|
||||
/* callback to be called in case paging completes */
|
||||
gsm_cbfn *cbfn;
|
||||
void *cbfn_param;
|
||||
};
|
||||
|
||||
/*
|
||||
* This keeps track of the paging status of one BTS. It
|
||||
* includes a number of pending requests, a back pointer
|
||||
@@ -487,6 +491,12 @@ struct gsm_bts_gprs_nsvc {
|
||||
struct gsm_nm_state nm_state;
|
||||
};
|
||||
|
||||
enum neigh_list_manual_mode {
|
||||
NL_MODE_AUTOMATIC = 0,
|
||||
NL_MODE_MANUAL = 1,
|
||||
NL_MODE_MANUAL_SI5SEP = 2, /* SI2 and SI5 have separate neighbor lists */
|
||||
};
|
||||
|
||||
/* One BTS */
|
||||
struct gsm_bts {
|
||||
/* list header in net->bts_list */
|
||||
@@ -538,19 +548,24 @@ struct gsm_bts {
|
||||
struct gsm_nm_state nm_state;
|
||||
} site_mgr;
|
||||
|
||||
enum neigh_list_manual_mode neigh_list_manual_mode;
|
||||
/* parameters from which we build SYSTEM INFORMATION */
|
||||
struct {
|
||||
struct gsm48_rach_control rach_control;
|
||||
u_int8_t ncc_permitted;
|
||||
struct gsm48_cell_sel_par cell_sel_par;
|
||||
struct gsm48_si_selection_params cell_ro_sel_par; /* rest octet */
|
||||
struct gsm48_cell_options cell_options;
|
||||
struct gsm48_control_channel_descr chan_desc;
|
||||
struct bitvec neigh_list;
|
||||
struct bitvec cell_alloc;
|
||||
struct bitvec si5_neigh_list;
|
||||
struct {
|
||||
/* bitmask large enough for all possible ARFCN's */
|
||||
u_int8_t neigh_list[1024/8];
|
||||
u_int8_t cell_alloc[1024/8];
|
||||
/* If the user wants a different neighbor list in SI5 than in SI2 */
|
||||
u_int8_t si5_neigh_list[1024/8];
|
||||
} data;
|
||||
} si_common;
|
||||
|
||||
@@ -577,6 +592,14 @@ struct gsm_bts {
|
||||
} rack;
|
||||
struct gsm_envabtse envabtse[4];
|
||||
} bs11;
|
||||
struct {
|
||||
struct {
|
||||
struct llist_head conn_groups;
|
||||
} is;
|
||||
struct {
|
||||
struct llist_head conn_groups;
|
||||
} con;
|
||||
} rbs2000;
|
||||
};
|
||||
|
||||
/* Not entirely sure how ip.access specific this is */
|
||||
@@ -603,6 +626,10 @@ struct gsm_bts {
|
||||
/* transceivers */
|
||||
int num_trx;
|
||||
struct llist_head trx_list;
|
||||
|
||||
/* Abis NM queue */
|
||||
struct llist_head abis_queue;
|
||||
int abis_nm_pend;
|
||||
};
|
||||
|
||||
/* Some statistics of our network */
|
||||
@@ -642,9 +669,10 @@ struct gsmnet_stats {
|
||||
struct counter *rp_err_other;
|
||||
} sms;
|
||||
struct {
|
||||
struct counter *dialled; /* total number of dialled calls */
|
||||
struct counter *alerted; /* we alerted the other end */
|
||||
struct counter *connected;/* how many calls were accepted */
|
||||
struct counter *mo_setup;
|
||||
struct counter *mo_connect_ack;
|
||||
struct counter *mt_setup;
|
||||
struct counter *mt_connect;
|
||||
} call;
|
||||
struct {
|
||||
struct counter *rf_fail;
|
||||
@@ -696,7 +724,7 @@ struct gsm_network {
|
||||
struct gsmnet_stats stats;
|
||||
|
||||
/* layer 4 */
|
||||
int (*mncc_recv) (struct gsm_network *net, int msg_type, void *arg);
|
||||
int (*mncc_recv) (struct gsm_network *net, struct msgb *msg);
|
||||
struct llist_head upqueue;
|
||||
struct llist_head trans_list;
|
||||
struct bsc_api *bsc_api;
|
||||
@@ -715,6 +743,7 @@ struct gsm_network {
|
||||
int T3115;
|
||||
int T3117;
|
||||
int T3119;
|
||||
int T3122;
|
||||
int T3141;
|
||||
|
||||
/* Radio Resource Location Protocol (TS 04.31) */
|
||||
@@ -732,6 +761,11 @@ struct gsm_network {
|
||||
|
||||
/* MSC data in case we are a true BSC */
|
||||
struct osmo_msc_data *msc_data;
|
||||
int hardcoded_rtp_payload;
|
||||
|
||||
/* subscriber related features */
|
||||
int keep_subscr;
|
||||
struct gsm_sms_queue *sms_queue;
|
||||
};
|
||||
|
||||
#define SMS_HDR_SIZE 128
|
||||
@@ -758,7 +792,7 @@ struct gsm_sms {
|
||||
|
||||
|
||||
struct gsm_network *gsm_network_init(u_int16_t country_code, u_int16_t network_code,
|
||||
int (*mncc_recv)(struct gsm_network *, int, void *));
|
||||
int (*mncc_recv)(struct gsm_network *, struct msgb *));
|
||||
struct gsm_bts *gsm_bts_alloc(struct gsm_network *net, enum gsm_bts_type type,
|
||||
u_int8_t tsc, u_int8_t bsic);
|
||||
struct gsm_bts_trx *gsm_bts_trx_alloc(struct gsm_bts *bts);
|
||||
@@ -781,12 +815,6 @@ char *gsm_ts_name(struct gsm_bts_trx_ts *ts);
|
||||
char *gsm_lchan_name(struct gsm_lchan *lchan);
|
||||
const char *gsm_lchans_name(enum gsm_lchan_state s);
|
||||
|
||||
enum gsm_e1_event {
|
||||
EVT_E1_NONE,
|
||||
EVT_E1_TEI_UP,
|
||||
EVT_E1_TEI_DN,
|
||||
};
|
||||
|
||||
void set_ts_e1link(struct gsm_bts_trx_ts *ts, u_int8_t e1_nr,
|
||||
u_int8_t e1_ts, u_int8_t e1_ts_ss);
|
||||
enum gsm_bts_type parse_btstype(const char *arg);
|
||||
|
||||
@@ -13,13 +13,11 @@
|
||||
#define GSM_MIN_EXTEN 20000
|
||||
#define GSM_MAX_EXTEN 49999
|
||||
|
||||
/* reserved according to GSM 03.03 § 2.4 */
|
||||
#define GSM_RESERVED_TMSI 0xFFFFFFFF
|
||||
|
||||
|
||||
#define GSM_SUBSCRIBER_FIRST_CONTACT 0x00000001
|
||||
#define tmsi_from_string(str) strtoul(str, NULL, 10)
|
||||
|
||||
struct vty;
|
||||
|
||||
struct gsm_equipment {
|
||||
long long unsigned int id;
|
||||
char imei[GSM_IMEI_LENGTH];
|
||||
@@ -81,13 +79,27 @@ struct gsm_subscriber *subscr_get_by_extension(struct gsm_network *net,
|
||||
const char *ext);
|
||||
struct gsm_subscriber *subscr_get_by_id(struct gsm_network *net,
|
||||
unsigned long long id);
|
||||
struct gsm_subscriber *subscr_get_or_create(struct gsm_network *net,
|
||||
const char *imsi);
|
||||
int subscr_update(struct gsm_subscriber *s, struct gsm_bts *bts, int reason);
|
||||
void subscr_put_channel(struct gsm_subscriber_connection *conn);
|
||||
void subscr_put_channel(struct gsm_subscriber *subscr);
|
||||
void subscr_get_channel(struct gsm_subscriber *subscr,
|
||||
int type, gsm_cbfn *cbfn, void *param);
|
||||
struct gsm_subscriber *subscr_active_by_tmsi(struct gsm_network *net,
|
||||
uint32_t tmsi);
|
||||
struct gsm_subscriber *subscr_active_by_imsi(struct gsm_network *net,
|
||||
const char *imsi);
|
||||
|
||||
int subscr_pending_requests(struct gsm_subscriber *subscr);
|
||||
int subscr_pending_clear(struct gsm_subscriber *subscr);
|
||||
int subscr_pending_dump(struct gsm_subscriber *subscr, struct vty *vty);
|
||||
int subscr_pending_kick(struct gsm_subscriber *subscr);
|
||||
|
||||
char *subscr_name(struct gsm_subscriber *subscr);
|
||||
|
||||
int subscr_purge_inactive(struct gsm_network *net);
|
||||
void subscr_update_from_db(struct gsm_subscriber *subscr);
|
||||
|
||||
/* internal */
|
||||
struct gsm_subscriber *subscr_alloc(void);
|
||||
extern struct llist_head active_subscribers;
|
||||
|
||||
@@ -9,6 +9,6 @@ struct gsm_subscriber_connection;
|
||||
int bsc_handover_start(struct gsm_lchan *old_lchan, struct gsm_bts *bts);
|
||||
|
||||
/* clear any operation for this connection */
|
||||
void bsc_clear_handover(struct gsm_subscriber_connection *conn);
|
||||
void bsc_clear_handover(struct gsm_subscriber_connection *conn, int free_lchan);
|
||||
|
||||
#endif /* _HANDOVER_H */
|
||||
|
||||
@@ -14,14 +14,21 @@ struct ipaccess_head {
|
||||
u_int8_t data[0];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct ipaccess_head_ext {
|
||||
uint8_t proto;
|
||||
uint8_t data[0];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
enum ipaccess_proto {
|
||||
IPAC_PROTO_RSL = 0x00,
|
||||
IPAC_PROTO_IPACCESS = 0xfe,
|
||||
IPAC_PROTO_SCCP = 0xfd,
|
||||
IPAC_PROTO_OML = 0xff,
|
||||
|
||||
|
||||
/* OpenBSC extensions */
|
||||
IPAC_PROTO_MGCP = 0xfc,
|
||||
IPAC_PROTO_OSMO = 0xee,
|
||||
IPAC_PROTO_MGCP_OLD = 0xfc,
|
||||
};
|
||||
|
||||
enum ipaccess_msgtype {
|
||||
@@ -32,7 +39,7 @@ enum ipaccess_msgtype {
|
||||
IPAC_MSGT_ID_ACK = 0x06,
|
||||
|
||||
/* OpenBSC extension */
|
||||
IPAC_MSGT_SCCP_STATE = 0xff,
|
||||
IPAC_MSGT_SCCP_OLD = 0xff,
|
||||
};
|
||||
|
||||
enum ipaccess_id_tags {
|
||||
|
||||
@@ -1,23 +1,22 @@
|
||||
/* A Media Gateway Control Protocol Media Gateway: RFC 3435 */
|
||||
|
||||
/*
|
||||
* (C) 2009-2010 by Holger Hans Peter Freyther <zecke@selfish.org>
|
||||
* (C) 2009-2010 by On-Waves
|
||||
* (C) 2009-2011 by Holger Hans Peter Freyther <zecke@selfish.org>
|
||||
* (C) 2009-2011 by On-Waves
|
||||
* All Rights Reserved
|
||||
*
|
||||
* 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 2 of the License, or
|
||||
* 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.
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -64,6 +63,7 @@ static inline int rtp_calculate_port(int multiplex, int base)
|
||||
*/
|
||||
struct mgcp_endpoint;
|
||||
struct mgcp_config;
|
||||
struct mgcp_trunk_config;
|
||||
|
||||
#define MGCP_ENDP_CRCX 1
|
||||
#define MGCP_ENDP_DLCX 2
|
||||
@@ -79,9 +79,9 @@ struct mgcp_config;
|
||||
#define MGCP_POLICY_REJECT 5
|
||||
#define MGCP_POLICY_DEFER 6
|
||||
|
||||
typedef int (*mgcp_realloc)(struct mgcp_config *cfg, int endpoint);
|
||||
typedef int (*mgcp_change)(struct mgcp_config *cfg, int endpoint, int state);
|
||||
typedef int (*mgcp_policy)(struct mgcp_config *cfg, int endpoint, int state, const char *transactio_id);
|
||||
typedef int (*mgcp_realloc)(struct mgcp_trunk_config *cfg, int endpoint);
|
||||
typedef int (*mgcp_change)(struct mgcp_trunk_config *cfg, int endpoint, int state);
|
||||
typedef int (*mgcp_policy)(struct mgcp_trunk_config *cfg, int endpoint, int state, const char *transactio_id);
|
||||
typedef int (*mgcp_reset)(struct mgcp_config *cfg);
|
||||
|
||||
#define PORT_ALLOC_STATIC 0
|
||||
@@ -102,18 +102,33 @@ struct mgcp_port_range {
|
||||
int last_port;
|
||||
};
|
||||
|
||||
struct mgcp_trunk_config {
|
||||
struct llist_head entry;
|
||||
|
||||
struct mgcp_config *cfg;
|
||||
|
||||
int trunk_nr;
|
||||
int trunk_type;
|
||||
|
||||
char *audio_name;
|
||||
int audio_payload;
|
||||
int audio_loop;
|
||||
|
||||
/* spec handling */
|
||||
int force_realloc;
|
||||
|
||||
unsigned int number_endpoints;
|
||||
struct mgcp_endpoint *endpoints;
|
||||
};
|
||||
|
||||
struct mgcp_config {
|
||||
int source_port;
|
||||
char *local_ip;
|
||||
char *source_addr;
|
||||
unsigned int number_endpoints;
|
||||
char *bts_ip;
|
||||
char *call_agent_addr;
|
||||
|
||||
struct in_addr bts_in;
|
||||
char *audio_name;
|
||||
int audio_payload;
|
||||
int audio_loop;
|
||||
|
||||
/* transcoder handling */
|
||||
char *transcoder_ip;
|
||||
@@ -127,24 +142,28 @@ struct mgcp_config {
|
||||
struct mgcp_port_range transcoder_ports;
|
||||
int endp_dscp;
|
||||
|
||||
/* spec handling */
|
||||
int force_realloc;
|
||||
|
||||
mgcp_change change_cb;
|
||||
mgcp_policy policy_cb;
|
||||
mgcp_reset reset_cb;
|
||||
mgcp_realloc realloc_cb;
|
||||
void *data;
|
||||
|
||||
struct mgcp_endpoint *endpoints;
|
||||
uint32_t last_call_id;
|
||||
|
||||
/* trunk handling */
|
||||
struct mgcp_trunk_config trunk;
|
||||
struct llist_head trunks;
|
||||
|
||||
/* only used for start with a static configuration */
|
||||
int last_net_port;
|
||||
int last_bts_port;
|
||||
};
|
||||
|
||||
/* config management */
|
||||
struct mgcp_config *mgcp_config_alloc(void);
|
||||
int mgcp_parse_config(const char *config_file, struct mgcp_config *cfg);
|
||||
int mgcp_vty_init(void);
|
||||
int mgcp_endpoints_allocate(struct mgcp_config *cfg);
|
||||
int mgcp_endpoints_allocate(struct mgcp_trunk_config *cfg);
|
||||
void mgcp_free_endp(struct mgcp_endpoint *endp);
|
||||
int mgcp_reset_transcoder(struct mgcp_config *cfg);
|
||||
|
||||
@@ -152,7 +171,7 @@ int mgcp_reset_transcoder(struct mgcp_config *cfg);
|
||||
* format helper functions
|
||||
*/
|
||||
struct msgb *mgcp_handle_message(struct mgcp_config *cfg, struct msgb *msg);
|
||||
struct msgb *mgcp_create_response_with_data(int code, const char *msg, const char *trans, const char *data);
|
||||
struct msgb *mgcp_create_response_with_data(int code, const char *txt, const char *msg, const char *trans, const char *data);
|
||||
|
||||
/* adc helper */
|
||||
static inline int mgcp_timeslot_to_endpoint(int multiplex, int timeslot)
|
||||
|
||||
@@ -1,23 +1,22 @@
|
||||
/* MGCP Private Data */
|
||||
|
||||
/*
|
||||
* (C) 2009-2010 by Holger Hans Peter Freyther <zecke@selfish.org>
|
||||
* (C) 2009-2010 by On-Waves
|
||||
* (C) 2009-2011 by Holger Hans Peter Freyther <zecke@selfish.org>
|
||||
* (C) 2009-2011 by On-Waves
|
||||
* All Rights Reserved
|
||||
*
|
||||
* 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 2 of the License, or
|
||||
* 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.
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -36,6 +35,11 @@ enum mgcp_connection_mode {
|
||||
MGCP_CONN_LOOPBACK = 4,
|
||||
};
|
||||
|
||||
enum mgcp_trunk_type {
|
||||
MGCP_TRUNK_VIRTUAL,
|
||||
MGCP_TRUNK_E1,
|
||||
};
|
||||
|
||||
struct mgcp_rtp_state {
|
||||
int initialized;
|
||||
int patch;
|
||||
@@ -94,6 +98,7 @@ struct mgcp_endpoint {
|
||||
|
||||
/* backpointer */
|
||||
struct mgcp_config *cfg;
|
||||
struct mgcp_trunk_config *tcfg;
|
||||
|
||||
/* port status for bts/net */
|
||||
struct mgcp_rtp_end bts_end;
|
||||
@@ -119,7 +124,7 @@ struct mgcp_endpoint {
|
||||
struct mgcp_rtp_tap taps[MGCP_TAP_COUNT];
|
||||
};
|
||||
|
||||
#define ENDPOINT_NUMBER(endp) abs(endp - endp->cfg->endpoints)
|
||||
#define ENDPOINT_NUMBER(endp) abs(endp - endp->tcfg->endpoints)
|
||||
|
||||
struct mgcp_msg_ptr {
|
||||
unsigned int start;
|
||||
@@ -142,5 +147,8 @@ static inline int endp_back_channel(int endpoint)
|
||||
return endpoint + 60;
|
||||
}
|
||||
|
||||
struct mgcp_trunk_config *mgcp_trunk_alloc(struct mgcp_config *cfg, int index);
|
||||
struct mgcp_trunk_config *mgcp_trunk_num(struct mgcp_config *cfg, int index);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -2,18 +2,17 @@
|
||||
* All Rights Reserved
|
||||
*
|
||||
* 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 2 of the License, or
|
||||
* 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.
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -23,7 +22,6 @@
|
||||
#include "e1_input.h"
|
||||
|
||||
int mi_setup(int cardnr, struct e1inp_line *line, int release_l2);
|
||||
int _abis_nm_sendmsg(struct msgb *msg);
|
||||
int mi_e1_line_update(struct e1inp_line *line);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -7,18 +7,17 @@
|
||||
* All Rights Reserved
|
||||
*
|
||||
* 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 2 of the License, or
|
||||
* 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.
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -28,6 +27,12 @@
|
||||
#include <osmocore/linuxlist.h>
|
||||
#include <osmocore/mncc.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
struct gsm_network;
|
||||
struct msgb;
|
||||
|
||||
|
||||
/* One end of a call */
|
||||
struct gsm_call {
|
||||
struct llist_head entry;
|
||||
@@ -36,9 +41,9 @@ struct gsm_call {
|
||||
void *net;
|
||||
|
||||
/* the 'local' transaction */
|
||||
u_int32_t callref;
|
||||
uint32_t callref;
|
||||
/* the 'remote' transaction */
|
||||
u_int32_t remote_ref;
|
||||
uint32_t remote_ref;
|
||||
};
|
||||
|
||||
#define MNCC_SETUP_REQ 0x0101
|
||||
@@ -112,11 +117,11 @@ struct gsm_call {
|
||||
|
||||
struct gsm_mncc {
|
||||
/* context based information */
|
||||
u_int32_t msg_type;
|
||||
u_int32_t callref;
|
||||
uint32_t msg_type;
|
||||
uint32_t callref;
|
||||
|
||||
/* which fields are present */
|
||||
u_int32_t fields;
|
||||
uint32_t fields;
|
||||
|
||||
/* data derived informations (MNCC_F_ based) */
|
||||
struct gsm_mncc_bearer_cap bearer_cap;
|
||||
@@ -147,13 +152,21 @@ struct gsm_mncc {
|
||||
};
|
||||
|
||||
struct gsm_data_frame {
|
||||
u_int32_t msg_type;
|
||||
u_int32_t callref;
|
||||
uint32_t msg_type;
|
||||
uint32_t callref;
|
||||
unsigned char data[0];
|
||||
};
|
||||
|
||||
char *get_mncc_name(int value);
|
||||
int mncc_recv(struct gsm_network *net, int msg_type, void *arg);
|
||||
void mncc_set_cause(struct gsm_mncc *data, int loc, int val);
|
||||
void cc_tx_to_mncc(struct gsm_network *net, struct msgb *msg);
|
||||
|
||||
/* input from CC code into mncc_builtin */
|
||||
int int_mncc_recv(struct gsm_network *net, struct msgb *msg);
|
||||
|
||||
/* input from CC code into mncc_sock */
|
||||
int mncc_sock_from_cc(struct gsm_network *net, struct msgb *msg);
|
||||
|
||||
int mncc_sock_init(struct gsm_network *gsmnet);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -4,18 +4,17 @@
|
||||
* All Rights Reserved
|
||||
*
|
||||
* 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 2 of the License, or
|
||||
* 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.
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
@@ -5,6 +5,39 @@
|
||||
|
||||
#include "bsc_api.h"
|
||||
|
||||
struct sccp_connection;
|
||||
|
||||
struct osmo_bsc_sccp_con {
|
||||
struct llist_head entry;
|
||||
|
||||
int ciphering_handled;
|
||||
int rtp_port;
|
||||
|
||||
/* SCCP connection realted */
|
||||
struct sccp_connection *sccp;
|
||||
struct bsc_msc_connection *msc_con;
|
||||
struct timer_list sccp_it_timeout;
|
||||
struct timer_list sccp_cc_timeout;
|
||||
|
||||
struct llist_head sccp_queue;
|
||||
unsigned int sccp_queue_size;
|
||||
|
||||
struct gsm_subscriber_connection *conn;
|
||||
uint8_t new_subscriber;
|
||||
};
|
||||
|
||||
struct bsc_api *osmo_bsc_api();
|
||||
|
||||
int bsc_queue_for_msc(struct osmo_bsc_sccp_con *conn, struct msgb *msg);
|
||||
int bsc_open_connection(struct osmo_bsc_sccp_con *sccp, struct msgb *msg);
|
||||
int bsc_create_new_connection(struct gsm_subscriber_connection *conn);
|
||||
int bsc_delete_connection(struct osmo_bsc_sccp_con *sccp);
|
||||
|
||||
int bsc_scan_bts_msg(struct gsm_subscriber_connection *conn, struct msgb *msg);
|
||||
int bsc_scan_msc_msg(struct gsm_subscriber_connection *conn, struct msgb *msg);
|
||||
|
||||
int bsc_handle_udt(struct gsm_network *net, struct bsc_msc_connection *conn, struct msgb *msg, unsigned int length);
|
||||
int bsc_handle_dt1(struct osmo_bsc_sccp_con *conn, struct msgb *msg, unsigned int len);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -4,18 +4,17 @@
|
||||
* All Rights Reserved
|
||||
*
|
||||
* 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 2 of the License, or
|
||||
* 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.
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define OSMO_BSC_RF
|
||||
|
||||
#include <osmocore/write_queue.h>
|
||||
#include <osmocore/timer.h>
|
||||
|
||||
struct gsm_network;
|
||||
|
||||
@@ -10,6 +11,18 @@ struct osmo_bsc_rf {
|
||||
int policy;
|
||||
struct bsc_fd listen;
|
||||
struct gsm_network *gsm_network;
|
||||
|
||||
const char *last_state_command;
|
||||
|
||||
/* delay the command */
|
||||
char last_request;
|
||||
struct timer_list delay_cmd;
|
||||
|
||||
/* verify that RF is up as it should be */
|
||||
struct timer_list rf_check;
|
||||
|
||||
/* some handling for the automatic grace switch */
|
||||
struct timer_list grace_timeout;
|
||||
};
|
||||
|
||||
struct osmo_bsc_rf_conn {
|
||||
|
||||
@@ -6,18 +6,17 @@
|
||||
* All Rights Reserved
|
||||
*
|
||||
* 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 2 of the License, or
|
||||
* 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.
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -29,6 +28,12 @@
|
||||
#include <osmocore/timer.h>
|
||||
|
||||
struct osmo_bsc_rf;
|
||||
struct gsm_network;
|
||||
|
||||
struct gsm_audio_support {
|
||||
uint8_t hr : 1,
|
||||
ver : 7;
|
||||
};
|
||||
|
||||
struct osmo_msc_data {
|
||||
/* Connection data */
|
||||
@@ -41,16 +46,31 @@ struct osmo_msc_data {
|
||||
struct timer_list ping_timer;
|
||||
struct timer_list pong_timer;
|
||||
struct bsc_msc_connection *msc_con;
|
||||
int core_ncc;
|
||||
int core_mcc;
|
||||
int rtp_base;
|
||||
|
||||
/* audio codecs */
|
||||
struct gsm_audio_support **audio_support;
|
||||
int audio_length;
|
||||
|
||||
|
||||
/* mgcp agent */
|
||||
struct write_queue mgcp_agent;
|
||||
|
||||
/* rf ctl related bits */
|
||||
char *ussd_grace_txt;
|
||||
char *mid_call_txt;
|
||||
int mid_call_timeout;
|
||||
struct osmo_bsc_rf *rf_ctl;
|
||||
|
||||
/* ussd welcome text */
|
||||
char *ussd_welcome_txt;
|
||||
};
|
||||
|
||||
int osmo_bsc_msc_init(struct gsm_network *network);
|
||||
int osmo_bsc_sccp_init(struct gsm_network *gsmnet);
|
||||
int msc_queue_write(struct bsc_msc_connection *conn, struct msgb *msg, int proto);
|
||||
|
||||
int osmo_bsc_audio_init(struct gsm_network *network);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -3,18 +3,17 @@
|
||||
* All Rights Reserved
|
||||
*
|
||||
* 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 2 of the License, or
|
||||
* 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.
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -29,6 +28,31 @@
|
||||
#include "gsm_subscriber.h"
|
||||
#include <osmocore/timer.h>
|
||||
|
||||
/**
|
||||
* A pending paging request
|
||||
*/
|
||||
struct gsm_paging_request {
|
||||
/* list_head for list of all paging requests */
|
||||
struct llist_head entry;
|
||||
/* the subscriber which we're paging. Later gsm_paging_request
|
||||
* should probably become a part of the gsm_subscriber struct? */
|
||||
struct gsm_subscriber *subscr;
|
||||
/* back-pointer to the BTS on which we are paging */
|
||||
struct gsm_bts *bts;
|
||||
/* what kind of channel type do we ask the MS to establish */
|
||||
int chan_type;
|
||||
|
||||
/* Timer 3113: how long do we try to page? */
|
||||
struct timer_list T3113;
|
||||
|
||||
/* How often did we ask the BTS to page? */
|
||||
int attempts;
|
||||
|
||||
/* callback to be called in case paging completes */
|
||||
gsm_cbfn *cbfn;
|
||||
void *cbfn_param;
|
||||
};
|
||||
|
||||
/* call once for every gsm_bts... */
|
||||
void paging_init(struct gsm_bts *bts);
|
||||
|
||||
@@ -38,7 +62,8 @@ int paging_request(struct gsm_network *network, struct gsm_subscriber *subscr,
|
||||
|
||||
/* stop paging requests */
|
||||
void paging_request_stop(struct gsm_bts *bts, struct gsm_subscriber *subscr,
|
||||
struct gsm_subscriber_connection *conn);
|
||||
struct gsm_subscriber_connection *conn,
|
||||
struct msgb *msg);
|
||||
|
||||
/* update paging load */
|
||||
void paging_update_buffer_space(struct gsm_bts *bts, u_int16_t);
|
||||
|
||||
@@ -7,18 +7,17 @@
|
||||
* All Rights Reserved
|
||||
*
|
||||
* 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 2 of the License, or
|
||||
* 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.
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
@@ -5,18 +5,17 @@
|
||||
* All Rights Reserved
|
||||
*
|
||||
* 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 2 of the License, or
|
||||
* 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.
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -47,6 +46,8 @@ enum signal_subsystems {
|
||||
SS_IPAC_NWL,
|
||||
SS_RF,
|
||||
SS_MSC,
|
||||
SS_HO,
|
||||
SS_INPUT,
|
||||
};
|
||||
|
||||
/* SS_PAGING signals */
|
||||
@@ -61,6 +62,7 @@ enum signal_sms {
|
||||
S_SMS_DELIVERED, /* A SMS has been successfully delivered to a MS */
|
||||
S_SMS_SMMA, /* A MS tells us it has more space available */
|
||||
S_SMS_MEM_EXCEEDED, /* A MS tells us it has no more space available */
|
||||
S_SMS_UNKNOWN_ERROR, /* A MS tells us it has an error */
|
||||
};
|
||||
|
||||
/* SS_ABISIP signals */
|
||||
@@ -80,6 +82,8 @@ enum signal_nm {
|
||||
S_NM_IPACC_RESTART_ACK, /* nanoBTS has send a restart ack */
|
||||
S_NM_IPACC_RESTART_NACK,/* nanoBTS has send a restart ack */
|
||||
S_NM_TEST_REP, /* GSM 12.21 Test Report */
|
||||
S_NM_STATECHG_OPER, /* Operational State changed*/
|
||||
S_NM_STATECHG_ADM, /* Administrative State changed */
|
||||
};
|
||||
|
||||
/* SS_LCHAN signals */
|
||||
@@ -125,6 +129,7 @@ enum signal_ipaccess {
|
||||
|
||||
enum signal_global {
|
||||
S_GLOBAL_SHUTDOWN,
|
||||
S_GLOBAL_BTS_CLOSE_OM,
|
||||
};
|
||||
|
||||
/* SS_RF signals */
|
||||
@@ -134,12 +139,24 @@ enum signal_rf {
|
||||
S_RF_GRACE,
|
||||
};
|
||||
|
||||
/* SS_INPUT signals */
|
||||
enum signal_input {
|
||||
S_INP_NONE,
|
||||
S_INP_TEI_UP,
|
||||
S_INP_TEI_DN,
|
||||
S_INP_LINE_INIT,
|
||||
S_INP_LINE_ALARM,
|
||||
S_INP_LINE_NOALARM,
|
||||
};
|
||||
|
||||
struct gsm_subscriber;
|
||||
|
||||
struct paging_signal_data {
|
||||
struct gsm_subscriber *subscr;
|
||||
struct gsm_bts *bts;
|
||||
|
||||
int paging_result;
|
||||
|
||||
/* NULL in case the paging didn't work */
|
||||
struct gsm_subscriber_connection *conn;
|
||||
};
|
||||
@@ -155,6 +172,14 @@ struct ipacc_ack_signal_data {
|
||||
u_int8_t msg_type;
|
||||
};
|
||||
|
||||
struct nm_statechg_signal_data {
|
||||
u_int8_t obj_class;
|
||||
void *obj;
|
||||
struct gsm_nm_state *old_state;
|
||||
struct gsm_nm_state *new_state;
|
||||
struct abis_om_obj_inst *obj_inst;
|
||||
};
|
||||
|
||||
struct nm_nack_signal_data {
|
||||
struct msgb *msg;
|
||||
uint8_t mt;
|
||||
@@ -170,6 +195,22 @@ struct rf_signal_data {
|
||||
struct gsm_network *net;
|
||||
};
|
||||
|
||||
struct sms_signal_data {
|
||||
/* The transaction where this occured */
|
||||
struct gsm_trans *trans;
|
||||
/* Can be NULL for SMMA */
|
||||
struct gsm_sms *sms;
|
||||
/* int paging result. Only the ones with > 0 */
|
||||
int paging_result;
|
||||
};
|
||||
|
||||
struct lchan_signal_data {
|
||||
/* The lchan the signal happened on */
|
||||
struct gsm_lchan *lchan;
|
||||
/* Measurement reports on this lchan */
|
||||
struct gsm_meas_rep *mr;
|
||||
};
|
||||
|
||||
enum signal_ns {
|
||||
S_NS_RESET,
|
||||
S_NS_BLOCK,
|
||||
@@ -193,5 +234,22 @@ struct msc_signal_data {
|
||||
struct osmo_msc_data *data;
|
||||
};
|
||||
|
||||
/* handover */
|
||||
enum signal_ho {
|
||||
S_HANDOVER_ACK,
|
||||
};
|
||||
|
||||
struct ho_signal_data {
|
||||
struct gsm_lchan *old_lchan;
|
||||
struct gsm_lchan *new_lchan;
|
||||
};
|
||||
|
||||
struct input_signal_data {
|
||||
int link_type;
|
||||
uint8_t tei;
|
||||
uint8_t sapi;
|
||||
struct gsm_bts_trx *trx;
|
||||
struct e1inp_line *line;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
17
openbsc/include/openbsc/sms_queue.h
Normal file
17
openbsc/include/openbsc/sms_queue.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#ifndef SMS_QUEUE_H
|
||||
#define SMS_QUEUE_H
|
||||
|
||||
struct gsm_network;
|
||||
struct gsm_sms_queue;
|
||||
struct vty;
|
||||
|
||||
int sms_queue_start(struct gsm_network *, int in_flight);
|
||||
int sms_queue_trigger(struct gsm_sms_queue *);
|
||||
|
||||
/* vty helper functions */
|
||||
int sms_queue_stats(struct gsm_sms_queue *, struct vty* vty);
|
||||
int sms_queue_set_max_pending(struct gsm_sms_queue *, int max);
|
||||
int sms_queue_set_max_failure(struct gsm_sms_queue *, int fail);
|
||||
int sms_queue_clear(struct gsm_sms_queue *);
|
||||
|
||||
#endif
|
||||
@@ -6,18 +6,17 @@
|
||||
* All Rights Reserved
|
||||
*
|
||||
* 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 2 of the License, or
|
||||
* 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.
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
|
||||
#define GSM_MACBLOCK_LEN 23
|
||||
|
||||
struct gsm_bts;
|
||||
|
||||
|
||||
enum osmo_sysinfo_type {
|
||||
SYSINFO_TYPE_NONE,
|
||||
SYSINFO_TYPE_1,
|
||||
@@ -34,7 +37,7 @@ enum osmo_sysinfo_type {
|
||||
|
||||
typedef u_int8_t sysinfo_buf_t[GSM_MACBLOCK_LEN];
|
||||
|
||||
const struct value_string osmo_sitype_strs[_MAX_SYSINFO_TYPE];
|
||||
extern const struct value_string osmo_sitype_strs[_MAX_SYSINFO_TYPE];
|
||||
uint8_t gsm_sitype2rsl(enum osmo_sysinfo_type si_type);
|
||||
const char *gsm_sitype_name(enum osmo_sysinfo_type si_type);
|
||||
int gsm_generate_si(struct gsm_bts *bts, enum osmo_sysinfo_type type);
|
||||
|
||||
@@ -29,6 +29,9 @@ struct gsm_trans {
|
||||
/* if traffic channel receive was requested */
|
||||
int tch_recv;
|
||||
|
||||
/* is thats one paging? */
|
||||
struct gsm_network **paging_request;
|
||||
|
||||
union {
|
||||
struct {
|
||||
|
||||
|
||||
@@ -6,18 +6,17 @@
|
||||
* All Rights Reserved
|
||||
*
|
||||
* 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 2 of the License, or
|
||||
* 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.
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
@@ -4,18 +4,17 @@
|
||||
* All Rights Reserved
|
||||
*
|
||||
* 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 2 of the License, or
|
||||
* 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.
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
@@ -29,12 +29,18 @@ enum bsc_vty_node {
|
||||
NS_NODE,
|
||||
BSSGP_NODE,
|
||||
OML_NODE,
|
||||
E1INP_NODE,
|
||||
NAT_NODE,
|
||||
NAT_BSC_NODE,
|
||||
MSC_NODE,
|
||||
OM2K_NODE,
|
||||
TRUNK_NODE,
|
||||
};
|
||||
|
||||
extern int bsc_vty_is_config_node(struct vty *vty, int node);
|
||||
extern void bsc_replace_string(void *ctx, char **dst, const char *newstr);
|
||||
|
||||
int bsc_vty_init(void);
|
||||
int bsc_vty_init_extra(void);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
INCLUDES = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)
|
||||
AM_CFLAGS=-Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOVTY_CFLAGS)
|
||||
AM_LDFLAGS = $(LIBOSMOCORE_LIBS)
|
||||
AM_CFLAGS=-Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(COVERAGE_CFLAGS)
|
||||
AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(COVERAGE_LDFLAGS)
|
||||
|
||||
# build current directory before building gprs
|
||||
SUBDIRS = . ipaccess gprs
|
||||
@@ -13,29 +13,31 @@ if BUILD_BSC
|
||||
SUBDIRS += bsc
|
||||
endif
|
||||
|
||||
sbin_PROGRAMS = bsc_hack bs11_config isdnsync bsc_mgcp
|
||||
bin_PROGRAMS = bsc_hack bs11_config isdnsync bsc_mgcp
|
||||
noinst_LIBRARIES = libbsc.a libmsc.a libvty.a libmgcp.a
|
||||
|
||||
libbsc_a_SOURCES = abis_rsl.c abis_nm.c gsm_data.c gsm_04_08_utils.c \
|
||||
chan_alloc.c debug.c socket.c abis_nm_vty.c \
|
||||
libbsc_a_SOURCES = abis_rsl.c abis_nm.c abis_om2000.c gsm_data.c gsm_04_08_utils.c \
|
||||
chan_alloc.c debug.c socket.c abis_nm_vty.c abis_om2000_vty.c \
|
||||
gsm_subscriber_base.c subchan_demux.c bsc_rll.c transaction.c \
|
||||
trau_frame.c trau_mux.c paging.c e1_config.c e1_input.c \
|
||||
input/misdn.c input/ipaccess.c handover_logic.c \
|
||||
talloc_ctx.c system_information.c rest_octets.c \
|
||||
rtp_proxy.c bts_siemens_bs11.c bts_ipaccess_nanobts.c \
|
||||
trau_frame.c trau_mux.c paging.c \
|
||||
e1_config.c e1_input.c e1_input_vty.c \
|
||||
input/misdn.c input/ipaccess.c input/dahdi.c input/lapd.c \
|
||||
handover_logic.c talloc_ctx.c system_information.c rest_octets.c \
|
||||
bts_siemens_bs11.c bts_ipaccess_nanobts.c bts_ericsson_rbs2000.c mncc_upqueue.c \
|
||||
bts_unknown.c bsc_version.c bsc_api.c bsc_vty.c meas_rep.c gsm_04_80.c
|
||||
|
||||
libmsc_a_SOURCES = gsm_subscriber.c db.c \
|
||||
mncc.c gsm_04_08.c gsm_04_11.c transaction.c \
|
||||
mncc.c mncc_builtin.c mncc_sock.c \
|
||||
gsm_04_08.c gsm_04_11.c transaction.c \
|
||||
token_auth.c rrlp.c ussd.c silent_call.c \
|
||||
handover_decision.c auth.c \
|
||||
osmo_msc.c
|
||||
osmo_msc.c rtp_proxy.c
|
||||
|
||||
libvty_a_SOURCES = common_vty.c
|
||||
|
||||
libmgcp_a_SOURCES = mgcp/mgcp_protocol.c mgcp/mgcp_network.c mgcp/mgcp_vty.c
|
||||
|
||||
bsc_hack_SOURCES = bsc_hack.c bsc_init.c bsc_vty.c vty_interface_layer3.c
|
||||
bsc_hack_SOURCES = bsc_hack.c bsc_init.c bsc_vty.c vty_interface_layer3.c sms_queue.c
|
||||
bsc_hack_LDADD = libmsc.a libbsc.a libvty.a libmsc.a \
|
||||
-ldl -ldbi $(LIBCRYPT) $(LIBOSMOVTY_LIBS)
|
||||
|
||||
@@ -46,3 +48,5 @@ isdnsync_SOURCES = isdnsync.c
|
||||
|
||||
bsc_mgcp_SOURCES = mgcp/mgcp_main.c debug.c
|
||||
bsc_mgcp_LDADD = libvty.a libmgcp.a $(LIBOSMOVTY_LIBS)
|
||||
|
||||
EXTRA_DIST = input/lapd.h
|
||||
|
||||
269
openbsc/src/a3a8.c
Normal file
269
openbsc/src/a3a8.c
Normal file
@@ -0,0 +1,269 @@
|
||||
/* An implementation of the GSM A3A8 algorithm. (Specifically, COMP128.)
|
||||
*/
|
||||
|
||||
/* Copyright 1998, Marc Briceno, Ian Goldberg, and David Wagner.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of the authors nor the names of the contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Coded in C merely because C is a much more precise, concise form of
|
||||
* expression for these purposes. See Judge Patel if you have any problems
|
||||
* with this...
|
||||
* Of course, it's only authentication, so it should be exportable for the
|
||||
* usual boring reasons.
|
||||
*/
|
||||
|
||||
typedef unsigned char Byte;
|
||||
|
||||
#include <stdio.h>
|
||||
/* #define TEST */
|
||||
|
||||
/*
|
||||
* rand[0..15]: the challenge from the base station
|
||||
* key[0..15]: the SIM's A3/A8 long-term key Ki
|
||||
* simoutput[0..11]: what you'd get back if you fed rand and key to a real
|
||||
* SIM.
|
||||
*
|
||||
* The GSM spec states that simoutput[0..3] is SRES,
|
||||
* and simoutput[4..11] is Kc (the A5 session key).
|
||||
* (See GSM 11.11, Section 8.16. See also the leaked document
|
||||
* referenced below.)
|
||||
* Note that Kc is bits 74..127 of the COMP128 output, followed by 10
|
||||
* zeros.
|
||||
* In other words, A5 is keyed with only 54 bits of entropy. This
|
||||
* represents a deliberate weakening of the key used for voice privacy
|
||||
* by a factor of over 1000.
|
||||
*
|
||||
* Verified with a Pacific Bell Schlumberger SIM. Your mileage may vary.
|
||||
*
|
||||
* Marc Briceno <marc@scard.org>, Ian Goldberg <iang@cs.berkeley.edu>,
|
||||
* and David Wagner <daw@cs.berkeley.edu>
|
||||
*/
|
||||
|
||||
void A3A8(/* in */ Byte rand[16], /* in */ Byte key[16],
|
||||
/* out */ Byte simoutput[12]);
|
||||
|
||||
/* The compression tables. */
|
||||
static const Byte table_0[512] = {
|
||||
102,177,186,162, 2,156,112, 75, 55, 25, 8, 12,251,193,246,188,
|
||||
109,213,151, 53, 42, 79,191,115,233,242,164,223,209,148,108,161,
|
||||
252, 37,244, 47, 64,211, 6,237,185,160,139,113, 76,138, 59, 70,
|
||||
67, 26, 13,157, 63,179,221, 30,214, 36,166, 69,152,124,207,116,
|
||||
247,194, 41, 84, 71, 1, 49, 14, 95, 35,169, 21, 96, 78,215,225,
|
||||
182,243, 28, 92,201,118, 4, 74,248,128, 17, 11,146,132,245, 48,
|
||||
149, 90,120, 39, 87,230,106,232,175, 19,126,190,202,141,137,176,
|
||||
250, 27,101, 40,219,227, 58, 20, 51,178, 98,216,140, 22, 32,121,
|
||||
61,103,203, 72, 29,110, 85,212,180,204,150,183, 15, 66,172,196,
|
||||
56,197,158, 0,100, 45,153, 7,144,222,163,167, 60,135,210,231,
|
||||
174,165, 38,249,224, 34,220,229,217,208,241, 68,206,189,125,255,
|
||||
239, 54,168, 89,123,122, 73,145,117,234,143, 99,129,200,192, 82,
|
||||
104,170,136,235, 93, 81,205,173,236, 94,105, 52, 46,228,198, 5,
|
||||
57,254, 97,155,142,133,199,171,187, 50, 65,181,127,107,147,226,
|
||||
184,218,131, 33, 77, 86, 31, 44, 88, 62,238, 18, 24, 43,154, 23,
|
||||
80,159,134,111, 9,114, 3, 91, 16,130, 83, 10,195,240,253,119,
|
||||
177,102,162,186,156, 2, 75,112, 25, 55, 12, 8,193,251,188,246,
|
||||
213,109, 53,151, 79, 42,115,191,242,233,223,164,148,209,161,108,
|
||||
37,252, 47,244,211, 64,237, 6,160,185,113,139,138, 76, 70, 59,
|
||||
26, 67,157, 13,179, 63, 30,221, 36,214, 69,166,124,152,116,207,
|
||||
194,247, 84, 41, 1, 71, 14, 49, 35, 95, 21,169, 78, 96,225,215,
|
||||
243,182, 92, 28,118,201, 74, 4,128,248, 11, 17,132,146, 48,245,
|
||||
90,149, 39,120,230, 87,232,106, 19,175,190,126,141,202,176,137,
|
||||
27,250, 40,101,227,219, 20, 58,178, 51,216, 98, 22,140,121, 32,
|
||||
103, 61, 72,203,110, 29,212, 85,204,180,183,150, 66, 15,196,172,
|
||||
197, 56, 0,158, 45,100, 7,153,222,144,167,163,135, 60,231,210,
|
||||
165,174,249, 38, 34,224,229,220,208,217, 68,241,189,206,255,125,
|
||||
54,239, 89,168,122,123,145, 73,234,117, 99,143,200,129, 82,192,
|
||||
170,104,235,136, 81, 93,173,205, 94,236, 52,105,228, 46, 5,198,
|
||||
254, 57,155, 97,133,142,171,199, 50,187,181, 65,107,127,226,147,
|
||||
218,184, 33,131, 86, 77, 44, 31, 62, 88, 18,238, 43, 24, 23,154,
|
||||
159, 80,111,134,114, 9, 91, 3,130, 16, 10, 83,240,195,119,253
|
||||
}, table_1[256] = {
|
||||
19, 11, 80,114, 43, 1, 69, 94, 39, 18,127,117, 97, 3, 85, 43,
|
||||
27,124, 70, 83, 47, 71, 63, 10, 47, 89, 79, 4, 14, 59, 11, 5,
|
||||
35,107,103, 68, 21, 86, 36, 91, 85,126, 32, 50,109, 94,120, 6,
|
||||
53, 79, 28, 45, 99, 95, 41, 34, 88, 68, 93, 55,110,125,105, 20,
|
||||
90, 80, 76, 96, 23, 60, 89, 64,121, 56, 14, 74,101, 8, 19, 78,
|
||||
76, 66,104, 46,111, 50, 32, 3, 39, 0, 58, 25, 92, 22, 18, 51,
|
||||
57, 65,119,116, 22,109, 7, 86, 59, 93, 62,110, 78, 99, 77, 67,
|
||||
12,113, 87, 98,102, 5, 88, 33, 38, 56, 23, 8, 75, 45, 13, 75,
|
||||
95, 63, 28, 49,123,120, 20,112, 44, 30, 15, 98,106, 2,103, 29,
|
||||
82,107, 42,124, 24, 30, 41, 16,108,100,117, 40, 73, 40, 7,114,
|
||||
82,115, 36,112, 12,102,100, 84, 92, 48, 72, 97, 9, 54, 55, 74,
|
||||
113,123, 17, 26, 53, 58, 4, 9, 69,122, 21,118, 42, 60, 27, 73,
|
||||
118,125, 34, 15, 65,115, 84, 64, 62, 81, 70, 1, 24,111,121, 83,
|
||||
104, 81, 49,127, 48,105, 31, 10, 6, 91, 87, 37, 16, 54,116,126,
|
||||
31, 38, 13, 0, 72,106, 77, 61, 26, 67, 46, 29, 96, 37, 61, 52,
|
||||
101, 17, 44,108, 71, 52, 66, 57, 33, 51, 25, 90, 2,119,122, 35
|
||||
}, table_2[128] = {
|
||||
52, 50, 44, 6, 21, 49, 41, 59, 39, 51, 25, 32, 51, 47, 52, 43,
|
||||
37, 4, 40, 34, 61, 12, 28, 4, 58, 23, 8, 15, 12, 22, 9, 18,
|
||||
55, 10, 33, 35, 50, 1, 43, 3, 57, 13, 62, 14, 7, 42, 44, 59,
|
||||
62, 57, 27, 6, 8, 31, 26, 54, 41, 22, 45, 20, 39, 3, 16, 56,
|
||||
48, 2, 21, 28, 36, 42, 60, 33, 34, 18, 0, 11, 24, 10, 17, 61,
|
||||
29, 14, 45, 26, 55, 46, 11, 17, 54, 46, 9, 24, 30, 60, 32, 0,
|
||||
20, 38, 2, 30, 58, 35, 1, 16, 56, 40, 23, 48, 13, 19, 19, 27,
|
||||
31, 53, 47, 38, 63, 15, 49, 5, 37, 53, 25, 36, 63, 29, 5, 7
|
||||
}, table_3[64] = {
|
||||
1, 5, 29, 6, 25, 1, 18, 23, 17, 19, 0, 9, 24, 25, 6, 31,
|
||||
28, 20, 24, 30, 4, 27, 3, 13, 15, 16, 14, 18, 4, 3, 8, 9,
|
||||
20, 0, 12, 26, 21, 8, 28, 2, 29, 2, 15, 7, 11, 22, 14, 10,
|
||||
17, 21, 12, 30, 26, 27, 16, 31, 11, 7, 13, 23, 10, 5, 22, 19
|
||||
}, table_4[32] = {
|
||||
15, 12, 10, 4, 1, 14, 11, 7, 5, 0, 14, 7, 1, 2, 13, 8,
|
||||
10, 3, 4, 9, 6, 0, 3, 2, 5, 6, 8, 9, 11, 13, 15, 12
|
||||
}, *table[5] = { table_0, table_1, table_2, table_3, table_4 };
|
||||
|
||||
/*
|
||||
* This code derived from a leaked document from the GSM standards.
|
||||
* Some missing pieces were filled in by reverse-engineering a working SIM.
|
||||
* We have verified that this is the correct COMP128 algorithm.
|
||||
*
|
||||
* The first page of the document identifies it as
|
||||
* _Technical Information: GSM System Security Study_.
|
||||
* 10-1617-01, 10th June 1988.
|
||||
* The bottom of the title page is marked
|
||||
* Racal Research Ltd.
|
||||
* Worton Drive, Worton Grange Industrial Estate,
|
||||
* Reading, Berks. RG2 0SB, England.
|
||||
* Telephone: Reading (0734) 868601 Telex: 847152
|
||||
* The relevant bits are in Part I, Section 20 (pages 66--67). Enjoy!
|
||||
*
|
||||
* Note: There are three typos in the spec (discovered by
|
||||
* reverse-engineering).
|
||||
* First, "z = (2 * x[n] + x[n]) mod 2^(9-j)" should clearly read
|
||||
* "z = (2 * x[m] + x[n]) mod 2^(9-j)".
|
||||
* Second, the "k" loop in the "Form bits from bytes" section is severely
|
||||
* botched: the k index should run only from 0 to 3, and clearly the range
|
||||
* on "the (8-k)th bit of byte j" is also off (should be 0..7, not 1..8,
|
||||
* to be consistent with the subsequent section).
|
||||
* Third, SRES is taken from the first 8 nibbles of x[], not the last 8 as
|
||||
* claimed in the document. (And the document doesn't specify how Kc is
|
||||
* derived, but that was also easily discovered with reverse engineering.)
|
||||
* All of these typos have been corrected in the following code.
|
||||
*/
|
||||
|
||||
void A3A8(/* in */ Byte rand[16], /* in */ Byte key[16],
|
||||
/* out */ Byte simoutput[12])
|
||||
{
|
||||
Byte x[32], bit[128];
|
||||
int i, j, k, l, m, n, y, z, next_bit;
|
||||
|
||||
/* ( Load RAND into last 16 bytes of input ) */
|
||||
for (i=16; i<32; i++)
|
||||
x[i] = rand[i-16];
|
||||
|
||||
/* ( Loop eight times ) */
|
||||
for (i=1; i<9; i++) {
|
||||
/* ( Load key into first 16 bytes of input ) */
|
||||
for (j=0; j<16; j++)
|
||||
x[j] = key[j];
|
||||
/* ( Perform substitutions ) */
|
||||
for (j=0; j<5; j++)
|
||||
for (k=0; k<(1<<j); k++)
|
||||
for (l=0; l<(1<<(4-j)); l++) {
|
||||
m = l + k*(1<<(5-j));
|
||||
n = m + (1<<(4-j));
|
||||
y = (x[m]+2*x[n]) % (1<<(9-j));
|
||||
z = (2*x[m]+x[n]) % (1<<(9-j));
|
||||
x[m] = table[j][y];
|
||||
x[n] = table[j][z];
|
||||
}
|
||||
/* ( Form bits from bytes ) */
|
||||
for (j=0; j<32; j++)
|
||||
for (k=0; k<4; k++)
|
||||
bit[4*j+k] = (x[j]>>(3-k)) & 1;
|
||||
/* ( Permutation but not on the last loop ) */
|
||||
if (i < 8)
|
||||
for (j=0; j<16; j++) {
|
||||
x[j+16] = 0;
|
||||
for (k=0; k<8; k++) {
|
||||
next_bit = ((8*j + k)*17) % 128;
|
||||
x[j+16] |= bit[next_bit] << (7-k);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* ( At this stage the vector x[] consists of 32 nibbles.
|
||||
* The first 8 of these are taken as the output SRES. )
|
||||
*/
|
||||
|
||||
/* The remainder of the code is not given explicitly in the
|
||||
* standard, but was derived by reverse-engineering.
|
||||
*/
|
||||
|
||||
for (i=0; i<4; i++)
|
||||
simoutput[i] = (x[2*i]<<4) | x[2*i+1];
|
||||
for (i=0; i<6; i++)
|
||||
simoutput[4+i] = (x[2*i+18]<<6) | (x[2*i+18+1]<<2)
|
||||
| (x[2*i+18+2]>>2);
|
||||
simoutput[4+6] = (x[2*6+18]<<6) | (x[2*6+18+1]<<2);
|
||||
simoutput[4+7] = 0;
|
||||
}
|
||||
|
||||
|
||||
#ifdef TEST
|
||||
int hextoint(char x)
|
||||
{
|
||||
x = toupper(x);
|
||||
if (x >= 'A' && x <= 'F')
|
||||
return x-'A'+10;
|
||||
else if (x >= '0' && x <= '9')
|
||||
return x-'0';
|
||||
fprintf(stderr, "bad input.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
Byte key[16], rand[16], simoutput[12];
|
||||
int i;
|
||||
|
||||
if (argc != 3 || strlen(argv[1]) != 34 || strlen(argv[2]) != 34
|
||||
|| strncmp(argv[1], "0x", 2) != 0
|
||||
|| strncmp(argv[2], "0x", 2) != 0) {
|
||||
fprintf(stderr, "Usage: %s 0x<key> 0x<rand>\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for (i=0; i<16; i++)
|
||||
key[i] = (hextoint(argv[1][2*i+2])<<4)
|
||||
| hextoint(argv[1][2*i+3]);
|
||||
for (i=0; i<16; i++)
|
||||
rand[i] = (hextoint(argv[2][2*i+2])<<4)
|
||||
| hextoint(argv[2][2*i+3]);
|
||||
A3A8(rand, key, simoutput);
|
||||
printf("simoutput: ");
|
||||
for (i=0; i<12; i++)
|
||||
printf("%02X", simoutput[i]);
|
||||
printf("\n");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -6,18 +6,17 @@
|
||||
* All Rights Reserved
|
||||
*
|
||||
* 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 2 of the License, or
|
||||
* 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.
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -410,11 +409,31 @@ static struct msgb *nm_msgb_alloc(void)
|
||||
}
|
||||
|
||||
/* Send a OML NM Message from BSC to BTS */
|
||||
int abis_nm_sendmsg(struct gsm_bts *bts, struct msgb *msg)
|
||||
static int abis_nm_queue_msg(struct gsm_bts *bts, struct msgb *msg)
|
||||
{
|
||||
msg->trx = bts->c0;
|
||||
|
||||
return _abis_nm_sendmsg(msg);
|
||||
/* queue OML messages */
|
||||
if (llist_empty(&bts->abis_queue) && !bts->abis_nm_pend) {
|
||||
bts->abis_nm_pend = OBSC_NM_W_ACK_CB(msg);
|
||||
return _abis_nm_sendmsg(msg, 0);
|
||||
} else {
|
||||
msgb_enqueue(&bts->abis_queue, msg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int abis_nm_sendmsg(struct gsm_bts *bts, struct msgb *msg)
|
||||
{
|
||||
OBSC_NM_W_ACK_CB(msg) = 1;
|
||||
return abis_nm_queue_msg(bts, msg);
|
||||
}
|
||||
|
||||
static int abis_nm_sendmsg_direct(struct gsm_bts *bts, struct msgb *msg)
|
||||
{
|
||||
OBSC_NM_W_ACK_CB(msg) = 0;
|
||||
return abis_nm_queue_msg(bts, msg);
|
||||
}
|
||||
|
||||
static int abis_nm_rcvmsg_sw(struct msgb *mb);
|
||||
@@ -664,11 +683,10 @@ static int update_admstate(struct gsm_bts *bts, u_int8_t obj_class,
|
||||
struct abis_om_obj_inst *obj_inst, u_int8_t adm_state)
|
||||
{
|
||||
struct gsm_nm_state *nm_state, new_state;
|
||||
void *obj;
|
||||
int rc;
|
||||
struct nm_statechg_signal_data nsd;
|
||||
|
||||
obj = objclass2obj(bts, obj_class, obj_inst);
|
||||
if (!obj)
|
||||
nsd.obj = objclass2obj(bts, obj_class, obj_inst);
|
||||
if (!nsd.obj)
|
||||
return -EINVAL;
|
||||
nm_state = objclass2nmstate(bts, obj_class, obj_inst);
|
||||
if (!nm_state)
|
||||
@@ -677,11 +695,15 @@ static int update_admstate(struct gsm_bts *bts, u_int8_t obj_class,
|
||||
new_state = *nm_state;
|
||||
new_state.administrative = adm_state;
|
||||
|
||||
rc = nm_state_event(EVT_STATECHG_ADM, obj_class, obj, nm_state, &new_state, obj_inst);
|
||||
nsd.obj_class = obj_class;
|
||||
nsd.old_state = nm_state;
|
||||
nsd.new_state = &new_state;
|
||||
nsd.obj_inst = obj_inst;
|
||||
dispatch_signal(SS_NM, S_NM_STATECHG_ADM, &nsd);
|
||||
|
||||
nm_state->administrative = adm_state;
|
||||
|
||||
return rc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int abis_nm_rx_statechg_rep(struct msgb *mb)
|
||||
@@ -691,7 +713,6 @@ static int abis_nm_rx_statechg_rep(struct msgb *mb)
|
||||
struct gsm_bts *bts = mb->trx->bts;
|
||||
struct tlv_parsed tp;
|
||||
struct gsm_nm_state *nm_state, new_state;
|
||||
int rc;
|
||||
|
||||
DEBUGPC(DNM, "STATE CHG: ");
|
||||
|
||||
@@ -730,8 +751,13 @@ static int abis_nm_rx_statechg_rep(struct msgb *mb)
|
||||
new_state.availability != nm_state->availability) {
|
||||
/* Update the operational state of a given object in our in-memory data
|
||||
* structures and send an event to the higher layer */
|
||||
void *obj = objclass2obj(bts, foh->obj_class, &foh->obj_inst);
|
||||
rc = nm_state_event(EVT_STATECHG_OPER, foh->obj_class, obj, nm_state, &new_state, &foh->obj_inst);
|
||||
struct nm_statechg_signal_data nsd;
|
||||
nsd.obj = objclass2obj(bts, foh->obj_class, &foh->obj_inst);
|
||||
nsd.obj_class = foh->obj_class;
|
||||
nsd.old_state = nm_state;
|
||||
nsd.new_state = &new_state;
|
||||
nsd.obj_inst = &foh->obj_inst;
|
||||
dispatch_signal(SS_NM, S_NM_STATECHG_OPER, &nsd);
|
||||
nm_state->operational = new_state.operational;
|
||||
nm_state->availability = new_state.availability;
|
||||
if (nm_state->administrative == 0)
|
||||
@@ -754,6 +780,8 @@ static int rx_fail_evt_rep(struct msgb *mb)
|
||||
struct abis_om_hdr *oh = msgb_l2(mb);
|
||||
struct abis_om_fom_hdr *foh = msgb_l3(mb);
|
||||
struct tlv_parsed tp;
|
||||
const uint8_t *p_val;
|
||||
char *p_text;
|
||||
|
||||
DEBUGPC(DNM, "Failure Event Report ");
|
||||
|
||||
@@ -763,6 +791,18 @@ static int rx_fail_evt_rep(struct msgb *mb)
|
||||
DEBUGPC(DNM, "Type=%s ", event_type_name(*TLVP_VAL(&tp, NM_ATT_EVENT_TYPE)));
|
||||
if (TLVP_PRESENT(&tp, NM_ATT_SEVERITY))
|
||||
DEBUGPC(DNM, "Severity=%s ", severity_name(*TLVP_VAL(&tp, NM_ATT_SEVERITY)));
|
||||
if (TLVP_PRESENT(&tp, NM_ATT_PROB_CAUSE)) {
|
||||
p_val = TLVP_VAL(&tp, NM_ATT_PROB_CAUSE);
|
||||
DEBUGPC(DNM, "Probable cause= %02X %02X %02X ", p_val[0], p_val[1], p_val[2]);
|
||||
}
|
||||
if (TLVP_PRESENT(&tp, NM_ATT_ADD_TEXT)) {
|
||||
p_val = TLVP_VAL(&tp, NM_ATT_ADD_TEXT);
|
||||
p_text = talloc_strndup(tall_bsc_ctx, (const char *) p_val, TLVP_LEN(&tp, NM_ATT_ADD_TEXT));
|
||||
if (p_text) {
|
||||
DEBUGPC(DNM, "Additional Text=%s ", p_text);
|
||||
talloc_free(p_text);
|
||||
}
|
||||
}
|
||||
|
||||
DEBUGPC(DNM, "\n");
|
||||
|
||||
@@ -951,12 +991,30 @@ static int abis_nm_rx_lmt_event(struct msgb *mb)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void abis_nm_queue_send_next(struct gsm_bts *bts)
|
||||
{
|
||||
int wait = 0;
|
||||
struct msgb *msg;
|
||||
/* the queue is empty */
|
||||
while (!llist_empty(&bts->abis_queue)) {
|
||||
msg = msgb_dequeue(&bts->abis_queue);
|
||||
wait = OBSC_NM_W_ACK_CB(msg);
|
||||
_abis_nm_sendmsg(msg, 0);
|
||||
|
||||
if (wait)
|
||||
break;
|
||||
}
|
||||
|
||||
bts->abis_nm_pend = wait;
|
||||
}
|
||||
|
||||
/* Receive a OML NM Message from BTS */
|
||||
static int abis_nm_rcvmsg_fom(struct msgb *mb)
|
||||
{
|
||||
struct abis_om_hdr *oh = msgb_l2(mb);
|
||||
struct abis_om_fom_hdr *foh = msgb_l3(mb);
|
||||
u_int8_t mt = foh->msg_type;
|
||||
int ret = 0;
|
||||
|
||||
/* check for unsolicited message */
|
||||
if (is_report(mt))
|
||||
@@ -983,6 +1041,7 @@ static int abis_nm_rcvmsg_fom(struct msgb *mb)
|
||||
nack_data.msg = mb;
|
||||
nack_data.mt = mt;
|
||||
dispatch_signal(SS_NM, S_NM_NACK, &nack_data);
|
||||
abis_nm_queue_send_next(mb->trx->bts);
|
||||
return 0;
|
||||
}
|
||||
#if 0
|
||||
@@ -1004,13 +1063,13 @@ static int abis_nm_rcvmsg_fom(struct msgb *mb)
|
||||
|
||||
switch (mt) {
|
||||
case NM_MT_CHG_ADM_STATE_ACK:
|
||||
return abis_nm_rx_chg_adm_state_ack(mb);
|
||||
ret = abis_nm_rx_chg_adm_state_ack(mb);
|
||||
break;
|
||||
case NM_MT_SW_ACT_REQ:
|
||||
return abis_nm_rx_sw_act_req(mb);
|
||||
ret = abis_nm_rx_sw_act_req(mb);
|
||||
break;
|
||||
case NM_MT_BS11_LMT_SESSION:
|
||||
return abis_nm_rx_lmt_event(mb);
|
||||
ret = abis_nm_rx_lmt_event(mb);
|
||||
break;
|
||||
case NM_MT_CONN_MDROP_LINK_ACK:
|
||||
DEBUGP(DNM, "CONN MDROP LINK ACK\n");
|
||||
@@ -1023,7 +1082,8 @@ static int abis_nm_rcvmsg_fom(struct msgb *mb)
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
abis_nm_queue_send_next(mb->trx->bts);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int abis_nm_rx_ipacc(struct msgb *mb);
|
||||
@@ -1036,6 +1096,7 @@ static int abis_nm_rcvmsg_manuf(struct msgb *mb)
|
||||
switch (bts_type) {
|
||||
case GSM_BTS_TYPE_NANOBTS:
|
||||
rc = abis_nm_rx_ipacc(mb);
|
||||
abis_nm_queue_send_next(mb->trx->bts);
|
||||
break;
|
||||
default:
|
||||
LOGP(DNM, LOGL_ERROR, "don't know how to parse OML for this "
|
||||
@@ -1280,7 +1341,7 @@ static int sw_load_segment(struct abis_nm_sw *sw)
|
||||
sw->obj_instance[0], sw->obj_instance[1],
|
||||
sw->obj_instance[2]);
|
||||
|
||||
return abis_nm_sendmsg(sw->bts, msg);
|
||||
return abis_nm_sendmsg_direct(sw->bts, msg);
|
||||
}
|
||||
|
||||
/* 6.2.4 / 8.3.4 Load Data End */
|
||||
@@ -1473,6 +1534,7 @@ static int abis_nm_rcvmsg_sw(struct msgb *mb)
|
||||
sw->cb_data, NULL);
|
||||
rc = sw_fill_window(sw);
|
||||
sw->state = SW_STATE_WAIT_SEGACK;
|
||||
abis_nm_queue_send_next(mb->trx->bts);
|
||||
break;
|
||||
case NM_MT_LOAD_INIT_NACK:
|
||||
if (sw->forced) {
|
||||
@@ -1493,6 +1555,7 @@ static int abis_nm_rcvmsg_sw(struct msgb *mb)
|
||||
sw->cb_data, NULL);
|
||||
sw->state = SW_STATE_ERROR;
|
||||
}
|
||||
abis_nm_queue_send_next(mb->trx->bts);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@@ -1513,6 +1576,7 @@ static int abis_nm_rcvmsg_sw(struct msgb *mb)
|
||||
sw->state = SW_STATE_WAIT_ENDACK;
|
||||
rc = sw_load_end(sw);
|
||||
}
|
||||
abis_nm_queue_send_next(mb->trx->bts);
|
||||
break;
|
||||
case NM_MT_LOAD_ABORT:
|
||||
if (sw->cbfn)
|
||||
@@ -1534,6 +1598,7 @@ static int abis_nm_rcvmsg_sw(struct msgb *mb)
|
||||
NM_MT_LOAD_END_ACK, mb,
|
||||
sw->cb_data, NULL);
|
||||
rc = 0;
|
||||
abis_nm_queue_send_next(mb->trx->bts);
|
||||
break;
|
||||
case NM_MT_LOAD_END_NACK:
|
||||
if (sw->forced) {
|
||||
@@ -1553,6 +1618,7 @@ static int abis_nm_rcvmsg_sw(struct msgb *mb)
|
||||
NM_MT_LOAD_END_NACK, mb,
|
||||
sw->cb_data, NULL);
|
||||
}
|
||||
abis_nm_queue_send_next(mb->trx->bts);
|
||||
break;
|
||||
}
|
||||
case SW_STATE_WAIT_ACTACK:
|
||||
@@ -1566,6 +1632,7 @@ static int abis_nm_rcvmsg_sw(struct msgb *mb)
|
||||
sw->cbfn(GSM_HOOK_NM_SWLOAD,
|
||||
NM_MT_ACTIVATE_SW_ACK, mb,
|
||||
sw->cb_data, NULL);
|
||||
abis_nm_queue_send_next(mb->trx->bts);
|
||||
break;
|
||||
case NM_MT_ACTIVATE_SW_NACK:
|
||||
DEBUGP(DNM, "Activate Software NACK\n");
|
||||
@@ -1575,6 +1642,7 @@ static int abis_nm_rcvmsg_sw(struct msgb *mb)
|
||||
sw->cbfn(GSM_HOOK_NM_SWLOAD,
|
||||
NM_MT_ACTIVATE_SW_NACK, mb,
|
||||
sw->cb_data, NULL);
|
||||
abis_nm_queue_send_next(mb->trx->bts);
|
||||
break;
|
||||
}
|
||||
case SW_STATE_NONE:
|
||||
@@ -1959,7 +2027,6 @@ int abis_nm_set_channel_attr(struct gsm_bts_trx_ts *ts, u_int8_t chan_comb)
|
||||
{
|
||||
struct gsm_bts *bts = ts->trx->bts;
|
||||
struct abis_om_hdr *oh;
|
||||
u_int16_t arfcn = htons(ts->trx->arfcn);
|
||||
u_int8_t zero = 0x00;
|
||||
struct msgb *msg = nm_msgb_alloc();
|
||||
u_int8_t len = 2 + 2;
|
||||
@@ -2032,7 +2099,7 @@ int abis_nm_sw_act_req_ack(struct gsm_bts *bts, u_int8_t obj_class, u_int8_t i1,
|
||||
if (nack)
|
||||
msgb_tv_put(msg, NM_ATT_NACK_CAUSES, NM_NACK_OBJCLASS_NOTSUPP);
|
||||
|
||||
return abis_nm_sendmsg(bts, msg);
|
||||
return abis_nm_sendmsg_direct(bts, msg);
|
||||
}
|
||||
|
||||
int abis_nm_raw_msg(struct gsm_bts *bts, int len, u_int8_t *rawmsg)
|
||||
@@ -2125,7 +2192,7 @@ int abis_nm_perform_test(struct gsm_bts *bts, u_int8_t obj_class,
|
||||
{
|
||||
struct abis_om_hdr *oh;
|
||||
|
||||
DEBUGP(DNM, "PEFORM TEST\n");
|
||||
DEBUGP(DNM, "PEFORM TEST %s\n", get_value_string(test_names, test_nr));
|
||||
|
||||
if (!msg)
|
||||
msg = nm_msgb_alloc();
|
||||
@@ -2681,6 +2748,20 @@ int abis_nm_bs11_set_ext_time(struct gsm_bts *bts)
|
||||
return abis_nm_sendmsg(bts, msg);
|
||||
}
|
||||
|
||||
int abis_nm_bs11_get_bport_line_cfg(struct gsm_bts *bts, u_int8_t bport)
|
||||
{
|
||||
struct abis_om_hdr *oh;
|
||||
struct msgb *msg = nm_msgb_alloc();
|
||||
u_int8_t attr = NM_ATT_BS11_LINE_CFG;
|
||||
|
||||
oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
|
||||
fill_om_fom_hdr(oh, 2+sizeof(attr), NM_MT_GET_ATTR,
|
||||
NM_OC_BS11_BPORT, bport, 0xff, 0x02);
|
||||
msgb_tlv_put(msg, NM_ATT_LIST_REQ_ATTR, sizeof(attr), &attr);
|
||||
|
||||
return abis_nm_sendmsg(bts, msg);
|
||||
}
|
||||
|
||||
int abis_nm_bs11_set_bport_line_cfg(struct gsm_bts *bts, u_int8_t bport, enum abis_bs11_line_cfg line_cfg)
|
||||
{
|
||||
struct abis_om_hdr *oh;
|
||||
@@ -3031,3 +3112,15 @@ int ipac_parse_bcch_info(struct ipac_bcch_info *binf, u_int8_t *buf)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void abis_nm_clear_queue(struct gsm_bts *bts)
|
||||
{
|
||||
struct msgb *msg;
|
||||
|
||||
while (!llist_empty(&bts->abis_queue)) {
|
||||
msg = msgb_dequeue(&bts->abis_queue);
|
||||
msgb_free(msg);
|
||||
}
|
||||
|
||||
bts->abis_nm_pend = 0;
|
||||
}
|
||||
|
||||
87
openbsc/src/abis_nm_ipaccess.c
Normal file
87
openbsc/src/abis_nm_ipaccess.c
Normal file
@@ -0,0 +1,87 @@
|
||||
/* GSM Network Management (OML) messages on the A-bis interface
|
||||
* Extensions for the ip.access A-bis over IP protocol*/
|
||||
|
||||
/* (C) 2008-2009 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/* A list of all the 'embedded' attributes of ip.access */
|
||||
enum ipa_embedded_att {
|
||||
IPA_ATT_ARFCN_WHITELIST = 0x01,
|
||||
IPA_ATT_ARFCN_BLACKLIST = 0x02,
|
||||
IPA_ATT_FREQ_ERR_LIST = 0x03,
|
||||
IPA_ATT_CHAN_USAGE_LIST = 0x04,
|
||||
IPA_ATT_BCCH_INF_TYPE = 0x05,
|
||||
IPA_ATT_BCCH_INF = 0x06,
|
||||
IPA_ATT_CONFIG = 0x07,
|
||||
IPA_ATT_RESULT_DETAILS = 0x08,
|
||||
IPA_ATT_RXLEV_THRESH = 0x09,
|
||||
IPA_ATT_FREQ_SYNC_OPT = 0x0a,
|
||||
IPA_ATT_MAC_ADDR = 0x0b,
|
||||
IPA_ATT_HW_SW_COMPAT_NR = 0x0c,
|
||||
IPA_ATT_MANUF_SER_NR = 0x0d,
|
||||
IPA_ATT_OEM_ID = 0x0e,
|
||||
IPA_ATT_DATETIME_MANUF = 0x0f,
|
||||
IPA_ATT_DATETIME_CALIB = 0x10,
|
||||
IPA_ATT_BEACON_INF = 0x11,
|
||||
IPA_ATT_FREQ_ERR = 0x12,
|
||||
IPA_ATT_SNMP_COMM_STRING = 0x13,
|
||||
IPA_ATT_SNMP_TRAP_ADDR = 0x14,
|
||||
IPA_ATT_SNMP_TRAP_PORT = 0x15,
|
||||
IPA_ATT_SNMP_MAN_ADDR = 0x16,
|
||||
IPA_ATT_SNMP_SYS_CONTACT = 0x17,
|
||||
IPA_ATT_FACTORY_ID = 0x18,
|
||||
IPA_ATT_FACTORY_SERIAL = 0x19,
|
||||
IPA_ATT_LOGGED_EVT_IND = 0x1a,
|
||||
IPA_ATT_LOCAL_ADD_TEXT = 0x1b,
|
||||
IPA_ATT_FREQ_BANDS = 0x1c,
|
||||
IPA_ATT_MAX_TA = 0x1d,
|
||||
IPA_ATT_CIPH_ALG = 0x1e,
|
||||
IPA_ATT_CHAN_TYPES = 0x1f,
|
||||
IPA_ATT_CHAN_MODES = 0x20,
|
||||
IPA_ATT_GPRS_CODING_SCHEMES = 0x21,
|
||||
IPA_ATT_RTP_FEATURES = 0x22,
|
||||
IPA_ATT_RSL_FEATURES = 0x23,
|
||||
IPA_ATT_BTS_HW_CLASS = 0x24,
|
||||
IPA_ATT_BTS_ID = 0x25,
|
||||
IPA_ATT_BCAST_L2_MSG = 0x26,
|
||||
};
|
||||
|
||||
/* append an ip.access channel list to the given msgb */
|
||||
static int ipa_chan_list_append(struct msgb *msg, u_int8_t ie,
|
||||
u_int16_t *arfcns, int arfcn_count)
|
||||
{
|
||||
int i;
|
||||
u_int8_t *u8;
|
||||
u_int16_t *u16;
|
||||
|
||||
/* tag */
|
||||
u8 = msgb_push(msg, 1);
|
||||
*u8 = ie;
|
||||
|
||||
/* length in octets */
|
||||
u16 = msgb_push(msg, 2);
|
||||
*u16 = htons(arfcn_count * 2);
|
||||
|
||||
for (i = 0; i < arfcn_count; i++) {
|
||||
u16 = msgb_push(msg, 2);
|
||||
*u16 = htons(arfcns[i]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -5,18 +5,17 @@
|
||||
* All Rights Reserved
|
||||
*
|
||||
* 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 2 of the License, or
|
||||
* 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.
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
878
openbsc/src/abis_om2000.c
Normal file
878
openbsc/src/abis_om2000.c
Normal file
@@ -0,0 +1,878 @@
|
||||
/* Ericsson RBS 2xxx GSM O&M (OM2000) messages on the A-bis interface
|
||||
* implemented based on protocol trace analysis, no formal documentation */
|
||||
|
||||
/* (C) 2010-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 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 <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <osmocore/msgb.h>
|
||||
#include <osmocore/tlv.h>
|
||||
#include <osmocore/talloc.h>
|
||||
#include <osmocore/utils.h>
|
||||
|
||||
#include <openbsc/gsm_data.h>
|
||||
#include <openbsc/debug.h>
|
||||
#include <openbsc/abis_nm.h>
|
||||
#include <openbsc/abis_om2000.h>
|
||||
#include <openbsc/signal.h>
|
||||
#include <openbsc/e1_input.h>
|
||||
|
||||
#define OM_ALLOC_SIZE 1024
|
||||
#define OM_HEADROOM_SIZE 128
|
||||
|
||||
/* use following functions from abis_nm.c:
|
||||
* om2k_msgb_alloc()
|
||||
* abis_om2k_sendmsg()
|
||||
*/
|
||||
|
||||
struct abis_om2k_hdr {
|
||||
struct abis_om_hdr om;
|
||||
uint16_t msg_type;
|
||||
struct abis_om2k_mo mo;
|
||||
uint8_t data[0];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
enum abis_om2k_msgtype {
|
||||
OM2K_MSGT_ABORT_SP_CMD = 0x0000,
|
||||
OM2K_MSGT_ABORT_SP_COMPL = 0x0002,
|
||||
OM2K_MSGT_ALARM_REP_ACK = 0x0004,
|
||||
OM2K_MSGT_ALARM_REP_NACK = 0x0005,
|
||||
OM2K_MSGT_ALARM_REP = 0x0006,
|
||||
OM2K_MSGT_ALARM_STATUS_REQ = 0x0008,
|
||||
OM2K_MSGT_ALARM_STATUS_REQ_ACK = 0x000a,
|
||||
OM2K_MSGT_ALARM_STATUS_REQ_REJ = 0x000b,
|
||||
OM2K_MSGT_ALARM_STATUS_RES_ACK = 0x000c,
|
||||
OM2K_MSGT_ALARM_STATUS_RES_NACK = 0x000d,
|
||||
OM2K_MSGT_ALARM_STATUS_RES = 0x000e,
|
||||
OM2K_MSGT_CAL_TIME_RESP = 0x0010,
|
||||
OM2K_MSGT_CAL_TIME_REJ = 0x0011,
|
||||
OM2K_MSGT_CAL_TIME_REQ = 0x0012,
|
||||
|
||||
OM2K_MSGT_CON_CONF_REQ = 0x0014,
|
||||
OM2K_MSGT_CON_CONF_REQ_ACK = 0x0016,
|
||||
OM2K_MSGT_CON_CONF_REQ_REJ = 0x0017,
|
||||
OM2K_MSGT_CON_CONF_RES_ACK = 0x0018,
|
||||
OM2K_MSGT_CON_CONF_RES_NACK = 0x0019,
|
||||
OM2K_MSGT_CON_CONF_RES = 0x001a,
|
||||
|
||||
OM2K_MSGT_CONNECT_CMD = 0x001c,
|
||||
OM2K_MSGT_CONNECT_COMPL = 0x001e,
|
||||
OM2K_MSGT_CONNECT_REJ = 0x001f,
|
||||
|
||||
OM2K_MSGT_DISABLE_REQ = 0x0028,
|
||||
OM2K_MSGT_DISABLE_REQ_ACK = 0x002a,
|
||||
OM2K_MSGT_DISABLE_REQ_REJ = 0x002b,
|
||||
OM2K_MSGT_DISABLE_RES_ACK = 0x002c,
|
||||
OM2K_MSGT_DISABLE_RES_NACK = 0x002d,
|
||||
OM2K_MSGT_DISABLE_RES = 0x002e,
|
||||
OM2K_MSGT_DISCONNECT_CMD = 0x0030,
|
||||
OM2K_MSGT_DISCONNECT_COMPL = 0x0032,
|
||||
OM2K_MSGT_DISCONNECT_REJ = 0x0033,
|
||||
OM2K_MSGT_ENABLE_REQ = 0x0034,
|
||||
OM2K_MSGT_ENABLE_REQ_ACK = 0x0036,
|
||||
OM2K_MSGT_ENABLE_REQ_REJ = 0x0037,
|
||||
OM2K_MSGT_ENABLE_RES_ACK = 0x0038,
|
||||
OM2K_MSGT_ENABLE_RES_NACK = 0x0039,
|
||||
OM2K_MSGT_ENABLE_RES = 0x003a,
|
||||
|
||||
OM2K_MSGT_FAULT_REP_ACK = 0x0040,
|
||||
OM2K_MSGT_FAULT_REP_NACK = 0x0041,
|
||||
OM2K_MSGT_FAULT_REP = 0x0042,
|
||||
|
||||
OM2K_MSGT_IS_CONF_REQ = 0x0060,
|
||||
OM2K_MSGT_IS_CONF_REQ_ACK = 0x0062,
|
||||
OM2K_MSGT_IS_CONF_REQ_REJ = 0x0063,
|
||||
OM2K_MSGT_IS_CONF_RES_ACK = 0x0064,
|
||||
OM2K_MSGT_IS_CONF_RES_NACK = 0x0065,
|
||||
OM2K_MSGT_IS_CONF_RES = 0x0066,
|
||||
|
||||
OM2K_MSGT_OP_INFO = 0x0074,
|
||||
OM2K_MSGT_OP_INFO_ACK = 0x0076,
|
||||
OM2K_MSGT_OP_INFO_REJ = 0x0077,
|
||||
OM2K_MSGT_RESET_CMD = 0x0078,
|
||||
OM2K_MSGT_RESET_COMPL = 0x007a,
|
||||
OM2K_MSGT_RESET_REJ = 0x007b,
|
||||
|
||||
OM2K_MSGT_START_REQ = 0x0084,
|
||||
OM2K_MSGT_START_REQ_ACK = 0x0086,
|
||||
OM2K_MSGT_START_REQ_REJ = 0x0087,
|
||||
OM2K_MSGT_START_RES_ACK = 0x0088,
|
||||
OM2K_MSGT_START_RES_NACK = 0x0089,
|
||||
OM2K_MSGT_START_RES = 0x008a,
|
||||
OM2K_MSGT_STATUS_REQ = 0x008c,
|
||||
OM2K_MSGT_STATUS_RESP = 0x008e,
|
||||
OM2K_MSGT_STATUS_REJ = 0x008f,
|
||||
|
||||
OM2K_MSGT_TEST_REQ = 0x0094,
|
||||
OM2K_MSGT_TEST_REQ_ACK = 0x0096,
|
||||
OM2K_MSGT_TEST_REQ_REJ = 0x0097,
|
||||
OM2K_MSGT_TEST_RES_ACK = 0x0098,
|
||||
OM2K_MSGT_TEST_RES_NACK = 0x0099,
|
||||
OM2K_MSGT_TEST_RES = 0x009a,
|
||||
|
||||
OM2K_MSGT_NEGOT_REQ_ACK = 0x0104,
|
||||
OM2K_MSGT_NEGOT_REQ_NACK = 0x0105,
|
||||
OM2K_MSGT_NEGOT_REQ = 0x0106,
|
||||
};
|
||||
|
||||
enum abis_om2k_dei {
|
||||
OM2K_DEI_CAL_TIME = 0x0d,
|
||||
OM2K_DEI_CON_CONN_LIST = 0x10,
|
||||
OM2K_DEI_END_LIST_NR = 0x13,
|
||||
OM2K_DEI_IS_CONN_LIST = 0x27,
|
||||
OM2K_DEI_LIST_NR = 0x28,
|
||||
OM2K_DEI_OP_INFO = 0x2e,
|
||||
OM2K_DEI_NEGOT_REC1 = 0x90,
|
||||
OM2K_DEI_NEGOT_REC2 = 0x91,
|
||||
};
|
||||
|
||||
enum abis_om2k_mo_cls {
|
||||
OM2K_MO_CLS_TRXC = 0x01,
|
||||
OM2K_MO_CLS_TS = 0x03,
|
||||
OM2K_MO_CLS_TF = 0x04,
|
||||
OM2K_MO_CLS_IS = 0x05,
|
||||
OM2K_MO_CLS_CON = 0x06,
|
||||
OM2K_MO_CLS_DP = 0x07,
|
||||
OM2K_MO_CLS_CF = 0x0a,
|
||||
OM2K_MO_CLS_TX = 0x0b,
|
||||
OM2K_MO_CLS_RX = 0x0c,
|
||||
};
|
||||
|
||||
static const struct value_string om2k_msgcode_vals[] = {
|
||||
{ 0x0000, "Abort SP Command" },
|
||||
{ 0x0002, "Abort SP Complete" },
|
||||
{ 0x0004, "Alarm Report ACK" },
|
||||
{ 0x0005, "Alarm Report NACK" },
|
||||
{ 0x0006, "Alarm Report" },
|
||||
{ 0x0008, "Alarm Status Request" },
|
||||
{ 0x000a, "Alarm Status Request Accept" },
|
||||
{ 0x000b, "Alarm Status Request Reject" },
|
||||
{ 0x000c, "Alarm Status Result ACK" },
|
||||
{ 0x000d, "Alarm Status Result NACK" },
|
||||
{ 0x000e, "Alarm Status Result" },
|
||||
{ 0x0010, "Calendar Time Response" },
|
||||
{ 0x0011, "Calendar Time Reject" },
|
||||
{ 0x0012, "Calendar Time Request" },
|
||||
{ 0x0014, "CON Configuration Request" },
|
||||
{ 0x0016, "CON Configuration Request Accept" },
|
||||
{ 0x0017, "CON Configuration Request Reject" },
|
||||
{ 0x0018, "CON Configuration Result ACK" },
|
||||
{ 0x0019, "CON Configuration Result NACK" },
|
||||
{ 0x001a, "CON Configuration Result" },
|
||||
{ 0x001c, "Connect Command" },
|
||||
{ 0x001e, "Connect Complete" },
|
||||
{ 0x001f, "Connect Rejecte" },
|
||||
{ 0x0028, "Disable Request" },
|
||||
{ 0x002a, "Disable Request Accept" },
|
||||
{ 0x002b, "Disable Request Reject" },
|
||||
{ 0x002c, "Disable Result ACK" },
|
||||
{ 0x002d, "Disable Result NACK" },
|
||||
{ 0x002e, "Disable Result" },
|
||||
{ 0x0030, "Disconnect Command" },
|
||||
{ 0x0032, "Disconnect Complete" },
|
||||
{ 0x0033, "Disconnect Reject" },
|
||||
{ 0x0034, "Enable Request" },
|
||||
{ 0x0036, "Enable Request Accept" },
|
||||
{ 0x0037, "Enable Request Reject" },
|
||||
{ 0x0038, "Enable Result ACK" },
|
||||
{ 0x0039, "Enable Result NACK" },
|
||||
{ 0x003a, "Enable Result" },
|
||||
{ 0x003c, "Escape Downlink Normal" },
|
||||
{ 0x003d, "Escape Downlink NACK" },
|
||||
{ 0x003e, "Escape Uplink Normal" },
|
||||
{ 0x003f, "Escape Uplink NACK" },
|
||||
{ 0x0040, "Fault Report ACK" },
|
||||
{ 0x0041, "Fault Report NACK" },
|
||||
{ 0x0042, "Fault Report" },
|
||||
{ 0x0044, "File Package End Command" },
|
||||
{ 0x0046, "File Package End Result" },
|
||||
{ 0x0047, "File Package End Reject" },
|
||||
{ 0x0048, "File Relation Request" },
|
||||
{ 0x004a, "File Relation Response" },
|
||||
{ 0x004b, "File Relation Request Reject" },
|
||||
{ 0x004c, "File Segment Transfer" },
|
||||
{ 0x004e, "File Segment Transfer Complete" },
|
||||
{ 0x004f, "File Segment Transfer Reject" },
|
||||
{ 0x0050, "HW Information Request" },
|
||||
{ 0x0052, "HW Information Request Accept" },
|
||||
{ 0x0053, "HW Information Request Reject" },
|
||||
{ 0x0054, "HW Information Result ACK" },
|
||||
{ 0x0055, "HW Information Result NACK" },
|
||||
{ 0x0056, "HW Information Result" },
|
||||
{ 0x0060, "IS Configuration Request" },
|
||||
{ 0x0062, "IS Configuration Request Accept" },
|
||||
{ 0x0063, "IS Configuration Request Reject" },
|
||||
{ 0x0064, "IS Configuration Result ACK" },
|
||||
{ 0x0065, "IS Configuration Result NACK" },
|
||||
{ 0x0066, "IS Configuration Result" },
|
||||
{ 0x0068, "Load Data End" },
|
||||
{ 0x006a, "Load Data End Result" },
|
||||
{ 0x006b, "Load Data End Reject" },
|
||||
{ 0x006c, "Load Data Init" },
|
||||
{ 0x006e, "Load Data Init Accept" },
|
||||
{ 0x006f, "Load Data Init Reject" },
|
||||
{ 0x0070, "Loop Control Command" },
|
||||
{ 0x0072, "Loop Control Complete" },
|
||||
{ 0x0073, "Loop Control Reject" },
|
||||
{ 0x0074, "Operational Information" },
|
||||
{ 0x0076, "Operational Information Accept" },
|
||||
{ 0x0077, "Operational Information Reject" },
|
||||
{ 0x0078, "Reset Command" },
|
||||
{ 0x007a, "Reset Complete" },
|
||||
{ 0x007b, "Reset Reject" },
|
||||
{ 0x007c, "RX Configuration Request" },
|
||||
{ 0x007e, "RX Configuration Request Accept" },
|
||||
{ 0x007f, "RX Configuration Request Reject" },
|
||||
{ 0x0080, "RX Configuration Result ACK" },
|
||||
{ 0x0081, "RX Configuration Result NACK" },
|
||||
{ 0x0082, "RX Configuration Result" },
|
||||
{ 0x0084, "Start Request" },
|
||||
{ 0x0086, "Start Request Accept" },
|
||||
{ 0x0087, "Start Request Reject" },
|
||||
{ 0x0088, "Start Result ACK" },
|
||||
{ 0x0089, "Start Result NACK" },
|
||||
{ 0x008a, "Start Result" },
|
||||
{ 0x008c, "Status Request" },
|
||||
{ 0x008e, "Status Response" },
|
||||
{ 0x008f, "Status Reject" },
|
||||
{ 0x0094, "Test Request" },
|
||||
{ 0x0096, "Test Request Accept" },
|
||||
{ 0x0097, "Test Request Reject" },
|
||||
{ 0x0098, "Test Result ACK" },
|
||||
{ 0x0099, "Test Result NACK" },
|
||||
{ 0x009a, "Test Result" },
|
||||
{ 0x00a0, "TF Configuration Request" },
|
||||
{ 0x00a2, "TF Configuration Request Accept" },
|
||||
{ 0x00a3, "TF Configuration Request Reject" },
|
||||
{ 0x00a4, "TF Configuration Result ACK" },
|
||||
{ 0x00a5, "TF Configuration Result NACK" },
|
||||
{ 0x00a6, "TF Configuration Result" },
|
||||
{ 0x00a8, "TS Configuration Request" },
|
||||
{ 0x00aa, "TS Configuration Request Accept" },
|
||||
{ 0x00ab, "TS Configuration Request Reject" },
|
||||
{ 0x00ac, "TS Configuration Result ACK" },
|
||||
{ 0x00ad, "TS Configuration Result NACK" },
|
||||
{ 0x00ae, "TS Configuration Result" },
|
||||
{ 0x00b0, "TX Configuration Request" },
|
||||
{ 0x00b2, "TX Configuration Request Accept" },
|
||||
{ 0x00b3, "TX Configuration Request Reject" },
|
||||
{ 0x00b4, "TX Configuration Result ACK" },
|
||||
{ 0x00b5, "TX Configuration Result NACK" },
|
||||
{ 0x00b6, "TX Configuration Result" },
|
||||
{ 0x00bc, "DIP Alarm Report ACK" },
|
||||
{ 0x00bd, "DIP Alarm Report NACK" },
|
||||
{ 0x00be, "DIP Alarm Report" },
|
||||
{ 0x00c0, "DIP Alarm Status Request" },
|
||||
{ 0x00c2, "DIP Alarm Status Response" },
|
||||
{ 0x00c3, "DIP Alarm Status Reject" },
|
||||
{ 0x00c4, "DIP Quality Report I ACK" },
|
||||
{ 0x00c5, "DIP Quality Report I NACK" },
|
||||
{ 0x00c6, "DIP Quality Report I" },
|
||||
{ 0x00c8, "DIP Quality Report II ACK" },
|
||||
{ 0x00c9, "DIP Quality Report II NACK" },
|
||||
{ 0x00ca, "DIP Quality Report II" },
|
||||
{ 0x00dc, "DP Configuration Request" },
|
||||
{ 0x00de, "DP Configuration Request Accept" },
|
||||
{ 0x00df, "DP Configuration Request Reject" },
|
||||
{ 0x00e0, "DP Configuration Result ACK" },
|
||||
{ 0x00e1, "DP Configuration Result NACK" },
|
||||
{ 0x00e2, "DP Configuration Result" },
|
||||
{ 0x00e4, "Capabilities HW Info Report ACK" },
|
||||
{ 0x00e5, "Capabilities HW Info Report NACK" },
|
||||
{ 0x00e6, "Capabilities HW Info Report" },
|
||||
{ 0x00e8, "Capabilities Request" },
|
||||
{ 0x00ea, "Capabilities Request Accept" },
|
||||
{ 0x00eb, "Capabilities Request Reject" },
|
||||
{ 0x00ec, "Capabilities Result ACK" },
|
||||
{ 0x00ed, "Capabilities Result NACK" },
|
||||
{ 0x00ee, "Capabilities Result" },
|
||||
{ 0x00f0, "FM Configuration Request" },
|
||||
{ 0x00f2, "FM Configuration Request Accept" },
|
||||
{ 0x00f3, "FM Configuration Request Reject" },
|
||||
{ 0x00f4, "FM Configuration Result ACK" },
|
||||
{ 0x00f5, "FM Configuration Result NACK" },
|
||||
{ 0x00f6, "FM Configuration Result" },
|
||||
{ 0x00f8, "FM Report Request" },
|
||||
{ 0x00fa, "FM Report Response" },
|
||||
{ 0x00fb, "FM Report Reject" },
|
||||
{ 0x00fc, "FM Start Command" },
|
||||
{ 0x00fe, "FM Start Complete" },
|
||||
{ 0x00ff, "FM Start Reject" },
|
||||
{ 0x0100, "FM Stop Command" },
|
||||
{ 0x0102, "FM Stop Complete" },
|
||||
{ 0x0103, "FM Stop Reject" },
|
||||
{ 0x0104, "Negotiation Request ACK" },
|
||||
{ 0x0105, "Negotiation Request NACK" },
|
||||
{ 0x0106, "Negotiation Request" },
|
||||
{ 0x0108, "BTS Initiated Request ACK" },
|
||||
{ 0x0109, "BTS Initiated Request NACK" },
|
||||
{ 0x010a, "BTS Initiated Request" },
|
||||
{ 0x010c, "Radio Channels Release Command" },
|
||||
{ 0x010e, "Radio Channels Release Complete" },
|
||||
{ 0x010f, "Radio Channels Release Reject" },
|
||||
{ 0x0118, "Feature Control Command" },
|
||||
{ 0x011a, "Feature Control Complete" },
|
||||
{ 0x011b, "Feature Control Reject" },
|
||||
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
/* TS 12.21 Section 9.4: Attributes */
|
||||
static const struct value_string om2k_attr_vals[] = {
|
||||
{ 0x00, "Accordance indication" },
|
||||
{ 0x01, "Alarm Id" },
|
||||
{ 0x02, "Alarm Data" },
|
||||
{ 0x03, "Alarm Severity" },
|
||||
{ 0x04, "Alarm Status" },
|
||||
{ 0x05, "Alarm Status Type" },
|
||||
{ 0x06, "BCC" },
|
||||
{ 0x07, "BS_AG_BKS_RES" },
|
||||
{ 0x09, "BSIC" },
|
||||
{ 0x0a, "BA_PA_MFRMS" },
|
||||
{ 0x0b, "CBCH Indicator" },
|
||||
{ 0x0c, "CCCH Options" },
|
||||
{ 0x0d, "Calendar Time" },
|
||||
{ 0x0f, "Channel Combination" },
|
||||
{ 0x10, "CON Connection List" },
|
||||
{ 0x11, "Data End Indication" },
|
||||
{ 0x12, "DRX_DEV_MAX" },
|
||||
{ 0x13, "End List Number" },
|
||||
{ 0x14, "External Condition Map Class 1" },
|
||||
{ 0x15, "External Condition Map Class 2" },
|
||||
{ 0x16, "File Relation Indication" },
|
||||
{ 0x17, "File Revision" },
|
||||
{ 0x18, "File Segment Data" },
|
||||
{ 0x19, "File Segment Length" },
|
||||
{ 0x1a, "File Segment Sequence Number" },
|
||||
{ 0x1b, "File Size" },
|
||||
{ 0x1c, "Filling Marker" },
|
||||
{ 0x1d, "FN Offset" },
|
||||
{ 0x1e, "Frequency List" },
|
||||
{ 0x1f, "Frequency Specifier RX" },
|
||||
{ 0x20, "Frequency Specifier TX" },
|
||||
{ 0x21, "HSN" },
|
||||
{ 0x22, "ICM Indicator" },
|
||||
{ 0x23, "Internal Fault Map Class 1A" },
|
||||
{ 0x24, "Internal Fault Map Class 1B" },
|
||||
{ 0x25, "Internal Fault Map Class 2A" },
|
||||
{ 0x26, "Internal Fault Map Class 2A Extension" },
|
||||
{ 0x27, "IS Connection List" },
|
||||
{ 0x28, "List Number" },
|
||||
{ 0x29, "File Package State Indication" },
|
||||
{ 0x2a, "Local Access State" },
|
||||
{ 0x2b, "MAIO" },
|
||||
{ 0x2c, "MO State" },
|
||||
{ 0x2d, "Ny1" },
|
||||
{ 0x2e, "Operational Information" },
|
||||
{ 0x2f, "Power" },
|
||||
{ 0x30, "RU Position Data" },
|
||||
{ 0x31, "Protocol Error" },
|
||||
{ 0x32, "Reason Code" },
|
||||
{ 0x33, "Receiver Diversity" },
|
||||
{ 0x34, "Replacement Unit Map" },
|
||||
{ 0x35, "Result Code" },
|
||||
{ 0x36, "RU Revision Data" },
|
||||
{ 0x38, "T3105" },
|
||||
{ 0x39, "Test Loop Setting" },
|
||||
{ 0x3a, "TF Mode" },
|
||||
{ 0x3b, "TF Compensation Value" },
|
||||
{ 0x3c, "Time Slot Number" },
|
||||
{ 0x3d, "TSC" },
|
||||
{ 0x3e, "RU Logical Id" },
|
||||
{ 0x3f, "RU Serial Number Data" },
|
||||
{ 0x40, "BTS Version" },
|
||||
{ 0x41, "OML IWD Version" },
|
||||
{ 0x42, "RWL IWD Version" },
|
||||
{ 0x43, "OML Function Map 1" },
|
||||
{ 0x44, "OML Function Map 2" },
|
||||
{ 0x45, "RSL Function Map 1" },
|
||||
{ 0x46, "RSL Function Map 2" },
|
||||
{ 0x47, "Extended Range Indicator" },
|
||||
{ 0x48, "Request Indicators" },
|
||||
{ 0x49, "DIP Alarm Condition Map" },
|
||||
{ 0x4a, "ES Incoming" },
|
||||
{ 0x4b, "ES Outgoing" },
|
||||
{ 0x4e, "SES Incoming" },
|
||||
{ 0x4f, "SES Outgoing" },
|
||||
{ 0x50, "Replacement Unit Map Extension" },
|
||||
{ 0x52, "UAS Incoming" },
|
||||
{ 0x53, "UAS Outgoing" },
|
||||
{ 0x58, "DF Incoming" },
|
||||
{ 0x5a, "DF Outgoing" },
|
||||
{ 0x5c, "SF" },
|
||||
{ 0x60, "S Bits Setting" },
|
||||
{ 0x61, "CRC-4 Use Option" },
|
||||
{ 0x62, "T Parameter" },
|
||||
{ 0x63, "N Parameter" },
|
||||
{ 0x64, "N1 Parameter" },
|
||||
{ 0x65, "N3 Parameter" },
|
||||
{ 0x66, "N4 Parameter" },
|
||||
{ 0x67, "P Parameter" },
|
||||
{ 0x68, "Q Parameter" },
|
||||
{ 0x69, "BI_Q1" },
|
||||
{ 0x6a, "BI_Q2" },
|
||||
{ 0x74, "ICM Boundary Parameters" },
|
||||
{ 0x77, "AFT" },
|
||||
{ 0x78, "AFT RAI" },
|
||||
{ 0x79, "Link Supervision Control" },
|
||||
{ 0x7a, "Link Supervision Filtering Time" },
|
||||
{ 0x7b, "Call Supervision Time" },
|
||||
{ 0x7c, "Interval Length UAS Incoming" },
|
||||
{ 0x7d, "Interval Length UAS Outgoing" },
|
||||
{ 0x7e, "ICM Channel Rate" },
|
||||
{ 0x7f, "Attribute Identifier" },
|
||||
{ 0x80, "FM Frequency List" },
|
||||
{ 0x81, "FM Frequency Report" },
|
||||
{ 0x82, "FM Percentile" },
|
||||
{ 0x83, "FM Clear Indication" },
|
||||
{ 0x84, "HW Info Signature" },
|
||||
{ 0x85, "MO Record" },
|
||||
{ 0x86, "TF Synchronisation Source" },
|
||||
{ 0x87, "TTA" },
|
||||
{ 0x88, "End Segment Number" },
|
||||
{ 0x89, "Segment Number" },
|
||||
{ 0x8a, "Capabilities Signature" },
|
||||
{ 0x8c, "File Relation List" },
|
||||
{ 0x90, "Negotiation Record I" },
|
||||
{ 0x91, "Negotiation Record II" },
|
||||
{ 0x92, "Encryption Algorithm" },
|
||||
{ 0x94, "Interference Rejection Combining" },
|
||||
{ 0x95, "Dedication Information" },
|
||||
{ 0x97, "Feature Code" },
|
||||
{ 0x98, "FS Offset" },
|
||||
{ 0x99, "ESB Timeslot" },
|
||||
{ 0x9a, "Master TG Instance" },
|
||||
{ 0x9b, "Master TX Chain Delay" },
|
||||
{ 0x9c, "External Condition Class 2 Extension" },
|
||||
{ 0x9d, "TSs MO State" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
const struct value_string om2k_mo_class_short_vals[] = {
|
||||
{ 0x01, "TRXC" },
|
||||
{ 0x03, "TS" },
|
||||
{ 0x04, "TF" },
|
||||
{ 0x05, "IS" },
|
||||
{ 0x06, "CON" },
|
||||
{ 0x07, "DP" },
|
||||
{ 0x0a, "CF" },
|
||||
{ 0x0b, "TX" },
|
||||
{ 0x0c, "RX" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
static struct msgb *om2k_msgb_alloc(void)
|
||||
{
|
||||
return msgb_alloc_headroom(OM_ALLOC_SIZE, OM_HEADROOM_SIZE,
|
||||
"OM2000");
|
||||
}
|
||||
|
||||
static char *om2k_mo_name(const struct abis_om2k_mo *mo)
|
||||
{
|
||||
static char mo_buf[64];
|
||||
|
||||
memset(mo_buf, 0, sizeof(mo_buf));
|
||||
snprintf(mo_buf, sizeof(mo_buf), "%s/%02x/%02x/%02x",
|
||||
get_value_string(om2k_mo_class_short_vals, mo->class),
|
||||
mo->bts, mo->assoc_so, mo->inst);
|
||||
return mo_buf;
|
||||
}
|
||||
|
||||
static int abis_om2k_sendmsg(struct gsm_bts *bts, struct msgb *msg)
|
||||
{
|
||||
struct abis_om2k_hdr *o2h;
|
||||
int to_trx_oml;
|
||||
|
||||
msg->l2h = msg->data;
|
||||
o2h = (struct abis_om2k_hdr *) msg->l2h;
|
||||
|
||||
switch (o2h->mo.class) {
|
||||
case OM2K_MO_CLS_TRXC:
|
||||
case OM2K_MO_CLS_TX:
|
||||
case OM2K_MO_CLS_RX:
|
||||
case OM2K_MO_CLS_TS:
|
||||
/* Route through per-TRX OML Link to the appropriate TRX */
|
||||
to_trx_oml = 1;
|
||||
msg->trx = gsm_bts_trx_by_nr(bts, o2h->mo.inst);
|
||||
if (!msg->trx) {
|
||||
LOGP(DNM, LOGL_ERROR, "MO=%s Tx Dropping msg to "
|
||||
"non-existing TRX\n", om2k_mo_name(&o2h->mo));
|
||||
return -ENODEV;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* Route through the IXU/DXU OML Link */
|
||||
msg->trx = bts->c0;
|
||||
to_trx_oml = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return _abis_nm_sendmsg(msg, to_trx_oml);
|
||||
}
|
||||
|
||||
static void fill_om2k_hdr(struct abis_om2k_hdr *o2h, const struct abis_om2k_mo *mo,
|
||||
uint16_t msg_type, uint8_t attr_len)
|
||||
{
|
||||
o2h->om.mdisc = ABIS_OM_MDISC_FOM;
|
||||
o2h->om.placement = ABIS_OM_PLACEMENT_ONLY;
|
||||
o2h->om.sequence = 0;
|
||||
o2h->om.length = 6 + attr_len;
|
||||
o2h->msg_type = htons(msg_type);
|
||||
memcpy(&o2h->mo, mo, sizeof(o2h->mo));
|
||||
}
|
||||
|
||||
const struct abis_om2k_mo om2k_mo_cf = { OM2K_MO_CLS_CF, 0, 0xFF, 0 };
|
||||
const struct abis_om2k_mo om2k_mo_is = { OM2K_MO_CLS_IS, 0, 0xFF, 0 };
|
||||
const struct abis_om2k_mo om2k_mo_con = { OM2K_MO_CLS_CON, 0, 0xFF, 0 };
|
||||
|
||||
static int abis_om2k_cal_time_resp(struct gsm_bts *bts)
|
||||
{
|
||||
struct msgb *msg = om2k_msgb_alloc();
|
||||
struct abis_om2k_hdr *o2k;
|
||||
time_t tm_t;
|
||||
struct tm *tm;
|
||||
|
||||
o2k = (struct abis_om2k_hdr *) msgb_put(msg, sizeof(*o2k));
|
||||
fill_om2k_hdr(o2k, &om2k_mo_cf, OM2K_MSGT_CAL_TIME_RESP, 7);
|
||||
|
||||
tm_t = time(NULL);
|
||||
tm = localtime(&tm_t);
|
||||
|
||||
msgb_put_u8(msg, OM2K_DEI_CAL_TIME);
|
||||
msgb_put_u8(msg, tm->tm_year % 100);
|
||||
msgb_put_u8(msg, tm->tm_mon + 1);
|
||||
msgb_put_u8(msg, tm->tm_mday);
|
||||
msgb_put_u8(msg, tm->tm_hour);
|
||||
msgb_put_u8(msg, tm->tm_min);
|
||||
msgb_put_u8(msg, tm->tm_sec);
|
||||
|
||||
return abis_om2k_sendmsg(bts, msg);
|
||||
}
|
||||
|
||||
static int abis_om2k_tx_simple(struct gsm_bts *bts, const struct abis_om2k_mo *mo,
|
||||
uint8_t msg_type)
|
||||
{
|
||||
struct msgb *msg = om2k_msgb_alloc();
|
||||
struct abis_om2k_hdr *o2k;
|
||||
|
||||
o2k = (struct abis_om2k_hdr *) msgb_put(msg, sizeof(*o2k));
|
||||
fill_om2k_hdr(o2k, mo, msg_type, 0);
|
||||
|
||||
DEBUGP(DNM, "Tx MO=%s %s\n", om2k_mo_name(mo),
|
||||
get_value_string(om2k_msgcode_vals, msg_type));
|
||||
|
||||
return abis_om2k_sendmsg(bts, msg);
|
||||
}
|
||||
|
||||
int abis_om2k_tx_reset_cmd(struct gsm_bts *bts, const struct abis_om2k_mo *mo)
|
||||
{
|
||||
return abis_om2k_tx_simple(bts, mo, OM2K_MSGT_RESET_CMD);
|
||||
}
|
||||
|
||||
int abis_om2k_tx_start_req(struct gsm_bts *bts, const struct abis_om2k_mo *mo)
|
||||
{
|
||||
return abis_om2k_tx_simple(bts, mo, OM2K_MSGT_START_REQ);
|
||||
}
|
||||
|
||||
int abis_om2k_tx_status_req(struct gsm_bts *bts, const struct abis_om2k_mo *mo)
|
||||
{
|
||||
return abis_om2k_tx_simple(bts, mo, OM2K_MSGT_STATUS_REQ);
|
||||
}
|
||||
|
||||
int abis_om2k_tx_connect_cmd(struct gsm_bts *bts, const struct abis_om2k_mo *mo)
|
||||
{
|
||||
return abis_om2k_tx_simple(bts, mo, OM2K_MSGT_CONNECT_CMD);
|
||||
}
|
||||
|
||||
int abis_om2k_tx_disconnect_cmd(struct gsm_bts *bts, const struct abis_om2k_mo *mo)
|
||||
{
|
||||
return abis_om2k_tx_simple(bts, mo, OM2K_MSGT_DISCONNECT_CMD);
|
||||
}
|
||||
|
||||
int abis_om2k_tx_test_req(struct gsm_bts *bts, const struct abis_om2k_mo *mo)
|
||||
{
|
||||
return abis_om2k_tx_simple(bts, mo, OM2K_MSGT_TEST_REQ);
|
||||
}
|
||||
|
||||
int abis_om2k_tx_enable_req(struct gsm_bts *bts, const struct abis_om2k_mo *mo)
|
||||
{
|
||||
return abis_om2k_tx_simple(bts, mo, OM2K_MSGT_ENABLE_REQ);
|
||||
}
|
||||
|
||||
int abis_om2k_tx_disable_req(struct gsm_bts *bts, const struct abis_om2k_mo *mo)
|
||||
{
|
||||
return abis_om2k_tx_simple(bts, mo, OM2K_MSGT_DISABLE_REQ);
|
||||
}
|
||||
|
||||
int abis_om2k_tx_op_info(struct gsm_bts *bts, const struct abis_om2k_mo *mo,
|
||||
uint8_t operational)
|
||||
{
|
||||
struct msgb *msg = om2k_msgb_alloc();
|
||||
struct abis_om2k_hdr *o2k;
|
||||
|
||||
o2k = (struct abis_om2k_hdr *) msgb_put(msg, sizeof(*o2k));
|
||||
fill_om2k_hdr(o2k, mo, OM2K_MSGT_OP_INFO, 2);
|
||||
|
||||
msgb_tv_put(msg, OM2K_DEI_OP_INFO, operational);
|
||||
|
||||
DEBUGP(DNM, "Tx MO=%s %s\n", om2k_mo_name(mo),
|
||||
get_value_string(om2k_msgcode_vals, OM2K_MSGT_OP_INFO));
|
||||
|
||||
return abis_om2k_sendmsg(bts, msg);
|
||||
}
|
||||
|
||||
int abis_om2k_tx_is_conf_req(struct gsm_bts *bts, struct om2k_is_conn_grp *cg,
|
||||
unsigned int num_cg )
|
||||
{
|
||||
struct msgb *msg = om2k_msgb_alloc();
|
||||
struct abis_om2k_hdr *o2k;
|
||||
|
||||
o2k = (struct abis_om2k_hdr *) msgb_put(msg, sizeof(*o2k));
|
||||
fill_om2k_hdr(o2k, &om2k_mo_is, OM2K_MSGT_IS_CONF_REQ,
|
||||
2 + 2 + TLV_GROSS_LEN(num_cg * sizeof(*cg)));
|
||||
|
||||
msgb_tv_put(msg, OM2K_DEI_LIST_NR, 1);
|
||||
msgb_tv_put(msg, OM2K_DEI_END_LIST_NR, 1);
|
||||
|
||||
msgb_tlv_put(msg, OM2K_DEI_IS_CONN_LIST,
|
||||
num_cg * sizeof(*cg), (uint8_t *)cg);
|
||||
|
||||
return abis_om2k_sendmsg(bts, msg);
|
||||
}
|
||||
|
||||
int abis_om2k_tx_con_conf_req(struct gsm_bts *bts, uint8_t *data,
|
||||
unsigned int len)
|
||||
{
|
||||
struct msgb *msg = om2k_msgb_alloc();
|
||||
struct abis_om2k_hdr *o2k;
|
||||
|
||||
o2k = (struct abis_om2k_hdr *) msgb_put(msg, sizeof(*o2k));
|
||||
fill_om2k_hdr(o2k, &om2k_mo_con, OM2K_MSGT_CON_CONF_REQ,
|
||||
2 + 2 + TLV_GROSS_LEN(len));
|
||||
|
||||
msgb_tv_put(msg, OM2K_DEI_LIST_NR, 1);
|
||||
msgb_tv_put(msg, OM2K_DEI_END_LIST_NR, 1);
|
||||
|
||||
msgb_tlv_put(msg, OM2K_DEI_CON_CONN_LIST, len, data);
|
||||
|
||||
return abis_om2k_sendmsg(bts, msg);
|
||||
}
|
||||
|
||||
|
||||
static int abis_om2k_tx_negot_req_ack(struct gsm_bts *bts, const struct abis_om2k_mo *mo,
|
||||
uint8_t *data, unsigned int len)
|
||||
{
|
||||
struct msgb *msg = om2k_msgb_alloc();
|
||||
struct abis_om2k_hdr *o2k;
|
||||
|
||||
o2k = (struct abis_om2k_hdr *) msgb_put(msg, sizeof(*o2k));
|
||||
fill_om2k_hdr(o2k, mo, OM2K_MSGT_NEGOT_REQ_ACK, 2+len);
|
||||
|
||||
msgb_tlv_put(msg, OM2K_DEI_NEGOT_REC2, len, data);
|
||||
|
||||
DEBUGP(DNM, "Tx MO=%s %s\n", om2k_mo_name(mo),
|
||||
get_value_string(om2k_msgcode_vals, OM2K_MSGT_NEGOT_REQ_ACK));
|
||||
|
||||
return abis_om2k_sendmsg(bts, msg);
|
||||
}
|
||||
|
||||
struct iwd_version {
|
||||
uint8_t gen_char[3+1];
|
||||
uint8_t rev_char[3+1];
|
||||
};
|
||||
|
||||
struct iwd_type {
|
||||
uint8_t num_vers;
|
||||
struct iwd_version v[8];
|
||||
};
|
||||
|
||||
static int om2k_rx_negot_req(struct msgb *msg)
|
||||
{
|
||||
struct abis_om2k_hdr *o2h = msgb_l2(msg);
|
||||
struct iwd_type iwd_types[16];
|
||||
uint8_t num_iwd_types = o2h->data[2];
|
||||
uint8_t *cur = o2h->data+3;
|
||||
unsigned int i, v;
|
||||
|
||||
uint8_t out_buf[1024];
|
||||
uint8_t *out_cur = out_buf+1;
|
||||
uint8_t out_num_types = 0;
|
||||
|
||||
memset(iwd_types, 0, sizeof(iwd_types));
|
||||
|
||||
/* Parse the RBS-supported IWD versions into iwd_types array */
|
||||
for (i = 0; i < num_iwd_types; i++) {
|
||||
uint8_t num_versions = *cur++;
|
||||
uint8_t iwd_type = *cur++;
|
||||
|
||||
iwd_types[iwd_type].num_vers = num_versions;
|
||||
|
||||
for (v = 0; v < num_versions; v++) {
|
||||
struct iwd_version *iwd_v = &iwd_types[iwd_type].v[v];
|
||||
|
||||
memcpy(iwd_v->gen_char, cur, 3);
|
||||
cur += 3;
|
||||
memcpy(iwd_v->rev_char, cur, 3);
|
||||
cur += 3;
|
||||
|
||||
DEBUGP(DNM, "\tIWD Type %u Gen %s Rev %s\n", iwd_type,
|
||||
iwd_v->gen_char, iwd_v->rev_char);
|
||||
}
|
||||
}
|
||||
|
||||
/* Select the last version for each IWD type */
|
||||
for (i = 0; i < ARRAY_SIZE(iwd_types); i++) {
|
||||
struct iwd_type *type = &iwd_types[i];
|
||||
struct iwd_version *last_v;
|
||||
|
||||
if (type->num_vers == 0)
|
||||
continue;
|
||||
|
||||
out_num_types++;
|
||||
|
||||
last_v = &type->v[type->num_vers-1];
|
||||
|
||||
*out_cur++ = i;
|
||||
memcpy(out_cur, last_v->gen_char, 3);
|
||||
out_cur += 3;
|
||||
memcpy(out_cur, last_v->rev_char, 3);
|
||||
out_cur += 3;
|
||||
}
|
||||
|
||||
out_buf[0] = out_num_types;
|
||||
|
||||
return abis_om2k_tx_negot_req_ack(msg->trx->bts, &o2h->mo, out_buf, out_cur - out_buf);
|
||||
}
|
||||
|
||||
static int om2k_rx_start_res(struct msgb *msg)
|
||||
{
|
||||
struct abis_om2k_hdr *o2h = msgb_l2(msg);
|
||||
int rc;
|
||||
|
||||
rc = abis_om2k_tx_simple(msg->trx->bts, &o2h->mo, OM2K_MSGT_START_RES_ACK);
|
||||
rc = abis_om2k_tx_op_info(msg->trx->bts, &o2h->mo, 1);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int om2k_rx_op_info_ack(struct msgb *msg)
|
||||
{
|
||||
struct abis_om2k_hdr *o2h = msgb_l2(msg);
|
||||
|
||||
/* FIXME: update Operational state in our structures */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int abis_om2k_rcvmsg(struct msgb *msg)
|
||||
{
|
||||
struct gsm_bts *bts = msg->trx->bts;
|
||||
struct abis_om2k_hdr *o2h = msgb_l2(msg);
|
||||
struct abis_om_hdr *oh = &o2h->om;
|
||||
uint16_t msg_type = ntohs(o2h->msg_type);
|
||||
int rc = 0;
|
||||
|
||||
/* Various consistency checks */
|
||||
if (oh->placement != ABIS_OM_PLACEMENT_ONLY) {
|
||||
LOGP(DNM, LOGL_ERROR, "ABIS OML placement 0x%x not supported\n",
|
||||
oh->placement);
|
||||
if (oh->placement != ABIS_OM_PLACEMENT_FIRST)
|
||||
return -EINVAL;
|
||||
}
|
||||
if (oh->sequence != 0) {
|
||||
LOGP(DNM, LOGL_ERROR, "ABIS OML sequence 0x%x != 0x00\n",
|
||||
oh->sequence);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
msg->l3h = (unsigned char *)o2h + sizeof(*o2h);
|
||||
|
||||
if (oh->mdisc != ABIS_OM_MDISC_FOM) {
|
||||
LOGP(DNM, LOGL_ERROR, "unknown ABIS OM2000 message discriminator 0x%x\n",
|
||||
oh->mdisc);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
DEBUGP(DNM, "Rx MO=%s %s (%s)\n", om2k_mo_name(&o2h->mo),
|
||||
get_value_string(om2k_msgcode_vals, msg_type),
|
||||
hexdump(msg->l2h, msgb_l2len(msg)));
|
||||
|
||||
switch (msg_type) {
|
||||
case OM2K_MSGT_CAL_TIME_REQ:
|
||||
rc = abis_om2k_cal_time_resp(bts);
|
||||
break;
|
||||
case OM2K_MSGT_FAULT_REP:
|
||||
rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_FAULT_REP_ACK);
|
||||
break;
|
||||
case OM2K_MSGT_NEGOT_REQ:
|
||||
rc = om2k_rx_negot_req(msg);
|
||||
break;
|
||||
case OM2K_MSGT_START_RES:
|
||||
rc = om2k_rx_start_res(msg);
|
||||
break;
|
||||
case OM2K_MSGT_OP_INFO_ACK:
|
||||
rc = om2k_rx_op_info_ack(msg);
|
||||
break;
|
||||
case OM2K_MSGT_IS_CONF_RES:
|
||||
rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_IS_CONF_RES_ACK);
|
||||
break;
|
||||
case OM2K_MSGT_CON_CONF_RES:
|
||||
rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_CON_CONF_RES_ACK);
|
||||
break;
|
||||
case OM2K_MSGT_CONNECT_COMPL:
|
||||
rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_RESET_CMD);
|
||||
break;
|
||||
case OM2K_MSGT_RESET_COMPL:
|
||||
rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_START_REQ);
|
||||
break;
|
||||
case OM2K_MSGT_ENABLE_RES:
|
||||
rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_ENABLE_RES_ACK);
|
||||
break;
|
||||
case OM2K_MSGT_DISABLE_RES:
|
||||
rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_DISABLE_RES_ACK);
|
||||
break;
|
||||
case OM2K_MSGT_TEST_RES:
|
||||
rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_TEST_RES_ACK);
|
||||
break;
|
||||
case OM2K_MSGT_STATUS_RESP:
|
||||
break;
|
||||
case OM2K_MSGT_START_REQ_ACK:
|
||||
case OM2K_MSGT_CON_CONF_REQ_ACK:
|
||||
case OM2K_MSGT_IS_CONF_REQ_ACK:
|
||||
case OM2K_MSGT_ENABLE_REQ_ACK:
|
||||
case OM2K_MSGT_ALARM_STATUS_REQ_ACK:
|
||||
case OM2K_MSGT_DISABLE_REQ_ACK:
|
||||
break;
|
||||
default:
|
||||
LOGP(DNM, LOGL_NOTICE, "Rx unhandled OM2000 msg %s\n",
|
||||
get_value_string(om2k_msgcode_vals, msg_type));
|
||||
}
|
||||
|
||||
msgb_free(msg);
|
||||
return rc;
|
||||
}
|
||||
456
openbsc/src/abis_om2000_vty.c
Normal file
456
openbsc/src/abis_om2000_vty.c
Normal file
@@ -0,0 +1,456 @@
|
||||
/* VTY interface for A-bis OM2000 */
|
||||
|
||||
/* (C) 2010-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 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 <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <openbsc/gsm_data.h>
|
||||
#include <osmocore/msgb.h>
|
||||
#include <osmocore/tlv.h>
|
||||
#include <osmocore/talloc.h>
|
||||
#include <openbsc/debug.h>
|
||||
#include <openbsc/signal.h>
|
||||
#include <openbsc/abis_om2000.h>
|
||||
#include <openbsc/vty.h>
|
||||
|
||||
#include <osmocom/vty/vty.h>
|
||||
#include <osmocom/vty/command.h>
|
||||
#include <osmocom/vty/logging.h>
|
||||
#include <osmocom/vty/telnet_interface.h>
|
||||
|
||||
extern struct gsm_network *bsc_gsmnet;
|
||||
|
||||
static struct cmd_node om2k_node = {
|
||||
OM2K_NODE,
|
||||
"%s(om2k)# ",
|
||||
1,
|
||||
};
|
||||
|
||||
struct oml_node_state {
|
||||
struct gsm_bts *bts;
|
||||
struct abis_om2k_mo mo;
|
||||
};
|
||||
|
||||
static int dummy_config_write(struct vty *v)
|
||||
{
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
/* FIXME: auto-generate those strings from the value_string lists */
|
||||
#define OM2K_OBJCLASS_VTY "(trxc|ts|tf|is|con|dp|cf|tx|rx)"
|
||||
#define OM2K_OBJCLASS_VTY_HELP "TRX Controller\n" \
|
||||
"Timeslot\n" \
|
||||
"Timing Function\n" \
|
||||
"Interface Switch\n" \
|
||||
"Abis Concentrator\n" \
|
||||
"Digital Path\n" \
|
||||
"Central Function\n" \
|
||||
"Transmitter\n" \
|
||||
"Receiver\n"
|
||||
|
||||
DEFUN(om2k_class_inst, om2k_class_inst_cmd,
|
||||
"bts <0-255> om2000 class " OM2K_OBJCLASS_VTY
|
||||
" <0-255> <0-255> <0-255>",
|
||||
"BTS related commands\n" "BTS Number\n"
|
||||
"Manipulate the OM2000 managed objects\n"
|
||||
"Object Class\n" OM2K_OBJCLASS_VTY_HELP
|
||||
"BTS Number\n" "Associated SO Instance\n" "Instance Number\n")
|
||||
{
|
||||
struct gsm_bts *bts;
|
||||
struct oml_node_state *oms;
|
||||
int bts_nr = atoi(argv[0]);
|
||||
|
||||
bts = gsm_bts_num(bsc_gsmnet, bts_nr);
|
||||
if (!bts) {
|
||||
vty_out(vty, "%% No such BTS (%d)%s", bts_nr, VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
if (bts->type != GSM_BTS_TYPE_RBS2000) {
|
||||
vty_out(vty, "%% BTS %d not an Ericsson RBS%s",
|
||||
bts_nr, VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
oms = talloc_zero(tall_bsc_ctx, struct oml_node_state);
|
||||
if (!oms)
|
||||
return CMD_WARNING;
|
||||
|
||||
oms->bts = bts;
|
||||
oms->mo.class = get_string_value(om2k_mo_class_short_vals, argv[1]);
|
||||
oms->mo.bts = atoi(argv[2]);
|
||||
oms->mo.assoc_so = atoi(argv[3]);
|
||||
oms->mo.inst = atoi(argv[4]);
|
||||
|
||||
vty->index = oms;
|
||||
vty->node = OM2K_NODE;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
|
||||
}
|
||||
|
||||
DEFUN(om2k_classnum_inst, om2k_classnum_inst_cmd,
|
||||
"bts <0-255> om2000 class <0-255> <0-255> <0-255> <0-255>",
|
||||
"BTS related commands\n" "BTS Number\n"
|
||||
"Manipulate the OML managed objects\n"
|
||||
"Object Class\n" "Object Class\n"
|
||||
"BTS Number\n" "Associated SO Instance\n" "Instance Number\n")
|
||||
{
|
||||
struct gsm_bts *bts;
|
||||
struct oml_node_state *oms;
|
||||
int bts_nr = atoi(argv[0]);
|
||||
|
||||
bts = gsm_bts_num(bsc_gsmnet, bts_nr);
|
||||
if (!bts) {
|
||||
vty_out(vty, "%% No such BTS (%d)%s", bts_nr, VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
oms = talloc_zero(tall_bsc_ctx, struct oml_node_state);
|
||||
if (!oms)
|
||||
return CMD_WARNING;
|
||||
|
||||
oms->bts = bts;
|
||||
oms->mo.class = atoi(argv[1]);
|
||||
oms->mo.bts = atoi(argv[2]);
|
||||
oms->mo.assoc_so = atoi(argv[3]);
|
||||
oms->mo.inst = atoi(argv[4]);
|
||||
|
||||
vty->index = oms;
|
||||
vty->node = OM2K_NODE;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(om2k_reset, om2k_reset_cmd,
|
||||
"reset-command",
|
||||
"Reset the MO\n")
|
||||
{
|
||||
struct oml_node_state *oms = vty->index;
|
||||
|
||||
abis_om2k_tx_reset_cmd(oms->bts, &oms->mo);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(om2k_start, om2k_start_cmd,
|
||||
"start-request",
|
||||
"Start the MO\n")
|
||||
{
|
||||
struct oml_node_state *oms = vty->index;
|
||||
|
||||
abis_om2k_tx_start_req(oms->bts, &oms->mo);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(om2k_status, om2k_status_cmd,
|
||||
"status-request",
|
||||
"Get the MO Status\n")
|
||||
{
|
||||
struct oml_node_state *oms = vty->index;
|
||||
|
||||
abis_om2k_tx_status_req(oms->bts, &oms->mo);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(om2k_connect, om2k_connect_cmd,
|
||||
"connect-command",
|
||||
"Connect the MO\n")
|
||||
{
|
||||
struct oml_node_state *oms = vty->index;
|
||||
|
||||
abis_om2k_tx_connect_cmd(oms->bts, &oms->mo);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(om2k_disconnect, om2k_disconnect_cmd,
|
||||
"disconnect-command",
|
||||
"Disconnect the MO\n")
|
||||
{
|
||||
struct oml_node_state *oms = vty->index;
|
||||
|
||||
abis_om2k_tx_disconnect_cmd(oms->bts, &oms->mo);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(om2k_enable, om2k_enable_cmd,
|
||||
"enable-request",
|
||||
"Enable the MO\n")
|
||||
{
|
||||
struct oml_node_state *oms = vty->index;
|
||||
|
||||
abis_om2k_tx_enable_req(oms->bts, &oms->mo);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(om2k_disable, om2k_disable_cmd,
|
||||
"disable-request",
|
||||
"Disable the MO\n")
|
||||
{
|
||||
struct oml_node_state *oms = vty->index;
|
||||
|
||||
abis_om2k_tx_disable_req(oms->bts, &oms->mo);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(om2k_op_info, om2k_op_info_cmd,
|
||||
"operational-info <0-1>",
|
||||
"Set operational information\n")
|
||||
{
|
||||
struct oml_node_state *oms = vty->index;
|
||||
int oper = atoi(argv[0]);
|
||||
|
||||
abis_om2k_tx_op_info(oms->bts, &oms->mo, oper);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(om2k_test, om2k_test_cmd,
|
||||
"test-request",
|
||||
"Test the MO\n")
|
||||
{
|
||||
struct oml_node_state *oms = vty->index;
|
||||
|
||||
abis_om2k_tx_test_req(oms->bts, &oms->mo);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
struct con_conn_group {
|
||||
struct llist_head list;
|
||||
|
||||
uint8_t cg;
|
||||
uint16_t ccp;
|
||||
uint8_t tag;
|
||||
uint8_t tei;
|
||||
};
|
||||
|
||||
static void add_con_list(struct gsm_bts *bts, uint8_t cg, uint16_t ccp,
|
||||
uint8_t tag, uint8_t tei)
|
||||
{
|
||||
struct con_conn_group *ent = talloc_zero(bts, struct con_conn_group);
|
||||
|
||||
ent->cg = cg;
|
||||
ent->ccp = ccp;
|
||||
ent->tag = tag;
|
||||
ent->tei = tei;
|
||||
|
||||
llist_add_tail(&ent->list, &bts->rbs2000.con.conn_groups);
|
||||
}
|
||||
|
||||
static int del_con_list(struct gsm_bts *bts, uint8_t cg, uint16_t ccp,
|
||||
uint8_t tag, uint8_t tei)
|
||||
{
|
||||
struct con_conn_group *grp, *grp2;
|
||||
|
||||
llist_for_each_entry_safe(grp, grp2, &bts->rbs2000.con.conn_groups, list) {
|
||||
if (grp->cg == cg && grp->ccp == ccp && grp->tag == tag
|
||||
&& grp->tei == tei) {
|
||||
llist_del(&grp->list);
|
||||
talloc_free(grp);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
#define CON_LIST_HELP "CON connetiton list\n" \
|
||||
"Add entry to CON list\n" \
|
||||
"Delete entry from CON list\n" \
|
||||
"Connection Group Number\n" \
|
||||
"CON Connection Point\n" \
|
||||
|
||||
DEFUN(om2k_con_list_dec, om2k_con_list_dec_cmd,
|
||||
"con-connection-list (add|del) <1-255> <0-1023> deconcentrated",
|
||||
CON_LIST_HELP "De-concentrated in/outlet\n")
|
||||
{
|
||||
struct oml_node_state *oms = vty->index;
|
||||
struct gsm_bts *bts = oms->bts;
|
||||
uint8_t cg = atoi(argv[1]);
|
||||
uint16_t ccp = atoi(argv[2]);
|
||||
|
||||
if (!strcmp(argv[0], "add"))
|
||||
add_con_list(bts, cg, ccp, 0, 0xff);
|
||||
else {
|
||||
if (del_con_list(bts, cg, ccp, 0, 0xff) < 0) {
|
||||
vty_out(vty, "%% No matching CON list entry%s",
|
||||
VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(om2k_con_list_tei, om2k_con_list_tei_cmd,
|
||||
"con-connection-list (add|del) <1-255> <0-1023> tei <0-63>",
|
||||
CON_LIST_HELP "Concentrated in/outlet with TEI\n" "TEI Number\n")
|
||||
{
|
||||
struct oml_node_state *oms = vty->index;
|
||||
struct gsm_bts *bts = oms->bts;
|
||||
uint8_t cg = atoi(argv[1]);
|
||||
uint16_t ccp = atoi(argv[2]);
|
||||
uint8_t tei = atoi(argv[3]);
|
||||
|
||||
if (!strcmp(argv[0], "add"))
|
||||
add_con_list(bts, cg, ccp, cg, tei);
|
||||
else {
|
||||
if (del_con_list(bts, cg, ccp, cg, tei) < 0) {
|
||||
vty_out(vty, "%% No matching CON list entry%s",
|
||||
VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
static void om2k_fill_is_conn_grp(struct om2k_is_conn_grp *grp, uint16_t icp1,
|
||||
uint16_t icp2, uint8_t cont_idx)
|
||||
{
|
||||
grp->icp1 = htons(icp1);
|
||||
grp->icp2 = htons(icp2);
|
||||
grp->cont_idx = cont_idx;
|
||||
}
|
||||
|
||||
struct is_conn_group {
|
||||
struct llist_head list;
|
||||
uint16_t icp1;
|
||||
uint16_t icp2;
|
||||
uint8_t ci;
|
||||
};
|
||||
|
||||
DEFUN(cfg_bts_is_conn_list, cfg_bts_is_conn_list_cmd,
|
||||
"is-connection-list (add|del) <0-2047> <0-2047> <0-255>",
|
||||
"Interface Switch Connnection List\n"
|
||||
"Add to IS list\n" "Delete from IS list\n"
|
||||
"ICP1\n" "ICP2\n" "Contiguity Index\n")
|
||||
{
|
||||
struct gsm_bts *bts = vty->index;
|
||||
uint16_t icp1 = atoi(argv[1]);
|
||||
uint16_t icp2 = atoi(argv[2]);
|
||||
uint8_t ci = atoi(argv[3]);
|
||||
struct is_conn_group *grp, *grp2;
|
||||
|
||||
if (!strcmp(argv[0], "add")) {
|
||||
grp = talloc_zero(bts, struct is_conn_group);
|
||||
grp->icp1 = icp1;
|
||||
grp->icp2 = icp2;
|
||||
grp->ci = ci;
|
||||
llist_add_tail(&grp->list, &bts->rbs2000.is.conn_groups);
|
||||
} else {
|
||||
llist_for_each_entry_safe(grp, grp2, &bts->rbs2000.is.conn_groups, list) {
|
||||
if (grp->icp1 == icp1 && grp->icp2 == icp2
|
||||
&& grp->ci == ci) {
|
||||
llist_del(&grp->list);
|
||||
talloc_free(grp);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
}
|
||||
vty_out(vty, "%% No matching IS Conn Group found!%s",
|
||||
VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
DEFUN(om2k_is_conf_req, om2k_is_conf_req_cmd,
|
||||
"is-conf-req",
|
||||
"Send IS Configuration Request\n")
|
||||
{
|
||||
struct oml_node_state *oms = vty->index;
|
||||
struct gsm_bts *bts = oms->bts;
|
||||
struct is_conn_group *grp;
|
||||
unsigned int num_grps = 0, i = 0;
|
||||
struct om2k_is_conn_grp *o2grps;
|
||||
|
||||
/* count number of groups in linked list */
|
||||
llist_for_each_entry(grp, &bts->rbs2000.is.conn_groups, list)
|
||||
num_grps++;
|
||||
|
||||
if (!num_grps) {
|
||||
vty_out(vty, "%% No IS connection groups configured!%s",
|
||||
VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
/* allocate buffer for oml group array */
|
||||
o2grps = talloc_zero_array(bts, struct om2k_is_conn_grp, num_grps);
|
||||
|
||||
/* fill array with data from linked list */
|
||||
llist_for_each_entry(grp, &bts->rbs2000.is.conn_groups, list)
|
||||
om2k_fill_is_conn_grp(&o2grps[i++], grp->icp1, grp->icp2, grp->ci);
|
||||
|
||||
/* send the actual OML request */
|
||||
abis_om2k_tx_is_conf_req(oms->bts, o2grps, num_grps);
|
||||
|
||||
talloc_free(o2grps);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
void abis_om2k_config_write_bts(struct vty *vty, struct gsm_bts *bts)
|
||||
{
|
||||
struct is_conn_group *igrp;
|
||||
struct con_conn_group *cgrp;
|
||||
|
||||
llist_for_each_entry(igrp, &bts->rbs2000.is.conn_groups, list)
|
||||
vty_out(vty, " is-connection-list add %u %u %u%s",
|
||||
igrp->icp1, igrp->icp2, igrp->ci, VTY_NEWLINE);
|
||||
|
||||
llist_for_each_entry(cgrp, &bts->rbs2000.con.conn_groups, list) {
|
||||
vty_out(vty, " con-connection-list add %u %u ",
|
||||
cgrp->cg, cgrp->ccp);
|
||||
if (cgrp->tei == 0xff)
|
||||
vty_out(vty, "deconcentrated%s", VTY_NEWLINE);
|
||||
else
|
||||
vty_out(vty, "tei %u%s", cgrp->tei, VTY_NEWLINE);
|
||||
}
|
||||
}
|
||||
|
||||
int abis_om2k_vty_init(void)
|
||||
{
|
||||
install_element(ENABLE_NODE, &om2k_class_inst_cmd);
|
||||
install_element(ENABLE_NODE, &om2k_classnum_inst_cmd);
|
||||
install_node(&om2k_node, dummy_config_write);
|
||||
|
||||
install_default(OM2K_NODE);
|
||||
install_element(OM2K_NODE, &ournode_exit_cmd);
|
||||
install_element(OM2K_NODE, &om2k_reset_cmd);
|
||||
install_element(OM2K_NODE, &om2k_start_cmd);
|
||||
install_element(OM2K_NODE, &om2k_status_cmd);
|
||||
install_element(OM2K_NODE, &om2k_connect_cmd);
|
||||
install_element(OM2K_NODE, &om2k_disconnect_cmd);
|
||||
install_element(OM2K_NODE, &om2k_enable_cmd);
|
||||
install_element(OM2K_NODE, &om2k_disable_cmd);
|
||||
install_element(OM2K_NODE, &om2k_op_info_cmd);
|
||||
install_element(OM2K_NODE, &om2k_test_cmd);
|
||||
install_element(OM2K_NODE, &om2k_is_conf_req_cmd);
|
||||
install_element(OM2K_NODE, &om2k_con_list_dec_cmd);
|
||||
install_element(OM2K_NODE, &om2k_con_list_tei_cmd);
|
||||
|
||||
install_element(BTS_NODE, &cfg_bts_is_conn_list_cmd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -6,18 +6,17 @@
|
||||
* All Rights Reserved
|
||||
*
|
||||
* 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 2 of the License, or
|
||||
* 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.
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -51,6 +50,15 @@
|
||||
|
||||
static int rsl_send_imm_assignment(struct gsm_lchan *lchan);
|
||||
|
||||
static void send_lchan_signal(int sig_no, struct gsm_lchan *lchan,
|
||||
struct gsm_meas_rep *resp)
|
||||
{
|
||||
struct lchan_signal_data sig;
|
||||
sig.lchan = lchan;
|
||||
sig.mr = resp;
|
||||
dispatch_signal(SS_LCHAN, sig_no, &sig);
|
||||
}
|
||||
|
||||
static u_int8_t mdisc_by_msgtype(u_int8_t msg_type)
|
||||
{
|
||||
/* mask off the transparent bit ? */
|
||||
@@ -130,9 +138,8 @@ struct gsm_lchan *lchan_lookup(struct gsm_bts_trx *trx, u_int8_t chan_nr)
|
||||
}
|
||||
|
||||
/* See Table 10.5.25 of GSM04.08 */
|
||||
u_int8_t lchan2chan_nr(const struct gsm_lchan *lchan)
|
||||
static u_int8_t ts2chan_nr(const struct gsm_bts_trx_ts *ts, uint8_t lchan_nr)
|
||||
{
|
||||
struct gsm_bts_trx_ts *ts = lchan->ts;
|
||||
u_int8_t cbits, chan_nr;
|
||||
|
||||
switch (ts->pchan) {
|
||||
@@ -143,15 +150,15 @@ u_int8_t lchan2chan_nr(const struct gsm_lchan *lchan)
|
||||
break;
|
||||
case GSM_PCHAN_TCH_H:
|
||||
cbits = 0x02;
|
||||
cbits += lchan->nr;
|
||||
cbits += lchan_nr;
|
||||
break;
|
||||
case GSM_PCHAN_CCCH_SDCCH4:
|
||||
cbits = 0x04;
|
||||
cbits += lchan->nr;
|
||||
cbits += lchan_nr;
|
||||
break;
|
||||
case GSM_PCHAN_SDCCH8_SACCH8C:
|
||||
cbits = 0x08;
|
||||
cbits += lchan->nr;
|
||||
cbits += lchan_nr;
|
||||
break;
|
||||
default:
|
||||
case GSM_PCHAN_CCCH:
|
||||
@@ -164,6 +171,11 @@ u_int8_t lchan2chan_nr(const struct gsm_lchan *lchan)
|
||||
return chan_nr;
|
||||
}
|
||||
|
||||
u_int8_t lchan2chan_nr(const struct gsm_lchan *lchan)
|
||||
{
|
||||
return ts2chan_nr(lchan->ts, lchan->nr);
|
||||
}
|
||||
|
||||
/* As per TS 03.03 Section 2.2, the IMSI has 'not more than 15 digits' */
|
||||
u_int64_t str_to_imsi(const char *imsi_str)
|
||||
{
|
||||
@@ -268,6 +280,25 @@ int rsl_sacch_filling(struct gsm_bts_trx *trx, u_int8_t type,
|
||||
return abis_rsl_sendmsg(msg);
|
||||
}
|
||||
|
||||
int rsl_sacch_info_modify(struct gsm_lchan *lchan, u_int8_t type,
|
||||
const u_int8_t *data, int len)
|
||||
{
|
||||
struct abis_rsl_dchan_hdr *dh;
|
||||
struct msgb *msg = rsl_msgb_alloc();
|
||||
u_int8_t chan_nr = lchan2chan_nr(lchan);
|
||||
|
||||
dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
|
||||
init_dchan_hdr(dh, RSL_MT_SACCH_INFO_MODIFY);
|
||||
dh->chan_nr = chan_nr;
|
||||
|
||||
msgb_tv_put(msg, RSL_IE_SYSINFO_TYPE, type);
|
||||
msgb_tl16v_put(msg, RSL_IE_L3_INFO, len, data);
|
||||
|
||||
msg->trx = lchan->ts->trx;
|
||||
|
||||
return abis_rsl_sendmsg(msg);
|
||||
}
|
||||
|
||||
int rsl_chan_bs_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int db)
|
||||
{
|
||||
struct abis_rsl_dchan_hdr *dh;
|
||||
@@ -644,6 +675,24 @@ static int rsl_rf_chan_release(struct gsm_lchan *lchan, int error)
|
||||
return abis_rsl_sendmsg(msg);
|
||||
}
|
||||
|
||||
static int rsl_rx_rf_chan_rel_ack(struct gsm_lchan *lchan)
|
||||
{
|
||||
|
||||
DEBUGP(DRSL, "%s RF CHANNEL RELEASE ACK\n", gsm_lchan_name(lchan));
|
||||
|
||||
if (lchan->state != LCHAN_S_REL_REQ && lchan->state != LCHAN_S_REL_ERR)
|
||||
LOGP(DRSL, LOGL_NOTICE, "%s CHAN REL ACK but state %s\n",
|
||||
gsm_lchan_name(lchan),
|
||||
gsm_lchans_name(lchan->state));
|
||||
bsc_del_timer(&lchan->T3111);
|
||||
/* we have an error timer pending to release that */
|
||||
if (lchan->state != LCHAN_S_REL_ERR)
|
||||
rsl_lchan_set_state(lchan, LCHAN_S_NONE);
|
||||
lchan_free(lchan);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rsl_paging_cmd(struct gsm_bts *bts, u_int8_t paging_group, u_int8_t len,
|
||||
u_int8_t *ms_ident, u_int8_t chan_needed)
|
||||
{
|
||||
@@ -663,18 +712,6 @@ int rsl_paging_cmd(struct gsm_bts *bts, u_int8_t paging_group, u_int8_t len,
|
||||
return abis_rsl_sendmsg(msg);
|
||||
}
|
||||
|
||||
int rsl_paging_cmd_subscr(struct gsm_bts *bts, u_int8_t chan_need,
|
||||
struct gsm_subscriber *subscr)
|
||||
{
|
||||
#if 0
|
||||
u_int8_t mi[128];
|
||||
unsigned int mi_len;
|
||||
u_int8_t paging_group;
|
||||
#endif
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int imsi_str2bcd(u_int8_t *bcd_out, const char *str_in)
|
||||
{
|
||||
int i, len = strlen(str_in);
|
||||
@@ -821,7 +858,7 @@ static int rsl_rx_chan_act_ack(struct msgb *msg)
|
||||
msg->lchan->rqd_ta = 0;
|
||||
}
|
||||
|
||||
dispatch_signal(SS_LCHAN, S_LCHAN_ACTIVATE_ACK, msg->lchan);
|
||||
send_lchan_signal(S_LCHAN_ACTIVATE_ACK, msg->lchan, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -851,7 +888,7 @@ static int rsl_rx_chan_act_nack(struct msgb *msg)
|
||||
|
||||
LOGPC(DRSL, LOGL_ERROR, "\n");
|
||||
|
||||
dispatch_signal(SS_LCHAN, S_LCHAN_ACTIVATE_NACK, msg->lchan);
|
||||
send_lchan_signal(S_LCHAN_ACTIVATE_NACK, msg->lchan, NULL);
|
||||
|
||||
lchan_free(msg->lchan);
|
||||
return 0;
|
||||
@@ -994,7 +1031,7 @@ static int rsl_rx_meas_res(struct msgb *msg)
|
||||
|
||||
print_meas_rep(mr);
|
||||
|
||||
dispatch_signal(SS_LCHAN, S_LCHAN_MEAS_REP, mr);
|
||||
send_lchan_signal(S_LCHAN_MEAS_REP, msg->lchan, mr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1015,7 +1052,7 @@ static int rsl_rx_hando_det(struct msgb *msg)
|
||||
else
|
||||
DEBUGPC(DRSL, "\n");
|
||||
|
||||
dispatch_signal(SS_LCHAN, S_LCHAN_HANDOVER_DETECT, msg->lchan);
|
||||
send_lchan_signal(S_LCHAN_HANDOVER_DETECT, msg->lchan, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1047,16 +1084,7 @@ static int abis_rsl_rx_dchan(struct msgb *msg)
|
||||
rc = rsl_rx_hando_det(msg);
|
||||
break;
|
||||
case RSL_MT_RF_CHAN_REL_ACK:
|
||||
DEBUGP(DRSL, "%s RF CHANNEL RELEASE ACK\n", ts_name);
|
||||
if (msg->lchan->state != LCHAN_S_REL_REQ && msg->lchan->state != LCHAN_S_REL_ERR)
|
||||
LOGP(DRSL, LOGL_NOTICE, "%s CHAN REL ACK but state %s\n",
|
||||
gsm_lchan_name(msg->lchan),
|
||||
gsm_lchans_name(msg->lchan->state));
|
||||
bsc_del_timer(&msg->lchan->T3111);
|
||||
/* we have an error timer pending to release that */
|
||||
if (msg->lchan->state != LCHAN_S_REL_ERR)
|
||||
rsl_lchan_set_state(msg->lchan, LCHAN_S_NONE);
|
||||
lchan_free(msg->lchan);
|
||||
rc = rsl_rx_rf_chan_rel_ack(msg->lchan);
|
||||
break;
|
||||
case RSL_MT_MODE_MODIFY_ACK:
|
||||
DEBUGP(DRSL, "%s CHANNEL MODE MODIFY ACK\n", ts_name);
|
||||
@@ -1160,6 +1188,45 @@ static void t3111_expired(void *data)
|
||||
|
||||
#define GSM48_LEN2PLEN(a) (((a) << 2) | 1)
|
||||
|
||||
/* Format an IMM ASS REJ according to 04.08 Chapter 9.1.20 */
|
||||
static int rsl_send_imm_ass_rej(struct gsm_bts *bts,
|
||||
unsigned int num_req_refs,
|
||||
struct gsm48_req_ref *rqd_refs,
|
||||
uint8_t wait_ind)
|
||||
{
|
||||
uint8_t buf[GSM_MACBLOCK_LEN];
|
||||
struct gsm48_imm_ass_rej *iar = (struct gsm48_imm_ass_rej *)buf;
|
||||
|
||||
/* create IMMEDIATE ASSIGN REJECT 04.08 message */
|
||||
memset(iar, 0, sizeof(*iar));
|
||||
iar->proto_discr = GSM48_PDISC_RR;
|
||||
iar->msg_type = GSM48_MT_RR_IMM_ASS;
|
||||
iar->page_mode = GSM48_PM_SAME;
|
||||
|
||||
memcpy(&iar->req_ref1, &rqd_refs[0], sizeof(iar->req_ref1));
|
||||
iar->wait_ind1 = wait_ind;
|
||||
|
||||
if (num_req_refs >= 2)
|
||||
memcpy(&iar->req_ref2, &rqd_refs[1], sizeof(iar->req_ref2));
|
||||
else
|
||||
memcpy(&iar->req_ref2, &rqd_refs[0], sizeof(iar->req_ref2));
|
||||
iar->wait_ind2 = wait_ind;
|
||||
|
||||
if (num_req_refs >= 3)
|
||||
memcpy(&iar->req_ref3, &rqd_refs[2], sizeof(iar->req_ref3));
|
||||
else
|
||||
memcpy(&iar->req_ref3, &rqd_refs[0], sizeof(iar->req_ref3));
|
||||
iar->wait_ind3 = wait_ind;
|
||||
|
||||
if (num_req_refs >= 4)
|
||||
memcpy(&iar->req_ref4, &rqd_refs[3], sizeof(iar->req_ref4));
|
||||
else
|
||||
memcpy(&iar->req_ref4, &rqd_refs[0], sizeof(iar->req_ref4));
|
||||
iar->wait_ind4 = wait_ind;
|
||||
|
||||
return rsl_imm_assign_cmd(bts, sizeof(iar), (uint8_t *) iar);
|
||||
}
|
||||
|
||||
/* MS has requested a channel on the RACH */
|
||||
static int rsl_rx_chan_rqd(struct msgb *msg)
|
||||
{
|
||||
@@ -1205,7 +1272,9 @@ static int rsl_rx_chan_rqd(struct msgb *msg)
|
||||
LOGP(DRSL, LOGL_NOTICE, "BTS %d CHAN RQD: no resources for %s 0x%x\n",
|
||||
msg->lchan->ts->trx->bts->nr, gsm_lchant_name(lctype), rqd_ref->ra);
|
||||
counter_inc(bts->network->stats.chreq.no_channel);
|
||||
/* FIXME: send some kind of reject ?!? */
|
||||
/* FIXME gather multiple CHAN RQD and reject up to 4 at the same time */
|
||||
if (bts->network->T3122)
|
||||
rsl_send_imm_ass_rej(bts, 1, rqd_ref, bts->network->T3122 & 0xff);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
@@ -1376,7 +1445,7 @@ static void rsl_handle_release(struct gsm_lchan *lchan)
|
||||
for (sapi = 0; sapi < ARRAY_SIZE(lchan->sapis); ++sapi) {
|
||||
if (lchan->sapis[sapi] == LCHAN_SAPI_UNUSED)
|
||||
continue;
|
||||
LOGP(DRSL, LOGL_NOTICE, "%s waiting for SAPI=%d to be released.\n",
|
||||
LOGP(DRSL, LOGL_DEBUG, "%s waiting for SAPI=%d to be released.\n",
|
||||
gsm_lchan_name(lchan), sapi);
|
||||
return;
|
||||
}
|
||||
@@ -1505,6 +1574,12 @@ static u_int8_t ipa_smod_s_for_lchan(struct gsm_lchan *lchan)
|
||||
|
||||
static u_int8_t ipa_rtp_pt_for_lchan(struct gsm_lchan *lchan)
|
||||
{
|
||||
struct gsm_network *net = lchan->ts->trx->bts->network;
|
||||
|
||||
/* allow to hardcode the rtp payload */
|
||||
if (net->hardcoded_rtp_payload != 0)
|
||||
return net->hardcoded_rtp_payload;
|
||||
|
||||
switch (lchan->tch_mode) {
|
||||
case GSM48_CMODE_SPEECH_V1:
|
||||
switch (lchan->type) {
|
||||
@@ -1677,7 +1752,7 @@ int rsl_ipacc_mdcx_to_rtpsock(struct gsm_lchan *lchan)
|
||||
return rc;
|
||||
}
|
||||
|
||||
int rsl_ipacc_pdch_activate(struct gsm_lchan *lchan, int act)
|
||||
int rsl_ipacc_pdch_activate(struct gsm_bts_trx_ts *ts, int act)
|
||||
{
|
||||
struct msgb *msg = rsl_msgb_alloc();
|
||||
struct abis_rsl_dchan_hdr *dh;
|
||||
@@ -1691,12 +1766,12 @@ int rsl_ipacc_pdch_activate(struct gsm_lchan *lchan, int act)
|
||||
dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
|
||||
init_dchan_hdr(dh, msg_type);
|
||||
dh->c.msg_discr = ABIS_RSL_MDISC_DED_CHAN;
|
||||
dh->chan_nr = lchan2chan_nr(lchan);
|
||||
dh->chan_nr = ts2chan_nr(ts, 0);
|
||||
|
||||
DEBUGP(DRSL, "%s IPAC_PDCH_%sACT\n", gsm_lchan_name(lchan),
|
||||
DEBUGP(DRSL, "%s IPAC_PDCH_%sACT\n", gsm_ts_name(ts),
|
||||
act ? "" : "DE");
|
||||
|
||||
msg->trx = lchan->ts->trx;
|
||||
msg->trx = ts->trx;
|
||||
|
||||
return abis_rsl_sendmsg(msg);
|
||||
}
|
||||
@@ -1721,32 +1796,9 @@ static int abis_rsl_rx_ipacc_crcx_ack(struct msgb *msg)
|
||||
|
||||
ipac_parse_rtp(lchan, &tv);
|
||||
|
||||
/* in case we don't use direct BTS-to-BTS RTP */
|
||||
if (!ipacc_rtp_direct) {
|
||||
int rc;
|
||||
/* the BTS has successfully bound a TCH to a local ip/port,
|
||||
* which means we can connect our UDP socket to it */
|
||||
if (lchan->abis_ip.rtp_socket) {
|
||||
rtp_socket_free(lchan->abis_ip.rtp_socket);
|
||||
lchan->abis_ip.rtp_socket = NULL;
|
||||
}
|
||||
|
||||
lchan->abis_ip.rtp_socket = rtp_socket_create();
|
||||
if (!lchan->abis_ip.rtp_socket)
|
||||
goto out_err;
|
||||
|
||||
rc = rtp_socket_connect(lchan->abis_ip.rtp_socket,
|
||||
lchan->abis_ip.bound_ip,
|
||||
lchan->abis_ip.bound_port);
|
||||
if (rc < 0)
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
dispatch_signal(SS_ABISIP, S_ABISIP_CRCX_ACK, msg->lchan);
|
||||
|
||||
return 0;
|
||||
out_err:
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
static int abis_rsl_rx_ipacc_mdcx_ack(struct msgb *msg)
|
||||
@@ -1770,7 +1822,6 @@ static int abis_rsl_rx_ipacc_dlcx_ind(struct msgb *msg)
|
||||
{
|
||||
struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
|
||||
struct tlv_parsed tv;
|
||||
struct gsm_lchan *lchan = msg->lchan;
|
||||
|
||||
rsl_tlv_parse(&tv, dh->data, msgb_l2len(msg)-sizeof(*dh));
|
||||
|
||||
@@ -1778,12 +1829,6 @@ static int abis_rsl_rx_ipacc_dlcx_ind(struct msgb *msg)
|
||||
print_rsl_cause(LOGL_DEBUG, TLVP_VAL(&tv, RSL_IE_CAUSE),
|
||||
TLVP_LEN(&tv, RSL_IE_CAUSE));
|
||||
|
||||
/* the BTS tells us a RTP stream has been disconnected */
|
||||
if (lchan->abis_ip.rtp_socket) {
|
||||
rtp_socket_free(lchan->abis_ip.rtp_socket);
|
||||
lchan->abis_ip.rtp_socket = NULL;
|
||||
}
|
||||
|
||||
dispatch_signal(SS_ABISIP, S_ABISIP_DLCX_IND, msg->lchan);
|
||||
|
||||
return 0;
|
||||
|
||||
194
openbsc/src/arfcn_list_range.c
Normal file
194
openbsc/src/arfcn_list_range.c
Normal file
@@ -0,0 +1,194 @@
|
||||
/* C-Implementation of the Algorithm described in Appendix J of GSM TS 44.018,
|
||||
* (C) 2009 by Dirk Hakkesteegt <dirk@hakkesteegt.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/>.
|
||||
*
|
||||
*/
|
||||
/* Annex J.3 indicates that at least in one BA list, we can never have more
|
||||
* than 29 frequencies within the 16byte limit */
|
||||
#define MAX_ARRFCNS 29
|
||||
|
||||
/*****************************************************************************
|
||||
* NAME : smod
|
||||
* DESCRIPTION : n smod m indicates the offset remainder of the euclidian
|
||||
* division of n by m
|
||||
* INPUT : n, m
|
||||
* OUTPUT : n smod m
|
||||
* RETURNS :
|
||||
* Errorcodes :
|
||||
******************************************************************************/
|
||||
static int smod(int n, int m)
|
||||
{
|
||||
int result = n % m;
|
||||
if (result < 0)
|
||||
result += m;
|
||||
|
||||
if (result == 0)
|
||||
result = m;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* NAME : mod
|
||||
* DESCRIPTION : n mod m indicates the remainder of the euclidian division of
|
||||
* n by m
|
||||
* INPUT : n, m
|
||||
* OUTPUT : n mod m
|
||||
* RETURNS :
|
||||
* Errorcodes :
|
||||
******************************************************************************/
|
||||
static int mod(int n, int m)
|
||||
{
|
||||
int result = n % m;
|
||||
if (result < 0)
|
||||
result += m;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* NAME : greatest_power_of_2_le_to
|
||||
* DESCRIPTION : Calculates the greatest power of 2 that is lesser or equal
|
||||
* to the input value;
|
||||
* INPUT :
|
||||
* OUTPUT :
|
||||
* RETURNS :
|
||||
* Errorcodes :
|
||||
******************************************************************************/
|
||||
static int greatest_power_of_2_le_to(int input)
|
||||
{
|
||||
int check_val = 1;
|
||||
while (check_val <= input)
|
||||
check_val *= 2;
|
||||
|
||||
return check_val / 2;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* NAME : ENCODE_SUBTREE
|
||||
* DESCRIPTION : Recursive encoding routine based on 3GPP TS44.018 Annex J.4
|
||||
* INPUT : index: current position in the W list
|
||||
* set: the array to be encoded
|
||||
* range: the current range
|
||||
* set_size: number of elements in set
|
||||
* OUTPUT : W: the array of results
|
||||
* RETURNS :
|
||||
* Errorcodes :
|
||||
******************************************************************************/
|
||||
static void encode_subtree(int index, int *set, int range, int set_size, int *W)
|
||||
{
|
||||
int index_in_set = 0;
|
||||
int N, J, I, x;
|
||||
int subset[18];
|
||||
int subset_index, origin_value;
|
||||
|
||||
/* Check if this is a leaf */
|
||||
if (set_size == 0) {
|
||||
W[index] = 0;
|
||||
return;
|
||||
} else {
|
||||
if (set_size == 1) {
|
||||
W[index] = 1 + set[1];
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (I = 1; I <= set_size; I++) {
|
||||
N = 0;
|
||||
for (J = 1; J <= set_size; J++) {
|
||||
x = set[J] - set[I];
|
||||
x = mod(x, range);
|
||||
if (x <= (range-1)/2)
|
||||
N++;
|
||||
}
|
||||
if (N-1 == (set_size-1) / 2) {
|
||||
index_in_set = I;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
W[index] = set[index_in_set] + 1;
|
||||
|
||||
/* Left subset */
|
||||
subset[0] = 0;
|
||||
origin_value = mod((set[index_in_set] + (range-1) / 2 + 1), range);
|
||||
subset_index = 1;
|
||||
for (I = 1; I <= set_size; I++) {
|
||||
if (mod((set[I]-origin_value), range) < range/2) {
|
||||
subset[subset_index] = mod((set[I] - origin_value), range);
|
||||
subset_index++;
|
||||
subset[subset_index] = 0;
|
||||
}
|
||||
}
|
||||
encode_subtree(index + greatest_power_of_2_le_to(index),
|
||||
subset, range / 2, subset_index-1, W);
|
||||
|
||||
/* Right subset */
|
||||
subset[0] = 0;
|
||||
origin_value = mod((set[index_in_set] + 1), range);
|
||||
subset_index=1;
|
||||
for (I = 1; I<= set_size; I++) {
|
||||
if (mod((set[I]-origin_value), range) < range/2) {
|
||||
subset[subset_index] = mod((set[I] - origin_value), range);
|
||||
subset_index++;
|
||||
subset[subset_index] = 0;
|
||||
}
|
||||
}
|
||||
encode_subtree(index + 2*greatest_power_of_2_le_to(index),
|
||||
subset, (range-1)/2, subset_index-1, W);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* NAME : CalcARFCN
|
||||
* DESCRIPTION : Calculate the ARFCN list
|
||||
* INPUT : F: the list of input frequencies. MUST BE SORTED!
|
||||
* count: the number of elements in the F list
|
||||
* range: the encoding range (default: range 512)
|
||||
* OUTPUT : W: the list of W values
|
||||
* RETURNS :
|
||||
* Errorcodes :
|
||||
******************************************************************************/
|
||||
static void CalcARFCN(const unsigned int *F, int *W, unsigned int count, unsigned int range)
|
||||
{
|
||||
int i;
|
||||
int Fd[MAX_ARFCNS+1];
|
||||
|
||||
W[0] = F[0];
|
||||
for (i = 1; i < count; i++) {
|
||||
Fd[i] = F[i] - F[0] - 1;
|
||||
}
|
||||
encode_subtree(1, Fd, range-1, count-1, W);
|
||||
}
|
||||
|
||||
int bitvec2arfcn_list_range(uint8_t *range, struct bitvec *bv, uint16_t range)
|
||||
{
|
||||
unsigned int i, idx = 0;
|
||||
int F[MAX_ARFCNS+1];
|
||||
int W[MAX_ARFCNS+1];
|
||||
|
||||
/* build an array of integers from the bitmask */
|
||||
for (i = 0; i < bv->data_len*8; i++) {
|
||||
if (bitvec_get_bit_pos(bv, i))
|
||||
F[idx++] = i;
|
||||
}
|
||||
/* Perform the actual algorithm to calculate the 'W' values */
|
||||
CalcARFCN(F, W, idx, range);
|
||||
|
||||
/* FIXME: Encode the 'W' values into the actual format as used in 04.08 */
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
@@ -6,23 +6,23 @@
|
||||
* All Rights Reserved
|
||||
*
|
||||
* 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 2 of the License, or
|
||||
* 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.
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* 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 <openbsc/db.h>
|
||||
#include <openbsc/debug.h>
|
||||
#include <openbsc/auth.h>
|
||||
#include <openbsc/gsm_data.h>
|
||||
|
||||
#include <osmocore/comp128.h>
|
||||
@@ -36,7 +36,7 @@ _use_xor(struct gsm_auth_info *ainfo, struct gsm_auth_tuple *atuple)
|
||||
int i, l = ainfo->a3a8_ki_len;
|
||||
|
||||
if ((l > A38_XOR_MAX_KEY_LEN) || (l < A38_XOR_MIN_KEY_LEN)) {
|
||||
DEBUGP(DMM, "Invalid XOR key (len=%d) %s",
|
||||
LOGP(DMM, LOGL_ERROR, "Invalid XOR key (len=%d) %s\n",
|
||||
ainfo->a3a8_ki_len,
|
||||
hexdump(ainfo->a3a8_ki, ainfo->a3a8_ki_len));
|
||||
return -1;
|
||||
@@ -54,7 +54,7 @@ static int
|
||||
_use_comp128_v1(struct gsm_auth_info *ainfo, struct gsm_auth_tuple *atuple)
|
||||
{
|
||||
if (ainfo->a3a8_ki_len != A38_COMP128_KEY_LEN) {
|
||||
DEBUGP(DMM, "Invalid COMP128v1 key (len=%d) %s",
|
||||
LOGP(DMM, LOGL_ERROR, "Invalid COMP128v1 key (len=%d) %s\n",
|
||||
ainfo->a3a8_ki_len,
|
||||
hexdump(ainfo->a3a8_ki, ainfo->a3a8_ki_len));
|
||||
return -1;
|
||||
@@ -80,8 +80,9 @@ int auth_get_tuple_for_subscr(struct gsm_auth_tuple *atuple,
|
||||
/* Get subscriber info (if any) */
|
||||
rc = db_get_authinfo_for_subscr(&ainfo, subscr);
|
||||
if (rc < 0) {
|
||||
DEBUGP(DMM, "No retrievable Ki for subscriber, skipping auth");
|
||||
return rc == -ENOENT ? 0 : -1;
|
||||
LOGP(DMM, LOGL_NOTICE,
|
||||
"No retrievable Ki for subscriber, skipping auth\n");
|
||||
return rc == -ENOENT ? AUTH_NOT_AVAIL : -1;
|
||||
}
|
||||
|
||||
/* If possible, re-use the last tuple and skip auth */
|
||||
@@ -92,7 +93,8 @@ int auth_get_tuple_for_subscr(struct gsm_auth_tuple *atuple,
|
||||
{
|
||||
atuple->use_count++;
|
||||
db_sync_lastauthtuple_for_subscr(atuple, subscr);
|
||||
return 2;
|
||||
DEBUGP(DMM, "Auth tuple use < 3, just doing ciphering\n");
|
||||
return AUTH_DO_CIPH;
|
||||
}
|
||||
|
||||
/* Generate a new one */
|
||||
@@ -102,27 +104,29 @@ int auth_get_tuple_for_subscr(struct gsm_auth_tuple *atuple,
|
||||
atuple->rand[i] = random() & 0xff;
|
||||
|
||||
switch (ainfo.auth_algo) {
|
||||
case AUTH_ALGO_NONE:
|
||||
case AUTH_ALGO_NONE:
|
||||
DEBUGP(DMM, "No authentication for subscriber\n");
|
||||
return 0;
|
||||
|
||||
case AUTH_ALGO_XOR:
|
||||
if (_use_xor(&ainfo, atuple))
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case AUTH_ALGO_XOR:
|
||||
if (_use_xor(&ainfo, atuple))
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case AUTH_ALGO_COMP128v1:
|
||||
if (_use_comp128_v1(&ainfo, atuple))
|
||||
return 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
DEBUGP(DMM, "Unsupported auth type algo_id=%d\n",
|
||||
ainfo.auth_algo);
|
||||
case AUTH_ALGO_COMP128v1:
|
||||
if (_use_comp128_v1(&ainfo, atuple))
|
||||
return 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
DEBUGP(DMM, "Unsupported auth type algo_id=%d\n",
|
||||
ainfo.auth_algo);
|
||||
return 0;
|
||||
}
|
||||
|
||||
db_sync_lastauthtuple_for_subscr(atuple, subscr);
|
||||
|
||||
return 1;
|
||||
DEBUGP(DMM, "Need to do authentication and ciphering\n");
|
||||
return AUTH_DO_AUTH_THAN_CIPH;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,24 +1,23 @@
|
||||
/* Siemens BS-11 microBTS configuration tool */
|
||||
|
||||
/* (C) 2009 by Harald Welte <laforge@gnumonks.org>
|
||||
/* (C) 2009-2010 by Harald Welte <laforge@gnumonks.org>
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This software is based on ideas (but not code) of BS11Config
|
||||
* (C) 2009 by Dieter Spaar <spaar@mirider.augusta.de>
|
||||
*
|
||||
* 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 2 of the License, or
|
||||
* 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.
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -331,6 +330,18 @@ static const char *cclk_acc_name(u_int8_t acc)
|
||||
}
|
||||
}
|
||||
|
||||
static const char *bport_lcfg_name(u_int8_t lcfg)
|
||||
{
|
||||
switch (lcfg) {
|
||||
case BS11_LINE_CFG_STAR:
|
||||
return "Star";
|
||||
case BS11_LINE_CFG_MULTIDROP:
|
||||
return "Multi-Drop";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
static const char *obj_name(struct abis_om_fom_hdr *foh)
|
||||
{
|
||||
static char retbuf[256];
|
||||
@@ -356,6 +367,10 @@ static const char *obj_name(struct abis_om_fom_hdr *foh)
|
||||
case NM_OC_SITE_MANAGER:
|
||||
strcat(retbuf, "SITE MANAGER ");
|
||||
break;
|
||||
case NM_OC_BS11_BPORT:
|
||||
sprintf(retbuf+strlen(retbuf), "BPORT%u ",
|
||||
foh->obj_inst.bts_nr);
|
||||
break;
|
||||
}
|
||||
return retbuf;
|
||||
}
|
||||
@@ -441,6 +456,13 @@ static int print_attr(struct tlv_parsed *tp)
|
||||
const u_int8_t *acc = TLVP_VAL(tp, NM_ATT_BS11_CCLK_TYPE);
|
||||
printf("\tCCLK Type=%d\n", *acc);
|
||||
}
|
||||
if (TLVP_PRESENT(tp, NM_ATT_BS11_LINE_CFG) &&
|
||||
TLVP_LEN(tp, NM_ATT_BS11_LINE_CFG) >= 1) {
|
||||
const u_int8_t *lcfg = TLVP_VAL(tp, NM_ATT_BS11_LINE_CFG);
|
||||
printf("\tLine Configuration: %s (%d)\n",
|
||||
bport_lcfg_name(*lcfg), *lcfg);
|
||||
}
|
||||
|
||||
|
||||
|
||||
return 0;
|
||||
@@ -459,6 +481,8 @@ static void cmd_query(void)
|
||||
trx = gsm_bts_trx_num(g_bts, 1);
|
||||
if (trx)
|
||||
abis_nm_bs11_get_trx_power(trx);
|
||||
abis_nm_bs11_get_bport_line_cfg(g_bts, 0);
|
||||
abis_nm_bs11_get_bport_line_cfg(g_bts, 1);
|
||||
sleep(1);
|
||||
abis_nm_bs11_factory_logon(g_bts, 0);
|
||||
command = NULL;
|
||||
@@ -585,7 +609,13 @@ static int handle_state_resp(enum abis_bs11_phase state)
|
||||
sleep(1);
|
||||
abis_nm_bs11_factory_logon(g_bts, 0);
|
||||
command = NULL;
|
||||
} else if (!strcmp(command, "bport1-multidrop")) {
|
||||
abis_nm_bs11_set_bport_line_cfg(g_bts, 1, BS11_LINE_CFG_MULTIDROP);
|
||||
sleep(1);
|
||||
abis_nm_bs11_factory_logon(g_bts, 0);
|
||||
command = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
case BS11_STATE_NORMAL:
|
||||
@@ -672,6 +702,21 @@ int handle_serial_msg(struct msgb *rx_msg)
|
||||
foh->obj_class, foh->obj_inst.bts_nr,
|
||||
foh->obj_inst.trx_nr, foh->obj_inst.ts_nr);
|
||||
break;
|
||||
case NM_MT_GET_ATTR_NACK:
|
||||
printf("\n%sGET ATTR NACK\n", obj_name(foh));
|
||||
break;
|
||||
case NM_MT_BS11_CREATE_OBJ_ACK:
|
||||
printf("\n%sCREATE OBJECT ACK\n", obj_name(foh));
|
||||
break;
|
||||
case NM_MT_BS11_CREATE_OBJ_NACK:
|
||||
printf("\n%sCREATE OBJECT NACK\n", obj_name(foh));
|
||||
break;
|
||||
case NM_MT_BS11_DELETE_OBJ_ACK:
|
||||
printf("\n%sDELETE OBJECT ACK\n", obj_name(foh));
|
||||
break;
|
||||
case NM_MT_BS11_DELETE_OBJ_NACK:
|
||||
printf("\n%sDELETE OBJECT NACK\n", obj_name(foh));
|
||||
break;
|
||||
default:
|
||||
rc = abis_nm_rcvmsg(rx_msg);
|
||||
}
|
||||
@@ -696,13 +741,6 @@ int handle_serial_msg(struct msgb *rx_msg)
|
||||
return rc;
|
||||
}
|
||||
|
||||
int nm_state_event(enum nm_evt evt, u_int8_t obj_class, void *obj,
|
||||
struct gsm_nm_state *old_state, struct gsm_nm_state *new_state,
|
||||
struct abis_om_obj_inst *obj_ins)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void status_timer_cb(void *data)
|
||||
{
|
||||
abis_nm_bs11_get_state(g_bts);
|
||||
@@ -710,7 +748,7 @@ void status_timer_cb(void *data)
|
||||
|
||||
static void print_banner(void)
|
||||
{
|
||||
printf("bs11_config (C) 2009 by Harald Welte and Dieter Spaar\n");
|
||||
printf("bs11_config (C) 2009-2010 by Harald Welte and Dieter Spaar\n");
|
||||
printf("This is FREE SOFTWARE with ABSOLUTELY NO WARRANTY\n\n");
|
||||
}
|
||||
|
||||
@@ -740,7 +778,8 @@ static void print_help(void)
|
||||
printf("\tpll-workvalue <value>\tSet the PLL work value\n");
|
||||
printf("\toml-tei\t\t\tSet OML E1 TS and TEI\n");
|
||||
printf("\tbport0-star\t\tSet BPORT0 line config to star\n");
|
||||
printf("\tbport0-multiport\tSet BPORT0 line config to multiport\n");
|
||||
printf("\tbport0-multidrop\tSet BPORT0 line config to multidrop\n");
|
||||
printf("\tbport1-multidrop\tSet BPORT1 line config to multidrop\n");
|
||||
printf("\tcreate-bport1\t\tCreate BPORT1 object\n");
|
||||
printf("\tdelete-bport1\t\tDelete BPORT1 object\n");
|
||||
}
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
INCLUDES = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)
|
||||
AM_CFLAGS=-Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(LIBOSMOSCCP_CFLAGS)
|
||||
AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(LIBOSMOVTY_LIBS)
|
||||
AM_CFLAGS=-Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(LIBOSMOSCCP_CFLAGS) $(COVERAGE_CFLAGS)
|
||||
AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(LIBOSMOVTY_LIBS) $(COVERAGE_LDFLAGS)
|
||||
|
||||
bin_PROGRAMS = osmo-bsc
|
||||
|
||||
|
||||
osmo_bsc_SOURCES = osmo_bsc_main.c osmo_bsc_rf.c osmo_bsc_vty.c osmo_bsc_api.c \
|
||||
osmo_bsc_grace.c osmo_bsc_msc.c \
|
||||
osmo_bsc_grace.c osmo_bsc_msc.c osmo_bsc_sccp.c \
|
||||
osmo_bsc_filter.c osmo_bsc_bssap.c osmo_bsc_audio.c \
|
||||
$(top_srcdir)/src/debug.c $(top_srcdir)/src/bsc_msc.c \
|
||||
$(top_srcdir)/src/bsc_init.c
|
||||
osmo_bsc_LDADD = $(top_builddir)/src/libvty.a \
|
||||
|
||||
@@ -3,73 +3,169 @@
|
||||
* All Rights Reserved
|
||||
*
|
||||
* 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 2 of the License, or
|
||||
* 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.
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* 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 <openbsc/osmo_bsc.h>
|
||||
#include <openbsc/osmo_msc_data.h>
|
||||
#include <openbsc/debug.h>
|
||||
|
||||
#include <osmocore/protocol/gsm_08_08.h>
|
||||
#include <osmocore/gsm0808.h>
|
||||
|
||||
#define return_when_not_connected(conn) \
|
||||
if (!conn->sccp_con) {\
|
||||
LOGP(DMSC, LOGL_ERROR, "MSC Connection not present.\n"); \
|
||||
return; \
|
||||
}
|
||||
|
||||
#define return_when_not_connected_val(conn, ret) \
|
||||
if (!conn->sccp_con) {\
|
||||
LOGP(DMSC, LOGL_ERROR, "MSC Connection not present.\n"); \
|
||||
return ret; \
|
||||
}
|
||||
|
||||
#define queue_msg_or_return(resp) \
|
||||
if (!resp) { \
|
||||
LOGP(DMSC, LOGL_ERROR, "Failed to allocate response.\n"); \
|
||||
return; \
|
||||
} \
|
||||
bsc_queue_for_msc(conn->sccp_con, resp);
|
||||
|
||||
static uint16_t get_network_code_for_msc(struct gsm_network *net)
|
||||
{
|
||||
if (net->msc_data->core_ncc != -1)
|
||||
return net->msc_data->core_ncc;
|
||||
return net->network_code;
|
||||
}
|
||||
|
||||
static uint16_t get_country_code_for_msc(struct gsm_network *net)
|
||||
{
|
||||
if (net->msc_data->core_mcc != -1)
|
||||
return net->msc_data->core_mcc;
|
||||
return net->country_code;
|
||||
}
|
||||
|
||||
static void bsc_sapi_n_reject(struct gsm_subscriber_connection *conn, int dlci)
|
||||
{
|
||||
struct msgb *resp;
|
||||
return_when_not_connected(conn);
|
||||
|
||||
resp = gsm0808_create_sapi_reject(dlci);
|
||||
queue_msg_or_return(resp);
|
||||
}
|
||||
|
||||
static void bsc_cipher_mode_compl(struct gsm_subscriber_connection *conn,
|
||||
struct msgb *msg, uint8_t chosen_encr)
|
||||
{
|
||||
struct msgb *resp;
|
||||
return_when_not_connected(conn);
|
||||
|
||||
LOGP(DMSC, LOGL_DEBUG, "CIPHER MODE COMPLETE from MS, forwarding to MSC\n");
|
||||
resp = gsm0808_create_cipher_complete(msg, chosen_encr);
|
||||
queue_msg_or_return(resp);
|
||||
}
|
||||
|
||||
static void bsc_cipher_mode_reject(struct gsm_subscriber_connection *conn,
|
||||
struct msgb *msg, uint16_t reason)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Instruct to reserve data for a new connectiom, create the complete
|
||||
* layer three message, send it to open the connection.
|
||||
*/
|
||||
static int bsc_compl_l3(struct gsm_subscriber_connection *conn, struct msgb *msg,
|
||||
uint16_t chosen_channel)
|
||||
{
|
||||
return BSC_API_CONN_POL_REJECT;
|
||||
struct msgb *resp;
|
||||
uint16_t network_code = get_network_code_for_msc(conn->bts->network);
|
||||
uint16_t country_code = get_country_code_for_msc(conn->bts->network);
|
||||
|
||||
/* allocate resource for a new connection */
|
||||
if (bsc_create_new_connection(conn) != 0)
|
||||
return BSC_API_CONN_POL_REJECT;
|
||||
|
||||
bsc_scan_bts_msg(conn, msg);
|
||||
resp = gsm0808_create_layer3(msg, network_code, country_code,
|
||||
conn->bts->location_area_code,
|
||||
conn->bts->cell_identity);
|
||||
if (!resp) {
|
||||
LOGP(DMSC, LOGL_DEBUG, "Failed to create layer3 message.\n");
|
||||
bsc_delete_connection(conn->sccp_con);
|
||||
return BSC_API_CONN_POL_REJECT;
|
||||
}
|
||||
|
||||
if (bsc_open_connection(conn->sccp_con, resp) != 0) {
|
||||
bsc_delete_connection(conn->sccp_con);
|
||||
msgb_free(resp);
|
||||
return BSC_API_CONN_POL_REJECT;
|
||||
}
|
||||
|
||||
return BSC_API_CONN_POL_ACCEPT;
|
||||
}
|
||||
|
||||
static void bsc_dtap(struct gsm_subscriber_connection *conn, struct msgb *msg)
|
||||
static void bsc_dtap(struct gsm_subscriber_connection *conn, uint8_t link_id, struct msgb *msg)
|
||||
{
|
||||
struct msgb *resp;
|
||||
return_when_not_connected(conn);
|
||||
|
||||
bsc_scan_bts_msg(conn, msg);
|
||||
resp = gsm0808_create_dtap(msg, link_id);
|
||||
queue_msg_or_return(resp);
|
||||
}
|
||||
|
||||
static void bsc_assign_compl(struct gsm_subscriber_connection *conn, uint16_t rr_cause)
|
||||
static void bsc_assign_compl(struct gsm_subscriber_connection *conn, uint8_t rr_cause,
|
||||
uint8_t chosen_channel, uint8_t encr_alg_id,
|
||||
uint8_t speech_model)
|
||||
{
|
||||
struct msgb *resp;
|
||||
return_when_not_connected(conn);
|
||||
|
||||
resp = gsm0808_create_assignment_completed(rr_cause, chosen_channel,
|
||||
encr_alg_id, speech_model);
|
||||
queue_msg_or_return(resp);
|
||||
}
|
||||
|
||||
static void bsc_assign_fail(struct gsm_subscriber_connection *conn, uint32_t cause)
|
||||
static void bsc_assign_fail(struct gsm_subscriber_connection *conn,
|
||||
uint8_t cause, uint8_t *rr_cause)
|
||||
{
|
||||
struct msgb *resp;
|
||||
return_when_not_connected(conn);
|
||||
|
||||
resp = gsm0808_create_assignment_failure(cause, rr_cause);
|
||||
queue_msg_or_return(resp);
|
||||
}
|
||||
|
||||
static void bsc_clear_request(struct gsm_subscriber_connection *conn, uint32_t cause)
|
||||
static int bsc_clear_request(struct gsm_subscriber_connection *conn, uint32_t cause)
|
||||
{
|
||||
}
|
||||
struct msgb *resp;
|
||||
return_when_not_connected_val(conn, 1);
|
||||
|
||||
static void bsc_clear_compl(struct gsm_subscriber_connection *conn)
|
||||
{
|
||||
resp = gsm0808_create_clear_rqst(GSM0808_CAUSE_RADIO_INTERFACE_FAILURE);
|
||||
if (!resp) {
|
||||
LOGP(DMSC, LOGL_ERROR, "Failed to allocate response.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
bsc_queue_for_msc(conn->sccp_con, resp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct bsc_api bsc_handler = {
|
||||
.sapi_n_reject = bsc_sapi_n_reject,
|
||||
.cipher_mode_compl = bsc_cipher_mode_compl,
|
||||
.cipher_mode_reject = bsc_cipher_mode_reject,
|
||||
.compl_l3 = bsc_compl_l3,
|
||||
.dtap = bsc_dtap,
|
||||
.assign_compl = bsc_assign_compl,
|
||||
.assign_fail = bsc_assign_fail,
|
||||
.clear_request = bsc_clear_request,
|
||||
.clear_compl = bsc_clear_compl,
|
||||
};
|
||||
|
||||
struct bsc_api *osmo_bsc_api()
|
||||
|
||||
70
openbsc/src/bsc/osmo_bsc_audio.c
Normal file
70
openbsc/src/bsc/osmo_bsc_audio.c
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* ipaccess audio handling
|
||||
*
|
||||
* (C) 2009-2010 by Holger Hans Peter Freyther <zecke@selfish.org>
|
||||
* (C) 2009-2010 by On-Waves
|
||||
* 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 <openbsc/osmo_msc_data.h>
|
||||
#include <openbsc/osmo_bsc.h>
|
||||
#include <openbsc/abis_rsl.h>
|
||||
#include <openbsc/gsm_data.h>
|
||||
#include <openbsc/debug.h>
|
||||
#include <openbsc/signal.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
|
||||
static int handle_abisip_signal(unsigned int subsys, unsigned int signal,
|
||||
void *handler_data, void *signal_data)
|
||||
{
|
||||
struct gsm_subscriber_connection *con;
|
||||
struct gsm_lchan *lchan = signal_data;
|
||||
int rc;
|
||||
|
||||
if (subsys != SS_ABISIP)
|
||||
return 0;
|
||||
|
||||
con = lchan->conn;
|
||||
if (!con || !con->sccp_con)
|
||||
return 0;
|
||||
|
||||
switch (signal) {
|
||||
case S_ABISIP_CRCX_ACK:
|
||||
/* we can ask it to connect now */
|
||||
LOGP(DMSC, LOGL_DEBUG, "Connecting BTS to port: %d conn: %d\n",
|
||||
con->sccp_con->rtp_port, lchan->abis_ip.conn_id);
|
||||
|
||||
rc = rsl_ipacc_mdcx(lchan, ntohl(INADDR_ANY),
|
||||
con->sccp_con->rtp_port,
|
||||
lchan->abis_ip.rtp_payload2);
|
||||
if (rc < 0) {
|
||||
LOGP(DMSC, LOGL_ERROR, "Failed to send MDCX: %d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int osmo_bsc_audio_init(struct gsm_network *net)
|
||||
{
|
||||
net->hardcoded_rtp_payload = 98;
|
||||
register_signal_handler(SS_ABISIP, handle_abisip_signal, net);
|
||||
return 0;
|
||||
}
|
||||
548
openbsc/src/bsc/osmo_bsc_bssap.c
Normal file
548
openbsc/src/bsc/osmo_bsc_bssap.c
Normal file
@@ -0,0 +1,548 @@
|
||||
/* GSM 08.08 BSSMAP handling */
|
||||
/* (C) 2009-2010 by Holger Hans Peter Freyther <zecke@selfish.org>
|
||||
* (C) 2009-2010 by On-Waves
|
||||
* 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 <openbsc/osmo_bsc.h>
|
||||
#include <openbsc/osmo_bsc_grace.h>
|
||||
#include <openbsc/osmo_msc_data.h>
|
||||
#include <openbsc/debug.h>
|
||||
#include <openbsc/gsm_subscriber.h>
|
||||
#include <openbsc/mgcp.h>
|
||||
#include <openbsc/paging.h>
|
||||
|
||||
#include <osmocore/gsm0808.h>
|
||||
#include <osmocore/protocol/gsm_08_08.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
|
||||
static uint16_t read_data16(const uint8_t *data)
|
||||
{
|
||||
uint16_t res;
|
||||
|
||||
memcpy(&res, data, sizeof(res));
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* helpers for the assignment command
|
||||
*/
|
||||
enum gsm0808_permitted_speech audio_support_to_gsm88(struct gsm_audio_support *audio)
|
||||
{
|
||||
if (audio->hr) {
|
||||
switch (audio->ver) {
|
||||
case 1:
|
||||
return GSM0808_PERM_HR1;
|
||||
break;
|
||||
case 2:
|
||||
return GSM0808_PERM_HR2;
|
||||
break;
|
||||
case 3:
|
||||
return GSM0808_PERM_HR3;
|
||||
break;
|
||||
default:
|
||||
LOGP(DMSC, LOGL_ERROR, "Wrong speech mode: %d\n", audio->ver);
|
||||
return GSM0808_PERM_FR1;
|
||||
}
|
||||
} else {
|
||||
switch (audio->ver) {
|
||||
case 1:
|
||||
return GSM0808_PERM_FR1;
|
||||
break;
|
||||
case 2:
|
||||
return GSM0808_PERM_FR2;
|
||||
break;
|
||||
case 3:
|
||||
return GSM0808_PERM_FR3;
|
||||
break;
|
||||
default:
|
||||
LOGP(DMSC, LOGL_ERROR, "Wrong speech mode: %d\n", audio->ver);
|
||||
return GSM0808_PERM_HR1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum gsm48_chan_mode gsm88_to_chan_mode(enum gsm0808_permitted_speech speech)
|
||||
{
|
||||
switch (speech) {
|
||||
case GSM0808_PERM_HR1:
|
||||
case GSM0808_PERM_FR1:
|
||||
return GSM48_CMODE_SPEECH_V1;
|
||||
break;
|
||||
case GSM0808_PERM_HR2:
|
||||
case GSM0808_PERM_FR2:
|
||||
return GSM48_CMODE_SPEECH_EFR;
|
||||
break;
|
||||
case GSM0808_PERM_HR3:
|
||||
case GSM0808_PERM_FR3:
|
||||
return GSM48_CMODE_SPEECH_AMR;
|
||||
break;
|
||||
}
|
||||
|
||||
LOGP(DMSC, LOGL_FATAL, "Should not be reached.\n");
|
||||
return GSM48_CMODE_SPEECH_AMR;
|
||||
}
|
||||
|
||||
static int bssmap_handle_reset_ack(struct gsm_network *net,
|
||||
struct msgb *msg, unsigned int length)
|
||||
{
|
||||
LOGP(DMSC, LOGL_NOTICE, "Reset ACK from MSC\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* GSM 08.08 § 3.2.1.19 */
|
||||
static int bssmap_handle_paging(struct gsm_network *net,
|
||||
struct msgb *msg, unsigned int payload_length)
|
||||
{
|
||||
struct gsm_subscriber *subscr;
|
||||
struct tlv_parsed tp;
|
||||
char mi_string[GSM48_MI_SIZE];
|
||||
uint32_t tmsi = GSM_RESERVED_TMSI;
|
||||
unsigned int lac = GSM_LAC_RESERVED_ALL_BTS;
|
||||
uint8_t data_length;
|
||||
const uint8_t *data;
|
||||
uint8_t chan_needed = RSL_CHANNEED_ANY;
|
||||
|
||||
tlv_parse(&tp, gsm0808_att_tlvdef(), msg->l4h + 1, payload_length - 1, 0, 0);
|
||||
|
||||
if (!TLVP_PRESENT(&tp, GSM0808_IE_IMSI)) {
|
||||
LOGP(DMSC, LOGL_ERROR, "Mandantory IMSI not present.\n");
|
||||
return -1;
|
||||
} else if ((TLVP_VAL(&tp, GSM0808_IE_IMSI)[0] & GSM_MI_TYPE_MASK) != GSM_MI_TYPE_IMSI) {
|
||||
LOGP(DMSC, LOGL_ERROR, "Wrong content in the IMSI\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!TLVP_PRESENT(&tp, GSM0808_IE_CELL_IDENTIFIER_LIST)) {
|
||||
LOGP(DMSC, LOGL_ERROR, "Mandantory CELL IDENTIFIER LIST not present.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (TLVP_PRESENT(&tp, GSM0808_IE_TMSI)) {
|
||||
gsm48_mi_to_string(mi_string, sizeof(mi_string),
|
||||
TLVP_VAL(&tp, GSM0808_IE_TMSI), TLVP_LEN(&tp, GSM0808_IE_TMSI));
|
||||
tmsi = strtoul(mi_string, NULL, 10);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* parse the IMSI
|
||||
*/
|
||||
gsm48_mi_to_string(mi_string, sizeof(mi_string),
|
||||
TLVP_VAL(&tp, GSM0808_IE_IMSI), TLVP_LEN(&tp, GSM0808_IE_IMSI));
|
||||
|
||||
/*
|
||||
* parse the cell identifier list
|
||||
*/
|
||||
data_length = TLVP_LEN(&tp, GSM0808_IE_CELL_IDENTIFIER_LIST);
|
||||
data = TLVP_VAL(&tp, GSM0808_IE_CELL_IDENTIFIER_LIST);
|
||||
|
||||
/*
|
||||
* Support paging to all network or one BTS at one LAC
|
||||
*/
|
||||
if (data_length == 3 && data[0] == CELL_IDENT_LAC) {
|
||||
lac = ntohs(read_data16(&data[1]));
|
||||
} else if (data_length > 1 || (data[0] & 0x0f) != CELL_IDENT_BSS) {
|
||||
LOGP(DMSC, LOGL_ERROR, "Unsupported Cell Identifier List: %s\n", hexdump(data, data_length));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (TLVP_PRESENT(&tp, GSM0808_IE_CHANNEL_NEEDED) && TLVP_LEN(&tp, GSM0808_IE_CHANNEL_NEEDED) == 1)
|
||||
chan_needed = TLVP_VAL(&tp, GSM0808_IE_CHANNEL_NEEDED)[0] & 0x03;
|
||||
|
||||
if (TLVP_PRESENT(&tp, GSM0808_IE_EMLPP_PRIORITY)) {
|
||||
LOGP(DMSC, LOGL_ERROR, "eMLPP is not handled\n");
|
||||
}
|
||||
|
||||
subscr = subscr_get_or_create(net, mi_string);
|
||||
if (!subscr) {
|
||||
LOGP(DMSC, LOGL_ERROR, "Failed to allocate a subscriber for %s\n", mi_string);
|
||||
return -1;
|
||||
}
|
||||
|
||||
subscr->lac = lac;
|
||||
subscr->tmsi = tmsi;
|
||||
|
||||
LOGP(DMSC, LOGL_DEBUG, "Paging request from MSC IMSI: '%s' TMSI: '0x%x/%u' LAC: 0x%x\n", mi_string, tmsi, tmsi, lac);
|
||||
paging_request(net, subscr, chan_needed, NULL, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* GSM 08.08 § 3.1.9.1 and 3.2.1.21...
|
||||
* release our gsm_subscriber_connection and send message
|
||||
*/
|
||||
static int bssmap_handle_clear_command(struct osmo_bsc_sccp_con *conn,
|
||||
struct msgb *msg, unsigned int payload_length)
|
||||
{
|
||||
struct msgb *resp;
|
||||
|
||||
/* TODO: handle the cause of this package */
|
||||
|
||||
if (conn->conn) {
|
||||
LOGP(DMSC, LOGL_DEBUG, "Releasing all transactions on %p\n", conn);
|
||||
gsm0808_clear(conn->conn);
|
||||
subscr_con_free(conn->conn);
|
||||
conn->conn = NULL;
|
||||
}
|
||||
|
||||
/* send the clear complete message */
|
||||
resp = gsm0808_create_clear_complete();
|
||||
if (!resp) {
|
||||
LOGP(DMSC, LOGL_ERROR, "Sending clear complete failed.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
bsc_queue_for_msc(conn, resp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* GSM 08.08 § 3.4.7 cipher mode handling. We will have to pick
|
||||
* the cipher to be used for this. In case we are already using
|
||||
* a cipher we will have to send cipher mode reject to the MSC,
|
||||
* otherwise we will have to pick something that we and the MS
|
||||
* is supporting. Currently we are doing it in a rather static
|
||||
* way by picking one ecnryption or no encrytpion.
|
||||
*/
|
||||
static int bssmap_handle_cipher_mode(struct osmo_bsc_sccp_con *conn,
|
||||
struct msgb *msg, unsigned int payload_length)
|
||||
{
|
||||
uint16_t len;
|
||||
struct gsm_network *network = NULL;
|
||||
const uint8_t *data;
|
||||
struct tlv_parsed tp;
|
||||
struct msgb *resp;
|
||||
int reject_cause = -1;
|
||||
int include_imeisv = 1;
|
||||
|
||||
if (!conn->conn) {
|
||||
LOGP(DMSC, LOGL_ERROR, "No lchan/msc_data in cipher mode command.\n");
|
||||
goto reject;
|
||||
}
|
||||
|
||||
if (conn->ciphering_handled) {
|
||||
LOGP(DMSC, LOGL_ERROR, "Already seen ciphering command. Protocol Error.\n");
|
||||
goto reject;
|
||||
}
|
||||
|
||||
conn->ciphering_handled = 1;
|
||||
|
||||
tlv_parse(&tp, gsm0808_att_tlvdef(), msg->l4h + 1, payload_length - 1, 0, 0);
|
||||
if (!TLVP_PRESENT(&tp, GSM0808_IE_ENCRYPTION_INFORMATION)) {
|
||||
LOGP(DMSC, LOGL_ERROR, "IE Encryption Information missing.\n");
|
||||
goto reject;
|
||||
}
|
||||
|
||||
/*
|
||||
* check if our global setting is allowed
|
||||
* - Currently we check for A5/0 and A5/1
|
||||
* - Copy the key if that is necessary
|
||||
* - Otherwise reject
|
||||
*/
|
||||
len = TLVP_LEN(&tp, GSM0808_IE_ENCRYPTION_INFORMATION);
|
||||
if (len < 1) {
|
||||
LOGP(DMSC, LOGL_ERROR, "IE Encryption Information is too short.\n");
|
||||
goto reject;
|
||||
}
|
||||
|
||||
network = conn->conn->bts->network;
|
||||
data = TLVP_VAL(&tp, GSM0808_IE_ENCRYPTION_INFORMATION);
|
||||
|
||||
if (TLVP_PRESENT(&tp, GSM0808_IE_CIPHER_RESPONSE_MODE))
|
||||
include_imeisv = TLVP_VAL(&tp, GSM0808_IE_CIPHER_RESPONSE_MODE)[0] & 0x1;
|
||||
|
||||
if (network->a5_encryption == 0 && (data[0] & 0x1) == 0x1) {
|
||||
gsm0808_cipher_mode(conn->conn, 0, NULL, 0, include_imeisv);
|
||||
} else if (network->a5_encryption != 0 && (data[0] & 0x2) == 0x2) {
|
||||
gsm0808_cipher_mode(conn->conn, 1, &data[1], len - 1, include_imeisv);
|
||||
} else {
|
||||
LOGP(DMSC, LOGL_ERROR, "Can not select encryption...\n");
|
||||
goto reject;
|
||||
}
|
||||
|
||||
reject:
|
||||
resp = gsm0808_create_cipher_reject(reject_cause);
|
||||
if (!resp) {
|
||||
LOGP(DMSC, LOGL_ERROR, "Sending the cipher reject failed.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
bsc_queue_for_msc(conn, resp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle the assignment request message.
|
||||
*
|
||||
* See §3.2.1.1 for the message type
|
||||
*/
|
||||
static int bssmap_handle_assignm_req(struct osmo_bsc_sccp_con *conn,
|
||||
struct msgb *msg, unsigned int length)
|
||||
{
|
||||
struct msgb *resp;
|
||||
struct gsm_network *network;
|
||||
struct tlv_parsed tp;
|
||||
uint8_t *data;
|
||||
uint16_t cic;
|
||||
uint8_t timeslot;
|
||||
uint8_t multiplex;
|
||||
enum gsm48_chan_mode chan_mode = GSM48_CMODE_SIGN;
|
||||
int i, supported, port, full_rate = -1;
|
||||
|
||||
if (!conn->conn) {
|
||||
LOGP(DMSC, LOGL_ERROR, "No lchan/msc_data in cipher mode command.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
network = conn->conn->bts->network;
|
||||
tlv_parse(&tp, gsm0808_att_tlvdef(), msg->l4h + 1, length - 1, 0, 0);
|
||||
|
||||
if (!TLVP_PRESENT(&tp, GSM0808_IE_CHANNEL_TYPE)) {
|
||||
LOGP(DMSC, LOGL_ERROR, "Mandantory channel type not present.\n");
|
||||
goto reject;
|
||||
}
|
||||
|
||||
if (!TLVP_PRESENT(&tp, GSM0808_IE_CIRCUIT_IDENTITY_CODE)) {
|
||||
LOGP(DMSC, LOGL_ERROR, "Identity code missing. Audio routing will not work.\n");
|
||||
goto reject;
|
||||
}
|
||||
|
||||
cic = ntohs(read_data16(TLVP_VAL(&tp, GSM0808_IE_CIRCUIT_IDENTITY_CODE)));
|
||||
timeslot = cic & 0x1f;
|
||||
multiplex = (cic & ~0x1f) >> 5;
|
||||
|
||||
/*
|
||||
* Currently we only support a limited subset of all
|
||||
* possible channel types. The limitation ends by not using
|
||||
* multi-slot, limiting the channel coding, speech...
|
||||
*/
|
||||
if (TLVP_LEN(&tp, GSM0808_IE_CHANNEL_TYPE) < 3) {
|
||||
LOGP(DMSC, LOGL_ERROR, "ChannelType len !=3 not supported: %d\n",
|
||||
TLVP_LEN(&tp, GSM0808_IE_CHANNEL_TYPE));
|
||||
goto reject;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to figure out if we support the proposed speech codecs. For
|
||||
* now we will always pick the full rate codecs.
|
||||
*/
|
||||
|
||||
data = (uint8_t *) TLVP_VAL(&tp, GSM0808_IE_CHANNEL_TYPE);
|
||||
if ((data[0] & 0xf) != 0x1) {
|
||||
LOGP(DMSC, LOGL_ERROR, "ChannelType != speech: %d\n", data[0]);
|
||||
goto reject;
|
||||
}
|
||||
|
||||
if (data[1] != GSM0808_SPEECH_FULL_PREF && data[1] != GSM0808_SPEECH_HALF_PREF) {
|
||||
LOGP(DMSC, LOGL_ERROR, "ChannelType full not allowed: %d\n", data[1]);
|
||||
goto reject;
|
||||
}
|
||||
|
||||
/*
|
||||
* go through the list of preferred codecs of our gsm network
|
||||
* and try to find it among the permitted codecs. If we found
|
||||
* it we will send chan_mode to the right mode and break the
|
||||
* inner loop. The outer loop will exit due chan_mode having
|
||||
* the correct value.
|
||||
*/
|
||||
full_rate = 0;
|
||||
for (supported = 0;
|
||||
chan_mode == GSM48_CMODE_SIGN && supported < network->msc_data->audio_length;
|
||||
++supported) {
|
||||
|
||||
int perm_val = audio_support_to_gsm88(network->msc_data->audio_support[supported]);
|
||||
for (i = 2; i < TLVP_LEN(&tp, GSM0808_IE_CHANNEL_TYPE); ++i) {
|
||||
if ((data[i] & 0x7f) == perm_val) {
|
||||
chan_mode = gsm88_to_chan_mode(perm_val);
|
||||
full_rate = (data[i] & 0x4) == 0;
|
||||
break;
|
||||
} else if ((data[i] & 0x80) == 0x00) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (chan_mode == GSM48_CMODE_SIGN) {
|
||||
LOGP(DMSC, LOGL_ERROR, "No supported audio type found.\n");
|
||||
goto reject;
|
||||
}
|
||||
|
||||
/* map it to a MGCP Endpoint and a RTP port */
|
||||
port = mgcp_timeslot_to_endpoint(multiplex, timeslot);
|
||||
conn->rtp_port = rtp_calculate_port(port,
|
||||
network->msc_data->rtp_base);
|
||||
|
||||
return gsm0808_assign_req(conn->conn, chan_mode, full_rate);
|
||||
|
||||
reject:
|
||||
resp = gsm0808_create_assignment_failure(GSM0808_CAUSE_NO_RADIO_RESOURCE_AVAILABLE, NULL);
|
||||
if (!resp) {
|
||||
LOGP(DMSC, LOGL_ERROR, "Channel allocation failure.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
bsc_queue_for_msc(conn, resp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int bssmap_rcvmsg_udt(struct gsm_network *net,
|
||||
struct msgb *msg, unsigned int length)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (length < 1) {
|
||||
LOGP(DMSC, LOGL_ERROR, "Not enough room: %d\n", length);
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (msg->l4h[0]) {
|
||||
case BSS_MAP_MSG_RESET_ACKNOWLEDGE:
|
||||
ret = bssmap_handle_reset_ack(net, msg, length);
|
||||
break;
|
||||
case BSS_MAP_MSG_PAGING:
|
||||
if (bsc_grace_allow_new_connection(net))
|
||||
ret = bssmap_handle_paging(net, msg, length);
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int bssmap_rcvmsg_dt1(struct osmo_bsc_sccp_con *conn,
|
||||
struct msgb *msg, unsigned int length)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (length < 1) {
|
||||
LOGP(DMSC, LOGL_ERROR, "Not enough room: %d\n", length);
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (msg->l4h[0]) {
|
||||
case BSS_MAP_MSG_CLEAR_CMD:
|
||||
ret = bssmap_handle_clear_command(conn, msg, length);
|
||||
break;
|
||||
case BSS_MAP_MSG_CIPHER_MODE_CMD:
|
||||
ret = bssmap_handle_cipher_mode(conn, msg, length);
|
||||
break;
|
||||
case BSS_MAP_MSG_ASSIGMENT_RQST:
|
||||
ret = bssmap_handle_assignm_req(conn, msg, length);
|
||||
break;
|
||||
default:
|
||||
LOGP(DMSC, LOGL_DEBUG, "Unimplemented msg type: %d\n", msg->l4h[0]);
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int dtap_rcvmsg(struct osmo_bsc_sccp_con *conn,
|
||||
struct msgb *msg, unsigned int length)
|
||||
{
|
||||
struct dtap_header *header;
|
||||
struct msgb *gsm48;
|
||||
uint8_t *data;
|
||||
|
||||
if (!conn->conn) {
|
||||
LOGP(DMSC, LOGL_ERROR, "No subscriber connection available\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
header = (struct dtap_header *) msg->l3h;
|
||||
if (sizeof(*header) >= length) {
|
||||
LOGP(DMSC, LOGL_ERROR, "The DTAP header does not fit. Wanted: %u got: %u\n", sizeof(*header), length);
|
||||
LOGP(DMSC, LOGL_ERROR, "hex: %s\n", hexdump(msg->l3h, length));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (header->length > length - sizeof(*header)) {
|
||||
LOGP(DMSC, LOGL_ERROR, "The DTAP l4 information does not fit: header: %u length: %u\n", header->length, length);
|
||||
LOGP(DMSC, LOGL_ERROR, "hex: %s\n", hexdump(msg->l3h, length));
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOGP(DMSC, LOGL_DEBUG, "DTAP message: SAPI: %u CHAN: %u\n", header->link_id & 0x07, header->link_id & 0xC0);
|
||||
|
||||
/* forward the data */
|
||||
gsm48 = gsm48_msgb_alloc();
|
||||
if (!gsm48) {
|
||||
LOGP(DMSC, LOGL_ERROR, "Allocation of the message failed.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
gsm48->l3h = gsm48->data;
|
||||
data = msgb_put(gsm48, length - sizeof(*header));
|
||||
memcpy(data, msg->l3h + sizeof(*header), length - sizeof(*header));
|
||||
|
||||
/* pass it to the filter for extra actions */
|
||||
bsc_scan_msc_msg(conn->conn, gsm48);
|
||||
return gsm0808_submit_dtap(conn->conn, gsm48, header->link_id, 1);
|
||||
}
|
||||
|
||||
int bsc_handle_udt(struct gsm_network *network,
|
||||
struct bsc_msc_connection *conn,
|
||||
struct msgb *msgb, unsigned int length)
|
||||
{
|
||||
struct bssmap_header *bs;
|
||||
|
||||
LOGP(DMSC, LOGL_DEBUG, "Incoming SCCP message ftom MSC: %s\n",
|
||||
hexdump(msgb->l3h, length));
|
||||
|
||||
if (length < sizeof(*bs)) {
|
||||
LOGP(DMSC, LOGL_ERROR, "The header is too short.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
bs = (struct bssmap_header *) msgb->l3h;
|
||||
if (bs->length < length - sizeof(*bs))
|
||||
return -1;
|
||||
|
||||
switch (bs->type) {
|
||||
case BSSAP_MSG_BSS_MANAGEMENT:
|
||||
msgb->l4h = &msgb->l3h[sizeof(*bs)];
|
||||
bssmap_rcvmsg_udt(network, msgb, length - sizeof(*bs));
|
||||
break;
|
||||
default:
|
||||
LOGP(DMSC, LOGL_ERROR, "Unimplemented msg type: %d\n", bs->type);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bsc_handle_dt1(struct osmo_bsc_sccp_con *conn,
|
||||
struct msgb *msg, unsigned int len)
|
||||
{
|
||||
if (len < sizeof(struct bssmap_header)) {
|
||||
LOGP(DMSC, LOGL_ERROR, "The header is too short.\n");
|
||||
}
|
||||
|
||||
switch (msg->l3h[0]) {
|
||||
case BSSAP_MSG_BSS_MANAGEMENT:
|
||||
msg->l4h = &msg->l3h[sizeof(struct bssmap_header)];
|
||||
bssmap_rcvmsg_dt1(conn, msg, len - sizeof(struct bssmap_header));
|
||||
break;
|
||||
case BSSAP_MSG_DTAP:
|
||||
dtap_rcvmsg(conn, msg, len);
|
||||
break;
|
||||
default:
|
||||
LOGP(DMSC, LOGL_DEBUG, "Unimplemented msg type: %d\n", msg->l3h[0]);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
170
openbsc/src/bsc/osmo_bsc_filter.c
Normal file
170
openbsc/src/bsc/osmo_bsc_filter.c
Normal file
@@ -0,0 +1,170 @@
|
||||
/* (C) 2009-2010 by Holger Hans Peter Freyther <zecke@selfish.org>
|
||||
* (C) 2009-2010 by On-Waves
|
||||
* 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 <openbsc/osmo_bsc.h>
|
||||
#include <openbsc/osmo_msc_data.h>
|
||||
#include <openbsc/gsm_04_80.h>
|
||||
#include <openbsc/gsm_subscriber.h>
|
||||
#include <openbsc/debug.h>
|
||||
#include <openbsc/paging.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
static void handle_lu_request(struct gsm_subscriber_connection *conn,
|
||||
struct msgb *msg)
|
||||
{
|
||||
struct gsm48_hdr *gh;
|
||||
struct gsm48_loc_upd_req *lu;
|
||||
struct gsm48_loc_area_id lai;
|
||||
struct gsm_network *net;
|
||||
|
||||
if (msgb_l3len(msg) < sizeof(*gh) + sizeof(*lu)) {
|
||||
LOGP(DMSC, LOGL_ERROR, "LU too small to look at: %u\n", msgb_l3len(msg));
|
||||
return;
|
||||
}
|
||||
|
||||
net = conn->bts->network;
|
||||
|
||||
gh = msgb_l3(msg);
|
||||
lu = (struct gsm48_loc_upd_req *) gh->data;
|
||||
|
||||
gsm48_generate_lai(&lai, net->country_code, net->network_code,
|
||||
conn->bts->location_area_code);
|
||||
|
||||
if (memcmp(&lai, &lu->lai, sizeof(lai)) != 0) {
|
||||
LOGP(DMSC, LOGL_DEBUG, "Marking con for welcome USSD.\n");
|
||||
conn->sccp_con->new_subscriber = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* we will need to stop the paging request */
|
||||
static int handle_page_resp(struct gsm_subscriber_connection *conn, struct msgb *msg)
|
||||
{
|
||||
uint8_t mi_type;
|
||||
char mi_string[GSM48_MI_SIZE];
|
||||
struct gsm48_hdr *gh;
|
||||
struct gsm48_pag_resp *resp;
|
||||
struct gsm_subscriber *subscr;
|
||||
|
||||
if (msgb_l3len(msg) < sizeof(*gh) + sizeof(*resp)) {
|
||||
LOGP(DMSC, LOGL_ERROR, "PagingResponse too small: %u\n", msgb_l3len(msg));
|
||||
return -1;
|
||||
}
|
||||
|
||||
gh = msgb_l3(msg);
|
||||
resp = (struct gsm48_pag_resp *) &gh->data[0];
|
||||
|
||||
gsm48_paging_extract_mi(resp, msgb_l3len(msg) - sizeof(*gh),
|
||||
mi_string, &mi_type);
|
||||
DEBUGP(DRR, "PAGING RESPONSE: mi_type=0x%02x MI(%s)\n",
|
||||
mi_type, mi_string);
|
||||
|
||||
switch (mi_type) {
|
||||
case GSM_MI_TYPE_TMSI:
|
||||
subscr = subscr_active_by_tmsi(conn->bts->network,
|
||||
tmsi_from_string(mi_string));
|
||||
break;
|
||||
case GSM_MI_TYPE_IMSI:
|
||||
subscr = subscr_active_by_imsi(conn->bts->network, mi_string);
|
||||
break;
|
||||
default:
|
||||
subscr = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!subscr) {
|
||||
LOGP(DMSC, LOGL_ERROR, "Non active subscriber got paged.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
paging_request_stop(conn->bts, subscr, conn, msg);
|
||||
subscr_put(subscr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is used to scan a message for extra functionality of the BSC. This
|
||||
* includes scanning for location updating requests/acceptd and then send
|
||||
* a welcome USSD message to the subscriber.
|
||||
*/
|
||||
int bsc_scan_bts_msg(struct gsm_subscriber_connection *conn, struct msgb *msg)
|
||||
{
|
||||
struct gsm48_hdr *gh = msgb_l3(msg);
|
||||
uint8_t pdisc = gh->proto_discr & 0x0f;
|
||||
uint8_t mtype = gh->msg_type & 0xbf;
|
||||
|
||||
if (pdisc == GSM48_PDISC_MM) {
|
||||
if (mtype == GSM48_MT_MM_LOC_UPD_REQUEST)
|
||||
handle_lu_request(conn, msg);
|
||||
} else if (pdisc == GSM48_PDISC_RR) {
|
||||
if (mtype == GSM48_MT_RR_PAG_RESP)
|
||||
handle_page_resp(conn, msg);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void send_welcome_ussd(struct gsm_subscriber_connection *conn)
|
||||
{
|
||||
struct gsm_network *net;
|
||||
net = conn->bts->network;
|
||||
|
||||
if (!net->msc_data->ussd_welcome_txt)
|
||||
return;
|
||||
|
||||
gsm0480_send_ussdNotify(conn, 1, net->msc_data->ussd_welcome_txt);
|
||||
gsm0480_send_releaseComplete(conn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Messages coming back from the MSC.
|
||||
*/
|
||||
int bsc_scan_msc_msg(struct gsm_subscriber_connection *conn, struct msgb *msg)
|
||||
{
|
||||
struct gsm_network *net;
|
||||
struct gsm48_loc_area_id *lai;
|
||||
struct gsm48_hdr *gh;
|
||||
uint8_t mtype;
|
||||
|
||||
if (msgb_l3len(msg) < sizeof(*gh)) {
|
||||
LOGP(DMSC, LOGL_ERROR, "GSM48 header does not fit.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
gh = (struct gsm48_hdr *) msgb_l3(msg);
|
||||
mtype = gh->msg_type & 0xbf;
|
||||
net = conn->bts->network;
|
||||
|
||||
if (mtype == GSM48_MT_MM_LOC_UPD_ACCEPT) {
|
||||
if (net->msc_data->core_ncc != -1 ||
|
||||
net->msc_data->core_mcc != -1) {
|
||||
if (msgb_l3len(msg) >= sizeof(*gh) + sizeof(*lai)) {
|
||||
lai = (struct gsm48_loc_area_id *) &gh->data[0];
|
||||
gsm48_generate_lai(lai, net->country_code,
|
||||
net->network_code,
|
||||
conn->bts->location_area_code);
|
||||
}
|
||||
}
|
||||
|
||||
if (conn->sccp_con->new_subscriber)
|
||||
send_welcome_ussd(conn);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -4,18 +4,17 @@
|
||||
* All Rights Reserved
|
||||
*
|
||||
* 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 2 of the License, or
|
||||
* 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.
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -69,7 +68,7 @@ static int handle_grace(struct gsm_network *network)
|
||||
struct gsm_bts *bts;
|
||||
struct gsm_bts_trx *trx;
|
||||
|
||||
if (!network->msc_data->ussd_grace_txt)
|
||||
if (!network->msc_data->mid_call_txt)
|
||||
return 0;
|
||||
|
||||
llist_for_each_entry(bts, &network->bts_list, list) {
|
||||
@@ -78,7 +77,7 @@ static int handle_grace(struct gsm_network *network)
|
||||
struct gsm_bts_trx_ts *ts = &trx->ts[ts_nr];
|
||||
for (lchan_nr = 0; lchan_nr < TS_MAX_LCHAN; ++lchan_nr) {
|
||||
handle_sub(&ts->lchan[lchan_nr],
|
||||
network->msc_data->ussd_grace_txt);
|
||||
network->msc_data->mid_call_txt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,18 +4,17 @@
|
||||
* All Rights Reserved
|
||||
*
|
||||
* 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 2 of the License, or
|
||||
* 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.
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -51,8 +50,7 @@ static const char *rf_ctl = NULL;
|
||||
extern const char *openbsc_copyright;
|
||||
static int daemonize = 0;
|
||||
|
||||
extern void bsc_vty_init(void);
|
||||
extern int bsc_bootstrap_network(int (*layer4)(struct gsm_network *, int, void *), const char *cfg_file);
|
||||
extern int bsc_bootstrap_network(int (*layer4)(struct gsm_network *, struct msgb *), const char *cfg_file);
|
||||
|
||||
static void print_usage()
|
||||
{
|
||||
@@ -140,7 +138,7 @@ extern int bts_model_nanobts_init(void);
|
||||
extern enum node_type bsc_vty_go_parent(struct vty *vty);
|
||||
|
||||
static struct vty_app_info vty_info = {
|
||||
.name = "OpenBSC Osmo BSC",
|
||||
.name = "OsmoBSC",
|
||||
.version = PACKAGE_VERSION,
|
||||
.go_parent_cb = bsc_vty_go_parent,
|
||||
.is_config_node = bsc_vty_is_config_node,
|
||||
@@ -231,6 +229,16 @@ int main(int argc, char **argv)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (osmo_bsc_sccp_init(bsc_gsmnet) != 0) {
|
||||
LOGP(DNM, LOGL_ERROR, "Failed to register SCCP.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (osmo_bsc_audio_init(bsc_gsmnet) != 0) {
|
||||
LOGP(DMSC, LOGL_ERROR, "Failed to register audio support.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
signal(SIGINT, &signal_handler);
|
||||
signal(SIGABRT, &signal_handler);
|
||||
signal(SIGUSR1, &signal_handler);
|
||||
|
||||
@@ -6,18 +6,17 @@
|
||||
* All Rights Reserved
|
||||
*
|
||||
* 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 2 of the License, or
|
||||
* 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.
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -68,7 +67,7 @@ static int mgcp_do_read(struct bsc_fd *fd)
|
||||
}
|
||||
|
||||
mgcp->l2h = msgb_put(mgcp, ret);
|
||||
msc_queue_write(data->msc_con, mgcp, IPAC_PROTO_MGCP);
|
||||
msc_queue_write(data->msc_con, mgcp, IPAC_PROTO_MGCP_OLD);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -175,12 +174,12 @@ int msc_queue_write(struct bsc_msc_connection *conn, struct msgb *msg, int proto
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int msc_sccp_do_write(struct bsc_fd *fd, struct msgb *msg)
|
||||
static int msc_alink_do_write(struct bsc_fd *fd, struct msgb *msg)
|
||||
{
|
||||
int ret;
|
||||
|
||||
LOGP(DMSC, LOGL_DEBUG, "Sending SCCP to MSC: %u\n", msgb_l2len(msg));
|
||||
LOGP(DMI, LOGL_DEBUG, "MSC TX %s\n", hexdump(msg->l2h, msgb_l2len(msg)));
|
||||
LOGP(DMI, LOGL_DEBUG, "MSC TX %s\n", hexdump(msg->data, msg->len));
|
||||
|
||||
ret = write(fd->fd, msg->data, msg->len);
|
||||
if (ret < msg->len)
|
||||
@@ -194,8 +193,7 @@ static int ipaccess_a_fd_cb(struct bsc_fd *bfd)
|
||||
int error;
|
||||
struct msgb *msg = ipaccess_read_msg(bfd, &error);
|
||||
struct ipaccess_head *hh;
|
||||
struct gsm_network *net = (struct gsm_network *) bfd->data;
|
||||
struct osmo_msc_data *data = net->msc_data;
|
||||
struct osmo_msc_data *data = (struct osmo_msc_data *) bfd->data;
|
||||
|
||||
if (!msg) {
|
||||
if (error == 0) {
|
||||
@@ -225,7 +223,7 @@ static int ipaccess_a_fd_cb(struct bsc_fd *bfd)
|
||||
}
|
||||
} else if (hh->proto == IPAC_PROTO_SCCP) {
|
||||
sccp_system_incoming(msg);
|
||||
} else if (hh->proto == IPAC_PROTO_MGCP) {
|
||||
} else if (hh->proto == IPAC_PROTO_MGCP_OLD) {
|
||||
mgcp_forward(data, msg);
|
||||
}
|
||||
|
||||
@@ -283,7 +281,7 @@ static void msc_connection_connected(struct bsc_msc_connection *con)
|
||||
LOGP(DMSC, LOGL_ERROR, "Failed to set TCP_NODELAY: %s\n", strerror(errno));
|
||||
|
||||
data = (struct osmo_msc_data *) con->write_queue.bfd.data;
|
||||
msc_ping_timeout_cb(con);
|
||||
msc_ping_timeout_cb(data);
|
||||
|
||||
sig.data = data;
|
||||
dispatch_signal(SS_MSC, S_MSC_CONNECTED, &sig);
|
||||
@@ -363,7 +361,7 @@ int osmo_bsc_msc_init(struct gsm_network *network)
|
||||
data->msc_con->connection_loss = msc_connection_was_lost;
|
||||
data->msc_con->connected = msc_connection_connected;
|
||||
data->msc_con->write_queue.read_cb = ipaccess_a_fd_cb;
|
||||
data->msc_con->write_queue.write_cb = msc_sccp_do_write;
|
||||
data->msc_con->write_queue.write_cb = msc_alink_do_write;
|
||||
bsc_msc_connect(data->msc_con);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -6,18 +6,17 @@
|
||||
* All Rights Reserved
|
||||
*
|
||||
* 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 2 of the License, or
|
||||
* 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.
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -25,6 +24,7 @@
|
||||
#include <openbsc/debug.h>
|
||||
#include <openbsc/gsm_data.h>
|
||||
#include <openbsc/signal.h>
|
||||
#include <openbsc/osmo_msc_data.h>
|
||||
|
||||
#include <osmocore/talloc.h>
|
||||
#include <osmocore/protocol/gsm_12_21.h>
|
||||
@@ -38,7 +38,8 @@
|
||||
#define RF_CMD_QUERY '?'
|
||||
#define RF_CMD_OFF '0'
|
||||
#define RF_CMD_ON '1'
|
||||
#define RF_CMD_GRACE 'g'
|
||||
#define RF_CMD_D_OFF 'd'
|
||||
#define RF_CMD_ON_G 'g'
|
||||
|
||||
static int lock_each_trx(struct gsm_network *net, int lock)
|
||||
{
|
||||
@@ -54,25 +55,9 @@ static int lock_each_trx(struct gsm_network *net, int lock)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send a '1' when one TRX is online, otherwise send 0
|
||||
*/
|
||||
static void handle_query(struct osmo_bsc_rf_conn *conn)
|
||||
static void send_resp(struct osmo_bsc_rf_conn *conn, char send)
|
||||
{
|
||||
struct msgb *msg;
|
||||
struct gsm_bts *bts;
|
||||
char send = RF_CMD_OFF;
|
||||
|
||||
llist_for_each_entry(bts, &conn->rf->gsm_network->bts_list, list) {
|
||||
struct gsm_bts_trx *trx;
|
||||
llist_for_each_entry(trx, &bts->trx_list, list) {
|
||||
if (trx->nm_state.availability == NM_AVSTATE_OK &&
|
||||
trx->nm_state.operational != NM_STATE_LOCKED) {
|
||||
send = RF_CMD_ON;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
msg = msgb_alloc(10, "RF Query");
|
||||
if (!msg) {
|
||||
@@ -92,15 +77,122 @@ static void handle_query(struct osmo_bsc_rf_conn *conn)
|
||||
return;
|
||||
}
|
||||
|
||||
static void send_signal(struct osmo_bsc_rf_conn *conn, int val)
|
||||
|
||||
/*
|
||||
* Send a
|
||||
* 'g' when we are in grace mode
|
||||
* '1' when one TRX is online,
|
||||
* '0' otherwise
|
||||
*/
|
||||
static void handle_query(struct osmo_bsc_rf_conn *conn)
|
||||
{
|
||||
struct gsm_bts *bts;
|
||||
char send = RF_CMD_OFF;
|
||||
|
||||
if (conn->rf->policy == S_RF_GRACE)
|
||||
return send_resp(conn, RF_CMD_ON_G);
|
||||
|
||||
llist_for_each_entry(bts, &conn->rf->gsm_network->bts_list, list) {
|
||||
struct gsm_bts_trx *trx;
|
||||
llist_for_each_entry(trx, &bts->trx_list, list) {
|
||||
if (trx->nm_state.availability == NM_AVSTATE_OK &&
|
||||
trx->nm_state.operational != NM_STATE_LOCKED) {
|
||||
send = RF_CMD_ON;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
send_resp(conn, send);
|
||||
}
|
||||
|
||||
static void rf_check_cb(void *_data)
|
||||
{
|
||||
struct gsm_bts *bts;
|
||||
struct osmo_bsc_rf *rf = _data;
|
||||
|
||||
llist_for_each_entry(bts, &rf->gsm_network->bts_list, list) {
|
||||
struct gsm_bts_trx *trx;
|
||||
|
||||
/* don't bother to check a booting or missing BTS */
|
||||
if (!bts->oml_link || !is_ipaccess_bts(bts))
|
||||
continue;
|
||||
|
||||
llist_for_each_entry(trx, &bts->trx_list, list) {
|
||||
if (trx->nm_state.availability != NM_AVSTATE_OK ||
|
||||
trx->nm_state.operational != NM_OPSTATE_ENABLED ||
|
||||
trx->nm_state.administrative != NM_STATE_UNLOCKED) {
|
||||
LOGP(DNM, LOGL_ERROR, "RF activation failed. Starting again.\n");
|
||||
ipaccess_drop_oml(bts);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void send_signal(struct osmo_bsc_rf *rf, int val)
|
||||
{
|
||||
struct rf_signal_data sig;
|
||||
sig.net = conn->rf->gsm_network;
|
||||
sig.net = rf->gsm_network;
|
||||
|
||||
conn->rf->policy = val;
|
||||
rf->policy = val;
|
||||
dispatch_signal(SS_RF, val, &sig);
|
||||
}
|
||||
|
||||
static int switch_rf_off(struct osmo_bsc_rf *rf)
|
||||
{
|
||||
lock_each_trx(rf->gsm_network, 1);
|
||||
send_signal(rf, S_RF_OFF);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void grace_timeout(void *_data)
|
||||
{
|
||||
struct osmo_bsc_rf *rf = (struct osmo_bsc_rf *) _data;
|
||||
|
||||
LOGP(DINP, LOGL_NOTICE, "Grace timeout. Disabling the TRX.\n");
|
||||
switch_rf_off(rf);
|
||||
}
|
||||
|
||||
static int enter_grace(struct osmo_bsc_rf *rf)
|
||||
{
|
||||
rf->grace_timeout.cb = grace_timeout;
|
||||
rf->grace_timeout.data = rf;
|
||||
bsc_schedule_timer(&rf->grace_timeout, rf->gsm_network->msc_data->mid_call_timeout, 0);
|
||||
LOGP(DINP, LOGL_NOTICE, "Going to switch RF off in %d seconds.\n",
|
||||
rf->gsm_network->msc_data->mid_call_timeout);
|
||||
|
||||
send_signal(rf, S_RF_GRACE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rf_delay_cmd_cb(void *data)
|
||||
{
|
||||
struct osmo_bsc_rf *rf = data;
|
||||
|
||||
switch (rf->last_request) {
|
||||
case RF_CMD_D_OFF:
|
||||
rf->last_state_command = "RF Direct Off";
|
||||
bsc_del_timer(&rf->rf_check);
|
||||
bsc_del_timer(&rf->grace_timeout);
|
||||
switch_rf_off(rf);
|
||||
break;
|
||||
case RF_CMD_ON:
|
||||
rf->last_state_command = "RF Direct On";
|
||||
bsc_del_timer(&rf->grace_timeout);
|
||||
lock_each_trx(rf->gsm_network, 0);
|
||||
send_signal(rf, S_RF_ON);
|
||||
bsc_schedule_timer(&rf->rf_check, 3, 0);
|
||||
break;
|
||||
case RF_CMD_OFF:
|
||||
rf->last_state_command = "RF Scheduled Off";
|
||||
bsc_del_timer(&rf->rf_check);
|
||||
enter_grace(rf);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int rf_read_cmd(struct bsc_fd *fd)
|
||||
{
|
||||
struct osmo_bsc_rf_conn *conn = fd->data;
|
||||
@@ -121,18 +213,15 @@ static int rf_read_cmd(struct bsc_fd *fd)
|
||||
case RF_CMD_QUERY:
|
||||
handle_query(conn);
|
||||
break;
|
||||
case RF_CMD_OFF:
|
||||
lock_each_trx(conn->rf->gsm_network, 1);
|
||||
send_signal(conn, S_RF_OFF);
|
||||
break;
|
||||
case RF_CMD_D_OFF:
|
||||
case RF_CMD_ON:
|
||||
lock_each_trx(conn->rf->gsm_network, 0);
|
||||
send_signal(conn, S_RF_ON);
|
||||
break;
|
||||
case RF_CMD_GRACE:
|
||||
send_signal(conn, S_RF_GRACE);
|
||||
case RF_CMD_OFF:
|
||||
conn->rf->last_request = buf[0];
|
||||
if (!bsc_timer_pending(&conn->rf->delay_cmd))
|
||||
bsc_schedule_timer(&conn->rf->delay_cmd, 1, 0);
|
||||
break;
|
||||
default:
|
||||
conn->rf->last_state_command = "Unknown command";
|
||||
LOGP(DINP, LOGL_ERROR, "Unknown command %d\n", buf[0]);
|
||||
break;
|
||||
}
|
||||
@@ -260,6 +349,15 @@ struct osmo_bsc_rf *osmo_bsc_rf_create(const char *path, struct gsm_network *net
|
||||
|
||||
rf->gsm_network = net;
|
||||
rf->policy = S_RF_ON;
|
||||
rf->last_state_command = "";
|
||||
|
||||
/* check the rf state */
|
||||
rf->rf_check.data = rf;
|
||||
rf->rf_check.cb = rf_check_cb;
|
||||
|
||||
/* delay cmd handling */
|
||||
rf->delay_cmd.data = rf;
|
||||
rf->delay_cmd.cb = rf_delay_cmd_cb;
|
||||
|
||||
return rf;
|
||||
}
|
||||
|
||||
288
openbsc/src/bsc/osmo_bsc_sccp.c
Normal file
288
openbsc/src/bsc/osmo_bsc_sccp.c
Normal file
@@ -0,0 +1,288 @@
|
||||
/* Interaction with the SCCP subsystem */
|
||||
/*
|
||||
* (C) 2009-2010 by Holger Hans Peter Freyther <zecke@selfish.org>
|
||||
* (C) 2009-2010 by On-Waves
|
||||
* 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 <openbsc/gsm_data.h>
|
||||
#include <openbsc/osmo_bsc.h>
|
||||
#include <openbsc/osmo_bsc_grace.h>
|
||||
#include <openbsc/osmo_msc_data.h>
|
||||
#include <openbsc/debug.h>
|
||||
#include <openbsc/ipaccess.h>
|
||||
#include <openbsc/signal.h>
|
||||
|
||||
#include <osmocore/gsm0808.h>
|
||||
#include <osmocore/talloc.h>
|
||||
#include <osmocore/protocol/gsm_08_08.h>
|
||||
|
||||
#include <osmocom/sccp/sccp.h>
|
||||
|
||||
/* SCCP helper */
|
||||
#define SCCP_IT_TIMER 60
|
||||
|
||||
static LLIST_HEAD(active_connections);
|
||||
|
||||
static void free_queued(struct osmo_bsc_sccp_con *conn)
|
||||
{
|
||||
struct msgb *msg;
|
||||
|
||||
while (!llist_empty(&conn->sccp_queue)) {
|
||||
/* this is not allowed to fail */
|
||||
msg = msgb_dequeue(&conn->sccp_queue);
|
||||
msgb_free(msg);
|
||||
}
|
||||
|
||||
conn->sccp_queue_size = 0;
|
||||
}
|
||||
|
||||
static void send_queued(struct osmo_bsc_sccp_con *conn)
|
||||
{
|
||||
struct msgb *msg;
|
||||
|
||||
while (!llist_empty(&conn->sccp_queue)) {
|
||||
/* this is not allowed to fail */
|
||||
msg = msgb_dequeue(&conn->sccp_queue);
|
||||
sccp_connection_write(conn->sccp, msg);
|
||||
msgb_free(msg);
|
||||
conn->sccp_queue_size -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void msc_outgoing_sccp_data(struct sccp_connection *conn,
|
||||
struct msgb *msg, unsigned int len)
|
||||
{
|
||||
struct osmo_bsc_sccp_con *bsc_con =
|
||||
(struct osmo_bsc_sccp_con *) conn->data_ctx;
|
||||
|
||||
bsc_handle_dt1(bsc_con, msg, len);
|
||||
}
|
||||
|
||||
static void msc_outgoing_sccp_state(struct sccp_connection *conn, int old_state)
|
||||
{
|
||||
struct osmo_bsc_sccp_con *con_data;
|
||||
|
||||
if (conn->connection_state >= SCCP_CONNECTION_STATE_RELEASE_COMPLETE) {
|
||||
con_data = (struct osmo_bsc_sccp_con *) conn->data_ctx;
|
||||
if(con_data->conn) {
|
||||
LOGP(DMSC, LOGL_ERROR,
|
||||
"ERROR: The lchan is still associated\n.");
|
||||
gsm0808_clear(con_data->conn);
|
||||
subscr_con_free(con_data->conn);
|
||||
con_data->conn = NULL;
|
||||
}
|
||||
|
||||
con_data->sccp = NULL;
|
||||
free_queued(con_data);
|
||||
sccp_connection_free(conn);
|
||||
bsc_delete_connection(con_data);
|
||||
} else if (conn->connection_state == SCCP_CONNECTION_STATE_ESTABLISHED) {
|
||||
LOGP(DMSC, LOGL_DEBUG, "Connection established: %p\n", conn);
|
||||
con_data = (struct osmo_bsc_sccp_con *) conn->data_ctx;
|
||||
|
||||
bsc_del_timer(&con_data->sccp_cc_timeout);
|
||||
bsc_schedule_timer(&con_data->sccp_it_timeout, SCCP_IT_TIMER, 0);
|
||||
|
||||
send_queued(con_data);
|
||||
}
|
||||
}
|
||||
|
||||
static void bsc_sccp_force_free(struct osmo_bsc_sccp_con *data)
|
||||
{
|
||||
if (data->conn) {
|
||||
gsm0808_clear(data->conn);
|
||||
subscr_con_free(data->conn);
|
||||
data->conn = NULL;
|
||||
}
|
||||
|
||||
free_queued(data);
|
||||
sccp_connection_force_free(data->sccp);
|
||||
data->sccp = NULL;
|
||||
bsc_delete_connection(data);
|
||||
}
|
||||
|
||||
static void sccp_it_timeout(void *_data)
|
||||
{
|
||||
struct osmo_bsc_sccp_con *data =
|
||||
(struct osmo_bsc_sccp_con *) _data;
|
||||
|
||||
sccp_connection_send_it(data->sccp);
|
||||
bsc_schedule_timer(&data->sccp_it_timeout, SCCP_IT_TIMER, 0);
|
||||
}
|
||||
|
||||
static void sccp_cc_timeout(void *_data)
|
||||
{
|
||||
struct osmo_bsc_sccp_con *data =
|
||||
(struct osmo_bsc_sccp_con *) _data;
|
||||
|
||||
if (data->sccp->connection_state >= SCCP_CONNECTION_STATE_ESTABLISHED)
|
||||
return;
|
||||
|
||||
LOGP(DMSC, LOGL_ERROR, "The connection was never established.\n");
|
||||
bsc_sccp_force_free(data);
|
||||
}
|
||||
|
||||
static void msc_sccp_write_ipa(struct sccp_connection *conn, struct msgb *msg, void *data)
|
||||
{
|
||||
struct gsm_network *net = (struct gsm_network *) data;
|
||||
msc_queue_write(net->msc_data->msc_con, msg, IPAC_PROTO_SCCP);
|
||||
}
|
||||
|
||||
static int msc_sccp_accept(struct sccp_connection *connection, void *data)
|
||||
{
|
||||
LOGP(DMSC, LOGL_DEBUG, "Rejecting incoming SCCP connection.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int msc_sccp_read(struct msgb *msgb, unsigned int length, void *data)
|
||||
{
|
||||
struct gsm_network *net = (struct gsm_network *) data;
|
||||
return bsc_handle_udt(net, net->msc_data->msc_con, msgb, length);
|
||||
}
|
||||
|
||||
int bsc_queue_for_msc(struct osmo_bsc_sccp_con *conn, struct msgb *msg)
|
||||
{
|
||||
struct sccp_connection *sccp = conn->sccp;
|
||||
|
||||
if (sccp->connection_state > SCCP_CONNECTION_STATE_ESTABLISHED) {
|
||||
LOGP(DMSC, LOGL_ERROR, "Connection closing, dropping packet on: %p\n", sccp);
|
||||
msgb_free(msg);
|
||||
} else if (sccp->connection_state == SCCP_CONNECTION_STATE_ESTABLISHED
|
||||
&& conn->sccp_queue_size == 0) {
|
||||
sccp_connection_write(sccp, msg);
|
||||
msgb_free(msg);
|
||||
} else if (conn->sccp_queue_size > 10) {
|
||||
LOGP(DMSC, LOGL_ERROR, "Connection closing, dropping packet on: %p\n", sccp);
|
||||
msgb_free(msg);
|
||||
} else {
|
||||
LOGP(DMSC, LOGL_DEBUG, "Queueing packet on %p. Queue size: %d\n", sccp, conn->sccp_queue_size);
|
||||
conn->sccp_queue_size += 1;
|
||||
msgb_enqueue(&conn->sccp_queue, msg);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bsc_create_new_connection(struct gsm_subscriber_connection *conn)
|
||||
{
|
||||
struct gsm_network *net;
|
||||
struct osmo_bsc_sccp_con *bsc_con;
|
||||
struct sccp_connection *sccp;
|
||||
|
||||
net = conn->bts->network;
|
||||
if (!net->msc_data->msc_con->is_authenticated) {
|
||||
LOGP(DMSC, LOGL_ERROR, "Not connected to a MSC. Not forwarding data.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!bsc_grace_allow_new_connection(net)) {
|
||||
LOGP(DMSC, LOGL_NOTICE, "BSC in grace period. No new connections.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
sccp = sccp_connection_socket();
|
||||
if (!sccp) {
|
||||
LOGP(DMSC, LOGL_ERROR, "Failed to allocate memory.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
bsc_con = talloc_zero(conn->bts, struct osmo_bsc_sccp_con);
|
||||
if (!bsc_con) {
|
||||
LOGP(DMSC, LOGL_ERROR, "Failed to allocate.\n");
|
||||
sccp_connection_free(sccp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* callbacks */
|
||||
sccp->state_cb = msc_outgoing_sccp_state;
|
||||
sccp->data_cb = msc_outgoing_sccp_data;
|
||||
sccp->data_ctx = bsc_con;
|
||||
|
||||
/* prepare the timers */
|
||||
bsc_con->sccp_it_timeout.cb = sccp_it_timeout;
|
||||
bsc_con->sccp_it_timeout.data = bsc_con;
|
||||
bsc_con->sccp_cc_timeout.cb = sccp_cc_timeout;
|
||||
bsc_con->sccp_cc_timeout.data = bsc_con;
|
||||
|
||||
INIT_LLIST_HEAD(&bsc_con->sccp_queue);
|
||||
|
||||
bsc_con->sccp = sccp;
|
||||
bsc_con->msc_con = net->msc_data->msc_con;
|
||||
bsc_con->conn = conn;
|
||||
llist_add(&bsc_con->entry, &active_connections);
|
||||
conn->sccp_con = bsc_con;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bsc_open_connection(struct osmo_bsc_sccp_con *conn, struct msgb *msg)
|
||||
{
|
||||
bsc_schedule_timer(&conn->sccp_cc_timeout, 10, 0);
|
||||
sccp_connection_connect(conn->sccp, &sccp_ssn_bssap, msg);
|
||||
msgb_free(msg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bsc_delete_connection(struct osmo_bsc_sccp_con *sccp)
|
||||
{
|
||||
if (!sccp)
|
||||
return 0;
|
||||
|
||||
if (sccp->conn)
|
||||
LOGP(DMSC, LOGL_ERROR, "Should have been cleared.\n");
|
||||
|
||||
llist_del(&sccp->entry);
|
||||
bsc_del_timer(&sccp->sccp_it_timeout);
|
||||
bsc_del_timer(&sccp->sccp_cc_timeout);
|
||||
talloc_free(sccp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bsc_close_connections(struct bsc_msc_connection *msc_con)
|
||||
{
|
||||
struct osmo_bsc_sccp_con *con, *tmp;
|
||||
|
||||
llist_for_each_entry_safe(con, tmp, &active_connections, entry)
|
||||
bsc_sccp_force_free(con);
|
||||
}
|
||||
|
||||
static int handle_msc_signal(unsigned int subsys, unsigned int signal,
|
||||
void *handler_data, void *signal_data)
|
||||
{
|
||||
struct osmo_msc_data *data;
|
||||
|
||||
if (subsys != SS_MSC)
|
||||
return 0;
|
||||
|
||||
data = (struct osmo_msc_data *) signal_data;
|
||||
if (signal == S_MSC_LOST)
|
||||
bsc_close_connections(data->msc_con);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int osmo_bsc_sccp_init(struct gsm_network *gsmnet)
|
||||
{
|
||||
sccp_set_log_area(DSCCP);
|
||||
sccp_system_init(msc_sccp_write_ipa, gsmnet);
|
||||
sccp_connection_set_incoming(&sccp_ssn_bssap, msc_sccp_accept, NULL);
|
||||
sccp_set_read(&sccp_ssn_bssap, msc_sccp_read, gsmnet);
|
||||
|
||||
register_signal_handler(SS_MSC, handle_msc_signal, gsmnet);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -4,18 +4,17 @@
|
||||
* All Rights Reserved
|
||||
*
|
||||
* 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 2 of the License, or
|
||||
* 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.
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -25,6 +24,9 @@
|
||||
|
||||
#include <osmocore/talloc.h>
|
||||
|
||||
|
||||
#define IPA_STR "IP.ACCESS specific\n"
|
||||
|
||||
extern struct gsm_network *bsc_gsmnet;
|
||||
|
||||
static struct osmo_msc_data *osmo_msc_data(struct vty *vty)
|
||||
@@ -54,18 +56,45 @@ static int config_write_msc(struct vty *vty)
|
||||
vty_out(vty, " msc%s", VTY_NEWLINE);
|
||||
if (data->bsc_token)
|
||||
vty_out(vty, " token %s%s", data->bsc_token, VTY_NEWLINE);
|
||||
if (data->core_ncc != -1)
|
||||
vty_out(vty, " core-mobile-network-code %d%s",
|
||||
data->core_ncc, VTY_NEWLINE);
|
||||
if (data->core_mcc != -1)
|
||||
vty_out(vty, " core-mobile-country-code %d%s",
|
||||
data->core_mcc, VTY_NEWLINE);
|
||||
vty_out(vty, " ip.access rtp-base %d%s", data->rtp_base, VTY_NEWLINE);
|
||||
vty_out(vty, " ip %s%s", data->msc_ip, VTY_NEWLINE);
|
||||
vty_out(vty, " port %d%s", data->msc_port, VTY_NEWLINE);
|
||||
vty_out(vty, " ip-dscp %d%s", data->msc_ip_dscp, VTY_NEWLINE);
|
||||
vty_out(vty, " timeout-ping %d%s", data->ping_timeout, VTY_NEWLINE);
|
||||
vty_out(vty, " timeout-pong %d%s", data->pong_timeout, VTY_NEWLINE);
|
||||
if (data->ussd_grace_txt)
|
||||
vty_out(vty, "bsc-grace-text %s%s", data->ussd_grace_txt, VTY_NEWLINE);
|
||||
if (data->mid_call_txt)
|
||||
vty_out(vty, "mid-call-text %s%s", data->mid_call_txt, VTY_NEWLINE);
|
||||
vty_out(vty, " mid-call-timeout %d%s", data->mid_call_timeout, VTY_NEWLINE);
|
||||
if (data->ussd_welcome_txt)
|
||||
vty_out(vty, " bsc-welcome-text %s%s", data->ussd_welcome_txt, VTY_NEWLINE);
|
||||
|
||||
if (data->audio_length != 0) {
|
||||
int i;
|
||||
|
||||
vty_out(vty, " codec_list ");
|
||||
for (i = 0; i < data->audio_length; ++i) {
|
||||
if (i != 0)
|
||||
vty_out(vty, ", ");
|
||||
|
||||
if (data->audio_support[i]->hr)
|
||||
vty_out(vty, "hr%.1u", data->audio_support[i]->ver);
|
||||
else
|
||||
vty_out(vty, "fr%.1u", data->audio_support[i]->ver);
|
||||
}
|
||||
vty_out(vty, "%s", VTY_NEWLINE);
|
||||
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_net_msc_token,
|
||||
DEFUN(cfg_net_bsc_token,
|
||||
cfg_net_bsc_token_cmd,
|
||||
"token TOKEN",
|
||||
"A token for the BSC to be sent to the MSC")
|
||||
@@ -76,6 +105,98 @@ DEFUN(cfg_net_msc_token,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_net_bsc_ncc,
|
||||
cfg_net_bsc_ncc_cmd,
|
||||
"core-mobile-network-code <1-999>",
|
||||
"Use this network code for the backbone\n" "NCC value\n")
|
||||
{
|
||||
struct osmo_msc_data *data = osmo_msc_data(vty);
|
||||
data->core_ncc = atoi(argv[0]);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_net_bsc_mcc,
|
||||
cfg_net_bsc_mcc_cmd,
|
||||
"core-mobile-country-code <1-999>",
|
||||
"Use this country code for the backbone\n" "MCC value\n")
|
||||
{
|
||||
struct osmo_msc_data *data = osmo_msc_data(vty);
|
||||
data->core_mcc = atoi(argv[0]);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_net_bsc_rtp_base,
|
||||
cfg_net_bsc_rtp_base_cmd,
|
||||
"ip.access rtp-base <1-65000>",
|
||||
IPA_STR
|
||||
"Set the rtp-base port for the RTP stream\n"
|
||||
"Port number\n")
|
||||
{
|
||||
struct osmo_msc_data *data = osmo_msc_data(vty);
|
||||
data->rtp_base = atoi(argv[0]);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_net_bsc_codec_list,
|
||||
cfg_net_bsc_codec_list_cmd,
|
||||
"codec-list .LIST",
|
||||
"Set the allowed audio codecs\n"
|
||||
"List of audio codecs\n")
|
||||
{
|
||||
struct osmo_msc_data *data = osmo_msc_data(vty);
|
||||
int saw_fr, saw_hr;
|
||||
int i;
|
||||
|
||||
saw_fr = saw_hr = 0;
|
||||
|
||||
/* free the old list... if it exists */
|
||||
if (data->audio_support) {
|
||||
talloc_free(data->audio_support);
|
||||
data->audio_support = NULL;
|
||||
data->audio_length = 0;
|
||||
}
|
||||
|
||||
/* create a new array */
|
||||
data->audio_support =
|
||||
talloc_zero_array(data, struct gsm_audio_support *, argc);
|
||||
data->audio_length = argc;
|
||||
|
||||
for (i = 0; i < argc; ++i) {
|
||||
/* check for hrX or frX */
|
||||
if (strlen(argv[i]) != 3
|
||||
|| argv[i][1] != 'r'
|
||||
|| (argv[i][0] != 'h' && argv[i][0] != 'f')
|
||||
|| argv[i][2] < 0x30
|
||||
|| argv[i][2] > 0x39)
|
||||
goto error;
|
||||
|
||||
data->audio_support[i] = talloc_zero(data->audio_support,
|
||||
struct gsm_audio_support);
|
||||
data->audio_support[i]->ver = atoi(argv[i] + 2);
|
||||
|
||||
if (strncmp("hr", argv[i], 2) == 0) {
|
||||
data->audio_support[i]->hr = 1;
|
||||
saw_hr = 1;
|
||||
} else if (strncmp("fr", argv[i], 2) == 0) {
|
||||
data->audio_support[i]->hr = 0;
|
||||
saw_fr = 1;
|
||||
}
|
||||
|
||||
if (saw_hr && saw_fr) {
|
||||
vty_out(vty, "Can not have full-rate and half-rate codec.%s",
|
||||
VTY_NEWLINE);
|
||||
return CMD_ERR_INCOMPLETE;
|
||||
}
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
|
||||
error:
|
||||
vty_out(vty, "Codec name must be hrX or frX. Was '%s'%s",
|
||||
argv[i], VTY_NEWLINE);
|
||||
return CMD_ERR_INCOMPLETE;
|
||||
}
|
||||
|
||||
DEFUN(cfg_net_msc_ip,
|
||||
cfg_net_msc_ip_cmd,
|
||||
"ip A.B.C.D", "Set the MSC/MUX IP address.")
|
||||
@@ -127,33 +248,64 @@ DEFUN(cfg_net_msc_pong_time,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_net_msc_grace_ussd,
|
||||
cfg_net_msc_grace_ussd_cmd,
|
||||
"bsc-grace-text .TEXT",
|
||||
DEFUN(cfg_net_msc_mid_call_text,
|
||||
cfg_net_msc_mid_call_text_cmd,
|
||||
"mid-call-text .TEXT",
|
||||
"Set the USSD notifcation to be send.\n" "Text to be sent\n")
|
||||
{
|
||||
struct osmo_msc_data *data = osmo_msc_data(vty);
|
||||
char *txt = argv_concat(argv, argc, 1);
|
||||
char *txt = argv_concat(argv, argc, 0);
|
||||
if (!txt)
|
||||
return CMD_WARNING;
|
||||
|
||||
bsc_replace_string(data, &data->ussd_grace_txt, txt);
|
||||
bsc_replace_string(data, &data->mid_call_txt, txt);
|
||||
talloc_free(txt);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_net_msc_mid_call_timeout,
|
||||
cfg_net_msc_mid_call_timeout_cmd,
|
||||
"mid-call-timeout NR",
|
||||
"Switch from Grace to Off in NR seconds.\n" "Timeout in seconds\n")
|
||||
{
|
||||
struct osmo_msc_data *data = osmo_msc_data(vty);
|
||||
data->mid_call_timeout = atoi(argv[0]);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_net_msc_welcome_ussd,
|
||||
cfg_net_msc_welcome_ussd_cmd,
|
||||
"bsc-welcome-text .TEXT",
|
||||
"Set the USSD notification to be sent.\n" "Text to be sent\n")
|
||||
{
|
||||
struct osmo_msc_data *data = osmo_msc_data(vty);
|
||||
char *str = argv_concat(argv, argc, 0);
|
||||
if (!str)
|
||||
return CMD_WARNING;
|
||||
|
||||
bsc_replace_string(data, &data->ussd_welcome_txt, str);
|
||||
talloc_free(str);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
int bsc_vty_init_extra(void)
|
||||
{
|
||||
install_element(GSMNET_NODE, &cfg_net_msc_cmd);
|
||||
install_node(&msc_node, config_write_msc);
|
||||
install_default(MSC_NODE);
|
||||
install_element(MSC_NODE, &cfg_net_bsc_token_cmd);
|
||||
install_element(MSC_NODE, &cfg_net_bsc_ncc_cmd);
|
||||
install_element(MSC_NODE, &cfg_net_bsc_mcc_cmd);
|
||||
install_element(MSC_NODE, &cfg_net_bsc_rtp_base_cmd);
|
||||
install_element(MSC_NODE, &cfg_net_bsc_codec_list_cmd);
|
||||
install_element(MSC_NODE, &cfg_net_msc_ip_cmd);
|
||||
install_element(MSC_NODE, &cfg_net_msc_port_cmd);
|
||||
install_element(MSC_NODE, &cfg_net_msc_prio_cmd);
|
||||
install_element(MSC_NODE, &cfg_net_msc_ping_time_cmd);
|
||||
install_element(MSC_NODE, &cfg_net_msc_pong_time_cmd);
|
||||
install_element(MSC_NODE, &cfg_net_msc_grace_ussd_cmd);
|
||||
install_element(MSC_NODE, &cfg_net_msc_mid_call_text_cmd);
|
||||
install_element(MSC_NODE, &cfg_net_msc_mid_call_timeout_cmd);
|
||||
install_element(MSC_NODE, &cfg_net_msc_welcome_ussd_cmd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -7,36 +7,202 @@
|
||||
* All Rights Reserved
|
||||
*
|
||||
* 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 2 of the License, or
|
||||
* 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.
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* 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 <openbsc/bsc_api.h>
|
||||
#include <openbsc/bsc_rll.h>
|
||||
#include <openbsc/gsm_data.h>
|
||||
#include <openbsc/gsm_subscriber.h>
|
||||
#include <openbsc/signal.h>
|
||||
#include <openbsc/abis_rsl.h>
|
||||
#include <openbsc/chan_alloc.h>
|
||||
#include <openbsc/handover.h>
|
||||
#include <openbsc/debug.h>
|
||||
#include <openbsc/gsm_04_08.h>
|
||||
|
||||
#include <osmocore/protocol/gsm_08_08.h>
|
||||
|
||||
#include <osmocore/talloc.h>
|
||||
|
||||
#define GSM0808_T10_VALUE 6, 0
|
||||
|
||||
static LLIST_HEAD(sub_connections);
|
||||
|
||||
static void rll_ind_cb(struct gsm_lchan *, uint8_t, void *, enum bsc_rllr_ind);
|
||||
static void send_sapi_reject(struct gsm_subscriber_connection *conn, int link_id);
|
||||
static void handle_release(struct gsm_subscriber_connection *conn, struct bsc_api *bsc, struct gsm_lchan *lchan);
|
||||
static void handle_chan_ack(struct gsm_subscriber_connection *conn, struct bsc_api *bsc, struct gsm_lchan *lchan);
|
||||
static void handle_chan_nack(struct gsm_subscriber_connection *conn, struct bsc_api *bsc, struct gsm_lchan *lchan);
|
||||
|
||||
/* GSM 08.08 3.2.2.33 */
|
||||
static u_int8_t lchan_to_chosen_channel(struct gsm_lchan *lchan)
|
||||
{
|
||||
u_int8_t channel_mode = 0, channel = 0;
|
||||
|
||||
switch (lchan->tch_mode) {
|
||||
case GSM48_CMODE_SPEECH_V1:
|
||||
case GSM48_CMODE_SPEECH_EFR:
|
||||
case GSM48_CMODE_SPEECH_AMR:
|
||||
channel_mode = 0x9;
|
||||
break;
|
||||
case GSM48_CMODE_SIGN:
|
||||
channel_mode = 0x8;
|
||||
break;
|
||||
case GSM48_CMODE_DATA_14k5:
|
||||
channel_mode = 0xe;
|
||||
break;
|
||||
case GSM48_CMODE_DATA_12k0:
|
||||
channel_mode = 0xb;
|
||||
break;
|
||||
case GSM48_CMODE_DATA_6k0:
|
||||
channel_mode = 0xc;
|
||||
break;
|
||||
case GSM48_CMODE_DATA_3k6:
|
||||
channel_mode = 0xd;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (lchan->type) {
|
||||
case GSM_LCHAN_NONE:
|
||||
channel = 0x0;
|
||||
break;
|
||||
case GSM_LCHAN_SDCCH:
|
||||
channel = 0x1;
|
||||
break;
|
||||
case GSM_LCHAN_TCH_F:
|
||||
channel = 0x8;
|
||||
break;
|
||||
case GSM_LCHAN_TCH_H:
|
||||
channel = 0x9;
|
||||
break;
|
||||
case GSM_LCHAN_UNKNOWN:
|
||||
LOGP(DMSC, LOGL_ERROR, "Unknown lchan type: %p\n", lchan);
|
||||
break;
|
||||
}
|
||||
|
||||
return channel_mode << 4 | channel;
|
||||
}
|
||||
|
||||
static u_int8_t chan_mode_to_speech(struct gsm_lchan *lchan)
|
||||
{
|
||||
int mode = 0;
|
||||
|
||||
switch (lchan->tch_mode) {
|
||||
case GSM48_CMODE_SPEECH_V1:
|
||||
mode = 1;
|
||||
break;
|
||||
case GSM48_CMODE_SPEECH_EFR:
|
||||
mode = 0x11;
|
||||
break;
|
||||
case GSM48_CMODE_SPEECH_AMR:
|
||||
mode = 0x21;
|
||||
break;
|
||||
case GSM48_CMODE_SIGN:
|
||||
case GSM48_CMODE_DATA_14k5:
|
||||
case GSM48_CMODE_DATA_12k0:
|
||||
case GSM48_CMODE_DATA_6k0:
|
||||
case GSM48_CMODE_DATA_3k6:
|
||||
default:
|
||||
LOGP(DMSC, LOGL_ERROR, "Using non speech mode: %d\n", mode);
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
|
||||
/* assume to always do AMR HR on any TCH type */
|
||||
if (lchan->type == GSM_LCHAN_TCH_H ||
|
||||
lchan->tch_mode == GSM48_CMODE_SPEECH_AMR)
|
||||
mode |= 0x4;
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
static void assignment_t10_timeout(void *_conn)
|
||||
{
|
||||
struct bsc_api *api;
|
||||
struct gsm_subscriber_connection *conn =
|
||||
(struct gsm_subscriber_connection *) _conn;
|
||||
|
||||
LOGP(DMSC, LOGL_ERROR, "Assigment T10 timeout on %p\n", conn);
|
||||
|
||||
/* normal release on the secondary channel */
|
||||
lchan_release(conn->secondary_lchan, 0, 1);
|
||||
conn->secondary_lchan = NULL;
|
||||
|
||||
/* inform them about the failure */
|
||||
api = conn->bts->network->bsc_api;
|
||||
api->assign_fail(conn, GSM0808_CAUSE_NO_RADIO_RESOURCE_AVAILABLE, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Start a new assignment and make sure that it is completed within T10 either
|
||||
* positively, negatively or by the timeout.
|
||||
*
|
||||
* 1.) allocate a new lchan
|
||||
* 2.) copy the encryption key and other data from the
|
||||
* old to the new channel.
|
||||
* 3.) RSL Channel Activate this channel and wait
|
||||
*
|
||||
* -> Signal handler for the LCHAN
|
||||
* 4.) Send GSM 04.08 assignment command to the MS
|
||||
*
|
||||
* -> Assignment Complete/Assignment Failure
|
||||
* 5.) Release the SDCCH, continue signalling on the new link
|
||||
*/
|
||||
static int handle_new_assignment(struct gsm_subscriber_connection *conn, int chan_mode, int full_rate)
|
||||
{
|
||||
struct gsm_lchan *new_lchan;
|
||||
int chan_type;
|
||||
|
||||
chan_type = full_rate ? GSM_LCHAN_TCH_F : GSM_LCHAN_TCH_H;
|
||||
|
||||
new_lchan = lchan_alloc(conn->bts, chan_type, 0);
|
||||
|
||||
if (!new_lchan) {
|
||||
LOGP(DMSC, LOGL_NOTICE, "No free channel.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* copy old data to the new channel */
|
||||
memcpy(&new_lchan->encr, &conn->lchan->encr, sizeof(new_lchan->encr));
|
||||
new_lchan->ms_power = conn->lchan->ms_power;
|
||||
new_lchan->bs_power = conn->lchan->bs_power;
|
||||
|
||||
/* copy new data to it */
|
||||
new_lchan->tch_mode = chan_mode;
|
||||
new_lchan->rsl_cmode = RSL_CMOD_SPD_SPEECH;
|
||||
|
||||
/* handle AMR correctly */
|
||||
if (chan_mode == GSM48_CMODE_SPEECH_AMR) {
|
||||
new_lchan->mr_conf.ver = 1;
|
||||
new_lchan->mr_conf.icmi = 1;
|
||||
new_lchan->mr_conf.m5_90 = 1;
|
||||
}
|
||||
|
||||
if (rsl_chan_activate_lchan(new_lchan, 0x1, 0, 0) < 0) {
|
||||
LOGP(DHO, LOGL_ERROR, "could not activate channel\n");
|
||||
lchan_free(new_lchan);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* remember that we have the channel */
|
||||
conn->secondary_lchan = new_lchan;
|
||||
new_lchan->conn = conn;
|
||||
|
||||
rsl_lchan_set_state(new_lchan, LCHAN_S_ACT_REQ);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct gsm_subscriber_connection *subscr_con_allocate(struct gsm_lchan *lchan)
|
||||
{
|
||||
@@ -57,9 +223,6 @@ struct gsm_subscriber_connection *subscr_con_allocate(struct gsm_lchan *lchan)
|
||||
/* TODO: move subscriber put here... */
|
||||
void subscr_con_free(struct gsm_subscriber_connection *conn)
|
||||
{
|
||||
struct gsm_lchan *lchan;
|
||||
|
||||
|
||||
if (!conn)
|
||||
return;
|
||||
|
||||
@@ -70,16 +233,23 @@ void subscr_con_free(struct gsm_subscriber_connection *conn)
|
||||
}
|
||||
|
||||
|
||||
if (conn->ho_lchan)
|
||||
if (conn->ho_lchan) {
|
||||
LOGP(DNM, LOGL_ERROR, "The ho_lchan should have been cleared.\n");
|
||||
conn->ho_lchan->conn = NULL;
|
||||
}
|
||||
|
||||
if (conn->lchan) {
|
||||
LOGP(DNM, LOGL_ERROR, "The lchan should have been cleared.\n");
|
||||
conn->lchan->conn = NULL;
|
||||
}
|
||||
|
||||
if (conn->secondary_lchan) {
|
||||
LOGP(DNM, LOGL_ERROR, "The secondary_lchan should have been cleared.\n");
|
||||
conn->secondary_lchan->conn = NULL;
|
||||
}
|
||||
|
||||
llist_del(&conn->entry);
|
||||
|
||||
lchan = conn->lchan;
|
||||
talloc_free(conn);
|
||||
|
||||
if (lchan)
|
||||
lchan->conn = NULL;
|
||||
}
|
||||
|
||||
int bsc_api_init(struct gsm_network *network, struct bsc_api *api)
|
||||
@@ -89,12 +259,28 @@ int bsc_api_init(struct gsm_network *network, struct bsc_api *api)
|
||||
}
|
||||
|
||||
int gsm0808_submit_dtap(struct gsm_subscriber_connection *conn,
|
||||
struct msgb *msg, int link_id)
|
||||
struct msgb *msg, int link_id, int allow_sach)
|
||||
{
|
||||
uint8_t sapi = link_id & 0x7;
|
||||
uint8_t sapi;
|
||||
|
||||
|
||||
if (!conn->lchan) {
|
||||
LOGP(DMSC, LOGL_ERROR,
|
||||
"Called submit dtap without an lchan.\n");
|
||||
msgb_free(msg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
sapi = link_id & 0x7;
|
||||
msg->lchan = conn->lchan;
|
||||
msg->trx = msg->lchan->ts->trx;
|
||||
|
||||
/* If we are on a TCH and need to submit a SMS (on SAPI=3) we need to use the SACH */
|
||||
if (allow_sach && sapi != 0) {
|
||||
if (conn->lchan->type == GSM_LCHAN_TCH_F || conn->lchan->type == GSM_LCHAN_TCH_H)
|
||||
link_id |= 0x40;
|
||||
}
|
||||
|
||||
msg->l3h = msg->data;
|
||||
if (conn->lchan->sapis[sapi] == LCHAN_SAPI_UNUSED) {
|
||||
OBSC_LINKID_CB(msg) = link_id;
|
||||
@@ -111,15 +297,40 @@ int gsm0808_submit_dtap(struct gsm_subscriber_connection *conn,
|
||||
|
||||
/**
|
||||
* Send a GSM08.08 Assignment Request. Right now this does not contain the
|
||||
* audio codec type or the allowed rates for the config.
|
||||
* audio codec type or the allowed rates for the config. It is assumed that
|
||||
* this is for audio handling and that when we have a TCH it is capable of
|
||||
* handling the audio codec. On top of that it is assumed that we are using
|
||||
* AMR 5.9 when assigning a TCH/H.
|
||||
*/
|
||||
int gsm0808_assign_req(struct gsm_subscriber_connection *conn, int chan_type, int audio)
|
||||
int gsm0808_assign_req(struct gsm_subscriber_connection *conn, int chan_mode, int full_rate)
|
||||
{
|
||||
struct bsc_api *api;
|
||||
api = conn->bts->network->bsc_api;
|
||||
|
||||
api->assign_fail(conn, 0);
|
||||
if (conn->lchan->type == GSM_LCHAN_SDCCH) {
|
||||
if (handle_new_assignment(conn, chan_mode, full_rate) != 0)
|
||||
goto error;
|
||||
} else {
|
||||
LOGP(DMSC, LOGL_NOTICE,
|
||||
"Sending ChanModify for speech %d %d\n", chan_mode, full_rate);
|
||||
if (chan_mode == GSM48_CMODE_SPEECH_AMR) {
|
||||
conn->lchan->mr_conf.ver = 1;
|
||||
conn->lchan->mr_conf.icmi = 1;
|
||||
conn->lchan->mr_conf.m5_90 = 1;
|
||||
}
|
||||
|
||||
gsm48_lchan_modify(conn->lchan, chan_mode);
|
||||
}
|
||||
|
||||
/* we will now start the timer to complete the assignment */
|
||||
conn->T10.cb = assignment_t10_timeout;
|
||||
conn->T10.data = conn;
|
||||
bsc_schedule_timer(&conn->T10, GSM0808_T10_VALUE);
|
||||
return 0;
|
||||
|
||||
error:
|
||||
api->assign_fail(conn, 0, NULL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int gsm0808_page(struct gsm_bts *bts, unsigned int page_group, unsigned int mi_len,
|
||||
@@ -128,23 +339,124 @@ int gsm0808_page(struct gsm_bts *bts, unsigned int page_group, unsigned int mi_l
|
||||
return rsl_paging_cmd(bts, page_group, mi_len, mi, chan_type);
|
||||
}
|
||||
|
||||
/* dequeue messages to layer 4 */
|
||||
int bsc_upqueue(struct gsm_network *net)
|
||||
static void handle_ass_compl(struct gsm_subscriber_connection *conn,
|
||||
struct msgb *msg)
|
||||
{
|
||||
struct gsm_mncc *mncc;
|
||||
struct msgb *msg;
|
||||
int work = 0;
|
||||
struct gsm48_hdr *gh;
|
||||
struct bsc_api *api = conn->bts->network->bsc_api;
|
||||
|
||||
if (net)
|
||||
while ((msg = msgb_dequeue(&net->upqueue))) {
|
||||
mncc = (struct gsm_mncc *)msg->data;
|
||||
if (net->mncc_recv)
|
||||
net->mncc_recv(net, mncc->msg_type, mncc);
|
||||
work = 1; /* work done */
|
||||
talloc_free(msg);
|
||||
if (conn->secondary_lchan != msg->lchan) {
|
||||
LOGP(DMSC, LOGL_ERROR, "Assignment Compl should occur on second lchan.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
gh = msgb_l3(msg);
|
||||
if (msgb_l3len(msg) - sizeof(*gh) != 1) {
|
||||
LOGP(DMSC, LOGL_ERROR, "Assignment Compl invalid: %lu\n",
|
||||
msgb_l3len(msg) - sizeof(*gh));
|
||||
return;
|
||||
}
|
||||
|
||||
/* swap channels */
|
||||
bsc_del_timer(&conn->T10);
|
||||
|
||||
lchan_release(conn->lchan, 0, 1);
|
||||
conn->lchan = conn->secondary_lchan;
|
||||
conn->secondary_lchan = NULL;
|
||||
|
||||
if (is_ipaccess_bts(conn->bts) && conn->lchan->tch_mode != GSM48_CMODE_SIGN)
|
||||
rsl_ipacc_crcx(conn->lchan);
|
||||
|
||||
api->assign_compl(conn, gh->data[0],
|
||||
lchan_to_chosen_channel(conn->lchan),
|
||||
conn->lchan->encr.alg_id,
|
||||
chan_mode_to_speech(conn->lchan));
|
||||
}
|
||||
|
||||
static void handle_ass_fail(struct gsm_subscriber_connection *conn,
|
||||
struct msgb *msg)
|
||||
{
|
||||
struct bsc_api *api = conn->bts->network->bsc_api;
|
||||
uint8_t *rr_failure;
|
||||
struct gsm48_hdr *gh;
|
||||
|
||||
|
||||
if (conn->lchan != msg->lchan) {
|
||||
LOGP(DMSC, LOGL_ERROR, "Assignment failure should occur on primary lchan.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* stop the timer and release it */
|
||||
bsc_del_timer(&conn->T10);
|
||||
lchan_release(conn->secondary_lchan, 0, 1);
|
||||
conn->secondary_lchan = NULL;
|
||||
|
||||
gh = msgb_l3(msg);
|
||||
if (msgb_l3len(msg) - sizeof(*gh) != 1) {
|
||||
LOGP(DMSC, LOGL_ERROR, "assignemnt failure unhandled: %lu\n",
|
||||
msgb_l3len(msg) - sizeof(*gh));
|
||||
rr_failure = NULL;
|
||||
} else {
|
||||
rr_failure = &gh->data[0];
|
||||
}
|
||||
|
||||
api->assign_fail(conn,
|
||||
GSM0808_CAUSE_RADIO_INTERFACE_MESSAGE_FAILURE,
|
||||
rr_failure);
|
||||
}
|
||||
|
||||
static void dispatch_dtap(struct gsm_subscriber_connection *conn,
|
||||
uint8_t link_id, struct msgb *msg)
|
||||
{
|
||||
struct bsc_api *api = msg->lchan->ts->trx->bts->network->bsc_api;
|
||||
struct gsm48_hdr *gh;
|
||||
uint8_t pdisc;
|
||||
int rc;
|
||||
|
||||
if (msgb_l3len(msg) < sizeof(*gh)) {
|
||||
LOGP(DMSC, LOGL_ERROR, "Message too short for a GSM48 header.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
gh = msgb_l3(msg);
|
||||
pdisc = gh->proto_discr & 0x0f;
|
||||
switch (pdisc) {
|
||||
case GSM48_PDISC_RR:
|
||||
switch (gh->msg_type) {
|
||||
case GSM48_MT_RR_CIPH_M_COMPL:
|
||||
if (api->cipher_mode_compl)
|
||||
return api->cipher_mode_compl(conn, msg,
|
||||
conn->lchan->encr.alg_id);
|
||||
break;
|
||||
case GSM48_MT_RR_ASS_COMPL:
|
||||
handle_ass_compl(conn, msg);
|
||||
break;
|
||||
case GSM48_MT_RR_ASS_FAIL:
|
||||
handle_ass_fail(conn, msg);
|
||||
break;
|
||||
case GSM48_MT_RR_CHAN_MODE_MODIF_ACK:
|
||||
bsc_del_timer(&conn->T10);
|
||||
rc = gsm48_rx_rr_modif_ack(msg);
|
||||
if (rc < 0 && api->assign_fail) {
|
||||
api->assign_fail(conn,
|
||||
GSM0808_CAUSE_NO_RADIO_RESOURCE_AVAILABLE,
|
||||
NULL);
|
||||
} else if (rc >= 0 && api->assign_compl)
|
||||
api->assign_compl(conn, 0,
|
||||
lchan_to_chosen_channel(conn->lchan),
|
||||
conn->lchan->encr.alg_id,
|
||||
chan_mode_to_speech(conn->lchan));
|
||||
return;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case GSM48_PDISC_MM:
|
||||
break;
|
||||
}
|
||||
|
||||
return work;
|
||||
/* default case */
|
||||
if (api->dtap)
|
||||
api->dtap(conn, link_id, msg);
|
||||
}
|
||||
|
||||
int gsm0408_rcvmsg(struct msgb *msg, uint8_t link_id)
|
||||
@@ -155,21 +467,26 @@ int gsm0408_rcvmsg(struct msgb *msg, uint8_t link_id)
|
||||
|
||||
lchan = msg->lchan;
|
||||
if (lchan->state != LCHAN_S_ACTIVE) {
|
||||
LOGP(DRSL, LOGL_ERROR, "Got data in non active state. discarding.\n");
|
||||
LOGP(DRSL, LOGL_INFO, "Got data in non active state(%s), "
|
||||
"discarding.\n", gsm_lchans_name(lchan->state));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
if (lchan->conn) {
|
||||
api->dtap(lchan->conn, msg);
|
||||
dispatch_dtap(lchan->conn, link_id, msg);
|
||||
} else {
|
||||
rc = BSC_API_CONN_POL_REJECT;
|
||||
lchan->conn = subscr_con_allocate(msg->lchan);
|
||||
if (!lchan->conn) {
|
||||
lchan_release(lchan, 0, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (lchan->conn)
|
||||
rc = api->compl_l3(lchan->conn, msg, 0);
|
||||
rc = api->compl_l3(lchan->conn, msg, 0);
|
||||
|
||||
if (rc != BSC_API_CONN_POL_ACCEPT) {
|
||||
lchan->conn->lchan = NULL;
|
||||
subscr_con_free(lchan->conn);
|
||||
lchan_release(lchan, 0, 0);
|
||||
}
|
||||
@@ -179,9 +496,25 @@ int gsm0408_rcvmsg(struct msgb *msg, uint8_t link_id)
|
||||
}
|
||||
|
||||
int gsm0808_cipher_mode(struct gsm_subscriber_connection *conn, int cipher,
|
||||
uint8_t *key, int len)
|
||||
const uint8_t *key, int len, int include_imeisv)
|
||||
{
|
||||
return -1;
|
||||
if (cipher > 0 && key == NULL) {
|
||||
LOGP(DRSL, LOGL_ERROR, "Need to have an encrytpion key.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (len > MAX_A5_KEY_LEN) {
|
||||
LOGP(DRSL, LOGL_ERROR, "The key is too long: %d\n", len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
conn->lchan->encr.alg_id = RSL_ENC_ALG_A5(cipher);
|
||||
if (key) {
|
||||
conn->lchan->encr.key_len = len;
|
||||
memcpy(conn->lchan->encr.key, key, len);
|
||||
}
|
||||
|
||||
return gsm48_send_rr_ciph_mode(conn->lchan, include_imeisv);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -190,17 +523,21 @@ int gsm0808_cipher_mode(struct gsm_subscriber_connection *conn, int cipher,
|
||||
int gsm0808_clear(struct gsm_subscriber_connection *conn)
|
||||
{
|
||||
if (conn->ho_lchan)
|
||||
bsc_clear_handover(conn);
|
||||
bsc_clear_handover(conn, 1);
|
||||
|
||||
if (conn->lchan) {
|
||||
if (conn->secondary_lchan)
|
||||
lchan_release(conn->secondary_lchan, 0, 1);
|
||||
|
||||
if (conn->lchan)
|
||||
lchan_release(conn->lchan, 1, 0);
|
||||
conn->lchan->conn = NULL;
|
||||
}
|
||||
|
||||
conn->lchan = NULL;
|
||||
conn->secondary_lchan = NULL;
|
||||
conn->ho_lchan = NULL;
|
||||
conn->bts = NULL;
|
||||
|
||||
bsc_del_timer(&conn->T10);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -222,6 +559,14 @@ static void rll_ind_cb(struct gsm_lchan *lchan, uint8_t link_id, void *_data, en
|
||||
{
|
||||
struct msgb *msg = _data;
|
||||
|
||||
/*
|
||||
* There seems to be a small window that the RLL timer can
|
||||
* fire after a lchan_release call and before the S_CHALLOC_FREED
|
||||
* is called. Check if a conn is set before proceeding.
|
||||
*/
|
||||
if (!lchan->conn)
|
||||
return;
|
||||
|
||||
switch (rllr_ind) {
|
||||
case BSC_RLLR_IND_EST_CONF:
|
||||
rsl_data_request(msg, OBSC_LINKID_CB(msg));
|
||||
@@ -240,31 +585,88 @@ static int bsc_handle_lchan_signal(unsigned int subsys, unsigned int signal,
|
||||
{
|
||||
struct bsc_api *bsc;
|
||||
struct gsm_lchan *lchan;
|
||||
struct gsm_subscriber_connection *conn;
|
||||
struct lchan_signal_data *lchan_data;
|
||||
|
||||
if (subsys != SS_LCHAN || signal != S_LCHAN_UNEXPECTED_RELEASE)
|
||||
if (subsys != SS_LCHAN)
|
||||
return 0;
|
||||
|
||||
lchan = (struct gsm_lchan *)signal_data;
|
||||
if (!lchan || !lchan->conn)
|
||||
|
||||
lchan_data = signal_data;
|
||||
if (!lchan_data->lchan || !lchan_data->lchan->conn)
|
||||
return 0;
|
||||
|
||||
lchan = lchan_data->lchan;
|
||||
bsc = lchan->ts->trx->bts->network->bsc_api;
|
||||
if (!bsc)
|
||||
return 0;
|
||||
|
||||
conn = lchan->conn;
|
||||
switch (signal) {
|
||||
case S_LCHAN_UNEXPECTED_RELEASE:
|
||||
handle_release(lchan->conn, bsc, lchan);
|
||||
break;
|
||||
case S_LCHAN_ACTIVATE_ACK:
|
||||
handle_chan_ack(lchan->conn, bsc, lchan);
|
||||
break;
|
||||
case S_LCHAN_ACTIVATE_NACK:
|
||||
handle_chan_nack(lchan->conn, bsc, lchan);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void handle_release(struct gsm_subscriber_connection *conn,
|
||||
struct bsc_api *bsc, struct gsm_lchan *lchan)
|
||||
{
|
||||
int destruct = 1;
|
||||
|
||||
if (conn->secondary_lchan == lchan) {
|
||||
bsc_del_timer(&conn->T10);
|
||||
conn->secondary_lchan = NULL;
|
||||
|
||||
bsc->assign_fail(conn,
|
||||
GSM0808_CAUSE_RADIO_INTERFACE_FAILURE,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/* clear the connection now */
|
||||
if (bsc->clear_request)
|
||||
bsc->clear_request(conn, 0);
|
||||
destruct = bsc->clear_request(conn, 0);
|
||||
|
||||
/* now give up all channels */
|
||||
if (conn->lchan == lchan)
|
||||
conn->lchan = NULL;
|
||||
if (conn->ho_lchan == lchan)
|
||||
if (conn->ho_lchan == lchan) {
|
||||
bsc_clear_handover(conn, 0);
|
||||
conn->ho_lchan = NULL;
|
||||
}
|
||||
lchan->conn = NULL;
|
||||
|
||||
gsm0808_clear(conn);
|
||||
|
||||
return 0;
|
||||
if (destruct)
|
||||
subscr_con_free(conn);
|
||||
}
|
||||
|
||||
static void handle_chan_ack(struct gsm_subscriber_connection *conn,
|
||||
struct bsc_api *api, struct gsm_lchan *lchan)
|
||||
{
|
||||
if (conn->secondary_lchan != lchan)
|
||||
return;
|
||||
|
||||
LOGP(DMSC, LOGL_NOTICE, "Sending assignment on chan: %p\n", lchan);
|
||||
gsm48_send_rr_ass_cmd(conn->lchan, lchan, 0x3);
|
||||
}
|
||||
|
||||
static void handle_chan_nack(struct gsm_subscriber_connection *conn,
|
||||
struct bsc_api *api, struct gsm_lchan *lchan)
|
||||
{
|
||||
if (conn->secondary_lchan != lchan)
|
||||
return;
|
||||
|
||||
LOGP(DMSC, LOGL_ERROR, "Channel activation failed. Waiting for timeout now\n");
|
||||
conn->secondary_lchan->conn = NULL;
|
||||
conn->secondary_lchan = NULL;
|
||||
}
|
||||
|
||||
static __attribute__((constructor)) void on_dso_load_bsc(void)
|
||||
|
||||
@@ -5,18 +5,17 @@
|
||||
* All Rights Reserved
|
||||
*
|
||||
* 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 2 of the License, or
|
||||
* 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.
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -38,6 +37,7 @@
|
||||
#include <osmocore/talloc.h>
|
||||
#include <openbsc/signal.h>
|
||||
#include <openbsc/osmo_msc.h>
|
||||
#include <openbsc/sms_queue.h>
|
||||
#include <openbsc/vty.h>
|
||||
|
||||
#include "../bscconfig.h"
|
||||
@@ -49,12 +49,13 @@ static const char *database_name = "hlr.sqlite3";
|
||||
static const char *config_file = "openbsc.cfg";
|
||||
extern const char *openbsc_copyright;
|
||||
static int daemonize = 0;
|
||||
static int use_mncc_sock = 0;
|
||||
|
||||
/* timer to store statistics */
|
||||
#define DB_SYNC_INTERVAL 60, 0
|
||||
static struct timer_list db_sync_timer;
|
||||
|
||||
extern int bsc_bootstrap_network(int (*mmc_rev)(struct gsm_network *, int, void *),
|
||||
extern int bsc_bootstrap_network(int (*mncc_recv)(struct gsm_network *, struct msgb *),
|
||||
const char *cfg_file);
|
||||
extern int bsc_shutdown_net(struct gsm_network *net);
|
||||
|
||||
@@ -91,6 +92,7 @@ static void print_help()
|
||||
printf(" -V --version. Print the version of OpenBSC.\n");
|
||||
printf(" -P --rtp-proxy Enable the RTP Proxy code inside OpenBSC\n");
|
||||
printf(" -e --log-level number. Set a global loglevel.\n");
|
||||
printf(" -m --mncc-sock Disable built-in MNCC handler and offer socket\n");
|
||||
}
|
||||
|
||||
static void handle_options(int argc, char **argv)
|
||||
@@ -110,10 +112,11 @@ static void handle_options(int argc, char **argv)
|
||||
{"version", 0, 0, 'V' },
|
||||
{"rtp-proxy", 0, 0, 'P'},
|
||||
{"log-level", 1, 0, 'e'},
|
||||
{"mncc-sock", 0, 0, 'm'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
c = getopt_long(argc, argv, "hd:Dsl:ar:p:TPVc:e:",
|
||||
c = getopt_long(argc, argv, "hd:Dsl:ar:p:TPVc:e:m",
|
||||
long_options, &option_index);
|
||||
if (c == -1)
|
||||
break;
|
||||
@@ -150,6 +153,9 @@ static void handle_options(int argc, char **argv)
|
||||
case 'e':
|
||||
log_set_log_level(stderr_target, atoi(optarg));
|
||||
break;
|
||||
case 'm':
|
||||
use_mncc_sock = 1;
|
||||
break;
|
||||
case 'V':
|
||||
print_version(1);
|
||||
exit(0);
|
||||
@@ -204,6 +210,8 @@ static void db_sync_timer_cb(void *data)
|
||||
extern int bts_model_unknown_init(void);
|
||||
extern int bts_model_bs11_init(void);
|
||||
extern int bts_model_nanobts_init(void);
|
||||
extern int bts_model_rbs2k_init(void);
|
||||
void talloc_ctx_init(void);
|
||||
|
||||
extern enum node_type bsc_vty_go_parent(struct vty *vty);
|
||||
|
||||
@@ -232,6 +240,9 @@ int main(int argc, char **argv)
|
||||
bts_model_unknown_init();
|
||||
bts_model_bs11_init();
|
||||
bts_model_nanobts_init();
|
||||
bts_model_rbs2k_init();
|
||||
|
||||
e1inp_init();
|
||||
|
||||
/* enable filters */
|
||||
log_set_all_filter(stderr_target, 1);
|
||||
@@ -243,10 +254,17 @@ int main(int argc, char **argv)
|
||||
/* parse options */
|
||||
handle_options(argc, argv);
|
||||
|
||||
rc = bsc_bootstrap_network(mncc_recv, config_file);
|
||||
/* internal MNCC handler or MNCC socket? */
|
||||
if (use_mncc_sock) {
|
||||
rc = bsc_bootstrap_network(mncc_sock_from_cc, config_file);
|
||||
if (rc >= 0)
|
||||
mncc_sock_init(bsc_gsmnet);
|
||||
} else
|
||||
rc = bsc_bootstrap_network(int_mncc_recv, config_file);
|
||||
if (rc < 0)
|
||||
exit(1);
|
||||
bsc_api_init(bsc_gsmnet, msc_bsc_api());
|
||||
mncc_sock_init(bsc_gsmnet);
|
||||
|
||||
/* seed the PRNG */
|
||||
srand(time(NULL));
|
||||
@@ -274,6 +292,10 @@ int main(int argc, char **argv)
|
||||
signal(SIGUSR2, &signal_handler);
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
|
||||
/* start the SMS queue */
|
||||
if (sms_queue_start(bsc_gsmnet, 20) != 0)
|
||||
return -1;
|
||||
|
||||
if (daemonize) {
|
||||
rc = osmo_daemonize();
|
||||
if (rc < 0) {
|
||||
@@ -283,7 +305,6 @@ int main(int argc, char **argv)
|
||||
}
|
||||
|
||||
while (1) {
|
||||
bsc_upqueue(bsc_gsmnet);
|
||||
log_reset_context();
|
||||
bsc_select_main(0);
|
||||
}
|
||||
|
||||
@@ -5,18 +5,17 @@
|
||||
* All Rights Reserved
|
||||
*
|
||||
* 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 2 of the License, or
|
||||
* 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.
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -33,542 +32,30 @@
|
||||
#include <openbsc/signal.h>
|
||||
#include <openbsc/chan_alloc.h>
|
||||
#include <osmocore/talloc.h>
|
||||
#include <openbsc/ipaccess.h>
|
||||
|
||||
/* global pointer to the gsm network data structure */
|
||||
extern struct gsm_network *bsc_gsmnet;
|
||||
|
||||
static void patch_nm_tables(struct gsm_bts *bts);
|
||||
|
||||
/* The following definitions are for OM and NM packets that we cannot yet
|
||||
* generate by code but we just pass on */
|
||||
|
||||
// BTS Site Manager, SET ATTRIBUTES
|
||||
|
||||
/*
|
||||
Object Class: BTS Site Manager
|
||||
Instance 1: FF
|
||||
Instance 2: FF
|
||||
Instance 3: FF
|
||||
SET ATTRIBUTES
|
||||
sAbisExternalTime: 2007/09/08 14:36:11
|
||||
omLAPDRelTimer: 30sec
|
||||
shortLAPDIntTimer: 5sec
|
||||
emergencyTimer1: 10 minutes
|
||||
emergencyTimer2: 0 minutes
|
||||
*/
|
||||
|
||||
unsigned char msg_1[] =
|
||||
{
|
||||
NM_MT_BS11_SET_ATTR, NM_OC_SITE_MANAGER, 0xFF, 0xFF, 0xFF,
|
||||
NM_ATT_BS11_ABIS_EXT_TIME, 0x07,
|
||||
0xD7, 0x09, 0x08, 0x0E, 0x24, 0x0B, 0xCE,
|
||||
0x02,
|
||||
0x00, 0x1E,
|
||||
NM_ATT_BS11_SH_LAPD_INT_TIMER,
|
||||
0x01, 0x05,
|
||||
0x42, 0x02, 0x00, 0x0A,
|
||||
0x44, 0x02, 0x00, 0x00
|
||||
};
|
||||
|
||||
// BTS, SET BTS ATTRIBUTES
|
||||
|
||||
/*
|
||||
Object Class: BTS
|
||||
BTS relat. Number: 0
|
||||
Instance 2: FF
|
||||
Instance 3: FF
|
||||
SET BTS ATTRIBUTES
|
||||
bsIdentityCode / BSIC:
|
||||
PLMN_colour_code: 7h
|
||||
BS_colour_code: 7h
|
||||
BTS Air Timer T3105: 4 ,unit 10 ms
|
||||
btsIsHopping: FALSE
|
||||
periodCCCHLoadIndication: 1sec
|
||||
thresholdCCCHLoadIndication: 0%
|
||||
cellAllocationNumber: 00h = GSM 900
|
||||
enableInterferenceClass: 00h = Disabled
|
||||
fACCHQual: 6 (FACCH stealing flags minus 1)
|
||||
intaveParameter: 31 SACCH multiframes
|
||||
interferenceLevelBoundaries:
|
||||
Interference Boundary 1: 0Ah
|
||||
Interference Boundary 2: 0Fh
|
||||
Interference Boundary 3: 14h
|
||||
Interference Boundary 4: 19h
|
||||
Interference Boundary 5: 1Eh
|
||||
mSTxPwrMax: 11
|
||||
GSM range: 2=39dBm, 15=13dBm, stepsize 2 dBm
|
||||
DCS1800 range: 0=30dBm, 15=0dBm, stepsize 2 dBm
|
||||
PCS1900 range: 0=30dBm, 15=0dBm, stepsize 2 dBm
|
||||
30=33dBm, 31=32dBm
|
||||
ny1:
|
||||
Maximum number of repetitions for PHYSICAL INFORMATION message (GSM 04.08): 20
|
||||
powerOutputThresholds:
|
||||
Out Power Fault Threshold: -10 dB
|
||||
Red Out Power Threshold: - 6 dB
|
||||
Excessive Out Power Threshold: 5 dB
|
||||
rACHBusyThreshold: -127 dBm
|
||||
rACHLoadAveragingSlots: 250 ,number of RACH burst periods
|
||||
rfResourceIndicationPeriod: 125 SACCH multiframes
|
||||
T200:
|
||||
SDCCH: 044 in 5 ms
|
||||
FACCH/Full rate: 031 in 5 ms
|
||||
FACCH/Half rate: 041 in 5 ms
|
||||
SACCH with TCH SAPI0: 090 in 10 ms
|
||||
SACCH with SDCCH: 090 in 10 ms
|
||||
SDCCH with SAPI3: 090 in 5 ms
|
||||
SACCH with TCH SAPI3: 135 in 10 ms
|
||||
tSync: 9000 units of 10 msec
|
||||
tTrau: 9000 units of 10 msec
|
||||
enableUmLoopTest: 00h = disabled
|
||||
enableExcessiveDistance: 00h = Disabled
|
||||
excessiveDistance: 64km
|
||||
hoppingMode: 00h = baseband hopping
|
||||
cellType: 00h = Standard Cell
|
||||
BCCH ARFCN / bCCHFrequency: 1
|
||||
*/
|
||||
|
||||
static unsigned char bs11_attr_bts[] =
|
||||
{
|
||||
NM_ATT_BSIC, HARDCODED_BSIC,
|
||||
NM_ATT_BTS_AIR_TIMER, 0x04,
|
||||
NM_ATT_BS11_BTSLS_HOPPING, 0x00,
|
||||
NM_ATT_CCCH_L_I_P, 0x01,
|
||||
NM_ATT_CCCH_L_T, 0x00,
|
||||
NM_ATT_BS11_CELL_ALLOC_NR, NM_BS11_CANR_GSM,
|
||||
NM_ATT_BS11_ENA_INTERF_CLASS, 0x01,
|
||||
NM_ATT_BS11_FACCH_QUAL, 0x06,
|
||||
/* interference avg. period in numbers of SACCH multifr */
|
||||
NM_ATT_INTAVE_PARAM, 0x1F,
|
||||
NM_ATT_INTERF_BOUND, 0x0A, 0x0F, 0x14, 0x19, 0x1E, 0x7B,
|
||||
NM_ATT_CCCH_L_T, 0x23,
|
||||
NM_ATT_GSM_TIME, 0x28, 0x00,
|
||||
NM_ATT_ADM_STATE, 0x03,
|
||||
NM_ATT_RACH_B_THRESH, 0x7F,
|
||||
NM_ATT_LDAVG_SLOTS, 0x00, 0xFA,
|
||||
NM_ATT_BS11_RF_RES_IND_PER, 0x7D,
|
||||
NM_ATT_T200, 0x2C, 0x1F, 0x29, 0x5A, 0x5A, 0x5A, 0x87,
|
||||
NM_ATT_BS11_TSYNC, 0x23, 0x28,
|
||||
NM_ATT_BS11_TTRAU, 0x23, 0x28,
|
||||
NM_ATT_TEST_DUR, 0x01, 0x00,
|
||||
NM_ATT_OUTST_ALARM, 0x01, 0x00,
|
||||
NM_ATT_BS11_EXCESSIVE_DISTANCE, 0x01, 0x40,
|
||||
NM_ATT_BS11_HOPPING_MODE, 0x01, 0x00,
|
||||
NM_ATT_BS11_PLL, 0x01, 0x00,
|
||||
NM_ATT_BCCH_ARFCN, 0x00, HARDCODED_ARFCN/*0x01*/,
|
||||
};
|
||||
|
||||
// Handover Recognition, SET ATTRIBUTES
|
||||
|
||||
/*
|
||||
Illegal Contents GSM Formatted O&M Msg
|
||||
Object Class: Handover Recognition
|
||||
BTS relat. Number: 0
|
||||
Instance 2: FF
|
||||
Instance 3: FF
|
||||
SET ATTRIBUTES
|
||||
enableDelayPowerBudgetHO: 00h = Disabled
|
||||
enableDistanceHO: 00h = Disabled
|
||||
enableInternalInterCellHandover: 00h = Disabled
|
||||
enableInternalIntraCellHandover: 00h = Disabled
|
||||
enablePowerBudgetHO: 00h = Disabled
|
||||
enableRXLEVHO: 00h = Disabled
|
||||
enableRXQUALHO: 00h = Disabled
|
||||
hoAveragingDistance: 8 SACCH multiframes
|
||||
hoAveragingLev:
|
||||
A_LEV_HO: 8 SACCH multiframes
|
||||
W_LEV_HO: 1 SACCH multiframes
|
||||
hoAveragingPowerBudget: 16 SACCH multiframes
|
||||
hoAveragingQual:
|
||||
A_QUAL_HO: 8 SACCH multiframes
|
||||
W_QUAL_HO: 2 SACCH multiframes
|
||||
hoLowerThresholdLevDL: (10 - 110) dBm
|
||||
hoLowerThresholdLevUL: (5 - 110) dBm
|
||||
hoLowerThresholdQualDL: 06h = 6.4% < BER < 12.8%
|
||||
hoLowerThresholdQualUL: 06h = 6.4% < BER < 12.8%
|
||||
hoThresholdLevDLintra : (20 - 110) dBm
|
||||
hoThresholdLevULintra: (20 - 110) dBm
|
||||
hoThresholdMsRangeMax: 20 km
|
||||
nCell: 06h
|
||||
timerHORequest: 3 ,unit 2 SACCH multiframes
|
||||
*/
|
||||
|
||||
unsigned char msg_3[] =
|
||||
{
|
||||
NM_MT_BS11_SET_ATTR, NM_OC_BS11_HANDOVER, 0x00, 0xFF, 0xFF,
|
||||
0xD0, 0x00, /* enableDelayPowerBudgetHO */
|
||||
0x64, 0x00, /* enableDistanceHO */
|
||||
0x67, 0x00, /* enableInternalInterCellHandover */
|
||||
0x68, 0x00, /* enableInternalInterCellHandover */
|
||||
0x6A, 0x00, /* enablePowerBudgetHO */
|
||||
0x6C, 0x00, /* enableRXLEVHO */
|
||||
0x6D, 0x00, /* enableRXQUALHO */
|
||||
0x6F, 0x08, /* hoAveragingDistance */
|
||||
0x70, 0x08, 0x01, /* hoAveragingLev */
|
||||
0x71, 0x10, 0x10, 0x10,
|
||||
0x72, 0x08, 0x02, /* hoAveragingQual */
|
||||
0x73, 0x0A, /* hoLowerThresholdLevDL */
|
||||
0x74, 0x05, /* hoLowerThresholdLevUL */
|
||||
0x75, 0x06, /* hoLowerThresholdQualDL */
|
||||
0x76, 0x06, /* hoLowerThresholdQualUL */
|
||||
0x78, 0x14, /* hoThresholdLevDLintra */
|
||||
0x79, 0x14, /* hoThresholdLevULintra */
|
||||
0x7A, 0x14, /* hoThresholdMsRangeMax */
|
||||
0x7D, 0x06, /* nCell */
|
||||
NM_ATT_BS11_TIMER_HO_REQUEST, 0x03,
|
||||
0x20, 0x01, 0x00,
|
||||
0x45, 0x01, 0x00,
|
||||
0x48, 0x01, 0x00,
|
||||
0x5A, 0x01, 0x00,
|
||||
0x5B, 0x01, 0x05,
|
||||
0x5E, 0x01, 0x1A,
|
||||
0x5F, 0x01, 0x20,
|
||||
0x9D, 0x01, 0x00,
|
||||
0x47, 0x01, 0x00,
|
||||
0x5C, 0x01, 0x64,
|
||||
0x5D, 0x01, 0x1E,
|
||||
0x97, 0x01, 0x20,
|
||||
0xF7, 0x01, 0x3C,
|
||||
};
|
||||
|
||||
// Power Control, SET ATTRIBUTES
|
||||
|
||||
/*
|
||||
Object Class: Power Control
|
||||
BTS relat. Number: 0
|
||||
Instance 2: FF
|
||||
Instance 3: FF
|
||||
SET ATTRIBUTES
|
||||
enableMsPowerControl: 00h = Disabled
|
||||
enablePowerControlRLFW: 00h = Disabled
|
||||
pcAveragingLev:
|
||||
A_LEV_PC: 4 SACCH multiframes
|
||||
W_LEV_PC: 1 SACCH multiframes
|
||||
pcAveragingQual:
|
||||
A_QUAL_PC: 4 SACCH multiframes
|
||||
W_QUAL_PC: 2 SACCH multiframes
|
||||
pcLowerThresholdLevDL: 0Fh
|
||||
pcLowerThresholdLevUL: 0Ah
|
||||
pcLowerThresholdQualDL: 05h = 3.2% < BER < 6.4%
|
||||
pcLowerThresholdQualUL: 05h = 3.2% < BER < 6.4%
|
||||
pcRLFThreshold: 0Ch
|
||||
pcUpperThresholdLevDL: 14h
|
||||
pcUpperThresholdLevUL: 0Fh
|
||||
pcUpperThresholdQualDL: 04h = 1.6% < BER < 3.2%
|
||||
pcUpperThresholdQualUL: 04h = 1.6% < BER < 3.2%
|
||||
powerConfirm: 2 ,unit 2 SACCH multiframes
|
||||
powerControlInterval: 2 ,unit 2 SACCH multiframes
|
||||
powerIncrStepSize: 02h = 4 dB
|
||||
powerRedStepSize: 01h = 2 dB
|
||||
radioLinkTimeoutBs: 64 SACCH multiframes
|
||||
enableBSPowerControl: 00h = disabled
|
||||
*/
|
||||
|
||||
unsigned char msg_4[] =
|
||||
{
|
||||
NM_MT_BS11_SET_ATTR, NM_OC_BS11_PWR_CTRL, 0x00, 0xFF, 0xFF,
|
||||
NM_ATT_BS11_ENA_MS_PWR_CTRL, 0x00,
|
||||
NM_ATT_BS11_ENA_PWR_CTRL_RLFW, 0x00,
|
||||
0x7E, 0x04, 0x01, /* pcAveragingLev */
|
||||
0x7F, 0x04, 0x02, /* pcAveragingQual */
|
||||
0x80, 0x0F, /* pcLowerThresholdLevDL */
|
||||
0x81, 0x0A, /* pcLowerThresholdLevUL */
|
||||
0x82, 0x05, /* pcLowerThresholdQualDL */
|
||||
0x83, 0x05, /* pcLowerThresholdQualUL */
|
||||
0x84, 0x0C, /* pcRLFThreshold */
|
||||
0x85, 0x14, /* pcUpperThresholdLevDL */
|
||||
0x86, 0x0F, /* pcUpperThresholdLevUL */
|
||||
0x87, 0x04, /* pcUpperThresholdQualDL */
|
||||
0x88, 0x04, /* pcUpperThresholdQualUL */
|
||||
0x89, 0x02, /* powerConfirm */
|
||||
0x8A, 0x02, /* powerConfirmInterval */
|
||||
0x8B, 0x02, /* powerIncrStepSize */
|
||||
0x8C, 0x01, /* powerRedStepSize */
|
||||
0x8D, 0x40, /* radioLinkTimeoutBs */
|
||||
0x65, 0x01, 0x00 // set to 0x01 to enable BSPowerControl
|
||||
};
|
||||
|
||||
|
||||
// Transceiver, SET TRX ATTRIBUTES (TRX 0)
|
||||
|
||||
/*
|
||||
Object Class: Transceiver
|
||||
BTS relat. Number: 0
|
||||
Tranceiver number: 0
|
||||
Instance 3: FF
|
||||
SET TRX ATTRIBUTES
|
||||
aRFCNList (HEX): 0001
|
||||
txPwrMaxReduction: 00h = 30dB
|
||||
radioMeasGran: 254 SACCH multiframes
|
||||
radioMeasRep: 01h = enabled
|
||||
memberOfEmergencyConfig: 01h = TRUE
|
||||
trxArea: 00h = TRX doesn't belong to a concentric cell
|
||||
*/
|
||||
|
||||
static unsigned char bs11_attr_radio[] =
|
||||
{
|
||||
NM_ATT_ARFCN_LIST, 0x01, 0x00, HARDCODED_ARFCN /*0x01*/,
|
||||
NM_ATT_RF_MAXPOWR_R, 0x00,
|
||||
NM_ATT_BS11_RADIO_MEAS_GRAN, 0x01, 0x05,
|
||||
NM_ATT_BS11_RADIO_MEAS_REP, 0x01, 0x01,
|
||||
NM_ATT_BS11_EMRG_CFG_MEMBER, 0x01, 0x01,
|
||||
NM_ATT_BS11_TRX_AREA, 0x01, 0x00,
|
||||
};
|
||||
|
||||
static unsigned char nanobts_attr_bts[] = {
|
||||
NM_ATT_INTERF_BOUND, 0x55, 0x5b, 0x61, 0x67, 0x6d, 0x73,
|
||||
/* interference avg. period in numbers of SACCH multifr */
|
||||
NM_ATT_INTAVE_PARAM, 0x06,
|
||||
/* conn fail based on SACCH error rate */
|
||||
NM_ATT_CONN_FAIL_CRIT, 0x00, 0x02, 0x01, 0x10,
|
||||
NM_ATT_T200, 0x1e, 0x24, 0x24, 0xa8, 0x34, 0x21, 0xa8,
|
||||
NM_ATT_MAX_TA, 0x3f,
|
||||
NM_ATT_OVERL_PERIOD, 0x00, 0x01, 10, /* seconds */
|
||||
NM_ATT_CCCH_L_T, 10, /* percent */
|
||||
NM_ATT_CCCH_L_I_P, 1, /* seconds */
|
||||
NM_ATT_RACH_B_THRESH, 10, /* busy threshold in - dBm */
|
||||
NM_ATT_LDAVG_SLOTS, 0x03, 0xe8, /* rach load averaging 1000 slots */
|
||||
NM_ATT_BTS_AIR_TIMER, 128, /* miliseconds */
|
||||
NM_ATT_NY1, 10, /* 10 retransmissions of physical config */
|
||||
NM_ATT_BCCH_ARFCN, HARDCODED_ARFCN >> 8, HARDCODED_ARFCN & 0xff,
|
||||
NM_ATT_BSIC, HARDCODED_BSIC,
|
||||
NM_ATT_IPACC_CGI, 0, 7, 0x00, 0xf1, 0x10, 0x00, 0x01, 0x00, 0x00,
|
||||
};
|
||||
|
||||
static unsigned char nanobts_attr_radio[] = {
|
||||
NM_ATT_RF_MAXPOWR_R, 0x0c, /* number of -2dB reduction steps / Pn */
|
||||
NM_ATT_ARFCN_LIST, 0x00, 0x02, HARDCODED_ARFCN >> 8, HARDCODED_ARFCN & 0xff,
|
||||
};
|
||||
|
||||
static unsigned char nanobts_attr_nse[] = {
|
||||
NM_ATT_IPACC_NSEI, 0, 2, 0x03, 0x9d, /* NSEI 925 */
|
||||
NM_ATT_IPACC_NS_CFG, 0, 7, 3, /* (un)blocking timer (Tns-block) */
|
||||
3, /* (un)blocking retries */
|
||||
3, /* reset timer (Tns-reset) */
|
||||
3, /* reset retries */
|
||||
30, /* test timer (Tns-test) */
|
||||
3, /* alive timer (Tns-alive) */
|
||||
10, /* alive retrires */
|
||||
NM_ATT_IPACC_BSSGP_CFG, 0, 11,
|
||||
3, /* blockimg timer (T1) */
|
||||
3, /* blocking retries */
|
||||
3, /* unblocking retries */
|
||||
3, /* reset timer */
|
||||
3, /* reset retries */
|
||||
10, /* suspend timer (T3) in 100ms */
|
||||
3, /* suspend retries */
|
||||
10, /* resume timer (T4) in 100ms */
|
||||
3, /* resume retries */
|
||||
10, /* capability update timer (T5) */
|
||||
3, /* capability update retries */
|
||||
};
|
||||
|
||||
static unsigned char nanobts_attr_cell[] = {
|
||||
NM_ATT_IPACC_RAC, 0, 1, 1, /* routing area code */
|
||||
NM_ATT_IPACC_GPRS_PAGING_CFG, 0, 2,
|
||||
5, /* repeat time (50ms) */
|
||||
3, /* repeat count */
|
||||
NM_ATT_IPACC_BVCI, 0, 2, 0x03, 0x9d, /* BVCI 925 */
|
||||
NM_ATT_IPACC_RLC_CFG, 0, 9,
|
||||
20, /* T3142 */
|
||||
5, /* T3169 */
|
||||
5, /* T3191 */
|
||||
200, /* T3193 */
|
||||
5, /* T3195 */
|
||||
10, /* N3101 */
|
||||
4, /* N3103 */
|
||||
8, /* N3105 */
|
||||
15, /* RLC CV countdown */
|
||||
NM_ATT_IPACC_CODING_SCHEMES, 0, 2, 0x0f, 0x00, /* CS1..CS4 */
|
||||
NM_ATT_IPACC_RLC_CFG_2, 0, 5,
|
||||
0x00, 250, /* T downlink TBF extension (0..500) */
|
||||
0x00, 250, /* T uplink TBF extension (0..500) */
|
||||
2, /* CS2 */
|
||||
#if 0
|
||||
/* EDGE model only, breaks older models.
|
||||
* Should inquire the BTS capabilities */
|
||||
NM_ATT_IPACC_RLC_CFG_3, 0, 1,
|
||||
2, /* MCS2 */
|
||||
#endif
|
||||
};
|
||||
|
||||
static unsigned char nanobts_attr_nsvc0[] = {
|
||||
NM_ATT_IPACC_NSVCI, 0, 2, 0x03, 0x9d, /* 925 */
|
||||
NM_ATT_IPACC_NS_LINK_CFG, 0, 8,
|
||||
0x59, 0xd8, /* remote udp port (23000) */
|
||||
192, 168, 100, 11, /* remote ip address */
|
||||
0x59, 0xd8, /* local udp port (23000) */
|
||||
};
|
||||
|
||||
/* Callback function to be called whenever we get a GSM 12.21 state change event */
|
||||
int nm_state_event(enum nm_evt evt, u_int8_t obj_class, void *obj,
|
||||
struct gsm_nm_state *old_state, struct gsm_nm_state *new_state,
|
||||
struct abis_om_obj_inst *obj_inst)
|
||||
{
|
||||
struct gsm_bts *bts;
|
||||
struct gsm_bts_trx *trx;
|
||||
struct gsm_bts_trx_ts *ts;
|
||||
struct gsm_bts_gprs_nsvc *nsvc;
|
||||
|
||||
/* This event-driven BTS setup is currently only required on nanoBTS */
|
||||
|
||||
/* EVT_STATECHG_ADM is called after we call chg_adm_state() and would create
|
||||
* endless loop */
|
||||
if (evt != EVT_STATECHG_OPER)
|
||||
return 0;
|
||||
|
||||
switch (obj_class) {
|
||||
case NM_OC_SITE_MANAGER:
|
||||
bts = container_of(obj, struct gsm_bts, site_mgr);
|
||||
if ((new_state->operational == NM_OPSTATE_ENABLED &&
|
||||
new_state->availability == NM_AVSTATE_OK) ||
|
||||
(new_state->operational == NM_OPSTATE_DISABLED &&
|
||||
new_state->availability == NM_AVSTATE_OFF_LINE))
|
||||
abis_nm_opstart(bts, obj_class, 0xff, 0xff, 0xff);
|
||||
break;
|
||||
case NM_OC_BTS:
|
||||
bts = obj;
|
||||
if (new_state->availability == NM_AVSTATE_DEPENDENCY) {
|
||||
patch_nm_tables(bts);
|
||||
abis_nm_set_bts_attr(bts, nanobts_attr_bts,
|
||||
sizeof(nanobts_attr_bts));
|
||||
abis_nm_chg_adm_state(bts, obj_class,
|
||||
bts->bts_nr, 0xff, 0xff,
|
||||
NM_STATE_UNLOCKED);
|
||||
abis_nm_opstart(bts, obj_class,
|
||||
bts->bts_nr, 0xff, 0xff);
|
||||
}
|
||||
break;
|
||||
case NM_OC_CHANNEL:
|
||||
ts = obj;
|
||||
trx = ts->trx;
|
||||
if (new_state->operational == NM_OPSTATE_DISABLED &&
|
||||
new_state->availability == NM_AVSTATE_DEPENDENCY) {
|
||||
patch_nm_tables(trx->bts);
|
||||
enum abis_nm_chan_comb ccomb =
|
||||
abis_nm_chcomb4pchan(ts->pchan);
|
||||
abis_nm_set_channel_attr(ts, ccomb);
|
||||
abis_nm_chg_adm_state(trx->bts, obj_class,
|
||||
trx->bts->bts_nr, trx->nr, ts->nr,
|
||||
NM_STATE_UNLOCKED);
|
||||
abis_nm_opstart(trx->bts, obj_class,
|
||||
trx->bts->bts_nr, trx->nr, ts->nr);
|
||||
}
|
||||
break;
|
||||
case NM_OC_RADIO_CARRIER:
|
||||
trx = obj;
|
||||
if (new_state->operational == NM_OPSTATE_DISABLED &&
|
||||
new_state->availability == NM_AVSTATE_OK)
|
||||
abis_nm_opstart(trx->bts, obj_class, trx->bts->bts_nr,
|
||||
trx->nr, 0xff);
|
||||
break;
|
||||
case NM_OC_GPRS_NSE:
|
||||
bts = container_of(obj, struct gsm_bts, gprs.nse);
|
||||
if (bts->gprs.mode == BTS_GPRS_NONE)
|
||||
break;
|
||||
if (new_state->availability == NM_AVSTATE_DEPENDENCY) {
|
||||
abis_nm_ipaccess_set_attr(bts, obj_class, bts->bts_nr,
|
||||
0xff, 0xff, nanobts_attr_nse,
|
||||
sizeof(nanobts_attr_nse));
|
||||
abis_nm_opstart(bts, obj_class, bts->bts_nr,
|
||||
0xff, 0xff);
|
||||
abis_nm_chg_adm_state(bts, obj_class, bts->bts_nr,
|
||||
0xff, 0xff, NM_STATE_UNLOCKED);
|
||||
}
|
||||
break;
|
||||
case NM_OC_GPRS_CELL:
|
||||
bts = container_of(obj, struct gsm_bts, gprs.cell);
|
||||
if (bts->gprs.mode == BTS_GPRS_NONE)
|
||||
break;
|
||||
if (new_state->availability == NM_AVSTATE_DEPENDENCY) {
|
||||
abis_nm_ipaccess_set_attr(bts, obj_class, bts->bts_nr,
|
||||
0, 0xff, nanobts_attr_cell,
|
||||
sizeof(nanobts_attr_cell));
|
||||
abis_nm_opstart(bts, obj_class, bts->bts_nr,
|
||||
0, 0xff);
|
||||
abis_nm_chg_adm_state(bts, obj_class, bts->bts_nr,
|
||||
0, 0xff, NM_STATE_UNLOCKED);
|
||||
}
|
||||
break;
|
||||
case NM_OC_GPRS_NSVC:
|
||||
nsvc = obj;
|
||||
bts = nsvc->bts;
|
||||
if (bts->gprs.mode == BTS_GPRS_NONE)
|
||||
break;
|
||||
/* We skip NSVC1 since we only use NSVC0 */
|
||||
if (nsvc->id == 1)
|
||||
break;
|
||||
if (new_state->availability == NM_AVSTATE_OFF_LINE) {
|
||||
abis_nm_ipaccess_set_attr(bts, obj_class, bts->bts_nr,
|
||||
nsvc->id, 0xff,
|
||||
nanobts_attr_nsvc0,
|
||||
sizeof(nanobts_attr_nsvc0));
|
||||
abis_nm_opstart(bts, obj_class, bts->bts_nr,
|
||||
nsvc->id, 0xff);
|
||||
abis_nm_chg_adm_state(bts, obj_class, bts->bts_nr,
|
||||
nsvc->id, 0xff,
|
||||
NM_STATE_UNLOCKED);
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Callback function to be called every time we receive a 12.21 SW activated report */
|
||||
static int sw_activ_rep(struct msgb *mb)
|
||||
{
|
||||
struct abis_om_fom_hdr *foh = msgb_l3(mb);
|
||||
struct gsm_bts *bts = mb->trx->bts;
|
||||
struct gsm_bts_trx *trx = gsm_bts_trx_num(bts, foh->obj_inst.trx_nr);
|
||||
|
||||
if (!trx)
|
||||
return -EINVAL;
|
||||
|
||||
switch (foh->obj_class) {
|
||||
case NM_OC_BASEB_TRANSC:
|
||||
abis_nm_chg_adm_state(trx->bts, foh->obj_class,
|
||||
trx->bts->bts_nr, trx->nr, 0xff,
|
||||
NM_STATE_UNLOCKED);
|
||||
abis_nm_opstart(trx->bts, foh->obj_class,
|
||||
trx->bts->bts_nr, trx->nr, 0xff);
|
||||
/* TRX software is active, tell it to initiate RSL Link */
|
||||
abis_nm_ipaccess_rsl_connect(trx, 0, 3003, trx->rsl_tei);
|
||||
break;
|
||||
case NM_OC_RADIO_CARRIER: {
|
||||
/*
|
||||
* Locking the radio carrier will make it go
|
||||
* offline again and we would come here. The
|
||||
* framework should determine that there was
|
||||
* no change and avoid recursion.
|
||||
*
|
||||
* This code is here to make sure that on start
|
||||
* a TRX remains locked.
|
||||
*/
|
||||
int rc_state = trx->nm_state.administrative;
|
||||
/* Patch ARFCN into radio attribute */
|
||||
nanobts_attr_radio[5] &= 0xf0;
|
||||
nanobts_attr_radio[5] |= trx->arfcn >> 8;
|
||||
nanobts_attr_radio[6] = trx->arfcn & 0xff;
|
||||
abis_nm_set_radio_attr(trx, nanobts_attr_radio,
|
||||
sizeof(nanobts_attr_radio));
|
||||
abis_nm_chg_adm_state(trx->bts, foh->obj_class,
|
||||
trx->bts->bts_nr, trx->nr, 0xff,
|
||||
rc_state);
|
||||
abis_nm_opstart(trx->bts, foh->obj_class, trx->bts->bts_nr,
|
||||
trx->nr, 0xff);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Callback function for NACK on the OML NM */
|
||||
static int oml_msg_nack(struct nm_nack_signal_data *nack)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (nack->mt == NM_MT_SET_BTS_ATTR_NACK) {
|
||||
|
||||
LOGP(DNM, LOGL_FATAL, "Failed to set BTS attributes. That is fatal. "
|
||||
"Was the bts type and frequency properly specified?\n");
|
||||
exit(-1);
|
||||
} else {
|
||||
LOGP(DNM, LOGL_ERROR, "Got a NACK going to drop the OML links.\n");
|
||||
for (i = 0; i < bsc_gsmnet->num_bts; ++i) {
|
||||
struct gsm_bts *bts = gsm_bts_num(bsc_gsmnet, i);
|
||||
if (is_ipaccess_bts(bts))
|
||||
ipaccess_drop_oml(bts);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -579,11 +66,8 @@ static int nm_sig_cb(unsigned int subsys, unsigned int signal,
|
||||
void *handler_data, void *signal_data)
|
||||
{
|
||||
struct nm_nack_signal_data *nack;
|
||||
u_int8_t *msg_type;
|
||||
|
||||
switch (signal) {
|
||||
case S_NM_SW_ACTIV_REP:
|
||||
return sw_activ_rep(signal_data);
|
||||
case S_NM_NACK:
|
||||
nack = signal_data;
|
||||
return oml_msg_nack(nack);
|
||||
@@ -593,190 +77,13 @@ static int nm_sig_cb(unsigned int subsys, unsigned int signal,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bootstrap_om_nanobts(struct gsm_bts *bts)
|
||||
{
|
||||
/* We don't do callback based bootstrapping, but event driven (see above) */
|
||||
}
|
||||
|
||||
static void nm_reconfig_ts(struct gsm_bts_trx_ts *ts)
|
||||
{
|
||||
enum abis_nm_chan_comb ccomb = abis_nm_chcomb4pchan(ts->pchan);
|
||||
struct gsm_e1_subslot *e1l = &ts->e1_link;
|
||||
|
||||
abis_nm_set_channel_attr(ts, ccomb);
|
||||
|
||||
if (is_ipaccess_bts(ts->trx->bts))
|
||||
return;
|
||||
|
||||
switch (ts->pchan) {
|
||||
case GSM_PCHAN_TCH_F:
|
||||
case GSM_PCHAN_TCH_H:
|
||||
abis_nm_conn_terr_traf(ts, e1l->e1_nr, e1l->e1_ts,
|
||||
e1l->e1_ts_ss);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void nm_reconfig_trx(struct gsm_bts_trx *trx)
|
||||
{
|
||||
struct gsm_e1_subslot *e1l = &trx->rsl_e1_link;
|
||||
int i;
|
||||
|
||||
patch_nm_tables(trx->bts);
|
||||
|
||||
switch (trx->bts->type) {
|
||||
case GSM_BTS_TYPE_BS11:
|
||||
/* FIXME: discover this by fetching an attribute */
|
||||
#if 0
|
||||
trx->nominal_power = 15; /* 15dBm == 30mW PA configuration */
|
||||
#else
|
||||
trx->nominal_power = 24; /* 24dBm == 250mW PA configuration */
|
||||
#endif
|
||||
abis_nm_conn_terr_sign(trx, e1l->e1_nr, e1l->e1_ts,
|
||||
e1l->e1_ts_ss);
|
||||
abis_nm_establish_tei(trx->bts, trx->nr, e1l->e1_nr,
|
||||
e1l->e1_ts, e1l->e1_ts_ss, trx->rsl_tei);
|
||||
|
||||
/* Set Radio Attributes */
|
||||
if (trx == trx->bts->c0)
|
||||
abis_nm_set_radio_attr(trx, bs11_attr_radio,
|
||||
sizeof(bs11_attr_radio));
|
||||
else {
|
||||
u_int8_t trx1_attr_radio[sizeof(bs11_attr_radio)];
|
||||
u_int8_t arfcn_low = trx->arfcn & 0xff;
|
||||
u_int8_t arfcn_high = (trx->arfcn >> 8) & 0x0f;
|
||||
memcpy(trx1_attr_radio, bs11_attr_radio,
|
||||
sizeof(trx1_attr_radio));
|
||||
|
||||
/* patch ARFCN into TRX Attributes */
|
||||
trx1_attr_radio[2] &= 0xf0;
|
||||
trx1_attr_radio[2] |= arfcn_high;
|
||||
trx1_attr_radio[3] = arfcn_low;
|
||||
|
||||
abis_nm_set_radio_attr(trx, trx1_attr_radio,
|
||||
sizeof(trx1_attr_radio));
|
||||
}
|
||||
break;
|
||||
case GSM_BTS_TYPE_NANOBTS:
|
||||
switch (trx->bts->band) {
|
||||
case GSM_BAND_850:
|
||||
case GSM_BAND_900:
|
||||
trx->nominal_power = 20;
|
||||
break;
|
||||
case GSM_BAND_1800:
|
||||
case GSM_BAND_1900:
|
||||
trx->nominal_power = 23;
|
||||
break;
|
||||
default:
|
||||
LOGP(DNM, LOGL_ERROR, "Unsupported nanoBTS GSM band %s\n",
|
||||
gsm_band_name(trx->bts->band));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; i < TRX_NR_TS; i++)
|
||||
nm_reconfig_ts(&trx->ts[i]);
|
||||
}
|
||||
|
||||
static void nm_reconfig_bts(struct gsm_bts *bts)
|
||||
{
|
||||
struct gsm_bts_trx *trx;
|
||||
|
||||
switch (bts->type) {
|
||||
case GSM_BTS_TYPE_BS11:
|
||||
patch_nm_tables(bts);
|
||||
abis_nm_raw_msg(bts, sizeof(msg_1), msg_1); /* set BTS SiteMgr attr*/
|
||||
abis_nm_set_bts_attr(bts, bs11_attr_bts, sizeof(bs11_attr_bts));
|
||||
abis_nm_raw_msg(bts, sizeof(msg_3), msg_3); /* set BTS handover attr */
|
||||
abis_nm_raw_msg(bts, sizeof(msg_4), msg_4); /* set BTS power control attr */
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
llist_for_each_entry(trx, &bts->trx_list, list)
|
||||
nm_reconfig_trx(trx);
|
||||
}
|
||||
|
||||
static void bootstrap_om_bs11(struct gsm_bts *bts)
|
||||
{
|
||||
/* stop sending event reports */
|
||||
abis_nm_event_reports(bts, 0);
|
||||
|
||||
/* begin DB transmission */
|
||||
abis_nm_bs11_db_transmission(bts, 1);
|
||||
|
||||
/* end DB transmission */
|
||||
abis_nm_bs11_db_transmission(bts, 0);
|
||||
|
||||
/* Reset BTS Site manager resource */
|
||||
abis_nm_bs11_reset_resource(bts);
|
||||
|
||||
/* begin DB transmission */
|
||||
abis_nm_bs11_db_transmission(bts, 1);
|
||||
|
||||
/* reconfigure BTS with all TRX and all TS */
|
||||
nm_reconfig_bts(bts);
|
||||
|
||||
/* end DB transmission */
|
||||
abis_nm_bs11_db_transmission(bts, 0);
|
||||
|
||||
/* Reset BTS Site manager resource */
|
||||
abis_nm_bs11_reset_resource(bts);
|
||||
|
||||
/* restart sending event reports */
|
||||
abis_nm_event_reports(bts, 1);
|
||||
}
|
||||
|
||||
static void bootstrap_om(struct gsm_bts *bts)
|
||||
{
|
||||
LOGP(DNM, LOGL_NOTICE, "bootstrapping OML for BTS %u\n", bts->nr);
|
||||
|
||||
switch (bts->type) {
|
||||
case GSM_BTS_TYPE_BS11:
|
||||
bootstrap_om_bs11(bts);
|
||||
break;
|
||||
case GSM_BTS_TYPE_NANOBTS:
|
||||
bootstrap_om_nanobts(bts);
|
||||
break;
|
||||
default:
|
||||
LOGP(DNM, LOGL_ERROR, "Unable to bootstrap OML: Unknown BTS type %d\n", bts->type);
|
||||
}
|
||||
}
|
||||
|
||||
static int shutdown_om(struct gsm_bts *bts)
|
||||
{
|
||||
LOGP(DNM, LOGL_NOTICE, "shutting down OML for BTS %u\n", bts->nr);
|
||||
|
||||
/* stop sending event reports */
|
||||
abis_nm_event_reports(bts, 0);
|
||||
|
||||
/* begin DB transmission */
|
||||
abis_nm_bs11_db_transmission(bts, 1);
|
||||
|
||||
/* end DB transmission */
|
||||
abis_nm_bs11_db_transmission(bts, 0);
|
||||
|
||||
/* Reset BTS Site manager resource */
|
||||
abis_nm_bs11_reset_resource(bts);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bsc_shutdown_net(struct gsm_network *net)
|
||||
{
|
||||
struct gsm_bts *bts;
|
||||
|
||||
llist_for_each_entry(bts, &net->bts_list, list) {
|
||||
int rc;
|
||||
rc = shutdown_om(bts);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
LOGP(DNM, LOGL_NOTICE, "shutting down OML for BTS %u\n", bts->nr);
|
||||
dispatch_signal(SS_GLOBAL, S_GLOBAL_BTS_CLOSE_OM, bts);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -858,98 +165,6 @@ err_out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void patch_16(uint8_t *data, const uint16_t val)
|
||||
{
|
||||
memcpy(data, &val, sizeof(val));
|
||||
}
|
||||
|
||||
static void patch_32(uint8_t *data, const uint32_t val)
|
||||
{
|
||||
memcpy(data, &val, sizeof(val));
|
||||
}
|
||||
|
||||
/*
|
||||
* Patch the various SYSTEM INFORMATION tables to update
|
||||
* the LAI
|
||||
*/
|
||||
static void patch_nm_tables(struct gsm_bts *bts)
|
||||
{
|
||||
u_int8_t arfcn_low = bts->c0->arfcn & 0xff;
|
||||
u_int8_t arfcn_high = (bts->c0->arfcn >> 8) & 0x0f;
|
||||
|
||||
/* patch ARFCN into BTS Attributes */
|
||||
bs11_attr_bts[69] &= 0xf0;
|
||||
bs11_attr_bts[69] |= arfcn_high;
|
||||
bs11_attr_bts[70] = arfcn_low;
|
||||
nanobts_attr_bts[42] &= 0xf0;
|
||||
nanobts_attr_bts[42] |= arfcn_high;
|
||||
nanobts_attr_bts[43] = arfcn_low;
|
||||
|
||||
/* patch ARFCN into TRX Attributes */
|
||||
bs11_attr_radio[2] &= 0xf0;
|
||||
bs11_attr_radio[2] |= arfcn_high;
|
||||
bs11_attr_radio[3] = arfcn_low;
|
||||
|
||||
/* patch the RACH attributes */
|
||||
if (bts->rach_b_thresh != -1) {
|
||||
nanobts_attr_bts[33] = bts->rach_b_thresh & 0xff;
|
||||
bs11_attr_bts[33] = bts->rach_b_thresh & 0xff;
|
||||
}
|
||||
|
||||
if (bts->rach_ldavg_slots != -1) {
|
||||
u_int8_t avg_high = bts->rach_ldavg_slots & 0xff;
|
||||
u_int8_t avg_low = (bts->rach_ldavg_slots >> 8) & 0x0f;
|
||||
|
||||
nanobts_attr_bts[35] = avg_high;
|
||||
nanobts_attr_bts[36] = avg_low;
|
||||
bs11_attr_bts[35] = avg_high;
|
||||
bs11_attr_bts[36] = avg_low;
|
||||
}
|
||||
|
||||
/* patch BSIC */
|
||||
bs11_attr_bts[1] = bts->bsic;
|
||||
nanobts_attr_bts[sizeof(nanobts_attr_bts)-11] = bts->bsic;
|
||||
|
||||
/* patch CGI */
|
||||
abis_nm_ipaccess_cgi(nanobts_attr_bts+sizeof(nanobts_attr_bts)-7, bts);
|
||||
|
||||
/* patch the power reduction */
|
||||
bs11_attr_radio[5] = bts->c0->max_power_red / 2;
|
||||
nanobts_attr_radio[1] = bts->c0->max_power_red / 2;
|
||||
|
||||
/* patch NSEI */
|
||||
nanobts_attr_nse[3] = bts->gprs.nse.nsei >> 8;
|
||||
nanobts_attr_nse[4] = bts->gprs.nse.nsei & 0xff;
|
||||
memcpy(nanobts_attr_nse+8, bts->gprs.nse.timer,
|
||||
ARRAY_SIZE(bts->gprs.nse.timer));
|
||||
memcpy(nanobts_attr_nse+18, bts->gprs.cell.timer,
|
||||
ARRAY_SIZE(bts->gprs.cell.timer));
|
||||
|
||||
/* patch NSVCI */
|
||||
nanobts_attr_nsvc0[3] = bts->gprs.nsvc[0].nsvci >> 8;
|
||||
nanobts_attr_nsvc0[4] = bts->gprs.nsvc[0].nsvci & 0xff;
|
||||
|
||||
/* patch IP address as SGSN IP */
|
||||
patch_16(nanobts_attr_nsvc0 + 8,
|
||||
htons(bts->gprs.nsvc[0].remote_port));
|
||||
patch_32(nanobts_attr_nsvc0 + 10,
|
||||
htonl(bts->gprs.nsvc[0].remote_ip));
|
||||
patch_16(nanobts_attr_nsvc0 + 14,
|
||||
htons(bts->gprs.nsvc[0].local_port));
|
||||
|
||||
/* patch BVCI */
|
||||
nanobts_attr_cell[12] = bts->gprs.cell.bvci >> 8;
|
||||
nanobts_attr_cell[13] = bts->gprs.cell.bvci & 0xff;
|
||||
/* patch RAC */
|
||||
nanobts_attr_cell[3] = bts->gprs.rac;
|
||||
|
||||
if (bts->gprs.mode == BTS_GPRS_EGPRS) {
|
||||
/* patch EGPRS coding schemes MCS 1..9 */
|
||||
nanobts_attr_cell[29] = 0x8f;
|
||||
nanobts_attr_cell[30] = 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
/* Produce a MA as specified in 10.5.2.21 */
|
||||
static int generate_ma_for_ts(struct gsm_bts_trx_ts *ts)
|
||||
{
|
||||
@@ -1023,29 +238,28 @@ static void bootstrap_rsl(struct gsm_bts_trx *trx)
|
||||
generate_ma_for_ts(&trx->ts[i]);
|
||||
}
|
||||
|
||||
void input_event(int event, enum e1inp_sign_type type, struct gsm_bts_trx *trx)
|
||||
/* Callback function to be called every time we receive a signal from INPUT */
|
||||
static int inp_sig_cb(unsigned int subsys, unsigned int signal,
|
||||
void *handler_data, void *signal_data)
|
||||
{
|
||||
struct input_signal_data *isd = signal_data;
|
||||
struct gsm_bts_trx *trx = isd->trx;
|
||||
int ts_no, lchan_no;
|
||||
|
||||
switch (event) {
|
||||
case EVT_E1_TEI_UP:
|
||||
switch (type) {
|
||||
case E1INP_SIGN_OML:
|
||||
bootstrap_om(trx->bts);
|
||||
break;
|
||||
case E1INP_SIGN_RSL:
|
||||
bootstrap_rsl(trx);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case EVT_E1_TEI_DN:
|
||||
LOGP(DMI, LOGL_ERROR, "Lost some E1 TEI link: %d %p\n", type, trx);
|
||||
if (subsys != SS_INPUT)
|
||||
return -EINVAL;
|
||||
|
||||
if (type == E1INP_SIGN_OML)
|
||||
switch (signal) {
|
||||
case S_INP_TEI_UP:
|
||||
if (isd->link_type == E1INP_SIGN_RSL)
|
||||
bootstrap_rsl(trx);
|
||||
break;
|
||||
case S_INP_TEI_DN:
|
||||
LOGP(DMI, LOGL_ERROR, "Lost some E1 TEI link: %d %p\n", isd->link_type, trx);
|
||||
|
||||
if (isd->link_type == E1INP_SIGN_OML)
|
||||
counter_inc(trx->bts->network->stats.bts.oml_fail);
|
||||
else if (type == E1INP_SIGN_RSL)
|
||||
else if (isd->link_type == E1INP_SIGN_RSL)
|
||||
counter_inc(trx->bts->network->stats.bts.rsl_fail);
|
||||
|
||||
/*
|
||||
@@ -1070,10 +284,14 @@ void input_event(int event, enum e1inp_sign_type type, struct gsm_bts_trx *trx)
|
||||
trx->nm_state.availability = 0;
|
||||
trx->bb_transc.nm_state.operational = 0;
|
||||
trx->bb_transc.nm_state.availability = 0;
|
||||
|
||||
abis_nm_clear_queue(trx->bts);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bootstrap_bts(struct gsm_bts *bts)
|
||||
@@ -1125,6 +343,8 @@ static int bootstrap_bts(struct gsm_bts *bts)
|
||||
/* Control Channel Description */
|
||||
bts->si_common.chan_desc.att = 1;
|
||||
bts->si_common.chan_desc.bs_pa_mfrms = RSL_BS_PA_MFRMS_5;
|
||||
bts->si_common.chan_desc.bs_ag_blks_res = 1;
|
||||
|
||||
/* T3212 is set from vty/config */
|
||||
|
||||
/* Set ccch config by looking at ts config */
|
||||
@@ -1172,7 +392,7 @@ static int bootstrap_bts(struct gsm_bts *bts)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bsc_bootstrap_network(int (*mncc_recv)(struct gsm_network *, int, void *),
|
||||
int bsc_bootstrap_network(int (*mncc_recv)(struct gsm_network *, struct msgb *),
|
||||
const char *config_file)
|
||||
{
|
||||
struct telnet_connection dummy_conn;
|
||||
@@ -1200,14 +420,17 @@ int bsc_bootstrap_network(int (*mncc_recv)(struct gsm_network *, int, void *),
|
||||
return rc;
|
||||
|
||||
register_signal_handler(SS_NM, nm_sig_cb, NULL);
|
||||
register_signal_handler(SS_INPUT, inp_sig_cb, NULL);
|
||||
|
||||
llist_for_each_entry(bts, &bsc_gsmnet->bts_list, list) {
|
||||
bootstrap_bts(bts);
|
||||
if (!is_ipaccess_bts(bts))
|
||||
rc = e1_reconfig_bts(bts);
|
||||
|
||||
if (rc < 0)
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "Error in E1 input driver setup\n");
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
/* initialize nanoBTS support omce */
|
||||
|
||||
@@ -5,18 +5,17 @@
|
||||
* All Rights Reserved
|
||||
*
|
||||
* 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 2 of the License, or
|
||||
* 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.
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
@@ -6,18 +6,17 @@
|
||||
* All Rights Reserved
|
||||
*
|
||||
* 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 2 of the License, or
|
||||
* 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.
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
@@ -3,18 +3,17 @@
|
||||
* All Rights Reserved
|
||||
*
|
||||
* 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 2 of the License, or
|
||||
* 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.
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -22,9 +21,9 @@
|
||||
|
||||
const char *openbsc_copyright =
|
||||
"Copyright (C) 2008-2010 Harald Welte, Holger Freyther\r\n"
|
||||
"Contributions by Daniel Willmann, Jan Lübbe,Stefan Schmidt\r\n"
|
||||
"Dieter Spaar, Andreas Eversberg\r\n\r\n"
|
||||
"License GPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/gpl.html>\r\n"
|
||||
"Contributions by Daniel Willmann, Jan Lübbe, Stefan Schmidt\r\n"
|
||||
"Dieter Spaar, Andreas Eversberg, Sylvain Munaut\r\n\r\n"
|
||||
"License AGPLv3+: GNU AGPL version 3 or later <http://gnu.org/licenses/agpl-3.0.html>\r\n"
|
||||
"This is free software: you are free to change and redistribute it.\r\n"
|
||||
"There is NO WARRANTY, to the extent permitted by law.\r\n";
|
||||
|
||||
|
||||
@@ -3,18 +3,17 @@
|
||||
* All Rights Reserved
|
||||
*
|
||||
* 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 2 of the License, or
|
||||
* 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.
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -34,6 +33,7 @@
|
||||
#include <openbsc/gsm_data.h>
|
||||
#include <openbsc/e1_input.h>
|
||||
#include <openbsc/abis_nm.h>
|
||||
#include <openbsc/abis_om2000.h>
|
||||
#include <osmocore/utils.h>
|
||||
#include <osmocore/gsm_utils.h>
|
||||
#include <openbsc/chan_alloc.h>
|
||||
@@ -44,6 +44,11 @@
|
||||
#include <openbsc/gprs_ns.h>
|
||||
#include <openbsc/system_information.h>
|
||||
#include <openbsc/debug.h>
|
||||
#include <openbsc/paging.h>
|
||||
#include <openbsc/ipaccess.h>
|
||||
#include <openbsc/abis_rsl.h>
|
||||
#include <openbsc/osmo_msc_data.h>
|
||||
#include <openbsc/osmo_bsc_rf.h>
|
||||
|
||||
#include "../bscconfig.h"
|
||||
|
||||
@@ -74,6 +79,13 @@ static const struct value_string gprs_bssgp_cfg_strs[] = {
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
static const struct value_string bts_neigh_mode_strs[] = {
|
||||
{ NL_MODE_AUTOMATIC, "automatic" },
|
||||
{ NL_MODE_MANUAL, "manual" },
|
||||
{ NL_MODE_MANUAL_SI5SEP, "manual-si5" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
struct cmd_node net_node = {
|
||||
GSMNET_NODE,
|
||||
"%s(network)#",
|
||||
@@ -175,6 +187,12 @@ static void net_dump_vty(struct vty *vty, struct gsm_network *net)
|
||||
network_chan_load(&pl, net);
|
||||
vty_out(vty, " Current Channel Load:%s", VTY_NEWLINE);
|
||||
dump_pchan_load_vty(vty, " ", &pl);
|
||||
|
||||
/* show rf */
|
||||
if (net->msc_data)
|
||||
vty_out(vty, " Last RF Command: %s%s",
|
||||
net->msc_data->rf_ctl->last_state_command,
|
||||
VTY_NEWLINE);
|
||||
}
|
||||
|
||||
DEFUN(show_net, show_net_cmd, "show network",
|
||||
@@ -241,11 +259,15 @@ static void bts_dump_vty(struct vty *vty, struct gsm_bts *bts)
|
||||
net_dump_nmstate(vty, &bts->site_mgr.nm_state);
|
||||
vty_out(vty, " Paging: FIXME pending requests, %u free slots%s",
|
||||
bts->paging.available_slots, VTY_NEWLINE);
|
||||
if (!is_ipaccess_bts(bts)) {
|
||||
if (is_ipaccess_bts(bts)) {
|
||||
vty_out(vty, " OML Link state: %s.%s",
|
||||
bts->oml_link ? "connected" : "disconnected", VTY_NEWLINE);
|
||||
} else {
|
||||
vty_out(vty, " E1 Signalling Link:%s", VTY_NEWLINE);
|
||||
e1isl_dump_vty(vty, bts->oml_link);
|
||||
}
|
||||
/* FIXME: oml_link, chan_desc */
|
||||
|
||||
/* FIXME: chan_desc */
|
||||
memset(&pl, 0, sizeof(pl));
|
||||
bts_chan_load(&pl, bts);
|
||||
vty_out(vty, " Current Channel Load:%s", VTY_NEWLINE);
|
||||
@@ -262,7 +284,7 @@ DEFUN(show_bts, show_bts_cmd, "show bts [number]",
|
||||
if (argc != 0) {
|
||||
/* use the BTS number that the user has specified */
|
||||
bts_nr = atoi(argv[0]);
|
||||
if (bts_nr > net->num_bts) {
|
||||
if (bts_nr >= net->num_bts) {
|
||||
vty_out(vty, "%% can't find BTS '%s'%s", argv[0],
|
||||
VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
@@ -325,8 +347,11 @@ static void config_write_ts_single(struct vty *vty, struct gsm_bts_trx_ts *ts)
|
||||
vty_out(vty, " hopping arfcn add %u%s",
|
||||
i, VTY_NEWLINE);
|
||||
}
|
||||
} else
|
||||
}
|
||||
config_write_e1_link(vty, &ts->e1_link, " ");
|
||||
|
||||
if (ts->trx->bts->model->config_write_ts)
|
||||
ts->trx->bts->model->config_write_ts(vty, ts);
|
||||
}
|
||||
|
||||
static void config_write_trx_single(struct vty *vty, struct gsm_bts_trx *trx)
|
||||
@@ -346,6 +371,9 @@ static void config_write_trx_single(struct vty *vty, struct gsm_bts_trx *trx)
|
||||
config_write_e1_link(vty, &trx->rsl_e1_link, " rsl ");
|
||||
vty_out(vty, " rsl e1 tei %u%s", trx->rsl_tei, VTY_NEWLINE);
|
||||
|
||||
if (trx->bts->model->config_write_trx)
|
||||
trx->bts->model->config_write_trx(vty, trx);
|
||||
|
||||
for (i = 0; i < TRX_NR_TS; i++)
|
||||
config_write_ts_single(vty, &trx->ts[i]);
|
||||
}
|
||||
@@ -409,6 +437,34 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts)
|
||||
bts->si_common.cell_sel_par.cell_resel_hyst*2, VTY_NEWLINE);
|
||||
vty_out(vty, " rxlev access min %u%s",
|
||||
bts->si_common.cell_sel_par.rxlev_acc_min, VTY_NEWLINE);
|
||||
|
||||
if (bts->si_common.cell_ro_sel_par.present) {
|
||||
struct gsm48_si_selection_params *sp;
|
||||
sp = &bts->si_common.cell_ro_sel_par;
|
||||
|
||||
if (sp->cbq)
|
||||
vty_out(vty, " cell bar qualify %u%s",
|
||||
sp->cbq, VTY_NEWLINE);
|
||||
|
||||
if (sp->cell_resel_off)
|
||||
vty_out(vty, " cell reselection offset %u%s",
|
||||
sp->cell_resel_off*2, VTY_NEWLINE);
|
||||
|
||||
if (sp->temp_offs == 7)
|
||||
vty_out(vty, " temporary offset infinite%s",
|
||||
VTY_NEWLINE);
|
||||
else if (sp->temp_offs)
|
||||
vty_out(vty, " temporary offset %u%s",
|
||||
sp->temp_offs*10, VTY_NEWLINE);
|
||||
|
||||
if (sp->penalty_time == 31)
|
||||
vty_out(vty, " penalty time reserved%s",
|
||||
VTY_NEWLINE);
|
||||
else if (sp->penalty_time)
|
||||
vty_out(vty, " penalty time %u%s",
|
||||
(sp->penalty_time*20)+20, VTY_NEWLINE);
|
||||
}
|
||||
|
||||
if (bts->si_common.chan_desc.t3212)
|
||||
vty_out(vty, " periodic location update %u%s",
|
||||
bts->si_common.chan_desc.t3212 * 6, VTY_NEWLINE);
|
||||
@@ -454,8 +510,28 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts)
|
||||
if (bts->paging.free_chans_need >= 0)
|
||||
vty_out(vty, " paging free %d%s", bts->paging.free_chans_need, VTY_NEWLINE);
|
||||
|
||||
vty_out(vty, " neighbor-list mode %s%s",
|
||||
get_value_string(bts_neigh_mode_strs, bts->neigh_list_manual_mode), VTY_NEWLINE);
|
||||
if (bts->neigh_list_manual_mode != NL_MODE_AUTOMATIC) {
|
||||
for (i = 0; i < 1024; i++) {
|
||||
if (bitvec_get_bit_pos(&bts->si_common.neigh_list, i))
|
||||
vty_out(vty, " neighbor-list add arfcn %u%s",
|
||||
i, VTY_NEWLINE);
|
||||
}
|
||||
}
|
||||
if (bts->neigh_list_manual_mode == NL_MODE_MANUAL_SI5SEP) {
|
||||
for (i = 0; i < 1024; i++) {
|
||||
if (bitvec_get_bit_pos(&bts->si_common.si5_neigh_list, i))
|
||||
vty_out(vty, " si5 neighbor-list add arfcn %u%s",
|
||||
i, VTY_NEWLINE);
|
||||
}
|
||||
}
|
||||
|
||||
config_write_bts_gprs(vty, bts);
|
||||
|
||||
if (bts->model->config_write_bts)
|
||||
bts->model->config_write_bts(vty, bts);
|
||||
|
||||
llist_for_each_entry(trx, &bts->trx_list, list)
|
||||
config_write_trx_single(vty, trx);
|
||||
}
|
||||
@@ -512,8 +588,11 @@ static int config_write_net(struct vty *vty)
|
||||
vty_out(vty, " timer t3115 %u%s", gsmnet->T3115, VTY_NEWLINE);
|
||||
vty_out(vty, " timer t3117 %u%s", gsmnet->T3117, VTY_NEWLINE);
|
||||
vty_out(vty, " timer t3119 %u%s", gsmnet->T3119, VTY_NEWLINE);
|
||||
vty_out(vty, " timer t3122 %u%s", gsmnet->T3122, VTY_NEWLINE);
|
||||
vty_out(vty, " timer t3141 %u%s", gsmnet->T3141, VTY_NEWLINE);
|
||||
vty_out(vty, " use-dtx %u%s", gsmnet->dtx_enabled, VTY_NEWLINE);
|
||||
vty_out(vty, " dtx-used %u%s", gsmnet->dtx_enabled, VTY_NEWLINE);
|
||||
vty_out(vty, " subscriber-keep-in-ram %d%s",
|
||||
gsmnet->keep_subscr, VTY_NEWLINE);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
@@ -597,9 +676,13 @@ DEFUN(show_trx,
|
||||
|
||||
static void ts_dump_vty(struct vty *vty, struct gsm_bts_trx_ts *ts)
|
||||
{
|
||||
vty_out(vty, "Timeslot %u of TRX %u in BTS %u, phys cfg %s%s",
|
||||
ts->nr, ts->trx->nr, ts->trx->bts->nr,
|
||||
gsm_pchan_name(ts->pchan), VTY_NEWLINE);
|
||||
vty_out(vty, "BTS %u, TRX %u, Timeslot %u, phys cfg %s",
|
||||
ts->trx->bts->nr, ts->trx->nr, ts->nr,
|
||||
gsm_pchan_name(ts->pchan));
|
||||
if (ts->pchan == GSM_PCHAN_TCH_F_PDCH)
|
||||
vty_out(vty, " (%s mode)",
|
||||
ts->flags & TS_F_PDCH_MODE ? "PDCH" : "TCH/F");
|
||||
vty_out(vty, "%s", VTY_NEWLINE);
|
||||
vty_out(vty, " NM State: ");
|
||||
net_dump_nmstate(vty, &ts->nm_state);
|
||||
if (!is_ipaccess_bts(ts->trx->bts))
|
||||
@@ -615,9 +698,9 @@ DEFUN(show_ts,
|
||||
"BTS Number\n" "TRX Number\n" "Timeslot Number\n")
|
||||
{
|
||||
struct gsm_network *net = gsmnet_from_vty(vty);
|
||||
struct gsm_bts *bts;
|
||||
struct gsm_bts_trx *trx;
|
||||
struct gsm_bts_trx_ts *ts;
|
||||
struct gsm_bts *bts = NULL;
|
||||
struct gsm_bts_trx *trx = NULL;
|
||||
struct gsm_bts_trx_ts *ts = NULL;
|
||||
int bts_nr, trx_nr, ts_nr;
|
||||
|
||||
if (argc >= 1) {
|
||||
@@ -646,12 +729,20 @@ DEFUN(show_ts,
|
||||
VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
/* Fully Specified: print and exit */
|
||||
ts = &trx->ts[ts_nr];
|
||||
ts_dump_vty(vty, ts);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
for (bts_nr = 0; bts_nr < net->num_bts; bts_nr++) {
|
||||
bts = gsm_bts_num(net, bts_nr);
|
||||
|
||||
if (bts && trx) {
|
||||
/* Iterate over all TS in this TRX */
|
||||
for (ts_nr = 0; ts_nr < TRX_NR_TS; ts_nr++) {
|
||||
ts = &trx->ts[ts_nr];
|
||||
ts_dump_vty(vty, ts);
|
||||
}
|
||||
} else if (bts) {
|
||||
/* Iterate over all TRX in this BTS, TS in each TRX */
|
||||
for (trx_nr = 0; trx_nr < bts->num_trx; trx_nr++) {
|
||||
trx = gsm_bts_trx_num(bts, trx_nr);
|
||||
for (ts_nr = 0; ts_nr < TRX_NR_TS; ts_nr++) {
|
||||
@@ -659,6 +750,18 @@ DEFUN(show_ts,
|
||||
ts_dump_vty(vty, ts);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Iterate over all BTS, TRX in each BTS, TS in each TRX */
|
||||
for (bts_nr = 0; bts_nr < net->num_bts; bts_nr++) {
|
||||
bts = gsm_bts_num(net, bts_nr);
|
||||
for (trx_nr = 0; trx_nr < bts->num_trx; trx_nr++) {
|
||||
trx = gsm_bts_trx_num(bts, trx_nr);
|
||||
for (ts_nr = 0; ts_nr < TRX_NR_TS; ts_nr++) {
|
||||
ts = &trx->ts[ts_nr];
|
||||
ts_dump_vty(vty, ts);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
@@ -720,10 +823,9 @@ static void lchan_dump_full_vty(struct vty *vty, struct gsm_lchan *lchan)
|
||||
{
|
||||
int idx;
|
||||
|
||||
vty_out(vty, "Lchan %u in Timeslot %u of TRX %u in BTS %u, Type %s%s",
|
||||
lchan->nr, lchan->ts->nr, lchan->ts->trx->nr,
|
||||
lchan->ts->trx->bts->nr, gsm_lchant_name(lchan->type),
|
||||
VTY_NEWLINE);
|
||||
vty_out(vty, "BTS %u, TRX %u, Timeslot %u, Lchan %u: Type %s%s",
|
||||
lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
|
||||
lchan->nr, gsm_lchant_name(lchan->type), VTY_NEWLINE);
|
||||
vty_out(vty, " Connection: %u, State: %s%s",
|
||||
lchan->conn ? 1: 0,
|
||||
gsm_lchans_name(lchan->state), VTY_NEWLINE);
|
||||
@@ -762,11 +864,10 @@ static void lchan_dump_short_vty(struct vty *vty, struct gsm_lchan *lchan)
|
||||
lchan->meas_rep_idx, 1);
|
||||
mr = &lchan->meas_rep[idx];
|
||||
|
||||
vty_out(vty, "Lchan: %u Timeslot: %u TRX: %u BTS: %u Type: %s - L1 MS Power: %u dBm "
|
||||
"RXL-FULL-dl: %4d dBm RXL-FULL-ul: %4d dBm%s",
|
||||
lchan->nr, lchan->ts->nr, lchan->ts->trx->nr,
|
||||
lchan->ts->trx->bts->nr, gsm_lchant_name(lchan->type),
|
||||
mr->ms_l1.pwr,
|
||||
vty_out(vty, "BTS %u, TRX %u, Timeslot %u, Lchan %u, Type %s - "
|
||||
"L1 MS Power: %u dBm RXL-FULL-dl: %4d dBm RXL-FULL-ul: %4d dBm%s",
|
||||
lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
|
||||
lchan->nr, gsm_lchant_name(lchan->type), mr->ms_l1.pwr,
|
||||
rxlev2dbm(mr->dl.full.rx_lev),
|
||||
rxlev2dbm(mr->ul.full.rx_lev),
|
||||
VTY_NEWLINE);
|
||||
@@ -1288,6 +1389,7 @@ DECLARE_TIMER(3113, "Set the time to try paging a subscriber.")
|
||||
DECLARE_TIMER(3115, "Currently not used.")
|
||||
DECLARE_TIMER(3117, "Currently not used.")
|
||||
DECLARE_TIMER(3119, "Currently not used.")
|
||||
DECLARE_TIMER(3122, "Waiting time (seconds) after IMM ASS REJECT")
|
||||
DECLARE_TIMER(3141, "Currently not used.")
|
||||
|
||||
DEFUN(cfg_net_dtx,
|
||||
@@ -1301,6 +1403,17 @@ DEFUN(cfg_net_dtx,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_net_subscr_keep,
|
||||
cfg_net_subscr_keep_cmd,
|
||||
"subscriber-keep-in-ram (0|1)",
|
||||
"Keep unused subscribers in RAM.\n"
|
||||
"Delete unused subscribers\n" "Keep unused subscribers\n")
|
||||
{
|
||||
struct gsm_network *gsmnet = gsmnet_from_vty(vty);
|
||||
gsmnet->keep_subscr = atoi(argv[0]);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
/* per-BTS configuration */
|
||||
DEFUN(cfg_bts,
|
||||
cfg_bts_cmd,
|
||||
@@ -1644,6 +1757,80 @@ DEFUN(cfg_bts_rxlev_acc_min, cfg_bts_rxlev_acc_min_cmd,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_bts_cell_bar_qualify, cfg_bts_cell_bar_qualify_cmd,
|
||||
"cell bar qualify (0|1)",
|
||||
"Cell Bar Qualify")
|
||||
{
|
||||
struct gsm_bts *bts = vty->index;
|
||||
|
||||
bts->si_common.cell_ro_sel_par.present = 1;
|
||||
bts->si_common.cell_ro_sel_par.cbq = atoi(argv[0]);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_bts_cell_resel_ofs, cfg_bts_cell_resel_ofs_cmd,
|
||||
"cell reselection offset <0-126>",
|
||||
"Cell Re-Selection Offset in dB")
|
||||
{
|
||||
struct gsm_bts *bts = vty->index;
|
||||
|
||||
bts->si_common.cell_ro_sel_par.present = 1;
|
||||
bts->si_common.cell_ro_sel_par.cell_resel_off = atoi(argv[0])/2;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_bts_temp_ofs, cfg_bts_temp_ofs_cmd,
|
||||
"temporary offset <0-60>",
|
||||
"Cell selection temporary negative offset in dB")
|
||||
{
|
||||
struct gsm_bts *bts = vty->index;
|
||||
|
||||
bts->si_common.cell_ro_sel_par.present = 1;
|
||||
bts->si_common.cell_ro_sel_par.temp_offs = atoi(argv[0])/10;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_bts_temp_ofs_inf, cfg_bts_temp_ofs_inf_cmd,
|
||||
"temporary offset infinite",
|
||||
"Sets cell selection temporary negative offset to infinity")
|
||||
{
|
||||
struct gsm_bts *bts = vty->index;
|
||||
|
||||
bts->si_common.cell_ro_sel_par.present = 1;
|
||||
bts->si_common.cell_ro_sel_par.temp_offs = 7;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_bts_penalty_time, cfg_bts_penalty_time_cmd,
|
||||
"penalty time <20-620>",
|
||||
"Cell selection penalty time in seconds (by 20s increments)")
|
||||
{
|
||||
struct gsm_bts *bts = vty->index;
|
||||
|
||||
bts->si_common.cell_ro_sel_par.present = 1;
|
||||
bts->si_common.cell_ro_sel_par.penalty_time = (atoi(argv[0])-20)/20;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_bts_penalty_time_rsvd, cfg_bts_penalty_time_rsvd_cmd,
|
||||
"penalty time reserved",
|
||||
"Set cell selection penalty time to reserved value 31\n"
|
||||
"(indicate that CELL_RESELECT_OFFSET is subtracted from C2 "
|
||||
"and TEMPORARY_OFFSET is ignored)")
|
||||
{
|
||||
struct gsm_bts *bts = vty->index;
|
||||
|
||||
bts->si_common.cell_ro_sel_par.present = 1;
|
||||
bts->si_common.cell_ro_sel_par.penalty_time = 31;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_bts_per_loc_upd, cfg_bts_per_loc_upd_cmd,
|
||||
"periodic location update <0-1530>",
|
||||
"Periodic Location Updating Interval in Minutes")
|
||||
@@ -1971,6 +2158,80 @@ DEFUN(cfg_bts_si_static, cfg_bts_si_static_cmd,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_bts_neigh_mode, cfg_bts_neigh_mode_cmd,
|
||||
"neighbor-list mode (automatic|manual|manual-si5)",
|
||||
"Neighbor List\n" "Mode of Neighbor List generation\n"
|
||||
"Automatically from all BTS in this OpenBSC\n" "Manual\n"
|
||||
"Manual with different lists for SI2 and SI5\n")
|
||||
{
|
||||
struct gsm_bts *bts = vty->index;
|
||||
int mode = get_string_value(bts_neigh_mode_strs, argv[0]);
|
||||
|
||||
switch (mode) {
|
||||
case NL_MODE_MANUAL_SI5SEP:
|
||||
case NL_MODE_MANUAL:
|
||||
/* make sure we clear the current list when switching to
|
||||
* manual mode */
|
||||
if (bts->neigh_list_manual_mode == 0)
|
||||
memset(&bts->si_common.data.neigh_list, 0,
|
||||
sizeof(bts->si_common.data.neigh_list));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
bts->neigh_list_manual_mode = mode;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_bts_neigh, cfg_bts_neigh_cmd,
|
||||
"neighbor-list (add|del) arfcn <0-1024>",
|
||||
"Neighbor List\n" "Add to manual neighbor list\n"
|
||||
"Delete from manual neighbor list\n" "ARFCN of neighbor\n"
|
||||
"ARFCN of neighbor\n")
|
||||
{
|
||||
struct gsm_bts *bts = vty->index;
|
||||
struct bitvec *bv = &bts->si_common.neigh_list;
|
||||
uint16_t arfcn = atoi(argv[1]);
|
||||
|
||||
if (!bts->neigh_list_manual_mode) {
|
||||
vty_out(vty, "%% Cannot configure neighbor list in "
|
||||
"automatic mode%s", VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
if (!strcmp(argv[0], "add"))
|
||||
bitvec_set_bit_pos(bv, arfcn, 1);
|
||||
else
|
||||
bitvec_set_bit_pos(bv, arfcn, 0);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_bts_si5_neigh, cfg_bts_si5_neigh_cmd,
|
||||
"si5 neighbor-list (add|del) arfcn <0-1024>",
|
||||
"SI5 Neighbor List\n" "Add to manual SI5 neighbor list\n"
|
||||
"Delete from SI5 manual neighbor list\n" "ARFCN of neighbor\n"
|
||||
"ARFCN of neighbor\n")
|
||||
{
|
||||
struct gsm_bts *bts = vty->index;
|
||||
struct bitvec *bv = &bts->si_common.si5_neigh_list;
|
||||
uint16_t arfcn = atoi(argv[1]);
|
||||
|
||||
if (!bts->neigh_list_manual_mode) {
|
||||
vty_out(vty, "%% Cannot configure neighbor list in "
|
||||
"automatic mode%s", VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
if (!strcmp(argv[0], "add"))
|
||||
bitvec_set_bit_pos(bv, arfcn, 1);
|
||||
else
|
||||
bitvec_set_bit_pos(bv, arfcn, 0);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
#define TRX_TEXT "Radio Transceiver\n"
|
||||
|
||||
@@ -2252,18 +2513,16 @@ DEFUN(logging_fltr_imsi,
|
||||
LOGGING_STR FILTER_STR
|
||||
"Filter log messages by IMSI\n" "IMSI to be used as filter\n")
|
||||
{
|
||||
struct telnet_connection *conn;
|
||||
struct log_target *tgt = osmo_log_vty2tgt(vty);
|
||||
|
||||
conn = (struct telnet_connection *) vty->priv;
|
||||
if (!conn->dbg) {
|
||||
vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
|
||||
if (!tgt)
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
log_set_imsi_filter(conn->dbg, argv[0]);
|
||||
log_set_imsi_filter(tgt, argv[0]);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
DEFUN(drop_bts,
|
||||
drop_bts_cmd,
|
||||
"drop bts connection <0-65535> (oml|rsl)",
|
||||
@@ -2298,13 +2557,11 @@ DEFUN(drop_bts,
|
||||
|
||||
/* close all connections */
|
||||
if (strcmp(argv[1], "oml") == 0) {
|
||||
if (bts->oml_link)
|
||||
close(bts->oml_link->ts->driver.ipaccess.fd.fd);
|
||||
ipaccess_drop_oml(bts);
|
||||
} else if (strcmp(argv[1], "rsl") == 0) {
|
||||
/* close all rsl connections */
|
||||
llist_for_each_entry(trx, &bts->trx_list, list) {
|
||||
if (trx->rsl_link)
|
||||
close(trx->rsl_link->ts->driver.ipaccess.fd.fd);
|
||||
ipaccess_drop_rsl(trx);
|
||||
}
|
||||
} else {
|
||||
vty_out(vty, "Argument must be 'oml# or 'rsl'.%s", VTY_NEWLINE);
|
||||
@@ -2314,6 +2571,56 @@ DEFUN(drop_bts,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(pdch_act, pdch_act_cmd,
|
||||
"bts <0-255> trx <0-255> timeslot <0-7> pdch (activate|deactivate)",
|
||||
"BTS related commands\n" "BTS Number\n" "Transceiver\n" "Transceiver Number\n"
|
||||
"TRX Timeslot\n" "Timeslot Number\n" "Packet Data Channel\n"
|
||||
"Activate Dynamic PDCH/TCH (-> PDCH mode)\n"
|
||||
"Deactivate Dynamic PDCH/TCH (-> TCH mode)\n")
|
||||
{
|
||||
struct gsm_bts *bts;
|
||||
struct gsm_bts_trx *trx;
|
||||
struct gsm_bts_trx_ts *ts;
|
||||
int bts_nr = atoi(argv[0]);
|
||||
int trx_nr = atoi(argv[1]);
|
||||
int ts_nr = atoi(argv[2]);
|
||||
int activate;
|
||||
|
||||
bts = gsm_bts_num(bsc_gsmnet, bts_nr);
|
||||
if (!bts) {
|
||||
vty_out(vty, "%% No such BTS (%d)%s", bts_nr, VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
if (!is_ipaccess_bts(bts)) {
|
||||
vty_out(vty, "%% This command only works for ipaccess BTS%s",
|
||||
VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
trx = gsm_bts_trx_num(bts, trx_nr);
|
||||
if (!trx) {
|
||||
vty_out(vty, "%% No such TRX (%d)%s", trx_nr, VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
ts = &trx->ts[ts_nr];
|
||||
if (ts->pchan != GSM_PCHAN_TCH_F_PDCH) {
|
||||
vty_out(vty, "%% Timeslot %u is not in dynamic TCH_F/PDCH "
|
||||
"mode%s", ts_nr, VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
if (!strcmp(argv[3], "activate"))
|
||||
activate = 1;
|
||||
else
|
||||
activate = 0;
|
||||
|
||||
rsl_ipacc_pdch_activate(ts, activate);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
|
||||
}
|
||||
|
||||
extern int bsc_vty_init_extra(void);
|
||||
extern const char *openbsc_copyright;
|
||||
@@ -2335,6 +2642,7 @@ int bsc_vty_init(void)
|
||||
install_element_ve(&show_paging_cmd);
|
||||
|
||||
logging_vty_add_cmds();
|
||||
install_element(CFG_LOG_NODE, &logging_fltr_imsi_cmd);
|
||||
|
||||
install_element(CONFIG_NODE, &cfg_net_cmd);
|
||||
install_node(&net_node, config_write_net);
|
||||
@@ -2368,8 +2676,10 @@ int bsc_vty_init(void)
|
||||
install_element(GSMNET_NODE, &cfg_net_T3115_cmd);
|
||||
install_element(GSMNET_NODE, &cfg_net_T3117_cmd);
|
||||
install_element(GSMNET_NODE, &cfg_net_T3119_cmd);
|
||||
install_element(GSMNET_NODE, &cfg_net_T3122_cmd);
|
||||
install_element(GSMNET_NODE, &cfg_net_T3141_cmd);
|
||||
install_element(GSMNET_NODE, &cfg_net_dtx_cmd);
|
||||
install_element(GSMNET_NODE, &cfg_net_subscr_keep_cmd);
|
||||
install_element(GSMNET_NODE, &cfg_net_pag_any_tch_cmd);
|
||||
|
||||
install_element(GSMNET_NODE, &cfg_bts_cmd);
|
||||
@@ -2400,6 +2710,12 @@ int bsc_vty_init(void)
|
||||
install_element(BTS_NODE, &cfg_bts_per_loc_upd_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_cell_resel_hyst_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_rxlev_acc_min_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_cell_bar_qualify_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_cell_resel_ofs_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_temp_ofs_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_temp_ofs_inf_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_penalty_time_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_penalty_time_rsvd_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_gprs_mode_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_gprs_ns_timer_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_gprs_rac_cmd);
|
||||
@@ -2413,6 +2729,9 @@ int bsc_vty_init(void)
|
||||
install_element(BTS_NODE, &cfg_bts_pag_free_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_si_mode_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_si_static_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_neigh_mode_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_neigh_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_si5_neigh_cmd);
|
||||
|
||||
install_element(BTS_NODE, &cfg_trx_cmd);
|
||||
install_node(&trx_node, dummy_config_write);
|
||||
@@ -2442,8 +2761,11 @@ int bsc_vty_init(void)
|
||||
install_element(TS_NODE, &cfg_ts_e1_subslot_cmd);
|
||||
|
||||
install_element(ENABLE_NODE, &drop_bts_cmd);
|
||||
install_element(ENABLE_NODE, &pdch_act_cmd);
|
||||
|
||||
abis_nm_vty_init();
|
||||
abis_om2k_vty_init();
|
||||
e1inp_vty_init();
|
||||
|
||||
bsc_vty_init_extra();
|
||||
|
||||
|
||||
164
openbsc/src/bts_ericsson_rbs2000.c
Normal file
164
openbsc/src/bts_ericsson_rbs2000.c
Normal file
@@ -0,0 +1,164 @@
|
||||
/* Ericsson RBS-2xxx specific code */
|
||||
|
||||
/* (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 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 <sys/types.h>
|
||||
|
||||
#include <osmocore/tlv.h>
|
||||
|
||||
#include <openbsc/debug.h>
|
||||
#include <openbsc/gsm_data.h>
|
||||
#include <openbsc/abis_om2000.h>
|
||||
#include <openbsc/e1_input.h>
|
||||
#include <openbsc/signal.h>
|
||||
|
||||
#include "input/lapd.h"
|
||||
|
||||
static void bootstrap_om_bts(struct gsm_bts *bts)
|
||||
{
|
||||
LOGP(DNM, LOGL_NOTICE, "bootstrapping OML for BTS %u\n", bts->nr);
|
||||
abis_om2k_tx_start_req(bts, &om2k_mo_cf);
|
||||
/* FIXME */
|
||||
}
|
||||
|
||||
static void bootstrap_om_trx(struct gsm_bts_trx *trx)
|
||||
{
|
||||
LOGP(DNM, LOGL_NOTICE, "bootstrapping OML for TRX %u/%u\n",
|
||||
trx->bts->nr, trx->nr);
|
||||
/* FIXME */
|
||||
}
|
||||
|
||||
static int shutdown_om(struct gsm_bts *bts)
|
||||
{
|
||||
/* FIXME */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Tell LAPD to start start the SAP (send SABM requests) for all signalling
|
||||
* timeslots in this line */
|
||||
static void start_sabm_in_line(struct e1inp_line *line, int start)
|
||||
{
|
||||
struct e1inp_sign_link *link;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(line->ts); i++) {
|
||||
struct e1inp_ts *ts = &line->ts[i];
|
||||
|
||||
if (ts->type != E1INP_TS_TYPE_SIGN)
|
||||
continue;
|
||||
|
||||
llist_for_each_entry(link, &ts->sign.sign_links, list) {
|
||||
if (start)
|
||||
lapd_sap_start(ts->driver.dahdi.lapd, link->tei, link->sapi);
|
||||
else
|
||||
lapd_sap_stop(ts->driver.dahdi.lapd, link->tei, link->sapi);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Callback function to be called every time we receive a signal from INPUT */
|
||||
static int gbl_sig_cb(unsigned int subsys, unsigned int signal,
|
||||
void *handler_data, void *signal_data)
|
||||
{
|
||||
struct gsm_bts *bts;
|
||||
|
||||
if (subsys != SS_GLOBAL)
|
||||
return 0;
|
||||
|
||||
switch (signal) {
|
||||
case S_GLOBAL_BTS_CLOSE_OM:
|
||||
bts = signal_data;
|
||||
if (bts->type == GSM_BTS_TYPE_RBS2000)
|
||||
shutdown_om(signal_data);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Callback function to be called every time we receive a signal from INPUT */
|
||||
static int inp_sig_cb(unsigned int subsys, unsigned int signal,
|
||||
void *handler_data, void *signal_data)
|
||||
{
|
||||
struct input_signal_data *isd = signal_data;
|
||||
|
||||
if (subsys != SS_INPUT)
|
||||
return 0;
|
||||
|
||||
switch (signal) {
|
||||
case S_INP_TEI_UP:
|
||||
switch (isd->link_type) {
|
||||
case E1INP_SIGN_OML:
|
||||
if (isd->trx->bts->type != GSM_BTS_TYPE_RBS2000)
|
||||
break;
|
||||
if (isd->tei == isd->trx->bts->oml_tei)
|
||||
bootstrap_om_bts(isd->trx->bts);
|
||||
else
|
||||
bootstrap_om_trx(isd->trx);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case S_INP_LINE_INIT:
|
||||
/* Right now Ericsson RBS are only supported on DAHDI */
|
||||
if (strcasecmp(isd->line->driver->name, "DAHDI"))
|
||||
break;
|
||||
start_sabm_in_line(isd->line, 1);
|
||||
break;
|
||||
case S_INP_LINE_ALARM:
|
||||
if (strcasecmp(isd->line->driver->name, "DAHDI"))
|
||||
break;
|
||||
start_sabm_in_line(isd->line, 0);
|
||||
break;
|
||||
case S_INP_LINE_NOALARM:
|
||||
if (strcasecmp(isd->line->driver->name, "DAHDI"))
|
||||
break;
|
||||
start_sabm_in_line(isd->line, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void config_write_bts(struct vty *vty, struct gsm_bts *bts)
|
||||
{
|
||||
abis_om2k_config_write_bts(vty, bts);
|
||||
}
|
||||
|
||||
static struct gsm_bts_model model_rbs2k = {
|
||||
.type = GSM_BTS_TYPE_RBS2000,
|
||||
.name = "rbs2000",
|
||||
.oml_rcvmsg = &abis_om2k_rcvmsg,
|
||||
.config_write_bts = &config_write_bts,
|
||||
};
|
||||
|
||||
int bts_model_rbs2k_init(void)
|
||||
{
|
||||
model_rbs2k.features.data = &model_rbs2k._features_data[0];
|
||||
model_rbs2k.features.data_len = sizeof(model_rbs2k._features_data);
|
||||
|
||||
gsm_btsmodel_set_feature(&model_rbs2k, BTS_FEAT_HOPPING);
|
||||
gsm_btsmodel_set_feature(&model_rbs2k, BTS_FEAT_HSCSD);
|
||||
|
||||
register_signal_handler(SS_INPUT, inp_sig_cb, NULL);
|
||||
register_signal_handler(SS_GLOBAL, gbl_sig_cb, NULL);
|
||||
|
||||
return gsm_bts_model_register(&model_rbs2k);
|
||||
}
|
||||
@@ -5,29 +5,33 @@
|
||||
* All Rights Reserved
|
||||
*
|
||||
* 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 2 of the License, or
|
||||
* 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.
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* 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 <sys/types.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <osmocore/tlv.h>
|
||||
|
||||
#include <openbsc/gsm_data.h>
|
||||
#include <osmocore/tlv.h>
|
||||
#include <openbsc/signal.h>
|
||||
#include <openbsc/abis_nm.h>
|
||||
|
||||
static struct gsm_bts_model model_nanobts = {
|
||||
.type = GSM_BTS_TYPE_NANOBTS,
|
||||
.name = "nanobts",
|
||||
.oml_rcvmsg = &abis_nm_rcvmsg,
|
||||
.nm_att_tlvdef = {
|
||||
.def = {
|
||||
/* ip.access specifics */
|
||||
@@ -77,6 +81,358 @@ static struct gsm_bts_model model_nanobts = {
|
||||
},
|
||||
};
|
||||
|
||||
static unsigned char nanobts_attr_bts[] = {
|
||||
NM_ATT_INTERF_BOUND, 0x55, 0x5b, 0x61, 0x67, 0x6d, 0x73,
|
||||
/* interference avg. period in numbers of SACCH multifr */
|
||||
NM_ATT_INTAVE_PARAM, 0x06,
|
||||
/* conn fail based on SACCH error rate */
|
||||
NM_ATT_CONN_FAIL_CRIT, 0x00, 0x02, 0x01, 0x10,
|
||||
NM_ATT_T200, 0x1e, 0x24, 0x24, 0xa8, 0x34, 0x21, 0xa8,
|
||||
NM_ATT_MAX_TA, 0x3f,
|
||||
NM_ATT_OVERL_PERIOD, 0x00, 0x01, 10, /* seconds */
|
||||
NM_ATT_CCCH_L_T, 10, /* percent */
|
||||
NM_ATT_CCCH_L_I_P, 1, /* seconds */
|
||||
NM_ATT_RACH_B_THRESH, 10, /* busy threshold in - dBm */
|
||||
NM_ATT_LDAVG_SLOTS, 0x03, 0xe8, /* rach load averaging 1000 slots */
|
||||
NM_ATT_BTS_AIR_TIMER, 128, /* miliseconds */
|
||||
NM_ATT_NY1, 10, /* 10 retransmissions of physical config */
|
||||
NM_ATT_BCCH_ARFCN, HARDCODED_ARFCN >> 8, HARDCODED_ARFCN & 0xff,
|
||||
NM_ATT_BSIC, HARDCODED_BSIC,
|
||||
NM_ATT_IPACC_CGI, 0, 7, 0x00, 0xf1, 0x10, 0x00, 0x01, 0x00, 0x00,
|
||||
};
|
||||
|
||||
static unsigned char nanobts_attr_radio[] = {
|
||||
NM_ATT_RF_MAXPOWR_R, 0x0c, /* number of -2dB reduction steps / Pn */
|
||||
NM_ATT_ARFCN_LIST, 0x00, 0x02, HARDCODED_ARFCN >> 8, HARDCODED_ARFCN & 0xff,
|
||||
};
|
||||
|
||||
static unsigned char nanobts_attr_nse[] = {
|
||||
NM_ATT_IPACC_NSEI, 0, 2, 0x03, 0x9d, /* NSEI 925 */
|
||||
NM_ATT_IPACC_NS_CFG, 0, 7, 3, /* (un)blocking timer (Tns-block) */
|
||||
3, /* (un)blocking retries */
|
||||
3, /* reset timer (Tns-reset) */
|
||||
3, /* reset retries */
|
||||
30, /* test timer (Tns-test) */
|
||||
3, /* alive timer (Tns-alive) */
|
||||
10, /* alive retrires */
|
||||
NM_ATT_IPACC_BSSGP_CFG, 0, 11,
|
||||
3, /* blockimg timer (T1) */
|
||||
3, /* blocking retries */
|
||||
3, /* unblocking retries */
|
||||
3, /* reset timer */
|
||||
3, /* reset retries */
|
||||
10, /* suspend timer (T3) in 100ms */
|
||||
3, /* suspend retries */
|
||||
10, /* resume timer (T4) in 100ms */
|
||||
3, /* resume retries */
|
||||
10, /* capability update timer (T5) */
|
||||
3, /* capability update retries */
|
||||
};
|
||||
|
||||
static unsigned char nanobts_attr_cell[] = {
|
||||
NM_ATT_IPACC_RAC, 0, 1, 1, /* routing area code */
|
||||
NM_ATT_IPACC_GPRS_PAGING_CFG, 0, 2,
|
||||
5, /* repeat time (50ms) */
|
||||
3, /* repeat count */
|
||||
NM_ATT_IPACC_BVCI, 0, 2, 0x03, 0x9d, /* BVCI 925 */
|
||||
NM_ATT_IPACC_RLC_CFG, 0, 9,
|
||||
20, /* T3142 */
|
||||
5, /* T3169 */
|
||||
5, /* T3191 */
|
||||
200, /* T3193 */
|
||||
5, /* T3195 */
|
||||
10, /* N3101 */
|
||||
4, /* N3103 */
|
||||
8, /* N3105 */
|
||||
15, /* RLC CV countdown */
|
||||
NM_ATT_IPACC_CODING_SCHEMES, 0, 2, 0x0f, 0x00, /* CS1..CS4 */
|
||||
NM_ATT_IPACC_RLC_CFG_2, 0, 5,
|
||||
0x00, 250, /* T downlink TBF extension (0..500) */
|
||||
0x00, 250, /* T uplink TBF extension (0..500) */
|
||||
2, /* CS2 */
|
||||
#if 0
|
||||
/* EDGE model only, breaks older models.
|
||||
* Should inquire the BTS capabilities */
|
||||
NM_ATT_IPACC_RLC_CFG_3, 0, 1,
|
||||
2, /* MCS2 */
|
||||
#endif
|
||||
};
|
||||
|
||||
static unsigned char nanobts_attr_nsvc0[] = {
|
||||
NM_ATT_IPACC_NSVCI, 0, 2, 0x03, 0x9d, /* 925 */
|
||||
NM_ATT_IPACC_NS_LINK_CFG, 0, 8,
|
||||
0x59, 0xd8, /* remote udp port (23000) */
|
||||
192, 168, 100, 11, /* remote ip address */
|
||||
0x59, 0xd8, /* local udp port (23000) */
|
||||
};
|
||||
|
||||
static void patch_16(uint8_t *data, const uint16_t val)
|
||||
{
|
||||
memcpy(data, &val, sizeof(val));
|
||||
}
|
||||
|
||||
static void patch_32(uint8_t *data, const uint32_t val)
|
||||
{
|
||||
memcpy(data, &val, sizeof(val));
|
||||
}
|
||||
|
||||
/*
|
||||
* Patch the various SYSTEM INFORMATION tables to update
|
||||
* the LAI
|
||||
*/
|
||||
static void patch_nm_tables(struct gsm_bts *bts)
|
||||
{
|
||||
u_int8_t arfcn_low = bts->c0->arfcn & 0xff;
|
||||
u_int8_t arfcn_high = (bts->c0->arfcn >> 8) & 0x0f;
|
||||
|
||||
/* patch ARFCN into BTS Attributes */
|
||||
nanobts_attr_bts[42] &= 0xf0;
|
||||
nanobts_attr_bts[42] |= arfcn_high;
|
||||
nanobts_attr_bts[43] = arfcn_low;
|
||||
|
||||
/* patch the RACH attributes */
|
||||
if (bts->rach_b_thresh != -1) {
|
||||
nanobts_attr_bts[33] = bts->rach_b_thresh & 0xff;
|
||||
}
|
||||
|
||||
if (bts->rach_ldavg_slots != -1) {
|
||||
u_int8_t avg_high = bts->rach_ldavg_slots & 0xff;
|
||||
u_int8_t avg_low = (bts->rach_ldavg_slots >> 8) & 0x0f;
|
||||
|
||||
nanobts_attr_bts[35] = avg_high;
|
||||
nanobts_attr_bts[36] = avg_low;
|
||||
}
|
||||
|
||||
/* patch BSIC */
|
||||
nanobts_attr_bts[sizeof(nanobts_attr_bts)-11] = bts->bsic;
|
||||
|
||||
/* patch CGI */
|
||||
abis_nm_ipaccess_cgi(nanobts_attr_bts+sizeof(nanobts_attr_bts)-7, bts);
|
||||
|
||||
/* patch the power reduction */
|
||||
nanobts_attr_radio[1] = bts->c0->max_power_red / 2;
|
||||
|
||||
/* patch NSEI */
|
||||
nanobts_attr_nse[3] = bts->gprs.nse.nsei >> 8;
|
||||
nanobts_attr_nse[4] = bts->gprs.nse.nsei & 0xff;
|
||||
memcpy(nanobts_attr_nse+8, bts->gprs.nse.timer,
|
||||
ARRAY_SIZE(bts->gprs.nse.timer));
|
||||
memcpy(nanobts_attr_nse+18, bts->gprs.cell.timer,
|
||||
ARRAY_SIZE(bts->gprs.cell.timer));
|
||||
|
||||
/* patch NSVCI */
|
||||
nanobts_attr_nsvc0[3] = bts->gprs.nsvc[0].nsvci >> 8;
|
||||
nanobts_attr_nsvc0[4] = bts->gprs.nsvc[0].nsvci & 0xff;
|
||||
|
||||
/* patch IP address as SGSN IP */
|
||||
patch_16(nanobts_attr_nsvc0 + 8,
|
||||
htons(bts->gprs.nsvc[0].remote_port));
|
||||
patch_32(nanobts_attr_nsvc0 + 10,
|
||||
htonl(bts->gprs.nsvc[0].remote_ip));
|
||||
patch_16(nanobts_attr_nsvc0 + 14,
|
||||
htons(bts->gprs.nsvc[0].local_port));
|
||||
|
||||
/* patch BVCI */
|
||||
nanobts_attr_cell[12] = bts->gprs.cell.bvci >> 8;
|
||||
nanobts_attr_cell[13] = bts->gprs.cell.bvci & 0xff;
|
||||
/* patch RAC */
|
||||
nanobts_attr_cell[3] = bts->gprs.rac;
|
||||
|
||||
if (bts->gprs.mode == BTS_GPRS_EGPRS) {
|
||||
/* patch EGPRS coding schemes MCS 1..9 */
|
||||
nanobts_attr_cell[29] = 0x8f;
|
||||
nanobts_attr_cell[30] = 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Callback function to be called whenever we get a GSM 12.21 state change event */
|
||||
static int nm_statechg_event(int evt, struct nm_statechg_signal_data *nsd)
|
||||
{
|
||||
u_int8_t obj_class = nsd->obj_class;
|
||||
void *obj = nsd->obj;
|
||||
struct gsm_nm_state *new_state = nsd->new_state;
|
||||
|
||||
struct gsm_bts *bts;
|
||||
struct gsm_bts_trx *trx;
|
||||
struct gsm_bts_trx_ts *ts;
|
||||
struct gsm_bts_gprs_nsvc *nsvc;
|
||||
|
||||
/* This event-driven BTS setup is currently only required on nanoBTS */
|
||||
|
||||
/* S_NM_STATECHG_ADM is called after we call chg_adm_state() and would create
|
||||
* endless loop */
|
||||
if (evt != S_NM_STATECHG_OPER)
|
||||
return 0;
|
||||
|
||||
switch (obj_class) {
|
||||
case NM_OC_SITE_MANAGER:
|
||||
bts = container_of(obj, struct gsm_bts, site_mgr);
|
||||
if ((new_state->operational == NM_OPSTATE_ENABLED &&
|
||||
new_state->availability == NM_AVSTATE_OK) ||
|
||||
(new_state->operational == NM_OPSTATE_DISABLED &&
|
||||
new_state->availability == NM_AVSTATE_OFF_LINE))
|
||||
abis_nm_opstart(bts, obj_class, 0xff, 0xff, 0xff);
|
||||
break;
|
||||
case NM_OC_BTS:
|
||||
bts = obj;
|
||||
if (new_state->availability == NM_AVSTATE_DEPENDENCY) {
|
||||
patch_nm_tables(bts);
|
||||
abis_nm_set_bts_attr(bts, nanobts_attr_bts,
|
||||
sizeof(nanobts_attr_bts));
|
||||
abis_nm_chg_adm_state(bts, obj_class,
|
||||
bts->bts_nr, 0xff, 0xff,
|
||||
NM_STATE_UNLOCKED);
|
||||
abis_nm_opstart(bts, obj_class,
|
||||
bts->bts_nr, 0xff, 0xff);
|
||||
}
|
||||
break;
|
||||
case NM_OC_CHANNEL:
|
||||
ts = obj;
|
||||
trx = ts->trx;
|
||||
if (new_state->operational == NM_OPSTATE_DISABLED &&
|
||||
new_state->availability == NM_AVSTATE_DEPENDENCY) {
|
||||
patch_nm_tables(trx->bts);
|
||||
enum abis_nm_chan_comb ccomb =
|
||||
abis_nm_chcomb4pchan(ts->pchan);
|
||||
abis_nm_set_channel_attr(ts, ccomb);
|
||||
abis_nm_chg_adm_state(trx->bts, obj_class,
|
||||
trx->bts->bts_nr, trx->nr, ts->nr,
|
||||
NM_STATE_UNLOCKED);
|
||||
abis_nm_opstart(trx->bts, obj_class,
|
||||
trx->bts->bts_nr, trx->nr, ts->nr);
|
||||
}
|
||||
break;
|
||||
case NM_OC_RADIO_CARRIER:
|
||||
trx = obj;
|
||||
if (new_state->operational == NM_OPSTATE_DISABLED &&
|
||||
new_state->availability == NM_AVSTATE_OK)
|
||||
abis_nm_opstart(trx->bts, obj_class, trx->bts->bts_nr,
|
||||
trx->nr, 0xff);
|
||||
break;
|
||||
case NM_OC_GPRS_NSE:
|
||||
bts = container_of(obj, struct gsm_bts, gprs.nse);
|
||||
if (bts->gprs.mode == BTS_GPRS_NONE)
|
||||
break;
|
||||
if (new_state->availability == NM_AVSTATE_DEPENDENCY) {
|
||||
abis_nm_ipaccess_set_attr(bts, obj_class, bts->bts_nr,
|
||||
0xff, 0xff, nanobts_attr_nse,
|
||||
sizeof(nanobts_attr_nse));
|
||||
abis_nm_opstart(bts, obj_class, bts->bts_nr,
|
||||
0xff, 0xff);
|
||||
}
|
||||
break;
|
||||
case NM_OC_GPRS_CELL:
|
||||
bts = container_of(obj, struct gsm_bts, gprs.cell);
|
||||
if (bts->gprs.mode == BTS_GPRS_NONE)
|
||||
break;
|
||||
if (new_state->availability == NM_AVSTATE_DEPENDENCY) {
|
||||
abis_nm_ipaccess_set_attr(bts, obj_class, bts->bts_nr,
|
||||
0, 0xff, nanobts_attr_cell,
|
||||
sizeof(nanobts_attr_cell));
|
||||
abis_nm_opstart(bts, obj_class, bts->bts_nr,
|
||||
0, 0xff);
|
||||
abis_nm_chg_adm_state(bts, obj_class, bts->bts_nr,
|
||||
0, 0xff, NM_STATE_UNLOCKED);
|
||||
abis_nm_chg_adm_state(bts, NM_OC_GPRS_NSE, bts->bts_nr,
|
||||
0xff, 0xff, NM_STATE_UNLOCKED);
|
||||
}
|
||||
break;
|
||||
case NM_OC_GPRS_NSVC:
|
||||
nsvc = obj;
|
||||
bts = nsvc->bts;
|
||||
if (bts->gprs.mode == BTS_GPRS_NONE)
|
||||
break;
|
||||
/* We skip NSVC1 since we only use NSVC0 */
|
||||
if (nsvc->id == 1)
|
||||
break;
|
||||
if (new_state->availability == NM_AVSTATE_OFF_LINE) {
|
||||
abis_nm_ipaccess_set_attr(bts, obj_class, bts->bts_nr,
|
||||
nsvc->id, 0xff,
|
||||
nanobts_attr_nsvc0,
|
||||
sizeof(nanobts_attr_nsvc0));
|
||||
abis_nm_opstart(bts, obj_class, bts->bts_nr,
|
||||
nsvc->id, 0xff);
|
||||
abis_nm_chg_adm_state(bts, obj_class, bts->bts_nr,
|
||||
nsvc->id, 0xff,
|
||||
NM_STATE_UNLOCKED);
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Callback function to be called every time we receive a 12.21 SW activated report */
|
||||
static int sw_activ_rep(struct msgb *mb)
|
||||
{
|
||||
struct abis_om_fom_hdr *foh = msgb_l3(mb);
|
||||
struct gsm_bts *bts = mb->trx->bts;
|
||||
struct gsm_bts_trx *trx = gsm_bts_trx_num(bts, foh->obj_inst.trx_nr);
|
||||
|
||||
if (!trx)
|
||||
return -EINVAL;
|
||||
|
||||
if (trx->bts->type != GSM_BTS_TYPE_NANOBTS)
|
||||
return 0;
|
||||
|
||||
switch (foh->obj_class) {
|
||||
case NM_OC_BASEB_TRANSC:
|
||||
abis_nm_chg_adm_state(trx->bts, foh->obj_class,
|
||||
trx->bts->bts_nr, trx->nr, 0xff,
|
||||
NM_STATE_UNLOCKED);
|
||||
abis_nm_opstart(trx->bts, foh->obj_class,
|
||||
trx->bts->bts_nr, trx->nr, 0xff);
|
||||
/* TRX software is active, tell it to initiate RSL Link */
|
||||
abis_nm_ipaccess_rsl_connect(trx, 0, 3003, trx->rsl_tei);
|
||||
break;
|
||||
case NM_OC_RADIO_CARRIER: {
|
||||
/*
|
||||
* Locking the radio carrier will make it go
|
||||
* offline again and we would come here. The
|
||||
* framework should determine that there was
|
||||
* no change and avoid recursion.
|
||||
*
|
||||
* This code is here to make sure that on start
|
||||
* a TRX remains locked.
|
||||
*/
|
||||
int rc_state = trx->nm_state.administrative;
|
||||
/* Patch ARFCN into radio attribute */
|
||||
nanobts_attr_radio[5] &= 0xf0;
|
||||
nanobts_attr_radio[5] |= trx->arfcn >> 8;
|
||||
nanobts_attr_radio[6] = trx->arfcn & 0xff;
|
||||
abis_nm_set_radio_attr(trx, nanobts_attr_radio,
|
||||
sizeof(nanobts_attr_radio));
|
||||
abis_nm_chg_adm_state(trx->bts, foh->obj_class,
|
||||
trx->bts->bts_nr, trx->nr, 0xff,
|
||||
rc_state);
|
||||
abis_nm_opstart(trx->bts, foh->obj_class, trx->bts->bts_nr,
|
||||
trx->nr, 0xff);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Callback function to be called every time we receive a signal from NM */
|
||||
static int nm_sig_cb(unsigned int subsys, unsigned int signal,
|
||||
void *handler_data, void *signal_data)
|
||||
{
|
||||
if (subsys != SS_NM)
|
||||
return 0;
|
||||
|
||||
switch (signal) {
|
||||
case S_NM_SW_ACTIV_REP:
|
||||
return sw_activ_rep(signal_data);
|
||||
case S_NM_STATECHG_OPER:
|
||||
case S_NM_STATECHG_ADM:
|
||||
return nm_statechg_event(signal, signal_data);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bts_model_nanobts_init(void)
|
||||
{
|
||||
model_nanobts.features.data = &model_nanobts._features_data[0];
|
||||
@@ -85,5 +441,7 @@ int bts_model_nanobts_init(void)
|
||||
gsm_btsmodel_set_feature(&model_nanobts, BTS_FEAT_GPRS);
|
||||
gsm_btsmodel_set_feature(&model_nanobts, BTS_FEAT_EGPRS);
|
||||
|
||||
register_signal_handler(SS_NM, nm_sig_cb, NULL);
|
||||
|
||||
return gsm_bts_model_register(&model_nanobts);
|
||||
}
|
||||
|
||||
@@ -5,29 +5,34 @@
|
||||
* All Rights Reserved
|
||||
*
|
||||
* 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 2 of the License, or
|
||||
* 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.
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* 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 <sys/types.h>
|
||||
|
||||
#include <openbsc/gsm_data.h>
|
||||
#include <osmocore/tlv.h>
|
||||
|
||||
#include <openbsc/debug.h>
|
||||
#include <openbsc/gsm_data.h>
|
||||
#include <openbsc/abis_nm.h>
|
||||
#include <openbsc/e1_input.h>
|
||||
#include <openbsc/signal.h>
|
||||
|
||||
static struct gsm_bts_model model_bs11 = {
|
||||
.type = GSM_BTS_TYPE_BS11,
|
||||
.name = "bs11",
|
||||
.oml_rcvmsg = &abis_nm_rcvmsg,
|
||||
.nm_att_tlvdef = {
|
||||
.def = {
|
||||
[NM_ATT_AVAIL_STATUS] = { TLV_TYPE_TLV },
|
||||
@@ -60,6 +65,517 @@ static struct gsm_bts_model model_bs11 = {
|
||||
},
|
||||
};
|
||||
|
||||
/* The following definitions are for OM and NM packets that we cannot yet
|
||||
* generate by code but we just pass on */
|
||||
|
||||
// BTS Site Manager, SET ATTRIBUTES
|
||||
|
||||
/*
|
||||
Object Class: BTS Site Manager
|
||||
Instance 1: FF
|
||||
Instance 2: FF
|
||||
Instance 3: FF
|
||||
SET ATTRIBUTES
|
||||
sAbisExternalTime: 2007/09/08 14:36:11
|
||||
omLAPDRelTimer: 30sec
|
||||
shortLAPDIntTimer: 5sec
|
||||
emergencyTimer1: 10 minutes
|
||||
emergencyTimer2: 0 minutes
|
||||
*/
|
||||
|
||||
unsigned char msg_1[] =
|
||||
{
|
||||
NM_MT_BS11_SET_ATTR, NM_OC_SITE_MANAGER, 0xFF, 0xFF, 0xFF,
|
||||
NM_ATT_BS11_ABIS_EXT_TIME, 0x07,
|
||||
0xD7, 0x09, 0x08, 0x0E, 0x24, 0x0B, 0xCE,
|
||||
0x02,
|
||||
0x00, 0x1E,
|
||||
NM_ATT_BS11_SH_LAPD_INT_TIMER,
|
||||
0x01, 0x05,
|
||||
0x42, 0x02, 0x00, 0x0A,
|
||||
0x44, 0x02, 0x00, 0x00
|
||||
};
|
||||
|
||||
// BTS, SET BTS ATTRIBUTES
|
||||
|
||||
/*
|
||||
Object Class: BTS
|
||||
BTS relat. Number: 0
|
||||
Instance 2: FF
|
||||
Instance 3: FF
|
||||
SET BTS ATTRIBUTES
|
||||
bsIdentityCode / BSIC:
|
||||
PLMN_colour_code: 7h
|
||||
BS_colour_code: 7h
|
||||
BTS Air Timer T3105: 4 ,unit 10 ms
|
||||
btsIsHopping: FALSE
|
||||
periodCCCHLoadIndication: 1sec
|
||||
thresholdCCCHLoadIndication: 0%
|
||||
cellAllocationNumber: 00h = GSM 900
|
||||
enableInterferenceClass: 00h = Disabled
|
||||
fACCHQual: 6 (FACCH stealing flags minus 1)
|
||||
intaveParameter: 31 SACCH multiframes
|
||||
interferenceLevelBoundaries:
|
||||
Interference Boundary 1: 0Ah
|
||||
Interference Boundary 2: 0Fh
|
||||
Interference Boundary 3: 14h
|
||||
Interference Boundary 4: 19h
|
||||
Interference Boundary 5: 1Eh
|
||||
mSTxPwrMax: 11
|
||||
GSM range: 2=39dBm, 15=13dBm, stepsize 2 dBm
|
||||
DCS1800 range: 0=30dBm, 15=0dBm, stepsize 2 dBm
|
||||
PCS1900 range: 0=30dBm, 15=0dBm, stepsize 2 dBm
|
||||
30=33dBm, 31=32dBm
|
||||
ny1:
|
||||
Maximum number of repetitions for PHYSICAL INFORMATION message (GSM 04.08): 20
|
||||
powerOutputThresholds:
|
||||
Out Power Fault Threshold: -10 dB
|
||||
Red Out Power Threshold: - 6 dB
|
||||
Excessive Out Power Threshold: 5 dB
|
||||
rACHBusyThreshold: -127 dBm
|
||||
rACHLoadAveragingSlots: 250 ,number of RACH burst periods
|
||||
rfResourceIndicationPeriod: 125 SACCH multiframes
|
||||
T200:
|
||||
SDCCH: 044 in 5 ms
|
||||
FACCH/Full rate: 031 in 5 ms
|
||||
FACCH/Half rate: 041 in 5 ms
|
||||
SACCH with TCH SAPI0: 090 in 10 ms
|
||||
SACCH with SDCCH: 090 in 10 ms
|
||||
SDCCH with SAPI3: 090 in 5 ms
|
||||
SACCH with TCH SAPI3: 135 in 10 ms
|
||||
tSync: 9000 units of 10 msec
|
||||
tTrau: 9000 units of 10 msec
|
||||
enableUmLoopTest: 00h = disabled
|
||||
enableExcessiveDistance: 00h = Disabled
|
||||
excessiveDistance: 64km
|
||||
hoppingMode: 00h = baseband hopping
|
||||
cellType: 00h = Standard Cell
|
||||
BCCH ARFCN / bCCHFrequency: 1
|
||||
*/
|
||||
|
||||
static unsigned char bs11_attr_bts[] =
|
||||
{
|
||||
NM_ATT_BSIC, HARDCODED_BSIC,
|
||||
NM_ATT_BTS_AIR_TIMER, 0x04,
|
||||
NM_ATT_BS11_BTSLS_HOPPING, 0x00,
|
||||
NM_ATT_CCCH_L_I_P, 0x01,
|
||||
NM_ATT_CCCH_L_T, 0x00,
|
||||
NM_ATT_BS11_CELL_ALLOC_NR, NM_BS11_CANR_GSM,
|
||||
NM_ATT_BS11_ENA_INTERF_CLASS, 0x01,
|
||||
NM_ATT_BS11_FACCH_QUAL, 0x06,
|
||||
/* interference avg. period in numbers of SACCH multifr */
|
||||
NM_ATT_INTAVE_PARAM, 0x1F,
|
||||
NM_ATT_INTERF_BOUND, 0x0A, 0x0F, 0x14, 0x19, 0x1E, 0x7B,
|
||||
NM_ATT_CCCH_L_T, 0x23,
|
||||
NM_ATT_GSM_TIME, 0x28, 0x00,
|
||||
NM_ATT_ADM_STATE, 0x03,
|
||||
NM_ATT_RACH_B_THRESH, 0x7F,
|
||||
NM_ATT_LDAVG_SLOTS, 0x00, 0xFA,
|
||||
NM_ATT_BS11_RF_RES_IND_PER, 0x7D,
|
||||
NM_ATT_T200, 0x2C, 0x1F, 0x29, 0x5A, 0x5A, 0x5A, 0x87,
|
||||
NM_ATT_BS11_TSYNC, 0x23, 0x28,
|
||||
NM_ATT_BS11_TTRAU, 0x23, 0x28,
|
||||
NM_ATT_TEST_DUR, 0x01, 0x00,
|
||||
NM_ATT_OUTST_ALARM, 0x01, 0x00,
|
||||
NM_ATT_BS11_EXCESSIVE_DISTANCE, 0x01, 0x40,
|
||||
NM_ATT_BS11_HOPPING_MODE, 0x01, 0x00,
|
||||
NM_ATT_BS11_PLL, 0x01, 0x00,
|
||||
NM_ATT_BCCH_ARFCN, 0x00, HARDCODED_ARFCN/*0x01*/,
|
||||
};
|
||||
|
||||
// Handover Recognition, SET ATTRIBUTES
|
||||
|
||||
/*
|
||||
Illegal Contents GSM Formatted O&M Msg
|
||||
Object Class: Handover Recognition
|
||||
BTS relat. Number: 0
|
||||
Instance 2: FF
|
||||
Instance 3: FF
|
||||
SET ATTRIBUTES
|
||||
enableDelayPowerBudgetHO: 00h = Disabled
|
||||
enableDistanceHO: 00h = Disabled
|
||||
enableInternalInterCellHandover: 00h = Disabled
|
||||
enableInternalIntraCellHandover: 00h = Disabled
|
||||
enablePowerBudgetHO: 00h = Disabled
|
||||
enableRXLEVHO: 00h = Disabled
|
||||
enableRXQUALHO: 00h = Disabled
|
||||
hoAveragingDistance: 8 SACCH multiframes
|
||||
hoAveragingLev:
|
||||
A_LEV_HO: 8 SACCH multiframes
|
||||
W_LEV_HO: 1 SACCH multiframes
|
||||
hoAveragingPowerBudget: 16 SACCH multiframes
|
||||
hoAveragingQual:
|
||||
A_QUAL_HO: 8 SACCH multiframes
|
||||
W_QUAL_HO: 2 SACCH multiframes
|
||||
hoLowerThresholdLevDL: (10 - 110) dBm
|
||||
hoLowerThresholdLevUL: (5 - 110) dBm
|
||||
hoLowerThresholdQualDL: 06h = 6.4% < BER < 12.8%
|
||||
hoLowerThresholdQualUL: 06h = 6.4% < BER < 12.8%
|
||||
hoThresholdLevDLintra : (20 - 110) dBm
|
||||
hoThresholdLevULintra: (20 - 110) dBm
|
||||
hoThresholdMsRangeMax: 20 km
|
||||
nCell: 06h
|
||||
timerHORequest: 3 ,unit 2 SACCH multiframes
|
||||
*/
|
||||
|
||||
unsigned char msg_3[] =
|
||||
{
|
||||
NM_MT_BS11_SET_ATTR, NM_OC_BS11_HANDOVER, 0x00, 0xFF, 0xFF,
|
||||
0xD0, 0x00, /* enableDelayPowerBudgetHO */
|
||||
0x64, 0x00, /* enableDistanceHO */
|
||||
0x67, 0x00, /* enableInternalInterCellHandover */
|
||||
0x68, 0x00, /* enableInternalInterCellHandover */
|
||||
0x6A, 0x00, /* enablePowerBudgetHO */
|
||||
0x6C, 0x00, /* enableRXLEVHO */
|
||||
0x6D, 0x00, /* enableRXQUALHO */
|
||||
0x6F, 0x08, /* hoAveragingDistance */
|
||||
0x70, 0x08, 0x01, /* hoAveragingLev */
|
||||
0x71, 0x10, 0x10, 0x10,
|
||||
0x72, 0x08, 0x02, /* hoAveragingQual */
|
||||
0x73, 0x0A, /* hoLowerThresholdLevDL */
|
||||
0x74, 0x05, /* hoLowerThresholdLevUL */
|
||||
0x75, 0x06, /* hoLowerThresholdQualDL */
|
||||
0x76, 0x06, /* hoLowerThresholdQualUL */
|
||||
0x78, 0x14, /* hoThresholdLevDLintra */
|
||||
0x79, 0x14, /* hoThresholdLevULintra */
|
||||
0x7A, 0x14, /* hoThresholdMsRangeMax */
|
||||
0x7D, 0x06, /* nCell */
|
||||
NM_ATT_BS11_TIMER_HO_REQUEST, 0x03,
|
||||
0x20, 0x01, 0x00,
|
||||
0x45, 0x01, 0x00,
|
||||
0x48, 0x01, 0x00,
|
||||
0x5A, 0x01, 0x00,
|
||||
0x5B, 0x01, 0x05,
|
||||
0x5E, 0x01, 0x1A,
|
||||
0x5F, 0x01, 0x20,
|
||||
0x9D, 0x01, 0x00,
|
||||
0x47, 0x01, 0x00,
|
||||
0x5C, 0x01, 0x64,
|
||||
0x5D, 0x01, 0x1E,
|
||||
0x97, 0x01, 0x20,
|
||||
0xF7, 0x01, 0x3C,
|
||||
};
|
||||
|
||||
// Power Control, SET ATTRIBUTES
|
||||
|
||||
/*
|
||||
Object Class: Power Control
|
||||
BTS relat. Number: 0
|
||||
Instance 2: FF
|
||||
Instance 3: FF
|
||||
SET ATTRIBUTES
|
||||
enableMsPowerControl: 00h = Disabled
|
||||
enablePowerControlRLFW: 00h = Disabled
|
||||
pcAveragingLev:
|
||||
A_LEV_PC: 4 SACCH multiframes
|
||||
W_LEV_PC: 1 SACCH multiframes
|
||||
pcAveragingQual:
|
||||
A_QUAL_PC: 4 SACCH multiframes
|
||||
W_QUAL_PC: 2 SACCH multiframes
|
||||
pcLowerThresholdLevDL: 0Fh
|
||||
pcLowerThresholdLevUL: 0Ah
|
||||
pcLowerThresholdQualDL: 05h = 3.2% < BER < 6.4%
|
||||
pcLowerThresholdQualUL: 05h = 3.2% < BER < 6.4%
|
||||
pcRLFThreshold: 0Ch
|
||||
pcUpperThresholdLevDL: 14h
|
||||
pcUpperThresholdLevUL: 0Fh
|
||||
pcUpperThresholdQualDL: 04h = 1.6% < BER < 3.2%
|
||||
pcUpperThresholdQualUL: 04h = 1.6% < BER < 3.2%
|
||||
powerConfirm: 2 ,unit 2 SACCH multiframes
|
||||
powerControlInterval: 2 ,unit 2 SACCH multiframes
|
||||
powerIncrStepSize: 02h = 4 dB
|
||||
powerRedStepSize: 01h = 2 dB
|
||||
radioLinkTimeoutBs: 64 SACCH multiframes
|
||||
enableBSPowerControl: 00h = disabled
|
||||
*/
|
||||
|
||||
unsigned char msg_4[] =
|
||||
{
|
||||
NM_MT_BS11_SET_ATTR, NM_OC_BS11_PWR_CTRL, 0x00, 0xFF, 0xFF,
|
||||
NM_ATT_BS11_ENA_MS_PWR_CTRL, 0x00,
|
||||
NM_ATT_BS11_ENA_PWR_CTRL_RLFW, 0x00,
|
||||
0x7E, 0x04, 0x01, /* pcAveragingLev */
|
||||
0x7F, 0x04, 0x02, /* pcAveragingQual */
|
||||
0x80, 0x0F, /* pcLowerThresholdLevDL */
|
||||
0x81, 0x0A, /* pcLowerThresholdLevUL */
|
||||
0x82, 0x05, /* pcLowerThresholdQualDL */
|
||||
0x83, 0x05, /* pcLowerThresholdQualUL */
|
||||
0x84, 0x0C, /* pcRLFThreshold */
|
||||
0x85, 0x14, /* pcUpperThresholdLevDL */
|
||||
0x86, 0x0F, /* pcUpperThresholdLevUL */
|
||||
0x87, 0x04, /* pcUpperThresholdQualDL */
|
||||
0x88, 0x04, /* pcUpperThresholdQualUL */
|
||||
0x89, 0x02, /* powerConfirm */
|
||||
0x8A, 0x02, /* powerConfirmInterval */
|
||||
0x8B, 0x02, /* powerIncrStepSize */
|
||||
0x8C, 0x01, /* powerRedStepSize */
|
||||
0x8D, 0x40, /* radioLinkTimeoutBs */
|
||||
0x65, 0x01, 0x00 // set to 0x01 to enable BSPowerControl
|
||||
};
|
||||
|
||||
|
||||
// Transceiver, SET TRX ATTRIBUTES (TRX 0)
|
||||
|
||||
/*
|
||||
Object Class: Transceiver
|
||||
BTS relat. Number: 0
|
||||
Tranceiver number: 0
|
||||
Instance 3: FF
|
||||
SET TRX ATTRIBUTES
|
||||
aRFCNList (HEX): 0001
|
||||
txPwrMaxReduction: 00h = 30dB
|
||||
radioMeasGran: 254 SACCH multiframes
|
||||
radioMeasRep: 01h = enabled
|
||||
memberOfEmergencyConfig: 01h = TRUE
|
||||
trxArea: 00h = TRX doesn't belong to a concentric cell
|
||||
*/
|
||||
|
||||
static unsigned char bs11_attr_radio[] =
|
||||
{
|
||||
NM_ATT_ARFCN_LIST, 0x01, 0x00, HARDCODED_ARFCN /*0x01*/,
|
||||
NM_ATT_RF_MAXPOWR_R, 0x00,
|
||||
NM_ATT_BS11_RADIO_MEAS_GRAN, 0x01, 0x05,
|
||||
NM_ATT_BS11_RADIO_MEAS_REP, 0x01, 0x01,
|
||||
NM_ATT_BS11_EMRG_CFG_MEMBER, 0x01, 0x01,
|
||||
NM_ATT_BS11_TRX_AREA, 0x01, 0x00,
|
||||
};
|
||||
|
||||
/*
|
||||
* Patch the various SYSTEM INFORMATION tables to update
|
||||
* the LAI
|
||||
*/
|
||||
static void patch_nm_tables(struct gsm_bts *bts)
|
||||
{
|
||||
u_int8_t arfcn_low = bts->c0->arfcn & 0xff;
|
||||
u_int8_t arfcn_high = (bts->c0->arfcn >> 8) & 0x0f;
|
||||
|
||||
/* patch ARFCN into BTS Attributes */
|
||||
bs11_attr_bts[69] &= 0xf0;
|
||||
bs11_attr_bts[69] |= arfcn_high;
|
||||
bs11_attr_bts[70] = arfcn_low;
|
||||
|
||||
/* patch ARFCN into TRX Attributes */
|
||||
bs11_attr_radio[2] &= 0xf0;
|
||||
bs11_attr_radio[2] |= arfcn_high;
|
||||
bs11_attr_radio[3] = arfcn_low;
|
||||
|
||||
/* patch the RACH attributes */
|
||||
if (bts->rach_b_thresh != -1)
|
||||
bs11_attr_bts[33] = bts->rach_b_thresh & 0xff;
|
||||
|
||||
if (bts->rach_ldavg_slots != -1) {
|
||||
u_int8_t avg_high = bts->rach_ldavg_slots & 0xff;
|
||||
u_int8_t avg_low = (bts->rach_ldavg_slots >> 8) & 0x0f;
|
||||
|
||||
bs11_attr_bts[35] = avg_high;
|
||||
bs11_attr_bts[36] = avg_low;
|
||||
}
|
||||
|
||||
/* patch BSIC */
|
||||
bs11_attr_bts[1] = bts->bsic;
|
||||
|
||||
/* patch the power reduction */
|
||||
bs11_attr_radio[5] = bts->c0->max_power_red / 2;
|
||||
}
|
||||
|
||||
|
||||
static void nm_reconfig_ts(struct gsm_bts_trx_ts *ts)
|
||||
{
|
||||
enum abis_nm_chan_comb ccomb = abis_nm_chcomb4pchan(ts->pchan);
|
||||
struct gsm_e1_subslot *e1l = &ts->e1_link;
|
||||
|
||||
abis_nm_set_channel_attr(ts, ccomb);
|
||||
|
||||
if (is_ipaccess_bts(ts->trx->bts))
|
||||
return;
|
||||
|
||||
switch (ts->pchan) {
|
||||
case GSM_PCHAN_TCH_F:
|
||||
case GSM_PCHAN_TCH_H:
|
||||
abis_nm_conn_terr_traf(ts, e1l->e1_nr, e1l->e1_ts,
|
||||
e1l->e1_ts_ss);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void nm_reconfig_trx(struct gsm_bts_trx *trx)
|
||||
{
|
||||
struct gsm_e1_subslot *e1l = &trx->rsl_e1_link;
|
||||
int i;
|
||||
|
||||
patch_nm_tables(trx->bts);
|
||||
|
||||
switch (trx->bts->type) {
|
||||
case GSM_BTS_TYPE_BS11:
|
||||
/* FIXME: discover this by fetching an attribute */
|
||||
#if 0
|
||||
trx->nominal_power = 15; /* 15dBm == 30mW PA configuration */
|
||||
#else
|
||||
trx->nominal_power = 24; /* 24dBm == 250mW PA configuration */
|
||||
#endif
|
||||
abis_nm_conn_terr_sign(trx, e1l->e1_nr, e1l->e1_ts,
|
||||
e1l->e1_ts_ss);
|
||||
abis_nm_establish_tei(trx->bts, trx->nr, e1l->e1_nr,
|
||||
e1l->e1_ts, e1l->e1_ts_ss, trx->rsl_tei);
|
||||
|
||||
/* Set Radio Attributes */
|
||||
if (trx == trx->bts->c0)
|
||||
abis_nm_set_radio_attr(trx, bs11_attr_radio,
|
||||
sizeof(bs11_attr_radio));
|
||||
else {
|
||||
u_int8_t trx1_attr_radio[sizeof(bs11_attr_radio)];
|
||||
u_int8_t arfcn_low = trx->arfcn & 0xff;
|
||||
u_int8_t arfcn_high = (trx->arfcn >> 8) & 0x0f;
|
||||
memcpy(trx1_attr_radio, bs11_attr_radio,
|
||||
sizeof(trx1_attr_radio));
|
||||
|
||||
/* patch ARFCN into TRX Attributes */
|
||||
trx1_attr_radio[2] &= 0xf0;
|
||||
trx1_attr_radio[2] |= arfcn_high;
|
||||
trx1_attr_radio[3] = arfcn_low;
|
||||
|
||||
abis_nm_set_radio_attr(trx, trx1_attr_radio,
|
||||
sizeof(trx1_attr_radio));
|
||||
}
|
||||
break;
|
||||
case GSM_BTS_TYPE_NANOBTS:
|
||||
switch (trx->bts->band) {
|
||||
case GSM_BAND_850:
|
||||
case GSM_BAND_900:
|
||||
trx->nominal_power = 20;
|
||||
break;
|
||||
case GSM_BAND_1800:
|
||||
case GSM_BAND_1900:
|
||||
trx->nominal_power = 23;
|
||||
break;
|
||||
default:
|
||||
LOGP(DNM, LOGL_ERROR, "Unsupported nanoBTS GSM band %s\n",
|
||||
gsm_band_name(trx->bts->band));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; i < TRX_NR_TS; i++)
|
||||
nm_reconfig_ts(&trx->ts[i]);
|
||||
}
|
||||
|
||||
static void nm_reconfig_bts(struct gsm_bts *bts)
|
||||
{
|
||||
struct gsm_bts_trx *trx;
|
||||
|
||||
switch (bts->type) {
|
||||
case GSM_BTS_TYPE_BS11:
|
||||
patch_nm_tables(bts);
|
||||
abis_nm_raw_msg(bts, sizeof(msg_1), msg_1); /* set BTS SiteMgr attr*/
|
||||
abis_nm_set_bts_attr(bts, bs11_attr_bts, sizeof(bs11_attr_bts));
|
||||
abis_nm_raw_msg(bts, sizeof(msg_3), msg_3); /* set BTS handover attr */
|
||||
abis_nm_raw_msg(bts, sizeof(msg_4), msg_4); /* set BTS power control attr */
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
llist_for_each_entry(trx, &bts->trx_list, list)
|
||||
nm_reconfig_trx(trx);
|
||||
}
|
||||
|
||||
|
||||
static void bootstrap_om_bs11(struct gsm_bts *bts)
|
||||
{
|
||||
LOGP(DNM, LOGL_NOTICE, "bootstrapping OML for BTS %u\n", bts->nr);
|
||||
|
||||
/* stop sending event reports */
|
||||
abis_nm_event_reports(bts, 0);
|
||||
|
||||
/* begin DB transmission */
|
||||
abis_nm_bs11_db_transmission(bts, 1);
|
||||
|
||||
/* end DB transmission */
|
||||
abis_nm_bs11_db_transmission(bts, 0);
|
||||
|
||||
/* Reset BTS Site manager resource */
|
||||
abis_nm_bs11_reset_resource(bts);
|
||||
|
||||
/* begin DB transmission */
|
||||
abis_nm_bs11_db_transmission(bts, 1);
|
||||
|
||||
/* reconfigure BTS with all TRX and all TS */
|
||||
nm_reconfig_bts(bts);
|
||||
|
||||
/* end DB transmission */
|
||||
abis_nm_bs11_db_transmission(bts, 0);
|
||||
|
||||
/* Reset BTS Site manager resource */
|
||||
abis_nm_bs11_reset_resource(bts);
|
||||
|
||||
/* restart sending event reports */
|
||||
abis_nm_event_reports(bts, 1);
|
||||
}
|
||||
|
||||
static int shutdown_om(struct gsm_bts *bts)
|
||||
{
|
||||
/* stop sending event reports */
|
||||
abis_nm_event_reports(bts, 0);
|
||||
|
||||
/* begin DB transmission */
|
||||
abis_nm_bs11_db_transmission(bts, 1);
|
||||
|
||||
/* end DB transmission */
|
||||
abis_nm_bs11_db_transmission(bts, 0);
|
||||
|
||||
/* Reset BTS Site manager resource */
|
||||
abis_nm_bs11_reset_resource(bts);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Callback function to be called every time we receive a signal from INPUT */
|
||||
static int gbl_sig_cb(unsigned int subsys, unsigned int signal,
|
||||
void *handler_data, void *signal_data)
|
||||
{
|
||||
struct gsm_bts *bts;
|
||||
|
||||
if (subsys != SS_GLOBAL)
|
||||
return 0;
|
||||
|
||||
switch (signal) {
|
||||
case S_GLOBAL_BTS_CLOSE_OM:
|
||||
bts = signal_data;
|
||||
if (bts->type == GSM_BTS_TYPE_BS11)
|
||||
shutdown_om(signal_data);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Callback function to be called every time we receive a signal from INPUT */
|
||||
static int inp_sig_cb(unsigned int subsys, unsigned int signal,
|
||||
void *handler_data, void *signal_data)
|
||||
{
|
||||
struct input_signal_data *isd = signal_data;
|
||||
|
||||
if (subsys != SS_INPUT)
|
||||
return 0;
|
||||
|
||||
switch (signal) {
|
||||
case S_INP_TEI_UP:
|
||||
switch (isd->link_type) {
|
||||
case E1INP_SIGN_OML:
|
||||
if (isd->trx->bts->type == GSM_BTS_TYPE_BS11)
|
||||
bootstrap_om_bs11(isd->trx->bts);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bts_model_bs11_init(void)
|
||||
{
|
||||
model_bs11.features.data = &model_bs11._features_data[0];
|
||||
@@ -68,5 +584,8 @@ int bts_model_bs11_init(void)
|
||||
gsm_btsmodel_set_feature(&model_bs11, BTS_FEAT_HOPPING);
|
||||
gsm_btsmodel_set_feature(&model_bs11, BTS_FEAT_HSCSD);
|
||||
|
||||
register_signal_handler(SS_INPUT, inp_sig_cb, NULL);
|
||||
register_signal_handler(SS_GLOBAL, gbl_sig_cb, NULL);
|
||||
|
||||
return gsm_bts_model_register(&model_bs11);
|
||||
}
|
||||
|
||||
@@ -5,18 +5,17 @@
|
||||
* All Rights Reserved
|
||||
*
|
||||
* 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 2 of the License, or
|
||||
* 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.
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -28,6 +27,8 @@
|
||||
|
||||
static struct gsm_bts_model model_unknown = {
|
||||
.type = GSM_BTS_TYPE_UNKNOWN,
|
||||
.name = "unknown",
|
||||
.oml_rcvmsg = &abis_nm_rcvmsg,
|
||||
.nm_att_tlvdef = {
|
||||
.def = {
|
||||
},
|
||||
|
||||
@@ -6,18 +6,17 @@
|
||||
* All Rights Reserved
|
||||
*
|
||||
* 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 2 of the License, or
|
||||
* 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.
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -26,7 +25,7 @@
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <openbsc/gsm_data.h>
|
||||
#include <openbsc/gsm_subscriber.h>
|
||||
#include <openbsc/chan_alloc.h>
|
||||
#include <openbsc/abis_nm.h>
|
||||
#include <openbsc/abis_rsl.h>
|
||||
@@ -281,13 +280,6 @@ struct gsm_lchan *lchan_alloc(struct gsm_bts *bts, enum gsm_chan_t type,
|
||||
|
||||
/* clear multi rate config */
|
||||
memset(&lchan->mr_conf, 0, sizeof(lchan->mr_conf));
|
||||
|
||||
/* clear per MSC/BSC data */
|
||||
if (lchan->conn) {
|
||||
LOGP(DRLL, LOGL_ERROR, "lchan->conn should be NULL.\n");
|
||||
subscr_con_free(lchan->conn);
|
||||
lchan->conn = NULL;
|
||||
}
|
||||
} else {
|
||||
struct challoc_signal_data sig;
|
||||
sig.bts = bts;
|
||||
@@ -309,8 +301,12 @@ void lchan_free(struct gsm_lchan *lchan)
|
||||
|
||||
|
||||
if (lchan->conn) {
|
||||
struct lchan_signal_data sig;
|
||||
|
||||
/* We might kill an active channel... */
|
||||
dispatch_signal(SS_LCHAN, S_LCHAN_UNEXPECTED_RELEASE, lchan);
|
||||
sig.lchan = lchan;
|
||||
sig.mr = NULL;
|
||||
dispatch_signal(SS_LCHAN, S_LCHAN_UNEXPECTED_RELEASE, &sig);
|
||||
}
|
||||
|
||||
|
||||
@@ -338,7 +334,6 @@ void lchan_free(struct gsm_lchan *lchan)
|
||||
|
||||
if (lchan->conn) {
|
||||
LOGP(DRLL, LOGL_ERROR, "the subscriber connection should be gone.\n");
|
||||
subscr_con_free(lchan->conn);
|
||||
lchan->conn = NULL;
|
||||
}
|
||||
|
||||
@@ -422,6 +417,7 @@ int lchan_release(struct gsm_lchan *lchan, int sach_deact, int reason)
|
||||
DEBUGP(DRLL, "%s starting release sequence\n", gsm_lchan_name(lchan));
|
||||
rsl_lchan_set_state(lchan, LCHAN_S_REL_REQ);
|
||||
|
||||
lchan->conn = NULL;
|
||||
lchan->release_reason = reason;
|
||||
lchan->sach_deact = sach_deact;
|
||||
_lchan_handle_release(lchan);
|
||||
|
||||
@@ -4,18 +4,17 @@
|
||||
* All Rights Reserved
|
||||
*
|
||||
* 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 2 of the License, or
|
||||
* 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.
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -68,6 +67,7 @@ enum node_type bsc_vty_go_parent(struct vty *vty)
|
||||
}
|
||||
break;
|
||||
case OML_NODE:
|
||||
case OM2K_NODE:
|
||||
vty->node = ENABLE_NODE;
|
||||
talloc_free(vty->index);
|
||||
vty->index = NULL;
|
||||
@@ -86,6 +86,9 @@ enum node_type bsc_vty_go_parent(struct vty *vty)
|
||||
case MSC_NODE:
|
||||
vty->node = GSMNET_NODE;
|
||||
break;
|
||||
case TRUNK_NODE:
|
||||
vty->node = MGCP_NODE;
|
||||
break;
|
||||
default:
|
||||
vty->node = CONFIG_NODE;
|
||||
}
|
||||
@@ -146,6 +149,7 @@ gDEFUN(ournode_exit,
|
||||
vty->index = NULL;
|
||||
break;
|
||||
case OML_NODE:
|
||||
case OM2K_NODE:
|
||||
vty->node = ENABLE_NODE;
|
||||
talloc_free(vty->index);
|
||||
vty->index = NULL;
|
||||
@@ -153,6 +157,10 @@ gDEFUN(ournode_exit,
|
||||
case MSC_NODE:
|
||||
vty->node = GSMNET_NODE;
|
||||
break;
|
||||
case TRUNK_NODE:
|
||||
vty->node = MGCP_NODE;
|
||||
vty->index = NULL;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -174,6 +182,7 @@ gDEFUN(ournode_end,
|
||||
case TRX_NODE:
|
||||
case TS_NODE:
|
||||
case MGCP_NODE:
|
||||
case TRUNK_NODE:
|
||||
case GBPROXY_NODE:
|
||||
case SGSN_NODE:
|
||||
case NS_NODE:
|
||||
@@ -197,6 +206,7 @@ int bsc_vty_is_config_node(struct vty *vty, int node)
|
||||
switch (node) {
|
||||
/* add items that are not config */
|
||||
case OML_NODE:
|
||||
case OM2K_NODE:
|
||||
case SUBSCR_NODE:
|
||||
case CONFIG_NODE:
|
||||
return 0;
|
||||
|
||||
140
openbsc/src/db.c
140
openbsc/src/db.c
@@ -5,18 +5,17 @@
|
||||
* All Rights Reserved
|
||||
*
|
||||
* 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 2 of the License, or
|
||||
* 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.
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -30,10 +29,12 @@
|
||||
#include <dbi/dbi.h>
|
||||
|
||||
#include <openbsc/gsm_data.h>
|
||||
#include <openbsc/gsm_subscriber.h>
|
||||
#include <openbsc/gsm_04_11.h>
|
||||
#include <openbsc/db.h>
|
||||
#include <osmocore/talloc.h>
|
||||
#include <openbsc/debug.h>
|
||||
|
||||
#include <osmocore/talloc.h>
|
||||
#include <osmocore/statistics.h>
|
||||
#include <osmocore/rate_ctr.h>
|
||||
|
||||
@@ -556,13 +557,35 @@ int db_sync_lastauthtuple_for_subscr(struct gsm_auth_tuple *atuple,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void db_set_from_query(struct gsm_subscriber *subscr, dbi_conn result)
|
||||
{
|
||||
const char *string;
|
||||
string = dbi_result_get_string(result, "imsi");
|
||||
if (string)
|
||||
strncpy(subscr->imsi, string, GSM_IMSI_LENGTH);
|
||||
|
||||
string = dbi_result_get_string(result, "tmsi");
|
||||
if (string)
|
||||
subscr->tmsi = tmsi_from_string(string);
|
||||
|
||||
string = dbi_result_get_string(result, "name");
|
||||
if (string)
|
||||
strncpy(subscr->name, string, GSM_NAME_LENGTH);
|
||||
|
||||
string = dbi_result_get_string(result, "extension");
|
||||
if (string)
|
||||
strncpy(subscr->extension, string, GSM_EXTENSION_LENGTH);
|
||||
|
||||
subscr->lac = dbi_result_get_uint(result, "lac");
|
||||
subscr->authorized = dbi_result_get_uint(result, "authorized");
|
||||
}
|
||||
|
||||
#define BASE_QUERY "SELECT * FROM Subscriber "
|
||||
struct gsm_subscriber *db_get_subscriber(struct gsm_network *net,
|
||||
enum gsm_subscriber_field field,
|
||||
const char *id)
|
||||
{
|
||||
dbi_result result;
|
||||
const char *string;
|
||||
char *quoted;
|
||||
struct gsm_subscriber *subscr;
|
||||
|
||||
@@ -619,24 +642,8 @@ struct gsm_subscriber *db_get_subscriber(struct gsm_network *net,
|
||||
subscr = subscr_alloc();
|
||||
subscr->net = net;
|
||||
subscr->id = dbi_result_get_ulonglong(result, "id");
|
||||
string = dbi_result_get_string(result, "imsi");
|
||||
if (string)
|
||||
strncpy(subscr->imsi, string, GSM_IMSI_LENGTH);
|
||||
|
||||
string = dbi_result_get_string(result, "tmsi");
|
||||
if (string)
|
||||
subscr->tmsi = tmsi_from_string(string);
|
||||
|
||||
string = dbi_result_get_string(result, "name");
|
||||
if (string)
|
||||
strncpy(subscr->name, string, GSM_NAME_LENGTH);
|
||||
|
||||
string = dbi_result_get_string(result, "extension");
|
||||
if (string)
|
||||
strncpy(subscr->extension, string, GSM_EXTENSION_LENGTH);
|
||||
|
||||
subscr->lac = dbi_result_get_uint(result, "lac");
|
||||
subscr->authorized = dbi_result_get_uint(result, "authorized");
|
||||
db_set_from_query(subscr, result);
|
||||
DEBUGP(DDB, "Found Subscriber: ID %llu, IMSI %s, NAME '%s', TMSI %u, EXTEN '%s', LAC %hu, AUTH %u\n",
|
||||
subscr->id, subscr->imsi, subscr->name, subscr->tmsi, subscr->extension,
|
||||
subscr->lac, subscr->authorized);
|
||||
@@ -647,12 +654,46 @@ struct gsm_subscriber *db_get_subscriber(struct gsm_network *net,
|
||||
return subscr;
|
||||
}
|
||||
|
||||
int db_subscriber_update(struct gsm_subscriber *subscr)
|
||||
{
|
||||
char buf[32];
|
||||
dbi_result result;
|
||||
|
||||
/* Copy the id to a string as queryf with %llu is failing */
|
||||
sprintf(buf, "%llu", subscr->id);
|
||||
result = dbi_conn_queryf(conn,
|
||||
BASE_QUERY
|
||||
"WHERE id = %s", buf);
|
||||
|
||||
if (!result) {
|
||||
LOGP(DDB, LOGL_ERROR, "Failed to query Subscriber: %llu\n", subscr->id);
|
||||
return -EIO;
|
||||
}
|
||||
if (!dbi_result_next_row(result)) {
|
||||
DEBUGP(DDB, "Failed to find the Subscriber. %llu\n",
|
||||
subscr->id);
|
||||
dbi_result_free(result);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
db_set_from_query(subscr, result);
|
||||
dbi_result_free(result);
|
||||
get_equipment_by_subscr(subscr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int db_sync_subscriber(struct gsm_subscriber *subscriber)
|
||||
{
|
||||
dbi_result result;
|
||||
char tmsi[14];
|
||||
char *q_tmsi;
|
||||
char *q_tmsi, *q_name, *q_extension;
|
||||
|
||||
dbi_conn_quote_string_copy(conn,
|
||||
subscriber->name, &q_name);
|
||||
dbi_conn_quote_string_copy(conn,
|
||||
subscriber->extension, &q_extension);
|
||||
|
||||
if (subscriber->tmsi != GSM_RESERVED_TMSI) {
|
||||
sprintf(tmsi, "%u", subscriber->tmsi);
|
||||
dbi_conn_quote_string_copy(conn,
|
||||
@@ -664,20 +705,22 @@ int db_sync_subscriber(struct gsm_subscriber *subscriber)
|
||||
result = dbi_conn_queryf(conn,
|
||||
"UPDATE Subscriber "
|
||||
"SET updated = datetime('now'), "
|
||||
"name = '%s', "
|
||||
"extension = '%s', "
|
||||
"name = %s, "
|
||||
"extension = %s, "
|
||||
"authorized = %i, "
|
||||
"tmsi = %s, "
|
||||
"lac = %i "
|
||||
"WHERE imsi = %s ",
|
||||
subscriber->name,
|
||||
subscriber->extension,
|
||||
q_name,
|
||||
q_extension,
|
||||
subscriber->authorized,
|
||||
q_tmsi,
|
||||
subscriber->lac,
|
||||
subscriber->imsi);
|
||||
|
||||
free(q_tmsi);
|
||||
free(q_name);
|
||||
free(q_extension);
|
||||
|
||||
if (!result) {
|
||||
LOGP(DDB, LOGL_ERROR, "Failed to update Subscriber (by IMSI).\n");
|
||||
@@ -693,6 +736,7 @@ int db_sync_equipment(struct gsm_equipment *equip)
|
||||
{
|
||||
dbi_result result;
|
||||
unsigned char *cm2, *cm3;
|
||||
char *q_imei;
|
||||
u_int8_t classmark1;
|
||||
|
||||
memcpy(&classmark1, &equip->classmark1, sizeof(classmark1));
|
||||
@@ -710,6 +754,7 @@ int db_sync_equipment(struct gsm_equipment *equip)
|
||||
equip->classmark2_len, &cm2);
|
||||
dbi_conn_quote_binary_copy(conn, equip->classmark3,
|
||||
equip->classmark3_len, &cm3);
|
||||
dbi_conn_quote_string_copy(conn, equip->imei, &q_imei);
|
||||
|
||||
result = dbi_conn_queryf(conn,
|
||||
"UPDATE Equipment SET "
|
||||
@@ -717,11 +762,12 @@ int db_sync_equipment(struct gsm_equipment *equip)
|
||||
"classmark1 = %u, "
|
||||
"classmark2 = %s, "
|
||||
"classmark3 = %s "
|
||||
"WHERE imei = '%s' ",
|
||||
classmark1, cm2, cm3, equip->imei);
|
||||
"WHERE imei = %s ",
|
||||
classmark1, cm2, cm3, q_imei);
|
||||
|
||||
free(cm2);
|
||||
free(cm3);
|
||||
free(q_imei);
|
||||
|
||||
if (!result) {
|
||||
LOGP(DDB, LOGL_ERROR, "Failed to update Equipment\n");
|
||||
@@ -1025,6 +1071,28 @@ static struct gsm_sms *sms_from_result(struct gsm_network *net, dbi_result resul
|
||||
return sms;
|
||||
}
|
||||
|
||||
struct gsm_sms *db_sms_get(struct gsm_network *net, unsigned long long id)
|
||||
{
|
||||
dbi_result result;
|
||||
struct gsm_sms *sms;
|
||||
|
||||
result = dbi_conn_queryf(conn,
|
||||
"SELECT * FROM SMS WHERE SMS.id = %llu", id);
|
||||
if (!result)
|
||||
return NULL;
|
||||
|
||||
if (!dbi_result_next_row(result)) {
|
||||
dbi_result_free(result);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sms = sms_from_result(net, result);
|
||||
|
||||
dbi_result_free(result);
|
||||
|
||||
return sms;
|
||||
}
|
||||
|
||||
/* retrieve the next unsent SMS with ID >= min_id */
|
||||
struct gsm_sms *db_sms_get_unsent(struct gsm_network *net, unsigned long long min_id)
|
||||
{
|
||||
@@ -1054,7 +1122,9 @@ struct gsm_sms *db_sms_get_unsent(struct gsm_network *net, unsigned long long mi
|
||||
return sms;
|
||||
}
|
||||
|
||||
struct gsm_sms *db_sms_get_unsent_by_subscr(struct gsm_network *net, unsigned long long min_subscr_id)
|
||||
struct gsm_sms *db_sms_get_unsent_by_subscr(struct gsm_network *net,
|
||||
unsigned long long min_subscr_id,
|
||||
unsigned int failed)
|
||||
{
|
||||
dbi_result result;
|
||||
struct gsm_sms *sms;
|
||||
@@ -1064,9 +1134,9 @@ struct gsm_sms *db_sms_get_unsent_by_subscr(struct gsm_network *net, unsigned lo
|
||||
"FROM SMS JOIN Subscriber ON "
|
||||
"SMS.receiver_id = Subscriber.id "
|
||||
"WHERE SMS.receiver_id >= %llu AND SMS.sent IS NULL "
|
||||
"AND Subscriber.lac > 0 "
|
||||
"AND Subscriber.lac > 0 AND SMS.deliver_attempts < %u "
|
||||
"ORDER BY SMS.receiver_id, SMS.id LIMIT 1",
|
||||
min_subscr_id);
|
||||
min_subscr_id, failed);
|
||||
if (!result)
|
||||
return NULL;
|
||||
|
||||
|
||||
@@ -5,18 +5,17 @@
|
||||
* All Rights Reserved
|
||||
*
|
||||
* 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 2 of the License, or
|
||||
* 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.
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,3 +1,23 @@
|
||||
/* OpenBSC E1 Input code */
|
||||
|
||||
/* (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 <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
@@ -28,12 +48,19 @@ int e1_reconfig_ts(struct gsm_bts_trx_ts *ts)
|
||||
|
||||
DEBUGP(DMI, "e1_reconfig_ts(%u,%u,%u)\n", ts->trx->bts->nr, ts->trx->nr, ts->nr);
|
||||
|
||||
if (!e1_link->e1_ts)
|
||||
if (!e1_link->e1_ts) {
|
||||
LOGP(DINP, LOGL_ERROR, "TS (%u/%u/%u) without E1 timeslot?\n",
|
||||
ts->nr, ts->trx->nr, ts->trx->bts->nr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
line = e1inp_line_get_create(e1_link->e1_nr);
|
||||
if (!line)
|
||||
line = e1inp_line_get(e1_link->e1_nr);
|
||||
if (!line) {
|
||||
LOGP(DINP, LOGL_ERROR, "TS (%u/%u/%u) referring to "
|
||||
"non-existing E1 line %u\n", ts->nr, ts->trx->nr,
|
||||
ts->trx->bts->nr, e1_link->e1_nr);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
switch (ts->pchan) {
|
||||
case GSM_PCHAN_TCH_F:
|
||||
@@ -57,19 +84,43 @@ int e1_reconfig_trx(struct gsm_bts_trx *trx)
|
||||
struct e1inp_sign_link *rsl_link;
|
||||
int i;
|
||||
|
||||
if (!e1_link->e1_ts)
|
||||
if (!e1_link->e1_ts) {
|
||||
LOGP(DINP, LOGL_ERROR, "TRX (%u/%u) RSL link without "
|
||||
"timeslot?\n", trx->bts->nr, trx->nr);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* RSL Link */
|
||||
line = e1inp_line_get_create(e1_link->e1_nr);
|
||||
if (!line)
|
||||
line = e1inp_line_get(e1_link->e1_nr);
|
||||
if (!line) {
|
||||
LOGP(DINP, LOGL_ERROR, "TRX (%u/%u) RSL link referring "
|
||||
"to non-existing E1 line %u\n", trx->bts->nr,
|
||||
trx->nr, e1_link->e1_nr);
|
||||
return -ENOMEM;
|
||||
}
|
||||
sign_ts = &line->ts[e1_link->e1_ts-1];
|
||||
e1inp_ts_config(sign_ts, line, E1INP_TS_TYPE_SIGN);
|
||||
/* Ericsson RBS have a per-TRX OML link in parallel to RSL */
|
||||
if (trx->bts->type == GSM_BTS_TYPE_RBS2000) {
|
||||
struct e1inp_sign_link *oml_link;
|
||||
oml_link = e1inp_sign_link_create(sign_ts, E1INP_SIGN_OML, trx,
|
||||
trx->rsl_tei, SAPI_OML);
|
||||
if (!oml_link) {
|
||||
LOGP(DINP, LOGL_ERROR, "TRX (%u/%u) OML link creation "
|
||||
"failed\n", trx->bts->nr, trx->nr);
|
||||
return -ENOMEM;
|
||||
}
|
||||
if (trx->oml_link)
|
||||
e1inp_sign_link_destroy(trx->oml_link);
|
||||
trx->oml_link = oml_link;
|
||||
}
|
||||
rsl_link = e1inp_sign_link_create(sign_ts, E1INP_SIGN_RSL,
|
||||
trx, trx->rsl_tei, SAPI_RSL);
|
||||
if (!rsl_link)
|
||||
if (!rsl_link) {
|
||||
LOGP(DINP, LOGL_ERROR, "TRX (%u/%u) RSL link creation "
|
||||
"failed\n", trx->bts->nr, trx->nr);
|
||||
return -ENOMEM;
|
||||
}
|
||||
if (trx->rsl_link)
|
||||
e1inp_sign_link_destroy(trx->rsl_link);
|
||||
trx->rsl_link = rsl_link;
|
||||
@@ -90,19 +141,28 @@ int e1_reconfig_bts(struct gsm_bts *bts)
|
||||
|
||||
DEBUGP(DMI, "e1_reconfig_bts(%u)\n", bts->nr);
|
||||
|
||||
if (!e1_link->e1_ts)
|
||||
if (!e1_link->e1_ts) {
|
||||
LOGP(DINP, LOGL_ERROR, "BTS %u OML link without timeslot?\n",
|
||||
bts->nr);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* OML link */
|
||||
line = e1inp_line_get_create(e1_link->e1_nr);
|
||||
if (!line)
|
||||
line = e1inp_line_get(e1_link->e1_nr);
|
||||
if (!line) {
|
||||
LOGP(DINP, LOGL_ERROR, "BTS %u OML link referring to "
|
||||
"non-existing E1 line %u\n", bts->nr, e1_link->e1_nr);
|
||||
return -ENOMEM;
|
||||
}
|
||||
sign_ts = &line->ts[e1_link->e1_ts-1];
|
||||
e1inp_ts_config(sign_ts, line, E1INP_TS_TYPE_SIGN);
|
||||
oml_link = e1inp_sign_link_create(sign_ts, E1INP_SIGN_OML,
|
||||
bts->c0, bts->oml_tei, SAPI_OML);
|
||||
if (!oml_link)
|
||||
if (!oml_link) {
|
||||
LOGP(DINP, LOGL_ERROR, "BTS %u OML link creation failed\n",
|
||||
bts->nr);
|
||||
return -ENOMEM;
|
||||
}
|
||||
if (bts->oml_link)
|
||||
e1inp_sign_link_destroy(bts->oml_link);
|
||||
bts->oml_link = oml_link;
|
||||
|
||||
@@ -5,18 +5,17 @@
|
||||
* All Rights Reserved
|
||||
*
|
||||
* 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 2 of the License, or
|
||||
* 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.
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -55,6 +54,8 @@
|
||||
#include <openbsc/signal.h>
|
||||
#include <openbsc/misdn.h>
|
||||
|
||||
#include "../bscconfig.h"
|
||||
|
||||
#define NUM_E1_TS 32
|
||||
|
||||
/* list of all E1 drivers */
|
||||
@@ -65,9 +66,6 @@ LLIST_HEAD(e1inp_line_list);
|
||||
|
||||
static void *tall_sigl_ctx;
|
||||
|
||||
/* to be implemented, e.g. by bsc_hack.c */
|
||||
void input_event(int event, enum e1inp_sign_type type, struct gsm_bts_trx *trx);
|
||||
|
||||
/*
|
||||
* pcap writing of the misdn load
|
||||
* pcap format is from http://wiki.wireshark.org/Development/LibpcapFileFormat
|
||||
@@ -110,11 +108,11 @@ struct lapd_header {
|
||||
u_int8_t control_foo; /* fake UM's ... */
|
||||
} __attribute__((packed));
|
||||
|
||||
static_assert((int)&((struct fake_linux_lapd_header*)NULL)->hatype == 2, hatype_offset);
|
||||
static_assert((int)&((struct fake_linux_lapd_header*)NULL)->halen == 4, halen_offset);
|
||||
static_assert((int)&((struct fake_linux_lapd_header*)NULL)->addr == 6, addr_offset);
|
||||
static_assert((int)&((struct fake_linux_lapd_header*)NULL)->protocol == 14, proto_offset);
|
||||
static_assert(sizeof(struct fake_linux_lapd_header) == 16, lapd_header_size);
|
||||
static_assert(offsetof(struct fake_linux_lapd_header, hatype) == 2, hatype_offset);
|
||||
static_assert(offsetof(struct fake_linux_lapd_header, halen) == 4, halen_offset);
|
||||
static_assert(offsetof(struct fake_linux_lapd_header, addr) == 6, addr_offset);
|
||||
static_assert(offsetof(struct fake_linux_lapd_header, protocol) == 14, proto_offset);
|
||||
static_assert(sizeof(struct fake_linux_lapd_header) == 16, lapd_header_size);
|
||||
|
||||
|
||||
static int pcap_fd = -1;
|
||||
@@ -145,7 +143,6 @@ static void write_pcap_packet(int direction, int sapi, int tei,
|
||||
int ret;
|
||||
time_t cur_time;
|
||||
struct tm *tm;
|
||||
int mi_head = (direction==PCAP_INPUT) ? MISDN_HEADER_LEN : 0;
|
||||
|
||||
struct fake_linux_lapd_header header = {
|
||||
.pkttype = 4,
|
||||
@@ -167,12 +164,10 @@ static void write_pcap_packet(int direction, int sapi, int tei,
|
||||
struct pcaprec_hdr payload_header = {
|
||||
.ts_sec = 0,
|
||||
.ts_usec = 0,
|
||||
.incl_len = msg->len + sizeof(struct fake_linux_lapd_header)
|
||||
+ sizeof(struct lapd_header)
|
||||
- mi_head,
|
||||
.orig_len = msg->len + sizeof(struct fake_linux_lapd_header)
|
||||
+ sizeof(struct lapd_header)
|
||||
- mi_head,
|
||||
.incl_len = msgb_l2len(msg) + sizeof(struct fake_linux_lapd_header)
|
||||
+ sizeof(struct lapd_header),
|
||||
.orig_len = msgb_l2len(msg) + sizeof(struct fake_linux_lapd_header)
|
||||
+ sizeof(struct lapd_header),
|
||||
};
|
||||
|
||||
|
||||
@@ -183,8 +178,7 @@ static void write_pcap_packet(int direction, int sapi, int tei,
|
||||
ret = write(pcap_fd, &payload_header, sizeof(payload_header));
|
||||
ret = write(pcap_fd, &header, sizeof(header));
|
||||
ret = write(pcap_fd, &lapd_header, sizeof(lapd_header));
|
||||
ret = write(pcap_fd, msg->data + mi_head,
|
||||
msg->len - mi_head);
|
||||
ret = write(pcap_fd, msg->l2h, msgb_l2len(msg));
|
||||
}
|
||||
|
||||
static const char *sign_types[] = {
|
||||
@@ -261,7 +255,7 @@ int abis_rsl_sendmsg(struct msgb *msg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _abis_nm_sendmsg(struct msgb *msg)
|
||||
int _abis_nm_sendmsg(struct msgb *msg, int to_trx_oml)
|
||||
{
|
||||
struct e1inp_sign_link *sign_link;
|
||||
struct e1inp_driver *e1inp_driver;
|
||||
@@ -270,11 +264,18 @@ int _abis_nm_sendmsg(struct msgb *msg)
|
||||
msg->l2h = msg->data;
|
||||
|
||||
if (!msg->trx || !msg->trx->bts || !msg->trx->bts->oml_link) {
|
||||
LOGP(DRSL, LOGL_ERROR, "nm_sendmsg: msg->trx == NULL\n");
|
||||
LOGP(DNM, LOGL_ERROR, "nm_sendmsg: msg->trx == NULL\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
sign_link = msg->trx->bts->oml_link;
|
||||
/* Check for TRX-specific OML link first */
|
||||
if (to_trx_oml) {
|
||||
if (!msg->trx->oml_link)
|
||||
return -ENODEV;
|
||||
sign_link = msg->trx->oml_link;
|
||||
} else
|
||||
sign_link = msg->trx->bts->oml_link;
|
||||
|
||||
e1i_ts = sign_link->ts;
|
||||
if (!bsc_timer_pending(&e1i_ts->sign.tx_timer)) {
|
||||
/* notify the driver we have something to write */
|
||||
@@ -303,6 +304,10 @@ int e1inp_ts_config(struct e1inp_ts *ts, struct e1inp_line *line,
|
||||
|
||||
switch (type) {
|
||||
case E1INP_TS_TYPE_SIGN:
|
||||
if (line && line->driver)
|
||||
ts->sign.delay = line->driver->default_delay;
|
||||
else
|
||||
ts->sign.delay = 100000;
|
||||
INIT_LLIST_HEAD(&ts->sign.sign_links);
|
||||
break;
|
||||
case E1INP_TS_TYPE_TRAU:
|
||||
@@ -319,7 +324,7 @@ int e1inp_ts_config(struct e1inp_ts *ts, struct e1inp_line *line,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct e1inp_line *e1inp_line_get(u_int8_t e1_nr)
|
||||
struct e1inp_line *e1inp_line_get(u_int8_t e1_nr)
|
||||
{
|
||||
struct e1inp_line *e1i_line;
|
||||
|
||||
@@ -331,6 +336,43 @@ static struct e1inp_line *e1inp_line_get(u_int8_t e1_nr)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct e1inp_line *e1inp_line_create(u_int8_t e1_nr, const char *driver_name)
|
||||
{
|
||||
struct e1inp_driver *driver;
|
||||
struct e1inp_line *line;
|
||||
int i;
|
||||
|
||||
line = e1inp_line_get(e1_nr);
|
||||
if (line) {
|
||||
LOGP(DINP, LOGL_ERROR, "E1 Line %u already exists\n",
|
||||
e1_nr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
driver = e1inp_driver_find(driver_name);
|
||||
if (!driver) {
|
||||
LOGP(DINP, LOGL_ERROR, "No such E1 driver '%s'\n",
|
||||
driver_name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
line = talloc_zero(tall_bsc_ctx, struct e1inp_line);
|
||||
if (!line)
|
||||
return NULL;
|
||||
|
||||
line->driver = driver;
|
||||
|
||||
line->num = e1_nr;
|
||||
for (i = 0; i < NUM_E1_TS; i++) {
|
||||
line->ts[i].num = i+1;
|
||||
line->ts[i].line = line;
|
||||
}
|
||||
llist_add_tail(&line->list, &e1inp_line_list);
|
||||
|
||||
return line;
|
||||
}
|
||||
|
||||
#if 0
|
||||
struct e1inp_line *e1inp_line_get_create(u_int8_t e1_nr)
|
||||
{
|
||||
struct e1inp_line *line;
|
||||
@@ -353,6 +395,7 @@ struct e1inp_line *e1inp_line_get_create(u_int8_t e1_nr)
|
||||
|
||||
return line;
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct e1inp_ts *e1inp_ts_get(u_int8_t e1_nr, u_int8_t ts_nr)
|
||||
{
|
||||
@@ -439,6 +482,7 @@ int e1inp_rx_ts(struct e1inp_ts *ts, struct msgb *msg,
|
||||
u_int8_t tei, u_int8_t sapi)
|
||||
{
|
||||
struct e1inp_sign_link *link;
|
||||
struct gsm_bts *bts;
|
||||
int ret;
|
||||
|
||||
switch (ts->type) {
|
||||
@@ -456,7 +500,8 @@ int e1inp_rx_ts(struct e1inp_ts *ts, struct msgb *msg,
|
||||
switch (link->type) {
|
||||
case E1INP_SIGN_OML:
|
||||
msg->trx = link->trx;
|
||||
ret = abis_nm_rcvmsg(msg);
|
||||
bts = msg->trx->bts;
|
||||
ret = bts->model->oml_rcvmsg(msg);
|
||||
break;
|
||||
case E1INP_SIGN_RSL:
|
||||
msg->trx = link->trx;
|
||||
@@ -520,13 +565,19 @@ struct msgb *e1inp_tx_ts(struct e1inp_ts *e1i_ts,
|
||||
int e1inp_event(struct e1inp_ts *ts, int evt, u_int8_t tei, u_int8_t sapi)
|
||||
{
|
||||
struct e1inp_sign_link *link;
|
||||
struct input_signal_data isd;
|
||||
|
||||
link = e1inp_lookup_sign_link(ts, tei, sapi);
|
||||
if (!link)
|
||||
return -EINVAL;
|
||||
|
||||
/* FIXME: report further upwards */
|
||||
input_event(evt, link->type, link->trx);
|
||||
isd.link_type = link->type;
|
||||
isd.trx = link->trx;
|
||||
isd.tei = tei;
|
||||
isd.sapi = sapi;
|
||||
|
||||
/* report further upwards */
|
||||
dispatch_signal(SS_INPUT, evt, &isd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -537,9 +588,34 @@ int e1inp_driver_register(struct e1inp_driver *drv)
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct e1inp_driver *e1inp_driver_find(const char *name)
|
||||
{
|
||||
struct e1inp_driver *drv;
|
||||
|
||||
llist_for_each_entry(drv, &e1inp_driver_list, list) {
|
||||
if (!strcasecmp(name, drv->name))
|
||||
return drv;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int e1inp_line_update(struct e1inp_line *line)
|
||||
{
|
||||
return mi_e1_line_update(line);
|
||||
struct input_signal_data isd;
|
||||
int rc;
|
||||
|
||||
if (line->driver && line->driver->line_update)
|
||||
rc = line->driver->line_update(line);
|
||||
else
|
||||
rc = 0;
|
||||
|
||||
/* Send a signal to anyone who is interested in new lines being
|
||||
* configured */
|
||||
memset(&isd, 0, sizeof(isd));
|
||||
isd.line = line;
|
||||
dispatch_signal(SS_INPUT, S_INP_LINE_INIT, &isd);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int e1i_sig_cb(unsigned int subsys, unsigned int signal,
|
||||
@@ -557,9 +633,17 @@ static int e1i_sig_cb(unsigned int subsys, unsigned int signal,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __attribute__((constructor)) void on_dso_load_e1_inp(void)
|
||||
void e1inp_misdn_init(void);
|
||||
void e1inp_dahdi_init(void);
|
||||
|
||||
void e1inp_init(void)
|
||||
{
|
||||
tall_sigl_ctx = talloc_named_const(tall_bsc_ctx, 1,
|
||||
"e1inp_sign_link");
|
||||
register_signal_handler(SS_GLOBAL, e1i_sig_cb, NULL);
|
||||
|
||||
e1inp_misdn_init();
|
||||
#ifdef HAVE_DAHDI_USER_H
|
||||
e1inp_dahdi_init();
|
||||
#endif
|
||||
}
|
||||
|
||||
102
openbsc/src/e1_input_vty.c
Normal file
102
openbsc/src/e1_input_vty.c
Normal file
@@ -0,0 +1,102 @@
|
||||
/* OpenBSC E1 vty interface */
|
||||
/* (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 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 <unistd.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <osmocom/vty/command.h>
|
||||
#include <osmocom/vty/buffer.h>
|
||||
#include <osmocom/vty/vty.h>
|
||||
#include <osmocom/vty/logging.h>
|
||||
#include <osmocom/vty/telnet_interface.h>
|
||||
|
||||
#include <osmocore/linuxlist.h>
|
||||
#include <openbsc/gsm_data.h>
|
||||
#include <openbsc/e1_input.h>
|
||||
#include <osmocore/utils.h>
|
||||
#include <osmocore/gsm_utils.h>
|
||||
#include <osmocore/talloc.h>
|
||||
#include <openbsc/vty.h>
|
||||
#include <openbsc/debug.h>
|
||||
|
||||
#include "../bscconfig.h"
|
||||
|
||||
#define E1_DRIVER_NAMES "(misdn|dahdi)"
|
||||
#define E1_DRIVER_HELP "mISDN supported E1 Card\n" \
|
||||
"DAHDI supported E1/T1/J1 Card\n"
|
||||
|
||||
DEFUN(cfg_e1line_driver, cfg_e1_line_driver_cmd,
|
||||
"e1_line <0-255> driver " E1_DRIVER_NAMES,
|
||||
"Configure E1/T1/J1 Line\n" "Line Number\n" "Set driver for this line\n"
|
||||
E1_DRIVER_HELP)
|
||||
{
|
||||
struct e1inp_line *line;
|
||||
int e1_nr = atoi(argv[0]);
|
||||
|
||||
line = e1inp_line_get(e1_nr);
|
||||
if (line) {
|
||||
vty_out(vty, "%% Line %d already exists%s", e1_nr, VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
line = e1inp_line_create(e1_nr, argv[1]);
|
||||
if (!line) {
|
||||
vty_out(vty, "%% Error creating line %d%s", e1_nr, VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_e1inp, cfg_e1inp_cmd,
|
||||
"e1_input",
|
||||
"Configure E1/T1/J1 TDM input\n")
|
||||
{
|
||||
vty->node = E1INP_NODE;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
static int e1inp_config_write(struct vty *vty)
|
||||
{
|
||||
struct e1inp_line *line;
|
||||
|
||||
vty_out(vty, "e1_input%s", VTY_NEWLINE);
|
||||
|
||||
llist_for_each_entry(line, &e1inp_line_list, list) {
|
||||
vty_out(vty, " e1_line %u driver %s%s", line->num,
|
||||
line->driver->name, VTY_NEWLINE);
|
||||
}
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
struct cmd_node e1inp_node = {
|
||||
E1INP_NODE,
|
||||
"%s(e1_input)#",
|
||||
1,
|
||||
};
|
||||
|
||||
int e1inp_vty_init(void)
|
||||
{
|
||||
install_element(CONFIG_NODE, &cfg_e1inp_cmd);
|
||||
install_node(&e1inp_node, e1inp_config_write);
|
||||
install_element(E1INP_NODE, &cfg_e1_line_driver_cmd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
2
openbsc/src/gprs/.gitignore
vendored
Normal file
2
openbsc/src/gprs/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
gsn_restart
|
||||
osmo_*.cfg*
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user