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


Change subject: erab_fsm: implement E-RAB MODIFY Ind/Cnf procedure
......................................................................

erab_fsm: implement E-RAB MODIFY Ind/Cnf procedure

The eNB-initiated E-RAB modification procedure is defined
in 3GPP TS 36.413 section 8.2.4.  This is pretty much the same
as the MME-initiated E-RAB modification.

Change-Id: I750ada0a5a21edc8bc06d567c8000b6304966474
---
M src/erab_fsm.erl
M test/erab_fsm_test.erl
M test/pfcp_mock.hrl
3 files changed, 119 insertions(+), 3 deletions(-)



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

diff --git a/src/erab_fsm.erl b/src/erab_fsm.erl
index c684510..9d11be6 100644
--- a/src/erab_fsm.erl
+++ b/src/erab_fsm.erl
@@ -51,6 +51,8 @@
          erab_setup_rsp/2,
          erab_modify_req/2,
          erab_modify_rsp/2,
+         erab_modify_ind/2,
+         erab_modify_cnf/2,
          erab_release/2,
          erab_release_cmd/1,
          erab_release_rsp/1,
@@ -77,7 +79,9 @@

 -type mod_kind() :: setup_rsp |
                     modify_req |
-                    modify_rsp_nack.
+                    modify_rsp_nack |
+                    modify_ind |
+                    modify_cnf_nack.
 -type rel_kind() :: cmd | ind.

 -record(erab_state, {uid :: term(), %% unique E-RAB identifier
@@ -87,6 +91,7 @@
                      a2u :: undefined | teid_addr(), %% GTP-U params for UPF 
<- Access
                      u2a :: undefined | teid_addr(), %% GTP-U params for UPF 
-> Access
                      u2cm :: undefined | teid_addr(), %% GTP-U params for UPF 
-> Core (modified)
+                     u2am :: undefined | teid_addr(), %% GTP-U params for UPF 
-> Access (modified)
                      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
                      mod_kind :: undefined | mod_kind(), %% E-RAB MODIFY kind
@@ -156,6 +161,28 @@
     gen_statem:call(Pid, {?FUNCTION_NAME, Res}).


+%% @doc Indicate reception of E-RAB modify indication (from access).
+%% @param Pid  PID of an erab_fsm.
+%% @param F_TEID  TEID and bind address indicated by the eNB.
+%% @returns TEID and Addr to be sent to the MME;  an error otherwise.
+%% @end
+-spec erab_modify_ind(pid(), teid_addr()) -> {ok, teid_addr()} |
+                                             {error, term()}.
+erab_modify_ind(Pid, F_TEID) ->
+    gen_statem:call(Pid, {?FUNCTION_NAME, F_TEID}).
+
+
+%% @doc Indicate reception of E-RAB modify confirmation (from core).
+%% @param Pid  PID of an erab_fsm.
+%% @param Res  ack  if MME indicates successful modification;
+%%             nack if MME indicates unsuccessful modification.
+%% @returns ok or an error.
+%% @end
+-spec erab_modify_cnf(pid(), ack | nack) -> ok | {error, term()}.
+erab_modify_cnf(Pid, Res) ->
+    gen_statem:call(Pid, {?FUNCTION_NAME, Res}).
+
+
 -spec erab_release(pid(), rel_kind()) -> ok.
 erab_release(Pid, cmd) ->
     erab_release_cmd(Pid);
@@ -320,6 +347,10 @@
         modify_req ->
             {ok, S#erab_state.a2u};
         modify_rsp_nack ->
+            ok;
+        modify_ind ->
+            {ok, S#erab_state.c2u};
+        modify_cnf_nack ->
             ok
     end,
     {next_state, erab_setup,
@@ -379,6 +410,41 @@
     end;

 erab_setup({call, From},
+           {erab_modify_ind, U2AM},
+           #erab_state{} = S) ->
+    ?LOG_DEBUG("Rx E-RAB MODIFY Ind (U2AM ~p)", [U2AM]),
+    {next_state, session_modify,
+     S#erab_state{mod_kind = modify_ind,
+                  from = From,
+                  u2am = U2AM}};
+
+erab_setup({call, From},
+           {erab_modify_cnf, Res},
+           #erab_state{u2am = undefined}) ->
+    %% Ignore erab_modify_cnf events without prior erab_modify_ind.  This 
happens
+    %% when the S1AP E-RAB MODIFY Ind contains no F-TEID (nothing to modify).
+    ?LOG_DEBUG("Rx E-RAB MODIFY Cnf (~p), F-TEID remains unchanged", [Res]),
+    {keep_state_and_data, {reply, From, ok}};
+
+erab_setup({call, From},
+           {erab_modify_cnf, Res},
+           #erab_state{u2am = U2AM} = S0) ->
+    ?LOG_DEBUG("Rx E-RAB MODIFY Cnf (~p)", [Res]),
+    case Res of
+        ack ->
+            {keep_state,
+             S0#erab_state{u2a = U2AM,
+                           u2am = undefined},
+             {reply, From, ok}};
+        nack ->
+            %% revert PFCP session params
+            {next_state, session_modify,
+             S0#erab_state{mod_kind = modify_cnf_nack,
+                           u2am = undefined,
+                           from = From}}
+    end;
+
+erab_setup({call, From},
            erab_release_cmd,
            #erab_state{} = S) ->
     ?LOG_DEBUG("Rx E-RAB RELEASE Cmd"),
@@ -559,7 +625,21 @@
                                u2c = U2C}) ->
     %% E-RAB MODIFY Rsp (NACK) - eNB NACK's E-RAB modification
     %% so we modify the respective FAR (id=2)
-    session_modify_req(SEID, 2, U2C).
+    session_modify_req(SEID, 2, U2C);
+
+session_modify_req(#erab_state{mod_kind = modify_ind,
+                               seid_rem = SEID,
+                               u2am = U2AM}) ->
+    %% E-RAB MODIFY Ind - eNB orders modification of U2A F-TEID,
+    %% so we modify the respective FAR (id=1)
+    session_modify_req(SEID, 1, U2AM);
+
+session_modify_req(#erab_state{mod_kind = modify_cnf_nack,
+                               seid_rem = SEID,
+                               u2a = U2A}) ->
+    %% E-RAB MODIFY Cnf (NACK) - MME NACK's E-RAB modification
+    %% so we modify the respective FAR (id=1)
+    session_modify_req(SEID, 1, U2A).


 -spec session_modify_req(SEID, FAR_ID, F_TEID) -> Result
diff --git a/test/erab_fsm_test.erl b/test/erab_fsm_test.erl
index 5563d02..c000701 100644
--- a/test/erab_fsm_test.erl
+++ b/test/erab_fsm_test.erl
@@ -9,6 +9,7 @@
 -define(U2A, {?TEID_U2A, ?ADDR_U2A}).

 -define(U2CM, {?TEID_U2CM, ?ADDR_U2CM}).
+-define(U2AM, {?TEID_U2AM, ?ADDR_U2AM}).

 %% ------------------------------------------------------------------
 %% setup/misc functions
@@ -54,7 +55,11 @@
     [{"E-RAB MODIFY REQ :: ACK",
       ?TC(fun test_erab_modify_req_ack/1)},
      {"E-RAB MODIFY REQ :: NACK",
-      ?TC(fun test_erab_modify_req_nack/1)}].
+      ?TC(fun test_erab_modify_req_nack/1)},
+     {"E-RAB MODIFY IND :: ACK",
+      ?TC(fun test_erab_modify_ind_ack/1)},
+     {"E-RAB MODIFY IND :: NACK",
+      ?TC(fun test_erab_modify_ind_nack/1)}].


 erab_release_test_() ->
@@ -143,6 +148,35 @@
     test_erab_modify_req(Pid, nack).


+test_erab_modify_ind(Pid, Res) ->
+    U2A = case Res of
+        ack -> ?U2AM;
+        nack -> ?U2A
+    end,
+    [?_assertEqual({ok, ?A2U}, erab_fsm:erab_setup_req(Pid, ?U2C)),
+     ?_assertEqual({ok, ?C2U}, erab_fsm:erab_setup_rsp(Pid, ?U2A)),
+     %% E-RAB MODIFY Ind indicates the new (modified) F-TEID to be used
+     %% in the UPF -> Access direction.  The FSM logic indicates the old
+     %% (unmodified) F-TEID to be used in the UPF <- Core direction.
+     ?_assertEqual({ok, ?C2U}, erab_fsm:erab_modify_ind(Pid, ?U2AM)),
+     %% Before getting the Rsp, the U2C F-TEID remains unchanged
+     ?_assertEqual(?U2A, erab_fsm_info(Pid, f_teid_u2a)),
+     %% After getting the Cnf (ACK), the new (modified) U2A F-TEID is used
+     %% After getting the Cnf (NACK), the U2A F-TEID remains unchanged
+     ?_assertEqual(ok, erab_fsm:erab_modify_cnf(Pid, Res)),
+     ?_assertEqual(U2A, erab_fsm_info(Pid, f_teid_u2a)),
+     ?_assertEqual(ok, erab_fsm:shutdown(Pid)),
+     ?_assertNot(erlang:is_process_alive(Pid))].
+
+
+test_erab_modify_ind_ack(Pid) ->
+    test_erab_modify_ind(Pid, ack).
+
+
+test_erab_modify_ind_nack(Pid) ->
+    test_erab_modify_ind(Pid, nack).
+
+
 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)),
diff --git a/test/pfcp_mock.hrl b/test/pfcp_mock.hrl
index 9a0232a..609d5f2 100644
--- a/test/pfcp_mock.hrl
+++ b/test/pfcp_mock.hrl
@@ -7,6 +7,7 @@
 -define(TEID_U2A,   16#0002). %% UPF -> Access

 -define(TEID_U2CM,  16#0f0001). %% UPF -> Core (modified)
+-define(TEID_U2AM,  16#0f0002). %% UPF -> Access (modified)

 -define(ADDR_U2C,   << 16#7f, 16#00, 16#00, 16#01 >>). %% UPF -> Core
 -define(ADDR_C2U,   << 16#7f, 16#00, 16#01, 16#01 >>). %% UPF <- Core
@@ -14,5 +15,6 @@
 -define(ADDR_U2A,   << 16#7f, 16#00, 16#00, 16#02 >>). %% UPF -> Access

 -define(ADDR_U2CM,  << 16#7f, 16#0f, 16#00, 16#01 >>). %% UPF -> Core 
(modified)
+-define(ADDR_U2AM,  << 16#7f, 16#0f, 16#00, 16#02 >>). %% UPF -> Access 
(modified)

 %% vim:set ts=4 sw=4 et:

--
To view, visit https://gerrit.osmocom.org/c/erlang/osmo-s1gw/+/39147?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: I750ada0a5a21edc8bc06d567c8000b6304966474
Gerrit-Change-Number: 39147
Gerrit-PatchSet: 1
Gerrit-Owner: fixeria <[email protected]>

Reply via email to