YateDRA Routing

Routing table description

Each configured node have its own routing table.
Each entry contains:

FieldFormatDescription
realmString/Regexp Realm to match (from DestinationRealm)
routesArrayList of routes for the realm

A route entry will be used to route a list of destination hosts and/or applications to a peer with whom DRA has a direct connection.
Route entry contents:

Replacing variables

The first entry in routing table may indicate a set of replacing variables in the following way.

  • Must not contain a realm property
  • Contains a vars object whose properties will be used to replace strings in all other routing table items.

NOTES:

  • Variable replace is done on vars also
  • This option needs Yate 6.0.1

Matching parameters

Parameters used to match a request against current routing table entry.

FieldFormatDescription
random NumberPercentage to match randomly, 0 (never matches) to 100 (always matches)
recv_peer String/Regexp Match peer node we received the request from
originString/Regexp Match the node originating the request. The value is taken from Origin-Realm/Origin-Host AVPs
hostString/Regexp Host (Destination-Host AVP) to match
appidString/Regexp Application ID to match (this is the Auth-/Acct-/Vendor-Specific Application-ID AVP). Vendor specific application ID should expect a vendor. E.g. S6a/d should match 16777251/10415
cmdappidString/Regexp Command application ID from Diameter message header to match
cmdcode cmdshortname cmdnameString/Regexp Command identifier. These parameters are mutually exclusive. When one of them is set to non empty value the subsequent parameters will be ignored.
cmdcode: Command code (e.g. 316)
cmdshortname: Command short name (e.g. ULR)
cmdname: Command full name (e.g. UpdateLocationRequest)
avp ArrayAVP(s) to match. Each entry is an object with the following fields:
path: AVP path
value: String/Regexp: Value to match if the AVP is present. Empty or missing value matches AVP presence
optional: Boolean: Set it to true to indicate the AVP may not be present. This is the matching rule if the AVP is not found
anyArrayORed array of objects containing matching criteria. Evaluation stops when a criteria set matches. Objects may contain any matching criteria including any Objects with no matching fields will be ignored

Forwarding parameters

Parameters used to forward a request matching current routing table entry.

FieldFormatDescription
forwardBooleanTrue to forward the request to indicated Destination-Host AVP. Request will fail if Destination-Host is empty
The following parameters are ignored if this parameter is enabled: peer, peer_list, node, node_override
peerNODENext peer node to forward the request (peer of current node or node indicated in local_node)
peer_listObjectNext peer nodes to forward the request (peers of current node or node indicated in local_node).
This parameter is ignored if peer is set.
Parameters:
• peers: Array of NODE
• algorithm: String: Optional algorithm to use: rotate:
• Rotate the list of peers each time a request is forwarded. This is the default value
• fixed or -: Always forward to the same peers list
• avp-hash:Rotate the list starting from a fixed point given by AVP value hash
• random: Rotate the list starting from a random point in it
• path: AVP path. This parameter is required for algorithm=avp-hash, ignored otherwise. If AVP value is missing (AVP is missing or it's a grouped one) the initial list is used
NOTE: This option needs Yate 6.0.1
nodeNODEInternal node to pass the message to if peer is not set (jump to another node's routing table). The node will apply its own routing rules.
This parameter is ignored if peer or peer_list is set
The following parameters are ignored if this parameter is set: proxy, msgparams, alternate_node
local_nodeNODELocal node to use when forwarding the request (current node is used if this parameter is not set).
The following parameters are ignored if this parameter is set: node, node_override

Reject parameters

Parameters used when a request matching an entry is rejected (not forwarded).
These parameters are ignored if the route entry contains information used to forward matched request.

FieldFormatDescription
codeString/Number Result code. Minimum allowed value is 1000
vendor_code String/Number Vendor specific result code. Format: code[/[vendor]].
Minimum allowed value for code is 1000.
The vendor part is optional. Minimum allowed value is 1. Defaults to 10415 (3GPP) if missing.
This parameter is ignored if code is present
error_message StringError string to return in ErrorMessage AVP
reject_add_avpsStringXML fragment with AVPs to add to response. XML is not validated

If code and vendor_code are missing but other reject parameters are present the request will be rejected with Diameter code 3002.

Other parameters

Parameters used to alter the message when forwarding a request:

FieldFormatDescription
msgparamsObjectYate message parameters to set (without routing prefix).
Here are some useful parameters:
• track_msg_level: integer: Instruct diameter module to put more debug when handling the message. Debug messages will be put using set debug level. This will debug used node(s) and peer(s)
alternate_nodeArrayList of objects with alternate node(s) to use on failure to send using current node (or local_node)
Known item parameters:
• local_node: NODE: Required local node
• peer: NODE or String (with host only): Optional peer to use. Leave it empty to use node's default routing priority if set
proxyObjectOptional parameters to be set when forwarding a request. These parameters are set in diameter message as they are.
This parameter is ignored if node is set.
Known parameters:
• del_avps: string: Comma separated list of AVPs (XML tags, first level only) to delete from message when sending it. All instances of a given tag will be removed.
NOTES:
• This option should be the first entry in proxy params to avoid conflicts with other options
• This option needs Yate 6.0.1
• hide_network_topology_avps: boolean/string. Boolean: Remove ProxyInfo and RouteRecord AVPs (restore ProxyInfo in answer if true)
• add_avps: string: XML fragment with AVPs to add to request. XML is not validated
node_overrideObjectOverride destination node table parameters when jumping to another node's table:
• alternate_node: Boolean: Set it to true to ignore alternate node(s) when forwarding the request
• proxy: Boolean: Set it to true to ignore proxy parameters when forwarding the request
• msgparams: Boolean: Set it to true to ignore Yate message parameters when forwarding the request
• route_record: Boolean: Set it to true to ignore (disable) Route-Record AVP addition when forwarding the request

Miscellaneous parameters:

FieldFormatDescription
traceString String to be put on output when route matches. Matching parameters are replaced in it (e.g. trace:"Matched ${recv_peer}/${appid}")

NOTES:

  • NODE format: String (realm/host)
  • Regexp values are detected when a string starts with '^'
  • To reverse regexp match condition add a '^' char at string end
  • AVP path format: String with AVP tree separated by '/'. Empty elements in path (including first element) are not allowed

Valid values: TerminalInfo/IMEI or Username
Invalid values: TerminalInfo/IMEI/ or /Username

Routing algorithm

Routing table not configured:

  • DestinationHost AVP present: Try to forward the request to peer indicated in DestinationHost
  • DestinationHost AVP is missing: Reject the request (UNABLE_TO_DELIVER)

Routing table configured

  • DestinationRealm AVP is missing: Reject the request (UNABLE_TO_DELIVER)
  • DestinationRealm AVP value not found (matched) in routing table: Reject the request (REALM_NOT_SERVED)
  • Search for a rule match in realm entry
  • Rule not found: Reject the request (UNABLE_TO_DELIVER)
  • Rule found: handle it

JSON routing table example

The following is an example of a standard setup with 2 DRAs. All nodes are connected to both DRAs.

Interconnect with any other operator is done using an interconnect hub.

This describes DRA 1 configuration with the following nodes (for DRA 2 one may just change the digits in identities and alternate node routing):

  • epc.mnc001.mcc001.3gppnetwork.org/dra1.epc.mnc001.mcc001.3gppnetwork.org: We are assuming all internal network services (HSS, MMEs, UCNs ...) are connected to this node.
  • epc.mnc001.mcc001.3gppnetwork.org/dea1.epc.mnc001.mcc001.3gppnetwork.org: We are connected to an interconnect hub using this identity. The hub is handling all our interconnect agreements
  • epc.mnc001.mcc001.3gppnetwork.org/dra1fb.epc.mnc001.mcc001.3gppnetwork.org: DRA 1 identity used toward our second DRA

epc.mnc001.mcc001.3gppnetwork.org/dra1.epc.mnc001.mcc001.3gppnetwork.org routing table:

[
    {
        “vars”: {
            “domain_3gpp”: “mnc001.mcc001.3gppnetwork.org”,
            “domain_3gpp_regexp”: “.*\\.mnc001\\.mcc001\\.3gppnetwork\\.org”,
            “epc”: “epc.${domain_3gpp}”,
            “hss1”: “${epc}/hss1.${epc}”,
            “hss2”: “${epc}/hss2.${epc}”,
            // Our DRAs. Internal identities used to connect our nodes
            “dra1”: “${epc}/dra1.${epc}”,
            “dra2”: “${epc}/dra2.${epc}”,
            // Fallback routing between our DRAs
            “dra1fb”: “${epc}/dra1fb.${epc}”,
            “dra2fb”: “${epc}/dra2fb.${epc}”,
            // Interconnect. External identities used toward interconnect hub partner
            “dea1”: “${epc}/dea1.${epc}”,
            “dea2”: “${epc}/dea2.${epc}”,
            // Interconnect hub. Identities of interconnect partner
            “hub_realm”: “epc.mnc002.mcc001.3gppnetwork.org”,
            “hub_dea1”: “${hub_realm}/dea1.${hub_realm}”,
            “hub_dea2”: “${hub_realm}/dea2.${hub_realm}”
        }
    },
    {
        // Destination is our realm
        “realm”: “^${domain_3gpp_regexp}$”,
        “routes”: [
            {
                // Known destination host. Forward the request
                “host”: “^(hss|ucn)”,
                “forward”: true,
                // Use second DRA as fallback if node’s connection is down
                // This will be disabled by fallback node’s rules to avoid looping
                “alternate_node”: [
                    {
                        “local_node”: “${dra1fb}”,
                        “peer”: “${dra2fb}”
                    }
                ]
            },
            {
                // Unknown destination host
                // 3002 code will be sent by the above rule also if destination node’s connection is down
                // The error message will help us to debug the cause when seeing it
                “host”: “^.*”,
                “code”: 3002,
                “error_message”: “Unknown host”
            },
            // Requests with no destination host. Send them to corresponding server
            {
                // 3GPP S6a/d and Cx/Dx – send to HSS
                “cmdappid”: “^(16777251|16777216)”,
                “peer_list”: {
                    “peers”: [
                        “${hss1}”,
                        “${hss2}”
                    ]
                },
                “alternate_node”: [
                    {
                        “local_node”: “${dra1fb}”,
                        “peer”: “${dra2fb}”
                    }
                ]
            }
        ]
    },
    {
        // Requests for a foreign realm. Send them to interconnect hub
        “realm”: “^.*”,
        “routes”: [
            {
                “local_node”: “${dea1}”,
                “peer_list”: {
                    “peers”: [
                        “${hub_dea1}”,
                        “${hub_dea2}”
                    ]
                },
                “alternate_node”: [
                    {
                        “local_node”: “${dra1fb}”,
                        “peer”: “${dra2fb}”
                    }
                ]
            }
        ]
    }
]

epc.mnc001.mcc001.3gppnetwork.org/dea1.epc.mnc001.mcc001.3gppnetwork.org routing table:

[
    {
        // Destination is our realm. Jump to DRA1 node routing table
        “realm”: “epc.mnc001.mcc001.3gppnetwork.org”,
        “routes”: [
            {
                “node”: “dra1.epc.mnc001.mcc001.3gppnetwork.org”
            }
        ]
    },
    {
        // Destination is any other realm. Reject it
        // This is just an example. The request would be rejected anyway (code 3003 / REALM_NOT_SERVED)
        “realm”: “^.*”,
        “routes”: [
            {
                “code”: 3003,
                “error_message”: “Unknown realm”
            }
        ]
    }
]

epc.mnc001.mcc001.3gppnetwork.org/dra1fb.epc.mnc001.mcc001.3gppnetwork.org routing table:

[
    {
        “realm”: “^.*”,
        “routes”: [
            {
                // Jump to DRA1 node routing table
                “node”: “dra1.epc.mnc001.mcc001.3gppnetwork.org”,
                // Disable alternate routing to avoid looping
                “node_override”: {
                    “alternate_node”: false
                }
            }
        ]
    }
]

Other examples

Replacing variables

[
  {
    "vars": {
      "domain": "epc.mnc001.mcc001.3gppnetwork.org", 
      "hss1": "${domain}/hss1.${domain}",
      "hss2": "${domain}/hss2.${domain}",
      "test_imsi": "^(001010000000000|001010000000007)$"
    }
  },
  {
    "realm": "^.*\\.mnc001\\.mcc001\\.3gppnetwork\\.org$",
    "routes": [
      {
        "cmdappid": "16777251",
        "avp": [
          {
            "path": "Username",
            "value": "${test_imsi}"
          }
        ],
        "peer": "${hss1}"
      },
      {
        "host": "^$",
        "cmdappid": "^(16777251|16777216)$",
        "peer_list": {
          "peers": [
            "${hss1}",
            "${hss2}"
          ]
        }
      }
    ]
  }
]

Load balancing

This example shows how to distribute 3GPP S6a/d requests with no Destination-Host AVP to HSS

{
  cmdappid: "16777251",
  cmdshortname: "^(AIR\|ULR\|PUR\|NOR)$"
  host: "^$",
  peer_list: {
    peers: ["example.com/hss1.example.com", "example.com/hss2.example.com"]
  }
}

any matching usage

In this example the request will be forwarded to destination host if it starts with ‘hss’ AND:

  • Peer sending the request has 'example.com' as realm AND command application ID is 16777251 OR
  • Command application ID is 16777216
{
  host: "^hss",
  any: [
    {
      recv_peer: "^example\\.com/",
      cmdappid: "16777251"
    },
    { cmdappid: "16777216" }
  ],
  forward: true
}

Probabilistic distribution

In this example the request will be sent to ‘hss1.example.com’ with a probability of 60% or load balanced between HSS1 and HSS2

{
  host: "^$",
  cmdappid: "16777251",
  random: 60,
  peer: "example.com/hss1.example.com"
}
{
  host: "^$",
  cmdappid: "16777251",
  peer_list: {
    peers: ["example.com/hss1.example.com", "example.com/hss2.example.com"]
  }
}

Reject usage

{
  realm: "epc.mnc001.mcc001.3gppnetwork.org",
  routes: [
    // Match ULR for served IMSI range 
    {
      cmdcode: "316",
      avp: [
        {
          path: "Username",
          value: "^0010100000",
        },
      ],
      peer: "epc.mnc001.mcc001.3gppnetwork.org/hss1.epc.mnc001.mcc001.3gppnetwork.org"
    },
    // ULR for unknown IMSI
    {
      cmdcode: "316",
      // Override returned code with DIAMETER_REALM_NOT_SERVED
      //code: 3003,

      // Vendor specific error: DIAMETER_ERROR_USER_UNKNOWN
      //vendor_code: "5001/10415",

      // Vendor specific error: DIAMETER_ERROR_UNKNOWN_EPS_SUBSCRIPTION
      //vendor_code: 5420,
      //reject_add_avps: "<ErrorDiagnostic vendor=\"10415\">1</ErrorDiagnostic>",

      error_message: "IMSI not in our range"
    },
    // Set a message when rejecting everything else
    {
      error_message: "Sorry, no route!!!"
    },
  ]
}

appid usage

{
  realm: "epc.mnc001.mcc001.3gppnetwork.org",
  routes: [
      {
        // Handle 3GPP S6a/d interface with missing VendorSpecificApplicationID
        appid: "^$",
        cmdappid: "16777251",
        peer: "example.com/hss.example.com",
      },
      {
        // Reject failed or missing application id AVP
        appid: "^$",
      },
      {
        // Handle 3GPP S13 interface application with
        //  non 3GPP vendor or with app id set in wrong AVP
        appid: "^16777252(/.*)?",
        peer: "example.com/eir.example.com"
      }
  ]
}