pespin submitted this change.

View Change


Approvals: Jenkins Builder: Verified pespin: Looks good to me, approved laforge: Looks good to me, but someone else must approve
UE-initiated detach: Do STR+STA ePDG<->AAA-Server

Change-Id: I6f7554e24b26bfe191b28b56904bc8432690625d
---
M src/aaa_diameter_swm.erl
M src/epdg_diameter_swm.erl
M src/epdg_ue_fsm.erl
3 files changed, 110 insertions(+), 10 deletions(-)

diff --git a/src/aaa_diameter_swm.erl b/src/aaa_diameter_swm.erl
index f99ae91..a3e5132 100644
--- a/src/aaa_diameter_swm.erl
+++ b/src/aaa_diameter_swm.erl
@@ -14,7 +14,7 @@
-export([init/1, handle_call/3, handle_cast/2, handle_info/2]).
-export([code_change/3, terminate/2]).

--export([auth_request/1, auth_compl_request/2]).
+-export([auth_request/1, auth_compl_request/2, session_termination_request/1]).

-define(SERVER, ?MODULE).

@@ -32,6 +32,9 @@
auth_compl_request(Imsi, Apn) ->
gen_server:cast(?SERVER, {epdg_auth_compl_req, Imsi, Apn}).

+session_termination_request(Imsi) ->
+ gen_server:cast(?SERVER, {str, Imsi}).
+
handle_cast({epdg_auth_req, Imsi}, State) ->
% request the diameter code for a tuple
CKey = [],
@@ -54,6 +57,10 @@
end,
{noreply, State};

+handle_cast({str, Imsi}, State) ->
+ ok = epdg_diameter_swm:session_termination_answer(Imsi, 2001),
+ {noreply, State};
+
handle_cast(Info, S) ->
error_logger:error_report(["unknown handle_cast", {module, ?MODULE}, {info, Info}, {state, S}]),
{noreply, S}.
diff --git a/src/epdg_diameter_swm.erl b/src/epdg_diameter_swm.erl
index 7c2043d..bfb8f2d 100644
--- a/src/epdg_diameter_swm.erl
+++ b/src/epdg_diameter_swm.erl
@@ -19,8 +19,8 @@
-export([init/1, handle_call/3, handle_cast/2, handle_info/2]).
-export([code_change/3, terminate/2]).

--export([auth_request/1, auth_compl_request/2]).
--export([auth_response/2, auth_compl_response/2]).
+-export([auth_request/1, auth_compl_request/2, session_termination_request/1]).
+-export([auth_response/2, auth_compl_response/2, session_termination_answer/2]).

-define(SERVER, ?MODULE).

@@ -52,6 +52,15 @@
_ -> Result
end.

+% 3GPP TS 29.273 7.1.2.3
+session_termination_request(Imsi) ->
+ Result = gen_server:call(?SERVER, {str, Imsi}),
+ case Result of
+ {ok, _Mar} ->
+ epdg_ue_fsm:received_swm_session_terminate_answer(self(), Result),
+ ok;
+ _ -> Result
+ end.

handle_call({epdg_auth_req, Imsi}, {Pid, _Tag} = _From, State0) ->
% we yet don't implement the Diameter SWm interface on the wire, we process the call internally:
@@ -68,6 +77,17 @@
undefined ->
Reply = {error,unknown_imsi}
end,
+ {reply, Reply, State};
+
+handle_call({str, Imsi}, _From, State) ->
+ % we yet don't implement the Diameter SWm interface on the wire, we process the call internally:
+ Sess = find_swm_session_by_imsi(Imsi, State),
+ case Sess of
+ #swm_session{imsi = Imsi} ->
+ Reply = aaa_diameter_swm:session_termination_request(Imsi);
+ undefined ->
+ Reply = {error,unknown_imsi}
+ end,
{reply, Reply, State}.

handle_cast({epdg_auth_resp, Imsi, Result}, State) ->
@@ -90,6 +110,16 @@
end,
{noreply, State};

+handle_cast({sta, Imsi, Result}, State) ->
+ Sess = find_swm_session_by_imsi(Imsi, State),
+ case Sess of
+ #swm_session{imsi = Imsi} ->
+ epdg_ue_fsm:received_swm_session_termination_answer(Sess#swm_session.pid, Result);
+ undefined ->
+ error_logger:error_report(["unknown swm_session", {module, ?MODULE}, {imsi, Imsi}, {state, State}])
+ end,
+ {noreply, State};
+
handle_cast(Info, S) ->
error_logger:error_report(["unknown handle_cast", {module, ?MODULE}, {info, Info}, {state, S}]),
{noreply, S}.
@@ -116,6 +146,10 @@
auth_compl_response(Imsi, Result) ->
ok = gen_server:cast(?SERVER, {epdg_auth_compl_resp, Imsi, Result}).

+% Rx SWm Diameter STA:
+session_termination_answer(Imsi, Result) ->
+ ok = gen_server:cast(?SERVER, {sta, Imsi, Result}).
+
%% ------------------------------------------------------------------
%% Internal Function Definitions
%% ------------------------------------------------------------------
diff --git a/src/epdg_ue_fsm.erl b/src/epdg_ue_fsm.erl
index 1d934c5..3e9d1be 100644
--- a/src/epdg_ue_fsm.erl
+++ b/src/epdg_ue_fsm.erl
@@ -40,13 +40,15 @@
-export([start_link/1]).
-export([init/1,callback_mode/0,terminate/3]).
-export([auth_request/1, lu_request/1, tunnel_request/1, purge_ms_request/1]).
--export([received_swm_auth_response/2, received_swm_auth_compl_response/2]).
+-export([received_swm_auth_response/2, received_swm_auth_compl_response/2, received_swm_session_termination_answer/2]).
-export([received_gtpc_create_session_response/2, received_gtpc_delete_session_response/2]).
--export([state_new/3, state_wait_auth_resp/3, state_authenticating/3, state_authenticated/3, state_wait_delete_session_resp/3]).
+-export([state_new/3, state_wait_auth_resp/3, state_authenticating/3, state_authenticated/3,
+ state_wait_delete_session_resp/3, state_wait_swm_session_termination_answer/3]).

-record(ue_fsm_data, {
imsi,
- apn = "internet" :: string()
+ apn = "internet" :: string(),
+ tear_down_gsup_cause = 0 :: integer()
}).

start_link(Imsi) ->
@@ -108,6 +110,15 @@
{error, Err}
end.

+received_swm_session_termination_answer(Pid, Result) ->
+ lager:info("ue_fsm received_swm_session_termination_answer ~p~n", [Result]),
+ try
+ gen_statem:call(Pid, {received_swm_sta, Result})
+ catch
+ exit:Err ->
+ {error, Err}
+ end.
+
received_gtpc_create_session_response(Pid, Msg) ->
lager:info("ue_fsm received_gtpc_create_session_response ~p~n", [Msg]),
try
@@ -140,12 +151,15 @@
{ok, state_new, Data}.

callback_mode() ->
- state_functions.
+ [state_functions, state_enter].

terminate(Reason, State, Data) ->
lager:info("terminating ~p with reason ~p state=~p, ~p~n", [?MODULE, Reason, State, Data]),
ok.

+state_new(enter, _OldState, Data) ->
+ {keep_state, Data};
+
state_new({call, From}, auth_request, Data) ->
lager:info("ue_fsm state_new event=auth_request, ~p~n", [Data]),
case epdg_diameter_swm:auth_request(Data#ue_fsm_data.imsi) of
@@ -157,6 +171,9 @@
lager:info("ue_fsm state_new event=purge_ms_request, ~p~n", [Data]),
{stop_and_reply, purge_ms_request, Data, [{reply,From,ok}]}.

+state_wait_auth_resp(enter, _OldState, Data) ->
+ {keep_state, Data};
+
state_wait_auth_resp({call, From}, {received_swm_auth_response, Auth}, Data) ->
lager:info("ue_fsm state_wait_auth_resp event=received_swm_auth_response, ~p~n", [Data]),
gsup_server:auth_response(Data#ue_fsm_data.imsi, Auth),
@@ -169,6 +186,9 @@
{next_state, state_new, Data, [{reply,From,{error,unknown}}]}
end.

+state_authenticating(enter, _OldState, Data) ->
+ {keep_state, Data};
+
state_authenticating({call, From}, lu_request, Data) ->
lager:info("ue_fsm state_authenticating event=lu_request, ~p~n", [Data]),
% Rx "GSUP CEAI LU Req" is our way of saying Rx "Swm Diameter-EAP REQ (DER) with EAP AVP containing successuful auth":
@@ -191,6 +211,9 @@
gsup_server:lu_response(Data#ue_fsm_data.imsi, Ret),
{next_state, state_authenticated, Data, [{reply,From,Ret}]}.

+state_authenticated(enter, _OldState, Data) ->
+ {keep_state, Data};
+
state_authenticated({call, From}, tunnel_request, Data) ->
lager:info("ue_fsm state_authenticated event=tunnel_request, ~p~n", [Data]),
epdg_gtpc_s2b:create_session_req(Data#ue_fsm_data.imsi),
@@ -216,6 +239,9 @@
lager:error("ue_fsm state_authenticated: Unexpected cast event, ~p~n", [Data]),
{keep_state, Data}.

+state_wait_delete_session_resp(enter, _OldState, Data) ->
+ {keep_state, Data};
+
state_wait_delete_session_resp({call, From}, {received_gtpc_delete_session_response, _Resp = #gtp{version = v2, type = delete_session_response, ie = IEs}}, Data) ->
lager:info("ue_fsm state_wait_delete_session_resp event=received_gtpc_delete_session_response, ~p~n", [Data]),
#{{v2_cause,0} := CauseIE} = IEs,
@@ -223,11 +249,35 @@
GsupCause = conv:cause_gtp2gsup(GtpCause),
lager:debug("Cause: GTP_atom=~p -> GTP_int=~p -> GSUP_int=~p~n", [CauseIE#v2_cause.v2_cause, GtpCause, GsupCause]),
case GsupCause of
- 0 -> gsup_server:purge_ms_response(Data#ue_fsm_data.imsi, ok);
- _ -> gsup_server:purge_ms_response(Data#ue_fsm_data.imsi, {error, GsupCause})
+ 0 -> Data1 = Data;
+ _ -> Data1 = Data#ue_fsm_data{tear_down_gsup_cause = GsupCause}
+ end,
+ {next_state, state_wait_swm_session_termination_answer, Data1, [{reply,From,ok}]};
+
+state_wait_delete_session_resp({call, From}, Event, Data) ->
+ lager:error("ue_fsm state_wait_delete_session_resp: Unexpected call event ~p, ~p~n", [Event, Data]),
+ {keep_state, Data, [{reply,From,{error,unexpected_event}}]}.
+
+state_wait_swm_session_termination_answer(enter, _OldState, Data) ->
+ % TODO: Send STR towards AAA-Server
+ % % 3GPP TS 29.273 7.1.2.3
+ lager:info("ue_fsm state_wait_swm_session_termination_answer event=enter, ~p~n", [Data]),
+ case epdg_diameter_swm:session_termination_request(Data#ue_fsm_data.imsi) of
+ ok -> {keep_state, Data};
+ {error, _Err} ->
+ gsup_server:purge_ms_response(Data#ue_fsm_data.imsi, {error, ?GSUP_CAUSE_NET_FAIL}),
+ {keep_state, Data}
+ end;
+
+state_wait_swm_session_termination_answer({call, From}, {received_swm_sta, DiaResultCode}, Data) ->
+ lager:info("ue_fsm state_wait_swm_session_termination_answer event=received_swm_sta, ~p~n", [Data]),
+ case {DiaResultCode, Data#ue_fsm_data.tear_down_gsup_cause} of
+ {2001, 0} -> gsup_server:purge_ms_response(Data#ue_fsm_data.imsi, ok);
+ {2001, _} -> gsup_server:purge_ms_response(Data#ue_fsm_data.imsi, {error, Data#ue_fsm_data.tear_down_gsup_cause});
+ _ -> gsup_server:purge_ms_response(Data#ue_fsm_data.imsi, {error, ?GSUP_CAUSE_NET_FAIL})
end,
{keep_state, Data, [{reply,From,ok}]};

-state_wait_delete_session_resp({call, From}, Event, Data) ->
+state_wait_swm_session_termination_answer({call, From}, Event, Data) ->
lager:error("ue_fsm state_wait_delete_session_resp: Unexpected call event ~p, ~p~n", [Event, Data]),
{keep_state, Data, [{reply,From,{error,unexpected_event}}]}.

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

Gerrit-Project: erlang/osmo-epdg
Gerrit-Branch: master
Gerrit-Change-Id: I6f7554e24b26bfe191b28b56904bc8432690625d
Gerrit-Change-Number: 35737
Gerrit-PatchSet: 1
Gerrit-Owner: pespin <pespin@sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: laforge <laforge@osmocom.org>
Gerrit-Reviewer: pespin <pespin@sysmocom.de>
Gerrit-MessageType: merged