fixeria has uploaded this change for review. ( https://gerrit.osmocom.org/c/erlang/osmo-s1gw/+/42366?usp=email )
Change subject: doc/manuals: document GTP-U KPI monitoring
......................................................................
doc/manuals: document GTP-U KPI monitoring
Change-Id: I2709cd545bfd6c8f6e34358caf9d372c02dd5c3e
Related: OS#6671
---
M doc/manuals/chapters/configuration.adoc
A doc/manuals/chapters/gtpu_kpi.adoc
M doc/manuals/osmo-s1gw-usermanual.adoc
3 files changed, 113 insertions(+), 2 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/erlang/osmo-s1gw refs/changes/66/42366/1
diff --git a/doc/manuals/chapters/configuration.adoc b/doc/manuals/chapters/configuration.adoc
index 8bd7eea..dc738a4 100644
--- a/doc/manuals/chapters/configuration.adoc
+++ b/doc/manuals/chapters/configuration.adoc
@@ -161,8 +161,8 @@
=== GTP-U KPI Reporting (Optional)
OsmoS1GW can optionally poll nftables counters to derive per-eNB GTP-U
-traffic statistics and report them as exometer metrics. This feature
-requires a matching nftables ruleset.
+traffic statistics and report them as exometer metrics (see <<gtpu_kpi>>).
+This feature requires a matching nftables ruleset.
----
%% {gtpu_kpi_enable, true},
diff --git a/doc/manuals/chapters/gtpu_kpi.adoc b/doc/manuals/chapters/gtpu_kpi.adoc
new file mode 100644
index 0000000..ed43cd1
--- /dev/null
+++ b/doc/manuals/chapters/gtpu_kpi.adoc
@@ -0,0 +1,109 @@
+[[gtpu_kpi]]
+== GTP-U KPI Monitoring
+
+OsmoS1GW includes an optional GTP-U KPI monitoring module that tracks
+per-eNB GTP-U traffic volume. Because OsmoS1GW does not carry GTP-U
+traffic itself (see <<architecture>>), it cannot count packets and bytes
+from the data path directly. Instead, it leverages the Linux
+https://netfilter.org/projects/nftables/[nftables] framework: when an
+eNB connects and its GTP-U transport address becomes known, OsmoS1GW
+dynamically installs nftables rules with named counters to measure the
+traffic for that eNB. The counters are polled at a configurable interval
+and the results are exposed as exometer metrics.
+
+This feature is disabled by default. See <<config_gtpu_kpi>> for the
+configuration parameters.
+
+[[gtpu_kpi_requirements]]
+=== Requirements
+
+* Linux kernel 5.2 or later with nftables support.
+* The `CAP_NET_ADMIN` capability is required to manipulate nftables
+ rules. This is already granted by the installed systemd unit (see
+ <<running_systemd>>).
+
+[[gtpu_kpi_how_it_works]]
+=== How It Works
+
+[[gtpu_kpi_nftables_setup]]
+==== nftables Table and Chains
+
+At startup, the GTP-U KPI module creates a dedicated nftables table (an
+`inet` family table named `osmo-s1gw` by default, configurable via
+`gtpu_kpi_table_name`). The table is marked as process-owned, so the
+kernel automatically removes it if OsmoS1GW terminates unexpectedly. If
+a table with the same name already exists from a previous run, it is
+flushed first.
+
+Inside this table the module creates two base chains:
+
+`gtpu-ul` (hook: `prerouting`)::
+ Counts uplink GTP-U traffic — packets whose source address matches a
+ registered eNB's GTP-U address.
+
+`gtpu-dl` (hook: `postrouting`)::
+ Counts downlink GTP-U traffic — packets whose destination address
+ matches a registered eNB's GTP-U address.
+
+Both chains prepend two rules that fast-skip non-GTP-U packets (i.e.
+anything that is not UDP or whose destination port is not 2152).
+
+[[gtpu_kpi_address_learning]]
+==== GTP-U Address Learning
+
+GTP-U transport addresses are not explicitly configured; they are learned
+at run time from the S1AP signalling exchanged during E-RAB establishment.
+The source of the address used for nftables rule matching is controlled by
+the `gtpu_kpi_ul_addr` and `gtpu_kpi_dl_addr` configuration parameters:
+
+`s1ap` (default)::
+ The GTP-U address is taken from the F-TEID IEs carried in S1AP PDUs
+ (E-RAB Setup, Initial Context Setup, etc.).
+
+`sctp`::
+ The GTP-U address is assumed to be the same as the eNB's SCTP source
+ address. Useful when the GTP-U and S1AP addresses are always the same.
+
+[[gtpu_kpi_per_enb_rules]]
+==== Per-eNB Counter Rules
+
+Once an eNB's GTP-U address is known, the module adds:
+
+* A named nftables counter (`ul-{GlobalENBId}` for uplink,
+ `dl-{GlobalENBId}` for downlink).
+* A rule in the appropriate chain that matches packets by source (UL) or
+ destination (DL) IP address and updates the corresponding counter.
+
+When an eNB disconnects, the matching nftables rule is removed, but the
+counter object is intentionally left in place. This means counters
+accumulate across reconnections of the same eNB and do not reset to zero
+if the eNB briefly drops and re-establishes its connection.
+
+[[gtpu_kpi_polling]]
+==== Counter Polling and Metric Reporting
+
+A periodic timer (interval configurable via `gtpu_kpi_interval`, default
+3000 ms) fires and reads all named counters from the nftables table. For
+each registered eNB the difference since the last poll is computed and
+added to the corresponding exometer counters.
+
+Three metrics are maintained per eNB per direction (see also
+<<metrics_per_enb_counters>>):
+
+`enb.{id}.gtpu.packets.{ul|dl}`::
+ Total number of GTP-U packets seen for this eNB.
+
+`enb.{id}.gtpu.bytes.total.{ul|dl}`::
+ Total bytes seen for this eNB, including the outer IP, UDP, and GTP-U
+ headers (i.e. what nftables reports).
+
+`enb.{id}.gtpu.bytes.ue.{ul|dl}`::
+ Estimated UE payload bytes — total bytes minus the fixed overhead of
+ the outer IP header (20 bytes), UDP header (8 bytes), and GTP-U header
+ (8 bytes), i.e. 36 bytes per packet.
+
+NOTE: The UE payload byte estimate assumes a fixed 20-byte IP header.
+ IPv6 or IP options would result in a slight overcount in the
+ overhead subtraction.
+
+// vim:set ts=4 sw=4 et:
diff --git a/doc/manuals/osmo-s1gw-usermanual.adoc b/doc/manuals/osmo-s1gw-usermanual.adoc
index 7c97192..2427d31 100644
--- a/doc/manuals/osmo-s1gw-usermanual.adoc
+++ b/doc/manuals/osmo-s1gw-usermanual.adoc
@@ -17,6 +17,8 @@
include::{srcdir}/chapters/metrics.adoc[]
+include::{srcdir}/chapters/gtpu_kpi.adoc[]
+
include::{commondir}/chapters/glossary.adoc[]
include::{commondir}/chapters/bibliography.adoc[]
--
To view, visit https://gerrit.osmocom.org/c/erlang/osmo-s1gw/+/42366?usp=email
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: newchange
Gerrit-Project: erlang/osmo-s1gw
Gerrit-Branch: master
Gerrit-Change-Id: I2709cd545bfd6c8f6e34358caf9d372c02dd5c3e
Gerrit-Change-Number: 42366
Gerrit-PatchSet: 1
Gerrit-Owner: fixeria <vyanitskiy(a)sysmocom.de>
fixeria has uploaded this change for review. ( https://gerrit.osmocom.org/c/erlang/osmo-s1gw/+/42365?usp=email )
Change subject: doc/manuals: document the metrics
......................................................................
doc/manuals: document the metrics
Change-Id: Iacfefd387d0cd26eebbbeba0cd37efa78f90bb46
Related: OS#6671
---
M doc/manuals/chapters/configuration.adoc
A doc/manuals/chapters/metrics.adoc
M doc/manuals/osmo-s1gw-usermanual.adoc
3 files changed, 190 insertions(+), 3 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/erlang/osmo-s1gw refs/changes/65/42365/1
diff --git a/doc/manuals/chapters/configuration.adoc b/doc/manuals/chapters/configuration.adoc
index 53e23e5..8bd7eea 100644
--- a/doc/manuals/chapters/configuration.adoc
+++ b/doc/manuals/chapters/configuration.adoc
@@ -256,9 +256,10 @@
=== `exometer_core` — Metrics and StatsD Reporting
OsmoS1GW uses the https://github.com/Feuerlabs/exometer_core[exometer_core]
-library for internal metrics (counters and gauges). The `exometer_core`
-section configures reporters — processes that periodically push metric
-values to an external destination.
+library for internal metrics (counters and gauges); see <<metrics>> for the
+full list of available metrics. The `exometer_core` section configures
+reporters — processes that periodically push metric values to an external
+destination.
The default configuration reports all counters and gauges to a StatsD
server:
diff --git a/doc/manuals/chapters/metrics.adoc b/doc/manuals/chapters/metrics.adoc
new file mode 100644
index 0000000..5b81227
--- /dev/null
+++ b/doc/manuals/chapters/metrics.adoc
@@ -0,0 +1,184 @@
+[[metrics]]
+== Metrics
+
+OsmoS1GW exposes internal metrics using the
+https://github.com/Feuerlabs/exometer_core[exometer_core] library. Two
+metric types are used:
+
+Counter:: A monotonically increasing integer, incremented each time a
+ specific event occurs. Counters never decrease.
+
+Gauge:: An integer that reflects a current quantity (e.g. the number of
+ active connections). Gauges can go up and down.
+
+[[metrics_naming]]
+=== Metric Names
+
+Internally, each metric is identified by an Erlang list such as
+`[ctr, pfcp, heartbeat_req, tx]`. When reported externally — via StatsD
+(see <<config_exometer>>) or the REST API (see <<rest_metrics>>) — the
+list elements are joined with dots and the leading type element (`ctr` or
+`gauge`) is dropped. For example:
+
+* `[ctr, pfcp, heartbeat_req, tx]` → `pfcp.heartbeat_req.tx`
+* `[gauge, pfcp, associated]` → `pfcp.associated`
+
+When StatsD reporting is enabled, all metric names are further prefixed
+with the configured `prefix` string (default: `s1gw`), giving e.g.
+`s1gw.pfcp.heartbeat_req.tx`.
+
+[[metrics_global_counters]]
+=== Global Counters
+
+The following counters are registered at startup and count events across
+all connections.
+
+[[metrics_pfcp_counters]]
+==== PFCP Counters
+
+[options="header",cols="45,55"]
+|===
+| Metric name | Description
+| `pfcp.heartbeat_req.tx` | PFCP Heartbeat Requests sent to the UPF
+| `pfcp.heartbeat_req.rx` | PFCP Heartbeat Requests received from the UPF
+| `pfcp.heartbeat_req.timeout` | PFCP Heartbeat Requests that timed out
+| `pfcp.heartbeat_resp.tx` | PFCP Heartbeat Responses sent to the UPF
+| `pfcp.heartbeat_resp.rx` | PFCP Heartbeat Responses received from the UPF
+| `pfcp.assoc_setup_req.tx` | PFCP Association Setup Requests sent
+| `pfcp.assoc_setup_req.timeout` | PFCP Association Setup Requests that timed out
+| `pfcp.assoc_setup_resp.rx` | PFCP Association Setup Responses received
+| `pfcp.assoc_setup_resp.rx_ack` | PFCP Association Setup Responses with success cause
+| `pfcp.assoc_setup_resp.rx_nack` | PFCP Association Setup Responses with failure cause
+| `pfcp.unexpected_pdu` | Unexpected or unrecognised PFCP PDUs received
+|===
+
+[[metrics_s1ap_counters]]
+==== S1AP Counters
+
+[options="header",cols="55,45"]
+|===
+| Metric name | Description
+| `s1ap.enb.all.rx` | S1AP PDUs received from any eNB
+| `s1ap.enb.all.rx_unknown_enb` | S1AP PDUs received from an unregistered eNB
+| `s1ap.proxy.exception` | Exceptions raised during S1AP PDU processing
+| `s1ap.proxy.in_pkt.all` | S1AP PDUs entering the proxy (all directions)
+| `s1ap.proxy.in_pkt.drop.all` | S1AP PDUs dropped by the proxy
+| `s1ap.proxy.in_pkt.decode_error` | S1AP PDUs that failed to decode
+| `s1ap.proxy.in_pkt.proc_error` | S1AP PDUs that failed to process
+| `s1ap.proxy.in_pkt.erab_setup_req` | E-RAB SETUP REQUEST PDUs
+| `s1ap.proxy.in_pkt.erab_setup_rsp` | E-RAB SETUP RESPONSE PDUs
+| `s1ap.proxy.in_pkt.erab_modify_req` | E-RAB MODIFY REQUEST PDUs
+| `s1ap.proxy.in_pkt.erab_modify_rsp` | E-RAB MODIFY RESPONSE PDUs
+| `s1ap.proxy.in_pkt.erab_release_cmd` | E-RAB RELEASE COMMAND PDUs
+| `s1ap.proxy.in_pkt.erab_release_rsp` | E-RAB RELEASE RESPONSE PDUs
+| `s1ap.proxy.in_pkt.erab_release_ind` | E-RAB RELEASE INDICATION PDUs
+| `s1ap.proxy.in_pkt.erab_mod_ind` | E-RAB MODIFICATION INDICATION PDUs
+| `s1ap.proxy.in_pkt.erab_mod_cnf` | E-RAB MODIFICATION CONFIRM PDUs
+| `s1ap.proxy.in_pkt.init_ctx_req` | INITIAL CONTEXT SETUP REQUEST PDUs
+| `s1ap.proxy.in_pkt.init_ctx_rsp` | INITIAL CONTEXT SETUP RESPONSE PDUs
+| `s1ap.proxy.in_pkt.release_ctx_req` | UE CONTEXT RELEASE REQUEST PDUs
+| `s1ap.proxy.in_pkt.release_ctx_cmd` | UE CONTEXT RELEASE COMMAND PDUs
+| `s1ap.proxy.in_pkt.release_ctx_compl` | UE CONTEXT RELEASE COMPLETE PDUs
+| `s1ap.proxy.in_pkt.handover_cmd` | HANDOVER COMMAND PDUs
+| `s1ap.proxy.in_pkt.handover_req` | HANDOVER REQUEST PDUs
+| `s1ap.proxy.in_pkt.handover_req_ack` | HANDOVER REQUEST ACKNOWLEDGE PDUs
+| `s1ap.proxy.out_pkt.forward.all` | S1AP PDUs forwarded (total)
+| `s1ap.proxy.out_pkt.forward.proc` | S1AP PDUs forwarded after processing (with IE rewriting)
+| `s1ap.proxy.out_pkt.forward.unmodified` | S1AP PDUs forwarded without modification
+| `s1ap.proxy.out_pkt.reply.all` | S1AP PDUs generated locally by the proxy (total)
+| `s1ap.proxy.out_pkt.reply.erab_setup_rsp` | E-RAB SETUP RESPONSE PDUs generated locally
+|===
+
+[[metrics_enb_proxy_counters]]
+==== eNB Proxy Counters
+
+[options="header",cols="45,55"]
+|===
+| Metric name | Description
+| `enb_proxy.s1setup.req` | S1 SETUP REQUEST PDUs received from eNBs
+| `enb_proxy.s1setup.rsp` | S1 SETUP RESPONSE PDUs received from the MME and forwarded
+| `enb_proxy.s1setup.failure` | S1 SETUP FAILURE PDUs received from an MME (triggers retry)
+| `enb_proxy.s1setup.req.timeout` | Timeouts waiting for S1 SETUP REQUEST from an eNB
+| `enb_proxy.s1setup.rsp.timeout` | Timeouts waiting for S1 SETUP RESPONSE from an MME
+| `enb_proxy.conn_est.timeout` | MME SCTP connection establishment timeouts
+| `enb_proxy.conn_est.failure` | MME SCTP connection establishment failures
+| `enb_proxy.unexpected_pdu` | Unexpected PDUs received from an eNB or MME
+| `enb_proxy.malformed_pdu` | Malformed PDUs received from an eNB or MME
+| `enb_proxy.mme_select.ok` | Successful MME selections from the pool
+| `enb_proxy.mme_select.error` | Failed MME selections (pool exhausted)
+|===
+
+[[metrics_sctp_counters]]
+==== SCTP Error Counters
+
+[options="header",cols="40,60"]
+|===
+| Metric name | Description
+| `sctp.error.all` | Total number of SCTP errors
+| `sctp.error.send_failed` | SCTP send operation failures
+| `sctp.error.pdapi_event` | SCTP partial delivery API failures
+| `sctp.error.remote_error` | SCTP remote error notifications
+|===
+
+[[metrics_per_enb_counters]]
+=== Per-eNB Counters
+
+When an eNB connects and its Global-eNB-ID becomes known (after the S1
+Setup procedure), OsmoS1GW dynamically creates a set of per-eNB counters
+scoped to that eNB. These counters mirror the global eNB proxy counters
+but are broken down per connected base station.
+
+The naming scheme for per-eNB counters is
+`enb.{Global-eNB-ID}.{suffix}`, where `{Global-eNB-ID}` is the
+MCC-MNC-eNBId string (e.g. `001-01-1337`).
+
+In addition to the mirrored proxy counters, the following per-eNB
+counters are also registered:
+
+[options="header",cols="50,50"]
+|===
+| Metric name | Description
+| `enb.{id}.uptime` | Time (in seconds) since the eNB connected
+| `enb.{id}.gtpu.packets.ul` | GTP-U uplink packets (requires GTP-U KPI)
+| `enb.{id}.gtpu.packets.dl` | GTP-U downlink packets (requires GTP-U KPI)
+| `enb.{id}.gtpu.bytes.ue.ul` | GTP-U uplink bytes (UE side, requires GTP-U KPI)
+| `enb.{id}.gtpu.bytes.ue.dl` | GTP-U downlink bytes (UE side, requires GTP-U KPI)
+| `enb.{id}.gtpu.bytes.total.ul` | GTP-U uplink bytes (total, requires GTP-U KPI)
+| `enb.{id}.gtpu.bytes.total.dl` | GTP-U downlink bytes (total, requires GTP-U KPI)
+|===
+
+GTP-U counters are only populated when the GTP-U KPI module is enabled
+(see <<config_gtpu_kpi>>).
+
+[[metrics_per_mme_counters]]
+=== Per-MME Counters
+
+When an MME is registered in the pool — either at startup from the
+configuration file (see <<config_mme_pool>>) or dynamically via the REST
+API — OsmoS1GW creates a set of per-MME counters scoped to that MME entry.
+
+The naming scheme is `mme.{name}.{suffix}`, where `{name}` is the MME's
+configured name (e.g. `mme0`).
+
+[options="header",cols="45,55"]
+|===
+| Metric name | Description
+| `mme.{name}.selected` | Number of times this MME was selected for a connection attempt
+| `mme.{name}.conn_est.timeout` | Connection establishment timeouts to this MME
+| `mme.{name}.conn_est.failure` | Connection establishment failures to this MME
+| `mme.{name}.s1setup.rsp` | Successful S1 Setup procedures completed via this MME
+| `mme.{name}.s1setup.failure` | S1 SETUP FAILURE responses received from this MME
+| `mme.{name}.s1setup.rsp.timeout` | Timeouts waiting for S1 SETUP RESPONSE from this MME
+|===
+
+[[metrics_gauges]]
+=== Gauges
+
+[options="header",cols="45,55"]
+|===
+| Metric name | Description
+| `pfcp.associated` | `1` if the PFCP association with the UPF is currently established, `0` otherwise
+| `s1ap.enb.num_sctp_connections` | Current number of active eNB SCTP connections
+|===
+
+// vim:set ts=4 sw=4 et:
diff --git a/doc/manuals/osmo-s1gw-usermanual.adoc b/doc/manuals/osmo-s1gw-usermanual.adoc
index 13dcd4b..7c97192 100644
--- a/doc/manuals/osmo-s1gw-usermanual.adoc
+++ b/doc/manuals/osmo-s1gw-usermanual.adoc
@@ -15,6 +15,8 @@
include::{srcdir}/chapters/configuration.adoc[]
+include::{srcdir}/chapters/metrics.adoc[]
+
include::{commondir}/chapters/glossary.adoc[]
include::{commondir}/chapters/bibliography.adoc[]
--
To view, visit https://gerrit.osmocom.org/c/erlang/osmo-s1gw/+/42365?usp=email
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: newchange
Gerrit-Project: erlang/osmo-s1gw
Gerrit-Branch: master
Gerrit-Change-Id: Iacfefd387d0cd26eebbbeba0cd37efa78f90bb46
Gerrit-Change-Number: 42365
Gerrit-PatchSet: 1
Gerrit-Owner: fixeria <vyanitskiy(a)sysmocom.de>
fixeria has uploaded this change for review. ( https://gerrit.osmocom.org/c/erlang/osmo-s1gw/+/42367?usp=email )
Change subject: doc/manuals: document the REST interface
......................................................................
doc/manuals: document the REST interface
Change-Id: I8bc9183fff8f65db71554ee26369db9bdb61b78a
Related: OS#6671
---
M doc/manuals/chapters/metrics.adoc
M doc/manuals/chapters/overview.adoc
A doc/manuals/chapters/rest.adoc
M doc/manuals/osmo-s1gw-usermanual.adoc
4 files changed, 338 insertions(+), 3 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/erlang/osmo-s1gw refs/changes/67/42367/1
diff --git a/doc/manuals/chapters/metrics.adoc b/doc/manuals/chapters/metrics.adoc
index 5b81227..963e303 100644
--- a/doc/manuals/chapters/metrics.adoc
+++ b/doc/manuals/chapters/metrics.adoc
@@ -155,7 +155,8 @@
When an MME is registered in the pool — either at startup from the
configuration file (see <<config_mme_pool>>) or dynamically via the REST
-API — OsmoS1GW creates a set of per-MME counters scoped to that MME entry.
+API (see <<rest_mme>>) — OsmoS1GW creates a set of per-MME counters
+scoped to that MME entry.
The naming scheme is `mme.{name}.{suffix}`, where `{name}` is the MME's
configured name (e.g. `mme0`).
diff --git a/doc/manuals/chapters/overview.adoc b/doc/manuals/chapters/overview.adoc
index d8248ca..d91b466 100644
--- a/doc/manuals/chapters/overview.adoc
+++ b/doc/manuals/chapters/overview.adoc
@@ -63,9 +63,9 @@
provisioned statically via the configuration file or dynamically via
the REST API.
* *`enb_registry`* — Tracks all active eNB connections and their state.
- Queryable via the REST API.
+ Queryable via the REST API (see <<rest_enb>>).
* *`rest_server`* — OpenAPI-based HTTP REST interface for monitoring and
- management.
+ management (see <<rest>>).
[[use_cases]]
=== Use Cases
diff --git a/doc/manuals/chapters/rest.adoc b/doc/manuals/chapters/rest.adoc
new file mode 100644
index 0000000..e1fb324
--- /dev/null
+++ b/doc/manuals/chapters/rest.adoc
@@ -0,0 +1,332 @@
+[[rest]]
+== REST Interface
+
+OsmoS1GW exposes an HTTP REST API for monitoring and management. The
+API follows the OpenAPI 3.0 specification; the full machine-readable spec
+is served at `GET /openapi.json`. A Swagger UI is available at
+`/swagger` when enabled (see <<config_rest>>).
+
+By default the REST server listens on port `8080`. No authentication is
+implemented; access control should be enforced at the network level if
+required.
+
+[[rest_identifiers]]
+=== Resource Identifiers
+
+Several endpoints accept a resource identifier in the URL path that can
+be expressed in multiple forms:
+
+[[rest_mme_id]]
+==== MME Identifier (`{MmeId}`)
+
+[options="header",cols="25,35,40"]
+|===
+| Form | Pattern | Example
+| Name | `name:<name>` | `name:mme0`
+| Address/port | `addr:<ip>-<port>` | `addr:192.168.1.1-36412`
+|===
+
+[[rest_enb_id]]
+==== eNB Identifier (`{EnbId}`)
+
+[options="header",cols="25,35,40"]
+|===
+| Form | Pattern | Example
+| Registry handle | `handle:<n>` | `handle:42`
+| Process ID | `pid:<x>.<y>.<z>` | `pid:0.33.1`
+| Global-eNB-ID | `genbid:<mcc>-<mnc>-<id>` | `genbid:999-70-1337`
+| eNB SCTP assoc ID | `enb-sctp-aid:<n>` | `enb-sctp-aid:42`
+| MME SCTP assoc ID | `mme-sctp-aid:<n>` | `mme-sctp-aid:42`
+| eNB connection addr | `enb-conn:<ip>-<port>` | `enb-conn:192.168.1.1-34650`
+|===
+
+[[rest_erab_id]]
+==== E-RAB Identifier (`{ErabId}`)
+
+[options="header",cols="25,35,40"]
+|===
+| Form | Pattern | Example
+| Process ID | `pid:<x>.<y>.<z>` | `pid:0.33.1`
+|===
+
+[[rest_metrics]]
+=== Metrics
+
+[[rest_metrics_list]]
+==== `GET /metrics-list` — List Metrics
+
+Returns a list of all matching metrics with their current values.
+
+Query parameters:
+
+`type`::
+ Filter by metric type. One of `all` (default), `counter`, or `gauge`.
+
+`path`::
+ Filter by metric name prefix (dot-separated). For example, `s1ap.proxy`
+ returns all metrics whose name starts with `s1ap.proxy`.
+
+Response (HTTP 200):
+
+----
+[
+ {"type": "counter", "name": "pfcp.heartbeat_req.tx", "value": 42},
+ {"type": "counter", "name": "pfcp.heartbeat_req.timeout", "value": 0},
+ {"type": "gauge", "name": "pfcp.associated", "value": 1}
+]
+----
+
+Returns HTTP 404 if no metrics match the given filter.
+
+See <<metrics>> for the full list of metric names.
+
+[[rest_pfcp]]
+=== PFCP
+
+[[rest_pfcp_assoc]]
+==== `GET /pfcp/assoc` — PFCP Association State
+
+Returns the current PFCP association state between OsmoS1GW and the UPF.
+
+Response (HTTP 200):
+
+----
+{
+ "state": "connected",
+ "laddr": "127.0.1.1",
+ "raddr": "127.0.1.2",
+ "lrts": 3967211233,
+ "rrts": 3965211123
+}
+----
+
+`state`:: Current association state: `connecting` or `connected`.
+`laddr`:: Local PFCP bind address.
+`raddr`:: Remote UPF address.
+`lrts`:: Local Recovery Timestamp.
+`rrts`:: Remote Recovery Timestamp (present only when associated).
+
+==== `POST /pfcp/assoc` — Initiate PFCP Association Setup
+
+Triggers an immediate PFCP Association Setup Request to the UPF.
+Returns an `OperationResult` object indicating success or failure.
+
+==== `DELETE /pfcp/assoc` — Release PFCP Association
+
+Initiates a PFCP Association Release procedure.
+Returns an `OperationResult` object.
+
+==== `POST /pfcp/heartbeat` — Send PFCP Heartbeat
+
+Sends a PFCP Heartbeat Request to the UPF and waits for the response.
+Returns an `OperationResult` object.
+
+[[rest_mme]]
+=== MME Pool
+
+[[rest_mme_list]]
+==== `GET /mme-list` — List MMEs
+
+Returns the current contents of the MME pool.
+
+Response (HTTP 200):
+
+----
+[
+ {"name": "mme0", "laddr": "::", "raddr": "192.168.2.10", "rport": 36412, "tac_list": []},
+ {"name": "mme1", "laddr": "::", "raddr": "192.168.2.20", "rport": 36412, "tac_list": [100, 101]}
+]
+----
+
+[[rest_mme_add]]
+==== `POST /mme-list` — Add MME
+
+Adds a new MME to the pool. The request body is a JSON object with the
+same fields as the entries returned by `GET /mme-list`:
+
+`name` (required):: Unique human-readable name.
+`raddr` (required):: Remote IP address of the MME.
+`laddr` (optional):: Local bind address. Default: `"::"` (any).
+`rport` (optional):: Remote SCTP port. Default: `36412`.
+`tac_list` (optional):: List of TACs this MME serves. Default: `[]` (all).
+
+Returns HTTP 201 on success, HTTP 409 if the name or address is already
+registered.
+
+[[rest_mme_info]]
+==== `GET /mme/{MmeId}` — MME Info
+
+Returns configuration details for a single MME. The response format is
+the same as a single element from `GET /mme-list`.
+
+Returns HTTP 404 if no matching MME is found.
+
+[[rest_mme_delete]]
+==== `DELETE /mme/{MmeId}` — Delete MME
+
+Removes an MME from the pool. Active connections to this MME are not
+affected; the change only prevents the MME from being selected for future
+connection attempts.
+
+Returns HTTP 200 on success, HTTP 404 if no matching MME is found.
+
+[[rest_enb]]
+=== eNB Connections
+
+[[rest_enb_list]]
+==== `GET /enb-list` — List eNB Connections
+
+Returns a list of all currently connected eNBs.
+
+Response (HTTP 200):
+
+----
+[
+ {
+ "handle": 0,
+ "pid": "<0.699.0>",
+ "genb_id": "001-01-0",
+ "state": "connected",
+ "enb_saddr": "192.168.1.10",
+ "enb_sport": 56767,
+ "enb_sctp_aid": 5706,
+ "mme_daddr": "192.168.2.10",
+ "mme_dport": 36412,
+ "mme_sport": 34500,
+ "mme_sctp_aid": 5707,
+ "uptime": 418,
+ "erab_count": 3
+ }
+]
+----
+
+`handle`:: Unique integer identifier within the eNB registry.
+`pid`:: Erlang process ID of the `enb_proxy` process.
+`genb_id`:: Global-eNB-ID in MCC-MNC-eNBId format. Present once the S1
+ Setup procedure has completed.
+`state`:: Current proxy state: `wait_s1setup_req`, `connecting`,
+ `wait_s1setup_rsp`, or `connected`.
+`enb_saddr` / `enb_sport`:: Source address and port of the eNB's SCTP connection.
+`enb_sctp_aid`:: SCTP association ID of the eNB-S1GW connection.
+`mme_daddr` / `mme_dport`:: Destination address and port of the MME.
+`mme_sport`:: Local source port of the S1GW-MME SCTP connection.
+`mme_sctp_aid`:: SCTP association ID of the S1GW-MME connection.
+`uptime`:: Seconds since the eNB connected.
+`erab_count`:: Number of currently active E-RABs for this eNB.
+
+==== `GET /enb/{EnbId}` — eNB Info
+
+Returns details for a single eNB. The response format is the same as a
+single element from `GET /enb-list`.
+
+Returns HTTP 404 if no matching eNB is found.
+
+==== `DELETE /enb/{EnbId}` — Force Disconnect eNB
+
+Forcibly terminates the SCTP connection to the specified eNB. This
+causes the eNB to reconnect and restart the S1 Setup procedure.
+
+Returns HTTP 200 on success, HTTP 404 if no matching eNB is found.
+
+[[rest_erab]]
+=== E-RAB Bearers
+
+==== `GET /erab-list` — List All E-RABs
+
+Returns a list of all active E-RABs across all connected eNBs.
+
+==== `GET /enb/{EnbId}/erab-list` — List E-RABs for an eNB
+
+Returns all active E-RABs for a specific eNB.
+
+Returns HTTP 404 if no matching eNB is found.
+
+The response for both list endpoints is an array of E-RAB objects (same
+format as `GET /erab/{ErabId}`).
+
+==== `GET /erab/{ErabId}` — E-RAB Info
+
+Returns details for a single E-RAB.
+
+Response (HTTP 200):
+
+----
+{
+ "pid": "<0.714.0>",
+ "mme_ue_id": 4242,
+ "erab_id": 1,
+ "state": "erab_setup",
+ "pfcp_lseid": 2,
+ "pfcp_rseid": 6076548759901618177,
+ "f_teid_u2c": {"teid": 65537, "tla": "127.0.0.1"},
+ "f_teid_c2u": {"teid": 16842753, "tla": "127.0.1.1"},
+ "f_teid_a2u": {"teid": 33686529, "tla": "127.0.2.2"},
+ "f_teid_u2a": {"teid": 131073, "tla": "127.0.0.2"}
+}
+----
+
+`pid`:: Erlang process ID of the `erab_fsm` process.
+`mme_ue_id`:: MME-UE-S1AP-ID.
+`erab_id`:: E-RAB-ID.
+`state`:: Current FSM state.
+`pfcp_lseid` / `pfcp_rseid`:: Local and remote PFCP SEIDs.
+`f_teid_u2c`:: GTP-U F-TEID for UPF → Core direction.
+`f_teid_c2u`:: GTP-U F-TEID for Core → UPF direction.
+`f_teid_a2u`:: GTP-U F-TEID for Access (eNB) → UPF direction.
+`f_teid_u2a`:: GTP-U F-TEID for UPF → Access (eNB) direction.
+
+Each F-TEID object has a `teid` (integer) and a `tla` (Transport Layer
+Address, dotted IP string).
+
+==== `DELETE /erab/{ErabId}` — Terminate E-RAB
+
+Forcibly terminates the `erab_fsm` process for the given E-RAB. This
+triggers PFCP Session Deletion towards the UPF. Use with caution on
+live connections.
+
+Returns HTTP 200 on success, HTTP 404 if no matching E-RAB is found.
+
+[[rest_cli]]
+=== Interactive CLI (`osmo-s1gw-cli`)
+
+`osmo-s1gw-cli` is an interactive command-line shell built on Python's
+https://cmd2.readthedocs.io/[cmd2] library. It provides a convenient
+alternative to issuing raw HTTP requests, with tab-completion, filtering
+(`CMD | grep ...`), and output redirection (`CMD > FILE`).
+
+After installation, the CLI is available as `osmo-s1gw-cli`. It
+communicates with OsmoS1GW via the REST interface.
+
+----
+osmo-s1gw-cli [-h] [-v] [-p PORT] [HOST]
+
+ HOST OsmoS1GW REST host/address (default: localhost)
+ -p REST port (default: 8080)
+ -v Enable verbose/debug logging
+----
+
+Available commands can be listed within the shell using `help -v`, and
+per-command help is available with `help <command>`. The following
+commands are supported:
+
+[options="header",cols="30,70"]
+|===
+| Command | Description
+| `fetch_openapi_spec` | Fetch and display the OpenAPI specification
+| `metrics_list` | List metrics, optionally filtered by type and/or name path
+| `pfcp_assoc_state` | Display the PFCP association state
+| `pfcp_heartbeat` | Send a PFCP Heartbeat Request
+| `mme_list` | List registered MMEs
+| `mme_add` | Add an MME to the pool
+| `mme_info` | Show details for a specific MME
+| `mme_delete` | Remove an MME from the pool
+| `enb_list` | List connected eNBs
+| `enb_info` | Show details for a specific eNB
+| `enb_delete` | Force-disconnect an eNB
+| `enb_erab_list` | List E-RABs for a specific eNB
+| `erab_list` | List all E-RABs across all eNBs
+| `erab_info` | Show details for a specific E-RAB
+| `erab_delete` | Terminate an E-RAB FSM process
+|===
+
+// vim:set ts=4 sw=4 et:
diff --git a/doc/manuals/osmo-s1gw-usermanual.adoc b/doc/manuals/osmo-s1gw-usermanual.adoc
index 2427d31..c565911 100644
--- a/doc/manuals/osmo-s1gw-usermanual.adoc
+++ b/doc/manuals/osmo-s1gw-usermanual.adoc
@@ -19,6 +19,8 @@
include::{srcdir}/chapters/gtpu_kpi.adoc[]
+include::{srcdir}/chapters/rest.adoc[]
+
include::{commondir}/chapters/glossary.adoc[]
include::{commondir}/chapters/bibliography.adoc[]
--
To view, visit https://gerrit.osmocom.org/c/erlang/osmo-s1gw/+/42367?usp=email
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: newchange
Gerrit-Project: erlang/osmo-s1gw
Gerrit-Branch: master
Gerrit-Change-Id: I8bc9183fff8f65db71554ee26369db9bdb61b78a
Gerrit-Change-Number: 42367
Gerrit-PatchSet: 1
Gerrit-Owner: fixeria <vyanitskiy(a)sysmocom.de>
fixeria has uploaded this change for review. ( https://gerrit.osmocom.org/c/erlang/osmo-s1gw/+/42364?usp=email )
Change subject: doc/manuals: add overview, document running and configuration
......................................................................
doc/manuals: add overview, document running and configuration
Change-Id: I4ceca069866d7191ef2b153af95a20cb522bffeb
Related: OS#6671
---
M README.md
A doc/manuals/Makefile
A doc/manuals/chapters/configuration.adoc
A doc/manuals/chapters/overview.adoc
A doc/manuals/chapters/running.adoc
A doc/manuals/osmo-s1gw-usermanual-docinfo.xml
A doc/manuals/osmo-s1gw-usermanual.adoc
7 files changed, 730 insertions(+), 38 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/erlang/osmo-s1gw refs/changes/64/42364/1
diff --git a/README.md b/README.md
index 5ff4589..d6a5299 100644
--- a/README.md
+++ b/README.md
@@ -54,8 +54,10 @@
Documentation
-------------
-Once the project reaches a usable milestone, we will be working on a
-user manual. Stay tuned.
+The user manual source is in [`doc/manuals/`](doc/manuals/). It covers
+installation, configuration, metrics, the REST API, and the interactive CLI.
+A pre-built PDF is published on the
+[Osmocom documentation server](https://ftp.osmocom.org/docs/osmo-s1gw).
Contributing
@@ -113,54 +115,39 @@
Installation
------------
-OsmoS1GW is built for common versions of Debian, Ubuntu and other distributions as a part of
-the [Osmocom binary packages](https://osmocom.org/projects/cellular-infrastructure/wiki/Binary_….
-If you're not doing development, it is suggested to simply use those binary packages, rather
-than building from source. Otherwise, you can invoke the `install` target:
+Osmocom provides binary packages for common Debian and Ubuntu releases via
+the [Osmocom binary package feed](https://osmocom.org/projects/cellular-infrastructure/wiki/Binary_Pack….
+Both a stable feed (tracking the latest release) and a nightly feed are
+available. If you are not doing development, using the binary packages is
+the recommended approach.
+
+To build and install from source:
```
+$ make
$ sudo make install
```
-This will install the following:
+`make install` deploys a complete ERTS release together with a convenience
+wrapper script and the interactive CLI tool:
-* `/usr/lib/osmo-s1gw` - complete OTP release package
-* `/usr/bin/osmo-s1gw` - convenience script for running `osmo-s1gw`
-* `/usr/bin/osmo-s1gw-cli` - interactive CLI for `osmo-s1gw`
-* `/lib/systemd/system/osmo-s1gw.service` - systemd unit file
-* `/etc/osmocom/osmo-s1gw.config` - the configuration file
+* `/usr/lib/osmo-s1gw` — complete OTP/ERTS release package
+* `/usr/bin/osmo-s1gw` — bootstrap script for starting the release
+* `/usr/bin/osmo-s1gw-cli` — interactive CLI tool
+* `/lib/systemd/system/osmo-s1gw.service` — systemd unit file
+* `/etc/osmocom/osmo-s1gw.config` — default configuration file
-The installation paths can be adjusted using `DESTDIR`, `LIBDIR`, `BINDIR`,
-`CONFDIR`, and `SYSTEMDUNITDIR` variables.
+Installation paths can be adjusted with `DESTDIR`, `LIBDIR`, `BINDIR`,
+`CONFDIR`, and `SYSTEMDUNITDIR`. See the user manual for full details.
Configuration
-------------
-The default configuration can be found in
-[config/sys.config](config/sys.config).
-
-The existing parameters can be represented as follows:
-
-```
- eNB S1GW
-+-----+ +----------------+
-| ... | --> | s1gw_bind_addr | MME
-+-----+ +----------------+ +-----------------+
- | mme_loc_addr | --> | mme_rem_addr |
- +----------------+ +-----------------+
-```
-
-* `s1gw_bind_addr` - S1GW bind address for incoming eNB connections
-* `mme_loc_addr` - local address for outgoing connections to the MME
-* `mme_rem_addr` - remote address for outgoing connections to the MME
-
-Logging can be configured in the `kernel` section:
-
-* `{logger_level, info}` - logging level (one of `emergency | alert |
- critical | error | warning | notice |
- info | debug`)
-* `#{formatter => { ... }` - logging formatting configuration
+The default configuration file is [`config/sys.config`](config/sys.config).
+For a full description of all available configuration parameters, see the
+Configuration chapter in the user manual
+([`doc/manuals/chapters/configuration.adoc`](doc/manuals/chapters/configuration.adoc)).
REST interface
diff --git a/doc/manuals/Makefile b/doc/manuals/Makefile
new file mode 100644
index 0000000..b56e51d
--- /dev/null
+++ b/doc/manuals/Makefile
@@ -0,0 +1,16 @@
+OSMO_GSM_MANUALS_DIR ?= $(shell pkg-config osmo-gsm-manuals --variable=osmogsmmanualsdir 2>/dev/null)
+ifeq ($(OSMO_GSM_MANUALS_DIR),)
+$(error "osmo-gsm-manuals not found via pkg-config. Please install it.")
+endif
+
+# Without autotools, srcdir must be set explicitly so that Makefile.asciidoc.inc
+# can resolve {srcdir} in AsciiDoc include directives correctly.
+srcdir ?= $(CURDIR)
+
+ASCIIDOC = osmo-s1gw-usermanual.adoc
+include $(OSMO_GSM_MANUALS_DIR)/build/Makefile.asciidoc.inc
+
+osmo-s1gw-usermanual.pdf: $(wildcard chapters/*.adoc)
+
+OSMO_REPOSITORY = osmo-s1gw
+include $(OSMO_GSM_MANUALS_DIR)/build/Makefile.common.inc
diff --git a/doc/manuals/chapters/configuration.adoc b/doc/manuals/chapters/configuration.adoc
new file mode 100644
index 0000000..53e23e5
--- /dev/null
+++ b/doc/manuals/chapters/configuration.adoc
@@ -0,0 +1,304 @@
+[[configuration]]
+== Configuration
+
+OsmoS1GW is configured through an Erlang/OTP system configuration file.
+By default this file is `config/sys.config` in the source tree, or
+`/etc/osmocom/osmo-s1gw.config` after installation. A different path
+can be supplied at start time via the `-c` option of the `osmo-s1gw`
+bootstrap script (see <<running_bootstrap_script>>) or via the `CONFIG`
+variable when using the project Makefile (see <<running_building_make_targets>>).
+
+The file uses Erlang term syntax. The top level is a list of
+`{ApplicationName, [{Key, Value}, ...]}` tuples. OsmoS1GW-specific
+parameters live under the `osmo_s1gw` application key. Kernel
+parameters (logging) live under the standard `kernel` key, and metrics
+reporting parameters under the `exometer_core` key.
+
+[[config_sctp_server]]
+=== `sctp_server` — eNB-Facing SCTP Listener
+
+This section controls the SCTP socket on which OsmoS1GW listens for
+incoming connections from eNodeBs.
+
+----
+{sctp_server, #{
+ laddr => "127.0.1.1", %% local bind address
+ lport => 36412, %% local bind port (S1AP standard port)
+ sockopts => #{ } %% optional socket options (see below)
+}}
+----
+
+`laddr`::
+ IP address to bind to. Accepts a string in dotted-decimal (IPv4) or
+ colon-separated (IPv6) notation, or the atom `any` to bind to all
+ interfaces. Default: `"127.0.1.1"`.
+
+`lport`::
+ TCP/SCTP port to listen on. Default: `36412` (the IANA-assigned S1AP
+ port).
+
+`sockopts`::
+ An optional map of additional SCTP socket options:
++
+[options="header",cols="20,60,20"]
+|===
+| Option | Description | Default
+| `recbuf` | Receive buffer size in bytes | `65536`
+| `sndbuf` | Send buffer size in bytes | `65536`
+| `nodelay` | Disable Nagle algorithm (`true` to disable) | `true`
+|===
+
+[[config_mme_pool]]
+=== `mme_pool` — MME Pool Configuration
+
+The `mme_pool` key defines the list of MMEs that OsmoS1GW may connect to
+on behalf of connecting eNBs. This is the recommended way to configure
+MME connectivity; it supports multiple MMEs and TAC-based selection.
+
+----
+{mme_pool, [
+ #{
+ name => "mme0", %% unique name (required)
+ raddr => "192.168.2.10", %% MME IP address (required)
+ rport => 36412, %% MME SCTP port (default: 36412)
+ laddr => any, %% local bind address (default: any)
+ tac_list => [] %% allowed TACs (default: [] = all)
+ },
+ #{
+ name => "mme1",
+ raddr => "192.168.2.20",
+ tac_list => [100, 101, 102]
+ }
+]}
+----
+
+Each entry in the list is a map with the following fields:
+
+`name`::
+ A unique, human-readable string identifying this MME in log messages,
+ the REST API, and per-MME metrics. Required.
+
+`raddr`::
+ The remote IP address of the MME. Required.
+
+`rport`::
+ The remote SCTP port of the MME. Default: `36412`.
+
+`laddr`::
+ The local IP address to bind to when connecting to this MME. Accepts
+ a string or the atom `any`. Default: `any`.
+
+`tac_list`::
+ A list of Tracking Area Codes (TACs) that this MME is willing to serve.
+ When an eNB connects and sends its S1 Setup Request, OsmoS1GW filters
+ the pool to MMEs whose `tac_list` is a superset of the eNB's
+ advertised TACs. An empty list means the MME accepts all TACs.
+ Default: `[]`.
+
+MMEs can also be added and removed at run time via the REST API without
+restarting OsmoS1GW (see <<rest_mme>>).
+
+NOTE: The `mme_pool` key is mutually exclusive with the deprecated
+`sctp_client` key described in the next section. If `mme_pool` is
+present, keys `laddr`, `raddr`, and `rport` from the `sctp_client`
+block are ignored.
+
+[[config_sctp_client]]
+=== `sctp_client` — Single MME (Deprecated)
+
+Prior to the introduction of MME pooling, the outbound MME connection was
+configured via the `sctp_client` section:
+
+----
+{sctp_client, #{
+ laddr => "127.0.2.1", %% local bind address
+ raddr => "127.0.2.10", %% MME IP address
+ rport => 36412, %% MME SCTP port
+ sockopts => #{ } %% optional socket options (same as sctp_server)
+}}
+----
+
+When OsmoS1GW starts and finds no `mme_pool` key in the configuration,
+it automatically creates a single `"default"` MME pool entry from the
+`sctp_client` parameters and logs a deprecation warning. This allows
+existing single-MME deployments to continue working without changes, but
+migration to `mme_pool` is strongly recommended.
+
+NOTE: The socket options (`sockopts`) from the `sctp_client` section are
+still used for the outbound SCTP socket regardless of whether `mme_pool`
+or `sctp_client` is used for MME addressing.
+
+[[config_pfcp]]
+=== PFCP — User Plane Function
+
+These parameters control the PFCP session between OsmoS1GW and the UPF.
+
+----
+{pfcp_loc_addr, "127.0.1.1"}, %% local address for PFCP (UDP)
+{pfcp_rem_addr, "127.0.1.2"}, %% remote address of the UPF
+
+%% Optional Network Instance IEs:
+%% {pfcp_net_inst_core, "core-side"},
+%% {pfcp_net_inst_access, "radio-side"}
+----
+
+`pfcp_loc_addr`::
+ Local IP address on which OsmoS1GW listens for PFCP messages from the
+ UPF. Default: `"127.0.1.1"`.
+
+`pfcp_rem_addr`::
+ Remote IP address of the UPF. Default: `"127.0.1.2"`.
+
+`pfcp_net_inst_core`::
+ Value for the PFCP Network Instance IE on the core-network side of each
+ GTP-U session. Omit if the UPF does not require Network Instance IEs.
+
+`pfcp_net_inst_access`::
+ Value for the PFCP Network Instance IE on the radio-access side of each
+ GTP-U session. Omit if the UPF does not require Network Instance IEs.
+
+[[config_gtpu_kpi]]
+=== GTP-U KPI Reporting (Optional)
+
+OsmoS1GW can optionally poll nftables counters to derive per-eNB GTP-U
+traffic statistics and report them as exometer metrics. This feature
+requires a matching nftables ruleset.
+
+----
+%% {gtpu_kpi_enable, true},
+%% {gtpu_kpi_table_name, "osmo-s1gw"},
+%% {gtpu_kpi_ul_addr, s1ap},
+%% {gtpu_kpi_dl_addr, s1ap},
+%% {gtpu_kpi_interval, 3000}
+----
+
+`gtpu_kpi_enable`::
+ Set to `true` to enable the GTP-U KPI module. Default: `false`.
+
+`gtpu_kpi_table_name`::
+ The nftables table name to read counters from.
+ Default: `"osmo-s1gw"`.
+
+`gtpu_kpi_ul_addr`::
+ Source of the uplink GTP-U address used to match nftables counters.
+ `s1ap` means learn the address from S1AP signalling; `sctp` means use
+ the eNB's SCTP source address. Default: `s1ap`.
+
+`gtpu_kpi_dl_addr`::
+ Source of the downlink GTP-U address. Same options as `gtpu_kpi_ul_addr`.
+ Default: `s1ap`.
+
+`gtpu_kpi_interval`::
+ How often (in milliseconds) to poll the nftables counters.
+ Default: `3000`.
+
+[[config_rest]]
+=== REST Interface
+
+----
+%% {rest_srv_port, 8080},
+%% {rest_srv_swagger_ui, true}
+----
+
+`rest_srv_port`::
+ TCP port on which the HTTP REST server listens. Default: `8080`.
+
+`rest_srv_swagger_ui`::
+ Whether to serve the Swagger UI at `http://host:rest_srv_port/swagger`.
+ Default: `true`.
+
+[[config_kernel]]
+=== `kernel` — Logging
+
+OsmoS1GW uses the standard Erlang/OTP `logger` framework. The `kernel`
+application section controls log levels and handlers. See
+<<running_logging>> for a description of the log handlers configured by
+default.
+
+----
+{kernel, [
+ {logger_level, debug},
+ {logger, [
+ {handler, gsmtap, logger_gsmtap_h,
+ #{level => debug,
+ config => #{rem_addr => "127.0.0.1",
+ app_name => "OsmoS1GW"}}},
+ {handler, default, logger_std_h,
+ #{level => info,
+ formatter => {logger_color_formatter, #{...}}}}
+ ]}
+]}
+----
+
+`logger_level`::
+ The global minimum log level. Log records below this level are
+ discarded before reaching any handler. Common values: `debug`,
+ `info`, `notice`, `warning`, `error`.
+
+For each handler in the `logger` list:
+
+`level`::
+ Handler-specific minimum log level. Can be set independently per
+ handler to, for example, send only `warning` and above to the console
+ while sending all `debug` output over GSMTAP.
+
+`gsmtap` handler (`logger_gsmtap_h`)::
+ Sends log messages as GSMTAP frames over UDP.
++
+`rem_addr`::: Destination IP address. Default: `"127.0.0.1"`.
+`app_name`::: Application name tag embedded in each GSMTAP frame.
+
+`default` handler (`logger_std_h`)::
+ Writes log lines to standard output. When OsmoS1GW runs under systemd
+ this output is captured by the journal.
+
+[[config_exometer]]
+=== `exometer_core` — Metrics and StatsD Reporting
+
+OsmoS1GW uses the https://github.com/Feuerlabs/exometer_core[exometer_core]
+library for internal metrics (counters and gauges). The `exometer_core`
+section configures reporters — processes that periodically push metric
+values to an external destination.
+
+The default configuration reports all counters and gauges to a StatsD
+server:
+
+----
+{exometer_core, [
+ {report, [
+ {reporters, [
+ {exometer_report_statsd, [
+ {hostname, "127.0.4.10"},
+ {port, 8125},
+ {prefix, "s1gw"},
+ {type_map, []}
+ ]}
+ ]},
+ {subscribers, [
+ {select, {[{ {['_'|'_'], counter, '_'}, [], ['$_']}],
+ exometer_report_statsd, value, 1000, true,
+ [{report_type, counter}]}},
+ {select, {[{ {['_'|'_'], gauge, '_'}, [], ['$_']}],
+ exometer_report_statsd, value, 1000, true,
+ [{report_type, gauge}]}}
+ ]}
+ ]}
+]}
+----
+
+`hostname`::
+ IP address or hostname of the StatsD server.
+
+`port`::
+ UDP port of the StatsD server. Default: `8125`.
+
+`prefix`::
+ String prepended to all metric names as reported to StatsD.
+ Default: `"s1gw"`.
+
+The `subscribers` list uses exometer's `select` mechanism to
+automatically subscribe all counters and gauges to the StatsD reporter
+with a reporting interval of 1000 ms. To disable StatsD reporting,
+comment out or remove the `exometer_report_statsd` reporter entry.
+
+// vim:set ts=4 sw=4 et:
diff --git a/doc/manuals/chapters/overview.adoc b/doc/manuals/chapters/overview.adoc
new file mode 100644
index 0000000..d8248ca
--- /dev/null
+++ b/doc/manuals/chapters/overview.adoc
@@ -0,0 +1,121 @@
+[[overview]]
+== Overview
+
+[[about]]
+=== About OsmoS1GW
+
+OsmoS1GW is an S1 Gateway for LTE (4G) networks, developed by
+https://www.sysmocom.de/[sysmocom]. It acts as a transparent proxy
+between eNodeBs (eNBs, i.e. radio base stations) and one or more MMEs
+(Mobility Management Entities), relaying S1AP signalling over SCTP/IP in
+both directions.
+
+In addition to S1AP proxying, OsmoS1GW manages GTP-U data plane tunnels
+(E-RABs / EPS bearers) by communicating with a co-located UPF (User
+Plane Function) via PFCP. OsmoS1GW does not carry GTP-U traffic itself:
+GTP-U flows directly between the eNB and the UPF (access side), and
+between the UPF and the S-GW of the core network (core side). OsmoS1GW
+only instructs the UPF — via PFCP Session Establishment, Modification,
+and Deletion procedures — to create, update, or tear down the
+corresponding forwarding rules. It also rewrites the GTP-U TEID and
+Transport Layer Address (TLA) IEs inside S1AP messages so that eNBs send
+their GTP-U traffic to the UPF rather than directly to the core network.
+
+[[architecture]]
+=== Architecture
+
+The following diagram shows the high-level data flow through OsmoS1GW:
+
+----
+ S1AP/SCTP S1AP/SCTP
+eNB <----------> S1GW <----------> MME (core)
+ ^ ^
+ | |
+ | GTP-U | PFCP
+ | |
+ | GTP-U V GTP-U
+ +-------------> UPF <-----------> S-GW (core)
+----
+
+All S1AP messages are inspected by the gateway. Most are forwarded
+unchanged; those that carry GTP-U endpoint information (E-RAB Setup,
+Modify, Release, Initial Context Setup, etc.) are rewritten so that the
+UPF's TLA/TEID is substituted for the core network's endpoint before
+forwarding to the eNB. GTP-U traffic itself never passes through
+OsmoS1GW — it flows directly between the eNB and the UPF, and between
+the UPF and the S-GW.
+
+Internally, OsmoS1GW is structured as a set of Erlang/OTP processes:
+
+* *`sctp_server`* — Listens for incoming eNB SCTP connections and spawns
+ one `enb_proxy` instance per connection.
+* *`enb_proxy`* — One instance per connected eNB. Manages the outbound
+ SCTP connection to the selected MME and drives the S1 Setup handshake.
+ Implements MME pooling and retry logic.
+* *`s1ap_proxy`* — Paired with each `enb_proxy`. Inspects S1AP PDUs in
+ both directions and manages per-UE `erab_fsm` instances.
+* *`erab_fsm`* — One instance per active E-RAB. Exchanges PFCP Session
+ Establishment/Modification/Deletion messages with the UPF and rewrites
+ GTP-U F-TEID IEs in S1AP messages.
+* *`pfcp_peer`* — Manages the PFCP association with the UPF (UDP-based),
+ including periodic heartbeat and SEID allocation.
+* *`mme_registry`* — Manages the pool of known MMEs. MMEs can be
+ provisioned statically via the configuration file or dynamically via
+ the REST API.
+* *`enb_registry`* — Tracks all active eNB connections and their state.
+ Queryable via the REST API.
+* *`rest_server`* — OpenAPI-based HTTP REST interface for monitoring and
+ management.
+
+[[use_cases]]
+=== Use Cases
+
+[[use_case_isolated_networks]]
+==== Separated Core and Access Networks
+
+A common deployment scenario in private or industrial LTE networks is one
+where the core network (EPC) and the radio access network (RAN) reside in
+strictly separated IP domains with no direct routing between them — for
+example, a dedicated operations network for eNBs and a separate
+production network for the EPC.
+
+In this configuration, OsmoS1GW is deployed at the boundary between the
+two networks. Each eNB connects to the gateway's access-facing SCTP
+listener, and the gateway in turn connects outward to the MME. The eNBs
+never need a route to the core, and the EPC never needs a route to the
+radio access domain.
+
+----
+ +-----------+ +----------+ +-----+
+ | eNB |--S1AP/-->| OsmoS1GW |--S1AP/-->| MME |
+ | (RAN net) | SCTP | (border) | SCTP +-----+
+ +-----------+ +----------+
+ | | PFCP
+ | GTP-U +----+
+ +-------------->| UPF |-----> S-GW (EPC net)
+ +-----+
+----
+
+The gateway acts as the sole point of contact between the two networks,
+providing a natural place to apply access control, logging, and
+monitoring.
+
+[[use_case_mme_pooling]]
+==== MME Pooling
+
+OsmoS1GW supports connecting multiple MMEs in a pool. When an eNB
+connects and performs the S1 Setup procedure, the gateway selects an MME
+from the pool, establishes an SCTP connection to it, and forwards the S1
+Setup Request. If the selected MME rejects the setup or is unreachable,
+the gateway automatically retries with the next candidate in the pool
+before returning a failure to the eNB.
+
+Pool members can be filtered by Tracking Area Code (TAC): each MME entry
+in the pool can carry an optional list of TACs it is willing to serve.
+The gateway uses the TAC list advertised by the eNB in the S1 Setup
+Request to restrict selection to compatible MMEs.
+
+MMEs can be configured statically in the configuration file or managed
+dynamically at run time via the REST API (see <<rest_mme>>).
+
+// vim:set ts=4 sw=4 et:
diff --git a/doc/manuals/chapters/running.adoc b/doc/manuals/chapters/running.adoc
new file mode 100644
index 0000000..743456f
--- /dev/null
+++ b/doc/manuals/chapters/running.adoc
@@ -0,0 +1,204 @@
+[[running]]
+== Running OsmoS1GW
+
+[[running_requirements]]
+=== Requirements
+
+OsmoS1GW requires:
+
+* Erlang/OTP 25 or later.
+* A Linux kernel with SCTP support (`sctp` kernel module).
+* A reachable UPF that speaks PFCP (e.g. https://osmocom.org/projects/osmo-upf[OsmoUPF]).
+* One or more reachable MMEs (e.g. https://github.com/open5gs/open5gs[Open5GS]).
+
+[[running_installation_options]]
+=== Installation Options
+
+[[running_binary_packages]]
+==== Official Osmocom Binary Packages
+
+Osmocom provides binary packages of OsmoS1GW for a variety of GNU/Linux
+distributions, primarily Debian based ones. This is the recommended
+installation method for production deployments.
+
+Two package feeds are available:
+
+`latest`::
+ Contains the most recent tagged release of each program.
+ Suitable for production use.
+
+`nightly`::
+ Contains automatic nightly builds from the current master branch.
+ Useful for testing new features or bug fixes before they are formally released.
+
+For up-to-date instructions on how to add the Osmocom package repository
+for your distribution, see:
+https://osmocom.org/projects/cellular-infrastructure/wiki/Binary_Packages
+
+[[running_building]]
+==== Building from Source
+
+OsmoS1GW uses https://rebar3.org[rebar3] as its build tool, wrapped by a
+convenience `Makefile` in the project root. To fetch dependencies and
+compile:
+
+----
+git clone https://gitea.osmocom.org/osmocom/osmo-s1gw.git
+cd osmo-s1gw
+make
+----
+
+[[running_building_make_targets]]
+===== Available Make Targets
+
+The following targets are available:
+
+`make` / `make build`::
+ Compile the application and all dependencies (default target).
+
+`make shell` / `make run`::
+ Compile and start OsmoS1GW in an interactive Erlang shell. Intended
+ for development and local testing. The config file used is controlled
+ by the `CONFIG` variable (default: `config/sys.config`).
+
+`make check`::
+ Run the EUnit test suite. Additional arguments can be passed to the
+ test runner via the `EUNIT_ARGS` variable.
+
+`make analyze`::
+ Run Dialyzer static type analysis.
+
+`make release`::
+ Build a self-contained Erlang/OTP release package (includes the ERTS
+ runtime) under `_build/default/rel/osmo-s1gw/`.
+
+`make run-release`::
+ Build the release and immediately start it using the `osmo-s1gw.sh`
+ bootstrap script (see <<running_bootstrap_script>>). The `CONFIG`
+ variable selects the config file.
+
+`make install`::
+ Build the release and install OsmoS1GW system-wide. See
+ <<running_building_installation>> for details.
+
+`make clean`::
+ Remove all build artefacts.
+
+[[running_building_make_variables]]
+===== Make Variables
+
+The following variables customise the build and installation:
+
+[options="header",cols="25,50,25"]
+|===
+| Variable | Description | Default
+| `CONFIG` | Config file used by `make shell` and `make run-release` | `config/sys.config`
+| `EUNIT_ARGS` | Extra arguments forwarded to `rebar3 eunit` | (none)
+| `BINDIR` | Installation directory for executables | `/usr/bin`
+| `LIBDIR` | Installation directory for the release package | `/usr/lib`
+| `CONFDIR` | Installation directory for the config file | `/etc/osmocom`
+| `SYSTEMDUNITDIR` | Installation directory for the systemd unit | `/lib/systemd/system`
+| `DESTDIR` | Staging root prefix (for package builds) | (empty)
+|===
+
+[[running_building_installation]]
+===== Installation
+
+Running `make install` (typically as root, or with `DESTDIR` set for
+packaging) performs the following steps:
+
+* Copies the self-contained Erlang/OTP release to `$(LIBDIR)/osmo-s1gw`
+ (default: `/usr/lib/osmo-s1gw`). This directory bundles the ERTS
+ runtime and all application code, so no separate Erlang installation is
+ required on the target system.
+* Installs the `osmo-s1gw.sh` bootstrap script (see
+ <<running_bootstrap_script>>) as `$(BINDIR)/osmo-s1gw`
+ (default: `/usr/bin/osmo-s1gw`).
+* Installs the `osmo-s1gw-cli.py` management CLI as
+ `$(BINDIR)/osmo-s1gw-cli` (default: `/usr/bin/osmo-s1gw-cli`).
+* Installs the example `config/sys.config` as
+ `$(CONFDIR)/osmo-s1gw.config` (default: `/etc/osmocom/osmo-s1gw.config`).
+* Installs the systemd unit file to `$(SYSTEMDUNITDIR)/osmo-s1gw.service`
+ (default: `/lib/systemd/system/osmo-s1gw.service`).
+
+[[running_options]]
+=== Running Options
+
+[[running_bootstrap_script]]
+==== The `osmo-s1gw` Bootstrap Script
+
+The installed `osmo-s1gw` executable is a POSIX shell script
+(`contrib/osmo-s1gw.sh`) that locates the bundled ERTS runtime inside
+the release package and launches `erlexec` with the correct boot, config,
+and node parameters. It is the standard entry point both for systemd and
+for manual invocation.
+
+Usage:
+
+----
+osmo-s1gw [-s] [-r ROOTDIR] [-c CONFIG] [-C COOKIE] [-n NAME@HOST]
+----
+
+Options:
+
+`-r ROOTDIR`::
+ Path to the Erlang/OTP release root directory.
+ Default: `/usr/lib/osmo-s1gw`.
+
+`-c CONFIG`::
+ Path to the configuration file.
+ Default: `/etc/osmocom/osmo-s1gw.config`.
+
+`-C COOKIE`::
+ Erlang distribution cookie used for inter-node communication.
+ Default: `osmo-s1gw`.
+
+`-n NAME@HOST`::
+ Erlang node name. Default: `osmo-s1gw@<hostname>`.
+
+`-s`::
+ Start with an interactive Erlang shell instead of running headless.
+ Useful for debugging on a deployed system.
+
+[[running_systemd]]
+==== Running Under systemd
+
+After installation, enable and start OsmoS1GW as a systemd service:
+
+----
+systemctl enable osmo-s1gw
+systemctl start osmo-s1gw
+----
+
+The unit file runs OsmoS1GW as the `osmocom` user and group and requests
+the `CAP_NET_ADMIN` capability (required for GTP-U KPI monitoring).
+The service is restarted automatically on failure with a 2-second delay.
+OsmoS1GW reads its configuration from `/etc/osmocom/osmo-s1gw.config`.
+
+To inspect the log output:
+
+----
+journalctl -u osmo-s1gw -f
+----
+
+[[running_logging]]
+=== Logging
+
+OsmoS1GW uses the standard Erlang/OTP `logger` framework. Two log
+handlers are configured by default in `config/sys.config`:
+
+`default`::
+ Writes formatted log lines to standard output. When running under
+ systemd this output is captured by the journal. The log level is set
+ to `info` by default.
+
+`gsmtap`::
+ Sends log messages as GSMTAP frames over UDP to a configurable
+ destination (default: `127.0.0.1`). These frames can be captured with
+ Wireshark and are tagged with the application name `OsmoS1GW`.
+
+The global minimum log level is controlled by the `logger_level` kernel
+parameter; individual handler levels can be overridden independently.
+See <<config_kernel>> for the relevant configuration section.
+
+// vim:set ts=4 sw=4 et:
diff --git a/doc/manuals/osmo-s1gw-usermanual-docinfo.xml b/doc/manuals/osmo-s1gw-usermanual-docinfo.xml
new file mode 100644
index 0000000..27fd2f3
--- /dev/null
+++ b/doc/manuals/osmo-s1gw-usermanual-docinfo.xml
@@ -0,0 +1,38 @@
+<revhistory>
+ <revision>
+ <revnumber>1</revnumber>
+ <date>March 2026</date>
+ <authorinitials>s</authorinitials>
+ <revremark>Initial version</revremark>
+ </revision>
+</revhistory>
+
+<authorgroup>
+ <author>
+ <firstname>sysmocom</firstname>
+ <surname>- s.f.m.c. GmbH</surname>
+ <email>info(a)sysmocom.de</email>
+ </author>
+</authorgroup>
+
+<copyright>
+ <year>2025-2026</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://gitea.osmocom.org/osmocom/osmo-s1gw">
+ https://gitea.osmocom.org/osmocom/osmo-s1gw
+ </ulink>
+ </para>
+</legalnotice>
diff --git a/doc/manuals/osmo-s1gw-usermanual.adoc b/doc/manuals/osmo-s1gw-usermanual.adoc
new file mode 100644
index 0000000..13dcd4b
--- /dev/null
+++ b/doc/manuals/osmo-s1gw-usermanual.adoc
@@ -0,0 +1,22 @@
+OsmoS1GW User Manual
+====================
+:author: sysmocom - s.f.m.c. GmbH
+:toc:
+:numbered:
+:toclevels: 5
+:sectnumlevels: 5
+
+
+include::{commondir}/chapters/preface.adoc[]
+
+include::{srcdir}/chapters/overview.adoc[]
+
+include::{srcdir}/chapters/running.adoc[]
+
+include::{srcdir}/chapters/configuration.adoc[]
+
+include::{commondir}/chapters/glossary.adoc[]
+
+include::{commondir}/chapters/bibliography.adoc[]
+
+include::{commondir}/chapters/gfdl.adoc[]
--
To view, visit https://gerrit.osmocom.org/c/erlang/osmo-s1gw/+/42364?usp=email
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: newchange
Gerrit-Project: erlang/osmo-s1gw
Gerrit-Branch: master
Gerrit-Change-Id: I4ceca069866d7191ef2b153af95a20cb522bffeb
Gerrit-Change-Number: 42364
Gerrit-PatchSet: 1
Gerrit-Owner: fixeria <vyanitskiy(a)sysmocom.de>
Hello Jenkins Builder,
I'd like you to reexamine a change. Please visit
https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/42360?usp=email
to look at the new patch set (#2).
The following approvals got outdated and were removed:
Verified+1 by Jenkins Builder
Change subject: s1gw: add tests for MME registry REST procedures
......................................................................
s1gw: add tests for MME registry REST procedures
Add three test cases exercising the S1GW REST interface for MME pool
management. The REST TCs are gated on the mp_rest_enable module
parameter in the control block.
TC_rest_mme_list: query the MME pool list via REST and verify it
matches the three static entries from the 'mme_pool' section in
osmo-s1gw.config (mme0/mme1/mme2 with their respective addresses).
TC_rest_mme_add_del: add a new MME entry at runtime via REST, verify
it appears in both the list and individual GET responses, then delete
it and confirm it is gone.
TC_rest_mme_del_fallback: delete mme0 from the pool at runtime and
verify that a connecting eNB is routed directly to mme1, skipping the
deleted entry. The pool is restored to its original state afterwards
via f_REST_mme_pool_restore().
Also add:
* {ts,tr}_MmeItem templates to S1GW_REST_Types.ttcn
* f_REST_mme_find(): returns the integer index of a named entry in a
MmeList, or -1 if not found; used for both presence and absence checks
* f_REST_mme_pool_restore(): deletes all current entries and re-adds
mme0/mme1/mme2 in original order to keep pool state predictable
across test cases
Change-Id: I260bc987ab8ae0ecb547d0b69b261fd97c5c9c23
Related: SYS#7052
---
M s1gw/S1GW_REST_Types.ttcn
M s1gw/S1GW_Tests.ttcn
M s1gw/expected-results.xml
3 files changed, 199 insertions(+), 1 deletion(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-ttcn3-hacks refs/changes/60/42360/2
--
To view, visit https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/42360?usp=email
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: newpatchset
Gerrit-Project: osmo-ttcn3-hacks
Gerrit-Branch: master
Gerrit-Change-Id: I260bc987ab8ae0ecb547d0b69b261fd97c5c9c23
Gerrit-Change-Number: 42360
Gerrit-PatchSet: 2
Gerrit-Owner: fixeria <vyanitskiy(a)sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
fixeria has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/42362?usp=email )
Change subject: s1gw: use REST interface to check PFCP assoc state
......................................................................
s1gw: use REST interface to check PFCP assoc state
It's quicker to query the IUT using the REST interface rather than
waiting for StatsD metric "gauge.pfcp.associated.value" to be received.
As a bonus, we "learn" the local/remote RTS from the S1GW, which can
be used in new PFCP related testcases.
Change-Id: Iec7594e79f533b08ee93b443a39cb9c8ff03da43
---
M s1gw/S1GW_ConnHdlr.ttcn
M s1gw/S1GW_Tests.ttcn
2 files changed, 13 insertions(+), 16 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-ttcn3-hacks refs/changes/62/42362/1
diff --git a/s1gw/S1GW_ConnHdlr.ttcn b/s1gw/S1GW_ConnHdlr.ttcn
index 574a2d0..fd171d3 100644
--- a/s1gw/S1GW_ConnHdlr.ttcn
+++ b/s1gw/S1GW_ConnHdlr.ttcn
@@ -434,16 +434,7 @@
function f_ConnHdlr_pfcp_assoc_handler(charstring id)
runs on ConnHdlr {
- var charstring key_name := g_pars.statsd_prefix & "gauge.pfcp.associated.value";
- var StatsDMetricKeys statsd_keys := { valueof(ts_StatsDMetricKey(key_name, "g")) };
- var StatsDMetrics statsd_snapshot := f_statsd_snapshot(statsd_keys, since_last_snapshot := false);
- var boolean pfcp_associated := statsd_snapshot[0].val == 1;
-
- if (not pfcp_associated) {
- log("Waiting for IUT to associate over PFCP");
- f_ConnHdlr_pfcp_assoc_setup();
- }
-
+ f_ConnHdlr_pfcp_assoc_setup();
setverdict(pass);
}
diff --git a/s1gw/S1GW_Tests.ttcn b/s1gw/S1GW_Tests.ttcn
index b7b01b1..f86546c 100644
--- a/s1gw/S1GW_Tests.ttcn
+++ b/s1gw/S1GW_Tests.ttcn
@@ -76,6 +76,7 @@
var S1AP_ServerList vc_S1APSRVs := {};
var PFCP_Emulation_CT vc_PFCP;
var StatsD_Checker_CT vc_STATSD;
+ var PfcpAssocInfo g_pfcp_assoc;
};
private altstep as_Tguard() runs on test_CT {
@@ -98,11 +99,11 @@
if (s1apsrv_start) {
f_init_s1ap_srv(num_mmes);
}
+ f_init_rest();
if (upf_start) {
f_init_pfcp();
f_pfcp_assoc();
}
- f_init_rest();
}
/* compute the IP address for pool MME server [idx]: mp_mme_bind_ip + idx */
@@ -140,11 +141,16 @@
var verdicttype verdict;
var ConnHdlr vc_conn;
- vc_conn := f_ConnHdlr_spawn(refers(f_ConnHdlr_pfcp_assoc_handler),
- pars := valueof(t_ConnHdlrPars));
- vc_conn.done -> value verdict;
- if (verdict != pass) {
- Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+ g_pfcp_assoc := f_REST_PfcpAssocState();
+ if (g_pfcp_assoc.state != connected) {
+ log("Waiting for IUT to associate over PFCP");
+ vc_conn := f_ConnHdlr_spawn(refers(f_ConnHdlr_pfcp_assoc_handler),
+ pars := valueof(t_ConnHdlrPars));
+ vc_conn.done -> value verdict;
+ if (verdict != pass) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+ }
+ g_pfcp_assoc := f_REST_PfcpAssocState();
}
}
--
To view, visit https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/42362?usp=email
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: newchange
Gerrit-Project: osmo-ttcn3-hacks
Gerrit-Branch: master
Gerrit-Change-Id: Iec7594e79f533b08ee93b443a39cb9c8ff03da43
Gerrit-Change-Number: 42362
Gerrit-PatchSet: 1
Gerrit-Owner: fixeria <vyanitskiy(a)sysmocom.de>