pespin has submitted this change. ( https://gerrit.osmocom.org/c/erlang/osmo-epdg/+/36112?usp=email )
Change subject: s2b: Handle CreateSession with failed Cause ......................................................................
s2b: Handle CreateSession with failed Cause
Related: OS#6371 Change-Id: I7bc840e863c0a1eff3b1df2c42f6b1868dec8dae --- M src/epdg_gtpc_s2b.erl M src/epdg_ue_fsm.erl M src/gsup_server.erl M src/gtp_utils.erl 4 files changed, 89 insertions(+), 49 deletions(-)
Approvals: Jenkins Builder: Verified pespin: Looks good to me, approved laforge: Looks good to me, but someone else must approve
diff --git a/src/epdg_gtpc_s2b.erl b/src/epdg_gtpc_s2b.erl index cef9bab..b0a34bd 100644 --- a/src/epdg_gtpc_s2b.erl +++ b/src/epdg_gtpc_s2b.erl @@ -389,46 +389,13 @@ {noreply, State0}; Sess0 -> % Do GTP specific msg parsing here, pass only relevant fields: - #{{v2_fully_qualified_tunnel_endpoint_identifier,1} := - #v2_fully_qualified_tunnel_endpoint_identifier{ - interface_type = 32, %% "S2b PGW GTP-C" - key = RemoteTEIC, ipv4 = _IPc4, ipv6 = _IPc6}, - {v2_pdn_address_allocation,0} := Paa, - {v2_bearer_context,0} := #v2_bearer_context{instance = 0, group = BearerIE}} = Resp#gtp.ie, - % Parse BearerContext: - #{{v2_eps_bearer_id,0} := #v2_eps_bearer_id{instance = 0, eps_bearer_id = Ebi}, - {v2_fully_qualified_tunnel_endpoint_identifier,4} := - #v2_fully_qualified_tunnel_endpoint_identifier{ - interface_type = 33, %% "S2b-U PGW GTP-U" - key = RemoteTEID, ipv4 = IPu4, ipv6 = IPu6} - } = BearerIE, - Bearer = gtp_session_find_bearer_by_ebi(Sess0, Ebi), - Sess1 = gtp_session_update_bearer(Sess0, Bearer, Bearer#gtp_bearer{remote_data_tei = RemoteTEID}), - Sess2 = Sess1#gtp_session{remote_control_tei = RemoteTEIC}, - lager:info("s2b: Updated Session after create_session_response: ~p~n", [Sess2]), - State1 = update_gtp_session(Sess0, Sess2, State0), - case maps:find({v2_additional_protocol_configuration_options,0}, Resp#gtp.ie) of - {ok, APCO_dec} -> - lager:debug("s2b: APCO_dec: ~p~n", [APCO_dec]), - APCO = gtp_packet:encode_protocol_config_opts(APCO_dec#v2_additional_protocol_configuration_options.config); - error -> - lager:notice("s2b: APCO not found in CreateSessionResp!~n", []), - APCO = undefined - end, - ResInfo0 = #{ - apn => binary_to_list(Sess0#gtp_session.apn), - eua => conv:gtp2_paa_to_epdg_eua(Paa), - local_teid => Bearer#gtp_bearer.local_data_tei, - remote_teid => RemoteTEID, - remote_ipv4 => IPu4, - remote_ipv6 => IPu6 - }, - case APCO of - undefined -> ResInfo = ResInfo0; - _ -> ResInfo = maps:put(apco, APCO, ResInfo0) - end, - epdg_ue_fsm:received_gtpc_create_session_response(Sess0#gtp_session.pid, {ok, ResInfo}), - {noreply, State1} + % First lookup Cause: + #{{v2_cause,0} := #v2_cause{instance = 0, v2_cause = GtpCauseAtom}} = Resp#gtp.ie, + GtpCause = gtp_utils:enum_v2_cause(GtpCauseAtom), + case gtp_utils:v2_cause_successful(GtpCause) of + true -> rx_gtp_create_session_response_successful(Resp, Sess0, State0); + false -> rx_gtp_create_session_response_failure(GtpCause, Sess0, State0) + end end;
rx_gtp(Resp = #gtp{version = v2, type = delete_session_response}, State0) -> @@ -487,6 +454,54 @@ lager:error("S2b: UNIMPLEMENTED Rx: ~p~n", [Req]), {noreply, State}.
+ +rx_gtp_create_session_response_successful(Resp, Sess0, State0) -> + #{{v2_fully_qualified_tunnel_endpoint_identifier,1} := + #v2_fully_qualified_tunnel_endpoint_identifier{ + interface_type = 32, %% "S2b PGW GTP-C" + key = RemoteTEIC, ipv4 = _IPc4, ipv6 = _IPc6}, + {v2_pdn_address_allocation,0} := Paa, + {v2_bearer_context,0} := #v2_bearer_context{instance = 0, group = BearerIE}} = Resp#gtp.ie, + % Parse BearerContext: + #{{v2_eps_bearer_id,0} := #v2_eps_bearer_id{instance = 0, eps_bearer_id = Ebi}, + {v2_fully_qualified_tunnel_endpoint_identifier,4} := + #v2_fully_qualified_tunnel_endpoint_identifier{ + interface_type = 33, %% "S2b-U PGW GTP-U" + key = RemoteTEID, ipv4 = IPu4, ipv6 = IPu6} + } = BearerIE, + Bearer = gtp_session_find_bearer_by_ebi(Sess0, Ebi), + Sess1 = gtp_session_update_bearer(Sess0, Bearer, Bearer#gtp_bearer{remote_data_tei = RemoteTEID}), + Sess2 = Sess1#gtp_session{remote_control_tei = RemoteTEIC}, + lager:info("s2b: Updated Session after create_session_response: ~p~n", [Sess2]), + State1 = update_gtp_session(Sess0, Sess2, State0), + case maps:find({v2_additional_protocol_configuration_options,0}, Resp#gtp.ie) of + {ok, APCO_dec} -> + lager:debug("s2b: APCO_dec: ~p~n", [APCO_dec]), + APCO = gtp_packet:encode_protocol_config_opts(APCO_dec#v2_additional_protocol_configuration_options.config); + error -> + lager:notice("s2b: APCO not found in CreateSessionResp!~n", []), + APCO = undefined + end, + ResInfo0 = #{ + apn => binary_to_list(Sess0#gtp_session.apn), + eua => conv:gtp2_paa_to_epdg_eua(Paa), + local_teid => Bearer#gtp_bearer.local_data_tei, + remote_teid => RemoteTEID, + remote_ipv4 => IPu4, + remote_ipv6 => IPu6 + }, + case APCO of + undefined -> ResInfo = ResInfo0; + _ -> ResInfo = maps:put(apco, APCO, ResInfo0) + end, + epdg_ue_fsm:received_gtpc_create_session_response(Sess0#gtp_session.pid, {ok, ResInfo}), + {noreply, State1}. + +rx_gtp_create_session_response_failure(GtpCause, Sess, State0) -> + epdg_ue_fsm:received_gtpc_create_session_response(Sess#gtp_session.pid, {error, GtpCause}), + State1 = delete_gtp_session(Sess, State0), + {noreply, State1}. + tx_gtp(Req, State) -> lager:info("s2b: Tx ~p~n", [Req]), Msg = gtp_packet:encode(Req), diff --git a/src/epdg_ue_fsm.erl b/src/epdg_ue_fsm.erl index cf4d280..439cb3f 100644 --- a/src/epdg_ue_fsm.erl +++ b/src/epdg_ue_fsm.erl @@ -36,6 +36,7 @@
-include_lib("osmo_gsup/include/gsup_protocol.hrl"). -include_lib("gtplib/include/gtp_packet.hrl"). +-include_lib("gtp_utils.hrl"). -include("conv.hrl").
-export([start_link/1, stop/1]). @@ -288,11 +289,14 @@ eua = EUA, peer_addr = RemoteIPv4}, Ret = gtp_u_tun:create_pdp_context(TunPdpCtx), lager:debug("gtp_u_tun:create_pdp_context(~p) returned ~p~n", [ResInfo, Ret]), - Data1 = Data#ue_fsm_data{tun_pdp_ctx = TunPdpCtx}; - _ -> Data1 = Data - end, - gsup_server:tunnel_response(Data1#ue_fsm_data.imsi, Result), - {next_state, state_active, Data1, [{reply,From,ok}]}; + Data1 = Data#ue_fsm_data{tun_pdp_ctx = TunPdpCtx}, + gsup_server:tunnel_response(Data1#ue_fsm_data.imsi, Result), + {next_state, state_active, Data1, [{reply,From,ok}]}; + {error, GtpCause} -> + GsupCause = conv:cause_gtp2gsup(GtpCause), + gsup_server:tunnel_response(Data#ue_fsm_data.imsi, {error, GsupCause}), + {next_state, state_authenticated, Data, [{reply,From,ok}]} + end;
state_wait_create_session_resp({call, From}, Event, Data) -> lager:error("ue_fsm state_wait_delete_session_resp: Unexpected call event ~p, ~p~n", [Event, Data]), @@ -300,7 +304,7 @@
state_wait_create_session_resp(state_timeout, create_session_timeout, Data) -> lager:error("ue_fsm state_wait_create_session_resp: Timeout ~p, ~p~n", [create_session_timeout, Data]), - gsup_server:tunnel_response(Data#ue_fsm_data.imsi, {error, create_session_timeout}), + gsup_server:tunnel_response(Data#ue_fsm_data.imsi, {error, ?GSUP_CAUSE_CONGESTION}), {next_state, state_authenticated, Data}.
state_active(enter, _OldState, Data) -> diff --git a/src/gsup_server.erl b/src/gsup_server.erl index 1e5173e..3b69849 100644 --- a/src/gsup_server.erl +++ b/src/gsup_server.erl @@ -171,11 +171,11 @@ {ok, APCO} -> Resp = maps:put(pco, APCO, Resp0); error -> Resp = Resp0 end; - {error, _} -> + {error, GsupCause} -> Resp = #{message_type => epdg_tunnel_error, imsi => Imsi, message_class => 5, - cause => ?GSUP_CAUSE_NET_FAIL + cause => GsupCause } end, tx_gsup(Socket, Resp), diff --git a/src/gtp_utils.erl b/src/gtp_utils.erl index 6098da2..0cca8d2 100644 --- a/src/gtp_utils.erl +++ b/src/gtp_utils.erl @@ -35,7 +35,9 @@ -module(gtp_utils). -author('Alexander Couzens lynxis@fe80.eu').
--export([plmn_to_bin/3, enum_v2_cause/1]). +-include_lib("gtp_utils.hrl"). + +-export([plmn_to_bin/3, enum_v2_cause/1, v2_cause_successful/1]).
% ergw/apps/ergw/test/*.erl @@ -125,3 +127,12 @@ 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. + + +-spec v2_cause_successful(integer()) -> boolean(). + +v2_cause_successful(GtpCauseInt) -> + GtpCauseInt == ?GTP2_CAUSE_REQUEST_ACCEPTED orelse + GtpCauseInt == ?GTP2_CAUSE_REQUEST_ACCEPTED_PARTIALLY orelse + GtpCauseInt == ?GTP2_CAUSE_NEW_PDN_TYPE_DUE_TO_NETWORK_PREFERENCE orelse + GtpCauseInt == ?GTP2_CAUSE_NEW_PDN_TYPE_DUE_TO_SINGLE_ADDRESS_BEARER_ONLY.