fixeria has submitted this change. (
https://gerrit.osmocom.org/c/erlang/osmo-s1gw/+/39113?usp=email )
Change subject: s1ap_proxy: handle_ies(): pass IEI path to handle_ie()
......................................................................
s1ap_proxy: handle_ies(): pass IEI path to handle_ie()
This patch prepares for a follow-up change adding E-RAB MODIFY REQ/RSP.
We need to be able to match the IEs unambiguously, because the same
IEI may be used in different contexts and thus have different meaning,
sometimes within the same PDU. The E-RABItem IE is such an example:
* 9.1.3.5 E-RAB RELEASE COMMAND
** contains an E-RABToBeReleasedList IE
*** contains E-RABItem IEs
* 9.1.3.7 E-RAB RELEASE INDICATION
** contains an E-RABReleasedList IE
*** contains E-RABItem IEs
So far we handled this duality by passing the release kind via
the #proxy_state record ('rel_kind' field) and it worked. But
soon in follow-up changes we'll have to deal with other PDUs:
* 9.1.3.4 E-RAB MODIFY RESPONSE
** contains an E-RABModifyListBearerModRes IE
** may contain an E-RABFailedToModifyList IE
*** contains E-RABItem IEs
* 9.1.3.9 E-RAB MODIFICATION CONFIRM
** may contain an E-RABFailedToModifyList IE
*** contains E-RABItem IEs
** may contain an E-RABToBeReleased IE
*** contains E-RABItem IEs
A universal approach allowing to match and handle IEs properly
depending on the context is to maintain the full IEI path
in handle_ies() and pass it to handle_ie().
Change-Id: I35528a91f7dbf321ad1a0811f1bbcdfb529d3530
---
M src/s1ap_proxy.erl
1 file changed, 59 insertions(+), 38 deletions(-)
Approvals:
laforge: Looks good to me, but someone else must approve
pespin: Looks good to me, but someone else must approve
fixeria: Looks good to me, approved
Jenkins Builder: Verified
diff --git a/src/s1ap_proxy.erl b/src/s1ap_proxy.erl
index b0d174d..18b054b 100644
--- a/src/s1ap_proxy.erl
+++ b/src/s1ap_proxy.erl
@@ -71,7 +71,7 @@
-record(proxy_state, {erabs :: dict:dict(),
mme_ue_id :: undefined | mme_ue_id(),
enb_ue_id :: undefined | enb_ue_id(),
- rel_kind :: undefined | cmd | ind
+ path :: [s1ap_ie_id()]
}).
-type proxy_state() :: #proxy_state{}.
@@ -118,7 +118,8 @@
init([]) ->
process_flag(trap_exit, true),
- {ok, #proxy_state{erabs = dict:new()}}.
+ {ok, #proxy_state{erabs = dict:new(),
+ path = []}}.
handle_call({process_pdu, OrigData}, _From,
@@ -275,8 +276,7 @@
?LOG_DEBUG("Processing E-RAB RELEASE COMMAND"),
s1gw_metrics:ctr_inc(?S1GW_CTR_S1AP_PROXY_IN_PKT_ERAB_RELEASE_CMD),
case handle_ies(?'id-E-RABToBeReleasedList',
- C0#'E-RABReleaseCommand'.protocolIEs,
- S0#proxy_state{rel_kind = cmd}) of
+ C0#'E-RABReleaseCommand'.protocolIEs, S0) of
{{ok, IEs}, S1} ->
C1 = C0#'E-RABReleaseCommand'{protocolIEs = IEs},
PDU = {Outcome, Msg#'InitiatingMessage'{value = C1}},
@@ -312,8 +312,7 @@
?LOG_DEBUG("Processing E-RAB RELEASE INDICATION"),
s1gw_metrics:ctr_inc(?S1GW_CTR_S1AP_PROXY_IN_PKT_ERAB_RELEASE_IND),
case handle_ies(?'id-E-RABReleasedList',
- C0#'E-RABReleaseIndication'.protocolIEs,
- S0#proxy_state{rel_kind = ind}) of
+ C0#'E-RABReleaseIndication'.protocolIEs, S0) of
{{ok, IEs}, S1} ->
C1 = C0#'E-RABReleaseIndication'{protocolIEs = IEs},
PDU = {Outcome, Msg#'InitiatingMessage'{value = C1}},
@@ -392,19 +391,20 @@
%% Handle a single IE (Information Element)
-type handle_ie_result() :: {ok, s1ap_ie_val()} | {error, term()}.
--spec handle_ie(IEI, C, S) -> Result
- when IEI :: s1ap_ie_id(),
- C :: s1ap_ie_val(),
- S :: proxy_state(),
+-spec handle_ie(Path, Content, State) -> Result
+ when Path :: [s1ap_ie_id()],
+ Content :: s1ap_ie_val(),
+ State :: proxy_state(),
Result :: {handle_ie_result(),
proxy_state()}.
%% E-RAB SETUP REQUEST related IEs
-handle_ie(?'id-E-RABToBeSetupListBearerSUReq', C, S) ->
+handle_ie([?'id-E-RABToBeSetupListBearerSUReq'], C, S) ->
%% This IE contains a list of BearerSUReq, so patch inner IEs
handle_ies(?'id-E-RABToBeSetupItemBearerSUReq', C, S);
-handle_ie(?'id-E-RABToBeSetupItemBearerSUReq',
+handle_ie([?'id-E-RABToBeSetupItemBearerSUReq',
+ ?'id-E-RABToBeSetupListBearerSUReq'],
#'E-RABToBeSetupItemBearerSUReq'{'e-RAB-ID' = ERABId,
'transportLayerAddress' = TLA_In,
'gTP-TEID' = << TEID_In:32/big
>>} = C0, S0) ->
@@ -420,11 +420,12 @@
end;
%% E-RAB SETUP RESPONSE related IEs
-handle_ie(?'id-E-RABSetupListBearerSURes', C, S) ->
+handle_ie([?'id-E-RABSetupListBearerSURes'], C, S) ->
%% This IE contains a list of BearerSURes, so patch inner IEs
handle_ies(?'id-E-RABSetupItemBearerSURes', C, S);
-handle_ie(?'id-E-RABSetupItemBearerSURes',
+handle_ie([?'id-E-RABSetupItemBearerSURes',
+ ?'id-E-RABSetupListBearerSURes'],
#'E-RABSetupItemBearerSURes'{'e-RAB-ID' = ERABId,
'transportLayerAddress' = TLA_In,
'gTP-TEID' = << TEID_In:32/big
>>} = C0, S) ->
@@ -445,17 +446,17 @@
end;
%% 9.1.3.5 E-RAB RELEASE COMMAND related IEs
-handle_ie(?'id-E-RABToBeReleasedList', C, S) ->
+handle_ie([?'id-E-RABToBeReleasedList'], C, S) ->
%% This IE contains a list of E-RABItem
handle_ies(?'id-E-RABItem', C, S);
-handle_ie(?'id-E-RABItem',
- #'E-RABItem'{'e-RAB-ID' = ERABId} = C,
- #proxy_state{rel_kind = RelKind} = S) ->
+handle_ie([?'id-E-RABItem',
+ ?'id-E-RABToBeReleasedList'],
+ #'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(Pid, RelKind),
+ ok = erab_fsm:erab_release(Pid, cmd),
{{ok, C}, S};
error ->
?LOG_ERROR("E-RAB ~p is not registered", [erab_uid(ERABId, S)]),
@@ -463,11 +464,12 @@
end;
%% 9.1.3.6 E-RAB RELEASE RESPONSE related IEs
-handle_ie(?'id-E-RABReleaseListBearerRelComp', C, S) ->
+handle_ie([?'id-E-RABReleaseListBearerRelComp'], C, S) ->
%% This IE contains a list of E-RABReleaseItemBearerRelComp
handle_ies(?'id-E-RABReleaseItemBearerRelComp', C, S);
-handle_ie(?'id-E-RABReleaseItemBearerRelComp',
+handle_ie([?'id-E-RABReleaseItemBearerRelComp',
+ ?'id-E-RABReleaseListBearerRelComp'],
#'E-RABReleaseItemBearerRelComp'{'e-RAB-ID' = ERABId} = C, S)
->
%% poke E-RAB FSM
case erab_fsm_find(ERABId, S) of
@@ -480,35 +482,51 @@
end;
%% 9.1.3.7 E-RAB RELEASE INDICATION related IEs
-handle_ie(?'id-E-RABReleasedList', C, S) ->
+handle_ie([?'id-E-RABReleasedList'], C, S) ->
%% This IE contains a list of E-RABItem
handle_ies(?'id-E-RABItem', C, S);
+handle_ie([?'id-E-RABItem',
+ ?'id-E-RABReleasedList'],
+ #'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(Pid, ind),
+ {{ok, C}, S};
+ error ->
+ ?LOG_ERROR("E-RAB ~p is not registered", [erab_uid(ERABId, S)]),
+ {{error, erab_not_registered}, S}
+ end;
+
%% E-RAB MODIFICATION INDICATION related IEs
-handle_ie(?'id-E-RABToBeModifiedListBearerModInd', C, S) ->
+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',
+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};
-handle_ie(?'id-E-RABNotToBeModifiedListBearerModInd', C, S) ->
+handle_ie([?'id-E-RABNotToBeModifiedListBearerModInd'], C, S) ->
%% This IE contains a list of BearerModInd, so patch inner IEs
handle_ies(?'id-E-RABNotToBeModifiedItemBearerModInd', C, S);
-handle_ie(?'id-E-RABNotToBeModifiedItemBearerModInd',
+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};
%% INITIAL CONTEXT SETUP REQUEST related IEs
-handle_ie(?'id-E-RABToBeSetupListCtxtSUReq', C, S) ->
+handle_ie([?'id-E-RABToBeSetupListCtxtSUReq'], C, S) ->
%% This IE contains a list of CtxtSUReq, so patch inner IEs
handle_ies(?'id-E-RABToBeSetupItemCtxtSUReq', C, S);
-handle_ie(?'id-E-RABToBeSetupItemCtxtSUReq',
+handle_ie([?'id-E-RABToBeSetupItemCtxtSUReq',
+ ?'id-E-RABToBeSetupListCtxtSUReq'],
#'E-RABToBeSetupItemCtxtSUReq'{'e-RAB-ID' = ERABId,
'transportLayerAddress' = TLA_In,
'gTP-TEID' = << TEID_In:32/big
>>} = C0, S0) ->
@@ -524,11 +542,12 @@
end;
%% INITIAL CONTEXT SETUP RESPONSE related IEs
-handle_ie(?'id-E-RABSetupListCtxtSURes', C, S) ->
+handle_ie([?'id-E-RABSetupListCtxtSURes'], C, S) ->
%% This IE contains a list of CtxtSURes, so patch inner IEs
handle_ies(?'id-E-RABSetupItemCtxtSURes', C, S);
-handle_ie(?'id-E-RABSetupItemCtxtSURes',
+handle_ie([?'id-E-RABSetupItemCtxtSURes',
+ ?'id-E-RABSetupListCtxtSURes'],
#'E-RABSetupItemCtxtSURes'{'e-RAB-ID' = ERABId,
'transportLayerAddress' = TLA_In,
'gTP-TEID' = << TEID_In:32/big
>>} = C0, S) ->
@@ -549,8 +568,8 @@
end;
%% Catch-all variant, which should not be called normally
-handle_ie(IEI, C, S) ->
- ?LOG_ERROR("[BUG] Unhandled S1AP IE: ~p, ~p", [IEI, C]),
+handle_ie(P, C, S) ->
+ ?LOG_ERROR("[BUG] Unhandled S1AP IE: ~p, ~p", [P, C]),
{{error, unhandled_ie}, S}.
@@ -559,13 +578,14 @@
%% Additionally look for {MME,eNB}-UE-S1AP-ID IEs and store their values.
-type handle_ies_result() :: {ok, list()} | {error, term()}.
-spec handle_ies(s1ap_ie_id(), list(), proxy_state()) -> {handle_ies_result(),
proxy_state()}.
-handle_ies(IEI, IEs, S) ->
- handle_ies([], IEI, IEs, S).
+handle_ies(IEI, IEs, #proxy_state{path = P} = S) ->
+ handle_ies([], IEI, IEs, S#proxy_state{path = [IEI | P]}).
-handle_ies(Acc, IEI, [IE | IEs], S0) ->
+handle_ies(Acc, IEI, [IE | IEs],
+ #proxy_state{path = P} = S0) ->
case IE of
#'ProtocolIE-Field'{id = IEI, value = C0} ->
- case handle_ie(IEI, C0, S0) of
+ case handle_ie(P, C0, S0) of
{{ok, C1}, S1} ->
NewIE = IE#'ProtocolIE-Field'{value = C1},
handle_ies([NewIE | Acc], IEI, IEs, S1);
@@ -582,9 +602,10 @@
handle_ies([IE | Acc], IEI, IEs, S0)
end;
-handle_ies(Acc, _IEI, [], S) ->
+handle_ies(Acc, IEI, [],
+ #proxy_state{path = [IEI | P]} = S) ->
IEs = lists:reverse(Acc),
- {{ok, IEs}, S}.
+ {{ok, IEs}, S#proxy_state{path = P}}.
build_erab_setup_response_failure(#proxy_state{erabs = ERABs,
--
To view, visit
https://gerrit.osmocom.org/c/erlang/osmo-s1gw/+/39113?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: I35528a91f7dbf321ad1a0811f1bbcdfb529d3530
Gerrit-Change-Number: 39113
Gerrit-PatchSet: 2
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>