# &adminguide;

## Overview

CDP (C Diameter Peer) allows Diameter communication to and from Kamailio. Most of the code is inherited from DISC http://developer.berlios.de/projects/disc/ and OpenIMS and modified for use within Kamailio. A few improvements and new functionality has been added along the way, for example, threshold reporting on Diameter calls that are serviced above a certain threshold.

## How it works

CDP forks the following processes:

- 1 x Timer

- 1 x Acceptor

- k x Workers (k configurable through configuration)

- i x Receivers (one for each peer plus one for unknown peers)

CDP is really only an API and offers all of its methods to other modules. No commands are made available to the main Kamailio configuration file. The exported API can be seen in mod.c. The Full Diameter API is in diameter.h and diameter_api.h. IMS-specific constants can be found in diameter_ims.h. The protocol coding is implemented in diameter_avp.c and diameter_msg.c. The diameter state machine is implemented in peerstatemachine.c - there is one of these for each peer which maintains all protocol/application state for each peer. peermanager.c is responsible for peer administration. Diameter transactions are implemented in transaction.c.

There are 2 configuration areas for CDP. Firstly it must be loaded and configured in the Kamailio.cfg file (this is the normal task associated with Kamailio modules). Then, an XML file is required to configure various Diameter parameters and all related peers and the associated routes.

## Dependencies

### &kamailio; Modules

The following modules must be loaded before this module:

- None.

### External Libraries or Applications

The following libraries or applications must be installed before running &kamailio; with this module loaded:

- None.

## Parameters

### config_file (string)

This is the location of the XML configuration file.

Default value is DiameterPeer.xml.

#### Set `config_file` parameter

    ...
    modparam("cdp", "config_file", "/etc/kamailio/diametercfg.xml")
    ...

### latency_threshold (int)

The time in ms above which a log error is written to log file for long CDP transactions.

Default value is 500.

#### Set `latency_threshold` parameter

    ...
    modparam("cdp", "latency_threshold", 1000)
    ...

### `workerq_latency_threshold` (int)

The time in ms above which a log error is written to log file for putting tasks into task queue.

Default value is 100.

#### Set `workerq_latency_threshold` parameter

    ...
    modparam("cdp", "workerq_latency_threshold", 250)
    ...

### `workerq_length_threshold_percentage` (int)

The threshold of the length of the worker queue as a percentage of the maximum queue size - when exceeded a warning is written to the log file. 0 means disabled

Default value is 0.

#### Set `workerq_length_threshold_percentage` parameter

    ...
    modparam("cdp", "workerq_length_threshold_percentage", 25)
    ...

### debug_heavy (int)

Flag to enable a more verbose log, which tells you more details about peers. This is disabled by default because it brings to a log too much verbose in DBG mode Can be enabled upon needs

Default value is 0.

#### Set `debug_heavy` parameter

    ...
    modparam("cdp", "debug_heavy", 1)
    ...

### enable_tls (int)

Flag to enable TLS for communication with all the peers.

Default value is 0.

#### Set `enable_tls` parameter

    ...
    modparam("cdp", "enable_tls", 1)
    ...

### tls_method (string)

Sets the TLS protocol method. Possible values are:

- TLSv1.3+ - TLSv1.3 or newer connections are accepted (available starting with openssl/libssl v1.1.1)

- TLSv1.3 - only TLSv1.3 connections are accepted (available starting with openssl/libssl v1.1.1)

- TLSv1.2+ - TLSv1.2 or newer (TLSv1.3, ...) connections are accepted (available starting with openssl/libssl v1.1.1)

- TLSv1.2 - only TLSv1.2 connections are accepted (available starting with openssl/libssl v1.0.1e)

- TLSv1.1+ - TLSv1.1 or newer (TLSv1.2, ...) connections are accepted (available starting with openssl/libssl v1.0.1)

- TLSv1.1 - only TLSv1.1 connections are accepted (available starting with openssl/libssl v1.0.1)

- TLSv1+ - TLSv1.0 or newer (TLSv1.1, TLSv1.2, ...) connections are accepted.

- TLSv1 - only TLSv1 (TLSv1.0) connections are accepted. This is the default value.

Default value is TLSv1.2.

#### Set `tls_method` parameter

    ...
    modparam("tls", "tls_method", "TLSv1")
    ...

### private_key (string)

Sets the private key file name.

#### Set `private_key` parameter

    ...
    modparam("cdp", "private_key", "/usr/local/etc/kamailio/my_pkey.pem")
    ...

### certificate (string)

Sets the certificate file name. Must be in PEM format.

#### Set `certificate` parameter

    ...
    modparam("cdp", "certificate", "/usr/local/etc/kamailio/my_certificate.pem")
    ...

### ca_list (string)

Sets the CA list file name. This file contains a list of all the trusted CAs certificates used when connecting to other SIP implementations. If a signature in a certificate chain belongs to one of the listed CAs, the verification of that certificate will succeed. If not set, the PCRF sent certificate is not checked.

The parameter must contain an absolute path. Only PEM files are accepted.

By default this parameter is not set.

An easy way to create the CA list is to append each trusted trusted CA certificate in the PEM format to one file.

#### Set `ca_list` parameter

    ...
    modparam("cdp", "ca_list", "/usr/local/etc/kamailio/ca_list.pem")
    ...

## Functions

### `cdp_check_peer(fqdn)`

The method checks, if a specific peer is connected and ready.

Meaning of the parameter is as follows:

- fqdn - the Fully qualified domain name of the peer, that should be checked. The parameter may contain pseudovariables.

#### `cdp_check_peer` usage

    ...
    if(!cdp_check_peer("hss.mnc001.mcc001.3gppnetwork.org")) {
    	send_reply("503", "HSS not ready");
    	exit;
    }
    ...

### `cdp_has_app([vendorid, ]application)`

The method checks, if any peer with this specific application has connected.

Meaning of the parameters are as follows:

- vendorid - The Vendor ID of the App

  application - The Application ID

#### `cdp_check_peer` usage

    ...
    if(!cdp_has_app("10415", "4")) {
    	send_reply("503", "Charging Server not ready");
    	exit;
    }
    ...

#### `cdp_check_peer` usage

    ...
    if(!cdp_has_app("16777216")) {
    	send_reply("503", "Cx/Dx Interface not ready");
    	exit;
    }
    ...

## RPC Commands

exported RPC commands.

### cdp.disable_peer

instantly disable a particular diameter peer.

### cdp.enable_peer

enable/re-enable a diameter peer

## Configuration Examples

### DiameterPeer.xml example

This is an example CDP configuration file. The location of this file is configured as a CDP parameter (config_file) - See section 4.1 Above

#### DiameterPeer.xml example

    <?xml version="1.0" encoding="UTF-8"?>
    <!--

     DiameterPeer Parameters
      - FQDN - FQDN of this peer, as it should appear in the Origin-Host AVP
      - Realm - Realm of this peer, as it should appear in the Origin-Realm AVP
      - Vendor_Id - Default Vendor-Id to appear in the Capabilities Exchange
      - Product_Name - Product Name to appear in the Capabilities Exchange
      - AcceptUnknownPeers - Whether to accept (1) or deny (0) connections from peers with FQDN
        not configured below
      - DropUnknownOnDisconnect - Whether to drop (1) or keep (0) and retry connections (until restart)
        unknown peers in the list of peers after a disconnection.
      - Tc - Value for the RFC3588 Tc timer - default 30 seconds
      - Workers - Number of incoming messages processing workers forked processes.
      - Queue - Length of queue of tasks for the workers:
         - too small and the incoming messages will be blocked too often;
         - too large and the senders of incoming messages will have a longer feedback loop to notice that
         this Diameter peer is overloaded in processing incoming requests;
         - a good choice is to have it about 2 times the number of workers. This will mean that each worker
         will have about 2 tasks in the queue to process before new incoming messages will start to block.
      - ConnectTimeout - time in seconds to wait for an outbound TCP connection to be established.
      - TransactionTimeout - time in seconds after which the transaction timeout callback will be fired,
        when using transactional processing.
      - SessionsHashSize - size of the hash-table to use for the Diameter sessions. When searching for a
        session, the time required for this operation will be that of sequential searching in a list of
        NumberOfActiveSessions/SessionsHashSize. So higher the better, yet each hashslot will consume an
        extra 2xsizeof(void*) bytes (typically 8 or 16 bytes extra).
      - DefaultAuthSessionTimeout - default value to use when there is no Authorization Session Timeout
      AVP present.
      - MaxAuthSessionTimeout - maximum Authorization Session Timeout as a cut-out measure meant to
      enforce session refreshes.

     -->
    <DiameterPeer
            FQDN="pcscf.ims.smilecoms.com"
            Realm="ims.smilecoms.com"
            Vendor_Id="10415"
            Product_Name="CDiameterPeer"
            AcceptUnknownPeers="0"
            DropUnknownOnDisconnect="1"
            Tc="30"
            Workers="4"
            QueueLength="32"
            ConnectTimeout="5"
            TransactionTimeout="5"
            SessionsHashSize="128"
            DefaultAuthSessionTimeout="60"
            MaxAuthSessionTimeout="300"
    >

            <!--
                    Definition of peers to connect to and accept connections from. For each peer found in here
                    a dedicated receiver process will be forked. All other unknown peers will share a single
                    receiver. NB: You must have a peer definition for each peer listed in the realm routing section
            -->
            <Peer FQDN="pcrf1.ims.smilecoms.com" Realm="ims.smilecoms.com" port="3868"/>
            <Peer FQDN="pcrf2.ims.smilecoms.com" Realm="ims.smilecoms.com" port="3868"/>
            <Peer FQDN="pcrf3.ims.smilecoms.com" Realm="ims.smilecoms.com" port="3868"/>
            <Peer FQDN="pcrf4.ims.smilecoms.com" Realm="ims.smilecoms.com" port="3868"/>
            <Peer FQDN="pcrf5.ims.smilecoms.com" Realm="ims.smilecoms.com" port="3868"/>
            <Peer FQDN="pcrf6.ims.smilecoms.com" Realm="ims.smilecoms.com" port="3868"/>

            <!--
                    Definition of incoming connection acceptors. If no bind is specified, the acceptor will bind
                    on all available interfaces.
            -->
            <Acceptor port="3868"  />
            <Acceptor port="3869" bind="127.0.0.1" />
            <Acceptor port="3870" bind="192.168.1.1" />

            <!--
                    Definition of Auth (authorization) and Acct (accounting) supported applications. This
                    information is sent as part of the Capabilities Exchange procedures on connecting to
                    peers. If no common application is found, the peers will disconnect. Messages will only
                    be sent to a peer if that peer actually has declared support for the application id of
                    the message.
            -->
            <Acct id="16777216" vendor="10415" />
            <Acct id="16777216" vendor="0" />
            <Auth id="16777216" vendor="10415"/>
            <Auth id="16777216" vendor="0" />

            <!--
                    Supported Vendor IDs - list of values which will be sent in the CER/CEA in the
                    Supported-Vendor-ID AVPs
            -->
            <SupportedVendor vendor="10415" />

            <!--
                    Realm routing definition.
                    Each Realm can have a different table of peers to route towards. In case the Destination
                    Realm AVP contains a Realm not defined here, the DefaultRoute entries will be used.

                    Note: In case a message already contains a Destination-Host AVP, Realm Routing will not be
                    applied.
                    Note: Routing will only happen towards connected and application id supporting peers.

                    The metric is used to order the list of preferred peers, while looking for a connected and
                    application id supporting peer. In the end, of course, just one peer will be selected.
            -->
            <Realm name="ims.smilecoms.com">
                    <Route FQDN="pcrf1.ims.smilecoms.com" metric="3"/>
                    <Route FQDN="pcrf2.ims.smilecoms.com" metric="5"/>
            </Realm>

            <Realm name="temp.ims.smilecoms.com">
                    <Route FQDN="pcrf3.ims.smilecoms.com" metric="7"/>
                    <Route FQDN="pcrf4.ims.smilecoms.com" metric="11"/>
            </Realm>
            <DefaultRoute FQDN="pcrf5.ims.smilecoms.com" metric="15"/>
            <DefaultRoute FQDN="pcrf6.ims.smilecoms.com" metric="13"/>

    </DiameterPeer>