-
Core components
GDT is a stateful stream based application layer protocol used for data communication between various MINK nodes. It is defined using ASN.1 syntax notation and carried by wire in binary Basic Encoding Rules (BER) format. At the moment, GDT uses SCTP for reliable data transfer, although it can be easily ported to TCP. Correct order of packets and statefulness is maintained by both SCTP and GDT to ensure maximum quality of packet delivery.
The overall design of the protocol was influenced by TCAP but with various enhancements and differences. GDT supports label based application layer routing; every end-point is defined by a two part string label. The first part, named id, is a unique MINK node identifier string, similar to IP address of a machine. The second part is a type string, used mainly for grouping of various nodes for redundancy and load balancing purposes. MINK framework comes with a specialized node called Routing daemon (routingd) which is used mainly for GDT label-based routing and Weighted round robin (WRR) load balancing.
All GDT messages consist of two basic parts; a Header and a Body. Header is mandatory and is handled by the libgdt library and mostly not used by the end-user. The body of the message is where the actual data resides; there are many different types of message bodies and most of them are specialized and used internally by MINK framework. User generated data is transferred in a ServiceMessage body; every service message stream contains a user defined service-id value used for data classification.
-- ============
-- GDT Message
-- ============
-- header - packet header
-- body - packet body
GDTMessage ::= SEQUENCE {
header Header,
body Body OPTIONAL,
...
}
-- ===========
-- GDT Header
-- ===========
-- version - GDT version
-- source - source information
-- destination - destination information
-- uuid - universally unique identifier (UUID)
-- sequence-num - sequence number
-- sequence-flag - packet sequence information (stateful/stateless/etc.)
-- enc-info - encryption information
-- hop-info - hop counter
-- status - error code
Header ::= SEQUENCE {
version [0] INTEGER,
source [1] EndPointDescriptor,
destination [2] EndPointDescriptor,
uuid [3] OCTET STRING,
sequence-num [4] INTEGER,
sequence-flag [5] SequenceFlag,
enc-info [6] EncryptionInfo OPTIONAL,
hop-info [7] HopInfo OPTIONAL,
status [8] ErrorCode OPTIONAL,
...
}
-- =========
-- GDT Body
-- =========
-- encrypted-data - Encrypted GDT body, used only when content is encrypted (header.encryption)
-- packet-fwd - General packet forwarding, used for routing and failovers
-- filter - Filtering service, mostly used but not limited to SMS
-- data-retention - Data retention service, used for DB storage
-- general - Reserved for custom daemons and/or future use
-- conf - Configuration daemon service
-- stats - Statistical data exchange
-- auth - Authentication messages, used for daemon authentication
-- reg - Registration messages, used for daemon discovery and various
-- registration procedures
-- ntfy - Various notification/alarm/etc. messages
-- data - payload data exchange
-- routing - routing related messages
-- service-msg - service related messages
-- state-msg - statefulness related messages
Body ::= CHOICE {
encrypted-data [1] OCTET STRING,
packet-fwd [2] PacketFwdMessage,
filter [3] FilterMessage,
data-retention [4] DataRetentionMessage,
conf [6] ConfigMessage,
stats [7] StatsMessage,
auth [8] AuthMessage,
reg [9] RegistrationMessage,
ntfy [10] NotifyMessage,
data [11] DataMessage,
routing [12] RoutingMessage,
service-msg [13] ServiceMessage,
state-msg [14] StateMessage,
...
}
MINK Configuration parser library is a core component used primarily by Configuration daemon (configd). When designing a system on top of MINK framework, configuration definition is always a good starting point. There are two types of configuration files used by configd; definition and contents.
Definition file is used to describe the structure of data stored in the contents file. Proper definition ensures data
integrity and avoids unnecessary implementations of custom data validators in user specific daemons. Both types
of configuration files share a similar structure and are parsed using the same grammar. Default extension for MINK
configuration files is .mink
; a standard naming convention used in this project is to add a _def
suffix to
base name of definition file (e.g. mink_def.pmcfg
for definition and mink.pmcfg
for contents).
The following example shows a simple configuration showing 3 main types of configuration items:
- primitive
- single field container whose type is defined in the TYPES section of configuration definition file
- block
- a storage container similar to a file system directory, defined with CONST keyword and used mostly for grouping
- dynamic block
- special storage container identified by a "*" (star) symbol; serves a purpose of being a template node for dynamic creation of block nodes
// data types
TYPES {
// each type is defined by perl-type regex
"INT" PTRN\d+PTRN "Number type"
"STRING" PTRN.*PTRN "Alphanumeric type"
}
// config structure
CONFIG {
// global parameter
test_global "INT" "Global INT parameter"
// static sub node
local CONST "Local group" {
test_local "INT" "Local INT parameter"
}
// dynamic nodes
dynamic CONST "Dynamic container node" {
dynamic_child * "STRING" "Dynamic child node" {
test "INT" "Test INT parameter"
}
}
}
test_global "10"
local {
test_local "666"
}
dynamic {
node_1 {
test "10"
}
node_2 {
test "20"
}
}
Configuration daemon is a MINK daemon used for configuration management and is a central most important service of this framework. These are the main features of configd:
- configuration file management
- replication of configuration data
- ACID like properties for configuration transactions (COMMIT/DISCARD/ROLLBACK)
- real-time distribution of configuration data to all affected daemons
- each MINK daemon attaches itself to its own subset of configuration nodes; smart configuration definition will play a vital role in minimizing bandwith usage for configuration data
- when configuration data is changed in some way (using MINK Command Line Interface), all connected daemons that are affected with that particular modification, are notified
- configuration data can grow quite a bit and is therefore advised for each daemon to attach itself to its own subset of configuration defintion (e.g. STP daemon should not get any configuration data related to GDT routing)
config_daemon - MINK Configuration daemon
Options:
-? help
-i unique daemon id
-p GDT inbound port
-d configuration definition file
-c configuration contents file
-r routing daemon address (ipv4:port)
-n other config daemon id
-t user timeout in seconds
-D debug mode
-R enable routing
GDT Options:
=============
--gdt-streams GDT Session stream pool (default = 1000)
--gdt-stimeout GDT Stream timeout in seconds (default = 5
$ ./configd -i cfg1 -p 10000 -d /tmp/test_def.pmcfg -c /tmp/test.pmcfg -R
This will start configd with the following parameters set:
- MINK unique daemon id = cfg1
- SCTP listening port = 10000
- configuration definition file = /tmp/test_def.pmcfg
- configuration contents file = /tmp/test.pmcfg
- -R flag is used when configd should accept connections directly and not via routingd
MINK Command Line Service (CLI) is a specialized shell used for interaction with configd; it features a powerful TAB activated auto-complete and was inspired by CISCO and Vyatta command line interfaces.
cli_service - MINK CLI service
Options:
-i unique service id
-f cli definition file
-c config daemon address (ipv4:port)
$ ./cli_service -i cli1 -f /tmp/cli_default.pmcfg -c 127.0.0.1:10000
This will start cli_service with the following parameters set:
- MINK unique daemon id = cli1
- CLI definition file = /tmp/cli_default.pmcfg
- configd IP address and listening port = 127.0.0.1:10000
CLI definition file is used for defining commands and modules available to the user. At the moment, cli_service uses only one available plugin; pm_plg_cli_cfg.so module is used for cli <---> configd communication.
Routing daemon is a general purpose GDT router; it is used for label based GDT routing and load balancing. The most common type of setup assumes the following:
- two routing daemons (or one if redundancy is not an issue)
- one config daemon
- any number of user daemons
In this setup, routingd connects directly to configd while other daemons involved in this setup connect only to routingd. Routing daemon facilitates all daemon-to-daemon communication, takes care of load balancing (if used), and creates an extra layer of security for configd. Direct connection to configd is established only by routing, all other daemons communicate with configd via routingd.
routingd - MINK Routing daemon
Options:
-? help
-i unique daemon id
-c config daemon address (ipv4:port)
-p GDT inbound port
-D start in debug mode
GDT Options:
=============
--gdt-streams GDT Session stream pool (default = 1000)
--gdt-stimeout GDT Stream timeout in seconds (default = 5)
$ ./routingd -i rtr1 -c 127.0.0.1:10000 -p 15000
This will start routingd with the following parameters set:
- MINK unique daemon id = rtr1
- configd IP address and listening port = 127.0.0.1:10000
- SCTP listening port = 15000
Configuration daemon client is an alternative interface to configd. Unlike cli_service which is interactive, configdc is a script based client used by 3rd party applications like WEB GUIs and shell scripts. Script format used by configdc is a simple text file containing a list of commands to be sent to configd. Commands are processed sequentially and results are outputted to standard output. The resulting output is generated for each command found in a script file; commands are outputted with a : (colon) prefix and their results follow in the next line, unmodified. If an error occurs, configd will do an automatic discard of the whole transaction, and the resulting output will start with "ERROR:", followed by the actual error message generated by configd.
cfgdc - MINK Config daemon client
Options:
========
-? help
-i unique daemon id
-f config daemon command script file
-r routing daemon address (ipv4:port)
-D start in debug mode
GDT Options:
=============
--gdt-streams GDT Session stream pool (default = 1000)
--gdt-stimeout GDT Stream timeout in seconds (default = 5)
$ cat /tmp/test.txt
configuration
show dyn node_1 test
$ ./configdc -i cfgc1 -r 127.0.0.1:10000 -f /tmp/test.txt
: configuration
test_global "10"
local {
test_local "666"
}
dynamic {
node_1 {
test "10"
}
node_2 {
test "20"
}
}
: show dyn node_1 test
test = 10
This will start configdc with the following parameters set:
- MINK unique daemon id = cfgc1
- configd (or routingd) IP address and listening port = 127.0.0.1:10000
- script file with the list of commands to send to configd = /tmp/test.txt
$ cat /tmp/test_err.txt
configuration
show dyn node_1 testbla
$ ./configdc -i cfgc1 -r 127.0.0.1:10000 -f /tmp/test_err.txt
: configuration
test_global "10"
local {
test_local "666"
}
dynamic {
node_1 {
test "10"
}
node_2 {
test "20"
}
}
: show dyn node_1 testbla
ERROR: Unknown item or command "testbla"!
This will start configdc with the following parameters set:
- MINK unique daemon id = cfgc1
- configd (or routingd) IP address and listening port = 127.0.0.1:10000
- script file with the list of commands to send to configd = /tmp/test_err.txt
GDT Trap client is a tool used for fetching MINK performance counters. Daemons can expose various counters which are usually required for performance tracking and trouble shooting. MINK framework uses its own system for counters; it is an GDT protocol extension quite similar but not as powerful as SNMP. Most production environments use their own 3rd party monitoring tools; creating wrapper scripts to convert gdttrapc output to SNMP compatible data should not be a big issue.
gdttrapc - MINK GDT trap client
Options:
-c target daemon address (ipv4:port)
-t target daemon type
-i target daemon id
-s target trap id (0 for ALL)
-a unique client id
GDT Options:
=============
--gdt-streams GDT Session stream pool (default = 10)
--gdt-stimeout GDT Stream timeout in seconds (default = 5)
--gdt-smsg-pool GDT Service message pool (default = 10)
--gdt-sparam-pool GDT Service message parameter pool (default = 1000)
$ ./gdttrapc -c 127.0.0.1:15000 -t routingd -i rtr1 -s GDT_IN_config_daemon_cfg1_BYTES -a trapc1
Trap Id Trap Value
-------------------------------------------------------------
GDT_IN_config_daemon_cfg1_BYTES 140
This will start gdttrapc with the following parameters set:
- routingd IP address and listening port = 127.0.0.1:10000
- type label of target daemon to fetch counters from = routingd
- id label of target daemon to fetch counters from = rtr1
- counter id (multiple -s supported) to fetch = GDT_IN_config_daemon_cfg1_BYTES
- trap client's unique daemon id = trapc1
$ ./gdttrapc -c 127.0.0.1:15000 -t routingd -i rtr1 -s 0 -a trapc1
Trap Id Trap Value
----------------------------------------------------------------------------
GDT_IN_%routingd_%rtr1_BYTES 441
GDT_IN_%routingd_%rtr1_DISCARDED 0
GDT_IN_%routingd_%rtr1_MALFORMED 0
GDT_IN_%routingd_%rtr1_PACKETS 5
GDT_IN_%routingd_%rtr1_POOL_ERR 0
GDT_IN_%routingd_%rtr1_SOCKET_ERR 0
GDT_IN_%routingd_%rtr1_STREAMS 1
GDT_IN_%routingd_%rtr1_STREAM_BYTES 192
GDT_IN_%routingd_%rtr1_STREAM_ERR 0
GDT_IN_%routingd_%rtr1_STREAM_LOOPBACK 0
GDT_IN_%routingd_%rtr1_STREAM_TIMEOUT 0
GDT_IN_gdttrapc_trapc117815_BYTES 0
GDT_IN_gdttrapc_trapc117815_DISCARDED 0
GDT_IN_gdttrapc_trapc117815_MALFORMED 0
GDT_IN_gdttrapc_trapc117815_PACKETS 0
GDT_IN_gdttrapc_trapc117815_POOL_ERR 0
GDT_IN_gdttrapc_trapc117815_SOCKET_ERR 0
GDT_IN_gdttrapc_trapc117815_STREAMS 0
GDT_IN_gdttrapc_trapc117815_STREAM_BYTES 0
GDT_IN_gdttrapc_trapc117815_STREAM_ERR 0
GDT_IN_gdttrapc_trapc117815_STREAM_LOOPBACK 0
GDT_IN_gdttrapc_trapc117815_STREAM_TIMEOUT 0
GDT_OUT_%routingd_%rtr1_BYTES 815
GDT_OUT_%routingd_%rtr1_DISCARDED 0
GDT_OUT_%routingd_%rtr1_MALFORMED 0
GDT_OUT_%routingd_%rtr1_PACKETS 7
GDT_OUT_%routingd_%rtr1_POOL_ERR 0
GDT_OUT_%routingd_%rtr1_SOCKET_ERR 0
GDT_OUT_%routingd_%rtr1_STREAMS 0
GDT_OUT_%routingd_%rtr1_STREAM_BYTES 0
GDT_OUT_%routingd_%rtr1_STREAM_ERR 0
GDT_OUT_%routingd_%rtr1_STREAM_LOOPBACK 0
GDT_OUT_%routingd_%rtr1_STREAM_TIMEOUT 0
GDT_OUT_gdttrapc_trapc117815_BYTES 0
GDT_OUT_gdttrapc_trapc117815_DISCARDED 0
GDT_OUT_gdttrapc_trapc117815_MALFORMED 0
GDT_OUT_gdttrapc_trapc117815_PACKETS 0
GDT_OUT_gdttrapc_trapc117815_POOL_ERR 0
GDT_OUT_gdttrapc_trapc117815_SOCKET_ERR 0
GDT_OUT_gdttrapc_trapc117815_STREAMS 0
GDT_OUT_gdttrapc_trapc117815_STREAM_BYTES 0
GDT_OUT_gdttrapc_trapc117815_STREAM_ERR 0
GDT_OUT_gdttrapc_trapc117815_STREAM_LOOPBACK 0
GDT_OUT_gdttrapc_trapc117815_STREAM_TIMEOUT 0
This will start gdttrapc with the following parameters set:
- routingd IP address and listening port = 127.0.0.1:10000
- type label of target daemon to fetch counters from = routingd
- id label of target daemon to fetch counters from = rtr1
- counter id (multiple -s supported) to fetch = 0
- trap client's unique daemon id = trapc1
This software is licensed under the MIT license