pespin has submitted this change. ( https://gerrit.osmocom.org/c/erlang/osmo-epdg/+/35691?usp=email )
Change subject: Make SWm MAR+MAA asynchronous ......................................................................
Make SWm MAR+MAA asynchronous
Change-Id: Ie7762843e463f404cd4f0c5fcf03a9566dcf173b --- M src/aaa_diameter_swm.erl M src/epdg_diameter_swm.erl M src/epdg_ue_fsm.erl 3 files changed, 108 insertions(+), 22 deletions(-)
Approvals: laforge: Looks good to me, but someone else must approve pespin: Looks good to me, approved Jenkins Builder: Verified
diff --git a/src/aaa_diameter_swm.erl b/src/aaa_diameter_swm.erl index 6aef1b2..c8ae250 100644 --- a/src/aaa_diameter_swm.erl +++ b/src/aaa_diameter_swm.erl @@ -29,26 +29,31 @@
auth_request(Imsi) -> - gen_server:call(?SERVER, {epdg_auth_req, Imsi}). + gen_server:cast(?SERVER, {epdg_auth_req, Imsi}).
-handle_call({epdg_auth_req, Imsi}, From, State) -> +handle_cast({epdg_auth_req, Imsi}, State) -> % request the diameter code for a tuple CKey = [], IntegrityKey = [], Result = aaa_diameter_swx:multimedia_auth_request(Imsi, 1, "EAP-AKA", 1, CKey, IntegrityKey), case Result of - {ok, Mar} -> {reply, {ok, Mar}, State}; - {error, Err} -> {reply, {error, Err}, State}; - {_, _} -> {reply, {error, unknown}, State} - end. + {ok, _MAA} -> epdg_diameter_swm:auth_response(Imsi, Result); + {error, Err} -> epdg_diameter_swm:auth_response(Imsi, Result); + _ -> epdg_diameter_swm:auth_response(Imsi, {error, unknown}) + end, + {noreply, State};
handle_cast(Info, S) -> error_logger:error_report(["unknown handle_cast", {module, ?MODULE}, {info, Info}, {state, S}]), {noreply, S}. + handle_info(Info, S) -> error_logger:error_report(["unknown handle_info", {module, ?MODULE}, {info, Info}, {state, S}]), {noreply, S}.
+handle_call(Request, From, S) -> + error_logger:error_report(["unknown handle_call", {module, ?MODULE}, {request, Request}, {from, From}, {state, S}]), + {noreply, S}.
stop() -> gen_server:call(?MODULE, stop). diff --git a/src/epdg_diameter_swm.erl b/src/epdg_diameter_swm.erl index 9c3145b..dbb764f 100644 --- a/src/epdg_diameter_swm.erl +++ b/src/epdg_diameter_swm.erl @@ -7,13 +7,20 @@ -include_lib("diameter_3gpp_ts29_273_swx.hrl").
-record(swm_state, { + sessions = sets:new() }).
+-record(swm_session, { + imsi :: binary(), + pid :: pid() + }). + -export([start_link/0]). -export([init/1, handle_call/3, handle_cast/2, handle_info/2]). -export([code_change/3, terminate/2]).
-export[(auth_request/1)]. +-export[(auth_response/2)].
-define(SERVER, ?MODULE).
@@ -27,17 +34,31 @@
auth_request(Imsi) -> - gen_server:call(?SERVER, {epdg_auth_req, Imsi}). - -handle_call({epdg_auth_req, Imsi}, _From, State) -> - % we yet don't implement the Diameter SWm interface on the wire, we process the call internally: - Result = aaa_diameter_swm:auth_request(Imsi), + Result = gen_server:call(?SERVER, {epdg_auth_req, Imsi}), case Result of - {ok, Mar} -> {reply, {ok, Mar}, State}; - {error, Err} -> {reply, {error, Err}, State}; - {_, _} -> {reply, {error, unknown}, State} + {ok, _Mar} -> + epdg_ue_fsm:received_swm_auth_response(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: + {_Sess, State1} = find_or_new_swm_session(Imsi, Pid, State0), + ok = aaa_diameter_swm:auth_request(Imsi), + {reply, ok, State1}. + +handle_cast({epdg_auth_resp, Imsi, Result}, State) -> + Sess = find_swm_session_by_imsi(Imsi, State), + case Sess of + #swm_session{imsi = Imsi} -> + epdg_ue_fsm:received_swm_auth_response(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}. @@ -54,3 +75,36 @@
terminate(Reason, _S) -> lager:info("terminating ~p with reason ~p~n", [?MODULE, Reason]). + +%% Emulation from the wire (DIAMETER SWm), called from internal AAA Server: +auth_response(Imsi, Result) -> + ok = gen_server:cast(?SERVER, {epdg_auth_resp, Imsi, Result}). + +%% ------------------------------------------------------------------ +%% Internal Function Definitions +%% ------------------------------------------------------------------ + +new_swm_session(Imsi, Pid, State) -> + Sess = #swm_session{imsi = Imsi, + pid = Pid + }, + NewSt = State#swm_state{sessions = sets:add_element(Sess, State#swm_state.sessions)}, + {Sess, NewSt}. + +% returns Sess if found, undefined it not +find_swm_session_by_imsi(Imsi, State) -> + sets:fold( + fun(SessIt = #swm_session{imsi = Imsi}, _AccIn) -> SessIt; + (_, AccIn) -> AccIn + end, + undefined, + State#swm_state.sessions). + +find_or_new_swm_session(Imsi, Pid, State) -> + Sess = find_swm_session_by_imsi(Imsi, State), + case Sess of + #swm_session{imsi = Imsi} -> + {Sess, State}; + undefined -> + new_swm_session(Imsi, Pid, State) + end. \ No newline at end of file diff --git a/src/epdg_ue_fsm.erl b/src/epdg_ue_fsm.erl index 787689d..9d20a73 100644 --- a/src/epdg_ue_fsm.erl +++ b/src/epdg_ue_fsm.erl @@ -40,8 +40,9 @@ -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]). -export([received_gtpc_create_session_response/2, received_gtpc_delete_session_response/2]). --export([state_new/3,state_authenticated/3, state_wait_delete_session_resp/3]). +-export([state_new/3, state_wait_auth_resp/3, state_authenticated/3, state_wait_delete_session_resp/3]).
-record(ue_fsm_data, { imsi @@ -88,6 +89,15 @@ {error, Err} end.
+received_swm_auth_response(Pid, Result) -> + lager:info("ue_fsm received_swm_auth_response ~p~n", [Result]), + try + gen_statem:call(Pid, {received_swm_auth_response, 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 @@ -128,19 +138,27 @@
state_new({call, From}, auth_request, Data) -> lager:info("ue_fsm state_new event=auth_request, ~p~n", [Data]), - Auth = epdg_diameter_swm:auth_request(Data#ue_fsm_data.imsi), - gsup_server:auth_response(Data#ue_fsm_data.imsi, Auth), - case Auth of - {ok, _} -> - {next_state, state_authenticated, Data, [{reply,From,ok}]}; - {error, Err} -> - {stop_and_reply, Err, Data, [{reply,From,{error,Err}}]} + case epdg_diameter_swm:auth_request(Data#ue_fsm_data.imsi) of + ok -> {next_state, state_wait_auth_resp, Data, [{reply,From,ok}]}; + {error, Err} -> {stop_and_reply, Err, Data, [{reply,From,{error,Err}}]} end;
state_new({call, From}, purge_ms_request, Data) -> 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({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), + case Auth of + {ok, _} -> + {next_state, state_authenticated, Data, [{reply,From,ok}]}; + {error, Err} -> + {next_state, state_new, Data, [{reply,From,{error,Err}}]}; + _ -> + {next_state, state_new, Data, [{reply,From,{error,unknown}}]} + end. + state_authenticated({call, From}, lu_request, Data) -> lager:info("ue_fsm state_authenticated event=lu_request, ~p~n", [Data]), Result = aaa_diameter_swx:server_assignment_request(Data#ue_fsm_data.imsi, 1, "internet"),