fixeria submitted this change.
s1ap_proxy: erab_fsm_start_reg/2: check if already registered
Before this patch, s1ap_proxy would spawn a new erab_fsm process with
a duplicate UID and simply replace the old process in the registry.
This would result in stale erab_fsm process, still linked but not
present in the registry, and thus not reachable.
If there's already an E-RAB process for the given UID, simply return
Pid of that existing process. The FSM will most likely reject an
unexpected event, resulting in a negative verdict:
* 'reply' for duplicate E-RAB SETUP REQUEST
* 'drop' for duplicate INITIAL CONTEXT SETUP REQUEST
Change-Id: I8e93492219100496fd8dc69e031310858ba9c7fb
---
M src/s1ap_proxy.erl
M test/s1ap_proxy_test.erl
2 files changed, 42 insertions(+), 2 deletions(-)
diff --git a/src/s1ap_proxy.erl b/src/s1ap_proxy.erl
index 8111ad6..0195e39 100644
--- a/src/s1ap_proxy.erl
+++ b/src/s1ap_proxy.erl
@@ -1104,8 +1104,14 @@
-spec erab_fsm_start_reg(erab_id(), proxy_state()) -> {pid(), proxy_state()}.
erab_fsm_start_reg(RABId, #proxy_state{erabs = ERABs} = S) ->
UID = erab_uid(RABId, S),
- {ok, Pid} = erab_fsm:start_link(UID),
- {Pid, S#proxy_state{erabs = dict:store(UID, Pid, ERABs)}}.
+ case dict:find(UID, ERABs) of
+ {ok, Pid} ->
+ ?LOG_ERROR("E-RAB ~p is already registered?!?", [UID]),
+ {Pid, S}; %% return Pid of the existing erab_fsm process
+ error ->
+ {ok, Pid} = erab_fsm:start_link(UID),
+ {Pid, S#proxy_state{erabs = dict:store(UID, Pid, ERABs)}}
+ end.
-spec erab_fsm_find(erab_id(), proxy_state()) -> {ok, pid()} | error.
diff --git a/test/s1ap_proxy_test.erl b/test/s1ap_proxy_test.erl
index 1145bc5..8f338c9 100644
--- a/test/s1ap_proxy_test.erl
+++ b/test/s1ap_proxy_test.erl
@@ -52,6 +52,8 @@
?TC(fun test_e_rab_setup/1)},
{"E-RAB SETUP REQUEST (failure)",
?TC(fun test_e_rab_setup_req_fail/1)},
+ {"E-RAB SETUP REQUEST (duplicate)",
+ ?TC(fun test_e_rab_setup_dup/1)},
{"E-RAB RELEASE COMMAND/RESPONSE",
?TC(fun test_e_rab_release_cmd/1)},
{"E-RAB RELEASE INDICATION",
@@ -68,6 +70,8 @@
?TC(fun test_e_rab_modify_ind_cnf_release/1)},
{"INITIAL CONTEXT SETUP REQUEST/RESPONSE",
?TC(fun test_initial_context_setup/1)},
+ {"INITIAL CONTEXT SETUP REQUEST/RESPONSE (duplicate)",
+ ?TC(fun test_initial_context_setup_dup/1)},
{"UE CONTEXT RELEASE REQUEST",
?TC(fun test_ue_ctx_release_req/1)},
{"UE CONTEXT RELEASE COMMAND/COMPLETE",
@@ -147,6 +151,23 @@
?_assertEqual([], s1ap_proxy:fetch_erab_list(Pid))].
+test_e_rab_setup_dup(#{handler := Pid}) ->
+ %% [eNB <- MME] E-RAB SETUP REQUEST
+ SetupReqIn = e_rab_setup_req_pdu(?ADDR_U2C, ?TEID_U2C),
+ %% [eNB -> MME] E-RAB SETUP RESPONSE
+ SetupRspIn = e_rab_setup_rsp_pdu(?ADDR_U2A, ?TEID_U2A),
+ %% eNB <- [S1GW <- MME] E-RAB SETUP REQUEST (duplicate)
+ %% eNB -- [S1GW -> MME] E-RAB SETUP RESPONSE (failure)
+ SetupRspExp = e_rab_setup_rsp_fail_pdu(),
+
+ [?_assertMatch({forward, _}, s1ap_proxy:process_pdu(Pid, SetupReqIn)),
+ ?_assertMatch({forward, _}, s1ap_proxy:process_pdu(Pid, SetupRspIn)),
+ %% duplicate E-RAB SETUP REQUEST triggers a reply
+ ?_assertEqual({reply, SetupRspExp}, s1ap_proxy:process_pdu(Pid, SetupReqIn)),
+ ?_assertMatch({ok, _}, s1ap_proxy:fetch_erab(Pid, {7, 9, 6})),
+ ?_assertMatch([_], s1ap_proxy:fetch_erab_list(Pid))].
+
+
test_e_rab_release_cmd(#{handler := Pid}) ->
%% [eNB <- MME] E-RAB SETUP REQUEST
SetupReq = e_rab_setup_req_pdu(?ADDR_U2C, ?TEID_U2C),
@@ -357,6 +378,19 @@
?_assertMatch([_], s1ap_proxy:fetch_erab_list(Pid))].
+test_initial_context_setup_dup(#{handler := Pid}) ->
+ %% [eNB <- MME] INITIAL CONTEXT SETUP REQUEST
+ InitCtxSetupReqIn = initial_context_setup_req_pdu(?ADDR_U2C, ?TEID_U2C),
+ %% [eNB -> MME] INITIAL CONTEXT SETUP RESPONSE
+ InitCtxSetupRspIn = initial_context_setup_rsp_pdu(?ADDR_U2A, ?TEID_U2A),
+
+ [?_assertMatch({forward, _}, s1ap_proxy:process_pdu(Pid, InitCtxSetupReqIn)),
+ ?_assertMatch({forward, _}, s1ap_proxy:process_pdu(Pid, InitCtxSetupRspIn)),
+ %% duplicate INITIAL CONTEXT SETUP REQUEST results in the PDU being dropped
+ ?_assertEqual({drop, InitCtxSetupReqIn}, s1ap_proxy:process_pdu(Pid, InitCtxSetupReqIn)),
+ ?_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),
To view, visit change 40993. To unsubscribe, or for help writing mail filters, visit settings.