[[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>>).  An interactive CLI tool
(`osmo-s1gw-cli`) is also available as a convenient alternative to
issuing raw HTTP requests — see <<cli>>.

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_config]]
=== Configuration

==== `GET /config` — Runtime Configuration

Returns the effective runtime configuration that OsmoS1GW is currently
using, with all defaults applied.  This reflects the values read via
`osmo_s1gw:get_env/2` at startup, which may differ from the raw
`sys.config` if legacy environment variables were merged in.

Response (HTTP 200):

----
{
  "sctp_server": {
    "laddr": "127.0.1.1",
    "lport": 36412,
    "sockopts": {"recbuf": 65536, "sndbuf": 65536, "sctp_nodelay": true}
  },
  "sctp_client": {
    "laddr": "127.0.2.1",
    "raddr": "127.0.2.10",
    "rport": 36412,
    "sockopts": {"recbuf": 65536, "sndbuf": 65536, "sctp_nodelay": true}
  },
  "pfcp": {
    "laddr": "127.0.1.1",
    "raddr": "127.0.1.2",
    "assoc_setup_timeout": 2000,
    "heartbeat_req_timeout": 2000,
    "heartbeat_interval": 10000,
    "heartbeat_fail_threshold": 3
  },
  "gtpu_kpi": {
    "enable": false,
    "table_name": "osmo-s1gw",
    "interval": 3000
  },
  "rest": {
    "port": 8080,
    "swagger_ui": true
  }
}
----

`sctp_server`:: Configuration of the eNB-facing SCTP server.
  `laddr`::: Local bind address.
  `lport`::: Local bind port.
  `sockopts`::: Effective SCTP socket options, including defaults.

`sctp_client`:: Legacy/deprecated section reflecting the MME-facing SCTP
  client defaults.  MME pool entries are managed via <<rest_mme>>.
  `laddr`::: Local bind address.
  `raddr`::: Default remote (MME) address.
  `rport`::: Default remote (MME) port.
  `sockopts`::: Effective SCTP socket options, including defaults.

`pfcp`::
  `laddr`::: Local PFCP bind address.
  `raddr`::: Remote UPF (PFCP peer) address.
  `assoc_setup_timeout`::: PFCP Association Setup response timeout in milliseconds.
  `heartbeat_req_timeout`::: PFCP Heartbeat Request response timeout in milliseconds.
  `heartbeat_interval`::: Periodic PFCP heartbeat interval in milliseconds (0 = disabled).
  `heartbeat_fail_threshold`::: Number of heartbeat failures before resetting the association.

`gtpu_kpi`::
  `enable`::: Whether GTP-U KPI reporting via nftables counters is active.
  `table_name`::: nftables table name used for GTP-U KPI counters.
  `interval`::: KPI polling interval in milliseconds.

`rest`::
  `port`::: REST server listen port.
  `swagger_ui`::: Whether the Swagger UI endpoint is enabled.

[[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": "any", "raddr": "192.168.2.10", "rport": 36412, "tac_list": []},
  {"name": "mme1", "laddr": "any", "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",
    "plmn_id": {"mcc": "001", "mnc": "01"},
    "enb_id": 0,
    "state": "connected",
    "enb_saddr": "192.168.1.10",
    "enb_sport": 56767,
    "enb_sctp_aid": 5706,
    "mme_name": "mme0",
    "mme_saddr": "192.168.2.1",
    "mme_sport": 34500,
    "mme_daddr": "192.168.2.10",
    "mme_dport": 36412,
    "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 (MCC-MNC-eNBId) parsed from the S1 Setup Request.
`plmn_id`:: PLMN identifier as received in the S1 Setup Request, encoded as
  an object with `mcc` and `mnc` string fields.
`enb_id`:: eNB identifier (integer) parsed from the S1 Setup Request.
`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_name`:: Name of the selected MME (from the MME pool).
`mme_saddr` / `mme_sport`:: Local address and port of the S1GW-MME SCTP connection.
`mme_daddr` / `mme_dport`:: Destination address and port of the MME.
`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:
