fixeria has submitted this change. ( https://gerrit.osmocom.org/c/erlang/osmo-s1gw/+/42486?usp=email )
Change subject: pfcp_peer: make assoc_setup and heartbeat_req timeouts configurable ......................................................................
pfcp_peer: make assoc_setup and heartbeat_req timeouts configurable
Add assoc_setup_timeout and heartbeat_req_timeout as optional fields in the pfcp_peer config map, with 2000 ms defaults. Store the full cfg() map in #peer_state{} and read values from it with maps:get/3 at the point of use.
Change-Id: I58a472a3bbbbad029a2f0246b084428ab3b1905c --- 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, 62 insertions(+), 13 deletions(-)
Approvals: pespin: Looks good to me, approved Jenkins Builder: Verified laforge: Looks good to me, but someone else must approve
diff --git a/config/sys.config b/config/sys.config index af6480b..5bebbe6 100644 --- a/config/sys.config +++ b/config/sys.config @@ -32,6 +32,10 @@ laddr => "127.0.1.1", %% remote address for outgoing PFCP PDUs to the UPF raddr => "127.0.1.2" + %% 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 }} %% 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 59de93f..8ca18aa 100644 --- a/contrib/openapi.yaml +++ b/contrib/openapi.yaml @@ -529,6 +529,12 @@ raddr: type: string description: Remote IP address of the UPF (PFCP peer) + assoc_setup_timeout: + type: integer + description: PFCP Association Setup response timeout in milliseconds + heartbeat_req_timeout: + type: integer + description: PFCP Heartbeat Request response timeout in milliseconds
GtpuKpiCfg: type: object diff --git a/doc/manuals/chapters/configuration.adoc b/doc/manuals/chapters/configuration.adoc index a43c9ad..a361730 100644 --- a/doc/manuals/chapters/configuration.adoc +++ b/doc/manuals/chapters/configuration.adoc @@ -137,6 +137,8 @@ {pfcp_peer, #{ 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 }},
%% Optional Network Instance IEs: @@ -151,6 +153,14 @@ `raddr`:: Remote IP address of the UPF. Default: `"127.0.1.2"`.
+`assoc_setup_timeout`:: + How long (in milliseconds) to wait for a PFCP Association Setup Response + before retrying. Default: `2000`. + +`heartbeat_req_timeout`:: + How long (in milliseconds) to wait for a PFCP Heartbeat Response before + declaring the heartbeat timed out. Default: `2000`. + 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 92b4f7a..c3f53af 100644 --- a/doc/manuals/chapters/rest.adoc +++ b/doc/manuals/chapters/rest.adoc @@ -78,7 +78,9 @@ }, "pfcp": { "laddr": "127.0.1.1", - "raddr": "127.0.1.2" + "raddr": "127.0.1.2", + "assoc_setup_timeout": 2000, + "heartbeat_req_timeout": 2000 }, "gtpu_kpi": { "enable": false, @@ -107,6 +109,8 @@ `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.
`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 91bd2e6..692a6ff 100644 --- a/include/osmo_s1gw.hrl +++ b/include/osmo_s1gw.hrl @@ -41,6 +41,8 @@ -define(ENV_DEFAULT_MME_REM_PORT, 36412). -define(ENV_DEFAULT_PFCP_LOC_ADDR, "127.0.1.1"). -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_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 cf2fb50..3153505 100644 --- a/priv/openapi.json +++ b/priv/openapi.json @@ -763,6 +763,14 @@ "raddr": { "type": "string", "description": "Remote IP address of the UPF (PFCP peer)" + }, + "assoc_setup_timeout": { + "type": "integer", + "description": "PFCP Association Setup response timeout in milliseconds" + }, + "heartbeat_req_timeout": { + "type": "integer", + "description": "PFCP Heartbeat Request response timeout in milliseconds" } } }, diff --git a/src/osmo_s1gw_sup.erl b/src/osmo_s1gw_sup.erl index 573f2cb..9809fff 100644 --- a/src/osmo_s1gw_sup.erl +++ b/src/osmo_s1gw_sup.erl @@ -159,7 +159,11 @@ %% parse the new pfcp configuration block (takes priority) Cfg = maps:merge(OldCfg, osmo_s1gw:get_env(pfcp_peer, #{ })), #{laddr => maps:get(laddr, Cfg, ?ENV_DEFAULT_PFCP_LOC_ADDR), - raddr => maps:get(raddr, Cfg, ?ENV_DEFAULT_PFCP_REM_ADDR)}. + raddr => maps:get(raddr, Cfg, ?ENV_DEFAULT_PFCP_REM_ADDR), + 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)}.
-spec gtpu_kpi_cfg() -> gtpu_kpi:cfg(). diff --git a/src/pfcp_peer.erl b/src/pfcp_peer.erl index 3423237..a6f4b03 100644 --- a/src/pfcp_peer.erl +++ b/src/pfcp_peer.erl @@ -55,14 +55,14 @@
-include_lib("kernel/include/logger.hrl"). -include_lib("pfcplib/include/pfcp_packet.hrl"). + +-include("osmo_s1gw.hrl"). -include("s1gw_metrics.hrl").
%% 3GPP TS 29.244, section 4.2 "UDP Header and Port Numbers" -define(PFCP_PORT, 8805). -define(PFCP_SEQ_NR_MAX, 16#ffffff). -define(PFCP_SEID_MAX, 16#ffffffffffffffff). --define(PFCP_ASSOC_SETUP_TIMEOUT, 2000). --define(PFCP_HEARTBEAT_REQ_TIMEOUT, 2000).
-type pfcp_session_rsp() :: ok | {error, term()}.
@@ -75,7 +75,9 @@ -type pfcp_pdu() :: #pfcp{}.
-type cfg() :: #{laddr := string() | inet:ip_address(), - raddr := string() | inet:ip_address()}. + raddr := string() | inet:ip_address(), + assoc_setup_timeout => pos_integer(), + heartbeat_req_timeout => pos_integer()}.
-type peer_info() :: #{state := atom(), laddr := inet:ip_address(), @@ -98,7 +100,8 @@ tref :: reference() }).
--record(peer_state, {seid :: pfcp_seid(), +-record(peer_state, {cfg :: cfg(), + seid :: pfcp_seid(), sock :: gen_udp:socket(), loc_addr :: inet:ip_address(), rem_addr :: inet:ip_address(), @@ -189,7 +192,8 @@ {reuseaddr, true}, {active, true}]), ?LOG_INFO("PFCP peer @ ~p will talk to UPF @ ~p", [LocAddr, RemAddr]), - {ok, connecting, #peer_state{seid = 1, %% SEID=0 is special, see 7.2.2.4.2 + {ok, connecting, #peer_state{cfg = Cfg, + seid = 1, %% SEID=0 is special, see 7.2.2.4.2 sock = Sock, loc_addr = LocAddr, rem_addr = RemAddr, @@ -204,12 +208,13 @@
%% CONNECTING state connecting(enter, OldState, - #peer_state{} = S0) -> + #peer_state{cfg = Cfg} = S0) -> ?LOG_INFO("State change: ~p -> ~p", [OldState, ?FUNCTION_NAME]), s1gw_metrics:gauge_set(?S1GW_GAUGE_PFCP_ASSOCIATED, 0), %% Tx PFCP Association Setup {ok, S1} = send_assoc_setup(S0), - {keep_state, S1, [{state_timeout, ?PFCP_ASSOC_SETUP_TIMEOUT, assoc_setup_timeout}]}; + TVal = maps:get(assoc_setup_timeout, Cfg, ?ENV_DEFAULT_PFCP_ASSOC_SETUP_TIMEOUT), + {keep_state, S1, [{state_timeout, TVal, assoc_setup_timeout}]};
%% Handle Association Setup timeout connecting(state_timeout, assoc_setup_timeout, S) -> @@ -571,7 +576,8 @@ ?LOG_ERROR("Another Heartbeat Request is still pending (SeqNr=~p)", [SeqNr]), {{error, heartbeat_req_pending}, S};
-send_heartbeat_request(From, #peer_state{heartbeat = undefined, +send_heartbeat_request(From, #peer_state{cfg = Cfg, + heartbeat = undefined, seq_nr = SeqNr, loc_rts = LRTS} = S0) -> ReqIEs = #{recovery_time_stamp => #recovery_time_stamp{time = LRTS}}, @@ -579,8 +585,9 @@ case send_pdu({heartbeat_request, ReqIEs}, S0) of {ok, S1} -> s1gw_metrics:ctr_inc(?S1GW_CTR_PFCP_HEARTBEAT_REQ_TX), - TRef = erlang:start_timer(?PFCP_HEARTBEAT_REQ_TIMEOUT, self(), - heartbeat_request_watchdog), + TVal = maps:get(heartbeat_req_timeout, Cfg, + ?ENV_DEFAULT_PFCP_HEARTBEAT_REQ_TIMEOUT), + TRef = erlang:start_timer(TVal, self(), heartbeat_request_watchdog), HB = #heartbeat_state{from = From, seq_nr = SeqNr, tref = TRef}, diff --git a/src/rest_server.erl b/src/rest_server.erl index 24ca33b..7960ffa 100644 --- a/src/rest_server.erl +++ b/src/rest_server.erl @@ -281,7 +281,11 @@ config_pfcp() -> Cfg = osmo_s1gw:get_env(pfcp_peer, #{}), #{<<"laddr">> => bval(maps:get(laddr, Cfg, ?ENV_DEFAULT_PFCP_LOC_ADDR)), - <<"raddr">> => bval(maps:get(raddr, Cfg, ?ENV_DEFAULT_PFCP_REM_ADDR))}. + <<"raddr">> => bval(maps:get(raddr, Cfg, ?ENV_DEFAULT_PFCP_REM_ADDR)), + <<"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)}.
-spec config_gtpu_kpi() -> map().