complete SCCP routing code
we now use ss7_links in order to determine which point codes are local or not, and we use the routing table to determine the signalling link. local-out routing form N-UNITDATA.req to the actual MTP3 on the correct signalling link is now working.
This commit is contained in:
parent
8880b7e585
commit
ab61a4ec38
|
@ -24,17 +24,10 @@
|
|||
-include_lib("osmo_ss7/include/sccp.hrl").
|
||||
-include_lib("osmo_ss7/include/mtp3.hrl").
|
||||
|
||||
-export([route_mtp3_sccp_in/1, route_local_out/1]).
|
||||
-export([route_mtp3_sccp_in/1, route_local_out/1, select_opc/2]).
|
||||
|
||||
pointcode_is_local(Pc) ->
|
||||
% FIXME: use SCRC routing information
|
||||
LocalPc = osmo_util:pointcode2int(itu, {1,2,4}),
|
||||
case Pc of
|
||||
LocalPc ->
|
||||
true;
|
||||
_ ->
|
||||
false
|
||||
end.
|
||||
pointcode_is_local(Pc) when is_integer(Pc) ->
|
||||
ss7_links:is_pc_local(Pc).
|
||||
|
||||
% local helper function
|
||||
msg_return_or_cr_refusal(SccpMsg, RetCause, RefCause) ->
|
||||
|
@ -94,6 +87,30 @@ route_local_out(SccpMsg) when is_record(SccpMsg, sccp_msg) ->
|
|||
end,
|
||||
route_local_out_action(Action, SccpMsg, CalledParty).
|
||||
|
||||
% select Originating Point Code for given (local_out) SCCP Msg
|
||||
select_opc(SccpMsg, LsName) when is_record(SccpMsg, sccp_msg) ->
|
||||
% first try to find the Calling Party as specified by user
|
||||
case proplists:get_value(calling_party_addr,
|
||||
SccpMsg#sccp_msg.parameters) of
|
||||
undefined ->
|
||||
% no calling party: auto selection
|
||||
select_opc_auto(SccpMsg, LsName);
|
||||
CallingParty ->
|
||||
case CallingParty#sccp_addr.point_code of
|
||||
% calling party has no point code: auto selection
|
||||
undefined ->
|
||||
select_opc_auto(SccpMsg, LsName);
|
||||
Opc ->
|
||||
% calling party has point code: use it
|
||||
Opc
|
||||
end
|
||||
end.
|
||||
|
||||
select_opc_auto(SccpMsg, LsName) when is_record(SccpMsg, sccp_msg) ->
|
||||
% use SS7 link management to determine Opc
|
||||
ss7_links:get_opc_for_linkset(LsName).
|
||||
|
||||
|
||||
% Acccording to 2.3.2 Action (1)
|
||||
route_local_out_action(1, SccpMsg, CalledParty) ->
|
||||
#sccp_addr{global_title = Gt, ssn = Ssn, point_code = Pc} = CalledParty,
|
||||
|
@ -116,7 +133,8 @@ route_local_out_action(1, SccpMsg, CalledParty) ->
|
|||
% primitive is invoked unless the compatibility test returns
|
||||
% the message to SCLC or unless the message is discarded by the
|
||||
% traffic limitation mechanism;
|
||||
{remote, SccpMsg}
|
||||
LsName = ss7_routes:route_dpc(Pc),
|
||||
{remote, SccpMsg, LsName}
|
||||
end;
|
||||
|
||||
% Acccording to 2.3.2 Action (2)
|
||||
|
@ -140,7 +158,8 @@ route_local_out_action(2, SccpMsg, CalledParty) ->
|
|||
% compatibility test returns the message to SCLC or
|
||||
% unless the message is discarded by the traffic
|
||||
% limitation mechanism
|
||||
{remote, SccpMsg}
|
||||
LsName = ss7_routes:route_dpc(Dpc),
|
||||
{remote, SccpMsg, LsName}
|
||||
end
|
||||
end;
|
||||
|
||||
|
@ -159,7 +178,8 @@ route_local_out_action(3, SccpMsg, CalledParty) ->
|
|||
% primitive is invoked unless the compatibility test returns
|
||||
% the message to SCLC or unless the message is discarded by the
|
||||
% traffic limitation mechanism;
|
||||
{remote, SccpMsg}
|
||||
LsName = ss7_routes:route_dpc(Pc),
|
||||
{remote, SccpMsg, LsName}
|
||||
end;
|
||||
|
||||
% Acccording to 2.3.2 Action (4)
|
||||
|
@ -208,6 +228,7 @@ route_cr_connless(Mtp3Msg, SccpMsg) when is_record(SccpMsg, sccp_msg) ->
|
|||
% FIXME: handle UDTS/XUDTS/LUDTS messages (RI=0 check) of C.1/Q.714 (1/12)
|
||||
% FIXME: handle translation already performed == yes) case of C.1/Q.714 (1/12)
|
||||
route_main(SccpMsg),
|
||||
%LsName = ss7_routes:route_dpc(),
|
||||
{remote, SccpMsg}.
|
||||
|
||||
|
||||
|
|
|
@ -149,33 +149,34 @@ idle(P = #primitive{subsystem = 'N', gen_name = 'CONNECT',
|
|||
idle(P= #primitive{subsystem = 'N', gen_name = 'UNITDATA',
|
||||
spec_name = request, parameters = Params}, LoopDat) ->
|
||||
% User needs to specify: Protocol Class, Called Party, Calling Party, Data
|
||||
% FIXME: implement XUDT / LUDT support
|
||||
% encode the actual SCCP message
|
||||
EncMsg = sccp_codec:encode_sccp_msgt(?SCCP_MSGT_UDT, Params),
|
||||
% generate a MTP-TRANSFER.req primitive to the lower layer
|
||||
send_mtp_transfer_down(LoopDat, EncMsg),
|
||||
{next_state, idle, LoopDat};
|
||||
SccpMsg = #sccp_msg{msg_type = ?SCCP_MSGT_UDT, parameters = Params},
|
||||
case sccp_routing:route_local_out(SccpMsg) of
|
||||
{remote, SccpMsg2, LsName} ->
|
||||
% FIXME: get to MTP-TRANSFER.req
|
||||
{ok, M3} = create_mtp3_out(SccpMsg2, LsName),
|
||||
% generate a MTP-TRANSFER.req primitive to the lower layer
|
||||
send_mtp_transfer_down(LoopDat, M3),
|
||||
LoopDat1 = LoopDat;
|
||||
{local, SccpMsg2, UserPid} ->
|
||||
LoopDat1 = deliver_to_scoc_sclc(LoopDat, SccpMsg2, UserPid)
|
||||
end,
|
||||
{next_state, idle, LoopDat1};
|
||||
|
||||
% MTP-TRANSFER.ind from lower layer is passed into SCRC
|
||||
idle(#primitive{subsystem = 'MTP', gen_name = 'TRANSFER',
|
||||
spec_name = indication, parameters = Params}, LoopDat) ->
|
||||
case sccp_routing:route_mtp3_sccp_in(Params) of
|
||||
{remote, SccpMsg} ->
|
||||
% routing has taken care of it
|
||||
{remote, SccpMsg2, LsName} ->
|
||||
{ok, M3} = create_mtp3_out(SccpMsg2, LsName),
|
||||
% generate a MTP-TRANSFER.req primitive to the lower layer
|
||||
send_mtp_transfer_down(LoopDat, M3),
|
||||
LoopDat1 = LoopDat;
|
||||
{local, SccpMsg, UserPid} ->
|
||||
LoopDat1 = deliver_to_scoc_sclc(LoopDat, SccpMsg, UserPid)
|
||||
end,
|
||||
{next_state, idle, LoopDat1};
|
||||
idle({sclc_scrc_connless_msg, SccpMsg}, LoopDat) ->
|
||||
case sccp_routing:route_local_out(SccpMsg) of
|
||||
{remote, SccpMsg2} ->
|
||||
% FIXME: get to MTP-TRANSFER.req
|
||||
LoopDat1 = LoopDat;
|
||||
{error, _} ->
|
||||
LoopDat1 = LoopDat;
|
||||
{local, SccpMsg2, UserPid} ->
|
||||
LoopDat1 = deliver_to_scoc_sclc(LoopDat, SccpMsg2, UserPid)
|
||||
end,
|
||||
% FIXME: see above, N-UNITDATA.req from user
|
||||
{next_state, idle, LoopDat};
|
||||
% connection oriented messages like N-DATA.req from user
|
||||
idle(#primitive{subsystem = 'OCRC', gen_name = 'CONNECTION-MSG',
|
||||
|
@ -204,11 +205,33 @@ idle(#primitive{subsystem = 'OCRC', gen_name = 'CONNECTION',
|
|||
send_mtp_transfer_down(LoopDat, EncMsg),
|
||||
{next_state, idle, LoopDat}.
|
||||
|
||||
send_mtp_transfer_down(LoopDat, EncMsg) ->
|
||||
Rlbl = #mtp3_routing_label{sig_link_sel = 0, origin_pc = 123, dest_pc = 456},
|
||||
Mtp3 = #mtp3_msg{network_ind = ?MTP3_NETIND_INTERNATIONAL,
|
||||
service_ind = ?MTP3_SERV_SCCP,
|
||||
routing_label = Rlbl, payload = EncMsg},
|
||||
MtpPrim = #primitive{subsystem = 'MTP', gen_name = 'TRANSFER',
|
||||
spec_name = request, parameters = Mtp3},
|
||||
send_mtp_transfer_down(LoopDat, Mtp3) when is_record(Mtp3, mtp3_msg) ->
|
||||
ss7_links:mtp3_tx(Mtp3).
|
||||
|
||||
create_mtp3_out(SccpMsg, LsName) when is_record(SccpMsg, sccp_msg) ->
|
||||
CalledParty = proplists:get_value(called_party_addr,
|
||||
SccpMsg#sccp_msg.parameters),
|
||||
% we _have_ to have a destination point code here
|
||||
Dpc = CalledParty#sccp_addr.point_code,
|
||||
case Dpc of
|
||||
undefined ->
|
||||
{error, dpc_undefined};
|
||||
_ ->
|
||||
Opc = sccp_routing:select_opc(SccpMsg, LsName),
|
||||
case Opc of
|
||||
undefined ->
|
||||
{error, opc_undefined};
|
||||
_ ->
|
||||
% FIXME: implement XUDT / LUDT support
|
||||
SccpEnc = sccp_codec:encode_sccp_msg(SccpMsg),
|
||||
% FIXME: select sls at random
|
||||
M3R = #mtp3_routing_label{sig_link_sel = 0,
|
||||
origin_pc = Opc,
|
||||
dest_pc = Dpc},
|
||||
M3 = #mtp3_msg{network_ind = ?MTP3_NETIND_INTERNATIONAL,
|
||||
service_ind = ?MTP3_SERV_SCCP,
|
||||
routing_label = M3R,
|
||||
payload = SccpEnc},
|
||||
{ok, M3}
|
||||
end
|
||||
end.
|
||||
|
|
Loading…
Reference in New Issue