pespin has submitted this change. ( 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 M test/s1ap_proxy_test.erl 3 files changed, 166 insertions(+), 117 deletions(-)
Approvals: laforge: Looks good to me, but someone else must approve Jenkins Builder: Verified pespin: Looks good to me, approved
diff --git a/src/s1ap_proxy.erl b/src/s1ap_proxy.erl index eaa7dfd..048b91d 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,14 @@ -include("S1AP-Constants.hrl").
--record(proxy_state, { }). +-type mme_ue_id() :: 0..16#ffffffff. +-type enb_ue_id() :: 0..16#ffffff. +-type erab_id() :: 0..16#ff. + +-record(proxy_state, {erabs :: dict:dict(), + mme_ue_id :: undefined | mme_ue_id(), + enb_ue_id :: undefined | enb_ue_id() + }).
-type proxy_state() :: #proxy_state{}.
@@ -59,7 +67,7 @@ %% Initialize per-connection data -spec init() -> proxy_state(). init() -> - #proxy_state{}. + #proxy_state{erabs = dict:new()}.
%% De-initialize per-connection data @@ -81,6 +89,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 %% ------------------------------------------------------------------ @@ -189,10 +204,16 @@ handle_ies(Content, ?'id-E-RABToBeSetupItemBearerSUReq', S);
handle_ie(#'ProtocolIE-Field'{id = ?'id-E-RABToBeSetupItemBearerSUReq', - value = Content}, S) -> - %% eNB -> MME direction: we pass our MME facing local address - TLA = transp_layer_addr(mme_loc_addr), - {Content#'E-RABToBeSetupItemBearerSUReq'{transportLayerAddress = TLA}, S}; + value = C0}, S0) -> + %% start and register an E-RAB FSM + #'E-RABToBeSetupItemBearerSUReq'{'e-RAB-ID' = ERABId, + 'transportLayerAddress' = TLA_In, + 'gTP-TEID' = << TEID_In:32/big >>} = C0, + {Pid, S1} = erab_fsm_start_reg(ERABId, S0), + {ok, {TEID_Out, TLA_Out}} = erab_fsm:erab_setup_req(Pid, {TEID_In, TLA_In}), + C1 = C0#'E-RABToBeSetupItemBearerSUReq'{'transportLayerAddress' = TLA_Out, + 'gTP-TEID' = << TEID_Out:32/big >>}, + {C1, S1};
%% E-RAB SETUP RESPONSE related IEs handle_ie(#'ProtocolIE-Field'{id = ?'id-E-RABSetupListBearerSURes', @@ -201,10 +222,21 @@ handle_ies(Content, ?'id-E-RABSetupItemBearerSURes', S);
handle_ie(#'ProtocolIE-Field'{id = ?'id-E-RABSetupItemBearerSURes', - value = Content}, S) -> - %% MME -> eNB direction: we pass our eNB facing local address - TLA = transp_layer_addr(s1gw_bind_addr), - {Content#'E-RABSetupItemBearerSURes'{transportLayerAddress = TLA}, S}; + value = C0}, S) -> + %% poke E-RAB FSM + #'E-RABSetupItemBearerSURes'{'e-RAB-ID' = ERABId, + 'transportLayerAddress' = TLA_In, + 'gTP-TEID' = << TEID_In:32/big >>} = C0, + C1 = case erab_fsm_find(ERABId, S) of + {ok, Pid} -> + {ok, {TEID_Out, TLA_Out}} = erab_fsm:erab_setup_rsp(Pid, {TEID_In, TLA_In}), + C0#'E-RABSetupItemBearerSURes'{'transportLayerAddress' = TLA_Out, + 'gTP-TEID' = << TEID_Out:32/big >>}; + error -> + ?LOG_ERROR("E-RAB-ID ~p is not registered", [ERABId]), + C0 %% XXX: proxy as-is or drop? + end, + {C1, S};
%% E-RAB MODIFICATION INDICATION related IEs handle_ie(#'ProtocolIE-Field'{id = ?'id-E-RABToBeModifiedListBearerModInd', @@ -214,9 +246,8 @@
handle_ie(#'ProtocolIE-Field'{id = ?'id-E-RABToBeModifiedItemBearerModInd', value = Content}, S) -> - %% eNB -> MME direction: we pass our MME facing local address - TLA = transp_layer_addr(mme_loc_addr), - {Content#'E-RABToBeModifiedItemBearerModInd'{transportLayerAddress = TLA}, S}; + %% TODO: find and poke an E-RAB FSM associated with this E-RAB + {Content#'E-RABToBeModifiedItemBearerModInd'{}, S};
handle_ie(#'ProtocolIE-Field'{id = ?'id-E-RABNotToBeModifiedListBearerModInd', value = Content}, S) -> @@ -225,9 +256,8 @@
handle_ie(#'ProtocolIE-Field'{id = ?'id-E-RABNotToBeModifiedItemBearerModInd', value = Content}, S) -> - %% eNB -> MME direction: we pass our MME facing local address - TLA = transp_layer_addr(mme_loc_addr), - {Content#'E-RABNotToBeModifiedItemBearerModInd'{transportLayerAddress = TLA}, S}; + %% TODO: find and poke an E-RAB FSM associated with this E-RAB + {Content#'E-RABNotToBeModifiedItemBearerModInd'{}, S};
%% INITIAL CONTEXT SETUP REQUEST related IEs handle_ie(#'ProtocolIE-Field'{id = ?'id-E-RABToBeSetupListCtxtSUReq', @@ -236,10 +266,16 @@ handle_ies(Content, ?'id-E-RABToBeSetupItemCtxtSUReq', S);
handle_ie(#'ProtocolIE-Field'{id = ?'id-E-RABToBeSetupItemCtxtSUReq', - value = Content}, S) -> - %% eNB -> MME direction: we pass our MME facing local address - TLA = transp_layer_addr(mme_loc_addr), - {Content#'E-RABToBeSetupItemCtxtSUReq'{transportLayerAddress = TLA}, S}; + value = C0}, S0) -> + %% start and register an E-RAB FSM + #'E-RABToBeSetupItemCtxtSUReq'{'e-RAB-ID' = ERABId, + 'transportLayerAddress' = TLA_In, + 'gTP-TEID' = << TEID_In:32/big >>} = C0, + {Pid, S1} = erab_fsm_start_reg(ERABId, S0), + {ok, {TEID_Out, TLA_Out}} = erab_fsm:erab_setup_req(Pid, {TEID_In, TLA_In}), + C1 = C0#'E-RABToBeSetupItemCtxtSUReq'{'transportLayerAddress' = TLA_Out, + 'gTP-TEID' = << TEID_Out:32/big >>}, + {C1, S1};
%% INITIAL CONTEXT SETUP RESPONSE related IEs handle_ie(#'ProtocolIE-Field'{id = ?'id-E-RABSetupListCtxtSURes', @@ -248,10 +284,21 @@ handle_ies(Content, ?'id-E-RABSetupItemCtxtSURes', S);
handle_ie(#'ProtocolIE-Field'{id = ?'id-E-RABSetupItemCtxtSURes', - value = Content}, S) -> - %% MME -> eNB direction: we pass our eNB facing local address - TLA = transp_layer_addr(s1gw_bind_addr), - {Content#'E-RABSetupItemCtxtSURes'{transportLayerAddress = TLA}, S}; + value = C0}, S) -> + %% poke E-RAB FSM + #'E-RABSetupItemCtxtSURes'{'e-RAB-ID' = ERABId, + 'transportLayerAddress' = TLA_In, + 'gTP-TEID' = << TEID_In:32/big >>} = C0, + C1 = case erab_fsm_find(ERABId, S) of + {ok, Pid} -> + {ok, {TEID_Out, TLA_Out}} = erab_fsm:erab_setup_rsp(Pid, {TEID_In, TLA_In}), + C0#'E-RABSetupItemCtxtSURes'{'transportLayerAddress' = TLA_Out, + 'gTP-TEID' = << TEID_Out:32/big >>}; + error -> + ?LOG_ERROR("E-RAB-ID ~p is not registered", [ERABId]), + C0 %% XXX: proxy as-is or drop? + end, + {C1, S};
%% Catch-all variant, which should not be called normally handle_ie(#'ProtocolIE-Field'{value = Content} = IE, S) -> @@ -261,6 +308,7 @@
%% Iterate over the given list of 'ProtocolIE-Field' IEs, %% calling function handle_ie/1 for IEs matching the given IEI. +%% Additionally look for {MME,eNB}-UE-S1AP-ID IEs and store their values. -spec handle_ies(list(), integer(), proxy_state()) -> {list(), proxy_state()}. handle_ies(IEs, IEI, S) -> handle_ies([], IEs, IEI, S). @@ -271,6 +319,12 @@ {Content, S1} = handle_ie(IE, S0), NewIE = IE#'ProtocolIE-Field'{value = Content}, handle_ies([NewIE | Acc], IEs, IEI, S1); + #'ProtocolIE-Field'{id = ?'id-MME-UE-S1AP-ID', value = Id} -> + S1 = S0#proxy_state{mme_ue_id = Id}, + handle_ies([IE | Acc], IEs, IEI, S1); + #'ProtocolIE-Field'{id = ?'id-eNB-UE-S1AP-ID', value = Id} -> + S1 = S0#proxy_state{enb_ue_id = Id}, + handle_ies([IE | Acc], IEs, IEI, S1); _ -> handle_ies([IE | Acc], IEs, IEI, S0) end; @@ -279,12 +333,20 @@ {lists:reverse(Acc), S}.
-%% GTP-U IP address (TransportLayerAddress) to be used while patching --spec transp_layer_addr(atom()) -> binary(). -transp_layer_addr(EnvParam) -> - {ok, AddrStr} = application:get_env(osmo_s1gw, EnvParam), - {ok, Addr} = inet:parse_address(AddrStr), - %% sadly, there exists inet:ntoa/1, but not inet:aton/1 - list_to_binary(tuple_to_list(Addr)). +-spec erab_fsm_start_reg(erab_id(), proxy_state()) -> {pid(), proxy_state()}. +erab_fsm_start_reg(RABId, #proxy_state{erabs = ERABs, + mme_ue_id = MmeUeId, + enb_ue_id = EnbUeId} = S) -> + UID = {MmeUeId, EnbUeId, RABId}, + {ok, Pid} = erab_fsm:start_link(UID), + {Pid, S#proxy_state{erabs = dict:store(UID, Pid, ERABs)}}. + + +-spec erab_fsm_find(erab_id(), proxy_state()) -> {ok, pid()} | error. +erab_fsm_find(RABId, #proxy_state{erabs = ERABs, + mme_ue_id = MmeUeId, + enb_ue_id = EnbUeId}) -> + UID = {MmeUeId, EnbUeId, RABId}, + dict:find(UID, 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) -> diff --git a/test/s1ap_proxy_test.erl b/test/s1ap_proxy_test.erl index cb0a4ca..9426119 100644 --- a/test/s1ap_proxy_test.erl +++ b/test/s1ap_proxy_test.erl @@ -1,9 +1,7 @@ -module(s1ap_proxy_test).
-include_lib("eunit/include/eunit.hrl"). - --define(EXP_ADDR_STR, "127.0.0.1"). --define(EXP_ADDR_BIN, << 16#7f, 16#00, 16#00, 16#01 >>). +-include("pfcp_mock.hrl").
%% ------------------------------------------------------------------ %% setup functions @@ -16,10 +14,12 @@
start() -> + pfcp_mock:mock_all(), s1ap_proxy:init().
stop(S) -> + pfcp_mock:unmock_all(), s1ap_proxy:deinit(S).
@@ -30,22 +30,67 @@ s1ap_proxy_test_() -> [{"S1 SETUP REQUEST (unmodified)", ?TC(fun test_s1_setup_req/1)}, - {"E-RAB SETUP REQUEST", - ?TC(fun test_e_rab_setup_req/1)}, - {"E-RAB SETUP RESPONSE", - ?TC(fun test_e_rab_setup_rsp/1)}, + {"E-RAB SETUP REQUEST/RESPONSE", + ?TC(fun test_e_rab_setup/1)}, {"E-RAB MODIFICATION INDICATION", ?TC(fun test_e_rab_modify_ind/1)}, - {"INITIAL CONTEXT SETUP REQUEST", - ?TC(fun test_initial_context_setup_req/1)}, - {"INITIAL CONTEXT SETUP RESPONSE", - ?TC(fun test_initial_context_setup_rsp/1)}]. + {"INITIAL CONTEXT SETUP REQUEST/RESPONSE", + ?TC(fun test_initial_context_setup/1)}].
%% ------------------------------------------------------------------ %% actual testcases %% ------------------------------------------------------------------
+test_s1_setup_req(S0) -> + SetupReq = s1_setup_req_pdu(), + %% Expect the PDU to be proxied unmodified + [?_assertEqual({SetupReq, S0}, s1ap_proxy:handle_pdu(SetupReq, S0))]. + + +test_e_rab_setup(S0) -> + %% [eNB <- MME] E-RAB SETUP REQUEST + SetupReqIn = e_rab_setup_req_pdu(?ADDR_U2C, ?TEID_U2C), + SetupReqExp = e_rab_setup_req_pdu(?ADDR_A2U, ?TEID_A2U), + {SetupReqOut, S1} = s1ap_proxy:handle_pdu(SetupReqIn, S0), + + %% [eNB -> MME] E-RAB SETUP RESPONSE + SetupRspIn = e_rab_setup_rsp_pdu(?ADDR_U2A, ?TEID_U2A), + SetupRspExp = e_rab_setup_rsp_pdu(?ADDR_C2U, ?TEID_C2U), + {SetupRspOut, _S2} = s1ap_proxy:handle_pdu(SetupRspIn, S1), + + [?_assertEqual(SetupReqExp, SetupReqOut), + ?_assertEqual(SetupRspExp, SetupRspOut)]. + + +test_e_rab_modify_ind(S0) -> + %% [eNB -> MME] E-RAB MODIFICATION INDICATION + ModifyIndIn = e_rab_modify_ind_pdu(?ADDR_U2A, ?TEID_U2A), + %% XXX: not implemented, we should actually expect ?ADDR_C2U, ?TEID_C2U + ModifyIndExp = e_rab_modify_ind_pdu(?ADDR_U2A, ?TEID_U2A), + {ModifyIndOut, _S1} = s1ap_proxy:handle_pdu(ModifyIndIn, S0), + + [?_assertEqual(ModifyIndExp, ModifyIndOut)]. + +test_initial_context_setup(S0) -> + %% [eNB <- MME] INITIAL CONTEXT SETUP REQUEST + InitCtxSetupReqIn = initial_context_setup_req_pdu(?ADDR_U2C, ?TEID_U2C), + InitCtxSetupReqExp = initial_context_setup_req_pdu(?ADDR_A2U, ?TEID_A2U), + {InitCtxSetupReqOut, S1} = s1ap_proxy:handle_pdu(InitCtxSetupReqIn, S0), + + %% [eNB -> MME] INITIAL CONTEXT SETUP RESPONSE + InitCtxSetupRspIn = initial_context_setup_rsp_pdu(?ADDR_U2A, ?TEID_U2A), + InitCtxSetupRspExp = initial_context_setup_rsp_pdu(?ADDR_C2U, ?TEID_C2U), + {InitCtxSetupRspOut, _S2} = s1ap_proxy:handle_pdu(InitCtxSetupRspIn, S1), + + [?_assertEqual(InitCtxSetupReqExp, InitCtxSetupReqOut), + ?_assertEqual(InitCtxSetupRspExp, InitCtxSetupRspOut)]. + + +%% ------------------------------------------------------------------ +%% S1AP PDU templates +%% ------------------------------------------------------------------ + %% S1 SETUP REQUEST s1_setup_req_pdu() -> << 16#00, 16#11, 16#00, 16#1a, 16#00, 16#00, 16#02, 16#00, @@ -54,22 +99,17 @@ 16#0c, 16#0e, 16#40, 16#00, 16#f1, 16#10 >>.
-test_s1_setup_req(S) -> - OrigData = s1_setup_req_pdu(), - %% Expect the PDU to be proxied unmodified - [?_assertEqual({OrigData, S}, s1ap_proxy:handle_pdu(OrigData, S))]. -
%% [eNB <- MME] E-RAB SETUP REQUEST e_rab_setup_req_pdu(TLA, TEID) when is_binary(TLA), - is_binary(TEID) -> + is_integer(TEID) -> << 16#00, 16#05, 16#00, 16#80, 16#9b, 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#10, 16#00, 16#80, 16#87, 16#00, 16#00, 16#11, 16#00, 16#80, 16#81, 16#0c, 16#00, 16#05, 16#04, 16#0f, 16#80, TLA/bytes, %% transportLayerAddress (IPv4) - TEID/bytes, %% GTP-TEID + TEID:32/big, %% GTP-TEID 16#72, 16#27, 16#c8, 16#1a, 16#bc, 16#ec, 16#11, 16#62, 16#54, 16#c1, 16#01, 16#05, 16#04, 16#03, 16#69, 16#6d, 16#73, 16#05, 16#01, @@ -87,70 +127,34 @@ 16#16, 16#00, 16#15, 16#00, 16#10, 16#02, 16#05, 16#78 >>.
-test_e_rab_setup_req(S) -> - %% Original input data - TEID = << 16#00, 16#00, 16#00, 16#18 >>, - OrigTLA = << 16#ac, 16#16, 16#00, 16#06 >>, - OrigData = e_rab_setup_req_pdu(OrigTLA, TEID), - - %% Expected output data - ExpData = e_rab_setup_req_pdu(?EXP_ADDR_BIN, TEID), - - application:set_env(osmo_s1gw, mme_loc_addr, ?EXP_ADDR_STR), - [?_assertMatch({ExpData, _}, s1ap_proxy:handle_pdu(OrigData, S))]. -
%% [eNB -> MME] E-RAB SETUP RESPONSE e_rab_setup_rsp_pdu(TLA, TEID) when is_binary(TLA), - is_binary(TEID) -> + is_integer(TEID) -> << 16#20, 16#05, 16#00, 16#22, 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#1c, 16#40, 16#0f, 16#00, 16#00, 16#27, 16#40, 16#0a, 16#0c, 16#1f, TLA/bytes, %% transportLayerAddress (IPv4) - TEID/bytes %% GTP-TEID + TEID:32/big %% GTP-TEID >>.
-test_e_rab_setup_rsp(S) -> - %% Original input data - TEID = << 16#6c, 16#05, 16#bf, 16#56 >>, - OrigTLA = << 16#c0, 16#a8, 16#68, 16#a7 >>, - OrigData = e_rab_setup_rsp_pdu(OrigTLA, TEID), - - %% Expected output data - ExpData = e_rab_setup_rsp_pdu(?EXP_ADDR_BIN, TEID), - - application:set_env(osmo_s1gw, s1gw_bind_addr, ?EXP_ADDR_STR), - [?_assertMatch({ExpData, _}, s1ap_proxy:handle_pdu(OrigData, S))]. -
%% [eNB -> MME] E-RAB MODIFICATION INDICATION e_rab_modify_ind_pdu(TLA, TEID) when is_binary(TLA), - is_binary(TEID) -> + is_integer(TEID) -> << 16#00, 16#32, 16#00, 16#24, 16#00, 16#00, 16#03, 16#00, 16#00, 16#00, 16#02, 16#00, 16#02, 16#00, 16#08, 16#00, 16#04, 16#80, 16#06, 16#69, 16#2d, 16#00, 16#c7, 16#00, 16#0f, 16#00, 16#00, 16#c8, 16#00, 16#0a, 16#0a, 16#1f, TLA/bytes, %% transportLayerAddress (IPv4) - TEID/bytes %% GTP-TEID + TEID:32/big %% GTP-TEID >>.
-test_e_rab_modify_ind(S) -> - %% Original input data - TEID = << 16#3d, 16#b0, 16#b5, 16#1d >>, - OrigTLA = << 16#c0, 16#a8, 16#12, 16#c6 >>, - OrigData = e_rab_modify_ind_pdu(OrigTLA, TEID), - - %% Expected output data - ExpData = e_rab_modify_ind_pdu(?EXP_ADDR_BIN, TEID), - - application:set_env(osmo_s1gw, mme_loc_addr, ?EXP_ADDR_STR), - [?_assertMatch({ExpData, _}, s1ap_proxy:handle_pdu(OrigData, S))]. -
%% [eNB <- MME] INITIAL CONTEXT SETUP REQUEST initial_context_setup_req_pdu(TLA, TEID) when is_binary(TLA), - is_binary(TEID) -> + is_integer(TEID) -> << 16#00, 16#09, 16#00, 16#81, 16#10, 16#00, 16#00, 16#07, 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#42, 16#00, 16#0a, @@ -159,7 +163,7 @@ 16#00, 16#34, 16#00, 16#80, 16#af, 16#45, 16#00, 16#09, 16#20, 16#0f, 16#80, TLA/bytes, %% transportLayerAddress (IPv4) - TEID/bytes, %% GTP-TEID + TEID:32/big, %% GTP-TEID 16#80, 16#9f, 16#27, 16#bd, 16#de, 16#61, 16#4e, 16#02, 16#07, 16#42, 16#02, 16#29, 16#06, 16#40, 16#32, 16#f8, 16#10, 16#00, 16#01, 16#00, 16#6e, @@ -190,40 +194,16 @@ 16#10, 16#03, 16#ff, 16#ff, 16#74 >>.
-test_initial_context_setup_req(S) -> - %% Original input data - TEID = << 16#00, 16#00, 16#71, 16#23 >>, - OrigTLA = << 16#c0, 16#a8, 16#02, 16#d2 >>, - OrigData = initial_context_setup_req_pdu(OrigTLA, TEID), - - %% Expected output data - ExpData = initial_context_setup_req_pdu(?EXP_ADDR_BIN, TEID), - - application:set_env(osmo_s1gw, mme_loc_addr, ?EXP_ADDR_STR), - [?_assertMatch({ExpData, _}, s1ap_proxy:handle_pdu(OrigData, S))]. -
%% [eNB -> MME] INITIAL CONTEXT SETUP RESPONSE initial_context_setup_rsp_pdu(TLA, TEID) when is_binary(TLA), - is_binary(TEID) -> + is_integer(TEID) -> << 16#20, 16#09, 16#00, 16#22, 16#00, 16#00, 16#03, 16#00, 16#00, 16#40, 16#02, 16#00, 16#01, 16#00, 16#08, 16#40, 16#02, 16#00, 16#01, 16#00, 16#33, 16#40, 16#0f, 16#00, 16#00, 16#32, 16#40, 16#0a, 16#0a, 16#1f, TLA/bytes, %% transportLayerAddress (IPv4) - TEID/bytes %% GTP-TEID + TEID:32/big %% GTP-TEID >>.
-test_initial_context_setup_rsp(S) -> - %% Original input data - TEID = << 16#00, 16#00, 16#00, 16#01 >>, - OrigTLA = << 16#c0, 16#a8, 16#02, 16#cb >>, - OrigData = initial_context_setup_rsp_pdu(OrigTLA, TEID), - - %% Expected output data - ExpData = initial_context_setup_rsp_pdu(?EXP_ADDR_BIN, TEID), - - application:set_env(osmo_s1gw, s1gw_bind_addr, ?EXP_ADDR_STR), - [?_assertMatch({ExpData, _}, s1ap_proxy:handle_pdu(OrigData, S))]. - %% vim:set ts=4 sw=4 et: