pespin has submitted this change. ( https://gerrit.osmocom.org/c/erlang/osmo-epdg/+/36053?usp=email )
Change subject: Forward PCO from GSUP ePDG Tunnel Req to SMF CreateSessionRequest ......................................................................
Forward PCO from GSUP ePDG Tunnel Req to SMF CreateSessionRequest
A patch in gtplib was submitted to make it possible to encode/decode PCO payload.
Related: OS#6369 Change-Id: I51fba731e77c77a95b9310820ec7116f0e5abf8b --- M rebar.lock M src/epdg_gtpc_s2b.erl M src/epdg_ue_fsm.erl M src/gsup_server.erl 4 files changed, 61 insertions(+), 26 deletions(-)
Approvals: Jenkins Builder: Verified pespin: Looks good to me, approved
diff --git a/rebar.lock b/rebar.lock index da93a4f..79503ee 100644 --- a/rebar.lock +++ b/rebar.lock @@ -21,6 +21,10 @@ {git,"https://github.com/osmocom/gtp_u_kmod", {ref,"b3656ebb11528a2db3171dbf94f1a8bf0d6ffd00"}}, 0}, + {<<"gtplib">>, + {git,"https://github.com/osmocom/gtplib", + {ref,"526a7e5d6ba4e76aaae87c31421f26a71dd79d33"}}, + 0}, {<<"lager">>, {git,"https://github.com/erlang-lager/lager", {ref,"459a3b2cdd9eadd29e5a7ce5c43932f5ccd6eb88"}}, diff --git a/src/epdg_gtpc_s2b.erl b/src/epdg_gtpc_s2b.erl index f635036..a4ab573 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/2, delete_session_req/1]). +-export([create_session_req/3, delete_session_req/1]).
%% Application Definitions -define(SERVER, ?MODULE). @@ -142,17 +142,17 @@ lager:error("GTPv2C UDP socket open error: ~w~n", [Reason]) end.
-create_session_req(Imsi, Apn) -> - gen_server:call(?SERVER, {gtpc_create_session_req, {Imsi, Apn}}). +create_session_req(Imsi, Apn, APCO) -> + gen_server:call(?SERVER, {gtpc_create_session_req, {Imsi, Apn, APCO}}).
delete_session_req(Imsi) -> gen_server:call(?SERVER, {gtpc_delete_session_req, {Imsi}}).
-handle_call({gtpc_create_session_req, {Imsi, Apn}}, {Pid, _Tag} = _From, State0) -> +handle_call({gtpc_create_session_req, {Imsi, Apn, APCO}}, {Pid, _Tag} = _From, State0) -> {Sess0, State1} = find_or_new_gtp_session(Imsi, #gtp_session{pid = Pid, apn = list_to_binary(Apn)}, State0), - Req = gen_create_session_request(Sess0, State1), + Req = gen_create_session_request(Sess0, APCO, State1), tx_gtp(Req, State1), State2 = inc_seq_no(State1), lager:debug("Waiting for CreateSessionResponse~n", []), @@ -385,7 +385,15 @@ 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), - ResInfo = #{ + 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, @@ -393,6 +401,10 @@ 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} end; @@ -462,6 +474,7 @@ gen_create_session_request(#gtp_session{imsi = Imsi, apn = Apn, local_control_tei = LocalCtlTEI} = Sess, + APCO, #gtp_state{laddr = LocalAddr, laddr_gtpu = LocalAddrGtpu, restart_counter = RCnt, @@ -482,6 +495,7 @@ ipv4 = conv:ip_to_bin(LocalAddrGtpu) } ], + APCO_decoded = gtp_packet:decode_protocol_config_opts(APCO), IEs = [#v2_international_mobile_subscriber_identity{imsi = Imsi}, #v2_serving_network{ plmn_id = gtp_utils:plmn_to_bin(?MCC, ?MNC, ?MNC_SIZE) @@ -497,7 +511,8 @@ #v2_selection_mode{mode = 0}, #v2_pdn_address_allocation{type = ipv4, address = <<0,0,0,0>>}, #v2_bearer_context{group = BearersIE}, - #v2_recovery{restart_counter = RCnt} + #v2_recovery{restart_counter = RCnt}, + #v2_additional_protocol_configuration_options{instance = 0, config = APCO_decoded} ], #gtp{version = v2, type = create_session_request, tei = 0, seq_no = SeqNo, ie = IEs}.
diff --git a/src/epdg_ue_fsm.erl b/src/epdg_ue_fsm.erl index 188d461..cf4d280 100644 --- a/src/epdg_ue_fsm.erl +++ b/src/epdg_ue_fsm.erl @@ -41,7 +41,7 @@ -export([start_link/1, stop/1]). -export([init/1,callback_mode/0,terminate/3]). -export([get_server_name_by_imsi/1, get_pid_by_imsi/1]). --export([auth_request/2, lu_request/1, tunnel_request/1, 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_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, @@ -90,10 +90,10 @@ {error, Err} end.
-tunnel_request(Pid) -> - lager:info("ue_fsm tunnel_request~n", []), +tunnel_request(Pid, PCO) -> + lager:info("ue_fsm tunnel_request(~p)~n", [PCO]), try - gen_statem:call(Pid, tunnel_request) + gen_statem:call(Pid, {tunnel_request, PCO}) catch exit:Err -> {error, Err} @@ -248,9 +248,9 @@ lager:info("ue_fsm state_authenticated event=auth_request {~p, ~p}, ~p~n", [PdpTypeNr, Apn, Data]), {next_state, state_new, Data, [postpone]};
-state_authenticated({call, From}, tunnel_request, Data) -> +state_authenticated({call, From}, {tunnel_request, PCO}, Data) -> lager:info("ue_fsm state_authenticated event=tunnel_request, ~p~n", [Data]), - epdg_gtpc_s2b:create_session_req(Data#ue_fsm_data.imsi, Data#ue_fsm_data.apn), + epdg_gtpc_s2b:create_session_req(Data#ue_fsm_data.imsi, Data#ue_fsm_data.apn, PCO), {next_state, state_wait_create_session_resp, Data, [{reply,From,ok}]};
state_authenticated({call, From}, purge_ms_request, Data) -> diff --git a/src/gsup_server.erl b/src/gsup_server.erl index 0af015c..1e5173e 100644 --- a/src/gsup_server.erl +++ b/src/gsup_server.erl @@ -156,18 +156,21 @@ lager:info("tunnel_response for ~p: ~p~n", [Imsi, Result]), Socket = State#gsups_state.socket, case Result of - {ok, #{apn := Apn, eua := Eua}} -> + {ok, #{apn := Apn, eua := Eua} = Map} -> PdpInfo = #{pdp_context_id => 0, - pdp_address => conv:epdg_eua_to_gsup_pdp_address(Eua), - access_point_name => Apn, - quality_of_service => <<0, 0, 0>>, - pdp_charging => 0}, - Resp = #{message_type => epdg_tunnel_result, - imsi => Imsi, - message_class => 5, - pdp_info_complete => true, - pdp_info_list => [PdpInfo] - }; + pdp_address => conv:epdg_eua_to_gsup_pdp_address(Eua), + access_point_name => Apn, + quality_of_service => <<0, 0, 0>>, + pdp_charging => 0}, + Resp0 = #{message_type => epdg_tunnel_result, + imsi => Imsi, + message_class => 5, + pdp_info_complete => true, + pdp_info_list => [PdpInfo]}, + case maps:find(apco, Map) of + {ok, APCO} -> Resp = maps:put(pco, APCO, Resp0); + error -> Resp = Resp0 + end; {error, _} -> Resp = #{message_type => epdg_tunnel_error, imsi => Imsi, @@ -286,12 +289,12 @@
% epdg tunnel request / trigger the establishment to the PGW and prepares everything for the user traffic to flow % When sending a epdg_tunnel_response everything must be ready for the UE traffic -handle_info({ipa, Socket, ?IPAC_PROTO_EXT_GSUP, GsupMsgRx = #{message_type := epdg_tunnel_request, imsi := Imsi}}, State) -> +handle_info({ipa, Socket, ?IPAC_PROTO_EXT_GSUP, GsupMsgRx = #{message_type := epdg_tunnel_request, imsi := Imsi, pco := PCO}}, State) -> lager:info("GSUP: Rx ~p~n", [GsupMsgRx]), UE = find_gsups_ue_by_imsi(Imsi, State), case UE of #gsups_ue{imsi = Imsi} -> - case epdg_ue_fsm:tunnel_request(UE#gsups_ue.pid) of + case epdg_ue_fsm:tunnel_request(UE#gsups_ue.pid, PCO) of ok -> ok; {error, _} -> Resp = #{message_type => epdg_tunnel_error,