fixeria has uploaded this change for review. ( https://gerrit.osmocom.org/c/erlang/osmo-s1gw/+/39463?usp=email )
Change subject: s1ap_proxy: handle UE CONTEXT RELEASE PDUs ...................................................................... s1ap_proxy: handle UE CONTEXT RELEASE PDUs On receipt of UE CONTEXT RELEASE PDUs, signal the release of all affected E-RAB FSMs with the matching {MME,eNB}-UE-S1AP-ID. Change-Id: Ic94489e3d3052221b49431da3a95e5c1eb0e0ba0 Related: osmo-ttcn3-hacks.git I065692f311e9d03630ab3ca2f6a03465418f0e71 Related: SYS#7310 --- M include/s1gw_metrics.hrl M src/s1ap_proxy.erl M src/s1gw_metrics.erl M test/s1ap_proxy_test.erl 4 files changed, 149 insertions(+), 1 deletion(-) git pull ssh://gerrit.osmocom.org:29418/erlang/osmo-s1gw refs/changes/63/39463/1 diff --git a/include/s1gw_metrics.hrl b/include/s1gw_metrics.hrl index 77d6a8e..268b2e9 100644 --- a/include/s1gw_metrics.hrl +++ b/include/s1gw_metrics.hrl @@ -24,6 +24,9 @@ -define(S1GW_CTR_S1AP_PROXY_IN_PKT_ERAB_MOD_IND, [ctr, s1ap, proxy, in_pkt, erab_mod_ind]). -define(S1GW_CTR_S1AP_PROXY_IN_PKT_INIT_CTX_REQ, [ctr, s1ap, proxy, in_pkt, init_ctx_req]). -define(S1GW_CTR_S1AP_PROXY_IN_PKT_INIT_CTX_RSP, [ctr, s1ap, proxy, in_pkt, init_ctx_rsp]). +-define(S1GW_CTR_S1AP_PROXY_IN_PKT_RELEASE_CTX_REQ, [ctr, s1ap, proxy, in_pkt, release_ctx_req]). +-define(S1GW_CTR_S1AP_PROXY_IN_PKT_RELEASE_CTX_CMD, [ctr, s1ap, proxy, in_pkt, release_ctx_cmd]). +-define(S1GW_CTR_S1AP_PROXY_IN_PKT_RELEASE_CTX_COMPL, [ctr, s1ap, proxy, in_pkt, release_ctx_cnf]). -define(S1GW_CTR_S1AP_PROXY_OUT_PKT_FWD_ALL, [ctr, s1ap, proxy, out_pkt, forward, all]). -define(S1GW_CTR_S1AP_PROXY_OUT_PKT_FWD_PROC, [ctr, s1ap, proxy, out_pkt, forward, proc]). -define(S1GW_CTR_S1AP_PROXY_OUT_PKT_FWD_UNMODIFIED, [ctr, s1ap, proxy, out_pkt, forward, unmodified]). diff --git a/src/s1ap_proxy.erl b/src/s1ap_proxy.erl index f04fb61..56e5dee 100644 --- a/src/s1ap_proxy.erl +++ b/src/s1ap_proxy.erl @@ -172,6 +172,28 @@ {MmeUeId, EnbUeId, ERABId}. +-spec erab_for_each(UID, Fun, ERABs) -> ok + when UID :: {mme_ue_id(), enb_ue_id()} | {mme_ue_id()}, + Fun :: fun((pid()) -> term()), + ERABs :: [{erab_uid(), pid()}]. +erab_for_each({MMEUEId, ENBUEId} = UID, Fun, + [{{MMEUEId, ENBUEId, _}, Pid} | ERABs]) -> + Fun(Pid), %% matched by a pair of {MME,eNB}-UE-S1AP-ID + erab_for_each(UID, Fun, ERABs); + +erab_for_each({MMEUEId} = UID, Fun, + [{{MMEUEId, _, _}, Pid} | ERABs]) -> + Fun(Pid), %% matched by an MME-UE-S1AP-ID + erab_for_each(UID, Fun, ERABs); + +erab_for_each(UID, Fun, + [_ERAB | ERABs]) -> + erab_for_each(UID, Fun, ERABs); + +erab_for_each(_UID, _Fun, []) -> + ok. + + %% Encode an S1AP PDU -spec encode_pdu(s1ap_pdu()) -> {ok, binary()} | {error, {asn1, tuple()}}. @@ -377,6 +399,66 @@ {forward, S1} %% XXX: forward as-is or drop? end; +%% 9.1.4.5 UE CONTEXT RELEASE REQUEST +handle_pdu({initiatingMessage, + #'InitiatingMessage'{procedureCode = ?'id-UEContextReleaseRequest', + value = #'UEContextReleaseRequest'{protocolIEs = IEs}}}, + #proxy_state{erabs = ERABs} = S) -> + ?LOG_DEBUG("Processing UE CONTEXT RELEASE REQUEST"), + s1gw_metrics:ctr_inc(?S1GW_CTR_S1AP_PROXY_IN_PKT_RELEASE_CTX_REQ), + %% fetch {MME,eNB}-UE-S1AP-ID values (mandatory IEs) + #'ProtocolIE-Field'{id = ?'id-MME-UE-S1AP-ID', + value = MMEUEId} = lists:nth(1, IEs), + #'ProtocolIE-Field'{id = ?'id-eNB-UE-S1AP-ID', + value = ENBUEId} = lists:nth(2, IEs), + %% poke E-RAB FSMs with the matching {MME,eNB}-UE-S1AP-ID + erab_for_each({MMEUEId, ENBUEId}, + fun erab_fsm:erab_release_ind/1, + dict:to_list(ERABs)), + {forward, S}; %% forward as-is, there's nothing to patch + +%% 9.1.4.6 UE CONTEXT RELEASE COMMAND +handle_pdu({initiatingMessage, + #'InitiatingMessage'{procedureCode = ?'id-UEContextRelease', + value = #'UEContextReleaseCommand'{protocolIEs = IEs}}}, + #proxy_state{erabs = ERABs} = S) -> + ?LOG_DEBUG("Processing UE CONTEXT RELEASE COMMAND"), + s1gw_metrics:ctr_inc(?S1GW_CTR_S1AP_PROXY_IN_PKT_RELEASE_CTX_CMD), + #'ProtocolIE-Field'{id = ?'id-UE-S1AP-IDs', + value = S1APIDs} = lists:nth(1, IEs), + case S1APIDs of + {'uE-S1AP-ID-pair', #'UE-S1AP-ID-pair'{'mME-UE-S1AP-ID' = MMEUEId, + 'eNB-UE-S1AP-ID' = ENBUEId}} -> + %% poke E-RAB FSMs with the matching {MME,eNB}-UE-S1AP-ID + erab_for_each({MMEUEId, ENBUEId}, + fun erab_fsm:erab_release_cmd/1, + dict:to_list(ERABs)); + {'mME-UE-S1AP-ID', MMEUEId} -> + %% poke E-RAB FSMs with the matching MME-UE-S1AP-ID + erab_for_each({MMEUEId}, + fun erab_fsm:erab_release_cmd/1, + dict:to_list(ERABs)) + end, + {forward, S}; %% forward as-is, there's nothing to patch + +%% 9.1.4.7 UE CONTEXT RELEASE COMPLETE +handle_pdu({successfulOutcome, + #'SuccessfulOutcome'{procedureCode = ?'id-UEContextRelease', + value = #'UEContextReleaseComplete'{protocolIEs = IEs}}}, + #proxy_state{erabs = ERABs} = S) -> + ?LOG_DEBUG("Processing UE CONTEXT RELEASE COMPLETE"), + s1gw_metrics:ctr_inc(?S1GW_CTR_S1AP_PROXY_IN_PKT_RELEASE_CTX_COMPL), + %% fetch {MME,eNB}-UE-S1AP-ID values (mandatory IEs) + #'ProtocolIE-Field'{id = ?'id-MME-UE-S1AP-ID', + value = MMEUEId} = lists:nth(1, IEs), + #'ProtocolIE-Field'{id = ?'id-eNB-UE-S1AP-ID', + value = ENBUEId} = lists:nth(2, IEs), + %% poke E-RAB FSMs with the matching {MME,eNB}-UE-S1AP-ID + erab_for_each({MMEUEId, ENBUEId}, + fun erab_fsm:erab_release_rsp/1, + dict:to_list(ERABs)), + {forward, S}; %% forward as-is, there's nothing to patch + %% TODO: 9.1.5.2 HANDOVER COMMAND :: (O) UL/DL Transport Layer Address %% TODO: 9.1.5.4 HANDOVER REQUEST :: (M) Transport Layer Address %% TODO: 9.1.5.5 HANDOVER REQUEST ACKNOWLEDGE :: (M) Transport Layer Address, diff --git a/src/s1gw_metrics.erl b/src/s1gw_metrics.erl index 55421e7..50cab10 100644 --- a/src/s1gw_metrics.erl +++ b/src/s1gw_metrics.erl @@ -75,6 +75,9 @@ ?S1GW_CTR_S1AP_PROXY_IN_PKT_ERAB_MOD_IND, %% E-RAB MODIFY.ind PDUs ?S1GW_CTR_S1AP_PROXY_IN_PKT_INIT_CTX_REQ, %% INITIAL CONTEXT SETUP.req PDUs ?S1GW_CTR_S1AP_PROXY_IN_PKT_INIT_CTX_RSP, %% INITIAL CONTEXT SETUP.rsp PDUs + ?S1GW_CTR_S1AP_PROXY_IN_PKT_RELEASE_CTX_REQ, %% UE CONTEXT RELEASE.req PDUs + ?S1GW_CTR_S1AP_PROXY_IN_PKT_RELEASE_CTX_CMD, %% UE CONTEXT RELEASE.cmd PDUs + ?S1GW_CTR_S1AP_PROXY_IN_PKT_RELEASE_CTX_COMPL, %% UE CONTEXT RELEASE.compl PDUs %% s1ap_proxy: OUTgoing PDU counters ?S1GW_CTR_S1AP_PROXY_OUT_PKT_FWD_ALL, %% forwarded: total ?S1GW_CTR_S1AP_PROXY_OUT_PKT_FWD_PROC, %% forwarded: processed diff --git a/test/s1ap_proxy_test.erl b/test/s1ap_proxy_test.erl index 917b63e..ce9032e 100644 --- a/test/s1ap_proxy_test.erl +++ b/test/s1ap_proxy_test.erl @@ -45,7 +45,11 @@ {"E-RAB MODIFICATION INDICATION", ?TC(fun test_e_rab_modify_ind/1)}, {"INITIAL CONTEXT SETUP REQUEST/RESPONSE", - ?TC(fun test_initial_context_setup/1)}]. + ?TC(fun test_initial_context_setup/1)}, + {"UE CONTEXT RELEASE REQUEST", + ?TC(fun test_ue_ctx_release_req/1)}, + {"UE CONTEXT RELEASE COMMAND/COMPLETE", + ?TC(fun test_ue_ctx_release_cmd/1)}]. %% ------------------------------------------------------------------ @@ -139,6 +143,37 @@ ?_assertMatch([_], s1ap_proxy:fetch_erab_list(Pid))]. +test_ue_ctx_release_req(#{handler := Pid}) -> + %% [eNB <- MME] INITIAL CONTEXT SETUP REQUEST + InitCtxSetupReq = initial_context_setup_req_pdu(?ADDR_U2C, ?TEID_U2C), + %% [eNB -> MME] INITIAL CONTEXT SETUP RESPONSE + InitCtxSetupRsp = initial_context_setup_rsp_pdu(?ADDR_U2A, ?TEID_U2A), + %% [eNB -> MME] UE CONTEXT RELEASE REQUEST + UeCtxReleaseReq = ue_ctx_release_req_pdu(), + + [?_assertMatch({forward, _}, s1ap_proxy:process_pdu(Pid, InitCtxSetupReq)), + ?_assertMatch({forward, _}, s1ap_proxy:process_pdu(Pid, InitCtxSetupRsp)), + ?_assertEqual({forward, UeCtxReleaseReq}, s1ap_proxy:process_pdu(Pid, UeCtxReleaseReq)), + ?_assertMatch([], s1ap_proxy:fetch_erab_list(Pid))]. + + +test_ue_ctx_release_cmd(#{handler := Pid}) -> + %% [eNB <- MME] INITIAL CONTEXT SETUP REQUEST + InitCtxSetupReq = initial_context_setup_req_pdu(?ADDR_U2C, ?TEID_U2C), + %% [eNB -> MME] INITIAL CONTEXT SETUP RESPONSE + InitCtxSetupRsp = initial_context_setup_rsp_pdu(?ADDR_U2A, ?TEID_U2A), + %% [eNB <- MME] UE CONTEXT RELEASE COMMAND + UeCtxReleaseCmd = ue_ctx_release_cmd_pdu(), + %% [eNB -> MME] UE CONTEXT RELEASE COMPLETE + UeCtxReleaseCompl = ue_ctx_release_compl_pdu(), + + [?_assertMatch({forward, _}, s1ap_proxy:process_pdu(Pid, InitCtxSetupReq)), + ?_assertMatch({forward, _}, s1ap_proxy:process_pdu(Pid, InitCtxSetupRsp)), + ?_assertEqual({forward, UeCtxReleaseCmd}, s1ap_proxy:process_pdu(Pid, UeCtxReleaseCmd)), + ?_assertEqual({forward, UeCtxReleaseCompl}, s1ap_proxy:process_pdu(Pid, UeCtxReleaseCompl)), + ?_assertMatch([], s1ap_proxy:fetch_erab_list(Pid))]. + + %% ------------------------------------------------------------------ %% S1AP PDU templates %% ------------------------------------------------------------------ @@ -298,4 +333,29 @@ TEID:32/big %% GTP-TEID >>. + +%% [eNB -> MME] UE CONTEXT RELEASE REQUEST +ue_ctx_release_req_pdu() -> + << 16#00, 16#12, 16#40, 16#14, 16#00, 16#00, 16#03, 16#00, + 16#00, 16#00, 16#02, 16#00, 16#01, 16#00, 16#08, 16#00, + 16#02, 16#00, 16#01, 16#00, 16#02, 16#40, 16#01, 16#20 + >>. + + +%% [eNB <- MME] UE CONTEXT RELEASE COMMAND +ue_ctx_release_cmd_pdu() -> + << 16#00, 16#17, 16#00, 16#10, 16#00, 16#00, 16#02, 16#00, + 16#63, 16#00, 16#04, 16#00, 16#01, 16#00, 16#01, 16#00, + 16#02, 16#40, 16#01, 16#20 + >>. + + +%% [eNB -> MME] UE CONTEXT RELEASE COMPLETE +ue_ctx_release_compl_pdu() -> + << 16#20, 16#17, 16#00, 16#0f, 16#00, 16#00, 16#02, 16#00, + 16#00, 16#40, 16#02, 16#00, 16#01, 16#00, 16#08, 16#40, + 16#02, 16#00, 16#01 + >>. + + %% vim:set ts=4 sw=4 et: -- To view, visit https://gerrit.osmocom.org/c/erlang/osmo-s1gw/+/39463?usp=email To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email Gerrit-MessageType: newchange Gerrit-Project: erlang/osmo-s1gw Gerrit-Branch: master Gerrit-Change-Id: Ic94489e3d3052221b49431da3a95e5c1eb0e0ba0 Gerrit-Change-Number: 39463 Gerrit-PatchSet: 1 Gerrit-Owner: fixeria <vyanits...@sysmocom.de>