fixeria has submitted this change. (
https://gerrit.osmocom.org/c/erlang/osmo-s1gw/+/39118?usp=email )
Change subject: s1ap_proxy: handle E-RAB MODIFICATION IND/CNF
......................................................................
s1ap_proxy: handle E-RAB MODIFICATION IND/CNF
Change-Id: Icc16a57d40b68bd17c5d207b643927d58176e088
Related: osmo-ttcn3-hacks.git Iec95ca0ecf37290bddfbefce1861f8ae66bf4db1
Related: SYS#7308
---
M include/s1gw_metrics.hrl
M src/s1ap_proxy.erl
M src/s1gw_metrics.erl
M test/erab_fsm_test.erl
M test/s1ap_proxy_test.erl
5 files changed, 209 insertions(+), 19 deletions(-)
Approvals:
Jenkins Builder: Verified
pespin: Looks good to me, approved
laforge: Looks good to me, but someone else must approve
diff --git a/include/s1gw_metrics.hrl b/include/s1gw_metrics.hrl
index a2a0afd..940529b 100644
--- a/include/s1gw_metrics.hrl
+++ b/include/s1gw_metrics.hrl
@@ -24,6 +24,7 @@
-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]).
-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_ERAB_MOD_CNF, [ctr, s1ap, proxy, in_pkt,
erab_mod_cnf]).
-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]).
diff --git a/src/s1ap_proxy.erl b/src/s1ap_proxy.erl
index 402eaaa..db72dab 100644
--- a/src/s1ap_proxy.erl
+++ b/src/s1ap_proxy.erl
@@ -399,6 +399,25 @@
PDU = {Outcome, Msg#'InitiatingMessage'{value = C1}},
{{forward, PDU}, S2};
+%% 9.1.3.9 E-RAB MODIFICATION CONFIRM
+handle_pdu({successfulOutcome,
+ #'SuccessfulOutcome'{procedureCode =
?'id-E-RABModificationIndication',
+ value = C0}}, S0) ->
+ ?LOG_DEBUG("Processing E-RAB MODIFICATION CONFIRM"),
+ s1gw_metrics:ctr_inc(?S1GW_CTR_S1AP_PROXY_IN_PKT_ERAB_MOD_CNF),
+ IEs = C0#'E-RABModificationConfirm'.protocolIEs,
+ %% E-RAB Modify List
+ %% TODO: handle {error, Reason}
+ {_, S1} = handle_ies(?'id-E-RABModifyListBearerModConf', IEs, S0),
+ %% E-RAB Failed to Modify List
+ %% TODO: handle {error, Reason}
+ {_, S2} = handle_ies(?'id-E-RABFailedToModifyListBearerModConf', IEs, S1),
+ %% E-RAB To Be Released List
+ %% TODO: handle {error, Reason}
+ {_, S3} = handle_ies(?'id-E-RABToBeReleasedListBearerModConf', IEs, S2),
+ %% there's nothing to patch in this PDU, so we forward it as-is
+ {forward, S3};
+
%% 9.1.4.1 INITIAL CONTEXT SETUP REQUEST
handle_pdu({Outcome = initiatingMessage,
#'InitiatingMessage'{procedureCode =
?'id-InitialContextSetup',
@@ -700,16 +719,31 @@
{{error, erab_not_registered}, S}
end;
-%% E-RAB MODIFICATION INDICATION related IEs
+%% 9.1.3.8 E-RAB MODIFICATION INDICATION related IEs
handle_ie([?'id-E-RABToBeModifiedListBearerModInd'], C, S) ->
%% This IE contains a list of BearerModInd, so patch inner IEs
handle_ies(?'id-E-RABToBeModifiedItemBearerModInd', C, S);
handle_ie([?'id-E-RABToBeModifiedItemBearerModInd',
?'id-E-RABToBeModifiedListBearerModInd'],
- #'E-RABToBeModifiedItemBearerModInd'{} = C, S) ->
- %% TODO: find and poke an E-RAB FSM associated with this E-RAB
- {{ok, C}, S};
+ #'E-RABToBeModifiedItemBearerModInd'{'e-RAB-ID' = ERABId,
+ 'transportLayerAddress' = TLA_In,
+ 'dL-GTP-TEID' = <<
TEID_In:32/big >>} = C0, S) ->
+ %% poke E-RAB FSM
+ case erab_fsm_find(ERABId, S) of
+ {ok, Pid} ->
+ case erab_fsm:erab_modify_ind(Pid, {TEID_In, TLA_In}) of
+ {ok, {TEID_Out, TLA_Out}} ->
+ C1 =
C0#'E-RABToBeModifiedItemBearerModInd'{'transportLayerAddress' = TLA_Out,
+ 'dL-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(ERABId,
S)]),
+ {{error, erab_not_registered}, S}
+ end;
handle_ie([?'id-E-RABNotToBeModifiedListBearerModInd'], C, S) ->
%% This IE contains a list of BearerModInd, so patch inner IEs
@@ -717,9 +751,77 @@
handle_ie([?'id-E-RABNotToBeModifiedItemBearerModInd',
?'id-E-RABNotToBeModifiedListBearerModInd'],
- #'E-RABNotToBeModifiedItemBearerModInd'{} = C, S) ->
- %% TODO: find and poke an E-RAB FSM associated with this E-RAB
- {{ok, C}, S};
+ #'E-RABNotToBeModifiedItemBearerModInd'{'e-RAB-ID' = ERABId} =
C0, S) ->
+ %% poke E-RAB FSM
+ case erab_fsm_find(ERABId, S) of
+ {ok, Pid} ->
+ %% Ignore F-TEID in the original message, just replace it with C2U F-TEID
+ Info = erab_fsm:fetch_info(Pid),
+ case proplists:get_value(f_teid_c2u, Info) of
+ {TEID, TLA} ->
+ C1 =
C0#'E-RABNotToBeModifiedItemBearerModInd'{'transportLayerAddress' = TLA,
+ 'dL-GTP-TEID'
= << TEID:32/big >>},
+ {{ok, C1}, S};
+ undefined ->
+ ?LOG_ERROR("E-RAB-ID ~p :: missing C2U F-TEID",
[erab_uid(ERABId, S)]),
+ {{error, missing_f_teid}, S}
+ end;
+ error ->
+ ?LOG_ERROR("E-RAB-ID ~p is not registered", [erab_uid(ERABId,
S)]),
+ {{error, erab_not_registered}, S}
+ end;
+
+%% 9.1.3.9 E-RAB MODIFICATION CONFIRM related IEs
+handle_ie([?'id-E-RABModifyListBearerModConf'], C, S) ->
+ %% This IE contains a list of BearerModConf, so patch inner IEs
+ handle_ies(?'id-E-RABModifyItemBearerModConf', C, S);
+
+handle_ie([?'id-E-RABModifyItemBearerModConf',
+ ?'id-E-RABModifyListBearerModConf'],
+ #'E-RABModifyItemBearerModConf'{'e-RAB-ID' = ERABId} = C, S)
->
+ %% poke E-RAB FSM
+ case erab_fsm_find(ERABId, S) of
+ {ok, Pid} ->
+ ok = erab_fsm:erab_modify_cnf(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-RABFailedToModifyListBearerModConf'], 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-RABFailedToModifyListBearerModConf'],
+ #'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_cnf(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;
+
+handle_ie([?'id-E-RABToBeReleasedListBearerModConf'], 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-RABToBeReleasedListBearerModConf'],
+ #'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_release_ind(Pid),
+ {{ok, C}, S};
+ error ->
+ ?LOG_ERROR("E-RAB-ID ~p is not registered", [erab_uid(ERABId,
S)]),
+ {{error, erab_not_registered}, S}
+ end;
%% INITIAL CONTEXT SETUP REQUEST related IEs
handle_ie([?'id-E-RABToBeSetupListCtxtSUReq'], C, S) ->
diff --git a/src/s1gw_metrics.erl b/src/s1gw_metrics.erl
index c2785de..9f7b2e8 100644
--- a/src/s1gw_metrics.erl
+++ b/src/s1gw_metrics.erl
@@ -75,6 +75,7 @@
?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
?S1GW_CTR_S1AP_PROXY_IN_PKT_ERAB_MOD_IND, %% E-RAB MODIFY.ind PDUs
+ ?S1GW_CTR_S1AP_PROXY_IN_PKT_ERAB_MOD_CNF, %% E-RAB MODIFY.cnf 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
diff --git a/test/erab_fsm_test.erl b/test/erab_fsm_test.erl
index 3740f9a..a3dfb4d 100644
--- a/test/erab_fsm_test.erl
+++ b/test/erab_fsm_test.erl
@@ -51,6 +51,9 @@
?TC(fun test_erab_setup_pfcp_modify_error/1)}].
+%% 8.2.4.2 Interactions with E-RAB Setup procedure or E-RAB Modify procedure:
+%% TODO: test E-RAB MODIFY IND/CNF during E-RAB SETUP
+%% TODO: test E-RAB MODIFY IND/CNF during E-RAB MODIFY
erab_modify_test_() ->
[{"E-RAB MODIFY REQ :: ACK",
?TC(fun test_erab_modify_req_ack/1)},
diff --git a/test/s1ap_proxy_test.erl b/test/s1ap_proxy_test.erl
index 6c04d1b..74f3f05 100644
--- a/test/s1ap_proxy_test.erl
+++ b/test/s1ap_proxy_test.erl
@@ -46,8 +46,12 @@
?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)},
+ {"E-RAB MODIFICATION INDICATION (modified)",
+ ?TC(fun test_e_rab_modify_ind_cnf_modified/1)},
+ {"E-RAB MODIFICATION INDICATION (not modified)",
+ ?TC(fun test_e_rab_modify_ind_cnf_not_modified/1)},
+ {"E-RAB MODIFICATION INDICATION (release)",
+ ?TC(fun test_e_rab_modify_ind_cnf_release/1)},
{"INITIAL CONTEXT SETUP REQUEST/RESPONSE",
?TC(fun test_initial_context_setup/1)},
{"UE CONTEXT RELEASE REQUEST",
@@ -168,13 +172,70 @@
?_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),
- %% XXX: not implemented, we should actually expect ?ADDR_C2U, ?TEID_C2U
- ModifyIndExp = e_rab_modify_ind_pdu(?ADDR_U2A, ?TEID_U2A),
+test_e_rab_modify_ind_cnf_modified(#{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 MODIFICATION INDICATION (new F-TEID)
+ ModifyIndIn = e_rab_modify_ind_pdu(?ADDR_U2AM, ?TEID_U2AM),
+ %% eNB -> [S1GW -> MME] E-RAB MODIFICATION INDICATION
+ %% for the MME F-TEID remains unchanged
+ ModifyIndExp = e_rab_modify_ind_pdu(?ADDR_C2U, ?TEID_C2U),
+ %% [eNB <- MME] E-RAB MODIFICATION CONFIRMATION
+ ModifyCnf = e_rab_modify_cnf_pdu(modified),
+ %% [eNB -> MME] E-RAB RELEASE INDICATION
+ ReleaseInd = e_rab_release_ind_pdu(),
- [?_assertEqual({forward, ModifyIndExp}, s1ap_proxy:process_pdu(Pid, ModifyIndIn))].
+ [?_assertMatch({forward, _}, s1ap_proxy:process_pdu(Pid, SetupReq)),
+ ?_assertMatch({forward, _}, s1ap_proxy:process_pdu(Pid, SetupRsp)),
+ ?_assertEqual({forward, ModifyIndExp}, s1ap_proxy:process_pdu(Pid, ModifyIndIn)),
+ ?_assertEqual({forward, ModifyCnf}, s1ap_proxy:process_pdu(Pid, ModifyCnf)),
+ ?_assertEqual({forward, ReleaseInd}, s1ap_proxy:process_pdu(Pid, ReleaseInd)),
+ ?_assertEqual([], s1ap_proxy:fetch_erab_list(Pid))].
+
+
+test_e_rab_modify_ind_cnf_not_modified(#{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 MODIFICATION INDICATION (new F-TEID)
+ ModifyIndIn = e_rab_modify_ind_pdu(?ADDR_U2AM, ?TEID_U2AM),
+ %% eNB -> [S1GW -> MME] E-RAB MODIFICATION INDICATION
+ %% for the MME F-TEID remains unchanged
+ ModifyIndExp = e_rab_modify_ind_pdu(?ADDR_C2U, ?TEID_C2U),
+ %% [eNB <- MME] E-RAB MODIFICATION CONFIRMATION
+ ModifyCnf = e_rab_modify_cnf_pdu(not_modified),
+ %% [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, ModifyIndExp}, s1ap_proxy:process_pdu(Pid, ModifyIndIn)),
+ ?_assertEqual({forward, ModifyCnf}, s1ap_proxy:process_pdu(Pid, ModifyCnf)),
+ ?_assertEqual({forward, ReleaseInd}, s1ap_proxy:process_pdu(Pid, ReleaseInd)),
+ ?_assertEqual([], s1ap_proxy:fetch_erab_list(Pid))].
+
+
+test_e_rab_modify_ind_cnf_release(#{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 MODIFICATION INDICATION (new F-TEID)
+ ModifyIndIn = e_rab_modify_ind_pdu(?ADDR_U2AM, ?TEID_U2AM),
+ %% eNB -> [S1GW -> MME] E-RAB MODIFICATION INDICATION
+ %% for the MME F-TEID remains unchanged
+ ModifyIndExp = e_rab_modify_ind_pdu(?ADDR_C2U, ?TEID_C2U),
+ %% [eNB <- MME] E-RAB MODIFICATION CONFIRMATION
+ ModifyCnf = e_rab_modify_cnf_pdu(release),
+
+ [?_assertMatch({forward, _}, s1ap_proxy:process_pdu(Pid, SetupReq)),
+ ?_assertMatch({forward, _}, s1ap_proxy:process_pdu(Pid, SetupRsp)),
+ ?_assertEqual({forward, ModifyIndExp}, s1ap_proxy:process_pdu(Pid, ModifyIndIn)),
+ ?_assertEqual({forward, ModifyCnf}, s1ap_proxy:process_pdu(Pid, ModifyCnf)),
+ ?_assertEqual([], s1ap_proxy:fetch_erab_list(Pid))].
test_initial_context_setup(#{handler := Pid}) ->
@@ -349,15 +410,37 @@
%% [eNB -> MME] E-RAB MODIFICATION INDICATION
e_rab_modify_ind_pdu(TLA, TEID) when is_binary(TLA),
is_integer(TEID) ->
- << 16#00, 16#32, 16#00, 16#24, 16#00, 16#00, 16#03, 16#00,
- 16#00, 16#00, 16#02, 16#00, 16#02, 16#00, 16#08, 16#00,
- 16#04, 16#80, 16#06, 16#69, 16#2d, 16#00, 16#c7, 16#00,
- 16#0f, 16#00, 16#00, 16#c8, 16#00, 16#0a, 16#0a, 16#1f,
+ << 16#00, 16#32, 16#00, 16#22, 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#c7, 16#00, 16#0f, 16#00,
+ 16#00, 16#c8, 16#00, 16#0a, 16#0c, 16#1f,
TLA/bytes, %% transportLayerAddress (IPv4)
TEID:32/big %% GTP-TEID
>.
+%% [eNB -> MME] E-RAB MODIFICATION CONFIRMATION
+e_rab_modify_cnf_pdu(Res) ->
+ IEs = case Res of
+ modified ->
+ << 16#00, 16#cb, 16#40, 16#06, 16#00,
+ 16#00, 16#cc, 16#40, 16#01, 16#0c >>;
+ not_modified ->
+ %% cause: transport: transport-resource-unavailable (0)
+ << 16#00, 16#cd, 16#40, 16#07, 16#00,
+ 16#00, 16#23, 16#40, 16#02, 16#0c, 16#20 >>;
+ release ->
+ %% cause: transport: transport-resource-unavailable (0)
+ << 16#00, 16#d2, 16#40, 16#07, 16#00,
+ 16#00, 16#23, 16#40, 16#02, 16#0c, 16#20 >>
+ end,
+ << 16#20, 16#32, 16#00, (15 + byte_size(IEs)),
+ 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,
+ IEs/bytes
+ >>.
+
+
%% [eNB <- MME] INITIAL CONTEXT SETUP REQUEST
initial_context_setup_req_pdu(TLA, TEID) when is_binary(TLA),
is_integer(TEID) ->
--
To view, visit
https://gerrit.osmocom.org/c/erlang/osmo-s1gw/+/39118?usp=email
To unsubscribe, or for help writing mail filters, visit
https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: merged
Gerrit-Project: erlang/osmo-s1gw
Gerrit-Branch: master
Gerrit-Change-Id: Icc16a57d40b68bd17c5d207b643927d58176e088
Gerrit-Change-Number: 39118
Gerrit-PatchSet: 7
Gerrit-Owner: fixeria <vyanitskiy(a)sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: fixeria <vyanitskiy(a)sysmocom.de>
Gerrit-Reviewer: laforge <laforge(a)osmocom.org>
Gerrit-Reviewer: pespin <pespin(a)sysmocom.de>