THE 7-SCALES DEVELOPER´S NOTES

 File structure
 Configuration and network integration
 Signaling Point Codes and Global Titles at run time
 Global Title translations
 Point codes and messages
 Creating a dynamic thisIE structure for a message
 Assigning a session to an incoming message
 Assigning a session to an outgoing message
 Exploring a message
 Modifying a message
 Sending a message
 Repetition of tests
 Adding a scenario
 Classification of return codes
 Logging and Debugging
 Message transport
 

This section provides various useful items of information regarding the architecture, capabilities and usage of the Code. These notes do not pretend to be exhaustive; they will be extended and refined through next releases.

File structure

 

The file tree is presented on figure on the left as a snapshot of the Eclipse screen. Scenarios are located in ../scenarios folder. The ../network folder contains two header files with functions that provide the equivalent of MTP Level 2 and Level 3 functionality. Message templates are located in folders ../cs1p and ../mapv3 and a fodders devoted to CAP will be added soon.

Folders Binaries, Includes and Debug are not parts of the 7-Scales; they are elements of Eclipse´s file structure.

Most of the header files are described in the text.

Back to top

Configuration and network integration

Headers ipv4conf.h and ccs7conf.h contain all configuration data that the Code needs to communicate with the outside World. The former holds default information for the IP connectivity; it can be changed by command line options -i and -p for the STU, and -I and -P for the NSU. The latter contains SPCs and GTs for the Code itself and for the Network. This header file needs to be modified to match the particular network. Note that STU may have up to three point codes, but no tests have been made with more than one point code so far.

Back to top

Signaling Point Codes and Global Titles at run time

There is a great variety in ways GTs can be constructed. They all step on the structure GT_stru defined in ccs7base.h. Two functions are provided to decode and to code GTs at runtime: get_sccpGT and gen_sccpGT15. The former takes Calling or Called party fields from the SCCP packet and fills in a GT_stru object accordingly. The latter takes a GT_stru object and produces Calling or Called party I.E.s, placed in a uint8_t array that is maximum 15 bytes (with BCD encoding this allows more than 20 digits).

Processing GTs from scratches every time a message comes or is to be sent is tiresome and stupid. Within TCAP dialogue GTs are seldom changed, so it is worth creating regular channels to process GTs automatically in the context of the session. Same stands for the Point codes. This automated SPC and GT processing is built in the functions that deal with session objects (SessiTC[i].tcs). These functions are:

setSPC_sesTCAPalli, setGT_sesTCAPalli, addRAARQ_sesTCAPremi, addLAARE_sesTCAPremi, addLAARQ_sesTCAPloci, addRAARE_sesTCAPloci, addREMOT_sesTCAPalli, addLOCAL_sesTCAPalli, addRABRT_sesTCAPalli and addLABRT_sesTCAPalli.

From the above list, the first function explicitly sets SPCs and the second explicitly sets GTs. addRAARQ_sesTCAPremi sets GTs and SPCs as received in the first message of the Dialogue that conveys AARQ APDU and is usually TCAP BEGIN. In most of the cases this is sufficient to provide MTP3 and SCCP information to the Session. addRAARE_sesTCAPloci modifies remote GT, as it is the first message from the remote side, conveying the response AARE to the AARQ and may contain different GT from the one that has been used to send the AARQ. Generally, the change of the remote GT may affect the remote SPC. For this reason you should call setSPC_sesTCAPalli with OVRD=0 to reset remote SPC accordingly. Conventions are provided in the body of this function (it is located in main.c). You should read also the comments in tests 1.1.1 and 2.1.x.

Back to top

Global Title translations

The Code carries out simple GT translation according to the following rules:

- If indRtg is set, nothing is changed (this means Routing on SSN),

- If it is not set, it is checked first if the Address information matches the Address information of the own GT and if the check is successful, indRtg is set, indSSN is also set, and if there is no SSN, the default SSN is supplied.

For the STU, the GT is provided in stuGT_ADR or ownGT4 or stuGT4. The NSU, on the other hand, accepts any GT, even the STU´s one (no check is done at all). GT translations are carried out at the beginning of the scenario code. Therefore, they can be manipulated per scenario, without affecting other scenarios.

Back to top

Point codes and messages

Both STU and NSU provide filters for incoming messages. STU accepts messages with DPC that matches stuSPC or stuSPC2 or stuSPC3 as set in the header ccs7conf.h. NSU accept any message, which DPC does not match stuSPC, stuSPC2 and stuSPC3.

Always check point codes when a message is seen at the Wireshark, but not processed by the receiving unit.

Back to top

Creating a dynamic thisIE structure for a message

Use function dmtcap to create an object of type TCAPmsu for a raw message. For incoming messages always use s7AP=UAP_ID (0, AP unknown). In this case dmtcap analyses message and associates it with a relevant TCAPses object where the information regarding the session the message belongs to is being collected. You can use dmtcap with s7AP=MAP1ID, CS1PID or any other AP, but you have to supply also the Application Context to be associated with the operations in this message. This is used to create dynamic thisIE structures for template messages and is explained in document "Creation of Message Templates and Operations Definitions".

Function dmtcap returns Zero (dmtcap( ) == 0) when the formal decoding is successful and the SS7 Application Part, Application Context and Version have been recognized (found in map_base.h, cap_base.h and cs1pbase.h).

Function dmtcap returns negative result (dmtcap( ) < 0) only when a deep error is encountered and the message cannot be decoded in full or when Application Context is not recognized or the SS7 Application Part is not recognized. The return value can be mapped against the error codes in the header file errorbase.h to analyze the case.

Positive result (dmtcap( ) > 0) means that some error have been encountered in the Dialogue Portion and the Components that are not fatal for the formal decoding of the message. dmtcap tries to decode the message and returns the information in TCAPmsu.dp.rcod (for the Dialogue Portion) and TCAPmsu.cm[i].rcod (for the Components). This information can be examined by the invoking function to study the problem. Note that in this case the return value of dmtcap has no meaning as error code; it just indicates that some non fatal errors have been encountered.

Application Context Version needs special attention. The 7-Scales recognizes all AC versions and the corresponding Operations up to MAP4/2011 and CAP4/2010. If newer version is encountered but the Operation is found in the set operations for the lower version, it is not considered a fatal error. Information about this case will be provided in TCAPmsu.dp.rcod. This will certainly happen with the Ericsson CS1+. The 7-Scales recognizes only CS1+ Revision 0. No fatal error will be generated if message has Revision 1, but a kind of warning will be written in TCAPmsu.dp.rcod.

Even in the case of negative return value of dmtcap it may be useful to study TCAPmsu.dp.rcod and TCAPmsu.cm[i].rcod, as they may carry significant information regarding the message.

Back to top

Assigning a session to an incoming message

For every TCAP BEGIN or CONTINUE message with AARQ APDU, a new Session has to be established. This could be done in the message decoding function dmtcap(), but here another approach is chosen. dmtcap() only finds a free storage for the Session information, seizes it and sets .sessid element of TCAPmsu. Then, the function addRAARQ_sesTCAPremi() places the Session-related information in the Session storage addressed by TCAPmsu.sessid. The remaining cases are processed the same way: dmtcap() sets the index TCAPmsu.sessid to the Session, which the message belongs to. Then, using an appropriate session-related function - addRAARE_sesTCAPloci, addREMOT_sesTCAPalli or addRABRT_sesTCAPalli, the information is filled in the Session storage. All these functions are called at the beginning of the state machine that implements the scenario itself. Refer to tests 1.1.1 and 2.1.x for examples.

Back to top

Assigning a session to an outgoing message

Before sending a TCAP BEGIN to the remote end, you have to seize a TCAPses object to put there Session-related information. This is done by the function seize_sesTCAP. Then you should use addLAARQ_sesTCAPloci to save session-related information into TCAPses object, seized by seize_sesTCAP. Before that you have to set SPCs and GTs, using functions setSPC_sesTCAPalli, setGT_sesTCAPalli as described in subsection Configuration and network integration.

Back to top

Exploring a message

Use dmgsie() and dmgmie() to compare the Value of an I.E. with a particular value. The former can be used for a unique I.E. The latter is designed for the case when there are many I.E.s of the same type in a message, and uses more complicated criterion to find the right I.E. among all I.E.s of the same type. The criterion consists of another I.E., called "Condition" I.E. with a specific Value that is bundled to the one being sought. Example for such bundled I.E.s is eventTypeBCSM and monitorMode. They are bundled by bcsmEvent, which is their Owner.

With dmgsie() and dmgmie() you can check if an I.E. is presented in an operation in a message. If not found, they return warning WNG_TGTIE_NOTF2. Note that dmgmie() returns WNG_TGTIE_NOTF2 in two cases: when target I.E. is not found and when the bundled I.E. is not found, too. dmgsie() and dmgmie() do not carry out any comparisons themselves; they provide two indexes, opi and iei that should be supplied to get2ptr_ieval to retrieve a pointer of type uint8_t* to the field in the message that is to be compared. Study test 2.1.x to learn more about this matter.

For a given Message, given Operation in this Message and given I.E. in this Operation, the process of exploring a message comprises two steps:

- Obtain the index of the Operation in the TCAPmsu structure of the Message and

- Obtain the index of the I.E. within the thisIE structure, associated with this Operation in this Message.

Taking InitialDP operation from test 2.1.1 as an example, you start with the name of the Operation - opInitialDP_v0. This is a named constant defined in the header file cs1pbase.h. You need the table that implements the static thisIE structure, associated with the InitialDP operation, which name is tab_opInitialDP_v0. This table is located in header file cs1popdefs.h. The last piece of infor mation that you need to feed functions dmgsie() and dmgmie() is the name of the I.E., serviceKey in this example. At this point you are ready to call functions dmgsie() and dmgmie().

Back to top

Modifying a message

The Code has a lot of messages that, after some modification, can be sent to the remote unit. These messages should be regarded as templates rather than ready to use messages. They can be modified by means of a number of functions: dmnew(), dmadd(),dmdel(), dmcdn(), dmgnb(), dmfci(). Modifications may include increase of the I.E.s in the Operations in the message. If that happens, there will certainly be problems with the Scenario at runtime. To avoid memory mutilation, always use function cloneTCAPmsu() to produce a copy of the message template in the Heap. Then you can apply all changes to the cloned message without risk of a problem.

Function dmnew() changes the Value of a unique I.E. where as dmcdn() changes the Value of an I.E. that has many occurrences in an Operation; similarity exists between these two functions and dmgsie() and dmgmie(). Function dmadd() adds a new I.E. and has two options: to add an I.E. only if there isn´t any other I.E. of the same type or to add I.E. anyway. Function dmdel() can be used to delete an I.E. from a message. Use this function for unique I.E.s. Function dmfci() is designed for FCI operation and calls dmgnb(), which, in general, is designed to modify Generic Number I.E. and Generic Digit I.E.

These functions are used in a manner similar to the one shown in subsection Assigning a session to an incoming message

Back to top

Sending a message

Use put2udt_QS to place a message into the sending buffer msu_QS. Note that this function sets into the raw message all MTP3 and SCCP data -- SIF, SPCs, GTs, etc. With the function setMTP3_sccpudt you are given the last chance to change of MTP3 data before put2udt_QS.

Note that put2udt_QS may produce more than one message from the one you intend to send. This happens when the length of the resulting message exceeds the max length for UDT messages and XUDT has to be used instead. Note that XUDT-related procedures have been tested only for messages that produce two segments.

Function mov_tcap_sccp is used to create an input to put2udt_QS, which expects pointer to sccp_udt structure and conversion from TCAPmsu is required. That could be done automatically with C++, using the inheritance mechanism.

Back to top

Repetition of tests

A scenario can be repeated many times against the network with different data, addressed by the second parameter of the scenario signature (int (*branch[2])(int, uint32_t)). This option is not available in simulation mode for the time being.

Back to top

Adding a scenario

Scenarios can be integrated in many different ways, but the one proposed here consists of the following. Place the scenarios in different header files, named test_x_y_z.h. Here x, y, and z specify the Group, Subgroup and consecutive number of the scenario. At the beginning of the header file place the header file that contains messages templates for this scenario. For test_2_1_1 example this is: #include "../cs1p/cs1pv0_ac0_op1.h"

You can use already existing headers, if they match your intensions.

Add an empty template for the scenario test_2_1_1 in Test cases section of main.c. That is:

#define group_name_2 "Ericsson INAP CS1Plus Operations"

#define group_numb_2 "2"

#define subgr_name_2_1 "Mobile Originating VPN Scenarios"

#define subgr_numb_2_1 "2.1"

#define tgrp_name_2_1_1 group_name_2

#define tgrp_numb_2_1_1 group_numb_2

#define sgrp_name_2_1_1 subgr_name_2_1

#define sgrp_numb_2_1_1 subgr_numb_2_1

#define test_name_2_1_1 "Successful on-net mVPN call"

#define test_numb_2_1_1 "2.1.1"

#define spec_refr_2_1_1 "Ericsson CRT_249_12_Rev_B"

#define xtra_info_2_1_1 "Author, mail, ..."

#define descript_2_1_1 "\

A-party, who is a mVPN member calls B-party, who is also a mVPN member\n\

using their short (VPN) number\

"

#define testcase_2_1_1 {NULL, NULL}

#define scenario_2_1_1 {testcase_1_1_1, 0, 0}

#include "scenarios/test_2_1_1.h"

Now go back to the header file test_2_1_1.h and add at the end of the file redefinitions of the above definitions:

#ifdef testcase_2_1_1

#undef testcase_2_1_1

#endif

#ifdef scenario_2_1_1

#undef scenario_2_1_1

#endif

#define testcase_2_1_1 {test_2_1_1_stu, test_2_1_1_nsu}

#define scenario_2_1_1 {testcase_2_1_1, 300, 1}

Finally, go again to main.c and add the following line in the section Test scenarios list:

{tgrp_name_2_1_1,tgrp_numb_2_1_1,sgrp_name_2_1_1,sgrp_numb_2_1_1,test_name_2_1_1,test_numb_2_1_1, xtra_info_2_1_1, descript_2_1_1, spec_refr_1_1_1, scenario_2_1_1, 0, 0},

Now you compile and run.

Back to top

Classification of return codes

At the highest level, return codes are defined in the header file mainbase.h. They have been used throughout the Code with the following framework in mind:

TEST_RESULT_SUCCESS means that the scenario has met all expectations during its execution.

TEST_RESULT_FAILED means that the scenario has failed due at the conceptual level, e.g. the network has behaved in an expected manner that is not matching the success criteria. For a scenario that is considered ready for execution, this result shouldn´t happen when running simulation mode.

TEST_RESULT_SCRIPTERR means that the scenario is not constructed well. This could be because some fields are not correctly modified, or an unexpected result within the scenario code has been encountered.

TEST_RESULT_INCONCLUSIVE means that the result of scenario can be classified as neither successful, not failed. This could be when the network behaves in an unexpected manner. Note that the line between failure and inconclusive could be vague in some cases. It depends on the context the scenario is implemented.

At system level the execution of a scenario can be either success or failure. For the cases of system failure the return code is ERR_SYSTEM_FAILURE, which means that the scenario has failed due to bad design of the Code itself. It could be for example that a limit of a buffer is reached and it is not possible to process the next message. For cases like this debug information is provided in the log to give a clue of the problem. The scenario itself should be classified as TEST_RESULT_INCONCLUSIVE.

In general, there are two types of error codes: errors and warnings. Errors are negative numbers, warnings are positive numbers, and therefore a single check is sufficient to distinguish between them. The idea is to leave the scenario in case of error and to continue in case of warning, taking some measurements. All functions addressed in this section are compliant with this framework. However, some functions do not comply with it. If you need to use some low-level functions, you should look through the code of these functions.

More details regarding error codes framework used in this release can be found in the comments to the header file errorbase.h.

Back to top

Logging and Debugging

A number of macro definitions in the header compile.h control the compilation and execution of the Code. Compilation control in fact determines which scenarios and which packages of messages to be compiled. Debugging is controlled by another set of macro definitions, also located in compile.h. Debugging in this context is not debugging provided by the gdb. This is more likely extended log information that helps to solve problems rising during scenarios creation.

This information is structured as follows:

- For conditionally compiled prints of parameters:

+++ [0|1]:[<function>:´<Some reminder>´]#<Type of print>: <Item >=<Value>, ..

Example:

+++[0]:[test_1_1_1:´SST_RECV´]#PARMS: recvSSN=252, recvSPS=1234

- For conditional compiled prints of messages:

[0|1]:[<function>]$[SEND|RECV](<more info>) [-,<length>]:

AA BB CC ..

Example:

[1]:[sendrecv]$SEND(-->´rmt´) [-,28]:

46 56 46 56 00 00 00 00 f4 1f 6c cc 03 00 00 10 00 00 00 02 00 00 fa 00 00 00 00 00

- For events that are not under conditional compilation:

>>> [0|1]:[<function>@<number>]$<Even description>: <more info>=<return code>,

Instead of ">>>" other signs may be used: "---", "+++", "!!!" etc.

Example:

>>> [0]:[test_1_1_1@07]$SCRIPTERR: dmnew=450

Back to top

Message transport

As already mentioned, the message transport of 7-Scales is based on the raw socket technique for sending and receiving IP packets. The author used this technique to implement a subset of SCTP and M2PA. Note that the functionality the author developed is very limited - enough to cover the bare minimum to exchange messages and keep the signalling link to the network alive. On the base of this bare minimum the author developed a kind of ´fast forward´ through MTP3 (again the bare minimum) and SCCP (only UDT and XUDT) so that the base for TCAP was built.

The author has never been interested in low level protocols, except for network design and troubleshooting.

Back to top

Back to Contents