fixeria has uploaded this change for review. (
https://gerrit.osmocom.org/c/erlang/osmo-s1gw/+/37463?usp=email )
Change subject: {sctp,s1ap}_proxy: employ E-RAB FSMs
......................................................................
{sctp,s1ap}_proxy: employ E-RAB FSMs
Change-Id: Ibb7e25ab3adbadd7fd85e9cb22e0136c6ca133cf
---
M src/s1ap_proxy.erl
M src/sctp_proxy.erl
2 files changed, 71 insertions(+), 6 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/erlang/osmo-s1gw refs/changes/63/37463/1
diff --git a/src/s1ap_proxy.erl b/src/s1ap_proxy.erl
index eaa7dfd..f1a2726 100644
--- a/src/s1ap_proxy.erl
+++ b/src/s1ap_proxy.erl
@@ -37,6 +37,7 @@
-export([init/0,
deinit/1,
handle_pdu/2,
+ handle_exit/2,
encode_pdu/1,
decode_pdu/1]).
@@ -48,7 +49,7 @@
-include("S1AP-Constants.hrl").
--record(proxy_state, { }).
+-record(proxy_state, {erabs :: dict:dict()}).
-type proxy_state() :: #proxy_state{}.
@@ -59,7 +60,7 @@
%% Initialize per-connection data
-spec init() -> proxy_state().
init() ->
- #proxy_state{}.
+ #proxy_state{erabs = dict:new()}.
%% De-initialize per-connection data
@@ -81,6 +82,13 @@
end.
+%% Handle an exit event
+-spec handle_exit(pid(), proxy_state()) -> proxy_state().
+handle_exit(Pid, #proxy_state{erabs = ERABs} = S) ->
+ Fun = fun(_Key, Val) -> Val =/= Pid end,
+ S#proxy_state{erabs = dict:filter(Fun, ERABs)}.
+
+
%% ------------------------------------------------------------------
%% private API
%% ------------------------------------------------------------------
@@ -99,6 +107,18 @@
'S1AP-PDU-Descriptions':decode('S1AP-PDU', Data).
+%% Decode TEID from binary to integer
+-spec decode_teid(binary()) -> non_neg_integer().
+decode_teid(<< TEID:32/big >>) ->
+ TEID.
+
+
+%% Encode TEID from integer to binary
+-spec encode_teid(non_neg_integer()) -> binary().
+encode_teid(TEID) when is_integer(TEID) ->
+ << TEID:32/big >>.
+
+
%% Helper function for handle_pdu/3.
%% Attempt to encode a new (modified) S1AP PDU,
%% return a new binary() on success or Data on error.
@@ -189,10 +209,16 @@
handle_ies(Content, ?'id-E-RABToBeSetupItemBearerSUReq', S);
handle_ie(#'ProtocolIE-Field'{id = ?'id-E-RABToBeSetupItemBearerSUReq',
- value = Content}, S) ->
+ value = Content}, S0) ->
%% eNB -> MME direction: we pass our MME facing local address
TLA = transp_layer_addr(mme_loc_addr),
- {Content#'E-RABToBeSetupItemBearerSUReq'{transportLayerAddress = TLA}, S};
+ %% start and register an E-RAB FSM
+ #'E-RABToBeSetupItemBearerSUReq'{'e-RAB-ID' = ERABId,
+ 'gTP-TEID' = TEID_FromAcc} = Content,
+ {Pid, S1} = erab_fsm_start_reg(ERABId, S0),
+ {ok, TEID_ToCore} = erab_fsm:erab_setup_req(Pid, decode_teid(TEID_FromAcc)),
+ {Content#'E-RABToBeSetupItemBearerSUReq'{transportLayerAddress = TLA,
+ 'gTP-TEID' =
encode_teid(TEID_ToCore)}, S1};
%% E-RAB SETUP RESPONSE related IEs
handle_ie(#'ProtocolIE-Field'{id = ?'id-E-RABSetupListBearerSURes',
@@ -201,10 +227,22 @@
handle_ies(Content, ?'id-E-RABSetupItemBearerSURes', S);
handle_ie(#'ProtocolIE-Field'{id = ?'id-E-RABSetupItemBearerSURes',
- value = Content}, S) ->
+ value = C0}, S) ->
%% MME -> eNB direction: we pass our eNB facing local address
TLA = transp_layer_addr(s1gw_bind_addr),
- {Content#'E-RABSetupItemBearerSURes'{transportLayerAddress = TLA}, S};
+ %% poke E-RAB FSM
+ #'E-RABSetupItemBearerSURes'{'e-RAB-ID' = ERABId,
+ 'gTP-TEID' = TEID_FromCore} = C0,
+ C1 = case dict:find(ERABId, S#proxy_state.erabs) of
+ {ok, Pid} ->
+ {ok, TEID_ToAcc} = erab_fsm:erab_setup_rsp(Pid, decode_teid(TEID_FromCore)),
+ C0#'E-RABSetupItemBearerSURes'{transportLayerAddress = TLA,
+ 'gTP-TEID' =
encode_teid(TEID_ToAcc)};
+ error ->
+ ?LOG_ERROR("E-RAB-ID ~p is not registered", [ERABId]),
+ C0#'E-RABSetupItemBearerSURes'{transportLayerAddress = TLA}
+ end,
+ {C1, S};
%% E-RAB MODIFICATION INDICATION related IEs
handle_ie(#'ProtocolIE-Field'{id =
?'id-E-RABToBeModifiedListBearerModInd',
@@ -287,4 +325,15 @@
%% sadly, there exists inet:ntoa/1, but not inet:aton/1
list_to_binary(tuple_to_list(Addr)).
+
+-spec erab_fsm_start_reg(non_neg_integer(), proxy_state()) -> {pid(), proxy_state()}.
+erab_fsm_start_reg(RABId, S) ->
+ {ok, Pid} = erab_fsm:start_link(RABId), %% TODO: add {eNB,MME}-UE-ID
+ {Pid, erab_fsm_reg(RABId, Pid, S)}.
+
+
+-spec erab_fsm_reg(non_neg_integer(), pid(), proxy_state()) -> proxy_state().
+erab_fsm_reg(RABId, Pid, #proxy_state{erabs = ERABs} = S) ->
+ S#proxy_state{erabs = dict:store(RABId, Pid, ERABs)}.
+
%% vim:set ts=4 sw=4 et:
diff --git a/src/sctp_proxy.erl b/src/sctp_proxy.erl
index 148e00a..1d8d305 100644
--- a/src/sctp_proxy.erl
+++ b/src/sctp_proxy.erl
@@ -167,6 +167,13 @@
sctp_server:send_data(EnbAid, NewData),
{keep_state, S#{priv := NewPriv}};
+%% Handle termination events of the child processes
+connected(info, {'EXIT', Pid, Reason},
+ #{priv := Priv} = S) ->
+ ?LOG_DEBUG("Child process ~p terminated with reason ~p", [Pid, Reason]),
+ NewPriv = s1ap_proxy:handle_exit(Pid, Priv),
+ {keep_state, S#{priv := NewPriv}};
+
%% Catch-all for other kinds of SCTP events
connected(info, {sctp, _Socket, MmeAddr, MmePort,
{AncData, Data}}, S) ->
--
To view, visit
https://gerrit.osmocom.org/c/erlang/osmo-s1gw/+/37463?usp=email
To unsubscribe, or for help writing mail filters, visit
https://gerrit.osmocom.org/settings
Gerrit-Project: erlang/osmo-s1gw
Gerrit-Branch: master
Gerrit-Change-Id: Ibb7e25ab3adbadd7fd85e9cb22e0136c6ca133cf
Gerrit-Change-Number: 37463
Gerrit-PatchSet: 1
Gerrit-Owner: fixeria <vyanitskiy(a)sysmocom.de>
Gerrit-MessageType: newchange