mirror of
https://gitea.osmocom.org/cellular-infrastructure/osmo-bts.git
synced 2025-11-12 09:57:54 +00:00
Compare commits
768 Commits
shared/31c
...
0.7.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a5ed03fe5c | ||
|
|
6bf97927f1 | ||
|
|
a39dab4b7c | ||
|
|
2757cbc2a8 | ||
|
|
9982b95069 | ||
|
|
bf9298eb0f | ||
|
|
fe291a97c2 | ||
|
|
36fa0bd079 | ||
|
|
0a21b7a5f8 | ||
|
|
0c9bc5422a | ||
|
|
8c9bc5c6c7 | ||
|
|
3552247ae8 | ||
|
|
2d3aa02ba3 | ||
|
|
236269397e | ||
|
|
d49915eccf | ||
|
|
ec33b0397f | ||
|
|
8a89c7d3c3 | ||
|
|
ab4696bb2f | ||
|
|
9605b695fa | ||
|
|
ae134f896a | ||
|
|
cb9f608094 | ||
|
|
9e36dca82a | ||
|
|
bbf6c435f6 | ||
|
|
6384c73fbf | ||
|
|
fab4efdaf5 | ||
|
|
1283e3d543 | ||
|
|
b026d38703 | ||
|
|
8876a507ff | ||
|
|
aa11997480 | ||
|
|
9a30b77813 | ||
|
|
01e84be54f | ||
|
|
2bbf98afa3 | ||
|
|
4d5df2ebd1 | ||
|
|
ed662e0799 | ||
|
|
b0578dda95 | ||
|
|
d4450051fc | ||
|
|
b78fc1eeee | ||
|
|
69ec4a419e | ||
|
|
506a7f98b2 | ||
|
|
fb78397cbd | ||
|
|
fe6c75d24a | ||
|
|
bd65b72f91 | ||
|
|
cd1b08b14f | ||
|
|
bc56094cac | ||
|
|
de99be4afb | ||
|
|
d1f8001cdf | ||
|
|
6fe823a7e1 | ||
|
|
d208132ab9 | ||
|
|
dc469994f3 | ||
|
|
82987f7a7d | ||
|
|
d6da809d2f | ||
|
|
69e0461674 | ||
|
|
bbd4d54e46 | ||
|
|
8edfe03595 | ||
|
|
cbb64cffa5 | ||
|
|
824764fa6b | ||
|
|
db4ab8e5ce | ||
|
|
69de62a573 | ||
|
|
9dccaa2064 | ||
|
|
0ebf985492 | ||
|
|
8785978c37 | ||
|
|
0e9dadc3d8 | ||
|
|
d7546ed090 | ||
|
|
f66d2fc1e6 | ||
|
|
2d2fca4342 | ||
|
|
b2bbc81921 | ||
|
|
91cecc051a | ||
|
|
173a4f1f79 | ||
|
|
f690e5d45c | ||
|
|
a59fb6220b | ||
|
|
df07f0a9cb | ||
|
|
3617fd1cb6 | ||
|
|
e0e2b9e303 | ||
|
|
576408b651 | ||
|
|
e3b8279f26 | ||
|
|
6feae225eb | ||
|
|
3cda4ff532 | ||
|
|
1f45db0ff5 | ||
|
|
81335edae3 | ||
|
|
5eb17e28ac | ||
|
|
152c2f489c | ||
|
|
9a2187e7b1 | ||
|
|
65db0f5c41 | ||
|
|
9a280eba48 | ||
|
|
7887ce7aea | ||
|
|
6a538a0921 | ||
|
|
390742b3ed | ||
|
|
f06ba300c4 | ||
|
|
ffdc05bc4e | ||
|
|
c2d3f14bfb | ||
|
|
f588b5f91d | ||
|
|
0bd7a19114 | ||
|
|
aa15504097 | ||
|
|
3ae0be0f12 | ||
|
|
523ae04e5e | ||
|
|
171d80a8d6 | ||
|
|
8baa45a8e3 | ||
|
|
3902e4d9c4 | ||
|
|
9b97d0f683 | ||
|
|
a38d34112f | ||
|
|
cc1602f592 | ||
|
|
f2eaba8869 | ||
|
|
cdf20fec7c | ||
|
|
bb71947829 | ||
|
|
c19ab9ed2f | ||
|
|
7738f5282f | ||
|
|
0ada527bc0 | ||
|
|
dd3c7815a5 | ||
|
|
b7425f3642 | ||
|
|
8d645dd0e5 | ||
|
|
250d77f8df | ||
|
|
53ce11ab95 | ||
|
|
59d0c2cca6 | ||
|
|
5047fbe3b8 | ||
|
|
521ab50dcc | ||
|
|
ae7ece1064 | ||
|
|
4962ed1811 | ||
|
|
d0846651a3 | ||
|
|
620bd83b12 | ||
|
|
2a4c5fa2b3 | ||
|
|
4699ebaa26 | ||
|
|
7a6b178fc0 | ||
|
|
53216b5d1f | ||
|
|
50f8165540 | ||
|
|
61f9158eaf | ||
|
|
1ba0cfe9c0 | ||
|
|
9d294c9cb1 | ||
|
|
5466ff9c1b | ||
|
|
94bdcfd803 | ||
|
|
114293a414 | ||
|
|
d4806db1e5 | ||
|
|
71ad40c647 | ||
|
|
5b87144f91 | ||
|
|
d5971d0681 | ||
|
|
aa5edff477 | ||
|
|
f4544573f8 | ||
|
|
186c6bac07 | ||
|
|
340cff51f4 | ||
|
|
0b7a3e9f62 | ||
|
|
0227e4d04c | ||
|
|
61d36212b1 | ||
|
|
de9357251c | ||
|
|
b7793ed8fd | ||
|
|
1dcbee3420 | ||
|
|
78a5073dfb | ||
|
|
16b8f51839 | ||
|
|
0e7886d379 | ||
|
|
3e2de526b0 | ||
|
|
88b2cc30a6 | ||
|
|
67d3b8b136 | ||
|
|
95d2505e57 | ||
|
|
d22b5b84c0 | ||
|
|
d5fdcfe6d9 | ||
|
|
e3a3906ee9 | ||
|
|
8a8d73a691 | ||
|
|
d36b3a8463 | ||
|
|
e91cd2b088 | ||
|
|
9eeb0b1a13 | ||
|
|
a8bf666a09 | ||
|
|
cb5a969a45 | ||
|
|
450714b19c | ||
|
|
43c763f5af | ||
|
|
440930be44 | ||
|
|
05ba5c2a10 | ||
|
|
3f97e4b1fc | ||
|
|
538475259c | ||
|
|
524e3e3170 | ||
|
|
ed9e022eb4 | ||
|
|
a493ce9e66 | ||
|
|
031e8fedac | ||
|
|
b4c9c8f35d | ||
|
|
ed51c3d145 | ||
|
|
72993079ed | ||
|
|
e0fb3ae52d | ||
|
|
27b022e0c4 | ||
|
|
3aeb9301f4 | ||
|
|
efbef50efc | ||
|
|
9c1d3f9606 | ||
|
|
2f028c4e2c | ||
|
|
67d8c72c2e | ||
|
|
b16eed22c7 | ||
|
|
2c841100a9 | ||
|
|
17a09507b8 | ||
|
|
e3de64cd67 | ||
|
|
22704a88e2 | ||
|
|
2d848a061e | ||
|
|
8913b29be2 | ||
|
|
028820510e | ||
|
|
9563039a2a | ||
|
|
9d5ec1af74 | ||
|
|
91685096f8 | ||
|
|
40dca8f991 | ||
|
|
d62a58dbfb | ||
|
|
322252d793 | ||
|
|
fce5b31b94 | ||
|
|
b4bf603c98 | ||
|
|
25742a5929 | ||
|
|
e4403464ed | ||
|
|
7a21dccec1 | ||
|
|
d040bf97de | ||
|
|
1fde15c8bd | ||
|
|
8e7a51d8c3 | ||
|
|
416ee3ec89 | ||
|
|
dafb363533 | ||
|
|
bbe90fd651 | ||
|
|
e16b593574 | ||
|
|
957843959d | ||
|
|
f4816fa577 | ||
|
|
a80c7024f8 | ||
|
|
b609ee879e | ||
|
|
f9eef0ce3e | ||
|
|
83c4fbc2dc | ||
|
|
f462c87581 | ||
|
|
339b9329ff | ||
|
|
9dfdf54d30 | ||
|
|
6f5e398ccb | ||
|
|
a1b891aab4 | ||
|
|
4acc98e68a | ||
|
|
758522947f | ||
|
|
64d16028eb | ||
|
|
70c68853c2 | ||
|
|
6b4c6aa375 | ||
|
|
c4ac69dcc2 | ||
|
|
b390dfb90d | ||
|
|
0418ef588c | ||
|
|
e2e0ed5a89 | ||
|
|
d5414cc30e | ||
|
|
ae50f7dac2 | ||
|
|
7a18906cfa | ||
|
|
d15dc832c9 | ||
|
|
1631266993 | ||
|
|
3c144069da | ||
|
|
69d297ce75 | ||
|
|
df5ac9aa11 | ||
|
|
13d0feb404 | ||
|
|
4ba7363286 | ||
|
|
eb4a3392e1 | ||
|
|
1beb9bcbe0 | ||
|
|
1965b0d880 | ||
|
|
67bc885c5d | ||
|
|
a760a043c4 | ||
|
|
16b4179fbe | ||
|
|
42ffb325f8 | ||
|
|
9344080109 | ||
|
|
8c45ae59f9 | ||
|
|
d81e5e963a | ||
|
|
c1d8f5a490 | ||
|
|
f65b57a707 | ||
|
|
871e0bec7e | ||
|
|
10b11325a7 | ||
|
|
8be9d7a6fe | ||
|
|
ea5ccfa481 | ||
|
|
2b763cc30c | ||
|
|
70b71507c2 | ||
|
|
c37fd88985 | ||
|
|
1e399f888e | ||
|
|
0e5b12f981 | ||
|
|
df75195666 | ||
|
|
b76043e6f4 | ||
|
|
de6d25e21d | ||
|
|
4723a19508 | ||
|
|
962b33ea9d | ||
|
|
563b744b38 | ||
|
|
792573dc97 | ||
|
|
ec11a85929 | ||
|
|
c038cb7903 | ||
|
|
94dd5060c8 | ||
|
|
2cf6b73a42 | ||
|
|
f3763590bd | ||
|
|
bfd42c2b0a | ||
|
|
f9778b2a26 | ||
|
|
c2ecca6b04 | ||
|
|
86d7843712 | ||
|
|
304420ca42 | ||
|
|
fbe655f320 | ||
|
|
fed8ce3c5a | ||
|
|
2c95ae6a09 | ||
|
|
a1fa955212 | ||
|
|
55a7b07417 | ||
|
|
960dd993cd | ||
|
|
20363d165e | ||
|
|
4a85828462 | ||
|
|
b58aa60d78 | ||
|
|
36153239bf | ||
|
|
aabeb2eae4 | ||
|
|
f4b238f91e | ||
|
|
103ddc7155 | ||
|
|
704fba5dc2 | ||
|
|
dd8a4a85e4 | ||
|
|
6f4ce14ed7 | ||
|
|
8ea93a8a7d | ||
|
|
ae5405e2a4 | ||
|
|
be671bc61f | ||
|
|
f7b559f960 | ||
|
|
b2fbdd023b | ||
|
|
66325aee71 | ||
|
|
bdf10eb705 | ||
|
|
c43352dbc4 | ||
|
|
c757272443 | ||
|
|
388a91cbd1 | ||
|
|
5ee3dba39f | ||
|
|
9f936344ea | ||
|
|
57b5fb8819 | ||
|
|
203ea2c209 | ||
|
|
38843fbf48 | ||
|
|
acfccb3f02 | ||
|
|
4008ebb925 | ||
|
|
9d102508a8 | ||
|
|
bce25a60f4 | ||
|
|
efb4a4baeb | ||
|
|
64a2bd72f5 | ||
|
|
ced9a5d0e2 | ||
|
|
5a4f4d12e1 | ||
|
|
c22da59342 | ||
|
|
068918f990 | ||
|
|
c88a10cece | ||
|
|
ebb483b69a | ||
|
|
b0c1d21581 | ||
|
|
21142f7898 | ||
|
|
b058778df1 | ||
|
|
de9dbe7958 | ||
|
|
babd05661d | ||
|
|
c09e5a44c3 | ||
|
|
93f3102da9 | ||
|
|
b8b939faa9 | ||
|
|
4ca5be766c | ||
|
|
9f9b96a67b | ||
|
|
c1b86d80d1 | ||
|
|
8b39ff8bcf | ||
|
|
f5494e84e8 | ||
|
|
3f192f2291 | ||
|
|
fac02d3d75 | ||
|
|
5f2e2de84f | ||
|
|
067ef3f1ce | ||
|
|
9959f45d90 | ||
|
|
7dffd553df | ||
|
|
94fa25295f | ||
|
|
1559678fa2 | ||
|
|
654175f33b | ||
|
|
eb08a87be5 | ||
|
|
a570e05ec8 | ||
|
|
e2069d968c | ||
|
|
c77b574d1f | ||
|
|
70460814ce | ||
|
|
527dd402c7 | ||
|
|
80473a113d | ||
|
|
0a05181603 | ||
|
|
b4969cc915 | ||
|
|
a91b2d9691 | ||
|
|
ac84afa409 | ||
|
|
d44f0772f9 | ||
|
|
3cc91746a3 | ||
|
|
c9a1f284ac | ||
|
|
ed6b48e4a5 | ||
|
|
8431bbb80f | ||
|
|
bf6bae2b23 | ||
|
|
8a148613b4 | ||
|
|
4dfc3da96b | ||
|
|
9faaf4ecf0 | ||
|
|
3b2e5de3ae | ||
|
|
988f634c97 | ||
|
|
e77bcaecb6 | ||
|
|
43d082e6f1 | ||
|
|
55c46022e1 | ||
|
|
37af36e85e | ||
|
|
63849ebf71 | ||
|
|
67a056c122 | ||
|
|
ef8e2ef681 | ||
|
|
b7cdd381d6 | ||
|
|
4b76a323b3 | ||
|
|
b0f8fa8143 | ||
|
|
44663c17e7 | ||
|
|
d6920df630 | ||
|
|
af3443385b | ||
|
|
0d4b37d641 | ||
|
|
45d3bbfb44 | ||
|
|
576071d6ca | ||
|
|
5069c1c518 | ||
|
|
108b60faba | ||
|
|
ba656fff91 | ||
|
|
2b34ae32cf | ||
|
|
53d792c3b0 | ||
|
|
dab54b9178 | ||
|
|
9407e644b0 | ||
|
|
e07ba54d62 | ||
|
|
a888e95efa | ||
|
|
dd34540ce4 | ||
|
|
7b186adb0a | ||
|
|
b0f77ce685 | ||
|
|
090a41f897 | ||
|
|
78458a3811 | ||
|
|
21ffe07894 | ||
|
|
6e656748b7 | ||
|
|
73cb583e51 | ||
|
|
c9582ac2d7 | ||
|
|
c57304b65e | ||
|
|
9ab51522da | ||
|
|
8e22ac3d1a | ||
|
|
ee2299c8fa | ||
|
|
95dec9ff4a | ||
|
|
334df9441a | ||
|
|
290c7d954f | ||
|
|
7f1365c05e | ||
|
|
2479ef4133 | ||
|
|
ae65ccd0b2 | ||
|
|
8a2f026cf0 | ||
|
|
4355021b8a | ||
|
|
2ed03cd640 | ||
|
|
cff0d44e53 | ||
|
|
b8f5f4e176 | ||
|
|
b151301c6c | ||
|
|
1c1b0e843d | ||
|
|
e3edc17426 | ||
|
|
7267a0d37e | ||
|
|
d5f95c308b | ||
|
|
bb1e3b089b | ||
|
|
c03d3ae7af | ||
|
|
5c0d88e69d | ||
|
|
4fa641d7b2 | ||
|
|
64e3813b06 | ||
|
|
9797a72cd7 | ||
|
|
99642656a0 | ||
|
|
c2874c4360 | ||
|
|
3f919171ef | ||
|
|
a4c6802315 | ||
|
|
0eaa27a6be | ||
|
|
037dcfe981 | ||
|
|
380a2e6d90 | ||
|
|
ccb1148717 | ||
|
|
724412a49a | ||
|
|
f0d6d6ba02 | ||
|
|
dd084e6e57 | ||
|
|
61372a20de | ||
|
|
c3fb0dcc8c | ||
|
|
274d29bedd | ||
|
|
7efc2f3c5b | ||
|
|
b231e0f6cd | ||
|
|
63b296bdd9 | ||
|
|
57fc1124e1 | ||
|
|
294fbe104b | ||
|
|
24a31cfe43 | ||
|
|
0d10f0e482 | ||
|
|
f8bf95fa6b | ||
|
|
e6cc04827a | ||
|
|
9375aa9a68 | ||
|
|
bfc9ff3118 | ||
|
|
6b60611a4d | ||
|
|
bc9c42663d | ||
|
|
8a75e60d0c | ||
|
|
ae2a8b75f9 | ||
|
|
3686005180 | ||
|
|
ea40bd60e7 | ||
|
|
a8168271eb | ||
|
|
e951042475 | ||
|
|
65efa691f8 | ||
|
|
6ab1ed580d | ||
|
|
213db32e30 | ||
|
|
703c2d6eb8 | ||
|
|
ecd5bc2aef | ||
|
|
7cc3c3156e | ||
|
|
58e4e18206 | ||
|
|
cbbce0be09 | ||
|
|
d0d2c9217a | ||
|
|
7158c2ed08 | ||
|
|
a55b166c6c | ||
|
|
3f3f34ba52 | ||
|
|
495fed9f43 | ||
|
|
a10ac248c6 | ||
|
|
60970056c8 | ||
|
|
8ecadc66ce | ||
|
|
9302abe054 | ||
|
|
45e97ac59a | ||
|
|
3a1f1b8e91 | ||
|
|
4582222757 | ||
|
|
c1586388dc | ||
|
|
51bfebec39 | ||
|
|
ef30f50d5d | ||
|
|
201b424b73 | ||
|
|
0778cd488a | ||
|
|
ed494443cc | ||
|
|
b61850248a | ||
|
|
c8da1ac9a6 | ||
|
|
227015e52e | ||
|
|
460e1b7387 | ||
|
|
21fc6e45fb | ||
|
|
925fcf48ed | ||
|
|
0fe3b215b9 | ||
|
|
06968beab9 | ||
|
|
ae5a737c18 | ||
|
|
c4fc00d851 | ||
|
|
3044a26d71 | ||
|
|
b857f27704 | ||
|
|
9591b6c253 | ||
|
|
bb0cc685f1 | ||
|
|
6044785a22 | ||
|
|
b2b1112a6e | ||
|
|
f3ee66207d | ||
|
|
0be80aa2d1 | ||
|
|
710e99c2e3 | ||
|
|
40e8365854 | ||
|
|
d5c658b22e | ||
|
|
91565b2d51 | ||
|
|
2278fdc580 | ||
|
|
cb20c83323 | ||
|
|
94bb3769f3 | ||
|
|
e81cc6a158 | ||
|
|
69b959e557 | ||
|
|
ad7f7a7117 | ||
|
|
81cc8cdba5 | ||
|
|
e634fd256b | ||
|
|
433863e4c9 | ||
|
|
634c3e4648 | ||
|
|
a9a7120c82 | ||
|
|
5dfb115eaf | ||
|
|
c6723c8206 | ||
|
|
3b4d9e7c07 | ||
|
|
53e0291df6 | ||
|
|
e9a17292e8 | ||
|
|
9b5cff87ec | ||
|
|
9684099ae9 | ||
|
|
38933afdd9 | ||
|
|
6a0f0f9e21 | ||
|
|
4dd8bd84a4 | ||
|
|
8f0266b885 | ||
|
|
234309878e | ||
|
|
1dcb97eaa3 | ||
|
|
29a0197ead | ||
|
|
ccc7a1bf46 | ||
|
|
b936bd7162 | ||
|
|
6e1aed4b23 | ||
|
|
2a711887b7 | ||
|
|
5a945dad0c | ||
|
|
b1d2dd316f | ||
|
|
f5b42c3421 | ||
|
|
a02bf125ac | ||
|
|
fcef6b2b52 | ||
|
|
d784e50747 | ||
|
|
f58542899a | ||
|
|
1a5b00ebe2 | ||
|
|
48726242ad | ||
|
|
67311cc1f2 | ||
|
|
b6b42d150d | ||
|
|
11db925f15 | ||
|
|
2b0e209029 | ||
|
|
5538f5cff8 | ||
|
|
5f17720fcd | ||
|
|
5d212055b7 | ||
|
|
6f9beedc48 | ||
|
|
131ab36e3a | ||
|
|
2ed116efec | ||
|
|
5f8c85bf9c | ||
|
|
3ca59512d2 | ||
|
|
111a02f214 | ||
|
|
0d19e48487 | ||
|
|
728448a7f1 | ||
|
|
0db18d030d | ||
|
|
0048a788dd | ||
|
|
611ef23700 | ||
|
|
a0192b859b | ||
|
|
ec3be11ec6 | ||
|
|
69fc57b028 | ||
|
|
32d681ab98 | ||
|
|
e60b9d1de6 | ||
|
|
3d431bb4eb | ||
|
|
5e8d8a1e75 | ||
|
|
f9de18ea15 | ||
|
|
97cb71971a | ||
|
|
dd562d84ba | ||
|
|
773ab8b2c5 | ||
|
|
69ace680dd | ||
|
|
1bdd08d07d | ||
|
|
519a639cf3 | ||
|
|
6323d2e617 | ||
|
|
601781f463 | ||
|
|
695d8eb277 | ||
|
|
5b500f5d8f | ||
|
|
2bf00d7729 | ||
|
|
12992d86dc | ||
|
|
d93bd21185 | ||
|
|
8250800d3b | ||
|
|
6d101a79a8 | ||
|
|
20e8770df0 | ||
|
|
866f9b979d | ||
|
|
3e98f942e5 | ||
|
|
7bd2251dcb | ||
|
|
0c017618cd | ||
|
|
8d198f3598 | ||
|
|
bca8d3b8f8 | ||
|
|
a9003acb1c | ||
|
|
dad89e50a2 | ||
|
|
b92100ad36 | ||
|
|
e9f12acbeb | ||
|
|
7d6860b114 | ||
|
|
056c267b89 | ||
|
|
2b7728cd9d | ||
|
|
65b4a7ba2b | ||
|
|
74269054a6 | ||
|
|
a62e3221b6 | ||
|
|
085569df55 | ||
|
|
21b020b336 | ||
|
|
e28a20a2d9 | ||
|
|
2da932c7a0 | ||
|
|
2ecbf87130 | ||
|
|
62d7502b82 | ||
|
|
2d5481da27 | ||
|
|
44bc9408b1 | ||
|
|
02337e1d1d | ||
|
|
437deb5f3a | ||
|
|
48e99fd05a | ||
|
|
3c161bb7df | ||
|
|
bbcf703be8 | ||
|
|
94da045be5 | ||
|
|
33f234f278 | ||
|
|
55d89d17b2 | ||
|
|
94a05abb98 | ||
|
|
45e597cc16 | ||
|
|
9a9ddc1203 | ||
|
|
13947b3408 | ||
|
|
1009a87f3c | ||
|
|
f1fb0fa3af | ||
|
|
caa648d92e | ||
|
|
88a31e2a99 | ||
|
|
307bfc81c1 | ||
|
|
5becc4613a | ||
|
|
b812839dfa | ||
|
|
ae525a8761 | ||
|
|
29ea40f538 | ||
|
|
e9abc5a4f3 | ||
|
|
17be7fa73b | ||
|
|
68e8b2b1d5 | ||
|
|
391ff14977 | ||
|
|
cf18dcd5fd | ||
|
|
6fceaca584 | ||
|
|
ddc0bf14d5 | ||
|
|
deb01a2652 | ||
|
|
3cfc9d5fa3 | ||
|
|
a7d0c5ef5a | ||
|
|
f39c739bd6 | ||
|
|
f66f5b3ddc | ||
|
|
c241afa87c | ||
|
|
178d618d5a | ||
|
|
c9ddb2ba22 | ||
|
|
73d3f46994 | ||
|
|
b2482a8574 | ||
|
|
812fdd92c7 | ||
|
|
ec6225e3e0 | ||
|
|
ef6eb5442c | ||
|
|
f0072a8de8 | ||
|
|
3cf28aa924 | ||
|
|
578340c7a7 | ||
|
|
3caf3b7c45 | ||
|
|
ee47913389 | ||
|
|
f5aaf523c5 | ||
|
|
8c8998e551 | ||
|
|
da0c44a9db | ||
|
|
798c1bba9d | ||
|
|
db0b93ac39 | ||
|
|
86c936cbb1 | ||
|
|
b9a917a138 | ||
|
|
6527dffc94 | ||
|
|
fb04746bce | ||
|
|
05597a7ddb | ||
|
|
82676c13ee | ||
|
|
c2ee307fd4 | ||
|
|
2e4a26a0e9 | ||
|
|
6508f21130 | ||
|
|
c5241c3aa4 | ||
|
|
c910a332b2 | ||
|
|
f62a64e440 | ||
|
|
a7f5e07712 | ||
|
|
5e2341411f | ||
|
|
917cf7018b | ||
|
|
84b9a44535 | ||
|
|
7ff22823ca | ||
|
|
9855e8bd48 | ||
|
|
219ece83a3 | ||
|
|
889890da43 | ||
|
|
23a5183767 | ||
|
|
ce0f20b597 | ||
|
|
7bd6e8b89b | ||
|
|
d692b6e054 | ||
|
|
89e36c0e64 | ||
|
|
801c182c02 | ||
|
|
7451ce29a7 | ||
|
|
450d32919a | ||
|
|
78b2080027 | ||
|
|
9de67ca962 | ||
|
|
b9880bc812 | ||
|
|
d10eaee4cc | ||
|
|
b104aed5ec | ||
|
|
cd463dd72a | ||
|
|
7d684d6866 | ||
|
|
e0959e7929 | ||
|
|
2ea68e2b7b | ||
|
|
2c8787224f | ||
|
|
74d63b7212 | ||
|
|
d0603d96e9 | ||
|
|
414faaca19 | ||
|
|
7a0d11dd68 | ||
|
|
cd0581d815 | ||
|
|
1de7085d31 | ||
|
|
acc71ffb4b | ||
|
|
c64fa4f888 | ||
|
|
79bc80102c | ||
|
|
5fa388c366 | ||
|
|
75f105bbb5 | ||
|
|
2340b88ede | ||
|
|
329085a8ff | ||
|
|
819b50e1a7 | ||
|
|
f449842053 | ||
|
|
9cfbf27d4c | ||
|
|
a450ef73ed | ||
|
|
04b5d65575 | ||
|
|
90e543bd83 | ||
|
|
75caaf2949 | ||
|
|
5027e122a8 | ||
|
|
a313bb0a47 | ||
|
|
923e324abc | ||
|
|
bac087c207 | ||
|
|
80f039973e | ||
|
|
3a381367a6 | ||
|
|
12472df8f0 | ||
|
|
7cc199ea95 | ||
|
|
793e713c4b | ||
|
|
faba84b9b7 | ||
|
|
7cf313c75b | ||
|
|
21b5e6318e | ||
|
|
4fe00da9f8 | ||
|
|
75be092b99 | ||
|
|
c9441b3c0b | ||
|
|
ace9a8742f | ||
|
|
54eceac257 | ||
|
|
d410eb9787 | ||
|
|
9ae5b50d78 | ||
|
|
52476fc1d4 | ||
|
|
e969f08892 | ||
|
|
7b1b832618 | ||
|
|
e0146997a6 | ||
|
|
a391d3691a | ||
|
|
5e90f2a809 | ||
|
|
1eaa3d72ea | ||
|
|
668f8df3be | ||
|
|
cc4a08bdc7 | ||
|
|
862807504b | ||
|
|
a7c276b72b | ||
|
|
f869a95f3b | ||
|
|
0ddd4b6c25 | ||
|
|
24839068f5 | ||
|
|
b631bd21d2 | ||
|
|
579651bf30 | ||
|
|
0d6946741c | ||
|
|
7e10bd6401 | ||
|
|
84e4dd92d4 | ||
|
|
55da9874c0 | ||
|
|
d8d5f5904f | ||
|
|
9acc82ce4a | ||
|
|
c017e309c4 | ||
|
|
2e59b20204 | ||
|
|
fd425b1484 | ||
|
|
50131c125e | ||
|
|
5a03e129a6 | ||
|
|
b7ebf545e6 | ||
|
|
8fc2630dd4 | ||
|
|
bd988f6ad3 | ||
|
|
1e245336ec | ||
|
|
4457c0d9ba | ||
|
|
660116fb9d | ||
|
|
b15d2c9d2f |
30
.gitignore
vendored
30
.gitignore
vendored
@@ -25,10 +25,21 @@ core.*
|
||||
contrib/sysmobts-calib/sysmobts-calib
|
||||
|
||||
src/osmo-bts-sysmo/l1fwd-proxy
|
||||
src/osmo-bts-sysmo/sysmobts
|
||||
src/osmo-bts-sysmo/sysmobts-remote
|
||||
src/osmo-bts-sysmo/osmo-bts-sysmo
|
||||
src/osmo-bts-sysmo/osmo-bts-sysmo-remote
|
||||
src/osmo-bts-sysmo/sysmobts-mgr
|
||||
src/osmo-bts-sysmo/sysmobts-util
|
||||
|
||||
src/osmo-bts-litecell15/lc15bts-mgr
|
||||
src/osmo-bts-litecell15/lc15bts-util
|
||||
src/osmo-bts-litecell15/misc/.dirstamp
|
||||
src/osmo-bts-litecell15/osmo-bts-lc15
|
||||
|
||||
src/osmo-bts-trx/osmo-bts-trx
|
||||
|
||||
src/osmo-bts-octphy/osmo-bts-octphy
|
||||
|
||||
src/osmo-bts-virtual/osmo-bts-virtual
|
||||
|
||||
tests/atconfig
|
||||
tests/package.m4
|
||||
@@ -37,6 +48,8 @@ tests/paging/paging_test
|
||||
tests/cipher/cipher_test
|
||||
tests/sysmobts/sysmobts_test
|
||||
tests/misc/misc_test
|
||||
tests/handover/handover_test
|
||||
tests/tx_power/tx_power_test
|
||||
tests/testsuite
|
||||
tests/testsuite.log
|
||||
|
||||
@@ -44,6 +57,19 @@ tests/testsuite.log
|
||||
doc/vty_reference.xml
|
||||
|
||||
# Backups, vi, merges
|
||||
*~
|
||||
*.sw?
|
||||
*.orig
|
||||
*.sav
|
||||
|
||||
# debian
|
||||
.tarball-version
|
||||
debian/autoreconf.after
|
||||
debian/autoreconf.before
|
||||
debian/files
|
||||
debian/*.debhelper.log
|
||||
debian/*.substvars
|
||||
debian/osmo-bts-trx-dbg/
|
||||
debian/osmo-bts-trx/
|
||||
debian/tmp/
|
||||
/tests/power/power_test
|
||||
|
||||
3
.gitreview
Normal file
3
.gitreview
Normal file
@@ -0,0 +1,3 @@
|
||||
[gerrit]
|
||||
host=gerrit.osmocom.org
|
||||
project=osmo-bts
|
||||
12
.mailmap
Normal file
12
.mailmap
Normal file
@@ -0,0 +1,12 @@
|
||||
Harald Welte <laforge@gnumonks.org>
|
||||
Harald Welte <laforge@gnumonks.org> <laflocal@hanuman.gnumonks.org>
|
||||
Harald Welte <laforge@gnumonks.org> <laflocal@goeller.de.gnumonks.org>
|
||||
Holger Hans Peter Freyther <holger@moiji-mobile.com> <zecke@selfish.org>
|
||||
Holger Hans Peter Freyther <holger@moiji-mobile.com> <ich@tamarin.(none)>
|
||||
Holger Hans Peter Freyther <holgre@moiji-mobile.com> <holger@freyther.de>
|
||||
Andreas Eversberg <jolly@eversberg.eu>
|
||||
Andreas Eversberg <jolly@eversberg.eu> <Andreas.Eversberg@versatel.de>
|
||||
Andreas Eversberg <jolly@eversberg.eu> <root@nuedel.(none)>
|
||||
Pablo Neira Ayuso <pablo@soleta.eu> <pablo@gnumonks.org>
|
||||
Max Suraev <msuraev@sysmocom.de>
|
||||
Tom Tsou <tom.tsou@ettus.com> <tom@tsou.cc>
|
||||
19
Makefile.am
19
Makefile.am
@@ -5,11 +5,24 @@ SUBDIRS = include src tests
|
||||
|
||||
# package the contrib and doc
|
||||
EXTRA_DIST = \
|
||||
contrib/dump_docs.py contrib/screenrc-l1fwd contrib/sysmobts.service \
|
||||
contrib/dump_docs.py contrib/screenrc-l1fwd contrib/osmo-bts-sysmo.service \
|
||||
contrib/l1fwd.init contrib/screenrc-sysmobts contrib/respawn.sh \
|
||||
contrib/sysmobts.init contrib/sysmobts-calib/Makefile \
|
||||
contrib/sysmobts-calib/sysmobts-calib.c \
|
||||
contrib/sysmobts-calib/sysmobts-layer1.c \
|
||||
contrib/sysmobts-calib/sysmobts-layer1.h \
|
||||
doc/examples/osmo-bts.cfg \
|
||||
doc/examples/sysmobts-mgr.cfg
|
||||
doc/examples/sysmo/osmo-bts.cfg \
|
||||
doc/examples/sysmo/sysmobts-mgr.cfg \
|
||||
doc/examples/virtual/openbsc-virtual.cfg \
|
||||
doc/examples/virtual/osmobts-virtual.cfg \
|
||||
git-version-gen .version \
|
||||
README.md
|
||||
|
||||
@RELMAKE@
|
||||
|
||||
BUILT_SOURCES = $(top_srcdir)/.version
|
||||
|
||||
$(top_srcdir)/.version:
|
||||
echo $(VERSION) > $@-t && mv $@-t $@
|
||||
dist-hook:
|
||||
echo $(VERSION) > $(distdir)/.tarball-version
|
||||
|
||||
59
README
59
README
@@ -1,59 +0,0 @@
|
||||
Repository for new the Osmocom BTS implementation.
|
||||
|
||||
This code implementes the Layer 2 and higher of a more or less
|
||||
conventional GSM BTS (Base Transceiver Station) - however, using an
|
||||
Abis/IP interface, rather than the old-fashioned E1/T1.
|
||||
|
||||
Specificallt, this includes
|
||||
* BTS-Side implementation of TS 08.58 (RSL) and TS 12.21 (OML)
|
||||
* BTS-Side implementation of LAPDm (using libosmocore/libosmogsm)
|
||||
* A somewhat separated interface between those higher layer parts
|
||||
and the Layer1 interface.
|
||||
|
||||
Right now, only one hardware and Layer1 are supported: The sysmocom
|
||||
sysmoBTS.
|
||||
|
||||
There is some experimental and way incomplete code to use a couple of
|
||||
OsmocomBB phones and run them in the BTS. However, the required code
|
||||
for the Calypso DSP code have not been written yet. This would still
|
||||
require a lot of work.
|
||||
|
||||
Some additional work is being done in using some parts of the OpenBTS
|
||||
L1FEC and glue it against omso-bts. However, this is also still in an
|
||||
early, experimental stage.
|
||||
|
||||
== Known Limitations ==
|
||||
|
||||
As of June 3, 2012, the following known limitations exist in this
|
||||
implementation:
|
||||
|
||||
=== Common Core ===
|
||||
* No Extended BCCH support
|
||||
* System Information limited to 1,2,2bis,2ter,2quater,3,4,5,6,9,13
|
||||
* No RATSCCH in AMR
|
||||
* No OML (TS 12.21) alarms yet (temperature, ...)
|
||||
* Only single-TRX BTS at this point
|
||||
* Will reject TS 12.21 STARTING TIME in SET BTS ATTR / SET CHAN ATTR
|
||||
* No support for frequency hopping
|
||||
* No reporting of interference levels as part of TS 08.58 RF RES IND
|
||||
* No error reporting in case PAGING COMMAND fails due to queue overflow
|
||||
* No hand-over support (planned)
|
||||
* No use of TS 08.58 BS Power and MS Power parameters
|
||||
* No support of TS 08.58 MultiRate Control
|
||||
* No support of TS 08.58 Supported Codec Types
|
||||
* No support of Bter frame / ENHANCED MEASUREMENT REPORT
|
||||
|
||||
=== osmo-bts-sysmo ===
|
||||
* No CSD / ECSD support (not planned)
|
||||
* No GPRS/EDGE support (planned)
|
||||
* GSM-R frequency band supported, but no NCH/ASCI/SoLSA
|
||||
* All timeslots on one TRX have to use same training sequence (TSC)
|
||||
* No multi-TRX support yet, though hardware+L1 support stacking
|
||||
* Makes no use of 12.21 Intave Parameters and Interference
|
||||
Level Boundaries
|
||||
* Makes no use of TS 12.21 T3105
|
||||
* Doesn't yet include MAC address in Abis/IP Identity message
|
||||
* MphConfig.CNF can be returned to the wrong callback. E.g. with Tx Power
|
||||
and ciphering. The dispatch should take a look at the hLayer3.
|
||||
|
||||
|
||||
127
README.md
Normal file
127
README.md
Normal file
@@ -0,0 +1,127 @@
|
||||
osmo-bts - Osmocom BTS Implementation
|
||||
====================================
|
||||
|
||||
This repository contains a C-language implementation of a GSM Base
|
||||
Transceiver Station (BTS). It is part of the
|
||||
[Osmocom](https://osmocom.org/) Open Source Mobile Communications
|
||||
project.
|
||||
|
||||
This code implements Layer 2 and higher of a more or less conventional GSM BTS
|
||||
(Base Transceiver Station) - however, using an Abis/IP interface, rather than
|
||||
the old-fashioned E1/T1.
|
||||
|
||||
Specifically, this includes
|
||||
* BTS-side implementation of TS 08.58 (RSL) and TS 12.21 (OML)
|
||||
* BTS-side implementation of LAPDm (using libosmocore/libosmogsm)
|
||||
* A somewhat separated interface between those higher layer parts and the
|
||||
Layer1 interface.
|
||||
|
||||
Several kinds of BTS hardware are supported:
|
||||
* sysmocom sysmoBTS
|
||||
* Octasic octphy
|
||||
* Nutaq litecell 1.5
|
||||
* software-defined radio based osmo-bts-trx (e.g. USRP B210, UmTRX)
|
||||
|
||||
Homepage
|
||||
--------
|
||||
|
||||
The official homepage of the project is
|
||||
https://osmocom.org/projects/osmobts/wiki
|
||||
|
||||
GIT Repository
|
||||
--------------
|
||||
|
||||
You can clone from the official osmo-bts.git repository using
|
||||
|
||||
git clone git://git.osmocom.org/osmo-bts.git
|
||||
|
||||
There is a cgit interface at http://git.osmocom.org/osmo-bts/
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
We provide a
|
||||
[User Manual](http://ftp.osmocom.org/docs/latest/osmobts-usermanual.pdf)
|
||||
as well as a
|
||||
[VTY Reference Manual](http://ftp.osmocom.org/docs/latest/osmobsc-vty-reference.pdf)
|
||||
and a
|
||||
[Abis refrence MAnual](http://ftp.osmocom.org/docs/latest/osmobts-abis.pdf)
|
||||
describing the OsmoBTS specific A-bis dialect.
|
||||
|
||||
Mailing List
|
||||
------------
|
||||
|
||||
Discussions related to osmo-bts are happening on the
|
||||
openbsc@lists.osmocom.org mailing list, please see
|
||||
https://lists.osmocom.org/mailman/listinfo/openbsc for subscription
|
||||
options and the list archive.
|
||||
|
||||
Please observe the [Osmocom Mailing List
|
||||
Rules](https://osmocom.org/projects/cellular-infrastructure/wiki/Mailing_List_Rules)
|
||||
when posting.
|
||||
|
||||
Contributing
|
||||
------------
|
||||
|
||||
Our coding standards are described at
|
||||
https://osmocom.org/projects/cellular-infrastructure/wiki/Coding_standards
|
||||
|
||||
We us a gerrit based patch submission/review process for managing
|
||||
contributions. Please see
|
||||
https://osmocom.org/projects/cellular-infrastructure/wiki/Gerrit for
|
||||
more details
|
||||
|
||||
The current patch queue for osmo-bts can be seen at
|
||||
https://gerrit.osmocom.org/#/q/project:osmo-bts+status:open
|
||||
|
||||
Known Limitations
|
||||
=================
|
||||
|
||||
As of March 17, 2017, the following known limitations exist in this
|
||||
implementation:
|
||||
|
||||
Common Core
|
||||
-----------
|
||||
|
||||
* No Extended BCCH support
|
||||
* System Information limited to 1,2,2bis,2ter,2quater,3,4,5,6,9,13
|
||||
* No RATSCCH in AMR
|
||||
* Will reject TS 12.21 STARTING TIME in SET BTS ATTR / SET CHAN ATTR
|
||||
* No support for frequency hopping
|
||||
* No reporting of interference levels as part of TS 08.58 RF RES IND
|
||||
* No error reporting in case PAGING COMMAND fails due to queue overflow
|
||||
* No use of TS 08.58 BS Power and MS Power parameters
|
||||
* No support of TS 08.58 MultiRate Control
|
||||
* No support of TS 08.58 Supported Codec Types
|
||||
* No support of Bter frame / ENHANCED MEASUREMENT REPORT
|
||||
|
||||
osmo-bts-sysmo
|
||||
--------------
|
||||
|
||||
* No CSD / ECSD support (not planned)
|
||||
* GSM-R frequency band supported, but no NCH/ASCI/SoLSA
|
||||
* All timeslots on one TRX have to use same training sequence (TSC)
|
||||
* No multi-TRX support yet, though hardware+L1 support stacking
|
||||
* Makes no use of 12.21 Intave Parameters and Interference
|
||||
Level Boundaries
|
||||
* MphConfig.CNF can be returned to the wrong callback. E.g. with Tx Power
|
||||
and ciphering. The dispatch should take a look at the hLayer3.
|
||||
|
||||
osmo-bts-octphy
|
||||
---------------
|
||||
|
||||
* No support of EFR, HR voice codec (lack of PHY support?)
|
||||
* No re-transmission of PHY primitives in case of time-out
|
||||
* Link Quality / Measurement processing incomplete
|
||||
* impossible to modify encryption parameters using RSL MODE MODIFY
|
||||
* no clear indication of nominal transmit power, various power related
|
||||
computations are likely off
|
||||
* no OML attribute validation during bts_model_check_oml()
|
||||
|
||||
osmo-bts-trx
|
||||
------------
|
||||
|
||||
* TCH/F_PDCH cannel not working as voice (https://osmocom.org/issues/1865)
|
||||
* No BER value delivered to OsmoPCU (https://osmocom.org/issues/1855)
|
||||
* No 11bit RACH support (https://osmocom.org/issues/1854)
|
||||
* No CBCH support (https://osmocom.org/issues/1617)
|
||||
147
configure.ac
147
configure.ac
@@ -1,7 +1,10 @@
|
||||
dnl Process this file with autoconf to produce a configure script
|
||||
AC_INIT([osmo-bts],
|
||||
m4_esyscmd([./git-version-gen .tarball-version]),
|
||||
[openbsc-devel@lists.openbsc.org])
|
||||
[openbsc@lists.osmocom.org])
|
||||
|
||||
dnl *This* is the root dir, even if an install-sh exists in ../ or ../../
|
||||
AC_CONFIG_AUX_DIR([.])
|
||||
|
||||
AM_INIT_AUTOMAKE([dist-bzip2])
|
||||
AC_CONFIG_TESTDIR(tests)
|
||||
@@ -9,52 +12,144 @@ AC_CONFIG_TESTDIR(tests)
|
||||
dnl kernel style compile messages
|
||||
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
|
||||
|
||||
dnl include release helper
|
||||
RELMAKE='-include osmo-release.mk'
|
||||
AC_SUBST([RELMAKE])
|
||||
|
||||
dnl checks for programs
|
||||
AC_PROG_MAKE_SET
|
||||
AC_PROG_CC
|
||||
AC_PROG_INSTALL
|
||||
AC_PROG_RANLIB
|
||||
|
||||
dnl check for pkg-config (explained in detail in libosmocore/configure.ac)
|
||||
AC_PATH_PROG(PKG_CONFIG_INSTALLED, pkg-config, no)
|
||||
if test "x$PKG_CONFIG_INSTALLED" = "xno"; then
|
||||
AC_MSG_WARN([You need to install pkg-config])
|
||||
fi
|
||||
PKG_PROG_PKG_CONFIG([0.20])
|
||||
|
||||
dnl checks for header files
|
||||
AC_HEADER_STDC
|
||||
|
||||
dnl Checks for typedefs, structures and compiler characteristics
|
||||
|
||||
dnl checks for libraries
|
||||
PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 0.3.9)
|
||||
PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty)
|
||||
PKG_CHECK_MODULES(LIBOSMOTRAU, libosmotrau >= 0.0.7)
|
||||
PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 0.3.3)
|
||||
PKG_CHECK_MODULES(LIBOSMOCTRL, libosmoctrl)
|
||||
PKG_CHECK_MODULES(LIBOSMOABIS, libosmoabis)
|
||||
PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 0.10.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 0.10.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOTRAU, libosmotrau >= 0.3.2)
|
||||
PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 0.10.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOCTRL, libosmoctrl >= 0.10.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOABIS, libosmoabis >= 0.3.2)
|
||||
PKG_CHECK_MODULES(LIBOSMOCODEC, libosmocodec >= 0.10.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOCODING, libosmocoding >= 0.10.0)
|
||||
PKG_CHECK_MODULES(ORTP, ortp)
|
||||
|
||||
AC_MSG_CHECKING([whether to enable sysmocom-bts hardware support])
|
||||
AC_MSG_CHECKING([whether to enable support for sysmoBTS L1/PHY support])
|
||||
AC_ARG_ENABLE(sysmocom-bts,
|
||||
AC_HELP_STRING([--enable-sysmocom-bts],
|
||||
[enable code for sysmocom femto-bts [default=no]]),
|
||||
[enable code for sysmoBTS L1/PHY [default=no]]),
|
||||
[enable_sysmocom_bts="yes"],[enable_sysmocom_bts="no"])
|
||||
AC_MSG_RESULT([$enable_sysmocom_bts])
|
||||
AM_CONDITIONAL(ENABLE_SYSMOBTS, test "x$enable_sysmocom_bts" = "xyes")
|
||||
if test "$enable_sysmocom_bts" = "yes"; then
|
||||
PKG_CHECK_MODULES(LIBGPS, libgps)
|
||||
fi
|
||||
|
||||
# We share gsm_data.h with OpenBSC and need to be pointed to the source
|
||||
# directory of OpenBSC for now.
|
||||
AC_ARG_WITH([openbsc],
|
||||
[AS_HELP_STRING([--with-openbsc=INCLUDE_DIR],
|
||||
[OpenBSC include directory for openbsc/gsm_data_shared.h])],
|
||||
[openbsc_incdir="$withval"],
|
||||
[openbsc_incdir="`cd $srcdir; pwd`/../openbsc/openbsc/include"])
|
||||
AC_SUBST([OPENBSC_INCDIR], $openbsc_incdir)
|
||||
AC_MSG_CHECKING([whether to enable support for osmo-trx based L1/PHY support])
|
||||
AC_ARG_ENABLE(trx,
|
||||
AC_HELP_STRING([--enable-trx],
|
||||
[enable code for osmo-trx L1/PHY [default=no]]),
|
||||
[enable_trx="yes"],[enable_trx="no"])
|
||||
AC_MSG_RESULT([$enable_trx])
|
||||
AM_CONDITIONAL(ENABLE_TRX, test "x$enable_trx" = "xyes")
|
||||
|
||||
AC_MSG_CHECKING([whether to enable support for Octasic OCTPHY-2G])
|
||||
AC_ARG_ENABLE(octphy,
|
||||
AC_HELP_STRING([--enable-octphy],
|
||||
[enable code for Octasic OCTPHY-2G [default=no]]),
|
||||
[enable_octphy="yes"],[enable_octphy="no"])
|
||||
AC_ARG_WITH([octsdr-2g], [AS_HELP_STRING([--with-octsdr-2g], [Location of the OCTSDR-2G API header files])],
|
||||
[octsdr2g_incdir="$withval"],[octsdr2g_incdir="`cd $srcdir; pwd`/src/osmo-bts-octphy/"])
|
||||
AC_SUBST([OCTSDR2G_INCDIR], $octsdr2g_incdir)
|
||||
AC_MSG_RESULT([$enable_octphy])
|
||||
AM_CONDITIONAL(ENABLE_OCTPHY, test "x$enable_octphy" = "xyes")
|
||||
if test "$enable_octphy" = "yes" ; then
|
||||
oldCPPFLAGS=$CPPFLAGS
|
||||
CPPFLAGS="$CPPFLAGS -I$OPENBSC_INCDIR -I$srcdir/include $LIBOSMOCORE_CFLAGS"
|
||||
AC_CHECK_HEADER([openbsc/gsm_data_shared.h],[],
|
||||
[AC_MSG_ERROR([openbsc/gsm_data_shared.h can not be found in $openbsc_incdir])],
|
||||
[#include <osmo-bts/tx_power.h>])
|
||||
CPPFLAGS="$CPPFLAGS -I$OCTSDR2G_INCDIR -I$srcdir/include $LIBOSMOCORE_CFLAGS"
|
||||
|
||||
AC_CHECK_HEADER([octphy/octvc1/gsm/octvc1_gsm_default.h],[],
|
||||
[AC_MSG_ERROR([octphy/octvc1/gsm/octvc1_gsm_default.h can not be found in $octsdr2g_incdir])],
|
||||
[#include <octphy/octvc1/gsm/octvc1_gsm_default.h>])
|
||||
|
||||
AC_CHECK_MEMBER([tOCTVC1_GSM_TRX_CONFIG.usCentreArfcn],
|
||||
AC_DEFINE([OCTPHY_MULTI_TRX],
|
||||
[1],
|
||||
[Define to 1 if your octphy header files support multi-trx]),
|
||||
[],
|
||||
[#include <octphy/octvc1/gsm/octvc1_gsm_api.h>])
|
||||
|
||||
AC_CHECK_MEMBER([tOCTVC1_HW_RF_PORT_RX_STATS.Frequency],
|
||||
AC_DEFINE([OCTPHY_USE_FREQUENCY],
|
||||
[1],
|
||||
[Define to 1 if your octphy header files support tOCTVC1_RADIO_FREQUENCY_VALUE type]),
|
||||
[],
|
||||
[#include <octphy/octvc1/hw/octvc1_hw_api.h>])
|
||||
|
||||
AC_CHECK_MEMBER([tOCTVC1_HW_MSG_CLOCK_SYNC_MGR_STATS_RSP.ulSyncLossCnt],
|
||||
AC_DEFINE([OCTPHY_USE_SYNC_LOSS_CNT],
|
||||
[1],
|
||||
[Define to 1 if your octphy header files renamed ulSyncLosseCnt to ulSyncLossCnt]),
|
||||
[],
|
||||
[#include <octphy/octvc1/hw/octvc1_hw_api.h>])
|
||||
|
||||
AC_CHECK_MEMBER([tOCTVC1_HW_MSG_RF_PORT_INFO_ANTENNA_TX_CONFIG_RSP.TxConfig],
|
||||
AC_DEFINE([OCTPHY_USE_TX_CONFIG],
|
||||
[1],
|
||||
[Define to 1 if your octphy header files support tOCTVC1_HW_RF_PORT_ANTENNA_TX_CONFIG type]),
|
||||
[],
|
||||
[#include <octphy/octvc1/hw/octvc1_hw_api.h>])
|
||||
|
||||
AC_CHECK_MEMBER([tOCTVC1_HW_MSG_RF_PORT_INFO_ANTENNA_RX_CONFIG_RSP.RxConfig],
|
||||
AC_DEFINE([OCTPHY_USE_RX_CONFIG],
|
||||
[1],
|
||||
[Define to 1 if your octphy header files support tOCTVC1_HW_RF_PORT_ANTENNA_RX_CONFIG type]),
|
||||
[],
|
||||
[#include <octphy/octvc1/hw/octvc1_hw_api.h>])
|
||||
|
||||
AC_CHECK_MEMBER([tOCTVC1_GSM_RF_CONFIG.ulTxAntennaId],
|
||||
AC_DEFINE([OCTPHY_USE_ANTENNA_ID],
|
||||
[1],
|
||||
[Define to 1 if your octphy header files support antenna ids in tOCTVC1_GSM_RF_CONFIG]),
|
||||
[],
|
||||
[#include <octphy/octvc1/gsm/octvc1_gsm_api.h>])
|
||||
|
||||
CPPFLAGS=$oldCPPFLAGS
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([whether to enable NuRAN Wireless Litecell 1.5 hardware support])
|
||||
AC_ARG_ENABLE(litecell15,
|
||||
AC_HELP_STRING([--enable-litecell15],
|
||||
[enable code for NuRAN Wireless Litecell15 bts [default=no]]),
|
||||
[enable_litecell15="yes"],[enable_litecell15="no"])
|
||||
AC_ARG_WITH([litecell15], [AS_HELP_STRING([--with-litecell15=INCLUDE_DIR], [Location of the litecell 1.5 API header files])],
|
||||
[litecell15_incdir="$withval"],[litecell15_incdir="$incdir"])
|
||||
AC_SUBST([LITECELL15_INCDIR], $litecell15_incdir)
|
||||
AC_MSG_RESULT([$enable_litecell15])
|
||||
AM_CONDITIONAL(ENABLE_LC15BTS, test "x$enable_litecell15" = "xyes")
|
||||
if test "$enable_litecell15" = "yes"; then
|
||||
oldCPPFLAGS=$CPPFLAGS
|
||||
CPPFLAGS="$CPPFLAGS -I$LITECELL15_INCDIR -I$srcdir/include $LIBOSMOCORE_CFLAGS"
|
||||
AC_CHECK_HEADER([nrw/litecell15/litecell15.h],[],
|
||||
[AC_MSG_ERROR([nrw/litecell15/litecell15.h can not be found in $litecell15_incdir])],
|
||||
[#include <nrw/litecell15/litecell15.h>])
|
||||
PKG_CHECK_MODULES(LIBSYSTEMD, libsystemd)
|
||||
CPPFLAGS=$oldCPPFLAGS
|
||||
fi
|
||||
|
||||
# Check for the sbts2050_header.h that was added after the 3.6 release
|
||||
oldCPPFLAGS=$CPPFLAGS
|
||||
CPPFLAGS="$CPPFLAGS -I$OPENBSC_INCDIR $LIBOSMOCORE_CFLAGS"
|
||||
CPPFLAGS="$CPPFLAGS $LIBOSMOCORE_CFLAGS"
|
||||
AC_CHECK_HEADER([sysmocom/femtobts/sbts2050_header.h],
|
||||
[sysmo_uc_header="yes"],[])
|
||||
CPPFLAGS=$oldCPPFLAGS
|
||||
@@ -68,7 +163,11 @@ AM_CONFIG_HEADER(btsconfig.h)
|
||||
AC_OUTPUT(
|
||||
src/Makefile
|
||||
src/common/Makefile
|
||||
src/osmo-bts-virtual/Makefile
|
||||
src/osmo-bts-sysmo/Makefile
|
||||
src/osmo-bts-litecell15/Makefile
|
||||
src/osmo-bts-trx/Makefile
|
||||
src/osmo-bts-octphy/Makefile
|
||||
include/Makefile
|
||||
include/osmo-bts/Makefile
|
||||
tests/Makefile
|
||||
@@ -77,4 +176,8 @@ AC_OUTPUT(
|
||||
tests/cipher/Makefile
|
||||
tests/sysmobts/Makefile
|
||||
tests/misc/Makefile
|
||||
tests/handover/Makefile
|
||||
tests/tx_power/Makefile
|
||||
tests/power/Makefile
|
||||
tests/meas/Makefile
|
||||
Makefile)
|
||||
|
||||
89
contrib/dtx_check.gawk
Executable file
89
contrib/dtx_check.gawk
Executable file
@@ -0,0 +1,89 @@
|
||||
#!/usr/bin/gawk -f
|
||||
|
||||
# Expected input format: FN TYPE
|
||||
|
||||
BEGIN {
|
||||
DELTA = 0
|
||||
ERR = 0
|
||||
FORCE = 0
|
||||
FN = 0
|
||||
SILENCE = 0
|
||||
TYPE = ""
|
||||
CHK = ""
|
||||
U_MAX = 8 * 20 + 120 / 26
|
||||
U_MIN = 8 * 20 - 120 / 26
|
||||
F_MAX = 3 * 20 + 120 / 26
|
||||
F_MIN = 3 * 20 - 120 / 26
|
||||
}
|
||||
|
||||
{
|
||||
if (NR > 2) { # we have data from previous record to compare to
|
||||
DELTA = ($1 - FN) * 120 / 26
|
||||
CHK = "OK"
|
||||
if ("FACCH" == $2 && "ONSET" == TYPE) { # ONSET due to FACCH is NOT a talkspurt
|
||||
SILENCE = 1
|
||||
}
|
||||
if (("UPDATE" == TYPE || "FIRST" == TYPE) && ("FACCH" == $2 || "SPEECH" == $2)) { # check for missing ONSET:
|
||||
CHK = "FAIL: missing ONSET (" $2 ") after " TYPE "."
|
||||
ERR++
|
||||
}
|
||||
if ("SID_P1" == $2) {
|
||||
CHK = "FAIL: regular AMR payload with FT SID and STI=0 (should be either pyaload Update or STI=1)."
|
||||
ERR++
|
||||
}
|
||||
if ("FORCED_FIRST" == $2 || "FORCED_NODATA" == $2 || "FORCED_F_P2" == $2 || "FORCED_F_INH" == $2 || "FORCED_U_INH" == $2) {
|
||||
CHK = "FAIL: event " $2 " inserted by DSP."
|
||||
FORCE++
|
||||
ERR++
|
||||
}
|
||||
if ("FIRST_P2" != $2 && "FIRST_P1" == TYPE) {
|
||||
CHK = "FAIL: " TYPE " followed by " $2 " instead of P2."
|
||||
ERR++
|
||||
}
|
||||
if ("FIRST" == $2 && "FIRST" == TYPE) {
|
||||
CHK = "FAIL: multiple SID FIRST in a row."
|
||||
ERR++
|
||||
}
|
||||
if ("OK" == CHK && "ONSET" != $2) { # check inter-SID distances:
|
||||
if ("UPDATE" == TYPE) {
|
||||
if (DELTA > U_MAX) {
|
||||
CHK = "FAIL: delta (" $1 - FN "fn) from previous SID UPDATE (@" FN ") too big " DELTA "ms > " U_MAX "ms."
|
||||
ERR++
|
||||
}
|
||||
if ("UPDATE" == $2 && DELTA < U_MIN) {
|
||||
CHK = "FAIL: delta (" $1 - FN "fn) from previous SID UPDATE (@" FN ") too small " DELTA "ms < " U_MIN "ms."
|
||||
ERR++
|
||||
}
|
||||
}
|
||||
if ("FIRST" == TYPE) {
|
||||
if (DELTA > F_MAX) {
|
||||
CHK = "FAIL: delta (" $1 - FN "fn) from previous SID FIRST (@" FN ") too big " DELTA "ms > " F_MAX "ms."
|
||||
ERR++
|
||||
}
|
||||
if ("UPDATE" == $2 && DELTA < F_MIN) {
|
||||
CHK = "FAIL: delta (" $1 - FN "fn) from previous SID UPDATE (@" FN ") too small " DELTA "ms < " F_MIN "ms."
|
||||
ERR++
|
||||
}
|
||||
}
|
||||
}
|
||||
if ("FACCH" == TYPE && "FIRST" != $2 && "FACCH" != $2 && 1 == SILENCE) { # check FACCH handling
|
||||
CHK = "FAIL: incorrect silence resume with " $2 " after FACCH."
|
||||
ERR++
|
||||
}
|
||||
}
|
||||
if ("SPEECH" == $2 || "ONSET" == $2) { # talkspurt
|
||||
SILENCE = 0
|
||||
}
|
||||
if ("UPDATE" == $2 || "FIRST" == $2) { # silence
|
||||
SILENCE = 1
|
||||
}
|
||||
print $1, $2, CHK
|
||||
if ($2 != "EMPTY") { # skip over EMPTY records
|
||||
TYPE = $2
|
||||
FN = $1
|
||||
}
|
||||
}
|
||||
|
||||
END {
|
||||
print "Check completed: found " ERR " errors (" FORCE " events inserted by DSP) in " NR " records."
|
||||
}
|
||||
@@ -10,7 +10,7 @@ env = os.environ
|
||||
env['L1FWD_BTS_HOST'] = '127.0.0.1'
|
||||
|
||||
bts_proc = subprocess.Popen(["./src/osmo-bts-sysmo/sysmobts-remote",
|
||||
"-c", "./doc/examples/osmo-bts.cfg"], env = env,
|
||||
"-c", "./doc/examples/sysmo/osmo-bts.cfg"], env = env,
|
||||
stdin=None, stdout=None)
|
||||
time.sleep(1)
|
||||
|
||||
|
||||
91
contrib/eeprom_reader.c
Normal file
91
contrib/eeprom_reader.c
Normal file
@@ -0,0 +1,91 @@
|
||||
/* GPLv3+ to read sysmobts-v2 revD or later EEPROM from userspace */
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-dev.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
/* Can read a 16bit at24 eeprom with 8192 byte in storage (24c64) */
|
||||
static int dump_eeprom(int fd, int out)
|
||||
{
|
||||
#define STEP 8192
|
||||
#define SIZE 8192
|
||||
uint8_t buf[STEP + 2];
|
||||
int rc = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < SIZE; i += STEP) {
|
||||
/* write the address */
|
||||
buf[0] = i >> 8;
|
||||
buf[1] = i;
|
||||
rc = write(fd, buf, 2);
|
||||
if (rc != 2) {
|
||||
fprintf(stderr, "writing address failed: %d/%d/%s\n", rc, errno, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* execute step amount of reads */
|
||||
rc = read(fd, buf, STEP);
|
||||
if (rc != STEP) {
|
||||
fprintf(stderr, "Failed to read: %d/%d/%s\n", rc, errno, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
write(out, buf, STEP);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int i2c_fd, out_fd;
|
||||
char *filename = "/dev/i2c-1";
|
||||
char *out_file = "eeprom.out";
|
||||
int addr = 0x50;
|
||||
int rc;
|
||||
|
||||
i2c_fd = open(filename, O_RDWR);
|
||||
if (i2c_fd < 0) {
|
||||
fprintf(stderr, "Failed to open i2c device %d/%d/%s\n",
|
||||
i2c_fd, errno, strerror(errno));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* force using that address it is already bound with a driver */
|
||||
rc = ioctl(i2c_fd, I2C_SLAVE_FORCE, addr);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "Failed to claim i2c device %d/%d/%s\n",
|
||||
rc, errno, strerror(errno));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (argc >= 2)
|
||||
out_file = argv[1];
|
||||
out_fd = open(out_file, O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
||||
if (out_fd < 0) {
|
||||
fprintf(stderr, "Failed to open out device %s %d/%d/%s\n",
|
||||
out_file, rc, errno, strerror(errno));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (dump_eeprom(i2c_fd, out_fd) != 0) {
|
||||
unlink(out_file);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
45
contrib/jenkins_bts_model.sh
Executable file
45
contrib/jenkins_bts_model.sh
Executable file
@@ -0,0 +1,45 @@
|
||||
#!/bin/sh
|
||||
# this is a dispatcher script which will call the bts-model-specific
|
||||
# script based on the bts model specified as command line argument
|
||||
|
||||
bts_model="$1"
|
||||
|
||||
if [ "x$bts_model" == "x" ]; then
|
||||
echo "Error: You have to specify the BTS model as first argument, e.g. $0 sysmo"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
if [ ! -d "./contrib" ]; then
|
||||
echo "Run ./contrib/jenkins_bts_model.sh from the root of the osmo-bts tree"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
set -x -e
|
||||
|
||||
case "$bts_model" in
|
||||
|
||||
sysmo)
|
||||
./contrib/jenkins_sysmobts.sh
|
||||
;;
|
||||
|
||||
oct)
|
||||
./contrib/jenkins_oct.sh
|
||||
;;
|
||||
|
||||
lc15)
|
||||
./contrib/jenkins_lc15.sh
|
||||
;;
|
||||
|
||||
trx)
|
||||
./contrib/jenkins_bts_trx.sh
|
||||
;;
|
||||
|
||||
oct+trx)
|
||||
./contrib/jenkins_oct_and_bts_trx.sh
|
||||
;;
|
||||
|
||||
*)
|
||||
set +x
|
||||
echo "Unknown BTS model '$bts_model'"
|
||||
;;
|
||||
esac
|
||||
26
contrib/jenkins_bts_trx.sh
Executable file
26
contrib/jenkins_bts_trx.sh
Executable file
@@ -0,0 +1,26 @@
|
||||
#!/bin/sh
|
||||
# jenkins build helper script for osmo-bts-trx
|
||||
|
||||
# shellcheck source=contrib/jenkins_common.sh
|
||||
. $(dirname "$0")/jenkins_common.sh
|
||||
|
||||
export PKG_CONFIG_PATH="$inst/lib/pkgconfig:$PKG_CONFIG_PATH"
|
||||
export LD_LIBRARY_PATH="$inst/lib"
|
||||
|
||||
osmo-build-dep.sh libosmocore
|
||||
|
||||
osmo-build-dep.sh libosmo-abis
|
||||
|
||||
cd "$deps"
|
||||
|
||||
# Get osmo-pcu for pcuif_proto.h
|
||||
osmo-deps.sh osmo-pcu
|
||||
|
||||
configure_flags="\
|
||||
--with-osmo-pcu=$deps/osmo-pcu/include \
|
||||
--enable-trx \
|
||||
"
|
||||
|
||||
build_bts "osmo-bts-trx" "$configure_flags"
|
||||
|
||||
osmo-clean-workspace.sh
|
||||
47
contrib/jenkins_common.sh
Normal file
47
contrib/jenkins_common.sh
Normal file
@@ -0,0 +1,47 @@
|
||||
#!/bin/sh
|
||||
|
||||
# this is a common helper script that is shared among all BTS model
|
||||
# specific helper scripts like jenkins_sysmobts.sh. You shouldn't call
|
||||
# this directly, but rather indirectly via the bts-specific scripts
|
||||
|
||||
if ! [ -x "$(command -v osmo-deps.sh)" ]; then
|
||||
echo "Error: We need to have scripts/osmo-deps.sh from http://git.osmocom.org/osmo-ci/ in PATH !"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
set -ex
|
||||
|
||||
base="$PWD"
|
||||
deps="$base/deps"
|
||||
inst="$deps/install"
|
||||
|
||||
export deps inst
|
||||
|
||||
osmo-clean-workspace.sh
|
||||
|
||||
mkdir -p "$deps"
|
||||
|
||||
verify_value_string_arrays_are_terminated.py $(find . -name "*.[hc]")
|
||||
|
||||
# generic project build function, usage:
|
||||
# build "PROJECT-NAME" "CONFIGURE OPTIONS"
|
||||
build_bts() {
|
||||
set +x
|
||||
echo
|
||||
echo
|
||||
echo
|
||||
echo " =============================== $1 ==============================="
|
||||
echo
|
||||
set -x
|
||||
|
||||
cd $deps
|
||||
osmo-deps.sh libosmocore
|
||||
cd $base
|
||||
shift
|
||||
conf_flags="$*"
|
||||
autoreconf --install --force
|
||||
./configure $conf_flags
|
||||
$MAKE $PARALLEL_MAKE
|
||||
$MAKE check || cat-testlogs.sh
|
||||
DISTCHECK_CONFIGURE_FLAGS=$conf_flags $MAKE distcheck || cat-testlogs.sh
|
||||
}
|
||||
21
contrib/jenkins_lc15.sh
Executable file
21
contrib/jenkins_lc15.sh
Executable file
@@ -0,0 +1,21 @@
|
||||
#!/bin/sh
|
||||
# jenkins build helper script for osmo-bts-lc15
|
||||
|
||||
# shellcheck source=contrib/jenkins_common.sh
|
||||
. $(dirname "$0")/jenkins_common.sh
|
||||
|
||||
osmo-build-dep.sh libosmocore
|
||||
|
||||
export PKG_CONFIG_PATH="$inst/lib/pkgconfig:$PKG_CONFIG_PATH"
|
||||
export LD_LIBRARY_PATH="$inst/lib"
|
||||
|
||||
osmo-build-dep.sh libosmo-abis
|
||||
|
||||
cd "$deps"
|
||||
osmo-layer1-headers.sh lc15 "$FIRMWARE_VERSION"
|
||||
|
||||
configure_flags="--with-litecell15=$deps/layer1-headers/inc/ --enable-litecell15"
|
||||
|
||||
build_bts "osmo-bts-lc15" "$configure_flags"
|
||||
|
||||
osmo-clean-workspace.sh
|
||||
21
contrib/jenkins_oct.sh
Executable file
21
contrib/jenkins_oct.sh
Executable file
@@ -0,0 +1,21 @@
|
||||
#!/bin/sh
|
||||
# jenkins build helper script for osmo-bts-octphy
|
||||
|
||||
# shellcheck source=contrib/jenkins_common.sh
|
||||
. $(dirname "$0")/jenkins_common.sh
|
||||
|
||||
osmo-build-dep.sh libosmocore
|
||||
|
||||
export PKG_CONFIG_PATH="$inst/lib/pkgconfig:$PKG_CONFIG_PATH"
|
||||
export LD_LIBRARY_PATH="$inst/lib"
|
||||
|
||||
osmo-build-dep.sh libosmo-abis
|
||||
|
||||
cd "$deps"
|
||||
osmo-layer1-headers.sh oct "$FIRMWARE_VERSION"
|
||||
|
||||
configure_flags="--with-octsdr-2g=$deps/layer1-headers/ --enable-octphy"
|
||||
|
||||
build_bts "osmo-bts-octphy" "$configure_flags"
|
||||
|
||||
osmo-clean-workspace.sh
|
||||
30
contrib/jenkins_oct_and_bts_trx.sh
Executable file
30
contrib/jenkins_oct_and_bts_trx.sh
Executable file
@@ -0,0 +1,30 @@
|
||||
#!/bin/sh
|
||||
# jenkins build helper script for osmo-bts-octphy + osmo-bts-trx
|
||||
|
||||
# shellcheck source=contrib/jenkins_common.sh
|
||||
. $(dirname "$0")/jenkins_common.sh
|
||||
|
||||
export PKG_CONFIG_PATH="$inst/lib/pkgconfig:$PKG_CONFIG_PATH"
|
||||
export LD_LIBRARY_PATH="$inst/lib"
|
||||
|
||||
osmo-build-dep.sh libosmocore
|
||||
|
||||
osmo-build-dep.sh libosmo-abis
|
||||
|
||||
cd "$deps"
|
||||
|
||||
# Get osmo-pcu for pcuif_proto.h
|
||||
osmo-deps.sh osmo-pcu
|
||||
|
||||
osmo-layer1-headers.sh oct "$FIRMWARE_VERSION"
|
||||
|
||||
configure_flags="\
|
||||
--with-osmo-pcu=$deps/osmo-pcu/include \
|
||||
--with-octsdr-2g=$deps/layer1-headers/ \
|
||||
--enable-octphy \
|
||||
--enable-trx \
|
||||
"
|
||||
|
||||
build_bts "osmo-bts-octphy+trx" "$configure_flags"
|
||||
|
||||
osmo-clean-workspace.sh
|
||||
28
contrib/jenkins_sysmobts.sh
Executable file
28
contrib/jenkins_sysmobts.sh
Executable file
@@ -0,0 +1,28 @@
|
||||
#!/bin/sh
|
||||
# jenkins build helper script for osmo-bts-sysmo
|
||||
|
||||
# shellcheck source=contrib/jenkins_common.sh
|
||||
. $(dirname "$0")/jenkins_common.sh
|
||||
|
||||
osmo-build-dep.sh libosmocore
|
||||
|
||||
export PKG_CONFIG_PATH="$inst/lib/pkgconfig:$PKG_CONFIG_PATH"
|
||||
export LD_LIBRARY_PATH="$inst/lib"
|
||||
|
||||
osmo-build-dep.sh libosmo-abis
|
||||
|
||||
cd "$deps"
|
||||
osmo-layer1-headers.sh sysmo "$FIRMWARE_VERSION"
|
||||
mkdir -p "$inst/include/sysmocom/femtobts"
|
||||
ln -s $deps/layer1-headers/include/* "$inst/include/sysmocom/femtobts/"
|
||||
|
||||
configure_flags="--enable-sysmocom-bts"
|
||||
|
||||
build_bts "osmo-bts-sysmo" "$configure_flags"
|
||||
|
||||
# This will not work for the femtobts
|
||||
if [ $FIRMWARE_VERSION != "femtobts_v2.7" ]; then
|
||||
$MAKE -C contrib/sysmobts-calib
|
||||
fi
|
||||
|
||||
osmo-clean-workspace.sh
|
||||
29
contrib/lc15bts-mgr.service
Normal file
29
contrib/lc15bts-mgr.service
Normal file
@@ -0,0 +1,29 @@
|
||||
[Unit]
|
||||
Description=osmo-bts manager for LC15 / sysmoBTS 2100
|
||||
After=lc15-sysdev-remap.service
|
||||
Wants=lc15-sysdev-remap.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
NotifyAccess=all
|
||||
WatchdogSec=21780s
|
||||
Restart=always
|
||||
RestartSec=2
|
||||
|
||||
# Make sure directories and symbolic link exist
|
||||
ExecStartPre=/bin/sh -c 'test -d /mnt/storage/var/run/lc15bts-mgr || mkdir -p /mnt/storage/var/run/lc15bts-mgr ; test -d /var/run/lc15bts-mgr || ln -sf /mnt/storage/var/run/lc15bts-mgr/ /var/run'
|
||||
# Make sure BTS operation hour exist
|
||||
ExecStartPre=/bin/sh -c 'test -f /mnt/storage/var/run/lc15bts-mgr/hours-running || echo 0 > /mnt/storage/var/run/lc15bts-mgr/hours-running'
|
||||
# Shutdown all PA correctly
|
||||
ExecStartPre=/bin/sh -c 'echo disabled > /var/lc15/pa-state/pa0/state; echo disabled > /var/lc15/pa-state/pa1/state'
|
||||
ExecStartPre=/bin/sh -c 'echo 0 > /var/lc15/pa-supply/max_microvolts; echo 0 > /var/lc15/pa-supply/min_microvolts'
|
||||
|
||||
ExecStart=/usr/bin/lc15bts-mgr -s -c /etc/osmocom/lc15bts-mgr.cfg
|
||||
|
||||
# Shutdown all PA correctly
|
||||
ExecStopPost=/bin/sh -c 'echo disabled > /var/lc15/pa-state/pa0/state; echo disabled > /var/lc15/pa-state/pa1/state'
|
||||
ExecStopPost=/bin/sh -c 'echo 0 > /var/lc15/pa-supply/max_microvolts; echo 0 > /var/lc15/pa-supply/min_microvolts'
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
Alias=osmo-bts-mgr.service
|
||||
21
contrib/osmo-bts-lc15.service
Normal file
21
contrib/osmo-bts-lc15.service
Normal file
@@ -0,0 +1,21 @@
|
||||
[Unit]
|
||||
Description=osmo-bts for LC15 / sysmoBTS 2100
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStartPre=/bin/sh -c 'echo 1 > /sys/class/leds/usr0/brightness'
|
||||
ExecStartPre=/bin/sh -c 'echo 1 > /sys/class/leds/usr1/brightness'
|
||||
ExecStart=/usr/bin/osmo-bts-lc15 -t 2 -s -c /etc/osmocom/osmo-bts.cfg -M
|
||||
ExecStopPost=/bin/sh -c 'echo 1 > /sys/class/leds/usr0/brightness'
|
||||
ExecStopPost=/bin/sh -c 'echo 0 > /sys/class/leds/usr1/brightness'
|
||||
Restart=always
|
||||
RestartSec=2
|
||||
RestartPreventExitStatus=1
|
||||
|
||||
# The msg queues must be read fast enough
|
||||
CPUSchedulingPolicy=rr
|
||||
CPUSchedulingPriority=1
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
Alias=osmo-bts.service
|
||||
21
contrib/osmo-bts-sysmo.service
Normal file
21
contrib/osmo-bts-sysmo.service
Normal file
@@ -0,0 +1,21 @@
|
||||
[Unit]
|
||||
Description=osmo-bts for sysmocom sysmoBTS
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStartPre=/bin/sh -c 'echo 0 > /sys/class/leds/activity_led/brightness'
|
||||
ExecStart=/usr/bin/osmo-bts-sysmo -s -c /etc/osmocom/osmo-bts.cfg -M
|
||||
ExecStopPost=/bin/sh -c 'echo 0 > /sys/class/leds/activity_led/brightness'
|
||||
ExecStopPost=/bin/sh -c 'cat /lib/firmware/sysmobts-v?.bit > /dev/fpgadl_par0 ; sleep 3s; cat /lib/firmware/sysmobts-v?.out > /dev/dspdl_dm644x_0; sleep 1s'
|
||||
Restart=always
|
||||
RestartSec=2
|
||||
RestartPreventExitStatus=1
|
||||
|
||||
# The msg queues must be read fast enough
|
||||
CPUSchedulingPolicy=rr
|
||||
CPUSchedulingPriority=1
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
Alias=sysmobts.service
|
||||
Alias=osmo-bts.service
|
||||
@@ -1,5 +1,5 @@
|
||||
chdir /tmp
|
||||
screen -t BTS 0 /etc/osmocom/respawn.sh /usr/bin/sysmobts -c /etc/osmocom/osmo-bts.cfg -r 1 -M
|
||||
screen -t BTS 0 /etc/osmocom/respawn.sh /usr/bin/osmo-bts-sysmo -c /etc/osmocom/osmo-bts.cfg -r 1 -M
|
||||
screen -t PCU 1 /etc/osmocom/respawn-only.sh /usr/bin/osmo-pcu -c /etc/osmocom/osmo-pcu.cfg -e
|
||||
screen -t MGR 2 /etc/osmocom/respawn-only.sh /usr/bin/sysmobts-mgr -n -c /etc/osmocom/sysmobts-mgr.cfg
|
||||
detach
|
||||
|
||||
91
contrib/si_check.gawk
Executable file
91
contrib/si_check.gawk
Executable file
@@ -0,0 +1,91 @@
|
||||
#!/usr/bin/gawk -f
|
||||
|
||||
# Usage example:
|
||||
# tshark -2 -t r -E 'header=n' -E 'separator=,' -E 'quote=n' -T fields -e gsmtap.frame_nr -e gsmtap.ts -e gsmtap.arfcn -e _ws.col.Info -Y 'gsmtap' -r test.pcapng.gz | grep Information | env ARFCN=878 ./si_check.gawk
|
||||
# read summary on number of bis/ter messages and adjust BT_BOTH and BT_NONE environment variables accordingly
|
||||
|
||||
BEGIN {
|
||||
FS = ","
|
||||
FAILED = 0
|
||||
IGNORE = 0
|
||||
BIS = 0
|
||||
TER = 0
|
||||
QUA = 0
|
||||
BT_BOTH = ENVIRON["BOTH"]
|
||||
BT_NONE = ENVIRON["NONE"]
|
||||
TC_INDEX = 0
|
||||
TC4[4] = 0
|
||||
}
|
||||
|
||||
{ # expected .csv input as follows: gsmtap.frame_nr,gsmtap.ts,gsmtap.arfcn,_ws.col.Info
|
||||
if ("ARFCN" in ENVIRON) { # ARFCN filtering is enabled
|
||||
if (ENVIRON["ARFCN"] != $3) { # ignore other ARFCNs
|
||||
IGNORE++
|
||||
next
|
||||
}
|
||||
}
|
||||
type = get_si_type($4)
|
||||
tc = get_tc($1)
|
||||
result = "FAIL"
|
||||
|
||||
if (1 == check_si_tc(tc, type)) { result = "OK" }
|
||||
else { FAILED++ }
|
||||
|
||||
if (4 == tc) {
|
||||
TC4[TC_INDEX] = type
|
||||
TC_INDEX = int((TC_INDEX + 1) % 4)
|
||||
if (0 == check_tc4c(type) && "OK" == result) {
|
||||
result = "FAIL"
|
||||
FAILED++
|
||||
}
|
||||
}
|
||||
if (type == "2bis") { BIS++ }
|
||||
if (type == "2ter") { TER++ }
|
||||
if (type == "2quater") { QUA++ }
|
||||
# for (i in TC4) print TC4[i] # debugging
|
||||
printf "ARFCN=%d FN=%d TS=%d TC=%d TYPE=%s %s\n", $3, $1, $2, tc, type, result
|
||||
}
|
||||
|
||||
END {
|
||||
printf "check completed: total %d, failed %d, ignored %d, ok %d\nSI2bis = %d, SI2ter = %d, SI2quater = %d\n", NR, FAILED, IGNORE, NR - FAILED - IGNORE, BIS, TER, QUA
|
||||
if ((BIS > 0 || TER > 0) && BT_NONE) { printf "please re-run with correct environment: unset 'NONE' variable\n" }
|
||||
if ((BIS > 0 && TER > 0) && !BT_BOTH) { printf "please re-run with correct environment: set 'BOTH' variable\n" }
|
||||
}
|
||||
|
||||
func get_si_type(s, x) { # we rely on format of Info column in wireshark output - if it's changed we're screwed
|
||||
return x[split(s, x, " ")]
|
||||
}
|
||||
|
||||
func get_tc(f) { # N. B: all numbers in awk are float
|
||||
return int(int(f / 51) % 8)
|
||||
}
|
||||
|
||||
func check_tc4c(si, count) { # check for "once in 4 consecutive occurrences" rule
|
||||
count = 0
|
||||
if ("2quater" != si || "2ter" != si) { return 1 } # rules is not applicable to other types
|
||||
if (BT_NONE && "2quater" == si) { return 0 } # should be on TC=5 instead
|
||||
if (!BT_BOTH && "2ter" == si) { return 0 } # should be on TC=5 instead
|
||||
if (0 in TC4 && 1 in TC4 && 2 in TC4 && 3 in TC4) { # only check if we have 4 consecutive occurrences already
|
||||
if (si == TC4[0]) { count++ }
|
||||
if (si == TC4[1]) { count++ }
|
||||
if (si == TC4[2]) { count++ }
|
||||
if (si == TC4[3]) { count++ }
|
||||
if (0 == count) { return 0 }
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
||||
func check_si_tc(tc, si) { # check that SI scheduling on BCCH Norm is matching rules from 3GPP TS 05.02 § 6.3.1.3
|
||||
switch (si) {
|
||||
case "1": return (0 == tc) ? 1 : 0
|
||||
case "2": return (1 == tc) ? 1 : 0
|
||||
case "2bis": return (5 == tc) ? 1 : 0
|
||||
case "13": return (4 == tc) ? 1 : 0
|
||||
case "9": return (4 == tc) ? 1 : 0
|
||||
case "2ter": if (BT_BOTH) { return (4 == tc) ? 1 : 0 } else { return (5 == tc) ? 1 : 0 }
|
||||
case "2quater": if (BT_NONE) { return (5 == tc) ? 1 : 0 } else { return (4 == tc) ? 1 : 0 }
|
||||
case "3": return (2 == tc || 6 == tc) ? 1 : 0
|
||||
case "4": return (3 == tc || 7 == tc) ? 1 : 0
|
||||
}
|
||||
return 0
|
||||
}
|
||||
110
contrib/superfemto.sh
Executable file
110
contrib/superfemto.sh
Executable file
@@ -0,0 +1,110 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Split common DSP call log file (produced by superfemto-compatible firmware) into 4 separate call leg files (MO/MT & DL/UL) with events in format "FN EVENT_TYPE":
|
||||
# MO Mobile Originated
|
||||
# MT Mobile Terminated
|
||||
# DL DownLink (BTS -> L1)
|
||||
# UL UpLink (L1 -> BTS)
|
||||
|
||||
if [ -z $1 ]; then
|
||||
echo "expecting DSP log file name as parameter"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# MO handle appear 1st in the logs
|
||||
MO=$(grep 'h=' $1 | head -n 1 | cut -f2 -d',' | cut -f2 -d= | cut -f1 -d']')
|
||||
|
||||
# direction markers:
|
||||
DLST="_CodeBurst"
|
||||
ULST="_DecodeAndIdentify"
|
||||
|
||||
# DL sed filters:
|
||||
D_EMP='s/ Empty frame request!/EMPTY/i'
|
||||
D_FAC='s/ Coding a FACCH\/. frame !!/FACCH/i'
|
||||
D_FST='s/ Coding a RTP SID First frame !!/FIRST/i'
|
||||
D_FS1='s/ Coding a SID First P1 frame !!/FIRST_P1/i'
|
||||
D_FS2='s/ Coding a SID First P2 frame !!/FIRST_P2/i'
|
||||
D_RP1='s/ Coding a RTP SID P1 frame !!/SID_P1/i'
|
||||
D_UPD='s/ Coding a RTP SID Update frame !!/UPDATE/i'
|
||||
D_SPE='s/ Coding a RTP Speech frame !!/SPEECH/i'
|
||||
D_ONS='s/ Coding a Onset frame !!/ONSET/i'
|
||||
D_FO1='s/ A speech frame is following a NoData or SID First without an Onset./FORCED_FIRST/i'
|
||||
D_FO2='s/ A speech frame is following a NoData without an Onset./FORCED_NODATA/i'
|
||||
D_FP2='s/ A speech frame is following a NoData or SID_FIRST_P2 without an Onset./FORCED_F_P2/i'
|
||||
D_FIN='s/ A speech frame is following a SID_FIRST without inhibit. A SID_FIRST_INH will be inserted./FORCED_F_INH/i'
|
||||
D_UIN='s/ A speech frame is following a SID_UPDATE without inhibit. A SID_UPDATE_INH will be inserted./FORCED_U_INH/i'
|
||||
|
||||
# UL sed filters:
|
||||
U_NOD='s/ It is a No Data frame !!/NODATA/i'
|
||||
U_ONS='s/ It is an ONSET frame !!/ONSET/i'
|
||||
U_UPD='s/ It is a SID UPDATE frame !!/UPDATE/i'
|
||||
U_FST='s/ It is a SID FIRST frame !!/FIRST/i'
|
||||
U_FP1='s/ It is a SID-First P1 frame !!/FIRST_P1/i'
|
||||
U_FP2='s/ It is a SID-First P2 frame !!/FIRST_P2/i'
|
||||
U_SPE='s/ It is a SPEECH frame *!!/SPEECH/i'
|
||||
U_UIN='s/ It is a SID update InH frame !!/UPD_INH/i'
|
||||
U_FIN='s/ It is a SID-First InH frame !!/FST_INH/i'
|
||||
U_RAT='s/ It is a RATSCCH data frame !!/RATSCCH/i'
|
||||
|
||||
DL () { # filter downlink-related entries
|
||||
grep $DLST $1 > $1.DL.tmp
|
||||
}
|
||||
|
||||
UL () { # uplink does not require special fix
|
||||
grep $ULST $1 > $1.UL.tmp.fix
|
||||
}
|
||||
|
||||
DL $1
|
||||
UL $1
|
||||
|
||||
FIX() { # add MO/MT marker from preceding line to inserted ONSETs so filtering works as expected
|
||||
cat $1.DL.tmp | awk 'BEGIN{ FS=" h="; H="" } { if (NF > 1) { H = $2; print $1 "h=" $2 } else { print $1 ", h=" H } }' > $1.DL.tmp.fix
|
||||
}
|
||||
|
||||
FIX $1
|
||||
|
||||
MO() { # filter MO call DL or UL logs
|
||||
grep "h=$MO" $1.tmp.fix > $1.MO.raw
|
||||
}
|
||||
|
||||
MT() { # filter MT call DL or UL logs
|
||||
grep -v "h=$MO" $1.tmp.fix > $1.MT.raw
|
||||
}
|
||||
|
||||
MO $1.DL
|
||||
MT $1.DL
|
||||
MO $1.UL
|
||||
MT $1.UL
|
||||
|
||||
PREP() { # prepare logs for reformatting
|
||||
cat $1.raw | cut -f2 -d')' | cut -f1 -d',' | cut -f2 -d'>' | sed 's/\[u32Fn/fn/' | sed 's/\[ u32Fn/fn/' | sed 's/fn = /fn=/' | sed 's/fn=//' | sed 's/\[Fn=//' | sed 's/ An Onset will be inserted.//' > $1.tmp1
|
||||
}
|
||||
|
||||
PREP "$1.DL.MT"
|
||||
PREP "$1.DL.MO"
|
||||
PREP "$1.UL.MT"
|
||||
PREP "$1.UL.MO"
|
||||
|
||||
RD() { # reformat DL logs for consistency checks
|
||||
cat $1.tmp1 | sed "$D_FST" | sed "$D_SPE" | sed "$D_FS1" | sed "$D_FS2" | sed "$D_UIN" | sed "$D_FIN" | sed "$D_UPD" | sed "$D_INH" | sed "$D_RP1" | sed "$D_ONS" | sed "$D_EMP" | sed "$D_FAC" | sed "$D_FO1" | sed "$D_FO2" | sed "$D_FP2" > $1.tmp2
|
||||
}
|
||||
|
||||
RU() { # reformat UL logs for consistency checks
|
||||
cat $1.tmp1 | sed "$U_FST" | sed "$U_SPE" | sed "$U_FP1" | sed "$U_FP2" | sed "$U_UPD" | sed "$U_ONS" | sed "$U_NOD" | sed "$U_UIN" | sed "$U_FIN" | sed "$U_RAT" > $1.tmp2
|
||||
}
|
||||
|
||||
RD "$1.DL.MT"
|
||||
RD "$1.DL.MO"
|
||||
RU "$1.UL.MT"
|
||||
RU "$1.UL.MO"
|
||||
|
||||
SW() { # swap fields
|
||||
cat $1.tmp2 | awk '{ print $2, $1 }' > $1
|
||||
}
|
||||
|
||||
SW "$1.DL.MT"
|
||||
SW "$1.DL.MO"
|
||||
SW "$1.UL.MT"
|
||||
SW "$1.UL.MO"
|
||||
|
||||
rm $1.*.tmp*
|
||||
@@ -310,19 +310,36 @@ int print_system_info()
|
||||
#ifdef FEMTOBTS_NO_BOARD_VERSION
|
||||
#define BOARD_REV(x) -1
|
||||
#define BOARD_OPT(x) -1
|
||||
#define COMPILED_MAJOR (FEMTOBTS_API_VERSION >> 16)
|
||||
#define COMPILED_MINOR ((FEMTOBTS_API_VERSION >> 8) & 0xff)
|
||||
#define COMPILED_BUILD (FEMTOBTS_API_VERSION & 0xff)
|
||||
#else
|
||||
#define BOARD_REV(x) x.u.systemInfoCnf.boardVersion.rev
|
||||
#define BOARD_OPT(x) x.u.systemInfoCnf.boardVersion.option
|
||||
#define COMPILED_MAJOR (SUPERFEMTO_API_VERSION >> 16)
|
||||
#define COMPILED_MINOR ((SUPERFEMTO_API_VERSION >> 8) & 0xff)
|
||||
#define COMPILED_BUILD (SUPERFEMTO_API_VERSION & 0xff)
|
||||
#endif
|
||||
|
||||
printf("DSP v%d.%d.%d FPGA v%d.%d.%d Rev: %d Option: %d\n",
|
||||
printf("Compiled against: v%u.%u.%u\n",
|
||||
COMPILED_MAJOR, COMPILED_MINOR, COMPILED_BUILD);
|
||||
printf("Running DSP v%d.%d.%d FPGA v%d.%d.%d Rev: %d Option: %d\n",
|
||||
INFO_DSP(prim).major, INFO_DSP(prim).minor, INFO_DSP(prim).build,
|
||||
INFO_FPGA(prim).major, INFO_FPGA(prim).minor, INFO_FPGA(prim).build,
|
||||
BOARD_REV(prim), BOARD_OPT(prim));
|
||||
|
||||
if (COMPILED_MAJOR != INFO_DSP(prim).major || COMPILED_MINOR != INFO_DSP(prim).minor) {
|
||||
printf("WARNING! WARNING! WARNING! WARNING! WARNING\n");
|
||||
printf("You might run this against an incompatible firmware.\n");
|
||||
printf("Continuing anyway but the result might be broken\n");
|
||||
}
|
||||
#undef INFO_DSP
|
||||
#undef INFO_FPGA
|
||||
#undef BOARD_REV
|
||||
#undef BOARD_OPT
|
||||
#undef COMPILED_MAJOR
|
||||
#undef COMPILED_MINOR
|
||||
#undef COMPILED_BUILD
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[Unit]
|
||||
Description=sysmocom sysmoBTS manager
|
||||
Description=osmo-bts manager for sysmoBTS
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
@@ -9,4 +9,4 @@ RestartSec=2
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
Alias=osmo-bts-mgr.service
|
||||
|
||||
@@ -4,7 +4,7 @@ Description=sysmocom sysmoBTS
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStartPre=/bin/sh -c 'echo 0 > /sys/class/leds/activity_led/brightness'
|
||||
ExecStart=/usr/bin/sysmobts -s -c /etc/osmocom/osmo-bts.cfg -M
|
||||
ExecStart=/usr/bin/osmo-bts-sysmo -s -c /etc/osmocom/osmo-bts.cfg -M
|
||||
ExecStopPost=/bin/sh -c 'echo 0 > /sys/class/leds/activity_led/brightness'
|
||||
ExecStopPost=/bin/sh -c 'cat /lib/firmware/sysmobts-v?.bit > /dev/fpgadl_par0 ; sleep 3s; cat /lib/firmware/sysmobts-v?.out > /dev/dspdl_dm644x_0; sleep 1s'
|
||||
Restart=always
|
||||
@@ -17,3 +17,4 @@ CPUSchedulingPriority=1
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
Alias=osmo-bts-sysmo.service
|
||||
|
||||
522
debian/changelog
vendored
Normal file
522
debian/changelog
vendored
Normal file
@@ -0,0 +1,522 @@
|
||||
osmo-bts (0.7.0) unstable; urgency=medium
|
||||
|
||||
[ Max ]
|
||||
* Use value string check from osmo-ci
|
||||
* Support sending SI13 to PCU
|
||||
* Support removing SI13 from PCU
|
||||
* trx: avoid deactivating lchan on LCHAN_REL_ACT_REACT
|
||||
* Check readv() return value to prevent crash
|
||||
* OML: print actual type of report sent to BSC
|
||||
* Replace dead code
|
||||
* vty: print version and description for each phy
|
||||
* Remove build dependency on legacy OpenBSC
|
||||
* Fix multiple SI2q reception
|
||||
* jenkins: remove openbsc dependency
|
||||
* sysmo: use clock calibration source wrapper
|
||||
* sysmo: don't override clock source with defaults
|
||||
* Fix race condition in attribute reporting
|
||||
* Move power loop to generic tests
|
||||
* Make power test more verbose
|
||||
|
||||
[ Neels Hofmeyr ]
|
||||
* vty: mgr: sysmobts, lc15: install default commands for ACT_NORM_NODE
|
||||
* osmo-bts-trx: vty: various fixes of 'write file' and doc
|
||||
* jenkins: use osmo-clean-workspace.sh before and after build
|
||||
|
||||
[ Pau Espin Pedrol ]
|
||||
* l1sap: Improve log msg when frame diff >1
|
||||
* vty: Print string for Administrative state
|
||||
|
||||
[ Harald Welte ]
|
||||
* Fix Downlink AMR FSM name to avoid illegal space character
|
||||
* update dependencies to latest libosmo-*
|
||||
* configure.ac: Fix Mailing list address
|
||||
|
||||
-- Harald Welte <laforge@gnumonks.org> Sat, 28 Oct 2017 20:53:21 +0200
|
||||
|
||||
osmo-bts (0.6.0) unstable; urgency=medium
|
||||
|
||||
[ Holger Hans Peter Freyther ]
|
||||
* Initial release.
|
||||
* misc: Ignore files generated by a debian packaging build
|
||||
* jenkins: Add the build script from jenkins here
|
||||
* jenkins: Add the build script from jenkins here
|
||||
* sysmobts: Add the barebox boot state reservation
|
||||
* sysmobts: Fix eeprom padding before gpg key
|
||||
* ci/spatch: Remove the "static" analysis handling
|
||||
* oct: Attempt to enable the Octphy for the osmo-bts-oct build
|
||||
* debian: Use the header files installed by openbsc-dev
|
||||
* build: Do not require more headers from OpenBSC
|
||||
* sysmobts: Make reservation for mode/netmask/ip and suc
|
||||
* sysmobts: Store a simple network config in the EEPROM as well
|
||||
|
||||
[ Max ]
|
||||
* Ensure TRX invariant
|
||||
* Use libosmocore function for uplink measurements
|
||||
* Fix debug output
|
||||
* Fix RTP timestamps in case of DTX
|
||||
* Add DTXd support for sysmoBTS and LC15
|
||||
* Use libosmocodec for AMR RTP
|
||||
* octphy: Use the app. info. defaults as base
|
||||
* Fix debug output
|
||||
* DTXd: store/repeat last SID
|
||||
* DTXd: store/repeat last SID
|
||||
* DTXu: mark beginning of speech burst in RTP
|
||||
* Fix OML activation
|
||||
* TRX: Add vty command to power on/off transceiver
|
||||
* TRX: add configuration example
|
||||
* Add .gitreview
|
||||
* DTX: add support for AMR/HR
|
||||
* Move copy-pasted code into common part
|
||||
* Use libosmocodec functions for AMR
|
||||
* Use error values instead of number for RSL error
|
||||
* Clarify logging message
|
||||
* Make get_lchan_by_chan_nr globally available
|
||||
* DTXu: move copy-pasted code to common part
|
||||
* Remove duplicated nibble shift code
|
||||
* TRX: add Uplink DTX support for FR/HR
|
||||
* Mark array as static const
|
||||
* sysmobts: dump PRACH and PTCCH parameters
|
||||
* Activate PTCCH UL
|
||||
* Fix dsp tracing at phy config
|
||||
* octphy: fix build
|
||||
* Fill measurements data for L1SAP
|
||||
* sysmo: ts_connect: log channel combination name instead of number
|
||||
* DTX: fix last SID saving
|
||||
* DTX: fix SID repeat scheduling
|
||||
* DTX: fix SID logic
|
||||
* lc15, sysmo: Use SID_FIRST_P1 to initiate DTX
|
||||
* DTX: check Marker bit to send ONSET to L1
|
||||
* DTX: remove misleading comment
|
||||
* LC15: Clarify msgb ownership / fix memory leaks
|
||||
* DTX: move scheduling check inside repeat_last_sid
|
||||
* DTX: further AMR SID cache fixes (lc15, sysmo)
|
||||
* DTX: move ONSET detection into separate function
|
||||
* DTX: send AMR voice alongside with ONSET
|
||||
* DTX: fix conversion from fn to ms
|
||||
* Move copy-pasted array into shared header
|
||||
* DTX DL: use FSM for AMR
|
||||
* TRX: fix building with latest DTX changes
|
||||
* DTX: fix array size calculation
|
||||
* DTX AMR - fix buffer length check
|
||||
* Replace magic number with define
|
||||
* Fix lc15 build
|
||||
* Extend RTP RX callback parameters
|
||||
* DTX HR - fix array size calculation
|
||||
* Fix DTX DL AMR SIDscheduling logic
|
||||
* Add tools to check DTX operation
|
||||
* DTX DL: split ONSET state handling
|
||||
* Remove obsolete define
|
||||
* DTX DL: add AMR HR support to scheduling check
|
||||
* DTX fix ONSET handling
|
||||
* dtx_check.gawk: Fix false-positives in DTX check
|
||||
* Fix tests linking with libosmocodec
|
||||
* DTX DL: tighten check for enabled operation
|
||||
* DTX: wrap FSM signal dispatching
|
||||
* Add libosmocodec for octphy build
|
||||
* dtx_check.gawk: add check for repetitive SID FIRST
|
||||
* Remove duplicated code
|
||||
* Replace link_id constant with define
|
||||
* DTX DL AMR: rewrite FSM recursion
|
||||
* Remove duplicated code
|
||||
* Fix AGCH/PCH proportional allocation
|
||||
* TRX: prevent segfault upon phy init
|
||||
* DTX: add explicit check if DTX enabled
|
||||
* Save RTP metadata in Control Buffer
|
||||
* osmo-bts-trx: fix lchan deactivation
|
||||
* DTX: fix TS adjustment for ONSET
|
||||
* Optionally use adaptive RTP jitter buffering
|
||||
* Integrate Debian packaging changes
|
||||
* DTX AMR HR: fix inhibition
|
||||
* Add copyright for .deb packages
|
||||
* Move code to libosmocore
|
||||
* Log socket path on error
|
||||
* Add Abis OML failure event reporting
|
||||
* Alarm on various errors
|
||||
* Remove obsolete define TLVP_PRES_LEN
|
||||
* scheduler: log lchan on which prim error occured
|
||||
* deb: use gsm_data_shared.* from openbsc-dev
|
||||
* OML: internalize failure reporting
|
||||
* Add ctrl command to send OML alert
|
||||
* Fix typo in TCH/H interleaving table
|
||||
* Use oml-alert CTRL command for temp report
|
||||
* Remove code duplication
|
||||
* Handle ctrl cmd allocation failures
|
||||
* Check for suitable lchan type when detecting HO
|
||||
* osmo-bts-trx: fix scheduling of broken frames
|
||||
* Sync protocol with OsmoPCU
|
||||
* vty: reduce code duplication
|
||||
* Handle TXT indication from OsmoPCU
|
||||
* Add MS TO to RSL measurements
|
||||
* Signal to BSC when PCU disconnects
|
||||
* Prepare for extended SI2quater support
|
||||
* Set BTS variant while initializing BTS model
|
||||
* Prepare for BTS attribute reporting via OML
|
||||
* osmo-bts-trx: use libosmocoding
|
||||
* Remove redundant test
|
||||
* Implement basic Get Attribute responder
|
||||
* Add version to phy_instance
|
||||
* OML: fix Coverity-reported issues
|
||||
* Re-add version to phy_instance
|
||||
* Use systemd template specifiers
|
||||
* Place *-mgr config examples according to BTS model
|
||||
* lc15: add example systemd service file
|
||||
* Extend Get Attribute responder
|
||||
* Set and report BTS features
|
||||
* Cleanup SI scheduling
|
||||
* RSL: receive and send multiple SI2q messages
|
||||
* RSL: check for abnormal SI2q values
|
||||
* lc15bts-mgr: use extended config file example
|
||||
* Move parameter file opening into separate function
|
||||
* Move common steps into common jenkins helper
|
||||
* lc15: add jenkins helper
|
||||
* Use generic L1 headers helper
|
||||
* Copy sysmobts.service to osmo-bts-sysmo
|
||||
* OML: move BTS number check into separate function
|
||||
* lc15: make jenkins helper executable
|
||||
* lc15: fix jenkins build
|
||||
* Add missing include for abis.h header file
|
||||
* RSL: receive and send multiple SI2q messages
|
||||
* Use release helper from libosmocore
|
||||
* si2q: do not consider count update as error
|
||||
* Cleanup example config files
|
||||
* Fix .deb build
|
||||
* Unify *.service files
|
||||
* lc15: cleanup board parameters reading
|
||||
* lc15-mgr: update parameter read/write
|
||||
* lc15: fix BTS revision and hw options
|
||||
* lc15: make default config usable
|
||||
* lc15: port lc15bts-mgr changes
|
||||
* lc15bts-mgr: separate service file
|
||||
* lc15: port lc15bts-mgr dependency changes
|
||||
* Simplify jenkins build scripts
|
||||
* OML: use fom_hdr while handling attr. request
|
||||
* osmo-bts-trx: fix 'osmotrx legacy-setbsic'
|
||||
* osmo-bts-trx: remove global variables from loops
|
||||
|
||||
[ Daniel Laszlo Sitzer ]
|
||||
* octphy: Update outdated config param name in error message.
|
||||
|
||||
[ Jason DSouza ]
|
||||
* Close TRX session before opening new one
|
||||
|
||||
[ Minh-Quang Nguyen ]
|
||||
* l1sap.h: fix wrong L1SAP_FN2PTCCHBLOCK calculation according to TS 45.002 Table 6
|
||||
* common/abis.c: fix 100% CPU usage after disconnecting OML/RSL link (Bug #1703)
|
||||
* LC15: Bring back DSP trace argument
|
||||
* LC15: Hardware changes
|
||||
* LC15: TRX nominal TX power can be used from EEPROM or from BTS configuration
|
||||
* rsl: Fix dropping of LAPDm UA message.
|
||||
* LC15: properly handle BS-AG-BLKS-RES as received from BSC
|
||||
|
||||
[ Neels Hofmeyr ]
|
||||
* sysmo: add L3 handle to l1prim messages
|
||||
* pcu_sock: add pcu_connected() to query PCU availability
|
||||
* tests/stubs.c: remove unused stubs
|
||||
* fix typo in error message ('at lEast')
|
||||
* oml, Set Chan Attr: treat unknown PCHAN types as error
|
||||
* dyn PDCH: rsl rx dchan: also log ip.access message names
|
||||
* doc: add ladder diagram on dynamic PDCH, add msc-README
|
||||
* add missing DSUM entry to bts_log_info_cat
|
||||
* fix compiler warning: printf format for sizeof()
|
||||
* fix compiler warning: add missing case (PHY_LINK_CONNECTING)
|
||||
* fix two compiler warnings: add two opaque struct declarations
|
||||
* dyn PDCH: add bts_model_ts_connect() and _disconnect() stubs
|
||||
* dyn PDCH: conf_lchans_for_pchan(): handle TCH/F_PDCH
|
||||
* dyn PDCH: pcu_tx_info_ind(): handle TCH/F_PDCH in PDCH mode
|
||||
* dyn PDCH: chan_nr_by_sapi(): handle TCH/F_PDCH according to ts->flags
|
||||
* dyn PDCH: implement main dyn PDCH logic in common/
|
||||
* dyn PDCH: sysmo-bts/oml.c: add ts_connect_as(), absorbing ts_connect() guts
|
||||
* dyn PDCH: sysmo: handle TCH/F_PDCH init like TCH/F
|
||||
* dyn PDCH: complete for sysmo-bts: implement bts_model_ts_*()
|
||||
* error log: two minor clarifications
|
||||
* debug log: log lchan state transitions
|
||||
* debug log: log TS pchan type on connect
|
||||
* fix lc15 build: put src/common/libbts.a left of -losmogsm
|
||||
* lc15: add L3 handle to l1prim messages
|
||||
* dyn PDCH: lc15: chan_nr_by_sapi(): handle TCH/F_PDCH according to ts->flags
|
||||
* dyn PDCH: lc15: add ts_connect_as(), absorbing ts_connect() guts
|
||||
* dyn PDCH: lc15: handle TCH/F_PDCH init like TCH/F
|
||||
* dyn PDCH: lc15: complete for litecell15-bts: implement bts_model_ts_*()
|
||||
* dyn PDCH: safeguard: exit if nothing pending in dyn_pdch_ts_disconnected()
|
||||
* vty: install orphaned trx nominal power command
|
||||
* fix compiler warnings: include bts_model.h in phy_link.c
|
||||
* fix compiler warning: remove useless 'static' storage class for struct decl
|
||||
* fix compiler warning: remove unused variable 'i' in calib_verify()
|
||||
* log: osmo-bts-trx: change access burst logs to DEBUG level
|
||||
* log: osmo-bts-trx: change PDTCH block logs to DEBUG level
|
||||
* osmo-bts-trx: init OML only once by sending AVSTATE_OK with OPSTATE_ENABLED
|
||||
* doc: move dyn_pdch.msc to osmo-gsm-manuals.git
|
||||
* error log: rsl.c: typo x2
|
||||
* info log: l1sap.c: add '0x' to hex output
|
||||
* fix compiler warning: msg_utils.c: fn_chk() constify arg
|
||||
* fix compiler warning: msg_utils.c: fn_chk() constify arg
|
||||
* info log: l1sap.c: add '0x' to hex output
|
||||
* error log: rsl.c: typo x2
|
||||
* dyn PDCH: code dup: use conf_lchans_as_pchan()
|
||||
* prepare dyn TS: split/replace conf_lchans_for_pchan()
|
||||
* code dup: join [rsl_]lchan_lookup() from libbsc and osmo-bts
|
||||
* dyn TS: common TCH/F_TCH/H_PDCH implementation
|
||||
* sysmo/oml.c: rename ts_connect() to ts_opstart()
|
||||
* dyn TS: implement SysmoBTS specifics
|
||||
* lc15/oml.c: rename ts_connect() to ts_opstart()
|
||||
* dyn TS: implement litecell15 specifics
|
||||
* comment typo: common/l1sap.c
|
||||
* log typo: trx_sched_set_pchan()
|
||||
* dyn TS: sysmo,lc15: chan_nr_by_sapi(): add missing assertion
|
||||
* fix comment in common/l1sap.c, function name changed
|
||||
* dyn TS, dyn PDCH: common/l1sap.c: properly notice PDCH
|
||||
* dyn PDCH: trx l1_if.c: factor out trx_set_ts_as_pchan() from trx_set_ts()
|
||||
* dyn PDCH: complete for trx: implement bts_model_ts_[dis]connect()
|
||||
* dyn PDCH: trx l1_if.c: drop fixme, add comment
|
||||
* dyn TS: complete for TRX
|
||||
* dyn TS: measurement.c: replace fixme with comment
|
||||
* sysmo,lc15: ts_connect_as(): log error also for pchan_as == TCH/F_PDCH
|
||||
* sysmo: fix dyn TS: Revert "Activate PTCCH UL" [in sysmobts]
|
||||
* log: l1sap: add 0x to hex output of chan_nr, 5 times
|
||||
* dyn TS: measurement: use correct nr of subslots, rm code dup
|
||||
* dyn TS: sysmo,lc15: ph_data_req: fix PDCH mode detection
|
||||
* Fix ip.access style dyn PDCH, broken in 37af36e85eca546595081246aec010fa7f6fd0be
|
||||
* common/rsl: move decision whether to chan act ack/nack to common function
|
||||
* octphy: fix build: Revert "octphy: fix for multiple trx with more than 1 dsp"
|
||||
* octphy: fix build: Revert "octphy: add support for multiple trx ids"
|
||||
* octphy: fix build with OCTSDR-OPENBSC-02.07.00-B708: name changed
|
||||
* dyn TS: if PCU is not connected, allow operation as TCH
|
||||
* log: sysmo,lc15: tweak log about sapi_cmds queue
|
||||
* log causing rx event for lchan_lookup errors
|
||||
* heed VTY 'line vty'/'bind' command
|
||||
* sysmobts_mgr, lc15bts_mgr: fix tall context for telnet vty
|
||||
* build: be robust against install-sh files above the root dir
|
||||
* configure: check for pkg-config presence
|
||||
* jenkins.sh: use osmo-build-dep.sh, log test failures
|
||||
* msgb ctx: use new msgb_talloc_ctx_init() in various main()s
|
||||
* jenkins-oct.sh: fix build: typo in deps path
|
||||
* fix 'osmo-bts-* --version' segfault
|
||||
* osmo-bts-trx: remove obsolete include of netif/rtp.h
|
||||
* add jenkins_bts_trx.sh
|
||||
* add jenkins_oct_and_bts_trx.sh
|
||||
* jenkins: add jenkins_bts_model.sh
|
||||
* bursts test: test_pdtch: pre-init result mem
|
||||
* fix: dyn ts: uplink measurement report
|
||||
* fix missing ~ in bit logic for lchan->si.valid in rsl_rx_sacch_inf_mod()
|
||||
* SACCH: fix sending of SI with an enum value > 7
|
||||
* SACCH SI: assert that SI enum vals fit in bit mask
|
||||
* all models: fix vty write: bts_model_config_write_phy
|
||||
* jenkins: add value_string termination check
|
||||
* Revert "Add version to phy_instance"
|
||||
* Revert "RSL: check for abnormal SI2q values"
|
||||
* Revert "RSL: receive and send multiple SI2q messages"
|
||||
|
||||
[ Harald Welte ]
|
||||
* sysmobts: screnrc/systemd-service: Use osmo-bts-sysmo instead of sysmobts
|
||||
* Add .mailmap for mapping mail addresses in shortlog
|
||||
* vty: Ensure to not use negative (error) sapi value
|
||||
* sysmobts: Add correct nominal transmit power for sysmoBTS 1020
|
||||
* sysmobts_eeprom.h: Fix/extend model number definitions
|
||||
* Revert "sysmobts: Add correct nominal transmit power for sysmoBTS 1020"
|
||||
* tx_power: Change PA calibration tables to use delta vales
|
||||
* Add new unit-test for transmit power computation code
|
||||
* sysmobts: fully support trx_power_params
|
||||
* README: Add general project information and convert to markdown
|
||||
* README: update some of the limitations
|
||||
* sysmobts: Don't start with 0dBm TRX output power before ramping
|
||||
* Remove unusued left-over gsm0503_conv.c
|
||||
* scheduler_trx.c: Avoid code duplication for BER10k computation
|
||||
* scheduler_trx: Avoid copy+pasting determining CMR from FN
|
||||
* rx_tchh_fn(): Avoid copy+pasting formula to determine odd-ness of fn
|
||||
* Consistently check for minimum attribute/TLV length in RSL and OML
|
||||
* l1sap.c: Add spec reference to link timeout implementation
|
||||
* osmo-bts-trx: Remove duplicate parsing of NM_ATT_CONN_FAIL_CRIT
|
||||
* vty: Remove command for manual channel activation/deactivation
|
||||
* l1_if: Add inline functions to check dsp/fgpa version at runtime
|
||||
* sysmobts: Re-order the bit-endianness of every HR codec parameter
|
||||
* OML Add osmocom-specific way to deactivate radio link timeout
|
||||
* measurement: Remove dead code
|
||||
* l1sap.c: Factor out function to limit message queue
|
||||
* osmo-bts-sysmo/l1_if.c: PH-DATA.ind belongs to L1P, not L1C
|
||||
* l1sap: if lchan is in loopback, don't accept incoming RTP
|
||||
* TRX: Use timerfd and CLOCK_MONOTONIC for GSM frame timer (Closes: #2325)
|
||||
* Add loopback support for PDTCH
|
||||
* TRX: trx_if: Improve code description / comments
|
||||
* trx_if: Improve error handling
|
||||
* TRX: Rename trx_if_data() -> trx_if_send_burst()
|
||||
* TRX: merge/simplify l1_if and trx_if code
|
||||
* TRX: don't free l1h in trx_phy_inst_close()
|
||||
* l1sap: Don't enqueue PTCCH blocks for loopback
|
||||
* TRX: permit transmission of all-zero loopback frames
|
||||
* jenkins helpers: some minimal documentation/comments + print errors
|
||||
* VIRT-PHY: Initial check-in of a new virtual BTS
|
||||
* VIRT-PHY: Fix handling of default values for vty configuration
|
||||
* VIRT-PHY: Use IPv4 multicast groups for private / local scope
|
||||
* VIRT-PHY: cause BTS to terminate in case of recv()/send() on udp socket returns 0
|
||||
* Ensure we don't send dummy UI frames on BCCH for TC=5
|
||||
* virt: Don't print NOTICE log message if ARFCN doesn't match
|
||||
* VIRT-PHY: Report virtual RACH bursts with plausible burst type
|
||||
* scheduler: Fix wrong log subsystem: L1C is L1 *control* not user data
|
||||
* VIRT-PHY: Print NOTICE log message from unimplemented stubs
|
||||
* TRX / VIRT-PHY: Make check for BCCH/CCCH more specific
|
||||
* L1SAP: Print chan_nr and link_id always as hex
|
||||
* VIRT-BTS: Support for GPRS
|
||||
* L1SAP: Use RSL_CHAN_OSMO_PDCH across L1SAP
|
||||
* GSMTAP: Don't log fill frames via GSMTAP
|
||||
* TRX: Remove bogus extern global variable declarations
|
||||
* l1sap/osmo-bts-sysmo: Improve logging
|
||||
* TRX: Remove global variables, move SETBSIC/SETTSC handling into phy_link
|
||||
* Fix build after recent gsm_bts_alloc() change
|
||||
* Treat SIGTERM just like SIGINT in our programs
|
||||
|
||||
[ Tom Tsou ]
|
||||
* trx: Add EGPRS tables, sequences, and mappings
|
||||
* trx: Add EGPRS coding and decoding procedures
|
||||
* trx: Enable EGPRS handling through burst lengths
|
||||
* trx: Fix coverity BER calculation NULL dereference
|
||||
|
||||
[ Vadim Yanitskiy ]
|
||||
* pcu_sock: use osmo_sock_unix_init() from libosmocore
|
||||
* osmo-bts-trx/l1_if.c: use channel combination III for TCH/H
|
||||
* scheduler_trx.c: strip unused variable
|
||||
|
||||
[ Mike McTernan ]
|
||||
* osmo-bts-trx: Fix PCS1900 operation
|
||||
* osmo-bts-trx: log decoder bit errors as DEBUG, not NOTICE
|
||||
|
||||
[ bhargava ]
|
||||
* Change interface in osmo-bts for 11 bit RACH
|
||||
* Update parameters in osmo-bts-sysmo for 11bit RACH
|
||||
* 11bit RACH support for osmo-bts-litecell15
|
||||
* Initialize parameters in osmo-trx for 11bit RACH
|
||||
|
||||
[ Philipp ]
|
||||
* octphy: Fixing missing payload type in ph. chan. activation
|
||||
* octphy: Fixing band selection for ARFCN 0
|
||||
* octphy: reintroducing multi-trx support
|
||||
* octopy: fixing renamed constant
|
||||
* octphy: prevent mismatch between dsp-firmware and octphy headers
|
||||
* rsl: improving the log output
|
||||
* octphy: multi-trx support: fix AC_CHECK order
|
||||
* RSL: drop obsolete NULL check
|
||||
* RSL: add assertions to check args of public API
|
||||
* OML: fix possible segfault: add NULL check in oml_ipa_set_attr()
|
||||
* CTRL: make the CTRL-Interface IP address configurable
|
||||
* l1sap: Fix expired rach slot counting
|
||||
* l1sap: fix missing 'else's causing wrong rach frame expiry counts
|
||||
* octphy: set tx attenuation via VTY
|
||||
* octphy: Improve OML ADM state handling
|
||||
|
||||
[ Yves Godin ]
|
||||
* DTX: fix 1st RTP packet drop
|
||||
|
||||
[ Alexander Chemeris ]
|
||||
* l1sap: Fix use-after-free in loopback mode.
|
||||
* vty: Add commands to manually activate/deactivate a channel.
|
||||
* trx: Add "maxdlynb" VTY command to control max TA for Normal Bursts.
|
||||
* rsl: Output RTP stats before closing the socket.
|
||||
* osmo-bts-trx: Fix MS power control loop.
|
||||
* osmo-bts-trx: Remove an unused variable. Resolves a compiler warning.
|
||||
* osmo-bts-trx: Increase a maximum allowed MS power reduction step from 2dB to 4dB.
|
||||
* Fix static build of osmo-bts-trx and osmo-bts-virtual.
|
||||
|
||||
[ Jean-Francois Dionne ]
|
||||
* DTX: don't always perform AMR HR specific check
|
||||
* DTX: fix SID-FIRST detection
|
||||
* lc15,sysmobts l1_if: fix memleak in handle_mph_time_ind()
|
||||
* sysmo,lc15: fix memory leak at each call placed
|
||||
* DTX: fix "unexpected burst" error
|
||||
* Fix AMR HR DTX FSM logic.
|
||||
* Fix SACCH channel release indication not sent to BSC after location update.
|
||||
* Fix RTP duration adjustment not done when speech resumes in DTX mode.
|
||||
|
||||
[ Ruben Undheim ]
|
||||
* Fix some spelling errors
|
||||
|
||||
[ Holger Freyther ]
|
||||
* Revert "deb: use gsm_data_shared.* from openbsc-dev"
|
||||
|
||||
[ Philipp Maier ]
|
||||
* octphy VTY: fix vty write output for octphy's phy section
|
||||
* octphy: Fix VTY commands
|
||||
* l1sap: fix rach reason (ra) parsing
|
||||
* l1sap: fix PTCCH detection
|
||||
* octphy: fix usage of wrong define constant
|
||||
* octphy: add CBCH support
|
||||
* l1sap: improve log output
|
||||
* octphy: print log message for multi-trx support
|
||||
* octphy: display hint in case of wrongly configured transceiver number
|
||||
* octphy: add conditional compilation to support latest octasic header release
|
||||
* octphy: set tx/rx antenne IDs via VTY
|
||||
* bts: revert trx shutdown order
|
||||
* octphy: activate CBCH after all physical channels are activated
|
||||
* octphy: align frame number for new firmware versions
|
||||
* octphy: ensure that 11 bit rach flag is not set
|
||||
* measurement: fix measurement reporting period
|
||||
* measurement: make lchan_meas_check_compute() available to l1sap.c
|
||||
* measurement: Compute measurement results on measurement idication
|
||||
* measurement: exclude idle channels from uplink measurement
|
||||
* octphy: integrate channel measurement handling
|
||||
* octphy: remove old event control code
|
||||
* osmo-bts-sysmo: Include frame number in MEAS IND
|
||||
* measurement: fix measurement computation
|
||||
* octphy: fix segfault
|
||||
* Revert "measurement: exclude idle channels from uplink measurement"
|
||||
* sysmobts: normalize frame number in measurement indication
|
||||
* measurement: Improve log output
|
||||
* measurement: improve log output
|
||||
* octphy: improve log output
|
||||
* octphy: initalize l1msg and only when needed
|
||||
* octphy: initalize nmsg only when needed
|
||||
* octphy: remove log output
|
||||
* Revert "sysmobts: normalize frame number in measurement indication"
|
||||
* osmo-bts-trx: fix missing frame number in MEAS IND
|
||||
* osmo-bts-litecell15: Fix missing frame number in MEAS IND
|
||||
* Revert "osmo-bts-sysmo: Include frame number in MEAS IND"
|
||||
* octphy: complete value strings (octphy_cid_vals)
|
||||
* octphy: do not send empty frames to phy
|
||||
* osmo-bts-sysmo: Include frame number in MEAS IND
|
||||
* measurement: fix measurment report
|
||||
* octphy: remap frame number in MEAS_IND
|
||||
* octphy: implement support for dynamic timeslots
|
||||
|
||||
[ Ivan Klyuchnikov ]
|
||||
* osmo-trx-bts: Fix incorrect setting of RXGAIN and POWER parameters on second channel (TRX1) of osmo-trx
|
||||
* osmo-trx-bts: Fix osmo-bts-trx crash on startup during reading phy instance parameters from config file
|
||||
* osmo-trx-bts: Fix incorrect bts shutdown procedure in case of abis connection closure
|
||||
* osmo-trx-bts: Fix incorrect bts shutdown procedure in case of clock loss from osmo-trx
|
||||
|
||||
[ Ivan Kluchnikov ]
|
||||
* oml: Fix incorrect usage of const variable abis_nm_att_tlvdef_ipa
|
||||
|
||||
[ Pau Espin Pedrol ]
|
||||
* phy_link: Fix typo in state being printed
|
||||
* trx: Allow BTS and TRX to be on different IPs
|
||||
* trx: Save osmotrx base-port vty properties
|
||||
* sysmo/tch.c: Clean up use of empty buffer
|
||||
* litecell15/tch.c: Clean up use of empty buffer
|
||||
* Use L1P instead of L1C for TCH logging and allocation
|
||||
* Fix annoying trailing whitespace
|
||||
* sysmo, litecell15: Make sure all TCH events are triggered
|
||||
* sysmo: Remove non longer valid -p option from help
|
||||
* Allow passing low link quality buffers to upper layers
|
||||
* l1sap.c: Avoid sending RTP frame with empty payload
|
||||
* l1sap.c: fn_ms_adj: Add err logging and always return GSM_RTP_DURATION
|
||||
* Move dump_gsmtime to libosmocore as osmo_dump_gsmtime
|
||||
* Use osmo_dump_gsmtime to log fn across different layers
|
||||
* lc15bts-mgr.cfg: Set default vswr to a value inside valid range
|
||||
* litecell15: Register in vty limits for paX_pwr
|
||||
* lc15: Tweak led colors used in service file
|
||||
* lc-15, sysmo: l1_if: print name on PH-DATA.ind unknwon sapi
|
||||
* lc15bts-mgr.service: Prepare dirs and sysctls for the process
|
||||
* osmo-bts-trx: Enable osmotrx tx-attenuation oml by default
|
||||
* osmo-bts-trx: Relax validation to allow TRX data bursts without padding
|
||||
|
||||
[ Sebastian Stumpf ]
|
||||
* VIRT-PHY: Added example configurations for openbsc and osmobts.
|
||||
* VIRT-PHY: Fixed timeslot in gsmtap-msg on downlink which was always 0.
|
||||
* VIRT-PHY: Added test option for fast hyperframe repeat.
|
||||
|
||||
-- Max <msuraev@sysmocom.de> Fri, 25 Aug 2017 15:16:56 +0200
|
||||
|
||||
osmo-bts (0.5.0) unstable; urgency=medium
|
||||
|
||||
* Initial release.
|
||||
|
||||
-- Holger Hans Peter Freyther <holger@moiji-mobile.com> Fri, 01 Apr 2016 16:13:40 +0200
|
||||
1
debian/compat
vendored
Normal file
1
debian/compat
vendored
Normal file
@@ -0,0 +1 @@
|
||||
9
|
||||
35
debian/control
vendored
Normal file
35
debian/control
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
Source: osmo-bts
|
||||
Maintainer: Holger Hans Peter Freyther <holger@moiji-mobile.com>
|
||||
Section: net
|
||||
Priority: optional
|
||||
Build-Depends: debhelper (>= 9),
|
||||
pkg-config,
|
||||
dh-autoreconf,
|
||||
dh-systemd (>= 1.5),
|
||||
autotools-dev,
|
||||
pkg-config,
|
||||
libosmocore-dev,
|
||||
libosmo-abis-dev,
|
||||
libosmo-netif-dev,
|
||||
libgps-dev,
|
||||
libortp-dev,
|
||||
txt2man
|
||||
Standards-Version: 3.9.8
|
||||
Vcs-Browser: http://git.osmocom.org/osmo-bts/
|
||||
Vcs-Git: git://git.osmocom.org/osmo-bts
|
||||
Homepage: https://projects.osmocom.org/projects/osmobts
|
||||
|
||||
Package: osmo-bts-trx
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends}, ${misc:Depends}
|
||||
Description: osmo-bts-trx GSM BTS with osmo-trx
|
||||
osmo-bts-trx to be used with the osmo-trx application
|
||||
|
||||
Package: osmo-bts-trx-dbg
|
||||
Architecture: any
|
||||
Section: debug
|
||||
Priority: extra
|
||||
Depends: osmo-bts-trx (= ${binary:Version}), ${misc:Depends}
|
||||
Description: Debug symbols for the osmo-bts-trx
|
||||
Make debugging possible
|
||||
|
||||
81
debian/copyright
vendored
Normal file
81
debian/copyright
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||
Upstream-Name: osmo-bts
|
||||
Source: http://cgit.osmocom.org/osmo-bts/
|
||||
|
||||
Files: *
|
||||
Copyright: 2008-2014 Harald Welte <laforge@gnumonks.org>
|
||||
2009,2011,2013 Andreas Eversberg <jolly@eversberg.eu>
|
||||
2010,2011 On-Waves
|
||||
2012-2015 Holger Hans Peter Freyther
|
||||
2014 sysmocom s.f.m.c. Gmbh
|
||||
2015 Alexander Chemeris <Alexander.Chemeris@fairwaves.co>
|
||||
License: AGPL-3+
|
||||
|
||||
Files: src/osmo-bts-sysmo/eeprom.c
|
||||
src/osmo-bts-sysmo/eeprom.h
|
||||
Copyright: 2012 Nutaq
|
||||
License: MIT
|
||||
Comment: Yves Godin is the author
|
||||
|
||||
Files: src/common/pcu_sock.c
|
||||
Copyright: 2008-2010 Harald Welte <laforge@gnumonks.org>
|
||||
2009-2012 Andreas Eversberg <jolly@eversberg.eu>
|
||||
2012 Holger Hans Peter Freyther
|
||||
License: GPL-2+
|
||||
|
||||
Files: debian/*
|
||||
Copyright: 2015-2016 Ruben Undheim <ruben.undheim@gmail.com>
|
||||
License: AGPL-3+
|
||||
|
||||
|
||||
License: AGPL-3+
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
.
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
License: GPL-2+
|
||||
This package is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
.
|
||||
On Debian systems, the complete text of the GNU General
|
||||
Public License version 2 can be found in "/usr/share/common-licenses/GPL-2".
|
||||
|
||||
|
||||
License: MIT
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
.
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
2
debian/osmo-bts-trx.install
vendored
Normal file
2
debian/osmo-bts-trx.install
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
usr/bin/osmo-bts-trx
|
||||
usr/bin/osmo-bts-virtual
|
||||
15
debian/osmo-bts-trx.service
vendored
Normal file
15
debian/osmo-bts-trx.service
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
[Unit]
|
||||
Description=Osmocom osmo-bts for osmo-trx
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStart=/usr/bin/osmo-bts-trx -s -c /etc/osmocom/osmo-bts.cfg
|
||||
Restart=always
|
||||
RestartSec=2
|
||||
|
||||
# Let it process messages quickly enough
|
||||
CPUSchedulingPolicy=rr
|
||||
CPUSchedulingPriority=1
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
32
debian/rules
vendored
Executable file
32
debian/rules
vendored
Executable file
@@ -0,0 +1,32 @@
|
||||
#!/usr/bin/make -f
|
||||
|
||||
DEBIAN := $(shell dpkg-parsechangelog | grep ^Version: | cut -d' ' -f2)
|
||||
DEBVERS := $(shell echo '$(DEBIAN)' | cut -d- -f1)
|
||||
VERSION := $(shell echo '$(DEBVERS)' | sed -e 's/[+-].*//' -e 's/~//g')
|
||||
|
||||
#export DH_VERBOSE=1
|
||||
export DEB_BUILD_MAINT_OPTIONS = hardening=+all
|
||||
|
||||
|
||||
%:
|
||||
dh $@ --with=systemd --with autoreconf --fail-missing
|
||||
|
||||
override_dh_strip:
|
||||
dh_strip --dbg-package=osmo-bts-trx-dbg
|
||||
|
||||
override_dh_autoreconf:
|
||||
echo $(VERSION) > .tarball-version
|
||||
dh_autoreconf
|
||||
|
||||
override_dh_auto_configure:
|
||||
dh_auto_configure -- --enable-trx
|
||||
|
||||
override_dh_clean:
|
||||
dh_clean
|
||||
$(RM) tests/package.m4
|
||||
$(RM) tests/testsuite
|
||||
|
||||
# Print test results in case of a failure
|
||||
override_dh_auto_test:
|
||||
dh_auto_test || (find . -name testsuite.log -exec cat {} \; ; false)
|
||||
|
||||
1
debian/source/format
vendored
Normal file
1
debian/source/format
vendored
Normal file
@@ -0,0 +1 @@
|
||||
3.0 (native)
|
||||
43
doc/examples/litecell15/lc15bts-mgr.cfg
Normal file
43
doc/examples/litecell15/lc15bts-mgr.cfg
Normal file
@@ -0,0 +1,43 @@
|
||||
!
|
||||
! lc15bts-mgr (0.3.0.284-a7c2-dirty) configuration saved from vty
|
||||
!!
|
||||
!
|
||||
log stderr
|
||||
logging filter all 1
|
||||
logging color 1
|
||||
logging print category 0
|
||||
logging timestamp 0
|
||||
logging level temp info
|
||||
logging level fw info
|
||||
logging level find info
|
||||
logging level calib info
|
||||
logging level lglobal notice
|
||||
logging level llapd notice
|
||||
logging level linp notice
|
||||
logging level lmux notice
|
||||
logging level lmi notice
|
||||
logging level lmib notice
|
||||
logging level lsms notice
|
||||
logging level lctrl notice
|
||||
logging level lgtp notice
|
||||
!
|
||||
line vty
|
||||
no login
|
||||
!
|
||||
lc15bts-mgr
|
||||
limits supply_volt
|
||||
threshold warning min 17500
|
||||
threshold critical min 19000
|
||||
limits tx0_vswr
|
||||
threshold warning max 1000
|
||||
limits tx1_vswr
|
||||
threshold warning max 1000
|
||||
limits supply_pwr
|
||||
threshold warning max 110
|
||||
threshold critical max 120
|
||||
limits pa0_pwr
|
||||
threshold warning max 50
|
||||
threshold critical max 60
|
||||
limits pa1_pwr
|
||||
threshold warning max 50
|
||||
threshold critical max 60
|
||||
43
doc/examples/litecell15/osmo-bts.cfg
Normal file
43
doc/examples/litecell15/osmo-bts.cfg
Normal file
@@ -0,0 +1,43 @@
|
||||
!
|
||||
! OsmoBTS (0.0.1.100-0455-dirty) configuration saved from vty
|
||||
!!
|
||||
!
|
||||
log stderr
|
||||
logging color 1
|
||||
logging timestamp 0
|
||||
logging level rsl info
|
||||
logging level oml info
|
||||
logging level rll notice
|
||||
logging level rr notice
|
||||
logging level meas notice
|
||||
logging level pag info
|
||||
logging level l1c info
|
||||
logging level l1p info
|
||||
logging level dsp debug
|
||||
logging level abis notice
|
||||
logging level rtp notice
|
||||
logging level lglobal notice
|
||||
logging level llapd notice
|
||||
logging level linp notice
|
||||
logging level lmux notice
|
||||
logging level lmi notice
|
||||
logging level lmib notice
|
||||
logging level lsms notice
|
||||
!
|
||||
line vty
|
||||
no login
|
||||
!
|
||||
phy 0
|
||||
instance 0
|
||||
trx-calibration-path /mnt/rom/factory/calib
|
||||
phy 1
|
||||
instance 0
|
||||
trx-calibration-path /mnt/rom/factory/calib
|
||||
bts 0
|
||||
band 900
|
||||
ipa unit-id 1500 0
|
||||
oml remote-ip 192.168.234.185
|
||||
trx 0
|
||||
phy 0 instance 0
|
||||
trx 1
|
||||
phy 1 instance 0
|
||||
34
doc/examples/octphy/osmo-bts-trx2dsp1.cfg
Normal file
34
doc/examples/octphy/osmo-bts-trx2dsp1.cfg
Normal file
@@ -0,0 +1,34 @@
|
||||
!
|
||||
! OsmoBTS () configuration saved from vty
|
||||
!!
|
||||
!
|
||||
log stderr
|
||||
logging color 1
|
||||
logging timestamp 0
|
||||
logging level rsl info
|
||||
logging level oml info
|
||||
logging level rll notice
|
||||
logging level rr notice
|
||||
logging level meas notice
|
||||
logging level pag info
|
||||
logging level l1c info
|
||||
logging level l1p info
|
||||
logging level dsp info
|
||||
logging level abis notice
|
||||
!
|
||||
line vty
|
||||
no login
|
||||
!
|
||||
phy 0
|
||||
octphy hw-addr 00:0c:de:ad:fa:ce
|
||||
octphy net-device eth2
|
||||
instance 0
|
||||
instance 1
|
||||
bts 0
|
||||
band 1800
|
||||
ipa unit-id 1234 0
|
||||
oml remote-ip 127.0.0.1
|
||||
trx 0
|
||||
phy 0 instance 0
|
||||
trx 1
|
||||
phy 0 instance 1
|
||||
31
doc/examples/octphy/osmo-bts.cfg
Normal file
31
doc/examples/octphy/osmo-bts.cfg
Normal file
@@ -0,0 +1,31 @@
|
||||
!
|
||||
! OsmoBTS () configuration saved from vty
|
||||
!!
|
||||
!
|
||||
log stderr
|
||||
logging color 1
|
||||
logging timestamp 0
|
||||
logging level rsl info
|
||||
logging level oml info
|
||||
logging level rll notice
|
||||
logging level rr notice
|
||||
logging level meas notice
|
||||
logging level pag info
|
||||
logging level l1c info
|
||||
logging level l1p info
|
||||
logging level dsp info
|
||||
logging level abis notice
|
||||
!
|
||||
line vty
|
||||
no login
|
||||
!
|
||||
phy 0
|
||||
octphy hw-addr 00:0C:90:2e:80:1e
|
||||
octphy net-device eth0.2342
|
||||
instance 0
|
||||
bts 0
|
||||
band 1800
|
||||
ipa unit-id 1234 0
|
||||
oml remote-ip 127.0.0.1
|
||||
trx 0
|
||||
phy 0 instance 0
|
||||
@@ -3,9 +3,8 @@
|
||||
!!
|
||||
!
|
||||
log stderr
|
||||
logging color 0
|
||||
logging color 1
|
||||
logging timestamp 0
|
||||
logging level all everything
|
||||
logging level rsl info
|
||||
logging level oml info
|
||||
logging level rll notice
|
||||
@@ -14,13 +13,17 @@ log stderr
|
||||
logging level pag info
|
||||
logging level l1c info
|
||||
logging level l1p info
|
||||
logging level dsp debug
|
||||
logging level dsp info
|
||||
logging level abis notice
|
||||
!
|
||||
line vty
|
||||
no login
|
||||
!
|
||||
phy 0
|
||||
instance 0
|
||||
bts 0
|
||||
band 1800
|
||||
ipa unit-id 1234 0
|
||||
oml remote-ip 192.168.100.11
|
||||
ipa unit-id 666 0
|
||||
oml remote-ip 10.1.2.3
|
||||
trx 0
|
||||
phy 0 instance 0
|
||||
@@ -6,7 +6,6 @@ log stderr
|
||||
logging filter all 1
|
||||
logging color 1
|
||||
logging timestamp 0
|
||||
logging level all everything
|
||||
logging level temp info
|
||||
logging level fw info
|
||||
logging level find info
|
||||
34
doc/examples/trx/osmo-bts.cfg
Normal file
34
doc/examples/trx/osmo-bts.cfg
Normal file
@@ -0,0 +1,34 @@
|
||||
!
|
||||
! OsmoBTS () configuration saved from vty
|
||||
!!
|
||||
!
|
||||
log stderr
|
||||
logging color 1
|
||||
logging timestamp 0
|
||||
logging level rsl notice
|
||||
logging level oml notice
|
||||
logging level rll notice
|
||||
logging level rr notice
|
||||
logging level meas error
|
||||
logging level pag error
|
||||
logging level l1c error
|
||||
logging level l1p error
|
||||
logging level dsp error
|
||||
logging level abis error
|
||||
!
|
||||
line vty
|
||||
no login
|
||||
!
|
||||
phy 0
|
||||
instance 0
|
||||
osmotrx rx-gain 1
|
||||
osmotrx ip local 127.0.0.1
|
||||
osmotrx ip remote 127.0.0.1
|
||||
bts 0
|
||||
band 1800
|
||||
ipa unit-id 6969 0
|
||||
oml remote-ip 192.168.122.1
|
||||
gsmtap-sapi ccch
|
||||
gsmtap-sapi pdtch
|
||||
trx 0
|
||||
phy 0 instance 0
|
||||
151
doc/examples/virtual/openbsc-virtual.cfg
Normal file
151
doc/examples/virtual/openbsc-virtual.cfg
Normal file
@@ -0,0 +1,151 @@
|
||||
!
|
||||
! OpenBSC (0.15.0.629-34f0-dirty) configuration saved from vty
|
||||
!!
|
||||
!
|
||||
log stderr
|
||||
logging filter all 1
|
||||
logging color 0
|
||||
logging print category 1
|
||||
logging timestamp 1
|
||||
logging level all info
|
||||
logging level rll notice
|
||||
logging level cc notice
|
||||
logging level mm debug
|
||||
logging level rr notice
|
||||
logging level rsl notice
|
||||
logging level nm info
|
||||
logging level mncc notice
|
||||
logging level pag notice
|
||||
logging level meas notice
|
||||
logging level sccp notice
|
||||
logging level msc notice
|
||||
logging level mgcp notice
|
||||
logging level ho notice
|
||||
logging level db notice
|
||||
logging level ref notice
|
||||
logging level gprs debug
|
||||
logging level ns info
|
||||
logging level bssgp debug
|
||||
logging level llc debug
|
||||
logging level sndcp debug
|
||||
logging level nat notice
|
||||
logging level ctrl notice
|
||||
logging level smpp debug
|
||||
logging level filter debug
|
||||
logging level ranap debug
|
||||
logging level sua debug
|
||||
logging level lglobal notice
|
||||
logging level llapd notice
|
||||
logging level linp notice
|
||||
logging level lmux notice
|
||||
logging level lmi notice
|
||||
logging level lmib notice
|
||||
logging level lsms notice
|
||||
logging level lctrl notice
|
||||
logging level lgtp notice
|
||||
logging level lstats notice
|
||||
logging level lgsup notice
|
||||
logging level loap notice
|
||||
!
|
||||
stats interval 5
|
||||
!
|
||||
line vty
|
||||
no login
|
||||
!
|
||||
e1_input
|
||||
e1_line 0 driver ipa
|
||||
e1_line 0 port 0
|
||||
no e1_line 0 keepalive
|
||||
network
|
||||
network country code 262
|
||||
mobile network code 42
|
||||
short name OpenBSC
|
||||
long name OpenBSC
|
||||
auth policy accept-all
|
||||
authorized-regexp .*
|
||||
location updating reject cause 13
|
||||
encryption a5 0
|
||||
neci 1
|
||||
paging any use tch 0
|
||||
rrlp mode ms-based
|
||||
mm info 1
|
||||
handover 0
|
||||
handover window rxlev averaging 10
|
||||
handover window rxqual averaging 1
|
||||
handover window rxlev neighbor averaging 10
|
||||
handover power budget interval 6
|
||||
handover power budget hysteresis 3
|
||||
handover maximum distance 9999
|
||||
timer t3101 10
|
||||
timer t3103 0
|
||||
timer t3105 0
|
||||
timer t3107 0
|
||||
timer t3109 4
|
||||
timer t3111 0
|
||||
timer t3113 60
|
||||
timer t3115 0
|
||||
timer t3117 0
|
||||
timer t3119 0
|
||||
timer t3122 10
|
||||
timer t3141 0
|
||||
subscriber-keep-in-ram 0
|
||||
bts 0
|
||||
type sysmobts
|
||||
band DCS1800
|
||||
cell_identity 6969
|
||||
location_area_code 1
|
||||
base_station_id_code 63
|
||||
ms max power 0
|
||||
cell reselection hysteresis 4
|
||||
rxlev access min 0
|
||||
periodic location update 30
|
||||
radio-link-timeout 32
|
||||
channel allocator descending
|
||||
rach tx integer 9
|
||||
rach max transmission 7
|
||||
channel-descrption attach 1
|
||||
channel-descrption bs-pa-mfrms 5
|
||||
channel-descrption bs-ag-blks-res 1
|
||||
ip.access unit_id 6969 0
|
||||
oml ip.access stream_id 255 line 0
|
||||
neighbor-list mode automatic
|
||||
codec-support fr
|
||||
gprs mode none
|
||||
no force-combined-si
|
||||
trx 0
|
||||
rf_locked 0
|
||||
arfcn 666
|
||||
nominal power 0
|
||||
max_power_red 0
|
||||
rsl e1 tei 0
|
||||
timeslot 0
|
||||
phys_chan_config CCCH+SDCCH4
|
||||
hopping enabled 0
|
||||
timeslot 1
|
||||
phys_chan_config SDCCH8
|
||||
hopping enabled 0
|
||||
timeslot 2
|
||||
phys_chan_config TCH/F
|
||||
hopping enabled 0
|
||||
timeslot 3
|
||||
phys_chan_config TCH/F
|
||||
hopping enabled 0
|
||||
timeslot 4
|
||||
phys_chan_config TCH/F
|
||||
hopping enabled 0
|
||||
timeslot 5
|
||||
phys_chan_config TCH/F
|
||||
hopping enabled 0
|
||||
timeslot 6
|
||||
phys_chan_config TCH/F
|
||||
hopping enabled 0
|
||||
timeslot 7
|
||||
phys_chan_config TCH/F
|
||||
hopping enabled 0
|
||||
mncc-int
|
||||
default-codec tch-f fr
|
||||
default-codec tch-h hr
|
||||
nitb
|
||||
subscriber-create-on-demand
|
||||
subscriber-create-on-demand random 1 24
|
||||
assign-tmsi
|
||||
61
doc/examples/virtual/osmobts-virtual.cfg
Normal file
61
doc/examples/virtual/osmobts-virtual.cfg
Normal file
@@ -0,0 +1,61 @@
|
||||
!
|
||||
! OsmoBTS (0.4.0.216-bc49-dirty) configuration saved from vty
|
||||
!!
|
||||
!
|
||||
log stderr
|
||||
logging filter all 0
|
||||
logging color 0
|
||||
logging print category 1
|
||||
logging timestamp 0
|
||||
logging level rsl info
|
||||
logging level oml info
|
||||
logging level rll notice
|
||||
logging level rr notice
|
||||
logging level meas notice
|
||||
logging level pag info
|
||||
logging level l1c info
|
||||
logging level l1p info
|
||||
logging level dsp error
|
||||
logging level pcu notice
|
||||
logging level ho debug
|
||||
logging level trx notice
|
||||
logging level loop notice
|
||||
logging level abis debug
|
||||
logging level rtp notice
|
||||
logging level sum error
|
||||
logging level lglobal notice
|
||||
logging level llapd notice
|
||||
logging level linp notice
|
||||
logging level lmux notice
|
||||
logging level lmi notice
|
||||
logging level lmib notice
|
||||
logging level lsms notice
|
||||
logging level lctrl notice
|
||||
logging level lgtp notice
|
||||
logging level lstats error
|
||||
!
|
||||
line vty
|
||||
no login
|
||||
!
|
||||
e1_input
|
||||
e1_line 0 driver ipa
|
||||
e1_line 0 port 0
|
||||
no e1_line 0 keepalive
|
||||
phy 0
|
||||
instance 0
|
||||
bts 0
|
||||
band DCS1800
|
||||
ipa unit-id 6969 0
|
||||
oml remote-ip 127.0.0.1
|
||||
rtp jitter-buffer 100
|
||||
paging queue-size 200
|
||||
paging lifetime 0
|
||||
uplink-power-target -75
|
||||
min-qual-rach 50
|
||||
min-qual-norm -5
|
||||
trx 0
|
||||
power-ramp max-initial 23000 mdBm
|
||||
power-ramp step-size 2000 mdB
|
||||
power-ramp step-interval 1
|
||||
ms-power-control dsp
|
||||
phy 0 instance 0
|
||||
57
doc/phy_link.txt
Normal file
57
doc/phy_link.txt
Normal file
@@ -0,0 +1,57 @@
|
||||
|
||||
== OsmoBTS PHY interface abstraction
|
||||
|
||||
The OsmoBTS PHY interface serves as an abstraction layer between given
|
||||
PHY hardware and the actual logical transceivers (TRXs) of a BTS inside
|
||||
the OsmoBTS code base.
|
||||
|
||||
|
||||
=== PHY link
|
||||
|
||||
A PHY link is a physical connection / link towards a given PHY. This
|
||||
might be, for example,
|
||||
|
||||
* a set of file descriptors to device nodes in the /dev/ directory
|
||||
(sysmobts, litecell15)
|
||||
* a packet socket for sending raw Ethernet frames to an OCTPHY
|
||||
* a set of UDP sockets for interacting with OsmoTRX
|
||||
|
||||
Each PHY interface has a set of attribute/parameters and a list of 1 to
|
||||
n PHY instances.
|
||||
|
||||
PHY links are numbered 0..n globally inside OsmoBTS.
|
||||
|
||||
Each PHY link is configured via the VTY using its individual top-level
|
||||
vty node. Given the different bts-model / phy specific properties, the
|
||||
VTY configuration options (if any) of the PHY instance differ between
|
||||
BTS models.
|
||||
|
||||
The PHY links and instances must be configured above the BTS/TRX nodes
|
||||
in the configuration file. If the file is saved via the VTY, the code
|
||||
automatically ensures this.
|
||||
|
||||
|
||||
=== PHY instance
|
||||
|
||||
A PHY instance is an instance of a PHY, accessed via a PHY link.
|
||||
|
||||
In the case of osmo-bts-sysmo and osmo-bts-trx, there is only one
|
||||
instance in every PHY link. This is due to the fact that the API inside
|
||||
that PHY link does not permit for distinguishing multiple different
|
||||
logical TRXs.
|
||||
|
||||
Other PHY implementations like the OCTPHY however do support addressing
|
||||
multiple PHY instances via a single PHY link.
|
||||
|
||||
PHY instances are numbered 0..n inside each PHY link.
|
||||
|
||||
Each PHY instance is configured via the VTY as a separate node beneath each
|
||||
PHY link. Given the different bts-model / phy specific properties, the
|
||||
VTY configuration options (if any) of the PHY instance differ between
|
||||
BTS models.
|
||||
|
||||
|
||||
=== Mapping PHY instances to TRXs
|
||||
|
||||
Each TRX node in the VTY must use the 'phy N instance M' command in
|
||||
order to specify which PHY instance is allocated to this specific TRX.
|
||||
42
doc/startup.txt
Normal file
42
doc/startup.txt
Normal file
@@ -0,0 +1,42 @@
|
||||
|
||||
== start-up / sequencing during OsmoBTS start
|
||||
|
||||
The start-up procedure of OsmoBTS can be described as follows:
|
||||
|
||||
|===
|
||||
| bts-specific | main() |
|
||||
| common | bts_main() | initialization of talloc contexts
|
||||
| common | bts_log_init() | initialization of logging
|
||||
| common | handle_options() | common option parsing
|
||||
| bts-specific | bts_model_handle_options() | model-specific option parsing
|
||||
| common | gsm_bts_alloc() | allocation of BTS/TRX/TS data structures
|
||||
| common | vty_init() | Initialziation of VTY core, libosmo-abis and osmo-bts VTY
|
||||
| common | main() | Setting of scheduler RR priority (if configured)
|
||||
| common | main() | Initialization of GSMTAP (if configured)
|
||||
| common | bts_init() | configuration of defaults in bts/trx/s object
|
||||
| bts-specific | bts_model_init | ?
|
||||
| common | abis_init() | Initialization of libosmo-abis
|
||||
| common | vty_read_config_file() | Reading of configuration file
|
||||
| bts-specific | bts_model_phy_link_set_defaults() | Called for every PHY link created
|
||||
| bts-specific | bts_model_phy_instance_set_defaults() | Called for every PHY Instance created
|
||||
| common | bts_controlif_setup() | Initialization of Control Interface
|
||||
| bts-specific | bts_model_ctrl_cmds_install()
|
||||
| common | telnet_init() | Initialization of telnet interface
|
||||
| common | pcu_sock_init() | Initializaiton of PCU socket
|
||||
| common | main() | Installation of signal handlers
|
||||
| common | abis_open() | Start of the A-bis connection to BSC
|
||||
| common | phy_links_open() | Iterate over list of configured PHY links
|
||||
| bts-specific | bts_model_phy_link_open() | Open each of the configured PHY links
|
||||
| common | write_pid_file() | Generate the pid file
|
||||
| common | osmo_daemonize() | Fork as daemon in background (if configured)
|
||||
| common | bts_main() | Run main loop until global variable quit >= 2
|
||||
| bts-specific | bts_model_oml_estab() | Called by core once OML link is established
|
||||
| bts-specific | bts_model_check_oml() | called each time OML sets some attributes on a MO, checks if attributes are valid
|
||||
| bts-specific | bts_model_apply_oml() | called each time OML sets some attributes on a MO, stores attribute contents in data structures
|
||||
| bts-specific | bts_model_opstart() | for NM_OC_BTS, NM_OC_SITE_MANAGER, NM_OC_GPRS_NSE, NM_OC_GPRS_CELL, NMO_OC_GPRS_NSVC
|
||||
| bts-specific | bts_model_opstart() | for NM_OC_RADIO_CARRIER for each trx
|
||||
| bts-specific | bts_model_opstart() | for NM_OC_BASEB_TRANSC for each trx
|
||||
| bts-specific | bts_model_opstart() | for NM_OC_CHANNEL for each timeslot on each trx
|
||||
| bts-specific | bts_model_change_power() | change transmit power for each trx (power ramp-up/ramp-down
|
||||
|
||||
| bts-specific | bts_model_abis_close() | called when either one of the RSL links or the OML link are down
|
||||
@@ -1,3 +1 @@
|
||||
SUBDIRS = osmo-bts
|
||||
|
||||
noinst_HEADERS = openbsc/gsm_data.h
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
../osmo-bts/gsm_data.h
|
||||
@@ -1,3 +1,5 @@
|
||||
noinst_HEADERS = abis.h bts.h bts_model.h gsm_data.h logging.h measurement.h \
|
||||
noinst_HEADERS = abis.h bts.h bts_model.h gsm_data.h gsm_data_shared.h logging.h measurement.h \
|
||||
oml.h paging.h rsl.h signal.h vty.h amr.h pcu_if.h pcuif_proto.h \
|
||||
handover.h msg_utils.h tx_power.h control_if.h
|
||||
handover.h msg_utils.h tx_power.h control_if.h cbch.h l1sap.h \
|
||||
power_control.h scheduler.h scheduler_backend.h phy_link.h \
|
||||
dtx_dl_amr_fsm.h
|
||||
|
||||
@@ -11,7 +11,8 @@ void amr_log_mr_conf(int ss, int logl, const char *pfx,
|
||||
|
||||
int amr_parse_mr_conf(struct amr_multirate_conf *amr_mrc,
|
||||
const uint8_t *mr_conf, unsigned int len);
|
||||
|
||||
void amr_set_mode_pref(uint8_t *data, const struct amr_multirate_conf *amr_mrc,
|
||||
uint8_t cmi, uint8_t cmr);
|
||||
unsigned int amr_get_initial_mode(struct gsm_lchan *lchan);
|
||||
|
||||
#endif /* _OSMO_BTS_AMR_H */
|
||||
|
||||
@@ -21,23 +21,29 @@ void destroy_bts(struct gsm_bts *bts);
|
||||
int work_bts(struct gsm_bts *bts);
|
||||
int bts_link_estab(struct gsm_bts *bts);
|
||||
int trx_link_estab(struct gsm_bts_trx *trx);
|
||||
int trx_set_available(struct gsm_bts_trx *trx, int avail);
|
||||
void bts_new_si(void *arg);
|
||||
void bts_setup_slot(struct gsm_bts_trx_ts *slot, uint8_t comb);
|
||||
|
||||
int bts_agch_enqueue(struct gsm_bts *bts, struct msgb *msg);
|
||||
struct msgb *bts_agch_dequeue(struct gsm_bts *bts);
|
||||
void bts_update_agch_max_queue_length(struct gsm_bts *bts);
|
||||
int bts_agch_max_queue_length(int T, int bcch_conf);
|
||||
int bts_ccch_copy_msg(struct gsm_bts *bts, uint8_t *out_buf, struct gsm_time *gt,
|
||||
int is_ag_res);
|
||||
|
||||
uint8_t *bts_sysinfo_get(struct gsm_bts *bts, struct gsm_time *g_time);
|
||||
uint8_t *bts_sysinfo_get(struct gsm_bts *bts, const struct gsm_time *g_time);
|
||||
uint8_t *lchan_sacch_get(struct gsm_lchan *lchan);
|
||||
int lchan_init_lapdm(struct gsm_lchan *lchan);
|
||||
|
||||
void load_timer_start(struct gsm_bts *bts);
|
||||
|
||||
uint8_t num_agch(struct gsm_bts_trx *trx, const char * arg);
|
||||
void bts_update_status(enum bts_global_status which, int on);
|
||||
|
||||
int trx_ms_pwr_ctrl_is_osmo(struct gsm_bts_trx *trx);
|
||||
|
||||
struct gsm_time *get_time(struct gsm_bts *bts);
|
||||
|
||||
int bts_main(int argc, char **argv);
|
||||
|
||||
#endif /* _BTS_H */
|
||||
|
||||
|
||||
@@ -8,12 +8,13 @@
|
||||
|
||||
#include <osmo-bts/gsm_data.h>
|
||||
|
||||
struct phy_link;
|
||||
struct phy_instance;
|
||||
|
||||
/* BTS model specific functions needed by the common code */
|
||||
|
||||
int bts_model_init(struct gsm_bts *bts);
|
||||
|
||||
struct gsm_time *bts_model_get_time(struct gsm_bts *bts);
|
||||
|
||||
int bts_model_check_oml(struct gsm_bts *bts, uint8_t msg_type,
|
||||
struct tlv_parsed *old_attr, struct tlv_parsed *new_attr,
|
||||
void *obj);
|
||||
@@ -27,25 +28,37 @@ int bts_model_opstart(struct gsm_bts *bts, struct gsm_abis_mo *mo,
|
||||
int bts_model_chg_adm_state(struct gsm_bts *bts, struct gsm_abis_mo *mo,
|
||||
void *obj, uint8_t adm_state);
|
||||
|
||||
int bts_model_rsl_chan_act(struct gsm_lchan *lchan, struct tlv_parsed *tp);
|
||||
int bts_model_rsl_chan_rel(struct gsm_lchan *lchan);
|
||||
int bts_model_rsl_chan_mod(struct gsm_lchan *lchan);
|
||||
int bts_model_rsl_deact_sacch(struct gsm_lchan *lchan);
|
||||
int bts_model_rsl_mode_modify(struct gsm_lchan *lchan);
|
||||
|
||||
int bts_model_trx_deact_rf(struct gsm_bts_trx *trx);
|
||||
int bts_model_trx_close(struct gsm_bts_trx *trx);
|
||||
|
||||
void bts_model_rtp_rx_cb(struct osmo_rtp_socket *rs, const uint8_t *rtp_pl,
|
||||
unsigned int rtp_pl_len);
|
||||
|
||||
int bts_model_vty_init(struct gsm_bts *bts);
|
||||
|
||||
void bts_model_config_write_bts(struct vty *vty, struct gsm_bts *bts);
|
||||
void bts_model_config_write_trx(struct vty *vty, struct gsm_bts_trx *trx);
|
||||
void bts_model_config_write_phy(struct vty *vty, struct phy_link *plink);
|
||||
void bts_model_config_write_phy_inst(struct vty *vty, struct phy_instance *pinst);
|
||||
|
||||
int bts_model_oml_estab(struct gsm_bts *bts);
|
||||
|
||||
int bts_model_change_power(struct gsm_bts_trx *trx, int p_trxout_mdBm);
|
||||
int bts_model_adjst_ms_pwr(struct gsm_lchan *lchan);
|
||||
|
||||
int bts_model_l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap);
|
||||
|
||||
int bts_model_lchan_deactivate(struct gsm_lchan *lchan);
|
||||
int bts_model_lchan_deactivate_sacch(struct gsm_lchan *lchan);
|
||||
|
||||
void bts_model_abis_close(struct gsm_bts *bts);
|
||||
|
||||
int bts_model_ctrl_cmds_install(struct gsm_bts *bts);
|
||||
|
||||
int bts_model_handle_options(int argc, char **argv);
|
||||
void bts_model_print_help();
|
||||
|
||||
void bts_model_phy_link_set_defaults(struct phy_link *plink);
|
||||
void bts_model_phy_instance_set_defaults(struct phy_instance *pinst);
|
||||
|
||||
int bts_model_ts_disconnect(struct gsm_bts_trx_ts *ts);
|
||||
int bts_model_ts_connect(struct gsm_bts_trx_ts *ts, enum gsm_phys_chan_config as_pchan);
|
||||
|
||||
#endif
|
||||
|
||||
16
include/osmo-bts/cbch.h
Normal file
16
include/osmo-bts/cbch.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include <osmocom/gsm/gsm_utils.h>
|
||||
#include <osmocom/gsm/protocol/gsm_08_58.h>
|
||||
|
||||
#include <osmo-bts/gsm_data.h>
|
||||
#include <osmo-bts/bts.h>
|
||||
|
||||
/* incoming SMS broadcast command from RSL */
|
||||
int bts_process_smscb_cmd(struct gsm_bts *bts,
|
||||
struct rsl_ie_cb_cmd_type cmd_type,
|
||||
uint8_t msg_len, const uint8_t *msg);
|
||||
|
||||
/* call-back from bts model specific code when it wants to obtain a CBCH
|
||||
* block for a given gsm_time. outbuf must have 23 bytes of space. */
|
||||
int bts_cbch_get(struct gsm_bts *bts, uint8_t *outbuf, struct gsm_time *g_time);
|
||||
@@ -1,4 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
int bts_ctrl_cmds_install(struct gsm_bts *bts);
|
||||
struct ctrl_handle *bts_controlif_setup(struct gsm_bts *bts);
|
||||
struct ctrl_handle *bts_controlif_setup(struct gsm_bts *bts,
|
||||
const char *bind_addr, uint16_t port);
|
||||
|
||||
44
include/osmo-bts/dtx_dl_amr_fsm.h
Normal file
44
include/osmo-bts/dtx_dl_amr_fsm.h
Normal file
@@ -0,0 +1,44 @@
|
||||
#pragma once
|
||||
|
||||
#include <osmocom/core/fsm.h>
|
||||
#include <osmocom/core/utils.h>
|
||||
#include <osmocom/core/logging.h>
|
||||
|
||||
/* DTX DL AMR FSM */
|
||||
|
||||
#define X(s) (1 << (s))
|
||||
|
||||
enum dtx_dl_amr_fsm_states {
|
||||
ST_VOICE,
|
||||
ST_SID_F1,
|
||||
ST_SID_F2,
|
||||
ST_F1_INH_V,
|
||||
ST_F1_INH_F,
|
||||
ST_U_INH_V,
|
||||
ST_U_INH_F,
|
||||
ST_U_NOINH,
|
||||
ST_F1_INH_V_REC,
|
||||
ST_F1_INH_F_REC,
|
||||
ST_U_INH_V_REC,
|
||||
ST_U_INH_F_REC,
|
||||
ST_SID_U,
|
||||
ST_ONSET_V,
|
||||
ST_ONSET_F,
|
||||
ST_ONSET_V_REC,
|
||||
ST_ONSET_F_REC,
|
||||
ST_FACCH,
|
||||
};
|
||||
|
||||
enum dtx_dl_amr_fsm_events {
|
||||
E_VOICE,
|
||||
E_ONSET,
|
||||
E_FACCH,
|
||||
E_COMPL,
|
||||
E_FIRST,
|
||||
E_INHIB,
|
||||
E_SID_F,
|
||||
E_SID_U,
|
||||
};
|
||||
|
||||
extern const struct value_string dtx_dl_amr_fsm_event_names[];
|
||||
extern struct osmo_fsm dtx_dl_amr_fsm;
|
||||
@@ -8,12 +8,23 @@
|
||||
#include <osmo-bts/paging.h>
|
||||
#include <osmo-bts/tx_power.h>
|
||||
|
||||
#define GSM_FR_BITS 260
|
||||
#define GSM_EFR_BITS 244
|
||||
|
||||
#define GSM_FR_BYTES 33 /* TS 101318 Chapter 5.1: 260 bits + 4bit sig */
|
||||
#define GSM_HR_BYTES 14 /* TS 101318 Chapter 5.2: 112 bits, no sig */
|
||||
#define GSM_EFR_BYTES 31 /* TS 101318 Chapter 5.3: 244 bits + 4bit sig */
|
||||
|
||||
#define GSM_SUPERFRAME (26*51) /* 1326 TDMA frames */
|
||||
#define GSM_HYPERFRAME (2048*GSM_SUPERFRAME) /* GSM_HYPERFRAME frames */
|
||||
|
||||
#define GSM_BTS_AGCH_QUEUE_THRESH_LEVEL_DEFAULT 41
|
||||
#define GSM_BTS_AGCH_QUEUE_THRESH_LEVEL_DISABLE 999999
|
||||
#define GSM_BTS_AGCH_QUEUE_LOW_LEVEL_DEFAULT 41
|
||||
#define GSM_BTS_AGCH_QUEUE_HIGH_LEVEL_DEFAULT 91
|
||||
|
||||
struct pcu_sock_state;
|
||||
struct smscb_msg;
|
||||
|
||||
struct gsm_network {
|
||||
struct llist_head bts_list;
|
||||
@@ -73,45 +84,66 @@ struct gsm_bts_role_bts {
|
||||
|
||||
struct paging_state *paging_state;
|
||||
char *bsc_oml_host;
|
||||
struct llist_head oml_queue;
|
||||
unsigned int rtp_jitter_buf_ms;
|
||||
bool rtp_jitter_adaptive;
|
||||
struct {
|
||||
uint8_t ciphers; /* flags A5/1==0x1, A5/2==0x2, A5/3==0x4 */
|
||||
} support;
|
||||
struct {
|
||||
uint8_t tc4_ctr;
|
||||
} si;
|
||||
uint8_t radio_link_timeout;
|
||||
struct gsm_time gsm_time;
|
||||
/* Radio Link Timeout counter. -1 disables timeout for
|
||||
* lab/measurement purpose */
|
||||
int radio_link_timeout;
|
||||
|
||||
int ul_power_target; /* Uplink Rx power target */
|
||||
|
||||
/* used by the sysmoBTS to adjust band */
|
||||
uint8_t auto_band;
|
||||
|
||||
struct {
|
||||
struct llist_head queue; /* list of struct smscb_msg */
|
||||
struct smscb_msg *cur_msg; /* current SMS-CB */
|
||||
} smscb_state;
|
||||
|
||||
float min_qual_rach; /* minimum quality for RACH bursts */
|
||||
float min_qual_norm; /* minimum quality for normal daata */
|
||||
|
||||
struct {
|
||||
char *sock_path;
|
||||
} pcu;
|
||||
|
||||
struct {
|
||||
uint32_t last_fn;
|
||||
struct timeval tv_clock;
|
||||
struct osmo_timer_list fn_timer;
|
||||
} vbts;
|
||||
};
|
||||
|
||||
enum lchan_ciph_state {
|
||||
LCHAN_CIPH_NONE,
|
||||
LCHAN_CIPH_RX_REQ,
|
||||
LCHAN_CIPH_RX_CONF,
|
||||
LCHAN_CIPH_TXRX_REQ,
|
||||
LCHAN_CIPH_TXRX_CONF,
|
||||
LCHAN_CIPH_RXTX_REQ,
|
||||
LCHAN_CIPH_RX_CONF_TX_REQ,
|
||||
LCHAN_CIPH_RXTX_CONF,
|
||||
};
|
||||
|
||||
#define bts_role_bts(x) ((struct gsm_bts_role_bts *)(x)->role)
|
||||
|
||||
#include "openbsc/gsm_data_shared.h"
|
||||
|
||||
struct femtol1_hdl;
|
||||
|
||||
static inline struct femtol1_hdl *trx_femtol1_hdl(struct gsm_bts_trx *trx)
|
||||
{
|
||||
return trx->role_bts.l1h;
|
||||
}
|
||||
|
||||
#include <osmo-bts/gsm_data_shared.h>
|
||||
|
||||
void lchan_set_state(struct gsm_lchan *lchan, enum gsm_lchan_state state);
|
||||
int conf_lchans_as_pchan(struct gsm_bts_trx_ts *ts,
|
||||
enum gsm_phys_chan_config pchan);
|
||||
|
||||
/* cipher code */
|
||||
#define CIPHER_A5(x) (1 << (x-1))
|
||||
|
||||
int bts_supports_cipher(struct gsm_bts_role_bts *bts, int rsl_cipher);
|
||||
|
||||
bool ts_is_pdch(const struct gsm_bts_trx_ts *ts);
|
||||
|
||||
#endif /* _GSM_DATA_H */
|
||||
|
||||
999
include/osmo-bts/gsm_data_shared.h
Normal file
999
include/osmo-bts/gsm_data_shared.h
Normal file
@@ -0,0 +1,999 @@
|
||||
#ifndef _GSM_DATA_SHAREDH
|
||||
#define _GSM_DATA_SHAREDH
|
||||
|
||||
#include <regex.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <osmocom/core/timer.h>
|
||||
#include <osmocom/core/bitvec.h>
|
||||
#include <osmocom/core/statistics.h>
|
||||
#include <osmocom/core/utils.h>
|
||||
#include <osmocom/gsm/gsm_utils.h>
|
||||
#include <osmocom/gsm/tlv.h>
|
||||
#include <osmocom/gsm/rxlev_stat.h>
|
||||
#include <osmocom/gsm/sysinfo.h>
|
||||
#include <osmocom/gsm/meas_rep.h>
|
||||
#include <osmocom/gsm/protocol/gsm_04_08.h>
|
||||
#include <osmocom/gsm/protocol/gsm_08_58.h>
|
||||
#include <osmocom/gsm/protocol/gsm_12_21.h>
|
||||
|
||||
#include <osmocom/abis/e1_input.h>
|
||||
|
||||
#ifndef ROLE_BSC
|
||||
#include <osmocom/gsm/lapdm.h>
|
||||
#endif
|
||||
|
||||
/* 16 is the max. number of SI2quater messages according to 3GPP TS 44.018 Table 10.5.2.33b.1:
|
||||
4-bit index is used (2#1111 = 10#15) */
|
||||
#define SI2Q_MAX_NUM 16
|
||||
/* length in bits (for single SI2quater message) */
|
||||
#define SI2Q_MAX_LEN 160
|
||||
#define SI2Q_MIN_LEN 18
|
||||
|
||||
struct osmo_bsc_data;
|
||||
|
||||
struct osmo_bsc_sccp_con;
|
||||
struct gsm_sms_queue;
|
||||
|
||||
/* RRLP mode of operation */
|
||||
enum rrlp_mode {
|
||||
RRLP_MODE_NONE,
|
||||
RRLP_MODE_MS_BASED,
|
||||
RRLP_MODE_MS_PREF,
|
||||
RRLP_MODE_ASS_PREF,
|
||||
};
|
||||
|
||||
/* Channel Request reason */
|
||||
enum gsm_chreq_reason_t {
|
||||
GSM_CHREQ_REASON_EMERG,
|
||||
GSM_CHREQ_REASON_PAG,
|
||||
GSM_CHREQ_REASON_CALL,
|
||||
GSM_CHREQ_REASON_LOCATION_UPD,
|
||||
GSM_CHREQ_REASON_OTHER,
|
||||
GSM_CHREQ_REASON_PDCH,
|
||||
};
|
||||
|
||||
/* lchans 0..3 are SDCCH in combined channel configuration,
|
||||
use 4 as magic number for BCCH hack - see osmo-bts-../oml.c:opstart_compl() */
|
||||
#define CCCH_LCHAN 4
|
||||
|
||||
#define TRX_NR_TS 8
|
||||
#define TS_MAX_LCHAN 8
|
||||
|
||||
#define HARDCODED_ARFCN 123
|
||||
#define HARDCODED_BSIC 0x3f /* NCC = 7 / BCC = 7 */
|
||||
|
||||
/* for multi-drop config */
|
||||
#define HARDCODED_BTS0_TS 1
|
||||
#define HARDCODED_BTS1_TS 6
|
||||
#define HARDCODED_BTS2_TS 11
|
||||
|
||||
#define MAX_VERSION_LENGTH 64
|
||||
|
||||
#define MAX_BTS_FEATURES 128
|
||||
|
||||
enum gsm_hooks {
|
||||
GSM_HOOK_NM_SWLOAD,
|
||||
GSM_HOOK_RR_PAGING,
|
||||
GSM_HOOK_RR_SECURITY,
|
||||
};
|
||||
|
||||
enum gsm_paging_event {
|
||||
GSM_PAGING_SUCCEEDED,
|
||||
GSM_PAGING_EXPIRED,
|
||||
GSM_PAGING_OOM,
|
||||
GSM_PAGING_BUSY,
|
||||
};
|
||||
|
||||
enum bts_gprs_mode {
|
||||
BTS_GPRS_NONE = 0,
|
||||
BTS_GPRS_GPRS = 1,
|
||||
BTS_GPRS_EGPRS = 2,
|
||||
};
|
||||
|
||||
struct gsm_lchan;
|
||||
struct gsm_subscriber;
|
||||
struct gsm_mncc;
|
||||
struct osmo_rtp_socket;
|
||||
struct rtp_socket;
|
||||
struct bsc_api;
|
||||
|
||||
/* Network Management State */
|
||||
struct gsm_nm_state {
|
||||
uint8_t operational;
|
||||
uint8_t administrative;
|
||||
uint8_t availability;
|
||||
};
|
||||
|
||||
struct gsm_abis_mo {
|
||||
uint8_t obj_class;
|
||||
uint8_t procedure_pending;
|
||||
struct abis_om_obj_inst obj_inst;
|
||||
const char *name;
|
||||
struct gsm_nm_state nm_state;
|
||||
struct tlv_parsed *nm_attr;
|
||||
struct gsm_bts *bts;
|
||||
};
|
||||
|
||||
/* Ericsson OM2000 Managed Object */
|
||||
struct abis_om2k_mo {
|
||||
uint8_t class;
|
||||
uint8_t bts;
|
||||
uint8_t assoc_so;
|
||||
uint8_t inst;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct om2k_mo {
|
||||
struct abis_om2k_mo addr;
|
||||
struct osmo_fsm_inst *fsm;
|
||||
};
|
||||
|
||||
#define MAX_A5_KEY_LEN (128/8)
|
||||
#define A38_XOR_MIN_KEY_LEN 12
|
||||
#define A38_XOR_MAX_KEY_LEN 16
|
||||
#define A38_COMP128_KEY_LEN 16
|
||||
#define RSL_ENC_ALG_A5(x) (x+1)
|
||||
#define MAX_EARFCN_LIST 32
|
||||
|
||||
/* is the data link established? who established it? */
|
||||
#define LCHAN_SAPI_UNUSED 0
|
||||
#define LCHAN_SAPI_MS 1
|
||||
#define LCHAN_SAPI_NET 2
|
||||
#define LCHAN_SAPI_REL 3
|
||||
|
||||
/* state of a logical channel */
|
||||
enum gsm_lchan_state {
|
||||
LCHAN_S_NONE, /* channel is not active */
|
||||
LCHAN_S_ACT_REQ, /* channel activation requested */
|
||||
LCHAN_S_ACTIVE, /* channel is active and operational */
|
||||
LCHAN_S_REL_REQ, /* channel release has been requested */
|
||||
LCHAN_S_REL_ERR, /* channel is in an error state */
|
||||
LCHAN_S_BROKEN, /* channel is somehow unusable */
|
||||
LCHAN_S_INACTIVE, /* channel is set inactive */
|
||||
};
|
||||
|
||||
/* BTS ONLY */
|
||||
#define MAX_NUM_UL_MEAS 104
|
||||
#define LC_UL_M_F_L1_VALID (1 << 0)
|
||||
#define LC_UL_M_F_RES_VALID (1 << 1)
|
||||
|
||||
struct bts_ul_meas {
|
||||
/* BER in units of 0.01%: 10.000 == 100% ber, 0 == 0% ber */
|
||||
uint16_t ber10k;
|
||||
/* timing advance offset (in quarter bits) */
|
||||
int16_t ta_offs_qbits;
|
||||
/* C/I ratio in dB */
|
||||
float c_i;
|
||||
/* flags */
|
||||
uint8_t is_sub:1;
|
||||
/* RSSI in dBm * -1 */
|
||||
uint8_t inv_rssi;
|
||||
};
|
||||
|
||||
struct bts_codec_conf {
|
||||
uint8_t hr;
|
||||
uint8_t efr;
|
||||
uint8_t amr;
|
||||
};
|
||||
|
||||
struct amr_mode {
|
||||
uint8_t mode;
|
||||
uint8_t threshold;
|
||||
uint8_t hysteresis;
|
||||
};
|
||||
|
||||
struct amr_multirate_conf {
|
||||
uint8_t gsm48_ie[2];
|
||||
struct amr_mode ms_mode[4];
|
||||
struct amr_mode bts_mode[4];
|
||||
uint8_t num_modes;
|
||||
};
|
||||
/* /BTS ONLY */
|
||||
|
||||
enum lchan_csd_mode {
|
||||
LCHAN_CSD_M_NT,
|
||||
LCHAN_CSD_M_T_1200_75,
|
||||
LCHAN_CSD_M_T_600,
|
||||
LCHAN_CSD_M_T_1200,
|
||||
LCHAN_CSD_M_T_2400,
|
||||
LCHAN_CSD_M_T_9600,
|
||||
LCHAN_CSD_M_T_14400,
|
||||
LCHAN_CSD_M_T_29000,
|
||||
LCHAN_CSD_M_T_32000,
|
||||
};
|
||||
|
||||
/* State of the SAPIs in the lchan */
|
||||
enum lchan_sapi_state {
|
||||
LCHAN_SAPI_S_NONE,
|
||||
LCHAN_SAPI_S_REQ,
|
||||
LCHAN_SAPI_S_ASSIGNED,
|
||||
LCHAN_SAPI_S_REL,
|
||||
LCHAN_SAPI_S_ERROR,
|
||||
};
|
||||
|
||||
struct gsm_lchan {
|
||||
/* The TS that we're part of */
|
||||
struct gsm_bts_trx_ts *ts;
|
||||
/* The logical subslot number in the TS */
|
||||
uint8_t nr;
|
||||
/* The logical channel type */
|
||||
enum gsm_chan_t type;
|
||||
/* RSL channel mode */
|
||||
enum rsl_cmod_spd rsl_cmode;
|
||||
/* If TCH, traffic channel mode */
|
||||
enum gsm48_chan_mode tch_mode;
|
||||
enum lchan_csd_mode csd_mode;
|
||||
/* State */
|
||||
enum gsm_lchan_state state;
|
||||
const char *broken_reason;
|
||||
/* Power levels for MS and BTS */
|
||||
uint8_t bs_power;
|
||||
uint8_t ms_power;
|
||||
/* Encryption information */
|
||||
struct {
|
||||
uint8_t alg_id;
|
||||
uint8_t key_len;
|
||||
uint8_t key[MAX_A5_KEY_LEN];
|
||||
} encr;
|
||||
|
||||
/* AMR bits */
|
||||
uint8_t mr_ms_lv[7];
|
||||
uint8_t mr_bts_lv[7];
|
||||
|
||||
/* Established data link layer services */
|
||||
uint8_t sapis[8];
|
||||
int sacch_deact;
|
||||
|
||||
struct {
|
||||
uint32_t bound_ip;
|
||||
uint32_t connect_ip;
|
||||
uint16_t bound_port;
|
||||
uint16_t connect_port;
|
||||
uint16_t conn_id;
|
||||
uint8_t rtp_payload;
|
||||
uint8_t rtp_payload2;
|
||||
uint8_t speech_mode;
|
||||
#ifdef ROLE_BSC
|
||||
struct rtp_socket *rtp_socket;
|
||||
#else
|
||||
struct osmo_rtp_socket *rtp_socket;
|
||||
#endif
|
||||
} abis_ip;
|
||||
|
||||
uint8_t rqd_ta;
|
||||
|
||||
char *name;
|
||||
|
||||
#ifdef ROLE_BSC
|
||||
struct osmo_timer_list T3101;
|
||||
struct osmo_timer_list T3109;
|
||||
struct osmo_timer_list T3111;
|
||||
struct osmo_timer_list error_timer;
|
||||
struct osmo_timer_list act_timer;
|
||||
struct osmo_timer_list rel_work;
|
||||
uint8_t error_cause;
|
||||
|
||||
/* table of neighbor cell measurements */
|
||||
struct neigh_meas_proc neigh_meas[MAX_NEIGH_MEAS];
|
||||
|
||||
/* cache of last measurement reports on this lchan */
|
||||
struct gsm_meas_rep meas_rep[6];
|
||||
int meas_rep_idx;
|
||||
|
||||
/* GSM Random Access data */
|
||||
struct gsm48_req_ref *rqd_ref;
|
||||
|
||||
struct gsm_subscriber_connection *conn;
|
||||
|
||||
struct {
|
||||
/* channel activation type and handover ref */
|
||||
uint8_t act_type;
|
||||
uint8_t ho_ref;
|
||||
struct gsm48_req_ref *rqd_ref;
|
||||
uint8_t rqd_ta;
|
||||
} dyn;
|
||||
#else
|
||||
/* Number of different GsmL1_Sapi_t used in osmo_bts_sysmo is 23.
|
||||
* Currently we don't share these headers so this is a magic number. */
|
||||
struct llist_head sapi_cmds;
|
||||
uint8_t sapis_dl[23];
|
||||
uint8_t sapis_ul[23];
|
||||
struct lapdm_channel lapdm_ch;
|
||||
struct llist_head dl_tch_queue;
|
||||
struct {
|
||||
/* bitmask of all SI that are present/valid in si_buf */
|
||||
uint32_t valid;
|
||||
uint32_t last;
|
||||
/* buffers where we put the pre-computed SI:
|
||||
SI2Q_MAX_NUM is the max number of SI2quater messages (see 3GPP TS 44.018) */
|
||||
sysinfo_buf_t buf[_MAX_SYSINFO_TYPE][SI2Q_MAX_NUM];
|
||||
} si;
|
||||
struct {
|
||||
uint8_t flags;
|
||||
/* RSL measurment result number, 0 at lchan_act */
|
||||
uint8_t res_nr;
|
||||
/* current Tx power level of the BTS */
|
||||
uint8_t bts_tx_pwr;
|
||||
/* number of measurements stored in array below */
|
||||
uint8_t num_ul_meas;
|
||||
struct bts_ul_meas uplink[MAX_NUM_UL_MEAS];
|
||||
/* last L1 header from the MS */
|
||||
uint8_t l1_info[2];
|
||||
struct gsm_meas_rep_unidir ul_res;
|
||||
} meas;
|
||||
struct {
|
||||
struct amr_multirate_conf amr_mr;
|
||||
struct {
|
||||
struct osmo_fsm_inst *dl_amr_fsm;
|
||||
/* TCH cache */
|
||||
uint8_t cache[20];
|
||||
/* FACCH cache */
|
||||
uint8_t facch[GSM_MACBLOCK_LEN];
|
||||
uint8_t len;
|
||||
uint32_t fn;
|
||||
bool is_update;
|
||||
/* set for each SID frame to detect talkspurt for codecs
|
||||
without explicit ONSET event */
|
||||
bool ul_sid;
|
||||
/* indicates if DTXd was active during DL measurement
|
||||
period */
|
||||
bool dl_active;
|
||||
} dtx;
|
||||
uint8_t last_cmr;
|
||||
uint32_t last_fn;
|
||||
} tch;
|
||||
|
||||
/* 3GPP TS 48.058 § 9.3.37: [0; 255] ok, -1 means invalid*/
|
||||
int16_t ms_t_offs;
|
||||
/* 3GPP TS 45.010 § 1.2 round trip propagation delay (in symbols) or -1 */
|
||||
int16_t p_offs;
|
||||
|
||||
/* BTS-side ciphering state (rx only, bi-directional, ...) */
|
||||
uint8_t ciph_state;
|
||||
uint8_t ciph_ns;
|
||||
uint8_t loopback;
|
||||
struct {
|
||||
uint8_t active;
|
||||
uint8_t ref;
|
||||
/* T3105: PHYS INF retransmission */
|
||||
struct osmo_timer_list t3105;
|
||||
/* counts up to Ny1 */
|
||||
unsigned int phys_info_count;
|
||||
} ho;
|
||||
/* S counter for link loss */
|
||||
int s;
|
||||
/* Kind of the release/activation. E.g. RSL or PCU */
|
||||
int rel_act_kind;
|
||||
/* RTP header Marker bit to indicate beginning of speech after pause */
|
||||
bool rtp_tx_marker;
|
||||
/* power handling */
|
||||
struct {
|
||||
uint8_t current;
|
||||
uint8_t fixed;
|
||||
} ms_power_ctrl;
|
||||
|
||||
struct msgb *pending_rel_ind_msg;
|
||||
#endif
|
||||
};
|
||||
|
||||
enum {
|
||||
TS_F_PDCH_ACTIVE = 0x1000,
|
||||
TS_F_PDCH_ACT_PENDING = 0x2000,
|
||||
TS_F_PDCH_DEACT_PENDING = 0x4000,
|
||||
TS_F_PDCH_PENDING_MASK = 0x6000 /*<
|
||||
TS_F_PDCH_ACT_PENDING | TS_F_PDCH_DEACT_PENDING */
|
||||
} gsm_bts_trx_ts_flags;
|
||||
|
||||
/* One Timeslot in a TRX */
|
||||
struct gsm_bts_trx_ts {
|
||||
struct gsm_bts_trx *trx;
|
||||
/* number of this timeslot at the TRX */
|
||||
uint8_t nr;
|
||||
|
||||
enum gsm_phys_chan_config pchan;
|
||||
|
||||
struct {
|
||||
enum gsm_phys_chan_config pchan_is;
|
||||
enum gsm_phys_chan_config pchan_want;
|
||||
struct msgb *pending_chan_activ;
|
||||
} dyn;
|
||||
|
||||
unsigned int flags;
|
||||
struct gsm_abis_mo mo;
|
||||
struct tlv_parsed nm_attr;
|
||||
uint8_t nm_chan_comb;
|
||||
int tsc; /* -1 == use BTS TSC */
|
||||
|
||||
struct {
|
||||
/* Parameters below are configured by VTY */
|
||||
int enabled;
|
||||
uint8_t maio;
|
||||
uint8_t hsn;
|
||||
struct bitvec arfcns;
|
||||
uint8_t arfcns_data[1024/8];
|
||||
/* This is the pre-computed MA for channel assignments */
|
||||
struct bitvec ma;
|
||||
uint8_t ma_len; /* part of ma_data that is used */
|
||||
uint8_t ma_data[8]; /* 10.5.2.21: max 8 bytes value part */
|
||||
} hopping;
|
||||
|
||||
/* To which E1 subslot are we connected */
|
||||
struct gsm_e1_subslot e1_link;
|
||||
|
||||
union {
|
||||
struct {
|
||||
struct om2k_mo om2k_mo;
|
||||
} rbs2000;
|
||||
};
|
||||
|
||||
struct gsm_lchan lchan[TS_MAX_LCHAN];
|
||||
};
|
||||
|
||||
/* One TRX in a BTS */
|
||||
struct gsm_bts_trx {
|
||||
/* list header in bts->trx_list */
|
||||
struct llist_head list;
|
||||
|
||||
struct gsm_bts *bts;
|
||||
/* number of this TRX in the BTS */
|
||||
uint8_t nr;
|
||||
/* human readable name / description */
|
||||
char *description;
|
||||
/* how do we talk RSL with this TRX? */
|
||||
struct gsm_e1_subslot rsl_e1_link;
|
||||
uint8_t rsl_tei;
|
||||
struct e1inp_sign_link *rsl_link;
|
||||
|
||||
/* Some BTS (specifically Ericsson RBS) have a per-TRX OML Link */
|
||||
struct e1inp_sign_link *oml_link;
|
||||
|
||||
struct gsm_abis_mo mo;
|
||||
struct tlv_parsed nm_attr;
|
||||
struct {
|
||||
struct gsm_abis_mo mo;
|
||||
} bb_transc;
|
||||
|
||||
uint16_t arfcn;
|
||||
int nominal_power; /* in dBm */
|
||||
unsigned int max_power_red; /* in actual dB */
|
||||
|
||||
#ifndef ROLE_BSC
|
||||
struct trx_power_params power_params;
|
||||
int ms_power_control;
|
||||
|
||||
struct {
|
||||
void *l1h;
|
||||
} role_bts;
|
||||
#endif
|
||||
|
||||
union {
|
||||
struct {
|
||||
struct {
|
||||
struct gsm_abis_mo mo;
|
||||
} bbsig;
|
||||
struct {
|
||||
struct gsm_abis_mo mo;
|
||||
} pa;
|
||||
} bs11;
|
||||
struct {
|
||||
unsigned int test_state;
|
||||
uint8_t test_nr;
|
||||
struct rxlev_stats rxlev_stat;
|
||||
} ipaccess;
|
||||
struct {
|
||||
struct {
|
||||
struct om2k_mo om2k_mo;
|
||||
} trxc;
|
||||
struct {
|
||||
struct om2k_mo om2k_mo;
|
||||
} rx;
|
||||
struct {
|
||||
struct om2k_mo om2k_mo;
|
||||
} tx;
|
||||
} rbs2000;
|
||||
};
|
||||
struct gsm_bts_trx_ts ts[TRX_NR_TS];
|
||||
};
|
||||
|
||||
#define GSM_BTS_SI2Q(bts, i) (struct gsm48_system_information_type_2quater *)((bts)->si_buf[SYSINFO_TYPE_2quater][i])
|
||||
#define GSM_BTS_HAS_SI(bts, i) ((bts)->si_valid & (1 << i))
|
||||
#define GSM_BTS_SI(bts, i) (void *)((bts)->si_buf[i][0])
|
||||
#define GSM_LCHAN_SI(lchan, i) (void *)((lchan)->si.buf[i][0])
|
||||
|
||||
enum gsm_bts_type {
|
||||
GSM_BTS_TYPE_UNKNOWN,
|
||||
GSM_BTS_TYPE_BS11,
|
||||
GSM_BTS_TYPE_NANOBTS,
|
||||
GSM_BTS_TYPE_RBS2000,
|
||||
GSM_BTS_TYPE_NOKIA_SITE,
|
||||
GSM_BTS_TYPE_OSMOBTS,
|
||||
_NUM_GSM_BTS_TYPE
|
||||
};
|
||||
|
||||
enum gsm_bts_type_variant {
|
||||
BTS_UNKNOWN,
|
||||
BTS_OSMO_LITECELL15,
|
||||
BTS_OSMO_OCTPHY,
|
||||
BTS_OSMO_SYSMO,
|
||||
BTS_OSMO_TRX,
|
||||
_NUM_BTS_VARIANT
|
||||
};
|
||||
|
||||
/* Used by OML layer for BTS Attribute reporting */
|
||||
enum bts_attribute {
|
||||
BTS_TYPE_VARIANT,
|
||||
BTS_SUB_MODEL,
|
||||
TRX_PHY_VERSION,
|
||||
};
|
||||
|
||||
struct vty;
|
||||
|
||||
struct gsm_bts_model {
|
||||
struct llist_head list;
|
||||
|
||||
enum gsm_bts_type type;
|
||||
enum gsm_bts_type_variant variant;
|
||||
const char *name;
|
||||
|
||||
bool started;
|
||||
int (*start)(struct gsm_network *net);
|
||||
int (*oml_rcvmsg)(struct msgb *msg);
|
||||
|
||||
void (*e1line_bind_ops)(struct e1inp_line *line);
|
||||
|
||||
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;
|
||||
|
||||
/* features of a given BTS model set via gsm_bts_model_register() locally */
|
||||
struct bitvec features;
|
||||
uint8_t _features_data[MAX_BTS_FEATURES/8];
|
||||
};
|
||||
|
||||
/* N. B: always add new features to the end of the list (right before _NUM_BTS_FEAT) to avoid breaking compatibility
|
||||
with BTS compiled against earlier version of this header */
|
||||
enum gsm_bts_features {
|
||||
BTS_FEAT_HSCSD,
|
||||
BTS_FEAT_GPRS,
|
||||
BTS_FEAT_EGPRS,
|
||||
BTS_FEAT_ECSD,
|
||||
BTS_FEAT_HOPPING,
|
||||
BTS_FEAT_MULTI_TSC,
|
||||
BTS_FEAT_OML_ALERTS,
|
||||
BTS_FEAT_AGCH_PCH_PROP,
|
||||
BTS_FEAT_CBCH,
|
||||
_NUM_BTS_FEAT
|
||||
};
|
||||
|
||||
extern const struct value_string gsm_bts_features_descs[];
|
||||
|
||||
/*
|
||||
* This keeps track of the paging status of one BTS. It
|
||||
* includes a number of pending requests, a back pointer
|
||||
* to the gsm_bts, a timer and some more state.
|
||||
*/
|
||||
struct gsm_bts_paging_state {
|
||||
/* pending requests */
|
||||
struct llist_head pending_requests;
|
||||
struct gsm_bts *bts;
|
||||
|
||||
struct osmo_timer_list work_timer;
|
||||
struct osmo_timer_list credit_timer;
|
||||
|
||||
/* free chans needed */
|
||||
int free_chans_need;
|
||||
|
||||
/* load */
|
||||
uint16_t available_slots;
|
||||
};
|
||||
|
||||
struct gsm_envabtse {
|
||||
struct gsm_abis_mo mo;
|
||||
};
|
||||
|
||||
struct gsm_bts_gprs_nsvc {
|
||||
struct gsm_bts *bts;
|
||||
/* data read via VTY config file, to configure the BTS
|
||||
* via OML from BSC */
|
||||
int id;
|
||||
uint16_t nsvci;
|
||||
uint16_t local_port; /* on the BTS */
|
||||
uint16_t remote_port; /* on the SGSN */
|
||||
uint32_t remote_ip; /* on the SGSN */
|
||||
|
||||
struct gsm_abis_mo mo;
|
||||
};
|
||||
|
||||
enum gprs_rlc_par {
|
||||
RLC_T3142,
|
||||
RLC_T3169,
|
||||
RLC_T3191,
|
||||
RLC_T3193,
|
||||
RLC_T3195,
|
||||
RLC_N3101,
|
||||
RLC_N3103,
|
||||
RLC_N3105,
|
||||
CV_COUNTDOWN,
|
||||
T_DL_TBF_EXT, /* ms */
|
||||
T_UL_TBF_EXT, /* ms */
|
||||
_NUM_RLC_PAR
|
||||
};
|
||||
|
||||
enum gprs_cs {
|
||||
GPRS_CS1,
|
||||
GPRS_CS2,
|
||||
GPRS_CS3,
|
||||
GPRS_CS4,
|
||||
GPRS_MCS1,
|
||||
GPRS_MCS2,
|
||||
GPRS_MCS3,
|
||||
GPRS_MCS4,
|
||||
GPRS_MCS5,
|
||||
GPRS_MCS6,
|
||||
GPRS_MCS7,
|
||||
GPRS_MCS8,
|
||||
GPRS_MCS9,
|
||||
_NUM_GRPS_CS
|
||||
};
|
||||
|
||||
struct gprs_rlc_cfg {
|
||||
uint16_t parameter[_NUM_RLC_PAR];
|
||||
struct {
|
||||
uint16_t repeat_time; /* ms */
|
||||
uint8_t repeat_count;
|
||||
} paging;
|
||||
uint32_t cs_mask; /* bitmask of gprs_cs */
|
||||
uint8_t initial_cs;
|
||||
uint8_t initial_mcs;
|
||||
};
|
||||
|
||||
|
||||
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 */
|
||||
};
|
||||
|
||||
enum bts_loc_fix {
|
||||
BTS_LOC_FIX_INVALID = 0,
|
||||
BTS_LOC_FIX_2D = 1,
|
||||
BTS_LOC_FIX_3D = 2,
|
||||
};
|
||||
|
||||
extern const struct value_string bts_loc_fix_names[];
|
||||
|
||||
struct bts_location {
|
||||
struct llist_head list;
|
||||
time_t tstamp;
|
||||
enum bts_loc_fix valid;
|
||||
double lat;
|
||||
double lon;
|
||||
double height;
|
||||
};
|
||||
|
||||
/* One BTS */
|
||||
struct gsm_bts {
|
||||
/* list header in net->bts_list */
|
||||
struct llist_head list;
|
||||
|
||||
/* Geographical location of the BTS */
|
||||
struct llist_head loc_list;
|
||||
|
||||
/* number of ths BTS in network */
|
||||
uint8_t nr;
|
||||
/* human readable name / description */
|
||||
char *description;
|
||||
/* Cell Identity */
|
||||
uint16_t cell_identity;
|
||||
/* location area code of this BTS */
|
||||
uint16_t location_area_code;
|
||||
/* Base Station Identification Code (BSIC), lower 3 bits is BCC,
|
||||
* which is used as TSC for the CCCH */
|
||||
uint8_t bsic;
|
||||
/* type of BTS */
|
||||
enum gsm_bts_type type;
|
||||
enum gsm_bts_type_variant variant;
|
||||
struct gsm_bts_model *model;
|
||||
enum gsm_band band;
|
||||
char version[MAX_VERSION_LENGTH];
|
||||
char sub_model[MAX_VERSION_LENGTH];
|
||||
|
||||
/* features of a given BTS set/reported via OML */
|
||||
struct bitvec features;
|
||||
uint8_t _features_data[MAX_BTS_FEATURES/8];
|
||||
|
||||
/* Connected PCU version (if any) */
|
||||
char pcu_version[MAX_VERSION_LENGTH];
|
||||
|
||||
/* maximum Tx power that the MS is permitted to use in this cell */
|
||||
int ms_max_power;
|
||||
|
||||
/* how do we talk OML with this TRX? */
|
||||
struct gsm_e1_subslot oml_e1_link;
|
||||
uint8_t oml_tei;
|
||||
struct e1inp_sign_link *oml_link;
|
||||
/* when OML link was established */
|
||||
time_t uptime;
|
||||
|
||||
/* Abis network management O&M handle */
|
||||
struct abis_nm_h *nmh;
|
||||
|
||||
struct gsm_abis_mo mo;
|
||||
|
||||
/* number of this BTS on given E1 link */
|
||||
uint8_t bts_nr;
|
||||
|
||||
/* DTX features of this BTS */
|
||||
enum gsm48_dtx_mode dtxu;
|
||||
bool dtxd;
|
||||
|
||||
/* paging state and control */
|
||||
struct gsm_bts_paging_state paging;
|
||||
|
||||
/* CCCH is on C0 */
|
||||
struct gsm_bts_trx *c0;
|
||||
|
||||
struct {
|
||||
struct gsm_abis_mo mo;
|
||||
} site_mgr;
|
||||
|
||||
/* bitmask of all SI that are present/valid in si_buf */
|
||||
uint32_t si_valid;
|
||||
/* 3GPP TS 44.018 Table 10.5.2.33b.1 INDEX and COUNT for SI2quater */
|
||||
uint8_t si2q_index; /* distinguish individual SI2quater messages */
|
||||
uint8_t si2q_count; /* si2q_index for the last (highest indexed) individual SI2quater message */
|
||||
/* buffers where we put the pre-computed SI */
|
||||
sysinfo_buf_t si_buf[_MAX_SYSINFO_TYPE][SI2Q_MAX_NUM];
|
||||
/* offsets used while generating SI2quater */
|
||||
size_t e_offset;
|
||||
size_t u_offset;
|
||||
|
||||
/* ip.accesss Unit ID's have Site/BTS/TRX layout */
|
||||
union {
|
||||
struct {
|
||||
uint16_t site_id;
|
||||
uint16_t bts_id;
|
||||
uint32_t flags;
|
||||
uint32_t rsl_ip;
|
||||
} ip_access;
|
||||
struct {
|
||||
struct {
|
||||
struct gsm_abis_mo mo;
|
||||
} cclk;
|
||||
struct {
|
||||
struct gsm_abis_mo mo;
|
||||
} rack;
|
||||
struct gsm_envabtse envabtse[4];
|
||||
} bs11;
|
||||
struct {
|
||||
struct {
|
||||
struct om2k_mo om2k_mo;
|
||||
struct gsm_abis_mo mo;
|
||||
struct llist_head conn_groups;
|
||||
} cf;
|
||||
struct {
|
||||
struct om2k_mo om2k_mo;
|
||||
struct gsm_abis_mo mo;
|
||||
struct llist_head conn_groups;
|
||||
} is;
|
||||
struct {
|
||||
struct om2k_mo om2k_mo;
|
||||
struct gsm_abis_mo mo;
|
||||
struct llist_head conn_groups;
|
||||
} con;
|
||||
struct {
|
||||
struct om2k_mo om2k_mo;
|
||||
struct gsm_abis_mo mo;
|
||||
} dp;
|
||||
struct {
|
||||
struct om2k_mo om2k_mo;
|
||||
struct gsm_abis_mo mo;
|
||||
} tf;
|
||||
uint32_t use_superchannel:1;
|
||||
} rbs2000;
|
||||
struct {
|
||||
uint8_t bts_type;
|
||||
unsigned int configured:1,
|
||||
skip_reset:1,
|
||||
no_loc_rel_cnf:1,
|
||||
bts_reset_timer_cnf,
|
||||
did_reset:1,
|
||||
wait_reset:1;
|
||||
struct osmo_timer_list reset_timer;
|
||||
} nokia;
|
||||
};
|
||||
|
||||
/* Not entirely sure how ip.access specific this is */
|
||||
struct {
|
||||
uint8_t supports_egprs_11bit_rach;
|
||||
enum bts_gprs_mode mode;
|
||||
struct {
|
||||
struct gsm_abis_mo mo;
|
||||
uint16_t nsei;
|
||||
uint8_t timer[7];
|
||||
} nse;
|
||||
struct {
|
||||
struct gsm_abis_mo mo;
|
||||
uint16_t bvci;
|
||||
uint8_t timer[11];
|
||||
struct gprs_rlc_cfg rlc_cfg;
|
||||
} cell;
|
||||
struct gsm_bts_gprs_nsvc nsvc[2];
|
||||
uint8_t rac;
|
||||
uint8_t net_ctrl_ord;
|
||||
bool ctrl_ack_type_use_block;
|
||||
} gprs;
|
||||
|
||||
/* RACH NM values */
|
||||
int rach_b_thresh;
|
||||
int rach_ldavg_slots;
|
||||
|
||||
/* transceivers */
|
||||
int num_trx;
|
||||
struct llist_head trx_list;
|
||||
|
||||
/* SI related items */
|
||||
int force_combined_si;
|
||||
int bcch_change_mark;
|
||||
|
||||
#ifdef ROLE_BSC
|
||||
/* Abis NM queue */
|
||||
struct llist_head abis_queue;
|
||||
int abis_nm_pend;
|
||||
|
||||
struct gsm_network *network;
|
||||
|
||||
/* should the channel allocator allocate channels from high TRX to TRX0,
|
||||
* rather than starting from TRX0 and go upwards? */
|
||||
int chan_alloc_reverse;
|
||||
|
||||
enum neigh_list_manual_mode neigh_list_manual_mode;
|
||||
/* parameters from which we build SYSTEM INFORMATION */
|
||||
struct {
|
||||
struct gsm48_rach_control rach_control;
|
||||
uint8_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 osmo_earfcn_si2q si2quater_neigh_list;
|
||||
size_t uarfcn_length; /* index for uarfcn and scramble lists */
|
||||
struct {
|
||||
/* bitmask large enough for all possible ARFCN's */
|
||||
uint8_t neigh_list[1024/8];
|
||||
uint8_t cell_alloc[1024/8];
|
||||
/* If the user wants a different neighbor list in SI5 than in SI2 */
|
||||
uint8_t si5_neigh_list[1024/8];
|
||||
uint8_t meas_bw_list[MAX_EARFCN_LIST];
|
||||
uint16_t earfcn_list[MAX_EARFCN_LIST];
|
||||
uint16_t uarfcn_list[MAX_EARFCN_LIST];
|
||||
uint16_t scramble_list[MAX_EARFCN_LIST];
|
||||
} data;
|
||||
} si_common;
|
||||
bool early_classmark_allowed;
|
||||
/* for testing only: Have an infinitely long radio link timeout */
|
||||
bool infinite_radio_link_timeout;
|
||||
|
||||
/* do we use static (user-defined) system information messages? (bitmask) */
|
||||
uint32_t si_mode_static;
|
||||
|
||||
/* exclude the BTS from the global RF Lock handling */
|
||||
int excl_from_rf_lock;
|
||||
|
||||
/* supported codecs beside FR */
|
||||
struct bts_codec_conf codec;
|
||||
|
||||
/* BTS dependencies bit field */
|
||||
uint32_t depends_on[256/(8*4)];
|
||||
|
||||
/* full and half rate multirate config */
|
||||
struct amr_multirate_conf mr_full;
|
||||
struct amr_multirate_conf mr_half;
|
||||
|
||||
/* PCU socket state */
|
||||
char *pcu_sock_path;
|
||||
struct pcu_sock_state *pcu_state;
|
||||
|
||||
#endif /* ROLE_BSC */
|
||||
void *role;
|
||||
};
|
||||
|
||||
|
||||
struct gsm_bts *gsm_bts_alloc(void *talloc_ctx, uint8_t bts_num);
|
||||
struct gsm_bts *gsm_bts_num(struct gsm_network *net, int num);
|
||||
|
||||
struct gsm_bts_trx *gsm_bts_trx_alloc(struct gsm_bts *bts);
|
||||
struct gsm_bts_trx *gsm_bts_trx_num(const struct gsm_bts *bts, int num);
|
||||
|
||||
enum gsm_bts_type str2btstype(const char *arg);
|
||||
const char *btstype2str(enum gsm_bts_type type);
|
||||
|
||||
enum bts_attribute str2btsattr(const char *s);
|
||||
const char *btsatttr2str(enum bts_attribute v);
|
||||
|
||||
enum gsm_bts_type_variant str2btsvariant(const char *arg);
|
||||
const char *btsvariant2str(enum gsm_bts_type_variant v);
|
||||
|
||||
extern const struct value_string gsm_chreq_descs[];
|
||||
const struct value_string gsm_pchant_names[13];
|
||||
const struct value_string gsm_pchant_descs[13];
|
||||
const char *gsm_pchan_name(enum gsm_phys_chan_config c);
|
||||
enum gsm_phys_chan_config gsm_pchan_parse(const char *name);
|
||||
const char *gsm_lchant_name(enum gsm_chan_t c);
|
||||
const char *gsm_chreq_name(enum gsm_chreq_reason_t c);
|
||||
char *gsm_trx_name(const struct gsm_bts_trx *trx);
|
||||
char *gsm_ts_name(const struct gsm_bts_trx_ts *ts);
|
||||
char *gsm_ts_and_pchan_name(const struct gsm_bts_trx_ts *ts);
|
||||
char *gsm_lchan_name_compute(const struct gsm_lchan *lchan);
|
||||
const char *gsm_lchans_name(enum gsm_lchan_state s);
|
||||
|
||||
static inline char *gsm_lchan_name(const struct gsm_lchan *lchan)
|
||||
{
|
||||
return lchan->name;
|
||||
}
|
||||
|
||||
static inline int gsm_bts_set_feature(struct gsm_bts *bts, enum gsm_bts_features feat)
|
||||
{
|
||||
OSMO_ASSERT(_NUM_BTS_FEAT < MAX_BTS_FEATURES);
|
||||
return bitvec_set_bit_pos(&bts->features, feat, 1);
|
||||
}
|
||||
|
||||
static inline bool gsm_bts_has_feature(const struct gsm_bts *bts, enum gsm_bts_features feat)
|
||||
{
|
||||
OSMO_ASSERT(_NUM_BTS_FEAT < MAX_BTS_FEATURES);
|
||||
return bitvec_get_bit_pos(&bts->features, feat);
|
||||
}
|
||||
|
||||
void gsm_abis_mo_reset(struct gsm_abis_mo *mo);
|
||||
|
||||
struct gsm_abis_mo *
|
||||
gsm_objclass2mo(struct gsm_bts *bts, uint8_t obj_class,
|
||||
const struct abis_om_obj_inst *obj_inst);
|
||||
|
||||
struct gsm_nm_state *
|
||||
gsm_objclass2nmstate(struct gsm_bts *bts, uint8_t obj_class,
|
||||
const struct abis_om_obj_inst *obj_inst);
|
||||
void *
|
||||
gsm_objclass2obj(struct gsm_bts *bts, uint8_t obj_class,
|
||||
const struct abis_om_obj_inst *obj_inst);
|
||||
|
||||
/* reset the state of all MO in the BTS */
|
||||
void gsm_bts_mo_reset(struct gsm_bts *bts);
|
||||
|
||||
uint8_t gsm_pchan2chan_nr(enum gsm_phys_chan_config pchan,
|
||||
uint8_t ts_nr, uint8_t lchan_nr);
|
||||
uint8_t gsm_lchan2chan_nr(const struct gsm_lchan *lchan);
|
||||
uint8_t gsm_lchan_as_pchan2chan_nr(const struct gsm_lchan *lchan,
|
||||
enum gsm_phys_chan_config as_pchan);
|
||||
|
||||
/* return the gsm_lchan for the CBCH (if it exists at all) */
|
||||
struct gsm_lchan *gsm_bts_get_cbch(struct gsm_bts *bts);
|
||||
|
||||
/*
|
||||
* help with parsing regexps
|
||||
*/
|
||||
int gsm_parse_reg(void *ctx, regex_t *reg, char **str,
|
||||
int argc, const char **argv) __attribute__ ((warn_unused_result));
|
||||
|
||||
static inline uint8_t gsm_ts_tsc(const struct gsm_bts_trx_ts *ts)
|
||||
{
|
||||
if (ts->tsc != -1)
|
||||
return ts->tsc;
|
||||
else
|
||||
return ts->trx->bts->bsic & 7;
|
||||
}
|
||||
|
||||
struct gsm_lchan *rsl_lchan_lookup(struct gsm_bts_trx *trx, uint8_t chan_nr,
|
||||
int *rc);
|
||||
|
||||
enum gsm_phys_chan_config ts_pchan(struct gsm_bts_trx_ts *ts);
|
||||
uint8_t ts_subslots(struct gsm_bts_trx_ts *ts);
|
||||
bool ts_is_tch(struct gsm_bts_trx_ts *ts);
|
||||
|
||||
#endif
|
||||
96
include/osmo-bts/l1sap.h
Normal file
96
include/osmo-bts/l1sap.h
Normal file
@@ -0,0 +1,96 @@
|
||||
#ifndef L1SAP_H
|
||||
#define L1SAP_H
|
||||
|
||||
#include <osmocom/gsm/protocol/gsm_04_08.h>
|
||||
|
||||
/* lchan link ID */
|
||||
#define LID_SACCH 0x40
|
||||
#define LID_DEDIC 0x00
|
||||
|
||||
/* timeslot and subslot from chan_nr */
|
||||
#define L1SAP_CHAN2TS(chan_nr) (chan_nr & 7)
|
||||
#define L1SAP_CHAN2SS_TCHH(chan_nr) ((chan_nr >> 3) & 1)
|
||||
#define L1SAP_CHAN2SS_SDCCH4(chan_nr) ((chan_nr >> 3) & 3)
|
||||
#define L1SAP_CHAN2SS_SDCCH8(chan_nr) ((chan_nr >> 3) & 7)
|
||||
|
||||
/* logical channel from chan_nr + link_id */
|
||||
#define L1SAP_IS_LINK_SACCH(link_id) ((link_id & 0xC0) == LID_SACCH)
|
||||
#define L1SAP_IS_CHAN_TCHF(chan_nr) ((chan_nr & 0xf8) == 0x08)
|
||||
#define L1SAP_IS_CHAN_TCHH(chan_nr) ((chan_nr & 0xf0) == 0x10)
|
||||
#define L1SAP_IS_CHAN_SDCCH4(chan_nr) ((chan_nr & 0xe0) == 0x20)
|
||||
#define L1SAP_IS_CHAN_SDCCH8(chan_nr) ((chan_nr & 0xc0) == 0x40)
|
||||
#define L1SAP_IS_CHAN_BCCH(chan_nr) ((chan_nr & 0xf8) == 0x80)
|
||||
#define L1SAP_IS_CHAN_RACH(chan_nr) ((chan_nr & 0xf8) == 0x88)
|
||||
#define L1SAP_IS_CHAN_AGCH_PCH(chan_nr) ((chan_nr & 0xf8) == 0x90)
|
||||
#define L1SAP_IS_CHAN_PDCH(chan_nr) ((chan_nr & 0xf8) == 0xc0)
|
||||
|
||||
/* rach type from ra */
|
||||
#define L1SAP_IS_PACKET_RACH(ra) ((ra & 0xf0) == 0x70 && (ra & 0x0f) != 0x0f)
|
||||
|
||||
/* CCCH block from frame number */
|
||||
#define L1SAP_FN2CCCHBLOCK(fn) ((fn % 51) / 5 - 1)
|
||||
|
||||
/* PTCH layout from frame number */
|
||||
#define L1SAP_FN2MACBLOCK(fn) ((fn % 52) / 4)
|
||||
#define L1SAP_FN2PTCCHBLOCK(fn) ((fn / 104) & 3)
|
||||
|
||||
/* Calculate PTCCH occurrence, See also 3GPP TS 05.02, Clause 7, Table 6 of 9 */
|
||||
#define L1SAP_IS_PTCCH(fn) (((fn % 52) == 12) || ((fn % 52) == 38))
|
||||
|
||||
|
||||
static const uint8_t fill_frame[GSM_MACBLOCK_LEN] = {
|
||||
0x03, 0x03, 0x01, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B,
|
||||
0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B,
|
||||
0x2B, 0x2B, 0x2B
|
||||
};
|
||||
|
||||
/* subslot from any chan_nr */
|
||||
static inline uint8_t l1sap_chan2ss(uint8_t chan_nr)
|
||||
{
|
||||
if (L1SAP_IS_CHAN_SDCCH8(chan_nr))
|
||||
return L1SAP_CHAN2SS_SDCCH8(chan_nr);
|
||||
if (L1SAP_IS_CHAN_SDCCH4(chan_nr))
|
||||
return L1SAP_CHAN2SS_SDCCH4(chan_nr);
|
||||
if (L1SAP_IS_CHAN_TCHH(chan_nr))
|
||||
return L1SAP_CHAN2SS_TCHH(chan_nr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct gsm_lchan *get_lchan_by_chan_nr(struct gsm_bts_trx *trx,
|
||||
unsigned int chan_nr);
|
||||
|
||||
/* allocate a msgb containing a osmo_phsap_prim + optional l2 data */
|
||||
struct msgb *l1sap_msgb_alloc(unsigned int l2_len);
|
||||
|
||||
/* any L1 prim received from bts model */
|
||||
int l1sap_up(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap);
|
||||
|
||||
/* pcu (socket interface) sends us a data request primitive */
|
||||
int l1sap_pdch_req(struct gsm_bts_trx_ts *ts, int is_ptcch, uint32_t fn,
|
||||
uint16_t arfcn, uint8_t block_nr, uint8_t *data, uint8_t len);
|
||||
|
||||
/* call-back function for incoming RTP */
|
||||
void l1sap_rtp_rx_cb(struct osmo_rtp_socket *rs, const uint8_t *rtp_pl,
|
||||
unsigned int rtp_pl_len, uint16_t seq_number,
|
||||
uint32_t timestamp, bool marker);
|
||||
|
||||
/* channel control */
|
||||
int l1sap_chan_act(struct gsm_bts_trx *trx, uint8_t chan_nr, struct tlv_parsed *tp);
|
||||
int l1sap_chan_rel(struct gsm_bts_trx *trx, uint8_t chan_nr);
|
||||
int l1sap_chan_deact_sacch(struct gsm_bts_trx *trx, uint8_t chan_nr);
|
||||
int l1sap_chan_modify(struct gsm_bts_trx *trx, uint8_t chan_nr);
|
||||
|
||||
extern const struct value_string gsmtap_sapi_names[];
|
||||
extern struct gsmtap_inst *gsmtap;
|
||||
extern uint32_t gsmtap_sapi_mask;
|
||||
extern uint8_t gsmtap_sapi_acch;
|
||||
|
||||
int add_l1sap_header(struct gsm_bts_trx *trx, struct msgb *rmsg,
|
||||
struct gsm_lchan *lchan, uint8_t chan_nr, uint32_t fn,
|
||||
uint16_t ber10k, int16_t lqual_cb);
|
||||
|
||||
#define msgb_l1sap_prim(msg) ((struct osmo_phsap_prim *)(msg)->l1h)
|
||||
|
||||
int bts_check_for_first_ciphrd(struct gsm_lchan *lchan,
|
||||
uint8_t *data, int len);
|
||||
#endif /* L1SAP_H */
|
||||
@@ -16,6 +16,8 @@ enum {
|
||||
DDSP,
|
||||
DPCU,
|
||||
DHO,
|
||||
DTRX,
|
||||
DLOOP,
|
||||
DABIS,
|
||||
DRTP,
|
||||
DSUM,
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
#ifndef OSMO_BTS_MEAS_H
|
||||
#define OSMO_BTS_MEAS_H
|
||||
|
||||
#define MEAS_MAX_TIMING_ADVANCE 63
|
||||
#define MEAS_MIN_TIMING_ADVANCE 0
|
||||
|
||||
int lchan_new_ul_meas(struct gsm_lchan *lchan, struct bts_ul_meas *ulm);
|
||||
|
||||
int trx_meas_check_compute(struct gsm_bts_trx *trx, uint32_t fn);
|
||||
|
||||
/* build the 3 byte RSL uplinke measurement IE content */
|
||||
int lchan_build_rsl_ul_meas(struct gsm_lchan *, uint8_t *buf);
|
||||
int lchan_meas_check_compute(struct gsm_lchan *lchan, uint32_t fn);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -4,8 +4,24 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <osmo-bts/gsm_data.h>
|
||||
#include <osmo-bts/dtx_dl_amr_fsm.h>
|
||||
|
||||
#include <osmocom/codec/codec.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
struct msgb;
|
||||
|
||||
/* Access 1st part of msgb control buffer */
|
||||
#define rtpmsg_marker_bit(x) ((x)->cb[0])
|
||||
|
||||
/* Access 2nd part of msgb control buffer */
|
||||
#define rtpmsg_seq(x) ((x)->cb[1])
|
||||
|
||||
/* Access 3rd part of msgb control buffer */
|
||||
#define rtpmsg_ts(x) ((x)->cb[2])
|
||||
|
||||
/**
|
||||
* Classification of OML message. ETSI for plain GSM 12.21
|
||||
* messages and IPA/Osmo for manufacturer messages.
|
||||
@@ -16,5 +32,17 @@ enum {
|
||||
OML_MSG_TYPE_OSMO,
|
||||
};
|
||||
|
||||
void lchan_set_marker(bool t, struct gsm_lchan *lchan);
|
||||
bool dtx_dl_amr_enabled(const struct gsm_lchan *lchan);
|
||||
void dtx_dispatch(struct gsm_lchan *lchan, enum dtx_dl_amr_fsm_events e);
|
||||
bool dtx_recursion(const struct gsm_lchan *lchan);
|
||||
void dtx_int_signal(struct gsm_lchan *lchan);
|
||||
bool dtx_is_first_p1(const struct gsm_lchan *lchan);
|
||||
void dtx_cache_payload(struct gsm_lchan *lchan, const uint8_t *l1_payload,
|
||||
size_t length, uint32_t fn, int update);
|
||||
int dtx_dl_amr_fsm_step(struct gsm_lchan *lchan, const uint8_t *rtp_pl,
|
||||
size_t rtp_pl_len, uint32_t fn, uint8_t *l1_payload,
|
||||
bool marker, uint8_t *len, uint8_t *ft_out);
|
||||
uint8_t repeat_last_sid(struct gsm_lchan *lchan, uint8_t *dst, uint32_t fn);
|
||||
int msg_verify_ipa_structure(struct msgb *msg);
|
||||
int msg_verify_oml_structure(struct msgb *msg);
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
#ifndef _OML_H
|
||||
#define _OML_H
|
||||
|
||||
#include <osmocom/gsm/protocol/gsm_12_21.h>
|
||||
|
||||
struct gsm_bts;
|
||||
struct gsm_abis_mo;
|
||||
struct msgb;
|
||||
struct gsm_lchan;
|
||||
|
||||
|
||||
int oml_init(void);
|
||||
int oml_init(struct gsm_abis_mo *mo);
|
||||
int down_oml(struct gsm_bts *bts, struct msgb *msg);
|
||||
|
||||
struct msgb *oml_msgb_alloc(void);
|
||||
@@ -37,4 +40,11 @@ int oml_fom_ack_nack(struct msgb *old_msg, uint8_t cause);
|
||||
int oml_mo_fom_ack_nack(struct gsm_abis_mo *mo, uint8_t orig_msg_type,
|
||||
uint8_t cause);
|
||||
|
||||
/* Configure LAPDm T200 timers for this lchan according to OML */
|
||||
int oml_set_lchan_t200(struct gsm_lchan *lchan);
|
||||
extern const unsigned int oml_default_t200_ms[7];
|
||||
|
||||
/* Transmit failure event report */
|
||||
void oml_fail_rep(uint16_t cause_value, const char *fmt, ...);
|
||||
|
||||
#endif // _OML_H */
|
||||
|
||||
@@ -1,18 +1,26 @@
|
||||
#ifndef _PCU_IF_H
|
||||
#define _PCU_IF_H
|
||||
|
||||
#define PCU_SOCK_DEFAULT "/tmp/pcu_bts"
|
||||
|
||||
extern int pcu_direct;
|
||||
|
||||
int pcu_tx_info_ind(void);
|
||||
int pcu_tx_si13(const struct gsm_bts *bts, bool enable);
|
||||
int pcu_tx_rts_req(struct gsm_bts_trx_ts *ts, uint8_t is_ptcch, uint32_t fn,
|
||||
uint16_t arfcn, uint8_t block_nr);
|
||||
int pcu_tx_data_ind(struct gsm_bts_trx_ts *ts, uint8_t is_ptcch, uint32_t fn,
|
||||
uint16_t arfcn, uint8_t block_nr, uint8_t *data, uint8_t len,
|
||||
int8_t rssi);
|
||||
int pcu_tx_rach_ind(struct gsm_bts *bts, int16_t qta, uint8_t ra, uint32_t fn);
|
||||
int8_t rssi, uint16_t ber10k, int16_t bto, int16_t lqual);
|
||||
int pcu_tx_rach_ind(struct gsm_bts *bts, int16_t qta, uint16_t ra, uint32_t fn,
|
||||
uint8_t is_11bit, enum ph_burst_type burst_type);
|
||||
int pcu_tx_time_ind(uint32_t fn);
|
||||
int pcu_tx_pag_req(const uint8_t *identity_lv, uint8_t chan_needed);
|
||||
int pcu_tx_pch_data_cnf(uint32_t fn, uint8_t *data, uint8_t len);
|
||||
|
||||
int pcu_sock_init(void);
|
||||
int pcu_sock_init(const char *path);
|
||||
void pcu_sock_exit(void);
|
||||
|
||||
bool pcu_connected(void);
|
||||
|
||||
#endif /* _PCU_IF_H */
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
#ifndef _PCUIF_PROTO_H
|
||||
#define _PCUIF_PROTO_H
|
||||
|
||||
#define PCU_IF_VERSION 0x05
|
||||
#include <osmocom/gsm/l1sap.h>
|
||||
|
||||
#define PCU_IF_VERSION 0x07
|
||||
#define TXT_MAX_LEN 128
|
||||
|
||||
/* msg_type */
|
||||
#define PCU_IF_MSG_DATA_REQ 0x00 /* send data to given channel */
|
||||
@@ -13,6 +16,7 @@
|
||||
#define PCU_IF_MSG_ACT_REQ 0x40 /* activate/deactivate PDCH */
|
||||
#define PCU_IF_MSG_TIME_IND 0x52 /* GSM time indication */
|
||||
#define PCU_IF_MSG_PAG_REQ 0x60 /* paging request */
|
||||
#define PCU_IF_MSG_TXT_IND 0x70 /* Text indication for BTS */
|
||||
|
||||
/* sapi */
|
||||
#define PCU_IF_SAPI_RACH 0x01 /* channel request on CCCH */
|
||||
@@ -40,6 +44,16 @@
|
||||
#define PCU_IF_FLAG_MCS8 (1 << 27)
|
||||
#define PCU_IF_FLAG_MCS9 (1 << 28)
|
||||
|
||||
enum gsm_pcu_if_text_type {
|
||||
PCU_VERSION,
|
||||
PCU_OML_ALERT,
|
||||
};
|
||||
|
||||
struct gsm_pcu_if_txt_ind {
|
||||
uint8_t type; /* gsm_pcu_if_text_type */
|
||||
char text[TXT_MAX_LEN]; /* Text to be transmitted to BTS */
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct gsm_pcu_if_data {
|
||||
uint8_t sapi;
|
||||
uint8_t len;
|
||||
@@ -50,6 +64,9 @@ struct gsm_pcu_if_data {
|
||||
uint8_t ts_nr;
|
||||
uint8_t block_nr;
|
||||
int8_t rssi;
|
||||
uint16_t ber10k; /*!< \brief BER in units of 0.01% */
|
||||
int16_t ta_offs_qbits; /* !< \brief Burst TA Offset in quarter bits */
|
||||
int16_t lqual_cb; /* !< \brief Link quality in centiBel */
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct gsm_pcu_if_rts_req {
|
||||
@@ -64,10 +81,12 @@ struct gsm_pcu_if_rts_req {
|
||||
|
||||
struct gsm_pcu_if_rach_ind {
|
||||
uint8_t sapi;
|
||||
uint8_t ra;
|
||||
uint16_t ra;
|
||||
int16_t qta;
|
||||
uint32_t fn;
|
||||
uint16_t arfcn;
|
||||
uint8_t is_11bit;
|
||||
uint8_t burst_type;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct gsm_pcu_if_info_trx {
|
||||
@@ -143,6 +162,7 @@ struct gsm_pcu_if {
|
||||
struct gsm_pcu_if_data data_ind;
|
||||
struct gsm_pcu_if_rts_req rts_req;
|
||||
struct gsm_pcu_if_rach_ind rach_ind;
|
||||
struct gsm_pcu_if_txt_ind txt_ind;
|
||||
struct gsm_pcu_if_info_ind info_ind;
|
||||
struct gsm_pcu_if_act_req act_req;
|
||||
struct gsm_pcu_if_time_ind time_ind;
|
||||
|
||||
160
include/osmo-bts/phy_link.h
Normal file
160
include/osmo-bts/phy_link.h
Normal file
@@ -0,0 +1,160 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <osmocom/core/linuxlist.h>
|
||||
|
||||
#include <osmo-bts/scheduler.h>
|
||||
|
||||
#include <linux/if_packet.h>
|
||||
#include "btsconfig.h"
|
||||
|
||||
struct gsm_bts_trx;
|
||||
struct virt_um_inst;
|
||||
|
||||
enum phy_link_type {
|
||||
PHY_LINK_T_NONE,
|
||||
PHY_LINK_T_SYSMOBTS,
|
||||
PHY_LINK_T_OSMOTRX,
|
||||
PHY_LINK_T_VIRTUAL,
|
||||
};
|
||||
|
||||
enum phy_link_state {
|
||||
PHY_LINK_SHUTDOWN,
|
||||
PHY_LINK_CONNECTING,
|
||||
PHY_LINK_CONNECTED,
|
||||
};
|
||||
|
||||
/* A PHY link represents the connection to a given PHYsical layer
|
||||
* implementation. That PHY link contains 1...N PHY instances, one for
|
||||
* each TRX */
|
||||
struct phy_link {
|
||||
struct llist_head list;
|
||||
int num;
|
||||
enum phy_link_type type;
|
||||
enum phy_link_state state;
|
||||
struct llist_head instances;
|
||||
char *description;
|
||||
union {
|
||||
struct {
|
||||
} sysmobts;
|
||||
struct {
|
||||
char *local_ip;
|
||||
char *remote_ip;
|
||||
uint16_t base_port_local;
|
||||
uint16_t base_port_remote;
|
||||
struct osmo_fd trx_ofd_clk;
|
||||
bool trx_ta_loop;
|
||||
bool trx_ms_power_loop;
|
||||
int8_t trx_target_rssi;
|
||||
uint32_t clock_advance;
|
||||
uint32_t rts_advance;
|
||||
bool use_legacy_setbsic;
|
||||
} osmotrx;
|
||||
struct {
|
||||
char *mcast_dev; /* Network device for multicast */
|
||||
char *bts_mcast_group; /* BTS are listening to this group */
|
||||
uint16_t bts_mcast_port;
|
||||
char *ms_mcast_group; /* MS are listening to this group */
|
||||
uint16_t ms_mcast_port;
|
||||
struct virt_um_inst *virt_um;
|
||||
} virt;
|
||||
struct {
|
||||
/* MAC address of the PHY */
|
||||
struct sockaddr_ll phy_addr;
|
||||
/* Network device name */
|
||||
char *netdev_name;
|
||||
|
||||
/* configuration */
|
||||
uint32_t rf_port_index;
|
||||
#if OCTPHY_USE_ANTENNA_ID == 1
|
||||
uint32_t rx_ant_id;
|
||||
uint32_t tx_ant_id;
|
||||
#endif
|
||||
uint32_t rx_gain_db;
|
||||
bool tx_atten_flag;
|
||||
uint32_t tx_atten_db;
|
||||
#if OCTPHY_MULTI_TRX == 1
|
||||
/* arfcn used by TRX with id 0 */
|
||||
uint16_t center_arfcn;
|
||||
#endif
|
||||
|
||||
struct octphy_hdl *hdl;
|
||||
} octphy;
|
||||
} u;
|
||||
};
|
||||
|
||||
struct phy_instance {
|
||||
/* liked inside phy_link.linstances */
|
||||
struct llist_head list;
|
||||
int num;
|
||||
char *description;
|
||||
char version[MAX_VERSION_LENGTH];
|
||||
/* pointer to the PHY link to which we belong */
|
||||
struct phy_link *phy_link;
|
||||
|
||||
/* back-pointer to the TRX to which we're associated */
|
||||
struct gsm_bts_trx *trx;
|
||||
|
||||
union {
|
||||
struct {
|
||||
/* configuration */
|
||||
uint8_t clk_use_eeprom;
|
||||
uint32_t dsp_trace_f;
|
||||
int clk_cal;
|
||||
uint8_t clk_src;
|
||||
char *calib_path;
|
||||
|
||||
struct femtol1_hdl *hdl;
|
||||
} sysmobts;
|
||||
struct {
|
||||
struct trx_l1h *hdl;
|
||||
bool sw_act_reported;
|
||||
} osmotrx;
|
||||
struct {
|
||||
struct l1sched_trx sched;
|
||||
} virt;
|
||||
struct {
|
||||
/* logical transceiver number within one PHY */
|
||||
uint32_t trx_id;
|
||||
/* trx lock state variable */
|
||||
int trx_locked;
|
||||
} octphy;
|
||||
struct {
|
||||
/* configuration */
|
||||
uint32_t dsp_trace_f;
|
||||
char *calib_path;
|
||||
int minTxPower;
|
||||
int maxTxPower;
|
||||
struct lc15l1_hdl *hdl;
|
||||
uint8_t max_cell_size; /* 0:166 qbits*/
|
||||
uint8_t diversity_mode; /* 0: SISO A, 1: SISO B, 2: MRC */
|
||||
uint8_t pedestal_mode; /* 0: unused TS is OFF, 1: unused TS is in minimum Tx power */
|
||||
uint8_t dsp_alive_period; /* DSP alive timer period */
|
||||
uint8_t tx_pwr_adj_mode; /* 0: no auto adjust power, 1: auto adjust power using RMS detector */
|
||||
uint8_t tx_pwr_red_8psk; /* 8-PSK maximum Tx power reduction level in dB */
|
||||
} lc15;
|
||||
} u;
|
||||
};
|
||||
|
||||
struct phy_link *phy_link_by_num(int num);
|
||||
struct phy_link *phy_link_create(void *ctx, int num);
|
||||
void phy_link_destroy(struct phy_link *plink);
|
||||
void phy_link_state_set(struct phy_link *plink, enum phy_link_state state);
|
||||
int phy_links_open(void);
|
||||
|
||||
struct phy_instance *phy_instance_by_num(struct phy_link *plink, int num);
|
||||
struct phy_instance *phy_instance_create(struct phy_link *plink, int num);
|
||||
void phy_instance_link_to_trx(struct phy_instance *pinst, struct gsm_bts_trx *trx);
|
||||
void phy_instance_destroy(struct phy_instance *pinst);
|
||||
const char *phy_instance_name(struct phy_instance *pinst);
|
||||
|
||||
void phy_user_statechg_notif(struct phy_instance *pinst, enum phy_link_state link_state);
|
||||
|
||||
static inline struct phy_instance *trx_phy_instance(struct gsm_bts_trx *trx)
|
||||
{
|
||||
OSMO_ASSERT(trx);
|
||||
return trx->role_bts.l1h;
|
||||
}
|
||||
|
||||
int bts_model_phy_link_open(struct phy_link *plink);
|
||||
7
include/osmo-bts/power_control.h
Normal file
7
include/osmo-bts/power_control.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <osmo-bts/gsm_data.h>
|
||||
|
||||
int lchan_ms_pwr_ctrl(struct gsm_lchan *lchan,
|
||||
const uint8_t ms_power, const int rxLevel);
|
||||
@@ -9,20 +9,27 @@ enum {
|
||||
LCHAN_REL_ACT_RSL,
|
||||
LCHAN_REL_ACT_PCU,
|
||||
LCHAN_REL_ACT_OML,
|
||||
LCHAN_REL_ACT_REACT, /* remove once auto-activation hack is removed from opstart_compl() */
|
||||
};
|
||||
|
||||
#define LCHAN_FN_DUMMY 0xFFFFFFFF
|
||||
#define LCHAN_FN_WAIT 0xFFFFFFFE
|
||||
|
||||
int msgb_queue_flush(struct llist_head *list);
|
||||
|
||||
int down_rsl(struct gsm_bts_trx *trx, struct msgb *msg);
|
||||
int rsl_tx_rf_res(struct gsm_bts_trx *trx);
|
||||
int rsl_tx_chan_rqd(struct gsm_bts_trx *trx, struct gsm_time *gtime,
|
||||
uint8_t ra, uint8_t acc_delay);
|
||||
int rsl_tx_est_ind(struct gsm_lchan *lchan, uint8_t link_id, uint8_t *data, int len);
|
||||
|
||||
int rsl_tx_chan_act_ack(struct gsm_lchan *lchan, struct gsm_time *gtime);
|
||||
int rsl_tx_chan_act_nack(struct gsm_lchan *lchan, uint8_t cause);
|
||||
int rsl_tx_chan_act_acknack(struct gsm_lchan *lchan, uint8_t cause);
|
||||
int rsl_tx_conn_fail(struct gsm_lchan *lchan, uint8_t cause);
|
||||
int rsl_tx_rf_rel_ack(struct gsm_lchan *lchan);
|
||||
int rsl_tx_hando_det(struct gsm_lchan *lchan, uint8_t *ho_delay);
|
||||
|
||||
int lchan_deactivate(struct gsm_lchan *lchan);
|
||||
|
||||
/* call-back for LAPDm code, called when it wants to send msgs UP */
|
||||
int lapdm_rll_tx_cb(struct msgb *msg, struct lapdm_entity *le, void *ctx);
|
||||
|
||||
@@ -31,7 +38,9 @@ int rsl_tx_ccch_load_ind_pch(struct gsm_bts *bts, uint16_t paging_avail);
|
||||
int rsl_tx_ccch_load_ind_rach(struct gsm_bts *bts, uint16_t total,
|
||||
uint16_t busy, uint16_t access);
|
||||
|
||||
struct gsm_lchan *rsl_lchan_lookup(struct gsm_bts_trx *trx, uint8_t chan_nr);
|
||||
void cb_ts_disconnected(struct gsm_bts_trx_ts *ts);
|
||||
void cb_ts_connected(struct gsm_bts_trx_ts *ts);
|
||||
void ipacc_dyn_pdch_complete(struct gsm_bts_trx_ts *ts, int rc);
|
||||
|
||||
#endif // _RSL_H */
|
||||
|
||||
|
||||
191
include/osmo-bts/scheduler.h
Normal file
191
include/osmo-bts/scheduler.h
Normal file
@@ -0,0 +1,191 @@
|
||||
#ifndef TRX_SCHEDULER_H
|
||||
#define TRX_SCHEDULER_H
|
||||
|
||||
#include <osmocom/core/utils.h>
|
||||
|
||||
#include <osmo-bts/gsm_data.h>
|
||||
|
||||
/* These types define the different channels on a multiframe.
|
||||
* Each channel has queues and can be activated individually.
|
||||
*/
|
||||
enum trx_chan_type {
|
||||
TRXC_IDLE = 0,
|
||||
TRXC_FCCH,
|
||||
TRXC_SCH,
|
||||
TRXC_BCCH,
|
||||
TRXC_RACH,
|
||||
TRXC_CCCH,
|
||||
TRXC_TCHF,
|
||||
TRXC_TCHH_0,
|
||||
TRXC_TCHH_1,
|
||||
TRXC_SDCCH4_0,
|
||||
TRXC_SDCCH4_1,
|
||||
TRXC_SDCCH4_2,
|
||||
TRXC_SDCCH4_3,
|
||||
TRXC_SDCCH8_0,
|
||||
TRXC_SDCCH8_1,
|
||||
TRXC_SDCCH8_2,
|
||||
TRXC_SDCCH8_3,
|
||||
TRXC_SDCCH8_4,
|
||||
TRXC_SDCCH8_5,
|
||||
TRXC_SDCCH8_6,
|
||||
TRXC_SDCCH8_7,
|
||||
TRXC_SACCHTF,
|
||||
TRXC_SACCHTH_0,
|
||||
TRXC_SACCHTH_1,
|
||||
TRXC_SACCH4_0,
|
||||
TRXC_SACCH4_1,
|
||||
TRXC_SACCH4_2,
|
||||
TRXC_SACCH4_3,
|
||||
TRXC_SACCH8_0,
|
||||
TRXC_SACCH8_1,
|
||||
TRXC_SACCH8_2,
|
||||
TRXC_SACCH8_3,
|
||||
TRXC_SACCH8_4,
|
||||
TRXC_SACCH8_5,
|
||||
TRXC_SACCH8_6,
|
||||
TRXC_SACCH8_7,
|
||||
TRXC_PDTCH,
|
||||
TRXC_PTCCH,
|
||||
_TRX_CHAN_MAX
|
||||
};
|
||||
|
||||
extern const struct value_string trx_chan_type_names[];
|
||||
|
||||
#define GSM_BURST_LEN 148
|
||||
#define GPRS_BURST_LEN GSM_BURST_LEN
|
||||
#define EGPRS_BURST_LEN 444
|
||||
|
||||
enum trx_burst_type {
|
||||
TRX_BURST_GMSK,
|
||||
TRX_BURST_8PSK,
|
||||
};
|
||||
|
||||
/* States each channel on a multiframe */
|
||||
struct l1sched_chan_state {
|
||||
/* scheduler */
|
||||
uint8_t active; /* Channel is active */
|
||||
ubit_t *dl_bursts; /* burst buffer for TX */
|
||||
enum trx_burst_type dl_burst_type; /* GMSK or 8PSK burst type */
|
||||
sbit_t *ul_bursts; /* burst buffer for RX */
|
||||
uint32_t ul_first_fn; /* fn of first burst */
|
||||
uint8_t ul_mask; /* mask of received bursts */
|
||||
|
||||
/* RSSI / TOA */
|
||||
uint8_t rssi_num; /* number of RSSI values */
|
||||
float rssi_sum; /* sum of RSSI values */
|
||||
uint8_t toa_num; /* number of TOA values */
|
||||
float toa_sum; /* sum of TOA values */
|
||||
|
||||
/* loss detection */
|
||||
uint8_t lost; /* (SACCH) loss detection */
|
||||
|
||||
/* mode */
|
||||
uint8_t rsl_cmode, tch_mode; /* mode for TCH channels */
|
||||
|
||||
/* AMR */
|
||||
uint8_t codec[4]; /* 4 possible codecs for amr */
|
||||
int codecs; /* number of possible codecs */
|
||||
float ber_sum; /* sum of bit error rates */
|
||||
int ber_num; /* number of bit error rates */
|
||||
uint8_t ul_ft; /* current uplink FT index */
|
||||
uint8_t dl_ft; /* current downlink FT index */
|
||||
uint8_t ul_cmr; /* current uplink CMR index */
|
||||
uint8_t dl_cmr; /* current downlink CMR index */
|
||||
uint8_t amr_loop; /* if AMR loop is enabled */
|
||||
|
||||
/* TCH/H */
|
||||
uint8_t dl_ongoing_facch; /* FACCH/H on downlink */
|
||||
uint8_t ul_ongoing_facch; /* FACCH/H on uplink */
|
||||
|
||||
/* encryption */
|
||||
int ul_encr_algo; /* A5/x encry algo downlink */
|
||||
int dl_encr_algo; /* A5/x encry algo uplink */
|
||||
int ul_encr_key_len;
|
||||
int dl_encr_key_len;
|
||||
uint8_t ul_encr_key[MAX_A5_KEY_LEN];
|
||||
uint8_t dl_encr_key[MAX_A5_KEY_LEN];
|
||||
|
||||
/* measurements */
|
||||
struct {
|
||||
uint8_t clock; /* cyclic clock counter */
|
||||
int8_t rssi[32]; /* last RSSI values */
|
||||
int rssi_count; /* received RSSI values */
|
||||
int rssi_valid_count; /* number of stored value */
|
||||
int rssi_got_burst; /* any burst received so far */
|
||||
float toa_sum; /* sum of TOA values */
|
||||
int toa_num; /* number of TOA value */
|
||||
} meas;
|
||||
|
||||
/* handover */
|
||||
uint8_t ho_rach_detect; /* if rach detection is on */
|
||||
};
|
||||
|
||||
struct l1sched_ts {
|
||||
uint8_t mf_index; /* selected multiframe index */
|
||||
uint32_t mf_last_fn; /* last received frame number */
|
||||
uint8_t mf_period; /* period of multiframe */
|
||||
const struct trx_sched_frame *mf_frames; /* pointer to frame layout */
|
||||
|
||||
struct llist_head dl_prims; /* Queue primitives for TX */
|
||||
|
||||
/* Channel states for all logical channels */
|
||||
struct l1sched_chan_state chan_state[_TRX_CHAN_MAX];
|
||||
};
|
||||
|
||||
struct l1sched_trx {
|
||||
struct gsm_bts_trx *trx;
|
||||
struct l1sched_ts ts[TRX_NR_TS];
|
||||
};
|
||||
|
||||
struct l1sched_ts *l1sched_trx_get_ts(struct l1sched_trx *l1t, uint8_t tn);
|
||||
|
||||
/*! \brief how many frame numbers in advance we should send bursts to PHY */
|
||||
extern uint32_t trx_clock_advance;
|
||||
/*! \brief advance RTS.ind to L2 by that many clocks */
|
||||
extern uint32_t trx_rts_advance;
|
||||
/*! \brief last frame number as received from PHY */
|
||||
extern uint32_t transceiver_last_fn;
|
||||
|
||||
|
||||
/*! \brief Initialize the scheduler data structures */
|
||||
int trx_sched_init(struct l1sched_trx *l1t, struct gsm_bts_trx *trx);
|
||||
|
||||
/*! \brief De-initialize the scheduler data structures */
|
||||
void trx_sched_exit(struct l1sched_trx *l1t);
|
||||
|
||||
/*! \brief Handle a PH-DATA.req from L2 down to L1 */
|
||||
int trx_sched_ph_data_req(struct l1sched_trx *l1t, struct osmo_phsap_prim *l1sap);
|
||||
|
||||
/*! \brief Handle a PH-TCH.req from L2 down to L1 */
|
||||
int trx_sched_tch_req(struct l1sched_trx *l1t, struct osmo_phsap_prim *l1sap);
|
||||
|
||||
/*! \brief PHY informs us of new (current) GSM frame number */
|
||||
int trx_sched_clock(struct gsm_bts *bts, uint32_t fn);
|
||||
|
||||
/*! \brief handle an UL burst received by PHY */
|
||||
int trx_sched_ul_burst(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||
sbit_t *bits, uint16_t nbits, int8_t rssi, float toa);
|
||||
|
||||
/*! \brief set multiframe scheduler to given physical channel config */
|
||||
int trx_sched_set_pchan(struct l1sched_trx *l1t, uint8_t tn,
|
||||
enum gsm_phys_chan_config pchan);
|
||||
|
||||
/*! \brief set all matching logical channels active/inactive */
|
||||
int trx_sched_set_lchan(struct l1sched_trx *l1t, uint8_t chan_nr, uint8_t link_id,
|
||||
int active);
|
||||
|
||||
/*! \brief set mode of all matching logical channels to given mode(s) */
|
||||
int trx_sched_set_mode(struct l1sched_trx *l1t, uint8_t chan_nr, uint8_t rsl_cmode,
|
||||
uint8_t tch_mode, int codecs, uint8_t codec0, uint8_t codec1,
|
||||
uint8_t codec2, uint8_t codec3, uint8_t initial_codec,
|
||||
uint8_t handover);
|
||||
|
||||
/*! \brief set ciphering on given logical channels */
|
||||
int trx_sched_set_cipher(struct l1sched_trx *l1t, uint8_t chan_nr, int downlink,
|
||||
int algo, uint8_t *key, int key_len);
|
||||
|
||||
/* \brief close all logical channels and reset timeslots */
|
||||
void trx_sched_reset(struct l1sched_trx *l1t);
|
||||
|
||||
#endif /* TRX_SCHEDULER_H */
|
||||
88
include/osmo-bts/scheduler_backend.h
Normal file
88
include/osmo-bts/scheduler_backend.h
Normal file
@@ -0,0 +1,88 @@
|
||||
#pragma once
|
||||
|
||||
typedef int trx_sched_rts_func(struct l1sched_trx *l1t, uint8_t tn,
|
||||
uint32_t fn, enum trx_chan_type chan);
|
||||
|
||||
typedef ubit_t *trx_sched_dl_func(struct l1sched_trx *l1t, uint8_t tn,
|
||||
uint32_t fn, enum trx_chan_type chan,
|
||||
uint8_t bid, uint16_t *nbits);
|
||||
|
||||
typedef int trx_sched_ul_func(struct l1sched_trx *l1t, uint8_t tn,
|
||||
uint32_t fn, enum trx_chan_type chan,
|
||||
uint8_t bid, sbit_t *bits, uint16_t nbits,
|
||||
int8_t rssi, float toa);
|
||||
|
||||
struct trx_chan_desc {
|
||||
/*! \brief Is this on a PDCH (PS) ? */
|
||||
int pdch;
|
||||
/*! \brief TRX Channel Type */
|
||||
enum trx_chan_type chan;
|
||||
/*! \brief Channel Number (like in RSL) */
|
||||
uint8_t chan_nr;
|
||||
/*! \brief Link ID (like in RSL) */
|
||||
uint8_t link_id;
|
||||
/*! \brief Human-readable name */
|
||||
const char *name;
|
||||
/*! \brief function to call when we want to generate RTS.req to L2 */
|
||||
trx_sched_rts_func *rts_fn;
|
||||
/*! \brief function to call when DATA.req received from L2 */
|
||||
trx_sched_dl_func *dl_fn;
|
||||
/*! \brief function to call when burst received from PHY */
|
||||
trx_sched_ul_func *ul_fn;
|
||||
/*! \brief is this channel automatically active at start? */
|
||||
int auto_active;
|
||||
};
|
||||
extern const struct trx_chan_desc trx_chan_desc[_TRX_CHAN_MAX];
|
||||
|
||||
extern const ubit_t _sched_tsc[8][26];
|
||||
extern const ubit_t _sched_egprs_tsc[8][78];
|
||||
const ubit_t _sched_fcch_burst[148];
|
||||
const ubit_t _sched_sch_train[64];
|
||||
|
||||
struct msgb *_sched_dequeue_prim(struct l1sched_trx *l1t, int8_t tn, uint32_t fn,
|
||||
enum trx_chan_type chan);
|
||||
|
||||
int _sched_compose_ph_data_ind(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||
enum trx_chan_type chan, uint8_t *l2,
|
||||
uint8_t l2_len, float rssi,
|
||||
int16_t ta_offs_qbits, int16_t link_qual_cb,
|
||||
uint16_t ber10k,
|
||||
enum osmo_ph_pres_info_type presence_info);
|
||||
|
||||
int _sched_compose_tch_ind(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||
enum trx_chan_type chan, uint8_t *tch, uint8_t tch_len);
|
||||
|
||||
ubit_t *tx_idle_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||
enum trx_chan_type chan, uint8_t bid, uint16_t *nbits);
|
||||
ubit_t *tx_fcch_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||
enum trx_chan_type chan, uint8_t bid, uint16_t *nbits);
|
||||
ubit_t *tx_sch_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||
enum trx_chan_type chan, uint8_t bid, uint16_t *nbits);
|
||||
ubit_t *tx_data_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||
enum trx_chan_type chan, uint8_t bid, uint16_t *nbits);
|
||||
ubit_t *tx_pdtch_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||
enum trx_chan_type chan, uint8_t bid, uint16_t *nbits);
|
||||
ubit_t *tx_tchf_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||
enum trx_chan_type chan, uint8_t bid, uint16_t *nbits);
|
||||
ubit_t *tx_tchh_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||
enum trx_chan_type chan, uint8_t bid, uint16_t *nbits);
|
||||
int rx_rach_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||
enum trx_chan_type chan, uint8_t bid, sbit_t *bits, uint16_t nbits,
|
||||
int8_t rssi, float toa);
|
||||
int rx_data_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||
enum trx_chan_type chan, uint8_t bid, sbit_t *bits, uint16_t nbits,
|
||||
int8_t rssi, float toa);
|
||||
int rx_pdtch_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||
enum trx_chan_type chan, uint8_t bid, sbit_t *bits, uint16_t nbits,
|
||||
int8_t rssi, float toa);
|
||||
int rx_tchf_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||
enum trx_chan_type chan, uint8_t bid, sbit_t *bits, uint16_t nbits,
|
||||
int8_t rssi, float toa);
|
||||
int rx_tchh_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||
enum trx_chan_type chan, uint8_t bid, sbit_t *bits, uint16_t nbits,
|
||||
int8_t rssi, float toa);
|
||||
|
||||
const ubit_t *_sched_dl_burst(struct l1sched_trx *l1t, uint8_t tn,
|
||||
uint32_t fn, uint16_t *nbits);
|
||||
int _sched_rts(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn);
|
||||
void _sched_act_rach_det(struct l1sched_trx *l1t, uint8_t tn, uint8_t ss, int activate);
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
enum sig_subsys {
|
||||
SS_GLOBAL,
|
||||
SS_FAIL,
|
||||
};
|
||||
|
||||
enum signals_global {
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
/* PA calibration table */
|
||||
struct pa_calibration {
|
||||
int gain_mdB[1024]; /* gain provided at given ARFCN */
|
||||
int delta_mdB[1024]; /* gain delta at given ARFCN */
|
||||
/* FIXME: thermal calibration */
|
||||
};
|
||||
|
||||
@@ -74,3 +74,5 @@ int get_p_trxout_actual_mdBm_lchan(struct gsm_lchan *lchan);
|
||||
int power_ramp_start(struct gsm_bts_trx *trx, int p_total_tgt_mdBm, int bypass);
|
||||
|
||||
void power_trx_change_compl(struct gsm_bts_trx *trx, int p_trxout_cur_mdBm);
|
||||
|
||||
int power_ramp_initial_power_mdBm(struct gsm_bts_trx *trx);
|
||||
|
||||
@@ -5,17 +5,27 @@
|
||||
#include <osmocom/vty/command.h>
|
||||
|
||||
enum bts_vty_node {
|
||||
BTS_NODE = _LAST_OSMOVTY_NODE + 1,
|
||||
/* PHY_NODE must come before BTS node to ensure the phy
|
||||
* instances are created at the time the TRX nodes want to refer
|
||||
* to them */
|
||||
PHY_NODE = _LAST_OSMOVTY_NODE + 1,
|
||||
PHY_INST_NODE,
|
||||
BTS_NODE,
|
||||
TRX_NODE,
|
||||
};
|
||||
|
||||
extern struct cmd_element ournode_exit_cmd;
|
||||
extern struct cmd_element ournode_end_cmd;
|
||||
|
||||
enum node_type bts_vty_go_parent(struct vty *vty);
|
||||
extern struct cmd_element cfg_bts_auto_band_cmd;
|
||||
extern struct cmd_element cfg_bts_no_auto_band_cmd;
|
||||
|
||||
struct phy_instance *vty_get_phy_instance(struct vty *vty, int phy_nr, int inst_nr);
|
||||
|
||||
int bts_vty_go_parent(struct vty *vty);
|
||||
int bts_vty_is_config_node(struct vty *vty, int node);
|
||||
|
||||
int bts_vty_init(const struct log_info *cat);
|
||||
int bts_vty_init(struct gsm_bts *bts, const struct log_info *cat);
|
||||
|
||||
extern struct vty_app_info bts_vty_info;
|
||||
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
SUBDIRS = common
|
||||
SUBDIRS = common osmo-bts-virtual
|
||||
|
||||
if ENABLE_SYSMOBTS
|
||||
SUBDIRS += osmo-bts-sysmo
|
||||
endif
|
||||
|
||||
if ENABLE_TRX
|
||||
SUBDIRS += osmo-bts-trx
|
||||
endif
|
||||
|
||||
if ENABLE_OCTPHY
|
||||
SUBDIRS += osmo-bts-octphy
|
||||
endif
|
||||
|
||||
if ENABLE_LC15BTS
|
||||
SUBDIRS += osmo-bts-litecell15
|
||||
endif
|
||||
|
||||
@@ -1,10 +1,17 @@
|
||||
AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include -I$(OPENBSC_INCDIR)
|
||||
AM_CFLAGS = -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOTRAU_CFLAGS)
|
||||
LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOTRAU_LIBS)
|
||||
AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include
|
||||
AM_CFLAGS = -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOTRAU_CFLAGS) $(LIBOSMOCODEC_CFLAGS)
|
||||
LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOTRAU_LIBS) $(LIBOSMOCODEC_LIBS)
|
||||
|
||||
noinst_LIBRARIES = libbts.a
|
||||
if ENABLE_LC15BTS
|
||||
AM_CFLAGS += -DENABLE_LC15BTS
|
||||
endif
|
||||
|
||||
noinst_LIBRARIES = libbts.a libl1sched.a
|
||||
libbts_a_SOURCES = gsm_data_shared.c sysinfo.c logging.c abis.c oml.c bts.c \
|
||||
rsl.c vty.c paging.c measurement.c amr.c lchan.c \
|
||||
load_indication.c pcu_sock.c handover.c msg_utils.c \
|
||||
load_indication.c pcu_sock.c handover.c msg_utils.c \
|
||||
tx_power.c bts_ctrl_commands.c bts_ctrl_lookup.c
|
||||
tx_power.c bts_ctrl_commands.c bts_ctrl_lookup.c \
|
||||
l1sap.c cbch.c power_control.c main.c phy_link.c \
|
||||
dtx_dl_amr_fsm.c
|
||||
|
||||
libl1sched_a_SOURCES = scheduler.c
|
||||
|
||||
@@ -47,18 +47,39 @@
|
||||
#include <osmo-bts/bts.h>
|
||||
#include <osmo-bts/rsl.h>
|
||||
#include <osmo-bts/oml.h>
|
||||
#include <osmo-bts/bts_model.h>
|
||||
|
||||
static struct gsm_bts *g_bts;
|
||||
|
||||
int abis_oml_sendmsg(struct msgb *msg)
|
||||
{
|
||||
struct gsm_bts *bts = msg->trx->bts;
|
||||
struct gsm_bts_role_bts *btsb = bts_role_bts(bts);
|
||||
|
||||
if (!bts->oml_link) {
|
||||
llist_add_tail(&msg->list, &btsb->oml_queue);
|
||||
return 0;
|
||||
} else {
|
||||
/* osmo-bts uses msg->trx internally, but libosmo-abis uses
|
||||
* the signalling link at msg->dst */
|
||||
msg->dst = bts->oml_link;
|
||||
return abis_sendmsg(msg);
|
||||
}
|
||||
}
|
||||
|
||||
static void drain_oml_queue(struct gsm_bts *bts)
|
||||
{
|
||||
struct gsm_bts_role_bts *btsb = bts_role_bts(bts);
|
||||
struct msgb *msg, *msg2;
|
||||
|
||||
llist_for_each_entry_safe(msg, msg2, &btsb->oml_queue, list) {
|
||||
/* osmo-bts uses msg->trx internally, but libosmo-abis uses
|
||||
* the signalling link at msg->dst */
|
||||
llist_del(&msg->list);
|
||||
msg->dst = bts->oml_link;
|
||||
abis_sendmsg(msg);
|
||||
}
|
||||
}
|
||||
|
||||
int abis_bts_rsl_sendmsg(struct msgb *msg)
|
||||
{
|
||||
@@ -72,6 +93,8 @@ static struct e1inp_sign_link *sign_link_up(void *unit, struct e1inp_line *line,
|
||||
enum e1inp_sign_type type)
|
||||
{
|
||||
struct e1inp_sign_link *sign_link = NULL;
|
||||
struct gsm_bts_trx *trx;
|
||||
int trx_nr;
|
||||
|
||||
switch (type) {
|
||||
case E1INP_SIGN_OML:
|
||||
@@ -80,20 +103,26 @@ static struct e1inp_sign_link *sign_link_up(void *unit, struct e1inp_line *line,
|
||||
sign_link = g_bts->oml_link =
|
||||
e1inp_sign_link_create(&line->ts[E1INP_SIGN_OML-1],
|
||||
E1INP_SIGN_OML, NULL, 255, 0);
|
||||
drain_oml_queue(g_bts);
|
||||
sign_link->trx = g_bts->c0;
|
||||
bts_link_estab(g_bts);
|
||||
break;
|
||||
case E1INP_SIGN_RSL:
|
||||
LOGP(DABIS, LOGL_INFO, "RSL Signalling link up\n");
|
||||
e1inp_ts_config_sign(&line->ts[E1INP_SIGN_RSL-1], line);
|
||||
sign_link = g_bts->c0->rsl_link =
|
||||
e1inp_sign_link_create(&line->ts[E1INP_SIGN_RSL-1],
|
||||
E1INP_SIGN_RSL, NULL, 0, 0);
|
||||
/* FIXME: This assumes there is only one TRX! */
|
||||
sign_link->trx = g_bts->c0;
|
||||
trx_link_estab(sign_link->trx);
|
||||
break;
|
||||
default:
|
||||
trx_nr = type - E1INP_SIGN_RSL;
|
||||
LOGP(DABIS, LOGL_INFO, "RSL Signalling link for TRX%d up\n",
|
||||
trx_nr);
|
||||
trx = gsm_bts_trx_num(g_bts, trx_nr);
|
||||
if (!trx) {
|
||||
LOGP(DABIS, LOGL_ERROR, "TRX%d does not exixt!\n",
|
||||
trx_nr);
|
||||
break;
|
||||
}
|
||||
e1inp_ts_config_sign(&line->ts[type-1], line);
|
||||
sign_link = trx->rsl_link =
|
||||
e1inp_sign_link_create(&line->ts[type-1],
|
||||
E1INP_SIGN_RSL, NULL, 0, 0);
|
||||
sign_link->trx = trx;
|
||||
trx_link_estab(trx);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -102,19 +131,23 @@ static struct e1inp_sign_link *sign_link_up(void *unit, struct e1inp_line *line,
|
||||
|
||||
static void sign_link_down(struct e1inp_line *line)
|
||||
{
|
||||
struct gsm_bts_trx *trx;
|
||||
LOGP(DABIS, LOGL_ERROR, "Signalling link down\n");
|
||||
|
||||
if (g_bts->c0->rsl_link) {
|
||||
e1inp_sign_link_destroy(g_bts->c0->rsl_link);
|
||||
g_bts->c0->rsl_link = NULL;
|
||||
trx_link_estab(g_bts->c0);
|
||||
}
|
||||
|
||||
/* First remove the OML signalling link */
|
||||
if (g_bts->oml_link)
|
||||
e1inp_sign_link_destroy(g_bts->oml_link);
|
||||
g_bts->oml_link = NULL;
|
||||
|
||||
bts_shutdown(g_bts, "Abis close");
|
||||
/* Then iterate over the RSL signalling links */
|
||||
llist_for_each_entry(trx, &g_bts->trx_list, list) {
|
||||
if (trx->rsl_link) {
|
||||
e1inp_sign_link_destroy(trx->rsl_link);
|
||||
trx->rsl_link = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bts_model_abis_close(g_bts);
|
||||
}
|
||||
|
||||
|
||||
@@ -202,8 +235,7 @@ void abis_init(struct gsm_bts *bts)
|
||||
{
|
||||
g_bts = bts;
|
||||
|
||||
oml_init();
|
||||
e1inp_vty_init();
|
||||
oml_init(&bts->mo);
|
||||
libosmo_abis_init(NULL);
|
||||
|
||||
osmo_signal_register_handler(SS_L_INPUT, &inp_s_cbfn, bts);
|
||||
|
||||
@@ -16,11 +16,62 @@ void amr_log_mr_conf(int ss, int logl, const char *pfx,
|
||||
|
||||
for (i = 0; i < amr_mrc->num_modes; i++)
|
||||
LOGPC(ss, logl, ", mode[%u] = %u/%u/%u",
|
||||
i, amr_mrc->mode[i].mode, amr_mrc->mode[i].threshold,
|
||||
amr_mrc->mode[i].hysteresis);
|
||||
i, amr_mrc->bts_mode[i].mode,
|
||||
amr_mrc->bts_mode[i].threshold,
|
||||
amr_mrc->bts_mode[i].hysteresis);
|
||||
LOGPC(ss, logl, "\n");
|
||||
}
|
||||
|
||||
static inline int get_amr_mode_idx(const struct amr_multirate_conf *amr_mrc,
|
||||
uint8_t cmi)
|
||||
{
|
||||
unsigned int i;
|
||||
for (i = 0; i < amr_mrc->num_modes; i++) {
|
||||
if (amr_mrc->bts_mode[i].mode == cmi)
|
||||
return i;
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline uint8_t set_cmr_mode_idx(const struct amr_multirate_conf *amr_mrc,
|
||||
uint8_t cmr)
|
||||
{
|
||||
int rc;
|
||||
|
||||
/* Codec Mode Request is in upper 4 bits of RTP payload header,
|
||||
* and we simply copy the CMR into the CMC */
|
||||
if (cmr == 0xF) {
|
||||
/* FIXME: we need some state about the last codec mode */
|
||||
return 0;
|
||||
}
|
||||
|
||||
rc = get_amr_mode_idx(amr_mrc, cmr);
|
||||
if (rc < 0) {
|
||||
/* FIXME: we need some state about the last codec mode */
|
||||
LOGP(DRTP, LOGL_INFO, "RTP->L1: overriding CMR %u\n", cmr);
|
||||
return 0;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static inline uint8_t set_cmi_mode_idx(const struct amr_multirate_conf *amr_mrc,
|
||||
uint8_t cmi)
|
||||
{
|
||||
int rc = get_amr_mode_idx(amr_mrc, cmi);
|
||||
if (rc < 0) {
|
||||
LOGP(DRTP, LOGL_ERROR, "AMR CMI %u not part of AMR MR set\n",
|
||||
cmi);
|
||||
return 0;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
void amr_set_mode_pref(uint8_t *data, const struct amr_multirate_conf *amr_mrc,
|
||||
uint8_t cmi, uint8_t cmr)
|
||||
{
|
||||
data[0] = set_cmi_mode_idx(amr_mrc, cmi);
|
||||
data[1] = set_cmr_mode_idx(amr_mrc, cmr);
|
||||
}
|
||||
|
||||
/* parse a GSM 04.08 MultiRate Config IE (10.5.2.21aa) in a more
|
||||
* comfortable internal data structure */
|
||||
@@ -32,7 +83,7 @@ int amr_parse_mr_conf(struct amr_multirate_conf *amr_mrc,
|
||||
int i, j = 0;
|
||||
|
||||
if (mr_version != 1) {
|
||||
LOGP(DRSL, LOGL_ERROR, "AMR Multirate Version %u unknonw\n",
|
||||
LOGP(DRSL, LOGL_ERROR, "AMR Multirate Version %u unknown\n",
|
||||
mr_version);
|
||||
goto ret_einval;
|
||||
}
|
||||
@@ -63,23 +114,23 @@ int amr_parse_mr_conf(struct amr_multirate_conf *amr_mrc,
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (mr_conf[1] & (1 << i)) {
|
||||
amr_mrc->mode[j++].mode = i;
|
||||
amr_mrc->bts_mode[j++].mode = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (num_codecs >= 2) {
|
||||
amr_mrc->mode[0].threshold = mr_conf[1] & 0x3F;
|
||||
amr_mrc->mode[0].hysteresis = mr_conf[2] >> 4;
|
||||
amr_mrc->bts_mode[0].threshold = mr_conf[1] & 0x3F;
|
||||
amr_mrc->bts_mode[0].hysteresis = mr_conf[2] >> 4;
|
||||
}
|
||||
if (num_codecs >= 3) {
|
||||
amr_mrc->mode[1].threshold =
|
||||
amr_mrc->bts_mode[1].threshold =
|
||||
((mr_conf[2] & 0xF) << 2) | (mr_conf[3] >> 6);
|
||||
amr_mrc->mode[1].hysteresis = (mr_conf[3] >> 2) & 0x7;
|
||||
amr_mrc->bts_mode[1].hysteresis = (mr_conf[3] >> 2) & 0xF;
|
||||
}
|
||||
if (num_codecs >= 4) {
|
||||
amr_mrc->mode[3].threshold =
|
||||
amr_mrc->bts_mode[2].threshold =
|
||||
((mr_conf[3] & 0x3) << 4) | (mr_conf[4] >> 4);
|
||||
amr_mrc->mode[3].hysteresis = mr_conf[4] & 0xF;
|
||||
amr_mrc->bts_mode[2].hysteresis = mr_conf[4] & 0xF;
|
||||
}
|
||||
|
||||
return num_codecs;
|
||||
@@ -94,10 +145,12 @@ ret_einval:
|
||||
unsigned int amr_get_initial_mode(struct gsm_lchan *lchan)
|
||||
{
|
||||
struct amr_multirate_conf *amr_mrc = &lchan->tch.amr_mr;
|
||||
struct gsm48_multi_rate_conf *mr_conf =
|
||||
(struct gsm48_multi_rate_conf *) amr_mrc->gsm48_ie;
|
||||
|
||||
if (lchan->mr_conf.icmi) {
|
||||
if (mr_conf->icmi) {
|
||||
/* initial mode given, coding in TS 05.09 3.4.1 */
|
||||
return lchan->mr_conf.smod;
|
||||
return mr_conf->smod;
|
||||
} else {
|
||||
/* implicit rule according to TS 05.09 Chapter 3.4.3 */
|
||||
switch (amr_mrc->num_modes) {
|
||||
|
||||
@@ -40,10 +40,17 @@
|
||||
#include <osmo-bts/abis.h>
|
||||
#include <osmo-bts/bts.h>
|
||||
#include <osmo-bts/bts_model.h>
|
||||
#include <osmo-bts/dtx_dl_amr_fsm.h>
|
||||
#include <osmo-bts/pcu_if.h>
|
||||
#include <osmo-bts/rsl.h>
|
||||
#include <osmo-bts/oml.h>
|
||||
#include <osmo-bts/signal.h>
|
||||
#include <osmo-bts/dtx_dl_amr_fsm.h>
|
||||
|
||||
#define MIN_QUAL_RACH 5.0f /* at least 5 dB C/I */
|
||||
#define MIN_QUAL_NORM -0.5f /* at least -1 dB C/I */
|
||||
|
||||
static void bts_update_agch_max_queue_length(struct gsm_bts *bts);
|
||||
|
||||
struct gsm_network bts_gsmnet = {
|
||||
.bts_list = { &bts_gsmnet.bts_list, &bts_gsmnet.bts_list },
|
||||
@@ -72,12 +79,15 @@ static int bts_signal_cbfn(unsigned int subsys, unsigned int signal,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Initialize the BTS (and TRX) data structures, called before config
|
||||
* file reading */
|
||||
int bts_init(struct gsm_bts *bts)
|
||||
{
|
||||
struct gsm_bts_role_bts *btsb;
|
||||
struct gsm_bts_trx *trx;
|
||||
int rc;
|
||||
int rc, i;
|
||||
static int initialized = 0;
|
||||
void *tall_rtp_ctx;
|
||||
|
||||
/* add to list of BTSs */
|
||||
llist_add_tail(&bts->list, &bts_gsmnet.bts_list);
|
||||
@@ -99,6 +109,8 @@ int bts_init(struct gsm_bts *bts)
|
||||
|
||||
/* configurable via VTY */
|
||||
btsb->paging_state = paging_init(btsb, 200, 0);
|
||||
btsb->ul_power_target = -75; /* dBm default */
|
||||
btsb->rtp_jitter_adaptive = false;
|
||||
|
||||
/* configurable via OML */
|
||||
btsb->load.ccch.load_ind_period = 112;
|
||||
@@ -107,6 +119,11 @@ int bts_init(struct gsm_bts *bts)
|
||||
btsb->max_ta = 63;
|
||||
btsb->ny1 = 4;
|
||||
btsb->t3105_ms = 300;
|
||||
btsb->min_qual_rach = MIN_QUAL_RACH;
|
||||
btsb->min_qual_norm = MIN_QUAL_NORM;
|
||||
btsb->pcu.sock_path = talloc_strdup(btsb, PCU_SOCK_DEFAULT);
|
||||
for (i = 0; i < ARRAY_SIZE(btsb->t200_ms); i++)
|
||||
btsb->t200_ms[i] = oml_default_t200_ms[i];
|
||||
|
||||
/* default RADIO_LINK_TIMEOUT */
|
||||
btsb->radio_link_timeout = 32;
|
||||
@@ -136,12 +153,15 @@ int bts_init(struct gsm_bts *bts)
|
||||
}
|
||||
}
|
||||
/* Default values for the power adjustments */
|
||||
tpp->ramp.max_initial_pout_mdBm = to_mdB(23);
|
||||
tpp->ramp.max_initial_pout_mdBm = to_mdB(0);
|
||||
tpp->ramp.step_size_mdB = to_mdB(2);
|
||||
tpp->ramp.step_interval_sec = 1;
|
||||
}
|
||||
|
||||
osmo_rtp_init(tall_bts_ctx);
|
||||
/* allocate a talloc pool for ORTP to ensure it doesn't have to go back
|
||||
* to the libc malloc all the time */
|
||||
tall_rtp_ctx = talloc_pool(tall_bts_ctx, 262144);
|
||||
osmo_rtp_init(tall_rtp_ctx);
|
||||
|
||||
rc = bts_model_init(bts);
|
||||
if (rc < 0) {
|
||||
@@ -156,6 +176,13 @@ int bts_init(struct gsm_bts *bts)
|
||||
initialized = 1;
|
||||
}
|
||||
|
||||
INIT_LLIST_HEAD(&btsb->smscb_state.queue);
|
||||
INIT_LLIST_HEAD(&btsb->oml_queue);
|
||||
|
||||
/* register DTX DL FSM */
|
||||
rc = osmo_fsm_register(&dtx_dl_amr_fsm);
|
||||
OSMO_ASSERT(rc == 0);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -182,7 +209,7 @@ void bts_shutdown(struct gsm_bts *bts, const char *reason)
|
||||
LOGP(DOML, LOGL_NOTICE, "Shutting down BTS %u, Reason %s\n",
|
||||
bts->nr, reason);
|
||||
|
||||
llist_for_each_entry(trx, &bts->trx_list, list) {
|
||||
llist_for_each_entry_reverse(trx, &bts->trx_list, list) {
|
||||
bts_model_trx_deact_rf(trx);
|
||||
bts_model_trx_close(trx);
|
||||
}
|
||||
@@ -231,6 +258,7 @@ int trx_link_estab(struct gsm_bts_trx *trx)
|
||||
{
|
||||
struct e1inp_sign_link *link = trx->rsl_link;
|
||||
uint8_t radio_state = link ? NM_OPSTATE_ENABLED : NM_OPSTATE_DISABLED;
|
||||
int rc;
|
||||
|
||||
LOGP(DSUM, LOGL_INFO, "RSL link (TRX %02x) state changed to %s, sending Status'.\n",
|
||||
trx->nr, link ? "up" : "down");
|
||||
@@ -238,8 +266,38 @@ int trx_link_estab(struct gsm_bts_trx *trx)
|
||||
oml_mo_state_chg(&trx->mo, radio_state, NM_AVSTATE_OK);
|
||||
|
||||
if (link)
|
||||
rsl_tx_rf_res(trx);
|
||||
rc = rsl_tx_rf_res(trx);
|
||||
else
|
||||
rc = bts_model_trx_deact_rf(trx);
|
||||
if (rc < 0)
|
||||
oml_fail_rep(OSMO_EVT_MAJ_RSL_FAIL,
|
||||
link ? "Failed to establish RSL link (%d)" :
|
||||
"Failed to deactivate RF (%d)", rc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* set the availability of the TRX (used by PHY driver) */
|
||||
int trx_set_available(struct gsm_bts_trx *trx, int avail)
|
||||
{
|
||||
int tn;
|
||||
|
||||
LOGP(DSUM, LOGL_INFO, "TRX(%d): Setting available = %d\n",
|
||||
trx->nr, avail);
|
||||
if (avail) {
|
||||
/* FIXME: This needs to be sorted out */
|
||||
#if 0
|
||||
oml_mo_state_chg(&trx->mo, NM_OPSTATE_DISABLED, NM_AVSTATE_OFF_LINE);
|
||||
oml_mo_state_chg(&trx->bb_transc.mo, -1, NM_AVSTATE_OFF_LINE);
|
||||
for (tn = 0; tn < ARRAY_SIZE(trx->ts); tn++)
|
||||
oml_mo_state_chg(&trx->ts[tn].mo, NM_OPSTATE_DISABLED, NM_AVSTATE_DEPENDENCY);
|
||||
#endif
|
||||
} else {
|
||||
oml_mo_state_chg(&trx->mo, NM_OPSTATE_DISABLED, NM_AVSTATE_NOT_INSTALLED);
|
||||
oml_mo_state_chg(&trx->bb_transc.mo, -1, NM_AVSTATE_NOT_INSTALLED);
|
||||
|
||||
for (tn = 0; tn < ARRAY_SIZE(trx->ts); tn++)
|
||||
oml_mo_state_chg(&trx->ts[tn].mo, NM_OPSTATE_DISABLED, NM_AVSTATE_NOT_INSTALLED);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -251,6 +309,7 @@ int lchan_init_lapdm(struct gsm_lchan *lchan)
|
||||
lapdm_channel_set_flags(lc, LAPDM_ENT_F_POLLING_ONLY);
|
||||
lapdm_channel_set_l1(lc, NULL, lchan);
|
||||
lapdm_channel_set_l3(lc, lapdm_rll_tx_cb, lchan);
|
||||
oml_set_lchan_t200(lchan);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -297,7 +356,7 @@ int bts_agch_max_queue_length(int T, int bcch_conf)
|
||||
return (T + 2 * S) * ccch_rach_ratio256 / 256;
|
||||
}
|
||||
|
||||
void bts_update_agch_max_queue_length(struct gsm_bts *bts)
|
||||
static void bts_update_agch_max_queue_length(struct gsm_bts *bts)
|
||||
{
|
||||
struct gsm_bts_role_bts *btsb = bts_role_bts(bts);
|
||||
struct gsm48_system_information_type_3 *si3;
|
||||
@@ -604,3 +663,15 @@ int bts_supports_cipher(struct gsm_bts_role_bts *bts, int rsl_cipher)
|
||||
sup = (1 << (rsl_cipher - 2)) & bts->support.ciphers;
|
||||
return sup > 0;
|
||||
}
|
||||
|
||||
int trx_ms_pwr_ctrl_is_osmo(struct gsm_bts_trx *trx)
|
||||
{
|
||||
return trx->ms_power_control == 1;
|
||||
}
|
||||
|
||||
struct gsm_time *get_time(struct gsm_bts *bts)
|
||||
{
|
||||
struct gsm_bts_role_bts *btsb = bts->role;
|
||||
|
||||
return &btsb->gsm_time;
|
||||
}
|
||||
|
||||
@@ -24,11 +24,15 @@
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <osmocom/gsm/protocol/gsm_12_21.h>
|
||||
#include <osmocom/ctrl/control_cmd.h>
|
||||
|
||||
#include <osmo-bts/logging.h>
|
||||
#include <osmo-bts/gsm_data.h>
|
||||
#include <osmo-bts/tx_power.h>
|
||||
#include <osmo-bts/signal.h>
|
||||
#include <osmo-bts/oml.h>
|
||||
#include <osmo-bts/bts.h>
|
||||
|
||||
CTRL_CMD_DEFINE(therm_att, "thermal-attenuation");
|
||||
static int get_therm_att(struct ctrl_cmd *cmd, void *data)
|
||||
@@ -67,12 +71,23 @@ static int verify_therm_att(struct ctrl_cmd *cmd, const char *value, void *data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
CTRL_CMD_DEFINE_WO_NOVRF(oml_alert, "oml-alert");
|
||||
static int set_oml_alert(struct ctrl_cmd *cmd, void *data)
|
||||
{
|
||||
/* Note: we expect signal dispatch to be synchronous */
|
||||
osmo_signal_dispatch(SS_FAIL, OSMO_EVT_EXT_ALARM, cmd->value);
|
||||
|
||||
cmd->reply = "OK";
|
||||
|
||||
return CTRL_CMD_REPLY;
|
||||
}
|
||||
|
||||
int bts_ctrl_cmds_install(struct gsm_bts *bts)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
rc |= ctrl_cmd_install(CTRL_NODE_TRX, &cmd_therm_att);
|
||||
rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_oml_alert);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -24,8 +24,10 @@
|
||||
#include <osmocom/vty/command.h>
|
||||
#include <osmocom/ctrl/control_if.h>
|
||||
#include <osmocom/ctrl/ports.h>
|
||||
#include <osmo-bts/bts_model.h>
|
||||
#include <osmo-bts/logging.h>
|
||||
#include <osmo-bts/gsm_data.h>
|
||||
#include <osmo-bts/control_if.h>
|
||||
|
||||
extern vector ctrl_node_vec;
|
||||
|
||||
@@ -85,12 +87,14 @@ err_index:
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
struct ctrl_handle *bts_controlif_setup(struct gsm_bts *bts)
|
||||
struct ctrl_handle *bts_controlif_setup(struct gsm_bts *bts,
|
||||
const char *bind_addr, uint16_t port)
|
||||
{
|
||||
struct ctrl_handle *hdl;
|
||||
int rc = 0;
|
||||
|
||||
hdl = ctrl_interface_setup(bts, OSMO_CTRL_PORT_BTS, bts_ctrl_node_lookup);
|
||||
hdl = ctrl_interface_setup_dynip(bts, bind_addr, port,
|
||||
bts_ctrl_node_lookup);
|
||||
if (!hdl)
|
||||
return NULL;
|
||||
|
||||
@@ -100,5 +104,12 @@ struct ctrl_handle *bts_controlif_setup(struct gsm_bts *bts)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rc = bts_model_ctrl_cmds_install(bts);
|
||||
if (rc) {
|
||||
/* FIXME: cleanup generic control commands */
|
||||
/* FIXME: close control interface */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return hdl;
|
||||
}
|
||||
|
||||
196
src/common/cbch.c
Normal file
196
src/common/cbch.c
Normal file
@@ -0,0 +1,196 @@
|
||||
/* Cell Broadcast routines */
|
||||
|
||||
/* (C) 2014 by Harald Welte <laforge@gnumonks.org>
|
||||
*
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include <osmocom/core/linuxlist.h>
|
||||
#include <osmocom/gsm/protocol/gsm_04_12.h>
|
||||
|
||||
#include <osmo-bts/bts.h>
|
||||
#include <osmo-bts/cbch.h>
|
||||
#include <osmo-bts/logging.h>
|
||||
|
||||
struct smscb_msg {
|
||||
struct llist_head list; /* list in smscb_state.queue */
|
||||
|
||||
uint8_t msg[GSM412_MSG_LEN]; /* message buffer */
|
||||
uint8_t next_seg; /* next segment number */
|
||||
uint8_t num_segs; /* total number of segments */
|
||||
};
|
||||
|
||||
static int get_smscb_null_block(uint8_t *out)
|
||||
{
|
||||
struct gsm412_block_type *block_type = (struct gsm412_block_type *) out;
|
||||
|
||||
block_type->spare = 0;
|
||||
block_type->lpd = 1;
|
||||
block_type->seq_nr = GSM412_SEQ_NULL_MSG;
|
||||
block_type->lb = 0;
|
||||
memset(out+1, GSM_MACBLOCK_PADDING, GSM412_BLOCK_LEN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* get the next block of the current CB message */
|
||||
static int get_smscb_block(struct gsm_bts *bts, uint8_t *out)
|
||||
{
|
||||
int to_copy;
|
||||
struct gsm_bts_role_bts *btsb = bts_role_bts(bts);
|
||||
struct gsm412_block_type *block_type;
|
||||
struct smscb_msg *msg = btsb->smscb_state.cur_msg;
|
||||
|
||||
if (!msg) {
|
||||
/* No message: Send NULL mesage */
|
||||
return get_smscb_null_block(out);
|
||||
}
|
||||
|
||||
block_type = (struct gsm412_block_type *) out++;
|
||||
|
||||
/* LPD is always 01 */
|
||||
block_type->spare = 0;
|
||||
block_type->lpd = 1;
|
||||
|
||||
/* determine how much data to copy */
|
||||
to_copy = GSM412_MSG_LEN - (msg->next_seg * GSM412_BLOCK_LEN);
|
||||
if (to_copy > GSM412_BLOCK_LEN)
|
||||
to_copy = GSM412_BLOCK_LEN;
|
||||
|
||||
/* copy data and increment index */
|
||||
memcpy(out, &msg->msg[msg->next_seg * GSM412_BLOCK_LEN], to_copy);
|
||||
|
||||
/* set + increment sequence number */
|
||||
block_type->seq_nr = msg->next_seg++;
|
||||
|
||||
/* determine if this is the last block */
|
||||
if (block_type->seq_nr + 1 == msg->num_segs)
|
||||
block_type->lb = 1;
|
||||
else
|
||||
block_type->lb = 0;
|
||||
|
||||
if (block_type->lb == 1) {
|
||||
/* remove/release the message memory */
|
||||
talloc_free(btsb->smscb_state.cur_msg);
|
||||
btsb->smscb_state.cur_msg = NULL;
|
||||
}
|
||||
|
||||
return block_type->lb;
|
||||
}
|
||||
|
||||
static const uint8_t last_block_rsl2um[4] = {
|
||||
[RSL_CB_CMD_LASTBLOCK_4] = 4,
|
||||
[RSL_CB_CMD_LASTBLOCK_1] = 1,
|
||||
[RSL_CB_CMD_LASTBLOCK_2] = 2,
|
||||
[RSL_CB_CMD_LASTBLOCK_3] = 3,
|
||||
};
|
||||
|
||||
|
||||
/* incoming SMS broadcast command from RSL */
|
||||
int bts_process_smscb_cmd(struct gsm_bts *bts,
|
||||
struct rsl_ie_cb_cmd_type cmd_type,
|
||||
uint8_t msg_len, const uint8_t *msg)
|
||||
{
|
||||
struct gsm_bts_role_bts *btsb = bts_role_bts(bts);
|
||||
struct smscb_msg *scm;
|
||||
|
||||
if (msg_len > sizeof(scm->msg)) {
|
||||
LOGP(DLSMS, LOGL_ERROR,
|
||||
"Cannot process SMSCB of %u bytes (max %zu)\n",
|
||||
msg_len, sizeof(scm->msg));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
scm = talloc_zero_size(bts, sizeof(*scm));
|
||||
|
||||
/* initialize entire message with default padding */
|
||||
memset(scm->msg, GSM_MACBLOCK_PADDING, sizeof(scm->msg));
|
||||
/* next segment is first segment */
|
||||
scm->next_seg = 0;
|
||||
|
||||
switch (cmd_type.command) {
|
||||
case RSL_CB_CMD_TYPE_NORMAL:
|
||||
case RSL_CB_CMD_TYPE_SCHEDULE:
|
||||
case RSL_CB_CMD_TYPE_NULL:
|
||||
scm->num_segs = last_block_rsl2um[cmd_type.last_block&3];
|
||||
memcpy(scm->msg, msg, msg_len);
|
||||
/* def_bcast is ignored */
|
||||
break;
|
||||
case RSL_CB_CMD_TYPE_DEFAULT:
|
||||
/* use def_bcast, ignore command */
|
||||
/* def_bcast == 0: normal mess */
|
||||
break;
|
||||
}
|
||||
|
||||
llist_add_tail(&scm->list, &btsb->smscb_state.queue);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct smscb_msg *select_next_smscb(struct gsm_bts *bts)
|
||||
{
|
||||
struct smscb_msg *msg;
|
||||
struct gsm_bts_role_bts *btsb = bts_role_bts(bts);
|
||||
|
||||
if (llist_empty(&btsb->smscb_state.queue))
|
||||
return NULL;
|
||||
|
||||
msg = llist_entry(btsb->smscb_state.queue.next,
|
||||
struct smscb_msg, list);
|
||||
|
||||
llist_del(&msg->list);
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
/* call-back from bts model specific code when it wants to obtain a CBCH
|
||||
* block for a given gsm_time. outbuf must have 23 bytes of space. */
|
||||
int bts_cbch_get(struct gsm_bts *bts, uint8_t *outbuf, struct gsm_time *g_time)
|
||||
{
|
||||
struct gsm_bts_role_bts *btsb = bts_role_bts(bts);
|
||||
uint32_t fn = gsm_gsmtime2fn(g_time);
|
||||
/* According to 05.02 Section 6.5.4 */
|
||||
uint32_t tb = (fn / 51) % 8;
|
||||
int rc = 0;
|
||||
|
||||
/* The multiframes used for the basic cell broadcast channel
|
||||
* shall be those in * which TB = 0,1,2 and 3. The multiframes
|
||||
* used for the extended cell broadcast channel shall be those
|
||||
* in which TB = 4, 5, 6 and 7 */
|
||||
|
||||
/* The SMSCB header shall be sent in the multiframe in which TB
|
||||
* = 0 for the basic, and TB = 4 for the extended cell
|
||||
* broadcast channel. */
|
||||
|
||||
switch (tb) {
|
||||
case 0:
|
||||
/* select a new SMSCB message */
|
||||
btsb->smscb_state.cur_msg = select_next_smscb(bts);
|
||||
rc = get_smscb_block(bts, outbuf);
|
||||
break;
|
||||
case 1: case 2: case 3:
|
||||
rc = get_smscb_block(bts, outbuf);
|
||||
break;
|
||||
case 4: case 5: case 6: case 7:
|
||||
/* always send NULL frame in extended CBCH for now */
|
||||
rc = get_smscb_null_block(outbuf);
|
||||
break;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
477
src/common/dtx_dl_amr_fsm.c
Normal file
477
src/common/dtx_dl_amr_fsm.c
Normal file
@@ -0,0 +1,477 @@
|
||||
/* DTX DL AMR FSM */
|
||||
|
||||
/* (C) 2016 by sysmocom s.f.m.c. GmbH
|
||||
*
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <osmo-bts/dtx_dl_amr_fsm.h>
|
||||
#include <osmo-bts/logging.h>
|
||||
|
||||
void dtx_fsm_voice(struct osmo_fsm_inst *fi, uint32_t event, void *data)
|
||||
{
|
||||
switch (event) {
|
||||
case E_VOICE:
|
||||
case E_FACCH:
|
||||
break;
|
||||
case E_SID_F:
|
||||
osmo_fsm_inst_state_chg(fi, ST_SID_F1, 0, 0);
|
||||
break;
|
||||
case E_SID_U:
|
||||
osmo_fsm_inst_state_chg(fi, ST_U_NOINH, 0, 0);
|
||||
break;
|
||||
case E_INHIB:
|
||||
osmo_fsm_inst_state_chg(fi, ST_F1_INH_V, 0, 0);
|
||||
break;
|
||||
default:
|
||||
LOGP(DL1P, LOGL_ERROR, "Inexpected event %d\n", event);
|
||||
OSMO_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void dtx_fsm_sid_f1(struct osmo_fsm_inst *fi, uint32_t event, void *data)
|
||||
{
|
||||
switch (event) {
|
||||
case E_SID_F:
|
||||
/* FIXME: what shall we do if we get SID-FIRST _again_ (twice in a row)?
|
||||
Was observed during testing, let's just ignore it for now */
|
||||
break;
|
||||
case E_SID_U:
|
||||
osmo_fsm_inst_state_chg(fi, ST_U_NOINH, 0, 0);
|
||||
break;
|
||||
case E_FACCH:
|
||||
osmo_fsm_inst_state_chg(fi, ST_F1_INH_F, 0, 0);
|
||||
break;
|
||||
case E_FIRST:
|
||||
osmo_fsm_inst_state_chg(fi, ST_SID_F2, 0, 0);
|
||||
break;
|
||||
case E_ONSET:
|
||||
osmo_fsm_inst_state_chg(fi, ST_ONSET_V, 0, 0);
|
||||
break;
|
||||
default:
|
||||
LOGP(DL1P, LOGL_ERROR, "Unexpected event %d\n", event);
|
||||
OSMO_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void dtx_fsm_sid_f2(struct osmo_fsm_inst *fi, uint32_t event, void *data)
|
||||
{
|
||||
switch (event) {
|
||||
case E_COMPL:
|
||||
osmo_fsm_inst_state_chg(fi, ST_U_NOINH, 0, 0);
|
||||
break;
|
||||
case E_FACCH:
|
||||
osmo_fsm_inst_state_chg(fi, ST_ONSET_F, 0, 0);
|
||||
break;
|
||||
case E_ONSET:
|
||||
osmo_fsm_inst_state_chg(fi, ST_ONSET_V, 0, 0);
|
||||
break;
|
||||
default:
|
||||
LOGP(DL1P, LOGL_ERROR, "Unexpected event %d\n", event);
|
||||
OSMO_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void dtx_fsm_f1_inh_v(struct osmo_fsm_inst *fi, uint32_t event, void *data)
|
||||
{
|
||||
switch (event) {
|
||||
case E_COMPL:
|
||||
osmo_fsm_inst_state_chg(fi, ST_F1_INH_V_REC, 0, 0);
|
||||
break;
|
||||
default:
|
||||
LOGP(DL1P, LOGL_ERROR, "Unexpected event %d\n", event);
|
||||
OSMO_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void dtx_fsm_f1_inh_f(struct osmo_fsm_inst *fi, uint32_t event, void *data)
|
||||
{
|
||||
switch (event) {
|
||||
case E_COMPL:
|
||||
osmo_fsm_inst_state_chg(fi, ST_F1_INH_F_REC, 0, 0);
|
||||
break;
|
||||
default:
|
||||
LOGP(DL1P, LOGL_ERROR, "Unexpected event %d\n", event);
|
||||
OSMO_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void dtx_fsm_u_inh_v(struct osmo_fsm_inst *fi, uint32_t event, void *data)
|
||||
{
|
||||
switch (event) {
|
||||
case E_COMPL:
|
||||
osmo_fsm_inst_state_chg(fi, ST_U_INH_V_REC, 0, 0);
|
||||
break;
|
||||
default:
|
||||
LOGP(DL1P, LOGL_ERROR, "Unexpected event %d\n", event);
|
||||
OSMO_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void dtx_fsm_u_inh_f(struct osmo_fsm_inst *fi, uint32_t event, void *data)
|
||||
{
|
||||
switch (event) {
|
||||
case E_COMPL:
|
||||
osmo_fsm_inst_state_chg(fi, ST_U_INH_F_REC, 0, 0);
|
||||
break;
|
||||
default:
|
||||
LOGP(DL1P, LOGL_ERROR, "Unexpected event %d\n", event);
|
||||
OSMO_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void dtx_fsm_f1_inh_v_rec(struct osmo_fsm_inst *fi, uint32_t event, void *data)
|
||||
{
|
||||
switch (event) {
|
||||
case E_VOICE:
|
||||
case E_COMPL:
|
||||
osmo_fsm_inst_state_chg(fi, ST_VOICE, 0, 0);
|
||||
break;
|
||||
default:
|
||||
LOGP(DL1P, LOGL_ERROR, "Unexpected event %d\n", event);
|
||||
OSMO_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void dtx_fsm_f1_inh_f_rec(struct osmo_fsm_inst *fi, uint32_t event, void *data)
|
||||
{
|
||||
switch (event) {
|
||||
case E_FACCH:
|
||||
case E_COMPL:
|
||||
osmo_fsm_inst_state_chg(fi, ST_FACCH, 0, 0);
|
||||
break;
|
||||
default:
|
||||
LOGP(DL1P, LOGL_ERROR, "Unexpected event %d\n", event);
|
||||
OSMO_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void dtx_fsm_u_inh_v_rec(struct osmo_fsm_inst *fi, uint32_t event, void *data)
|
||||
{
|
||||
switch (event) {
|
||||
case E_VOICE:
|
||||
case E_COMPL:
|
||||
osmo_fsm_inst_state_chg(fi, ST_VOICE, 0, 0);
|
||||
break;
|
||||
default:
|
||||
LOGP(DL1P, LOGL_ERROR, "Unexpected event %d\n", event);
|
||||
OSMO_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void dtx_fsm_u_inh_f_rec(struct osmo_fsm_inst *fi, uint32_t event, void *data)
|
||||
{
|
||||
switch (event) {
|
||||
case E_FACCH:
|
||||
case E_COMPL:
|
||||
osmo_fsm_inst_state_chg(fi, ST_FACCH, 0, 0);
|
||||
break;
|
||||
default:
|
||||
LOGP(DL1P, LOGL_ERROR, "Unexpected event %d\n", event);
|
||||
OSMO_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void dtx_fsm_u_noinh(struct osmo_fsm_inst *fi, uint32_t event, void *data)
|
||||
{
|
||||
switch (event) {
|
||||
case E_FACCH:
|
||||
osmo_fsm_inst_state_chg(fi, ST_ONSET_F, 0, 0);
|
||||
break;
|
||||
case E_VOICE:
|
||||
osmo_fsm_inst_state_chg(fi, ST_VOICE, 0, 0);
|
||||
break;
|
||||
case E_COMPL:
|
||||
osmo_fsm_inst_state_chg(fi, ST_SID_U, 0, 0);
|
||||
break;
|
||||
case E_SID_U:
|
||||
case E_SID_F:
|
||||
/* FIXME: what shall we do if we get SID-FIRST _after_ sending SID-UPDATE?
|
||||
Was observed during testing, let's just ignore it for now */
|
||||
break;
|
||||
case E_ONSET:
|
||||
osmo_fsm_inst_state_chg(fi, ST_ONSET_V, 0, 0);
|
||||
break;
|
||||
default:
|
||||
LOGP(DL1P, LOGL_ERROR, "Unexpected event %d\n", event);
|
||||
OSMO_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void dtx_fsm_sid_upd(struct osmo_fsm_inst *fi, uint32_t event, void *data)
|
||||
{
|
||||
switch (event) {
|
||||
case E_FACCH:
|
||||
osmo_fsm_inst_state_chg(fi, ST_U_INH_F, 0, 0);
|
||||
break;
|
||||
case E_VOICE:
|
||||
osmo_fsm_inst_state_chg(fi, ST_VOICE, 0, 0);
|
||||
break;
|
||||
case E_INHIB:
|
||||
osmo_fsm_inst_state_chg(fi, ST_U_INH_V, 0, 0);
|
||||
break;
|
||||
case E_SID_U:
|
||||
case E_SID_F:
|
||||
osmo_fsm_inst_state_chg(fi, ST_U_NOINH, 0, 0);
|
||||
break;
|
||||
default:
|
||||
LOGP(DL1P, LOGL_ERROR, "Unexpected event %d\n", event);
|
||||
OSMO_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void dtx_fsm_onset_v(struct osmo_fsm_inst *fi, uint32_t event, void *data)
|
||||
{
|
||||
switch (event) {
|
||||
case E_COMPL:
|
||||
osmo_fsm_inst_state_chg(fi, ST_ONSET_V_REC, 0, 0);
|
||||
break;
|
||||
default:
|
||||
LOGP(DL1P, LOGL_ERROR, "Unexpected event %d\n", event);
|
||||
OSMO_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void dtx_fsm_onset_f(struct osmo_fsm_inst *fi, uint32_t event, void *data)
|
||||
{
|
||||
switch (event) {
|
||||
case E_COMPL:
|
||||
osmo_fsm_inst_state_chg(fi, ST_ONSET_F_REC, 0, 0);
|
||||
break;
|
||||
default:
|
||||
LOGP(DL1P, LOGL_ERROR, "Unexpected event %d\n", event);
|
||||
OSMO_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void dtx_fsm_onset_v_rec(struct osmo_fsm_inst *fi, uint32_t event, void *data)
|
||||
{
|
||||
switch (event) {
|
||||
case E_COMPL:
|
||||
osmo_fsm_inst_state_chg(fi, ST_VOICE, 0, 0);
|
||||
break;
|
||||
default:
|
||||
LOGP(DL1P, LOGL_ERROR, "Unexpected event %d\n", event);
|
||||
OSMO_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void dtx_fsm_onset_f_rec(struct osmo_fsm_inst *fi, uint32_t event, void *data)
|
||||
{
|
||||
switch (event) {
|
||||
case E_COMPL:
|
||||
osmo_fsm_inst_state_chg(fi, ST_FACCH, 0, 0);
|
||||
break;
|
||||
default:
|
||||
LOGP(DL1P, LOGL_ERROR, "Unexpected event %d\n", event);
|
||||
OSMO_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void dtx_fsm_facch(struct osmo_fsm_inst *fi, uint32_t event, void *data)
|
||||
{
|
||||
switch (event) {
|
||||
case E_SID_U:
|
||||
case E_SID_F:
|
||||
case E_FACCH:
|
||||
break;
|
||||
case E_VOICE:
|
||||
osmo_fsm_inst_state_chg(fi, ST_VOICE, 0, 0);
|
||||
break;
|
||||
case E_COMPL:
|
||||
osmo_fsm_inst_state_chg(fi, ST_SID_F1, 0, 0);
|
||||
break;
|
||||
default:
|
||||
LOGP(DL1P, LOGL_ERROR, "Unexpected event %d\n", event);
|
||||
OSMO_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static struct osmo_fsm_state dtx_dl_amr_fsm_states[] = {
|
||||
/* default state for non-DTX and DTX when SPEECH is in progress */
|
||||
[ST_VOICE] = {
|
||||
.in_event_mask = X(E_SID_F) | X(E_SID_U) | X(E_VOICE) | X(E_FACCH) | X(E_INHIB),
|
||||
.out_state_mask = X(ST_SID_F1) | X(ST_U_NOINH) | X(ST_F1_INH_V),
|
||||
.name = "Voice",
|
||||
.action = dtx_fsm_voice,
|
||||
},
|
||||
/* SID-FIRST or SID-FIRST-P1 in case of AMR HR:
|
||||
start of silence period (might be interrupted in case of AMR HR) */
|
||||
[ST_SID_F1]= {
|
||||
.in_event_mask = X(E_SID_F) | X(E_SID_U) | X(E_FACCH) | X(E_FIRST) | X(E_ONSET),
|
||||
.out_state_mask = X(ST_U_NOINH) | X(ST_ONSET_F) | X(ST_SID_F2) | X(ST_ONSET_V),
|
||||
.name = "SID-FIRST (P1)",
|
||||
.action = dtx_fsm_sid_f1,
|
||||
},
|
||||
/* SID-FIRST P2 (only for AMR HR):
|
||||
actual start of silence period in case of AMR HR */
|
||||
[ST_SID_F2]= {
|
||||
.in_event_mask = X(E_COMPL) | X(E_FACCH) | X(E_ONSET),
|
||||
.out_state_mask = X(ST_U_NOINH) | X(ST_ONSET_F) | X(ST_ONSET_V),
|
||||
.name = "SID-FIRST (P2)",
|
||||
.action = dtx_fsm_sid_f2,
|
||||
},
|
||||
/* SID-FIRST Inhibited: incoming SPEECH (only for AMR HR) */
|
||||
[ST_F1_INH_V]= {
|
||||
.in_event_mask = X(E_COMPL),
|
||||
.out_state_mask = X(ST_F1_INH_V_REC),
|
||||
.name = "SID-FIRST (Inh, SPEECH)",
|
||||
.action = dtx_fsm_f1_inh_v,
|
||||
},
|
||||
/* SID-FIRST Inhibited: incoming FACCH frame (only for AMR HR) */
|
||||
[ST_F1_INH_F]= {
|
||||
.in_event_mask = X(E_COMPL),
|
||||
.out_state_mask = X(ST_F1_INH_F_REC),
|
||||
.name = "SID-FIRST (Inh, FACCH)",
|
||||
.action = dtx_fsm_f1_inh_f,
|
||||
},
|
||||
/* SID-UPDATE Inhibited: incoming SPEECH (only for AMR HR) */
|
||||
[ST_U_INH_V]= {
|
||||
.in_event_mask = X(E_COMPL),
|
||||
.out_state_mask = X(ST_U_INH_V_REC),
|
||||
.name = "SID-UPDATE (Inh, SPEECH)",
|
||||
.action = dtx_fsm_u_inh_v,
|
||||
},
|
||||
/* SID-UPDATE Inhibited: incoming FACCH frame (only for AMR HR) */
|
||||
[ST_U_INH_F]= {
|
||||
.in_event_mask = X(E_COMPL),
|
||||
.out_state_mask = X(ST_U_INH_F_REC),
|
||||
.name = "SID-UPDATE (Inh, FACCH)",
|
||||
.action = dtx_fsm_u_inh_f,
|
||||
},
|
||||
/* SID-UPDATE: Inhibited not allowed (only for AMR HR) */
|
||||
[ST_U_NOINH]= {
|
||||
.in_event_mask = X(E_FACCH) | X(E_VOICE) | X(E_COMPL) | X(E_SID_U) | X(E_SID_F) | X(E_ONSET),
|
||||
.out_state_mask = X(ST_ONSET_F) | X(ST_VOICE) | X(ST_SID_U) | X(ST_ONSET_V),
|
||||
.name = "SID-UPDATE (NoInh)",
|
||||
.action = dtx_fsm_u_noinh,
|
||||
},
|
||||
/* SID-FIRST Inhibition recursion in progress:
|
||||
Inhibit itself was already sent, now have to send the voice that caused it */
|
||||
[ST_F1_INH_V_REC]= {
|
||||
.in_event_mask = X(E_COMPL) | X(E_VOICE),
|
||||
.out_state_mask = X(ST_VOICE),
|
||||
.name = "SID-FIRST (Inh, SPEECH, Rec)",
|
||||
.action = dtx_fsm_f1_inh_v_rec,
|
||||
},
|
||||
/* SID-FIRST Inhibition recursion in progress:
|
||||
Inhibit itself was already sent, now have to send the data that caused it */
|
||||
[ST_F1_INH_F_REC]= {
|
||||
.in_event_mask = X(E_COMPL) | X(E_FACCH),
|
||||
.out_state_mask = X(ST_FACCH),
|
||||
.name = "SID-FIRST (Inh, FACCH, Rec)",
|
||||
.action = dtx_fsm_f1_inh_f_rec,
|
||||
},
|
||||
/* SID-UPDATE Inhibition recursion in progress:
|
||||
Inhibit itself was already sent, now have to send the voice that caused it */
|
||||
[ST_U_INH_V_REC]= {
|
||||
.in_event_mask = X(E_COMPL) | X(E_VOICE),
|
||||
.out_state_mask = X(ST_VOICE),
|
||||
.name = "SID-UPDATE (Inh, SPEECH, Rec)",
|
||||
.action = dtx_fsm_u_inh_v_rec,
|
||||
},
|
||||
/* SID-UPDATE Inhibition recursion in progress:
|
||||
Inhibit itself was already sent, now have to send the data that caused it */
|
||||
[ST_U_INH_F_REC]= {
|
||||
.in_event_mask = X(E_COMPL) | X(E_FACCH),
|
||||
.out_state_mask = X(ST_FACCH),
|
||||
.name = "SID-UPDATE (Inh, FACCH, Rec)",
|
||||
.action = dtx_fsm_u_inh_f_rec,
|
||||
},
|
||||
/* Silence period with periodic comfort noise data updates */
|
||||
[ST_SID_U]= {
|
||||
.in_event_mask = X(E_FACCH) | X(E_VOICE) | X(E_INHIB) | X(E_SID_U) | X(E_SID_F),
|
||||
.out_state_mask = X(ST_ONSET_F) | X(ST_VOICE) | X(ST_U_INH_V) | X(ST_U_INH_F) | X(ST_U_NOINH),
|
||||
.name = "SID-UPDATE (AMR/HR)",
|
||||
.action = dtx_fsm_sid_upd,
|
||||
},
|
||||
/* ONSET - end of silent period due to incoming SPEECH frame */
|
||||
[ST_ONSET_V]= {
|
||||
.in_event_mask = X(E_COMPL),
|
||||
.out_state_mask = X(ST_ONSET_V_REC),
|
||||
.name = "ONSET (SPEECH)",
|
||||
.action = dtx_fsm_onset_v,
|
||||
},
|
||||
/* ONSET - end of silent period due to incoming FACCH frame */
|
||||
[ST_ONSET_F]= {
|
||||
.in_event_mask = X(E_COMPL),
|
||||
.out_state_mask = X(ST_ONSET_F_REC),
|
||||
.name = "ONSET (FACCH)",
|
||||
.action = dtx_fsm_onset_f,
|
||||
},
|
||||
/* ONSET recursion in progress:
|
||||
ONSET itself was already sent, now have to send the voice that caused it */
|
||||
[ST_ONSET_V_REC]= {
|
||||
.in_event_mask = X(E_COMPL),
|
||||
.out_state_mask = X(ST_VOICE),
|
||||
.name = "ONSET (SPEECH, Rec)",
|
||||
.action = dtx_fsm_onset_v_rec,
|
||||
},
|
||||
/* ONSET recursion in progress:
|
||||
ONSET itself was already sent, now have to send the data that caused it */
|
||||
[ST_ONSET_F_REC]= {
|
||||
.in_event_mask = X(E_COMPL),
|
||||
.out_state_mask = X(ST_FACCH),
|
||||
.name = "ONSET (FACCH, Rec)",
|
||||
.action = dtx_fsm_onset_f_rec,
|
||||
},
|
||||
/* FACCH sending state */
|
||||
[ST_FACCH]= {
|
||||
.in_event_mask = X(E_FACCH) | X(E_VOICE) | X(E_COMPL) | X(E_SID_U) | X(E_SID_F),
|
||||
.out_state_mask = X(ST_VOICE) | X(ST_SID_F1),
|
||||
.name = "FACCH",
|
||||
.action = dtx_fsm_facch,
|
||||
},
|
||||
};
|
||||
|
||||
const struct value_string dtx_dl_amr_fsm_event_names[] = {
|
||||
{ E_VOICE, "Voice" },
|
||||
{ E_ONSET, "ONSET" },
|
||||
{ E_FACCH, "FACCH" },
|
||||
{ E_COMPL, "Complete" },
|
||||
{ E_FIRST, "FIRST P1->P2" },
|
||||
{ E_INHIB, "Inhibit" },
|
||||
{ E_SID_F, "SID-FIRST" },
|
||||
{ E_SID_U, "SID-UPDATE" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
struct osmo_fsm dtx_dl_amr_fsm = {
|
||||
.name = "DTX_DL_AMR_FSM",
|
||||
.states = dtx_dl_amr_fsm_states,
|
||||
.num_states = ARRAY_SIZE(dtx_dl_amr_fsm_states),
|
||||
.event_names = dtx_dl_amr_fsm_event_names,
|
||||
.log_subsys = DL1C,
|
||||
};
|
||||
@@ -1 +1,853 @@
|
||||
#include "../../../openbsc/openbsc/src/libcommon/gsm_data_shared.c"
|
||||
/* (C) 2008-2010 by Harald Welte <laforge@gnumonks.org>
|
||||
*
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <osmocom/core/linuxlist.h>
|
||||
#include <osmocom/core/talloc.h>
|
||||
#include <osmocom/gsm/gsm_utils.h>
|
||||
#include <osmocom/gsm/abis_nm.h>
|
||||
#include <osmocom/core/statistics.h>
|
||||
|
||||
#include <osmo-bts/gsm_data.h>
|
||||
|
||||
void gsm_abis_mo_reset(struct gsm_abis_mo *mo)
|
||||
{
|
||||
mo->nm_state.operational = NM_OPSTATE_NULL;
|
||||
mo->nm_state.availability = NM_AVSTATE_POWER_OFF;
|
||||
}
|
||||
|
||||
static void gsm_mo_init(struct gsm_abis_mo *mo, struct gsm_bts *bts,
|
||||
uint8_t obj_class, uint8_t p1, uint8_t p2, uint8_t p3)
|
||||
{
|
||||
mo->bts = bts;
|
||||
mo->obj_class = obj_class;
|
||||
mo->obj_inst.bts_nr = p1;
|
||||
mo->obj_inst.trx_nr = p2;
|
||||
mo->obj_inst.ts_nr = p3;
|
||||
gsm_abis_mo_reset(mo);
|
||||
}
|
||||
|
||||
const struct value_string bts_attribute_names[] = {
|
||||
OSMO_VALUE_STRING(BTS_TYPE_VARIANT),
|
||||
OSMO_VALUE_STRING(BTS_SUB_MODEL),
|
||||
OSMO_VALUE_STRING(TRX_PHY_VERSION),
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
enum bts_attribute str2btsattr(const char *s)
|
||||
{
|
||||
return get_string_value(bts_attribute_names, s);
|
||||
}
|
||||
|
||||
const char *btsatttr2str(enum bts_attribute v)
|
||||
{
|
||||
return get_value_string(bts_attribute_names, v);
|
||||
}
|
||||
|
||||
const struct value_string osmo_bts_variant_names[_NUM_BTS_VARIANT + 1] = {
|
||||
{ BTS_UNKNOWN, "unknown" },
|
||||
{ BTS_OSMO_LITECELL15, "osmo-bts-lc15" },
|
||||
{ BTS_OSMO_OCTPHY, "osmo-bts-octphy" },
|
||||
{ BTS_OSMO_SYSMO, "osmo-bts-sysmo" },
|
||||
{ BTS_OSMO_TRX, "omso-bts-trx" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
enum gsm_bts_type_variant str2btsvariant(const char *arg)
|
||||
{
|
||||
return get_string_value(osmo_bts_variant_names, arg);
|
||||
}
|
||||
|
||||
const char *btsvariant2str(enum gsm_bts_type_variant v)
|
||||
{
|
||||
return get_value_string(osmo_bts_variant_names, v);
|
||||
}
|
||||
|
||||
const struct value_string bts_type_names[_NUM_GSM_BTS_TYPE + 1] = {
|
||||
{ GSM_BTS_TYPE_UNKNOWN, "unknown" },
|
||||
{ GSM_BTS_TYPE_BS11, "bs11" },
|
||||
{ GSM_BTS_TYPE_NANOBTS, "nanobts" },
|
||||
{ GSM_BTS_TYPE_RBS2000, "rbs2000" },
|
||||
{ GSM_BTS_TYPE_NOKIA_SITE, "nokia_site" },
|
||||
{ GSM_BTS_TYPE_OSMOBTS, "sysmobts" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
enum gsm_bts_type str2btstype(const char *arg)
|
||||
{
|
||||
return get_string_value(bts_type_names, arg);
|
||||
}
|
||||
|
||||
const char *btstype2str(enum gsm_bts_type type)
|
||||
{
|
||||
return get_value_string(bts_type_names, type);
|
||||
}
|
||||
|
||||
const struct value_string gsm_bts_features_descs[] = {
|
||||
{ BTS_FEAT_HSCSD, "HSCSD" },
|
||||
{ BTS_FEAT_GPRS, "GPRS" },
|
||||
{ BTS_FEAT_EGPRS, "EGPRS" },
|
||||
{ BTS_FEAT_ECSD, "ECSD" },
|
||||
{ BTS_FEAT_HOPPING, "Frequency Hopping" },
|
||||
{ BTS_FEAT_MULTI_TSC, "Multi-TSC" },
|
||||
{ BTS_FEAT_OML_ALERTS, "OML Alerts" },
|
||||
{ BTS_FEAT_AGCH_PCH_PROP, "AGCH/PCH proportional allocation" },
|
||||
{ BTS_FEAT_CBCH, "CBCH" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
const struct value_string gsm_chreq_descs[] = {
|
||||
{ GSM_CHREQ_REASON_EMERG, "emergency call" },
|
||||
{ GSM_CHREQ_REASON_PAG, "answer to paging" },
|
||||
{ GSM_CHREQ_REASON_CALL, "call re-establishment" },
|
||||
{ GSM_CHREQ_REASON_LOCATION_UPD,"Location updating" },
|
||||
{ GSM_CHREQ_REASON_PDCH, "one phase packet access" },
|
||||
{ GSM_CHREQ_REASON_OTHER, "other" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
const struct value_string gsm_pchant_names[13] = {
|
||||
{ GSM_PCHAN_NONE, "NONE" },
|
||||
{ GSM_PCHAN_CCCH, "CCCH" },
|
||||
{ GSM_PCHAN_CCCH_SDCCH4,"CCCH+SDCCH4" },
|
||||
{ GSM_PCHAN_TCH_F, "TCH/F" },
|
||||
{ GSM_PCHAN_TCH_H, "TCH/H" },
|
||||
{ GSM_PCHAN_SDCCH8_SACCH8C, "SDCCH8" },
|
||||
{ GSM_PCHAN_PDCH, "PDCH" },
|
||||
{ GSM_PCHAN_TCH_F_PDCH, "TCH/F_PDCH" },
|
||||
{ GSM_PCHAN_UNKNOWN, "UNKNOWN" },
|
||||
{ GSM_PCHAN_CCCH_SDCCH4_CBCH, "CCCH+SDCCH4+CBCH" },
|
||||
{ GSM_PCHAN_SDCCH8_SACCH8C_CBCH, "SDCCH8+CBCH" },
|
||||
{ GSM_PCHAN_TCH_F_TCH_H_PDCH, "TCH/F_TCH/H_PDCH" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
const struct value_string gsm_pchant_descs[13] = {
|
||||
{ GSM_PCHAN_NONE, "Physical Channel not configured" },
|
||||
{ GSM_PCHAN_CCCH, "FCCH + SCH + BCCH + CCCH (Comb. IV)" },
|
||||
{ GSM_PCHAN_CCCH_SDCCH4,
|
||||
"FCCH + SCH + BCCH + CCCH + 4 SDCCH + 2 SACCH (Comb. V)" },
|
||||
{ GSM_PCHAN_TCH_F, "TCH/F + FACCH/F + SACCH (Comb. I)" },
|
||||
{ GSM_PCHAN_TCH_H, "2 TCH/H + 2 FACCH/H + 2 SACCH (Comb. II)" },
|
||||
{ GSM_PCHAN_SDCCH8_SACCH8C, "8 SDCCH + 4 SACCH (Comb. VII)" },
|
||||
{ GSM_PCHAN_PDCH, "Packet Data Channel for GPRS/EDGE" },
|
||||
{ GSM_PCHAN_TCH_F_PDCH, "Dynamic TCH/F or GPRS PDCH" },
|
||||
{ GSM_PCHAN_UNKNOWN, "Unknown / Unsupported channel combination" },
|
||||
{ GSM_PCHAN_CCCH_SDCCH4_CBCH, "FCCH + SCH + BCCH + CCCH + CBCH + 3 SDCCH + 2 SACCH (Comb. V)" },
|
||||
{ GSM_PCHAN_SDCCH8_SACCH8C_CBCH, "7 SDCCH + 4 SACCH + CBCH (Comb. VII)" },
|
||||
{ GSM_PCHAN_TCH_F_TCH_H_PDCH, "Dynamic TCH/F or TCH/H or GPRS PDCH" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
const char *gsm_pchan_name(enum gsm_phys_chan_config c)
|
||||
{
|
||||
return get_value_string(gsm_pchant_names, c);
|
||||
}
|
||||
|
||||
enum gsm_phys_chan_config gsm_pchan_parse(const char *name)
|
||||
{
|
||||
return get_string_value(gsm_pchant_names, name);
|
||||
}
|
||||
|
||||
/* TODO: move to libosmocore, next to gsm_chan_t_names? */
|
||||
const char *gsm_lchant_name(enum gsm_chan_t c)
|
||||
{
|
||||
return get_value_string(gsm_chan_t_names, c);
|
||||
}
|
||||
|
||||
static const struct value_string lchan_s_names[] = {
|
||||
{ LCHAN_S_NONE, "NONE" },
|
||||
{ LCHAN_S_ACT_REQ, "ACTIVATION REQUESTED" },
|
||||
{ LCHAN_S_ACTIVE, "ACTIVE" },
|
||||
{ LCHAN_S_INACTIVE, "INACTIVE" },
|
||||
{ LCHAN_S_REL_REQ, "RELEASE REQUESTED" },
|
||||
{ LCHAN_S_REL_ERR, "RELEASE DUE ERROR" },
|
||||
{ LCHAN_S_BROKEN, "BROKEN UNUSABLE" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
const char *gsm_lchans_name(enum gsm_lchan_state s)
|
||||
{
|
||||
return get_value_string(lchan_s_names, s);
|
||||
}
|
||||
|
||||
static const struct value_string chreq_names[] = {
|
||||
{ GSM_CHREQ_REASON_EMERG, "EMERGENCY" },
|
||||
{ GSM_CHREQ_REASON_PAG, "PAGING" },
|
||||
{ GSM_CHREQ_REASON_CALL, "CALL" },
|
||||
{ GSM_CHREQ_REASON_LOCATION_UPD,"LOCATION_UPDATE" },
|
||||
{ GSM_CHREQ_REASON_OTHER, "OTHER" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
const char *gsm_chreq_name(enum gsm_chreq_reason_t c)
|
||||
{
|
||||
return get_value_string(chreq_names, c);
|
||||
}
|
||||
|
||||
struct gsm_bts *gsm_bts_num(struct gsm_network *net, int num)
|
||||
{
|
||||
struct gsm_bts *bts;
|
||||
|
||||
if (num >= net->num_bts)
|
||||
return NULL;
|
||||
|
||||
llist_for_each_entry(bts, &net->bts_list, list) {
|
||||
if (bts->nr == num)
|
||||
return bts;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct gsm_bts_trx *gsm_bts_trx_alloc(struct gsm_bts *bts)
|
||||
{
|
||||
struct gsm_bts_trx *trx = talloc_zero(bts, struct gsm_bts_trx);
|
||||
int k;
|
||||
|
||||
if (!trx)
|
||||
return NULL;
|
||||
|
||||
trx->bts = bts;
|
||||
trx->nr = bts->num_trx++;
|
||||
trx->mo.nm_state.administrative = NM_STATE_UNLOCKED;
|
||||
|
||||
gsm_mo_init(&trx->mo, bts, NM_OC_RADIO_CARRIER,
|
||||
bts->nr, trx->nr, 0xff);
|
||||
gsm_mo_init(&trx->bb_transc.mo, bts, NM_OC_BASEB_TRANSC,
|
||||
bts->nr, trx->nr, 0xff);
|
||||
|
||||
for (k = 0; k < TRX_NR_TS; k++) {
|
||||
struct gsm_bts_trx_ts *ts = &trx->ts[k];
|
||||
int l;
|
||||
|
||||
ts->trx = trx;
|
||||
ts->nr = k;
|
||||
ts->pchan = GSM_PCHAN_NONE;
|
||||
ts->dyn.pchan_is = GSM_PCHAN_NONE;
|
||||
ts->dyn.pchan_want = GSM_PCHAN_NONE;
|
||||
ts->tsc = -1;
|
||||
|
||||
gsm_mo_init(&ts->mo, bts, NM_OC_CHANNEL,
|
||||
bts->nr, trx->nr, ts->nr);
|
||||
|
||||
ts->hopping.arfcns.data_len = sizeof(ts->hopping.arfcns_data);
|
||||
ts->hopping.arfcns.data = ts->hopping.arfcns_data;
|
||||
ts->hopping.ma.data_len = sizeof(ts->hopping.ma_data);
|
||||
ts->hopping.ma.data = ts->hopping.ma_data;
|
||||
|
||||
for (l = 0; l < TS_MAX_LCHAN; l++) {
|
||||
struct gsm_lchan *lchan;
|
||||
char *name;
|
||||
lchan = &ts->lchan[l];
|
||||
|
||||
lchan->ts = ts;
|
||||
lchan->nr = l;
|
||||
lchan->type = GSM_LCHAN_NONE;
|
||||
|
||||
name = gsm_lchan_name_compute(lchan);
|
||||
lchan->name = talloc_strdup(trx, name);
|
||||
#ifndef ROLE_BSC
|
||||
INIT_LLIST_HEAD(&lchan->sapi_cmds);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (trx->nr != 0)
|
||||
trx->nominal_power = bts->c0->nominal_power;
|
||||
|
||||
llist_add_tail(&trx->list, &bts->trx_list);
|
||||
|
||||
return trx;
|
||||
}
|
||||
|
||||
|
||||
static const uint8_t bts_nse_timer_default[] = { 3, 3, 3, 3, 30, 3, 10 };
|
||||
static const uint8_t bts_cell_timer_default[] =
|
||||
{ 3, 3, 3, 3, 3, 10, 3, 10, 3, 10, 3 };
|
||||
static const struct gprs_rlc_cfg rlc_cfg_default = {
|
||||
.parameter = {
|
||||
[RLC_T3142] = 20,
|
||||
[RLC_T3169] = 5,
|
||||
[RLC_T3191] = 5,
|
||||
[RLC_T3193] = 160, /* 10ms */
|
||||
[RLC_T3195] = 5,
|
||||
[RLC_N3101] = 10,
|
||||
[RLC_N3103] = 4,
|
||||
[RLC_N3105] = 8,
|
||||
[CV_COUNTDOWN] = 15,
|
||||
[T_DL_TBF_EXT] = 250 * 10, /* ms */
|
||||
[T_UL_TBF_EXT] = 250 * 10, /* ms */
|
||||
},
|
||||
.paging = {
|
||||
.repeat_time = 5 * 50, /* ms */
|
||||
.repeat_count = 3,
|
||||
},
|
||||
.cs_mask = 0x1fff,
|
||||
.initial_cs = 2,
|
||||
.initial_mcs = 6,
|
||||
};
|
||||
|
||||
struct gsm_bts *gsm_bts_alloc(void *ctx, uint8_t bts_num)
|
||||
{
|
||||
struct gsm_bts *bts = talloc_zero(ctx, struct gsm_bts);
|
||||
int i;
|
||||
|
||||
if (!bts)
|
||||
return NULL;
|
||||
|
||||
bts->nr = bts_num;
|
||||
bts->num_trx = 0;
|
||||
INIT_LLIST_HEAD(&bts->trx_list);
|
||||
bts->ms_max_power = 15; /* dBm */
|
||||
|
||||
gsm_mo_init(&bts->mo, bts, NM_OC_BTS,
|
||||
bts->nr, 0xff, 0xff);
|
||||
gsm_mo_init(&bts->site_mgr.mo, bts, NM_OC_SITE_MANAGER,
|
||||
0xff, 0xff, 0xff);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(bts->gprs.nsvc); i++) {
|
||||
bts->gprs.nsvc[i].bts = bts;
|
||||
bts->gprs.nsvc[i].id = i;
|
||||
gsm_mo_init(&bts->gprs.nsvc[i].mo, bts, NM_OC_GPRS_NSVC,
|
||||
bts->nr, i, 0xff);
|
||||
}
|
||||
memcpy(&bts->gprs.nse.timer, bts_nse_timer_default,
|
||||
sizeof(bts->gprs.nse.timer));
|
||||
gsm_mo_init(&bts->gprs.nse.mo, bts, NM_OC_GPRS_NSE,
|
||||
bts->nr, 0xff, 0xff);
|
||||
memcpy(&bts->gprs.cell.timer, bts_cell_timer_default,
|
||||
sizeof(bts->gprs.cell.timer));
|
||||
gsm_mo_init(&bts->gprs.cell.mo, bts, NM_OC_GPRS_CELL,
|
||||
bts->nr, 0xff, 0xff);
|
||||
memcpy(&bts->gprs.cell.rlc_cfg, &rlc_cfg_default,
|
||||
sizeof(bts->gprs.cell.rlc_cfg));
|
||||
|
||||
/* create our primary TRX */
|
||||
bts->c0 = gsm_bts_trx_alloc(bts);
|
||||
if (!bts->c0) {
|
||||
talloc_free(bts);
|
||||
return NULL;
|
||||
}
|
||||
bts->c0->ts[0].pchan = GSM_PCHAN_CCCH_SDCCH4;
|
||||
|
||||
bts->rach_b_thresh = -1;
|
||||
bts->rach_ldavg_slots = -1;
|
||||
bts->paging.free_chans_need = -1;
|
||||
bts->features.data = &bts->_features_data[0];
|
||||
bts->features.data_len = sizeof(bts->_features_data);
|
||||
|
||||
/* si handling */
|
||||
bts->bcch_change_mark = 1;
|
||||
|
||||
return bts;
|
||||
}
|
||||
|
||||
/* reset the state of all MO in the BTS */
|
||||
void gsm_bts_mo_reset(struct gsm_bts *bts)
|
||||
{
|
||||
struct gsm_bts_trx *trx;
|
||||
unsigned int i;
|
||||
|
||||
gsm_abis_mo_reset(&bts->mo);
|
||||
gsm_abis_mo_reset(&bts->site_mgr.mo);
|
||||
for (i = 0; i < ARRAY_SIZE(bts->gprs.nsvc); i++)
|
||||
gsm_abis_mo_reset(&bts->gprs.nsvc[i].mo);
|
||||
gsm_abis_mo_reset(&bts->gprs.nse.mo);
|
||||
gsm_abis_mo_reset(&bts->gprs.cell.mo);
|
||||
|
||||
llist_for_each_entry(trx, &bts->trx_list, list) {
|
||||
gsm_abis_mo_reset(&trx->mo);
|
||||
gsm_abis_mo_reset(&trx->bb_transc.mo);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(trx->ts); i++) {
|
||||
struct gsm_bts_trx_ts *ts = &trx->ts[i];
|
||||
gsm_abis_mo_reset(&ts->mo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct gsm_bts_trx *gsm_bts_trx_num(const struct gsm_bts *bts, int num)
|
||||
{
|
||||
struct gsm_bts_trx *trx;
|
||||
|
||||
if (num >= bts->num_trx)
|
||||
return NULL;
|
||||
|
||||
llist_for_each_entry(trx, &bts->trx_list, list) {
|
||||
if (trx->nr == num)
|
||||
return trx;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static char ts2str[255];
|
||||
|
||||
char *gsm_trx_name(const struct gsm_bts_trx *trx)
|
||||
{
|
||||
if (!trx)
|
||||
snprintf(ts2str, sizeof(ts2str), "(trx=NULL)");
|
||||
else
|
||||
snprintf(ts2str, sizeof(ts2str), "(bts=%d,trx=%d)",
|
||||
trx->bts->nr, trx->nr);
|
||||
|
||||
return ts2str;
|
||||
}
|
||||
|
||||
|
||||
char *gsm_ts_name(const struct gsm_bts_trx_ts *ts)
|
||||
{
|
||||
snprintf(ts2str, sizeof(ts2str), "(bts=%d,trx=%d,ts=%d)",
|
||||
ts->trx->bts->nr, ts->trx->nr, ts->nr);
|
||||
|
||||
return ts2str;
|
||||
}
|
||||
|
||||
/*! Log timeslot number with full pchan information */
|
||||
char *gsm_ts_and_pchan_name(const struct gsm_bts_trx_ts *ts)
|
||||
{
|
||||
switch (ts->pchan) {
|
||||
case GSM_PCHAN_TCH_F_TCH_H_PDCH:
|
||||
if (ts->dyn.pchan_is == ts->dyn.pchan_want)
|
||||
snprintf(ts2str, sizeof(ts2str),
|
||||
"(bts=%d,trx=%d,ts=%d,pchan=%s as %s)",
|
||||
ts->trx->bts->nr, ts->trx->nr, ts->nr,
|
||||
gsm_pchan_name(ts->pchan),
|
||||
gsm_pchan_name(ts->dyn.pchan_is));
|
||||
else
|
||||
snprintf(ts2str, sizeof(ts2str),
|
||||
"(bts=%d,trx=%d,ts=%d,pchan=%s"
|
||||
" switching %s -> %s)",
|
||||
ts->trx->bts->nr, ts->trx->nr, ts->nr,
|
||||
gsm_pchan_name(ts->pchan),
|
||||
gsm_pchan_name(ts->dyn.pchan_is),
|
||||
gsm_pchan_name(ts->dyn.pchan_want));
|
||||
break;
|
||||
case GSM_PCHAN_TCH_F_PDCH:
|
||||
if ((ts->flags & TS_F_PDCH_PENDING_MASK) == 0)
|
||||
snprintf(ts2str, sizeof(ts2str),
|
||||
"(bts=%d,trx=%d,ts=%d,pchan=%s as %s)",
|
||||
ts->trx->bts->nr, ts->trx->nr, ts->nr,
|
||||
gsm_pchan_name(ts->pchan),
|
||||
(ts->flags & TS_F_PDCH_ACTIVE)? "PDCH"
|
||||
: "TCH/F");
|
||||
else
|
||||
snprintf(ts2str, sizeof(ts2str),
|
||||
"(bts=%d,trx=%d,ts=%d,pchan=%s"
|
||||
" switching %s -> %s)",
|
||||
ts->trx->bts->nr, ts->trx->nr, ts->nr,
|
||||
gsm_pchan_name(ts->pchan),
|
||||
(ts->flags & TS_F_PDCH_ACTIVE)? "PDCH"
|
||||
: "TCH/F",
|
||||
(ts->flags & TS_F_PDCH_ACT_PENDING)? "PDCH"
|
||||
: "TCH/F");
|
||||
break;
|
||||
default:
|
||||
snprintf(ts2str, sizeof(ts2str), "(bts=%d,trx=%d,ts=%d,pchan=%s)",
|
||||
ts->trx->bts->nr, ts->trx->nr, ts->nr,
|
||||
gsm_pchan_name(ts->pchan));
|
||||
break;
|
||||
}
|
||||
|
||||
return ts2str;
|
||||
}
|
||||
|
||||
char *gsm_lchan_name_compute(const struct gsm_lchan *lchan)
|
||||
{
|
||||
struct gsm_bts_trx_ts *ts = lchan->ts;
|
||||
|
||||
snprintf(ts2str, sizeof(ts2str), "(bts=%d,trx=%d,ts=%d,ss=%d)",
|
||||
ts->trx->bts->nr, ts->trx->nr, ts->nr, lchan->nr);
|
||||
|
||||
return ts2str;
|
||||
}
|
||||
|
||||
/* obtain the MO structure for a given object instance */
|
||||
struct gsm_abis_mo *
|
||||
gsm_objclass2mo(struct gsm_bts *bts, uint8_t obj_class,
|
||||
const struct abis_om_obj_inst *obj_inst)
|
||||
{
|
||||
struct gsm_bts_trx *trx;
|
||||
struct gsm_abis_mo *mo = NULL;
|
||||
|
||||
switch (obj_class) {
|
||||
case NM_OC_BTS:
|
||||
mo = &bts->mo;
|
||||
break;
|
||||
case NM_OC_RADIO_CARRIER:
|
||||
if (obj_inst->trx_nr >= bts->num_trx) {
|
||||
return NULL;
|
||||
}
|
||||
trx = gsm_bts_trx_num(bts, obj_inst->trx_nr);
|
||||
mo = &trx->mo;
|
||||
break;
|
||||
case NM_OC_BASEB_TRANSC:
|
||||
if (obj_inst->trx_nr >= bts->num_trx) {
|
||||
return NULL;
|
||||
}
|
||||
trx = gsm_bts_trx_num(bts, obj_inst->trx_nr);
|
||||
mo = &trx->bb_transc.mo;
|
||||
break;
|
||||
case NM_OC_CHANNEL:
|
||||
if (obj_inst->trx_nr >= bts->num_trx) {
|
||||
return NULL;
|
||||
}
|
||||
trx = gsm_bts_trx_num(bts, obj_inst->trx_nr);
|
||||
if (obj_inst->ts_nr >= TRX_NR_TS)
|
||||
return NULL;
|
||||
mo = &trx->ts[obj_inst->ts_nr].mo;
|
||||
break;
|
||||
case NM_OC_SITE_MANAGER:
|
||||
mo = &bts->site_mgr.mo;
|
||||
break;
|
||||
case NM_OC_BS11:
|
||||
switch (obj_inst->bts_nr) {
|
||||
case BS11_OBJ_CCLK:
|
||||
mo = &bts->bs11.cclk.mo;
|
||||
break;
|
||||
case BS11_OBJ_BBSIG:
|
||||
if (obj_inst->ts_nr > bts->num_trx)
|
||||
return NULL;
|
||||
trx = gsm_bts_trx_num(bts, obj_inst->trx_nr);
|
||||
mo = &trx->bs11.bbsig.mo;
|
||||
break;
|
||||
case BS11_OBJ_PA:
|
||||
if (obj_inst->ts_nr > bts->num_trx)
|
||||
return NULL;
|
||||
trx = gsm_bts_trx_num(bts, obj_inst->trx_nr);
|
||||
mo = &trx->bs11.pa.mo;
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
case NM_OC_BS11_RACK:
|
||||
mo = &bts->bs11.rack.mo;
|
||||
break;
|
||||
case NM_OC_BS11_ENVABTSE:
|
||||
if (obj_inst->trx_nr >= ARRAY_SIZE(bts->bs11.envabtse))
|
||||
return NULL;
|
||||
mo = &bts->bs11.envabtse[obj_inst->trx_nr].mo;
|
||||
break;
|
||||
case NM_OC_GPRS_NSE:
|
||||
mo = &bts->gprs.nse.mo;
|
||||
break;
|
||||
case NM_OC_GPRS_CELL:
|
||||
mo = &bts->gprs.cell.mo;
|
||||
break;
|
||||
case NM_OC_GPRS_NSVC:
|
||||
if (obj_inst->trx_nr >= ARRAY_SIZE(bts->gprs.nsvc))
|
||||
return NULL;
|
||||
mo = &bts->gprs.nsvc[obj_inst->trx_nr].mo;
|
||||
break;
|
||||
}
|
||||
return mo;
|
||||
}
|
||||
|
||||
/* obtain the gsm_nm_state data structure for a given object instance */
|
||||
struct gsm_nm_state *
|
||||
gsm_objclass2nmstate(struct gsm_bts *bts, uint8_t obj_class,
|
||||
const struct abis_om_obj_inst *obj_inst)
|
||||
{
|
||||
struct gsm_abis_mo *mo;
|
||||
|
||||
mo = gsm_objclass2mo(bts, obj_class, obj_inst);
|
||||
if (!mo)
|
||||
return NULL;
|
||||
|
||||
return &mo->nm_state;
|
||||
}
|
||||
|
||||
/* obtain the in-memory data structure of a given object instance */
|
||||
void *
|
||||
gsm_objclass2obj(struct gsm_bts *bts, uint8_t obj_class,
|
||||
const struct abis_om_obj_inst *obj_inst)
|
||||
{
|
||||
struct gsm_bts_trx *trx;
|
||||
void *obj = NULL;
|
||||
|
||||
switch (obj_class) {
|
||||
case NM_OC_BTS:
|
||||
obj = bts;
|
||||
break;
|
||||
case NM_OC_RADIO_CARRIER:
|
||||
if (obj_inst->trx_nr >= bts->num_trx) {
|
||||
return NULL;
|
||||
}
|
||||
trx = gsm_bts_trx_num(bts, obj_inst->trx_nr);
|
||||
obj = trx;
|
||||
break;
|
||||
case NM_OC_BASEB_TRANSC:
|
||||
if (obj_inst->trx_nr >= bts->num_trx) {
|
||||
return NULL;
|
||||
}
|
||||
trx = gsm_bts_trx_num(bts, obj_inst->trx_nr);
|
||||
obj = &trx->bb_transc;
|
||||
break;
|
||||
case NM_OC_CHANNEL:
|
||||
if (obj_inst->trx_nr >= bts->num_trx) {
|
||||
return NULL;
|
||||
}
|
||||
trx = gsm_bts_trx_num(bts, obj_inst->trx_nr);
|
||||
if (obj_inst->ts_nr >= TRX_NR_TS)
|
||||
return NULL;
|
||||
obj = &trx->ts[obj_inst->ts_nr];
|
||||
break;
|
||||
case NM_OC_SITE_MANAGER:
|
||||
obj = &bts->site_mgr;
|
||||
break;
|
||||
case NM_OC_GPRS_NSE:
|
||||
obj = &bts->gprs.nse;
|
||||
break;
|
||||
case NM_OC_GPRS_CELL:
|
||||
obj = &bts->gprs.cell;
|
||||
break;
|
||||
case NM_OC_GPRS_NSVC:
|
||||
if (obj_inst->trx_nr >= ARRAY_SIZE(bts->gprs.nsvc))
|
||||
return NULL;
|
||||
obj = &bts->gprs.nsvc[obj_inst->trx_nr];
|
||||
break;
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
/* See Table 10.5.25 of GSM04.08 */
|
||||
uint8_t gsm_pchan2chan_nr(enum gsm_phys_chan_config pchan,
|
||||
uint8_t ts_nr, uint8_t lchan_nr)
|
||||
{
|
||||
uint8_t cbits, chan_nr;
|
||||
|
||||
switch (pchan) {
|
||||
case GSM_PCHAN_TCH_F:
|
||||
case GSM_PCHAN_TCH_F_PDCH:
|
||||
OSMO_ASSERT(lchan_nr == 0);
|
||||
cbits = 0x01;
|
||||
break;
|
||||
case GSM_PCHAN_PDCH:
|
||||
OSMO_ASSERT(lchan_nr == 0);
|
||||
cbits = RSL_CHAN_OSMO_PDCH >> 3;
|
||||
break;
|
||||
case GSM_PCHAN_TCH_H:
|
||||
OSMO_ASSERT(lchan_nr < 2);
|
||||
cbits = 0x02;
|
||||
cbits += lchan_nr;
|
||||
break;
|
||||
case GSM_PCHAN_CCCH_SDCCH4:
|
||||
case GSM_PCHAN_CCCH_SDCCH4_CBCH:
|
||||
/*
|
||||
* As a special hack for BCCH, lchan_nr == 4 may be passed
|
||||
* here. This should never be sent in an RSL message.
|
||||
* See osmo-bts-xxx/oml.c:opstart_compl().
|
||||
*/
|
||||
if (lchan_nr == CCCH_LCHAN)
|
||||
chan_nr = 0;
|
||||
else
|
||||
OSMO_ASSERT(lchan_nr < 4);
|
||||
cbits = 0x04;
|
||||
cbits += lchan_nr;
|
||||
break;
|
||||
case GSM_PCHAN_SDCCH8_SACCH8C:
|
||||
case GSM_PCHAN_SDCCH8_SACCH8C_CBCH:
|
||||
OSMO_ASSERT(lchan_nr < 8);
|
||||
cbits = 0x08;
|
||||
cbits += lchan_nr;
|
||||
break;
|
||||
default:
|
||||
case GSM_PCHAN_CCCH:
|
||||
#ifdef ROLE_BSC
|
||||
OSMO_ASSERT(lchan_nr == 0);
|
||||
#else
|
||||
/*
|
||||
* FIXME: On octphy and litecell, we hit above assertion (see
|
||||
* Max's comment at https://gerrit.osmocom.org/589 ); disabled
|
||||
* for BTS until this is clarified; remove the #ifdef when it
|
||||
* is fixed.
|
||||
*/
|
||||
#warning "fix caller that passes lchan_nr != 0"
|
||||
#endif
|
||||
cbits = 0x10;
|
||||
break;
|
||||
}
|
||||
|
||||
chan_nr = (cbits << 3) | (ts_nr & 0x7);
|
||||
|
||||
return chan_nr;
|
||||
}
|
||||
|
||||
uint8_t gsm_lchan2chan_nr(const struct gsm_lchan *lchan)
|
||||
{
|
||||
enum gsm_phys_chan_config pchan = lchan->ts->pchan;
|
||||
if (pchan == GSM_PCHAN_TCH_F_TCH_H_PDCH)
|
||||
return gsm_lchan_as_pchan2chan_nr(lchan,
|
||||
lchan->ts->dyn.pchan_is);
|
||||
return gsm_pchan2chan_nr(lchan->ts->pchan, lchan->ts->nr, lchan->nr);
|
||||
}
|
||||
|
||||
uint8_t gsm_lchan_as_pchan2chan_nr(const struct gsm_lchan *lchan,
|
||||
enum gsm_phys_chan_config as_pchan)
|
||||
{
|
||||
if (lchan->ts->pchan == GSM_PCHAN_TCH_F_TCH_H_PDCH
|
||||
&& as_pchan == GSM_PCHAN_PDCH)
|
||||
return RSL_CHAN_OSMO_PDCH | (lchan->ts->nr & ~RSL_CHAN_NR_MASK);
|
||||
return gsm_pchan2chan_nr(as_pchan, lchan->ts->nr, lchan->nr);
|
||||
}
|
||||
|
||||
/* return the gsm_lchan for the CBCH (if it exists at all) */
|
||||
struct gsm_lchan *gsm_bts_get_cbch(struct gsm_bts *bts)
|
||||
{
|
||||
struct gsm_lchan *lchan = NULL;
|
||||
struct gsm_bts_trx *trx = bts->c0;
|
||||
|
||||
if (trx->ts[0].pchan == GSM_PCHAN_CCCH_SDCCH4_CBCH)
|
||||
lchan = &trx->ts[0].lchan[2];
|
||||
else {
|
||||
int i;
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (trx->ts[i].pchan == GSM_PCHAN_SDCCH8_SACCH8C_CBCH) {
|
||||
lchan = &trx->ts[i].lchan[2];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return lchan;
|
||||
}
|
||||
|
||||
/* determine logical channel based on TRX and channel number IE */
|
||||
struct gsm_lchan *rsl_lchan_lookup(struct gsm_bts_trx *trx, uint8_t chan_nr,
|
||||
int *rc)
|
||||
{
|
||||
uint8_t ts_nr = chan_nr & 0x07;
|
||||
uint8_t cbits = chan_nr >> 3;
|
||||
uint8_t lch_idx;
|
||||
struct gsm_bts_trx_ts *ts = &trx->ts[ts_nr];
|
||||
bool ok = true;
|
||||
|
||||
if (rc)
|
||||
*rc = -EINVAL;
|
||||
|
||||
if (cbits == 0x01) {
|
||||
lch_idx = 0; /* TCH/F */
|
||||
if (ts->pchan != GSM_PCHAN_TCH_F &&
|
||||
ts->pchan != GSM_PCHAN_PDCH &&
|
||||
ts->pchan != GSM_PCHAN_TCH_F_PDCH
|
||||
&& !(ts->pchan == GSM_PCHAN_TCH_F_TCH_H_PDCH
|
||||
&& (ts->dyn.pchan_is == GSM_PCHAN_TCH_F
|
||||
|| ts->dyn.pchan_want == GSM_PCHAN_TCH_F)))
|
||||
ok = false;
|
||||
} else if ((cbits & 0x1e) == 0x02) {
|
||||
lch_idx = cbits & 0x1; /* TCH/H */
|
||||
if (ts->pchan != GSM_PCHAN_TCH_H
|
||||
&& !(ts->pchan == GSM_PCHAN_TCH_F_TCH_H_PDCH
|
||||
&& (ts->dyn.pchan_is == GSM_PCHAN_TCH_H
|
||||
|| ts->dyn.pchan_want == GSM_PCHAN_TCH_H)))
|
||||
ok = false;
|
||||
} else if ((cbits & 0x1c) == 0x04) {
|
||||
lch_idx = cbits & 0x3; /* SDCCH/4 */
|
||||
if (ts->pchan != GSM_PCHAN_CCCH_SDCCH4 &&
|
||||
ts->pchan != GSM_PCHAN_CCCH_SDCCH4_CBCH)
|
||||
ok = false;
|
||||
} else if ((cbits & 0x18) == 0x08) {
|
||||
lch_idx = cbits & 0x7; /* SDCCH/8 */
|
||||
if (ts->pchan != GSM_PCHAN_SDCCH8_SACCH8C &&
|
||||
ts->pchan != GSM_PCHAN_SDCCH8_SACCH8C_CBCH)
|
||||
ok = false;
|
||||
} else if (cbits == 0x10 || cbits == 0x11 || cbits == 0x12) {
|
||||
lch_idx = 0;
|
||||
if (ts->pchan != GSM_PCHAN_CCCH &&
|
||||
ts->pchan != GSM_PCHAN_CCCH_SDCCH4 &&
|
||||
ts->pchan != GSM_PCHAN_CCCH_SDCCH4_CBCH)
|
||||
ok = false;
|
||||
/* FIXME: we should not return first sdcch4 !!! */
|
||||
} else if ((chan_nr & RSL_CHAN_NR_MASK) == RSL_CHAN_OSMO_PDCH) {
|
||||
lch_idx = 0;
|
||||
if (ts->pchan != GSM_PCHAN_TCH_F_TCH_H_PDCH)
|
||||
ok = false;
|
||||
} else
|
||||
return NULL;
|
||||
|
||||
if (rc && ok)
|
||||
*rc = 0;
|
||||
|
||||
return &ts->lchan[lch_idx];
|
||||
}
|
||||
|
||||
static const uint8_t subslots_per_pchan[] = {
|
||||
[GSM_PCHAN_NONE] = 0,
|
||||
[GSM_PCHAN_CCCH] = 0,
|
||||
[GSM_PCHAN_PDCH] = 0,
|
||||
[GSM_PCHAN_CCCH_SDCCH4] = 4,
|
||||
[GSM_PCHAN_TCH_F] = 1,
|
||||
[GSM_PCHAN_TCH_H] = 2,
|
||||
[GSM_PCHAN_SDCCH8_SACCH8C] = 8,
|
||||
[GSM_PCHAN_CCCH_SDCCH4_CBCH] = 4,
|
||||
[GSM_PCHAN_SDCCH8_SACCH8C_CBCH] = 8,
|
||||
/*
|
||||
* GSM_PCHAN_TCH_F_PDCH and GSM_PCHAN_TCH_F_TCH_H_PDCH should not be
|
||||
* part of this, those TS are handled according to their dynamic state.
|
||||
*/
|
||||
};
|
||||
|
||||
/*! Return the actual pchan type, also heeding dynamic TS. */
|
||||
enum gsm_phys_chan_config ts_pchan(struct gsm_bts_trx_ts *ts)
|
||||
{
|
||||
switch (ts->pchan) {
|
||||
case GSM_PCHAN_TCH_F_TCH_H_PDCH:
|
||||
return ts->dyn.pchan_is;
|
||||
case GSM_PCHAN_TCH_F_PDCH:
|
||||
if (ts->flags & TS_F_PDCH_ACTIVE)
|
||||
return GSM_PCHAN_PDCH;
|
||||
else
|
||||
return GSM_PCHAN_TCH_F;
|
||||
default:
|
||||
return ts->pchan;
|
||||
}
|
||||
}
|
||||
|
||||
/*! According to ts->pchan and possibly ts->dyn_pchan, return the number of
|
||||
* logical channels available in the timeslot. */
|
||||
uint8_t ts_subslots(struct gsm_bts_trx_ts *ts)
|
||||
{
|
||||
return subslots_per_pchan[ts_pchan(ts)];
|
||||
}
|
||||
|
||||
static bool pchan_is_tch(enum gsm_phys_chan_config pchan)
|
||||
{
|
||||
switch (pchan) {
|
||||
case GSM_PCHAN_TCH_F:
|
||||
case GSM_PCHAN_TCH_H:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool ts_is_tch(struct gsm_bts_trx_ts *ts)
|
||||
{
|
||||
return pchan_is_tch(ts_pchan(ts));
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include <osmo-bts/rsl.h>
|
||||
#include <osmo-bts/logging.h>
|
||||
#include <osmo-bts/handover.h>
|
||||
#include <osmo-bts/l1sap.h>
|
||||
|
||||
/* Transmit a handover related PHYS INFO on given lchan */
|
||||
static int ho_tx_phys_info(struct gsm_lchan *lchan)
|
||||
@@ -105,16 +106,24 @@ void handover_rach(struct gsm_lchan *lchan, uint8_t ra, uint8_t acc_delay)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Ignore handover on channels other than DCCH and SACCH */
|
||||
if (lchan->type != GSM_LCHAN_SDCCH && lchan->type != GSM_LCHAN_TCH_H &&
|
||||
lchan->type != GSM_LCHAN_TCH_F) {
|
||||
LOGP(DHO, LOGL_ERROR, "%s handover RACH received on %s?!\n",
|
||||
gsm_lchan_name(lchan), gsm_lchant_name(lchan->type));
|
||||
return;
|
||||
}
|
||||
|
||||
LOGP(DHO, LOGL_NOTICE,
|
||||
"%s RACH on dedicated channel received with TA=%u\n",
|
||||
gsm_lchan_name(lchan), acc_delay);
|
||||
"%s RACH on dedicated channel type %s received with TA=%u, ref=%u\n",
|
||||
gsm_lchan_name(lchan), gsm_lchant_name(lchan->type), acc_delay, ra);
|
||||
|
||||
/* Set timing advance */
|
||||
lchan->rqd_ta = acc_delay;
|
||||
|
||||
/* Stop handover detection, wait for valid frame */
|
||||
lchan->ho.active = HANDOVER_WAIT_FRAME;
|
||||
if (bts_model_rsl_chan_mod(lchan) != 0) {
|
||||
if (l1sap_chan_modify(lchan->ts->trx, gsm_lchan2chan_nr(lchan)) != 0) {
|
||||
LOGP(DHO, LOGL_ERROR,
|
||||
"%s failed to modify channel after handover\n",
|
||||
gsm_lchan_name(lchan));
|
||||
|
||||
1398
src/common/l1sap.c
Normal file
1398
src/common/l1sap.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -19,9 +19,31 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <osmocom/core/logging.h>
|
||||
#include <osmo-bts/logging.h>
|
||||
#include <osmo-bts/gsm_data.h>
|
||||
|
||||
void lchan_set_state(struct gsm_lchan *lchan, enum gsm_lchan_state state)
|
||||
{
|
||||
DEBUGP(DL1C, "%s state %s -> %s\n",
|
||||
gsm_lchan_name(lchan),
|
||||
gsm_lchans_name(lchan->state),
|
||||
gsm_lchans_name(state));
|
||||
lchan->state = state;
|
||||
}
|
||||
|
||||
bool ts_is_pdch(const struct gsm_bts_trx_ts *ts)
|
||||
{
|
||||
switch (ts->pchan) {
|
||||
case GSM_PCHAN_PDCH:
|
||||
return true;
|
||||
case GSM_PCHAN_TCH_F_PDCH:
|
||||
return (ts->flags & TS_F_PDCH_ACTIVE)
|
||||
&& !(ts->flags & TS_F_PDCH_PENDING_MASK);
|
||||
case GSM_PCHAN_TCH_F_TCH_H_PDCH:
|
||||
return ts->dyn.pchan_is == GSM_PCHAN_PDCH
|
||||
&& ts->dyn.pchan_want == ts->dyn.pchan_is;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,6 +107,18 @@ static struct log_info_cat bts_log_info_cat[] = {
|
||||
.color = "\033[0;37m",
|
||||
.enabled = 1, .loglevel = LOGL_NOTICE,
|
||||
},
|
||||
[DTRX] = {
|
||||
.name = "DTRX",
|
||||
.description = "TRX interface",
|
||||
.color = "\033[1;33m",
|
||||
.enabled = 1, .loglevel = LOGL_NOTICE,
|
||||
},
|
||||
[DLOOP] = {
|
||||
.name = "DLOOP",
|
||||
.description = "Control loops",
|
||||
.color = "\033[0;34m",
|
||||
.enabled = 1, .loglevel = LOGL_NOTICE,
|
||||
},
|
||||
#if 0
|
||||
[DNS] = {
|
||||
.name = "DNS",
|
||||
@@ -124,6 +136,12 @@ static struct log_info_cat bts_log_info_cat[] = {
|
||||
.enabled = 1, .loglevel = LOGL_DEBUG,
|
||||
},
|
||||
#endif
|
||||
[DSUM] = {
|
||||
.name = "DSUM",
|
||||
.description = "DSUM",
|
||||
.loglevel = LOGL_NOTICE,
|
||||
.enabled = 1,
|
||||
},
|
||||
};
|
||||
|
||||
const struct log_info bts_log_info = {
|
||||
|
||||
365
src/common/main.c
Normal file
365
src/common/main.c
Normal file
@@ -0,0 +1,365 @@
|
||||
/* Main program for Osmocom BTS */
|
||||
|
||||
/* (C) 2011-2016 by Harald Welte <laforge@gnumonks.org>
|
||||
*
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <getopt.h>
|
||||
#include <limits.h>
|
||||
#include <sys/signal.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sched.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <osmocom/core/talloc.h>
|
||||
#include <osmocom/core/application.h>
|
||||
#include <osmocom/vty/telnet_interface.h>
|
||||
#include <osmocom/vty/logging.h>
|
||||
#include <osmocom/core/gsmtap_util.h>
|
||||
#include <osmocom/core/gsmtap.h>
|
||||
|
||||
#include <osmo-bts/gsm_data.h>
|
||||
#include <osmo-bts/phy_link.h>
|
||||
#include <osmo-bts/logging.h>
|
||||
#include <osmo-bts/abis.h>
|
||||
#include <osmo-bts/bts.h>
|
||||
#include <osmo-bts/vty.h>
|
||||
#include <osmo-bts/l1sap.h>
|
||||
#include <osmo-bts/bts_model.h>
|
||||
#include <osmo-bts/pcu_if.h>
|
||||
#include <osmo-bts/control_if.h>
|
||||
#include <osmocom/ctrl/control_if.h>
|
||||
#include <osmocom/ctrl/ports.h>
|
||||
#include <osmocom/ctrl/control_vty.h>
|
||||
#include <osmo-bts/oml.h>
|
||||
|
||||
int quit = 0;
|
||||
static const char *config_file = "osmo-bts.cfg";
|
||||
static int daemonize = 0;
|
||||
static int rt_prio = -1;
|
||||
static int trx_num = 1;
|
||||
static char *gsmtap_ip = 0;
|
||||
extern int g_vty_port_num;
|
||||
|
||||
static void print_help()
|
||||
{
|
||||
printf( "Some useful options:\n"
|
||||
" -h --help this text\n"
|
||||
" -d --debug MASK Enable debugging (e.g. -d DRSL:DOML:DLAPDM)\n"
|
||||
" -D --daemonize For the process into a background daemon\n"
|
||||
" -c --config-file Specify the filename of the config file\n"
|
||||
" -s --disable-color Don't use colors in stderr log output\n"
|
||||
" -T --timestamp Prefix every log line with a timestamp\n"
|
||||
" -V --version Print version information and exit\n"
|
||||
" -e --log-level Set a global log-level\n"
|
||||
" -r --realtime PRIO Use SCHED_RR with the specified priority\n"
|
||||
" -i --gsmtap-ip The destination IP used for GSMTAP.\n"
|
||||
" -t --trx-num Set number of TRX (default=%d)\n",
|
||||
trx_num
|
||||
);
|
||||
bts_model_print_help();
|
||||
}
|
||||
|
||||
/* FIXME: finally get some option parsing code into libosmocore */
|
||||
static void handle_options(int argc, char **argv)
|
||||
{
|
||||
char *argv_out[argc];
|
||||
int argc_out = 0;
|
||||
|
||||
argv_out[argc_out++] = argv[0];
|
||||
|
||||
/* disable generation of error messages on encountering unknown
|
||||
* options */
|
||||
opterr = 0;
|
||||
|
||||
while (1) {
|
||||
int option_idx = 0, c;
|
||||
static const struct option long_options[] = {
|
||||
/* FIXME: all those are generic Osmocom app options */
|
||||
{ "help", 0, 0, 'h' },
|
||||
{ "debug", 1, 0, 'd' },
|
||||
{ "daemonize", 0, 0, 'D' },
|
||||
{ "config-file", 1, 0, 'c' },
|
||||
{ "disable-color", 0, 0, 's' },
|
||||
{ "timestamp", 0, 0, 'T' },
|
||||
{ "version", 0, 0, 'V' },
|
||||
{ "log-level", 1, 0, 'e' },
|
||||
/* FIXME: generic BTS app options */
|
||||
{ "gsmtap-ip", 1, 0, 'i' },
|
||||
{ "trx-num", 1, 0, 't' },
|
||||
{ "realtime", 1, 0, 'r' },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
c = getopt_long(argc, argv, "-hc:d:Dc:sTVe:i:t:r:",
|
||||
long_options, &option_idx);
|
||||
if (c == -1)
|
||||
break;
|
||||
|
||||
switch (c) {
|
||||
case 'h':
|
||||
print_help();
|
||||
exit(0);
|
||||
break;
|
||||
case 's':
|
||||
log_set_use_color(osmo_stderr_target, 0);
|
||||
break;
|
||||
case 'd':
|
||||
log_parse_category_mask(osmo_stderr_target, optarg);
|
||||
break;
|
||||
case 'D':
|
||||
daemonize = 1;
|
||||
break;
|
||||
case 'c':
|
||||
config_file = optarg;
|
||||
break;
|
||||
case 'T':
|
||||
log_set_print_timestamp(osmo_stderr_target, 1);
|
||||
break;
|
||||
case 'V':
|
||||
print_version(1);
|
||||
exit(0);
|
||||
break;
|
||||
case 'e':
|
||||
log_set_log_level(osmo_stderr_target, atoi(optarg));
|
||||
break;
|
||||
case 'r':
|
||||
rt_prio = atoi(optarg);
|
||||
break;
|
||||
case 'i':
|
||||
gsmtap_ip = optarg;
|
||||
break;
|
||||
case 't':
|
||||
trx_num = atoi(optarg);
|
||||
if (trx_num < 1)
|
||||
trx_num = 1;
|
||||
break;
|
||||
case '?':
|
||||
case 1:
|
||||
/* prepare argv[] for bts_model */
|
||||
argv_out[argc_out++] = argv[optind-1];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* re-set opt-ind for new parsig round */
|
||||
optind = 1;
|
||||
/* enable error-checking for the following getopt call */
|
||||
opterr = 1;
|
||||
if (bts_model_handle_options(argc_out, argv_out)) {
|
||||
print_help();
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
static struct gsm_bts *bts;
|
||||
|
||||
static void signal_handler(int signal)
|
||||
{
|
||||
fprintf(stderr, "signal %u received\n", signal);
|
||||
|
||||
switch (signal) {
|
||||
case SIGINT:
|
||||
case SIGTERM:
|
||||
if (!quit) {
|
||||
oml_fail_rep(OSMO_EVT_CRIT_PROC_STOP,
|
||||
"BTS: SIGINT received -> shutdown");
|
||||
bts_shutdown(bts, "SIGINT");
|
||||
}
|
||||
quit++;
|
||||
break;
|
||||
case SIGABRT:
|
||||
case SIGUSR1:
|
||||
case SIGUSR2:
|
||||
oml_fail_rep(OSMO_EVT_CRIT_PROC_STOP,
|
||||
"BTS: signal %d (%s) received", signal,
|
||||
strsignal(signal));
|
||||
talloc_report_full(tall_bts_ctx, stderr);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int write_pid_file(char *procname)
|
||||
{
|
||||
FILE *outf;
|
||||
char tmp[PATH_MAX+1];
|
||||
|
||||
snprintf(tmp, sizeof(tmp)-1, "/var/run/%s.pid", procname);
|
||||
tmp[PATH_MAX-1] = '\0';
|
||||
|
||||
outf = fopen(tmp, "w");
|
||||
if (!outf)
|
||||
return -1;
|
||||
|
||||
fprintf(outf, "%d\n", getpid());
|
||||
|
||||
fclose(outf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bts_main(int argc, char **argv)
|
||||
{
|
||||
struct gsm_bts_role_bts *btsb;
|
||||
struct gsm_bts_trx *trx;
|
||||
struct e1inp_line *line;
|
||||
int rc, i;
|
||||
|
||||
printf("((*))\n |\n / \\ OsmoBTS\n");
|
||||
|
||||
tall_bts_ctx = talloc_named_const(NULL, 1, "OsmoBTS context");
|
||||
msgb_talloc_ctx_init(tall_bts_ctx, 100*1024);
|
||||
|
||||
bts_log_init(NULL);
|
||||
vty_init(&bts_vty_info);
|
||||
ctrl_vty_init(tall_bts_ctx);
|
||||
|
||||
handle_options(argc, argv);
|
||||
|
||||
bts = gsm_bts_alloc(tall_bts_ctx, 0);
|
||||
if (!bts) {
|
||||
fprintf(stderr, "Failed to create BTS structure\n");
|
||||
exit(1);
|
||||
}
|
||||
for (i = 1; i < trx_num; i++) {
|
||||
trx = gsm_bts_trx_alloc(bts);
|
||||
if (!trx) {
|
||||
fprintf(stderr, "Failed to create TRX structure\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
e1inp_vty_init();
|
||||
bts_vty_init(bts, &bts_log_info);
|
||||
|
||||
/* enable realtime priority for us */
|
||||
if (rt_prio != -1) {
|
||||
struct sched_param param;
|
||||
|
||||
memset(¶m, 0, sizeof(param));
|
||||
param.sched_priority = rt_prio;
|
||||
rc = sched_setscheduler(getpid(), SCHED_RR, ¶m);
|
||||
if (rc != 0) {
|
||||
fprintf(stderr, "Setting SCHED_RR priority(%d) failed: %s\n",
|
||||
param.sched_priority, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (gsmtap_ip) {
|
||||
gsmtap = gsmtap_source_init(gsmtap_ip, GSMTAP_UDP_PORT, 1);
|
||||
if (!gsmtap) {
|
||||
fprintf(stderr, "Failed during gsmtap_init()\n");
|
||||
exit(1);
|
||||
}
|
||||
gsmtap_source_add_sink(gsmtap);
|
||||
}
|
||||
|
||||
if (bts_init(bts) < 0) {
|
||||
fprintf(stderr, "unable to open bts\n");
|
||||
exit(1);
|
||||
}
|
||||
btsb = bts_role_bts(bts);
|
||||
|
||||
abis_init(bts);
|
||||
|
||||
rc = vty_read_config_file(config_file, NULL);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "Failed to parse the config file: '%s'\n",
|
||||
config_file);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!phy_link_by_num(0)) {
|
||||
fprintf(stderr, "You need to configure at least phy0\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
llist_for_each_entry(trx, &bts->trx_list, list) {
|
||||
if (!trx->role_bts.l1h) {
|
||||
fprintf(stderr, "TRX %u has no associated PHY instance\n",
|
||||
trx->nr);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
write_pid_file("osmo-bts");
|
||||
|
||||
bts_controlif_setup(bts, ctrl_vty_get_bind_addr(), OSMO_CTRL_PORT_BTS);
|
||||
|
||||
rc = telnet_init_dynif(tall_bts_ctx, NULL, vty_get_bind_addr(),
|
||||
g_vty_port_num);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "Error initializing telnet\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (pcu_sock_init(btsb->pcu.sock_path)) {
|
||||
fprintf(stderr, "PCU L1 socket failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
signal(SIGINT, &signal_handler);
|
||||
signal(SIGTERM, &signal_handler);
|
||||
//signal(SIGABRT, &signal_handler);
|
||||
signal(SIGUSR1, &signal_handler);
|
||||
signal(SIGUSR2, &signal_handler);
|
||||
osmo_init_ignore_signals();
|
||||
|
||||
if (!btsb->bsc_oml_host) {
|
||||
fprintf(stderr, "Cannot start BTS without knowing BSC OML IP\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
line = abis_open(bts, btsb->bsc_oml_host, "sysmoBTS");
|
||||
if (!line) {
|
||||
fprintf(stderr, "unable to connect to BSC\n");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
rc = phy_links_open();
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "unable ot open PHY link(s)\n");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
if (daemonize) {
|
||||
rc = osmo_daemonize();
|
||||
if (rc < 0) {
|
||||
perror("Error during daemonize");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
while (quit < 2) {
|
||||
log_reset_context();
|
||||
osmo_select_main(0);
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@@ -8,19 +8,42 @@
|
||||
#include <osmo-bts/logging.h>
|
||||
#include <osmo-bts/measurement.h>
|
||||
|
||||
/* TS 05.08, Chapter 8.4.1 */
|
||||
/* measurement period ends at fn % 104 == ? */
|
||||
/* Measurment reporting period and mapping of SACCH message block for TCHF
|
||||
* and TCHH chan As per in 3GPP TS 45.008, secton 8.4.1.
|
||||
*
|
||||
* Timeslot number (TN) TDMA frame number (FN) modulo 104
|
||||
* Half rate, Half rate, Reporting SACCH
|
||||
* Full Rate subch.0 subch.1 period Message block
|
||||
* 0 0 and 1 0 to 103 12, 38, 64, 90
|
||||
* 1 0 and 1 13 to 12 25, 51, 77, 103
|
||||
* 2 2 and 3 26 to 25 38, 64, 90, 12
|
||||
* 3 2 and 3 39 to 38 51, 77, 103, 25
|
||||
* 4 4 and 5 52 to 51 64, 90, 12, 38
|
||||
* 5 4 and 5 65 to 64 77, 103, 25, 51
|
||||
* 6 6 and 7 78 to 77 90, 12, 38, 64
|
||||
* 7 6 and 7 91 to 90 103, 25, 51, 77 */
|
||||
|
||||
static const uint8_t tchf_meas_rep_fn104[] = {
|
||||
[0] = 103,
|
||||
[1] = 12,
|
||||
[2] = 25,
|
||||
[3] = 38,
|
||||
[4] = 51,
|
||||
[5] = 64,
|
||||
[6] = 77,
|
||||
[7] = 90,
|
||||
[0] = 90,
|
||||
[1] = 103,
|
||||
[2] = 12,
|
||||
[3] = 25,
|
||||
[4] = 38,
|
||||
[5] = 51,
|
||||
[6] = 64,
|
||||
[7] = 77,
|
||||
};
|
||||
static const uint8_t tchh0_meas_rep_fn104[] = {
|
||||
[0] = 90,
|
||||
[1] = 90,
|
||||
[2] = 12,
|
||||
[3] = 12,
|
||||
[4] = 38,
|
||||
[5] = 38,
|
||||
[6] = 64,
|
||||
[7] = 64,
|
||||
};
|
||||
static const uint8_t tchh1_meas_rep_fn104[] = {
|
||||
[0] = 103,
|
||||
[1] = 103,
|
||||
[2] = 25,
|
||||
@@ -30,59 +53,130 @@ static const uint8_t tchh0_meas_rep_fn104[] = {
|
||||
[6] = 77,
|
||||
[7] = 77,
|
||||
};
|
||||
static const uint8_t tchh1_meas_rep_fn104[] = {
|
||||
[0] = 12,
|
||||
[1] = 12,
|
||||
[2] = 38,
|
||||
[3] = 38,
|
||||
[4] = 64,
|
||||
[5] = 64,
|
||||
[6] = 90,
|
||||
[7] = 90,
|
||||
|
||||
/* Measurment reporting period for SDCCH8 and SDCCH4 chan
|
||||
* As per in 3GPP TS 45.008, section 8.4.2.
|
||||
*
|
||||
* Logical Chan TDMA frame number
|
||||
* (FN) modulo 102
|
||||
*
|
||||
* SDCCH/8 12 to 11
|
||||
* SDCCH/4 37 to 36
|
||||
*/
|
||||
|
||||
/* Added interleve offset to Meas period end Fn which
|
||||
* would reduce the Meas Res msg load at Abis */
|
||||
|
||||
static const uint8_t sdcch8_meas_rep_fn102[] = {
|
||||
[0] = 11 + 7,
|
||||
[1] = 11 + 11,
|
||||
[2] = 11 + 15,
|
||||
[3] = 11 + 19,
|
||||
[4] = 11 + 23,
|
||||
[5] = 11 + 27,
|
||||
[6] = 11 + 31,
|
||||
[7] = 11 + 35
|
||||
};
|
||||
|
||||
/* determine if a measurement period ends at the given frame number */
|
||||
static int is_meas_complete(enum gsm_phys_chan_config pchan, unsigned int ts,
|
||||
unsigned int subch, uint32_t fn)
|
||||
static const uint8_t sdcch4_meas_rep_fn102[] = {
|
||||
[0] = 36 + 4,
|
||||
[1] = 36 + 8,
|
||||
[2] = 36 + 14,
|
||||
[3] = 36 + 18
|
||||
};
|
||||
|
||||
/* Note: The reporting of the measurement results is done via the SACCH channel.
|
||||
* The measurement interval is not alligned with the interval in which the
|
||||
* SACCH is tranmitted. When we receive the measurement indication with the
|
||||
* SACCH block, the coresponding measurement interval will already have ended
|
||||
* and we will get the results late, but on spot with the beginning of the
|
||||
* next measurement interval.
|
||||
*
|
||||
* For example: We get a measurement indication on FN%104=38 in TS=2. Then we
|
||||
* will have to look at 3GPP TS 45.008, secton 8.4.1 (or 3GPP TS 05.02 Clause 7
|
||||
* Table 1 of 9) what value we need to feed into the lookup tables in order to
|
||||
* detect the measurement period ending. In this example the "real" ending
|
||||
* was on FN%104=12. This is the value we have to look for in
|
||||
* tchf_meas_rep_fn104 to know that a measurement period has just ended. */
|
||||
|
||||
/* See also 3GPP TS 05.02 Clause 7 Table 1 of 9:
|
||||
* Mapping of logical channels onto physical channels (see subclauses 6.3, 6.4, 6.5) */
|
||||
static uint8_t translate_tch_meas_rep_fn104(uint8_t fn_mod)
|
||||
{
|
||||
unsigned int fn_mod;
|
||||
switch (fn_mod) {
|
||||
case 25:
|
||||
return 103;
|
||||
case 38:
|
||||
return 12;
|
||||
case 51:
|
||||
return 25;
|
||||
case 64:
|
||||
return 38;
|
||||
case 77:
|
||||
return 51;
|
||||
case 90:
|
||||
return 64;
|
||||
case 103:
|
||||
return 77;
|
||||
case 12:
|
||||
return 90;
|
||||
}
|
||||
|
||||
/* Invalid / not of interest */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* determine if a measurement period ends at the given frame number */
|
||||
static int is_meas_complete(struct gsm_lchan *lchan, uint32_t fn)
|
||||
{
|
||||
unsigned int fn_mod = -1;
|
||||
const uint8_t *tbl;
|
||||
int rc = 0;
|
||||
enum gsm_phys_chan_config pchan = ts_pchan(lchan->ts);
|
||||
|
||||
if (ts >= 8)
|
||||
if (lchan->ts->nr >= 8)
|
||||
return -EINVAL;
|
||||
if (pchan >= _GSM_PCHAN_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
switch (pchan) {
|
||||
case GSM_PCHAN_TCH_F:
|
||||
fn_mod = fn % 104;
|
||||
if (tchf_meas_rep_fn104[ts] == fn_mod)
|
||||
fn_mod = translate_tch_meas_rep_fn104(fn % 104);
|
||||
if (tchf_meas_rep_fn104[lchan->ts->nr] == fn_mod)
|
||||
rc = 1;
|
||||
break;
|
||||
case GSM_PCHAN_TCH_H:
|
||||
fn_mod = fn % 104;
|
||||
if (subch == 0)
|
||||
fn_mod = translate_tch_meas_rep_fn104(fn % 104);
|
||||
if (lchan->nr == 0)
|
||||
tbl = tchh0_meas_rep_fn104;
|
||||
else
|
||||
tbl = tchh1_meas_rep_fn104;
|
||||
if (tbl[ts] == fn_mod)
|
||||
if (tbl[lchan->ts->nr] == fn_mod)
|
||||
rc = 1;
|
||||
break;
|
||||
case GSM_PCHAN_SDCCH8_SACCH8C:
|
||||
case GSM_PCHAN_SDCCH8_SACCH8C_CBCH:
|
||||
fn_mod = fn % 102;
|
||||
if (fn_mod == 11)
|
||||
if (sdcch8_meas_rep_fn102[lchan->nr] == fn_mod)
|
||||
rc = 1;
|
||||
break;
|
||||
case GSM_PCHAN_CCCH_SDCCH4:
|
||||
case GSM_PCHAN_CCCH_SDCCH4_CBCH:
|
||||
fn_mod = fn % 102;
|
||||
if (fn_mod == 36)
|
||||
if (sdcch4_meas_rep_fn102[lchan->nr] == fn_mod)
|
||||
rc = 1;
|
||||
break;
|
||||
default:
|
||||
rc = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (rc == 1) {
|
||||
DEBUGP(DMEAS,
|
||||
"%s meas period end fn:%u, fn_mod:%i, status:%d, pchan:%s\n",
|
||||
gsm_lchan_name(lchan), fn, fn_mod, rc, gsm_pchan_name(pchan));
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -93,13 +187,16 @@ int lchan_new_ul_meas(struct gsm_lchan *lchan, struct bts_ul_meas *ulm)
|
||||
gsm_lchan_name(lchan), lchan->meas.num_ul_meas);
|
||||
|
||||
if (lchan->state != LCHAN_S_ACTIVE) {
|
||||
LOGP(DMEAS, LOGL_NOTICE, "%s measurement during state: %s\n",
|
||||
gsm_lchan_name(lchan), gsm_lchans_name(lchan->state));
|
||||
LOGP(DMEAS, LOGL_NOTICE,
|
||||
"%s measurement during state: %s, num_ul_meas=%d\n",
|
||||
gsm_lchan_name(lchan), gsm_lchans_name(lchan->state),
|
||||
lchan->meas.num_ul_meas);
|
||||
}
|
||||
|
||||
if (lchan->meas.num_ul_meas >= ARRAY_SIZE(lchan->meas.uplink)) {
|
||||
LOGP(DMEAS, LOGL_NOTICE, "%s no space for uplink measurement\n",
|
||||
gsm_lchan_name(lchan));
|
||||
LOGP(DMEAS, LOGL_NOTICE,
|
||||
"%s no space for uplink measurement, num_ul_meas=%d\n",
|
||||
gsm_lchan_name(lchan), lchan->meas.num_ul_meas);
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
@@ -112,7 +209,20 @@ int lchan_new_ul_meas(struct gsm_lchan *lchan, struct bts_ul_meas *ulm)
|
||||
/* input: BER in steps of .01%, i.e. percent/100 */
|
||||
static uint8_t ber10k_to_rxqual(uint32_t ber10k)
|
||||
{
|
||||
/* 05.08 / 8.2.4 */
|
||||
/* Eight levels of Rx quality are defined and are mapped to the
|
||||
* equivalent BER before channel decoding, as per in 3GPP TS 45.008,
|
||||
* secton 8.2.4.
|
||||
*
|
||||
* RxQual: BER Range:
|
||||
* RXQUAL_0 BER < 0,2 % Assumed value = 0,14 %
|
||||
* RXQUAL_1 0,2 % < BER < 0,4 % Assumed value = 0,28 %
|
||||
* RXQUAL_2 0,4 % < BER < 0,8 % Assumed value = 0,57 %
|
||||
* RXQUAL_3 0,8 % < BER < 1,6 % Assumed value = 1,13 %
|
||||
* RXQUAL_4 1,6 % < BER < 3,2 % Assumed value = 2,26 %
|
||||
* RXQUAL_5 3,2 % < BER < 6,4 % Assumed value = 4,53 %
|
||||
* RXQUAL_6 6,4 % < BER < 12,8 % Assumed value = 9,05 %
|
||||
* RXQUAL_7 12,8 % < BER Assumed value = 18,10 % */
|
||||
|
||||
if (ber10k < 20)
|
||||
return 0;
|
||||
if (ber10k < 40)
|
||||
@@ -130,7 +240,51 @@ static uint8_t ber10k_to_rxqual(uint32_t ber10k)
|
||||
return 7;
|
||||
}
|
||||
|
||||
static int lchan_meas_check_compute(struct gsm_lchan *lchan, uint32_t fn)
|
||||
/* Update order TA at end of meas period */
|
||||
static void lchan_meas_update_ordered_TA(struct gsm_lchan *lchan,
|
||||
int32_t taqb_sum)
|
||||
{
|
||||
int32_t ms_timing_offset = 0;
|
||||
uint8_t l1_info_valid;
|
||||
|
||||
l1_info_valid = lchan->meas.flags & LC_UL_M_F_L1_VALID;
|
||||
|
||||
if (l1_info_valid) {
|
||||
DEBUGP(DMEAS,
|
||||
"%s Update TA TimingOffset_Mean:%d, UL RX TA:%d, DL ordered TA:%d, flags:%d \n",
|
||||
gsm_lchan_name(lchan), taqb_sum, lchan->meas.l1_info[1],
|
||||
lchan->rqd_ta, lchan->meas.flags);
|
||||
|
||||
ms_timing_offset =
|
||||
taqb_sum + (lchan->meas.l1_info[1] - lchan->rqd_ta);
|
||||
|
||||
if (ms_timing_offset > 0) {
|
||||
if (lchan->rqd_ta < MEAS_MAX_TIMING_ADVANCE) {
|
||||
/* MS is moving away from BTS.
|
||||
* So increment Ordered TA by 1 */
|
||||
lchan->rqd_ta++;
|
||||
}
|
||||
} else if (ms_timing_offset < 0) {
|
||||
if (lchan->rqd_ta > MEAS_MIN_TIMING_ADVANCE) {
|
||||
/* MS is moving toward BTS. So decrement
|
||||
* Ordered TA by 1 */
|
||||
lchan->rqd_ta--;
|
||||
}
|
||||
}
|
||||
|
||||
DEBUGP(DMEAS,
|
||||
"%s New Update TA--> TimingOff_diff:%d, UL RX TA:%d, DL ordered TA:%d \n",
|
||||
gsm_lchan_name(lchan), ms_timing_offset,
|
||||
lchan->meas.l1_info[1], lchan->rqd_ta);
|
||||
}
|
||||
|
||||
/* Clear L1 INFO valid flag at Meas period end */
|
||||
lchan->meas.flags &= ~LC_UL_M_F_L1_VALID;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int lchan_meas_check_compute(struct gsm_lchan *lchan, uint32_t fn)
|
||||
{
|
||||
struct gsm_meas_rep_unidir *mru;
|
||||
uint32_t ber_full_sum = 0;
|
||||
@@ -142,8 +296,7 @@ static int lchan_meas_check_compute(struct gsm_lchan *lchan, uint32_t fn)
|
||||
int i;
|
||||
|
||||
/* if measurement period is not complete, abort */
|
||||
if (!is_meas_complete(lchan->ts->pchan, lchan->ts->nr,
|
||||
lchan->nr, fn))
|
||||
if (!is_meas_complete(lchan, fn))
|
||||
return 0;
|
||||
|
||||
/* if there are no measurements, skip computation */
|
||||
@@ -175,6 +328,9 @@ static int lchan_meas_check_compute(struct gsm_lchan *lchan, uint32_t fn)
|
||||
if (num_meas_sub) {
|
||||
ber_sub_sum = ber_sub_sum / num_meas_sub;
|
||||
irssi_sub_sum = irssi_sub_sum / num_meas_sub;
|
||||
} else {
|
||||
ber_sub_sum = ber_full_sum;
|
||||
irssi_sub_sum = irssi_full_sum;
|
||||
}
|
||||
|
||||
DEBUGP(DMEAS, "%s Computed TA(% 4dqb) BER-FULL(%2u.%02u%%), RSSI-FULL(-%3udBm), "
|
||||
@@ -183,6 +339,9 @@ static int lchan_meas_check_compute(struct gsm_lchan *lchan, uint32_t fn)
|
||||
ber_full_sum%100, irssi_full_sum, ber_sub_sum/100, ber_sub_sum%100,
|
||||
irssi_sub_sum);
|
||||
|
||||
/* Update ordered TA for DL SACCH L1 Header */
|
||||
lchan_meas_update_ordered_TA(lchan, taqb_sum);
|
||||
|
||||
/* store results */
|
||||
mru = &lchan->meas.ul_res;
|
||||
mru->full.rx_lev = dbm2rxlev((int)irssi_full_sum * -1);
|
||||
@@ -190,6 +349,14 @@ static int lchan_meas_check_compute(struct gsm_lchan *lchan, uint32_t fn)
|
||||
mru->full.rx_qual = ber10k_to_rxqual(ber_full_sum);
|
||||
mru->sub.rx_qual = ber10k_to_rxqual(ber_sub_sum);
|
||||
|
||||
DEBUGP(DMEAS, "%s UL MEAS RXLEV_FULL(%u), RXLEV_SUB(%u),"
|
||||
"RXQUAL_FULL(%u), RXQUAL_SUB(%u), num_meas_sub(%u), num_ul_meas(%u) \n",
|
||||
gsm_lchan_name(lchan),
|
||||
mru->full.rx_lev,
|
||||
mru->sub.rx_lev,
|
||||
mru->full.rx_qual,
|
||||
mru->sub.rx_qual, num_meas_sub, lchan->meas.num_ul_meas);
|
||||
|
||||
lchan->meas.flags |= LC_UL_M_F_RES_VALID;
|
||||
lchan->meas.num_ul_meas = 0;
|
||||
|
||||
@@ -197,63 +364,3 @@ static int lchan_meas_check_compute(struct gsm_lchan *lchan, uint32_t fn)
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* build the 3 byte RSL uplinke measurement IE content */
|
||||
int lchan_build_rsl_ul_meas(struct gsm_lchan *lchan, uint8_t *buf)
|
||||
{
|
||||
struct gsm_meas_rep_unidir *mru = &lchan->meas.ul_res;
|
||||
buf[0] = (mru->full.rx_lev & 0x3f); /* FIXME: DTXu support */
|
||||
buf[1] = (mru->sub.rx_lev & 0x3f);
|
||||
buf[2] = ((mru->full.rx_qual & 7) << 3) | (mru->sub.rx_qual & 7);
|
||||
|
||||
return 3;
|
||||
}
|
||||
|
||||
/* Copied from OpenBSC and enlarged to _GSM_PCHAN_MAX */
|
||||
static const uint8_t subslots_per_pchan[_GSM_PCHAN_MAX] = {
|
||||
[GSM_PCHAN_NONE] = 0,
|
||||
[GSM_PCHAN_CCCH] = 0,
|
||||
[GSM_PCHAN_CCCH_SDCCH4] = 4,
|
||||
[GSM_PCHAN_TCH_F] = 1,
|
||||
[GSM_PCHAN_TCH_H] = 2,
|
||||
[GSM_PCHAN_SDCCH8_SACCH8C] = 8,
|
||||
/* FIXME: what about dynamic TCH_F_TCH_H ? */
|
||||
[GSM_PCHAN_TCH_F_PDCH] = 1,
|
||||
};
|
||||
|
||||
static int ts_meas_check_compute(struct gsm_bts_trx_ts *ts, uint32_t fn)
|
||||
{
|
||||
int i;
|
||||
const int num_subslots = subslots_per_pchan[ts->pchan];
|
||||
|
||||
for (i = 0; i < num_subslots; ++i) {
|
||||
struct gsm_lchan *lchan = &ts->lchan[i];
|
||||
|
||||
if (lchan->state != LCHAN_S_ACTIVE)
|
||||
continue;
|
||||
|
||||
switch (lchan->type) {
|
||||
case GSM_LCHAN_SDCCH:
|
||||
case GSM_LCHAN_TCH_F:
|
||||
case GSM_LCHAN_TCH_H:
|
||||
case GSM_LCHAN_PDTCH:
|
||||
lchan_meas_check_compute(lchan, fn);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* needs to be called once every TDMA frame ! */
|
||||
int trx_meas_check_compute(struct gsm_bts_trx *trx, uint32_t fn)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(trx->ts); i++) {
|
||||
struct gsm_bts_trx_ts *ts = &trx->ts[i];
|
||||
ts_meas_check_compute(ts, fn);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -17,17 +17,24 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <osmo-bts/dtx_dl_amr_fsm.h>
|
||||
#include <osmo-bts/msg_utils.h>
|
||||
#include <osmo-bts/logging.h>
|
||||
#include <osmo-bts/oml.h>
|
||||
#include <osmo-bts/amr.h>
|
||||
#include <osmo-bts/rsl.h>
|
||||
|
||||
#include <osmocom/gsm/protocol/ipaccess.h>
|
||||
#include <osmocom/gsm/protocol/gsm_12_21.h>
|
||||
#include <osmocom/gsm/abis_nm.h>
|
||||
#include <osmocom/core/msgb.h>
|
||||
#include <osmocom/core/fsm.h>
|
||||
#include <osmocom/trau/osmo_ortp.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <errno.h>
|
||||
|
||||
#define STI_BIT_MASK 16
|
||||
|
||||
static int check_fom(struct abis_om_hdr *omh, size_t len)
|
||||
{
|
||||
@@ -86,6 +93,425 @@ static int check_manuf(struct msgb *msg, struct abis_om_hdr *omh, size_t msg_siz
|
||||
return type;
|
||||
}
|
||||
|
||||
/* check that DTX is in the middle of silence */
|
||||
static inline bool dtx_is_update(const struct gsm_lchan *lchan)
|
||||
{
|
||||
if (!dtx_dl_amr_enabled(lchan))
|
||||
return false;
|
||||
if (lchan->tch.dtx.dl_amr_fsm->state == ST_SID_U ||
|
||||
lchan->tch.dtx.dl_amr_fsm->state == ST_U_NOINH)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* check that DTX is in the beginning of silence for AMR HR */
|
||||
bool dtx_is_first_p1(const struct gsm_lchan *lchan)
|
||||
{
|
||||
if (!dtx_dl_amr_enabled(lchan))
|
||||
return false;
|
||||
if ((lchan->type == GSM_LCHAN_TCH_H &&
|
||||
lchan->tch.dtx.dl_amr_fsm->state == ST_SID_F1))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* update lchan SID status */
|
||||
void lchan_set_marker(bool t, struct gsm_lchan *lchan)
|
||||
{
|
||||
if (t)
|
||||
lchan->tch.dtx.ul_sid = true;
|
||||
else if (lchan->tch.dtx.ul_sid) {
|
||||
lchan->tch.dtx.ul_sid = false;
|
||||
lchan->rtp_tx_marker = true;
|
||||
}
|
||||
}
|
||||
|
||||
/*! \brief Store the last SID frame in lchan context
|
||||
* \param[in] lchan Logical channel on which we check scheduling
|
||||
* \param[in] l1_payload buffer with SID data
|
||||
* \param[in] length length of l1_payload
|
||||
* \param[in] fn Frame Number for which we check scheduling
|
||||
* \param[in] update 0 if SID_FIRST, 1 if SID_UPDATE, -1 if not AMR SID
|
||||
*/
|
||||
void dtx_cache_payload(struct gsm_lchan *lchan, const uint8_t *l1_payload,
|
||||
size_t length, uint32_t fn, int update)
|
||||
{
|
||||
size_t amr = (update < 0) ? 0 : 2,
|
||||
copy_len = OSMO_MIN(length,
|
||||
ARRAY_SIZE(lchan->tch.dtx.cache) - amr);
|
||||
|
||||
lchan->tch.dtx.len = copy_len + amr;
|
||||
/* SID FIRST is special because it's both sent and cached: */
|
||||
if (update == 0) {
|
||||
lchan->tch.dtx.is_update = false; /* Mark SID FIRST explicitly */
|
||||
/* for non-AMR case - always update FN for incoming SID FIRST */
|
||||
if (!amr || !dtx_is_update(lchan))
|
||||
lchan->tch.dtx.fn = fn;
|
||||
/* for AMR case - do not update FN if SID FIRST arrives in a
|
||||
middle of silence: this should not be happening according to
|
||||
the spec */
|
||||
}
|
||||
|
||||
memcpy(lchan->tch.dtx.cache + amr, l1_payload, copy_len);
|
||||
}
|
||||
|
||||
/*! \brief Check current state of DTX DL AMR FSM and dispatch necessary events
|
||||
* \param[in] lchan Logical channel on which we check scheduling
|
||||
* \param[in] rtp_pl buffer with RTP data
|
||||
* \param[in] rtp_pl_len length of rtp_pl
|
||||
* \param[in] fn Frame Number for which we check scheduling
|
||||
* \param[in] l1_payload buffer where CMR and CMI prefix should be added
|
||||
* \param[in] marker RTP Marker bit
|
||||
* \param[out] len Length of expected L1 payload
|
||||
* \param[out] ft_out Frame Type to be populated after decoding
|
||||
* \returns 0 in case of success; negative on error
|
||||
*/
|
||||
int dtx_dl_amr_fsm_step(struct gsm_lchan *lchan, const uint8_t *rtp_pl,
|
||||
size_t rtp_pl_len, uint32_t fn, uint8_t *l1_payload,
|
||||
bool marker, uint8_t *len, uint8_t *ft_out)
|
||||
{
|
||||
uint8_t cmr;
|
||||
enum osmo_amr_type ft;
|
||||
enum osmo_amr_quality bfi;
|
||||
int8_t sti, cmi;
|
||||
int rc;
|
||||
|
||||
if (dtx_dl_amr_enabled(lchan)) {
|
||||
if (lchan->type == GSM_LCHAN_TCH_H && !rtp_pl) {
|
||||
/* we're called by gen_empty_tch_msg() to handle states
|
||||
specific to AMR HR DTX */
|
||||
switch (lchan->tch.dtx.dl_amr_fsm->state) {
|
||||
case ST_SID_F2:
|
||||
*len = 3; /* SID-FIRST P1 -> P2 completion */
|
||||
memcpy(l1_payload, lchan->tch.dtx.cache, 2);
|
||||
rc = 0;
|
||||
dtx_dispatch(lchan, E_COMPL);
|
||||
break;
|
||||
case ST_SID_U:
|
||||
rc = -EBADMSG;
|
||||
dtx_dispatch(lchan, E_SID_U);
|
||||
break;
|
||||
default:
|
||||
rc = -EBADMSG;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
if (!rtp_pl_len)
|
||||
return -EBADMSG;
|
||||
|
||||
rc = osmo_amr_rtp_dec(rtp_pl, rtp_pl_len, &cmr, &cmi, &ft, &bfi, &sti);
|
||||
if (rc < 0) {
|
||||
LOGP(DRTP, LOGL_ERROR, "failed to decode AMR RTP (length %zu, "
|
||||
"%p)\n", rtp_pl_len, rtp_pl);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* only needed for old sysmo firmware: */
|
||||
*ft_out = ft;
|
||||
|
||||
/* CMI in downlink tells the L1 encoder which encoding function
|
||||
* it will use, so we have to use the frame type */
|
||||
if (osmo_amr_is_speech(ft))
|
||||
cmi = ft;
|
||||
|
||||
/* populate L1 payload with CMR/CMI - might be ignored by caller: */
|
||||
amr_set_mode_pref(l1_payload, &lchan->tch.amr_mr, cmi, cmr);
|
||||
|
||||
/* populate DTX cache with CMR/CMI - overwrite cache which will be
|
||||
either updated or invalidated by caller anyway: */
|
||||
amr_set_mode_pref(lchan->tch.dtx.cache, &lchan->tch.amr_mr, cmi, cmr);
|
||||
*len = 3 + rtp_pl_len;
|
||||
|
||||
/* DTX DL is not enabled, move along */
|
||||
if (!lchan->ts->trx->bts->dtxd)
|
||||
return 0;
|
||||
|
||||
if (osmo_amr_is_speech(ft)) {
|
||||
/* AMR HR - SID-FIRST_P1 Inhibition */
|
||||
if (marker && lchan->tch.dtx.dl_amr_fsm->state == ST_VOICE)
|
||||
return osmo_fsm_inst_dispatch(lchan->tch.dtx.dl_amr_fsm,
|
||||
E_INHIB, (void *)lchan);
|
||||
|
||||
/* AMR HR - SID-UPDATE Inhibition */
|
||||
if (marker && lchan->type == GSM_LCHAN_TCH_H &&
|
||||
lchan->tch.dtx.dl_amr_fsm->state == ST_SID_U)
|
||||
return osmo_fsm_inst_dispatch(lchan->tch.dtx.dl_amr_fsm,
|
||||
E_INHIB, (void *)lchan);
|
||||
|
||||
/* AMR FR & HR - generic */
|
||||
if (marker && (lchan->tch.dtx.dl_amr_fsm->state == ST_SID_F1 ||
|
||||
lchan->tch.dtx.dl_amr_fsm->state == ST_SID_F2 ||
|
||||
lchan->tch.dtx.dl_amr_fsm->state == ST_U_NOINH))
|
||||
return osmo_fsm_inst_dispatch(lchan->tch.dtx.dl_amr_fsm,
|
||||
E_ONSET, (void *)lchan);
|
||||
|
||||
if (lchan->tch.dtx.dl_amr_fsm->state != ST_VOICE)
|
||||
return osmo_fsm_inst_dispatch(lchan->tch.dtx.dl_amr_fsm,
|
||||
E_VOICE, (void *)lchan);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ft == AMR_SID) {
|
||||
if (lchan->tch.dtx.dl_amr_fsm->state == ST_VOICE) {
|
||||
/* SID FIRST/UPDATE scheduling logic relies on SID FIRST
|
||||
being sent first hence we have to force caching of SID
|
||||
as FIRST regardless of actually decoded type */
|
||||
dtx_cache_payload(lchan, rtp_pl, rtp_pl_len, fn, false);
|
||||
return osmo_fsm_inst_dispatch(lchan->tch.dtx.dl_amr_fsm,
|
||||
sti ? E_SID_U : E_SID_F,
|
||||
(void *)lchan);
|
||||
} else if (lchan->tch.dtx.dl_amr_fsm->state != ST_FACCH)
|
||||
dtx_cache_payload(lchan, rtp_pl, rtp_pl_len, fn, sti);
|
||||
if (lchan->tch.dtx.dl_amr_fsm->state == ST_SID_F2)
|
||||
return osmo_fsm_inst_dispatch(lchan->tch.dtx.dl_amr_fsm,
|
||||
E_COMPL, (void *)lchan);
|
||||
return osmo_fsm_inst_dispatch(lchan->tch.dtx.dl_amr_fsm,
|
||||
sti ? E_SID_U : E_SID_F,
|
||||
(void *)lchan);
|
||||
}
|
||||
|
||||
if (ft != AMR_NO_DATA) {
|
||||
LOGP(DRTP, LOGL_ERROR, "unsupported AMR FT 0x%02x\n", ft);
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
if (marker)
|
||||
osmo_fsm_inst_dispatch(lchan->tch.dtx.dl_amr_fsm, E_VOICE,
|
||||
(void *)lchan);
|
||||
*len = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* STI is located in payload byte 6, cache contains 2 byte prefix (CMR/CMI)
|
||||
* STI set = SID UPDATE, STI unset = SID FIRST
|
||||
*/
|
||||
static inline void dtx_sti_set(struct gsm_lchan *lchan)
|
||||
{
|
||||
lchan->tch.dtx.cache[6 + 2] |= STI_BIT_MASK;
|
||||
}
|
||||
|
||||
static inline void dtx_sti_unset(struct gsm_lchan *lchan)
|
||||
{
|
||||
lchan->tch.dtx.cache[6 + 2] &= ~STI_BIT_MASK;
|
||||
}
|
||||
|
||||
/*! \brief Check if enough time has passed since last SID (if any) to repeat it
|
||||
* \param[in] lchan Logical channel on which we check scheduling
|
||||
* \param[in] fn Frame Number for which we check scheduling
|
||||
* \returns true if transmission can be omitted, false otherwise
|
||||
*/
|
||||
static inline bool dtx_amr_sid_optional(struct gsm_lchan *lchan, uint32_t fn)
|
||||
{
|
||||
if (!dtx_dl_amr_enabled(lchan))
|
||||
return true;
|
||||
|
||||
/* Compute approx. time delta x26 based on Fn duration */
|
||||
uint32_t dx26 = 120 * (fn - lchan->tch.dtx.fn);
|
||||
|
||||
/* We're resuming after FACCH interruption */
|
||||
if (lchan->tch.dtx.dl_amr_fsm->state == ST_FACCH) {
|
||||
/* force STI bit to 0 so cache is treated as SID FIRST */
|
||||
dtx_sti_unset(lchan);
|
||||
lchan->tch.dtx.is_update = false;
|
||||
/* check that this FN has not been used for FACCH message
|
||||
already: we rely here on the order of RTS arrival from L1 - we
|
||||
expect that PH-DATA.req ALWAYS comes before PH-TCH.req for the
|
||||
same FN */
|
||||
if(lchan->type == GSM_LCHAN_TCH_H) {
|
||||
if (lchan->tch.dtx.fn != LCHAN_FN_DUMMY &&
|
||||
lchan->tch.dtx.fn != LCHAN_FN_WAIT) {
|
||||
/* FACCH interruption is over */
|
||||
dtx_dispatch(lchan, E_COMPL);
|
||||
return false;
|
||||
} else if(lchan->tch.dtx.fn == LCHAN_FN_DUMMY) {
|
||||
lchan->tch.dtx.fn = LCHAN_FN_WAIT;
|
||||
} else
|
||||
lchan->tch.dtx.fn = fn;
|
||||
} else if(lchan->type == GSM_LCHAN_TCH_F) {
|
||||
if (lchan->tch.dtx.fn != LCHAN_FN_DUMMY) {
|
||||
/* FACCH interruption is over */
|
||||
dtx_dispatch(lchan, E_COMPL);
|
||||
return false;
|
||||
} else
|
||||
lchan->tch.dtx.fn = fn;
|
||||
}
|
||||
/* this FN was already used for FACCH or ONSET message so we just
|
||||
prepare things for next one */
|
||||
return true;
|
||||
}
|
||||
|
||||
if (lchan->tch.dtx.dl_amr_fsm->state == ST_VOICE)
|
||||
return true;
|
||||
|
||||
/* according to 3GPP TS 26.093 A.5.1.1:
|
||||
(*26) to avoid float math, add 1 FN tolerance (-120) */
|
||||
if (lchan->tch.dtx.is_update) { /* SID UPDATE: every 8th RTP frame */
|
||||
if (dx26 < GSM_RTP_FRAME_DURATION_MS * 8 * 26 - 120)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
/* 3rd frame after SID FIRST should be SID UPDATE */
|
||||
if (dx26 < GSM_RTP_FRAME_DURATION_MS * 3 * 26 - 120)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool fn_chk(const uint8_t *t, uint32_t fn, uint8_t len)
|
||||
{
|
||||
uint8_t i;
|
||||
for (i = 0; i < len; i++)
|
||||
if (fn % 104 == t[i])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*! \brief Check if TX scheduling is optional for a given FN in case of DTX
|
||||
* \param[in] lchan Logical channel on which we check scheduling
|
||||
* \param[in] fn Frame Number for which we check scheduling
|
||||
* \returns true if transmission can be omitted, false otherwise
|
||||
*/
|
||||
static inline bool dtx_sched_optional(struct gsm_lchan *lchan, uint32_t fn)
|
||||
{
|
||||
/* According to 3GPP TS 45.008 § 8.3: */
|
||||
static const uint8_t f[] = { 52, 53, 54, 55, 56, 57, 58, 59 },
|
||||
h0[] = { 0, 2, 4, 6, 52, 54, 56, 58 },
|
||||
h1[] = { 14, 16, 18, 20, 66, 68, 70, 72 };
|
||||
if (lchan->tch_mode == GSM48_CMODE_SPEECH_V1) {
|
||||
if (lchan->type == GSM_LCHAN_TCH_F)
|
||||
return fn_chk(f, fn, ARRAY_SIZE(f));
|
||||
else
|
||||
return fn_chk(lchan->nr ? h1 : h0, fn,
|
||||
lchan->nr ? ARRAY_SIZE(h1) :
|
||||
ARRAY_SIZE(h0));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*! \brief Check if DTX DL AMR is enabled for a given lchan (it have proper type,
|
||||
* FSM is allocated etc.)
|
||||
* \param[in] lchan Logical channel on which we check scheduling
|
||||
* \returns true if DTX DL AMR is enabled, false otherwise
|
||||
*/
|
||||
bool dtx_dl_amr_enabled(const struct gsm_lchan *lchan)
|
||||
{
|
||||
if (lchan->ts->trx->bts->dtxd &&
|
||||
lchan->tch.dtx.dl_amr_fsm &&
|
||||
lchan->tch_mode == GSM48_CMODE_SPEECH_AMR)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*! \brief Check if DTX DL AMR FSM state is recursive: requires secondary
|
||||
* response to a single RTS request from L1.
|
||||
* \param[in] lchan Logical channel on which we check scheduling
|
||||
* \returns true if DTX DL AMR FSM state is recursive, false otherwise
|
||||
*/
|
||||
bool dtx_recursion(const struct gsm_lchan *lchan)
|
||||
{
|
||||
if (!dtx_dl_amr_enabled(lchan))
|
||||
return false;
|
||||
|
||||
if (lchan->tch.dtx.dl_amr_fsm->state == ST_U_INH_V ||
|
||||
lchan->tch.dtx.dl_amr_fsm->state == ST_U_INH_F ||
|
||||
lchan->tch.dtx.dl_amr_fsm->state == ST_U_INH_V_REC ||
|
||||
lchan->tch.dtx.dl_amr_fsm->state == ST_U_INH_F_REC ||
|
||||
lchan->tch.dtx.dl_amr_fsm->state == ST_F1_INH_V ||
|
||||
lchan->tch.dtx.dl_amr_fsm->state == ST_F1_INH_F ||
|
||||
lchan->tch.dtx.dl_amr_fsm->state == ST_F1_INH_V_REC ||
|
||||
lchan->tch.dtx.dl_amr_fsm->state == ST_F1_INH_F_REC ||
|
||||
lchan->tch.dtx.dl_amr_fsm->state == ST_ONSET_F ||
|
||||
lchan->tch.dtx.dl_amr_fsm->state == ST_ONSET_V ||
|
||||
lchan->tch.dtx.dl_amr_fsm->state == ST_ONSET_F_REC ||
|
||||
lchan->tch.dtx.dl_amr_fsm->state == ST_ONSET_V_REC)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*! \brief Send signal to FSM: with proper check if DIX is enabled for this lchan
|
||||
* \param[in] lchan Logical channel on which we check scheduling
|
||||
* \param[in] e DTX DL AMR FSM Event
|
||||
*/
|
||||
void dtx_dispatch(struct gsm_lchan *lchan, enum dtx_dl_amr_fsm_events e)
|
||||
{
|
||||
if (dtx_dl_amr_enabled(lchan))
|
||||
osmo_fsm_inst_dispatch(lchan->tch.dtx.dl_amr_fsm, e,
|
||||
(void *)lchan);
|
||||
}
|
||||
|
||||
/*! \brief Send internal signal to FSM: check that DTX is enabled for this chan,
|
||||
* check that current FSM and lchan states are permitting such signal.
|
||||
* Note: this should be the only way to dispatch E_COMPL to FSM from
|
||||
* BTS code.
|
||||
* \param[in] lchan Logical channel on which we check scheduling
|
||||
*/
|
||||
void dtx_int_signal(struct gsm_lchan *lchan)
|
||||
{
|
||||
if (!dtx_dl_amr_enabled(lchan))
|
||||
return;
|
||||
|
||||
if (dtx_is_first_p1(lchan) || dtx_recursion(lchan))
|
||||
dtx_dispatch(lchan, E_COMPL);
|
||||
}
|
||||
|
||||
/*! \brief Repeat last SID if possible in case of DTX
|
||||
* \param[in] lchan Logical channel on which we check scheduling
|
||||
* \param[in] dst Buffer to copy last SID into
|
||||
* \returns Number of bytes copied + 1 (to accommodate for extra byte with
|
||||
* payload type), 0 if there's nothing to copy
|
||||
*/
|
||||
uint8_t repeat_last_sid(struct gsm_lchan *lchan, uint8_t *dst, uint32_t fn)
|
||||
{
|
||||
/* FIXME: add EFR support */
|
||||
if (lchan->tch_mode == GSM48_CMODE_SPEECH_EFR)
|
||||
return 0;
|
||||
|
||||
if (lchan->tch_mode != GSM48_CMODE_SPEECH_AMR) {
|
||||
if (dtx_sched_optional(lchan, fn))
|
||||
return 0;
|
||||
} else
|
||||
if (dtx_amr_sid_optional(lchan, fn))
|
||||
return 0;
|
||||
|
||||
if (lchan->tch.dtx.len) {
|
||||
if (dtx_dl_amr_enabled(lchan)) {
|
||||
if ((lchan->type == GSM_LCHAN_TCH_H &&
|
||||
lchan->tch.dtx.dl_amr_fsm->state == ST_SID_F2) ||
|
||||
(lchan->type == GSM_LCHAN_TCH_F &&
|
||||
lchan->tch.dtx.dl_amr_fsm->state == ST_SID_F1)) {
|
||||
/* advance FSM in case we've just sent SID FIRST
|
||||
to restore silence after FACCH interruption */
|
||||
osmo_fsm_inst_dispatch(lchan->tch.dtx.dl_amr_fsm,
|
||||
E_SID_U, (void *)lchan);
|
||||
dtx_sti_unset(lchan);
|
||||
} else if (dtx_is_update(lchan)) {
|
||||
/* enforce SID UPDATE for next repetition: it
|
||||
might have been altered by FACCH handling */
|
||||
dtx_sti_set(lchan);
|
||||
if (lchan->type == GSM_LCHAN_TCH_H &&
|
||||
lchan->tch.dtx.dl_amr_fsm->state ==
|
||||
ST_U_NOINH)
|
||||
osmo_fsm_inst_dispatch(lchan->tch.dtx.dl_amr_fsm,
|
||||
E_COMPL,
|
||||
(void *)lchan);
|
||||
lchan->tch.dtx.is_update = true;
|
||||
}
|
||||
}
|
||||
memcpy(dst, lchan->tch.dtx.cache, lchan->tch.dtx.len);
|
||||
lchan->tch.dtx.fn = fn;
|
||||
return lchan->tch.dtx.len + 1;
|
||||
}
|
||||
|
||||
LOGP(DL1C, LOGL_DEBUG, "Have to send %s frame on TCH but SID buffer "
|
||||
"is empty - sent nothing\n",
|
||||
get_value_string(gsm48_chan_mode_names, lchan->tch_mode));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return 0 in case the IPA structure is okay and in this
|
||||
* case the l2h will be set to the beginning of the data.
|
||||
@@ -96,28 +522,30 @@ int msg_verify_ipa_structure(struct msgb *msg)
|
||||
|
||||
if (msgb_l1len(msg) < sizeof(struct ipaccess_head)) {
|
||||
LOGP(DL1C, LOGL_ERROR,
|
||||
"Ipa header insufficient space %d %d\n",
|
||||
"Ipa header insufficient space %d %zu\n",
|
||||
msgb_l1len(msg), sizeof(struct ipaccess_head));
|
||||
return -1;
|
||||
}
|
||||
|
||||
hh = (struct ipaccess_head *) msg->l1h;
|
||||
|
||||
if (hh->proto != IPAC_PROTO_OML) {
|
||||
LOGP(DL1C, LOGL_ERROR,
|
||||
"Incorrect ipa header protocol 0x%x 0x%x\n",
|
||||
hh->proto, IPAC_PROTO_OML);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ntohs(hh->len) != msgb_l1len(msg) - sizeof(struct ipaccess_head)) {
|
||||
LOGP(DL1C, LOGL_ERROR,
|
||||
"Incorrect ipa header msg size %d %d\n",
|
||||
"Incorrect ipa header msg size %d %zu\n",
|
||||
ntohs(hh->len), msgb_l1len(msg) - sizeof(struct ipaccess_head));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (hh->proto == IPAC_PROTO_OSMO) {
|
||||
struct ipaccess_head_ext *hh_ext = (struct ipaccess_head_ext *) hh->data;
|
||||
if (ntohs(hh->len) < sizeof(*hh_ext)) {
|
||||
LOGP(DL1C, LOGL_ERROR, "IPA length shorter than OSMO header\n");
|
||||
return -1;
|
||||
}
|
||||
msg->l2h = hh_ext->data;
|
||||
} else
|
||||
msg->l2h = hh->data;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -140,7 +568,7 @@ int msg_verify_oml_structure(struct msgb *msg)
|
||||
struct abis_om_hdr *omh;
|
||||
|
||||
if (msgb_l2len(msg) < sizeof(*omh)) {
|
||||
LOGP(DL1C, LOGL_ERROR, "Om header insufficient space %d %d\n",
|
||||
LOGP(DL1C, LOGL_ERROR, "Om header insufficient space %d %zu\n",
|
||||
msgb_l2len(msg), sizeof(*omh));
|
||||
return -1;
|
||||
}
|
||||
|
||||
717
src/common/oml.c
717
src/common/oml.c
@@ -24,11 +24,16 @@
|
||||
* Operation and Maintainance Messages
|
||||
*/
|
||||
|
||||
#include "btsconfig.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <osmocom/core/talloc.h>
|
||||
#include <osmocom/core/msgb.h>
|
||||
#include <osmocom/gsm/protocol/gsm_12_21.h>
|
||||
#include <osmocom/gsm/abis_nm.h>
|
||||
#include <osmocom/abis/e1_input.h>
|
||||
@@ -41,115 +46,19 @@
|
||||
#include <osmo-bts/bts_model.h>
|
||||
#include <osmo-bts/bts.h>
|
||||
#include <osmo-bts/signal.h>
|
||||
|
||||
/* FIXME: move this to libosmocore */
|
||||
static struct tlv_definition abis_nm_att_tlvdef_ipa = {
|
||||
.def = {
|
||||
/* ip.access specifics */
|
||||
[NM_ATT_IPACC_DST_IP] = { TLV_TYPE_FIXED, 4 },
|
||||
[NM_ATT_IPACC_DST_IP_PORT] = { TLV_TYPE_FIXED, 2 },
|
||||
[NM_ATT_IPACC_STREAM_ID] = { TLV_TYPE_TV, },
|
||||
[NM_ATT_IPACC_SEC_OML_CFG] = { TLV_TYPE_FIXED, 6 },
|
||||
[NM_ATT_IPACC_IP_IF_CFG] = { TLV_TYPE_FIXED, 8 },
|
||||
[NM_ATT_IPACC_IP_GW_CFG] = { TLV_TYPE_FIXED, 12 },
|
||||
[NM_ATT_IPACC_IN_SERV_TIME] = { TLV_TYPE_FIXED, 4 },
|
||||
[NM_ATT_IPACC_LOCATION] = { TLV_TYPE_TL16V },
|
||||
[NM_ATT_IPACC_PAGING_CFG] = { TLV_TYPE_FIXED, 2 },
|
||||
[NM_ATT_IPACC_UNIT_ID] = { TLV_TYPE_TL16V },
|
||||
[NM_ATT_IPACC_UNIT_NAME] = { TLV_TYPE_TL16V },
|
||||
[NM_ATT_IPACC_SNMP_CFG] = { TLV_TYPE_TL16V },
|
||||
[NM_ATT_IPACC_PRIM_OML_CFG_LIST] = { TLV_TYPE_TL16V },
|
||||
[NM_ATT_IPACC_NV_FLAGS] = { TLV_TYPE_TL16V },
|
||||
[NM_ATT_IPACC_FREQ_CTRL] = { TLV_TYPE_FIXED, 2 },
|
||||
[NM_ATT_IPACC_PRIM_OML_FB_TOUT] = { TLV_TYPE_TL16V },
|
||||
[NM_ATT_IPACC_CUR_SW_CFG] = { TLV_TYPE_TL16V },
|
||||
[NM_ATT_IPACC_TIMING_BUS] = { TLV_TYPE_TL16V },
|
||||
[NM_ATT_IPACC_CGI] = { TLV_TYPE_TL16V },
|
||||
[NM_ATT_IPACC_RAC] = { TLV_TYPE_TL16V },
|
||||
[NM_ATT_IPACC_OBJ_VERSION] = { TLV_TYPE_TL16V },
|
||||
[NM_ATT_IPACC_GPRS_PAGING_CFG]= { TLV_TYPE_TL16V },
|
||||
[NM_ATT_IPACC_NSEI] = { TLV_TYPE_TL16V },
|
||||
[NM_ATT_IPACC_BVCI] = { TLV_TYPE_TL16V },
|
||||
[NM_ATT_IPACC_NSVCI] = { TLV_TYPE_TL16V },
|
||||
[NM_ATT_IPACC_NS_CFG] = { TLV_TYPE_TL16V },
|
||||
[NM_ATT_IPACC_BSSGP_CFG] = { TLV_TYPE_TL16V },
|
||||
[NM_ATT_IPACC_NS_LINK_CFG] = { TLV_TYPE_TL16V },
|
||||
[NM_ATT_IPACC_RLC_CFG] = { TLV_TYPE_TL16V },
|
||||
[NM_ATT_IPACC_ALM_THRESH_LIST]= { TLV_TYPE_TL16V },
|
||||
[NM_ATT_IPACC_MONIT_VAL_LIST] = { TLV_TYPE_TL16V },
|
||||
[NM_ATT_IPACC_TIB_CONTROL] = { TLV_TYPE_TL16V },
|
||||
[NM_ATT_IPACC_SUPP_FEATURES] = { TLV_TYPE_TL16V },
|
||||
[NM_ATT_IPACC_CODING_SCHEMES] = { TLV_TYPE_TL16V },
|
||||
[NM_ATT_IPACC_RLC_CFG_2] = { TLV_TYPE_TL16V },
|
||||
[NM_ATT_IPACC_HEARTB_TOUT] = { TLV_TYPE_TL16V },
|
||||
[NM_ATT_IPACC_UPTIME] = { TLV_TYPE_TL16V },
|
||||
[NM_ATT_IPACC_RLC_CFG_3] = { TLV_TYPE_TL16V },
|
||||
[NM_ATT_IPACC_SSL_CFG] = { TLV_TYPE_TL16V },
|
||||
[NM_ATT_IPACC_SEC_POSSIBLE] = { TLV_TYPE_TL16V },
|
||||
[NM_ATT_IPACC_IML_SSL_STATE] = { TLV_TYPE_TL16V },
|
||||
[NM_ATT_IPACC_REVOC_DATE] = { TLV_TYPE_TL16V },
|
||||
},
|
||||
};
|
||||
#include <osmo-bts/phy_link.h>
|
||||
|
||||
static int oml_ipa_set_attr(struct gsm_bts *bts, struct msgb *msg);
|
||||
|
||||
static struct tlv_definition abis_nm_att_tlvdef_ipa_local = {};
|
||||
|
||||
/*
|
||||
* support
|
||||
*/
|
||||
|
||||
struct tlv_parsed *tlvp_copy(const struct tlv_parsed *tp_orig, void *ctx)
|
||||
{
|
||||
struct tlv_parsed *tp_out;
|
||||
unsigned int i;
|
||||
|
||||
tp_out = talloc_zero(ctx, struct tlv_parsed);
|
||||
if (!tp_out)
|
||||
return NULL;
|
||||
|
||||
/* if the original is NULL, return empty tlvp */
|
||||
if (!tp_orig)
|
||||
return tp_out;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(tp_orig->lv); i++) {
|
||||
unsigned int len = tp_orig->lv[i].len;
|
||||
tp_out->lv[i].len = len;
|
||||
if (len && tp_out->lv[i].val) {
|
||||
tp_out->lv[i].val = talloc_zero_size(tp_out, len);
|
||||
if (!tp_out->lv[i].val) {
|
||||
talloc_free(tp_out);
|
||||
return NULL;
|
||||
}
|
||||
memcpy((uint8_t *)tp_out->lv[i].val, tp_orig->lv[i].val, len);
|
||||
}
|
||||
}
|
||||
|
||||
return tp_out;
|
||||
}
|
||||
|
||||
/* merge all attributes of 'new' into 'out' */
|
||||
int tlvp_merge(struct tlv_parsed *out, const struct tlv_parsed *new)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(out->lv); i++) {
|
||||
unsigned int len = new->lv[i].len;
|
||||
if (len == 0 || new->lv[i].val == NULL)
|
||||
continue;
|
||||
if (out->lv[i].val) {
|
||||
talloc_free((uint8_t *) out->lv[i].val);
|
||||
out->lv[i].len = 0;
|
||||
}
|
||||
out->lv[i].val = talloc_zero_size(out, len);
|
||||
if (!out->lv[i].val)
|
||||
return -ENOMEM;
|
||||
memcpy((uint8_t *) out->lv[i].val, new->lv[i].val, len);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int oml_tlv_parse(struct tlv_parsed *tp, const uint8_t *buf, int len)
|
||||
{
|
||||
return tlv_parse(tp, &abis_nm_att_tlvdef_ipa, buf, len, 0, 0);
|
||||
return tlv_parse(tp, &abis_nm_att_tlvdef_ipa_local, buf, len, 0, 0);
|
||||
}
|
||||
|
||||
struct msgb *oml_msgb_alloc(void)
|
||||
@@ -157,6 +66,42 @@ struct msgb *oml_msgb_alloc(void)
|
||||
return msgb_alloc_headroom(1024, 128, "OML");
|
||||
}
|
||||
|
||||
/* 3GPP TS 12.21 § 8.8.2 */
|
||||
static int oml_tx_failure_event_rep(struct gsm_abis_mo *mo, uint16_t cause_value,
|
||||
const char *fmt, ...)
|
||||
{
|
||||
struct msgb *nmsg;
|
||||
va_list ap;
|
||||
|
||||
LOGP(DOML, LOGL_NOTICE, "Sending %s to BSC: ", get_value_string(abis_mm_event_cause_names, cause_value));
|
||||
va_start(ap, fmt);
|
||||
osmo_vlogp(DOML, LOGL_NOTICE, __FILE__, __LINE__, 1, fmt, ap);
|
||||
nmsg = abis_nm_fail_evt_vrep(NM_EVT_PROC_FAIL, NM_SEVER_CRITICAL,
|
||||
NM_PCAUSE_T_MANUF, cause_value, fmt, ap);
|
||||
va_end(ap);
|
||||
LOGPC(DOML, LOGL_NOTICE, "\n");
|
||||
|
||||
if (!nmsg)
|
||||
return -ENOMEM;
|
||||
|
||||
return oml_mo_send_msg(mo, nmsg, NM_MT_FAILURE_EVENT_REP);
|
||||
}
|
||||
|
||||
void oml_fail_rep(uint16_t cause_value, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char *rep;
|
||||
|
||||
va_start(ap, fmt);
|
||||
rep = talloc_asprintf(tall_bts_ctx, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
osmo_signal_dispatch(SS_FAIL, cause_value, rep);
|
||||
/* signal dispatch is synchronous so all the signal handlers are
|
||||
finished already: we're free to free */
|
||||
talloc_free(rep);
|
||||
}
|
||||
|
||||
int oml_send_msg(struct msgb *msg, int is_manuf)
|
||||
{
|
||||
struct abis_om_hdr *omh;
|
||||
@@ -209,6 +154,156 @@ char *gsm_abis_mo_name(const struct gsm_abis_mo *mo)
|
||||
return mo_buf;
|
||||
}
|
||||
|
||||
static inline void add_bts_attrs(struct msgb *msg, const struct gsm_bts *bts)
|
||||
{
|
||||
abis_nm_put_sw_file(msg, btstype2str(GSM_BTS_TYPE_OSMOBTS), PACKAGE_VERSION, true);
|
||||
abis_nm_put_sw_file(msg, btsatttr2str(BTS_TYPE_VARIANT), btsvariant2str(bts->variant), true);
|
||||
|
||||
if (strlen(bts->sub_model))
|
||||
abis_nm_put_sw_file(msg, btsatttr2str(BTS_SUB_MODEL), bts->sub_model, true);
|
||||
}
|
||||
|
||||
/* Add BTS features as 3GPP TS 52.021 §9.4.30 Manufacturer Id */
|
||||
static inline void add_bts_feat(struct msgb *msg, const struct gsm_bts *bts)
|
||||
{
|
||||
msgb_tl16v_put(msg, NM_ATT_MANUF_ID, _NUM_BTS_FEAT/8 + 1, bts->_features_data);
|
||||
}
|
||||
|
||||
static inline void add_trx_attr(struct msgb *msg, struct gsm_bts_trx *trx)
|
||||
{
|
||||
const struct phy_instance *pinst = trx_phy_instance(trx);
|
||||
|
||||
abis_nm_put_sw_file(msg, btsatttr2str(TRX_PHY_VERSION), strlen(pinst->version) ? pinst->version : "Unknown",
|
||||
true);
|
||||
}
|
||||
|
||||
/* The number of attributes in §9.4.26 List of Required Attributes is 2 bytes,
|
||||
but the Count of not-reported attributes from §9.4.64 is 1 byte */
|
||||
static inline uint8_t pack_num_unreported_attr(uint16_t attrs)
|
||||
{
|
||||
if (attrs > 255) {
|
||||
LOGP(DOML, LOGL_ERROR, "O&M Get Attributes, Count of not-reported attributes is too big: %u\n",
|
||||
attrs);
|
||||
return 255;
|
||||
}
|
||||
return attrs; /* Return number of unhandled attributes */
|
||||
}
|
||||
|
||||
/* copy all the attributes accumulated in msg to out and return the total length of out buffer */
|
||||
static inline int cleanup_attr_msg(uint8_t *out, int out_offset, struct msgb *msg)
|
||||
{
|
||||
int len = 0;
|
||||
|
||||
out[0] = pack_num_unreported_attr(out_offset - 1);
|
||||
|
||||
if (msg) {
|
||||
memcpy(out + out_offset, msgb_data(msg), msg->len);
|
||||
len = msg->len;
|
||||
msgb_free(msg);
|
||||
}
|
||||
|
||||
return len + out_offset + 1;
|
||||
}
|
||||
|
||||
static inline int handle_attrs_trx(uint8_t *out, struct gsm_bts_trx *trx, const uint8_t *attr, uint16_t attr_len)
|
||||
{
|
||||
uint16_t i, attr_out_index = 1; /* byte 0 is reserved for unsupported attributes counter */
|
||||
struct msgb *attr_buf = oml_msgb_alloc();
|
||||
|
||||
if (!attr_buf)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < attr_len; i++) {
|
||||
bool processed = false;
|
||||
switch (attr[i]) {
|
||||
case NM_ATT_SW_CONFIG:
|
||||
if (trx) {
|
||||
add_trx_attr(attr_buf, trx);
|
||||
processed = true;
|
||||
} else
|
||||
LOGP(DOML, LOGL_ERROR, "O&M Get Attributes [%u], %s is unhandled due to missing TRX.\n",
|
||||
i, get_value_string(abis_nm_att_names, attr[i]));
|
||||
break;
|
||||
default:
|
||||
LOGP(DOML, LOGL_ERROR, "O&M Get Attributes [%u], %s is unsupported by TRX.\n", i,
|
||||
get_value_string(abis_nm_att_names, attr[i]));
|
||||
}
|
||||
/* assemble values of supported attributes and list of unsupported ones */
|
||||
if (!processed) {
|
||||
out[attr_out_index] = attr[i];
|
||||
attr_out_index++;
|
||||
}
|
||||
}
|
||||
|
||||
return cleanup_attr_msg(out, attr_out_index, attr_buf);
|
||||
}
|
||||
|
||||
static inline int handle_attrs_bts(uint8_t *out, const struct gsm_bts *bts, const uint8_t *attr, uint16_t attr_len)
|
||||
{
|
||||
uint16_t i, attr_out_index = 1; /* byte 0 is reserved for unsupported attributes counter */
|
||||
struct msgb *attr_buf = oml_msgb_alloc();
|
||||
|
||||
if (!attr_buf)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < attr_len; i++) {
|
||||
switch (attr[i]) {
|
||||
case NM_ATT_SW_CONFIG:
|
||||
add_bts_attrs(attr_buf, bts);
|
||||
break;
|
||||
case NM_ATT_MANUF_ID:
|
||||
add_bts_feat(attr_buf, bts);
|
||||
break;
|
||||
default:
|
||||
LOGP(DOML, LOGL_ERROR, "O&M Get Attributes [%u], %s is unsupported by BTS.\n", i,
|
||||
get_value_string(abis_nm_att_names, attr[i]));
|
||||
out[attr_out_index] = attr[i]; /* assemble values of supported attributes and list of unsupported ones */
|
||||
attr_out_index++;
|
||||
}
|
||||
}
|
||||
|
||||
return cleanup_attr_msg(out, attr_out_index, attr_buf);
|
||||
}
|
||||
|
||||
/* send 3GPP TS 52.021 §8.11.2 Get Attribute Response */
|
||||
static int oml_tx_attr_resp(struct gsm_bts *bts, const struct abis_om_fom_hdr *foh, const uint8_t *attr,
|
||||
uint16_t attr_len)
|
||||
{
|
||||
struct msgb *nmsg = oml_msgb_alloc();
|
||||
uint8_t resp[MAX_VERSION_LENGTH * attr_len * 2]; /* heuristic for Attribute Response Info space requirements */
|
||||
int len;
|
||||
|
||||
LOGP(DOML, LOGL_INFO, "%s Tx Get Attribute Response\n",
|
||||
get_value_string(abis_nm_obj_class_names, foh->obj_class));
|
||||
|
||||
if (!nmsg)
|
||||
return -ENOMEM;
|
||||
|
||||
switch (foh->obj_class) {
|
||||
case NM_OC_BTS:
|
||||
len = handle_attrs_bts(resp, bts, attr, attr_len);
|
||||
break;
|
||||
case NM_OC_BASEB_TRANSC:
|
||||
len = handle_attrs_trx(resp, gsm_bts_trx_num(bts, foh->obj_inst.trx_nr), attr, attr_len);
|
||||
break;
|
||||
default:
|
||||
LOGP(DOML, LOGL_ERROR, "Unsupported MO class %s in Get Attribute Response\n",
|
||||
get_value_string(abis_nm_obj_class_names, foh->obj_class));
|
||||
len = -EINVAL;
|
||||
}
|
||||
|
||||
if (len < 0) {
|
||||
LOGP(DOML, LOGL_ERROR, "Tx Get Attribute Response FAILED with %d\n", len);
|
||||
msgb_free(nmsg);
|
||||
return len;
|
||||
}
|
||||
|
||||
/* §9.4.64 Get Attribute Response Info */
|
||||
msgb_tl16v_put(nmsg, NM_ATT_GET_ARI, len, resp);
|
||||
|
||||
return oml_mo_send_msg(&bts->mo, nmsg, NM_MT_GET_ATTR_RESP);
|
||||
}
|
||||
|
||||
/* 8.8.1 sending State Changed Event Report */
|
||||
int oml_tx_state_changed(struct gsm_abis_mo *mo)
|
||||
{
|
||||
@@ -369,27 +464,108 @@ int oml_mo_tx_sw_act_rep(struct gsm_abis_mo *mo)
|
||||
return oml_mo_send_msg(mo, nmsg, NM_MT_SW_ACTIVATED_REP);
|
||||
}
|
||||
|
||||
/* TS 12.21 9.4.53 */
|
||||
enum abis_nm_t200_idx {
|
||||
T200_SDCCH = 0,
|
||||
T200_FACCH_F = 1,
|
||||
T200_FACCH_H = 2,
|
||||
T200_SACCH_TCH_SAPI0 = 3,
|
||||
T200_SACCH_SDCCH = 4,
|
||||
T200_SDCCH_SAPI3 = 5,
|
||||
T200_SACCH_TCH_SAPI3 = 6
|
||||
/* the below defaults correpsond to the libocmocore default of 1s for
|
||||
* DCCH and 2s for ACCH. The BSC should overried this via OML anyway. */
|
||||
const unsigned int oml_default_t200_ms[7] = {
|
||||
[T200_SDCCH] = 1000,
|
||||
[T200_FACCH_F] = 1000,
|
||||
[T200_FACCH_H] = 1000,
|
||||
[T200_SACCH_TCH_SAPI0] = 2000,
|
||||
[T200_SACCH_SDCCH] = 2000,
|
||||
[T200_SDCCH_SAPI3] = 1000,
|
||||
[T200_SACCH_TCH_SAPI3] = 2000,
|
||||
};
|
||||
|
||||
/* TS 12.21 9.4.53 */
|
||||
static const uint8_t abis_nm_t200_mult[] = {
|
||||
[T200_SDCCH] = 5,
|
||||
[T200_FACCH_F] = 5,
|
||||
[T200_FACCH_H] = 5,
|
||||
[T200_SACCH_TCH_SAPI0] = 10,
|
||||
[T200_SACCH_SDCCH] = 10,
|
||||
[T200_SDCCH_SAPI3] = 5,
|
||||
[T200_SACCH_TCH_SAPI3] = 10
|
||||
};
|
||||
static void dl_set_t200(struct lapdm_datalink *dl, unsigned int t200_msec)
|
||||
{
|
||||
dl->dl.t200_sec = t200_msec / 1000;
|
||||
dl->dl.t200_usec = (t200_msec % 1000) * 1000;
|
||||
}
|
||||
|
||||
/* Configure LAPDm T200 timers for this lchan according to OML */
|
||||
int oml_set_lchan_t200(struct gsm_lchan *lchan)
|
||||
{
|
||||
struct gsm_bts *bts = lchan->ts->trx->bts;
|
||||
struct gsm_bts_role_bts *btsb = bts_role_bts(bts);
|
||||
struct lapdm_channel *lc = &lchan->lapdm_ch;
|
||||
unsigned int t200_dcch, t200_dcch_sapi3, t200_acch, t200_acch_sapi3;
|
||||
|
||||
/* set T200 for main and associated channel */
|
||||
switch (lchan->type) {
|
||||
case GSM_LCHAN_SDCCH:
|
||||
t200_dcch = btsb->t200_ms[T200_SDCCH];
|
||||
t200_dcch_sapi3 = btsb->t200_ms[T200_SDCCH_SAPI3];
|
||||
t200_acch = btsb->t200_ms[T200_SACCH_SDCCH];
|
||||
t200_acch_sapi3 = btsb->t200_ms[T200_SACCH_SDCCH];
|
||||
break;
|
||||
case GSM_LCHAN_TCH_F:
|
||||
t200_dcch = btsb->t200_ms[T200_FACCH_F];
|
||||
t200_dcch_sapi3 = btsb->t200_ms[T200_FACCH_F];
|
||||
t200_acch = btsb->t200_ms[T200_SACCH_TCH_SAPI0];
|
||||
t200_acch_sapi3 = btsb->t200_ms[T200_SACCH_TCH_SAPI3];
|
||||
break;
|
||||
case GSM_LCHAN_TCH_H:
|
||||
t200_dcch = btsb->t200_ms[T200_FACCH_H];
|
||||
t200_dcch_sapi3 = btsb->t200_ms[T200_FACCH_H];
|
||||
t200_acch = btsb->t200_ms[T200_SACCH_TCH_SAPI0];
|
||||
t200_acch_sapi3 = btsb->t200_ms[T200_SACCH_TCH_SAPI3];
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
DEBUGP(DLLAPD, "%s: Setting T200 D0=%u, D3=%u, S0=%u, S3=%u"
|
||||
"(all in ms)\n", gsm_lchan_name(lchan), t200_dcch,
|
||||
t200_dcch_sapi3, t200_acch, t200_acch_sapi3);
|
||||
|
||||
dl_set_t200(&lc->lapdm_dcch.datalink[DL_SAPI0], t200_dcch);
|
||||
dl_set_t200(&lc->lapdm_dcch.datalink[DL_SAPI3], t200_dcch_sapi3);
|
||||
dl_set_t200(&lc->lapdm_acch.datalink[DL_SAPI0], t200_acch);
|
||||
dl_set_t200(&lc->lapdm_acch.datalink[DL_SAPI3], t200_acch_sapi3);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 3GPP TS 52.021 §8.11.1 Get Attributes has been received */
|
||||
static int oml_rx_get_attr(struct gsm_bts *bts, struct msgb *msg)
|
||||
{
|
||||
struct abis_om_fom_hdr *foh = msgb_l3(msg);
|
||||
struct tlv_parsed tp;
|
||||
int rc;
|
||||
|
||||
if (!foh || !bts)
|
||||
return -EINVAL;
|
||||
|
||||
abis_nm_debugp_foh(DOML, foh);
|
||||
DEBUGPC(DOML, "Rx GET ATTR\n");
|
||||
|
||||
rc = oml_tlv_parse(&tp, foh->data, msgb_l3len(msg) - sizeof(*foh));
|
||||
if (rc < 0) {
|
||||
oml_tx_failure_event_rep(&bts->mo, OSMO_EVT_MAJ_UNSUP_ATTR, "Get Attribute parsing failure");
|
||||
return oml_fom_ack_nack(msg, NM_NACK_INCORR_STRUCT);
|
||||
}
|
||||
|
||||
if (!TLVP_PRES_LEN(&tp, NM_ATT_LIST_REQ_ATTR, 1)) {
|
||||
LOGP(DOML, LOGL_ERROR, "O&M Get Attributes message without Attribute List?!\n");
|
||||
oml_tx_failure_event_rep(&bts->mo, OSMO_EVT_MAJ_UNSUP_ATTR, "Get Attribute without Attribute List");
|
||||
return oml_fom_ack_nack(msg, NM_NACK_INCORR_STRUCT);
|
||||
}
|
||||
|
||||
rc = oml_tx_attr_resp(bts, foh, TLVP_VAL(&tp, NM_ATT_LIST_REQ_ATTR), TLVP_LEN(&tp, NM_ATT_LIST_REQ_ATTR));
|
||||
if (rc < 0) {
|
||||
LOGP(DOML, LOGL_ERROR, "Failed to respond to O&M Get Attributes message: %s\n", strerror(-rc));
|
||||
switch (-rc) {
|
||||
case ENOMEM:
|
||||
return oml_fom_ack_nack(msg, NM_NACK_CANT_PERFORM);
|
||||
case ENOTSUP:
|
||||
return oml_fom_ack_nack(msg, NM_NACK_OBJCLASS_NOTSUPP);
|
||||
default:
|
||||
return oml_fom_ack_nack(msg, NM_NACK_RES_NOTIMPL);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 8.6.1 Set BTS Attributes has been received */
|
||||
static int oml_rx_set_bts_attr(struct gsm_bts *bts, struct msgb *msg)
|
||||
@@ -404,31 +580,34 @@ static int oml_rx_set_bts_attr(struct gsm_bts *bts, struct msgb *msg)
|
||||
DEBUGPC(DOML, "Rx SET BTS ATTR\n");
|
||||
|
||||
rc = oml_tlv_parse(&tp, foh->data, msgb_l3len(msg) - sizeof(*foh));
|
||||
if (rc < 0)
|
||||
if (rc < 0) {
|
||||
oml_tx_failure_event_rep(&bts->mo, OSMO_EVT_MAJ_UNSUP_ATTR,
|
||||
"New value for Attribute not supported");
|
||||
return oml_fom_ack_nack(msg, NM_NACK_INCORR_STRUCT);
|
||||
}
|
||||
|
||||
/* Test for globally unsupported stuff here */
|
||||
if (TLVP_PRESENT(&tp, NM_ATT_BCCH_ARFCN)) {
|
||||
const uint16_t *value = (const uint16_t *) TLVP_VAL(&tp, NM_ATT_BCCH_ARFCN);
|
||||
if (TLVP_PRES_LEN(&tp, NM_ATT_BCCH_ARFCN, 2)) {
|
||||
uint16_t arfcn = ntohs(tlvp_val16_unal(&tp, NM_ATT_BCCH_ARFCN));
|
||||
|
||||
LOGP(DOML, LOGL_NOTICE, "MSG: %s\n", osmo_hexdump(msgb_l3(msg), msgb_l3len(msg)));
|
||||
LOGP(DOML, LOGL_NOTICE, "L3=%p, VAL=%p, DIF=%tu\n", msgb_l3(msg), value,
|
||||
(void *)value - (void *) msgb_l3(msg));
|
||||
|
||||
if (arfcn > 1024) {
|
||||
oml_tx_failure_event_rep(&bts->mo, OSMO_EVT_WARN_SW_WARN,
|
||||
"Given ARFCN %u is not supported",
|
||||
arfcn);
|
||||
LOGP(DOML, LOGL_NOTICE, "Given ARFCN %d is not supported.\n", arfcn);
|
||||
return oml_fom_ack_nack(msg, NM_NACK_FREQ_NOTAVAIL);
|
||||
}
|
||||
}
|
||||
/* 9.4.52 Starting Time */
|
||||
if (TLVP_PRESENT(&tp, NM_ATT_START_TIME)) {
|
||||
oml_tx_failure_event_rep(&bts->mo, OSMO_EVT_MAJ_UNSUP_ATTR,
|
||||
"NM_ATT_START_TIME Attribute not "
|
||||
"supported");
|
||||
return oml_fom_ack_nack(msg, NM_NACK_SPEC_IMPL_NOTSUPP);
|
||||
}
|
||||
|
||||
/* merge existing BTS attributes with new attributes */
|
||||
tp_merged = tlvp_copy(bts->mo.nm_attr, bts);
|
||||
tlvp_merge(tp_merged, &tp);
|
||||
tp_merged = osmo_tlvp_copy(bts->mo.nm_attr, bts);
|
||||
osmo_tlvp_merge(tp_merged, &tp);
|
||||
|
||||
/* Ask BTS driver to validate new merged attributes */
|
||||
rc = bts_model_check_oml(bts, foh->msg_type, bts->mo.nm_attr, tp_merged, bts);
|
||||
@@ -444,7 +623,7 @@ static int oml_rx_set_bts_attr(struct gsm_bts *bts, struct msgb *msg)
|
||||
/* ... and actually still parse them */
|
||||
|
||||
/* 9.4.25 Interference Level Boundaries */
|
||||
if (TLVP_PRESENT(&tp, NM_ATT_INTERF_BOUND)) {
|
||||
if (TLVP_PRES_LEN(&tp, NM_ATT_INTERF_BOUND, 6)) {
|
||||
payload = TLVP_VAL(&tp, NM_ATT_INTERF_BOUND);
|
||||
for (i = 0; i < 6; i++) {
|
||||
int16_t boundary = *payload;
|
||||
@@ -452,62 +631,87 @@ static int oml_rx_set_bts_attr(struct gsm_bts *bts, struct msgb *msg)
|
||||
}
|
||||
}
|
||||
/* 9.4.24 Intave Parameter */
|
||||
if (TLVP_PRESENT(&tp, NM_ATT_INTAVE_PARAM))
|
||||
if (TLVP_PRES_LEN(&tp, NM_ATT_INTAVE_PARAM, 1))
|
||||
btsb->interference.intave = *TLVP_VAL(&tp, NM_ATT_INTAVE_PARAM);
|
||||
|
||||
/* 9.4.14 Connection Failure Criterion */
|
||||
if (TLVP_PRESENT(&tp, NM_ATT_CONN_FAIL_CRIT)) {
|
||||
if (TLVP_PRES_LEN(&tp, NM_ATT_CONN_FAIL_CRIT, 1)) {
|
||||
const uint8_t *val = TLVP_VAL(&tp, NM_ATT_CONN_FAIL_CRIT);
|
||||
|
||||
if (TLVP_LEN(&tp, NM_ATT_CONN_FAIL_CRIT) < 2
|
||||
|| val[0] != 0x01 || val[1] < 4 || val[1] > 64) {
|
||||
switch (val[0]) {
|
||||
case 0xFF: /* Osmocom specific Extension of TS 12.21 */
|
||||
LOGP(DOML, LOGL_NOTICE, "WARNING: Radio Link Timeout "
|
||||
"explicitly disabled, only use this for lab testing!\n");
|
||||
btsb->radio_link_timeout = -1;
|
||||
break;
|
||||
case 0x01: /* Based on uplink SACCH (radio link timeout) */
|
||||
if (TLVP_LEN(&tp, NM_ATT_CONN_FAIL_CRIT) >= 2 &&
|
||||
val[1] >= 4 && val[1] <= 64) {
|
||||
btsb->radio_link_timeout = val[1];
|
||||
break;
|
||||
}
|
||||
/* fall-through */
|
||||
case 0x02: /* Based on RXLEV/RXQUAL measurements */
|
||||
default:
|
||||
LOGP(DOML, LOGL_NOTICE, "Given Conn. Failure Criterion "
|
||||
"not supported. Please use critetion 0x01 with "
|
||||
"RADIO_LINK_TIMEOUT value of 4..64\n");
|
||||
return oml_fom_ack_nack(msg, NM_NACK_PARAM_RANGE);
|
||||
}
|
||||
btsb->radio_link_timeout = val[1];
|
||||
}
|
||||
/* if val[0] != 0x01: can be 'operator dependent' and needs to
|
||||
* be parsed by bts driver */
|
||||
|
||||
/* 9.4.53 T200 */
|
||||
if (TLVP_PRESENT(&tp, NM_ATT_T200)) {
|
||||
if (TLVP_PRES_LEN(&tp, NM_ATT_T200, ARRAY_SIZE(btsb->t200_ms))) {
|
||||
payload = TLVP_VAL(&tp, NM_ATT_T200);
|
||||
for (i = 0; i < ARRAY_SIZE(btsb->t200_ms); i++)
|
||||
btsb->t200_ms[i] = payload[i] * abis_nm_t200_mult[i];
|
||||
for (i = 0; i < ARRAY_SIZE(btsb->t200_ms); i++) {
|
||||
uint32_t t200_ms = payload[i] * abis_nm_t200_ms[i];
|
||||
#if 0
|
||||
btsb->t200_ms[i] = t200_ms;
|
||||
DEBUGP(DOML, "T200[%u]: OML=%u, mult=%u => %u ms\n",
|
||||
i, payload[i], abis_nm_t200_mult[i],
|
||||
btsb->t200_ms[i]);
|
||||
#else
|
||||
/* we'd rather use the 1s/2s (long) defaults by
|
||||
* libosmocore, as we appear to have some bug(s)
|
||||
* related to handling T200 expiration in
|
||||
* libosmogsm lapd(m) code? */
|
||||
LOGP(DOML, LOGL_NOTICE, "Ignoring T200[%u] (%u ms) "
|
||||
"as sent by BSC due to suspected LAPDm bug!\n",
|
||||
i, t200_ms);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* 9.4.31 Maximum Timing Advance */
|
||||
if (TLVP_PRESENT(&tp, NM_ATT_MAX_TA))
|
||||
if (TLVP_PRES_LEN(&tp, NM_ATT_MAX_TA, 1))
|
||||
btsb->max_ta = *TLVP_VAL(&tp, NM_ATT_MAX_TA);
|
||||
|
||||
/* 9.4.39 Overload Period */
|
||||
if (TLVP_PRESENT(&tp, NM_ATT_OVERL_PERIOD))
|
||||
if (TLVP_PRES_LEN(&tp, NM_ATT_OVERL_PERIOD, 1))
|
||||
btsb->load.overload_period = *TLVP_VAL(&tp, NM_ATT_OVERL_PERIOD);
|
||||
|
||||
/* 9.4.12 CCCH Load Threshold */
|
||||
if (TLVP_PRESENT(&tp, NM_ATT_CCCH_L_T))
|
||||
if (TLVP_PRES_LEN(&tp, NM_ATT_CCCH_L_T, 1))
|
||||
btsb->load.ccch.load_ind_thresh = *TLVP_VAL(&tp, NM_ATT_CCCH_L_T);
|
||||
|
||||
/* 9.4.11 CCCH Load Indication Period */
|
||||
if (TLVP_PRESENT(&tp, NM_ATT_CCCH_L_I_P))
|
||||
if (TLVP_PRES_LEN(&tp, NM_ATT_CCCH_L_I_P, 1))
|
||||
btsb->load.ccch.load_ind_period = *TLVP_VAL(&tp, NM_ATT_CCCH_L_I_P);
|
||||
|
||||
/* 9.4.44 RACH Busy Threshold */
|
||||
if (TLVP_PRESENT(&tp, NM_ATT_RACH_B_THRESH)) {
|
||||
if (TLVP_PRES_LEN(&tp, NM_ATT_RACH_B_THRESH, 1)) {
|
||||
int16_t thresh = *TLVP_VAL(&tp, NM_ATT_RACH_B_THRESH);
|
||||
btsb->load.rach.busy_thresh = -1 * thresh;
|
||||
}
|
||||
|
||||
/* 9.4.45 RACH Load Averaging Slots */
|
||||
if (TLVP_PRESENT(&tp, NM_ATT_LDAVG_SLOTS)) {
|
||||
if (TLVP_PRES_LEN(&tp, NM_ATT_LDAVG_SLOTS, 2)) {
|
||||
btsb->load.rach.averaging_slots =
|
||||
ntohs(tlvp_val16_unal(&tp, NM_ATT_LDAVG_SLOTS));
|
||||
}
|
||||
|
||||
/* 9.4.10 BTS Air Timer */
|
||||
if (TLVP_PRESENT(&tp, NM_ATT_BTS_AIR_TIMER)) {
|
||||
if (TLVP_PRES_LEN(&tp, NM_ATT_BTS_AIR_TIMER, 1)) {
|
||||
uint8_t t3105 = *TLVP_VAL(&tp, NM_ATT_BTS_AIR_TIMER);
|
||||
if (t3105 == 0) {
|
||||
LOGP(DOML, LOGL_NOTICE,
|
||||
@@ -518,15 +722,15 @@ static int oml_rx_set_bts_attr(struct gsm_bts *bts, struct msgb *msg)
|
||||
}
|
||||
|
||||
/* 9.4.37 NY1 */
|
||||
if (TLVP_PRESENT(&tp, NM_ATT_NY1))
|
||||
if (TLVP_PRES_LEN(&tp, NM_ATT_NY1, 1))
|
||||
btsb->ny1 = *TLVP_VAL(&tp, NM_ATT_NY1);
|
||||
|
||||
/* 9.4.8 BCCH ARFCN */
|
||||
if (TLVP_PRESENT(&tp, NM_ATT_BCCH_ARFCN))
|
||||
if (TLVP_PRES_LEN(&tp, NM_ATT_BCCH_ARFCN, 2))
|
||||
bts->c0->arfcn = ntohs(tlvp_val16_unal(&tp, NM_ATT_BCCH_ARFCN));
|
||||
|
||||
/* 9.4.9 BSIC */
|
||||
if (TLVP_PRESENT(&tp, NM_ATT_BSIC))
|
||||
if (TLVP_PRES_LEN(&tp, NM_ATT_BSIC, 1))
|
||||
bts->bsic = *TLVP_VAL(&tp, NM_ATT_BSIC);
|
||||
|
||||
/* call into BTS driver to apply new attributes to hardware */
|
||||
@@ -544,12 +748,16 @@ static int oml_rx_set_radio_attr(struct gsm_bts_trx *trx, struct msgb *msg)
|
||||
DEBUGPC(DOML, "Rx SET RADIO CARRIER ATTR\n");
|
||||
|
||||
rc = oml_tlv_parse(&tp, foh->data, msgb_l3len(msg) - sizeof(*foh));
|
||||
if (rc < 0)
|
||||
if (rc < 0) {
|
||||
oml_tx_failure_event_rep(&trx->mo, OSMO_EVT_MAJ_UNSUP_ATTR,
|
||||
"New value for Set Radio Attribute not"
|
||||
" supported");
|
||||
return oml_fom_ack_nack(msg, NM_NACK_INCORR_STRUCT);
|
||||
}
|
||||
|
||||
/* merge existing BTS attributes with new attributes */
|
||||
tp_merged = tlvp_copy(trx->mo.nm_attr, trx->bts);
|
||||
tlvp_merge(tp_merged, &tp);
|
||||
tp_merged = osmo_tlvp_copy(trx->mo.nm_attr, trx->bts);
|
||||
osmo_tlvp_merge(tp_merged, &tp);
|
||||
|
||||
/* Ask BTS driver to validate new merged attributes */
|
||||
rc = bts_model_check_oml(trx->bts, foh->msg_type, trx->mo.nm_attr, tp_merged, trx);
|
||||
@@ -565,7 +773,7 @@ static int oml_rx_set_radio_attr(struct gsm_bts_trx *trx, struct msgb *msg)
|
||||
/* ... and actually still parse them */
|
||||
|
||||
/* 9.4.47 RF Max Power Reduction */
|
||||
if (TLVP_PRESENT(&tp, NM_ATT_RF_MAXPOWR_R)) {
|
||||
if (TLVP_PRES_LEN(&tp, NM_ATT_RF_MAXPOWR_R, 1)) {
|
||||
trx->max_power_red = *TLVP_VAL(&tp, NM_ATT_RF_MAXPOWR_R) * 2;
|
||||
LOGP(DOML, LOGL_INFO, "Set RF Max Power Reduction = %d dBm\n",
|
||||
trx->max_power_red);
|
||||
@@ -590,25 +798,80 @@ static int oml_rx_set_radio_attr(struct gsm_bts_trx *trx, struct msgb *msg)
|
||||
trx->arfcn_num = length;
|
||||
} else
|
||||
trx->arfcn_num = 0;
|
||||
#else
|
||||
if (trx != trx->bts->c0 && TLVP_PRESENT(&tp, NM_ATT_ARFCN_LIST)) {
|
||||
const uint8_t *value = TLVP_VAL(&tp, NM_ATT_ARFCN_LIST);
|
||||
uint16_t _value;
|
||||
uint16_t length = TLVP_LEN(&tp, NM_ATT_ARFCN_LIST);
|
||||
uint16_t arfcn;
|
||||
if (length != 2) {
|
||||
LOGP(DOML, LOGL_ERROR, "Expecting only one ARFCN, "
|
||||
"because hopping not supported\n");
|
||||
/* FIXME: send NACK */
|
||||
return -ENOTSUP;
|
||||
}
|
||||
memcpy(&_value, value, 2);
|
||||
arfcn = ntohs(_value);
|
||||
value += 2;
|
||||
if (arfcn > 1024) {
|
||||
oml_tx_failure_event_rep(&trx->bts->mo,
|
||||
OSMO_EVT_WARN_SW_WARN,
|
||||
"Given ARFCN %u is unsupported",
|
||||
arfcn);
|
||||
LOGP(DOML, LOGL_NOTICE,
|
||||
"Given ARFCN %u is unsupported.\n", arfcn);
|
||||
return oml_fom_ack_nack(msg, NM_NACK_FREQ_NOTAVAIL);
|
||||
}
|
||||
trx->arfcn = arfcn;
|
||||
}
|
||||
#endif
|
||||
/* call into BTS driver to apply new attributes to hardware */
|
||||
return bts_model_apply_oml(trx->bts, msg, tp_merged, NM_OC_RADIO_CARRIER, trx);
|
||||
}
|
||||
|
||||
static int conf_lchans_for_pchan(struct gsm_bts_trx_ts *ts)
|
||||
static int conf_lchans(struct gsm_bts_trx_ts *ts)
|
||||
{
|
||||
enum gsm_phys_chan_config pchan = ts->pchan;
|
||||
|
||||
/* RSL_MT_IPAC_PDCH_ACT style dyn PDCH */
|
||||
if (pchan == GSM_PCHAN_TCH_F_PDCH)
|
||||
pchan = ts->flags & TS_F_PDCH_ACTIVE? GSM_PCHAN_PDCH
|
||||
: GSM_PCHAN_TCH_F;
|
||||
|
||||
/* Osmocom RSL CHAN ACT style dyn TS */
|
||||
if (pchan == GSM_PCHAN_TCH_F_TCH_H_PDCH) {
|
||||
pchan = ts->dyn.pchan_is;
|
||||
|
||||
/* If the dyn TS doesn't have a pchan yet, do nothing. */
|
||||
if (pchan == GSM_PCHAN_NONE)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return conf_lchans_as_pchan(ts, pchan);
|
||||
}
|
||||
|
||||
int conf_lchans_as_pchan(struct gsm_bts_trx_ts *ts,
|
||||
enum gsm_phys_chan_config pchan)
|
||||
{
|
||||
struct gsm_lchan *lchan;
|
||||
unsigned int i;
|
||||
|
||||
switch (ts->pchan) {
|
||||
switch (pchan) {
|
||||
case GSM_PCHAN_CCCH_SDCCH4_CBCH:
|
||||
/* fallthrough */
|
||||
case GSM_PCHAN_CCCH_SDCCH4:
|
||||
for (i = 0; i < 4; i++) {
|
||||
lchan = &ts->lchan[i];
|
||||
if (pchan == GSM_PCHAN_CCCH_SDCCH4_CBCH
|
||||
&& i == 2) {
|
||||
lchan->type = GSM_LCHAN_CBCH;
|
||||
} else {
|
||||
lchan->type = GSM_LCHAN_SDCCH;
|
||||
}
|
||||
}
|
||||
/* fallthrough */
|
||||
case GSM_PCHAN_CCCH:
|
||||
lchan = &ts->lchan[4];
|
||||
lchan = &ts->lchan[CCCH_LCHAN];
|
||||
lchan->type = GSM_LCHAN_CCCH;
|
||||
break;
|
||||
case GSM_PCHAN_TCH_F:
|
||||
@@ -621,19 +884,27 @@ static int conf_lchans_for_pchan(struct gsm_bts_trx_ts *ts)
|
||||
lchan->type = GSM_LCHAN_TCH_H;
|
||||
}
|
||||
break;
|
||||
case GSM_PCHAN_SDCCH8_SACCH8C_CBCH:
|
||||
/* fallthrough */
|
||||
case GSM_PCHAN_SDCCH8_SACCH8C:
|
||||
for (i = 0; i < 8; i++) {
|
||||
lchan = &ts->lchan[i];
|
||||
if (pchan == GSM_PCHAN_SDCCH8_SACCH8C_CBCH
|
||||
&& i == 2) {
|
||||
lchan->type = GSM_LCHAN_CBCH;
|
||||
} else {
|
||||
lchan->type = GSM_LCHAN_SDCCH;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GSM_PCHAN_PDCH:
|
||||
lchan = &ts->lchan[0];
|
||||
lchan->type = GSM_LCHAN_PDTCH;
|
||||
break;
|
||||
default:
|
||||
/* FIXME */
|
||||
break;
|
||||
LOGP(DOML, LOGL_ERROR, "Unknown/unhandled PCHAN type: %u %s\n",
|
||||
ts->pchan, gsm_pchan_name(ts->pchan));
|
||||
return -NM_NACK_PARAM_RANGE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -650,8 +921,12 @@ static int oml_rx_set_chan_attr(struct gsm_bts_trx_ts *ts, struct msgb *msg)
|
||||
DEBUGPC(DOML, "Rx SET CHAN ATTR\n");
|
||||
|
||||
rc = oml_tlv_parse(&tp, foh->data, msgb_l3len(msg) - sizeof(*foh));
|
||||
if (rc < 0)
|
||||
if (rc < 0) {
|
||||
oml_tx_failure_event_rep(&ts->mo, OSMO_EVT_MAJ_UNSUP_ATTR,
|
||||
"New value for Set Channel Attribute "
|
||||
"not supported");
|
||||
return oml_fom_ack_nack(msg, NM_NACK_INCORR_STRUCT);
|
||||
}
|
||||
|
||||
/* 9.4.21 HSN... */
|
||||
/* 9.4.27 MAIO */
|
||||
@@ -667,8 +942,8 @@ static int oml_rx_set_chan_attr(struct gsm_bts_trx_ts *ts, struct msgb *msg)
|
||||
}
|
||||
|
||||
/* merge existing BTS attributes with new attributes */
|
||||
tp_merged = tlvp_copy(ts->mo.nm_attr, bts);
|
||||
tlvp_merge(tp_merged, &tp);
|
||||
tp_merged = osmo_tlvp_copy(ts->mo.nm_attr, bts);
|
||||
osmo_tlvp_merge(tp_merged, &tp);
|
||||
|
||||
/* Call into BTS driver to check attribute values */
|
||||
rc = bts_model_check_oml(bts, foh->msg_type, ts->mo.nm_attr, tp_merged, ts);
|
||||
@@ -683,16 +958,21 @@ static int oml_rx_set_chan_attr(struct gsm_bts_trx_ts *ts, struct msgb *msg)
|
||||
ts->mo.nm_attr = tp_merged;
|
||||
|
||||
/* 9.4.13 Channel Combination */
|
||||
if (TLVP_PRESENT(&tp, NM_ATT_CHAN_COMB)) {
|
||||
if (TLVP_PRES_LEN(&tp, NM_ATT_CHAN_COMB, 1)) {
|
||||
uint8_t comb = *TLVP_VAL(&tp, NM_ATT_CHAN_COMB);
|
||||
ts->pchan = abis_nm_pchan4chcomb(comb);
|
||||
conf_lchans_for_pchan(ts);
|
||||
rc = conf_lchans(ts);
|
||||
if (rc < 0) {
|
||||
talloc_free(tp_merged);
|
||||
/* Send NACK */
|
||||
return oml_fom_ack_nack(msg, -rc);
|
||||
}
|
||||
}
|
||||
|
||||
/* 9.4.5 ARFCN List */
|
||||
|
||||
/* 9.4.60 TSC */
|
||||
if (TLVP_PRESENT(&tp, NM_ATT_TSC) && TLVP_LEN(&tp, NM_ATT_TSC) >= 1) {
|
||||
if (TLVP_PRES_LEN(&tp, NM_ATT_TSC, 1)) {
|
||||
ts->tsc = *TLVP_VAL(&tp, NM_ATT_TSC);
|
||||
} else {
|
||||
/* If there is no TSC specified, use the BCC */
|
||||
@@ -772,6 +1052,38 @@ static int oml_rx_chg_adm_state(struct gsm_bts *bts, struct msgb *msg)
|
||||
return bts_model_chg_adm_state(bts, mo, obj, adm_state);
|
||||
}
|
||||
|
||||
/* Check and report if the BTS number received via OML is incorrect:
|
||||
according to 3GPP TS 52.021 §9.3 BTS number is used to distinguish between different BTS of the same Site Manager.
|
||||
As we always have only single BTS per Site Manager (in case of Abis/IP with each BTS having dedicated OML connection
|
||||
to BSC), the only valid values are 0 and 0xFF (means all BTS' of a given Site Manager). */
|
||||
static inline bool report_bts_number_incorrect(struct gsm_bts *bts, const struct abis_om_fom_hdr *foh, bool is_formatted)
|
||||
{
|
||||
struct gsm_bts_trx *trx;
|
||||
struct gsm_abis_mo *mo = &bts->mo;
|
||||
const char *form = is_formatted ?
|
||||
"Unexpected BTS %d in formatted O&M %s (exp. 0 or 0xFF)" :
|
||||
"Unexpected BTS %d in manufacturer O&M %s (exp. 0 or 0xFF)";
|
||||
|
||||
if (foh->obj_inst.bts_nr != 0 && foh->obj_inst.bts_nr != 0xff) {
|
||||
LOGP(DOML, LOGL_ERROR, form, foh->obj_inst.bts_nr, get_value_string(abis_nm_msgtype_names,
|
||||
foh->msg_type));
|
||||
LOGPC(DOML, LOGL_ERROR, "\n");
|
||||
trx = gsm_bts_trx_num(bts, foh->obj_inst.trx_nr);
|
||||
if (trx) {
|
||||
trx->mo.obj_inst.bts_nr = 0;
|
||||
trx->mo.obj_inst.trx_nr = foh->obj_inst.trx_nr;
|
||||
trx->mo.obj_inst.ts_nr = 0xff;
|
||||
mo = &trx->mo;
|
||||
}
|
||||
oml_tx_failure_event_rep(mo, OSMO_EVT_MAJ_UKWN_MSG, form, foh->obj_inst.bts_nr,
|
||||
get_value_string(abis_nm_msgtype_names, foh->msg_type));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int down_fom(struct gsm_bts *bts, struct msgb *msg)
|
||||
{
|
||||
struct abis_om_fom_hdr *foh = msgb_l3(msg);
|
||||
@@ -780,13 +1092,19 @@ static int down_fom(struct gsm_bts *bts, struct msgb *msg)
|
||||
|
||||
if (msgb_l2len(msg) < sizeof(*foh)) {
|
||||
LOGP(DOML, LOGL_NOTICE, "Formatted O&M message too short\n");
|
||||
trx = gsm_bts_trx_num(bts, foh->obj_inst.trx_nr);
|
||||
if (trx) {
|
||||
trx->mo.obj_inst.bts_nr = 0;
|
||||
trx->mo.obj_inst.trx_nr = foh->obj_inst.trx_nr;
|
||||
trx->mo.obj_inst.ts_nr = 0xff;
|
||||
oml_tx_failure_event_rep(&trx->mo, OSMO_EVT_MAJ_UKWN_MSG,
|
||||
"Formatted O&M message too short");
|
||||
}
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (foh->obj_inst.bts_nr != 0 && foh->obj_inst.bts_nr != 0xff) {
|
||||
LOGP(DOML, LOGL_INFO, "Formatted O&M with BTS %d out of range.\n", foh->obj_inst.bts_nr);
|
||||
if (report_bts_number_incorrect(bts, foh, true))
|
||||
return oml_fom_ack_nack(msg, NM_NACK_BTSNR_UNKN);
|
||||
}
|
||||
|
||||
switch (foh->msg_type) {
|
||||
case NM_MT_SET_BTS_ATTR:
|
||||
@@ -815,9 +1133,26 @@ static int down_fom(struct gsm_bts *bts, struct msgb *msg)
|
||||
case NM_MT_IPACC_SET_ATTR:
|
||||
ret = oml_ipa_set_attr(bts, msg);
|
||||
break;
|
||||
case NM_MT_GET_ATTR:
|
||||
ret = oml_rx_get_attr(bts, msg);
|
||||
break;
|
||||
default:
|
||||
LOGP(DOML, LOGL_INFO, "unknown Formatted O&M msg_type 0x%02x\n",
|
||||
foh->msg_type);
|
||||
trx = gsm_bts_trx_num(bts, foh->obj_inst.trx_nr);
|
||||
if (trx) {
|
||||
trx->mo.obj_inst.bts_nr = 0;
|
||||
trx->mo.obj_inst.trx_nr = foh->obj_inst.trx_nr;
|
||||
trx->mo.obj_inst.ts_nr = 0xff;
|
||||
oml_tx_failure_event_rep(&trx->mo, OSMO_EVT_MAJ_UKWN_MSG,
|
||||
"unknown Formatted O&M "
|
||||
"msg_type 0x%02x",
|
||||
foh->msg_type);
|
||||
} else
|
||||
oml_tx_failure_event_rep(&bts->mo, OSMO_EVT_MAJ_UKWN_MSG,
|
||||
"unknown Formatted O&M "
|
||||
"msg_type 0x%02x",
|
||||
foh->msg_type);
|
||||
ret = oml_fom_ack_nack(msg, NM_NACK_MSGTYPE_INVAL);
|
||||
}
|
||||
|
||||
@@ -828,11 +1163,6 @@ static int down_fom(struct gsm_bts *bts, struct msgb *msg)
|
||||
* manufacturer related messages
|
||||
*/
|
||||
|
||||
#ifndef TLVP_PRES_LEN /* old libosmocore */
|
||||
#define TLVP_PRES_LEN(tp, tag, min_len) \
|
||||
(TLVP_PRESENT(tp, tag) && TLVP_LEN(tp, tag) >= min_len)
|
||||
#endif
|
||||
|
||||
static int oml_ipa_mo_set_attr_nse(void *obj, struct tlv_parsed *tp)
|
||||
{
|
||||
struct gsm_bts *bts = container_of(obj, struct gsm_bts, gprs.nse);
|
||||
@@ -986,8 +1316,15 @@ static int oml_ipa_set_attr(struct gsm_bts *bts, struct msgb *msg)
|
||||
DEBUGPC(DOML, "Rx IPA SET ATTR\n");
|
||||
|
||||
rc = oml_tlv_parse(&tp, foh->data, msgb_l3len(msg) - sizeof(*foh));
|
||||
if (rc < 0)
|
||||
if (rc < 0) {
|
||||
mo = gsm_objclass2mo(bts, foh->obj_class, &foh->obj_inst);
|
||||
if (!mo)
|
||||
return oml_fom_ack_nack(msg, NM_NACK_OBJINST_UNKN);
|
||||
oml_tx_failure_event_rep(mo, OSMO_EVT_MAJ_UNSUP_ATTR,
|
||||
"New value for IPAC Set Attribute not "
|
||||
"supported\n");
|
||||
return oml_fom_ack_nack(msg, NM_NACK_INCORR_STRUCT);
|
||||
}
|
||||
|
||||
/* Resolve MO by obj_class/obj_inst */
|
||||
mo = gsm_objclass2mo(bts, foh->obj_class, &foh->obj_inst);
|
||||
@@ -1011,13 +1348,13 @@ static int rx_oml_ipa_rsl_connect(struct gsm_bts_trx *trx, struct msgb *msg,
|
||||
|
||||
uint8_t stream_id = 0;
|
||||
|
||||
if (TLVP_PRESENT(tp, NM_ATT_IPACC_DST_IP)) {
|
||||
if (TLVP_PRES_LEN(tp, NM_ATT_IPACC_DST_IP, 4)) {
|
||||
ip = ntohl(tlvp_val32_unal(tp, NM_ATT_IPACC_DST_IP));
|
||||
}
|
||||
if (TLVP_PRESENT(tp, NM_ATT_IPACC_DST_IP_PORT)) {
|
||||
if (TLVP_PRES_LEN(tp, NM_ATT_IPACC_DST_IP_PORT, 2)) {
|
||||
port = ntohs(tlvp_val16_unal(tp, NM_ATT_IPACC_DST_IP_PORT));
|
||||
}
|
||||
if (TLVP_PRESENT(tp, NM_ATT_IPACC_STREAM_ID)) {
|
||||
if (TLVP_PRES_LEN(tp, NM_ATT_IPACC_STREAM_ID, 1)) {
|
||||
stream_id = *TLVP_VAL(tp, NM_ATT_IPACC_STREAM_ID);
|
||||
}
|
||||
|
||||
@@ -1025,7 +1362,8 @@ static int rx_oml_ipa_rsl_connect(struct gsm_bts_trx *trx, struct msgb *msg,
|
||||
LOGP(DOML, LOGL_INFO, "Rx IPA RSL CONNECT IP=%s PORT=%u STREAM=0x%02x\n",
|
||||
inet_ntoa(in), port, stream_id);
|
||||
|
||||
rc = e1inp_ipa_bts_rsl_connect(oml_link->ts->line, inet_ntoa(in), port);
|
||||
rc = e1inp_ipa_bts_rsl_connect_n(oml_link->ts->line, inet_ntoa(in), port,
|
||||
trx->nr);
|
||||
if (rc < 0) {
|
||||
LOGP(DOML, LOGL_ERROR, "Error in abis_open(RSL): %d\n", rc);
|
||||
return oml_fom_ack_nack(msg, NM_NACK_CANT_PERFORM);
|
||||
@@ -1056,10 +1394,8 @@ static int down_mom(struct gsm_bts *bts, struct msgb *msg)
|
||||
msg->l3h = oh->data + 1 + idstrlen;
|
||||
foh = (struct abis_om_fom_hdr *) msg->l3h;
|
||||
|
||||
if (foh->obj_inst.bts_nr != 0 && foh->obj_inst.bts_nr != 0xff) {
|
||||
LOGP(DOML, LOGL_INFO, "Manufacturer O&M with BTS %d out of range.\n", foh->obj_inst.bts_nr);
|
||||
if (report_bts_number_incorrect(bts, foh, false))
|
||||
return oml_fom_ack_nack(msg, NM_NACK_BTSNR_UNKN);
|
||||
}
|
||||
|
||||
ret = oml_tlv_parse(&tp, foh->data, oh->length - sizeof(*foh));
|
||||
if (ret < 0) {
|
||||
@@ -1128,10 +1464,23 @@ int down_oml(struct gsm_bts *bts, struct msgb *msg)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int oml_init(void)
|
||||
static int handle_fail_sig(unsigned int subsys, unsigned int signal, void *handle,
|
||||
void *signal_data)
|
||||
{
|
||||
DEBUGP(DOML, "Initializing OML attribute definitions\n");
|
||||
tlv_def_patch(&abis_nm_att_tlvdef_ipa, &abis_nm_att_tlvdef);
|
||||
if (signal_data)
|
||||
oml_tx_failure_event_rep(handle, signal, "%s", signal_data);
|
||||
else
|
||||
oml_tx_failure_event_rep(handle, signal, "");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int oml_init(struct gsm_abis_mo *mo)
|
||||
{
|
||||
DEBUGP(DOML, "Initializing OML attribute definitions\n");
|
||||
tlv_def_patch(&abis_nm_att_tlvdef_ipa_local, &abis_nm_att_tlvdef_ipa);
|
||||
tlv_def_patch(&abis_nm_att_tlvdef_ipa_local, &abis_nm_att_tlvdef);
|
||||
osmo_signal_register_handler(SS_FAIL, handle_fail_sig, mo);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -538,12 +538,6 @@ static int paging_signal_cbfn(unsigned int subsys, unsigned int signal, void *hd
|
||||
struct paging_state *ps = btsb->paging_state;
|
||||
struct gsm48_system_information_type_3 *si3 = (void *) bts->si_buf[SYSINFO_TYPE_3];
|
||||
|
||||
#warning "TODO: Remove this when setting u8NbrOfAgch is implemented properly"
|
||||
if (si3->control_channel_desc.bs_ag_blks_res != 1)
|
||||
LOGP(DPAG, LOGL_ERROR,
|
||||
"Paging: BS_AG_BLKS_RES = %d != 1 not fully supported\n",
|
||||
si3->control_channel_desc.bs_ag_blks_res);
|
||||
|
||||
paging_si_update(ps, &si3->control_channel_desc);
|
||||
}
|
||||
return 0;
|
||||
|
||||
@@ -29,9 +29,11 @@
|
||||
#include <assert.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <osmocom/core/talloc.h>
|
||||
#include <osmocom/core/select.h>
|
||||
#include <osmocom/core/socket.h>
|
||||
#include <osmo-bts/logging.h>
|
||||
#include <osmo-bts/gsm_data.h>
|
||||
#include <osmo-bts/pcu_if.h>
|
||||
@@ -39,12 +41,12 @@
|
||||
#include <osmo-bts/bts.h>
|
||||
#include <osmo-bts/rsl.h>
|
||||
#include <osmo-bts/signal.h>
|
||||
#include <osmo-bts/bts_model.h>
|
||||
#include <osmo-bts/l1sap.h>
|
||||
|
||||
uint32_t trx_get_hlayer1(struct gsm_bts_trx *trx);
|
||||
|
||||
extern struct gsm_network bts_gsmnet;
|
||||
extern int pcu_direct;
|
||||
int pcu_direct = 0;
|
||||
static int avail_lai = 0, avail_nse = 0, avail_cell = 0, avail_nsvc[2] = {0, 0};
|
||||
|
||||
static const char *sapi_string[] = {
|
||||
@@ -57,27 +59,7 @@ static const char *sapi_string[] = {
|
||||
[PCU_IF_SAPI_PTCCH] = "PTCCH",
|
||||
};
|
||||
|
||||
/* FIXME: common l1if include ? */
|
||||
int l1if_pdch_req(struct gsm_bts_trx_ts *ts, int is_ptcch, uint32_t fn,
|
||||
uint16_t arfcn, uint8_t block_nr, uint8_t *data, uint8_t len);
|
||||
|
||||
static int pcu_sock_send(struct gsm_network *net, struct msgb *msg);
|
||||
/* FIXME: move this to libosmocore */
|
||||
int osmo_unixsock_listen(struct osmo_fd *bfd, int type, const char *path);
|
||||
|
||||
|
||||
static struct gsm_bts_trx *trx_by_nr(struct gsm_bts *bts, uint8_t trx_nr)
|
||||
{
|
||||
struct gsm_bts_trx *trx;
|
||||
|
||||
llist_for_each_entry(trx, &bts->trx_list, list) {
|
||||
if (trx->nr == trx_nr)
|
||||
return trx;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* PCU messages
|
||||
@@ -99,6 +81,32 @@ struct msgb *pcu_msgb_alloc(uint8_t msg_type, uint8_t bts_nr)
|
||||
return msg;
|
||||
}
|
||||
|
||||
static bool ts_should_be_pdch(struct gsm_bts_trx_ts *ts) {
|
||||
if (ts->pchan == GSM_PCHAN_PDCH)
|
||||
return true;
|
||||
if (ts->pchan == GSM_PCHAN_TCH_F_PDCH) {
|
||||
/* When we're busy deactivating the PDCH, we first set
|
||||
* DEACT_PENDING, tell the PCU about it and wait for a
|
||||
* response. So DEACT_PENDING means "no PDCH" to the PCU.
|
||||
* Similarly, when we're activating PDCH, we set the
|
||||
* ACT_PENDING and wait for an activation response from the
|
||||
* PCU, so ACT_PENDING means "is PDCH". */
|
||||
if (ts->flags & TS_F_PDCH_ACTIVE)
|
||||
return !(ts->flags & TS_F_PDCH_DEACT_PENDING);
|
||||
else
|
||||
return (ts->flags & TS_F_PDCH_ACT_PENDING);
|
||||
}
|
||||
if (ts->pchan == GSM_PCHAN_TCH_F_TCH_H_PDCH) {
|
||||
/*
|
||||
* When we're busy de-/activating the PDCH, we first set
|
||||
* ts->dyn.pchan_want, tell the PCU about it and wait for a
|
||||
* response. So only care about dyn.pchan_want here.
|
||||
*/
|
||||
return ts->dyn.pchan_want == GSM_PCHAN_PDCH;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int pcu_tx_info_ind(void)
|
||||
{
|
||||
struct gsm_network *net = &bts_gsmnet;
|
||||
@@ -202,7 +210,7 @@ int pcu_tx_info_ind(void)
|
||||
}
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
trx = trx_by_nr(bts, i);
|
||||
trx = gsm_bts_trx_num(bts, i);
|
||||
if (!trx)
|
||||
break;
|
||||
info_ind->trx[i].pdch_mask = 0;
|
||||
@@ -211,10 +219,10 @@ int pcu_tx_info_ind(void)
|
||||
for (j = 0; j < 8; j++) {
|
||||
ts = &trx->ts[j];
|
||||
if (ts->mo.nm_state.operational == NM_OPSTATE_ENABLED
|
||||
&& ts->pchan == GSM_PCHAN_PDCH) {
|
||||
&& ts_should_be_pdch(ts)) {
|
||||
info_ind->trx[i].pdch_mask |= (1 << j);
|
||||
info_ind->trx[i].tsc[j] =
|
||||
(ts->tsc >= 0) ? ts->tsc : bts->tsc;
|
||||
(ts->tsc >= 0) ? ts->tsc : bts->bsic & 7;
|
||||
LOGP(DPCU, LOGL_INFO, "trx=%d ts=%d: "
|
||||
"available (tsc=%d arfcn=%d)\n",
|
||||
trx->nr, ts->nr,
|
||||
@@ -314,18 +322,24 @@ int pcu_tx_rts_req(struct gsm_bts_trx_ts *ts, uint8_t is_ptcch, uint32_t fn,
|
||||
return pcu_sock_send(&bts_gsmnet, msg);
|
||||
}
|
||||
|
||||
int pcu_tx_data_ind(struct gsm_bts_trx_ts *ts, uint8_t is_ptcch, uint32_t fn,
|
||||
int pcu_tx_data_ind(struct gsm_bts_trx_ts *ts, uint8_t sapi, uint32_t fn,
|
||||
uint16_t arfcn, uint8_t block_nr, uint8_t *data, uint8_t len,
|
||||
int8_t rssi)
|
||||
int8_t rssi, uint16_t ber10k, int16_t bto, int16_t lqual)
|
||||
{
|
||||
struct msgb *msg;
|
||||
struct gsm_pcu_if *pcu_prim;
|
||||
struct gsm_pcu_if_data *data_ind;
|
||||
struct gsm_bts *bts = ts->trx->bts;
|
||||
struct gsm_bts_role_bts *btsb = bts_role_bts(bts);
|
||||
|
||||
LOGP(DPCU, LOGL_DEBUG, "Sending data indication: is_ptcch=%d arfcn=%d "
|
||||
"block=%d data=%s\n", is_ptcch, arfcn, block_nr,
|
||||
osmo_hexdump(data, len));
|
||||
LOGP(DPCU, LOGL_DEBUG, "Sending data indication: sapi=%s arfcn=%d block=%d data=%s\n",
|
||||
sapi_string[sapi], arfcn, block_nr, osmo_hexdump(data, len));
|
||||
|
||||
if (lqual / 10 < btsb->min_qual_norm) {
|
||||
LOGP(DPCU, LOGL_DEBUG, "Link quality %"PRId16" is below threshold %f, dropping packet\n",
|
||||
lqual, btsb->min_qual_norm);
|
||||
return 0;
|
||||
}
|
||||
|
||||
msg = pcu_msgb_alloc(PCU_IF_MSG_DATA_IND, bts->nr);
|
||||
if (!msg)
|
||||
@@ -333,20 +347,25 @@ int pcu_tx_data_ind(struct gsm_bts_trx_ts *ts, uint8_t is_ptcch, uint32_t fn,
|
||||
pcu_prim = (struct gsm_pcu_if *) msg->data;
|
||||
data_ind = &pcu_prim->u.data_ind;
|
||||
|
||||
data_ind->sapi = (is_ptcch) ? PCU_IF_SAPI_PTCCH : PCU_IF_SAPI_PDTCH;
|
||||
data_ind->sapi = sapi;
|
||||
data_ind->rssi = rssi;
|
||||
data_ind->fn = fn;
|
||||
data_ind->arfcn = arfcn;
|
||||
data_ind->trx_nr = ts->trx->nr;
|
||||
data_ind->ts_nr = ts->nr;
|
||||
data_ind->block_nr = block_nr;
|
||||
data_ind->rssi = rssi;
|
||||
data_ind->ber10k = ber10k;
|
||||
data_ind->ta_offs_qbits = bto;
|
||||
data_ind->lqual_cb = lqual;
|
||||
memcpy(data_ind->data, data, len);
|
||||
data_ind->len = len;
|
||||
|
||||
return pcu_sock_send(&bts_gsmnet, msg);
|
||||
}
|
||||
|
||||
int pcu_tx_rach_ind(struct gsm_bts *bts, int16_t qta, uint8_t ra, uint32_t fn)
|
||||
int pcu_tx_rach_ind(struct gsm_bts *bts, int16_t qta, uint16_t ra, uint32_t fn,
|
||||
uint8_t is_11bit, enum ph_burst_type burst_type)
|
||||
{
|
||||
struct msgb *msg;
|
||||
struct gsm_pcu_if *pcu_prim;
|
||||
@@ -365,6 +384,8 @@ int pcu_tx_rach_ind(struct gsm_bts *bts, int16_t qta, uint8_t ra, uint32_t fn)
|
||||
rach_ind->ra = ra;
|
||||
rach_ind->qta = qta;
|
||||
rach_ind->fn = fn;
|
||||
rach_ind->is_11bit = is_11bit;
|
||||
rach_ind->burst_type = burst_type;
|
||||
|
||||
return pcu_sock_send(&bts_gsmnet, msg);
|
||||
}
|
||||
@@ -466,16 +487,6 @@ static int pcu_rx_data_req(struct gsm_bts *bts, uint8_t msg_type,
|
||||
osmo_hexdump(data_req->data, data_req->len));
|
||||
|
||||
switch (data_req->sapi) {
|
||||
case PCU_IF_SAPI_BCCH:
|
||||
if (data_req->len == 23) {
|
||||
bts->si_valid |= (1 << SYSINFO_TYPE_13);
|
||||
memcpy(bts->si_buf[SYSINFO_TYPE_13], data_req->data,
|
||||
data_req->len);
|
||||
} else {
|
||||
bts->si_valid &= ~(1 << SYSINFO_TYPE_13);
|
||||
}
|
||||
osmo_signal_dispatch(SS_GLOBAL, S_NEW_SYSINFO, bts);
|
||||
break;
|
||||
case PCU_IF_SAPI_PCH:
|
||||
if (msg_type == PCU_IF_MSG_PAG_REQ) {
|
||||
/* FIXME: Add function to schedule paging request.
|
||||
@@ -503,7 +514,7 @@ static int pcu_rx_data_req(struct gsm_bts *bts, uint8_t msg_type,
|
||||
break;
|
||||
case PCU_IF_SAPI_PDTCH:
|
||||
case PCU_IF_SAPI_PTCCH:
|
||||
trx = trx_by_nr(bts, data_req->trx_nr);
|
||||
trx = gsm_bts_trx_num(bts, data_req->trx_nr);
|
||||
if (!trx) {
|
||||
LOGP(DPCU, LOGL_ERROR, "Received PCU data request with "
|
||||
"not existing TRX %d\n", data_req->trx_nr);
|
||||
@@ -512,7 +523,7 @@ static int pcu_rx_data_req(struct gsm_bts *bts, uint8_t msg_type,
|
||||
}
|
||||
ts = &trx->ts[data_req->ts_nr];
|
||||
is_ptcch = (data_req->sapi == PCU_IF_SAPI_PTCCH);
|
||||
rc = l1if_pdch_req(ts, is_ptcch, data_req->fn, data_req->arfcn,
|
||||
rc = l1sap_pdch_req(ts, is_ptcch, data_req->fn, data_req->arfcn,
|
||||
data_req->block_nr, data_req->data, data_req->len);
|
||||
break;
|
||||
default:
|
||||
@@ -524,6 +535,48 @@ static int pcu_rx_data_req(struct gsm_bts *bts, uint8_t msg_type,
|
||||
return rc;
|
||||
}
|
||||
|
||||
int pcu_tx_si13(const struct gsm_bts *bts, bool enable)
|
||||
{
|
||||
/* the SI is per-BTS so it doesn't matter which TRX we use */
|
||||
struct gsm_bts_trx *trx = gsm_bts_trx_num(bts, 0);
|
||||
|
||||
/* The low-level data like FN, ARFCN etc will be ignored but we have to set lqual high enough to bypass
|
||||
the check at lower levels */
|
||||
int rc = pcu_tx_data_ind(&trx->ts[0], PCU_IF_SAPI_BCCH, 0, 0, 0, GSM_BTS_SI(bts, SYSINFO_TYPE_13),
|
||||
enable ? GSM_MACBLOCK_LEN : 0, 0, 0, 0, INT16_MAX);
|
||||
if (rc < 0)
|
||||
LOGP(DPCU, LOGL_NOTICE, "Failed to send SI13 to PCU: %d\n", rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int pcu_rx_txt_ind(struct gsm_bts *bts,
|
||||
struct gsm_pcu_if_txt_ind *txt)
|
||||
{
|
||||
switch (txt->type) {
|
||||
case PCU_VERSION:
|
||||
LOGP(DPCU, LOGL_INFO, "OsmoPCU version %s connected\n",
|
||||
txt->text);
|
||||
osmo_signal_dispatch(SS_FAIL, OSMO_EVT_PCU_VERS, txt->text);
|
||||
osmo_strlcpy(bts->pcu_version, txt->text, MAX_VERSION_LENGTH);
|
||||
|
||||
if (GSM_BTS_HAS_SI(bts, SYSINFO_TYPE_13))
|
||||
return pcu_tx_si13(bts, true);
|
||||
|
||||
LOGP(DPCU, LOGL_INFO, "SI13 is not available on PCU connection\n");
|
||||
break;
|
||||
case PCU_OML_ALERT:
|
||||
osmo_signal_dispatch(SS_FAIL, OSMO_EVT_EXT_ALARM, txt->text);
|
||||
break;
|
||||
default:
|
||||
LOGP(DPCU, LOGL_ERROR, "Unknown TXT_IND type %u received\n",
|
||||
txt->type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pcu_rx_act_req(struct gsm_bts *bts,
|
||||
struct gsm_pcu_if_act_req *act_req)
|
||||
{
|
||||
@@ -534,21 +587,23 @@ static int pcu_rx_act_req(struct gsm_bts *bts,
|
||||
(act_req->activate) ? "Activate" : "Deactivate",
|
||||
act_req->trx_nr, act_req->ts_nr);
|
||||
|
||||
trx = trx_by_nr(bts, act_req->trx_nr);
|
||||
trx = gsm_bts_trx_num(bts, act_req->trx_nr);
|
||||
if (!trx || act_req->ts_nr >= 8)
|
||||
return -EINVAL;
|
||||
|
||||
lchan = trx->ts[act_req->ts_nr].lchan;
|
||||
lchan->rel_act_kind = LCHAN_REL_ACT_PCU;
|
||||
if (lchan->type != GSM_LCHAN_PDTCH) {
|
||||
LOGP(DPCU, LOGL_ERROR, "Lchan is not of type PDCH, but %d.\n",
|
||||
lchan->type);
|
||||
LOGP(DPCU, LOGL_ERROR,
|
||||
"%s request, but lchan is not of type PDTCH (is %s)\n",
|
||||
(act_req->activate) ? "Activate" : "Deactivate",
|
||||
gsm_lchant_name(lchan->type));
|
||||
return -EINVAL;
|
||||
}
|
||||
if (act_req->activate)
|
||||
bts_model_rsl_chan_act(lchan, NULL);
|
||||
l1sap_chan_act(trx, gsm_lchan2chan_nr(lchan), NULL);
|
||||
else
|
||||
bts_model_rsl_chan_rel(lchan);
|
||||
l1sap_chan_rel(trx, gsm_lchan2chan_nr(lchan));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -570,6 +625,9 @@ static int pcu_rx(struct gsm_network *net, uint8_t msg_type,
|
||||
case PCU_IF_MSG_ACT_REQ:
|
||||
rc = pcu_rx_act_req(bts, &pcu_prim->u.act_req);
|
||||
break;
|
||||
case PCU_IF_MSG_TXT_IND:
|
||||
rc = pcu_rx_txt_ind(bts, &pcu_prim->u.txt_ind);
|
||||
break;
|
||||
default:
|
||||
LOGP(DPCU, LOGL_ERROR, "Received unknwon PCU msg type %d\n",
|
||||
msg_type);
|
||||
@@ -629,6 +687,8 @@ static void pcu_sock_close(struct pcu_sock_state *state)
|
||||
bts = llist_entry(state->net->bts_list.next, struct gsm_bts, list);
|
||||
|
||||
LOGP(DPCU, LOGL_NOTICE, "PCU socket has LOST connection\n");
|
||||
osmo_signal_dispatch(SS_FAIL, OSMO_EVT_PCU_VERS, NULL);
|
||||
bts->pcu_version[0] = '\0';
|
||||
|
||||
close(bfd->fd);
|
||||
bfd->fd = -1;
|
||||
@@ -645,7 +705,7 @@ static void pcu_sock_close(struct pcu_sock_state *state)
|
||||
|
||||
/* release PDCH */
|
||||
for (i = 0; i < 8; i++) {
|
||||
trx = trx_by_nr(bts, i);
|
||||
trx = gsm_bts_trx_num(bts, i);
|
||||
if (!trx)
|
||||
break;
|
||||
for (j = 0; j < 8; j++) {
|
||||
@@ -653,7 +713,8 @@ static void pcu_sock_close(struct pcu_sock_state *state)
|
||||
if (ts->mo.nm_state.operational == NM_OPSTATE_ENABLED
|
||||
&& ts->pchan == GSM_PCHAN_PDCH) {
|
||||
ts->lchan->rel_act_kind = LCHAN_REL_ACT_PCU;
|
||||
bts_model_rsl_chan_rel(ts->lchan);
|
||||
l1sap_chan_rel(trx,
|
||||
gsm_lchan2chan_nr(ts->lchan));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -811,7 +872,7 @@ static int pcu_sock_accept(struct osmo_fd *bfd, unsigned int flags)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pcu_sock_init(void)
|
||||
int pcu_sock_init(const char *path)
|
||||
{
|
||||
struct pcu_sock_state *state;
|
||||
struct osmo_fd *bfd;
|
||||
@@ -827,12 +888,13 @@ int pcu_sock_init(void)
|
||||
|
||||
bfd = &state->listen_bfd;
|
||||
|
||||
rc = osmo_unixsock_listen(bfd, SOCK_SEQPACKET, "/tmp/pcu_bts");
|
||||
if (rc < 0) {
|
||||
LOGP(DPCU, LOGL_ERROR, "Could not create unix socket: %s\n",
|
||||
strerror(errno));
|
||||
bfd->fd = osmo_sock_unix_init(SOCK_SEQPACKET, 0, path,
|
||||
OSMO_SOCK_F_BIND);
|
||||
if (bfd->fd < 0) {
|
||||
LOGP(DPCU, LOGL_ERROR, "Could not create %s unix socket: %s\n",
|
||||
path, strerror(errno));
|
||||
talloc_free(state);
|
||||
return rc;
|
||||
return -1;
|
||||
}
|
||||
|
||||
bfd->when = BSC_FD_READ;
|
||||
@@ -874,53 +936,13 @@ void pcu_sock_exit(void)
|
||||
bts_gsmnet.pcu_state = NULL;
|
||||
}
|
||||
|
||||
/* FIXME: move this to libosmocore */
|
||||
int osmo_unixsock_listen(struct osmo_fd *bfd, int type, const char *path)
|
||||
{
|
||||
struct sockaddr_un local;
|
||||
unsigned int namelen;
|
||||
int rc;
|
||||
bool pcu_connected(void) {
|
||||
struct gsm_network *net = &bts_gsmnet;
|
||||
struct pcu_sock_state *state = net->pcu_state;
|
||||
|
||||
bfd->fd = socket(AF_UNIX, type, 0);
|
||||
|
||||
if (bfd->fd < 0) {
|
||||
fprintf(stderr, "Failed to create Unix Domain Socket.\n");
|
||||
return -1;
|
||||
if (!state)
|
||||
return false;
|
||||
if (state->conn_bfd.fd <= 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
local.sun_family = AF_UNIX;
|
||||
strncpy(local.sun_path, path, sizeof(local.sun_path));
|
||||
local.sun_path[sizeof(local.sun_path) - 1] = '\0';
|
||||
unlink(local.sun_path);
|
||||
|
||||
/* we use the same magic that X11 uses in Xtranssock.c for
|
||||
* calculating the proper length of the sockaddr */
|
||||
#if defined(BSD44SOCKETS) || defined(__UNIXWARE__)
|
||||
local.sun_len = strlen(local.sun_path);
|
||||
#endif
|
||||
#if defined(BSD44SOCKETS) || defined(SUN_LEN)
|
||||
namelen = SUN_LEN(&local);
|
||||
#else
|
||||
namelen = strlen(local.sun_path) +
|
||||
offsetof(struct sockaddr_un, sun_path);
|
||||
#endif
|
||||
|
||||
rc = bind(bfd->fd, (struct sockaddr *) &local, namelen);
|
||||
if (rc != 0) {
|
||||
fprintf(stderr, "Failed to bind the unix domain socket. '%s'\n",
|
||||
local.sun_path);
|
||||
close(bfd->fd);
|
||||
bfd->fd = -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (listen(bfd->fd, 0) != 0) {
|
||||
fprintf(stderr, "Failed to listen.\n");
|
||||
close(bfd->fd);
|
||||
bfd->fd = -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
163
src/common/phy_link.c
Normal file
163
src/common/phy_link.c
Normal file
@@ -0,0 +1,163 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#include <osmocom/core/linuxlist.h>
|
||||
#include <osmocom/core/talloc.h>
|
||||
|
||||
#include <osmo-bts/bts.h>
|
||||
#include <osmo-bts/gsm_data.h>
|
||||
#include <osmo-bts/phy_link.h>
|
||||
#include <osmo-bts/oml.h>
|
||||
#include <osmo-bts/logging.h>
|
||||
#include <osmo-bts/bts_model.h>
|
||||
|
||||
static LLIST_HEAD(g_phy_links);
|
||||
|
||||
struct phy_link *phy_link_by_num(int num)
|
||||
{
|
||||
struct phy_link *plink;
|
||||
|
||||
llist_for_each_entry(plink, &g_phy_links, list) {
|
||||
if (plink->num == num)
|
||||
return plink;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct phy_link *phy_link_create(void *ctx, int num)
|
||||
{
|
||||
struct phy_link *plink;
|
||||
|
||||
if (phy_link_by_num(num))
|
||||
return NULL;
|
||||
|
||||
plink = talloc_zero(ctx, struct phy_link);
|
||||
plink->num = num;
|
||||
plink->state = PHY_LINK_SHUTDOWN;
|
||||
INIT_LLIST_HEAD(&plink->instances);
|
||||
llist_add_tail(&plink->list, &g_phy_links);
|
||||
|
||||
bts_model_phy_link_set_defaults(plink);
|
||||
|
||||
return plink;
|
||||
}
|
||||
|
||||
const struct value_string phy_link_state_vals[] = {
|
||||
{ PHY_LINK_SHUTDOWN, "shutdown" },
|
||||
{ PHY_LINK_CONNECTING, "connecting" },
|
||||
{ PHY_LINK_CONNECTED, "connected" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
void phy_link_state_set(struct phy_link *plink, enum phy_link_state state)
|
||||
{
|
||||
struct phy_instance *pinst;
|
||||
|
||||
LOGP(DL1C, LOGL_INFO, "PHY link state change %s -> %s\n",
|
||||
get_value_string(phy_link_state_vals, plink->state),
|
||||
get_value_string(phy_link_state_vals, state));
|
||||
|
||||
/* notify all TRX associated with this phy */
|
||||
llist_for_each_entry(pinst, &plink->instances, list) {
|
||||
struct gsm_bts_trx *trx = pinst->trx;
|
||||
if (!trx)
|
||||
continue;
|
||||
|
||||
switch (state) {
|
||||
case PHY_LINK_CONNECTED:
|
||||
LOGP(DL1C, LOGL_INFO, "trx_set_avail(1)\n");
|
||||
trx_set_available(trx, 1);
|
||||
break;
|
||||
case PHY_LINK_SHUTDOWN:
|
||||
LOGP(DL1C, LOGL_INFO, "trx_set_avail(0)\n");
|
||||
trx_set_available(trx, 0);
|
||||
break;
|
||||
case PHY_LINK_CONNECTING:
|
||||
/* nothing to do */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
plink->state = state;
|
||||
}
|
||||
|
||||
struct phy_instance *phy_instance_by_num(struct phy_link *plink, int num)
|
||||
{
|
||||
struct phy_instance *pinst;
|
||||
|
||||
llist_for_each_entry(pinst, &plink->instances, list) {
|
||||
if (pinst->num == num)
|
||||
return pinst;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct phy_instance *phy_instance_create(struct phy_link *plink, int num)
|
||||
{
|
||||
struct phy_instance *pinst;
|
||||
|
||||
if (phy_instance_by_num(plink, num))
|
||||
return NULL;
|
||||
|
||||
pinst = talloc_zero(plink, struct phy_instance);
|
||||
pinst->num = num;
|
||||
pinst->phy_link = plink;
|
||||
llist_add_tail(&pinst->list, &plink->instances);
|
||||
|
||||
bts_model_phy_instance_set_defaults(pinst);
|
||||
|
||||
return pinst;
|
||||
}
|
||||
|
||||
void phy_instance_link_to_trx(struct phy_instance *pinst, struct gsm_bts_trx *trx)
|
||||
{
|
||||
trx->role_bts.l1h = pinst;
|
||||
pinst->trx = trx;
|
||||
}
|
||||
|
||||
void phy_instance_destroy(struct phy_instance *pinst)
|
||||
{
|
||||
/* remove from list of instances in the link */
|
||||
llist_del(&pinst->list);
|
||||
|
||||
/* remove reverse link from TRX */
|
||||
OSMO_ASSERT(pinst->trx->role_bts.l1h == pinst);
|
||||
pinst->trx->role_bts.l1h = NULL;
|
||||
pinst->trx = NULL;
|
||||
|
||||
talloc_free(pinst);
|
||||
}
|
||||
|
||||
void phy_link_destroy(struct phy_link *plink)
|
||||
{
|
||||
struct phy_instance *pinst, *pinst2;
|
||||
|
||||
llist_for_each_entry_safe(pinst, pinst2, &plink->instances, list)
|
||||
phy_instance_destroy(pinst);
|
||||
|
||||
talloc_free(plink);
|
||||
}
|
||||
|
||||
int phy_links_open(void)
|
||||
{
|
||||
struct phy_link *plink;
|
||||
|
||||
llist_for_each_entry(plink, &g_phy_links, list) {
|
||||
int rc;
|
||||
|
||||
rc = bts_model_phy_link_open(plink);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *phy_instance_name(struct phy_instance *pinst)
|
||||
{
|
||||
static char buf[32];
|
||||
|
||||
snprintf(buf, sizeof(buf), "phy%u.%u", pinst->phy_link->num,
|
||||
pinst->num);
|
||||
return buf;
|
||||
}
|
||||
99
src/common/power_control.c
Normal file
99
src/common/power_control.c
Normal file
@@ -0,0 +1,99 @@
|
||||
/* MS Power Control Loop L1 */
|
||||
|
||||
/* (C) 2014 by Holger Hans Peter Freyther
|
||||
*
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <osmo-bts/logging.h>
|
||||
#include <osmo-bts/bts.h>
|
||||
#include <osmo-bts/gsm_data.h>
|
||||
#include <osmo-bts/measurement.h>
|
||||
#include <osmo-bts/bts_model.h>
|
||||
#include <osmo-bts/l1sap.h>
|
||||
|
||||
/*
|
||||
* Check if manual power control is needed
|
||||
* Check if fixed power was selected
|
||||
* Check if the MS is already using our level if not
|
||||
* the value is bogus..
|
||||
* TODO: Add a timeout.. e.g. if the ms is not capable of reaching
|
||||
* the value we have set.
|
||||
*/
|
||||
int lchan_ms_pwr_ctrl(struct gsm_lchan *lchan,
|
||||
const uint8_t ms_power, const int rxLevel)
|
||||
{
|
||||
int rx;
|
||||
int cur_dBm, new_dBm, new_pwr;
|
||||
struct gsm_bts *bts = lchan->ts->trx->bts;
|
||||
struct gsm_bts_role_bts *btsb = bts_role_bts(bts);
|
||||
const enum gsm_band band = bts->band;
|
||||
|
||||
if (!trx_ms_pwr_ctrl_is_osmo(lchan->ts->trx))
|
||||
return 0;
|
||||
if (lchan->ms_power_ctrl.fixed)
|
||||
return 0;
|
||||
|
||||
/* The phone hasn't reached the power level yet */
|
||||
if (lchan->ms_power_ctrl.current != ms_power)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* What is the difference between what we want and received?
|
||||
* Ignore a margin that is within the range of measurement
|
||||
* and MS output issues.
|
||||
*/
|
||||
rx = btsb->ul_power_target - rxLevel;
|
||||
if (rx >= 0 && rx < 1)
|
||||
return 0;
|
||||
if (rx < 0 && rx > -1)
|
||||
return 0;
|
||||
|
||||
/* We don't really care about the truncation of int + float */
|
||||
cur_dBm = ms_pwr_dbm(band, ms_power);
|
||||
new_dBm = cur_dBm + rx;
|
||||
|
||||
/* Clamp negative values and do it depending on the band */
|
||||
if (new_dBm < 0)
|
||||
new_dBm = 0;
|
||||
|
||||
switch (band) {
|
||||
case GSM_BAND_1800:
|
||||
/* If MS_TX_PWR_MAX_CCH is set the values 29,
|
||||
* 30, 31 are not used. Avoid specifying a dBm
|
||||
* that would lead to these power levels. The
|
||||
* phone might not be able to reach them. */
|
||||
if (new_dBm > 30)
|
||||
new_dBm = 30;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
new_pwr = ms_pwr_ctl_lvl(band, new_dBm);
|
||||
if (lchan->ms_power_ctrl.current != new_pwr) {
|
||||
lchan->ms_power_ctrl.current = new_pwr;
|
||||
bts_model_adjst_ms_pwr(lchan);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
1074
src/common/rsl.c
1074
src/common/rsl.c
File diff suppressed because it is too large
Load Diff
1712
src/common/scheduler.c
Normal file
1712
src/common/scheduler.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,82 +0,0 @@
|
||||
/* (C) 2011 by Andreas Eversberg <jolly@eversberg.eu>
|
||||
*
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <string.h>
|
||||
#include <osmocom/gsm/protocol/gsm_12_21.h>
|
||||
//#include <osmocom/bb/common/osmocom_data.h>
|
||||
#include <osmo-bts/support.h>
|
||||
|
||||
struct bts_support bts_support;
|
||||
|
||||
void bts_support_init(void)
|
||||
{
|
||||
struct bts_support *sup = &bts_support;
|
||||
int i;
|
||||
|
||||
memset(sup, 0, sizeof(*sup));
|
||||
|
||||
/* crypto supprot */
|
||||
sup->a5_1 = 0;
|
||||
sup->a5_2 = 0;
|
||||
sup->a5_3 = 0;
|
||||
sup->a5_4 = 0;
|
||||
sup->a5_5 = 0;
|
||||
sup->a5_6 = 0;
|
||||
sup->a5_7 = 0;
|
||||
/* set supported frequencies */
|
||||
for(i = 1; i <= 124; i++) // P-GSM
|
||||
sup->freq_map[i >> 3] |= (1 << (i & 7));
|
||||
for(i = 512; i <= 885; i++) // DCS
|
||||
sup->freq_map[i >> 3] |= (1 << (i & 7));
|
||||
for(i = 975; i <= 1023; i++) // E-GSM extension
|
||||
sup->freq_map[i >> 3] |= (1 << (i & 7));
|
||||
sup->freq_map[0] |= 1; // channel 0
|
||||
for(i = 955; i <= 974; i++) // R-GSM extension
|
||||
sup->freq_map[i >> 3] |= (1 << (i & 7));
|
||||
/* channel combinations */
|
||||
sup->chan_comb[NM_CHANC_mainBCCH] = 1;
|
||||
sup->chan_comb[NM_CHANC_BCCHComb] = 1;
|
||||
sup->chan_comb[NM_CHANC_SDCCH] = 1;
|
||||
sup->chan_comb[NM_CHANC_TCHFull] = 1;
|
||||
sup->chan_comb[NM_CHANC_TCHHalf] = 1;
|
||||
/* codec */
|
||||
sup->full_v1 = 1;
|
||||
sup->full_v2 = 1;
|
||||
sup->full_v3 = 1;
|
||||
sup->half_v1 = 1;
|
||||
sup->half_v3 = 1;
|
||||
}
|
||||
|
||||
char *bts_support_comb_name(uint8_t chan_comb)
|
||||
{
|
||||
if (chan_comb == NM_CHANC_mainBCCH)
|
||||
return("BCCH");
|
||||
if (chan_comb == NM_CHANC_BCCHComb)
|
||||
return("BCCH+SDCCH/4");
|
||||
if (chan_comb == NM_CHANC_SDCCH)
|
||||
return("SDCCH/8");
|
||||
if (chan_comb == NM_CHANC_TCHFull)
|
||||
return("TCH/F");
|
||||
if (chan_comb == NM_CHANC_TCHHalf)
|
||||
return("TCH/H");
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
|
||||
@@ -22,12 +22,21 @@
|
||||
#include <osmocom/gsm/gsm_utils.h>
|
||||
#include <osmocom/gsm/sysinfo.h>
|
||||
|
||||
#include <osmo-bts/logging.h>
|
||||
#include <osmo-bts/gsm_data.h>
|
||||
|
||||
#define BTS_HAS_SI(bts, sinum) ((bts)->si_valid & (1 << sinum))
|
||||
/* properly increment SI2q index and return SI2q data for scheduling */
|
||||
static inline uint8_t *get_si2q_inc_index(struct gsm_bts *bts)
|
||||
{
|
||||
uint8_t i = bts->si2q_index;
|
||||
/* si2q_count is the max si2q_index value, not the number of messages */
|
||||
bts->si2q_index = (bts->si2q_index + 1) % (bts->si2q_count + 1);
|
||||
|
||||
return (uint8_t *)GSM_BTS_SI2Q(bts, i);
|
||||
}
|
||||
|
||||
/* Apply the rules from 05.02 6.3.1.3 Mapping of BCCH Data */
|
||||
uint8_t *bts_sysinfo_get(struct gsm_bts *bts, struct gsm_time *g_time)
|
||||
uint8_t *bts_sysinfo_get(struct gsm_bts *bts, const struct gsm_time *g_time)
|
||||
{
|
||||
struct gsm_bts_role_bts *btsb = bts_role_bts(bts);
|
||||
unsigned int tc4_cnt = 0;
|
||||
@@ -76,21 +85,20 @@ uint8_t *bts_sysinfo_get(struct gsm_bts *bts, struct gsm_time *g_time)
|
||||
/* iterate over 2ter, 2quater, 9, 13 */
|
||||
/* determine how many SI we need to send on TC=4,
|
||||
* and which of them we send when */
|
||||
if (BTS_HAS_SI(bts, SYSINFO_TYPE_2ter)) {
|
||||
if (GSM_BTS_HAS_SI(bts, SYSINFO_TYPE_2ter) && GSM_BTS_HAS_SI(bts, SYSINFO_TYPE_2bis)) {
|
||||
tc4_sub[tc4_cnt] = SYSINFO_TYPE_2ter;
|
||||
tc4_cnt += 1; /* 2bis */
|
||||
tc4_cnt += 1;
|
||||
}
|
||||
if (BTS_HAS_SI(bts, SYSINFO_TYPE_2quater) &&
|
||||
(BTS_HAS_SI(bts, SYSINFO_TYPE_2bis) ||
|
||||
BTS_HAS_SI(bts, SYSINFO_TYPE_2bis))) {
|
||||
if (GSM_BTS_HAS_SI(bts, SYSINFO_TYPE_2quater) &&
|
||||
(GSM_BTS_HAS_SI(bts, SYSINFO_TYPE_2bis) || GSM_BTS_HAS_SI(bts, SYSINFO_TYPE_2ter))) {
|
||||
tc4_sub[tc4_cnt] = SYSINFO_TYPE_2quater;
|
||||
tc4_cnt += 1;
|
||||
}
|
||||
if (BTS_HAS_SI(bts, SYSINFO_TYPE_13)) {
|
||||
if (GSM_BTS_HAS_SI(bts, SYSINFO_TYPE_13)) {
|
||||
tc4_sub[tc4_cnt] = SYSINFO_TYPE_13;
|
||||
tc4_cnt += 1;
|
||||
}
|
||||
if (BTS_HAS_SI(bts, SYSINFO_TYPE_9)) {
|
||||
if (GSM_BTS_HAS_SI(bts, SYSINFO_TYPE_9)) {
|
||||
/* FIXME: check SI3 scheduling info! */
|
||||
tc4_sub[tc4_cnt] = SYSINFO_TYPE_9;
|
||||
tc4_cnt += 1;
|
||||
@@ -101,26 +109,30 @@ uint8_t *bts_sysinfo_get(struct gsm_bts *bts, struct gsm_time *g_time)
|
||||
else {
|
||||
/* increment static counter by one, modulo count */
|
||||
btsb->si.tc4_ctr = (btsb->si.tc4_ctr + 1) % tc4_cnt;
|
||||
|
||||
if (tc4_sub[btsb->si.tc4_ctr] == SYSINFO_TYPE_2quater)
|
||||
return get_si2q_inc_index(bts);
|
||||
|
||||
return GSM_BTS_SI(bts, tc4_sub[btsb->si.tc4_ctr]);
|
||||
}
|
||||
case 5:
|
||||
/* 2bis, 2ter, 2quater */
|
||||
if (BTS_HAS_SI(bts, SYSINFO_TYPE_2bis) &&
|
||||
!BTS_HAS_SI(bts, SYSINFO_TYPE_2ter))
|
||||
if (GSM_BTS_HAS_SI(bts, SYSINFO_TYPE_2bis) && !GSM_BTS_HAS_SI(bts, SYSINFO_TYPE_2ter))
|
||||
return GSM_BTS_SI(bts, SYSINFO_TYPE_2bis);
|
||||
|
||||
else if (BTS_HAS_SI(bts, SYSINFO_TYPE_2ter) &&
|
||||
!BTS_HAS_SI(bts, SYSINFO_TYPE_2bis))
|
||||
else if (GSM_BTS_HAS_SI(bts, SYSINFO_TYPE_2ter) && !GSM_BTS_HAS_SI(bts, SYSINFO_TYPE_2bis))
|
||||
return GSM_BTS_SI(bts, SYSINFO_TYPE_2ter);
|
||||
|
||||
else if (BTS_HAS_SI(bts, SYSINFO_TYPE_2bis) &&
|
||||
BTS_HAS_SI(bts, SYSINFO_TYPE_2ter))
|
||||
else if (GSM_BTS_HAS_SI(bts, SYSINFO_TYPE_2bis) && GSM_BTS_HAS_SI(bts, SYSINFO_TYPE_2ter))
|
||||
return GSM_BTS_SI(bts, SYSINFO_TYPE_2bis);
|
||||
|
||||
else if (BTS_HAS_SI(bts, SYSINFO_TYPE_2quater) &&
|
||||
!BTS_HAS_SI(bts, SYSINFO_TYPE_2bis) &&
|
||||
!BTS_HAS_SI(bts, SYSINFO_TYPE_2ter))
|
||||
return GSM_BTS_SI(bts, SYSINFO_TYPE_2quater);
|
||||
else if (GSM_BTS_HAS_SI(bts, SYSINFO_TYPE_2quater) &&
|
||||
!GSM_BTS_HAS_SI(bts, SYSINFO_TYPE_2bis) && !GSM_BTS_HAS_SI(bts, SYSINFO_TYPE_2ter))
|
||||
return get_si2q_inc_index(bts);
|
||||
|
||||
/* simply send SI2 if we have nothing else to send */
|
||||
else
|
||||
return GSM_BTS_SI(bts, SYSINFO_TYPE_2);
|
||||
break;
|
||||
case 6:
|
||||
return GSM_BTS_SI(bts, SYSINFO_TYPE_3);
|
||||
@@ -128,7 +140,22 @@ uint8_t *bts_sysinfo_get(struct gsm_bts *bts, struct gsm_time *g_time)
|
||||
return GSM_BTS_SI(bts, SYSINFO_TYPE_4);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
/* this should never bve reached. We must transmit a BCCH
|
||||
* message on the normal BCCH in all cases. */
|
||||
OSMO_ASSERT(0);
|
||||
}
|
||||
|
||||
uint8_t num_agch(struct gsm_bts_trx *trx, const char * arg)
|
||||
{
|
||||
struct gsm_bts *b = trx->bts;
|
||||
struct gsm48_system_information_type_3 *si3;
|
||||
if (GSM_BTS_HAS_SI(b, SYSINFO_TYPE_3)) {
|
||||
si3 = GSM_BTS_SI(b, SYSINFO_TYPE_3);
|
||||
return si3->control_channel_desc.bs_ag_blks_res;
|
||||
}
|
||||
LOGP(DL1P, LOGL_ERROR, "%s: Unable to determine actual BS_AG_BLKS_RES "
|
||||
"value as SI3 is not available yet, fallback to 1\n", arg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t *lchan_sacch_get(struct gsm_lchan *lchan)
|
||||
@@ -136,10 +163,10 @@ uint8_t *lchan_sacch_get(struct gsm_lchan *lchan)
|
||||
uint32_t tmp;
|
||||
|
||||
for (tmp = lchan->si.last + 1; tmp != lchan->si.last; tmp = (tmp + 1) % _MAX_SYSINFO_TYPE) {
|
||||
if (lchan->si.valid & (1 << tmp)) {
|
||||
if (!(lchan->si.valid & (1 << tmp)))
|
||||
continue;
|
||||
lchan->si.last = tmp;
|
||||
return lchan->si.buf[tmp];
|
||||
}
|
||||
return GSM_LCHAN_SI(lchan, tmp);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -33,12 +33,12 @@
|
||||
static int get_pa_drive_level_mdBm(const struct power_amp *pa,
|
||||
int desired_p_out_mdBm, unsigned int arfcn)
|
||||
{
|
||||
if (arfcn >= ARRAY_SIZE(pa->calib.gain_mdB))
|
||||
if (arfcn >= ARRAY_SIZE(pa->calib.delta_mdB))
|
||||
return INT_MIN;
|
||||
|
||||
/* FIXME: temperature compensation */
|
||||
|
||||
return desired_p_out_mdBm - pa->calib.gain_mdB[arfcn];
|
||||
return desired_p_out_mdBm - pa->nominal_gain_mdB - pa->calib.delta_mdB[arfcn];
|
||||
}
|
||||
|
||||
/* maximum output power of the system */
|
||||
@@ -58,7 +58,7 @@ int get_p_nominal_mdBm(struct gsm_bts_trx *trx)
|
||||
}
|
||||
|
||||
/* calculate the target total output power required, reduced by both
|
||||
* OML and RSL, but ignoring the attenutation required for power ramping and
|
||||
* OML and RSL, but ignoring the attenuation required for power ramping and
|
||||
* thermal management */
|
||||
int get_p_target_mdBm(struct gsm_bts_trx *trx, uint8_t bs_power_ie)
|
||||
{
|
||||
@@ -71,7 +71,7 @@ int get_p_target_mdBm_lchan(struct gsm_lchan *lchan)
|
||||
}
|
||||
|
||||
/* calculate the actual total output power required, taking into account the
|
||||
* attenutation required for power ramping but not thermal management */
|
||||
* attenuation required for power ramping but not thermal management */
|
||||
int get_p_actual_mdBm(struct gsm_bts_trx *trx, int p_target_mdBm)
|
||||
{
|
||||
struct trx_power_params *tpp = &trx->power_params;
|
||||
@@ -81,7 +81,7 @@ int get_p_actual_mdBm(struct gsm_bts_trx *trx, int p_target_mdBm)
|
||||
}
|
||||
|
||||
/* calculate the effective total output power required, taking into account the
|
||||
* attenutation required for power ramping and thermal management */
|
||||
* attenuation required for power ramping and thermal management */
|
||||
int get_p_eff_mdBm(struct gsm_bts_trx *trx, int p_target_mdBm)
|
||||
{
|
||||
struct trx_power_params *tpp = &trx->power_params;
|
||||
@@ -144,7 +144,7 @@ int get_p_trxout_target_mdBm_lchan(struct gsm_lchan *lchan)
|
||||
* one hand side to avoid very fast dynamic load changes towards the PA power
|
||||
* supply, but is also needed in order to avoid a DoS by too many subscriber
|
||||
* attempting to register at the same time. Rather, grow the cell slowly in
|
||||
* radius than start with the full raduis at once. */
|
||||
* radius than start with the full radius at once. */
|
||||
|
||||
static int we_are_ramping_up(struct gsm_bts_trx *trx)
|
||||
{
|
||||
@@ -158,7 +158,7 @@ static int we_are_ramping_up(struct gsm_bts_trx *trx)
|
||||
|
||||
static void power_ramp_do_step(struct gsm_bts_trx *trx, int first);
|
||||
|
||||
/* timer call-back for the ramp tumer */
|
||||
/* timer call-back for the ramp timer */
|
||||
static void power_ramp_timer_cb(void *_trx)
|
||||
{
|
||||
struct gsm_bts_trx *trx = _trx;
|
||||
@@ -289,3 +289,18 @@ int power_ramp_start(struct gsm_bts_trx *trx, int p_total_tgt_mdBm, int bypass)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* determine the initial transceiver output power at start-up time */
|
||||
int power_ramp_initial_power_mdBm(struct gsm_bts_trx *trx)
|
||||
{
|
||||
struct trx_power_params *tpp = &trx->power_params;
|
||||
int pout_mdBm;
|
||||
|
||||
/* this is the maximum initial output on the antenna connector
|
||||
* towards the antenna */
|
||||
pout_mdBm = tpp->ramp.max_initial_pout_mdBm;
|
||||
|
||||
/* use this as input to compute transceiver board power
|
||||
* (reflecting gains in internal/external amplifiers */
|
||||
return get_p_trxout_eff_mdBm(trx, pout_mdBm);
|
||||
}
|
||||
|
||||
537
src/common/vty.c
537
src/common/vty.c
@@ -1,6 +1,6 @@
|
||||
/* OsmoBTS VTY interface */
|
||||
|
||||
/* (C) 2011 by Harald Welte <laforge@gnumonks.org>
|
||||
/* (C) 2011-2014 by Harald Welte <laforge@gnumonks.org>
|
||||
*
|
||||
* All Rights Reserved
|
||||
*
|
||||
@@ -21,34 +21,72 @@
|
||||
|
||||
#include "btsconfig.h"
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <osmocom/core/talloc.h>
|
||||
#include <osmocom/gsm/abis_nm.h>
|
||||
#include <osmocom/vty/vty.h>
|
||||
#include <osmocom/vty/command.h>
|
||||
#include <osmocom/vty/logging.h>
|
||||
|
||||
#include <osmocom/vty/misc.h>
|
||||
#include <osmocom/vty/ports.h>
|
||||
#include <osmocom/core/gsmtap.h>
|
||||
#include <osmocom/core/utils.h>
|
||||
#include <osmocom/trau/osmo_ortp.h>
|
||||
|
||||
|
||||
#include <osmo-bts/logging.h>
|
||||
#include <osmo-bts/gsm_data.h>
|
||||
#include <osmo-bts/phy_link.h>
|
||||
#include <osmo-bts/abis.h>
|
||||
#include <osmo-bts/bts.h>
|
||||
#include <osmo-bts/rsl.h>
|
||||
#include <osmo-bts/oml.h>
|
||||
#include <osmo-bts/signal.h>
|
||||
#include <osmo-bts/bts_model.h>
|
||||
#include <osmo-bts/pcu_if.h>
|
||||
#include <osmo-bts/measurement.h>
|
||||
#include <osmo-bts/vty.h>
|
||||
#include <osmo-bts/l1sap.h>
|
||||
|
||||
#define VTY_STR "Configure the VTY\n"
|
||||
|
||||
enum node_type bts_vty_go_parent(struct vty *vty)
|
||||
int g_vty_port_num = OSMO_VTY_PORT_BTS;
|
||||
|
||||
struct phy_instance *vty_get_phy_instance(struct vty *vty, int phy_nr, int inst_nr)
|
||||
{
|
||||
struct phy_link *plink = phy_link_by_num(phy_nr);
|
||||
struct phy_instance *pinst;
|
||||
|
||||
if (!plink) {
|
||||
vty_out(vty, "Cannot find PHY link number %d%s",
|
||||
phy_nr, VTY_NEWLINE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pinst = phy_instance_by_num(plink, inst_nr);
|
||||
if (!pinst) {
|
||||
vty_out(vty, "Cannot find PHY instance number %d%s",
|
||||
inst_nr, VTY_NEWLINE);
|
||||
return NULL;
|
||||
}
|
||||
return pinst;
|
||||
}
|
||||
|
||||
int bts_vty_go_parent(struct vty *vty)
|
||||
{
|
||||
switch (vty->node) {
|
||||
case PHY_INST_NODE:
|
||||
vty->node = PHY_NODE;
|
||||
{
|
||||
struct phy_instance *pinst = vty->index;
|
||||
vty->index = pinst->phy_link;
|
||||
}
|
||||
break;
|
||||
case TRX_NODE:
|
||||
vty->node = BTS_NODE;
|
||||
{
|
||||
@@ -56,6 +94,7 @@ enum node_type bts_vty_go_parent(struct vty *vty)
|
||||
vty->index = trx->bts;
|
||||
}
|
||||
break;
|
||||
case PHY_NODE:
|
||||
default:
|
||||
vty->node = CONFIG_NODE;
|
||||
}
|
||||
@@ -67,6 +106,8 @@ int bts_vty_is_config_node(struct vty *vty, int node)
|
||||
switch (node) {
|
||||
case TRX_NODE:
|
||||
case BTS_NODE:
|
||||
case PHY_NODE:
|
||||
case PHY_INST_NODE:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
@@ -77,6 +118,17 @@ gDEFUN(ournode_exit, ournode_exit_cmd, "exit",
|
||||
"Exit current node, go down to provious node")
|
||||
{
|
||||
switch (vty->node) {
|
||||
case PHY_INST_NODE:
|
||||
vty->node = PHY_NODE;
|
||||
{
|
||||
struct phy_instance *pinst = vty->index;
|
||||
vty->index = pinst->phy_link;
|
||||
}
|
||||
break;
|
||||
case PHY_NODE:
|
||||
vty->node = CONFIG_NODE;
|
||||
vty->index = NULL;
|
||||
break;
|
||||
case TRX_NODE:
|
||||
vty->node = BTS_NODE;
|
||||
{
|
||||
@@ -137,8 +189,31 @@ static struct cmd_node trx_node = {
|
||||
1,
|
||||
};
|
||||
|
||||
gDEFUN(cfg_bts_auto_band, cfg_bts_auto_band_cmd,
|
||||
"auto-band",
|
||||
"Automatically select band for ARFCN based on configured band\n")
|
||||
{
|
||||
struct gsm_bts *bts = vty->index;
|
||||
struct gsm_bts_role_bts *btsb = bts_role_bts(bts);
|
||||
|
||||
btsb->auto_band = 1;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
gDEFUN(cfg_bts_no_auto_band, cfg_bts_no_auto_band_cmd,
|
||||
"no auto-band",
|
||||
NO_STR "Automatically select band for ARFCN based on configured band\n")
|
||||
{
|
||||
struct gsm_bts *bts = vty->index;
|
||||
struct gsm_bts_role_bts *btsb = bts_role_bts(bts);
|
||||
|
||||
btsb->auto_band = 0;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
DEFUN(cfg_bts_trx, cfg_bts_trx_cmd,
|
||||
"trx <0-0>",
|
||||
"trx <0-254>",
|
||||
"Select a TRX to configure\n" "TRX number\n")
|
||||
{
|
||||
int trx_nr = atoi(argv[0]);
|
||||
@@ -147,7 +222,10 @@ DEFUN(cfg_bts_trx, cfg_bts_trx_cmd,
|
||||
|
||||
trx = gsm_bts_trx_num(bts, trx_nr);
|
||||
if (!trx) {
|
||||
vty_out(vty, "Unknown TRX %u%s", trx_nr, VTY_NEWLINE);
|
||||
vty_out(vty, "Unknown TRX %u. Available TRX are: 0..%u%s",
|
||||
trx_nr, bts->num_trx - 1, VTY_NEWLINE);
|
||||
vty_out(vty, "Hint: Check if commandline option -t matches the"
|
||||
"number of available transceivers!%s", VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
@@ -162,20 +240,27 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts)
|
||||
{
|
||||
struct gsm_bts_role_bts *btsb = bts_role_bts(bts);
|
||||
struct gsm_bts_trx *trx;
|
||||
char buf_casecnvt[256];
|
||||
int i;
|
||||
|
||||
vty_out(vty, "bts %u%s", bts->nr, VTY_NEWLINE);
|
||||
if (bts->description)
|
||||
vty_out(vty, " description %s%s", bts->description, VTY_NEWLINE);
|
||||
vty_out(vty, " band %s%s", gsm_band_name(bts->band), VTY_NEWLINE);
|
||||
if (btsb->auto_band)
|
||||
vty_out(vty, " auto-band%s", VTY_NEWLINE);
|
||||
vty_out(vty, " ipa unit-id %u %u%s",
|
||||
bts->ip_access.site_id, bts->ip_access.bts_id, VTY_NEWLINE);
|
||||
vty_out(vty, " oml remote-ip %s%s", btsb->bsc_oml_host, VTY_NEWLINE);
|
||||
vty_out(vty, " rtp jitter-buffer %u%s", btsb->rtp_jitter_buf_ms,
|
||||
VTY_NEWLINE);
|
||||
vty_out(vty, " rtp jitter-buffer %u", btsb->rtp_jitter_buf_ms);
|
||||
if (btsb->rtp_jitter_adaptive)
|
||||
vty_out(vty, " adaptive");
|
||||
vty_out(vty, "%s", VTY_NEWLINE);
|
||||
vty_out(vty, " paging queue-size %u%s", paging_get_queue_max(btsb->paging_state),
|
||||
VTY_NEWLINE);
|
||||
vty_out(vty, " paging lifetime %u%s", paging_get_lifetime(btsb->paging_state),
|
||||
VTY_NEWLINE);
|
||||
vty_out(vty, " uplink-power-target %d%s", btsb->ul_power_target, VTY_NEWLINE);
|
||||
if (btsb->agch_queue_thresh_level != GSM_BTS_AGCH_QUEUE_THRESH_LEVEL_DEFAULT
|
||||
|| btsb->agch_queue_low_level != GSM_BTS_AGCH_QUEUE_LOW_LEVEL_DEFAULT
|
||||
|| btsb->agch_queue_high_level != GSM_BTS_AGCH_QUEUE_HIGH_LEVEL_DEFAULT)
|
||||
@@ -183,10 +268,28 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts)
|
||||
btsb->agch_queue_thresh_level, btsb->agch_queue_low_level,
|
||||
btsb->agch_queue_high_level, VTY_NEWLINE);
|
||||
|
||||
for (i = 0; i < 32; i++) {
|
||||
if (gsmtap_sapi_mask & (1 << i)) {
|
||||
osmo_str2lower(buf_casecnvt, get_value_string(gsmtap_sapi_names, i));
|
||||
vty_out(vty, " gsmtap-sapi %s%s", buf_casecnvt, VTY_NEWLINE);
|
||||
}
|
||||
}
|
||||
if (gsmtap_sapi_acch) {
|
||||
osmo_str2lower(buf_casecnvt, get_value_string(gsmtap_sapi_names, GSMTAP_CHANNEL_ACCH));
|
||||
vty_out(vty, " gsmtap-sapi %s%s", buf_casecnvt, VTY_NEWLINE);
|
||||
}
|
||||
vty_out(vty, " min-qual-rach %.0f%s", btsb->min_qual_rach * 10.0f,
|
||||
VTY_NEWLINE);
|
||||
vty_out(vty, " min-qual-norm %.0f%s", btsb->min_qual_norm * 10.0f,
|
||||
VTY_NEWLINE);
|
||||
if (strcmp(btsb->pcu.sock_path, PCU_SOCK_DEFAULT))
|
||||
vty_out(vty, " pcu-socket %s%s", btsb->pcu.sock_path, VTY_NEWLINE);
|
||||
|
||||
bts_model_config_write_bts(vty, bts);
|
||||
|
||||
llist_for_each_entry(trx, &bts->trx_list, list) {
|
||||
struct trx_power_params *tpp = &trx->power_params;
|
||||
struct phy_instance *pinst = trx_phy_instance(trx);
|
||||
vty_out(vty, " trx %u%s", trx->nr, VTY_NEWLINE);
|
||||
|
||||
if (trx->power_params.user_gain_mdB)
|
||||
@@ -198,6 +301,11 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts)
|
||||
tpp->ramp.step_size_mdB, VTY_NEWLINE);
|
||||
vty_out(vty, " power-ramp step-interval %d%s",
|
||||
tpp->ramp.step_interval_sec, VTY_NEWLINE);
|
||||
vty_out(vty, " ms-power-control %s%s",
|
||||
trx->ms_power_control == 0 ? "dsp" : "osmo",
|
||||
VTY_NEWLINE);
|
||||
vty_out(vty, " phy %u instance %u%s", pinst->phy_link->num,
|
||||
pinst->num, VTY_NEWLINE);
|
||||
|
||||
bts_model_config_write_trx(vty, trx);
|
||||
}
|
||||
@@ -214,11 +322,50 @@ static int config_write_bts(struct vty *vty)
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
static void config_write_phy_single(struct vty *vty, struct phy_link *plink)
|
||||
{
|
||||
int i;
|
||||
|
||||
vty_out(vty, "phy %u%s", plink->num, VTY_NEWLINE);
|
||||
bts_model_config_write_phy(vty, plink);
|
||||
|
||||
for (i = 0; i < 255; i++) {
|
||||
struct phy_instance *pinst = phy_instance_by_num(plink, i);
|
||||
if (!pinst)
|
||||
break;
|
||||
vty_out(vty, " instance %u%s", pinst->num, VTY_NEWLINE);
|
||||
bts_model_config_write_phy_inst(vty, pinst);
|
||||
}
|
||||
}
|
||||
|
||||
static int config_write_phy(struct vty *vty)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 255; i++) {
|
||||
struct phy_link *plink = phy_link_by_num(i);
|
||||
if (!plink)
|
||||
break;
|
||||
config_write_phy_single(vty, plink);
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
static int config_write_dummy(struct vty *vty)
|
||||
{
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_vty_telnet_port, cfg_vty_telnet_port_cmd,
|
||||
"vty telnet-port <0-65535>",
|
||||
VTY_STR "Set the VTY telnet port\n"
|
||||
"TCP Port number\n")
|
||||
{
|
||||
g_vty_port_num = atoi(argv[0]);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
/* per-BTS configuration */
|
||||
DEFUN(cfg_bts,
|
||||
cfg_bts_cmd,
|
||||
@@ -319,13 +466,15 @@ DEFUN_HIDDEN(cfg_bts_rtp_bind_ip,
|
||||
|
||||
DEFUN(cfg_bts_rtp_jitbuf,
|
||||
cfg_bts_rtp_jitbuf_cmd,
|
||||
"rtp jitter-buffer <0-10000>",
|
||||
"rtp jitter-buffer <0-10000> [adaptive]",
|
||||
RTP_STR "RTP jitter buffer\n" "jitter buffer in ms\n")
|
||||
{
|
||||
struct gsm_bts *bts = vty->index;
|
||||
struct gsm_bts_role_bts *btsb = bts_role_bts(bts);
|
||||
|
||||
btsb->rtp_jitter_buf_ms = atoi(argv[0]);
|
||||
if (argc > 1)
|
||||
btsb->rtp_jitter_adaptive = true;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
@@ -396,6 +545,63 @@ DEFUN(cfg_bts_agch_queue_mgmt_default,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_bts_ul_power_target, cfg_bts_ul_power_target_cmd,
|
||||
"uplink-power-target <-110-0>",
|
||||
"Set the nominal target Rx Level for uplink power control loop\n"
|
||||
"Target uplink Rx level in dBm\n")
|
||||
{
|
||||
struct gsm_bts *bts = vty->index;
|
||||
struct gsm_bts_role_bts *btsb = bts_role_bts(bts);
|
||||
|
||||
btsb->ul_power_target = atoi(argv[0]);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_bts_min_qual_rach, cfg_bts_min_qual_rach_cmd,
|
||||
"min-qual-rach <-100-100>",
|
||||
"Set the minimum quality level of RACH burst to be accpeted\n"
|
||||
"C/I level in tenth of dB\n")
|
||||
{
|
||||
struct gsm_bts *bts = vty->index;
|
||||
struct gsm_bts_role_bts *btsb = bts_role_bts(bts);
|
||||
|
||||
btsb->min_qual_rach = strtof(argv[0], NULL) / 10.0f;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_bts_min_qual_norm, cfg_bts_min_qual_norm_cmd,
|
||||
"min-qual-norm <-100-100>",
|
||||
"Set the minimum quality level of normal burst to be accpeted\n"
|
||||
"C/I level in tenth of dB\n")
|
||||
{
|
||||
struct gsm_bts *bts = vty->index;
|
||||
struct gsm_bts_role_bts *btsb = bts_role_bts(bts);
|
||||
|
||||
btsb->min_qual_norm = strtof(argv[0], NULL) / 10.0f;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_bts_pcu_sock, cfg_bts_pcu_sock_cmd,
|
||||
"pcu-socket PATH",
|
||||
"Configure the PCU socket file/path name\n")
|
||||
{
|
||||
struct gsm_bts *bts = vty->index;
|
||||
struct gsm_bts_role_bts *btsb = bts_role_bts(bts);
|
||||
|
||||
if (btsb->pcu.sock_path) {
|
||||
/* FIXME: close the interface? */
|
||||
talloc_free(btsb->pcu.sock_path);
|
||||
}
|
||||
btsb->pcu.sock_path = talloc_strdup(btsb, argv[0]);
|
||||
/* FIXME: re-open the interface? */
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
#define DB_DBM_STR \
|
||||
"Unit is dB (decibels)\n" \
|
||||
"Unit is mdB (milli-decibels, or rather 1/10000 bel)\n"
|
||||
@@ -460,7 +666,44 @@ DEFUN(cfg_trx_pr_step_interval, cfg_trx_pr_step_interval_cmd,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_trx_ms_power_control, cfg_trx_ms_power_control_cmd,
|
||||
"ms-power-control (dsp|osmo)",
|
||||
"Mobile Station Power Level Control (change requires restart)\n"
|
||||
"Handled by DSP\n" "Handled by OsmoBTS\n")
|
||||
{
|
||||
struct gsm_bts_trx *trx = vty->index;
|
||||
|
||||
trx->ms_power_control = argv[0][0] == 'd' ? 0 : 1;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_trx_phy, cfg_trx_phy_cmd,
|
||||
"phy <0-255> instance <0-255>",
|
||||
"Configure PHY Link+Instance for this TRX\n"
|
||||
"PHY Link number\n" "PHY instance\n" "PHY Instance number")
|
||||
{
|
||||
struct gsm_bts_trx *trx = vty->index;
|
||||
struct phy_link *plink = phy_link_by_num(atoi(argv[0]));
|
||||
struct phy_instance *pinst;
|
||||
|
||||
if (!plink) {
|
||||
vty_out(vty, "phy%s does not exist%s",
|
||||
argv[0], VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
pinst = phy_instance_by_num(plink, atoi(argv[1]));
|
||||
if (!pinst) {
|
||||
vty_out(vty, "phy%s instance %s does not exit%s",
|
||||
argv[0], argv[1], VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
trx->role_bts.l1h = pinst;
|
||||
pinst->trx = trx;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
/* ======================================================================
|
||||
* SHOW
|
||||
@@ -468,20 +711,33 @@ DEFUN(cfg_trx_pr_step_interval, cfg_trx_pr_step_interval_cmd,
|
||||
|
||||
static void net_dump_nmstate(struct vty *vty, struct gsm_nm_state *nms)
|
||||
{
|
||||
vty_out(vty,"Oper '%s', Admin %u, Avail '%s'%s",
|
||||
abis_nm_opstate_name(nms->operational), nms->administrative,
|
||||
vty_out(vty,"Oper '%s', Admin '%s', Avail '%s'%s",
|
||||
abis_nm_opstate_name(nms->operational),
|
||||
get_value_string(abis_nm_adm_state_names, nms->administrative),
|
||||
abis_nm_avail_name(nms->availability), VTY_NEWLINE);
|
||||
}
|
||||
|
||||
static unsigned int llist_length(struct llist_head *list)
|
||||
{
|
||||
unsigned int len = 0;
|
||||
struct llist_head *pos;
|
||||
|
||||
llist_for_each(pos, list)
|
||||
len++;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static void bts_dump_vty(struct vty *vty, struct gsm_bts *bts)
|
||||
{
|
||||
struct gsm_bts_role_bts *btsb = bts->role;
|
||||
struct gsm_bts_trx *trx;
|
||||
|
||||
vty_out(vty, "BTS %u is of %s type in band %s, has CI %u LAC %u, "
|
||||
"BSIC %u, TSC %u and %u TRX%s",
|
||||
"BSIC %u and %u TRX%s",
|
||||
bts->nr, "FIXME", gsm_band_name(bts->band),
|
||||
bts->cell_identity,
|
||||
bts->location_area_code, bts->bsic, bts->tsc,
|
||||
bts->location_area_code, bts->bsic,
|
||||
bts->num_trx, VTY_NEWLINE);
|
||||
vty_out(vty, " Description: %s%s",
|
||||
bts->description ? bts->description : "(null)", VTY_NEWLINE);
|
||||
@@ -492,35 +748,38 @@ static void bts_dump_vty(struct vty *vty, struct gsm_bts *bts)
|
||||
net_dump_nmstate(vty, &bts->mo.nm_state);
|
||||
vty_out(vty, " Site Mgr NM State: ");
|
||||
net_dump_nmstate(vty, &bts->site_mgr.mo.nm_state);
|
||||
if (strnlen(bts->pcu_version, MAX_VERSION_LENGTH))
|
||||
vty_out(vty, " PCU version %s connected%s",
|
||||
bts->pcu_version, VTY_NEWLINE);
|
||||
vty_out(vty, " Paging: Queue size %u, occupied %u, lifetime %us%s",
|
||||
paging_get_queue_max(btsb->paging_state), paging_queue_length(btsb->paging_state),
|
||||
paging_get_lifetime(btsb->paging_state), VTY_NEWLINE);
|
||||
vty_out(vty, " AGCH: Queue limit %u, occupied %d, "
|
||||
"dropped %llu, merged %llu, rejected %llu, "
|
||||
"ag-res %llu, non-res %llu%s",
|
||||
"dropped %"PRIu64", merged %"PRIu64", rejected %"PRIu64", "
|
||||
"ag-res %"PRIu64", non-res %"PRIu64"%s",
|
||||
btsb->agch_max_queue_length, btsb->agch_queue_length,
|
||||
btsb->agch_queue_dropped_msgs, btsb->agch_queue_merged_msgs,
|
||||
btsb->agch_queue_rejected_msgs, btsb->agch_queue_agch_msgs,
|
||||
btsb->agch_queue_pch_msgs,
|
||||
VTY_NEWLINE);
|
||||
#if 0
|
||||
vty_out(vty, " Paging: %u pending requests, %u free slots%s",
|
||||
paging_pending_requests_nr(bts),
|
||||
bts->paging.available_slots, VTY_NEWLINE);
|
||||
if (is_ipaccess_bts(bts)) {
|
||||
vty_out(vty, " CBCH backlog queue length: %u%s",
|
||||
llist_length(&btsb->smscb_state.queue), VTY_NEWLINE);
|
||||
vty_out(vty, " Paging: queue length %d, buffer space %d%s",
|
||||
paging_queue_length(btsb->paging_state), paging_buffer_space(btsb->paging_state),
|
||||
VTY_NEWLINE);
|
||||
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: chan_desc */
|
||||
memset(&pl, 0, sizeof(pl));
|
||||
bts_chan_load(&pl, bts);
|
||||
vty_out(vty, " Current Channel Load:%s", VTY_NEWLINE);
|
||||
dump_pchan_load_vty(vty, " ", &pl);
|
||||
#endif
|
||||
llist_for_each_entry(trx, &bts->trx_list, list) {
|
||||
struct phy_instance *pinst = trx_phy_instance(trx);
|
||||
vty_out(vty, " TRX %u%s", trx->nr, VTY_NEWLINE);
|
||||
if (pinst) {
|
||||
vty_out(vty, " phy %d %s", pinst->num, pinst->version);
|
||||
if (pinst->description)
|
||||
vty_out(vty, " (%s)", pinst->description);
|
||||
vty_out(vty, "%s", VTY_NEWLINE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -588,6 +847,138 @@ static struct gsm_lchan *resolve_lchan(struct gsm_network *net,
|
||||
"logical channel commands\n" \
|
||||
"logical channel number\n"
|
||||
|
||||
DEFUN(cfg_trx_gsmtap_sapi, cfg_trx_gsmtap_sapi_cmd,
|
||||
"HIDDEN", "HIDDEN")
|
||||
{
|
||||
int sapi;
|
||||
|
||||
sapi = get_string_value(gsmtap_sapi_names, argv[0]);
|
||||
OSMO_ASSERT(sapi >= 0);
|
||||
|
||||
if (sapi == GSMTAP_CHANNEL_ACCH)
|
||||
gsmtap_sapi_acch = 1;
|
||||
else
|
||||
gsmtap_sapi_mask |= (1 << sapi);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_trx_no_gsmtap_sapi, cfg_trx_no_gsmtap_sapi_cmd,
|
||||
"HIDDEN", "HIDDEN")
|
||||
{
|
||||
int sapi;
|
||||
|
||||
sapi = get_string_value(gsmtap_sapi_names, argv[0]);
|
||||
OSMO_ASSERT(sapi >= 0);
|
||||
|
||||
if (sapi == GSMTAP_CHANNEL_ACCH)
|
||||
gsmtap_sapi_acch = 0;
|
||||
else
|
||||
gsmtap_sapi_mask &= ~(1 << sapi);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
static struct cmd_node phy_node = {
|
||||
PHY_NODE,
|
||||
"%s(phy)# ",
|
||||
1,
|
||||
};
|
||||
|
||||
static struct cmd_node phy_inst_node = {
|
||||
PHY_INST_NODE,
|
||||
"%s(phy-inst)# ",
|
||||
1,
|
||||
};
|
||||
|
||||
DEFUN(cfg_phy, cfg_phy_cmd,
|
||||
"phy <0-255>",
|
||||
"Select a PHY to configure\n" "PHY number\n")
|
||||
{
|
||||
int phy_nr = atoi(argv[0]);
|
||||
struct phy_link *plink;
|
||||
|
||||
plink = phy_link_by_num(phy_nr);
|
||||
if (!plink)
|
||||
plink = phy_link_create(tall_bts_ctx, phy_nr);
|
||||
if (!plink)
|
||||
return CMD_WARNING;
|
||||
|
||||
vty->index = plink;
|
||||
vty->index_sub = &plink->description;
|
||||
vty->node = PHY_NODE;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_phy_inst, cfg_phy_inst_cmd,
|
||||
"instance <0-255>",
|
||||
"Select a PHY instance to configure\n" "PHY Instance number\n")
|
||||
{
|
||||
int inst_nr = atoi(argv[0]);
|
||||
struct phy_link *plink = vty->index;
|
||||
struct phy_instance *pinst;
|
||||
|
||||
pinst = phy_instance_by_num(plink, inst_nr);
|
||||
if (!pinst) {
|
||||
pinst = phy_instance_create(plink, inst_nr);
|
||||
if (!pinst) {
|
||||
vty_out(vty, "Unable to create phy%u instance %u%s",
|
||||
plink->num, inst_nr, VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
}
|
||||
|
||||
vty->index = pinst;
|
||||
vty->index_sub = &pinst->description;
|
||||
vty->node = PHY_INST_NODE;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_phy_no_inst, cfg_phy_no_inst_cmd,
|
||||
"no instance <0-255>"
|
||||
NO_STR "Select a PHY instance to remove\n", "PHY Instance number\n")
|
||||
{
|
||||
int inst_nr = atoi(argv[0]);
|
||||
struct phy_link *plink = vty->index;
|
||||
struct phy_instance *pinst;
|
||||
|
||||
pinst = phy_instance_by_num(plink, inst_nr);
|
||||
if (!pinst) {
|
||||
vty_out(vty, "No such instance %u%s", inst_nr, VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
phy_instance_destroy(pinst);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
#if 0
|
||||
DEFUN(cfg_phy_type, cfg_phy_type_cmd,
|
||||
"type (sysmobts|osmo-trx|virtual)",
|
||||
"configure the type of the PHY\n"
|
||||
"sysmocom sysmoBTS PHY\n"
|
||||
"OsmoTRX based PHY\n"
|
||||
"Virtual PHY (GSMTAP based)\n")
|
||||
{
|
||||
struct phy_link *plink = vty->index;
|
||||
|
||||
if (plink->state != PHY_LINK_SHUTDOWN) {
|
||||
vty_out(vty, "Cannot change type of active PHY%s", VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
if (!strcmp(argv[0], "sysmobts"))
|
||||
plink->type = PHY_LINK_T_SYSMOBTS;
|
||||
else if (!strcmp(argv[0], "osmo-trx"))
|
||||
plink->type = PHY_LINK_T_OSMOTRX;
|
||||
else if (!strcmp(argv[0], "virtual"))
|
||||
plink->type = PHY_LINK_T_VIRTUAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
DEFUN(bts_t_t_l_jitter_buf,
|
||||
bts_t_t_l_jitter_buf_cmd,
|
||||
"bts <0-0> trx <0-0> ts <0-7> lchan <0-1> rtp jitter-buffer <0-10000>",
|
||||
@@ -596,7 +987,8 @@ DEFUN(bts_t_t_l_jitter_buf,
|
||||
{
|
||||
struct gsm_network *net = gsmnet_from_vty(vty);
|
||||
struct gsm_lchan *lchan;
|
||||
int jitbuf_ms = atoi(argv[4]);
|
||||
struct gsm_bts_role_bts *btsb;
|
||||
int jitbuf_ms = atoi(argv[4]), rc;
|
||||
|
||||
lchan = resolve_lchan(net, argv, 0);
|
||||
if (!lchan) {
|
||||
@@ -608,20 +1000,79 @@ DEFUN(bts_t_t_l_jitter_buf,
|
||||
VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
osmo_rtp_socket_set_param(lchan->abis_ip.rtp_socket,
|
||||
OSMO_RTP_P_JITBUF, jitbuf_ms);
|
||||
btsb = bts_role_bts(lchan->ts->trx->bts);
|
||||
rc = osmo_rtp_socket_set_param(lchan->abis_ip.rtp_socket,
|
||||
btsb->rtp_jitter_adaptive ?
|
||||
OSMO_RTP_P_JIT_ADAP : OSMO_RTP_P_JITBUF,
|
||||
jitbuf_ms);
|
||||
if (rc < 0)
|
||||
vty_out(vty, "%% error setting jitter parameters: %s%s",
|
||||
strerror(-rc), VTY_NEWLINE);
|
||||
else
|
||||
vty_out(vty, "%% jitter parameters set: %d%s", rc, VTY_NEWLINE);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
int bts_vty_init(const struct log_info *cat)
|
||||
DEFUN(bts_t_t_l_loopback,
|
||||
bts_t_t_l_loopback_cmd,
|
||||
"bts <0-0> trx <0-0> ts <0-7> lchan <0-1> loopback",
|
||||
BTS_T_T_L_STR "Set loopback\n")
|
||||
{
|
||||
struct gsm_network *net = gsmnet_from_vty(vty);
|
||||
struct gsm_lchan *lchan;
|
||||
|
||||
lchan = resolve_lchan(net, argv, 0);
|
||||
if (!lchan) {
|
||||
vty_out(vty, "%% can't find BTS%s", VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
lchan->loopback = 1;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(no_bts_t_t_l_loopback,
|
||||
no_bts_t_t_l_loopback_cmd,
|
||||
"no bts <0-0> trx <0-0> ts <0-7> lchan <0-1> loopback",
|
||||
NO_STR BTS_T_T_L_STR "Set loopback\n")
|
||||
{
|
||||
struct gsm_network *net = gsmnet_from_vty(vty);
|
||||
struct gsm_lchan *lchan;
|
||||
|
||||
lchan = resolve_lchan(net, argv, 0);
|
||||
if (!lchan) {
|
||||
vty_out(vty, "%% can't find BTS%s", VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
lchan->loopback = 0;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
int bts_vty_init(struct gsm_bts *bts, const struct log_info *cat)
|
||||
{
|
||||
cfg_trx_gsmtap_sapi_cmd.string = vty_cmd_string_from_valstr(bts, gsmtap_sapi_names,
|
||||
"gsmtap-sapi (",
|
||||
"|",")", VTY_DO_LOWER);
|
||||
cfg_trx_gsmtap_sapi_cmd.doc = vty_cmd_string_from_valstr(bts, gsmtap_sapi_names,
|
||||
"GSMTAP SAPI\n",
|
||||
"\n", "", 0);
|
||||
|
||||
cfg_trx_no_gsmtap_sapi_cmd.string = vty_cmd_string_from_valstr(bts, gsmtap_sapi_names,
|
||||
"no gsmtap-sapi (",
|
||||
"|",")", VTY_DO_LOWER);
|
||||
cfg_trx_no_gsmtap_sapi_cmd.doc = vty_cmd_string_from_valstr(bts, gsmtap_sapi_names,
|
||||
NO_STR "GSMTAP SAPI\n",
|
||||
"\n", "", 0);
|
||||
|
||||
install_element_ve(&show_bts_cmd);
|
||||
|
||||
logging_vty_add_cmds(cat);
|
||||
|
||||
install_node(&bts_node, config_write_bts);
|
||||
install_element(CONFIG_NODE, &cfg_bts_cmd);
|
||||
install_element(CONFIG_NODE, &cfg_vty_telnet_port_cmd);
|
||||
install_default(BTS_NODE);
|
||||
install_element(BTS_NODE, &cfg_bts_unit_id_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_oml_ip_cmd);
|
||||
@@ -634,6 +1085,13 @@ int bts_vty_init(const struct log_info *cat)
|
||||
install_element(BTS_NODE, &cfg_bts_paging_lifetime_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_agch_queue_mgmt_default_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_agch_queue_mgmt_params_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_ul_power_target_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_min_qual_rach_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_min_qual_norm_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_pcu_sock_cmd);
|
||||
|
||||
install_element(BTS_NODE, &cfg_trx_gsmtap_sapi_cmd);
|
||||
install_element(BTS_NODE, &cfg_trx_no_gsmtap_sapi_cmd);
|
||||
|
||||
/* add and link to TRX config node */
|
||||
install_element(BTS_NODE, &cfg_bts_trx_cmd);
|
||||
@@ -644,8 +1102,21 @@ int bts_vty_init(const struct log_info *cat)
|
||||
install_element(TRX_NODE, &cfg_trx_pr_max_initial_cmd);
|
||||
install_element(TRX_NODE, &cfg_trx_pr_step_size_cmd);
|
||||
install_element(TRX_NODE, &cfg_trx_pr_step_interval_cmd);
|
||||
install_element(TRX_NODE, &cfg_trx_ms_power_control_cmd);
|
||||
install_element(TRX_NODE, &cfg_trx_phy_cmd);
|
||||
|
||||
install_element(ENABLE_NODE, &bts_t_t_l_jitter_buf_cmd);
|
||||
install_element(ENABLE_NODE, &bts_t_t_l_loopback_cmd);
|
||||
install_element(ENABLE_NODE, &no_bts_t_t_l_loopback_cmd);
|
||||
|
||||
install_element(CONFIG_NODE, &cfg_phy_cmd);
|
||||
install_node(&phy_node, config_write_phy);
|
||||
install_default(PHY_NODE);
|
||||
install_element(PHY_NODE, &cfg_phy_inst_cmd);
|
||||
install_element(PHY_NODE, &cfg_phy_no_inst_cmd);
|
||||
|
||||
install_node(&phy_inst_node, config_write_dummy);
|
||||
install_default(PHY_INST_NODE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
38
src/osmo-bts-litecell15/Makefile.am
Normal file
38
src/osmo-bts-litecell15/Makefile.am
Normal file
@@ -0,0 +1,38 @@
|
||||
AUTOMAKE_OPTIONS = subdir-objects
|
||||
|
||||
AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include -I$(LITECELL15_INCDIR)
|
||||
AM_CFLAGS = -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOCODEC_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(LIBOSMOTRAU_CFLAGS) $(LIBOSMOABIS_CFLAGS) $(LIBOSMOCTRL_CFLAGS) $(LIBOSMOABIS_CFLAGS) $(LIBGPS_CFLAGS) $(ORTP_CFLAGS) $(LIBSYSTEMD_CFLAGS)
|
||||
COMMON_LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOCODEC_LIBS) $(LIBOSMOGSM_LIBS) $(LIBOSMOVTY_LIBS) $(LIBOSMOTRAU_LIBS) $(LIBOSMOABIS_LIBS) $(LIBOSMOCTRL_LIBS) $(ORTP_LIBS)
|
||||
|
||||
AM_CFLAGS += -DENABLE_LC15BTS
|
||||
|
||||
EXTRA_DIST = misc/lc15bts_mgr.h misc/lc15bts_misc.h misc/lc15bts_par.h misc/lc15bts_led.h \
|
||||
misc/lc15bts_temp.h misc/lc15bts_power.h misc/lc15bts_clock.h \
|
||||
misc/lc15bts_bid.h misc/lc15bts_nl.h misc/lc15bts_bts.h misc/lc15bts_swd.h \
|
||||
hw_misc.h l1_if.h l1_transp.h lc15bts.h oml_router.h utils.h
|
||||
|
||||
bin_PROGRAMS = osmo-bts-lc15 lc15bts-mgr lc15bts-util
|
||||
|
||||
COMMON_SOURCES = main.c lc15bts.c l1_if.c oml.c lc15bts_vty.c tch.c hw_misc.c calib_file.c \
|
||||
utils.c misc/lc15bts_par.c misc/lc15bts_bid.c oml_router.c
|
||||
|
||||
osmo_bts_lc15_SOURCES = $(COMMON_SOURCES) l1_transp_hw.c
|
||||
osmo_bts_lc15_LDADD = $(top_builddir)/src/common/libbts.a $(COMMON_LDADD)
|
||||
|
||||
lc15bts_mgr_SOURCES = \
|
||||
misc/lc15bts_mgr.c misc/lc15bts_misc.c \
|
||||
misc/lc15bts_par.c misc/lc15bts_nl.c \
|
||||
misc/lc15bts_temp.c misc/lc15bts_power.c \
|
||||
misc/lc15bts_clock.c misc/lc15bts_bid.c \
|
||||
misc/lc15bts_mgr_vty.c \
|
||||
misc/lc15bts_mgr_nl.c \
|
||||
misc/lc15bts_mgr_temp.c \
|
||||
misc/lc15bts_mgr_calib.c \
|
||||
misc/lc15bts_led.c \
|
||||
misc/lc15bts_bts.c \
|
||||
misc/lc15bts_swd.c
|
||||
|
||||
lc15bts_mgr_LDADD = $(top_builddir)/src/common/libbts.a $(LIBGPS_LIBS) $(LIBOSMOCORE_LIBS) $(LIBOSMOVTY_LIBS) $(LIBOSMOABIS_LIBS) $(LIBOSMOGSM_LIBS) $(LIBOSMOCTRL_LIBS) $(LIBSYSTEMD_LIBS) $(COMMON_LDADD)
|
||||
|
||||
lc15bts_util_SOURCES = misc/lc15bts_util.c misc/lc15bts_par.c
|
||||
lc15bts_util_LDADD = $(LIBOSMOCORE_LIBS)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user