[[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 <>), 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 <> 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 <>). [[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 <>): `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: