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


Change subject: Send SAR(DEREGISTRATION) to HSS when all sessions are terminated
......................................................................

Send SAR(DEREGISTRATION) to HSS when all sessions are terminated

Change-Id: I62eba8ef916d52964df4135d1031f3950b6818a2
---
M src/aaa_diameter_s6b.erl
M src/aaa_diameter_s6b_cb.erl
M src/aaa_diameter_swm.erl
M src/aaa_diameter_swx_cb.erl
M src/aaa_ue_fsm.erl
5 files changed, 157 insertions(+), 21 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/erlang/osmo-epdg 
refs/changes/60/35760/1

diff --git a/src/aaa_diameter_s6b.erl b/src/aaa_diameter_s6b.erl
index 2de479c..2792b6a 100644
--- a/src/aaa_diameter_s6b.erl
+++ b/src/aaa_diameter_s6b.erl
@@ -51,7 +51,7 @@
 -export([code_change/3]).
 -export([multimedia_auth_request/6]).
 -export([server_assignment_request/3]).
--export([tx_aa_answer/2]).
+-export([tx_aa_answer/2, tx_st_answer/2]).
 -export([test/0, test/1]).

 %% Diameter Application Definitions
@@ -151,6 +151,10 @@
     % handle_request(AAR) was spawned into its own process, and it's blocked 
waiting for AAA:
     Pid ! {aaa, ResultCode}.

+tx_st_answer(Pid, ResultCode) ->
+    % handle_request(STR) was spawned into its own process, and it's blocked 
waiting for STA:
+    Pid ! {sta, ResultCode}.
+
 result_code_success(2001) -> ok;
 result_code_success(2002) -> ok;
 result_code_success(_) -> invalid_result_code.
diff --git a/src/aaa_diameter_s6b_cb.erl b/src/aaa_diameter_s6b_cb.erl
index b03bce1..339f735 100644
--- a/src/aaa_diameter_s6b_cb.erl
+++ b/src/aaa_diameter_s6b_cb.erl
@@ -86,10 +86,30 @@
     #diameter_caps{origin_host = {OH,_}, origin_realm = {OR,_}} = Caps,
     #'STR'{'Session-Id' = SessionId,
            'Auth-Application-Id' = _AuthAppId,
-           'User-Name' = _UserNameOpt} = Req,
+           'Termination-Cause' = _TermCause,
+           'User-Name' = [UserName]} = Req,
+    Result = aaa_diameter_swm:get_ue_fsm_by_imsi(UserName),
+    case Result of
+    {ok, Pid} ->
+        case aaa_ue_fsm:ev_rx_s6b_str(Pid) of
+        ok ->
+            lager:debug("Waiting for S6b STA~n", []),
+            receive
+                {sta, ResultCode} -> lager:debug("Rx STA with 
ResultCode=~p~n", [ResultCode])
+            end;
+        {ok, DiaRC} when is_integer(DiaRC) ->
+            ResultCode = DiaRC;
+        {error, Err} when is_integer(Err) ->
+            ResultCode = Err;
+        {error, _} ->
+            ResultCode = ?'RULE-FAILURE-CODE_CM_AUTHORIZATION_REJECTED'
+        end;
+    _ -> lager:error("Error looking up FSM for IMSI~n", [UserName]),
+        ResultCode = ?'RULE-FAILURE-CODE_CM_AUTHORIZATION_REJECTED'
+    end,
     % 3GPP TS 29.273 9.2.2.3.2 Session-Termination-Answer (STA) Command:
     Resp = #'STA'{'Session-Id' = SessionId,
-                  'Result-Code' = 2001,
+                  'Result-Code' = ResultCode,
                   'Origin-Host' = OH,
                   'Origin-Realm' = OR},
     lager:info("S6b Tx to ~p: ~p~n", [Caps, Resp]),
diff --git a/src/aaa_diameter_swm.erl b/src/aaa_diameter_swm.erl
index 68aa054..9458383 100644
--- a/src/aaa_diameter_swm.erl
+++ b/src/aaa_diameter_swm.erl
@@ -4,7 +4,7 @@
 -module(aaa_diameter_swm).
 -behaviour(gen_server).

--include_lib("diameter_3gpp_ts29_273_swx.hrl").
+-include_lib("diameter_3gpp_ts29_273.hrl").

 -record(swm_state, {
        table_id, % ets table id,
@@ -22,7 +22,7 @@
 -export([get_ue_fsm_by_imsi/1]).

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

 -define(SERVER, ?MODULE).

@@ -45,6 +45,9 @@
 auth_compl_response(Imsi, Result) ->
        _Result = gen_server:call(?SERVER, {epdg_auth_compl_resp, Imsi, 
Result}).

+session_termination_answer(Imsi, Result) ->
+       _Result = gen_server:call(?SERVER, {sta, Imsi, Result}).
+
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 % Rx from emulated SWm wire:
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -73,7 +76,21 @@
        {noreply, State};

 handle_cast({str, Imsi}, State) ->
-       ok = epdg_diameter_swm:session_termination_answer(Imsi, 2001),
+       Sess = find_swm_session_by_imsi(Imsi, State),
+       case Sess of
+       #swm_session{} ->
+               case aaa_ue_fsm:ev_rx_swm_str(Sess#swm_session.pid) of
+               ok -> ok; % Answering delayed due to SAR+SAA towards HSS.
+               {ok, DiaRC} when is_integer(DiaRC) ->
+                       ok = epdg_diameter_swm:session_termination_answer(Imsi, 
DiaRC);
+               {error, Err} when is_integer(Err) ->
+                       ok = epdg_diameter_swm:session_termination_answer(Imsi, 
Err);
+               {error, _} ->
+                       ok = epdg_diameter_swm:session_termination_answer(Imsi, 
?'RULE-FAILURE-CODE_CM_AUTHORIZATION_REJECTED')
+               end;
+       undefined ->
+               ok = epdg_diameter_swm:session_termination_answer(Imsi, 
?'RULE-FAILURE-CODE_CM_AUTHORIZATION_REJECTED')
+       end,
        {noreply, State};

 handle_cast(Info, S) ->
@@ -102,6 +119,10 @@
        epdg_diameter_swm:auth_compl_response(Imsi, Result),
        {reply, ok, State};

+handle_call({sta, Imsi, DiaRC}, _From, State) ->
+       epdg_diameter_swm:session_termination_answer(Imsi, DiaRC),
+       {reply, ok, State};
+
 handle_call(Request, From, S) ->
        error_logger:error_report(["unknown handle_call", {module, ?MODULE}, 
{request, Request}, {from, From}, {state, S}]),
        {noreply, S}.
diff --git a/src/aaa_diameter_swx_cb.erl b/src/aaa_diameter_swx_cb.erl
index a7b9b7c..472f1d4 100644
--- a/src/aaa_diameter_swx_cb.erl
+++ b/src/aaa_diameter_swx_cb.erl
@@ -71,10 +71,13 @@
     lager:info("SWx Rx MAA ~p: ~p/ Errors ~p ~n", [Peer, Msg, Errors]),
     aaa_ue_fsm:ev_rx_swx_maa(ReqPid, Msg),
     {ok, Msg};
-handle_answer(#diameter_packet{msg = Msg, errors = Errors}, _Request, 
_SvcName, Peer, ReqPid) when is_record(Msg, 'SAA')  ->
+handle_answer(#diameter_packet{msg = Msg, errors = Errors}, Request, _SvcName, 
Peer, ReqPid) when is_record(Msg, 'SAA')  ->
     lager:info("SWx Rx SAA ~p: ~p/ Errors ~p ~n", [Peer, Msg, Errors]),
+    % Recover fields from originating request:
+    #'SAR'{'Server-Assignment-Type' = SAType} = Request,
+    % Retrieve fields from answer:
     #'SAA'{'Result-Code' = [ResultCode]} = Msg,
-    aaa_ue_fsm:ev_rx_swx_saa(ReqPid, ResultCode),
+    aaa_ue_fsm:ev_rx_swx_saa(ReqPid, {SAType, ResultCode}),
     {ok, Msg}.
 handle_answer(#diameter_packet{msg = Msg, errors = []}, _Request, _SvcName, 
Peer) ->
     lager:info("SWx Rx ~p: ~p~n", [Peer, Msg]),
diff --git a/src/aaa_ue_fsm.erl b/src/aaa_ue_fsm.erl
index e214540..c043cdb 100644
--- a/src/aaa_ue_fsm.erl
+++ b/src/aaa_ue_fsm.erl
@@ -35,15 +35,18 @@
 -define(NAME, aaa_ue_fsm).

 -include_lib("diameter/include/diameter.hrl").
+-include_lib("diameter_3gpp_ts29_229.hrl").
 -include_lib("diameter_3gpp_ts29_273_s6b.hrl").

 -export([start_link/1]).
 -export([init/1,callback_mode/0,terminate/3]).
--export([ev_swm_auth_req/1, ev_swm_auth_compl/2, ev_rx_swx_maa/2, 
ev_rx_swx_saa/2, ev_rx_s6b_aar/2]).
+-export([ev_swm_auth_req/1, ev_swm_auth_compl/2, ev_rx_swm_str/1, 
ev_rx_swx_maa/2, ev_rx_swx_saa/2,
+         ev_rx_s6b_aar/2, ev_rx_s6b_str/1]).
 -export([state_new/3, state_wait_swx_maa/3, state_wait_swx_saa/3, 
state_authenticated/3, state_authenticated_wait_swx_saa/3]).

 -record(ue_fsm_data, {
         imsi             = unknown :: binary(),
+        apn                        :: string(),
         epdg_sess_active = false   :: boolean(),
         pgw_sess_active  = false   :: boolean(),
         s6b_resp_pid               :: pid()
@@ -72,6 +75,15 @@
                 {error, Err}
         end.

+ev_rx_swm_str(Pid) ->
+        lager:info("ue_fsm ev_rx_swm_str~n", []),
+        try
+                gen_statem:call(Pid, rx_swm_str)
+        catch
+        exit:Err ->
+                {error, Err}
+        end.
+
 ev_rx_swx_maa(Pid, MAA) ->
         lager:info("ue_fsm ev_rx_swx_maa~n", []),
         try
@@ -81,10 +93,10 @@
                 {error, Err}
         end.

-ev_rx_swx_saa(Pid, ResultCode) ->
+ev_rx_swx_saa(Pid, {SAType, ResultCode}) ->
         lager:info("ue_fsm ev_rx_swx_saa~n", []),
         try
-                gen_statem:call(Pid, {rx_swx_saa, ResultCode})
+                gen_statem:call(Pid, {rx_swx_saa, SAType, ResultCode})
         catch
         exit:Err ->
                 {error, Err}
@@ -99,6 +111,15 @@
                 {error, Err}
         end.

+ev_rx_s6b_str(Pid) ->
+        lager:info("ue_fsm ev_rx_s6b_str: ~p~n", []),
+        try
+                gen_statem:call(Pid, rx_s6b_str)
+        catch
+        exit:Err ->
+                {error, Err}
+        end.
+
 %% ------------------------------------------------------------------
 %% Internal helpers
 %% ------------------------------------------------------------------
@@ -151,9 +172,9 @@
 state_wait_swx_saa(enter, _OldState, Data) ->
         {keep_state, Data};

-state_wait_swx_saa({call, From}, {rx_swx_saa, SAA}, Data) ->
+state_wait_swx_saa({call, From}, {rx_swx_saa, _SAType, ResultCode}, Data) ->
         lager:info("ue_fsm state_wait_swx_saa event=rx_swx_saa, ~p~n", [Data]),
-        aaa_diameter_swm:auth_compl_response(Data#ue_fsm_data.imsi, {ok, SAA}),
+        aaa_diameter_swm:auth_compl_response(Data#ue_fsm_data.imsi, {ok, 
ResultCode}),
         % TODO: don't transit if SAS returned error code.
         {next_state, state_authenticated, Data, [{reply,From,ok}]}.

@@ -164,12 +185,57 @@

 state_authenticated({call, {Pid, _Tag} = From}, {rx_s6b_aar, Apn}, Data) ->
         lager:info("ue_fsm state_authenticated event=rx_s6b_aar Apn=~p, ~p~n", 
[Apn, Data]),
-        case aaa_diameter_swx:server_assignment_request(Data#ue_fsm_data.imsi, 
1, Apn) of
-        ok ->   Data1 = Data#ue_fsm_data{s6b_resp_pid = Pid},
+        case aaa_diameter_swx:server_assignment_request(Data#ue_fsm_data.imsi,
+                                                        
?'DIAMETER_CX_SERVER-ASSIGNMENT-TYPE_REGISTRATION',
+                                                        Apn) of
+        ok ->   Data1 = Data#ue_fsm_data{s6b_resp_pid = Pid, apn = Apn},
                 {next_state, state_authenticated_wait_swx_saa, Data1, 
[{reply,From,ok}]};
         {error, Err} -> {keep_state, Data, [{reply,From,{error, Err}}]}
         end;

+state_authenticated({call, From}, rx_swm_str, Data) ->
+        lager:info("ue_fsm state_authenticated event=rx_swm_str, ~p~n", 
[Data]),
+        case {Data#ue_fsm_data.epdg_sess_active, 
Data#ue_fsm_data.pgw_sess_active} of
+        {false, _} -> %% The SWm session is not active...
+                DiaRC = 5002, %% UNKNOWN_SESSION_ID
+                {keep_state, Data, [{reply,From,{error, DiaRC}}]};
+        {true, true} -> %% The other session is still active, no need to send 
SAR Type=USER_DEREGISTRATION
+                lager:info("ue_fsm state_authenticated event=rx_swn_str: PGW 
session still active, skip updating the HSS~n", []),
+                Data1 = Data#ue_fsm_data{epdg_sess_active = false},
+                {keep_state, Data1, [{reply,From,{ok, 2001}}]};
+        {true, false} -> %% All sessions will now be gone, trigger SAR 
Type=USER_DEREGISTRATION
+                case 
aaa_diameter_swx:server_assignment_request(Data#ue_fsm_data.imsi,
+                                                                
?'DIAMETER_CX_SERVER-ASSIGNMENT-TYPE_USER_DEREGISTRATION',
+                                                                
Data#ue_fsm_data.apn) of
+                ok ->   {next_state, state_authenticated_wait_swx_saa, Data, 
[{reply,From,ok}]};
+                {error, _Err} ->
+                        DiaRC = 5002, %% UNKNOWN_SESSION_ID
+                        {keep_state, Data, [{reply,From,{error, DiaRC}}]}
+                end
+        end;
+
+state_authenticated({call, {Pid, _Tag} = From}, rx_s6b_str, Data) ->
+        lager:info("ue_fsm state_authenticated event=rx_s6b_str, ~p~n", 
[Data]),
+        case {Data#ue_fsm_data.pgw_sess_active, 
Data#ue_fsm_data.epdg_sess_active} of
+        {false, _} -> %% The S6b session is not active...
+                DiaRC = 5002, %% UNKNOWN_SESSION_ID
+                {keep_state, Data, [{reply,From,{error, DiaRC}}]};
+        {true, true} -> %% The other session is still active, no need to send 
SAR Type=USER_DEREGISTRATION
+                lager:info("ue_fsm state_authenticated event=rx_s6b_str: ePDG 
session still active, skip updating the HSS~n", []),
+                Data1 = Data#ue_fsm_data{pgw_sess_active = false},
+                {keep_state, Data1, [{reply,From,{ok, 2001}}]};
+        {true, false} -> %% All sessions will now be gone, trigger SAR 
Type=USER_DEREGISTRATION
+                case 
aaa_diameter_swx:server_assignment_request(Data#ue_fsm_data.imsi,
+                                                                
?'DIAMETER_CX_SERVER-ASSIGNMENT-TYPE_USER_DEREGISTRATION',
+                                                                
Data#ue_fsm_data.apn) of
+                ok ->   Data1 = Data#ue_fsm_data{s6b_resp_pid = Pid},
+                        {next_state, state_authenticated_wait_swx_saa, Data1, 
[{reply,From,ok}]};
+                {error, _Err} ->
+                        DiaRC = 5002, %% UNKNOWN_SESSION_ID
+                        {keep_state, Data, [{reply,From,{error, DiaRC}}]}
+                end
+        end;
+
 state_authenticated({call, From}, _Whatever, Data) ->
         lager:info("ue_fsm state_authenticated event=purge_ms_request, ~p~n", 
[Data]),
         {keep_state, Data, [{reply,From,ok}]}.
@@ -177,9 +243,22 @@
 state_authenticated_wait_swx_saa(enter, _OldState, Data) ->
         {keep_state, Data};

-state_authenticated_wait_swx_saa({call, From}, {rx_swx_saa, ResultCode}, Data) 
->
-        lager:info("ue_fsm state_authenticated_wait_swx_saa event=rx_swx_saa 
ResulCode=~p, ~p~n", [ResultCode, Data]),
-        aaa_diameter_s6b:tx_aa_answer(Data#ue_fsm_data.s6b_resp_pid, 
ResultCode),
-        Data1 = Data#ue_fsm_data{s6b_resp_pid = undefined},
-        {next_state, state_authenticated, Data1, [{reply,From,ok}]}.
-
+state_authenticated_wait_swx_saa({call, From}, {rx_swx_saa, SAType, 
ResultCode}, Data) ->
+        lager:info("ue_fsm state_authenticated_wait_swx_saa event=rx_swx_saa 
SAType=~p ResulCode=~p, ~p~n", [SAType, ResultCode, Data]),
+        case SAType of
+        ?'DIAMETER_CX_SERVER-ASSIGNMENT-TYPE_REGISTRATION' ->
+                aaa_diameter_s6b:tx_aa_answer(Data#ue_fsm_data.s6b_resp_pid, 
ResultCode),
+                Data1 = Data#ue_fsm_data{pgw_sess_active = true, s6b_resp_pid 
= undefined},
+                {next_state, state_authenticated, Data1, [{reply,From,ok}]};
+        ?'DIAMETER_CX_SERVER-ASSIGNMENT-TYPE_USER_DEREGISTRATION' ->
+                case Data#ue_fsm_data.s6b_resp_pid of
+                undefined -> %% SWm initiated
+                        
aaa_diameter_swm:session_termination_answer(Data#ue_fsm_data.imsi, ResultCode),
+                        Data1 = Data#ue_fsm_data{epdg_sess_active = false},
+                        {next_state, state_new, Data1, [{reply,From,ok}]};
+                _ -> %% S6b initiated
+                        
aaa_diameter_s6b:tx_st_answer(Data#ue_fsm_data.s6b_resp_pid, ResultCode),
+                        Data1 = Data#ue_fsm_data{pgw_sess_active = false, 
s6b_resp_pid = undefined},
+                        {next_state, state_new, Data1, [{reply,From,ok}]}
+                end
+        end.
\ No newline at end of file

--
To view, visit https://gerrit.osmocom.org/c/erlang/osmo-epdg/+/35760?usp=email
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.osmocom.org/settings

Gerrit-Project: erlang/osmo-epdg
Gerrit-Branch: master
Gerrit-Change-Id: I62eba8ef916d52964df4135d1031f3950b6818a2
Gerrit-Change-Number: 35760
Gerrit-PatchSet: 1
Gerrit-Owner: pespin <[email protected]>
Gerrit-MessageType: newchange

Reply via email to