fixeria has uploaded this change for review. ( https://gerrit.osmocom.org/c/erlang/osmo-s1gw/+/38766?usp=email )
Change subject: erab_fsm: add erab_release/2 and erab_release_ind/1 ......................................................................
erab_fsm: add erab_release/2 and erab_release_ind/1
The E-RAB RELEASE INDICATION message is used by the eNB to indicate termination of one or several E-RAB(s). Unlike with the RELEASE COMMAND, there is no response to that message. Thus, we shall not wait for it (by entering state erab_wait_release_rsp) but terminate the E-RAB FSM immediately instead.
Change-Id: Icc9c0f6a1aef327e9585942b3c9d2302feda393a --- M src/erab_fsm.erl M test/erab_fsm_test.erl 2 files changed, 51 insertions(+), 9 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/erlang/osmo-s1gw refs/changes/66/38766/1
diff --git a/src/erab_fsm.erl b/src/erab_fsm.erl index fb6def3..f185867 100644 --- a/src/erab_fsm.erl +++ b/src/erab_fsm.erl @@ -49,8 +49,10 @@ -export([start_link/1, erab_setup_req/2, erab_setup_rsp/2, + erab_release/2, erab_release_cmd/1, erab_release_rsp/1, + erab_release_ind/1, shutdown/1]).
-include_lib("kernel/include/logger.hrl"). @@ -70,13 +72,16 @@ addr() %% GTP-U Transport Layer Address }.
+-type rel_kind() :: cmd | ind. + -record(erab_state, {from :: undefined | gen_statem:from(), %% destination to use when replying u2c :: undefined | teid_addr(), %% GTP-U params for UPF -> Core c2u :: undefined | teid_addr(), %% GTP-U params for UPF <- Core a2u :: undefined | teid_addr(), %% GTP-U params for UPF <- Access u2a :: undefined | teid_addr(), %% GTP-U params for UPF -> Access seid_loc :: undefined | pfcp_peer:pfcp_seid(), %% local SEID, chosen by us - seid_rem :: undefined | pfcp_peer:pfcp_seid() %% remote SEID, chosen by the UPF + seid_rem :: undefined | pfcp_peer:pfcp_seid(), %% remote SEID, chosen by the UPF + rel_kind :: undefined | rel_kind() %% E-RAB RELEASE kind }).
-type erab_state() :: #erab_state{}. @@ -120,6 +125,13 @@ gen_statem:call(Pid, {?FUNCTION_NAME, F_TEID}).
+-spec erab_release(pid(), rel_kind()) -> ok. +erab_release(Pid, cmd) -> + erab_release_cmd(Pid); +erab_release(Pid, ind) -> + erab_release_ind(Pid). + + -spec erab_release_cmd(pid()) -> ok. erab_release_cmd(Pid) -> gen_statem:call(Pid, ?FUNCTION_NAME). @@ -130,6 +142,11 @@ gen_statem:cast(Pid, ?FUNCTION_NAME).
+-spec erab_release_ind(pid()) -> ok. +erab_release_ind(Pid) -> + gen_statem:call(Pid, ?FUNCTION_NAME). + + -spec shutdown(pid()) -> ok. shutdown(Pid) -> gen_statem:stop(Pid). @@ -290,7 +307,16 @@ #erab_state{} = S) -> ?LOG_DEBUG("Rx E-RAB RELEASE Req"), {next_state, session_delete, - S#erab_state{from = From}}; + S#erab_state{from = From, + rel_kind = cmd}}; + +erab_setup({call, From}, + erab_release_ind, + #erab_state{} = S) -> + ?LOG_DEBUG("Rx E-RAB RELEASE Ind"), + {next_state, session_delete, + S#erab_state{from = From, + rel_kind = ind}};
%% Catch-all handler for this state erab_setup(Event, EventData, S) -> @@ -317,15 +343,22 @@
session_delete(info, #pfcp{} = PDU, #erab_state{from = From, - seid_loc = SEID_Rsp} = S) -> + seid_loc = SEID_Rsp, + rel_kind = RelKind} = S) -> case PDU of #pfcp{type = session_deletion_response, seid = SEID_Rsp, %% matches F-SEID we sent in the ESTABLISH Req ie = #{pfcp_cause := 'Request accepted'}} -> ?LOG_DEBUG("PFCP session deleted"), - {next_state, erab_wait_release_rsp, - S#erab_state{from = undefined}, - [{reply, From, ok}]}; + Reply = {reply, From, ok}, + case RelKind of + cmd -> %% E-RAB RELEASE CMD => wait for the RSP + {next_state, erab_wait_release_rsp, + S#erab_state{from = undefined}, + [Reply]}; + ind -> %% E-RAB RELEASE IND => terminate immediately + {stop_and_reply, normal, [Reply]} + end; _ -> ?LOG_ERROR("Rx unexpected PFCP PDU: ~p", [PDU]), {stop_and_reply, diff --git a/test/erab_fsm_test.erl b/test/erab_fsm_test.erl index e4b036e..0bd6b8b 100644 --- a/test/erab_fsm_test.erl +++ b/test/erab_fsm_test.erl @@ -44,8 +44,10 @@
erab_release_test_() -> - [{"E-RAB release :: success", - ?TC(fun test_erab_release_success/1)}, + [{"E-RAB RELEASE CMD :: success", + ?TC(fun test_erab_release_cmd_success/1)}, + {"E-RAB RELEASE IND :: success", + ?TC(fun test_erab_release_ind_success/1)}, {"E-RAB release :: PFCP session deletion error", ?TC(fun test_erab_release_pfcp_delete_error/1)}].
@@ -91,7 +93,7 @@ ?_assertNot(erlang:is_process_alive(Pid))].
-test_erab_release_success(Pid) -> +test_erab_release_cmd_success(Pid) -> [?_assertEqual({ok, ?A2U}, erab_fsm:erab_setup_req(Pid, ?U2C)), ?_assertEqual({ok, ?C2U}, erab_fsm:erab_setup_rsp(Pid, ?U2A)), ?_assertEqual(ok, erab_fsm:erab_release_cmd(Pid)), @@ -99,6 +101,13 @@ ?_assertNot(erlang:is_process_alive(Pid))].
+test_erab_release_ind_success(Pid) -> + [?_assertEqual({ok, ?A2U}, erab_fsm:erab_setup_req(Pid, ?U2C)), + ?_assertEqual({ok, ?C2U}, erab_fsm:erab_setup_rsp(Pid, ?U2A)), + ?_assertEqual(ok, erab_fsm:erab_release_ind(Pid)), + ?_assertNot(erlang:is_process_alive(Pid))]. + + test_erab_release_pfcp_delete_error(Pid) -> %% pfcp_peer:session_delete_req/1 responds with a reject PDU = pfcp_mock:pdu_rsp_reject(session_deletion_response, ?SEID_Loc),