fixeria has submitted this change. ( https://gerrit.osmocom.org/c/erlang/osmo-s1gw/+/39117?usp=email )
Change subject: s1ap_proxy: handle E-RAB MODIFY REQ/RSP ......................................................................
s1ap_proxy: handle E-RAB MODIFY REQ/RSP
Change-Id: I057a1c58d0c6ad04c00ad3ea4c68230d8632a07e Related: osmo-ttcn3-hacks.git I58b9964bae24b5aac526ee0c0c8ac8798f351e05 Related: SYS#7308 --- M include/s1gw_metrics.hrl M src/s1ap_proxy.erl M src/s1gw_metrics.erl M test/s1ap_proxy_test.erl 4 files changed, 197 insertions(+), 1 deletion(-)
Approvals: Jenkins Builder: Verified laforge: Looks good to me, but someone else must approve pespin: Looks good to me, approved
diff --git a/include/s1gw_metrics.hrl b/include/s1gw_metrics.hrl index c416b1b..a2a0afd 100644 --- a/include/s1gw_metrics.hrl +++ b/include/s1gw_metrics.hrl @@ -18,6 +18,8 @@ -define(S1GW_CTR_S1AP_PROXY_IN_PKT_PROC_ERROR, [ctr, s1ap, proxy, in_pkt, proc_error]). -define(S1GW_CTR_S1AP_PROXY_IN_PKT_ERAB_SETUP_REQ, [ctr, s1ap, proxy, in_pkt, erab_setup_req]). -define(S1GW_CTR_S1AP_PROXY_IN_PKT_ERAB_SETUP_RSP, [ctr, s1ap, proxy, in_pkt, erab_setup_rsp]). +-define(S1GW_CTR_S1AP_PROXY_IN_PKT_ERAB_MODIFY_REQ, [ctr, s1ap, proxy, in_pkt, erab_modify_req]). +-define(S1GW_CTR_S1AP_PROXY_IN_PKT_ERAB_MODIFY_RSP, [ctr, s1ap, proxy, in_pkt, erab_modify_rsp]). -define(S1GW_CTR_S1AP_PROXY_IN_PKT_ERAB_RELEASE_CMD, [ctr, s1ap, proxy, in_pkt, erab_release_cmd]). -define(S1GW_CTR_S1AP_PROXY_IN_PKT_ERAB_RELEASE_RSP, [ctr, s1ap, proxy, in_pkt, erab_release_rsp]). -define(S1GW_CTR_S1AP_PROXY_IN_PKT_ERAB_RELEASE_IND, [ctr, s1ap, proxy, in_pkt, erab_release_ind]). diff --git a/src/s1ap_proxy.erl b/src/s1ap_proxy.erl index 0cef81e..402eaaa 100644 --- a/src/s1ap_proxy.erl +++ b/src/s1ap_proxy.erl @@ -71,6 +71,7 @@ -record(proxy_state, {erabs :: dict:dict(), mme_ue_id :: undefined | mme_ue_id(), enb_ue_id :: undefined | enb_ue_id(), + erab_id :: undefined | erab_id(), path :: [s1ap_ie_id()] }).
@@ -295,7 +296,37 @@ {forward, S1} %% XXX: forward as-is or drop? end;
-%% TODO: 9.1.3.3 E-RAB MODIFY REQUEST / (Optional) Transport Information +%% 9.1.3.3 E-RAB MODIFY REQUEST +handle_pdu({Outcome = initiatingMessage, + #'InitiatingMessage'{procedureCode = ?'id-E-RABModify', + value = C0} = Msg}, S0) -> + ?LOG_DEBUG("Processing E-RAB MODIFY REQUEST"), + s1gw_metrics:ctr_inc(?S1GW_CTR_S1AP_PROXY_IN_PKT_ERAB_MODIFY_REQ), + case handle_ies(?'id-E-RABToBeModifiedListBearerModReq', + C0#'E-RABModifyRequest'.protocolIEs, S0) of + {{ok, IEs}, S1} -> + C1 = C0#'E-RABModifyRequest'{protocolIEs = IEs}, + PDU = {Outcome, Msg#'InitiatingMessage'{value = C1}}, + {{forward, PDU}, S1}; %% forward patched PDU + {{error, Reason}, S1} -> + ?LOG_NOTICE("Failed to process E-RAB MODIFY REQUEST: ~p", [Reason]), + s1gw_metrics:ctr_inc(?S1GW_CTR_S1AP_PROXY_IN_PKT_PROC_ERROR), + {forward, S1} %% XXX: forward as-is or drop? + end; + +%% 9.1.3.4 E-RAB MODIFY RESPONSE +handle_pdu({successfulOutcome, + #'SuccessfulOutcome'{procedureCode = ?'id-E-RABModify', + value = C0}}, S0) -> + ?LOG_DEBUG("Processing E-RAB MODIFY RESPONSE"), + s1gw_metrics:ctr_inc(?S1GW_CTR_S1AP_PROXY_IN_PKT_ERAB_MODIFY_RSP), + %% there's nothing to patch in this PDU, so we forward it as-is + %% TODO: check result of handle_ies(), inc. ?S1GW_CTR_S1AP_PROXY_IN_PKT_PROC_ERROR + {_, S1} = handle_ies(?'id-E-RABModifyListBearerModRes', + C0#'E-RABModifyResponse'.protocolIEs, S0), + {_, S2} = handle_ies(?'id-E-RABFailedToModifyList', + C0#'E-RABModifyResponse'.protocolIEs, S1), + {forward, S2};
%% 9.1.3.5 E-RAB RELEASE COMMAND handle_pdu({Outcome = initiatingMessage, @@ -533,6 +564,88 @@ {{error, erab_not_registered}, S} end;
+%% 9.1.3.3 E-RAB MODIFY REQUEST related IEs +handle_ie([?'id-E-RABToBeModifiedListBearerModReq'], C, S) -> + %% This IE contains a list of BearerModReq, so patch inner IEs + handle_ies(?'id-E-RABToBeModifiedItemBearerModReq', C, S); + +handle_ie([?'id-E-RABToBeModifiedItemBearerModReq', + ?'id-E-RABToBeModifiedListBearerModReq'], + #'E-RABToBeModifiedItemBearerModReq'{'e-RAB-ID' = ERABId, + 'iE-Extensions' = E0} = C0, S0) -> + %% The IE-Extensions may optionally contain F-TEID, so patch inner IEs + case E0 of + %% no extensions means no F-TEID, so nothing to patch + asn1_NOVALUE -> + {{ok, C0}, S0}; + _ -> + case handle_ies(?'id-TransportInformation', + E0, S0#proxy_state{erab_id = ERABId}) of + {{ok, E1}, S1} -> + C1 = C0#'E-RABToBeModifiedItemBearerModReq'{'iE-Extensions' = E1}, + {{ok, C1}, S1}; + Error -> + Error + end + end; + +handle_ie([?'id-TransportInformation', + ?'id-E-RABToBeModifiedItemBearerModReq', + ?'id-E-RABToBeModifiedListBearerModReq'], + #'TransportInformation'{'transportLayerAddress' = TLA_In, + 'uL-GTP-TEID' = << TEID_In:32/big >>} = C0, S) -> + %% poke E-RAB FSM + case erab_fsm_find(S#proxy_state.erab_id, S) of + {ok, Pid} -> + case erab_fsm:erab_modify_req(Pid, {TEID_In, TLA_In}) of + {ok, {TEID_Out, TLA_Out}} -> + C1 = C0#'TransportInformation'{'transportLayerAddress' = TLA_Out, + 'uL-GTP-TEID' = << TEID_Out:32/big >>}, + {{ok, C1}, S}; + {error, Reason} -> + {{error, Reason}, S} + end; + error -> + ?LOG_ERROR("E-RAB-ID ~p is not registered", + [erab_uid(S#proxy_state.erab_id, S)]), + {{error, erab_not_registered}, S} + end; + +%% 9.1.3.4 E-RAB MODIFY RESPONSE related IEs +handle_ie([?'id-E-RABModifyListBearerModRes'], C, S) -> + %% This IE contains a list of BearerModRes, so patch inner IEs + handle_ies(?'id-E-RABModifyItemBearerModRes', C, S); + +handle_ie([?'id-E-RABModifyItemBearerModRes', + ?'id-E-RABModifyListBearerModRes'], + #'E-RABModifyItemBearerModRes'{'e-RAB-ID' = ERABId} = C, S) -> + %% poke E-RAB FSM + case erab_fsm_find(ERABId, S) of + {ok, Pid} -> + ok = erab_fsm:erab_modify_rsp(Pid, ack), + {{ok, C}, S}; + error -> + ?LOG_ERROR("E-RAB-ID ~p is not registered", [erab_uid(ERABId, S)]), + {{error, erab_not_registered}, S} + end; + +handle_ie([?'id-E-RABFailedToModifyList'], C, S) -> + %% This IE contains a list of E-RABItem, so patch inner IEs + handle_ies(?'id-E-RABItem', C, S); + +handle_ie([?'id-E-RABItem', + ?'id-E-RABFailedToModifyList'], + #'E-RABItem'{'e-RAB-ID' = ERABId} = C, S) -> + %% poke E-RAB FSM + case erab_fsm_find(ERABId, S) of + {ok, Pid} -> + ok = erab_fsm:erab_modify_rsp(Pid, nack), + {{ok, C}, S}; + error -> + ?LOG_ERROR("E-RAB-ID ~p is not registered", [erab_uid(ERABId, S)]), + {{error, erab_not_registered}, S} + end; + %% 9.1.3.5 E-RAB RELEASE COMMAND related IEs handle_ie([?'id-E-RABToBeReleasedList'], C, S) -> %% This IE contains a list of E-RABItem diff --git a/src/s1gw_metrics.erl b/src/s1gw_metrics.erl index 50cab10..c2785de 100644 --- a/src/s1gw_metrics.erl +++ b/src/s1gw_metrics.erl @@ -69,6 +69,8 @@ ?S1GW_CTR_S1AP_PROXY_IN_PKT_PROC_ERROR, %% failed to process ?S1GW_CTR_S1AP_PROXY_IN_PKT_ERAB_SETUP_REQ, %% E-RAB SETUP.req PDUs ?S1GW_CTR_S1AP_PROXY_IN_PKT_ERAB_SETUP_RSP, %% E-RAB SETUP.rsp PDUs + ?S1GW_CTR_S1AP_PROXY_IN_PKT_ERAB_MODIFY_REQ, %% E-RAB MODIFY.req PDUs + ?S1GW_CTR_S1AP_PROXY_IN_PKT_ERAB_MODIFY_RSP, %% E-RAB MODIFY.rsp PDUs ?S1GW_CTR_S1AP_PROXY_IN_PKT_ERAB_RELEASE_CMD, %% E-RAB RELEASE.cmd PDUs ?S1GW_CTR_S1AP_PROXY_IN_PKT_ERAB_RELEASE_RSP, %% E-RAB RELEASE.rsp PDUs ?S1GW_CTR_S1AP_PROXY_IN_PKT_ERAB_RELEASE_IND, %% E-RAB RELEASE.ind PDUs diff --git a/test/s1ap_proxy_test.erl b/test/s1ap_proxy_test.erl index ce9032e..6c04d1b 100644 --- a/test/s1ap_proxy_test.erl +++ b/test/s1ap_proxy_test.erl @@ -42,6 +42,10 @@ ?TC(fun test_e_rab_release_cmd/1)}, {"E-RAB RELEASE INDICATION", ?TC(fun test_e_rab_release_ind/1)}, + {"E-RAB MODIFY REQUEST/RESPONSE (success)", + ?TC(fun test_e_rab_modify_req_rsp/1)}, + {"E-RAB MODIFY REQUEST/RESPONSE (failure)", + ?TC(fun test_e_rab_modify_req_rsp_fail/1)}, {"E-RAB MODIFICATION INDICATION", ?TC(fun test_e_rab_modify_ind/1)}, {"INITIAL CONTEXT SETUP REQUEST/RESPONSE", @@ -121,6 +125,49 @@ ?_assertEqual([], s1ap_proxy:fetch_erab_list(Pid))].
+test_e_rab_modify_req_rsp(#{handler := Pid}) -> + %% [eNB <- MME] E-RAB SETUP REQUEST + SetupReq = e_rab_setup_req_pdu(?ADDR_U2C, ?TEID_U2C), + %% [eNB -> MME] E-RAB SETUP RESPONSE + SetupRsp = e_rab_setup_rsp_pdu(?ADDR_U2A, ?TEID_U2A), + %% eNB <- [S1GW <- MME] E-RAB MODIFY REQUEST (new F-TEID) + ModifyReqIn = e_rab_modify_req_pdu(?ADDR_U2CM, ?TEID_U2CM), + %% [eNB <- S1GW] <- MME E-RAB MODIFY REQUEST + %% for the eNB F-TEID remains unchanged + ModifyReqExp = e_rab_modify_req_pdu(?ADDR_A2U, ?TEID_A2U), + %% [eNB -> MME] E-RAB MODIFY RESPONSE + ModifyRsp = e_rab_modify_rsp_pdu(), + %% [eNB -> MME] E-RAB RELEASE INDICATION + ReleaseInd = e_rab_release_ind_pdu(), + + [?_assertMatch({forward, _}, s1ap_proxy:process_pdu(Pid, SetupReq)), + ?_assertMatch({forward, _}, s1ap_proxy:process_pdu(Pid, SetupRsp)), + ?_assertEqual({forward, ModifyReqExp}, s1ap_proxy:process_pdu(Pid, ModifyReqIn)), + ?_assertEqual({forward, ModifyRsp}, s1ap_proxy:process_pdu(Pid, ModifyRsp)), + ?_assertEqual({forward, ReleaseInd}, s1ap_proxy:process_pdu(Pid, ReleaseInd)), + ?_assertEqual([], s1ap_proxy:fetch_erab_list(Pid))]. + + +test_e_rab_modify_req_rsp_fail(#{handler := Pid}) -> + %% [eNB <- MME] E-RAB SETUP REQUEST + SetupReq = e_rab_setup_req_pdu(?ADDR_U2C, ?TEID_U2C), + %% [eNB -> MME] E-RAB SETUP RESPONSE + SetupRsp = e_rab_setup_rsp_pdu(?ADDR_U2A, ?TEID_U2A), + %% [eNB <- MME] E-RAB MODIFY REQUEST (new F-TEID) + ModifyReq = e_rab_modify_req_pdu(?ADDR_U2CM, ?TEID_U2CM), + %% [eNB -> MME] E-RAB MODIFY RESPONSE (failure) + ModifyRsp = e_rab_modify_rsp_fail_pdu(), + %% [eNB -> MME] E-RAB RELEASE INDICATION + ReleaseInd = e_rab_release_ind_pdu(), + + [?_assertMatch({forward, _}, s1ap_proxy:process_pdu(Pid, SetupReq)), + ?_assertMatch({forward, _}, s1ap_proxy:process_pdu(Pid, SetupRsp)), + ?_assertMatch({forward, _}, s1ap_proxy:process_pdu(Pid, ModifyReq)), + ?_assertEqual({forward, ModifyRsp}, s1ap_proxy:process_pdu(Pid, ModifyRsp)), + ?_assertEqual({forward, ReleaseInd}, s1ap_proxy:process_pdu(Pid, ReleaseInd)), + ?_assertEqual([], s1ap_proxy:fetch_erab_list(Pid))]. + + test_e_rab_modify_ind(#{handler := Pid}) -> %% [eNB -> MME] E-RAB MODIFICATION INDICATION ModifyIndIn = e_rab_modify_ind_pdu(?ADDR_U2A, ?TEID_U2A), @@ -267,6 +314,38 @@ >>.
+%% [eNB <- MME] E-RAB MODIFY REQUEST +e_rab_modify_req_pdu(TLA, TEID) when is_binary(TLA), + is_integer(TEID) -> + << 16#00, 16#06, 16#00, 16#2d, 16#00, 16#00, 16#03, 16#00, + 16#00, 16#00, 16#02, 16#00, 16#07, 16#00, 16#08, 16#00, + 16#02, 16#00, 16#09, 16#00, 16#1e, 16#00, 16#1a, 16#00, + 16#00, 16#24, 16#00, 16#15, 16#4c, 16#00, 16#05, 16#04, + 16#00, 16#00, 16#00, 16#00, 16#b9, 16#00, 16#0a, 16#07, + 16#c0, + TLA/bytes, %% transportLayerAddress (IPv4) + TEID:32/big %% GTP-TEID + >>. + + +%% [eNB -> MME] E-RAB MODIFY RESPONSE (success) +e_rab_modify_rsp_pdu() -> + << 16#20, 16#06, 16#00, 16#19, 16#00, 16#00, 16#03, 16#00, + 16#00, 16#40, 16#02, 16#00, 16#07, 16#00, 16#08, 16#40, + 16#02, 16#00, 16#09, 16#00, 16#1f, 16#40, 16#06, 16#00, + 16#00, 16#25, 16#40, 16#01, 16#0c + >>. + + +%% [eNB -> MME] E-RAB MODIFY RESPONSE (failure) +e_rab_modify_rsp_fail_pdu() -> + << 16#20, 16#06, 16#00, 16#1a, 16#00, 16#00, 16#03, 16#00, + 16#00, 16#40, 16#02, 16#00, 16#07, 16#00, 16#08, 16#40, + 16#02, 16#00, 16#09, 16#00, 16#20, 16#40, 16#07, 16#00, + 16#00, 16#23, 16#40, 16#02, 16#0c, 16#40 + >>. + + %% [eNB -> MME] E-RAB MODIFICATION INDICATION e_rab_modify_ind_pdu(TLA, TEID) when is_binary(TLA), is_integer(TEID) ->