Compare commits
4 Commits
ce2299d176
...
7bf413c2a0
Author | SHA1 | Date |
---|---|---|
Pau Espin | 7bf413c2a0 | |
Pau Espin | ff57ae27ff | |
Pau Espin | 859807eb7f | |
Pau Espin | 0d09d1e568 |
|
@ -28,6 +28,7 @@
|
||||||
{dia_s6b_watchdog_config,
|
{dia_s6b_watchdog_config,
|
||||||
[{okay, 3},
|
[{okay, 3},
|
||||||
{suspect, 1}]},
|
{suspect, 1}]},
|
||||||
|
{dia_s6b_transmit_timer, 10000},
|
||||||
{dia_s6b_vendor_id, 0},
|
{dia_s6b_vendor_id, 0},
|
||||||
{dia_s6b_origin_host, "aaa.localdomain"},
|
{dia_s6b_origin_host, "aaa.localdomain"},
|
||||||
{dia_s6b_origin_realm, "localdomain"},
|
{dia_s6b_origin_realm, "localdomain"},
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#!/bin/sh -ex
|
#!/bin/sh -ex
|
||||||
|
|
||||||
rebar3 compile
|
make clean || true
|
||||||
rebar3 escriptize
|
make
|
||||||
rebar3 eunit
|
make check
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
{osmo_gsup, {git, "https://gerrit.osmocom.org/erlang/osmo_gsup", {branch, "osmocom/epdg"}}}
|
{osmo_gsup, {git, "https://gerrit.osmocom.org/erlang/osmo_gsup", {branch, "osmocom/epdg"}}}
|
||||||
]}.
|
]}.
|
||||||
|
|
||||||
{minimum_otp_vsn, "20.3"}.
|
{minimum_otp_vsn, "25.2.3"}.
|
||||||
{plugins, [
|
{plugins, [
|
||||||
{rebar3_diameter_compiler,
|
{rebar3_diameter_compiler,
|
||||||
{git, "https://github.com/carlosedp/rebar3_diameter_compiler.git", {tag, "0.8.0"}}}
|
{git, "https://github.com/carlosedp/rebar3_diameter_compiler.git", {tag, "0.8.0"}}}
|
||||||
|
|
|
@ -40,6 +40,7 @@
|
||||||
|
|
||||||
-behaviour(gen_server).
|
-behaviour(gen_server).
|
||||||
|
|
||||||
|
-include_lib("eunit/include/eunit.hrl").
|
||||||
-include_lib("diameter/include/diameter_gen_base_rfc6733.hrl").
|
-include_lib("diameter/include/diameter_gen_base_rfc6733.hrl").
|
||||||
-include_lib("diameter_3gpp_ts29_273_s6b.hrl").
|
-include_lib("diameter_3gpp_ts29_273_s6b.hrl").
|
||||||
|
|
||||||
|
@ -49,6 +50,7 @@
|
||||||
%% gen_server Function Exports
|
%% gen_server Function Exports
|
||||||
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, peer_down/3]).
|
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, peer_down/3]).
|
||||||
-export([code_change/3]).
|
-export([code_change/3]).
|
||||||
|
-export([tx_as_request/1]).
|
||||||
-export([tx_aa_answer/2, tx_st_answer/2]).
|
-export([tx_aa_answer/2, tx_st_answer/2]).
|
||||||
|
|
||||||
%% Diameter Application Definitions
|
%% Diameter Application Definitions
|
||||||
|
@ -68,6 +70,7 @@
|
||||||
-define(ENV_DEFAULT_DIAMETER_CONNECT_TIMER_MS, 30000).
|
-define(ENV_DEFAULT_DIAMETER_CONNECT_TIMER_MS, 30000).
|
||||||
-define(ENV_DEFAULT_DIAMETER_WATCHDOG_TIMER_MS, 30000).
|
-define(ENV_DEFAULT_DIAMETER_WATCHDOG_TIMER_MS, 30000).
|
||||||
-define(ENV_DEFAULT_DIAMETER_WATCHDOG_CFG, [{okay, 3}, {suspect, 1}]).
|
-define(ENV_DEFAULT_DIAMETER_WATCHDOG_CFG, [{okay, 3}, {suspect, 1}]).
|
||||||
|
-define(ENV_DEFAULT_DIAMETER_TRANSMIT_TIMER_MS, 10000).
|
||||||
|
|
||||||
-define(VENDOR_ID_3GPP, 10415).
|
-define(VENDOR_ID_3GPP, 10415).
|
||||||
-define(VENDOR_ID_3GPP2, 5535).
|
-define(VENDOR_ID_3GPP2, 5535).
|
||||||
|
@ -93,6 +96,10 @@
|
||||||
{module, ?CALLBACK_MOD},
|
{module, ?CALLBACK_MOD},
|
||||||
{answer_errors, callback}]}]).
|
{answer_errors, callback}]}]).
|
||||||
|
|
||||||
|
-record(s6b_state, {
|
||||||
|
tx_timeout :: non_neg_integer()
|
||||||
|
}).
|
||||||
|
|
||||||
%% @doc starts gen_server implementation process
|
%% @doc starts gen_server implementation process
|
||||||
-spec start() -> ok | {error, term()}.
|
-spec start() -> ok | {error, term()}.
|
||||||
start() ->
|
start() ->
|
||||||
|
@ -111,17 +118,18 @@ peer_down(_API, SvcName, {_PeerRef, _} = Peer) ->
|
||||||
gen_server:cast(?SERVER, {peer_down, SvcName, Peer}),
|
gen_server:cast(?SERVER, {peer_down, SvcName, Peer}),
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
init(State) ->
|
init([]) ->
|
||||||
Proto = application:get_env(?ENV_APP_NAME, dia_s6b_proto, ?ENV_DEFAULT_DIAMETER_PROTO),
|
Proto = application:get_env(?ENV_APP_NAME, dia_s6b_proto, ?ENV_DEFAULT_DIAMETER_PROTO),
|
||||||
Ip = application:get_env(?ENV_APP_NAME, dia_s6b_local_ip, ?ENV_DEFAULT_DIAMETER_REMOTE_IP),
|
Ip = application:get_env(?ENV_APP_NAME, dia_s6b_local_ip, ?ENV_DEFAULT_DIAMETER_REMOTE_IP),
|
||||||
Port = application:get_env(?ENV_APP_NAME, dia_s6b_local_port, ?ENV_DEFAULT_DIAMETER_REMOTE_PORT),
|
Port = application:get_env(?ENV_APP_NAME, dia_s6b_local_port, ?ENV_DEFAULT_DIAMETER_REMOTE_PORT),
|
||||||
ConnectTimer = application:get_env(?ENV_APP_NAME, dia_s6b_connect_timer, ?ENV_DEFAULT_DIAMETER_CONNECT_TIMER_MS),
|
ConnectTimer = application:get_env(?ENV_APP_NAME, dia_s6b_connect_timer, ?ENV_DEFAULT_DIAMETER_CONNECT_TIMER_MS),
|
||||||
WatchdogTimer = application:get_env(?ENV_APP_NAME, dia_s6b_watchdog_timer, ?ENV_DEFAULT_DIAMETER_WATCHDOG_TIMER_MS),
|
WatchdogTimer = application:get_env(?ENV_APP_NAME, dia_s6b_watchdog_timer, ?ENV_DEFAULT_DIAMETER_WATCHDOG_TIMER_MS),
|
||||||
WatchdogConfig = application:get_env(?ENV_APP_NAME, diameter_watchdog_config, ?ENV_DEFAULT_DIAMETER_WATCHDOG_CFG),
|
WatchdogConfig = application:get_env(?ENV_APP_NAME, diameter_watchdog_config, ?ENV_DEFAULT_DIAMETER_WATCHDOG_CFG),
|
||||||
|
TxTimer = application:get_env(?ENV_APP_NAME, dia_s6b_transmit_timer, ?ENV_DEFAULT_DIAMETER_TRANSMIT_TIMER_MS),
|
||||||
ok = diameter:start_service(?MODULE, ?SERVICE),
|
ok = diameter:start_service(?MODULE, ?SERVICE),
|
||||||
% lager:info("DiaServices is ~p~n", [DiaServ]),
|
% lager:info("DiaServices is ~p~n", [DiaServ]),
|
||||||
{ok, _} = listen({address, Proto, Ip, Port}, {timer, ConnectTimer, WatchdogTimer, WatchdogConfig}),
|
{ok, _} = listen({address, Proto, Ip, Port}, {timer, ConnectTimer, WatchdogTimer, WatchdogConfig}),
|
||||||
{ok, State}.
|
{ok, #s6b_state{tx_timeout = TxTimer}}.
|
||||||
|
|
||||||
tx_aa_answer(Pid, DiaRC) ->
|
tx_aa_answer(Pid, DiaRC) ->
|
||||||
% handle_request(AAR) was spawned into its own process, and it's blocked waiting for AAA:
|
% handle_request(AAR) was spawned into its own process, and it's blocked waiting for AAA:
|
||||||
|
@ -131,6 +139,27 @@ tx_st_answer(Pid, DiaRC) ->
|
||||||
% handle_request(STR) was spawned into its own process, and it's blocked waiting for STA:
|
% handle_request(STR) was spawned into its own process, and it's blocked waiting for STA:
|
||||||
Pid ! {sta, DiaRC}.
|
Pid ! {sta, DiaRC}.
|
||||||
|
|
||||||
|
tx_as_request(Imsi) ->
|
||||||
|
gen_server:call(?SERVER, {asr, Imsi}).
|
||||||
|
|
||||||
|
handle_call({asr, Imsi}, _From, State) ->
|
||||||
|
lager:debug("S6b Tx ASR Imsi=~p~n", [Imsi]),
|
||||||
|
SessionId = diameter:session_id(application:get_env(?ENV_APP_NAME, dia_s6b_origin_host, ?ENV_DEFAULT_ORIG_HOST)),
|
||||||
|
ASR = #'ASR'{'Session-Id' = SessionId,
|
||||||
|
'Auth-Application-Id' = ?DIAMETER_APP_ID_S6b,
|
||||||
|
'User-Name' = Imsi,
|
||||||
|
'Auth-Session-State' = ?'AUTH-SESSION-STATE_NO_STATE_MAINTAINED'
|
||||||
|
},
|
||||||
|
lager:debug("S6b Tx ASR: ~p~n", [ASR]),
|
||||||
|
Ret = diameter_call(ASR, State),
|
||||||
|
case Ret of
|
||||||
|
ok ->
|
||||||
|
{reply, ok, State};
|
||||||
|
{error, Err} ->
|
||||||
|
lager:error("Error: ~w~n", [Err]),
|
||||||
|
{reply, {error, Err}, State}
|
||||||
|
end;
|
||||||
|
|
||||||
handle_call(Info, _From, State) ->
|
handle_call(Info, _From, State) ->
|
||||||
error_logger:error_report(["unknown handle_call", {module, ?MODULE}, {info, Info}, {state, State}]).
|
error_logger:error_report(["unknown handle_call", {module, ?MODULE}, {info, Info}, {state, State}]).
|
||||||
|
|
||||||
|
@ -189,4 +218,21 @@ tmod(tcp) ->
|
||||||
tmod(sctp) ->
|
tmod(sctp) ->
|
||||||
diameter_sctp.
|
diameter_sctp.
|
||||||
|
|
||||||
|
diameter_call(Msg, State) ->
|
||||||
|
diameter:call(?SVC_NAME, ?APP_ALIAS, Msg, [{timeout, State#s6b_state.tx_timeout},
|
||||||
|
detach]).
|
||||||
|
|
||||||
|
|
||||||
|
%% TESTING:
|
||||||
|
reverse_test() ->
|
||||||
|
State = #s6b_state{tx_timeout = 10000},
|
||||||
|
Imsi = "262422638508077",
|
||||||
|
SessionId = diameter:session_id(application:get_env(?ENV_APP_NAME, dia_s6b_origin_host, ?ENV_DEFAULT_ORIG_HOST)),
|
||||||
|
ASR = #'ASR'{'Session-Id' = SessionId,
|
||||||
|
'Auth-Application-Id' = ?DIAMETER_APP_ID_S6b,
|
||||||
|
'User-Name' = Imsi,
|
||||||
|
'Auth-Session-State' = ?'AUTH-SESSION-STATE_NO_STATE_MAINTAINED'
|
||||||
|
},
|
||||||
|
lager:debug("S6b Tx ASR: ~p~n", [ASR]),
|
||||||
|
Ret = diameter_call(ASR, State),
|
||||||
|
ok = Ret.
|
|
@ -29,23 +29,31 @@ pick_peer([Peer | _], _, _SvcName, _State) ->
|
||||||
{ok, Peer}.
|
{ok, Peer}.
|
||||||
|
|
||||||
%% prepare_request/3
|
%% prepare_request/3
|
||||||
prepare_request(_Req, _SvcName, _Peer) ->
|
prepare_request(#diameter_packet{msg = [ T | Avps ]}, _, {_, Caps})
|
||||||
lager:error("Unexpected prepare_request(): ~p~n", [_Req]),
|
when is_list(Avps) ->
|
||||||
?UNEXPECTED.
|
#diameter_caps{origin_host = {OH, DH}, origin_realm = {OR, DR}} = Caps,
|
||||||
|
{send,
|
||||||
|
[T,
|
||||||
|
{'Origin-Host', OH},
|
||||||
|
{'Origin-Realm', OR},
|
||||||
|
{'Destination-Host', [DH]},
|
||||||
|
{'Destination-Realm', DR}
|
||||||
|
| Avps]};
|
||||||
|
% TODO: is there a simple way to capture all the following requests?
|
||||||
|
prepare_request(#diameter_packet{msg = Req}, _, {_, Caps})
|
||||||
|
when is_record(Req, 'ASR') ->
|
||||||
|
#diameter_caps{origin_host = {OH, DH}, origin_realm = {OR, DR}} = Caps,
|
||||||
|
Msg = Req#'ASR'{'Origin-Host' = OH,
|
||||||
|
'Origin-Realm' = OR,
|
||||||
|
'Destination-Realm' = DR,
|
||||||
|
'Destination-Host' = DH},
|
||||||
|
lager:debug("S6b prepare_request: ~p~n", [Msg]),
|
||||||
|
{send, Msg}.
|
||||||
|
|
||||||
%% prepare_retransmit/3
|
%% prepare_retransmit/3
|
||||||
prepare_retransmit(Packet, SvcName, Peer) ->
|
prepare_retransmit(Packet, SvcName, Peer) ->
|
||||||
prepare_request(Packet, SvcName, Peer).
|
prepare_request(Packet, SvcName, Peer).
|
||||||
|
|
||||||
%% handle_answer/4
|
|
||||||
|
|
||||||
%% Since client.erl has detached the call when using the list
|
|
||||||
%% encoding and not otherwise, output to the terminal in the
|
|
||||||
%% the former case, return in the latter.
|
|
||||||
|
|
||||||
handle_answer(_Packet, _Request, _SvcName, _Peer) ->
|
|
||||||
?UNEXPECTED.
|
|
||||||
|
|
||||||
%% handle_error/4
|
%% handle_error/4
|
||||||
handle_error(Reason, Request, _SvcName, _Peer) when is_list(Request) ->
|
handle_error(Reason, Request, _SvcName, _Peer) when is_list(Request) ->
|
||||||
lager:error("Request error: ~p~n", [Reason]),
|
lager:error("Request error: ~p~n", [Reason]),
|
||||||
|
@ -123,4 +131,21 @@ handle_request(#diameter_packet{msg = Req, errors = []}, _SvcName, {_, Caps}) wh
|
||||||
|
|
||||||
handle_request(Packet, _SvcName, Peer) ->
|
handle_request(Packet, _SvcName, Peer) ->
|
||||||
lager:error("S6b Rx unexpected msg from ~p: ~p~n", [Peer, Packet]),
|
lager:error("S6b Rx unexpected msg from ~p: ~p~n", [Peer, Packet]),
|
||||||
erlang:error({unexpected, ?MODULE, ?LINE}).
|
erlang:error({unexpected, ?MODULE, ?LINE}).
|
||||||
|
|
||||||
|
%% handle_answer/4
|
||||||
|
handle_answer(#diameter_packet{msg = Msg, errors = Errors}, _Request, _SvcName, Peer) when is_record(Msg, 'ASA') ->
|
||||||
|
lager:info("S6b Rx ASA ~p: ~p/ Errors ~p ~n", [Peer, Msg, Errors]),
|
||||||
|
#'ASA'{'Result-Code' = ResultCode} = Msg,
|
||||||
|
DiaRC = #epdg_dia_rc{result_code = ResultCode},
|
||||||
|
case conv:dia_rc_success(DiaRC) of
|
||||||
|
ok ->
|
||||||
|
aaa_ue_fsm:ev_rx_s6b_asa(ok);
|
||||||
|
_ ->
|
||||||
|
aaa_ue_fsm:ev_rx_s6b_asa({error, DiaRC})
|
||||||
|
end,
|
||||||
|
{ok, Msg};
|
||||||
|
|
||||||
|
handle_answer(#diameter_packet{msg = Msg, errors = []}, _Request, _SvcName, Peer) ->
|
||||||
|
lager:notice("S6b Rx unexpected ~p: ~p~n", [Peer, Msg]),
|
||||||
|
{ok, Msg}.
|
|
@ -14,8 +14,8 @@
|
||||||
-export([init/1, handle_call/3, handle_cast/2, handle_info/2]).
|
-export([init/1, handle_call/3, handle_cast/2, handle_info/2]).
|
||||||
-export([code_change/3, terminate/2]).
|
-export([code_change/3, terminate/2]).
|
||||||
|
|
||||||
-export([auth_request/4, auth_compl_request/2, session_termination_request/1]).
|
-export([auth_request/4, auth_compl_request/2, session_termination_request/1, abort_session_answer/1]).
|
||||||
-export([auth_response/2, auth_compl_response/2, session_termination_answer/2]).
|
-export([auth_response/2, auth_compl_response/2, session_termination_answer/2, tx_as_request/1]).
|
||||||
|
|
||||||
-define(SERVER, ?MODULE).
|
-define(SERVER, ?MODULE).
|
||||||
|
|
||||||
|
@ -38,6 +38,9 @@ auth_compl_response(Imsi, Result) ->
|
||||||
session_termination_answer(Imsi, Result) ->
|
session_termination_answer(Imsi, Result) ->
|
||||||
_Result = gen_server:call(?SERVER, {sta, Imsi, Result}).
|
_Result = gen_server:call(?SERVER, {sta, Imsi, Result}).
|
||||||
|
|
||||||
|
tx_as_request(Imsi) ->
|
||||||
|
_result = gen_server:call(?SERVER, {asr, Imsi}).
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
% Rx from emulated SWm wire:
|
% Rx from emulated SWm wire:
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
@ -50,6 +53,9 @@ auth_compl_request(Imsi, Apn) ->
|
||||||
session_termination_request(Imsi) ->
|
session_termination_request(Imsi) ->
|
||||||
gen_server:cast(?SERVER, {str, Imsi}).
|
gen_server:cast(?SERVER, {str, Imsi}).
|
||||||
|
|
||||||
|
abort_session_answer(Imsi) ->
|
||||||
|
gen_server:cast(?SERVER, {asa, Imsi}).
|
||||||
|
|
||||||
handle_cast({epdg_auth_req, Imsi, PdpTypeNr, Apn, EAP}, State) ->
|
handle_cast({epdg_auth_req, Imsi, PdpTypeNr, Apn, EAP}, State) ->
|
||||||
case aaa_ue_fsm:get_pid_by_imsi(Imsi) of
|
case aaa_ue_fsm:get_pid_by_imsi(Imsi) of
|
||||||
undefined -> {ok, Pid} = aaa_ue_fsm:start(Imsi);
|
undefined -> {ok, Pid} = aaa_ue_fsm:start(Imsi);
|
||||||
|
@ -85,6 +91,15 @@ handle_cast({str, Imsi}, State) ->
|
||||||
end,
|
end,
|
||||||
{noreply, State};
|
{noreply, State};
|
||||||
|
|
||||||
|
handle_cast({asa, Imsi}, State) ->
|
||||||
|
case aaa_ue_fsm:get_pid_by_imsi(Imsi) of
|
||||||
|
Pid when is_pid(Pid) ->
|
||||||
|
aaa_ue_fsm:ev_rx_swm_asa(Pid);
|
||||||
|
undefined ->
|
||||||
|
ok
|
||||||
|
end,
|
||||||
|
{noreply, State};
|
||||||
|
|
||||||
handle_cast(Info, S) ->
|
handle_cast(Info, S) ->
|
||||||
error_logger:error_report(["unknown handle_cast", {module, ?MODULE}, {info, Info}, {state, S}]),
|
error_logger:error_report(["unknown handle_cast", {module, ?MODULE}, {info, Info}, {state, S}]),
|
||||||
{noreply, S}.
|
{noreply, S}.
|
||||||
|
@ -105,6 +120,10 @@ handle_call({sta, Imsi, DiaRC}, _From, State) ->
|
||||||
epdg_diameter_swm:session_termination_answer(Imsi, DiaRC),
|
epdg_diameter_swm:session_termination_answer(Imsi, DiaRC),
|
||||||
{reply, ok, State};
|
{reply, ok, State};
|
||||||
|
|
||||||
|
handle_call({asr, Imsi}, _From, State) ->
|
||||||
|
epdg_diameter_swm:abort_session_request(Imsi),
|
||||||
|
{reply, ok, State};
|
||||||
|
|
||||||
handle_call(Request, From, S) ->
|
handle_call(Request, From, S) ->
|
||||||
error_logger:error_report(["unknown handle_call", {module, ?MODULE}, {request, Request}, {from, From}, {state, S}]),
|
error_logger:error_report(["unknown handle_call", {module, ?MODULE}, {request, Request}, {from, From}, {state, S}]),
|
||||||
{noreply, S}.
|
{noreply, S}.
|
||||||
|
|
|
@ -78,10 +78,18 @@ handle_request(#diameter_packet{msg = Req, errors = []}, _SvcName, {_, Caps}) wh
|
||||||
'Vendor-Specific-Application-Id' = VendorAppId,
|
'Vendor-Specific-Application-Id' = VendorAppId,
|
||||||
'Auth-Session-State' = AuthSessState,
|
'Auth-Session-State' = AuthSessState,
|
||||||
'User-Name' = Imsi,
|
'User-Name' = Imsi,
|
||||||
'Deregistration-Reason' = _DeregReason} = Req,
|
'Deregistration-Reason' = DeregReason} = Req,
|
||||||
case aaa_ue_fsm:get_pid_by_imsi(Imsi) of
|
case aaa_ue_fsm:get_pid_by_imsi(Imsi) of
|
||||||
Pid when is_pid(Pid) ->
|
Pid when is_pid(Pid) ->
|
||||||
aaa_ue_fsm:stop(Pid),
|
case DeregReason of
|
||||||
|
#'Deregistration-Reason'{'Reason-Code' = ?'REASON-CODE_PERMANENT_TERMINATION'} ->
|
||||||
|
case aaa_ue_fsm:ev_rx_swx_rtr(Pid) of
|
||||||
|
{error, _} -> aaa_ue_fsm:stop(Pid);
|
||||||
|
_ -> ok
|
||||||
|
end;
|
||||||
|
_ ->
|
||||||
|
aaa_ue_fsm:stop(Pid)
|
||||||
|
end,
|
||||||
Res = 2001, %% Success
|
Res = 2001, %% Success
|
||||||
ERes = [];
|
ERes = [];
|
||||||
undefined ->
|
undefined ->
|
||||||
|
@ -109,7 +117,7 @@ handle_answer(#diameter_packet{msg = Msg, errors = Errors}, _Request, _SvcName,
|
||||||
#'MAA'{'Result-Code' = ResultCodeOpt,
|
#'MAA'{'Result-Code' = ResultCodeOpt,
|
||||||
'Experimental-Result' = ExperimentalResultOpt} = Msg,
|
'Experimental-Result' = ExperimentalResultOpt} = Msg,
|
||||||
DiaRC = parse_epdg_dia_rc(ResultCodeOpt, ExperimentalResultOpt),
|
DiaRC = parse_epdg_dia_rc(ResultCodeOpt, ExperimentalResultOpt),
|
||||||
case dia_rc_success(DiaRC) of
|
case conv:dia_rc_success(DiaRC) of
|
||||||
ok ->
|
ok ->
|
||||||
#'MAA'{'SIP-Auth-Data-Item' = SipAuthTuples} = Msg,
|
#'MAA'{'SIP-Auth-Data-Item' = SipAuthTuples} = Msg,
|
||||||
AuthTuples = lists:map(fun dia_sip2epdg_auth_tuple/1, SipAuthTuples),
|
AuthTuples = lists:map(fun dia_sip2epdg_auth_tuple/1, SipAuthTuples),
|
||||||
|
@ -127,7 +135,7 @@ handle_answer(#diameter_packet{msg = Msg, errors = Errors}, Request, _SvcName, P
|
||||||
#'SAA'{'Result-Code' = ResultCodeOpt,
|
#'SAA'{'Result-Code' = ResultCodeOpt,
|
||||||
'Experimental-Result' = ExperimentalResultOpt} = Msg,
|
'Experimental-Result' = ExperimentalResultOpt} = Msg,
|
||||||
DiaRC = parse_epdg_dia_rc(ResultCodeOpt, ExperimentalResultOpt),
|
DiaRC = parse_epdg_dia_rc(ResultCodeOpt, ExperimentalResultOpt),
|
||||||
case dia_rc_success(DiaRC) of
|
case conv:dia_rc_success(DiaRC) of
|
||||||
ok ->
|
ok ->
|
||||||
#'SAA'{'Non-3GPP-User-Data' = N3UA} = Msg,
|
#'SAA'{'Non-3GPP-User-Data' = N3UA} = Msg,
|
||||||
PGWAddresses = parse_pgw_addr_from_N3UA(N3UA),
|
PGWAddresses = parse_pgw_addr_from_N3UA(N3UA),
|
||||||
|
@ -165,10 +173,6 @@ handle_error(Reason, _Request, _SvcName, _Peer, ExtraPars) ->
|
||||||
%% Internal Function Definitions
|
%% Internal Function Definitions
|
||||||
%% ------------------------------------------------------------------
|
%% ------------------------------------------------------------------
|
||||||
|
|
||||||
dia_rc_success(#epdg_dia_rc{result_code = 2001}) -> ok;
|
|
||||||
dia_rc_success(#epdg_dia_rc{result_code = 2002}) -> ok;
|
|
||||||
dia_rc_success(_) -> invalid_result_code.
|
|
||||||
|
|
||||||
parse_epdg_dia_rc([], []) ->
|
parse_epdg_dia_rc([], []) ->
|
||||||
#epdg_dia_rc{vendor_id = undefined, result_code = 2001 };
|
#epdg_dia_rc{vendor_id = undefined, result_code = 2001 };
|
||||||
parse_epdg_dia_rc([ResultCode], []) ->
|
parse_epdg_dia_rc([ResultCode], []) ->
|
||||||
|
|
|
@ -42,9 +42,19 @@
|
||||||
-export([start/1, stop/1]).
|
-export([start/1, stop/1]).
|
||||||
-export([init/1,callback_mode/0,terminate/3]).
|
-export([init/1,callback_mode/0,terminate/3]).
|
||||||
-export([get_server_name_by_imsi/1, get_pid_by_imsi/1]).
|
-export([get_server_name_by_imsi/1, get_pid_by_imsi/1]).
|
||||||
-export([ev_swm_auth_req/2, ev_swm_auth_compl/2, ev_rx_swm_str/1, ev_rx_swx_maa/2, ev_rx_swx_saa/2,
|
-export([ev_swm_auth_req/2, ev_swm_auth_compl/2, ev_rx_swm_str/1, ev_rx_swm_asa/1,
|
||||||
ev_rx_s6b_aar/2, ev_rx_s6b_str/1]).
|
ev_rx_swx_maa/2, ev_rx_swx_saa/2, ev_rx_swx_rtr/1,
|
||||||
-export([state_new/3, state_wait_swx_maa/3, state_wait_swx_saa/3, state_authenticated/3, state_authenticated_wait_swx_saa/3]).
|
ev_rx_s6b_aar/2, ev_rx_s6b_str/1, ev_rx_s6b_asa/2]).
|
||||||
|
-export([state_new/3,
|
||||||
|
state_wait_swx_maa/3,
|
||||||
|
state_wait_swx_saa/3,
|
||||||
|
state_authenticated/3,
|
||||||
|
state_authenticated_wait_swx_saa/3,
|
||||||
|
state_dereg_net_initiated_wait_s6b_asa/3,
|
||||||
|
state_dereg_net_initiated_wait_swm_asa/3]).
|
||||||
|
|
||||||
|
-define(TIMEOUT_VAL_WAIT_S6b_ANSWER, 10000).
|
||||||
|
-define(TIMEOUT_VAL_WAIT_SWm_ANSWER, 10000).
|
||||||
|
|
||||||
-record(ue_fsm_data, {
|
-record(ue_fsm_data, {
|
||||||
imsi = unknown :: string(),
|
imsi = unknown :: string(),
|
||||||
|
@ -102,6 +112,15 @@ ev_rx_swm_str(Pid) ->
|
||||||
{error, Err}
|
{error, Err}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
ev_rx_swm_asa(Pid) ->
|
||||||
|
lager:info("ue_fsm ev_rx_swm_asa~n", []),
|
||||||
|
try
|
||||||
|
gen_statem:call(Pid, rx_swm_asa)
|
||||||
|
catch
|
||||||
|
exit:Err ->
|
||||||
|
{error, Err}
|
||||||
|
end.
|
||||||
|
|
||||||
ev_rx_swx_maa(Pid, Result) ->
|
ev_rx_swx_maa(Pid, Result) ->
|
||||||
lager:info("ue_fsm ev_rx_swx_maa~n", []),
|
lager:info("ue_fsm ev_rx_swx_maa~n", []),
|
||||||
try
|
try
|
||||||
|
@ -120,6 +139,15 @@ ev_rx_swx_saa(Pid, Result) ->
|
||||||
{error, Err}
|
{error, Err}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
ev_rx_swx_rtr(Pid) ->
|
||||||
|
lager:info("ue_fsm ev_rx_swx_rtr~n", []),
|
||||||
|
try
|
||||||
|
gen_statem:call(Pid, rx_swx_rtr)
|
||||||
|
catch
|
||||||
|
exit:Err ->
|
||||||
|
{error, Err}
|
||||||
|
end.
|
||||||
|
|
||||||
ev_rx_s6b_aar(Pid, {Apn, AgentInfoOpt}) ->
|
ev_rx_s6b_aar(Pid, {Apn, AgentInfoOpt}) ->
|
||||||
lager:info("ue_fsm ev_rx_s6b_aar: ~p ~p~n", [Apn, AgentInfoOpt]),
|
lager:info("ue_fsm ev_rx_s6b_aar: ~p ~p~n", [Apn, AgentInfoOpt]),
|
||||||
try
|
try
|
||||||
|
@ -129,6 +157,15 @@ ev_rx_s6b_aar(Pid, {Apn, AgentInfoOpt}) ->
|
||||||
{error, Err}
|
{error, Err}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
ev_rx_s6b_asa(Pid, Result) ->
|
||||||
|
lager:info("ue_fsm ev_rx_s6b_asa: ~p~n", [Result]),
|
||||||
|
try
|
||||||
|
gen_statem:call(Pid, {rx_s6b_asa, Result})
|
||||||
|
catch
|
||||||
|
exit:Err ->
|
||||||
|
{error, Err}
|
||||||
|
end.
|
||||||
|
|
||||||
ev_rx_s6b_str(Pid) ->
|
ev_rx_s6b_str(Pid) ->
|
||||||
lager:info("ue_fsm ev_rx_s6b_str~n", []),
|
lager:info("ue_fsm ev_rx_s6b_str~n", []),
|
||||||
try
|
try
|
||||||
|
@ -223,7 +260,7 @@ state_authenticated({call, From}, rx_swm_str, Data) ->
|
||||||
DiaRC = 5002, %% UNKNOWN_SESSION_ID
|
DiaRC = 5002, %% UNKNOWN_SESSION_ID
|
||||||
{keep_state, Data, [{reply,From,{error, DiaRC}}]};
|
{keep_state, Data, [{reply,From,{error, DiaRC}}]};
|
||||||
{true, true} -> %% The other session is still active, no need to send SAR Type=USER_DEREGISTRATION
|
{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", []),
|
lager:info("ue_fsm state_authenticated event=rx_swm_str: PGW session still active, skip updating the HSS~n", []),
|
||||||
Data1 = Data#ue_fsm_data{epdg_sess_active = false},
|
Data1 = Data#ue_fsm_data{epdg_sess_active = false},
|
||||||
{keep_state, Data1, [{reply,From,{ok, 2001}}]};
|
{keep_state, Data1, [{reply,From,{ok, 2001}}]};
|
||||||
{true, false} -> %% All sessions will now be gone, trigger SAR Type=USER_DEREGISTRATION
|
{true, false} -> %% All sessions will now be gone, trigger SAR Type=USER_DEREGISTRATION
|
||||||
|
@ -264,6 +301,13 @@ state_authenticated({call, _From}, {swm_auth_req, PdpTypeNr, Apn, EAP}, Data) ->
|
||||||
lager:info("ue_fsm state_authenticated event=swm_auth_req {~p, ~p, ~p}, ~p~n", [PdpTypeNr, Apn, EAP, Data]),
|
lager:info("ue_fsm state_authenticated event=swm_auth_req {~p, ~p, ~p}, ~p~n", [PdpTypeNr, Apn, EAP, Data]),
|
||||||
{next_state, state_new, Data, [postpone]};
|
{next_state, state_new, Data, [postpone]};
|
||||||
|
|
||||||
|
state_authenticated({call, From}, rx_swx_rtr, Data) ->
|
||||||
|
lager:info("ue_fsm state_authenticated event=rx_swx_rtr ~p~n", [Data]),
|
||||||
|
case {Data#ue_fsm_data.pgw_sess_active, Data#ue_fsm_data.epdg_sess_active} of
|
||||||
|
{true, _} -> {next_state, state_dereg_net_initiated_wait_s6b_asa, Data, [{reply,From,ok}]};
|
||||||
|
{false, _} -> {next_state, state_dereg_net_initiated_wait_s6b_asa, Data, [{reply,From,ok}]} %% TODO: proper state for s6b
|
||||||
|
end;
|
||||||
|
|
||||||
state_authenticated({call, From}, Ev, Data) ->
|
state_authenticated({call, From}, Ev, Data) ->
|
||||||
lager:info("ue_fsm state_authenticated: Unexpected call event ~p, ~p~n", [Ev, Data]),
|
lager:info("ue_fsm state_authenticated: Unexpected call event ~p, ~p~n", [Ev, Data]),
|
||||||
{keep_state, Data, [{reply,From,ok}]}.
|
{keep_state, Data, [{reply,From,ok}]}.
|
||||||
|
@ -293,4 +337,36 @@ state_authenticated_wait_swx_saa({call, From}, {rx_swx_saa, Result}, Data) ->
|
||||||
Data1 = Data#ue_fsm_data{pgw_sess_active = false, s6b_resp_pid = undefined},
|
Data1 = Data#ue_fsm_data{pgw_sess_active = false, s6b_resp_pid = undefined},
|
||||||
{next_state, state_new, Data1, [{reply,From,ok}]}
|
{next_state, state_new, Data1, [{reply,From,ok}]}
|
||||||
end
|
end
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
%% HSS asked us to do deregistration towards the user.
|
||||||
|
%% Transmit S6b ASR towards PGW and wait for ASA back.
|
||||||
|
state_dereg_net_initiated_wait_s6b_asa(enter, _OldState, Data) ->
|
||||||
|
aaa_diameter_s6b:tx_as_request(Data#ue_fsm_data.imsi),
|
||||||
|
{keep_state, Data, {state_timeout,?TIMEOUT_VAL_WAIT_S6b_ANSWER,s6b_asa_timeout}};
|
||||||
|
|
||||||
|
state_dereg_net_initiated_wait_s6b_asa({call, From}, {rx_s6b_asa, _Result}, Data) ->
|
||||||
|
{next_state, state_dereg_net_initiated_wait_swm_asa, Data, [{reply,From,ok}]};
|
||||||
|
|
||||||
|
state_dereg_net_initiated_wait_s6b_asa({call, From}, Ev, Data) ->
|
||||||
|
lager:info("ue_fsm state_dereg_net_initiated_wait_s6b_asa: Unexpected call event ~p, ~p~n", [Ev, Data]),
|
||||||
|
{keep_state, Data, [{reply,From,ok}]};
|
||||||
|
|
||||||
|
state_dereg_net_initiated_wait_s6b_asa(state_timeout, s6b_asa_timeout, Data) ->
|
||||||
|
{next_state, state_dereg_net_initiated_wait_swm_asa, Data}.
|
||||||
|
|
||||||
|
%% HSS asked us to do deregistration towards the user.
|
||||||
|
%% S6b (PGW) was already torn down. Now transmit SWm ASR towards ePDG and wait for ASA back.
|
||||||
|
state_dereg_net_initiated_wait_swm_asa(enter, _OldState, Data) ->
|
||||||
|
aaa_diameter_swm:tx_as_request(Data#ue_fsm_data.imsi),
|
||||||
|
{keep_state, Data, {state_timeout,?TIMEOUT_VAL_WAIT_SWm_ANSWER,swm_asa_timeout}};
|
||||||
|
|
||||||
|
state_dereg_net_initiated_wait_swm_asa({call, From}, {rx_swm_asa, _Result}, Data) ->
|
||||||
|
{stop_and_reply, normal, [{reply,From,ok}], Data};
|
||||||
|
|
||||||
|
state_dereg_net_initiated_wait_swm_asa({call, From}, Ev, Data) ->
|
||||||
|
lager:info("ue_fsm state_dereg_net_initiated_wait_swm_asa: Unexpected call event ~p, ~p~n", [Ev, Data]),
|
||||||
|
{keep_state, Data, [{reply,From,ok}]};
|
||||||
|
|
||||||
|
state_dereg_net_initiated_wait_swm_asa(state_timeout, swm_asa_timeout, _Data) ->
|
||||||
|
{stop, normal}.
|
||||||
|
|
|
@ -40,7 +40,7 @@
|
||||||
|
|
||||||
-export([ip_to_bin/1, bin_to_ip/1]).
|
-export([ip_to_bin/1, bin_to_ip/1]).
|
||||||
-export([cause_gtp2gsup/1]).
|
-export([cause_gtp2gsup/1]).
|
||||||
-export([dia_rc_to_gsup_cause/1]).
|
-export([dia_rc_success/1, dia_rc_to_gsup_cause/1]).
|
||||||
-export([gtp2_paa_to_epdg_eua/1, epdg_eua_to_gsup_pdp_address/1]).
|
-export([gtp2_paa_to_epdg_eua/1, epdg_eua_to_gsup_pdp_address/1]).
|
||||||
-export([nai_to_imsi/1]).
|
-export([nai_to_imsi/1]).
|
||||||
|
|
||||||
|
@ -92,6 +92,10 @@ cause_gtp2gsup(_) -> ?GSUP_CAUSE_PROTO_ERR_UNSPEC.
|
||||||
-define(DIAMETER_ERROR_EQUIPMENT_UNKNOWN, 5422).
|
-define(DIAMETER_ERROR_EQUIPMENT_UNKNOWN, 5422).
|
||||||
-define(DIAMETER_ERROR_UNKOWN_SERVING_NODE, 5423).
|
-define(DIAMETER_ERROR_UNKOWN_SERVING_NODE, 5423).
|
||||||
|
|
||||||
|
dia_rc_success(#epdg_dia_rc{result_code = 2001}) -> ok;
|
||||||
|
dia_rc_success(#epdg_dia_rc{result_code = 2002}) -> ok;
|
||||||
|
dia_rc_success(_) -> invalid_result_code.
|
||||||
|
|
||||||
-spec dia_rc_to_gsup_cause(#epdg_dia_rc{}) -> non_neg_integer().
|
-spec dia_rc_to_gsup_cause(#epdg_dia_rc{}) -> non_neg_integer().
|
||||||
dia_rc_to_gsup_cause(#epdg_dia_rc{result_code = 2001}) -> 0;
|
dia_rc_to_gsup_cause(#epdg_dia_rc{result_code = 2001}) -> 0;
|
||||||
dia_rc_to_gsup_cause(#epdg_dia_rc{result_code = 2002}) -> 0;
|
dia_rc_to_gsup_cause(#epdg_dia_rc{result_code = 2002}) -> 0;
|
||||||
|
|
|
@ -19,8 +19,10 @@
|
||||||
-export([init/1, handle_call/3, handle_cast/2, handle_info/2]).
|
-export([init/1, handle_call/3, handle_cast/2, handle_info/2]).
|
||||||
-export([code_change/3, terminate/2]).
|
-export([code_change/3, terminate/2]).
|
||||||
|
|
||||||
-export([auth_request/4, auth_compl_request/2, session_termination_request/1]).
|
-export([auth_request/4, auth_compl_request/2,
|
||||||
-export([auth_response/2, auth_compl_response/2, session_termination_answer/2]).
|
session_termination_request/1, abort_session_answer/1]).
|
||||||
|
-export([auth_response/2, auth_compl_response/2,
|
||||||
|
session_termination_answer/2, abort_session_request/1]).
|
||||||
|
|
||||||
-define(SERVER, ?MODULE).
|
-define(SERVER, ?MODULE).
|
||||||
|
|
||||||
|
@ -72,6 +74,17 @@ session_termination_request(Imsi) ->
|
||||||
_ -> Result
|
_ -> Result
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
% 3GPP TS 29.273 7.1.2.4
|
||||||
|
abort_session_answer(Imsi) ->
|
||||||
|
% In Diameter we use Imsi as strings, as done by diameter module.
|
||||||
|
ImsiStr = binary_to_list(Imsi),
|
||||||
|
Result = gen_server:call(?SERVER, {asa, ImsiStr}),
|
||||||
|
case Result of
|
||||||
|
{ok, _Mar} ->
|
||||||
|
ok;
|
||||||
|
_ -> Result
|
||||||
|
end.
|
||||||
|
|
||||||
handle_call({epdg_auth_req, Imsi, PdpTypeNr, Apn, EAP}, {Pid, _Tag} = _From, State0) ->
|
handle_call({epdg_auth_req, Imsi, PdpTypeNr, Apn, EAP}, {Pid, _Tag} = _From, State0) ->
|
||||||
% we yet don't implement the Diameter SWm interface on the wire, we process the call internally:
|
% 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),
|
{_Sess, State1} = find_or_new_swm_session(Imsi, Pid, State0),
|
||||||
|
@ -98,6 +111,17 @@ handle_call({str, Imsi}, _From, State) ->
|
||||||
undefined ->
|
undefined ->
|
||||||
Reply = {error,unknown_imsi}
|
Reply = {error,unknown_imsi}
|
||||||
end,
|
end,
|
||||||
|
{reply, Reply, State};
|
||||||
|
|
||||||
|
handle_call({asa, 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:abort_session_answer(Imsi);
|
||||||
|
undefined ->
|
||||||
|
Reply = {error,unknown_imsi}
|
||||||
|
end,
|
||||||
{reply, Reply, State}.
|
{reply, Reply, State}.
|
||||||
|
|
||||||
handle_cast({epdg_auth_resp, Imsi, Result}, State) ->
|
handle_cast({epdg_auth_resp, Imsi, Result}, State) ->
|
||||||
|
@ -130,6 +154,16 @@ handle_cast({sta, Imsi, Result}, State) ->
|
||||||
end,
|
end,
|
||||||
{noreply, State};
|
{noreply, State};
|
||||||
|
|
||||||
|
handle_cast({asr, Imsi}, State) ->
|
||||||
|
Sess = find_swm_session_by_imsi(Imsi, State),
|
||||||
|
case Sess of
|
||||||
|
#swm_session{imsi = Imsi} ->
|
||||||
|
epdg_ue_fsm:received_swm_abort_session_request(Sess#swm_session.pid);
|
||||||
|
undefined ->
|
||||||
|
error_logger:error_report(["unknown swm_session", {module, ?MODULE}, {imsi, Imsi}, {state, State}])
|
||||||
|
end,
|
||||||
|
{noreply, State};
|
||||||
|
|
||||||
handle_cast(Info, S) ->
|
handle_cast(Info, S) ->
|
||||||
error_logger:error_report(["unknown handle_cast", {module, ?MODULE}, {info, Info}, {state, S}]),
|
error_logger:error_report(["unknown handle_cast", {module, ?MODULE}, {info, Info}, {state, S}]),
|
||||||
{noreply, S}.
|
{noreply, S}.
|
||||||
|
@ -160,6 +194,10 @@ auth_compl_response(Imsi, Result) ->
|
||||||
session_termination_answer(Imsi, Result) ->
|
session_termination_answer(Imsi, Result) ->
|
||||||
ok = gen_server:cast(?SERVER, {sta, Imsi, Result}).
|
ok = gen_server:cast(?SERVER, {sta, Imsi, Result}).
|
||||||
|
|
||||||
|
% Rx SWm Diameter ASR:
|
||||||
|
abort_session_request(Imsi) ->
|
||||||
|
ok = gen_server:cast(?SERVER, {asr, Imsi}).
|
||||||
|
|
||||||
%% ------------------------------------------------------------------
|
%% ------------------------------------------------------------------
|
||||||
%% Internal Function Definitions
|
%% Internal Function Definitions
|
||||||
%% ------------------------------------------------------------------
|
%% ------------------------------------------------------------------
|
||||||
|
|
|
@ -43,11 +43,13 @@
|
||||||
-export([init/1,callback_mode/0,terminate/3]).
|
-export([init/1,callback_mode/0,terminate/3]).
|
||||||
-export([get_server_name_by_imsi/1, get_pid_by_imsi/1]).
|
-export([get_server_name_by_imsi/1, get_pid_by_imsi/1]).
|
||||||
-export([auth_request/2, lu_request/1, tunnel_request/2, purge_ms_request/1]).
|
-export([auth_request/2, lu_request/1, tunnel_request/2, purge_ms_request/1]).
|
||||||
-export([received_swm_auth_response/2, received_swm_auth_compl_response/2, received_swm_session_termination_answer/2]).
|
-export([received_swm_auth_response/2, received_swm_auth_compl_response/2,
|
||||||
|
received_swm_session_termination_answer/2, received_swm_abort_session_request/1]).
|
||||||
-export([received_gtpc_create_session_response/2, received_gtpc_delete_session_response/2, received_gtpc_delete_bearer_request/1]).
|
-export([received_gtpc_create_session_response/2, received_gtpc_delete_session_response/2, received_gtpc_delete_bearer_request/1]).
|
||||||
-export([state_new/3, state_wait_auth_resp/3, state_authenticating/3, state_authenticated/3,
|
-export([state_new/3, state_wait_auth_resp/3, state_authenticating/3, state_authenticated/3,
|
||||||
state_wait_create_session_resp/3, state_wait_delete_session_resp/3,
|
state_wait_create_session_resp/3, state_wait_delete_session_resp/3,
|
||||||
state_wait_swm_session_termination_answer/3, state_active/3]).
|
state_wait_swm_session_termination_answer/3, state_active/3,
|
||||||
|
state_dereg_net_initiated_wait_s2b_delete_session_resp/3]).
|
||||||
|
|
||||||
-define(TIMEOUT_VAL_WAIT_GTP_ANSWER, 10000).
|
-define(TIMEOUT_VAL_WAIT_GTP_ANSWER, 10000).
|
||||||
|
|
||||||
|
@ -144,6 +146,15 @@ received_swm_session_termination_answer(Pid, Result) ->
|
||||||
{error, Err}
|
{error, Err}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
received_swm_abort_session_request(Pid) ->
|
||||||
|
lager:info("ue_fsm received_swm_abort_session_request~n", []),
|
||||||
|
try
|
||||||
|
gen_statem:call(Pid, received_swm_asr)
|
||||||
|
catch
|
||||||
|
exit:Err ->
|
||||||
|
{error, Err}
|
||||||
|
end.
|
||||||
|
|
||||||
received_gtpc_create_session_response(Pid, Result) ->
|
received_gtpc_create_session_response(Pid, Result) ->
|
||||||
lager:info("ue_fsm received_gtpc_create_session_response ~p~n", [Result]),
|
lager:info("ue_fsm received_gtpc_create_session_response ~p~n", [Result]),
|
||||||
try
|
try
|
||||||
|
@ -360,6 +371,14 @@ state_active({call, From}, received_gtpc_delete_bearer_request, Data) ->
|
||||||
Data1 = Data#ue_fsm_data{tun_pdp_ctx = undefined, tear_down_gsup_needed = false},
|
Data1 = Data#ue_fsm_data{tun_pdp_ctx = undefined, tear_down_gsup_needed = false},
|
||||||
{next_state, state_wait_swm_session_termination_answer, Data1, [{reply,From,ok}]};
|
{next_state, state_wait_swm_session_termination_answer, Data1, [{reply,From,ok}]};
|
||||||
|
|
||||||
|
%%% network (HSS/AAA) initiated de-registation requested:
|
||||||
|
state_active({call, From}, received_swm_asr, Data) ->
|
||||||
|
lager:info("ue_fsm state_active event=received_swm_asr, ~p~n", [Data]),
|
||||||
|
gsup_server:cancel_location_request(Data#ue_fsm_data.imsi),
|
||||||
|
gtp_u_tun:delete_pdp_context(Data#ue_fsm_data.tun_pdp_ctx),
|
||||||
|
Data1 = Data#ue_fsm_data{tun_pdp_ctx = undefined, tear_down_gsup_needed = false},
|
||||||
|
{next_state, state_dereg_net_initiated_wait_s2b_delete_session_resp, Data1, [{reply,From,ok}]};
|
||||||
|
|
||||||
state_active({call, From}, Event, Data) ->
|
state_active({call, From}, Event, Data) ->
|
||||||
lager:error("ue_fsm state_active: Unexpected call event ~p, ~p~n", [Event, Data]),
|
lager:error("ue_fsm state_active: Unexpected call event ~p, ~p~n", [Event, Data]),
|
||||||
{keep_state, Data, [{reply,From,ok}]};
|
{keep_state, Data, [{reply,From,ok}]};
|
||||||
|
@ -418,3 +437,36 @@ state_wait_swm_session_termination_answer({call, From}, {received_swm_sta, DiaRC
|
||||||
state_wait_swm_session_termination_answer({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]),
|
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}}]}.
|
{keep_state, Data, [{reply,From,{error,unexpected_event}}]}.
|
||||||
|
|
||||||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
%% state_dereg_net_initiated_wait_s2b_delete_session_resp:
|
||||||
|
%% Network (AAA/HSS) initiated de-registration: We have informed UE (GSUP), and
|
||||||
|
%% have triggered GTPCv1 Delete Session Req against PGW.
|
||||||
|
%% Wait for GTPCv1 Delete Session Response, ssend SWm ASA to AAAA and terminate FSM.
|
||||||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
state_dereg_net_initiated_wait_s2b_delete_session_resp(enter, _OldState, Data) ->
|
||||||
|
case epdg_gtpc_s2b:delete_session_req(Data#ue_fsm_data.imsi) of
|
||||||
|
ok ->
|
||||||
|
{keep_state, Data, {state_timeout,?TIMEOUT_VAL_WAIT_GTP_ANSWER,s2b_delete_session_timeout}};
|
||||||
|
{error, Err} ->
|
||||||
|
epdg_diameter_swm:abort_session_answer(Data#ue_fsm_data.imsi),
|
||||||
|
{stop, {error,Err}}
|
||||||
|
end;
|
||||||
|
|
||||||
|
state_dereg_net_initiated_wait_s2b_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=state_dereg_net_initiated_wait_s2b_delete_session_resp, ~p~n", [Data]),
|
||||||
|
#{{v2_cause,0} := CauseIE} = IEs,
|
||||||
|
GtpCause = gtp_utils:enum_v2_cause(CauseIE#v2_cause.v2_cause),
|
||||||
|
lager:debug("Cause: GTP_atom=~p -> GTP_int=~p~n", [CauseIE#v2_cause.v2_cause, GtpCause]),
|
||||||
|
epdg_diameter_swm:abort_session_answer(Data#ue_fsm_data.imsi),
|
||||||
|
{stop_and_reply, normal, [{reply,From,ok}], Data};
|
||||||
|
|
||||||
|
state_dereg_net_initiated_wait_s2b_delete_session_resp({call, From}, Event, Data) ->
|
||||||
|
lager:error("ue_fsm state_dereg_net_initiated_wait_s2b_delete_session_resp: Unexpected call event ~p, ~p~n", [Event, Data]),
|
||||||
|
{keep_state, Data, [{reply,From,ok}]};
|
||||||
|
|
||||||
|
|
||||||
|
state_dereg_net_initiated_wait_s2b_delete_session_resp(state_timeout, s2b_delete_session_timeout, Data) ->
|
||||||
|
lager:error("ue_fsm state_dereg_net_initiated_wait_s2b_delete_session_resp: Timeout ~p, ~p~n", [s2b_delete_session_timeout, Data]),
|
||||||
|
epdg_diameter_swm:abort_session_answer(Data#ue_fsm_data.imsi),
|
||||||
|
{stop, normal}.
|
||||||
|
|
Loading…
Reference in New Issue