mirror of
https://gitea.osmocom.org/cellular-infrastructure/osmo-mgw.git
synced 2025-11-02 21:13:44 +00:00
Compare commits
275 Commits
openbsc/0.
...
openbsc/0.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3f78600346 | ||
|
|
76afa16d04 | ||
|
|
8b29180cad | ||
|
|
1af682adb9 | ||
|
|
f876c39887 | ||
|
|
e1145cf0f9 | ||
|
|
e972dba8dd | ||
|
|
9b5192b153 | ||
|
|
f4be327b4c | ||
|
|
63b0e44f65 | ||
|
|
456fccf697 | ||
|
|
b02fc1e9bb | ||
|
|
75e13a41dc | ||
|
|
647db848e3 | ||
|
|
ce1d742f27 | ||
|
|
af33e1d3a1 | ||
|
|
0a7c6a3549 | ||
|
|
883fbc9d04 | ||
|
|
dc030960fc | ||
|
|
3d119f1de4 | ||
|
|
e30d40de0e | ||
|
|
e7ea08379e | ||
|
|
1590727b64 | ||
|
|
c5e0851054 | ||
|
|
b862cef60d | ||
|
|
6a85c15eea | ||
|
|
b5a4edd09b | ||
|
|
d4d1d5e751 | ||
|
|
9e1952a901 | ||
|
|
164ee307b2 | ||
|
|
69665f8722 | ||
|
|
7d10983865 | ||
|
|
2a896070a7 | ||
|
|
036b25fb7f | ||
|
|
c7de8ef014 | ||
|
|
431ceada36 | ||
|
|
25eca0bfdc | ||
|
|
23446844a8 | ||
|
|
7b6ea56f41 | ||
|
|
baa1a2df20 | ||
|
|
ed0374ffeb | ||
|
|
ba36bf4c5d | ||
|
|
30a3d2f0fe | ||
|
|
4babba62b8 | ||
|
|
3749dc93a3 | ||
|
|
f2621e506d | ||
|
|
608ac2a8a4 | ||
|
|
bac7dcc367 | ||
|
|
75077955e9 | ||
|
|
25aa749f10 | ||
|
|
ff799f0912 | ||
|
|
0b19d55dd6 | ||
|
|
c7db4dce4a | ||
|
|
d5edc4f84d | ||
|
|
83d2d38a3c | ||
|
|
ea46b77f3e | ||
|
|
aa191adce6 | ||
|
|
1f8276e588 | ||
|
|
0434faedc9 | ||
|
|
184950e298 | ||
|
|
bdf764a025 | ||
|
|
adc2e87372 | ||
|
|
6fbd864a65 | ||
|
|
6ecb3cb599 | ||
|
|
b9b828b1e5 | ||
|
|
b5ae7288a9 | ||
|
|
1c201c6055 | ||
|
|
bfbdeec714 | ||
|
|
4d62d63151 | ||
|
|
4d2a68cf11 | ||
|
|
39c31dea2e | ||
|
|
01c13a3a45 | ||
|
|
11c1b6e014 | ||
|
|
977cd13741 | ||
|
|
0c282f5268 | ||
|
|
324c8052ae | ||
|
|
4173b174eb | ||
|
|
56260b648c | ||
|
|
cf77b3a2cf | ||
|
|
c121bb3188 | ||
|
|
006e3d87e0 | ||
|
|
48ea4e8aec | ||
|
|
6e300682df | ||
|
|
4485321219 | ||
|
|
7d0f60dce6 | ||
|
|
b348939d86 | ||
|
|
638da51a78 | ||
|
|
9d50a27695 | ||
|
|
8582535c82 | ||
|
|
960c4044e6 | ||
|
|
93599a2c2c | ||
|
|
d66777f9cf | ||
|
|
5ca825e431 | ||
|
|
1411c066cc | ||
|
|
10049bc3b7 | ||
|
|
3e9b2ec257 | ||
|
|
405824c057 | ||
|
|
25b70cea9d | ||
|
|
0e0a09c610 | ||
|
|
3a41b80bd7 | ||
|
|
2f25747e3f | ||
|
|
bce5675e5f | ||
|
|
c751cf92cb | ||
|
|
408208d887 | ||
|
|
5ea1bc77a3 | ||
|
|
7e7ee5f8c6 | ||
|
|
1bf6610ce7 | ||
|
|
ce55361e93 | ||
|
|
29de346b32 | ||
|
|
a769dcb889 | ||
|
|
cf2f158caa | ||
|
|
d267f4d685 | ||
|
|
0d904e004a | ||
|
|
01d315f19c | ||
|
|
3d4d79d890 | ||
|
|
d2361d970a | ||
|
|
f589221ed0 | ||
|
|
b3089e437d | ||
|
|
383d3c33e6 | ||
|
|
c5903a2b01 | ||
|
|
536a10b63b | ||
|
|
bc6c43f759 | ||
|
|
f7396eac2f | ||
|
|
07dec137de | ||
|
|
70ae5d3000 | ||
|
|
6d818839a9 | ||
|
|
8d0be259cb | ||
|
|
0d0c9ec5c5 | ||
|
|
c6483683eb | ||
|
|
b8a1f967c5 | ||
|
|
c0de14da8f | ||
|
|
e07b6a77e5 | ||
|
|
338e3b3b4b | ||
|
|
eff4094950 | ||
|
|
366c33185b | ||
|
|
0a1a312311 | ||
|
|
6c7680d726 | ||
|
|
1a2993adb7 | ||
|
|
9122c13933 | ||
|
|
874f9f1aa7 | ||
|
|
8a1b056bff | ||
|
|
9ad0362429 | ||
|
|
4dbcdad903 | ||
|
|
e94db49698 | ||
|
|
d4bdee79e9 | ||
|
|
f1033cc752 | ||
|
|
90d7f26f67 | ||
|
|
eedb45362d | ||
|
|
98da544992 | ||
|
|
88c06bcd64 | ||
|
|
cb306a689e | ||
|
|
30690adbc8 | ||
|
|
38e02c5125 | ||
|
|
769912c9e9 | ||
|
|
1e85af661c | ||
|
|
ed3a661d0b | ||
|
|
0bf15a8187 | ||
|
|
2e8e659586 | ||
|
|
952f752ffa | ||
|
|
2a60a11c48 | ||
|
|
de1674ab02 | ||
|
|
75172124e7 | ||
|
|
3dfe8a1705 | ||
|
|
e2f34d588c | ||
|
|
93fda87cf8 | ||
|
|
e0b5972d30 | ||
|
|
f3a317ceed | ||
|
|
e600eed7fa | ||
|
|
6b55f603e3 | ||
|
|
7456891439 | ||
|
|
cb3c2c95bf | ||
|
|
07fc097fc4 | ||
|
|
aff20717e4 | ||
|
|
511f9c3e4a | ||
|
|
d49eb74732 | ||
|
|
2ee7ecddeb | ||
|
|
94c2b0578b | ||
|
|
c15d0ac8dd | ||
|
|
d9173c3fce | ||
|
|
8936d00587 | ||
|
|
becc89a98e | ||
|
|
778695d0b4 | ||
|
|
221ff66327 | ||
|
|
bf0a7c97be | ||
|
|
34203bd487 | ||
|
|
9ceea68ba9 | ||
|
|
ca5d211113 | ||
|
|
31b245b91a | ||
|
|
cbaa880ae8 | ||
|
|
18fa70aa3a | ||
|
|
210565ed8c | ||
|
|
c11889f3dd | ||
|
|
f67d9a9bed | ||
|
|
644b0bf3da | ||
|
|
076af1c54b | ||
|
|
354c87cdfc | ||
|
|
8b902d74cf | ||
|
|
8c176cc6ab | ||
|
|
ffd6856249 | ||
|
|
7a7c2f8567 | ||
|
|
806d6549f8 | ||
|
|
6dc6910b79 | ||
|
|
6088f149b5 | ||
|
|
65924a5fe8 | ||
|
|
11620111f4 | ||
|
|
d08ad7d6d9 | ||
|
|
ebe22375a6 | ||
|
|
7aa4f0a263 | ||
|
|
fa0ec157af | ||
|
|
a5352a0174 | ||
|
|
47b5b3eeb2 | ||
|
|
5e95f45af0 | ||
|
|
5ff06af6f5 | ||
|
|
d5eb431c47 | ||
|
|
adcde9f8f5 | ||
|
|
47824541f0 | ||
|
|
ad2946ce03 | ||
|
|
d79da3baac | ||
|
|
721f0325b5 | ||
|
|
114a010c33 | ||
|
|
6fc4a98fc5 | ||
|
|
f3b31eb349 | ||
|
|
4dd84ff7c2 | ||
|
|
8c3d0695e4 | ||
|
|
d98136d25c | ||
|
|
a5050b14c9 | ||
|
|
86f240aded | ||
|
|
79c34ffb4f | ||
|
|
4c889a5c49 | ||
|
|
0818f31144 | ||
|
|
240a828ffd | ||
|
|
037065deee | ||
|
|
e422798866 | ||
|
|
bb53e3577a | ||
|
|
9fc70f365a | ||
|
|
6fcac63cc0 | ||
|
|
b561459dd6 | ||
|
|
6e7d137e79 | ||
|
|
3d610e63cc | ||
|
|
dd68fcaeee | ||
|
|
010c9551ff | ||
|
|
a73ca05db6 | ||
|
|
570ce24deb | ||
|
|
e555c2b545 | ||
|
|
57e0724ed4 | ||
|
|
4ab9d7c012 | ||
|
|
13fe21939c | ||
|
|
d13e0cd6db | ||
|
|
cfaabbb21e | ||
|
|
fe568f235f | ||
|
|
df49a983e2 | ||
|
|
b7b6cf5695 | ||
|
|
f42e908cea | ||
|
|
602559fd9f | ||
|
|
4552d8061a | ||
|
|
59043d8c94 | ||
|
|
9b5db287c6 | ||
|
|
1a6b83c919 | ||
|
|
bc6a54dadc | ||
|
|
d028807658 | ||
|
|
64c17fa598 | ||
|
|
3217fa2412 | ||
|
|
70f9205cd9 | ||
|
|
ae1d010220 | ||
|
|
fdf453c0a9 | ||
|
|
7b022eed2d | ||
|
|
45f9171175 | ||
|
|
25cf824edc | ||
|
|
153b13b02e | ||
|
|
8c00496e42 | ||
|
|
ad66a2d150 | ||
|
|
f383aa11a5 | ||
|
|
0c1bd61bb3 | ||
|
|
019f913ca3 | ||
|
|
c95175fb88 |
1
debian/autoreconf
vendored
Normal file
1
debian/autoreconf
vendored
Normal file
@@ -0,0 +1 @@
|
||||
openbsc
|
||||
61
debian/changelog
vendored
Normal file
61
debian/changelog
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
openbsc (0.12.0+git26-7) unstable; urgency=low
|
||||
|
||||
* 64bit fix for the MGCP rewriting
|
||||
|
||||
-- Holger Hans Peter Freyther <holger@freyther.de> Wed, 07 Nov 2012 11:39:34 +0100
|
||||
|
||||
openbsc (0.12.0+git26-6) precise; urgency=low
|
||||
|
||||
* Added init script for osmocom-sgsn.
|
||||
|
||||
-- Eric Butler <eric@codebutler.com> Fri, 24 Aug 2012 21:04:32 -0700
|
||||
|
||||
openbsc (0.12.0+git26-5) precise; urgency=low
|
||||
|
||||
* Don't enable MNCC sock by default.
|
||||
* Automatically create important directories.
|
||||
* Fix init script 'stop' command.
|
||||
|
||||
-- Eric Butler <eric@codebutler.com> Fri, 24 Aug 2012 20:56:33 -0700
|
||||
|
||||
openbsc (0.12.0+git26-4) precise; urgency=low
|
||||
|
||||
* Specify HLR path and enable RTP proxy.
|
||||
|
||||
-- Eric Butler <eric@codebutler.com> Mon, 20 Aug 2012 00:21:07 -0700
|
||||
|
||||
openbsc (0.12.0+git26-3) precise; urgency=low
|
||||
|
||||
* Fix init script.
|
||||
|
||||
-- Eric Butler <eric@codebutler.com> Sun, 19 Aug 2012 16:05:44 -0700
|
||||
|
||||
openbsc (0.12.0+git26-2) precise; urgency=low
|
||||
|
||||
* Fix libdbi package dependency.
|
||||
|
||||
-- Eric Butler <eric@codebutler.com> Wed, 15 Aug 2012 00:35:37 -0700
|
||||
|
||||
openbsc (0.12.0+git26-1) precise; urgency=low
|
||||
|
||||
* Fix version issue.
|
||||
|
||||
-- Eric Butler <eric@codebutler.com> Tue, 14 Aug 2012 21:00:51 -0700
|
||||
|
||||
openbsc (0.12.0+git26) precise; urgency=low
|
||||
|
||||
* Updated ubuntu package.
|
||||
|
||||
-- Eric Butler <eric@codebutler.com> Tue, 14 Aug 2012 17:36:51 -0700
|
||||
|
||||
openbsc (0.9.13.115.eb113-1) natty; urgency=low
|
||||
|
||||
* New upstream release
|
||||
|
||||
-- Harald Welte <laforge@gnumonks.org> Wed, 11 May 2011 18:41:24 +0000
|
||||
|
||||
openbsc (0.9.4-1) unstable; urgency=low
|
||||
|
||||
* Initial release (Closes: #nnnn) <nnnn is the bug number of your ITP>
|
||||
|
||||
-- Harald Welte <laforge@gnumonks.org> Tue, 24 Aug 2010 13:34:24 +0200
|
||||
0
openbsc/debian/compat → debian/compat
vendored
0
openbsc/debian/compat → debian/compat
vendored
4
openbsc/debian/control → debian/control
vendored
4
openbsc/debian/control → debian/control
vendored
@@ -2,7 +2,7 @@ Source: openbsc
|
||||
Section: net
|
||||
Priority: optional
|
||||
Maintainer: Harald Welte <laforge@gnumonks.org>
|
||||
Build-Depends: debhelper (>= 7.0.0~), autotools-dev, pkg-config, libgtp, libosmocore-dev, libosmo-sccp-dev, libdbi0-dev
|
||||
Build-Depends: debhelper (>= 7.0.0~), autotools-dev, pkg-config, libgtp-dev, libosmocore-dev, libosmo-sccp-dev, libdbi0-dev, dh-autoreconf, libosmo-abis-dev, libdbd-sqlite3
|
||||
Standards-Version: 3.8.4
|
||||
Homepage: http://openbsc.osmocom.org/
|
||||
Vcs-Git: git://bs11-abis.gnumonks.org/openbsc.git
|
||||
@@ -15,7 +15,7 @@ Description: GSM Base Station Controller; BSC-only version of OpenBSC. Needs a
|
||||
|
||||
Package: osmocom-nitb
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends}, ${misc:Depends}, libosmocore, libdbd-sqlite3, libdbi0
|
||||
Depends: ${shlibs:Depends}, ${misc:Depends}, libosmocore, libdbd-sqlite3, libdbi1
|
||||
Description: GSM Network-in-a-Box, implements BSC, MSC, SMSC, HLR, VLR
|
||||
|
||||
Package: osmocom-ipaccess-utils
|
||||
0
openbsc/debian/docs → debian/docs
vendored
0
openbsc/debian/docs → debian/docs
vendored
1
debian/osmocom-bsc.examples
vendored
Normal file
1
debian/osmocom-bsc.examples
vendored
Normal file
@@ -0,0 +1 @@
|
||||
openbsc/doc/examples/osmo-bsc_mgcp
|
||||
8
debian/osmocom-nitb.default
vendored
Normal file
8
debian/osmocom-nitb.default
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
CONFIG_FILE="/etc/osmocom/osmo-nitb.cfg"
|
||||
HLR_FILE="/var/lib/osmocom/hlr.sqlite3"
|
||||
|
||||
DAEMON_ARGS="-P"
|
||||
|
||||
# Uncomment if using LCR+Asterisk
|
||||
# DAEMON_ARGS="-m -P"
|
||||
|
||||
3
debian/osmocom-nitb.dirs
vendored
Normal file
3
debian/osmocom-nitb.dirs
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
/etc/osmocom
|
||||
/var/log/osmocom
|
||||
/var/lib/osmocom
|
||||
1
debian/osmocom-nitb.examples
vendored
Normal file
1
debian/osmocom-nitb.examples
vendored
Normal file
@@ -0,0 +1 @@
|
||||
openbsc/doc/examples/osmo-nitb
|
||||
@@ -15,18 +15,16 @@
|
||||
|
||||
# PATH should only include /usr/* if it runs after the mountnfs.sh script
|
||||
PATH=/sbin:/usr/sbin:/bin:/usr/bin
|
||||
DESC=osmo-nitb # Introduce a short description here
|
||||
NAME=osmo-nitb # Introduce the short server's name here
|
||||
DAEMON=/usr/sbin/osmo-nitb # Introduce the server's location here
|
||||
DAEMON_ARGS="-D" # Arguments to run the daemon with
|
||||
PIDFILE=/var/run/$NAME.pid
|
||||
SCRIPTNAME=/etc/init.d/$NAME
|
||||
NAME=osmo-nitb # Introduce the short server's name here
|
||||
DESC="Osmocom GSM Network-in-a-Box" # Introduce a short description here
|
||||
DAEMON=/usr/bin/osmo-nitb # Introduce the server's location here
|
||||
SCRIPTNAME=/etc/init.d/osmocom-nitb
|
||||
|
||||
# Exit if the package is not installed
|
||||
[ -x $DAEMON ] || exit 0
|
||||
|
||||
# Read configuration variable file if it is present
|
||||
[ -r /etc/default/$NAME ] && . /etc/default/$NAME
|
||||
[ -r /etc/default/osmocom-nitb ] && . /etc/default/osmocom-nitb
|
||||
|
||||
# Load the VERBOSE setting and other rcS variables
|
||||
. /lib/init/vars.sh
|
||||
@@ -35,7 +33,7 @@ SCRIPTNAME=/etc/init.d/$NAME
|
||||
# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
|
||||
. /lib/lsb/init-functions
|
||||
|
||||
DAEMON_ARGS="$DAEMON_ARGS -c $CONFIG_FILE"
|
||||
DAEMON_ARGS="$DAEMON_ARGS -D -c $CONFIG_FILE -l $HLR_FILE"
|
||||
|
||||
#
|
||||
# Function that starts the daemon/service
|
||||
@@ -46,9 +44,9 @@ do_start()
|
||||
# 0 if daemon has been started
|
||||
# 1 if daemon was already running
|
||||
# 2 if daemon could not be started
|
||||
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
|
||||
start-stop-daemon --start --quiet --exec $DAEMON --test > /dev/null \
|
||||
|| return 1
|
||||
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \
|
||||
start-stop-daemon --start --quiet --exec $DAEMON -- \
|
||||
$DAEMON_ARGS \
|
||||
|| return 2
|
||||
# Add code here, if necessary, that waits for the process to be ready
|
||||
@@ -66,7 +64,7 @@ do_stop()
|
||||
# 1 if daemon was already stopped
|
||||
# 2 if daemon could not be stopped
|
||||
# other if a failure occurred
|
||||
start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME
|
||||
start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --name $NAME
|
||||
RETVAL="$?"
|
||||
[ "$RETVAL" = 2 ] && return 2
|
||||
# Wait for children to finish too if this is a daemon that forks
|
||||
@@ -77,8 +75,6 @@ do_stop()
|
||||
# sleep for some time.
|
||||
start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
|
||||
[ "$?" = 2 ] && return 2
|
||||
# Many daemons don't delete their pidfiles when they exit.
|
||||
rm -f $PIDFILE
|
||||
return "$RETVAL"
|
||||
}
|
||||
|
||||
@@ -91,7 +87,7 @@ do_reload() {
|
||||
# restarting (for example, when it is sent a SIGHUP),
|
||||
# then implement that here.
|
||||
#
|
||||
start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME
|
||||
start-stop-daemon --stop --signal 1 --quiet $PIDFILE --name $NAME
|
||||
return 0
|
||||
}
|
||||
|
||||
2
debian/osmocom-sgsn.default
vendored
Normal file
2
debian/osmocom-sgsn.default
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
CONFIG_FILE="/etc/osmocom/osmo-sgsn.cfg"
|
||||
|
||||
150
debian/osmocom-sgsn.init
vendored
Executable file
150
debian/osmocom-sgsn.init
vendored
Executable file
@@ -0,0 +1,150 @@
|
||||
#!/bin/sh
|
||||
### BEGIN INIT INFO
|
||||
# Provides: osmo-sgsn
|
||||
# Required-Start: $network $local_fs
|
||||
# Required-Stop:
|
||||
# Default-Start: 2 3 4 5
|
||||
# Default-Stop: 0 1 6
|
||||
# Short-Description: Osmocom Serving GPRS Support Node
|
||||
# Description: Osmocom Serving GPRS Support Node
|
||||
### END INIT INFO
|
||||
|
||||
# Author: Harald Welte <laforge@gnumonks.org>
|
||||
|
||||
# PATH should only include /usr/* if it runs after the mountnfs.sh script
|
||||
PATH=/sbin:/usr/sbin:/bin:/usr/bin
|
||||
NAME=osmo-sgsn # Introduce the short server's name here
|
||||
DESC="Osmocom Serving GPRS Support Node" # Introduce a short description here
|
||||
DAEMON=/usr/bin/osmo-sgsn # Introduce the server's location here
|
||||
SCRIPTNAME=/etc/init.d/osmocom-sgsn
|
||||
|
||||
# Exit if the package is not installed
|
||||
[ -x $DAEMON ] || exit 0
|
||||
|
||||
# Read configuration variable file if it is present
|
||||
[ -r /etc/default/osmocom-sgsn ] && . /etc/default/osmocom-sgsn
|
||||
|
||||
# Load the VERBOSE setting and other rcS variables
|
||||
. /lib/init/vars.sh
|
||||
|
||||
# Define LSB log_* functions.
|
||||
# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
|
||||
. /lib/lsb/init-functions
|
||||
|
||||
DAEMON_ARGS="$DAEMON_ARGS -D -c $CONFIG_FILE"
|
||||
|
||||
#
|
||||
# Function that starts the daemon/service
|
||||
#
|
||||
do_start()
|
||||
{
|
||||
# Return
|
||||
# 0 if daemon has been started
|
||||
# 1 if daemon was already running
|
||||
# 2 if daemon could not be started
|
||||
start-stop-daemon --start --quiet --exec $DAEMON --test > /dev/null \
|
||||
|| return 1
|
||||
start-stop-daemon --start --quiet --exec $DAEMON -- \
|
||||
$DAEMON_ARGS \
|
||||
|| return 2
|
||||
# Add code here, if necessary, that waits for the process to be ready
|
||||
# to handle requests from services started subsequently which depend
|
||||
# on this one. As a last resort, sleep for some time.
|
||||
}
|
||||
|
||||
#
|
||||
# Function that stops the daemon/service
|
||||
#
|
||||
do_stop()
|
||||
{
|
||||
# Return
|
||||
# 0 if daemon has been stopped
|
||||
# 1 if daemon was already stopped
|
||||
# 2 if daemon could not be stopped
|
||||
# other if a failure occurred
|
||||
start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --name $NAME
|
||||
RETVAL="$?"
|
||||
[ "$RETVAL" = 2 ] && return 2
|
||||
# Wait for children to finish too if this is a daemon that forks
|
||||
# and if the daemon is only ever run from this initscript.
|
||||
# If the above conditions are not satisfied then add some other code
|
||||
# that waits for the process to drop all resources that could be
|
||||
# needed by services started subsequently. A last resort is to
|
||||
# sleep for some time.
|
||||
start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
|
||||
[ "$?" = 2 ] && return 2
|
||||
return "$RETVAL"
|
||||
}
|
||||
|
||||
#
|
||||
# Function that sends a SIGHUP to the daemon/service
|
||||
#
|
||||
do_reload() {
|
||||
#
|
||||
# If the daemon can reload its configuration without
|
||||
# restarting (for example, when it is sent a SIGHUP),
|
||||
# then implement that here.
|
||||
#
|
||||
start-stop-daemon --stop --signal 1 --quiet $PIDFILE --name $NAME
|
||||
return 0
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC " "$NAME"
|
||||
do_start
|
||||
case "$?" in
|
||||
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
|
||||
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
|
||||
esac
|
||||
;;
|
||||
stop)
|
||||
[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
|
||||
do_stop
|
||||
case "$?" in
|
||||
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
|
||||
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
|
||||
esac
|
||||
;;
|
||||
status)
|
||||
status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
|
||||
;;
|
||||
#reload|force-reload)
|
||||
#
|
||||
# If do_reload() is not implemented then leave this commented out
|
||||
# and leave 'force-reload' as an alias for 'restart'.
|
||||
#
|
||||
#log_daemon_msg "Reloading $DESC" "$NAME"
|
||||
#do_reload
|
||||
#log_end_msg $?
|
||||
#;;
|
||||
restart|force-reload)
|
||||
#
|
||||
# If the "reload" option is implemented then remove the
|
||||
# 'force-reload' alias
|
||||
#
|
||||
log_daemon_msg "Restarting $DESC" "$NAME"
|
||||
do_stop
|
||||
case "$?" in
|
||||
0|1)
|
||||
do_start
|
||||
case "$?" in
|
||||
0) log_end_msg 0 ;;
|
||||
1) log_end_msg 1 ;; # Old process is still running
|
||||
*) log_end_msg 1 ;; # Failed to start
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
# Failed to stop
|
||||
log_end_msg 1
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
#echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
|
||||
echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2
|
||||
exit 3
|
||||
;;
|
||||
esac
|
||||
|
||||
:
|
||||
27
openbsc/debian/rules → debian/rules
vendored
27
openbsc/debian/rules → debian/rules
vendored
@@ -13,19 +13,18 @@
|
||||
# Uncomment this to turn on verbose mode.
|
||||
#export DH_VERBOSE=1
|
||||
|
||||
# This has to be exported to make some magic below work.
|
||||
export DH_OPTIONS
|
||||
|
||||
# this requires debhelper 7.0.50 or above, which lenny doesn't have yet!
|
||||
#override_dh_auto_configure:
|
||||
# dh_auto_configure -- --enable-nat --enable-osmo-bsc
|
||||
|
||||
build: build-stamp
|
||||
build-stamp:
|
||||
dh build --before configure
|
||||
dh_auto_configure -- --enable-nat --enable-osmo-bsc
|
||||
dh build --after configure
|
||||
touch build-stamp
|
||||
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')
|
||||
|
||||
%:
|
||||
dh $@
|
||||
dh --sourcedirectory=openbsc --with autoreconf $@
|
||||
|
||||
# This is needed for debian stable (squeeze)
|
||||
override_dh_autoreconf:
|
||||
cd openbsc && autoreconf --install --force
|
||||
|
||||
override_dh_auto_configure:
|
||||
echo $(VERSION) > openbsc/.tarball-version
|
||||
dh_auto_configure --sourcedirectory=openbsc -- --enable-nat --enable-osmo-bsc
|
||||
|
||||
1
debian/source/format
vendored
Normal file
1
debian/source/format
vendored
Normal file
@@ -0,0 +1 @@
|
||||
3.0 (native)
|
||||
1
openbsc/.gitignore
vendored
1
openbsc/.gitignore
vendored
@@ -58,6 +58,7 @@ tests/sccp/sccp_test
|
||||
tests/sms/sms_test
|
||||
tests/timer/timer_test
|
||||
tests/gprs/gprs_test
|
||||
tests/abis/abis_test
|
||||
|
||||
tests/atconfig
|
||||
tests/atlocal
|
||||
|
||||
@@ -19,33 +19,38 @@ dnl checks for libraries
|
||||
AC_SEARCH_LIBS(crypt, crypt,
|
||||
[LIBCRYPT="-lcrypt"; AC_DEFINE([VTY_CRYPT_PW], [], [Use crypt functionality of vty.])])
|
||||
|
||||
PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 0.5.3.60)
|
||||
PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 0.3.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 0.6.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOABIS, libosmoabis >= 0.1.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOGB, libosmogb >= 0.5.2)
|
||||
|
||||
# Enabke/disable the NAT?
|
||||
AC_ARG_ENABLE([nat], [AS_HELP_STRING([--enable-nat], [Build the BSC NAT. Requires SCCP])],
|
||||
[
|
||||
[osmo_ac_build_nat="$enableval"],[osmo_ac_build_nat="no"])
|
||||
if test "$osmo_ac_build_nat" = "yes" ; then
|
||||
PKG_CHECK_MODULES(LIBOSMOSCCP, libosmo-sccp >= 0.0.2)
|
||||
osmo_ac_build_nat="yes"
|
||||
],
|
||||
[
|
||||
osmo_ac_build_nat="no"
|
||||
])
|
||||
fi
|
||||
AM_CONDITIONAL(BUILD_NAT, test "x$osmo_ac_build_nat" = "xyes")
|
||||
AC_SUBST(osmo_ac_build_nat)
|
||||
|
||||
# Enable/disable the BSC?
|
||||
AC_ARG_ENABLE([osmo-bsc], [AS_HELP_STRING([--enable-osmo-bsc], [Build the Osmo BSC])],
|
||||
[
|
||||
PKG_CHECK_MODULES(LIBOSMOSCCP, libosmo-sccp >= 0.0.6)
|
||||
osmo_ac_build_bsc="yes"
|
||||
],
|
||||
[
|
||||
osmo_ac_build_bsc="no"
|
||||
])
|
||||
[osmo_ac_build_bsc="$enableval"])
|
||||
if test "$osmo_ac_build_bsc" = "yes" ; then
|
||||
PKG_CHECK_MODULES(LIBOSMOSCCP, libosmo-sccp >= 0.0.6)
|
||||
fi
|
||||
AM_CONDITIONAL(BUILD_BSC, test "x$osmo_ac_build_bsc" = "xyes")
|
||||
|
||||
PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 0.3.2)
|
||||
PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 0.3.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 0.3.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOABIS, libosmoabis >= 0.1.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOGB, libosmogb >= 0.5.1)
|
||||
# Enable/disable smpp support in the nitb?
|
||||
AC_ARG_ENABLE([smpp], [AS_HELP_STRING([--enable-smpp], [Build the SMPP interface])],
|
||||
[osmo_ac_build_smpp="$enableval"])
|
||||
if test "$osmo_ac_build_smpp" = "yes" ; then
|
||||
PKG_CHECK_MODULES(LIBSMPP34, libsmpp34 >= 1.10)
|
||||
AC_DEFINE(BUILD_SMPP, 1, [Define if we want to build SMPP])
|
||||
fi
|
||||
AM_CONDITIONAL(BUILD_SMPP, test "x$osmo_ac_build_smpp" = "xyes")
|
||||
|
||||
|
||||
found_libgtp=yes
|
||||
PKG_CHECK_MODULES(LIBGTP, libgtp, , found_libgtp=no)
|
||||
@@ -132,13 +137,14 @@ AC_OUTPUT(
|
||||
src/gprs/Makefile
|
||||
tests/Makefile
|
||||
tests/atlocal
|
||||
tests/debug/Makefile
|
||||
tests/gsm0408/Makefile
|
||||
tests/db/Makefile
|
||||
tests/channel/Makefile
|
||||
tests/bsc-nat/Makefile
|
||||
tests/mgcp/Makefile
|
||||
tests/gprs/Makefile
|
||||
tests/si/Makefile
|
||||
tests/abis/Makefile
|
||||
doc/Makefile
|
||||
doc/examples/Makefile
|
||||
Makefile)
|
||||
|
||||
57
openbsc/contrib/dump_all_docs.py
Executable file
57
openbsc/contrib/dump_all_docs.py
Executable file
@@ -0,0 +1,57 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Start the process and dump the documentation to the doc dir. This is
|
||||
copied from the BTS directory and a fix might need to be applied there
|
||||
too.
|
||||
"""
|
||||
|
||||
import socket, subprocess, time,os
|
||||
|
||||
|
||||
def dump_doc(end, port, filename):
|
||||
sck = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
sck.setblocking(1)
|
||||
sck.connect(("localhost", port))
|
||||
sck.recv(4096)
|
||||
|
||||
# Now send the command
|
||||
sck.send("show online-help\r")
|
||||
xml = ""
|
||||
while True:
|
||||
data = sck.recv(4096)
|
||||
xml = "%s%s" % (xml, data)
|
||||
if data.endswith(end):
|
||||
break
|
||||
|
||||
# Now write everything until the end to the file
|
||||
out = open(filename, 'w')
|
||||
out.write(xml[18:len(end)*-1])
|
||||
out.close()
|
||||
|
||||
|
||||
apps = [
|
||||
# The same could be done with an empty config file but this way
|
||||
# the example files are properly tested.
|
||||
(4242, "src/osmo-nitb/osmo-nitb", "doc/examples/osmo-nitb/nanobts/openbsc.cfg", "OpenBSC", "nitb"),
|
||||
(4242, "src/osmo-bsc/osmo-bsc", "doc/examples/osmo-bsc/osmo-bsc.cfg", "OsmoBSC", "bsc"),
|
||||
(4243, "src/osmo-bsc_mgcp/osmo-bsc_mgcp", "doc/examples/osmo-bsc_mgcp/mgcp.cfg", "OpenBSC MGCP", "mgcp"),
|
||||
(4244, "src/osmo-bsc_nat/osmo-bsc_nat", "doc/examples/osmo-bsc_nat/osmo-bsc_nat.cfg", "OsmoBSCNAT", "nat"),
|
||||
(4245, "src/gprs/osmo-sgsn", "doc/examples/osmo-sgsn/osmo-sgsn.cfg", "OsmoSGSN", "sgsn"),
|
||||
(4246, "src/gprs/osmo-gbproxy", "doc/examples/osmo-gbproxy/osmo-gbproxy.cfg", "OsmoGbProxy", "gbproxy"),
|
||||
]
|
||||
|
||||
# Dump the config of all our apps
|
||||
for app in apps:
|
||||
print "Starting app for %s" % app[4]
|
||||
|
||||
cmd = [app[1], "-c", app[2]]
|
||||
proc = subprocess.Popen(cmd, stdin=None, stdout=None)
|
||||
time.sleep(1)
|
||||
try:
|
||||
dump_doc('\r\n%s> ' % app[3], app[0], 'doc/%s_vty_reference.xml' % app[4])
|
||||
finally:
|
||||
# Clean-up
|
||||
proc.kill()
|
||||
proc.wait()
|
||||
|
||||
18
openbsc/contrib/hlr-remove-old.sql
Normal file
18
openbsc/contrib/hlr-remove-old.sql
Normal file
@@ -0,0 +1,18 @@
|
||||
-- Remove old data from the database
|
||||
DELETE FROM Subscriber
|
||||
WHERE id != 1 AND datetime('now', '-10 days') > updated AND authorized != 1;
|
||||
DELETE FROM Equipment
|
||||
WHERE datetime('now', '-10 days') > updated;
|
||||
DELETE FROM EquipmentWatch
|
||||
WHERE datetime('now', '-10 days') > updated;
|
||||
DELETE FROM SMS
|
||||
WHERE datetime('now', '-10 days') > created;
|
||||
DELETE FROM VLR
|
||||
WHERE datetime('now', '-10 days') > updated;
|
||||
DELETE FROM ApduBlobs
|
||||
WHERE datetime('now', '-10 days') > created;
|
||||
DELETE FROM Counters
|
||||
WHERE datetime('now', '-10 days') > timestamp;
|
||||
DELETE FROM RateCounters
|
||||
WHERE datetime('now', '-10 days') > timestamp;
|
||||
VACUUM;
|
||||
@@ -3,54 +3,15 @@ Simple UDP replay from the state files
|
||||
"
|
||||
|
||||
PackageLoader fileInPackage: #Sockets.
|
||||
FileStream fileIn: 'rtp_replay_shared.st'.
|
||||
|
||||
|
||||
Eval [
|
||||
| last_time last_image udp_send socket dest |
|
||||
| replay |
|
||||
|
||||
last_time := nil.
|
||||
last_image := nil.
|
||||
file := FileStream open: 'rtp_ssrc13529910.240.240.1_to_10.240.240.50.state'.
|
||||
|
||||
"Send the payload"
|
||||
dest := Sockets.SocketAddress byName: '127.0.0.1'.
|
||||
socket := Sockets.DatagramSocket new.
|
||||
udp_send := [:payload | | datagram |
|
||||
datagram := Sockets.Datagram data: payload contents address: dest port: 4000.
|
||||
socket nextPut: datagram
|
||||
].
|
||||
replay := RTPReplay on: 'rtp_ssrc6976010.240.240.1_to_10.240.240.50.state'.
|
||||
|
||||
[file atEnd] whileFalse: [
|
||||
| lineStream time data now_image |
|
||||
lineStream := file nextLine readStream.
|
||||
|
||||
"Read the time, skip the blank, parse the data"
|
||||
time := Number readFrom: lineStream.
|
||||
lineStream skip: 1.
|
||||
|
||||
data := WriteStream on: (ByteArray new: 30).
|
||||
[lineStream atEnd] whileFalse: [
|
||||
| hex |
|
||||
hex := lineStream next: 2.
|
||||
data nextPut: (Number readFrom: hex readStream radix: 16).
|
||||
].
|
||||
|
||||
last_time isNil
|
||||
ifTrue: [
|
||||
"First time, send it right now"
|
||||
last_time := time.
|
||||
last_image := Time millisecondClockValue.
|
||||
udp_send value: data.
|
||||
]
|
||||
ifFalse: [
|
||||
| wait_image new_image_time |
|
||||
|
||||
"How long to wait?"
|
||||
wait_image := last_image + ((time - last_time) * 1000).
|
||||
[ wait_image > Time millisecondClockValue ] whileTrue: [].
|
||||
|
||||
udp_send value: data.
|
||||
last_time := time.
|
||||
last_image := wait_image.
|
||||
]
|
||||
].
|
||||
Transcript nextPutAll: 'Going to stream now'; nl.
|
||||
replay streamAudio: '127.0.0.1' port: 4000.
|
||||
]
|
||||
|
||||
108
openbsc/contrib/rtp/rtp_replay_shared.st
Normal file
108
openbsc/contrib/rtp/rtp_replay_shared.st
Normal file
@@ -0,0 +1,108 @@
|
||||
"
|
||||
Simple UDP replay from the state files
|
||||
"
|
||||
|
||||
PackageLoader fileInPackage: #Sockets.
|
||||
|
||||
Object subclass: SDPUtils [
|
||||
"Look into using PetitParser."
|
||||
SDPUtils class >> findPort: aSDP [
|
||||
aSDP linesDo: [:line |
|
||||
(line startsWith: 'm=audio ') ifTrue: [
|
||||
| stream |
|
||||
stream := line readStream
|
||||
skip: 'm=audio ' size;
|
||||
yourself.
|
||||
^ Number readFrom: stream.
|
||||
]
|
||||
].
|
||||
|
||||
^ self error: 'Not found'.
|
||||
]
|
||||
|
||||
SDPUtils class >> findHost: aSDP [
|
||||
aSDP linesDo: [:line |
|
||||
(line startsWith: 'c=IN IP4 ') ifTrue: [
|
||||
| stream |
|
||||
^ stream := line readStream
|
||||
skip: 'c=IN IP4 ' size;
|
||||
upToEnd.
|
||||
]
|
||||
].
|
||||
|
||||
^ self error: 'Not found'.
|
||||
]
|
||||
]
|
||||
|
||||
Object subclass: RTPReplay [
|
||||
| filename socket |
|
||||
RTPReplay class >> on: aFile [
|
||||
^ self new
|
||||
initialize;
|
||||
file: aFile; yourself
|
||||
]
|
||||
|
||||
initialize [
|
||||
socket := Sockets.DatagramSocket new.
|
||||
]
|
||||
|
||||
file: aFile [
|
||||
filename := aFile
|
||||
]
|
||||
|
||||
localPort [
|
||||
^ socket port
|
||||
]
|
||||
|
||||
streamAudio: aHost port: aPort [
|
||||
| file last_time last_image udp_send dest |
|
||||
|
||||
last_time := nil.
|
||||
last_image := nil.
|
||||
file := FileStream open: filename.
|
||||
|
||||
"Send the payload"
|
||||
dest := Sockets.SocketAddress byName: aHost.
|
||||
udp_send := [:payload | | datagram |
|
||||
datagram := Sockets.Datagram data: payload contents address: dest port: aPort.
|
||||
socket nextPut: datagram
|
||||
].
|
||||
|
||||
[file atEnd] whileFalse: [
|
||||
| lineStream time data now_image |
|
||||
lineStream := file nextLine readStream.
|
||||
|
||||
"Read the time, skip the blank, parse the data"
|
||||
time := Number readFrom: lineStream.
|
||||
lineStream skip: 1.
|
||||
|
||||
data := WriteStream on: (ByteArray new: 30).
|
||||
[lineStream atEnd] whileFalse: [
|
||||
| hex |
|
||||
hex := lineStream next: 2.
|
||||
data nextPut: (Number readFrom: hex readStream radix: 16).
|
||||
].
|
||||
|
||||
last_time isNil
|
||||
ifTrue: [
|
||||
"First time, send it right now"
|
||||
last_time := time.
|
||||
last_image := Time millisecondClockValue.
|
||||
udp_send value: data.
|
||||
]
|
||||
ifFalse: [
|
||||
| wait_image new_image_time |
|
||||
|
||||
"How long to wait?"
|
||||
wait_image := last_image + ((time - last_time) * 1000).
|
||||
[ wait_image > Time millisecondClockValue ]
|
||||
whileTrue: [Processor yield].
|
||||
|
||||
udp_send value: data.
|
||||
last_time := time.
|
||||
last_image := wait_image.
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
|
||||
87
openbsc/contrib/rtp/rtp_replay_sip.st
Normal file
87
openbsc/contrib/rtp/rtp_replay_sip.st
Normal file
@@ -0,0 +1,87 @@
|
||||
"""
|
||||
Create a SIP connection and then stream...
|
||||
"""
|
||||
|
||||
PackageLoader
|
||||
fileInPackage: #OsmoSIP.
|
||||
|
||||
"Load for the replay code"
|
||||
FileStream fileIn: 'rtp_replay_shared.st'.
|
||||
|
||||
|
||||
Osmo.SIPCall subclass: StreamCall [
|
||||
| sem stream |
|
||||
|
||||
createCall: aSDP [
|
||||
| sdp |
|
||||
stream := RTPReplay on: 'rtp_ssrc6976010.240.240.1_to_10.240.240.50.state'.
|
||||
sdp := aSDP % {stream localPort}.
|
||||
^ super createCall: sdp.
|
||||
]
|
||||
|
||||
sem: aSemaphore [
|
||||
sem := aSemaphore
|
||||
]
|
||||
|
||||
sessionNew [
|
||||
| host port |
|
||||
Transcript nextPutAll: 'The call has started'; nl.
|
||||
Transcript nextPutAll: sdp_result; nl.
|
||||
|
||||
host := SDPUtils findHost: sdp_result.
|
||||
port := SDPUtils findPort: sdp_result.
|
||||
|
||||
[
|
||||
stream streamAudio: host port: port.
|
||||
Transcript nextPutAll: 'Streaming has finished.'; nl.
|
||||
] fork.
|
||||
]
|
||||
|
||||
sessionFailed [
|
||||
sem signal
|
||||
]
|
||||
|
||||
sessionEnd [
|
||||
sem signal
|
||||
]
|
||||
]
|
||||
|
||||
Eval [
|
||||
| transport agent call sem sdp_fr sdp_amr |
|
||||
|
||||
|
||||
sdp_fr := (WriteStream on: String new)
|
||||
nextPutAll: 'v=0'; cr; nl;
|
||||
nextPutAll: 'o=twinkle 1739517580 1043400482 IN IP4 127.0.0.1'; cr; nl;
|
||||
nextPutAll: 's=-'; cr; nl;
|
||||
nextPutAll: 'c=IN IP4 127.0.0.1'; cr; nl;
|
||||
nextPutAll: 't=0 0'; cr; nl;
|
||||
nextPutAll: 'm=audio %1 RTP/AVP 0 101'; cr; nl;
|
||||
nextPutAll: 'a=rtpmap:0 PCMU/8000'; cr; nl;
|
||||
nextPutAll: 'a=rtpmap:101 telephone-event/8000'; cr; nl;
|
||||
nextPutAll: 'a=fmtp:101 0-15'; cr; nl;
|
||||
nextPutAll: 'a=ptime:20'; cr; nl;
|
||||
contents.
|
||||
|
||||
sem := Semaphore new.
|
||||
transport := Osmo.SIPUdpTransport
|
||||
startOn: '0.0.0.0' port: 5066.
|
||||
agent := Osmo.SIPUserAgent createOn: transport.
|
||||
transport start.
|
||||
|
||||
call := (StreamCall
|
||||
fromUser: 'sip:1000@sip.zecke.osmocom.org'
|
||||
host: '127.0.0.1'
|
||||
port: 5060
|
||||
to: 'sip:123456@127.0.0.1'
|
||||
on: agent)
|
||||
sem: sem; yourself.
|
||||
|
||||
call createCall: sdp_fr.
|
||||
|
||||
|
||||
"Wait for the stream to have ended"
|
||||
sem wait.
|
||||
|
||||
(Delay forSeconds: 4) wait.
|
||||
]
|
||||
9
openbsc/contrib/systemd/osmo-bsc-mgcp.service
Normal file
9
openbsc/contrib/systemd/osmo-bsc-mgcp.service
Normal file
@@ -0,0 +1,9 @@
|
||||
[Unit]
|
||||
Description=OpenBSC MGCP
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
Restart=always
|
||||
ExecStart=/usr/bin/osmo-bsc_mgcp -s -c /etc/osmocom/osmo-bsc-mgcp.cfg
|
||||
Restart=always
|
||||
RestartSec=2
|
||||
10
openbsc/contrib/systemd/osmo-bsc.service
Normal file
10
openbsc/contrib/systemd/osmo-bsc.service
Normal file
@@ -0,0 +1,10 @@
|
||||
[Unit]
|
||||
Description=OpenBSC BSC
|
||||
Requires=osmo-bsc-mgcp.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
Restart=always
|
||||
ExecStart=/usr/bin/osmo-bsc -c /etc/osmocom/osmo-bsc.cfg -s
|
||||
Restart=always
|
||||
RestartSec=2
|
||||
9
openbsc/contrib/systemd/osmo-nitb.service
Normal file
9
openbsc/contrib/systemd/osmo-nitb.service
Normal file
@@ -0,0 +1,9 @@
|
||||
[Unit]
|
||||
Description=OpenBSC Network In the Box (NITB)
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
Restart=always
|
||||
ExecStart=/usr/bin/osmo-nitb -s -C -c /etc/osmocom/osmo-nitb.cfg -l /var/lib/osmocom/hlr.sqlite3
|
||||
Restart=always
|
||||
RestartSec=2
|
||||
@@ -1,11 +0,0 @@
|
||||
openbsc (0.9.13.115.eb113-1) natty; urgency=low
|
||||
|
||||
* New upstream release
|
||||
|
||||
-- Harald Welte <laforge@gnumonks.org> Wed, 11 May 2011 18:41:24 +0000
|
||||
|
||||
openbsc (0.9.4-1) unstable; urgency=low
|
||||
|
||||
* Initial release (Closes: #nnnn) <nnnn is the bug number of your ITP>
|
||||
|
||||
-- Harald Welte <laforge@gnumonks.org> Tue, 24 Aug 2010 13:34:24 +0200
|
||||
@@ -1 +0,0 @@
|
||||
doc/examples/osmo-bsc_mgcp
|
||||
@@ -1,2 +0,0 @@
|
||||
# Configuration file
|
||||
CONFIG_FILE="/etc/osmocom/osmo-nitb.cfg"
|
||||
@@ -1 +0,0 @@
|
||||
doc/examples/osmo-nitb
|
||||
@@ -1,29 +0,0 @@
|
||||
Description: Upstream changes introduced in version 0.9.4-1
|
||||
This patch has been created by dpkg-source during the package build.
|
||||
Here's the last changelog entry, hopefully it gives details on why
|
||||
those changes were made:
|
||||
.
|
||||
openbsc (0.9.4-1) unstable; urgency=low
|
||||
.
|
||||
* Initial release (Closes: #nnnn) <nnnn is the bug number of your ITP>
|
||||
.
|
||||
The person named in the Author field signed this changelog entry.
|
||||
Author: Harald Welte <laforge@gnumonks.org>
|
||||
|
||||
---
|
||||
The information above should follow the Patch Tagging Guidelines, please
|
||||
checkout http://dep.debian.net/deps/dep3/ to learn about the format. Here
|
||||
are templates for supplementary fields that you might want to add:
|
||||
|
||||
Origin: <vendor|upstream|other>, <url of original patch>
|
||||
Bug: <url in upstream bugtracker>
|
||||
Bug-Debian: http://bugs.debian.org/<bugnumber>
|
||||
Bug-Ubuntu: https://launchpad.net/bugs/<bugnumber>
|
||||
Forwarded: <no|not-needed|url proving that it has been forwarded>
|
||||
Reviewed-By: <name and email of someone who approved the patch>
|
||||
Last-Update: <YYYY-MM-DD>
|
||||
|
||||
--- /dev/null
|
||||
+++ openbsc-0.9.4/.version
|
||||
@@ -0,0 +1 @@
|
||||
+0.9.4
|
||||
@@ -1 +0,0 @@
|
||||
debian-changes-0.9.4-1
|
||||
@@ -1 +0,0 @@
|
||||
3.0 (quilt)
|
||||
@@ -56,21 +56,21 @@ bsc_api.c:gsm0808_clear
|
||||
* Release the primary lchan with normal release, SACH deactivate
|
||||
|
||||
chan_alloc.c:lchan_release(chan, sacch_deactivate, reason)
|
||||
* Start release procedure. It is working in steps with callbacks
|
||||
coming from the abis_rsl.c code.
|
||||
* Release all SAPI's > 0, wait for them to be released
|
||||
* Send SACH Deactivate on SAPI=0
|
||||
* Finally Release the channel
|
||||
* Start the release procedure. It is working in steps with callbacks
|
||||
coming from the abis_rsl.c code.
|
||||
* Release all SAPI's > 0 as local end (The BTS should send a
|
||||
REL_CONF a message)
|
||||
* Send SACH Deactivate on SAPI=0 if required.
|
||||
* Start T3109 (stop it when the main signalling link is disconnected)
|
||||
or when the channel released. On timeout start the error handling.
|
||||
* abis_rsl.c schedules the RSL_MT_RF_CHAN_REL once all SAPI's are
|
||||
released and after T3111 has timed out or there is an error.
|
||||
|
||||
RX of RELease INDication:
|
||||
* Calls internal rsl_handle_release which might release the RF.
|
||||
* Informs chan_alloc.c about the release with
|
||||
rsl_lchan_rll_release.
|
||||
|
||||
RX of RELease CONFimem:
|
||||
RX of RELease CONFirmation:
|
||||
* Calls internal rsl_handle_release which might release the RF.
|
||||
* Informs chan_alloc.c about the release with
|
||||
rsl_lchan_rll_release.
|
||||
|
||||
* RX of RF_CHAN_REL_ACK
|
||||
* call lchan_free()
|
||||
|
||||
@@ -3,38 +3,6 @@
|
||||
!!
|
||||
password foo
|
||||
!
|
||||
log stderr
|
||||
logging color 1
|
||||
logging timestamp 0
|
||||
logging level all everything
|
||||
logging level rll notice
|
||||
logging level cc notice
|
||||
logging level mm notice
|
||||
logging level rr notice
|
||||
logging level rsl notice
|
||||
logging level nm info
|
||||
logging level mncc notice
|
||||
logging level sms notice
|
||||
logging level pag notice
|
||||
logging level meas notice
|
||||
logging level mi notice
|
||||
logging level mib notice
|
||||
logging level mux notice
|
||||
logging level inp 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 lglobal notice
|
||||
logging level llapdm notice
|
||||
!
|
||||
line vty
|
||||
no login
|
||||
@@ -129,5 +97,4 @@ msc
|
||||
ip.access rtp-base 4000
|
||||
timeout-ping 20
|
||||
timeout-pong 5
|
||||
mid-call-timeout 0
|
||||
dest 192.168.100.11 6666 0
|
||||
|
||||
@@ -9,7 +9,7 @@ line vty
|
||||
mgcp
|
||||
! local ip 213.167.134.14
|
||||
bts ip 172.16.252.43
|
||||
bind ip 213.167.134.141
|
||||
bind ip 127.0.0.1
|
||||
bind port 2427
|
||||
bind early 1
|
||||
rtp base 4000
|
||||
|
||||
3
openbsc/doc/examples/osmo-bsc_nat/osmo-bsc_nat.cfg
Normal file
3
openbsc/doc/examples/osmo-bsc_nat/osmo-bsc_nat.cfg
Normal file
@@ -0,0 +1,3 @@
|
||||
nat
|
||||
mgcp
|
||||
call agent ip 127.0.0.1
|
||||
@@ -20,5 +20,6 @@ ns
|
||||
timer tns-test 30
|
||||
timer tns-alive 3
|
||||
timer tns-alive-retries 10
|
||||
encapsulation framerelay-gre enabled 1
|
||||
encapsulation framerelay-gre enabled 0
|
||||
encapsulation framerelay-gre local-ip 0.0.0.0
|
||||
encapsulation udp local-port 23000
|
||||
@@ -30,7 +30,7 @@ network
|
||||
timer t3103 0
|
||||
timer t3105 0
|
||||
timer t3107 0
|
||||
timer t3109 0
|
||||
timer t3109 4
|
||||
timer t3111 0
|
||||
timer t3113 60
|
||||
timer t3115 0
|
||||
|
||||
@@ -31,7 +31,7 @@ network
|
||||
timer t3103 0
|
||||
timer t3105 0
|
||||
timer t3107 0
|
||||
timer t3109 0
|
||||
timer t3109 4
|
||||
timer t3111 0
|
||||
timer t3113 60
|
||||
timer t3115 0
|
||||
|
||||
@@ -30,7 +30,7 @@ network
|
||||
timer t3103 0
|
||||
timer t3105 0
|
||||
timer t3107 0
|
||||
timer t3109 0
|
||||
timer t3109 4
|
||||
timer t3111 0
|
||||
timer t3113 60
|
||||
timer t3115 0
|
||||
|
||||
@@ -30,7 +30,7 @@ network
|
||||
timer t3103 0
|
||||
timer t3105 0
|
||||
timer t3107 0
|
||||
timer t3109 0
|
||||
timer t3109 4
|
||||
timer t3111 0
|
||||
timer t3113 60
|
||||
timer t3115 0
|
||||
|
||||
@@ -13,7 +13,6 @@ network
|
||||
mobile network code 1
|
||||
short name OpenBSC
|
||||
long name OpenBSC
|
||||
auth policy accept-all
|
||||
timer t3101 10
|
||||
timer t3113 60
|
||||
bts 0
|
||||
|
||||
@@ -29,7 +29,7 @@ network
|
||||
timer t3103 0
|
||||
timer t3105 0
|
||||
timer t3107 0
|
||||
timer t3109 0
|
||||
timer t3109 4
|
||||
timer t3111 0
|
||||
timer t3113 60
|
||||
timer t3115 0
|
||||
|
||||
94
openbsc/doc/ipa-sccp.txt
Normal file
94
openbsc/doc/ipa-sccp.txt
Normal file
@@ -0,0 +1,94 @@
|
||||
|
||||
IPA SCCP message flow in the BSC
|
||||
|
||||
February, 2013 Holger Hans Peter Freyther
|
||||
|
||||
CONTENTS
|
||||
|
||||
1. SCCP inside the IPA header
|
||||
2. Supported SCCP message types
|
||||
3. Receiving SCCP messages
|
||||
4. Sending SCCP messages
|
||||
|
||||
|
||||
1. SCCP inside the IPA header
|
||||
|
||||
Many Soft-MSCs implement something that is called SCCP/lite. This means
|
||||
that SCCP messages are transported inside a small multiplexing protocol
|
||||
over TCP/IP. This is an alternative to a full SIGTRAN implementation.
|
||||
|
||||
The multiplexing protocol is the same as used with the sysmoBTS and the
|
||||
ip.access nanoBTS. It is a three byte header with two bytes for the length
|
||||
in network byte order and one byte for the type. The type to be used for
|
||||
SCCP is 0xFD.
|
||||
|
||||
struct ipa_header {
|
||||
uint16_t length_in_network_order;
|
||||
uint8_t type;
|
||||
} __attribute__((packed));
|
||||
|
||||
|
||||
|
||||
2. Supported SCCP message types
|
||||
|
||||
To implement GSM 08.08 only a subset of SCCP messages need to be implemented.
|
||||
For transporting paging and reset messages SCCP UDT messages are used. For
|
||||
the connections with a Mobile Station (MS) a SCCP connection is opened. This
|
||||
means that the SCCP CR, SCCP CC, SCCP CREF, SCCP RLC, SCCP RLSD, SCCP DT1
|
||||
and SCCP IT messages are supported.
|
||||
|
||||
|
||||
3. Receiving SCCP UDT messages
|
||||
|
||||
This is an illustration of the flow of messages. The IPA multiplexing protocol
|
||||
is used for various protocols. This means there is a central place where the
|
||||
multiplexing stream terminates. The stream is terminated in the osmo_bsc_msc.c
|
||||
file and the ipaccess_a_fd_cb method. For SCCP messages the SCCP dispatching
|
||||
sccp_system_incoming method is called. This function is implemented in the
|
||||
libosmo-sccp library.
|
||||
|
||||
To receive UDT messages osmo_bsc_sccp.c:osmo_bsc_sccp_init is using the
|
||||
sccp_set_read function to register a callback for UDT messages. The callback
|
||||
is msc_sccp_read and it is calling bsc_handle_udt that is implemented in the
|
||||
osmo_bsc_bssap.c. This function will handle the GSM 08.08 BSSAP messages.
|
||||
Currently only the reset acknowledge and the paging messages are handled.
|
||||
|
||||
The BSC currently does not accept incoming SCCP messages and is only opening
|
||||
SCCP connections to the MSC. When opening a connection the callbacks for state
|
||||
changes (connection confirmed, released, release complete) are set and a routine
|
||||
for handling incoming data. This registration is done in the osmo_bsc_sccp.c
|
||||
file and the bsc_create_new_connection method. The name of the callback is
|
||||
msc_outgoing_sccp_data and this will call bsc_handle_dt1 that is implemented
|
||||
in the osmo_bsc_bssap.c file. This will forward the messages to the right
|
||||
Mobile Station (MS).
|
||||
|
||||
|
||||
4. Sending SCCP messages
|
||||
|
||||
There are three parts to sending that will be explained below. The first part
|
||||
is to send an entire SCCP frame (which includes the GSM 08.08 data) to the
|
||||
MSC. This is done by first registering the low level sending. sccp_system_init
|
||||
is called with the function that is responsible for sending a message. The
|
||||
msc_sccp_write_ipa will call the msc_queue_write function with the data and
|
||||
the right MSC connection. Below the msc_queue_write the IPA header will be
|
||||
prepended to the msg and then send to the MSC.
|
||||
|
||||
The BSC supports multiple different A-link connections, the decision to pick
|
||||
the right MSC is done in this method. It is either done via the SCCP connection
|
||||
or the ctx pointer.
|
||||
|
||||
When the BSC is starting a BSS RESET message will be sent to the MSC. The reset
|
||||
is created in osmo_bsc_msc.c:initialize_if_needed and sccp_write is called with
|
||||
the GSM 08.08 data and the connection to use. The libosmo-sccp library will
|
||||
embed it into a SCCP UDT message and call the msc_sccp_write_ipa method.
|
||||
|
||||
When a new SCCP connection is to be created the bsc_create_new_connection
|
||||
in the osmo_bsc_sccp.c file. The sccp_connection_socket method will create
|
||||
the context for a SCCP connection. The state and data callback will be used
|
||||
to be notified about data and changes. Once the connection is configured the
|
||||
bsc_open_connection will be called that will ask the libosmo-sccp library to
|
||||
create a SCCP CR message using the sccp_connection_connect method. For active
|
||||
connections the sccp_connection_write method will be called.
|
||||
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ problems:
|
||||
* therefore, we can have e.g. both the BSC and the OML interface send a
|
||||
SET ATTRIBUTE message, where the responses would end up at the wrong
|
||||
query.
|
||||
* The BTS has 10s to ACK/NACK a command. We do not run any timers.
|
||||
|
||||
the only possible solutions i can imagine:
|
||||
* have some kind of exclusive locking, where the OML interface gets blocked
|
||||
|
||||
48
openbsc/doc/paging.txt
Normal file
48
openbsc/doc/paging.txt
Normal file
@@ -0,0 +1,48 @@
|
||||
|
||||
GSM Paging implementation in OpenBSC
|
||||
|
||||
== Code structure ==
|
||||
|
||||
The code is implemented in the libbsc/paging.c file. The external
|
||||
interface is documented/specified in the include/openbsc/paging.h
|
||||
header file. The code is used by the NITB and BSC application.
|
||||
|
||||
|
||||
== Implementation ==
|
||||
|
||||
Paging can be initiated in two ways. The standard way is to page by
|
||||
LAC. Each BTS has its own list/queue of outstanding paging operation.
|
||||
When a subscriber is paged one "struct paging_request" per BTS will
|
||||
be allocated and added to the tail of the list. The BTS is supposed
|
||||
to be configured to not repeat the paging.
|
||||
|
||||
A paging_request will remain in the queue until a paging response or at
|
||||
the expiry of the T3113. Every 500 milliseconds a RSL paging command is
|
||||
send to the BTS. The 500 milliseconds is a throttling to not crash the
|
||||
ip.access nanoBTS. Once one paging_request has been handled it will be
|
||||
put at the end of the queue/list and the available slots for the BTS
|
||||
will be decreased.
|
||||
|
||||
The available slots will be updated based on the paging load information
|
||||
element of the CCCH Load indication. If no paging slots are considered
|
||||
to be available and no load indication is sent a timer is started. The
|
||||
current timeout is 500 milliseconds and at the expiry of the timer the
|
||||
available slots will be set to 20.
|
||||
|
||||
OpenBSC has the " paging free <-1-1024>" configuration option. In case
|
||||
there are less free channels than required no paging request will be
|
||||
sent to the BTS. Instead it will be attempted to send the paging request
|
||||
at the next timeout (500 milliseconds).
|
||||
|
||||
== Limitation ==
|
||||
|
||||
The paging throughput could be higher but this has lead to crashes on the
|
||||
ip.access nanoBTS in the past.
|
||||
|
||||
== Configuration ==
|
||||
|
||||
=== ip.access nanoBTS ===
|
||||
|
||||
The current CCCH Load indication threshold is 10% and the period is 1 second.
|
||||
The code can be found inside the src/libbsc/bts_ipaccess_nanobts.c inside the
|
||||
nanobts_attr_bts array.
|
||||
@@ -12,7 +12,8 @@ noinst_HEADERS = abis_nm.h abis_rsl.h db.h gsm_04_08.h gsm_data.h \
|
||||
auth.h osmo_msc.h bsc_msc.h bsc_nat.h \
|
||||
osmo_bsc_rf.h osmo_bsc.h network_listen.h bsc_nat_sccp.h \
|
||||
osmo_msc_data.h osmo_bsc_grace.h sms_queue.h abis_om2000.h \
|
||||
bss.h gsm_data_shared.h control_cmd.h ipaccess.h mncc_int.h
|
||||
bss.h gsm_data_shared.h control_cmd.h ipaccess.h mncc_int.h \
|
||||
arfcn_range_encode.h
|
||||
|
||||
openbsc_HEADERS = gsm_04_08.h meas_rep.h bsc_api.h
|
||||
openbscdir = $(includedir)/openbsc
|
||||
|
||||
@@ -66,6 +66,18 @@ struct abis_nm_cfg {
|
||||
int (*sw_act_req)(struct msgb *);
|
||||
};
|
||||
|
||||
struct abis_nm_sw_descr {
|
||||
/* where does it start? how long is it? */
|
||||
const uint8_t *start;
|
||||
size_t len;
|
||||
|
||||
/* the parsed data */
|
||||
const uint8_t *file_id;
|
||||
uint16_t file_id_len;
|
||||
const uint8_t *file_ver;
|
||||
uint16_t file_ver_len;
|
||||
};
|
||||
|
||||
extern int abis_nm_rcvmsg(struct msgb *msg);
|
||||
|
||||
int abis_nm_tlv_parse(struct tlv_parsed *tp, struct gsm_bts *bts, const uint8_t *buf, int len);
|
||||
@@ -81,6 +93,9 @@ int abis_nm_conn_terr_sign(struct gsm_bts_trx *trx,
|
||||
int abis_nm_conn_terr_traf(struct gsm_bts_trx_ts *ts,
|
||||
uint8_t e1_port, uint8_t e1_timeslot,
|
||||
uint8_t e1_subslot);
|
||||
int abis_nm_get_attr(struct gsm_bts *bts, uint8_t obj_class,
|
||||
uint8_t bts_nr, uint8_t trx_nr, uint8_t ts_nr,
|
||||
uint8_t *attr, uint8_t attr_len);
|
||||
int abis_nm_set_bts_attr(struct gsm_bts *bts, uint8_t *attr, int attr_len);
|
||||
int abis_nm_set_radio_attr(struct gsm_bts_trx *trx, uint8_t *attr, int attr_len);
|
||||
int abis_nm_set_channel_attr(struct gsm_bts_trx_ts *ts, uint8_t chan_comb);
|
||||
@@ -164,4 +179,8 @@ int _abis_nm_sendmsg(struct msgb *msg);
|
||||
|
||||
void abis_nm_queue_send_next(struct gsm_bts *bts); /* for bs11_config. */
|
||||
|
||||
int abis_nm_parse_sw_config(const uint8_t *data, const size_t len,
|
||||
struct abis_nm_sw_descr *res, const int res_len);
|
||||
int abis_nm_select_newest_sw(const struct abis_nm_sw_descr *sw, const size_t len);
|
||||
|
||||
#endif /* _NM_H */
|
||||
|
||||
@@ -67,13 +67,13 @@ int rsl_ipacc_pdch_activate(struct gsm_bts_trx_ts *ts, int act);
|
||||
int abis_rsl_rcvmsg(struct msgb *msg);
|
||||
|
||||
uint64_t str_to_imsi(const char *imsi_str);
|
||||
int rsl_release_request(struct gsm_lchan *lchan, uint8_t link_id, uint8_t reason);
|
||||
int rsl_release_request(struct gsm_lchan *lchan, uint8_t link_id,
|
||||
enum rsl_rel_mode release_mode);
|
||||
|
||||
int rsl_lchan_set_state(struct gsm_lchan *lchan, int);
|
||||
|
||||
/* to be provided by external code */
|
||||
int rsl_deact_sacch(struct gsm_lchan *lchan);
|
||||
int rsl_lchan_rll_release(struct gsm_lchan *lchan, uint8_t link_id);
|
||||
|
||||
/* BCCH related code */
|
||||
int rsl_ccch_conf_to_bs_cc_chans(int ccch_conf);
|
||||
@@ -96,5 +96,12 @@ int rsl_nokia_si_end(struct gsm_bts_trx *trx);
|
||||
/* required for Nokia BTS power control */
|
||||
int rsl_bs_power_control(struct gsm_bts_trx *trx, uint8_t channel, uint8_t reduction);
|
||||
|
||||
|
||||
int rsl_release_sapis_from(struct gsm_lchan *lchan, int start,
|
||||
enum rsl_rel_mode release_mode);
|
||||
int rsl_start_t3109(struct gsm_lchan *lchan);
|
||||
|
||||
int rsl_direct_rf_release(struct gsm_lchan *lchan);
|
||||
|
||||
#endif /* RSL_MT_H */
|
||||
|
||||
|
||||
26
openbsc/include/openbsc/arfcn_range_encode.h
Normal file
26
openbsc/include/openbsc/arfcn_range_encode.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#ifndef ARFCN_RANGE_ENCODE_H
|
||||
#define ARFCN_RANGE_ENCODE_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
enum {
|
||||
ARFCN_RANGE_INVALID = -1,
|
||||
ARFCN_RANGE_128 = 127,
|
||||
ARFCN_RANGE_256 = 255,
|
||||
ARFCN_RANGE_512 = 511,
|
||||
ARFCN_RANGE_1024 = 1023,
|
||||
};
|
||||
|
||||
#define RANGE_ENC_MAX_ARFCNS 29
|
||||
|
||||
int range_enc_determine_range(const int *arfcns, int size, int *f0_out);
|
||||
int range_enc_arfcns(const int rng, const int *arfcns, int sze, int *out, int idx);
|
||||
int range_enc_find_index(const int rng, const int *arfcns, int size);
|
||||
int range_enc_filter_arfcns(const int rng, int *arfcns, const int sze, const int f0, int *f0_included);
|
||||
|
||||
int range_enc_range128(uint8_t *chan_list, int f0, int *w);
|
||||
int range_enc_range256(uint8_t *chan_list, int f0, int *w);
|
||||
int range_enc_range512(uint8_t *chan_list, int f0, int *w);
|
||||
int range_enc_range1024(uint8_t *chan_list, int f0, int f0_incl, int *w);
|
||||
|
||||
#endif
|
||||
@@ -34,6 +34,13 @@ struct bsc_api {
|
||||
void (*classmark_chg)(struct gsm_subscriber_connection *conn,
|
||||
const uint8_t *cm2, uint8_t cm2_len,
|
||||
const uint8_t *cm3, uint8_t cm3_len);
|
||||
|
||||
/**
|
||||
* Configure the multirate setting on this channel. If it is
|
||||
* not implemented AMR5.9 will be used.
|
||||
*/
|
||||
void (*mr_config)(struct gsm_subscriber_connection *conn,
|
||||
struct gsm48_multi_rate_conf *conf);
|
||||
};
|
||||
|
||||
int bsc_api_init(struct gsm_network *network, struct bsc_api *api);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* (C) 2010-2011 by Holger Hans Peter Freyther <zecke@selfish.org>
|
||||
* (C) 2010-2011 by On-Waves
|
||||
* (C) 2010-2012 by Holger Hans Peter Freyther <zecke@selfish.org>
|
||||
* (C) 2010-2012 by On-Waves
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -287,6 +287,10 @@ struct bsc_nat {
|
||||
/* filter */
|
||||
char *acc_lst_name;
|
||||
|
||||
/* Barring of subscribers with a rb tree */
|
||||
struct rb_root imsi_black_list;
|
||||
char *imsi_black_list_fn;
|
||||
|
||||
/* number rewriting */
|
||||
char *num_rewr_name;
|
||||
struct llist_head num_rewr;
|
||||
@@ -314,6 +318,9 @@ struct bsc_nat {
|
||||
|
||||
/* statistics */
|
||||
struct bsc_nat_statistics stats;
|
||||
|
||||
/* control interface */
|
||||
struct ctrl_handle *ctrl;
|
||||
};
|
||||
|
||||
struct bsc_nat_ussd_con {
|
||||
@@ -324,6 +331,11 @@ struct bsc_nat_ussd_con {
|
||||
struct osmo_timer_list auth_timeout;
|
||||
};
|
||||
|
||||
struct bsc_nat_reject_cause {
|
||||
int lu_reject_cause;
|
||||
int cm_reject_cause;
|
||||
};
|
||||
|
||||
/* create and init the structures */
|
||||
struct bsc_config *bsc_config_alloc(struct bsc_nat *nat, const char *token);
|
||||
struct bsc_config *bsc_config_num(struct bsc_nat *nat, int num);
|
||||
@@ -357,9 +369,11 @@ int bsc_nat_find_paging(struct msgb *msg, const uint8_t **,int *len);
|
||||
* Content filtering.
|
||||
*/
|
||||
int bsc_nat_filter_sccp_cr(struct bsc_connection *bsc, struct msgb *msg,
|
||||
struct bsc_nat_parsed *, int *con_type, char **imsi);
|
||||
struct bsc_nat_parsed *, int *con_type, char **imsi,
|
||||
struct bsc_nat_reject_cause *cause);
|
||||
int bsc_nat_filter_dt(struct bsc_connection *bsc, struct msgb *msg,
|
||||
struct sccp_connections *con, struct bsc_nat_parsed *parsed);
|
||||
struct sccp_connections *con, struct bsc_nat_parsed *parsed,
|
||||
struct bsc_nat_reject_cause *cause);
|
||||
|
||||
/**
|
||||
* SCCP patching and handling
|
||||
@@ -438,4 +452,19 @@ struct bsc_nat_num_rewr_entry {
|
||||
|
||||
void bsc_nat_num_rewr_entry_adapt(void *ctx, struct llist_head *head, const struct osmo_config_list *);
|
||||
|
||||
struct bsc_nat_barr_entry {
|
||||
struct rb_node node;
|
||||
|
||||
char *imsi;
|
||||
int cm_reject_cause;
|
||||
int lu_reject_cause;
|
||||
};
|
||||
|
||||
int bsc_nat_barr_adapt(void *ctx, struct rb_root *rbtree, const struct osmo_config_list *);
|
||||
int bsc_nat_barr_find(struct rb_root *root, const char *imsi, int *cm, int *lu);
|
||||
|
||||
struct ctrl_handle *bsc_nat_controlif_setup(struct bsc_nat *nat, int port);
|
||||
void bsc_nat_ctrl_del_pending(struct bsc_cmd_list *pending);
|
||||
int bsc_nat_handle_ctrlif_msg(struct bsc_connection *bsc, struct msgb *msg);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -15,4 +15,5 @@ extern int bts_model_rbs2k_init(void);
|
||||
extern int bts_model_nanobts_init(void);
|
||||
extern int bts_model_hslfemto_init(void);
|
||||
extern int bts_model_nokia_site_init(void);
|
||||
extern int bts_model_sysmobts_init(void);
|
||||
#endif
|
||||
|
||||
@@ -46,7 +46,7 @@ void lchan_free(struct gsm_lchan *lchan);
|
||||
void lchan_reset(struct gsm_lchan *lchan);
|
||||
|
||||
/* Release the given lchan */
|
||||
int lchan_release(struct gsm_lchan *lchan, int sacch_deact, int release_mode);
|
||||
int lchan_release(struct gsm_lchan *lchan, int sacch_deact, enum rsl_rel_mode release_mode);
|
||||
|
||||
struct load_counter {
|
||||
unsigned int total;
|
||||
|
||||
@@ -2,17 +2,21 @@
|
||||
#define _CONTROL_CMD_H
|
||||
|
||||
#include <osmocom/core/msgb.h>
|
||||
#include <osmocom/core/talloc.h>
|
||||
#include <osmocom/core/write_queue.h>
|
||||
|
||||
#include <osmocom/vty/vector.h>
|
||||
|
||||
#include <openbsc/vty.h>
|
||||
|
||||
#define CTRL_CMD_ERROR -1
|
||||
#define CTRL_CMD_HANDLED 0
|
||||
#define CTRL_CMD_REPLY 1
|
||||
|
||||
struct ctrl_handle;
|
||||
|
||||
enum ctrl_node_type {
|
||||
CTRL_NODE_ROOT, /* Root elements */
|
||||
CTRL_NODE_NET, /* Network specific (net.) */
|
||||
CTRL_NODE_BTS, /* BTS specific (net.btsN.) */
|
||||
CTRL_NODE_TRX, /* TRX specific (net.btsN.trxM.) */
|
||||
CTRL_NODE_TS, /* TS specific (net.btsN.trxM.tsI.) */
|
||||
@@ -75,15 +79,17 @@ int ctrl_cmd_exec(vector vline, struct ctrl_cmd *command, vector node, void *dat
|
||||
int ctrl_cmd_install(enum ctrl_node_type node, struct ctrl_cmd_element *cmd);
|
||||
int ctrl_cmd_handle(struct ctrl_cmd *cmd, void *data);
|
||||
int ctrl_cmd_send(struct osmo_wqueue *queue, struct ctrl_cmd *cmd);
|
||||
int ctrl_cmd_send_to_all(struct ctrl_handle *ctrl, struct ctrl_cmd *cmd);
|
||||
struct ctrl_cmd *ctrl_cmd_parse(void *ctx, struct msgb *msg);
|
||||
struct msgb *ctrl_cmd_make(struct ctrl_cmd *cmd);
|
||||
struct ctrl_cmd *ctrl_cmd_cpy(void *ctx, struct ctrl_cmd *cmd);
|
||||
struct ctrl_cmd *ctrl_cmd_create(void *ctx, enum ctrl_type);
|
||||
struct ctrl_cmd *ctrl_cmd_trap(struct ctrl_cmd *cmd);
|
||||
|
||||
#define CTRL_CMD_DEFINE_RANGE(cmdname, cmdstr, dtype, element, min, max) \
|
||||
static int get_##cmdname(struct ctrl_cmd *cmd, void *data) \
|
||||
static int get_##cmdname(struct ctrl_cmd *cmd, void *_data) \
|
||||
{ \
|
||||
dtype *node = data; \
|
||||
dtype *node = cmd->node; \
|
||||
cmd->reply = talloc_asprintf(cmd, "%i", node->element); \
|
||||
if (!cmd->reply) { \
|
||||
cmd->reply = "OOM"; \
|
||||
@@ -91,14 +97,14 @@ static int get_##cmdname(struct ctrl_cmd *cmd, void *data) \
|
||||
} \
|
||||
return CTRL_CMD_REPLY; \
|
||||
} \
|
||||
static int set_##cmdname(struct ctrl_cmd *cmd, void *data) \
|
||||
static int set_##cmdname(struct ctrl_cmd *cmd, void *_data) \
|
||||
{ \
|
||||
dtype *node = data; \
|
||||
dtype *node = cmd->node; \
|
||||
int tmp = atoi(cmd->value); \
|
||||
node->element = tmp; \
|
||||
return get_##cmdname(cmd, data); \
|
||||
return get_##cmdname(cmd, _data); \
|
||||
} \
|
||||
static int verify_##cmdname(struct ctrl_cmd *cmd, const char *value, void *data) \
|
||||
static int verify_##cmdname(struct ctrl_cmd *cmd, const char *value, void *_data) \
|
||||
{ \
|
||||
int tmp = atoi(value); \
|
||||
if ((tmp >= min)&&(tmp <= max)) { \
|
||||
@@ -115,8 +121,9 @@ struct ctrl_cmd_element cmd_##cmdname = { \
|
||||
}
|
||||
|
||||
#define CTRL_CMD_DEFINE_STRING(cmdname, cmdstr, dtype, element) \
|
||||
static int get_##cmdname(struct ctrl_cmd *cmd, dtype *data) \
|
||||
static int get_##cmdname(struct ctrl_cmd *cmd, void *_data) \
|
||||
{ \
|
||||
dtype *data = cmd->node; \
|
||||
cmd->reply = talloc_asprintf(cmd, "%s", data->element); \
|
||||
if (!cmd->reply) { \
|
||||
cmd->reply = "OOM"; \
|
||||
@@ -124,10 +131,11 @@ static int get_##cmdname(struct ctrl_cmd *cmd, dtype *data) \
|
||||
} \
|
||||
return CTRL_CMD_REPLY; \
|
||||
} \
|
||||
static int set_##cmdname(struct ctrl_cmd *cmd, dtype *data) \
|
||||
static int set_##cmdname(struct ctrl_cmd *cmd, void *_data) \
|
||||
{ \
|
||||
dtype *data = cmd->node; \
|
||||
bsc_replace_string(cmd->node, &data->element, cmd->value); \
|
||||
return get_##cmdname(cmd, data); \
|
||||
return get_##cmdname(cmd, _data); \
|
||||
} \
|
||||
struct ctrl_cmd_element cmd_##cmdname = { \
|
||||
.name = cmdstr, \
|
||||
@@ -150,6 +158,5 @@ struct ctrl_cmd_element cmd_##cmdname = { \
|
||||
}
|
||||
|
||||
struct gsm_network;
|
||||
int controlif_setup(struct gsm_network *gsmnet, uint16_t port);
|
||||
|
||||
#endif /* _CONTROL_CMD_H */
|
||||
|
||||
@@ -5,9 +5,17 @@
|
||||
#include <openbsc/control_cmd.h>
|
||||
#include <openbsc/gsm_data.h>
|
||||
|
||||
struct ctrl_handle {
|
||||
struct osmo_fd listen_fd;
|
||||
struct gsm_network *gsmnet;
|
||||
|
||||
/* List of control connections */
|
||||
struct llist_head ccon_list;
|
||||
};
|
||||
|
||||
int ctrl_cmd_send(struct osmo_wqueue *queue, struct ctrl_cmd *cmd);
|
||||
int ctrl_cmd_handle(struct ctrl_cmd *cmd, void *data);
|
||||
int controlif_setup(struct gsm_network *gsmnet, uint16_t port);
|
||||
struct ctrl_handle *controlif_setup(struct gsm_network *gsmnet, uint16_t port);
|
||||
|
||||
#endif /* _CONTROL_IF_H */
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@ struct gsm_subscriber *db_get_subscriber(struct gsm_network *net,
|
||||
enum gsm_subscriber_field field,
|
||||
const char *subscr);
|
||||
int db_sync_subscriber(struct gsm_subscriber *subscriber);
|
||||
int db_subscriber_expire(void *priv, void (*callback)(void *priv, long long unsigned int id));
|
||||
int db_subscriber_alloc_tmsi(struct gsm_subscriber *subscriber);
|
||||
int db_subscriber_alloc_exten(struct gsm_subscriber *subscriber);
|
||||
int db_subscriber_alloc_token(struct gsm_subscriber *subscriber, uint32_t* token);
|
||||
|
||||
@@ -16,7 +16,6 @@ enum {
|
||||
DRSL,
|
||||
DNM,
|
||||
DMNCC,
|
||||
DSMS,
|
||||
DPAG,
|
||||
DMEAS,
|
||||
DSCCP,
|
||||
@@ -32,6 +31,7 @@ enum {
|
||||
DSNDCP,
|
||||
DNAT,
|
||||
DCTRL,
|
||||
DSMPP,
|
||||
Debug_LastEntry,
|
||||
};
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ int gsm0411_rcv_sms(struct gsm_subscriber_connection *conn, struct msgb *msg);
|
||||
|
||||
struct gsm_sms *sms_alloc(void);
|
||||
void sms_free(struct gsm_sms *sms);
|
||||
struct gsm_sms *sms_from_text(struct gsm_subscriber *receiver, int dcs, const char *text);
|
||||
struct gsm_sms *sms_from_text(struct gsm_subscriber *receiver, struct gsm_subscriber *sender, int dcs, const char *text);
|
||||
|
||||
void _gsm411_sms_trans_free(struct gsm_trans *trans);
|
||||
int gsm411_send_sms_subscr(struct gsm_subscriber *subscr,
|
||||
|
||||
@@ -192,6 +192,7 @@ enum gsm_auth_policy {
|
||||
#define GSM_T3101_DEFAULT 10
|
||||
#define GSM_T3105_DEFAULT 40
|
||||
#define GSM_T3113_DEFAULT 60
|
||||
#define GSM_T3122_DEFAULT 10
|
||||
|
||||
struct gsm_network {
|
||||
/* global parameters */
|
||||
@@ -247,6 +248,9 @@ struct gsm_network {
|
||||
int T3122;
|
||||
int T3141;
|
||||
|
||||
/* timer to expire old location updates */
|
||||
struct osmo_timer_list subscr_expire_timer;
|
||||
|
||||
/* Radio Resource Location Protocol (TS 04.31) */
|
||||
struct {
|
||||
enum rrlp_mode mode;
|
||||
@@ -266,14 +270,42 @@ struct gsm_network {
|
||||
/* subscriber related features */
|
||||
int keep_subscr;
|
||||
struct gsm_sms_queue *sms_queue;
|
||||
|
||||
/* control interface */
|
||||
struct ctrl_handle *ctrl;
|
||||
};
|
||||
|
||||
struct osmo_esme;
|
||||
|
||||
enum gsm_sms_source_id {
|
||||
SMS_SOURCE_UNKNOWN = 0,
|
||||
SMS_SOURCE_MS, /* received from MS */
|
||||
SMS_SOURCE_VTY, /* received from VTY */
|
||||
SMS_SOURCE_SMPP, /* received via SMPP */
|
||||
};
|
||||
|
||||
#define SMS_HDR_SIZE 128
|
||||
#define SMS_TEXT_SIZE 256
|
||||
|
||||
struct gsm_sms_addr {
|
||||
uint8_t ton;
|
||||
uint8_t npi;
|
||||
char addr[21+1];
|
||||
};
|
||||
|
||||
struct gsm_sms {
|
||||
unsigned long long id;
|
||||
struct gsm_subscriber *sender;
|
||||
struct gsm_subscriber *receiver;
|
||||
struct gsm_sms_addr src, dst;
|
||||
enum gsm_sms_source_id source;
|
||||
|
||||
struct {
|
||||
struct osmo_esme *esme;
|
||||
uint32_t sequence_nr;
|
||||
int transaction_mode;
|
||||
char msg_id[16];
|
||||
} smpp;
|
||||
|
||||
unsigned long validity_minutes;
|
||||
uint8_t reply_path_req;
|
||||
@@ -282,8 +314,6 @@ struct gsm_sms {
|
||||
uint8_t protocol_id;
|
||||
uint8_t data_coding_scheme;
|
||||
uint8_t msg_ref;
|
||||
char dest_addr[20+1]; /* DA LV is 12 bytes max, i.e. 10 bytes
|
||||
* BCD == 20 bytes string */
|
||||
uint8_t user_data_len;
|
||||
uint8_t user_data[SMS_TEXT_SIZE];
|
||||
|
||||
@@ -308,10 +338,12 @@ struct gsm_bts *gsm_bts_by_lac(struct gsm_network *net, unsigned int lac,
|
||||
extern void *tall_bsc_ctx;
|
||||
extern int ipacc_rtp_direct;
|
||||
|
||||
/* this actaully refers to the IPA transport, not the BTS model */
|
||||
static inline int is_ipaccess_bts(struct gsm_bts *bts)
|
||||
{
|
||||
switch (bts->type) {
|
||||
case GSM_BTS_TYPE_NANOBTS:
|
||||
case GSM_BTS_TYPE_OSMO_SYSMO:
|
||||
return 1;
|
||||
default:
|
||||
break;
|
||||
@@ -363,4 +395,7 @@ struct gsm_bts_trx *gsm_bts_trx_by_nr(struct gsm_bts *bts, int nr);
|
||||
/* generic E1 line operations for all ISDN-based BTS. */
|
||||
extern struct e1inp_line_ops bts_isdn_e1inp_line_ops;
|
||||
|
||||
extern const struct value_string bts_type_names[_NUM_GSM_BTS_TYPE+1];
|
||||
extern const struct value_string bts_type_descs[_NUM_GSM_BTS_TYPE+1];
|
||||
|
||||
#endif /* _GSM_DATA_H */
|
||||
|
||||
@@ -19,6 +19,10 @@
|
||||
|
||||
#include <osmocom/abis/e1_input.h>
|
||||
|
||||
#ifndef ROLE_BSC
|
||||
#include <osmocom/gsm/lapdm.h>
|
||||
#endif
|
||||
|
||||
struct osmo_bsc_data;
|
||||
|
||||
struct osmo_bsc_sccp_con;
|
||||
@@ -116,6 +120,7 @@ enum gsm_lchan_state {
|
||||
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 */
|
||||
};
|
||||
|
||||
@@ -149,6 +154,27 @@ struct amr_multirate_conf {
|
||||
};
|
||||
/* /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;
|
||||
@@ -160,6 +186,7 @@ struct gsm_lchan {
|
||||
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;
|
||||
/* Power levels for MS and BTS */
|
||||
@@ -179,9 +206,6 @@ struct gsm_lchan {
|
||||
uint8_t sapis[8];
|
||||
int sacch_deact;
|
||||
|
||||
/** GSM 08.58 9.3.20 */
|
||||
int release_mode;
|
||||
|
||||
struct {
|
||||
uint32_t bound_ip;
|
||||
uint32_t connect_ip;
|
||||
@@ -202,9 +226,11 @@ struct gsm_lchan {
|
||||
|
||||
#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;
|
||||
uint8_t error_cause;
|
||||
|
||||
/* table of neighbor cell measurements */
|
||||
struct neigh_meas_proc neigh_meas[MAX_NEIGH_MEAS];
|
||||
@@ -218,6 +244,10 @@ struct gsm_lchan {
|
||||
|
||||
struct gsm_subscriber_connection *conn;
|
||||
#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. */
|
||||
uint8_t sapis_dl[23];
|
||||
uint8_t sapis_ul[23];
|
||||
struct lapdm_channel lapdm_ch;
|
||||
struct llist_head dl_tch_queue;
|
||||
struct {
|
||||
@@ -263,6 +293,8 @@ struct gsm_lchan {
|
||||
/* counts up to Ny1 */
|
||||
unsigned int phys_info_count;
|
||||
} ho;
|
||||
/* S counter for link loss */
|
||||
int s;
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -362,6 +394,8 @@ enum gsm_bts_type {
|
||||
GSM_BTS_TYPE_RBS2000,
|
||||
GSM_BTS_TYPE_HSL_FEMTO,
|
||||
GSM_BTS_TYPE_NOKIA_SITE,
|
||||
GSM_BTS_TYPE_OSMO_SYSMO,
|
||||
_NUM_GSM_BTS_TYPE
|
||||
};
|
||||
|
||||
struct vty;
|
||||
@@ -433,17 +467,81 @@ struct gsm_bts_gprs_nsvc {
|
||||
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 */
|
||||
@@ -492,9 +590,11 @@ struct gsm_bts {
|
||||
sysinfo_buf_t si_buf[_MAX_SYSINFO_TYPE];
|
||||
|
||||
/* TimeZone hours, mins, and bts specific */
|
||||
int tzhr;
|
||||
int tzmn;
|
||||
int tz_bts_specific;
|
||||
struct {
|
||||
int hr;
|
||||
int mn;
|
||||
int override;
|
||||
} tz;
|
||||
|
||||
/* ip.accesss Unit ID's have Site/BTS/TRX layout */
|
||||
union {
|
||||
@@ -502,6 +602,7 @@ struct gsm_bts {
|
||||
uint16_t site_id;
|
||||
uint16_t bts_id;
|
||||
uint32_t flags;
|
||||
uint32_t rsl_ip;
|
||||
} ip_access;
|
||||
struct {
|
||||
struct {
|
||||
@@ -553,6 +654,7 @@ struct gsm_bts {
|
||||
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;
|
||||
@@ -600,6 +702,9 @@ struct gsm_bts {
|
||||
|
||||
/* 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;
|
||||
#endif /* ROLE_BSC */
|
||||
void *role;
|
||||
};
|
||||
@@ -610,6 +715,10 @@ 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);
|
||||
|
||||
|
||||
const struct value_string gsm_pchant_names[10];
|
||||
const struct value_string gsm_pchant_descs[10];
|
||||
const struct value_string gsm_lchant_names[6];
|
||||
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);
|
||||
|
||||
@@ -38,6 +38,7 @@ struct gsm_subscriber {
|
||||
char name[GSM_NAME_LENGTH];
|
||||
char extension[GSM_EXTENSION_LENGTH];
|
||||
int authorized;
|
||||
time_t expire_lu;
|
||||
|
||||
/* Temporary field which is not stored in the DB/HLR */
|
||||
uint32_t flags;
|
||||
@@ -98,6 +99,7 @@ char *subscr_name(struct gsm_subscriber *subscr);
|
||||
|
||||
int subscr_purge_inactive(struct gsm_network *net);
|
||||
void subscr_update_from_db(struct gsm_subscriber *subscr);
|
||||
void subscr_expire(struct gsm_network *net);
|
||||
|
||||
/* internal */
|
||||
struct gsm_subscriber *subscr_alloc(void);
|
||||
|
||||
@@ -11,4 +11,7 @@ int bsc_handover_start(struct gsm_lchan *old_lchan, struct gsm_bts *bts);
|
||||
/* clear any operation for this connection */
|
||||
void bsc_clear_handover(struct gsm_subscriber_connection *conn, int free_lchan);
|
||||
|
||||
/* Return the old lchan or NULL. This is meant for audio handling */
|
||||
struct gsm_lchan *bsc_handover_pending(struct gsm_lchan *new_lchan);
|
||||
|
||||
#endif /* _HANDOVER_H */
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/* A Media Gateway Control Protocol Media Gateway: RFC 3435 */
|
||||
|
||||
/*
|
||||
* (C) 2009-2011 by Holger Hans Peter Freyther <zecke@selfish.org>
|
||||
* (C) 2009-2011 by On-Waves
|
||||
* (C) 2009-2012 by Holger Hans Peter Freyther <zecke@selfish.org>
|
||||
* (C) 2009-2012 by On-Waves
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -83,6 +83,7 @@ typedef int (*mgcp_realloc)(struct mgcp_trunk_config *cfg, int endpoint);
|
||||
typedef int (*mgcp_change)(struct mgcp_trunk_config *cfg, int endpoint, int state);
|
||||
typedef int (*mgcp_policy)(struct mgcp_trunk_config *cfg, int endpoint, int state, const char *transactio_id);
|
||||
typedef int (*mgcp_reset)(struct mgcp_trunk_config *cfg);
|
||||
typedef int (*mgcp_rqnt)(struct mgcp_endpoint *endp, char tone);
|
||||
|
||||
#define PORT_ALLOC_STATIC 0
|
||||
#define PORT_ALLOC_DYNAMIC 1
|
||||
@@ -110,6 +111,7 @@ struct mgcp_trunk_config {
|
||||
int trunk_nr;
|
||||
int trunk_type;
|
||||
|
||||
char *audio_fmtp_extra;
|
||||
char *audio_name;
|
||||
int audio_payload;
|
||||
int audio_loop;
|
||||
@@ -148,6 +150,7 @@ struct mgcp_config {
|
||||
mgcp_policy policy_cb;
|
||||
mgcp_reset reset_cb;
|
||||
mgcp_realloc realloc_cb;
|
||||
mgcp_rqnt rqnt_cb;
|
||||
void *data;
|
||||
|
||||
uint32_t last_call_id;
|
||||
@@ -168,12 +171,12 @@ int mgcp_vty_init(void);
|
||||
int mgcp_endpoints_allocate(struct mgcp_trunk_config *cfg);
|
||||
void mgcp_free_endp(struct mgcp_endpoint *endp);
|
||||
int mgcp_reset_transcoder(struct mgcp_config *cfg);
|
||||
void mgcp_format_stats(struct mgcp_endpoint *endp, char *stats, size_t size);
|
||||
|
||||
/*
|
||||
* format helper functions
|
||||
*/
|
||||
struct msgb *mgcp_handle_message(struct mgcp_config *cfg, struct msgb *msg);
|
||||
struct msgb *mgcp_create_response_with_data(int code, const char *txt, const char *msg, const char *trans, const char *data);
|
||||
|
||||
/* adc helper */
|
||||
static inline int mgcp_timeslot_to_endpoint(int multiplex, int timeslot)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/* MGCP Private Data */
|
||||
|
||||
/*
|
||||
* (C) 2009-2011 by Holger Hans Peter Freyther <zecke@selfish.org>
|
||||
* (C) 2009-2011 by On-Waves
|
||||
* (C) 2009-2012 by Holger Hans Peter Freyther <zecke@selfish.org>
|
||||
* (C) 2009-2012 by On-Waves
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -46,22 +46,30 @@ struct mgcp_rtp_state {
|
||||
|
||||
uint32_t orig_ssrc;
|
||||
uint32_t ssrc;
|
||||
uint16_t seq_no;
|
||||
int lost_no;
|
||||
|
||||
uint16_t base_seq;
|
||||
uint16_t max_seq;
|
||||
int seq_offset;
|
||||
int cycles;
|
||||
|
||||
uint32_t last_timestamp;
|
||||
int32_t timestamp_offset;
|
||||
uint32_t jitter;
|
||||
int32_t transit;
|
||||
};
|
||||
|
||||
struct mgcp_rtp_end {
|
||||
/* statistics */
|
||||
unsigned int packets;
|
||||
unsigned int octets;
|
||||
struct in_addr addr;
|
||||
|
||||
/* in network byte order */
|
||||
int rtp_port, rtcp_port;
|
||||
|
||||
/* per endpoint data */
|
||||
int payload_type;
|
||||
char *fmtp_extra;
|
||||
|
||||
/*
|
||||
* Each end has a socket...
|
||||
@@ -120,6 +128,10 @@ struct mgcp_endpoint {
|
||||
/* SSRC/seq/ts patching for loop */
|
||||
int allow_patch;
|
||||
|
||||
/* fields for re-transmission */
|
||||
char *last_trans;
|
||||
char *last_response;
|
||||
|
||||
/* tap for the endpoint */
|
||||
struct mgcp_rtp_tap taps[MGCP_TAP_COUNT];
|
||||
};
|
||||
@@ -147,5 +159,9 @@ static inline int endp_back_channel(int endpoint)
|
||||
struct mgcp_trunk_config *mgcp_trunk_alloc(struct mgcp_config *cfg, int index);
|
||||
struct mgcp_trunk_config *mgcp_trunk_num(struct mgcp_config *cfg, int index);
|
||||
|
||||
void mgcp_state_calc_loss(struct mgcp_rtp_state *s, struct mgcp_rtp_end *,
|
||||
uint32_t *expected, int *loss);
|
||||
uint32_t mgcp_state_calc_jitter(struct mgcp_rtp_state *);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
|
||||
#include "bsc_api.h"
|
||||
|
||||
#define BSS_SEND_USSD 1
|
||||
|
||||
struct sccp_connection;
|
||||
struct osmo_msc_data;
|
||||
struct bsc_msc_connection;
|
||||
@@ -32,14 +34,18 @@ struct bsc_api *osmo_bsc_api();
|
||||
|
||||
int bsc_queue_for_msc(struct osmo_bsc_sccp_con *conn, struct msgb *msg);
|
||||
int bsc_open_connection(struct osmo_bsc_sccp_con *sccp, struct msgb *msg);
|
||||
int bsc_create_new_connection(struct gsm_subscriber_connection *conn);
|
||||
int bsc_create_new_connection(struct gsm_subscriber_connection *conn,
|
||||
struct osmo_msc_data *msc);
|
||||
int bsc_delete_connection(struct osmo_bsc_sccp_con *sccp);
|
||||
|
||||
struct osmo_msc_data *bsc_find_msc(struct gsm_subscriber_connection *conn, struct msgb *);
|
||||
int bsc_scan_bts_msg(struct gsm_subscriber_connection *conn, struct msgb *msg);
|
||||
int bsc_scan_msc_msg(struct gsm_subscriber_connection *conn, struct msgb *msg);
|
||||
int bsc_send_welcome_ussd(struct gsm_subscriber_connection *conn);
|
||||
|
||||
int bsc_handle_udt(struct gsm_network *net, struct bsc_msc_connection *conn, struct msgb *msg, unsigned int length);
|
||||
int bsc_handle_udt(struct osmo_msc_data *msc, struct msgb *msg, unsigned int length);
|
||||
int bsc_handle_dt1(struct osmo_bsc_sccp_con *conn, struct msgb *msg, unsigned int len);
|
||||
|
||||
int bsc_ctrl_cmds_install();
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
|
||||
* (C) 2010 by On-Waves
|
||||
* (C) 2010-2013 by Holger Hans Peter Freyther <zecke@selfish.org>
|
||||
* (C) 2010-2013 by On-Waves
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -23,6 +23,9 @@
|
||||
|
||||
#include "gsm_data.h"
|
||||
|
||||
int bsc_grace_allow_new_connection(struct gsm_network *network);
|
||||
struct osmo_msc_data;
|
||||
|
||||
int bsc_grace_allow_new_connection(struct gsm_network *net, struct gsm_bts *bts);
|
||||
int bsc_grace_paging_request(struct gsm_subscriber *sub, int type, struct osmo_msc_data *msc);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,9 +1,28 @@
|
||||
#ifndef OSMO_BSC_RF
|
||||
#define OSMO_BSC_RF
|
||||
|
||||
#include <openbsc/gsm_data.h>
|
||||
#include <osmocom/core/write_queue.h>
|
||||
#include <osmocom/core/timer.h>
|
||||
|
||||
enum osmo_bsc_rf_opstate {
|
||||
OSMO_BSC_RF_OPSTATE_INOPERATIONAL,
|
||||
OSMO_BSC_RF_OPSTATE_OPERATIONAL,
|
||||
};
|
||||
|
||||
enum osmo_bsc_rf_adminstate {
|
||||
OSMO_BSC_RF_ADMINSTATE_UNLOCKED,
|
||||
OSMO_BSC_RF_ADMINSTATE_LOCKED,
|
||||
};
|
||||
|
||||
enum osmo_bsc_rf_policy {
|
||||
OSMO_BSC_RF_POLICY_OFF,
|
||||
OSMO_BSC_RF_POLICY_ON,
|
||||
OSMO_BSC_RF_POLICY_GRACE,
|
||||
OSMO_BSC_RF_POLICY_UNKNOWN,
|
||||
};
|
||||
|
||||
|
||||
struct gsm_network;
|
||||
|
||||
struct osmo_bsc_rf {
|
||||
@@ -23,6 +42,9 @@ struct osmo_bsc_rf {
|
||||
|
||||
/* some handling for the automatic grace switch */
|
||||
struct osmo_timer_list grace_timeout;
|
||||
|
||||
/* auto RF switch-off due lack of MSC connection */
|
||||
struct osmo_timer_list auto_off_timer;
|
||||
};
|
||||
|
||||
struct osmo_bsc_rf_conn {
|
||||
@@ -30,6 +52,13 @@ struct osmo_bsc_rf_conn {
|
||||
struct osmo_bsc_rf *rf;
|
||||
};
|
||||
|
||||
const char *osmo_bsc_rf_get_opstate_name(enum osmo_bsc_rf_opstate opstate);
|
||||
const char *osmo_bsc_rf_get_adminstate_name(enum osmo_bsc_rf_adminstate adminstate);
|
||||
const char *osmo_bsc_rf_get_policy_name(enum osmo_bsc_rf_policy policy);
|
||||
enum osmo_bsc_rf_opstate osmo_bsc_rf_get_opstate_by_bts(struct gsm_bts *bts);
|
||||
enum osmo_bsc_rf_adminstate osmo_bsc_rf_get_adminstate_by_bts(struct gsm_bts *bts);
|
||||
enum osmo_bsc_rf_policy osmo_bsc_rf_get_policy_by_bts(struct gsm_bts *bts);
|
||||
struct osmo_bsc_rf *osmo_bsc_rf_create(const char *path, struct gsm_network *net);
|
||||
void osmo_bsc_rf_schedule_lock(struct osmo_bsc_rf *rf, char cmd);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -26,6 +26,9 @@
|
||||
#include "bsc_msc.h"
|
||||
|
||||
#include <osmocom/core/timer.h>
|
||||
#include <osmocom/gsm/protocol/gsm_04_08.h>
|
||||
|
||||
#include <regex.h>
|
||||
|
||||
struct osmo_bsc_rf;
|
||||
struct gsm_network;
|
||||
@@ -35,12 +38,25 @@ struct gsm_audio_support {
|
||||
ver : 7;
|
||||
};
|
||||
|
||||
enum {
|
||||
MSC_CON_TYPE_NORMAL,
|
||||
MSC_CON_TYPE_LOCAL,
|
||||
};
|
||||
|
||||
struct osmo_msc_data {
|
||||
struct llist_head entry;
|
||||
|
||||
/* Back pointer */
|
||||
struct gsm_network *network;
|
||||
|
||||
int allow_emerg;
|
||||
int type;
|
||||
|
||||
/* local call routing */
|
||||
char *local_pref;
|
||||
regex_t local_pref_reg;
|
||||
|
||||
|
||||
/* Connection data */
|
||||
char *bsc_token;
|
||||
int ping_timeout;
|
||||
@@ -53,6 +69,7 @@ struct osmo_msc_data {
|
||||
int rtp_base;
|
||||
|
||||
/* audio codecs */
|
||||
struct gsm48_multi_rate_conf amr_conf;
|
||||
struct gsm_audio_support **audio_support;
|
||||
int audio_length;
|
||||
|
||||
@@ -82,6 +99,7 @@ struct osmo_bsc_data {
|
||||
int mid_call_timeout;
|
||||
char *rf_ctrl_name;
|
||||
struct osmo_bsc_rf *rf_ctrl;
|
||||
int auto_off_timeout;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -56,6 +56,8 @@ struct gsm_paging_request {
|
||||
/* schedule paging request */
|
||||
int paging_request(struct gsm_network *network, struct gsm_subscriber *subscr,
|
||||
int type, gsm_cbfn *cbfn, void *data);
|
||||
int paging_request_bts(struct gsm_bts *bts, struct gsm_subscriber *subscr,
|
||||
int type, gsm_cbfn *cbfn, void *data);
|
||||
|
||||
/* stop paging requests */
|
||||
void paging_request_stop(struct gsm_bts *bts, struct gsm_subscriber *subscr,
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include <openbsc/gsm_04_08.h>
|
||||
|
||||
/* generate SI1 rest octets */
|
||||
int rest_octets_si1(uint8_t *data, uint8_t *nch_pos);
|
||||
int rest_octets_si1(uint8_t *data, uint8_t *nch_pos, int is1800_net);
|
||||
|
||||
struct gsm48_si_selection_params {
|
||||
uint16_t penalty_time:5,
|
||||
|
||||
@@ -185,6 +185,7 @@ struct nm_om2k_signal_data {
|
||||
|
||||
struct nm_nack_signal_data {
|
||||
struct msgb *msg;
|
||||
struct gsm_bts *bts;
|
||||
uint8_t mt;
|
||||
};
|
||||
|
||||
@@ -218,6 +219,7 @@ struct lchan_signal_data {
|
||||
enum signal_msc {
|
||||
S_MSC_LOST,
|
||||
S_MSC_CONNECTED,
|
||||
S_MSC_AUTHENTICATED,
|
||||
};
|
||||
|
||||
struct osmo_msc_data;
|
||||
@@ -225,16 +227,6 @@ struct msc_signal_data {
|
||||
struct osmo_msc_data *data;
|
||||
};
|
||||
|
||||
/* handover */
|
||||
enum signal_ho {
|
||||
S_HANDOVER_ACK,
|
||||
};
|
||||
|
||||
struct ho_signal_data {
|
||||
struct gsm_lchan *old_lchan;
|
||||
struct gsm_lchan *new_lchan;
|
||||
};
|
||||
|
||||
/* SS_CCCH signals */
|
||||
enum signal_ccch {
|
||||
S_CCCH_PAGING_LOAD,
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
#include <osmocom/core/linuxlist.h>
|
||||
#include <openbsc/gsm_04_11.h>
|
||||
#include <openbsc/mncc.h>
|
||||
#include <osmocom/gsm/gsm0411_smc.h>
|
||||
#include <osmocom/gsm/gsm0411_smr.h>
|
||||
|
||||
/* One transaction */
|
||||
struct gsm_trans {
|
||||
@@ -46,12 +48,8 @@ struct gsm_trans {
|
||||
struct gsm_mncc msg; /* stores setup/disconnect/release message */
|
||||
} cc;
|
||||
struct {
|
||||
uint8_t link_id; /* RSL Link ID to be used for this trans */
|
||||
int is_mt; /* is this a MO (0) or MT (1) transfer */
|
||||
enum gsm411_cp_state cp_state;
|
||||
struct osmo_timer_list cp_timer;
|
||||
|
||||
enum gsm411_rp_state rp_state;
|
||||
struct gsm411_smc_inst smc_inst;
|
||||
struct gsm411_smr_inst smr_inst;
|
||||
|
||||
struct gsm_sms *sms;
|
||||
} sms;
|
||||
@@ -72,5 +70,6 @@ void trans_free(struct gsm_trans *trans);
|
||||
|
||||
int trans_assign_trans_id(struct gsm_subscriber *subscr,
|
||||
uint8_t protocol, uint8_t ti_flag);
|
||||
int trans_has_conn(const struct gsm_subscriber_connection *conn);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -34,6 +34,9 @@ enum bsc_vty_node {
|
||||
TRUNK_NODE,
|
||||
PGROUP_NODE,
|
||||
MNCC_INT_NODE,
|
||||
BSC_NODE,
|
||||
SMPP_NODE,
|
||||
SMPP_ESME_NODE,
|
||||
};
|
||||
|
||||
extern int bsc_vty_is_config_node(struct vty *vty, int node);
|
||||
|
||||
@@ -1,194 +0,0 @@
|
||||
/* C-Implementation of the Algorithm described in Appendix J of GSM TS 44.018,
|
||||
* (C) 2009 by Dirk Hakkesteegt <dirk@hakkesteegt.org>
|
||||
*
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
/* Annex J.3 indicates that at least in one BA list, we can never have more
|
||||
* than 29 frequencies within the 16byte limit */
|
||||
#define MAX_ARRFCNS 29
|
||||
|
||||
/*****************************************************************************
|
||||
* NAME : smod
|
||||
* DESCRIPTION : n smod m indicates the offset remainder of the euclidian
|
||||
* division of n by m
|
||||
* INPUT : n, m
|
||||
* OUTPUT : n smod m
|
||||
* RETURNS :
|
||||
* Errorcodes :
|
||||
******************************************************************************/
|
||||
static int smod(int n, int m)
|
||||
{
|
||||
int result = n % m;
|
||||
if (result < 0)
|
||||
result += m;
|
||||
|
||||
if (result == 0)
|
||||
result = m;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* NAME : mod
|
||||
* DESCRIPTION : n mod m indicates the remainder of the euclidian division of
|
||||
* n by m
|
||||
* INPUT : n, m
|
||||
* OUTPUT : n mod m
|
||||
* RETURNS :
|
||||
* Errorcodes :
|
||||
******************************************************************************/
|
||||
static int mod(int n, int m)
|
||||
{
|
||||
int result = n % m;
|
||||
if (result < 0)
|
||||
result += m;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* NAME : greatest_power_of_2_le_to
|
||||
* DESCRIPTION : Calculates the greatest power of 2 that is lesser or equal
|
||||
* to the input value;
|
||||
* INPUT :
|
||||
* OUTPUT :
|
||||
* RETURNS :
|
||||
* Errorcodes :
|
||||
******************************************************************************/
|
||||
static int greatest_power_of_2_le_to(int input)
|
||||
{
|
||||
int check_val = 1;
|
||||
while (check_val <= input)
|
||||
check_val *= 2;
|
||||
|
||||
return check_val / 2;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* NAME : ENCODE_SUBTREE
|
||||
* DESCRIPTION : Recursive encoding routine based on 3GPP TS44.018 Annex J.4
|
||||
* INPUT : index: current position in the W list
|
||||
* set: the array to be encoded
|
||||
* range: the current range
|
||||
* set_size: number of elements in set
|
||||
* OUTPUT : W: the array of results
|
||||
* RETURNS :
|
||||
* Errorcodes :
|
||||
******************************************************************************/
|
||||
static void encode_subtree(int index, int *set, int range, int set_size, int *W)
|
||||
{
|
||||
int index_in_set = 0;
|
||||
int N, J, I, x;
|
||||
int subset[18];
|
||||
int subset_index, origin_value;
|
||||
|
||||
/* Check if this is a leaf */
|
||||
if (set_size == 0) {
|
||||
W[index] = 0;
|
||||
return;
|
||||
} else {
|
||||
if (set_size == 1) {
|
||||
W[index] = 1 + set[1];
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (I = 1; I <= set_size; I++) {
|
||||
N = 0;
|
||||
for (J = 1; J <= set_size; J++) {
|
||||
x = set[J] - set[I];
|
||||
x = mod(x, range);
|
||||
if (x <= (range-1)/2)
|
||||
N++;
|
||||
}
|
||||
if (N-1 == (set_size-1) / 2) {
|
||||
index_in_set = I;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
W[index] = set[index_in_set] + 1;
|
||||
|
||||
/* Left subset */
|
||||
subset[0] = 0;
|
||||
origin_value = mod((set[index_in_set] + (range-1) / 2 + 1), range);
|
||||
subset_index = 1;
|
||||
for (I = 1; I <= set_size; I++) {
|
||||
if (mod((set[I]-origin_value), range) < range/2) {
|
||||
subset[subset_index] = mod((set[I] - origin_value), range);
|
||||
subset_index++;
|
||||
subset[subset_index] = 0;
|
||||
}
|
||||
}
|
||||
encode_subtree(index + greatest_power_of_2_le_to(index),
|
||||
subset, range / 2, subset_index-1, W);
|
||||
|
||||
/* Right subset */
|
||||
subset[0] = 0;
|
||||
origin_value = mod((set[index_in_set] + 1), range);
|
||||
subset_index=1;
|
||||
for (I = 1; I<= set_size; I++) {
|
||||
if (mod((set[I]-origin_value), range) < range/2) {
|
||||
subset[subset_index] = mod((set[I] - origin_value), range);
|
||||
subset_index++;
|
||||
subset[subset_index] = 0;
|
||||
}
|
||||
}
|
||||
encode_subtree(index + 2*greatest_power_of_2_le_to(index),
|
||||
subset, (range-1)/2, subset_index-1, W);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* NAME : CalcARFCN
|
||||
* DESCRIPTION : Calculate the ARFCN list
|
||||
* INPUT : F: the list of input frequencies. MUST BE SORTED!
|
||||
* count: the number of elements in the F list
|
||||
* range: the encoding range (default: range 512)
|
||||
* OUTPUT : W: the list of W values
|
||||
* RETURNS :
|
||||
* Errorcodes :
|
||||
******************************************************************************/
|
||||
static void CalcARFCN(const unsigned int *F, int *W, unsigned int count, unsigned int range)
|
||||
{
|
||||
int i;
|
||||
int Fd[MAX_ARFCNS+1];
|
||||
|
||||
W[0] = F[0];
|
||||
for (i = 1; i < count; i++) {
|
||||
Fd[i] = F[i] - F[0] - 1;
|
||||
}
|
||||
encode_subtree(1, Fd, range-1, count-1, W);
|
||||
}
|
||||
|
||||
int bitvec2arfcn_list_range(uint8_t *range, struct bitvec *bv, uint16_t range)
|
||||
{
|
||||
unsigned int i, idx = 0;
|
||||
int F[MAX_ARFCNS+1];
|
||||
int W[MAX_ARFCNS+1];
|
||||
|
||||
/* build an array of integers from the bitmask */
|
||||
for (i = 0; i < bv->data_len*8; i++) {
|
||||
if (bitvec_get_bit_pos(bv, i))
|
||||
F[idx++] = i;
|
||||
}
|
||||
/* Perform the actual algorithm to calculate the 'W' values */
|
||||
CalcARFCN(F, W, idx, range);
|
||||
|
||||
/* FIXME: Encode the 'W' values into the actual format as used in 04.08 */
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
@@ -306,7 +306,7 @@ static int gbprox_rx_sig_from_bss(struct msgb *msg, struct gprs_nsvc *nsvc,
|
||||
* don't want the SGSN to reset, as the signalling endpoint
|
||||
* is common for all point-to-point BVCs (and thus all BTS) */
|
||||
if (TLVP_PRESENT(&tp, BSSGP_IE_BVCI)) {
|
||||
uint16_t bvci = ntohs(*(uint16_t *)TLVP_VAL(&tp, BSSGP_IE_BVCI));
|
||||
uint16_t bvci = ntohs(tlvp_val16_unal(&tp, BSSGP_IE_BVCI));
|
||||
LOGP(DGPRS, LOGL_INFO, "NSEI=%u Rx BVC RESET (BVCI=%u)\n",
|
||||
nsvc->nsei, bvci);
|
||||
if (bvci == 0) {
|
||||
@@ -367,7 +367,7 @@ static int gbprox_rx_paging(struct msgb *msg, struct tlv_parsed *tp,
|
||||
LOGP(DGPRS, LOGL_INFO, "NSEI=%u(SGSN) BSSGP PAGING ",
|
||||
nsvc->nsei);
|
||||
if (TLVP_PRESENT(tp, BSSGP_IE_BVCI)) {
|
||||
uint16_t bvci = ntohs(*(uint16_t *)TLVP_VAL(tp, BSSGP_IE_BVCI));
|
||||
uint16_t bvci = ntohs(tlvp_val16_unal(tp, BSSGP_IE_BVCI));
|
||||
LOGPC(DGPRS, LOGL_INFO, "routing by BVCI to peer BVCI=%u\n",
|
||||
bvci);
|
||||
} else if (TLVP_PRESENT(tp, BSSGP_IE_ROUTEING_AREA)) {
|
||||
@@ -400,7 +400,7 @@ static int rx_reset_from_sgsn(struct msgb *msg, struct tlv_parsed *tp,
|
||||
return bssgp_tx_status(BSSGP_CAUSE_MISSING_MAND_IE,
|
||||
NULL, msg);
|
||||
}
|
||||
ptp_bvci = ntohs(*(uint16_t *)TLVP_VAL(tp, BSSGP_IE_BVCI));
|
||||
ptp_bvci = ntohs(tlvp_val16_unal(tp, BSSGP_IE_BVCI));
|
||||
|
||||
if (ptp_bvci >= 2) {
|
||||
/* A reset for a PTP BVC was received, forward it to its
|
||||
@@ -464,7 +464,7 @@ static int gbprox_rx_sig_from_sgsn(struct msgb *msg, struct gprs_nsvc *nsvc,
|
||||
/* simple case: BVCI IE is mandatory */
|
||||
if (!TLVP_PRESENT(&tp, BSSGP_IE_BVCI))
|
||||
goto err_mand_ie;
|
||||
bvci = ntohs(*(uint16_t *)TLVP_VAL(&tp, BSSGP_IE_BVCI));
|
||||
bvci = ntohs(tlvp_val16_unal(&tp, BSSGP_IE_BVCI));
|
||||
rc = gbprox_relay2bvci(msg, bvci, ns_bvci);
|
||||
break;
|
||||
case BSSGP_PDUT_PAGING_PS:
|
||||
@@ -484,10 +484,9 @@ static int gbprox_rx_sig_from_sgsn(struct msgb *msg, struct gprs_nsvc *nsvc,
|
||||
"cause=0x%02x(%s) ", *TLVP_VAL(&tp, BSSGP_IE_CAUSE),
|
||||
bssgp_cause_str(*TLVP_VAL(&tp, BSSGP_IE_CAUSE)));
|
||||
if (TLVP_PRESENT(&tp, BSSGP_IE_BVCI)) {
|
||||
uint16_t *bvci = (uint16_t *)
|
||||
TLVP_VAL(&tp, BSSGP_IE_BVCI);
|
||||
uint16_t bvci = tlvp_val16_unal(&tp, BSSGP_IE_BVCI);
|
||||
LOGPC(DGPRS, LOGL_NOTICE,
|
||||
"BVCI=%u\n", ntohs(*bvci));
|
||||
"BVCI=%u\n", ntohs(bvci));
|
||||
} else
|
||||
LOGPC(DGPRS, LOGL_NOTICE, "\n");
|
||||
break;
|
||||
@@ -508,7 +507,7 @@ static int gbprox_rx_sig_from_sgsn(struct msgb *msg, struct gprs_nsvc *nsvc,
|
||||
case BSSGP_PDUT_BVC_UNBLOCK_ACK:
|
||||
if (!TLVP_PRESENT(&tp, BSSGP_IE_BVCI))
|
||||
goto err_mand_ie;
|
||||
bvci = ntohs(*(uint16_t *)TLVP_VAL(&tp, BSSGP_IE_BVCI));
|
||||
bvci = ntohs(tlvp_val16_unal(&tp, BSSGP_IE_BVCI));
|
||||
if (bvci == 0) {
|
||||
LOGP(DGPRS, LOGL_NOTICE, "NSEI=%u(SGSN) BSSGP "
|
||||
"%sBLOCK_ACK for signalling BVCI ?!?\n", nsvc->nsei,
|
||||
|
||||
@@ -40,7 +40,7 @@ static struct gbproxy_config *g_cfg = NULL;
|
||||
*/
|
||||
static struct cmd_node gbproxy_node = {
|
||||
GBPROXY_NODE,
|
||||
"%s(gbproxy)#",
|
||||
"%s(config-gbproxy)# ",
|
||||
1,
|
||||
};
|
||||
|
||||
|
||||
@@ -604,6 +604,9 @@ static int gsm48_rx_gmm_id_resp(struct sgsn_mm_ctx *ctx, struct msgb *msg)
|
||||
ictx->p_tmsi, ctx->p_tmsi);
|
||||
gprs_llgmm_assign(ictx->llme, ictx->tlli,
|
||||
0xffffffff, GPRS_ALGO_GEA0, NULL);
|
||||
/* FIXME: this is a hard free, we don't
|
||||
* clean-up any PDP contexts on the
|
||||
* libgtp side */
|
||||
sgsn_mm_ctx_free(ictx);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,11 +43,16 @@ static int _bssgp_tx_dl_ud(struct msgb *msg, struct sgsn_mm_ctx *mmctx)
|
||||
struct bssgp_dl_ud_par dup;
|
||||
const uint8_t qos_profile_default[3] = { 0x00, 0x00, 0x20 };
|
||||
|
||||
dup.tlli = NULL;
|
||||
dup.imsi = mmctx->imsi;
|
||||
dup.drx_parms = mmctx->drx_parms;
|
||||
dup.ms_ra_cap.len = mmctx->ms_radio_access_capa.len;
|
||||
dup.ms_ra_cap.v = mmctx->ms_radio_access_capa.buf;
|
||||
memset(&dup, 0, sizeof(dup));
|
||||
/* before we have received some identity from the MS, we might
|
||||
* not yet have a MMC context (e.g. XID negotiation of primarly
|
||||
* LLC connection fro GMM sapi). */
|
||||
if (mmctx) {
|
||||
dup.imsi = mmctx->imsi;
|
||||
dup.drx_parms = mmctx->drx_parms;
|
||||
dup.ms_ra_cap.len = mmctx->ms_radio_access_capa.len;
|
||||
dup.ms_ra_cap.v = mmctx->ms_radio_access_capa.buf;
|
||||
}
|
||||
memcpy(&dup.qos_profile, qos_profile_default,
|
||||
sizeof(qos_profile_default));
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <osmocom/core/talloc.h>
|
||||
#include <osmocom/core/timer.h>
|
||||
#include <osmocom/core/rate_ctr.h>
|
||||
#include <osmocom/core/backtrace.h>
|
||||
#include <osmocom/gprs/gprs_ns.h>
|
||||
#include <osmocom/gprs/gprs_bssgp.h>
|
||||
|
||||
@@ -173,6 +174,8 @@ struct sgsn_mm_ctx *sgsn_mm_ctx_alloc(uint32_t tlli,
|
||||
return ctx;
|
||||
}
|
||||
|
||||
/* this is a hard _free_ function, it doesn't clean up the PDP contexts
|
||||
* in libgtp! */
|
||||
void sgsn_mm_ctx_free(struct sgsn_mm_ctx *mm)
|
||||
{
|
||||
struct sgsn_pdp_ctx *pdp, *pdp2;
|
||||
@@ -215,6 +218,7 @@ struct sgsn_pdp_ctx *sgsn_pdp_ctx_by_tid(const struct sgsn_mm_ctx *mm,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* you don't want to use this directly, call sgsn_create_pdp_ctx() */
|
||||
struct sgsn_pdp_ctx *sgsn_pdp_ctx_alloc(struct sgsn_mm_ctx *mm,
|
||||
uint8_t nsapi)
|
||||
{
|
||||
@@ -237,11 +241,26 @@ struct sgsn_pdp_ctx *sgsn_pdp_ctx_alloc(struct sgsn_mm_ctx *mm,
|
||||
return pdp;
|
||||
}
|
||||
|
||||
#include <pdp.h>
|
||||
/* you probably want to call sgsn_delete_pdp_ctx() instead */
|
||||
void sgsn_pdp_ctx_free(struct sgsn_pdp_ctx *pdp)
|
||||
{
|
||||
rate_ctr_group_free(pdp->ctrg);
|
||||
llist_del(&pdp->list);
|
||||
llist_del(&pdp->g_list);
|
||||
|
||||
/* _if_ we still have a library handle, at least set it to NULL
|
||||
* to avoid any dereferences of the now-deleted PDP context from
|
||||
* sgsn_libgtp:cb_data_ind() */
|
||||
if (pdp->lib) {
|
||||
struct pdp_t *lib = pdp->lib;
|
||||
LOGP(DGPRS, LOGL_NOTICE, "freeing PDP context that still "
|
||||
"has a libgtp handle attached to it, this shouldn't "
|
||||
"happen!\n");
|
||||
osmo_generate_backtrace();
|
||||
lib->priv = NULL;
|
||||
}
|
||||
|
||||
talloc_free(pdp);
|
||||
}
|
||||
|
||||
@@ -359,6 +378,7 @@ static void drop_one_pdp(struct sgsn_pdp_ctx *pdp)
|
||||
/* FIXME: GPRS paging in case MS is SUSPENDED */
|
||||
LOGP(DGPRS, LOGL_NOTICE, "Hard-dropping PDP ctx due to GGSN "
|
||||
"recovery\n");
|
||||
/* FIXME: how to tell this to libgtp? */
|
||||
sgsn_pdp_ctx_free(pdp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -317,6 +317,10 @@ static int delete_pdp_conf(struct pdp_t *pdp, void *cbp, int cause)
|
||||
/* Confirm deactivation of PDP context to MS */
|
||||
rc = gsm48_tx_gsm_deact_pdp_acc(pctx);
|
||||
|
||||
/* unlink the now non-existing library handle from the pdp
|
||||
* context */
|
||||
pctx->lib = NULL;
|
||||
|
||||
sgsn_pdp_ctx_free(pctx);
|
||||
|
||||
return rc;
|
||||
@@ -422,10 +426,16 @@ static int cb_data_ind(struct pdp_t *lib, void *packet, unsigned int len)
|
||||
|
||||
pdp = lib->priv;
|
||||
if (!pdp) {
|
||||
DEBUGP(DGPRS, "GTP DATA IND from GGSN for unknown PDP\n");
|
||||
LOGP(DGPRS, LOGL_NOTICE,
|
||||
"GTP DATA IND from GGSN for unknown PDP\n");
|
||||
return -EIO;
|
||||
}
|
||||
mm = pdp->mm;
|
||||
if (!mm) {
|
||||
LOGP(DGPRS, LOGL_ERROR,
|
||||
"PDP context (imsi=%s) without MM context!\n", mm->imsi);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
msg = msgb_alloc_headroom(len+256, 128, "GTP->SNDCP");
|
||||
ud = msgb_put(msg, len);
|
||||
|
||||
@@ -119,7 +119,7 @@ int bssgp_prim_cb(struct osmo_prim_hdr *oph, void *ctx)
|
||||
return gprs_gmm_rx_suspend(bp->ra_id, bp->tlli);
|
||||
case PRIM_BSSGP_GMM_RESUME:
|
||||
return gprs_gmm_rx_resume(bp->ra_id, bp->tlli,
|
||||
*bp->u.resume.suspend_ref);
|
||||
bp->u.resume.suspend_ref);
|
||||
}
|
||||
break;
|
||||
case SAP_BSSGP_NM:
|
||||
@@ -235,12 +235,6 @@ static struct log_info_cat gprs_categories[] = {
|
||||
.color = "\033[1;33m",
|
||||
.enabled = 1, .loglevel = LOGL_NOTICE,
|
||||
},
|
||||
[DSMS] = {
|
||||
.name = "DSMS",
|
||||
.description = "Layer3 Short Message Service (SMS)",
|
||||
.color = "\033[1;37m",
|
||||
.enabled = 1, .loglevel = LOGL_NOTICE,
|
||||
},
|
||||
[DPAG] = {
|
||||
.name = "DPAG",
|
||||
.description = "Paging Subsystem",
|
||||
|
||||
@@ -106,7 +106,7 @@ static char *gprs_pdpaddr2str(uint8_t *pdpa, uint8_t len)
|
||||
|
||||
static struct cmd_node sgsn_node = {
|
||||
SGSN_NODE,
|
||||
"%s(sgsn)#",
|
||||
"%s(config-sgsn)# ",
|
||||
1,
|
||||
};
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ libbsc_a_SOURCES = abis_nm.c abis_nm_vty.c \
|
||||
bts_nokia_site.c \
|
||||
bts_hsl_femtocell.c \
|
||||
bts_unknown.c \
|
||||
bts_sysmobts.c \
|
||||
chan_alloc.c \
|
||||
gsm_subscriber_base.c \
|
||||
handover_decision.c handover_logic.c meas_rep.c \
|
||||
@@ -21,5 +22,6 @@ libbsc_a_SOURCES = abis_nm.c abis_nm_vty.c \
|
||||
e1_config.c \
|
||||
bsc_api.c bsc_msc.c bsc_vty.c \
|
||||
gsm_04_08_utils.c \
|
||||
bsc_init.c bts_init.c bsc_rf_ctrl.c
|
||||
bsc_init.c bts_init.c bsc_rf_ctrl.c \
|
||||
arfcn_range_encode.c
|
||||
|
||||
|
||||
@@ -359,7 +359,8 @@ static int ipacc_sw_activate(struct gsm_bts *bts, uint8_t obj_class, uint8_t i0,
|
||||
return abis_nm_sendmsg(bts, msg);
|
||||
}
|
||||
|
||||
static int abis_nm_parse_sw_descr(const uint8_t *sw_descr, int sw_descr_len)
|
||||
int abis_nm_parse_sw_config(const uint8_t *sw_descr, const size_t sw_descr_len,
|
||||
struct abis_nm_sw_descr *desc, const int res_len)
|
||||
{
|
||||
static const struct tlv_definition sw_descr_def = {
|
||||
.def = {
|
||||
@@ -368,38 +369,72 @@ static int abis_nm_parse_sw_descr(const uint8_t *sw_descr, int sw_descr_len)
|
||||
},
|
||||
};
|
||||
|
||||
uint8_t tag;
|
||||
uint16_t tag_len;
|
||||
const uint8_t *val;
|
||||
int ofs = 0, len;
|
||||
size_t pos = 0;
|
||||
int desc_pos = 0;
|
||||
|
||||
/* Classic TLV parsing doesn't work well with SW_DESCR because of it's
|
||||
* nested nature and the fact you have to assume it contains only two sub
|
||||
* tags NM_ATT_FILE_VERSION & NM_ATT_FILE_ID to parse it */
|
||||
for (pos = 0; pos < sw_descr_len && desc_pos < res_len; ++desc_pos) {
|
||||
uint8_t tag;
|
||||
uint16_t tag_len;
|
||||
const uint8_t *val;
|
||||
int len;
|
||||
|
||||
if (sw_descr[0] != NM_ATT_SW_DESCR) {
|
||||
DEBUGP(DNM, "SW_DESCR attribute identifier not found!\n");
|
||||
return -1;
|
||||
memset(&desc[desc_pos], 0, sizeof(desc[desc_pos]));
|
||||
desc[desc_pos].start = &sw_descr[pos];
|
||||
|
||||
/* Classic TLV parsing doesn't work well with SW_DESCR because of it's
|
||||
* nested nature and the fact you have to assume it contains only two sub
|
||||
* tags NM_ATT_FILE_VERSION & NM_ATT_FILE_ID to parse it */
|
||||
if (sw_descr[pos] != NM_ATT_SW_DESCR) {
|
||||
LOGP(DNM, LOGL_ERROR,
|
||||
"SW_DESCR attribute identifier not found!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
pos += 1;
|
||||
len = tlv_parse_one(&tag, &tag_len, &val,
|
||||
&sw_descr_def, &sw_descr[pos], sw_descr_len - pos);
|
||||
if (len < 0 || (tag != NM_ATT_FILE_ID)) {
|
||||
LOGP(DNM, LOGL_ERROR,
|
||||
"FILE_ID attribute identifier not found!\n");
|
||||
return -2;
|
||||
}
|
||||
desc[desc_pos].file_id = val;
|
||||
desc[desc_pos].file_id_len = tag_len;
|
||||
pos += len;
|
||||
|
||||
|
||||
len = tlv_parse_one(&tag, &tag_len, &val,
|
||||
&sw_descr_def, &sw_descr[pos], sw_descr_len - pos);
|
||||
if (len < 0 || (tag != NM_ATT_FILE_VERSION)) {
|
||||
LOGP(DNM, LOGL_ERROR,
|
||||
"FILE_VERSION attribute identifier not found!\n");
|
||||
return -3;
|
||||
}
|
||||
desc[desc_pos].file_ver = val;
|
||||
desc[desc_pos].file_ver_len = tag_len;
|
||||
pos += len;
|
||||
|
||||
/* final size */
|
||||
desc[desc_pos].len = &sw_descr[pos] - desc[desc_pos].start;
|
||||
}
|
||||
ofs += 1;
|
||||
|
||||
len = tlv_parse_one(&tag, &tag_len, &val,
|
||||
&sw_descr_def, &sw_descr[ofs], sw_descr_len-ofs);
|
||||
if (len < 0 || (tag != NM_ATT_FILE_ID)) {
|
||||
DEBUGP(DNM, "FILE_ID attribute identifier not found!\n");
|
||||
return -2;
|
||||
return desc_pos;
|
||||
}
|
||||
|
||||
int abis_nm_select_newest_sw(const struct abis_nm_sw_descr *sw_descr,
|
||||
const size_t size)
|
||||
{
|
||||
int res = 0;
|
||||
int i;
|
||||
|
||||
for (i = 1; i < size; ++i) {
|
||||
if (memcmp(sw_descr[res].file_ver, sw_descr[i].file_ver,
|
||||
OSMO_MIN(sw_descr[i].file_ver_len, sw_descr[res].file_ver_len)) < 0) {
|
||||
res = i;
|
||||
}
|
||||
}
|
||||
ofs += len;
|
||||
|
||||
len = tlv_parse_one(&tag, &tag_len, &val,
|
||||
&sw_descr_def, &sw_descr[ofs], sw_descr_len-ofs);
|
||||
if (len < 0 || (tag != NM_ATT_FILE_VERSION)) {
|
||||
DEBUGP(DNM, "FILE_VERSION attribute identifier not found!\n");
|
||||
return -3;
|
||||
}
|
||||
ofs += len;
|
||||
|
||||
return ofs;
|
||||
return res;
|
||||
}
|
||||
|
||||
static int abis_nm_rx_sw_act_req(struct msgb *mb)
|
||||
@@ -409,7 +444,8 @@ static int abis_nm_rx_sw_act_req(struct msgb *mb)
|
||||
struct e1inp_sign_link *sign_link = mb->dst;
|
||||
struct tlv_parsed tp;
|
||||
const uint8_t *sw_config;
|
||||
int ret, sw_config_len, sw_descr_len;
|
||||
int ret, sw_config_len, len;
|
||||
struct abis_nm_sw_descr sw_descr[5];
|
||||
|
||||
abis_nm_debugp_foh(DNM, foh);
|
||||
|
||||
@@ -439,16 +475,22 @@ static int abis_nm_rx_sw_act_req(struct msgb *mb)
|
||||
DEBUGP(DNM, "Found SW config: %s\n", osmo_hexdump(sw_config, sw_config_len));
|
||||
}
|
||||
|
||||
/* Use the first SW_DESCR present in SW config */
|
||||
sw_descr_len = abis_nm_parse_sw_descr(sw_config, sw_config_len);
|
||||
if (sw_descr_len < 0)
|
||||
/* Parse up to two sw descriptions from the data */
|
||||
len = abis_nm_parse_sw_config(sw_config, sw_config_len,
|
||||
&sw_descr[0], ARRAY_SIZE(sw_descr));
|
||||
if (len <= 0) {
|
||||
LOGP(DNM, LOGL_ERROR, "Failed to parse SW Config.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = abis_nm_select_newest_sw(&sw_descr[0], len);
|
||||
DEBUGP(DNM, "Selected sw description %d of %d\n", ret, len);
|
||||
|
||||
return ipacc_sw_activate(sign_link->trx->bts, foh->obj_class,
|
||||
foh->obj_inst.bts_nr,
|
||||
foh->obj_inst.trx_nr,
|
||||
foh->obj_inst.ts_nr,
|
||||
sw_config, sw_descr_len);
|
||||
sw_descr[ret].start, sw_descr[ret].len);
|
||||
}
|
||||
|
||||
/* Receive a CHANGE_ADM_STATE_ACK, parse the TLV and update local state */
|
||||
@@ -548,6 +590,7 @@ static int abis_nm_rcvmsg_fom(struct msgb *mb)
|
||||
|
||||
nack_data.msg = mb;
|
||||
nack_data.mt = mt;
|
||||
nack_data.bts = sign_link->trx->bts;
|
||||
osmo_signal_dispatch(SS_NM, S_NM_NACK, &nack_data);
|
||||
abis_nm_queue_send_next(sign_link->trx->bts);
|
||||
return 0;
|
||||
@@ -610,6 +653,7 @@ static int abis_nm_rcvmsg_manuf(struct msgb *mb)
|
||||
|
||||
switch (bts_type) {
|
||||
case GSM_BTS_TYPE_NANOBTS:
|
||||
case GSM_BTS_TYPE_OSMO_SYSMO:
|
||||
rc = abis_nm_rx_ipacc(mb);
|
||||
abis_nm_queue_send_next(sign_link->trx->bts);
|
||||
break;
|
||||
@@ -634,13 +678,16 @@ int abis_nm_rcvmsg(struct msgb *msg)
|
||||
if (oh->placement != ABIS_OM_PLACEMENT_ONLY) {
|
||||
LOGP(DNM, LOGL_ERROR, "ABIS OML placement 0x%x not supported\n",
|
||||
oh->placement);
|
||||
if (oh->placement != ABIS_OM_PLACEMENT_FIRST)
|
||||
return -EINVAL;
|
||||
if (oh->placement != ABIS_OM_PLACEMENT_FIRST) {
|
||||
rc = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
if (oh->sequence != 0) {
|
||||
LOGP(DNM, LOGL_ERROR, "ABIS OML sequence 0x%x != 0x00\n",
|
||||
oh->sequence);
|
||||
return -EINVAL;
|
||||
rc = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
#if 0
|
||||
unsigned int l2_len = msg->tail - (uint8_t *)msgb_l2(msg);
|
||||
@@ -670,9 +717,10 @@ int abis_nm_rcvmsg(struct msgb *msg)
|
||||
default:
|
||||
LOGP(DNM, LOGL_ERROR, "unknown ABIS OML message discriminator 0x%x\n",
|
||||
oh->mdisc);
|
||||
return -EINVAL;
|
||||
rc = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
err:
|
||||
msgb_free(msg);
|
||||
return rc;
|
||||
}
|
||||
@@ -1369,6 +1417,24 @@ int abis_nm_disc_terr_traf(struct abis_nm_h *h, struct abis_om_obj_inst *inst,
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Chapter 8.11.1 */
|
||||
int abis_nm_get_attr(struct gsm_bts *bts, uint8_t obj_class,
|
||||
uint8_t bts_nr, uint8_t trx_nr, uint8_t ts_nr,
|
||||
uint8_t *attr, uint8_t attr_len)
|
||||
{
|
||||
struct abis_om_hdr *oh;
|
||||
struct msgb *msg = nm_msgb_alloc();
|
||||
|
||||
DEBUGP(DNM, "Get Attr (bts=%d)\n", bts->nr);
|
||||
|
||||
oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
|
||||
fill_om_fom_hdr(oh, attr_len, NM_MT_GET_ATTR, obj_class,
|
||||
bts_nr, trx_nr, ts_nr);
|
||||
msgb_tl16v_put(msg, NM_ATT_LIST_REQ_ATTR, attr_len, attr);
|
||||
|
||||
return abis_nm_sendmsg(bts, msg);
|
||||
}
|
||||
|
||||
/* Chapter 8.6.1 */
|
||||
int abis_nm_set_bts_attr(struct gsm_bts *bts, uint8_t *attr, int attr_len)
|
||||
{
|
||||
@@ -1404,10 +1470,13 @@ int abis_nm_set_radio_attr(struct gsm_bts_trx *trx, uint8_t *attr, int attr_len)
|
||||
return abis_nm_sendmsg(trx->bts, msg);
|
||||
}
|
||||
|
||||
static int verify_chan_comb(struct gsm_bts_trx_ts *ts, uint8_t chan_comb)
|
||||
static int verify_chan_comb(struct gsm_bts_trx_ts *ts, uint8_t chan_comb,
|
||||
const char **reason)
|
||||
{
|
||||
int i;
|
||||
|
||||
*reason = "Reason unknown";
|
||||
|
||||
/* As it turns out, the BS-11 has some very peculiar restrictions
|
||||
* on the channel combinations it allows */
|
||||
switch (ts->trx->bts->type) {
|
||||
@@ -1416,6 +1485,7 @@ static int verify_chan_comb(struct gsm_bts_trx_ts *ts, uint8_t chan_comb)
|
||||
case NM_CHANC_TCHHalf:
|
||||
case NM_CHANC_TCHHalf2:
|
||||
/* not supported */
|
||||
*reason = "TCH/H is not supported.";
|
||||
return -EINVAL;
|
||||
case NM_CHANC_SDCCH:
|
||||
/* only one SDCCH/8 per TRX */
|
||||
@@ -1423,34 +1493,45 @@ static int verify_chan_comb(struct gsm_bts_trx_ts *ts, uint8_t chan_comb)
|
||||
if (i == ts->nr)
|
||||
continue;
|
||||
if (ts->trx->ts[i].nm_chan_comb ==
|
||||
NM_CHANC_SDCCH)
|
||||
NM_CHANC_SDCCH) {
|
||||
*reason = "Only one SDCCH/8 per TRX allowed.";
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
/* not allowed for TS0 of BCCH-TRX */
|
||||
if (ts->trx == ts->trx->bts->c0 &&
|
||||
ts->nr == 0)
|
||||
return -EINVAL;
|
||||
ts->nr == 0) {
|
||||
*reason = "SDCCH/8 must be on TS0.";
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* not on the same TRX that has a BCCH+SDCCH4
|
||||
* combination */
|
||||
if (ts->trx == ts->trx->bts->c0 &&
|
||||
if (ts->trx != ts->trx->bts->c0 &&
|
||||
(ts->trx->ts[0].nm_chan_comb == 5 ||
|
||||
ts->trx->ts[0].nm_chan_comb == 8))
|
||||
return -EINVAL;
|
||||
ts->trx->ts[0].nm_chan_comb == 8)) {
|
||||
*reason = "SDCCH/8 and BCCH must be on the same TRX.";
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case NM_CHANC_mainBCCH:
|
||||
case NM_CHANC_BCCHComb:
|
||||
/* allowed only for TS0 of C0 */
|
||||
if (ts->trx != ts->trx->bts->c0 ||
|
||||
ts->nr != 0)
|
||||
if (ts->trx != ts->trx->bts->c0 || ts->nr != 0) {
|
||||
*reason = "Main BCCH must be on TS0.";
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case NM_CHANC_BCCH:
|
||||
/* allowed only for TS 2/4/6 of C0 */
|
||||
if (ts->trx != ts->trx->bts->c0)
|
||||
if (ts->trx != ts->trx->bts->c0) {
|
||||
*reason = "BCCH must be on C0.";
|
||||
return -EINVAL;
|
||||
if (ts->nr != 2 && ts->nr != 4 &&
|
||||
ts->nr != 6)
|
||||
}
|
||||
if (ts->nr != 2 && ts->nr != 4 && ts->nr != 6) {
|
||||
*reason = "BCCH must be on TS 2/4/6.";
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case 8: /* this is not like 08.58, but in fact
|
||||
* FCCH+SCH+BCCH+CCCH+SDCCH/4+SACCH/C4+CBCH */
|
||||
@@ -1470,6 +1551,7 @@ static int verify_chan_comb(struct gsm_bts_trx_ts *ts, uint8_t chan_comb)
|
||||
return 0;
|
||||
break;
|
||||
default:
|
||||
*reason = "TS0 of TRX0 must carry a BCCH.";
|
||||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
@@ -1479,6 +1561,7 @@ static int verify_chan_comb(struct gsm_bts_trx_ts *ts, uint8_t chan_comb)
|
||||
case NM_CHANC_IPAC_TCHFull_TCHHalf:
|
||||
return 0;
|
||||
default:
|
||||
*reason = "TS0 must carry a TCH/F or TCH/H.";
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
@@ -1490,6 +1573,7 @@ static int verify_chan_comb(struct gsm_bts_trx_ts *ts, uint8_t chan_comb)
|
||||
if (ts->trx->ts[0].nm_chan_comb ==
|
||||
NM_CHANC_mainBCCH)
|
||||
return 0;
|
||||
*reason = "TS0 must be the main BCCH for CBCH.";
|
||||
return -EINVAL;
|
||||
case NM_CHANC_SDCCH:
|
||||
case NM_CHANC_TCHFull:
|
||||
@@ -1497,6 +1581,9 @@ static int verify_chan_comb(struct gsm_bts_trx_ts *ts, uint8_t chan_comb)
|
||||
case NM_CHANC_IPAC_TCHFull_TCHHalf:
|
||||
case NM_CHANC_IPAC_TCHFull_PDCH:
|
||||
return 0;
|
||||
default:
|
||||
*reason = "TS1 must carry a CBCH, SDCCH or TCH.";
|
||||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
switch (chan_comb) {
|
||||
@@ -1506,6 +1593,7 @@ static int verify_chan_comb(struct gsm_bts_trx_ts *ts, uint8_t chan_comb)
|
||||
case NM_CHANC_IPAC_TCHFull_TCHHalf:
|
||||
return 0;
|
||||
default:
|
||||
*reason = "TS1 must carry a SDCCH or TCH.";
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
@@ -1525,12 +1613,18 @@ static int verify_chan_comb(struct gsm_bts_trx_ts *ts, uint8_t chan_comb)
|
||||
case NM_CHANC_IPAC_TCHFull_PDCH:
|
||||
if (ts->trx->nr == 0)
|
||||
return 0;
|
||||
else
|
||||
else {
|
||||
*reason = "PDCH must be on TRX0.";
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
*reason = "Unknown combination";
|
||||
return -EINVAL;
|
||||
case GSM_BTS_TYPE_OSMO_SYSMO:
|
||||
/* no known restrictions */
|
||||
return 0;
|
||||
default:
|
||||
/* unknown BTS type */
|
||||
return 0;
|
||||
@@ -1546,14 +1640,17 @@ int abis_nm_set_channel_attr(struct gsm_bts_trx_ts *ts, uint8_t chan_comb)
|
||||
uint8_t zero = 0x00;
|
||||
struct msgb *msg = nm_msgb_alloc();
|
||||
uint8_t len = 2 + 2;
|
||||
const char *reason = NULL;
|
||||
|
||||
if (bts->type == GSM_BTS_TYPE_BS11)
|
||||
len += 4 + 2 + 2 + 3;
|
||||
|
||||
DEBUGP(DNM, "Set Chan Attr %s\n", gsm_ts_name(ts));
|
||||
if (verify_chan_comb(ts, chan_comb) < 0) {
|
||||
if (verify_chan_comb(ts, chan_comb, &reason) < 0) {
|
||||
msgb_free(msg);
|
||||
DEBUGP(DNM, "Invalid Channel Combination!!!\n");
|
||||
LOGP(DNM, LOGL_ERROR,
|
||||
"Invalid Channel Combination %d on %s. Reason: %s\n",
|
||||
chan_comb, gsm_ts_name(ts), reason);
|
||||
return -EINVAL;
|
||||
}
|
||||
ts->nm_chan_comb = chan_comb;
|
||||
@@ -2563,7 +2660,7 @@ void ipac_parse_cgi(struct cell_global_id *cid, const uint8_t *buf)
|
||||
int ipac_parse_bcch_info(struct ipac_bcch_info *binf, uint8_t *buf)
|
||||
{
|
||||
uint8_t *cur = buf;
|
||||
uint16_t len;
|
||||
uint16_t len __attribute__((unused));
|
||||
|
||||
memset(binf, 0, sizeof(*binf));
|
||||
|
||||
|
||||
@@ -63,7 +63,24 @@ static int dummy_config_write(struct vty *v)
|
||||
|
||||
/* FIXME: auto-generate those strings from the value_string lists */
|
||||
#define NM_OBJCLASS_VTY "(site-manager|bts|radio-carrier|baseband-transceiver|channel|adjc|handover|power-contorl|btse|rack|test|envabtse|bport|gprs-nse|gprs-cell|gprs-nsvc|siemenshw)"
|
||||
#define NM_OBJCLASS_VTY_HELP "FIXME"
|
||||
#define NM_OBJCLASS_VTY_HELP "Site Manager Object\n" \
|
||||
"BTS Object\n" \
|
||||
"Radio Carrier Object\n" \
|
||||
"Baseband Transceiver Object\n" \
|
||||
"Channel (Timeslot) Object\n" \
|
||||
"Adjacent Object (Siemens)\n" \
|
||||
"Handover Object (Siemens)\n" \
|
||||
"Power Control Object (Siemens)\n" \
|
||||
"BTSE Object (Siemens)\n" \
|
||||
"Rack Object (Siemens)\n" \
|
||||
"Test Object (Siemens)\n" \
|
||||
"ENVABTSE Object (Siemens)\n" \
|
||||
"BPORT Object (Siemens)\n" \
|
||||
"GPRS NSE Object (ip.access/osmo-bts)\n" \
|
||||
"GPRS Cell Object (ip.acecss/osmo-bts)\n" \
|
||||
"GPRS NSVC Object (ip.acecss/osmo-bts)\n" \
|
||||
"SIEMENSHW Object (Siemens)\n"
|
||||
|
||||
|
||||
DEFUN(oml_class_inst, oml_class_inst_cmd,
|
||||
"bts <0-255> oml class " NM_OBJCLASS_VTY
|
||||
|
||||
@@ -788,6 +788,9 @@ static void signal_op_state(struct gsm_bts *bts, struct abis_om2k_mo *mo)
|
||||
struct gsm_nm_state *nm_state = mo2nm_state(bts, mo);
|
||||
struct nm_statechg_signal_data nsd;
|
||||
|
||||
if (!nm_state)
|
||||
return;
|
||||
|
||||
nsd.bts = bts;
|
||||
nsd.obj = mo2obj(bts, mo);
|
||||
nsd.old_state = nm_state;
|
||||
@@ -819,6 +822,7 @@ static int abis_om2k_sendmsg(struct gsm_bts *bts, struct msgb *msg)
|
||||
"non-existing TRX\n", om2k_mo_name(&o2h->mo));
|
||||
return -ENODEV;
|
||||
}
|
||||
msg->dst = trx->oml_link;
|
||||
break;
|
||||
case OM2K_MO_CLS_TS:
|
||||
/* Route through per-TRX OML Link to the appropriate TRX */
|
||||
@@ -828,13 +832,13 @@ static int abis_om2k_sendmsg(struct gsm_bts *bts, struct msgb *msg)
|
||||
"non-existing TRX\n", om2k_mo_name(&o2h->mo));
|
||||
return -ENODEV;
|
||||
}
|
||||
msg->dst = trx->oml_link;
|
||||
break;
|
||||
default:
|
||||
/* Route through the IXU/DXU OML Link */
|
||||
trx = bts->c0;
|
||||
msg->dst = bts->oml_link;
|
||||
break;
|
||||
}
|
||||
msg->dst = trx->oml_link;
|
||||
|
||||
return _abis_nm_sendmsg(msg);
|
||||
}
|
||||
@@ -995,6 +999,9 @@ int abis_om2k_tx_is_conf_req(struct gsm_bts *bts)
|
||||
|
||||
talloc_free(cg);
|
||||
|
||||
DEBUGP(DNM, "Tx MO=%s %s\n", om2k_mo_name(&om2k_mo_is),
|
||||
get_value_string(om2k_msgcode_vals, OM2K_MSGT_IS_CONF_REQ));
|
||||
|
||||
return abis_om2k_sendmsg(bts, msg);
|
||||
}
|
||||
|
||||
@@ -1012,6 +1019,9 @@ int abis_om2k_tx_con_conf_req(struct gsm_bts *bts, uint8_t *data,
|
||||
|
||||
msgb_tlv_put(msg, OM2K_DEI_CON_CONN_LIST, len, data);
|
||||
|
||||
DEBUGP(DNM, "Tx MO=%s %s\n", om2k_mo_name(&om2k_mo_con),
|
||||
get_value_string(om2k_msgcode_vals, OM2K_MSGT_CON_CONF_REQ));
|
||||
|
||||
return abis_om2k_sendmsg(bts, msg);
|
||||
}
|
||||
|
||||
@@ -1095,6 +1105,9 @@ int abis_om2k_tx_tf_conf_req(struct gsm_bts *bts)
|
||||
msgb_tv_fixed_put(msg, OM2K_DEI_FS_OFFSET,
|
||||
sizeof(fs_offset_undef), fs_offset_undef);
|
||||
|
||||
DEBUGP(DNM, "Tx MO=%s %s\n", om2k_mo_name(&om2k_mo_tf),
|
||||
get_value_string(om2k_msgcode_vals, OM2K_MSGT_TF_CONF_REQ));
|
||||
|
||||
return abis_om2k_sendmsg(bts, msg);
|
||||
}
|
||||
|
||||
|
||||
@@ -216,7 +216,8 @@ DEFUN(om2k_disable, om2k_disable_cmd,
|
||||
|
||||
DEFUN(om2k_op_info, om2k_op_info_cmd,
|
||||
"operational-info <0-1>",
|
||||
"Set operational information\n")
|
||||
"Set operational information\n"
|
||||
"Set operational info to 0 or 1\n")
|
||||
{
|
||||
struct oml_node_state *oms = vty->index;
|
||||
int oper = atoi(argv[0]);
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* 3GPP TS 08.58 version 8.6.0 Release 1999 / ETSI TS 100 596 V8.6.0 */
|
||||
|
||||
/* (C) 2008-2010 by Harald Welte <laforge@gnumonks.org>
|
||||
* (C) 2012 by Holger Hans Peter Freyther
|
||||
*
|
||||
* All Rights Reserved
|
||||
*
|
||||
@@ -45,6 +46,11 @@
|
||||
#define RSL_ALLOC_SIZE 1024
|
||||
#define RSL_ALLOC_HEADROOM 128
|
||||
|
||||
enum sacch_deact {
|
||||
SACCH_NONE,
|
||||
SACCH_DEACTIVATE,
|
||||
};
|
||||
|
||||
static int rsl_send_imm_assignment(struct gsm_lchan *lchan);
|
||||
|
||||
static void send_lchan_signal(int sig_no, struct gsm_lchan *lchan,
|
||||
@@ -56,6 +62,14 @@ static void send_lchan_signal(int sig_no, struct gsm_lchan *lchan,
|
||||
osmo_signal_dispatch(SS_LCHAN, sig_no, &sig);
|
||||
}
|
||||
|
||||
static void do_lchan_free(struct gsm_lchan *lchan)
|
||||
{
|
||||
/* we have an error timer pending to release that */
|
||||
if (lchan->state != LCHAN_S_REL_ERR)
|
||||
rsl_lchan_set_state(lchan, LCHAN_S_NONE);
|
||||
lchan_free(lchan);
|
||||
}
|
||||
|
||||
static uint8_t mdisc_by_msgtype(uint8_t msg_type)
|
||||
{
|
||||
/* mask off the transparent bit ? */
|
||||
@@ -182,7 +196,7 @@ static void lchan_act_tmr_cb(void *data)
|
||||
{
|
||||
struct gsm_lchan *lchan = data;
|
||||
|
||||
LOGP(DRSL, LOGL_NOTICE, "%s Timeout during activation!\n",
|
||||
LOGP(DRSL, LOGL_ERROR, "%s Timeout during activation!\n",
|
||||
gsm_lchan_name(lchan));
|
||||
|
||||
rsl_lchan_set_state(lchan, LCHAN_S_NONE);
|
||||
@@ -193,12 +207,10 @@ static void lchan_deact_tmr_cb(void *data)
|
||||
{
|
||||
struct gsm_lchan *lchan = data;
|
||||
|
||||
LOGP(DRSL, LOGL_NOTICE, "%s Timeout during deactivation!\n",
|
||||
LOGP(DRSL, LOGL_ERROR, "%s Timeout during deactivation!\n",
|
||||
gsm_lchan_name(lchan));
|
||||
|
||||
if (lchan->state != LCHAN_S_REL_ERR)
|
||||
rsl_lchan_set_state(lchan, LCHAN_S_NONE);
|
||||
lchan_free(lchan);
|
||||
do_lchan_free(lchan);
|
||||
}
|
||||
|
||||
|
||||
@@ -317,7 +329,7 @@ int rsl_chan_ms_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int dbm)
|
||||
static int channel_mode_from_lchan(struct rsl_ie_chan_mode *cm,
|
||||
struct gsm_lchan *lchan)
|
||||
{
|
||||
memset(cm, 0, sizeof(cm));
|
||||
memset(cm, 0, sizeof(*cm));
|
||||
|
||||
/* FIXME: what to do with data calls ? */
|
||||
if (lchan->ts->trx->bts->network->dtx_enabled)
|
||||
@@ -363,14 +375,53 @@ static int channel_mode_from_lchan(struct rsl_ie_chan_mode *cm,
|
||||
cm->chan_rate = RSL_CMOD_SP_GSM3;
|
||||
break;
|
||||
case GSM48_CMODE_DATA_14k5:
|
||||
cm->chan_rate = RSL_CMOD_SP_NT_14k5;
|
||||
break;
|
||||
case GSM48_CMODE_DATA_12k0:
|
||||
cm->chan_rate = RSL_CMOD_SP_NT_12k0;
|
||||
break;
|
||||
case GSM48_CMODE_DATA_6k0:
|
||||
cm->chan_rate = RSL_CMOD_SP_NT_6k0;
|
||||
break;
|
||||
switch (lchan->csd_mode) {
|
||||
case LCHAN_CSD_M_NT:
|
||||
/* non-transparent CSD with RLP */
|
||||
switch (lchan->tch_mode) {
|
||||
case GSM48_CMODE_DATA_14k5:
|
||||
cm->chan_rate = RSL_CMOD_SP_NT_14k5;
|
||||
break;
|
||||
case GSM48_CMODE_DATA_12k0:
|
||||
cm->chan_rate = RSL_CMOD_SP_NT_12k0;
|
||||
break;
|
||||
case GSM48_CMODE_DATA_6k0:
|
||||
cm->chan_rate = RSL_CMOD_SP_NT_6k0;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
/* transparent data services below */
|
||||
case LCHAN_CSD_M_T_1200_75:
|
||||
cm->chan_rate = RSL_CMOD_CSD_T_1200_75;
|
||||
break;
|
||||
case LCHAN_CSD_M_T_600:
|
||||
cm->chan_rate = RSL_CMOD_CSD_T_600;
|
||||
break;
|
||||
case LCHAN_CSD_M_T_1200:
|
||||
cm->chan_rate = RSL_CMOD_CSD_T_1200;
|
||||
break;
|
||||
case LCHAN_CSD_M_T_2400:
|
||||
cm->chan_rate = RSL_CMOD_CSD_T_2400;
|
||||
break;
|
||||
case LCHAN_CSD_M_T_9600:
|
||||
cm->chan_rate = RSL_CMOD_CSD_T_9600;
|
||||
break;
|
||||
case LCHAN_CSD_M_T_14400:
|
||||
cm->chan_rate = RSL_CMOD_CSD_T_14400;
|
||||
break;
|
||||
case LCHAN_CSD_M_T_29000:
|
||||
cm->chan_rate = RSL_CMOD_CSD_T_29000;
|
||||
break;
|
||||
case LCHAN_CSD_M_T_32000:
|
||||
cm->chan_rate = RSL_CMOD_CSD_T_32000;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -598,12 +649,16 @@ static void error_timeout_cb(void *data)
|
||||
static int rsl_rx_rf_chan_rel_ack(struct gsm_lchan *lchan);
|
||||
|
||||
/* Chapter 8.4.14 / 4.7: Tell BTS to release the radio channel */
|
||||
static int rsl_rf_chan_release(struct gsm_lchan *lchan, int error)
|
||||
static int rsl_rf_chan_release(struct gsm_lchan *lchan, int error,
|
||||
enum sacch_deact deact_sacch)
|
||||
{
|
||||
struct abis_rsl_dchan_hdr *dh;
|
||||
struct msgb *msg;
|
||||
int rc;
|
||||
|
||||
/* Stop timers that should lead to a channel release */
|
||||
osmo_timer_del(&lchan->T3109);
|
||||
|
||||
if (lchan->state == LCHAN_S_REL_ERR) {
|
||||
LOGP(DRSL, LOGL_NOTICE, "%s is in error state not sending release.\n",
|
||||
gsm_lchan_name(lchan));
|
||||
@@ -621,13 +676,34 @@ static int rsl_rf_chan_release(struct gsm_lchan *lchan, int error)
|
||||
DEBUGP(DRSL, "%s RF Channel Release CMD due error %d\n", gsm_lchan_name(lchan), error);
|
||||
|
||||
if (error) {
|
||||
/*
|
||||
* the nanoBTS sends RLL release indications after the channel release. This can
|
||||
* be a problem when we have reassigned the channel to someone else and then can
|
||||
* not figure out who used this channel.
|
||||
*/
|
||||
struct e1inp_sign_link *sign_link = msg->dst;
|
||||
|
||||
/*
|
||||
* FIXME: GSM 04.08 gives us two options for the abnormal
|
||||
* chanel release. This can be either like in the non-existent
|
||||
* sub-lcuase 3.5.1 or for the main signalling link deactivate
|
||||
* the SACCH, start timer T3109 and consider the channel as
|
||||
* released.
|
||||
*
|
||||
* This code is doing the later for all raido links and not
|
||||
* only the main link. Right now all SAPIs are released on the
|
||||
* local end, the SACCH will be de-activated and right now the
|
||||
* T3111 will be started. First T3109 should be started and then
|
||||
* the T3111.
|
||||
*
|
||||
* TODO: Move this out of the function.
|
||||
*/
|
||||
|
||||
/*
|
||||
* sacch de-activate and "local end release"
|
||||
*/
|
||||
if (deact_sacch == SACCH_DEACTIVATE)
|
||||
rsl_deact_sacch(lchan);
|
||||
rsl_release_sapis_from(lchan, 0, RSL_REL_LOCAL_END);
|
||||
|
||||
/*
|
||||
* TODO: start T3109 now.
|
||||
*/
|
||||
rsl_lchan_set_state(lchan, LCHAN_S_REL_ERR);
|
||||
lchan->error_timer.data = lchan;
|
||||
lchan->error_timer.cb = error_timeout_cb;
|
||||
@@ -657,17 +733,15 @@ static int rsl_rx_rf_chan_rel_ack(struct gsm_lchan *lchan)
|
||||
|
||||
DEBUGP(DRSL, "%s RF CHANNEL RELEASE ACK\n", gsm_lchan_name(lchan));
|
||||
|
||||
/* Stop all pending timers */
|
||||
osmo_timer_del(&lchan->act_timer);
|
||||
osmo_timer_del(&lchan->T3111);
|
||||
|
||||
if (lchan->state != LCHAN_S_REL_REQ && lchan->state != LCHAN_S_REL_ERR)
|
||||
LOGP(DRSL, LOGL_NOTICE, "%s CHAN REL ACK but state %s\n",
|
||||
gsm_lchan_name(lchan),
|
||||
gsm_lchans_name(lchan->state));
|
||||
osmo_timer_del(&lchan->T3111);
|
||||
/* we have an error timer pending to release that */
|
||||
if (lchan->state != LCHAN_S_REL_ERR)
|
||||
rsl_lchan_set_state(lchan, LCHAN_S_NONE);
|
||||
lchan_free(lchan);
|
||||
do_lchan_free(lchan);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -794,7 +868,8 @@ int rsl_establish_request(struct gsm_lchan *lchan, uint8_t link_id)
|
||||
RELEASE CONFIRM, which we in turn use to trigger RSL CHANNEL RELEASE,
|
||||
which in turn is acknowledged by RSL CHANNEL RELEASE ACK, which calls
|
||||
lchan_free() */
|
||||
int rsl_release_request(struct gsm_lchan *lchan, uint8_t link_id, uint8_t reason)
|
||||
int rsl_release_request(struct gsm_lchan *lchan, uint8_t link_id,
|
||||
enum rsl_rel_mode release_mode)
|
||||
{
|
||||
|
||||
struct msgb *msg;
|
||||
@@ -802,14 +877,14 @@ int rsl_release_request(struct gsm_lchan *lchan, uint8_t link_id, uint8_t reason
|
||||
msg = rsl_rll_simple(RSL_MT_REL_REQ, gsm_lchan2chan_nr(lchan),
|
||||
link_id, 0);
|
||||
/* 0 is normal release, 1 is local end */
|
||||
msgb_tv_put(msg, RSL_IE_RELEASE_MODE, reason);
|
||||
msgb_tv_put(msg, RSL_IE_RELEASE_MODE, release_mode);
|
||||
|
||||
/* FIXME: start some timer in case we don't receive a REL ACK ? */
|
||||
|
||||
msg->dst = lchan->ts->trx->rsl_link;
|
||||
|
||||
DEBUGP(DRLL, "%s RSL RLL RELEASE REQ (link_id=0x%02x, reason=%u)\n",
|
||||
gsm_lchan_name(lchan), link_id, reason);
|
||||
gsm_lchan_name(lchan), link_id, release_mode);
|
||||
|
||||
return abis_rsl_sendmsg(msg);
|
||||
}
|
||||
@@ -870,19 +945,18 @@ static int rsl_rx_chan_act_nack(struct msgb *msg)
|
||||
const uint8_t *cause = TLVP_VAL(&tp, RSL_IE_CAUSE);
|
||||
print_rsl_cause(LOGL_ERROR, cause,
|
||||
TLVP_LEN(&tp, RSL_IE_CAUSE));
|
||||
msg->lchan->error_cause = *cause;
|
||||
if (*cause != RSL_ERR_RCH_ALR_ACTV_ALLOC)
|
||||
rsl_lchan_set_state(msg->lchan, LCHAN_S_NONE);
|
||||
rsl_lchan_set_state(msg->lchan, LCHAN_S_BROKEN);
|
||||
else
|
||||
rsl_rf_chan_release(msg->lchan, 1);
|
||||
rsl_rf_chan_release(msg->lchan, 1, SACCH_DEACTIVATE);
|
||||
|
||||
} else
|
||||
rsl_lchan_set_state(msg->lchan, LCHAN_S_NONE);
|
||||
rsl_lchan_set_state(msg->lchan, LCHAN_S_BROKEN);
|
||||
|
||||
LOGPC(DRSL, LOGL_ERROR, "\n");
|
||||
|
||||
send_lchan_signal(S_LCHAN_ACTIVATE_NACK, msg->lchan, NULL);
|
||||
|
||||
lchan_free(msg->lchan);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -905,7 +979,7 @@ static int rsl_rx_conn_fail(struct msgb *msg)
|
||||
LOGPC(DRSL, LOGL_NOTICE, "\n");
|
||||
/* FIXME: only free it after channel release ACK */
|
||||
osmo_counter_inc(msg->lchan->ts->trx->bts->network->stats.chan.rf_fail);
|
||||
return rsl_rf_chan_release(msg->lchan, 1);
|
||||
return rsl_rf_chan_release(msg->lchan, 1, SACCH_DEACTIVATE);
|
||||
}
|
||||
|
||||
static void print_meas_rep_uni(struct gsm_meas_rep_unidir *mru,
|
||||
@@ -918,11 +992,15 @@ static void print_meas_rep_uni(struct gsm_meas_rep_unidir *mru,
|
||||
prefix, mru->full.rx_qual, prefix, mru->sub.rx_qual);
|
||||
}
|
||||
|
||||
static void print_meas_rep(struct gsm_meas_rep *mr)
|
||||
static void print_meas_rep(struct gsm_lchan *lchan, struct gsm_meas_rep *mr)
|
||||
{
|
||||
int i;
|
||||
char *name = "";
|
||||
|
||||
DEBUGP(DMEAS, "MEASUREMENT RESULT NR=%d ", mr->nr);
|
||||
if (lchan && lchan->conn && lchan->conn->subscr)
|
||||
name = subscr_name(lchan->conn->subscr);
|
||||
|
||||
DEBUGP(DMEAS, "[%s] MEASUREMENT RESULT NR=%d ", name, mr->nr);
|
||||
|
||||
if (mr->flags & MEAS_REP_F_DL_DTX)
|
||||
DEBUGPC(DMEAS, "DTXd ");
|
||||
@@ -1027,7 +1105,7 @@ static int rsl_rx_meas_res(struct msgb *msg)
|
||||
return rc;
|
||||
}
|
||||
|
||||
print_meas_rep(mr);
|
||||
print_meas_rep(msg->lchan, mr);
|
||||
|
||||
send_lchan_signal(S_LCHAN_MEAS_REP, msg->lchan, mr);
|
||||
|
||||
@@ -1182,7 +1260,7 @@ static void t3101_expired(void *data)
|
||||
{
|
||||
struct gsm_lchan *lchan = data;
|
||||
|
||||
rsl_rf_chan_release(lchan, 1);
|
||||
rsl_rf_chan_release(lchan, 1, SACCH_DEACTIVATE);
|
||||
}
|
||||
|
||||
/* If T3111 expires, we will send the RF Channel Request */
|
||||
@@ -1190,7 +1268,17 @@ static void t3111_expired(void *data)
|
||||
{
|
||||
struct gsm_lchan *lchan = data;
|
||||
|
||||
rsl_rf_chan_release(lchan, 0);
|
||||
rsl_rf_chan_release(lchan, 0, SACCH_NONE);
|
||||
}
|
||||
|
||||
/* If T3109 expires the MS has not send a UA/UM do the error release */
|
||||
static void t3109_expired(void *data)
|
||||
{
|
||||
struct gsm_lchan *lchan = data;
|
||||
|
||||
LOGP(DRSL, LOGL_ERROR,
|
||||
"%s SACCH deactivation timeout.\n", gsm_lchan_name(lchan));
|
||||
rsl_rf_chan_release(lchan, 1, SACCH_NONE);
|
||||
}
|
||||
|
||||
#define GSM48_LEN2PLEN(a) (((a) << 2) | 1)
|
||||
@@ -1207,7 +1295,7 @@ static int rsl_send_imm_ass_rej(struct gsm_bts *bts,
|
||||
/* create IMMEDIATE ASSIGN REJECT 04.08 message */
|
||||
memset(iar, 0, sizeof(*iar));
|
||||
iar->proto_discr = GSM48_PDISC_RR;
|
||||
iar->msg_type = GSM48_MT_RR_IMM_ASS;
|
||||
iar->msg_type = GSM48_MT_RR_IMM_ASS_REJ;
|
||||
iar->page_mode = GSM48_PM_SAME;
|
||||
|
||||
memcpy(&iar->req_ref1, &rqd_refs[0], sizeof(iar->req_ref1));
|
||||
@@ -1231,7 +1319,10 @@ static int rsl_send_imm_ass_rej(struct gsm_bts *bts,
|
||||
memcpy(&iar->req_ref4, &rqd_refs[0], sizeof(iar->req_ref4));
|
||||
iar->wait_ind4 = wait_ind;
|
||||
|
||||
return rsl_imm_assign_cmd(bts, sizeof(iar), (uint8_t *) iar);
|
||||
/* we need to subtract 1 byte from sizeof(*iar) since ia includes the l2_plen field */
|
||||
iar->l2_plen = GSM48_LEN2PLEN((sizeof(*iar)-1));
|
||||
|
||||
return rsl_imm_assign_cmd(bts, sizeof(*iar), (uint8_t *) iar);
|
||||
}
|
||||
|
||||
/* MS has requested a channel on the RACH */
|
||||
@@ -1437,18 +1528,28 @@ static int abis_rsl_rx_cchan(struct msgb *msg)
|
||||
|
||||
static int rsl_rx_rll_err_ind(struct msgb *msg)
|
||||
{
|
||||
struct tlv_parsed tp;
|
||||
struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
|
||||
uint8_t *rlm_cause = rllh->data;
|
||||
uint8_t rlm_cause;
|
||||
|
||||
rsl_tlv_parse(&tp, rllh->data, msgb_l2len(msg) - sizeof(*rllh));
|
||||
if (!TLVP_PRESENT(&tp, RSL_IE_RLM_CAUSE)) {
|
||||
LOGP(DRLL, LOGL_ERROR,
|
||||
"%s ERROR INDICATION without mandantory cause.\n",
|
||||
gsm_lchan_name(msg->lchan));
|
||||
return -1;
|
||||
}
|
||||
|
||||
rlm_cause = *TLVP_VAL(&tp, RSL_IE_RLM_CAUSE);
|
||||
LOGP(DRLL, LOGL_ERROR, "%s ERROR INDICATION cause=%s\n",
|
||||
gsm_lchan_name(msg->lchan),
|
||||
rsl_rlm_cause_name(rlm_cause[1]));
|
||||
rsl_rlm_cause_name(rlm_cause));
|
||||
|
||||
rll_indication(msg->lchan, rllh->link_id, BSC_RLLR_IND_ERR_IND);
|
||||
|
||||
if (rlm_cause[1] == RLL_CAUSE_T200_EXPIRED) {
|
||||
if (rlm_cause == RLL_CAUSE_T200_EXPIRED) {
|
||||
osmo_counter_inc(msg->lchan->ts->trx->bts->network->stats.chan.rll_err);
|
||||
return rsl_rf_chan_release(msg->lchan, 1);
|
||||
return rsl_rf_chan_release(msg->lchan, 1, SACCH_DEACTIVATE);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -1459,7 +1560,11 @@ static void rsl_handle_release(struct gsm_lchan *lchan)
|
||||
int sapi;
|
||||
struct gsm_bts *bts;
|
||||
|
||||
/* maybe we have only brought down one RLL */
|
||||
/*
|
||||
* Maybe only one link/SAPI was releasd or the error handling
|
||||
* was activated. Just return now and let the other code handle
|
||||
* it.
|
||||
*/
|
||||
if (lchan->state != LCHAN_S_REL_REQ)
|
||||
return;
|
||||
|
||||
@@ -1472,8 +1577,8 @@ static void rsl_handle_release(struct gsm_lchan *lchan)
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* wait a bit to send the RF Channel Release */
|
||||
/* Stop T3109 and wait for T3111 before re-using the channel */
|
||||
osmo_timer_del(&lchan->T3109);
|
||||
lchan->T3111.cb = t3111_expired;
|
||||
lchan->T3111.data = lchan;
|
||||
bts = lchan->ts->trx->bts;
|
||||
@@ -1533,7 +1638,6 @@ static int abis_rsl_rx_rll(struct msgb *msg)
|
||||
rll_indication(msg->lchan, rllh->link_id,
|
||||
BSC_RLLR_IND_REL_IND);
|
||||
rsl_handle_release(msg->lchan);
|
||||
rsl_lchan_rll_release(msg->lchan, rllh->link_id);
|
||||
break;
|
||||
case RSL_MT_REL_CONF:
|
||||
/* BTS informs us of having received UA from MS,
|
||||
@@ -1541,7 +1645,6 @@ static int abis_rsl_rx_rll(struct msgb *msg)
|
||||
DEBUGPC(DRLL, "RELEASE CONFIRMATION\n");
|
||||
msg->lchan->sapis[rllh->link_id & 0x7] = LCHAN_SAPI_UNUSED;
|
||||
rsl_handle_release(msg->lchan);
|
||||
rsl_lchan_rll_release(msg->lchan, rllh->link_id);
|
||||
break;
|
||||
case RSL_MT_ERROR_IND:
|
||||
rc = rsl_rx_rll_err_ind(msg);
|
||||
@@ -1685,6 +1788,9 @@ static void ipac_parse_rtp(struct gsm_lchan *lchan, struct tlv_parsed *tv)
|
||||
}
|
||||
}
|
||||
|
||||
/*! \brief Issue IPA RSL CRCX to configure RTP on BTS side
|
||||
* \param[in] lchan Logical Channel for which we issue CRCX
|
||||
*/
|
||||
int rsl_ipacc_crcx(struct gsm_lchan *lchan)
|
||||
{
|
||||
struct msgb *msg = rsl_msgb_alloc();
|
||||
@@ -1710,6 +1816,12 @@ int rsl_ipacc_crcx(struct gsm_lchan *lchan)
|
||||
return abis_rsl_sendmsg(msg);
|
||||
}
|
||||
|
||||
/*! \brief Issue IPA RSL MDCX to configure MGW-side of RTP
|
||||
* \param[in] lchan Logical Channel for which we issue MDCX
|
||||
* \param[in] ip Remote (MGW) IP address for RTP
|
||||
* \param[in] port Remote (MGW) UDP port number for RTP
|
||||
* \param[in] rtp_payload2 Contents of RTP PAYLOAD 2 IE
|
||||
*/
|
||||
int rsl_ipacc_mdcx(struct gsm_lchan *lchan, uint32_t ip, uint16_t port,
|
||||
uint8_t rtp_payload2)
|
||||
{
|
||||
@@ -2010,3 +2122,66 @@ int rsl_bs_power_control(struct gsm_bts_trx *trx, uint8_t channel, uint8_t reduc
|
||||
|
||||
return abis_rsl_sendmsg(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Release all allocated SAPIs starting from @param start and
|
||||
* release them with the given release mode. Once the release
|
||||
* confirmation arrives it will be attempted to release the
|
||||
* the RF channel.
|
||||
*/
|
||||
int rsl_release_sapis_from(struct gsm_lchan *lchan, int start,
|
||||
enum rsl_rel_mode release_mode)
|
||||
{
|
||||
int no_sapi = 1;
|
||||
int sapi;
|
||||
|
||||
for (sapi = start; sapi < ARRAY_SIZE(lchan->sapis); ++sapi) {
|
||||
uint8_t link_id;
|
||||
if (lchan->sapis[sapi] == LCHAN_SAPI_UNUSED)
|
||||
continue;
|
||||
|
||||
link_id = sapi;
|
||||
if (lchan->type == GSM_LCHAN_TCH_F || lchan->type == GSM_LCHAN_TCH_H)
|
||||
link_id |= 0x40;
|
||||
rsl_release_request(lchan, link_id, release_mode);
|
||||
no_sapi = 0;
|
||||
}
|
||||
|
||||
return no_sapi;
|
||||
}
|
||||
|
||||
int rsl_start_t3109(struct gsm_lchan *lchan)
|
||||
{
|
||||
struct gsm_bts *bts = lchan->ts->trx->bts;
|
||||
|
||||
/* Disabled, mostly legacy code */
|
||||
if (bts->network->T3109 == 0)
|
||||
return -1;
|
||||
|
||||
lchan->T3109.cb = t3109_expired;
|
||||
lchan->T3109.data = lchan;
|
||||
osmo_timer_schedule(&lchan->T3109, bts->network->T3109, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief directly RF Channel Release the lchan
|
||||
*
|
||||
* When no SAPI was allocated, directly release the logical channel. This
|
||||
* should only be called from chan_alloc.c on channel release handling. In
|
||||
* case no SAPI was established the RF Channel can be directly released,
|
||||
*/
|
||||
int rsl_direct_rf_release(struct gsm_lchan *lchan)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < ARRAY_SIZE(lchan->sapis); ++i) {
|
||||
if (lchan->sapis[i] != LCHAN_SAPI_UNUSED) {
|
||||
LOGP(DRSL, LOGL_ERROR, "%s SAPI(%d) still allocated.\n",
|
||||
gsm_lchan_name(lchan), i);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now release it */
|
||||
return rsl_rf_chan_release(lchan, 0, SACCH_NONE);
|
||||
}
|
||||
|
||||
305
openbsc/src/libbsc/arfcn_range_encode.c
Normal file
305
openbsc/src/libbsc/arfcn_range_encode.c
Normal file
@@ -0,0 +1,305 @@
|
||||
/* gsm 04.08 system information (si) encoding and decoding
|
||||
* 3gpp ts 04.08 version 7.21.0 release 1998 / etsi ts 100 940 v7.21.0 */
|
||||
|
||||
/*
|
||||
* (C) 2012 Holger Hans Peter Freyther
|
||||
* (C) 2012 by On-Waves
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <openbsc/arfcn_range_encode.h>
|
||||
#include <openbsc/debug.h>
|
||||
|
||||
#include <osmocom/gsm/protocol/gsm_04_08.h>
|
||||
|
||||
#include <osmocom/core/utils.h>
|
||||
|
||||
int greatest_power_of_2_lesser_or_equal_to(int index)
|
||||
{
|
||||
int power_of_2 = 1;
|
||||
|
||||
do {
|
||||
power_of_2 *= 2;
|
||||
} while (power_of_2 <= index);
|
||||
|
||||
/* now go back one step */
|
||||
return power_of_2 / 2;
|
||||
}
|
||||
|
||||
static inline int mod(int data, int range)
|
||||
{
|
||||
int res = data % range;
|
||||
while (res < 0)
|
||||
res += range;
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine at which index to split the ARFCNs to create an
|
||||
* equally size partition for the given range. Return -1 if
|
||||
* no such partition exists.
|
||||
*/
|
||||
int range_enc_find_index(const int range, const int *freqs, const int size)
|
||||
{
|
||||
int i, j, n;
|
||||
|
||||
const int RANGE_DELTA = (range - 1) / 2;
|
||||
|
||||
for (i = 0; i < size; ++i) {
|
||||
n = 0;
|
||||
for (j = 0; j < size; ++j) {
|
||||
if (mod(freqs[j] - freqs[i], range) <= RANGE_DELTA)
|
||||
n += 1;
|
||||
}
|
||||
|
||||
if (n - 1 == (size - 1) / 2)
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Range encode the ARFCN list.
|
||||
* \param range The range to use.
|
||||
* \param arfcns The list of ARFCNs
|
||||
* \param size The size of the list of ARFCNs
|
||||
* \param out Place to store the W(i) output.
|
||||
*/
|
||||
int range_enc_arfcns(const int range,
|
||||
const int *arfcns, int size, int *out,
|
||||
const int index)
|
||||
{
|
||||
int split_at;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* The below is a GNU extension and we can remove it when
|
||||
* we move to a quicksort like in-situ swap with the pivot.
|
||||
*/
|
||||
int arfcns_left[size / 2];
|
||||
int arfcns_right[size / 2];
|
||||
int l_size;
|
||||
int r_size;
|
||||
int l_origin;
|
||||
int r_origin;
|
||||
|
||||
|
||||
/* Test the two recursion anchors and stop processing */
|
||||
if (size == 0)
|
||||
return 0;
|
||||
|
||||
if (size == 1) {
|
||||
out[index] = 1 + arfcns[0];
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Now do the processing */
|
||||
split_at = range_enc_find_index(range, arfcns, size);
|
||||
|
||||
/* we now know where to split */
|
||||
out[index] = 1 + arfcns[split_at];
|
||||
|
||||
/* calculate the work that needs to be done for the leafs */
|
||||
l_origin = mod(arfcns[split_at] + ((range - 1) / 2) + 1, range);
|
||||
r_origin = mod(arfcns[split_at] + 1, range);
|
||||
for (i = 0, l_size = 0, r_size = 0; i < size; ++i) {
|
||||
if (mod(arfcns[i] - l_origin, range) < range / 2)
|
||||
arfcns_left[l_size++] = mod(arfcns[i] - l_origin, range);
|
||||
if (mod(arfcns[i] - r_origin, range) < range / 2)
|
||||
arfcns_right[r_size++] = mod(arfcns[i] - r_origin, range);
|
||||
}
|
||||
|
||||
/*
|
||||
* Now recurse and we need to make this iterative... but as the
|
||||
* tree is balanced the stack will not be too deep.
|
||||
*/
|
||||
range_enc_arfcns(range / 2, arfcns_left, l_size,
|
||||
out, index + greatest_power_of_2_lesser_or_equal_to(index + 1));
|
||||
range_enc_arfcns((range -1 ) / 2, arfcns_right, r_size,
|
||||
out, index + (2 * greatest_power_of_2_lesser_or_equal_to(index + 1)));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The easiest is to use f0 == arfcns[0]. This means that under certain
|
||||
* circumstances we can encode less ARFCNs than possible with an optimal f0.
|
||||
*
|
||||
* TODO: Solve the optimisation problem and pick f0 so that the max distance
|
||||
* is the smallest. Taking into account the modulo operation. I think picking
|
||||
* size/2 will be the optimal arfcn.
|
||||
*/
|
||||
/**
|
||||
* This implements the range determination as described in GSM 04.08 J4. The
|
||||
* result will be a base frequency f0 and the range to use.
|
||||
*
|
||||
* \param[in] arfcns The input frequencies, they must be sorted, lowest number first
|
||||
* \param[in] size The length of the array
|
||||
* \param[out] f0 The selected F0 base frequency. It might not be inside the list
|
||||
*/
|
||||
int range_enc_determine_range(const int *arfcns, const int size, int *f0)
|
||||
{
|
||||
int max = 0;
|
||||
|
||||
/*
|
||||
* Go for the easiest. And pick arfcns[0] == f0.
|
||||
*/
|
||||
max = arfcns[size - 1] - arfcns[0];
|
||||
*f0 = arfcns[0];
|
||||
|
||||
if (max < 128 && size <= 29)
|
||||
return ARFCN_RANGE_128;
|
||||
if (max < 256 && size <= 22)
|
||||
return ARFCN_RANGE_256;
|
||||
if (max < 512 && size <= 18)
|
||||
return ARFCN_RANGE_512;
|
||||
if (max < 1024 && size <= 17)
|
||||
return ARFCN_RANGE_1024;
|
||||
|
||||
return ARFCN_RANGE_INVALID;
|
||||
}
|
||||
|
||||
/*
|
||||
* The below is easier is to write in four methods than
|
||||
* to use the max_bits. The encoding is so screwed.. as
|
||||
* the bits need to be put in place in the wrong order..
|
||||
*/
|
||||
#define HIGH_BITS(w, index, bits, offset) \
|
||||
(w[index - 1] >> (bits - offset))
|
||||
#define LOW_BITS(w, index, bits, offset) \
|
||||
(w[index - 1])
|
||||
|
||||
static void write_orig_arfcn(uint8_t *chan_list, int f0)
|
||||
{
|
||||
chan_list[0] |= (f0 >> 9) & 1;
|
||||
chan_list[1] = (f0 >> 1);
|
||||
chan_list[2] = (f0 & 1) << 7;
|
||||
}
|
||||
|
||||
int range_enc_range128(uint8_t *chan_list, int f0, int *w)
|
||||
{
|
||||
chan_list[0] = 0x8C;
|
||||
write_orig_arfcn(chan_list, f0);
|
||||
|
||||
LOGP(DRR, LOGL_ERROR, "Range128 encoding is not implemented.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int range_enc_range256(uint8_t *chan_list, int f0, int *w)
|
||||
{
|
||||
chan_list[0] = 0x8A;
|
||||
write_orig_arfcn(chan_list, f0);
|
||||
|
||||
LOGP(DRR, LOGL_ERROR, "Range256 encoding is not implemented.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int range_enc_range512(uint8_t *chan_list, int f0, int *w)
|
||||
{
|
||||
struct gsm48_range_512 *range512;
|
||||
write_orig_arfcn(chan_list, f0);
|
||||
|
||||
range512 = (struct gsm48_range_512 *) &chan_list[0];
|
||||
range512->form_id = chan_list[0] = 0x44;
|
||||
|
||||
/* W(1) */
|
||||
range512->w1_hi = HIGH_BITS(w, 1, 9, 7);
|
||||
range512->w1_lo = LOW_BITS (w, 1, 9, 2);
|
||||
/* W(2) */
|
||||
range512->w2_hi = HIGH_BITS(w, 2, 8, 6);
|
||||
range512->w2_lo = LOW_BITS (w, 2, 8, 2);
|
||||
/* W(3) */
|
||||
range512->w3_hi = HIGH_BITS(w, 3, 8, 6);
|
||||
range512->w3_lo = LOW_BITS (w, 3, 8, 2);
|
||||
/* W(4) */
|
||||
range512->w4_hi = HIGH_BITS(w, 4, 7, 6);
|
||||
range512->w4_lo = LOW_BITS (w, 4, 7, 1);
|
||||
/* W(5) */
|
||||
range512->w5 = HIGH_BITS(w, 5, 7, 7);
|
||||
/* W(6) */
|
||||
range512->w6 = HIGH_BITS(w, 6, 7, 7);
|
||||
/* W(7) */
|
||||
range512->w7_hi = HIGH_BITS(w, 7, 7, 1);
|
||||
range512->w7_lo = LOW_BITS (w, 7, 7, 6);
|
||||
/* W(8) */
|
||||
range512->w8_hi = HIGH_BITS(w, 8, 6, 2);
|
||||
range512->w8_lo = LOW_BITS (w, 8, 6, 4);
|
||||
/* W(9) */
|
||||
range512->w9_hi = HIGH_BITS(w, 9, 6, 4);
|
||||
range512->w9_lo = LOW_BITS(w, 9, 6, 2);
|
||||
/* W(10) */
|
||||
range512->w10 = HIGH_BITS(w, 10, 6, 6);
|
||||
/* W(11) */
|
||||
range512->w11 = HIGH_BITS(w, 11, 6, 6);
|
||||
/* W(12) */
|
||||
range512->w12_hi = HIGH_BITS(w, 12, 6, 2);
|
||||
range512->w12_lo = LOW_BITS (w, 12, 6, 4);
|
||||
/* W(13) */
|
||||
range512->w13_hi = HIGH_BITS(w, 13, 6, 4);
|
||||
range512->w13_lo = LOW_BITS(w, 13, 6, 2);
|
||||
/* W(14) */
|
||||
range512->w14 = HIGH_BITS(w, 14, 6, 6);
|
||||
/* W(15) */
|
||||
range512->w15 = HIGH_BITS(w, 15, 6, 6);
|
||||
/* W(16) */
|
||||
range512->w16_hi = HIGH_BITS(w, 16, 5, 2);
|
||||
range512->w16_lo = HIGH_BITS(w, 16, 5, 3);
|
||||
/* W(17) */
|
||||
range512->w17 = HIGH_BITS(w, 17, 5, 5);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int range_enc_range1024(uint8_t *chan_list, int f0, int f0_included, int *w)
|
||||
{
|
||||
chan_list[0] = 0x80 | (f0_included << 2);
|
||||
|
||||
LOGP(DRR, LOGL_ERROR, "Range1024 encoding is not implemented.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int range_enc_filter_arfcns(const int range, int *arfcns,
|
||||
const int size, const int f0, int *f0_included)
|
||||
{
|
||||
int i, j = 0;
|
||||
*f0_included = 0;
|
||||
|
||||
if (range == ARFCN_RANGE_1024) {
|
||||
for (i = 0; i < size; ++i) {
|
||||
if (arfcns[i] == f0) {
|
||||
*f0_included = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* copy and subtract */
|
||||
arfcns[j++] = mod(arfcns[i] - 1, 1024);
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < size; ++i) {
|
||||
/*
|
||||
* Appendix J.4 says the following:
|
||||
* All frequencies except F(0), minus F(0) + 1.
|
||||
* I assume we need to exclude it here.
|
||||
*/
|
||||
if (arfcns[i] == f0)
|
||||
continue;
|
||||
|
||||
arfcns[j++] = mod(arfcns[i] - (f0 + 1), 1024);
|
||||
}
|
||||
}
|
||||
|
||||
return j;
|
||||
}
|
||||
@@ -141,7 +141,7 @@ static void assignment_t10_timeout(void *_conn)
|
||||
* secondary_channel has not been released by the handle_chan_nack.
|
||||
*/
|
||||
if (conn->secondary_lchan)
|
||||
lchan_release(conn->secondary_lchan, 0, 1);
|
||||
lchan_release(conn->secondary_lchan, 0, RSL_REL_LOCAL_END);
|
||||
conn->secondary_lchan = NULL;
|
||||
|
||||
/* inform them about the failure */
|
||||
@@ -155,6 +155,12 @@ static void assignment_t10_timeout(void *_conn)
|
||||
static void handle_mr_config(struct gsm_subscriber_connection *conn,
|
||||
struct gsm_lchan *lchan)
|
||||
{
|
||||
struct bsc_api *api;
|
||||
api = conn->bts->network->bsc_api;
|
||||
|
||||
if (api->mr_config)
|
||||
return api->mr_config(conn, &lchan->mr_conf);
|
||||
|
||||
lchan->mr_conf.ver = 1;
|
||||
lchan->mr_conf.icmi = 1;
|
||||
lchan->mr_conf.m5_90 = 1;
|
||||
@@ -313,17 +319,42 @@ int gsm0808_submit_dtap(struct gsm_subscriber_connection *conn,
|
||||
|
||||
/*
|
||||
* \brief Check if the given channel is compatible with the mode/fullrate
|
||||
*
|
||||
* NOTE: This code is only written with TCH/F and TCH/H in mind. This means
|
||||
* that it will not work for CSD, handover, etc. This also assumes that the
|
||||
* type of the lchan is either a TCH or a SDCCH.
|
||||
*/
|
||||
static int chan_compat_with_mode(struct gsm_lchan *lchan, int chan_mode, int full_rate)
|
||||
{
|
||||
if (lchan->type == GSM_LCHAN_SDCCH)
|
||||
return 1;
|
||||
if (full_rate && lchan->type != GSM_LCHAN_TCH_F)
|
||||
switch (chan_mode) {
|
||||
case GSM48_CMODE_SIGN:
|
||||
/* signalling is always possible */
|
||||
return 1;
|
||||
case GSM48_CMODE_SPEECH_V1:
|
||||
case GSM48_CMODE_SPEECH_AMR:
|
||||
case GSM48_CMODE_DATA_3k6:
|
||||
case GSM48_CMODE_DATA_6k0:
|
||||
/* these services can all run on TCH/H, but we may have
|
||||
* an explicit override by the 'full_rate' argument */
|
||||
switch (lchan->type) {
|
||||
case GSM_LCHAN_TCH_F:
|
||||
return 1;
|
||||
case GSM_LCHAN_TCH_H:
|
||||
if (full_rate)
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case GSM48_CMODE_DATA_12k0:
|
||||
case GSM48_CMODE_DATA_14k5:
|
||||
case GSM48_CMODE_SPEECH_EFR:
|
||||
/* these services all explicitly require a TCH/F */
|
||||
if (lchan->type == GSM_LCHAN_TCH_F)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -341,7 +372,7 @@ int gsm0808_assign_req(struct gsm_subscriber_connection *conn, int chan_mode, in
|
||||
struct bsc_api *api;
|
||||
api = conn->bts->network->bsc_api;
|
||||
|
||||
if (chan_compat_with_mode(conn->lchan, chan_mode, full_rate) != 0) {
|
||||
if (!chan_compat_with_mode(conn->lchan, chan_mode, full_rate)) {
|
||||
if (handle_new_assignment(conn, chan_mode, full_rate) != 0)
|
||||
goto error;
|
||||
} else {
|
||||
@@ -391,7 +422,7 @@ static void handle_ass_compl(struct gsm_subscriber_connection *conn,
|
||||
/* swap channels */
|
||||
osmo_timer_del(&conn->T10);
|
||||
|
||||
lchan_release(conn->lchan, 0, 1);
|
||||
lchan_release(conn->lchan, 0, RSL_REL_LOCAL_END);
|
||||
conn->lchan = conn->secondary_lchan;
|
||||
conn->secondary_lchan = NULL;
|
||||
|
||||
@@ -419,7 +450,7 @@ static void handle_ass_fail(struct gsm_subscriber_connection *conn,
|
||||
|
||||
/* stop the timer and release it */
|
||||
osmo_timer_del(&conn->T10);
|
||||
lchan_release(conn->secondary_lchan, 0, 1);
|
||||
lchan_release(conn->secondary_lchan, 0, RSL_REL_LOCAL_END);
|
||||
conn->secondary_lchan = NULL;
|
||||
|
||||
gh = msgb_l3(msg);
|
||||
@@ -577,6 +608,12 @@ static void dispatch_dtap(struct gsm_subscriber_connection *conn,
|
||||
case GSM48_MT_RR_CLSM_CHG:
|
||||
handle_classmark_chg(conn, msg);
|
||||
break;
|
||||
case GSM48_MT_RR_APP_INFO:
|
||||
/* Passing RR APP INFO to MSC, not quite
|
||||
* according to spec */
|
||||
if (api->dtap)
|
||||
api->dtap(conn, link_id, msg);
|
||||
break;
|
||||
default:
|
||||
/* Normally, a MSC should never receive RR
|
||||
* messages, but we'd rather forward what we
|
||||
@@ -618,7 +655,7 @@ int gsm0408_rcvmsg(struct msgb *msg, uint8_t link_id)
|
||||
rc = BSC_API_CONN_POL_REJECT;
|
||||
lchan->conn = subscr_con_allocate(msg->lchan);
|
||||
if (!lchan->conn) {
|
||||
lchan_release(lchan, 1, 0);
|
||||
lchan_release(lchan, 1, RSL_REL_NORMAL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -628,7 +665,7 @@ int gsm0408_rcvmsg(struct msgb *msg, uint8_t link_id)
|
||||
if (rc != BSC_API_CONN_POL_ACCEPT) {
|
||||
lchan->conn->lchan = NULL;
|
||||
subscr_con_free(lchan->conn);
|
||||
lchan_release(lchan, 1, 0);
|
||||
lchan_release(lchan, 1, RSL_REL_NORMAL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -667,10 +704,10 @@ int gsm0808_clear(struct gsm_subscriber_connection *conn)
|
||||
bsc_clear_handover(conn, 1);
|
||||
|
||||
if (conn->secondary_lchan)
|
||||
lchan_release(conn->secondary_lchan, 0, 1);
|
||||
lchan_release(conn->secondary_lchan, 0, RSL_REL_LOCAL_END);
|
||||
|
||||
if (conn->lchan)
|
||||
lchan_release(conn->lchan, 1, 0);
|
||||
lchan_release(conn->lchan, 1, RSL_REL_NORMAL);
|
||||
|
||||
conn->lchan = NULL;
|
||||
conn->secondary_lchan = NULL;
|
||||
|
||||
@@ -43,8 +43,6 @@ extern int hsl_setup(struct gsm_network *gsmnet);
|
||||
/* Callback function for NACK on the OML NM */
|
||||
static int oml_msg_nack(struct nm_nack_signal_data *nack)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (nack->mt == NM_MT_SET_BTS_ATTR_NACK) {
|
||||
|
||||
LOGP(DNM, LOGL_ERROR, "Failed to set BTS attributes. That is fatal. "
|
||||
@@ -58,12 +56,14 @@ static int oml_msg_nack(struct nm_nack_signal_data *nack)
|
||||
return 0;
|
||||
|
||||
drop_bts:
|
||||
for (i = 0; i < bsc_gsmnet->num_bts; ++i) {
|
||||
struct gsm_bts *bts = gsm_bts_num(bsc_gsmnet, i);
|
||||
if (is_ipaccess_bts(bts))
|
||||
ipaccess_drop_oml(bts);
|
||||
if (!nack->bts) {
|
||||
LOGP(DNM, LOGL_ERROR, "Unknown bts. Can not drop it.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (is_ipaccess_bts(nack->bts))
|
||||
ipaccess_drop_oml(nack->bts);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -124,6 +124,7 @@ static int rsl_si(struct gsm_bts_trx *trx, enum osmo_sysinfo_type i, int si_len)
|
||||
osmo_sitype2rsl(i),
|
||||
GSM_BTS_SI(bts, i), si_len);
|
||||
}
|
||||
rc = 0;
|
||||
} else
|
||||
rc = rsl_sacch_filling(trx, osmo_sitype2rsl(i),
|
||||
GSM_BTS_SI(bts, i), si_len);
|
||||
@@ -175,9 +176,11 @@ static int set_system_infos(struct gsm_bts_trx *trx)
|
||||
|
||||
for (n = 0; n < n_si; n++) {
|
||||
i = gen_si[n];
|
||||
bts->si_valid |= (1 << i);
|
||||
/* Only generate SI if this SI is not in "static" (user-defined) mode */
|
||||
if (!(bts->si_mode_static & (1 << i))) {
|
||||
/* Set SI as being valid. gsm_generate_si() might unset
|
||||
* it, if SI is not required. */
|
||||
bts->si_valid |= (1 << i);
|
||||
rc = gsm_generate_si(bts, i);
|
||||
if (rc < 0)
|
||||
goto err_out;
|
||||
@@ -195,10 +198,10 @@ static int set_system_infos(struct gsm_bts_trx *trx)
|
||||
|
||||
/* Third, we send the selected SI via RSL */
|
||||
|
||||
for (i = SYSINFO_TYPE_1; i < _MAX_SYSINFO_TYPE; i++) {
|
||||
for (n = 0; n < n_si; n++) {
|
||||
i = gen_si[n];
|
||||
if (!(bts->si_valid & (1 << i)))
|
||||
continue;
|
||||
|
||||
rc = rsl_si(trx, i, si_len[i]);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
@@ -206,9 +209,9 @@ static int set_system_infos(struct gsm_bts_trx *trx)
|
||||
|
||||
return 0;
|
||||
err_out:
|
||||
LOGP(DRR, LOGL_ERROR, "Cannot generate SI %u for BTS %u, most likely "
|
||||
LOGP(DRR, LOGL_ERROR, "Cannot generate SI%s for BTS %u, most likely "
|
||||
"a problem with neighbor cell list generation\n",
|
||||
i, bts->nr);
|
||||
get_value_string(osmo_sitype_strs, i), bts->nr);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -418,10 +421,7 @@ static int bootstrap_bts(struct gsm_bts *bts)
|
||||
"GSM networks and should only be used in a RF "
|
||||
"shielded environment such as a faraday cage!\n\n");
|
||||
|
||||
/* Control Channel Description */
|
||||
bts->si_common.chan_desc.att = 1;
|
||||
bts->si_common.chan_desc.bs_pa_mfrms = RSL_BS_PA_MFRMS_5;
|
||||
bts->si_common.chan_desc.bs_ag_blks_res = 1;
|
||||
/* Control Channel Description is set from vty/config */
|
||||
|
||||
/* T3212 is set from vty/config */
|
||||
|
||||
@@ -432,6 +432,9 @@ static int bootstrap_bts(struct gsm_bts *bts)
|
||||
switch (n) {
|
||||
case 0:
|
||||
bts->si_common.chan_desc.ccch_conf = RSL_BCCH_CCCH_CONF_1_C;
|
||||
/* Limit reserved block to 2 on combined channel */
|
||||
if (bts->si_common.chan_desc.bs_ag_blks_res > 2)
|
||||
bts->si_common.chan_desc.bs_ag_blks_res = 2;
|
||||
break;
|
||||
case 1:
|
||||
bts->si_common.chan_desc.ccch_conf = RSL_BCCH_CCCH_CONF_1_NC;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user