fixeria has submitted this change. ( 
https://gerrit.osmocom.org/c/erlang/osmo-s1gw/+/41006?usp=email )

Change subject: s1ap_proxy: Add support for S1 HANDOVER procedure
......................................................................

s1ap_proxy: Add support for S1 HANDOVER procedure

The HANDOVER procedure consists of two parts:

* Preparation of handover on the source eNB

A list of E-RABs to be released are processed by the proxy.

* Resource allocation on the target eNB

A list of E-RABs to be established are processed by the proxy. GTP-TEIDs
and transport layer addresses will be modified.

Change-Id: Ib2c8b1787c60d35a512c3c78d35e1f72a9d7bb08
Related: osmo-ttcn3-hacks.git Id349c84749f7e897defa8cfd2ecd2c1f2fb52fc7
Related: SYS#7309
---
M include/s1gw_metrics.hrl
M src/s1ap_proxy.erl
M src/s1gw_metrics.erl
3 files changed, 127 insertions(+), 4 deletions(-)

Approvals:
  pespin: Looks good to me, approved
  Jenkins Builder: Verified
  fixeria: Looks good to me, but someone else must approve




diff --git a/include/s1gw_metrics.hrl b/include/s1gw_metrics.hrl
index 83ec768..5afbff0 100644
--- a/include/s1gw_metrics.hrl
+++ b/include/s1gw_metrics.hrl
@@ -31,6 +31,9 @@
 -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_IN_PKT_HANDOVER_CMD, [ctr, s1ap, proxy, in_pkt, 
handover_cmd]).
+-define(S1GW_CTR_S1AP_PROXY_IN_PKT_HANDOVER_REQ, [ctr, s1ap, proxy, in_pkt, 
handover_req]).
+-define(S1GW_CTR_S1AP_PROXY_IN_PKT_HANDOVER_REQ_ACK, [ctr, s1ap, proxy, 
in_pkt, handover_req_ack]).
 -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 a08f61d..0046167 100644
--- a/src/s1ap_proxy.erl
+++ b/src/s1ap_proxy.erl
@@ -626,10 +626,58 @@
                   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,
-%%                                               (O) UL/DL Transport Layer 
Address
+%% 9.1.5.2 HANDOVER COMMAND
+handle_pdu({successfulOutcome,
+            #'SuccessfulOutcome'{procedureCode = ?'id-HandoverPreparation',
+                                 value = C0}}, S0) ->
+    ?LOG_DEBUG("Processing HANDOVER COMMAND"),
+    ctr_inc(?S1GW_CTR_S1AP_PROXY_IN_PKT_HANDOVER_CMD, S0),
+    case handle_ies(?'id-E-RABtoReleaseListHOCmd',
+                    C0#'HandoverCommand'.protocolIEs, S0) of
+        {{ok, _}, S1} ->
+            {forward, S1}; %% forward as-is, there's nothing to patch
+        {{error, Reason}, S1} ->
+            ?LOG_NOTICE("Failed to process HANDOVER COMMAND: ~p", [Reason]),
+            ctr_inc(?S1GW_CTR_S1AP_PROXY_IN_PKT_PROC_ERROR, S1),
+            {forward, S1}
+    end;
+
+%% 9.1.5.4 HANDOVER REQUEST
+handle_pdu({Outcome = initiatingMessage,
+            #'InitiatingMessage'{procedureCode = 
?'id-HandoverResourceAllocation',
+                                 value = C0} = Msg}, S0) ->
+    ?LOG_DEBUG("Processing HANDOVER REQUEST"),
+    ctr_inc(?S1GW_CTR_S1AP_PROXY_IN_PKT_HANDOVER_REQ, S0),
+    case handle_ies(?'id-E-RABToBeSetupListHOReq',
+                    C0#'HandoverRequest'.protocolIEs, S0) of
+        {{ok, IEs}, S1} ->
+            C1 = C0#'HandoverRequest'{protocolIEs = IEs},
+            PDU = {Outcome, Msg#'InitiatingMessage'{value = C1}},
+            {{forward, PDU}, S1}; %% forward patched PDU
+        {{error, Reason}, S1} ->
+            ?LOG_NOTICE("Failed to process HANDOVER REQUEST: ~p", [Reason]),
+            ctr_inc(?S1GW_CTR_S1AP_PROXY_IN_PKT_PROC_ERROR, S1),
+            {drop, S1} %% drop this PDU
+    end;
+
+%% 9.1.5.5 HANDOVER REQUEST ACKNOWLEDGE,
+handle_pdu({Outcome = successfulOutcome,
+            #'SuccessfulOutcome'{procedureCode = 
?'id-HandoverResourceAllocation',
+                                 value = C0} = Msg}, S0) ->
+    ?LOG_DEBUG("Processing HANDOVER REQUEST ACKNOWLEDGE"),
+    ctr_inc(?S1GW_CTR_S1AP_PROXY_IN_PKT_HANDOVER_REQ_ACK, S0),
+    case handle_ies(?'id-E-RABAdmittedList',
+                    C0#'HandoverRequestAcknowledge'.protocolIEs, S0) of
+        {{ok, IEs}, S1} ->
+            C1 = C0#'HandoverRequestAcknowledge'{protocolIEs = IEs},
+            PDU = {Outcome, Msg#'SuccessfulOutcome'{value = C1}},
+            {{forward, PDU}, S1}; %% forward patched PDU
+        {{error, Reason}, S1} ->
+            ?LOG_NOTICE("Failed to process HANDOVER REQUEST ACKNOWLEDGE: ~p", 
[Reason]),
+            ctr_inc(?S1GW_CTR_S1AP_PROXY_IN_PKT_PROC_ERROR, S1),
+            {drop, S1} %% drop this PDU
+    end;
+
 %% TODO: 9.1.5.8 PATH SWITCH REQUEST :: (M) Transport Layer Address
 %% TODO: 9.1.5.9 PATH SWITCH REQUEST ACKNOWLEDGE :: (M) Transport Layer Address

@@ -1010,6 +1058,74 @@
             {{error, erab_not_registered}, S}
     end;

+%% HANDOVER COMMAND related IEs
+handle_ie([?'id-E-RABtoReleaseListHOCmd'], 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-RABtoReleaseListHOCmd'],
+          #'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;
+
+%% HANDOVER REQUEST related IEs
+handle_ie([?'id-E-RABToBeSetupListHOReq'], C, S) ->
+    %% This IE contains a list of E-RABToBeSetupItemHOReq, so patch inner IEs
+    handle_ies(?'id-E-RABToBeSetupItemHOReq', C, S);
+
+handle_ie([?'id-E-RABToBeSetupItemHOReq',
+           ?'id-E-RABToBeSetupListHOReq'],
+          #'E-RABToBeSetupItemHOReq'{'e-RAB-ID' = ERABId,
+                                     'transportLayerAddress' = TLA_In,
+                                     'gTP-TEID' = << TEID_In:32/big >>} = C0, 
S0) ->
+    %% start and register an E-RAB FSM
+    {Pid, S1} = erab_fsm_start_reg(ERABId, S0),
+    case erab_fsm:erab_setup_req(Pid, {TEID_In, TLA_In}) of
+        {ok, {TEID_Out, TLA_Out}} ->
+            C1 = C0#'E-RABToBeSetupItemHOReq'{'transportLayerAddress' = 
TLA_Out,
+                                              'gTP-TEID' = << TEID_Out:32/big 
>>},
+            {{ok, C1}, S1};
+        {error, Reason} ->
+            {{error, Reason}, S1}
+    end;
+
+%% HANDOVER REQUEST ACKNOWLEDGE related IEs
+handle_ie([?'id-E-RABAdmittedList'], C, S) ->
+    %% This IE contains a list of E-RABAdmittedItem, so patch inner IEs
+    handle_ies(?'id-E-RABAdmittedItem', C, S);
+
+handle_ie([?'id-E-RABAdmittedItem',
+           ?'id-E-RABAdmittedList'],
+          #'E-RABAdmittedItem'{'e-RAB-ID' = ERABId,
+                               'transportLayerAddress' = TLA_In,
+                               'gTP-TEID' = << TEID_In:32/big >>} = C0, S) ->
+    %% indicate eNB's address to the gtpu_kpi module
+    gtpu_kpi_enb_set_addr({s1ap, tla_str(TLA_In)}),
+    %% poke E-RAB FSM
+    case erab_fsm_find(ERABId, S) of
+        {ok, Pid} ->
+            case erab_fsm:erab_setup_rsp(Pid, {TEID_In, TLA_In}) of
+                {ok, {TEID_Out, TLA_Out}} ->
+                    C1 = C0#'E-RABAdmittedItem'{'transportLayerAddress' = 
TLA_Out,
+                                                '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;
+
+
 %% Catch-all variant, which should not be called normally
 handle_ie(P, C, S) ->
     ?LOG_ERROR("[BUG] Unhandled S1AP IE: ~p, ~p", [P, C]),
diff --git a/src/s1gw_metrics.erl b/src/s1gw_metrics.erl
index 1c3d76e..8a74774 100644
--- a/src/s1gw_metrics.erl
+++ b/src/s1gw_metrics.erl
@@ -86,6 +86,10 @@
     ?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
+    ?S1GW_CTR_S1AP_PROXY_IN_PKT_HANDOVER_CMD,               %% HANDOVER 
COMMAND PDUs
+    ?S1GW_CTR_S1AP_PROXY_IN_PKT_HANDOVER_REQ,               %% HANDOVER 
REQUEST PDUs
+    ?S1GW_CTR_S1AP_PROXY_IN_PKT_HANDOVER_REQ_ACK,           %% HANDOVER 
REQUEST ACKNOWLEDGE 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

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

Reply via email to