1%% -*- erlang-indent-level: 2 -*- 2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3%% 4%% Among testing other things, this module shows why performing LCM on 5%% SPARC is currently problematic. SPARC does not mark untagged values 6%% as dead when they are live over function calls which in turn causes 7%% them to be traced by the garbage collector leading to crashes. 8%% 9%% A simple way to get this behaviour is to compile just the function 10%% 11%% {bsextract,tid_internal_storage,2} 12%% 13%% with the compiler option "rtl_lcm" on and without. 14%% 15%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 16 17-module(bs_extract). 18 19-export([test/0]). 20 21-include("bs_decode_extract.hrl"). 22 23-define(PDU, <<30,16,0,90,0,1,0,0,255,255,255,255,81,67,101,7,0,0,0,96, 24 6,12,146,18,14,0,15,252,16,0,0,17,0,0,128,0,2,241,33,131, 25 0,20,7,97,112,110,48,49,51,97,8,101,114,105,99,115,115, 26 111,110,2,115,101,132,0,20,128,192,35,16,1,5,0,16,5,117, 27 115,101,114,53,5,112,97,115,115,53,133,0,4,172,28,12,1, 28 133,0,4,172,28,12,3,134,0,8,145,148,113,129,0,0,0,0>>). 29 30-define(RES, {ok, {mvsgT_imsi, <<81,67,101,7,0,0,0,240>>}}). 31 32test() -> 33 ?RES = extract_v0_opt(1000, ?PDU), 34 ok. 35 36extract_v0_opt(0, Pdu) -> 37 get_external_id(Pdu); 38extract_v0_opt(N, Pdu) -> 39 {ok,_} = get_external_id(Pdu), 40 extract_v0_opt(N-1, Pdu). 41 42get_external_id(<<0:3,_:4,0:1,1:8,_Length:16,SequenceNumber:16, 43 _FlowLabel:16,_SNDCP_N_PDU_Number:8,_:3/binary-unit:8, 44 _TID:8/binary-unit:8,_InformationElements/binary>>) -> 45 {echo,#sesT_echoReqV0{},SequenceNumber}; 46%% Create PDP Context Request 47%% GTP97, SNN=0 48%% (No SNDCP N-PDU number) 49get_external_id(<<0:3,_:4,0:1,16:8,_Length:16,_SequenceNumber:16, 50 _FlowLabel:16,_SNDCP_N_PDU_Number:8,_:3/binary-unit:8, 51 TID:8/binary-unit:8,_InformationElements/binary>>) -> 52 {ok,_IMSI} = extract_imsi(TID); 53%%% Update PDP Context Request 54%%% GTP97, SNN=0 55%%% (No SNDCP N-PDU number) 56get_external_id(<<0:3,_:4,0:1,18:8,_Length:16,_SequenceNumber:16, 57 _FlowLabel:16,_SNDCP_N_PDU_Number:8,_:3/binary-unit:8, 58 TID:8/binary-unit:8,_InformationElements/binary>>) -> 59 {ok,_IMSI} = extract_imsi(TID); 60%%% Delete PDP Context Request 61%%% GTP97, SNN=0 62%%% (No SNDCP N-PDU number) 63get_external_id(<<0:3,_:4,0:1,20:8,_Length:16,_SequenceNumber:16, 64 _FlowLabel:16,_SNDCP_N_PDU_Number:8,_:3/binary-unit:8, 65 TID:8/binary-unit:8,_InformationElements/binary>>) -> 66 {ok,_IMSI} = extract_imsi(TID); 67%%% Error handling: GTP Message Too Short 68%%% Error handling: Unknown GTP Signalling message. 69%%% Error handling: Unexpected GTP Signalling message. 70get_external_id(_GTP_Message) -> 71 fault. 72 73%% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 74%% extract_imsi/1 75%% Get the IMSI element from TID 76extract_imsi(TID) -> 77 {ok,#mvsgT_tid{imsi=IMSI}} = tid_internal_storage(TID,[]), 78 {ok,IMSI}. 79 80%%% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 81%%% tid_internal_storage/3 82%%% Convert TID binary to internal datatype 83tid_internal_storage(Bin,_) -> 84 Size = byte_size(Bin) - 1, 85 <<Front:Size/binary,NSAPI:4,DigitN:4>> = Bin, 86 Result = 87 case DigitN of 88 2#1111 -> 89 #mvsgT_tid{imsi = #mvsgT_imsi{value=Front}, nsapi = NSAPI}; 90 _ -> 91 Value = <<Front/binary,2#1111:4,DigitN:4>>, 92 #mvsgT_tid{imsi = #mvsgT_imsi{value = Value}, nsapi = NSAPI} 93 end, 94 {ok,Result}. 95