Attention is currently required from: fixeria.
laforge has posted comments on this change by fixeria. ( https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/42359?usp=email )
Change subject: s1gw: add testcases for impatient eNB during MME pool selection
......................................................................
Patch Set 1: Code-Review+1
--
To view, visit https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/42359?usp=email
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: comment
Gerrit-Project: osmo-ttcn3-hacks
Gerrit-Branch: master
Gerrit-Change-Id: I5d27cdafcb9f595a2d3db59beff17cd55de2539e
Gerrit-Change-Number: 42359
Gerrit-PatchSet: 1
Gerrit-Owner: fixeria <vyanitskiy(a)sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: laforge <laforge(a)osmocom.org>
Gerrit-Reviewer: pespin <pespin(a)sysmocom.de>
Gerrit-Attention: fixeria <vyanitskiy(a)sysmocom.de>
Gerrit-Comment-Date: Wed, 18 Mar 2026 10:30:41 +0000
Gerrit-HasComments: No
Gerrit-Has-Labels: Yes
Attention is currently required from: fixeria.
laforge has posted comments on this change by fixeria. ( https://gerrit.osmocom.org/c/pysim/+/42375?usp=email )
Change subject: global_platform: fix store_data() returning last chunk only
......................................................................
Patch Set 3: Code-Review+2
--
To view, visit https://gerrit.osmocom.org/c/pysim/+/42375?usp=email
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: comment
Gerrit-Project: pysim
Gerrit-Branch: master
Gerrit-Change-Id: I3e15c8004d1e366e8c3896e559656622f48bb1a2
Gerrit-Change-Number: 42375
Gerrit-PatchSet: 3
Gerrit-Owner: fixeria <vyanitskiy(a)sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: daniel <dwillmann(a)sysmocom.de>
Gerrit-Reviewer: laforge <laforge(a)osmocom.org>
Gerrit-Attention: fixeria <vyanitskiy(a)sysmocom.de>
Gerrit-Comment-Date: Wed, 18 Mar 2026 10:20:22 +0000
Gerrit-HasComments: No
Gerrit-Has-Labels: Yes
fixeria has submitted this change. ( 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, SYS#7307
---
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(-)
Approvals:
pespin: Looks good to me, approved
Jenkins Builder: Verified
osmith: Looks good to me, but someone else must approve
diff --git a/doc/manuals/chapters/configuration.adoc b/doc/manuals/chapters/configuration.adoc
index 1f623b9..73f9152 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: merged
Gerrit-Project: erlang/osmo-s1gw
Gerrit-Branch: master
Gerrit-Change-Id: I2709cd545bfd6c8f6e34358caf9d372c02dd5c3e
Gerrit-Change-Number: 42366
Gerrit-PatchSet: 5
Gerrit-Owner: fixeria <vyanitskiy(a)sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: fixeria <vyanitskiy(a)sysmocom.de>
Gerrit-Reviewer: osmith <osmith(a)sysmocom.de>
Gerrit-Reviewer: pespin <pespin(a)sysmocom.de>
fixeria has submitted this change. ( 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, SYS#7065
---
M doc/manuals/chapters/configuration.adoc
A doc/manuals/chapters/metrics.adoc
M doc/manuals/osmo-s1gw-usermanual.adoc
3 files changed, 189 insertions(+), 4 deletions(-)
Approvals:
Jenkins Builder: Verified
pespin: Looks good to me, approved
osmith: Looks good to me, but someone else must approve
diff --git a/doc/manuals/chapters/configuration.adoc b/doc/manuals/chapters/configuration.adoc
index 7354d56..1f623b9 100644
--- a/doc/manuals/chapters/configuration.adoc
+++ b/doc/manuals/chapters/configuration.adoc
@@ -255,10 +255,10 @@
[[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.
+See <<metrics>> for an introduction to OsmoS1GW metrics and the full
+list of available 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:
diff --git a/doc/manuals/chapters/metrics.adoc b/doc/manuals/chapters/metrics.adoc
new file mode 100644
index 0000000..a6d495e
--- /dev/null
+++ b/doc/manuals/chapters/metrics.adoc
@@ -0,0 +1,183 @@
+[[metrics]]
+== Metrics
+
+OsmoS1GW exposes internal metrics using the
+https://github.com/Feuerlabs/exometer_core[exometer_core] library, and
+ships with the
+https://github.com/osmocom/exometer_report_statsd[exometer_report_statsd]
+plugin for StatsD reporting. See <<config_exometer>> for configuration
+details.
+
+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
+
+Metric names follow a hierarchical dot-separated structure that reflects
+the subsystem they belong to. For example, metrics related to S1AP
+processing contain `s1ap` in their name, while metrics specific to PFCP
+contain `pfcp`. When StatsD reporting is enabled, all metric names are
+further prefixed with the configured `prefix` string (default: `s1gw`),
+giving e.g. `s1gw.s1ap.proxy.in_pkt.all`.
+
+[[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 received by the proxy (all directions)
+| `s1ap.proxy.in_pkt.drop.all` | Received S1AP PDUs dropped by the proxy
+| `s1ap.proxy.in_pkt.decode_error` | Received S1AP PDUs that failed to decode
+| `s1ap.proxy.in_pkt.proc_error` | Received S1AP PDUs that failed to process
+| `s1ap.proxy.in_pkt.erab_setup_req` | E-RAB SETUP REQUEST PDUs received
+| `s1ap.proxy.in_pkt.erab_setup_rsp` | E-RAB SETUP RESPONSE PDUs received
+| `s1ap.proxy.in_pkt.erab_modify_req` | E-RAB MODIFY REQUEST PDUs received
+| `s1ap.proxy.in_pkt.erab_modify_rsp` | E-RAB MODIFY RESPONSE PDUs received
+| `s1ap.proxy.in_pkt.erab_release_cmd` | E-RAB RELEASE COMMAND PDUs received
+| `s1ap.proxy.in_pkt.erab_release_rsp` | E-RAB RELEASE RESPONSE PDUs received
+| `s1ap.proxy.in_pkt.erab_release_ind` | E-RAB RELEASE INDICATION PDUs received
+| `s1ap.proxy.in_pkt.erab_mod_ind` | E-RAB MODIFICATION INDICATION PDUs received
+| `s1ap.proxy.in_pkt.erab_mod_cnf` | E-RAB MODIFICATION CONFIRM PDUs received
+| `s1ap.proxy.in_pkt.init_ctx_req` | INITIAL CONTEXT SETUP REQUEST PDUs received
+| `s1ap.proxy.in_pkt.init_ctx_rsp` | INITIAL CONTEXT SETUP RESPONSE PDUs received
+| `s1ap.proxy.in_pkt.release_ctx_req` | UE CONTEXT RELEASE REQUEST PDUs received
+| `s1ap.proxy.in_pkt.release_ctx_cmd` | UE CONTEXT RELEASE COMMAND PDUs received
+| `s1ap.proxy.in_pkt.release_ctx_compl` | UE CONTEXT RELEASE COMPLETE PDUs received
+| `s1ap.proxy.in_pkt.handover_cmd` | HANDOVER COMMAND PDUs received
+| `s1ap.proxy.in_pkt.handover_req` | HANDOVER REQUEST PDUs received
+| `s1ap.proxy.in_pkt.handover_req_ack` | HANDOVER REQUEST ACKNOWLEDGE PDUs received
+| `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: merged
Gerrit-Project: erlang/osmo-s1gw
Gerrit-Branch: master
Gerrit-Change-Id: Iacfefd387d0cd26eebbbeba0cd37efa78f90bb46
Gerrit-Change-Number: 42365
Gerrit-PatchSet: 5
Gerrit-Owner: fixeria <vyanitskiy(a)sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: fixeria <vyanitskiy(a)sysmocom.de>
Gerrit-Reviewer: osmith <osmith(a)sysmocom.de>
Gerrit-Reviewer: pespin <pespin(a)sysmocom.de>
fixeria has submitted this change. ( 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, SYS#7066
---
M doc/manuals/chapters/configuration.adoc
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
5 files changed, 297 insertions(+), 5 deletions(-)
Approvals:
osmith: Looks good to me, but someone else must approve
Jenkins Builder: Verified
pespin: Looks good to me, approved
diff --git a/doc/manuals/chapters/configuration.adoc b/doc/manuals/chapters/configuration.adoc
index 73f9152..d032d31 100644
--- a/doc/manuals/chapters/configuration.adoc
+++ b/doc/manuals/chapters/configuration.adoc
@@ -96,7 +96,7 @@
Default: `[]`.
MMEs can also be added and removed at run time via the REST API without
-restarting OsmoS1GW.
+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
diff --git a/doc/manuals/chapters/metrics.adoc b/doc/manuals/chapters/metrics.adoc
index a6d495e..4ea8a53 100644
--- a/doc/manuals/chapters/metrics.adoc
+++ b/doc/manuals/chapters/metrics.adoc
@@ -154,7 +154,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 0ffbc6c..8207290 100644
--- a/doc/manuals/chapters/overview.adoc
+++ b/doc/manuals/chapters/overview.adoc
@@ -90,9 +90,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
@@ -132,6 +132,6 @@
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.
+dynamically at run time via the REST API (see <<rest_mme>>).
// vim:set ts=4 sw=4 et:
diff --git a/doc/manuals/chapters/rest.adoc b/doc/manuals/chapters/rest.adoc
new file mode 100644
index 0000000..c21f4c1
--- /dev/null
+++ b/doc/manuals/chapters/rest.adoc
@@ -0,0 +1,289 @@
+[[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.
+
+// 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: merged
Gerrit-Project: erlang/osmo-s1gw
Gerrit-Branch: master
Gerrit-Change-Id: I8bc9183fff8f65db71554ee26369db9bdb61b78a
Gerrit-Change-Number: 42367
Gerrit-PatchSet: 5
Gerrit-Owner: fixeria <vyanitskiy(a)sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: fixeria <vyanitskiy(a)sysmocom.de>
Gerrit-Reviewer: osmith <osmith(a)sysmocom.de>
Gerrit-Reviewer: pespin <pespin(a)sysmocom.de>