pespin submitted this change.

View Change


Approvals: laforge: Looks good to me, but someone else must approve pespin: Looks good to me, approved Jenkins Builder: Verified
Make Auth Compl procedure more similar to specs

Properly document our LU Request message matching the 2nd DER in usual
3GPP architecture, which should contain the Auth RES from the MS and be
forwarded up to the AAA-Server.
In our architecture, the auth is handled earlier, in strongswan (part of
ePDG node), hence why our LU Request contains no Auth RES info, and it's
only signalled by strongswan to osmo-epdg to signal the auth completed
successfuly.
Make the handling of LU Req and events triggered by it asynchronous and
clean up a bit some related code paths and states.

Change-Id: I480c110deeb04abf1ff19147a70e10be9cbafae8
---
M src/aaa_diameter_s6b_cb.erl
M src/aaa_diameter_swm.erl
M src/epdg_diameter_swm.erl
M src/epdg_ue_fsm.erl
M src/gsup_server.erl
5 files changed, 109 insertions(+), 21 deletions(-)

diff --git a/src/aaa_diameter_s6b_cb.erl b/src/aaa_diameter_s6b_cb.erl
index 8651383..ccfcaff 100644
--- a/src/aaa_diameter_s6b_cb.erl
+++ b/src/aaa_diameter_s6b_cb.erl
@@ -57,8 +57,9 @@
#'AAR'{'Session-Id' = SessionId,
'Auth-Application-Id' = AuthAppId,
'Auth-Request-Type' = AuthReqType,
- 'User-Name' = UserName} = Req,
- Result = aaa_diameter_swx:server_assignment_request(UserName, 1, "internet"),
+ 'User-Name' = [UserName],
+ 'Service-Selection' = [Apn]} = Req,
+ Result = aaa_diameter_swx:server_assignment_request(UserName, 1, Apn),
case Result of
{ok, _} ->
ResultCode = 2001;
diff --git a/src/aaa_diameter_swm.erl b/src/aaa_diameter_swm.erl
index c8ae250..f99ae91 100644
--- a/src/aaa_diameter_swm.erl
+++ b/src/aaa_diameter_swm.erl
@@ -14,12 +14,10 @@
-export([init/1, handle_call/3, handle_cast/2, handle_info/2]).
-export([code_change/3, terminate/2]).

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

-define(SERVER, ?MODULE).

-% The ets table contains only IMSIs
-
start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).

@@ -31,6 +29,9 @@
auth_request(Imsi) ->
gen_server:cast(?SERVER, {epdg_auth_req, Imsi}).

+auth_compl_request(Imsi, Apn) ->
+ gen_server:cast(?SERVER, {epdg_auth_compl_req, Imsi, Apn}).
+
handle_cast({epdg_auth_req, Imsi}, State) ->
% request the diameter code for a tuple
CKey = [],
@@ -38,11 +39,21 @@
Result = aaa_diameter_swx:multimedia_auth_request(Imsi, 1, "EAP-AKA", 1, CKey, IntegrityKey),
case Result of
{ok, _MAA} -> epdg_diameter_swm:auth_response(Imsi, Result);
- {error, Err} -> 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({epdg_auth_compl_req, Imsi, Apn}, State) ->
+ % request the diameter code for a tuple
+ Result = aaa_diameter_swx:server_assignment_request(Imsi, 1, Apn),
+ case Result of
+ {ok, _SAA} -> epdg_diameter_swm:auth_compl_response(Imsi, Result);
+ {error, _Err} -> epdg_diameter_swm:auth_compl_response(Imsi, Result);
+ _ -> epdg_diameter_swm:auth_compl_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}.
diff --git a/src/epdg_diameter_swm.erl b/src/epdg_diameter_swm.erl
index dbb764f..7c2043d 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)].
--export[(auth_response/2)].
+-export([auth_request/1, auth_compl_request/2]).
+-export([auth_response/2, auth_compl_response/2]).

-define(SERVER, ?MODULE).

@@ -42,12 +42,33 @@
_ -> Result
end.

+% Rx "GSUP CEAI LU Req" is our way of saying Rx "Swm Diameter-EAP REQ (DER) with EAP AVP containing successuful auth":
+auth_compl_request(Imsi, Apn) ->
+ Result = gen_server:call(?SERVER, {epdg_auth_compl_req, Imsi, Apn}),
+ case Result of
+ {ok, _Mar} ->
+ epdg_ue_fsm:received_swm_auth_compl_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}.
+ {reply, ok, State1};
+
+handle_call({epdg_auth_compl_req, Imsi, Apn}, _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:auth_compl_request(Imsi, Apn);
+ undefined ->
+ Reply = {error,unknown_imsi}
+ end,
+ {reply, Reply, State}.

handle_cast({epdg_auth_resp, Imsi, Result}, State) ->
Sess = find_swm_session_by_imsi(Imsi, State),
@@ -59,6 +80,16 @@
end,
{noreply, State};

+handle_cast({epdg_auth_compl_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_compl_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}.
@@ -80,6 +111,11 @@
auth_response(Imsi, Result) ->
ok = gen_server:cast(?SERVER, {epdg_auth_resp, Imsi, Result}).

+%Rx Swm Diameter-EAP Answer (DEA) containing APN-Configuration, triggered by
+%earlier Tx DER EAP AVP containing successuful auth":
+auth_compl_response(Imsi, Result) ->
+ ok = gen_server:cast(?SERVER, {epdg_auth_compl_resp, Imsi, Result}).
+
%% ------------------------------------------------------------------
%% Internal Function Definitions
%% ------------------------------------------------------------------
diff --git a/src/epdg_ue_fsm.erl b/src/epdg_ue_fsm.erl
index 9d20a73..1d934c5 100644
--- a/src/epdg_ue_fsm.erl
+++ b/src/epdg_ue_fsm.erl
@@ -40,12 +40,13 @@
-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_swm_auth_response/2, received_swm_auth_compl_response/2]).
-export([received_gtpc_create_session_response/2, received_gtpc_delete_session_response/2]).
--export([state_new/3, state_wait_auth_resp/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]).

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

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

+received_swm_auth_compl_response(Pid, Result) ->
+ lager:info("ue_fsm received_swm_auth_compl_response ~p~n", [Result]),
+ try
+ gen_statem:call(Pid, {received_swm_auth_compl_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
@@ -152,23 +162,34 @@
gsup_server:auth_response(Data#ue_fsm_data.imsi, Auth),
case Auth of
{ok, _} ->
- {next_state, state_authenticated, Data, [{reply,From,ok}]};
+ {next_state, state_authenticating, 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"),
- gsup_server:lu_response(Data#ue_fsm_data.imsi, Result),
+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":
+ case epdg_diameter_swm:auth_compl_request(Data#ue_fsm_data.imsi, Data#ue_fsm_data.apn) of
+ ok -> {keep_state, Data, [{reply,From,ok}]};
+ {error, Err} -> {stop_and_reply, Err, Data, [{reply,From,{error,Err}}]}
+ end;
+
+% Rx Swm Diameter-EAP Answer (DEA) containing APN-Configuration, triggered by
+% earlier Tx DER EAP AVP containing successuful auth", when we received GSUP LU Req:
+state_authenticating({call, From}, {received_swm_auth_compl_response, Result}, Data) ->
+ lager:info("ue_fsm state_authenticating event=lu_request, ~p, ~p~n", [Result, Data]),
+ % Rx "GSUP CEAI LU Req" is our way of saying Rx "Swm Diameter-EAP REQ (DER) with EAP AVP containing successuful auth":
case Result of
{ok, _} ->
- {keep_state, Data, [{reply,From,ok}]};
+ Ret = ok;
{error, Err} ->
- {stop, Err, Data, [{reply,From,{error,Err}}]}
- end;
+ Ret = {error, Err}
+ end,
+ gsup_server:lu_response(Data#ue_fsm_data.imsi, Ret),
+ {next_state, state_authenticated, Data, [{reply,From,Ret}]}.

state_authenticated({call, From}, tunnel_request, Data) ->
lager:info("ue_fsm state_authenticated event=tunnel_request, ~p~n", [Data]),
diff --git a/src/gsup_server.erl b/src/gsup_server.erl
index ae677c9..4d50fba 100644
--- a/src/gsup_server.erl
+++ b/src/gsup_server.erl
@@ -138,7 +138,7 @@
lager:info("lu_response for ~p: ~p~n", [Imsi, Result]),
Socket = State#gsups_state.socket,
case Result of
- {ok, _Sar} -> Resp = #{message_type => location_upd_res,
+ ok -> Resp = #{message_type => location_upd_res,
imsi => Imsi,
message_class => 5
};

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

Gerrit-Project: erlang/osmo-epdg
Gerrit-Branch: master
Gerrit-Change-Id: I480c110deeb04abf1ff19147a70e10be9cbafae8
Gerrit-Change-Number: 35698
Gerrit-PatchSet: 3
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