lists.osmocom.org
Sign In
Sign Up
Sign In
Sign Up
Manage this list
×
Keyboard Shortcuts
Thread View
j
: Next unread message
k
: Previous unread message
j a
: Jump to all threads
j l
: Jump to MailingList overview
2025
June
May
April
March
February
January
2024
December
November
October
September
August
July
June
May
April
March
February
January
2023
December
November
October
September
August
July
June
May
April
March
February
January
2022
December
November
October
September
August
July
June
May
April
March
February
January
List overview
Download
gerrit-log
September 2024
----- 2025 -----
June 2025
May 2025
April 2025
March 2025
February 2025
January 2025
----- 2024 -----
December 2024
November 2024
October 2024
September 2024
August 2024
July 2024
June 2024
May 2024
April 2024
March 2024
February 2024
January 2024
----- 2023 -----
December 2023
November 2023
October 2023
September 2023
August 2023
July 2023
June 2023
May 2023
April 2023
March 2023
February 2023
January 2023
----- 2022 -----
December 2022
November 2022
October 2022
September 2022
August 2022
July 2022
June 2022
May 2022
April 2022
March 2022
February 2022
January 2022
gerrit-log@lists.osmocom.org
1 participants
1983 discussions
Start a n
N
ew thread
[S] Change in ...osmo-s1gw[master]: s1ap_proxy: move sctp_proxy:handle_pdu() to process_pdu_safe()
by fixeria
fixeria has submitted this change. (
https://gerrit.osmocom.org/c/erlang/osmo-s1gw/+/38298?usp=email
) Change subject: s1ap_proxy: move sctp_proxy:handle_pdu() to process_pdu_safe() ...................................................................... s1ap_proxy: move sctp_proxy:handle_pdu() to process_pdu_safe() This way we can have more precise counting of PDUs forwarded as-is due to exceptions, for which this patch also adds a counter. Change-Id: I16d4cf279a930d35ca179bd9b49234d10180e5c5 --- M include/s1gw_metrics.hrl M src/s1ap_proxy.erl M src/s1gw_metrics.erl M src/sctp_proxy.erl 4 files changed, 21 insertions(+), 15 deletions(-) Approvals: pespin: Looks good to me, approved Jenkins Builder: Verified diff --git a/include/s1gw_metrics.hrl b/include/s1gw_metrics.hrl index 551c136..bb7043f 100644 --- a/include/s1gw_metrics.hrl +++ b/include/s1gw_metrics.hrl @@ -6,6 +6,7 @@ -define(S1GW_CTR_S1AP_ENB_ALL_RX, [ctr, s1ap, enb, all, rx]). -define(S1GW_CTR_S1AP_ENB_ALL_RX_UNKNOWN_ENB, [ctr, s1ap, enb, all, rx_unknown_enb]). -define(S1GW_CTR_S1AP_PROXY_UPLINK_PACKETS_QUEUED, [ctr, s1ap, proxy, uplink_packets_queued]). +-define(S1GW_CTR_S1AP_PROXY_EXCEPTION, [ctr, s1ap, proxy, exception]). -define(S1GW_CTR_S1AP_PROXY_IN_PKT_ALL, [ctr, s1ap, proxy, in_pkt, all]). -define(S1GW_CTR_S1AP_PROXY_IN_PKT_DECODE_ERROR, [ctr, s1ap, proxy, in_pkt, decode_error]). -define(S1GW_CTR_S1AP_PROXY_IN_PKT_PROC_ERROR, [ctr, s1ap, proxy, in_pkt, proc_error]). diff --git a/src/s1ap_proxy.erl b/src/s1ap_proxy.erl index 68d0d0e..6ec3d10 100644 --- a/src/s1ap_proxy.erl +++ b/src/s1ap_proxy.erl @@ -37,6 +37,7 @@ -export([init/0, deinit/1, process_pdu/2, + process_pdu_safe/2, handle_exit/2, encode_pdu/1, decode_pdu/1]). @@ -90,7 +91,8 @@ %% Process an S1AP PDU --spec process_pdu(binary(), proxy_state()) -> {{proxy_action(), binary()}, proxy_state()}. +-type process_pdu_result() :: {{proxy_action(), binary()}, proxy_state()}. +-spec process_pdu(binary(), proxy_state()) -> process_pdu_result(). process_pdu(OrigData, S0) -> s1gw_metrics:ctr_inc(?S1GW_CTR_S1AP_PROXY_IN_PKT_ALL), case decode_pdu(OrigData) of @@ -122,6 +124,20 @@ end. +%% A safe wrapper for proc/2 +-spec process_pdu_safe(binary(), proxy_state()) -> process_pdu_result(). +process_pdu_safe(OrigData, S) -> + try process_pdu(OrigData, S) of + Result -> Result + catch + Exception:Reason:StackTrace -> + ?LOG_ERROR("An exception occurred: ~p, ~p, ~p", [Exception, Reason, StackTrace]), + s1gw_metrics:ctr_inc(?S1GW_CTR_S1AP_PROXY_EXCEPTION), + s1gw_metrics:ctr_inc(?S1GW_CTR_S1AP_PROXY_OUT_PKT_FWD_UNMODIFIED), + {{forward, OrigData}, S} %% XXX: proxy as-is or drop? + end. + + %% Handle an exit event -spec handle_exit(pid(), proxy_state()) -> proxy_state(). handle_exit(Pid, #proxy_state{erabs = ERABs} = S) -> diff --git a/src/s1gw_metrics.erl b/src/s1gw_metrics.erl index ee14d08..e065a4a 100644 --- a/src/s1gw_metrics.erl +++ b/src/s1gw_metrics.erl @@ -56,6 +56,7 @@ ?S1GW_CTR_S1AP_ENB_ALL_RX, ?S1GW_CTR_S1AP_ENB_ALL_RX_UNKNOWN_ENB, ?S1GW_CTR_S1AP_PROXY_UPLINK_PACKETS_QUEUED, + ?S1GW_CTR_S1AP_PROXY_EXCEPTION, %% exception(s) occurred %% s1ap_proxy: INcoming PDU counters ?S1GW_CTR_S1AP_PROXY_IN_PKT_ALL, %% received total ?S1GW_CTR_S1AP_PROXY_IN_PKT_DECODE_ERROR, %% failed to decode diff --git a/src/sctp_proxy.erl b/src/sctp_proxy.erl index c901b80..9bec272 100644 --- a/src/sctp_proxy.erl +++ b/src/sctp_proxy.erl @@ -171,7 +171,7 @@ priv := Priv} = S) -> ?LOG_DEBUG("MME connection (id=~p, ~p:~p) -> eNB: ~p", [Aid, MmeAddr, MmePort, Data]), - {Action, NewPriv} = handle_pdu(Data, Priv), + {Action, NewPriv} = s1ap_proxy:process_pdu_safe(Data, Priv), case Action of {forward, FwdData} -> sctp_server:send_data(EnbAid, FwdData); @@ -224,25 +224,13 @@ %% private API %% ------------------------------------------------------------------ -%% A safe wrapper for s1ap_proxy:proc/2 --spec handle_pdu(binary(), term()) -> {{s1ap_proxy:proxy_action(), binary()}, term()}. -handle_pdu(OrigData, Priv) when is_binary(OrigData) -> - try s1ap_proxy:process_pdu(OrigData, Priv) of - Result -> Result %% {Action, NewPriv} - catch - Exception:Reason:StackTrace -> - ?LOG_ERROR("An exception occurred: ~p, ~p, ~p", [Exception, Reason, StackTrace]), - {{forward, OrigData}, Priv} %% XXX: proxy as-is or drop? - end. - - %% Send a single message to the MME sctp_send(Data, #{sock := Sock, enb_aid := EnbAid, mme_aid := Aid, priv := Priv} = S) -> - {Action, NewPriv} = handle_pdu(Data, Priv), + {Action, NewPriv} = s1ap_proxy:process_pdu_safe(Data, Priv), case Action of {forward, FwdData} -> ok = sctp_client:send_data({Sock, Aid}, FwdData); -- To view, visit
https://gerrit.osmocom.org/c/erlang/osmo-s1gw/+/38298?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: I16d4cf279a930d35ca179bd9b49234d10180e5c5 Gerrit-Change-Number: 38298 Gerrit-PatchSet: 6 Gerrit-Owner: fixeria <vyanitskiy(a)sysmocom.de> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: fixeria <vyanitskiy(a)sysmocom.de> Gerrit-Reviewer: pespin <pespin(a)sysmocom.de>
8 months, 4 weeks
1
0
0
0
[M] Change in ...osmo-s1gw[master]: s1ap_proxy: handle E-RAB RELEASE INDICATION
by fixeria
fixeria has submitted this change. (
https://gerrit.osmocom.org/c/erlang/osmo-s1gw/+/38241?usp=email
) Change subject: s1ap_proxy: handle E-RAB RELEASE INDICATION ...................................................................... s1ap_proxy: handle E-RAB RELEASE INDICATION Change-Id: I13584620e28edf529325dc661c4b40d09acacc3f --- M src/s1ap_proxy.erl M test/s1ap_proxy_test.erl 2 files changed, 54 insertions(+), 2 deletions(-) Approvals: Jenkins Builder: Verified pespin: Looks good to me, approved diff --git a/src/s1ap_proxy.erl b/src/s1ap_proxy.erl index 0faa42f..4758484 100644 --- a/src/s1ap_proxy.erl +++ b/src/s1ap_proxy.erl @@ -210,6 +210,22 @@ {forward, S1} %% XXX: forward as-is or drop? end; +%% 9.1.3.7 E-RAB RELEASE INDICATION +handle_pdu({Outcome = initiatingMessage, + #'InitiatingMessage'{procedureCode = ?'id-E-RABReleaseIndication', + value = C0} = Msg}, S0) -> + ?LOG_DEBUG("Processing E-RAB RELEASE INDICATION"), + case handle_ies(C0#'E-RABReleaseIndication'.protocolIEs, + ?'id-E-RABReleasedList', S0) of + {{ok, IEs}, S1} -> + C1 = C0#'E-RABReleaseIndication'{protocolIEs = IEs}, + PDU = {Outcome, Msg#'InitiatingMessage'{value = C1}}, + {{forward, PDU}, S1}; %% forward patched PDU + {{error, Reason}, S1} -> + ?LOG_NOTICE("Failed to process E-RAB RELEASE INDICATION: ~p", [Reason]), + {forward, S1} %% XXX: forward as-is or drop? + end; + %% 9.1.3.8 E-RAB MODIFICATION INDICATION handle_pdu({Outcome = initiatingMessage, #'InitiatingMessage'{procedureCode = ?'id-E-RABModificationIndication', @@ -361,6 +377,12 @@ {{error, erab_not_registered}, S} end; +%% 9.1.3.7 E-RAB RELEASE INDICATION related IEs +handle_ie(#'ProtocolIE-Field'{id = ?'id-E-RABReleasedList', + value = Content}, S) -> + %% This IE contains a list of E-RABItem + handle_ies(Content, ?'id-E-RABItem', S); + %% E-RAB MODIFICATION INDICATION related IEs handle_ie(#'ProtocolIE-Field'{id = ?'id-E-RABToBeModifiedListBearerModInd', value = Content}, S) -> diff --git a/test/s1ap_proxy_test.erl b/test/s1ap_proxy_test.erl index aa3763e..04d52df 100644 --- a/test/s1ap_proxy_test.erl +++ b/test/s1ap_proxy_test.erl @@ -35,7 +35,9 @@ {"E-RAB SETUP REQUEST (failure)", ?TC(fun test_e_rab_setup_req_fail/1)}, {"E-RAB RELEASE COMMAND/RESPONSE", - ?TC(fun test_e_rab_release/1)}, + ?TC(fun test_e_rab_release_cmd/1)}, + {"E-RAB RELEASE INDICATION", + ?TC(fun test_e_rab_release_ind/1)}, {"E-RAB MODIFICATION INDICATION", ?TC(fun test_e_rab_modify_ind/1)}, {"INITIAL CONTEXT SETUP REQUEST/RESPONSE", @@ -84,7 +86,7 @@ [?_assertEqual(SetupRspExp, SetupRspOut)]. -test_e_rab_release(S0) -> +test_e_rab_release_cmd(S0) -> %% [eNB <- MME] E-RAB SETUP REQUEST SetupReqIn = e_rab_setup_req_pdu(?ADDR_U2C, ?TEID_U2C), {_, S1} = s1ap_proxy:process_pdu(SetupReqIn, S0), @@ -107,6 +109,24 @@ ?_assertEqual(ReleaseRsp, ReleaseRspOut)]. +test_e_rab_release_ind(S0) -> + %% [eNB <- MME] E-RAB SETUP REQUEST + SetupReqIn = e_rab_setup_req_pdu(?ADDR_U2C, ?TEID_U2C), + {_, S1} = s1ap_proxy:process_pdu(SetupReqIn, S0), + + %% [eNB -> MME] E-RAB SETUP RESPONSE + SetupRspIn = e_rab_setup_rsp_pdu(?ADDR_U2A, ?TEID_U2A), + {_, S2} = s1ap_proxy:process_pdu(SetupRspIn, S1), + + %% [eNB -> MME] E-RAB RELEASE INDICATION + ReleaseInd = e_rab_release_ind_pdu(), + {{forward, ReleaseIndOut}, _S3} = s1ap_proxy:process_pdu(ReleaseInd, S2), + + %% TODO: make sure that the E-RAB FSM has been terminated + + [?_assertEqual(ReleaseInd, ReleaseIndOut)]. + + test_e_rab_modify_ind(S0) -> %% [eNB -> MME] E-RAB MODIFICATION INDICATION ModifyIndIn = e_rab_modify_ind_pdu(?ADDR_U2A, ?TEID_U2A), @@ -214,6 +234,16 @@ >>. +%% [eNB -> MME] E-RAB RELEASE INDICATION +%% TODO: make E-RAB IDs configurable +e_rab_release_ind_pdu() -> + << 16#00, 16#08, 16#00, 16#1a, 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#6e, 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/+/38241?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: I13584620e28edf529325dc661c4b40d09acacc3f Gerrit-Change-Number: 38241 Gerrit-PatchSet: 5 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>
8 months, 4 weeks
1
0
0
0
[L] Change in ...osmo-s1gw[master]: s1ap_proxy: Support replying errors
by fixeria
fixeria has submitted this change. (
https://gerrit.osmocom.org/c/erlang/osmo-s1gw/+/37924?usp=email
) Change subject: s1ap_proxy: Support replying errors ...................................................................... s1ap_proxy: Support replying errors Sometimes it is needed not only to forward, but to transmit messages initiated at the S1GW. This is the case, for instance, if the MME wants to initiate an E-RAB establishment, but the co-located UPF is not available at the time or responds with an error. This patch adds the generic infrastructure to be able to reply (errors) and implements the above mentioned specific case for the S1AP E-RAB SETUP REQUEST procedure. Change-Id: I242e84fb09b00f4794b6e1aa770f348a0e60aea4 --- M src/s1ap_proxy.erl M src/sctp_proxy.erl M test/s1ap_proxy_test.erl 3 files changed, 281 insertions(+), 147 deletions(-) Approvals: Jenkins Builder: Verified pespin: Looks good to me, approved diff --git a/src/s1ap_proxy.erl b/src/s1ap_proxy.erl index a98514c..0faa42f 100644 --- a/src/s1ap_proxy.erl +++ b/src/s1ap_proxy.erl @@ -36,7 +36,7 @@ -export([init/0, deinit/1, - handle_pdu/2, + process_pdu/2, handle_exit/2, encode_pdu/1, decode_pdu/1]). @@ -67,6 +67,9 @@ }). -type proxy_state() :: #proxy_state{}. +-type proxy_action() :: forward | reply. + +-export_type([proxy_action/0]). %% ------------------------------------------------------------------ %% public API @@ -85,15 +88,23 @@ %% Process an S1AP PDU --spec handle_pdu(binary(), proxy_state()) -> {binary(), proxy_state()}. -handle_pdu(Data, S) when is_binary(Data) -> - case decode_pdu(Data) of - {ok, Pdu} -> - ?LOG_DEBUG("Rx S1AP PDU: ~p", [Pdu]), - handle_pdu(Data, Pdu, S); +-spec process_pdu(binary(), proxy_state()) -> {{proxy_action(), binary()}, proxy_state()}. +process_pdu(OrigData, S0) -> + case decode_pdu(OrigData) of + {ok, PDU} -> + ?LOG_DEBUG("Rx S1AP PDU: ~p", [PDU]), + case handle_pdu(PDU, S0) of + {{Action, NewPDU}, S1} -> + {ok, NewData} = encode_pdu(NewPDU), + ?LOG_DEBUG("Tx (~p) S1AP PDU: ~p", [Action, NewPDU]), + {{Action, NewData}, S1}; + {forward, S1} -> + ?LOG_DEBUG("Tx (forward) S1AP PDU unmodified"), + {{forward, OrigData}, S1} + end; {error, {asn1, Error}} -> ?LOG_ERROR("S1AP PDU decoding failed: ~p", [Error]), - {Data, S} + {{forward, OrigData}, S0} %% XXX: forward as-is or drop? end. @@ -128,96 +139,124 @@ 'S1AP-PDU-Descriptions':decode('S1AP-PDU', Data). -%% Helper function for handle_pdu/3. -%% Attempt to encode a new (modified) S1AP PDU, -%% return a new binary() on success or Data on error. --spec handle_pdu_new(binary(), s1ap_pdu(), proxy_state()) -> {binary(), proxy_state()}. -handle_pdu_new(Data, NewPdu, S) -> - case encode_pdu(NewPdu) of - {ok, NewData} -> - {NewData, S}; - {error, {asn1, Error}} -> - ?LOG_ERROR("S1AP PDU encoding failed: ~p", [Error]), - {Data, S} - end. - - --spec handle_pdu(binary(), s1ap_pdu(), proxy_state()) -> {binary(), proxy_state()}. +%% Process an S1AP PDU +-spec handle_pdu(s1ap_pdu(), proxy_state()) -> {{proxy_action(), s1ap_pdu()}, proxy_state()} | + {forward, proxy_state()}. %% 9.1.3.1 E-RAB SETUP REQUEST -handle_pdu(Data, {Outcome = initiatingMessage, - #'InitiatingMessage'{procedureCode = ?'id-E-RABSetup', - value = Content} = Pdu}, S0) -> - ?LOG_DEBUG("Patching E-RAB SETUP REQUEST"), - {IEs, S1} = handle_ies(Content#'E-RABSetupRequest'.protocolIEs, - ?'id-E-RABToBeSetupListBearerSUReq', S0), - NewContent = Content#'E-RABSetupRequest'{protocolIEs = IEs}, - handle_pdu_new(Data, {Outcome, Pdu#'InitiatingMessage'{value = NewContent}}, S1); +handle_pdu({Outcome = initiatingMessage, + #'InitiatingMessage'{procedureCode = ?'id-E-RABSetup', + value = C0} = Msg}, S0) -> + ?LOG_DEBUG("Processing E-RAB SETUP REQUEST"), + case handle_ies(C0#'E-RABSetupRequest'.protocolIEs, + ?'id-E-RABToBeSetupListBearerSUReq', S0) of + {{ok, IEs}, S1} -> + C1 = C0#'E-RABSetupRequest'{protocolIEs = IEs}, + PDU = {Outcome, Msg#'InitiatingMessage'{value = C1}}, + {{forward, PDU}, S1}; %% forward patched PDU + {{error, Reason}, S1} -> + ?LOG_NOTICE("Failed to process E-RAB SETUP REQUEST: ~p", [Reason]), + PDU = build_erab_setup_response_failure(S1), + {{reply, PDU}, S1} %% reply PDU back to sender + end; %% 9.1.3.2 E-RAB SETUP RESPONSE -handle_pdu(Data, {Outcome = successfulOutcome, - #'SuccessfulOutcome'{procedureCode = ?'id-E-RABSetup', - value = Content} = Pdu}, S0) -> - ?LOG_DEBUG("Patching E-RAB SETUP RESPONSE"), - {IEs, S1} = handle_ies(Content#'E-RABSetupResponse'.protocolIEs, - ?'id-E-RABSetupListBearerSURes', S0), - NewContent = Content#'E-RABSetupResponse'{protocolIEs = IEs}, - handle_pdu_new(Data, {Outcome, Pdu#'SuccessfulOutcome'{value = NewContent}}, S1); +handle_pdu({Outcome = successfulOutcome, + #'SuccessfulOutcome'{procedureCode = ?'id-E-RABSetup', + value = C0} = Msg}, S0) -> + ?LOG_DEBUG("Processing E-RAB SETUP RESPONSE"), + case handle_ies(C0#'E-RABSetupResponse'.protocolIEs, + ?'id-E-RABSetupListBearerSURes', S0) of + {{ok, IEs}, S1} -> + C1 = C0#'E-RABSetupResponse'{protocolIEs = IEs}, + PDU = {Outcome, Msg#'SuccessfulOutcome'{value = C1}}, + {{forward, PDU}, S1}; %% forward patched PDU + {{error, Reason}, S1} -> + ?LOG_NOTICE("Failed to process E-RAB SETUP RESPONSE: ~p", [Reason]), + {forward, S1} %% XXX: forward as-is or drop? + end; %% TODO: 9.1.3.3 E-RAB MODIFY REQUEST / (Optional) Transport Information %% 9.1.3.5 E-RAB RELEASE COMMAND -handle_pdu(Data, {Outcome = initiatingMessage, - #'InitiatingMessage'{procedureCode = ?'id-E-RABRelease', - value = Content} = Pdu}, S0) -> +handle_pdu({Outcome = initiatingMessage, + #'InitiatingMessage'{procedureCode = ?'id-E-RABRelease', + value = C0} = Msg}, S0) -> ?LOG_DEBUG("Processing E-RAB RELEASE COMMAND"), - {IEs, S1} = handle_ies(Content#'E-RABReleaseCommand'.protocolIEs, - ?'id-E-RABToBeReleasedList', S0), - NewContent = Content#'E-RABReleaseCommand'{protocolIEs = IEs}, - handle_pdu_new(Data, {Outcome, Pdu#'InitiatingMessage'{value = NewContent}}, S1); + case handle_ies(C0#'E-RABReleaseCommand'.protocolIEs, + ?'id-E-RABToBeReleasedList', S0) of + {{ok, IEs}, S1} -> + C1 = C0#'E-RABReleaseCommand'{protocolIEs = IEs}, + PDU = {Outcome, Msg#'InitiatingMessage'{value = C1}}, + {{forward, PDU}, S1}; %% forward patched PDU + {{error, Reason}, S1} -> + ?LOG_NOTICE("Failed to process E-RAB RELEASE COMMAND: ~p", [Reason]), + {forward, S1} %% XXX: forward as-is or drop? + end; %% 9.1.3.6 E-RAB RELEASE RESPONSE -handle_pdu(Data, {Outcome = successfulOutcome, - #'SuccessfulOutcome'{procedureCode = ?'id-E-RABRelease', - value = Content} = Pdu}, S0) -> +handle_pdu({Outcome = successfulOutcome, + #'SuccessfulOutcome'{procedureCode = ?'id-E-RABRelease', + value = C0} = Msg}, S0) -> ?LOG_DEBUG("Processing E-RAB RELEASE RESPONSE"), - {IEs, S1} = handle_ies(Content#'E-RABReleaseResponse'.protocolIEs, - ?'id-E-RABReleaseListBearerRelComp', S0), - NewContent = Content#'E-RABReleaseResponse'{protocolIEs = IEs}, - handle_pdu_new(Data, {Outcome, Pdu#'SuccessfulOutcome'{value = NewContent}}, S1); + case handle_ies(C0#'E-RABReleaseResponse'.protocolIEs, + ?'id-E-RABReleaseListBearerRelComp', S0) of + {{ok, IEs}, S1} -> + C1 = C0#'E-RABReleaseResponse'{protocolIEs = IEs}, + PDU = {Outcome, Msg#'SuccessfulOutcome'{value = C1}}, + {{forward, PDU}, S1}; %% forward patched PDU + {{error, Reason}, S1} -> + ?LOG_NOTICE("Failed to process E-RAB RELEASE RESPONSE: ~p", [Reason]), + {forward, S1} %% XXX: forward as-is or drop? + end; %% 9.1.3.8 E-RAB MODIFICATION INDICATION -handle_pdu(Data, {Outcome = initiatingMessage, - #'InitiatingMessage'{procedureCode = ?'id-E-RABModificationIndication', - value = Content} = Pdu}, S0) -> - ?LOG_DEBUG("Patching E-RAB MODIFICATION INDICATION"), - IEs = Content#'E-RABModificationIndication'.protocolIEs, +handle_pdu({Outcome = initiatingMessage, + #'InitiatingMessage'{procedureCode = ?'id-E-RABModificationIndication', + value = C0} = Msg}, S0) -> + ?LOG_DEBUG("Processing E-RAB MODIFICATION INDICATION"), + IEs0 = C0#'E-RABModificationIndication'.protocolIEs, %% E-RAB to be Modified List - {IEs1, S1} = handle_ies(IEs, ?'id-E-RABToBeModifiedListBearerModInd', S0), + %% TODO: handle {error, Reason} + {{ok, IEs1}, S1} = handle_ies(IEs0, ?'id-E-RABToBeModifiedListBearerModInd', S0), %% E-RAB not to be Modified List - {IEs2, S2} = handle_ies(IEs1, ?'id-E-RABNotToBeModifiedListBearerModInd', S1), - NewContent = Content#'E-RABModificationIndication'{protocolIEs = IEs2}, - handle_pdu_new(Data, {Outcome, Pdu#'InitiatingMessage'{value = NewContent}}, S2); + %% TODO: handle {error, Reason} + {{ok, IEs2}, S2} = handle_ies(IEs1, ?'id-E-RABNotToBeModifiedListBearerModInd', S1), + C1 = C0#'E-RABModificationIndication'{protocolIEs = IEs2}, + PDU = {Outcome, Msg#'InitiatingMessage'{value = C1}}, + {{forward, PDU}, S2}; %% 9.1.4.1 INITIAL CONTEXT SETUP REQUEST -handle_pdu(Data, {Outcome = initiatingMessage, - #'InitiatingMessage'{procedureCode = ?'id-InitialContextSetup', - value = Content} = Pdu}, S0) -> - ?LOG_DEBUG("Patching INITIAL CONTEXT SETUP REQUEST"), - {IEs, S1} = handle_ies(Content#'InitialContextSetupRequest'.protocolIEs, - ?'id-E-RABToBeSetupListCtxtSUReq', S0), - NewContent = Content#'InitialContextSetupRequest'{protocolIEs = IEs}, - handle_pdu_new(Data, {Outcome, Pdu#'InitiatingMessage'{value = NewContent}}, S1); +handle_pdu({Outcome = initiatingMessage, + #'InitiatingMessage'{procedureCode = ?'id-InitialContextSetup', + value = C0} = Msg}, S0) -> + ?LOG_DEBUG("Processing INITIAL CONTEXT SETUP REQUEST"), + case handle_ies(C0#'InitialContextSetupRequest'.protocolIEs, + ?'id-E-RABToBeSetupListCtxtSUReq', S0) of + {{ok, IEs}, S1} -> + C1 = C0#'InitialContextSetupRequest'{protocolIEs = IEs}, + PDU = {Outcome, Msg#'InitiatingMessage'{value = C1}}, + {{forward, PDU}, S1}; %% forward patched PDU + {{error, Reason}, S1} -> + ?LOG_NOTICE("Failed to process INITIAL CONTEXT SETUP REQUEST: ~p", [Reason]), + {forward, S1} %% XXX: forward as-is or drop? + end; %% 9.1.4.3 INITIAL CONTEXT SETUP RESPONSE -handle_pdu(Data, {Outcome = successfulOutcome, - #'SuccessfulOutcome'{procedureCode = ?'id-InitialContextSetup', - value = Content} = Pdu}, S0) -> - ?LOG_DEBUG("Patching INITIAL CONTEXT SETUP RESPONSE"), - {IEs, S1} = handle_ies(Content#'InitialContextSetupResponse'.protocolIEs, - ?'id-E-RABSetupListCtxtSURes', S0), - NewContent = Content#'InitialContextSetupResponse'{protocolIEs = IEs}, - handle_pdu_new(Data, {Outcome, Pdu#'SuccessfulOutcome'{value = NewContent}}, S1); +handle_pdu({Outcome = successfulOutcome, + #'SuccessfulOutcome'{procedureCode = ?'id-InitialContextSetup', + value = C0} = Msg}, S0) -> + ?LOG_DEBUG("Processing INITIAL CONTEXT SETUP RESPONSE"), + case handle_ies(C0#'InitialContextSetupResponse'.protocolIEs, + ?'id-E-RABSetupListCtxtSURes', S0) of + {{ok, IEs}, S1} -> + C1 = C0#'InitialContextSetupResponse'{protocolIEs = IEs}, + PDU = {Outcome, Msg#'SuccessfulOutcome'{value = C1}}, + {{forward, PDU}, S1}; %% forward patched PDU + {{error, Reason}, S1} -> + ?LOG_NOTICE("Failed to process INITIAL CONTEXT SETUP RESPONSE: ~p", [Reason]), + {forward, S1} %% XXX: forward as-is or drop? + end; %% TODO: 9.1.5.2 HANDOVER COMMAND :: (O) UL/DL Transport Layer Address %% TODO: 9.1.5.4 HANDOVER REQUEST :: (M) Transport Layer Address @@ -227,12 +266,13 @@ %% TODO: 9.1.5.9 PATH SWITCH REQUEST ACKNOWLEDGE :: (M) Transport Layer Address %% Proxy all other messages unmodified -handle_pdu(Data, _Pdu, S) -> - {Data, S}. +handle_pdu(_PDU, S) -> + {forward, S}. %% Handle a single IE (Information Element) --spec handle_ie(s1ap_ie(), proxy_state()) -> {s1ap_ie_val(), proxy_state()}. +-type handle_ie_result() :: {ok, s1ap_ie_val()} | {error, term()}. +-spec handle_ie(s1ap_ie(), proxy_state()) -> {handle_ie_result(), proxy_state()}. %% E-RAB SETUP REQUEST related IEs handle_ie(#'ProtocolIE-Field'{id = ?'id-E-RABToBeSetupListBearerSUReq', @@ -247,10 +287,14 @@ '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}; + case erab_fsm:erab_setup_req(Pid, {TEID_In, TLA_In}) of + {ok, {TEID_Out, TLA_Out}} -> + C1 = C0#'E-RABToBeSetupItemBearerSUReq'{'transportLayerAddress' = TLA_Out, + 'gTP-TEID' = << TEID_Out:32/big >>}, + {{ok, C1}, S1}; + {error, Reason} -> + {{error, Reason}, S1} + end; %% E-RAB SETUP RESPONSE related IEs handle_ie(#'ProtocolIE-Field'{id = ?'id-E-RABSetupListBearerSURes', @@ -264,16 +308,20 @@ #'E-RABSetupItemBearerSURes'{'e-RAB-ID' = ERABId, 'transportLayerAddress' = TLA_In, 'gTP-TEID' = << TEID_In:32/big >>} = C0, - C1 = case erab_fsm_find(ERABId, S) of + 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 >>}; + case erab_fsm:erab_setup_rsp(Pid, {TEID_In, TLA_In}) of + {ok, {TEID_Out, TLA_Out}} -> + C1 = C0#'E-RABSetupItemBearerSURes'{'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", [ERABId]), - C0 %% XXX: proxy as-is or drop? - end, - {C1, S}; + {{error, erab_not_registered}, S} + end; %% 9.1.3.5 E-RAB RELEASE COMMAND related IEs handle_ie(#'ProtocolIE-Field'{id = ?'id-E-RABToBeReleasedList', @@ -282,16 +330,17 @@ handle_ies(Content, ?'id-E-RABItem', S); handle_ie(#'ProtocolIE-Field'{id = ?'id-E-RABItem', - value = Content}, S) -> + value = C}, S) -> %% poke E-RAB FSM - #'E-RABItem'{'e-RAB-ID' = ERABId} = Content, + #'E-RABItem'{'e-RAB-ID' = ERABId} = C, case erab_fsm_find(ERABId, S) of {ok, Pid} -> - ok = erab_fsm:erab_release_req(Pid); + ok = erab_fsm:erab_release_req(Pid), + {{ok, C}, S}; error -> - ?LOG_ERROR("E-RAB ~p is not registered", [erab_uid(ERABId, S)]) - end, - {Content, S}; + ?LOG_ERROR("E-RAB ~p is not registered", [erab_uid(ERABId, S)]), + {{error, erab_not_registered}, S} + end; %% 9.1.3.6 E-RAB RELEASE RESPONSE related IEs handle_ie(#'ProtocolIE-Field'{id = ?'id-E-RABReleaseListBearerRelComp', @@ -300,16 +349,17 @@ handle_ies(Content, ?'id-E-RABReleaseItemBearerRelComp', S); handle_ie(#'ProtocolIE-Field'{id = ?'id-E-RABReleaseItemBearerRelComp', - value = Content}, S) -> + value = C}, S) -> %% poke E-RAB FSM - #'E-RABReleaseItemBearerRelComp'{'e-RAB-ID' = ERABId} = Content, + #'E-RABReleaseItemBearerRelComp'{'e-RAB-ID' = ERABId} = C, case erab_fsm_find(ERABId, S) of {ok, Pid} -> - ok = erab_fsm:erab_release_rsp(Pid); + ok = erab_fsm:erab_release_rsp(Pid), + {{ok, C}, S}; error -> - ?LOG_ERROR("E-RAB ~p is not registered", [erab_uid(ERABId, S)]) - end, - {Content, S}; + ?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(#'ProtocolIE-Field'{id = ?'id-E-RABToBeModifiedListBearerModInd', @@ -318,9 +368,9 @@ handle_ies(Content, ?'id-E-RABToBeModifiedItemBearerModInd', S); handle_ie(#'ProtocolIE-Field'{id = ?'id-E-RABToBeModifiedItemBearerModInd', - value = Content}, S) -> + value = C}, S) -> %% TODO: find and poke an E-RAB FSM associated with this E-RAB - {Content#'E-RABToBeModifiedItemBearerModInd'{}, S}; + {{ok, C}, S}; handle_ie(#'ProtocolIE-Field'{id = ?'id-E-RABNotToBeModifiedListBearerModInd', value = Content}, S) -> @@ -328,9 +378,9 @@ handle_ies(Content, ?'id-E-RABNotToBeModifiedItemBearerModInd', S); handle_ie(#'ProtocolIE-Field'{id = ?'id-E-RABNotToBeModifiedItemBearerModInd', - value = Content}, S) -> + value = C}, S) -> %% TODO: find and poke an E-RAB FSM associated with this E-RAB - {Content#'E-RABNotToBeModifiedItemBearerModInd'{}, S}; + {{ok, C}, S}; %% INITIAL CONTEXT SETUP REQUEST related IEs handle_ie(#'ProtocolIE-Field'{id = ?'id-E-RABToBeSetupListCtxtSUReq', @@ -345,10 +395,14 @@ '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}; + case erab_fsm:erab_setup_req(Pid, {TEID_In, TLA_In}) of + {ok, {TEID_Out, TLA_Out}} -> + C1 = C0#'E-RABToBeSetupItemCtxtSUReq'{'transportLayerAddress' = TLA_Out, + 'gTP-TEID' = << TEID_Out:32/big >>}, + {{ok, C1}, S1}; + {error, Reason} -> + {{error, Reason}, S1} + end; %% INITIAL CONTEXT SETUP RESPONSE related IEs handle_ie(#'ProtocolIE-Field'{id = ?'id-E-RABSetupListCtxtSURes', @@ -362,36 +416,45 @@ #'E-RABSetupItemCtxtSURes'{'e-RAB-ID' = ERABId, 'transportLayerAddress' = TLA_In, 'gTP-TEID' = << TEID_In:32/big >>} = C0, - C1 = case erab_fsm_find(ERABId, S) of + 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 >>}; + case erab_fsm:erab_setup_rsp(Pid, {TEID_In, TLA_In}) of + {ok, {TEID_Out, TLA_Out}} -> + C1 = C0#'E-RABSetupItemCtxtSURes'{'transportLayerAddress' = TLA_Out, + 'gTP-TEID' = << TEID_Out:32/big >>}, + {{ok, C1}, S}; + {error, Reason} -> + {{error, Reason}, S} + end; error -> ?LOG_ERROR("E-RAB ~p is not registered", [erab_uid(ERABId, S)]), - C0 %% XXX: proxy as-is or drop? - end, - {C1, S}; + {{error, erab_not_registered}, S} + end; %% Catch-all variant, which should not be called normally -handle_ie(#'ProtocolIE-Field'{value = Content} = IE, S) -> +handle_ie(#'ProtocolIE-Field'{} = IE, S) -> ?LOG_ERROR("[BUG] Unhandled S1AP IE: ~p", [IE]), - {Content, S}. + {{error, unhandled_ie}, S}. %% 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()}. +-type handle_ies_result() :: {ok, list()} | {error, term()}. +-spec handle_ies(list(), integer(), proxy_state()) -> {handle_ies_result(), proxy_state()}. handle_ies(IEs, IEI, S) -> handle_ies([], IEs, IEI, S). handle_ies(Acc, [IE | IEs], IEI, S0) -> case IE of #'ProtocolIE-Field'{id = IEI} -> - {Content, S1} = handle_ie(IE, S0), - NewIE = IE#'ProtocolIE-Field'{value = Content}, - handle_ies([NewIE | Acc], IEs, IEI, S1); + case handle_ie(IE, S0) of + {{ok, C}, S1} -> + NewIE = IE#'ProtocolIE-Field'{value = C}, + handle_ies([NewIE | Acc], IEs, IEI, S1); + {{error, Reason}, S1} -> + {{error, Reason}, S1} + end; #'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); @@ -403,7 +466,35 @@ end; handle_ies(Acc, [], _IEI, S) -> - {lists:reverse(Acc), S}. + IEs = lists:reverse(Acc), + {{ok, IEs}, S}. + + +build_erab_setup_response_failure(#proxy_state{erabs = ERABs, + mme_ue_id = MmeUeId, + enb_ue_id = EnbUeId}) -> + %% FIXME: Currently we respond with E-RAB-ID of the first E-RAB in the registry. + %% Instead, we need to iterate over E-RABs in the REQUEST and reject them all. + [{_, _, FirstERABid}|_] = dict:fetch_keys(ERABs), + Cause = {transport, 'transport-resource-unavailable'}, + ERABitem = #'E-RABItem'{'e-RAB-ID' = FirstERABid, + cause = Cause}, + ERABlist = [#'ProtocolIE-Field'{id = ?'id-E-RABItem', + criticality = ignore, + value = ERABitem}], + IEs = [#'ProtocolIE-Field'{id = ?'id-MME-UE-S1AP-ID', + criticality = ignore, + value = MmeUeId}, + #'ProtocolIE-Field'{id = ?'id-eNB-UE-S1AP-ID', + criticality = ignore, + value = EnbUeId}, + #'ProtocolIE-Field'{id = ?'id-E-RABFailedToSetupListBearerSURes', + criticality = ignore, + value = ERABlist}], + {successfulOutcome, + #'SuccessfulOutcome'{procedureCode = ?'id-E-RABSetup', + criticality = reject, + value = #'E-RABSetupResponse'{protocolIEs = IEs}}}. -spec erab_fsm_start_reg(erab_id(), proxy_state()) -> {pid(), proxy_state()}. diff --git a/src/sctp_proxy.erl b/src/sctp_proxy.erl index 3ebabbd..b37bead 100644 --- a/src/sctp_proxy.erl +++ b/src/sctp_proxy.erl @@ -161,11 +161,19 @@ %% Handle an #sctp_sndrcvinfo event (MME -> eNB data) connected(info, {sctp, _Socket, MmeAddr, MmePort, {[#sctp_sndrcvinfo{assoc_id = Aid}], Data}}, - #{enb_aid := EnbAid, priv := Priv} = S) -> + #{sock := Sock, + enb_aid := EnbAid, + mme_aid := Aid, + priv := Priv} = S) -> ?LOG_DEBUG("MME connection (id=~p, ~p:~p) -> eNB: ~p", [Aid, MmeAddr, MmePort, Data]), - {NewData, NewPriv} = handle_pdu(Data, Priv), - sctp_server:send_data(EnbAid, NewData), + {Action, NewPriv} = handle_pdu(Data, Priv), + case Action of + {forward, FwdData} -> + sctp_server:send_data(EnbAid, FwdData); + {reply, ReData} -> + ok = sctp_client:send_data({Sock, Aid}, ReData) + end, {keep_state, S#{priv := NewPriv}}; %% Handle termination events of the child processes @@ -212,25 +220,31 @@ %% private API %% ------------------------------------------------------------------ -%% A safe wrapper for s1ap_proxy:handle_pdu/1 --spec handle_pdu(binary(), term()) -> {binary(), term()}. -handle_pdu(Data, Priv) when is_binary(Data) -> - try s1ap_proxy:handle_pdu(Data, Priv) of - Result -> Result %% {NewData, NewPriv} +%% A safe wrapper for s1ap_proxy:proc/2 +-spec handle_pdu(binary(), term()) -> {{s1ap_proxy:proxy_action(), binary()}, term()}. +handle_pdu(OrigData, Priv) when is_binary(OrigData) -> + try s1ap_proxy:process_pdu(OrigData, Priv) of + Result -> Result %% {Action, NewPriv} catch Exception:Reason:StackTrace -> ?LOG_ERROR("An exception occurred: ~p, ~p, ~p", [Exception, Reason, StackTrace]), - {Data, Priv} %% proxy as-is + {{forward, OrigData}, Priv} %% XXX: proxy as-is or drop? end. %% Send a single message to the MME sctp_send(Data, #{sock := Sock, + enb_aid := EnbAid, mme_aid := Aid, priv := Priv} = S) -> - {NewData, NewPriv} = handle_pdu(Data, Priv), - ok = sctp_client:send_data({Sock, Aid}, NewData), + {Action, NewPriv} = handle_pdu(Data, Priv), + case Action of + {forward, FwdData} -> + ok = sctp_client:send_data({Sock, Aid}, FwdData); + {reply, ReData} -> + sctp_server:send_data(EnbAid, ReData) + end, S#{priv := NewPriv}. diff --git a/test/s1ap_proxy_test.erl b/test/s1ap_proxy_test.erl index 5f6167d..aa3763e 100644 --- a/test/s1ap_proxy_test.erl +++ b/test/s1ap_proxy_test.erl @@ -32,6 +32,8 @@ ?TC(fun test_s1_setup_req/1)}, {"E-RAB SETUP REQUEST/RESPONSE", ?TC(fun test_e_rab_setup/1)}, + {"E-RAB SETUP REQUEST (failure)", + ?TC(fun test_e_rab_setup_req_fail/1)}, {"E-RAB RELEASE COMMAND/RESPONSE", ?TC(fun test_e_rab_release/1)}, {"E-RAB MODIFICATION INDICATION", @@ -47,40 +49,57 @@ 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))]. + [?_assertEqual({{forward, SetupReq}, S0}, s1ap_proxy:process_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), + {{forward, SetupReqOut}, S1} = s1ap_proxy:process_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), + {{forward, SetupRspOut}, _S2} = s1ap_proxy:process_pdu(SetupRspIn, S1), [?_assertEqual(SetupReqExp, SetupReqOut), ?_assertEqual(SetupRspExp, SetupRspOut)]. +test_e_rab_setup_req_fail(S0) -> + %% pfcp_peer:session_establish_req/3 responds with a reject + PDU = pfcp_mock:pdu_rsp_reject(session_establishment_response, ?SEID_Loc), + pfcp_mock:mock_req(session_establish_req, PDU), + %% the linked erab_fsm will terminate abnormally, so trap this + process_flag(trap_exit, true), + %% eNB <- [S1GW <- MME] E-RAB SETUP REQUEST + %% eNB -- [S1GW -> MME] E-RAB SETUP RESPONSE (failure) + SetupReqIn = e_rab_setup_req_pdu(?ADDR_U2C, ?TEID_U2C), + SetupRspExp = e_rab_setup_rsp_fail_pdu(), + {{reply, SetupRspOut}, _S1} = s1ap_proxy:process_pdu(SetupReqIn, S0), + + %% TODO: make sure that the E-RAB FSM has been terminated + + [?_assertEqual(SetupRspExp, SetupRspOut)]. + + test_e_rab_release(S0) -> %% [eNB <- MME] E-RAB SETUP REQUEST SetupReqIn = e_rab_setup_req_pdu(?ADDR_U2C, ?TEID_U2C), - {_, S1} = s1ap_proxy:handle_pdu(SetupReqIn, S0), + {_, S1} = s1ap_proxy:process_pdu(SetupReqIn, S0), %% [eNB -> MME] E-RAB SETUP RESPONSE SetupRspIn = e_rab_setup_rsp_pdu(?ADDR_U2A, ?TEID_U2A), - {_, S2} = s1ap_proxy:handle_pdu(SetupRspIn, S1), + {_, S2} = s1ap_proxy:process_pdu(SetupRspIn, S1), %% [eNB <- MME] E-RAB RELEASE COMMAND ReleaseCmd = e_rab_release_cmd_pdu(), - {ReleaseCmdOut, S3} = s1ap_proxy:handle_pdu(ReleaseCmd, S2), + {{forward, ReleaseCmdOut}, S3} = s1ap_proxy:process_pdu(ReleaseCmd, S2), %% [eNB -> MME] E-RAB RELEASE RESPONSE ReleaseRsp = e_rab_release_rsp_pdu(), - {ReleaseRspOut, _S4} = s1ap_proxy:handle_pdu(ReleaseRsp, S3), + {{forward, ReleaseRspOut}, _S4} = s1ap_proxy:process_pdu(ReleaseRsp, S3), %% TODO: make sure that the E-RAB FSM has been terminated @@ -93,7 +112,7 @@ 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), + {{forward, ModifyIndOut}, _S1} = s1ap_proxy:process_pdu(ModifyIndIn, S0), [?_assertEqual(ModifyIndExp, ModifyIndOut)]. @@ -101,12 +120,12 @@ %% [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), + {{forward, InitCtxSetupReqOut}, S1} = s1ap_proxy:process_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), + {{forward, InitCtxSetupRspOut}, _S2} = s1ap_proxy:process_pdu(InitCtxSetupRspIn, S1), [?_assertEqual(InitCtxSetupReqExp, InitCtxSetupReqOut), ?_assertEqual(InitCtxSetupRspExp, InitCtxSetupRspOut)]. @@ -165,6 +184,16 @@ >>. +%% [S1GW -> MME] E-RAB SETUP RESPONSE (failure) +%% Transport-cause: transport-resource-unavailable +e_rab_setup_rsp_fail_pdu() -> + << 16#20, 16#05, 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#1d, 16#40, 16#07, 16#00, + 16#00, 16#23, 16#40, 16#02, 16#0c, 16#20 + >>. + + %% [eNB <- MME] E-RAB RELEASE COMMAND %% TODO: make E-RAB IDs configurable e_rab_release_cmd_pdu() -> -- To view, visit
https://gerrit.osmocom.org/c/erlang/osmo-s1gw/+/37924?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: I242e84fb09b00f4794b6e1aa770f348a0e60aea4 Gerrit-Change-Number: 37924 Gerrit-PatchSet: 7 Gerrit-Owner: pespin <pespin(a)sysmocom.de> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: fixeria <vyanitskiy(a)sysmocom.de> Gerrit-Reviewer: laforge <laforge(a)osmocom.org> Gerrit-Reviewer: lynxis lazus <lynxis(a)fe80.eu> Gerrit-Reviewer: pespin <pespin(a)sysmocom.de>
8 months, 4 weeks
1
0
0
0
[L] Change in ...osmo-s1gw[master]: Introduce initial metrics support
by fixeria
fixeria has submitted this change. (
https://gerrit.osmocom.org/c/erlang/osmo-s1gw/+/37955?usp=email
) Change subject: Introduce initial metrics support ...................................................................... Introduce initial metrics support Metrics are implemented with the "exometer" library. A reference config to export the metrics through statsd is provided. Change-Id: I952e198238384dca4be94f91a01d7cfff0a1471f Related: SYS#7065 --- M config/sys.config A include/s1gw_metrics.hrl M rebar.config M rebar.lock M src/osmo_s1gw.app.src M src/osmo_s1gw_sup.erl M src/pfcp_peer.erl M src/s1ap_proxy.erl A src/s1gw_metrics.erl M src/sctp_proxy.erl M src/sctp_server.erl A test/exometer_mock.erl M test/s1ap_proxy_test.erl 13 files changed, 357 insertions(+), 8 deletions(-) Approvals: Jenkins Builder: Verified pespin: Looks good to me, approved diff --git a/config/sys.config b/config/sys.config index 45a14cb..d405db8 100644 --- a/config/sys.config +++ b/config/sys.config @@ -35,6 +35,54 @@ {prefix, [" ", prefix, " ::"], ""}, " ", msg, {mfa, [" (", mfa, ":", line, ")"], ""}, - reset, "\n"]}}}}]}]}]. + reset, "\n"]}}}}]} + ] + }, + {exometer_core, + [{predefined, + [%{[erlang, memory], {function, erlang, memory, [], value, []}, []}, + %{[erlang, system_info], {function, erlang, system_info, ['$dp'], value, [process_count]}, []}, + %{[erlang, statistics], {function, erlang, statistics, ['$dp'], value, [run_queue]}, []}, + %{[erlang, io], {function, erlang, statistics, [io], match, {{'_', input}, {'_', output}}}, []} + ] + }, + {report, + [{reporters, + [%%{exometer_report_tty, []}, + {exometer_report_statsd, + [{hostname, "127.0.4.10"}, + {port, 8125}, + {prefix, "s1gw"}, + {type_map, []} + ] + } + ] + }, + {subscribers, + [%%{select, {[{ {['_' | '_'],'_','_'}, [], ['$_']}], + %% exometer_report_tty, value, 1000, true}} + {select, {[{ {['_' | '_'],counter,'_'}, [], ['$_']}], + exometer_report_statsd, + value, + 1000, + true, + [{report_type, counter}] + } + }, + {select, {[{ {['_' | '_'],gauge,'_'}, [], ['$_']}], + exometer_report_statsd, + value, + 1000, + true, + [{report_type, gauge}] + } + } + ] + } + ] + } + ] + } +]. %% vim:set ts=2 sw=2 et: diff --git a/include/s1gw_metrics.hrl b/include/s1gw_metrics.hrl new file mode 100644 index 0000000..551c136 --- /dev/null +++ b/include/s1gw_metrics.hrl @@ -0,0 +1,32 @@ +-define(S1GW_CTR_PFCP_ASSOC_SETUP_REQ_TX, [ctr, pfcp, assoc_setup_req, tx]). +-define(S1GW_CTR_PFCP_ASSOC_SETUP_REQ_TIMEOUT, [ctr, pfcp, assoc_setup_req, timeout]). +-define(S1GW_CTR_PFCP_ASSOC_SETUP_RESP_RX, [ctr, pfcp, assoc_setup_resp, rx]). +-define(S1GW_CTR_PFCP_ASSOC_SETUP_RESP_RX_ACK, [ctr, pfcp, assoc_setup_resp, rx_ack]). +-define(S1GW_CTR_PFCP_ASSOC_SETUP_RESP_RX_NACK, [ctr, pfcp, assoc_setup_resp, rx_nack]). +-define(S1GW_CTR_S1AP_ENB_ALL_RX, [ctr, s1ap, enb, all, rx]). +-define(S1GW_CTR_S1AP_ENB_ALL_RX_UNKNOWN_ENB, [ctr, s1ap, enb, all, rx_unknown_enb]). +-define(S1GW_CTR_S1AP_PROXY_UPLINK_PACKETS_QUEUED, [ctr, s1ap, proxy, uplink_packets_queued]). +-define(S1GW_CTR_S1AP_PROXY_IN_PKT_ALL, [ctr, s1ap, proxy, in_pkt, all]). +-define(S1GW_CTR_S1AP_PROXY_IN_PKT_DECODE_ERROR, [ctr, s1ap, proxy, in_pkt, decode_error]). +-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_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]). +-define(S1GW_CTR_S1AP_PROXY_IN_PKT_ERAB_MOD_IND, [ctr, s1ap, proxy, in_pkt, erab_mod_ind]). +-define(S1GW_CTR_S1AP_PROXY_IN_PKT_INIT_CTX_REQ, [ctr, s1ap, proxy, in_pkt, init_ctx_req]). +-define(S1GW_CTR_S1AP_PROXY_IN_PKT_INIT_CTX_RSP, [ctr, s1ap, proxy, in_pkt, init_ctx_rsp]). +-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]). +-define(S1GW_CTR_S1AP_PROXY_OUT_PKT_REPLY_ALL, [ctr, s1ap, proxy, out_pkt, reply, all]). +-define(S1GW_CTR_S1AP_PROXY_OUT_PKT_REPLY_ERAB_SETUP_RSP, [ctr, s1ap, proxy, out_pkt, reply, erab_setup_rsp]). + +-define(S1GW_GAUGE_PFCP_ASSOCIATED, [gauge, pfcp, associated]). +-define(S1GW_GAUGE_S1AP_ENB_NUM_SCTP_CONNECTIONS, [gauge, s1ap, enb, num_sctp_connections]). +-define(S1GW_GAUGE_S1AP_PROXY_UPLINK_PACKETS_QUEUED, [gauge, s1ap, proxy, uplink_packets_queued]). + +%% NOTE: Remember to add new entries to s1gw_metric:init()! + +%% vim:set ts=4 sw=4 et: diff --git a/rebar.config b/rebar.config index 91bd759..ef3931d 100644 --- a/rebar.config +++ b/rebar.config @@ -8,7 +8,11 @@ {deps, [{logger_color_formatter, {git, "
https://github.com/rlipscombe/logger_color_formatter.git
", {tag, "0.5.0"}}}, {pfcplib, - {git, "
https://github.com/travelping/pfcplib.git
", {branch, "master"}}} + {git, "
https://github.com/travelping/pfcplib.git
", {branch, "master"}}}, + {exometer_core, + {git, "
https://github.com/Feuerlabs/exometer_core.git
", {branch, "master"}}}, + {exometer_report_statsd, + {git, "
https://github.com/esl/exometer_report_statsd.git
", {branch, "master"}}} ]}. %% test deps diff --git a/rebar.lock b/rebar.lock index 3b99c22..c52d677 100644 --- a/rebar.lock +++ b/rebar.lock @@ -1,16 +1,33 @@ {"1.2.0", [{<<"cut">>,{pkg,<<"cut">>,<<"1.0.3">>},1}, + {<<"exometer_core">>, + {git,"
https://github.com/Feuerlabs/exometer_core.git
", + {ref,"f9c7abc095edc893c9354a3d5f061715de1d9e79"}}, + 0}, + {<<"exometer_report_statsd">>, + {git,"
https://github.com/esl/exometer_report_statsd.git
", + {ref,"f1c369becb6e57871f1c7b0e491f6c3a302a65ee"}}, + 0}, + {<<"hut">>,{pkg,<<"hut">>,<<"1.3.0">>},1}, {<<"logger_color_formatter">>, {git,"
https://github.com/rlipscombe/logger_color_formatter.git
", {ref,"f1c96f979e6350f8cd787d27fe9ff003cbf3416b"}}, 0}, + {<<"parse_trans">>,{pkg,<<"parse_trans">>,<<"3.4.1">>},1}, {<<"pfcplib">>, {git,"
https://github.com/travelping/pfcplib.git
", {ref,"e505c0a4c05f5f14a2c40c7ebf36db62cc911d93"}}, - 0}]}. + 0}, + {<<"setup">>,{pkg,<<"setup">>,<<"2.1.0">>},1}]}. [ {pkg_hash,[ - {<<"cut">>, <<"1577F2F3BC0F2BF3B97903B7426F8A3D79523687B6A444D0F59A095EF69A0E81">>}]}, + {<<"cut">>, <<"1577F2F3BC0F2BF3B97903B7426F8A3D79523687B6A444D0F59A095EF69A0E81">>}, + {<<"hut">>, <<"71F2F054E657C03F959CF1ACC43F436EA87580696528CA2A55C8AFB1B06C85E7">>}, + {<<"parse_trans">>, <<"6E6AA8167CB44CC8F39441D05193BE6E6F4E7C2946CB2759F015F8C56B76E5FF">>}, + {<<"setup">>, <<"05F69185A5EB71474C9BC6BA892565651EC7507791F85632B7B914DBFE130510">>}]}, {pkg_hash_ext,[ - {<<"cut">>, <<"1A4A25DB2B7C5565FD28B314A4EEB898B1ED3CAFFA1AB09149345FB5731ED04B">>}]} + {<<"cut">>, <<"1A4A25DB2B7C5565FD28B314A4EEB898B1ED3CAFFA1AB09149345FB5731ED04B">>}, + {<<"hut">>, <<"7E15D28555D8A1F2B5A3A931EC120AF0753E4853A4C66053DB354F35BF9AB563">>}, + {<<"parse_trans">>, <<"620A406CE75DADA827B82E453C19CF06776BE266F5A67CFF34E1EF2CBB60E49A">>}, + {<<"setup">>, <<"EFD072578F0CF85BEA96CAAFFC7ADB0992398272522660A136E10567377071C5">>}]} ]. diff --git a/src/osmo_s1gw.app.src b/src/osmo_s1gw.app.src index 8bb89de..363d6d6 100644 --- a/src/osmo_s1gw.app.src +++ b/src/osmo_s1gw.app.src @@ -8,7 +8,9 @@ kernel, stdlib, logger_color_formatter, - pfcplib + pfcplib, + exometer_core, + exometer_report_statsd ]}, {modules, []}, {mod, {osmo_s1gw_app, []}}, diff --git a/src/osmo_s1gw_sup.erl b/src/osmo_s1gw_sup.erl index c6adb55..32272bf 100644 --- a/src/osmo_s1gw_sup.erl +++ b/src/osmo_s1gw_sup.erl @@ -81,6 +81,7 @@ worker, [pfcp_peer]}, + s1gw_metrics:init(), {ok, {{one_for_one, 5, 10}, [SctpServer, PfcpPeer]}}. diff --git a/src/pfcp_peer.erl b/src/pfcp_peer.erl index aa33e3a..d0da4bb 100644 --- a/src/pfcp_peer.erl +++ b/src/pfcp_peer.erl @@ -50,6 +50,7 @@ -include_lib("kernel/include/logger.hrl"). -include_lib("pfcplib/include/pfcp_packet.hrl"). +-include("s1gw_metrics.hrl"). %% 3GPP TS 29.244, section 4.2 "UDP Header and Port Numbers" -define(PFCP_PORT, 8805). @@ -136,6 +137,7 @@ init([LocAddr, RemAddr]) -> process_flag(trap_exit, true), + s1gw_metrics:gauge_set(?S1GW_GAUGE_PFCP_ASSOCIATED, 0), {ok, Sock} = gen_udp:open(?PFCP_PORT, [binary, {ip, LocAddr}, {reuseaddr, true}, @@ -158,6 +160,7 @@ connecting(enter, OldState, #peer_state{} = S0) -> ?LOG_INFO("State change: ~p -> ~p", [OldState, ?FUNCTION_NAME]), + s1gw_metrics:gauge_set(?S1GW_GAUGE_PFCP_ASSOCIATED, 0), %% Tx PFCP Association Setup {ok, S1} = send_assoc_setup(S0), {keep_state, S1, [{state_timeout, 2_000, assoc_setup_timeout}]}; @@ -166,6 +169,7 @@ connecting(state_timeout, assoc_setup_timeout, S) -> % Re-start sending PFCP Association Setup above: ?LOG_NOTICE("PFCP Association Setup timeout, UPF may be down, retrying..."), + s1gw_metrics:ctr_inc(?S1GW_CTR_PFCP_ASSOC_SETUP_REQ_TIMEOUT), {repeat_state, S}; %% Handle incoming PFCP PDU(s) @@ -177,11 +181,15 @@ ie = #{pfcp_cause := 'Request accepted', recovery_time_stamp := #recovery_time_stamp{time = RRTS}}} -> ?LOG_INFO("Rx Association Setup Response (Request accepted)"), + s1gw_metrics:ctr_inc(?S1GW_CTR_PFCP_ASSOC_SETUP_RESP_RX), + s1gw_metrics:ctr_inc(?S1GW_CTR_PFCP_ASSOC_SETUP_RESP_RX_ACK), {next_state, connected, S#peer_state{rem_rts = RRTS}}; #pfcp{type = association_setup_response, ie = #{pfcp_cause := Cause}} -> ?LOG_ERROR("Rx Association Setup Response (~p)", [Cause]), + s1gw_metrics:ctr_inc(?S1GW_CTR_PFCP_ASSOC_SETUP_RESP_RX), + s1gw_metrics:ctr_inc(?S1GW_CTR_PFCP_ASSOC_SETUP_RESP_RX_NACK), {stop, {shutdown, assoc_setup_nack}}; %% 3GPP TS 29.244, 6.2.2.2 Heartbeat Request %% A CP function or UP function shall be prepared to receive a Heartbeat Request @@ -201,6 +209,7 @@ %% CONNECTED state connected(enter, OldState, S) -> ?LOG_INFO("State change: ~p -> ~p", [OldState, ?FUNCTION_NAME]), + s1gw_metrics:gauge_set(?S1GW_GAUGE_PFCP_ASSOCIATED, 1), {keep_state, S}; connected({call, From}, @@ -272,7 +281,8 @@ ?LOG_NOTICE("Terminating in state ~p, reason ~p", [State, Reason]), case State of connected -> - send_assoc_release(S); + send_assoc_release(S), + s1gw_metrics:gauge_set(?S1GW_GAUGE_PFCP_ASSOCIATED, 0); _ -> nop end, @@ -395,6 +405,7 @@ send_assoc_setup(#peer_state{loc_rts = LRTS} = S) -> IEs = #{node_id => #node_id{id = get_node_id(S)}, recovery_time_stamp => #recovery_time_stamp{time = LRTS}}, + s1gw_metrics:ctr_inc(?S1GW_CTR_PFCP_ASSOC_SETUP_REQ_TX), send_pdu({association_setup_request, IEs}, S). diff --git a/src/s1ap_proxy.erl b/src/s1ap_proxy.erl index 4758484..68d0d0e 100644 --- a/src/s1ap_proxy.erl +++ b/src/s1ap_proxy.erl @@ -43,6 +43,8 @@ -include_lib("kernel/include/logger.hrl"). +-include("s1gw_metrics.hrl"). + -include("S1AP-PDU-Descriptions.hrl"). -include("S1AP-PDU-Contents.hrl"). -include("S1AP-Containers.hrl"). @@ -90,6 +92,7 @@ %% Process an S1AP PDU -spec process_pdu(binary(), proxy_state()) -> {{proxy_action(), binary()}, proxy_state()}. process_pdu(OrigData, S0) -> + s1gw_metrics:ctr_inc(?S1GW_CTR_S1AP_PROXY_IN_PKT_ALL), case decode_pdu(OrigData) of {ok, PDU} -> ?LOG_DEBUG("Rx S1AP PDU: ~p", [PDU]), @@ -97,13 +100,24 @@ {{Action, NewPDU}, S1} -> {ok, NewData} = encode_pdu(NewPDU), ?LOG_DEBUG("Tx (~p) S1AP PDU: ~p", [Action, NewPDU]), + case Action of + forward -> + s1gw_metrics:ctr_inc(?S1GW_CTR_S1AP_PROXY_OUT_PKT_FWD_ALL), + s1gw_metrics:ctr_inc(?S1GW_CTR_S1AP_PROXY_OUT_PKT_FWD_PROC); + reply -> + s1gw_metrics:ctr_inc(?S1GW_CTR_S1AP_PROXY_OUT_PKT_REPLY_ALL) + end, {{Action, NewData}, S1}; {forward, S1} -> ?LOG_DEBUG("Tx (forward) S1AP PDU unmodified"), + s1gw_metrics:ctr_inc(?S1GW_CTR_S1AP_PROXY_OUT_PKT_FWD_ALL), + s1gw_metrics:ctr_inc(?S1GW_CTR_S1AP_PROXY_OUT_PKT_FWD_UNMODIFIED), {{forward, OrigData}, S1} end; {error, {asn1, Error}} -> ?LOG_ERROR("S1AP PDU decoding failed: ~p", [Error]), + s1gw_metrics:ctr_inc(?S1GW_CTR_S1AP_PROXY_IN_PKT_DECODE_ERROR), + s1gw_metrics:ctr_inc(?S1GW_CTR_S1AP_PROXY_OUT_PKT_FWD_UNMODIFIED), {{forward, OrigData}, S0} %% XXX: forward as-is or drop? end. @@ -148,6 +162,7 @@ #'InitiatingMessage'{procedureCode = ?'id-E-RABSetup', value = C0} = Msg}, S0) -> ?LOG_DEBUG("Processing E-RAB SETUP REQUEST"), + s1gw_metrics:ctr_inc(?S1GW_CTR_S1AP_PROXY_IN_PKT_ERAB_SETUP_REQ), case handle_ies(C0#'E-RABSetupRequest'.protocolIEs, ?'id-E-RABToBeSetupListBearerSUReq', S0) of {{ok, IEs}, S1} -> @@ -156,7 +171,9 @@ {{forward, PDU}, S1}; %% forward patched PDU {{error, Reason}, S1} -> ?LOG_NOTICE("Failed to process E-RAB SETUP REQUEST: ~p", [Reason]), + s1gw_metrics:ctr_inc(?S1GW_CTR_S1AP_PROXY_IN_PKT_PROC_ERROR), PDU = build_erab_setup_response_failure(S1), + s1gw_metrics:ctr_inc(?S1GW_CTR_S1AP_PROXY_OUT_PKT_REPLY_ERAB_SETUP_RSP), {{reply, PDU}, S1} %% reply PDU back to sender end; @@ -165,6 +182,7 @@ #'SuccessfulOutcome'{procedureCode = ?'id-E-RABSetup', value = C0} = Msg}, S0) -> ?LOG_DEBUG("Processing E-RAB SETUP RESPONSE"), + s1gw_metrics:ctr_inc(?S1GW_CTR_S1AP_PROXY_IN_PKT_ERAB_SETUP_RSP), case handle_ies(C0#'E-RABSetupResponse'.protocolIEs, ?'id-E-RABSetupListBearerSURes', S0) of {{ok, IEs}, S1} -> @@ -173,6 +191,7 @@ {{forward, PDU}, S1}; %% forward patched PDU {{error, Reason}, S1} -> ?LOG_NOTICE("Failed to process E-RAB SETUP RESPONSE: ~p", [Reason]), + s1gw_metrics:ctr_inc(?S1GW_CTR_S1AP_PROXY_IN_PKT_PROC_ERROR), {forward, S1} %% XXX: forward as-is or drop? end; @@ -183,6 +202,7 @@ #'InitiatingMessage'{procedureCode = ?'id-E-RABRelease', value = C0} = Msg}, S0) -> ?LOG_DEBUG("Processing E-RAB RELEASE COMMAND"), + s1gw_metrics:ctr_inc(?S1GW_CTR_S1AP_PROXY_IN_PKT_ERAB_RELEASE_CMD), case handle_ies(C0#'E-RABReleaseCommand'.protocolIEs, ?'id-E-RABToBeReleasedList', S0) of {{ok, IEs}, S1} -> @@ -191,6 +211,7 @@ {{forward, PDU}, S1}; %% forward patched PDU {{error, Reason}, S1} -> ?LOG_NOTICE("Failed to process E-RAB RELEASE COMMAND: ~p", [Reason]), + s1gw_metrics:ctr_inc(?S1GW_CTR_S1AP_PROXY_IN_PKT_PROC_ERROR), {forward, S1} %% XXX: forward as-is or drop? end; @@ -199,6 +220,7 @@ #'SuccessfulOutcome'{procedureCode = ?'id-E-RABRelease', value = C0} = Msg}, S0) -> ?LOG_DEBUG("Processing E-RAB RELEASE RESPONSE"), + s1gw_metrics:ctr_inc(?S1GW_CTR_S1AP_PROXY_IN_PKT_ERAB_RELEASE_RSP), case handle_ies(C0#'E-RABReleaseResponse'.protocolIEs, ?'id-E-RABReleaseListBearerRelComp', S0) of {{ok, IEs}, S1} -> @@ -207,6 +229,7 @@ {{forward, PDU}, S1}; %% forward patched PDU {{error, Reason}, S1} -> ?LOG_NOTICE("Failed to process E-RAB RELEASE RESPONSE: ~p", [Reason]), + s1gw_metrics:ctr_inc(?S1GW_CTR_S1AP_PROXY_IN_PKT_PROC_ERROR), {forward, S1} %% XXX: forward as-is or drop? end; @@ -215,6 +238,7 @@ #'InitiatingMessage'{procedureCode = ?'id-E-RABReleaseIndication', value = C0} = Msg}, S0) -> ?LOG_DEBUG("Processing E-RAB RELEASE INDICATION"), + s1gw_metrics:ctr_inc(?S1GW_CTR_S1AP_PROXY_IN_PKT_ERAB_RELEASE_IND), case handle_ies(C0#'E-RABReleaseIndication'.protocolIEs, ?'id-E-RABReleasedList', S0) of {{ok, IEs}, S1} -> @@ -223,6 +247,7 @@ {{forward, PDU}, S1}; %% forward patched PDU {{error, Reason}, S1} -> ?LOG_NOTICE("Failed to process E-RAB RELEASE INDICATION: ~p", [Reason]), + s1gw_metrics:ctr_inc(?S1GW_CTR_S1AP_PROXY_IN_PKT_PROC_ERROR), {forward, S1} %% XXX: forward as-is or drop? end; @@ -231,6 +256,7 @@ #'InitiatingMessage'{procedureCode = ?'id-E-RABModificationIndication', value = C0} = Msg}, S0) -> ?LOG_DEBUG("Processing E-RAB MODIFICATION INDICATION"), + s1gw_metrics:ctr_inc(?S1GW_CTR_S1AP_PROXY_IN_PKT_ERAB_MOD_IND), IEs0 = C0#'E-RABModificationIndication'.protocolIEs, %% E-RAB to be Modified List %% TODO: handle {error, Reason} @@ -247,6 +273,7 @@ #'InitiatingMessage'{procedureCode = ?'id-InitialContextSetup', value = C0} = Msg}, S0) -> ?LOG_DEBUG("Processing INITIAL CONTEXT SETUP REQUEST"), + s1gw_metrics:ctr_inc(?S1GW_CTR_S1AP_PROXY_IN_PKT_INIT_CTX_REQ), case handle_ies(C0#'InitialContextSetupRequest'.protocolIEs, ?'id-E-RABToBeSetupListCtxtSUReq', S0) of {{ok, IEs}, S1} -> @@ -255,6 +282,7 @@ {{forward, PDU}, S1}; %% forward patched PDU {{error, Reason}, S1} -> ?LOG_NOTICE("Failed to process INITIAL CONTEXT SETUP REQUEST: ~p", [Reason]), + s1gw_metrics:ctr_inc(?S1GW_CTR_S1AP_PROXY_IN_PKT_PROC_ERROR), {forward, S1} %% XXX: forward as-is or drop? end; @@ -263,6 +291,7 @@ #'SuccessfulOutcome'{procedureCode = ?'id-InitialContextSetup', value = C0} = Msg}, S0) -> ?LOG_DEBUG("Processing INITIAL CONTEXT SETUP RESPONSE"), + s1gw_metrics:ctr_inc(?S1GW_CTR_S1AP_PROXY_IN_PKT_INIT_CTX_RSP), case handle_ies(C0#'InitialContextSetupResponse'.protocolIEs, ?'id-E-RABSetupListCtxtSURes', S0) of {{ok, IEs}, S1} -> @@ -271,6 +300,7 @@ {{forward, PDU}, S1}; %% forward patched PDU {{error, Reason}, S1} -> ?LOG_NOTICE("Failed to process INITIAL CONTEXT SETUP RESPONSE: ~p", [Reason]), + s1gw_metrics:ctr_inc(?S1GW_CTR_S1AP_PROXY_IN_PKT_PROC_ERROR), {forward, S1} %% XXX: forward as-is or drop? end; diff --git a/src/s1gw_metrics.erl b/src/s1gw_metrics.erl new file mode 100644 index 0000000..6b078e5 --- /dev/null +++ b/src/s1gw_metrics.erl @@ -0,0 +1,168 @@ +%% Copyright (C) 2024 by sysmocom - s.f.m.c. GmbH <info(a)sysmocom.de> +%% Author: Pau Espin Pedrol <pespin(a)sysmocom.de> +%% +%% All Rights Reserved +%% +%% SPDX-License-Identifier: AGPL-3.0-or-later +%% +%% This program is free software; you can redistribute it and/or modify +%% it under the terms of the GNU Affero General Public License as +%% published by the Free Software Foundation; either version 3 of the +%% License, or (at your option) any later version. +%% +%% This program is distributed in the hope that it will be useful, +%% but WITHOUT ANY WARRANTY; without even the implied warranty of +%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +%% GNU General Public License for more details. +%% +%% You should have received a copy of the GNU Affero General Public License +%% along with this program. If not, see <
https://www.gnu.org/licenses/
>. +%% +%% Additional Permission under GNU AGPL version 3 section 7: +%% +%% If you modify this Program, or any covered work, by linking or +%% combining it with runtime libraries of Erlang/OTP as released by +%% Ericsson on
https://www.erlang.org
(or a modified version of these +%% libraries), containing parts covered by the terms of the Erlang Public +%% License (
https://www.erlang.org/EPLICENSE
), the licensors of this +%% Program grant you additional permission to convey the resulting work +%% without the need to license the runtime libraries of Erlang/OTP under +%% the GNU Affero General Public License. Corresponding Source for a +%% non-source form of such a combination shall include the source code +%% for the parts of the runtime libraries of Erlang/OTP used as well as +%% that of the covered work. + +-module(s1gw_metrics). + +-export([init/0, + ctr_reset/1, + ctr_inc/1, + ctr_inc/2, + gauge_reset/1, + gauge_set/2, + gauge_inc/1, + gauge_inc/2, + gauge_dec/1]). + +-include_lib("kernel/include/logger.hrl"). +-include("s1gw_metrics.hrl"). + +-define(S1GW_COUNTERS, [ + ?S1GW_CTR_PFCP_ASSOC_SETUP_REQ_TX, + ?S1GW_CTR_PFCP_ASSOC_SETUP_REQ_TIMEOUT, + ?S1GW_CTR_PFCP_ASSOC_SETUP_RESP_RX, + ?S1GW_CTR_PFCP_ASSOC_SETUP_RESP_RX_ACK, + ?S1GW_CTR_PFCP_ASSOC_SETUP_RESP_RX_NACK, + ?S1GW_CTR_S1AP_ENB_ALL_RX, + ?S1GW_CTR_S1AP_ENB_ALL_RX_UNKNOWN_ENB, + ?S1GW_CTR_S1AP_PROXY_UPLINK_PACKETS_QUEUED, + %% s1ap_proxy: INcoming PDU counters + ?S1GW_CTR_S1AP_PROXY_IN_PKT_ALL, %% received total + ?S1GW_CTR_S1AP_PROXY_IN_PKT_DECODE_ERROR, %% failed to decode + ?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_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 + ?S1GW_CTR_S1AP_PROXY_IN_PKT_ERAB_MOD_IND, %% E-RAB MODIFY.ind PDUs + ?S1GW_CTR_S1AP_PROXY_IN_PKT_INIT_CTX_REQ, %% INITIAL CONTEXT SETUP.req PDUs + ?S1GW_CTR_S1AP_PROXY_IN_PKT_INIT_CTX_RSP, %% INITIAL CONTEXT SETUP.rsp 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 + ?S1GW_CTR_S1AP_PROXY_OUT_PKT_FWD_UNMODIFIED, %% forwarded: unmodified + ?S1GW_CTR_S1AP_PROXY_OUT_PKT_REPLY_ALL, %% replied: total + ?S1GW_CTR_S1AP_PROXY_OUT_PKT_REPLY_ERAB_SETUP_RSP %% replied: E-RAB SETUP.rsp +]). + +-define(S1GW_GAUGES, [ + ?S1GW_GAUGE_PFCP_ASSOCIATED, + ?S1GW_GAUGE_S1AP_ENB_NUM_SCTP_CONNECTIONS, + ?S1GW_GAUGE_S1AP_PROXY_UPLINK_PACKETS_QUEUED +]). + +-spec new_ctr(list()) -> ok. +new_ctr(Name) -> + %%?LOG_INFO("New counter ~p", [Name]), + ok = exometer:new(Name, counter). + +-spec new_ctrs(list()) -> ok. +new_ctrs([]) -> + ok; +new_ctrs([Name | MoreNames]) -> + new_ctr(Name), + new_ctrs(MoreNames). + +-spec new_gauge(list()) -> ok. +new_gauge(Name) -> + %%?LOG_INFO("New gauge ~p", [Name]), + ok = exometer:new(Name, gauge). + +-spec new_gauges(list()) -> ok. +new_gauges([]) -> + ok; +new_gauges([Name | MoreNames]) -> + new_gauge(Name), + new_gauges(MoreNames). + +-spec get_current_value(list()) -> integer(). +get_current_value(Name) -> + Result = exometer:get_value(Name, value), + {ok, [{value, PrevVal}]} = Result, + PrevVal. + +%% ------------------------------------------------------------------ +%% public API +%% ------------------------------------------------------------------ + +init() -> + ?LOG_INFO("Initiating metrics"), + new_ctrs(?S1GW_COUNTERS), + new_gauges(?S1GW_GAUGES). + +%%%%%%%%%%%%% +%% CTR APIs +%%%%%%%%%%%%% +-spec ctr_reset(list()) -> ok | {error, any()}. +ctr_reset(Name) -> + ?LOG_DEBUG("ctr_reset(~p)", [Name]), + exometer:reset(Name). + +-spec ctr_inc(list(), integer()) -> ok | {error, any()}. +ctr_inc(Name, Value) -> + ?LOG_DEBUG("ctr_inc(~p, ~p)", [Name, Value]), + exometer:update(Name, Value). + +-spec ctr_inc(list()) -> ok | {error, any()}. +ctr_inc(Name) -> + ctr_inc(Name, 1). + +%%%%%%%%%%%%% +%% GAUGE APIs +%%%%%%%%%%%%% +-spec gauge_reset(list()) -> ok | {error, any()}. +gauge_reset(Name) -> + ?LOG_DEBUG("gauge_reset(~p)", [Name]), + exometer:reset(Name). + +-spec gauge_set(list(), integer()) -> ok | {error, any()}. +gauge_set(Name, Value) -> + exometer:update(Name, Value). + +-spec gauge_inc(list(), integer()) -> ok | {error, any()}. +gauge_inc(Name, Value) -> + PrevVal = get_current_value(Name), + ?LOG_DEBUG("gauge_inc(~p, ~p): pre_val=~p", [Name, Value, PrevVal]), + exometer:update(Name, Value + PrevVal). + +-spec gauge_inc(list()) -> ok | {error, any()}. +gauge_inc(Name) -> + gauge_inc(Name, 1). + +-spec gauge_dec(list()) -> ok | {error, any()}. +gauge_dec(Name) -> + gauge_inc(Name, -1). + + +%% vim:set ts=4 sw=4 et: diff --git a/src/sctp_proxy.erl b/src/sctp_proxy.erl index b37bead..280e408 100644 --- a/src/sctp_proxy.erl +++ b/src/sctp_proxy.erl @@ -49,6 +49,8 @@ -include_lib("kernel/include/inet.hrl"). -include_lib("kernel/include/inet_sctp.hrl"). +-include("s1gw_metrics.hrl"). + %% ------------------------------------------------------------------ %% public API %% ------------------------------------------------------------------ @@ -104,6 +106,8 @@ %% Handle an eNB -> MME data forwarding request (queue) connecting(cast, {send_data, Data}, #{tx_queue := Pending} = S) -> + s1gw_metrics:ctr_inc(?S1GW_CTR_S1AP_PROXY_UPLINK_PACKETS_QUEUED), + s1gw_metrics:gauge_inc(?S1GW_GAUGE_S1AP_PROXY_UPLINK_PACKETS_QUEUED), {keep_state, S#{tx_queue := [Data | Pending]}}; %% Handle an #sctp_assoc_change event (connection state) @@ -254,6 +258,7 @@ sctp_send_pending([Data | Pending], S0) -> S1 = sctp_send(Data, S0), + s1gw_metrics:gauge_dec(?S1GW_CTR_S1AP_PROXY_UPLINK_PACKETS_QUEUED), sctp_send_pending(Pending, S1); sctp_send_pending([], S) -> diff --git a/src/sctp_server.erl b/src/sctp_server.erl index 8ea311f..58d91ca 100644 --- a/src/sctp_server.erl +++ b/src/sctp_server.erl @@ -48,6 +48,7 @@ -include_lib("kernel/include/inet.hrl"). -include_lib("kernel/include/inet_sctp.hrl"). +-include("s1gw_metrics.hrl"). -include("s1ap.hrl"). -record(server_state, {sock, clients, mme_addr_port}). @@ -170,12 +171,14 @@ sctp_recv(State, {FromAddr, FromPort, [#sctp_sndrcvinfo{assoc_id = Aid}], Data}) -> ?LOG_DEBUG("eNB connection (id=~p, ~p:~p) -> MME: ~p", [Aid, FromAddr, FromPort, Data]), + s1gw_metrics:ctr_inc(?S1GW_CTR_S1AP_ENB_ALL_RX), case dict:find(Aid, State#server_state.clients) of {ok, #client_state{pid = Pid}} -> sctp_proxy:send_data(Pid, Data); error -> ?LOG_ERROR("eNB connection (id=~p, ~p:~p) is not known to us?!?", - [Aid, FromAddr, FromPort]) + [Aid, FromAddr, FromPort]), + s1gw_metrics:ctr_inc(?S1GW_CTR_S1AP_ENB_ALL_RX_UNKNOWN_ENB) end, State; @@ -190,6 +193,7 @@ client_add(Clients, Aid, FromAddr, FromPort, {MmeAddr, MmePort}) -> {ok, Pid} = sctp_proxy:start_link(Aid, MmeAddr, MmePort), NewClient = #client_state{addr_port = {FromAddr, FromPort}, pid = Pid}, + s1gw_metrics:gauge_inc(?S1GW_GAUGE_S1AP_ENB_NUM_SCTP_CONNECTIONS), dict:store(Aid, NewClient, Clients). @@ -200,6 +204,7 @@ %% the proxy process might be already dead, so we guard %% against exceptions like noproc or {nodedown,Node}. catch sctp_proxy:shutdown(Client#client_state.pid), + s1gw_metrics:gauge_dec(?S1GW_GAUGE_S1AP_ENB_NUM_SCTP_CONNECTIONS), dict:erase(Aid, Clients); error -> Clients diff --git a/test/exometer_mock.erl b/test/exometer_mock.erl new file mode 100644 index 0000000..5a09692 --- /dev/null +++ b/test/exometer_mock.erl @@ -0,0 +1,24 @@ +-module(exometer_mock). + +-export([mock_all/0, + unmock_all/0]). + + +%% ------------------------------------------------------------------ +%% public API +%% ------------------------------------------------------------------ + +%% mock all pfcp_peer module functions +mock_all() -> + meck:new(exometer), + meck:expect(exometer, new, fun(_Name, _Type) -> ok end), + meck:expect(exometer, reset, fun(_Name) -> ok end), + meck:expect(exometer, update, fun(_Name, _Value) -> ok end), + meck:expect(exometer, get_value, fun(_Name, DataPoint) -> {ok,[{DataPoint,0}]} end). + +%% unmock all pfcp_peer module functions +unmock_all() -> + true = meck:validate(exometer), + meck:unload(exometer). + +%% vim:set ts=4 sw=4 et: diff --git a/test/s1ap_proxy_test.erl b/test/s1ap_proxy_test.erl index 04d52df..28fe209 100644 --- a/test/s1ap_proxy_test.erl +++ b/test/s1ap_proxy_test.erl @@ -15,10 +15,12 @@ start() -> pfcp_mock:mock_all(), + exometer_mock:mock_all(), s1ap_proxy:init(). stop(S) -> + exometer_mock:unmock_all(), pfcp_mock:unmock_all(), s1ap_proxy:deinit(S). -- To view, visit
https://gerrit.osmocom.org/c/erlang/osmo-s1gw/+/37955?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: I952e198238384dca4be94f91a01d7cfff0a1471f Gerrit-Change-Number: 37955 Gerrit-PatchSet: 8 Gerrit-Owner: pespin <pespin(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>
8 months, 4 weeks
1
0
0
0
[S] Change in ...osmo-s1gw[master]: s1ap_proxy: move sctp_proxy:handle_pdu() to process_pdu_safe()
by pespin
Attention is currently required from: fixeria. pespin has posted comments on this change by fixeria. (
https://gerrit.osmocom.org/c/erlang/osmo-s1gw/+/38298?usp=email
) Change subject: s1ap_proxy: move sctp_proxy:handle_pdu() to process_pdu_safe() ...................................................................... Patch Set 6: Code-Review+2 -- To view, visit
https://gerrit.osmocom.org/c/erlang/osmo-s1gw/+/38298?usp=email
To unsubscribe, or for help writing mail filters, visit
https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: comment Gerrit-Project: erlang/osmo-s1gw Gerrit-Branch: master Gerrit-Change-Id: I16d4cf279a930d35ca179bd9b49234d10180e5c5 Gerrit-Change-Number: 38298 Gerrit-PatchSet: 6 Gerrit-Owner: fixeria <vyanitskiy(a)sysmocom.de> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: pespin <pespin(a)sysmocom.de> Gerrit-Attention: fixeria <vyanitskiy(a)sysmocom.de> Gerrit-Comment-Date: Fri, 27 Sep 2024 22:57:42 +0000 Gerrit-HasComments: No Gerrit-Has-Labels: Yes
8 months, 4 weeks
1
0
0
0
[L] Change in ...osmo-s1gw[master]: Introduce initial metrics support
by pespin
Attention is currently required from: fixeria, laforge. pespin has posted comments on this change by pespin. (
https://gerrit.osmocom.org/c/erlang/osmo-s1gw/+/37955?usp=email
) Change subject: Introduce initial metrics support ...................................................................... Patch Set 8: Code-Review+2 -- To view, visit
https://gerrit.osmocom.org/c/erlang/osmo-s1gw/+/37955?usp=email
To unsubscribe, or for help writing mail filters, visit
https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: comment Gerrit-Project: erlang/osmo-s1gw Gerrit-Branch: master Gerrit-Change-Id: I952e198238384dca4be94f91a01d7cfff0a1471f Gerrit-Change-Number: 37955 Gerrit-PatchSet: 8 Gerrit-Owner: pespin <pespin(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> Gerrit-Attention: laforge <laforge(a)osmocom.org> Gerrit-Attention: fixeria <vyanitskiy(a)sysmocom.de> Gerrit-Comment-Date: Fri, 27 Sep 2024 22:57:10 +0000 Gerrit-HasComments: No Gerrit-Has-Labels: Yes
8 months, 4 weeks
1
0
0
0
[M] Change in ...osmo-s1gw[master]: s1ap_proxy: handle E-RAB RELEASE INDICATION
by pespin
Attention is currently required from: fixeria, laforge. pespin has posted comments on this change by fixeria. (
https://gerrit.osmocom.org/c/erlang/osmo-s1gw/+/38241?usp=email
) Change subject: s1ap_proxy: handle E-RAB RELEASE INDICATION ...................................................................... Patch Set 5: Code-Review+2 -- To view, visit
https://gerrit.osmocom.org/c/erlang/osmo-s1gw/+/38241?usp=email
To unsubscribe, or for help writing mail filters, visit
https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: comment Gerrit-Project: erlang/osmo-s1gw Gerrit-Branch: master Gerrit-Change-Id: I13584620e28edf529325dc661c4b40d09acacc3f Gerrit-Change-Number: 38241 Gerrit-PatchSet: 5 Gerrit-Owner: fixeria <vyanitskiy(a)sysmocom.de> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: laforge <laforge(a)osmocom.org> Gerrit-Reviewer: pespin <pespin(a)sysmocom.de> Gerrit-Attention: laforge <laforge(a)osmocom.org> Gerrit-Attention: fixeria <vyanitskiy(a)sysmocom.de> Gerrit-Comment-Date: Fri, 27 Sep 2024 22:56:35 +0000 Gerrit-HasComments: No Gerrit-Has-Labels: Yes
8 months, 4 weeks
1
0
0
0
[L] Change in ...osmo-s1gw[master]: s1ap_proxy: Support replying errors
by pespin
Attention is currently required from: fixeria, laforge, lynxis lazus. pespin has posted comments on this change by pespin. (
https://gerrit.osmocom.org/c/erlang/osmo-s1gw/+/37924?usp=email
) Change subject: s1ap_proxy: Support replying errors ...................................................................... Patch Set 7: Code-Review+2 -- To view, visit
https://gerrit.osmocom.org/c/erlang/osmo-s1gw/+/37924?usp=email
To unsubscribe, or for help writing mail filters, visit
https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: comment Gerrit-Project: erlang/osmo-s1gw Gerrit-Branch: master Gerrit-Change-Id: I242e84fb09b00f4794b6e1aa770f348a0e60aea4 Gerrit-Change-Number: 37924 Gerrit-PatchSet: 7 Gerrit-Owner: pespin <pespin(a)sysmocom.de> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: fixeria <vyanitskiy(a)sysmocom.de> Gerrit-Reviewer: laforge <laforge(a)osmocom.org> Gerrit-Reviewer: lynxis lazus <lynxis(a)fe80.eu> Gerrit-Reviewer: pespin <pespin(a)sysmocom.de> Gerrit-Attention: laforge <laforge(a)osmocom.org> Gerrit-Attention: fixeria <vyanitskiy(a)sysmocom.de> Gerrit-Attention: lynxis lazus <lynxis(a)fe80.eu> Gerrit-Comment-Date: Fri, 27 Sep 2024 22:55:47 +0000 Gerrit-HasComments: No Gerrit-Has-Labels: Yes
8 months, 4 weeks
1
0
0
0
[M] Change in libosmo-abis[master]: libosmotrau: add CSD RA2 functions
by pespin
Attention is currently required from: dexter, falconia, fixeria, laforge. pespin has posted comments on this change by falconia. (
https://gerrit.osmocom.org/c/libosmo-abis/+/38290?usp=email
) Change subject: libosmotrau: add CSD RA2 functions ...................................................................... Patch Set 3: Code-Review+2 -- To view, visit
https://gerrit.osmocom.org/c/libosmo-abis/+/38290?usp=email
To unsubscribe, or for help writing mail filters, visit
https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: comment Gerrit-Project: libosmo-abis Gerrit-Branch: master Gerrit-Change-Id: I7b98b958651b3fc1a814d119d1b8644c91f98676 Gerrit-Change-Number: 38290 Gerrit-PatchSet: 3 Gerrit-Owner: falconia <falcon(a)freecalypso.org> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: dexter <pmaier(a)sysmocom.de> Gerrit-Reviewer: fixeria <vyanitskiy(a)sysmocom.de> Gerrit-Reviewer: laforge <laforge(a)osmocom.org> Gerrit-Reviewer: pespin <pespin(a)sysmocom.de> Gerrit-Attention: falconia <falcon(a)freecalypso.org> Gerrit-Attention: laforge <laforge(a)osmocom.org> Gerrit-Attention: fixeria <vyanitskiy(a)sysmocom.de> Gerrit-Attention: dexter <pmaier(a)sysmocom.de> Gerrit-Comment-Date: Fri, 27 Sep 2024 22:55:07 +0000 Gerrit-HasComments: No Gerrit-Has-Labels: Yes
8 months, 4 weeks
1
0
0
0
[L] Change in ...osmo-s1gw[master]: Introduce initial metrics support
by fixeria
Attention is currently required from: laforge, pespin. fixeria has posted comments on this change by pespin. (
https://gerrit.osmocom.org/c/erlang/osmo-s1gw/+/37955?usp=email
) Change subject: Introduce initial metrics support ...................................................................... Patch Set 8: (1 comment) File rebar.config:
https://gerrit.osmocom.org/c/erlang/osmo-s1gw/+/37955/comment/3d86f997_3ebb…
: PS6, Line 13:
https://github.com/osmocom/exometer_core.git
> TODO:
https://github
. […] Done -- To view, visit
https://gerrit.osmocom.org/c/erlang/osmo-s1gw/+/37955?usp=email
To unsubscribe, or for help writing mail filters, visit
https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: comment Gerrit-Project: erlang/osmo-s1gw Gerrit-Branch: master Gerrit-Change-Id: I952e198238384dca4be94f91a01d7cfff0a1471f Gerrit-Change-Number: 37955 Gerrit-PatchSet: 8 Gerrit-Owner: pespin <pespin(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> Gerrit-Attention: laforge <laforge(a)osmocom.org> Gerrit-Attention: pespin <pespin(a)sysmocom.de> Gerrit-Comment-Date: Fri, 27 Sep 2024 22:12:38 +0000 Gerrit-HasComments: Yes Gerrit-Has-Labels: No Comment-In-Reply-To: fixeria <vyanitskiy(a)sysmocom.de>
8 months, 4 weeks
1
0
0
0
← Newer
1
...
6
7
8
9
10
11
12
...
199
Older →
Jump to page:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
Results per page:
10
25
50
100
200