fixeria has submitted this change. ( 
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(-)

Approvals:
  pespin: Looks good to me, approved
  Jenkins Builder: Verified




diff --git a/include/s1gw_metrics.hrl b/include/s1gw_metrics.hrl
index 77d6a8e..c416b1b 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_compl]).
 -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: merged
Gerrit-Project: erlang/osmo-s1gw
Gerrit-Branch: master
Gerrit-Change-Id: Ic94489e3d3052221b49431da3a95e5c1eb0e0ba0
Gerrit-Change-Number: 39463
Gerrit-PatchSet: 2
Gerrit-Owner: fixeria <vyanits...@sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: fixeria <vyanits...@sysmocom.de>
Gerrit-Reviewer: laforge <lafo...@osmocom.org>
Gerrit-Reviewer: osmith <osm...@sysmocom.de>
Gerrit-Reviewer: pespin <pes...@sysmocom.de>

Reply via email to