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) ->

--
To view, visit https://gerrit.osmocom.org/c/erlang/osmo-s1gw/+/39117?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: I057a1c58d0c6ad04c00ad3ea4c68230d8632a07e
Gerrit-Change-Number: 39117
Gerrit-PatchSet: 6
Gerrit-Owner: fixeria <[email protected]>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: fixeria <[email protected]>
Gerrit-Reviewer: laforge <[email protected]>
Gerrit-Reviewer: pespin <[email protected]>

Reply via email to