fixeria has uploaded this change for review. ( 
https://gerrit.osmocom.org/c/erlang/osmo-s1gw/+/42487?usp=email )


Change subject: pfcp_peer: implement periodic PFCP heartbeat
......................................................................

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 0 (disabled).

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(-)



  git pull ssh://gerrit.osmocom.org:29418/erlang/osmo-s1gw 
refs/changes/87/42487/1

diff --git a/config/sys.config b/config/sys.config
index 5bebbe6..ac4a428 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: 
0, disabled)
+      %% heartbeat_interval => 0
    }}
 %% 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..c9d668a 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 (0 = 
disabled)

     GtpuKpiCfg:
       type: object
diff --git a/doc/manuals/chapters/configuration.adoc 
b/doc/manuals/chapters/configuration.adoc
index a361730..a8ea114 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: `0`.
+
 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..2a5dcbf 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": 0
   },
   "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..95dabfc 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, 0). %% disabled
 -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..bf5aaf2 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 (0 = disabled)"
                     }
                 }
             },
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 a6f4b03..2002a19 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 https://gerrit.osmocom.org/c/erlang/osmo-s1gw/+/42487?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: I306324f8eca325202a3fa23125854db9d5eaab38
Gerrit-Change-Number: 42487
Gerrit-PatchSet: 1
Gerrit-Owner: fixeria <[email protected]>

Reply via email to