diff options
author | Oliver Smith <osmith@sysmocom.de> | 2021-02-01 12:48:48 +0100 |
---|---|---|
committer | osmith <osmith@sysmocom.de> | 2021-02-08 11:52:53 +0000 |
commit | 901ed14c898ef229c654009ac0dc078d09d7b054 (patch) | |
tree | bb23d5be682970a6a6a764b1b8c23f4e95d1cc96 | |
parent | 4be5ab37071d8102c133d65546b76117d1da18f1 (diff) |
gbproxy: remove (moved to own repository)
New repository:
https://git.osmocom.org/osmo-gbproxy/
Related: OS#4992
Change-Id: I37f7cebaf2a06bd93627a452f5df44edcfc0f87a
42 files changed, 5 insertions, 6710 deletions
diff --git a/.gitignore b/.gitignore index 466a744c2..3626a5a62 100644 --- a/.gitignore +++ b/.gitignore @@ -41,7 +41,6 @@ ltmain.sh # apps and app data src/sgsn/osmo-sgsn -src/gbproxy/osmo-gbproxy src/gtphub/osmo-gtphub src/libcommon/gsup_test_client diff --git a/configure.ac b/configure.ac index f1a4ed480..947ecf152 100644 --- a/configure.ac +++ b/configure.ac @@ -259,7 +259,6 @@ AC_OUTPUT( src/Makefile src/gprs/Makefile src/sgsn/Makefile - src/gbproxy/Makefile src/gtphub/Makefile tests/Makefile tests/atlocal diff --git a/contrib/gprs/gb-proxy-unblock-bug.py b/contrib/gprs/gb-proxy-unblock-bug.py deleted file mode 100755 index 0cd4b871f..000000000 --- a/contrib/gprs/gb-proxy-unblock-bug.py +++ /dev/null @@ -1,58 +0,0 @@ -#!/usr/bin/env python - -""" -demonstrate a unblock bug on the GB Proxy.. -""" - -bts_ns_reset = "\x02\x00\x81\x01\x01\x82\x1f\xe7\x04\x82\x1f\xe7" -ns_reset_ack = "\x03\x01\x82\x1f\xe7\x04\x82\x1f\xe7" - -bts_ns_unblock = "\x06" -ns_unblock_ack = "\x07" - -bts_bvc_reset_0 = "\x00\x00\x00\x00\x22\x04\x82\x00\x00\x07\x81\x03\x3b\x81\x02" -ns_bvc_reset_0_ack = "\x00\x00\x00\x00\x23\x04\x82\x00\x00" - -bts_bvc_reset_8167 = "\x00\x00\x00\x00\x22\x04\x82\x1f\xe7\x07\x81\x08\x08\x88\x72\xf4\x80\x10\x1c\x00\x9c\x40" - - -import socket -socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) -socket.bind(("0.0.0.0", 0)) -socket.setblocking(1) - - -import sys -port = int(sys.argv[1]) -print "Sending data to port: %d" % port - -def send_and_receive(packet): - socket.sendto(packet, ("127.0.0.1", port)) - - try: - data, addr = socket.recvfrom(4096) - except socket.error, e: - print "ERROR", e - import sys - sys.exit(0) - return data - -#send stuff once - -to_send = [ - (bts_ns_reset, ns_reset_ack, "reset ack"), - (bts_ns_unblock, ns_unblock_ack, "unblock ack"), - (bts_bvc_reset_0, ns_bvc_reset_0_ack, "BVCI=0 reset ack"), -] - - -for (out, inp, type) in to_send: - res = send_and_receive(out) - if res != inp: - print "Failed to get the %s" % type - sys.exit(-1) - -import time -time.sleep(3) -res = send_and_receive(bts_bvc_reset_8167) -print "Sent all messages... check wireshark for the last response" diff --git a/contrib/osmo-sgsn.spec.in b/contrib/osmo-sgsn.spec.in index ca66e2ea9..cd3b5b7bf 100644 --- a/contrib/osmo-sgsn.spec.in +++ b/contrib/osmo-sgsn.spec.in @@ -61,14 +61,6 @@ Group: Productivity/Telephony/Servers %description -n osmo-gtphub Osmocom GTP Hub: Proxy for GTP traffic between multiple SGSNs and GGSNs. -%package -n osmo-gbproxy -Summary: Osmocom GPRS Gb Interface Proxy -Group: Productivity/Telephony/Servers - -%description -n osmo-gbproxy -The purpose of the Gb proxy is to aggregate the Gb links of multiple -BSS's and present them in one Gb link to the SGSN. - %prep %setup -q @@ -95,10 +87,6 @@ make %{?_smp_mflags} %postun -n osmo-gtphub %service_del_postun osmo-gtphub.service %pre -n osmo-gtphub %service_add_pre osmo-gtphub.service %post -n osmo-gtphub %service_add_post osmo-gtphub.service -%preun -n osmo-gbproxy %service_del_preun osmo-gbproxy.service -%postun -n osmo-gbproxy %service_del_postun osmo-gbproxy.service -%pre -n osmo-gbproxy %service_add_pre osmo-gbproxy.service -%post -n osmo-gbproxy %service_add_post osmo-gbproxy.service %endif %check @@ -109,7 +97,6 @@ make %{?_smp_mflags} check || (find . -name testsuite.log -exec cat {} +) %dir %{_docdir}/%{name}/examples %dir %{_docdir}/%{name}/examples/osmo-sgsn %exclude %{_docdir}/%{name}/examples/osmo-gtphub -%exclude %{_docdir}/%{name}/examples/osmo-gbproxy %{_docdir}/%{name}/examples/osmo-sgsn/osmo-sgsn-accept-all.cfg %{_docdir}/%{name}/examples/osmo-sgsn/osmo-sgsn.cfg %{_docdir}/%{name}/examples/osmo-sgsn/osmo-sgsn_custom-sccp.cfg @@ -128,13 +115,4 @@ make %{?_smp_mflags} check || (find . -name testsuite.log -exec cat {} +) %config(noreplace) %{_sysconfdir}/osmocom/osmo-gtphub.cfg %{_unitdir}/osmo-gtphub.service -%files -n osmo-gbproxy -%dir %{_docdir}/%{name}/examples -%dir %{_docdir}/%{name}/examples/osmo-gbproxy -%{_docdir}/%{name}/examples/osmo-gbproxy/osmo-gbproxy.cfg -%{_bindir}/osmo-gbproxy -%dir %{_sysconfdir}/osmocom -%config(noreplace) %{_sysconfdir}/osmocom/osmo-gbproxy.cfg -%{_unitdir}/osmo-gbproxy.service - %changelog diff --git a/contrib/systemd/Makefile.am b/contrib/systemd/Makefile.am index 11e8f9815..ae4694c2a 100644 --- a/contrib/systemd/Makefile.am +++ b/contrib/systemd/Makefile.am @@ -1,11 +1,9 @@ EXTRA_DIST = \ - osmo-gbproxy.service \ osmo-gtphub.service \ osmo-sgsn.service if HAVE_SYSTEMD SYSTEMD_SERVICES = \ - osmo-gbproxy.service \ osmo-gtphub.service \ osmo-sgsn.service diff --git a/contrib/systemd/osmo-gbproxy.service b/contrib/systemd/osmo-gbproxy.service deleted file mode 100644 index a0b7829db..000000000 --- a/contrib/systemd/osmo-gbproxy.service +++ /dev/null @@ -1,12 +0,0 @@ -[Unit] -Description=Osmocom Gb proxy - -[Service] -Type=simple -ExecStart=/usr/bin/osmo-gbproxy -c /etc/osmocom/osmo-gbproxy.cfg -Restart=always -RestartSec=2 -RestartPreventExitStatus=1 - -[Install] -WantedBy=multi-user.target diff --git a/debian/control b/debian/control index e512c8fb6..fe2f1e63f 100644 --- a/debian/control +++ b/debian/control @@ -53,22 +53,6 @@ Priority: extra Depends: osmo-gtphub (= ${binary:Version}), ${misc:Depends} Description: Debug symbols for Osmocom GTP Hub -Package: osmo-gbproxy -Architecture: any -Depends: ${shlibs:Depends}, - ${misc:Depends} -Recommends: osmo-sgsn -Description: Osmocom GPRS Gb Interface Proxy - The purpose of the Gb proxy is to aggregate the Gb links of multiple - BSS's and present them in one Gb link to the SGSN. - -Package: osmo-gbproxy-dbg -Architecture: any -Section: debug -Priority: extra -Depends: osmo-gbproxy (= ${binary:Version}), ${misc:Depends} -Description: Debug symbols for Osmocom GPRS Gb Interface Proxy - Package: osmo-sgsn-doc Architecture: all Section: doc diff --git a/debian/copyright b/debian/copyright index 5bc764d67..dd7b6672b 100644 --- a/debian/copyright +++ b/debian/copyright @@ -19,12 +19,10 @@ Files: .gitignore contrib/ipa.py contrib/jenkins.sh contrib/soap.py - contrib/systemd/osmo-gbproxy.service contrib/systemd/osmo-sgsn.service contrib/twisted_ipa.py doc/Makefile.am doc/examples/Makefile.am - doc/examples/osmo-gbproxy/osmo-gbproxy.cfg doc/examples/osmo-gtphub/gtphub-example.txt doc/examples/osmo-gtphub/osmo-gtphub-1iface.cfg doc/examples/osmo-gtphub/osmo-gtphub.cfg @@ -50,8 +48,6 @@ Files: .gitignore src/gprs/osmo_sgsn.cfg tests/Makefile.am tests/atlocal.in - tests/gbproxy/Makefile.am - tests/gbproxy/gbproxy_test.ok tests/gprs/Makefile.am tests/gprs/gprs_test.c tests/gprs/gprs_test.ok @@ -85,10 +81,6 @@ Files: include/osmocom/sgsn/a_reset.h src/gprs/gprs_gb_parse.c src/gprs/gprs_utils.c src/gprs/sgsn_ares.c - src/gbproxy/gb_proxy.c - src/gbproxy/gb_proxy_main.c - src/gbproxy/gb_proxy_peer.c - src/gbproxy/gb_proxy_vty.c src/gtphub/gtphub.c src/gtphub/gtphub_main.c src/gtphub/gtphub_vty.c @@ -139,7 +131,6 @@ License: AGPL-3.0+ Files: src/gtphub/gtphub_ares.c src/gtphub/gtphub_sock.c - tests/gbproxy/gbproxy_test.c Copyright: 2013 Jacob Erlbeck <jerlbeck@sysmocom.de> 2013 sysmocom s.f.m.c. GmbH 2014 Holger Hans Peter Freyther diff --git a/debian/osmo-gbproxy.init b/debian/osmo-gbproxy.init deleted file mode 100755 index 924f32d10..000000000 --- a/debian/osmo-gbproxy.init +++ /dev/null @@ -1,151 +0,0 @@ -#!/bin/sh -### BEGIN INIT INFO -# Provides: osmo-gbproxy -# Required-Start: $network $local_fs -# Required-Stop: -# Default-Start: 2 3 4 5 -# Default-Stop: 0 1 6 -# Short-Description: Osmocom GBproxy -# Description: A tool to proxy the GPRS Gb interface. -### 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-gbproxy # Introduce the short server's name here -DESC="Osmocom GBProxy" # Introduce a short description here -DAEMON=/usr/bin/osmo-gbproxy # Introduce the server's location here -SCRIPTNAME=/etc/init.d/osmocom-gbproxy -CONFIG_FILE=/etc/osmocom/osmocom-gbproxy.cfg - -# Exit if the package is not installed -[ -x $DAEMON ] || exit 0 - -# Read configuration variable file if it is present -[ -r /etc/default/osmocom-gbproxy ] && . /etc/default/osmocom-gbproxy - -# 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="-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 - -: diff --git a/debian/osmo-gbproxy.install b/debian/osmo-gbproxy.install deleted file mode 100644 index 1cb91d5d4..000000000 --- a/debian/osmo-gbproxy.install +++ /dev/null @@ -1,4 +0,0 @@ -etc/osmocom/osmo-gbproxy.cfg -lib/systemd/system/osmo-gbproxy.service -usr/bin/osmo-gbproxy -usr/share/doc/osmo-sgsn/examples/osmo-gbproxy/osmo-gbproxy.cfg usr/share/doc/osmo-gbproxy/examples diff --git a/debian/rules b/debian/rules index cfd692a48..24161a190 100755 --- a/debian/rules +++ b/debian/rules @@ -58,7 +58,6 @@ override_dh_auto_configure: override_dh_strip: dh_strip -posmo-sgsn --dbg-package=osmo-sgsn-dbg dh_strip -posmo-gtphub --dbg-package=osmo-gtphub-dbg - dh_strip -posmo-gbproxy --dbg-package=osmo-gbproxy-dbg # Print test results in case of a failure override_dh_auto_test: diff --git a/doc/examples/Makefile.am b/doc/examples/Makefile.am index 2b5781a59..c725bc1ad 100644 --- a/doc/examples/Makefile.am +++ b/doc/examples/Makefile.am @@ -1,7 +1,7 @@ OSMOCONF_FILES = \ osmo-gtphub/osmo-gtphub.cfg \ osmo-sgsn/osmo-sgsn.cfg \ - osmo-gbproxy/osmo-gbproxy.cfg + $(NULL) osmoconfdir = $(sysconfdir)/osmocom osmoconf_DATA = $(OSMOCONF_FILES) diff --git a/doc/examples/osmo-gbproxy/osmo-gbproxy-legacy.cfg b/doc/examples/osmo-gbproxy/osmo-gbproxy-legacy.cfg deleted file mode 100644 index e30b9f7fe..000000000 --- a/doc/examples/osmo-gbproxy/osmo-gbproxy-legacy.cfg +++ /dev/null @@ -1,42 +0,0 @@ -! -! OsmoGbProxy (UNKNOWN) configuration saved from vty -!! -! -log stderr - logging filter all 1 - logging color 1 - logging timestamp 0 - logging level all debug - logging level gprs debug - logging level ns info - logging level bssgp debug - logging level lglobal notice - logging level llapd notice - logging level linp notice - logging level lmux notice - logging level lmi notice - logging level lmib notice - logging level lsms notice -! -line vty - no login -! -ns - bind udp local - listen 127.0.0.1 23000 - accept-ipaccess - nse 666 - nsvc ipa local 127.0.0.1 23001 nsvci 666 - timer tns-block 3 - timer tns-block-retries 3 - timer tns-reset 3 - timer tns-reset-retries 3 - timer tns-test 30 - timer tns-alive 3 - timer tns-alive-retries 10 -gbproxy - sgsn nsei 666 - core-mobile-country-code 666 - core-mobile-network-code 6 - core-access-point-name none match-imsi ^666066|^66607 - tlli-list max-length 200 diff --git a/doc/examples/osmo-gbproxy/osmo-gbproxy-pool.cfg b/doc/examples/osmo-gbproxy/osmo-gbproxy-pool.cfg deleted file mode 100644 index bbc8a1b70..000000000 --- a/doc/examples/osmo-gbproxy/osmo-gbproxy-pool.cfg +++ /dev/null @@ -1,32 +0,0 @@ -! -! Osmocom Gb Proxy (0.9.0.404-6463) configuration saved from vty -!! -! -line vty - no login -! -gbproxy - nri bitlen 4 - nri null add 0 4 -sgsn nsei 101 - name main - nri add 1 - nri add 11 -sgsn nsei 102 - nri add 2 - nri add 12 -ns - bind udp local - listen 127.0.0.100 23000 - accept-ipaccess - nse 101 - nsvc ipa local 192.168.100.239 7777 nsvci 101 - nse 102 - nsvc ipa local 192.168.100.239 7778 nsvci 102 - timer tns-block 3 - timer tns-block-retries 3 - timer tns-reset 3 - timer tns-reset-retries 3 - timer tns-test 30 - timer tns-alive 3 - timer tns-alive-retries 10 diff --git a/doc/examples/osmo-gbproxy/osmo-gbproxy.cfg b/doc/examples/osmo-gbproxy/osmo-gbproxy.cfg deleted file mode 100644 index 777d0b0f9..000000000 --- a/doc/examples/osmo-gbproxy/osmo-gbproxy.cfg +++ /dev/null @@ -1,23 +0,0 @@ -! -! Osmocom Gb Proxy (0.9.0.404-6463) configuration saved from vty -!! -! -line vty - no login -! -gbproxy -sgsn nsei 101 - name main -ns - bind udp local - listen 127.0.0.100 23000 - accept-ipaccess - nse 101 - nsvc ipa local 192.168.100.239 7777 nsvci 101 - timer tns-block 3 - timer tns-block-retries 3 - timer tns-reset 3 - timer tns-reset-retries 3 - timer tns-test 30 - timer tns-alive 3 - timer tns-alive-retries 10 diff --git a/doc/manuals/Makefile.am b/doc/manuals/Makefile.am index cd57cf148..bc3449743 100644 --- a/doc/manuals/Makefile.am +++ b/doc/manuals/Makefile.am @@ -1,21 +1,17 @@ EXTRA_DIST = osmosgsn-usermanual.adoc \ osmosgsn-usermanual-docinfo.xml \ osmosgsn-vty-reference.xml \ - osmogbproxy-usermanual.adoc \ - osmogbproxy-usermanual-docinfo.xml \ regen_doc.sh \ chapters \ vty \ - osmogbproxy-vty-reference.xml \ - vty-osmogbproxy \ $(NULL) if BUILD_MANUALS - ASCIIDOC = osmosgsn-usermanual.adoc osmogbproxy-usermanual.adoc + ASCIIDOC = osmosgsn-usermanual.adoc ASCIIDOC_DEPS = $(srcdir)/chapters/*.adoc include $(OSMO_GSM_MANUALS_DIR)/build/Makefile.asciidoc.inc - VTY_REFERENCE = osmosgsn-vty-reference.xml osmogbproxy-vty-reference.xml + VTY_REFERENCE = osmosgsn-vty-reference.xml include $(OSMO_GSM_MANUALS_DIR)/build/Makefile.vty-reference.inc OSMO_REPOSITORY = osmo-sgsn diff --git a/doc/manuals/chapters/gbproxy-configuration.adoc b/doc/manuals/chapters/gbproxy-configuration.adoc deleted file mode 100644 index 87da471ff..000000000 --- a/doc/manuals/chapters/gbproxy-configuration.adoc +++ /dev/null @@ -1,41 +0,0 @@ -== Configuring OsmoGbProxy - -OsmoGbProxy requires very little configuration, most of it being the -configuration of the NS links. -Most config options specific to OsmoGbProxy are related to SGSN pooling and -telling the proxy which NSE(s) it should use to talk to the SGSN(s). - -=== Configure the Network Service (NS) - -A detailed description of the NS configuration can be found in <<libosmogb>>. -The following config snippets assume the SGSN(s) (NSEI 101 and 102) are using -IP-SNS and listen on 10.0.1.1:23000 and 10.0.1.2:23000 respectively. - -This would be the NS config for the SGSN(s): - -.Example: NS configuration example (SGSN) ----- -ns - bind udp local - listen 10.0.0.1 23000 <1> - nse 101 <2> - ip-sns 10.0.1.1 23000 <3> - nse 102 - ip-sns 10.0.1.2 23000 ----- -<1> Define the local IP/port from which to connect -<2> Define an NSE with NSEI -<3> Use IP-SNS to connect to the SGSN - -=== Configure an SGSN - -Configuration of a single (non-pooling) SGSN is rather simple. - -.Example: SGSN configuration example ----- -sgsn 101 <1> - name Main SGSN <2> ----- -<1> Each SGSN is identified by its NSEI (same as in the NS configuration) -<2> An SGSN can optionally have a name. If none is set a default name will be used. - diff --git a/doc/manuals/chapters/gbproxy-control.adoc b/doc/manuals/chapters/gbproxy-control.adoc deleted file mode 100644 index 2f83e6add..000000000 --- a/doc/manuals/chapters/gbproxy-control.adoc +++ /dev/null @@ -1,29 +0,0 @@ -[[control]] -== Control interface - -The actual protocol is described in <<common-control-if>>, the variables -common to all programs using it are described in <<ctrl_common_vars>>. Here we -describe variables specific to OsmoGbProxy. - -.Variables available over control interface -[options="header",width="100%",cols="20%,5%,5%,50%,20%"] -|=== -|Name|Access|Trap|Value|Comment -|nsvc-state|RO|No|"<nsei>,<nsvci>,<local-alive>,<local-blocked>,<remote-role>,<remote-alive>,<remote-blocked>"|See <<nsvc_state>> for details. -|gbproxy-state|RO|No|"<nsei>,<bvci>,<mcc>,<mnc>,<lac>,<rac>,<blocked>"|See <<gbproxy_state>> for details. -|number-of-peers|RO|No|"<num-of-bss>"|Count of concurrent BSS(BTS) peers. -|=== - -[[nsvc_state]] -=== nsvc-state - -Return the list of active NS-VCs (NS Virtual Circuits), including information -on the key parameters, such as NSEI, NSVCI and the local + remote ALIVE -and BLOCKED state. - -[[gbproxy_state]] -=== gbproxy-state - -Return the list of active Peers, including information on the key -parameters, such as NSEI, BVCI, and the MCC-MNC-LAC-RAC of the attached -BSS, as well as the overall state (BLOCKED or UNBLOCKED). diff --git a/doc/manuals/chapters/gbproxy-details.adoc b/doc/manuals/chapters/gbproxy-details.adoc deleted file mode 100644 index f77d40cf9..000000000 --- a/doc/manuals/chapters/gbproxy-details.adoc +++ /dev/null @@ -1,113 +0,0 @@ -[[chapter_details]] -== Proxy details - -=== BVC handling - -This section describes in more detail how BVCs are handled in OsmoGbProxy - -If a BSS connects to OsmoGbProxy while the SGSN is not available it will -acknowledge the BVC RESET on the signalling BVC, but ignore other messages -(especially any PTP BVC RESET). - -.BSS connects to OsmoGbProxy -[mscgen] ----- -msc { - hscale="1.8"; - bss1 [label="BSS1"], bss2 [label="BSS2"], gbproxy [label="GbProxy"], sgsn [label="SGSN"]; - bss1 <=> gbproxy [label="NS link available"]; - bss1 => gbproxy [label="BVC RESET (BVCI=0)"]; - gbproxy => bss1 [label="BVC RESET ACK"]; - bss1 -x gbproxy [label="PTP BVC RESET (ignored)"]; -} ----- - -As soon as the SGSN is reachable through NS OsmoGbProxy will send a BVC RESET -to the signalling BVC towards the SGSN. After that completes it will reset the -signalling BVC of all BSS connections. At this point the BSS will send a BVC -RESET for its PTP BVCs which will be forwarded to the SGSN, similarly the PTP -BVC RESET ACK from the SGSN will be sent back to the BSS. - -.SGSN connection to OsmoGbProxy -[mscgen] ----- -msc { - hscale="1.8"; - bss1 [label="BSS1"], bss2 [label="BSS2"], gbproxy [label="GbProxy"], sgsn [label="SGSN"]; - gbproxy <=> sgsn [label="NS link available"]; - gbproxy => sgsn [label="BVC RESET (BVCI=0)"]; - sgsn => gbproxy [label="BVC RESET ACK"]; - - gbproxy => bss1 [label="BVC RESET (BVCI=0)"]; - bss1 => gbproxy [label="BVC RESET ACK"]; - bss1 box bss1 [label="PTP BVCs need to be reset"]; - bss1 => gbproxy [label="PTP BVC RESET (BVCI=x)"]; - gbproxy => sgsn [label="PTP BVC RESET (BVCI=x)"]; - sgsn => gbproxy [label="PTP BVC RESET ACK (BVCI=x)"]; - gbproxy => bss1 [label="PTP BVC RESET ACK (BVCI=x)"]; - bss2 <=> sgsn [label="BVCI x established"]; -} ----- - -The communication on the PTP BVC will then be forwarded between the BSS and the -SGSN. - -If a BSS connects while the SGSN is up the PTP BVC RESET will directly be -forwarded. - -.BSS connects to OsmoGbProxy -[mscgen] ----- -msc { - hscale="1.8"; - bss1 [label="BSS1"], bss2 [label="BSS2"], gbproxy [label="GbProxy"], sgsn [label="SGSN"]; - bss2 <=> gbproxy [label="NS link available"]; - bss2 => gbproxy [label="BVC RESET (BVCI=0)"]; - gbproxy => bss2 [label="BVC RESET ACK"]; - bss2 => gbproxy [label="PTP BVC RESET (BVCI=y)"]; - gbproxy => sgsn [label="PTP BVC RESET (BVCI=y)"]; - sgsn => gbproxy [label="PTP BVC RESET ACK (BVCI=y)"]; - gbproxy => bss2 [label="PTP BVC RESET ACK (BVCI=y)"]; - bss2 <=> sgsn [label="BVCI y established"]; -} ----- - -If OsmoGbProxy looses the connection to the SGSN it will reset the signalling -BVC of all BSS connections. This ensures that the BSS will not send traffic -over a PTP BVC before its reset procedure has been completed. - -.SGSN connection fails -[mscgen] ----- -msc { - hscale="1.8"; - bss1 [label="BSS1"], bss2 [label="BSS2"], gbproxy [label="GbProxy"], sgsn [label="SGSN"]; - gbproxy <=> sgsn [label="NS link fails"]; - gbproxy => bss1 [label="BVC RESET (BVCI=0)"]; - gbproxy => bss2 [label="BVC RESET (BVCI=0)"]; -} ----- - -When the connection to the SGSN is eventually restored the signalling BVC -between OsmoGbProxy and SGSN will be reset. - -After that completes OsmoGbProxy will reset the signalling BVC on all BSS NS -connections and forward the PTP BVC RESET messages. - -.SGSN connection restored -[mscgen] ----- -msc { - hscale="1.8"; - bss1 [label="BSS1"], bss2 [label="BSS2"], gbproxy [label="GbProxy"], sgsn [label="SGSN"]; - gbproxy <=> sgsn [label="NS link available"]; - gbproxy => sgsn [label="BVC RESET (BVCI=0)"]; - sgsn => gbproxy [label="BVC RESET ACK"]; - gbproxy => bss1 [label="BVC RESET (BVCI=0)"]; - bss1 => gbproxy [label="BVC RESET ACK"]; - bss1 box bss1 [label="PTP BVCs need to be reset"]; - gbproxy => bss2 [label="BVC RESET (BVCI=0)"]; - bss2 => gbproxy [label="BVC RESET ACK"]; - bss2 box bss2 [label="PTP BVCs need to be reset"]; -} ----- diff --git a/doc/manuals/chapters/gbproxy-overview.adoc b/doc/manuals/chapters/gbproxy-overview.adoc deleted file mode 100644 index 3cd0d73c8..000000000 --- a/doc/manuals/chapters/gbproxy-overview.adoc +++ /dev/null @@ -1,95 +0,0 @@ -[[chapter_overview]] -== Overview - -IMPORTANT: If you have used an earlier version of OsmoGbProxy please note -that support for various features such as PLMN/APN patching, support for a -secondary SGSN has been removed. - -=== About OsmoGbProxy - -OsmoGbProxy is the Osmocom proxy for the 3GPP Gb interface. The Gb -interface is defined by 3GPP as the protocol between the BSS and the -SGSN inside the 2G/2.5G/2.75G packet switched network domain. - -As Osmocom implements a BTS-colocated PCU, there are potentially many -Gb interface connections between all those many PCUs in the network -and the SGSN. This can be cumbersome to configure/maintain at the -SGSN side. - -OsmoGbProxy aggregates many PCU-facing Gb connections into one Gb -connection to the SGSN. This is achieved by - -* maintaining separate NS-VCs on the PCU side and on the SGSN side -* more or less transparently routing BSSGP peer-to-peer Virtual Circuits - (BVCs) through the proxy -* having some special handling for the signaling BVC (BVCI=0) which is - shared among all the PCUs connected to the proxy - - -=== Data Model - -==== gbproxy_config - -This contains the parsed configuration of the OsmoGbProxy. - -==== gbproxy_nse - -The remote NS-entity that the proxy interacts with. Includes -information about: - -* the [unique] NSEI of the peer -* the Routeing Area (RA) of the peer -* which side this NSE is facing - SGSN or BSS -* the list of BVCs in this NSE - -==== gbproxy_bvc - -A ptp-BVC on an NSE - -* the BVCI of this BVC -* the routing area of this BVC -* the BVC state machine - -==== gbproxy_cell - -This contains a view of the cell and its associated BVCs - -* the unique BVCI of this cell -* the routing area of this cell -* one bss-side BVC -* one BVC per SGSN in the pool - -==== gbproxy_sgsn - -Represents one SGSN in the pool. Contains: - -* the NSE belonging to this SGSN -* a (configurable) name of the SGSN -* pool-related configuration of the SGSNs - -==== IMSI cache - -In order to route messages to the correct BSS or SGSN OsmoGbProxy -sometimes needs to cache where messages came from. - -In BSS->SGSN direction the IMSI-cache is needed for - -* paging ps reject -* dummy paging response - -when SGSN-pooling is enabled and multiple SGSNs are configured. The IMSI -contained in a paging ps or dummy paging message is cached together with -the originating SGSN/NSE. The answer, which also contains the IMSI, is -then routed back to the original SGSN. - -==== TLLI cache - -In SGSN->BSS direction OsmoGbProxy needs a TLLI cache to correctly route the -following messages: - -* suspend ack/nack -* resume ack/nack - -Suspend/resume are sent over the signalling BVC to the SGSN. OsmoGbProxy saves -the TLLI->NSE association in the TLLI cache and routes the ack/nack back to -the signalling BVC of the originating NSE.
\ No newline at end of file diff --git a/doc/manuals/chapters/gbproxy-running.adoc b/doc/manuals/chapters/gbproxy-running.adoc deleted file mode 100644 index 1f6b6a1bb..000000000 --- a/doc/manuals/chapters/gbproxy-running.adoc +++ /dev/null @@ -1,39 +0,0 @@ -== Running OsmoGbProxy - -The OsmoGbProxy executable (`osmo-gbproxy`) offers the following command-line -options: - - -=== SYNOPSIS - -*osmo-gbproxy* [-h|-V] [-d 'DBGMASK'] [-D] [-c 'CONFIGFILE'] [-s] [-e 'LOGLEVEL'] [-T] - - -=== OPTIONS - -*-h, --help*:: - Print a short help message about the supported options -*-V, --version*:: - Print the compile-time version number of the program -*-d, --debug 'DBGMASK','DBGLEVELS'*:: - Set the log subsystems and levels for logging to stderr. This - has mostly been superseded by VTY-based logging configuration, - see <<logging>> for further information. -*-D, --daemonize*:: - Fork the process as a daemon into background. -*-c, --config-file 'CONFIGFILE'*:: - Specify the file and path name of the configuration file to be - used. If none is specified, use `osmo_sgsn.cfg` in the current - working directory. -*-s, --disable-color*:: - Disable colors for logging to stderr. This has mostly been - deprecated by VTY based logging configuration, see <<logging>> - for more information. -*-e, --log-level 'LOGLEVEL'*:: - Set the global log level for logging to stderr. This has mostly - been deprecated by VTY based logging configuration, see - <<logging>> for more information. -*-T, --timestamp*:: - Enable prefixing each log line on stderr with a timestamp. This - has mostly been deprecated by VTY based logging configuration, see - <<logging>> for more information. diff --git a/doc/manuals/chapters/gbproxy-sgsnpool.adoc b/doc/manuals/chapters/gbproxy-sgsnpool.adoc deleted file mode 100644 index 61806af8c..000000000 --- a/doc/manuals/chapters/gbproxy-sgsnpool.adoc +++ /dev/null @@ -1,219 +0,0 @@ -== SGSN Pooling - -SGSN pooling is described in 3GPP TS 23.236 <<3gpp-ts-23-236>>, and is supported -by OsmoGbProxy since early 2021. - -The aim of SGSN pooling is to distribute load from a BSS across multiple SGSNs, -which are equivalent and redundant infrastructure for the same core network. - -The main mechanism for SGSN pooling is the TLLI/P-TMSI, which an SGSN hands out -to its attached subscribers. Typically 10 bits of the P-TMSI are designated as a -Network Resource Identifier (NRI) that identifies the originating SGSN, and -allows OsmoGbProxy to direct a subscriber back to the same SGSN instance that -previously negotiated the Attach procedure. Typically, the full NRI value -range available is divided into N even ranges, where each SGSN is assigned one -NRI range. - -Subscribers attaching without a TLLI, or those with unknown NRI value, -are evenly distributed across SGSN instances. OsmoGbProxy uses a hash-based -approach to distribute load across all connected SGSNs. - -A Paging Response from a subscriber is always returned back to whichever SGSN -initiated the Paging, regardless of the Mobile Identity used. - -Finally, a NULL-NRI is a special NRI value that indicates that the SGSN wishes -to offload this subscriber to a different SGSN. A NULL-NRI is an arbitrary NRI -value that is chosen distinctly for each PLMN served by a BSS, so that a -subscriber can be reassigned within that PLMN. Upon (periodic) Location -Updating, an offloading SGSN hands out a NULL-NRI value in the assigned TLLI, -along with a non-broadcast LAI. The subscriber will notice the LAI mismatch, -and immediately re-attempt the attach using the TLLI containing the NULL-NRI. -OsmoGbProxy recognises the NULL-NRI and redirects the subscriber to one of the -other SGSNs. A prerequisite for this to work well is that the particular SGSN is -previously marked as not accepting new subscribers, in OsmoGbProxy's configuration. - -The mechanisms described above make up the NAS node selection function -implemented in OsmoGbProxy. - -3GPP TS 23.236 also defines that an offloading SGSN hands subscriber information -to the newly assigned SGSN, which takes place outside the scope of OsmoGbProxy. - -=== Configuring SGSN Pooling - -The NRI ranges assigned to each SGSN must match in the OsmoGbProxy and the SGSN -configuration. If inconsistent NRI value ranges are configured, -attached subscribers would be redirected to SGSN instances that did not perform the -attach, possibly rendering the core network unusable. - -==== Connecting Multiple SGSNs - ----- -# Configure the Network Service -ns - bind udp sgsn - listen 10.0.0.1 23000 - nse 1 - ip-sns 10.0.1.1 23000 - ip-sns 10.0.1.1 23001 - nse 2 - ip-sns 10.0.1.2 23000 - nse 3 - ip-sns 10.0.1.3 23000 -# configure NRI value ranges -gbproxy - nri bitlen 10 - nri null add 0 -sgsn 1 - nri add 1 341 -sgsn 2 - nri add 342 682 -sgsn 3 - nri add 683 1023 ----- - -==== NRI Value Bit Length - -In OsmGbProxy, the NRI value's bit length is freely configurable from 0 to 15 -bits. 3GPP TS 23.236 suggests a typical bit length of 10. Setting the length -to 0 disables SGSN pooling, this is also the default. -The NRI bit length must be identical across the entire SGSN pool. - -Change the NRI value bit length in OsmoGbProxy's VTY configuration like this: - ----- -gbproxy - nri bitlen 10 ----- - -In the TMSI bits, regardless of the NRI bit length, the NRI value always starts -just after the most significant octet of a TMSI (most significant bit at TMSI's -bit 23). - -==== NULL-NRI - -Since OsmoGbProxy supports serving only one PLMN, NULL-NRI are configured globally. -Even though 3GPP TS 23.236 indicates that there is a single NULL-NRI per PLMN, -OsmoGbProxy allows configuring multiple NULL-NRI values. - ----- -network - nri null add 0 - nri null add 423 ----- - -==== Assigning NRI Ranges to SGSNs - -Each SGSN configured in OsmoGbProxy must be assigned a distinct NRI value range. -Overlapping NRI value ranges will cause failure to serve subscribers. - -NRI values are typically configured in ranges, here dividing a 10bit range -(0..1023) into three equal ranges, while leaving 0 available to be configured -as NULL-NRI: - ----- -sgsn nsei 1 - nri add 1 341 -sgsn nsei 2 - nri add 342 684 -sgsn nsei 3 - nri add 685 1023 ----- - -NRI can also be assigned in single values: - ----- -sgsn nsei 1 - nri add 23 ----- - -Ranges can be constructed arbitrarily by a sequence of `add` and `del` -configurations, here a contrived example: - ----- -sgsn nsei 1 - nri add 0 342 - nri del 23 - nri del 42 235 - nri add 1000 1023 ----- - -On the VIEW and ENABLE VTY nodes, `show nri all` shows all SGSNs: - ----- -OsmoGbProxy> show nri all -sgsn nsei 1 - nri add 1 341 -sgsn nsei 2 - nri add 342 684 -sgsn nsei 3 - nri add 685 1023 ----- - -When configuring overlapping NRI value ranges across SGSNs, the telnet VTY warns -about it, and starting OsmoGbProxy with such a configuration will fail: - ----- -sgsn nsei 1 - nri add 1 511 -sgsn nsei 2 - nri add 512 1023 -sgsn nsei 3 - nri add 500 555 ----- - -This results in: - ----- -$ osmo-gbproxy -% Warning: NSE(00003/SGSN): NRI range [500..555] overlaps between NSE 00003 and NSE 00001. For overlaps, NSE 00001 has higher priority than NSE 00003 -% Warning: NSE(00003/SGSN): NRI range [500..555] overlaps between NSE 00003 and NSE 00002. For overlaps, NSE 00002 has higher priority than NSE 00003 ----- - -==== SGSN Offloading - -To effectively offload a particular SGSN, it must be marked as no longer taking -new subscribers in OsmoGbProxy. This can be achieved in the telnet VTY by: - ----- -sgsn nsei 1 - no allow-attach ----- - -This SGSN will, as long as it is connected, continue to serve subscribers -already attached to it: those that yield an NRI matching this SGSN, and those -that are being paged by this SGSN. But OsmoGbProxy will no longer direct new -subscribers to this SGSN. - -TODO: Is paging response relevant for SGSN? - -To re-enable an SGSN for attaching new subscribers: - ----- -sgsn nsei 1 - allow-attach ----- - -==== Traffic allocation - -In a SGSN pool, osmo-gbproxy is facing the problem of dividing the downlink -capacity of a cell towards the SGSN. The BSS advertises the per-BVC capacity -by means of the BSSGP FLOW-CONTROL-BVC messages, but as there are multiple -SGSN in a pool, they all have to share / divide that total capacity. - -By default, osmo-gbproxy advertises the full capacity to _each_ of the SGSN -pool members, which results in significant over-provisioning and can lead to -overload situations. - -The administrator can configure the _percentage_ of the overall BSS-advertised -capacity that shall be reported to each pool member SGSN using the -`pool bvc-flow-control-ratio <1-100>` configuration command. - -A setting of 100 means that each pool member is informed of 100% of the -BSS side capacity. - -A setting of 25 means that each pool member is informed of 25% of the -BSS side capacity. This would make most sense in a set-up with four -SGSN of equal share. - -More complex capacity division schemes are so far not supported by -osmo-gbproxy. diff --git a/doc/manuals/osmogbproxy-usermanual-docinfo.xml b/doc/manuals/osmogbproxy-usermanual-docinfo.xml deleted file mode 100644 index 29bb2aa74..000000000 --- a/doc/manuals/osmogbproxy-usermanual-docinfo.xml +++ /dev/null @@ -1,46 +0,0 @@ -<revhistory> - <revision> - <revnumber>1</revnumber> - <date>March 21, 2019</date> - <authorinitials>HW</authorinitials> - <revremark> - Initial version. - </revremark> - </revision> -</revhistory> - -<authorgroup> - <author> - <firstname>Harald</firstname> - <surname>Welte</surname> - <email>hwelte@sysmocom.de</email> - <authorinitials>HW</authorinitials> - <affiliation> - <shortaffil>sysmocom</shortaffil> - <orgname>sysmocom - s.f.m.c. GmbH</orgname> - <jobtitle>Managing Director</jobtitle> - </affiliation> - </author> -</authorgroup> - -<copyright> - <year>2013-2019</year> - <holder>sysmocom - s.f.m.c. GmbH</holder> -</copyright> - -<legalnotice> - <para> - Permission is granted to copy, distribute and/or modify this - document under the terms of the GNU Free Documentation License, - Version 1.3 or any later version published by the Free Software - Foundation; with no Invariant Sections, no Front-Cover Texts, - and no Back-Cover Texts. A copy of the license is included in - the section entitled "GNU Free Documentation License". - </para> - <para> - The Asciidoc source code of this manual can be found at - <ulink url="https://git.osmocom.org/osmo-sgsn/doc/"> - https://git.osmocom.org/osmo-sgsn/doc/ - </ulink> - </para> -</legalnotice> diff --git a/doc/manuals/osmogbproxy-usermanual.adoc b/doc/manuals/osmogbproxy-usermanual.adoc deleted file mode 100644 index d19bdd4af..000000000 --- a/doc/manuals/osmogbproxy-usermanual.adoc +++ /dev/null @@ -1,36 +0,0 @@ -:gfdl-enabled: - -OsmoGbProxy User Manual -======================= -Harald Welte <hwelte@sysmocom.de> - - -include::./common/chapters/preface.adoc[] - -include::{srcdir}/chapters/gbproxy-overview.adoc[] - -include::{srcdir}/chapters/gbproxy-details.adoc[] - -include::{srcdir}/chapters/gbproxy-running.adoc[] - -include::{srcdir}/chapters/gbproxy-control.adoc[] - -include::./common/chapters/vty.adoc[] - -include::./common/chapters/logging.adoc[] - -include::{srcdir}/chapters/gbproxy-configuration.adoc[] - -include::./common/chapters/gb.adoc[] - -include::./common/chapters/control_if.adoc[] - -//include::{srcdir}/chapters/counters.adoc[] - -include::./common/chapters/port_numbers.adoc[] - -include::./common/chapters/bibliography.adoc[] - -include::./common/chapters/glossary.adoc[] - -include::./common/chapters/gfdl.adoc[] diff --git a/doc/manuals/osmogbproxy-vty-reference.xml b/doc/manuals/osmogbproxy-vty-reference.xml deleted file mode 100644 index ecf226808..000000000 --- a/doc/manuals/osmogbproxy-vty-reference.xml +++ /dev/null @@ -1,38 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ex:ts=2:sw=42sts=2:et - -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- ---> -<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML 5.0//EN" -"http://docbook.org/xml/5.0/dtd/docbook.dtd" [ -<!ENTITY chapter-vty SYSTEM "./common/chapters/vty.xml" > -<!ENTITY sections-vty SYSTEM "generated/docbook_osmogbproxy-vty-reference.xml" > -]> - -<book> - <info> - <revhistory> - <revision> - <revnumber>v1</revnumber> - <date>2nd December 2019</date> - <authorinitials>hw</authorinitials> - <revremark>Initial</revremark> - </revision> - </revhistory> - - <title>OsmoGbProxy VTY Reference</title> - - <copyright> - <year>2019</year> - </copyright> - - <legalnotice> - <para>This work is copyright by <orgname>sysmocom - s.f.m.c. GmbH</orgname>. All rights reserved. - </para> - </legalnotice> - </info> - - <!-- Main chapters--> - &chapter-vty; -</book> - diff --git a/doc/manuals/regen_doc.sh b/doc/manuals/regen_doc.sh index 847b764aa..9fcebb8b4 100755 --- a/doc/manuals/regen_doc.sh +++ b/doc/manuals/regen_doc.sh @@ -62,12 +62,6 @@ interact_vty \ osmo-sgsn -c "../examples/osmo-sgsn/osmo-sgsn.cfg" interact_vty \ - "update_vty_reference" \ - "vty-osmogbproxy/gbproxy_vty_reference.xml" \ - 4246 \ - osmo-gbproxy -c "../examples/osmo-gbproxy/osmo-gbproxy.cfg" - -interact_vty \ "update_counters" \ "chapters/counters_generated.adoc" \ 4245 \ diff --git a/doc/manuals/vty-osmogbproxy/gbproxy_vty_additions.xml b/doc/manuals/vty-osmogbproxy/gbproxy_vty_additions.xml deleted file mode 100644 index 6da2d2f2f..000000000 --- a/doc/manuals/vty-osmogbproxy/gbproxy_vty_additions.xml +++ /dev/null @@ -1,5 +0,0 @@ -<vtydoc xmlns='urn:osmocom:xml:libosmocore:vty:doc:1.0'> - <node id='config-gbproxy'> - <description>Configure the Gb proxy</description> - </node> -</vtydoc> diff --git a/doc/manuals/vty-osmogbproxy/gbproxy_vty_reference.xml b/doc/manuals/vty-osmogbproxy/gbproxy_vty_reference.xml deleted file mode 100644 index 1db3c0d2f..000000000 --- a/doc/manuals/vty-osmogbproxy/gbproxy_vty_reference.xml +++ /dev/null @@ -1,1627 +0,0 @@ -<vtydoc xmlns='urn:osmocom:xml:libosmocore:vty:doc:1.0'> - <node id='_common_cmds_'> - <name>Common Commands</name> - <description>These commands are available on all VTY nodes. They are listed here only once, to unclutter the VTY reference.</description> - <command id='help'> - <params> - <param name='help' doc='Description of the interactive help system' /> - </params> - </command> - <command id='list'> - <params> - <param name='list' doc='Print command list' /> - </params> - </command> - <command id='write terminal'> - <params> - <param name='write' doc='Write running configuration to memory, network, or terminal' /> - <param name='terminal' doc='Write to terminal' /> - </params> - </command> - <command id='write file [PATH]'> - <params> - <param name='write' doc='Write running configuration to memory, network, or terminal' /> - <param name='file' doc='Write to configuration file' /> - <param name='[PATH]' doc='Set file path to store the config, or replace if already exists' /> - </params> - </command> - <command id='write memory'> - <params> - <param name='write' doc='Write running configuration to memory, network, or terminal' /> - <param name='memory' doc='Write configuration to the file (same as write file)' /> - </params> - </command> - <command id='write'> - <params> - <param name='write' doc='Write running configuration to memory, network, or terminal' /> - </params> - </command> - <command id='show running-config'> - <params> - <param name='show' doc='Show running system information' /> - <param name='running-config' doc='running configuration' /> - </params> - </command> - <command id='exit'> - <params> - <param name='exit' doc='Exit current mode and down to previous mode' /> - </params> - </command> - <command id='end'> - <params> - <param name='end' doc='End current mode and change to enable mode.' /> - </params> - </command> - </node> - <node id='view'> - <name>view</name> - <command id='show version'> - <params> - <param name='show' doc='Show running system information' /> - <param name='version' doc='Displays program version' /> - </params> - </command> - <command id='show online-help'> - <params> - <param name='show' doc='Show running system information' /> - <param name='online-help' doc='Online help' /> - </params> - </command> - <command id='enable'> - <params> - <param name='enable' doc='Turn on privileged mode command' /> - </params> - </command> - <command id='terminal length <0-512>'> - <params> - <param name='terminal' doc='Set terminal line parameters' /> - <param name='length' doc='Set number of lines on a screen' /> - <param name='<0-512>' doc='Number of lines on screen (0 for no pausing)' /> - </params> - </command> - <command id='terminal no length'> - <params> - <param name='terminal' doc='Set terminal line parameters' /> - <param name='no' doc='Negate a command or set its defaults' /> - <param name='length' doc='Set number of lines on a screen' /> - </params> - </command> - <command id='who'> - <params> - <param name='who' doc='Display who is on vty' /> - </params> - </command> - <command id='show history'> - <params> - <param name='show' doc='Show running system information' /> - <param name='history' doc='Display the session command history' /> - </params> - </command> - <command id='logging enable'> - <params> - <param name='logging' doc='Configure logging' /> - <param name='enable' doc='Enables logging to this vty' /> - </params> - </command> - <command id='logging disable'> - <params> - <param name='logging' doc='Configure logging' /> - <param name='disable' doc='Disables logging to this vty' /> - </params> - </command> - <command id='logging filter all (0|1)'> - <params> - <param name='logging' doc='Configure logging' /> - <param name='filter' doc='Filter log messages' /> - <param name='all' doc='Do you want to log all messages?' /> - <param name='0' doc='Only print messages matched by other filters' /> - <param name='1' doc='Bypass filter and print all messages' /> - </params> - </command> - <command id='logging color (0|1)'> - <params> - <param name='logging' doc='Configure logging' /> - <param name='color' doc='Configure color-printing for log messages' /> - <param name='0' doc='Don't use color for printing messages' /> - <param name='1' doc='Use color for printing messages' /> - </params> - </command> - <command id='logging timestamp (0|1)'> - <params> - <param name='logging' doc='Configure logging' /> - <param name='timestamp' doc='Configure log message timestamping' /> - <param name='0' doc='Don't prefix each log message' /> - <param name='1' doc='Prefix each log message with current timestamp' /> - </params> - </command> - <command id='logging print extended-timestamp (0|1)'> - <params> - <param name='logging' doc='Configure logging' /> - <param name='print' doc='Log output settings' /> - <param name='extended-timestamp' doc='Configure log message timestamping' /> - <param name='0' doc='Don't prefix each log message' /> - <param name='1' doc='Prefix each log message with current timestamp with YYYYMMDDhhmmssnnn' /> - </params> - </command> - <command id='logging print category (0|1)'> - <params> - <param name='logging' doc='Configure logging' /> - <param name='print' doc='Log output settings' /> - <param name='category' doc='Configure log message' /> - <param name='0' doc='Don't prefix each log message' /> - <param name='1' doc='Prefix each log message with category/subsystem name' /> - </params> - </command> - <command id='logging print category-hex (0|1)'> - <params> - <param name='logging' doc='Configure logging' /> - <param name='print' doc='Log output settings' /> - <param name='category-hex' doc='Configure log message' /> - <param name='0' doc='Don't prefix each log message' /> - <param name='1' doc='Prefix each log message with category/subsystem nr in hex ('<000b>')' /> - </params> - </command> - <command id='logging print level (0|1)'> - <params> - <param name='logging' doc='Configure logging' /> - <param name='print' doc='Log output settings' /> - <param name='level' doc='Configure log message' /> - <param name='0' doc='Don't prefix each log message' /> - <param name='1' doc='Prefix each log message with the log level name' /> - </params> - </command> - <command id='logging print file (0|1|basename) [last]'> - <params> - <param name='logging' doc='Configure logging' /> - <param name='print' doc='Log output settings' /> - <param name='file' doc='Configure log message' /> - <param name='0' doc='Don't prefix each log message' /> - <param name='1' doc='Prefix each log message with the source file and line' /> - <param name='basename' doc='Prefix each log message with the source file's basename (strip leading paths) and line' /> - <param name='[last]' doc='Log source file info at the end of a log line. If omitted, log source file info just before the log text.' /> - </params> - </command> - <command id='logging set-log-mask MASK'> - <params> - <param name='logging' doc='Configure logging' /> - <param name='set-log-mask' doc='Set the logmask of this logging target' /> - <param name='MASK' doc='List of logging categories to log, e.g. 'abc:mno:xyz'. Available log categories depend on the specific application, refer to the 'logging level' command. Optionally add individual log levels like 'abc,1:mno,3:xyz,5', where the level numbers are LOGL_DEBUG=1 LOGL_INFO=3 LOGL_NOTICE=5 LOGL_ERROR=7 LOGL_FATAL=8' /> - </params> - </command> - <command id='logging level (|gprs|ns|bssgp|lglobal|llapd|linp|lmux|lmi|lmib|lsms|lctrl|lgtp|lstats|lgsup|loap|lss7|lsccp|lsua|lm3ua|lmgcp|ljibuf|lrspro) (debug|info|notice|error|fatal)'> - <params> - <param name='logging' doc='Configure logging' /> - <param name='level' doc='Set the log level for a specified category' /> - <param name='gprs' doc='GPRS Packet Service' /> - <param name='ns' doc='GPRS Network Service (NS)' /> - <param name='bssgp' doc='GPRS BSS Gateway Protocol (BSSGP)' /> - <param name='lglobal' doc='Library-internal global log family' /> - <param name='llapd' doc='LAPD in libosmogsm' /> - <param name='linp' doc='A-bis Intput Subsystem' /> - <param name='lmux' doc='A-bis B-Subchannel TRAU Frame Multiplex' /> - <param name='lmi' doc='A-bis Input Driver for Signalling' /> - <param name='lmib' doc='A-bis Input Driver for B-Channels (voice)' /> - <param name='lsms' doc='Layer3 Short Message Service (SMS)' /> - <param name='lctrl' doc='Control Interface' /> - <param name='lgtp' doc='GPRS GTP library' /> - <param name='lstats' doc='Statistics messages and logging' /> - <param name='lgsup' doc='Generic Subscriber Update Protocol' /> - <param name='loap' doc='Osmocom Authentication Protocol' /> - <param name='lss7' doc='libosmo-sigtran Signalling System 7' /> - <param name='lsccp' doc='libosmo-sigtran SCCP Implementation' /> - <param name='lsua' doc='libosmo-sigtran SCCP User Adaptation' /> - <param name='lm3ua' doc='libosmo-sigtran MTP3 User Adaptation' /> - <param name='lmgcp' doc='libosmo-mgcp Media Gateway Control Protocol' /> - <param name='ljibuf' doc='libosmo-netif Jitter Buffer' /> - <param name='lrspro' doc='Remote SIM protocol' /> - <param name='debug' doc='Log debug messages and higher levels' /> - <param name='info' doc='Log informational messages and higher levels' /> - <param name='notice' doc='Log noticeable messages and higher levels' /> - <param name='error' doc='Log error messages and higher levels' /> - <param name='fatal' doc='Log only fatal messages' /> - </params> - </command> - <command id='logging level set-all (debug|info|notice|error|fatal)'> - <params> - <param name='logging' doc='Configure logging' /> - <param name='level' doc='Set the log level for a specified category' /> - <param name='set-all' doc='Once-off set all categories to the given log level. There is no single command to take back these changes -- each category is set to the given level, period.' /> - <param name='debug' doc='Log debug messages and higher levels' /> - <param name='info' doc='Log informational messages and higher levels' /> - <param name='notice' doc='Log noticeable messages and higher levels' /> - <param name='error' doc='Log error messages and higher levels' /> - <param name='fatal' doc='Log only fatal messages' /> - </params> - </command> - <command id='logging level force-all (debug|info|notice|error|fatal)'> - <params> - <param name='logging' doc='Configure logging' /> - <param name='level' doc='Set the log level for a specified category' /> - <param name='force-all' doc='Globally force all logging categories to a specific level. This is released by the 'no logging level force-all' command. Note: any 'logging level <category> <level>' commands will have no visible effect after this, until the forced level is released.' /> - <param name='debug' doc='Log debug messages and higher levels' /> - <param name='info' doc='Log informational messages and higher levels' /> - <param name='notice' doc='Log noticeable messages and higher levels' /> - <param name='error' doc='Log error messages and higher levels' /> - <param name='fatal' doc='Log only fatal messages' /> - </params> - </command> - <command id='no logging level force-all'> - <params> - <param name='no' doc='Negate a command or set its defaults' /> - <param name='logging' doc='Configure logging' /> - <param name='level' doc='Set the log level for a specified category' /> - <param name='force-all' doc='Release any globally forced log level set with 'logging level force-all <level>'' /> - </params> - </command> - <command id='logp (|gprs|ns|bssgp|lglobal|llapd|linp|lmux|lmi|lmib|lsms|lctrl|lgtp|lstats|lgsup|loap|lss7|lsccp|lsua|lm3ua|lmgcp|ljibuf|lrspro) (debug|info|notice|error|fatal) .LOGMESSAGE'> - <params> - <param name='logp' doc='Print a message on all log outputs; useful for placing markers in test logs' /> - <param name='gprs' doc='GPRS Packet Service' /> - <param name='ns' doc='GPRS Network Service (NS)' /> - <param name='bssgp' doc='GPRS BSS Gateway Protocol (BSSGP)' /> - <param name='lglobal' doc='Library-internal global log family' /> - <param name='llapd' doc='LAPD in libosmogsm' /> - <param name='linp' doc='A-bis Intput Subsystem' /> - <param name='lmux' doc='A-bis B-Subchannel TRAU Frame Multiplex' /> - <param name='lmi' doc='A-bis Input Driver for Signalling' /> - <param name='lmib' doc='A-bis Input Driver for B-Channels (voice)' /> - <param name='lsms' doc='Layer3 Short Message Service (SMS)' /> - <param name='lctrl' doc='Control Interface' /> - <param name='lgtp' doc='GPRS GTP library' /> - <param name='lstats' doc='Statistics messages and logging' /> - <param name='lgsup' doc='Generic Subscriber Update Protocol' /> - <param name='loap' doc='Osmocom Authentication Protocol' /> - <param name='lss7' doc='libosmo-sigtran Signalling System 7' /> - <param name='lsccp' doc='libosmo-sigtran SCCP Implementation' /> - <param name='lsua' doc='libosmo-sigtran SCCP User Adaptation' /> - <param name='lm3ua' doc='libosmo-sigtran MTP3 User Adaptation' /> - <param name='lmgcp' doc='libosmo-mgcp Media Gateway Control Protocol' /> - <param name='ljibuf' doc='libosmo-netif Jitter Buffer' /> - <param name='lrspro' doc='Remote SIM protocol' /> - <param name='debug' doc='Log debug messages and higher levels' /> - <param name='info' doc='Log informational messages and higher levels' /> - <param name='notice' doc='Log noticeable messages and higher levels' /> - <param name='error' doc='Log error messages and higher levels' /> - <param name='fatal' doc='Log only fatal messages' /> - <param name='.LOGMESSAGE' doc='Arbitrary message to log on given category and log level' /> - </params> - </command> - <command id='show logging vty'> - <params> - <param name='show' doc='Show running system information' /> - <param name='logging' doc='Show current logging configuration' /> - <param name='vty' doc='Show current logging configuration for this vty' /> - </params> - </command> - <command id='show alarms'> - <params> - <param name='show' doc='Show running system information' /> - <param name='alarms' doc='Show current logging configuration' /> - </params> - </command> - <command id='show talloc-context (application|all) (full|brief|DEPTH)'> - <params> - <param name='show' doc='Show running system information' /> - <param name='talloc-context' doc='Show talloc memory hierarchy' /> - <param name='application' doc='Application's context' /> - <param name='all' doc='All contexts, if NULL-context tracking is enabled' /> - <param name='full' doc='Display a full talloc memory hierarchy' /> - <param name='brief' doc='Display a brief talloc memory hierarchy' /> - <param name='DEPTH' doc='Specify required maximal depth value' /> - </params> - </command> - <command id='show talloc-context (application|all) (full|brief|DEPTH) tree ADDRESS'> - <params> - <param name='show' doc='Show running system information' /> - <param name='talloc-context' doc='Show talloc memory hierarchy' /> - <param name='application' doc='Application's context' /> - <param name='all' doc='All contexts, if NULL-context tracking is enabled' /> - <param name='full' doc='Display a full talloc memory hierarchy' /> - <param name='brief' doc='Display a brief talloc memory hierarchy' /> - <param name='DEPTH' doc='Specify required maximal depth value' /> - <param name='tree' doc='Display only a specific memory chunk' /> - <param name='ADDRESS' doc='Chunk address (e.g. 0xdeadbeef)' /> - </params> - </command> - <command id='show talloc-context (application|all) (full|brief|DEPTH) filter REGEXP'> - <params> - <param name='show' doc='Show running system information' /> - <param name='talloc-context' doc='Show talloc memory hierarchy' /> - <param name='application' doc='Application's context' /> - <param name='all' doc='All contexts, if NULL-context tracking is enabled' /> - <param name='full' doc='Display a full talloc memory hierarchy' /> - <param name='brief' doc='Display a brief talloc memory hierarchy' /> - <param name='DEPTH' doc='Specify required maximal depth value' /> - <param name='filter' doc='Filter chunks using regular expression' /> - <param name='REGEXP' doc='Regular expression' /> - </params> - </command> - <command id='show stats'> - <params> - <param name='show' doc='Show running system information' /> - <param name='stats' doc='Show statistical values' /> - </params> - </command> - <command id='show stats level (global|peer|subscriber)'> - <params> - <param name='show' doc='Show running system information' /> - <param name='stats' doc='Show statistical values' /> - <param name='level' doc='Set the maximum group level' /> - <param name='global' doc='Show global groups only' /> - <param name='peer' doc='Show global and network peer related groups' /> - <param name='subscriber' doc='Show global, peer, and subscriber groups' /> - </params> - </command> - <command id='show asciidoc counters'> - <params> - <param name='show' doc='Show running system information' /> - <param name='asciidoc' doc='Asciidoc generation' /> - <param name='counters' doc='Generate table of all registered counters' /> - </params> - </command> - <command id='show rate-counters'> - <params> - <param name='show' doc='Show running system information' /> - <param name='rate-counters' doc='Show all rate counters' /> - </params> - </command> - <command id='show gbproxy [stats]'> - <params> - <param name='show' doc='Show running system information' /> - <param name='gbproxy' doc='Display information about the Gb proxy' /> - <param name='[stats]' doc='Show statistics' /> - </params> - </command> - <command id='show gbproxy links'> - <params> - <param name='show' doc='Show running system information' /> - <param name='gbproxy' doc='Display information about the Gb proxy' /> - <param name='links' doc='Show logical links' /> - </params> - </command> - <command id='show ns'> - <params> - <param name='show' doc='Show running system information' /> - <param name='ns' doc='Display information about the NS protocol' /> - </params> - </command> - <command id='show ns stats'> - <params> - <param name='show' doc='Show running system information' /> - <param name='ns' doc='Display information about the NS protocol' /> - <param name='stats' doc='Include statistics' /> - </params> - </command> - <command id='show ns persistent'> - <params> - <param name='show' doc='Show running system information' /> - <param name='ns' doc='Display information about the NS protocol' /> - <param name='persistent' doc='Show only persistent NS' /> - </params> - </command> - <command id='show ns (nsei|nsvc) <0-65535> [stats]'> - <params> - <param name='show' doc='Show running system information' /> - <param name='ns' doc='Display information about the NS protocol' /> - <param name='nsei' doc='Select one NSE by its NSE Identifier' /> - <param name='nsvc' doc='Select one NSE by its NS-VC Identifier' /> - <param name='<0-65535>' doc='The Identifier of selected type' /> - <param name='[stats]' doc='Include Statistics' /> - </params> - </command> - <command id='logging filter nsvc (nsei|nsvci) <0-65535>'> - <params> - <param name='logging' doc='Configure logging' /> - <param name='filter' doc='Filter log messages' /> - <param name='nsvc' doc='Filter based on NS Virtual Connection' /> - <param name='nsei' doc='Identify NS-VC by NSEI' /> - <param name='nsvci' doc='Identify NS-VC by NSVCI' /> - <param name='<0-65535>' doc='Numeric identifier' /> - </params> - </command> - </node> - <node id='enable'> - <name>enable</name> - <command id='disable'> - <params> - <param name='disable' doc='Turn off privileged mode command' /> - </params> - </command> - <command id='configure terminal'> - <params> - <param name='configure' doc='Configuration from vty interface' /> - <param name='terminal' doc='Configuration terminal' /> - </params> - </command> - <command id='copy running-config startup-config'> - <params> - <param name='copy' doc='Copy configuration' /> - <param name='running-config' doc='Copy running config to... ' /> - <param name='startup-config' doc='Copy running config to startup config (same as write file)' /> - </params> - </command> - <command id='show startup-config'> - <params> - <param name='show' doc='Show running system information' /> - <param name='startup-config' doc='Contentes of startup configuration' /> - </params> - </command> - <command id='show version'> - <params> - <param name='show' doc='Show running system information' /> - <param name='version' doc='Displays program version' /> - </params> - </command> - <command id='show online-help'> - <params> - <param name='show' doc='Show running system information' /> - <param name='online-help' doc='Online help' /> - </params> - </command> - <command id='terminal length <0-512>'> - <params> - <param name='terminal' doc='Set terminal line parameters' /> - <param name='length' doc='Set number of lines on a screen' /> - <param name='<0-512>' doc='Number of lines on screen (0 for no pausing)' /> - </params> - </command> - <command id='terminal no length'> - <params> - <param name='terminal' doc='Set terminal line parameters' /> - <param name='no' doc='Negate a command or set its defaults' /> - <param name='length' doc='Set number of lines on a screen' /> - </params> - </command> - <command id='who'> - <params> - <param name='who' doc='Display who is on vty' /> - </params> - </command> - <command id='show history'> - <params> - <param name='show' doc='Show running system information' /> - <param name='history' doc='Display the session command history' /> - </params> - </command> - <command id='terminal monitor'> - <params> - <param name='terminal' doc='Set terminal line parameters' /> - <param name='monitor' doc='Copy debug output to the current terminal line' /> - </params> - </command> - <command id='terminal no monitor'> - <params> - <param name='terminal' doc='Set terminal line parameters' /> - <param name='no' doc='Negate a command or set its defaults' /> - <param name='monitor' doc='Copy debug output to the current terminal line' /> - </params> - </command> - <command id='logging enable'> - <params> - <param name='logging' doc='Configure logging' /> - <param name='enable' doc='Enables logging to this vty' /> - </params> - </command> - <command id='logging disable'> - <params> - <param name='logging' doc='Configure logging' /> - <param name='disable' doc='Disables logging to this vty' /> - </params> - </command> - <command id='logging filter all (0|1)'> - <params> - <param name='logging' doc='Configure logging' /> - <param name='filter' doc='Filter log messages' /> - <param name='all' doc='Do you want to log all messages?' /> - <param name='0' doc='Only print messages matched by other filters' /> - <param name='1' doc='Bypass filter and print all messages' /> - </params> - </command> - <command id='logging color (0|1)'> - <params> - <param name='logging' doc='Configure logging' /> - <param name='color' doc='Configure color-printing for log messages' /> - <param name='0' doc='Don't use color for printing messages' /> - <param name='1' doc='Use color for printing messages' /> - </params> - </command> - <command id='logging timestamp (0|1)'> - <params> - <param name='logging' doc='Configure logging' /> - <param name='timestamp' doc='Configure log message timestamping' /> - <param name='0' doc='Don't prefix each log message' /> - <param name='1' doc='Prefix each log message with current timestamp' /> - </params> - </command> - <command id='logging print extended-timestamp (0|1)'> - <params> - <param name='logging' doc='Configure logging' /> - <param name='print' doc='Log output settings' /> - <param name='extended-timestamp' doc='Configure log message timestamping' /> - <param name='0' doc='Don't prefix each log message' /> - <param name='1' doc='Prefix each log message with current timestamp with YYYYMMDDhhmmssnnn' /> - </params> - </command> - <command id='logging print category (0|1)'> - <params> - <param name='logging' doc='Configure logging' /> - <param name='print' doc='Log output settings' /> - <param name='category' doc='Configure log message' /> - <param name='0' doc='Don't prefix each log message' /> - <param name='1' doc='Prefix each log message with category/subsystem name' /> - </params> - </command> - <command id='logging print category-hex (0|1)'> - <params> - <param name='logging' doc='Configure logging' /> - <param name='print' doc='Log output settings' /> - <param name='category-hex' doc='Configure log message' /> - <param name='0' doc='Don't prefix each log message' /> - <param name='1' doc='Prefix each log message with category/subsystem nr in hex ('<000b>')' /> - </params> - </command> - <command id='logging print level (0|1)'> - <params> - <param name='logging' doc='Configure logging' /> - <param name='print' doc='Log output settings' /> - <param name='level' doc='Configure log message' /> - <param name='0' doc='Don't prefix each log message' /> - <param name='1' doc='Prefix each log message with the log level name' /> - </params> - </command> - <command id='logging print file (0|1|basename) [last]'> - <params> - <param name='logging' doc='Configure logging' /> - <param name='print' doc='Log output settings' /> - <param name='file' doc='Configure log message' /> - <param name='0' doc='Don't prefix each log message' /> - <param name='1' doc='Prefix each log message with the source file and line' /> - <param name='basename' doc='Prefix each log message with the source file's basename (strip leading paths) and line' /> - <param name='[last]' doc='Log source file info at the end of a log line. If omitted, log source file info just before the log text.' /> - </params> - </command> - <command id='logging set-log-mask MASK'> - <params> - <param name='logging' doc='Configure logging' /> - <param name='set-log-mask' doc='Set the logmask of this logging target' /> - <param name='MASK' doc='List of logging categories to log, e.g. 'abc:mno:xyz'. Available log categories depend on the specific application, refer to the 'logging level' command. Optionally add individual log levels like 'abc,1:mno,3:xyz,5', where the level numbers are LOGL_DEBUG=1 LOGL_INFO=3 LOGL_NOTICE=5 LOGL_ERROR=7 LOGL_FATAL=8' /> - </params> - </command> - <command id='logging level (|gprs|ns|bssgp|lglobal|llapd|linp|lmux|lmi|lmib|lsms|lctrl|lgtp|lstats|lgsup|loap|lss7|lsccp|lsua|lm3ua|lmgcp|ljibuf|lrspro) (debug|info|notice|error|fatal)'> - <params> - <param name='logging' doc='Configure logging' /> - <param name='level' doc='Set the log level for a specified category' /> - <param name='gprs' doc='GPRS Packet Service' /> - <param name='ns' doc='GPRS Network Service (NS)' /> - <param name='bssgp' doc='GPRS BSS Gateway Protocol (BSSGP)' /> - <param name='lglobal' doc='Library-internal global log family' /> - <param name='llapd' doc='LAPD in libosmogsm' /> - <param name='linp' doc='A-bis Intput Subsystem' /> - <param name='lmux' doc='A-bis B-Subchannel TRAU Frame Multiplex' /> - <param name='lmi' doc='A-bis Input Driver for Signalling' /> - <param name='lmib' doc='A-bis Input Driver for B-Channels (voice)' /> - <param name='lsms' doc='Layer3 Short Message Service (SMS)' /> - <param name='lctrl' doc='Control Interface' /> - <param name='lgtp' doc='GPRS GTP library' /> - <param name='lstats' doc='Statistics messages and logging' /> - <param name='lgsup' doc='Generic Subscriber Update Protocol' /> - <param name='loap' doc='Osmocom Authentication Protocol' /> - <param name='lss7' doc='libosmo-sigtran Signalling System 7' /> - <param name='lsccp' doc='libosmo-sigtran SCCP Implementation' /> - <param name='lsua' doc='libosmo-sigtran SCCP User Adaptation' /> - <param name='lm3ua' doc='libosmo-sigtran MTP3 User Adaptation' /> - <param name='lmgcp' doc='libosmo-mgcp Media Gateway Control Protocol' /> - <param name='ljibuf' doc='libosmo-netif Jitter Buffer' /> - <param name='lrspro' doc='Remote SIM protocol' /> - <param name='debug' doc='Log debug messages and higher levels' /> - <param name='info' doc='Log informational messages and higher levels' /> - <param name='notice' doc='Log noticeable messages and higher levels' /> - <param name='error' doc='Log error messages and higher levels' /> - <param name='fatal' doc='Log only fatal messages' /> - </params> - </command> - <command id='logging level set-all (debug|info|notice|error|fatal)'> - <params> - <param name='logging' doc='Configure logging' /> - <param name='level' doc='Set the log level for a specified category' /> - <param name='set-all' doc='Once-off set all categories to the given log level. There is no single command to take back these changes -- each category is set to the given level, period.' /> - <param name='debug' doc='Log debug messages and higher levels' /> - <param name='info' doc='Log informational messages and higher levels' /> - <param name='notice' doc='Log noticeable messages and higher levels' /> - <param name='error' doc='Log error messages and higher levels' /> - <param name='fatal' doc='Log only fatal messages' /> - </params> - </command> - <command id='logging level force-all (debug|info|notice|error|fatal)'> - <params> - <param name='logging' doc='Configure logging' /> - <param name='level' doc='Set the log level for a specified category' /> - <param name='force-all' doc='Globally force all logging categories to a specific level. This is released by the 'no logging level force-all' command. Note: any 'logging level <category> <level>' commands will have no visible effect after this, until the forced level is released.' /> - <param name='debug' doc='Log debug messages and higher levels' /> - <param name='info' doc='Log informational messages and higher levels' /> - <param name='notice' doc='Log noticeable messages and higher levels' /> - <param name='error' doc='Log error messages and higher levels' /> - <param name='fatal' doc='Log only fatal messages' /> - </params> - </command> - <command id='no logging level force-all'> - <params> - <param name='no' doc='Negate a command or set its defaults' /> - <param name='logging' doc='Configure logging' /> - <param name='level' doc='Set the log level for a specified category' /> - <param name='force-all' doc='Release any globally forced log level set with 'logging level force-all <level>'' /> - </params> - </command> - <command id='logp (|gprs|ns|bssgp|lglobal|llapd|linp|lmux|lmi|lmib|lsms|lctrl|lgtp|lstats|lgsup|loap|lss7|lsccp|lsua|lm3ua|lmgcp|ljibuf|lrspro) (debug|info|notice|error|fatal) .LOGMESSAGE'> - <params> - <param name='logp' doc='Print a message on all log outputs; useful for placing markers in test logs' /> - <param name='gprs' doc='GPRS Packet Service' /> - <param name='ns' doc='GPRS Network Service (NS)' /> - <param name='bssgp' doc='GPRS BSS Gateway Protocol (BSSGP)' /> - <param name='lglobal' doc='Library-internal global log family' /> - <param name='llapd' doc='LAPD in libosmogsm' /> - <param name='linp' doc='A-bis Intput Subsystem' /> - <param name='lmux' doc='A-bis B-Subchannel TRAU Frame Multiplex' /> - <param name='lmi' doc='A-bis Input Driver for Signalling' /> - <param name='lmib' doc='A-bis Input Driver for B-Channels (voice)' /> - <param name='lsms' doc='Layer3 Short Message Service (SMS)' /> - <param name='lctrl' doc='Control Interface' /> - <param name='lgtp' doc='GPRS GTP library' /> - <param name='lstats' doc='Statistics messages and logging' /> - <param name='lgsup' doc='Generic Subscriber Update Protocol' /> - <param name='loap' doc='Osmocom Authentication Protocol' /> - <param name='lss7' doc='libosmo-sigtran Signalling System 7' /> - <param name='lsccp' doc='libosmo-sigtran SCCP Implementation' /> - <param name='lsua' doc='libosmo-sigtran SCCP User Adaptation' /> - <param name='lm3ua' doc='libosmo-sigtran MTP3 User Adaptation' /> - <param name='lmgcp' doc='libosmo-mgcp Media Gateway Control Protocol' /> - <param name='ljibuf' doc='libosmo-netif Jitter Buffer' /> - <param name='lrspro' doc='Remote SIM protocol' /> - <param name='debug' doc='Log debug messages and higher levels' /> - <param name='info' doc='Log informational messages and higher levels' /> - <param name='notice' doc='Log noticeable messages and higher levels' /> - <param name='error' doc='Log error messages and higher levels' /> - <param name='fatal' doc='Log only fatal messages' /> - <param name='.LOGMESSAGE' doc='Arbitrary message to log on given category and log level' /> - </params> - </command> - <command id='show logging vty'> - <params> - <param name='show' doc='Show running system information' /> - <param name='logging' doc='Show current logging configuration' /> - <param name='vty' doc='Show current logging configuration for this vty' /> - </params> - </command> - <command id='show alarms'> - <params> - <param name='show' doc='Show running system information' /> - <param name='alarms' doc='Show current logging configuration' /> - </params> - </command> - <command id='show talloc-context (application|all) (full|brief|DEPTH)'> - <params> - <param name='show' doc='Show running system information' /> - <param name='talloc-context' doc='Show talloc memory hierarchy' /> - <param name='application' doc='Application's context' /> - <param name='all' doc='All contexts, if NULL-context tracking is enabled' /> - <param name='full' doc='Display a full talloc memory hierarchy' /> - <param name='brief' doc='Display a brief talloc memory hierarchy' /> - <param name='DEPTH' doc='Specify required maximal depth value' /> - </params> - </command> - <command id='show talloc-context (application|all) (full|brief|DEPTH) tree ADDRESS'> - <params> - <param name='show' doc='Show running system information' /> - <param name='talloc-context' doc='Show talloc memory hierarchy' /> - <param name='application' doc='Application's context' /> - <param name='all' doc='All contexts, if NULL-context tracking is enabled' /> - <param name='full' doc='Display a full talloc memory hierarchy' /> - <param name='brief' doc='Display a brief talloc memory hierarchy' /> - <param name='DEPTH' doc='Specify required maximal depth value' /> - <param name='tree' doc='Display only a specific memory chunk' /> - <param name='ADDRESS' doc='Chunk address (e.g. 0xdeadbeef)' /> - </params> - </command> - <command id='show talloc-context (application|all) (full|brief|DEPTH) filter REGEXP'> - <params> - <param name='show' doc='Show running system information' /> - <param name='talloc-context' doc='Show talloc memory hierarchy' /> - <param name='application' doc='Application's context' /> - <param name='all' doc='All contexts, if NULL-context tracking is enabled' /> - <param name='full' doc='Display a full talloc memory hierarchy' /> - <param name='brief' doc='Display a brief talloc memory hierarchy' /> - <param name='DEPTH' doc='Specify required maximal depth value' /> - <param name='filter' doc='Filter chunks using regular expression' /> - <param name='REGEXP' doc='Regular expression' /> - </params> - </command> - <command id='show stats'> - <params> - <param name='show' doc='Show running system information' /> - <param name='stats' doc='Show statistical values' /> - </params> - </command> - <command id='show stats level (global|peer|subscriber)'> - <params> - <param name='show' doc='Show running system information' /> - <param name='stats' doc='Show statistical values' /> - <param name='level' doc='Set the maximum group level' /> - <param name='global' doc='Show global groups only' /> - <param name='peer' doc='Show global and network peer related groups' /> - <param name='subscriber' doc='Show global, peer, and subscriber groups' /> - </params> - </command> - <command id='show asciidoc counters'> - <params> - <param name='show' doc='Show running system information' /> - <param name='asciidoc' doc='Asciidoc generation' /> - <param name='counters' doc='Generate table of all registered counters' /> - </params> - </command> - <command id='show rate-counters'> - <params> - <param name='show' doc='Show running system information' /> - <param name='rate-counters' doc='Show all rate counters' /> - </params> - </command> - <command id='show gbproxy [stats]'> - <params> - <param name='show' doc='Show running system information' /> - <param name='gbproxy' doc='Display information about the Gb proxy' /> - <param name='[stats]' doc='Show statistics' /> - </params> - </command> - <command id='show gbproxy links'> - <params> - <param name='show' doc='Show running system information' /> - <param name='gbproxy' doc='Display information about the Gb proxy' /> - <param name='links' doc='Show logical links' /> - </params> - </command> - <command id='delete-gbproxy-peer <0-65534> bvci <2-65534>'> - <params> - <param name='delete-gbproxy-peer' doc='Delete a GBProxy peer by NSEI and optionally BVCI' /> - <param name='<0-65534>' doc='NSEI number' /> - <param name='bvci' doc='Only delete peer with a matching BVCI' /> - <param name='<2-65534>' doc='BVCI number' /> - </params> - </command> - <command id='delete-gbproxy-peer <0-65534> (only-bvc|only-nsvc|all) [dry-run]'> - <params> - <param name='delete-gbproxy-peer' doc='Delete a GBProxy peer by NSEI and optionally BVCI' /> - <param name='<0-65534>' doc='NSEI number' /> - <param name='only-bvc' doc='Only delete BSSGP connections (BVC)' /> - <param name='only-nsvc' doc='Only delete dynamic NS connections (NS-VC)' /> - <param name='all' doc='Delete BVC and dynamic NS connections' /> - <param name='[dry-run]' doc='Show what would be deleted instead of actually deleting' /> - </params> - </command> - <command id='delete-gbproxy-link <0-65534> (tlli|imsi|sgsn-nsei) IDENT'> - <params> - <param name='delete-gbproxy-link' doc='Delete a GBProxy logical link entry by NSEI and identification' /> - <param name='<0-65534>' doc='NSEI number' /> - <param name='tlli' doc='Delete entries with a matching TLLI (hex)' /> - <param name='imsi' doc='Delete entries with a matching IMSI' /> - <param name='sgsn-nsei' doc='Delete entries with a matching SGSN NSEI' /> - <param name='IDENT' doc='Identification to match' /> - </params> - </command> - <command id='delete-gbproxy-link <0-65534> (stale|de-registered)'> - <params> - <param name='delete-gbproxy-link' doc='Delete a GBProxy logical link entry by NSEI and identification' /> - <param name='<0-65534>' doc='NSEI number' /> - <param name='stale' doc='Delete stale entries' /> - <param name='de-registered' doc='Delete de-registered entries' /> - </params> - </command> - <command id='show ns'> - <params> - <param name='show' doc='Show running system information' /> - <param name='ns' doc='Display information about the NS protocol' /> - </params> - </command> - <command id='show ns stats'> - <params> - <param name='show' doc='Show running system information' /> - <param name='ns' doc='Display information about the NS protocol' /> - <param name='stats' doc='Include statistics' /> - </params> - </command> - <command id='show ns persistent'> - <params> - <param name='show' doc='Show running system information' /> - <param name='ns' doc='Display information about the NS protocol' /> - <param name='persistent' doc='Show only persistent NS' /> - </params> - </command> - <command id='show ns (nsei|nsvc) <0-65535> [stats]'> - <params> - <param name='show' doc='Show running system information' /> - <param name='ns' doc='Display information about the NS protocol' /> - <param name='nsei' doc='Select one NSE by its NSE Identifier' /> - <param name='nsvc' doc='Select one NSE by its NS-VC Identifier' /> - <param name='<0-65535>' doc='The Identifier of selected type' /> - <param name='[stats]' doc='Include Statistics' /> - </params> - </command> - <command id='logging filter nsvc (nsei|nsvci) <0-65535>'> - <params> - <param name='logging' doc='Configure logging' /> - <param name='filter' doc='Filter log messages' /> - <param name='nsvc' doc='Filter based on NS Virtual Connection' /> - <param name='nsei' doc='Identify NS-VC by NSEI' /> - <param name='nsvci' doc='Identify NS-VC by NSVCI' /> - <param name='<0-65535>' doc='Numeric identifier' /> - </params> - </command> - <command id='nsvc (nsei|nsvci) <0-65535> (block|unblock|reset)'> - <params> - <param name='nsvc' doc='Perform an operation on a NSVC' /> - <param name='nsei' doc='NSEI to identify NS-VC Identifier (NS-VCI)' /> - <param name='nsvci' doc='NS-VC Identifier (NS-VCI)' /> - <param name='<0-65535>' doc='The NSEI' /> - <param name='block' doc='Initiate BLOCK procedure' /> - <param name='unblock' doc='Initiate UNBLOCK procedure' /> - <param name='reset' doc='Initiate RESET procedure' /> - </params> - </command> - </node> - <node id='config'> - <name>config</name> - <command id='hostname WORD'> - <params> - <param name='hostname' doc='Set system's network name' /> - <param name='WORD' doc='This system's network name' /> - </params> - </command> - <command id='no hostname [HOSTNAME]'> - <params> - <param name='no' doc='Negate a command or set its defaults' /> - <param name='hostname' doc='Reset system's network name' /> - <param name='[HOSTNAME]' doc='Host name of this router' /> - </params> - </command> - <command id='password (8|) WORD'> - <params> - <param name='password' doc='Assign the terminal connection password' /> - <param name='8' doc='Specifies a HIDDEN password will follow' /> - <param name='' doc='dummy string ' /> - <param name='WORD' doc='The HIDDEN line password string' /> - </params> - </command> - <command id='password LINE'> - <params> - <param name='password' doc='Assign the terminal connection password' /> - <param name='LINE' doc='The UNENCRYPTED (cleartext) line password' /> - </params> - </command> - <command id='enable password (8|) WORD'> - <params> - <param name='enable' doc='Modify enable password parameters' /> - <param name='password' doc='Assign the privileged level password' /> - <param name='8' doc='Specifies a HIDDEN password will follow' /> - <param name='' doc='dummy string ' /> - <param name='WORD' doc='The HIDDEN 'enable' password string' /> - </params> - </command> - <command id='enable password LINE'> - <params> - <param name='enable' doc='Modify enable password parameters' /> - <param name='password' doc='Assign the privileged level password' /> - <param name='LINE' doc='The UNENCRYPTED (cleartext) 'enable' password' /> - </params> - </command> - <command id='no enable password'> - <params> - <param name='no' doc='Negate a command or set its defaults' /> - <param name='enable' doc='Modify enable password parameters' /> - <param name='password' doc='Assign the privileged level password' /> - </params> - </command> - <command id='banner motd default'> - <params> - <param name='banner' doc='Set banner string' /> - <param name='motd' doc='Strings for motd' /> - <param name='default' doc='Default string' /> - </params> - </command> - <command id='banner motd file [FILE]'> - <params> - <param name='banner' doc='Set banner' /> - <param name='motd' doc='Banner for motd' /> - <param name='file' doc='Banner from a file' /> - <param name='[FILE]' doc='Filename' /> - </params> - </command> - <command id='no banner motd'> - <params> - <param name='no' doc='Negate a command or set its defaults' /> - <param name='banner' doc='Set banner string' /> - <param name='motd' doc='Strings for motd' /> - </params> - </command> - <command id='service terminal-length <0-512>'> - <params> - <param name='service' doc='Set up miscellaneous service' /> - <param name='terminal-length' doc='System wide terminal length configuration' /> - <param name='<0-512>' doc='Number of lines of VTY (0 means no line control)' /> - </params> - </command> - <command id='no service terminal-length [<0-512>]'> - <params> - <param name='no' doc='Negate a command or set its defaults' /> - <param name='service' doc='Set up miscellaneous service' /> - <param name='terminal-length' doc='System wide terminal length configuration' /> - <param name='[<0-512>]' doc='Number of lines of VTY (0 means no line control)' /> - </params> - </command> - <command id='line vty'> - <params> - <param name='line' doc='Configure a terminal line' /> - <param name='vty' doc='Virtual terminal' /> - </params> - </command> - <command id='service advanced-vty'> - <params> - <param name='service' doc='Set up miscellaneous service' /> - <param name='advanced-vty' doc='Enable advanced mode vty interface' /> - </params> - </command> - <command id='no service advanced-vty'> - <params> - <param name='no' doc='Negate a command or set its defaults' /> - <param name='service' doc='Set up miscellaneous service' /> - <param name='advanced-vty' doc='Enable advanced mode vty interface' /> - </params> - </command> - <command id='show history'> - <params> - <param name='show' doc='Show running system information' /> - <param name='history' doc='Display the session command history' /> - </params> - </command> - <command id='log stderr'> - <params> - <param name='log' doc='Configure logging sub-system' /> - <param name='stderr' doc='Logging via STDERR of the process' /> - </params> - </command> - <command id='no log stderr'> - <params> - <param name='no' doc='Negate a command or set its defaults' /> - <param name='log' doc='Configure logging sub-system' /> - <param name='stderr' doc='Logging via STDERR of the process' /> - </params> - </command> - <command id='log file .FILENAME'> - <params> - <param name='log' doc='Configure logging sub-system' /> - <param name='file' doc='Logging to text file' /> - <param name='.FILENAME' doc='Filename' /> - </params> - </command> - <command id='no log file .FILENAME'> - <params> - <param name='no' doc='Negate a command or set its defaults' /> - <param name='log' doc='Configure logging sub-system' /> - <param name='file' doc='Logging to text file' /> - <param name='.FILENAME' doc='Filename' /> - </params> - </command> - <command id='log alarms <2-32700>'> - <params> - <param name='log' doc='Configure logging sub-system' /> - <param name='alarms' doc='Logging alarms to osmo_strrb' /> - <param name='<2-32700>' doc='Maximum number of messages to log' /> - </params> - </command> - <command id='no log alarms'> - <params> - <param name='no' doc='Negate a command or set its defaults' /> - <param name='log' doc='Configure logging sub-system' /> - <param name='alarms' doc='Logging alarms to osmo_strrb' /> - </params> - </command> - <command id='log syslog (authpriv|cron|daemon|ftp|lpr|mail|news|user|uucp)'> - <params> - <param name='log' doc='Configure logging sub-system' /> - <param name='syslog' doc='Logging via syslog' /> - <param name='authpriv' doc='Security/authorization messages facility' /> - <param name='cron' doc='Clock daemon (cron/at) facility' /> - <param name='daemon' doc='General system daemon facility' /> - <param name='ftp' doc='Ftp daemon facility' /> - <param name='lpr' doc='Line printer facility' /> - <param name='mail' doc='Mail facility' /> - <param name='news' doc='News facility' /> - <param name='user' doc='Generic facility' /> - <param name='uucp' doc='UUCP facility' /> - </params> - </command> - <command id='log syslog local <0-7>'> - <params> - <param name='log' doc='Configure logging sub-system' /> - <param name='syslog' doc='Logging via syslog' /> - <param name='local' doc='Syslog LOCAL facility' /> - <param name='<0-7>' doc='Local facility number' /> - </params> - </command> - <command id='no log syslog'> - <params> - <param name='no' doc='Negate a command or set its defaults' /> - <param name='log' doc='Configure logging sub-system' /> - <param name='syslog' doc='Logging via syslog' /> - </params> - </command> - <command id='log gsmtap [HOSTNAME]'> - <params> - <param name='log' doc='Configure logging sub-system' /> - <param name='gsmtap' doc='Logging via GSMTAP' /> - <param name='[HOSTNAME]' doc='Host name to send the GSMTAP logging to (UDP port 4729)' /> - </params> - </command> - <command id='stats reporter statsd'> - <params> - <param name='stats' doc='Configure stats sub-system' /> - <param name='reporter' doc='Configure a stats reporter' /> - <param name='statsd' doc='Report to a STATSD server' /> - </params> - </command> - <command id='no stats reporter statsd'> - <params> - <param name='no' doc='Negate a command or set its defaults' /> - <param name='stats' doc='Configure stats sub-system' /> - <param name='reporter' doc='Configure a stats reporter' /> - <param name='statsd' doc='Report to a STATSD server' /> - </params> - </command> - <command id='stats reporter log'> - <params> - <param name='stats' doc='Configure stats sub-system' /> - <param name='reporter' doc='Configure a stats reporter' /> - <param name='log' doc='Report to the logger' /> - </params> - </command> - <command id='no stats reporter log'> - <params> - <param name='no' doc='Negate a command or set its defaults' /> - <param name='stats' doc='Configure stats sub-system' /> - <param name='reporter' doc='Configure a stats reporter' /> - <param name='log' doc='Report to the logger' /> - </params> - </command> - <command id='stats interval <1-65535>'> - <params> - <param name='stats' doc='Configure stats sub-system' /> - <param name='interval' doc='Set the reporting interval' /> - <param name='<1-65535>' doc='Interval in seconds' /> - </params> - </command> - <command id='gbproxy'> - <params> - <param name='gbproxy' doc='Configure the Gb proxy' /> - </params> - </command> - <command id='ns'> - <params> - <param name='ns' doc='Configure the GPRS Network Service' /> - </params> - </command> - </node> - <node id='config-log'> - <name>config-log</name> - <command id='logging filter all (0|1)'> - <params> - <param name='logging' doc='Configure logging' /> - <param name='filter' doc='Filter log messages' /> - <param name='all' doc='Do you want to log all messages?' /> - <param name='0' doc='Only print messages matched by other filters' /> - <param name='1' doc='Bypass filter and print all messages' /> - </params> - </command> - <command id='logging color (0|1)'> - <params> - <param name='logging' doc='Configure logging' /> - <param name='color' doc='Configure color-printing for log messages' /> - <param name='0' doc='Don't use color for printing messages' /> - <param name='1' doc='Use color for printing messages' /> - </params> - </command> - <command id='logging timestamp (0|1)'> - <params> - <param name='logging' doc='Configure logging' /> - <param name='timestamp' doc='Configure log message timestamping' /> - <param name='0' doc='Don't prefix each log message' /> - <param name='1' doc='Prefix each log message with current timestamp' /> - </params> - </command> - <command id='logging print extended-timestamp (0|1)'> - <params> - <param name='logging' doc='Configure logging' /> - <param name='print' doc='Log output settings' /> - <param name='extended-timestamp' doc='Configure log message timestamping' /> - <param name='0' doc='Don't prefix each log message' /> - <param name='1' doc='Prefix each log message with current timestamp with YYYYMMDDhhmmssnnn' /> - </params> - </command> - <command id='logging print category (0|1)'> - <params> - <param name='logging' doc='Configure logging' /> - <param name='print' doc='Log output settings' /> - <param name='category' doc='Configure log message' /> - <param name='0' doc='Don't prefix each log message' /> - <param name='1' doc='Prefix each log message with category/subsystem name' /> - </params> - </command> - <command id='logging print category-hex (0|1)'> - <params> - <param name='logging' doc='Configure logging' /> - <param name='print' doc='Log output settings' /> - <param name='category-hex' doc='Configure log message' /> - <param name='0' doc='Don't prefix each log message' /> - <param name='1' doc='Prefix each log message with category/subsystem nr in hex ('<000b>')' /> - </params> - </command> - <command id='logging print level (0|1)'> - <params> - <param name='logging' doc='Configure logging' /> - <param name='print' doc='Log output settings' /> - <param name='level' doc='Configure log message' /> - <param name='0' doc='Don't prefix each log message' /> - <param name='1' doc='Prefix each log message with the log level name' /> - </params> - </command> - <command id='logging print file (0|1|basename) [last]'> - <params> - <param name='logging' doc='Configure logging' /> - <param name='print' doc='Log output settings' /> - <param name='file' doc='Configure log message' /> - <param name='0' doc='Don't prefix each log message' /> - <param name='1' doc='Prefix each log message with the source file and line' /> - <param name='basename' doc='Prefix each log message with the source file's basename (strip leading paths) and line' /> - <param name='[last]' doc='Log source file info at the end of a log line. If omitted, log source file info just before the log text.' /> - </params> - </command> - <command id='logging level (|gprs|ns|bssgp|lglobal|llapd|linp|lmux|lmi|lmib|lsms|lctrl|lgtp|lstats|lgsup|loap|lss7|lsccp|lsua|lm3ua|lmgcp|ljibuf|lrspro) (debug|info|notice|error|fatal)'> - <params> - <param name='logging' doc='Configure logging' /> - <param name='level' doc='Set the log level for a specified category' /> - <param name='gprs' doc='GPRS Packet Service' /> - <param name='ns' doc='GPRS Network Service (NS)' /> - <param name='bssgp' doc='GPRS BSS Gateway Protocol (BSSGP)' /> - <param name='lglobal' doc='Library-internal global log family' /> - <param name='llapd' doc='LAPD in libosmogsm' /> - <param name='linp' doc='A-bis Intput Subsystem' /> - <param name='lmux' doc='A-bis B-Subchannel TRAU Frame Multiplex' /> - <param name='lmi' doc='A-bis Input Driver for Signalling' /> - <param name='lmib' doc='A-bis Input Driver for B-Channels (voice)' /> - <param name='lsms' doc='Layer3 Short Message Service (SMS)' /> - <param name='lctrl' doc='Control Interface' /> - <param name='lgtp' doc='GPRS GTP library' /> - <param name='lstats' doc='Statistics messages and logging' /> - <param name='lgsup' doc='Generic Subscriber Update Protocol' /> - <param name='loap' doc='Osmocom Authentication Protocol' /> - <param name='lss7' doc='libosmo-sigtran Signalling System 7' /> - <param name='lsccp' doc='libosmo-sigtran SCCP Implementation' /> - <param name='lsua' doc='libosmo-sigtran SCCP User Adaptation' /> - <param name='lm3ua' doc='libosmo-sigtran MTP3 User Adaptation' /> - <param name='lmgcp' doc='libosmo-mgcp Media Gateway Control Protocol' /> - <param name='ljibuf' doc='libosmo-netif Jitter Buffer' /> - <param name='lrspro' doc='Remote SIM protocol' /> - <param name='debug' doc='Log debug messages and higher levels' /> - <param name='info' doc='Log informational messages and higher levels' /> - <param name='notice' doc='Log noticeable messages and higher levels' /> - <param name='error' doc='Log error messages and higher levels' /> - <param name='fatal' doc='Log only fatal messages' /> - </params> - </command> - <command id='logging level set-all (debug|info|notice|error|fatal)'> - <params> - <param name='logging' doc='Configure logging' /> - <param name='level' doc='Set the log level for a specified category' /> - <param name='set-all' doc='Once-off set all categories to the given log level. There is no single command to take back these changes -- each category is set to the given level, period.' /> - <param name='debug' doc='Log debug messages and higher levels' /> - <param name='info' doc='Log informational messages and higher levels' /> - <param name='notice' doc='Log noticeable messages and higher levels' /> - <param name='error' doc='Log error messages and higher levels' /> - <param name='fatal' doc='Log only fatal messages' /> - </params> - </command> - <command id='logging level force-all (debug|info|notice|error|fatal)'> - <params> - <param name='logging' doc='Configure logging' /> - <param name='level' doc='Set the log level for a specified category' /> - <param name='force-all' doc='Globally force all logging categories to a specific level. This is released by the 'no logging level force-all' command. Note: any 'logging level <category> <level>' commands will have no visible effect after this, until the forced level is released.' /> - <param name='debug' doc='Log debug messages and higher levels' /> - <param name='info' doc='Log informational messages and higher levels' /> - <param name='notice' doc='Log noticeable messages and higher levels' /> - <param name='error' doc='Log error messages and higher levels' /> - <param name='fatal' doc='Log only fatal messages' /> - </params> - </command> - <command id='no logging level force-all'> - <params> - <param name='no' doc='Negate a command or set its defaults' /> - <param name='logging' doc='Configure logging' /> - <param name='level' doc='Set the log level for a specified category' /> - <param name='force-all' doc='Release any globally forced log level set with 'logging level force-all <level>'' /> - </params> - </command> - <command id='logging filter nsvc (nsei|nsvci) <0-65535>'> - <params> - <param name='logging' doc='Configure logging' /> - <param name='filter' doc='Filter log messages' /> - <param name='nsvc' doc='Filter based on NS Virtual Connection' /> - <param name='nsei' doc='Identify NS-VC by NSEI' /> - <param name='nsvci' doc='Identify NS-VC by NSVCI' /> - <param name='<0-65535>' doc='Numeric identifier' /> - </params> - </command> - </node> - <node id='config-stats'> - <name>config-stats</name> - <command id='local-ip ADDR'> - <params> - <param name='local-ip' doc='Set the IP address to which we bind locally' /> - <param name='ADDR' doc='IP Address' /> - </params> - </command> - <command id='no local-ip'> - <params> - <param name='no' doc='Negate a command or set its defaults' /> - <param name='local-ip' doc='Set the IP address to which we bind locally' /> - </params> - </command> - <command id='remote-ip ADDR'> - <params> - <param name='remote-ip' doc='Set the remote IP address to which we connect' /> - <param name='ADDR' doc='IP Address' /> - </params> - </command> - <command id='remote-port <1-65535>'> - <params> - <param name='remote-port' doc='Set the remote port to which we connect' /> - <param name='<1-65535>' doc='Remote port number' /> - </params> - </command> - <command id='mtu <100-65535>'> - <params> - <param name='mtu' doc='Set the maximum packet size' /> - <param name='<100-65535>' doc='Size in byte' /> - </params> - </command> - <command id='no mtu'> - <params> - <param name='no' doc='Negate a command or set its defaults' /> - <param name='mtu' doc='Set the maximum packet size' /> - </params> - </command> - <command id='prefix PREFIX'> - <params> - <param name='prefix' doc='Set the item name prefix' /> - <param name='PREFIX' doc='The prefix string' /> - </params> - </command> - <command id='no prefix'> - <params> - <param name='no' doc='Negate a command or set its defaults' /> - <param name='prefix' doc='Set the item name prefix' /> - </params> - </command> - <command id='level (global|peer|subscriber)'> - <params> - <param name='level' doc='Set the maximum group level' /> - <param name='global' doc='Report global groups only' /> - <param name='peer' doc='Report global and network peer related groups' /> - <param name='subscriber' doc='Report global, peer, and subscriber groups' /> - </params> - </command> - <command id='enable'> - <params> - <param name='enable' doc='Enable the reporter' /> - </params> - </command> - <command id='disable'> - <params> - <param name='disable' doc='Disable the reporter' /> - </params> - </command> - </node> - <node id='config-line'> - <name>config-line</name> - <command id='login'> - <params> - <param name='login' doc='Enable password checking' /> - </params> - </command> - <command id='no login'> - <params> - <param name='no' doc='Negate a command or set its defaults' /> - <param name='login' doc='Enable password checking' /> - </params> - </command> - <command id='bind A.B.C.D [<0-65535>]'> - <params> - <param name='bind' doc='Accept VTY telnet connections on local interface' /> - <param name='A.B.C.D' doc='Local interface IP address (default: 127.0.0.1)' /> - <param name='[<0-65535>]' doc='Local TCP port number' /> - </params> - </command> - </node> - <node id='config-ns'> - <name>config-ns</name> - <command id='nse <0-65535> nsvci <0-65534>'> - <params> - <param name='nse' doc='Persistent NS Entity' /> - <param name='<0-65535>' doc='NS Entity ID (NSEI)' /> - <param name='nsvci' doc='NS Virtual Connection' /> - <param name='<0-65534>' doc='NS Virtual Connection ID (NSVCI)' /> - </params> - </command> - <command id='nse <0-65535> remote-ip A.B.C.D'> - <params> - <param name='nse' doc='Persistent NS Entity' /> - <param name='<0-65535>' doc='NS Entity ID (NSEI)' /> - <param name='remote-ip' doc='Remote IP Address' /> - <param name='A.B.C.D' doc='Remote IP Address' /> - </params> - </command> - <command id='nse <0-65535> remote-port <0-65535>'> - <params> - <param name='nse' doc='Persistent NS Entity' /> - <param name='<0-65535>' doc='NS Entity ID (NSEI)' /> - <param name='remote-port' doc='Remote UDP Port' /> - <param name='<0-65535>' doc='Remote UDP Port Number' /> - </params> - </command> - <command id='nse <0-65535> fr-dlci <16-1007>'> - <params> - <param name='nse' doc='Persistent NS Entity' /> - <param name='<0-65535>' doc='NS Entity ID (NSEI)' /> - <param name='fr-dlci' doc='Frame Relay DLCI' /> - <param name='<16-1007>' doc='Frame Relay DLCI Number' /> - </params> - </command> - <command id='nse <0-65535> encapsulation (udp|framerelay-gre)'> - <params> - <param name='nse' doc='Persistent NS Entity' /> - <param name='<0-65535>' doc='NS Entity ID (NSEI)' /> - <param name='encapsulation' doc='Encapsulation for NS' /> - <param name='udp' doc='UDP/IP Encapsulation' /> - <param name='framerelay-gre' doc='Frame-Relay/GRE/IP Encapsulation' /> - </params> - </command> - <command id='nse <0-65535> remote-role (sgsn|bss)'> - <params> - <param name='nse' doc='Persistent NS Entity' /> - <param name='<0-65535>' doc='NS Entity ID (NSEI)' /> - <param name='remote-role' doc='Remote NSE Role' /> - <param name='sgsn' doc='Remote Peer is SGSN' /> - <param name='bss' doc='Remote Peer is BSS' /> - </params> - </command> - <command id='no nse <0-65535>'> - <params> - <param name='no' doc='Delete Persistent NS Entity' /> - <param name='nse' doc='Delete Persistent NS Entity' /> - <param name='<0-65535>' doc='NS Entity ID (NSEI)' /> - </params> - </command> - <command id='timer (tns-block|tns-block-retries|tns-reset|tns-reset-retries|tns-test|tns-alive|tns-alive-retries|tsns-prov) <0-65535>'> - <params> - <param name='timer' doc='Network Service Timer' /> - <param name='tns-block' doc='(un)blocking Timer (Tns-block) timeout' /> - <param name='tns-block-retries' doc='(un)blocking Timer (Tns-block) number of retries' /> - <param name='tns-reset' doc='Reset Timer (Tns-reset) timeout' /> - <param name='tns-reset-retries' doc='Reset Timer (Tns-reset) number of retries' /> - <param name='tns-test' doc='Test Timer (Tns-test) timeout' /> - <param name='tns-alive' doc='Alive Timer (Tns-alive) timeout' /> - <param name='tns-alive-retries' doc='Alive Timer (Tns-alive) number of retries' /> - <param name='tsns-prov' doc='SNS Provision Timer (Tsns-prov) timeout' /> - <param name='<0-65535>' doc='Timer Value' /> - </params> - </command> - <command id='encapsulation udp local-ip A.B.C.D'> - <params> - <param name='encapsulation' doc='NS encapsulation options' /> - <param name='udp' doc='NS over UDP Encapsulation' /> - <param name='local-ip' doc='Set the IP address on which we listen for NS/UDP' /> - <param name='A.B.C.D' doc='IP Address' /> - </params> - </command> - <command id='encapsulation udp local-port <0-65535>'> - <params> - <param name='encapsulation' doc='NS encapsulation options' /> - <param name='udp' doc='NS over UDP Encapsulation' /> - <param name='local-port' doc='Set the UDP port on which we listen for NS/UDP' /> - <param name='<0-65535>' doc='UDP port number' /> - </params> - </command> - <command id='encapsulation udp dscp <0-255>'> - <params> - <param name='encapsulation' doc='NS encapsulation options' /> - <param name='udp' doc='NS over UDP Encapsulation' /> - <param name='dscp' doc='Set DSCP/TOS on the UDP socket' /> - <param name='<0-255>' doc='DSCP Value' /> - </params> - </command> - <command id='encapsulation framerelay-gre enabled (1|0)'> - <params> - <param name='encapsulation' doc='NS encapsulation options' /> - <param name='framerelay-gre' doc='NS over Frame Relay over GRE Encapsulation' /> - <param name='enabled' doc='Enable or disable Frame Relay over GRE' /> - <param name='1' doc='Enable' /> - <param name='0' doc='Disable' /> - </params> - </command> - <command id='encapsulation framerelay-gre local-ip A.B.C.D'> - <params> - <param name='encapsulation' doc='NS encapsulation options' /> - <param name='framerelay-gre' doc='NS over Frame Relay over GRE Encapsulation' /> - <param name='local-ip' doc='Set the IP address on which we listen for NS/FR/GRE' /> - <param name='A.B.C.D' doc='IP Address' /> - </params> - </command> - </node> - <node id='config-gbproxy'> - <name>config-gbproxy</name> - <command id='sgsn nsei <0-65534>'> - <params> - <param name='sgsn' doc='SGSN information' /> - <param name='nsei' doc='NSEI to be used in the connection with the SGSN' /> - <param name='<0-65534>' doc='The NSEI' /> - </params> - </command> - <command id='core-mobile-country-code <1-999>'> - <params> - <param name='core-mobile-country-code' doc='Use this country code for the core network' /> - <param name='<1-999>' doc='MCC value' /> - </params> - </command> - <command id='core-mobile-network-code <1-999>'> - <params> - <param name='core-mobile-network-code' doc='Use this network code for the core network' /> - <param name='<1-999>' doc='NCC value' /> - </params> - </command> - <command id='match-imsi (patching|routing) .REGEXP'> - <params> - <param name='match-imsi' doc='Restrict actions to certain IMSIs' /> - <param name='patching' doc='Patch MS related information elements on match only' /> - <param name='routing' doc='Route to the secondary SGSN on match only' /> - <param name='.REGEXP' doc='Regular expression for the IMSI match' /> - </params> - </command> - <command id='core-access-point-name (APN|none)'> - <params> - <param name='core-access-point-name' doc='Use this access point name (APN) for the backbone' /> - <param name='APN' doc='Replace APN by this string' /> - <param name='none' doc='Remove APN' /> - </params> - </command> - <command id='secondary-sgsn nsei <0-65534>'> - <params> - <param name='secondary-sgsn' doc='Route matching LLC connections to a second SGSN (Experimental)' /> - <param name='nsei' doc='NSEI to be used in the connection with the SGSN' /> - <param name='<0-65534>' doc='The NSEI' /> - </params> - </command> - <command id='patch-ptmsi'> - <params> - <param name='patch-ptmsi' doc='Patch P-TMSI/TLLI' /> - </params> - </command> - <command id='acquire-imsi'> - <params> - <param name='acquire-imsi' doc='Acquire the IMSI before establishing a LLC connection (Experimental)' /> - </params> - </command> - <command id='link-list clean-stale-timer <1-999999>'> - <params> - <param name='link-list' doc='Set TLLI list parameters' /> - <param name='clean-stale-timer' doc='Periodic timer to clean stale links' /> - <param name='<1-999999>' doc='Frequency at which the periodic timer is fired (in seconds)' /> - </params> - </command> - <command id='link-list max-age <1-999999>'> - <params> - <param name='link-list' doc='Set TLLI list parameters' /> - <param name='max-age' doc='Limit maximum age' /> - <param name='<1-999999>' doc='Maximum age in seconds' /> - </params> - </command> - <command id='link-list max-length <1-99999>'> - <params> - <param name='link-list' doc='Set TLLI list parameters' /> - <param name='max-length' doc='Limit list length' /> - <param name='<1-99999>' doc='Maximum number of logical links in the list' /> - </params> - </command> - <command id='link-list keep-mode (never|re-attach|identified|always)'> - <params> - <param name='link-list' doc='Set TLLI list parameters' /> - <param name='keep-mode' doc='How to keep entries for detached logical links' /> - <param name='never' doc='Discard entry immediately after detachment' /> - <param name='re-attach' doc='Keep entry if a re-attachment has be requested' /> - <param name='identified' doc='Keep entry if it associated with an IMSI' /> - <param name='always' doc='Don't discard entries after detachment' /> - </params> - </command> - <command id='link stored-msgs-max-length <1-99999>'> - <params> - <param name='link' doc='Set TLLI parameters' /> - <param name='stored-msgs-max-length' doc='Limit list length' /> - <param name='<1-99999>' doc='Maximum number of msgb stored in the logical link waiting to acquire its IMSI' /> - </params> - </command> - <command id='no core-mobile-country-code'> - <params> - <param name='no' doc='Negate a command or set its defaults' /> - <param name='core-mobile-country-code' doc='Use this country code for the core network' /> - </params> - </command> - <command id='no core-mobile-network-code'> - <params> - <param name='no' doc='Negate a command or set its defaults' /> - <param name='core-mobile-network-code' doc='Use this network code for the core network' /> - </params> - </command> - <command id='no match-imsi'> - <params> - <param name='no' doc='Negate a command or set its defaults' /> - <param name='match-imsi' doc='Restrict actions to certain IMSIs' /> - </params> - </command> - <command id='no core-access-point-name'> - <params> - <param name='no' doc='Negate a command or set its defaults' /> - <param name='core-access-point-name' doc='Use this access point name (APN) for the backbone' /> - </params> - </command> - <command id='no secondary-sgsn'> - <params> - <param name='no' doc='Negate a command or set its defaults' /> - <param name='secondary-sgsn' doc='Route matching LLC connections to a second SGSN (Experimental)' /> - </params> - </command> - <command id='no patch-ptmsi'> - <params> - <param name='no' doc='Negate a command or set its defaults' /> - <param name='patch-ptmsi' doc='Patch P-TMSI/TLLI' /> - </params> - </command> - <command id='no acquire-imsi'> - <params> - <param name='no' doc='Negate a command or set its defaults' /> - <param name='acquire-imsi' doc='Acquire the IMSI before establishing a LLC connection (Experimental)' /> - </params> - </command> - <command id='no link-list clean-stale-timer'> - <params> - <param name='no' doc='Negate a command or set its defaults' /> - <param name='link-list' doc='Set TLLI list parameters' /> - <param name='clean-stale-timer' doc='Periodic timer to clean stale links' /> - </params> - </command> - <command id='no link-list max-age'> - <params> - <param name='no' doc='Negate a command or set its defaults' /> - <param name='link-list' doc='Set TLLI list parameters' /> - <param name='max-age' doc='Limit maximum age' /> - </params> - </command> - <command id='no link-list max-length'> - <params> - <param name='no' doc='Negate a command or set its defaults' /> - <param name='link-list' doc='Set TLLI list parameters' /> - <param name='max-length' doc='Limit list length' /> - </params> - </command> - <command id='no link stored-msgs-max-length'> - <params> - <param name='no' doc='Negate a command or set its defaults' /> - <param name='link' doc='Set TLLI parameters' /> - <param name='stored-msgs-max-length' doc='Limit list length' /> - </params> - </command> - </node> -</vtydoc> diff --git a/include/osmocom/sgsn/Makefile.am b/include/osmocom/sgsn/Makefile.am index 95c811aa5..51bdee8f7 100644 --- a/include/osmocom/sgsn/Makefile.am +++ b/include/osmocom/sgsn/Makefile.am @@ -2,7 +2,6 @@ noinst_HEADERS = \ common.h \ crc24.h \ debug.h \ - gb_proxy.h \ gprs_gb.h \ gprs_gb_parse.h \ gprs_gmm.h \ diff --git a/include/osmocom/sgsn/gb_proxy.h b/include/osmocom/sgsn/gb_proxy.h deleted file mode 100644 index d988cae7c..000000000 --- a/include/osmocom/sgsn/gb_proxy.h +++ /dev/null @@ -1,298 +0,0 @@ -#ifndef _GB_PROXY_H -#define _GB_PROXY_H - - -#include <osmocom/core/msgb.h> -#include <osmocom/core/timer.h> -#include <osmocom/core/fsm.h> -#include <osmocom/core/hashtable.h> -#include <osmocom/gsm/gsm23003.h> -#include <osmocom/gsm/gsm23236.h> -#include <osmocom/gsm/protocol/gsm_23_003.h> - -#include <osmocom/gprs/gprs_ns2.h> -#include <osmocom/vty/command.h> - -#include <sys/types.h> -#include <regex.h> -#include <stdbool.h> - -#define GBPROXY_INIT_VU_GEN_TX 256 -#define GBPROXY_MAX_NR_SGSN 16 - -/* BVCI uses 16 bits */ -#define BVC_LOG_CTX_FLAG (1<<17) - -struct rate_ctr_group; -struct gprs_gb_parse_context; -struct tlv_parsed; - -enum gbproxy_global_ctr { - GBPROX_GLOB_CTR_INV_BVCI, - GBPROX_GLOB_CTR_INV_LAI, - GBPROX_GLOB_CTR_INV_RAI, - GBPROX_GLOB_CTR_INV_NSEI, - GBPROX_GLOB_CTR_PROTO_ERR_BSS, - GBPROX_GLOB_CTR_PROTO_ERR_SGSN, - GBPROX_GLOB_CTR_NOT_SUPPORTED_BSS, - GBPROX_GLOB_CTR_NOT_SUPPORTED_SGSN, - GBPROX_GLOB_CTR_RESTART_RESET_SGSN, - GBPROX_GLOB_CTR_TX_ERR_SGSN, - GBPROX_GLOB_CTR_OTHER_ERR, -}; - -enum gbproxy_bvc_ctr { - GBPROX_PEER_CTR_BLOCKED, - GBPROX_PEER_CTR_UNBLOCKED, - GBPROX_PEER_CTR_DROPPED, - GBPROX_PEER_CTR_INV_NSEI, - GBPROX_PEER_CTR_TX_ERR, - GBPROX_PEER_CTR_LAST, -}; - -/* global gb-proxy configuration */ -struct gbproxy_config { - /* NS instance of libosmogb */ - struct gprs_ns2_inst *nsi; - - struct { - /* percentage of BVC flow control advertised to each SGSN in the pool */ - uint8_t bvc_fc_ratio; - /* NRI bitlen and usable NULL-NRI ranges */ - uint8_t nri_bitlen; - struct osmo_nri_ranges *null_nri_ranges; - - /* Used for testing: If not NULL then this SGSN is returned by - * gbproxy_sgsn_by_tlli() */ - struct gbproxy_sgsn *nsf_override; - } pool; - - /* hash table of all BSS side Gb peers */ - DECLARE_HASHTABLE(bss_nses, 8); - - /* hash table of all SGSN-side Gb peers */ - DECLARE_HASHTABLE(sgsn_nses, 8); - - /* hash table of all gbproxy_cell */ - DECLARE_HASHTABLE(cells, 8); - - /* tlli<->nse cache used to map SUSPEND/RESUME (N)ACKS */ - struct { - DECLARE_HASHTABLE(entries, 10); - struct osmo_timer_list timer; - /* Time in seconds that the entries should be valid */ - uint8_t timeout; - } tlli_cache; - - /* imsi<->nse cache used for PAGING REJECT */ - struct { - DECLARE_HASHTABLE(entries, 10); - struct osmo_timer_list timer; - /* Time in seconds that the entries should be valid */ - uint8_t timeout; - } imsi_cache; - - /* List of all SGSNs */ - struct llist_head sgsns; - - /* Counter */ - struct rate_ctr_group *ctrg; -}; - -/* One Cell within the BSS: Links BSS-side BVC to SGSN-side BVCs */ -struct gbproxy_cell { - /* linked to gbproxy_config.cells hashtable */ - struct hlist_node list; - - /* point back to the config */ - struct gbproxy_config *cfg; - - /* BVCI of PTP BVCs associated to this cell */ - uint16_t bvci; - - /* Routing Area that this BVC is part of (raw 04.08 encoding) */ - uint8_t ra[6]; - - /* pointer to the BSS-side BVC */ - struct gbproxy_bvc *bss_bvc; - - /* pointers to SGSN-side BVC (one for each pool member) */ - struct gbproxy_bvc *sgsn_bvc[GBPROXY_MAX_NR_SGSN]; -}; - -/* One BVC inside an NSE */ -struct gbproxy_bvc { - /* linked to gbproxy_nse.bvcs */ - struct hlist_node list; - - /* The NSE this BVC belongs to */ - struct gbproxy_nse *nse; - - /* PTP BVCI of this BVC */ - uint16_t bvci; - - /* Routing Area that this BVC is part of (raw 04.08 encoding) */ - uint8_t ra[6]; - - /* Counter */ - struct rate_ctr_group *ctrg; - - /* the cell to which this BVC belongs */ - struct gbproxy_cell *cell; - - /* per-BVC FSM instance */ - struct osmo_fsm_inst *fi; -}; - -/* one NS Entity that we interact with (BSS/PCU) */ -struct gbproxy_nse { - /* linked to gbproxy_config.bss_nses */ - struct hlist_node list; - - /* point back to the config */ - struct gbproxy_config *cfg; - - /* NSEI of the NSE */ - uint16_t nsei; - - /* Are we facing towards a SGSN (true) or BSS (false) */ - bool sgsn_facing; - - /* List of all BVCs in this NSE */ - DECLARE_HASHTABLE(bvcs, 10); -}; - -/* SGSN configuration such as pool options (only for NSE where sgsn_facing == true) */ -struct gbproxy_sgsn { - /* linked to gbproxy_config.sgsns */ - struct llist_head list; - - /* The NSE belonging to this SGSN */ - struct gbproxy_nse *nse; - - /* Name of the SGSN */ - char *name; - - /* Pool configuration for the sgsn (only valid if sgsn_facing == true) */ - struct { - bool allow_attach; - struct osmo_nri_ranges *nri_ranges; - } pool; -}; - -/* TLLI cache */ -struct gbproxy_tlli_cache_entry { - /* linked to gbproxy_config.tlli_cache.entries */ - struct hlist_node list; - - /* TLLI of the entry */ - uint32_t tlli; - /* When was this entry last seen */ - time_t tstamp; - /* The Cell this TLLI was last seen */ - struct gbproxy_nse *nse; -}; - -/* IMSI cache */ -struct gbproxy_imsi_cache_entry { - /* linked to gbproxy_config.imsi_cache.entries */ - struct hlist_node list; - - /* IMSI of the entry */ - char imsi[OSMO_IMSI_BUF_SIZE]; - /* When was this entry last seen */ - time_t tstamp; - /* The SGSN where the request came from */ - struct gbproxy_nse *nse; -}; - -/* Convenience logging macros for NSE/BVC */ -#define LOGPNSE_CAT(NSE, SUBSYS, LEVEL, FMT, ARGS...) \ - LOGP(SUBSYS, LEVEL, "NSE(%05u/%s) " FMT, (NSE)->nsei, \ - (NSE)->sgsn_facing ? "SGSN" : "BSS", ## ARGS) -#define LOGPNSE(NSE, LEVEL, FMT, ARGS...) \ - LOGPNSE_CAT(NSE, DGPRS, LEVEL, FMT, ## ARGS) - -#define LOGPBVC_CAT(BVC, SUBSYS, LEVEL, FMT, ARGS...) \ - LOGP(SUBSYS, LEVEL, "NSE(%05u/%s)-BVC(%05u/%s) " FMT, (BVC)->nse->nsei, \ - (BVC)->nse->sgsn_facing ? "SGSN" : "BSS", (BVC)->bvci, \ - osmo_fsm_inst_state_name((BVC)->fi), ## ARGS) -#define LOGPBVC(BVC, LEVEL, FMT, ARGS...) \ - LOGPBVC_CAT(BVC, DGPRS, LEVEL, FMT, ## ARGS) - -#define LOGPCELL_CAT(CELL, SUBSYS, LEVEL, FMT, ARGS...) \ - LOGP(SUBSYS, LEVEL, "CELL(%05u) " FMT, (CELL)->bvci, ## ARGS) -#define LOGPCELL(CELL, LEVEL, FMT, ARGS...) \ - LOGPCELL_CAT(CELL, DGPRS, LEVEL, FMT, ## ARGS) - -#define LOGPSGSN_CAT(SGSN, SUBSYS, LEVEL, FMT, ARGS...) \ - LOGP(SUBSYS, LEVEL, "NSE(%05u)-SGSN(%s) " FMT, (SGSN)->nse->nsei, (SGSN)->name, ## ARGS) -#define LOGPSGSN(SGSN, LEVEL, FMT, ARGS...) \ - LOGPSGSN_CAT(SGSN, DGPRS, LEVEL, FMT, ## ARGS) - -/* gb_proxy_vty .c */ - -int gbproxy_vty_init(void); -int gbproxy_parse_config(const char *config_file, struct gbproxy_config *cfg); - -/* gb_proxy_ctrl.c */ -int gb_ctrl_cmds_install(void); - - -/* gb_proxy.c */ -int gbproxy_init_config(struct gbproxy_config *cfg); - -/* Main input function for Gb proxy */ -int gbprox_rcvmsg(void *ctx, struct msgb *msg); - -int gbprox_signal(unsigned int subsys, unsigned int signal, - void *handler_data, void *signal_data); - - -int gprs_ns2_prim_cb(struct osmo_prim_hdr *oph, void *ctx); - -void gbprox_reset(struct gbproxy_config *cfg); - -/* Peer handling */ -#define NSE_F_SGSN 0x0001 -#define NSE_F_BSS 0x0002 - -struct gbproxy_bvc *gbproxy_bvc_by_bvci(struct gbproxy_nse *nse, uint16_t bvci); -struct gbproxy_bvc *gbproxy_bvc_alloc(struct gbproxy_nse *nse, uint16_t bvci); -void gbproxy_bvc_free(struct gbproxy_bvc *bvc); -int gbproxy_cleanup_bvcs(struct gbproxy_nse *nse, uint16_t bvci); - -struct gbproxy_cell *gbproxy_cell_alloc(struct gbproxy_config *cfg, uint16_t bvci); -struct gbproxy_cell *gbproxy_cell_by_bvci(struct gbproxy_config *cfg, uint16_t bvci); -void gbproxy_cell_free(struct gbproxy_cell *cell); -bool gbproxy_cell_add_sgsn_bvc(struct gbproxy_cell *cell, struct gbproxy_bvc *bvc); - -/* NSE handling */ -struct gbproxy_nse *gbproxy_nse_alloc(struct gbproxy_config *cfg, uint16_t nsei, bool sgsn_facing); -void gbproxy_nse_free(struct gbproxy_nse *nse); -struct gbproxy_nse *gbproxy_nse_by_nsei(struct gbproxy_config *cfg, uint16_t nsei, uint32_t flags); -struct gbproxy_nse *gbproxy_nse_by_nsei_or_new(struct gbproxy_config *cfg, uint16_t nsei, bool sgsn_facing); -struct gbproxy_nse *gbproxy_nse_by_tlli(struct gbproxy_config *cfg, uint32_t tlli); -struct gbproxy_nse *gbproxy_nse_by_imsi(struct gbproxy_config *cfg, const char *imsi); - -/* TLLI cache */ -void gbproxy_tlli_cache_update(struct gbproxy_nse *nse, uint32_t tlli); -void gbproxy_tlli_cache_remove(struct gbproxy_config *cfg, uint32_t tlli); -int gbproxy_tlli_cache_cleanup(struct gbproxy_config *cfg); - -/* IMSI cache */ -void gbproxy_imsi_cache_update(struct gbproxy_nse *nse, const char *imsi); -void gbproxy_imsi_cache_remove(struct gbproxy_config *cfg, const char *imsi); -int gbproxy_imsi_cache_cleanup(struct gbproxy_config *cfg); - -/* SGSN handling */ -struct gbproxy_sgsn *gbproxy_sgsn_alloc(struct gbproxy_config *cfg, uint16_t nsei, const char *name); -void gbproxy_sgsn_free(struct gbproxy_sgsn *sgsn); -struct gbproxy_sgsn *gbproxy_sgsn_by_name(struct gbproxy_config *cfg, const char *name); -struct gbproxy_sgsn *gbproxy_sgsn_by_nsei(struct gbproxy_config *cfg, uint16_t nsei); -struct gbproxy_sgsn *gbproxy_sgsn_by_nsei_or_new(struct gbproxy_config *cfg, uint16_t nsei); -struct gbproxy_sgsn *gbproxy_sgsn_by_nri(struct gbproxy_config *cfg, uint16_t nri, bool *null_nri); -struct gbproxy_sgsn *gbproxy_sgsn_by_tlli(struct gbproxy_config *cfg, struct gbproxy_sgsn *sgsn_avoid, - uint32_t tlli); - -#endif diff --git a/osmoappdesc.py b/osmoappdesc.py index 1fccafd7f..c3275978b 100644 --- a/osmoappdesc.py +++ b/osmoappdesc.py @@ -16,18 +16,16 @@ app_configs = { - "gbproxy": ["doc/examples/osmo-gbproxy/osmo-gbproxy.cfg"], "sgsn": ["doc/examples/osmo-sgsn/osmo-sgsn.cfg"], "gtphub": ["doc/examples/osmo-gtphub/osmo-gtphub-1iface.cfg"] } -apps = [(4246, "src/gbproxy/osmo-gbproxy", "OsmoGbProxy", "gbproxy"), - (4245, "src/sgsn/osmo-sgsn", "OsmoSGSN", "sgsn"), +apps = [(4245, "src/sgsn/osmo-sgsn", "OsmoSGSN", "sgsn"), (4253, "src/gtphub/osmo-gtphub", "OsmoGTPhub", "gtphub") ] vty_command = ["./src/sgsn/osmo-sgsn", "-c", "doc/examples/osmo-sgsn/osmo-sgsn.cfg"] -vty_app = apps[1] +vty_app = apps[0] diff --git a/src/Makefile.am b/src/Makefile.am index c45d3ab46..e389b7f65 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,6 +1,5 @@ SUBDIRS = \ gprs \ sgsn \ - gbproxy \ gtphub \ $(NULL) diff --git a/src/gbproxy/Makefile.am b/src/gbproxy/Makefile.am deleted file mode 100644 index 1500e1173..000000000 --- a/src/gbproxy/Makefile.am +++ /dev/null @@ -1,40 +0,0 @@ -AM_CPPFLAGS = \ - $(all_includes) \ - -I$(top_srcdir)/include \ - -I$(top_builddir) \ - $(NULL) - -AM_CFLAGS = \ - -Wall \ - -fno-strict-aliasing \ - $(LIBOSMOCORE_CFLAGS) \ - $(LIBOSMOGSM_CFLAGS) \ - $(LIBOSMOVTY_CFLAGS) \ - $(LIBOSMOCTRL_CFLAGS) \ - $(LIBOSMOABIS_CFLAGS) \ - $(LIBOSMOGB_CFLAGS) \ - $(LIBOSMOGSUPCLIENT_CFLAGS) \ - $(COVERAGE_CFLAGS) \ - $(LIBGTP_CFLAGS) \ - $(NULL) - -bin_PROGRAMS = \ - osmo-gbproxy \ - $(NULL) - -osmo_gbproxy_SOURCES = \ - gb_proxy.c \ - gb_proxy_main.c \ - gb_proxy_vty.c \ - gb_proxy_ctrl.c \ - gb_proxy_peer.c \ - $(NULL) -osmo_gbproxy_LDADD = \ - $(LIBOSMOCORE_LIBS) \ - $(LIBOSMOGSM_LIBS) \ - $(LIBOSMOVTY_LIBS) \ - $(LIBOSMOCTRL_LIBS) \ - $(LIBOSMOGB_LIBS) \ - $(LIBGTP_LIBS) \ - -lrt \ - $(NULL) diff --git a/src/gbproxy/gb_proxy.c b/src/gbproxy/gb_proxy.c deleted file mode 100644 index c882eb068..000000000 --- a/src/gbproxy/gb_proxy.c +++ /dev/null @@ -1,1549 +0,0 @@ -/* NS-over-IP proxy */ - -/* (C) 2010-2020 by Harald Welte <laforge@gnumonks.org> - * (C) 2010-2013 by On-Waves - * (C) 2013 by Holger Hans Peter Freyther - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU 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 <unistd.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <getopt.h> -#include <errno.h> -#include <sys/fcntl.h> -#include <sys/stat.h> -#include <arpa/inet.h> -#include <time.h> - -#include <osmocom/core/hashtable.h> -#include <osmocom/core/logging.h> -#include <osmocom/core/linuxlist.h> -#include <osmocom/core/talloc.h> -#include <osmocom/core/select.h> -#include <osmocom/core/rate_ctr.h> -#include <osmocom/core/stats.h> -#include <osmocom/core/utils.h> - -#include <osmocom/gprs/gprs_ns2.h> -#include <osmocom/gprs/gprs_bssgp.h> -#include <osmocom/gprs/gprs_bssgp2.h> -#include <osmocom/gprs/gprs_bssgp_bss.h> -#include <osmocom/gprs/bssgp_bvc_fsm.h> - -#include <osmocom/gsm/gsm23236.h> -#include <osmocom/gsm/gsm_utils.h> - -#include <osmocom/sgsn/signal.h> -#include <osmocom/sgsn/debug.h> -#include <osmocom/sgsn/gprs_gb_parse.h> -#include <osmocom/sgsn/gb_proxy.h> - -#include <osmocom/sgsn/gprs_llc.h> -#include <osmocom/gsm/protocol/gsm_04_08_gprs.h> -#include <osmocom/sgsn/gprs_utils.h> - -extern void *tall_sgsn_ctx; - -static const struct rate_ctr_desc global_ctr_description[] = { - { "inv-bvci", "Invalid BVC Identifier " }, - { "inv-lai", "Invalid Location Area Identifier" }, - { "inv-rai", "Invalid Routing Area Identifier " }, - { "inv-nsei", "No BVC established for NSEI " }, - { "proto-err:bss", "BSSGP protocol error (BSS )" }, - { "proto-err:sgsn", "BSSGP protocol error (SGSN)" }, - { "not-supp:bss", "Feature not supported (BSS )" }, - { "not-supp:sgsn", "Feature not supported (SGSN)" }, - { "restart:sgsn", "Restarted RESET procedure (SGSN)" }, - { "tx-err:sgsn", "NS Transmission error (SGSN)" }, - { "error", "Other error " }, - { "mod-peer-err", "Patch error: no peer " }, -}; - -static const struct rate_ctr_group_desc global_ctrg_desc = { - .group_name_prefix = "gbproxy:global", - .group_description = "GBProxy Global Statistics", - .num_ctr = ARRAY_SIZE(global_ctr_description), - .ctr_desc = global_ctr_description, - .class_id = OSMO_STATS_CLASS_GLOBAL, -}; - -static int gbprox_relay2peer(struct msgb *old_msg, struct gbproxy_bvc *bvc, - uint16_t ns_bvci); - - -/* generate BVC-STATUS message with cause value derived from TLV-parser error */ -static int tx_status_from_tlvp(enum osmo_tlv_parser_error tlv_p_err, struct msgb *orig_msg) -{ - uint8_t bssgp_cause; - switch (tlv_p_err) { - case OSMO_TLVP_ERR_MAND_IE_MISSING: - bssgp_cause = BSSGP_CAUSE_MISSING_MAND_IE; - break; - default: - bssgp_cause = BSSGP_CAUSE_PROTO_ERR_UNSPEC; - } - return bssgp_tx_status(bssgp_cause, NULL, orig_msg); -} - -/* strip off the NS header */ -static void strip_ns_hdr(struct msgb *msg) -{ - int strip_len = msgb_bssgph(msg) - msg->data; - msgb_pull(msg, strip_len); -} - -#if 0 -/* feed a message down the NS-VC associated with the specified bvc */ -static int gbprox_relay2sgsn(struct gbproxy_config *cfg, struct msgb *old_msg, - uint16_t ns_bvci, uint16_t sgsn_nsei) -{ - /* create a copy of the message so the old one can - * be free()d safely when we return from gbprox_rcvmsg() */ - struct gprs_ns2_inst *nsi = cfg->nsi; - struct osmo_gprs_ns2_prim nsp = {}; - struct msgb *msg = bssgp_msgb_copy(old_msg, "msgb_relay2sgsn"); - int rc; - - DEBUGP(DGPRS, "NSE(%05u/BSS)-BVC(%05u) proxying BTS->SGSN NSE(%05u/SGSN)\n", - msgb_nsei(msg), ns_bvci, sgsn_nsei); - - nsp.bvci = ns_bvci; - nsp.nsei = sgsn_nsei; - - strip_ns_hdr(msg); - osmo_prim_init(&nsp.oph, SAP_NS, PRIM_NS_UNIT_DATA, - PRIM_OP_REQUEST, msg); - rc = gprs_ns2_recv_prim(nsi, &nsp.oph); - if (rc < 0) - rate_ctr_inc(&cfg->ctrg->ctr[GBPROX_GLOB_CTR_TX_ERR_SGSN]); - return rc; -} -#endif - -/*! Determine the TLLI from the given BSSGP message. - * \param[in] bssgp pointer to start of BSSGP header - * \param[in] bssgp_len length of BSSGP message in octets - * \param[out] tlli TLLI (if any) in host byte order - * \returns 1 if TLLI found; 0 if none found; negative on parse error */ -int gprs_gb_parse_tlli(const uint8_t *bssgp, size_t bssgp_len, uint32_t *tlli) -{ - const struct bssgp_normal_hdr *bgph; - uint8_t pdu_type; - - if (bssgp_len < sizeof(struct bssgp_normal_hdr)) - return -EINVAL; - - bgph = (struct bssgp_normal_hdr *)bssgp; - pdu_type = bgph->pdu_type; - - if (pdu_type == BSSGP_PDUT_UL_UNITDATA || - pdu_type == BSSGP_PDUT_DL_UNITDATA) { - const struct bssgp_ud_hdr *budh = (struct bssgp_ud_hdr *)bssgp; - if (bssgp_len < sizeof(struct bssgp_ud_hdr)) - return -EINVAL; - *tlli = osmo_load32be((const uint8_t *)&budh->tlli); - return 1; - } else { - const uint8_t *data = bgph->data; - size_t data_len = bssgp_len - sizeof(*bgph); - struct tlv_parsed tp; - - if (bssgp_tlv_parse(&tp, data, data_len) < 0) - return -EINVAL; - - if (TLVP_PRESENT(&tp, BSSGP_IE_TLLI)) { - *tlli = osmo_load32be(TLVP_VAL(&tp, BSSGP_IE_TLLI)); - return 1; - } - } - - /* No TLLI present in message */ - return 0; -} - -/* feed a message down the NSE */ -static int gbprox_relay2nse(struct msgb *old_msg, struct gbproxy_nse *nse, - uint16_t ns_bvci) -{ - OSMO_ASSERT(nse); - OSMO_ASSERT(nse->cfg); - - /* create a copy of the message so the old one can - * be free()d safely when we return from gbprox_rcvmsg() */ - struct gprs_ns2_inst *nsi = nse->cfg->nsi; - struct osmo_gprs_ns2_prim nsp = {}; - struct msgb *msg = bssgp_msgb_copy(old_msg, "msgb_relay2nse"); - uint32_t tlli; - int rc; - - DEBUGP(DGPRS, "NSE(%05u/%s)-BVC(%05u/??) proxying to NSE(%05u/%s)\n", msgb_nsei(msg), - !nse->sgsn_facing ? "SGSN" : "BSS", ns_bvci, nse->nsei, nse->sgsn_facing ? "SGSN" : "BSS"); - - nsp.bvci = ns_bvci; - nsp.nsei = nse->nsei; - - /* Strip the old NS header, it will be replaced with a new one */ - strip_ns_hdr(msg); - - /* TS 48.018 Section 5.4.2: The link selector parameter is - * defined in 3GPP TS 48.016. At one side of the Gb interface, - * all BSSGP UNITDATA PDUs related to an MS shall be passed with - * the same LSP, e.g. the LSP contains the MS's TLLI, to the - * underlying network service. */ - if (gprs_gb_parse_tlli(msgb_data(msg), msgb_length(msg), &tlli) == 1) - nsp.u.unitdata.link_selector = tlli; - - osmo_prim_init(&nsp.oph, SAP_NS, GPRS_NS2_PRIM_UNIT_DATA, - PRIM_OP_REQUEST, msg); - rc = gprs_ns2_recv_prim(nsi, &nsp.oph); - /* FIXME: We need a counter group for gbproxy_nse */ - //if (rc < 0) - // rate_ctr_inc(&bvc->ctrg->ctr[GBPROX_PEER_CTR_TX_ERR]); - - return rc; -} - -/* feed a message down the NS-VC associated with the specified bvc */ -static int gbprox_relay2peer(struct msgb *old_msg, struct gbproxy_bvc *bvc, - uint16_t ns_bvci) -{ - int rc; - struct gbproxy_nse *nse = bvc->nse; - OSMO_ASSERT(nse); - - rc = gbprox_relay2nse(old_msg, nse, ns_bvci); - if (rc < 0) - rate_ctr_inc(&bvc->ctrg->ctr[GBPROX_PEER_CTR_TX_ERR]); - - return rc; -} - -int bssgp_prim_cb(struct osmo_prim_hdr *oph, void *ctx) -{ - return 0; -} - - -/*********************************************************************** - * PTP BVC handling - ***********************************************************************/ - -/* FIXME: Handle the tlli NULL case correctly, - * This function should take a generic selector - * and choose an sgsn based on that - */ -static struct gbproxy_sgsn *gbproxy_select_sgsn(struct gbproxy_config *cfg, const uint32_t *tlli) -{ - struct gbproxy_sgsn *sgsn = NULL; - struct gbproxy_sgsn *sgsn_avoid = NULL; - - int tlli_type; - int16_t nri; - bool null_nri = false; - - if (!tlli) { - sgsn = llist_first_entry(&cfg->sgsns, struct gbproxy_sgsn, list); - if (!sgsn) { - return NULL; - } - LOGPSGSN(sgsn, LOGL_INFO, "Could not get TLLI, using first SGSN\n"); - return sgsn; - } - - if (cfg->pool.nri_bitlen == 0) { - /* Pooling is disabled */ - sgsn = llist_first_entry(&cfg->sgsns, struct gbproxy_sgsn, list); - if (!sgsn) { - return NULL; - } - - LOGPSGSN(sgsn, LOGL_INFO, "Pooling disabled, using first configured SGSN\n"); - } else { - /* Pooling is enabled, try to use the NRI for routing to an SGSN - * See 3GPP TS 23.236 Ch. 5.3.2 */ - tlli_type = gprs_tlli_type(*tlli); - if (tlli_type == TLLI_LOCAL || tlli_type == TLLI_FOREIGN) { - /* Only get/use the NRI if tlli type is local */ - osmo_tmsi_nri_v_get(&nri, *tlli, cfg->pool.nri_bitlen); - if (nri >= 0) { - /* Get the SGSN for the NRI */ - sgsn = gbproxy_sgsn_by_nri(cfg, nri, &null_nri); - if (sgsn && !null_nri) - return sgsn; - /* If the NRI is the null NRI, we need to avoid the chosen SGSN */ - if (null_nri && sgsn) { - sgsn_avoid = sgsn; - } - } else { - /* We couldn't get the NRI from the TLLI */ - LOGP(DGPRS, LOGL_ERROR, "Could not extract NRI from local TLLI %08x\n", *tlli); - } - } else { - LOGP(DGPRS, LOGL_INFO, "TLLI %08x is neither local nor foreign, not routing by NRI\n", *tlli); - } - } - - /* If we haven't found an SGSN yet we need to choose one, but avoid the one in sgsn_avoid - * NOTE: This function is not stable if the number of SGSNs or allow_attach changes - * We could implement TLLI tracking here, but 3GPP TS 23.236 Ch. 5.3.2 (see NOTE) argues that - * we can just wait for the MS to reattempt the procedure. - */ - if (!sgsn) - sgsn = gbproxy_sgsn_by_tlli(cfg, sgsn_avoid, *tlli); - - if (!sgsn) { - LOGP(DGPRS, LOGL_ERROR, "No suitable SGSN found for TLLI %u\n", *tlli); - return NULL; - } - - return sgsn; -} - -/*! Find the correct gbproxy_bvc given a cell and an SGSN - * \param[in] cfg The gbproxy configuration - * \param[in] cell The cell the message belongs to - * \param[in] tlli An optional TLLI used for tracking - * \return Returns 0 on success, otherwise a negative value - */ -static struct gbproxy_bvc *gbproxy_select_sgsn_bvc(struct gbproxy_config *cfg, struct gbproxy_cell *cell, const uint32_t *tlli) -{ - struct gbproxy_sgsn *sgsn; - struct gbproxy_bvc *sgsn_bvc = NULL; - int i; - - sgsn = gbproxy_select_sgsn(cfg, tlli); - if (!sgsn) { - LOGPCELL(cell, LOGL_ERROR, "Could not find any SGSN, dropping message!\n"); - return NULL; - } - - /* Get the BVC for this SGSN/NSE */ - for (i = 0; i < ARRAY_SIZE(cell->sgsn_bvc); i++) { - sgsn_bvc = cell->sgsn_bvc[i]; - if (!sgsn_bvc) - continue; - if (sgsn->nse != sgsn_bvc->nse) - continue; - - return sgsn_bvc; - } - - /* This shouldn't happen */ - LOGPCELL(cell, LOGL_ERROR, "Could not find matching BVC for SGSN %s, dropping message!\n", sgsn->name); - return NULL; -} - -/*! Send a message to the next SGSN, possibly ignoring the null SGSN - * route an uplink message on a PTP-BVC to a SGSN using the TLLI - * \param[in] cell The cell the message belongs to - * \param[in] msg The BSSGP message - * \param[in] null_sgsn If not NULL then avoid this SGSN (because this message contains its null NRI) - * \param[in] tlli An optional TLLI used for tracking - * \return Returns 0 on success, otherwise a negative value - */ -static int gbprox_bss2sgsn_tlli(struct gbproxy_cell *cell, struct msgb *msg, const uint32_t *tlli, - bool sig_bvci) -{ - struct gbproxy_config *cfg = cell->cfg; - struct gbproxy_bvc *sgsn_bvc; - - sgsn_bvc = gbproxy_select_sgsn_bvc(cfg, cell, tlli); - if (!sgsn_bvc) { - LOGPCELL(cell, LOGL_NOTICE, "Could not find any SGSN for TLLI %u, dropping message!\n", *tlli); - return -EINVAL; - } - - return gbprox_relay2peer(msg, sgsn_bvc, sig_bvci ? 0 : sgsn_bvc->bvci); -} - -/* Receive an incoming PTP message from a BSS-side NS-VC */ -static int gbprox_rx_ptp_from_bss(struct gbproxy_nse *nse, struct msgb *msg, uint16_t ns_bvci) -{ - struct bssgp_normal_hdr *bgph = (struct bssgp_normal_hdr *) msgb_bssgph(msg); - const char *pdut_name = osmo_tlv_prot_msg_name(&osmo_pdef_bssgp, bgph->pdu_type); - struct gbproxy_bvc *bss_bvc; - struct tlv_parsed tp; - char log_pfx[32]; - uint32_t tlli; - int rc; - - snprintf(log_pfx, sizeof(log_pfx), "NSE(%05u/BSS)-BVC(%05u/??)", nse->nsei, ns_bvci); - - LOGP(DGPRS, LOGL_DEBUG, "%s Rx %s\n", log_pfx, pdut_name); - - if (ns_bvci == 0 || ns_bvci == 1) { - LOGP(DGPRS, LOGL_NOTICE, "%s BVCI=%05u is not PTP\n", log_pfx, ns_bvci); - return bssgp_tx_status(BSSGP_CAUSE_PROTO_ERR_UNSPEC, NULL, msg); - } - - if (!(bssgp_pdu_type_flags(bgph->pdu_type) & BSSGP_PDUF_PTP)) { - LOGP(DGPRS, LOGL_NOTICE, "%s %s not allowed in PTP BVC\n", log_pfx, pdut_name); - return bssgp_tx_status(BSSGP_CAUSE_PROTO_ERR_UNSPEC, NULL, msg); - } - - if (!(bssgp_pdu_type_flags(bgph->pdu_type) & BSSGP_PDUF_UL)) { - LOGP(DGPRS, LOGL_NOTICE, "%s %s not allowed in uplink direction\n", log_pfx, pdut_name); - return bssgp_tx_status(BSSGP_CAUSE_PROTO_ERR_UNSPEC, NULL, msg); - } - - bss_bvc = gbproxy_bvc_by_bvci(nse, ns_bvci); - if (!bss_bvc) { - LOGP(DGPRS, LOGL_NOTICE, "%s %s - Didn't find BVC for PTP message, discarding\n", - log_pfx, pdut_name); - return bssgp_tx_status(BSSGP_CAUSE_UNKNOWN_BVCI, &ns_bvci, msg); - } - - /* UL_UNITDATA has a different header than all other uplink PDUs */ - if (bgph->pdu_type == BSSGP_PDUT_UL_UNITDATA) { - const struct bssgp_ud_hdr *budh = (struct bssgp_ud_hdr *) msgb_bssgph(msg); - if (msgb_bssgp_len(msg) < sizeof(*budh)) - return bssgp_tx_status(BSSGP_CAUSE_INV_MAND_INF, NULL, msg); - rc = osmo_tlv_prot_parse(&osmo_pdef_bssgp, &tp, 1, bgph->pdu_type, budh->data, - msgb_bssgp_len(msg) - sizeof(*budh), 0, 0, DGPRS, log_pfx); - /* populate TLLI from the fixed headser into the TLV-parsed array so later code - * doesn't have to worry where the TLLI came from */ - tp.lv[BSSGP_IE_TLLI].len = 4; - tp.lv[BSSGP_IE_TLLI].val = (const uint8_t *) &budh->tlli; - } else { - rc = osmo_tlv_prot_parse(&osmo_pdef_bssgp, &tp, 1, bgph->pdu_type, bgph->data, - msgb_bssgp_len(msg) - sizeof(*bgph), 0, 0, DGPRS, log_pfx); - } - if (rc < 0) { - rate_ctr_inc(&nse->cfg->ctrg->ctr[GBPROX_GLOB_CTR_PROTO_ERR_BSS]); - return tx_status_from_tlvp(rc, msg); - } - /* hack to get both msg + tlv_parsed passed via osmo_fsm_inst_dispatch */ - msgb_bcid(msg) = (void *)&tp; - - switch (bgph->pdu_type) { - case BSSGP_PDUT_UL_UNITDATA: - case BSSGP_PDUT_RA_CAPA_UPDATE: - case BSSGP_PDUT_FLOW_CONTROL_MS: - case BSSGP_PDUT_DOWNLOAD_BSS_PFC: - case BSSGP_PDUT_CREATE_BSS_PFC_ACK: - case BSSGP_PDUT_CREATE_BSS_PFC_NACK: - case BSSGP_PDUT_MODIFY_BSS_PFC_ACK: - case BSSGP_PDUT_DELETE_BSS_PFC_ACK: - case BSSGP_PDUT_FLOW_CONTROL_PFC: - case BSSGP_PDUT_DELETE_BSS_PFC_REQ: - case BSSGP_PDUT_PS_HO_REQUIRED: - case BSSGP_PDUT_PS_HO_REQUEST_ACK: - case BSSGP_PDUT_PS_HO_REQUEST_NACK: - case BSSGP_PDUT_PS_HO_COMPLETE: - case BSSGP_PDUT_PS_HO_CANCEL: - /* We can route based on TLLI-NRI */ - tlli = osmo_load32be(TLVP_VAL(&tp, BSSGP_IE_TLLI)); - rc = gbprox_bss2sgsn_tlli(bss_bvc->cell, msg, &tlli, false); - break; - case BSSGP_PDUT_RADIO_STATUS: - if (TLVP_PRESENT(&tp, BSSGP_IE_TLLI)) { - tlli = osmo_load32be(TLVP_VAL(&tp, BSSGP_IE_TLLI)); - rc = gbprox_bss2sgsn_tlli(bss_bvc->cell, msg, &tlli, false); - } else if (TLVP_PRESENT(&tp, BSSGP_IE_TMSI)) { - /* we treat the TMSI like a TLLI and extract the NRI from it */ - tlli = osmo_load32be(TLVP_VAL(&tp, BSSGP_IE_TMSI)); - /* Convert the TMSI into a FOREIGN TLLI so it is routed appropriately */ - tlli = gprs_tmsi2tlli(tlli, TLLI_FOREIGN); - rc = gbprox_bss2sgsn_tlli(bss_bvc->cell, msg, &tlli, false); - } else if (TLVP_PRESENT(&tp, BSSGP_IE_IMSI)) { - /* FIXME: Use the IMSI as selector? */ - rc = gbprox_bss2sgsn_tlli(bss_bvc->cell, msg, NULL, false); - /* rc = gbprox_bss2sgsn_hashed(bss_bvc->cell, msg, NULL); */ - } else - LOGPBVC(bss_bvc, LOGL_ERROR, "Rx RADIO-STATUS without any of the conditional IEs\n"); - break; - case BSSGP_PDUT_DUMMY_PAGING_PS_RESP: - case BSSGP_PDUT_PAGING_PS_REJECT: - { - /* Route according to IMSI<->NSE cache entry */ - struct osmo_mobile_identity mi; - const uint8_t *mi_data = TLVP_VAL(&tp, BSSGP_IE_IMSI); - uint8_t mi_len = TLVP_LEN(&tp, BSSGP_IE_IMSI); - osmo_mobile_identity_decode(&mi, mi_data, mi_len, false); - nse = gbproxy_nse_by_imsi(nse->cfg, mi.imsi); - if (nse) { - OSMO_ASSERT(nse->sgsn_facing); - rc = gbprox_relay2nse(msg, nse, ns_bvci); - } else { - LOGPBVC(bss_bvc, LOGL_ERROR, "Rx unmatched %s with IMSI %s\n", pdut_name, mi.imsi); - } - break; - } - case BSSGP_PDUT_FLOW_CONTROL_BVC: - osmo_fsm_inst_dispatch(bss_bvc->fi, BSSGP_BVCFSM_E_RX_FC_BVC, msg); - break; - case BSSGP_PDUT_STATUS: - /* TODO: Implement by inspecting the contained PDU */ - if (!TLVP_PRESENT(&tp, BSSGP_IE_PDU_IN_ERROR)) - break; - LOGPBVC(bss_bvc, LOGL_ERROR, "Rx %s: Implementation missing\n", pdut_name); - break; - } - - return 0; -} - -/* Receive an incoming PTP message from a SGSN-side NS-VC */ -static int gbprox_rx_ptp_from_sgsn(struct gbproxy_nse *nse, struct msgb *msg, uint16_t ns_bvci) -{ - struct bssgp_normal_hdr *bgph = (struct bssgp_normal_hdr *) msgb_bssgph(msg); - const char *pdut_name = osmo_tlv_prot_msg_name(&osmo_pdef_bssgp, bgph->pdu_type); - struct gbproxy_bvc *sgsn_bvc, *bss_bvc; - struct tlv_parsed tp; - char log_pfx[32]; - int rc; - - snprintf(log_pfx, sizeof(log_pfx), "NSE(%05u/SGSN)-BVC(%05u/??)", nse->nsei, ns_bvci); - - LOGP(DGPRS, LOGL_DEBUG, "%s Rx %s\n", log_pfx, pdut_name); - - if (ns_bvci == 0 || ns_bvci == 1) { - LOGP(DGPRS, LOGL_NOTICE, "%s BVCI is not PTP\n", log_pfx); - return bssgp_tx_status(BSSGP_CAUSE_PROTO_ERR_UNSPEC, NULL, msg); - } - - if (!(bssgp_pdu_type_flags(bgph->pdu_type) & BSSGP_PDUF_PTP)) { - LOGP(DGPRS, LOGL_NOTICE, "%s %s not allowed in PTP BVC\n", log_pfx, pdut_name); - return bssgp_tx_status(BSSGP_CAUSE_PROTO_ERR_UNSPEC, NULL, msg); - } - - if (!(bssgp_pdu_type_flags(bgph->pdu_type) & BSSGP_PDUF_DL)) { - LOGP(DGPRS, LOGL_NOTICE, "%s %s not allowed in downlink direction\n", log_pfx, pdut_name); - return bssgp_tx_status(BSSGP_CAUSE_PROTO_ERR_UNSPEC, NULL, msg); - } - - sgsn_bvc = gbproxy_bvc_by_bvci(nse, ns_bvci); - if (!sgsn_bvc) { - LOGP(DGPRS, LOGL_NOTICE, "%s %s - Didn't find BVC for for PTP message, discarding\n", - log_pfx, pdut_name); - rate_ctr_inc(&nse->cfg->ctrg-> ctr[GBPROX_GLOB_CTR_INV_BVCI]); - return bssgp_tx_status(BSSGP_CAUSE_UNKNOWN_BVCI, &ns_bvci, msg); - } - - if (!bssgp_bvc_fsm_is_unblocked(sgsn_bvc->fi)) { - LOGPBVC(sgsn_bvc, LOGL_NOTICE, "Rx %s: Dropping on blocked BVC\n", pdut_name); - rate_ctr_inc(&sgsn_bvc->ctrg->ctr[GBPROX_PEER_CTR_DROPPED]); - return bssgp_tx_status(BSSGP_CAUSE_BVCI_BLOCKED, &ns_bvci, msg); - } - - /* DL_UNITDATA has a different header than all other uplink PDUs */ - if (bgph->pdu_type == BSSGP_PDUT_DL_UNITDATA) { - const struct bssgp_ud_hdr *budh = (struct bssgp_ud_hdr *) msgb_bssgph(msg); - if (msgb_bssgp_len(msg) < sizeof(*budh)) - return bssgp_tx_status(BSSGP_CAUSE_INV_MAND_INF, NULL, msg); - rc = osmo_tlv_prot_parse(&osmo_pdef_bssgp, &tp, 1, bgph->pdu_type, budh->data, - msgb_bssgp_len(msg) - sizeof(*budh), 0, 0, DGPRS, log_pfx); - /* populate TLLI from the fixed headser into the TLV-parsed array so later code - * doesn't have to worry where the TLLI came from */ - tp.lv[BSSGP_IE_TLLI].len = 4; - tp.lv[BSSGP_IE_TLLI].val = (const uint8_t *) &budh->tlli; - } else { - rc = osmo_tlv_prot_parse(&osmo_pdef_bssgp, &tp, 1, bgph->pdu_type, bgph->data, - msgb_bssgp_len(msg) - sizeof(*bgph), 0, 0, DGPRS, log_pfx); - } - if (rc < 0) { - rate_ctr_inc(&nse->cfg->ctrg->ctr[GBPROX_GLOB_CTR_PROTO_ERR_BSS]); - return tx_status_from_tlvp(rc, msg); - } - /* hack to get both msg + tlv_parsed passed via osmo_fsm_inst_dispatch */ - msgb_bcid(msg) = (void *)&tp; - - OSMO_ASSERT(sgsn_bvc->cell); - bss_bvc = sgsn_bvc->cell->bss_bvc; - - switch (bgph->pdu_type) { - case BSSGP_PDUT_FLOW_CONTROL_BVC_ACK: - return osmo_fsm_inst_dispatch(sgsn_bvc->fi, BSSGP_BVCFSM_E_RX_FC_BVC_ACK, msg); - case BSSGP_PDUT_DUMMY_PAGING_PS: - case BSSGP_PDUT_PAGING_PS: - { - /* Cache the IMSI<->NSE to route PAGING REJECT */ - struct osmo_mobile_identity mi; - const uint8_t *mi_data = TLVP_VAL(&tp, BSSGP_IE_IMSI); - uint8_t mi_len = TLVP_LEN(&tp, BSSGP_IE_IMSI); - osmo_mobile_identity_decode(&mi, mi_data, mi_len, false); - gbproxy_imsi_cache_update(nse, mi.imsi); - break; - } - default: - break; - } - return gbprox_relay2peer(msg, bss_bvc, bss_bvc->bvci); - -} - -/*********************************************************************** - * BVC FSM call-backs - ***********************************************************************/ - -/* helper function to dispatch a FSM event to all SGSN-side BVC FSMs of a cell */ -static void dispatch_to_all_sgsn_bvc(struct gbproxy_cell *cell, uint32_t event, void *priv) -{ - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(cell->sgsn_bvc); i++) { - struct gbproxy_bvc *sgsn_bvc = cell->sgsn_bvc[i]; - if (!sgsn_bvc) - continue; - osmo_fsm_inst_dispatch(sgsn_bvc->fi, event, priv); - } -} - -/* BVC FSM informs us about a BSS-side reset of the signaling BVC */ -static void bss_sig_bvc_reset_notif(uint16_t nsei, uint16_t bvci, const struct gprs_ra_id *ra_id, - uint16_t cell_id, uint8_t cause, void *priv) -{ - struct gbproxy_bvc *sig_bvc = priv; - struct gbproxy_nse *nse = sig_bvc->nse; - struct gbproxy_bvc *ptp_bvc; - unsigned int i; - - /* BLOCK all SGSN-side PTP BVC within this NSE */ - hash_for_each(nse->bvcs, i, ptp_bvc, list) { - if (ptp_bvc == sig_bvc) - continue; - OSMO_ASSERT(ptp_bvc->cell); - - dispatch_to_all_sgsn_bvc(ptp_bvc->cell, BSSGP_BVCFSM_E_REQ_BLOCK, &cause); - } - - /* Delete all BSS-side PTP BVC within this NSE */ - gbproxy_cleanup_bvcs(nse, 0); - - /* TODO: we keep the "CELL" around for now, re-connecting it to - * any (later) new PTP-BVC for that BVCI. Not sure if that's the - * best idea ? */ -} - -/* forward declaration */ -static const struct bssgp_bvc_fsm_ops sgsn_ptp_bvc_fsm_ops; - -static const struct bssgp_bvc_fsm_ops bss_sig_bvc_fsm_ops = { - .reset_notification = bss_sig_bvc_reset_notif, -}; - -/* BVC FSM informs us about a BSS-side reset of a PTP BVC */ -static void bss_ptp_bvc_reset_notif(uint16_t nsei, uint16_t bvci, const struct gprs_ra_id *ra_id, - uint16_t cell_id, uint8_t cause, void *priv) -{ - struct gbproxy_bvc *bvc = priv; - struct gbproxy_config *cfg = bvc->nse->cfg; - struct gbproxy_nse *sgsn_nse; - unsigned int i; - - OSMO_ASSERT(bvci != 0); - - if (!bvc->cell) { - /* see if we have a CELL dangling around */ - bvc->cell = gbproxy_cell_by_bvci(cfg, bvci); - if (bvc->cell) { - /* the CELL already exists. This means either it * was created before at an - * earlier PTP BVC-RESET, or that there are non-unique BVCIs and hence a - * malconfiguration */ - if (bvc->cell->bss_bvc) { - LOGPBVC(bvc, LOGL_NOTICE, "Rx BVC-RESET via this NSE, but CELL already " - "has BVC on NSEI=%05u\n", bvc->cell->bss_bvc->nse->nsei); - LOGPBVC(bvc->cell->bss_bvc, LOGL_NOTICE, "Destroying due to conflicting " - "BVCI configuration (new NSEI=%05u)!\n", bvc->nse->nsei); - gbproxy_bvc_free(bvc->cell->bss_bvc); - } - bvc->cell->bss_bvc = bvc; - } - } - - if (!bvc->cell) { - /* if we end up here, it means this is the first time we received a BVC-RESET - * for this BVC. We need to create the 'cell' data structure and the SGSN-side - * BVC counterparts */ - - bvc->cell = gbproxy_cell_alloc(cfg, bvci); - OSMO_ASSERT(bvc->cell); - memcpy(bvc->cell->ra, bvc->ra, sizeof(bvc->cell->ra)); - - /* link us to the cell and vice-versa */ - bvc->cell->bss_bvc = bvc; - } - - /* allocate (any missing) SGSN-side BVCs within the cell, and reset them */ - hash_for_each(cfg->sgsn_nses, i, sgsn_nse, list) { - struct gbproxy_bvc *sgsn_bvc = gbproxy_bvc_by_bvci(sgsn_nse, bvci); - if (sgsn_bvc) - OSMO_ASSERT(sgsn_bvc->cell == bvc->cell || !sgsn_bvc->cell); - - if (!sgsn_bvc) { - sgsn_bvc = gbproxy_bvc_alloc(sgsn_nse, bvci); - OSMO_ASSERT(sgsn_bvc); - - sgsn_bvc->cell = bvc->cell; - memcpy(sgsn_bvc->ra, bvc->cell->ra, sizeof(sgsn_bvc->ra)); - sgsn_bvc->fi = bssgp_bvc_fsm_alloc_ptp_bss(sgsn_bvc, cfg->nsi, sgsn_nse->nsei, - bvci, ra_id, cell_id); - OSMO_ASSERT(sgsn_bvc->fi); - bssgp_bvc_fsm_set_ops(sgsn_bvc->fi, &sgsn_ptp_bvc_fsm_ops, sgsn_bvc); - - gbproxy_cell_add_sgsn_bvc(bvc->cell, sgsn_bvc); - } - } - - /* Trigger outbound BVC-RESET procedure toward each SGSN */ - dispatch_to_all_sgsn_bvc(bvc->cell, BSSGP_BVCFSM_E_REQ_RESET, &cause); -} - -/* BVC FSM informs us about a BSS-side FSM state change */ -static void bss_ptp_bvc_state_chg_notif(uint16_t nsei, uint16_t bvci, int old_state, int state, void *priv) -{ - struct gbproxy_bvc *bvc = priv; - struct gbproxy_cell *cell = bvc->cell; - uint8_t cause = bssgp_bvc_fsm_get_block_cause(bvc->fi); - - /* we have just been created but due to callback ordering the cell is not associated */ - if (!cell) - return; - - switch (state) { - case BSSGP_BVCFSM_S_BLOCKED: - /* block the corresponding SGSN-side PTP BVCs */ - dispatch_to_all_sgsn_bvc(cell, BSSGP_BVCFSM_E_REQ_BLOCK, &cause); - break; - case BSSGP_BVCFSM_S_UNBLOCKED: - /* unblock the corresponding SGSN-side PTP BVCs */ - dispatch_to_all_sgsn_bvc(cell, BSSGP_BVCFSM_E_REQ_UNBLOCK, NULL); - break; - } -} - -/* BVC FSM informs us about BVC-FC PDU receive */ -static void bss_ptp_bvc_fc_bvc(uint16_t nsei, uint16_t bvci, const struct bssgp2_flow_ctrl *fc, void *priv) -{ - struct bssgp2_flow_ctrl fc_reduced; - struct gbproxy_bvc *bss_bvc = priv; - struct gbproxy_cell *cell; - struct gbproxy_config *cfg; - - OSMO_ASSERT(bss_bvc); - OSMO_ASSERT(fc); - - cell = bss_bvc->cell; - if (!cell) - return; - - cfg = cell->cfg; - - /* reduce / scale according to configuration to make sure we only advertise a fraction - * of the capacity to each of the SGSNs in the pool */ - fc_reduced = *fc; - fc_reduced.bucket_size_max = (fc->bucket_size_max * cfg->pool.bvc_fc_ratio) / 100; - fc_reduced.bucket_leak_rate = (fc->bucket_leak_rate * cfg->pool.bvc_fc_ratio) / 100; - /* we don't modify the per-MS related values as any single MS is only served by one SGSN */ - - dispatch_to_all_sgsn_bvc(cell, BSSGP_BVCFSM_E_REQ_FC_BVC, (void *) &fc_reduced); -} - -static const struct bssgp_bvc_fsm_ops bss_ptp_bvc_fsm_ops = { - .reset_notification = bss_ptp_bvc_reset_notif, - .state_chg_notification = bss_ptp_bvc_state_chg_notif, - .rx_fc_bvc = bss_ptp_bvc_fc_bvc, -}; - -/* BVC FSM informs us about a SGSN-side reset of a PTP BVC */ -static void sgsn_ptp_bvc_reset_notif(uint16_t nsei, uint16_t bvci, const struct gprs_ra_id *ra_id, - uint16_t cell_id, uint8_t cause, void *priv) -{ - struct gbproxy_bvc *bvc = priv; - - if (!bvc->cell) { - LOGPBVC(bvc, LOGL_ERROR, "RESET of PTP BVC on SGSN side for which we have no BSS?\n"); - return; - } - - OSMO_ASSERT(bvc->cell->bss_bvc); - - /* request reset of BSS-facing PTP-BVC */ - osmo_fsm_inst_dispatch(bvc->cell->bss_bvc->fi, BSSGP_BVCFSM_E_REQ_RESET, &cause); -} - -static const struct bssgp_bvc_fsm_ops sgsn_ptp_bvc_fsm_ops = { - .reset_notification = sgsn_ptp_bvc_reset_notif, -}; - -/* BVC FSM informs us about a SGSN-side reset of the signaling BVC */ -static void sgsn_sig_bvc_reset_notif(uint16_t nsei, uint16_t bvci, const struct gprs_ra_id *ra_id, - uint16_t cell_id, uint8_t cause, void *priv) -{ - struct gbproxy_bvc *bvc = priv; - struct gbproxy_config *cfg = bvc->nse->cfg; - struct gbproxy_nse *bss_nse; - unsigned int i; - - /* delete all SGSN-side PTP BVC for this SGSN */ - gbproxy_cleanup_bvcs(bvc->nse, 0); - /* FIXME: what to do about the cells? */ - /* FIXME: do we really want to RESET all signaling BVC on the BSS and affect all other SGSN? */ - - /* we need to trigger generating a reset procedure towards each BSS side signaling BVC */ - hash_for_each(cfg->bss_nses, i, bss_nse, list) { - struct gbproxy_bvc *bss_bvc = gbproxy_bvc_by_bvci(bss_nse, 0); - if (!bss_bvc) { - LOGPNSE(bss_nse, LOGL_ERROR, "Doesn't have BVC with BVCI=0 ?!?\n"); - continue; - } - osmo_fsm_inst_dispatch(bss_bvc->fi, BSSGP_BVCFSM_E_REQ_RESET, &cause); - } -} - -const struct bssgp_bvc_fsm_ops sgsn_sig_bvc_fsm_ops = { - .reset_notification = sgsn_sig_bvc_reset_notif, -}; - -/*********************************************************************** - * Signaling BVC handling - ***********************************************************************/ - -/* process a BVC-RESET message from the BSS side */ -static int rx_bvc_reset_from_bss(struct gbproxy_nse *nse, struct msgb *msg, struct tlv_parsed *tp) -{ - struct gbproxy_bvc *from_bvc = NULL; - uint16_t bvci = ntohs(tlvp_val16_unal(tp, BSSGP_IE_BVCI)); - uint32_t features = 0; // FIXME: make configurable - - LOGPNSE(nse, LOGL_INFO, "Rx BVC-RESET (BVCI=%05u)\n", bvci); - - if (bvci == 0) { - /* If we receive a BVC reset on the signalling endpoint, we - * don't want the SGSN to reset, as the signalling endpoint - * is common for all point-to-point BVCs (and thus all BTS) */ - - from_bvc = gbproxy_bvc_by_bvci(nse, 0); - if (!from_bvc) { - from_bvc = gbproxy_bvc_alloc(nse, 0); - OSMO_ASSERT(from_bvc); - from_bvc->fi = bssgp_bvc_fsm_alloc_sig_sgsn(from_bvc, nse->cfg->nsi, nse->nsei, features); - if (!from_bvc->fi) { - LOGPNSE(nse, LOGL_ERROR, "Cannot allocate SIG-BVC FSM\n"); - gbproxy_bvc_free(from_bvc); - return -ENOMEM; - } - bssgp_bvc_fsm_set_ops(from_bvc->fi, &bss_sig_bvc_fsm_ops, from_bvc); - } - } else { - from_bvc = gbproxy_bvc_by_bvci(nse, bvci); - if (!from_bvc) { - /* if a PTP-BVC is reset, and we don't know that - * PTP-BVCI yet, we should allocate a new bvc */ - from_bvc = gbproxy_bvc_alloc(nse, bvci); - OSMO_ASSERT(from_bvc); - from_bvc->fi = bssgp_bvc_fsm_alloc_ptp_sgsn(from_bvc, nse->cfg->nsi, - nse->nsei, bvci); - if (!from_bvc->fi) { - LOGPNSE(nse, LOGL_ERROR, "Cannot allocate SIG-BVC FSM\n"); - gbproxy_bvc_free(from_bvc); - return -ENOMEM; - } - bssgp_bvc_fsm_set_ops(from_bvc->fi, &bss_ptp_bvc_fsm_ops, from_bvc); - } -#if 0 - /* Could have moved to a different NSE */ - if (!check_bvc_nsei(from_bvc, nsei)) { - LOGPBVC(from_bvc, LOGL_NOTICE, "moving bvc to NSE(%05u)\n", nsei); - - struct gbproxy_nse *nse_new = gbproxy_nse_by_nsei(cfg, nsei, false); - if (!nse_new) { - LOGP(DGPRS, LOGL_NOTICE, "NSE(%05u) Got PtP BVC reset before signalling reset for " - "BVCI=%05u\n", bvci, nsei); - bssgp_tx_status(BSSGP_CAUSE_PDU_INCOMP_STATE, NULL, msg); - return 0; - } - - /* Move bvc to different NSE */ - gbproxy_bvc_move(from_bvc, nse_new); - } -#endif - /* FIXME: do we need this, if it happens within FSM? */ - if (TLVP_PRES_LEN(tp, BSSGP_IE_CELL_ID, 8)) { - struct gprs_ra_id raid; - /* We have a Cell Identifier present in this - * PDU, this means we can extend our local - * state information about this particular cell - * */ - memcpy(from_bvc->ra, TLVP_VAL(tp, BSSGP_IE_CELL_ID), sizeof(from_bvc->ra)); - gsm48_parse_ra(&raid, from_bvc->ra); - LOGPBVC(from_bvc, LOGL_INFO, "Cell ID %s\n", osmo_rai_name(&raid)); - } - } - /* hand into FSM for further processing */ - osmo_fsm_inst_dispatch(from_bvc->fi, BSSGP_BVCFSM_E_RX_RESET, msg); - return 0; -} - -/* Receive an incoming signalling message from a BSS-side NS-VC */ -static int gbprox_rx_sig_from_bss(struct gbproxy_nse *nse, struct msgb *msg, uint16_t ns_bvci) -{ - struct bssgp_normal_hdr *bgph = (struct bssgp_normal_hdr *) msgb_bssgph(msg); - uint8_t pdu_type = bgph->pdu_type; - const char *pdut_name = osmo_tlv_prot_msg_name(&osmo_pdef_bssgp, bgph->pdu_type); - struct tlv_parsed tp; - int data_len = msgb_bssgp_len(msg) - sizeof(*bgph); - struct gbproxy_bvc *from_bvc = NULL; - char log_pfx[32]; - uint16_t ptp_bvci; - uint32_t tlli; - int rc; - - snprintf(log_pfx, sizeof(log_pfx), "NSE(%05u/BSS)-BVC(%05u/??)", nse->nsei, ns_bvci); - - LOGP(DGPRS, LOGL_DEBUG, "%s Rx %s\n", log_pfx, pdut_name); - - if (ns_bvci != 0 && ns_bvci != 1) { - LOGP(DGPRS, LOGL_NOTICE, "%s %s BVCI=%05u is not signalling\n", log_pfx, pdut_name, ns_bvci); - return bssgp_tx_status(BSSGP_CAUSE_PROTO_ERR_UNSPEC, NULL, msg); - } - - if (!(bssgp_pdu_type_flags(pdu_type) & BSSGP_PDUF_SIG)) { - LOGP(DGPRS, LOGL_NOTICE, "%s %s not allowed in signalling BVC\n", log_pfx, pdut_name); - return bssgp_tx_status(BSSGP_CAUSE_PROTO_ERR_UNSPEC, NULL, msg); - } - - if (!(bssgp_pdu_type_flags(pdu_type) & BSSGP_PDUF_UL)) { - LOGP(DGPRS, LOGL_NOTICE, "%s %s not allowed in uplink direction\n", log_pfx, pdut_name); - return bssgp_tx_status(BSSGP_CAUSE_PROTO_ERR_UNSPEC, NULL, msg); - } - - rc = osmo_tlv_prot_parse(&osmo_pdef_bssgp, &tp, 1, pdu_type, bgph->data, data_len, 0, 0, - DGPRS, log_pfx); - if (rc < 0) { - rate_ctr_inc(&nse->cfg->ctrg->ctr[GBPROX_GLOB_CTR_PROTO_ERR_BSS]); - return tx_status_from_tlvp(rc, msg); - } - /* hack to get both msg + tlv_parsed passed via osmo_fsm_inst_dispatch */ - msgb_bcid(msg) = (void *)&tp; - - /* special case handling for some PDU types */ - switch (pdu_type) { - case BSSGP_PDUT_BVC_RESET: - /* resolve or create gbproxy_bvc + handlei n BVC-FSM */ - return rx_bvc_reset_from_bss(nse, msg, &tp); - case BSSGP_PDUT_BVC_RESET_ACK: - ptp_bvci = ntohs(tlvp_val16_unal(&tp, BSSGP_IE_BVCI)); - from_bvc = gbproxy_bvc_by_bvci(nse, ptp_bvci); - if (!from_bvc) - goto err_no_bvc; - return osmo_fsm_inst_dispatch(from_bvc->fi, BSSGP_BVCFSM_E_RX_RESET_ACK, msg); - case BSSGP_PDUT_BVC_BLOCK: - ptp_bvci = ntohs(tlvp_val16_unal(&tp, BSSGP_IE_BVCI)); - from_bvc = gbproxy_bvc_by_bvci(nse, ptp_bvci); - if (!from_bvc) - goto err_no_bvc; - return osmo_fsm_inst_dispatch(from_bvc->fi, BSSGP_BVCFSM_E_RX_BLOCK, msg); - case BSSGP_PDUT_BVC_UNBLOCK: - ptp_bvci = ntohs(tlvp_val16_unal(&tp, BSSGP_IE_BVCI)); - from_bvc = gbproxy_bvc_by_bvci(nse, ptp_bvci); - if (!from_bvc) - goto err_no_bvc; - return osmo_fsm_inst_dispatch(from_bvc->fi, BSSGP_BVCFSM_E_RX_UNBLOCK, msg); - case BSSGP_PDUT_SUSPEND: - case BSSGP_PDUT_RESUME: - { - struct gbproxy_sgsn *sgsn; - - tlli = osmo_load32be(TLVP_VAL(&tp, BSSGP_IE_TLLI)); - sgsn = gbproxy_select_sgsn(nse->cfg, &tlli); - if (!sgsn) { - LOGP(DGPRS, LOGL_ERROR, "Could not find any SGSN for TLLI, dropping message!\n"); - rc = -EINVAL; - break; - } - - gbproxy_tlli_cache_update(nse, tlli); - - rc = gbprox_relay2nse(msg, sgsn->nse, 0); -#if 0 - /* TODO: Validate the RAI for consistency with the RAI - * we expect for any of the BVC within this BSS side NSE */ - memcpy(ra, TLVP_VAL(&tp, BSSGP_IE_ROUTEING_AREA), sizeof(from_bvc->ra)); - gsm48_parse_ra(&raid, from_bvc->ra); -#endif - break; - } - case BSSGP_PDUT_STATUS: - /* FIXME: inspect the erroneous PDU IE (if any) and check - * if we can extract a TLLI/RNI to route it to the correct SGSN */ - break; - case BSSGP_PDUT_RAN_INFO: - case BSSGP_PDUT_RAN_INFO_REQ: - case BSSGP_PDUT_RAN_INFO_ACK: - case BSSGP_PDUT_RAN_INFO_ERROR: - case BSSGP_PDUT_RAN_INFO_APP_ERROR: - /* FIXME: route based in RIM Routing IE */ - rc = bssgp_tx_status(BSSGP_CAUSE_PDU_INCOMP_FEAT, NULL, msg); - break; - case BSSGP_PDUT_LLC_DISCARD: - case BSSGP_PDUT_FLUSH_LL_ACK: - /* route based on BVCI + TLLI */ - ptp_bvci = ntohs(tlvp_val16_unal(&tp, BSSGP_IE_BVCI)); - tlli = osmo_load32be(TLVP_VAL(&tp, BSSGP_IE_TLLI)); - from_bvc = gbproxy_bvc_by_bvci(nse, ptp_bvci); - if (!from_bvc) - goto err_no_bvc; - gbprox_bss2sgsn_tlli(from_bvc->cell, msg, &tlli, true); - break; - case BSSGP_PDUT_PAGING_PS_REJECT: - case BSSGP_PDUT_DUMMY_PAGING_PS_RESP: - { - /* Route according to IMSI<->NSE cache entry */ - struct osmo_mobile_identity mi; - const uint8_t *mi_data = TLVP_VAL(&tp, BSSGP_IE_IMSI); - uint8_t mi_len = TLVP_LEN(&tp, BSSGP_IE_IMSI); - osmo_mobile_identity_decode(&mi, mi_data, mi_len, false); - nse = gbproxy_nse_by_imsi(nse->cfg, mi.imsi); - if (!nse) { - return bssgp_tx_status(BSSGP_CAUSE_INV_MAND_INF, NULL, msg); - } - OSMO_ASSERT(nse->sgsn_facing); - rc = gbprox_relay2nse(msg, nse, 0); - break; - } - default: - LOGPNSE(nse, LOGL_ERROR, "Rx %s: Implementation missing\n", pdut_name); - break; - } - - return rc; -err_no_bvc: - LOGPNSE(nse, LOGL_ERROR, "Rx %s: cannot find BVC for BVCI=%05u\n", pdut_name, ptp_bvci); - rate_ctr_inc(&nse->cfg->ctrg->ctr[GBPROX_GLOB_CTR_INV_NSEI]); - return bssgp_tx_status(BSSGP_CAUSE_INV_MAND_INF, NULL, msg); -} - -/* Receive paging request from SGSN, we need to relay to proper BSS */ -static int gbprox_rx_paging(struct gbproxy_nse *sgsn_nse, struct msgb *msg, const char *pdut_name, - struct tlv_parsed *tp, uint16_t ns_bvci, bool broadcast) -{ - struct gbproxy_config *cfg = sgsn_nse->cfg; - struct gbproxy_bvc *sgsn_bvc, *bss_bvc; - struct gbproxy_nse *nse; - unsigned int n_nses = 0; - int errctr = GBPROX_GLOB_CTR_PROTO_ERR_SGSN; - int i, j; - - /* FIXME: Handle paging logic to only page each matching NSE */ - - if (TLVP_PRES_LEN(tp, BSSGP_IE_BVCI, 2)) { - uint16_t bvci = ntohs(tlvp_val16_unal(tp, BSSGP_IE_BVCI)); - errctr = GBPROX_GLOB_CTR_OTHER_ERR; - sgsn_bvc = gbproxy_bvc_by_bvci(sgsn_nse, bvci); - if (!sgsn_bvc) { - LOGPNSE(sgsn_nse, LOGL_NOTICE, "Rx %s: unable to route: BVCI=%05u unknown\n", - pdut_name, bvci); - rate_ctr_inc(&cfg->ctrg->ctr[errctr]); - return -EINVAL; - } - LOGPBVC(sgsn_bvc, LOGL_INFO, "Rx %s: routing by BVCI\n", pdut_name); - return gbprox_relay2peer(msg, sgsn_bvc->cell->bss_bvc, ns_bvci); - } else if (TLVP_PRES_LEN(tp, BSSGP_IE_ROUTEING_AREA, 6)) { - errctr = GBPROX_GLOB_CTR_INV_RAI; - /* iterate over all bvcs and dispatch the paging to each matching one */ - hash_for_each(cfg->bss_nses, i, nse, list) { - hash_for_each(nse->bvcs, j, bss_bvc, list) { - if (!memcmp(bss_bvc->ra, TLVP_VAL(tp, BSSGP_IE_ROUTEING_AREA), 6)) { - LOGPNSE(nse, LOGL_INFO, "Rx %s: routing to NSE (RAI match)\n", - pdut_name); - gbprox_relay2peer(msg, bss_bvc, ns_bvci); - n_nses++; - /* Only send it once to each NSE */ - break; - } - } - } - } else if (TLVP_PRES_LEN(tp, BSSGP_IE_LOCATION_AREA, 5)) { - errctr = GBPROX_GLOB_CTR_INV_LAI; - /* iterate over all bvcs and dispatch the paging to each matching one */ - hash_for_each(cfg->bss_nses, i, nse, list) { - hash_for_each(nse->bvcs, j, bss_bvc, list) { - if (!memcmp(bss_bvc->ra, TLVP_VAL(tp, BSSGP_IE_LOCATION_AREA), 5)) { - LOGPNSE(nse, LOGL_INFO, "Rx %s: routing to NSE (LAI match)\n", - pdut_name); - gbprox_relay2peer(msg, bss_bvc, ns_bvci); - n_nses++; - /* Only send it once to each NSE */ - break; - } - } - } - } else if (TLVP_PRES_LEN(tp, BSSGP_IE_BSS_AREA_ID, 1) || broadcast) { - /* iterate over all bvcs and dispatch the paging to each matching one */ - hash_for_each(cfg->bss_nses, i, nse, list) { - hash_for_each(nse->bvcs, j, bss_bvc, list) { - LOGPNSE(nse, LOGL_INFO, "Rx %s:routing to NSE (broadcast)\n", pdut_name); - gbprox_relay2peer(msg, bss_bvc, ns_bvci); - n_nses++; - /* Only send it once to each NSE */ - break; - } - } - } else { - LOGPNSE(sgsn_nse, LOGL_ERROR, "BSSGP PAGING: unable to route, missing IE\n"); - rate_ctr_inc(&cfg->ctrg->ctr[errctr]); - } - - if (n_nses == 0) { - LOGPNSE(sgsn_nse, LOGL_ERROR, "BSSGP PAGING: unable to route, no destination found\n"); - rate_ctr_inc(&cfg->ctrg->ctr[errctr]); - return -EINVAL; - } - return 0; -} - -/* Receive an incoming BVC-RESET message from the SGSN */ -static int rx_bvc_reset_from_sgsn(struct gbproxy_nse *nse, struct msgb *msg, struct tlv_parsed *tp, - uint16_t ns_bvci) -{ - uint16_t ptp_bvci = ntohs(tlvp_val16_unal(tp, BSSGP_IE_BVCI)); - struct gbproxy_bvc *from_bvc; - - LOGPNSE(nse, LOGL_INFO, "Rx BVC-RESET (BVCI=%05u)\n", ptp_bvci); - - if (ptp_bvci == 0) { - from_bvc = gbproxy_bvc_by_bvci(nse, 0); - OSMO_ASSERT(from_bvc); - osmo_fsm_inst_dispatch(from_bvc->fi, BSSGP_BVCFSM_E_RX_RESET, msg); - } else { - from_bvc = gbproxy_bvc_by_bvci(nse, ptp_bvci); - if (!from_bvc) { - LOGPNSE(nse, LOGL_ERROR, "Rx BVC-RESET BVCI=%05u: Cannot find BVC\n", ptp_bvci); - rate_ctr_inc(&nse->cfg->ctrg->ctr[GBPROX_GLOB_CTR_INV_BVCI]); - return bssgp_tx_status(BSSGP_CAUSE_UNKNOWN_BVCI, &ptp_bvci, msg); - } - osmo_fsm_inst_dispatch(from_bvc->fi, BSSGP_BVCFSM_E_RX_RESET, msg); - } - - return 0; -} - -/* Receive an incoming signalling message from the SGSN-side NS-VC */ -static int gbprox_rx_sig_from_sgsn(struct gbproxy_nse *nse, struct msgb *msg, uint16_t ns_bvci) -{ - struct bssgp_normal_hdr *bgph = (struct bssgp_normal_hdr *) msgb_bssgph(msg); - uint8_t pdu_type = bgph->pdu_type; - const char *pdut_name = osmo_tlv_prot_msg_name(&osmo_pdef_bssgp, bgph->pdu_type); - struct gbproxy_config *cfg = nse->cfg; - struct gbproxy_bvc *sgsn_bvc; - struct tlv_parsed tp; - int data_len; - uint16_t bvci; - char log_pfx[32]; - int rc = 0; - int cause; - int i; - bool paging_bc = false; - - snprintf(log_pfx, sizeof(log_pfx), "NSE(%05u/SGSN)-BVC(%05u/??)", nse->nsei, ns_bvci); - - LOGP(DGPRS, LOGL_DEBUG, "%s Rx %s\n", log_pfx, pdut_name); - - if (ns_bvci != 0 && ns_bvci != 1) { - LOGP(DGPRS, LOGL_NOTICE, "%s BVCI=%05u is not signalling\n", log_pfx, ns_bvci); - return bssgp_tx_status(BSSGP_CAUSE_PROTO_ERR_UNSPEC, NULL, msg); - } - - if (!(bssgp_pdu_type_flags(pdu_type) & BSSGP_PDUF_SIG)) { - LOGP(DGPRS, LOGL_NOTICE, "%s %s not allowed in signalling BVC\n", log_pfx, pdut_name); - return bssgp_tx_status(BSSGP_CAUSE_PROTO_ERR_UNSPEC, NULL, msg); - } - - if (!(bssgp_pdu_type_flags(pdu_type) & BSSGP_PDUF_DL)) { - LOGP(DGPRS, LOGL_NOTICE, "%s %s not allowed in downlink direction\n", log_pfx, pdut_name); - return bssgp_tx_status(BSSGP_CAUSE_PROTO_ERR_UNSPEC, NULL, msg); - } - - data_len = msgb_bssgp_len(msg) - sizeof(*bgph); - - rc = osmo_tlv_prot_parse(&osmo_pdef_bssgp, &tp, 1, pdu_type, bgph->data, data_len, 0, 0, - DGPRS, log_pfx); - if (rc < 0) { - rc = tx_status_from_tlvp(rc, msg); - rate_ctr_inc(&cfg->ctrg->ctr[GBPROX_GLOB_CTR_PROTO_ERR_SGSN]); - return rc; - } - /* hack to get both msg + tlv_parsed passed via osmo_fsm_inst_dispatch */ - msgb_bcid(msg) = (void *)&tp; - - switch (pdu_type) { - case BSSGP_PDUT_BVC_RESET: - /* resolve or create ggbproxy_bvc + handle in BVC-FSM */ - bvci = ntohs(tlvp_val16_unal(&tp, BSSGP_IE_BVCI)); - rc = rx_bvc_reset_from_sgsn(nse, msg, &tp, ns_bvci); - break; - case BSSGP_PDUT_BVC_RESET_ACK: - bvci = ntohs(tlvp_val16_unal(&tp, BSSGP_IE_BVCI)); - sgsn_bvc = gbproxy_bvc_by_bvci(nse, bvci); - if (!sgsn_bvc) - goto err_no_bvc; - rc = osmo_fsm_inst_dispatch(sgsn_bvc->fi, BSSGP_BVCFSM_E_RX_RESET_ACK, msg); - break; - case BSSGP_PDUT_BVC_BLOCK_ACK: - bvci = ntohs(tlvp_val16_unal(&tp, BSSGP_IE_BVCI)); - sgsn_bvc = gbproxy_bvc_by_bvci(nse, bvci); - if (!sgsn_bvc) - goto err_no_bvc; - rc = osmo_fsm_inst_dispatch(sgsn_bvc->fi, BSSGP_BVCFSM_E_RX_BLOCK_ACK, msg); - break; - case BSSGP_PDUT_BVC_UNBLOCK_ACK: - bvci = ntohs(tlvp_val16_unal(&tp, BSSGP_IE_BVCI)); - sgsn_bvc = gbproxy_bvc_by_bvci(nse, bvci); - if (!sgsn_bvc) - goto err_no_bvc; - rc = osmo_fsm_inst_dispatch(sgsn_bvc->fi, BSSGP_BVCFSM_E_RX_UNBLOCK_ACK, msg); - break; - case BSSGP_PDUT_FLUSH_LL: - /* simple case: BVCI IE is mandatory */ - bvci = ntohs(tlvp_val16_unal(&tp, BSSGP_IE_BVCI)); - sgsn_bvc = gbproxy_bvc_by_bvci(nse, bvci); - if (!sgsn_bvc) - goto err_no_bvc; - if (sgsn_bvc->cell && sgsn_bvc->cell->bss_bvc) - rc = gbprox_relay2peer(msg, sgsn_bvc->cell->bss_bvc, ns_bvci); - break; - case BSSGP_PDUT_DUMMY_PAGING_PS: - /* Routing area is optional in dummy paging and we have nothing else to go by - * so in case it is missing we need to broadcast the paging */ - paging_bc = true; - /* fall through */ - case BSSGP_PDUT_PAGING_PS: - { - /* Cache the IMSI<->NSE to route PAGING REJECT */ - struct osmo_mobile_identity mi; - const uint8_t *mi_data = TLVP_VAL(&tp, BSSGP_IE_IMSI); - uint8_t mi_len = TLVP_LEN(&tp, BSSGP_IE_IMSI); - osmo_mobile_identity_decode(&mi, mi_data, mi_len, false); - gbproxy_imsi_cache_update(nse, mi.imsi); - /* fall through */ - } - case BSSGP_PDUT_PAGING_CS: - /* process the paging request (LAI/RAI lookup) */ - rc = gbprox_rx_paging(nse, msg, pdut_name, &tp, ns_bvci, paging_bc); - break; - case BSSGP_PDUT_STATUS: - /* Some exception has occurred */ - cause = *TLVP_VAL(&tp, BSSGP_IE_CAUSE); - LOGPNSE(nse, LOGL_NOTICE, "Rx STATUS cause=0x%02x(%s) ", cause, - bssgp_cause_str(cause)); - if (TLVP_PRES_LEN(&tp, BSSGP_IE_BVCI, 2)) { - bvci = ntohs(tlvp_val16_unal(&tp, BSSGP_IE_BVCI)); - LOGPC(DGPRS, LOGL_NOTICE, "BVCI=%05u\n", bvci); - sgsn_bvc = gbproxy_bvc_by_bvci(nse, bvci); - /* don't send STATUS in response to STATUS if !bvc */ - if (sgsn_bvc && sgsn_bvc->cell && sgsn_bvc->cell->bss_bvc) - rc = gbprox_relay2peer(msg, sgsn_bvc->cell->bss_bvc, ns_bvci); - } else - LOGPC(DGPRS, LOGL_NOTICE, "\n"); - break; - /* those only exist in the SGSN -> BSS direction */ - case BSSGP_PDUT_SUSPEND_ACK: - case BSSGP_PDUT_SUSPEND_NACK: - case BSSGP_PDUT_RESUME_ACK: - case BSSGP_PDUT_RESUME_NACK: - { - struct gbproxy_nse *nse_peer; - uint32_t tlli = osmo_load32be(TLVP_VAL(&tp, BSSGP_IE_TLLI)); - - nse_peer = gbproxy_nse_by_tlli(cfg, tlli); - if (!nse_peer) { - LOGPNSE(nse, LOGL_ERROR, "Rx %s: Cannot find NSE\n", pdut_name); - /* TODO: Counter */ - return bssgp_tx_status(BSSGP_CAUSE_INV_MAND_INF, NULL, msg); - } - /* Delete the entry after we're done */ - gbproxy_tlli_cache_remove(cfg, tlli); - LOGPNSE(nse_peer, LOGL_DEBUG, "Rx %s: forwarding\n", pdut_name); - gbprox_relay2nse(msg, nse_peer, ns_bvci); - break; - } - case BSSGP_PDUT_SGSN_INVOKE_TRACE: - case BSSGP_PDUT_OVERLOAD: - LOGPNSE(nse, LOGL_DEBUG, "Rx %s: broadcasting\n", pdut_name); - /* broadcast to all BSS-side bvcs */ - hash_for_each(cfg->bss_nses, i, nse, list) { - gbprox_relay2nse(msg, nse, 0); - } - break; - case BSSGP_PDUT_RAN_INFO: - case BSSGP_PDUT_RAN_INFO_REQ: - case BSSGP_PDUT_RAN_INFO_ACK: - case BSSGP_PDUT_RAN_INFO_ERROR: - case BSSGP_PDUT_RAN_INFO_APP_ERROR: - /* FIXME: route based in RIM Routing IE */ - rc = bssgp_tx_status(BSSGP_CAUSE_PDU_INCOMP_FEAT, NULL, msg); - break; - default: - LOGPNSE(nse, LOGL_NOTICE, "Rx %s: Not supported\n", pdut_name); - rate_ctr_inc(&cfg->ctrg->ctr[GBPROX_GLOB_CTR_PROTO_ERR_SGSN]); - rc = bssgp_tx_status(BSSGP_CAUSE_PROTO_ERR_UNSPEC, NULL, msg); - break; - } - - return rc; - -err_no_bvc: - LOGPNSE(nse, LOGL_ERROR, "Rx %s: Cannot find BVC\n", pdut_name); - rate_ctr_inc(&cfg->ctrg-> ctr[GBPROX_GLOB_CTR_INV_RAI]); - return bssgp_tx_status(BSSGP_CAUSE_INV_MAND_INF, NULL, msg); -} - - -/*********************************************************************** - * libosmogb NS/BSSGP integration - ***********************************************************************/ - -int gbprox_bssgp_send_cb(void *ctx, struct msgb *msg) -{ - int rc; - struct gbproxy_config *cfg = (struct gbproxy_config *) ctx; - struct gprs_ns2_inst *nsi = cfg->nsi; - struct osmo_gprs_ns2_prim nsp = {}; - - nsp.bvci = msgb_bvci(msg); - nsp.nsei = msgb_nsei(msg); - - osmo_prim_init(&nsp.oph, SAP_NS, GPRS_NS2_PRIM_UNIT_DATA, PRIM_OP_REQUEST, msg); - rc = gprs_ns2_recv_prim(nsi, &nsp.oph); - - return rc; -} - -/* Main input function for Gb proxy */ -int gbprox_rcvmsg(void *ctx, struct msgb *msg) -{ - struct gbproxy_config *cfg = (struct gbproxy_config *) ctx; - uint16_t ns_bvci = msgb_bvci(msg); - uint16_t nsei = msgb_nsei(msg); - struct gbproxy_nse *nse; - - /* ensure minimum length to decode PCU type */ - if (msgb_bssgp_len(msg) < sizeof(struct bssgp_normal_hdr)) - return bssgp_tx_status(BSSGP_CAUSE_SEM_INCORR_PDU, NULL, msg); - - nse = gbproxy_nse_by_nsei(cfg, nsei, NSE_F_SGSN); - if (nse) { - if (ns_bvci == 0 || ns_bvci == 1) - return gbprox_rx_sig_from_sgsn(nse, msg, ns_bvci); - else - return gbprox_rx_ptp_from_sgsn(nse, msg, ns_bvci); - } - - nse = gbproxy_nse_by_nsei(cfg, nsei, NSE_F_BSS); - if (!nse) { - LOGP(DGPRS, LOGL_NOTICE, "NSE(%05u/BSS) not known -> allocating\n", nsei); - nse = gbproxy_nse_alloc(cfg, nsei, false); - } - if (nse) { - if (ns_bvci == 0 || ns_bvci == 1) - return gbprox_rx_sig_from_bss(nse, msg, ns_bvci); - else - return gbprox_rx_ptp_from_bss(nse, msg, ns_bvci); - } - - return 0; -} - -/* TODO: What about handling: - * GPRS_NS2_AFF_CAUSE_VC_FAILURE, - GPRS_NS2_AFF_CAUSE_VC_RECOVERY, - GPRS_NS2_AFF_CAUSE_FAILURE, - GPRS_NS2_AFF_CAUSE_RECOVERY, - osmocom own causes - GPRS_NS2_AFF_CAUSE_SNS_CONFIGURED, - GPRS_NS2_AFF_CAUSE_SNS_FAILURE, - */ - -void gprs_ns_prim_status_cb(struct gbproxy_config *cfg, struct osmo_gprs_ns2_prim *nsp) -{ - /* TODO: bss nsei available/unavailable bssgp_tx_simple_bvci(BSSGP_PDUT_BVC_BLOCK, nsvc->nsei, bvc->bvci, 0); - * TODO: sgsn nsei available/unavailable - */ - - struct gbproxy_bvc *bvc; - struct gbproxy_nse *sgsn_nse; - - switch (nsp->u.status.cause) { - case GPRS_NS2_AFF_CAUSE_SNS_FAILURE: - case GPRS_NS2_AFF_CAUSE_SNS_CONFIGURED: - break; - - case GPRS_NS2_AFF_CAUSE_RECOVERY: - LOGP(DGPRS, LOGL_NOTICE, "NS-NSE %d became available\n", nsp->nsei); - sgsn_nse = gbproxy_nse_by_nsei(cfg, nsp->nsei, NSE_F_SGSN); - if (sgsn_nse) { - uint8_t cause = BSSGP_CAUSE_OML_INTERV; - bvc = gbproxy_bvc_by_bvci(sgsn_nse, 0); - if (bvc) - osmo_fsm_inst_dispatch(bvc->fi, BSSGP_BVCFSM_E_REQ_RESET, &cause); - } - break; - case GPRS_NS2_AFF_CAUSE_FAILURE: -#if 0 - if (gbproxy_is_sgsn_nsei(cfg, nsp->nsei)) { - /* sgsn */ - /* TODO: BSVC: block all PtP towards bss */ - rate_ctr_inc(&cfg->ctrg-> - ctr[GBPROX_GLOB_CTR_RESTART_RESET_SGSN]); - } else { - /* bss became unavailable - * TODO: Block all BVC belonging to that NSE */ - bvc = gbproxy_bvc_by_nsei(cfg, nsp->nsei); - if (!bvc) { - /* TODO: use primitive name + status cause name */ - LOGP(DGPRS, LOGL_NOTICE, "Received ns2 primitive %d for unknown bvc NSEI=%u\n", - nsp->u.status.cause, nsp->nsei); - break; - } - - if (!bvc->blocked) - break; - hash_for_each(cfg->sgsn_nses, _sgsn, sgsn_nse, list) { - bssgp_tx_simple_bvci(BSSGP_PDUT_BVC_BLOCK, sgsn_nse->nsei, bvc->bvci, 0); - } - } -#endif - LOGP(DGPRS, LOGL_NOTICE, "NS-NSE %d became unavailable\n", nsp->nsei); - break; - default: - LOGP(DGPRS, LOGL_NOTICE, "NS: Unknown NS-STATUS.ind cause=%s from NS\n", - gprs_ns2_aff_cause_prim_str(nsp->u.status.cause)); - break; - } -} - -/* called by the ns layer */ -int gprs_ns2_prim_cb(struct osmo_prim_hdr *oph, void *ctx) -{ - struct osmo_gprs_ns2_prim *nsp; - struct gbproxy_config *cfg = (struct gbproxy_config *) ctx; - uintptr_t bvci; - int rc = 0; - - if (oph->sap != SAP_NS) - return 0; - - nsp = container_of(oph, struct osmo_gprs_ns2_prim, oph); - - if (oph->operation != PRIM_OP_INDICATION) { - LOGP(DGPRS, LOGL_NOTICE, "NS: Unexpected primitive operation %s from NS\n", - get_value_string(osmo_prim_op_names, oph->operation)); - return 0; - } - - switch (oph->primitive) { - case GPRS_NS2_PRIM_UNIT_DATA: - - /* hand the message into the BSSGP implementation */ - msgb_bssgph(oph->msg) = oph->msg->l3h; - msgb_bvci(oph->msg) = nsp->bvci; - msgb_nsei(oph->msg) = nsp->nsei; - bvci = nsp->bvci | BVC_LOG_CTX_FLAG; - - log_set_context(LOG_CTX_GB_BVC, (void *)bvci); - rc = gbprox_rcvmsg(cfg, oph->msg); - msgb_free(oph->msg); - break; - case GPRS_NS2_PRIM_STATUS: - gprs_ns_prim_status_cb(cfg, nsp); - break; - default: - LOGP(DGPRS, LOGL_NOTICE, "NS: Unknown prim %s %s from NS\n", - gprs_ns2_prim_str(oph->primitive), - get_value_string(osmo_prim_op_names, oph->operation)); - break; - } - - return rc; -} - -void gbprox_reset(struct gbproxy_config *cfg) -{ - struct gbproxy_nse *nse; - struct hlist_node *ntmp; - int i, j; - - hash_for_each_safe(cfg->bss_nses, i, ntmp, nse, list) { - struct gbproxy_bvc *bvc; - struct hlist_node *tmp; - hash_for_each_safe(nse->bvcs, j, tmp, bvc, list) - gbproxy_bvc_free(bvc); - - gbproxy_nse_free(nse); - } - /* FIXME: cells */ - /* FIXME: SGSN side BVCs (except signaling) */ - - rate_ctr_group_free(cfg->ctrg); - gbproxy_init_config(cfg); -} - -static void tlli_cache_cleanup(void *data) -{ - struct gbproxy_config *cfg = data; - gbproxy_tlli_cache_cleanup(cfg); - - /* TODO: Disable timer when cache is empty */ - osmo_timer_schedule(&cfg->tlli_cache.timer, 2, 0); -} - -static void imsi_cache_cleanup(void *data) -{ - struct gbproxy_config *cfg = data; - gbproxy_imsi_cache_cleanup(cfg); - - /* TODO: Disable timer when cache is empty */ - osmo_timer_schedule(&cfg->imsi_cache.timer, 2, 0); -} - -int gbproxy_init_config(struct gbproxy_config *cfg) -{ - struct timespec tp; - - /* by default we advertise 100% of the BSS-side capacity to _each_ SGSN */ - cfg->pool.bvc_fc_ratio = 100; - cfg->pool.null_nri_ranges = osmo_nri_ranges_alloc(cfg); - /* TODO: Make configurable */ - cfg->tlli_cache.timeout = 10; - cfg->imsi_cache.timeout = 10; - - hash_init(cfg->bss_nses); - hash_init(cfg->sgsn_nses); - hash_init(cfg->cells); - hash_init(cfg->tlli_cache.entries); - INIT_LLIST_HEAD(&cfg->sgsns); - - osmo_timer_setup(&cfg->tlli_cache.timer, tlli_cache_cleanup, cfg); - osmo_timer_schedule(&cfg->tlli_cache.timer, 2, 0); - - /* We could also combine both timers */ - osmo_timer_setup(&cfg->imsi_cache.timer, imsi_cache_cleanup, cfg); - osmo_timer_schedule(&cfg->imsi_cache.timer, 2, 0); - - cfg->ctrg = rate_ctr_group_alloc(tall_sgsn_ctx, &global_ctrg_desc, 0); - if (!cfg->ctrg) { - LOGP(DGPRS, LOGL_ERROR, "Cannot allocate global counter group!\n"); - return -1; - } - osmo_clock_gettime(CLOCK_REALTIME, &tp); - osmo_fsm_log_timeouts(true); - - return 0; -}
\ No newline at end of file diff --git a/src/gbproxy/gb_proxy_ctrl.c b/src/gbproxy/gb_proxy_ctrl.c deleted file mode 100644 index 456163466..000000000 --- a/src/gbproxy/gb_proxy_ctrl.c +++ /dev/null @@ -1,137 +0,0 @@ -/* Control Interface Implementation for the Gb-proxy */ -/* - * (C) 2018 by sysmocom s.f.m.c. GmbH <info@sysmocom.de> - * All Rights Reserved - * - * Author: Daniel Willmann - * - * 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 <osmocom/core/talloc.h> - - -#include <osmocom/gprs/gprs_bssgp.h> -#include <osmocom/gprs/gprs_ns.h> - -#include <osmocom/ctrl/control_if.h> -#include <osmocom/ctrl/control_cmd.h> -#include <osmocom/sgsn/gb_proxy.h> -#include <osmocom/sgsn/debug.h> - -extern vector ctrl_node_vec; - -struct nsvc_cb_data { - struct ctrl_cmd *cmd; - uint16_t nsei; - bool is_sgsn; -}; - -static int ctrl_nsvc_state_cb(struct gprs_ns2_vc *nsvc, void *ctx) { - struct nsvc_cb_data *data = (struct nsvc_cb_data *)ctx; - struct ctrl_cmd *cmd = (struct ctrl_cmd *)data->cmd; - - cmd->reply = talloc_asprintf_append(cmd->reply, "%u,%s,%s,%s\n", - data->nsei, gprs_ns2_ll_str(nsvc), gprs_ns2_nsvc_state_name(nsvc), - data->is_sgsn ? "SGSN" : "BSS" ); - - return 0; -} - -static int get_nsvc_state(struct ctrl_cmd *cmd, void *data) -{ - struct gbproxy_config *cfg = data; - struct gprs_ns2_inst *nsi = cfg->nsi; - struct gprs_ns2_nse *nse; - struct gbproxy_nse *nse_peer; - int i; - - cmd->reply = talloc_strdup(cmd, ""); - - /* NS-VCs for SGSN */ - hash_for_each(cfg->sgsn_nses, i, nse_peer, list) { - nse = gprs_ns2_nse_by_nsei(nsi, nse_peer->nsei); - if (nse) - gprs_ns2_nse_foreach_nsvc(nse, &ctrl_nsvc_state_cb, cmd); - } - - /* NS-VCs for BSS peers */ - hash_for_each(cfg->bss_nses, i, nse_peer, list) { - nse = gprs_ns2_nse_by_nsei(nsi, nse_peer->nsei); - if (nse) - gprs_ns2_nse_foreach_nsvc(nse, &ctrl_nsvc_state_cb, cmd); - } - - return CTRL_CMD_REPLY; -} - -CTRL_CMD_DEFINE_RO(nsvc_state, "nsvc-state"); - -static int get_gbproxy_state(struct ctrl_cmd *cmd, void *data) -{ - struct gbproxy_config *cfg = data; - struct gbproxy_nse *nse_peer; - int i, j; - - cmd->reply = talloc_strdup(cmd, ""); - - hash_for_each(cfg->bss_nses, i, nse_peer, list) { - struct gbproxy_bvc *bvc; - hash_for_each(nse_peer->bvcs, j, bvc, list) { - struct gprs_ra_id raid; - gsm48_parse_ra(&raid, bvc->ra); - - cmd->reply = talloc_asprintf_append(cmd->reply, "%u,%u,%u,%u,%u,%u,%s\n", - nse_peer->nsei, bvc->bvci, - raid.mcc, raid.mnc, - raid.lac, raid.rac, - osmo_fsm_inst_state_name(bvc->fi)); - } - } - - return CTRL_CMD_REPLY; -} - -CTRL_CMD_DEFINE_RO(gbproxy_state, "gbproxy-state"); - -static int get_num_peers(struct ctrl_cmd *cmd, void *data) -{ - struct gbproxy_config *cfg = data; - struct gbproxy_nse *nse_peer; - struct gbproxy_bvc *bvc; - uint32_t count = 0; - int i, j; - - hash_for_each(cfg->bss_nses, i, nse_peer, list) { - hash_for_each(nse_peer->bvcs, j, bvc, list) - count++; - } - - cmd->reply = talloc_strdup(cmd, ""); - cmd->reply = talloc_asprintf_append(cmd->reply, "%u", count); - - return CTRL_CMD_REPLY; -} -CTRL_CMD_DEFINE_RO(num_peers, "number-of-peers"); - -int gb_ctrl_cmds_install(void) -{ - int rc = 0; - rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_nsvc_state); - rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_gbproxy_state); - rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_num_peers); - - return rc; -} diff --git a/src/gbproxy/gb_proxy_main.c b/src/gbproxy/gb_proxy_main.c deleted file mode 100644 index b76e0fbb6..000000000 --- a/src/gbproxy/gb_proxy_main.c +++ /dev/null @@ -1,336 +0,0 @@ -/* NS-over-IP proxy */ - -/* (C) 2010 by Harald Welte <laforge@gnumonks.org> - * (C) 2010 by On-Waves - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - */ - -#include <unistd.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <getopt.h> -#include <errno.h> -#include <signal.h> -#include <sys/fcntl.h> -#include <sys/stat.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <arpa/inet.h> - -#include <osmocom/core/application.h> -#include <osmocom/core/talloc.h> -#include <osmocom/core/select.h> -#include <osmocom/core/rate_ctr.h> -#include <osmocom/core/stats.h> - -#include <osmocom/gprs/gprs_ns2.h> -#include <osmocom/gprs/gprs_bssgp.h> - -#include <osmocom/sgsn/signal.h> -#include <osmocom/sgsn/debug.h> -#include <osmocom/sgsn/vty.h> -#include <osmocom/sgsn/gb_proxy.h> - -#include <osmocom/ctrl/control_vty.h> -#include <osmocom/ctrl/control_if.h> -#include <osmocom/ctrl/ports.h> - -#include <osmocom/vty/command.h> -#include <osmocom/vty/telnet_interface.h> -#include <osmocom/vty/logging.h> -#include <osmocom/vty/stats.h> -#include <osmocom/vty/ports.h> -#include <osmocom/vty/misc.h> - -#include "../../bscconfig.h" - -#define _GNU_SOURCE -#include <getopt.h> - -void *tall_sgsn_ctx; - -const char *openbsc_copyright = - "Copyright (C) 2010 Harald Welte and On-Waves\r\n" - "License AGPLv3+: GNU AGPL version 3 or later <http://gnu.org/licenses/agpl-3.0.html>\r\n" - "This is free software: you are free to change and redistribute it.\r\n" - "There is NO WARRANTY, to the extent permitted by law.\r\n"; - -#define CONFIG_FILE_DEFAULT "osmo-gbproxy.cfg" -#define CONFIG_FILE_LEGACY "osmo_gbproxy.cfg" - -static char *config_file = NULL; -struct gbproxy_config *gbcfg; -static int daemonize = 0; - -/* Pointer to the SGSN peer */ -extern struct gbprox_peer *gbprox_peer_sgsn; - -static void signal_handler(int signum) -{ - fprintf(stdout, "signal %u received\n", signum); - - switch (signum) { - case SIGINT: - case SIGTERM: - osmo_signal_dispatch(SS_L_GLOBAL, S_L_GLOBAL_SHUTDOWN, NULL); - sleep(1); - exit(0); - break; - case SIGABRT: - /* in case of abort, we want to obtain a talloc report and - * then run default SIGABRT handler, who will generate coredump - * and abort the process. abort() should do this for us after we - * return, but program wouldn't exit if an external SIGABRT is - * received. - */ - talloc_report(tall_vty_ctx, stderr); - talloc_report_full(tall_sgsn_ctx, stderr); - signal(SIGABRT, SIG_DFL); - raise(SIGABRT); - break; - case SIGUSR1: - talloc_report(tall_vty_ctx, stderr); - talloc_report_full(tall_sgsn_ctx, stderr); - break; - case SIGUSR2: - talloc_report_full(tall_vty_ctx, stderr); - break; - default: - break; - } -} - -static void print_usage() -{ - printf("Usage: bsc_hack\n"); -} - -static void print_help() -{ - printf(" Some useful help...\n"); - printf(" -h --help this text\n"); - printf(" -d option --debug=DNS:DGPRS,0:0 enable debugging\n"); - printf(" -D --daemonize Fork the process into a background daemon\n"); - printf(" -c --config-file filename The config file to use [%s]\n", CONFIG_FILE_DEFAULT); - printf(" -s --disable-color\n"); - printf(" -T --timestamp Prefix every log line with a timestamp\n"); - printf(" -V --version. Print the version.\n"); - printf(" -e --log-level number. Set a global loglevel.\n"); -} - -static void handle_options(int argc, char **argv) -{ - while (1) { - int option_index = 0, c; - static struct option long_options[] = { - { "help", 0, 0, 'h' }, - { "debug", 1, 0, 'd' }, - { "daemonize", 0, 0, 'D' }, - { "config-file", 1, 0, 'c' }, - { "disable-color", 0, 0, 's' }, - { "timestamp", 0, 0, 'T' }, - { "version", 0, 0, 'V' }, - { "log-level", 1, 0, 'e' }, - { 0, 0, 0, 0 } - }; - - c = getopt_long(argc, argv, "hd:Dc:sTVe:", - long_options, &option_index); - if (c == -1) - break; - - switch (c) { - case 'h': - print_usage(); - print_help(); - exit(0); - case 's': - log_set_use_color(osmo_stderr_target, 0); - break; - case 'd': - log_parse_category_mask(osmo_stderr_target, optarg); - break; - case 'D': - daemonize = 1; - break; - case 'c': - config_file = optarg; - break; - case 'T': - log_set_print_timestamp(osmo_stderr_target, 1); - break; - case 'e': - log_set_log_level(osmo_stderr_target, atoi(optarg)); - break; - case 'V': - print_version(1); - exit(0); - break; - default: - break; - } - } - - if (argc > optind) { - fprintf(stderr, "Unsupported positional arguments on command line\n"); - exit(2); - } -} - -static struct vty_app_info vty_info = { - .name = "OsmoGbProxy", - .version = PACKAGE_VERSION, -}; - -/* default categories */ -static struct log_info_cat gprs_categories[] = { - [DGPRS] = { - .name = "DGPRS", - .description = "GPRS Packet Service", - .enabled = 1, .loglevel = LOGL_DEBUG, - }, - [DNS] = { - .name = "DNS", - .description = "GPRS Network Service (NS)", - .enabled = 1, .loglevel = LOGL_INFO, - }, - [DOBJ] = { - .name = "DOBJ", - .description = "GbProxy object allocation/release", - .enabled = 1, - .color = "\033[38;5;121m" - }, -}; - -static const struct log_info gprs_log_info = { - .filter_fn = gprs_log_filter_fn, - .cat = gprs_categories, - .num_cat = ARRAY_SIZE(gprs_categories), -}; - -static bool file_exists(const char *path) -{ - struct stat sb; - return stat(path, &sb) ? false : true; -} - -int gbprox_bssgp_send_cb(void *ctx, struct msgb *msg); - -int main(int argc, char **argv) -{ - int rc; - struct ctrl_handle *ctrl; - - tall_sgsn_ctx = talloc_named_const(NULL, 0, "nsip_proxy"); - msgb_talloc_ctx_init(tall_sgsn_ctx, 0); - vty_info.tall_ctx = tall_sgsn_ctx; - - signal(SIGINT, &signal_handler); - signal(SIGTERM, &signal_handler); - signal(SIGABRT, &signal_handler); - signal(SIGUSR1, &signal_handler); - signal(SIGUSR2, &signal_handler); - osmo_init_ignore_signals(); - - osmo_init_logging2(tall_sgsn_ctx, &gprs_log_info); - - vty_info.copyright = openbsc_copyright; - vty_init(&vty_info); - logging_vty_add_cmds(); - osmo_talloc_vty_add_cmds(); - osmo_stats_vty_add_cmds(); - osmo_fsm_vty_add_cmds(); - gbproxy_vty_init(); - - handle_options(argc, argv); - - /* Backwards compatibility: for years, the default config file name was - * osmo_gbproxy.cfg. All other Osmocom programs use osmo-*.cfg with a - * dash. To be able to use the new config file name without breaking - * previous setups that might rely on the legacy default config file - * name, we need to look for the old config file if no -c option was - * passed AND no file exists with the new default file name. */ - if (!config_file) { - /* No -c option was passed */ - if (file_exists(CONFIG_FILE_LEGACY) - && !file_exists(CONFIG_FILE_DEFAULT)) - config_file = CONFIG_FILE_LEGACY; - else - config_file = CONFIG_FILE_DEFAULT; - } - - rate_ctr_init(tall_sgsn_ctx); - osmo_stats_init(tall_sgsn_ctx); - - gbcfg = talloc_zero(tall_sgsn_ctx, struct gbproxy_config); - if (!gbcfg) { - LOGP(DGPRS, LOGL_FATAL, "Unable to allocate config\n"); - exit(1); - } - gbproxy_init_config(gbcfg); - gbcfg->nsi = gprs_ns2_instantiate(tall_sgsn_ctx, gprs_ns2_prim_cb, gbcfg); - if (!gbcfg->nsi) { - LOGP(DGPRS, LOGL_ERROR, "Unable to instantiate NS\n"); - exit(1); - } - gprs_ns2_vty_init(gbcfg->nsi); - logging_vty_add_deprecated_subsys(tall_sgsn_ctx, "bssgp"); - - bssgp_set_bssgp_callback(gbprox_bssgp_send_cb, gbcfg); - - rc = gbproxy_parse_config(config_file, gbcfg); - if (rc < 0) { - LOGP(DGPRS, LOGL_FATAL, "Cannot parse config file '%s'\n", config_file); - exit(2); - } - - /* start telnet after reading config for vty_get_bind_addr() */ - rc = telnet_init_dynif(tall_sgsn_ctx, NULL, - vty_get_bind_addr(), OSMO_VTY_PORT_GBPROXY); - if (rc < 0) - exit(1); - - /* Start control interface after getting config for - * ctrl_vty_get_bind_addr() */ - ctrl = ctrl_interface_setup_dynip(gbcfg, ctrl_vty_get_bind_addr(), OSMO_CTRL_PORT_GBPROXY, NULL); - if (!ctrl) { - LOGP(DGPRS, LOGL_FATAL, "Failed to create CTRL interface.\n"); - exit(1); - } - - if (gb_ctrl_cmds_install() != 0) { - LOGP(DGPRS, LOGL_FATAL, "Failed to install CTRL commands.\n"); - exit(1); - } - - if (daemonize) { - rc = osmo_daemonize(); - if (rc < 0) { - perror("Error during daemonize"); - exit(1); - } - } - - while (1) { - rc = osmo_select_main(0); - if (rc < 0) - exit(3); - } - - exit(0); -} diff --git a/src/gbproxy/gb_proxy_peer.c b/src/gbproxy/gb_proxy_peer.c deleted file mode 100644 index 7d6ba864a..000000000 --- a/src/gbproxy/gb_proxy_peer.c +++ /dev/null @@ -1,759 +0,0 @@ -/* Gb proxy peer handling */ - -/* (C) 2010 by Harald Welte <laforge@gnumonks.org> - * (C) 2010-2013 by On-Waves - * (C) 2013 by Holger Hans Peter Freyther - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU 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 <osmocom/sgsn/gb_proxy.h> - -#include <osmocom/sgsn/debug.h> - -#include <osmocom/gprs/protocol/gsm_08_18.h> -#include <osmocom/core/crc16.h> -#include <osmocom/core/logging.h> -#include <osmocom/core/linuxlist.h> -#include <osmocom/core/rate_ctr.h> -#include <osmocom/core/stats.h> -#include <osmocom/core/talloc.h> -#include <osmocom/core/utils.h> -#include <osmocom/gsm/tlv.h> - -#include <string.h> - -extern void *tall_sgsn_ctx; - -static const struct rate_ctr_desc bvc_ctr_description[] = { - { "blocked", "BVC Block " }, - { "unblocked", "BVC Unblock " }, - { "dropped", "BVC blocked, dropped packet " }, - { "inv-nsei", "NSEI mismatch " }, - { "tx-err", "NS Transmission error " }, -}; - -osmo_static_assert(ARRAY_SIZE(bvc_ctr_description) == GBPROX_PEER_CTR_LAST, everything_described); - -static const struct rate_ctr_group_desc bvc_ctrg_desc = { - .group_name_prefix = "gbproxy:peer", - .group_description = "GBProxy Peer Statistics", - .num_ctr = ARRAY_SIZE(bvc_ctr_description), - .ctr_desc = bvc_ctr_description, - .class_id = OSMO_STATS_CLASS_PEER, -}; - - -/* Find the gbproxy_bvc by its BVCI. There can only be one match */ -struct gbproxy_bvc *gbproxy_bvc_by_bvci(struct gbproxy_nse *nse, uint16_t bvci) -{ - struct gbproxy_bvc *bvc; - hash_for_each_possible(nse->bvcs, bvc, list, bvci) { - if (bvc->bvci == bvci) - return bvc; - } - return NULL; -} - -struct gbproxy_bvc *gbproxy_bvc_alloc(struct gbproxy_nse *nse, uint16_t bvci) -{ - struct gbproxy_bvc *bvc; - OSMO_ASSERT(nse); - struct gbproxy_config *cfg = nse->cfg; - OSMO_ASSERT(cfg); - - bvc = talloc_zero(tall_sgsn_ctx, struct gbproxy_bvc); - if (!bvc) - return NULL; - - bvc->bvci = bvci; - bvc->ctrg = rate_ctr_group_alloc(bvc, &bvc_ctrg_desc, (nse->nsei << 16) | bvci); - if (!bvc->ctrg) { - talloc_free(bvc); - return NULL; - } - bvc->nse = nse; - - hash_add(nse->bvcs, &bvc->list, bvc->bvci); - - LOGPBVC_CAT(bvc, DOBJ, LOGL_INFO, "BVC Created\n"); - - /* We leave allocating the bvc->fi to the caller, as the FSM details depend - * on the type of BVC (SIG/PTP) and role (SGSN/BSS) */ - - return bvc; -} - -void gbproxy_bvc_free(struct gbproxy_bvc *bvc) -{ - struct gbproxy_cell *cell; - - if (!bvc) - return; - - LOGPBVC_CAT(bvc, DOBJ, LOGL_INFO, "BVC Destroying\n"); - - hash_del(&bvc->list); - - rate_ctr_group_free(bvc->ctrg); - bvc->ctrg = NULL; - - osmo_fsm_inst_free(bvc->fi); - - cell = bvc->cell; - if (cell) { - int i; - - if (cell->bss_bvc == bvc) - cell->bss_bvc = NULL; - - /* we could also be a SGSN-side BVC */ - for (i = 0; i < ARRAY_SIZE(cell->sgsn_bvc); i++) { - if (cell->sgsn_bvc[i] == bvc) - cell->sgsn_bvc[i] = NULL; - } - bvc->cell = NULL; - } - - talloc_free(bvc); -} - -/*! remove BVCs on NSE specified by NSEI. - * \param[in] cfg proxy in which we operate - * \param[in] nsei NS entity in which we should clean up - * \param[in] bvci if 0: remove all PTP BVCs; if != 0: BVCI of the single BVC to clean up */ -int gbproxy_cleanup_bvcs(struct gbproxy_nse *nse, uint16_t bvci) -{ - struct hlist_node *btmp; - struct gbproxy_bvc *bvc; - int j, counter = 0; - - if (!nse) - return 0; - - hash_for_each_safe(nse->bvcs, j, btmp, bvc, list) { - if (bvci && bvc->bvci != bvci) - continue; - if (bvci == 0 && bvc->bvci == 0) - continue; - - gbproxy_bvc_free(bvc); - counter += 1; - } - - return counter; -} - - -/*********************************************************************** - * CELL - ***********************************************************************/ - -/* Allocate a new 'cell' object */ -struct gbproxy_cell *gbproxy_cell_alloc(struct gbproxy_config *cfg, uint16_t bvci) -{ - struct gbproxy_cell *cell; - OSMO_ASSERT(cfg); - - cell = talloc_zero(cfg, struct gbproxy_cell); - if (!cell) - return NULL; - - cell->cfg = cfg; - cell->bvci = bvci; - - hash_add(cfg->cells, &cell->list, cell->bvci); - - LOGPCELL_CAT(cell, DOBJ, LOGL_INFO, "CELL Created\n"); - - return cell; -} - -/* Find cell by BVCI */ -struct gbproxy_cell *gbproxy_cell_by_bvci(struct gbproxy_config *cfg, uint16_t bvci) -{ - struct gbproxy_cell *cell; - - hash_for_each_possible(cfg->cells, cell, list, bvci) { - if (cell->bvci == bvci) - return cell; - } - return NULL; -} - -struct gbproxy_cell *gbproxy_cell_by_bvci_or_new(struct gbproxy_config *cfg, uint16_t bvci) -{ - struct gbproxy_cell *cell; - OSMO_ASSERT(cfg); - - cell = gbproxy_cell_by_bvci(cfg, bvci); - if (!cell) - cell = gbproxy_cell_alloc(cfg, bvci); - - return cell; -} - -void gbproxy_cell_free(struct gbproxy_cell *cell) -{ - unsigned int i; - - if (!cell) - return; - - LOGPCELL_CAT(cell, DOBJ, LOGL_INFO, "CELL Destroying\n"); - - /* remove from cfg.cells */ - hash_del(&cell->list); - - /* remove back-pointers from the BSS side */ - if (cell->bss_bvc && cell->bss_bvc->cell) - cell->bss_bvc->cell = NULL; - - /* remove back-pointers from the SGSN side */ - for (i = 0; i < ARRAY_SIZE(cell->sgsn_bvc); i++) { - if (!cell->sgsn_bvc[i]) - continue; - if (cell->sgsn_bvc[i]->cell) - cell->sgsn_bvc[i]->cell = NULL; - } - - talloc_free(cell); -} - -bool gbproxy_cell_add_sgsn_bvc(struct gbproxy_cell *cell, struct gbproxy_bvc *bvc) -{ - unsigned int i; - for (i = 0; i < ARRAY_SIZE(cell->sgsn_bvc); i++) { - if (!cell->sgsn_bvc[i]) { - cell->sgsn_bvc[i] = bvc; - LOGPCELL_CAT(cell, DOBJ, LOGL_DEBUG, "CELL linked to SGSN\n"); - LOGPBVC_CAT(bvc, DOBJ, LOGL_DEBUG, "BVC linked to CELL\n"); - return true; - } - } - return false; -} - - -/*********************************************************************** - * TLLI cache - ***********************************************************************/ - -static inline struct gbproxy_tlli_cache_entry *_get_tlli_entry(struct gbproxy_config *cfg, uint32_t tlli) -{ - struct gbproxy_tlli_cache_entry *cache_entry; - - hash_for_each_possible(cfg->tlli_cache.entries, cache_entry, list, tlli) { - if (cache_entry->tlli == tlli) - return cache_entry; - } - return NULL; -} - -void gbproxy_tlli_cache_update(struct gbproxy_nse *nse, uint32_t tlli) -{ - struct gbproxy_config *cfg = nse->cfg; - struct timespec now; - struct gbproxy_tlli_cache_entry *cache_entry = _get_tlli_entry(cfg, tlli); - - osmo_clock_gettime(CLOCK_MONOTONIC, &now); - - if (cache_entry) { - /* Update the entry if it already exists */ - cache_entry->nse = nse; - cache_entry->tstamp = now.tv_sec; - return; - } - - cache_entry = talloc_zero(cfg, struct gbproxy_tlli_cache_entry); - cache_entry->tlli = tlli; - cache_entry->nse = nse; - cache_entry->tstamp = now.tv_sec; - hash_add(cfg->tlli_cache.entries, &cache_entry->list, cache_entry->tlli); -} - -static void _tlli_cache_remove_nse(struct gbproxy_nse *nse) { - uint i; - struct gbproxy_config *cfg = nse->cfg; - struct gbproxy_tlli_cache_entry *tlli_cache; - struct hlist_node *tmp; - - hash_for_each_safe(cfg->tlli_cache.entries, i, tmp, tlli_cache, list) { - if (tlli_cache->nse == nse) { - hash_del(&tlli_cache->list); - talloc_free(tlli_cache); - } - } -} - -void gbproxy_tlli_cache_remove(struct gbproxy_config *cfg, uint32_t tlli) -{ - struct gbproxy_tlli_cache_entry *tlli_cache; - struct hlist_node *tmp; - - hash_for_each_possible_safe(cfg->tlli_cache.entries, tlli_cache, tmp, list, tlli) { - if (tlli_cache->tlli == tlli) { - hash_del(&tlli_cache->list); - talloc_free(tlli_cache); - return; - } - } -} - -int gbproxy_tlli_cache_cleanup(struct gbproxy_config *cfg) -{ - int i, count = 0; - struct gbproxy_tlli_cache_entry *tlli_cache; - struct hlist_node *tmp; - struct timespec now; - time_t expiry; - - osmo_clock_gettime(CLOCK_MONOTONIC, &now); - expiry = now.tv_sec - cfg->tlli_cache.timeout; - - hash_for_each_safe(cfg->tlli_cache.entries, i, tmp, tlli_cache, list) { - if (tlli_cache->tstamp < expiry) { - count++; - LOGP(DGPRS, LOGL_NOTICE, "Cache entry for TLLI %08x expired, removing\n", tlli_cache->tlli); - hash_del(&tlli_cache->list); - talloc_free(tlli_cache); - } - } - return count; - -} -/*********************************************************************** - * IMSI cache - ***********************************************************************/ -static inline uint16_t _checksum_imsi(const char *imsi) -{ - size_t len = strlen(imsi); - return osmo_crc16(0, (const uint8_t *)imsi, len); -} - -static inline struct gbproxy_imsi_cache_entry *_get_imsi_entry(struct gbproxy_config *cfg, const char *imsi) -{ - struct gbproxy_imsi_cache_entry *cache_entry; - uint16_t imsi_hash = _checksum_imsi(imsi); - - hash_for_each_possible(cfg->imsi_cache.entries, cache_entry, list, imsi_hash) { - if (!strncmp(cache_entry->imsi, imsi, sizeof(cache_entry->imsi))) - return cache_entry; - } - return NULL; -} - -void gbproxy_imsi_cache_update(struct gbproxy_nse *nse, const char *imsi) -{ - struct gbproxy_config *cfg = nse->cfg; - struct timespec now; - struct gbproxy_imsi_cache_entry *cache_entry = _get_imsi_entry(cfg, imsi); - uint16_t imsi_hash = _checksum_imsi(imsi); - - osmo_clock_gettime(CLOCK_MONOTONIC, &now); - - if (cache_entry) { - /* Update the entry if it already exists */ - cache_entry->nse = nse; - cache_entry->tstamp = now.tv_sec; - return; - } - - cache_entry = talloc_zero(cfg, struct gbproxy_imsi_cache_entry); - OSMO_STRLCPY_ARRAY(cache_entry->imsi, imsi); - cache_entry->nse = nse; - cache_entry->tstamp = now.tv_sec; - hash_add(cfg->imsi_cache.entries, &cache_entry->list, imsi_hash); -} - -static void _imsi_cache_remove_nse(struct gbproxy_nse *nse) { - uint i; - struct gbproxy_config *cfg = nse->cfg; - struct gbproxy_imsi_cache_entry *imsi_cache; - struct hlist_node *tmp; - - hash_for_each_safe(cfg->imsi_cache.entries, i, tmp, imsi_cache, list) { - if (imsi_cache->nse == nse) { - hash_del(&imsi_cache->list); - talloc_free(imsi_cache); - } - } -} - -void gbproxy_imsi_cache_remove(struct gbproxy_config *cfg, const char *imsi) -{ - struct gbproxy_imsi_cache_entry *imsi_cache; - struct hlist_node *tmp; - uint16_t imsi_hash = _checksum_imsi(imsi); - - hash_for_each_possible_safe(cfg->imsi_cache.entries, imsi_cache, tmp, list, imsi_hash) { - if (!(strncmp(imsi_cache->imsi, imsi, sizeof(imsi_cache->imsi)))) { - hash_del(&imsi_cache->list); - talloc_free(imsi_cache); - return; - } - } -} - -int gbproxy_imsi_cache_cleanup(struct gbproxy_config *cfg) -{ - int i, count = 0; - struct gbproxy_imsi_cache_entry *imsi_cache; - struct hlist_node *tmp; - struct timespec now; - time_t expiry; - - osmo_clock_gettime(CLOCK_MONOTONIC, &now); - expiry = now.tv_sec - cfg->imsi_cache.timeout; - - hash_for_each_safe(cfg->imsi_cache.entries, i, tmp, imsi_cache, list) { - if (imsi_cache->tstamp < expiry) { - count++; - LOGP(DGPRS, LOGL_NOTICE, "Cache entry for IMSI %s expired, removing\n", imsi_cache->imsi); - hash_del(&imsi_cache->list); - talloc_free(imsi_cache); - } - } - return count; -} - -/*********************************************************************** - * NSE - NS Entity - ***********************************************************************/ - -struct gbproxy_nse *gbproxy_nse_alloc(struct gbproxy_config *cfg, uint16_t nsei, bool sgsn_facing) -{ - struct gbproxy_nse *nse; - OSMO_ASSERT(cfg); - - nse = talloc_zero(tall_sgsn_ctx, struct gbproxy_nse); - if (!nse) - return NULL; - - nse->nsei = nsei; - nse->cfg = cfg; - nse->sgsn_facing = sgsn_facing; - - if (sgsn_facing) - hash_add(cfg->sgsn_nses, &nse->list, nsei); - else - hash_add(cfg->bss_nses, &nse->list, nsei); - - hash_init(nse->bvcs); - - LOGPNSE_CAT(nse, DOBJ, LOGL_INFO, "NSE Created\n"); - - return nse; -} - -static void _nse_free(struct gbproxy_nse *nse) -{ - struct gbproxy_bvc *bvc; - struct hlist_node *tmp; - int i; - - if (!nse) - return; - - LOGPNSE_CAT(nse, DOBJ, LOGL_INFO, "NSE Destroying\n"); - - hash_del(&nse->list); - /* Clear the cache entries of this NSE */ - _tlli_cache_remove_nse(nse); - _imsi_cache_remove_nse(nse); - - hash_for_each_safe(nse->bvcs, i, tmp, bvc, list) - gbproxy_bvc_free(bvc); - - talloc_free(nse); -} -static void _sgsn_free(struct gbproxy_sgsn *sgsn); - -void gbproxy_nse_free(struct gbproxy_nse *nse) -{ - if (!nse) - return; - OSMO_ASSERT(nse->cfg); - - if (nse->sgsn_facing) { - struct gbproxy_sgsn *sgsn = gbproxy_sgsn_by_nsei(nse->cfg, nse->nsei); - OSMO_ASSERT(sgsn); - _sgsn_free(sgsn); - } - - _nse_free(nse); -} - -struct gbproxy_nse *gbproxy_nse_by_nsei(struct gbproxy_config *cfg, uint16_t nsei, uint32_t flags) -{ - struct gbproxy_nse *nse; - OSMO_ASSERT(cfg); - - if (flags & NSE_F_SGSN) { - hash_for_each_possible(cfg->sgsn_nses, nse, list, nsei) { - if (nse->nsei == nsei) - return nse; - } - } - - if (flags & NSE_F_BSS) { - hash_for_each_possible(cfg->bss_nses, nse, list, nsei) { - if (nse->nsei == nsei) - return nse; - } - } - - return NULL; -} - -struct gbproxy_nse *gbproxy_nse_by_nsei_or_new(struct gbproxy_config *cfg, uint16_t nsei, bool sgsn_facing) -{ - struct gbproxy_nse *nse; - OSMO_ASSERT(cfg); - - nse = gbproxy_nse_by_nsei(cfg, nsei, sgsn_facing ? NSE_F_SGSN : NSE_F_BSS); - if (!nse) - nse = gbproxy_nse_alloc(cfg, nsei, sgsn_facing); - - return nse; -} - -struct gbproxy_nse *gbproxy_nse_by_tlli(struct gbproxy_config *cfg, uint32_t tlli) -{ - struct gbproxy_tlli_cache_entry *tlli_cache; - - hash_for_each_possible(cfg->tlli_cache.entries, tlli_cache, list, tlli) { - if (tlli_cache->tlli == tlli) - return tlli_cache->nse; - } - return NULL; -} - -struct gbproxy_nse *gbproxy_nse_by_imsi(struct gbproxy_config *cfg, const char *imsi) -{ - struct gbproxy_imsi_cache_entry *imsi_cache; - uint16_t imsi_hash = _checksum_imsi(imsi); - - hash_for_each_possible(cfg->imsi_cache.entries, imsi_cache, list, imsi_hash) { - if (!strncmp(imsi_cache->imsi, imsi, sizeof(imsi_cache->imsi))) - return imsi_cache->nse; - } - return NULL; -} - -/*********************************************************************** - * SGSN - Serving GPRS Support Node - ***********************************************************************/ - -/*! Allocate a new SGSN. This ensures the corresponding gbproxy_nse is allocated as well - * \param[in] cfg The gbproxy configuration - * \param[in] nsei The nsei where the SGSN can be reached - * \param[in] name A name to give the SGSN - * \return The SGSN, NULL if it couldn't be allocated - */ -struct gbproxy_sgsn *gbproxy_sgsn_alloc(struct gbproxy_config *cfg, uint16_t nsei, const char *name) -{ - struct gbproxy_sgsn *sgsn; - OSMO_ASSERT(cfg); - - sgsn = talloc_zero(tall_sgsn_ctx, struct gbproxy_sgsn); - if (!sgsn) - return NULL; - - sgsn->nse = gbproxy_nse_alloc(cfg, nsei, true); - if (!sgsn->nse) { - LOGP(DOBJ, LOGL_ERROR, "Could not allocate NSE(%05u) for SGSN(%s)\n", - nsei, sgsn->name); - goto free_sgsn; - } - - if (name) - sgsn->name = talloc_strdup(sgsn, name); - else - sgsn->name = talloc_asprintf(sgsn, "NSE(%05u)", sgsn->nse->nsei); - if (!sgsn->name) - goto free_sgsn; - - sgsn->pool.allow_attach = true; - sgsn->pool.nri_ranges = osmo_nri_ranges_alloc(sgsn); - - llist_add_tail(&sgsn->list, &cfg->sgsns); - LOGPSGSN_CAT(sgsn, DOBJ, LOGL_INFO, "SGSN Created\n"); - return sgsn; - -free_sgsn: - talloc_free(sgsn); - return NULL; -} - -/* Only free gbproxy_sgsn, sgsn can't be NULL */ -static void _sgsn_free(struct gbproxy_sgsn *sgsn) { - struct gbproxy_config *cfg; - - OSMO_ASSERT(sgsn->nse); - cfg = sgsn->nse->cfg; - OSMO_ASSERT(cfg); - - LOGPSGSN_CAT(sgsn, DOBJ, LOGL_INFO, "SGSN Destroying\n"); - llist_del(&sgsn->list); - /* talloc will free ->name and ->pool.nri_ranges */ - talloc_free(sgsn); -} - -/*! Free the SGSN. This ensures the corresponding gbproxy_nse is freed as well - * \param[in] sgsn The SGSN - */ -void gbproxy_sgsn_free(struct gbproxy_sgsn *sgsn) -{ - if (!sgsn) - return; - - OSMO_ASSERT(sgsn->nse) - - _nse_free(sgsn->nse); - _sgsn_free(sgsn); -} - -/*! Return the SGSN for a given NSEI - * \param[in] cfg The gbproxy configuration - * \param[in] nsei The nsei where the SGSN can be reached - * \return Returns the matching SGSN or NULL if it couldn't be found - */ -struct gbproxy_sgsn *gbproxy_sgsn_by_name(struct gbproxy_config *cfg, const char *name) -{ - struct gbproxy_sgsn *sgsn; - OSMO_ASSERT(cfg); - - llist_for_each_entry(sgsn, &cfg->sgsns, list) { - if (!strcmp(sgsn->name, name)) - return sgsn; - } - - return NULL; -} - -/*! Return the SGSN for a given NSEI - * \param[in] cfg The gbproxy configuration - * \param[in] nsei The nsei where the SGSN can be reached - * \return Returns the matching SGSN or NULL if it couldn't be found - */ -struct gbproxy_sgsn *gbproxy_sgsn_by_nsei(struct gbproxy_config *cfg, uint16_t nsei) -{ - struct gbproxy_sgsn *sgsn; - OSMO_ASSERT(cfg); - - llist_for_each_entry(sgsn, &cfg->sgsns, list) { - if (sgsn->nse->nsei == nsei) - return sgsn; - } - - return NULL; -} - -/*! Return the SGSN for a given NSEI, creating a new one if none exists - * \param[in] cfg The gbproxy configuration - * \param[in] nsei The nsei where the SGSN can be reached - * \return Returns the SGSN - */ -struct gbproxy_sgsn *gbproxy_sgsn_by_nsei_or_new(struct gbproxy_config *cfg, uint16_t nsei) -{ - struct gbproxy_sgsn *sgsn; - OSMO_ASSERT(cfg); - - sgsn = gbproxy_sgsn_by_nsei(cfg, nsei); - if (!sgsn) - sgsn = gbproxy_sgsn_alloc(cfg, nsei, NULL); - - return sgsn; -} - -/*! Return the gbproxy_sgsn matching that NRI - * \param[in] cfg proxy in which we operate - * \param[in] nri NRI to look for - * \param[out] null_nri If not NULL this indicates whether the NRI is a null NRI - * \return The SGSN this NRI has been added to, NULL if no matching SGSN could be found - */ -struct gbproxy_sgsn *gbproxy_sgsn_by_nri(struct gbproxy_config *cfg, uint16_t nri, bool *null_nri) -{ - struct gbproxy_sgsn *sgsn; - OSMO_ASSERT(cfg); - - llist_for_each_entry(sgsn, &cfg->sgsns, list) { - if (osmo_nri_v_matches_ranges(nri, sgsn->pool.nri_ranges)) { - /* Also check if the NRI we're looking for is a NULL NRI */ - if (null_nri) { - if (osmo_nri_v_matches_ranges(nri, cfg->pool.null_nri_ranges)) - *null_nri = true; - else - *null_nri = false; - } - return sgsn; - } - } - - return NULL; -} - -/*! Seleect a pseudo-random SGSN for a given TLLI, ignoring any SGSN that is not accepting connections - * \param[in] cfg The gbproxy configuration - * \param[in] sgsn_avoid If not NULL then avoid this SGSN when selecting a new one. Use for load redistribution - * \param[in] tlli The tlli to choose an SGSN for. The same tlli will map to the same SGSN as long as no SGSN is - * added/removed or allow_attach changes. - * \return Returns the sgsn on success, NULL if no SGSN that allows new connections could be found - */ -struct gbproxy_sgsn *gbproxy_sgsn_by_tlli(struct gbproxy_config *cfg, struct gbproxy_sgsn *sgsn_avoid, - uint32_t tlli) -{ - uint32_t i = 0; - uint32_t index, num_sgsns; - OSMO_ASSERT(cfg); - - struct gbproxy_sgsn *sgsn = cfg->pool.nsf_override; - - if (sgsn) { - LOGPSGSN(sgsn, LOGL_DEBUG, "Node selection function is overridden by config\n"); - return sgsn; - } - - /* TODO: We should keep track of count in cfg */ - num_sgsns = llist_count(&cfg->sgsns); - - if (num_sgsns == 0) - return NULL; - - /* FIXME: 256 SGSNs ought to be enough for everyone */ - index = hash_32(tlli, 8) % num_sgsns; - - /* Get the first enabled SGSN after index */ - llist_for_each_entry(sgsn, &cfg->sgsns, list) { - if (i >= index && sgsn->pool.allow_attach) { - return sgsn; - } - i++; - } - /* Start again from the beginning */ - i = 0; - llist_for_each_entry(sgsn, &cfg->sgsns, list) { - if (i >= index) { - break; - } else if (sgsn->pool.allow_attach) { - return sgsn; - } - i++; - } - - return NULL; -} diff --git a/src/gbproxy/gb_proxy_vty.c b/src/gbproxy/gb_proxy_vty.c deleted file mode 100644 index 7ae65d20e..000000000 --- a/src/gbproxy/gb_proxy_vty.c +++ /dev/null @@ -1,778 +0,0 @@ -/* - * (C) 2010 by Harald Welte <laforge@gnumonks.org> - * (C) 2010 by On-Waves - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - */ - -#include <sys/socket.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <string.h> -#include <time.h> -#include <inttypes.h> - -#include <osmocom/core/hashtable.h> -#include <osmocom/core/talloc.h> -#include <osmocom/core/timer.h> -#include <osmocom/core/rate_ctr.h> -#include <osmocom/core/utils.h> - -#include <osmocom/gprs/gprs_ns2.h> -#include <osmocom/gprs/bssgp_bvc_fsm.h> - -#include <osmocom/gsm/apn.h> -#include <osmocom/gsm/gsm23236.h> -#include <osmocom/gsm/gsm48.h> - -#include <osmocom/sgsn/debug.h> -#include <osmocom/sgsn/gb_proxy.h> -#include <osmocom/sgsn/gprs_utils.h> -#include <osmocom/sgsn/vty.h> - -#include <osmocom/vty/command.h> -#include <osmocom/vty/logging.h> -#include <osmocom/vty/vty.h> -#include <osmocom/vty/misc.h> - -#define GBPROXY_STR "Display information about the Gb proxy\n" -#define NRI_STR "Mapping of Network Resource Indicators to this SGSN, for SGSN pooling\n" -#define NULL_NRI_STR "Define NULL-NRI values that cause re-assignment of an MS to a different SGSN, for SGSN pooling.\n" -#define NRI_FIRST_LAST_STR "First value of the NRI value range, should not surpass the configured 'nri bitlen'.\n" \ - "Last value of the NRI value range, should not surpass the configured 'nri bitlen' and be larger than the" \ - " first value; if omitted, apply only the first value.\n" -#define NRI_ARGS_TO_STR_FMT "%s%s%s" -#define NRI_ARGS_TO_STR_ARGS(ARGC, ARGV) ARGV[0], (ARGC>1)? ".." : "", (ARGC>1)? ARGV[1] : "" -#define NRI_WARN(SGSN, FORMAT, args...) do { \ - vty_out(vty, "%% Warning: NSE(%05d/SGSN): " FORMAT "%s", (SGSN)->nse->nsei, ##args, VTY_NEWLINE); \ - LOGP(DLBSSGP, LOGL_ERROR, "NSE(%05d/SGSN): " FORMAT "\n", (SGSN)->nse->nsei, ##args); \ - } while (0) - -static struct gbproxy_config *g_cfg = NULL; - -/* - * vty code for gbproxy below - */ -static struct cmd_node gbproxy_node = { - GBPROXY_NODE, - "%s(config-gbproxy)# ", - 1, -}; - -static void gbprox_vty_print_bvc(struct vty *vty, struct gbproxy_bvc *bvc) -{ - - if (bvc->bvci == 0) { - vty_out(vty, "NSEI %5u, SIG-BVCI %5u [%s]%s", bvc->nse->nsei, bvc->bvci, - osmo_fsm_inst_state_name(bvc->fi), VTY_NEWLINE); - } else { - struct gprs_ra_id raid; - gsm48_parse_ra(&raid, bvc->ra); - vty_out(vty, "NSEI %5u, PTP-BVCI %5u, RAI %s [%s]%s", bvc->nse->nsei, bvc->bvci, - osmo_rai_name(&raid), osmo_fsm_inst_state_name(bvc->fi), VTY_NEWLINE); - } -} - -static void gbproxy_vty_print_nse(struct vty *vty, struct gbproxy_nse *nse, bool show_stats) -{ - struct gbproxy_bvc *bvc; - int j; - - hash_for_each(nse->bvcs, j, bvc, list) { - gbprox_vty_print_bvc(vty, bvc); - - if (show_stats) - vty_out_rate_ctr_group(vty, " ", bvc->ctrg); - } -} - -static void gbproxy_vty_print_cell(struct vty *vty, struct gbproxy_cell *cell, bool show_stats) -{ - struct gprs_ra_id raid; - gsm48_parse_ra(&raid, cell->ra); - unsigned int num_sgsn_bvc = 0; - unsigned int i; - - vty_out(vty, "BVCI %5u RAI %s: ", cell->bvci, osmo_rai_name(&raid)); - if (cell->bss_bvc) - vty_out(vty, "BSS NSEI %5u, SGSN NSEI ", cell->bss_bvc->nse->nsei); - else - vty_out(vty, "BSS NSEI <none>, SGSN NSEI "); - - for (i = 0; i < ARRAY_SIZE(cell->sgsn_bvc); i++) { - struct gbproxy_bvc *sgsn_bvc = cell->sgsn_bvc[i]; - if (sgsn_bvc) { - vty_out(vty, "%5u ", sgsn_bvc->nse->nsei); - num_sgsn_bvc++; - } - } - if (num_sgsn_bvc) - vty_out(vty, "%s", VTY_NEWLINE); - else - vty_out(vty, "<none>%s", VTY_NEWLINE); -} - -static int config_write_gbproxy(struct vty *vty) -{ - struct osmo_nri_range *r; - - vty_out(vty, "gbproxy%s", VTY_NEWLINE); - - if (g_cfg->pool.bvc_fc_ratio != 100) - vty_out(vty, " pool bvc-flow-control-ratio %u%s", g_cfg->pool.bvc_fc_ratio, VTY_NEWLINE); - - if (g_cfg->pool.nri_bitlen != OSMO_NRI_BITLEN_DEFAULT) - vty_out(vty, " nri bitlen %u%s", g_cfg->pool.nri_bitlen, VTY_NEWLINE); - - llist_for_each_entry(r, &g_cfg->pool.null_nri_ranges->entries, entry) { - vty_out(vty, " nri null add %d", r->first); - if (r->first != r->last) - vty_out(vty, " %d", r->last); - vty_out(vty, "%s", VTY_NEWLINE); - } - return CMD_SUCCESS; -} - -DEFUN(cfg_gbproxy, - cfg_gbproxy_cmd, - "gbproxy", - "Configure the Gb proxy") -{ - vty->node = GBPROXY_NODE; - return CMD_SUCCESS; -} - -/* VTY code for SGSN (pool) configuration */ -extern const struct bssgp_bvc_fsm_ops sgsn_sig_bvc_fsm_ops; -#include <osmocom/gprs/protocol/gsm_08_18.h> - -static struct cmd_node sgsn_node = { - SGSN_NODE, - "%s(config-sgsn)# ", - 1, -}; - -static void sgsn_write_nri(struct vty *vty, struct gbproxy_sgsn *sgsn, bool verbose) -{ - struct osmo_nri_range *r; - - if (verbose) { - vty_out(vty, "sgsn nsei %d%s", sgsn->nse->nsei, VTY_NEWLINE); - if (llist_empty(&sgsn->pool.nri_ranges->entries)) { - vty_out(vty, " %% no NRI mappings%s", VTY_NEWLINE); - return; - } - } - - llist_for_each_entry(r, &sgsn->pool.nri_ranges->entries, entry) { - if (osmo_nri_range_validate(r, 255)) - vty_out(vty, " %% INVALID RANGE:"); - vty_out(vty, " nri add %d", r->first); - if (r->first != r->last) - vty_out(vty, " %d", r->last); - vty_out(vty, "%s", VTY_NEWLINE); - } -} - -static void write_sgsn(struct vty *vty, struct gbproxy_sgsn *sgsn) -{ - vty_out(vty, "sgsn nsei %u%s", sgsn->nse->nsei, VTY_NEWLINE); - vty_out(vty, " name %s%s", sgsn->name, VTY_NEWLINE); - vty_out(vty, " %sallow-attach%s", sgsn->pool.allow_attach ? "" : "no ", VTY_NEWLINE); - sgsn_write_nri(vty, sgsn, false); -} - -static int config_write_sgsn(struct vty *vty) -{ - struct gbproxy_sgsn *sgsn; - - llist_for_each_entry(sgsn, &g_cfg->sgsns, list) - write_sgsn(vty, sgsn); - - return CMD_SUCCESS; -} - -DEFUN(cfg_sgsn_nsei, - cfg_sgsn_nsei_cmd, - "sgsn nsei <0-65534>", - "Configure the SGSN\n" - "NSEI to be used in the connection with the SGSN\n" - "The NSEI\n") -{ - uint32_t features = 0; // FIXME: make configurable - unsigned int nsei = atoi(argv[0]); - unsigned int num_sgsn = llist_count(&g_cfg->sgsns); - struct gbproxy_sgsn *sgsn; - struct gbproxy_nse *nse; - struct gbproxy_bvc *bvc; - - if (num_sgsn >= GBPROXY_MAX_NR_SGSN) { - vty_out(vty, "%% Too many SGSN NSE defined (%d), increase GBPROXY_MAX_NR_SGSN%s", - num_sgsn, VTY_NEWLINE); - return CMD_WARNING; - } - - /* This will have created the gbproxy_nse as well */ - sgsn = gbproxy_sgsn_by_nsei_or_new(g_cfg, nsei); - if (!sgsn) - goto free_nothing; - nse = sgsn->nse; - if (num_sgsn > 1 && g_cfg->pool.nri_bitlen == 0) - vty_out(vty, "%% Multiple SGSNs defined, but no pooling enabled%s", VTY_NEWLINE); - - - if (!gbproxy_bvc_by_bvci(nse, 0)) { - uint8_t cause = BSSGP_CAUSE_OML_INTERV; - bvc = gbproxy_bvc_alloc(nse, 0); - if (!bvc) - goto free_sgsn; - bvc->fi = bssgp_bvc_fsm_alloc_sig_bss(bvc, nse->cfg->nsi, nsei, features); - if (!bvc->fi) - goto free_bvc; - bssgp_bvc_fsm_set_ops(bvc->fi, &sgsn_sig_bvc_fsm_ops, bvc); - osmo_fsm_inst_dispatch(bvc->fi, BSSGP_BVCFSM_E_REQ_RESET, &cause); - } - - vty->node = SGSN_NODE; - vty->index = sgsn; - return CMD_SUCCESS; - -free_bvc: - gbproxy_bvc_free(bvc); -free_sgsn: - gbproxy_sgsn_free(sgsn); -free_nothing: - vty_out(vty, "%% Unable to create NSE for NSEI=%05u%s", nsei, VTY_NEWLINE); - return CMD_WARNING; -} - -DEFUN(cfg_sgsn_name, - cfg_sgsn_name_cmd, - "name NAME", - "Configure the SGSN\n" - "Name the SGSN\n" - "The name\n") -{ - struct gbproxy_sgsn *sgsn = vty->index; - const char *name = argv[0]; - - - osmo_talloc_replace_string(sgsn, &sgsn->name, name); - if (!sgsn->name) { - vty_out(vty, "%% Unable to set name for SGSN with nsei %05u%s", sgsn->nse->nsei, VTY_NEWLINE); - return CMD_WARNING; - } - - return CMD_SUCCESS; -} - -DEFUN_ATTR(cfg_sgsn_nri_add, cfg_sgsn_nri_add_cmd, - "nri add <0-32767> [<0-32767>]", - NRI_STR "Add NRI value or range to the NRI mapping for this MSC\n" - NRI_FIRST_LAST_STR, - CMD_ATTR_IMMEDIATE) -{ - struct gbproxy_sgsn *sgsn = vty->index; - struct gbproxy_sgsn *other_sgsn; - bool before; - int rc; - const char *message; - struct osmo_nri_range add_range; - - rc = osmo_nri_ranges_vty_add(&message, &add_range, sgsn->pool.nri_ranges, argc, argv, g_cfg->pool.nri_bitlen); - if (message) { - NRI_WARN(sgsn, "%s: " NRI_ARGS_TO_STR_FMT, message, NRI_ARGS_TO_STR_ARGS(argc, argv)); - } - if (rc < 0) - return CMD_WARNING; - - /* Issue a warning about NRI range overlaps (but still allow them). - * Overlapping ranges will map to whichever SGSN comes fist in the gbproxy_config->sgsns llist, - * which should be the first one defined in the config */ - before = true; - - llist_for_each_entry(other_sgsn, &g_cfg->sgsns, list) { - if (other_sgsn == sgsn) { - before = false; - continue; - } - if (osmo_nri_range_overlaps_ranges(&add_range, other_sgsn->pool.nri_ranges)) { - uint16_t nsei = sgsn->nse->nsei; - uint16_t other_nsei = other_sgsn->nse->nsei; - NRI_WARN(sgsn, "NRI range [%d..%d] overlaps between NSE %05d and NSE %05d." - " For overlaps, NSE %05d has higher priority than NSE %05d", - add_range.first, add_range.last, nsei, other_nsei, - before ? other_nsei : nsei, before ? nsei : other_nsei); - } - } - return CMD_SUCCESS; -} - -DEFUN_ATTR(cfg_sgsn_nri_del, cfg_sgsn_nri_del_cmd, - "nri del <0-32767> [<0-32767>]", - NRI_STR "Remove NRI value or range from the NRI mapping for this MSC\n" - NRI_FIRST_LAST_STR, - CMD_ATTR_IMMEDIATE) -{ - struct gbproxy_sgsn *sgsn = vty->index; - int rc; - const char *message; - - rc = osmo_nri_ranges_vty_del(&message, NULL, sgsn->pool.nri_ranges, argc, argv); - if (message) { - NRI_WARN(sgsn, "%s: " NRI_ARGS_TO_STR_FMT, message, NRI_ARGS_TO_STR_ARGS(argc, argv)); - } - if (rc < 0) - return CMD_WARNING; - return CMD_SUCCESS; -} - -DEFUN_ATTR(cfg_sgsn_allow_attach, cfg_sgsn_allow_attach_cmd, - "allow-attach", - "Allow this SGSN to attach new subscribers (default).\n", - CMD_ATTR_IMMEDIATE) -{ - struct gbproxy_sgsn *sgsn = vty->index; - sgsn->pool.allow_attach = true; - return CMD_SUCCESS; -} - -DEFUN_ATTR(cfg_sgsn_no_allow_attach, cfg_sgsn_no_allow_attach_cmd, - "no allow-attach", - NO_STR - "Do not assign new subscribers to this MSC." - " Useful if an MSC in an MSC pool is configured to off-load subscribers." - " The MSC will still be operational for already IMSI-Attached subscribers," - " but the NAS node selection function will skip this MSC for new subscribers\n", - CMD_ATTR_IMMEDIATE) -{ - struct gbproxy_sgsn *sgsn = vty->index; - sgsn->pool.allow_attach = false; - return CMD_SUCCESS; -} - -DEFUN(sgsn_show_nri_all, show_nri_all_cmd, - "show nri all", - SHOW_STR NRI_STR "Show all SGSNs\n") -{ - struct gbproxy_sgsn *sgsn; - - llist_for_each_entry(sgsn, &g_cfg->sgsns, list) - sgsn_write_nri(vty, sgsn, true); - - return CMD_SUCCESS; -} - -DEFUN(show_nri_nsei, show_nri_nsei_cmd, - "show nri nsei <0-65535>", - SHOW_STR NRI_STR "Identify SGSN by NSEI\n" - "NSEI of the SGSN\n") -{ - struct gbproxy_sgsn *sgsn; - int nsei = atoi(argv[0]); - - sgsn = gbproxy_sgsn_by_nsei(g_cfg, nsei); - if (!sgsn) { - vty_out(vty, "%% No SGSN with found for NSEI %05d%s", nsei, VTY_NEWLINE); - return CMD_SUCCESS; - } - sgsn_write_nri(vty, sgsn, true); - - return CMD_SUCCESS; -} - -DEFUN(cfg_pool_bvc_fc_ratio, - cfg_pool_bvc_fc_ratio_cmd, - "pool bvc-flow-control-ratio <1-100>", - "SGSN Pool related configuration\n" - "Ratio of BSS-advertised bucket size + leak rate advertised to each SGSN\n" - "Ratio of BSS-advertised bucket size + leak rate advertised to each SGSN (Percent)\n") -{ - g_cfg->pool.bvc_fc_ratio = atoi(argv[0]); - return CMD_SUCCESS; -} -DEFUN_ATTR(cfg_gbproxy_nri_bitlen, - cfg_gbproxy_nri_bitlen_cmd, - "nri bitlen <0-15>", - NRI_STR - "Set number of bits that an NRI has, to extract from TMSI identities (always starting just after the TMSI's most significant octet).\n" - "bit count (0 disables) pooling)\n", - CMD_ATTR_IMMEDIATE) -{ - g_cfg->pool.nri_bitlen = atoi(argv[0]); - - if (llist_count(&g_cfg->sgsns) > 1 && g_cfg->pool.nri_bitlen == 0) - vty_out(vty, "%% Pooling disabled, but multiple SGSNs defined%s", VTY_NEWLINE); - - /* TODO: Verify all nri ranges and warn on mismatch */ - - return CMD_SUCCESS; -} - -DEFUN_ATTR(cfg_gbproxy_nri_null_add, - cfg_gbproxy_nri_null_add_cmd, - "nri null add <0-32767> [<0-32767>]", - NRI_STR NULL_NRI_STR "Add NULL-NRI value (or range)\n" - NRI_FIRST_LAST_STR, - CMD_ATTR_IMMEDIATE) -{ - int rc; - const char *message; - - rc = osmo_nri_ranges_vty_add(&message, NULL, g_cfg->pool.null_nri_ranges, argc, argv, - g_cfg->pool.nri_bitlen); - if (message) { - vty_out(vty, "%% nri null add: %s: " NRI_ARGS_TO_STR_FMT "%s", message, NRI_ARGS_TO_STR_ARGS(argc, argv), - VTY_NEWLINE); - vty_out(vty, "%s: \n" NRI_ARGS_TO_STR_FMT, message, NRI_ARGS_TO_STR_ARGS(argc, argv)); - } - if (rc < 0) - return CMD_WARNING; - return CMD_SUCCESS; -} - -DEFUN_ATTR(cfg_gbproxy_nri_null_del, - cfg_gbproxy_nri_null_del_cmd, - "nri null del <0-32767> [<0-32767>]", - NRI_STR NULL_NRI_STR "Remove NRI value or range from the NRI mapping for this MSC\n" - NRI_FIRST_LAST_STR, - CMD_ATTR_IMMEDIATE) -{ - int rc; - const char *message; - rc = osmo_nri_ranges_vty_del(&message, NULL, g_cfg->pool.null_nri_ranges, argc, argv); - if (message) { - vty_out(vty, "%% %s: " NRI_ARGS_TO_STR_FMT "%s", message, NRI_ARGS_TO_STR_ARGS(argc, argv), - VTY_NEWLINE); - } - if (rc < 0) - return CMD_WARNING; - return CMD_SUCCESS; -} - -static void log_set_bvc_filter(struct log_target *target, - const uint16_t *bvci) -{ - if (bvci) { - uintptr_t bvci_filter = *bvci | BVC_LOG_CTX_FLAG; - target->filter_map |= (1 << LOG_FLT_GB_BVC); - target->filter_data[LOG_FLT_GB_BVC] = (void *)bvci_filter; - } else if (target->filter_data[LOG_FLT_GB_BVC]) { - target->filter_map = ~(1 << LOG_FLT_GB_BVC); - target->filter_data[LOG_FLT_GB_BVC] = NULL; - } -} - -DEFUN(logging_fltr_bvc, - logging_fltr_bvc_cmd, - "logging filter bvc bvci <0-65535>", - LOGGING_STR FILTER_STR - "Filter based on BSSGP VC\n" - "Identify BVC by BVCI\n" - "Numeric identifier\n") -{ - struct log_target *tgt; - uint16_t id = atoi(argv[0]); - - log_tgt_mutex_lock(); - tgt = osmo_log_vty2tgt(vty); - if (!tgt) { - log_tgt_mutex_unlock(); - return CMD_WARNING; - } - - log_set_bvc_filter(tgt, &id); - log_tgt_mutex_unlock(); - return CMD_SUCCESS; -} - -DEFUN(show_gbproxy_bvc, show_gbproxy_bvc_cmd, "show gbproxy bvc (bss|sgsn) [stats]", - SHOW_STR GBPROXY_STR - "Show BSSGP Virtual Connections\n" - "Display BSS-side BVCs\n" - "Display SGSN-side BVCs\n" - "Show statistics\n") -{ - struct gbproxy_nse *nse; - bool show_stats = argc >= 2; - int i; - - if (show_stats) - vty_out_rate_ctr_group(vty, "", g_cfg->ctrg); - - if (!strcmp(argv[0], "bss")) { - hash_for_each(g_cfg->bss_nses, i, nse, list) - gbproxy_vty_print_nse(vty, nse, show_stats); - } else { - hash_for_each(g_cfg->sgsn_nses, i, nse, list) - gbproxy_vty_print_nse(vty, nse, show_stats); - } - return CMD_SUCCESS; -} - -DEFUN(show_gbproxy_cell, show_gbproxy_cell_cmd, "show gbproxy cell [stats]", - SHOW_STR GBPROXY_STR - "Show GPRS Cell Information\n" - "Show statistics\n") -{ - struct gbproxy_cell *cell; - bool show_stats = argc >= 1; - int i; - - hash_for_each(g_cfg->cells, i, cell, list) - gbproxy_vty_print_cell(vty, cell, show_stats); - - return CMD_SUCCESS; -} - -DEFUN(show_gbproxy_links, show_gbproxy_links_cmd, "show gbproxy links", - SHOW_STR GBPROXY_STR "Show logical links\n") -{ - struct gbproxy_nse *nse; - int i, j; - - hash_for_each(g_cfg->bss_nses, i, nse, list) { - struct gbproxy_bvc *bvc; - hash_for_each(nse->bvcs, j, bvc, list) { - gbprox_vty_print_bvc(vty, bvc); - } - } - return CMD_SUCCESS; -} - -DEFUN(show_gbproxy_tlli_cache, show_gbproxy_tlli_cache_cmd, - "show gbproxy tlli-cache", - SHOW_STR GBPROXY_STR "Show TLLI cache entries\n") -{ - struct gbproxy_tlli_cache_entry *entry; - struct timespec now; - time_t expiry; - int i, count = 0; - - osmo_clock_gettime(CLOCK_MONOTONIC, &now); - expiry = now.tv_sec - g_cfg->tlli_cache.timeout; - - vty_out(vty, "TLLI cache timeout %us%s", g_cfg->tlli_cache.timeout, VTY_NEWLINE); - hash_for_each(g_cfg->tlli_cache.entries, i, entry, list) { - time_t valid = entry->tstamp - expiry; - struct gbproxy_nse *nse = entry->nse; - - vty_out(vty, " TLLI %08x -> NSE(%05u/%s) valid %lds%s", entry->tlli, nse->nsei, - nse->sgsn_facing ? "SGSN" : "BSS", valid, VTY_NEWLINE); - count++; - } - vty_out(vty, "TLLI cache contains %u entries%s", count, VTY_NEWLINE); - return CMD_SUCCESS; -} - -DEFUN(show_gbproxy_imsi_cache, show_gbproxy_imsi_cache_cmd, - "show gbproxy imsi-cache", - SHOW_STR GBPROXY_STR "Show IMSI cache entries\n") -{ - struct gbproxy_imsi_cache_entry *entry; - struct timespec now; - time_t expiry; - int i, count = 0; - - osmo_clock_gettime(CLOCK_MONOTONIC, &now); - expiry = now.tv_sec - g_cfg->imsi_cache.timeout; - - vty_out(vty, "IMSI cache timeout %us%s", g_cfg->imsi_cache.timeout, VTY_NEWLINE); - hash_for_each(g_cfg->imsi_cache.entries, i, entry, list) { - time_t valid = entry->tstamp - expiry; - struct gbproxy_nse *nse = entry->nse; - vty_out(vty, " IMSI %s -> NSE(%05u/%s): valid %lds%s", entry->imsi, nse->nsei, - nse->sgsn_facing ? "SGSN" : "BSS", valid, VTY_NEWLINE); - count++; - } - vty_out(vty, "IMSI cache contains %u entries%s", count, VTY_NEWLINE); - return CMD_SUCCESS; -} - -DEFUN(delete_gb_bvci, delete_gb_bvci_cmd, - "delete-gbproxy-peer <0-65534> bvci <2-65534>", - "Delete a GBProxy bvc by NSEI and optionally BVCI\n" - "NSEI number\n" - "Only delete bvc with a matching BVCI\n" - "BVCI number\n") -{ - const uint16_t nsei = atoi(argv[0]); - const uint16_t bvci = atoi(argv[1]); - struct gbproxy_nse *nse = gbproxy_nse_by_nsei(g_cfg, nsei, NSE_F_BSS); - int counter; - - if (!nse) { - vty_out(vty, "NSE not found%s", VTY_NEWLINE); - return CMD_WARNING; - } - - counter = gbproxy_cleanup_bvcs(nse, bvci); - - if (counter == 0) { - vty_out(vty, "BVC not found%s", VTY_NEWLINE); - return CMD_WARNING; - } - - return CMD_SUCCESS; -} - -DEFUN(delete_gb_nsei, delete_gb_nsei_cmd, - "delete-gbproxy-peer <0-65534> (only-bvc|only-nsvc|all) [dry-run]", - "Delete a GBProxy bvc by NSEI and optionally BVCI\n" - "NSEI number\n" - "Only delete BSSGP connections (BVC)\n" - "Only delete dynamic NS connections (NS-VC)\n" - "Delete BVC and dynamic NS connections\n" - "Show what would be deleted instead of actually deleting\n" - ) -{ - const uint16_t nsei = atoi(argv[0]); - const char *mode = argv[1]; - int dry_run = argc > 2; - int delete_bvc = 0; - int delete_nsvc = 0; - int counter; - - if (strcmp(mode, "only-bvc") == 0) - delete_bvc = 1; - else if (strcmp(mode, "only-nsvc") == 0) - delete_nsvc = 1; - else - delete_bvc = delete_nsvc = 1; - - if (delete_bvc) { - if (!dry_run) { - struct gbproxy_nse *nse = gbproxy_nse_by_nsei(g_cfg, nsei, NSE_F_BSS); - counter = gbproxy_cleanup_bvcs(nse, 0); - gbproxy_nse_free(nse); - } else { - struct gbproxy_nse *nse; - struct gbproxy_bvc *bvc; - int i, j; - counter = 0; - hash_for_each(g_cfg->bss_nses, i, nse, list) { - if (nse->nsei != nsei) - continue; - hash_for_each(nse->bvcs, j, bvc, list) { - vty_out(vty, "BVC: "); - gbprox_vty_print_bvc(vty, bvc); - counter += 1; - } - } - } - vty_out(vty, "%sDeleted %d BVC%s", - dry_run ? "Not " : "", counter, VTY_NEWLINE); - } - - if (delete_nsvc) { - struct gprs_ns2_inst *nsi = g_cfg->nsi; - struct gprs_ns2_nse *nse; - - nse = gprs_ns2_nse_by_nsei(nsi, nsei); - if (!nse) { - vty_out(vty, "NSEI not found%s", VTY_NEWLINE); - return CMD_WARNING; - } - - /* TODO: We should NOT delete a persistent NSEI/NSVC as soon as we can check for these */ - if (!dry_run) - gprs_ns2_free_nse(nse); - - vty_out(vty, "%sDeleted NS-VCs for NSEI %d%s", - dry_run ? "Not " : "", nsei, VTY_NEWLINE); - } - - return CMD_SUCCESS; -} - -/* Only for ttcn3 testing */ -DEFUN_HIDDEN(sgsn_pool_nsf_fixed, sgsn_pool_nsf_fixed_cmd, - "sgsn-pool nsf fixed NAME", - "SGSN pooling: load balancing across multiple SGSNs.\n" - "Customize the Network Selection Function.\n" - "Set a fixed SGSN to use (for testing).\n" - "The name of the SGSN to use.\n") -{ - const char *name = argv[0]; - struct gbproxy_sgsn *sgsn = gbproxy_sgsn_by_name(g_cfg, name); - - if (!sgsn) { - vty_out(vty, "%% Could not find SGSN with name %s%s", name, VTY_NEWLINE); - return CMD_WARNING; - } - - g_cfg->pool.nsf_override = sgsn; - return CMD_SUCCESS; -} - -DEFUN_HIDDEN(sgsn_pool_nsf_normal, sgsn_pool_nsf_normal_cmd, - "sgsn-pool nsf normal", - "SGSN pooling: load balancing across multiple SGSNs.\n" - "Customize the Network Selection Function.\n" - "Reset the NSF back to regular operation (for testing).\n") -{ - g_cfg->pool.nsf_override = NULL; - return CMD_SUCCESS; -} - -int gbproxy_vty_init(void) -{ - install_element_ve(&show_gbproxy_bvc_cmd); - install_element_ve(&show_gbproxy_cell_cmd); - install_element_ve(&show_gbproxy_links_cmd); - install_element_ve(&show_gbproxy_tlli_cache_cmd); - install_element_ve(&show_gbproxy_imsi_cache_cmd); - install_element_ve(&show_nri_all_cmd); - install_element_ve(&show_nri_nsei_cmd); - install_element_ve(&logging_fltr_bvc_cmd); - - install_element(ENABLE_NODE, &delete_gb_bvci_cmd); - install_element(ENABLE_NODE, &delete_gb_nsei_cmd); - install_element(ENABLE_NODE, &sgsn_pool_nsf_fixed_cmd); - install_element(ENABLE_NODE, &sgsn_pool_nsf_normal_cmd); - - install_element(CONFIG_NODE, &cfg_gbproxy_cmd); - install_node(&gbproxy_node, config_write_gbproxy); - install_element(GBPROXY_NODE, &cfg_pool_bvc_fc_ratio_cmd); - install_element(GBPROXY_NODE, &cfg_gbproxy_nri_bitlen_cmd); - install_element(GBPROXY_NODE, &cfg_gbproxy_nri_null_add_cmd); - install_element(GBPROXY_NODE, &cfg_gbproxy_nri_null_del_cmd); - - install_element(CONFIG_NODE, &cfg_sgsn_nsei_cmd); - install_node(&sgsn_node, config_write_sgsn); - install_element(SGSN_NODE, &cfg_sgsn_name_cmd); - install_element(SGSN_NODE, &cfg_sgsn_allow_attach_cmd); - install_element(SGSN_NODE, &cfg_sgsn_no_allow_attach_cmd); - install_element(SGSN_NODE, &cfg_sgsn_nri_add_cmd); - install_element(SGSN_NODE, &cfg_sgsn_nri_del_cmd); - - - return 0; -} - -int gbproxy_parse_config(const char *config_file, struct gbproxy_config *cfg) -{ - int rc; - - g_cfg = cfg; - rc = vty_read_config_file(config_file, NULL); - if (rc < 0) { - fprintf(stderr, "Failed to parse the config file: '%s'\n", config_file); - return rc; - } - - return 0; -} diff --git a/tests/Makefile.am b/tests/Makefile.am index 32ed47258..cb6d343b5 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -33,8 +33,6 @@ EXTRA_DIST = \ vty_test_runner.py \ ctrl_test_runner.py \ osmo-sgsn_test-nodes.vty \ - osmo-gbproxy_test-nodes.vty \ - osmo-gbproxy-pool_test-nodes.vty \ $(NULL) TESTSUITE = $(srcdir)/testsuite @@ -63,14 +61,6 @@ vty-python-test: $(BUILT_SOURCES) # make vty-transcript-test U=-u vty-transcript-test: osmo_verify_transcript_vty.py -v \ - -n OsmoGbProxy -p 4246 \ - -r "$(top_builddir)/src/gbproxy/osmo-gbproxy -c $(top_srcdir)/doc/examples/osmo-gbproxy/osmo-gbproxy.cfg" \ - $(U) $${T:-$(srcdir)/osmo-gbproxy_test-nodes.vty} - osmo_verify_transcript_vty.py -v \ - -n OsmoGbProxy -p 4246 \ - -r "$(top_builddir)/src/gbproxy/osmo-gbproxy -c $(top_srcdir)/doc/examples/osmo-gbproxy/osmo-gbproxy-pool.cfg" \ - $(U) $${T:-$(srcdir)/osmo-gbproxy-pool_test-nodes.vty} - osmo_verify_transcript_vty.py -v \ -n OsmoSGSN -p 4245 \ -r "$(top_builddir)/src/sgsn/osmo-sgsn -c $(top_srcdir)/doc/examples/osmo-sgsn/osmo-sgsn.cfg" \ $(U) $${T:-$(srcdir)/osmo-sgsn*.vty} diff --git a/tests/osmo-gbproxy-pool_test-nodes.vty b/tests/osmo-gbproxy-pool_test-nodes.vty deleted file mode 100644 index a741e483e..000000000 --- a/tests/osmo-gbproxy-pool_test-nodes.vty +++ /dev/null @@ -1,35 +0,0 @@ -OsmoGbProxy> enable -OsmoGbProxy# show nri all -sgsn nsei 101 - nri add 1 - nri add 11 -sgsn nsei 102 - nri add 2 - nri add 12 -OsmoGbProxy# configure terminal -OsmoGbProxy(config)# list -... - gbproxy - sgsn nsei <0-65534> - ns -... - -OsmoGbProxy(config)# sgsn nsei 101 -OsmoGbProxy(config-sgsn)# list -... - allow-attach - no allow-attach - nri add <0-32767> [<0-32767>] - nri del <0-32767> [<0-32767>] -... - -OsmoGbProxy(config-sgsn)# exit -OsmoGbProxy(config)# gbproxy - -OsmoGbProxy(config-gbproxy)# list -... - pool bvc-flow-control-ratio <1-100> - nri bitlen <0-15> - nri null add <0-32767> [<0-32767>] - nri null del <0-32767> [<0-32767>] -... diff --git a/tests/osmo-gbproxy_test-nodes.vty b/tests/osmo-gbproxy_test-nodes.vty deleted file mode 100644 index 8a47aa075..000000000 --- a/tests/osmo-gbproxy_test-nodes.vty +++ /dev/null @@ -1,32 +0,0 @@ -OsmoGbProxy> enable -OsmoGbProxy# show nri all -sgsn nsei 101 - % no NRI mappings -... -OsmoGbProxy# configure terminal -OsmoGbProxy(config)# list -... - gbproxy - sgsn nsei <0-65534> - ns -... - -OsmoGbProxy(config)# sgsn nsei 101 -OsmoGbProxy(config-sgsn)# list -... - allow-attach - no allow-attach - nri add <0-32767> [<0-32767>] - nri del <0-32767> [<0-32767>] -... - -OsmoGbProxy(config-sgsn)# exit -OsmoGbProxy(config)# gbproxy - -OsmoGbProxy(config-gbproxy)# list -... - pool bvc-flow-control-ratio <1-100> - nri bitlen <0-15> - nri null add <0-32767> [<0-32767>] - nri null del <0-32767> [<0-32767>] -... diff --git a/tests/vty_test_runner.py b/tests/vty_test_runner.py index 92466bb04..0b7df8c89 100755 --- a/tests/vty_test_runner.py +++ b/tests/vty_test_runner.py @@ -67,53 +67,6 @@ class TestVTYBase(unittest.TestCase): self.vty = None osmoutil.end_proc(self.proc) - -class TestVTYGbproxy(TestVTYBase): - - def vty_command(self): - return ["./src/gbproxy/osmo-gbproxy", "-c", - "doc/examples/osmo-gbproxy/osmo-gbproxy.cfg"] - - def vty_app(self): - return (4246, "./src/gbproxy/osmo-gbproxy", "OsmoGbProxy", "gbproxy") - - def testVtyTree(self): - self.vty.enable() - self.assertTrue(self.vty.verify('configure terminal', [''])) - self.assertEqual(self.vty.node(), 'config') - self.checkForEndAndExit() - self.assertTrue(self.vty.verify('ns', [''])) - self.assertEqual(self.vty.node(), 'config-ns') - self.checkForEndAndExit() - self.assertTrue(self.vty.verify('exit', [''])) - self.assertEqual(self.vty.node(), 'config') - self.assertTrue(self.vty.verify('gbproxy', [''])) - self.assertEqual(self.vty.node(), 'config-gbproxy') - self.checkForEndAndExit() - self.assertTrue(self.vty.verify('exit', [''])) - self.assertEqual(self.vty.node(), 'config') - - def testVtyShow(self): - res = self.vty.command("show ns") - self.assertTrue(res.find('UDP bind') >= 0) - - res = self.vty.command("show gbproxy bvc bss stats") - self.assertTrue(res.find('GBProxy Global Statistics') >= 0) - - def testVtyDeletePeer(self): - self.vty.enable() - self.assertTrue(self.vty.verify('delete-gbproxy-peer 9999 bvci 7777', ['NSE not found'])) - res = self.vty.command("delete-gbproxy-peer 9999 all dry-run") - self.assertTrue(res.find('Not Deleted 0 BVC') >= 0) - self.assertTrue(res.find('NSEI not found') >= 0) - res = self.vty.command("delete-gbproxy-peer 9999 only-bvc dry-run") - self.assertTrue(res.find('Not Deleted 0 BVC') >= 0) - res = self.vty.command("delete-gbproxy-peer 9999 only-nsvc dry-run") - self.assertTrue(res.find('NSEI not found') >= 0) - res = self.vty.command("delete-gbproxy-peer 9999 all") - self.assertTrue(res.find('Deleted 0 BVC') >= 0) - self.assertTrue(res.find('NSEI not found') >= 0) - class TestVTYSGSN(TestVTYBase): def vty_command(self): @@ -274,13 +227,6 @@ class TestVTYSGSN(TestVTYBase): for t in [3312, 3322, 3350, 3360, 3370, 3313, 3314, 3316, 3385, 3395, 3397]: self.assertTrue(self.vty.verify('timer t%d 10' % t, [''])) -def add_gbproxy_test(suite, workdir): - if not os.path.isfile(os.path.join(workdir, "src/gbproxy/osmo-gbproxy")): - print("Skipping the Gb-Proxy test") - return - test = unittest.TestLoader().loadTestsFromTestCase(TestVTYGbproxy) - suite.addTest(test) - def add_sgsn_test(suite, workdir): if not os.path.isfile(os.path.join(workdir, "src/sgsn/osmo-sgsn")): print("Skipping the SGSN test") @@ -318,7 +264,6 @@ if __name__ == '__main__': os.chdir(workdir) print("Running tests for specific VTY commands") suite = unittest.TestSuite() - add_gbproxy_test(suite, workdir) add_sgsn_test(suite, workdir) if args.test_name: |