pespin has submitted this change. ( https://gerrit.osmocom.org/c/erlang/osmo-epdg/+/35676?usp=email )
Change subject: Implement UE-initiated Detach ...................................................................... Implement UE-initiated Detach This commit is a first step towards implementing the full procedure. It implements handling at the GSUP CEAI interface and operating on the attached PGW to delete the session. No work towards the HSS from AAA server now from PGW to the AAA is done yet. Change-Id: I2e922f76c2fa601c5f61fa23d6df5fb62c3e133d --- M .gitignore A include/gtp_utils.hrl A src/conv.erl M src/epdg_gtpc_s2b.erl M src/gsup_server.erl M src/gtp_utils.erl M src/ue_fsm.erl 7 files changed, 423 insertions(+), 10 deletions(-) Approvals: Jenkins Builder: Verified pespin: Looks good to me, approved diff --git a/.gitignore b/.gitignore index 08ae348..253618b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ _build/ -include/ +include/diameter_* log/ *.beam diff --git a/include/gtp_utils.hrl b/include/gtp_utils.hrl new file mode 100644 index 0000000..453efb0 --- /dev/null +++ b/include/gtp_utils.hrl @@ -0,0 +1,113 @@ +% (C) 2023 by sysmocom +% +% All Rights Reserved +% +% This program is free software; you can redistribute it and/or modify +% it under the terms of the GNU Affero General Public License as +% published by the Free Software Foundation; either version 3 of the +% License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU Affero General Public License +% along with this program. If not, see <http://www.gnu.org/licenses/>. +% +% Additional Permission under GNU AGPL version 3 section 7: +% +% If you modify this Program, or any covered work, by linking or +% combining it with runtime libraries of Erlang/OTP as released by +% Ericsson on http://www.erlang.org (or a modified version of these +% libraries), containing parts covered by the terms of the Erlang Public +% License (http://www.erlang.org/EPLICENSE), the licensors of this +% Program grant you additional permission to convey the resulting work +% without the need to license the runtime libraries of Erlang/OTP under +% the GNU Affero General Public License. Corresponding Source for a +% non-source form of such a combination shall include the source code +% for the parts of the runtime libraries of Erlang/OTP used as well as +% that of the covered work. +% +-hrl_name('gtp_utils.hrl'). + +-define(GTP2_CAUSE_RESERVED, 1). +-define(GTP2_CAUSE_LOCAL_DETACH, 2). +-define(GTP2_CAUSE_COMPLETE_DETACH, 3). +-define(GTP2_CAUSE_RAT_CHANGED_FROM_3GPP_TO_NON_3GPP, 4). +-define(GTP2_CAUSE_ISR_DEACTIVATION, 5). +-define(GTP2_CAUSE_ERROR_INDICATION_RECEIVED_FROM_RNC_ENODEB_S4_SGSN, 6). +-define(GTP2_CAUSE_IMSI_DETACH_ONLY, 7). +-define(GTP2_CAUSE_REACTIVATION_REQUESTED, 8). +-define(GTP2_CAUSE_PDN_RECONNECTION_TO_THIS_APN_DISALLOWED, 9). +-define(GTP2_CAUSE_ACCESS_CHANGED_FROM_NON_3GPP_TO_3GPP, 10). +-define(GTP2_CAUSE_PDN_CONNECTION_INACTIVITY_TIMER_EXPIRES, 11). +-define(GTP2_CAUSE_PGW_NOT_RESPONDING, 12). +-define(GTP2_CAUSE_NETWORK_FAILURE, 13). +-define(GTP2_CAUSE_QOS_PARAMETER_MISMATCH, 14). +-define(GTP2_CAUSE_REQUEST_ACCEPTED, 16). +-define(GTP2_CAUSE_REQUEST_ACCEPTED_PARTIALLY, 17). +-define(GTP2_CAUSE_NEW_PDN_TYPE_DUE_TO_NETWORK_PREFERENCE, 18). +-define(GTP2_CAUSE_NEW_PDN_TYPE_DUE_TO_SINGLE_ADDRESS_BEARER_ONLY, 19). +-define(GTP2_CAUSE_CONTEXT_NOT_FOUND, 64). +-define(GTP2_CAUSE_INVALID_MESSAGE_FORMAT, 65). +-define(GTP2_CAUSE_VERSION_NOT_SUPPORTED_BY_NEXT_PEER, 66). +-define(GTP2_CAUSE_INVALID_LENGTH, 67). +-define(GTP2_CAUSE_SERVICE_NOT_SUPPORTED, 68). +-define(GTP2_CAUSE_MANDATORY_IE_INCORRECT, 69). +-define(GTP2_CAUSE_MANDATORY_IE_MISSING, 70). +-define(GTP2_CAUSE_SYSTEM_FAILURE, 72). +-define(GTP2_CAUSE_NO_RESOURCES_AVAILABLE, 73). +-define(GTP2_CAUSE_SEMANTIC_ERROR_IN_THE_TFT_OPERATION, 74). +-define(GTP2_CAUSE_SYNTACTIC_ERROR_IN_THE_TFT_OPERATION, 75). +-define(GTP2_CAUSE_SEMANTIC_ERRORS_IN_PACKET_FILTER, 76). +-define(GTP2_CAUSE_SYNTACTIC_ERRORS_IN_PACKET_FILTER, 77). +-define(GTP2_CAUSE_MISSING_OR_UNKNOWN_APN, 78). +-define(GTP2_CAUSE_GRE_KEY_NOT_FOUND, 80). +-define(GTP2_CAUSE_RELOCATION_FAILURE, 81). +-define(GTP2_CAUSE_DENIED_IN_RAT, 82). +-define(GTP2_CAUSE_PREFERRED_PDN_TYPE_NOT_SUPPORTED, 83). +-define(GTP2_CAUSE_ALL_DYNAMIC_ADDRESSES_ARE_OCCUPIED, 84). +-define(GTP2_CAUSE_UE_CONTEXT_WITHOUT_TFT_ALREADY_ACTIVATED, 85). +-define(GTP2_CAUSE_PROTOCOL_TYPE_NOT_SUPPORTED, 86). +-define(GTP2_CAUSE_UE_NOT_RESPONDING, 87). +-define(GTP2_CAUSE_UE_REFUSES, 88). +-define(GTP2_CAUSE_SERVICE_DENIED, 89). +-define(GTP2_CAUSE_UNABLE_TO_PAGE_UE, 90). +-define(GTP2_CAUSE_NO_MEMORY_AVAILABLE, 91). +-define(GTP2_CAUSE_USER_AUTHENTICATION_FAILED, 92). +-define(GTP2_CAUSE_APN_ACCESS_DENIED___NO_SUBSCRIPTION, 93). +-define(GTP2_CAUSE_REQUEST_REJECTED, 94). +-define(GTP2_CAUSE_P_TMSI_SIGNATURE_MISMATCH, 95). +-define(GTP2_CAUSE_IMSI_IMEI_NOT_KNOWN, 96). +-define(GTP2_CAUSE_SEMANTIC_ERROR_IN_THE_TAD_OPERATION, 97). +-define(GTP2_CAUSE_SYNTACTIC_ERROR_IN_THE_TAD_OPERATION, 98). +-define(GTP2_CAUSE_REMOTE_PEER_NOT_RESPONDING, 100). +-define(GTP2_CAUSE_COLLISION_WITH_NETWORK_INITIATED_REQUEST, 101). +-define(GTP2_CAUSE_UNABLE_TO_PAGE_UE_DUE_TO_SUSPENSION, 102). +-define(GTP2_CAUSE_CONDITIONAL_IE_MISSING, 103). +-define(GTP2_CAUSE_APN_RESTRICTION_TYPE_INCOMPATIBLE_WITH_CURRENTLY_ACTIVE_PDN_CONNECTION, 104). +-define(GTP2_CAUSE_INVALID_OVERALL_LENGTH_OF_THE_TRIGGERED_RESPONSE_MESSAGE_AND_A_PIGGYBACKED_INITIAL_MESSAGE, 105). +-define(GTP2_CAUSE_DATA_FORWARDING_NOT_SUPPORTED, 106). +-define(GTP2_CAUSE_INVALID_REPLY_FROM_REMOTE_PEER, 107). +-define(GTP2_CAUSE_FALLBACK_TO_GTPV1, 108). +-define(GTP2_CAUSE_INVALID_PEER, 109). +-define(GTP2_CAUSE_TEMPORARILY_REJECTED_DUE_TO_HANDOVER_TAU_RAU_PROCEDURE_IN_PROGRESS, 110). +-define(GTP2_CAUSE_MODIFICATIONS_NOT_LIMITED_TO_S1_U_BEARERS, 111). +-define(GTP2_CAUSE_REQUEST_REJECTED_FOR_A_PMIPV6_REASON, 112). +-define(GTP2_CAUSE_APN_CONGESTION, 113). +-define(GTP2_CAUSE_BEARER_HANDLING_NOT_SUPPORTED, 114). +-define(GTP2_CAUSE_UE_ALREADY_RE_ATTACHED, 115). +-define(GTP2_CAUSE_MULTIPLE_PDN_CONNECTIONS_FOR_A_GIVEN_APN_NOT_ALLOWED, 116). +-define(GTP2_CAUSE_TARGET_ACCESS_RESTRICTED_FOR_THE_SUBSCRIBER, 117). +-define(GTP2_CAUSE_MME_SGSN_REFUSES_DUE_TO_VPLMN_POLICY, 119). +-define(GTP2_CAUSE_GTP_C_ENTITY_CONGESTION, 120). +-define(GTP2_CAUSE_LATE_OVERLAPPING_REQUEST, 121). +-define(GTP2_CAUSE_TIMED_OUT_REQUEST, 122). +-define(GTP2_CAUSE_UE_IS_TEMPORARILY_NOT_REACHABLE_DUE_TO_POWER_SAVING, 123). +-define(GTP2_CAUSE_RELOCATION_FAILURE_DUE_TO_NAS_MESSAGE_REDIRECTION, 124). +-define(GTP2_CAUSE_UE_NOT_AUTHORISED_BY_OCS_OR_EXTERNAL_AAA_SERVER, 125). +-define(GTP2_CAUSE_MULTIPLE_ACCESSES_TO_A_PDN_CONNECTION_NOT_ALLOWED, 126). +-define(GTP2_CAUSE_REQUEST_REJECTED_DUE_TO_UE_CAPABILITY, 127). +-define(GTP2_CAUSE_S1_U_PATH_FAILURE, 128). +-define(GTP2_CAUSE_5GC_NOT_ALLOWED, 129). \ No newline at end of file diff --git a/src/conv.erl b/src/conv.erl new file mode 100644 index 0000000..30365cc --- /dev/null +++ b/src/conv.erl @@ -0,0 +1,53 @@ +% Conversion tools +% (C) 2023 by sysmocom +% +% All Rights Reserved +% +% This program is free software; you can redistribute it and/or modify +% it under the terms of the GNU Affero General Public License as +% published by the Free Software Foundation; either version 3 of the +% License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU Affero General Public License +% along with this program. If not, see <http://www.gnu.org/licenses/>. +% +% Additional Permission under GNU AGPL version 3 section 7: +% +% If you modify this Program, or any covered work, by linking or +% combining it with runtime libraries of Erlang/OTP as released by +% Ericsson on http://www.erlang.org (or a modified version of these +% libraries), containing parts covered by the terms of the Erlang Public +% License (http://www.erlang.org/EPLICENSE), the licensors of this +% Program grant you additional permission to convey the resulting work +% without the need to license the runtime libraries of Erlang/OTP under +% the GNU Affero General Public License. Corresponding Source for a +% non-source form of such a combination shall include the source code +% for the parts of the runtime libraries of Erlang/OTP used as well as +% that of the covered work. +% +-module(conv). +-author('Pau Espin Pedrol <pes...@sysmocom.de>'). + +-include_lib("osmo_gsup/include/gsup_protocol.hrl"). +-include_lib("gtp_utils.hrl"). + +-export([cause_gtp2gsup/1]). + +-spec cause_gtp2gsup(integer()) -> integer(). + +cause_gtp2gsup(?GTP2_CAUSE_REQUEST_ACCEPTED) -> 0; +cause_gtp2gsup(?GTP2_CAUSE_IMSI_IMEI_NOT_KNOWN) -> ?GSUP_CAUSE_IMSI_UNKNOWN; +cause_gtp2gsup(?GTP2_CAUSE_INVALID_PEER) -> ?GSUP_CAUSE_ILLEGAL_MS; +cause_gtp2gsup(?GTP2_CAUSE_DENIED_IN_RAT) -> ?GSUP_CAUSE_GPRS_NOTALLOWED; +cause_gtp2gsup(?GTP2_CAUSE_NETWORK_FAILURE) -> ?GSUP_CAUSE_NET_FAIL; +cause_gtp2gsup(?GTP2_CAUSE_APN_CONGESTION) -> ?GSUP_CAUSE_CONGESTION; +cause_gtp2gsup(?GTP2_CAUSE_GTP_C_ENTITY_CONGESTION) -> ?GSUP_CAUSE_CONGESTION; +cause_gtp2gsup(?GTP2_CAUSE_USER_AUTHENTICATION_FAILED) -> ?GSUP_CAUSE_GSM_AUTH_UNACCEPT; +cause_gtp2gsup(?GTP2_CAUSE_MANDATORY_IE_INCORRECT) -> ?GSUP_CAUSE_INV_MAND_INFO; +cause_gtp2gsup(?GTP2_CAUSE_MANDATORY_IE_MISSING) -> ?GSUP_CAUSE_INV_MAND_INFO; +cause_gtp2gsup(_) -> ?GSUP_CAUSE_PROTO_ERR_UNSPEC. diff --git a/src/epdg_gtpc_s2b.erl b/src/epdg_gtpc_s2b.erl index fc41351..7e3dd6e 100644 --- a/src/epdg_gtpc_s2b.erl +++ b/src/epdg_gtpc_s2b.erl @@ -48,7 +48,7 @@ %% gen_server Function Exports -export([init/1, handle_call/3, handle_cast/2, handle_info/2]). -export([code_change/3]). --export([create_session_req/1]). +-export([create_session_req/1, delete_session_req/1]). %% Application Definitions -define(SERVER, ?MODULE). @@ -139,13 +139,28 @@ create_session_req(Imsi) -> gen_server:call(?SERVER, {gtpc_create_session_req, {Imsi}}). +delete_session_req(Imsi) -> + gen_server:call(?SERVER, {gtpc_delete_session_req, {Imsi}}). + handle_call({gtpc_create_session_req, {Imsi}}, {Pid, _Tag} = _From, State0) -> {Sess0, State1} = find_or_new_gtp_session(Imsi, Pid, State0), Req = gen_create_session_request(Sess0, State1), %TODO: increment State.seq_no. tx_gtp(Req, State1), lager:debug("Waiting for CreateSessionResponse~n", []), - {reply, ok, State1}. + {reply, ok, State1}; + +handle_call({gtpc_delete_session_req, {Imsi}}, _From, State) -> + Sess = find_gtp_session_by_imsi(Imsi, State), + case Sess of + #gtp_session{imsi = Imsi} -> + Req = gen_delete_session_request(Sess, State), + %TODO: increment State.seq_no. + tx_gtp(Req, State), + {reply, ok, State}; + undefined -> + {reply, {error, imsi_unknown}, State} + end. %% @callback gen_server handle_cast(stop, State) -> @@ -276,6 +291,18 @@ {noreply, State1} end; +rx_gtp(Resp = #gtp{version = v2, type = delete_session_response}, State0) -> + Sess = find_gtp_session_by_local_teic(Resp#gtp.tei, State0), + case Sess of + undefined -> + lager:error("Rx unknown TEI ~p: ~p~n", [Resp#gtp.tei, Resp]), + {noreply, State0}; + Sess -> + State1 = delete_gtp_session(Sess, State0), + ue_fsm:received_gtpc_delete_session_response(Sess#gtp_session.pid, Resp), + {noreply, State1} + end; + rx_gtp(Req = #gtp{version = v2, type = delete_bearer_request}, State) -> Sess = find_gtp_session_by_local_teic(Req#gtp.tei, State), case Sess of @@ -340,6 +367,22 @@ ], #gtp{version = v2, type = create_session_request, tei = 0, seq_no = SeqNo, ie = IEs}. +%% 7.2.9 Delete Session Request +gen_delete_session_request(#gtp_session{remote_control_tei = RemoteCtlTEI, + bearer = Bearer}, + #gtp_state{laddr = LocalAddr, + seq_no = SeqNo}) -> + IEs = [#v2_eps_bearer_id{eps_bearer_id = Bearer#gtp_bearer.ebi}, + #v2_fully_qualified_tunnel_endpoint_identifier{ + instance = Bearer#gtp_bearer.ebi, + interface_type = 30, %% "S2b ePDG GTP-C" + key = Bearer#gtp_bearer.local_data_tei, + ipv4 = gtp_utils:ip_to_bin(LocalAddr) + } + ], + #gtp{version = v2, type = delete_session_request, tei = RemoteCtlTEI, seq_no = SeqNo, ie = IEs}. + + gen_delete_bearer_response(Req = #gtp{version = v2, type = delete_bearer_request}, Sess = #gtp_session{remote_control_tei = RemoteCtlTEI}, GtpCause, diff --git a/src/gsup_server.erl b/src/gsup_server.erl index 30e8864..cebcc0f 100644 --- a/src/gsup_server.erl +++ b/src/gsup_server.erl @@ -62,7 +62,7 @@ -export([init/1, handle_call/3, handle_cast/2, handle_info/2]). -export([code_change/3, terminate/2]). --export([auth_response/2, lu_response/2, tunnel_response/2]). +-export([auth_response/2, lu_response/2, tunnel_response/2, purge_ms_response/2]). % TODO: -spec dia_sip2gsup('SIP-Auth-Data-Item'()) -> #'GSUPAuthTuple'{}. dia_sip2gsup(#'SIP-Auth-Data-Item'{'SIP-Authenticate' = [Authenticate], 'SIP-Authorization' = [Authorization], @@ -182,6 +182,25 @@ tx_gsup(Socket, Resp), {noreply, State}; +handle_cast({purge_ms_response, {Imsi, Result}}, State0) -> + lager:info("purge_ms_response for ~p: ~p~n", [Imsi, Result]), + Socket = State0#gsups_state.socket, + case Result of + ok -> + Resp = #{message_type => purge_ms_res, + imsi => Imsi, + freeze_p_tmsi => true + }; + {error, GsupCause} -> + Resp = #{message_type => purge_ms_err, + imsi => Imsi, + cause => GsupCause + } + end, + tx_gsup(Socket, Resp), + State1 = delete_gsups_ue(Imsi, State0), + {noreply, State1}; + handle_cast(Info, S) -> error_logger:error_report(["unknown handle_cast", {module, ?MODULE}, {info, Info}, {state, S}]), {noreply, S}. @@ -269,6 +288,31 @@ end, {noreply, State}; +% Purge MS / trigger the delete of session to the PGW +handle_info({ipa, Socket, ?IPAC_PROTO_EXT_GSUP, GsupMsgRx = #{message_type := purge_ms_req, imsi := Imsi}}, State) -> + lager:info("GSUP: Rx ~p~n", [GsupMsgRx]), + UE = find_gsups_ue_by_imsi(Imsi, State), + case UE of + #gsups_ue{imsi = Imsi} -> + case ue_fsm:purge_ms_request(UE#gsups_ue.pid) of + ok -> ok; + _ -> Resp = #{message_type => purge_ms_err, + imsi => Imsi, + message_class => 5, + cause => ?GSUP_CAUSE_NET_FAIL + }, + tx_gsup(Socket, Resp) + end; + undefined -> + Resp = #{message_type => purge_ms_err, + imsi => Imsi, + message_class => 5, + cause => ?GSUP_CAUSE_IMSI_UNKNOWN + }, + tx_gsup(Socket, Resp) + end, + {noreply, State}; + handle_info(Info, S) -> error_logger:error_report(["unknown handle_info", {module, ?MODULE}, {info, Info}, {state, S}]), {noreply, S}. @@ -291,6 +335,10 @@ lager:info("tunnel_response(~p): ~p~n", [Imsi, Result]), gen_server:cast(?SERVER, {tunnel_response, {Imsi, Result}}). +purge_ms_response(Imsi, Result) -> + lager:info("purge_ms_response(~p): ~p~n", [Imsi, Result]), + gen_server:cast(?SERVER, {purge_ms_response, {Imsi, Result}}). + %% ------------------------------------------------------------------ %% Internal Function Definitions %% ------------------------------------------------------------------ @@ -322,4 +370,8 @@ {UE, State}; undefined -> new_gsups_ue(Imsi, State) - end. \ No newline at end of file + end. + +delete_gsups_ue(Imsi, State) -> + SetRemoved = sets:del_element(Imsi, State#gsups_state.ues), + State#gsups_state{ues = SetRemoved}. \ No newline at end of file diff --git a/src/gtp_utils.erl b/src/gtp_utils.erl index 85f69ef..eb0a23a 100644 --- a/src/gtp_utils.erl +++ b/src/gtp_utils.erl @@ -35,7 +35,7 @@ -module(gtp_utils). -author('Alexander Couzens <lyn...@fe80.eu>'). --export([ip_to_bin/1, plmn_to_bin/3]). +-export([ip_to_bin/1, plmn_to_bin/3, enum_v2_cause/1]). % ergw_aaa/src/ergw_aaa_3gpp_dict.erl % under GPLv2+ @@ -52,3 +52,84 @@ MCC = iolist_to_binary(io_lib:format("~3..0b", [CC])), MNC = iolist_to_binary(io_lib:format("~*..0b", [NCSize, NC])), {MCC, MNC}. + +enum_v2_cause(reserved) -> 1; +enum_v2_cause(local_detach) -> 2; +enum_v2_cause(complete_detach) -> 3; +enum_v2_cause(rat_changed_from_3gpp_to_non_3gpp) -> 4; +enum_v2_cause(isr_deactivation) -> 5; +enum_v2_cause(error_indication_received_from_rnc_enodeb_s4_sgsn) -> 6; +enum_v2_cause(imsi_detach_only) -> 7; +enum_v2_cause(reactivation_requested) -> 8; +enum_v2_cause(pdn_reconnection_to_this_apn_disallowed) -> 9; +enum_v2_cause(access_changed_from_non_3gpp_to_3gpp) -> 10; +enum_v2_cause(pdn_connection_inactivity_timer_expires) -> 11; +enum_v2_cause(pgw_not_responding) -> 12; +enum_v2_cause(network_failure) -> 13; +enum_v2_cause(qos_parameter_mismatch) -> 14; +enum_v2_cause(request_accepted) -> 16; +enum_v2_cause(request_accepted_partially) -> 17; +enum_v2_cause(new_pdn_type_due_to_network_preference) -> 18; +enum_v2_cause(new_pdn_type_due_to_single_address_bearer_only) -> 19; +enum_v2_cause(context_not_found) -> 64; +enum_v2_cause(invalid_message_format) -> 65; +enum_v2_cause(version_not_supported_by_next_peer) -> 66; +enum_v2_cause(invalid_length) -> 67; +enum_v2_cause(service_not_supported) -> 68; +enum_v2_cause(mandatory_ie_incorrect) -> 69; +enum_v2_cause(mandatory_ie_missing) -> 70; +enum_v2_cause(system_failure) -> 72; +enum_v2_cause(no_resources_available) -> 73; +enum_v2_cause(semantic_error_in_the_tft_operation) -> 74; +enum_v2_cause(syntactic_error_in_the_tft_operation) -> 75; +enum_v2_cause(semantic_errors_in_packet_filter) -> 76; +enum_v2_cause(syntactic_errors_in_packet_filter) -> 77; +enum_v2_cause(missing_or_unknown_apn) -> 78; +enum_v2_cause(gre_key_not_found) -> 80; +enum_v2_cause(relocation_failure) -> 81; +enum_v2_cause(denied_in_rat) -> 82; +enum_v2_cause(preferred_pdn_type_not_supported) -> 83; +enum_v2_cause(all_dynamic_addresses_are_occupied) -> 84; +enum_v2_cause(ue_context_without_tft_already_activated) -> 85; +enum_v2_cause(protocol_type_not_supported) -> 86; +enum_v2_cause(ue_not_responding) -> 87; +enum_v2_cause(ue_refuses) -> 88; +enum_v2_cause(service_denied) -> 89; +enum_v2_cause(unable_to_page_ue) -> 90; +enum_v2_cause(no_memory_available) -> 91; +enum_v2_cause(user_authentication_failed) -> 92; +enum_v2_cause(apn_access_denied___no_subscription) -> 93; +enum_v2_cause(request_rejected) -> 94; +enum_v2_cause(p_tmsi_signature_mismatch) -> 95; +enum_v2_cause(imsi_imei_not_known) -> 96; +enum_v2_cause(semantic_error_in_the_tad_operation) -> 97; +enum_v2_cause(syntactic_error_in_the_tad_operation) -> 98; +enum_v2_cause(remote_peer_not_responding) -> 100; +enum_v2_cause(collision_with_network_initiated_request) -> 101; +enum_v2_cause(unable_to_page_ue_due_to_suspension) -> 102; +enum_v2_cause(conditional_ie_missing) -> 103; +enum_v2_cause(apn_restriction_type_incompatible_with_currently_active_pdn_connection) -> 104; +enum_v2_cause(invalid_overall_length_of_the_triggered_response_message_and_a_piggybacked_initial_message) -> 105; +enum_v2_cause(data_forwarding_not_supported) -> 106; +enum_v2_cause(invalid_reply_from_remote_peer) -> 107; +enum_v2_cause(fallback_to_gtpv1) -> 108; +enum_v2_cause(invalid_peer) -> 109; +enum_v2_cause(temporarily_rejected_due_to_handover_tau_rau_procedure_in_progress) -> 110; +enum_v2_cause(modifications_not_limited_to_s1_u_bearers) -> 111; +enum_v2_cause(request_rejected_for_a_pmipv6_reason) -> 112; +enum_v2_cause(apn_congestion) -> 113; +enum_v2_cause(bearer_handling_not_supported) -> 114; +enum_v2_cause(ue_already_re_attached) -> 115; +enum_v2_cause(multiple_pdn_connections_for_a_given_apn_not_allowed) -> 116; +enum_v2_cause(target_access_restricted_for_the_subscriber) -> 117; +enum_v2_cause(mme_sgsn_refuses_due_to_vplmn_policy) -> 119; +enum_v2_cause(gtp_c_entity_congestion) -> 120; +enum_v2_cause(late_overlapping_request) -> 121; +enum_v2_cause(timed_out_request) -> 122; +enum_v2_cause(ue_is_temporarily_not_reachable_due_to_power_saving) -> 123; +enum_v2_cause(relocation_failure_due_to_nas_message_redirection) -> 124; +enum_v2_cause(ue_not_authorised_by_ocs_or_external_aaa_server) -> 125; +enum_v2_cause(multiple_accesses_to_a_pdn_connection_not_allowed) -> 126; +enum_v2_cause(request_rejected_due_to_ue_capability) -> 127; +enum_v2_cause(s1_u_path_failure) -> 128; +enum_v2_cause('5gc_not_allowed') -> 129. diff --git a/src/ue_fsm.erl b/src/ue_fsm.erl index c0b8872..f17dfdc 100644 --- a/src/ue_fsm.erl +++ b/src/ue_fsm.erl @@ -34,10 +34,14 @@ -behaviour(gen_statem). -define(NAME, ue_fsm). +-include_lib("osmo_gsup/include/gsup_protocol.hrl"). +-include_lib("gtplib/include/gtp_packet.hrl"). + -export([start_link/1]). -export([init/1,callback_mode/0,terminate/3]). --export([auth_request/1, lu_request/1, tunnel_request/1, received_gtpc_create_session_response/2]). --export([state_new/3,state_authenticated/3]). +-export([auth_request/1, lu_request/1, tunnel_request/1, purge_ms_request/1]). +-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]). -record(ue_fsm_data, { imsi @@ -75,6 +79,15 @@ {error, Err} end. +purge_ms_request(Pid) -> + lager:info("ue_fsm purge_ms_request~n", []), + try + gen_statem:call(Pid, purge_ms_request) + 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 @@ -84,6 +97,23 @@ {error, Err} end. +received_gtpc_delete_session_response(Pid, Msg) -> + lager:info("ue_fsm received_gtpc_delete_session_response ~p~n", [Msg]), + try + gen_statem:call(Pid, {received_gtpc_delete_session_response, Msg}) + catch + exit:Err -> + {error, Err} + end. + +%% ------------------------------------------------------------------ +%% Internal helpers +%% ------------------------------------------------------------------ + +%% ------------------------------------------------------------------ +%% gen_statem Function Definitions +%% ------------------------------------------------------------------ + init(Imsi) -> lager:info("ue_fsm init(~p)~n", [Imsi]), Data = #ue_fsm_data{imsi = Imsi}, @@ -105,7 +135,11 @@ {next_state, state_authenticated, Data, [{reply,From,ok}]}; {error, Err} -> {stop_and_reply, Err, Data, [{reply,From,{error,Err}}]} - end. + 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_authenticated({call, From}, lu_request, Data) -> lager:info("ue_fsm state_authenticated event=lu_request, ~p~n", [Data]), @@ -128,10 +162,33 @@ gsup_server:tunnel_response(Data#ue_fsm_data.imsi, Result), {keep_state, Data, [{reply,From,ok}]}; +state_authenticated({call, From}, purge_ms_request, Data) -> + lager:info("ue_fsm state_authenticated event=purge_ms_request, ~p~n", [Data]), + case epdg_gtpc_s2b:delete_session_req(Data#ue_fsm_data.imsi) of + ok -> {next_state, state_wait_delete_session_resp, Data, [{reply,From,ok}]}; + {error, Err} -> {keep_state, Data, [{reply,From,{error, Err}}]} + end; + state_authenticated({call, From}, _Whatever, Data) -> lager:error("ue_fsm state_authenticated: Unexpected call event, ~p~n", [Data]), {keep_state, Data, [{reply,From,ok}]}; state_authenticated(cast, _Whatever, Data) -> lager:error("ue_fsm state_authenticated: Unexpected cast event, ~p~n", [Data]), - {keep_state, Data}. \ No newline at end of file + {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, + GtpCause = gtp_utils:enum_v2_cause(CauseIE#v2_cause.v2_cause), + 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}) + end, + {keep_state, Data, [{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}}]}. -- To view, visit https://gerrit.osmocom.org/c/erlang/osmo-epdg/+/35676?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: I2e922f76c2fa601c5f61fa23d6df5fb62c3e133d Gerrit-Change-Number: 35676 Gerrit-PatchSet: 1 Gerrit-Owner: pespin <pes...@sysmocom.de> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: pespin <pes...@sysmocom.de> Gerrit-MessageType: merged