laforge submitted this change.

View Change

Approvals: pespin: Looks good to me, but someone else must approve Jenkins Builder: Verified laforge: Looks good to me, approved
pfcp_peer: implement periodic PFCP heartbeat

Add a heartbeat_interval parameter to the pfcp_peer config section.
When non-zero, pfcp_peer sends a periodic Heartbeat Request to the UPF
at the configured interval using a named gen_statem timeout (hb_timer).
The timer is started on entry to the connected state and cancelled on
re-entry to the connecting state. Default is 10000 ms (10 seconds).

Change-Id: I306324f8eca325202a3fa23125854db9d5eaab38
---
M config/sys.config
M contrib/openapi.yaml
M doc/manuals/chapters/configuration.adoc
M doc/manuals/chapters/rest.adoc
M include/osmo_s1gw.hrl
M priv/openapi.json
M src/osmo_s1gw_sup.erl
M src/pfcp_peer.erl
M src/rest_server.erl
9 files changed, 46 insertions(+), 9 deletions(-)

diff --git a/config/sys.config b/config/sys.config
index 5bebbe6..a34837d 100644
--- a/config/sys.config
+++ b/config/sys.config
@@ -35,7 +35,9 @@
%% optional: PFCP Association Setup timeout in milliseconds (default: 2000)
%% assoc_setup_timeout => 2000,
%% optional: PFCP Heartbeat Request timeout in milliseconds (default: 2000)
- %% heartbeat_req_timeout => 2000
+ %% heartbeat_req_timeout => 2000,
+ %% optional: periodic PFCP heartbeat interval in milliseconds (default: 10000)
+ %% heartbeat_interval => 10000
}}
%% Optional PFCP Network Instance IEs (omitted if not configured)
%% {pfcp_net_inst_core, "core-side"}, %% PFCP Network Instance IE value (to core)
diff --git a/contrib/openapi.yaml b/contrib/openapi.yaml
index 8ca18aa..f6dae12 100644
--- a/contrib/openapi.yaml
+++ b/contrib/openapi.yaml
@@ -535,6 +535,9 @@
heartbeat_req_timeout:
type: integer
description: PFCP Heartbeat Request response timeout in milliseconds
+ heartbeat_interval:
+ type: integer
+ description: Periodic PFCP heartbeat interval in milliseconds

GtpuKpiCfg:
type: object
diff --git a/doc/manuals/chapters/configuration.adoc b/doc/manuals/chapters/configuration.adoc
index a361730..62dbc87 100644
--- a/doc/manuals/chapters/configuration.adoc
+++ b/doc/manuals/chapters/configuration.adoc
@@ -138,7 +138,8 @@
laddr => "127.0.1.1", %% local address for PFCP (UDP)
raddr => "127.0.1.2" %% remote address of the UPF
%% assoc_setup_timeout => 2000, %% optional, milliseconds
- %% heartbeat_req_timeout => 2000 %% optional, milliseconds
+ %% heartbeat_req_timeout => 2000, %% optional, milliseconds
+ %% heartbeat_interval => 0 %% optional, milliseconds (0 = disabled)
}},

%% Optional Network Instance IEs:
@@ -161,6 +162,11 @@
How long (in milliseconds) to wait for a PFCP Heartbeat Response before
declaring the heartbeat timed out. Default: `2000`.

+`heartbeat_interval`::
+ Interval (in milliseconds) between periodic PFCP Heartbeat Requests sent
+ by OsmoS1GW while associated with the UPF. Set to `0` to disable periodic
+ heartbeats entirely. Default: `10000`.
+
NOTE: The legacy flat keys `pfcp_loc_addr` and `pfcp_rem_addr` are still
accepted for backwards compatibility. The `pfcp_peer` map takes priority
if both are present.
diff --git a/doc/manuals/chapters/rest.adoc b/doc/manuals/chapters/rest.adoc
index c3f53af..2f3dd92 100644
--- a/doc/manuals/chapters/rest.adoc
+++ b/doc/manuals/chapters/rest.adoc
@@ -80,7 +80,8 @@
"laddr": "127.0.1.1",
"raddr": "127.0.1.2",
"assoc_setup_timeout": 2000,
- "heartbeat_req_timeout": 2000
+ "heartbeat_req_timeout": 2000,
+ "heartbeat_interval": 10000
},
"gtpu_kpi": {
"enable": false,
@@ -111,6 +112,7 @@
`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).

`gtpu_kpi`::
`enable`::: Whether GTP-U KPI reporting via nftables counters is active.
diff --git a/include/osmo_s1gw.hrl b/include/osmo_s1gw.hrl
index 692a6ff..87da075 100644
--- a/include/osmo_s1gw.hrl
+++ b/include/osmo_s1gw.hrl
@@ -43,6 +43,7 @@
-define(ENV_DEFAULT_PFCP_REM_ADDR, "127.0.1.2").
-define(ENV_DEFAULT_PFCP_ASSOC_SETUP_TIMEOUT, 2000).
-define(ENV_DEFAULT_PFCP_HEARTBEAT_REQ_TIMEOUT, 2000).
+-define(ENV_DEFAULT_PFCP_HEARTBEAT_INTERVAL, 10000). %% 10 seconds
-define(ENV_DEFAULT_GTPU_KPI_ENABLE, false).
-define(ENV_DEFAULT_GTPU_KPI_TABLE_NAME, "osmo-s1gw").
-define(ENV_DEFAULT_GTPU_KPI_INTERVAL, 3000).
diff --git a/priv/openapi.json b/priv/openapi.json
index 3153505..3bc27f9 100644
--- a/priv/openapi.json
+++ b/priv/openapi.json
@@ -771,6 +771,10 @@
"heartbeat_req_timeout": {
"type": "integer",
"description": "PFCP Heartbeat Request response timeout in milliseconds"
+ },
+ "heartbeat_interval": {
+ "type": "integer",
+ "description": "Periodic PFCP heartbeat interval in milliseconds"
}
}
},
diff --git a/src/osmo_s1gw_sup.erl b/src/osmo_s1gw_sup.erl
index 9809fff..832d30f 100644
--- a/src/osmo_s1gw_sup.erl
+++ b/src/osmo_s1gw_sup.erl
@@ -163,7 +163,9 @@
assoc_setup_timeout => maps:get(assoc_setup_timeout, Cfg,
?ENV_DEFAULT_PFCP_ASSOC_SETUP_TIMEOUT),
heartbeat_req_timeout => maps:get(heartbeat_req_timeout, Cfg,
- ?ENV_DEFAULT_PFCP_HEARTBEAT_REQ_TIMEOUT)}.
+ ?ENV_DEFAULT_PFCP_HEARTBEAT_REQ_TIMEOUT),
+ heartbeat_interval => maps:get(heartbeat_interval, Cfg,
+ ?ENV_DEFAULT_PFCP_HEARTBEAT_INTERVAL)}.


-spec gtpu_kpi_cfg() -> gtpu_kpi:cfg().
diff --git a/src/pfcp_peer.erl b/src/pfcp_peer.erl
index 30b45bd..9dd25ea 100644
--- a/src/pfcp_peer.erl
+++ b/src/pfcp_peer.erl
@@ -77,7 +77,8 @@
-type cfg() :: #{laddr := string() | inet:ip_address(),
raddr := string() | inet:ip_address(),
assoc_setup_timeout => pos_integer(),
- heartbeat_req_timeout => pos_integer()}.
+ heartbeat_req_timeout => pos_integer(),
+ heartbeat_interval => non_neg_integer()}.

-type peer_info() :: #{state := atom(),
laddr := inet:ip_address(),
@@ -214,7 +215,8 @@
%% Tx PFCP Association Setup
{ok, S1} = send_assoc_setup(S0),
TVal = maps:get(assoc_setup_timeout, Cfg, ?ENV_DEFAULT_PFCP_ASSOC_SETUP_TIMEOUT),
- {keep_state, S1, [{state_timeout, TVal, assoc_setup_timeout}]};
+ {keep_state, S1, [{{timeout, hb_timer}, cancel},
+ {state_timeout, TVal, assoc_setup_timeout}]};

%% Handle Association Setup timeout
connecting(state_timeout, assoc_setup_timeout, S) ->
@@ -269,10 +271,23 @@


%% CONNECTED state
-connected(enter, OldState, S) ->
+connected(enter, OldState,
+ #peer_state{cfg = Cfg} = S) ->
?LOG_INFO("State change: ~p -> ~p", [OldState, ?FUNCTION_NAME]),
s1gw_metrics:gauge_set(?S1GW_GAUGE_PFCP_ASSOCIATED, 1),
- {keep_state, S};
+ case maps:get(heartbeat_interval, Cfg, ?ENV_DEFAULT_PFCP_HEARTBEAT_INTERVAL) of
+ 0 -> {keep_state, S}; %% periodic heartbeat is disabled
+ Interval ->
+ ?LOG_INFO("Starting periodic PFCP heartbeat (interval=~p ms)", [Interval]),
+ {keep_state, S, [{{timeout, hb_timer}, Interval, heartbeat}]}
+ end;
+
+%% Periodic heartbeat timer
+connected({timeout, hb_timer}, heartbeat,
+ #peer_state{cfg = Cfg} = S0) ->
+ {_, S1} = send_heartbeat_request(undefined, S0),
+ Interval = maps:get(heartbeat_interval, Cfg, ?ENV_DEFAULT_PFCP_HEARTBEAT_INTERVAL),
+ {keep_state, S1, [{{timeout, hb_timer}, Interval, heartbeat}]};

connected({call, From},
{session_establish_req, SEID, PDRs, FARs},
diff --git a/src/rest_server.erl b/src/rest_server.erl
index 7960ffa..bff37fc 100644
--- a/src/rest_server.erl
+++ b/src/rest_server.erl
@@ -285,7 +285,9 @@
<<"assoc_setup_timeout">> => maps:get(assoc_setup_timeout, Cfg,
?ENV_DEFAULT_PFCP_ASSOC_SETUP_TIMEOUT),
<<"heartbeat_req_timeout">> => maps:get(heartbeat_req_timeout, Cfg,
- ?ENV_DEFAULT_PFCP_HEARTBEAT_REQ_TIMEOUT)}.
+ ?ENV_DEFAULT_PFCP_HEARTBEAT_REQ_TIMEOUT),
+ <<"heartbeat_interval">> => maps:get(heartbeat_interval, Cfg,
+ ?ENV_DEFAULT_PFCP_HEARTBEAT_INTERVAL)}.


-spec config_gtpu_kpi() -> map().

To view, visit change 42487. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-MessageType: merged
Gerrit-Project: erlang/osmo-s1gw
Gerrit-Branch: master
Gerrit-Change-Id: I306324f8eca325202a3fa23125854db9d5eaab38
Gerrit-Change-Number: 42487
Gerrit-PatchSet: 3
Gerrit-Owner: fixeria <vyanitskiy@sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: laforge <laforge@osmocom.org>
Gerrit-Reviewer: pespin <pespin@sysmocom.de>