# Sentinel VoLTE Administration Guide

Sentinel VoLTE - Version 3.1.0

This document covers procedures for deploying, configuring, and managing Sentinel VoLTE:

- Getting Started— how to install the product

- Features— the behaviour and configuration of each feature

- Mappers— the behaviour of mappers

- Mapping of GSMA IR.92 to Sentinel VoLTE Features— features that provide support for GSMA’s IR.92 specification

- Provisioning— how to provision and configure the Sentinel VoLTE product

- Sentinel VoLTE and Data— the various data sources for Sentinel VoLTE and how VoLTE is configured to use them

- Session Processing— how Sentinel VoLTE processes sessions, including Initial Filter Criteria, use of the HSS via Sh, and related topics

- Charging Information— describes the format and content of CDRs, and AVPs present in the Diameter Ro interface

- XCAP Server— how to configure the XCAP server

- Manual Upgrade Procedure— how to manually upgrade your Sentinel VoLTE version

- DNS Redundancy— how to configure DNS to provide a redundant configuration

- Feature Source— list of features that have source code available through the SDK

- Resource Adaptors— interfaces used by Sentinel VoLTE to communicate with external systems

- System Statistics— statistics defined for Sentinel VoLTE features

- License Requirements— license requirements for running Sentinel VoLTE

- Service Assurance Server (SAS) Tracing

- Enable Companion Device

| Read this document in conjunction with the Sentinel VoLTE Architecture document.

## Getting Started

This section explains how to set up a standalone version Sentinel VoLTE on a Rhino SDK.

In this section…​

- Preparing to Install Sentinel VoLTE— prerequisites needed to install Sentinel VoLTE services into Rhino

- Installing Sentinel VoLTE Services— how to install the Sentinel VoLTE services into Rhino

- Installing the Sentinel VoLTE Provisioning Module— how to (optionally) install the Sentinel VoLTE Provisioning module into the Rhino Element Manager

- Post Installation Instructions— configuration, updates, and other steps to perform after the installation

- Changing configuration post-installation— configuration changes made by the installer that may be changed after post-installation has completed

- Virtualized Deployment Requirements— Virtual environment specification and supported configurations

## Preparing to Install Sentinel VoLTE

| Artifactory This page refers to a public Artifactory instance that is no longer available. Please contact us via support if you require more information.

Before you install Sentinel VoLTE, you need to download the SDK package, get other required software.

You can then either:

- let the built-in installer install both the Rhino SDK and Sentinel VoLTE, or

- install and configure Rhino and the JVM manually, then use the installer to install Sentinel VoLTE into your Rhino

In both cases you need to get a license.

Allowing the installer to install both the Rhino SDK and Sentinel VoLTE software is recommended for functional testing or experimentation with Sentinel VoLTE. For production installs and/or load testing it is recommended to manually install and configure Rhino and the JVM.

Finally, if you are planning to install Sentinel VoLTE on an existing Metaswitch Rhino installation (for example, to use clustering), it makes sense to refer to other Metaswitch product dependencies

On this page…​

- Download the Sentinel VoLTE SDK package

- Get required software

- Know the TAS cluster DNS domain name

- Session Replication installation checklist

- Install and configure Rhino and the JVM

- Get a license

- Ports

- other Metaswitch product dependencies

### Download the Sentinel VoLTE SDK package

To get the latest Sentinel VoLTE SDK package go to https://repo.opencloud.com/artifactory/opencloud-sentinel-volte-3.1.0/opencloud/volte/3.1.0/sentinel-volte-sdk/ Choose the version with the highest release number.

The SDK package contains an installer, that can install Sentinel VoLTE as an out-of-the-box system. It is also an SDK allowing customisation of the product.

| You will need Metaswitch-supplied credentials to download the package.

### Get required software

You’ll need the following software to run Sentinel VoLTE:

Software | Download Link | Documentation Link
--- | --- | ---
Java JDK 8, update 172 or later | http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html |
Apache Tomcat 7.0.39 or greater (7.0.x series or 8.5.x series, not 9.x.x series) | http://tomcat.apache.org |
Rhino 2.7.0.0 or later - optional - to be used when installing and configuring Rhino manually | Rhino 2.7.0 SDK from Artifactory | Rhino Documentation
Rhino Element Manager 2.7.0.0 or later | REM Download Page | REM Documentation
Sentinel VoLTE SDK including out of the box installer | Sentinel VoLTE SDK, from Artifactory | Sentinel VoLTE SDK
Cassandra Database, version 3.11.2 or later version from the 3.11.x series. Cassandra is required for multiple functions including the SCC-AS, Rhino’s Session Ownership subsystem and the Rhino Key-value store subsystems. | http://cassandra.apache.org/download/ | http://cassandra.apache.org/doc/latest/getting_started/index.html

Note that it is not necessary to configure auto-start (e.g. systemctl or init.d) for Cassandra or Tomcat.

### Know the TAS cluster DNS domain name

The TAS needs to be able to resolve its own domain name as is defined in the IMS Initial Filter Criteria. This must be resolvable on all nodes in the cluster.

DNS is expected to be configured according to DNS SRV configuration.

The TAS domain name is asked for, in the `TAS cluster DNS domain name?` question during the Sentinel VoLTE application installation. For example, if the Initial Filter Criteria uses the Application Server URI `sip:tas-cluster.example.com;transport=tcp`, then the value entered should be `tas-cluster.example.com`. It is recommended that this domain name is resolvable prior to installation. The value can be adjusted after installation has completed, see: SIP SIS RA Network Interface changes.

### Session Replication installation checklist

Session Replication is optional and is supported through the use of various Rhino subsystems (first introduced in Rhino 2.6.1), and enhancements to various application components installed into Rhino.

| In order to install Sentinel VoLTE with Session Replication enabled, specific answers are required during both the Rhino production installation and Sentinel VoLTE application installation.

For the Rhino installation the questions and answers are:

1. the `Session Ownership Facility` question answered with value `True`

2. the `Replicated Storage` question answered with value `KeyValueDatabase`

3. the `Enable remote timer support?` question answered with value `True`

All three of these questions must be answered correctly, as they affect code generation for applications on top of Rhino. Once applications are installed, the generated code cannot change. Hence only a re-install can change these values.

During the Sentinel VoLTE application installation answer `Yes` to the `Session Replicated Enabled` question:

1. this question changes application configuration that can be updated post installation if desired (i.e. answering `Yes` or `No` does not preclude a later configuration change to enable/disable)

| The installer sets a SIP SIS RA configuration property (`DynamicSRVNameFormat`) if replication is enabled.

### Install and configure Rhino and the JVM

Optionally you can install and configure Rhino and the JVM for use with Sentinel VoLTE. This is recommended for production deployments, and clustered setups. It is required if using Session Replication. If using Session Replication, read the

Alternatively for Proof of Concept and lab functional testing it is recommended to use the Installer documented in Installing Sentinel VoLTE Services

If the installation is to use Session Replication, see the Session Replication installation checklist.

#### Install Rhino

1 | Start by choosing a location to extract the contents of the Rhino package. We’ll refer to this directory as `RHINO_HOME`.
2 | Rhino must be started at least once to generate the necessary configuration files. To start Rhino, in the `RHINO_HOME` directory, execute:
    ./start-rhino.sh
3 | Wait until Rhino is ready. It prints the following message in its log when ready:
    SLEE successfully started on node(s) [101]
4 | Stop Rhino by executing in the `RHINO_HOME` directory:
    ./stop-rhino.sh --node 101
(specifying the node ID of the local node)

| For more about installing and configuring the Rhino TAS, please see the Rhino 2.7.0 Documentation.

#### Configure Rhino and the JVM

If you want to install Sentinel VoLTE in top of an already running Rhino then this step must be performed. If you are letting the installer configure the Rhino SDK for you, this step can be skipped.

The following settings are needed:

Setting | Configuration
--- | ---
Management database size | For a full Sentinel VoLTE install, the default Rhino 2.6.1 management database size is insufficient and should be increased to at least 400MB. To do this, edit `RHINO_HOME/config/rhino-config.xml` on all nodes, increasing the `<committed-size>` in the following section:
        <memdb>
          <jndi-name>ManagementDatabase</jndi-name>
          <message-id>10003</message-id>
          <group-name>rhino-db</group-name>
          <committed-size>400M</committed-size>
          <stripe-count>1</stripe-count>
          ...
        </memdb>
JVM | You’ll also need to configure the JVM: For RhinoSDK: * The Rhino `HEAP_SIZE` setting should be set to 2560m at a minimum. * The recommended `MAX_NEW_SIZE` and `NEW_SIZE` setting for a Rhino node running Sentinel VoLTE is 1/4th of the total heap size (for example, 640m when the `HEAP_SIZE` is 2560m). All of these settings can be found in `RHINO_HOME/config/config_variables` after running Rhino for the first time. For Rhino Production: The configuration will depend on the expected traffic characteristics and the hardware configuration. There is no general rule for a production setup and each project installation will require specific analysis. Recommendations are: The Rhino `HEAP_SIZE` setting should be set to 6144m at a minimum. `TieredCompilation` is enabled by default in Java 8. It is recommended Sentinel VoLTE is run with a larger `CodeCache`. Use the JVM settings `-XX:ReservedCodeCacheSize=768m` and `-XX:InitialCodeCacheSize=768m`. These options will need to be set in environment variables, either in the `config_variables` file or the `read_config_variables` script.
Socket permissions | If running the installer remotely, you will need to add the host address where the installer is running to the mlet configuration file. In addition, you’ll need to add the address of any Rhino Element Manager hosts and any remote hosts from which you might access the Rhino console. For RhinoSDK the configuration file is `RHINO_HOME/config/mlet.conf` For Rhino Production the configuration file is `RHINO_HOME/node-xxx/config/permachine-mlet.conf` In the configuration file look for the xmltag `<security-permission-spec>` and add the following entry, replacing <IP ADDRESS> with your installer’s IP address:
    <mlets>
        <mlet enabled="true">
            <classpath>
                <jar-url>$${rhino.dir.base.url}/lib/jmxr-adaptor.jar</jar-url>
                <security-permission-spec>
    		.... other entries

    		permission java.net.SocketPermission "<IP ADDRESS>", "accept,resolve";

    		.... other entries
     	    </security-permission-spec>
            </classpath>
        </mlet>
    </mlets>

| Start Rhino to load the new configuration To start Rhino, in the `RHINO_HOME` directory run `./start-rhino.sh`. This applies the Rhino and JVM configuration.

### Get a license

| To install Sentinel VoLTE you need a license to run SIS, CGIN, and Sentinel VoLTE from Metaswitch. In order to obtain a license file, please contact Metaswitch. A full overview of license requirements can be found of this page: License Requirements.

If you allow the installer to install both Rhino SDK and Sentinel VoLTE for you, it will prompt you for the location of the license file.

If you prefer to set up Rhino manually, then you need to install the license file prior to installing Sentinel VoLTE.

To install your license file:

1 | Make sure Rhino is started and running.
2 | Go to the `RHINO_HOME/client/bin` directory.
3 | In this directory, start the Rhino Console with the `rhino-console` script (or `rhino-console.bat` in Microsoft Windows).
4 | In the Rhino Console execute, this command:
    installlicense [PATH_TO_LICENSE_FILE]
(`[PATH_TO_LICENSE_FILE]` should be relative to the `RHINO_HOME/client/bin` directory.)

### Ports

If using the standard configuration, the following ports need to be open on the VoLTE TAS host’s firewall.

Port | Purpose
--- | ---
5060 | SIP traffic
5061 | Secure SIP traffic
8080 | REM GUI
1199-1203 | RMI Access

If using other configuration the firewall should be configured for those non-standard ports. Other ports may be opened as needed. For example if ssh is used to administer a node, then port 22 would be opened

### Metaswitch product dependencies

Sentinel VoLTE is built on top of other Metaswitch products. The 3.1.0 series depends on the following series:

Product | Series
--- | ---
Rhino | 2.7.0.x
REM | 2.7.0.x
SIP | 2.7.0.x
CGIN | 2.0.0.x
SIS | 2.7.0.x
SIS-EM | 2.6.1.x
Diameter | 3.1.3.x
IM-SSF | 2.7.0.x
CDR-RA | 2.3.0.x
HTTP-RA | 2.5.0.x
DB-Query-RA | 1.4.0.x
FSM Tool | 1.3.0.x
CQL-RA | 1.2.0.x

## Installing Sentinel VoLTE Services

| Artifactory This page refers to a public Artifactory instance that is no longer available. Please contact us via support if you require more information.

Sentinel VoLTE is installed through the use of an installer program.

The installer can run in interactive and non-interactive modes - suitable for manual and automated installs respectively. When running in interactive mode it will prompt you for various necessary settings and save them.

| The installer will offer to install the Rhino SDK for you, or allow you to specify an existing Rhino installation. Once either a new Rhino SDK install, or an existing installation is selected the installer will install Sentinel VoLTE into your Rhino or Rhino SDK.

The installer configures a single node Sentinel VoLTE system, with a single peer for various other network elements such as:

- Media Resource Function (MRF)

- Interrogating Call Session Control Function (I-CSCF)

- Home Subscriber Server (HSS)

- Online Charging System (OCS), and/or Prepaid Service Control Point (SCP)

- Alternative options for storage of the Third Party Registration data

For more advanced configurations, such as clustering, or multiple signalling peers, it is recommended becoming familiar with the Rhino platform, SIS and Sentinel VoLTE products.

To install Sentinel VoLTE services in interactive mode:

1. Unzip sentinel-volte-sdk-VERSION.zip

2. Run the installer

For further information on installation read:

- Review the directories created for SIS and CGIN

- Review background information for the installer

- The Sentinel Installer

### 1. Unzip sentinel-volte-sdk.zip

To unzip `sentinel-volte-sdk.zip`:

1 | Copy the downloaded install zip file to a machine where Rhino and Sentinel VoLTE will run.
| It’s easiest if you create a new directory in the home directory.
    user@machine$ mkdir ~/sentinel-volte
2 | Unzip.
    user@machine$ cp ~/sentinel-volte-sdk.zip ~/sentinel-volte
    user@machine$ cd ~/sentinel-volte
    user@machine$ unzip sentinel-volte-sdk.zip

### 2. Run the installer

| The installer prompts you for various configuration settings, such as the SIP URI for the MRF. You can review and change settings prior to installation if you got something wrong the first time. Some of the answers can be reconfigured after installation, as described in the Changing configuration post-installation section. Finally, all questions which might be asked are described below, so that you can prepare any necessary information before performing the installation.

The install program is split into several "phases".

These are:

- initialisation of the environment

- question and answer (in interactive mode)

- several opportunities to review settings (in interactive mode)

- execution of installation

| The installer captures full logging from the various tools that it uses, and writes these logs into the sentinel-volte-sdk/build/target/log directory. This can be helpful when debugging issues.

NB: Before installing, if the host requires a proxy to access Artifactory then it must be configured in `sdk.properties`. `sdk.properties` can be found in the top-level directory of the unzipped package. Find the section marked with `# Proxy settings` and change it to the following:

    # Proxy settings
    #
    sdk.http.proxyHost=<proxy hostname here>
    sdk.http.proxyPort=<proxy port here>
    sdk.https.proxyHost<proxy hostname here>
    sdk.https.proxyPort=<proxy port here>
    #
    # These properties are used for both http and https.
    sdk.http.nonProxyHosts=localhost|127.0.0.1

To run the installer:

1 | The `installer` command is in the `build/bin` directory of the extracted Sentinel VoLTE SDK .
    testuser@machine$ cd ~/sentinel-volte/sentinel-volte-sdk
    testuser@machine$ build/bin/installer
The installer first initialises the environment. It typically shows output similar to the following
    Initialising the SDK ...
    Retrieving Installer dependencies ... done.
You may be prompted for Artifactory credentials, which should have been supplied to you by OpenCloud.
2 | Question and answer to determine necessary settings The installer will prompt the user for various values. A value inside square brackets, if present, is the default answer for that question. When the user presses the `Enter` key without entering any value the default is used if it is present. If the default isn’t present, the prompt will be repeated. In subsequent runs of the installer, the default will reflect the values that the user has previously entered. Explanations of all of the questions the installer will ask are laid out over the next few steps. Note that some of the questions will only appear under certain circumstances, so not all of them will be seen in a given installer run.
3 | Taking the SDK offline The user is prompted whether or not they want to take the SDK offline.
    You can optionally take the SDK offline by creating a local repository. This will take several minutes depending on connection speed, but will make subsequent retrievals much faster and remove the need for an internet connection.
    Do you want to take the SDK offline? y/[N] >
If the user presses the `Enter` key then the default of `N` is applied by the installer. This means that the SDK remains online, and will connect to the OpenCloud repositories on an as-needs basis. Answering yes will create a local Ivy repository that includes all of the remote artifacts required to build the SDK. The user is then presented with progress information related to the downloading of artifacts necessary to take the SDK offline. This process can take more than 30 minutes.
4 | Basic SDK Questions
    Your organization's name, e.g. Rocket Communications Inc.
    sdk.component.vendor [UNSET] >
This value will be used for the `vendor` portion of the SLEE Component ID for all SLEE components published by the SDK.
    sdk.component.version [1.0] >
This value will be used for the `version` portion of the SLEE Component ID for all SLEE components published by the SDK.
    The name of the platform operator, e.g. Rocket.
    sdk.platform.operator.name [UNSET] >
The name of the platform operator for the system. It is used extensively throughout configuration profiles.
    An Ivy organization field, recommended lower case with no whitespace e.g. "rocket".
    sdk.ivy.org [UNSET] >
This value is used as the `org` value for all Ivy artifacts created by the SDK.
    sdk.ivy.publish.revision [1.0.0] >
This value is used as the base of the `revision` value for all Ivy artifacts created by the SDK. Additional letters and numbers will be appended to it to identify specific releases, snapshots and milestones when an artifact is actually published.
5 | Install Rhino Questions
    You can either have the installer set up a Rhino SDK for you or point it at an existing Rhino installation, SDK or production.
    Note: If you want to use an existing Rhino installation it has to be running and a proper license has to be installed when finishing the installation after the configuration. Also make sure that you have adjusted the memory settings and created a tcapsim-gt-table.txt file as detailed in the documentation.
    Set up a Rhino SDK installation automatically? y/[N] >
If you allow the installer to set up a new Rhino SDK installation, it will prompt for a license file.
    Enter the path to your Rhino license file > /home/testuser/Downloads/opencloud.license
It then installs the Rhino SDK and starts it. If you instruct the installer to use an existing Rhino, the installer will prompt for the path to the Rhino client directory.
    Enter the path to your Rhino client directory > /home/testuser/rhino/2.6.1/client
If the associated installation is a Rhino production then additional information is required to complete configuration.
    You can either have the installer deploy against Rhino SDK or production.
    Does the specified client point to a production installation? y/[N] >
If you choose Yes, then the installer prompts for details of the cluster nodes and hosts.
    Enter your Rhino node setup.
    It has to be formatted like this: {nodeId,nodeId}host,{nodeId}host
    Examples:
      {101}localhost
      {101,102}host1,{103}host2
    Node setup [{101}localhost] > {101}hostname1,{102}hostname2
6 | Review settings Once the basic SDK configuration questions have been answered, the user is provided the opportunity to review and if happy, accept the settings.
| Settings are saved to disk, so that they can be read later.
    Review settings
    ***************

    Basic SDK properties
    ====================

      sdk.component.vendor: Rocket Communications Inc
      sdk.component.version: 1.0
      sdk.platform.operator.name: Rocket
      sdk.ivy.org: rocket
      sdk.ivy.publish.revision: 1.0.0

    ... edited for brevity

    Configuration changes written.
If the user presses the `n` key then the questions are asked again. Note that the list of configuration files that have been modified are printed out by the configuration portion.
7 | VoLTE mode The installer will ask several questions to determine which parts of Sentinel VoLTE to deploy.
    VoLTE can be deployed in four different ways: a basic developer mode, MMTel only, SCC only or both MMTel and SCC
    VoLTE mode [mmtel-scc] >
| The installer supports tab-completion to easily select the desired mode.
The basic developer mode only includes the core Sentinel VoLTE functionality, without any of the MMTel and SCC features. This mode is intended to be a bare-bones environment suitable for development of VoLTE-based applications that do not require any of the MMTel and SCC features. If the deployment includes SCC, the installer will ask whether to deploy the GSM or CDMA components.
    VoLTE SCC can be deployed in either GSM or CDMA mode
    SCC mode [gsm] >
Finally, if deploying MMTel only, the installer asks whether to deploy GSM components, so CAP charging and the SubscriberDataLookupFromHLR feature can be used.
    VoLTE MMTel can optionally deploy GSM components.
    Deploy GSM components? [Y]/n >
8 | Review settings Once the VoLTE mode questions have been answered, the user again gets the opportunity to review.
    Review settings
    ***************

    VoLTE mode
    ==========

      VoLTE mode: mmtel-scc
      SCC mode: gsm
      Deploy module: sentinel-volte-full-gsm-deploy

    Accept these values? [Y]/n >

    Configuration changes written.
9 | Creation of a deployment module The installer will now create a suitable deployment module. This may take several minutes.
10 | Home PLMN IDs Questions
    Home PLMN IDs >
The PLMN IDs for the home network. A PLMN ID is entered in the form (MCC,MNC), and multiple PLMN IDs are comma-separated. Example: (001,01),(001,001),(999,99)
11 | International and Roaming Network Questions
    Home domain >
A domain name for a home network.
    Home network prefix >
A corresponding network prefix for that home domain.
    Two letter ISO country code for the home network e.g 'SG'
    Home network ISO country code >
The ISO country code for the home network. Note that additional networks can be specified through the Determine International and Roaming Status feature configuration profile once setup is complete. See the Changing configuration post-installation section for more details.
12 | Play Announcement Questions
    Media server URI [sip:annc-audio@localhost:5260;lr;transport=tcp] >
The URI of the Media Resource Function (MRF). The hostname part should either be a resolvable name or the IP address of the MRF.
13 | Online Charging Questions
    Online charging involves realtime communication with an external charging system, e.g. to an OCS via Diameter Ro
    Enable online charging? [Y]/n > y
If the user enters `y` and the user selected a VoLTE mode containing the IM-SSF (any mode including GSM components) during the VoLTE mode step, the installer prompts for online charging options.
    This install allows online charging using either Diameter Ro or CAP. Enter the type you want with "ro" or "cap".
    Charging type [ro] >
The installer uses Diameter Ro by default if the user did NOT select a VoLTE mode containing the IM-SSF.
    Using Diameter Ro for online charging.
If the user chooses Yes and `ro`, then the installer prompts for details of Diameter Ro and CCA Questions in next step. Or if the user chooses Yes and `cap`, then the installer prompts for details of CAP Charging Questions in the CAP Charging (IM-SSF) step.
14 | Diameter Ro and CCA Questions (only if `ro` chosen during the online charging questions).
    This value is placed into the Origin-Host AVP.
    Host [diameterclient] >
The Diameter hostname for Sentinel VoLTE. It is used in the Origin-Host AVP of outgoing diameter messages.
    The Diameter Ro release used for online charging can be configured to one of the following release versions: V8d0, V960, Va00, Vb80, Vcb0
    Diameter Ro release [Vcb0] >
The Diameter release e.g (rel 12.11.0,Vcb0) used for online charging.
    This installer allows setting up a simple configuration with a single peer for the OCS. If you need a configuration with multiple peers, you can either do so after the installation finishes by following the Diameter documentation, or editing the following file now:
    [path-to-config-file]/DiameterConfig.xml
    Do you want to set up a simple configuration? [Y]/n >
If yes, the installer will provide a series of prompts for setting up a basic diameter configuration (where there is a single OCS server); if no, you will need to manually configure diameter peers for the charging system. More details about configuring Diameter Ro manually can be found in the Diameter Resource Adaptors Guide.
    Peer URI [aaa://diameterserver:3868;transport=tcp] >
URI of the online charging server.
    Diameter peer address [diameterserver] >
Diameter address of the online charging server.
    Realm name [example.com] >
Diameter Realm for the online charging system.
15 | Diameter Rf
    The Rf Control RA is used by interim CDR features to send accounting data to the CDF during offline charging interactions. Enabling this RA will implicitly enable interim CDRs.

    Disabling the Rf Control RA will prevent interim CDR features from interacting with the CDF, but they may still be configured to write interim CDRs to disk.
    Enable Rf Control RA? [Y]/n >
    This value is placed into the Origin-Host AVP.
    Host [diameterclient] >
The Diameter hostname for Sentinel VoLTE. It is used in the Origin-Host AVP of outgoing diameter messages.
    The Diameter Rf release used for offline charging can be configured to one of the following release versions: V8d0, V960, Va00, Vb80, Vcb0
    Diameter Rf release [Vcb0] >
The Diameter release e.g (rel 12.11.0,Vcb0) used for Rf.
    This installer allows setting up a simple configuration with a single peer for the CDF. If you need a configuration with multiple peers, you can either do so after the installation finishes by following the Diameter documentation, or editing the following file now:
    [path-to-config-file]/rf-control-ra-config.yaml
    Do you want to set up a simple configuration? [Y]/n >
If yes, the installer will provide a series of prompts for setting up a basic diameter configuration (where there is a single CDF); if no, you will need to manually configure diameter peers for the Rf system. More details about configuring Diameter Rf manually can be found in the Rf Control Resource Adaptor Guide.
    Peer URI [aaa://RfCDF:5898;transport=tcp] >
URI of the CDF.
    This address is only necessary if the host in the peer URI specified above is not resolvable. If it is then you can just accept the default value here.
    Peer address [RfCDF] >
Peer address of the CDF.
    Realm name [opencloud] >
Realm of the CDF.
16 | Call Detail Records (CDRs) (only if the VoLTE mode includes MMTel) If Rf was enabled during the Diameter Rf step interim CDRs will be enabled implicitly.
    Enabling interim CDRs implicitly due to Rf Control RA being enabled
Otherwise, an additional question will be asked regaring enabling interim CDRs. The advantages of interim CDRs are described in the Interim CDRs section.
    Interim CDRs are written to disk at the Start and End of a session, as well as periodically during the lifetime of a session.
    Enable interim CDRs? [Y]/n >
Regardless of whether or not interim CDRs have been enabled, the installer asks next if the user wants to enable session CDRs.
    Session CDRs are written to disk only at the end of a session.
    Enable session CDRs? y/[N] >
17 | CAP Charging (IM-SSF) (only if CAP has been chosen during the Online charging questions)
    Country code [65] >
The country code for the home network.
    Default media server address [sip:mrf@mrfhost.example:5060]>
Address of the media server (MRF) to be used by the IM-SSF.
18 | Sh Cache Microservice RA Questions
    The URL for the Sh Cache Microservice.
    Server URL [http://localhost:8088] >
The URL for the Sh Cache Microservice. This is what Sh Cache Microservice requests are sent to.
    Whether to use a proxy server.
    Proxy Enabled y/[N] >
If yes, the installer will next ask to configure the proxy server.
    The hostname of the proxy server.
    Proxy Host [localhost] >
Hostname of the proxy server.
    The port of the proxy server.
    Proxy Port [3128] >
Port of the proxy server.
19 | Sentinel Registrar Questions
    The registrar allows configuration to be specific to a particular node, which may be necessary for some settings like
    the ATU-STI. If a certain property is not found in a node-specific profile, or no profile exists for the current node,
    the registrar will fall back on the standard profile. This installer will configure the standard profile and add a
    node-specific profile for node 101. If you are using more than one node then you can edit the file
    [path-to-config-file]/RegistrarConfigurationTable.yaml after finishing the configuration in the installer, but before
    proceeding with the actual installation.

    ATU-STI [sip:localhost:5060] >
The Access Transfer Update - Session Transfer Identifier.
    Please enter the time (ms) to wait before we consider the ATCF update has failed
    ATCF Update Timeout [2000] >
Determines how long we wait before we consider an ATCF update to have failed.
    STN-SR [6421999999] >
The Session Transfer Number - Single Radio.
    Registration Data Storage can use either the HSS, or a Cassandra database. Specify the type you want with either "HssCache" or "Cassandra".
    Registration Data Storage type [Cassandra] >
Determines where the registrar will store third party registration data. Data can be stored in either the HSS, or a Cassandra database.
    Please enter a comma separated list of Cassandra contact points in the form "host1,host2"
    Cassandra Contact Points [localhost] >
Comma separated list of hostnames for the Cassandra database.
    Please enter the port Cassandra is listening on
    Cassandra Port [9042] >
The destination port for the Cassandra database server.
20 | Cassandra General Questions
    Session Ownership uses Cassandra to save session information that can be shared across nodes. Other features also use Cassandra

    Please enter a comma separated list of Cassandra contact points in the form "host1,host2"
    Cassandra Contact Points [localhost] >
Comma separated list of hostnames for the Cassandra database.
    Please enter the port Cassandra is listening on
    Cassandra Port [9042] >
The destination port for the Cassandra database server.
21 | SIP SIS RA Questions
    SIP SIS RA Host [localhost] >
The hostname for the server hosting Sentinel VoLTE.
    Please enter an optional DNS domain name for the TAS cluster.  This will be set as a virtual address in the SIP SIS RA.
    This name must resolve to an address, NAPTR, or SRV record on each cluster node.
    Enter "none" if you do not wish to configure this option now.
    Example: tas-cluster.example.com
    DNS name [none] >
This should be set to the DNS domain name used in IMS Initial Filter Criteria. E.g. `tas-cluster.example.com`.
22 | MMTel Conferencing Questions (only if the VoLTE mode includes MMTel)
    The URI of the Interrogating Call Session Control Function. The Conf and ECT features will automatically add an "lr" parameter to it. The hostname part should either be a resolvable name or the IP address of the I-CSCF.
    Example: sip:127.0.0.1:5054;transport=tcp
    I-CSCF URI [sip:icscf@icscfhost.example:5060] >
The URI of the Interrogating Call Session Control Function (I-CSCF).
    The URI of the Media Resource Function. The hostname part should either be a resolvable name or the IP address of the MRF.
    Example: sip:msml@127.0.0.1:5060
    MRF URI [sip:mrf@mrfhost.example:5060] >
The URI of the Media Resource Function (MRF) to be used as the conference bridge.
    Conference Factory PSI [sip:conf-factory@example.com] >
A Public Service Identifier that can be used by a subscriber to establish a conference call.
    The Conference MSML Schema Vendor Name. Used by the Conf feature to determine mapper selection when creating MSML documents for interaction with the MRF.
    Conference MSML Schema Vendor Name [Dialogic] >
The name of the vendor providing the conference MSML schema.
23 | ODB Questions
    Enable HSS IMS-ODB-Information query
    ====================================
    The SubscriberDataLookupFromHss feature does NOT query the Operator Determined Barring information (IMS-ODB-Information) by default.
    Enable HSS query for IMS-ODB-Information: y/[N]
Answering `y` will enable the Operator Determined Barring (ODB) query from the SubscriberDataLookupFromHss feature.
24 | Metaswitch TAS Services Questions
    Enable HSS Metaswitch-TAS-Services query
    ====================================
    The SubscriberDataLookupFromHss feature does NOT query the Metaswitch TAS Services information (Metaswitch-TAS-Services) by default.
    Enable HSS query for Metaswitch-TAS-Services: y/[N]
Answering `y` will enable the Metaswitch TAS Services query from the SubscriberDataLookupFromHss feature.
25 | IMCSI Configuration (only if the SCC mode is GSM and `cap` is chosen during the online-charging-questions
    When using CAP charging and GSM, the IMCSI can be fetched from the HLR and provided to the IMSSF in the originating and/or terminating case
    Enable IMCSI fetching in the originating case y/[N] >
    Enable IMCSI fetching in the terminating case y/[N] >
26 | CDMA HLR Configuration (only if the SCC mode is CDMA) The following questions concern the HLR configuration. For an overview of Terminating Access Domain Selection (T-ADS) see Terminating Access Domain Selection (T-ADS) and Terminating Access Domain Selection Features.
    By default SCC TADS Routing uses the CMSISDN from the HSS, but it can also be configured to use the TLDN from the HLR.
    Use MSRN for SCC TADS Routing? y/[N] >
The following questions only get asked if the option above has been chosen.
    The SCCP address of the HLR.
    Example: type=A7,ri=pcssn,pc=1-1-1,ssn=101,national=true
    HLR address [type=A7,ri=pcssn,pc=1-1-1,ssn=101,national=true] >

    The SCCP address of the Sentinel VoLTE AS.
    Example: type=A7,ri=pcssn,pc=1-1-2,ssn=102,national=true
    Originating Sentinel address [type=A7,ri=pcssn,pc=1-1-2,ssn=102,national=true] >

    The address of the MLC (Sentinel).
    Example: address=222,nature=INTERNATIONAL,numberingPlan=ISDN
    MLC address [address=653333333,nature=INTERNATIONAL,numberingPlan=ISDN] >

    The timeout value for opening the dialog with the HLR (in milliseconds).
    Invoke timeout [4000] >

    The market ID value to be used in the MSCID set on outgoing CDMA requests to the HLR
    Market ID [1] >

    The switch number value to be used in the MSCID set on outgoing CDMA requests to the HLR
    Switch Number [1] >
27 | GSM HLR Configuration (only if the VoLTE mode includes the GSM components) The following questions concern the HLR configuration. For an overview of Terminating Access Domain Selection (T-ADS) see Terminating Access Domain Selection (T-ADS) and Terminating Access Domain Selection Features.
    By default SCC TADS Routing uses the CMSISDN from the HSS, but it can also be configured to use the MSRN from the HLR.
    Use MSRN for SCC TADS Routing? y/[N] >
The previous question is only asked if the VoLTE mode includes SCC; the next question is asked if the the VoLTE mode includes MMTel.
    The HLR can be used to try to determine the roaming status of a subscriber by sending an ATI query to it.
    Determine roaming from HLR y/[N] >
The following questions only get asked if the HLR is required by answers to previous questions.
    The SCCP address of the HLR.
    Example: type=C7,ri=pcssn,pc=6,ssn=143,national=false
    HLR address [type=C7,ri=pcssn,pc=6,ssn=143,national=false] >

    The SCCP address of the Sentinel VoLTE AS.
    Example: type=C7,ri=gt,digits=653333333,gti=4,nature=international,numbering=isdn,tt=0,national=true
    Originating Sentinel address [type=C7,ri=pcssn,pc=7,ssn=157] >

    The address of the MLC (Sentinel).
    Example: address=222,nature=INTERNATIONAL,numberingPlan=ISDN
    MLC address [address=653333333,nature=INTERNATIONAL,numberingPlan=ISDN] >

    The timeout value for opening the MAP dialog with the HLR (in milliseconds).
    Invoke timeout [5000] >
28 | T-ADS Questions (only if the VoLTE mode includes SCC)
    LTE (E-UTRAN) is an allowed PS access network technology. You can also configure WLAN to be an allowed access network.
    Allow WLAN access? y/[N] >
Answering 'yes' will allow subscribers to use WiFi as an access network.
29 | Session Replication Questions
    Session replication can be enabled for two-party MMTel and SCC calls upon receipt of the initial INVITE ACK from the calling party.
    Enable session replication? y/[N] >
Answering 'yes' will enable session replication on all established two-party calls on the MMTel and SCC AS instances.
30 | Review settings Once all questions have been answered, the user is provided the opportunity to review and if happy, accept the settings.
| settings are saved to disk, so that they can be read later.
    Review settings
    ***************

    ... edited for brevity

    MMTel Conferencing
    ==================

      I-CSCF URI: sip:192.168.10.1:5054;transport=tcp
      MRF URI: sip:192.168.10.17
      Conference Factory PSI: sip:conf-factory@example.com

    Play Announcements
    ==================

      Media server URI: sip:annc@192.168.10.17:5060

    Accept these values? [Y]/n > y

    ... edited for brevity

    Configuration changes written.
If the user presses the `n` key then the questions are asked again. Note that the list of configuration files that have been modified are printed out by the configuration portion.
31 | Execution phase Now that the installer has gathered all necessary information it provides the user with the option to install the VoLTE TAS now.
    Install now? [Y]/n >
If the user wants to install at a later time, they can press the `n` key. The installer exits having saved settings that the user has entered. I.e. the installer can be run later if desired.
    Installing Rhino ... done.
    Starting Rhino in the background ... done.
    Publishing deployment module deploy-volte ... done.
    Deploying; this is going to take a while ... done.
    Binding; this is going to take a while ... done.
    Configuring; this is going to take a while ... done.
    Running post-installation tasks ... done.
    Installation completed successfully in 32 minutes and 19 seconds. Rhino has been left running to finish applying configuration changes.

    The configuration has been saved to the file {sdk-path}/install.properties. This file can be used to re-run the installation non-interactively with the same settings.
The installation has now completed successfully.

| A properties file is automatically created when the interactive installer is run. This file is located in the `sentinel-volte-sdk` directory and named `install.properties`. In this way an interactive installations settings are saved, and can be distributed through the `install.properties` file. You can later use this file for a new installation using the Non-interactive mode. Save this file for future upgrade procedure as instructed here and here.

### Non-interactive mode

To run the installer in non-interactive mode a properties file is passed to the installer program

    testuser@machine$ cd ~/sentinel-volte/sentinel-volte-sdk
    testuser@machine$ ./build/bin/installer -p my-install.properties

### SIS and CGIN

During installation SIS and CGIN versions are extracted into the SDK directory structure. This is so that SIS can be configured as necessary.

The CGIN connectivity pack is extracted into the `sentinel-volte-sdk/cgin/cgin-connectivity-full-CGIN_VERSION` directory. The SIS is extracted into the `sentinel-volte-sdk/sis/SIS_VERSION` directory. Here `CGIN_VERSION` and `SIS_VERSION` are the release versions for each product respectively (e.g. 2.0.0.0 and 2.7.0.0)

The SIS console command is located at `sentinel-volte-sdk/sis/SIS_VERSION/admin/sis-console`.

### Background information

#### The installer sits on top of the Sentinel VoLTE SDK infrastructure

The installer works by creation of a "deployment module" for Sentinel VoLTE. This module name is "deploy-volte" and it is located in the root of the Sentinel VoLTE SDK directory.

A deployment module can be created through the use of the sdkadm create-deployment-module command. The values that the user enters (or passes in when using non-interactive mode) are written into the various configuration files in this deployment module.

The deployment module is then published, and the deployer, binder and configurer are invoked in order to install/bind/configure the application in Rhino.

This means that the the installer is part of the Sentinel VoLTE SDK, and that there is no technology difference between the SDK and an "off the shelf install". Therefore custom configurations can easily be made through modification of the deployment module, and publishing it, and running the configurer.

### Installer log files

The installer captures full logging from the various tools that it uses, and writes these logs into the sentinel-volte-sdk/build/target/log directory. This output is more verbose than the user sees when running the installer.

Each time an install is done, files called installer.log and installer.rhino.log are created in this directory. If there is a previous installer.log file, that it is moved to installer_date.log (and similarly for installer.rhino.log). The value of "date" is the time of the last write timestamp in the file.

Therefore running the installer three times results in three installer.log files.

## Post-Installation Instructions

### Update XCAP server

To configure the XCAP Server for Sentinel VoLTE, you need to populate XCAP server settings and MMTel service data. You may optionally enable XCAP authentication using Sentinel AGW.

### Populate XCAP server settings and MMTel service data

There are several configuration items for the administrative User Interface (in REM) related to XCAP connectivity and MMTel service data mappings.

These include:

- the XCAP server configuration, such as

  - Sh Cache Microservice stack configuration

  - XPaths used to map between the UE’s "simservs" document and the HSS "MMTel-Services" document

  - any extension configuration to expand the standard Simservs document

- the REM Web UI for viewing and editing Transparent Data in the HSS, such as

  - the MMTel-Services document (for example Communication Diversion, Communication Barring etc)

  - the IMS-ODB-Information document used for Operator Determined Barring

  - the Metaswitch-TAS-Services document used for additional subscriber configuration

This can either be done manually following the admin guide, or more easily using the script `sentinel-volte-mappings-config`. This file is located in the `build/bin` directory of the Sentinel VoLTE SDK.

This can be executed from your VoLTE TAS’s command line, provided the Java Runtime Environment (v 7+) is installed. The command must be given these arguments:

Mandatory Arguments | What it specifies
--- | ---
    -u (--username)
| Your Rhino Element Manager (REM) username.
    -pw (--password)
| Your Rhino Element Manager (REM) password.
    -h (--hostname)
| The hostname or IP address of your Rhino Element Manager (REM).
    -p (--port)
| The port of your Rhino Element Manager (REM).
    -n (--network-operator)
| The network operator name.
    -r (--rhino-instance-id)
| The Rhino Instance ID.
    -s (--serverurl-shcm)
| The URL for the Sh Cache Microservice
Optional Arguments | What it specifies
    -sph (--shcm-proxy-host)
| The proxy host used to connect to the Sh Cache Microservice
    -sph (--shcm-proxy-port)
| The proxy port used to connect to the Sh Cache Microservice
    -x (--xcap-mapping)
| Additional MMTel-Services XCAP Simservs mappings. Must be in the format `-x "<simservsPath>;<mmtelPath>"`. Can be specified multiple times. e.g. `-x "<simservsPath1>;<mmtelPath1>" -x "<simservsPath2>;<mmtelPath2>"`
    -m (--metaswitch-xcap-mapping)
| Additional Metaswitch-TAS-Services XCAP Simservs mappings. Must be in the format `-x "<simservsPath>;<metaswitchTasServicesPath>"`. Can be specified multiple times. e.g. `-m "<simservsPath1>;<metaswitchTasServicesPath1>" -x "<simservsPath2>;<metaswitchTasServicesPath2>"`
    -im (--include-mappings)
| Explicitly designate what Subscriber Data and XCAP mappings to include in a comma delimited list while implicitly excluding other mappings. Valid options include 'msw' = Metaswitch-TAS-Services, 'odb' = IMS-ODB-Information, 'mmtel' = MMTEL-Services
    -ah (--additional-host-mappings)
| Additional XCAP host names (in addition to the one specified with -h or --hostname), can be specified multiple times
    -o (--override)
| Will override all existing mappings with the currently provided options

Here is an example command:

    cd ~/sentinel-volte/sentinel-volte-sdk
    ./build/bin/sentinel-volte-mappings-config -u emadm -pw password -h localhost -p 8080 -r Local -n Metaswitch -s http://localhost:8088/shcache/v1

| To see a listing of the required arguments, from the command line, execute the JAR file without any arguments.

| The tool can also be run from the Sentinel AGW SDK inside the `sentinel-gaa-sdk` directory.

### Enable XCAP authentication using Sentinel AGW

By default the XCAP Server assumes that requests will be authenticated externally using an Authentication Proxy (AP). If this is the case, no further configuration is required.

If an AP is not suitable or available, the XCAP server can be configured to authenticate requests itself using OpenCloud Sentinel AGW. Sentinel AGW provides an implementation of 3GPP GAA (Generic Authentication Architecture) procedures.

For more information, and instructions on configuring the XCAP Server with Sentinel AGW, see the Sentinel AGW Guide.

### OpenIMS HSS

If you’re using the OpenIMS HSS, you’ll need to specify the interface (IP address and port values) that it uses:

1 | Edit the `DiameterPeerHSS.xml` file in the `/path/to/HSS/FHoss/deploy` directory.
2 | Find the `Acceptor` XML element.
3 | Change its `binding` to the desired IP address (or host name).
4 | Change its `port` values to the desired port.

### Create init.d scripts

There are two `init.d` scripts for Ubuntu Linux which make starting and stopping Rhino and REM easier (linked below):

- rhino— for Rhino

- rem— for REM running on Apache Tomcat

Note: These are illustrative and useful for Proof of concept rather than production environments.

To set these up:

1 | Copy the script to the host server’s `/etc/init.d/` folder:
    sudo cp rhino /etc/init.d
2 | Make the script executable:
    sudo chmod +x /etc/init.d/rhino
3 | Refresh, with the `update-rc.d` command:
    sudo update-rc.d rhino defaults 99

### Rhino SAS Configuration

To enable Rhino to send events to MetaView Service Assurance Server (SAS), refer to Enabling VoLTE SAS tracing

### Provision Location Based Dialling Data

Tools are provided to provision and verify data mappings for the LocationBasedDialling feature.

`lbd-provision` and `ldb-verify` are located in the `build/bin` directory of the Sentinel VoLTE SDK.

#### lbd-provision

This tool takes a .csv file as input and populates the `location_based_dialling_data_3gpp` table in Cassandra with the data.

Mandatory Arguments | What it specifies
--- | ---
    -c
| Comma separated list of Cassandra contact points.
Optional Arguments | What it specifies
    -p
| Cassandra port (defaults to 9042 if omitted).
    -f
| Input CSV file.
    -d
| Dryrun, no data in Cassandra will be modified.
    -i
| Reset, Cassandra data will be overwritten with input file.
    -b
| Rollback, second most recent stored data will be restored.
    -h
| Help

The input CSV file must be comma separated with no header row. Each line should be in the following format `<cell-id>,<dialled-number>,<destination-number>`. Whitespaces and empty lines are ignored. Valid characters for `dialled-number` and `destination-number` entries are: `0-9`, `#`, and `*`.

`lbd-provision` will fetch the existing data in cassandra and perform a diff with the content of the input CSV file. New entries in the input file not present in the database are added. Current entries not in the input file are removed. If the `-i` option is used, all data is overwritten with the content of the input file.

Each time `lbd-provision` is run the dataset is stored in the `location_based_dialling_uploaded_files` table. The `-b` option can be used to rollback to the previous data set. The `location_based_dialling_uploaded_files` table has to have been loaded with previous runs of `lbd-provision` before rollback can be used. If `-b` is run twice, the original record set is returned, so effectively it toggles between the current and previous data sets. If the `-b` option is not used, `-f` must be provided.

Here is an example:

    $ cat lbd-provision-test-data.csv
    testdata0,717,4165550000
    testdata1,718,4165550001
    testdata2,719,4165550002
    $
    $ ./lbd-provision -c localhost -f lbd-provision-test-data.csv -i
    Saving Cassandra contact points: localhost
    Saving input file: /home/ubuntu/lbd-provision-test-data.csv
    Setting reset flag
    Connected to Cassandra
    Sorted file to: /home/ubuntu/work/input-sorted.csv
    Processing input file to update Cassandra: /home/ubuntu/work/input-sorted.csv
    Creating entry: testdata0,717,4165550000
    Creating entry: testdata1,718,4165550001
    Creating entry: testdata2,719,4165550002
    Removing all data from table: location_based_dialling_data_3gpp
    Creating data in: location_based_dialling_data_3gpp
    Updated Cassandra with entire input file
    Not deleting old rows as less than 3 files saved

    SUCCESS

| The lbd-provisioning tool can provision up to 5 million rows. Functionality beyond this number of rows is not supported.

#### lbd-verify

This tool queries the existing data in Cassandra and the Vertical Service Code profiles in Rhino and checks that each entry exists in both places.

Mandatory Arguments | What it specifies
--- | ---
    -c
| Comma separated list of Cassandra contact points.
    -r
| Rhino client directory.
Optional Arguments | What it specifies
    -p
| Cassandra port (defaults to 9042 if omitted).
    -h
| Help

Here is an example:

    $ ./lbd-verify -c localhost -r RhinoSDK/client
    Saving Cassandra contact points: localhost
    Saving rhino client: /home/ubuntu/RhinoSDK/client
    Connected to Cassandra
    Found dialled number: 717
    Found dialled number: 718
    Found dialled number: 719
    Found platformOperator: Metaswitch
    Found address: 718
    Found address: 717
    Found address: 719

    SUCCESS: All data in Cassandra and profiles matches

### Restart Rhino

Finally, restart Rhino by executing the following commands in a terminal, from the Rhino install directory.

    ./stop-rhino.sh --node 101
    ./start-rhino.sh

| If you chose to set up the Rhino `init.d` script, you can use these commands to stop and start it.

## Init.d Sample Scripts for VoLTE

| These sample scripts are illustrative init.d scripts for Rhino and REM

For production installations use production Rhino’s own init.d scripts rather than these.

### Sample Rhino script

    #!/bin/bash
    #
    # Manage the Rhino SLEE.
    # Put this file in /etc/init.d and symlink that in /etc/rc?.d

    RHINO_HOME=/home/ubuntu/sentinel-volte-sdk/rhino-sdk/RhinoSDK
    RHINO_USER=ubuntu

    case "$1" in
    start)
    	# This command will fail nicely if that file is not there, so
    	#  checking for that file's existence is not necessary.
            echo "Starting the Rhino SLEE"
    	sudo su - ${RHINO_USER} -c ${RHINO_HOME}/start-rhino.sh > /dev/null 2>&1 &
            # logs will be in ${RHINO_HOME}/work/log
    	;;

    stop)
            echo "Stopping the Rhino SLEE"
            [ -d ${RHINO_HOME} ] && [ -x ${RHINO_HOME}/stop-rhino.sh ] \
    	    && ${RHINO_HOME}/stop-rhino.sh --nice
    	;;

    *)
    	echo "Usage: $0 { start | stop }"
    	exit 1
    	;;
    esac
    exit 0

### Sample REM script

    #!/bin/sh
    #
    # Rhino Element Manager start/stop script.
    #
    #

    # Location of the Rhino Element Manager
    REM_HOME=/home/ubuntu/sentinel-volte-sdk/rhino-sdk/RhinoSDK/apache-tomcat-*
    RHINO_USER=ubuntu

    usage()
    {
        echo "Usage: $0 {start|stop}"
        exit 1
    }

    #
    # Main
    #

    # Parameter check

    [ $# -gt 0 ] || usage

    case "$1" in
      start)
            # Start REM
            sudo su - "$RHINO_USER" -c "$REM_HOME/bin/catalina.sh start"
            echo "REM Starting"

            ;;

      stop)
            # Stop REM
            sudo su - "$RHINO_USER" -c "$REM_HOME/bin/catalina.sh stop"
            echo "REM Stopping"
            ;;

      *)
            usage
            exit 2
            ;;

    esac

    exit 0

## Changing configuration post-installation

On this page we explain how the answers given to the various questions asked by the installer affect the configuration of the Sentinel VoLTE SDK, and how this configuration can be changed without reinstalling the Sentinel VoLTE SDK.

Where changes to profile tables do not specify an explicit profile, the change is made to the profile `${platform.operator.name}::::`.

Please note that some parts of the installer do not require user input, hence some of the sections below do not appear in the installer.

### Basic SDK questions

#### Property file changes

The following values are written to `sdk.properties`, based on the answers given to their respective questions:

- `sdk.component.vendor`,

- `sdk.component.version`,

- `sdk.platform.operator.name`,

- `sdk.ivy.org`, and

- `sdk.ivy.publish.revision`.

#### Notes

These values are used in various places throughout the remainder of the installer (e.g. when determining profile names). It is therefore not recommended to change any of these values.

### Rhino

#### Property file changes

The following values are written to `sdk.properties`:

- `client.home` is set to the configured Rhino client directory, and

- `rhino.home` is set to the parent directory of the configured Rhino client directory.

#### Notes

These values can be changed after installation.

If using the Sentinel VoLTE SDK installer to install Rhino automatically, Rhino uses the supplied license file.

The Rhino node setup is used later during the installation.

### Deploy module

#### Configuration profile changes

Many, see notes.

#### Notes

This question determines which features are deployed (this always includes the core features, and can include MMTel and SCC features) and whether the GSM or CDMA features are deployed. Only the chosen features, with their configurations, are deployed. This setting cannot be changed without a reinstall of the Sentinel VoLTE SDK.

### Home PLMN IDs

#### Configuration profile changes

The installer creates a profile in `HomePlmnIdConfigProfileTable` for every configured MCC, with all the MNCs configured for this particular MCC.

#### Notes

These values can be changed after installation.

### Determine international and roaming status

#### Configuration profile changes

The installer create two kinds of profiles, one named `DEFAULT` and one named after every configured home network MCC, in:

- `${platform.operator.name}_DetermineInternationalAndRoamingStatus_AddressListEntryTable`, and

- `${platform.operator.name}_DetermineInternationalAndRoamingStatus_AddressListConfigurationTable`.

These profiles are initialised using the configured home PLMN IDs from the Home PLMN IDs section.

Furthermore, it sets the following value in the `SipSentinelConfigurationTable` profile table:

- `HomeNetworkIDs` is set to the home domain.

Finally, the `NormalizationFeatureConfigProfileTable` is updated as follows:

- `CountryCode` is set to the configured home network prefix.

#### Notes

All values can be changed after installation. Furthermore, more profiles can be added to `${platform.operator.name}_DetermineInternationalAndRoamingStatus_AddressListEntryTable` and `${platform.operator.name}_DetermineInternationalAndRoamingStatus_AddressListConfigurationTable`, using the installer-created profiles as a prototype.

### Play announcements

#### Configuration profile changes

The installer sets `MediaServerURI` in the `SipAnnouncementResourceProfileTable` to the supplied media server URI.

#### Notes

The media server URI can be changed after installation.

### Online charging

#### Configuration profile changes

If using Diameter Ro online charging, the `DestinationRealm` in the `DiameterMediationOcsConfigurationTable` is set to the value chosen for the destination realm during the Diameter configuration.

#### Resource adaptor configuration changes

If not using Diameter Ro online charging, the `diameterro-0` resource adaptor is deactivated.

#### Notes

The online charging mode can be changed after installation, if the new charging mode is manually configured as detailed below.

### Diameter (RO & CCA)

#### Configuration profile changes

The installer sets `Host` in the `DiameterConfig` profile table to the supplied host.

If using the installer to set up a simple configuration, all profiles in the `DiameterConfig` profile table, except the default profile (the nameless profile), are updated as follows:

- `PeerTable` is updated using the supplied peer URI and address,

- `Realm` is set to the configured realm name, and

- `RealmTable` is updated using the supplied realm name and peer URI.

If setting up a simple configuration, and deploying against a production Rhino (as configured in the Rhino step), we additionally set in the same profiles:

- `EnableMultiNodeConfig` is set to the `EnableMultiNodeConfig` value of the `DiameterRoOcsProfile` (default `false`),)

- `NodeIDs` is set using the node configuration from the Rhino step, and

- `PerNodeHosts` is set using the node configuration from the Rhino step.

Finally, the installer sets `DisableCharging` in the DetermineChargingConfigProfileTable to `false` exactly if Diameter Ro online charging was selected in the Online charging step.

#### Resource adaptor configuration changes

The field `3GPPVersion` in the `diameterro-0` resource adaptor configuration is set to the configured version.

If Session Replication is enabled, the following `diameterro-0` resource adaptor configuration properties are adjusted:

- `ReplicateActivities` is set to `true`

- `ReplicateByDefault` is set to `false`

#### Notes

The configuration can be changed after installation.

### Diameter Rf

#### Configuration profile changes

The installer sets `host` in the `client` profile of the `RfControlDiameterConfiguration` table to the supplied host.

If using the installer to set up a simple configuration, all profiles in the `RfControlDiameterConfiguration` profile table are updated as follows:

- `PeerTable` is updated using the supplied peer URI and address,

- `Realm` is set to the configured realm name, and

- `RealmTable` is updated using the supplied realm name and peer URI.

#### Resource adaptor configuration changes

The `rf-control-ra` resource adaptor configuration is updated as followed:

- `3GPPVersion` is set to the configured version.

Additionally, if using the installer to set up a simple configuration:

- `DestinationHost` is set to the peer host, and

- `DestinationRealm` is set to the realm name.

Finally, if not using Diameter Rf, the `rf-control-ra` resource adaptor is deactivated.

#### Notes

The configuration can be changed after installation. If enabling Diameter Rf after installation, please also make the required changes in the Call detail records (CDRs) step.

### Call detail records (CDRs)

#### Configuration profile changes

The installer makes the following changes in the `DetermineChargingConfigProfileTable` profile table:

- `InterimCdrsEnabled` is set to `true` exactly if interim CDRs have been enabled, and

- `SessionCdrsEnabled` is set to `true` exactly if session CDRs have been enabled.

Similarly, the installer makes the following changes to all profiles in the `SipInterimCdrProfileTable` profile table:

- `UseCdrRa` is set to `true` exactly if interim CDRs have been enabled, and

- `UseRfControlRa` is set to `true` exactly if Diameter Rf has been enabled in the Diameter Rf step.

#### Notes

These values can be changed after installation, keeping in mind that interim CDRs should be enabled if Diameter Rf is enabled.

### CAP charging (IM-SSF)

#### Property file changes

The properties file `imssf-install.properties` is updated as follows:

- `imssf.countrycode` is set to the supplied country code, and

- `imssf.default.mediaserver.address` is set to the supplied default media server address.

#### Notes

These values can be changed after installation as detailed in the IM-SSF documentation.

### Sh Cache Microservice RA

#### Configuration profile changes

The following values are set in the `sh-cache-microservice-ra` resource adaptor configuration:

- `serverURL` is set to the URL for the Sh Cache Microservice

- `proxy.enabled` is set to true if a proxy has been enabled, and

- `proxy.host` and `proxy.port` are set to the configured proxy values (if enabled).

#### Notes

`DestinationRealm` can be changed after installation, but changing `DestinationHost` is not recommended.

### Sentinel registrar

#### Configuration profile changes

The installer sets the following values in the `RegistrarConfigurationTable` profile table:

- `AtuSti` is set to the configured ATU-STI,

- `AtcfUpdateTimeout` is set to the configured ATCF update timeout,

- `StnSr` is set to the configured STN-SR, and

- `SubscriberDataFacadeType` is set to the chosen registration data storage type.

Additionally it will set one value on the `VolteServiceConfigProfileTable` profile table:

- `RegistrationDataSource` will be set to either `HSS` or `CASSANDRA`.

Furthermore, a prototype profile `${platform.operator.name}:::::101` is created in the same profile table, with a single entry:

- `AtuSti` is set to the configured ATU-STI.

#### Resource adaptor configuration changes

If Cassandra has been chosen for the registration data storage, the installer enables the `cassandra` resource adaptor, and sets the following values in the `cassandra-third-party-reg` resource adaptor configuration:

- `cassandraContactPoints` is set to the configured Cassandra contact points, and

- `policy.protocol.port` is set to the configured Cassandra port.

If Cassandra has not been chosen for the registration data storage, the installer disables the `cassandra-third-party-reg` resource adaptor.

#### Notes

It is not recommended to change the data storage type after installation. However, the details for the chosen storage type can be altered. Furthermore, the `${platform.operator.name}:::::101` profile can be used as a prototype for adding additional nodes.

### Cassandra

#### Resource adaptor configuration changes

The installer sets the following values in the `cassandra-general` resource adaptor configuration:

- `cassandraContactPoints` is set to the configured Cassandra contact points, and

- `policy.protocol.port` is set to the configured Cassandra port.

#### Notes

These values can be changed after installation.

### SIP SIS RA

#### Resource adaptor configuration properties

The `sis-sip-ra` entity has the following properties set:

- `RFC3263:failover_enabled` is set to `true`

- `RFC3263:failover_timer` is set to `10000`

- `RFC3263:blacklist_timer` is set to `300000`

#### Network Interface changes

The DNS domain name specified during installation will be set:

- in the `VirtualAddresses` configuration property for the network interface (named `sip-sis-ra-default`) of the `sip-sis-ra` resource adaptor entity.

Additionally, if session replication was specified during installation, the Dynamic SRV Name format will be set:

- in the `DynamicSRVNameFormat` configuration property for the network interface (named `sip-sis-ra-default`) of the `sip-sis-ra` resource adaptor entity

  - If the TAS domain name is tas.example.com then this is set to the value `node-${ip}.tas.example.com`.

If the Dynamic SRV Name was not specified at installation time, this resource adaptor entity configuration property will be left blank.

#### Configuration file changes

The installer records the configured SIP SIS RA hostname in the `IPAddress` property in `sentinel-volte-base-service-components/config.ant.xml`.

#### Notes

Please see the SIP network settings for more information about changing the RFC 3263 settings.

Further information on the use of the DNS domain name is available in Non-sharded DNS configuration and SIP default network interface settings.

### MMTel conferencing

#### Configuration profile changes

The installer sets the following values in the `MMTelCONFConfigProfileTable` profile table:

- `ICSCFURI` is set to the configured conference I-CSCF URI,

- `MRFURI` is set to the configured MRF URI, and

- `ConfFactoryPSI` is set to the configured conference factory PSI.

Furthermore, it sets the following values in the `MMTelECTConfigProfileTable` profile table:

- `ICSCFURI` is set to the configured ECT I-CSCF URI.

It also sets the following values in the `SccConfHandlingConfigProfileTable` profile table:

- `ConfFactoryPSI` is set to the configured conference factory PSI.

Finally, it updates the `SentinelMapperSetEntryTable` to use the mappers corresponding to the configured MSML vendor.

#### Notes

These values cannot be changed after installation.

### Enable HSS IMS-ODB-Information query

#### Configuration profile changes

In the `IMS-ODB-Information` profile of the `${platform.operator.name}_SubscriberDataLookupFromHss2ServiceIndicationProfileTable` profile table, DisableQuery is set to `true` if the HSS query for `IMS-ODB-Information` has been disabled.

#### Notes

This value can be changed after installation. If this value is changed post installation there are some secondary steps required as well.

You will need to run the `sentinel-volte-mappings-config` tool making use of both the `-im` and `-o` flags to add or remove mappings.

- If you are changing the flag from `false` to `true` you will need to remove the mappings by not including them in your `-im` list.

- If you are changing the flag from `true` to `false` you will need to add the mappings by including them in your `-im` list.

### Enable HSS Metaswitch-TAS-Services query

#### Configuration profile changes

In the `Metaswitch-TAS-Services` profile of the `${platform.operator.name}_SubscriberDataLookupFromHss2ServiceIndicationProfileTable` profile table, DisableQuery is set to `true` if the HSS query for `Metaswitch-TAS-Services` has been disabled.

#### Notes

This value can be changed after installation. If this value is changed post installation there are some secondary steps required as well.

You will need to run the `sentinel-volte-mappings-config` tool making use of both the `-im` and `-o` flags to add or remove mappings.

- If you are changing the flag from `false` to `true` you will need to remove the mappings by not including them in your `-im` list.

- If you are changing the flag from `true` to `false` you will need to add the mappings by including them in your `-im` list.

### IMCSI Configuration

#### Configuration profile changes

This step only makes any changes if installing a GSM deploy, and using CAP for online charging. If so the installer sets the following values in the `FetchIMCSIConfigProfileTable` profile table:

- `FetchImcsiEnabledOnOrigCall` determines if the IMCSI should be fetched for originating calls

- `FetchImcsiEnabledOnTermCall` determines if the IMCSI should be fetched for terminating calls

#### Notes

These values can be changed after installation.

### Correlation RA

#### Configuration profile changes

The default profiles (i.e. the profiles without a name) in both the `ReoriginationCorrelationIdPools` and `EtcAriCorrelationIdPools` tables are updated in the following way:

- `NodeIds` is set using the node configuration from the Rhino step, and

- `PreconfiguredCorrelationIdSet` is set using the node configuration from the Rhino step.

#### Notes

These values can be changed after installation.

### CDMA HLR

#### Configuration profile changes

This step only makes any changes if installing a CDMA deploy, and using TLDN for SCC TADS routing. If so, the installer first makes the following change in `VolteServiceConfigProfileTable`:

- `RetrieveTLDN` is set to `true`.

Next the installer sets the following values in the `CDMAHLRConfigProfileTable` profile table:

- `HLRSccpAddressAsString` is set to the configured HLR Address,

- `SentinelSccpAddressAsString` is set to the configured originating Sentinel address,

- `HLRInvokeTimeout` is set to the configured invoke timeout,

- `MarketID` is set to the configured market ID, and

- `SwitchNumber` is set to the configured switch number.

#### Notes

The values in `CDMAHLRConfigProfileTable` can be changed after installation.

### HLR GSM

#### Configuration profile changes

This step only makes any changes if installing a GSM deploy, and using either the MSRN from the HLR for SCC TADS routing, or determining roaming from HLR.

If using the MSRN from the HLR, the installer first makes the following change in `VolteServiceConfigProfileTable`:

- `RetrieveMSRN` is set to `true`.

If determining roaming from HLR, the installer makes another change in `VolteServiceConfigProfileTable`:

- `RetrieveHLRRoamingStatus` is set to `true`.

Next the installer sets the following values in the `HLRConfigProfileTable` profile table:

- `HLRSccpAddressAsString` is set to the configured HLR Address,

- `SentinelSccpAddressAsString` is set to the configured originating Sentinel address,

- `SentinelSccpMscEndpointAddressAsString` is set to the configured originating Sentinel address,

- `SentinelAddressStringAsString` is set to the configured MLC address, and

- `HLRInvokeTimeout` is set to the configured invoke timeout.

#### Notes

The values in `HLRConfigProfileTable` can be changed after installation.

### TADS

#### Configuration profile changes

If configured to allow WLAN access, the following profiles are added to the `SCCTADSNetworkTypeConfigProfileTable`:

- `${platform.operator.name}:::::0`

  - `NetworkType: 0`

  - `Description: RAT value 0 = WLAN from TS 29.212 section 5.3.31`

  - `TerminatingDomain: PS=WLAN`

- `${platform.operator.name}:::::3GPP-WLAN`

  - `NetworkType: 3GPP-WLAN`

  - `Description: P-Access-Network-Info value from TS 24.229 section 7.2A.4`

  - `TerminatingDomain: PS=WLAN`

- `${platform.operator.name}:::::IEEE-802.11`

  - `NetworkType: IEEE-802.11`

  - `Description: P-Access-Network-Info value from TS 24.229 section 7.2A.4`

  - `TerminatingDomain: PS=WLAN`

- `${platform.operator.name}:::::IEEE-802.11A`

  - `NetworkType: IEEE-802.11A`

  - `Description: P-Access-Network-Info value from TS 24.229 section 7.2A.4`

  - `TerminatingDomain: PS=WLAN`

- `${platform.operator.name}:::::IEEE-802.11B`

  - `NetworkType: IEEE-802.11B`

  - `Description: P-Access-Network-Info value from TS 24.229 section 7.2A.4`

  - `TerminatingDomain: PS=WLAN`

- `${platform.operator.name}:::::IEEE-802.11G`

  - `NetworkType: IEEE-802.11G`

  - `Description: P-Access-Network-Info value from TS 24.229 section 7.2A.4`

  - `TerminatingDomain: PS=WLAN`

- `${platform.operator.name}:::::IEEE-802.11N`

  - `NetworkType: IEEE-802.11N`

  - `Description: P-Access-Network-Info value from TS 24.229 section 7.2A.4`

  - `TerminatingDomain: PS=WLAN`

#### Notes

This setting can be changed after installation by adding or removing the profiles.

## Installing the Sentinel VoLTE Provisioning Module

| Artifactory This page refers to a public Artifactory instance that is no longer available. Please contact us via support if you require more information.

The Sentinel VoLTE provisioning module is distributed as a Rhino Element Manager (REM) plugin.

It requires REM 2.7.0 or compatible. REM can be installed with Jetty or Apache Tomcat. For Sentinel VoLTE, the Apache Tomcat method is required.

To install the Sentinel VoLTE Provisioning module you will need:

- the REM distribution package —`rhino-element-manager-<version>.zip`; expanded to a location of your choice

  - download from https://repo.opencloud.com/artifactory/opencloud-sentinel-volte-3.1.0/opencloud/rem/2.7.0/rem-package/

- an Apache Tomcat installation — either downloaded and configured manually, or installed via a package manager; minimum supported version is `7.0.39`

- the Sentinel VoLTE REM plugin —`sentinel-volte-element-manager-<version>.em.jar`

  - download for your release version from https://repo.opencloud.com/artifactory/opencloud-sentinel-volte-3.1.0/opencloud/volte/3.1.0/sentinel-volte-element-manager

- (optional) the SIS REM plugin —`sis-em-<version>.em.jar`

  - download for your release version from https://repo.opencloud.com/artifactory/opencloud-sentinel-volte-3.1.0/opencloud/sis-em/2.6.1/sis-em

Below are the procedures to:

- set up Tomcat

- install the REM plugin

- customize plugin logging

- import Rhino trust certificate

- run it securely

| REM restart required After installing and configuring the plugin, you will need to restart REM, for example by restarting the Tomcat webapp it is running in:
    ${CATALINA_BASE}/bin/catalina.sh stop
    ${CATALINA_BASE}/bin/catalina.sh start

### Set up Tomcat

To set up Apache Tomcat for the Sentinel VoLTE Provisioning module:

1 | Follow the instructions for running REM on Apache Tomcat in the REM Guide.
2 | Create the `rem_home/plugins` directory.
    cd apache-tomcat-<version>
    mkdir -p rem_home/plugins
3 | If running Apache Tomcat using Java 1.7, you will need to increase the PermGen size. Add `JAVA_OPTS` to `bin/setenv.sh`.
    JAVA_OPTS="-XX:PermSize=512m -XX:MaxPermSize=512m"
This step should be skipped if running Apache Tomcat on Java 1.8 or higher.

### Install the REM plugin

To install the REM plugin for the Sentinel VoLTE Provisioning Module:

1 | Copy `sentinel-volte-element-manager-<version>.em.jar` into `rem_home/plugins`.
    cd apache-tomcat-<version>
    cp /full/path/to/sentinel-volte-element-manager-<version>.em.jar rem_home/plugins/
2 | (Optional) Copy `sis-em-<version>.em.jar` into `rem_home/plugins`.
    cd apache-tomcat-<version>
    cp /full/path/to/sis-em-<version>.em.jar rem_home/plugins/

### Customize plugin logging

1 | Edit `log4j2.properties` and append the following content:
    # additional lines to add to the rem.war log4j2.properties file

    # the XCAP server only logs when user traffic arrives
    # per-request logging is at debug level
    logger.xcapserver.name=xcapserver
    logger.xcapserver.level=DEBUG

    # the diameter stack in the XCAP Server - logs regardless of user traffic
    logger.xcapdiameter.name=xcapserver.diameter
    logger.xcapdiameter.level=INFO

    # transport level logging from the XCAP Server's diameter stack
    # set to DEBUG for interoperability diagnostics
    logger.xcapdiametertransport.name=xcapserver.diameter.transport
    logger.xcapdiametertransport.level=INFO

    # part of the XCAP server logging
    logger.remxcap.name=rem.server.sentinel.xcap
    logger.remxcap.level=DEBUG

    # a rolling audit file of Sentinel EM plugin audit logging
    appender.sentinelaudit.type=RollingFile
    appender.sentinelaudit.name=AUDIT
    appender.sentinelaudit.fileName=${sys:catalina.base}/logs/sentinel-audit.log
    appender.sentinelaudit.filePattern = ${sys:catalina.base}/logs/sentinel-audit.log.%i
    appender.sentinelaudit.policies.type = Policies
    appender.sentinelaudit.policies.size.type = SizeBasedTriggeringPolicy
    appender.sentinelaudit.policies.size.size=10MB
    appender.sentinelaudit.strategy.type = DefaultRolloverStrategy
    appender.sentinelaudit.strategy.max = 10
    appender.sentinelaudit.layout.type=PatternLayout
    appender.sentinelaudit.layout.pattern="%d{yyyy-MM-dd HH:mm:ss,SSS}", "%c{1}", %m{nolookups}%n

    # send Sentinel EM plugin audit logging to the AUDIT appender, only
    logger.sentinelaudit.name=sentinel.audit
    logger.sentinelaudit.level=INFO
    logger.sentinelaudit.appenderRef.file.ref=AUDIT
    logger.sentinelaudit.additivity=false

### Import Rhino trust certificate

This can also be done using the REM web UI.

1 | Import a Rhino Trust Certificate into REM:
    "${JAVA_HOME}/bin/keytool" -importcert -file ${RHINO_HOME}/rhino-trust.cert -keystore "${TOMCAT_HOME}/rem_home/rhino-ems.ks" -storepass changeit -noprompt

### Security considerations

Below are recommendations for securely running the Sentinel VoLTE Provisioning Module.

#### Use https

Be aware that the Sentinel VoLTE machine API uses HTTP BASIC authentication. This passes the username and password with every request.

To prevent your credentials going over the network unencrypted, run REM over https.

#### Set up SSL

See the Tomcat 7 - SSL How-To docs for help setting up SSL in Apache Tomcat 7.

## Virtualized Deployment Requirements

Sentinel VoLTE is supported in a virtualized environment, details presented here provide a guide to the scope of that support and how Sentinel VoLTE should be setup in that environment.

### VMWare Supported

VMWare vSphere ESXi 5.1 and 6 is supported and certified. vCenter is not a mandatory requirement.

### Operating System Support

Please refer to the Platforms section of the Rhino Compatibility Guide for supported operating systems.

### Hyper-threading support

Hyper-threading is supported and used to maximize performance throughput.

### Uncontended RAM Required

Sentinel VoLTE does make use of Uncontended RAM.

### Uncontended disk I/O Required

Sentinel VoLTE does not require Uncontended disk I/O.

### Dedicated Storage Array Required

Sentinel VoLTE does not require dedicated storage. CDR files and Rhino logs should be partitioned separately and managed to avoid failure or data loss due to space utilization.

### CPU Contention Supported

CPU Contention is supported, however %ready numbers should be kept below 5% to avoid significant impact on overall application performance. It is strongly recommended that VMs are bound to physical CPU sockets to ensure predictable latency.

### Fault Tolerance

A rhino cluster provides support for both high availability and fault tolerance internally. Sentinel VoLTE does not make use of the Rhino replication but does use the high availability systems. The cluster as a whole can tolerate failure of individual nodes with no support from the virtual machine. Live replication of virtual machines (FT Model) will interfere with Rhino’s internal clustering mechanisms.

### VMWare Fault Tolerance

Sentinel VoLTE does not support VMWare Fault Tolerance.

### VMWare vSphere High Availability

Sentinel VoLTE provides is own HA clustering based upon the Rhino SLEE Architecture.

### VMWare vSphere App High Availability

Sentinel VoLTE does not support App High Availability.

### VMWare vMotion

VMWare vMotion is not supported

### VMWare vSphere Data Protection

Sentinel VoLTE supports Data Protection with the exception of RAM.

### Stretched Clustering

Sentinel VoLTE supports Stretched Clustering.

### VMWare VM Suspend/Resume

Sentinel VoLTE does not support Suspend/Resume.

### VMWare VM Snapshots

Sentinel VoLTE does not support Snapshots.

### VMWare VM Clone

Sentinel VoLTE does not support Cloning.

### VMWare power management options supported

Sentinel VoLTE supports all power management.

### VMWare clock synchronization

Sentinel VoLTE does not require clock synchronization.

### SR-IOV

Sentinel VoLTE does not require SR-IOV.

### Test Lab Minimum Virtual Host Requirements

1 vCPU, 8Gb RAM, 30Gb HD, 0 IOPS (Disk I/O is not normally a significant requirement as it’s not used except for logging and installation/configuration changes. Under normal operation a rhino node produces very little logging, but can use > 100Mb/s during severe error conditions under load).

### Production Minimum Virtual Host Requirements

1 Rhino node per VM, 1 CPU (bound) @2.4+Ghz, 12Gb java heap, 30Gb HD, 0 IOPS. A quorum node is much lighter weight, and would require a vm with 1 vcpu, 512Mb ram, 0 IOPS.

### System capacity/performance for each production system

1.08M BHCA, + 10.8K Conference attempts.

### Scalability

Linear to 2.4Ghz, No scaling improvement over 2.4Ghz. (At Maximum load @ 2.4GHz, we reach saturation of Java CMS collector).

### Virtual host resource changes while running

Sentinel VoLTE does not support host resource changes while running.

### Virtual network interface requirements

VoLTE Sentinel requires 1 network interface for each mgmt/signalling interface.

### Signalling bandwidth requirements

Sentinel VoLTE requires 500kbps/BHCA.

### Latency added by signalling

Sentinel VoLTE adds 20ms at 50th percentile.

## Features

This page presents summaries and links to more detailed descriptions of features installed with the Sentinel VoLTE product.

### SIP features

The SIP features can be thought of as building blocks for any SIP-AS functionality, regardless of whether it is MMTel-AS, SCC-AS or any other SIP-AS.

### General VoLTE features

The General VoLTE Features are used by both the MMTel-AS and SCC-AS functionality of the Sentinel VoLTE product. They can be thought of as building blocks for MMTel-AS and SCC-AS.

### MMTel features

The MMTel Features implement MMTel-AS functionality.

### SCC features

The SCC Features implement SCC-AS functionality.

### Third Party Registration features

The Third Party Registration features implement the necessary Third Party Registration functionality for the MMTel-AS and SCC-AS.

### CAMEL features

The CAMEL features can be thought of as building blocks for SCP functionality.

### General features

The General Features are essentially utility features that are installed out-of-the-box.

The Sentinel VoLTE product does not use the Subscriber Data Lookup and Subscriber Validity features as the General VoLTE features are used instead. These features may be used when customising Sentinel VoLTE.

## SIP features

The SIP Features are not specific to SCC or MMTel or even VoLTE installations. They are installed out-of-the-box with Sentinel VoLTE.

## General VoLTE Features

These features are neither MMTel specific nor SCC specific.

Feature | What it does
--- | ---
DetermineChargeMode | uses information from the incoming INVITE request to determine whether Ro Online charging should be applied to the session,
DetermineInitialLegNames | uses the Leg Manager to get the names of the original SIP legs established during call set up, and saves the values
Determine International and Roaming Status | determines if the SIP session is roaming and if it represents an international, or international ex HC call, based on the location of the calling party and the destination address
DetermineVoltePlanId | uses information from an incoming `INVITE`, `MESSAGE` or `SUBSCRIBE` request, and from session state to set the plan ID in the Sentinel selection key
DialPlanEnforcement | analyses the request-uri of an originating trigger to determine if the dialed digits match the dial plan
IMSIDLookup | reads Third Party Registration information stored in the HSS as Transparent Data, and writes it into session state.
IMSIDLookupFromCassandraSIP | reads Third Party Registration information stored in the Cassandra Database, and writes it into session state.
IMSIDLookupFromCassandraIN | reads Third Party Registration information stored in the Cassandra Database, and writes it into session state.
SubscriberDataLookupFromHSS | is responsible for reading data from the HSS and writing it into Sentinel session state fields.
SubscriberDataLookupFromHSSOld | is responsible for reading data from the HSS and writing it into Sentinel session state variables fields.
SubscriberDataLookupFromHLR | is responsible for reading subscriber data from the HLR and writing it into Sentinel session state variable fields.
VolteSipAvpCdr | is responsible for building a Call Detail Record that reflects the actions taken whilst processing a session.
SuppressSdpCdr | is a system feature which prevents SDP-change initiated CDRs from being written by the `VolteInterimCdr` feature for non-roaming Mobile Terminating calls.
VolteInterimCdr | is a system feature that is responsible for writing interim Call Detail Records and/or Diameter Accounting Requests (ACRs) throughout the session.
FeatureCapsManagement | sets values for the Feature-Caps header on outgoing messages based on data from the session’s FeatureCapsManager
SetOcsAnnouncementID | schedules configurable announcements to the subscriber based on Credit-Control-Answers
DetectHoldResume | updates session state when a session’s held status changes
AccessLegTracking | This feature gathers the information required to allow the session tracking system to be used for access transfer procedures.
FetchIMCSI | retrieves CAMEL Subscription Information (CSI) from the HLR for charging purposes
CapLocationHeaders | adds proprietary SIP headers to outbound INVITE requests to allow CAP charging of the session.
VolteLoadServiceConfig | loads service configuration out of a profile and into session state.
StripPreconditions | optionally strips preconditions information from initial INVITEs

## Access Leg Tracking

This feature gathers the information required to allow the session tracking system to be used for access transfer procedures.

### Feature Cheat Sheet

Feature Script Name | AccessLegTracking
MMTel or SCC | Both
Call-Type | All
Session Plan | MMTel, SCC, SCC-Term-Anchor
Execution Point | SipAccess_SubscriberCheck, SipAccess_PartyResponse, SipAccess_PartyRequest, SipMidSession_PartyRequest, SipMidSession_PartyResponse
Network Operator Config | None
Subscriber Config | None
POJO or SBB | POJO
Feature FSMs | None
Feature Parameters | None
SAS Support | No
Related features | ExternalSessionTracking

### Feature Statistics

`AccessLegTracking` statistics are tracked by the `sentinel.volte.sip` SBB and can be found under the following parameter set:
SLEE-Usage → sentinel.volte.sip service ID → sentinel.volte.sip SBB ID → feature.DetermineSessionReplication

Name | Type | Description
--- | --- | ---
    Started
| Counter | Incremented when the feature is triggered.
    FailedToStart
| Counter | Incremented when the feature fails to start.
    FailedDuringExecution
| Counter | Incremented when the feature fails while executing.
    IssuedWarning
| Counter | Incremented when the feature issues a warning.
    TimedOut
| Counter | Incremented when the feature times out during execution.
    TrackingDataOnInitialInvite
| Counter | Incremented when the feature updates tracked data due to an initial INVITE.
    TrackingDataOnProvisionalResponse
| Counter | Incremented when the feature updates tracked data due to a provisional response to the initial INVITE.
    TrackingDataOnAck
| Counter | Incremented when the feature updates tracked data due to the ACK for the initial INVITE.
    TrackingDataOnHoldStatusChange
| Counter | Incremented when the feature updates tracked data due to a change in the hold status of a session.

### Behaviour

This feature uses the Sentinel SIP `Leg` API to provide information to the ExternalSessionTracking feature. This allows the Session Ownership Facility to be used for tracking sessions for the purposes of access transfer.

The feature passes through four phases during session processing. Each phase is associated with a particular point in the session plan. At each phase the feature updates different sets of data.

#### Tracked Data

There are several sets of data that the feature maintains in the session tracking system. Different sets are updated at different times based on where in the session plan the feature is running. The data sets are:

- Basic Tracking Data

- Call Setup Data

- Media State Data

The following sections outline each piece of information that is handled by this feature, and which of the above sets each belongs to.

##### Tracking Enabled

Data Set | Leg API Field
--- | ---
Basic Tracking Data |
    TrackingEnabled

Flags a leg for tracking be the External Session Tracking feature. The Access Leg Tracking feature will set it to `true` for all access legs.

##### WaitForTrackingResultEnabled

Data Set | Leg API Field
--- | ---
Basic Tracking Data |
    WaitForTrackingResultEnabled

Flag that indicates to the External Session Tracking feature that it should wait for the result of any session ownership facility operations relating to this leg before allowing the session to proceed. The Access Leg Tracking feature will set this flag to true for all access legs. This is done to ensure access transfer is prepared to run before the session is allowed to continue.

##### Owner

Data Set | Leg API Field
--- | ---
Basic Tracking Data |
    Owner

URI of the node that currently owns the session. The feature will always ensure this matches the URI of the node it’s running on.

##### Additional Tracking Keys

Data Set | Leg API Field
--- | ---
Basic Tracking Data |
    AdditionalTrackingKeys

These are alternative keys (i.e. keys besides the leg’s dialog ID) that can be used to retrieve tracking data for a leg. The feature retrieves these keys from the `AccessLegTrackingKeys` session state field. The keys present in this session state field are set by various VoLTE features that make use of access leg tracking.

##### Dialog State

Data Set | Leg API Field
--- | ---
Basic Tracking Data |
    AdditionalTrackedAttributes (with attribute key: dialog-state)

This field describes the current state of the leg. The current dialog state is determined first by how far through call setup the leg is, and once call setup is complete, by whether the call is held or not (as determined by the Detect Hold Resume feature). The field will have one of the following values:

- `PARTIAL_DIALOG`

- `PRE_ALERTING`

- `ALERTING`

- `ACTIVE`

- `HELD`

##### Media Feature Tags

Data Set | Leg API Field
--- | ---
Call Setup Data |
    AdditionalTrackedAttributes (with attribute key: media-feature-tags)

These are the media feature tags that have been seen on this session. They are retrieved from the contact header of the initial INVITE for originating access legs, and the initial INVITE response for terminating access legs.

##### Associated Dialog ID

Data Set | Leg API Field
--- | ---
Call Setup Data |
    AdditionalTrackedAttributes (with attribute key: associated-dialog)

This is the dialog ID of the leg currently linked to the access leg.

##### Last Active Time

Data Set | Leg API Field
--- | ---
Media State Data |
    AdditionalTrackedAttributes (with attribute key: last-active-time)

This is the timestamp for the last time the session entered the active state (i.e. the time the ACK was received, or the last time the call was resumed after being held).

##### Last Held Time

Data Set | Leg API Field
--- | ---
Media State Data |
    AdditionalTrackedAttributes (with attribute key: last-held-time)

This is the timestamp for the last time the session entered the held state.

##### Committed SDP

Data Set | Leg API Field
--- | ---
Media State Data |
    AdditionalTrackedAttributes (with attribute key: committed-sdp)

This is the current negotiated SDP in use on the access leg.

##### Committed SDP Timestamp

Data Set | Leg API Field
--- | ---
Media State Data |
    AdditionalTrackedAttributes (with attribute key: committed-sdp-timestamp)

This is the time at which the current committed SDP on the access leg was accepted.

#### Feature Phases

The four phases the feature passes through are:

- Initial Request Processing

- INVITE Response Processing

- ACK Processing

- Mid-Session Message Processing

Once any type of access transfer has been executed on a session, this feature will no longer attempt to maintain access leg information, and will always end without executing any phase.

##### Initial Request Processing

Execution Point: `SipAccess_SubscriberCheck`

This phase is only executed on originating AS instances, and only on the initial `INVITE` request. This means that the access leg will always be the leg the `INVITE` was received on, and there will never be any forked access legs.

The feature will skip this phase if the `PartialDialogAccessLegTrackingActive` session state field is false. This session state field is set by the SCCDetermineExternalSessionTracking feature, based on the presence of a `g.3gpp.ps2cs-srvcc-orig-pre-alerting` media feature tag on the `INVITE` request.

In this phase:

- The feature will record the media-feature tags present on the initial `INVITE`.

- The feature will set the dialog state to `PARTIAL_DIALOG`.

- Basic Tracking Data will be updated.

- Call Setup Data will be updated.

##### INVITE Response Processing

Execution Point: `SipAccess_PartyResponse`

This phase is executed when the feature receives a provisional response for the initial `INVITE` request. On terminating AS instances the leg the response is received on is the access leg, and on originating AS instances the leg the response will be forwarded on is the access leg. The access leg may be forked during this phase, so multiple legs could be tracked in a single session at this time.

In this phase:

- The feature will record the media-feature tags present on the response if the AS is a terminating instance.

- The feature will set the dialog state to `PRE_ALERTING` or `ALERTING` based on whether a `180 Ringing` response has been received.

- Basic Tracking Data will be updated.

- Call Setup Data will be updated.

##### ACK Processing

Execution Point: `SipAccess_PartyRequest`

This phase is executed when the feature receives a `ACK` request for the initial `INVITE` 2xx response. On originating AS instances the leg the `ACK` is received on is the access leg, and on terminating AS instances the leg the ACK will be forwarded on is the access leg. Any forked access legs will have ended by the time this message is received, so there will only be one access leg in this phase. The `ExternalSessionTracking` feature will have automatically cleaned up tracked data for these forks.

In this phase:

- The feature will record the last active time for the call as now.

- The feature will set the dialog state to `HELD` (very unlikely) or `ACTIVE` based on the hold status of the call.

- Basic Tracking Data will be updated.

- Call Setup Data will be updated.

- Media State Data will be updated.

##### Mid-Session Message Processing

Execution Points: `SipMidSession_PartyRequest` and `SipMidSession_PartyResponse`

This phase is executed on receipt of any message after call setup that results in a change to the hold status of the call. The access leg is determined by looking up its name from the `CurrentLocalLegName` session state field.

In this phase:

- The feature will set the dialog state to `HELD` or `ACTIVE` based on the hold status of the call.

- Basic Tracking Data will be updated.

- Media State Data will be updated.

## VoLTE Load Service Config

This feature loads service configuration out of a profile and into session state.

### Feature Cheat Sheet

Feature Script Name | VolteLoadServiceConfig
MMTel or SCC | Both
Call-Type | All
Session Plan | All
Execution Point | SipAccess_SessionAccept (SIP), DirectAccess_SessionAccept (SS7)
Network Operator Config | Yes
Subscriber Config | None
POJO or SBB | POJO
Feature FSMs | None
Feature Parameters | None
SAS Support | No

### Feature Statistics

`VolteLoadServiceConfig` statistics are tracked by the `sentinel.volte.sip` SBB and can be found under the following parameter set:
SLEE-Usage → sentinel.volte.sip service ID → sentinel.volte.sip SBB ID → feature.VolteLoadServiceConfig

Name | Type | Description
--- | --- | ---
`Started` | Counter | Incremented when the feature is triggered.
`FailedToStart` | Counter | Incremented when the feature fails to start.
`FailedDuringExecution` | Counter | Incremented when the feature fails while executing.
`IssuedWarning` | Counter | Incremented when the feature issues a warning.
`TimedOut` | Counter | Incremented when the feature times out during execution.
`ConfigLoaded` | Counter | Incremented when the feature successfully loads configuration data into session state.

### Session Input Variables

Variable name | Type | Comments
--- | --- | ---
`SentinelSelectionKey` | `SentinelSelectionKey` | Used to select which profile to load from the configuration table.

### Session Output Variables

Variable name | Type | Comments
--- | --- | ---
`RetrieveMSRN` | `boolean` | Determines whether the service will attempt to retrieve an MSRN from the HLR when required.
`RetrieveTLDN` | `boolean` | Determines whether the service will attempt to retrieve a TLDN from the HLR when required.
`RetrieveHLRRoamingStatus` | `boolean` | Determines whether the service will attempt to determine the subscriber’s roaming status from the HLR when required.
`RegistrationDataSource` | `RegistrationDataSource` (enum) | Determines where the service will attempt to retrieve third party registration data from. Possible values are `HSS` and `CASSANDRA`.
`SubscriberDataSource` | `SubscriberDataSource` (enum) | Determines where the service will attempt to retrieve subscriber data from. Possible values are `HSS` and `HLR`.

### Configuration

Network configuration is stored in a profile table named `VolteServiceConfigProfileTable`. Profiles in this table are scoped on Sentinel Selection Key.

| Directly modifying values in this profile is not recommended, they should instead be set through the Sentinel VoLTE installer. See Installing Sentinel VoLTE Services and Changing configuration post-installation.

Attribute | Type | Default Value | Description
--- | --- | --- | ---
`RetrieveMSRN` | `boolean` | `false` | Determines whether the service will attempt to retrieve an MSRN from the HLR when required.
`RetrieveTLDN` | `boolean` | `false` | Determines whether the service will attempt to retrieve a TLDN from the HLR when required.
`RetrieveHLRRoamingStatus` | `boolean` | `false` | Determines whether the service will attempt to determine the subscriber’s roaming status from the HLR when required.
`RegistrationDataSource` | `RegistrationDataSource` (enum) | `CASSANDRA` | Determines where the service will attempt to retrieve third party registration data from. Possible values are `HSS` and `CASSANDRA`.
`SubscriberDataSource` | `SubscriberDataSource` (enum) | `HSS` | Determines where the service will attempt to retrieve subscriber data from. Possible values are `HSS` and `HLR`.

### Behaviour

When triggered this feature will attempt to retrieve a profile from the `VolteServiceConfigProfileTable` using the current Sentinel Selection Key. If it successfully finds a profile it will copy each attribute on the profile into its corresponding session state field. If it fails to find a profile it will raise a configuration error.

## DetectHoldResume

This feature updates session state when a session’s held status changes .

### Feature cheat sheet

B2BUA Instance | SAS Support | Originating / Terminating | Point(s) in Session Plan | Network Operator Data | Subscriber Data | Stateful or Stateless | POJO or SBB Feature | Other notes
--- | --- | --- | --- | --- | --- | --- | --- | ---
SCC | No | Both Originating and Terminating |
    SIP Mid Session Party Request,
    SIP Mid Session Party Response
| None | None | Stateless | POJO |

### Session input and output variables

#### Session input variables

None.

#### Session output variables

Session State variable name | Type | Comments
--- | --- | ---
    HeldStatusChanged
| Boolean | Indicates that the current message has changed the held status of the session.
    SessionIsHeld
| Boolean | Indicates whether the session is currently on hold.
    LastActiveTime
| Long | The time that the session last changed from held to active.
    LastHeldTime
| Long | The time that the session last changed from active to held.

### Statistics

DetectHoldResume statistics are tracked by the sentinel.volte.sip SBB and can be found under the following parameter set in REM:
SLEE-Usage → sentinel.volte.sip service → sentinel.volte.sip SBB → feature → DetectHoldResume
or with rhino-stats:
"SLEE-Usage.Services.ServiceID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].SbbID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].feature.DetectHoldResume"

Name | Description
--- | ---
    Started
| Incremented each time the feature runs
    FailedToStart
| Incremented when a fatal error occurs before feature execution
    IssuedWarning
| Incremented when a non-fatal error occurs during feature execution
    FailedDuringExecution
| Incremented when a fatal error occurs during feature execution
    TimedOut
| Incremented when feature execution does not complete within a reasonable time frame
    DetectSessionHold
| Incremented when the feature detects a transition from active to held
    DetectSessionResume
| Incremented when the feature detects a transition from held to active

### Behaviour

The `DetectHoldResume` feature updates session state when the session’s held status changes.

The feature runs on the SIP Mid-Session Party Request and SIP Mid-Session Party Response execution points. If a message containing an SDP offer arrives, the SDP is compared to the session’s previous SDP.

The feature looks for changes in directionality attribute in the session description, for example `a=sendrecv` or `a=sendonly`, to determine if the session is being put on hold or resumed. If the held status has changed, session state is updated with the new held status.

## CapLocationHeaders

The CapLocationHeaders feature adds proprietary SIP headers to outbound INVITE requests to allow CAP charging of the session.

The `OC-Charging-GT` header contains the location of the subscriber to allow roaming to be correctly charged.

The `OC-IM-TDP` header contains the location of the SCP that IM-SSF should send charging requests to.

The `OC-Replication-Information` header contains instructions on how the IM-SSF should handle session tracking and replication.

### Feature cheat sheet

Feature Script Name | CapLocationHeaders
MMTel or SCC | Both
Call-Type | Orig or Term
Session Plan | mmtel-orig, scc-tads-only
Execution Points | SipAccess_SubscriberCheck
Network Operator Config | Yes
Subscriber Config | No
POJO or SBB | POJO
Feature FSMs | None
Feature Parameters | None
SAS Support | Yes
RA Entity Links | None

### Prerequisite features

- DetermineCallType

- ExtractNetworkInfo

- FetchIMCSI

- DetermineChargeMode

- FetchMSRN

### Network Operator Data

The CapLocationHeaders feature depends on configuration in the `CapChargingConfigProfileTable` to specify how to generate the `OC-Charging-GT` header.

It also reads the `RefreshPeriod` in the SessionRefresh configuration profile table to determine the refresh period to include on the `OC-Replication-Information` header when replication is enabled.

#### CapChargingConfigProfileTable

Configuration is stored on a profile table called `CapChargingConfigProfileTable`.

Data is scoped according to a Sentinel selection key.

Attribute Name | Type | Default | Description
--- | --- | --- | ---
    ChargingGTFormatString
| String | null | The format template to use when creating Charging GTs. It must be a digit string except for tokens ('{iso}', '{mcc}', '{mnc}) which are substituted in.
    UnknownLocationChargingGT
| String | null | The Charging GT to use when one could not be generated because the user’s location could not be determined.
    OnlyChargeTerminatingCallsIfInternationalRoaming
| boolean | false | When true, terminating calls will only be charged if the served user is roaming outside of their home country.

### Session Input Variables

Variable name | Type | Comments
--- | --- | ---
ChargeMode | Enum | The feature will only run if the charge mode is `CAP`.
SentinelSelectionKey | SentinelSelectionKey | Affects which profiles are loaded from each configuration table.
CallType | Enum | Affects whether CAP headers are added and what values are used for them.
RoamingStatus | Enum | If the call is terminating and not roaming, no headers are added.
VLRNumber | AddressString | If the call is CS terminating then the VLRNumber is used for the `OC-Charging-GT`.
VMSCAddress | AddressString | If the call is CS terminating and there is no VLRNumber available then the VMSCAddress is used for the `OC-Charging-GT`.
OcImTdpHeader | String | The value to use for the `OC-IM-TDP` header.
IsoCountryCode | String | The ISO country code that the subscriber is registered with. It is used for formatting the `OC-Charging-GT` header.
PaniMccMncs | List<MccMnc> | The MCCs and MNCs that the subscriber is registered with. They are used for formatting the `OC-Charging-GT` header.
SessionUACLegReplicationTrigger | Enum | Used to determine if replication should be indicated as enabled on the `OC-Replication-Information` header.
SessionUASLegReplicationTrigger | Enum | Used to determine if replication should be indicated as enabled on the `OC-Replication-Information` header.

### Statistics

CapLocationHeaders statistics are tracked by the sentinel.volte.sip SBB and can be found under the following parameter set in REM:
SLEE-Usage → sentinel.volte.sip service → sentinel.volte.sip SBB → feature → CapLocationHeaders
or with rhino-stats:
"SLEE-Usage.Services.ServiceID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].SbbID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].feature.CapLocationHeaders"

    Statistic
| Type | Description
    Started
| Counter | Incremented when the feature is invoked.
    FailedToStart
| Counter | Incremented when Sentinel VoLTE encounters an error while attempting to start the feature.
    IssuedWarning
| Counter | Incremented when a non-fatal problem is encountered and the feature issues a warning.
    FailedDuringExecution
| Counter | Incremented when a fatal problem is encountered and the feature cannot execute correctly.
    TimedOut
| Counter | Incremented when the feature takes too long to complete and Sentinel VoLTE aborts execution.
    CapLocationHeadersNotRequired
| Counter | Incremented when the feature determines that no CAP location headers need to be added.
    UsedVlrNumber
| Counter | Incremented when the VLR number is used for the `OC-Charging-GT` header.
    UsedVmscNumber
| Counter | Incremented when the VMSC address is used for the `OC-Charging-GT` header.
    NoVlrOrVmscNumberFound
| Counter | Incremented when no VLR number and no VMSC address could be found.
    UsedGeneratedChargingGT
| Counter | Incremented when a generated Charging GT is used for the `OC-Charging-GT` header.
    UsedUnknownLocationChargingGT
| Counter | Incremented when the unknown location Charging GT is used for the `OC-Charging-GT` header.
    SetOCIMTDP
| Counter | Incremented when an `OC-IM-TDP` header is set on an outgoing request.
    SetOCChargingGT
| Counter | Incremented when an `OC-Charging-GT` header is set on an outgoing request.
    SetOCReplicationInformation
| Counter | Incremented when an `OC-Replication-Information` header is set on an outgoing request.

### Installation

CapLocationHeaders is a GSM only feature and as such will only be deployed if GSM mode is selected in the installer.

### Behaviour

The behaviour varies depending on whether the call is terminating or not.

#### Originating Behaviour

The feature attempts to generate a Charging GT using the `ChargingGTFormatString` and sets the `OC-Charging-GT` with this. If this fails, the feature uses the `UnknownLocationChargingGT` for the `OC-Charging-GT` header.

The feature sets the `OC-IM-TDP` header to the value stored in session state by the `FetchIMCSI` feature.

The feature sets the `OC-Replication-Information` as described below in the Replication Information section.

#### Terminating Behaviour

If the subscriber is not roaming the feature will check the `OnlyChargeTerminatingCallsIfInternationalRoaming` configuration value to determine whether it should do anything.

If the call is forked then the following occurs for each outgoing forked leg.

If the outgoing leg is CS then the feature attempts to set the `OC-Charging-GT` to the VLR Number retrieved by FetchMSRN. If there is no VLR Number in session state, the feature attempts to set the `OC-Charging-GT` to the VMSC address. If that is not present in session state either then the feature returns.

If the outgoing leg is PS then the feature attempts to generate a Charging GT using the `ChargingGTFormatString` and sets the `OC-Charging-GT` with this. If this fails, the feature uses the `UnknownLocationChargingGT` for the `OC-Charging-GT` header.

The feature sets the `OC-IM-TDP` header to the value stored in session state by the `FetchIMCSI` feature.

The feature sets the `OC-Replication-Information` as described below in the Replication Information section.

#### Generating Charging GTs

The feature uses the CAP Charging Component to generate Charging GTs based on location data.

#### Replication Information

The feature includes an `OC-Replication-Information` header on the request towards the IM-SSF which indicates whether replication behaviour is required.

The header value is determined based on the values of the `SessionUASLegReplicationTrigger` and `SessionUACLegReplicationTrigger` session input fields. If either of the fields indicated `DISABLED` then the the header value will be set to `disabled`, otherwise it will be set ot `enabled`.

When the header value is set to `enabled`, a `refreshPeriod` parameter will be added as well. This parameter is used to determine the TTL value the IM-SSF should use for session ownership records when doing session tracking. It is set equal to the value of the `RefreshPeriod` field in the SessionRefresh configuration profile table.

## Determine International and Roaming Status

This feature determines if the SIP session is roaming and if it represents an international, or international ex HC call, based on the location of the calling party and the destination address . The results of this feature are applied by the VoLTE communication barring features (MMTelOCB and MMTelICB).

### From the spec

Here’s what 3GPP 24.611 says:

| international: This condition evaluates to true when the request URI of the outgoing SIP request: corresponds to a telephone number, i.e. a SIP URI with a “user” URI parameter set to “phone” or a tel URI; and does not point to a destination served by a network within the country where the originating user is located when initiating the call. international-exHC: This condition for international barring, excluding the home country, evaluates to true when the request URI of the outgoing SIP request: corresponds to a telephone number, i.e. a SIP URI with a “user” URI parameter set to “phone” or a tel URI; does not point to a destination served by a network within the country where the originating user is located when initiating the call; and does not point to a destination served within the served users home network.

### Feature cheat sheet

Feature Script Name | DetermineInternationalAndRoamingStatus
MMTel or SCC | Both
Call-Type | Orig or Term
Session Plan | mmtel-orig, mmtel-term, scc-tads-only
Execution Points | SipAccess_SessionCheck or SipAccess_SubscriberCheck
Network Operator Config | Yes
Subscriber Config | No
POJO or SBB | POJO
Feature FSMs | None
Feature Parameters | None
SAS Support | Yes
RA Entity Links | None

### Prerequisite features

Sentinel-SIP:

- SIP Determine Network Operator

- SND:Determine Call Type Feature

- SIP Extract Network Info

- SIP Normalization (recommended)

VoLTE:

- IMSIDLookup

- DetermineChargeMode (only required when using CAP charging)

### Source Code

This feature’s source code is available in the Sentinel VoLTE SDK in the `volte-determine-international-and-roaming-status` module pack. It can be viewed by using the `create-module` command in the SDK with that module pack, for example:

`> create-module new-diar-module opencloud#volte-determine-international-and-roaming-status#volte/3.1.0;3.1.0.0`

This command will prompt you for information needed to create the new modules, once completed the original source for the feature can be found in the new modules.

The module-pack includes the following modules:

Module Name | Description
--- | ---
volte-determine-international-and-roaming-status | Group module for the feature that includes all of the modules listed below.
volte-determine-international-and-roaming-status-address-list | Contains the profile specification for the feature address list profile table.
volte-determine-international-and-roaming-status-profile | Contains the profile specification for the feature configuration profile table.
volte-determine-international-and-roaming-status-feature | Contains the feature itself.

### Configuration

Configuration for this feature is in the `DetermineInternationalAndRoamingStatusConfigProfileTable`. The profiles within this table have the following fields:

Parameter | Type | Description
--- | --- | ---
`EndCallIfNoVisitedNetwork` | Boolean | Decide if the feature will end the call if no Visited Network can be determined.
`ForceUserEqualsPhone` | Boolean | Explicitly add user=phone parameter and value to SIP URI during inspection.
`MinLength` | int | The minimum length of address that will be checked.
`NonInternationalFormatDNIsNational` | Boolean | Whether non international format DNs, i.e. with no leading "+", should always be treated as national.
`UseMCCSpecificAddressListTables` | Boolean | Use a prefix address list table for the subscribers Mobile Country Code.

### Behaviour

1. Get the address string to use in address analysis

2. Get the visited Mobile Country Code and Mobile Network Code

3. Get the visited-network-id for the served user

4. Get the address prefix address list

5. Determine international and international-exHC status

6. Determine roaming status

7. Using MCC specific prefix address lists

#### Get the address string to use in address analysis

The `DetermineInternationalAndRoamingStatus` feature analyses a digit string that corresponds to the destination (or called) party. Digit strings may be in a Tel URL, or the user part of a SIP URI.

If the number retrieved from the Tel URI or SIP URI user part contains a + sign, the + sign is removed to leave just the digits.

The `DetermineInternationalAndRoamingStatus` feature uses different properties of the initial `INVITE` request for originating and terminating treatment:

- If the session is originating, then it checks the `request-uri` and `To` address.

- If the session is terminating, then it checks the `P-Asserted-Identity` address, the `From` address, and the `Referred-By` address.

Otherwise, the feature execution ends.

If a digit string is not found, then the feature will respond to the sentinel-core with `featureCannotStart`, and end.

#### Determine if address international and roaming status should be skipped

The `DetermineInternationalAndRoamingStatus` feature may decide to not handle the address if either:

- The address is shorter than the configured `MinLength` defined in `DetermineInternationalAndRoamingStatusConfigProfileTable`

- The address matches an entry in the `SkipDIRSAddressList`

This allows for short codes and specific longer length numbers to avoid `DetermineInternationalAndRoamingStatus`. The `SkipDIRSAddressList` is a configurable address list scoped by the Sentinel selection key; it is only given to the component when used by the SIP normalization component.

The format of the `SkipDIRSAddressList` is described by a standard address list configuration table. See Address List Configuration Profile for more information. The `SkipDIRSAddressList` configuration is found in its profile within `${PLATFORM_OPERATOR_NAME}_Sentinel_AddressListConfigurationTable`.

#### Get the visited Mobile Country Code and Mobile Network Code

The prerequisite Extract Network Info Feature attempts to parse the `P-Access-Network-Info` and `P-Visited-Network-Identifier` headers to obtain the visited MCC and MNCs, and stores them in session state. The feature first checks if the session state field `PaniMccsMncs` (obtained from `P-Access-Network-Info`) contains any entries. If so, it takes the first entries for both the MCC and MNC. Otherwise, the visited MCC and MNCs are retrieved from the session state field `PvniMccMnc`, obtained by parsing the `P-Visited-Network-Identifier` according to IETF RFC 3455.

#### Get the ISO Country Code

The ISO country code is determined by the ExtractNetworkInfo or DetermineLocationFromMSRN feature. It is stored in session state in the `IsoCountryCode` field. The feature will attempt to retrieve it from this field.

#### Get the visited-network-id for the served user

The feature first checks if the session state field `IMSInformation` contains a valid IMS Visited Network Identifier populated by Diameter Per Leg Info Feature.

If no value is present, it extracts the visited network id for the served user as follows:

- If the session is originating, the `P-Visited-Network-Id` header is checked in the incoming request.

  - If this header exists, then the visited network id is set to the header value.

- If the session is terminating, the `OC-Term-P-Visited-Network-Id` header is checked in the incoming request.

  - If this header exists, then the visited network id is set to the header value.

If the incoming request did not contain the visited network id, and if the served user is logged into the IMS, then Third Party Registration Data is consulted - to find the P-Visited-Network-Id at the time of IMS registration. Third Party Registration data is looked up with an access key of the default public identity for the served user. It is accessed via the Sh Cache Microservice.

If a visited network id cannot be determined, the feature checks the configuration in the `DetermineInternationalAndRoamingStatusConfigProfileTable` to determine if the call should proceed or not. If `EndCallIfNoVisitedNetwork` is false, then the feature exits without modifying session state. If `EndCallIfNoVisitedNetwork` is true then the call is terminated.

#### Get the prefix address list

An important part of this feature is an address list of prefixes for each MCC or each visited network. Each entry in the list states whether an address with this prefix, for a subscriber of the network operator, registered with a subscriber location network, represents a visited or home network.

The addresses in the list will be used to determine the international status based on the MCC. For originating calls the called party address is used to find the destination MCC, and for terminating calls the calling party address is used to define the MCC from the originating party. This list allows the operator to define how the international status will be resolved by setting the field `isVisitedNetwork`.

For a session processed by VoLTE:

- The session is scoped to the network operator by the SIP Determine Network Operator feature (this is the subscriber’s home).

- The MCC or `visited-network-id` is found as described above.

- In addition to a `DEFAULT` entry, it is possible to add entries for any MCC or visited network in the `DetermineInternationalAndRoamingStatus_AddressListConfigurationTable` profile. The installer adds the `DEFAULT` entry, and an entry for the home network MCC. Furthermore, there is an address list of prefixes stored in the `DetermineInternationalAndRoamingStatus_AddressListEntryTable` for both `DEFAULT` and each MCC or visited network stored in the `DetermineInternationalAndRoamingStatus_AddressListConfigurationTable` profile. Both tables are scoped to the Network operator.

The `DetermineInternationalAndRoamingStatus_AddressListConfigurationTable` is a standard address list configuration table, see Address List Configuration Profile for more information.

The `DetermineInternationalAndRoamingStatus_AddressListEntryTable` profile format is outlined by the following:

Parameter | Type | Description
--- | --- | ---
`Description` | String |
`Address` | String | The prefix address this address list entry is for — a sequence of characters matching: 0 … 9, a … f, A … F, #, *, .
`ListId` | String | The list id is a string that identifies the address list this entry belongs to. It has the following form: <selectionkey>:<schemaName>:<listname>
`CountryName` | String | Name of the country for where the subscriber is located.
`ISOCountryCode` | String | The ISO country code for the subscriber’s location.
`MCCs` | String[] | The list of MCCs for this prefix.
`HomeNetwork` | boolean | Is true if and only if this prefix represents a home network.
`VisitedNetwork` | boolean | Is true if and only if this prefix represents a visited network.

The prefix address list to use is now determined as follows:

- If an MCC was found and the profile field `useMCCSpecificAddressListTables` is set to `false`:

  1. The feature will first attempt to use the default prefix address list named `DEFAULT`.

  2. If the default list could not be found, the feature attempts to use the prefix address list for the `visited-network-id`.

- If an MCC was found and the profile field `useMCCSpecificAddressListTables` is set to `true`:

  1. The feature will first attempt to use the prefix address list for the specific MCC.

  2. If the prefix address list for the MCC could not be found, the feature attempts to use the prefix address list for the `visited-network-id`.

- If an MCC could not be found:

  1. The feature will use the prefix address list for the `visited-network-id`.

If no prefix address list is found, the feature will respond to the sentinel-core with `featureFailedToExecute`, and end.

#### Determine international and international-exHC status

If the original number did not include a + prefix and the profile field `nonInternationalFormatDNIsNational` is set to true, then the feature determines that the number is national, regardless of the MNC and MCC. Both the `international` and `internationalExHC` session state fields are set to false.

The `DetermineInternationalAndRoamingStatus` feature does a longest-prefix search of the prefix address list with the address string (extracted in step #1).

If a match is found, then the address starts with a prefix of significance within the scope of the MCC or visited network. The feature can set the `International` session state field in two ways:

- If an MCC has been determined for the served user and there is a list of MCCs present in the prefix address list entry then 'International' is set to 'true' if the served user MCC is not present in the address list entry.

- If either MCC could not be found then 'International' is set to `not networkPrefixListEntry.isVisitedNetwork()`.

The `internationalExHC` session state field is set to `International and not networkPrefixListEntry.isHomeNetwork()`.

If a prefix address list match is not found, then it must be an international call; so the feature sets the `International` session state field to `true` and the `internationalExHC` session state field to `true`.

#### Using MCC specific prefix address lists

The `DetermineInternationalAndRoamingStatus` feature uses a single prefix address list named `DEFAULT` unless `useMCCSpecificAddressListTables` is configured as `true` in the feature’s profile.

MCC specific prefix address list tables may be needed for more advanced scenarios where different MCCs are desired to not be treated as international.

#### Determine roaming status

The home network ids define the home network for the subscriber.

If the feature finds a non-empty MCC for the visited network, it compares that value with the home MCCs using the PLMN ID Analyser Component.

If it is not a home MCC the feature sets the RoamingStatus to `INTERNATIONAL` and the `RoamingIndicator` session state field is set to `true`.

If they are equal and the PLMN ID is a home PLMN ID, the feature sets the RoamingStatus to `NOT_ROAMING` and the `RoamingIndicator` session state field is set to `false`.

If they are equal and the visited MNC is not present in the home MNCs, the feature sets the RoamingStatus to `NATIONAL` and the `RoamingIndicator` session state field is set to `false`.

If no MCC is present then the feature does the roaming analysis based on the ISO Country Code.

If the ISO country code is equal to the configured home network ISO country code, the feature sets the RoamingStatus to `NOT_ROAMING` and the `RoamingIndicator` session state field is set to `false`.

If they are not equal the feature sets the RoamingStatus to `INTERNATIONAL` and the `RoamingIndicator` session state field is set to `true`.

If no ISO country code is present then the feature does the roaming analysis based on the `visited-network-id`.

If the `visited-network-id` is a member of the set of home network ids, the feature sets the RoamingStatus to `NOT_ROAMING` and the `RoamingIndicator` session state field is set to `false`.

If the `visited-network-id` is not a member of the set of home network ids, the feature sets the RoamingStatus to `INTERNATIONAL` and the `RoamingIndicator` session state field is set to `true`.

If neither the visited MCC nor the visited network are present, the feature sets the RoamingStatus to `UNKNOWN`.

#### OC-Roaming-Status Header

##### Setting the Header

If the feature is running on a terminating MMTel instance, and CAP charging is enabled, it will attempt to add an `OC-Roaming-Status` header to the outbound request. The value of the header will be set to match the value of `RoamingStatus`.

##### Using the Header

When the feature is invoked, it will check for an `OC-Roaming-Status` header on the inbound request. If the header is found, the feature will forgo the usual process for determining the roaming status. Instead, the value of the header will be used to set the `RoamingStatus` field, and if the value is `INTERNATIONAL` the `RoamingIndicator` field will be set to `true`. The international status of the call will not be determined if the header is found, as it should only be present for the SCC AS, which does not need the international status. If the header is absent the feature will go through the usual roaming and international determination procedure as described above.

### Session state inputs and outputs

#### Inputs

Name | Type | Format | Description | Behaviour if null/invalid
--- | --- | --- | --- | ---
SentinelSelectionKey | com.opencloud. sentinel.common.SentinelSelectionKey | selection key (for example, `<platform>:<network>:::`) | For selecting configuration data | Report featureCannotStart, featureHasFinished if the network operator field is not set.
CallType | com.opencloud.sentinel.common.CallType | One of: `MobileOriginating`, `MobileTerminating`, `MobileForwarded`, `NetworkInitiated`, `EmergencyCall` | Session type of this call | Report `featureCannotStart`, `featureHasFinished`
IMSDefaultPublicID | java.lang.String | tel URL or SIP URI | the `default-public-id` (set by IMSIDLookup) | Increment statistic `SubscriberNotLoggedIn` and report `featureHasFinished`
ImsInformation. ImsVisitedNetworkIdentifier | java.lang.String | recommended format is `epc.ims.mnc<MNC>.mcc<MCC>.3gppnetwork.org` according to IR65 | The visited network id extracted from the Invite request or from the registration data by the Diameter Leg Info feature | Try to extract from the triggered request
PaniMccsMncs | List<MccMnc> | MCC and MNC as String | A list of MCCs and MNCs extracted from the P-Access-Network-Info header from the request or from the registration data by the Extract Network Info Feature | Try to extract from the session state PvniMccMnc
PvniMccMnc | com.opencloud.sentinel.common.MccMnc | MCC and MNC as String | A list of MCC and MNC extracted from P-Visited-Network-Id header from the request or from the registration data by the Extract Network Info feature | Try to use the ISO country code
IsoCountryCode | java.lang.String | Two-letter ISO country code | An ISO country code determined by the Extract Network Info or Determine Location From MSRN feature. | Try to use `visited-network-id`
ChargeMode | com.opencloud.volte.sentinel.common.sessionstate.types.ChargeMode | ChargeMode enum value | Used to determine whether a OC-Roaming-Status header should be included on the outbound message. | Header will not be included.

#### Outputs

Name | Type | Format | Description
--- | --- | --- | ---
International | boolean | true or false | the international condition as defined by 3GPP 24.611
InternationalExHC | boolean | true or false | the international-exHC condition as defined by 3GPP 24.611
RoamingIndicator | boolean | true or false | true, if the subscriber is roaming
RoamingStatus | enum | `NOT_ROAMING`, `NATIONAL`, `INTERNATIONAL`, `UNKNOWN` | `NOT_ROAMING` if served user is in home network. `NATIONAL` if served user is in home country but not in the home mobile network. `INTERNATIONAL` if served user is not in his home country. `UNKNOWN` if there were not enough information to assert roaming.

### Error scenarios

These scenarios trigger the following reports.

Scenario | Report
--- | ---
`Sessionstate SentinelSelectionKey` network operator field is not set | `featureCannotStart`
`Sessionstate CallType` is null | `featureCannotStart`
No Called Party Leg available from the `LegManager` | `featureCannotStart`
Cannot determine a digit String to analyse in originating case | `featureIssuedWarning`
Cannot determine a digit String to analyse in terminating case | `featureIssuedWarning`
There is no prefix address list for a `visited-network-id` | `featureFailedToExecute`
No registration data found for `default-public-id` | `featureFailedToExecute`
Registration data fetched for `default-public-id` indicates this id is not a `default-public-id` | `featureFailedToExecute`

### Statistics

DetermineInternationalAndRoamingStatus statistics are tracked by the volte.sentinel.sip SBB and can be found under the following parameter set in REM:
SLEE-Usage → volte.sentinel.sip service → volte.sentinel.sip SBB → feature → DetermineInternationalAndRoamingStatus
or with rhino-stats:
"SLEE-Usage.Services.ServiceID[name=volte.sentinel.sip,vendor=OpenCloud,version=3.1.0].SbbID[name=volte.sentinel.sip,vendor=OpenCloud,version=3.1.0].feature.DetermineInternationalAndRoamingStatus"

Parameter | Type | Description
--- | --- | ---
    Started
| Counter | Incremented each time the feature runs
    FailedToStart
| Counter | Incremented when a fatal error occurs before feature execution
    IssuedWarning
| Counter | Incremented when a non-fatal error occurs during feature execution
    FailedDuringExecution
| Counter | Incremented when a fatal error occurs during feature execution
    TimedOut
| Counter | Incremented when feature execution does not complete within a reasonable time frame
    VisitedNetworkHeaderFound
| Counter | Incremented when the requestURI identity is in RegistrationRecords list of public identities.
    AccessNetworkMccFound
| Counter | Incremented when the mobile-Country-Code is found in the P-Access-Network-Info header.
    DeterminedInternationalUsingAccessNetworkMcc
| Counter | Incremented when the MCC prefix address list is used to determine whether the call is international.
    DeterminedInternationalUsingVisitedNetworkId
| Counter | Incremented when the visited-network-id prefix address list is used to determine whether the call is international.
    CouldNotGetPVisitedNetworkID
| Counter | Incremented when no visited network ID information could be found.
    HomeNetworkIdSetForNetworkOperatorIsEmpty
| Counter | Incremented when the Sentinel SIP configuration for the network operator has an empty `home-network-id` set (the feature cannot determine if the subscriber is roaming).
    InternationalRoaming
| Counter | Incremented when the feature determines that the served user is roaming in a foreign country.
    NationalRoaming
| Counter | Incremented when the feature determines that the served user is roaming in their home country.
    NotRoaming
| Counter | Incremented when the feature determines that the served user is on their home network.
    UnknownRoaming
| Counter | Incremented when the feature is unable to determine the served user’s roaming status.
    AddressNotMinimumLength
| Counter | Incremented when destination address is less than the configured minimum length
    AddressOnBlackList
| Counter | Incremented when destination address matches an entry in the `SkipDIRSAddressList`
    StatusDeterminedFromHeader
| Counter | Incremented when the roaming status is determined from a OC-Roaming-Status header on the incoming request.
    NoActionRequired
| Counter | Incremented when the feature determines that it does not need to do anything for the current invocation.

## DetermineChargeMode

This feature uses information from the incoming INVITE request to determine whether Ro Online charging should be applied to the session, by setting the MonitorCallOnly session state variable. The MonitorCallOnly variable affects whether Sentinel VoLTE should perform online charging through Diameter Ro, or only monitor the call. Online Charging through CAP is handled by a separate service composition, see Service Compositions for more details about this. Offline Charging and whether to use CDRs, Diameter Rf or both is controlled by the VoLTE Interim CDR Feature.

### Feature cheat sheet

B2BUA Instance | SAS Support | Originating / Terminating | Point in Session Plan | Network Operator Data | Subscriber Data | Stateful or Stateless | POJO Feature or SBB Feature
--- | --- | --- | --- | --- | --- | --- | ---
Any and All | No | Originating and Terminating | `SIPAccess_SessionAccept` | No | No | Stateless | POJO

### Session output variables

Session State variable name | Variable type | Comments
--- | --- | ---
    MonitorCallOnly
| boolean | True if the feature finds the Route Header “oc-charge-mode” Parameter set to `cap` or `offline`.
    ChargeMode
| ChargeMode (enum) | The charge mode determined by the feature.

### Statistics

DetermineChargeMode statistics are tracked by the sentinel.volte.sip SBB and can be found under the following parameter set in REM:
SLEE-Usage → sentinel.volte.sip service → sentinel.volte.sip SBB → feature → DetermineChargeMode
or with rhino-stats:
"SLEE-Usage.Services.ServiceID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].SbbID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].feature.DetermineChargeMode"

Name | Description
--- | ---
    Started
| Incremented each time the feature runs
    FailedToStart
| Incremented when a fatal error occurs before feature execution
    IssuedWarning
| Incremented when a non-fatal error occurs during feature execution
    FailedDuringExecution
| Incremented when a fatal error occurs during feature execution
    TimedOut
| Incremented when feature execution does not complete within a reasonable time frame
    MonitorOnly
| Incremented when the feature has set the MonitorCallOnly Session State field to true
    NonMonitorOnly
| Incremented when the feature has set the MonitorCallOnly Session State field to false
    Error
| Incremented when the feature was unable to determine the charge mode

### Behaviour

This feature checks information from the incoming SIP request in order to set a Session State variable which affects Sentinel VoLTE’s charging behaviour.

#### Values examined

Value Name | Source | Notes
--- | --- | ---
Route Header “oc-charge-mode” Parameter | Incoming SIP request | This is a custom parameter on the URI of the top-most route header. It is expected that this will be added by the S-CSCF based on iFCs.

#### Charge mode selection circumstances

Route Header “oc-charge-mode” Parameter | Resulting Charging behaviour
--- | ---
oc-charge-mode=ro | MonitorCallOnly set to false, Diameter Ro charging will be applied, ChargeMode set to `RO`
oc-charge-mode=cap | MonitorCallOnly set to true, Diameter Ro charging will not be applied, ChargeMode set to `CAP`
oc-charge-mode=offline | MonitorCallOnly set to true, Diameter Ro charging will not be applied, ChargeMode set to `OFFLINE`
oc-charge-mode has any other value | MonitorCallOnly set to false, Diameter Ro charging will be applied, ChargeMode set to `DEFAULT`
oc-charge-mode parameter absent | MonitorCallOnly set to false, Diameter Ro charging will be applied, ChargeMode set to `DEFAULT`

Note that the VoLTE Interim CDR Feature is configured to select whether interim CDRs and/or ACRs are used. It is used if Diameter Rf and/or Interim CDRs are selected during installation. It’s settings are independent of the `oc-charge-mode` Route Header parameter.

## DetermineInitialLegNames

This feature uses the Leg Manager to get the names of the original SIP legs established during call set up, and saves the values to a set of session state fields that may be used by other VoLTE features when they need to access a specific leg by name.

### Feature cheat sheet

B2BUA Instance | SAS Support | Originating / Terminating | Point in Session Plan | Network Operator Data | Subscriber Data | Stateful or Stateless | POJO Feature or SBB Feature
--- | --- | --- | --- | --- | --- | --- | ---
Both or either of MMTEL or SCC | No | Originating and Terminating | `SIPAccess_*PreCreditCheck` AND `SIPAccess_PartyResponse` | No | No | Stateless | POJO

### Prerequisite features

These features must run before DetermineInitialLegNames:

- DetermineCallType

### Session input and output variables

#### Session input variables

Session state variable name | Variable type
--- | ---
    CallType
| Enum

#### Session output variables

Session state variable name | Variable type | Comments
--- | --- | ---
    CurrentLocalLegName
| String | The name of the leg towards the local UE (that is, the calling party on an originating instance, or the called party on a terminating instance)
    CurrentRemoteLegName
| String | The name of the leg towards the remote UE (that is, the called party on an originating instance, or the calling party on a terminating instance)
    CurrentCallingLegName
| String | The name of the leg towards the calling party
    CurrentCalledLegName
| String | The name of the leg towards the called party

### Statistics

DetermineInitialLegNames statistics are tracked by the sentinel.volte.sip SBB and can be found under the following parameter set in REM:
SLEE-Usage → sentinel.volte.sip service → sentinel.volte.sip SBB → feature → DetermineInitialLegNames
or with rhino-stats:
"SLEE-Usage.Services.ServiceID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].SbbID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].feature.DetermineInitialLegNames"

Name | Description
--- | ---
    FeatureStarted
| Incremented each time the feature runs
    FeatureFailedToStart
| Incremented when Sentinel VoLTE encounters an error while attempting to start the feature
    FeatureIssuedWarning
| Incremented when a non-fatal problem is encountered and the feature issues a warning
    FeatureFailedDuringExecution
| Incremented when a fatal problem is encountered and the feature cannot execute correctly
    FeatureTimedOut
| Incremented when the feature takes too long to complete and Sentinel VoLTE aborts execution
    FeatureCallingLegNameSet
| Incremented when calling leg name is found
    FeatureCalledLegNameSet
| Incremented when called leg name is found

### Behaviour

#### Network pre-credit check

When invoked at the `SipAccess_NetworkPreCreditCheck` execution point the feature will do the following:

- Retrieve the leg that the initial INVITE arrived on and get its name.

- Set the `CurrentCallingLegName` session variable to the leg’s name.

- On an originating instance, set the `CurrentLocalLegName` session variable to the leg’s name;
  on a terminating instance, set the `CurrentRemoteLegName` session variable to the leg’s name.

#### SIP access party response

When invoked at the `SipAccess_PartyResponse` execution point the feature will do the following:

- Retrieve the leg that the response arrived on and get its name.

- Verify that the response is to an INVITE and has a 2XX status. (If it isn’t, the feature will stop here.)

- Set the `CurrentCalledLegName` session variable to the leg’s name.

- On an originating instance, set the `CurrentRemoteLegName` session variable to the leg’s name;
  on a terminating instance, set the `CurrentLocalLegName` session variable to the leg’s name.

## DetermineVoltePlanId

This feature uses information from an incoming `INVITE`, `MESSAGE` or `SUBSCRIBE` request, and from session state to set the plan ID in the Sentinel selection key . The plan ID affects which features will run for the call on the current AS instance. It also will set some Session State fields.

### Feature cheat sheet

B2BUA Instance | SAS Support | Originating / Terminating | Point in Session Plan | Network Operator Data | Subscriber Data | Stateful or Stateless | POJO Feature or SBB Feature
--- | --- | --- | --- | --- | --- | --- | ---
Any and All | No | Originating and Terminating | `SIPAccess_SessionAccept`, `SubscriptionAccept`, `SipTransaction_Accept` | Yes | No | Stateless | POJO

### Prerequisite features

These features must run before DetermineVoltePlanId:

- DetermineCallType

- SCCDetermineSessionType (Only required on SCC AS)

### Source Code

This feature’s source code is available in the Sentinel VoLTE SDK in the `volte-determine-plan-id` module pack. It can be viewed by using the `create-module` command in the SDK with that module pack, for example:

`> create-module new-planid-module opencloud#volte-determine-plan-id#volte/3.1.0;3.1.0.0`

This command will prompt you for information needed to create the new modules, once completed the original source for the feature can be found in the new modules.

The module-pack includes the following modules:

Module Name | Description
--- | ---
volte-determine-plan-id | Contains all of the code for this feature.

### Session input variables

Session State variable name | Variable type
--- | ---
    CallType
| Enum
    SCCSessionType
| Enum
    SentinelSelectionKey
| SentinelSelectionKey

### Session output variables

Session State variable name | Variable type | Comments
--- | --- | ---
    SentinelSelectionKey
| SentinelSelectionKey | Updated by the feature based on factors described in the Behaviour section.
    RequestIsForMmtelTransfer
| Boolean | Set to true if request is targeted at configured Session-Transfer-To-Own-Device special URI.
    ConferenceFactoryPSI
| String | Set if the SIP request URI is a conference factory PSI supported by the platform.

### Network operator data

Parameter | Type | Description | Default
--- | --- | --- | ---
    MmtelTransferNumber
| String | SIP or TEL URI for special Session-Transfer-To-Own-Device | none

### Statistics

DetermineVoltePlanId statistics are tracked by the sentinel.volte.sip SBB and can be found under the following parameter set in REM:
SLEE-Usage → sentinel.volte.sip service → sentinel.volte.sip SBB → feature → DetermineVoltePlanId
or with rhino-stats:
"SLEE-Usage.Services.ServiceID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].SbbID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].feature.DetermineVoltePlanId"

Name | Type | Description
--- | --- | ---
    Started
| Counter | Incremented each time the feature runs
    FailedToStart
| Counter | Incremented when a fatal error occurs before feature execution
    IssuedWarning
| Counter | Incremented when a non-fatal error occurs during feature execution
    FailedDuringExecution
| Counter | Incremented when a fatal error occurs during feature execution
    TimedOut
| Counter | Incremented when feature execution does not complete within a reasonable time frame
    NoPlanSelected
| Counter | Incremented when the feature fails to select an appropriate plan ID
    MmtelOriginatingPlanSelected
| Counter | Incremented when the feature selects the plan ID as “mmtel-orig”
    MmtelTerminatingPlanSelected
| Counter | Incremented when the feature selects the plan ID as “mmtel-term”
    MmtelConferencingPlanSelected
| Counter | Incremented when the feature selects the plan ID as “mmtel-conf”
    SccOriginatingPlanSelected
| Counter | Incremented when the feature selects the plan ID as “scc-orig”
    SccTerminatingPlanSelected
| Counter | Incremented when the feature selects the plan ID as “scc-term”
    SccTerminatingTadsOnlyPlanSelected
| Counter | Incremented when the feature selects the plan ID as “scc-term-tads”
    SccTerminatingAnchorOnlyPlanSelected
| Counter | Incremented when the feature selects the plan ID as “scc-term-anchor”
    SccReoriginationPlanSelected
| Counter | Incremented when the feature selects the plan ID as “scc-reorigination”
    SccAccessTransferPlanSelected
| Counter | Incremented when the feature selects the plan ID as “scc-access-transfer”
    ConferenceConfigurationNotFound
| Counter | Incremented when the feature is unable to find a valid conference PSI from configuration profiles
    PlanIDAlreadySet
| Counter | Incremented when the feature detects that a plan ID has already been selected

### Behaviour

This feature checks a series of values from session state, feature configuration, and the incoming SIP request in order to select the appropriate session plan to run, and possibly set some Session State fields.

#### Values examined

Value Name | Source | Notes
--- | --- | ---
Custom Route Header `oc-mode` Parameters | Incoming SIP request | These are custom parameters on the URI of the top-most route header. It is expected that these will be added by the S-CSCF based on iFCs.
SCCSessionType | Session State | This is set by the SCCDetermineSessionType feature when it detects the incoming request is for Access Transfer or Reorigination, as these requests do not come from the S-CSCF there should never be a oc-mode parameter on the route header.
Call Type | Session State | Set by the DetermineCallType feature.
Request URI | Incoming SIP request | Analysed to determine if it corresponds to a supported conference factory PSI (when a conference call is being requested).

| If the Request URI of the incoming sip request is a supported conference factory PSI, the PSI is stored in session state.

#### Custom Route Header Parameters

Sentinel VoLTE supports specific custom headers and header parameters to indicate or propagate certain conditions between nodes in the network.

- OC-Access-Transfer-Procedure Header

- OC-IM-CallReferenceNumber Header

- OC-Retarget Header

- OC-Replication-Information Header

- OC-Terminating-Domain Header

- Route Header Parameters

- X-Msw-Companion-Device Header

#### Plan ID selection circumstances

Route Header `oc-mode` Parameter | SCCSessionType | Call Type | SIP Request-URI Matches Conference PSI | Resulting Plan ID
--- | --- | --- | --- | ---
(Not Present) | Access Transfer | (Ignored) | (Ignored) | scc-access-transfer
(Not Present) | Reorigination | (Ignored) | (Ignored) | scc-reorigination
oc-mode=mmtel | (Ignored) | Originating | (Ignored) | mmtel-orig
oc-mode=mmtel | (Ignored) | Terminating | No | mmtel-term
oc-mode=mmtel | (Ignored) | Terminating | Yes | mmtel-conf
oc-mode=scc | (Ignored) | Originating | (Ignored) | scc-orig
oc-mode=scc | (Ignored) | Terminating | (Ignored) | scc-term
oc-mode=scc-tads | (Ignored) | Terminating | (Ignored) | scc-term-tads
oc-mode=scc-anchor | (Ignored) | Terminating | (Ignored) | scc-term-anchor

If | Then …​
--- | ---
The route header `oc-mode` parameter is not present and the SCCSessionType is not ‘Access Transfer’ or ‘Reorigination’ | The feature will proceed as if the route header `oc-mode` parameter was set to ‘mmtel’.
A Plan ID has already been set on the Sentinel Selection Key | The feature will not attempt to do any analysis or change the plan ID.

## DialPlanEnforcement

This feature analyses the request-uri of an originating trigger to determine if the dialed digits match the dial plan

### Feature cheat sheet

B2BUA Instance | SAS Support | Originating / Terminating | Point in Session Plan | Network Operator Data | Subscriber Data | Stateful or Stateless | POJO Feature or SBB Feature
--- | --- | --- | --- | --- | --- | --- | ---
MMTEL | Yes | Originating | `SipAccess_SessionCheck` | No | No | Stateless | POJO

### Prerequisite features

DialPlanEnforcement should run after the DetermineVoltePlanId feature.

### Session input and output variables

#### Session input variables

Session state variable name | Variable type | Comments
--- | --- | ---
    SentinelSelectionKey
| SentinelSelectionKey | Affects which configuration profile is used DialPlanEnforcement inspects the plan ID field to determine if the session is originating

#### Session output variables

Session state variable name | Variable type | Comments
--- | --- | ---
    RejectedCallAsDialPlanDoesNotMatch
| boolean | The call is being rejected
    AnnouncementID
| int | The announcement to play (for SipPlayAnnouncement)
    EndSessionAfterAnnouncement
| int | End the session with this sip response, after playing an announcement (for SipPlayAnnouncement)

### Statistics

DetermineInitialLegNames statistics are tracked by the sentinel.volte.sip SBB and can be found under the following parameter set in REM:
SLEE-Usage → sentinel.volte.sip service → sentinel.volte.sip SBB → feature → DialPlanEnforcement
or with rhino-stats:
"SLEE-Usage.Services.ServiceID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].SbbID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].feature.DialPlanEnforcement"

Name | Description
--- | ---
    FeatureStarted
| Incremented each time the feature runs
    FeatureFailedToStart
| Incremented when Sentinel VoLTE encounters an error while attempting to start the feature
    FeatureIssuedWarning
| Incremented when a non-fatal problem is encountered and the feature issues a warning
    FeatureFailedDuringExecution
| Incremented when a fatal problem is encountered and the feature cannot execute correctly
    FeatureTimedOut
| Incremented when the feature takes too long to complete and Sentinel VoLTE aborts execution
    IgnoringAddress
| Incremented when analysis is not required
    DialPlanMatched
| Incremented when the call is allowed as the dialed digits match the dial plan
    DialPlanIsNotMatched
| Incremented when the call is rejected as the dialed digits do not match the dial plan

### Configuration

The DialPlanEnforcement feature uses configuration data from the `DialPlanEnforcementConfigProfileTable` and the `NormalizationFeatureConfigProfileTable`.

#### DialPlanEnforcementConfigProfileTable

The profiles within this table have the following fields:

Parameter | Type | Description
--- | --- | ---
`EndSessionOnEnforcement` | boolean | Whether a session should be ended with an announcement if the dialed digits do not match the dial plan
`EndSessionAnnouncementID` | int | The announcement to play if the dialed digits do not match the dial plan. The announcement ID should correspond to an ID that has been configured for SipPlayAnnouncement
`EndSessionSipResponseCode` | int | The SIP response code to use when ending the session
`PrefixesToCheck` | String[] | Set of prefixes to check for in the dialed digit string. PrefixesToCheck may be empty. The length of PrefixesToCheck, MinimumNumberOfDigitsPerPrefix and MaximumNumberOfDigitsPerPrefix must be the same
`MinimumNumberOfDigitsPerPrefix` | int[] | Minimum allowed length of dialed digits (after the prefix) per prefix. Must have the same number of elements as PrefixesToCheck. The value of each element may be 0 and must be less then the corresponding element in MaximumNumberOfDigitsPerPrefix
`MaximumNumberOfDigitsPerPrefix` | int[] | Maximum allowed length of dialed digits (after the prefix) per prefix. Must have the same number of elements as PrefixesToCheck. The value of each element in MaximumNumberOfDigitsPerPrefix must be greater than the corresponding element in MinimumNumberOfDigitsPerPrefix
`DefaultMaximumNumberOfDigits` | int | The required length of dialed digits if there are no prefixes configured or matched. The value must be within the range 7 .. 20.

| DialPlanEnforcement checks for prefixes in order from the longest prefix first.

#### NormalizationFeatureConfigProfileTable

The DialPlanEnforcement uses the following fields from profiles within this table:

Parameter | Type | Description
--- | --- | ---
`NationalPrefix` | String | National dialling prefix (for example, 0)
`InternationalEscapeCode` | String | Escape code for dialing international numbers (for example, 00)
`MinNormalizableLength` | Integer | The minimum length of an address for it to be normalizable

### Behaviour

The first step is to determine if DialPlanEnforcement should be applied to the incoming trigger. The following conditions must be satisfied:

- the sentinel selection key plan ID field is MMTEL_ORIG

- the request-uri is a phone number (either a Tel URL or a SIP URI with a phone number in the user part)

- the DialPlanEnforcement feature is enabled (`config.EndSessionOnEnforcement` is true)

- the number of dialed digits is greater than, or equal to, the minimum number for analysis

| The minimum number for analysis is the minimum value of these properties: `normalizerconfig.MinNormalizableLength` `config.DefaultMaximumNumberOfDigits` For each configured prefix: if allowed minimum == 0, prefix length + allowed maximum else prefix length + allowed minimum

If DialPlanEnforcement should be applied, then the following analysis of the request-uri is conducted.

1. If the dialed digits is an international number, starts `normalizerconfig.NationalPrefix` or starts with `normalizerconfig.InternationalEscapeCode` then accept the trigger otherwise continue analysis.

2. Check for prefixes in the dialed digit string in order from the longest prefix first. If there is a prefix match, then compare the number of digits after the prefix to the allowed minimum and allowed maximum configured for that prefix. If the number of digits in within range accept the trigger, otherwise reject the trigger by requesting an announcement to be played (`config.EndSessionAnnouncementID`) and ending the session.

3. If no prefix match is made, compare the number of dialed digits to `config.DefaultMaximumNumberOfDigits`. If the number of digits is less than, or equal to, `config.DefaultMaximumNumberOfDigits` then accept the trigger otherwise reject the trigger by requesting an announcement to be played (config.EndSessionAnnouncementID) and ending the session.

| A SAS event is generated when DialPlanEnforcement accepts a trigger or rejects a trigger. Statistics are incremented when DialPlanEnforcement ignores a trigger, accepts a trigger or rejects a trigger.

## FeatureCapsManagement

This feature sets values for the Feature-Caps header on outgoing messages based on data from the session’s FeatureCapsManager

### Feature cheat sheet

B2BUA Instance | SAS Support | Originating / Terminating | Point in Session Plan | Network Operator Data | Subscriber Data | Stateful or Stateless | POJO Feature or SBB Feature
--- | --- | --- | --- | --- | --- | --- | ---
SCC | No | Originating and Terminating | `SipAccess_SubscriberCheck`, `SipAccess_PartyRequest`, `SipAccess_PartyResponse`, `SipAccess_ServiceTimer`, `SipInstructionExecutionFailure`, `SipMidSession_PartyRequest`, `SipMidSession_PartyResponse`, `SipEndSession` | No | No | Stateless | POJO

### Session input variables

Session State variable name | Variable type | Comments
--- | --- | ---
    FeatureCapsManager
| FeatureCapsManager | Contains information about which Feature-Caps header values should be applied to outgoing messages on each SIP leg

### Statistics

FeatureCapsManagement statistics are tracked by the sentinel.volte.sip SBB and can be found under the following parameter set in REM:
SLEE-Usage → sentinel.volte.sip service → sentinel.volte.sip SBB → feature → FeatureCapsManagement
or with rhino-stats:
"SLEE-Usage.Services.ServiceID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].SbbID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].feature.FeatureCapsManagement"

Name | Description
--- | ---
    Started
| Incremented each time the feature runs
    FailedToStart
| Incremented when a fatal error occurs before feature execution
    IssuedWarning
| Incremented when a non-fatal error occurs during feature execution
    FailedDuringExecution
| Incremented when a fatal error occurs during feature execution
    TimedOut
| Incremented when feature execution does not complete within a reasonable time frame
    StrippedValuesFromMessage
| Incremented when the feature removes Feature-Caps parameter values from a message
    AddedValuesToMessage
| Incremented when the feature adds Feature-Caps parameter values to a message

### Behaviour

This feature interacts with the session’s `FeatureCapsManager` interface and its associated `LegFeatureCapsHandler` interfaces. These interfaces are documented in the Sentinel VoLTE SPI Javadoc.

When invoked, the FeatureCapsManagement feature iterates over all SIP legs associated with the current session. For each leg, the feature will check if there is a `LegFeatureCapsHandler` for that leg in the session’s `FeatureCapsManager`. If there is a `LegFeatureCapsHandler` for the leg, the feature will look for SIP INVITE requests and responses in the leg’s outgoing message queue. Each INVITE request or response found in the queue will be processed as described below. Each individual message in the queue will only be processed once (i.e. if the feature is invoked multiple times before a given message is sent, that message will only be processed on the first time that it is seen).

#### Values to Strip

When a message is processed, the feature will first determine if the `LegFeatureCapsHandler` has any `Feature-Caps` values to strip. If so, the feature will look for those values on any existing Feature-Caps header on the message. If the values are found, they will be removed from the given header.

#### Values to Add

After stripping values, the feature will check the `LegFeatureCapsHandler` for `Feature-Caps` values to add to the message. If values are found, then a new `Feature-Caps` header will be appended to the message. The new header will contain all of the values to add.

It is possible for the `LegFeatureCapsHandler` to indicate that new `Feature-Caps` values are currently suppressed for the leg. If this is the case, the feature will forgo adding any new `Feature-Caps` values to the outgoing message.

## FetchIMCSI

The FetchIMCSI feature retrieves CAMEL Subscription Information (CSI) from the HLR for charging purposes .

### Feature cheat sheet

Feature Script Name | FetchIMCSI
MMTel or SCC | Both
Call-Type | Orig or Term
Session Plan | mmtel-orig, scc-tads-only
Execution Points | SipAccess_SubscriberCheck
Network Operator Config | Yes
Subscriber Config | No
POJO or SBB | POJO
Feature FSMs | None
Feature Parameters | None
SAS Support | Yes
RA Entity Links | sentinel-sis-in-hlr

### Prerequisite features

- DetermineCallType

- DetermineChargeMode

### Network Operator Data

The FetchIMCSI feature depends on configuration from four profile tables:

- The `FetchIMCSIConfigProfileTable` provides the basic configuration for the feature.

- The `FetchIMCSIFeatureServiceKeyProfileTable` provides mapping between orig and term service keys.

- The `HLRConfigProfileTable` provides configuration for sending requests to the HLR.

- The `CapChargingConfigProfileTable` provides configuration for how the feature should behave on non-roaming terminating calls.

#### FetchIMCSIConfigProfileTable

Basic feature configuration is stored on a profile table called `FetchIMCSIConfigProfileTable`.

Data is scoped according to a Sentinel selection key.

Attribute Name | Type | Default | Description
--- | --- | --- | ---
    FetchImcsiEnabledOnOrigCall
| boolean | false | Enables/Disables the feature for originating calls.
    RequestedTdpOnOrigCall
| int | 1 (orig), 12 (term) | Trigger Detection Point to request on originating calls, determines whether the O-CSI or T-CSI is retrieved from the HLR. (1, 2, or 3 for O-CSI; 12 for T-CSI).
    FetchImcsiEnabledOnTermCall
| boolean | false | Enables/Disables the feature for terminating calls.
    RequestedTdpOnTermCall
| int | 1 (term), 12 (term) | Trigger Detection Point to request on terminating calls, determines whether the O-CSI or T-CSI is retrieved from the HLR. (1, 2, or 3 for O-CSI; 12 for T-CSI).

#### FetchIMCSIFeatureServiceKeyProfileTable

This profile table is used to provide mappings between orig and term TDP service keys. These mappings are used when the TDP requested is for a different call type (i.e. originating/terminating) than the session.

Data is scoped according to a Sentinel selection key, with a suffix which corresponds the the service key to map from. A `default` suffix can be used to define a mapping for keys that do not have specific profiles.

Attribute Name | Type | Default | Description
--- | --- | --- | ---
    SourceServiceKey
| String | None | The service key to map from, or 'default' to match all service keys that do not have a more specific match for the selection key.
    TargetServiceKey
| int | None | The service key to map to.

#### HLRConfigProfileTable

This profile table provides the configuration for connecting to the HLR. It is shared across all features that communicate with the HLR.

For more information refer to HLR MAP Configuration.

#### CapChargingConfigProfileTable

The feature checks a single field on the `OnlyChargeTerminatingCallsIfInternationalRoaming` profile table. This is used to determine if the feature needs to do anything on a non-roaming terminating call.

For more information refer to CapChargingConfigProfileTable.

### Session Input Variables

Variable name | Type | Comments
--- | --- | ---
ChargeMode | Enum | The feature will only run if the charge mode is `CAP`.
CallType | Enum | Affects whether `orig` or `term` feature config is loaded, and depending on the TDP, whether the service key is mapped.
SentinelSelectionKey | SentinelSelectionKey | Affects which profiles are loaded from each configuration table.

### Session Output Variables

Variable name | Type | Comments
--- | --- | ---
    OcImTdpHeader
| String | Contains the data that was retrieved from the HLR, ready for inclusion in a header on the SIP message towards the IMSSF.

### Statistics

FetchIMCSI statistics are tracked by the sentinel.volte.sip SBB and can be found under the following parameter set in REM:
SLEE-Usage → sentinel.volte.sip service → sentinel.volte.sip SBB → feature → FetchIMCSI
or with rhino-stats:
"SLEE-Usage.Services.ServiceID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].SbbID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].feature.FetchIMCSI"

    Statistic
| Type | Description
    Started
| Counter | Incremented when the feature is invoked.
    FailedToStart
| Counter | Incremented when Sentinel VoLTE encounters an error while attempting to start the feature.
    IssuedWarning
| Counter | Incremented when a non-fatal problem is encountered and the feature issues a warning.
    FailedDuringExecution
| Counter | Incremented when a fatal problem is encountered and the feature cannot execute correctly.
    TimedOut
| Counter | Incremented when the feature takes too long to complete and Sentinel VoLTE aborts execution.
    ExecutionNotRequired
| Counter | Incremented when the feature determines that it does not need to do anything.
    RequestSent
| Counter | Incremented when an ATSI request is sent to the HLR.
    RequestFailed
| Counter | Incremented when no result is received after attempting to send a request.
    ReceivedATSIResult
| Counter | Incremented when an ATSI result is received from the HLR.
    DialogOpenRefused
| Counter | Incremented when a DialogOpenRefused event is received after attempting to send a request.
    UserAbortedDialog
| Counter | Incremented when a UserAbortedDialog event is received after attempting to send a request.
    ProviderAbortedDialog
| Counter | Incremented when a ProviderAbortedDialog event is received after attempting to send a request.
    OperationErrorOccurred
| Counter | Incremented when a OperationErrorOccurred event is received after attempting to send a request.
    InvalidResponse
| Counter | Incremented when an ATSI result is received for a request, but it does not contain the requested data.
    ServiceKeyMappingFailed
| Counter | Incremented when a service key requires mapping, but no mapped value can be found.
    FetchedIMCSI
| Counter | Incremented when the feature successfully retrieved CSI information from the HLR.
    AttachedToMapRequestAci
| Counter | Incremented when the feature creates and attaches to the activity for the MAP request.
    DetachedFromMapRequestAci
| Counter | Incremented when the detaches from the activity for the MAP request.
    ResponseLatency
| Sample | Time from sending the ATSI request to receiving the ATSI result, sampled on receipt of the result.

### Installation

FetchIMCSI is a GSM only feature and as such will only be deployed if GSM mode is selected in the installer. Additionally the feature will only be enabled in its configuration profile if explicitly done so in the installer. The feature is only useful when CAP charging is being used, so the option to enable it will only be given by the installer if CAP charging is selected.

### Behaviour

The FetchIMCSI feature retrieves the O-CSI or T-CSI data for a subscriber from the HLR. The data in the response is extracted and put into a format for use in an OC-IM-TDP SIP header, which is sent to the IMSSF when doing CAP charging.

#### Sending the Request

When initially triggered, the feature will construct a Any Time Subscription Interrogation (ATSI) request in order to retrieve the required data from the HLR.

##### Execution Conditions

Before creating the request, the feature will check that the following conditions are met:

1. The enabled flag corresponding to the call type is `true` in the feature configuration profile.

2. The charge mode for the call is `CAP`

3. If the call is terminating and not international roaming, the `OnlyChargeTerminatingCallsIfInternationalRoaming` config flag is `false`.

If any of these conditions is not met, the feature will immediately finish execution without sending a request.

##### The ATSI Request

If the conditions are met, the feature will create the ATSI request towards the HLR.

The subscriber identity to request information for will be a digit string taken from the default public ID in the served user’s registration data. If a digit string is not found in the default public ID, then the feature will attempt to retrieve one from the `Subscriber` session state field. If `Subscriber` field also does not have an appropriate ID, then the feature will abort its attempt to create a request and record an error.

The data the feature requests from the HLR depends on the Requested TDP field corresponding to the call type in the feature configuration profile. The request will either be for the `O_CSI` or the `T_CSI` according to the following table:

TDP Value | Requested Data
--- | ---
2 or 3 | O_CSI
12 | T_CSI

Once the request is created, a MAP dialog will be opened to the HLR and the request will be sent. The feature will then enter a waiting state until a response is received.

#### Processing the Result

On receipt of an ATSI result from the HLR, the feature will attempt to extract the information within, and format it into an `OC-IM-TDP` header. This header will be put into the `OcImTdpHeader` session state field.

##### OC-IM-TDP Header

This header is formatted as a comma separated list of `property=value` pairs. It has the following data:

Property Name | Value
--- | ---
    bcsmTriggerDetectionPoint
| `collectedInfo` if the CallType is originating, `termAttemptAuthorized` if it is terminating.
    defaultCallHandling
| `continueCall` or `releaseCall` based on the `DefaultCallHandling` field in the requested TDP data in the ATSI result. May be absent if the field was empty in the result.
    serviceKey
| See below.
    scfAddress.address
| The address part of the `GsmSCF_Address` field in the requested TDP data in the ATSI result.
    scfAddress.nature
| The nature part of the `GsmSCF_Address` field in the requested TDP data in the ATSI result.
    scfAddress.numberingPlan
| The numbering plan part of the `GsmSCF_Address` field in the requested TDP data in the ATSI result.

##### Service Key

The `serviceKey` property in the final `OC-IM-TDP` header has special handling. If the requested information matches the session’s call type (i.e. `O_CSI` is requested on an originating call, or `T_CSI` requested on a terminating call), then the final `serviceKey` value used in the header will match the value of the `ServiceKey` field in the requested TDP data in the ATSI result. If the requested information does not match the call type, then the feature will attempt to map the service key to a different value based on the service key mapping profile.

To find the mapped value, the feature will search for a profile on the `FetchIMCSIFeatureServiceKeyProfileTable` profile table. The profile name used will be the sentinel selection key with the service key received in the ATSI result as a suffix. Standard selection key matching will apply, where the profile with the longest matching selection key and a matching service key suffix will be used. If no matching profile with the service key is found, then the feature will reattempt the search with `default` as the suffix. If still no profile is found, the feature will use the original, unmapped service key in the `OC-IM-TDP` header. If a profile is found, the value of the `TargetServiceKey` will be used in the `OC-IM-TDP` header.

#### Handling of Request Failure

If the feature fails to retrieve the requested information for any reason, it will increment the feature statistic that best explains why, and report the details to SAS. Beyond that, the feature will abort execution and no further action will be taken.

## IMSIDLookup

This feature reads Third Party Registration information stored in the HSS as Transparent Data, and writes it into session state. Information is read during INVITE processing. It reads the Third Party Registration information via the Sh Cache Microservice RA, which connects to the Sh Cache Microservice. For more information refer to Data Stored by the Third Party Registrar in HSS.

### Feature cheat sheet

B2BUA Instance | SAS Support | Originating / Terminating | Point in Session Plan | Network Operator Data | Subscriber Data | Stateful or Stateless | POJO Feature or SBB Feature
--- | --- | --- | --- | --- | --- | --- | ---
Both or either of MMTEL or SCC | Yes | Originating, Forwarding, and Terminating | SIP Access Session Pre-Credit Check | No | No | Stateless | SBB

### Prerequisite features

These features must run before IMSIDLookup:

- Determine Call Type

- SIP Subscriber Determination— in order to know who the subscriber is for the call.

### Source Code

This feature’s source code is available in the Sentinel VoLTE SDK in the `volte-imsid-lookup` module pack. It can be viewed by using the `create-module` command in the SDK with that module pack, for example:

`> create-module new-imsid-module opencloud#volte-imsid-lookup#volte/3.1.0;3.1.0.0`

This command will prompt you for information needed to create the new modules, once completed the original source for the feature can be found in the new modules.

The module-pack includes a single module:

Module Name | Description
--- | ---
volte-imsid-lookup | Contains the feature’s code.

### Session input and output variables

#### Session input variables

Session State variable name | Variable type
--- | ---
Subscriber | String

| This is the IMS Public Identity for the Served User, and is extracted from the SIP INVITE.

#### Session output variables

Session State variable name | Variable type | Comments
--- | --- | ---
    RegistrationRecords
| List<RegistrationRecord> | The list of registration records for the subscriber
    IsLoggedIn
| boolean | True, if the feature was able to set both IDs
    CMSISDN
| String | The correlation MSISDN registered for the subscriber
    HasCMSISDN
| boolean | True if the CMSISDN is set

### Statistics

IMSIDLookup statistics are tracked by the IMSIDLookup SBB and can be found under the following parameter set:
SLEE-Usage ▶ sentinel.volte.sip service ID ▶ IMSIDLookup SBB ID.

Name | Type | Description
--- | --- | ---
    Invoked
| Counter | Incremented when the feature runs.
    FeatureError
| Counter | Incremented when a fatal error occurs during feature execution.
    NoSubscriberSpecified
| Counter | Incremented when the feature is unable to determine which subscriber to retrieve IDs for.
    IMSIDRetrieveSuccess
| Counter | Incremented when IDs are successfully retrieved and decoded.
    IMSIDRetrieveFail
| Counter | Incremented when ID retrieval or decoding fails.
    CacheQueried
| Counter | Incremented when a query is made to the Sh Cache Microservice.
    CacheIndicatedQuerySuccess
| Counter | Incremented when a success response is received from the Sh Cache Microservice.
    CacheIndicatedQueryFailure
| Counter | Incremented when a failure response is received from the Sh Cache Microservice.
    SubscriberNotRegistered
| Counter | Incremented when the searched subscriber is not present in the Sh Cache Microservice or has no valid registration.
    RegistrationOutOfSync
| Counter | Incremented when the searched subscriber information is not consistent between the network and the Sh Cache Microservice.
    ResponseLatency
| Sampled | Records elapsed time between requesting data from the Sh Cache Microservice and getting a response (in milliseconds).

### Behaviour

The feature queries the HSS using an Access Key of the IMS Public Identity of the Served User and the Service Indication of `opencloud-3rd-party-registrar`.

#### User logged in

The `RegistrationRecords` session state field is set to a `List` of `RegistrationRecord`. Each element in the list indicates a device, with public and private IDs, that the subscriber is registered on. If the subscriber is registered on only one device, there is only one element in the list. If the subscriber is simultaneously registered on (say) four devices, there will be four elements in the list.

The `CMSISDN` field will be set if it is present in the data registered for the user. If the subscriber is simultaneously registered on multiple devices, this value will not be set.

#### User not logged in

If the user is not logged in, the feature finishes execution without modifying any state.

## IMSIDLookupFromCassandraIN

This feature reads Third Party Registration information stored in the Cassandra Database, and writes it into session state. Information is read during InitialDP processing. It reads the Third Party Registration information via the Cassandra CQL RA. For more information refer to Cassandra storage.

| From Sentinel 3.1.0 if several registration records are present for the IMPU the feature will select the valid (newest) registration per UE based on private identity, +sip.instance, and the creation time of the record. Prior to 3.1.0 it was not guaranteed that the correct registration would be used.

### Feature cheat sheet

B2BUA Instance | Originating / Terminating | Point in Session Plan | Network Operator Data | Subscriber Data | Stateful or Stateless | POJO Feature or SBB Feature
--- | --- | --- | --- | --- | --- | ---
SCC | Terminating | DirectAccessNetworkCheck | No | No | Stateless | SBB

### Prerequisite features

These features must run before IMSIDLookupFromCassandraIN:

- SS7 Subscriber Determination Feature

### Session input and output variables

#### Session input variables

Session State variable name | Variable type
--- | ---
Subscriber | String

| This is the IMS Public Identity for the Served User, and is extracted from the InitialDP.

#### Session output variables

Session State variable name | Variable type | Comments
--- | --- | ---
    IsLoggedIn
| boolean | True, if the feature was able to find a valid registrarion record for the subscriber.

### Statistics

IMSIDLookupFromCassandraIN statistics are tracked by the IMSIDLookupFromCassandraIN feature and can be found under the following parameter sets:

SLEE-Usage ▶ sentinel.volte.ss7 service ID ▶ sentinel.volte.ss7 SBB ID ▶ IMSIDLookupFromCassandraIN feature.

Name | Type | Description
--- | --- | ---
    Started
| Counter | Incremented when the feature runs.
    FailedToStart
| Counter | Incremented when Sentinel VoLTE encounters an error while attempting to start the feature.
    IssuedWarning
| Counter | Incremented when a non-fatal problem is encountered and the feature issues a warning.
    FailedDuringExecution
| Counter | Incremented when a fatal problem is encountered and the feature cannot execute correctly.
    TimedOut
| Counter | Incremented when the feature takes too long to complete and Sentinel VoLTE aborts execution.

SLEE-Usage ▶ sentinel.volte.ss7 service ID ▶ volte.sentinel.volte-imsid-lookup-cassandra-ss7-feature SBB ID.

Name | Type | Description
--- | --- | ---
    Started
| Counter | Incremented when the feature runs.
    FailedToStart
| Counter | Incremented when Sentinel VoLTE encounters an error while attempting to start the feature.
    IssuedWarning
| Counter | Incremented when a non-fatal problem is encountered and the feature issues a warning.
    FailedDuringExecution
| Counter | Incremented when a fatal problem is encountered and the feature cannot execute correctly.
    TimedOut
| Counter | Incremented when the feature takes too long to complete and Sentinel VoLTE aborts execution.
    CassandraQueried
| Counter | Incremented when Cassandra is queried for a subscriber’s registration.
    NoSubscriberSpecified
| Counter | Incremented when no subscriber is specified for the query.
    SubscriberNotRegistered
| Counter | Incremented when the returned subscriber from Cassandra is not registered.
    IMSIDRetrieveFail
| Counter | Incremented when the Cassandra lookup fails.
    IMSIDRetrieveSuccess
| Counter | Incremented when the Cassandra lookup succeeds.
    FeatureError
| Counter | Incremented when a feature error occurs.
    ResponseLatency
| Sampled | Records elapsed time between querying the Cassandra database and getting a response (in milliseconds).

### Behaviour

The feature queries the Cassandra Database using a Primary Key of the IMS Public Identity of the Served User. If a valid registration for the subscriber is found, the `IsLoggedIn` session state field will be set to true. Otherwise it will be set to false.

## IMSIDLookupFromCassandraSIP

This feature reads Third Party Registration information stored in the Cassandra Database, and writes it into session state. Information is read during INVITE processing. It reads the Third Party Registration information via the Cassandra CQL RA. For more information refer to Cassandra storage.

### Feature cheat sheet

B2BUA Instance | SAS Support | Originating / Terminating | Point in Session Plan | Network Operator Data | Subscriber Data | Stateful or Stateless | POJO Feature or SBB Feature
--- | --- | --- | --- | --- | --- | --- | ---
Both or either of MMTEL or SCC | No | Originating, Forwarding, and Terminating | SIP Access Session Pre-Credit Check | No | No | Stateless | POJO

### Prerequisite features

These features must run before IMSIDLookupFromCassandraSIP:

- Determine Call Type

- SIP Subscriber Determination— in order to know who the subscriber is for the call.

### Source Code

This feature’s source code is available in the Sentinel VoLTE SDK in the `volte-imsid-lookup-cassandra-sip` module pack. It can be viewed by using the `create-module` command in the SDK with that module pack, for example:

`> create-module new-imsid-cassandra-module opencloud#volte-imsid-lookup-cassandra-sip#volte/3.1.0;3.1.0.0`

This command will prompt you for information needed to create the new modules, once completed the original source for the feature can be found in the new modules.

The module-pack includes a single module:

Module Name | Description
--- | ---
volte-imsid-lookup-cassandra-sip | Contains the feature’s code.

### Session input and output variables

#### Session input variables

Session State variable name | Variable type
--- | ---
Subscriber | String

| This is the IMS Public Identity for the Served User, and is extracted from the SIP INVITE.

#### Session output variables

Session State variable name | Variable type | Comments
--- | --- | ---
    RegistrationRecords
| List<RegistrationRecord> | The list of registration records for the subscriber
    IsLoggedIn
| boolean | True, if the feature was able to set both IDs
    CMSISDN
| String | The correlation MSISDN registered for the subscriber
    HasCMSISDN
| boolean | True if the CMSISDN is set

### Statistics

IMSIDLookupFromCassandraSIP statistics are tracked by the IMSIDLookupFromCassandraSIP feature and can be found under the following parameter set:
SLEE-Usage ▶ sentinel.volte.sip service ID ▶ sentinel.volte.sip SBB ID ▶ IMSIDLookupFromCassandraSIP.

Name | Type | Description
--- | --- | ---
    Started
| Counter | Incremented when the feature runs.
    FailedToStart
| Counter | Incremented when Sentinel VoLTE encounters an error while attempting to start the feature.
    IssuedWarning
| Counter | Incremented when a non-fatal problem is encountered and the feature issues a warning.
    FailedDuringExecution
| Counter | Incremented when a fatal problem is encountered and the feature cannot execute correctly.
    FeatureError
| Counter | Incremented when a feature error occurs.
    TimedOut
| Counter | Incremented when the feature takes too long to complete and Sentinel VoLTE aborts execution.
    NoSubscriberSpecified
| Counter | Incremented when the feature is unable to determine which subscriber to retrieve IDs for.
    IMSIDRetrieveSuccess
| Counter | Incremented when IDs are successfully retrieved and decoded.
    IMSIDRetrieveFail
| Counter | Incremented when ID retrieval or decoding fails.
    CassandraQueried
| Counter | Incremented when a query is made to Cassandra.
    MultipleDevicesRegistered
| Counter | Incremented when multiple registered devices have been detected.
    SubscriberNotRegistered
| Counter | Incremented when could not find an active subscriber.
    RegistrationOutOfSync
| Counter | Incremented when the searched subscriber information is not consistent between the network and the database.
    ResponseLatency
| Sampled | Records elapsed time between querying the Cassandra database and getting a response (in milliseconds).

### Behaviour

The feature queries the Cassandra Database using a Primary Key of the IMS Public Identity of the Served User.

#### User logged in

The `RegistrationRecords` session state field is set to a `List` of `RegistrationRecord`. Each element in the list indicates a device, with public and private IDs, that the subscriber is registered on. If the subscriber is registered on only one device, there is only one element in the list. If the subscriber is simultaneously registered on (say) four devices, there will be four elements in the list.

The `CMSISDN` field will be set if it is present in the data registered for the user. If the subscriber is simultaneously registered on multiple devices, this value will not be set.

#### User not logged in

If the user is not logged in, the feature finishes execution without modifying any state.

## SetOcsAnnouncementID

SetOcsAnnouncementID schedules configurable announcements to the subscriber based on Credit-Control-Answers

The feature schedules charging announcements as defined by TS 32.281 as well as announcements for out-of-credit (4012 CCA result code), low balance (Low-Balance-Indicator AVP), and for custom OC-Play-Announcement-Id AVPs.

The feature runs on every successful and 4012 credit check result and analyses the CCA for announcement triggers:

- `Multiple-Services-Credit-Control` AVP containing `Announcement-Information` AVP;

- `OC-Play-Announcement-Id` AVP;

- low balance AVP; or

- result code 4012.

If the CCA contains such a trigger then the feature schedules the relevant announcement either immediately or on a timer relative to quota exhaustion. The feature is able to schedule multiple announcements to be played.

The feature also runs on each party request for a terminating call to determine whether the session has been established and so if a reauthorization request should be triggered or whether any timers should be set relative to quota exhaustion to start announcements. The feature runs on timer expiry to start any announcements that were scheduled on timers.

### Feature cheat sheet

B2BUA Instance | SAS Support | Originating / Terminating | Point(s) in Session Plan | Network Operator Data | Subscriber Data | Stateful or Stateless | POJO Feature or SBB Feature | Other notes
--- | --- | --- | --- | --- | --- | --- | --- | ---
MMTEL. | Yes | Originating, Forwarding, and Terminating | `SipAccess_PartyRequest` `SipAccess_ServiceTimer` `SipAccess_CreditAllocatedPostCC` `SipMidSession_CreditAllocatedPostCC` `SipAccess_CreditLimitReachedPostCC` `SipMidSession_CreditLimitReachedPostCC` | Yes | No | Stateless | POJO |

### Behaviour

Announcements requested in the Announcement-Information AVP are played in preference to other announcements. Announcements requested in the OC-Play-Announcement-Id AVP are played if no Announcement-Information announcements are present and configured announcement IDs for out-of-credit (4012 CCA result code) or low balance (Low-Balance-Indicator AVP) are only played if no Announcement-Information or OC-Play-Announcement-Id AVPs were present.

Call phase | Announcement-Information AVP | Low Balance Indicator AVP | 4012 Out-of- Credit | Behaviour
--- | --- | --- | --- | ---
Early media | Present | Not present | Not present | Charging announcement played, call continues
Early media | Present | Present | Not present | Charging announcement played, call continues (configured low balance announcement not played)
Early media | Present | Not present | Present | Charging announcement played, call ends
Early media | Not present | Present | Not present | Low balance feature configured announcement played, call continues
Early media | Not present | Present | Present | Out of credit feature configured announcement played, call ends
Mid call | Present | Not present | Not present | Charging announcement played, call continues
Mid call | Present | Present | Not present | Charging announcement played, call continues (configured low balance announcement not played)
Mid call | Present | Not present | Present | Charging announcement played, call ends
Mid call | Not present | Present | Not present | Low balance feature configured announcement played, call continues
Mid call | Not present | Present | Present | Out of credit feature configured announcement played, call ends

### Announcements for terminating user

It is not possible to play announcements to the terminating subscriber after the initial credit check as the session has not yet been established. Announcements requested by Announcement-Information AVPs to be played to the terminating party in the initial credit check are not played. If other announcements were requested when running as a terminating instance then a reauthorization request will be sent once the session is established. Any announcements in the response to this subsequent reauthorization request will be played. The reauthorization request can be delayed for a number of milliseconds using the `ChargingReauthDelayMillis` configuration field.

Mid call announcements to the terminating subscriber will be played immediately.

### Charging Announcements

The Announcement-Information AVP and its child AVPs were introduced in 3GPP Rel. 13 but Sentinel does support receiving them in Rel. 12.

Child AVP | Behaviour
--- | ---
    Announcement-Identifier
| Contains the ID for the announcement. This must be present and non-zero.
    Variable-Part
| Ignored
    Time-Indicator
| If present and non-zero a timer will be set relative to quota exhaustion and the announcement scheduled on timer expiry. If zero the announcement will be scheduled once the quota is exhausted and the call ended. If a credit check occurs before the timer fires or quota is exhausted then the announcement will not be played. An announcement with Time-Indicator 0 will only be played if the CCA contained a Final-Units-Indication AVP.
    Quota-Indicator
| If present this determines whether the user will be charged for the announcement. If not present, local announcement configuration will be used instead. This is ignored for early media announcements.
    Announcement-Order
| If multiple announcements are set in the CCA this should be used to order them.
    Play-Alternative
| If present determines whether the announcement should be played to the served or remote user. If not present the announcement will be played to the served user. If multiple announcements are present only announcements to the party with the lowest Announcement-Order will be played.
    Privacy-Indicator
| Ignored. The announcement is only to the requested party.
    Language
| If present this will be used in the request to the MRF, otherwise the determined language will be used.

### Low Balance Announcements

If the LowBalanceIndicator AVP is set in a successful CCA-I or CCA-U then a low balance announcement will be played (either configured or via the OC-Play-Announcement-Id-AVP) and a session state field is set to mark that a low balance announcement has been played. Subsequent credit checks will not trigger another low balance announcement unless the previous credit check response did not have the LowBalanceIndicator AVP set.

### Out of Credit Announcements

If a credit check response contains a 4012 result code then:

- For early originating sessions, the feature will schedule the configured early dialog announcement if an announcement was not supplied in the CCA and then end the session with the appropriate sip error response according to the CCA result code.

- For early terminating and forwarding sessions, the feature will not schedule an announcement and will end the session with a 480 Temporarily Unavailable response.

- For confirmed originating and terminating sessions, the feature will schedule the configured mid session announcement if an announcement was not supplied in the CCA and then end the session.

### Session state input variables

Attribute Name | Type
--- | ---
    LatestOcsAnswer
| org.jainslee.resources.diameter.ro.types.vcb0.CreditControlAnswer
    LegForCdrs
| String
    CallType
| com.opencloud.sentinel.common.CallType
    LowBalanceReauthTimerId
| javax.slee.facilities.TimerID

### Session state output variables

Attribute Name | Type | Description
--- | --- | ---
    EarlyMediaAnnouncementInfoQueue
| List | A List of early dialog announcements to play, if any
    MidCallAnnouncementInfoQueue
| List | A list of the mid call announcements to play, if any
    EndSessionAfterAnnouncement
| int | The Sip response error code for the SipPlayAnnouncement feature to use on endSession.
    EndSessionWithAnnouncement
| boolean | Set to true if session should end after announcement is played.
    MidCallAnnouncementPlayedParty
| String | Leg name indicating which party the announcement will be played to
    MidCallEndSessionWithAnnouncement
| boolean | Set to true if session should end after announcement is played.
    UserEndSessionCause
| int | The Sip response error code to use on endSession, if applicable.
    LowBalanceAnnouncementPlayed
| boolean | Set to true when a low balance announcement has been scheduled. Set to false when a CCA is received without a `Low-Balance-Indicator` AVP.
    OcsAnnouncementPlayed
| boolean | Set to true when `OC-Play-Announcement-Id` announcements have been scheduled. Set to false when a new CCA is received.
    AnnouncementTimersMapping
| Map | A map of TimerID to the SipAnnouncementInformation to be scheduled on the timer firing.
    AnnouncementTimersPostponed
| Boolean | Set to true if the initial CCA requested an announcement to be played on a timer.

### Configuration

`SetOcsAnnouncementID` uses two JSLEE configuration profile tables: `LowBalanceAnnouncementConfigProfileTable` and `SetOutOfCreditAnnouncementIDConfigProfileTable`.

Attribute Name | Profile Table | Type | Description
--- | --- | --- | ---
    EarlyDialogLowBalanceAnnouncementID
| LowBalanceAnnouncementConfigProfileTable | int | The ID of the early dialog announcement to play, if any
    MidSessionLowBalanceAnnouncementID
| LowBalanceAnnouncementConfigProfileTable | int | The ID of the mid call announcement to play, if any
    ChargingReauthDelayMillis
| LowBalanceAnnouncementConfigProfileTable | long | When a terminating call is ACKed and the latest CCA indicates a low balance, a delayed credit check will be performed to postpone playing an announcement. The reauth will be delayed by the amount specified here (0 triggers an immediate reauth.) This allows time for the ACK to propagate through the network to ensure the played party is fully connected before triggering the announcement after receiving another CCA-U with low balance indicator.
    OutOfCreditAnnouncementID
| SetOutOfCreditAnnouncementIDConfigProfileTable | int | The ID of the early dialog announcement to play, if any
    MidSessionOutOfCreditAnnouncementID
| SetOutOfCreditAnnouncementIDConfigProfileTable | int | The ID of the mid call announcement to play, if any

### Statistics

`SetOcsAnnouncementID` statistics are tracked by the `SetOcsAnnouncementID` feature and can be found under the following parameter set:
SLEE-Usage ▶ sentinel.volte.sip service ID ▶ sentinel.volte.sip SBB ID ▶ SetOcsAnnouncementID.

Name | Type | Description
--- | --- | ---
    Started
| Counter | Incremented each time the feature runs.
    FailedToStart
| Counter | Incremented when Sentinel VoLTE encounters an error while attempting to start the feature.
    IssuedWarning
| Counter | Incremented when a non-fatal problem is encountered and the feature issues a warning.
    FailedDuringExecution
| Counter | Incremented when a fatal problem is encountered and the feature cannot execute correctly.
    TimedOut
| Counter | Incremented when the feature takes too long to complete and Sentinel VoLTE aborts execution.
    InvalidExecutionPoint
| Counter | Incremented whenever the feature is invoked in an invalid execution point. Indicates misconfigured feature scripts.
    IgnoringRepeatLowBalance
| Counter | The feature will not trigger a second announcement for ongoing low balance indicators.
    ClearLowBalancePlayed
| Counter | If a CCA is received with no low balance indicator, any subsequent low balance will trigger another announcement.
    StartReauthTimer
| Counter | Incremented when a terminating call is ACKed but the latest CCA indicates an announcement is requested.
    LowBalanceReauthTimerEventReceived
| Counter | Incremented whenever a reauthorization timer event is received.
    DoCreditReauth
| Counter | Incremented whenever the feature issues a credit reauth.
    ScheduledOcPlayAnnouncementId
| Counter | Incremented whenever an OC-Play-Announcement-Id announcement is enqueued.
    EarlyDialogLowBalanceAnnouncementIDSet
| Counter | Incremented whenever a configured early media Low Balance Announcement ID is enqueued.
    MidSessionLowBalanceAnnouncementIDSet
| Counter | Incremented whenever a configured mid call Low Balance Announcement ID is enqueued.
    EarlyDialogOutOfCreditAnnouncementIDSet
| Counter | Incremented whenever a configured early media Out of Credit Announcement ID is enqueued.
    MidSessionOutOfCreditAnnouncementIDSet
| Counter | Incremented whenever a configured mid call Out of Credit Announcement ID is enqueued.
    EndSessionCauseSet
| Counter | Incremented whenever a session is terminated due to running out of credit.
    NoOutOfCreditAnnouncementID
| Counter | Incremented whenever an early media Out of Credit Announcement cannot be played as there is no configured announcement ID.
    NoMidSessionOutOfCreditAnnouncementID
| Counter | Incremented whenever a mid call Out of Credit Announcement cannot be played as there is no configured announcement ID.
    UnableToDetermineEndSessionCause
| Counter | Incremented whenever the end of session cause code could not be determined.
    MissingLegForCdrs
| Counter | Incremented whenever the leg to play announcements too could not be determined.
    ScheduledAnnouncementInformation
| Counter | Incremented whenever an Announcement-Information AVP announcement is scheduled.

### Provisioning interfaces

The feature is provisioned using the Sentinel REST API or web interface.

## StripPreconditions

This feature optionally strips preconditions information from initial INVITEs .

### Feature cheat sheet

B2BUA Instance | SAS Support | Originating / Terminating | Point in Session Plan | Network Operator Data | Subscriber Data | Stateful or Stateless | POJO Feature or SBB Feature
--- | --- | --- | --- | --- | --- | --- | ---
Any and All | No | Terminating | `MMTel_Post_SipAccess_SubscriberCheck`, `MMTel_Post_SipAccess_PartyResponse`, `SCC_Post_SipAccess_SubscriberCheck`, `SCC_Post_SipAccess_PartyResponse` | Yes | No | Stateless | POJO

### Behaviour

When SIP forking occurs, this may cause issues with upstream devices that cannot properly handle preconditions negotiation on multiple early dialogs. If this is a problem, then this can be worked around by stripping preconditions from the initial INVITE, if requested by another feature that is performing SIP forking. The StripPreconditions feature detects whether any other features have requested this behaviour, and removes preconditions from the outbound initial INVITE.

The StripPreconditions feature works as follows.

Features that execute prior to the StripPreconditions feature add legs to a session state variable variable called `StripPreconditionsLegNames`. Currently only MMTelParallelFA and SCCTADSParallelRouting features add legs to the collection, although any custom feature is permitted to add legs. When the StripPreconditions feature runs, it checks the `StripPreconditionsLegNames` session state variable and performs the following.

- check if feature’s `EnabledFlag` is `true`. If not selected the feature ends

- strip precondition attributes a=curr, a=des, and a=conf from the SDP of the INVITE. If there are no attributes to strip the feature ends.

- strip the "preconditions" option tag in the Supported header from the INVITE

The feature supports the removal of preconditions from initial INVITEs and retarget INVITEs.

### Prerequisite features

The feature must run before SDPMonitor mode "post" and DiameterPerLegInfo features.

### Session state input variables

Variable name | Variable type | Description
--- | --- | ---
    StripPreconditionsLegNames
| Set<String> | Collection of leg names that will have preconditions information stripped from initial INVITEs.

### Session state output variables

None.

### Network operator data

This feature reads the `EnabledFlag` in the feature configuration profile table `StripPreconditions` to determine if the feature will strip preconditions.

Parameter | Type | Description | Default
--- | --- | --- | ---
    EnabledFlag
| boolean | true or false | false

### Statistics

StripPreconditions statistics are tracked by the sentinel.volte.sip SBB and can be found under the following parameter set in REM:
SLEE-Usage → sentinel.volte.sip service → sentinel.volte.sip SBB → feature → StripPreconditions
or with rhino-stats:
"SLEE-Usage.Services.ServiceID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].SbbID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].feature.StripPreconditions"

Name | Type | Description
--- | --- | ---
    Started
| Counter | Incremented each time the feature runs
    FailedToStart
| Counter | Incremented when a fatal error occurs before feature execution
    IssuedWarning
| Counter | Incremented when a non-fatal error occurs during feature execution
    FailedDuringExecution
| Counter | Incremented when a fatal error occurs during feature execution
    TimedOut
| Counter | Incremented when feature execution does not complete within a reasonable time frame
    RemovePreconditionsFields
| Counter | Incremented when the feature strips preconditions attributes from INVITE SDP
    InviteNotFoundInQueue
| Counter | Incremented when the feature is unable to find the INVITE from an internal system queue
    MessageQueueEmpty
| Counter | Incremented when the feature is unable to find any SIP messages from an internal system queue
    InvalidSDP
| Counter | Incremented when the feature fails to parse the SDP

#### Values examined

Value Name | Source | Notes
--- | --- | ---
StripPreconditionsLegNames | Session State | Collection of leg names that will have preconditions stripped. The collection can be updated by any feature that has access to the session state variable `StripPreconditionsLegNames`. Currently the MMTelParallelFA and SCCTADSParallelRouting features add legs to the collection.
SDP | Outgoing INVITE request | Check if precondition attributes a=curr, a=des, and a=conf are present in the SDP of the INVITE. If yes strip, if no then don’t execute any further.
Supported Header | Outgoing INVITE request | Remove 'preconditions' option tag from the Supported header unless there are no preconditions attributes present in the SDP.

## SubscriberDataLookupFromHLR

SubscriberDataLookupFromHLR is responsible for reading subscriber data from the HLR and writing it into Sentinel session state variable fields.

The data it reads from the HLR is accessed through the `AnyTimeSubscriberInterrogation` MAP operation. The Application Context used is `anyTimeInfoHandlingContext_v3_ac`

### Feature cheat sheet

B2BUA Instance | SAS Support | Originating / Terminating | Point(s) in Session Plan | Network Operator Data | Subscriber Data | Stateful or Stateless | POJO Feature or SBB Feature | Other notes
--- | --- | --- | --- | --- | --- | --- | --- | ---
Both or either of MMTEL or SCC. | No | Originating, Forwarding, and Terminating | `SipAccess_SubscriberPreCreditCheck` | Yes | Yes | Stateless | POJO |

### Prerequisite features

- SubscriberDetermination

- IMSIDLookup or IMSIDLookupFromCassandraSIP

### Source Code

This feature’s source code is available in the Sentinel VoLTE SDK in the `volte-hlr-subscriber-data-lookup` module pack. It can be viewed by using the `create-module` command in the SDK with that module pack, for example:

`> create-module new-hlr-module opencloud#volte-hlr-subscriber-data-lookup#volte/3.1.0;3.1.0.0`

This command will prompt you for information needed to create the new module, once completed the original source for the feature can be found in the new module.

The module-pack consists of a single module, `volte-hlr-subscriber-data-lookup`, containing the feature’s code. It does rely on the `volte-map-event-handler` which contains the shared event handler for MAP features and also publishes a module pack, however the event handler will not require modification unless a new feature name is introduced.

### Session input variables

Attribute Name | Type
--- | ---
    Subscriber
| String
    RegistrationRecords
| List<RegistrationRecord>

### Configuration

The feature uses the `HLRConfigProfileTable` to access its configuration. For more information refer to HLR MAP Configuration.

### Statistics

`SubscriberDataLookupFromHLR` statistics are tracked by the `SubscriberDataLookupFromHLR` feature and can be found under the following parameter set: SLEE-Usage → sentinel.volte.sip service ID → SubscriberDataLookupFromHLR.

Name | Type | Description
--- | --- | ---
    Started
| Counter | Incremented each time the feature runs
    FailedToStart
| Counter | Incremented when Sentinel VoLTE encounters an error while attempting to start the feature
    IssuedWarning
| Counter | Incremented when a non-fatal problem is encountered and the feature issues a warning
    FailedDuringExecution
| Counter | Incremented when a fatal problem is encountered and the feature cannot execute correctly
    TimedOut
| Counter | Incremented when the feature takes too long to complete and Sentinel VoLTE aborts execution
    RequestSent
| Counter | Incremented when the feature receives subscriber data from the HLR
    RequestSuccessful
| Counter | Incremented after the feature successfully processes the data it received, and loads it into session state fields
    RequestFailed
| Counter | Incremented when absent configuration data prevents the feature from running
    ResponseLatency
| Sampled | Records elapsed time between sending the request to the HLR and getting a response (in milliseconds).

### Behaviour

This feature uses the CGIN MAP RA to access the HLR.

Each time the feature is invoked, it checks the call type and determines the subscriber number that it should use to query the HLR.

The feature attempts to extract "phone number digits" from the Default Public ID, and if it cannot, from any other registered IMS Public User Identity. The first IMS Public User Identity that has "phone number digits" has its digits extracted to form the MSISDN for the `AnytimeSubscriptionInterrogation` query. If the feature cannot form an MSISDN it raises a Feature Error and finishes execution.

The feature requests the subscriber data by sending a `AnyTimeSubscriptionInterrogation` request for all Supplementary Services. If the triggering attempt is a terminating trigger, the feature sends two queries in order to gather the Call Forwarding information.

In order to form the ATSI request the feature:

1. sets the GSM SCF address to the `SentinelSCCPAddress` configuration value

2. sets the destination SCCP address to the `HlrSCCPAddress` configuration value

3. sets the indicator fields to request CLIP, CLIR, CW, ODB and may request Forwarding information for unconditional forwarding

If the session is a terminating session, a second request is sent where Forwarding information is requested for conditional forwarding.

Once the query(s) are successful, it sets the session state fields for the supplementary services according the mapping below.

### Supplementary Service Session State Mappings

GSM Service | MMTel Service
--- | ---
CLIP | OIP
COLP | TIP
CLIR | OIR
COLR | TIR
ODB | ICB
ODB | OCB
Call Forwarding | CDIV
Call Waiting | CW
Call Hold | HOLD

### GSM ASN.1 Schema to Session-State Fields

The mapping below describes how the `AnyTimeSubscriptionInterrogation` result is mapped into the MMTel Subscriber Data Representation.

#### ss-Status ASN.1 field

The field `ss-Status` is used by almost all supplementary services and defines the service state. Each service defines a set of possible values based on ss-Status, so called `State Vectors`. A state vector is formed of 4 variables: Provisioning State, Registration State, Activation State and HLR Induction State. This feature only reads the `Activation State`, i.e. "A and Q" bits.

For more information see 3GPP TS 23.011 - Technical realization of Supplementary Services.

#### CLIP

ASN.1 Field (From) | Session-State Field (To) | Mapping Rules
--- | --- | ---
ClipData.ss-Status | MMTelOIPServiceData.active | `true` if ss-Status=`Active and Operative` else `false`.
OverrideCategory | MTelOIPServiceData.override | No default value. It is an obligatory field from HLR response.

#### CLIR

ASN.1 Field (From) | Session-State Field (To) | Mapping Rules
--- | --- | ---
ClirData.ss-Status | MMTelOIRServiceData.active | `true` if ss-Status=`Active and Operative` else `false`.
n/a | MMTelOIRServiceData.mode | the same default for IMS OIR
ClirData.CliRestrictionOption | MMTelOIRServiceData.defaultBehaviourType | No default value. It is an obligatory field from HLR response.

#### COLP

ASN.1 Field (From) | Session-State Field (To) | Mapping Rules
--- | --- | ---
n/a | MMTelTIPServiceData.active | `true`.
n/a | MMTelTIPServiceData.override | the same default for IMS TIP

#### COLR

ASN.1 Field (From) | Session-State Field (To) | Mapping Rules
--- | --- | ---
n/a | MMTelTIRServiceData.active | `true`.
n/a | MMTelTIRServiceData.mode | the same default for IMS TIR

#### ODB - Incoming calls

ASN.1 Field (From) | Session-State Field (To) | Mapping Rules
--- | --- | ---
n/a | MMTelICBServiceData.active | `true`.
ODB-Info.ODB-Data.ODB-GeneralData | MMTelICBServiceData.ruleset | see Ruleset Conditions for barring incoming calls

Ruleset Conditions for barring incoming calls

ODB Data Value | Condition
--- | ---
allIC-CallsBarred | Unconditional
n/a | Anonymous
roamingOutsidePLMNIC-CallsBarred | Roaming
roamingOutsidePLMNICountryIC-CallsBarred | Roaming and International ExHC

#### ODB - Outgoing calls

ASN.1 Field (From) | Session-State Field (To) | Mapping Rules
--- | --- | ---
n/a | MMTelOCBServiceData.active | `true`
ODB-Info.ODB-Data.ODB-GeneralData | MMTelOCBServiceData.ruleset | see Ruleset Conditions for barring outgoing calls

Ruleset Conditions for barring outgoing calls

ODB Data Value | Condition
--- | ---
allOG-CallsBarred | Unconditional
internationalOGCallsBarred | International
internationalOGCallsNotToHPLMN-CountryBarred | International-exHC
roamingOutsidePLMNOG-CallsBarred | Roaming

#### Call Forwarding

ASN.1 Field (From) | Session-State Field (To) | Mapping Rules
--- | --- | ---
callForwardingData.forwardingFeatureList[x].ss-Status | MMTelCDIVServiceData.active | `true` if ss-Status=`Active and Operative` else `false`.
callForwardingData.forwardingFeatureList.forwardingOptions | MMTelCDIVServiceData.ruleset | No default value defined.
callForwardingData.forwardingFeatureList.noReplyConditionTime | MMTelCDIVServiceData.noreplytimeout | No default value defined.

Ruleset Conditions for Call Forwarding

ASN.1 value in bits 4 and 3 of Octet 1 of Ext-ForwardOptions | Condition | 00
--- | --- | ---
Not Reachable | 01 | Busy
10 | No reply | 11

#### Call Waiting

ASN.1 Field (From) | Session-State Field (To) | Mapping Rules
--- | --- | ---
CallWaitingData.ss-Status | MMTelCWServiceData | `true` if ss-Status=`Active and Operative` else `false`.

#### Call Hold

ASN.1 Field (From) | Session-State Field (To) | Mapping Rules
--- | --- | ---
CallHoldData.ss-Status | MMTelHOLDServiceData.active | `true` if ss-Status=`Active and Operative` else `false`.

## SubscriberDataLookupFromHSS

SubscriberDataLookupFromHSS is responsible for reading data from the HSS and writing it into Sentinel session state fields.

The data it reads from the HSS must be accessed from `TransparentUserData` in the HSS.

### Feature cheat sheet

B2BUA Instance | SAS Support | Originating / Terminating | Point(s) in Session Plan | Network Operator Data | Subscriber Data | Stateful or Stateless | POJO Feature or SBB Feature | Other notes
--- | --- | --- | --- | --- | --- | --- | --- | ---
Both or either of MMTEL or SCC | Yes | Originating, Forwarding, and Terminating | `SipAccess_SubscriberPreCreditCheck` | Yes | Yes | Stateless | SBB |

### Prerequisite features

- SubscriberDetermination

- IMSIDLookup, or IMSIDLookupFromCassandraSIP

### Source Code

This feature’s source code is available in the Sentinel VoLTE SDK in the `volte-hss-subscriber-data-lookup-2` module pack. It can be viewed by using the `create-module` command in the SDK with that module pack, for example:

`> create-module new-hss2-module opencloud#volte-hss-subscriber-data-lookup-2#volte/3.1.0;3.1.0.0`

This command will prompt you for information needed to create the new modules, once completed the original source for the feature can be found in the new modules.

The module-pack includes the following modules:

Module Name | Description
--- | ---
volte-hss-subscriber-data-lookup-2 | Contains the feature’s code.
volte-hss-subscriber-data-lookup-2-service-indication-profile | Contains the profile specification for the feature configuration profile table.

### Session input variables

Attribute Name | Type
--- | ---
    Subscriber
| String
    RegistrationRecords
| List<RegistrationRecord>

### Configuration

This feature has an out-of-the-box configuration ensuring the MMTel features work. The configuration may be extended to

- support additional MMTel features that use the MMTel services XML schema

- support additional features that use a different XML schema

This configuration extensibility is supported through the profile table named `${PlatformOperatorName}_SubscriberDataLookupFromHss2ServiceIndicationProfileTable`. If the platform operator name is `RocketInc` then the profile table name is `RocketInc_SubscriberDataLookupFromHss2ServiceIndicationProfileTable`.

The profile table contains one profile for each Service Indication that shall be queried in the HSS. Each profile defines:

1. the Service-Indication

2. the fully qualified class name of the Transparent Data Codec class - used to parse the returned XML into a Java Object

3. a list of adaptor class names (fully qualified class names)

4. an option to enable or disable the query

5. a default value for operator authorized fields

This table, by default, has entries for `MMTEL-Services`, `IMS-ODB-Information`, and `Metaswitch-TAS-Services`, configured by the installer. The `MMTEL-Services` query is enabled by default, while `IMS-ODB-Information` and `Metaswitch-TAS-Services` are disabled. The query can be enabled or disabled by setting the value of `DisableQuery` field to `true` or `false`. A value of `true` disables the query.

### Statistics

`SubscriberDataLookupFromHss` statistics are tracked by the `SubscriberDataLookupFromHss2` SBB and can be found under the following parameter set: SLEE-Usage → volte.sentinel.sip service ID → SubscriberDataLookupFromHss2 SBB ID.

Name | Type | Description
--- | --- | ---
    Invoked
| Counter | Incremented each time the feature runs.
    Failed
| Counter | Incremented if a fatal error occurs while the feature is running.
    SubscriberDataRetrieved
| Counter | Incremented when the feature receives subscriber data from the Sh Cache Microservice.
    SessionStatePopulated
| Counter | Incremented after the feature successfully processes the data it received, and loads it into session state fields.
    AdaptorClassError
| Counter | Incremented when Adaptor class is not of type SimservsSessionAdaptor or the feature fails to retrieve adaptor class.
    CodecClassError
| Counter | Incremented when Codec class is not of type ServiceDataCodec or the feature fails to retrieve codec class.
    Misconfigured
| Counter | Incremented when absent configuration data prevents the feature from running.
    SessionStateNotFound
| Counter | Incremented when the session state field the feature requires for operation is missing.
    ResponseLatency
| Sampled | Records elapsed time between sending the request to the HSS and getting a response (in milliseconds).

### Behaviour

This feature uses the Sh Cache Microservice RA, connected to the Sh Cache Microservice, to access the HSS.

Each time the feature is invoked, it determines the IMS public identity that it should use to query the HSS.

If the session input variable `DefaultPublicID` of the first `RegistrationRecord` in the `RegistrationRecords` list is present, this field is used as the IMS public identity in the HSS query. Otherwise, the the session input variable `subscriber` is used as the IMS public identity in the HSS query.

The feature requests the Sh Cache Microservice RA to fetch the transparent user data for the IMS Public Identifier and Service Indication. This data is stored in the corresponding session-state fields.

The feature can be configured to fetch multiple Service Indications, i.e. to retrieve different documents. The out-of-the-box configuration looks for the MMTel Services document.

For each profile in the feature’s configuration

1. the feature requests the Sh Cache Microservice RA to fetch the transparent user data document

2. Once a result is available, each adaptor in the list of adaptors is invoked in order to populate session state

### MMTel-Services Schema to Session-State Fields

The MMTel-Services schema is configured into this feature in all out-of-the-box installations. This section describes the source of a variable (from within the returned document), and the destination session state field name and attribute for the out-of-the-box configuration.

#### OIP

XPath in document (From) | Session-State Field (To) | Default values
--- | --- | ---
MMTELServices/complete-originating-identity-presentation/originating-identity-presentation/active | MMTelOIPServiceData.active | If not present in the XML document, the field is set to `true` according to 3GPP TS 24.623.
MMTELServices/complete-originating-identity-presentation/operator-originating-identity-presentation/restriction-override | MMTelOIPServiceData.override | If not present in the XML document, the field is set to `override-not-active` according to 3GPP TS 24.607. This is the default from the XML schema.
MMTELServices/complete-originating-identity-presentation/operator-originating-identity-presentation/@authorized | MMTelOIPServiceData.operatorAuthorized | Value read from Configuration

For more information on MMTEL OIP see MMTelOIP.

#### OIR

XPath in document (From) | Session-State Field (To) | Default values
--- | --- | ---
MMTELServices/complete-originating-identity-restriction/originating-identity-presentation-restriction/active | MMTelOIRServiceData.active | If not present in the XML document, the field is set to `true` according to 3GPP TS 24.623.
MMTELServices/complete-originating-identity-restriction/operator-originating-identity-presentation-restriction/mode | MMTelOIRServiceData.mode | If not specified the field is set to `temporary` according to 3GPP TS 24.607.
MMTELServices/complete-originating-identity-restriction/originating-identity-presentation-restriction/default-behaviour | MMTelOIRServiceData.defaultBehaviourType | If not specified the field is set to `presentation-restricted` according to 3GPP TS 24.607. This is the default from the XML schema.
MMTELServices/complete-originating-identity-restriction/operator-originating-identity-presentation-restriction/@authorized | MMTelOIRServiceData.operatorAuthorized | Value read from Configuration

For more information on MMTEL OIR see MMTelOIR.

#### TIP

XPath in document (From) | Session-State Field (To) | Default values
--- | --- | ---
MMTELServices/complete-terminating-identity-presentation/terminating-identity-presentation/active | MMTelTIPServiceData.active | If not present in the XML document, the field is set to `true` according to 3GPP TS 24.623.
MMTELServices/complete-terminating-identity-presentation/operator-terminating-identity-presentation/restriction-override | MMTelTIPServiceData.override | If not specified the field is set to `override-not-active` according to 3GPP TS 24.608. This is the default from the XML schema.
MMTELServices/complete-terminating-identity-presentation/operator-terminating-identity-presentation/@authorized | MMTelTIPServiceData.operatorAuthorized | Value read from Configuration

For more information on MMTEL TIP see MMTelTIP.

#### TIR

XPath in document (From) | Session-State Field (To) | Default values
--- | --- | ---
MMTELServices/complete-terminating-identity-restriction/terminating-identity-presentation-restriction/active | MMTelTIRServiceData.active | If not present in the XML document, the field is set to `true` according to 3GPP TS 24.623.
MMTELServices/complete-terminating-identity-restriction/operator-terminating-identity-presentation-restriction/mode | MMTelTIRServiceData.mode | If not specified the field is set to `temporary` according to 3GPP TS 24.608. This is the default from the XML schema.
MMTELServices/complete-terminating-identity-restriction/operator-terminating-identity-presentation-restriction/@authorized | MMTelTIRServiceData.operatorAuthorized | Value read from Configuration

For more information on MMTEL TIR see MMTelTIR.

#### ICB

XPath in document (From) | Session-State Field (To) | Default values
--- | --- | ---
MMTELServices/complete-communication-barring/incoming-communication-barring/active | MMTelICBServiceData.active | If not present in the XML document, the field is set to `true` according to 3GPP TS 24.623.
MMTELServices/complete-communication-barring/incoming-communication-barring/ruleset | MMTelICBServiceData.ruleset | No default value specified.
MMTELServices/complete-communication-barring/operator-incoming-communication-barring/@authorized | MMTelICBServiceData.operatorAuthorized | Value read from Configuration

For more information on MMTEL ICB see MMTelICB.

#### OCB

XPath in document (From) | Session-State Field (To) | Default values
--- | --- | ---
MMTELServices/complete-communication-barring/outgoing-communication-barring/active | MMTelOCBServiceData.active | If not present in the XML document, the field is set to `true` according to 3GPP TS 24.623.
MMTELServices/complete-communication-barring/outgoing-communication-barring/ruleset | MMTelOCBServiceData.ruleset | No default value specified.
MMTELServices/complete-communication-barring/operator-outgoing-communication-barring/@authorized | MMTelOCBServiceData.operatorAuthorized | Value read from Configuration

For more information on MMTEL OCB see MMTelOCB.

#### CDIV

XPath in document (From) | Session-State Field (To) | Default values
--- | --- | ---
MMTELServices/complete-communication-diversion/communication-diversion/active | MMTelCDIVServiceData.active | If not present in the XML document, the field is set to `true` according to 3GPP TS 24.623.
MMTELServices/complete-communication-diversion/communication-diversion/NoReplyTimer | MMTelCDIVServiceData.noReplyTimeOut | The default value is specified in Network operator data for MMTEL CDIV `CDIVNoReplyTimeout`.
MMTELServices/complete-communication-diversion/communication-diversion/ruleset | MMTelCDIVServiceData.rules | No default value specified.
MMTELServices/complete-communication-diversion/operator-communication-diversion/@authorized | MMTelCDIVServiceData.operatorAuthorized | Value read from Configuration

Ruleset Conditions for CDIV. Ruleset is a collection of rules.

XPath in document (From) | Session-State Field (To) | Default values
--- | --- | ---
MMTELServices/common-policy/conditions | MMTelCDIVServiceData.rules[].conditions | No default value specified.
MMTELServices/complete-communication-diversion/forward-to | MMTelCDIVServiceData.rules[].forwardToAction | No default value specified.

For more information on MMTEL CDIV see MMTelCDIV.

#### CONF

XPath in document (From) | Session-State Field (To) | Default values
--- | --- | ---
MMTELServices/complete-conference/operator-conference/@authorized | MMTelCONFServiceData.operatorAuthorized | Value read from Configuration

For more information on MMTEL CONF see MMTel Conference.

#### CW

XPath in document (From) | Session-State Field (To) | Default values
--- | --- | ---
MMTELServices/complete-communication-waiting/communication-waiting/active | MMTelCWServiceData.active | If not present in the XML document, the field is set to `true` according to 3GPP TS 24.623.
MMTELServices/complete-communication-waiting/operator-communication-waiting/@authorized | MMTelCWServiceData.operatorAuthorized | Value read from Configuration

For more information on MMTEL CW see MMTelCW.

#### HOLD

XPath in document (From) | Session-State Field (To) | Default values
--- | --- | ---
MMTELServices/complete-communication-hold/operator-communication-hold/@authorized | MMTelHOLDServiceData.operatorAuthorized | Value read from Configuration

For more information on MMTEL Hold see MMTelHold.

#### Flexible-Alerting

XPath in document (From) | Session-State Field (To) | Default values
--- | --- | ---
MMTELServices/complete-flexible-alerting/operator-flexible-alerting-group/group-type | MMTelFAGroup | `single-user` or `multiple-users`.
MMTELServices/complete-flexible-alerting/operator-flexible-alerting-group/membership | MMTelFAMembership | `demand` or `permanent`.
MMTELServices/complete-flexible-alerting/operator-flexible-alerting-group/members | MMTelFAServiceData.members[] | No default value.
MMTELServices/complete-flexible-alerting/operator-flexible-alerting-group/identity | MMTelFAServiceData.identity | The `Pilot Number`. No default value.
MMTELServices/complete-flexible-alerting/operator-flexible-alerting-group/@authorized | MMTelFAServiceData.authorized | Value read from Configuration

For more information on MMTEL FA see Flexible Alerting.

#### ECT

XPath in document (From) | Session-State Field (To) | Default values
--- | --- | ---
MMTelServices/complete-explicit-communication-transfer/operator-explicit-communication-transfer/@authorized | MMTelECTServiceData.authorized | Value read from Configuration

For more information on MMTEL ECT see MMTelECT

### IMS-ODB-Information Schema to Session-State Fields

The IMS-ODB-Information schema is configured (but disabled) into this feature in all out-of-the-box installations. This section describes the source of a variable (from within the returned document), and the destination session state field name and attribute for the out-of-the-box configuration.

#### Operator Determined Barring

For more information see Operator Determined Barring.

### Metaswitch-TAS-Services Schema to Session-State Fields

The Metaswitch-TAS-Services schema is configured (but disabled) into this feature in all out-of-the-box installations. This section describes the source of a variable (from within the returned document), and the destination session state field name and attribute for the out-of-the-box configuration.

#### Basic Services

XPath in document (From) | Session-State Field (To) | Default values
--- | --- | ---
Metaswitch-Services/basic-settings/additional-attributes | MetaswitchBasicSettings.additionalAttributes | If not present in the XML document, the field is set to an empty map.

#### Location Based Dialling

XPath in document (From) | Session-State Field (To) | Default values
--- | --- | ---
Metaswitch-Services/location-based-dialling/group-id | MetaswitchLocationBasedDialling.groupId | If not present in the XML document, the field is set to `null`
Metaswitch-Services/basic-settings/additional-attributes | MetaswitchLocationBasedDialling.additionalAttributes | If not present in the XML document, the field is set to an empty map.

For more information on location based dialling see Location Based Dialling

#### Forward To Voicemail

XPath in document (From) | Session-State Field (To) | Default values | Notes
--- | --- | --- | ---
metaswitch-services/complete-forward-to-voicemail/forward-to-voicemail/voicemail-server | MetaswitchForwardToVoicemail.voicemailServer | If not present in the XML document, the field is set to `null`. |
metaswitch-services/complete-forward-to-voicemail/forward-to-voicemail/additional-attributes AND Metaswitch-Services/complete-forward-to-voicemail/operator-forward-to-voicemail/additional-attributes | MetaswitchForwardToVoicemail.additionalAttributes | If not present in the XML document, the field is set to an empty map of String → String. | Where there is an attribute with the same name in the operator and user sections of the document, the value in the user section takes precedence.
metaswitch-services/complete-forward-to-voicemail/forward-to-voicemail/active | MetaswitchForwardToVoicemail.active | If not present in the XML document, the field is set to `null`. |

For more information on forwarding to voicemail see:

- Default Forward to Voicemail

- Voicemail Dialling

#### Companion Device

XPath in document (From) | Session-State Field (To) | Default values | Notes
--- | --- | --- | ---
metaswitch-services/complete-companion-device/companion-device/@active | CompanionDeviceData.active | `true` |
metaswitch-services/complete-companion-device/operator-companion-device/@authorized | CompanionDeviceData.operatorAuthorized | Value read from Configuration |
metaswitch-services/complete-companion-device/operator-companion-device/radio-access | CompanionDeviceData.radioAccess | If not present in the XML document, the field is set to `null`. | Value is a `<network>` element as shown in the `RadioAccess` type. See example below.
metaswitch-services/complete-companion-device/operator-companion-device/msisdn | CompanionDeviceData.msisdn | If not present in the XML document, the field is set to `null`. |
metaswitch-services/complete-companion-device/operator-companion-device/additional-attributes AND metaswitch-services/complete-companion-device/companion-device/additional-attributes | CompanionDeviceData.additionalAttributes | If not present in the XML document, the field is set to an empty map of String → String. | Where there is an attribute with the same name in the operator and user sections of the document, the value in the user section takes precedence.

##### Example Radio Access field value

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <radio-access xmlns="http://metaswitch.com/XMLSchema/tas">
      <network>PS</network>
    </radio-access>

For more information on companion device support, see Companion Devices.

## SubscriberDataLookupFromHSSOld

SubscriberDataLookupFromHSSOld is responsible for reading data from the HSS and writing it into Sentinel session state variables fields.

Note: this feature is deprecated in favour of the new SubscriberDataLookupFromHSS feature. This deprecated feature is installed by default, but is not referenced in any feature execution script. The feature remains in case external developers used it as an extensibility mechanism. All out-of-the-box product features have been migrated away from this feature. In previous releases of the Sentinel VoLTE product, this feature was named SubscriberDataLookupFromHss, but it has now been renamed to SubscriberDataLookupFromHssOld. I.e. there is a new feature with the name SubscriberDataLookupFromHss.

The data it reads from the HSS must be accessed from `TransparentUserData` in the HSS.

The session state fields that are written to, and the locations in the XML documents retrieved from the HSS, are configurable.

### Feature cheat sheet

B2BUA Instance | SAS Support | Originating / Terminating | Point(s) in Session Plan | Network Operator Data | Subscriber Data | Stateful or Stateless | POJO Feature or SBB Feature | Other notes
--- | --- | --- | --- | --- | --- | --- | --- | ---
Both or either of MMTEL or SCC | No | Originating, Forwarding, and Terminating | `SipAccess_SubscriberPreCreditCheck` | Yes | Yes | Stateless | SBB |

### Prerequisite features

- SubscriberDetermination

- IMSIDLookup

### Source Code

This feature’s source code is available in the Sentinel VoLTE SDK in the `volte-hss-subscriber-data-lookup` module pack. It can be viewed by using the `create-module` command in the SDK with that module pack, for example:

`> create-module new-hss-module opencloud#volte-hss-subscriber-data-lookup#volte/3.1.0;3.1.0.0`

This command will prompt you for information needed to create the new modules, once completed the original source for the feature can be found in the new modules.

The module-pack includes the following modules:

Module Name | Description
--- | ---
volte-hss-subscriber-data-lookup | Contains the feature’s code.
volte-hss-subscriber-data-lookup-service-indication-profile | Contains the profile specification for configuring the service indications the feature should request.
volte-hss-subscriber-data-lookup-field-mapping-profile | Contains the profile specification for configuring the session state fields the feature should populate.

### Network operator data

This data is stored in two JSLEE configuration profile tables. Both are scoped by Sentinel selection key. (However, unlike various other features, each operator has a profile table with multiple profiles within the table.)

- The first is for mapping transparent user data service indications to Java codec classes.

- The second configures the mapping between sections of the decoded document and session state variables/fields.

#### Service indications and codecs

Different applications use transparent user data in the HSS. To distinguish the format of the data, individual applications get unique service indications.

To enable flexibility, this feature allows a new XML schema to be introduced, alongside Java classes to parse (turn the XML into Java objects) and generated XML (turn Java objects back into XML for storage in the HSS).

The Java classes are called “codecs”, as they encode and decode between XML and Java.

This is stored in the profile table named `$NetworkOperator_SubscriberDataLookupFromHssServiceIndicationProfileTable`.

For example, if the network operator is “TestOperator”, then the profile table name is `TestOperator_SubscriberDataLookupFromHssServiceIndicationProfileTable`.

Each profile in the table has the following attributes.

Attribute Name | Type | Comments
--- | --- | ---
    ServiceIndication
| String | This is the value of the Service Indication. For example, for MMTEL this is `MMTEL-Services`
    CodecFQCN
| String | This is the fully qualified class name of the codec class. For example, for Sentinel VoLTE MMTEL, this is `com.opencloud.mmtel.feature.hssdata.MmtelServiceDataCodec`

#### Field definition profile

For the XML document to be entered into session state (so that other features can read these variables), the XML document must be broken down into relevant variables.

This is fulfilled by use of a field definition profile. Each field definition profile defines one session state variable, and where it comes from in the XML document.

Attribute Name | Type | Comments
--- | --- | ---
    SessionStateFieldName
| String | The name of the session state field to write to.
    XPath
| String | The location in the XML document to read from.
    ServiceIndication
| String | The service indication in transparent user data in the HSS.
    RootElementName
| String | The name of the root element of the document; if non-empty it is chopped off the XPath.

This is stored in the profile table `$NetworkOperator_SubscriberDataLookupFromHssFieldDefinitionProfileTable`; for example, if the network operator is “TestOperator” then the profile table name is `TestOperator_SubscriberDataLookupFromHssFieldDefinitionProfileTable`.

##### Communication diversion active example

As an example, MMTEL supplementary service settings are read by using the “MMTEL-Services” service indication.

Within the returned document, the XPath for the CDIV feature being active is `/complete-communication-diversion/communication-diversion/@active`.

The session state variable name is determined by the feature in question. In this case, the MMTelCDIV feature looks for a session input variable called `CDIVActive`.

So we end up with the following configuration for this field:

Attribute Name | Value
--- | ---
    SessionStateFieldName
| CDIVActive
    XPath
| /complete-communication-diversion/communication-diversion/@active
    ServiceIndication
| MMTEL-Services
    RootElementName

An alternative (using `RootElementName`) is:

Attribute Name | Value
--- | ---
    SessionStateFieldName
| CDIVActive
    XPath
| MMTelServices/complete-communication-diversion/communication-diversion/@active
    ServiceIndication
| MMTEL-Services
    RootElementName
| MMTelServices

### Session input variables

Attribute Name | Type
--- | ---
    Subscriber
| String
    RegistrationRecords
| List<RegistrationRecord>

### Statistics

`SubscriberDataLookupFromHss` statistics are tracked by the `SubscriberDataLookupFromHss` SBB and can be found under the following parameter set: SLEE-Usage → sentinel.volte.sip service ID → SubscriberDataLookupFromHss SBB ID.

Name | Description
--- | ---
    Invoked
| Incremented each time the feature runs.
    Failed
| Incremented if a fatal error occurs while the feature is running.
    SubscriberDataRetrieved
| Incremented when the feature receives subscriber data from the HSS or Sh Cache Microservice.
    SessionStatePopulated
| Incremented after the feature successfully processes the data it received, and loads it into session state fields.
    Misconfigured
| Incremented when absent configuration data prevents the feature from running.
    SessionStateNotFound
| Incremented when the session state field the feature requires for operation is missing.

### Behaviour

This feature uses the Sh Cache Microservice RA, connected to the Sh Cache Microservice, to access the HSS.

Each time the feature is invoked, it checks the call type and determines the IMS public identity that it should use to query the HSS.

If the session input variable `DefaultPublicID` of the first `RegistrationRecord` in the `RegistrationRecords` list is present, this field is used as the IMS public identity in the HSS query. Otherwise, the the session input variable subscriber is used as the IMS public identity in the HSS query.

For each service indication profile, the feature requests the Sh Cache Microservice RA to return the transparent user data for the IMS public identifier and service indication.

Next, the document is queried once for each field definition profile. The results of each XPath query are written into the session state variable. If any error occurs, the session state variable is not modified.

Examples of errors include:

- Cannot decode the XML document.

- The session state variable name does not correspond to a session state variable (for example, it was mistyped).

- The Java type for the session state variable, and the type of the object returned by the XPath query are incompatible.

- The XPath query did not return any data.

### Recommended minimum configuration for MMTEL

In order to provide MMTEL, according to IR.92 it is recommended that:

- the service indication profile includes the pre-built MMTel codec

- all session input variables for the out-of-the-box MMTel features are included.

#### Minimum service indication profiles for MMTEL

ServiceIndication | CodecFQCN
--- | ---
    MMTEL-Services
| com.opencloud.mmtel.feature.hssdata.MmtelServiceDataCodec

#### Minimum field definition profiles for MMTEL

SessionStateFieldName | XPath | ServiceIndication | RootElementName
--- | --- | --- | ---
    CDIVActive
    /complete-communication-diversion/communication-diversion/@active
    MMTEL-Services
    CDIVRuleset
    /complete-communication-diversion/communication-diversion/ruleset
    MMTEL-Services
    CDIVSubscriberNoReplyTimeout
    /complete-communication-diversion/communication-diversion/NoReplyTimer
    MMTEL-Services
    CWActive
    /complete-communication-waiting/communication-waiting/@active
    MMTEL-Services
    ICBActive
    /complete-communication-barring/incoming-communication-barring/@active
    MMTEL-Services
    ICBRuleset
    /complete-communication-barring/incoming-communication-barring/ruleset
    MMTEL-Services
    OCBActive
    /complete-communication-barring/outgoing-communication-barring/@active
    MMTEL-Services
    OCBRuleset
    /complete-communication-barring/outgoing-communication-barring/ruleset
    MMTEL-Services
    OIPActive
    /complete-originating-identity-presentation/originating-identity-presentation/@active
    MMTEL-Services
    OIRActive
    /complete-originating-identity-restriction/originating-identity-presentation-restriction/@active
    MMTEL-Services
    OIRDefaultBehaviourType
    /complete-originating-identity-restriction/originating-identity-presentation-restriction/default-behaviour
    MMTEL-Services
    TIPActive
    /complete-terminating-identity-presentation/terminating-identity-presentation/@active
    MMTEL-Services
    TIRActive
    /complete-terminating-identity-restriction/terminating-identity-presentation-restriction/@active
    MMTEL-Services
    TIRDefaultBehaviourType
    /complete-terminating-identity-restriction/terminating-identity-presentation-restriction/default-behaviour
    MMTEL-Services

## SuppressSdpCdr

`SuppressSdpCdr` is a system feature which prevents SDP-change initiated CDRs from being written by the `VolteInterimCdr` feature for non-roaming Mobile Terminating calls.

### Statistics

SuppressSdrCdr statistics are tracked by the sentinel.volte.sip SBB and can be found under the following parameter set in REM:
SLEE-Usage → sentinel.volte.sip service → sentinel.volte.sip SBB → feature → SuppressSdpCdr
or with rhino-stats:
"SLEE-Usage.Services.ServiceID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].SbbID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].feature.SuppressSdpCdr"

Name | Type | Description
--- | --- | ---
    Started
| Counter | Incremented each time the feature runs.
    FailedToStart
| Counter | Incremented when Sentinel VoLTE encounters an error while attempting to start the feature.
    IssuedWarning
| Counter | Incremented when a non-fatal problem is encountered and the feature issues a warning.
    FailedDuringExecution
| Counter | Incremented when a fatal problem is encountered and the feature cannot execute correctly.
    TimedOut
| Counter | Incremented when the feature takes too long to complete and Sentinel VoLTE aborts execution.
    NoPendingSdpCdr
| Counter | Incremented when the feature runs but there is no pending SDP CDR to suppress
    SdpCdrWriteSuppressed
| Counter | Incremented each time an SDP CDR is suppressed
    SdpCdrWriteAllowed
| Counter | Incremented each time the feature runs but doesn’t suppress a pending SDP CDR

### Functionality

This feature uses information available in session state to suppress interim CDRs from being written in response to SDP changes for non-roaming Mobile Terminating calls. The mechanism it uses to suppress the CDRs from being written by the `VolteInterimCdr` feature is to unset the `WriteCdrOnSDPChange` session state field.

When this feature runs, if the session state variable `RoamingIndicator` is False, and `CallType` is MobileTerminating, the `WriteCdrOnSDPChange` session state field will be set to False.

## VoLTE Interim CDR Feature

`VolteInterimCdr` is a system feature that is responsible for writing interim Call Detail Records and/or Diameter Accounting Requests (ACRs) throughout the session.

`VolteInterimCdr` runs at various key points throughout a session and if any of its write conditions are met it writes either, both, or neither of:

1. an interim AVP CDR using the `cdr-ra`

2. an ACR using the `rf-control-ra`

Interim AVP CDRs and Diameter Accounting Records (ACRs) have substantially similar content and the same triggering logic hence both are supported by this feature.

| By default, Sentinel runs `VolteInterimCdr` as the very last feature in the `post` phase of almost every Sip or Charging related feature execution script and EndSession. For example:
    featurescript SipEndSession-SysPost-Default {
        run VolteInterimCdr
        run MaxCallDuration
        run SessionRefresh
    }

### Details

Feature script name | VolteInterimCdr
Applicable contexts | SIP service
SAS Support | No
Prerequisite features | None, but information from various features is used if available

### Session state inputs and outputs

#### Inputs

If any of these fields are unset the feature will skip writing the current CDR/ACR.

This feature uses the same session state fields as the Sentinel Interim CDR feature. This page will only discuss the additions to the fields described there.

Name | Type | Description | Where set
--- | --- | --- | ---
TerminatingDomain | String | The accepted terminating domain in a T-ADS scenario | MMTelWifiChargingFinalisation feature, SCCTADSParallelRouting feature
MMTelInformation | org.jainslee.resources.diameter .ro.types.vcb0.MmtelInformation | The MMTel-Information Diameter AVP | DiameterMMTelInfo feature
RegistrationRecords | List<com.opencloud.sentinel.state.RegistrationRecord> | Contains subscriber information retrieved from the Registrar and HSS or Cassandra | IMSIDLookup feature, IMSIDLookupFromCassandraSIP feature
CallReferenceNumber | byte[] | Contains the Call Reference Number used in queries to the HLR | FetchMSRN feature

### Functionality

This feature can be configured to:

- write CDRs to the local filesystem (through the `cdr-ra`), and/or

- write ACRs using the Diameter Rf protocol (through the `rf-control-ra`)

- not write either

This feature uses the information from the session state fields mentioned above and constructs a CDR and/or ACR for output. See AVP CDR Format for the format of the CDRs.

Although the feature runs in many execution points, it inspects various session state fields to decide whether or not to write an interim CDR and/or ACR.

An interim CDR and/or ACR will be written under any of the following conditions:

- On the initial SIP request on the 'LegForCdrs'

- On the `SipInterimCdr` feature timer, if no CDR has been recently written

- On session end

- When a feature (e.g. SDP Monitor) sets `WriteCdrOnSDPChange` to true

When the VoLTE TAS is configured for session replication CDRs will still be written and ACRs will continue to be sent after node failover. The feature maintains a timer for the interim CDR period. This timer may be adjusted according to the Rf accounting interval provided by the CDF. The interim CDR timer is armed redundantly if session replication is enabled.

When the feature is about to write an INTERIM or STOP ACR for a Sentinel Session, if checks if the current Rhino node has an Rf Control Activity for the Diameter Rf session. If it does not, a new Rf Control Activity is started using the same Rf session identifier. This fails over the Rf session. The new session will use `Accounting-Record-Number`s continuing from the last known record number before failover.

Also see Charging Information for general information about the contents of CDRs, ACRs and CCRs.

| This feature only supports writing binary CDRs. If the `cdr-ra` is configured to write text CDRs the feature will fail to execute.

### Configuration

These parameters configure the feature:

Parameter | Type | Description
--- | --- | ---
WriteCdrOnSDPChange | boolean | When a meaningful SDP change occurs on a monitored leg, write a CDR
InterimTimerPeriod | long | The maximum duration in seconds between timer driven interim CDRs. Setting this to zero will disable timer based interim CDRs.
UseCdrRa | boolean | Whether interim CDRs should be written to disk using the `cdr-ra`
UseRfControlRa | boolean | Whether ACRs should be written using the `rf-control-ra`

#### Configuration profile naming

Configuration Profile Table Name | Description | Profile Naming
--- | --- | ---
SipInterimCdrProfileTable | SipInterimCdr feature configuration parameters | SentinelSelectionKey (typically `$PLATFORM_OPERATOR_NAME::::` for example, `OpenCloud::::`)

### Feature responses

Response | Reason
--- | ---
featureHasFinished | feature has finished

## VoLTE SIP AVP CDR Feature

This feature is responsible for building a Call Detail Record that reflects the actions taken whilst processing a session.

It runs once when a session is ending and creates a CDR based on information gathered from session state, and then writes it out using the `cdr-ra`.

| By default, Sentinel runs `VolteSipAvpCdr` in the `post` SIP end session feature execution script. For example:
    featurescript SipEndSession-SysPost-Default {
        run VolteSipAvpCdr
        run MaxCallDuration
        run SessionRefresh
    }

### Details

Feature script name | VolteSipAvpCdr
Applicable contexts | SIP service
SAS Support | No
Prerequisite features | None, but information from various features is used if available

### Session state inputs and outputs

#### Inputs

If any of these fields are unset the feature will skip writing them to the CDR file.

This feature uses the same session state fields as the Sentinel SIP AVP CDR feature. This page will only discuss the additions to the fields described there.

Name | Type | Description | Where set
--- | --- | --- | ---
TerminatingDomain | String | The accepted terminating domain in a T-ADS scenario | MMTelWifiChargingFinalisation feature, SCCTADSParallelRouting feature
MMTelInformation | org.jainslee.resources.diameter .ro.types.vcb0.MmtelInformation | The MMTel-Information Diameter AVP | DiameterMMTelInfo feature
RegistrationRecords | List<com.opencloud.sentinel.state.RegistrationRecord> | Contains subscriber information retrieved from the Registrar and HSS or Cassandra | IMSIDLookup feature, IMSIDLookupFromCassandraSIP feature
CallReferenceNumber | byte[] | Contains the Call Reference Number used in queries to the HLR | FetchMSRN feature

### Functionality

This features uses the information from the session state fields mentioned above and constructs a protobuf message out of it for output. See AVP CDR Format for the format of these messages.

Also see Charging Information for general information about the contents of CDRs and CCRs.

| This feature only supports writing binary CDRs. If the `cdr-ra` is configured to write string CDRs the feature will fail to execute.

### Feature responses

Response | Reason
--- | ---
featureHasFinished | feature has finished

## MMTel Features

These features are MMTel specific.

Feature | What it does
--- | ---
MMTel Subscriber Data Representation | a logical representation of supplementary service data as a group of POJO objects. It allows MMTel services/features to execute independently of any concrete schema for the supplementary service data. Therefore it can be loaded from the HSS or the HLR using the MMTel-Services XML schema or 3GPP MAP ASN.1 schema.
MMTel Conference | lets users create multi-party sessions between two or more parties
MMTel Conference Subscription | provides a means for UEs to subscribe to “conference” event package notifications for a conference
MMTelCDIV | enables a ‘diverting user’ to divert communications addressed to the ‘diverting user’ to another destination
MMTelCW | lets a UE be informed that no resources are available for an incoming communication
MMTelHold | lets a user suspend reception of the media stream(s) of an established IP multimedia session, and resume the media stream(s) at a later time
MMTelICB | implements incoming communication barring and anonymous communication rejection
MMTelOCB | implements outgoing communication barring and operator determined retargeting
Operator Determined Barring | provides call barring rules determined by the operator that take precedence over MMTelICB and MMTelOCB
MMTelOIP | implements the Originating Identification Presentation (OIP) service
MMTelOIR | implements the Originating Identification Restriction (OIR) service
MMTelTIP | implements the Terminating Identification Presentation (TIP) service
MMTelTIR | implements the Terminating Identification Restriction (TIR) service
MMTelWifiChargingFinalisation | handles the finalisation of charging when a call is answered over WiFi.
Diameter MMTel Information | records charging information about MMTel supplementary services invoked on a call.
MMTel Determine Flexible Alerting Mode | determines if and how the Flexible Alerting features will execute based on feature configuration and the HSS Subscriber Data.
MMTelParallelFA | implements the Flexible Alerting service, by alerting the group members in parallel
MMTelSequentialFA | implements the Flexible Alerting service, by sequentially alerting the group members.
MMTelBindAci | connects the IMPU acquired from the subscriber registration to the existing ACI for the session transfer
MMTelStodEnabled | checks if the subscriber has the STOD service provisioned
MMTelStodTriggerAnchor | handles the transfer request and route it to the previous bound session
MMTelStodProcessHandover | intercepts the transfer INVITE routed by the MMTelStodTriggerAnchor feature and connects the existing called led to the new calling leg and releases the previous calling leg
MMTelECT | enables a party involved in a communication to transfer their role in that communication to a third party
Geo Local Normalization | adds the `geo-local` value to the Tel URI `phone-context` parameter for local numbers that should not be translated to international format.
DetermineSharedAndUndisclosedIdentities | uses information from a SIP `INVITE` and session state to determine if the call includes shared or undisclosed identity information associated with a companion device. The feature is run in both originating and terminating session execution plans.
Hide Undisclosed Identity | replaces the undisclosed identity with the shared identity for an originating call from a companion device where such hiding has been requested
DetermineRoamingFromHlr | is responsible for reading subscriber location data from the HLR and writing it into Sentinel session state variable fields.
MMTelDeterminePSAPCallback | determines whether a received SIP INVITE corresponds to a PSAP callback, and stops any other features that could potentially prevent the call being set up.
MMTel PSAP Callback | The two features here are responsible for identifying appropriate calls as PSAP callbacks and (if required) recording that a PSAP call has occurred.
Set Companion Device Headers | sets the companion device headers to the initial INVITE when the subscriber has been provisioned with companion devices.

Additionally the MMTel AS provides support for a number of Vertical Service Code Features.

Feature | What it does
--- | ---
LocationBasedDialling | updates the Request URI of a SIP INVITE, based on the location of the calling party and the dialled number
VoicemailDialling | redirects the calling party to their voicemail server.
XcapDataUpdate | performs a list of predefined HTTP PUT operations to update subscriber data in an XCAP server.

## Call Barring Features

Call Barring Features.

Feature | What it does
--- | ---
MMTelICB | implements incoming communication barring and anonymous communication rejection
MMTelOCB | implements outgoing communication barring and operator determined retargeting
Operator Determined Barring | provides call barring rules determined by the operator that take precedence over MMTelICB and MMTelOCB
Operator Specific Barring Types | are 4 operator defined rules that are stored in the AS. The ODB data indicates which of them should be evaluated and, like all others ODB conditions, they take precedence over MMTelICB and MMTelOCB
Prefix Based Barring | provides a mechanism for an operator to augment the implicit or explicit condition of a MMTelOCB barring rule, so that the rule will also apply when the called party number matches some prefix with optional length criteria
General Feature Barring | provides a mechanism for preceding features to bar a call on behalf of the terminating user. It takes precedence over ODB and MMTelICB

## General Feature Barring

General Feature Barring provides a mechanism for preceding features to bar a call on behalf of the terminating user. It takes precedence over ODB and MMTelICB .

### What is General Feature Barring

General Feature Barring is an enhancement to Incoming Call Barring, to enable other features to trigger barring.

General Feature barring uses the `BarIncomingCall` session state field to signal that another feature wishes a call to be barred.

When `BarIncomingCall` is `True` then the call will be barred.

General Feature Barring takes precedence over ODB and ICB rules.

## MMTelICB

The MMTelICB feature implements incoming communication barring and anonymous communication rejection . (The MMTelOCB feature implements outgoing communication barring.)

### What is ICB?

3GPP defines Communication Barring in TS 24.611, including Incoming Communication Barring (ICB), Anonymous Communication Rejection as a special case of ICB, and Outgoing Communication Barring (OCB):

| The incoming communication barring (ICB) is a service that rejects incoming communications that fulfil certain provisioned or configured conditions on behalf of the terminating user. The anonymous communication rejection (ACR) is a particular case of the ICB service, that allows barring of incoming communications from an anonymous originator on behalf of the terminating user. The incoming communication barring (ICB) service makes it possible for a user to have barring of certain categories of incoming communications according to a provisioned or user configured barring program and is valid for all incoming communications. A barring program is expressed as a set of rules in which the rules have a conditional part and an action part. Examples of conditions are whether the asserted originating public user identity matches a specific public user identity or whether the originating public user identity is restricted (anonymous). The action part could specify for a rule that contains a matching condition that the specific incoming communication is barred. The inhibition of incoming forwarded calls is a special case of the ICB and allows the served user to reject incoming communications from users or subscribers who have diverted the communication towards the served user. The communication history information will be used to trigger the service. The anonymous communication rejection (ACR) service allows the served user to reject incoming communications on which the asserted public user identity of the originating user is restricted. In case the asserted public user identity of the originating user is not provided then the communication is allowed by the ACR service. It is highlighted here because it is a regulatory service in many countries.

### Feature Cheat Sheet

B2BUA Instance | SAS Support | Originating / Terminating | Point(s) in Session Plan | Network Operator Data | Subscriber Data | Stateful or Stateless | POJO Feature or SBB Feature
--- | --- | --- | --- | --- | --- | --- | ---
MMTEL | Yes | Terminating | SipAccess_SubscriberPreCreditCheck | Yes | Yes, comes from the HSS | Stateless | POJO

### Prerequisite Features

- DetermineCallType

- SubscriberDataLookupFromHSS or SubscriberDataLookupFromHLR

- SubscriberDetermination

- Determine International and Roaming Status (used for Roaming, International and International-exHC detection)

| For announcements, SIPPlayAnnouncement is a dependent feature; but it is not a prerequisite.

### Source Code

This feature’s source code is available in the Sentinel VoLTE SDK in the `mmtel-communication-barring` module pack. It can be viewed by using the `create-module` command in the SDK with that module pack, for example:

`> create-module new-cb-module opencloud#mmtel-communication-barring#volte/3.1.0;3.1.0.0`

This command will prompt you for information needed to create the new modules, once completed the original source for the feature can be found in the new modules.

The module-pack includes the following modules relevant to this feature:

Module Name | Description
--- | ---
mmtel-communication-barring | Group module for the feature that includes all of the modules listed below.
mmtel-communication-barring-library | Contains code shared by both communication barring features.
mmtel-icb-profile | Contains the profile specification for the feature configuration profile table.
mmtel-icb | Contains the feature itself.

### Interaction with OIP

According to section 4.6.4 of 3GPP TS 24.611, MMTelICB must run before MMTelOIP.

### Network Operator Data

This data is stored in a JSLEE Configuration Profile Table, called `MMTelICBConfigProfileTable`.

Operator data is scoped according to a Sentinel selection key.

    Attribute Name
| Type |
    Default Value
| Description
    PlayAnnouncement
| Boolean |
    false
| If true, ICB will request an announcement is played in the case that it bars the session setup.
    ACRAnnouncementID
| int |
    0
| The ID for the announcement to be played in the case of Anonymous Call Rejection. If set to zero there is no announcement.
    AnnouncementID
| int |
    0
| The ID for the announcement to be played in all other ICB cases. If set to zero there is no announcement.
    InternationalRulesActive
| Boolean |
    false
| If false, ICB will ignore International and International-exHC rules.

### Session Input Variables

    Variable name
| Type | Comments
    MMTelICBServiceData
| Complex | Read from the HSS or HLR in SubscriberDataLookupFromHSS or SubscriberDataLookupFromHLR
    RoamingIndicator
| Boolean | Set by the Determine International and Roaming Status feature.
    International
| Boolean | Set by the Determine International and Roaming Status feature.
    InternationalExHC
| Boolean | Set by the Determine International and Roaming Status feature.
    BarIncomingCall
| Boolean | Set by other preceding features to trigger General Feature Barring.

### Session Output Variables

Variable name | Type | Comments
--- | --- | ---
    ICBBarred
| Boolean | Set to true if the ICB feature bars the call. It exists so that feature execution scripts can read the variable and take action
    ICBBarredWithAnnouncement
| Boolean | Set to true if the ICB feature bars the call, and the feature is configured to request an announcement as part of barring
    AnnouncementID
| int | The announcement ID to be used if an announcement is configured as part of barring
    EndSessionAfterAnnouncement
| int | The status code used when ending the session — if barring has occurred and announcements are used.
    RanIcb
| Boolean | Signals to other features that ICB ran on this session.

### Supported Barring Rule Conditions

Barring rule conditions that are evaluated include:

#### Anonymous

To comply with the requirements as set for simulation of the ACR service, the anonymous element only evaluates to true when the conditions as set out in subclause 4.5.2.6.2 for asserted originating public user identity apply.

Use this XML in the REM HSS Subscriber Data Page to configure ICB for anonymous calls:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <cp:ruleset xmlns="http://uri.etsi.org/ngn/params/xml/simservs/xcap" xmlns:cp="urn:ietf:params:xml:ns:common-policy" xmlns:ocp="urn:oma:xml:xdm:common-policy">
        <cp:rule id="anonymous">
            <cp:conditions>
                <anonymous/>
            </cp:conditions>
            <cp:actions>
                <allow>false</allow>
            </cp:actions>
        </cp:rule>
    </cp:ruleset>

#### Roaming

This condition evaluates to true if the session state variable `RoamingIndicator` is true. This is set by the Determine International and Roaming Status feature.

Use this XML in the REM HSS Subscriber Data Page to configure ICB for roaming calls:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <cp:ruleset xmlns="http://uri.etsi.org/ngn/params/xml/simservs/xcap" xmlns:cp="urn:ietf:params:xml:ns:common-policy" xmlns:ocp="urn:oma:xml:xdm:common-policy">
        <cp:rule id="roaming">
            <cp:conditions>
                <roaming/>
            </cp:conditions>
            <cp:actions>
                <allow>false</allow>
            </cp:actions>
        </cp:rule>
    </cp:ruleset>

#### Media

This condition evaluates to true when the value of this condition matches the media field in one of the "m=" lines in the SDP message body offered in an INVITE request.

Use this XML in the REM HSS Subscriber Data Page to configure ICB for calls offering specific media:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <cp:ruleset xmlns="http://uri.etsi.org/ngn/params/xml/simservs/xcap" xmlns:cp="urn:ietf:params:xml:ns:common-policy" xmlns:ocp="urn:oma:xml:xdm:common-policy">
        <cp:rule id="no_video">
            <cp:conditions>
                <media>video</media>
            </cp:conditions>
            <cp:actions>
                <allow>false</allow>
            </cp:actions>
        </cp:rule>
    </cp:ruleset>

Combinations of media types may be expressed as multiple conditions within the same rule. For example:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <cp:ruleset xmlns="http://uri.etsi.org/ngn/params/xml/simservs/xcap" xmlns:cp="urn:ietf:params:xml:ns:common-policy" xmlns:ocp="urn:oma:xml:xdm:common-policy">
        <cp:rule id="no_video_and_text">
            <cp:conditions>
                <media>video</media>
                <media>text</media>
            </cp:conditions>
            <cp:actions>
                <allow>false</allow>
            </cp:actions>
        </cp:rule>
    </cp:ruleset>

#### Identity

This condition evaluates to true if the identity of the other party in the communication matches that which is expressed in the condition. Identities within the condition can be expressed in different ways:

- a single, fully expressed identity (e.g. sip:alice@example.com)

- a whole domain (e.g. example.com)

- a whole domain, but with exceptional identities or domains (e.g. example.com except for alice@example.com)

- all identities (may also have exceptions)

- any combination of the above

In case of a single identity (i.e. a 'one' condition), or in case of an exception (i.e. an 'except' condition), the URI in the condition and the URI to match against are both normalized before they are compared. Normalization is done using the Normalization Component.

The following XML snippets show how to configure the user’s Subscriber data for each of the above cases.

A single, fully expressed identity (the identity 'sip:alice@example.com' is matched)

This example, without any other rule, blocks any session from 'sip:alice@example.com'.

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <cp:ruleset xmlns="http://uri.etsi.org/ngn/params/xml/simservs/xcap" xmlns:cp="urn:ietf:params:xml:ns:common-policy" xmlns:ocp="urn:oma:xml:xdm:common-policy">
        <cp:rule id="bar-alice">
            <cp:conditions>
                <cp:identity>
                    <one id="sip:alice@example.com"/>
                </cp:identity>
            </cp:conditions>
            <cp:actions>
                <allow>false</allow>
            </cp:actions>
        </cp:rule>
    </cp:ruleset>

A domain (all identities at 'example.com' are matched)

This example, without any other rule, blocks any session from domain 'example.com'.

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <cp:ruleset xmlns="http://uri.etsi.org/ngn/params/xml/simservs/xcap" xmlns:cp="urn:ietf:params:xml:ns:common-policy" xmlns:ocp="urn:oma:xml:xdm:common-policy">
        <cp:rule id="bar-domain">
            <cp:conditions>
                <cp:identity>
                    <many domain="example.com"></many>
                </cp:identity>
            </cp:conditions>
            <cp:actions>
                <allow>false</allow>
            </cp:actions>
        </cp:rule>
    </cp:ruleset>

A whole domain with an exceptional identity (all identities at 'example.com' are matched except 'sip:alice@example.com')

This example, without any other rule, blocks any session from domain 'example.com' except if originated from 'sip:alice@example.com'.

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <cp:ruleset xmlns="http://uri.etsi.org/ngn/params/xml/simservs/xcap" xmlns:cp="urn:ietf:params:xml:ns:common-policy" xmlns:ocp="urn:oma:xml:xdm:common-policy">
        <cp:rule id="barr-domain-with-exception">
            <cp:conditions>
                <cp:identity>
                    <many domain="example.com">
                        <except id="sip:alice@example.com"/>
                    </many>
                </cp:identity>
            </cp:conditions>
            <cp:actions>
                <allow>false</allow>
            </cp:actions>
        </cp:rule>
    </cp:ruleset>

A whole domain with an exceptional domain (all identities at 'example.com' are matched except 'sip:alice@example.com')

This example, without any other rule, blocks any session from domain 'example.com' except if originated from the subdomain 'callcentre.example.com'.

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <cp:ruleset xmlns="http://uri.etsi.org/ngn/params/xml/simservs/xcap" xmlns:cp="urn:ietf:params:xml:ns:common-policy" xmlns:ocp="urn:oma:xml:xdm:common-policy">
        <cp:rule id="barr-domain-except-callcentre">
            <cp:conditions>
                <cp:identity>
                    <many domain="example.com">
                        <except domain="callcentre.example.com"/>
                    </many>
                </cp:identity>
            </cp:conditions>
            <cp:actions>
                <allow>false</allow>
            </cp:actions>
        </cp:rule>
    </cp:ruleset>

| Note the attribute of the 'except' element is now 'domain'.

All identites (all identities are matched)

This example, without any other rule, blocks all sessions from any user.

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <cp:ruleset xmlns="http://uri.etsi.org/ngn/params/xml/simservs/xcap" xmlns:cp="urn:ietf:params:xml:ns:common-policy" xmlns:ocp="urn:oma:xml:xdm:common-policy">
        <cp:rule id="barr-all">
            <cp:conditions>
                <cp:identity>
                    <many />
                </cp:identity>
            </cp:conditions>
            <cp:actions>
                <allow>false</allow>
            </cp:actions>
        </cp:rule>
    </cp:ruleset>

A more complex Identity condition expression (all identies at 'example2.com' match except for 'sip:charlie@example2.com'. Also the identities 'sip:alice@example1.com' and 'sip:bob@example1.com' match.)

This example, without any other rule, blocks any session from all users registered in the domain 'example2.com', from the user 'sip:alice@example1.com' and from the user sip:bob@example1.com, except from 'sip:charlie@example2.com.

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <cp:ruleset xmlns="http://uri.etsi.org/ngn/params/xml/simservs/xcap" xmlns:cp="urn:ietf:params:xml:ns:common-policy" xmlns:ocp="urn:oma:xml:xdm:common-policy">
        <cp:rule id="barr-some">
            <cp:conditions>
                <cp:identity>
                    <one id="sip:alice@example1.com"/>
                    <one id="sip:bob@example1.com"/>
                    <many domain="example2.com">
                        <except id="sip:charlie@example2.com"/>
                    </many>
                </cp:identity>
            </cp:conditions>
            <cp:actions>
                <allow>false</allow>
            </cp:actions>
        </cp:rule>
    </cp:ruleset>

Another more complex Identity condition expression with more than one rule.

This example, always blocks some domains, always allow other domains and a set of sip URIs.

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <cp:ruleset xmlns="http://uri.etsi.org/ngn/params/xml/simservs/xcap" xmlns:cp="urn:ietf:params:xml:ns:common-policy" xmlns:ocp="urn:oma:xml:xdm:common-policy">
        <cp:rule id="always-allow-these-domains">
            <cp:conditions>
                <cp:identity>
                    <many domain="emergency.org"></many>
                    <many domain="police.org"></many>
                </cp:identity>
            </cp:conditions>
            <cp:actions>
                <allow>true</allow>
            </cp:actions>
        </cp:rule>

        <cp:rule id="always-barr-these-domains">
            <cp:conditions>
                <cp:identity>
                    <many domain="fakelotery.org"></many>
                    <many domain="dhueb!.org"></many>
            <many domain="fakeprize.com"></many>
                </cp:identity>
            </cp:conditions>
            <cp:actions>
                <allow>false</allow>
            </cp:actions>
        </cp:rule>

       <cp:rule id="always-barr-these-identities">
            <cp:conditions>
                <cp:identity>
                    <one id="sip:john@example.com"/>
                    <one id="sip:marc@example.com"/>
                </cp:identity>
            </cp:conditions>
            <cp:actions>
                <allow>false</allow>
            </cp:actions>
        </cp:rule>

    </cp:ruleset>

| Depending on the value of the 'allow' element of the rule, the rule can essentially become a 'whitelist' or a 'blacklist'.

#### International

This condition evaluates to true if the session state variable `International` is true and 'InternationalRulesActive' is true. 'International' is set by the Determine International and Roaming Status feature. 'InternationalRulesActive' is configured in the ICB feature profile and defaults to false. This is because it is not possible to accurately determine whether the calling party is international in all circumstances.

Use this XML in the REM HSS Subscriber Data Page to configure ICB for international calls:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <cp:ruleset xmlns="http://uri.etsi.org/ngn/params/xml/simservs/xcap" xmlns:cp="urn:ietf:params:xml:ns:common-policy" xmlns:ocp="urn:oma:xml:xdm:common-policy">
        <cp:rule id="international">
            <cp:conditions>
                <international/>
            </cp:conditions>
            <cp:actions>
                <allow>false</allow>
            </cp:actions>
        </cp:rule>
    </cp:ruleset>

#### International-exHC

This condition evaluates to true if the session state variable `InternationalExHC` is true and 'InternationalRulesActive' is true. 'International' is set by the Determine International and Roaming Status feature. 'InternationalRulesActive' is configured in the ICB feature profile and defaults to false. This is because it is not possible to accurately determine whether the calling party is international in all circumstances.

Use this XML in the REM HSS Subscriber Data Page to configure ICB for international-exHC calls:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <cp:ruleset xmlns="http://uri.etsi.org/ngn/params/xml/simservs/xcap" xmlns:cp="urn:ietf:params:xml:ns:common-policy" xmlns:ocp="urn:oma:xml:xdm:common-policy">
        <cp:rule id="international-exHC">
            <cp:conditions>
                <international-exHC/>
            </cp:conditions>
            <cp:actions>
                <allow>false</allow>
            </cp:actions>
        </cp:rule>
    </cp:ruleset>

#### Unconditional

An empty conditions element is used to represent unconditional.

Use this XML in the REM HSS Subscriber Data Page to configure ICB for all calls:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <cp:ruleset xmlns="http://uri.etsi.org/ngn/params/xml/simservs/xcap" xmlns:cp="urn:ietf:params:xml:ns:common-policy" xmlns:ocp="urn:oma:xml:xdm:common-policy">
        <cp:rule id="anonymous">
            <cp:conditions/>
            <cp:actions>
                <allow>false</allow>
            </cp:actions>
        </cp:rule>
    </cp:ruleset>

#### Communication Diverted

This condition evaluates to true when the incoming communication has been previously diverted.

Diverted communication can be recognised by the presence of the `History` header field, as specified in 3GPP TS 24.604

Use this XML in the REM HSS Subscriber Data Page to configure ICB for diverted calls:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <cp:ruleset xmlns="http://uri.etsi.org/ngn/params/xml/simservs/xcap" xmlns:cp="urn:ietf:params:xml:ns:common-policy" xmlns:ocp="urn:oma:xml:xdm:common-policy">
        <cp:rule id="diverted">
            <cp:conditions>
                <communication-diverted/>
            </cp:conditions>
            <cp:actions>
                <allow>false</allow>
            </cp:actions>
        </cp:rule>
    </cp:ruleset>

#### Validity

This condition evaluates to true if the current time is within the times specified by the validity period Time is based on the Home Network time; that is, the time of the MMTel Server.

Use this XML in the REM HSS Subscriber Data Page to configure ICB for a validity period:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <cp:ruleset xmlns="http://uri.etsi.org/ngn/params/xml/simservs/xcap" xmlns:cp="urn:ietf:params:xml:ns:common-policy" xmlns:ocp="urn:oma:xml:xdm:common-policy">
        <cp:rule id="validity">
            <cp:conditions>
                <cp:validity>
                    <cp:from>2000-01-01T00:00:00</cp:from>
                    <cp:until>2099-12-31T23:59:59</cp:until>
                </cp:validity>
            </cp:conditions>
            <cp:actions>
                <allow>false</allow>
            </cp:actions>
        </cp:rule>
    </cp:ruleset>

#### Rule Deactivated

This condition always evaluates to false. Generally used to disable a rule that has other conditions without removing the rule entirely.

The rule is re-enabled by removing this condition.

Use this XML in the REM HSS Subscriber Data Page to configure a deactivated rule:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <cp:ruleset xmlns="http://uri.etsi.org/ngn/params/xml/simservs/xcap" xmlns:cp="urn:ietf:params:xml:ns:common-policy" xmlns:ocp="urn:oma:xml:xdm:common-policy">
        <cp:rule id="deactivated">
            <cp:conditions>
                <rule-deactivated/>
            </cp:conditions>
            <cp:actions>
                <allow>false</allow>
            </cp:actions>
        </cp:rule>
    </cp:ruleset>

#### Barring Rule Actions

Barring rule actions are a string. There could be many actions defined, but the only one that makes any sense is the `allow` action.

The `allow` action has a Boolean attribute, with meaning as follows:

- `true`— allow session setup to proceed

- `false`— deny session setup from proceeding.

Any other rule action (in other words, an action that is not set to `allow`) will result in us treating the action as the following:

- allow rule action with value of true.

### Statistics

MMTelICB statistics are tracked by the sentinel.volte.sip SBB and can be found under the following parameter set in REM:
SLEE-Usage → sentinel.volte.sip service → sentinel.volte.sip SBB → feature → MMTelICB
or with rhino-stats:
"SLEE-Usage.Services.ServiceID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].SbbID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].feature.MMTelICB"

Statistic | Type | Incremented when…​
--- | --- | ---
    Started
| Counter | the feature runs
    FailedToStart
| Counter | Sentinel VoLTE encounters an error while attempting to start the feature
    IssuedWarning
| Counter | a non-fatal problem is encountered and the feature issues a warning
    FailedDuringExecution
| Counter | a fatal problem is encountered and the feature cannot execute correctly
    TimedOut
| Counter | the feature takes too long to complete and Sentinel VoLTE aborts execution
    CallBarred
| Counter | the feature bars a call (including when barring due to ACR)
    CallBarredByOdb
| Counter | the feature bars a call by Operator Determined Barring rule
    PlayAnnouncementTriggered
| Counter | the feature requests that an announcement be played to the calling party
    ACRTriggered
| Counter | a call is barred by ACR
    OdbRulesEvaluatedTrue
| Counter | a rule was evaluated to be True
    RulesEvaluatedTrue
| Counter | incremented by the number of rules which evaluated true

### Behaviour

#### Determination

If operator data is not present, the ICB feature:

1. Increments an error statistic.

2. Logs a message at the `Fine` level.

3. Informs the Sentinel core that the feature is not configured appropriately (`Invalid Configuration`).

4. Exits.

If General Feature Barring determines that a call should be barred - Barring Action below proceeds.

If `MMTelICBServiceData.OperatorAuthorized` or `MMTelICBServiceData.Active` is `false`, the feature finishes execution without modifying any state.

If the rules do not parse, then the feature:

- instructs Sentinel core that the feature has failed due to configuration problems

- finishes execution without modifying any state.

Incoming ODB Rule Processing occurs as below.

If no ODB rules match, ICB Rule Processing occurs as below.

If either rule set determines `allow=false`, the Barring Action is performed as below.

If either set determines `allow=true` or no rules are matched, the ICB feature sets the session output variable `ICBBarred` to `false` and finishes without modifying any further state.

#### Rule Processing

When the feature processes a set of rules (either ODB or ICB):

For each rule, if | then
--- | ---
the rule has no `<conditions>` element; the rule has an empty `<conditions>` element; or conditions are present and they all evaluate to true; | the rule matches.

The actions from all matching rules are combined.

If…​ | then the combined result for the rule set is:
--- | ---
any matching rules had the action `allow=true` | `allow=true`
all matching rules had the action `allow=false` | `allow=false`

| When a rule contains multiple conditions, they all must match for the whole rule to match. This is essentially a logical 'AND' between the conditions. To express a logical 'OR' of conditions, the conditions must be placed in different rules.

#### Barring Action

If a ruleset determines `allow=false` or GFB bars the call then…​

The ICB feature sets the session output variable `ICBBarred` to `true`.

If network configuration has `PlayAnnouncement` set to `true` (`MmtelICBConfig.PlayAnnouncement == true`), and ICB has decided to bar the communication, then the ICB feature sets session output variable `AnnouncementID` to `MmtelICBConfig.AnnouncementID`.

Finally, if the communication is to be barred, ICB rejects the call with the appropriate SIP error response code:

If any matching rule contains the “anonymous” condition, use 433 Anonymity Disallowed. This is to provide ACR functionality. (See section 4.5.2.6.1.)

Otherwise use 603 Decline.

#### Roaming Determination

The ICB feature does not compute whether or not the served user is roaming; rather it relies on a session input variable (`isRoaming`). This is set by Sentinel’s `DetermineIfRoaming` feature.

Example feature execution script fragment:

    run DetermineInternationalAndRoamingStatus
    run MMTelICB

#### Playing Announcements

The MMTelICB feature does not play announcements itself; rather it relies on setting of session output variables (`AnnouncementID`, `ICBBarredWithAnnouncement`, `EndSessionAfterAnnouncement`). These are set by the MMTelICB feature if an announcement is to be played. They are used by the out-of-the-box feature execution scripts such that if announcements are desired to be played prior to the barred call being terminated, it is played using the SIPPlayAnnouncement feature.

This is an example feature execution script, taken from a fragment of the out-of-the-box execution scripts.

    run MMTelICB
    if (session.ICBBarredWithAnnouncement) {
       run SIPPlayAnnouncement
    }

The SIPPlayAnnouncement feature checks session state for the `AnnouncementID` field, and if the value is non-zero will play an announcement. When the announcement is played using the `SIPPlayAnnouncement` feature, it is played to the calling party.

Finally, when the announcement is complete the `SIPPlayAnnouncement` feature ends the session with the appropriate SIP error response (provided by MMTelICB during its execution). The SIP error response code is set in the `EndSessionAfterAnnouncement` session output variable.

#### Graceful Handling of Originating Access

ICB is a terminating feature. It will finish execution without modifying any state if it is invoked in an originating attempt.

### Background Information on Format of Barring Rules

Each rule is expressed as an XCAP cp-rule.

That is, it is an XML fragment:

    <cp:rule id="rule66">
            <cp:conditions>
            condition1
            condition2
            </cp:conditions>
            <cp:actions>
              <allow>false</allow>
            </cp:actions>
     </cp:rule>

In case that the allow element is not found, the feature assumes allow = false.

## MMTelOCB

The MMTelOCB feature implements outgoing communication barring and operator determined retargeting .

(The MMTelICB feature implements incoming communication barring and anonymous communication rejection.)

### What is OCB?

3GPP defines communication barring in TS 24.611, including Incoming Communication Barring (ICB), Anonymous Communication Rejection as a special case of ICB, and Outgoing Communication Barring (OCB):

| The Outgoing Communication Barring (OCB) is a service that rejects outgoing communications that fulfil certain provisioned or configured conditions on behalf of the originating user. The Outgoing Communication Barring (OCB) service makes it possible for a user to have barring of certain categories of outgoing communications according to a provisioned or user configured barring program and is valid for all outgoing communications. A barring program is expressed as a set of rules in which the rules have a conditional part and an action part. An example condition is whether the request uri matches a specific public user identity. The action part can specify for a rule that contains a matching condition that the specific outgoing communication is to be barred. The complete set of conditions and actions that apply to this service and their semantics is described in subclause 4.9.Incoming.

### Feature cheat sheet

Feature Script Name | MMTelOCB
MMTel or SCC | MMTel
Call-Type | Originating
Session Plan | mmtel-orig
Execution Points | SipAccess_SubscriberCheck, SubscriptionSipRequest
Network Operator Config | Yes
Subscriber Config | Yes
POJO or SBB | POJO
Feature FSMs | None
Feature Parameters | None
SAS Support | Yes

### Prerequisite features

- DetermineCallType

- SubscriberDataLookupFromHSS or SubscriberDataLookupFromHLR

- Determine International and Roaming Status (used for Roaming, International and International-exHC detection)

| For announcements, SIPPlayAnnouncement is a dependent feature; but it is not a prerequisite.

### Source Code

This feature’s source code is available in the Sentinel VoLTE SDK in the `mmtel-communication-barring` module pack. It can be viewed by using the `create-module` command in the SDK with that module pack, for example:

`> create-module new-cb-module opencloud#mmtel-communication-barring#volte/3.1.0;3.1.0.0`

This command will prompt you for information needed to create the new modules, once completed the original source for the feature can be found in the new modules.

The module-pack includes the following modules relevant to this feature:

Module Name | Description
--- | ---
mmtel-communication-barring | Group module for the feature that includes all of the modules listed below.
mmtel-communication-barring-library | Contains code shared by both communication barring features.
mmtel-ocb-profile | Contains the profile specification for the feature configuration profile table.
mmtel-ocb-prefix-address-list | Contains the address list specification for prefix based barring.
mmtel-ocb-prefix-classification-profile | Contains the prefix classification profile specification for prefix based barring.
mmtel-ocb | Contains the feature itself.

### Network Operator Data

The MMTelOCB feature retrieves configuration from three profile tables and an address list:

- The `MMTelOCBConfigProfileTable` provides the basic configuration for the feature.

- The `MMTelOdbOperatorSpecificTypeRuleProfileTable` provides operator-specific ODB rule configuration.

- The `${platform.operator.name}_PrefixBarring_AddressListEntryTable` maps dialled numbers to prefix barring classifications.

- The `PrefixBarringClassificationsTable` defines matching criteria and the barring treatment for classes of dialled prefixes.

#### MMTelOCBConfigProfileTable

Basic feature configuration is stored on a profile table called `MMTelOCBConfigProfileTable`.

Operator data is scoped according to a Sentinel selection key.

Attribute Name | Type | Default | Description
--- | --- | --- | ---
    PlayAnnouncement
| boolean | false | If true, MMTelOCB will request an announcement is played when it bars a call.
    AnnouncementID
| int | 0 | The ID for the announcement to be played. If set to `0` no announcement will be played.

#### MMTelOdbOperatorSpecificTypeRuleProfileTable

Operator specific ODB rule configuration is stored on a profile table called `MMTelOdbOperatorSpecificTypeRuleProfileTable`.

See How to Provision the Operator Specific Barring Rules for details of this profile table.

#### ${platform.operator.name}_PrefixBarring_AddressListEntryTable

An address list called `${platform.operator.name}_PrefixBarring_AddressListEntryTable` is used to classify the called number for prefix based barring.

See How to Configure Prefix Based Barring.

#### PrefixBarringClassificationsTable

The prefix barring address list references one or more classifications for calls to addresses that match the prefix.

Details of how each classification is treated are stored in `PrefixBarringClassificationsTable` profile table.

See How to Configure Prefix Based Barring.

### Session Input Variables

Variable name | Type | Comments
--- | --- | ---
MMTelOCBServiceData | Complex | Read from the HSS or HLR in SubscriberDataLookupFromHSS or SubscriberDataLookupFromHLR
OdbServiceData | Complex | Read from the HSS in SubscriberDataLookupFromHSS
RoamingIndicator | Boolean | Set by the Determine International and Roaming Status feature
International | Boolean | Set by the Determine International and Roaming Status feature
InternationalExHC | Boolean | Set by the Determine International and Roaming Status feature

### Session Output Variables

Variable name | Type | Comments
--- | --- | ---
    OCBBarred
| boolean | Set to `true` if the OCB feature bars the call.
    EarlyMediaAnnouncementInfoQueue
| List<SipAnnouncementInformation> | Feature adds an entry with the value of the announcement ID to be played.
    EndSessionAfterAnnouncement
| int | The status code used when ending the session if barring has occurred and announcements are used.
    RanOcb
| boolean | Signal to other features that OCB ran on this session.
    MonitorCallOnly
| boolean | Set to `true` if the feature determines that charging should be disabled for the call.

### Statistics

MMTelOCB statistics are tracked by the sentinel.volte.sip SBB and can be found under the following parameter set in REM:
SLEE-Usage → sentinel.volte.sip service → sentinel.volte.sip SBB → feature → MMTelOCB
or with rhino-stats:
"SLEE-Usage.Services.ServiceID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].SbbID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].feature.MMTelOCB"

Statistic | Type | Description
--- | --- | ---
    Started
| Counter | Incremented when the feature is invoked.
    FailedToStart
| Counter | Incremented when Sentinel VoLTE encounters an error while attempting to start the feature.
    IssuedWarning
| Counter | Incremented when a non-fatal problem is encountered and the feature issues a warning.
    FailedDuringExecution
| Counter | Incremented when a fatal problem is encountered and the feature cannot execute correctly.
    TimedOut
| Counter | Incremented when the feature takes too long to complete and Sentinel VoLTE aborts execution.
    CallBarred
| Counter | Incremented when the feature bars a call.
    CallExplicitlyAllowed
| Counter | Incremented when the feature finds a rule that explicitly allows the call to go through, thus preventing any barring.
    ODBRuleApplied
| Counter | Incremented when an ODB rule’s conditions were met and its action was executed.
    OCBRuleApplied
| Counter | Incremented when an OCB rule’s conditions were met and its action was executed.
    PrefixBasedRuleApplied
| Counter | Incremented when a rule was applied due to prefix barring. Either `CallBarred`, `CallExplicitlyAllowed` or `RedirectionRequested` will be incremented in tandem. `ODBRuleApplied` will not be incremented, even when the treatment is an OSBType rule.
    PlayAnnouncementTriggered
| Counter | Incremented when the feature requests that an announcement be played to the calling party.
    RedirectionRequested
| Counter | Incremented when an operator specific ODB rule’s conditions were met and it has been configured to redirect the call.
    RedirectionFailed
| Counter | Incremented when an attempt to redirect the outbound `INVITE` fails.
    RedirectionSuccessful
| Counter | Incremented when an attempt to redirect the outbound `INVITE` is successful.
    OdbSpecificTypeRulesNotFound
| Counter | Incremented when the subscriber data for the served user indicates that an operator specific ODB rule should be applied, but no configuration could be found for the specified rule.
    ClassifiedNumberByPrefix
| Counter | Incremented when prefix barring classifies the dialled number as triggering some barring treatment(s).
    FoundMultipleNonConflictingPrefixBarringClassifications
| Counter | Incremented when prefix barring classifies the dialled number and selects multiple classifications, all with separate treatments.
    FoundConflictingPrefixBarringClassifications
| Counter | Incremented when prefix barring classifies the dialled number and selects multiple classifications, with some duplicate treatments. Such as `classification1` `BarringTreatment=OperatorBar` `OverrideOCBAnnouncement=true` `announcementID=1` `classification2` `BarringTreatment=OperatorBar` `OverrideOCBAnnouncement=true` `announcementID=0`

### Supported Barring Rule Conditions

#### Roaming

This condition evaluates to true if the session state variable `RoamingIndicator` is true. This is set by the Determine International and Roaming Status feature.

Use this XML in the REM HSS Subscriber Data page to configure OCB for roaming calls:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <cp:ruleset xmlns="http://uri.etsi.org/ngn/params/xml/simservs/xcap" xmlns:cp="urn:ietf:params:xml:ns:common-policy" xmlns:ocp="urn:oma:xml:xdm:common-policy">
        <cp:rule id="roaming">
            <cp:conditions>
                <roaming/>
            </cp:conditions>
            <cp:actions>
                <allow>false</allow>
            </cp:actions>
        </cp:rule>
    </cp:ruleset>

#### Media

This condition evaluates to true when the value of this condition matches the media field in one of the "m=" lines in the SDP message body offered in an INVITE request.

Use this XML in the REM HSS Subscriber Data Page to configure OCB for calls offering specific media:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <cp:ruleset xmlns="http://uri.etsi.org/ngn/params/xml/simservs/xcap" xmlns:cp="urn:ietf:params:xml:ns:common-policy" xmlns:ocp="urn:oma:xml:xdm:common-policy">
        <cp:rule id="no_video">
            <cp:conditions>
                <media>video</media>
            </cp:conditions>
            <cp:actions>
                <allow>false</allow>
            </cp:actions>
        </cp:rule>
    </cp:ruleset>

Combinations of media types may be expressed as multiple conditions within the same rule. For example:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <cp:ruleset xmlns="http://uri.etsi.org/ngn/params/xml/simservs/xcap" xmlns:cp="urn:ietf:params:xml:ns:common-policy" xmlns:ocp="urn:oma:xml:xdm:common-policy">
        <cp:rule id="no_video_and_text">
            <cp:conditions>
                <media>video</media>
                <media>text</media>
            </cp:conditions>
            <cp:actions>
                <allow>false</allow>
            </cp:actions>
        </cp:rule>
    </cp:ruleset>

#### Identity

This condition evaluates to true if the identity of the other party in the communication matches that which is expressed in the condition. Identities within the condition can be expressed in different ways:

- a single, fully expressed identity (e.g. sip:alice@example.com)

- a whole domain (e.g. example.com)

- a whole domain, but with exceptional identities or domains (e.g. example.com except for alice@example.com)

- all identities (may also have exceptions)

- any combination of the above

In case of a single identity (i.e. a 'one' condition), or in case of an exception (i.e. an 'except' condition), the URI in the condition and the URI to match against are both normalized before they are compared. Normalization is done using the Normalization Component.

The URI to match against although normalized comes from the inbound request. This means that the URI will not have had number translation features such as SIP Short Code applied. Therefore any condition intended to match a shortcode should take this into account.

The following XML snippets show how to configure the user’s Subscriber data for each of the above cases.

A single, fully expressed identity (the identity 'sip:alice@example.com' is matched)

This example, without any other rule, blocks any session towards 'sip:alice@example.com'.

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <cp:ruleset xmlns="http://uri.etsi.org/ngn/params/xml/simservs/xcap" xmlns:cp="urn:ietf:params:xml:ns:common-policy" xmlns:ocp="urn:oma:xml:xdm:common-policy">
        <cp:rule id="barr-alice">
            <cp:conditions>
                <cp:identity>
                    <one id="sip:alice@example.com"/>
                </cp:identity>
            </cp:conditions>
            <cp:actions>
                <allow>false</allow>
            </cp:actions>
        </cp:rule>
    </cp:ruleset>

A domain (all identities at 'example.com' are matched)

This example, without any other rule, blocks any session towards any user in the 'example.com' domain.

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <cp:ruleset xmlns="http://uri.etsi.org/ngn/params/xml/simservs/xcap" xmlns:cp="urn:ietf:params:xml:ns:common-policy" xmlns:ocp="urn:oma:xml:xdm:common-policy">
        <cp:rule id="barr-domains">
            <cp:conditions>
                <cp:identity>
                    <many domain="example.com"></many>
                </cp:identity>
            </cp:conditions>
            <cp:actions>
                <allow>false</allow>
            </cp:actions>
        </cp:rule>
    </cp:ruleset>

A whole domain with an exceptional identity (all identities at 'example.com' are matched except 'sip:alice@example.com')

This example, without any other rule, blocks any session towards any user in the 'example.com' domain, except for 'sip:alice@example.com'.

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <cp:ruleset xmlns="http://uri.etsi.org/ngn/params/xml/simservs/xcap" xmlns:cp="urn:ietf:params:xml:ns:common-policy" xmlns:ocp="urn:oma:xml:xdm:common-policy">
        <cp:rule id="barr-domains-with-exceptions">
            <cp:conditions>
                <cp:identity>
                    <many domain="example.com">
                        <except id="sip:alice@example.com"/>
                    </many>
                </cp:identity>
            </cp:conditions>
            <cp:actions>
                <allow>false</allow>
            </cp:actions>
        </cp:rule>
    </cp:ruleset>

A whole domain with an exceptional domain (all identities at 'example.com' are matched except 'sip:alice@example.com')

This example, without any other rule, blocks any session towards any user in the 'example.com' domain, except for users within the domain 'callcentre.example.com'.

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <cp:ruleset xmlns="http://uri.etsi.org/ngn/params/xml/simservs/xcap" xmlns:cp="urn:ietf:params:xml:ns:common-policy" xmlns:ocp="urn:oma:xml:xdm:common-policy">
        <cp:rule id="barr-domain-except-callcentre">
            <cp:conditions>
                <cp:identity>
                    <many domain="example.com">
                        <except domain="callcentre.example.com"/>
                    </many>
                </cp:identity>
            </cp:conditions>
            <cp:actions>
                <allow>false</allow>
            </cp:actions>
        </cp:rule>
    </cp:ruleset>

| Note the attribute of the 'except' element is now 'domain'.

All identities (all identities are matched)

This example, without any other rule, blocks all sessions towards any user.

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <cp:ruleset xmlns="http://uri.etsi.org/ngn/params/xml/simservs/xcap" xmlns:cp="urn:ietf:params:xml:ns:common-policy" xmlns:ocp="urn:oma:xml:xdm:common-policy">
        <cp:rule id="barr-all">
            <cp:conditions>
                <cp:identity>
                    <many />
                </cp:identity>
            </cp:conditions>
            <cp:actions>
                <allow>false</allow>
            </cp:actions>
        </cp:rule>
    </cp:ruleset>

A more complex Identity condition expression (all identities at 'example2.com' match except for 'sip:charlie@example2.com'. Also the identities 'sip:alice@example1.com' and 'sip:bob@example1.com' match.)

This example, without any other rule, blocks any session towards any user registered in the domain 'example2.com' except for 'sip:charlie@example2.com, for 'sip:alice@example1.com' and sip:bob@example1.com.

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <cp:ruleset xmlns="http://uri.etsi.org/ngn/params/xml/simservs/xcap" xmlns:cp="urn:ietf:params:xml:ns:common-policy" xmlns:ocp="urn:oma:xml:xdm:common-policy">
        <cp:rule id="barr-some">
            <cp:conditions>
                <cp:identity>
                    <one id="sip:alice@example1.com"/>
                    <one id="sip:bob@example1.com"/>
                    <many domain="example2.com">
                        <except id="sip:charlie@example2.com"/>
                    </many>
                </cp:identity>
            </cp:conditions>
            <cp:actions>
                <allow>false</allow>
            </cp:actions>
        </cp:rule>
    </cp:ruleset>

Another more complex Identity condition expression with more than one rule.

This example, always blocks some domains, always allow other domains and a set of sip URIs.

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <cp:ruleset xmlns="http://uri.etsi.org/ngn/params/xml/simservs/xcap" xmlns:cp="urn:ietf:params:xml:ns:common-policy" xmlns:ocp="urn:oma:xml:xdm:common-policy">
        <cp:rule id="always-allow-these-domains">
            <cp:conditions>
                <cp:identity>
                    <many domain="emergency.org"></many>
                    <many domain="police.org"></many>
                </cp:identity>
            </cp:conditions>
            <cp:actions>
                <allow>true</allow>
            </cp:actions>
        </cp:rule>

        <cp:rule id="always-barr-these-domains">
            <cp:conditions>
                <cp:identity>
                    <many domain="fakelotery.org"></many>
                    <many domain="dhueb!.org"></many>
                </cp:identity>
            </cp:conditions>
            <cp:actions>
                <allow>false</allow>
            </cp:actions>
        </cp:rule>

       <cp:rule id="always-barr-these-identities">
            <cp:conditions>
                <cp:identity>
                    <one id="sip:john@example.com"/>
                    <one id="sip:marc@example.com"/>
                </cp:identity>
            </cp:conditions>
            <cp:actions>
                <allow>false</allow>
            </cp:actions>
        </cp:rule>

    </cp:ruleset>

| Depending on the value of the 'allow' element of the rule, the rule can essentially become a 'whitelist' or a 'blacklist'.

#### International

This condition evaluates to true if the session state variable `International` is true. This is set by the Determine International and Roaming Status feature.

Use this XML in the REM HSS Subscriber Data page to configure OCB for international calls:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <cp:ruleset xmlns="http://uri.etsi.org/ngn/params/xml/simservs/xcap" xmlns:cp="urn:ietf:params:xml:ns:common-policy" xmlns:ocp="urn:oma:xml:xdm:common-policy">
        <cp:rule id="international">
            <cp:conditions>
                <international/>
            </cp:conditions>
            <cp:actions>
                <allow>false</allow>
            </cp:actions>
        </cp:rule>
    </cp:ruleset>

#### International-exHC

This condition evaluates to true if the session state variable `InternationalExHC` is true. This is set by the Determine International and Roaming Status feature.

Use this XML in the REM HSS Subscriber Data page to configure OCB for international-exHC calls:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <cp:ruleset xmlns="http://uri.etsi.org/ngn/params/xml/simservs/xcap" xmlns:cp="urn:ietf:params:xml:ns:common-policy" xmlns:ocp="urn:oma:xml:xdm:common-policy">
        <cp:rule id="international-exHC">
            <cp:conditions>
                <international-exHC/>
            </cp:conditions>
            <cp:actions>
                <allow>false</allow>
            </cp:actions>
        </cp:rule>
    </cp:ruleset>

#### International when roaming

This condition evaluates to true if the session state variable `International` is true and `RoamingIndicator` is true. These are set by the Determine International and Roaming Status feature.

Use this XML in the REM HSS Subscriber Data page to configure OCB for international when roaming calls:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <cp:ruleset xmlns="http://uri.etsi.org/ngn/params/xml/simservs/xcap" xmlns:cp="urn:ietf:params:xml:ns:common-policy" xmlns:ocp="urn:oma:xml:xdm:common-policy">
        <cp:rule id="international">
            <cp:conditions>
                <roaming/>
                <international/>
            </cp:conditions>
            <cp:actions>
                <allow>false</allow>
            </cp:actions>
        </cp:rule>
    </cp:ruleset>

#### Unconditional

Use this XML in the REM HSS Subscriber Data page to configure OCB for all calls:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <cp:ruleset xmlns="http://uri.etsi.org/ngn/params/xml/simservs/xcap" xmlns:cp="urn:ietf:params:xml:ns:common-policy" xmlns:ocp="urn:oma:xml:xdm:common-policy">
        <cp:rule id="all-calls">
            <cp:conditions/>
            <cp:actions>
                <allow>false</allow>
            </cp:actions>
        </cp:rule>
    </cp:ruleset>

#### Validity

This condition evaluates to true if the current time is within the times specified by the validity period.

Time is based on the Home Network time (that is, the time of the MMTel Server).

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <cp:ruleset xmlns="http://uri.etsi.org/ngn/params/xml/simservs/xcap" xmlns:cp="urn:ietf:params:xml:ns:common-policy" xmlns:ocp="urn:oma:xml:xdm:common-policy">
        <cp:rule id="all-calls">
            <cp:conditions>
                <cp:validity>
                    <cp:from>1970-01-01T00:00:00</cp:from>
                    <cp:until>1970-01-01T00:00:00</cp:until>
                </cp:validity>
            </cp:conditions>
        </cp:rule>
    </cp:ruleset>

#### Rule deactivated

This condition always evaluates to false. Used to disable a rule without removing the rule entirely. The rule is re-enabled by removing this condition.

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <cp:ruleset xmlns="http://uri.etsi.org/ngn/params/xml/simservs/xcap" xmlns:cp="urn:ietf:params:xml:ns:common-policy" xmlns:ocp="urn:oma:xml:xdm:common-policy">
        <cp:rule id="all-calls">
            <cp:conditions>
                <rule-deactivated/>
                <cp:validity>
                    <cp:from>1970-01-01T00:00:00</cp:from>
                    <cp:until>1970-01-01T00:00:00</cp:until>
                </cp:validity>
            </cp:conditions>
        </cp:rule>
    </cp:ruleset>

##### Barring rule actions

Barring rule actions are a string. There could be many actions defined, but the only one that makes any sense is the `allow` action.

The `allow` action has a Boolean attribute, with meaning as follows:

- `true`— allow session setup to proceed

- `false`— deny session setup from proceeding.

Any other rule action (that is, an action that is not set to `allow`) will result in us treating the action as the following:

- allow rule action with value of `true`.

### Behaviour

#### Initial Checks

When triggered the feature first undergoes a series of checks to ensure that the conditions for the feature to run are met. The feature enforces the following conditions:

- The call-type is `Originating` or `Forwarded`.

- OCB service data for the subscriber has been successfully loaded and the `OperatorAuthorized` flag in the data is set to `true`.

- Network operator configuration for the feature is present and has been successfully loaded.

- The invoking trigger for the feature is an inbound SIP `INVITE` or `REFER` request.

If any of those conditions are not met, the feature will terminate immediately and the OCB service will not run.

#### Barring Rule Evaluation

If all checks passed, then the feature will move on to carry out barring rule evaluation. This occurs in three phases, one for each type of rule:

1. All operator specific type rules are evaluated. If any of them apply (be they a barring, retarget or explicit allow action), then the feature will execute the appropriate action and then skip the following phases. Prefix barring interacts with this step as described in Prefix Based Barring Behaviour

2. The remaining ODB rules are evaluated, again if any of the rules apply, their action will be executed and the final evaluation phase skipped.

3. Prefix based premium-rate communication barring options are evaluated as described in Prefix Based Barring Behaviour

4. Standard OCB rules will be evaluated and the appropriate action applied if one is matched. This final phase will be skipped if the MMTel OCB `Active` flag is set to false in the service data.

When deciding whether a rule should be applied, the feature will check the set of conditions provided by the rule. The feature will apply the rule if any of the following statements are true:

- The rule has no set of conditions, i.e. the `<conditions>` element is absent in the rule definition.

- The set of conditions for the rule is empty.

- All of the conditions within the set defined in the rule are met.

If none of those statements are true for any rule, the feature will complete execution and the call will be allowed to continue.

##### Rule Format

Each rule is expressed as an XCAP `cp:rule` XML fragment, for example:

    <cp:rule id="rule66">
        <cp:conditions>
            <roaming/>
            <media>video</media>
        </cp:conditions>
        <cp:actions>
            <allow>false</allow>
        </cp:actions>
     </cp:rule>

When the `allow` element is not found, the feature assumes `allow` is `false`.

#### Rule Actions

When a rule is applied, there are three possible actions the feature may have to carry out:

1. Whitelisting (i.e. call is explicitly allowed to continue)

2. Call barring

3. Retargeting (only available with operator specified ODB rules)

##### Whitelisting

If the action of an applicable rule indicates the call should be allowed, then the feature immediately stops evaluating other rules and allows the call to proceed.

##### Call Barring

If the action of an applicable rule indicates that the call should be barred, the feature won’t act immediately. It will first evaluate the other rules of the same type to ensure that none of them indicate that the call should be whitelisted. If the call is not whitelisted by another rule, then the feature will execute the call barring procedure as follows:

1. Set the `OCBBarred` session state flag to `true` to limit which features will run after `MMTelOCB`.

2. Increment appropriate stats to indicate the call was barred.

3. Check whether the method for the incoming message is `INVITE` or `REFER`, and execute the appropriate procedure as described below.

`INVITE` barring procedure:

1. Check the feature configuration to determine if an announcement needs to played.

2. Depending on the outcome:

   1. If an announcement does not need to be played, instruct sentinel to immediately terminate the call with a `603 Decline` response for the `INVITE` request.

   2. If an announcement is to be played:

      1. Suppress online charging for the call (if applicable).

      2. Queue an announcement for the SipPlayAnnouncement feature, using the announcement ID provided in the feature configuration.

      3. Set the `EndSessionAfterAnnouncement` session state field to indicate to the `SipPlayAnnouncement` that it should terminate the session with a `603 Decline` response for the original `INVITE` request after the announcement has been played.

`REFER` barring procedure:

1. Send a SIP `403 Forbidden` response for the `REFER` request.

2. Search for the outbound `REFER` on the outbound leg’s message queue, and then remove it.

##### Retargeting

Only operator-specific ODB rules can be used to retarget a call. In the rule XML, the action is still listed with `allow` being `false` (i.e. bar the call), but additional configuration on the `MMTelOdbOperatorSpecificTypeRuleProfileTable` is used to transform the rule action into a retarget. If there are multiple applicable operator-specific ODB rules for a call, and they retarget to different destinations, or one retargets and another bars the call, then the rule with the lowest `Type` number will take precedence (e.g. the `Type2` rule will take precedence over the `Type3` rule). However, as always, an operator-specific ODB rule that explicitly whitelists the call will take precedence regardless of its number.

When it is determined that a call should be retargeted, the procedure is as follows:

1. Retrieve the new target URI from the rule’s configuration profile on the `MMTelOdbOperatorSpecificTypeRuleProfileTable`.

2. Release the original outbound leg towards the called party (at this point no signalling should have occurred on this leg, so no message is sent to do this).

3. Generate a new outbound `INVITE` request from the original inbound request.

4. Update the newly created request to retarget it, the procedure for doing this is similar to the one used by unconditional forwarding (CFU) in the MMTelCDIV feature:

   1. The `Request-URI` is set to the value of the new target URI and a `cause=302` parameter is added.

   2. The `To` header is set to the value of the new target URI.

   3. The `History-Info` header is modified/added to indicate a diversion has occurred, the original target URI is given the 'privacy=history' parameter.

5. Create a new outbound leg (named `MMTelOCBRetargetedLeg`) to send the new `INVITE` request, and link this leg to the calling party leg.

6. If the rule’s configuration profile indicates that the redirected call should not be subject to online charging, then suppress online charging for the call.

7. If the rule’s configuration profile indicates that a retarget announcement should be played, then queue an announcement with the announcement ID provided in the rule’s configuration (note that the standard barring announcement as configured on the `MMTelOCBConfigProfileTable` will not be played on a retarget action).

If at any point in the procedure there is a problem that prevents retargeting from working, then the feature will fall back to standard call barring behaviour (including playing the standard barring announcement if applicable).

##### Rule Priority

The behavior described above gives rise to a natural priority that rules will follow when multiple rules with different actions are applicable to a call.

To summarise:

- There are different types of rules: Prefix based `OperatorAllow` , Prefix based `OperatorBar`, Operator-specific ODB rules, Prefix based premium-rate communication barring, standard ODB rules, and OCB rules.

- The overall priority is

  - Prefix based `OperatorAllow`

  - Operator-specific ODB rules that whitelist a call, regardless whether applied by matching their defined condition, or by prefix based treatment

  - Prefix based `OperatorBar`

  - Operator-specific ODB rules that bar a call, regardless whether applied by matching their defined condition, or by prefix based treatment

  - Prefix based premium-rate communication barring

  - Standard ODB rules

  - OCB rules

- Within rules of the same type, a whitelisting action will always take precedence over a barring or retargeting action.

- If multiple operator-specific ODB rules apply and have conflicting retarget or barring actions, then the rule with the lower number will take precedence. (there are four slots available for operator-specific ODB rules, numbered one through four).

#### Roaming and International Determination

The MMTelOCB feature does not compute whether or not the served user is roaming or international; rather it relies on a session input fields (`RoamingIndicator`, `International`, and `InternationalExHC`). These fields are set by the DetermineInternationalAndRoamingStatus feature. For this reason the `DetermineInternationalAndRoamingStatus` feature must run before `MMTelOCB` in the feature execution scripts if international and roaming status need to be considered.

#### Playing Announcements

The MMTelOCB feature does not play announcements itself; rather it relies on setting data in session output fields (`EarlyMediaAnnouncementInfoQueue` and `EndSessionAfterAnnouncement`) if an announcement is to be played. These fields are read by the SipPlayAnnouncement feature.

Based on the the data in the fields that feature will:

- Handle the signalling required to play the announcement to the calling party.

- Terminate the call after the announcement if instructed to do so.

For this reason the `SipPlayAnnouncement` feature must run after `MMTelOCB` in the feature execution scripts if announcements are required.

## Operator Determined Barring

Operator Determined Barring provides call barring rules determined by the operator that take precedence over MMTelICB and MMTelOCB .

### What is ODB?

Operator determined barring is specified for IMS in the 3GPP specifications TS 24.315 and TS 22.041:

from TS 24.315

| The network feature Operator Determined Barring (ODB) allows a network operator or service provider to regulate access to IMS subsystem services, by the barring of certain categories of incoming or outgoing communications, the barring of certain categories of roaming and the barring of certain categories of supplementary services configuration and invocation.

The Sentinel VoLTE TAS provides an extension to standard ODB that allows the operator to retarget outbound calls to an arbitrary destination. See How to provision the Operator Specific Barring rules for details of how to enable this functionality, and MMTelOCB Behaviour for details of how it is executed.

### ODB Data

The ODB data is stored as transparent data in the HSS. The SubscriberDataLookupFromHSS feature is responsible to retrieve the ODB data from the HSS. The SubscriberDataLookupFromHSS Configuration should contain the service indication as `IMS-ODB-Information` and the proper `codec`. The SubscriberDataLookupFromHSS queries the HSS and if the operator had configured any ODB rules for that subscriber then user data will be returned, parsed and then stored in a session state field `MMTelODBServiceData`. The MMTelICB and MMTelOCB will use the session state field `MMTelODBServiceData` to evaluate the ODB conditions before the subscriber defined conditions.

### Enabling ODB

ODB can be enabled using the DisableQuery option in the SubscriberDataLookupFromHSS. The sdk installer provides an option for setting `DisableQuery` on IMS and `DisableQuery` on MMTel.

### Supported Barring Rule Conditions

The sections below show XML data stored in the HSS for the supported conditions. The outgoing conditions are evaluated by the MMTelOCB feature, the incoming conditions are evaluated by MMTelICB and the operator type conditions are evaluated by both features.

### Enabling ODB

The HSS `IMS-ODB-Information` query can be enabled using the `DisableQuery` option in the SubscriberDataLookupFromHSS.

#### Bar all outgoing communications

Bar all of the outgoing communications, The OutgoingBarring tag is set to "0".

    <?xml version="1.0" encoding="utf-8"?>
    <Sh-Data>
        <RepositoryData>
            <ServiceIndication>IMS-ODB-Information</ServiceIndication>
            <SequenceNumber>1</SequenceNumber>
            <ServiceData>
             <OdbForImsOrientedServices xmlns="odb.mmtel.sentinel.volte.opencloud.com">
              <OdbForImsMultimediaTelephonyServices>
                <OutgoingBarring>0</OutgoingBarring>
              </OdbForImsMultimediaTelephonyServices>
             </OdbForImsOrientedServices>
            </ServiceData>
        </RepositoryData>
    </Sh-Data>

#### Bar all outgoing international communications

Barring of all outgoing communications to international destinations. The OutgoingBarring tag is set to "1".

    <?xml version="1.0" encoding="utf-8"?>
    <Sh-Data>
        <RepositoryData>
            <ServiceIndication>IMS-ODB-Information</ServiceIndication>
            <SequenceNumber>1</SequenceNumber>
            <ServiceData>
             <OdbForImsOrientedServices xmlns="odb.mmtel.sentinel.volte.opencloud.com">
              <OdbForImsMultimediaTelephonyServices>
                <OutgoingBarring>1</OutgoingBarring>
              </OdbForImsMultimediaTelephonyServices>
             </OdbForImsOrientedServices>
            </ServiceData>
        </RepositoryData>
    </Sh-Data>

#### Bar all outgoing communications when international ex-hplmnc

Barring of all outgoing communications to international destinations excluding home network. The OutgoingBarring tag is set to "2".

    <?xml version="1.0" encoding="utf-8"?>
    <Sh-Data>
        <RepositoryData>
            <ServiceIndication>IMS-ODB-Information</ServiceIndication>
            <SequenceNumber>1</SequenceNumber>
            <ServiceData>
             <OdbForImsOrientedServices xmlns="odb.mmtel.sentinel.volte.opencloud.com">
               <OdbForImsMultimediaTelephonyServices>
                <OutgoingBarring>2</OutgoingBarring>
               </OdbForImsMultimediaTelephonyServices>
             </OdbForImsOrientedServices>
            </ServiceData>
        </RepositoryData>
    </Sh-Data>

#### Bar all outgoing communications when roaming

Barring of all outgoing communications roaming outside the home PLMN country. The OutgoingBarring tag is set to "3".

    <?xml version="1.0" encoding="utf-8"?>
    <Sh-Data>
        <RepositoryData>
            <ServiceIndication>IMS-ODB-Information</ServiceIndication>
            <SequenceNumber>1</SequenceNumber>
            <ServiceData>
             <OdbForImsOrientedServices xmlns="odb.mmtel.sentinel.volte.opencloud.com">
              <OdbForImsMultimediaTelephonyServices>
                <OutgoingBarring>3</OutgoingBarring>
              </OdbForImsMultimediaTelephonyServices>
             </OdbForImsOrientedServices>
            </ServiceData>
        </RepositoryData>
    </Sh-Data>

#### Bar all incoming international communications

Barring of all international communications, the IncomingBarring tag is set to "0".

    <?xml version="1.0" encoding="utf-8"?>
    <Sh-Data>
        <RepositoryData>
            <ServiceIndication>IMS-ODB-Information</ServiceIndication>
            <SequenceNumber>1</SequenceNumber>
            <ServiceData>
             <OdbForImsOrientedServices xmlns="odb.mmtel.sentinel.volte.opencloud.com">
              <OdbForImsMultimediaTelephonyServices>
               <IncomingBarring>0</IncomingBarring>
              </OdbForImsMultimediaTelephonyServices>
             </OdbForImsOrientedServices>
            </ServiceData>
        </RepositoryData>
    </Sh-Data>

#### Bar all incoming communications when roaming

Barring of all incoming communications when roaming outside the home PLMN country. The IncomingBarring tag is set to "1".

    <?xml version="1.0" encoding="utf-8"?>
    <Sh-Data>
        <RepositoryData>
            <ServiceIndication>IMS-ODB-Information</ServiceIndication>
            <SequenceNumber>1</SequenceNumber>
            <ServiceData>
             <OdbForImsOrientedServices xmlns="odb.mmtel.sentinel.volte.opencloud.com">
              <OdbForImsMultimediaTelephonyServices>
               <IncomingBarring>1</IncomingBarring>
              </OdbForImsMultimediaTelephonyServices>
             </OdbForImsOrientedServices>
            </ServiceData>
        </RepositoryData>
    </Sh-Data>

#### Bar Outgoing Premium-Rate Communication

The premium-rate barring options can be described as follows:

Option | Description
--- | ---
PremiumRateCommunicationsInformation | Bar all outgoing communications where the request URI has a "premium-rate" parameter with the value "information".
PremiumRateCommunicationsEntertainment | Bar all outgoing communications where the request URI has a "premium-rate" parameter with the value "entertainment".
PremiumRateCallsInformationWhenRoamingOutsideHplmnCountry | The same as 'PremiumRateCommunicationsInformation' but only for communications that are roaming outside of the Home PLMN Country.
PremiumRateCallsEntertainmentWhenRoamingOutsideHplmnCountry | The same as 'PremiumRateCommunicationsEntertainment' but only for communications that are roaming outside of the Home PLMN Country.

Certain prefix-based Barring Treatments will also affect the matching of these premium-rate barring options.

The information on ODB data in the HSS indicates which options should be evaluated.

Example XML:

    <?xml version="1.0" encoding="utf-8"?>
    <Sh-Data>
        <RepositoryData>
            <ServiceIndication>IMS-ODB-Information</ServiceIndication>
            <SequenceNumber>1</SequenceNumber>
            <ServiceData>
             <OdbForImsOrientedServices xmlns="odb.mmtel.sentinel.volte.opencloud.com">
              <OdbForImsMultimediaTelephonyServices>
               <OutgoingPremiumRateBarring>
                   <PremiumRateCommunicationsInformation>
                        true
                   </PremiumRateCommunicationsInformation>
                   <PremiumRateCommunicationsEntertainment>
                        true
                   </PremiumRateCommunicationsEntertainment>
                   <PremiumRateCallsInformationWhenRoamingOutsideHplmnCountry>
                        true
                   </PremiumRateCallsInformationWhenRoamingOutsideHplmnCountry>
                   <PremiumRateCallsEntertainmentWhenRoamingOutsideHplmnCountry>
                        true
                   </PremiumRateCallsEntertainmentWhenRoamingOutsideHplmnCountry>
               </OutgoingPremiumRateBarring>
              </OdbForImsMultimediaTelephonyServices>
             </OdbForImsOrientedServices>
            </ServiceData>
        </RepositoryData>
    </Sh-Data>

#### Operator Specific Barring Rules

The Operator Specific Barring Types conditions specifies 4 types of user defined rules. The rules are stored in the VoLTE profiles and follow the same schema for Simservs RuleSet. The information on ODB data in the HSS just indicates which rule types should be evaluated.

The example below indicated that all 4 rules should be evaluated.

    <?xml version="1.0" encoding="utf-8"?>
    <Sh-Data>
        <RepositoryData>
            <ServiceIndication>IMS-ODB-Information</ServiceIndication>
            <SequenceNumber>1</SequenceNumber>
            <ServiceData>
             <OdbForImsOrientedServices xmlns="odb.mmtel.sentinel.volte.opencloud.com">
              <OdbForImsMultimediaTelephonyServices>
               <OperatorSpecificBarring>
    	      <Type1>true</Type1>
    	      <Type2>true</Type2>
    	      <Type3>true</Type3>
    	      <Type4>true</Type4>
        	  </OperatorSpecificBarring>
              </OdbForImsMultimediaTelephonyServices>
             </OdbForImsOrientedServices>
            </ServiceData>
        </RepositoryData>
    </Sh-Data>

#### Bar Invocation of communication transfer

This condition prevents the Explicit Call Transfer feature MMTelECT from running. The conditions are:

Condition | Description
--- | ---
SimpleInvocationOfCommunicationTransferBarring | Prevents user-invoked call transfers from happening. Has three options: Barring of Invocation of Communication Transfer (0) Barring of Invocation of Communication Transfer Where at least one leg is charged (1) Not Supported Barring of Invocation of Communication Transfer Where at least one leg is charged at international rates (2) Not Supported
InvocationOfChargeableCommunicationTransferBarring | Prevents user-invoked call transfers when both calls are charged to the served user. Not Supported
MultipleInvocationOfCommunicationTransferBarring | Prevents a user-invoked call transfer when there is an existing transferred call for the served user.

    <?xml version="1.0" encoding="utf-8"?>
    <Sh-Data>
        <RepositoryData>
            <ServiceIndication>IMS-ODB-Information</ServiceIndication>
            <SequenceNumber>1</SequenceNumber>
            <ServiceData>
             <OdbForImsOrientedServices xmlns="odb.mmtel.sentinel.volte.opencloud.com">
              <OdbForImsMultimediaTelephonyServices>
                <SimpleInvocationOfCommunicationTransferBarring>
                   0
                </SimpleInvocationOfCommunicationTransferBarring>

        	    <InvocationOfChargeableCommunicationTransferBarring>
                   true
                </InvocationOfChargeableCommunicationTransferBarring>

       	    <MultipleInvocationOfCommunicationTransferBarring>
                   true
                </MultipleInvocationOfCommunicationTransferBarring>

              </OdbForImsMultimediaTelephonyServices>
             </OdbForImsOrientedServices>
            </ServiceData>
        </RepositoryData>
    </Sh-Data>

#### Bar Management of Supplementary Services

This condition is evaluated during provisioning time when the subscriber tries to change its own supplementary services configuration via XCAP Interface. If the condition is set to true the XCAP servers will deny any change to subscriber change attempt.

    <?xml version="1.0" encoding="utf-8"?>
    <Sh-Data>
        <RepositoryData>
            <ServiceIndication>IMS-ODB-Information</ServiceIndication>
            <SequenceNumber>1</SequenceNumber>
            <ServiceData>
             <OdbForImsOrientedServices xmlns="odb.mmtel.sentinel.volte.opencloud.com">
              <OdbForImsMultimediaTelephonyServices>
                <BarringOfSupplementaryServicesManagement>
                   true
                </BarringOfSupplementaryServicesManagement>
              </OdbForImsMultimediaTelephonyServices>
             </OdbForImsOrientedServices>
            </ServiceData>
        </RepositoryData>
    </Sh-Data>

#### Bar Registration of Diverted To Address

This condition is evaluated during provisioning time when the subscriber tries to change the target to address of the supplementary services via XCAP Interface. Currently the diverted to address is present at the Communication Diversion (CDIV) settings. It is the `<target>` sub-element of the `<forward-to>` element in a CDIV rule’s actions.

The bar condition can have the following values:

- 0 Barring of Registration of any communication diverted-to address

  - currently supported

- 1 Barring of Registration of any international communication diverted-to address

  - not supported yet

- 2 Barring of Registration of any international communication diverted-to address EXHPLMNC

  - not supported yet

    <?xml version="1.0" encoding="utf-8"?>
    <Sh-Data>
        <RepositoryData>
            <ServiceIndication>IMS-ODB-Information</ServiceIndication>
            <SequenceNumber>1</SequenceNumber>
            <ServiceData>
             <OdbForImsOrientedServices xmlns="odb.mmtel.sentinel.volte.opencloud.com">
              <OdbForImsMultimediaTelephonyServices>
                <DivertedToAddressRegistrationBarring>
                   0
                </DivertedToAddressRegistrationBarring>
              </OdbForImsMultimediaTelephonyServices>
             </OdbForImsOrientedServices>
            </ServiceData>
        </RepositoryData>
    </Sh-Data>

## Operator Specific Barring Types

The Operator Specific Barring Types are 4 operator defined rules that are stored in the AS. The ODB data indicates which of them should be evaluated and, like all others ODB conditions, they take precedence over MMTelICB and MMTelOCB .

### What is Operator Specific Barring?

The 3GPP specifications TS 24.315 defines:

| The Operator specific barring definition for type 1, type 2, type 3, and type 4 is locally configured in the AS providing the ODB service. For operator specific barring the criteria that can be used by the operator to define conditions that are used to determine whether the category applies may be based on any signalling information from the incoming request. Examples of such criteria are: 1) destination type e.g. international numbers or specific numbers; 2) media used in the communication, e.g. audio, video, or text.

The scope definition of what kind of conditions can be present in those rules is not specified. The OpenCloud implementation of those rules follows the simservs RuleSet definition (TS 29.364 ) for MMTelICB Supported Barring Rule Conditions and MMTelOCB Supported Barring Rule Conditions. This way the operator can define the same MMTel barring conditions supported by the MMTelOCB and MMTelICB features.

The Sentinel VoLTE TAS provides an extension to standard Operator Specific Barring that allows the operator to retarget outbound calls to an arbitrary destination. See How to provision the Operator Specific Barring rules for details of how to enable this functionality, and MMTelOCB Behaviour for details of how it is executed.

### ODB-Specific Conditions

There are conditions that are unique to ODB. These are:

#### Incoming Communications

To make a rule match on any communications that are 'incoming', add the `<incoming />` element to its set of conditions.

Example:

    <cp:ruleset xmlns="http://uri.etsi.org/ngn/params/xml/simservs/xcap" xmlns:cp="urn:ietf:params:xml:ns:common-policy">
        <cp:rule id="barr-alice-incoming">
            <cp:conditions>
                <incoming />
                <cp:identity>
                    <one id="sip:alice@example.com"/>
                </cp:identity>
            </cp:conditions>
            <cp:actions>
                <allow>false</allow>
            </cp:actions>
        </cp:rule>
    </cp:ruleset>

#### Outgoing Communications

To make a rule match on any communications that are 'outgoing', add the `<outgoing />` element to its set of conditions.

Example:

    <cp:ruleset xmlns="http://uri.etsi.org/ngn/params/xml/simservs/xcap" xmlns:cp="urn:ietf:params:xml:ns:common-policy">
        <cp:rule id="barr-alice-outgoing">
            <cp:conditions>
                <outgoing />
                <cp:identity>
                    <one id="sip:alice@example.com"/>
                </cp:identity>
            </cp:conditions>
            <cp:actions>
                <allow>false</allow>
            </cp:actions>
        </cp:rule>
    </cp:ruleset>

### How to Provision the Operator Specific Barring Rules

Definitions for each of the four allowed operator specific barring rules are provided on the `MMTelOdbOperatorSpecificTypeRuleProfileTable`. Each profile on the table corresponds to one of the four types. Profiles are named with the format: `{sentinel-selection-key}:{rule-type}`, for example:

    Metaswitch:Metaswitch::::Type1

Each profile has the following fields:

Name | Type | Default Value | Description
--- | --- | --- | ---
    OperatorSpecificType
| String (Enum) |
    null
| Identifies the type of the rule, should match the profile name, must be equal to one of: `Type1`, `Type2`, `Type3`, or `Type4`.
    Rule
| String |
    null
| The `cp:ruleset` XML for the entire OSB rule.
    Retarget
| boolean |
    false
| A flag to indicate whether this rule should retarget the call when the result of evaluating the `cp:ruleset` indicates the call should be barred.
    RetargetURI
| String |
    null
| The new target URI that should be used when retargeting a call. If the `Retarget` flag is `true`, this field must contain a valid `sip:` or `tel:` URI.
    PlayRetargetAnnouncement
| boolean |
    false
| A flag that indicates whether an announcement should be played if this rule triggers retargeting. This only applies if the `Retarget` flag is `true`.
    RetargetAnnouncementID
| int |
    0
| The ID of the announcement that should be played if the retarget announcement is triggered. If this is `0` no announcement will be played.
    DisableOnlineChargingOnRetarget
| boolean |
    false
| A flag that indicates whether online charging should be suppressed if this rule retargets the call.

Note that redirection behaviour only applies to outbound calls on an originating or forwarded TAS instance. When applied to inbound calls on a terminating TAS instance, Operator Specific Barring rules will execute standard barring behavior regardless of any retarget configuration on this profile table.

### Examples

The sections below show XML data stored in the `Rule` field of each profile on the `MMTelOdbOperatorSpecificTypeRuleConfigProfileTable`. The values can be applied for type 1 to type 4. The fact that the `<incoming\>` and `<outgoing\>` are not present, means that those rules will be applied to both directions.

#### Bar Video

    <cp:ruleset xmlns="http://uri.etsi.org/ngn/params/xml/simservs/xcap" xmlns:cp="urn:ietf:params:xml:ns:common-policy">
        <cp:rule id="no_video">
            <cp:conditions>
                <media>video</media>
            </cp:conditions>
            <cp:actions>
                <allow>false</allow>
            </cp:actions>
        </cp:rule>
    </cp:ruleset>

#### Bar Identity

    <cp:ruleset xmlns="http://uri.etsi.org/ngn/params/xml/simservs/xcap" xmlns:cp="urn:ietf:params:xml:ns:common-policy">
        <cp:rule id="barr-alice">
            <cp:conditions>
                <cp:identity>
                    <one id="sip:alice@example.com"/>
                </cp:identity>
            </cp:conditions>
            <cp:actions>
                <allow>false</allow>
            </cp:actions>
        </cp:rule>
    </cp:ruleset>

#### Bar Specific Domain for a One Month Period

    <cp:ruleset xmlns="http://uri.etsi.org/ngn/params/xml/simservs/xcap" xmlns:cp="urn:ietf:params:xml:ns:common-policy">
        <cp:rule id="barr-domain">
            <cp:conditions>
                <cp:identity>
                    <many domain="example.com"></many>
                </cp:identity>
                <cp:validity>
                    <cp:from>2016-01-01T00:00:00</cp:from>
                    <cp:until>2016-01-31T23:59:59</cp:until>
                </cp:validity>
            </cp:conditions>
            <cp:actions>
                <allow>false</allow>
            </cp:actions>
        </cp:rule>
    </cp:ruleset>

## Prefix Based Barring

Prefix Based Barring provides a mechanism for an operator to augment the implicit or explicit condition of a MMTelOCB barring rule, so that the rule will also apply when the called party number matches some prefix with optional length criteria .

### What is Prefix Based Barring

Prefix Based Barring is an enhancement to Outgoing Call Barring, to trigger certain barring treatments based on the dialled number.

### How to Configure Prefix Based Barring

#### ${platform.operator.name}_PrefixBarring_AddressListEntryTable

An address list called `${platform.operator.name}_PrefixBarring_AddressListEntryTable` is used to classify the called number for prefix based barring.

It is an extension of the standard Address List Entry Profile and has the same structure with the following additional field.

Parameter | Type | Description
--- | --- | ---
…​ | …​ | …​
NumberClassification | String[] | A list of 1 or more items where each is the name of a `PrefixBarringClassificationsTable` profile. REM provides a list from which elements of the array may be selected.

#### PrefixBarringClassificationsTable

The prefix barring address list references a classification for the matching prefixes.

Details of how that classification is treated are stored in `PrefixBarringClassificationsTable` profile table.

Attribute Name | Type | Default | Description
--- | --- | --- | ---
    ClassificationID
| String | n/a | The identifier of this classification, and the name of this profile.
    DisplayName
| String | n/a | User readable name for the classification that will be used to select it in the address list.
    MatchMinLength
| Integer | no minimum length criteria | The minimum number of digits in dial string to match this classification.
    MatchMaxLength
| Integer | no maximum length criteria | The maximum number of digits in dial string to match this classification.
    MatchInternational
| boolean | false | When true, this classification will only match international targets.
    BarringTreatment
| String | n/a | How to treat matching calls. See below.
    OverrideOCBAnnouncement
| boolean | n/a | When set to true `AnnouncementID` will override the generic outbound call barring announcement configuration if its `PlayAnnouncement` value is `true`.
    AnnouncementID
| int | n/a | An announcement to be played when a matching number is called and barred and `OverrideOCBAnnouncement` is set and the generic outbound call barring announcement configuration’s `PlayAnnouncement` value is `true`. Set to 0 to play no announcement.

#### Barring Treatments

BarringTreatment | Description
--- | ---
OperatorAllow | The call will not be barred.
OperatorBar | The call will be barred if no OSB rules or `OperatorAllow` treatment allows it.
OSBType1 | Operator Specific barring rules will be processed as though the `<conditions>` for `Type1` barring evaluated to `true`.
OSBType2 | Operator Specific barring rules will be processed as though the `<conditions>` for `Type2` barring evaluated to `true`.
OSBType3 | Operator Specific barring rules will be processed as though the `<conditions>` for `Type3` barring evaluated to `true`.
OSBType4 | Operator Specific barring rules will be processed as though the `<conditions>` for `Type4` barring evaluated to `true`.
PremiumRateInformation | Premium-rate communication barring options will be processed as though the call was classified with `premium-rate` set to `information`.
PremiumRateEntertainment | Premium-rate communication barring options will be processed as though the call was classified with `premium-rate` set to `entertainment`.

#### Configuring an OSB rule to only be triggered by a prefix

| If an OSB rule is being configured solely to be triggered by prefix barring then use `<rule-deactivated/>` as the rule’s condition so that it is not inadvertently triggered otherwise.

### Behaviour

Before other OCB rules are applied, the feature extracts the target from the Request URI. The target consists of the dialled digit string, and any international number indicator. If no digits can be found ODB and OCB proceed as normal.

The target will have had normalisation applied.

If the target is international but within the home country code, the home country code prefix is stripped from the digits, and the target is treated as national.

The feature attempts longest prefix matching of the target’s digits in the address list. If no address list entry is found ODB and OCB proceed as normal.

If an address list entry is found the `NumberClassification` values are used to retrieve corresponding profiles from the `PrefixBarringClassificationsTable`.

For each of these classification profiles in specified order:

- If the national/international indicator of the target conflicts with the classification’s `MatchInternational` value, that profile is discarded.

- If the number of digits in the target conflicts with the `MatchMinLength` or `MatchMaxLength` values in the profile, that profile is discarded.

If there are no remaining profiles ODB and OCB proceed as normal.

If more than one remaining profile has the same `BarringTreatment` value, the stats counter `FoundConflictingPrefixBarringClassifications` is incremented and all except the first of those profiles are discarded. This avoids having more than one applicable announcement configuration for an applied rule.

If one of the remaining profiles has a treatment of `OperatorAllow`, the call is allowed and the OCB feature completes.

Operator-specific ODB rules are applied, except the condition of each rule is assumed true if any of the remaining profiles has a `BarringTreatment` value corresponding to the OSB rule type. If any of the remaining profiles has a treatment of `OperatorBar` that takes precedence over any Operator-specific ODB rules that bar, but not those that whitelist. The classification with `OperatorBar` treatment may override the announcement settings.

If an OSB rule bars the call due to a prefix barring treatment, and does not retarget it, then the profile may override the announcement settings.

Premium-rate communication barring options are then evaluated against `PremiumRateInformation` and/or `PremiumRateEntertainment` `BarringTreatment` values. If the call is barred due to any of these, then the profile may override the announcement settings.

See Bar Outgoing Premium-Rate Communication for more information on premium-rate communication barring.

If the call has not been barred or allowed, ODB and OCB proceed as normal.

## Determine Shared And Undisclosed Identities

This feature uses information from a SIP `INVITE` and session state to determine if the call includes shared or undisclosed identity information associated with a companion device. The feature is run in both originating and terminating session execution plans.

### Feature cheat sheet

B2BUA Instance | SAS Support | Originating / Terminating | Point in Session Plan | Network Operator Data | Subscriber Data | Stateful or Stateless | POJO Feature or SBB Feature
--- | --- | --- | --- | --- | --- | --- | ---
MMTEL | Yes | Originating and Terminating | `MMTelOrig_SipAccess_SubscriberCheck`, `MMTelTerm_SipAccess_SubscriberCheck` | Yes | Yes | Stateless | POJO

### Prerequisite features

These features must run before DetermineSharedUndisclosedIdentities:

- SubscriberDataLookupFromHlr/SubscriberDataLookupFromHss

### Session input variables

Session State variable name | Variable type
--- | ---
    SentinelSelectionKey
| SentinelSelectionKey
    MetaswitchCompanionDevice
| CompanionDeviceData
    Subscriber
| String

### Session output variables

Session State variable name | Variable type | Comments
--- | --- | ---
    SharedIdentitySip
| String | SIP shared identity used by the companion device.
    SharedIdentityTel
| String | TEL shared identity used by the companion device.
    UndisclosedIdentity
| String | The undisclosed identity of the companion device.
    HideUndisclosedIdentities
| Boolean | Set to true if call is to the undisclosed identity of the companion device. Used by the HideUndisclosedIdentity feature.
    BarIncomingCall
| Boolean | Set to true if the call is made to undisclosed identity and configuration is set to bar.

### Network operator data

This feature reads `HideUndisclosedIdentities` in the feature configuration profile table `HideUndisclosedIdentityConfigProfileTable` to determine if the feature should execute.

Parameter | Type | Description | Default
--- | --- | --- | ---
    HideUndisclosedIdentities
| Boolean | Determines if calls to Undisclosed Identities should be hidden. | true

### Statistics

DetermineSharedUndisclosedIdentities statistics are tracked by the sentinel.volte.sip SBB and can be found under the following parameter set in REM:
SLEE-Usage → sentinel.volte.sip service → sentinel.volte.sip SBB → feature → DetermineSharedUndisclosedIdentities
or with rhino-stats:
"SLEE-Usage.Services.ServiceID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].SbbID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].feature.DetermineSharedUndisclosedIdentities"

Name | Type | Description
--- | --- | ---
    Started
| Counter | Incremented each time the feature runs
    FailedToStart
| Counter | Incremented when a fatal error occurs before feature execution
    IssuedWarning
| Counter | Incremented when a non-fatal error occurs during feature execution
    FailedDuringExecution
| Counter | Incremented when a fatal error occurs during feature execution
    TimedOut
| Counter | Incremented when feature execution does not complete within a reasonable time frame
    UnableToDetermineUndisclosedIdentity
| Counter | Incremented when the feature fails to find the subscriber id, sharedIdentitySip, and sharedIdentityTel when determining if undisclosed and shared identity logic should be applied.
    SubscriberIsUndisclosedIdentity
| Counter | Incremented if the subscriber is a companion device undisclosed identity.
    SubscriberIsSharedIdentity
| Counter | Incremented if the subscriber is a companion device shared identity.
    HideUndisclosedIdentities
| Counter | Incremented if the subscriber is undisclosed and the call will be barred.

### Behaviour

The feature checks session state, feature configuration, and the incoming SIP request in order to set session state fields, which are subsequently used by downstream features associated with companion calls.

- If triggered in the originating execution plan the feature sets session state fields to hide the companion device number from the callee.

- If triggered in the terminating execution plan, when the call is made to an undisclosed identity, then the feature sets the `BarIncomingCall` session state field. This is used by the General Barring feature to bar the incoming call.

#### Values examined

Value Name | Source | Notes
--- | --- | ---
    MetaswitchCompanionDevice
| Session State | Store information used to determine if the call is from or to a companion device.
    SharedIdentitySip
| Session State | Set by the DetermineSharedUndisclosedIdentities feature which is used by the HideUndisclosedIdentity feature.
    SharedIdentityTel
| Session State | Set by the DetermineSharedUndisclosedIdentities feature which is used by the HideUndisclosedIdentity feature.
    UndisclosedIdentity
| Session State | Set by the DetermineSharedUndisclosedIdentities feature.
    HideUndisclosedIdentities
| Session State | Flag set by the DetermineSharedUndisclosedIdentities feature to indicate to the HideUndisclosedIdentity feature to "hide" the identity of the caller by replacing SIP headers with the shared identity of the companion device.
    BarIncomingCall
| Session State | Set by the DetermineSharedUndisclosedIdentities feature which is used by the GeneralBarring Feature to bar the call.

= DetermineRoamingFromHlr :toc: macro :toclevels: 4 :toc-title: On this page…​

DetermineRoamingFromHlr is responsible for reading subscriber location data from the HLR and writing it into Sentinel session state variable fields.

The data it reads from the HLR is accessed through the `AnyTimeInterrogation` MAP operation. The Application Context used is `anyTimeInfoEnquiryContext_v3_ac`

== Feature cheat sheet

B2BUA Instance | SAS Support | Originating / Terminating | Point(s) in Session Plan | Network Operator Data | Subscriber Data | Stateful or Stateless | POJO Feature or SBB Feature | Other notes
--- | --- | --- | --- | --- | --- | --- | --- | ---
MMTel | Yes | Originating, Forwarding, and Terminating | `SipAccess_SessionCheck`, and `SipAccess_PartyResponse` | Yes | Yes | Stateless | POJO |

== Prerequisite features

- SubscriberDetermination

- FetchCMSISDN

- DetermineChargeMode (only required when using CAP charging)

== Source Code

This feature’s source code is available in the Sentinel VoLTE SDK in the `volte-determine-roaming-from-hlr` module pack. It can be viewed by using the `create-module` command in the SDK with that module pack, for example:

`> create-module new-hlr-module opencloud#volte-determine-roaming-from-hlr#volte/3.1.0;3.1.0.0`

This command will prompt you for information needed to create the new module; once completed the original source for the feature can be found in the new module.

The module-pack consists of a single module, `volte-determine-roaming-from-hlr`, containing the feature’s code. It does rely on the `volte-map-event-handler` which contains the shared event handler for MAP features and also publishes a module pack, however the event handler will not require modification unless a new feature name is introduced.

== Session state input variables

Attribute Name | Type
--- | ---
    Subscriber
| String
    CMSISDN
| String
    ChargeMode
| Enum

== Session state output variables

Attribute Name | Type | Description
--- | --- | ---
    RoamingStatus
| Enum | `UNKNOWN`, `NATIONAL` or `INTERNATIONAL`
    RoamingIndicator
| boolean | `false` if not roaming, `true` otherwise
    AttemptedATI
| boolean | `true` if an `AnyTimeInterrogation` has been attempted by the feature, `false` otherwise
    DiscoveredAccessNetworkInformation
| String | `3GPP-GERAN;cgi-3gpp=<mnc><mcc><lac><ci>;network-provided`, where <ci> defaults to `0000` when not provided in the ATI response

Note: The default values for both RoamingStatus and RoamingIndicator are `UNKNOWN` and `false` respectively. If this feature is unable to determine the roaming status for any reason, it will leave the pre-set values.

== Configuration

The feature uses configuration data from both the HLR MAP Configuration and SIP Sentinel Configuration.

== Statistics

`DetermineRoamingFromHlr` statistics are tracked by the `DetermineRoamingFromHlr` feature and can be found under the following parameter set:
SLEE-Usage ▶ sentinel.volte.sip service ID ▶ sentinel.volte.sip SBB ID ▶ DetermineRoamingFromHlr.

Name | Type | Description
--- | --- | ---
    Started
| Counter | Incremented each time the feature runs
    FailedToStart
| Counter | Incremented when Sentinel VoLTE encounters an error while attempting to start the feature
    IssuedWarning
| Counter | Incremented when a non-fatal problem is encountered and the feature issues a warning
    FailedDuringExecution
| Counter | Incremented when a fatal problem is encountered and the feature cannot execute correctly
    TimedOut
| Counter | Incremented when the feature takes too long to complete and Sentinel VoLTE aborts execution
    RequestSent
| Counter | Incremented when the feature receives subscriber data from the HLR
    RequestSuccessful
| Counter | Incremented after the feature successfully processes the data it received, and loads it into session state fields
    RequestFailed
| Counter | Incremented when absent configuration data prevents the feature from running
    ResponseLatency
| Sampled | Records elapsed time between sending the request to the HLR and getting a response (in milliseconds).
    InternationalRoaming
| Counter | Incremented when the feature determines that the subscriber is roaming internationally
    NotRoaming
| Counter | Incremented when the feature determines that the subscriber is not roaming
    NationalRoaming
| Counter | Incremented when the feature determines that the subscriber is national roaming
    RoamingDataMissingFromHlrResponse
| Counter | Incremented whenever an ATI result comes back from Hlr with missing or invalid location information
    DialogOpenRefuseEvent
| Counter | Incremented whenever the ATI fails due to a dialog open refuse
    DialogUserAbortEvent
| Counter | Incremented whenever the ATI fails due to a dialog user abort
    DialogProviderAbortEvent
| Counter | Incremented whenever the ATI fails due to a dialog provider abort
    OperationErrorEvent
| Counter | Incremented whenever the ATI fails due to an operation error

== Behaviour

This feature uses the CGIN MAP RA to query the HLR with an ATI for subscriber location information.

Each time the feature is invoked, it checks the call type and determines the subscriber number that it should use to query the HLR.

When invoked on a SIP response the feature checks whether a request to the HLR has not already been made and whether there is an `OC-Terminating-Domain` present in the SIP responses with value `CS`. If either is not the case then the feature finishes execution.

The feature attempts to extract "phone number digits" from the `CMSISDN` session state field set by `FetchCMSISDN`, and if it cannot, from the `Subscriber` field set by `SubscriberDetermination`. If the feature cannot form a MSISDN it raises a Feature Error and finishes execution.

The feature then requests subscriber location info by sending a `AnyTimeInterrogation` request to the configured HLR.

In order to form the ATI request the feature:

1. sets the GSM SCF address to the `SentinelSCCPAddress` configuration value

2. sets the destination SCCP address to the `HlrSCCPAddress` configuration value

3. sets the `RequestedInfo` indicator field to request Location Information

If a successful result is received, it retrieves location information from the ATI result. The location information can be in either of the `CellGlobalIdOrServiceAreaIdFixedLength` or `LaiFixedLength` fields. If neither field is present, the feature increments the `RoamingDataMissingFromHlrResponse` stat and finishes.

If the location information is found, the MCC and MNC are evaluated using the PLMN ID Analyser Component to determine whether the subscriber is roaming or not. The `RoamingStatus` and `RoamingIndicator` session state fields are then set accordingly. Their default values in the case of incomplete information or feature failure are `UNKNOWN` and `false` respectively.

If found, the location information is also used to generate a discovered network access information. If no other access network information is available, this will be used in charging content AVPs. The format for the generated information is `3GPP-GERAN;cgi-3gpp=<cgi>;network-provided`, where `<cgi>` is the Cell Global ID, made up of the MCC, MNC, Location Area Code (in hex) and Cell Id (in hex) concatenated. If the Cell Id is not provided by the HLR, it will default to 0000.

=== OC-Roaming-Status Header

If the feature is running on a terminating MMTel instance, and CAP charging is enabled, it will attempt to add an `OC-Roaming-Status` header to the outbound request. The value of the header will be set to match the value of `RoamingStatus`.

= Diameter MMTel Information :toc: macro :toclevels: 4 :toc-title: On this page…​

This feature records charging information about MMTel supplementary services invoked on a call.

The feature name is `DiameterMMTelInfo`, as it is based on 3GPP TS 32.299 v12.11.0 (vcb0).

== Feature cheat-sheet

B2BUA Instance | SAS Support | Originating / Terminating | Point(s) in Session Plan | Network Operator Data | Subscriber Data | Stateful or Stateless | POJO Feature or SBB Feature
--- | --- | --- | --- | --- | --- | --- | ---
MMTEL | No | Originating and Terminating | `SipAccess_PartyRequest` `SipAccess_PartyResponse` `SipAccess_SubscriberCheck` `SipAccess_ServiceTimer` `SipMidSession_PartyRequest` `SipMidSession_PartyResponse` `SipMidSession_CreditAllocatedPostCC` `SipMidSession_CreditLimitReachedPostCC` `SipMidSession_OCSFailurePostCC` `SipLegEnd` `SipEndSession` | No | No | Stateless | POJO

== Session state inputs and outputs

=== Inputs

Name | Type | Purpose
--- | --- | ---
CallType | Enum | Used to set the Subscriber-Role AVP.
RanOip | boolean | If true, adds Supplementary-Service AVP indicating that OIP was used on the call.
RanOir | boolean | If true, adds Supplementary-Service AVP indicating that OIR was used on the call.
RanTip | boolean | If true, adds Supplementary-Service AVP indicating that TIP was used on the call.
RanTir | boolean | If true, adds Supplementary-Service AVP indicating that TIR was used on the call.
RanIcb | boolean | If true, adds Supplementary-Service AVP indicating that ICB was used on the call.
RanOcb | boolean | If true, adds Supplementary-Service AVP indicating that OCB was used on the call.
RanCW | boolean | If true, adds Supplementary-Service AVP indicating that CW was used on the call.
RanHOLD | boolean | If true, adds Supplementary-Service AVP indicating that HOLD was used on the call.
LastDiversionType | Enum | Used to populate the CDIV Supplementary-Service AVP.
DiversionCounter | int | Used to populate the CDIV Supplementary-Service AVP.
Subscriber | String | Used to populate the Associated-Party-Address AVP in the CDIV Supplementary-Service AVP.

=== Outputs

Name | Type | Description
--- | --- | ---
MMTelInformation | MmtelInformation | The MMTel-Information AVP that will be written to a CDR, or sent in a Credit-Control-Request. This AVP is defined in 3GPP TS 32.299 v12.11.0 §7.2.111. Contains information about the MMTel supplementary services invoked during the call.

== Behaviour

The DiameterMMTelInfo feature populates the Diameter Ro MMTel-Information AVP with information about supplementary services used in the call. The feature stores an MMTel-Information AVP in session state, and updates it at various feature execution points when other supplementary services have run. The resulting MMTel-Information AVP is used by the VolteSipAvpCdr feature when writing a CDR. The MMTel-Information AVP is also sent in the final Credit-Control-Request to the OCS.

= Flexible Alerting Features :indexpage:

Flexible Alerting Features

Feature | What it does
--- | ---
MMTel Determine Flexible Alerting Mode | determines if and how the Flexible Alerting features will execute based on feature configuration and the HSS Subscriber Data.
MMTelParallelFA | implements the Flexible Alerting service, by alerting the group members in parallel
MMTelSequentialFA | implements the Flexible Alerting service, by sequentially alerting the group members.

= MMTel Determine Flexible Alerting Mode :toc: macro :toclevels: 4 :toc-title: On this page …​

The `MMTelDetermineFlexibleAlertingMode` feature determines if and how the Flexible Alerting features will execute based on feature configuration and the HSS Subscriber Data. .

| The Determine Flexible Alerting Mode feature runs before the Flexible Alerting features. It reads subscriber data and configuration profile tables to determine the flexible alerting mode and supplies this information to the MMTelParallelFA and MMTelSequentialFA features as a session state field.

== Feature cheat sheet

B2BUA Instance | SAS Support | Originating/Terminating | Point(s) in Session Plan | Network Operator Data | Subscriber Data | Stateful or Stateless | POJO Feature or SBB Feature
--- | --- | --- | --- | --- | --- | --- | ---
All | No | Terminating | Subscriber Check | Yes | Yes | Stateless | POJO

== Prerequisite features

- SubscriberDataLookupFromHSS

== Source Code

This feature’s source code is available in the Sentinel VoLTE SDK in the `mmtel-flexible-alerting` module pack. It can be viewed by using the `create-module` command in the SDK with that module pack, for example:

`> create-module new-mmtel-flexible-alerting opencloud#mmtel-flexible-alerting#volte/3.1.0;3.1.0.0`

This command will prompt you for information needed to create the new modules, once completed the original source for the feature can be found in the new modules.

The module-pack includes the following modules:

Module Name | Description
--- | ---
mmtel-determine-flexible-alerting-mode | Group module for the Determine Flexible Alerting Mode feature.
mmtel-determine-flexible-alerting-mode-profile | The profile for this feature
mmtel-determine-flexible-alerting-mode-library | The common library for this module pack
mmtel-parallel-fa | The flexible alerting parallel feature.
mmtel-sequential-fa | The flexible alerting sequential feature.

== Network Operator Data

The data present in JSLEE profile table `MMTelDetermineFAConfigProfileTable` is used to configure the behaviour of the Flexible Alerting features: MMTelParallelFA and MMTelSequentialFA. This profile table is scoped by the `sentinel key` and the `Pilot Number`.

Here is an example of a profile entry:

    'SomeOperatorName::::sip:callcentre@someoperator.com':
                ModeIsParallel: true
                ParallelMaxWaitTimeout: 5000
                SequentialAnyResponseTimeout: 2000
                SequentialFinalResponseTimeout: 5000
                AddHistoryInfoHeader: false
                AddMpParam: false

The default profile entry is not scoped by a `Pilot Number`:

    'SomeOperatorName::::':
                ModeIsParallel: true
                ParallelMaxWaitTimeout: 5000
                SequentialAnyResponseTimeout: 2000
                SequentialFinalResponseTimeout: 5000
                AddHistoryInfoHeader: false
                AddMpParam: false

Variable Name | Type | Comments
--- | --- | ---
    ParallelMaxWaitTimeout
| int | Set the amount of time in milliseconds that the MMTelParallelFA waits for a final response before canceling the session for a pilot number.
    ModeIsParallel
| boolean | Set the mode to parallel (true) or sequential (false).
    SequentialAnyResponseTimeout
| int | Set the amount of time in milliseconds that the MMTelSequentialFA waits for a any response from the INVITE before start alerting the next member.
    SequentialFinalResponseTimeout
| int | Set the amount of time in milliseconds that the MMTelSequentialFA waits for a final response from the INVITE before start alerting the next member.
    AddHistoryInfoHeader
| boolean | Determines whether to add `History-Info` headers to the outgoing requests.
    AddMpParam
| boolean | If adding `History-Info` headers, determines whether to add `hi-target-param` headers (of type `mp`) to the added `hi-entry`.

== Session Input Variables

Variable Name | Type | Comments
--- | --- | ---
    MMTelFAServiceData
| Complex | Read from the HSS in SubscriberDataLookupFromHSS

== Session Output Variables

Variable Name | Type | Comments
--- | --- | ---
    FlexibleAlertingMode
| Enum | Determines whether the `FA Group` will be alerted in sequential or parallel way or if none of the flexible alerting features will run. Possible values are: `NONE`, `PARALLEL` or `SEQUENTIAL`.
    FlexibleAlertingGroupMode
| Enum | Determines whether the `FA Group` is of type `single-user` or `multiple-users`. Possible values are: `GROUP_NONE`, `SINGLE_USER` or `MULTIPLE_USERS`

== Statistics

MMTelDetermineFAMode statistics are tracked by the sentinel.volte.sip SBB and can be found under the following parameter set in REM:
SLEE-Usage → sentinel.volte.sip service → sentinel.volte.sip SBB → feature → MMTelDetermineFAMode
or with rhino-stats:
"SLEE-Usage.Services.ServiceID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].SbbID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].feature.MMTelDetermineFAMode"

Statistic | Type | Incremented when…​
--- | --- | ---
    Started
| Counter | each time the feature runs
    FAModeStarted
| Counter | each time the feature runs
    FailedDuringExecution
| Counter | a fatal error occurs while the feature is executing
    FailedToStart
| Counter | Sentinel VoLTE encounters an error while attempting to start the feature.
    IssuedWarning
| Counter | a non-fatal problem is encountered and the feature issues a warning.
    TimedOut
| Counter | the feature takes too long to complete and Sentinel VoLTE aborts execution.
    FAModeNoFA
| Counter | the feature fails to trigger Flexible Alerting under FA mode
    FANoProfile
| Counter | no valid profile is loaded for poilt subscriber
    FAValidPilotNumber
| Counter | subscriber data equals the requestUri header.

== Behaviour

When the feature starts, it tries to load the configuration profile for the pilot number present in the flexible alerting subscriber data. The table `MMTelDetermineFAConfigProfileTable` is expected to contain a profile with name scoped by the `sentinel selection key` and the `Pilot Number`, i.e, `SomeOperatorName::::sip:callcentre@someoperator.com`.

If there is no profile for the pilot number the feature try to get the configuration from the default profile: `SomeOperatorName::::`.

When there is no suitable profile the `FlexibleAlertingMode` is set to `NONE` and the `FlexibleAlertingGroupMode` is set to `GROUP_NONE`. It means that the neither MMTelParallelFA nor MMTelSequentialFA will run.

When there is a suitable profile, the feature checks if the flexible-alerting is active by checking the `authorized` field in the flexible-alerting Subscriber Data. If the service is not active, i.e `authorized="false"`, neither MMTelParallelFA nor MMTelSequentialFA will run. The HSS schema for flexible alerting defines two sets of services that can contain the key `authorized`: `operator-flexible-alerting` and `operator-flexible-alerting-group`. The feature checks both to define if the service is authorized. The table below shows the logic:

    operator-flexible-alerting authorized
    operator-flexible-alerting-group authorized
    service status
    true
    true
    active
    true
    null
    active
    null
    true
    active
    false
    any
    inactive
    any
    false
    inactive
    null
    null
    inactive

When flexible alerting is active, the group type in the Subscriber Data (`single-user` or `multiple-users`) is written into the Session State variable `FlexibleAlertingGroupMode`. The `FlexibleAlertingMode` Session State field is set according to the value in the configuration profile (`ModeIsParallel` attribute).

== Subscriber data examples === MULTIPLE_USERS

HSS Subscriber Data

    <?xml version="1.0" encoding="UTF-8"?>
    <Sh-Data>
        <RepositoryData>
            <ServiceIndication>MMTEL-Services</ServiceIndication>
            <SequenceNumber>1</SequenceNumber>
            <ServiceData>
                <MMTelServices
                    xmlns="http://uri.etsi.org/ngn/params/xml/simservs/xcap"
                    xmlns:cp="urn:ietf:params:xml:ns:common-policy">
                    <complete-flexible-alerting>
                        <operator-flexible-alerting authorized="true"/>
                        <operator-flexible-alerting-group authorized="true">
                            <identity>sip:friends@home1.opencloud.co.nz</identity>
                            <group-type>multiple-users</group-type>
                            <membership>permanent</membership>
                            <members>
                                <member active="true">sip:bob@home1.opencloud.co.nz</member>
                                <member active="true">sip:charlie@home1.opencloud.co.nz</member>
                                <member active="true">sip:daisy@home1.opencloud.co.nz</member>
                            </members>
                        </operator-flexible-alerting-group>
                    </complete-flexible-alerting>
                </MMTelServices>
            </ServiceData>
        </RepositoryData>
    </Sh-Data>

Profile configuration

    ModeIsParallel: true
    ParallelMaxWaitTimeout: 20000
    SequentialAnyResponseTimeout: 2000
    SequentialFinalResponseTimeout: 5000

In the example above, the group `sip:friends@home1.opencloud.co.nz` has three active members. The FlexibleAlertingGroupMode is set to `MULTIPLE_USERS` , the FlexibleAlertingMode is set to `PARALLEL`, and the timeout is set to 20 seconds.

=== SINGLE_USER

HSS Subscriber Data

    <Sh-Data>
        <RepositoryData>
            <ServiceIndication>MMTEL-Services</ServiceIndication>
            <SequenceNumber>1</SequenceNumber>
            <ServiceData>
                <MMTelServices
                    xmlns="http://uri.etsi.org/ngn/params/xml/simservs/xcap"
                    xmlns:cp="urn:ietf:params:xml:ns:common-policy">
                    <complete-flexible-alerting>
                        <operator-flexible-alerting authorized="true"/>
                        <operator-flexible-alerting-group authorized="true">
                            <identity>sip:bob@home1.opencloud.co.nz</identity>
                            <group-type>single-user</group-type>
                            <membership>permanent</membership>
                            <members>
                                <member active="true">sip:bob@home1.opencloud.co.nz</member>
                                <member active="true">sip:bob-mobile@home1.opencloud.co.nz</member>
                                <member active="true">sip:bob-desk@home1.opencloud.co.nz</member>
                            </members>
                        </operator-flexible-alerting-group>
                    </complete-flexible-alerting>
                </MMTelServices>
            </ServiceData>
        </RepositoryData>
    </Sh-Data>

Profile configuration

    ModeIsParallel: false
    ParallelMaxWaitTimeout: 5000
    SequentialAnyResponseTimeout: 2000
    SequentialFinalResponseTimeout: 5000

In the example above, the group `sip:bob@home1.opencloud.co.nz` has three active members. The FlexibleAlertingGroupMode is set to `SINGLE_USER`, the FlexibleAlertingMode is set to `SEQUENTIAL` and the timeout is for receiving any response from a member is set to 2 seconds and the timeout for receiving a final response from a member is 5 seconds.

= MMTelParallelFA :toc: macro :toclevels: 4 :toc-title: On this page…​

The MMTelParallelFA feature implements the Flexible Alerting service, by alerting the group members in parallel

== Feature Cheat Sheet

B2BUA Instance | Originating / Terminating | SAS Support | Point(s) in Session Plan | Network Operator Data | Subscriber Data | Stateful or Stateless | POJO Feature or SBB Feature
--- | --- | --- | --- | --- | --- | --- | ---
MMTEL | No | Terminating | Sip_Access_Subscriber_Check, Sip_Access_Party_Request, Sip_Access_Party_Response, Sip_Access_Service_Timer, SipMidSession_Party_Request, Sip_Mid_Session_Party_Response, SipLegEnd | Yes | Yes | Statefull | POJO

== Source Code

This feature’s source code is available in the Sentinel VoLTE SDK in the `mmtel-flexible-alerting` module pack. It can be viewed by using the `create-module` command in the SDK with that module pack, for example:

`> create-module new-mmtel-flexible-alerting opencloud#mmtel-flexible-alerting#volte/3.1.0;3.1.0.0`

This command will prompt you for information needed to create the new modules, once completed the original source for the feature can be found in the new modules.

The module-pack includes the following modules:

Module Name | Description
--- | ---
mmtel-determine-flexible-alerting-mode | Group module for the Determine Flexible Alerting Mode feature.
mmtel-determine-flexible-alerting-mode-profile | The profile for this feature
mmtel-determine-flexible-alerting-mode-library | The common library for this module pack
mmtel-parallel-fa | The the flexible alerting parallel feature.
mmtel-sequential-fa | The the flexible alerting sequential feature.

== Statistics

MMTelParallelFA statistics are tracked by the sentinel.volte.sip SBB and can be found under the following parameter set in REM:
SLEE-Usage → sentinel.volte.sip service → sentinel.volte.sip SBB → feature → MMTelParallelFA
or with rhino-stats:
"SLEE-Usage.Services.ServiceID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].SbbID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].feature.MMTelParallelFA"

Name | Type | Incremented when …​
--- | --- | ---
Started | Counter | each time the feature runs
FailedDuringExecution | Counter | a fatal error occurs while the feature is executing
FailedToStart | Counter | Sentinel VoLTE encounters an error while attempting to start the feature.
IssuedWarning | Counter | a non-fatal problem is encountered and the feature issues a warning.
TimedOut | Counter | the feature takes too long to complete and Sentinel VoLTE aborts execution
ProcessingRequest | Counter | processing a request message.
ProcessingResponse | Counter | processing a response from the downstream forked legs.
InviteRequestReceived | Counter | the original INVITE is received.
CancelRequestReceived | Counter | a CANCEL message is received.
ProvisionalResponseReceived | Counter | a 1xx message is received.
GroupMemberAlerted | Counter | an INVITE request is sent to a group member.
LegReleased | Counter | a dialog leg is released.
UpstreamForkCreated | Counter | the feature creates a new leg towards the calling party. It happens on the provisional responses.
TriggeredOnResponse | Counter | the feature is triggered on a response message.
TriggeredOnRequest | Counter | the feature is triggered on a request message.
TriggeredOnTimer | Counter | the feature is triggered on a timmer.
TimeoutTimerCancelled | Counter | the feature cancel the timer.
TimeoutTimerSet | Counter | the feature sets the timer. The timer is set before the INVITE is sent to the first group member.
ExitedEarlyNoMembersToAlert | Counter | there is just one member in the group and it is the pilot number.
Received480 | Counter | receives a 480 (Temporarily Unavailable) response from a member
Received486 | Counter | receives a 486 (Busy Here) response from a member
Received408 | Counter | receives a 408 (Timeout) response from a member
Received404 | Counter | receives a 404 (Not found) response from a member
ReceivedSuccess | Counter | receives a 200 (OK) response from a member
RespondedUpstreamWith480 | Counter | the feature sends a 480 (Temporarily Unavailable) to the calling party.
RespondedUpstreamWith486 | Counter | the feature sends a 486 (Busy Here) to the calling party.
RespondedUpstreamWith408 | Counter | the feature sends a 408 (Timeout) to the calling party.
RespondedUpstreamWith404 | Counter | the feature sends a 404 (Not found) to the calling party.
RespondedUpstreamWithSuccess | Counter | the feature sends a 200 (OK) to the calling party.

== Interaction with other MMTel Services

=== CDIV Unconditional

If CDIV Unconditional is active for the Pilot Identity, CDIV Unconditional procedures will be applied and no FA group member will be alerted.

=== CDIV Busy

If CDIV Busy is active for the Pilot Identity, CDIV Busy procedures will be applied if the pilot number is considered busy. The definition of Busy for the pilot number depends on the group type: `single-user` or `multiple-users`. For `single-user`, when one member is busy the pilot number is busy, while for `multiple-uses` all group members have to be busy for the pilot number to be considered busy.

=== CDIV No Reply and CDIV Not Reachable

If the FA Pilot Number is considered in a state of `No Reply` or `Not Reachable` then the CDIV procedures for those MMTel services will be applied.

=== CDIV Not Logged-in

If the FA Pilot Identity has CDIV Not Registered active, the procedures for CDIV Not Registered will be applied.

=== MMTelOIP

OIP applied to any FA group member when OIP is active for the FA Pilot Identity.

=== MMTelTIP

If the FA Pilot Identity did not apply TIR, the termination identification is the FA Pilot Identity.

=== MMTelTIR

If the FA Pilot Identity has TIR activated, the termination identification is not presented.

=== MMTelICB

If the FA Pilot Identity has ICB activated, the procedures for ICB will be applied.

=== MMTelOCB

If any FA group member has OCB activated, the procedures for OCB will be applied for that member.

== Network Operator Data

The data present in JSLEE profile table `MMTelDetermineFAConfigProfileTable` is used to configure the behaviour of the Parallel Flexible Alerting feature.

Variable Name | Type | Comments
--- | --- | ---
    ParallelMaxWaitTimeout
| int | Set the amount of time in milliseconds that the MMTelParallelFA feature waits before canceling the session for a pilot number.
    AddHistoryInfoHeader
| boolean | Determines whether to add `History-Info` headers to the outgoing requests.
    AddMpParam
| boolean | If adding `History-Info` headers, determines whether to add `hi-target-param` headers (of type `mp`) to the added `hi-entry`.

== Session Input Variables

Variable Name | Type | Comments
--- | --- | ---
    MMTelFAServiceData
| Complex | Service data read from the HSS
    FlexibleAlertingGroupMode
| Enum | Determines whether single user or multi-user Flexible Alerting is used.

== Session Output Variables

Variable Name | Type | Comments
--- | --- | ---
    SuppressCdiv
| Boolean | Indicates whether response should be ignored by the MMTel CDIV feature.
    ParallelFATimerID
| int | Indicates the MMTelParallelFA timer identification.
    StripPreconditionsLegNames
| <Set>String | The MMTelParalleFA adds each parallel legname to this Set which is used by the StripPreconditions feature to remove preconditions (if StripPreconditions EnabledFlag is selected).

== Behaviour

The MMTelParallelFA implements the Flexible Alerting in parallel. It reads the `MMTelFAServiceData` session variable for the group information and issues INVITE requests towards all members in parallel using SIP parallel forking.

The INVITE request URI will have two parameters added to it.

- The first is the Cause Parameter with the value always set to `cause=302`.

- The second is the MMTel Service Type Parameter with the value set to `mmtel-service-type=11` for flexible alerting.

When a member answers the call with 200 (OK) the feature cancels all other sessions towards the other members and finishes the call setup procedures between the calling party and the member that answered.

It also controls the state of the FA Pilot Identity regarding busy, not reachable and no reply states. The determination of those states, depends on the members responses and on the FA group type: `single-user` or `multiple-users`. For further information regarding the state of a Pilot Identity see Flexible Alerting.

== OC-Retarget Header

The OC-Retarget header is added by MMTel Flexible Alerting to communicate that a retarget has occurred. This header is inserted into the initial INVITEs that goes towards the retargeted party. This is then used in the composition to decide whether to invoke the SCC-AS.

For more details see OC-Retarget Header

== Parallel Flexible Alerting and MMTelCDIV interaction

The CDIV feature runs before the Flexible Alerting feature on INVITE path. This way, the CFNL and CFU conditions can be applied to the `Pilot Number` before alerting any `FA-Group` member.

On the Response path, the CDIV feature runs after the Flexible Alerting feature. CDIV applies the conditions CFB, CFNR, and CFNRc based on the final response that the MMTelParallelFA feature sends to the caller. To avoid the CDIV feature being triggered on any final `FA-Group` members response, the MMTelParallelFA feature suppresses the CDIV feature execution by setting the session state variable `SuppressCdiv`. MMTelParallelFA will allow the CDIV feature to execute only after the the state of the `Pilot Number` is defined by receiving all members final responses or by timing out.

CDIV and MMTelParallelFA are both triggered on each other timers. This guarantees that the MMTelParallelFA feature cancels the ongoing downstream dialogs and that the CDIV feature can execute the CFNR and CFNRc conditions properly.

When the CDIV timer fires first, the MMTelParallelFA feature cancels the downstream dialogs and sends a 408 (Timeout) response towards the caller party. When CDIV executes, it will identify the 408 response and do the proper re-targeting towards the diverted subscriber.

When the MMTelParallelFA timer fires first, the MMTelParallelFA feature stops the CDIV timer and cancels the downstream dialogs and sends a 408 (Timeout) response towards the caller party. When CDIV executes, it identifies the trigger is the MMTelParallelFA timer, identifies the 408 response and do the proper re-targeting towards the diverted subscriber.

In the case when no timer has been fired, CDIV feature uses the sip response sent from the MMTelParallelFA feature to evaluate and execute the proper MMTelCDIV conditions.

== HSS Subscriber Data Examples

=== `single user` group type

In the first example the Subscriber Data configures a flexible alerting group with type `single-user`. The group has three active members and the flexible alerting service is authorized or active.

    <?xml version="1.0" encoding="UTF-8"?>
      <Sh-Data>
        <RepositoryData>
            <ServiceIndication>MMTEL-Services</ServiceIndication>
           <SequenceNumber>1</SequenceNumber>
            <ServiceData>
                <MMTelServices  xmlns="http://uri.etsi.org/ngn/params/xml/simservs/xcap" xmlns:cp="urn:ietf:params:xml:ns:common-policy">
                    <complete-flexible-alerting>
                        <operator-flexible-alerting authorized="true"/>
                        <operator-flexible-alerting-group authorized="true">
                            <identity>sip:bob@home1.opencloud.co.nz</identity>
                            <group-type>single-user</group-type>
                            <membership>permanent</membership>
                            <members>
                                <member active="true">sip:bob@home1.opencloud.co.nz</member>
                                <member active="true">sip:bobmobile@home1.opencloud.co.nz</member>
                                <member active="true">sip:bobdesk@home1.opencloud.co.nz</member>
                            </members>
                        </operator-flexible-alerting-group>
                    </complete-flexible-alerting>
                </MMTelServices>
            </ServiceData>
        </RepositoryData>
    </Sh-Data>

=== `multiple-users` group type

The following example shows a group of `multiple-users` type with four members. The flexible alerting service is authorized or active.

    <?xml version="1.0" encoding="UTF-8"?>
    <Sh-Data>
        <RepositoryData>
            <ServiceIndication>MMTEL-Services</ServiceIndication>
            <SequenceNumber>1</SequenceNumber>
            <ServiceData>
                <MMTelServices xmlns="http://uri.etsi.org/ngn/params/xml/simservs/xcap"   xmlns:cp="urn:ietf:params:xml:ns:common-policy">
                   <complete-flexible-alerting>
                        <operator-flexible-alerting authorized="true"/>
                        <operator-flexible-alerting-group authorized="true">
                           <identity>sip:office@home1.opencloud.co.nz</identity>
                           <group-type>multiple-users</group-type>
                            <membership>demand</membership>
                            <members>
                                <member active="true">sip:desk1@home1.opencloud.co.nz</member>
                                <member active="true">sip:desk2@home1.opencloud.co.nz</member>
                                <member active="true">sip:desk3@home1.opencloud.co.nz</member>
                                <member active="true">sip:desk4@home1.opencloud.co.nz</member>
                            </members>
                        </operator-flexible-alerting-group>
                    </complete-flexible-alerting>
                </MMTelServices>
            </ServiceData>
        </RepositoryData>
    </Sh-Data>

= MMTelSequentialFA :toc: macro :toclevels: 4 :toc-title: On this page…​

The MMTelSequentialFA feature implements the Flexible Alerting service, by sequentially alerting the group members.

== Feature Cheat Sheet

B2BUA Instance | SAS Support | Originating / Terminating | Point(s) in Session Plan | Network Operator Data | Subscriber Data | Stateful or Stateless | POJO Feature or SBB Feature
--- | --- | --- | --- | --- | --- | --- | ---
MMTEL | No | Terminating | Sip_Access_Subscriber_Check, Sip_Access_Party_Request, Sip_Access_Party_Response, Sip_Access_Service_Timer, SipMidSession_Party_Request, Sip_Mid_Session_Party_Response, SipLegEnd | Yes | Yes | Stateless | POJO

== Source Code

The source code for this feature is available in the Sentinel VoLTE SDK in the `mmtel-flexible-alerting` module pack. It can be viewed by using the `create-module` command in the SDK with that module pack, for example:

`> create-module new-mmtel-flexible-alerting opencloud#mmtel-flexible-alerting#volte/3.1.0;3.1.0.0`

This command will prompt you for information needed to create the new modules, once completed the original source for the feature can be found in the new modules.

The module-pack includes the following modules:

Module Name | Description
--- | ---
mmtel-determine-flexible-alerting-mode | Group module for the Determine Flexible Alerting Mode feature.
mmtel-determine-flexible-alerting-mode-profile | The profile for this feature
mmtel-determine-flexible-alerting-mode-library | The common library for this module pack
mmtel-parallel-fa | The flexible alerting parallel feature.
mmtel-sequential-fa | The flexible alerting sequential feature.

== Statistics

MMTelSequentialFA statistics are tracked by the sentinel.volte.sip SBB and can be found under the following parameter set in REM:
SLEE-Usage → sentinel.volte.sip service → sentinel.volte.sip SBB → feature → MMTelSequentialFA
or with rhino-stats:
"SLEE-Usage.Services.ServiceID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].SbbID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].feature.MMTelSequentialFA"

Name | Type | Incremented when …​
--- | --- | ---
Started | Counter | each time the feature runs
FailedDuringExecution | Counter | a fatal error occurs while the feature is executing
FailedToStart | Counter | Sentinel VoLTE encounters an error while attempting to start the feature.
IssuedWarning | Counter | a non-fatal problem is encountered and the feature issues a warning.
TimedOut | Counter | the feature takes too long to complete and Sentinel VoLTE aborts execution
ProcessingRequest | Counter | processing a request message.
ProcessingResponse | Counter | processing a response from a downstream forked leg.
InviteRequestReceived | Counter | the original invite is received.
CancelRequestReceived | Counter | a CANCEL message is received.
ProvisionalResponseReceived | Counter | a 1xx message is received.
SuccessResponseReceived | Counter | a 200 (OK) message is received.
GroupMemberAlerted | Counter | an INVITE message was sent to a group member.
GroupMemberAddedToQueue | Counter | a group member was queued for alerting.
MemberLegReleased | Counter | a dialog leg is released.
RespondedUpstreamManually | Counter | the feature created an upstream response.
TriggeredOnResponse | Counter | the feature is triggered on a response message.
TriggeredOnRequest | Counter | the feature is triggered on a request message.
TriggeredOnTimer | Counter | the feature is triggered on a timer event.
TriggeredOnLegEndEvent | Counter | the feature is triggered on a SIP leg end event.
AnyResponseTimerSet | Counter | the feature set a timer to wait for a response on a downstream leg.
FinalResponseTimerSet | Counter | the feature set a timer to wait for a final response on a downstream leg.
AnyResponseTimerCancelled | Counter | the timer waiting for a response on a downstream leg was cancelled.
FinalResponseTimerCancelled | Counter | the timer waiting for a final response on a downstream leg was cancelled.
TimerFired | Counter | the feature handled a timer event.
ExitedEarlyNoMembersToAlert | Counter | there is just one member in the group and it is the pilot number.

== Interaction with other MMTel Services

=== CDIV Unconditional

If CDIV Unconditional is active for the Pilot Identity, CDIV Unconditional procedures will be applied and no group member will be alerted.

=== CDIV Busy

If CDIV Busy is active for the Pilot Identity, CDIV Busy procedures will be applied if the pilot number is considered busy. The definition of Busy for the pilot number depends on the group type: `single-user` or `multiple-users`. For `single-user`, when one member is busy the pilot number is busy, while for `multiple-uses` all group members have to be busy for the pilot number to be considered busy.

=== CDIV No Reply and CDIV Not Reachable

If the FA Pilot Number is considered in a state of `No Reply` or `Not Reachable` then the CDIV procedures for those MMTel services will be applied.

=== CDIV Not Logged-in

If the FA Pilot Identity has CDIV Not Registered active, the procedures for CDIV Not Registered will be applied.

=== MMTelOIP

OIP applied to any FA group member when OIP is active for the FA Pilot Identity.

=== MMTelTIP

If the FA Pilot Identity did not apply TIR, the termination identification is the FA Pilot Identity.

=== MMTelTIR

If the FA Pilot Identity has TIR activated, the termination identification is not presented.

=== MMTelICB

If the FA Pilot Identity has ICB activated, the procedures for ICB will be applied.

=== MMTelOCB

If any FA group member has OCB activated, the procedures for OCB will be applied for that member.

== Network Operator Data

The data present in the JSLEE profile table `MMTelDetermineFAConfigProfileTable` is used to configure the behaviour of the Sequential Flexible Alerting Feature.

Variable Name | Type | Comments
--- | --- | ---
    SequentialAnyResponseTimeout
| int | Set the amount of time in milliseconds that the MMTelSequentialFA feature waits for a response before cancelling the dialog with that group member.
    SequentialFinalResponseTimeout
| int | Set the amount of time in milliseconds that the MMTelSequentialFA feature waits for a final response before cancelling the dialog with that group member.
    AddHistoryInfoHeader
| boolean | Determines whether to add `History-Info` headers to the outgoing requests.
    AddMpParam
| boolean | If adding `History-Info` headers, determines whether to add `hi-target-param` headers (of type `mp`) to the added `hi-entry`.

== Session Input Variables

Variable Name | Type | Comments
--- | --- | ---
    MMTelFAServiceData
| Complex | Service data read from the HSS
    FlexibleAlertingGroupMode
| Enum | Determines whether single user or multi-user Flexible Alerting is used.

== Session Output Variables

Variable Name | Type | Comments
--- | --- | ---
    SuppressCdiv
| Boolean | Indicates whether response should be ignored by the MMTel CDIV feature.

== Behaviour The MMTelSequentialFA implements Flexible Alerting sequentially. It reads the `MMTelFAServiceData` session variable to get the group information and will alert each active group member one at a time, using SIP sequential forking.

The INVITE request URI will have two parameters added to it.

- The first is the Cause Parameter with the value always set to `cause=302`.

- The second is the MMTel Service Type Parameter with the value set to `mmtel-service-type=11` for flexible alerting.

If a member responds with a final response other than a 200 (OK) or a timer event occurs the feature will end the dialog for that member and alert the next member in the queue. When a member answers the call with a 200 (OK) the feature will finish the call setup procedure between the calling party and the member that answered.

The feature also controls the state of the FA Pilot Identity regarding the busy, not reachable and no reply states. The determination of those states depends on the responses of the members and the FA group type: `single-user` `multiple-users`. For further information regarding the state of a Pilot Identity see Flexible Alerting.

== OC-Retarget Header

The OC-Retarget header is added by MMTel Flexible Alerting to communicate that a retarget has occurred. This header is inserted into the initial INVITE that goes towards the retargeted party. This is then used in the composition to decide whether to invoke the SCC-AS.

For more details see OC-Retarget Header

== Sequential Flexible Alerting and MMTelCDIV interaction

The CDIV feature runs before the Flexible Alerting feature on INVITE path. This way, the CFNL and CFU conditions can be applied to the pilot number before alerting any group member.

On the Response path, the CDIV feature runs after the Flexible Alerting feature. CDIV applies the conditions CFB, CFNR, and CFNRc based on the final response that the MMTelSequentialFA feature sends to the caller. To avoid the CDIV feature being triggered on any final response from a group member, the MMTelSequentialFA feature suppresses the CDIV feature execution by setting the session state variable `SuppressCdiv`. MMTelSequentialFA will allow the CDIV feature to execute only after the state of the pilot number is defined by receiving all members final responses or by timing out.

== HSS Subscriber Data Examples

=== `single user` group type

In the first example the Subscriber Data configures a flexible alerting group with type `single-user`. The group has three active members and the flexible alerting service is authorized or active.

    <?xml version="1.0" encoding="UTF-8"?>
      <Sh-Data>
        <RepositoryData>
            <ServiceIndication>MMTEL-Services</ServiceIndication>
           <SequenceNumber>1</SequenceNumber>
            <ServiceData>
                <MMTelServices  xmlns="http://uri.etsi.org/ngn/params/xml/simservs/xcap" xmlns:cp="urn:ietf:params:xml:ns:common-policy">
                    <complete-flexible-alerting>
                        <operator-flexible-alerting authorized="true"/>
                        <operator-flexible-alerting-group authorized="true">
                            <identity>sip:bob@home1.opencloud.co.nz</identity>
                            <group-type>single-user</group-type>
                            <membership>permanent</membership>
                            <members>
                                <member active="true">sip:bob@home1.opencloud.co.nz</member>
                                <member active="true">sip:bobmobile@home1.opencloud.co.nz</member>
                                <member active="true">sip:bobdesk@home1.opencloud.co.nz</member>
                            </members>
                        </operator-flexible-alerting-group>
                    </complete-flexible-alerting>
                </MMTelServices>
            </ServiceData>
        </RepositoryData>
    </Sh-Data>

=== `multiple-users` group type

The following example shows a group of `multiple-users` type with four members. The flexible alerting service is authorized or active.

    <?xml version="1.0" encoding="UTF-8"?>
    <Sh-Data>
        <RepositoryData>
            <ServiceIndication>MMTEL-Services</ServiceIndication>
            <SequenceNumber>1</SequenceNumber>
            <ServiceData>
                <MMTelServices xmlns="http://uri.etsi.org/ngn/params/xml/simservs/xcap"   xmlns:cp="urn:ietf:params:xml:ns:common-policy">
                   <complete-flexible-alerting>
                        <operator-flexible-alerting authorized="true"/>
                        <operator-flexible-alerting-group authorized="true">
                           <identity>sip:office@home1.opencloud.co.nz</identity>
                           <group-type>multiple-users</group-type>
                            <membership>demand</membership>
                            <members>
                                <member active="true">sip:desk1@home1.opencloud.co.nz</member>
                                <member active="true">sip:desk2@home1.opencloud.co.nz</member>
                                <member active="true">sip:desk3@home1.opencloud.co.nz</member>
                                <member active="true">sip:desk4@home1.opencloud.co.nz</member>
                            </members>
                        </operator-flexible-alerting-group>
                    </complete-flexible-alerting>
                </MMTelServices>
            </ServiceData>
        </RepositoryData>
    </Sh-Data>

= Geo Local Normalization :toc: macro :toclevels: 4 :toc-title: On this page…​

The GeoLocalNormalization service adds the `geo-local` value to the Tel URI `phone-context` parameter for local numbers that should not be translated to international format.

The GeoLocalNormalization feature includes the `geo-local` value in case the served user is in roaming and request URI is not in international format or already contains the `geo-local` value. If `geo-local` value is added to the `phone-context` parameter the feature sets the session state `GeoLocalNormalizationApplied` to true. This value is used to suppress the SIP Normalization Feature, that is executed afterwards.

== Feature cheat sheet

B2BUA Instance | SAS Support | Originating / Terminating | Point(s) in Session Plan | Network Operator Data | Subscriber Data | Stateful or Stateless | POJO or SBB Feature
--- | --- | --- | --- | --- | --- | --- | ---
MMTEL | No | Both Originating and Terminating | `MMTel_SipAccess_SessionCheck` | No | No | Reads Session State | SBB Feature

== Prerequisite features

- DetermineInitialLegNames

- DetermineInternationalAndRoamingStatus

== Session input variables

The roaming indicator is set by the `DetermineInternationalAndRoamingStatus` feature.

== Session output variables

The session state `GeoLocalNormalizationApplied`.

== Statistics

GeoLocalNormalization statistics are tracked by the sentinel.volte.sip SBB and can be found under the following parameter set in REM:
SLEE-Usage → sentinel.volte.sip service → sentinel.volte.sip SBB → feature → GeoLocalNormalization
or with rhino-stats:
SLEE-Usage → [sentinel.volte.sip service name] → [sentinel.volte.sip SBB name] → .feature.GeoLocalNormalization

Name | Description
--- | ---
    Started
| Incremented each time the feature runs
    FailedToStart
| Incremented when Sentinel VoLTE encounters an error while attempting to start the feature
    FailedDuringExecution
| Incremented when a fatal error occurs during feature execution
    IssuedWarning
| Incremented when a non-fatal error occurs during feature execution
    TimedOut
| Incremented when the feature takes too long to complete and Sentinel VoLTE aborts execution
    ContainsPhoneContext
| Incremented when the requestURI contains the phone-context
    ProcessingSipRequest
| Incremented when the incoming SIP request is an INVITE
    ProcessingSipURI
| Incremented when the requestURI is a SIP URI
    ProcessingTelURL
| Incremented when the requestURI is a TelURL
    Roaming
| Incremented when roaming

== Source

This feature’s source code is available in the Sentinel VoLTE SDK in the `mmtel-geo-local-normalization` module pack. It can be viewed by using the `create-module` command in the SDK with that module pack, for example:

`> create-module new-geoloc-module opencloud#mmtel-geo-local-normalization#volte/3.1.0;3.1.0.0`

This command will prompt you for information needed to create the new module, once completed the original source for the feature can be found in the new module.

== Specification Reference

- IR.65 version 12.0

- IR.92 version 9.0

- 3GPP TS 24.229 version 13.

= Hide Undisclosed Identity :toc: macro :toclevels: 4 :toc-title: On this page…​

This feature replaces the undisclosed identity with the shared identity for an originating call from a companion device where such hiding has been requested .

== Feature Cheat Sheet

B2BUA Instance | SAS Support | Originating / Terminating | Point(s) in Session Plan | Network Operator Data | Subscriber Data | Stateful or Stateless | POJO Feature or SBB Feature | Other notes
--- | --- | --- | --- | --- | --- | --- | --- | ---
MMTel | Yes | Originating | `SipAccess_SubscriberCheck` `SipAccess_PartyRequest` `SipMidSession_PartyRequest` `SipAccess_PartyResponse` `SipMidSession_PartyResponse` | Yes | Yes | Stateless | POJO |

== Prerequisite Features

- Determine Shared And Undisclosed Identities

== Feature Configuration

The profiles within the `HideUndisclosedIdentityConfigProfileTable` are selected using the `SentinelSelectionKey` and has the following field:

Parameter | Type | Description
--- | --- | ---
    HideUndisclosedIdentities
    boolean
| Whether undisclosed indentities should be hidden

== Session Input Variables

Session State variable name | Type | Comments
--- | --- | ---
    SentinelSelectionKey
| SentinelSelectionKey | Determines which configuration to use
    HideUndisclosedIdentities
| boolean | `true` when undisclosed identities should be hidden
    SharedIdentitySip
| URI | Used to replace undisclosed `sip:` URIs
    SharedIdentityTel
| URI | Used to replace undisclosed `tel:` URIs

== Statistics

HideUndisclosedIdentity statistics are tracked by the sentinel.volte.sip SBB and can be found under the following parameter set in REM:
SLEE-Usage → sentinel.volte.sip service → sentinel.volte.sip SBB → feature → HideUndisclosedIdentity
or with rhino-stats:
"SLEE-Usage.Services.ServiceID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].SbbID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].feature.HideUndisclosedIdentity"

Statistic | Incremented when…​
--- | ---
    Started
| the feature runs
    FailedToStart
| Sentinel VoLTE encounters an error while attempting to start the feature
    IssuedWarning
| a non-fatal problem is encountered and the feature issues a warning
    FailedDuringExecution
| a fatal problem is encountered and the feature cannot execute correctly
    TimedOut
| the feature takes too long to complete and Sentinel VoLTE aborts execution
    HideUndisclosedIdentities
| a message is modified to hide the undisclosed identity
    SharedIdentitySip
| a message header address is replaced with the SIP shared identity
    SharedIdentityTel
| a message header address is replaced with the TEL shared identity
    UnsupportedExecutionPoint
| the feature is called from an unsupported execution point

== Behaviour

- If the call type is not mobile originating then the feature finishes with no further processing.

- If the session state field `HideUndisclosedIdentities` is `false` then the feature finishes with no further processing.

- If neither `SharedIdentitySip` or `SharedIdentityTel` session state fields are defined, the feature fails to execute.

- The `HideUndisclosedIdentityConfigProfileTable` profile table is read using the current selection key, and if its `HideUndisclosedIdentities` field is `false`, then the feature finishes with no further processing.

- In the outgoing message, the `P-Asserted-Identity` header, and the `from` header when called from the `SipAccess_SubscriberCheck` execution point, are modified.

  - If the header value is a SIP URI, and `SharedIdentitySip` is defined, or if `SharedIdentityTel` is not defined, the header value address is replaced with `SharedIdentitySip`

  - Otherwise the header value address is replaced with `SharedIdentityTel`

= Identity Presentation and Identity Restriction Features :indexpage:

Identity Presentation and Identity Restriction Features.

Feature | What it does
--- | ---
MMTelOIP | implements the Originating Identification Presentation (OIP) service
MMTelOIR | implements the Originating Identification Restriction (OIR) service
MMTelTIP | implements the Terminating Identification Presentation (TIP) service
MMTelTIR | implements the Terminating Identification Restriction (TIR) service

= MMTelOIP :toc: macro :toclevels: 4 :toc-title: On this page…​

The MMTelOIP feature implements the Originating Identification Presentation (OIP) service .

== What is OIP?

From 3GPP 24.607:

| The Originating Identification Presentation (OIP) service provides the terminating user with the possibility of receiving identity information in order to identify the originating user. The OIP service provides the terminating user with the possibility of receiving trusted (i.e. network provided) identity information in order to identify the originating user. In addition to the trusted identity information, the identity information from the originating user can include identity information generated by the originating user and in general transparently transported by the network. In the particular case where the “no screening” special arrangement does not apply, the originating network shall verify the content of this user generated identity information. The terminating network cannot be responsible for the content of this user generated identity information.

== Feature cheat sheet

B2BUA Instance | SAS Support | Originating / Terminating | Point in Session Plan | Network Operator Data | Subscriber Data | Stateful or Stateless | POJO Feature or SBB Feature
--- | --- | --- | --- | --- | --- | --- | ---
MMTEL | Yes | Terminating | SipAccess_SubscriberPreCreditCheck |
    Yes
| Yes | Stateless | POJO

== Prerequisite features

These features must run before OIP:

- DetermineCallType

- SubscriberDataLookupFromHSS or SubscriberDataLookupFromHLR

== Source Code

This feature’s source code is available in the Sentinel VoLTE SDK in the `mmtel-id-presentation-restriction` module pack. It can be viewed by using the `create-module` command in the SDK with that module pack, for example:

`> create-module new-idpr-module opencloud#mmtel-id-presentation-restriction#volte/3.1.0;3.1.0.0`

This command will prompt you for information needed to create the new modules, once completed the original source for the feature can be found in the new modules.

The module-pack includes the following modules relevant to this feature:

Module Name | Description
--- | ---
mmtel-id-presentation-restriction | Group module for the feature that includes all of the modules listed below.
mmtel-id-presentation-restriction-library | Contains code shared by all ID presentation and restriction features.
mmtel-oip-profile | Contains the profile specification for the feature configuration profile table.
mmtel-oip | Contains the feature itself.

== Statistics

MMTelOIP statistics are tracked by the `sentinel.volte.sip` SBB and can be found under the following parameter set:
SLEE-Usage → sentinel.volte.sip service → sentinel.volte.sip SBB → feature → MMTelOIP

Name | Type | Description
--- | --- | ---
    Started
| Counter | Incremented when the feature is triggered.
    FailedToStart
| Counter | Incremented when the feature fails to start.
    FailedDuringExecution
| Counter | Incremented when the feature fails while executing.
    IssuedWarning
| Counter | Incremented when the feature issues a warning.
    TimedOut
| Counter | Incremented when the feature times out during execution.
    Misconfigured
| Counter | Incremented when a fatal error if the feature configuration can not be loaded.
    ReceivedMalformedPrivacyHeader
| Counter | Incremented when a non-standard ‘Privacy’ header is found in an incoming SIP message.
    FromHeaderAnonymized
| Counter | Incremented when the feature anonymizes the ‘From’ header in an outgoing SIP request.
    ContactHeaderAnonymized
| Counter | Incremented when the feature anonymizes the ‘Contact’ header in an outgoing SIP message.
    ReferredByHeaderAnonymized
| Counter | Incremented when the feature anonymizes the ‘Referred-By’ header in an outgoing SIP message.
    PerformedUserLevelAnonymization
| Counter | Incremented when the feature applies user-level privacy to an outgoing SIP message.
    PerformedHeaderLevelAnonymization
| Counter | Incremented when the feature applies header-level privacy to an outgoing SIP message.
    PerformedSessionLevelAnonymization
| Counter | Incremented when the feature applies session-level privacy to an outgoing SIP message.
    PerformedCustomHeaderAnonymization
| Counter | Incremented when the feature finds and evaluates custom header privacy rules for a message.
    OverrideCategoryTriggered
| Counter | Incremented when the feature disregards requested privacy settings on an incoming SIP message (due to the subscriber having override category status).
    CriticalPrivacyCannotBeFulfilled
| Counter | Incremented when the feature refuses an incoming request due to a `Privacy` header including both the value `critical` and an unrecognised value.

== Network Operator Data

This data is stored in a JSLEE Configuration Profile table called `MMTelOIPConfigProfileTable`. The operator data is scoped according to a Sentinel selection key.

Attribute Name | Type | Default Value | Description
--- | --- | --- | ---
    AnonymizeFromPolicy
| Enum (`ANONYMIZE`, `DO_NOT_ANONYMIZE`) |
    DO_NOT_ANONYMIZE
| When set to `ANONYMIZE` the `from` header of the `INVITE` will always be anonymized if the OIP feature is not active for the subscriber.
    PrivacyHeaderRemovalPolicy
| Enum (`USE_IETF`, `USE_3GPP`) |
    USE_3GPP
| This value is deprecated and no longer used by the feature.
    Override
| Enum (`OVERRIDE_ACTIVE`, `OVERRIDE_NOT_ACTIVE`) |
    OVERRIDE_NOT_ACTIVE
| This value is deprecated and has been replaced by subscriber level data, see MMTelOIPServiceData.
    AllowHistoryInfoDeletion
| boolean |
    false
| Flag to allow History-Info header deletion.

Additionally, the feature reads a second profile table that contains custom rules for removing additional headers under specified circumstances. See Custom Header Privacy Rules below.

== Session input variables

Variable name | Type | Comments
--- | --- | ---
    MMTelOIPServiceData
| Complex | Read from the HSS or HLR in SubscriberDataLookupFromHSS or SubscriberDataLookupFromHLR

== Session output variables

Variable name | Type | Comments
--- | --- | ---
    RanOip
| boolean | Signals to other features that OIP ran on this session.

== Behaviour

If operator data is not present, the OIP feature:

1. Increments an error statistic.

2. Logs a message at the `Fine` level.

3. Informs the Sentinel core that the feature is not configured appropriately (`Invalid Configuration`).

4. Exits.

=== Graceful handling of originating access

As OIP is a terminating feature. It will finish execution without modifying any state if it is invoked in an originating attempt.

=== OIP Override Category

The OIP override category overrides OIR’s requests for privacy, and provides as much identity information as is available to the terminating party.

It is extracted from the operator data in HSS or from HLR field ClipData.OverrideCategory field in ASN.1.

=== Critical Privacy Request

If the incoming request includes a `Privacy` header with the value `critical`, then the OIP feature will check to ensure that it can fulfill the privacy request. If another `Privacy` header value is present in the request that is not recognised by the OIP feature, it will assume that it can not fulfill the privacy request and refuse the incoming request with `500 Server Internal Error`. If all of the `Privacy` header values are recognised by the feature, then the request will be handled as per normal behaviour.

Recognised privacy header values are: `header`, `user`, `session`, `history`, `id`, `none`, `critical`.

=== SIP Header Manipulation

The primary purpose of MMTelOIP is to remove and anonymize headers that the originating UE and the OIR service requested to be removed or anonymized.

==== MMTelOIP Active

MMTel OIP is treated as active when `MMTelOIPServiceData.OperatorAuthorized` and `MMTelOIPServiceData.Active` are `true`

Table 1. SIP header manipulation when MMTelOIP is active
SIP Header [1] | Originating Subscriber’s Privacy Setting
--- | ---
User | Header | Session | Id | History | None [2]
Outgoing Requests to the Terminating Subscriber
Call-Info | Removed |  |  |  |  |
Contact |  | Anonymized |  |  |  |
From | Anonymized |  |  |  |  |
History-Info [3] |  | Removed | Removed |  | Removed |
In-Reply-To | Removed |  |  |  |  |
Organization | Removed |  |  |  |  |
Privacy | Preserved | Preserved | Preserved | Preserved | Preserved | Preserved
Reply-To | Removed |  |  |  |  |
Subject | Removed |  |  |  |  |
User-Agent | Removed |  |  |  |  |
Outgoing Responses to the Terminating Subscriber
Call-Info | Removed |  |  |  |  |
History-Info [3] |  | Removed | Removed |  | Removed |
Organization | Removed |  |  |  |  |
Privacy | Preserved | Preserved | Preserved | Preserved | Preserved | Preserved
Reply-To | Removed |  |  |  |  |
Server | Removed |  |  |  |  |
Warning | Anonymized |  |  |  |  |

==== MMTelOIP Not Active

MMTel OIP is treated as not active when `MMTelOIPServiceData.OperatorAuthorized` or `MMTelOIPServiceData.Active` is `false`

Table 2. SIP header manipulation when MMTelOIP is not active.
SIP Header [1] | Originating Subscriber’s Privacy Setting
--- | ---
User | Header | Session | Id | History | None [2]
Outgoing Requests to the Terminating Subscriber
Call-Info | Removed |  |  |  |  |
Contact |  | Anonymized |  |  |  |
From | Anonymized | Anonymized if the Network Operator Setting AnonymizeFromPolicy is set to `ANONYMIZE`
History-Info [3] |  | Removed | Removed |  | Removed |
In-Reply-To | Removed |  |  |  |  |
Organization | Removed |  |  |  |  |
Privacy | Removed | Removed | Removed | Removed | Removed | Removed
Reply-To | Removed |  |  |  |  |
Subject | Removed |  |  |  |  |
User-Agent | Removed |  |  |  |  |
Outgoing Responses to the Terminating Subscriber
Call-Info | Removed |  |  |  |  |
History-Info [3] |  | Removed | Removed |  | Removed |
Organization | Removed |  |  |  |  |
Privacy | Removed | Removed | Removed | Removed | Removed | Removed
Reply-To | Removed |  |  |  |  |
Server | Removed |  |  |  |  |
Warning | Anonymized |  |  |  |  |

=== Custom Header Privacy Rules

The MMTelOIP feature has support for configuring custom rules that instruct the feature to remove additional headers depending on the message type and the value of the `Privacy` header. These rules are defined in a profile table called `MMTelCustomHeaderPrivacyRules`. Rules are created on the `MMTel Custom Header Privacy Rules` tab on the MMTelOIP Feature Configuration page in REM. Each profile in the profile table represents a single rule for the feature to evaluate. The profile `Rule ID` is cosmetic, it can be any unique string. The profiles have the following fields:

Field Name | Type | Description
--- | --- | ---
    HeaderName
    String
| The name of the header that should be removed when this rule is applied to a message.
    ApplicableMessageTypeAsString
    Enumeration
| One of three values based on what type of message this rule should be applied to. Value must be one of: `REQUEST`, `RESPONSE`, or `BOTH`.
    ApplicablePrivacyHeaderValues
    String Array
| A list of `Privacy` header values that will trigger this rule.
    NetworkOperator
    String
| The name of the Network Operator this rule will be applied to. An empty string applies the rule to the platform overall.

| HeaderName matching is case-insensitive. Wildcards are not supported.

==== Black Listed SIP Headers

The following SIP headers can not be removed by MMTelOIP custom header privacy rules:

- From

- Call-ID

- Contact

- Content-Length

- CSeq

- Max-Forwards

- Record-Route

- Request-URI

- Route

- To

- Via

==== Rule Evaluation

Whenever the feature is processing a message, it will look for this profile table and check if there are any rules defined. If it finds rules, it will iterate through them and evaluate each one to determine if it should be applied to the message. For each rule, the evaluation process is as follows:

1. Check the Network Operator

The `NetworkOperator` field is compared to the Network Operator for the install. If it matches, the rule is applied. If `NetworkOperator` is an empty string, the rule is always applied.

2. Check the Message Type

The `ApplicableMessageType` field indicates what type of SIP message the rule should be applied to: `REQUEST` indicates the rule should be applied to SIP requests. `RESPONSE` indicates the rule should be applied to SIP responses. `BOTH` indicates the rule should be applied to all SIP messages.

3. Check the Privacy Header

The feature will look at the value(s) of the `Privacy` header on the message and compare them to the `ApplicablePrivacyHeaderValues` for the rule. If any one value of the `Privacy` header matches any one value in the `ApplicablePrivacyHeaderValues` field, the rule applies.

4. Apply Rule

If the previous two checks both indicate the rule should be applied, the feature will strip all headers from the message that match the `HeaderName` field of the rule.

= MMTelOIR :indexpage: :toc: macro :toclevels: 4 :toc-title: On this page…​

The MMTelOIR feature implements the Originating Identification Restriction (OIR) service .

== What is OIR?

From 3GPP 24.607:

| The Originating Identification Restriction (OIR) service enables the originating user to prevent presentation of its identity information to the terminating user. When the OIR service is applicable and activated, the originating network provides the destination network with the indication that the originating user’s identity information is not allowed to be presented to the terminating user. In this case, no originating user’s identity information shall be included in the requests sent to the terminating user. The presentation restriction function shall not influence the forwarding of the originating user’s identity information within the network as part of the supplementary service procedures.

== Feature cheat sheet

B2BUA Instance | SAS Support | Originating / Terminating | Point in Session Plan | Network Operator Data | Subscriber Data | Stateful or Stateless | POJO Feature or SBB Feature
--- | --- | --- | --- | --- | --- | --- | ---
MMTEL | Yes | Originating |
    SipAccess_SubscriberPreCreditCheck
| Yes | Yes | Stateless | POJO

== Prerequisite features

These features must run before OIR:

- DetermineCallType

- SubscriberDataLookupFromHSS or SubscriberDataLookupFromHLR

== Source Code

This feature’s source code is available in the Sentinel VoLTE SDK in the `mmtel-id-presentation-restriction` module pack. It can be viewed by using the `create-module` command in the SDK with that module pack, for example:

`> create-module new-idpr-module opencloud#mmtel-id-presentation-restriction#volte/3.1.0;3.1.0.0`

This command will prompt you for information needed to create the new modules, once completed the original source for the feature can be found in the new modules.

The module-pack includes the following modules relevant to this feature:

Module Name | Description
--- | ---
mmtel-id-presentation-restriction | Group module for the feature that includes all of the modules listed below.
mmtel-id-presentation-restriction-library | Contains code shared by all ID presentation and restriction features.
mmtel-oir-profile | Contains the profile specification for the feature configuration profile table.
mmtel-oir | Contains the feature itself.

== Network operator data

OIR Network Operator Data is present in a JSLEE configuration profile table named `MMTelOIRConfigProfileTable`. The operator data is scoped according to a Sentinel selection key.

Attribute Name | Type | Description
--- | --- | ---
    OIRMode (deprecated, present in MMTelOIRServiceData)
| An enum with two values: `PERMANENT` and `TEMPORARY`. Fully qualified type name is `com.opencloud.volte.sentinel.simservs.xcap.IdentityPresentationModeType` |
    OIRPresentationRestrictionType
| An enum with two values: `ONLY_IDENTITY` and `ALL_PRIVATE_INFORMATION`. Fully qualified type name is `com.opencloud.volte.sentinel.simservs.xcap.IdentityPresentationRestrictionType`. | Use of `ALL_PRIVATE_INFORMATION` means the `Privacy` header is set to `Privacy:header` Use of `ONLY_IDENTITY` means that the `Privacy` header is set to `Privacy:id`.
    OIRUserPolicy
| An enum with three values: `NONE`, `ANONYMIZE_FROM`, and `ADD_USER_PRIVACY`. Fully qualified type name is `com.opencloud.mmtel.sentinel.feature.common.IdentificationRestriction.UserPolicy`. |

=== Default for network operator data

Attribute | Default value
--- | ---
    MMTelOIRServiceData.Mode
    TEMPORARY
    OIRPresentationRestrictionType
    ONLY_IDENTITY
    OIRUserPolicy
    NONE

== Session input variables

Variable name | Type | Comments
--- | --- | ---
    MMTelOIRServiceData
| Complex | Stored from the HSS or HLR in SubscriberDataLookupFromHSS or SubscriberDataLookupFromHLR
    DialledCallerIDRestriction
| DialledCallerIDRestrictionType | Used to override `PRESENTATION_RESTRICTION` behavior, valid values are `OIR_AS_CONFIGURED`, `OIR_CALLER_ID_BLOCK` and `OIR_CALLER_ID_UNBLOCK`

== Session output variables

Variable name | Type | Comments
--- | --- | ---
    RanOir
| boolean | Signals to other features that OIR ran on this session.

== Statistics

MMTelOIR statistics are tracked by the sentinel.volte.sip SBB and can be found under the following parameter set:
SLEE-Usage → sentinel.volte.sip service → sentinel.volte.sip SBB

Statistic | Increments when…​
--- | ---
    Started
| the feature runs
    FailedToStart
| Sentinel VoLTE encounters an error while attempting to start the feature
    IssuedWarning
| a non-fatal problem is encountered and the feature issues a warning
    FailedDuringExecution
| a fatal problem is encountered and the feature cannot execute correctly
    TimedOut
| the feature takes too long to complete and Sentinel VoLTE aborts execution
    Misconfigured
| a fatal error if the feature configuration can not be loaded
    ReceivedMalformedPrivacyHeader
| a non-standard `Privacy` header is found in an incoming SIP message
    FromHeaderAnonymized
| the feature anonymizes the `From` header in an outgoing SIP message
    PrivacyHeaderChanged
| the feature changes the contents of the `Privacy` header on an outgoing SIP message

== Behaviour

If operator data is not present, the OIR feature:

1. Increments an error statistic.

2. Logs a message at the `Fine` level.

3. Informs the Sentinel core that the feature is not configured appropriately (`Invalid Configuration`).

4. Exits.

If `MMTelOIRServiceData.OperatorAuthorized` or `MMTelOIRServiceData.Active` is `false`, the feature finishes execution without modifying any state.

The rest of the behaviour section assumes that `MMTelOIRServiceData.Active` is `true`.

=== Temporary mode vs permanent mode

OIR behaves in temporary mode if the network configuration for `MMTelOIRServiceData.Mode` is set to `TEMPORARY`

It behaves in permanent mode if the network configuration for `MMTelOIRServiceData.Mode` is set to `PERMANENT`.

The UE signals its request for privacy through use of the `Privacy` header.

==== Adjustments to identity headers in temporary mode

When in temporary mode, the OIR feature will apply header manipulation related to privacy, based on:

- the value of `DialledCallerIDRestriction` session state field,

- whether or not the UE’s request has any `Privacy` header at all,

- whether or not the `Privacy` header indicates that privacy should be enabled or disabled (for this dialog), and

- the value of `MMTelOIRServiceData.DefaultBehaviourType`.

The value of `OirPerCallOverride` is used to modify privacy values as follows:

OIROverrideType | Resulting 'Privacy' header
--- | ---
    OIR_AS_CONFIGURED
| 'Privacy' header unchanged
    OIR_CALLER_ID_BLOCK
| 'Privacy' header with 'Privacy:user'
    OIR_CALLER_ID_UNBLOCK
| 'Privacy' header with 'Privacy:none'

Any changes are then treated as if the request has come from the UE and manipulation continues as follows:

UE request | Value of MMTelOIRServiceData.DefaultBehaviourType | Privacy based header manipulation occurs
--- | --- | ---
No `Privacy` header |
    PRESENTATION_RESTRICTED
| Yes
`Privacy` header with `Privacy:none` (UE is asking for no privacy) |
    PRESENTATION_RESTRICTED
| No
UE asks for privacy —`Privacy` header exists, and set to `Privacy:id`, or `Privacy:header`, or `Privacy:user` |
    PRESENTATION_RESTRICTED
| Yes
No `Privacy` header |
    PRESENTATION_NOT_RESTRICTED
| No
`Privacy` header with `Privacy:none` (UE is asking for no privacy) |
    PRESENTATION_NOT_RESTRICTED
| No
UE asks for privacy —`Privacy` header exists, and set to `Privacy:id`, or `Privacy:header`, or `Privacy:user` |
    PRESENTATION_NOT_RESTRICTED
| Yes

==== Adjustments to identity headers in permanent mode

When in permanent mode, the OIR feature will apply header manipulation related to privacy regardless of whether or not the UE’s request indicated that privacy is requested. Whether or not anything is modified is based on the value of the `MMTelOIRServiceData.DefaultBehaviourType` session state variable. The value of `PRESENTATION_NOT_RESTRICTED` means that the OIR feature will not modify header manipulation related to privacy.

UE request indicates privacy shall apply | Value of MMTelOIRServiceData.DefaultBehaviourType | Privacy-based header manipulation occurs
--- | --- | ---
N/A (the UE is ignored) |
    PRESENTATION_RESTRICTED
| Yes
N/A (the UE is ignored) |
    PRESENTATION_NOT_RESTRICTED
| No

=== Headers read and modified in SIP INVITE

Information about headers that are modified under different conditions are documented on the following links:

- MMTel OIR Header Manipulation - OIRMode = TEMPORARY

- MMTel OIR Header Manipulation - OIRMode = PERMANENT

A few of the options are in the table below. For more refer to the links above.

MMTelOIRServiceData.Mode (operator data) | MMTelOIRServiceData.DefaultBehaviourType (subscriber) | OIRPresentationRestrictionType (network data) | OIRUserPolicy (network data) | Link
--- | --- | --- | --- | ---
TEMPORARY |
    PRESENTATION_NOT_RESTRICTED
    ONLY_IDENTITY
    NONE
| link
TEMPORARY |
    PRESENTATION_NOT_RESTRICTED
    ONLY_IDENTITY
    ANONYMIZE_FROM
| link
TEMPORARY |
    PRESENTATION_NOT_RESTRICTED
    ONLY_IDENTITY
    ADD_USER_PRIVACY
| link
TEMPORARY |
    PRESENTATION_RESTRICTED
    ONLY_IDENTITY
    NONE
| link
TEMPORARY |
    PRESENTATION_RESTRICTED
    ONLY_IDENTITY
    ANONYMIZE_FROM
| link
TEMPORARY |
    PRESENTATION_RESTRICTED
    ONLY_IDENTITY
    ADD_USER_PRIVACY
| link

=== Graceful handling of terminating access

OIR is an originating feature. It will finish execution without modifying any state if it is invoked in a terminating attempt.

= MMTel OIR Header Manipulation :toc: macro :toclevels: 4 :toc-title: On this page…​

== OIRMode=TEMPORARY === OIRMode=TEMPORARY - OIRDefaultBehaviourType=PRESENTATION_NOT_RESTRICTED In this mode the network default is to not restrict the originating user identity. If the originating user wishes to override the "no restriction" default the UE of the originating user will add Privacy header set to the value "id", "header" or "user".

If the OIRDefaultBehaviourType is set to PRESENTATION_NOT_RESTRICTED and the request received contains Privacy header with value set to "id" or "header" (user is temporarily requesting privacy) the AS of originating user shall either (as a matter of operator policy):

- Add Privacy value set to "user", or

- change the From header value to remove the originating user identity.

In the example below, AS change the From header to anonymous values while preserving the privacy header value:

INVITE incoming, Privacy requested in TEMPORARY mode with default behaviour of PRESENTATION_NOT_RESTRICTED

    1: INVITE sip:userB_public1@home1.net;gr=2ad8950e-48a5-4a74-8d99-ad76cc7fc74c SIP/2.0
    ...
    10: From: <sip:userA_public1@home1.net>;tag=171828
    18: Contact: <sip:userA_public1@home1.net;gr=urn:uuid:388s9-48js9-37749-3774-usuw8u38;comp=sigcomp>;+g.3gpp.icsi - ref="urn%3Aurn-7%3gpp-service.ims.icsi.mmtel"
    30: P-Asserted-Identity: "John Doe" <sip:userA_public1@home1.net>
    30: Privacy: id
    ...

INVITE outgoing, Privacy respected, From header anonymized

    1: INVITE sip:userB_public1@home1.net;gr=2ad8950e-48a5-4a74-8d99-ad76cc7fc74c SIP/2.0
    ...
    10: From: <sip:anonymous@anonymous.invalid>;tag=637364
    18: Contact: <sip:userA_public1@home1.net;gr=urn:uuid:388s9-48js9-37749-3774-usuw8u38;comp=sigcomp>;+g.3gpp.icsi - ref="urn%3Aurn-7%3gpp-service.ims.icsi.mmtel"
    30: P-Asserted-Identity: "John Doe" <sip:userA_public1@home1.net>
    31: Privacy: id
    ...

==== OIRMode=TEMPORARY - OIRDefaultBehaviourType=PRESENTATION_NOT_RESTRICTED - OIRUserPolicy=NONE No action is required at AS of originating user. Unrestricted privacy level is overridden by UE setting the Privacy header value to an appropriate value (other than none).

==== OIRMode=TEMPORARY - OIRDefaultBehaviourType=PRESENTATION_NOT_RESTRICTED - OIRUserPolicy=ANONYMIZE_FROM AS of originating user shall set/adjust value of the Privacy header in the request received depending on precondition.

Precondition | Action of AS originating user
--- | ---
    Privacy header value contains id or header or both values
    1. Set URI of the From header to sip:anonymous@anonymous.invalid
    2. Set display name of the From header to "Anonymous"

==== OIRMode=TEMPORARY - OIRDefaultBehaviourType=PRESENTATION_NOT_RESTRICTED - OIRUserPolicy=ADD_USER_PRIVACY AS of originating user shall set/adjust value of the Privacy header in the request received depending on precondition.

Precondition | Action of AS originating user
--- | ---
    No Privacy header
    No action
    Privacy header value set to none
    No Action
    Privacy header value set to header
    Unless already included add value user
    Privacy header value set to id
    Unless already included add value user
    Privacy header value set to id and header
    Unless already included add value user

=== OIRMode=TEMPORARY - OIRDefaultBehaviourType=PRESENTATION_RESTRICTED In this mode the network default is to restrict the originating user identity. The default is overridden by UE inserting Privacy header set to value "none" in a received request.

If request contains no Privacy header or the Privacy header is not set to the value of "none" then the AS of originating user shall insert Privacy header with value to "id" or "header" according to the Restriction Privacy Attribute.

In the example below the privacy option id is added (asserted identity restriction option):

INVITE incoming, Privacy overridden by UE, OIRMode=TEMPORARY and OIRDefaultBehaviourType=PRESENTATION_RESTRICTED

    1: INVITE sip:userB_public1@home1.net;gr=2ad8950e-48a5-4a74-8d99-ad76cc7fc74c SIP/2.0
    ...
    10: From: <sip:userA_public1@home1.net>;tag=171828
    18: Contact: <sip:userA_public1@home1.net;gr=urn:uuid:388s9-48js9-37749-3774-usuw8u38;comp=sigcomp>;+g.3gpp.icsi - ref="urn%3Aurn-7%3gpp-service.ims.icsi.mmtel"
    30: P-Asserted-Identity: "John Doe" <sip:userA_public1@home1.net>
    30: Privacy: user
    ...

In the below example, the UE sets the privacy value of "none" in the received request indicates user’s preference to override the PRESENTATION_RESTRICTED default. In this case, headers P-Asserted-Identity and Privacy with value set to "none" will be forwarded by AS unchanged.

INVITE incoming, Privacy overridden by UE, OIRMode=TEMPORARY and OIRDefaultBehaviourType=PRESENTATION_RESTRICTED

    1: INVITE sip:userB_public1@home1.net;gr=2ad8950e-48a5-4a74-8d99-ad76cc7fc74c SIP/2.0
    ...
    10: From: <sip:userA_public1@home1.net>;tag=171828
    18: Contact: <sip:userA_public1@home1.net;gr=urn:uuid:388s9-48js9-37749-3774-usuw8u38;comp=sigcomp>;+g.3gpp.icsi - ref="urn%3Aurn-7%3gpp-service.ims.icsi.mmtel"
    30: P-Asserted-Identity: "John Doe" <sip:userA_public1@home1.net>
    30: Privacy: none
    ...

=== OIRMode=TEMPORARY - OIRDefaultBehaviourType=PRESENTATION_RESTRICTED - OIRPresentationRestrictionType=ONLY_IDENTITY - OIRUserPolicy=NONE AS of originating user shall set/adjust value of the Privacy header in the request received depending on precondition.

Precondition | Action of AS originating user
--- | ---
    No Privacy header
    Add Privacy header set to value id
    Privacy header value set to none
    No Action
    Privacy header value doesn’t include id
    Add value id

=== OIRMode=TEMPORARY - OIRDefaultBehaviourType=PRESENTATION_RESTRICTED - OIRPresentationRestrictionType=ONLY_IDENTITY - OIRUserPolicy=ANONYMISE_FROM AS of originating user shall set/adjust value of the Privacy header in the request received depending on precondition.

Precondition | Action of AS originating user
--- | ---
    No Privacy header
    1. Add Privacy header set to value id
    2. Set URI of the From header to sip:anonymous@anonymous.invalid
    3. Set display name of the From header to "Anonymous"
    Privacy header value set to none
    No Action
    Privacy header value doesn’t include id
    1. Add value id
    2. Set URI of the From header to sip:anonymous@anonymous.invalid
    3. Set display name of the From header to "Anonymous"

=== OIRMode=TEMPORARY - OIRDefaultBehaviourType=PRESENTATION_RESTRICTED - OIRPresentationRestrictionType=ONLY_IDENTITY - OIRUserPolicy=ADD_USER_PRIVACY AS of originating user shall set/adjust value of the Privacy header in the request received depending on precondition.

Precondition | Action of AS originating user
--- | ---
    No Privacy header
    Add Privacy header set to value id and user
    Privacy header value set to none
    No Action
    Privacy header value doesn’t include id
    1. Add value id
    2. Add value user unless already included

=== OIRMode=TEMPORARY - OIRDefaultBehaviourType=PRESENTATION_RESTRICTED - OIRPresentationRestrictionType=ALL_PRIVATE_INFORMATION - OIRUserPolicy=NONE AS of originating user shall set/adjust value of the Privacy header in the request received depending on precondition.

Precondition | Action of AS originating user
--- | ---
    No Privacy header
    Add Privacy header set to value header
    Privacy header value set to none
    No Action
    Privacy header value doesn’t include header
    Add value header

=== OIRMode=TEMPORARY - OIRDefaultBehaviourType=PRESENTATION_RESTRICTED - OIRPresentationRestrictionType=ALL_PRIVATE_INFORMATION - OIRUserPolicy=ANONYMIZE_FROM AS of originating user shall set/adjust value of the Privacy header in the request received depending on precondition.

Precondition | Action of AS originating user
--- | ---
    No Privacy header
    1. Add Privacy header set to value header
    2. Set URI of the From header to sip:anonymous@anonymous.invalid
    3. Set display name of the From header to "Anonymous"
    Privacy header value set to none
    No Action
    Privacy header value doesn’t include header
    1. Add value header
    2. Set URI of the From header to sip:anonymous@anonymous.invalid
    3. Set display name of the From header to "Anonymous"

=== OIRMode=TEMPORARY - OIRDefaultBehaviourType=PRESENTATION_RESTRICTED - OIRPresentationRestrictionType=ALL_PRIVATE_INFORMATION - OIRUserPolicy=ADD_USER_PRIVACY AS of originating user shall set/adjust value of the Privacy header in the request received depending on precondition.

Precondition | Action of AS originating user
--- | ---
    No Privacy header
    Add Privacy header set to value header and user
    Privacy header value set to none
    No Action
    Privacy header value doesn’t include header
    1. Add value header
    2. Add value user unless already included

== OIRMode=PERMANENT In a simple scenario, the AS of the originating user must inspect the identity of the originating caller.

- If Privacy header is not present AS must insert Privacy header set to header information

- If Privacy header is present and does not include values "id" or "header" corresponding to subscription restriction option AS must insert the appropriate value.

- If Privacy header is present and includes value "none" this value must be removed

The Privacy value of "id" is selected when "restrict asserted identity" restriction option is subscribed to. The Privacy value of "header" is selected when "restrict all private header information" restriction option is subscribed to.

Additionally, as an operator option From header can be anonymized or Privacy header value "user" added. The latter shall mandate AS of terminating user to anonymize all user configurable headers before forwarding the request to terminating P-CSCF. In case of internetworking, IBCF will be responsible for stripping identity headers and anonymizing other headers before forwarding the request into untrusted network.

Where From header is required to be anonymized the URI value shall be set to the value "sip:anonymous@anonymous.invalid".

Typically, the originating UE would already have the Privacy header value set correctly, however, since UE is considered to be untrusted entity AS must apply these procedures.

Example of Privacy header received from S-CSCF without privacy being requested by UE:

INVITE incoming, no Privacy

    1: INVITE sip:userB_public1@home1.net;gr=2ad8950e-48a5-4a74-8d99-ad76cc7fc74c SIP/2.0
    ...
    10: From: <sip:userA_public1@home1.net>;tag=171828
    18: Contact: <sip:userA_public1@home1.net;gr=urn:uuid:388s9-48js9-37749-3774-usuw8u38;comp=sigcomp>;+g.3gpp.icsi - ref="urn%3Aurn-7%3gpp-service.ims.icsi.mmtel"
    30: P-Asserted-Identity: "John Doe" <sip:userA_public1@home1.net>
    30: Privacy: none
    ...

AS adjusts the value of Privacy header by removing "none" and adding "id" (restrict asserted identity option):

INVITE outgoing, Privacy set

    1: INVITE sip:userB_public1@home1.net;gr=2ad8950e-48a5-4a74-8d99-ad76cc7fc74c SIP/2.0
    ...
    10: From: <sip:userA_public1@home1.net>;tag=637364
    18: Contact: <sip:userA_public1@home1.net;gr=urn:uuid:388s9-48js9-37749-3774-usuw8u38;comp=sigcomp>;+g.3gpp.icsi - ref="urn%3Aurn-7%3gpp-service.ims.icsi.mmtel"
    30: P-Asserted-Identity: "John Doe" <sip:userA_public1@home1.net>
    31: Privacy: id
    ...

Example of anonymization of the From header in the outgoing INVITE (operator option):

INVITE outgoing, Privacy set, From header anonymized

    1: INVITE sip:userB_public1@home1.net;gr=2ad8950e-48a5-4a74-8d99-ad76cc7fc74c SIP/2.0
    ...
    10: From: <sip:anonymous@anonymous.invalid>;tag=637364
    18: Contact: <sip:userA_public1@home1.net;gr=urn:uuid:388s9-48js9-37749-3774-usuw8u38;comp=sigcomp>;+g.3gpp.icsi - ref="urn%3Aurn-7%3gpp-service.ims.icsi.mmtel"
    30: P-Asserted-Identity: "John Doe" <sip:userA_public1@home1.net>
    31: Privacy: id
    ...

=== OIRMode=PERMANENT - OIRDefaultBehaviourType=PRESENTATION_RESTRICTED - OIRPresentationRestrictionType=ONLY_IDENTITY - OIRUserPolicy=NONE AS of originating user shall set/adjust value of the Privacy header in the request received depending on precondition.

Precondition | Action of AS originating user
--- | ---
    No Privacy header
    Insert header "Privacy: id"
    Privacy header value set to none
    Replace value none with id
    Privacy header exists but doesn’t include value id
    Add value id

=== OIRMode=PERMANENT - OIRDefaultBehaviourType=PRESENTATION_RESTRICTED - OIRPresentationRestrictionType=ONLY_IDENTITY - OIRUserPolicy=ANONYMIZE_FROM * Replace URI of the From header to sip:anonymous@anonymous.invalid * Set the From header display name to "Anonymous"

=== OIRMode=PERMANENT - OIRDefaultBehaviourType=PRESENTATION_RESTRICTED - OIRPresentationRestrictionType=ONLY_IDENTITY - OIRUserPolicy=ADD_USER_PRIVACY AS of originating user shall set/adjust value of the Privacy header in the request received depending on precondition.

Precondition | Action of AS originating user
--- | ---
    No Privacy header
    Insert header "Privacy: id;user"
    Privacy header value set to none
    Replace value none with id;user
    Privacy header exists but doesn’t include value id or user
    Add value id or user to make sure both are included

=== OIRMode=PERMANENT - OIRDefaultBehaviourType=PRESENTATION_RESTRICTED - OIRPresentationRestrictionType=ALL_PRIVATE_INFORMATION - OIRUserPolicy=NONE AS of originating user shall set/adjust value of the Privacy header in the request received depending on precondition.

Precondition | Action of AS originating user
--- | ---
    No Privacy header
    Insert header "Privacy: header"
    Privacy header value set to none
    Replace value none with header
    Privacy header exists but doesn’t include value header
    Add value header

=== OIRMode=PERMANENT - OIRDefaultBehaviourType=PRESENTATION_RESTRICTED - OIRPresentationRestrictionType=ALL_PRIVATE_INFORMATION - OIRUserPolicy=ANONYMIZE_FROM * Replace URI of the From header to sip:anonymous@anonymous.invalid * Set the From header display name to "Anonymous"

=== OIRMode=PERMANENT - OIRDefaultBehaviourType=PRESENTATION_RESTRICTED - OIRPresentationRestrictionType=ALL_PRIVATE_INFORMATION - OIRUserPolicy=ADD_USER_PRIVACY AS of originating user shall set/adjust value of the Privacy header in the request received depending on precondition.

Precondition | Action of AS originating user
--- | ---
    No Privacy header
    Insert header "Privacy: header;user"
    Privacy header value set to none
    Replace value none with header;user
    Privacy header exists but doesn’t include value header or user
    Add value header or user to make sure both are included

= MMTelTIP :toc: macro :toclevels: 4 :toc-title: On this page…​

The MMTelTIP feature implements the Terminating Identification Presentation (TIP) service .

== What is TIP?

From 3GPP TS 24.608:

| The Terminating Identification Presentation (TIP) service provides the originating party with the possibility of receiving identity information in order to identify the terminating party. The network shall deliver the Terminating Identity to the originating party on communication acceptance regardless of the terminal capability to handle the information.

== Feature cheat sheet

B2BUA Instance | SAS Support | Originating / Terminating | Point(s) in Session Plan | Network Operator Data | Subscriber Data | Stateful or Stateless | POJO Feature or SBB Feature
--- | --- | --- | --- | --- | --- | --- | ---
MMTEL | Yes | Originating | SipAccess_SubscriberCheck, and SipAccess_PartyResponse | No | Yes | Stateless — the feature is stateless, even though it is to be invoked at multiple feature execution points | POJO

== Prerequisite features

These features must run before TIP:

- DetermineCallType

- SubscriberDataLookupFromHSS or SubscriberDataLookupFromHLR

== Source Code

This feature’s source code is available in the Sentinel VoLTE SDK in the `mmtel-id-presentation-restriction` module pack. It can be viewed by using the `create-module` command in the SDK with that module pack, for example:

`> create-module new-idpr-module opencloud#mmtel-id-presentation-restriction#volte/3.1.0;3.1.0.0`

This command will prompt you for information needed to create the new modules, once completed the original source for the feature can be found in the new modules.

The module-pack includes the following modules relevant to this feature:

Module Name | Description
--- | ---
mmtel-id-presentation-restriction | Group module for the feature that includes all of the modules listed below.
mmtel-id-presentation-restriction-library | Contains code shared by all ID presentation and restriction features.
mmtel-tip-profile | Contains the profile specification for the feature configuration profile table.
mmtel-tip | Contains the feature itself.

== Network operator data

There is no network operator data.

== Session input variables

TIP requires the following session state input variables:

Variable name | Type | Comments
--- | --- | ---
    MMTelTIPServiceData
| Complex | Read from the HSS or HLR in SubscriberDataLookupFromHSS or SubscriberDataLookupFromHLR
    APartyFromHeaderAnonymized
| boolean | Used to determine whether the "from-change" tag needs to be removed from outgoing responses.

== Session output variables

Variable name | Type | Comments
--- | --- | ---
    RanTip
| boolean | Signals to other features that TIP ran on this session.

== Statistics

MMTelTIP statistics are tracked by the sentinel.volte.sip SBB and can be found under the following parameter set in REM:
SLEE-Usage → sentinel.volte.sip service → sentinel.volte.sip SBB → feature → MMTelTIP
or with rhino-stats:
SLEE-Usage → [sentinel.volte.sip service name] → [sentinel.volte.sip SBB name] → .feature.MMTelTIP

Statistic | Incremented when…​
--- | ---
    Started
| the feature runs
    FailedToStart
| Sentinel VoLTE encounters an error while attempting to start the feature
    IssuedWarning
| a non-fatal problem is encountered and the feature issues a warning
    FailedDuringExecution
| a fatal problem is encountered and the feature cannot execute correctly
    TimedOut
| the feature takes too long to complete and Sentinel VoLTE aborts execution
    ProcessingResponse
| the feature processes a SIP response
    ProcessingRequest
| the feature processes a SIP request
    OverrideCategoryTriggered
| the feature disregards requested privacy settings on an incoming SIP message (due to the subscriber having override category status)
    FromChangeTagRemoved
| the feature removes the `from-change` tag from a `Supported` header in the outgoing SIP message
    PrivacyHeaderChanged
| the feature changes the contents of the `Privacy` header on an outgoing SIP message

== Behaviour

TIP may modify the `INVITE` traversing through from A to B, and may modify responses from B to A.

MMTel TIP is treated as active when `MMTelTIPServiceData.OperatorAuthorized` and `MMTelTIPServiceData.Active` are `true`.

MMTel TIP is treated as not active when `MMTelTIPServiceData.OperatorAuthorized` or `MMTelTIPServiceData.Active` is `false`

=== Header manipulation behaviour

SIP Operation | TIPActive | Originating User TIP Override Category | Action(s)
--- | --- | --- | ---
`INVITE` | No | N/A | Remove option tag `from-change` from `INVITE` (if present).
`INVITE` | Yes | N/A | Forward `INVITE` as is.
Response from B party | Yes/No | Yes | Remove `Privacy` header (if present) remove "from-change" tag if `From` header was anonymised by OIR/OIP.
Response from B party | No | No | Remove `P-Asserted-Identity` header Remove `Privacy` headers (if present) Remove "from-change" tag if `From` header was anonymised by OIR/OIP.
Response from B party | Yes | No | Remove "from-change" tag if `From` header was anonymised by OIR/OIP.

=== Graceful handling of terminating access

TIP is an originating feature. It will finish execution without modifying any state if it is invoked in a terminating attempt.

= MMTelTIR :toc: macro :toclevels: 4 :toc-title: On this page…​

The MMTelTIR feature implements the Terminating Identification Restriction (TIR) service .

== What is TIR?

From 3GPP TS 24.608:

| The Terminating Identification Restriction (TIR) is a service offered to the terminating party which enables the terminating party to prevent presentation of the terminating identity information to originating party.

== Feature cheat sheet

B2BUA Instance | SAS Support | Originating / Terminating | Point(s) in Session Plan | Network Operator Data | Subscriber Data | Stateful or Stateless | POJO Feature or SBB Feature
--- | --- | --- | --- | --- | --- | --- | ---
MMTEL | Yes | Terminating |
    SipAccess_SubscriberPreCreditCheck

    SipAccess_PartyResponse
| Yes | Yes, loaded from HSS | Stateless | POJO

== Prerequisite features

These features must run before TIR:

- DetermineCallType

- SubscriberDataLookupFromHSS or SubscriberDataLookupFromHLR

== Source Code

This feature’s source code is available in the Sentinel VoLTE SDK in the `mmtel-id-presentation-restriction` module pack. It can be viewed by using the `create-module` command in the SDK with that module pack, for example:

`> create-module new-idpr-module opencloud#mmtel-id-presentation-restriction#volte/3.1.0;3.1.0.0`

This command will prompt you for information needed to create the new modules, once completed the original source for the feature can be found in the new modules.

The module-pack includes the following modules relevant to this feature:

Module Name | Description
--- | ---
mmtel-id-presentation-restriction | Group module for the feature that includes all of the modules listed below.
mmtel-id-presentation-restriction-library | Contains code shared by all ID presentation and restriction features.
mmtel-tir-profile | Contains the profile specification for the feature configuration profile table.
mmtel-tir | Contains the feature itself.

== Network operator data

TIR’s Network Operator Data is held in a JSLEE configuration profile table named `MMTelTIRConfigProfileTable`. This data is scoped by sentinel selection key — each network operator has one entry in the table.

    Attribute Name
| Type
    TIRMode (deprecated, present in MMTelTIRServiceData)
| An enum with values `PERMANENT`, and `TEMPORARY`. Fully qualified class name is `com.opencloud.volte.sentinel.simservs.xcap.IdentityPresentationModeType`

== Session input variables

Variable name | Type | Comments
--- | --- | ---
    MMTelTIRServiceData
| Complex | Loaded from the HSS in SubscriberDataLookupFromHSS or from HLR in SubscriberDataLookupFromHLR

== Session output variables

Variable name | Type | Comments
--- | --- | ---
    RanTir
| boolean | Signals to other features that TIR ran on this session.

== Statistics

MMTelTIR statistics are tracked by the sentinel.volte.sip SBB and can be found under the following parameter set in REM:
SLEE-Usage → sentinel.volte.sip service → sentinel.volte.sip SBB → feature → MMTelTIR
or with rhino-stats:
SLEE-Usage → [sentinel.volte.sip service name] → [sentinel.volte.sip SBB name] → .feature.MMTelTIR

Statistic | Incremented when…​
--- | ---
    Started
| the feature runs
    FailedToStart
| Sentinel VoLTE encounters an error while attempting to start the feature
    IssuedWarning
| a non-fatal problem is encountered and the feature issues a warning
    FailedDuringExecution
| a fatal problem is encountered and the feature cannot execute correctly
    TimedOut
| the feature takes too long to complete and Sentinel VoLTE aborts execution
    ProcessingResponse
| the feature processes a SIP response
    ProcessingRequest
| the feature processes a SIP request
    FromChangeTagRemoved
| the feature removes the `from-change` tag from a `Supported` header in the outgoing SIP message
    ReceivedMalformedPrivacyHeader
| a non-standard `Privacy` header is found in an incoming SIP message
    PrivacyHeaderChanged
| the feature changes the contents of the `Privacy` header on an outgoing SIP message

== Behaviour

If operator data is not present, the TIR feature:

1. Increments an error statistic.

2. Logs a message at the `Fine` level.

3. Informs the Sentinel core that the feature is not configured appropriately (`Invalid Configuration`).

4. Exits.

If `MMTelTIRServiceData.OperatorAuthorized` is `false`, the feature finishes execution without modifying any state.

=== Header manipulation

MMTelTIRServiceData.Mode (Operator data) | SIP Operation | MMTelTIRServiceData.Active (Subscriber data) | MMTelTIRServiceData.DefaultBehaviourType (Subscriber data) | Action(s)
--- | --- | --- | --- | ---
TEMPORARY | `INVITE` | No |
    PRESENTATION_NOT_RESTRICTED
| See row for Temporary, Active, Presentation Not Restricted
TEMPORARY | B-Party Responses | No |
    PRESENTATION_NOT_RESTRICTED
| See row for Temporary, Active, Presentation Not Restricted
TEMPORARY | `INVITE` | No |
    PRESENTATION_RESTRICTED
| See row for Temporary, Active, Presentation Restricted
TEMPORARY | B-Party Responses | No |
    PRESENTATION_RESTRICTED
| See row for Temporary, Active, Presentation Restricted
TEMPORARY | `INVITE` | Yes |
    PRESENTATION_NOT_RESTRICTED
| Forward `INVITE` to B party
TEMPORARY | `INVITE` | Yes |
    PRESENTATION_RESTRICTED
| Forward `INVITE` to B party
TEMPORARY | B-Party Responses | Yes |
    PRESENTATION_NOT_RESTRICTED
| Forward Response to A party
TEMPORARY | B-Party Responses | Yes |
    PRESENTATION_RESTRICTED
| If a response does not contain a `Privacy` header, insert a `Privacy` with value set to `id`. If the response contains a `Privacy` header and the value is set to `none`, the AS shall leave the value unchanged. If the response contains a `Privacy` header with a value other than none, and if the value that does not include `id`, then add value `id`.
PERMANENT | INVITE | Yes |
    Behave as though PRESENTATION_RESTRICTED, regardless of tge configuration value.
| If INVITE contains an option-tag `from-change`, remove the option-tag and forward to B party
PERMANENT | B-Party Responses | Yes |
    Behave as though PRESENTATION_RESTRICTED regardless of configuration value
| If a response does not contain a `Privacy` header, insert a `Privacy` with value set to `id`. If the response contains a `Privacy` header and the value is set to `none`, the AS shall replace the value with the value `id`. If the response contains a `Privacy` header with a value other than none, and if the value that does not include `id`, then add value `id`.

=== Graceful handling of originating access

TIR is a terminating feature. It will finish execution without modifying any state if it is invoked in an originating attempt.

= MMTel Conference :indexpage: :toc: macro :toclevels: 4 :toc-title: On this page…​

This feature lets users create multi-party sessions between two or more parties .

== Feature cheat-sheet

B2BUA Instance | SAS Support | Originating / Terminating | Point(s) in Session Plan | Network Operator Data | Subscriber Data | Stateful or Stateless | POJO Feature or SBB Feature
--- | --- | --- | --- | --- | --- | --- | ---
MMTEL | Yes | Terminating | `SipAccess_PartyRequest` `SipAccess_PartyResponse` `SipAccess_SubscriberCheck` `SipAccess_ServiceTimer` `SipMidSession_PartyRequest` `SipMidSession_PartyResponse` `SubscriptionSipRequest` `SubscriptionSipResponse` `SipMidSession_CreditAllocatedPostCC` `SipMidSession_CreditLimitReachedPostCC` `SipMidSession_OCSFailurePostCC` `SipLegEnd` `SipEndSession` | Yes | No | Stateful | SBB with multiple FSMs encoded into session state

== Source Code

This feature’s source code is available in the Sentinel VoLTE SDK in the `mmtel-conferencing` module pack. It can be viewed by using the `create-module` command in the SDK with that module pack, for example:

`> create-module new-conf-module opencloud#mmtel-conferencing#volte/3.1.0;3.1.0.0`

This command will prompt you for information needed to create the new modules, once completed the original source for the feature can be found in the new modules.

The module-pack includes the following modules relevant to this feature:

Module Name | Description
--- | ---
mmtel-conferencing | Group module for the feature that includes all of the modules listed below.
mmtel-conf-library | Contains common code for the conference modules.
mmtel-conf-profile | Contains the profile specification for the conferencing configuration profile table.
mmtel-conf-view-profile | Contains the profile specification for the profile table used to track information about a conference.
mmtel-conf-event-schema-library | Generates java code for the the conference event XML schema.
mmtel-conf-msml-schema-library-dialogic | Generates java code for the MSML XML schema. Required for interaction with Dialogic MRF.
mmtel-conf-msml-schema-library-radisys | Generates java code for the MSML XML schema. Required for interaction with Radisys MRF.
mmtel-conf-mapper-library-dialogic | Mapper library that uses mmtel-conf-msml-schema-library-dialogic to create conference MSML.
mmtel-conf-mapper-library-radisys | Mapper library that uses mmtel-conf-msml-schema-library-radisys to create conference MSML.
mmtel-conf | Contains the feature itself.

== Subscriber data

Not applicable; the feature is generally available unless disabled at the network level.

== Network data

Data is stored in the `MMTelCONFConfigProfileTable` profile, which is initially set up by the installer.

Parameter | Type | Description | Default | Note
--- | --- | --- | --- | ---
    MRFURI
| String | SIP or TEL URI for the MRF | none |
    ICSCFURI
| String | SIP or TEL URI for the I-SCSCF | none | Mandatory when the `IsMrfRoutableViaIMS` option is set to True.
    AliasConferenceFactoryPSI
| String[] | Set of non-standard SIP or TEL URI that are recognised as a conferencing factory PSI | none |
    ConfMaxParticipants
| Integer {`0`, `3`, or greater} | Maximum number of participants; `0` = disabled | 3 |
    ConfCascadingEnabled
| Boolean | Allow other conference participants to cascade conferencing | true | Reserved. Current implementation ignores it. Cascading is not explicitly disabled.
    ConferenceViewRemovalDelay
| Long | Delay after conference ends before ConferenceView profiles are removed | none | Delay to allow all outstanding subscriptions to conference to end
    IsVideoConferenceAllowed
| Boolean | Policy setting that allows a video conference to be created or not | False |
    IsMrfRoutableViaIMS
| Boolean | Policy setting that specifies if calls to the MRF should be routed via IMS | False | If set to true, then the ICSCFURI has to be set
    AddOrigParameter
| Boolean | Indicates whether or not to add the orig URI parameter to the Route header for initiating calls to participants | True |
    RootOnSelector
| Boolean | Decides whether the 'root' element will be a child of the 'selector' element, otherwise will be a child of 'videolayout' | False |
    Bandwidth
| Integer | Bandwidth value to be used as an attribute of the 'root' element if not specified in INVITE SDP | 128 | Required for integration with Radisys MRF
    MinimumPictureInterval
| Integer | Mpi value to be used as an attribute of the 'root' element if not specified in INVITE SDP | 16 | Required for integration with Radisys MRF
    MaximumPictureSize
| String | Bpp value to be used as an attribute of the 'root' element if not specified in INVITE SDP | none | Required for integration with Radisys MRF
    Framesize
| Integer | Framesize value to be used as an attribute of the 'root' element if not specified in INVITE SDP | 396 | Required for integration with Radisys MRF
    ProfileLevelId
| String | ProfileLevelId value to be used as an attribute of the 'root' element if not specified in INVITE SDP | 00800a | Required for integration with Radisys MRF

== Description

Feature name | `MMTelCONF`
Applicable contexts | SIP service
Prerequisite features |

This feature allows a user to create a multi-party session between two or more parties. The feature is initially triggered when a subscriber (conference moderator) makes a call to the conference factory PSI that points towards a media server (MRFC/MRFP). Subsequently, the conference moderator joins one or more participants into the conference by creating a call leg between the media server and every participant. For every participant added to the conference the feature instructs the media server to join (or mix) media of the new participant with the conference session media. The feature enables n-way voice communication between all conference participants by mixing media from each participant session.

Conference moderator is a special role that allows adding and removing participants to and from a conference. Charging is correlated to the moderator session. Accordingly, all participants' sessions are terminated when the moderator disconnects.

The feature feeds conference state data into the MMTel Conference Subscription, which renders the state of a conference to arbitrary endpoints subscribed to the conference event package.

== Specification compliance

- IR.92 v9.0, section 2.3.3, Ad-Hoc Multi Party Conference of IR.92 IMS Profile for Voice and SMS

- IR.94 v10.0, section 2.3.3, Ad-Hoc Multi Party Conference of IR.94 IMS Profile for Conversational Video Service

- 3GPP 24.605 Conferencing using the IP Multimedia (IM) Core Network (CN) subsystem. Release 12.

- 3GPP TS 23.003 3rd Generation Partnership Project; Technical Specification Group Core Network and Terminals; Numbering, addressing and identification. Release 15.

- RFC3261 Session Initiation Protocol

- RFC4579 Session Initiation Protocol Call Control — Conferencing for User Agents

- RFC4575 A Session Initiation Protocol (SIP) Event Package for Conference State

- RFC3515 The Session Initiation Protocol (SIP) Refer Method

- RFC3891 The Session Initiation Protocol (SIP) “Replaces” Header

- RFC3892 The Session Initiation Protocol (SIP) Referred-By Mechanism

- RFC5707 Media Server Markup Language (MSML)

- RFC3265 SIP-Specific Event Notification

- RFC8086 (SIP) INFO Method and Package Framework

== Conferencing between three participants

Conference setup begins when the conference moderator establishes a session with the media server using the conferencing feature. Although not strictly a precondition, the conference moderator would have established sessions with party B and C (dialogs x and y). These are established outside the scope of the conferencing feature. The moderator dials a destination that is translated into a conference factory URI by the feature, and routed to the media server.

Additionally, when the moderator sets up a connection to the media server, the feature allocates a conference focus URI. It is an opaque SIP URI that identifies the conference instance, and essentially the multi-party session. The conference focus URI is used as a SIP target by all participants including the moderator for all subsequent SIP messaging.

Having set up the initial connection, the conference moderator creates a conference object and begins adding participants to the conference. It is a multi-step process that involves setting up new sessions with the new participants and interaction with the media server, using the MSML protocol over SIP/INFO as the protocol transaction transport. See Interaction with Media Server for details.

=== Three-party conference setup overview

When the moderator establishes the session with the media server (control connection) the conferencing feature:

- creates the MSML conferencing object and the first MSML connection for the moderator.

The moderator can then join a participant by creating a `SIP REFER` transaction on dialog A, where the `REFER` request has a `Refer-to` header with a URI header `Replaces` that references an existing call x between the moderator (user A) and prospective participant (user B).

The conferencing feature then:

- acknowledges the `REFER` request with a `202` response

- performs a charging authorization check

- if charging authorization check is successful, creates and links two SIP sessions:

  - the conferencing server and the media server (dialog B1)

  - the new participant and the conferencing server (dialog B)

| After dialog B has been successfully created, the corresponding call x is terminated by the UA of the user B, as a part of processing of the `INVITE` request with the `Replaces` header copied from the corresponding `REFER` request.

- re-uses the MSML conferencing object, and joins the participant into the conference.

Once successful, the first two participants are joined into the conference. Adding subsequent participants is an identical process.

=== Routing SIP traffic towards Media Server (MRF) through the IMS The MMTelCONF feature may directly contact a Media Server/Media Resource Function. This means that any INVITE from the feature is sent directly to the MRF. The Request URI of the outbound INVITE is set to the URI of the MRF.

This feature also supports routing INVITEs destined for the MRF through the IMS. In order to route through the IMS, the network configuration attribute IsMrfRoutableViaIMS must be set to true in the `MMTelCONFConfigProfileTable`

When this attribute is set to true and the initial INVITE from the conference moderator is received via the S-CSCF, the feature stores the Record-route SIP URI in the Session State attribute named SCSCFRouteAddress. In order to route the INVITE through the IMS, the feature retrieves the SIP URI (of the S-CSCF) from Session State, and places it as the topmost route header of the outbound INVITE.

The feature will also add a header parameter specified in configuration attribute RouteOrigUrlParameter to the Route header. For example, if parameter is set to value "orig" it will enable originating services to be run on outbound sessions from the conference server towards the conference participants.

=== Conference media Every conference participant establishes signalling and media sessions with Media Server. Media Server performs mixing of media of all participants and enables all participants to hear each other (audio conference) and see each other (video conference).

==== Conference audio mixer Loudest participants Optional MSML element <n-loudest> determines the number of participants from which audio is mixed based on their audio energy. MMTelCONF doesn’t define this element and relies on the default behaviour that causes Media Server to mix audio from all participants.

==== Audio sampling rate Optional attribute samplerate determines the sample rate for the audio mixer. MMTelCONF doesn’t define this attribute leaving to the default 8000 kHz.

==== Active speaker notification Active speaker notification enables active speaker to be notified with appropriate type of MSML event. MMTelCONF doesn’t define this attribute leaving to the default behaviour where notification is not supported.

==== DTMF and in-band tone clamping When enabled Media Server blocks DTMF and in-band tones from being mixed. MMTelCONF doesn’t define this attribute leaving to the default where clamping is not performed.

==== Video layout MMTelCONF implements a simple video layout where a single region over the root window displays the most active speaker. The same video output is offered to all conference participants.

==== Video resolution Range of video resolutions are supported and configurable at a feature level. Media Server must support the values configured.

Abbreviation | MSML schema v1.1 compliant | Value | Note
--- | --- | --- | ---
CIF | Yes | 352 × 288 | Supported; Default
QCIF | Yes | 176 × 144 | Supported
4CIF | Yes | 704 × 576 | Not supported
16CIF | Yes | 1408 × 1152 | Not supported
SQCIF | No | 128 × 96 | Proprietary support only
VGA | No | 640 x 480 | Proprietary support only
QVGA | No | 320 x 240 | Proprietary support only
HD720p | No | 1280 x 720 | Proprietary support only
HD720p_4x3 | No | 960 x 720 | Proprietary support only

=== Degrading from and upgrading to video media Video conference is triggered when:

Video conferencing is administratively enabled (IsVideoConferenceAllowed=true), and Conference moderator makes a video media offer that is acceptable to Media Server If one of these preconditions is not met the conference shall have only audio media mixed irrespective if all or some participants have successfully negotiated video session with Media Server. This is because the feature will not instruct the Media Server to mix video media.

When the feature has determined a video conference session state field IsVideoConference will be set to true. The conference will remain marked as video conference regardless of whether some or all participants downgrade their media to audio only.

If a conference has been determined as a video conference any one participant including the moderator can downgrade/upgrade the media to/from video by sending re-INVITE with video media description IP port set to zero (downgrade) or non-zero (upgrade). Alternatively, conference participant can re-INVITE with video media description excluded or included achieving the same result.

=== Video only conference

Video only communication may occur on any one participant leg provided this is acceptable to both Media Server and the participant. Video only communication can occur when a participant or media server didn’t have matching audio codecs or have mismatching parameters.

=== Terminating conference

The conference is considered to be terminated when the conference moderator, either:

- has disconnected, which will trigger the feature to remove all remaining participants

- is the last participant remaining after all other participants have disconnected.

=== Removing participants

The conference moderator can eject any participant at will by creating a `REFER` transaction with a request that contains a `Refer-to` header with a URI parameter `method=BYE` and a URI referencing the participant to be ejected. This feature removes the participant by terminating both call legs for that participant.

=== Re-INVITE Based Three-party conference setup overview

There is an alternative flow when setting up a conference. Under this flow, participants receive a re-INVITE on the consulting call rather than an INVITE with Replaces. This means that releasing the consulting call between the moderator and the participant is now the responsibility of the AS, rather than the UE.

In order for the re-INVITE based flow to function:

1. SCC Conference Handling configuration must be toggled on (set the `EnableSCCConfHandling` attribute to `true`)

2. originating and terminating SCC-AS must be implemented

3. the INVITE with Replaces sent by conferencing must trigger originating SCC processing

4. all sessions are subject to Session Tracking (this is automatically enabled when the `EnableSCCConfHandling` attribute is set to `true`)

Once the requirements are met the originating SCC-AS can implement the re-INVITE based flow. For a reference to the features used to implement this in the SCC-AS please refer to Reuse of access transfer procedures for conferencing. Configuration and flows for this capability are described in the following portion.

The MMTel Conference feature uses the `X-MSW-Original-Refer-To` header in preference to the `Refer-To` header in the Re-INVITE based conference setup. This is to facilitate conference moderator Access Transfer where an originating SCC-AS must be present between the moderator UE and the call to the Conference Factory.

==== SCC Conference Handling Configuration

SCC Conference handling configuration data is stored in the `SCCConfHandlingConfigProfileTable` profile table. Each profile is scoped according to a Sentinel Selection Key. By default there is one profile in the table, which is created by the installer. Each profile contains the following attribute.

Parameter | Type | Description | Default | Note
--- | --- | --- | --- | ---
    EnableSCCConfHandling
| Boolean | Enables SCC conf handling | false |

==== Flows

The first flow shows standard treatment where the INVITE with Replaces is passed and translated all the way through to the participant.

The second flow shows the re-INVITE based alternative enabled by the originating SCC where the INVITE with Replaces is converted to a re-INVITE on the participant’s consulting call.

== Interaction with MMTel Conference Subscription feature

MMTel Conference and MMTel Conference Subscription features share the data stored in the MMTelCONFView profiles associated with a given conference if there is at least one active subscription session for the associated `conferenceID`. The data is updated in the MMTel Conference feature when the conference is modified and is subsequently read by the MMTel Conference Subscription feature when it periodically polls for state changes. The ConferenceViewRemovalDelay in the MMTel Conference feature’s configuration provides a mechanism to allow all subscription sessions associated with MMTel Conference Subscription feature for the ended conference to complete before the MMTelCONFView profiles are removed.

== Conference Privacy

During a standard conference call, outbound INVITEs to conference participants after the REFER message include a `Referred-By` header with the conference moderator’s SIP identity.

If the conference moderator includes a Privacy header with value `User` or `Header` in either the initial INVITE to the conference focus or the REFER message to participants, then the `Referred-By` header is excluded from the INVITE to participants.

If the moderator or partipants include a Privacy header with value `Id` or `User`, then the subscriber’s identity in conference subscription notifications is anonymized.

== Feature interaction

An initial `INVITE` with a `Replaces` header must be exempted from processing by a feature that performs call re-targeting, call barring, call rejection, or early session announcements.

== Charging

Online charging uses a single OCS session for all legs of the conference:

- The OCS Session begins when the conference creator sets up a call with the conference server (MT instance).

- A credit check is performed before each participant is joined (event-based charging).

- A credit check/reservation is performed on the MO instance of every participant leg.

- The `icid` value of the `P-Charging-Vector` header in the received `INVITE` from the conference creator is copied into the `P-Charging-Vector` of every `INVITE` sent towards a participant, as a way of charging correlation.

== Inputs and outputs

=== Session state and leg manager data

==== Inputs

Name | Type | Format | Description | Behaviour if null/invalid | Note
--- | --- | --- | --- | --- | ---
Sentinel Selection Key | com.opencloud.sentinel.common.SentinelSelectionKey | selection key (for example, `<platform>::::`) | For selecting configuration data | Feature not executed | Session State Data
Conference Factory PSI | java.lang.String | SIP URI or Tel URL | The conference factory PSI used for this session | NA | Session State Data set by feature `DetermineVoltePlanId`
Sentinel Script Execution Point | enum com.opencloud.sentinel.feature.SipFeatureScriptExecutionPoint |  | Determination of context of execution, such as credit check, early session, mid-dialog session | No execution | Session State Data
Call Type | enum com.opencloud.sentinel.common.CallType |  | Determination of context of execution, such as `MobileTerminating` | NA | Session State Data
Call Leg | com.opencloud.sentinel.multileg.Leg |  | Determination of leg that receives an event | Call terminated | Leg Manager API
MMTelCONFServiceData | Complex |  | Read from the HSS or HLR in SubscriberDataLookupFromHSSor SubscriberDataLookupFromHLR | Feature not executed | Session State Data

==== Outputs

Name | Type | Format | Description | Note
--- | --- | --- | --- | ---
    ConferenceID
| String | A 16-character alpha-numeric string prefixed with `mmtel-conf-` | Generated by the feature when setting up moderator connection |
    ConferenceFocusAddress
| String | SIP URI | URI derived from conference ID used to address the conference UA instance, such as `<sip:mmtel-conf-VdvxbG3LUjb-CzwXAHnCqQ@10.1.1.1:5060;oc-node=101;lr>;isfocus` | Session State Data
    ControlPartLegName
| String |  | Control leg name, participant side | Session State Data
    ControlMRFLegName
| String |  | Control leg name, Media server side | Session State Data
    CurrentConnectionRequest
| `com.opencloud.volte.sentinel.mmtel.feature.conf MMTelCONFConnectionRequest` |  | Value object that represent request data and state of processing for joining a new participant; request that is being processed currently | Session State Data
    ConnectionRequestQueue
| `com.opencloud.volte.sentinel.mmtel.feature.conf MMTelCONFConnectionRequestQueue` |  | Pending requests to join new participants | Session State Data
    JoiningParticipants
| `com.opencloud.volte.sentinel.mmtel.feature.conf MMTelCONFConnectionRequestQueue` |  | Requests for which media bridging is in progress (MSML transaction is in progress) | Session State Data
    JoinedParticipants
| `com.opencloud.volte.sentinel.mmtel.feature.conf MMTelCONFConnectionRequestQueue` |  | Value objects that represent that participants that have been joined into conference including those already disconnected | Session State Data
    VideoConferenceResolution
| `com.opencloud.volte.sentinel.mmtel.feature.conf VideoConferencePolicyType.VideoConferenceResolution` |  | Value to represent the video conference resolution used for control MRF session | Session State Data
    Bandwidth
| Integer |  | Bandwidth value to use for control MRF session | Session State Data
    MinimumPictureInterval
| Integer |  | Mpi value to use for control MRF session | Session State Data
    MaximumPictureSize
| String |  | Bpp value to use for control MRF session | Session State Data
    FrameSize
| Integer |  | Framesize value to use for control MRF session | Session State Data
    ProfileLevelId
| String |  | Profile-level-id value to use for control MRF session | Session State Data
    Codec
| String |  | Codec value to use for control MRF session | Session State Data

Execution of this feature can also affect the conference view during execution if a participant is added or their status has changed.

== Statistics

MMTelCONF statistics are tracked by the MMTelCONF SBB and can be found under the following parameter set:
SLEE-Usage → volte.sentinel.sip service ID → MMTelCONF SBB ID.

Statistic | Incremented when…​
--- | ---
    FeatureInvocations
| the conference feature runs
    FeatureFsmCompletions
| the main conference FSM reaches its end state
    SentinelAborts
| Sentinel VoLTE instructs the conference feature to abort execution
    SipParseMinorFailure
| a non-fatal error occurs while attempting to read the information in a SIP message
    SipDataAccessFailure
| a problem occurs while trying to access a SIP leg or message
    SipParticipantSentByeOnActiveConnection
| a `BYE` request is received on an active (join operation complete) participant connection
    SipParticipantSentByeOnInactiveConnection
| a `BYE` request is received on an inactive (join operation incomplete) participant connection
    SipMRFSentByeOnActiveConnection
| a `BYE` request is received on an active (join operation complete) media server connection.
    SipMRFSentByeOnInactiveConnection
| a `BYE` request is received on an inactive (join operation incomplete) media server connection
    ConferenceFeatureConfigurationFailure
| a problem occurs while trying to load the conference feature’s network-level configuration data
    ConferenceCoreError
| a fatal error occurs in the core conference feature FSM
    ConferenceConnectionError
| a fatal error occurs in the conference feature’s non-control connection management FSM
    ConferenceConnectionEstablished
| a non-control connection is successfully established between a conference participant and the MRF
    ConferenceConnectionMRFLegCreated
| a non-control leg to the MRF is successfully established
    ConferenceConnectionTerminated
| a fully established non-control conference connection is terminated
    ConferenceConnectionCreditCheckInitiated
| the conference feature triggers a credit check
    ConferenceConnectionParticipantSupportsVideo
| a participant has indicated that they support video in an SDP answer
    ConferenceControlConnectionError
| a fatal error occurs in the conference feature’s control connection management FSM
    ConferenceControlConnectionEstablished
| a control connection is successfully established between a conference moderator and the MRF.
    ConferenceControlConnectionTerminated
| a fully established conference control connection is terminated.
    ConferenceControlConnectionReceivedMalformedMessage
| a badly formed REFER request is received from the conference moderator.
    ConferenceControlConnectionQueuedNotify
| a NOTIFY is queued on the control connection
    ConferenceControlConnectionSentNotify
| a NOTIFY is sent to the conference moderator
    FromHeaderAnonymised
| the moderator has indicated they want privacy applied to the outgoing INVITE
    ConferenceMediaVideoSelected
| the moderator sets the conference up as a video session
    ConferenceMediaServerIsAccessedViaSCSCF
| the feature makes a call to the MRF via the S-CSCF

== Error scenarios

Scenario | Handling
--- | ---
Second initial request received towards conference PSI | Report `featureFailedToExecute`
Non MT request received by conference PSI | Report `featureFailedToExecute`

== Mappers

This feature uses two different sets of mappers that conform to:

Mapping | Mapper Execution Point
--- | ---
MMTelCONFConfigWrapper.class → CreateConferenceMSML.class |
MMTelCONFConnectionRequestQueue.class → JoinConferenceMSML.class |
IncomingSipResponse.class → ResponseMSML.class |

== Mapper Configuration

As mentioned in the previous section this feature uses two different sets of mappers. The set to configure depends on the media server in use with the feature. Configuring mappers can be done in the SentinelMapperSetEntryTable. The following yaml excerpts outline which profiles should be configured for each vendor.

=== Dialogic

    SentinelMapperSetEntryTable:
        ${platform.operator.name}::sipcall:::MMTelConfMSML-CreateConference-Dialogic:
            MapperSetName: '${platform.operator.name}:'
            SessionType: sipcall
            PlanId: ''
            MapperExecutionPoint: ''
            MappingName: MMTelConfMSML-CreateConference-Dialogic
        ${platform.operator.name}::sipcall:::MMTelConfMSML-JoinConference-Dialogic:
            MapperSetName: '${platform.operator.name}:'
            SessionType: sipcall
            PlanId: ''
            MapperExecutionPoint: ''
            MappingName: MMTelConfMSML-JoinConference-Dialogic
        ${platform.operator.name}::sipcall:::MMTelConfMSML-Response-Dialogic:
            MapperSetName: '${platform.operator.name}:'
            SessionType: sipcall
            PlanId: ''
            MapperExecutionPoint: ''
            MappingName: MMTelConfMSML-Response-Dialogic

=== Radisys

    SentinelMapperSetEntryTable:
        ${platform.operator.name}::sipcall:::MMTelConfMSML-CreateConference-Radisys:
            MapperSetName: '${platform.operator.name}:'
            SessionType: sipcall
            PlanId: ''
            MapperExecutionPoint: ''
            MappingName: MMTelConfMSML-CreateConference-Radisys
        ${platform.operator.name}::sipcall:::MMTelConfMSML-JoinConference-Radisys:
            MapperSetName: '${platform.operator.name}:'
            SessionType: sipcall
            PlanId: ''
            MapperExecutionPoint: ''
            MappingName: MMTelConfMSML-JoinConference-Radisys
        ${platform.operator.name}::sipcall:::MMTelConfMSML-Response-Radisys
            MapperSetName: '${platform.operator.name}:'
            SessionType: sipcall
            PlanId: ''
            MapperExecutionPoint: ''
            MappingName: MMTelConfMSML-Response-Radisys

== Feature responses

Response | Reason
--- | ---
    endSession
| Max number of participants < 3, or `MMTelCONFServiceData.OperatorAuthorized` is `false`.
    featureFailedToExecute
| Multiple initial requests or non MT initial request received towards conference PSI
    featureHasFinished
| Feature has finished

== Configuration profile naming

Configuration Profile Table Name | Description | Profile Naming
--- | --- | ---
    MMTelCONFConfigProfileTable
| See Network Data for a detailed description of parameters |
    Sentinel Selection Key

Example configuration for conference feature where `localhost:5260` is the address of the MMTel TAS:

ConfFactoryPSI | ConfMaxParticipants | ConfCascadingEnabled | ConferenceViewRemovalDelay
--- | --- | --- | ---
    sip:conf-factory@localhost:5260
    3
    false
    30000

== Conference view

The current view of a conference is stored as a series of read-only profiles (one for each participant) within the `MMTelCONFViewTable` profile table.

Profile Table Name | Description | Profile Naming
--- | --- | ---
    MMTelCONFViewTable
| Stores the current state of a participant within a conference |
    ${CONFERENCE_ID}__${CONNECTION_ID}

Parameter | Type | Description
--- | --- | ---
    ConferenceEndpointStatus
| String | Current status of a participant connected, disconnected or on-hold
    ConferenceID
| String | Unique 16-character alpha-numeric string prefixed by `mmtel-conf-` (common amongst all participants)
    ConnectionID
| String | Unique identifier for a participant as the uniqueness of `ParticipantID` cannot be guaranteed
    ParticipantID
| String | URI identifying the participant
    ParticipantDisplayText
| String | Participant display text
    EndpointID
| String Unique | Identifier for the endpoint
    ConferenceEnded
| Boolean | `true` if the conference has ended and we are waiting for notifications to end
    LastUpdateTime
| Long | Timestamp representing the last time the profile was updated
    ParticipantRequestedPrivacy
| Boolean | `true` if conference participant requested privacy

== Conference event package

A UE may attempt to subscribe to notifications for the `conference` event package. Subscriptions for the `conference` event package are handled by the MMTel Conference Subscription.

== Provisioning interfaces

The feature is provisioned using the Sentinel REST API or web interface.

= Interaction with Media Server :toc: macro :toclevels: 4 :toc-title: On this page…​

The conferencing feature facilitates connecting conference participants to the media server and instructs the media server to mix audio media from all participants to form an audio conference.

The feature controls mixing, using the MSML protocol over SIP in the context of an existing SIP dialog. For this purpose, this implementation uses the moderator SIP dialog established between the conferencing server and the media server, as long as the the lifeline of any conference instance is aligned with the lifeline of the moderator connection.

MSML transactions are carried by `SIP INFO` transactions and encoded as application/msml+xml content type. The result of the MSML transaction is returned in a `SIP INFO 200 OK` response.

This feature uses the MSML conference object and MSML connection object capabilities of MSML protocols.

Each MSML connection is linked or “joined” with an MSML conference object that creates a media bridge with other connections.

== MSML conference object

A conference object is a media bridge that links media with MSML connections. By joining MSML connection objects with the MSML conference objects, media between all connections are mixed, achieving conference functionality. A conference object is identified by a conference ID, which is a randomly unique string prefixed with `conf:`.

The conferencing feature creates an MSML conference object using the `<createconference>` MSML command. This command has several parameters, such as mixer type, half or full-duplex, and termination policy. This implementation creates a full-duplex audio mixer without a conference termination policy.

Here an is an example of a `<createconference>` MSML request that creates a conference object:

    <?xml version="1.0" encoding="UTF-8"?>
        <msml version="1.1">
            <createconference name="conf:mmtel-conf-378237676" deletewhen="nocontrol" term="false"/>
        </msml>

The media server returns with MSML response `200` indicating success:

    <?xml version="1.0" encoding="utf-8"?>
       <msml version="1.1">
           <result response="200"/>
       </msml>

The conference object created has parameters that specify:

- Conference ID `mmtel-conf-378237676`.

- The media server automatically removes the conference object when the moderator disconnects.

- The media server doesn’t disconnect remaining participants when the conference object is deleted. (This task is left to the conferencing server.)

- A full-duplex audio mixer will be used, with mixing active at all times, without notification of the active speakers.

== MSML connection object

A session between each participant and the media server (using the conferencing feature) is referred to as an MSML connection and is identified by the SIP `to-tag` (prefixed by `conn:`) of the SIP session between the conferencing server and the media server. An MSML connection is joined into the conference by the MSML command `<join>`, which takes arguments of the connection ID of the connection to be joined and the conference ID of the conference object.

== Forming a media conference

A conference is formed by creating a media bridge between the MSML conference object and each MSML connection. This is achieved by an MSML join transaction, as follows:

    <?xml version="1.0" encoding="UTF-8"?>
        <msml version="1.1">
            <join id1="conn:e7826yde8" id2="conf:mmtel-conf-378237676"/>
                <stream media="audio"/>
            </join>
        </msml>

== Removing a participant

It is sufficient to terminate the SIP dialog corresponding to the participant to be removed.

== Ending a conference

When the conference moderator disconnects, the conferencing will disconnect all remaining participants, bringing the conference to an end.

= Support for multiple conference factory PSI :toc: macro :toclevels: 4 :toc-title: On this page…​

The `Conference factory PSI` is a SIP URI or TEL URL that is a conferencing service `Public Service Identity`.

There are two reasons to support multiple conference factory PSI:

- support conference factory PSIs defined by relevant standards (Standard conference factory PSI)

- support operators that are live with handsets that use non-compliant conference factory PSI (Alias conference factory PSI)

== Standard Conference Factory PSI

A standard conference factory PSI is one that conforms to 3GPP TS 23.003.

=== Understanding Standard Conference Factory PSIs

3GPP TS 23.003 lists three conference factory PSI formats that could be required in a network:

- sip:mmtel@conf-factory.<domain>

- sip:mmtel@conf-factory.ims.mnc<MNC>.mcc<MCC>.3gppnetwork.org

- sip:conf-factory.ics.mnc<MNC>.mcc<MCC>.3gppnetwork.org

where <domain>, <MCC> and <MNC> correspond to properties of the platform.

The relevant sections of 3GPP TS 23.003 include:

> The Conference Factory URI shall take the form of a SIP URI (see IETF RFC 3261 [26]) with a host portion set to the home network domain name as described in subclause 20.3.2 prefixed with "conf-factory.". An example using the same example IMSI from sub-clause 20.3.2 can be found below:

> EXAMPLE: "sip:conf-factory.ics.mnc015.mcc234.3gppnetwork.org". The user portion of the SIP URI is optional and implementation specific.

— 3GPP TS 23.003
section 20.3.5 Conference Factory URI

> The home network domain name shall be in the form of an Internet domain name, e.g. operator.com, as specified in IETF RFC 1035 [19].

— 3GPP TS 23.003
section 20.3.2 Home network domain name

The values that parameterise standard conference PSIs (such as MCC/MNC) are in the configuration for the PLMN ID Analyser Component and the configuration profile defined in Sentinel SIP.

=== Checking standard MMTel conference factory PSI

The set of standard conference factory PSIs supported is derived from the Sentinel SIP Configuration profile and the PLMN ID Analyser Component. For example, if `HomeNetworkIds` is set to `example.com` and the configured home PLMN IDs are `(254,01)` and `(254,17)`, the set of standard conference factory PSIs is:

- sip:mmtel@conf-factory.example.com

- sip:mmtel@conf-factory.ims.mnc001.mcc254.3gppnetwork.org

- sip:mmtel@conf-factory.ims.mnc017.mcc254.3gppnetwork.org

- sip:conf-factory.ics.mnc001.mcc254.3gppnetwork.org

- sip:conf-factory.ics.mnc017.mcc254.3gppnetwork.org

If no matching standard conference factory PSI is found, then check all alias conference factory PSI.

== Alias Conference Factory PSI

An Alias conference factory PSI is a non-standard conference PSI used by a handset that does not conform to standards.

=== Supporting Alias conference factory PSI

The MMTelConf configuration profile (from the MMTelCONFConfigProfileTable table) defines a property `AliasConferenceFactoryPSI`. This property is a set of Strings that identify non-standard conference factory PSI that should be recognised by the platform. Each String must be a valid SIP URI or Tel URL.

=== Checking Alias conference factory PSI

Each entry in the alias conference factory PSI set is a String that is a constant or parameterised by:

- <HOME-DOMAIN>— replace with home domains configured for the platform

- <MCC> and <MNC>— replace with home PLMN IDs configured for the platform

For example, if `HomeNetworkIds` is set to `example.com` and the configured home PLMN IDs are `(254,01)` and `(254,17)`,

and …​

Property | Value
--- | ---
AliasConferenceFactoryPSI | sip:conf-factory@specialdomain.com, sip:conf-factory@<HOME-DOMAIN>, sip:conf-factory@ims.mnc<MNC>.mcc<MCC>.com, sip:conf-factory@ics.mnc<MNC>.mcc<MCC>.com, sip:conf-factory.ics.mnc019.mcc250.3gppnetwork.org

then the supported alias conference factory PSIs are:

- sip:conf-factory@specialdomain.com,

- sip:conf-factory@example.com,

- sip:conf-factory@ims.mnc001.mcc254.com,

- sip:conf-factory@ims.mnc017.mcc254.com,

- sip:conf-factory@ics.mnc001.mcc254.com,

- sip:conf-factory@ics.mnc017.mcc254.com,

- sip:conf-factory.ics.mnc019.mcc250.3gppnetwork.org

If no matches are found, then this trigger is not relevant for MMTel Conferencing. The feature will end, and control will return to the Sentinel runtime.

= MMTel Conference Subscription :toc: macro :toclevels: 4 :toc-title: On this page…​

This feature provides a means for UEs to subscribe to “conference” event package notifications for a conference .

== Feature cheat-sheet

B2BUA Instance | SAS Support | Originating / Terminating | Point(s) in Session Plan | Network Operator Data | Subscriber Data | Stateful or Stateless | POJO Feature or SBB Feature
--- | --- | --- | --- | --- | --- | --- | ---
MMTEL | Yes | Both | `SubscriptionSessionCheck` `SubscriptionPartyRequest` `SubscriptionPartyResponse` `SipAccess_ServiceTimer` `SipMidSession_PartyRequest` | Yes | No | Stateful | POJO with FSMs

== Source Code

This feature’s source code is available in the Sentinel VoLTE SDK in the `mmtel-conferencing` module pack. It can be viewed by using the `create-module` command in the SDK with that module pack, for example:

`> create-module new-conf-module opencloud#mmtel-conferencing#volte/3.1.0;3.1.0.0`

This command will prompt you for information needed to create the new modules, once completed the original source for the feature can be found in the new modules.

The module-pack includes the following modules relevant to this feature:

Module Name | Description
--- | ---
mmtel-conferencing | Group module for the feature that includes all of the modules listed below.
mmtel-conf-library | Contains common code for the conference modules.
mmtel-conf-subscription-profile | Contains the profile specification for the feature configuration profile table.
mmtel-conf-view-profile | Contains the profile specification for the profile table used to track information about a conference.
mmtel-conf-event-schema-library | Generates java code for the conference event XML schema.
mmtel-conf-subscription | Contains the feature itself.

== Subscriber data

Not applicable; the feature is generally available unless disabled at the network level.

== Network data

Data is stored in the `MMTelCONFSubscriptionConfigurationTable` profile

Parameter | Type | Default | Description
--- | --- | --- | ---
    DefaultSubscriptionExpirySecs
| Integer | 3600 | Expires value is used if SUBSCRIBE doesn’t contain Expires header
    MinSubscriptionExpirySecs
| Integer | 5 | SUBSCRIBE requests with a Expires value lower than this are are rejected
    PollingIntervalSecs
| Integer | 5 | Frequency of polls for changes to conference view

== Statistics

`MMTelCONFSubscription` statistics are tracked by the `sentinel.volte.sip` SBB and can be found under the following parameter set: SLEE-Usage → sentinel.volte.sip service → sentinel.volte.sip SBB → feature → MMTelCONFSubscription

Name | Type | Description
--- | --- | ---
    Started
| Counter | Incremented each time the feature runs.
    FailedToStart
| Counter | Incremented when Sentinel VoLTE encounters an error while attempting to start the feature.
    IssuedWarning
| Counter | Incremented when a non-fatal problem is encountered and the feature issues a warning.
    FailedDuringExecution
| Counter | Incremented when a fatal problem is encountered and the feature cannot execute correctly.
    TimedOut
| Counter | Incremented when the feature takes too long to complete and Sentinel VoLTE aborts execution.
    SubscriptionStarted
| Counter | Incremented when a subscription is successfully initiated.
    SubscriptionRefreshed
| Counter | Incremented when an in-progress subscription is refreshed with a new `SUBSCRIBE` request.
    SubscriptionEnded
| Counter | Incremented when an in-progress subscription is ended with a `NOTIFY` with subscription state `terminated`.
    SubscriptionRejected
| Counter | Incremented when a `SUBSCRIBE` request is refused with an error response.
    NewSubscriptionRequestedInNewDialog
| Counter | Incremented when a subscription is initiated by a `SUBSCRIBE` request received in a new SIP dialog.
    NewSubscriptionRequestedInExistingDialog
| Counter | Incremented when a subscription is initiated by a `SUBSCRIBE` request received in an existing SIP dialog.
    NotifySent
| Counter | Incremented each time the feature generates and sends a `NOTIFY` request.

== Session state inputs and outputs

=== Inputs

Name | Type | Description
--- | --- | ---
SentinelSelectionKey | com.opencloud.sentinel.common.SentinelSelectionKey | For selecting configuration data
HeadersByLeg | com.opencloud.sentinel.multileg.HeadersByLeg | Header information received on a given leg

== Behaviour

Name | `MMTelCONFSubscription`
Applicable contexts | SIP service
Prerequisite features | `MMTelCONF`

The MMTel Conference Subscription feature is to be used in conjunction with the MMTel Conference feature. It provides a means for UEs to subscribe to “conference” event package notifications for a conference managed by the MMTel Conference feature. Currently no distinction is made between conference and non conference participants.

Notifications are triggered by changes in the state of the conference for example when a participant joins or leaves. The feature is triggered initially on an incoming `SUBSCRIBE` and is subsequently triggered by a `re-SUBSCRIBE` attempt or on the expiry of the features polling timer. In the case where the feature is triggered by a incoming `SUBSCRIBE` message a `NOTIFY` will be sent detailing the complete state of the conference. In the case where the feature is triggered on the expiry of the polling timer a `NOTIFY` containing the current state of the conference will only be sent if the conference view has been modified since the last expiry of the timer. The feature may also be triggered by `BYE` requests and `REFER` requests that have a `Refer-To` method of `BYE`, this affects subscriptions that are created in the `INVITE` dialog for the conference and will trigger the same behaviour as a polling timer expiry.

=== Specification compliance

- SIP-Specific Event Notification

- Event Package for Conference State

==== Explicit exclusions

| This exclusion only applies to versions of Sentinel VoLTE prior to 2.6.0.18

- All error responses on a subscription session result in a NOTIFY request with Subscription-State “terminated” towards UE.

===== Subscription life-cycle with exclusion

=== Interaction with MMTel Conference feature

MMTel Conference and MMTel Conference Subscription features share the data stored in the MMTelCONFView profiles associated with a given conference if there is at least one active subscription session for the associated `conferenceID`. The data is updated in the MMTel Conference feature when the conference is modified and is subsequently read by the MMTel Conference Subscription feature when it periodically polls for state changes. The ConferenceViewRemovalDelay in the MMTel Conference feature’s configuration provides a mechanism to allow all subscription sessions associated with MMTel Conference Subscription feature for the ended conference to complete before the MMTelCONFView profiles are removed. There is a configurable delay in the MMTel Conference feature for how long the profiles should remain for after the conference ends. Generally the `PollingIntervalSecs` of MMTel Conference Subscription should be lower than this delay.

==== Conference view

The current view of a conference is stored as a series of read-only profiles (one for each participant) within the MMTelCONFViewTable. A conference is considered active and therefore a subscription successful if at least one profile exists with the requested `ConferenceID` and `ConferenceEnded` is `false`. Profiles from this table are used to create the body of outgoing NOTIFY messages.

Configuration profile table name | Description | Profile naming
--- | --- | ---
MMTelCONFViewTable | Stores the current state of a participant within a conference | ${CONFERENCE_ID}__${CONNECTION_ID}

Parameter | Type | Description
--- | --- | ---
ConferenceEndpointStatusInternal | String Current | Status of a participant connected, disconnected or on-hold
ConferenceID | String Unique | 16 character alpha-numeric string prefixed by “mmtel-conf-” (common amongst all participants)
ConnectionID | String Unique | Identifier for a participant as the uniqueness of ParticipantID cannot be guaranteed
ParticipantID | String URI | Identifying the participant
ParticipantDisplayText | String | Participant display text
EndpointID | String Unique | Identifier for the endpoint
ConferenceEnded | Boolean | `true` if the conference has ended and we are waiting for notifications to end
LastUpdateTime | Long | Timestamp representing the last time the profile was updated
ParticipantRequestedPrivacy | Boolean | `true` if conference participant requested privacy

==== Conference Subscription Privacy

If a conference moderator or participant includes the Privacy header with a value of `id` or `user` during conference establishment, the MMTel Conference Subscription feature anonymizes their identity in subscription `NOTIFY` messages.

For the moderator, the Privacy header on the initial INVITE to the conference focus determines the subscription privacy setting. For participants, the Privacy header on the 200 response to the Conference Leg INVITE determines the subscription privacy setting.

An anonymized subscriber identity takes the form `sip:anonymous@anonymous.invalid`. If multiple subscribers in a conference have Privacy set then unique anonymous values are used, e.g. `sip:anonymous_1@anonymous.invalid` and `sip:anonymous_2@anonymous.invalid`

A typical subscription `NOTIFY` message XML body with anonymous participants is shown in the example below.

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <conference-info xmlns="urn:ietf:params:xml:ns:conference-info" entity="mmtelconf101exmuAr6awKdkUaTRMf34QA" state="full" version="3">
      <conference-description/>
      <users>
        <user entity="sip:anonymous@anonymous.invalid" state="full">
          <display-text>Anonymous</display-text>
          <endpoint entity="sip:anonymous@anonymous.invalid">
            <status>connected</status>
          </endpoint>
        </user>
        <user entity="sip:anonymous_1@anonymous.invalid" state="full">
          <display-text>Anonymous_1</display-text>
          <endpoint entity="sip:anonymous_1@anonymous.invalid">
            <status>connected</status>
          </endpoint>
        </user>
        <user entity="sip:anonymous_2@anonymous.invalid" state="full">
          <display-text>Anonymous_2</display-text>
          <endpoint entity="sip:anonymous_2@anonymous.invalid">
            <status>disconnected</status>
          </endpoint>
        </user>
      </users>
    </conference-info>

=== Conference event schema

Event Package for Conference State and the associated schema are used to convey the current state of the conference for subscribed resources. The feature will always render the complete state of the conference regardless of subscription state.

= MMTel PSAP Callback :indexpage:

After placing a PSAP call a subscriber may receive a return call from the PSAP (for example to confirm the subscriber’s physical location). PSAP callbacks must not be blocked or delayed by MMTel features. The two features here are responsible for identifying appropriate calls as PSAP callbacks and (if required) recording that a PSAP call has occurred.

Feature | What it does
--- | ---
MMTel Determine PSAP Callback | determines whether a received SIP INVITE corresponds to a PSAP callback, and stops any other features that could potentially prevent the call being set up.
MMTel Record PSAP Call | identifies SIP MESSAGES sent to the AS by E-CSCF to notify the AS that a subscriber has placed an emergency call. The feature records this information in Cassandra where it can be used by MMTel Determine PSAP Callback to identify calls as potential PSAP callbacks.

= MMTel Determine PSAP Callback :toc: macro :toclevels: 4 :toc-title: On this page…​

This feature determines whether a received SIP INVITE corresponds to a PSAP callback, and stops any other features that could potentially prevent the call being set up. This is achieved by setting the session plan to `mmtel-term-psap-callback`. This session plan contains no MMTel features which could result in the call not reaching the intended subscriber (for example Incoming Call Barring).

== Feature Cheat Sheet

B2BUA Instance | SAS Support | Originating / Terminating | Point(s) in Session Plan | Network Operator Data | Subscriber Data | Stateful or Stateless | POJO Feature or SBB Feature | Other notes
--- | --- | --- | --- | --- | --- | --- | --- | ---
MMTel | Yes | Terminating | `SipAccess_SessionCheck` | No | Yes | Stateless | POJO |

== Prerequisite Features

- SIP Subscriber Determination— in order to know who the subscriber is for the call.

== Source Code

This feature’s source code is not available in the Sentinel VoLTE SDK as a module pack.

== Cassandra storage

The feature can be configured to access a Cassandra database, to determine whether terminating calls to the served subscriber should be treated as possible PSAP callbacks.

== Data Schema

If the SIP MESSAGE mechanism is used to record PSAP calls and identify possible PSAP callbacks then the following Cassandra configuration is required.

The Cassandra table for PSAP callbacks exists in a keyspace named `opencloud_psap_callback`

For a production environment, the keyspace must be created such that it is replicated. A sample command for creating this keyspace is:

    CREATE KEYSPACE  IF NOT EXISTS opencloud_psap_callback WITH REPLICATION={'class' : 'SimpleStrategy' ,'replication_factor' : 3 };

For testing purposes, replication may not be necessary. A sample CQL command for creating such a keyspace is:

    CREATE KEYSPACE  IF NOT EXISTS opencloud_psap_callback WITH REPLICATION={'class' : 'SimpleStrategy', 'replication_factor' : 1};

Once the keyspace is created, the required tables can be created. The following CQL statements provides the structure of the required table:

    USE opencloud_psap_callback ;

    CREATE TABLE IF NOT EXISTS opencloud_psap_callback.psapcalls(
        subscriber_id text,
        primary key(subscriber_id)
    )
    WITH gc_grace_seconds = 172800; // 2 days

== Configuration

Configuration for this feature is stored in the `MMTelPSAPCallbackConfigProfileTable` profile table, containing only one profile, which has the following fields:

Parameter | Type | Description
--- | --- | ---
`UsePriorityHeader` | boolean | Flag to use the contents of the Priority header in the initial INVITE to determine whether the call is a PSAP callback.
`UseSIPMessages` | boolean | Flag to use the SIP MESSAGEs mechanism to determine whether the call is a PSAP callback
`ExpiryTime` | int | When using the SIP MESSAGEs mechanism the time in seconds after a SIP MESSAGE notifying a PSAP call is received during which any call to the subscriber is assumed to be a PSAP callback.
`TerminateMessage` | boolean | When using the SIP MESSAGEs mechanism the flag to determine whether we reply to received SIP MESSAGEs notifying a PSAP call, or allow them to propagate further through the network.

== Session Input Variables

Session State variable name | Type | Comments
--- | --- | ---
`SentinelSelectionKey` | SentinelSelectionKey | Determines which configuration to use, also used when setting the Plan Id.
`CallType` | CallType | Use to determine whether the call is Mobile Terminating.
`Subscriber` | String | Subscriber value is used as the primary key in the Cassandra database.
`DeterminePSAPCallbackCassandraSessionACI` | ActivityContextInterface | Used for detaching from the ACI when the feature has finished.
`DeterminePSAPCallbackCassandraSessionRequestSendTime` | Long | Used to determine and log latency of Cassandra queries.

== Session Output Variables

Session State variable name | Type | Comments
--- | --- | ---
`SentinelSelectionKey` | SentinelSelectionKey | Used when setting the Plan Id.
`DeterminePSAPCallbackCassandraSessionACI` | ActivityContextInterface | Stored off so that the feature can detach from the ACI when finished.
`DeterminePSAPCallbackCassandraSessionRequestSendTime` | Long | Used to determine and log latency of Cassandra queries.

== Statistics

`MMTelDeterminePSAPCallback` statistics are tracked by the sentinel.volte.sip SBB and can be found under the following parameter set in REM:
SLEE-Usage → sentinel.volte.sip service → sentinel.volte.sip SBB → feature → MMTelDeterminePSAPCallback
or with rhino-stats:
"SLEE-Usage.Services.ServiceID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].SbbID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].feature.MMTelDeterminePSAPCallback"

Statistic | Incremented when…​
--- | ---
`Started` | The feature runs
`FailedToStart` | Sentinel VoLTE encounters an error while attempting to start the feature
`FailedDuringExecution` | A fatal problem is encountered and the feature cannot execute correctly
`Misconfigured` | The feature doesn’t have any config.
`DeterminedPSAPCallback` | The feature has determined that a call is possibly a PSAP callback.
`DeterminedPSAPCallbackFromPriorityHeader` | The feature has used the Priority header method to determine that a call is a PSAP callback.
`DeterminedPSAPCallbackFromCassandra` | The feature has queried the Cassandra database and determined that the call is possibly a PSAP callback.
`UpdatedPlanId` | The Plan Id has been updated as a result of the call being identified as a possible PSAP callback.
`CassandraQueried` | Cassandra is queried for the destination address
`CassandraResponseReceived` | A success response is received from Cassandra
`CassandraErrorReceived` | An error response is received from Cassandra
`CassandraEmptyResultSetReceived` | An empty result set is received from Cassandra
`CassandraResponseLatency` | Time from sending the Cassandra request to receiving the Cassandra result, sampled on receipt of the result

== Behaviour

The feature’s behaviour depends on the trigger. There are 3 supported triggers, a `SipRequest`, `CassandraQueryResultEvent`, and `CassandraErrorEvent`.

=== Invoked by a SipRequest

If invoked by a `SipRequest` trigger, the first things the feature does is perform some checks, to ensure that call is Mobile Terminating, and that the `SipRequest` is an initial INVITE. It then proceeds to determine whether the call is a PSAP callback.

If configured via the `UsePriorityHeader` value in the profile, the feature first checks for the presence of the `Priority` header in the INVITE. If that header has a value of `psap-callback`, then the call is determined to be a PSAP callback. The feature then updates the `PlanId` to have a value of `mmtel-term-psap-callback`, before finishing.

If a positive result is not found using the `Priority` header, and if configured using the `UseSIPMessages` value in the profile, the feature then checks for an entry in the Cassandra database, using the contents of the `Subscriber` session state variable as a primary key. The feature then waits for a response.

=== Invoked by a CassandraQueryResultEvent

This is the event the feature was waiting for after it sent a Cassandra query when invoked with a `SipRequest`. If the result returns a row, then a PSAP call was made by the subscriber within a configured number of seconds, and the call is assumed to be a PSAP callback. This isn’t expected to be true on every occasion. This timing window is configured using the `ExpiryTime` value in the profile, and is used as the TTL for the row created in the Cassandra database when a PSAP call is made by the subscriber.

If determined to be a possible PSAP callback, the feature updates the `PlanId` to have a value of `mmtel-term-psap-callback`, before finishing.

This method uses SIP `MESSAGES` to notify that a PSAP call has been made by the subscriber, and is explained in MMTelRecordPSAPCall feature doc.

=== Invoked by a CassandraErrorEvent

This means that the Cassandra query sent by the feature when it was invoked by a `SipRequest` went wrong. The error is logged, both to rhino logs and to SAS, before the feature finishes.

= MMTel Record PSAP Call :toc: macro :toclevels: 4 :toc-title: On this page…​

This feature identifies SIP MESSAGES sent to the AS by E-CSCF to notify the AS that a subscriber has placed an emergency call. The feature records this information in Cassandra where it can be used by MMTel Determine PSAP Callback to identify calls as potential PSAP callbacks. A PSAP callback is a returned call to a subscriber made by a Public Safety Answering Point.

== Feature Cheat Sheet

B2BUA Instance | SAS Support | Originating / Terminating | Point(s) in Session Plan | Network Operator Data | Subscriber Data | Stateful or Stateless | POJO Feature or SBB Feature | Other notes
--- | --- | --- | --- | --- | --- | --- | --- | ---
MMTel | Yes | Originating | `SipAccess_SessionCheck` | No | Yes | Stateless | POJO |

== Prerequisite Features

- SIP Subscriber Determination— in order to know who the subscriber is for the call.

== Source Code

This feature’s source code is not available in the Sentinel VoLTE SDK as a module pack.

== Cassandra storage

The feature requires access to a Cassandra database to store records of PSAP calls.

== Data Schema

If PSAP call are recorded using the SIP MESSAGE mechanism as per MMTel Determine PSAP Callback Configuration then the Cassandra configuration as per the MMTel Determine PSAP Callback Data Schema is required.

== Configuration

Configuration for this feature is stored in the `MMTelPSAPCallbackConfigProfileTable` profile table. Details can be found in the MMTel Determine PSAP Callback feature documentation.

== Session Input Variables

Session State variable name | Type | Comments
--- | --- | ---
`SentinelSelectionKey` | SentinelSelectionKey | Determines which configuration to use.
`Subscriber` | String | Subscriber value is used as the primary key in the Cassandra database as determined by SIP Subscriber Determination
`RecordPsapCallCassandraSessionACI` | ActivityContextInterface | The ACI used to update Cassandra.
`RecordPsapCallQueryStartTime` | Long | Used to determine and log latency of Cassandra queries.

== Session Output Variables

Session State variable name | Type | Comments
--- | --- | ---
`RecordPsapCallCassandraSessionACI` | ActivityContextInterface | Stored off so that the feature can detach from the ACI when finished.
`RecordPsapCallQueryStartTime` | Long | Used to determine and log latency of Cassandra queries.

== Statistics

`MMTelRecordPSAPCall` statistics are tracked by the sentinel.volte.sip SBB and can be found under the following parameter set in REM:
SLEE-Usage → sentinel.volte.sip service → sentinel.volte.sip SBB → feature → MMTelDeterminePSAPCallback
or with rhino-stats:
"SLEE-Usage.Services.ServiceID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].SbbID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].feature.MMTelRecordPSAPCall"

Statistic | Incremented when…​
--- | ---
`Started` | The feature runs
`FailedToStart` | Sentinel VoLTE encounters an error while attempting to start the feature
`FailedDuringExecution` | A fatal problem is encountered and the feature cannot execute correctly
`Misconfigured` | The feature doesn’t have any config.
`InvalidSipRequest` | The feature was started with a SIP request which is not a MESSAGE.
`RecordedPSAPCall` | A PSAP call has been successfully recorded in Cassandra.
`SentCassandraUpdate` | The feature has sent an update to Cassandra.
`CassandraError` | The feature failed to send an update to Cassandra.
`CassandraWriteFailed` | The feature received an error response from Cassandra.
`CassandraWriteSuccess` | The feature received a success response from Cassandra.
`SipMessageResponseSent` | The feature sent a response to the incoming SIP MESSAGE.
`SipMessagePassedThrough` | The feature allowed the incoming SIP MESSAGE to continue propagating through the network.
`CassandraResponseLatency` | Time from sending the Cassandra request to receiving the Cassandra result, sampled on receipt of the result

== Behaviour

The feature’s behaviour depends on the trigger. There are 3 supported triggers, a `SipRequest`, `CassandraQueryResultEvent`, and `CassandraErrorEvent`.

=== Invoked by a SipRequest

If invoked by a `SipRequest` trigger the feature first performs some checks to ensure that the request is a SIP MESSAGE. It then checks the request URI to identify messages notifying PSAP calls. SIP MESSAGEs that identify PSAP calls have a request URI of `urn:service:sos`.

If the SIP MESSAGE is identified as a PSAP call notification then the feature records that the subscriber has placed a PSAP call in Cassandra using a TTL as configured in the `ExpiryTime` profile field. The feature then waits for a response from Cassandra. If `TerminateMessage` is set to `true` the feature sends a `200 OK` response to the incoming SIP MESSAGE otherwise the SIP MESSAGE is allowed to propagate through the rest of the network.

=== Invoked by a CassandraQueryResultEvent

This event indicates that the PSAP call has been recorded in Cassandra. The feature simply increments the appropriate statistics and sends a SAS log in this case.

=== Invoked by a CassandraErrorEvent

This event indicates that the PSAP call has not been recorded in Cassandra. The error is logged to SAS and appropriate statistics are incremented but no further action is taken.

= MMTel Subscriber Data Representation :toc: macro :toclevels: 4 :toc-title: On this page…​

The MMTel Subscriber Data Representation is a logical representation of supplementary service data as a group of POJO objects. It allows MMTel services/features to execute independently of any concrete schema for the supplementary service data. Therefore it can be loaded from the HSS or the HLR using the MMTel-Services XML schema or 3GPP MAP ASN.1 schema. For mapping details see SubscriberDataLookupFromHSS and SubscriberDataLookupFromHLR.

== Motivation

The subscriber data schemas used by an HSS and HLR are very different. While HSS supports complex types in XML format (through the Sh interface), the HLR schema format is ASN.1 with different semantics (through the MAP interface). One example of a simple concept is the 'active' flags. The HSS and Sh protocol provide an XML document that indicates if the service is active or not as an option boolean flag (`active=true or false`, or not present). While the HLR and MAP protocol represents the data as a state vector which includes the service status indication with three values (`Active and Operative`, `Not Active` and `Active and Quiescent`).

The objective of this representation is to decouple the concrete representation of Subscriber Data to an extensible internal representation that supports different schemas.

== Description

The internal representation works by:

- defining one subscriber data containing class for each MMTel feature, and defining a suitable session state field for an instance of that class

- retrieving the supplementary service data from the suitable network element (HSS via Sh pull, or HLR via AnytimeSubscriptionInterrogation)

- invoking a schema specific adapter class based on the response i.e. the simServes adaptor or the ASN.1 adaptor

- for each MMTel feature, the adaptor writes an instance of the subscriber data containing class into the appropriate session state field

The adapter has the function of converting the concrete schema into the logical representation, and storing it into session state. After the adaptor has written the session state fields, the MMTel features are invoked and read their data from session state fields.

== ServiceData Types

Each of these types has a corresponding Java class.

=== MMTelTIPServiceData

Attribute | Description
--- | ---
Active | Indicates if the feature is active `true` or inactive `false`
Override | Indicates if the feature can take precedence over the TIR feature
OperatorAuthorized | Operator setting to authorize the feature for the user

=== MMTelTIRServiceData

Attribute | Description
--- | ---
Active | Indicates if the feature is active `true` or inactive `false`
DefaultBehaviour | Indicates if the the user data presentation is restricted or not
Mode | Indicates if it is permanent or temporary
OperatorAuthorized | Operator setting to authorize the feature for the user

=== MMTelOIPServiceData

Attribute | Description
--- | ---
Active | Indicates if the feature is active `true` or inactive `false`
Override | Indicates if the feature can take precedence over the OIR feature
OperatorAuthorized | Operator setting to authorize the feature for the user

=== MMTelOIRServiceData

Attribute | Description
--- | ---
Active | Indicates if the feature is active `true` or inactive `false`
DefaultBehaviour | Indicates if the user data presentation is restricted or not
Mode | Indicates if it is permanent or temporary
OperatorAuthorized | Operator setting to authorize the feature for the user

=== MMTelCDIVServiceData

These properties are from the `<communication-diversion>` element.

Attribute | Description
--- | ---
Active | Indicates if the feature is active `true` or inactive `false`
NoReplyTimeout | The time waiting for the response to trigger the noReply rule
Ruleset | This is a Java implementation of IETF’s common policy Ruleset as used by 3GPPs CDIV specification. A ruleset is a collection of Rules
Rule.ID | Unique identification for the rule
Rule.conditions | The conditions
Rule.forwardActions | The actions to forward the session. It includes the destination address and the notification and privacy rules for the caller and called parties

These properties are from the `<operator-communication-diversion>` element.

Attribute | Description
--- | ---
OperatorTotalNumberOfDiversionsForEachCommunication | The maximum number of times a communication may be diverted.
OperatorCommunicationForwardingOnNoReplyTimer | The time waiting for the response to trigger the noReply rule
OperatorRuleset | This is a Java implementation of IETF’s common policy Ruleset as used by 3GPPs CDIV specification. A ruleset is a collection of Rules
OperatorAuthorized | Operator setting to authorize the feature for the user

| The schema for the Operator part of the Communication Diversion (CDIV) services has been extended to support an optional ruleset. This feature is supported by some HSS vendors.

=== MMTelCWServiceData

Attribute | Description
--- | ---
Active | Indicates if the feature is active `true` or inactive `false`
OperatorAuthorized | Operator setting to authorize the feature for the user

=== MMTelOCBServiceData

Field | Description
--- | ---
Active | Indicates if the feature is active `true` or inactive `false`
Ruleset | Contains the subscriber’s barring rules. Read from the HSS and configurable via XCAP or read from HLR. It is a Java-parsed representation of a Common Policy Ruleset.
Rule.ID | Unique identification for the rule
Rule.conditions | The conditions
Rule.allow | Allow or not allow the session to be forwarded
OperatorAuthorized | Operator setting to authorize the feature for the user

=== MMTelICBServiceData

Field | Description
--- | ---
Active | Indicates if the feature is active `true` or inactive `false`
Ruleset | Contains the subscriber’s barring rules. Read from the HSS and configurable via XCAP or read from HLR. It is a Java-parsed representation of a Common Policy Ruleset.
Rule.ID | Unique identification for the rule
Rule.conditions | The conditions
Rule.allow | Allow or not allow the session towards the served user
OperatorAuthorized | Operator setting to authorize the feature for the user

=== MMTelFAServiceData

Attribute | Description
--- | ---
Authorized | Indicates if the feature is active `true` or inactive `false`
Identity | The `Pilot Number` URI
Group | The group type for the Flexible Alerting `single-user` or `multiple-users`
Membership | The membership type: `permanent` or `demand`
Members | List of member attached to the `Pilot Number`
Members.Active | If the member can be alerted `true` or `false` if not
Members.Uri | The member URI identity

=== MMTelECTServiceData

Attribute | Description
--- | ---
Authorized | True if the served-user is authorized to engage this operation.

=== MMTelCONFServiceData

Attribute | Description
--- | ---
OperatorAuthorized | Operator setting to authorize the feature for the user

=== MMTelHOLDServiceData

Attribute | Description
--- | ---
OperatorAuthorized | Operator setting to authorize the feature for the user

= MMTelCDIV :toc: macro :toclevels: 4 :toc-title: On this page…​

The Communications Diversion (CDIV) service enables a ‘diverting user’ to divert communications addressed to the ‘diverting user’ to another destination .

The service description of CDIV’s services CFU, CFB, CFNR, and CD is based on the PSTN/ISDN supplementary services; whereas CFNL is a CDIV service based on requirements for IP-based networks; and CFNRc is based on requirements for mobile networks.

The services are:

- Communication Forwarding Unconditional (CFU)

- Communication Forwarding on Busy user (CFB)

- Communication Forwarding on no Reply (CFNR)

- Communication Forwarding on Subscriber Not Reachable (CFNRc)

- Communication Deflection (CD)

- Communication Forwarding on Not Logged-in (CFNL).

== Feature Cheat Sheet

B2BUA Instance | SAS Support | Originating / Terminating | Point(s) in Session Plan | Network Operator Data | Subscriber Data | Stateful or Stateless | POJO Feature or SBB Feature | Other notes
--- | --- | --- | --- | --- | --- | --- | --- | ---
MMTel | Yes | Terminating | `SipAccess_SubscriberPreCreditCheck` `SipAccess_PartyResponse` `SipAccess_ServiceTimer` | Yes | Yes — CDIV rules are stored in the HSS | Stateless w/FSM in Session State | POJO but with much stateful behaviour implemented by storing an FSM instance into Session state | Implications on Charging for Forwarded calls

== Prerequisite Features

- DetermineCallType

- DetermineInitialLegNames

- SubscriberDataLookupFromHSS

- MMTelTIR (only when MMTelTIR is in use)

== Source Code

This feature’s source code is available in the Sentinel VoLTE SDK in the `mmtel-communication-diversion` module pack. It can be viewed by using the `create-module` command in the SDK with that module pack, for example:

`> create-module new-cdiv-module opencloud#mmtel-communication-diversion#volte/3.1.0;3.1.0.0`

This command will prompt you for information needed to create the new modules, once completed the original source for the feature can be found in the new modules.

The module-pack includes the following modules:

Module Name | Description
--- | ---
mmtel-communication-diversion | Group module for the feature that includes all of the modules listed below.
mmtel-cdiv-profile | Contains the profile specification for the feature configuration profile table.
mmtel-cdiv | Contains the feature itself.

== Specification References

- 3GPP TS 24.604 Rel 12: http://www.3gpp.org/ftp/Specs/html-info/24604.htm

- GSMA IR.92 (a subset of 24.604) This feature targets the IR.92 subset.

- RFC 7044 (“The History-Info header RFC”): http://tools.ietf.org/html/rfc7044

- RFC 4458 (“SIP Voicemail URI” — target and cause in request URI) RFC: http://tools.ietf.org/html/rfc4458

=== GSMA IR.92 Reference Information

This is taken from IR.92 v9.0:

2.3.8 Communication Diversion

| The UE and IMS core network must support the SIP procedures in 3GPP TS 24.604 for Communication Diversion (CDIV). For CDIV service activation, deactivation, and interrogation (XCAP operations), the UE and IMS core network must support the XML rules for Call Forwarding Unconditional and the conditions, actions and elements listed in Table 2.2. The UE and IMS core network shall support the XML rules as described in 3GPP TS 24.604 section 4.9.1. The UE must support the History-Info header for identification of diverting parties at the terminating side and of diverted-to parties at the originating side. At the terminating side, a History-Info entry shall be used for the identification of the diverting party only if another History-Info entry exists that has assigned the next index in sequence AND includes a cause value. At the originating side only History-Info entries including a cause value shall be used for presentation of the diverted-to party. Note: Support of subscription options and other conditions and actions are out of scope of the document.

It then shows the following table (reformatted)

Type | Parameter
--- | ---
Rule Condition |
    Busy
Rule Condition |
    media (supported media types: audio, audio AND video)
Rule Condition |
    no-answer
Rule Condition |
    not-registered
Rule Condition |
    not-reachable(Note)
Rule Condition |
    rule-deactivated
Rule Action |
    target
Element |
    NoReplyTimer

| Note: The GSM version of Communication Forwarding on Not Reachable (CFNRc) implies diversion when the user is not registered in the CS core or cannot be reached. To mimic this behaviour, it is recommended that an UE activates both the CFNRc (CDIV using condition not-reachable) and the Communication Forwarding on Not Logged-in (CFNL) (CDIV using condition not-registered) to the same target.

== Scope

=== In Scope

The following are in scope:

- Communication Forwarding Unconditional (CFU)

- Communication Forwarding on Busy user (CFB)

- Support for User Determined User Busy (UDUB)

- Communication Forwarding on No Reply (CFNR)

- Communication Forwarding on Subscriber Not Reachable (CFNRc)

- Communication Deflection (CD)

- Communication Forwarding on Not Logged-in (CFNL)

- Checking of the diversion limits

- Communication Diversion Notification (CDIVN) — 181 responses

=== Out of Scope

The following are out of scope:

- There is no support for “Ringing continues” in the no reply timeout case (option for CFNR).

- There is no support for Network Determined User Busy (NDUB).

- Deliver to last diverted user is not implemented as an approach when Max Diversions has been exceeded. This is because we consider it a bad practice.

== Network Operator Data

Network (or Operator) data may come from two sources:

- Provisioned data in the VoLTE platform stored in a profile table named `MMTelCDIVConfigProfileTable`.

- Received from the HSS in the `<operator-communication-diversion>` section of the CDIV network data fetched from the HSS.

Properties received from the HSS in the `<operator-communication-diversion>` section of an MMTel-Services XML document take precedence over data in the `MMTelCDIVConfigProfileTable`.

=== Platform Network Operator Data

Network configuration is stored in a JSLEE profile table named `MMTelCDIVConfigProfileTable`.

Individual configurations are entries in this table. The data is scoped on Sentinel Selection Key.

Parameter | Type | Default Value | Description
--- | --- | --- | ---
`MaxDiversionCount` | int | `20` | Maximum number of diversion hops that may occur, see the Diversion Limit section.
`MaxDiversionAction` | Enum (`REJECT`, `DELIVER_TO_FIXED_DESTINATION`) | `REJECT` | Determines the action to be taken when the `MaxDiversionCount` is exceeded, see the Diversion Limit section.
`MaxDiversionFixedDestination` | String, must be a valid SIP or Tel URI | `null` | The fixed destination to deliver to when `MaxDiversionAction` is set to `DELIVER_TO_FIXED_DESTINATION`, see the Diversion Limit section.
`NoRetargetURI` | String, comma separated list of SIP and/or TEL URIs | `null` | A list of URIs to which diversions are permitted even when `MaxDiversionCount` is exceeded (e.g. because they are known not to retarget calls), see the Diversion Limit section.
`DefaultTargetURI` | String | `null` | A default URI for use when re-targeting sip requests in the event that there are re-targeting rules and no target URI.
`DefaultTargetEnabled` | Boolean | `false` | A boolean flag indicating whether to apply the procedure for default re-targeting.
`PlayAnnouncement` | boolean | `false` | Determines if an announcement will be played when diversion occurs.
`AnnouncementID` | int | `0` | The announcement ID of the announcement that should be played when diversion occurs.
`VmAnnouncementID` | int | `0` | The announcement ID of the announcement that should be played when diversion to a known voice mail server occurs. If the call should not be allowed to reach the voice mail server if the announcement fails, the announcement must be configured with `EndSessionOnFailure` set to true.
`VmsUris` | String[] | `[]` | The list of known voice mail server URIs. When a call is diverted to one of these URIs, the voicemail announcement will be played if `VmAnnouncementID` is configured.
`NoReplyTimeout` | int | `20` | The maximum time (in seconds) to wait for a reply before triggering CFNR.
`AddOrigTag` | boolean | `false` | Determines whether to add an `orig` tag to an outgoing re-targeted `INVITE` request.
`SuppressForCSTerminatingDomain` | boolean | `false` | Determines whether CDIV’s behaviour should be suppressed when a call is on a CS network, see the CDIV Suppression section.
`AdditionalNotReachableStatusCodes` | int[] | `[]` | Can be used to trigger the CDIV not-reachable condition (CFNRc) with SIP response status codes not included in the CFNRc specification. This list may not include status codes that have other purposes in CDIV (i.e. 1xx, 2xx, 404, 408, 486, 487).
`AllowNotReachableDuringAlerting` | boolean | `false` | A flag that when set to true, will allow the CDIV not-reachable condition to trigger when the call is in the alerting state (usually this condition only triggers in the pre-alerting state).
`AddMpParam` | boolean | `false` | Determines whether to add `hi-target-param` headers (of type `mp`) to the added `hi-entry`.
`NonProvisionableRetargetURIs` | String[] | `[]` | A list of URIs that are not provisionable as a retarget URI, i.e. they are not allowed to be used as the target of a diversion.
`PreferSubscriberConfig` | boolean | `false` | Determine whether the subscriber provisioned diversion rules override the operator provisioned rules (these are the rules within the <communication-diversion> and <operator-communication-diversion> tags respectively).
`EnableDefaultForwardToVoicemail` | boolean | `false` | Determine whether the feature should divert to voicemail if call is unsuccessful
`DefaultForwardToVoicemailTimeout` | int | `60` | The maximum time (in seconds) to wait before forwarding to voicemail
`DefaultForwardToVoicemailWithoutCredit` | Enum (`NEVER_ALLOW`, `ALLOW_ONLY_FOR_WELL_KNOWN_SERVERS`. `ALWAYS_ALLOW`) | `NEVER_ALLOW` | Determines whether a call can be diverted to a subscriber’s voicemail server when credit could not be allocated.

=== HSS Network Operator Data

There are three elements of `<operator-communication-diversion>` received from the HSS that the CDIV feature may apply.

Element | Description
--- | ---
    <total-number-of-diversions-for-each-communication>
                        3
    </total-number-of-diversions-for-each-communication>
| This property, if present, take precedence over the `MaxDiversionCount` property of the Platform Network Operator Data profile. See the Diversion Limit section
    <communication-forwarding-on-no-reply-timer>
                       30
    </communication-forwarding-on-no-reply-timer>
| This property, if present, take precedence over the `NoReplyTimeout` property of the Platform Network Operator Data profile.
    <cp:ruleset>
        <cp:rule id="busy">
            <cp:conditions>
                <busy/>
            </cp:conditions>
            <cp:actions>
                <forward-to>
                    <target>sip:bob@someplace.com</target>
                    <notify-caller>false</notify-caller>
                </forward-to>
            </cp:actions>
        </cp:rule>
    </cp:ruleset>
| The CDIV feature supports an extension to the standard that allows an operator ruleset to be defined. Operator rules are evaluated before other rules, unless the PreferSubscriberConfig field is set to `true`.

The other child elements of `<operator-communication-diversion>` are not read by the CDIV feature.

| The schema for the Operator part of the Communication Diversion (CDIV) services has been extended to support an optional ruleset.

=== HSS Metaswitch TAS Data

Default Forward to Voicemail functionality depends on subscriber data provisioned in `Forward-To-Voicemail` section of the Metaswitch-TAS-Services document in the HSS.

The following attribute from that section is used:

Name | Type | Description
--- | --- | ---
    voicemailServer
| String | The URI for the voicemail server to connect to.

See the Metaswitch-TAS-Services Schema to Session-State Fields mapping for more details about the Metaswitch-TAS-Services document.

== Session Input Variables

Session State variable name | Type | Comments
--- | --- | ---
    MMTelCDIVServiceData
| Complex | Read from the HSS or HLR in SubscriberDataLookupFromHSS or SubscriberDataLookupFromHLR

== Session Output Variables

Session State variable name | Type | Comments
--- | --- | ---
    DiversionCounter
| int | The number of re-targeting attempts caused by the feature in one Session, whether immediate or due to a response
    HiLastReceivedIndex
| String | The index for the history-info received in the initial `INVITE`
    HistoryInfoHeaders
| String [] | The latest history-info headers sent or received
    LastDiversionType
| DiversionType (an enum) | One of: `none`, `CFU`, `CFNL`, `CFNR`, `CFB`, `CFNRc`, `CDImmediate`, `CDAlerting`, or `Media`
    EarlyMediaAnnouncementQueue
| List<Integer> | Updated announcement queue with diversion announcement id if any

== Statistics

MMTelCDIV statistics are tracked by the volte.sentinel.sip SBB and can be found under the following parameter set in REM:
SLEE-Usage → volte.sentinel.sip service → volte.sentinel.sip SBB → feature → MMTelCDIV
or with rhino-stats:
"SLEE-Usage.Services.ServiceID[name=volte.sentinel.sip,vendor=OpenCloud,version=3.1.0].SbbID[name=volte.sentinel.sip,vendor=OpenCloud,version=3.1.0].feature.MMTelCDIV"

Statistic | Incremented when…​
--- | ---
    Started
| the feature runs
    FailedToStart
| Sentinel VoLTE encounters an error while attempting to start the feature
    IssuedWarning
| a non-fatal problem is encountered and the feature issues a warning
    FailedDuringExecution
| a fatal problem is encountered and the feature cannot execute correctly
    TimedOut
| the feature takes too long to complete and Sentinel VoLTE aborts execution
    Misconfigured
| the feature configuration could not be loaded
    ProcessingSipResponse
| the feature is triggered on a SIP response
    ProcessingSipRequest
| the feature is triggered on a SIP request
    ProcessingChargingEvent
| the feature is triggered on a OCS event
    LegManagerError
| a problem occurs while trying to access data from the SIP leg manager
    ErrorProcessingSipRequest
| a problem occurs while trying to read or modify to a SIP request
    ErrorProcessingSipResponse
| a problem occurs while trying to read or modify to a SIP response
    DiversionLoopDetected
| diversion is aborted due to a diversion loop being detected
    DiversionLimitExceeded
| diversion is aborted due to the diversion limit being hit
    CancelledInviteRequest
| the CDIV feature cancels an `INVITE` on the terminating leg
    ErrorCancellingInviteRequest
| a problem occurs while attempting to cancel an `INVITE` request
    ReleasedDownstreamLeg
| caller is being diverted to voicemail
    TerminatedByResponse
| CDIV is aborted by sending an error response on the originating leg
    TerminatedByRetargeting
| CDIV is aborted by attempting to divert to a fixed final destination
    ErrorTerminatingByRetargeting
| diversion fails while trying to terminate by re-targeting
    NoReplyTimerSet
| the feature sets a timer for CFNR
    NoReplyTimerCancelled
| the feature cancels a timer for CFNR
    NoReplyTimerFired
| the feature is triggered by a CFNR timer expiring
    TimerSuppressedByResponseFromCSDomain
| timer is suppressed when parallel fork is done and the CS domain answers first
    CDIVSuppressedByResponseFromCSDomain
| CDIV service is suppressed when parallel fork is done and the CS domain answers first
    CallerNotifiedOfDiversion
| the feature notify the caller the session is being diverted
    FailedToNotifyCallerOfDiversion
| the feature fails to notify the caller the session is being diverted
    CFUSucceeded
| unconditional call forwarding is successfully executed
    CFUFailed
| a fatal problem occurs while trying to execute unconditional call forwarding
    CFNLSucceeded
| call forwarding due to the target user not being logged into IMS is successfully executed
    CFNLFailed
| a fatal problem occurs while trying to execute call forwarding due to the target user not being logged into IMS
    CFNRSucceeded
| call forwarding due to the target user not replying is successfully executed
    CFNRFailed
| a fatal problem occurs while trying to execute call forwarding due to the target user not replying
    CFBSucceeded
| call forwarding due to the target user being busy is successfully executed
    CFBFailed
| a fatal problem occurs while trying to execute call forwarding due to the target user being busy
    CFNRcSucceeded
| call forwarding due to the target user being unreachable is successfully executed
    CFNRcFailed
| a fatal problem occurs while trying to execute call forwarding due to the target user being unreachable
    CDImmediateSucceeded
| call forwarding due to immediate call deflection is successful.
    CDImmediateFailed
| a fatal problem occurs while trying to execute call forwarding due to immediate call deflection
    CDAlertingSucceeded
| call forwarding due to call deflection during alerting is successful
    CDAlertingFailed
| a fatal problem occurs while trying to execute call forwarding due to call deflection during alerting
    ToHeaderChanged
| 'To' header is set to diverted party or served user
    SubscriberCDIVAttempted
| call forwarding due to subscriber rules was attempted, either succesfully or unsuccesfully
    OperatorCDIVAttempted
| call forwarding due to operator rules was attempted, either succesfully or unsuccesfully
    DivertingCallToVoicemail
| call is being forwarded to voicemail
    ExecutingDefaultForwardToVoicemail
| call is being re-targeted to voicemail
    ErrorExecutingDefaultForwardToVoicemail
| a fatal problem occured while re-targeting to voicemail
    DefaultForwardToVoicemailTimerSet
| the default forward to voicemail timer has been started
    DefaultForwardToVoicemailTimerCancelled
| the default forward to voicemail timer has been cancelled
    DefaultForwardToVoicemailTimerFired
| the default forward to voicemail timer has fired, call will be diverted to voicemail

== Behaviour

If `MMTelCDIVServiceData.OperatorAuthorized` is `false` and `EnableDefaultForwardToVoicemail` is `false`, the feature finishes execution without modifying any state.

If `MMTelCDIVServiceData.OperatorAuthorized` is `false` and `EnableDefaultForwardToVoicemail` is `true`, the feature runs in voicemail-only mode, ignoring CDIV rules, but enabling the default forward to voicemail functionality.

=== Condition Evaluation

Triggered conditions and non-triggered conditions are part of CDIV rule and condition evaluation.

- Triggered conditions include:

  - Communication Forwarding on Busy user (CFB)

  - Communication Forwarding on No Reply (CFNR)

  - Communication Forwarding on Subscriber Not Reachable (CFNRc)

  - Communication Deflection (CD)

  - Communication Forwarding on Not Logged-in (CFNL)

  - Communication Forwarding Unconditional (CFU)

| Triggered conditions are mutually exclusive, therefore if more than one is in a rule the rule will evaluate to false.

- Non-triggered conditions include:

  - Media Type

  - Validity.

| Non-triggered conditions can evaluate to `true` in any type of diversion. Triggered conditions can only evaluate to `true` at particular points of session processing.

Triggered condition name | Applicable point in session | XML condition element value from HSS
--- | --- | ---
Communication Forwarding on Busy user (CFB) | `486-BUSY` response | `<cp:conditions><busy/></cp:conditions>`
Communication Forwarding on No Reply (CFNR) | A 180 Ringing response followed by a `408` response, or a 180 Ringing response followed by No Reply timer expiry | `<cp:conditions><no-answer/></cp:conditions>`
Communication Forwarding on Subscriber Not Reachable (CFNRc) | `500`, `503`, or `408` response prior to a `180` response, or a response with a status code included in the `AdditionalNotReachableStatusCodes` configuration parameter. Usually only triggers in pre-alerting call state, but can be configured to trigger during alerting (except on `408` responses) using the `AllowNotReachableDuringAlerting` configuration parameter. | `<cp:conditions><not-reachable/></cp:conditions>`
Communication Deflection (CD) | `302` response | Not configurable through XCAP
Communication Forwarding on Not Logged-in (CFNL) | Receipt of `INVITE` request | `<cp:conditions><not-registered/></cp:conditions>`
Communication Forwarding Unconditional (CFU) | Receipt of `INVITE` request | `<cp:conditions/>`

==== OC-Retarget Header

The OC-Retarget header is added by MMTel CDIV to communicate that a diversion has occurred. This header is inserted into the initial INVITE that goes towards the diverted party. This is then used in the composition to decide whether to invoke the SCC-AS.

For more details see OC-Retarget Header

==== Media

Media is evaluated as part of condition evaluation. Therefore CFB can cause a re-targeting to different destinations if there are several diversion rules with busy and media conditions.

Media-only conditions can be used to immediately re-target `INVITE` requests matching media conditions.

An example where all sessions that contain both audio and video are diverted is as follows:

    <cp:conditions>
        <media>video</media>
        <media>audio</media>
    </cp:conditions>

Each `<media>` element value is searched against all media descriptions in the `INVITE` request SDP. If all media conditions match, then the conditions block evaluates to `true`.

==== Validity

Validity provides the ability to filter a condition based on date comparisons. For example:

    <cp:conditions>
        <busy/>
        <cp:validity>
            <cp:from>2015-01-01T00:00:00</cp:from>
            <cp:until>2015-01-31T23:59:59</cp:until>
        </cp:validity>
    </cp:conditions>

This conditions block will evaluate to `true` if the condition is evaluated during January 2015.

==== Deflection and CDIV

There is no XCAP rule for receipt of `302`, yet the CDIV specification clearly describes the re-targeting of the `INVITE` due to a `302` response.

We interpret this as hardcoded behaviour of the CDIV feature.

=== Request URI for a Re-targeted INVITE

The request URI is set to the SIP URI or tel URI where the communication is being diverted to. This URI is normalized using the Normalization Component.

This comes from the `<target>` sub-element of the `<forward-to>` element in a CDIV rule’s actions:

    <cp:actions>
        <forward-to>
            <target>sip:+6505550201@example.com</target>
        </forward-to>
    </cp:actions>

It may or may not have a target parameter, and always has a cause parameter and MMTel service type parameter.

==== Target Parameter

The request URI has a target parameter if and only if the re-targeting is due to a response, such as in the following cases:

- busy

- no-answer

- deflection

- not-reachable.

The target parameter is set to the request URI for the received initial `INVITE`, including all parameters. Any parameters of the original request URI are in escaped format. This is to ensure that the SIP message has valid syntax.

Conversely, if communication forwarding is due to `Unconditional`, or `Not Logged In`, then there is no target parameter in the request URI.

==== Cause Parameter

There is always a cause parameter for every re-targeted `INVITE`.

The `cause-param` parameter of the request URI is simple `cause=` appended with a “cause value”.

Cause | Cause Value | Determination Rule
--- | --- | ---
    Communication Forwarding on Busy
    486
| `UDUB`—`486` Response received
    Communication Forwarding on No Reply
    408
| `CDIV No Reply Timer`, or a `408` response after a `180-RINGING` response
    Communication Forwarding Unconditional
    302
| `CFU`
    Communication Deflection (immediate response)
    480
| Immediate deflection: `302` received before `180-RINGING` response is received
    Communication Forwarding not logged in
    404
| `CFNL`
    Communication Deflection during alerting
    487
| deflection: 302 received after 180-RINGING is received
    Communication Forwarding Subscriber not Reachable
    503
| `500`, `503`, or `408` response prior to a `180-RINGING` response, or a response with a status code included in the `AdditionalNotReachableStatusCodes` configuration parameter. Usually only triggers in pre-alerting call state, but can be configured to trigger during alerting (except on `408` responses) using the `AllowNotReachableDuringAlerting` configuration parameter.

==== MMTel Service Type Parameter

There is always a MMTel service type for every re-targeted `INVITE`.

The `mmtel-service-type` parameter of the request URI is simple `mmtel-service-type=6` for CDIV.

==== 181 Responses

A `181` notification is sent to the calling party in a CDIV scenario if the `<notify-caller>` element is set to `true` or if the element is missing from the condition. For example:

    <cp:conditions/>
        <cp:actions>
            <forward-to>
                <target>sip:+6505550201@example.com</target>
                <notify-caller>true</notify-caller>
            </forward-to>
        </cp:actions>

| A `181` notification will not be sent if the `<notify-caller>` element is set to `false`.

==== Reveal Served User Identity to Caller

There is an optional flag that determines whether the identity of the served user is revealed to the calling party on `181` responses or not.

    <cp:conditions/>
        <cp:actions>
            <forward-to>
                <target>sip:+6505550201@example.com</target>
                <notify-caller>true</notify-caller>
                <reveal-served-user-identity-to-caller>false</reveal-served-user-identity-to-caller>
            </forward-to>
        </cp:actions>

- If `reveal-served-user-identity-to-caller` is set to `false`, or if TIR is enabled, then the `privacy` header on the History-Info entry for the served user is set to `history`, and the `privacy` header on the response is set to `id`.

- If `reveal-served-user-identity-to-caller` is set to `not-reveal-gruu`, and the target URI on the History-Info entry for the served user contains a `gr` parameter, it is replaced by the asserted identity of the served user.

- If `reveal-served-user-identity-to-caller` is omitted, the default is `true`.

==== Reveal Diverted-To User Identity to Caller

There is an optional flag that determines whether the identity of the diverted-to user is revealed to the calling party on `181` responses or not.

    <cp:conditions/>
        <cp:actions>
            <forward-to>
                <target>sip:+6505550201@example.com</target>
                <notify-caller>true</notify-caller>
                <reveal-identity-to-caller>false</reveal-identity-to-caller>
            </forward-to>
        </cp:actions>

- If `reveal-identity-to-caller` is set to `false`, then the `privacy` header on the History-Info entry for the diverted-to user is set to `history`.

- If `reveal-identity-to-caller` is omitted, the default is `true`.

==== Reveal Served User Identity to Diverted-To Party

There is an optional flag - reveal-identity-to-target - that determines whether the identity of the diverting party is revealed to the diverted-to party in the diverted INVITE request or not.

    <cp:conditions/>
        <cp:actions>
            <forward-to>
                <target>sip:+6505550201@example.com</target>
                <notify-caller>true</notify-caller>
                <reveal-identity-to-target>false</reveal-identity-to-target>
            </forward-to>
        </cp:actions>

- If `reveal-identity-to-target` is set to false, or if OIR is active, then the `To` header is modified to the SIP identity of the diverted-to party, and the `privacy` header on the History-Info entry for the served user is set to `history`.

- If `reveal-identity-to-target` is set to `not-reveal-gruu`, and the `To` header contains a `gr` parameter, the `To` header and the History-Info entry for the served user are set to the asserted identity of the served user.

- If `reveal-identity-to-target` is set to `true`, then the `To` header is the SIP identity of the diverting party.

- If `reveal-identity-to-target` is omitted, the default is `true`.

=== One Re-targeted INVITE

The MMTelCDIV feature will only ever re-target once. This is because MMTelCDIV is designed to execute on a public network. Private network derivations of this feature do not need to follow this rule.

As the feature re-targets once, it will insert one history-info element into one `INVITE` to represent a re-targeting.

The only case the feature inserts more than one element into history-info is in the case where no history-info or an empty history-info was received in the initial `INVITE`.

=== CDIV Suppression

There is a case where the CDIV feature needs to be suppressed even though it may be active. This is needed on an MT call, when the SCC-AS diverts a call to a CS network as the MSC will have its own CDIV services. This means that, when the call is diverted to CS, the MMTel-AS does not divert any calls, and cancels any remaining no-reply timers. If the SCC-AS utilizes parallel-routing (i.e. forwards call to both PS and CS domain), the MMTel-AS will respond in the same way.

CDIV suppression is achieved by analysing the provisional responses for the given call. These responses contain the `OC-Terminating-Domain` custom header, which indicates what network the call is diverted to. Because the `no-reply` timers are typically set upon provisional responses (i.e. 18X responses), it is here that CDIV suppression is engaged/disengaged.

The presence of CDIV suppression is configurable. Setting the `SuppressForCSTerminatingDomain` attribute of the `MmtelCDIVConfigProfile` profile to `true` will enable the aforementioned CDIV suppression. Its default value is `false`, which leaves CDIV suppression disabled.

=== CDIV Default Target URI

The CDIV feature can optionally use a default URI for re-targeting requests. The default URI is stored in the `DefaultTargetURI` field as a String. This default URI is applied when there is a re-targeting rule and no URI to forward to. The default re-targeting URI can be enabled using the `DefaultTargetEnabled` boolean variable.

=== CDIV No Reply Timer

When CDIV sees a `180 Ringing` response, it will check to see if there are any rules relevant to Communication Forwarding on No Reply (CFNR). If there is at least one relevant rule, CDIV sets a `CDIV No Reply Timer`. The duration of the timer is:

1. the `<communication-forwarding-on-no-reply-timer>` value in the `<operator-communication-diversion>` section of the MMTel-Services XML data, if present

2. …​ or the Network Operator Data `NoReplyTimeout` field

=== Default Forward to Voicemail

The CDIV feature can be configured to re-target a call to voicemail. This is configured via the feature configuration field `EnableDefaultForwardToVoicemail`. The re-target destination voicemail server is provisioned in the `<voicemail-server>` value in the `<forward-to-voicemail>` section of the subscriber’s Metaswitch TAS XML data. If configured, the CDIV feature sets a `Default Forward To Voicemail Timer` when processing the initial INVITE. The duration of the timer is based on the `DefaultForwardToVoicemailTimeout` feature configuration.

The re-target to voicemail will occur if:

- the `Default Forward To Voicemail Timer` expires;

- the called subscriber has no provisioned diversion rules but is busy or not logged in; or

- the called subscriber has provisioned diversion rules, but the diversion is terminated without initiating a further retarget; or

- credit could not be allocated for the call and configuration allows the voicemail server to be contacted without credit (see below).

==== Announcements

If `PlayAnnouncement` is `true` and an announcement is configured, then the announcement will be played before diverting the call to the subscriber’s voicemail server. If `VmAnnouncementID` is configured and the subscriber’s voicemail server matches one the URIs in `VmsUris`, then the voicemail announcement will be played. If the subscriber’s voicemail server does not match any of the URIs in `VmsUris`, or if `VmAnnouncementID` is not configured, then the default `AnnouncementID` announcement will be played (if it is configured).

==== Credit Not Allocated

Default forward to voicemail may be executed when using online charging if credit is required to deliver the call but:

- the subscriber does not have enough credit; or

- the OCS failed; or

- charging procedures were deliberately aborted by Sentinel.

This behaviour depends on the value of the `DefaultForwardToVoicemailWithoutCredit` field in feature configuration:

Value | Behaviour
--- | ---
    NEVER_ALLOW
| Default forward to voicemail will not execute.
    ALLOW_ONLY_FOR_WELL_KNOWN_SERVERS
| Default forward to voicemail will execute if the subscriber’s voicemail server URI is present in the `VmsUris` list the feature configuration.
    ALWAYS_ALLOW
| Default forward to voicemail will always execute if credit cannot be executed.

| If this behaviour is triggered then the online charging session will be finalised, after which no further updates will be sent to the OCS.

=== Diversion Limit

The CDIV feature enforces a limit on the maximum number of times a call may be diverted, this limit is:

1. the `<total-number-of-diversions-for-each-communication>` value in the `<operator-communication-diversion>` section of the MMTel-Services XML data, if present

2. …​ or the `MaxDiversionCount` field in the feature’s network operator data.

Before a call is diverted, this limit is checked against the number of diversions that have already occurred to ensure the new diversion can go ahead.

When the diversion limit is exceeded there are a number of things that can happen based on these Network Operator Data fields: `NoRetargetURI`, `MaxDiversionAction`, and `MaxDiversionFixedDestination`.

First, the feature will check the value of the next target URI against the list of URI’s in the `NoRetargetURI` field. This field contains a comma separated list of known URI’s that will never themselves trigger additional re-targeting. If the next target URI is equal to a URI on this list, after both are normalized using the Normalization Component, the feature considers it "safe" to allow the diversion to take place and the diversion limit will not be immediately enforced.

In the event that the next target URI is not in the `NoRetargetURI` list, the feature will execute its max diversion behaviour. There are two possible outcomes, based on the value of the `MaxDiversionAction` field.

1. If the field is set to `REJECT`, then the feature will reject the INVITE request with a 486 response in the event that the last re-target was triggered by CFB (Call Forward Busy), or a 480 response in all other cases.

2. If the field is set to `DELIVER_TO_FIXED_DESTINATION`, then the feature will attempt to re-target the call to the URI given in the `MaxDiversionFixedDestination` field.

If the `MaxDiversionAction` field is set to `DELIVER_TO_FIXED_DESTINATION`, but the `MaxDiversionFixedDestination` field does not contain a valid URI, then the feature will reject the INVITE as if `MaxDiversionAction` field had been set to `REJECT`.

If the `MaxDiversionAction` field is set to `DELIVER_TO_SUBSCRIBERS_VOICEMAIL_SERVER`, the feature will re-target the call towards voicemail. If a retarget to voicemail has already occurred the feature will reject the INVITE as if `MaxDiversionAction` field had been set to `REJECT`.

=== Choosing the CDIV Rule to Apply

The `<communication-diversion>` and `<operator-communication-diversion>` sections of the MMTel-Services XML document can contain diversion rules. A rule may be relevant for a diversion scenario (e.g CFB) and it may be applicable to a particular communication session (i.e its condition evaluates to true).

The CDIV feature:

1. finds all rules that are appropriate for a diversion scenario (e.g CFU)

2. evaluates the operator rules first

3. If no operator rule was applied, then evaluate subscriber rules

Consider the following example, where there are two rules relevant for CFU.

    <complete-communication-diversion>
      <communication-diversion active="true">
        <!-- ... -->
        <cp:ruleset>
          <cp:rule id="Audio">
            <cp:conditions>
              <media>audio</media>
            </cp:conditions>
            <cp:actions>
              <forward-to>
                <target>sip:bob@audio.somewhere.com</target>
                <notify-caller>false</notify-caller>
              </forward-to>
            </cp:actions>
          </cp:rule>
        </cp:ruleset>
      </communication-diversion>
      <operator-communication-diversion authorized="true">
        <!-- ... -->
        <cp:ruleset>
          <cp:rule id="Video">
            <cp:conditions>
              <media>video</media>
            </cp:conditions>
            <cp:actions>
              <forward-to>
                <target>sip:bob@video.somewhere.com</target>
                <notify-caller>false</notify-caller>
              </forward-to>
            </cp:actions>
          </cp:rule>
        </cp:ruleset>
      </operator-communication-diversion>
    </complete-communication-diversion>

The subscriber rule will cause `audio` calls to be forwarded to `sip:bob@audio.somewhere.com`. The operator rule will cause `video` calls to be forwarded to `sip:bob@video.somewhere.com`.

case #1 Alice makes a `Video` call to bob.

1. Search operator rules and evaluate rule 'Video', which matches, so forward the call.

    ---alice---[Video]--->bob----->(rule id="Video")---->bob@video.somewhere.com

case #2 Alice makes an `Audio` call to bob.

1. Search operator rules and evaluate rule 'Video', which does not match

2. Search subscriber rules and evaluate rule 'Audio`, which matches, so forward the call.

    ---alice---[Audio]--->bob--+-->(rule id="Video") X
                               |
                               +-->(rule id="Audio")---->bob@audio.somewhere.com

=== Non-Provisionable Retarget URIs

It is possible to configure a list of `NonProvisionableRetargetURIs` in the feature configuration. Retargeting to these URIs is not permitted. When selecting the CDIV rule to apply, any rules whose target URI (after normalization) matches a URI on the `NonProvisionableRetargetURIs` list (after normalization), are ignored. Normalization is done using the Normalization Component.

== Example CDIV Rules

For clarity, here are some example CDIV rules.

They can be pasted directly into the Transparent Data editor in REM.

- CDIV Unconditional

- CDIV Busy

- CDIV Not Reachable

- CDIV No Reply

- CDIV Not Logged-in

=== CDIV Unconditional

    <cp:ruleset xmlns="http://uri.etsi.org/ngn/params/xml/simservs/xcap" xmlns:cp="urn:ietf:params:xml:ns:common-policy">
        <cp:rule id="unconditional">
            <cp:conditions>
            </cp:conditions>
            <cp:actions>
                <forward-to>
                    <target>sip:+6505550201@example.com</target>
                    <notify-caller>false</notify-caller>
                </forward-to>
            </cp:actions>
        </cp:rule>
    </cp:ruleset>

=== CDIV Busy

    <cp:ruleset xmlns="http://uri.etsi.org/ngn/params/xml/simservs/xcap" xmlns:cp="urn:ietf:params:xml:ns:common-policy">
        <cp:rule id="busy">
            <cp:conditions>
                <busy/>
                <media>video</media>
                <media>audio</media>
            </cp:conditions>
            <cp:actions>
                <forward-to>
                    <target>sip:+6505550201@example.com</target>
                    <notify-caller>true</notify-caller>
                </forward-to>
            </cp:actions>
        </cp:rule>
    </cp:ruleset>

=== CDIV Not Reachable

    <cp:ruleset xmlns="http://uri.etsi.org/ngn/params/xml/simservs/xcap" xmlns:cp="urn:ietf:params:xml:ns:common-policy">
        <cp:rule id="not-reachable">
            <cp:conditions>
                <not-reachable/>
                <cp:validity>
                    <cp:from>2015-01-01T00:00:00</cp:from>
                    <cp:until>2015-01-31T23:59:59</cp:until>
                </cp:validity>
            </cp:conditions>
            <cp:actions>
                <forward-to>
                    <target>sip:+6505550201@example.com</target>
                    <notify-caller>true</notify-caller>
                </forward-to>
            </cp:actions>
        </cp:rule>
    </cp:ruleset>

=== CDIV No Reply

    <cp:ruleset xmlns="http://uri.etsi.org/ngn/params/xml/simservs/xcap" xmlns:cp="urn:ietf:params:xml:ns:common-policy">
        <cp:rule id="no-answer">
            <cp:conditions>
                <no-answer/>
            </cp:conditions>
            <cp:actions>
                <forward-to>
                    <target>sip:+6505550201@example.com</target>
                    <notify-caller>true</notify-caller>
                </forward-to>
            </cp:actions>
        </cp:rule>
    </cp:ruleset>

=== CDIV Not Registered

    <cp:ruleset xmlns="http://uri.etsi.org/ngn/params/xml/simservs/xcap" xmlns:cp="urn:ietf:params:xml:ns:common-policy">
        <cp:rule id="not-registered">
            <cp:conditions>
                <not-registered/>
            </cp:conditions>
            <cp:actions>
                <forward-to>
                    <target>sip:+6505550201@example.com</target>
                    <notify-caller>true</notify-caller>
                </forward-to>
            </cp:actions>
        </cp:rule>
    </cp:ruleset>

= MMTelCW :toc: macro :toclevels: 4 :toc-title: On this page…​

The Communication Waiting (CW) service lets a UE be informed that no resources are available for an incoming communication . The user then has the choice of accepting, rejecting, or ignoring the incoming communication (as per basic communication procedures).

== Feature cheat sheet

B2BUA Instance | SAS Support | Originating / Terminating | Point in Session Plan | Network Operator Data | Subscriber Data | Stateful or Stateless | POJO Feature or SBB Feature | Other notes
--- | --- | --- | --- | --- | --- | --- | --- | ---
MMTEL | Yes | Terminating | `SipAccess_SubscriberPreCreditCheck` `SipAccess_PartyResponse` `SipAccess_ServiceTimer` | Yes | Yes, Active flag stored in the HSS | Stateless w/FSM in session state | POJO but with much stateful behaviour implemented by storing an FSM instance into session state | Raises session state flags to enable interaction with announcement playing (or other notification) features

== Prerequisite features

- DetermineCallType

- DetermineInitialLegNames

- SubscriberDataLookupFromHSS or SubscriberDataLookupFromHLR

== Source Code

This feature’s source code is available in the Sentinel VoLTE SDK in the `mmtel-communication-waiting` module pack. It can be viewed by using the `create-module` command in the SDK with that module pack, for example:

`> create-module new-cw-module opencloud#mmtel-communication-waiting#volte/3.1.0;3.1.0.0`

This command will prompt you for information needed to create the new modules, once completed the original source for the feature can be found in the new modules.

The module-pack includes the following modules:

Module Name | Description
--- | ---
mmtel-communication-waiting | Group module for the feature that includes all of the modules listed below.
mmtel-cw-profile | Contains the profile specification for the feature configuration profile table.
mmtel-cw | Contains the feature itself.

== Description

When a call arrives towards the destination user and the user is already involved in a call, the user is alerted and has a choice of either accepting, ignoring, or rejecting the communication. For example: the destination user is already on a call; notification for a new call is delivered; and the user can decide to put the existing call on hold or reject the new call.

A notification may be offered to the destination user if the network or UE has determined the Approaching Busy condition. Approaching Busy can be in the forms of:

- Approaching Network Determined User Busy (A-NDUB) — the network (including the MMTEL AS) determines that the user is Approaching Busy, or

- Approaching User Determined User Busy (A-UDUB) — the user equipment determines that the user is Approaching Busy.

This feature targets the IR.92 scope for Communication Waiting. Therefore, support for A-UDUB is included, and A-NDUB is not.

The calling user may be offered an in-band (audio) announcement, subject to network configuration.

Communication Waiting is a terminating feature.

=== User Determined User Busy (UDUB)

Communication arrived at the UE, and the UE has determined the Approaching User Busy condition, for any reason. For example, the user is on a call, and maximum number of waiting communications has been reached. The UE shall reject communication with an appropriate SIP response.

=== Approaching User Determined User Busy (A-UDUB)

Communication arrived at the UE, and the UE has determined Approaching User Busy condition, for any reason. For example, the user is on a call, and maximum number of waiting communications has not been reached. The UE shall reject communication with an appropriate SIP response.

== Network data

Network operator data is stored in a JSLEE configuration profile with a profile table name of: `MMTelCWConfigProfileTable`.

Variable Name | Type | Constraint | Default | Default Value Interpretation | Note
--- | --- | --- | --- | --- | ---
    CWTimerCW
| Integer | 0, 30..120 | 0 | Timer doesn’t apply | Time in seconds for Communication Waiting timer
    CWAnnouncementID
| Integer |  | 0 | CW calling user not notified | ID for an announcement to be played if Calling User Notifications are enabled
    CWCallingUserNotification
| Boolean |  | False | Do not notify the calling User |

== Session input variables

Field | Type | Default | Interpretation | Note
--- | --- | --- | --- | ---
    MMTelCWServiceData
| Complex |  |  | Read from the HSS or HLR in SubscriberDataLookupFromHSS or SubscriberDataLookupFromHLR
    CWCallingUserNotification
| Boolean | false | True | If calling user to receive announcement

== Session output variables

Name | Type | Meaning
--- | --- | ---
    AnnouncementID
| Int | The ID of the announcement to be played, or zero if no announcement if the feature did not request an announcement
    CWAnnouncement
| Boolean | If true, the MMTelCW feature has indicated that an announcement should be played. The AnnouncementID field will also be set if this flag is set. Otherwise no announcement should be played
    RanCW
| Boolean | Signals to other features that CW ran on this session.

If the calling user should be notified of an Approaching UDUB condition, the Communication Waiting feature sets the CWAnnouncement session state flag indicating that an announcement should be played. It also sets the AnnouncementID field, indicating that an announcement should be played.

== Statistics

MMTelCW statistics are tracked by the sentinel.volte.sip SBB and can be found under the following parameter set in REM:
SLEE-Usage → sentinel.volte.sip service → sentinel.volte.sip SBB → feature → MMTelCW
or with rhino-stats:
"SLEE-Usage.Services.ServiceID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].SbbID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].feature.MMTelCW"

Statistic | Incremented when…​
--- | ---
    Started
| the feature runs
    FailedToStart
| Sentinel VoLTE encounters an error while attempting to start the feature
    IssuedWarning
| a non-fatal problem is encountered and the feature issues a warning
    FailedDuringExecution
| a fatal problem is encountered and the feature cannot execute correctly
    TimedOut
| the feature takes too long to complete and Sentinel VoLTE aborts execution
    Misconfigured
| a fatal error if the feature configuration can not be loaded
    TimerError
| there is an error while trying to set a timer
    TimerCancelled
| a timer is cancelled by the feature
    TimerSet
| a timer is set by the feature
    ProcessingResponse
| the feature is invoked on receiving a SIP response
    ProcessingTimerEvent
| the feature is invoked on a timer firing
    OutgoingMessageContentChanged
| the feature changes the contents of an outgoing SIP message
    ReattemptedCallSetup
| the feature requests that call set up be reattempted
    Triggered180AUDUBResponse
| the feature requests a 180 response be sent back to the original caller, indicating call waiting service
    PlayAnnouncementTriggered
| the feature triggers an announcement to be played
    CancelledInviteRequest
| the feature cancels an outgoing `INVITE`
    FinalResponseChangedTo486
| the feature changes a SIP response status code to `486` before forwarding the response
    FinalResponseChangedTo480
| the feature changes a SIP response status code to `480` before forwarding the response

== Feature interactions

When handling responses, `CDIV No Answer` and `CDIV Busy` must run after `CW`. `CW` may return a `480` (no answer condition) or `486` response (busy).

== Behaviour

If `MMTelCWServiceData.OperatorAuthorized` or `MMTelCWServiceData.Active` is `false`, the feature finishes execution without modifying any state.

User equipment can signal an Approaching User Determined User Busy (A-UDUB) by placing certain headers in responses passed back.

The MMTelCW feature looks for these inside responses:

- In the case of a `180-RINGING` response to an initial `INVITE`, the response contains an `Alert-Info` header with the header’s value set to `<urn:alert:service:call-waiting>` if the UE wishes to communication A-UDUB.

- In the case of a `486-BUSY` response to an initial `INVITE`, the response contains a `370` warning header with the value set to `insufficient bandwidth` if the UE wishes to communicate A-UDUB.

As a simplification, consider Communication Waiting where there is no Announcement to the A-party. In this case, there are two main “modes of operation” for Communication Waiting:

- a pure routing B2BUA that largely passes requests+responses between SIP dialogs

- a routing B2BUA that initiates new transactions, sometimes acting like a UAC.

The differences in behaviour are best explained with a few key flows. In these flows we simplify the IMS signalling by showing three nodes, UE-A, the MMTEL-AS (AS), and UE-B.

=== 180 Ringing Response handling

==== 180 response — not due to A-UDUB

The `180` response from UE-B is forwarded onto the SIP dialog towards UE-A (that is, forwarded upstream).

==== 180 response — due to A-UDUB

The CW feature forwards the `180` response upstream and arms a timer. If the timer fires before UE-B answers the call, the CW feature cancels the INVITE towards UE-B.

=== 486 Busy Response handling

==== 486 response — not due to A-UDUB

The `486` response from UE-B is forwarded upstream.

==== 486 response — due to A-UDUB

The `486` response indicates UDUB. The feature sends a `180-RINGING` upstream indicating approaching-UDUB.

The AS then sends a new `INVITE` to UE-B. This new `INVITE` includes:

- a MIME body according to the `<communication-waiting-indication>` element contained in the `<ims-cw>` root element

- a content-type of `application/vnd.3gpp.cw+xml`.

An example is:

    <?xml version="1.0"?>
    <ims-cw xmlns="urn:3gpp:ns:cw:1.0">
        <communication-waiting-indication/>
    </ims-cw>

The feature also starts a CW timer.

The following flow illustrates the signalling. In this example, the new INVITE is rejected.

=== Notifying the CallingParty of AUDUB via an in-band announcement

According to session output variables, the feature will set two session state fields to indicate that an announcement should be played.

The corresponding feature execution script can be written two ways:

    run MMTelCW
    run SIPPlayAnnouncement

This works because of a subtlety in SipPlayAnnouncement, it checks if the `AnnouncementID` field is not equal to zero.

However, the following is clearer and recommended:

    run MMTelCW
    if (CWAnnouncement) {
        run SIPPlayAnnouncement
    }

== Spec references

3GPP:

- 3GPP 22.173 P Multimedia Core Network Subsystem (IMS) Multimedia Telephony Service and supplementary services

- 3GPP 24.628 Common Basic Communication procedures using IP Multimedia (IM) Core Network (CN) subsystem

- 3GPP 22.228 Service requirements for the Internet Protocol (IP) multimedia core network subsystem (IMS)

- 3GPP 24.615 Communication Waiting (CW) using IP Multimedia (IM)

RFC:

- Alert-Info URNs for the Session Initiation Protocol (SIP) draft-ietf-salud-alert-info-urns-07 (expires Apr 2013)

- RFC5621 Message Body Handling in the Session Initiation Protocol (SIP)

- RFC3326 The Reason Header Field for the Session Initiation Protocol (SIP)

= MMTelECT :toc: macro :toclevels: 4 :toc-title: On this page…​

The Explicit Communication Transfer (ECT) service enables a party involved in a communication to transfer their role in that communication to a third party .

For a general overview of the service see Explicit Communication Transfer.

Consultative ECT using the 3pcc procedure does not support reusing the existing leg between the AS and the transfer-target, instead a new leg is created to link to the transferee.

== Feature Cheat Sheet

B2BUA Instance | SAS Support | Originating / Terminating | Point(s) in Session Plan | Network Operator Data | Subscriber Data | Stateful or Stateless | POJO Feature or SBB Feature | Other notes
--- | --- | --- | --- | --- | --- | --- | --- | ---
MMTel | No | Originating and/or Terminating | `MMTelOrig_SubscriptionSipRequest` `MMTelTerm_SubscriptionSipRequest` `MMTelOrig_SubscriptionSipResponse` `MMTelTerm_SubscriptionSipResponse` `MMTelOrig_SipAccess_SubscriberCheck` `MMTelTerm_SipAccess_SubscriberCheck` `MMTelOrig_SipAccess_PartyRequest` `MMTelTerm_SipAccess_PartyRequest` `MMTelOrig_SipAccess_PartyResponse` `MMTelTerm_SipAccess_PartyResponse` `MMTelOrig_SipMidSession_PartyRequest` `MMTelTerm_SipMidSession_PartyRequest` `MMTelOrig_SipMidSession_PartyResponse` `MMTelTerm_SipMidSession_PartyResponse` `MMTelOrig_SipAccess_ServiceTimer` `MMTelTerm_SipAccess_ServiceTimer` | Yes | Yes — Transferor authorization is stored in the HSS | Stateful | POJO | Implications on Charging for transferred communications

== Cassandra storage

The ECT feature utilises the Cassandra database to store session information for transfers

== Data Schema

The Cassandra table for ECT exists in a keyspace named `opencloud_mmtel_ect`

- For a production environment, the keyspace can be created such that it is replicated. A sample command for creating this keyspace is:

    CREATE KEYSPACE IF NOT EXISTS opencloud_mmtel_ect WITH REPLICATION={'class' : 'SimpleStrategy' ,'replication_factor' : 3 };

- For testing purposes, replication may not be necessary. A sample CQL command for creating such a keyspace is:

    CREATE KEYSPACE IF NOT EXISTS opencloud_mmtel_ect WITH REPLICATION={'class' : 'SimpleStrategy', 'replication_factor' : 1};

Once the keyspace is created, the required table can be created. The following CQL statements provides the structure of the required table.

    USE opencloud_mmtel_ect;

    CREATE TABLE IF NOT EXISTS ExplicitCommunicationTransfer (
    ect_id text,                           // The generated ECT identifier
    target_uri text,                       // URI of the transfer target
    transferor_p_asserted_id text,         // P-Asserted-Identity of transferor
    transfer_timeout int,                  // Value of REFER request's Expired header
    PRIMARY KEY (ect_id)
    )
    WITH gc_grace_seconds = 172800; // 2 days

== Session Input Variables

Variable Name | Type | Comments
--- | --- | ---
    MMTelECTServiceData
| Complex | Read from the HSS in SubscriberDataLookupFromHSS
    TransfereeLegName
| String | The `LegManager` leg-name of the Transferee.
    TransferorLegName
| String | The `LegManager` leg-name of the Transferor.
    ReferNotAllowedByTransferee
| boolean | True if the Transferee is not allowed to send a REFER request.
    EctSessionId
| String | The unique ID of the ECT session.
    TransferorIdentity
| String | The ID of the Transferor as found in the `P-Asserted-Identity` header of his/her REFER request.
    TransfereeCallID
| String | The `CallId` of the Transferee’s dialogue.
    TransfereeFromTag
| String | The `From` tag of the Transferee’s dialogue.
    TransfereeToTag
| String | The `To` tag of the Transferee’s dialogue.
    ExpiresTime
| int | The time indicated in the `Expires` header of the REFER request.
    TransferTargetUri
| String | The URI found in the `From` header’s `Address` part of the Transfer Target’s dialogue.
    TransfereeUri
| String | The URI found in the `From` header’s `Address` part of the Transferee’s dialogue.
    TransferorReferSequenceNumber
| long | The sequence number found in the `CSeq` header of the Transferor’s REFER request.
    ReleasedTransferorLeg
| boolean | True if the Transferor’s `LegManager` leg has been released.
    NoSubscriptionForRefer
| boolean | True if the REFER request contains the `ReferSub=false` header/value.
    NoAnswerTimerId
| TimerID | The ID of the Timer used to guard against unanswered requests.

== Session Output Variables

Variable name | Type | Comments
--- | --- | ---
    TransfereeLegName
| String | The `LegManager` leg-name of the Transferee.
    TransferorLegName
| String | The `LegManager` leg-name of the Transferor.
    TransferorReferSequenceNumber
| long | The sequence number found in the `CSeq` header of the Transferor’s REFER request.
    TransfereeUri
| String | The URI found in the `From` header’s `Address` part of the Transferee’s dialogue.
    NoSubscriptionForRefer
| boolean | True if the REFER request contains the `ReferSub=false` header/value.
    TransfereeCallID
| String | The `CallId` of the Transferee’s dialogue.
    TransfereeFromTag
| String | The `From` tag of the Transferee’s dialogue.
    TransfereeToTag
| String | The `To` tag of the Transferee’s dialogue.
    TransferorIdentity
| String | The ID of the Transferor as found in the `P-Asserted-Identity` header of his/her REFER request.
    ExpiresTime
| int | The time indicated in the `Expires` header of the REFER request.
    TransferTargetUri
| String | The URI found in the `From` header’s `Address` part of the Transfer Target’s dialogue.
    EctSessionId
| String | The unique ID of the ECT session.
    ReleasedTransferorLeg
| boolean | True if the Transferor’s `LegManager` leg has been released.
    NoAnswerTimerId
| TimerID | The ID of the Timer used to guard against unanswered requests.
    RanEct
| boolean | True if the ECT feature was invoked.
    ThirdPartyCallInitialisationRequested
| boolean | True if Third-Party Call Control (3PCC) was invoked.
    ECTOngoing
| boolean | True if an ECT operation is still ongoing.

== Behaviour

The ECT feature acts on INVITE, REFER, and NOTIFY requests and their responses. It also acts on service timers.

=== REFER Path

The feature creates an identifier for the transfer session by concatenating the prefix configured in Network Operator Data along with the from-tag, call-id, and to-tag of the REFER request. It then extracts the URI of the transfer-target from the Refer-To header, the P-Asserted-Identity and the value of the Expires header field. This information is stored in the database against the generated ID to be used when the transferee sends an INVITE request to the generated URI.

The feature then manipulates the outgoing REFER request by replacing the Refer-To header address with the generated URI and sets the Referred-By header to the P-Asserted-Identity in the request.

If ID privacy was requested the feature then adds a Privacy header with priv-value 'user'.

=== INVITE Path

The feature checks if the Request URI of the INVITE request could have been generated by the REFER handling behaviour of the ECT feature and if so attempts to query the database for the ECT session information. If no record can be found in the database table matching the Request URI the request is forwarded to the recipient without modification. If a record is found, the feature replaces the Request-URI of the downstream INVITE request with the URI of the transfer target.

If the retrieved Request-URI contains a 'Replaces' parameter the feature adds a 'Replaces' header with the same value to the INVITE request. If the Request-URI contains a Require header field parameter with a 'Replaces' token the feature adds a Require header field parameter with a 'Replaces' token to the INVITE request. If the downstream INVITE message does not contain a Referred-By header containing the transferor’s P-Asserted-Identity then the feature adds one.

=== NOTIFY Path

If the feature is triggered by a NOTIFY, and that NOTIFY is for a SIP 400 (Bad Request), the feature will invoke the 3PCC procedures. Otherwise, the NOTIFY is not acted upon.

=== Third Party Call Control

==== Scenarios

Under certain conditions where the standard signalling flow is impossible the feature invokes the Third Party Call Control (3pcc) procedures. These conditions are described in the following tables.

===== Terminating party sends a REFER request

Content of the Allow header in the initial INVITE request | Actions of the feature on the REFER request | Actions of the feature on the initial INVITE request
--- | --- | ---
INVITE request with an Allow header with no REFER token | Invoke the 3pcc procedures directly | Add a REFER token to the allow header
INVITE request with an Allow header including a REFER token | Forward the REFER request and if a 403 (Forbidden) or 501 (Not Implemented) response is received invoke the 3pcc procedure | No actions
INVITE request without an Allow header | Forward the REFER request and if a 403 (Forbidden) or 501 (Not Implemented) response is received invoke the 3pcc procedure | No actions

===== Originating party sends a REFER request

Content of the Allow header in the 200 (OK) response to the initial INVITE request | Actions of the feature on the REFER request | Actions of the feature on the 200 (OK) response to the initial INVITE request
--- | --- | ---
200 (OK) response with an Allow header with no REFER token | Invoke the 3pcc procedures directly | Add a REFER token to the allow header
200 (OK) response with an Allow header including a REFER token | Forward the REFER request and if a 403 (Forbidden) or 501 (Not Implemented) response is received invoke the 3pcc procedure | No actions
200 (OK) response without an Allow header | Forward the REFER request and if a 403 (Forbidden) or 501 (Not Implemented) response is received invoke the 3pcc procedure | No actions

==== Procedure

If the 3pcc procedures were triggered by a REFER request or a 403 (Forbidden) or 501 (Not Implemented) response the feature intercepts the message before it is forwarded to the recipient and instead responds to the REFER request by sending a 202 (Accepted). It then creates and sends a hold reINVITE request according to the procedures specified in 3GPP TS 24.610 subclause 4.5.2.1.

If however the 3pcc procedures were triggered by a NOTIFY request with a 420 (Bad Extension) status line the feature responds to the NOTIFY request with a 200 (OK) message and removes the message from the outgoing queue before sending the hold request.

Upon receipt of a success response to the hold request the feature then creates a new INVITE request to the transfer-target, and places this on the outgoing message queue of a new leg. The feature then creates a re-INVITE request to the transferee. If the Refer-To URI in the REFER request contained an Expires header, the feature starts a service timer set to its value. It then creates the re-INVITE request with same Call-ID, from-tag and to-tag as the existing dialogue between the transferee and the transferor, but replaces the address field of the From header with the address of the transfer-target. The feature then places the re-INVITE request on the outgoing message queue of the leg to the transferee and unlinks this leg from the leg to the transferor. MMTelECT then handles the call setup and SDP negotiation between the transferee and transfer-target.

MMTelECT continues to monitor the legs to the transferee and the transfer-target. When the INVITE to the transfer-target is acknowledged with a 200 (OK) response the feature sends a NOTIFY request with a 100 (trying) status line on the original leg to the transferor and when the re-INVITE to the transferee is acknowledged with a 200 (OK) the feature sends a NOTIFY request with a 200 (OK) status line towards the transferor and releases the leg.

If the Expires Service Timer fires before the transfer-target responds the feature sends a CANCEL and closes the partial dialogue to the transfer-target, then sends a NOTIFY request to the transferor with Subscription-State terminated and relinks the transferor and transferee legs resuming their original dialogue.

If the transfer-target responds to the INVITE request with a failure status code, the feature sends a NOTIFY request to the transferor with the Subcription-State header set to terminated and resumes the original dialogue between the transferor and transferee.

The transferor can request to not receive NOTIFY messages regarding the transfer progress by including a Refer-Sub header with value 'false' in the REFER request. The transferor can also release its leg at any time during the transfer attempt, in which case the feature will release the leg to the transferee and end the call in the event of a transfer failure.

=== Response Timer

The platform operator can configure a response timer for the feature which will trigger if the feature did not receive a response to a previously sent request within the configured period.

Scenarios where the response timer may be triggered:

- The transferee did not respond to a REFER request — Respond to the REFER request with a 603 (Decline) and send a REFER request with a cancel URI parameter in the Refer-To address

- The transfer-target did not respond to the INVITE request when executing 3pcc procedures — Release the newly-created leg to the transfer-target and attempt to resume the dialogue between the transferor and transferee. If the transferor has left the call release the leg to the transferee.

== Source Code

This feature’s source code is available in the Sentinel VoLTE SDK in the `mmtel-explicit-communication-transfer` module pack. It can be viewed by using the `create-module` command in the SDK with that module pack, for example:

`> create-module new-ect-module opencloud#mmtel-explicit-communication-transfer#volte/3.1.0;3.1.0.0`

This command will prompt you for information needed to create the new modules, once completed the original source for the feature can be found in the new modules.

The module-pack includes the following modules:

Module Name | Description
--- | ---
mmtel-explicit-communication-transfer | Group module for the feature that includes all of the modules listed below.
mmtel-ect-feature | The feature itself.
mmtel-ect-profile | The profile for this feature.

== Statistics

Name | Increments when …​
--- | ---
Started | each time the feature runs
FailedDuringExecution | a fatal error occurs while the feature is executing
FailedToStart | Sentinel VoLTE encounters an error while attempting to start the feature.
IssuedWarning | a non-fatal problem is encountered and the feature issues a warning.
TimedOut | the feature takes too long to complete and Sentinel VoLTE aborts execution.
ReferReceivedFromServedUser | a REFER request has been received from the served user
ReferSuccessful | the transferee has responded to a processed REFER request with a 202 Accepted)
ReferProcessedAndForwarded | a REFER request has been received from the transferor, appropriately modified and sent to the transferee
EctInviteReceived | an INVITE request has been received from the transferor as a result of a previous REFER request
EctInviteProcessedAndForwarded | an ECT INVITE request has been received by the transferee, appropriately modified and sent to the transfer-target
ThirdPartyCallControlProceduresInvoked | the Third Party Call Control (3pcc) transfer procedures have been invoked
ThirdPartyCallControlProceduresFailed | the Third Party Call Control (3pcc) transfer procedures did not result in a successful dialogue between the transferee and transfer-target
OriginalCallResumed | the original dialogue between the transferee and the transferor has been resumed if the 3pcc procedures failed
CassandraInsertSucceeded | ECT session information has been successfully inserted into the Cassandra DB
CassandraInsertFailed | an error occurred attempting to insert ECT session information into the Cassandra DB
CassandraQuerySucceeded | ECT session information has been successfully retrieved from the Cassandra DB
CassandraQueryFailed | an error occurred attempting to retrieve ECT session information from the Cassandra DB
DeletedCassandraRow | REFER request was cancelled by user, and so the Cassandra ECT record was deleted.
StoppedHandlingAndAllowedB2BUA | an INVITE request with a Request URI matching the ECT URI pattern was received and forwarded without modification
TransferSuccessful | a 200 (OK) was received from the transfer-target as a result of the ECT procedures
ErrorOccurredDuringExecution | an error occurred attempting to execute the feature
NoAnswerTimerFired | The feature timed-out waiting for an answer from a sent request.

== Specification References

3GPP TS 24.629 Version 12.7

== Scope

=== In Scope

- Blind and consultative communication transfer

- Blind and consultative communication transfer using 3pcc

=== Out of Scope

- Consultative ECT using the 3pcc procedure does not support reusing the existing leg between the AS and the transfer-target, instead a new leg is created to link to the transferee

- The feature does not play an announcement to the transferor when initiating the transfer attempt

== Network Operator Data

Network configuration is stored in the JSLEE profile table named `MMTelECTConfigProfileTable`.

The data is scoped on Sentinel Selection Key. The fields present in the JSLEE profile table are used to configure the behaviour of the Explicit Communication Transfer feature.

Parameter | Type | Default Value | Description
--- | --- | --- | ---
`TimeToLive` | integer | `60` | Determines how long ECT session information should remain in the Cassandra DB before being cleared.
`AuthorizedByDefault` | boolean | `true` | Determines if a transferor is authorized for ECT if no provisioning information is available.
`ICSCFURI` | String | `null` | The address of the Interrogating-CSCF, initially set by the installer.
`AddOrigParameter` | boolean | `true` | Determines if an `orig` parameter should be added to the Route header field when creating new INVITE requests.
`UseLRParameter` | boolean | `true` | Determines if an `lr` parameter should be added to the address parameter of the Route header field when creating new INVITE requests.
`EctPrefix` | String | `"ect-"` | Determines the prefix appended to generated URIs to identify them as relating to ECT session identifiers.
`ResponseTimeout` | integer | `2000` | Milliseconds to wait for a response to a request sent by this feature.

== Session Input Variables

    Variable Name
| Type | Comments
    MMTelECTServiceData
| Complex | Read from the HSS in SubscriberDataLookupFromHSS

== Example Call Flows

| Various IMS core elements and some SIP messages are omitted from the call flow diagrams for the sake of clarity.

=== Blind ECT

=== Consultative ECT

=== 3pcc procedure for Blind ECT after receiving a 501 (Not Implemented) response from a REFER

= MMTelHold :toc: macro :toclevels: 4 :toc-title: On this page…​

The Communication Hold supplementary service lets a user suspend reception of the media stream(s) of an established IP multimedia session, and resume the media stream(s) at a later time .

== 3GPP specification

3GPP define a specification for the Communication Hold supplementary service running in the IMS, in 24.610.

== CommunicationHold feature

OpenCloud’s CommunicationHold feature implements the capability of holding and resuming a session, according to the 3GPP spec.

== Feature cheat sheet

B2BUA Instance | SAS Support | Originating / Terminating | Point(s) in Session Plan | Network Operator Data | Subscriber Data | Stateful or Stateless | POJO or SBB Feature | Other notes
--- | --- | --- | --- | --- | --- | --- | --- | ---
MMTEL | Yes | Both Originating and Terminating | `SipMidSession_PartyRequest` `SipMidSession_PartyResponse` | Yes | No | FSM state | POJO with FSM encoded into Session State |

== Prerequisite features

- DetermineInitialLegNames

- SubscriberDataLookupFromHSS or SubscriberDataLookupFromHLR

== Source Code

This feature’s source code is available in the Sentinel VoLTE SDK in the `mmtel-communication-hold` module pack. It can be viewed by using the `create-module` command in the SDK with that module pack, for example:

`> create-module new-hold-module opencloud#mmtel-communication-hold#volte/3.1.0;3.1.0.0`

This command will prompt you for information needed to create the new modules, once completed the original source for the feature can be found in the new modules.

The module-pack includes the following modules:

Module Name | Description
--- | ---
mmtel-communication-hold | Group module for the feature that includes all of the modules listed below.
mmtel-hold-profile | Contains the profile specification for the feature configuration profile table.
mmtel-hold | Contains the feature itself.

== In scope

- Hold/resume an established session

- Adjusting bandwidth of responses to the Holding `INVITE` transaction

- Interaction with `MidCallPlayAnnouncement`

== XCAP provisioning

There is no XCAP Provisioning for Hold/Resume.

== Subscriber data

There is no subscriber data.

== Network operator data

Network operator data indicates:

- whether or not bandwidth should be adjusted

- what we should set each bandwidth attribute to

- whether or not an announcement should be played to the held party.

Network operator data is in a JSLEE configuration profile table: `MMTelHoldConfigProfileTable`.

This data is scoped by Sentinel selection key.

Each configuration has its own profile in this profile table.

Attribute Name | Type | Description
--- | --- | ---
    AdjustBandwidth
| Boolean | Indicates whether or not (true/false) Communication Hold should lower or increase the bandwidth of responses during sessions being Held and Resumed.
    B_AS
| int | The value of this attribute corresponds to the value for the `b=AS:` parameter to use when processing a Hold response.
    B_RR
| int | The value of this attribute corresponds to the value for the `b=RR:` parameter to use when processing a Hold response.
    B_RS
| int | The value of this attribute corresponds to the value for the `b=RS:` parameter to use when processing a Hold response.
    PlayAnnouncement
| Boolean | Indicates whether or not (true/false) Communication Hold requests an Announcement to be played when a session is held.
    AnnouncementID
| int | The announcement ID to be used when an announcement is requested
    AnnouncementHoldingPartyMediaMode
| String | Determines how media streams for the holding party are handled while an announcement to the held party is in progress. Can be set to `NO_HOLD`, `BLACK_HOLE_ONLY`, or `FULL_HOLD`.

=== Defaults for network operator data

Attribute name | Default Value | Meaning
--- | --- | ---
    AdjustBandwidth
| false | Hold does not adjust bandwidth
    B_AS
| 0 (zero) | If `AdjustBandwidth` is true, `b=AS:` is set to this value
    B_RR
| 800 | If `AdjustBandwidth` is true, `b=RR:` is set to this value
    B_RS
| 800 | If `AdjustBandwidth` is true, `b=RS:` is set to this value
    PlayAnnouncement
| false | Hold does not request an announcement is played
    AnnouncementID
| 0 (zero) | The `announcementID` of zero is a special ID meaning no announcement is to be played
    AnnouncementHoldingPartyMediaMode
| `FULL_HOLD` | The holding party is put on a two-way hold while the announcement is playing

== Session input variables

    Variable name
| Type | Comments
    MMTelHOLDServiceData
| Complex | Read from the HSS or HLR in SubscriberDataLookupFromHSS or SubscriberDataLookupFromHLR

== Session output variables

    Attribute Name
| Type | Comments
    RequestingLegCSeq
| String |
    RespondingLegCSeq
| String |
    AnnouncementID
| int |
    MidCallAnnouncementPlayedParty
| An enum with two fields: `CallingParty` and `CalledParty` |
    RanHOLD
| Boolean | Signals to other features that HOLD ran on this session.

=== MidCallAnnouncementPlayedParty

    package com.opencloud.sentinel.feature.announcement.midcall;

    public enum PlayedParty {
        CallingParty, CalledParty
    }

== Statistics

MMTelHold statistics are tracked by the sentinel.volte.sip SBB and can be found under the following parameter set in REM:
SLEE-Usage → sentinel.volte.sip service → sentinel.volte.sip SBB → feature → MMTelHold
or with rhino-stats:
"SLEE-Usage.Services.ServiceID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].SbbID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].feature.MMTelHold"

Statistic | Incremented when…​
--- | ---
    Started
| the feature runs
    FailedToStart
| Sentinel VoLTE encounters an error while attempting to start the feature
    IssuedWarning
| a non-fatal problem is encountered and the feature issues a warning
    FailedDuringExecution
| a fatal problem is encountered and the feature cannot execute correctly
    TimedOut
| the feature takes too long to complete and Sentinel VoLTE aborts execution
    ProcessingRequest
| the feature is invoked on receiving a SIP request
    ProcessingResponse
| the feature is invoked on receiving a SIP response
    SipDataAccessError
| an error occurs while trying to access a SIP leg or message
    SipMessageSDPUpdated
| the feature changes the SDP content in a SIP message
    ReceivedHoldRequest
| the feature determines that an incoming message is a hold request
    ReceivedResumeRequest
| the feature determines that an incoming message is a resume request
    SessionBandwidthAdjusted
| any bandwidth information is adjusted in an SDP body
    MediaStreamBandwidthAdjusted
| bandwidth information is adjusted on a SDP media stream description
    MissingDataWarningTriggered
| an operation on SDP data fails due to the data being unavailable
    ReceivedMalformedMessage
| the feature determines that an incoming message is mal formed
    PlayAnnouncementTriggered
| the feature determines triggers the play announcement

== Terminology

The UE invoking Hold/Resume is referred to as the invoking party.
The AS of this UE is referred to as the AS of the invoking party.

The UE that is being held/resumed is referred to as the receiving party.
The AS of this UE is referred to as the AS of the receiving party.

The invoking party makes an SDP offer. The receiving party responds with a SDP answer or rejects the offer with an error response. For each party, the SDP offer and corresponding answer from the other party need to be stored by the AS. The AS (B2BUA) refers to these as :

- In the B2BUA instance of the invoking party:

  - local SDP offer from the invoking party

  - remote SDP answer from the receiving party

- In the B2BUA instance of the receiving party:

  - remote SDP offer from the invoking party

  - local SDP answer from the receiving party.

THe SDP offer and answer are accompanied by `sdp-session-id` and `sdp-session-version`. Specifications mandate these parameters to change when the SDP changes.

== Behaviour

If `MMTelHOLDServiceData.OperatorAuthorized` is `false`, the feature finishes execution without modifying any state.

General behaviour for the MMTEL AS for the invoking UE:

- detecting if a Hold or Resume transaction is taking place:

  - The session-id or session-version of the SDP offer for the local or remote party has changed and follows the `HOLD` request rules:
    (`sendrecv` → `sendonly`, `recvonly` → `inactive`)

  - The session-id or session-version of the SDP answer for the local or remote party has changed and follows the `HOLD` request rules:
    (`sendrecv` → `recvonly`, `sendonly` → `inactive`)

- adjusting SDP bandwidth parameters in an offer and answer to reflect increased or reduced bandwidth demand.

How these simple goals are achieved is the subject of the rest of the behaviour description.

=== B2BUA instances and invoking UE

When the call is first set up, the AS of each party stores local and remote SDP offers and answers. That is, the AS of calling party that makes the SDP offer stores the current set of local SDP offers and remote SDP answers (see Behaviour).

When the originating party is the invoking party (that is, the originating party performs `HOLD`) then the originating B2BUA instance is `active` and the terminating B2BUA instance is `passive` for this request and its associated response.

When the terminating party is the invoking party (that is, the terminating party performs `HOLD`) then the terminating B2BUA instance is `active` and the originating B2BUA instance is `passive` for this request and its associated response.

=== Request processing

If the request is not a `Re-INVITE`, the feature finishes execution without modifying any state.

The feature determines if it is active or passive for a particular request.

If it is passive, it forwards the request upstream.

If it is active, it classifies the following:

- `Session Refresh` or not.

  - If `Session Refresh`, the feature finishes execution.

  - Otherwise, it classifies if the `Re-INVITE` should be an `Op` or a `No-op`.

    - If `No-Op`, it forwards the request.

    - Otherwise, if `Op`, it sets the session state field `HoldResumeResponseIsOp` to `TRUE`; then forwards the request.

==== Distinguishing hold requests from session refreshes

The AS of the invoking user stores the SDP session ID and version of the last successful offer or answer received from the invoking user. If a `Re-INVITE` received from the invoking user has both parameters unchanged, the `Re-INVITE` is a session audit (that is, session timer refresh). If either the session ID or version has changed, the SDP of the request must be inspected.

If the SDP session ID and session version are the same, then the `Re-INVITE` request represents a session refresh.

In case of a session refresh, both the originating and terminating B2BUA instance are `passive`.

==== Behaviour if the request is a session refresh

The feature does not alter any state, and finishes execution.

==== Hold request Op or No-op in the context of no announcements

Hold requests may be treated as an `Op` (short for Operation) or a `No-op` (short for No-Operation).

- If a request is classified as a `No-op` request, then the request is passed through as is, and its associated response is passed through as is.

- If a request is classified as an `Op` request, then the response’s bandwidth may be adjusted before being passed to the invoking UE.

- If the B2BUA instance is `passive` for a given request, then the request is always classified as a `No-Op`.

- If the B2BUA instance is `active` for a given request, then the request will be classified as either a `No-Op` or an `Op`.

If all of the streams within a request are treated as `Stream No-Op`, then the request is treated as a `No-op` request.

The following table shows how each stream within a request is treated as a `No-Op` or as an `Op`.

Most |normal case tables are taken from actions at the invoking UE 4.5.2.1

UE intention | Current Stream State | Requested State for Stream | Stream Op or Stream No-Op | Comments
--- | --- | --- | --- | ---
Hold a media stream | `stream is sendrecv` (assume this means both UEs are in sendrecv) | UE1 sends offer `sendonly`, UE2 responds with `recvonly` | `Op` for B2BUA serving UE1, `No-Op` for the other B2BUA | normal case for Hold where the session was fully active in both directions
Hold a media stream | `stream is recvonly` (assume this means UE1 is sendonly and UE2 is recvonly) | UE2 sends offer `inactive`, UE1 responds with `inactive` | `Op` for B2BUA serving UE2, `No-Op` for the other B2BUA | normal case where your UE got put on hold and you want to put the other on hold
Resume a media stream | `stream inactive` (assume this means both UEs are inactive) | UE1 sends offer `recvonly`, UE2 responds with `sendonly` | `Op` for B2BUA serving UE1, `No-Op` for the other B2BUA | normal case where both UEs had held each other, and one UE wants to resume
Resume a media stream | `send only` (assume this means UE1 is recvonly and UE2 is sendonly | UE2 offers sendrecv, UE1 response with `sendrecv` (or omitted because `sendrecv` is default) | `Op` for B2BUA serving UE2, `No-Op` for the other B2BUA | normal case where stream is held by one UE, and it wants to be resumed
Hold all media streams using session-level direction attribute in SDP | media streams are `sendrecv` | UE1 sends SDP where session-level direction attribute is set (with new session version) with offer of `sendonly`, UE2 responds with session-level direction of `recvonly` | `Op` for UE1s B2BUA, `No-Op` for other | normal case where all streams are to be held, and some are `sendrecv`
Hold all media streams using media-level direction attribute in SDP | at least one of the sessions media streams are in `sendrecv` | UE1 sends SDP with N direction attributes set to `sendonly` …​ (1 per media stream that is set to `sendrecv`), UE2 responds with `recvonly` at media level for each stream | `Op` for Invoking UE’s B2BUA, `No-Op` for other | normal case where all streams are to be held, and some are `sendrecv` single SDP offer can be sent combining this row and the next row
Hold all media streams using media-level direction attribute in SDP | at least one of the sessions media streams are in `recvonly` | invoking UE sends SDP with M direction attributes (1 per media stream that is set to `recvonly`), Other UE responds with `inactive` for each media stream | `Op` for invoking UE’s B2BUA, `No-Op` for other B2BUA | normal case where all streams are to be held, and some are in `recvonly` single SDP offer can be send combining this row and the previous row
Resume all media streams using session-level direction attribute in SDP | media streams are in `inactive` | invoking UE sends SDP offer where session-level direction attribute is `recvonly`, other UE responds with session-level direction attribute set to `sendonly` | `Op` for invoking UE’s B2BUA, `No-Op` for other | normal resume-all case where media was inactive
Resume all media streams using session-level direction attribute in SDP | media streams are in `sendonly` | invoking UE sends SDP where session-level direction attribute is `sendrecv` (or this attribute is omitted as `sendrecv` is the default), other UE responds with session-level direction attribute of `sendrecv` (or attribute is omitted as this is the default) | `Op` for invoking UE’s B2BUA, `No-Op` for other | normal resume-all case where session was held in one direction only, and the held UE wants to resume
Resume all, using Media level SDP | several possible states, one for each media stream; also similar to Hold all where there are different streams in different states | similar to the hold all cases, except the offer is to resume; that is, the media attributes are set to `recvonly` (if previously inactive), or `sendrecv` if previously `sendonly` | `Op` for invoking UE’s B2BUA, | `No-Op` for other normal resume-all case where some sessions are held and others aren’t

=== Response processing

If the response is not a response to a `Re-INVITE`, the feature finishes execution without modifying any state.

When processing a response, the feature detects if it is active or passive for the response.

- Read the session state field `HoldResumeResponseIsOp`.

- If `TRUE`, process the response in active manner

  - If the response is a final response (a 2xx or 4xx. response) set the session state field `HoldResumeResponseIsOp` to `FALSE`.

- If `FALSE`, process the response in passive manner.

==== Passive processing of response

When processing the response (SDP answer) in a passive manner, the feature forwards the response without modifying it.

==== Active processing of response

If the Network Data’s `AdjustBandwidth` attribute is set to `False`, the feature then finishes execution without modifying any state.

Otherwise the following steps are then performed:

- walks through each media stream in the answer, that is `held`

- checks to see if the media stream is marked as `recvonly`, and if so (as a network option) performs the following on each `held` media stream:

  - lowers the bandwidth of the invoking UE (the UE that sent the SDP offer) to a small value, by setting the `b=AS:` parameter (for example, setting `b=AS:0`).

The `b=RR:` and `b=RS:` parameters are set to values large enough to enable continuation of the RTCP flow; for example, `b=RR:800` and `b=RS:800`.

The values to be used for `b=AS:`, `b=RR:`, and `b=RS:` parameters are found in the network configuration’s `B-AS`, `B-RR`, and `B-RS` attributes respectively.

The adjusted response is then forwarded onwards.

=== Hold Announcements

The feature allows for the configuration of an announcement to be played to the held party when they are put on hold. The SIP Mid Session Play Announcement Feature is responsible for handling the signalling required to play the announcement.

There are two fields in the feature configuration profile that relate to announcements:

- The `AnnouncementID` determines which announcement should be played and should have a corresponding entry on the `SipAnnouncementProfileTable`. Setting this to `0` disables hold announcements.

- The `AnnouncementHoldingPartyMediaMode` determines how media streams with the party that initiated the hold are handled while the announcement is being played to the other party. See the Passive Party Media section of the mid-call announcement feature docs for an explanation on the possible values for this field and the affect they have on behaviour.

=== Background on SIP Sentinel and SDP negotiation

Sentinel stores the current set of SDP offers and answers along with the `sdp-session-id` and `sdp-session-version` for the offers and answers (this is accessible through the Leg API). When a SIP dialog is set up (whether early or confirmed) the set of (`local`|`remote`)(`offer`, `sdp-session-id`, `sdp-session-version`) and (`local`|`remote`)(`answer`, `sdp-session-id`, `sdp-session-version`) are recorded.

When SDP is updated by means of n `UPDATE` or `Re-INVITE` transaction, the `session-id` and `session-version` will change. If the `session-id` and `session-version` remain unchanged ,this indicates the media is unchanged (this is typically a session refresh).

While a transaction is in progress, the current SDP offer and answer is available in the “latest” SDP pair.

Upon successful SIP transaction completion, the latest SDP offer and answer are copied into the “committed” set.

Upon transaction failure, the committed set is not modified.

= MMTelWifiChargingFinalisation :toc: macro :toclevels: 4 :toc-title: On this page…​

The MMTelWifiChargingFinalisation feature handles the finalisation of charging when a call is answered over WiFi.

== What is MMTel WiFi Charging Finalisation?

MMTelWifiChargingFinalisation interacts with the T-ADS features in the Sentinel VoLTE SCC AS. It looks for a header that those features attach to responses to the initial INVITE in order to determine if a call has been answered over a WiFi network. If that is the case, it finalises charging.

== Feature cheat sheet

B2BUA Instance | SAS Support | Originating / Terminating | Point in Session Plan | Network Operator Data | Subscriber Data | Stateful or Stateless | POJO Feature or SBB Feature
--- | --- | --- | --- | --- | --- | --- | ---
MMTEL | No | Originating and Terminating |
    SipAccess_PartyResponse
| No | No | Stateless | POJO

== Prerequisite Features

These features must run before MMTelWifiChargingFinalisation:

- DetermineCallType

- DetermineChargeMode

== Source Code

This feature’s source code is available in the Sentinel VoLTE SDK in the `mmtel-wifi-charging-finalisation` module pack. It can be viewed by using the `create-module` command in the SDK with that module pack, for example:

`> create-module new-wcf-module opencloud#mmtel-wifi-charging-finalisation#volte/3.1.0;3.1.0.0`

This command will prompt you for information needed to create the new modules, once completed the original source for the feature can be found in the new modules.

The module-pack includes a single module:

Module Name | Description
--- | ---
mmtel-wifi-charging-finalisation | Contains all of the code for this feature.

== Session Input Variables

Attribute | Type | Comments
--- | --- | ---
    CallType
| CallType (enum) | Set by the DetermineCallType feature
    ChargeMode
| ChargeMode (enum) | Set by the DetermineChargeMode feature

== Session Output Variables

Attribute | Type | Comments
--- | --- | ---
    MonitorCallOnly
| boolean | The feature will set this to `true` when it finalises charging.
    TerminatingDomain
| String | The feature will set this to the value of OC-Terminating-Domain header of any 200 response to the original INVITE

== Statistics

MMTelWifiChargingFinalisation statistics are tracked by the sentinel.volte.sip SBB and can be found under the following parameter set:
SLEE-Usage → [sentinel.volte.sip service name] → [sentinel.volte.sip SBB name] → feature.MMTelWifiChargingFinalisation

Statistic | Increments when…​
--- | ---
    Started
| The feature is started.
    OCTerminatingDomainHeaderStripped
| An OC-Terminating-Domain header is found on an outgoing message and removed.
    ChargingInstanceFinalised
| A non-finalised reservation charging instance is found and finalised.
    Received2xxForOriginalInvite
| A SIP 2xx response for the initial INVITE is received by the feature.
    TerminatingDomainIsWifi
| The feature determines that terminating access is over WiFi.
    FailedToStart
| Sentinel VoLTE encounters an error while attempting to start the feature.
    IssuedWarning
| A non-fatal problem is encountered and the feature issues a warning.
    FailedDuringExecution
| A fatal problem is encountered and the feature cannot execute correctly.
    TimedOut
| The feature takes too long to complete and Sentinel VoLTE aborts execution.

== Behaviour

MMTelWifiChargingFinalisation has simple behaviour and always executes in the same way.

=== Basic Checks

After being triggered the feature undertakes some basic checks to ensure it should be running, they are:

- Ensure that a Call Type has been set in session state (i.e. the DetermineCallType feature has run)

- Ensure that a Charge Mode has been set in session state (i.e. the DetermineChargeMode feature has run)

- Ensure that the feature was triggered on an incoming SIP response message.

If any of these conditions is not met, the feature immediately terminates execution an raises an error. If they are both met, the feature will continue as described below.

=== Classifying the Session Status and Response

Once confirming that it is running under the correct conditions, the feature checks the session state and the incoming response to determine if a decision about charging should be made. The requirements for making a decision are:

- The Call Type is `MobileTerminating`

- The Charge Mode is `RO` (Online charging)

- The response has a `200 OK` status.

- The response has been sent in reply to the initial `INVITE` for the call.

If these requirements are all met, the feature will check the response to determine if charging should be finalised. If any are not met, the feature will skip to checking if it needs to strip the OC-Terminating-Domain from the outgoing response.

=== Handling Charging Status

If the feature has confirmed that the incoming response is a `200 OK` for the initial INVITE, it will look for the OC-Terminating-Domain header on the response. If the header is present and has the value `PS=WLAN` (which indicates the call has been routed to the terminating user over a WiFi network) the feature will finalise charging for the terminating leg of the call.

If it is present, the value of the OC-Terminating-Domain header (regardless of it is) will be stored in the TerminatingDomain session output variable.

If the header is not present or has a value not equal to `PS=WLAN`, charging for the call will not be affected.

==== Finalising Charging

If the feature has determined that it is necessary to finalise charging, it will carry out the following procedure:

1. Set the session output variable called `MonitorCallOnly` to `true`.

2. Find all charging instances associated with the session.

3. For each charging instance it finds it will:

   1. Determine if it is a reservation charging instance.

   2. Check that the instance has not already been finalised.

   3. If both of those conditions are true, the feature will instruct the instance to undertake charging finalisation.

=== Stripping the OC-Terminating-Domain Header

Under certain conditions, the feature will strip the `OC-Terminating-Domain` header from any outgoing messages before finishing execution. These conditions are met when either one of the following is true:

- The Call Type is `MobileOriginating`

- The Call Type is `MobileTerminating`, and the Charge Mode is `RO` (online) or `DEFAULT` (which is treated as online)

If the conditions are met, the feature will strip the header by accessing the outgoing message queue for the leg linked to the leg the response was received on. For every message found in the queue, the feature will check if the header is present and if so, remove it.

If the response was received on a leg that is not linked to another leg, or neither of the above conditions were met, the feature will not attempt to strip the header.

= Session Transfer to Own Device :indexpage:

Session Transfer to Own Device features. For an overview see Session Transfer to Own Device on Sentinel VoLTE Architecture.

Feature | What it does
--- | ---
MMTelStodEnabled | checks if the subscriber has the STOD service provisioned
MMTelBindAci | connects the IMPU acquired from the subscriber registration to the existing ACI for the session transfer
MMTelStodTriggerAnchor | handles the transfer request and route it to the previous bound session
MMTelStodProcessHandover | intercepts the transfer INVITE routed by the MMTelStodTriggerAnchor feature and connects the existing called led to the new calling leg and releases the previous calling leg
MMTelStodDetermineTargetSession | Reads STOD tracking information out of the Session Ownership Facility and sets it into the session state for processing by External Session Tracking features.

== Source Code

This feature’s source code is available in the Sentinel VoLTE SDK in the `mmtel-session-transfer` module pack. It can be viewed by using the `create-module` command in the SDK with that module pack, for example:

`> create-module new-session-transfer-module opencloud#mmtel-session-transfer#volte/3.1.0;3.1.0.0`

This command will prompt you for information needed to create the new modules, once completed the original source for the feature can be found in the new modules.

The module-pack includes the following modules:

Module Name | Description
--- | ---
mmtel-session-transfer | Group module for the feature that includes all of the modules listed below.
mmtel-stod-enabled | checks if the subscriber has the STOD service provisioned
mmtel-bind-aci | connects the IMPU acquired from the subscriber registration to the existing ACI for the session transfer
mmtel-stod-trigger-anchor | handles the transfer request and route it to the previous bound session
mmtel-stod-process-handover | intercepts the transfer INVITE routed by the MMTelStodTriggerAnchor feature and connects the existing called led to the new calling leg and releases the previous calling leg
mmtel-session-transfer-event-handler | The internal event used by the MMTelStodTriggerAnchor feature.
mmtel-stod-determine-target-session | Reads STOD tracking information out of the Session Ownership Facility and sets it into the session state for processing by External Session Tracking features.

= MMTelBindAci :toc: macro :toclevels: 4 :toc-title: On this page…​

The MMTelBindAci feature connects the IMPU acquired from the subscriber registration to the existing ACI for the session transfer .

== Feature Cheat Sheet

B2BUA Instance | SAS Support | Originating / Terminating | Point(s) in Session Plan | Network Operator Data | Subscriber Data | Stateful or Stateless | POJO Feature or SBB Feature | Other notes
--- | --- | --- | --- | --- | --- | --- | --- | ---
MMTel | No | Both | `MMTelOrig_SipAccess_PartyResponse` `MMTelTerm_SipAccess_PartyResponse` | Yes | Yes - subscriber data is from the HSS | Stateless | SBB Feature | Implications on Charging for Forwarded calls

== Prerequisite Features

- SubscriberDataLookupFromHssFeatureSbb

- MMTelStodEnabled

== Session Input Variables

Session State variable name | Type | Comments
--- | --- | ---
    RegistrationRecords
| Complex | Registration Records contain the public IMPU
    Subscriber
| String | The subscriber Id
    CallType
| Complex | The sip call type
    StodIsEnabledForUser
| boolean | Is the STOD enabled ?

== Statistics

MMTelBindAci statistics are tracked by the sentinel.volte.sip SBB and can be found under the following parameter set in REM:
SLEE-Usage → sentinel.volte.sip service → sentinel.volte.sip SBB → feature → MMTelBindAci
or with rhino-stats:
"SLEE-Usage.Services.ServiceID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].SbbID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].feature.MMTelBindAci"

Name | Incremented when…​
--- | ---
    Started
| the feature runs
    FailedToStart
| Sentinel VoLTE encounters an error while attempting to start the feature
    IssuedWarning
| a non-fatal problem is encountered and the feature issues a warning
    FailedDuringExecution
| a fatal problem is encountered and the feature cannot execute correctly
    TimedOut
| the feature takes too long to complete and Sentinel VoLTE aborts execution
    BoundAciToImpu
| the ACI is bound to an this is incremented.
    UsedLinkedAciForBinding
| the triggering ACI is not used for binding, i.e the call is not MobileTerminating then the linked ACI is used.
    UsedTriggeringAciForBinding
| the call is a MobileTerminating call the Triggering ACI is used for binding.

== Behaviour

The feature connects the IMPU acquired from the subscriber registration to the existing ACI for the session transfer. The subscriber has to be provisioned for the service, otherwise the feature won’t bind the session. The feature will only bind the session if the 200 OK from the INVITE is received.

== Source

For source code information see MMTel Session Transfer Source Code

= MMTelStodEnabled :toc: macro :toclevels: 4 :toc-title: On this page…​

The MMTelStodEnabled feature checks if the subscriber has the STOD service provisioned .

== Feature Cheat Sheet

B2BUA Instance | SAS Support | Originating / Terminating | Point(s) in Session Plan | Network Operator Data | Subscriber Data | Stateful or Stateless | POJO Feature or SBB Feature | Other notes
--- | --- | --- | --- | --- | --- | --- | --- | ---
MMTel | No | Both | `MMTelOrig_SipAccess_SubscriberCheck` `MMTelTerm_SipAccess_SubscriberCheck` `MMTel_Post_SipAccess_SubscriberCheck` `MMTelOrig_SipAccess_PartyResponse` `MMTelTerm_SipAccess_PartyResponse` `MMTel_Pre_SipAccess_PartyResponse` | Yes | Yes - subscriber data is from the HSS | Stateless | POJO Feature |

== Prerequisite Features

- SubscriberDataLookupFromHssFeatureSbb

== Session Input Variables

Session State variable name | Type | Comments
--- | --- | ---
    RegistrationRecords
| Complex | List of registration records containing public id
    Subscriber
| String | subscriber id

== Configuration

The configuration is stored in a JSLEE configuration profile with a profile table name of: `MMTelStodEnabledConfigProfileTable`. The profile is scoped by the `Sentinel selection key` and by the subscriber uri. Example : `Opencloud:::::alice@opencloud.com`.

Variable Name | Type | Constraint | Default | Default Value Interpretation | Note
--- | --- | --- | --- | --- | ---
    StodEnabled
| Boolean |  | False | Indicates the subscriber is not allowed to use the STOD service |

== Session Output Variables

Session State variable name | Type | Comments
--- | --- | ---
    StodIsEnabledForUser
| boolean | Set to `true` when Stod is enabled for the subscriber
    AccessLegTrackingKeys
| Set<String> | The set of external session tracking keys
    AccessLegTrackingActive
| boolean | Whether or not this session will be externally tracked

== Statistics

Name | Incremented when…​
--- | ---
    Started
| the feature runs
    FailedToStart
| Sentinel VoLTE encounters an error while attempting to start the feature
    IssuedWarning
| a non-fatal problem is encountered and the feature issues a warning
    FailedDuringExecution
| a fatal problem is encountered and the feature cannot execute correctly
    TimedOut
| the feature takes too long to complete and Sentinel VoLTE aborts execution
    StodIsEnabled
| the Stod is enabled for a subscriber
    StodIsNotEnabled
| the Stod is not enabled for a subscriber
    StodEnableSessionTracking
| STOD session tracking is enabled for this session
    StodSessionTrackingDisabled
| STOD session tracking is disabled for this session
    FoundTrackingKey
| A tracking key has been created for this session and added to the set

== Behaviour

The feature acts on INVITE requests and on responses.

On an INVITE request, the feature checks if the subscriber has the STOD service provisioned. For this, the IMPU is retrieved from registration data and matched with profile configuration. If the profile exists and the `StodEnabled` boolean variable is true, the feature sets the `StodIsEnabledForUser` session state field.

On responses, the feature checks to make sure that STOD session tracking has been enabled for the Served-User in the triggering message. In the event that the trigger is on a 200 (OK) response for an incoming INVITE request the feature will create a tracking key. The tracking key is taken from an IMPU in session state and the Tracking Key Prefix IMPU. The tracking key is then added to the External Session Tracking Keys. When there is no subscriber in session state or in the registration records there will be no IMPU in which case there will be no session tracking.

== Source

For source code information see MMTel Session Transfer Source Code

= MMTelStodProcessHandover :toc: macro :toclevels: 4 :toc-title: On this page…​

The MMTelStodProcessHandover feature intercepts the transfer INVITE routed by the MMTelStodTriggerAnchor feature and connects the existing called led to the new calling leg and releases the previous calling leg .

== Feature Cheat Sheet

B2BUA Instance | SAS Support | Originating / Terminating | Point(s) in Session Plan | Network Operator Data | Subscriber Data | Stateful or Stateless | POJO Feature or SBB Feature | Other notes
--- | --- | --- | --- | --- | --- | --- | --- | ---
MMTel | No | Both | `MMTelOrig_SipMidSession_PartyRequest` `MMTelTerm_SipMidSession_PartyRequest` `MMTelOrig_SipMidSession_PartyResponse` `MMTelTerm_SipMidSession_PartyResponse` | No |  | Stateful | SBB Feature |

== Prerequisite Features

- DetermineVoltePlanId

- MMTelStodTriggerAnchor

== Session Input Variables

Session State variable name | Type | Comments
--- | --- | ---
    CallType
| enum | MobileOriginating or MobileTerminating

== Statistics

MMTelStodProcessHandover statistics are tracked by the sentinel.volte.sip SBB and can be found under the following parameter set in REM:
SLEE-Usage → sentinel.volte.sip service → sentinel.volte.sip SBB → feature → MMTelStodProcessHandover
or with rhino-stats:
"SLEE-Usage.Services.ServiceID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].SbbID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].feature.MMTelStodProcessHandover"

Name | Incremented when…​
--- | ---
    Started
| the feature runs
    FailedToStart
| Sentinel VoLTE encounters an error while attempting to start the feature
    IssuedWarning
| a non-fatal problem is encountered and the feature issues a warning
    FailedDuringExecution
| a fatal problem is encountered and the feature cannot execute correctly
    TimedOut
| the feature takes too long to complete and Sentinel VoLTE aborts execution
    SentRemoteUpdate
| a re-INVITE is sent to the called party.
    RemoteUpdateSuccess
| re-INVITE was accepted (200 OK).
    RemoteUpdateError
| re-INVITE was not accepted.
    CallAnsweredWith200
| the (200 OK) from the re-INVITE is sent to the new access leg
    ReleasedOldAccessLeg
| the previous calling leg is released
    LinkedNewAccessLegToRemoteLeg
| the transfer INVITE leg is linked to the existing called party leg
    TerminatedSession
| the session finishes
    AccessTransferComplete
| the session transfer was done successfully
    HandoverRequestReceived
| a session transfer INVITE is received
    StodEnableSessionTracking
| tries to mark the new transfered session to be tracked
    FoundTrackingKey
| the tracking key is set
    StodSessionTrackingDisabled
| when failed to set the new transfered session to be tracked

== Behaviour

The feature intercepts the transfer INVITE routed by the MMTelStodTriggerAnchor feature and connects the existing called led to the new calling leg and releases the previous calling leg.

The feature also does the SDP remote update by sending the transfer INVITE as a reINVITE on the existing called leg and guarantees the SDP integrity and correctness on all involved dialogs.

== Source

For source code information see MMTel Session Transfer Source Code

= MMTelStodTriggerAnchor :toc: macro :toclevels: 4 :toc-title: On this page…​

The MMTelStodTriggerAnchor feature handles the transfer request and route it to the previous bound session .

== Feature Cheat Sheet

B2BUA Instance | SAS Support | Originating / Terminating | Point(s) in Session Plan | Network Operator Data | Subscriber Data | Stateful or Stateless | POJO Feature or SBB Feature | Other notes
--- | --- | --- | --- | --- | --- | --- | --- | ---
Stod | No | Originating | `Stod_SipAccess_SessionStart` | Yes | Yes - subscriber data is from the HSS | Stateless | SBB Feature |

== Prerequisite Features

- SubscriberDataLookupFromHssFeatureSbb

- MMTelStodBind

- MMTelStodEnabled

== Session Input Variables

Session State variable name | Type | Comments
--- | --- | ---
    RegistrationRecords
| Complex | Registration Records contain the public IMPU
    Subscriber
| String | The subscriber Id
    StodIsEnabledForUser
| boolean | Is the STOD enabled ?

== Statistics

MMTelStodTriggerAnchor statistics are tracked by the sentinel.volte.sip SBB and can be found under the following parameter set in REM:
SLEE-Usage → sentinel.volte.sip service → sentinel.volte.sip SBB → feature → MMTelStodTriggerAnchor
or with rhino-stats:
"SLEE-Usage.Services.ServiceID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].SbbID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].feature.MMTelStodTriggerAnchor"

Name | Incremented when…​
--- | ---
    Started
| the feature runs
    FailedToStart
| Sentinel VoLTE encounters an error while attempting to start the feature
    IssuedWarning
| a non-fatal problem is encountered and the feature issues a warning
    FailedDuringExecution
| a fatal problem is encountered and the feature cannot execute correctly
    TimedOut
| the feature takes too long to complete and Sentinel VoLTE aborts execution
    FiredIncomingRequestEvent
| the transfer INVITE is sent to the session to be transfered.

== Behaviour

The feature handles the transfer request and route it to the previous bound session.

The feature retrieves the existing session based on the IMPU from the registration records and fires an internal event, routing the transfer request to the previous bound existing session. If the existing session is owned by another operational node in the cluster, the transfer request is proxied to that node. 3 == Source

For source code information see MMTel Session Transfer Source Code

= STODDetermineTargetSession :toc: macro :toclevels: 4 :toc-title: On this page…​

The STODDetermineTargetSession feature Reads STOD tracking information out of the Session Ownership Facility and sets it into the session state for processing by External Session Tracking features. .

== Feature Cheat Sheet

B2BUA Instance | SAS Support | Originating / Terminating | Point(s) in Session Plan | Network Operator Data | Subscriber Data | Stateful or Stateless | POJO Feature or SBB Feature | Other notes
--- | --- | --- | --- | --- | --- | --- | --- | ---
Stod | No | Originating | `Stod_SipAccess_SessionStart` | Yes | Yes - subscriber data is from the HSS | Statefull | SBB Feature | Requires other features in STOD to work

== Prerequisites

- The subscriber has to have the STOD service enabled (see MMTelStodEnabled)

- The special number has to be configured in the AS (see DetermineVoltePlanId)

- Session Ownership Record writing is enabled by other STOD features.

== Session Input Variables

Session State variable name | Type | Comments
--- | --- | ---
    CallType
| Complex | The calltype
    RequestIsForMmtelTransfer
| boolean | Get request is for MMtel transfer
    MMTelDetermineTransferableSetQueryTime
| long | The query time
    MMTelIsNewCassandraSession
| boolean | Is the session a new Cassandra session
    SessionOwnershipACI
| Complex | the ACI for session ownership queries

== Session Output Variables

Session State variable name | Type | Comments
--- | --- | ---
    MMTelDetermineTransferableSetQueryTime
| long | The time for a Session Ownership Facility query to execute
    MMTelProceedWithStodTransfer
| boolean | True if a transferable session is found, otherwise false
    MMTelSessionToTransfer
| Complex | Insert the session tracking information into the Session State
    MMTelSessionTransferIsLocal
| boolean | Set whether the access transfer is local, i.e. does not require proxying to another node
    MMTelIsNewSessionOwnershipActivity
| boolean | Indicates whether the Session Ownership Activity is re-used or new for this query

== Statistics

STODDetermineTargetSession statistics are tracked by the sentinel.volte.sip SBB and can be found under the following parameter set in REM:
SLEE-Usage → sentinel.volte.sip service → sentinel.volte.sip SBB → feature → STODDetermineTargetSession
or with rhino-stats:
"SLEE-Usage.Services.ServiceID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].SbbID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].feature.STODDetermineTargetSession"

Name | Incremented when…​
--- | ---
    Started
| the feature runs
    FailedToStart
| Sentinel VoLTE encounters an error while attempting to start the feature
    IssuedWarning
| a non-fatal problem is encountered and the feature issues a warning
    FailedDuringExecution
| a fatal problem is encountered and the feature cannot execute correctly
    TimedOut
| the feature takes too long to complete and Sentinel VoLTE aborts execution
    StodDetTargetSessionInvoked
| The feature has started
    StodSessionOwnershipError
| The query result event has been received however the result is an error
    StodSampleCSessionOwnershipAsyncQueryTimeFailure
| The query result event has been received however the result is an error
    StodSessionOwnershipSuccess
| The query result event has been received with a non error result
    StodSampleSessionOwnershipAsyncQueryTimeSuccess
| The query result event has been received with a non error result
    StodSessionOwnershipQuery
| The query has been sent
    StodSessionOwnershipNoDataFound
| The results of the query showed that there was no session in the database for session transfer
    StodFoundTrackedSession
| The session to transfer has been found in a database
    StodSavedSessionToTransfer
| The session to transfer returned non null and has been set into a session state variable

== Behaviour

The feature determines whether its invocation was due to a Session Transfer attempt, or response to such an attempt. In the event that the trigger was a transfer attempt then the feature queries the Session Ownership Facility in order to determine the Session to Transfer. This query uses the IMPU of the Served user as the `AdditionalKey` for the query.

Once the feature has gathered the various Session Ownership Records for the Served User, it selects a Session To Transfer. The first `ACTIVE` session for the Served User is selected as the Session To Transfer and:

1. the `MMTelProceedWithStodTransfer` session state field is set to true

2. it is saved into the `MMTelSessionToTransfer` session state field

3. the `MMTelSessionTransferIsLocal` session state field is set to true if the `OwnerURI` for the Session Ownership Record is the same as the executing node’s AS URI

If no ongoing sessions are found for Served User the feature:

1. responds to the Initial INVITE Request with a SIP 404 Not Found Response

2. sets the `MMTelProceedWithStodTransfer` session state field to false

== Source

For source code information see MMTel Session Transfer Source Code.

= Set Companion Device Headers :toc: macro :toclevels: 4 :toc-title: On this page…​

This feature sets the companion device headers to the initial INVITE when the subscriber has been provisioned with companion devices.

== Feature Cheat Sheet

B2BUA Instance | SAS Support | Originating / Terminating | Point(s) in Session Plan | Network Operator Data | Subscriber Data | Stateful or Stateless | POJO Feature or SBB Feature | Other notes
--- | --- | --- | --- | --- | --- | --- | --- | ---
MMTel | Yes | Terminating | `SipAccessSubscriberCheck-SysPost-MMTel` | No | Yes | Stateless | POJO |

== Prerequisite Features

- SubscriberDataLookupFromHSS

== Feature Configuration

There is no feature configuration for this feature.

== Session Input Variables

Session State variable name | Type | Comments
--- | --- | ---
    CallType
| Complex | The calltype
    MetaswitchCompanionDevice
| Complex | The companion device data that is provisioned in HSS

== Statistics

Feature statistics are tracked by the sentinel.volte.sip SBB and can be found under the following parameter set in REM:
SLEE-Usage → sentinel.volte.sip service → sentinel.volte.sip SBB → feature → SetCompanionDeviceHeaders
or with rhino-stats:
"SLEE-Usage.Services.ServiceID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].SbbID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].feature.SetCompanionDeviceHeaders"

Statistic | Incremented when…​
--- | ---
    Started
| the feature runs
    FailedToStart
| Sentinel VoLTE encounters an error while attempting to start the feature
    IssuedWarning
| a non-fatal problem is encountered and the feature issues a warning
    FailedDuringExecution
| a fatal problem is encountered and the feature cannot execute correctly
    TimedOut
| the feature takes too long to complete and Sentinel VoLTE aborts execution
    processingSipRequest
| the sip request is processed to determine if adding `X-Msw-Companion-Device` header
    companionDeviceHeaderAdded
| the companion device header `X-Msw-Companion-Device` has been added
    companionDeviceHeaderExists
| the companion device header `X-Msw-Companion-Device` already exists in the sip request
    companionDeviceHeaderFailed
| fail to add companion device header
    companionDeviceHeaderNotAuthorized
| companion device provisioned is not operator authorized
    companionDeviceHeaderRetarget
| companion device header will not be added when the sip request is retargeted

== Behaviour

- If the call type is not mobile terminating then the feature finishes with no further processing.

- The feature increases relevant stats and finishes without adding the companion device header, if one of the following situations happens:

  - `oc-retarget` header is found in the sip request;

  - the companion header `X-Msw-Companion-Device` already exists;

  - the companion device data is not operator authorized.

- When it needs to add the companion device header, the feature goes through all the companion devices provisioned and adds the information as `X-Msw-Companion-Device` headers to the sip request. See the header format in X-Msw-Companion-Device Header.

= Vertical Service Code Features :indexpage: :toc: macro :toclevels: 4 :toc-title: On this page…​

Vertical Service Code processing is split between detection logic and processing logic.

== Vertical Service Code detection

VerticalServiceCode feature detects vertical service codes in the dial string, optionally removes them from the SIP Request, and sets the session so subsequent features can give effect to the service code.

Operators will normally only need to assign specific service codes and associated announcements in `VerticalServiceCodes`’s addressList entries.

== Vertical Service Code processing

The following features are designed to have at least some of their functionality triggered by `VerticalServiceCode` feature. These features provide one or more pre-defined VerticalServiceCode_Action profiles which are assigned to operator specific short codes in `VerticalServiceCode`’s addressList entries.

Feature | Description | VSC Triggers
--- | --- | ---
LocationBasedDialling | updates the Request URI of a SIP INVITE, based on the location of the calling party and the dialled number | `PerformLocationBasedDialling` session state field set to `true`
VoicemailDialling | redirects the calling party to their voicemail server. | `PerformLocationBasedDialling` session state field set to `true`
XcapDataUpdate | performs a list of predefined HTTP PUT operations to update subscriber data in an XCAP server. | `XCAP_User_Data` session plan set `XcapDataUpdateActionsQueueAsString` session state field contains required actions `DialledSuffix` sesssion state field used to update XCAP data as appropriate
MMTelOIR | implements the Originating Identification Restriction (OIR) service | `DialledCallerIDRestrictionType` session state field.

== Supplied Vertical Service Code Actions

Sentinel Volte ships with the following predefined VSC Actions. These cover the VSC use cases within the Sentinel Volte feature set.

Action | Session State Field | Value
--- | --- | ---
MMTel OIR - Enable Identity Restriction For Current Session |
    DialledCallerIDRestriction
    OIR_CALLER_ID_BLOCK
MMTel OIR - Disable Identity Restriction For Current Session |
    DialledCallerIDRestriction
    OIR_CALLER_ID_UNBLOCK
MMTel OIR - Enable Identity Restriction Permanently |
    XcapDataUpdateActionsQueueAsString
    Default-Privacy-Restricted
MMTel OIR - Disable Identity Restriction Permanently |
    XcapDataUpdateActionsQueueAsString
    Default-Privacy-Not-Restricted
MMTel OIR - Enable Identity Presentation |
    XcapDataUpdateActionsQueueAsString
    Activate-OIP
MMTel OIR - Disable Identity Presentation |
    XcapDataUpdateActionsQueueAsString
    Deactivate-OIP
MMTel CDIV - Enable Call Forwarding For Busy And No Answer |
    XcapDataUpdateActionsQueueAsString
    Activate-CFNR,
    Activate-CFB,
    Activate-CDIV
MMTel CDIV - Disable Call Forwarding For Busy And No Answer |
    XcapDataUpdateActionsQueueAsString
    Deactivate-CFNR,
    Deactivate-CFB
MMTel CDIV - Enable Unconditional Forwarding To Specified Number |
    XcapDataUpdateActionsQueueAsString
    CFU-Forward-To,
    Activate-CFU,
    Activate-CDIV
MMTel CDIV - Disable Unconditional Forwarding |
    XcapDataUpdateActionsQueueAsString
    Deactivate-CFU
MMTel CDIV - Enable Busy Call Forwarding To Specified Number |
    XcapDataUpdateActionsQueueAsString
    CFB-Forward-To,
    Activate-CFB,
    Activate-CDIV
MMTel CDIV - Disable Busy Call Forwarding |
    XcapDataUpdateActionsQueueAsString
    Deactivate-CFB
MMTel CDIV - Enable No Answer Call Forwarding To Specified Number |
    XcapDataUpdateActionsQueueAsString
    CFNR-Forward-To,
    Activate-CFNR,
    Activate-CDIV
MMTel CDIV - Disable No Answer Call Forwarding |
    XcapDataUpdateActionsQueueAsString
    Deactivate-CFNR
MMTel CDIV - Enable Not Logged In Call Forwarding To Specified Number |
    XcapDataUpdateActionsQueueAsString
    CFNL-Forward-To,
    Activate-CFNL,
    Activate-CDIV
MMTel CDIV - Disable Not Logged In Call Forwarding |
    XcapDataUpdateActionsQueueAsString
    Deactivate-CFNL
MMTel CDIV - Enable Not Reachable Call Forwarding To Specified Number |
    XcapDataUpdateActionsQueueAsString
    CFNRc-Forward-To,
    Activate-CFNRc,
    Activate-CDIV
MMTel CDIV - Disable Not Reachable Call Forwarding |
    XcapDataUpdateActionsQueueAsString
    Deactivate-CFNRc
MMTel CDIV - Enable Service |
    XcapDataUpdateActionsQueueAsString
    Activate-CDIV
MMTel CDIV - Disable Service |
    XcapDataUpdateActionsQueueAsString
    Deactivate-CDIV
Execute Location Based Dialling |
    PerformLocationBasedDialling
    true
Connect Subscriber To Voicemail Provider |
    DialVoicemailServer
    true
Set Default Forward Voicemail Server Number |
    XcapDataUpdateActionsQueueAsString
    Default-Voicemail-Number
Basic_Search_Continue |
Basic_Search_Stop |
Basic_Strip_Service_Code_And_Continue_Search |
Basic_Strip_Service_Code_And_Stop_Search |
Basic_Reject_With_603_Decline |

=== Supplied XCAP Update Action Assumptions

Many of the above VSC actions use the XCAP data Update feature to update subscriber data. The XCAP Data Update feature provides predefined actions to update portions of the user’s XCAP document. Those actions assume the subscriber’s user document has at least the following elements. If the user document has a different structure the XCAP Data Update feature’s corresponding predefined Action will need modification. If the user document has portions missing the provisioning system will need to provide them before the corresponding VSC Action can be assigned to a service code.

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <simservs xmlns:ocp="urn:oma:xml:xdm:common-policy" xmlns:cp="urn:ietf:params:xml:ns:common-policy" xmlns="http://uri.etsi.org/ngn/params/xml/simservs/xcap">
        <originating-identity-presentation active="true"/>
        <originating-identity-presentation-restriction active="true">
            <default-behaviour>presentation-not-restricted</default-behaviour>
        </originating-identity-presentation-restriction>
        <communication-diversion active="false">
            <NoReplyTimer>60</NoReplyTimer>
            <cp:ruleset>
                <cp:rule id="call-diversion-busy">
                    <cp:conditions>
                        <rule-deactivated/>
                        <busy/>
                    </cp:conditions>
                    <cp:actions>
                        <forward-to>
                            <target/>
                        </forward-to>
                    </cp:actions>
                </cp:rule>
                <cp:rule id="call-diversion-unconditional">
                    <cp:conditions>
                        <rule-deactivated/>
                    </cp:conditions>
                    <cp:actions>
                        <forward-to>
                            <target/>
                        </forward-to>
                    </cp:actions>
                </cp:rule>
                <cp:rule id="call-diversion-no-reply">
                    <cp:conditions>
                        <rule-deactivated/>
                        <no-answer/>
                    </cp:conditions>
                    <cp:actions>
                        <forward-to>
                            <target/>
                        </forward-to>
                    </cp:actions>
                </cp:rule>
                <cp:rule id="call-diversion-not-reachable">
                    <cp:conditions>
                        <rule-deactivated/>
                        <not-reachable/>
                    </cp:conditions>
                    <cp:actions>
                        <forward-to>
                            <target/>
                        </forward-to>
                    </cp:actions>
                </cp:rule>
                <cp:rule id="call-diversion-not-logged-in">
                    <cp:conditions>
                        <rule-deactivated/>
                        <not-registered/>
                    </cp:conditions>
                    <cp:actions>
                        <forward-to>
                            <target/>
                        </forward-to>
                    </cp:actions>
                </cp:rule>
            </cp:ruleset>
        </communication-diversion>
        <communication-waiting active="false"/>
        <terminating-identity-presentation active="true"/>
        <terminating-identity-presentation-restriction active="true">
            <default-behaviour>presentation-not-restricted</default-behaviour>
        </terminating-identity-presentation-restriction>
        <incoming-communication-barring active="false">
            <cp:ruleset/>
        </incoming-communication-barring>
        <outgoing-communication-barring active="false">
            <cp:ruleset/>
        </outgoing-communication-barring>
        <extensions/>
    </simservs>

== Related Features

SIP Short Code Feature

= Location Based Dialling :toc: macro :toclevels: 4 :toc-title: On this page…​

This feature updates the Request URI of a SIP INVITE, based on the location of the calling party and the dialled number . The destinations are stored in a Cassandra table by a provisioning tool.

== Feature Cheat Sheet

B2BUA Instance | SAS Support | Originating / Terminating | Point(s) in Session Plan | Network Operator Data | Subscriber Data | Stateful or Stateless | POJO Feature or SBB Feature | Other notes
--- | --- | --- | --- | --- | --- | --- | --- | ---
MMTel | Yes | Both | `SipAccess_SessionCheck` | Yes | No | Stateless | POJO | Will only run if indicated by Vertical Service Code

== Prerequisite Features

- DetermineCallType

- DetermineVoLTEPlanID

- VerticalServiceCode

== Source Code

This feature’s source code is available in the Sentinel VoLTE SDK in the `mmtel-location-based-dialling` module pack. It can be viewed by using the `create-module` command in the SDK with that module pack, for example:

`> create-module new-lbd-module opencloud#mmtel-location-based-dialling#volte/3.1.0;3.1.0.0`

This command will prompt you for information needed to create the new modules, once completed the original source for the feature can be found in the new modules.

The module-pack includes the following modules:

Module Name | Description
--- | ---
mmtel-location-based-dialling | Group module for the feature that includes all of the modules listed below.
mmtel-location-based-dialling-address-list | Contains the profile specification for the feature address list profile table.
mmtel-location-based-dialling-feature | Contains the feature itself.

== Cassandra storage

The feature utilises the Cassandra database to store the destination number to forward to.

== Data Schema

The Cassandra table for Location Based Dialling exists in a keyspace named `opencloud_location_based_dialling`

- For a production environment, the keyspace can be created such that it is replicated. A sample command for creating this keyspace is:

    CREATE KEYSPACE IF NOT EXISTS opencloud_location_based_dialling WITH REPLICATION={'class' : 'SimpleStrategy' ,'replication_factor' : 3 };

- For testing purposes, replication may not be necessary. A sample CQL command for creating such a keyspace is:

    CREATE KEYSPACE IF NOT EXISTS opencloud_location_based_dialling WITH REPLICATION={'class' : 'SimpleStrategy', 'replication_factor' : 1};

Once the keyspace is created, the required tables can be created. The following CQL statements provides the structure of the required table.

    USE opencloud_location_based_dialling;

    CREATE TABLE IF NOT EXISTS opencloud_location_based_dialling.location_based_dialling_data_3gpp (
      dialled_number text,
      cell_id text,
      destination text,
      identifier text,
      PRIMARY KEY (cell_id, dialled_number, identifier)
    );

    CREATE TABLE IF NOT EXISTS opencloud_location_based_dialling.location_based_dialling_uploaded_files (
      name text,
      upload_time timestamp,
      data blob,
      identifier text,
      PRIMARY KEY (name, upload_time, identifier)
    ) WITH CLUSTERING ORDER BY (upload_time DESC);

== Configuration

Configuration for this feature is stored in an address list with address list ID `DefaultActions`, and can be configured in the `LocationBasedDialling_AddressListEntryTable` profile table. The profiles within this table have the following fields:

Parameter | Type | Description
--- | --- | ---
`Address` | String | The digit string that this configuration is for (e.g.: `'611'`).
`FailCall` | boolean | Fail the call if no destination number can be determined for any reason.
`PlayAnnouncement` | boolean | Play an announcement if no destination number can be determined for any reason.
`AnnouncementId` | Integer | The ID of the announcement to play if no destination number can be determined, if 'Play Announcement' is enabled.
`DefaultDestination` | String | The default phone number to forward to if no destination number can be determined, and 'Fail Call' is disabled.

== Session Input Variables

Session State variable name | Type | Comments
--- | --- | ---
    PerformLocationBasedDialling
| boolean | Set by the Vertical Service Code feature. Indicated whether or not the feature should run.
    SentinelSelectionKey
| SentinelSelectionKey | Determines which configuration to use.
    CallType
| CallType | Determines whether or not to update the To header.

== Session Output Variables

Session State variable name | Type | Comments
--- | --- | ---
    EarlyMediaAnnouncementQueue
| List<Integer> | Updated announcement queue with default action announcement ID, if any.

== Statistics

LocationBasedDialling statistics are tracked by the sentinel.volte.sip SBB and can be found under the following parameter set in REM:
SLEE-Usage → sentinel.volte.sip service → sentinel.volte.sip SBB → feature → LocationBasedDialling
or with rhino-stats:
"SLEE-Usage.Services.ServiceID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].SbbID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].feature.LocationBasedDialling"

Statistic | Incremented when…​
--- | ---
    Started
| the feature runs
    FailedToStart
| Sentinel VoLTE encounters an error while attempting to start the feature
    IssuedWarning
| a non-fatal problem is encountered and the feature issues a warning
    FailedDuringExecution
| a fatal problem is encountered and the feature cannot execute correctly
    TimedOut
| the feature takes too long to complete and Sentinel VoLTE aborts execution
    PlayingAnnouncement
| an announcement is scheduled
    EndedCall
| a call is ended without playing an announcement
    PerformedDefaultAction
| no destination could be determined and the configured default action is performed
    UpdatedRequestUri
| the Request URI of the outgoing INVITE is updated
    RetrievedCellIdFromAccessNetworkInfo
| a usable location is extracted from `P-Access-Network-Info`
    RetrievedCellIdFromCellularNetworkInfo
| a usable location is extracted from `Cellular-Network-Info`
    CassandraQueried
| Cassandra is queried for the destination address
    CassandraResponseReceived
| a success response is received from Cassandra
    CassandraErrorReceived
| an error response is received from Cassandra
    CassandraEmptyResultSetReceived
| an empty result set is received from Cassandra
    FeatureInitiated
| the feature is initiated and `PerformLocationBasedDialling` is set to `true`
    InternationalNumberIgnored
| the extracted address string starts with a +, but it is not followed by the configured country code
    StrippedHomeCountryCode
| the + and country code are stripped from the extracted address string
    ResponseLatency
| time from sending the Cassandra request to receiving the Cassandra result, sampled on receipt of the result

== Data Provisioning

=== Rhino Profiles

This feature requires a VerticalServiceCode profile for each dialled number that will have the location based dialling feature applied.

This feature can optionally use a default profile for a dialled number. The default profile is invoked when no matches are found in the Cassandra table for the dialled number.

These default profiles can be created in REM on the feature configuration menu, `Location Based Dialling` page, or they can be provisioned via the console in the `LocationBasedDialling_AddressListEntryTable` profile table.

| If creating profiles via the console, make sure to increment the Version number on the `LocationBasedDialling:DefaultActions` profile in `LocationBasedDialling_AddressListConfigurationTable` in order for the new profiles to be recognized in rhino.

=== Cassandra Database Entries

Database entries for each dialled number can be provisioned with the lbd-provision tool.

| The lbd-provisioning tool can provision up to 5 million rows. Functionality beyond this number of rows is not supported.

== Behaviour

1. Get the address string to use in address analysis

2. Get the location

3. Find the destination address and update the outgoing INVITE

4. Default action if destination cannot be determined

=== Get the address string to use in address analysis

The feature first checks whether the `PerformLocationBasedDialling` session state field has been set to `true` by the Vertical Service Code feature. If not, the feature returns without making any changes.

Next, the feature extracts from the Request URI a digit string that corresponds to the destination (or called) party. Digit strings may be in a Tel URL, or the user part of a SIP URI.

If the number retrieved from the Tel URI or SIP URI user part contains a + sign followed by the configured country code, the + sign and the country code are removed.

=== Get the location

The feature extract the 3GPP Cell ID from the SIP INVITE. First, it tries to parse all `P-Access-Network-Info` headers until it can extract a 3GPP Cell ID as follows:

- If the access network is `3GPP-GERAN`, use the `cgi-3gpp` value.

- If the access network is `3GPP-UTRAN-FDD` or `3GPP-UTRAN-TDD` and `network-provided` is set, use the `utran-sai-3gpp` value.

- If the access network is `3GPP-UTRAN-FDD` or `3GPP-UTRAN-TDD` and `network-provided` is not set, use the `utran-cell-id-3gpp` value.

- If the access network is `3GPP-UTRAN` or `3GPP-HSPA`, use the `utran-sai-3gpp` value.

- If the access network is `3GPP2-1X`, use the `ci-3gpp2` value.

- If the access network is `3GPP-1X-HRPD`, use the `ci-3gpp2` value.

- If the access network is `3GPP-1X-UMB`, use the `ci-3gpp2` value.

- If the access network is `3GPP-1X-FEMTO`, use the `ci-3gpp2-femto` value.

- If the access network is `3GPP-E-UTRAN-FDD` or `3GPP-E-UTRAN-TDD`, use the `utran-cell-id-3gpp` value.

- If the access network is `3GPP-E-UTRAN`, use the `utran-cell-id-3gpp` value.

- If the access network is `3GPP-E-UTRAN-ProSe-UNR`, use the `utran-cell-id-3gpp` value.

If no 3GPP Cell ID can be determined from the `P-Access-Network-Info` headers (for example when the user is on WLAN), the feature next parses the `Cellular-Network-Info` headers in the same way.

If still no location can be determined, the default action is performed.

=== Find the destination address and update the outgoing INVITE

The feature performs a Cassandra lookup using the number extracted from the Request URI and the location extracted from the `P-Access-Network-Info` or `Cellular-Network-Info` headers. If Cassandra returns a destination address, the Request URI and (in the case of a `MobileOriginating` or `MobileForwarded` call) the To header field are updated to the new destination, and the feature finishes execution. If a + sign and the country code were previously stripped from the dialled number, they are now re-added.

If no destination address can be found, the default action is performed.

=== Default action if destination cannot be determined

If, for any reason, the destination cannot be determined, a default action is performed according to the configuration detailed above. The call is either rejected with a 403 error code, or is forwarded to a configured default destination. In either case, a configured announcement can be played to the calling party. This announcement is scheduled and is played by the SipPlayAnnouncement feature. If no address list entry can be found, the feature issues a warning and does not perform any other actions, and call processing continues as normal.

= Voicemail Dialling :toc: macro :toclevels: 4 :toc-title: On this page…​

This feature redirects the calling party to their voicemail server.

== Feature cheat sheet

Feature Script Name | VoicemailDialling
Call-Type | Orig
Session Plan | mmtel-orig
Execution Points | SipAccess_SubscriberCheck
Network Operator Config | No
Subscriber Config | Yes
POJO or SBB | POJO
Feature FSMs | None
Feature Parameters | None
SAS Support | Yes
RA Entity Links | None

== Prerequisite Features

There are no strict prerequisites, however this feature will not do anything unless the DialVoicemailServer session state field has been set to `true`. Normally this will be done by the VerticalServiceCode feature.

== Session State Inputs and Outputs

=== Inputs

Name | Type | Purpose
--- | --- | ---
DialVoicemailServer | boolean | Indicates whether or not the feature should execute redirection to the voicemail server.
MetaswitchForwardToVoicemail | ForwardToVoicemailData | Contains the subscriber data that has the voicemail server URI.

=== Outputs

None.

== Statistics

VoicemailDialling statistics are tracked by the sentinel.volte SBB and can be found under the following parameter set in REM:
SLEE-Usage → sentinel.volte service → sentinel.volte SBB → feature → VoicemailDialling
or with rhino-stats:
"SLEE-Usage.Services.ServiceID[name=sentinel.volte,vendor=OpenCloud,version=3.1.0].SbbID[name=sentinel.volte,vendor=OpenCloud,version=3.1.0].feature.VoicemailDialling"

Name | Type | Description
--- | --- | ---
    Started
| Counter | Incremented when the feature is triggered.
    FailedToStart
| Counter | Incremented when the feature fails to start.
    FailedDuringExecution
| Counter | Incremented when the feature fails while executing.
    IssuedWarning
| Counter | Incremented when the feature issues a warning.
    TimedOut
| Counter | Incremented when the feature times out during execution.
    MissingVoicemailServerURI
| Counter | Incremented when the feature is unable to redirect the call to the voicemail server because the URI could not be found.
    InvalidVoicemailServerURI
| Counter | Incremented when the feature is unable to redirect the call to the voicemail server because the URI is not valid.
    CallingLegMissing
| Counter | Incremented when the feature is unable to redirect the call to the voicemail server because the calling party leg has been released.
    RetargetSuccessful
| Counter | Incremented when the feature successfully redirects the call to the voicemail server.
    CallTerminated
| Counter | Incremented when the feature ends the session due to being unable to retarget the call.

== Configuration

This feature depends on subscriber data provisioned in `Forward-To-Voicemail` section of the Metaswitch-TAS-Services document in the HSS.

The following attribute from that section is used:

Name | Type | Description
--- | --- | ---
    voicemailServer
| String | The URI for the voicemail server to connect to.

See the Metaswitch-TAS-Services Schema to Session-State Fields mapping for more details about the Metaswitch-TAS-Services document.

== Behaviour

This feature redirects the calling party to their voicemail server. It will only do this if the DialVoicemailServer session state field has been set to `true`. Normally this will be done by the VerticalServiceCode feature when a subscriber dials a special number that has been configured with a vertical service code action.

There is a vertical service code action included in the out of the box Sentinel VoLTE deployment that can be used to do this. A full list of all pre-configured service code actions can be found here: Supplied Vertical Service Code Actions.

= XCAP Data Update :toc: macro :toclevels: 4 :toc-title: On this page…​

This feature performs a list of predefined HTTP PUT operations to update subscriber data in an XCAP server.

== Feature Cheat Sheet

B2BUA Instance | SAS Support | Originating / Terminating | Point(s) in Session Plan | Network Operator Data | Subscriber Data | Stateful or Stateless | POJO Feature or SBB Feature | Other notes
--- | --- | --- | --- | --- | --- | --- | --- | ---
MMTel | Yes | Originating | `SipAccess_SubscriberCheck` in `XCAP_User_Data` session plan. | Yes | Updated | Stateless | POJO | Will only run if indicated by Vertical Service Code feature

== Prerequisite Features

- SipSubscriberDetermination

- VerticalServiceCode

== Configuration

Feature configuration defines the XCAP server and document, and success and failure responses. It is common to all update actions.

Action configuration maps the named actions to details of which part of the XCAP document is to be updated and with what value.

=== Feature Configuration

The profiles within the `XcapDataUpdateConfigProfileTable` are selected using the `SentinelSelectionKey` and have the following fields:

Parameter | Type | Description
--- | --- | ---
    xcapServer
    String
| XCAP server to send HTTP requests to
    xcapServerPort
    int
| XCAP server port, a value of 0 will use the default port
    xcapServerPath
    String
| Path of the XCAP server application e.g. `/rem/sentinel/xcap`
    auid
    String
| Application Unique ID e.g. `simservs.ngn.etsi.org`
    Document
    String
| XCAP Document to update, e.g. `simservs.xml`
    successResponseStatusCode
    int
| SIP Response status code to use following a successful HTTP response. Because the SIP session is ended using this code, it should be a SIP error response (300+)
    failureResponseStatusCode
    int
| SIP Response status code to use following a failure HTTP response
    failureAnnouncementID
    int
| Announcement ID to play on document update failure. Use `0` to not play an announcement if the update fails
    useHttps
    boolean
| Whether to use HTTPS

=== Action Configuration

The profiles within the `XcapDataUpdateActionConfigProfileTable` are selected using the `SentinelSelectionKey` and action name and have the following fields:

Parameter | Type | Description
--- | --- | ---
    actionName
    String
| Name of the action
    documentPath
    String
| An XCAP Node Selector (subset of XPath) expression to select the element or attribute to update
    XMLNS
    String
| XCAP definitions for any XML namespaces used in `documentPath` e.g. `xmlns(cp=urn:ietf:params:xml:ns:common-policy)`. Empty if no namespaces are used
    isElement
    boolean
| Whether the field to update is an element. If `false` it is treated as an attribute.
    elementName
    String
| The name of the field to update if it is an element
    useDialledDigitsAsParameter
    boolean
| Whether the dialled digits should be used as the new value of the XCAP Node
    parameter
    String
| The new value of the XCAP Node when not using dialled digits

If `isElement` is `true` it is expected the `documentPath` node selector will select an element whose name is `elementName`.

if `isElement` is `true` and `useDialledDigitsAsParameter` is false, it is expected that `parameter` will be serialised replacement content of the selected element.

if `isElement` is `false` and `useDialledDigitsAsParameter` is false, it is expected that `parameter` will be a serialised attribute value and the `documentPath` node selector will select an element’s attribute.

== Session Input Variables

Session State variable name | Type | Comments
--- | --- | ---
    SentinelSelectionKey
| SentinelSelectionKey | Determines which configuration to use.
    XcapDataUpdateActionsQueueAsString
| String | A comma separated list of Actions to be performed (spaces not ignored)
    DialledSuffix
| String | Can be used as the replacement value in the xcap update request
    Subscriber
| String | Used as the XUI to identify the user in the XCAP server.

== Session Variables These fields are used internally to maintain state while each XCAP request is in progress.

Session State variable name | Type | Comments
--- | --- | ---
    XcapDataUpdateActionsQueue
| List<String> | Remaining actions to perform after the current one
    XcapDataUpdateActionInProgress
| String | The action currently in progress
    XcapDataUpdateAci
| ActivityContextInterface | The activity context associated with the current HTTP request
    XcapDataUpdateNormalizedDialledSuffix
| String | Cached normalized version of `DialledSuffix`

== Session Output Variables

Session State variable name | Type | Comments
--- | --- | ---
    EndSessionAfterAnnouncement
| int | `SuccessResponseStatusCode` of the feature config, when there is an announcement scheduled and all XCAP updates succeed. `FailureResponseStatusCode` of the feature config when a `FailureAnnouncementID` is configured and an XCAP update fails. Unchanged otherwise.
    EarlyMediaAnnouncementInfoQueue
| List<SipAnnouncementInformation> | Unmodified when all XCAP updates succeed. When an XCAP update fails if `FailureAnnouncementID` is not 0 in the feature config, this field is set to only contain that announcement otherwise, this field is cleared.

== Statistics

XcapDataUpdate statistics are tracked by the sentinel.volte.sip SBB and can be found under the following parameter set in REM:
SLEE-Usage → sentinel.volte.sip service → sentinel.volte.sip SBB → feature → XcapDataUpdate
or with rhino-stats:
"SLEE-Usage.Services.ServiceID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].SbbID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].feature.XcapDataUpdate"

Statistic | Incremented when…​
--- | ---
    Started
| the feature runs
    FailedToStart
| Sentinel VoLTE encounters an error while attempting to start the feature
    IssuedWarning
| a non-fatal problem is encountered and the feature issues a warning
    FailedDuringExecution
| a fatal problem is encountered and the feature cannot execute correctly
    TimedOut
| the feature takes too long to complete and Sentinel VoLTE aborts execution
    SentXcapUpdate
| the feature sends an XCAP request
    ReceivedXcapUpdateSuccess
| the features receives a success response to an XCAP update request
    ReceivedXcapUpdateFailure
| the feature receives a failure response to an XCAP update request

== Behaviour

The feature assumes that any appropriate announcements to indicate successful update of subscriber data have already been enqueued by `Vertical-Service-Code` feature.

The feature extracts the action names from `XcapDataUpdateActionsQueueAsString`.

For each action name sequentially

- The feature sends an XCAP request for the action and waits for a response. See [Sending an XCAP request]

- If a failure response is received

  - no further actions are processed

  - the announcement queue is cleared

  - if a `FailureAnnouncementID` is configured, that announcement is queued and the SIP session is ended with `FailureResponseStatusCode` after the announcement plays

  - otherwise the SIP session is ended with `FailureResponseStatusCode` immediately.

If all actions succeed…​

- if there are queued announcements the session state field `EndSessionAfterAnnouncement` is set to the value of `SuccessResponseStatusCode`

- otherwise the SIP session is ended immediately using `SuccessResponseStatusCode`

=== Sending an XCAP Request

The action name is used to read the appropriate action profile. If the profile cannot be found, the feature fails to execute with Invalid Configuration cause.

The URL for the request is generated from feature configuration, the action profile and the session state as follows:

- The URL’s protocol is set according to the feature config’s `UseHttps` value.

- The URL’s host and port are set from the feature config’s `XCAPServer` and `XCAPServerPort` values.

- The URL’s path is set to contain the following segments

  - The config’s `XCAPServerPath` value

  - The config’s `AUID` value

  - The constant value `users`

  - The session state’s `Subscriber` value percent encoded

  - The config’s `Document` value percent encoded

  - If the action’s `DocumentPath` is set,

    - the action’s `DocumentPath` value percent encoded and prefixed with `~~`

- The URL’s query is set to the action’s `XMLNS` value if present

Additional headers are set:

- `X-3GPP-Asserted-Identity` is set to the value of session state’s `Subscriber` field

- If the action’s `IsElement` is true `Content-Type` is set to `application/xcap-el+xml`

- otherwise `Content-Type` is set to `application/xcap-att+xml`

The request body is generated:

- if action’s `IsElement` is true the body is a serialized XML element.

  - The element name is the action’s `ElementName` value.

  - The element has no attributes.

  - If the action’s `UseDialledDigitsAsParameter` is true the content of the element is a `tel:` URI of the normalized value of the session state field `DialledSuffix`

  - Otherwise the content of the element is the action’s `Parameter` value.

- Otherwise

  - If the action’s `UseDialledDigitsAsParameter` is true the body is the normalized value of the session state field `DialledSuffix`.

  - Otherwise the body is the action’s `Parameter` value.

The request including those headers and that body is sent to that URL.

Session state is updated so that the HTTP response can handled.

= SCC Features :indexpage: :sortorder: 40

These features are SCC specific.

Group | What it provides
--- | ---
SCCDetermineSessionType | classifies incoming `INVITE` and `MESSAGE` requests to determine if they are invoking SCC services
SCC Decode Companion Device Info | decodes the `X-Msw-Companion-Device` headers in a SIP request into a list of `CompanionDevice` objects in `CompanionDevices` session state field for access by other features
Packet Switched to Circuit Switched Access Transfer Features | These features implement SCC-AS support for Single Radio VCC
Service Centralisation Features | These features implement support for service centralization via the SCP as described in GSMA IR.64
Terminating Access Domain Selection Features | These features implement the routing strategy for the terminating trigger

= SCCDetermineSessionType toc: :sortorder: 1

== What is SCC Determine Session Type? This feature classifies incoming `INVITE` and `MESSAGE` requests to determine if they are invoking SCC services .

An `INVITE` request may be classified as:

- a Reorigination `INVITE` request

- an Access Transfer Request

  - Which will be further classified by the type of Access Transfer

- a standard `INVITE` request

A `MESSAGE` request may be classified as:

- an OpenCloud internal Access Transfer directive

- not of interest to the SCC AS

Once classified, it rejects those that the implementation is known not to handle, by sending a `403 Forbidden` error response. If an incoming request appears to be invoking an SCC service but is missing critical information, it will be rejected with a `400 Bad Request` error response.

== Feature Cheat Sheet

B2BUA Instance | SAS Support | Originating / Terminating | Point(s) in Session Plan | Network Operator Data | Subscriber Data | Stateful or Stateless | POJO Feature or SBB Feature | Other notes
--- | --- | --- | --- | --- | --- | --- | --- | ---
SCC | Yes | Both Originating and Terminating | `SipAccess_SessionAccept`, `SipTransaction_Accept` | Yes | None | Stateless | POJO | Classifies an incoming Request, sets a session state field

== Related Features This feature is part of a group of features that implement SCC-AS behaviour. This feature is a prerequisite for SCCSendRequestToAnchor and for DetermineVoltePlanId (on an SCC-AS only).

== Network Operator Data === VoLTE Shared Config Configuration from the JSLEE profile table `VoLTESharedConfigProfileTable` is used to define the per node URI The following values are used:

- SCCASURI - When running as an SCC AS this value is used for the ASURI in Session State

=== Conferencing Conferencing handover detection relies on configuration data that is retrieved from the `SCCConfHandlingConfigProfileTable` profile table.

The following value is used:

- EnableSCCConfHandling - Used to determine whether conferencing handover is enabled

=== Reorigination Reorigination detection relies on configuration data that is retrieved from the JSLEE profile table named `SCCCommonReOriginationConfigProfileTable`.

The following values are used:

- UsePrefix - Used to determine if a network prefix is used to detect reorigination

- NetworkPrefix - The prefix that should be used to detect reorigination

=== Access Transfer Access Transfer detection relies on the platform having three values configured:

- the Access Transfer Update - Session Transfer Identifier (ATU-STI)

- the Session Transfer Number - Single Radio (STN-SR)

- the SCC AS’s own URI

The ATU-STI and STN-SR are configured in a profile table `RegistrarConfigurationTable`, and the SCC AS URI is configured in a second profile table `VoLTESharedConfigProfileTable`.

=== Notes on Config Profiles The profile tables used by this feature are `RegistrarConfigurationTable`, `VoLTESharedConfigProfileTable`, `SCCCommonReOriginationConfigProfileTable`, and `SCCConfHandlingConfigProfileTable`.

The Profile Name within the tables is scoped according to the Sentinel Selection Key.

An example profile name is "OpenCloud:::::". This means:

The platform name is "OpenCloud". There is no Network Operator, Session Type, Plan Id, or Subscription ID scoping. The values may also be configured through the Sentinel REM screen:

- Sentinel ▶ Feature Configuration ▶ SCC Determine Session Type (SIP)

- Sentinel ▶ Feature Configuration ▶ SCC Camel To IMS Reorigination (SIP)

- Sentinel ▶ Feature Configuration ▶ VoLTE Shared Config Profile (SIP)

== Session Output Variables

Session State Variable Name | Java Type | Valid Values
--- | --- | ---
SCCSessionType | A Java enum with type name `com.opencloud.volte.sentinel.common.sessionstate.types.SCCSessionType` | AccessTransfer, Reorigination, Standard
AccessTransferType | A Java enum with type name `com.opencloud.volte.sentinel.common.sessionstate.types.AccessTransferType` | eSRVCC_Anchored, eSRVCC_Not_Anchored, Additional_Session_Transfer, SRVCC, Internal_Directive, Bad_Request_STNSR, Bad_Request_ATUSTI, Bad_Request_SCCURI, None
ASURI | String | A SIP URI
ConferenceFactoryPSI | String | Set if the From header address is a conference factory PSI supported by the platform.

== Statistics

SCCDetermineSessionType statistics are tracked by the sentinel.volte.sip SBB and can be found under the following parameter set:
SLEE-Usage → [sentinel.volte.sip service name] → [sentinel.volte.sip SBB name] → feature.SCCDetermineSessionType

Statistic | Increments when…​
--- | ---
    Started
| The feature is started.
    FailedToStart
| Sentinel VoLTE encounters an error while attempting to start the feature.
    IssuedWarning
| A non-fatal problem is encountered and the feature issues a warning.
    FailedDuringExecution
| A fatal problem is encountered and the feature cannot execute correctly.
    TimedOut
| The feature takes too long to complete and Sentinel VoLTE aborts execution.
    SelectedStandardScc
| The feature determines that the incoming `INVITE` request is for a standard SCC session.
    SelectedReorigination
| The feature determines that the incoming `INVITE` request is for reorigination.
    SelectedESRVCCAnchored
| The feature determines that the incoming `INVITE` request is for rel-10 access transfer with anchored media.
    SelectedESRVCCNotAnchored
| The feature determines that the incoming `INVITE` request is for rel-10 access transfer with non-anchored media.
    SelectedSRVCC
| The feature determines that the incoming `INVITE` request is for rel-8 access transfer.
    SelectedAdditionalSessionTransfer
| The feature determines that the incoming `INVITE` request is for an additional session transfer.
    SelectedSpecialConfHandover
| The feature determines that the incoming `INVITE` request is for a special CONF handover
    SelectedInternalAccessTransferDirective
| The feature determines that the incoming `MESSAGE` request is for an OpenCloud internal access transfer directive.
    ReceivedBadRequestToSTNSR
| The feature receives a malformed request for rel-8 access transfer.
    ReceivedBadRequestToATUSTI
| The feature receives a malformed request for rel-10 access transfer.
    ReceivedBadRequestToSCCURI
| The feature receives a malformed request for an additional session transfer.
    ReceivedReoriginationRequestWithUnknownID
| The feature receives a reorigination request with an IMRN which is not known as a correlation ID

== Behaviour

The feature begins by checking that it was triggered by an initial SIP `INVITE` or `MESSAGE` request.

- If the trigger is not an initial SIP request, the feature will raise an unsupported trigger event error and complete processing.

- If the trigger is an initial SIP request but is not an `INVITE` or `MESSAGE`, then no further action is required and the feature will complete processing.

- If the trigger is an initial `INVITE` or `MESSAGE` request, the feature will move on to load its configuration

If any configuration data is missing, then the feature will raise an invalid configuration error and complete processing.

Once configuration is loaded, the feature will analyse the incoming request to determine what type of session the request is for. It populates the `SCCSessionType` and `AccessTransferType` session state fields based on what it determines.

For an `INVITE` request the feature will check if it is one of:

- A "Reorigination" request

- An SCC conferencing special request

- A "Rel-8 Access Transfer (SRVCC)" request

- A "Rel-10 Access Transfer (eSRVCC)" request

- An "Additional Session Transfer" request

If none of the above is true, then the `INVITE` will be treated as a "Standard SCC Session".

For a `MESSAGE` request the feature will check if it is an "Internal Access Transfer Directive", if it is not then the request will be treated as a "No Internal Access Transfer Directive" case.

The following sections detail the conditions and feature behaviour for each possible session type.

=== Reorigination

Reorigination is determined by looking at the `Request-URI` of the incoming `INVITE`. If it is a `tel:` URI that begins with the configured reorigination prefix number, then the request is considered a reorigination request and the feature will do the following:

- set the `SCCSessionType` to `Reorigination`.

- set the `AccessTransferType` to `None`.

- increment the `SelectedReorigination` statistic.

=== SCC conferencing special request

A SCC conferening special request is determined if:

- this is an `SCC` call that is `MobileOriginating` or `MobileForwarded`

- the `From` header address is a conference factory PSI supported by the platform

- there exists a Replaces header that is not empty

In this case:

- set the `SCCSessionType` to `AccessTransfer`.

- set the `AccessTransferType` to `Special_Conf_Handover`

- set the session state field `ConferenceFactoryPSI` to the From header address

=== Rel-8 Access Transfer (SRVCC)

Rel-8 Access Transfer is determined by looking at the `Request-URI` of the incoming `INVITE`. If it begins with the configured `STN-SR` prefix number, then the request is considered a rel-8 access transfer request. In 3GPP specifications this is known as a "SIP INVITE request due to STN-SR".

The feature will then do an additional check for the presence of a `P-Asserted-Identity` header on the `INVITE` request. If the header is present, then the request is considered to be a rel-8 access transfer request and the feature will do the following:

- set the `SCCSessionType` to `AccessTransfer`.

- set the `AccessTransferType` to `SRVCC`.

- increment the `SelectedSRVCC` statistic.

If the `P-Asserted-Identity` header is absent, then the request is malformed and the feature will do the following:

- set the `SCCSessionType` to `AccessTransfer`.

- set the `AccessTransferType` to `Bad_Request_STNSR`.

- increment the `ReceivedBadRequestToSTNSR` statistic.

- terminate the session by replying to the `INVITE` with a `400 Bad Request` response.

=== Rel-10 Access Transfer (eSRVCC)

Rel-10 Access Transfer is determined by looking at the `Request-URI` of the incoming `INVITE`. If it matches the configured value for the `ATU-STI`, then the request is considered to be a rel-10 access transfer request. In 3GPP specifications this is known as a "SIP INVITE request due to ATU-STI for PS to CS SRVCC".

The feature will then do an additional check for the presence of a `Target-Dialog` or `Replaces` header on the `INVITE` request. If one of those headers is present, then the request is considered to be a rel-10 access transfer request for the case where media is anchored in the ATCF and the feature will do the following:

- set the `SCCSessionType` to `AccessTransfer`.

- set the `AccessTransferType` to `eSRVCC_Anchored`.

- increment the `SelectedESRVCCAnchored` statistic.

If both the `Target-Dialog` and `Replaces` headers are absent, the feature will move on to check for the presence of a `P-Asserted-Identity` header. If that header is present, then the request is considered to be a rel-10 access transfer request for the case where media is not anchored in the ATCF, and the feature will do the following:

- set the `SCCSessionType` to `AccessTransfer`.

- set the `AccessTransferType` to `eSRVCC_Not_Anchored`.

- increment the `SelectedESRVCCNotAnchored` statistic.

If both the `P-Asserted-Identity` is also absent, then the request is malformed and the feature will do the following:

- set the `SCCSessionType` to `AccessTransfer`.

- set the `AccessTransferType` to `Bad_Request_ATUSTI`.

- increment the `ReceivedBadRequestToATUSTI` statistic.

- terminate the session by replying to the `INVITE` with a `400 Bad Request` response.

=== Additional Session Transfer

Additional session transfer is determined by looking at the `Request-URI` of the incoming `INVITE`. If it matches the configured value for the URI of the SCC-AS, then the request is considered to be for an additional session transfer.

The feature will then do an additional check for the presence of a `Target-Dialog` header on the `INVITE` request. If the header is present, then the feature will do the following:

- set the `SCCSessionType` to `AccessTransfer`.

- set the `AccessTransferType` to `Additional_Session_Transfer`.

- increment the `SelectedAdditionalSessionTransfer` statistic.

- terminate the session by replying to the `INVITE` with a `403 Forbidden` response, as this type of access transfer is not supported by the SCC-AS.

If the `Target-Dialog` header is absent, then the request is malformed and the feature will do the following:

- set the `SCCSessionType` to `AccessTransfer`.

- set the `AccessTransferType` to `Bad_Request_SCCURI`.

- increment the `ReceivedBadRequestToSCCURI` statistic.

- terminate the session by replying to the `INVITE` with a `400 Bad Request` response.

=== Standard SCC Session

If an `INVITE` meets none of the above conditions, then the request is considered to be for a standard SCC session and the feature will do the following:

- set the `SCCSessionType` to `Standard`.

- set the `AccessTransferType` to `None`.

- increment the `SelectedStandardScc` statistic.

=== Internal Access Transfer Directive

An Internal Access Transfer Directive is a `MESSAGE` request sent from a remote SCC AS node that is handling an access transfer request. Such a request is sent when the remote node determines that the node receiving the request is responsible for handling a session associated with the access transfer that it is processing. The request instructs the receiving node on what to do with that associated session.

To be considered an Internal Access Transfer Directive, a `MESSAGE` request must meet two conditions:

- The `Request-URI` must match the URI of the receiving SCC AS.

- The request must include an OC-Access-Transfer-Procedure header.

If those conditions are met, then the feature will do the following:

- set the `SCCSessionType` to `AccessTransfer`.

- set the `AccessTransferType` to `Internal_Directive`.

- increment the `SelectedInternalAccessTransferDirective` statistic.

=== No Internal Access Transfer Directive

If an incoming `MESSAGE` request is not an Internal Access Transfer Directive, then the SCC AS does not need to handle it. The feature will do the following

- set the `SCCSessionType` to `Standard`.

- set the `AccessTransferType` to `None`.

= Packet Switched to Circuit Switched Access Transfer Features :indexpage: :toc: macro :toclevel: 4 :toc-title: On this page…​ :sortorder: 2

An architecture view of SCC-AS capabilities is available in the Service Continuity and Access Transfer section of the architecture document.

== Feature listing

Feature | What it does
--- | ---
SCCBindEnhancedSRVCC | prepares a signalling anchor such that it is ready to receive and process an access transfer request for the current session
SCCSendRequestToAnchor | receives an Access Transfer `INVITE` or `MESSAGE` request and forwards the request to the appropriate Signalling Anchor instance
SCCProcessHandoverInsideAnchor | implements the procedures for SCC-AS transferring of a single active session. It executes inside a signalling anchor instance
SCCDetermineTransferableSet | determines the transferable set for access transfer
SCCCoordinateSignallingAnchors | sends SIP MESSAGE requests to instruct superfluous session removal
SCCRemoveSuperfluousSession | terminates a superfluous session as part of access transfer procedures
SCCDetermineExternalSessionTracking | enables Access Leg Tracking for the current session if the UE is SR-VCC capable and has a C-MSISDN
SCCTerminatingPreAnswerSessionTransfer | implements SCC-AS procedures for access transfer of a terminating call in the alerting phase using PS to CS SRVCC
SCCOriginatingPreAnswerSessionTransfer | implements SCC-AS procedures for access transfer of an originating call in the alerting or pre-alerting phases using PS to CS SRVCC
SCCAugmentRefer | assists with originating sessions towards the Conference Factory by augmenting the REFER request sent from the UE to the Conference Factory

== Relationship between the features

A high level relationship between the features is illustrated through a series of diagrams.

=== Access transfer of a single established session

Call flow diagrams for this case are shown on Call flows for Session transfer of an active session.

The following diagram shows the main features used for transfer of a single active session. It assumes all signalling involves a single cluster member for the purposes of simplicity.

There are two sessions shown:

1. the "Anchored session" - the session to be transferred and

2. the "Transfer session" - the session initiated by the Handover INVITE

The Anchored session is shown twice in the diagram to represent its two phases, the initial phase and the transfer phase. At the top of the diagram, the Anchored session in its initial phase is first executed until SCCBindEnhancedSRVCC feature has finished. The diagram shows that the DetermineVoltePlanId, SCCDetermineSessionType, SCCDetermineExternalSessionTracking, TrackSession, and SCCBindEnhancedSRVCC features are executed sequentially. At this point the call is answered.

In the middle of the diagram the Transfer session is shown. Some time after the Anchored session is answered, a Handover INVITE arrives at the SCC-AS. This then executes the DetermineVoltePlanId, SCCDetermineSessionType, SCCDetermineTransferableSet, and SCCSendRequestToAnchor features in sequence. The SCCSendRequestToAnchor feature internally passes the Handover INVITE to the existing Anchored session. The Transfer session is then deleted without performing any further signalling.

Finally at the bottom of the diagram, the Anchored session is shown for the transfer phase. It executes the SCCProcessHandoverInsideAnchor feature to perform access transfer for the established session, and then the SCCCoordinateSignallingAnchors feature once access transfer has completed. In this case there are no superfluous sessions and so it finishes execution without modifying any state.

=== Access transfer of an originating session in the alerting or pre-alerting state

Call flow diagrams for this case are shown on Call flows for Session transfer of an outgoing call in the alerting phases.

The following diagram shows the main features used for transfer of an outgoing call in the alerting phase. It assumes all signalling involves a single cluster member for the purposes of simplicity.

There are two sessions shown:

1. the "Anchored session" - the session to be transfered (in the alerting phase), and

2. the "Transfer session" - the session initiated by the Handover INVITE

The Anchored session is shown twice in the diagram to represent its two phases, the initial phase and the transfer phase. The initial phase in starts on receipt of an initial INVITE request and has finished when the call is in the alerting state. The sequence of the features executed in the initial phase are DetermineVoltePlanId, SCCDetermineSessionType, SCCDetermineExternalSessionTracking, AccessLegTracking, SCCBindEnhancedSRVCC, and ExternalSessionTracking. At this point the call is in the alerting phase.

In the middle of the diagram the Transfer session is shown. Some time after the Anchored session is alerting, a Handover INVITE arrives at the SCC-AS. This executes the DetermineVoltePlanId, SCCDetermineSessionType, SCCDetermineTransferableSet, and SCCSendRequestToAnchor features in sequence. The SCCSendRequestToAnchor feature internally passes the Handover INVITE to the existing Anchored session. The Transfer session is then deleted without performing any further signalling.

The last stage of the diagram shows the Anchored session during the transfer phase. It executes the SCCOriginatingPreAnswerSessionTransfer feature to perform access transfer for the originating alerting session. Once the transfer is complete (a 2xx to the Handover INVITE has been sent to the MSC and an ACK to that 2xx received) the SCCCoordinateSignallingAnchors feature executes. In this case there are no superfluous sessions and so it finishes execution without modifying any state.

=== Access transfer of a single established session and removal of a held session

A call flow for a similar case is shown in the Administration guide on the Complex co-ordination example.

The following diagram simplifies the case to simply having two established sessions, one in the held state (i.e call on hold), and another in the active state (i.e. call in speech).

There are three sessions shown:

1. the active session,

2. the held session, and

3. the transfer session

In time, prior to the diagram there are two established sessions, one active and one held.

The top of the diagram shows the receipt of a Handover INVITE. The transfer session executes these features in order DetermineVoltePlanId, SCCDetermineSessionType, SCCDetermineTransferableSet, SCCSendRequestToAnchor. In this example the transferable set indicates that there is one session to transfer (the active session), and one superfluous session (the held session).

The Handover INVITE is provided to the active session. This causes execution of SCCProcessHandoverInsideAnchor. Once the handover has completed, the SCCCoordinateSignallingAnchors feature executes. As the transferable set contains a superfluous session, SCCCoordinatingSignallingAnchors informs the held session to clean up. This is achieved through the use of a SIP MESSAGE request containing an OC-Access-Transfer-Procedure header with value `remove-superfluous`. The active session continues to exist until the call is terminated.

The MESSAGE request is received inside the held session. The SCCRemoveSuperfluousSession feature executes checking the OC-Access-Transfer-Procedure header value. As the session is established, it terminates the session through sending a BYE request on both the access leg and remote leg.

=== Reuse of Access Transfer procedures for conferencing

The SCC-AS is able to be configured to convert an INVITE w/Replaces from the Conference Factory to a re-INVITE on the consulting call. It follows similar procedures to Access transfer of a single established session with the following key differences:

- The "Anchored Session" is the consulting call between the conference moderator and the participant, that will be in the held state.

- The "Transfer Session" is the INVITE w/Replaces sent towards the participant from the conference factory.

- No sessions are classified as superfluous or additional sessions.

For how this affects the call flow see Re-INVITE Based Three-party conference setup overview

= SCCAugmentRefer :toc: macro :toclevel: 4 :toc-title: On this page…​ :sortorder: 1

This feature assists with originating sessions towards the Conference Factory by augmenting the REFER request sent from the UE to the Conference Factory .

The moderator UE sends a REFER request to add and remove conference participants. Such a REFER request contains a `Refer-To` header that is often re-written by Application Servers. The original value as sent by the UE is necessary for Re-INVITE based conferencing. This can be achieved through two means:

1. copying the original value into a different header - the approach taken by this feature, or

2. disabling any Application Server invocation for originating attempts towards the Conference Factory - the approach taken prior to introduction of this feature when re-INVITE based conference is used.

== Feature cheat sheet

B2BUA Instance | SAS Support | Originating / Terminating | Point(s) in Session Plan | Network Operator Data | Subscriber Data | Stateful or Stateless | POJO or SBB Feature | Other notes
--- | --- | --- | --- | --- | --- | --- | --- | ---
SCC | Yes | Originating only |
    SubscriptionSipRequest
| None | None | Stateless | POJO | Copies `Refer-To` header to `X-MSW-Original-Refer-To`

== Prerequisite features

- DetermineCallType

- DetermineVoltePlanId

== Network operator data

There is none.

== Subscriber data

There is none.

== Session input and output variables

=== Session input variables

N/A

=== Session output variables

N/A

== Statistics

SCCAugmentRefer statistics are tracked by the sentinel.volte.sip SBB and can be found under the following parameter set:
SLEE-Usage → [sentinel.volte.sip service name] → [sentinel.volte.sip SBB name] → feature.SCCAugmentRefer

Statistic | Increments when…​
--- | ---
    Started
| The feature is started.
    FailedToStart
| Sentinel VoLTE encounters an error while attempting to start the feature.
    IssuedWarning
| A non-fatal problem is encountered and the feature issues a warning.
    FailedDuringExecution
| A fatal problem is encountered and the feature cannot execute correctly.
    TimedOut
| The feature takes too long to complete and Sentinel VoLTE aborts execution.
    ReceivedRefer
| The feature is triggered on a REFER request.
    AugmentedRefer
| The REFER request contains a `Refer-To` header

== Behaviour

This feature ignores any Trigger that is not a SIP REFER request. If the REFER request has a `Refer-To` header the feature copies the incoming `Refer-To` header into an outbound `X-MSW-Original-Refer-To` header.

This is to facilitate conference moderator Access Transfer where an originating SCC-AS must be present between the moderator UE and the call to the Conference Factory.

The rationale for this behaviour is that the `Refer-To` header tends to be re-written by routing B2BUA’s and the original value must be visible to the Conference Factory for re-INVITE based flows.

= SCCBindEnhancedSRVCC :toc: macro :toclevel: 4 :toc-title: On this page…​ :sortorder: 1

This feature prepares a signalling anchor such that it is ready to receive and process an access transfer request for the current session .

The preparation takes place during session establishment. The notification is in the form of a SIP request. It includes the ID of the SIP dialog for the access leg to be transferred.

== Feature cheat sheet

B2BUA Instance | SAS Support | Originating / Terminating | Point(s) in Session Plan | Network Operator Data | Subscriber Data | Stateful or Stateless | POJO or SBB Feature | Other notes
--- | --- | --- | --- | --- | --- | --- | --- | ---
SCC | Yes | Both Originating and Terminating |
    SipAccess_SessionCheck, SipAccess_PartyResponse
| None | None | Stateless | POJO | Binds a name in `ACNaming`.

== Related features

3GPP Rel 10 Packet Switched to Circuit Switched support is implemented as a grouping of features and Sentinel capabilities.

Related features are:

- SCCSendRequestToAnchor

- SCCDetermineSessionType

- SCCProcessHandoverInsideAnchor

== Prerequisite features

- DetermineCallType

== Network operator data

There is none.

== Subscriber data

There is none.

== Session input and output variables

=== Session input variables

Variable | Type | Description
--- | --- | ---
CallType | Enum | Used to determine whether originating or terminating instance behaviour should be invoked.
EnhancedSRVCCBound | boolean | Indicates whether an activity context name has already been bound for this session.
FeatureCapsManager | FeatureCapsManager | Management interface for controlling Feature-Caps header values on outgoing messages.

=== Session output variables

Variable | Type | Description
--- | --- | ---
EnhancedSRVCCBound | boolean | This field is set when the access dialog is bound to its activity context name.
FeatureCapsManager | FeatureCapsManager | Management interface for controlling Feature-Caps header values on outgoing messages.

== Statistics

SCCBindEnhancedSRVCC statistics are tracked by the sentinel.volte.sip SBB and can be found under the following parameter set:
SLEE-Usage → [sentinel.volte.sip service name] → [sentinel.volte.sip SBB name] → feature.SCCBindEnhancedSRVCC

Statistic | Increments when…​
--- | ---
    Started
| The feature is started.
    FailedToStart
| Sentinel VoLTE encounters an error while attempting to start the feature.
    IssuedWarning
| A non-fatal problem is encountered and the feature issues a warning.
    FailedDuringExecution
| A fatal problem is encountered and the feature cannot execute correctly.
    TimedOut
| The feature takes too long to complete and Sentinel VoLTE aborts execution.
    BoundACName
| The feature binds and activity context name using the full dialog-ID.
    BoundPartialACName
| The feature binds and activity context name using the partial dialog-ID.
    UnboundACName
| The feature unbinds a full dialog-ID activity context name.
    UnboundPartialACName
| The feature unbinds a partial dialog-ID activity context name.

== Behaviour

This feature binds an activity context name for the access dialog.

=== Activity Context Name Binding

The feature binds the access dialog (access leg in 3GPP terminology) to a normalised name in the Activity Context Naming Facility.

The binding takes place once a non-100 provisional or a success response is received for the initial `INVITE`.

The feature does not attempt to bind more than once per session.

Once the name is bound successfully, the feature sets the session output variable `enhancedSRVCCBound` to `true`.

The access dialog is as follows:

- for an originating B2BUA instance, the access dialog is the dialog from the A party

- for a terminating B2BUA instance, the access dialog is the dialog towards the B party.

Therefore when acting as an originating anchor, the feature obtains the full SIP Dialog ID from the response in `SessionState.latestCallingPartyResponse`.

When acting as a terminating anchor, the feature obtains the full SIP Dialog ID from the response in `SessionState.latestCalledPartyResponse`.

==== Procedure for normalising the name to use

The normalised name string is comprised of four parts:

1. the CallID header in string form (for example, `me03a0s09a2sdfgjk1491777`)

2. the remote tag parameter value (for example, `774321`)

3. the local tag parameter value (for example, `64727891`)

4. a string to help with readability (for example, `esr` indicating “enhanced SRVCC”).

For the originating SCC B2BUA instance, the local tag is the `from-tag`, and the remote tag is the `to-tag`.

For the terminating SCC B2BUA instance, the local tag is the `to-tag`, and the remote tag is the `from-tag`.

These are then normalised into a single string form as follows:

- CallID value followed by a semi-colon, then

- `r=` followed by the value of the remote tag parameter, followed by a semi-colon, then

- `l=` followed by the value of the local tag parameter, followed by a semi-colon, then

- `esr;`

So, given the following:

- CallID of `me03a0s09a2sdfgjk1491777`

- remote tag parameter value of `774321`

- local tag parameter value of `64727891`

We generate the following normalised string:
`me03a0s09a2sdfgjk1491777;r=774321;l=64727891;esr;`

The rationale for choosing a format like this is so that an administrator can look at the string, and see:

- `esr` means it is enhanced SRVCC as opposed to SRVCC (because our BindSRVCC feature uses `sr` not `esr`)

- `r` and `l` are easy short hand for `remote` and `local`.

= SCCSendRequestToAnchor :toc: macro :toclevel: 4 :toc-title: On this page…​ :sortorder: 2

This feature receives an Access Transfer `INVITE` or `MESSAGE` request and forwards the request to the appropriate Signalling Anchor instance .

For an architectural view of co-ordinating signalling anchors refer to Shared ATU-STI.

== Feature cheat sheet

B2BUA Instance | SAS Support | Originating / Terminating | Point(s) in Session Plan | Network Operator Data | Subscriber Data | Stateful or Stateless | POJO Feature or SBB Feature | Other notes
--- | --- | --- | --- | --- | --- | --- | --- | ---
SCC | Yes | Both Originating and Terminating | `SipAccess_SessionStart`, `SipTransaction_Start` | Yes | None | Stateless | Feature SBB | Looks up an AC Name and fires an event

== Prerequisite features

SCCDetermineSessionType must run before this feature.

== Related features

Related features that run in a SCC signaling anchor instance are:

- SCCBindEnhancedSRVCC

- SCCProcessHandoverInsideAnchor

== Network operator data

Network operator data for SCCSendRequestToAnchor is stored in a profile table named `SCCSendRequestToAnchorConfigProfileTable`.

The data is scoped according to a Sentinel selection key.

=== SRTAAttemptWithReversedTags attribute

This is of type Boolean.

If true, the feature will reverse the remote and local tags when attempting to lookup a SIP session using its dialog ID.

=== Defaults for network operator data

Attribute Name | Default Value
--- | ---
    AttemptWithReversedTags
    false

== Subscriber data

None

== Session input and output variables

=== Session input variables

Variable | Type | Description
--- | --- | ---
AccessTransferType | Enum | Determines aspects of how a request is handled by the feature.
SentinelSelectionKey | SentinelSelectionKey | Used to load configuration data.
AccessTransferIsLocal | boolean | Determines if the feature should deliver to a session on the same node or proxy to another node in the cluster
SessionToTransfer | TrackedSession (POJO) | The session to transfer, as provided by the DetermineTransferableSetFeature

=== Session output variables

None

== Statistics

`SCCSendRequestToAnchor` statistics are tracked by the `scc-send-request-to-anchor-sbb` SBB and can be found under the following parameter set in REM:
SLEE-Usage → sentinel.volte.sip service → scc-send-request-to-anchor-sbb
or with rhino-stats:
"SLEE-Usage.Services.ServiceID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].SbbID[name=scc-send-request-to-anchor,vendor=OpenCloud,version=3.1.0]"

Name | Description
--- | ---
    Invoked
| Incremented each time the feature runs
    Error
| Incremented when a fatal error occurs during feature execution
    TerminatedSessionWith480
| Incremented when the feature rejects an access transfer request with a 480 response
    SentInviteRequest
| Incremented when the feature sends an access transfer INVITE to the signalling anchor instance
    SentMessageRequest
| Incremented when the feature sends an access transfer MESSAGE to the signalling anchor instance
    InviteSessionMismatched
| Incremented when the dialog-ID from the access transfer request does not match the session to transfer in session state

== Behaviour

On starting, the feature will check the method of the triggering SIP Request and read the session input attribute `AccessTransferType`.

If the request method is `INVITE`, and the `AccessTransferType` has the value `eSRVCC_Anchored`, `eSRVCC_Not_Anchored` or `SRVCC` the feature will execute the behaviour described in Handling of Access Transfer Request.

If the request method is `MESSAGE`, and the `AccessTransferType` has the value `Internal_Directive` the feature will execute the behaviour described in Handling of Access Transfer Request - Local.

Otherwise the feature finishes execution without modifying any state.

=== Handling of Access Transfer Request

If the session variable AccessTransferIsLocal is set to `true` the feature will execute the behaviour described in Handling of Access Transfer Request - Local. Otherwise the behaviour described in Handling of Access Transfer Request - Remote will be executed.

==== Handling of Access Transfer Request - Local

The feature will examine certain headers in the incoming request to determine a Activity Context Name that can be used to find the session that the request is targeted at. Which headers that are considered depend on the method of the request.

- For `INVITE` requests, the feature will check the `Target-Dialog` header first, if one is not found the `Replaces` header will also be checked.

- For `MESSAGE` requests, only the `Target-Dialog` header is considered.

If no appropriate header is present, the feature rejects the incoming request with a `480 Temporarily Unavailable` error response and complete execution.

The feature will use the header to create a normalised lookup string as described in Creation of Activity Context Naming lookup string. This string is used to look up an Activity Context from the Activity Context Naming Facility.

If the naming lookup indicates that there was no Activity Context bound to the name the feature will reject the incoming request with a `480 Temporarily Unavailable` error response and complete execution.

If the naming lookup returns an Activity Context the feature:

- fires the `INVITE` or `MESSAGE` request event on the returned activity context;

  - the OC-Access-Transfer-Procedure header will be added to the request (if not already present), to pass instructions to the receiving SCCProcessHandoverInsideAnchor feature.

- removes the AC name binding (unbinds the `ACName` that was just looked up);

- instructs the Sentinel core that this Sentinel instance shall finish; and in doing so, shall not modify any SIP signaling on the dialog.

==== Handling of Access Transfer Request - Remote

The feature:

- adds an `OC-Access-Transfer-Procedure` header with the value of the `AccessTransferType` variable,

- removes the topmost route header from the request so the local node is removed from the call path, and

- forwards the request to the URI stored in the `SessionToTransfer`.

If forwarding the request fails because the target node is no longer a member of the cluster, the feature will fall back to the procedure described in bxref:#handling-of-access-transfer-request-local.

=== Creation of Activity Context Naming lookup string

The feature creates a normalised string from the `Target-Dialog` or `Replaces` header using four values:

- the `Call-ID` value

- the `remote-tag` parameter value (or `from-tag` in `Replaces`)

- the `local-tag` parameter value (or `to-tag` in `Replaces`)

- and a string to help with readability (the value `esr` short form for “Enhanced SRVCC”).

It then takes these four values and constructs a lookup key as follows:

- `Call-ID` value, followed by a semi-colon

- `r=` followed by the value of the remote-tag parameter, and a semi-colon

- `l=` followed by the value of the local-tag parameter, and a semi-colon

- `esr;`

If the `AttemptWithReversedTags` configuration option is set to `true` the values for `l=` and 'r=' will be swapped.

The following example shows a `Target-Dialog` header and the normalised form:

- header is `Target-Dialog: me03a0s09a2sdfgjkl491777; remote-tag=774321; local-tag=64727891`

- normalised form is `me03a0s09a2sdfgjkl491777;r=774321;l=64727891;esr;`

- normalised form with reversed tags is `me03a0s09a2sdfgjkl491777;r=64727891;l=774321;esr;`

= SCCProcessHandoverInsideAnchor :toc: macro :toclevel: 4 :toc-title: On this page…​ :sortorder: 3

This feature implements the procedures for SCC-AS transferring of a single active session. It executes inside a signalling anchor instance .

It is executed once the SCC-AS has determined that there is an active session, and has provided the INVITE to the signalling anchor. It is responsible for processing incoming access transfer handover INVITE requests i.e. INVITE due to STN-SR or INVITE due to ATU-STI. It performs a remote update if necessary, and closes the old Access Leg (source access leg).

== Feature cheat sheet

B2BUA Instance | SAS Support | Originating / Terminating | Point(s) in Session Plan | Network Operator Data | Subscriber Data | Stateful or Stateless | POJO Feature or SBB Feature | Other notes
--- | --- | --- | --- | --- | --- | --- | --- | ---
SCC | Yes | Both Originating and Terminating | SIP Mid-Session Party Request/Response | None | None | Stateless | POJO |

== Prerequisite features

- DetermineInitialLegNames

- SCCDetermineSessionType

== Related features

Related features that run in a SCC signaling anchor instance are:

- SCCBindEnhancedSRVCC

- SCCSendRequestToAnchor

== Network operator data

None

== Subscriber data

None

== Session input and output variables

=== Session input variables

Variable | Type | Description
--- | --- | ---
CallType | String | Used to determine if access transfer is being performed for the called party or the calling party.
CurrentRemoteLegName | String | Used to find the remote leg.
CurrentLocalLegName | String | Used to find the old access leg.

=== Session output variables

Variable | Type | Description
--- | --- | ---
NewAccessLegName | String | The name of the new access leg.
OldAccessLegName | String | The name of the old access leg.
CurrentCalledLegName | String | The name of the current called leg, updated when access transfer is performed for the called party.
CurrentCallingLegName | String | The name of the current calling leg, updated when access transfer is performed for the calling party.
CurrentLocalLegName | String | The name of the current local leg, updated when access transfer occurs.

== Statistics

SCCProcessHandoverInsideAnchor statistics are tracked by the sentinel.volte.sip SBB and can be found under the following parameter set in REM:
SLEE-Usage → sentinel.volte.sip service → sentinel.volte.sip SBB → feature → SCCProcessHandoverInsideAnchor
or with rhino-stats:
"SLEE-Usage.Services.ServiceID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].SbbID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].feature.SCCProcessHandoverInsideAnchor"

Name | Description
--- | ---
    Started
| Incremented when the feature is started.
    FailedToStart
| Incremented when Sentinel VoLTE encounters an error while attempting to start the feature.
    IssuedWarning
| Incremented when a non-fatal problem is encountered and the feature issues a warning.
    FailedDuringExecution
| Incremented when a fatal problem is encountered and the feature cannot execute correctly.
    TimedOut
| Incremented when the feature takes too long to complete and Sentinel VoLTE aborts execution.
    RemoteUpdateRequired
| Incremented when the feature determines that a remote update is required.
    RemoteUpdateNotRequired
| Incremented when the feature determines that a remote update is not required.
    SentRemoteUpdate
| Incremented when a remote update is sent to the remote party.
    RemoteUpdateSuccess
| Incremented when a success response is received for the remote update request.
    RemoteUpdateError
| Incremented when a failure response is received for the remote update request.
    RemoteUpdate491Retry
| Incremented when a 491 response with `OC-Retry-After` header is received for the remote update request.
    CallAnsweredWith200
| Incremented when a success response is sent for the handover INVITE on the new access leg.
    ReleasedOldAccessLeg
| Incremented when the old access leg is released.
    LinkedNewAccessLegToRemoteLeg
| Incremented when the new access leg is linked to the remote leg.
    TerminatedSession
| Incremented when the session is terminated due to an error during access transfer.
    AccessTransferComplete
| Incremented when the access transfer process is complete, after the ACK is received on the new access leg.
    TimerStarted
| Incremented when the retry timer is started
    TimerFired
| Incremented when the retry timer is fired
    TimerCancelled
| Incremented when the retry timer is cancelled
    MaskedInviteEvent
| Incremented when the feature masks delivery of further INVITE events on the new access leg.
    UnmaskedInviteEvent
| Incremented when the feature unmasks delivery of further INVITE events on the new access leg.

== Behaviour

An INVITE due to ATU-STI, or an INVITE due to STN-SR that arrive at the SCC-AS are referred to as a "Handover INVITE" in this page. This feature implements the transfer of a single active session as per section 12.3.5 of 3GPP TS 24.237. It includes support for anchored and non-anchored media at the ATGW. The removal of superfluous sessions is implemented by the SCCCoordinateSignallingAnchors and SCCRemoveSuperfluousSession features.

=== Remote and Access Legs

An Originating SCC signalling anchor has two legs, prior to access transfer. One from the A party (the Access Leg), and one towards the B party (the Remote Leg). I.e. the INVITE received by the SCC-AS from the S-CSCF is on the Access Leg. The INVITE sent towards the S-CSCF is on the Remote Leg.

A Terminating SCC signalling anchor has two legs, prior to access transfer. One from the A party (the Remote Leg), and one towards the B party (the Access Leg). I.e. the INVITE received by the SCC-AS from the S-CSCF is on the Remote Leg. The INVITE sent towards the S-CSCF is on the Access Leg.

The SCC-AS acts as a routing B2BUA between the Access and Remote legs.

In 3GPP TS 24.237, the phrases source access leg and target access leg are used. This document refers to the old access leg and new access leg respectively.

=== Detecting Handover INVITE

The feature is initially triggered on any mid-session INVITE request. In order to determine if the request is a handover INVITE, the feature looks for the OC-Access-Transfer-Procedure header, set by the SCCSendRequestToAnchor feature.

If this header is not present, the feature ignores the request and finishes without interfering with the call flow.

If the header is present, the feature will begin Initial Handover Procedures, and then continue according to the selected access transfer type.

=== Initial Handover Procedures

Upon detecting a handover INVITE, the feature begins the access transfer process. It starts by importing the SIP leg that the handover INVITE was received on into the current call session as the "new access" leg. The feature then examines the SDP in the handover request to see if it is in line with the currently negotiated SDP for the session. If the SDP is different, then the feature will undertake Access Transfer Procedures for Non-Anchored Media to renegotiate the SDP with the remote party; if the SDP matches the currently negotiated SDP then Access Transfer Procedures for Anchored Media will be undertaken. Regardless of whether SDP needs to be renegotiated, the feature will unlink the old access SIP leg from the leg towards the remote party.

=== Access Transfer Procedures for Non-Anchored Media

If the SDP needs to be renegotiated with the remote party, the feature will generate a Re-INVITE request for the remote party based on the original handover request (with the `OC-Access-Transfer-Procedure` header removed). The feature will send this Re-INVITE and then end processing until triggered by a response (or a new request). The feature’s next action will depend on what triggers it:

Trigger | Behaviour
--- | ---
Error response from remote leg | Access transfer will be aborted, the old access leg will be re-linked to the remote leg, and the error response will be forwarded on the new access leg.
BYE request from remote leg | All legs will be terminated. A 200 OK to the BYE will be sent on the remote leg. A 480 Temporarily Unavailable in response to the access transfer INVITE will be sent on the new access leg. A BYE request will be sent on the old access leg.
New INVITE request from the old access leg | Reject the INVITE with a 491 response, continue waiting for Re-INVITE response
BYE request from old access leg | Reply with 200 OK, continue waiting for Re-INVITE response
Success response from remote leg | Forward the response on the new access leg and link the new access leg to the remote leg, await ACK

After receiving a 200 OK response from the remote leg, the feature will await the ACK for the 200 from the new access leg. Upon receiving the ACK, the feature will terminate the old access leg (sending a BYE).

The signalling anchor (Sentinel instance) hosting the SCC features is now acting as a B2BUA between the new access leg (from the ATCF) and the remote leg (through the S-CSCF).

The feature is then complete.

=== Access Transfer Procedures for Anchored Media

In the event that no change in the SDP needs to be negotiated with the remote party, the feature will immediately answer the handover INVITE with a 200 OK response, and await the ACK from the new access leg. Upon receiving the ACK from the new access leg, the feature will link that leg to the remote leg. The ACK will not be forwarded.

If a BYE is received from the old access leg while waiting for the ACK, the BYE will be accepted with a 200 OK, terminating the old access leg. If no BYE is received then the feature will automatically terminate the old access leg (sending a BYE) upon receiving the ACK from the new access leg.

Once the ACK has been received the transfer is complete.

The signalling anchor (Sentinel instance) hosting the SCC features is now acting as a B2BUA between the new access leg (from the ATCF) and the remote leg (through the S-CSCF).

A call flow for this procedure is shown SCC Access Transfer Media Anchored Flow.

== Call flows for Session transfer of an active session

The following flows described in 3GPP TS 24.237 and illustrate the signalling for transfer of a single active session.

=== Media not anchored in the ATGW

Please refer to 3GPP TS 24.237 appendix A.18.2. It contains a signalling flow for PS to CS SRVCC enhancements using the ATCF without media anchored in the ATGW.

=== Media anchored in the ATGW

Please refer to 3GPP TS 24.237 appendix A.18.3. It contains a signalling flow for PS to CS SRVCC enhancements using the ATCF where media is anchored in the ATGW.

= SCCDetermineTransferableSet :toc: macro :toclevel: 4 :toc-title: On this page…​ :sortorder: 4

This feature determines the transferable set for access transfer .

The transferable set is a phrase from 3GPP 24.237, and includes sessions that will be transferred during an access transfer, and those that are considered superfluous.

== Feature cheat sheet

B2BUA Instance | SAS Support | Originating / Terminating | Point(s) in Session Plan | Network Operator Data | Subscriber Data | Stateful or Stateless | POJO or SBB Feature | Other notes
--- | --- | --- | --- | --- | --- | --- | --- | ---
SCC | Yes | Both Originating and Terminating |
    SCCAccessTransfer_SipAccess_SessionStart
| None | None | Stateless | POJO |

== Prerequisite features

- SCCDetermineSessionType

== Session input and output variables

=== Session input variables

Variable | Type | Description
--- | --- | ---
    AccessTransferType
| AccessTransferType (Enum) | This feature will only run when this field is set to `eSRVCC_Not_Anchored`, `eSRVCC_Anchored`, or `SRVCC`
    ASURI
| String | The SIP URI of the current node

=== Session output variables

Variable | Type | Description
--- | --- | ---
    MostRecentlyActive
| TrackedSession (POJO) | Contains all the information in TrackedDialogKeys about the most recently active session
    SuperfluousSessions
| Set<TrackedSession> | A set of all of the other sessions found from querying the TrackedDialogKeys table
    AccessTransferIsLocal
| boolean | True if the MostRecentlyActive’s ASURI field is the same as the current nodes ASURI

== Statistics

SCCDetermineTransferableSet statistics are tracked by the sentinel.volte.sip SBB and can be found under the following parameter set in REM:
SLEE-Usage → sentinel.volte.sip service → sentinel.volte.sip SBB → feature → SCCDetermineTransferableSet
or with rhino-stats:
"SLEE-Usage.Services.ServiceID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].SbbID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].feature.SCCDetermineTransferableSet"

Name | Description
--- | ---
    Started
| Incremented each time the feature runs
    FailedToStart
| Incremented when a fatal error occurs before feature execution
    IssuedWarning
| Incremented when a non-fatal error occurs during feature execution
    FailedDuringExecution
| Incremented when a fatal error occurs during feature execution
    TimedOut
| Incremented when feature execution does not complete within a reasonable time frame
    SessionOwnershipQuery
| Incremented when the feature sends a query to the session ownership facility
    SessionOwnershipError
| Incremented when a TrackedDialogKeys lookup fails with a Session Ownership error
    SessionOwnershipSuccess
| Incremented when a TrackedDialogKeys lookup returns successfully
    SessionOwnershipNoDataFound
| Incremented when no matching tracked dialog keys entries were found in the session ownership facility
    FoundTrackedSession
| Incremented when the feature successfully finds a Session Ownership Record resulting from a TrackedSession
    SavedSessionToTransfer
| Incremented when the feature saves the most recently active TrackedSession to session state
    SavedSuperfluousSessions
| Incremented when the feature saves all of the remaining TrackedSession’s to session state
    SessionOwnershipAsyncQueryTimeSuccess
| Samples the elapsed time between starting a query and a success response arriving from the session ownership facility
    SessionOwnershipAsyncQueryTimeFailure
| Samples the elapsed time between starting a query and a failure response arriving from the session ownership facility

== Behaviour

This feature uses the `P-Asserted-Identity` header from the handover `INVITE` as an "additional key" to look up a Session Ownership Record. Prior sessions for the purposes of SCC write Session Ownership Records saved by the AccessLegTracking and External Session Tracking features.

Each returned Session Ownership Record is converted into an API object named `TrackedSession`.

The `TrackedSession` with the most recent `LastActiveTime` is stored in Session State as the `MostRecentlyActiveSession`. All other Tracked Sessions are stored in the `SuperfluousSessions` set. The feature sets the `AccessTransferIsLocal` flag in Session State if the `MostRecentlyActiveSession` has an `OwnerURI` value the same as the current node’s `ASURI`.

= SCCCoordinateSignallingAnchors :toc: macro :toclevels: 4 :toc-title: On this page…​ :sortorder: 5

This feature sends SIP MESSAGE requests to instruct superfluous session removal .

For an architectural view of co-ordinating signalling anchors refer to Shared ATU-STI.

== Feature cheat sheet

B2BUA Instance | SAS Support | Originating / Terminating | Point in Session Plan | Network Operator Data | Subscriber Data | Stateful or Stateless | POJO Feature or SBB Feature
--- | --- | --- | --- | --- | --- | --- | ---
SCC | Yes | Originating and Terminating | `SipMidSession_PartyRequest` and `SipEndSession` | Yes | No | Stateless | POJO

== Prerequisite Features

- SCCDetermineSessionType

- SCCProcessHandoverInsideAnchor

- SCCDetermineTransferableSet

== Network Operator Data

Network configuration is stored in a JSLEE profile table named `SCCCoordinateSignallingAnchorsConfigProfileTable`.

Parameter | Type | Default Value | Description
--- | --- | --- | ---
`CoordinateSessionsDelay` | int | `2000` | Time in milliseconds to wait between receiving the access transfer ACK and sending out SIP MESSAGEs to remove superfluous sessions.

== Session input variables

Variable | Type | Description
--- | --- | ---
    ASURI
| String | The URI of this SCC node loaded by SCCDetermineSessionType
    AccessTransferACKed
| boolean | Set by SCCProcessHandoverInsideAnchor to indicate that the Access Transfer INVITE has been ACK’d.
    SuperfluousSessions
| Set<TrackedSession> | The set of TrackedSessions that will be removed. A SIP MESSAGE is sent for each entry. Set by SCCDetermineTransferableSet.

== Session output variables

None.

== Statistics

SCCCoordinateSignallingAnchors statistics are tracked by the sentinel.volte.sip SBB and can be found under the following parameter set in REM:
SLEE-Usage → sentinel.volte.sip service → sentinel.volte.sip SBB → feature → SCCCoordinateSignallingAnchors
or with rhino-stats:
"SLEE-Usage.Services.ServiceID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].SbbID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].feature.SCCCoordinateSignallingAnchors"

Name | Description
--- | ---
    Started
| Incremented each time the feature runs
    FailedToStart
| Incremented when a fatal error occurs before feature execution
    IssuedWarning
| Incremented when a non-fatal error occurs during feature execution
    FailedDuringExecution
| Incremented when a fatal error occurs during feature execution
    TimedOut
| Incremented when feature execution does not complete within a reasonable time frame
    TimerStarted
| Incremented when the feature starts the timer
    TimerFired
| Incremented when the feature receives the timer event
    TimerCanceled
| Incremented when the feature cancels the timer
    SentSuperfluousSessionMessage
| Incremented when the feature sends a SIP MESSAGE request to a remote node to remove a superfluous session
    SentSuperfluousSessionMessageInternally
| Incremented when the feature sends a SIP MESSAGE event internally to remove a superfluous session
    CouldNotFindInternalTargetSession
| Incremented when the target session could not be found

== Behaviour

The feature is first triggered when an Access Transfer is completed by receiving an ACK for the handover INVITE. When the ACK is received, the SCCProcessHandoverInsideAnchor feature sets the session state flag `AccessTransferACKed`. When that flag is `TRUE`, this feature will arm a timer with the value in `CoordinateSessionsDelay`.

Then when either the timer fires, or the session is ending the feature will construct a SIP MESSAGE for each TrackedSession in `SuperfluousSessions`. These MESSAGEs are sent to trigger SCCRemoveSuperfluousSession on the node in control of those sessions.

The MESSAGE will have the following headers set:

Header Name | Header Value
--- | ---
    RequestURI
| The `ASURI` of the TrackedSession
    From
| The `ASURI` of this node from Session State
    To
| The `ASURI` of the TrackedSession
    Target-Dialog
| The `EstablishedDialogID` of the TrackedSession
    OC-Access-Transfer-Procedure
| `Remove-Superfluous`
    P-Asserted-Identity
| The `ASURI` of this node from Session State

= SCCRemoveSuperfluousSession :toc: macro :toclevel: 4 :toc-title: On this page…​ :sortorder: 6

This feature terminates a superfluous session as part of access transfer procedures .

== Feature cheat sheet

B2BUA Instance | SAS Support | Originating / Terminating | Point(s) in Session Plan | Network Operator Data | Subscriber Data | Stateful or Stateless | POJO or SBB Feature | Other notes
--- | --- | --- | --- | --- | --- | --- | --- | ---
SCC | Yes | Both Originating and Terminating |
    SipTransaction_Request
| None | None | Stateless | POJO |

== Prerequisite features

None.

== Session input and output variables

=== Session input variables

None.

=== Session output variables

None.

== Statistics

SCCRemoveSuperfluousSession statistics are tracked by the sentinel.volte.sip SBB and can be found under the following parameter set in REM:
SLEE-Usage → sentinel.volte.sip service → sentinel.volte.sip SBB → feature → SCCRemoveSuperfluousSession
or with rhino-stats:
"SLEE-Usage.Services.ServiceID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].SbbID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].feature.SCCRemoveSuperfluousSession"

Name | Description
--- | ---
    Started
| Incremented each time the feature runs
    FailedToStart
| Incremented when a fatal error occurs before feature execution
    IssuedWarning
| Incremented when a non-fatal error occurs during feature execution
    FailedDuringExecution
| Incremented when a fatal error occurs during feature execution
    TimedOut
| Incremented when feature execution does not complete within a reasonable time frame
    TriggeredOnSipRequest
| Incremented when the feature is triggered by a SIP `MESSAGE` request from another node
    TriggeredOnAccessTransferRequest
| Incremented when the feature is triggered by an internal `AccessTransferRequest` event from the same node
    SentMessageResponse
| Incremented when a response to the triggering `MESSAGE` request is successfully sent
    SessionTerminated
| Incremented when the session is terminated

== Behaviour

=== Background

This feature is one part of the SCC Access Transfer system. It is triggered on an existing `INVITE` session by a SIP `MESSAGE` request, which directed into the session by the SCCSendRequestToAnchor feature.

=== Feature Execution

When invoked, the feature will perform a check to ensure that it was triggered by an incoming SIP request; if not, the feature will complete execution raising an unsupported trigger error. If the trigger is an incoming SIP request, additional checks will be made to determine if the request is both a `MESSAGE` request, and has an OC-Access-Transfer-Procedure header with the value `Remove-Superfluous`. If either of those checks fail, the feature will ignore the request and complete execution normally.

If the trigger is confirmed to be an incoming SIP `MESSAGE` request with the appropriate header, the feature will do two things before completing execution:

1. Immediately send a SIP `200 OK` response for the `MESSAGE` request.

2. Terminate the session using the appropriate procedure based on the call state:

   - For sessions still being established, a `404 Not Found` response for the initial `INVITE` will be sent upstream and a `CANCEL` request will be sent downstream.

   - For established sessions, a `BYE` will be sent in both directions.

If `200 OK` response for the `MESSAGE` request fails to send for any reason, the feature will raise an error, but will still attempt to end the session.

= SCCDetermineExternalSessionTracking :toc: macro :toclevel: 4 :toc-title: On this page…​ :sortorder: 7

This feature enables Access Leg Tracking for the current session if the UE is SR-VCC capable and has a C-MSISDN .

== Feature cheat sheet

B2BUA Instance | SAS Support | Originating / Terminating | Point(s) in Session Plan | Network Operator Data | Subscriber Data | Stateful or Stateless | POJO Feature or SBB Feature | Other notes
--- | --- | --- | --- | --- | --- | --- | --- | ---
SCC | Yes | Both Originating and Terminating | `SipAccess_SessionStart` | Yes | None | Stateless | POJO | Consults third party registration state

== Pre-requisite features

- Determine Call Type

- DetermineVoLTEPlanID

- One of the following based on system configuration

  - IMSIDLookup

  - IMSIDLookupFromCassandraSIP

- FetchCMSISDN

== Session input and output variables

=== Session input variables

Session state variable name | Type | Comments
--- | --- | ---
    RegistrationRecord
| Object | This contains all of the registration information for the served user.
    CMSISDN
| String | A string set to a non-null value if there is a C-MSISDN provisioned for the user, and if the user is logged in; if the user is not logged in, or if the MSRN is set, then it is set to null.
    AccessLegTrackingKeys
| Set<String> | The tracking keys to use for the current sessions.
    SentinelSelectionKey
| SentinelSelectionKey | Used to check for session plans that do not require session tracking.

=== Session output variables

Session state variable name | Type | Comments
--- | --- | ---
    AccessLegTrackingKeys
| Set<String> | The tracking keys to use for the current session. The feature adds to this set.
    AccessLegTrackingActive
| boolean | Set to true if the UE has a C-MSISDN and UE-SRVCC capability.
    AccessLegUESRVCCSupport
| Enumeration | Set to one of NONE, DEFAULT, ALERTING, PRE-ALERTING.

== Statistics

SCCDetermineExternalSessionTracking statistics are tracked by the sentinel.volte.sip SBB and can be found under the following parameter set in REM:
SLEE-Usage → sentinel.volte.sip service → sentinel.volte.sip SBB → feature → SCCDetermineExternalSessionTracking
or with rhino-stats:
"SLEE-Usage.Services.ServiceID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].SbbID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].feature.SCCDetermineExternalSessionTracking"

Name | Description
--- | ---
    Started
| Incremented each time the feature runs
    FailedToStart
| Incremented when a fatal error occurs before feature execution
    IssuedWarning
| Incremented when a non-fatal error occurs during feature execution
    FailedDuringExecution
| Incremented when a fatal error occurs during feature execution
    TimedOut
| Incremented when feature execution does not complete within a reasonable time frame
    FoundTrackingKey
| Incremented when the Served User has an IMS registration with UE-SRVCC-Capability and a C-MSISDN
    ExternalSessionTrackingDisabled
| Incremented when the Served User does not have an IMS registration with UE-SRVCC-Capability and a C-MSISDN
    PartialDialogExternalSessionTrackingEnabled
| Incremented when the Served User supports UE-SRVCC-Capability and has the `g.3gpp.ps2cs-srvcc-orig-pre-alerting` media feature tag

== Behaviour

The feature scans all Third Party Registration information for the Served User’s IMS Public Identity. If any registration indicates that the device has support for UE-SRVCC-Capability, and it has an assigned C-MSISDN, then:

1. Session Tracking is enabled via setting the `AccessLegTrackingActive` flag in session state to `TRUE`,

2. the value of the C-MSISDN is added to the `AccessLegTrackingKeys` set in session state, and

3. the `AccessLegUESRVCCSupport` session state field is set to `DEFAULT`

4. the feature increments the `FoundTrackingKey` statistic and finishes execution

Otherwise the feature sets the `AccessLegTrackingActive` flag to `FALSE`, increments the `ExternalSessionTrackingDisabled` statistic and finishes execution.

| When running a T-ADS only session plan, this feature immediately determines that session tracking is not required and skips the registration data check.

= SCCTerminatingPreAnswerSessionTransfer :toc: macro :toclevel: 4 :toc-title: On this page…​ :sortorder: 9

This feature implements SCC-AS procedures for access transfer of a terminating call in the alerting phase using PS to CS SRVCC .

This page refers to SIP INVITE due to STN-SR or SIP INVITE due to ATU-STI as a "Handover INVITE".

== Feature cheat sheet

B2BUA Instance | SAS Support | Originating / Terminating | Points in Session Plan | Network Operator Data | Subscriber Data | Stateful or Stateless | POJO Feature or SBB Feature | Feature FSM
--- | --- | --- | --- | --- | --- | --- | --- | ---
SCC | Yes | Terminating | `SipAccessPartyRequest`, `SipAccessPartyResponse`, and `SipMidSession_PartyResponse` | No | No | Stateless | POJO | Yes

== Statistics

SCCTerminatingPreAnswerSessionTransfer statistics are tracked by the sentinel.volte.sip SBB and can be found under the following parameter set in REM:
SLEE-Usage → sentinel.volte.sip service → sentinel.volte.sip SBB → feature → SCCTerminatingPreAnswerSessionTransfer
or with rhino-stats:
"SLEE-Usage.Services.ServiceID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].SbbID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].feature.SCCTerminatingPreAnswerSessionTransfer"

Name | Description
--- | ---
    Started
| Incremented each time the feature runs
    FailedToStart
| Incremented when a fatal error occurs before feature execution
    IssuedWarning
| Incremented when a non-fatal error occurs during feature execution
    FailedDuringExecution
| Incremented when a fatal error occurs during feature execution
    TimedOut
| Incremented when feature execution does not complete within a reasonable time frame
    AccessTransferSuccessful
| Incremented when the ACK to the 2xx-INVITE due to ATU-STI or STN-SR is received by the feature
    AccessTransferAborted
| Incremented when the access transfer procedures are aborted before the transfer is complete
    SentPost405Update183
| Incremented when a 183 is sent to the MSC after a 405-UPDATE is received
    SentRemoteReInvite
| Incremented when a remote reINVITE occurs
    SentRemoteUpdate
| Incremented when a remote UPDATE occurs
    SentPostUpdate183
| Incremented when a 183 is sent to the MSC following an UPDATE-200 to the originating party
    SentInfoOnNewAccessLeg
| Incremented when an INFO is sent to the MSC as part of an Access Transfer
    SentForked183Response
| Incremented when a forked 183 response follows an UPDATE-200 with different SDP sent and received
    SentImmediate183
| Incremented when an access transfer does not trigger an UPDATE to the originating party and a 183 is immediately sent to the MSC
    MaskedInviteEvent
| Incremented when the feature masks delivery of further INVITE events on the new access leg.
    UnmaskedInviteEvent
| Incremented when the feature unmasks delivery of further INVITE events on the new access leg.

== Behaviour

This feature implements SCC-AS procedures for access transfer of a terminating call in the alerting phase using PS to CS SRVCC. It includes support for media anchored in the ATGW and media non-anchored.

The behaviour is best described by reading section 12.3.4.2 in 3GPP TS 24.237. The feature implements the full text. A call flow diagram showing the media anchored case is in the Example call flow section of this page.

Removal of superfluous sessions is implemented through the SCCCoordinateSignallingAnchors and SCCRemoveSuperfluousSession features.

The following sections define additional behaviour to cover specification gaps.

=== UEs with an Allow header that does not include UPDATE

TS 24.237 specification doesn’t explicitly describe procedures at the SCC-AS for the case where a UE has specified an Allows header without including an UPDATE as the value. This feature implements behaviour as though it has received a 405-UPDATE when it receives the handover INVITE if:

1. the speech media component of the session to transfer is not equal to that in the Handover INVITE, and

2. the session to transfer has an Allows header without including UPDATE

That is, it creates a new early dialog towards the MSC using a 183 response. The 183 response includes signalling elements described in subclause 6A.4.3A. It includes an SDP answer:

1. with c-line set to the unspecified address (0.0.0.0) if IPv4 or to a domain name within the ".invalid" DNS top-level domain in case of IPv6 as described in IETF RFC 6157; and

2. including media of media types received in SDP offer of the SIP INVITE request due to STN-SR, which are also offered in the SIP INVITE request from the served user; and

=== Error responses other than 405-UPDATE

The specification does not describe behaviour for error responses other than 405-UPDATE. If a necessary SIP procedure fails due to an error response, the feature terminates:

1. the old access leg

2. the new access leg

3. the remote leg

== Example call flow

Please refer to 3GPP TS 24.237 appendix A.17.8. It is a single "successful case" for a terminating alerting access transfer where media is anchored in the ATGW.

= SCCOriginatingPreAnswerSessionTransfer :toc: macro :toclevel: 4 :toc-title: On this page…​ :sortorder: 10

This feature implements SCC-AS procedures for access transfer of an originating call in the alerting or pre-alerting phases using PS to CS SRVCC .

This page refers to SIP INVITE due to STN-SR or SIP INVITE due to ATU-STI as a "Handover INVITE".

== Feature cheat sheet

B2BUA Instance | SAS Support | Originating / Terminating | Points in Session Plan | Network Operator Data | Subscriber Data | Stateful or Stateless | POJO Feature or SBB Feature | Feature FSM
--- | --- | --- | --- | --- | --- | --- | --- | ---
SCC | Yes | Originating | `SipAccessPartyRequest`, `SipAccessPartyResponse`, and `SipMidSession_PartyResponse`. | No | No | Stateless | POJO | Yes

== Statistics

SCCOriginatingPreAnswerSessionTransfer statistics are tracked by the sentinel.volte.sip SBB and can be found under the following parameter set in REM:
SLEE-Usage → sentinel.volte.sip service → sentinel.volte.sip SBB → feature → SCCOriginatingPreAnswerSessionTransfer
or with rhino-stats:
"SLEE-Usage.Services.ServiceID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].SbbID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].feature.SCCOriginatingPreAnswerSessionTransfer"

Parameter | Type | Description
--- | --- | ---
    Started
| Counter | Incremented each time the feature runs
    FailedToStart
| Counter | Incremented when a fatal error occurs before feature execution
    IssuedWarning
| Counter | Incremented when a non-fatal error occurs during feature execution
    FailedDuringExecution
| Counter | Incremented when a fatal error occurs during feature execution
    TimedOut
| Counter | Incremented when feature execution does not complete within a reasonable time frame
    AccessTransferSuccessful
| Counter | Incremented when the ACK to the 2xx-INVITE due to ATU-STI or STN-SR is received by the feature
    AccessTransferAborted
| Counter | Incremented when access transfer procedures are aborted before the transfer is complete
    SentRemoteUpdateUsingUpdate
| Counter | Incremented when a remote update occurs using the UPDATE method (prior to 2xx-INVITE on the remote leg)
    SentRemoteUpdateUsingPrack
| Counter | Incremented when a remote update should occur prior to session establishment, but the remote UE does not support the UPDATE method
    SentRemoteUpdateUsingInvite
| Counter | Incremented when a remote update occurs using the INVITE (reINVITE) method. Post 2xx-INVITE on the remote leg.
    MaskedInviteEvent
| Counter | Incremented when the feature masks delivery of further INVITE events on the new access leg.
    UnmaskedInviteEvent
| Counter | Incremented when the feature unmasks delivery of further INVITE events on the new access leg.

== Behaviour

This feature implements SCC-AS procedures for access transfer of an originating call in the alerting or pre-alerting phases using PS to CS SRVCC. It includes support for media anchored in the ATGW and media non-anchored, forks of the remote leg, and various race conditions between processing the Handover INVITE and the remote leg answering the call.

The behaviour is best described by reading section 12.3.4.3 in 3GPP TS 24.237. The feature implements the full text. Several call flows showing different success cases are shown in the Example call flows section of this page.

Removal of superfluous sessions is implemented through the SCCCoordinateSignallingAnchors and SCCRemoveSuperfluousSession features.

The following sections define additional behaviour to cover specification gaps.

=== UEs with an Allow header that does not include UPDATE

TS 24.237 specification doesn’t explicitly describe procedures at the SCC-AS for the case where a UE has specified an Allows header without including an UPDATE as the value. This feature implements behaviour as though it has received a 405-UPDATE when it receives the handover INVITE if:

1. the speech media component of the session to transfer is not equal to that in the Handover INVITE, and

2. the session to transfer has an Allows header without including UPDATE

That is, it creates a new early dialog towards the MSC using a 183 response. The 183 response includes signalling elements described in subclause 6A.4.3A. It includes an SDP answer:

1. with c-line set to the unspecified address (0.0.0.0) if IPv4 or to a domain name within the ".invalid" DNS top-level domain in case of IPv6 as described in IETF RFC 6157; and

2. including media of media types received in SDP offer of the SIP INVITE request due to STN-SR, which are also offered in the SIP INVITE request from the served user; and

It then waits for the 2xx-INVITE from the remote leg and does not forward that on to the MSC. It initiates a re-INVITE to provide the new SDP offer to the remote UE, waits for the 2xx response and forwards it to the MSC.

=== Error responses other than 405-UPDATE

The specification does not describe behaviour for error responses other than 405-UPDATE. If a necessary SIP procedure fails due to an error response, the feature terminates:

1. the old access leg

2. the new access leg

3. the remote leg

=== Receipt of non reliable provisional responses from the remote UE

The specification does not cover the remote UE sending non-reliable provisional responses. The feature deals with this case by:

1. making all provisional responses that it sends to the MSC be reliable,

2. when it receives a PRACK from the MSC, it waits for 2xx-INVITE from the remote leg (and does not forward it onwards to the MSC. It then sends a re-INVITE with SDP from the Handover INVITE. When it receives a 2xx to the re-INVITE it forwards that onwards to the MSC.

== Call flows for session transfer of an outgoing call in the alerting phases

=== Session Transfer for an outgoing call in the alerting phase

Please refer to 3GPP TS 24.237 appendix A.17.3. It is a single "successful case" for a originating alerting access transfer where media is not anchored in the ATGW.

=== Session Transfer for an outgoing call in the alerting phase with forks

Please refer to 3GPP TS 24.237 appendix A.17.6. It is a single "successful case" for a originating alerting access transfer where media is not anchored in the ATGW. Additionally the SC UE has received several forked responses prior to access transfer.

= SCC Decode Companion Device Info :toc: macro :toclevels: 2 :toc-title: On this page…​ :sortorder: 2

This feature decodes the `X-Msw-Companion-Device` headers in a SIP request into a list of `CompanionDevice` objects in `CompanionDevices` session state field for access by other features .

== Feature Cheat Sheet

B2BUA Instance | SAS Support | Originating / Terminating | Point(s) in Session Plan | Network Operator Data | Subscriber Data | Stateful or Stateless | POJO Feature or SBB Feature | Other notes
--- | --- | --- | --- | --- | --- | --- | --- | ---
SCC | Yes | Terminating | `SCCTerm_SipAccess_SessionCheck` | No | No | Stateless | POJO |

== Session output variables

Variable name | Type | Comments
--- | --- | ---
    CompanionDevices
| List<CompanionDevice> | One entry per `X-Msw-Companion-Device` header in the triggering message.

== Statistics

SCCDecodeCompanionDeviceInfo statistics are tracked by the `SCCDecodeCompanionDeviceInfo` SBB and can be found using the parameter set `SLEE-Usage.Services.ServiceID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].SbbID[name=scc-decode-companion-device-info-feature,vendor=OpenCloud,version=3.1.0]`

Or in REM under the following parameter sets:
SLEE-Usage → Services → sentinel.volte.sip service → scc-decode-companion-device-info-feature SBB

Parameter | Type | Description
--- | --- | ---
    Started
| Counter | Incremented when the feature is invoked.
    Failed
| Counter | Incremented when a fatal error has occurred.
    SCCDecodeCompanionDeviceInfoSuccess
| Counter | Incremented when a message with `X-Msw-Companion-Device` headers has those headers decoded successfully
    SCCDecodeCompanionDeviceInfoFailure
| Counter | Incremented when there is a parsing exception while decoding a `X-Msw-Companion-Device` header
    DecodeCompanionDeviceInfoParameterDecodeError
| Counter | Incremented when a `X-Msw-Companion-Device` header has a parameter that is not supported
    DecodeCompanionDeviceInfoDeviceDecodeError
| Counter | Incremented when an inconsistency exists in the parameters

== Behaviour

If the trigger is not a SIP request, the feature fails to execute.

If there are no `X-Msw-Companion-Device` headers in the request, the feature finishes with no further processing.

Each `X-Msw-Companion-Device` header is decoded in turn and added to a list of `CompanionDevice` s.

The resulting list is saved in the `CompanionDevices` session state field.

=== Decoding

`RadioAccess` is extracted from the header.

The following parameters on the header are extracted when present

- `msisdn`

- `imei`

- `impi`

- `imsi`

- `model`

Any other parameters result in a decode error, incrementing the `DecodeCompanionDeviceInfoDeviceDecodeError` stat.

Finally the consistency of the parameters are checked, and failure results in `SCCDecodeCompanionDeviceInfoDeviceDecodeError` stat being incremented and `CompanionDevices` session state field not being set.

- `radioAccessType` must be specified

- if `radioAccessType` is `CS` or `PS_CS` then `msisdn` must also be specified.

= Service Centralisation Features :indexpage: :sortorder: 3

== GSM

Feature/Component/Service | What it does
--- | ---
ReOriginationSharedInformation | describes the information shared by components that implement reorigination for GSM and CDMA networks
SCCCamelToIMSReOriginationIN | receives a CAP trigger, stores reorigination information, and is able to forward the call such that it is routed into the IMS
SCCCamelToIMSReOriginationSIP | triggered from the I-CSCF and retrieves reorigination information; optionally it can retrieve the subscriber’s assigned S-CSCF either from a HSS or from a profile from network configuration, then acts as a B2BUA between the I-CSCF and the subscriber’s assigned S-CSCF

== CDMA

Feature/Component/Service | What it does
--- | ---
CDMA ReOrigination Service | receives CDMA OriginationRequest and AnalyzedInformation triggers, stores reorigination information, and is able to forward the call such that it is routed into the IMS
SCCCDMAReOrigination | triggered from the I-CSCF and retrieves reorigination information. It retrieves the subscriber’s assigned S-CSCF either from an HSS or from a profile from network configuration and then acts as a B2BUA between the I-CSCF and the subscriber’s assigned S-CSCF

= ReOriginationSharedInformation :toc: macro :toclevel: 4 :toc-title: On this page…​

This page describes the information shared by components that implement reorigination for GSM and CDMA networks .

For GSM networks:

- SCCCamelToIMSReOriginationIN and SCCCamelToIMSReOriginationSIP features

For CDMA networks:

- CDMA Reorigination service and SCCCDMAReOrigination feature

These components use:

- shared network operation configuration, and

- a shared Correlation RA entity for reorigination information.

== Network operator configuration

Network configuration data is stored in a JSLEE configuration profile table named `SCCCommonReOriginationConfigProfileTable`.

Attribute name | Type | Comments
--- | --- | ---
    UsePrefix
| boolean | If set to true, prepends `NetworkPrefix` to the correlation IDs returned by the Correlation RA.
    NetworkPrefix
| String | See `UsePrefix`.
    SkipHSSLookup
| boolean | This decides whether the SIP feature will do a query to the HSS for the S-CSCF address or not
    DirectRoutingURI
| String | The value to use for the address to add to the route header that will be added to the INVITE after it has been reoriginated.
    GeneratedPVNITemplate
| String | A template string for the P-Visited-Network-Information header generated in the reorigination, where `{mnc}` and `{mcc}` are replaced with the MNC and MCC respectively. IR 65 versions 12 or earlier define this to be `epc.ims.mnc{mnc}.mcc{mcc}.3gppnetwork.org`, while later versions define this as `ims.mnc{mnc}.mcc{mcc}.3gppnetwork.org`.
    PoliceOriginatingRequests
| boolean | Police incoming originating requests, and reject attempts to hijack the call. Enabled by default.

== (CAMEL Only) Visited Network ID Address List

Both the IN and SIP Reorigination features, in a GSM deployment, make use of an address list for mapping a given VLR address to a Visited Network ID. This is used as a fallback if the InitialDP does not contain suitable location information.

The SIP feature uses this address list in order to populate headers on the outgoing INVITE message. The IN feature uses the address list purely as an early failure measure. It checks that there exists a matching Visited Network ID for the VLR address; this prevents network resources from being wasted establishing a SIP dialog that will ultimately fail at the SIP Reorigination feature anyway.

| Currently, we require that the VLR address’s nature is `International` and its numbering plan is `ISDN`.

There are two profile tables associated with this address list:

- <PlatformOperatorName>_SCCReorigination_AddressListConfigurationTable

- <PlatformOperatorName>_SCCReorigination_AddressListEntryTable

The configuration table is a standard address list configuration table, see Address List Configuration Profile for more information. The list entry table is an extended version of the standard address list entry table (details here: Address List Entry Profile) with one additional field, a String called VisitedNetworkId. Profiles in this table must use a standard format for their names, made up of three fields: the Sentinel Selection Key, a fixed String `VisitedNetworks`, and the VLR address prefix to be matched when searching for a Visited Network ID. The name should be formatted like this:

- <SelectionKey>:VisitedNetworks:<AddressPrefix>

Here’s an example:

- OpenCloud:OpenCloud::::VisitedNetworks:6421

See the respective behaviour sections of the IN and SIP Reorigination feature pages for details on how each feature uses the address list.

For an overview of how address lists work in general, see: Address Lists.

| We recommend that the visited network is formatted according to GSMA IR.65 section 6.2.1. I.e. is of the format epc.ims.mnc<MNC>.mcc<MCC>.3gppnetwork.org or ims.mnc<MNC>.mcc<MCC>.3gppnetwork.org, depending on the version used

== Use of the Correlation RA

The IN feature/CDMA reorigination service and their SIP counterparts share (and communicate) correlation information through the Correlation RA. The resource adaptor entity used has the resource-adaptor-entity-link name `sentinel-correlation-reorigination`.

| See Correlation Resource Adaptor for more information about the correlation RA.

The reorigination addresses allocated by the Correlation RA must route through to the IMS, and allow the I-CSCF to trigger the SCC-AS. Typically this is done by configuring a range of numbers that correspond to one or more IMS public service identifiers.

The sentinel-correlation-reorigination RA entity has one or more correlation ID pools.

1. a default ID pool (optional)

2. a set of named ID pools.

=== Choosing the Correlation ID Pool

Each named ID pool is identified by the NodeID and a set of prefixes for choosing/selecting the ID pool. From the Correlation RA standpoint, the prefixes can be any address string. The client to the RA provides an address that the RA uses:

In GSM Volte, the IN reorigination feature uses the `MobileCountryCode` extracted from `LocationInformation` in the triggering `InitialDP`

In CDMA Volte, the CDMA reorigination service uses the `LocationAreaID` extracted from the `OriginationRequest` or `AnalyzedInformation`

The Correlation RA performs a longestPrefix match address list search on pools with a matching NodeID for the current node. If no pool is matched by the search or no address is provided by the client to the RA, then the default pool is selected. If multiple pools match the longestPrefix address list search, the first pool in the result set is selected.

== Reorigination basic flow

The following diagrams cover some basic reorigination scenarios for GSM and CDMA networks.

=== GSM Reorigination Scenario 1

In the following diagram:

- Sentinel VoLTE acts as the SCC-AS.

- The “IN feature” is the SCCCamelToIMSReOriginationIN feature.

- The “SIP feature” is the SCCCamelToIMSReOriginationSIP feature.

- The User-Data-Request and Answer will not occur if the SkipHSSLookup flag is set to true and instead the value in the DirectRoutingURI will be used.

This flow diagram shows a configuration where the SkipHSSLookup flag is set to false, so that the SCC-AS looks up the HSS and acts as a B2BUA between the I-CSCF and the S-CSCF after B number restoration.

=== GSM Reorigination Scenario 2

As a variation to the above diagram, the following shows the effect of configuring:

1. SkipHSSLookup flag set to true

2. DirectRoutingURI set to the I-CSCF

=== CDMA Reorigination Scenario

In the following diagram:

- Sentinel VoLTE acts as the SCC-AS.

- The “CDMA Service” is the CDMA ReOrigination service.

- The “SIP feature” is the SCCCDMAReOrigination feature.

- The User-Data-Request and Answer will not occur if the SkipHSSLookup flag is set to true and instead the value in the DirectRoutingURI will be used.

This flow diagram shows a configuration where:

1. SkipHSSLookup flag set to true

2. DirectRoutingURI set to the I-CSCF

For further information related to headers set in the outgoing SIP INVITE, please refer to SIP headers in the outgoing INVITE.

= SCCCDMAReOrigination :toc: macro :toclevel: 5 :toc-title: On this page…​

| This feature is for CDMA networks.

This feature is triggered from the I-CSCF and retrieves reorigination information. It retrieves the subscriber’s assigned S-CSCF either from an HSS or from a profile from network configuration and then acts as a B2BUA between the I-CSCF and the subscriber’s assigned S-CSCF .

It is one of two components that enable circuit switched originating calls to be processed in the SCC-AS. The related component is the CDMA ReOrigination Service. These components are part of service centralization in the IMS for CDMA networks.

| For this feature’s fit into the overall flow, please see the Reorigination basic flow diagram.

== Relevant specifications

- 3GPP2 X.S0042-D v1.0

- GSMA IR.64.

== Feature cheat sheet

B2BUA Instance | Originating / Terminating | Point in Session Plan | Network Operator Data | Subscriber Data | Stateful or Stateless | POJO Feature or SBB Feature
--- | --- | --- | --- | --- | --- | ---
SCC signalling anchor B2BUA | From SIP triggering perspective, neither. Mobile Originating and Mobile Terminating determined from saved CDMA OriginationRequest or CDMA AnalyzedInformation |
    SipAccess_SessionAccept
| Yes | No | Stateless | Triggered by the I-CSCF

== Network operator data

Common network configuration data is stored in a profile table named `SCCCommonReOriginationConfigProfileTable`.

For more information, see the shared configuration between the SCCCDMAReOrigination feature and the CDMA reorigination service.

== Use of Correlation resource adaptor

For information about use of the Correlation RA, please see the shared Correlation RA.

== Session output variables

Variable name | Type | Comment
--- | --- | ---
    Reoriginated
| Boolean | Set to `true` if the feature finds reorigination data

== Statistics

SCCCDMAReOrigination statistics are tracked by the sentinel.volte.sip SBB and can be found under the following parameter set:
SLEE-Usage → sentinel.volte.sip service → sentinel.volte.sip SBB → feature → SCCCDMAReOrigination

Statistic | Incremented when…​
--- | ---
Complete | The feature ran to completion
MultipleHistoryInfoHeadersFound | Multiple history-info headers found on the INVITE
NoHistoryInfoHeaderFound | No history-info header found on the INVITE
OneHistoryInfoHeaderFoundAndRemoved | One history-info header found on the INVITE and removed
HSSLookupFailed | HSS lookup failed
HSSLookupSuccess | HSS lookup succeeded
HSSLookupSkipped | HSS lookup was skipped due to SkipHSSLookup feature configuration flag
CorrelationRaQueried | Correlation RA was queried for the call information
CorrelationRaQuerySuccess | The Correlation RA query succeeded
CorrelationRaQueryFailure | The Correlation RA query failed
FailedToDecodeCorrelationData | Failed to decode the correlation data into an OriginationRequest or AnalyzedInformation object
SetOCBillingIdHeader | Added a OCBillingId header with the BillingID from the OriginationRequest or AnalyzedInformation
CalledPartyNumberNotFound | Failed to determine the called party from parameters of the OriginationRequest or AnalyzedInformation
SCSCFAddressNotFound | The SCSCF could not be found in configuration, or retrieved from the HSS
CallingPartyAndPaiDoNotMatch | The request is rejected because of a mismatch between calling party and P-Asserted-Identity
Started | The feature starts
FailedToStart | The feature failed to start due to an error
IssuedWarning | The feature raised a warning
FailedDuringExecution | The feature failed due to a major error
TimedOut | The feature timed out during execution

== Behaviour

The feature is triggered on receipt of a SIP `INVITE` from the I-CSCF.

It checks for network operator data. If not present, the feature informs Sentinel that it failed to execute due to invalid configuration.

It looks at the received `INVITE` Request URI, and checks that it represents a phone number.

If the network configuration indicates a prefix is in use, it checks that the request URI’s digits start with that prefix. If not, the feature finishes execution without modifying any state. In other words, this is treated as an `INVITE` that is not for this feature.

The feature then attempts to retrieve the correlation data that was stored by the CDMA reorigination service. This data is looked up using the request URI’s digits as the key for the correlation data.

If correlation data is not found, the feature finishes execution without modifying any state.

If a P-Asserted-Identity header is present on the incoming INVITE, and a phone number can be extracted from it, it is normalised and compared to the (normalised) calling party number extracted from the ORREQ or ANLYZD. If they are different, the request is rejected with a 403 response. This functionally can be disabled using the `PoliceOriginatingRequests` configuration flag.

Next, the feature then retrieves the S-CSCF name for the calling party from either of two places based on the SkipHSSLookup flag:

Flag Value | Effect
--- | ---
`TRUE` | Use the value in DirectRoutingURI from network configuration.
`FALSE` | Do a lookup from the HSS through the Sh Cache Microservice RA and the Sh Cache Microservice.

The feature then adjusts or sets various headers in the outgoing `INVITE`.

Finally, the Sentinel SIP instance hosting this feature acts as a B2BUA between the I-CSCF and the S-CSCF.

=== SIP headers in the outgoing INVITE

The feature sets or adjusts the following headers in the outgoing `INVITE`:

Header Name | Change
--- | ---
`Request-URI` | Set to a tel URI with the digits being the original IDP’s called party number digit string (non-BCD encoded).
`To` | Set to the original IDP’s called party number digit string (non-BCD encoded).
`History-Info` | If only one such header exists on the `INVITE`, it is removed.
`P-Asserted-Identity` | If it is not present in the `INVITE` it is set to a tel URI using the calling party number from the original IDP.
`Privacy` | Set to `ONLY_IDENTITY` if the original IDP has presentation `RESTRICTED` or `NETWORK_RESTRICTED`.
`Route` | A new route to the S-CSCF for the served user is added, if the feature was invoked on an originating trigger an `orig` parameter will be included.
`OC-Billing-ID` | The `BillingID` from the OriginationRequest or AnalyzedInformation.
`P-Profile-Key` | If such header exists in the `INVITE`, it is removed.

| The `OC-Billing-ID` is a proprietary header created by OpenCloud. The `OC-Billing-ID` header is added so the original CDMA request can be correlated with the ongoing SIP session when it reaches MMTel.

= SCCCamelToIMSReOriginationIN :toc: macro :toclevel: 4 :toc-title: On this page…​

This feature receives a CAP trigger, stores reorigination information, and is able to forward the call such that it is routed into the IMS .

It enables processing circuit-switched originating calls in the SCC-AS.

Reorigination for terminating calls can be bypassed if the subscriber is not registered in the IMS network.

The related feature is SCCCamelToIMSReOriginationSIP; these features are part of service centralization in the IMS. For this feature’s fit into the overall flow, please see the Reorigination basic flow diagram.

== Relevant specifications

- 3GPP TS 23.292 and 24.292

- GSMA IR.64.

== Feature cheat sheet

B2BUA Instance | SAS Support | Originating / Terminating | Point in Session Plan | Network Operator Data | Subscriber Data | Stateful or Stateless | POJO Feature or SBB Feature
--- | --- | --- | --- | --- | --- | --- | ---
This feature is IN only, it does not exist in a SIP B2BUA | Yes | Mobile Originating and Mobile Terminating only |
    Session_PreInitialCreditCheck
| Yes. See Correlation RA | No | Stateless | 1 POJO for IN behaviour

== Network operator data

Common network configuration data is stored in a profile table named `SCCCommonReOriginationConfigProfileTable`.

For more information, see the shared configuration between the SCCCamelToIMSReOriginationSIP feature and the SCCCamelToIMSReOriginationIN feature.

Camel specific network configuration is stored in a profile table name `SCCCamelToIMSReOriginationConfigProfileTable`. This data is scoped by Sentinel selection key.

Attribute name | Type | Comments
--- | --- | ---
    RoutingToInternalNetworkNumber
| An enum. See RoutingToInternalNetworkNumber | Used by the IN feature when forwarding the call. For allowed values, see RoutingToInternalNetworkNumber
    Nature
| An enum. See Nature | Used by the IN feature when forwarding the call. For allowed values see Nature.
    NumberingPlan
| An enum. See NumberingPlan | Used by the IN feature when forwarding the call. For allowed values see NumberingPlan
    BypassTermReorIfNotRegistered
| Boolean | Used by the IN feature. If true, reorigination is skipped if the subscriber is not registered in the IMS network.

=== RoutingToInternalNetworkNumber

This value is part of the CAP and ETSI INAP CalledPartyNumber.

The allowed values are:

- `ALLOWED`

- `NOT_ALLOWED`

The values are as if the type were specified in ASN.1 as follows:

    RoutingToInternalNetworkNumber ::= ENUMERATED {
         ALLOWED     (0),
         NOT_ALLOWED (1)
     }

For more information, please see CGIN.

=== Nature

This value is part of the CAP and ETSI INAP CalledPartyNumber. The allowed values are:

- `SUBSCRIBER`

- `UNKNOWN`

- `NATIONAL`

- `INTERNATIONAL`

- `NETWORK_SPECIFIC`

- `NETWORK_ROUTING_NATIONAL`

- `NETWORK_ROUTING_NETWORK_SPECIFIC`

- `NETWORK_ROUTING_WITH_CALLED_DIRECTORY`

The values are as if the type were specified in ASN.1 as follows:

    Nature ::= ENUMERATED {
         ... ,
         SUBSCRIBER                            (1),
         UNKNOWN                               (2),
         NATIONAL                              (3),
         INTERNATIONAL                         (4),
         NETWORK_SPECIFIC                      (5),
         NETWORK_ROUTING_NATIONAL              (6),
         NETWORK_ROUTING_NETWORK_SPECIFIC      (7),
         NETWORK_ROUTING_WITH_CALLED_DIRECTORY (8),
         ...
     }

For more information, please see CGIN.

=== NumberingPlan

This value is part of the CAP and ETSI INAP CalledPartyNumber.

The allowed values are:

- `SPARE_0`

- `ISDN`

- `SPARE_2`

- `DATA`

- `TELEX`

- `NATIONAL_5`

- `NATIONAL_6`

- `SPARE_7`

The values are as if the type were specified in ASN.1 as follows:

    NumberingPlan ::= ENUMERATED {
         SPARE_0      (0),
         ISDN         (1),
         SPARE_2      (2),
         DATA         (3),
         TELEX        (4),
         NATIONAL_5   (5),
         NATIONAL_6   (6),
         SPARE_7      (7)
     }

For more information, please see CGIN.

== Use of Correlation resource adaptor

For information about use of the Correlation RA, please see the shared Correlation RA.

== Session input and output variables

=== Session input variables

Attribute Name | Type
--- | ---
    InitialDPArg
| an implementation of `com.opencloud.slee.resources.cgin.callcontrol.CCInitialDPArg`

=== Session output variables

Attribute Name | Type
--- | ---
    CCConnectArg
| an implementation of `com.opencloud.slee.resources.cgin.callcontrol.CCConnectArg`

== Statistics

SCCCamelToIMSReOriginationIN statistics are tracked by the sentinel.volte.ss7 SBB and can be found under the following parameter set:
SLEE-Usage → sentinel.volte.ss7 service → sentinel.volte.ss7 SBB → feature → SCCCamelToIMSReOriginationIN

Parameter | Type | Description
--- | --- | ---
    Started
| Counter | Incremented when the feature starts.
    FailedToStart
| Counter | Incremented when the feature failed to start due to an error.
    IssuedWarning
| Counter | Incremented when the feature raised a warning.
    FailedDuringExecution
| Counter | Incremented when the feature failed due to a major error.
    TimedOut
| Counter | Incremented when the feature timed out during execution.
    CallReOriginated
| Counter | Incremented when the call is successfully reoriginated.
    CallReleased
| Counter | Incremented when reorigination fails and the call is released.
    Misconfigured
| Counter | Incremented when the feature has not been correctly configured.
    IdpVlrNumberPresent
| Counter | Incremented when the VLR number is found in the incoming InitialDP.
    IdpVlrNumberNotPresent
| Counter | Incremented when the VLR number is not found in the incoming InitialDP.
    VisitedNetworkIdNotFound
| Counter | Incremented when the feature is unable to determine the Visited Network ID.
    VisitedNetworkIdFound
| Counter | Incremented when the feature is able to determine the Visited Network ID based on the VLR address.
    PoolAllocationFailed
| Counter | Incremented when the feature fails to acquire a correlation ID from the correlation RA.
    PoolAllocationSucceeded
| Counter | Incremented when the feature acquires a correlation ID from the correlation RA.
    OriginatingIMRNAttempt
| Counter | Incremented when the feature executes reorigination for an originating call leg.
    TerminatingIMRNAttempt
| Counter | Incremented when the feature executes reorigination for a terminating call leg.
    ReoriginationBypassed
| Counter | Incremented when the feature bypasses reorigination for an unregistered subscriber.

== Behaviour

The feature is triggered with an Initial DP. If the call type is not Mobile Originating or Mobile Terminating, the feature finishes execution without modifying any state.

The feature checks if the Initial DP is a CAMEL initial DP. If not, it finishes executing without modifying any state.

It then checks network configuration, and if not present it informs Sentinel that it failed to execute, with an invalid configuration cause. It then finishes execution.

Once configuration is loaded, it attempts to reoriginate the call (that is, forward the call into the IMS). This works as per the reorigination section.

If `BypassTermReorIfNotRegistered` = `True`, the feature performs a subcriber lookup in Cassandra using the IMSIDLookupFromCassandraIN feature. If the subscriber is not registered or the registration has expired, then an empty continue request is returned to the MSC and the feature exits. If `BypassTermReorIfNotRegistered` = `False`, or the subcriber lookup in Cassandra returns a current registration record, then reorigination is attempted.

=== Reoriginating the call

The IDP is checked for the presence of the `CalledPartyBCDNumber`. If not present, the call is treated as per the Failure to reoriginate section.

Following that, the feature uses the Visited Network ID Address List to check that there is a known Visited Network ID for the VLR address present in the IDP location information. If there is a matching ID, the feature will continue processing as normal. If there is no matching ID the feature will terminate the call as per the Failure to reoriginate section. The purpose of this is to avoid wasting resources establishing the SIP side of the call, only to have it fail when the SIP reorigination feature is unable to find a matching Visited Network ID.

The feature then consults the Correlation resource adaptor entity in order to allocate a reorigination address. This is an address that is used for routing the call onwards. The Correlation resource adaptor entity stores both the correlation number allocation, and the key fields of the CAP Initial DP argument. These are used later, in the SIP feature.

The feature then builds a destination routing address, using the address returned by the Correlation RA, and the network configuration for the address’s `Nature`, `RoutingToInternalNetworkNumber`, and `NumberingPlan` fields. The network configuration for a prefix is used if the network configuration indicates a prefix is required. This address is called the “IP Multimedia Routing Number”, or IMRN for short.

It then creates a new `Connect` operation, using the IMRN in the Destination Routing Address field, and requests sending of the `Connect` and a close of the TCAP dialog.

If | Then
--- | ---
there are any problems with any of: allocation of a reorigination address saving state in the correlation RA building the connect operation | the call is treated according to Failure to reoriginate and a `ReleaseCall` instruction is sent back to the MSC.

==== Failure to reoriginate

Failure to reoriginate the call results in a `ReleaseCall` instruction being sent back to the MSC.

= SCCCamelToIMSReOriginationSIP :toc: macro :toclevel: 4 :toc-title: On this page…​

This feature is triggered from the I-CSCF and retrieves reorigination information; optionally it can retrieve the subscriber’s assigned S-CSCF either from a HSS or from a profile from network configuration, then acts as a B2BUA between the I-CSCF and the subscriber’s assigned S-CSCF .

It is one of two features that enable circuit switched originating calls to be processed in the SCC-AS. The related feature is SCCCamelToIMSReOriginationIN. These features are part of service centralization in the IMS.

| For this feature’s fit into the overall flow, please see the Reorigination basic flow diagram.

== Relevant specifications

- 3GPP TS 23.292 and 24.292

- GSMA IR.64.

== Feature cheat sheet

B2BUA Instance | SAS Support | Originating / Terminating | Point in Session Plan | Network Operator Data | Subscriber Data | Stateful or Stateless | POJO Feature or SBB Feature
--- | --- | --- | --- | --- | --- | --- | ---
SCC signalling anchor B2BUA | Yes | From SIP triggering perspective, neither. Mobile Originating and Mobile Terminating determined from saved CAMEL InitialDP (IDP) |
    SipAccess_SessionAccept
| Yes | No | Stateless | Triggered by the I-CSCF

== Network operator data

Common network configuration data is stored in a profile table named `SCCCommonReOriginationConfigProfileTable`.

For more information, see the shared configuration between the SCCCamelToIMSReOriginationSIP feature and the SCCCamelToIMSReOriginationIN feature.

== Use of Correlation resource adaptor

For information about use of the Correlation RA, please see the shared Correlation RA..

== Session output variables

Variable name | Type | Comment
--- | --- | ---
    Reoriginated
| Boolean | Set to `true` if the feature finds reorigination data

== Statistics

SCCCamelToIMSReOriginationSIP statistics are tracked by the volte.sentinel.sip SBB and can be found under the following parameter set:
SLEE-Usage → volte.sentinel.sip service → volte.sentinel.sip SBB → feature → SCCCamelToIMSReOriginationSIP

Statistic | Incremented when…​
--- | ---
Complete | The feature ran to completion
MultipleHistoryInfoHeadersFound | Multiple history-info headers found on the INVITE
NoHistoryInfoHeaderFound | no history-info header found on the INVITE
OneHistoryInfoHeaderFoundAndRemoved | One history-info header found on the INVITE and removed
HSSLookupFailed | HSS lookup failed
HSSLookupSuccess | HSS lookup succeeded
HSSLookupSkipped | HSS lookup was skipped due to SkipHSSLookup feature configuration flag
CorrelationRaQueried | Correlation RA was queried for the call information
CorrelationRaQuerySuccess | The Correlation RA query succeeded
CorrelationRaQueryFailure | The Correlation RA query failed
IdpVlrNumberPresent | The VLR number is present in the initial IDP
IdpVlrNumberNotPresent | The VLR number is not present in the initial IDP
VisitedNetworkIdFound | The feature could set the Visited Network Id based on the Location information or on the VLR address
VisitedNetworkIdNotFound | The feature could set the Visited Network Id
IdpCalledPartyNumberPresent | The initial IDP has a called party number or called party BCD number
IdpCalledPartyNumberNotPresent | The initial IDP does not have a called party number or called party BCD number
SCSCFAddressNotFound | The SCSCF could not be found in configuration, or retrieved from the HSS
AccessNetworkInfoFound | AccessNetworkInfo was found in the original InitialDP
AccessNetworkInfoNotFound | AccessNetworkInfo could not be found in the original InitialDP
CallingPartyAndPaiDoNotMatch | The request is rejected because of a mismatch between calling party and P-Asserted-Identity
Started | The feature starts
FailedToStart | The feature failed to start due to an error
IssuedWarning | The feature raised a warning
FailedDuringExecution | The feature failed due to a major error
TimedOut | The feature timed out during execution

== Behaviour

The feature is triggered on receipt of a SIP `INVITE` or a SIP `UPDATE` from the I-CSCF. The majority of this feature’s functionality is reserved for the `INVITE` request.

It checks for network operator data. If not present, the feature informs Sentinel that it failed to execute due to invalid configuration.

=== For a received `INVITE` request, the following is executed:

It looks at the received `INVITE` Request URI, and checks that it represents a phone number.

If the network configuration indicates a prefix is in use, it checks that the request URI’s digits start with that prefix. If not, the feature finishes execution without modifying any state. In other words, this is treated as an `INVITE` that is not for this feature.

The feature then attempts to retrieve the correlation data that was stored by the IN feature. This data is looked up using the request URI’s digits as the key for the correlation data.

If correlation data is not found, the feature finishes execution without modifying any state.

If correlation data is found, the feature tries to extract the Mobile Country Code and the Mobile Network Code from the Cell Global Id or Location Area Id present in the Location Information section of the Initial IDP. If a MCC and MNC is found, a Visited Network Id is created using the GeneratedPVNITemplate in the common configuration. It is recommended that this is set according to IR.65, section 6.2.1 i.e. that the format for this is `epc.ims.mnc<MNC>.mcc<MCC>.3gppnetwork.org` if the version followed is 12 or less, or `ims.mnc<MNC>.mcc<MCC>.3gppnetwork.org` if a later version is used.

In the case of originating Initial DP arguments, if a MCC and MNC is found, and the Initial DP includes a Cell Global ID with a Location Area Code, the `P-Access-Network-Info` header is set to the form `3GPP-GERAN;cgi=3gpp=<mcc><mnc><location area code><cellId>`. This header is saved in the session state to correct future outgoing `UPDATE` requests in the session.

If MCC or MNC is not present, the feature uses the Visited Network ID Address List to find the Visited Network ID for the VLR address in the data. If a matching Visited Network ID is found, it is included in a header in the outgoing SIP request. If no matching ID is found then reorigination will be aborted. In practice this should never happen, as the IN reorigination feature performs this check as well and will terminate reorigination before any SIP signalling occurs if no Visited Network ID is found.

If a P-Asserted-Identity header is present on the incoming INVITE, and a phone number can be extracted from it, it is normalised and compared to the (normalised) calling party number from the InitialDP. If they are different, the request is rejected with a 403 response. This functionally can be disabled using the `PoliceOriginatingRequests` configuration flag.

Next, the feature then retrieves the S-CSCF name for the calling party from either of two places based on the SkipHSSLookup flag:

Flag Value | Effect
--- | ---
`TRUE` | Use the value in DirectRoutingURI from network configuration.
`FALSE` | Do a lookup from the HSS through the Sh Cache Microservice RA and Sh Cache Microservice.

The feature then adjusts or sets various headers in the outgoing `INVITE`.

Finally, the SIP Sentinel instance hosting this feature acts as a B2BUA between the I-CSCF and the S-CSCF.

=== For a received `UPDATE` request, the following is executed:

The `P-Access-Network-Info` header that was generated by the `INVITE` request is set on the `UPDATE` request. The other headers on the outgoing `UPDATE` request are unchanged.

Finally, the SIP Sentinel instance hosting this feature acts as a B2BUA between the I-CSCF and the S-CSCF.

=== SIP headers in the outgoing INVITE

The feature sets or adjusts the following headers in the outgoing `INVITE`:

Header Name | Change
--- | ---
`Request-URI` | Set to a tel URI with the digits being the original IDP’s called party number digit string (non-BCD encoded).
`To` | Set to the original IDP’s called party number digit string (non-BCD encoded).
`History-Info` | If only one such header exists on the `INVITE`, it is removed.
`P-Asserted-Identity` | If it is not present in the `INVITE` it is set to a tel URI using the calling party number from the original IDP.
`Privacy` | Set to `id` if the original IDP `CallingPartyNumber` presentation parameter value is `RESTRICTED` or `NETWORK_RESTRICTED`.
`Route` | A new route to the S-CSCF for the served user is added, if the feature was invoked on an originating trigger an `orig` parameter will be included.
`P-Access-Network-Info` | In case of originating Initial DP argument containing suitable location information, the feature sets this header in the form of `3GPP-GERAN;cgi=3gpp=<mcc><mnc><location area code><cellId>`
`P-Visited-Network-Info` | Set to a Visited Network ID if the feature was invoked on an originating trigger.
`OC-Term-P-Visited-Network` | Set to a Visited Network ID if the feature was invoked on an terminating trigger.
`OC-VLR-Number` | Set to the VLR address from the correlation data as a VLR Number address in a string.
`P-Profile-Key` | If such header exists in the `INVITE`, it is removed.

| The `OC-Term-P-Visited-Network` and `OC-VLR-Number` are proprietary headers created by OpenCloud.

==== Formatting of the P-Access-Network-Info header

The encoding follows 3GPP TS 24.229, in particular section '7.2A.4.3 Additional coding rules for P-Access-Network-Info header', which states:

The Cell Global Identity is a concatenation of MCC, MNC, LAC and CI …​ The value of "cgi-3gpp" parameter is therefore coded as a text string as follows: Starting with the most significant bit, MCC (3 digits), MNC (2 or 3 digits depending on MCC value), LAC (fixed length code of 16 bits using full hexadecimal representation) and CI (fixed length code of 16 bits using a full hexadecimal representation).

==== Formatting of the OC-VLR-Number header

The `OC-VLR-Number` header value is built by:

- retrieving the VLR address in the original InitialDP

- converting the SCCP address into an ascii string, formatted according to SS7’s AddressStringParser

- setting resulting the string into the SIP header value

The resulting complete header will be `OC-VLR-Number: address=651232343,nature=INTERNATIONAL,numberingPlan=ISDN`

==== Formatting of the OC-Term-P-Visited-Network header

This header has the same format as a P-Visited-Network-Info header.

= Terminating Access Domain Selection Features :indexpage: :sortorder: 4

For an overview of Terminating Access Domain Selection (T-ADS) see Terminating Access Domain Selection (T-ADS).

T-ADS features implement the routing strategy for a terminating call. It provides support for route signaling towards PS and CS domains, in a sequential, parallel or exclusive manner.

Sequential routing attempts to route towards a single preferred domain, and "falls back" to the non-preferred domain upon receipt of certain responses.

Parallel routing routes towards the PS and CS domains simultaneously. It decides the "chosen" domain based on responses that it receives.

The conditions for routing to PS and CS are checked by the SCCTADSDataLookup feature.

Feature | What it does
--- | ---
SCCTADSDataLookup | T-ADS Data Lookup gathers information from the received SIP signalling, and optionally queries the HSS, in order to determine available PS and CS routes that can be used to deliver the call to the served user.
SCCTADSDetermineCircuitRoutes | is used to populate the session state `TADSCircuitRoutes` with the primary and companion device CS routes.
SCCTADSRouting | It takes the T-ADS preferred routing decision from SCCTADSDataLookup, and uses it to attempt routing.
SCCTADSParallelRouting | The T-ADS Parallel Routing feature parallel-forks the incoming message to both CS and PS legs, and forwards the response from the leg that successfully responds first
FetchCMSISDN | Retrieves the Correlation MSISDN (C-MSISDN) from the HSS by using the "Sh-Pull" operation
FetchMSRN | Retrieves the Mobile Station Roaming Number (MSRN) from the HLR by using MAP "Send Routing Information" operation
CDMAFetchTLDN | Retrieves the Temporary Local Directory Number (TLDN) from the HLR by using the MAP "Location Request" operation
DetermineLocationFromMSRN | determines the two-letter ISO Country Code for a subscriber’s location, based on their MSRN.

== Additional Reference Pages

The following pages also have data relevant to T-ADS

Page | Description
--- | ---
Custom Headers | Provides information about the custom headers and header parameters, that influence system behaviour.

= SCCTADSDataLookup :toc: macro :toclevels: 4 :toc-title: On this page…​ :sortorder: 1

T-ADS Data Lookup gathers information from the received SIP signalling, and optionally queries the HSS, in order to determine available PS and CS routes that can be used to deliver the call to the served user.

All valid routes to PS and CS domains are written into session state. This information is then read by the appropriate T-ADS Routing feature, either SCCTADSRouting (for sequential routing) or SCCTADSParallelRouting (for parallel routing).

== Feature Cheat Sheet

B2BUA Instance | SAS Support | Originating / Terminating | Point(s) in Session Plan | Network Operator Data | Subscriber Data | Stateful or Stateless | POJO Feature or SBB Feature | Other notes
--- | --- | --- | --- | --- | --- | --- | --- | ---
SCC | Yes | Terminating | `SipAccess_SubscriberCheck` | Yes | No | Stateless | SBB |

== Prerequisite Features

- Determine Call Type

- SIP Subscriber Determination Feature

- DetermineVoLTEPlanID

- One of the following based on system configuration

  - IMSIDLookup

  - IMSIDLookupFromCassandraSIP

- FetchCMSISDN

== Session Input Variables

Session state variable name | Type | Comments
--- | --- | ---
    CallType
| CallType (Enum) | The call-type for the incoming call (e.g. MobileTerminating).
    RoutingMode
| TADSRoutingMode (Enum) | Determines whether CS and/or PS routing is enabled and the preferred attempt order.
    IsLoggedIn
| boolean | Set to true when the served user is currently logged in to the IMS.
    RegistrationRecords
| List<RegistrationRecord> | This contains all of the current registration information for the served user.
    CMSISDN
| String | A string set to a non-null value if there is a C-MSISDN provisioned for the user, and if the user is logged in; if the user is not logged in.
    Subscriber
| String | The subscriber’s identity.
    SentinelSelectionKey
| SentinelSelectionKey | Used to acquire configuration information.
    CompanionDevices
| List<CompanionDevice> | This contains companion information including SharedSip, SharedTel identities and devices.

== Session Output Variables

Session state variable name | Type | Comments
--- | --- | ---
    BlindPSRouting
| boolean | Indicates whether blind PS routing is permitted.
    RoutingMode
| TADSRoutingMode (Enum) | The routing strategy to be used by the T-ADS routing features.
    TADSSipInstanceRoutingPossible
| boolean | Indicates whether T-ADS sip.instance routing is possible for the served user.
    TADSCircuitRoutes
| Queue<String> | Contains all valid CS domain routes (CSRNs) that the feature has calculated
    TADSPacketRoutes
| Queue<RouteAndTerminatingDomain> | Contains all valid PS domain routes that the feature has found along with the network type for each route.
    PSTerminatingDomainHeaderValue
| String | The value inserted into `OC-Terminating-Domain` header e.g. 'PS'.
    TADSCircuitRoutesPending
| boolean | Used by SCC routing features to indicate if there are any further CS routes left in the queue.
    TADSEndSessionWhenNoValidRouteFound
| boolean | Indicates to the SCCTADSDetermineCircuitRoutes feature that no route was found.
    TADSEndSessionErrorCode
| int | SIP response code used by SCCTADSDetermineCircuitRoutes feature when releasing the session.

== Network Operator Data

T-ADS Data Lookup has network operator data in a JSLEE profile table named `SCCTADSDataLookUpConfigProfileTable` and also `SCCTADSNetworkTypeConfigProfileTable`. The data is scoped by Sentinel selection key.

=== SCCTADSDataLookUpConfigProfileTable

Attribute | Type | Meaning
--- | --- | ---
    ForceSipUserEqualsPhone
| boolean | If true, when attempting to extract a CS routable number from a SIP URI, the feature will proceed even if the URI does not have the `user=phone` parameter.
    VoiceOverPSSupportRequired
| boolean | If true, the HSS must be queried for voice over PS support as part of the decision to attempt to route via PS.
    RequestUserIdentityType
| TADSRequestIdentities (Enum) | Specifies which identities will be used for the voice over PS support request to the HSS.
    EnableSipInstanceRouting
| boolean | Determines whether the feature should attempt to use +sip.instance routing to calculate PS routes.
    EndSessionWhenNoValidRouteFound
| boolean | Will cause the feature to refuse an incoming `INVITE` with the response code from `EndSessionErrorCode` if no valid routes can be found.
    EndSessionErrorCode
| int | The response code used when ending the session.
    UsePathForSipInstanceRouting
| boolean | If true, Path information from the REGISTER should be used for routing. This applies to devices that don’t have GRUU support.
    EnableCompanionSipInstanceRouting
| boolean | If true, T-ADS will override `EnableSipInstanceRouting` flag and route to sip.instance addresses rather than public ID’s in calls with companion devices.

=== SCCTADSNetworkTypeConfigProfileTable

Attributes | Type | Meaning
--- | --- | ---
    NetworkType
| String | Either the RAT value or the Network Access Type value.
    TerminatingDomain
| String | The value used to populate the OC-Terminating-Domain Header when processing a response from a network of this type
    Description
| String | A text field for a description.

The `SCCTADSNetworkTypeConfigProfileTable` has multiple profiles, each one being either a RAT value or Network Access Type that will be checked to determine if a call can proceed on the PS network.

Each profile includes a `TerminatingDomain` value that T-ADS Data Lookup uses this value to populate the `PSTerminatingDomainHeaderValue` session state variable. The T-ADS Routing features use this to send information about the terminating access domain to upstream network nodes as described here.

The system comes with some default profiles pre-configured as follows, Where `${platform.operator.name}` will be substituted with the value used on installation.

Profile Name | Network Type | TerminatingDomain | Description
--- | --- | --- | ---
    ${platform.operator.name}:::::1004
| 1004 | PS=EUTRAN | RAT value 1004 = E-UTRAN from TS 29.212 section 5.3.31
    ${platform.operator.name}:::::3GPP-E-UTRAN
| 3GPP-E-UTRAN | PS=EUTRAN | P-Access-Network-Info value from TS 24.229 section 7.2A.4
    ${platform.operator.name}:::::3GPP-E-UTRAN-FDD
| 3GPP-E-UTRAN-FDD | PS=EUTRAN | P-Access-Network-Info value from TS 24.229 section 7.2A.4
    ${platform.operator.name}:::::3GPP-E-UTRAN-TDD
| 3GPP-E-UTRAN-TDD | PS=EUTRAN | P-Access-Network-Info value from TS 24.229 section 7.2A.4

Additionally if WLAN is chosen as part of the installation for allowed access types, the following entries will also be present in the profile table.

Profile Name | Network Type | TerminatingDomain | Description
--- | --- | --- | ---
    ${platform.operator.name}:::::0
| 0 | PS=WLAN | RAT value 0 = WLAN from TS 29.212 section 5.3.31
    ${platform.operator.name}:::::3GPP-WLAN
| 3GPP-WLAN | PS=WLAN | P-Access-Network-Info value from TS 24.229 section 7.2A.4
    ${platform.operator.name}:::::IEEE-802.11
| IEEE-802.11 | PS=WLAN | P-Access-Network-Info value from TS 24.229 section 7.2A.4
    ${platform.operator.name}:::::IEEE-802.11A
| IEEE-802.11A | PS=WLAN | P-Access-Network-Info value from TS 24.229 section 7.2A.4
    ${platform.operator.name}:::::IEEE-802.11B
| IEEE-802.11B | PS=WLAN | P-Access-Network-Info value from TS 24.229 section 7.2A.4
    ${platform.operator.name}:::::IEEE-802.11G
| IEEE-802.11G | PS=WLAN | P-Access-Network-Info value from TS 24.229 section 7.2A.4
    ${platform.operator.name}:::::IEEE-802.11N
| IEEE-802.11N | PS=WLAN | P-Access-Network-Info value from TS 24.229 section 7.2A.4

== Statistics

SCCTADSDataLookUp statistics are tracked by the SCCTADSDataLookUp SBB and can be found under the following parameter set: SLEE-Usage → volte.sentinel.sip service ID → SCCTADSDataLookUp SBB ID.

Name | Type | Description
--- | --- | ---
    Started
| Counter | Incremented when the feature is triggered.
    FailedToStart
| Counter | Incremented when the feature fails to start.
    FailedDuringExecution
| Counter | Incremented when the feature fails while executing.
    IssuedWarning
| Counter | Incremented when the feature issues a warning.
    TimedOut
| Counter | Incremented when the feature times out during execution.
    QueriedShCache
| Counter | Incremented when the Sh Cache Microservice RA is queried.
    ShCacheDataReceived
| Counter | Incremented when the Sh Cache Microservice RA returns data from the query.
    FoundValidCSRoute
| Counter | Incremented when the feature finds a valid route to the CS domain.
    FoundValidPSRoute
| Counter | Incremented when the feature finds a valid route to the PS domain.
    BlindPSRoutingRequested
| Counter | Incremented when the feature has set the BlindPSRouting Session State field.
    NoForkDispositionOverrodeRoutingMode
| Counter | Incremented when the feature does not fork due to disposition header.
    CompanionDeviceOverrodeRoutingMode
| Counter | Incremented when the feature selects `parallel` routing mode because the subscriber has a companion device.
    TriggeredEndSession
| Counter | Incremented when the feature rejects an `INVITE` request due to there being no valid routes to forward it on.
    ResponseLatency
| Sampled | Records elapsed time between requesting data from the Sh Cache Microservice RA and getting a response (in milliseconds).
    CompanionDeviceSipInstanceRoutingEnabled
| Counter | Incremented when enabling companion device sip instance routing override.

== Behaviour

=== Determining Routing Strategy

On receiving an `INVITE` request, the feature will analyse several headers in the request to determine how terminating domain selection should proceed. The main value checked is the `oc-tads-routing` parameter on the top-most `Route` header URI; in addition the feature also looks for the `oc-blindpsrouting` parameter on the same header, and certain values in the `Request-Disposition` header. The feature also checks the `x-msw-companion-device` header to determine if the subscriber has a companion device.

==== OC-TADS-Routing Parameter

`oc-tads-routing` is a custom parameter for the `Route` header. It determines the routing strategy used by T-ADS for domain selection. The following table shows the possible values of the parameter and resulting behavior:

Parameter Value | Behaviour
--- | ---
`ps-cs` | SCCTADSRouting feature will be invoked to attempt connection over PS first, sequentially forking to CS if that fails.
`cs-ps` | SCCTADSRouting feature will be invoked to attempt connection over CS first, sequentially forking to PS if that fails.
`ps-only` | SCCTADSRouting feature will be invoked to attempt connection over PS only.
`cs-only` | SCCTADSRouting feature will be invoked to attempt connection over CS only.
`parallel` | SCCTADSParallelRouting feature will be invoked to attempt connection over CS and PS simultaneously.

==== OC-Blindpsrouting Parameter

`oc-blindpsrouting` is another custom parameter for the route header. If this parameter is present on the top-most `Route` header URI, T-ADS will allow blind PS routing (i.e. no attempt will be made to verify that termination in the PS domain is supported/allowed).

==== Request-Disposition header

The `Request-Disposition` header is specified by RFC-3841. The header contains a comma separated list of values. There are many possible values that can be contained within this header, but TADS Data Lookup is only interested in two:

Value | Behaviour
--- | ---
`no-fork` | This will cause T-ADS to override the `oc-tads-routing` parameter to prevent any forking by the T-ADS routing features. `ps-cs` and `parallel` will be overridden to `ps-only`, `cs-ps` will be overridden to `cs-only`.
`redirect` | If this value is present in the header, the `no-fork` value will be ignored (if present).

==== X-Msw-Companion-Device

The `X-Msw-Companion-Device` header may be set by the upstream terminating MMTel-AS, if the SubscriberDataLookupFromHSS feature found companion device information in the subscriber’s service data.

The value of this header is the companion device’s radio access type — currently only the value "PS" is supported, other values are ignored. If this header is present with the value "PS", then TADS Data Lookup sets the routing mode to `parallel`, overriding the `oc-routing-mode` header. This can however be overridden if the `Request-Disposition` header is present. In which case the rules described in Request-Disposition header above are followed.

=== Determining CS Routes

CS routes are determined by the SCCTADSDetermineCircuitRoutes feature.

=== Determining if +sip.instance Routing should be used for PS Routes

The T-ADS Data Lookup feature has several ways of determining if +sip.instance routing should be used.

| The +sip.instance Contact header parameter is a Uniform Resource Name (URN) that uniquely identifies this specific UA instance.

If `RoutingMode` is not `cs-only` and `EnableSipInstanceRouting` or `EnableCompanionSipInstanceRouting` is true then +sip.instance routing is enabled. Otherwise +sip.instance routing is disabled.

Regardless of how a route is determined, the feature will perform additional analysis to discover if the route is actually usable for PS routing. If the subscriber is not logged in to the IMS according to the `IsLoggedIn` session state field, the T-ADS Data Lookup feature will not select any PS routes under any circumstances.

==== Determining Possible Route When +sip.instance Routing is Disabled

When +sip.instance routing is not in use, the feature will attempt to use the current subscriber identity from Sentinel session state. This identity is determined by the SIP Subscriber Determination Feature. The subscriber identity will be checked using the procedures outlined below, and if it is found to be a valid PS route it will be added to the `TADSPacketRoutes` queue in session state.

==== Determining Possible Routes When +sip.instance Routing is Enabled and UsePathForSipInstanceRouting is Disabled

When using +sip.instance routing, the feature will search for PS routes in the served user’s registration data. The `Contact` headers associated with each active registration for the served user will be checked for a `pub-gruu` parameter. In the case when multiple contact headers are present in a registration record, the parameter 'oc-ue-contact' is used to determine the actual device. This parameter is added during the registration process.

The value of each `pub-gruu` parameter that is found will be checked using the procedures outlined below, and if it is found to be a valid PS route it will be added to the `TADSPacketRoutes` queue in session state. If no valid +sip.instance routes are found, the feature will attempt to find a PS route with the procedure used when +sip.instance routing is disabled.

==== Determining Possible Routes When +sip.instance Routing is Enabled and UsePathForSipInstanceRouting is Enabled

As per above when using +sip.instance routing, the feature will search for PS routes in the served user’s registration data. However if a `pub-gruu` is not present then `Path` information (if `usePathForSipInstanceRouting` is true) will be used to add extra routes to the the outgoing INVITE. This applies to devices that don’t have GRUU support.

==== Determining Validity of a PS Route

Regardless of which of the above methods were used to find the possible PS route(s), each route will be checked to ensure it is valid to attempt to route to it over the PS domain.

There are three approaches the feature can use to validate the route:

1. Checking the registration data associated with the route

2. Querying the HSS for T-ADS information

3. No additional validation beyond checking the subscriber is logged into the IMS

Which method is used is based on the `VoiceOverPSSupportRequired` feature configuration option, and the `oc-blindpsrouting` Route header parameter:

VoiceOverPSSupportRequired | oc-blindpsrouting Route Parameter | Validation method
--- | --- | ---
False | Absent | Registration Data
False | Present | No Additional Validation
True | Absent | HSS Query
True | Present | No Additional Validation

Once a route is found to be valid, it will be added to the `TADSPacketRoutes` queue in session state.

===== Validation by Registration Data

When validating a route by registration data, the feature will retrieve the registration record associated with the route:

- For routes determined with +sip.instance routing, this will be the registration that contained the `pub-gruu` or `Path` that is being validated.

- For routes determined without +sip.instance routing, every active registration will be checked (only one needs to pass validation).

The feature will check the `P-Access-Network-Info` header information in the registration data to decide if PS can be supported. If the access-type values in any of the `P-Access-Network-Info` headers can be found in the `SCCTADSNetworkTypeConfigProfileTable` then the feature will consider the route valid.

===== Validation by HSS Query

If the feature needs to validate routes using the HSS it will form a query to the Sh Cache Microservice RA. This query uses Data Reference 26 `T-ADS Information`. The access key is determined by the value of the `RequestUserIdentityType` feature configuration value:

RequestUserIdentityType | Access Key Public ID | Access Key Private ID
--- | --- | ---
IMPU | SessionState → `Subscriber` | None
MSISDN | SessionState → `CMSISDN` | None
IMPU_IMPI | SessionState → `Subscriber` | Registration → `PrivateID`
MSISDN_IMPI | SessionState → `CMSISDN` | Registration → `PrivateID`

Which registration is used to get the private ID will depend on how the PS routes were determined:

- For routes determined with +sip.instance routing, this will be the registration that contained the `pub-gruu` that is being validated.

- For routes determined without +sip.instance routing, every active registration will be checked (only one needs to pass validation).

This means when an IMPI is required in the query, multiple queries may be needed.

The response to each query will be analysed:

- If the HSS response indicates that voice over PS is not supported, then the associated route(s) will be considered invalid.

- If the HSS response indicates that voice over PS is supported and the RAT type in the same response is present in the `SCCTADSNetworkTypeConfigProfileTable`, then the associated route(s) will be considered valid.

=== If No Valid Routes Are Found

If the feature is unable to determine any valid PS or CS routes for the given routing strategy, then its behaviour will be determined by the `EndSessionWhenNoValidRouteFound` configuration parameter. If the parameter is set to `false` (the default), then T-ADS will allow the incoming `INVITE` to be forwarded as-is. If the parameter is set to `true`, the feature will generate a response with the error code from `EndSessionErrorCode` to the incoming `INVITE` request, terminating the call.

=== Graceful Handling of Originating Access

The feature will finish execution without modifying any state, if invoked in an originating call attempt.

= SCCTADSDetermineCircuitRoutes :toc: macro :toclevels: 4 :toc-title: On this page…​ :sortorder: 1

This feature is used to populate the session state `TADSCircuitRoutes` with the primary and companion device CS routes.

== Feature Cheat Sheet

B2BUA Instance | SAS Support | Originating / Terminating | Point(s) in Session Plan | Network Operator Data | Subscriber Data | Stateful or Stateless | POJO Feature or SBB Feature | Other notes
--- | --- | --- | --- | --- | --- | --- | --- | ---
SCC | Yes | Terminating | `SipAccess_SubscriberCheck` `SipAccess_PartyResponse` | Yes | No | Stateless | POJO |

== Prerequisite Features

- SCCTADSDataLookup

- FetchCMSISDN

== Session Input Variables

Session state variable name | Type | Comments
--- | --- | ---
    RoutingMode
| TADSRoutingMode (Enum) | Determines whether CS and/or PS routing is enabled and the preferred attempt order.
    CircuitRoutesAlreadyDetermined
| boolean | Set to true when circuit routes have already been set.
    HasCompanionDeviceCSRNs
| boolean | Set to true when companion CSRNs have been identified by the FetchCMSISDN/FetchMRSN features.
    CompanionDeviceCSRNs
| Queue<String> | Contains companion device CSRNs.
    HasCSRN
| boolean | Set to true when a primary CSRN has been identified by the FetchCMSISDN/FetchMRSN features.
    CSRN
| String | Contains the primary device CSRN.
    TADSEndSessionWhenNoValidRouteFound
| boolean | Set to true by SCCTADSDataLookup feature if configuration `EndSessionWhenNoValidRouteFound` is true and no PacketRoutes are found.

== Session Output Variables

Session state variable name | Type | Comments
--- | --- | ---
    CircuitRoutesAlreadyDetermined
| boolean | Set to true when circuit routes have already been set.
    TADSCurrentLegRoute
| String | Contains a CSRN or URI that is used by SCCTADSRouting and SCCTADSParallelRouting features to setup a new CS/PS leg.
    TADSCircuitRoutes
| Queue<String> | Contains valid primary and companion CS routes (CSRNs).

== Statistics

Statistics are tracked by the sentinel.volte SBB and can be found under the following parameter set in REM:
SLEE-Usage → sentinel.volte service → sentinel.volte SBB → feature → SCCTADSDetermineCircuitRoutes
or with rhino-stats:
"SLEE-Usage.Services.ServiceID[name=sentinel.volte,vendor=OpenCloud,version=3.1.0].SbbID[name=sentinel.volte,vendor=OpenCloud,version=3.1.0].feature.SCCTADSDetermineCircuitRoutes"

Name | Type | Description
--- | --- | ---
    Started
| Counter | Incremented when the feature is triggered.
    FailedToStart
| Counter | Incremented when the feature fails to start.
    FailedDuringExecution
| Counter | Incremented when the feature fails while executing.
    IssuedWarning
| Counter | Incremented when the feature issues a warning.
    TimedOut
| Counter | Incremented when the feature times out during execution.
    FoundValidCSRoute
| Counter | Incremented when a route is added to the queue.
    TriggeredEndSession
| Counter | Incremented when the feature ends the session.

== Behaviour

=== Determining CS Routes

The feature adds primary and companion CS routes (CSRNs) that are present in session state `CSRN` and `CompanionDeviceCSRNs` into the session state `TADSCircuitRoutes`. The session state `TADSCircuitRoutes` is then used by SCCTADSRouting and SCCTADSParallelRouting features to setup the appropriate CS legs.

| The Circuit Switched Routing Number (CSRN) is made up of the CMSISDN, MSRN, or TLDN. The value is fetched by either FetchCMSISDN, FetchMSRN or CDMAFetchTLDN depending on configuration in `VolteServiceConfigProfileTable` and `SCCTADSDataLookUpConfigProfileTable`.

= SCCTADSRouting :toc: macro :toclevels: 4 :toc-title: On this page…​ :sortorder: 2

T-ADS Routing executes after T-ADS data lookup feature and performs sequential forked routing.

It takes the T-ADS preferred routing decision from SCCTADSDataLookup, and uses it to attempt routing.

It makes the necessary adjustments for PS or CS routing to the outgoing `INVITE` as required.

== Feature Cheat Sheet

B2BUA Instance | SAS Support | Originating / Terminating | Point(s) in Session Plan | Network Operator Data | Subscriber Data | Stateful or Stateless | POJO Feature or SBB Feature | Other notes
--- | --- | --- | --- | --- | --- | --- | --- | ---
SCC | Yes | Terminating only | `SipAccess_SubscriberCheck`, `SipAccess_PartyResponse`, `SipAccess_ServiceTimer` | Yes | No | Stateless | POJO | The feature itself is stateless, but an FSM is encoded into session state

== Prerequisite Features

- Determine Call Type

- SCCTADSDataLookup

== Session Input Variables

Session State variable name | Type | Comments
--- | --- | ---
    CallType
| CallType (Enum) | The call-type for the incoming call (e.g. MobileTerminating).
    RoutingMode
| TADSRoutingMode (Enum) | Determines whether CS and/or PS routing is enabled and the preferred attempt order.
    SentinelSelectionKey
| SentinelSelectionKey | Used to acquire configuration information.
    TADSCircuitRoutes
| Queue<String> | Contains all valid CS domain routes (CSRNs).
    TADSPacketRoutes
| Queue<RouteAndTerminatingDomain> | Contains all valid PS domain routes along with the network type for each route.
    TADSSipInstanceRoutingPossible
| boolean | Indicates whether T-ADS +sip.instance routing is possible for the served user.
    FeatureCapsManager
| FeatureCapsManager | Management interface for controlling Feature-Caps header values on outgoing messages.
    RegistrationRecords
| List<RegistrationRecord> | List of registered devices for the served user, determines the maximum number of downstream forks to wait for when routing on the preferred domain.
    TADSFallbackLegType
| LegType (Enum) | The fall back leg type (e.g. None, CS, or PS).
    TADSPreferredLegType
| LegType (Enum) | The preferred leg type.
    TADSCircuitRoutesPending
| boolean | Used to indicate if any CS leg attempts are outstanding.
    TADSCurrentLegName
| String | Current leg name being contacted.
    SendNextRequest
| boolean | Used to indicate if the feature should send the SIP request.
    TADSequentialInviteSeqNum
| Long | Used to check if the SIP response is for the current access leg `INVITE`.

== Session Output Variables

Session State variable name | Type | Comments
--- | --- | ---
    TerminatingDomain
| String | Records the current value being used for the OC-Terminating-Domain Header
    FeatureCapsManager
| FeatureCapsManager | Management interface for controlling Feature-Caps header values on outgoing messages.
    PSTerminatingDomainHeaderValue
| String | Value set in the `OC-Terminating-Domain` header
    TADSTimerID
| TimerID | Current leg max wait timer
    FetchedMSRN
| boolean | Flag to reactivate execution of FetchMSRN feature

== Network Operator Data

T-ADS Routing has network operator data in a profile table named `SCCTADSRoutingConfigProfileTable`. The data is scoped by Sentinel selection key.

Attributes | Type | Meaning
--- | --- | ---
    TimerTADS
| int | The time in milliseconds that the feature will wait for an acceptable response when routing to the preferred leg. This value is required to be between 500 and 5000 ms.
    PSToCSFallbackResponseCodes
| int[] | The list of SIP error response codes that will trigger CS fallback if received on a PS routing attempt.
    RouteCSDirectlyThroughICSCF
| boolean | When true, T-ADS will route requests to the CS domain directly via the I-CSCF (bypassing the S-CSCF).

T-ADS Routing also draws additional network operator data from SIP service configuration in a profile table named `SipSentinelConfigurationTable`. The data is scoped by Sentinel selection key.

Attributes | Type | Meaning
--- | --- | ---
    IcscfUri
| String | The `sip:` URI for the I-CSCF

== Statistics

SCCTADSRouting statistics are tracked by the SCCTADSRouting SBB and can be found under the following parameter set: SLEE-Usage → sentinel.volte.sip service ID → SCCTADSRouting SBB ID.

Name | Description
--- | ---
    Started
| Incremented when the feature is triggered.
    FailedToStart
| Incremented when the feature fails to start.
    FailedDuringExecution
| Incremented when the feature fails while executing.
    IssuedWarning
| Incremented when the feature issues a warning.
    TimedOut
| Incremented when the feature times out during execution.
    RouteToPreferredPS
| Incremented when the feature successfully to routes to a preferred leg when PS is preferred.
    RouteToPreferredCS
| Incremented when the feature successfully to routes to a preferred leg when CS is preferred.
    RouteToFallbackPS
| Incremented when the feature successfully to routes to a fallback leg when PS is preferred.
    RouteToFallbackCS
| Incremented when the feature successfully to routes to a fallback leg when CS is preferred.
    ErrorResponseMatched
| Incremented when an error response received from a routing attempt triggers a new routing attempt.
    Error18xMatched
| Incremented when the PS call 18x response matches the SDP requirements outlined in 18x Response.
    Received18xResponse
| Incremented when the feature receives a 18x response to the initial `INVITE` request
    Received488Response
| Incremented when the feature receives a 488 message from the PS call.
    ReceivedPSToCSFallbackResponseCode
| Incremented when the feature receives a error message from the PS call that is contained in `PSToCSFallbackResponseCodes`.
    TerminatingDomainHeaderSet
| Incremented when the feature adds a terminating domain header to an upstream response
    TADSTimerFired
| Incremented when the Max Wait Timer for a response on a routing attempt is exceeded
    RouteToPreferredPSAnswered
| Incremented when a preferred PS leg is answered
    RouteToFallbackPSAnswered
| Incremented when a fallback PS leg is answered
    RouteToPreferredCSAnswered
| Incremented when a preferred CS leg is answered
    RouteToFallbackCSAnswered
| Incremented when a fallback CS leg is answered
    RouteToPreferredPSFailed
| Incremented when a preferred PS leg returns a failed SIP response e.g. >299
    RouteToPreferredCSFailed
| Incremented when a preferred CS leg returns a failed SIP response e.g. >299
    RouteToFallbackPSFailed
| Incremented when a fallback PS leg returns a failed SIP response e.g. >299
    RouteToFallbackCSFailed
| Incremented when a fallback CS leg returns a failed SIP response e.g. >299

== Behaviour

The following behaviour is described below:

- Sequential routing strategies

- Domain is PS

- Domain is CS

- Cannot attempt CS routing case

- Graceful handling of originating access

=== Sequential routing strategies

The default routing strategy in VoLTE is to try to route to PS domain first and fallback to CS domain. This behaviour can be changed by the value of the parameter `oc-tads-routing` in the Route Header Parameters.

Based on the value of the `RoutingMode` session state field (calculated from the content of `oc-tads-routing` parameter), one of the following sequential routing modes is selected:

==== PS Domain only `RoutingMode = PS-ONLY`

The feature tries to route towards the PS domain with no fall back to the CS domain. 100-TRYING responses and QoS negotiation are not shown in the flow.

==== CS Domain only `RoutingMode = CS-ONLY`

The feature tries to route towards the CS domain with no fall back to PS domain. 100-TRYING responses and QoS negotiation are not shown in the flow.

==== PS network first with fallback to CS network `RoutingMode = PS-CS`

The feature tries the PS domain first and drops to CS if the PS conditions don’t match. This allows the setting of Package Switch network as a preferred domain but also allows the usage of a Circuit Switch network if the user is available. This is the default mode. 100-TRYING responses and QoS negotiation are not shown in the flow.

==== CS network first with fallback to PS network `RoutingMode = CS-PS`

The feature tries the CS domain first and drops to PS if the CS conditions don’t match. This allows the setting of Circuit Switch network as a preferred domain but also allows the usage of a Package Switch network if the user is logged in. 100-TRYING responses and QoS negotiation are not shown in the flow.

=== Selected Domain is CS

If T-ADS chooses to deliver on the CS domain, the T-ADS Routing feature will iterate through the CSRNs queued in the `TADSCircuitRoutes` session state field.

Going one at a time, for each CSRN the feature will:

- Create an `INVITE` to the called party using the CSRN as the `Request-URI` and also as the `To` header.

- If `RouteCSDirectlyThroughICSCF` is enabled in feature configuration, the `Route` header will be modified to direct the request to the configured `IcscfUri`.

- Add a `Request-Disposition` header indicating `no-fork`.

- Send the `INVITE` and await a response.

- Handle responses according to behaviour outlined below.

The feature will iterate to the next CSRN if the call fails but meets the conditions for fallback. If all possible CSRNs are exhausted and the routing strategy is `CS-PS`, the feature will fall-back to PS routing.

Note that the response handling for `488` and `18x` Responses is the same when the PS domain is selected and the same fallback rules are applied.

=== Selected Domain is PS

If T-ADS chooses to deliver on the PS domain, the T-ADS Routing feature will iterate through the URIs queued in the `TADSPacketRoutes` session state field. If any `Path` information is set in `TADSCurrentLegPaths` session state then these are added as routes to the outgoing `INVITE`.

Going one at a time, for each URI the feature will:

- Create an `INVITE` to the called party using the URI as the `Request-URI` and also as the `To` header.

- If `TADSSipInstanceRoutingPossible` is `true` in session state, add a `Request-Disposition` header indicating `no-fork`.

- Add any routes in `TADSCurrentLegPaths` to the `INVITE`.

- Send the `INVITE` and await a response.

- Handle responses according to behaviour outlined below.

The feature will iterate to the next URI if the call fails but meets the conditions for fall-back. If all possible URIs are exhausted and the routing strategy is `PS-CS`, the feature will fall-back to CS routing.

=== Response handling

The responses are handled the same way for PS and CS domains, except where noted.

==== Max Wait Timer

Upon forwarding the `INVITE` request towards the preferred access network, the T-ADS routing feature arms a timer with the value from `TimerTADS` configuration. If this timer expires before a response to the `INVITE` request is received, the `INVITE` will be cancelled and the feature will fall-back to the next available route. The timer will be cancelled if a response is received before it expires, though it may be replaced with a new timer under the conditions outlined in the 18x Response section.

==== 488 Response

After forwarding the `INVITE`, if the T-ADS Routing feature receives a `488` ("Not Acceptable Here") response from the UE that:

- does not include any SDP body; OR

- includes an SDP body:

  - without a media description (`m=`) indicating `audio`;

  - with a media description (`m=`) only indicating `audio` with the `<proto>` subfield set to `PSTN` and with a connection data line (`c=`) with `<nettype>` set to `PSTN`

The feature will not forward the response, and it will fall-back to the next available route.

A `488` response that does not meet the above conditions will be forwarded to the calling party.

==== PS Routing Error Response Handling

When attempting to route to PS, the feature will additionally consider SIP response error codes that are contained in the configured `PSToCSFallbackResponseCodes`. These error responses are handled in the same way as a 488 Response.

==== 18x Response

If the T-ADS Routing feature receives a `18x` response it will evaluate it to determine if it is acceptable. If the `18x` response contains an SDP answer with a media description (`m=`) set to `audio` and port portion set to `0`, then it is not acceptable. In all other cases the `18x` will be considered acceptable.

If the `18x` is acceptable the call will proceed on the leg it was received on and T-ADS will complete execution.

If the `18x` is not acceptable the feature will arm a timer using the `TimerTADS` feature configuration value as the duration. The feature will then wait until:

- a acceptable `18x` response arrives, in which case the timer will be cancelled and the call will proceed, OR

- a non-`18x` response arrives, which will be handled as described in its respective response handling section, OR

- the timer expires, OR

- the number of forked responses is equal to the number of simultaneously registered devices for the served user.

If either of the last two conditions are met, the T-ADS Routing feature will send a `CANCEL` for the outbound `INVITE`, and fall-back to the next available route.

==== Others

All other responses are forwarded upstream.

==== OC-Terminating-Domain header addition

The OC-Terminating-Domain header is added to responses heading upstream (usually for charging purposes). The feature adds this header to all responses for the original INVITE that are forwarded upstream.

For more details see OC-Terminating-Domain Header

=== Graceful Handling of Originating Access

The feature will finish execution without modifying any state if invoked in an originating call attempt.

= SCCTADSParallelRouting :toc: macro :toclevels: 4 :toc-title: On this page…​ :sortorder: 3

T-ADS Parallel Routing executes after the T-ADS data lookup feature if the session field `RoutingMode` is set to `PARALLEL`.

The T-ADS Parallel Routing feature parallel-forks the incoming message to both CS and PS legs, and forwards the response from the leg that successfully responds first

== Feature Cheat Sheet

B2BUA Instance | SAS Support | Originating / Terminating | Point(s) in Session Plan | Network Operator Data | Subscriber Data | Stateful or Stateless | POJO Feature or SBB Feature | Other notes
--- | --- | --- | --- | --- | --- | --- | --- | ---
SCC | Yes | Terminating only | SIP Access Session Pre-Credit Check | Yes | No | Stateless | POJO | The feature itself is stateless, but an FSM is encoded into session state

== Prerequisite Features

- Determine Call Type

- DetermineVoltePlanId

- SCCTADSDataLookup

== Session Input Variables

Session State variable name | Type | Comments
--- | --- | ---
    CallType
| CallType (Enum) | The call-type for the incoming call (e.g. MobileTerminating).
    SentinelSelectionKey
| SentinelSelectionKey | Used to acquire configuration information.
    TADSCircuitRoutes
| Queue<String> | Used to retrieve a CSRN for CS routing.
    TADSPacketRoutes
| Queue<RouteAndTerminatingDomain> | Used to determine if PS routing is possible, and to obtain the routes and terminating domains if +sip.instance routing is enabled.
    TADSSipInstanceRoutingPossible
| boolean | Indicates whether T-ADS +sip.instance routing is possible for the served user.
    FeatureCapsManager
| FeatureCapsManager | Management interface for controlling Feature-Caps header values on outgoing messages.

== Session Output Variables

Session State variable name | Type | Comments
--- | --- | ---
    TerminatingDomain
| String | Records the current value being used for the OC-Terminating-Domain Header
    FeatureCapsManager
| FeatureCapsManager | Management interface for controlling Feature-Caps header values on outgoing messages.
    StripPreconditionsLegNames
| <Set>String | The T-ADS Parallel Routing feature adds each parallel legname to the Set which is used by the StripPreconditions feature to remove preconditions (if StripPreconditions EnabledFlag is selected).

== Network Operator Data

T-ADS Routing has network operator data in a J-SLEE profile table named `SccTADSParallelRoutingConfigProfileTable`. The data is scoped by Sentinel selection key.

Attributes | Type | Meaning
--- | --- | ---
    ParallelTimerMaxWait
| int | The time in milliseconds that the feature will wait for a final response on the CS fork before abandoning it.
    RouteCSDirectlyThroughICSCF
| boolean | When true, T-ADS will route requests to the CS domain directly via the I-CSCF (bypassing the S-CSCF)
    ReleaseAllLegsOnBusy
| boolean | When true, T-ADS will terminate all forked legs when the first `486 (Busy Here)` response arrives from any leg.

T-ADS Parallel Routing also draws additional network operator data from SIP service configuration in a J-SLEE profile table named `SipSentinelConfigurationTable`. The data is scoped by Sentinel selection key.

Attributes | Type | Meaning
--- | --- | ---
    IcscfUri
| String | The `sip:` URI for the I-CSCF

== Statistics

`SCCTADSParallelRouting` statistics are tracked by the `volte.sentinel.sip` SBB and can be found under the following parameter set:
SLEE-Usage → volte.sentinel.sip service ID → volte.sentinel.sip SBB ID → feature.SCCTADSParallelRouting

Name | Description
--- | ---
    Started
| Incremented when the feature is triggered.
    FailedToStart
| Incremented when the feature fails to start.
    FailedDuringExecution
| Incremented when the feature fails while executing.
    IssuedWarning
| Incremented when the feature issues a warning.
    TimedOut
| Incremented when the feature times out during execution.
    TriggeredOnRequest
| Incremented when the feature is triggered on a SIP Request.
    TriggeredOnResponse
| Incremented when the feature is triggered on a SIP Response.
    TriggeredOnTimer
| Incremented when the feature is triggered on the timer firing.
    CSRNNotFound
| Incremented when the CS fork cannot be established because no CSRN can be found.
    MaxWaitTimerSet
| Incremented when the Max Wait Timer is started.
    MaxWaitTimerCancelled
| Incremented when the Max Wait Timer is cancelled.
    UpstreamForkCreated
| Incremented when an upstream forked leg is created to forward a provisional or success response from the CS leg or any secondary PS leg.
    ReceivedProvisionalResponse
| Incremented when a provisional 18x response is received.
    ReceivedFinalResponse
| Incremented when a final response is received for the initial INVITE.
    RouteToCSAttempted
| Incremented when an INVITE is routed down the CS forked leg.
    RouteToPSAttempted
| Incremented when an INVITE is routed down a PS forked leg.
    RouteToCSFailed
| Incremented when the CS leg is torn down without being answered.
    RouteToPSFailed
| Incremented when a PS leg is torn down without being answered.
    AnsweredOnCS
| Incremented when a success response is received on the CS leg.
    AnsweredOnPS
| Incremented when a success response is received on a PS leg.
    TADSTerminatingDomainsNotSet
| Incremented when the feature cannot retrieve the terminating domains for the active routes from session state.
    NoForkAdded
| Incremented when the feature adds the `Request-Disposition: no-fork` directive to an outgoing INVITE.
    NoForkRemoved
| Incremented when the feature removes the `Request-Disposition: no-fork` directive from an outgoing INVITE.

== Behaviour

The following behaviour is described below:

- Initial Forking

- On Receiving a Provisional Response

- On Receiving a Final Error Response

- On Receiving a Final Success Response

- On Receiving a CANCEL Request

=== Initial Forking

This feature will initiate an `INVITE` towards the PS domain if the session state field `IsPSRouting` is `TRUE`. It will also initiate an `INVITE` towards the CS domain if the session state field `CSRN` is populated.

If both of these conditions are true, then the two `INVITEs` form a parallel fork. If +sip.instance routing is enabled, the feature will initiate invites to all registered PS routes, and hence the parallel fork can consist of more than two `INVITEs`.

The outgoing `INVITE` for the CS leg is generated from the original incoming `INVITE` received from the calling party. The `Request-URI` and `To` headers are changed to a Tel URI generated from the CSRN. If configured in network operator data, the `Route` header will be modified to route the request directly to the I-CSCF.

When the PS and CS legs are created the `Request-Disposition` header is set to `no-fork` to ensure that the downstream SCSCF doesn’t perform a downstream fork.

If `INVITEs` are sent to both the PS and CS domains, the feature starts a timer. This timer will be set to expire after a length of time determined by the `ParallelTimerMaxWait` setting in the feature configuration profile. If this timer expires before a final response is received from any leg, the CS fork will be canceled.

In the event that both the PS and CS legs cannot be created, then the feature instructs Sentinel VoLTE to end the INVITE session by responding to the calling party with a final SIP error response with status code `480` (Temporarily Unavailable).

If only one of the legs is attempted then the TADS Parallel Routing feature did not create a parallel fork. In this case T-ADS acts as a routing B2BUA adding the `OC-Terminating-Domain` header as per the OC-Terminating-Domain header addition section.

=== On Receiving a Provisional Response

Provisional responses are always forwarded upstream.

In addition, the feature will add an `OC-Terminating-Domain` header to the forwarded response.

=== On Receiving a Final Error Response

When a final error response is received on one of the forked legs the exact behavior of the feature depends on the state of the other forked legs.

If some other forked leg is still active, then the leg the final error was received on will be released. In this case the feature will prevent the error response from being forwarded to the calling party.

If all other forked legs have been aborted or were never created, then the error response will be forwarded upstream, effectively ending the call.

If the error is forwarded upstream, the `OC-Terminating-Domain` header will be added to the response.

=== On Receiving a Final Success Response

In the case of a parallel fork, the first `2xx` success response processed by this feature will be forwarded and the call will be established over that Dialog. The remaining forked legs are terminated as per SIP procedures.

The `OC-Terminating-Domain` header will be included on the response.

In the event that multiple legs answer at the same time, they are processed in an order. The first response to be processed by the feature "wins".

=== On Receiving a CANCEL Request

If the calling party sends a CANCEL for the original INVITE, the TADS Parallel Routing feature will immediately terminate all remaining legs according to standard SIP protocol.

=== OC-Terminating-Domain Header addition

The OC-Terminating-Domain header is added to responses heading upstream (usually for charging purposes). The feature adds this header to all responses for the original INVITE that are forwarded upstream.

For more details see OC-Terminating-Domain Header

== Illustrative scenarios

To better illustrate the feature, consider the following scenarios.

=== Scenario 1

In this scenario the feature creates a parallel fork to the PS and CS domains, and arms an internal timer. Prior to timer expiry, an error response is received from the PS domain. The feature discards the PS leg. Session establishment continues on the CS domain.

=== Scenario 2

In this scenario the feature creates a parallel fork to the PS and CS domains, and arms an internal timer. In this case both domains send provisional responses. The PS domain answers first, and as a consequence the CS domain is terminated.

= FetchMSRN :toc: macro :toclevels: 4 :toc-title: On this page…​ :sortorder: 4

The FetchMSRN feature retrieves the MSRN (Mobile Subscriber Roaming Number) and the VLR number from the HLR. The FetchMSRN feature derives the Circuit Switched Routing Number (CSRN) from the MSRN and stores the CSRN in session state.

== Feature Cheat Sheet

B2BUA Instance | SAS Support | Originating / Terminating | Point(s) in Session Plan | Network Operator Data | Subscriber Data | Stateful or Stateless | POJO Feature or SBB Feature | Other notes
--- | --- | --- | --- | --- | --- | --- | --- | ---
SCC | Yes | Terminating | `SCCTerm_SipAccess_SubscriberCheck` `SCCTermTads_SipAccess_SubscriberCheck` `SCCTerm_SipAccess_PartyResponse` `SCCTermTads_SipAccess_PartyResponse` | Yes | No | Stateless | SBB |

== Session input variables

Variable name | Type | Comments
--- | --- | ---
    RegistrationRecords
| List<RegistrationRecord> | The list of registration records for the subscriber, used to find the subscriber’s identity for the HLR lookup.
    SentinelSelectionKey
| SentinelSelectionKey | Used to retrieve configuration data for the feature.
    Subscriber
| String | Used to obtain the subscriber’s identity if it could not be determined from the registration data.
    RoutingMode
| TADSRoutingMode | `PS_CS`, `CS_PS`, `CS_ONLY`, `PS_ONLY` or `PARALLEL`
    TADSCurrentLegType
| LegType | `None`, `CS` or `PS`
    ChargeMode
| ChargeMode | `RO`, `CAP`, `OFFLINE` or `DEFAULT`
    CompanionDevices
| List<CompanionDevice> | Used to obtain MSRNs corresponding to MSISDNs of any companion devices

== Session output variables

Variable name | Type | Comments
--- | --- | ---
    CSRN
| String | The CSRN of the served user, if the feature could derive it.
    HasCSRN
| boolean | Indicating whether the CSRN session state field has been populated.
    CallReferenceNumber
| byte[] | The Call Reference Number used in the SRI request to the HLR.
    VLRNumber
| AddressString | The VLR number for the served user, if the feature could retrieve it.
    FetchedMSRN
| boolean | Indicates whether the MSRN was fetched successfully.
    TADSHLRSuccess
| boolean | Indicates whether the HLR returned a `SendRoutingInfo-v3Result` response.
    CompanionDeviceMSRNs
| List<String> | MSRNs retrieved for the MSISDNs of the companion devices
    CompanionDeviceCSRNs
| List<String> | CSRNs derived from the `CompanionDeviceMSRNs`

| The `CSRN` is the `MSRN`, with an optional prefix (defined in feature configuration)

== Network Operator Data

The FetchMSRN feature depends on network operator data in two configuration profile tables. One is for feature specific configuration, the other is for general HLR connection configuration.

=== Feature Configuration

Feature specific configuration is set in a profile table called: `SCCFetchMSRNConfigProfileTable`. Profiles are scoped on Sentinel Selection Key.

==== SCCFetchMSRNConfigProfileTable

Attribute | Type | Default Value | Meaning
--- | --- | --- | ---
    SuppressTcsi
| boolean |
    true
| If enabled the feature will set the `Suppress_T_CSI` flag in outgoing SRI requests.
    ForceSipUserEqualsPhone
| boolean |
    false
| If true, when attempting to extract a number from a SIP URI, the feature will extract a number even if the URI does not have the `user=phone` parameter.
    TerminatingSuppressionOfAnnouncement
| boolean |
    false
| If true, will set the `Suppression Of Announcement` flag in outgoing SRI requests.
    CSRNPrefix
| String |
    null
| The (optional) prefix to be added to the MSRN to form the CSRN

=== HLR Connection Configuration

The FetchMSRN feature uses the common HLR configuration profile table. See this page for details: HLR MAP Configuration.

== Statistics

FetchMSRN statistics are tracked by the `FetchMSRN` SBB and can be found using the parameter set `SLEE-Usage.Services.ServiceID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].SbbID[name=scc-fetch-msrn-feature,vendor=OpenCloud,version=3.1.0]`

Or in REM under the following parameter sets:
SLEE-Usage → Services → sentinel.volte.sip service → scc-fetch-msrn-feature SBB

Parameter | Type | Description
--- | --- | ---
    Started
| Counter | Incremented when the feature is invoked.
    Failed
| Counter | Incremented when a fatal error has occurred.
    RequestSent
| Counter | Incremented when a request is sent to the HLR.
    RequestFailed
| Counter | Incremented when a MSRN is not received from the HLR.
    RequestReceivedAbsentSubscriber
| Counter | Incremented if the HLR indicates that the requested subscriber is not CS attached.
    RetrievedMSRN
| Counter | Incremented when an MSRN is received from the HLR.
    CSRNDetermined
| Counter | Incremented when a CSRN could be determined
    CSRNNotDetermined
| Counter | Incremented when a CSRN could not be determined
    OverwritingCSRN
| Counter | Incremented when CSRN is already set in session state and is overwritten with the MSRN
    ResponseLatency
| Sampled | Records elapsed time between sending the request to the HLR and getting a response (in milliseconds).

== Behaviour

if `FetchedMSRN` session state field is set, the feature finishes with no further processing.

If the feature has not previously run on this session then if none of the following conditions are true it does not need to run and the feature finishes with no further processing

- `RoutingMode` session state field is `PARALLEL`

- `TADSCurrentLegType` session state field is `CS`

- `ChargeMode` session state field is `CAP`.

Otherwise, the feature has previously run on this session. If either of the following conditions are true, then it does not need to run again and the feature finishes with no further processing

- `RoutingMode` session state field is `PARALLEL`

- There are no more companion device MSRNs to be fetched, in the `FetchedMSRNLegs` session state field, which in the non parallel case is actually the MSISDNs of the as yet unfetched legs.

If not done in a previous invocation of the feature, the feature builds a list of subscriber numbers as follows and saves it in `FetchedMSRNLegs` session state field.

- the first value is the "digits" portion of the IMS default public ID of the Served user from the first entry in the `RegistrationRecords` session state field. If this field does not contain digits, the "digits" portion of the subscriber ID is used. Note that the feature does not use the entire ID, only the digits portion. Specifically, the feature will use the numbers in a Tel URI, or the user part of a SIP URI that has the 'user=phone' parameter if `ForceSipUserEqualsPhone` is false, or the user part of a SIP URI without the 'user=phone' parameter if `ForceSipUserEqualsPhone` is true.

- subsequent values, if any, are the MSISDNs of any companion devices where the radio access is CS or PS_CS.

If session state field `RoutingMode` is `PARALLEL` then

- the feature issues an SRI request to the HLR for each subscriber as below

- once all responses are received (or failed), the feature finishes.

Otherwise

- the feature issues an SRI request to the HLR for the first subscriber in `FetchedMSRNLegs` session state field as below, and removes that subscriber from the session state field

- once a response (or failure) is received, the feature finishes

- SCC T-ADS Routing features will subsequently clear the `FetchedMSRN` session state field as necessary and trigger this feature to re-run in order to process subsequent subscribers sequentially.

=== Sending SRI and processing SRI-Response

The feature builds a query to the HLR for the MSRN using the MAP operation `Send Routing Info`. The MAP Application Context used is `locationInfoRetrievalContext_v3_ac`.

While building the HLR request the feature will generate a Call Reference Number used in the SRI. This is then put into a header on the incoming INVITE (from where it is copied as part of the outgoing INVITE) called OC-IM-CallReferenceNumber as well as saved in session state (for inclusion in CDRs).

If the feature configuration option `SuppressTcsi` is enabled, then the `Suppress_T_CSI` flag will be set in the CamelInfo on the request. This will prevent the VLR number from being included in the response.

The `FetchedMSRN` session state field is set to `true` to prevent the feature repeating the SRI request(s).

The feature issues the query to the HLR.

The HLR may return either a failure response, or a SendRoutingInfo-Res response containing the MSRN in the field ExtendedRoutingInfo.

If the feature is able to find an MSRN in the returned set, it increments the RequestSuccessful counter, and modifies the output session state variables. If there is a VLR number in the returned set, this will also be output to a session state variable.

If the returned set is empty, the feature increments the RequestFailed counter, and does not modify any output session state variables.

If the HLR returns a failure response, the feature increments the RequestFailed counter, and does not modify any output session state variables.

= CDMAFetchTLDN :toc: macro :toclevels: 4 :toc-title: On this page…​ :sortorder: 5

| This feature is for CDMA networks.

The CDMAFetchTLDN feature retrieves the TLDN (Temporary Local Directory Number) from the HLR. The CDMAFetchTLDN derives the Circuit Switched Routing Number (CSRN) from the TLDN and stores the CSRN in session state.

== Feature Cheat Sheet

B2BUA Instance | Originating / Terminating | Point(s) in Session Plan | Network Operator Data | Subscriber Data | Stateful or Stateless | POJO Feature or SBB Feature | Other notes
--- | --- | --- | --- | --- | --- | --- | ---
SCC | Terminating | `SipAccess_SessionCheck` | Yes | No | Stateless | POJO |

== Session input variables

Variable name | Type | Comments
--- | --- | ---
    RegistrationRecords
| List<RegistrationRecord> | The list of registration records for the subscriber, used to find the subscriber’s identity.
    Subscriber
| String | Used to obtain the subscriber’s identity if it could not be determined from the registration data.
    FetchedTLDN
| boolean | True, if the TLDN has been fetched successfully.
    RoutingMode
| TADSRoutingMode (Enum) | Determines whether CS and/or PS routing is enabled and the preferred attempt order.
    TADSCurrentLegType
| LegType (Enum) | One of NONE, CS or PS
    LastRequestSendTime
| Long | The last time a request was sent for the TLDN, or null if a request has not been made.
    SentinelSelectionKey
| SentinelSelectionKey | Used to retrieve configuration data for the feature.
    Subscriber
| String | Used to obtain the subscriber’s identity if it could not be determined from the registration data.

== Session output variables

Variable name | Type | Comments
--- | --- | ---
    CSRN
| String | The CSRN of the served user, if the feature could derive it.
    HasCSRN
| boolean | Indicates whether the CSRN session state field has been populated.
    FetchedTLDN
| boolean | Indicates whether the TLDN was fetched successfully.
    LastRequestSendTime
| Long | The last time a request was made for the TLDN.

| The `CSRN` is the `TLDN`, with an optional prefix (defined in feature configuration)

== Network Operator Data

The CDMAFetchTLDN feature depends on network operator data in two configuration profile tables. One is for feature specific configuration, the other is for general HLR connection configuration.

=== Feature Configuration

Feature specific configuration is set in a profile table called: `SCCCDMAFetchTLDNConfigProfileTable`. Profiles are scoped on Sentinel Selection Key.

==== SCCCDMAFetchTLDNConfigProfileTable

Attribute | Type | Default Value | Meaning
--- | --- | --- | ---
    ForceSipUserEqualsPhone
| boolean |
    false
| If true, when attempting to extract a number from a SIP URI, the feature will extract a number even if the URI does not have the `user=phone` parameter.
    CSRNPrefix
| String |
    null
| The (optional) prefix to be added to the TLDN to form the CSRN
    SubscriberTypeOfDigits
| String |
    DIALED_OR_CALLED_PARTY_NUMBER
| The type of digits field of the subscriber 'DigitsType' included in the LOCREQ.
    SubscriberNatureOfNumber
| String |
    INTERNATIONAL
| The nature field of the subscriber 'DigitsType' included in the LOCREQ.
    SubscriberNumberingPlan
| String |
    TELEPHONY
| The numbering plan field of the subscriber 'DigitsType' included in the LOCREQ.

=== HLR Connection Configuration

The CDMAFetchTLDN feature uses the HLR configuration in a profile table called: `CDMAHLRConfigProfileTable`. Profiles are scoped on Sentinel Selection Key.

==== CDMAHLRConfigProfileTable

Attribute | Type | Default Value | Meaning
--- | --- | --- | ---
    HLRSccpAddressAsString
| String |
    type=A7,ri=pcssn,pc=1-1-1,ssn=101,national=true
| SCCP Address of the HLR, used when establishing the MAP dialog
    SentinelSccpAddressAsString
| String |
    type=A7,ri=pcssn,pc=1-1-2,ssn=102,national=true
| SCCP Address of Sentinel, used when establishing the MAP dialog
    HLRInvokeTimeout
| long |
    4000
| The timeout (ms) for waiting the HLR response. Used in the TCAP layer for the invoke timeout.
    MarketID
| int |
    1
| The value of the market id field in the `MSCID` used in the `LOCREQ`.
    SwitchNumber
| int |
    1
| The value of the switch number field in the `MSCID` used in the `LOCREQ`.

| See: SCCP Address Format to understand the String format of SCCP addresses.

== Statistics

CDMAFetchTLDN statistics are tracked by the sentinel.volte.sip SBB and can be found under the following parameter set:
SLEE-Usage → [sentinel.volte.sip service name] → [sentinel.volte.sip SBB name] → feature.CDMAFetchTLDN

Parameter | Type | Description
--- | --- | ---
    RequestSent
| Counter | Incremented when a request is sent to the HLR.
    FailedToSendRequest
| Counter | Incremented when a request failed to be sent to the HLR.
    RequestFailed
| Counter | Incremented when a TLDN is not received from the HLR.
    CSRNNotDetermined
| Counter | Incremented if the CSRN could not be derived.
    CSRNDetermined
| Counter | Incremented when the CSRN is derived.
    UnableToDetermineSubscriber
| Counter | Incremented when it was not possible to determine an address for the subscriber.
    ResponseLatency
| Sampled | Records elapsed time between sending the request to the HLR and getting a response (in milliseconds).

== Behaviour

The feature issues a query to the HLR for the TLDN using the MAP operation `Location Request`. The CDMA Application Context used is `allOperationsAC`.

When building the request to the HLR, the feature retrieves the "digits" portion of the IMS default public ID of the Served user from the first entry in the `RegistrationRecords` session state field. If this field does not contain digits, the "digits" portion of the subscriber ID is used.

Note that the feature does not use the entire ID, only the digits portion. Specifically, the feature will use the numbers in a Tel URI, or the user part of a SIP URI that has the 'user=phone' parameter if `ForceSipUserEqualsPhone` is false, or the user part of a SIP URI without the 'user=phone' parameter if `ForceSipUserEqualsPhone` is true.

The HLR may return either a failure response, or a LocationRequest-Res response containing the TLDN as a PSTNTermination element in the field TerminationList. If there is no valid element in the TerminationList field, the feature will also check the top level digits field for any TLDNs marked as ROUTING_NUMBER.

If a TLDN is returned, the CDMAFetchTLDN feature sets the `CSRN` session state field.

= DetermineLocationFromMSRN :toc: macro :toclevels: 4 :toc-title: On this page…​

This feature determines the two-letter ISO Country Code for a subscriber’s location, based on their MSRN.

== Feature cheat sheet

Feature Script Name | DetermineLocationFromMSRN
Call-Type | Term
Session Plan | scc-tads
Execution Points | SipAccess_SubscriberCheck
Network Operator Config | Yes
Subscriber Config | No
POJO or SBB | POJO
Feature FSMs | None
Feature Parameters | None
SAS Support | Yes
RA Entity Links | None

== Prerequisite features

- FetchMSRN

== Session State Inputs and Outputs

=== Inputs

Name | Type | Purpose
--- | --- | ---
MSRN | String | The MSRN for the current subscriber.

=== Outputs

Name | Type | Description
--- | --- | ---
IsoCountryCode | String | The ISO country code for the subscriber’s location.

== Statistics

DetermineLocationFromMSRN statistics are tracked by the sentinel.volte SBB and can be found under the following parameter set in REM:
SLEE-Usage → sentinel.volte service → sentinel.volte SBB → feature → DetermineLocationFromMSRN
or with rhino-stats:
"SLEE-Usage.Services.ServiceID[name=sentinel.volte,vendor=OpenCloud,version=3.1.0].SbbID[name=sentinel.volte,vendor=OpenCloud,version=3.1.0].feature.DetermineLocationFromMSRN"

Name | Type | Description
--- | --- | ---
    Started
| Counter | Incremented when the feature is triggered.
    FailedToStart
| Counter | Incremented when the feature fails to start.
    FailedDuringExecution
| Counter | Incremented when the feature fails while executing.
    IssuedWarning
| Counter | Incremented when the feature issues a warning.
    TimedOut
| Counter | Incremented when the feature times out during execution.
    DeterminedIsoCountryCode
| Counter | Incremented when the ISO country code is determined.
    UnableToDetermineIsoCountryCode
| Counter | Incremented when the ISO country code cannot be determined.
    NoActionRequired
| Counter | Incremented when the feature does not need to do anything as the ISO country is already known.
    MsrnNotAvailable
| Counter | Incremented when the MSRN is not present in session state, so the feature cannot do anything.

== Configuration

This feature depends on an address list which maps country codes from E.164 numbers to ISO country codes. The address list is implemented according to the standard format as defined here: Address Lists. The schema name for this address list is `CountryCode`. Address list entries are kept on a list called `E164`. Each entry represents a E.164 number prefix that identifies the country the number is for. In most cases this prefix is simply the standard dial code for that country, however some countries share the same dial code, for these cases area codes are also included in the prefix to remove ambiguity.

The address list entry table includes the standard list entry table attributes, and the following additional attributes:

Attribute Name | Type | Description
--- | --- | ---
    Country
| String | The name of the country corresponding to the E.164 prefix.
    IsoCountryCode
| String | The two-letter ISO country code for the country.

== Behaviour

When first triggered, the feature will check session state to ensure two things:

1. The `IsoCountryCode` field has not already been set (by the ExtractNetworkInfo feature).

2. The `MSRN` field has been set (by the FetchMSRN feature).

If either of these conditions is not met, the feature will complete execution with no further action taken.

If the conditions are met, the feature will execute a longest prefix match for the MSRN in the CountryCode address list. If a result is found, the `IsoCountryCode` field on the list entry will be copied into the `IsoCountryCode` session state field.

= FetchCMSISDN

This feature fetches the Correlation MSISDN from the HSS, using the Sh Cache Microservice. It can be invoked during Third Party Registration and INVITE session processing.

== Prerequisite features

SCC Decode Companion Device Info Feature if companion device CRSNs are to be derived.

== Description

This feature fetches the Correlation MSISDN from the HSS, using the Sh Cache Microservice. It can be invoked during Third Party Registration and INVITE session processing. In addition, it tries to derive a CSRN from the CMSISDN.

The feature issues a query to the Sh Cache Microservice for the Correlation MSISDN, unless a value is already set in session state. When building the request to the HSS, it uses a User Data Request with Sh Data Reference 17 - MSISDN or MSISDN + ExtendedMSISDN. The query access key is the default Public Identity, or the default Public Identity plus the IMS Private Identity. The access chosen is based on the feature configuration attribute "UDRIncludedIdentities".

The Sh Cache Microservice may return either a failure response, or an Sh document.

If the feature is configured to look for the Correlation MSISDN in MSISDN, it uses the first MSISDN in the returned set at `Sh-Data/PublicIdentifiers/MSISDN` in the Sh UDA response.

If the feature is configured to look for the Correlation MSISDN in Extended-MSISDNs, it uses the first MSISDN in the returned Extended MSISDNs set at `Sh-Data/PublicIdentifiers/Extension/Extension/Extension/ExtendedMSISDN` in the Sh UDA response.

If the feature is able to find an MSISDN in the returned set, it increments the SuccessfullyRetrievedCMSISDN counter, and modifies the output session state variables.

If the returned set is empty, the feature increments the FailedToRetrieveCMSISDN counter, and does not modify any output session state variables.

If the Sh Cache Microservice returns a failure response, the feature increments the ShCacheError counter, and does not modify any output session state variables.

When the session state field `UseHLRBasedCSRN` is `false`

- the feature derives a CSRN by prefixing the MSISDN with the configured prefix. If a CMSISDN could not be found, and `EnableCSRoutingFromRequestUri` is enabled, the feature attempts to extract a phone number from the Request-URI, and sets the CSRN in session state as this phone number prefixed with the configured prefix.

- if session state has companion devices, the feature sets `CompanionDeviceCSRNs` and `HasCompanionDeviceCSRNs` by prefixing the MSISDNs in `CompanionDevices` session state field with the configured prefix.

== Session input variables

Variable name | Type | Comments
--- | --- | ---
    PublicIds
| String array | The IMS Public Ids for the Served User, used when triggered on a REGISTER
    PrivateId
| String | Contains the subscriber’s private identity, used when triggered on a REGISTER
    RegistrationRecords
| List<RegistrationRecord> | The registration records for the Served User, used when triggered on an INVITE
    CompanionDevices
| List<CompanionDevice> | The list of companion devices decoded from the `X-Msw-Companion-Device` header
    UseHLRBasedCSRN
| boolean | When `true` CSRNs are not derived.

== Session output variables

Variable name | Type | Comments
--- | --- | ---
    CMSISDN
| String | Set to the Correlation MSISDN if the feature could retrieve it
    HasCMSISDN
| boolean | Set to true if the feature could retrieve the CMSISDN
    CSRN
| String | The CSRN of the served user, if the feature could derive it.
    HasCSRN
| boolean | Indicating whether the CSRN session state field has been populated.
    CompanionDeviceCSRNs
| List<String> | The CSRNs of the companion devices
    HasCompanionDeviceCSRNs
| boolean | indicating whether the CompanionDeviceCSRNs session state field has been populated

= Statistics

There are two sets of statistics, one as the feature is invoked during Registration, and another during INVITE processing.

Both sets of statistics share the same interface. They are located in different SLEE services.

Parameter | Type | Description
--- | --- | ---
    Started
| Counter | Incremented each time the feature runs
    FailedToStart
| Counter | Incremented when a fatal error occurs before feature execution
    IssuedWarning
| Counter | Incremented when a non-fatal error occurs during feature execution
    FailedDuringExecution
| Counter | Incremented when a fatal error occurs during feature execution
    TimedOut
| Counter | Incremented when feature execution does not complete within a reasonable time frame
    FailedToRetrieveCMSISDN
| Counter | Incremented when the ShCM query returns a document that does not contain the CMSISDN in the expected location.
    SuccessfullyRetrievedCMSISDN
| Counter | Incremented when the ShCM query returns a document that does contain a CMSISDN in the expected location.
    ShCacheError
| Counter | Incremented when the ShCM query returns a non-success response code.
    InvalidConfig
| Counter | Incremented when unsupported CMSISDN source is configured.
    CSRNNotDetermined
| Counter | Incremented when the CSRN could not be determined
    CSRNDetermined
| Counter | Incremented when the CSRN could be determined
    CompanionDeviceCSRNsDetermined
| Counter | Incremented when the `CompanionDeviceCSRNs` session state field is set
    ResponseLatency
| Sampled | Records elapsed time between requesting data from the Sh Cache Microservice RA and getting a response (in milliseconds).

== Statistics as part of Registration

These statistics are tracked by the sentinel.registrar SBB and can be found using the parameter set `SLEE-Usage.Services.ServiceID[name=sentinel.registrar,vendor=OpenCloud,version=3.1.0].SbbID[name=sentinel.registrar,vendor=OpenCloud,version=3.1.0].feature.FetchCMSISDN`

Or in REM under the following parameter set:
SLEE-Usage → sentinel.registrar service → sentinel.registrar SBB → feature → FetchCMSISDN

== Statistics as part of INVITE processing

These statistics are tracked by the sentinel.volte.sip SBB and can be found using the parameter set `SLEE-Usage.Services.ServiceID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].SbbID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].feature.FetchCMSISDN`

Or in REM under the following parameter set:
SLEE-Usage → sentinel.volte.sip service → sentinel.volte.sip SBB → feature → FetchCMSISDN

== Configuration

The configuration is scoped according to the Sentinel Selection key, and is stored in the `FetchCMSISDNFeatureConfigProfileTable` profile.

There are four configuration attributes, as follows:

Attribute name | Type | Valid values
--- | --- | ---
    CMSISDNSource
| String | `MSISDN`, or `EXTENDED_MSISDN`
    UDRIncludedIdentities
| String | `IMPU` , or `IMPU_AND_IMPI`
    CSRNPrefix
| String |
    EnableCSRoutingFromRequestURI
| boolean |

Note: If the CMSISDN source is set to `EXTENDED_MSISDN` then the UDRIncludedIdentities must be set to `IMPU_AND_IMPI`.

= Third Party Registration features :indexpage: :sortorder: 50

The General Registrar Features provide general Third Party Registrar support in Sentinel. They are installed out-of-the box in a Sentinel VoLTE installation. The following features support the ESRVCC registration process within VOLTE.

Feature | What it provides
--- | ---
FetchMSRN | Fetches the Mobile Station Roaming Number (MSRN) from the HLR to be included in registration data.
FetchCMSISDN | Fetches the Correlation MSISDN (CMSISDN) from the HSS to be included in registration data and ESRVCC Registration.
ESRVCCRegistration | Implements the ESRVCC registration process (outlined in the Finite State Machine below).
ESRVCCReregistration | Handles ESRVCC re-registration procedures.
Invalidate MMTel Subscriber Data Cache on De-registration | Invalidates the Sh Cache Microservice’s Supplementary Service Data cache entry for the de-registering user.
Load MMTel Subscriber Data Cache on Registration | Warms the Sh Cache Microservice for the registering user’s Supplementary Service Data.

= ESRVCCRegistration :figure-caption!: :toc: macro :toclevels: 4 :toc-title: On this page…​

This feature implements the initial registration procedures for ESRVCC.

== ESRVCC registration process

Figure 1. ESRVCC registration process (Click image to enlarge)

=== ATCF not involved in registration

The ESRVCC registration feature takes no further action and ends.

=== ATCF is involved in registration

- The Feature-Caps header of the first-party REGISTER request includes a number of ATCF-related parameters:

  - `+g.3gpp.atcf`

  - `+g.3gpp.atcf-mgmt`

  - `+g.3gpp.atcf-path`

- The ESRVCC registration feature:

  - queries the HSS to obtain the STN-SR and the C-MSISDN (correlation MSISDN)

  - compares the STN-SR returned by the HSS with the STN-SR that was in the first-party REGISTER request

    - If they are different, the HSS is updated with the STN-SR from the first-party REGISTER request

  - updates the ATCF, passing it the SCC AS’s own ATU-STI and the C-MSISDN, by sending the ATCF a SIP MESSAGE message.

    - The address of the ATCF is taken from the `+g.3gpp.atcf-mgmt` parameter in the Feature-Caps header of the first-party REGISTER request.

    - The body of the SIP MESSAGE has a content type application/vnd.3gpp.SRVCC-info+xml and contains an XML document such as:

          <?xml version="1.0" encoding="UTF-8"?>
          <SRVCC-infos>
              <SRVCC-info ATCF-Path-URI="<sip:termsdgfdfwe@localhost:5560>">
                  <ATU-STI>sip:sccas1.home1.net:5060</ATU-STI>
                  <C-MSISDN>tel:+16505550425</C-MSISDN>
              </SRVCC-info>
          </SRVCC-infos>

| If any of these steps fail (for example, the ATCF update times out, or the HSS returns a failed Answer) the ESRVCC registration feature responds to the registrar core with `rejectRegisterRequest()`.

== Related features

- ESRVCCReregistration handles the re-registration procedures for ESRVCC.

== Prerequisite features

- RegistrarPlatformOperatorIsNetworkOperator OR RegistrarDetermineNetworkOperator

- ExtractEncapsulatedRequestandResponse

- ExtractPublicandPrivateIdentities

- VolteDetermineRegistrationSessionType

== Session state

=== Before …​

SentinelSelectionKey | A selection key with the platform operator, network operator and session type set to ESRVCCRegistration (such as `OpenCloud:OpenCloud:ESRVCCRegistration::`)
EncapsulatedRegisterRequest | The first-party REGISTER request that was in the body of the third-party REGISTER request received by the registrar. The ESRVCC feature processes the Feature-Caps header from the REGISTER request.

=== …​ After

CorrelationMsisdn | The correlation MSISDN retrieved from the HSS
StnSR | The STN-SR from the third-party register request, if it differs from the current HSS state.

== Mappers

This feature uses mappers that conform to:

Mapping | Mapper Execution Point
--- | ---
SentinelRegistrarSessionState.class → OutgoingSipRequest.class | RegistrarMappingPoint.UpdateATCF

== Feature responses

None

== Statistics

ESRVCCRegistration statistics are tracked by the sentinel.registrar SBB and can be found under the following parameter set in REM:
SLEE-Usage → sentinel.registrar service → sentinel.volte.sip SBB → feature → CacheESRVCCRegistration
or with rhino-stats:
"SLEE-Usage.Services.ServiceID[name=sentinel.registrar,vendor=OpenCloud,version=3.1.0].SbbID[name=sentinel.registrar,vendor=OpenCloud,version=3.1.0].feature.CacheESRVCCRegistration"

Parameter | …​ incremented if …​
--- | ---
Started | The feature runs
FailedToStart | A fatal error occurs before feature execution
IssuedWarning | A non-fatal error occurs during feature execution
FailedDuringExecution | A fatal error occurs during feature execution
TimedOut | Feature execution does not complete within a reasonable time frame
MapperErrorSendingPUR | The mapper that creates a ProfileUpdateRequest fails
NetworkErrorSendingPUR | There is a network error sending a ProfileUpdateRequest to the HSS
HssSentErrorPUA | The HSS responded to a ProfileUpdateRequest with an error response
MapperErrorUpdatingATCF | The mapper that creates a SIP MESSAGE message, to pass to the ATCF, fails
NetworkErrorUpdatingATCF | There is a network error sending a SIP MESSAGE message to the ATCF
ATCFRespondsWithSipError | The ATCF responds to a SIP MESSAGE message with an error response
ATCFResponseTimesOut | There is no response to the SIP MESSAGE message sent to the ATCF
RegisterMissingFeatureCAPSHeader | The REGISTER message is missing a Feature-Caps header
RegisterFeatureCAPSHeaderMissingAtcfMgmt | The Feature-Caps header does not contain a `+g.3gpp.atcf-mgmt` parameter

== Error scenarios

The ESRVCC feature increments statistics and responds to the registrar core with `rejectReqisterRequest()` if:

- the REGISTER request is missing essential headers or header parameters

- there is a problem sending a UserDataRequest to the HSS, such as a mapper error creating the message, or a network error sending the message

- there is a problem sending a ProfileUpdateRequest to the HSS, such as a mapper error creating the message, or a network error sending the message

- there is a problem sending a SIP MESSAGE message to the ATCF, such as a mapper error creating the message, or a network error sending the message.

== Configuration

This feature has a configuration profile which determines the user identities used when querying the HSS. The default profile table is named `CacheESRVCCRegistrationConfigProfileTable` and profiles are named with a Sentinel Selection Key e.g. `opencloud::::`. The feature has a Sentinel Feature Configuration page in REM.

Attribute Name | Type | Description
--- | --- | ---
UserIdentityTypeStringForStnSrRequest | An enum with value `PUBLIC_ID` or `CMSISDN` | Determines whether the user’s IMS Public ID or C-MSISDN will be used for their identity when requesting the STN-SR from the HSS.
IncludePrivateIdInStnSrRequest | boolean | Determines whether the user’s IMS Private ID will be included in the request for the STN-SR.

There are also fields relevant to this feature in the RegistrarConfigurationTable table:

AtcfUpdateTimeout | The time (ms) the ESRVCC registration feature should wait for a response from the ATCF.

= ESRVCCReregistration :toc: macro :toclevels: 4 :toc-title: On this page…​

This feature implements the re-registration procedures for ESRVCC.

== Related Features

- ESRVCCRegistration handles the initial registration procedures for ESRVCC.

== Prerequisite Features

- FetchPreviousRegistrationData

== Session Input Variables

Variable name | Type | Description
--- | --- | ---
    PreviousRegistrationData
    List<RegistrationRecord>
| The list of active registration records for the current subscriber and call ID.

== Session Output Variables

Variable name | Type | Description
--- | --- | ---
    CurrentATUSTI
    String
| ATU-STI to be stored in the third-party registrar database.
    AtcfMgmtUri
    String
| ATCF Management URI to be stored in the third-party registrar database.
    AtcfPathUri
    String
| ATCF Path URI to be stored in the third-party registrar database.
    StnSr
    String
| STN-SR to be stored in the third-party registrar database.

== Statistics

ESRVCCReregistration statistics are tracked by the sentinel.registrar SBB and can be found under the following parameter set in REM:
SLEE-Usage → sentinel.registrar service → sentinel.volte.sip SBB → feature → ESRVCCReregistration
or with rhino-stats:
"SLEE-Usage.Services.ServiceID[name=sentinel.registrar,vendor=OpenCloud,version=3.1.0].SbbID[name=sentinel.registrar,vendor=OpenCloud,version=3.1.0].feature.ESRVCCReregistration"

Name | Incremented when…​
--- | ---
Started | The feature is invoked (initial invocation only, not subsequent event triggers).
FailedDuringExecution | The feature fails during execution due to an internal `FeatureError`.
IssuedWarning | The feature issues a warning message.
FailedToStart | A fatal error occurs before feature execution
TimedOut | Feature execution does not complete within a reasonable time frame
ATCFUpdateRequestSent | A `MESSAGE` request is sent to the ATCF.
ATCFUpdateFailed | The `MESSAGE` request fails.
ATCFUpdateSucceeded | The `MESSAGE` request succeeds.

== Configuration

The ESRVCCReregistration feature does not have its own configuration, however it does depend on the Registrar Configuration Table to determine the currently configured value for the ATU-STI, and the length of time to wait for a response from the ATCF (`AtcfUpdateTimeout`).

== Behaviour

The primary function of this feature is to ensure the ATCF will trigger the correct SCC-AS during ESRVCC access transfer. This is may be necessary if re-registrations are sent to an SCC-AS node with a different ATU-STI than the initial (or previous) registration’s ATU-STI.

=== REGISTER trigger

The feature is triggered when the registration session type is determined to be `ESRVCCRegistration` and the registration action type is determined to be `re_register`.

The feature first checks the previous registration data provided by the FetchPreviousRegistrationData feature, searching for a registration record that includes all required ESRVCC registration information. If a record is found, the feature will load the ESRVCC specific data from the record and compare the ATU-STI value in that data to the currently configured ATU-STI for the SCC AS. If no previous ESRVCC registration data can be found, or only partial information can be found, the feature terminates with a `FeatureError`, and no other action is taken.

If the currently configured ATU-STI matches the one in the previous registration record, the feature will have nothing left to do and will terminate normally. If there is a mismatch, the feature will begin the procedure for updating the ATU-STI in the ATCF to match the currently configured value.

The feature starts the update procedure by attempting to generate a SIP `MESSAGE` request towards the ATCF Management URI. The request will have an XML body containing the updated ATU-STI, the ATCF Path URI and the subscriber’s C-MSISDN:

    <?xml version="1.0" encoding="UTF-8"?>
    <SRVCC-infos>
        <SRVCC-info ATCF-Path-URI="<sip:atcf@atcf.example.net:5560>">
            <ATU-STI>sip:scc-as.example.net:5060</ATU-STI>
            <C-MSISDN>tel:+16505550425</C-MSISDN>
        </SRVCC-info>
    </SRVCC-infos>

| the ATCF Path URI, the C-MSISDN and the ATCF Management URI will all be taken from the initial `REGISTER` request for the subscriber NOT the current `re-REGISTER` request (though in practice these values should be identical).

Once the `MESSAGE` request is ready the feature will trigger the request to be sent, and attach to the Activity Context Interface (ACI) for the resulting SIP session. The feature will then terminate and await a response.

=== Response Event Triggers

Any one of three events can trigger the feature at this point: a SIP success response, and SIP error response, or a SIP timeout.

| In all of these cases, when triggered the feature will check that the triggering ACI matches the ACI that was created when the `MESSAGE` request was sent. If there is a mismatch, the feature will log a warning and return to waiting for the correct trigger.

SIP Success Response

If the ATCF replies to the `MESSAGE` request with a SIP `200 OK` response, then the update was successful and the feature will update the session data to reflect the new ATU-STI.

SIP Error Response

If the ATCF replies to the `MESSAGE` request with any SIP error response, the feature will consider the update procedure to have failed and will execute error handling procedures.

SIP Timeout

If the ATCF does not reply to the `MESSAGE` request within the configured time frame, the feature will consider the update procedure to have failed and will execute error handling procedures.

| A timeout will be triggered after a period of time determined by the `AtcfUpdateTimeout` field on the Registrar Configuration Table; by default this is much faster than a standard SIP timeout.

=== Error Handling

If the ATCF update procedure fails at any point (be it from an internal `FeatureError`, a SIP error response, or a SIP timeout) the feature will rewrite the ATU-STI stored in session data to match the ATU-STI of the previous registration. This ensures the third party registrar database contains an accurate representation of the ATU-STI currently in use for the registration in the ATCF.

= Invalidate MMTel Subscriber Data Cache on De-registration

== Description

The purpose of the feature is to invalidate the Sh Cache Microservice’s Supplementary Service Data cache entry for the de-registering user. This feature is intended for use upon De-Registration.

It is related to the Load MMTel Subscriber Data Cache On Registration feature.

== Prerequisite features

- RegistrarPlatformOperatorIsNetworkOperator OR RegistrarDetermineNetworkOperator

- ExtractEncapsulatedRequestandResponse

- ExtractPublicandPrivateIdentities

- VolteDetermineRegistrationSessionType

- DetermineRegistrationActionType

== Session state

=== Before …​

SentinelSelectionKey | A selection key with the platform operator, network operator, session type, and plan-id set. The plan-id must be set to `de-register` (such as `OpenCloud:OpenCloud:ESRVCCRegistration:de-register:`)
CallId | The call-id associate with the activation session
PrivateId | The private-id of the UE

== Feature responses

featureFailedToExecute() | If any exception happens.
featureHasFinished() | Once the feature finishes.

= Load MMTel Subscriber Data Cache on Registration

== Description

The purpose of this feature is to "warm" the Sh Cache Microservice for the Registering User’s MMTel Supplementary Service Data. It issues an Sh-Pull using the served users default public identity. This ensures that the Sh Cache Microservice’s cache is seeded after the registration request is processed.

This feature is intended for use upon Initial Registration.

It is related to the Invalidate MMTel Subscriber Data Cache on De-registration feature.

== Prerequisite features

- RegistrarPlatformOperatorIsNetworkOperator OR RegistrarDetermineNetworkOperator

- ExtractEncapsulatedRequestandResponse

- ExtractPublicandPrivateIdentities

- VolteDetermineRegistrationSessionType

- DetermineRegistrationActionType

== Session state

=== Before …​

SentinelSelectionKey | A selection key with the platform operator, network operator, session type, and plan-id set. The plan-id must be set to `de-register` (such as `OpenCloud:OpenCloud:ESRVCCRegistration:de-register:`)
CallId | The call-id associate with the activation session
PrivateId | The private-id of the UE

== Feature responses

featureFailedToExecute() | If any exception happens.
featureHasFinished() | Once the feature finishes.

= Volte Determine Registration Session Type :toc: macro :toclevels: 4 :toc-title: On this page…​

This feature classifies a REGISTER request according to how it should be handled. For example, is this an ESRVCC registration scenario, or a regular registration scenario?

== Determining the Registration type

The `VolteDetermineRegistrationSessionType` analyses the Feature-Caps header:

- If the `+g.3gpp.atcf`, `+g.3gpp.atcf-mgmt` and `+g.3gpp.atcf-path` parameters are present:

  - the session is classified as eSRVCCRegistration;

- Otherwise, the session is classified as Regular3rdPartyRegistration.

== Details

Feature script name | VolteDetermineRegistrationSessionType
Applicable contexts | SIP service
SAS Support | No
Prerequisite features | Registrar Platform Operator Is Network Operator or Registrar Determine Network Operator

== Session state inputs and outputs

=== Inputs

SentinelSelectionKey | A selection key with the platform operator and network operator set (such as OpenCloud:OpenCloud:::)
EncapsulatedRegisterRequest | The first-party REGISTER request that was in the body of the third-party REGISTER request received by the registrar

=== Outputs

SentinelSelectionKey | A selection key with the platform operator, network operator, and session type set (such as OpenCloud:OpenCloud:eSRVCCRegistration::)

== Feature responses

featureCannotStart() | If the first-party REGISTER request does not contain a Feature-Caps header
featureHasfinished() | Once the feature has finished

== Statistics

Parameter | …​ incremented if …​
--- | ---
MissingFeatureCapsHeader | If the first-party REGISTER request does not contain a Feature-Caps header
ESRVCCRegistration | The session is an eSRVCC registration scenario
Regular3rdPartyRegistration | The session is a regular third-party registration scenario

= CAMEL features :indexpage: :sortorder: 60

The CAMEL Features are used to provide a basis for the SCP functionality in the SCC-AS. These are applicable to CAP triggers. These features are installed out-of-the-box.

= General features :indexpage: :sortorder: 70

The Sentinel product General Features are essentially utility features that are installed out-of-the-box.

The Sentinel VoLTE product does not use the Subscriber Data Lookup and Subscriber Validity features as the General VoLTE Features are used instead. These features may be used when customising Sentinel VoLTE.

= CDMA Reorigination Service :sortorder: 4 :toc: macro :toclevels: 4 :toc-title: On this page…​

| This service is for CDMA networks.

This CDMA Reorigination service receives CDMA OriginationRequest and AnalyzedInformation triggers, stores reorigination information, and is able to forward the call such that it is routed into the IMS .

It enables processing circuit-switched originating calls in the SCC-AS.

Reorigination for terminating calls can be bypassed if the subscriber is not registered in the IMS network.

There is a related feature (SCCCDMAReOrigination) that is part of service centralization in the IMS.

For this feature’s fit into the overall flow, please see the Reorigination basic flow diagram.

== Configuration

Configuration for the CDMA Reorigination Service is in a profile 'cdma-configuration' in the profile table `CDMAServiceConfigurationProfileTable`.

=== CDMAServiceConfigurationProfileTable

Attribute | Type | Default Value | Meaning
--- | --- | --- | ---
    SupportedAnalyzedInformationTriggerList
| String |
    'local-Call,local-Toll-Call,non-Local-Toll-Call,world-Zone-Call,international-Call,unrecognized-Number,prior-Agreement,specific-Called-Party-Digit-String,mobile-Termination,advanced-Termination,location'
| Supported terminating triggers in an AnalyzedInformation (comma separated list of CDMATriggerTypes)
    ActionOnUnsupportedTrigger
| String |
    accessDeniedReason_terminationDenied
| action to take when an unexpected trigger is received
    ActionOnFailedToAllocateRoutingNumber
| String |
    accessDeniedReason_busy
| action to take when there is a failure generating a routing number
    DefaultFailureAction
| String |
    accessDeniedReason_serviceDenied
| default action to take on error
    IMRNTypeOfDigits
| String |
    DIALED_OR_CALLED_PARTY_NUMBER
| The type of digits field of the IMRN generated
    IMRNNatureOfNumber
| String |
    INTERNATIONAL
| The nature field of the IMRN generated
    IMRNNumberingPlan
| String |
    TELEPHONY
| The numbering plan field of the IMRN generated
    BypassReoriginationIfNotRegistered
| Boolean |
    true
| If true, reorigination is skipped if the subscriber is not registered in the IMS network

=== Network operator data

Common network configuration data is stored in a profile table named `SCCCommonReOriginationConfigProfileTable`.

For more information, see the shared configuration between the SCCCDMAReOrigination feature and the CDMA reorigination service.

== Use of Correlation resource adaptor

For information about use of the Correlation RA, please see the shared Correlation RA.

== Statistics

CDMA reorigination statistics are collected by the 'volte.sentinel.cdma' SBB and can be found using the parameter set

`SLEE-Usage.Services.ServiceID[name=volte.sentinel.cdma,vendor=OpenCloud,version=3.1.0].SbbID[name=volte.sentinel.cdma,vendor=OpenCloud,version=3.1.0]`

Or in REM under the following parameter sets:
SLEE-Usage → Services → volte.sentinel.cdma service → volte.sentinel.cdma

Parameter | Type | Description
--- | --- | ---
    ConfigurationProfileTableMissing
| Counter | Incremented if the configuration profile table is missing
    ConfigurationProfileMissing
| Counter | Incremented if the configuration profile is missing
    FailedToEncodeRequest
| Counter | Incremented if there is a failure encoding the incoming request for the correlation RA
    NoAvailableCorrelationEntries
| Counter | Incremented if there are no free correlation entries
    OriginatingTreatment
| Counter | Incremented on an originating trigger
    TerminatingTreatment
| Counter | Incremented on a terminating trigger
    UnsupportedDialogOpenRequest
| Counter | Incremented on receipt of a Unidirectional dialog
    FailedToAcceptDialog
| Counter | Incremented if there is an error accepting the incoming dialog
    FailedToRefuseDialog
| Counter | Incremented if there is an error refusing the incoming dialog
    AnalyzedInformationErrorResponseSent
| Counter | Incremented if an error response is sent
    OriginationRequestErrorResponseSent
| Counter | Incremented if an error response is sent
    FailedToSendAnalyzedInformationResponse
| Counter | Incremented if there is a failure whilst sending an error response
    FailedToSendOriginationResponse
| Counter | Incremented if there is a failure whilst sending an error response
    UnsupportedTrigger
| Counter | Incremented if the trigger type of an AnalyzedInformation request is not supported
    UnsupportedCallType
| Counter | Incremented if the call scenario is not mobile originating or mobile terminating
    InvalidOriginationRequest
| Counter | Incremented if the called and calling parties cannot be determined
    InvalidAnalyzedInformation
| Counter | Incremented if the called and calling parties cannot be determined
    CassandraQueryResultReceived
| Counter | Incremented if 3rd-party registration lookup result received from Cassandra
    SubscriberNotRegistered
| Counter | Incremented if subscriber is not registered
    SubscriberRegistered
| Counter | Incremented if subscriber is registered
    CassandraError
| Counter | Incremented if error returned by Cassandra during 3rd-Party registration lookup
    CassandraQueried
| Counter | Incremented if 3rd-Party registration lookup invoked

== Reoriginating the call

The service is triggered with an `OriginationRequest` or an `AnalyzedInformation`. The service then attempts to reoriginate the call (that is, forward the call into the IMS). The steps involved are explained in the following sections.

1. The configuration data used is indexed by the `Sentinel Selection Key` (as in most places in Sentinel). The first step is to build a sentinel selection key, by using platform level configuration to get the name of the platform operator. In the current release the network operator field is set to the name of the platform operator. This selection key is used for all subsequent configuration lookup.

2. Find configuration, with a sentinel selection key based search. If there is no configuration, reject the session with `accessDeniedReason` of `unavailable`.

=== On OriginationRequest (ORREQ)

1. Check the OriginationRequest has all required fields to identify the calling and called parties. If not, send an OriginationRequest response based on the ActionOnUnsupportedTrigger configuration property.

2. Encode the OriginationRequest into a `byte[]` that can be stored by the correlation RA. If this fails, send an OriginationRequest response based on the ActionOnFailedToAllocateRoutingNumber configuration property.

3. Direct the Correlation resource adaptor entity to allocate a reorigination address. This address will be used for routing the call onwards. The Correlation resource adaptor entity records the allocated correlation number and the encoded OriginationRequest. These are used later, in the CDMA Reorigination SIP feature.

4. Build a destination routing address, using the address returned by the Correlation RA, and the configuration for the address’s `TypeOfDigits`, `NatureOfNumber` and `NumberingPlan` fields. The network configuration for a prefix is used if the network configuration indicates a prefix is required. This address is called the “IP Multimedia Routing Number”, or IMRN for short.

5. Send an OriginationRequest response with the IMRN in the `TerminationList`, and close the TCAP dialog.

=== On AnalyzedInformation (ANLYZD)

1. Check the `trigger type` against supported triggers in configuration. If the trigger is not supported, send an AnalyzedInformation response based on the ActionOnUnsupportedTrigger configuration property.

2. For supported AnalyzedInformation triggers, check the call is Mobile Originating (MO) or Mobile Terminating (MT). If not, send an AnalyzedInformation response based on the ActionOnUnsupportedTrigger configuration property.

| The call is MT if the trigger type is `mobile-Termination`, `advanced-Termination` or `location`. All other calls are MO, unless `RedirectingNumberDigits`, `RedirectingPartyName` or `RedirectingSubaddress` is present, in which case the call is MF (Mobile Forwarded).

1. Check the AnalyzedInformation has all required fields to identify the calling and called parties. If not, send an AnalyzedInformation response based on the ActionOnUnsupportedTrigger configuration property.

2. Execute the CDMA reorigination bypass feature.

   - If `BypassReoriginationIfNotRegistered` = `True`, construct a normalized IMRN from the `digits` address value in the ANLYZD message and perform a 3rd-Party registration lookup in Cassandra.

     - If no registration record is found, send an empty AnalyzedInformation response so the call can continue without reorigination.

     - If an expired registration record is found, send an empty AnalyzedInformation response so the call can continue without reorigination.

     - If a current registration record is found, continue to the next step.

     - If Cassandra returns an error/failure or no response, continue to the next step.

   - If `BypassReoriginationIfNotRegistered` = `False`, continue to the next step.

3. Encode the AnalyzedInformation into a `byte[]` that can be stored by the correlation RA. If this fails, send an AnalyzedInformation response based on the ActionOnFailedToAllocateRoutingNumber configuration property.

4. Direct the Correlation resource adaptor entity to allocate a reorigination address. This address will be used for routing the call onwards. The Correlation resource adaptor entity records the allocated correlation number and the encoded AnalyzedInformation. These are used later, in the CDMA Reorigination SIP feature.

5. Build a destination routing address, using the address returned by the Correlation RA, and the configuration for the address’s `TypeOfDigits`, `NatureOfNumber` and `NumberingPlan` fields. The network configuration for a prefix is used if the network configuration indicates a prefix is required. This address is called the “IP Multimedia Routing Number”, or IMRN for short.

6. Send an AnalyzedInformation response with the IMRN in the `TerminationList`, and close the TCAP dialog.

= Mappers :sortorder: 4 :toc: macro :toclevels: 4 :toc-title: On this page…​

VOLTE uses mappers as it processes third-party REGISTER requests.

The General Registrar Mappers provide general Third Party Registrar support in Sentinel. They are installed out-of-the box in a Sentinel VoLTE installation. The following mappers support the ESRVCC registration process within VOLTE.

| For an overview of what mappers are and how they work, please see Mappers in the Sentinel documentation.

== Mapper execution points

The Registrar searches for mappers at the following mapper execution points:

Mapper Execution Point | Role of mappers at this point
--- | ---
UpdateATCF | Building a SIP MESSAGE message to the ATCF.

| See the `enum com.opencloud.sentinel.mapper.RegistrarMappingPoint` in the `sentinel-sip-registrar-common` module.

== Mappers included with VOLTE

`SessionStateToSipMessage`

From …​ | …​ To | Description
--- | --- | ---
SentinelRegistrarSessionState | OutgoingSipRequest | Builds a SIP MESSAGE message that is passed to the ATCF during ESRVCC processing.

= Mapping of GSMA IR.92 to Sentinel VoLTE Features :sortorder: 5

Supplementary Service | Sentinel VoLTE support | Sentinel VoLTE feature
--- | --- | ---
Originating Identification Presentation 3GPP TS 24.607 | Yes | MMTelOIP
Terminating Identification Presentation 3GPP TS 24.608 | Yes | MMTelTIP
Originating Identification Restriction 3GPP TS 24.607 | Yes | MMTelOIR
Terminating Identification Restriction 3GPP TS 24.608 | Yes | MMTelTIR
Communication Forwarding Unconditional 3GPP TS 24.604 | Yes | MMTelCDIV
Communication Forwarding on not Logged in 3GPP TS 24.604 | Yes | MMTelCDIV
Communication Forwarding on Busy 3GPP TS 24.604 | Yes | MMTelCDIV
Communication Forwarding on not Reachable 3GPP TS 24.604 | Yes | MMTelCDIV
Communication Forwarding on No Reply 3GPP TS 24.604 | Yes | MMTelCDIV
Barring of All Incoming Calls 3GPP TS 24.611 | Yes | MMTelICB
Barring of All Outgoing Calls 3GPP TS 24.611 | Yes | MMTelOCB
Barring of Outgoing International Calls 3GPP TS 24.611 | Yes | MMTelOCB
Barring of Outgoing International Calls — ex Home Country 3GPP TS 24.611 | Yes | MMTelOCB
Barring of Outgoing International Calls — When Roaming 3GPP TS 24.611 | Yes | MMTelOCB
Barring of Incoming Calls - When Roaming 3GPP TS 24.611 | Yes | MMTelICB
Communication Hold 3GPP TS 24.610 | Yes | MMTelHold
Message Waiting Indication 3GPP TS 24.606 | N/A | No MMTelAS requirements
Communication Waiting 3GPP TS 24.615 | Yes | MMTelCW
Ad-Hoc Multi Party Conference 3GPP TS 24.605 | Yes | MMTel Conference

= Provisioning :indexpage: :sortorder: 6

You provision Sentinel VoLTE using the Sentinel VoLTE Element Manager, which provides a web interface and machine API.

The Sentinel VoLTE Element Manager is an extension of the Rhino Element Manager (REM). See Installing the Sentinel VoLTE Provisioning Module to install the Sentinel VoLTE provisioning module in REM.

For general information on using Rhino Element Manager, see the Rhino Element Manager User Guide.

To provision Sentinel VoLTE, see the procedures to:

- Provision Sentinel VoLTE using the REST API

- Provision Sentinel VoLTE using the Web Interface

- Working with CDRs

- Configure Auditing of Provisioning Operations (Sentinel)

- Configure the Sentinel VoLTE XCAP Server

= Provisioning Web Interface

The provisioning web interface appears as an extension inside the Rhino Element Manager (REM) web application.

Using Rhino Element Manager

For general information on using REM, see the Rhino Element Manager User Guide. To use the Sentinel provisioning web interface and machine API you will, at minimum, need to configure a Rhino instance in REM.

To access the Sentinel VoLTE provisioning interface in REM:

1 | Open a browser, and enter the URL of the REM server where the Sentinel REM extension has been installed (for example, http://localhost:8080/rem).
2 | Enter your REM login credentials (the default account credentials are `emadm` / `password`).
3 | Select Manage a Rhino Element.
4 | Connect to the Rhino instance where Sentinel VoLTE is installed.
5 | Select one of the options from the Sentinel menu.

For documentation on each of the VoLTE Sentinel panels, please see the following links:

Menu item(s) | Link
--- | ---
Session Plans | Managing Session Plans (Sentinel)
Feature Execution Scripts | Managing Feature Execution Scripts (Sentinel)
HSS Subscriber Data | REM HSS Transparent Data Editor (VoLTE)
Feature Configuration Service Configuration Sentinel Core Configuration | Configuring Features, Services, Sentinel Core, and Promotions (Sentinel)
Mappers | Managing Mappers (Sentinel)
Plans Session Types Subscriptions | Managing Plans, Session Types, and Subscriptions (Sentinel)
Correlation | Managing Correlation Resource Adaptor Entities (Sentinel)
XCAP and XCAP - Simservs | XCAP Server (VoLTE)
HSS Configuration | Configuring the Sh Cache Microservice Client for the XCAP Server and REM (VoLTE)

= Sentinel VoLTE and Data :indexpage: :sortorder: 7

Sentinel VoLTE has several uses of data, and different types of data.

== Types of data

The data Sentinel VoLTE uses can broadly be described as fitting one of the following three classifications:

- Platform data — typically indicating configuration data for the platform and its services

- Network operator data— feature configuration for the platform

- Subscriber data — stored as transparent user data in the HSS.

- Data Stored by the Third Party Registrar in HSS— stored as transparent data in the HSS.

== Configuration topics

This section covers the following configuration topics:

- Editing Transparent User Data in the HSS

- Configuring the Sh Cache Microservice Client for the XCAP Server and REM

- Sh Cache Microservice RA configuration

= Platform Data :sortorder: 1

Platform data includes, but is not limited to:

- Sentinel services and feature code

- Sentinel services configuration and feature configuration

- Protocol stacks and resource adaptors, and associated configuration

- Rhino Service Interaction Server and its configuration

- Rhino TAS configuration.

== Service configuration

Sentinel service configuration is stored in JSLEE configuration profiles. It includes multiple configuration areas, notably:

- Sentinel’s core configuration

- Sentinel’s mediation-layer configuration (configuration for online charging)

- configuration common to SS7 and SIP services

- Sentinel’s SIP Sentinel configuration.

= Network Operator Data :sortorder: 2

Network Operator data is used to configure Features.

As an example, the MMTelHold feature has the ability to play an announcement when the Session is placed on hold. This Feature configuration information is referred to as Network Operator Data. It is persisted by the Platform.

Each installation contains a single platform operator, and a single network operator.

Multi-tenancy of Network Operators is supported through each Network Operator having their own TAS cluster.

= Subscriber Data :sortorder: 3

In Sentinel VoLTE, subscriber data is stored either as transparent user data in the HSS or in the HLR.

When using HSS, it is accessed through:

- session processing

- the XCAP Server

- the REST Provisioning API

- and various screens in REM.

When using HLR, it is accessed through:

- session processing

Session processing uses the Sh Cache Microservice RA via the SubscriberDataLookupFromHSS feature or CGIN RA via SubscriberDataLookupFromHLR.

For more information, see Sh Cache Microservice RA configuration and Supplementary Service Data Access.

= Data Stored by the Third Party Registrar in HSS :sortorder: 4

== Overview

The default option for Registrar Data Storage uses Transparent Data in the HSS through the Diameter Sh interface. Documents stored in the HSS conform to an OpenCloud defined XML schema. During the Sentinel VoLTE installation the user is asked to choose between using an HSS or a Cassandra Database as the data repository technology.

== How it works

The HSS storage system creates, updates and removes documents from the HSS as appropriate based on SIP User Agent registration life cycle, catering for cases such as simultaneous registration of shared IMS public identities. Documents are created/updated/removed using an access of an IMS Public Identity and Service Indication of `opencloud-3rd-party-registrar`.

During INVITE processing, the IMSIDLookup feature uses the Served User’s IMS Public Identity and Service Indication of `opencloud-3rd-party-registrar` as the Diameter Sh Access Key.

It then populates Session State according to documents found in HSS storage. Both the HSS storage system, and the IMSIDLookup use the Sh Cache Microservice RA to interface to the HSS.

== Data Schema

The schema used by OpenCloud for Third Party Registration is shown below.

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

    <xs:schema targetNamespace="http://opencloud.com/sentinel/registrar/xml"
               xmlns:ss="http://opencloud.com/sentinel/registrar/xml"
               xmlns:xs="http://www.w3.org/2001/XMLSchema"
               version="1.0"
            >
        <xs:element name="publicId">
            <!-- Use an anonymous type so xjc will add an XmlRootElement to the generated PublicId class. -->
            <xs:complexType>
                <xs:sequence>
                    <xs:element maxOccurs="unbounded" minOccurs="0" name="registration"   type="ss:RegistrationData"/>
                    <xs:element maxOccurs="unbounded" minOccurs="0" name="reverseMapping" type="ss:ReverseMapping"/>
                </xs:sequence>
                <xs:attribute default="false" name="default" type="xs:boolean" use="optional"/>
                <xs:attribute name="id" type="xs:string" use="required"/>
            </xs:complexType>
        </xs:element>
        <xs:complexType name="EsrvccData">
            <xs:sequence>
                <xs:element name="cmsisdn" type="xs:string"/>
                <xs:element name="gruu" type="xs:string"/>
                <xs:element name="tempGruu" type="xs:string"/>
                <xs:element name="stnSr" type="xs:string"/>
                <xs:element name="isUeSrvccCapable" default="false" type="xs:boolean"/>
                <xs:element name="currentAtuSti" type="xs:string"/>
                <xs:element name="atcfMgmtUri" type="xs:string"/>
                <xs:element name="atcfPathUri" type="xs:string"/>
            </xs:sequence>
        </xs:complexType>
        <xs:complexType name="ReverseMapping">
            <xs:sequence>
                <xs:element maxOccurs="1" minOccurs="0" name="validityTime" type="ss:ValidityTime"/>
            </xs:sequence>
            <xs:attribute name="callId" type="xs:string" use="required"/>
            <xs:attribute name="defaultPublicId" type="xs:string" use="required"/>
        </xs:complexType>
        <xs:complexType name="Extension">
            <xs:sequence>
                <xs:element maxOccurs="1" minOccurs="1" name="key" type="xs:string"/>
                <xs:element maxOccurs="1" minOccurs="1" name="value" type="xs:string"/>
            </xs:sequence>
        </xs:complexType>
        <xs:complexType name="Extensions">
            <xs:sequence>
                <xs:element maxOccurs="unbounded" minOccurs="0" name="extension" type="ss:Extension"/>
            </xs:sequence>
        </xs:complexType>
        <xs:complexType name="RegistrationData">
            <xs:sequence>
                <xs:element name="privateId" type="xs:string"/>
                <xs:element maxOccurs="unbounded" name="publicIds" type="xs:string"/>
                <xs:element maxOccurs="unbounded" name="contact" type="xs:string"/>
                <xs:element name="validityTime" type="ss:ValidityTime"/>
                <xs:element name="visitedNetworkId" type="xs:string"/>
                <xs:element maxOccurs="unbounded" name="pAccessNetworkInfo" type="xs:string"/>
                <xs:element maxOccurs="1" minOccurs="0" name="esrvcc" type="ss:EsrvccData"/>
                <xs:element maxOccurs="1" minOccurs="0" name="extensions" type="ss:Extensions"/>
            </xs:sequence>
            <xs:attribute name="callId" type="xs:string" use="required"/>
        </xs:complexType>
        <xs:complexType name="ValidityTime">
            <xs:sequence>
                <xs:element name="created" type="xs:dateTime"/>
                <xs:element name="expires" type="xs:duration"/>
            </xs:sequence>
        </xs:complexType>
    </xs:schema>

== Configuration

The Diameter Sh interface is configured during the VoLTE installation.

== Statistics

The statistics are updated during the processing of the feature.

Parameter | …​ incremented if …​
--- | ---
failedToAddRegistrationData | Could not add a registration.
failedToAddReverseMappings | Could not decode the registration data.
failedToRemoveRegistrationData | Could not remove the registration data.
failedToRemoveReverseMappings | Could not remove the decoder for the registration data.
noDataToRemoveForDefaultPubicIdAndCallId | No registration found under the specified callid.
noDataToRemoveForDefaultPublicId | No registration foung undet the specified public id.
noMappingToRemoveForPubicIdAndCallId | Could not find any mapping associated to the specified callid.
noMappingToRemoveForPublicId | Could not find any mapping associated to the specified public id.

For Third Party Registration, the statistics are tracked by the sentinel.registrar SBB and can be found using the parameter set `SLEE-Usage.Services.ServiceID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].SbbID[name=registrar.subscribers.hsscache,vendor=OpenCloud,version=3.1.0]`

= REM HSS Transparent Data Editor :toc: macro :toclevels: 4 :toc-title: On this page…​ :figure-caption!: :sortorder: 4

The REM HSS Transparent Data Editor lets you use a web browser to view and edit HSS transparent user data.

== How it works

The web interface communicates with a web application hosted by Rhino Element Manager, which communicates with the HSS through the Sh Cache Microservice. Administrators can use it to:

- view provisioned data

- configure important settings

- add new data to the HSS

- remove data from the HSS.

== Prerequisites

Before using the editor, you need to configure:

- an appropriate HSS configuration for the network operator

- required settings for MMTel services.

For more information on Operator Determined Barring see Operator Determined Barring.

== Using the Data Editor

To use the Data Editor:

1 | From REM’s monitoring screen, select Sentinel ▶ HSS Subscriber Data. It may take a few seconds before the screen appears on first load. It should look like this:
2 | Follow the procedures to load or view, edit, or remove transparent data for an IMS public identity.

=== Load or view transparent data for an IMS public identity

| The HSS that the Editor queries depends on which network you’ve chosen. These instructions assume that, before loading data, you have configured the HSS address for the network operator.

To load or view data:

1 | Type the IMS public identity into the IMS User Identity field, and click the Load button. HSS Subscriber Data displays.

If there’s an error — for example, because the HSS is unavailable, the network operator is not configured properly, or the data cannot be parsed — a red-coloured error message will display in the panel, and red text in the log below. In the following example, a Sentinel network operator called ‘SteveInc’ has not been configured properly.

=== Edit transparent data for an IMS public identity

To edit data that you’ve loaded in the Editor:

1 | Click the Edit button. Fields become editable.
2 | Make your changes, depending on the field type.
Field type | How to edit | Example
--- | --- | ---
Boolean | select from a list |
    CDIV Active
integer | enter in a text box |
    CDIV No Reply Timer
complex XML | enter in a resizable text box, with basic XML validation (checks that the XML is well-formed) Click and drag the lower right corner to resize. |
    CDIV Rules
enumeration | select one of N values |
    OIR Default Behaviour
3 | Click the Save button at the lower right. If entered data is validated and saved successfully to the HSS, a green message displays in the panel and REM log. If saving fails, a red message displays in the panel and log. In the following example, the XML is not well-formed (in the `CDIV Rules` attribute), so REM rejects the user’s input before attempting to reach the HSS.

==== Add companion devices in transparent data for an IMS public identity

Companion devices can be added or edited in the step 2 listed above. Here is an example for adding a companion device that can use PS radio (VoLTE/VoWifi) and CS radio at the given MSISDN.

Field | Example
--- | ---
CD Active | true
CD Devices |
    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <devices xmlns="http://metaswitch.com/XMLSchema/tas">
        <device>
            <model>Acme Watch</model>
            <radio-access>
                <PS/>
                <CS msisdn="641234568"/>
            </radio-access>
        </device>
    </devices>
CD Hide | true
CD Operator Additional Attributes | null
CD Operator Authorized | true
CD SharedSipUri | sip:+641234567@example.com
CD SharedTelUri | tel:+641234567
CD User Additional Attributes | null

| It is recommended that both `SharedSipUri` and `SharedTelUri` are provisioned to a subscriber, in order to be used for properly determining the undisclosed identity. Those values are used in DetermineSharedAndUndisclosedIdentities and Hide Undisclosed Identity features. The XML for `CD Devices` needs to match the schema shown in `DeviceType`, otherwise the data won’t be able to be provisioned properly in HSS.

=== Remove transparent data for an IMS public identity

To remove data that you’ve loaded in the Editor:

1 | Click the Delete button ( ). The editor prompts you to confirm the deletion.
2 | Click OK. The panel becomes blank, and a green message displays in the REM log below.

== Required configuration for MMTel

To edit HSS transparent user data so it can use OpenCloud’s out-of-the-box IR.92 features, follow the manual configuration steps below.

| The `sentinel-volte-mappings-config` tool will carry out these steps for you. See Populate XCAP server settings and MMTel service data.

1 | Select Sentinel ▶ HSS Subscriber Data.
2 | Once the data’s loaded, select the Provisioning Field Mappings tab.
| not the Subscriber Data Editor tab!
3 | Click the Add Field Group button. A prompt displays to enter details.
4 | Fill in the following values — either by typing, or by selecting the text box and pressing the down arrow on your keyboard to select these default values:
Field | Default
--- | ---
Service indication |
    MMTEL-Services
Service data class |
    com.opencloud.volte.sentinel.simservs.xcap.TMMTelServicesType
Service data codec class |
    com.opencloud.volte.sentinel.provisioning.hss.TMMTelServicesCodec
JXPath factory class |
    com.opencloud.volte.sentinel.simservs.xcap.MMTelJXPathFactory
And select OK.
5 | Once the field group for MMTEL-Services has been added, select it; and click the Add Field button to add the following fields:
Field | Type | Description
--- | --- | ---
Xpath
OIP Active |
    java.lang.Boolean
| Whether or not originating identity presentation is active for this user. Refer to documentation for the ‘unset’ value.
    complete-originating-identity-presentation/originating-identity-presentation/@active
OIP Authorized |
    java.lang.Boolean
| Whether or not Originating Identity Presentation is authorized for this user. The Authorized indicator is present in the Operator Data, so it is not visible to the subscriber.
    complete-originating-identity-presentation/operator-originating-identity-presentation/@authorized
OIR Active |
    java.lang.Boolean
| Whether or not originating identity presentation restriction is active for this user. Refer to documentation for the ‘unset’ value
    complete-originating-identity-restriction/originating-identity-presentation-restriction/@active
OIR Authorized |
    java.lang.Boolean
| Whether or not Originating Identity Presentation Restriction is authorized for this user. The Authorized indicator is present in the Operator Data, so it is not visible to the subscriber.
    complete-originating-identity-restriction/operator-originating-identity-presentation-restriction/@authorized
OIR Default Behaviour |
    com.opencloud.volte.sentinel.simservs.xcap. OriginatingIdentityPresentationRestriction$DefaultBehaviourType
| Default behaviour value
    complete-originating-identity-restriction/originating-identity-presentation-restriction/default-behaviour
TIR Default Behaviour |
    com.opencloud.volte.sentinel.simservs.xcap. TerminatingIdentityPresentationRestriction$DefaultBehaviourType
| Default behaviour value
    complete-terminating-identity-restriction/terminating-identity-presentation-restriction/default-behaviour
TIP Active |
    java.lang.Boolean
| Whether or not Terminating Identity Presentation is active for this user. Refer to documentation for the ‘unset’ value
    complete-terminating-identity-presentation/terminating-identity-presentation/@active
TIP Authorized |
    java.lang.Boolean
| Whether or not Terminating Identity Presentation is authorized for this user. The Authorized indicator is present in the Operator Data, so it is not visible to the subscriber.
    complete-terminating-identity-presentation/operator-terminating-identity-presentation/@authorized
TIR Active |
    java.lang.Boolean
| Whether or not Terminating Identity Presentation Restriction is active for this user. Refer to documentation for the ‘unset’ value
    complete-terminating-identity-restriction/terminating-identity-presentation-restriction/@active
TIR Authorized |
    java.lang.Boolean
| Whether or not Terminating Identity Presentation Restriction is authorized for this user. The Authorized indicator is present in the Operator Data, so it is not visible to the subscriber.
    complete-terminating-identity-restriction/operator-terminating-identity-presentation-restriction/@authorized
ICB Active |
    java.lang.Boolean
| Whether or not Incoming Communication Barring is active for this user. Refer to documentation for the ‘unset’ value
    complete-communication-barring/incoming-communication-barring/@active
ICB Authorized |
    java.lang.Boolean
| Whether or not Incoming Communication Barring is authorized for this user. The Authorized indicator is present in the Operator Data, so it is not visible to the subscriber.
    complete-communication-barring/operator-incoming-communication-barring/@authorized
OCB Active |
    java.lang.Boolean
| Whether or not Outgoing Communication Barring is active for this user. Refer to documentation for the ‘unset’ value
    complete-communication-barring/outgoing-communication-barring/@active
OCB Authorized |
    java.lang.Boolean
| Whether or not Outgoing Communication Barring is authorized for this user. The Authorized indicator is present in the Operator Data, so it is not visible to the subscriber.
    complete-communication-barring/operator-outgoing-communication-barring/@authorized
CW Active |
    java.lang.Boolean
| Whether or not Communication Waiting is active for this user. Refer to documentation for the ‘unset’ value
    complete-communication-waiting/communication-waiting/@active
CW Authorized |
    java.lang.Boolean
| Whether or not Communication Waiting is authorized for this user. The Authorized indicator is present in the Operator Data, so it is not visible to the subscriber.
    complete-communication-waiting/operator-communication-waiting/@authorized
CDIV Active |
    java.lang.Boolean
| Whether or not Communication Diversion is active for this user. Refer to documentation for the ‘unset’ value
    complete-communication-diversion/communication-diversion/@active
CDIV Authorized |
    java.lang.Boolean
| Whether or not Communication Diversion is authorized for this user. The Authorized indicator is present in the Operator Data, so it is not visible to the subscriber.
    complete-communication-diversion/operator-communication-diversion/@authorized
CDIV No Reply Timer |
    java.lang.Integer
| Communication Diversion no reply timer
    complete-communication-diversion/communication-diversion/NoReplyTimer
CDIV Rules |
    com.opencloud.volte.sentinel.common.policy.Ruleset
| Communication Diversion rules
    complete-communication-diversion/communication-diversion/ruleset
ICB Rules |
    com.opencloud.volte.sentinel.common.policy.Ruleset
| Incoming Communication Barring rules
    complete-communication-barring/incoming-communication-barring/ruleset
OCB Rules |
    com.opencloud.volte.sentinel.common.policy.Ruleset
| Outgoing Communication Barring rules
    complete-communication-barring/outgoing-communication-barring/ruleset
Flexible Alerting Group Type |
    com.opencloud.volte.sentinel.simservs.xcap.OperatorFlexibleAlertingGroup$GroupType
| Whether the type of the group is single-user or multiple-users. For single user, the pilot number is busy if one of the members is busy. For multiple-user’s the pilot number is busy when all members are busy.
    complete-flexible-alerting/operator-flexible-alerting-group/group-type
Flexible Alerting Membership Type |
    com.opencloud.volte.sentinel.simservs.xcap.OperatorFlexibleAlertingGroup$MembershipType
| The membership type specifying whether a member is allowed to unsubscribe from the group or not. ‘Permanent’ means not allowed.
    complete-flexible-alerting/operator-flexible-alerting-group/membership
Flexible Alerting Group Members |
    com.opencloud.volte.sentinel.simservs.xcap.OperatorFlexibleAlertingGroup$Members
| The identities of the members that belong to this group
    complete-flexible-alerting/operator-flexible-alerting-group/members
Flexible Alerting Pilot Number |
    com.opencloud.volte.sentinel.common.policy.IdentityType
| The URI that defines the flexible alerting group and triggers the feature to activate.
    complete-flexible-alerting/operator-flexible-alerting-group/identity
Flexible Alerting Group Authorized |
    java.lang.Boolean
| Whether or not Flexible Alerting is authorized for this group. The Authorized indicator is present in the Operator Data, so it is not visible to the subscriber.
    complete-flexible-alerting/operator-flexible-alerting-group/@authorized
Flexible Alerting Authorized |
    java.lang.Boolean
| Whether or not Flexible Alerting is authorized for this user. The Authorized indicator is present in the Operator Data, so it is not visible to the subscriber.
    complete-flexible-alerting/operator-flexible-alerting/@authorized
Explicit Communication Transfer Authorized |
    java.lang.Boolean
| Whether or not Explicit Communication Transfer is authorized for this user. The Authorized indicator is present in the Operator Data, so it is not visible to the subscriber.
    complete-explicit-communication-transfer/operator-explicit-communication-transfer/@authorized
Operator CDIV Rules |
    com.opencloud.volte.sentinel.common.policy.Ruleset
| Operator Communication Diversion rules
    complete-communication-diversion/operator-communication-diversion/ruleset
Operator CDIV Maximum Diversion Count |
    java.math.BigInteger
| Operator Communication Diversion maximum diversion count
    complete-communication-diversion/operator-communication-diversion/total-number-of-diversions-for-each-communication
Operator CDIV No Reply Timer |
    java.lang.Integer
| Operator Communication Diversion no reply timer
    complete-communication-diversion/operator-communication-diversion/communication-forwarding-on-no-reply-timer
Communication Hold Authorized |
    java.lang.Boolean
| Whether or not Communication Hold is authorized for this user. The Authorized indicator is present in the Operator Data, so it is not visible to the subscriber.
    complete-communication-hold/operator-communication-hold/@authorized
Conferencing Authorized |
    java.lang.Boolean
| Whether or not Conferencing is authorized for this user. The Authorized indicator is present in the Operator Data, so it is not visible to the subscriber.
    complete-conference/operator-conference/@authorized

To delete a field: select it, and click the that displays next to it.

|6 |Click Save.

|7 |Once you have finished adding, editing, and/or removing fields — for the changes to take effect — disconnect from REM, and then log in again

== Active flags information There is special behaviour for each service’s "active" attribute. This is described in the Active attributes portion of the architecture document. The user interface has three possible values for each services active flag: * `Unset` means that the XML document does not have an active attribute for this service * `True` means that the attribute exists and has the value `true`, * `False` means that the attribute exists and has the value `false` == Required configuration for Operator Determined Barring To edit HSS transparent user data so it can use OpenCloud’s out-of-the-box IR.92 features: [cols="1h,99a"]

|1 |Select Sentinel ▶ HSS Subscriber Data.

|2 |Once the data’s loaded, select the Provisioning Field Mappings tab.

| not the Subscriber Data Editor tab!

|3 | Click the Add Field Group button.

A prompt displays to enter details.

|4 |Fill in the following values — either by typing, or by selecting the text box and pressing the down arrow on your keyboard to select these default values:

And select OK.

|5 |Once the field group for IMS-ODB-Information has been added, select it; and click the Add Field button to add the following fields:

None of these fields are required.

To delete a field: select it, and click the that displays next to it.

|6 |Click Save.

|7 |Once you have finished adding, editing, and/or removing fields — for the changes to take effect — disconnect from REM, and then log in again

== Required configuration for Metaswitch TAS Services To edit HSS transparent user data so it can use Metaswitch TAS Services custom document [cols="1h,99a"]

|1 |Select Sentinel ▶ HSS Subscriber Data.

|2 |Once the data’s loaded, select the Provisioning Field Mappings tab.

| not the Subscriber Data Editor tab!

|3 | Click the Add Field Group button.

A prompt displays to enter details.

|4 |Fill in the following values — either by typing, or by selecting the text box and pressing the down arrow on your keyboard to select these default values:

And select OK.

|5 |Once the field group for Metaswitch-TAS-Services has been added, select it; and click the Add Field button to add the following fields:

The `Operator Authorized Flag` fields are required. All other fields are optional.

To delete a field: select it, and click the that displays next to it.

|6 |Click Save.

|7 |Once you have finished adding, editing, and/or removing fields — for the changes to take effect — disconnect from REM, and then log in again

:leveloffset!: :ocdoc_current_file: /mnt/volume-01/jenkins/workspace/product/sentinel/sentinel-volte-documentation/release-3.1.0/Auto/volte-documentation/target/generated/sentinel-volte-administration-guide/sentinel-volte-and-data/configuring-sh-cache-microservice-client-for-the-xcap-server-and-rem.adoc :here: sentinel-volte-and-data/ :idprefix: configuring-the-sh-cache-microservice-client-for-the-xcap-server-and-rem :leveloffset: 1 = Configuring the Sh Cache Microservice Client for the XCAP Server and REM :toc: macro :toclevels: 4 :toc-title: On this page…​ :sortorder: 5 This section describes configuration of the Sh Cache Microservice Client stack instance(s) inside the Rhino EM Web Application. [TIP] .Architecture reference

For background on the architecture related to the instructions below, please read the XCAP Support page.

== Sh Cache Microservice Client stack configuration

As seen in XCAP Support, the Sh Cache Microservice Client stack is used by the XCAP Server and Rhino EM’s Web User interface.

Instances of the stack are configured through REM:

1 | Navigate to Sentinel ▶ HSS Configuration. The Sh Cache Microservice Client Instance Configuration page displays.
2 | Specify entries in the other fields to configure key parameters. See Configure the Sh Cache Microservice RA for more details about the various parameters.
| Click the ? help button next to a field for a description of that parameter.

Configuring the Sh Cache Microservice Client stack configures an instance of this stack unique to the Rhino cluster that your REM session is logged into.

This means that when an administrator uses the HSS Transparent Data Editor, since they’ve logged into a Rhino cluster, the associated Sh Cache Microservice Client stack instance in REM will be selected.

Also, when processing an XCAP request, the XCAP Server will find the Rhino cluster to use, as it queries this for some settings. The Sh Cache Microservice Client stack instance is then selected by the Rhino cluster’s linked Sh Cache Microservice Client stack instance.

= Session Processing :indexpage: :sortorder: 8 :toc: macro :toclevels: 4 :toc-title: On this page…​

Session processing includes topics related to how the Sentinel VoLTE product executes various different call flows.

- Selection of MMTel and SCC functionality— how the different AS functions are able to be selected through URI parameters

- Selection of charging mode— how online/offline charging is selected through URI parameters

- Initial Filter Criteria— example Initial Filter Criteria for use with Sentinel VoLTE

- Session Processing and the Use of HSS— how Sentinel VoLTE makes use of the HSS

- Service Compositions— selection of services that execute on each SIP session

- Sentinel VoLTE Session Plans— selection of features that execute inside a SIP session

- Custom Headers— OpenCloud defined headers that influence session processing behaviour

Out of the box, the Sentinel VoLTE product can:

- function as an SCC-AS, or an MMTel-AS for a given trigger

- function as a combined SCC+MMTel-AS off a single trigger, thereby optimising performance.

- perform offline charging only

- perform online charging, through either acting as a Charging Trigger Function using Diameter Ro, or CAP (using the IM-SSF)

These different configurations are all available on a per-trigger basis, rather than being a "hard configuration mode".

Online charging via the CAP interface is delivered through the use of OpenCloud’s IM-SSF, and is an optionally installed component.

== Selection of MMTel and SCC functionality through the Application Server URI

Different modes of operation (e.g. MMTel functionality, or SCC functionality) are determined through parameters added to the Application Server URI during initial filter criteria (iFC) configuration.

When the Sentinel VoLTE application server receives an initial SIP request (for example, an initial INVITE or third-party register request) parameters are present on the topmost route header. There are certain parameters that can be added to alter the behaviour of Sentinel VoLTE. That is to say, the iFC and application server configuration in the HSS may include URI parameters that select different sets of behaviour from the Sentinel VoLTE product.

Session plans are available that enable execution of MMTel and SCC feature sets in different combinations. These are selected through the use of the `oc-mode` parameter.

The specific URI parameters are discussed in the Custom Headers section.

| For a high-level view of the architecture, see Instance Architecture for Sentinel VoLTE. For a detailed description of the format of the `oc-mode` parameter, see the DetermineVoltePlanId feature page.

== Selection of charging mode

The system charging mode can be set to:

- offline only, meaning the system only writes CDRs and/or Diameter Accounting Requests (ACRs)

- online charging via Diameter Ro, meaning that the system acts as a charging trigger function towards the OCS as well as writing CDRs and/or ACRs

- online charging via CAMEL, meaning it includes an IM-SSF component that triggers a prepaid service control point via the CAP protocol.

The charging mode is selected through the `oc-charge-mode` parameter. This is an Application Server URI parameter.

| For detailed descriptions of the `oc-charge-mode` parameter, see the DetermineChargeMode and Service Compositions pages.

The VoLTE Interim CDR Feature is configured to select whether interim CDRs and/or ACRs are used. It is used if Diameter Rf and/or Interim CDRs are selected during installation.

= Initial Filter Criteria

Initial Filter Criteria (iFC) is the mechanism used by the IMS to invoke Application Servers. It applies to SIP initial requests.

Sentinel VoLTE defines various Route Header Parameters such that the iFC can select specific behaviour from the Sentinel VoLTE applications.

For example, SCC or MMTel functionality, or influencing the T-ADS routing mode are selected through the use of Route Header Parameters.

== Requirements for Sentinel VoLTE iFC

The iFC requirements can be met through various different iFC configurations. The purpose of this section is to cover the requirements.

=== INVITE related

==== Registered and Un-Registered Service Point Triggers

Both the MMTel and SCC require INVITE processing for originating, terminating, and the registered and un-registered cases. There are not any particular headers that are able to be used to "narrow" which INVITEs the SCC or MMTel receive such that they are triggered in certain cases only (unlike e.g. a voice-mail service that is only triggered on terminating INVITEs to a PSI).

Session Case | Consumers of case
--- | ---
Originating Registered | SCC Originating Signalling Anchor for access transfer, MMTel Originating Features
Originating Un-Registered | MMTel Originating Features in case of and unregistered originating party. This is typical when using IMS centralised services without I2. I.e. a non IMS-registered user making an outgoing Circuit Switched call that is routed into the IMS for service control.
Terminating Registered | SCC Terminating Signalling Anchor for access transfer, SCC T-ADS, MMTel Terminating Features
Terminating Un-Registered | SCC T-ADS, MMTel Terminating features (e.g CDIV Not Logged In)

==== INVITE trigger chaining

VoLTE calls can be processed sequentially by both the MMTel-AS and SCC-AS with INVITE iFC chaining. iFCs are chained together by associating the same Trigger Point (group of one or more SPTs) with multiple AS in a specific order.

The SCC-AS must be the first SIP-AS in the originating iFC trigger chain and last in the terminating iFC trigger chain. I.e it "wraps" the other SIP-AS nodes, and is the "closest" AS to the served UE. Therefore it directly observes the true SIP Dialog Identifier used between the IMS core and the served UE.

=== Third Party Registration Service Point Triggers

SCC-AS requires third party registration, as both eSRVCC and T-ADS functionality need access to (for example) the IMS private identity. MMTel-AS also requires third party registration so that it can access the default IMS public identity.

Typically the SCC-AS and MMTel-AS are co-located on the same TAS. In this case, there must be only one Third Party Registration request sent to the TAS. The TAS then performs appropriate logic for the MMTel and SCC functions based on the single request. Multiple distinct Third Party Registration requests should only be sent to the SCC-AS and MMTel-AS when the functions are not co-located on the same TAS.

Registration Case | Consumers of case | Needs first party registration content
--- | --- | ---
Initial Registration | SCC for eSRVCC registration and T-ADS. MMTel for default public identity. | Both first-party request and response
Re-registration | SCC for eSRVCC re-registration and T-ADS (e.g. P-Access-Network-Info). MMTel to refresh its registration data. | Both first-party request and response
De-registration | SCC and MMTel to clean up registration state database | Both first-party request and response

| Depending on your HSS, the configuration for including first-party request and response messages could be on the iFC or the associated AS.

=== MMTel Conferencing Service Point Triggers

MMTel Conferencing requires that the Conference Focus has a URI termed the Conference Factory Public Service Identity, or Conference Factory PSI for short.

Both Invites and Subscriptions to the Conference Factory PSI are implemented at the Conference Focus within the MMTel-AS.

Therefore the iFC for Conferencing needs to ensure that SIP SUBSCRIBE and INVITE sessions where the Request URI host part matches the host part of the Conference Factory PSI trigger the MMTel-AS.

== Trigger examples

Due to the nature of the iFC XML, and that `Method` and `SessionCase` elements are part of a choice (meaning one or the other can be specified inside an `SPT`) sometimes logical OR is used for different `SPT` elements inside a `Trigger`, and sometimes logical AND is used.

=== SCC-AS INVITE Trigger

The following XML fragment shows the use a single `Trigger` element to capture the various INVITE cases for the SCC-AS.

    <?xml version="1.0"?>

    <!-- this is a snippet of an iFC showing only the Trigger elements necessary for SCC-AS INVITE processing -->

    <!-- An example of INVITE trigger point for SCC-AS -->
    <TriggerPoint>
        <!-- ConditionTypeCNF 0 means logical AND of SPT elements in the same group ConditionTypeCNF 1 means logical OR of SPT elements the same group See TS 29.228 for Conjunctive Normal Form vs Disjunctive Normal Form SPT elements in different groups are AND'd together -->
        <ConditionTypeCNF>1</ConditionTypeCNF>

        <!-- logically the statement is INVITE AND (ORIGINATING_REGISTERED OR TERMINATING_REGISTERED OR TERMINATING_UNREGISTERED) -->
        <SPT>
            <Group>0</Group>
            <Method>INVITE</Method>
        </SPT>
        <SPT>
            <Group>1</Group>
            <SessionCase>0</SessionCase><!-- ORIGINATING_REGISTERED -->
        </SPT>
        <SPT>
            <Group>1</Group>
            <SessionCase>1</SessionCase><!-- TERMINATING_REGISTERED -->
        </SPT>
        <SPT>
            <Group>1</Group>
            <SessionCase>2</SessionCase><!-- TERMINATING_UNREGISTERED -->
        </SPT>
    </TriggerPoint>

=== SCC-AS Third Party Register Trigger

The following XML fragment shows the use of a `Trigger` element that includes all three cases of Third Party registration.

    <?xml version="1.0"?>

    <!-- this is a snippet of an iFC showing only the Trigger element necessary for Third Party Registration -->

    <!-- Initial Register OR Re-register OR de-register -->
    <TriggerPoint>
        <!-- there is only a single SPT so ConditionTypeCNF is not important yet it is a mandatory element so it is here as 1-->
        <ConditionTypeCNF>1</ConditionTypeCNF>
        <!-- Register, re-register and de-register -->
        <SPT>
            <Group>4</Group>
            <Method>REGISTER</Method>
        </SPT>
        <Extension>
            <RegistrationType>0</RegistrationType> <!-- INITIAL_REGISTRATION -->
            <RegistrationType>1</RegistrationType> <!-- RE_REGISTRATION -->
            <RegistrationType>2</RegistrationType> <!-- DE_REGISTRATION -->
        </Extension>

    </TriggerPoint>

=== MMTel-AS INVITE Trigger

The following XML fragment shows the use of a single `Trigger` element to invoke the MMTel-AS for all INVITE sessions except those going to voicemail.

    <?xml version="1.0"?>

    <!-- this is a snippet of an iFC showing only the Trigger elements necessary for MMTel-AS INVITE processing -->

    <!-- An example of INVITE trigger point for MMTel-AS excluding voicemail All MMTel services will be served on the same AS here -->
    <TriggerPoint>
        <!-- ConditionTypeCNF 0 means logical AND of SPT elements in the same group ConditionTypeCNF 1 means logical OR of SPT elements the same group See TS 29.228 for Conjunctive Normal Form vs Disjunctive Normal Form SPT elements in different groups are OR'd togethered -->
        <ConditionTypeCNF>1</ConditionTypeCNF>

        <!-- MMTel needs INVITEs for all SessionCases Voicemail is often not implemented on the same MMTel-AS platform Therefore exclude the voicemail AS, assuming it has a URI of voicemail.example.com Logically this is INVITE AND NOT (RequestURI equals voicemail.example.com) -->
        <SPT>
            <Group>0</Group>
            <Method>INVITE</Method>
        </SPT>
        <SPT>
            <ConditionNegated>1</ConditionNegated> <!-- Use ConditionNegated to exclude the RequestURI -->
            <Group>2</Group>
            <RequestURI>voicemail.example.com</RequestURI>
        </SPT>
    </TriggerPoint>

=== MMTel-AS SUBSCRIBE Trigger

The following XML fragment shows the use of a `Trigger` element to invoke the MMTel-AS for subscriptions to the Conference Factory PSI.

    <?xml version="1.0"?>

    <!-- this is a snippet of an iFC showing only the Trigger for subscriptions to the Conf Factory PSI -->

    <TriggerPoint>
        <!-- ConditionTypeCNF 0 means logical AND of SPT elements in the same group ConditionTypeCNF 1 means logical OR of SPT elements the same group See TS 29.228 for Conjunctive Normal Form vs Disjunctive Normal Form SPT elements in different groups are OR'd togethered -->
        <ConditionTypeCNF>1</ConditionTypeCNF>

        <!-- Logically this is SUBSCRIBE AND (RequestURI host part equals conf.example.com) -->
        <SPT>
            <Group>0</Group>
            <Method>SUBSCRIBE</Method>
        </SPT>
        <SPT>
            <Group>1</Group>
            <RequestURI>conf.example.com</RequestURI>
        </SPT>
    </TriggerPoint>

== Recommendations for Application Server element

An iFC document joins an Application Server and zero or more Trigger Point elements. Each Trigger Point element includes one or more Service Trigger Points (SPTs). These are discussed above.

This section discusses recommendations for the Application Server section.

=== Use a TCP transport

The default SIP transport mechanism for AS communication is UDP. TCP can be specified by appending `;transport=tcp` to the configured AS URI.

=== AS functional separation

One Sentinel VoLTE TAS instance can handle both SCC-AS and MMTel-AS roles. However it is possible to logically separate the roles onto their own instance or node. This can be useful for non-functional reasons such as sizing, or functional reasons such as debugging.

This is achieved with the `oc-mode` parameter as part of the AS URI. The `mmtel` oc-mode handles MMTel and Conferencing. Conferencing traffic can be diverted to its own node via iFC association.

For example, to split MMTel, SCC and MMTel-Conferencing traffic on such that they are on distinct ports 5060, 5070 and 5080.

Role | AS URI | Associated TP / iFC
--- | --- | ---
MMTel | sip:<volte-tas-address>:5060;transport=tcp;oc-mode=mmtel | MMTel iFCs
SCC | sip:<volte-tas-address>:5070;transport=tcp;oc-mode=scc | SCC iFCs
MMTel-Conferencing | sip:<volte-tas-address>:5080;transport=tcp;oc-mode=mmtel | Conf iFC

For each configured AS it is possible to assign further specific functions through the use of Route Header Parameters

== iFC examples

These examples provide a full initial filter criteria including `TriggerPoint` and `ApplicationServer` elements.

=== SCC-AS INVITE

The SCC-AS is invoked in three INVITE cases

1. originating

2. terminating registered

3. terminating un-registered

These can be shown in a single iFC for the INVITE case

    <?xml version="1.0"?>
    <InitialFilterCriteria>
        <Priority>2</Priority>
        <TriggerPoint>
            <!-- ConditionTypeCNF 0 means logical AND of SPT elements in the same group ConditionTypeCNF 1 means logical OR of SPT elements the same group See TS 29.228 for Conjunctive Normal Form vs Disjunctive Normal Form SPT elements in different groups are AND'd together -->
            <ConditionTypeCNF>1</ConditionTypeCNF>

            <!-- logically the statement is INVITE AND (ORIGINATING_REGISTERED OR TERMINATING_REGISTERED OR TERMINATING_UNREGISTERED) AND NOT (Recv-Info Header equals 'g.3gpp.ussd') -->
            <SPT>
                <Group>0</Group>
                <Method>INVITE</Method>
            </SPT>
            <SPT>
                <Group>1</Group>
                <SessionCase>0</SessionCase><!-- ORIGINATING_REGISTERED -->
            </SPT>
            <SPT>
                <Group>1</Group>
                <SessionCase>1</SessionCase><!-- TERMINATING_REGISTERED -->
            </SPT>
            <SPT>
                <Group>1</Group>
                <SessionCase>2</SessionCase><!-- TERMINATING_UNREGISTERED -->
            </SPT>
            <SPT>
                <ConditionNegated>1</ConditionNegated>
                <Group>2</Group>
                <SIPHeader>
                    <Header>Recv-Info</Header>
                    <Content>g.3gpp.ussd</Content>
                </SIPHeader>
                <Extension/>
            </SPT>
        </TriggerPoint>
        <ApplicationServer>
            <ServerName>sip:scc-as.domain.name:5060;transport=tcp;oc-mode=scc</ServerName>
            <DefaultHandling>1</DefaultHandling>
            <Extension>
                <IncludeRegisterRequest/>
                <IncludeRegisterResponse/>
            </Extension>
        </ApplicationServer>
    </InitialFilterCriteria>

=== MMTel-AS INVITE

An example showing the iFC for an MMTel-AS for INVITE requests is below.

    <?xml version="1.0"?>
    <InitialFilterCriteria>
        <Priority>2</Priority>
        <TriggerPoint>
            <!-- ConditionTypeCNF 0 means logical AND of SPT elements in the same group ConditionTypeCNF 1 means logical OR of SPT elements the same group See TS 29.228 for Conjunctive Normal Form vs Disjunctive Normal Form SPT elements in different groups are AND'd together -->
            <ConditionTypeCNF>1</ConditionTypeCNF>

            <!-- MMTel needs INVITEs for all SessionCases Voicemail is often not implemented on the same MMTel-AS platform Therefore exclude the voicemail AS, assuming it has a URI of voicemail.example.com Logically this is INVITE AND NOT (RequestURI equals voicemail.example.com) AND NOT (Recv-Info Header equals 'g.3gpp.ussd') -->
            <SPT>
                <Group>0</Group>
                <Method>INVITE</Method>
            </SPT>
            <SPT>
                <ConditionNegated>1</ConditionNegated> <!-- Use ConditionNegated to exclude the RequestURI -->
                <Group>2</Group>
                <RequestURI>voicemail.example.com</RequestURI>
            </SPT>
            <SPT>
                <ConditionNegated>1</ConditionNegated>
                <Group>3</Group>
                <SIPHeader>
                    <Header>Recv-Info</Header>
                    <Content>g.3gpp.ussd</Content>
                </SIPHeader>
                <Extension/>
            </SPT>
        </TriggerPoint>
        <ApplicationServer>
            <ServerName>sip:mmtel-as.domain.name:5060;transport=tcp;oc-mode=mmtel</ServerName>
            <DefaultHandling>1</DefaultHandling>
            <Extension>
                <IncludeRegisterRequest/>
                <IncludeRegisterResponse/>
            </Extension>
        </ApplicationServer>
    </InitialFilterCriteria>

Note: if the MMTel-AS will run the MMTel-Conferencing feature (ie. not the discrete conferencing example) then the iFC needs to also include SUBSCRIBE requests where the RequestURI matches the host name part of the conference factory PSI.

=== MMTel-AS SUBSCRIBE

If the MMTel-AS is running the MMTel-Conferencing feature, rather than a discrete MMTel-Conferencing AS node, then the MMTel-AS needs to receive SUBSCRIBE requests for the Conference Factory PSI.

An example is shown

    <?xml version="1.0"?>
    <InitialFilterCriteria>
        <Priority>2</Priority>
        <TriggerPoint>
            <!-- ConditionTypeCNF 0 means logical AND of SPT elements in the same group ConditionTypeCNF 1 means logical OR of SPT elements the same group See TS 29.228 for Conjunctive Normal Form vs Disjunctive Normal Form SPT elements in different groups are OR'd togethered -->
            <ConditionTypeCNF>1</ConditionTypeCNF>
            <!-- Logically this is SUBSCRIBE AND (RequestURI host part equals conf.example.com) -->
            <SPT>
                <Group>0</Group>
                <Method>SUBSCRIBE</Method>
            </SPT>
            <SPT>
                <Group>1</Group>
                <RequestURI>conf.example.com</RequestURI>
            </SPT>
        </TriggerPoint>
        <ApplicationServer>
            <ServerName>sip:mmtel-as.domain.name:5060;transport=tcp;oc-mode=mmtel</ServerName>
            <DefaultHandling>1</DefaultHandling>
            <Extension>
                <IncludeRegisterRequest/>
                <IncludeRegisterResponse/>
            </Extension>
        </ApplicationServer>
    </InitialFilterCriteria>

=== Third Party Registration example

The following example adds triggers for REGISTER request, for:

- initial registration

- re-registration

- de-registration

When sending the third-party register request, both the first party register request and response are included.

    <?xml version="1.0"?>
    <!-- sip registration IFC -->
    <InitialFilterCriteria>
        <Priority>1</Priority>

        <!-- Initial Register OR Re-register OR de-register -->
        <TriggerPoint>
            <!-- there are three SPTs, and we want OR, so ConditionTypeCNF 1 -->
            <ConditionTypeCNF>1</ConditionTypeCNF>

            <!-- Register -->
            <SPT>
                <Group>0</Group>
                <Method>REGISTER</Method>
                <Extension>
                    <RegistrationType>0</RegistrationType> <!-- INITIAL_REGISTRATION -->
                </Extension>
            </SPT>

            <!-- re-register -->
            <SPT>
                <Group>0</Group>
                <Method>REGISTER</Method>
                <Extension>
                    <RegistrationType>1</RegistrationType> <!-- RE_REGISTRATION -->
                </Extension>
            </SPT>

            <!-- de-register -->
            <SPT>
                <Group>0</Group>
                <Method>REGISTER</Method>
                <Extension>
                    <RegistrationType>2</RegistrationType> <!-- DE_REGISTRATION -->
                </Extension>
            </SPT>

        </TriggerPoint>
        <ApplicationServer>
            <ServerName>sip:third-party-registrar:5060;transport=tcp</ServerName>
            <DefaultHandling>0</DefaultHandling>
            <Extension>
                <IncludeRegisterRequest/>
                <IncludeRegisterResponse/>
            </Extension>
        </ApplicationServer>
    </InitialFilterCriteria>

=== Discrete Conferencing Example

Sentinel VoLTE implements many MMTel Services, including MMTel Conferencing. It may be useful to configure the Conference as a different set of VMs than the rest of MMTel, for example for sizing reasons.

If so, this iFC for conferencing can be defined.

    <?xml version="1.0"?>
    <!-- Conferencing IFC MMTel Conferencing requires SUBSCRIBE and INVITE requests to the Conference Factory PSI -->
    <InitialFilterCriteria>
        <Priority>2</Priority>

        <!-- Logically (INVITE OR SUBSCRIBE) AND (RequestURI host part equals conf.example.com) AND Terminating Unregistered -->
        <TriggerPoint>
            <ConditionTypeCNF>1</ConditionTypeCNF>
            <SPT>
                <Group>0</Group>
                <Method>INVITE</Method>
            </SPT>
            <SPT>
                <Group>0</Group>
                <Method>SUBSCRIBE</Method>
            </SPT>
            <SPT>
                <Group>1</Group>
                <RequestURI>conf.example.com</RequestURI>
            </SPT>
            <SPT>
                <Group>2</Group>
                <SessionCase>2</SessionCase> <!-- Terminating Unregistered -->
            </SPT>
        </TriggerPoint>
        <ApplicationServer>
            <ServerName>sip:conf-as.example.com:5060;transport=tcp;oc-mode=mmtel</ServerName>
            <DefaultHandling>0</DefaultHandling>
        </ApplicationServer>
    </InitialFilterCriteria>

Note: if MMTel-Conferencing is provided on a different node, then the Conference Factory PSI should be excluded from the MMTel-AS Trigger.

=== Excluding services

There are cases where there are services that are not implemented on a particular SIP-AS. If there are no other distinguishing characteristics of the INVITE (such as for MMTel) then any Public Service Identifiers for services that are not implemented on the MMTel-AS should be excluded. If there are distinguishing characteristics, such as a unique SIP header, these can be used for exclusion.

- Example - Voicemail AS

Add a negated condition specifying a Service Point Trigger where the URI is the host-part of the PSI for the VoiceMail service. An example is shown below.

        <SPT>
          <ConditionNegated>1</ConditionNegated>
          <Group>3</Group>
          <RequestURI>voicemail.example.com</RequestURI>
        </SPT>

- Example - USSI AS

Sentinel VoLTE does not implement the role of a USSI Application Server. As USSD over IMS requests are signalled using SIP INVITE, and MMTel and SCC AS are signalled using INVITE, a negated condition is added to the iFC for Sentinel VoLTE. USSI INVITE requests contain a Recv-Info header with the value `g.3gpp.ussd`.

An example is shown below.

        <SPT>
           <ConditionNegated>1</ConditionNegated>
           <Group>4</Group>
           <SIPHeader>
               <Header>Recv-Info</Header>
               <Content>g.3gpp.ussd</Content>
           </SIPHeader>
           <Extension/>
       </SPT>

Note: each excluded service should be in a Group that is independent of the other groups. This is because SPTs in different groups are AND’ed together.

= Session Processing and the Use of HSS :toc: macro :toclevels: 4 :toc-title: On this page…​ :sortorder: 2

== XML schemas in use

Standard Name | 3GPP TS | 3GPP Release version | Specific document version
--- | --- | --- | ---
Extensible Markup Language (XML) Configuration Access Protocol (XCAP) over the Ut interface for Manipulating Supplementary Services | 3GPP TS 24.623 | Release 11 | 11.1.0
Flexible Alerting (FA) using IP Multimedia (IM) Core Network (CN) subsystem | 3GPP TS 24.239 | Release 11 | 11.0.0
Originating Identification Presentation (OIP) and Originating Identification Restriction (OIR) using IP Multimedia (IM) Core Network (CN) subsystem | 3GPP TS 24.607 | Release 11 | 11.2.0
Terminating Identification Presentation (TIP) and Terminating Identification Restriction (TIR) using IP Multimedia (IM) Core Network (CN) subsystem | 3GPP TS 24.608 | Release 11 | 11.2.0
Communication Diversion (CDIV) using IP Multimedia (IM) Core Network (CN) subsystem | 3GPP TS 24.604 | Release 11 | 11.5.0
Anonymous Communication Rejection (ACR) and Communication Barring (CB) using IP Multimedia (IM) Core Network (CN) subsystem | 3GPP TS 24.611 | Release 11 | 11.2.0
Universal Mobile Telecommunications System (UMTS); LTE; IMS Operator Determined Barring | 3GPP TS 24.315 | Release 12 | 12.1.0
Digital cellular telecommunications system (Phase 2+) (GSM); Universal Mobile Telecommunication System (UMTS); LTE; Explicit Communication Transfer (ECT) using IP Multimedia (IM) Core Network (CN) subsystem; Protocol specification | 3GPP TS 24.629 | Release 12 | 12.7.0

There is no user data in the schema for the following features defined in the standards at the time of writing:

- Communication Hold/Resume

- 3PTY CONF

== Data references used by MMTEL

- Data Reference of RepositoryData (0)

- Service indications of:

  - “MMTEL-Services”

  - “opencloud-3rd-party-registrar”

== Data references used by SCC

eSRVCC Registration features

- MSISDN or MSISDN+ExtendedMSISDN (17)

- STN-SR (27)

- UE-SRVCC-Capability (28)

CAMEL/IMS Reorigination

- S-CSCFName (12)

T-ADS

- UE Reachability for IP (25)

- T-ADS Information (26)

== Sh protocol capabilities

- Single data reference in a query

- No use of “eff” features

- Sh schema from Sh rel-11 (vb60) i.e 3GPP TS 29.328 Rel-11 version 11.6.0

= Service Compositions :sortorder: 3

Sentinel VoLTE is a set of JSLEE services.

| For background, see Sentinel VoLTE Architecture.

A SIS service composition sends SIP signaling to the correct service. Sentinel VoLTE comes with three compositions pre-configured for different requirements:

- The default composition just invokes the VoLTE service:

  Figure 2. Standard VoLTE composition

- The other two compositions support CAP-based charging. This functionality is enabled by configuring the iFC to send an additional parameter in the AS URI called `oc-charge-mode` and setting its value to `cap`. The following diagrams illustrate the originating and terminating cases:

  Figure 3. Mobile Originating
  Figure 4. Mobile Terminating

For terminating CAP-based charging calls the IM-SSF service is invoked between SCC TADS and SCC Term Anchor to allow the user to be charged appropriately for the access network type (i.e. PS or CS).

== Listing the service compositions

You can list the services compositions by accessing the `sis-console`, normally under the volte installation path `sis/admin` and use the commands `listcompositions` and `dumpcomposition`. See the example below. The output may change for different releases.

    [Rhino@localhost (#0)] listcompositions sip-sis-ra

    CompositionID[name=SentinelVolteAndRegistrarOriginatingComposition,vendor=OpenCloud,version={majorversion}]
    CompositionID[name=SentinelVolteAndRegistrarTerminatingComposition,vendor=OpenCloud,version={majorversion}]

    [Rhino@localhost (#5)] dumpcomposition sip-sis-ra name=SentinelVolteAndRegistrarOriginatingComposition,vendor=OpenCloud,version={majorversion}
    <?xml version="1.0" encoding="UTF-8" standalone="no"?><composition xmlns="http://www.opencloud.com/SIS/Composition" xmlns:in="http://www.opencloud.com/SIS/Composition/IN" xmlns:sip="http://www.opencloud.com/SIS/Composition/SIP" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opencloud.com/SIS/Composition/SIP sip-sis-composition-1.6.xsd http://www.opencloud.com/SIS/Composition/IN in-sis-composition-1.6.xsd http://www.opencloud.com/SIS/Composition sis-composition-1.6.xsd">

        <composition-name>SentinelVolteAndRegistrarOriginatingComposition</composition-name>
        <composition-vendor>OpenCloud</composition-vendor>
        <composition-version>{majorversion}</composition-version>

        <script>
            <if>
                <equal>
                    <value value="${method}"/>
                    <value value="REGISTER"/>
                </equal>
                <then>
                    <!-- Invoke Registrar -->
                    <invoke on-timeout="ignore-service-and-continue" service="sentinel.registrar"/>
                </then>
                <else>
                    <if>
                        <equal a="${oc-mode}" b="mmtel-scc"/>
                        <then>
                            <!-- Invoke SCC -->
                            <invoke on-timeout="ignore-service-and-continue" service="sentinel.volte.sip">
                                <service-input-interceptor>
                                    <delete variable="${oc-mode}"/>
                                    <assign toVariable="${oc-mode}" value="scc"/>
                                </service-input-interceptor>
                            </invoke>

                            <!-- Invoke MMTel -->
                            <invoke on-timeout="ignore-service-and-continue" service="sentinel.volte.sip">
                                <service-input-interceptor>
                                    <delete variable="${oc-mode}"/>
                                    <assign toVariable="${oc-mode}" value="mmtel"/>
                                </service-input-interceptor>
                            </invoke>
                        </then>
                        <else>
                            <!-- Invoke VoLTE -->
                            <invoke on-timeout="ignore-service-and-continue" service="sentinel.volte.sip"/>
                        </else>
                    </if>
                </else>
            </if>

            <delete variable="${oc-mode}"/>
        </script>

        <debug-level>0</debug-level>
        <audit>false</audit>
    </composition>

== Creating and modifying service compositions

Service compositions are part of the OpenCloud Service Interaction SLEE (SIS). For more information on how to create and modify service compositions refer to SIS Documentation.

= Sentinel VoLTE Session Plans :indexpage: :toc: macro :toclevels: 4 :toc-title: On this page…​ :sortorder: 4

Sentinel VoLTE Session Plans define the system’s behaviour, and enable customisation.

== Sentinel VoLTE Session Plans

For out of the box Session Plans and their Feature Execution Scripts, please see Built-In session plans.

== Modifying the system through Session Plans

Sentinel VoLTE provides an implementation of core VoLTE standards as features. These features may be enhanced, replaced or even by-passed.

In order to add new features, replace features, or customise existing features it makes sense to read Sentinel Session Plans and Feature Execution Scripts. These “wire together” multiple features to form services that MMTel AS and SCC AS provide.

Both session plans and feature execution scripts are scoped via a Sentinel Selection Key. This provides flexibility, in allowing different combinations of features on a single platform. For example, you might want to have sets of features associated with different plans.

Sentinel successively falls back to a broader scoping of the selection key, to load the feature execution script for processing a session. Ultimately the least specific portion of the selection key, the platform operator, is used to load a feature execution script.

Feature execution scripts can change on-the-fly. For example, when an administrator changes a feature execution script, it can be used in processing subsequent sessions without a restart.

=== Different session plans for different types of sessions

Sentinel supports session plans for various different types of services:

- SIP INVITE-based session processing — see Session Plans for the SIP Service

- SS7 CAMEL-triggered session plan — see Session Plans for the SS7 Service

- Third-party Registration session plans — described in 3rd Party Registration Session Plans

=== Editing session plans and feature execution scripts using REM

Sentinel product documentation covers the basics for:

- Managing Session Plans

- Managing Feature Execution Scripts^

= Built-in Session Plans :toc: macro :toclevels: 4 :toc-title: On this page…​

== SIP INVITE session plans

Some session plans can be executed on an `INVITE`.

| Details on how they are selected can be found in the documentation for the DetermineVoltePlanId feature.

The session plans are:

Plan ID | Executed by
mmtel-orig | MMTel AS serving the originating user
mmtel-term | MMTel AS serving the terminating user
mmtel-conf | MMTel AS providing conferencing (MMTelCONF) functionality
scc-orig | SCC AS serving the originating user
scc-term | SCC AS serving the terminating user
scc-term-anchor | SCC AS serving the terminating user but only executing access transfer functions
scc-term-tads | SCC AS serving the terminating user but only executing T-ADS functions
scc-access-transfer | SCC AS on receiving an access transfer request
scc-reorigination | SCC AS on receiving a reorigination request

== SIP REGISTER session plans

The Registrar uses the session type and plan ID portion of the selection key in order to simplify the feature execution scripts that run for different types of third-party registration.

The main two features that do this are:

- VolteDetermineRegistrationSessionType— sets the session type to one of `eSRVCCRegistration` or `Regular3rdPartyRegistration`

- DetermineRegistrationActionType— sets the plan ID to one of `register`, `re-register`, or `de-register`.

Session type | Plan ID | Executed by
--- | --- | ---
    Regular3rdPartyRegistration
    register
| MMTel AS with third-party registrar
    Regular3rdPartyRegistration
    re-register
| MMTel AS with third-party registrar
    Regular3rdPartyRegistration
    de-register
| MMTel AS with third-party registrar
    eSRVCCRegistration
    register
| SCC AS with third-party registrar
    eSRVCCRegistration
    re-register
| SCC AS with third-party registrar
    eSRVCCRegistration
    de-register
| SCC AS with third-party registrar

Registration session plans for `register` and `re-register` distinguish the features that they execute. The `register` session plans are intended to execution upon Initial Registration into the IMS, whereas `re-register` corresponds to registration refreshes. Examples of features that should run on Initial Registration but not registration refresh are FetchCMSISDN, or ESRVCCRegistration

== IN session plan

Sentinel VoLTE uses minimal feature execution scripts for IN call processing — they exist purely for the purpose of IMS service centralization. This will result in the call being connected to an IP Multimedia Routing Number (IMRN) and the TCAP dialog being closed; no online charging request will be made as part of InitialDP processing.

These feature execution scripts run in the SS7 sessions initiated via the CAMEL IDP session plan. For more information refer to Service Centralisation Features.

== Viewing session plans

The list of execution points and their associated feature scripts can be viewed through REM by selecting the Management→Profiles menu, then selecting the `${PLATFORM_OPERATOR_NAME}_FeatureExecutionScriptTable` table. Here the variable `${PLATFORM_OPERATOR_NAME}` is replaced by the Platform Operator Name chosen at installation time. So if the Platform Operator Name was set to "Rocket" the table name would be "Rocket_FeatureExecutionScriptTable".

To view the same information from the rhino console, view the list of execution scripts by running `listprofiles ${PLATFORM_OPERATOR_NAME}_FeatureExecutionScriptTable`. To view an individual script use `listprofileattributes ${PLATFORM_OPERATOR_NAME}_FeatureExecutionScriptTable ${SCRIPT_NAME}`.

To view the Feature Execution Script name that is invoked for a particular Plan ID’s execution point, use `listprofileattributes ${PLATFORM_OPERATOR_NAME}_FeatureExecutionPointTable ${EXECUTION_POINT}`.

For more information related to Feature Execution Points, Feature Execution Scripts and Plan IDs refer to Session Plans

= Custom Headers :indexpage: :sortorder: 5

Sentinel VoLTE supports specific custom headers and header parameters to indicate or propagate certain conditions between nodes in the network.

- OC-Access-Transfer-Procedure Header

- OC-IM-CallReferenceNumber Header

- OC-Retarget Header

- OC-Replication-Information Header

- OC-Terminating-Domain Header

- Route Header Parameters

- X-Msw-Companion-Device Header

= OC-Access-Transfer-Procedure Header :toc: macro :toclevels: 4 :toc-title: On this page…​

The `OC-Access-Transfer-Procedure Header` header is a custom SIP header used by Sentinel VoLTE SCC-AS to coordinate access transfer procedures across multiple nodes. This header is inserted into handover `INVITE` requests and special internal `MESSAGE` requests when they are forwarded between Sentinel VoLTE SCC-AS nodes. It is also inserted into handover INVITE requests when they are forwarded into an existing session on the same node. The header indicates to the receiving session which access transfer procedures it should execute.

== Header Format The header name is `OC-Access-Transfer-Procedure` and its value is a simple string with no special formatting. The header does not have any special parameters. Possible values are described below.

Example:

    OC-Access-Transfer-Procedure: Remove-Superfluous

== Header Values

Value | Associated Access Transfer Procedure
`eSRVCC-Anchored-Active-Established` | Enhanced SRVCC for sessions that are currently active (not held), established (INVITE-200-ACK received), and with media anchored in the ATGW.
`eSRVCC-Non-Anchored-Active-Established` | Enhanced SRVCC for sessions that are currently active (not held), established (INVITE-200-ACK received), and with media not anchored in the ATGW.
`eSRVCC-Anchored-Pre-Alerting` | Enhanced SRVCC for sessions that are currently pre-alerting (INVITE-180 not yet received), and with media anchored in the ATGW.
`eSRVCC-Non-Anchored-Pre-Alerting` | Enhanced SRVCC for sessions that are currently pre-alerting (INVITE-180 not yet received), and with media not anchored in the ATGW.
`eSRVCC-Anchored-Alerting` | Enhanced SRVCC for sessions that are currently alerting (INVITE-180 received, INVITE-2xx not yet received), and with media anchored in the ATGW.
`eSRVCC-Non-Anchored-Alerting` | Enhanced SRVCC for sessions that are currently alerting (INVITE-180 received, INVITE-2xx not yet received), and with media not anchored in the ATGW.
`SRVCC-Active-Established` | SRVCC for sessions that are currently active (not held) and established (INVITE-200-ACK received).
`Remove-Superfluous` | End a session that has been deemed superfluous and will not be transferred.

== Header Usage

The header is used extensively by the Packet Switched to Circuit Switched Access Transfer Features. See the individual feature pages for specifics on where it is set and used.

It is also used by the SCCDetermineSessionType feature.

A call flow diagram showing its use is available on the Shared ATU-STI page.

= OC-IM-CallReferenceNumber Header :toc: macro :toclevels: 4 :toc-title: On this page…​

The `OC-IM-CallReferenceNumber` header is a custom SIP header used by Sentinel VoLTE SCC-AS to send the Call Reference Number to the IM-SSF to use in future messages.

== Header Format The header name is `OC-IM-CallReferenceNumber` and its value is a string representing the 8 bytes of the call reference number in Hexadecimal format. The header does not have any special parameters.

Example:

    OC-IM-CallReferenceNumber: 006500655F68D12B

== Header Usage

The header is set by the FetchMSRN Feature.

= OC-Replication-Information Header :toc: macro :toclevels: 4 :toc-title: On this page…​

The `OC-Replication-Information` header is a custom SIP header used by Sentinel VoLTE to relay details of session replication configuration to the IM-SSF.

== Header Format The header name is `OC-Replication-Information` and its value can either be `enabled` or `disabled`. A value of `disabled` indicates that session tracking and replication is disabled for the current session. A value of `enabled` indicates that session tracking and replication is either enabled or deferred for the current session.

The will also include a `refreshPeriod` parameter if the header value is `enabled`. The value of this parameter is the configured session refresh period in seconds. It is ultimately used by the IM-SSF to derive a TTL for any session ownership records it creates for the purposes of session tracking on its SIP dialogs.

== Header Usage

The header is set by the CapLocationHeaders.

It is used by the IM-SSF service to determine how it should handle replication and tracking for the session.

Under normal circumstances this header will not be seen outside of inter-service SIP messages within Rhino.

= OC-Retarget Header :toc: macro :toclevels: 4 :toc-title: On this page…​

The `OC-Retarget` header is a custom SIP header used by Sentinel VoLTE MMTel-AS to communicate that a retarget has occurred. This header is inserted into the INVITEs that go towards the retargeted party. This is then used in the composition to decide whether to invoke the SCC-AS.

| The header is for internal use only and is removed by the composition before the INVITE is sent to the network.

== Header Format

The header name is `OC-Retarget` and its value is a simple string with no special formatting. The header does not have any special parameters. Possible values are described below.

Example:

    OC-Retarget: cdiv

=== Header Values

Sentinel VoLTE uses the following values for the `OC-Retarget` header:

Value | MMTel-Service-Type | Feature(s) Performing Retarget
--- | --- | ---
cdiv | 6 | MMTelCDIV
flexible-alerting | 11 | Flexible Alerting Features

= OC-Terminating-Domain Header :toc: macro :toclevels: 4 :toc-title: On this page…​

The `OC-Terminating-Domain` header is a custom SIP header used by Sentinel VoLTE SCC-AS to communicate information about the terminating domain to upstream nodes in a network. This header is inserted into responses that go "upstream" (towards the calling party). This is typically used for charging purposes, as by definition the SCC-AS is the final AS in the iFC trigger chain for terminating triggers, and does not perform charging. Therefore any other SIP AS invoked in the terminating trigger chain was invoked prior to the SCC-AS. The SCCTADSRouting and SCCTADSParallelRouting features both add this header to all provisional and success responses for an initial INVITE that are forwarded upstream from a terminating instance. The header will never appear on a final error response.

== Header Format The header name is `OC-Terminating-Domain` and its value is a simple string with no special formatting. The header does not have any special parameters. Possible values are described below.

Example:

    OC-Terminating-Domain: PS=EUTRAN

== Header Values

The value of the header will depend on which domain the response originated in:

- Responses from the CS domain will always have the header value set to `CS`

- Responses from the PS domain will always have the header value set to the match the String stored in the `PSTerminatingDomainHeaderValue` in session state if +sip.instance routing is disabled, and otherwise will have it set to the String stored in the 'TADSPacketRoutes' in session state for the route that the response is arriving from.

The values stored in `PSTerminatingDomainHeaderValue` and `TADSPacketRoutes' are determined by the TADS Data Lookup feature.

=== Default Values Out of the box, Sentinel VoLTE supports the following values for the `OC-Terminating-Domain` header:

Value | Access Domain | Meaning
--- | --- | ---
CS | CS | The response was received from a leg that routed towards the Circuit Switched network.
PS | PS | The response was received from a leg that was routed towards the Packet Switched network. This value is used when more specific information about the Packet Switched network is not available
PS=EUTRAN | PS | Indicates terminating access is over E-UTRAN (LTE) radio network
PS=WLAN | PS | Indicates terminating access is over WLAN

= Route Header Parameters

== Custom Route Header Parameters

Parameter Name | Parameter Values | Description | used by
--- | --- | --- | ---
oc-charge-mode | `ro` `cap` `offline` | This is a custom parameter on the URI of the top-most route header. It is expected that this will be added by the S-CSCF based on iFCs. For more information see Session Processing. | DetermineChargeMode feature
oc-mode | `scc` `scc-anchor` `scc-tads` `mmtel` `mmtel-scc` | Indicates the selection of SCC or MMTel behaviour for an INVITE session. The values `scc`, `scc-anchor`, `scc-tads` and `mmtel` are used by DetermineVoltePlanId feature. The value `mmtel-scc` is used by the SIS composition to use Co-located mode as described here Co-location using the Rhino SIS. For more information see Session Processing. | DetermineVoltePlanId feature
oc-blindpsrouting | N/A | If present, indicates T-ADS should blindly attempt to route towards PS (only applicable if oc-mode is `scc` or `mmtel-scc`) | SCCTADSDataLookup feature
oc-tads-routing | `parallel` `cs-only` `ps-only` `ps-cs` `cs-ps` | If set to parallel, indicates TADS should run the SCCTADSParallelRouting feature, if the parameter is not present or set to any other value SCCTADSRouting will run (only applicable if oc-mode is `scc` or `mmtel-scc`) | SCCTADSDataLookup feature

= X-Msw-Companion-Device Header :toc: macro :toclevels: 4 :toc-title: On this page…​

The `X-Msw-Companion-Device` header is a custom SIP header used by Sentinel VoLTE when a companion device may be used on a call.

The terminating MMTel-AS instance inserts this header in the initial INVITE if the served user’s `Metaswitch-TAS-Services` transparent data indicates that they have a companion device. If the subscriber has multiple companion devices, multiple header values will be inserted. The header conveys this information to the terminating SCC-AS instance. The T-ADS features in the SCC-AS will use this information to decide whether the INVITE should be forked to the companion device.

| The header is for internal use only and is automatically removed when the INVITE exits the terminating SCC-AS instance. The header will also be removed at the MMTel-AS if retargeting has occurred.

== Header Format

The header name is `X-Msw-Companion-Device`, and its value is the companion device information provisioned for the subscriber. The header is presented in the following format:

    X-Msw-Companion-Device: <radioAccessType>[;<parameters>]

`<radioAccessType>` is either `CS`, `PS`, or `PS-CS`, where `PS` value indicates the subscriber has a companion device supporting packet-switched radio access types, e.g. LTE or WiFi. `CS` value indicates the companion device supports 3G network.

The `<parameters>` are normal SIP `name=value` header parameters which can include common parameters and CS only parameters.

=== Common Parameters

Parameter | Description | Example | Mandatory or Optional
--- | --- | --- | ---
model | quoted-string containing the companion model | model="CompanionWatch" | Optional
impi | quoted-string containing an IMPI (23.003 §13.3) | impi="234150999999999@ims.mnc015.mcc234.3gppnetwork.org" | Optional
imsi | quoted-string containing an IMSI (23.003 §2.2) | imsi="234150999999999" | Optional
imei | quoted-string containing an IMEI (23.003 §13.13) | imei="sip:90420156-025763-0@ims.mnc015.mcc234.3gppnetwork.org" | Optional

=== CS Only Parameters

Parameter | Description | Example | Mandatory or Optional
--- | --- | --- | ---
msisdn | quoted-string containing an MSISDN | msisdn="1234567" | Mandatory

=== Example: * For PS companion device:

    X-Msw-Companion-Device: PS;model="CompanionWatch"

- For CS companion device with optional parameters:

      X-Msw-Companion-Device: CS;model="CompanionGlass";msisdn="1234567";imei="sip:90420156-025763-0@ims.mnc015.mcc234.3gppnetwork.org"

- For multiple devices:

      X-Msw-Companion-Device: PS-CS;model="CompanionWatch";msisdn="1234567";imei="sip:90420156-025763-0@ims.mnc015.mcc234.3gppnetwork.org
      X-Msw-Companion-Device: CS;model="CompanionGlass";msisdn="1234568"

== Header Usage

The header is set by Set Companion Device Headers feature.

The header is decoded by SCC Decode Companion Device Info feature.

= Charging Information :sortorder: 9 :indexpage:

Charging Information describes the format and content of CDR files, and the information present in Diameter Ro.

== Topics

- CDR Formats— describes the formats used for CDRs

- Charging Content AVPs— describes the populated AVPs for both online and offline charging

- Ro Interface AVPs— describes the population of AVPs on the Ro interface

- Working with CDRs— describes tooling to extract the content of CDRs

- Interim CDRs— describes Interim CDRs for offline charging

- Sizing AVP CDRs— describes sizing requirements when using AVP CDRs

- Fault Tolerant Online Charging— describes how to configure Sentinel-Volte so that sessions continue if OCS communication fails

= CDR Formats :indexpage:

Sentinel supports two CDR formats "out of the box". These are the AVP CDR format, and the legacy format.

Note that Sentinel can be configured to use a user provided CDR format, or even no CDRs.

== AVP CDRs

An AVP CDR is an OpenCloud defined CDR that contains AVPs. This type of CDR is consistent with the approaches used in Diameter Ro and Diameter Rf interfaces. An AVP CDR contains AVPs that are standardised (e.g. 3GPP and IETF), or non-standardised (e.g. product specific or project specific).

AVP CDRs can almost be considered an "on-disk" form of the content contained in the Rf interface.

AVP CDRs are used by default in the Sentinel SIP service. The Sentinel SIP service can be configured to use the legacy format.

== Legacy CDRs

A legacy CDR is an OpenCloud defined CDR that is used in the Sentinel product set prior to (and during) the introduction of AVP CDRs. The product continues support for this format so that customers who use this format do not need migrate.

Legacy CDRs remain in use by the Sentinel SS7 and Sentinel Diameter services.

== Topics

- AVP CDR Format— describes the formats used for AVP CDRs

- Legacy CDR Format— describes the format used for Legacy CDRs

= AVP CDR Format

AVP CDRs have logical content, and an on-disk format.

== Logical content

Each CDR inside a CDR file has logical content. We use a BNF syntax to describe this logical content.

    CDR ::=
            [ Subscription-Id ]
            [ IMS-Information ]
            [ User-Equipment-Info ]
           *[ Multiple-Services-Credit-Control ]
            [ OC-Call-Type ]
            [ OC-Service-Type ]
            [ OC-Charging-Result ]
           *[ OC-OCS-Session-Id ]
            [ OC-OCS-Session-Termination-Cause ]
            [ OC-Sentinel-Error ]
           *[ OC-Charging-Instance ]
            [ OC-Event-Id ]
            [ OC-Call-Id ]
            [ OC-End-Session-Cause ]
            [ OC-Session-Start-Time ]
            [ OC-Session-Established-Time ]
            [ OC-Session-End-Time ]
            [ User-Name ]
            [ OC-Selection-Key ]
            [ OC-Play-Announcement-Id ]
            [ OC-Terminating-Domain ]
            [ OC-Billing-ID ]
           *[ AVP ]

Logically this means that an individual CDR has optional content. It may have zero or one Subscription-Id AVP, zero or one IMS-Information AVP, and so-on. It may have zero or more OC-Play-Announcement-Id AVPs, and zero or more OC-OCS-Session-Id AVPs, and so-on.

A CDR inside the CDR file is not an AVP. It is a protobuf record, and as such may contain additional "root" AVPs. So, for example an application may use the format, but add a LCS-Information AVP, or custom AVP.

You could consider each CDR to be roughly equivalent to the Service-Information AVP, yet more flexible/extensible regarding its content. This is because the Service-Information AVP is essentially closed for extension by non-3GPP groups.

To view the population of AVPs in use, refer to Charging Content AVPs

== On disk format

AVP CDRs are written using Google protocol buffers (protobuf).

An AVP CDR file has a protobuf schema. This schema allows any AVP to be written to a CDR.

    package com.opencloud.cdrformat;

    // AVP based CDR

    message AvpCdr {

        repeated AVP avps = 1;

        message AVP {
            required bytes avpData = 1; // The Diameter binary encoded AVP data
            required string interfaceName = 2; // The interface which the AVP is being written out as, e.g "Rf", "Ro"
            required string specRevision = 3; // E.g. "vcb0"
            optional string avpName = 4;
        }

    }

= Legacy CDR Format :toc: macro :toclevels: 4 :toc-title: On this page…​

The Legacy CDR format has an on-disk format defined using Google Protocol Buffers (aka `protobuf`).

There is a common "types definition" schema file that is used by multiple Sentinel Services for their CDRs. These types are called "base types". Each Sentinel Service then defines its own CDRs using these types and defining its own types.

== Base types

The base types are used in CDRs for Sentinel SS7, Sentinel Diameter Mediation.

    package com.opencloud.sentinel.cdr;

    message CdrSessionCounters {
        repeated CdrSessionCounterAccess counters = 1;
    }

    message CdrSessionCounterAccess {
        required string subscriberId = 1;
        required string bucketName = 2;

        optional int64 cumulativeRequestedUnits = 3;
        optional int64 cumulativeGrantedUnits = 4;
        optional int64 cumulativeSentUsedUnits = 5;
        optional int64 cumulativeCommittedUsedUnits = 6;
        optional int64 cumulativeRequestedRefundUnits = 7;
        optional int64 cumulativeGrantedRefundUnits = 8;

        repeated CdrSessionSubCounterAccess subCounters = 9;
    }

    message CdrSessionSubCounterAccess {
        required string subCounterId = 1;

        optional int64 cumulativeRequestedUnits = 3;
        optional int64 cumulativeGrantedUnits = 4;
        optional int64 cumulativeSentUsedUnits = 5;
        optional int64 cumulativeCommittedUsedUnits = 6;
        optional int64 cumulativeRequestedRefundUnits = 7;
        optional int64 cumulativeGrantedRefundUnits = 8;

        repeated CdrSessionSubCounterAccess subCounters = 9;
    }

    message Time {
        required int64 milliseconds_since_epoch = 1;
        required sint32 zoneoffset_minutes = 2;
    }

    enum SentinelError {
        None = 1;
        OcsTimeout = 2;
        OcsCommunicationFailure = 3;
        SentinelOverload = 4;
        ProtocolError = 5;
        InternalError = 6;
        MappingError = 7;
        OtherError = 8;
    }

= Charging Content AVPs :indexpage: :toc: macro :toclevels: 4 :toc-title: On this page…​

The population of AVPs for Sentinel VoLTE is described on this page. A definition of the AVPs used for the Sentinel VoLTE product is provided on Sentinel VoLTE AVP definitions.

== Detecting Online Charging

The OC-Charging-Result AVP in a CDR or ACR indicates whether online (Diameter Ro) charging was used for a session. This may be used to determine if further action is needed when processing CDRs offline.

- An `OC-Charging-Result` value of `-1` means that online charging was not used for the session.

- Otherwise the value is set to the Diameter `Result-Code` AVP value.

== Populated AVPs in the Multiple-Services-Credit-Control AVP

The Multiple-Services-Credit-Control AVP is of type grouped, and is defined in RFC 4006. Section 7.1.4 of 3GPP TS 32.299 defines it with additional 3GPP specific parameters and states some IETF parameters are not used in the 3GPP.

AVP Name | Specification reference | Included in CDR | Included in CCR | Included in ACR | Comments
--- | --- | --- | --- | --- | ---
Requested-Service-Unit | IETF RFC 4006 | No | Yes | No | Used in the CCR. The CDR represents this information in the OC-Session-Counter AVP
Used-Service-Unit | IETF RFC 4006 and 3GPP TS 32.299 | No | Yes | No | Used in the CCR according to Populated AVPs in the Used-Service-Unit AVP. The CDR represents this information in the OC-Session-Counter AVP
Service-Identifier | IETF RFC 4006 | Yes | Yes | Yes | For Originating attempts the AVP has the value `1`. For Forwarded attempts the AVP has the value `2`. For Terminating attempts the AVP has the value `3`. For Network Initiated attempts the AVP has the value `4`. For Immediate Event Charging the AVP has the value `50`.
Rating-Group | IETF RFC 4006 and 3GPP TS 32.299 v12.11.0 section 7.1.10 | No | Yes | No | This AVP is set according to Session Counters and the `ratingGroup` session state field.
Reporting-Reason | 3GPP TS 32.299 v12.11.0 section 7.2.175 | No | Yes | No |
Trigger | 3GPP TS 32.299 v12.11.0 section 7.2.235 | No | No | No |
PS-Furnish-Charging-Information | 3GPP TS 32.299 v12.11.0 section 7.2.157 | No | No | No |
Refund-Information | 3GPP TS 32.299 v12.11.0 section 7.2.171 | No | No | No |
AF-Correlation-Information | 3GPP TS 32.299 v12.11.0 section 7.2.11 | No | No | No |
Envelope | 3GPP TS 32.299 v12.11.0 section 7.2.59 | No | No | No |
Envelope-Reporting | 3GPP TS 32.299 v12.11.0 section 7.2.61 | No | No | No |
Time-Quota-Mechanism | 3GPP TS 32.299 v12.11.0 section 7.2.228 | No | No | No |
Service-Specific-Info | 3GPP TS 32.299 v12.11.0 section 7.2.195 | No | No | No |
QoS-Information | 3GPP TS 29.212 | No | No | No |

The BNF grammar for this AVP in 32.299 v12.11.0 is as follows:

    <Multiple-Services-Credit-Control> ::=	   < AVP Header: 456 >

        [ Granted-Service-Unit ]   // not used in CCR
        [ Requested-Service-Unit ]
      * [ Used-Service-Unit ]
        [ Tariff-Change-Usage ]    // not used in 3GPP
      * [ Service-Identifier ]
        [ Rating-Group ]
      * [ G-S-U-Pool-Reference ]   // not used in CCR
        [ Validity-Time ]          // not used in CCR
        [ Result-Code ]            // not used in CCR
        [ Final-Unit-Indication ]  // not used in CCR
        [ Time-Quota-Threshold ]   // not used in CCR
        [ Volume-Quota-Threshold ] // not used in CCR
        [ Unit-Quota-Threshold ]   // not used in CCR
        [ Quota-Holding-Time ]     // not used in CCR
        [ Quota-Consumption-Time ] // not used in CCR
      * [ Reporting-Reason ]
        [ Trigger ]
        [ PS-Furnish-Charging-Information ]
        [ Refund-Information ]
      * [ AF-Correlation-Information]
      * [ Envelope ]
        [ Envelope-Reporting ]
        [ Time-Quota-Mechanism ]
      * [ Service-Specific-Info ]
        [ QoS-Information ]
      * [ AVP ]                    // not used in 3GPP

=== Populated AVPs in the Used-Service-Unit AVP

The Used-Service-Unit AVP is defined in IETF RFC 4006, and then its BNF is modified slightly in 3GPP TS 32.299 section 7.1.9.

AVP Name | Specification reference | Included in CDR | Included in CCR | Included in ACR | Comments
--- | --- | --- | --- | --- | ---
Reporting-Reason | 3GPP TS 32.299 v12.11.0 section 7.2.175 | No | No | No |
Tariff-Change-Usage | IETF RFC 4006 | No | No | No |
CC-Time | IETF RFC 4006 | No | Yes | No | Used by default as the unit type for SIP Sessions
CC-Money | IETF RFC 4006 | No | No typically | No | Not used out-of-the-box for Sentinel SIP
CC-Total-Octets | IETF RFC 4006 | No | Not typically | No | Not used out-of-the-box for Sentinel SIP
CC-Input-Octets | IETF RFC 4006 | No | Not typically | No | Not used out-of-the-box for Sentinel SIP
CC-Output-Octets | IETF RFC 4006 | No | Not typically | No | Not used out-of-the-box for Sentinel SIP

The 3GPP definition (in v12.11.0) is

    <Used-Service-Unit> ::=	   < AVP Header: 446 >
        [ Reporting-Reason ]
        [ Tariff-Change-Usage ]
        [ CC-Time ]
        [ CC-Money ]    // not used in 3GPP
        [ CC-Total-Octets ]
        [ CC-Input-Octets ]
        [ CC-Output-Octets ]
        [ CC-Service-Specific-Units ]
       *[ Event-Charging-TimeStamp ]
       *[ AVP ]        // not used in 3GPP

== Populated AVPs in the Service-Information AVP

The Service-Information AVP is defined in 3GPP TS 32.299 v12.11.0. It is a grouped AVP. This table lists the AVPs grouped within Service-Information and how the product populates them.

AVP Name | Specification reference | Included in CDR | Included in CCR | Included in ACR | Comments
--- | --- | --- | --- | --- | ---
SMS-Information | 32.299 v12.11.0 section 7.2.211 | Yes | Yes | Yes | The Sentinel IP-SM-GW product populates this AVP
MMTel-Information | 32.299 v12.11.0 section 7.2.111 | Yes | Yes | Yes | Refer to Populated AVPs in the MMTel-Information AVP
Subscription-Id | IETF RFC 4006 | Yes | No | Yes | 3GPP TS 32.299 v12.11.0 states that it should be set on the Rf interface, not the Ro interface (see section 7.2.149)
AoC-Information | 32.299 v12.11.0 section 7.2.15 | No | No | No | Sentinel does not implement the advice of charge service out-of-the-box
PS-Information | 32.299 v12.11.0 section 7.2.158 | No | No | Yes | PS-Information AVP contains EPC layer information. It is only added in ACRs as a means of sending the IMEI in the User-Equipment-Information AVP.
IMS-Information | 32.299 v12.11.0 section 7.2.77 | Yes | Yes | Yes | See the IMS-Information table for further details
MMS-Information | 32.299 v12.11.0 section 7.2.110 | No | No | No | Sentinel does not implement any MMS node roles out-of-the-box
LCS-Information | 32.299 v12.11.0 section 7.2.89 | No | No | No |
PoC-Information | 32.299 v12.11.0 section 7.2.144 | No | No | No | Sentinel does not implement the PoC service out-of-the-box
MBMS-Information | 32.299 v12.11.0 section 7.2.99 | No | No | No | Sentinel does not implement the MBMS service out-of-the-box
SMS-Information | 32.299 v12.11.0 section 7.2.211 | No | No | No | Sentinel does not implement the SMS service out-of-the-box
VCS-Information | 32.299 v12.11.0 section 7.2.242A | No | No | No |
MMTel-Information | 32.299 v12.11.0 section 7.2.111 | Yes | Yes | Yes |
ProSe-Information | 32.299 v12.11.0 section 7.2.154I | No | No | No |
Service-Generic-Information | 32.299 v12.11.0 section 7.2.191 | No | No | No |
IM-Information | 32.299 v12.11.0 section 7.2.69 | No | No | No | Sentinel does not implement IM services out-of-the-box
DCD-Information | 32.299 v12.11.0 section 7.2.50 | No | No | No |

The BNF for the AVP is defined in section 7.2.149. It is as follows:

    Service-Information :: = 	< AVP Header: 873>

      * [ Subscription-Id ]
        [ AoC-Information ]
        [ PS-Information ]
        [ IMS-Information ]
        [ MMS-Information ]
        [ LCS-Information ]
        [ PoC-Information ]
        [ MBMS-Information ]
        [ SMS-Information ]
        [ VCS-Information ]
        [ MMTel-Information ]
        [ ProSe-Information ]
        [ Service-Generic-Information ]
        [ IM-Information ]
        [ DCD-Information ]

=== Populated AVPs in the MMTel-Information AVP

The MMTel-Information AVP is a grouped AVP. It is defined in 3GPP TS 32.299 v 12.11.0 section 7.2.111.

AVP Name | Specification reference | Included in CDR | Included in CCR | Included in ACR | Comments
--- | --- | --- | --- | --- | ---
Supplementary-Service | 32.299 v12.11.0 section 7.2.219 | Yes | Yes | Yes | There is one for each supplementary service used in a Session

It has the following BNF grammar:

    MMTel-Information :: =   < AVP Header: 2030>
      * [ Supplementary-Service ]

==== Populated AVPs in the Supplementary Service AVP

The Supplementary-Service AVP is a grouped AVP. It is defined in 3GPP TS 32.299 v12.11.0 section 7.2.219.

AVP Name | Specification reference | Included in CDR | Included in CCR | Included in ACR | Comments
--- | --- | --- | --- | --- | ---
MMTel-SService-Type | 32.299 v12.11.0 section 7.2.111A | Yes | Yes | Yes | Each supplementary service sets this enumeration to itself
Service-Mode | 32.299 v12.11.0 section 7.2.193 | Yes see comments | Yes see comments | Yes see comments | This is populated according to invocation of MMTel CDIV and MMTel ICB/OCB features. If these features are not invoked, it will not be present.
Number-Of-Diversions | 32.299 v12.11.0 section 7.2.115 | Yes see comments | Yes see comments | Yes see comments | This is populated according to invocation of MMTel CDIV. If this feature is not invoked, it will not be present.
Associated-Party-Address | 32.299 v12.11.0 section 7.2.25 | Yes see comments | Yes see comments | Yes see comments | This is populated according to invocation of MMTel CDIV. If this feature is not invoked, it will not be present.
Service-ID | 32.299 v12.11.0 section 7.2.190 | Yes see comments | Yes see comments | Yes see comments | This is populated according to invocation of MMTel Conferencing. If this feature is not invoked, it will not be present.
Change-Time | 32.299 v12.11.0 section 7.2.38 | Yes see comments | Yes see comments | Yes see comments | This is populated according to invocation of MMTel Conferencing. If this feature is not invoked, it will not be present.
Number-Of-Participants | 32.299 v12.11.0 section 7.2.117 | Yes see comments | Yes see comments | Yes see comments | This is populated according to invocation of MMTel Conferencing. If this feature is not invoked, it will not be present.
Participant-Action-Type | 32.299 v12.11.0 section 7.2.133 | Yes see comments | Yes see comments | Yes see comments | This is populated according to invocation of MMTel Conferencing. If this feature is not invoked, it will not be present.
CUG-Information | 32.299 v12.11.0 section 7.2.48 | No | No | No |
AoC-Information | 32.299 v12.11.0 section 7.2.15 | No | No | No |

    Supplementary-Service: = 		  < AVP Header: 2048>

        [ MMTel-SService-Type ]
        [ Service-Mode ]
        [ Number-Of-Diversions ]
        [ Associated-Party-Address ]
        [ Service-ID ]
        [ Change-Time ]
        [ Number-Of-Participants ]
        [ Participant-Action-Type ]
        [ CUG-Information ]
        [ AoC-Information ]

=== Populated AVPs in the IMS-Information AVP

The IMS-Information AVP is defined in 3GPP TS 32.299 v12.11.0. It is a grouped AVP. This table lists the AVPs grouped within IMS-Information and how the product populates them.

AVP Name | Specification reference | Included in CDR | Included in CCR | Included in ACR | Comments
--- | --- | --- | --- | --- | ---
Event-Type | 32.299 v12.11.0 section 7.2.65 | Yes | Yes | Yes |
Role-Of-Node | 32.299 v12.11.0 section 7.2.177 | Yes | Yes | Yes | Sessions with sescase of `orig` and `orig_cdiv` are in `ORIGINATING_ROLE`
Node-Functionality | 32.299 v12.11.0 section 7.2.113 | Yes | Yes | Yes | Set to value `6` as `AS`
User-Session-Id | 32.299 v12.11.0 section 7.2.242 | Yes | Yes | Yes | Set to the Call-Id for the initial request
Outgoing-Session-Id | 32.299 v12.11.0 section 7.2.128A | No | No | No |
Session-Priority | 29.229 | Yes | Yes | Yes | Set to value `2`
Calling-Party-Address | 32.299 v12.11.0 section 7.2.33 | Yes | Yes | Yes |
Called-Party-Address | 32.299 v12.11.0 section 7.2.32 | Yes | Yes | Yes |
Called-Asserted-Identity | 32.299 v12.11.0 section 7.2.31 | Yes | Yes | Yes |
Number-Portability-Routing-Information | 32.299 v12.11.0 section 7.2.120 | No | No | No |
Carrier-Select-Routing-Information | 32.299 v12.11.0 section 7.2.34 | No | No | No |
Alternate-Charged-Party-Address | 32.299 v12.11.0 section 7.2.12 | No | No | No |
Requested-Party-Address | 32.299 v12.11.0 section 7.2.176 | Yes | Yes | Yes | This field is only included if different from the `Called-Party-Address`
Associated-URI | 32.299 v12.11.0 section 7.2.26 | No | No | No |
Application-Server-Information | 32.299 v12.11.0 section 7.2.24 | No | No | No |
Inter-Operator-Identifier | 32.299 v12.11.0 section 7.2.80 | Yes | Yes | Yes |
Transit-IOI-List | 32.299 v12.11.0 section 7.2.233B | No | No | No |
IMS-Charging-Identifier | 32.299 v12.11.0 section 7.2.75 | Yes | Yes | Yes |
SDP-Session-Description | 32.299 v12.11.0 section 7.2.184 | Yes | Yes | Yes |
SDP-Media-Component | 32.299 v12.11.0 section 7.2.180 | Yes | Yes | Yes |
Served-Party-IP-Address | 32.299 v12.11.0 section 7.2.187 | No | No | No |
Server-Capabilities | 29.229 | No | No | No |
Trunk-Group-ID | 32.299 v12.11.0 section 7.2.237 | No | No | No |
Bearer-Service | 32.299 v12.11.0 section 7.2.30 | No | No | No |
Service-Id | 32.299 v12.11.0 section 7.2.190 | No | No | No |
Service-Specific-Info | 32.299 v12.11.0 section 7.2.195 | No | No | No |
Message-Body | 32.299 v12.11.0 section 7.2.103 | No | No | No |
Cause-Code | 32.299 v12.11.0 section 7.2.35 | Yes | Yes | Yes |
Reason-Header | 32.299 v12.11.0 section 7.2.164A | No | No | No |
Access-Network-Information | 32.299 v12.11.0 section 7.2.1 | Yes | Yes | Yes | The first value in the SIP P-Access-Network-Info header is included as the value for this AVP
Early-Media-Description | 32.299 v12.11.0 section 7.2.58 | Yes | Yes | Yes | The most recent Early Media offer/answer is included
IMS-Communication-Service-Identifier | 32.299 v12.11.0 section 7.2.76 | Yes | Yes | Yes |
IMS-Application-Reference-Identifier | 32.299 v12.11.0 section 7.2.74A | No | No | No |
Online-Charging-Flag | 32.299 v12.11.0 section 7.2.122 | No | No | No |
Real-Time-Tariff-Information | 32.299 v12.11.0 section 7.2.164 | No | No | No |
Account-Expiration | 32.299 v12.11.0 section 7.2.2 | No | No | No |
Initial-IMS-Charging-Identifier | 32.299 v12.11.0 section 7.2.79A | No | No | No |
NNI-Information | 32.299 v12.11.0 section 7.2.112A | No | No | No |
From-Address | 32.299 v12.11.0 section 7.2.67A | No | No | No |
IMS-Emergency-Indicator | 32.299 v12.11.0 section 7.2.76A | No | No | No |
IMS-Visited-Network-Identifier | 32.299 v12.11.0 section 7.2.77A | No | No | No |
Access-Transfer-Information | 32.299 v12.11.0 section 7.2.1A | No | No | No |
Related-IMS-Charging-Identifier | 32.299 v12.11.0 section 7.2.171B | No | No | No |
Related-IMS-Charging-Identifier-Node | 32.299 v12.11.0 section 7.2.171C | No | No | No |
Route-Header-Received | 32.299 v12.11.0 section 7.2.177A | No | No | No |
Route-Header-Transmitted | 32.299 v12.11.0 section 7.2.177B | No | No | No |
Instance-Id | 32.299 v12.11.0 section 7.2.70A | No | No | No |
TAD-Identifier | 32.299 v12.11.0 section 7.2.219A | No | No | No |

The BNF syntax for the IMS-Information AVP according to 3GPP TS 32.299 v12.11.0 is as follows

        IMS-Information :: =        < AVP Header: 876>
        [ Event-Type ]
        [ Role-Of-Node ]
        { Node-Functionality }
        [ User-Session-Id ]
        [ Outgoing-Session-Id ]
        [ Session-Priority ]
     *  [ Calling-Party-Address ]
        [ Called-Party-Address ]
     *  [ Called-Asserted-Identity ]
        [ Number-Portability-Routing-Information ]
        [ Carrier-Select-Routing-Information ]
        [ Alternate-Charged-Party-Address ]
     *  [ Requested-Party-Address ]
     *  [ Associated-URI ]
        [ Time-Stamps ]
     *  [ Application-Server-Information ]
     *  [ Inter-Operator-Identifier ]
     *  [ Transit-IOI-List ]
        [ IMS-Charging-Identifier ]
     *  [ SDP-Session-Description ]
     *  [ SDP-Media-Component ]
        [ Served-Party-IP-Address ]
        [ Server-Capabilities ]
        [ Trunk-Group-ID ]
        [ Bearer-Service ]
        [ Service-Id ]
     *  [ Service-Specific-Info ]
     *  [ Message-Body ]
        [ Cause-Code ]
     *  [ Reason-Header ]
     *  [ Access-Network-Information ]
     *  [ Early-Media-Description ]
        [ IMS-Communication-Service-Identifier ]
        [ IMS-Application-Reference-Identifier ]
        [ Online-Charging-Flag ]
        [ Real-Time-Tariff-Information ]
        [ Account-Expiration ]
        [ Initial-IMS-Charging-Identifier ]
      * [ NNI-Information ]
        [ From-Address ]
        [ IMS-Emergency-Indicator ]
        [ IMS-Visited-Network-Identifier ]
     *  [ Access-Transfer-Information ]
        [ Related-IMS-Charging-Identifier ]
        [ Related-IMS-Charging-Identifier-Node ]
        [ Route-Header-Received ]
        [ Route-Header-Transmitted ]
        [ Instance-Id ]
        [TAD-Identifier]

== Populated OpenCloud AVPs

The population of OpenCloud AVPs is described here. The definition of OpenCloud AVPs is provided in Sentinel AVP definitions.

AVP Name | Specification reference | Included in CDR | Included in CCR | Included in ACR | Comments
--- | --- | --- | --- | --- | ---
OC-Sentinel-Selection-Key | OC-Sentinel-Selection-Key | Yes | No | Yes | n/a
OC-Play-Announcement-Id | OC-Play-Announcement-Id | Yes | No | Yes | n/a
OC-Call-Type | OC-Call-Type | Yes | No | Yes | Role-Of-Node AVP has similar meaning on the Ro interface
OC-Service-Type | OC-Service-Type | Yes | No | Yes | n/a
OC-Charging-Result | OC-Charging-Result | Yes | No | Yes |
OC-OCS-Session-Id | OC-OCS-Session-Id | Yes | No | Yes | This is the session ID in Ro
OC-OCS-Session-Termination-Cause | OC-OCS-Session-Termination-Cause | Yes | No | Yes |
OC-Sentinel-Error | OC-Sentinel-Error | Yes | No | Yes |
OC-Charging-Instance | OC-Charging-Instance | Yes | No | Yes |
OC-Event-Id | OC-Event-Id | Yes | No | Yes |
OC-Call-Id | OC-Call-Id | Yes | No | Yes | The Ro Session Id optional part includes the SIP Call ID
OC-End-Session-Cause | OC-End-Session-Cause | Yes | No | Yes |
OC-Start-Time | OC-Start-Time | Yes | No | Yes |
OC-End-Time | OC-End-Time | Yes | No | Yes |
OC-Session-Start-Time | OC-Session-Start-Time | Yes | No | Yes |
OC-Session-Established-Time | OC-Session-Established-Time | Yes | No | Yes | Included if an INVITE session is answered
OC-Session-End-Time | OC-Session-End-Time | Yes | No | Yes |
OC-Session-Counter | OC-Session-Counter | Yes | No | Yes |
OC-Interim-CDR-Trigger | OC-Interim-CDR-Trigger | Yes | No | Yes |
OC-Access-Network-MCC-MNC | OC-Access-Network-MCC-MNC | Yes | Yes | Yes |
OC-Visited-Network-MCC-MNC | OC-Visited-Network-MCC-MNC | Yes | Yes | Yes |
OC-IMSI-MCC-MNC | OC-IMSI-MCC-MNC | Yes | Yes | Yes |
OC-Session-Failover-Detected | OC-Session-Failover-Detected | Yes | Yes | Yes |
OC-Terminating-Domain | OC-Terminating-Domain | Yes | No | Yes | n/a
OC-IMSSF-Call-Reference-Number | OC-IMSSF-Call-Reference-Number | Yes | No | Yes | n/a
OC-Conf-Type | OC-Conf-Type | No | Yes | No | n/a
OC-Billing-ID | OC-Billing-ID | Yes | Yes | Yes | n/a
OC-Metaswitch-Service-Information | OC-Metaswitch-Service-Information | Yes | Yes | Yes | The OC-Metaswitch-Service-Information AVP stores companion device information. If this information is not present then this AVP is not populated.

= Sentinel AVP definitions :toc: macro :toclevels: 4 :toc-title: On this page…​

The following AVPs are OpenCloud defined AVPs used that are used in the Sentinel VoLTE product. All OpenCloud defined AVPs have a diameter vendor ID of 19808.

== AVPs defined in the Sentinel VoLTE product

The Sentinel VoLTE product extends Sentinel Express and adds the following AVP.

=== OC-Terminating-Domain

The OC-Terminating-Domain AVP (AVP code 1005) is of type UTF8String and contains the value of the OC-Terminating-Domain Header SIP header.

No parent AVP.

=== OC-IMSSF-Call-Reference-Number

The OC-IMSSF-Call-Reference-Number AVP (AVP code 1046) is of type OctetString and contains the Call Reference Number used in queries to the HLR during the session.

No parent AVP.

=== OC-Conf-Type

The OC-Conf-Type AVP (AVP code 2008) is of type Enumerated and indicates what media a conference was initiated with.

It can be one of the following:

- `VOICE` = 0

- `VIDEO` = 1

No parent AVP.

=== OC-Billing-ID

The OC-Billing-ID AVP (AVP code 1065) is of type UTF8String and contains the BillingID argument from the ReOriginated CDMA request.

No parent AVP.

=== OC-Metaswitch-Service-Information

The OC-Metaswitch-Service-Information AVP (AVP code 2009) is of type grouped and contains the OC-Companion-Device grouped AVP.

See companion device overview for more information

=== OC-Companion-Device

The OC-Companion-Device AVP (AVP code 2010) is of type grouped and contains OC-Shared-Identity-SIP, OC-Shared-Identity-TEL, and OC-Undisclosed-Identity.

Parent AVP is OC-Metaswitch-Service-Information.

=== OC-Shared-Identity-SIP

The OC-Shared-Identity-SIP AVP (AVP code 2011) is of type UTF8String and contains the shared identity SIP URI.

Parent AVP is OC-Companion-Device.

=== OC-Shared-Identity-TEL

The OC-Shared-Identity-TEL AVP (AVP code 2012) is of type UTF8String and contains the shared identity TEL URI.

Parent AVP is OC-Companion-Device.

=== OC-Undisclosed-Identity

The OC-Undisclosed-Identity AVP (AVP code 2013) is of type UTF8String and contains the undisclosed identity.

Parent AVP is OC-Companion-Device.

== AVPs defined in Sentinel Express

The following AVPs are defined in the Sentinel Express product, and are used in the Sentinel VoLTE product.

=== OC-Sentinel-Selection-Key

The OC-Sentinel-Selection-Key AVP (AVP code 1001) is of type UTF8String and contains the Sentinel Selection Key for the session.

No Parent AVP.

=== OC-Play-Announcement-Id

The OC-Play-Announcement-Id AVP (AVP code 1002) is of type Integer32 and contains the ID of an announcement used during the session.

No Parent AVP.

=== OC-Call-Type

The OC-Call-Type AVP (AVP code 1003) is of type Enumerated and specifies the type of trigger for the session.

It can be one of the following:

- `MOC` = 1, the trigger was Originating

- `MOC_3RDPTY` = 2, the trigger was a non-SIP third party call setup request (e.g. via HTTP)

- `MTC` = 3, the trigger was Terminating

- `MFC` = 4, the trigger was Forwarding

- `EMERGENCY_CALL` = 9, the trigger was classified as emergency

No Parent AVP.

=== OC-Service-Type

The OC-Service-Type AVP (AVP code 1004) is of type Enumerated and specifies the initiating message for the session.

It can be one of the following:

- `UNKNOWN` = 1, the initiating reason is unknown

- `SipCall` = 2, the session was initiated due to receipt of SIP INVITE

- `Subscription` = 3, the session was initiated due to receipt of SIP SUBSCRIBE

- `Message` = 5, the session was initiated due to receipt of SIP MESSAGE

No Parent AVP.

=== OC-Charging-Result

The OC-Charging-Result AVP (AVP code 1006) is of type Integer32. It contains the value of the Diameter CCA result-code AVP. In case there was no Ro session, it will have the value of -1.

No Parent AVP.

=== OC-OCS-Session-Id

The OC-OCS-Session-Id AVP (AVP code 1008) is of type UTF8String. It indicates a Session Id used to communicate with the OCS during the session.

No Parent AVP.

=== OC-OCS-Session-Termination-Cause

The OC-OCS-Session-Termination-Cause AVP (AVP code 1009) is of type Integer32. It communicates the reason that the OCS (or mediation layer) terminated the Ro session. It can be one of the following:

- `NORMAL_SESSION_COMPLETION` = 0, the session terminated normally.

- `ERROR_CCA` = 1, the session was terminated due to a CCA error response.

- `CREDIT_LIMIT_REACHED` = 2, the session was terminated due to Credit-Limit-Reached.

- `OCS_ABORT` = 3, the session was terminated due to an ASR received from the OCS.

- `TCC_EXPIRED` = 4, the session was terminated due to the Sentinel Tcc timer expiring.

- `CREDIT_CONTROL_FAILURE` = 5, the session was terminated due to a failure generating CCR.

- `CLIENT_ABORT` = 6, the session terminated due to a client request, typically as a result of an abnormal event.

No Parent AVP.

=== OC-Sentinel-Error

The OC-Sentinel-Error AVP (AVP code 1010) is of type Enumerated.

It can be one of the following:

- `None` = 1

- `OcsTimeout` = 2

- `OcsCommunicationFailure` = 3

- `SentinelOverload` = 4

- `ProtocolError` = 5

- `InternalError` = 6

- `MappingError` = 7

- `OtherError` = 8

If there is a Credit Control Answer, and it has an Experimental Result Code, and that has an OpenCloud vendor ID, then this AVP is filled.

No Parent AVP.

=== OC-Charging-Instance

The OC-Charging-Instance AVP (AVP code 1011) is of type Grouped. An OC-Charging-Instance AVP represents an online charging instance used during the session.

    OC-Charging-Instance ::= < AVP Header: 1011 >
                             [ OC-Charging-Instance-Name ]
                            *[ OC-Session-Counter ]

No Parent AVP.

=== OC-Charging-Instance-Name

The OC-Charging-Instance-Name AVP (AVP code 1012) is of type UTF8String. It represents the name of an OC-Charging-Instance.

Parent AVP: OC-Charging-Instance

=== OC-Session-Counter

The OC-Session-Counter AVP (AVP code 1013) is of type Grouped. It represents a Session Counter used during the session.

Parent AVP: OC-Charging-Instance

    OC-Session-Counter ::= < AVP Header: 1013 >
                              *[ OC-Session-Counter-Address ]
                               [ OC-Cumulative-Committed-Used ]
                               [ OC-Cumulative-Granted ]
                               [ OC-Cumulative-Granted-Refund ]
                               [ OC-Cumulative-Requested ]
                               [ OC-Cumulative-Requested-Refund ]
                               [ OC-Cumulative-Sent-Used ]
                               [ OC-Cumulative-Suspended-Duration ]
                               [ OC-Reported-Used ]
                               [ OC-End-Time ]
                               [ OC-Pending-Requested ]
                               [ OC-Start-Time ]

=== OC-Session-Counter-Address

The OC-Session-Counter-Address AVP (AVP code 1014) is of type Grouped. It represents a Session Counter `address` field, as documented in Session counter structure.

    OC-Session-Counter-Address ::= < AVP Header: 1014 >

                                       [ OC-Session-Counter-Address-Key ]
                                       [ OC-Session-Counter-Address-Value ]

Parent AVP: OC-Session-Counter

=== OC-Session-Counter-Address-Key

The OC-Session-Counter-Address-Key AVP (AVP code 1015) is of type UTF8String.

Parent AVP: OC-Session-Counter-Address

=== OC-Session-Counter-Address-Value

The OC-Session-Counter-Address-Value AVP (AVP code 1016) is of type UTF8String.

Parent AVP: OC-Session-Counter-Address

=== OC-Cumulative-Committed-Used

The OC-Cumulative-Committed-Used AVP (AVP code 1017) is of type Integer64.

It contains the value of the `cumulativeCommittedUsed` unit counter documented in Session counter structure.

Parent AVP: OC-Session-Counter

=== OC-Cumulative-Granted

The OC-Cumulative-Granted AVP (AVP code 1018) is of type Integer64.

It contains the value of the `cumulativeGranted` unit counter documented in Session counter structure.

Parent AVP: OC-Session-Counter

=== OC-Cumulative-Granted-Refund

The OC-Cumulative-Granted-Refund AVP (AVP code 1019) is of type Integer64.

It contains the value of the `cumulatedGrantedRefund` unit counter documented in Session counter structure.

Parent AVP: OC-Session-Counter

=== OC-Cumulative-Requested

The OC-Cumulative-Request AVP (AVP code 1020) is of type Integer64.

It contains the value of the `cumulatedRequested` unit counter documented in Session counter structure.

Parent AVP: OC-Session-Counter === OC-Cumulative-Requested-Refund

The OC-Cumulative-Requested-Refund AVP (AVP code 1021) is of type Integer64.

It contains the value of the `cumulativeRequestedRefund` unit counter documented in Session counter structure.

Parent AVP: OC-Session-Counter

=== OC-Cumulative-Sent-Used

The OC-Cumulative-Sent-Used AVP (AVP code 1022) is of type Integer64. It contains the cumulative used units sent to the OCS for the Session Counter.

It contains the value of the `cumulativeSentUsed` unit counter documented in Session counter structure.

Parent AVP: OC-Session-Counter

=== OC-Cumulative-Suspended-Duration

The OC-Cumulative-Suspended-Duration AVP (AVP code 1023) is of type Integer64.

It contains the value of the `cumulativeSuspendedDuration` field documented in Session counter structure.

Parent AVP: OC-Session-Counter

=== OC-Reported-Used

The OC-Reported-Used AVP (AVP code 1024) is of type Integer64.

It contains the value of the `reportedUsed` field documented in Session counter structure.

Parent AVP: OC-Session-Counter

=== OC-Pending-Requested

The OC-Pending-Requested AVP (AVP code 1025) is of type Integer64.

It contains the value of the `pendingRequested` unit counter documented in Session counter structure.

Parent AVP: OC-Session-Counter

=== OC-Start-Time

The OC-Start-Time AVP (AVP code 1026) is of type Time.

It contains the value of the `startTime` field documented in Session counter structure.

Parent AVP: OC-Session-Counter

=== OC-End-Time

The OC-End-Time AVP (AVP code 1027) is of type Time.

It contains the value of the `endTime` field documented in Session counter structure.

Parent AVP: OC-Session-Counter

=== OC-Event-Id

The OC-Event-Id AVP (AVP code 1028) is of type UTF8String.

If the initial request for the Session was a `SIP SUBSCRIBE` or `SIP NOTIFY` request, this is set to the value of the `Event:` header in the initial request.

If the initial request for the Session was a `SIP REFER` request, this is set to the `CSeq` of the REFER request.

No parent AVP.

=== OC-Call-Id

The OC-Call-Id AVP (AVP code 1029) is of type UTF8String. This is set to the Call-ID of the initial SIP request for the Session.

No parent AVP.

=== OC-End-Session-Cause

The OC-End-Session-Cause AVP (AVP code 1036) is of type Integer32. This is set to indicate the reason a service or feature ended the session.

If the `LegManager.endSession` instruction is called with a cause value, the AVP value is set to the cause value.

Otherwise, if the session state field `endSessionCause` is set, the AVP value is set to the session state value.

No parent AVP.

=== OC-Interim-CDR-Trigger

The OC-Interim-CDR-Trigger AVP (AVP code 1037) is a repeated AVP of type Grouped and appears only in interim CDRs. Each occurrence indicates a reason and a supplementary reason for writing an Interim CDR and the leg for which the reasons apply.

    OC-Interim-CDR-Trigger ::= < AVP Header: 1037 >

                                       [ OC-Interim-CDR-Reason ]
                                       [ OC-Interim-CDR-Supplementary-Reason]
                                       [ OC-Interim-CDR-Leg ]

No parent AVP.

=== OC-Interim-CDR-Reason

The OC-Interim-CDR-Reason AVP (AVP code 1038) is of type UTF8String.

Parent AVP: OC-Interim-CDR-Trigger

=== OC-Interim-CDR-Leg

The OC-Interim-CDR-Leg AVP (AVP code 1039) is of type UTF8String.

Parent AVP: OC-Interim-CDR-Trigger

=== OC-Session-Start-Time

The OC-Session-Start-Time AVP (AVP code 1040) is of type Time.

It contains the time that the session’s Initial Request was processed.

No parent AVP.

=== OC-Session-Established-Time

The OC-Session-Established-Time AVP (AVP code 1041) is of type Time.

It contains the time that the session was answered, that is the ACK to the 2xx-INVITE was processed.

No parent AVP.

=== OC-Session-End-Time

The OC-Session-End-Time AVP (AVP code 1042) is of type Time.

It contains the time that the session was ended.

No parent AVP.

=== OC-Interim-CDR-Supplementary-Reason

The OC-Interim-CDR-Supplementary-Reason AVP (AVP code 1043) is of type UTF8String.

Parent AVP: OC-Interim-CDR-Trigger

=== OC-Age-Of-Information

The OC-Age-Of-Information AVP (AVP code 1060) is of type Integer64. The time in milliseconds of the source information. The value depends on which of the grouped AVP’s contains the OC-Age-Of-Information.

Parent AVP: OC-IMSI-MCC-MNC bxref:sentinel-avp-definitions#oc-access-network-mcc-mnc[OC-Access-Network-MCC-MNC OC-Visited-Network-MCC-MNC

=== OC-MCC-MNC

The OC-MCC-MNC AVP (AVP code 1061) is of type UTF8String. The length is 5 or 6 digits depending on the value of MNC, that can be 2 or 3. It is encoded as UTF8String characters representing the IMSI MCC-MNC numerical values. In accordance with 3GPP TS 29.060 24 (for GGSN), 3GPP TS 29.274 81 (for P-GW) and 3GPP TS 23.003 40, the MCC is 3 digits and the MNC is either 2 or 3 digits. There are no padding characters between the MCC and MNC.

Parent AVP: OC-IMSI-MCC-MNC bxref:sentinel-avp-definitions#oc-access-network-mcc-mnc[OC-Access-Network-MCC-MNC OC-Visited-Network-MCC-MNC

=== OC-Access-Network-MCC-MNC

The OC-Access-Network-MCC-MNC (AVP code 1062) indicates the home network MCC-MNC, in case the access network can be identified. The information is extracted from the P-Access-Network-Info header. It is a grouped AVP formed by:

- OC-MCC-MNC

- OC-Age-Of-Information

The OC-Age-Of-Information is the registration time.

No parent AVP.

=== OC-Visited-Network-MCC-MNC

The OC-Visited-Network-MCC-MNC (AVP code 1063) indicates the visited network MCC-MNC, in case the visited network can be identified. This information is extracted from the P-Visited-Network-Id header. It is a grouped AVP formed by:

- OC-MCC-MNC

- OC-Age-Of-Information

The OC-Age-Of-Information is the registration time.

No parent AVP.

=== OC-IMSI-MCC-MNC

The OC-IMSI-MCC-MNC (AVP code 1064) is extracted from the IMSI and indicates the network related to the subscriber IMSI. It is a grouped AVP formed by:

- OC-MCC-MNC

- OC-Age-Of-Information

The OC-Age-Of-Information is:

- registration time

- SRI response time in case it is extracted from the SRI response.

No parent AVP.

=== OC-Session-Failover-Detected

The OC-Session-Failover-Detected (AVP code 1066) flag indicates whether a session failover occured between the initial event and when this AVP was written.

It is of type Integer32, with the value '0' indicating that session failover has not been detected and '1' indicating session failover has been detected.

No parent AVP.

= Fault Tolerant Online Charging

When configured for both online and offline charging, it may be desirable to allow sessions to proceed when there is a communications outage with the OCS.

By default Sentinel VoLTE will end a session if there is no connection to the OCS, or there is a timeout waiting for a response from the OCS.

When the Determine Charging system feature’s configuration parameter `ContinueCallOnOCSFailure` is `true`, for a session that detects an OCS communication problem, the session will proceed:

- but no further Ro communication will occur even if Ro communication is re-established

- and Rf and CDRs will continue to track the session

- except a midsession OCS failure for a conference call will still result in the session ending.

= Interim CDRs :indexpage: :toc: macro :toclevels: 4 :toc-title: On this page…​

The purpose, lifecycle, and features related to Interim CDRs are described on this page.

== Overview

Interim CDRs are a CDR format used for recording CDRs at multiple points during the lifetime of a session. This format has several benefits over the once-per-session CDRs written by the session-based CDR features:

1. Improved failure characteristics. Interim CDRs are recording more frequently during a session, so any system failures will result in less records being lost.

2. Interop with offline charging systems. This format is designed to reflect the message content requirements for interaction with offline charging systems via the Rf interface.

3. More accurate. This format records changes in specific AVPs (e.g. SIP SDP AVPs) during the lifecycle of a session allowing changes in media state to be more accurately tracked.

== Interim CDR content

Interim CDRs are written as a collection of AVPs conforming to the definitions listed in Sentinel AVP definitions. In addition to the standard AVPs, Interim CDRs contain additional AVPs to facilitate interpretation and correlation of their content.

These additions are summarized in the following table:

AVP | Description | Specification
--- | --- | ---
Accounting-Record-Type | Lifecycle enum indicating when the record was written. See below table. | RFC 6733
Accounting-Record-Number | Unique-per-session number starting at 0 indicating how many records have been written for this session. | RFC 6733
OC-Interim-CDR-Reason | Contains the leg the Interim CDR relates to, and the reason it was written. | Sentinel AVP definitions

The `Accounting-Record-Type` AVP can have the following enumerated values:

Accounting-Record-Type | When written…​
--- | ---
START_RECORD | When a session is established (answered).
INTERIM_RECORD | Mid-session, either in response to SDP changes or based on timer events (both configurable).
STOP_RECORD | When a session finishes.
EVENT_RECORD | When the last Interim CDR written is also the first one written, e.g. for recording of one-off SMS events.

== Interim CDR Correlation

If the IMS Charging Identifier (ICID) is present during network interactions it will be included in all Interim CDRs produced for a session.

When Running List CDRs, ICIDs present in a CDR file can be listed with `--list-icids`, or filtered with a specific ICID using `--filter-by-icid`.

== Related features

For configuring when Interim CDRs are written, refer to the VoLTE Interim Cdr feature documentation.

Other features can inform the VoLTE Interim Cdr feature of important session state changes by writing values to the control fields defined by the `SipInterimCdrSessionState` session state interface.

The features which affect the behaviour of the VoLTE Interim Cdr features are:

Feature | Behaviour
--- | ---
Determine Chargeable Leg Feature | Determines which leg to charge then records it to the `LegForCdrs` session state field.
SDP Monitor Feature | Detects when SDPs have changed and sets the `WriteCdrOnSDPChange` session state field. This instructs the Interim CDR feature to (if configured) write an interim CDR when SDPs have changed.
MMTel Conference Subscription Feature | Sets the `LegForCdrs` session state field to the conference moderator leg.
Suppress SDP CDR Feature | Unsets the `WriteCdrOnSDPChange` session state field for non-roaming Mobile Terminating calls.

== Controlling when Interim CDRs are written

The Interim CDR feature writes CDRs at specific points during a session. There are several mechanisms to control when interim CDRs are written including feature configuration and session state control fields, as described in the feature documentation.

== Example call flow

Below is an annotated call flow indicating where Interim CDRs are written during a typical SIP Mobile Originating session.

== Extending CDR content

To customise the content included in Interim CDRs, refer to Customising CDRs from the SDK documentation.

= Rf Interface AVPs :indexpage:

The AVPs used by Sentinel VoLTE in the Accounting request are described.

== Sentinel VoLTE SIP Service population of Accounting Request

The Accounting Request message is defined according to IETF RFC 6733, and the diameter Rf interface is defined in 3GPP TS 32.299. Sentinel products use the definition in 3GPP TS 32.299 v12.11.0 for ACR.

This table indicates the top-level AVPs inside an ACR request and how the Sentinel SIP service populates them.

AVP Name | Specification reference | Included in CDR | Included in ACR | Comments
--- | --- | --- | --- | ---
Service-Context-Id | IETF RFC 4006 and refined by 3GPP TS 32.299 v12.11.0 section 7.1.12 | Yes | Yes | For MMTel the value is set to `12.32275@3gpp.org`. For SCC the value is set to `12.32260@3gpp.org`, even though SCC does not perform online charging. These values include the "Release", "service-context" and "domain" portions. For the Sentinel SS7 service the value is set to `session@opencloud.com`.
User-Name | IETF RFC 6733 | Yes | Yes | Set in Sentinel VoLTE to the IMS Private Identifier for the served user if the served user is IMS registered.
Session-Id | IETF RFC 6733 | Yes | Yes | The Session-Id optional part is set to the Call-ID of the initial request for the Session
Origin-Host | IETF RFC 6733 | No | Yes | Resource Adaptor entity configuration defines the value to be used for this AVP
Origin-Realm | IETF RFC 6733 | No | Yes | Resource Adaptor entity configuration defines the value to be used for this AVP
Destination-Realm | IETF RFC 6733 | No | Yes | This is set in Sentinel configuration, when selecting a CDF to use for the Session
Accounting-Record-Type | IETF RFC 6733 | Yes | Yes |
Accounting-Record-Number | IETF RFC 6733 | Yes | Yes |
Acct-Application-Id | IETF RFC 6733 | No | Yes | Set to the value `4L`
Vendor-Specific-Application-Id | IETF RFC 6733 | No | No | ## in volte documentation
User-Name | IETF RFC 6733 | Yes | Yes | This contains the Private Id from registration data
Destination-Host | IETF RFC 6733 | No | No |
Accounting-Sub-Session-Id | IETF RFC 6733 | No | No |
Acct-Session-Id | IETF RFC 6733 | No | No |
Acct-Multi-Session-Id | IETF RFC 6733 | No | No |
Acct-Interim-Interval | IETF RFC 6733 | Yes | Yes |
Accounting-Realtime-Required | IETF RFC 6733 | No | No |
Origin-State-Id | IETF RFC 6733 | No | No |
Event-Timestamp | IETF RFC 6733 | No | Yes |
Proxy-Info | IETF RFC 6733 | No | No |
Route-Record | IETF RFC 6733 | No | No | ## in volte documentation
Service-Context-Id | IETF RFC 4006 | Yes | Yes |
Service-Information | 3GPP TS 32.299 | No | Yes | Refer to Populated AVPs in the Service-Information AVP

The BNF for the ACR message according to 32.299 v12.11.0 section 6.2.2 is

    <ACR> ::= < Diameter Header: 271, REQ, PXY >
               < Session-Id >
               { Origin-Host }
               { Origin-Realm }
               { Destination-Realm }
               { Accounting-Record-Type }
               { Accounting-Record-Number }
               [ Acct-Application-Id ]
               [ Vendor-Specific-Application-Id ]   // not used in 3GPP
               [ User-Name ]
               [ Destination-Host ]
               [ Accounting-Sub-Session-Id ]        // not used in 3GPP
               [ Acct-Session-Id ]                  // not used in 3GPP
               [ Acct-Multi-Session-Id ]            // not used in 3GPP
               [ Acct-Interim-Interval ]
               [ Accounting-Realtime-Required ]     // not used in 3GPP
               [ Origin-State-Id ]
               [ Event-Timestamp ]
             * [ Proxy-Info ]
             * [ Route-Record ]
               [ Service-Context-Id ]
               [ Service-Information ]
             * [ AVP ]

= Ro Interface AVPs :indexpage:

The AVPs used by Sentinel VoLTE in the credit control request are described.

== Sentinel VoLTE SIP Service population of Credit Control Request

The Credit Control Request message is defined according to IETF RFC 4006, and some AVPs are removed and not used according to 3GPP TS 32.299. Sentinel products use the definition in 3GPP TS 32.299 v12.11.0 for CCR.

This table indicates the top-level AVPs inside a CCR request and how the Sentinel SIP service populates them.

AVP Name | Specification reference | Included in CDR | Included in CCR | Comments
--- | --- | --- | --- | ---
Service-Context-Id | IETF RFC 4006 and refined by 3GPP TS 32.299 v12.11.0 section 7.1.12 | Yes | Yes | For MMTel the value is set to `12.32275@3gpp.org`. For SCC the value is set to `12.32260@3gpp.org`, even though SCC does not perform online charging. These values include the "Release", "service-context" and "domain" portions. For the Sentinel SS7 service the value is set to `session@opencloud.com`.
User-Name | IETF RFC 4006 | Yes | Yes | Set in Sentinel VoLTE to the IMS Private Identifier for the served user if the served user is IMS registered.
Session-Id | IETF RFC 4006 | Yes | Yes | The Session-Id optional part is set to the Call-ID of the initial request for the Session
Origin-Host | IETF RFC 4006 | No | Yes | Resource Adaptor entity configuration defines the value to be used for this AVP
Origin-Realm | IETF RFC 4006 | No | Yes | Resource Adaptor entity configuration defines the value to be used for this AVP
Destination-Realm | IETF RFC 4006 | No | Yes | This is set in Sentinel configuration, when selecting an OCS to use for the Session
Auth-Application-Id | IETF RFC 4006 | No | Yes | Set to the value `4L` ## in volte documentation
Service-Context-Id | IETF RFC 4006 | Yes | Yes |
CC-Request-Type | IETF RFC 4006 | No | Yes |
CC-Request-Number | IETF RFC 4006 | No | Yes |
Destination-Host | IETF RFC 4006 | No | No |
Origin-State-Id | IETF RFC 4006 | No | No |
Event-Timestamp | IETF RFC 4006 | No | Yes |
Subscription-Id | IETF RFC 4006 | Yes | Yes | Set to the Served User, either as a SIP URI or Tel URI. This is populated via the SIP Subscriber Determination Feature.
Termination-Cause | IETF RFC 3588 | No | No |
Requested-Action | IETF RFC 4006 | No | Yes |
AoC-Request-Type | IETF RFC 4006 | No | No |
Multiple-Services-Indicator | IETF RFC 4006 | No | Yes | Set to `1` multiple services supported
Multiple-Services-Credit-Control | IETF RFC 4006 | Yes | Yes | In the case of AVP CDRs, if Ro charging is used then MSCC AVPs from the most recent CCA are written to the CDR. In the case of Ro charging the CCR’s MSCC AVP includes Populated AVPs in the Multiple-Services-Credit-Control AVP
CC-Correlation-Id | IETF RFC 4006 | No | No |
User-Equipment-Info | IETF RFC 4006 | Yes | Yes | The IMEI is used rather than the IMEISV, and the User-Equipment-Type AVP is set to IMEISV.
Proxy-Info | IETF RFC 4006 | No | No |
Route-Record | IETF RFC 4006 | No | No |
Service-Information | 3GPP TS 32.299 | No | Yes | Refer to Populated AVPs in the Service-Information AVP ## in volte documentation
User-Name | IETF RFC 6733 | Yes | Yes | This contains the Private Id from registration data

The BNF for the CCR message according to 32.299 v12.11.0 section 6.4.2 is

    <CCR> ::= < Diameter Header: 272, REQ, PXY >

        < Session-Id >
        { Origin-Host }
        { Origin-Realm }
        { Destination-Realm }
        { Auth-Application-Id }
        { Service-Context-Id }
        { CC-Request-Type }
        { CC-Request-Number }
        [ Destination-Host ]
        [ User-Name ]
        [ CC-Sub-Session-Id ]      // not used in 3GPP
        [ Acct-Multi-Session-Id ]  // not used in 3GPP
        [ Origin-State-Id ]
        [ Event-Timestamp ]
       *[ Subscription-Id ]
        [ Service-Identifier ]     // not used in 3GPP
        [ Termination-Cause ]
        [ Requested-Service-Unit ] // not used in 3GPP
        [ Requested-Action ]
       *[ Used-Service-Unit ]      // not used in 3GPP
        [ AoC-Request-Type ]
        [ Multiple-Services-Indicator ]
       *[ Multiple-Services-Credit-Control ]
       *[ Service-Parameter-Info ] // not used in 3GPP
        [ CC-Correlation-Id ]
        [ User-Equipment-Info ]
       *[ Proxy-Info ]
       *[ Route-Record ]
        [ Service-Information ]
       *[ AVP ]

= Sizing AVP CDRs :indexpage: :toc: macro :toclevels: 4 :toc-title: On this page…​

This section documents the storage requirements for AVP CDRs.

== Binary CDR log structure

Each CDR log file can be broken down into the following parts:

- Protobuf overhead - a small amount of type information about contained records.

- A header section - a small amount of data written by the CDR RA including version, host, and timestamp information.

- Zero or more AVP CDRs - these records will vary in individual size, and usually form the majority of a CDR log.

- A footer - this is empty for Sentinel products.

== Sizing analysis

The combined size of the header, footer, and protobuf overhead is normally trivial (<1KB) compared to the size of each finished CDR log file.

Individual CDR records will vary in size based on dynamic content such as hostnames, Sentinel selection key names, SDP content, and other similarly variable character data. As such, it is not possible to provide exact sizing for a given system without examining the CDR logs written while under a test load, but some approximations can be made.

A basic CDR record containing the information normally written by Sentinel will be on the order of 2000-3000 bytes. With this in mind, the following sections provide rough estimates regarding how much storage would be required for specific scenarios.

If Sentinel is configured to write Session CDRs (i.e. not writing Interim CDRs), then each session will write a single CDR on the order of 2000-3000 bytes.

This section documents the storage requirements for the AVP CDRs written by the CDR RA when Sentinel VoLTE is configured to output Interim CDRs.

=== B2BUA CDR Sizing

This scenario involves writing CDRs for a single leg of a two party call.

Assuming a Start and End CDR are always written for the call, and assuming an average CDR size of 2500 bytes, each call will require a minimum of 5000 bytes. In addition, the Interim CDR feature can be configured to write CDRs periodically as a call progresses, or in response to SDP changes. Each of these events will produce additional records.

Taking these additional timer driven and SDP driven records into account, a rough approximation of the CDR storage requirements can be made with a formula such as:

    2500 * Sessions Per Second * (2 + (Average SDP Driven CDRs Per Session) + (Average Timer Driven Interim CDRs Per Session))

It isn’t possible to use average call length when calculating storage requirements for timer driven CDRs as the number of timer driven CDRs written per call is sensitive to actual rather than average call length.

With the guideline above, we can perform approximations based on an example scenario:

- No SDP changes outside of initial call setup.

- 95% of calls last under the default Interim CDR timer threshold (5 minutes by default).

- 5% of calls last for 59 minutes and trigger numerous timer driven Interim CDRs during that period. With a 5 minute interim CDR timer, this will mean 11 timer driven interim CDRs.

- The overall system is running at 100 session per second.

Using the above, we can assume that the average number of interim timer CDRs per call is `0.05 * 11`, or `0.55` per session. This results in an estimated storage requirement per second of:

    2500 * 100 * (2 + 0 + 0.55) = 637500 bytes / second

or 2189MB / hour

==== Additional considerations for MMTel B2BUAs

MMTel is invoked for originating and terminating triggers, and therefore for each call one originating session and one terminating session.

Therefore MMTel typically uses 2x the storage requirements of a single B2BUA.

It is often the case that terminating calls are not charged unless the served user is roaming; therefore the default configuration for MMTel suppresses writing of SDP CDRs for terminating calls if the served user is not roaming. This is supported through use of the SuppressSdpCdr feature.

=== MMTel Conference CDR sizing

A conference call involves a long lived moderator leg, and one or more short lived consultation legs used to bring an additional users into the conference. A three-party conference call flow is available for reference.

The moderator’s conference leg will write 2 CDRs (start and end) plus additional SDP and timer driven CDRs. The short-lived consultation legs will usually only write 2 CDRs as they are just used to bring additional participants into the conference.

This means that for a three party conference, there will be a minimum of 6 CDRs written, plus any SDP and timer driven CDRs for the moderator leg.

A rough approximation of the CDR storage requirements can be made with a formula such as:

    2500 * Conferences Per Second * ((2 + Average SDP driven CDRs Per Moderator Leg + Average Timer Driven Interim CDRs Per Moderator Leg) + (2 * Average number of participants))

Using the guideline above, if we assume the following scenario:

- No SDP changes outside of initial call setup.

- Each conference has 5 participants.

- Each conference lasts 59 minutes (triggering 11 timer-driven Interim CDRs).

- System is running at 5 conferences per second.

Then we can assume that the CDR storage requirements will be:

    2500 * 5 * ((2 + 0 + 11) + (2 * 5)) = 287500 bytes / second

or 987MB / hour

= Working with CDRs :indexpage:

| Sentinel writes binary CDRs using the CDR RA. Refer to CDR Resource Adaptor section of this guide for more information about Sentinel and the CDR RA.

== List CDRs

The Sentinel SDK contains a List CDRs tool, which can be used to print Sentinel’s binary CDRs files to a human readable format.

The CDR files contain binary encoded Diameter AVPs files in addition to a header and footer. The List CDRs tool decodes the binary CDR file and all the Diameter AVPs which is contains, printing them to the console.

It also supports printing the older 'legacy' CDR format which is not based on AVPs, as used by Sentinel version 2.4.x and earlier.

How to use it in a nutshell:

- Install the SDK normally using the SDK installer script, which will automatically install list-cdrs at `sentinel-volte-sdk/tools/list-cdrs`

- Run `sentinel-volte-sdk/tools/list-cdrs/list-cdrs.sh CDRFILE1 [CDRFILE2]…​`

This guide covers the installation options and customisation options available for List CDRs.

== Protobuf

Protobuf 2.3.0 is required to build and extend CDR modules included with the SDK. This guide covers installing Protobuf for use with the SDK. If using the product "out of the box", Protobuf is not required.

== Topics

- Installing List CDRs— describes how to install the List CDRs tool

- Obtaining CDRs— describes how to obtain CDRs used as input to the List CDRs tool

- Running List CDRs— describes how to run the List CDRs tool

- Extension AVPs— describes how to configure extension AVPs in the List CDRs tool

- Installing Protobuf— describes how to install Protobuf

= Installing List CDRs :sortorder: 1

== Installing the List CDRs tools using the SDK installer

If you install the SDK using the `sentinel-volte-sdk/build/bin/installer` script, then the installer will automatically install the list-cdrs tool at `/home/testuser/sentinel-volte-sdk/list-cdrs/`.

    $ ./build/bin/installer
    [...]

    Creating deployment module deploy-volte ... done.
    [...]

    Configuration changes written.
    [...]

    Installing List CDRs tool ... done.
    [...]

== Installing List CDRs from the SDK using Ant

To install the List CDRs tool using the Ant script instead, use the `install-list-cdrs` Ant build target under the `sentinel-volte-sdk/tools` directory:

    $ cd /home/testuser/sentinel-volte-sdk/tools
    $ ant install-list-cdrs
    Buildfile: /home/testuser/sentinel-volte-sdk/tools/build.xml

    init-build-extensions:

    [...]

    install-list-cdrs:
         [echo]
         [echo] Retrieving List CDRs...
    [ivy:resolve] downloading https://{download-link-host}/artifactory/opencloud-internal-snapshots/opencloud/sentinel-core/3.1.0/sentinel-list-cdrs/3.1.0.0/sentinel-list-cdrs-package-3.1.0.0.zip ...
    [ivy:resolve] ..... (8971kB)
    [ivy:resolve] .. (0kB)
    [ivy:resolve] 	[SUCCESSFUL ] opencloud#sentinel-list-cdrs#sentinel-core/3.1.0;3.1.0.0!sentinel-list-cdrs-package.zip (1143ms)
         [echo]
         [echo] List CDRs retrieved.
         [echo]
         [echo] Installing List CDRs ...
         [echo]
        [unzip] Expanding: /home/testuser/sentinel-volte-sdk/tools/target/sentinel-list-cdrs-package.zip into /home/testuser/sentinel-volte-sdk/tools
         [echo]
         [echo]
         [echo] List CDRs installed.
         [echo] To print CDR files, use the script at list-cdrs/list-cdrs.sh
         [echo] Usage: list-cdrs CDRFILE [CDRFILE]...
         [echo]

    BUILD SUCCESSFUL
    Total time: 14 seconds

| See Setting up Ant in the Sentinel VoLTE SDK guide.

== Installing List CDRs Standalone

The above two approaches are automated ways of installing the List CDRs package (`sentinel-list-cdrs-package.zip`) into a particular location: `sentinel-volte-sdk/tools/list-cdrs/`.

Both the above methods place a List CDRs installer archive at `sentinel-volte-sdk/tools/target/sentinel-list-cdrs-package.zip`.

This `sentinel-list-cdrs-package.zip` archive can be moved to and unzipped into another location outside of the SDK and used as a standalone tool.

To install the List CDRs package as a standalone tool, simply unzip the `sentinel-list-cdrs-package.zip` archive to your chosen destination directory.

The mechanisms for invoking and configuration the List CDRs tools are the same as when running the tool inside the SDK. Simply substitute `/home/testuser/sentinel-volte-sdk/tools/list-cdrs` with `/your/chosen/directory/list-cdrs`.

== Uninstalling List CDRs

If you want to uninstall the List CDRs tool, use the `uninstall-list-cdrs` Ant target under the `sentinel-volte-sdk/tools` directory:

    $ cd /home/testuser/sentinel-volte-sdk/tools
    $ ant uninstall-list-cdrs
    Buildfile: /home/testuser/sentinel-volte-sdk/tools/build.xml

    uninstall-list-cdrs:
         [echo] Uninstalling (deleting) the list-cdrs install from: /home/testuser/sentinel-volte-sdk/tools/list-cdrs/
       [delete] Deleting directory /home/testuser/sentinel-volte-sdk/tools/list-cdrs

    BUILD SUCCESSFUL
    Total time: 0 seconds

Alternatively, just delete the `list-cdrs` directory:

    $ rm -rf sentinel-volte-sdk/tools/list-cdrs/

= Obtaining CDRs :sortorder: 2

== Obtaining CDR files

The List CDRs tool is designed to read completed binary CDR files generated by Sentinel.

Sentinel uses the CDR RA to write CDR files in a binary format. It typically writes these CDR files to the `cdr` directory inside the Rhino installation, and writes these binary CDR files using names such as `cdr_101_1468259745367.log`.

The List CDRs tool can read these completed binary CDR files either in their raw binary format (e.g. `cdr_101_1468259745367.log`), or in gzip compressed format (e.g. `cdr_101_1468259745367.log.gz`).

| Before a CDR file is completed, Sentinel may write a partial CDR file to disk, e.g. `cdr_101_cdr-stream_28929467492591509.tmp`. When a partially written CDR is ready to be rolled over, the CDR RA converts it to a completed binary CDR file, e.g. `cdr_101_1468259745367.log`. The List CDRs tool cannot read partially written CDR files. It can only read complete CDR files.

= Running List CDRs :sortorder: 3

To invoke the List CDRs tool, run the `list-cdrs.sh` script under the `sentinel-volte-sdk/tools/list-cdrs` directory. Pass one or more file paths as arguments, each being a path to a completed binary CDR file generated by Sentinel.

| If the `sentinel-volte-sdk/tools` parent directory does not contain a `list-cdrs` directory, then the List CDRs tool needs to be installed. The Installing List CDRs page describes how to install the List CDRs tool.

Calling the script with no arguments shows the expected syntax:

    $ ./tools/list-cdrs/list-cdrs.sh
    Usage: list-cdrs.sh [--no-header] [--no-footer] [--no-protocol] [--ignore-error]
                        [--output-file OUTPUTFILE] [--size-limit BYTES]
                        [--cdr-filter FIELD=REGEX] CDRFILE [CDRFILE]...

        --no-header              - Disable printing of CDR headers.
        --no-footer              - Disable printing of CDR footers.
        --no-protocol            - Disable printing of protocol and spec revisions
                                   in top level AVPs, e.g. "(Ro,vcb0)".
        --ignore-error           - Continue processing CDRs files when encountering
                                   recoverable errors.
        --list-icids             - List all unique IMS Charging Identifiers in the given CDR file(s),
                                   in order of first appearance.
        --filter-by-icid ICID    - Print CDR message body only when CDR contains the given IMS Charging Identifier.
                                   ICID can be listed by "--list-icids" option.
        --output-file OUTPUTFILE - Append CDR output to OUTPUTFILE rather than to the console.
        --size-limit BYTES       - CDR record size limit. Minimum and default value is
                                   67108864 (64MB). Increase if encountering
                                   "Protocol message was too large" exception.
        --cdr-filter FIELD=REGEX - Print CDR message body only when the given FIELD
                                   matches the given regular expression. FIELD can be
                                   a field name, an AVP name, or an AVP path like
                                   "/IMS-Information/User-Session-Id".
        CDRFILE                  - A completed binary CDR file as produced by Sentinel. Both the new
                                   AVP based format (Sentinel 2.5 and later) and the older
                                   format (Sentinel 2.4 and earlier) are supported. CDR files
                                   can optionally be in gzip format, using a '.gz' suffix.
                                   Partially written CDR files (ending in ".tmp") are not supported.

An example invocation, showing how to print a CDR file:

    $ ./tools/list-cdrs/list-cdrs.sh /path/to/cdr_101_1467865845057.log
    2016-07-07T16:30:36.554+1200 Header {
      ra_name=CDR Generation,
      ra_vendor=OpenCloud,
      ra_version=2.3,
      ra_release=2.3.0.0-M1,
      ra_build=20160706024526,
      ra_revision=cdr-ra/2.3.0@d55f6a1,
      description=CDR session,
      rhino_node=101,
      ra_entity=cdr,
      hostname=mortadella
    }
    2016-07-07T16:30:36.600+1200 AvpCdr {
      avps=[
        Subscription-Id(Ro,vcb0)[
          Subscription-Id-Type[2],
          Subscription-Id-Data[tel:34600000002]
        ],
        IMS-Information(Ro,vcb0)[
          Role-Of-Node[ORIGINATING_ROLE(0)],
          Node-Functionality[AS(6)],
          User-Session-Id[08tE5q0fRdQRrus7F4FWqg],
          Session-Priority[PRIORITY_2(2)],
          Calling-Party-Address[tel:34600000002],
          Called-Party-Address[tel:34600000001],
          Time-Stamps[
            SIP-Request-Timestamp[1467865834000],
            SIP-Response-Timestamp[1467865834000]
          ],
          SDP-Session-Description[v=0],
          SDP-Session-Description[o=- 1000 1000 IN IP4 127.0.0.1],
          SDP-Session-Description[s=test-session],
          SDP-Session-Description[t=0 0],
          Cause-Code[0],
          Early-Media-Description[
            SDP-TimeStamps[
              SDP-Offer-Timestamp[1467865834000],
              SDP-Answer-Timestamp[1467865834000]
            ],
            SDP-Session-Description[v=0],
            SDP-Session-Description[o=- 1000 1000 IN IP4 127.0.0.1],
            SDP-Session-Description[s=test-session],
            SDP-Session-Description[t=0 0]
          ]
        ],
        Service-Context-Id(Ro,vcb0)[12.32274@3gpp.org],
        OC-Sentinel-Selection-Key(Ext,Ext)[DefinitelyNotOpenCloud:DefinitelyNotOpenCloud:sipcall:mmtel-orig:],
        OC-Call-Type(Ext,Ext)[MOC(1)],
        OC-Service-Type(Ext,Ext)[SipCall(2)],
        OC-Charging-Result(Ext,Ext)[2001],
        OC-OCS-Session-Id(Ext,Ext)[diameterclient;diameterro-0;1529370976;0;08tE5q0fRdQRrus7F4FWqg],
        Session-Id(Ro,vcb0)[diameterclient;diameterro-0;1529370976;0;08tE5q0fRdQRrus7F4FWqg],
        OC-OCS-Session-Termination-Cause(Ext,Ext)[0],
        OC-Sentinel-Error(Ext,Ext)[None(1)],
        OC-Charging-Instance(Ext,Ext)[
          OC-Charging-Instance-Name[scur_charging_instance],
          OC-Session-Counter[
            OC-Session-Counter-Address[
              OC-Session-Counter-Address-Key[Subscriber-Id],
              OC-Session-Counter-Address-Value[tel:34600000002]
            ],
            OC-Session-Counter-Address[
              OC-Session-Counter-Address-Key[Service-Id],
              OC-Session-Counter-Address-Value[1]
            ],
            OC-Session-Counter-Address[
              OC-Session-Counter-Address-Key[Cc-Unit-Type],
              OC-Session-Counter-Address-Value[Cc-Time]
            ],
            OC-Cumulative-Committed-Used[1000],
            OC-Cumulative-Granted[60000],
            OC-Cumulative-Granted-Refund[0],
            OC-Cumulative-Requested[60000],
            OC-Cumulative-Requested-Refund[0],
            OC-Cumulative-Sent-Used[1000],
            OC-Cumulative-Suspended-Duration[0],
            OC-Reported-Used[0],
            OC-Pending-Requested[0],
            OC-Start-Time[1467865834000],
            OC-End-Time[1467865836000]
          ]
        ],
        OC-Call-Id(Ext,Ext)[08tE5q0fRdQRrus7F4FWqg],
        MMTel-Information(Ro,vcb0)[
          Supplementary-Service[
            Service-Type[2]
          ],
          Subscriber-Role[ORIGINATING(0)]
        ]
      ]
    }
    2016-07-07T16:30:38.937+1200 AvpCdr {
      avps=[
        Subscription-Id(Ro,vcb0)[
          Subscription-Id-Type[2],
          Subscription-Id-Data[tel:34600000002]
        ],
        IMS-Information(Ro,vcb0)[
          Role-Of-Node[ORIGINATING_ROLE(0)],
          Node-Functionality[AS(6)],
          User-Session-Id[cXD7xzRmA1w4iWBzT9XMdQ],
          Session-Priority[PRIORITY_2(2)],
          Calling-Party-Address[tel:34600000002],
          Called-Party-Address[tel:34600000003],
          Time-Stamps[
            SIP-Request-Timestamp[1467865837000],
            SIP-Response-Timestamp[1467865837000]
          ],
          SDP-Session-Description[v=0],
          SDP-Session-Description[o=- 1000 1000 IN IP4 127.0.0.1],
          SDP-Session-Description[s=test-session],
          SDP-Session-Description[t=0 0],
          Cause-Code[0],
          Early-Media-Description[
            SDP-TimeStamps[
              SDP-Offer-Timestamp[1467865837000],
              SDP-Answer-Timestamp[1467865837000]
            ],
            SDP-Session-Description[v=0],
            SDP-Session-Description[o=- 1000 1000 IN IP4 127.0.0.1],
            SDP-Session-Description[s=test-session],
            SDP-Session-Description[t=0 0]
          ]
        ],
        Service-Context-Id(Ro,vcb0)[12.32274@3gpp.org],
        OC-Sentinel-Selection-Key(Ext,Ext)[DefinitelyNotOpenCloud:DefinitelyNotOpenCloud:sipcall:mmtel-orig:],
        OC-Call-Type(Ext,Ext)[MOC(1)],
        OC-Service-Type(Ext,Ext)[SipCall(2)],
        OC-Charging-Result(Ext,Ext)[2001],
        OC-OCS-Session-Id(Ext,Ext)[diameterclient;diameterro-0;1529370976;2;cXD7xzRmA1w4iWBzT9XMdQ],
        Session-Id(Ro,vcb0)[diameterclient;diameterro-0;1529370976;2;cXD7xzRmA1w4iWBzT9XMdQ],
        OC-OCS-Session-Termination-Cause(Ext,Ext)[0],
        OC-Sentinel-Error(Ext,Ext)[None(1)],
        OC-Charging-Instance(Ext,Ext)[
          OC-Charging-Instance-Name[scur_charging_instance],
          OC-Session-Counter[
            OC-Session-Counter-Address[
              OC-Session-Counter-Address-Key[Subscriber-Id],
              OC-Session-Counter-Address-Value[tel:34600000002]
            ],
            OC-Session-Counter-Address[
              OC-Session-Counter-Address-Key[Service-Id],
              OC-Session-Counter-Address-Value[1]
            ],
            OC-Session-Counter-Address[
              OC-Session-Counter-Address-Key[Cc-Unit-Type],
              OC-Session-Counter-Address-Value[Cc-Time]
            ],
            OC-Cumulative-Committed-Used[1000],
            OC-Cumulative-Granted[60000],
            OC-Cumulative-Granted-Refund[0],
            OC-Cumulative-Requested[60000],
            OC-Cumulative-Requested-Refund[0],
            OC-Cumulative-Sent-Used[1000],
            OC-Cumulative-Suspended-Duration[0],
            OC-Reported-Used[0],
            OC-Pending-Requested[0],
            OC-Start-Time[1467865837000],
            OC-End-Time[1467865838000]
          ]
        ],
        OC-Call-Id(Ext,Ext)[cXD7xzRmA1w4iWBzT9XMdQ],
        MMTel-Information(Ro,vcb0)[
          Supplementary-Service[
            Service-Type[2]
          ],
          Subscriber-Role[ORIGINATING(0)]
        ]
      ]
    }
    2016-07-07T16:30:43.991+1200 AvpCdr {
      avps=[
        Subscription-Id(Ro,vcb0)[
          Subscription-Id-Type[2],
          Subscription-Id-Data[tel:34600000002]
        ],
        IMS-Information(Ro,vcb0)[
          Role-Of-Node[TERMINATING_ROLE(1)],
          Node-Functionality[AS(6)],
          User-Session-Id[AhzD75RR1S7WP1_BN88Ajg],
          Session-Priority[PRIORITY_2(2)],
          Calling-Party-Address[tel:34600000002],
          Called-Party-Address[sip:conf-factory@localhost:5280],
          Requested-Party-Address[sip:conf-factory@localhost:5060],
          Time-Stamps[
            SIP-Request-Timestamp[1467865835000],
            SIP-Response-Timestamp[1467865835000]
          ],
          SDP-Session-Description[v=0],
          SDP-Session-Description[o=- 2000 1000 IN IP4 10.4.1.1],
          SDP-Session-Description[s=test-session],
          SDP-Session-Description[t=0 0],
          Cause-Code[0],
          Early-Media-Description[
            SDP-TimeStamps[
              SDP-Offer-Timestamp[1467865838000],
              SDP-Answer-Timestamp[1467865838000]
            ],
            SDP-Session-Description[v=0],
            SDP-Session-Description[o=- 2000 1000 IN IP4 10.4.1.1],
            SDP-Session-Description[s=test-session],
            SDP-Session-Description[t=0 0]
          ]
        ],
        Service-Context-Id(Ro,vcb0)[12.32274@3gpp.org],
        OC-Sentinel-Selection-Key(Ext,Ext)[DefinitelyNotOpenCloud:DefinitelyNotOpenCloud:sipcall:mmtel-conf:],
        OC-Call-Type(Ext,Ext)[MTC(3)],
        OC-Service-Type(Ext,Ext)[SipCall(2)],
        OC-Charging-Result(Ext,Ext)[2001],
        OC-OCS-Session-Id(Ext,Ext)[diameterclient;diameterro-0;1529370976;1;daJvi_dNie_W_v-fzDOflg],
        Session-Id(Ro,vcb0)[diameterclient;diameterro-0;1529370976;1;daJvi_dNie_W_v-fzDOflg],
        OC-OCS-Session-Termination-Cause(Ext,Ext)[0],
        OC-Sentinel-Error(Ext,Ext)[None(1)],
        OC-Charging-Instance(Ext,Ext)[
          OC-Charging-Instance-Name[scur_charging_instance],
          OC-Session-Counter[
            OC-Session-Counter-Address[
              OC-Session-Counter-Address-Key[Subscriber-Id],
              OC-Session-Counter-Address-Value[tel:34600000002]
            ],
            OC-Session-Counter-Address[
              OC-Session-Counter-Address-Key[Service-Id],
              OC-Session-Counter-Address-Value[3]
            ],
            OC-Session-Counter-Address[
              OC-Session-Counter-Address-Key[Cc-Unit-Type],
              OC-Session-Counter-Address-Value[Cc-Time]
            ],
            OC-Cumulative-Committed-Used[8000],
            OC-Cumulative-Granted[63000],
            OC-Cumulative-Granted-Refund[0],
            OC-Cumulative-Requested[180000],
            OC-Cumulative-Requested-Refund[0],
            OC-Cumulative-Sent-Used[8000],
            OC-Cumulative-Suspended-Duration[0],
            OC-Reported-Used[0],
            OC-Pending-Requested[0],
            OC-Start-Time[1467865835000],
            OC-End-Time[1467865843000]
          ]
        ],
        OC-Call-Id(Ext,Ext)[daJvi_dNie_W_v-fzDOflg],
        MMTel-Information(Ro,vcb0)[
          Supplementary-Service[
            Service-Type[10],
            Associated-Party-Address[tel:34600000002],
            Service-Id[mmtelconf101MpAdqRMBdip0aIpqObY1hQ],
            Change-Time[1467865843000]
          ],
          Subscriber-Role[TERMINATING(1)]
        ]
      ]
    }
    2016-07-07T16:30:45.057+1200 Footer {}

== Logging output

The List CDRs tool writes its main output to the console, but it can be configured to write some extra debugging to a log file.

It uses the log4j logging library, and its log4j configuration file is located at `sentinel-volte-sdk/list-cdrs/log4j.properties`.

By default, it will log to `sentinel-volte-sdk/tools/list-cdrs/logs/list-cdrs.log`. It logs very little when using the default configuration — the log file will typically be empty unless configured for debug logging.

To enable debug logging, change the log level on the last line of the `log4j.properties` file to `DEBUG`:

    log4j.logger.sentinel.cdr=DEBUG

= Extension AVPs :sortorder: 4

== Built-in AVPs and extension AVPs

The binary CDR format contains Diameter AVPs encoded in binary form, and the List CDRs tool decodes these binary AVPs before printing them in a human readable format.

The tool has built-in knowledge of AVPs which are defined in Diameter protocols such as Rf and Ro.

It can also be customized with knowledge of user defined extension AVPs, by providing definitions of those AVPs in YAML files.

The List CDRs tool looks in the `list-cdrs/extension-avps` directory for YAML based files which define these extension AVPs.

A default installation of the List CDRs tool contains a `DiameterExtension-AVP.yaml` file inside this directory, which defines OpenCloud’s extension AVPs. This means that by default, the List CDRs tool recognizes all the AVPs in the CDR files produced by Sentinel.

== Known AVPs vs Undefined AVPs

When encountering an AVP which it does not recognize, the List CDRs tool treats it as an Undefined AVP. Because the tool can’t see which type of AVP it is (e.g. `UTF8String` or `Integer32`), it prints the raw binary content of the AVP in hexadecimal format.

This is how the List CDRs tool will print an extension AVP that it doesn’t recognize:

        Undefined-AVP[code=1029,vendor=19808,hex=64 61 4a 76 69 5f 64 4e 69 65 5f 57 5f 76 2d 66 7a 44 4f 66 6c 67,ascii=daJvi_dNie_W_v-fzDOflg],

This is how the List CDRs tool prints that same extension AVP, when that AVP is configured as an extension AVP (see below):

        OC-Call-Id[daJvi_dNie_W_v-fzDOflg],

== Built-in extension AVPs

This is an excerpt from the default extension AVP configuration file at
`list-cdrs/extension-avps/DiameterExtension-AVP.yaml`, showing the first two extension AVPs:

    $ cat extension-avps/DiameterExtension-AVP.yaml
    !profiles
    DiameterExtension-AVP:
        id:
            name: 'Diameter Extension AVP'
            vendor: 'OpenCloud'
            version: '2.7'
        imports: null
        profiles:
            ? ''
            :   AvpCode: 0
                AvpName: null
                AvpType: null
                MandatoryRule: 1
                ProtectedRule: 1
                VendorId: 0
            OC-Sentinel-Selection-Key:
                AvpCode: 1001
                AvpName: OC-Sentinel-Selection-Key
                AvpType: UTF8String
                MandatoryRule: 1
                ProtectedRule: 1
                VendorId: 19808
            OC-Play-Announcement-Id:
                AvpCode: 1002
                AvpName: OC-Play-Announcement-Id
                AvpType: Integer32
                MandatoryRule: 1
                ProtectedRule: 1
                VendorId: 19808
    [...]

== Customisation of extension AVPs

To configure your own custom AVP, add a new file with the same opening structure as `extension-avps/DiameterExtension-AVP.yaml`, but with your own extensions.

| Be sure to use your own Vendor ID, which we’ll assume to be `19404` below for the sake of example.

An example configuration file:

    $ cat extension-avps/ACME-DiameterExtension-AVP.yaml
    !profiles
    DiameterExtension-AVP:
        id:
            name: 'Diameter Extension AVP'
            vendor: 'OpenCloud'
            version: '2.7'
        imports: null
        profiles:
            ? ''
            :   AvpCode: 0
                AvpName: null
                AvpType: null
                MandatoryRule: 1
                ProtectedRule: 1
                VendorId: 0
            ACME-My-First-Custom-Code:
                AvpCode: 1000
                AvpName: ACME-My-First-Custom-Code
                AvpType: UTF8String
                MandatoryRule: 1
                ProtectedRule: 1
                VendorId: 19404
            ACME-My-Second-Custom-Code:
                AvpCode: 1000
                AvpName: ACME-My-Second-Custom-Code
                AvpType: UTF8String
                MandatoryRule: 1
                ProtectedRule: 1
                VendorId: 19404
    [...]

After you have created such a file you will also have to add the AVP names to the `Charging` profile in the `DiameterExtensions` profile table, which lives in the file `extension-avps/DiameterExtensions.yaml`. The profile consists of an array that lists all of the desired AVPs in the format `<profile table name>/<profile name>`. So for the two AVPs from the example above you would have to add these two lines to the `Charging` profile:

    - DiameterExtension-AVP/ACME-My-First-Custom-Code
    - DiameterExtension-AVP/ACME-My-Second-Custom-Code

Note that the profile to use for the supported extension AVP list is configured with the `ExtensionAvpSet` property of the Diameter RA. See Configuring Extension AVPs for the full documentation of these profile tables.

The required fields for each AVP:

AvpCode

  The code of the AVP. If using your own vendor code, then this AVP code is within your own namespace.

AvpName

  The name of the AVP.

AvpType

  The type of the AVP. See the available AVP types below.

MandatoryRule

  The "M" bit or Mandatory bit. Indicates whether support of the AVP is mandatory on the receiving end. Valid values are:

  - 0 - MUST

  - 1 - MAY

  - 2 - MUSTNOT

ProtectedRule

  The "P" bit, indicating the need for encryption. Valid values are:

  - 0 - MUST

  - 1 - MAY

  - 2 - MUSTNOT

VendorId

  The Vendor ID of the company which has defined this AVP.

The available AVP types

  - `OctetString`

  - `Integer32`

  - `Integer64`

  - `Unsigned32`

  - `Unsigned64`

  - `Float32`

  - `Float64`

  - `Grouped`

  - `Address`

  - `Time`

  - `UTF8String`

  - `DiameterIdentity`

  - `DiameterURI`

  - `Enumerated`

  - `IPFilterRule`

  - `QoSFilterRule`

  - `Undefined`

= Installing Protobuf :sortorder: 5

Protobuf 2.3.0 is required to build and extend CDR modules included with the SDK. The SDK infrastructure makes this version available for download from an Ant target.

| Protobuf 2.3.0 can be downloaded as a standalone package here. To complete installation, follow the instructions in the included `README.txt`.

== Installing Protobuf from the SDK using Ant

To install Protobuf use the `install-protobuf` Ant build target under the `sentinel-volte-sdk/tools` directory:

    $ cd /home/testuser/sentinel-volte-sdk/tools
    $ ant install-protobuf

    init-build-extensions:

    [...]

    init-tools-common:

    install-protobuf:
         [echo]
         [echo] Retrieving Protobuf...
        [mkdir] Created dir: /home/testuser/sentinel-volte-sdk/tools/target
          [get] Getting: https://s3-ap-southeast-2.amazonaws.com/ocaws-downloads/third-party/google/protobuf/protobuf-2.3.0.tar.gz
          [get] To: /home/testuser/sentinel-volte-sdk/tools/target/protobuf-2.3.0.tar.gz
          [get] ....................................................
          [get] ....................................................
          [get] ....................................................
          [get] ....................................................
          [get] .....
         [echo]
         [echo] Protobuf retrieved.
         [echo]
         [echo] Unpacking Protobuf...
         [echo]
       [gunzip] Expanding: /home/testuser/sentinel-volte-sdk/tools/target/protobuf-2.3.0.tar.gz to /home/testuser/sentinel-volte-sdk/tools/target/protobuf-2.3.0.tar
        [untar] Expanding: /home/testuser/sentinel-volte-sdk/tools/target/protobuf-2.3.0.tar into /home/testuser/sentinel-volte-sdk/tools
         [echo]
         [echo]
         [echo] Protobuf unpacked.
         [echo] Requires further install steps, please read protobuf-2.3.0/README.txt for further details.
         [echo]

    BUILD SUCCESSFUL
    Total time: 6 seconds

| See Setting up Ant in the Sentinel VoLTE SDK guide.

To complete installation, follow the instructions in `sentinel-volte-sdk/tools/protobuf-2.3.0/README.txt`.

== Uninstalling Protobuf

If you want to uninstall the version of Protobuf installed by the SDK, use the `uninstall-protobuf` Ant target under the `sentinel-volte-sdk/tools/` directory:

    $ cd /home/testuser/sentinel-volte-sdk/tools
    $ ant install-protobuf

    init-build-extensions:

    [...]

    init-tools-common:

    uninstall-protobuf:
         [echo] Uninstalling (deleting) the protobuf install from: /home/testuser/sentinel-volte-sdk/tools/protobuf-2.3.0/
       [delete] Deleting directory /home/testuser/sentinel-volte-sdk/tools/protobuf-2.3.0

    BUILD SUCCESSFUL
    Total time: 2 seconds

Alternatively, just delete the `protobuf-2.3.0` directory:

    $ rm -rf sentinel-volte-sdk/tools/protobuf-2.3.0/

= XCAP Server :sortorder: 10 :toc: macro :toclevels: 4 :toc-title: On this page…​

The XCAP Server is a software component that runs inside a web application called Rhino Element Manager (or REM for short).

It uses OpenCloud’s Sh Cache Microservice to communicate with the HSS.

| For information on this piece of the Sentinel VoLTE product architecture, please see XCAP Support.

== Example XCAP queries

XCAP Query Examples provide several examples of XCAP queries to get and modify the simservs document.

== Sh Cache Microservice Client configuration

The Sh Cache Microservice Client stack must be configured before running the XCAP server. See Configuring the Sh Cache Microservice Client for the XCAP Server and REM.

== HTTP configuration

The XCAP Server runs inside an HTTP servlet container. To configure it, please see that container’s documentation.

== XCAP simservs configuration

The XCAP simservs configuration defines how an XML simservs document (typically coming from a UE) is mapped into an MMTel services document (stored in transparent data in the HSS). This mapping must be configured into the product post install. A tool is available that will populate simservs and XCAP server settings.

The rest of this section describes how to manually configure those same settings, it can be skipped if the tool is used.

This configuration is defined using XPath:

1 | Select Sentinel ▶ XCAP — Simservs. The resulting panel differs depending on whether a configuration has already been entered for the network operator.
Not yet configured | This occurs if (for example) the network operator has not been configured yet. In the following image, a network operator called `TestOperator` is selected.
Configured | In this case, the network operator has not been selected, so the default platform configuration is displayed, for which Simservs mappings have already been configured.
2 | For an existing configuration, to enter sufficient XCAP Simservs mappings for IR.92: Click the + Add New button. Click the + Add Mapping Group button. A popup prompts you to enter details. Enter the following details.
| You can enter the defaults in a selected text box by pressing the “down arrow” key (↓).
Field Name | Required value for IR.92
--- | ---
Service indication |
    MMTEL-Services
Service data class |
    com.opencloud.volte.sentinel.simservs.xcap.TMMTelServicesType
Service data codec class |
    com.opencloud.volte.sentinel.provisioning.hss.TMMTelServicesCodec
JXPath factory class |
    com.opencloud.volte.sentinel.simservs.xcap.MMTelJXPathFactory
3 | With the mapping group created, add mappings: Click the + Add Mapping button. A prompt displays to enter the mapping. Enter the Simservs Path and HSS Document Path. Click the Save button. Enter these defaults:
Simservs Path | HSS Document Path
--- | ---
    originating-identity-presentation
    complete-originating-identity-presentation/originating-identity-presentation
    originating-identity-presentation-restriction
    complete-originating-identity-restriction/originating-identity-presentation-restriction
    communication-diversion
    complete-communication-diversion/communication-diversion
    communication-waiting
    complete-communication-waiting/communication-waiting
    terminating-identity-presentation
    complete-terminating-identity-presentation/terminating-identity-presentation
    terminating-identity-presentation-restriction
    complete-terminating-identity-restriction/terminating-identity-presentation-restriction
    incoming-communication-barring
    complete-communication-barring/incoming-communication-barring
    outgoing-communication-barring
    complete-communication-barring/outgoing-communication-barring

=== XCAP simservs extensions mappings

The XCAP server also supports simservs extensions mappings. This allows arbitrary elements of any transparent user data XML document from the HSS to be mapped to an element in the simservs document under the `extensions` parent element.

Examples:

Simservs Path | HSS Document Path
--- | ---
    extensions/operator-flexible-alerting
    complete-flexible-alerting/operator-flexible-alerting
    extensions/operator-flexible-alerting-group
    complete-flexible-alerting/operator-flexible-alerting-group

In these examples, select parts of operator data from the MMTel services document are being exposed to the UE for viewing and updating via XCAP as part of the Simservs document. Each can be specifically accessed via the simservs XCAP URL with the node selector specified as per the simservs path in the mapping.

==== Rules for creating extensions mappings

- An extension simservs path must start with `extensions/`.

- The element name after `extensions/` can be any alphanumeric string. Special characters are not allowed.

- The element name must be singular. e.g. `extensions/path1` is ok, but `extensions/path1/path2` is not.

- The HSS document path has to match an actual location in the HSS data.

- Only simple element names can be used for the HSS Document Path. i.e. no positional or attribute selectors.

| Extensions mappings have to be created in the group corresponding to the service indication they are for, alongside the pre-configured mappings.

== XCAP authentication

In the absence of an Authentication Proxy (AP), the XCAP server can be configured to authenticate requests itself using OpenCloud Sentinel AGW. Sentinel AGW provides an implementation of 3GPP GAA (Generic Authentication Architecture) procedures.

For more information, and instructions on configuring the XCAP Server with Sentinel AGW, see the Sentinel AGW Guide.

== Normalization

The XCAP server tries to normalize any numbers contained in CDIV rule targets and ICB/OCB conditions before accepting the request. If any number cannot be normalized, the request is rejected. Normalization is done using the Normalization Component.

Normalization can be disabled by setting the following config property, as described in the Provisioning Configuration section.

=== `volte.xcap.normalization.enabled`

Description | Whether to apply normalization to numbers contained in CDIV rule targets and ICB/OCB conditions.
Java type | boolean
Default value | true
Example | `volte.xcap.normalization.enabled=false`

== MMTelCDIV Non-Provisionable Retarget URIs

The MMTelCDIV feature can be configured with a list of `NonProvisionableRetargetURIs`. As the name implies, any XCAP request containing a diversion rule with a target equal to a URI on this list, after they are both normalized, is rejected.

== Operator Determined Barring

When any request is received, the XCAP server checks if the subscriber is barred from using the XCAP server (due to `Barring of Supplementary Services Management` being set), or if updating diversion rules, is barred from registering diverted numbers (`Diverted to Address Registration Barring`). To do so, it queries the Sh Cache Microservice for the `IMS-ODB-Information` service indication. If the XCAP server determines the request is not allowed, it is rejected with response code 403.

= Sentinel VoLTE Manual Upgrade Procedure :sortorder: 11 :indexpage:

This page describes how to manually upgrade a Sentinel VoLTE 3.1.0.x install to a newer version of 3.1.0.x. This procedure includes saving the configuration from your running system, installing a new version, and then applying the configuration from the old install to the new install. Generally you can just use the sentinel-volte-sdk installer to install a new version. However if you have bespoke post-install configuration in your current Sentinel VoLTE install that you want to retain, you can follow these instructions.

| This manual procedure is no longer the recommended way to upgrade VoLTE in production. Use the semi-automated VoLTE upgrade procedure instead. However, this manual procedure still applies when using the Rhino SDK.

This page does not cover upgrading between major releases, e.g. 2.7.0.x to 3.1.0.x.

This upgrade procedure should not be used in conjunction with changes to your installer choices, e.g. changing from HSS to HLR. A fresh install is required if you wish to change your network components.

It may be necessary to increase the Rhino Management Tools default memory settings in order to successfully export and import profiles. See Rhino Management Tools Memory Considerations for more details.

- Rhino Production— Use these instructions if you are using a Rhino Production Cluster.

- Rhino SDK— Use these instructions if you are using the Rhino SDK.

= Rhino Production

Manual Upgrade of a Sentinel VoLTE 3.1.0 install in a Rhino Production Cluster

| This manual procedure is no longer the recommended way to upgrade VoLTE in production. Use the semi-automated VoLTE upgrade procedure instead.

This document assumes a 2 node cluster, with each node on a separate server. Modify the steps accordingly if you have more nodes.

== Upgrade Steps

1 | From the Rhino client bin directory
    $ cd ~/rhino/client/bin
2 | Run a Rhino full export
    $ ./rhino-export -J backup
3 | On the node101 server, stop Rhino
    $ cd ~/rhino/node101
    $ ./stop-rhino.sh --node 101
4 | On the node102 server, stop Rhino
    $ cd ~/rhino/node102
    $ ./stop-rhino.sh --node 102
5 | Stop REM from the init-d directory (if you followed these post install Instructions
    /etc/init.d/rem stop
otherwise you can stop Catalina.
    $TOMCAT_HOME/bin/catatlina.sh stop
6 | Backup your Apache Tomcat install to a new location
    $ mv apache-tomcat* apache-tomcat.old
7 | If you have configured REM redundancy, repeat steps 5 and 6 on each node where you have Apache Tomcat REM installed
8 | On the node101 server, backup the node101 directory to a new location
    $ cd ~/rhino
    $ mv node101 node101.old
9 | On the node101 server, recreate node101 (say yes to initializing the db)
    $ ./create-node.sh
10 | On the node102 server, backup the node102 directory to a new location
    $ cd ~/rhino
    $ mv node102 node102.old
11 | On the node102 server, recreate node102 (say yes to initializing the db)
    $ ./create-node.sh
12 | Copy any configuration settings that you changed during your initial install from your old node101 directory to your new node101 directory. e.g. jvm settings, paths, ports etc.
13 | Start node101
    $ cd ~/rhino/node101
    $ ./start-rhino.sh -p -s
14 | Copy any configuration settings that you changed during your initial install from your old node102 directory to your new node102 directory. e.g. jvm settings, paths, ports etc.
15 | Start node102
    $ cd ~/rhino/node102
    $ ./start-rhino.sh -s
16 | Install your license into Rhino
    $ cd ~/rhino/client/bin
    $ ./rhino-console installlicense [PATH_TO_LICENSE_FILE]
17 | Install the new Sentinel VoLTE version and REM extension as per these instructions: Installing Sentinel VoLTE Services

You can use the default answers for the installer questions, as your config will be overwritten at step 18 with your backed-up data. Alternatively, install VoLTE using the installer in Non-interactive mode using the unedited `install.properties` file from the previous installation.

- Installing the Sentinel VoLTE Provisioning Module

- Post Installation Instructions

|18 |Import the exported profiles into Rhino

    $ cd ~/rhino/client/bin
    $ for i in backup/profiles/*; do ./rhino-console importprofiles $i -replace; done

|19 |Restart Rhino nodes and REM

:leveloffset!: :ocdoc_current_file: /mnt/volume-01/jenkins/workspace/product/sentinel/sentinel-volte-documentation/release-3.1.0/Auto/volte-documentation/target/generated/sentinel-volte-administration-guide/sentinel-volte-upgrade-procedure/rhino-sdk.adoc :here: sentinel-volte-upgrade-procedure/ :idprefix: rhino-sdk :leveloffset: 1 = Rhino SDK Manual Upgrade of a Sentinel VoLTE 3.1.0 install in a Rhino SDK == Upgrade Steps [cols="1h,19a" width="95"]

|1 |From the Rhino SDK client bin directory

    $ cd $RHINO_INSTALL_DIR/RhinoSDK/client/bin

|2 |Run a Rhino full export. For more information see Rhino Administration Guide - Export and Import.

    $ ./rhino-export -J backup

|3 |Stop Rhino

    $ cd ../../RhinoSDK
    $ ./stop-rhino --nice

|4 |Stop REM from the init-d directory (if you followed these post install Instructions

    /etc/init.d/rem stop

otherwise you can stop catalina.

    $TOMCAT_HOME/bin/catatlina.sh stop

|5 |From the Rhino install directory move the Rhino SDK directory to a new location

    $ mv RhinoSDK RhinoSDK.old

|6 |From the Rhino install directory unzip the Rhino SDK install zip

    $ unzip rhino-sdk-2.6.1.x.zip

|7 |Install the new Sentinel VoLTE version and REM extension as per these instructions:

- Preparing to Install Sentinel VoLTE

- Install VoLTE using the installer in Non-interactive mode using the unedited `install.properties` file from the previous installation.

- Installing the Sentinel VoLTE Provisioning Module

- Post Installation Instructions

|8 |Start Rhino

    $ cd ~/RhinoSDK
    $ ./start-rhino.sh

|9 |From the Rhino client bin directory

    $ cd RhinoSDK/client/bin

|10 |Copy the backup directory (export) created as part of the export step (step 2) to the new Rhino SDK install

    $ cp -R ../../../RhinoSDK.old/client/bin/backup .

|11 |Import the exported profiles into the Rhino SDK environment. For more information see Rhino Administration Guide - Export and Import.

    $ for i in backup/profiles/*; do ./rhino-console importprofiles $i -replace; done

|12 |Restart Rhino and REM

:leveloffset!: :ocdoc_current_file: /mnt/volume-01/jenkins/workspace/product/sentinel/sentinel-volte-documentation/release-3.1.0/Auto/volte-documentation/target/generated/sentinel-volte-administration-guide/dns-redundancy.adoc :here: :idprefix: dns-redundancy :leveloffset: 1 = DNS Redundancy :sortorder: 12 :toc: macro :toclevels: 4 :toc-title: On this page…​ This page provides notes and guidance regarding DNS based redundancy for a Sentinel VoLTE TAS cluster. toc::[] == Background SIP Routing mechanism The AS URI defined within a subscriber’s iFC is targeted by the S-CSCF using DNS procedures defined by RFC 3263 which can be summarised as follows: * Determine a transport protocol (NAPTR query) * Find a server port on a hostname (SRV query) * Find an IP Address (A-Record query) Step 2 is relevant here. The structure of a SRV record is: [source,role="small"] ---- _Service._Proto.Name TTL Class SRV Priority Weight Port Target ---- RFC 2782 provides more detail. The information element of particular interest is the "Priority". Multiple results are sorted in priority order and when communication toward one fails the next is chosen. RFCs 2782 and 3263 provide details. Additionally, the response received to an SRV query can be determined by the source IP Address using DNS "views" functionality which enables co-ordinated preference routing between IMS sites. NOTE: The use of TCP is assumed in this page, as in general, we recommend the use of SIP over TCP rather than UDP. If the use of UDP is required, then the DNS setup will need to add records using `_sip._udp.` for the Protocol (Proto) part of the SRV record. == Redundancy in a site image::features/mmtel-features/ClusterDNS-onesite.png[] === Domain names for each node [cols="20a,30a,30a,30a" options="header"]

|Node name |Domain name |Rhino node ID |Savanna Cluster ID

| VoLTE-1 | node1.site1.domain | 101 | 1

| VoLTE-2 | node2.site1.domain | 102 | 1

| VoLTE-3 | node3.site1.domain | 103 | 1

| VoLTE-4 | node4.site1.domain | 104 | 1

== DNS configuration to support the iFC address The DNS design for this product allows a subscriber to be served by any node in the cluster. There is no mapping of subscriber to node. Therefore there is no subscriber-level configuration/provisioning necessary at a DNS level. A "cluster-wide" domain name is used in the Application Server URI(s) in the IMS Initial Filter Criteria (iFC). === DNS SRV configuration For iFC configuration, only one Application Server URI is needed for each Application Server role. Typically there are two roles, the SCC-AS, and the MMTel-AS. Therefore, then only two Application Server URIs are configured for the purposes of iFC. [source,role="small"] ---- sip:tas-cluster.domain;transport=tcp;oc-mode=scc sip:tas-cluster.domain;transport=tcp;oc-mode=mmtel ---- All nodes are treated the same, therefore the DNS SRV result should return all nodes with equal priority. This means that nodes receive an equal amount of traffic. SRV Query: [source,role="small"] ---- _sip._tas-cluster.domain ---- SRV response: [source,role="small"] ---- _sip._tcp.node1.site1.domain 3600 IN SRV 20 0 5060 node1.site1.domain _sip._tcp.node2.site1.domain 3600 IN SRV 20 0 5060 node2.site1.domain _sip._tcp.node3.site1.domain 3600 IN SRV 20 0 5060 node3.site1.domain _sip._tcp.node4.site1.domain 3600 IN SRV 20 0 5060 node4.site1.domain ---- == Record Routing Sentinel VoLTE typically acts as a form of Back-to-Back User Agent (B2BUA). As such it records route on the vast majority of call cases. === Record Route for non replicated sessions When not replicating session state, the IP address of the node is record routed. This means that all subsequent requests for a session go to the particular cluster node. === Record Route to enable fail-over of sticky sessions A sticky session means that a particular session has to be processed by a single node. It only "migrates" between nodes if that node fails. When replicating session state with sticky sessions, instead of record routing the IP address, the node’s own SIP URI is used as a basis for record routing. This per-node SIP URI is not the same as the URI used for iFC. When Sentinel VoLTE records route for sticky sessions, it records route using a pattern that converts the IP address of the node into a particular domain name. For example a node with an IP address of `192.168.10.20` then a domain name such as `node-192-168-10-20.tas-cluster.site1.domain` is used. Paired with this IP is a related SRV configuration. This means every single TAS cluster node has its own node-specific SRV record. NOTE: This type of domain name is configured through the `DynamicSRVNameFormat` that is entered as part of installation. It can be modified post-installation as per SIP SIS RA Network Interface changes. === Node specific SRV record for fail-over of sticky sessions Each node’s own SRV record includes the node itself as the most important priority (zero is the most important priority in SRV). Then, every other cluster node are equal at a less important priority. For node 1 - we see [source,role="small"] ---- ;; SRV address Priority Weight Port Target _sip._tcp.node-192-168-10-20.tas-cluster.site1.domain. <ttl> IN SRV 0 1 5060 node1.site1.domain. _sip._tcp.node-192-168-10-20.tas-cluster.site1.domain. <ttl> IN SRV 10 1 5060 node2.site1.domain. _sip._tcp.node-192-168-10-20.tas-cluster.site1.domain. <ttl> IN SRV 10 1 5060 node3.site1.domain. _sip._tcp.node-192-168-10-20.tas-cluster.site1.domain. <ttl> IN SRV 10 1 5060 node4.site1.domain. ;; ADDITIONAL SECTION: node1.site1.domain <ttl> IN A 192.168.10.20 node2.site1.domain <ttl> IN A 192.168.10.21 node3.site1.domain <ttl> IN A 192.168.10.22 node4.site1.domain <ttl> IN A 192.168.10.23 ---- When a SIP client receives a Record-Route header such as `<sip:node-192-168-10-20.tas-cluster.site1.domain;transport=tcp>` and DNS is configured as above, the client must try `node1` first as it is the only entry at priority 0. If that fails, it will try one of `node2`, `node3`, or `node4` next. There are some subtleties to note. When sticky session fail-over is enabled, the Record-Route inserted by the TAS omits the port and includes the transport parameter. This forces SIP clients to perform an SRV lookup, by the rules of RFC3263, and retrieve the weighted results. For example, given a Record-Route containing the URI `<sip:node-192-168-10-20.domain;transport=tcp>`, a SIP client must look up the `_sip._tcp.node-192-168-1-20.domain` SRV record, and retrieve the weighted list of addresses to use. If the URI had a port, then by the rules of RFC3263 the client would have to skip the SRV lookup, and instead perform an A record lookup on `node-192-168-10-20.domain`, which would fail. == A complete example In this example the preceding sections are put together to provide a four node cluster, with an iFC address where: * all nodes receive equal traffic, and * every node has an equal number of backup nodes, so that load is spread evenly after a node failure [source,role="small"] ---- ;; SRV address Priority Weight Port Target ;; cluster wide domain name _sip._tcp.tas-cluster.site1.domain. <ttl> IN SRV 0 1 5060 node1.site1.domain. _sip._tcp.tas-cluster.site1.domain. <ttl> IN SRV 0 1 5060 node2.site1.domain. _sip._tcp.tas-cluster.site1.domain. <ttl> IN SRV 0 1 5060 node3.site1.domain. _sip._tcp.tas-cluster.site1.domain. <ttl> IN SRV 0 1 5060 node4.site1.domain. ;; node 1 _sip._tcp.node-192-168-10-20.tas-cluster.site1.domain. <ttl> IN SRV 0 1 5060 node1.site1.domain. _sip._tcp.node-192-168-10-20.tas-cluster.site1.domain. <ttl> IN SRV 10 1 5060 node2.site1.domain. _sip._tcp.node-192-168-10-20.tas-cluster.site1.domain. <ttl> IN SRV 10 1 5060 node3.site1.domain. _sip._tcp.node-192-168-10-20.tas-cluster.site1.domain. <ttl> IN SRV 10 1 5060 node4.site1.domain. ;; node 2 _sip._tcp.node-192-168-10-21.tas-cluster.site1.domain. <ttl> IN SRV 0 1 5060 node2.site1.domain. _sip._tcp.node-192-168-10-21.tas-cluster.site1.domain. <ttl> IN SRV 10 1 5060 node3.site1.domain. _sip._tcp.node-192-168-10-21.tas-cluster.site1.domain. <ttl> IN SRV 10 1 5060 node4.site1.domain. _sip._tcp.node-192-168-10-21.tas-cluster.site1.domain. <ttl> IN SRV 10 1 5060 node1.site1.domain. ;; node 3 _sip._tcp.node-192-168-10-22.tas-cluster.site1.domain. <ttl> IN SRV 0 1 5060 node3.site1.domain. _sip._tcp.node-192-168-10-22.tas-cluster.site1.domain. <ttl> IN SRV 10 1 5060 node4.site1.domain. _sip._tcp.node-192-168-10-22.tas-cluster.site1.domain. <ttl> IN SRV 10 1 5060 node1.site1.domain. _sip._tcp.node-192-168-10-22.tas-cluster.site1.domain. <ttl> IN SRV 10 1 5060 node2.site1.domain. ;; node 4 _sip._tcp.node-192-168-10-23.tas-cluster.site1.domain. <ttl> IN SRV 0 1 5060 node4.site1.domain. _sip._tcp.node-192-168-10-23.tas-cluster.site1.domain. <ttl> IN SRV 10 1 5060 node1.site1.domain. _sip._tcp.node-192-168-10-23.tas-cluster.site1.domain. <ttl> IN SRV 10 1 5060 node2.site1.domain. _sip._tcp.node-192-168-10-23.tas-cluster.site1.domain. <ttl> IN SRV 10 1 5060 node3.site1.domain. ;; ADDITIONAL SECTION: node1.site1.domain <ttl> IN A 192.168.10.20 node2.site1.domain <ttl> IN A 192.168.10.21 node3.site1.domain <ttl> IN A 192.168.10.22 node4.site1.domain <ttl> IN A 192.168.10.23 ---- NOTE: Corresponding records would be needed for UDP (_sip._udp.) and SCTP (_sip._sctp.) if those transports were used. :leveloffset!: :ocdoc_current_file: /mnt/volume-01/jenkins/workspace/product/sentinel/sentinel-volte-documentation/release-3.1.0/Auto/volte-documentation/target/generated/sentinel-volte-administration-guide/feature-source.adoc :here: :idprefix: feature-source :leveloffset: 1 = Feature Source :sortorder: 13 :toc: macro :toclevels: 4 :toc-title: On this page…​ Source code is available for all of Sentinel VoLTE’s MMTel features and most of its general features. Source for some of the "base" Sentinel features is also provided. The code can be viewed by using the `create-module` command in the SDK to create a new module from the module pack that contains the feature. For more information on creating a feature, refer to Creating a Feature. == Features with Source Available The following tables list the features that have source code available through the SDK, and the name of module packs that contain their source. === General VoLTE Features [cols="1,1" options="header"]

| Feature | Module Pack | SubscriberDataLookupFromHLR | volte-hlr-subscriber-data-lookup | SubscriberDataLookupFromHSS | volte-hss-subscriber-data-lookup-2 | SubscriberDataLookupFromHSSOld | volte-hss-subscriber-data-lookup | IMSIDLookup | volte-imsid-lookup | IMSIDLookupFromCassandraSIP | volte-imsid-lookup-cassandra-sip | IMSIDLookupFromCassandraIN | volte-imsid-lookup-cassandra-in | VoLTE SIP AVP CDR | volte-avp-cdr-feature | VoLTE Interim CDR | volte-interim-cdr | Determine International and Roaming Status | volte-determine-international-and-roaming-status

=== MMTel Features [cols="1,1" options="header"]

| Feature | Module Pack | MMTel Conference | mmtel-conferencing | MMTel Conference Subscription | mmtel-conferencing | MMTelCDIV | mmtel-communication-diversion | MMTelCW | mmtel-communication-waiting | MMTelECT | mmtel-explicit-communication-transfer | MMTelHold | mmtel-communication-hold | MMTelICB | mmtel-communication-barring | MMTelOCB | mmtel-communication-barring | MMTelOIP | mmtel-id-presentation-restriction | MMTelOIR | mmtel-id-presentation-restriction | MMTelTIP | mmtel-id-presentation-restriction | MMTelTIR | mmtel-id-presentation-restriction | Flexible Alerting Features | mmtel-flexible-alerting | MMTel Wifi Charging Finalisation| mmtel-wifi-charging-finalisation | Session Transfer to Own Device | mmtel-session-transfer | Geo Local Normalization | mmtel-geo-local-normalization

=== Base Sentinel Features [cols="1,1" options="header"]

| Feature | Module Pack | Do Not Monitor Session | sentinel-core-do-not-monitor-session-feature | OCS Round Robin | sentinel-core-ocs-round-robin-feature | Platform Operator is Network Operator | sentinel-core-platform-operator-is-network-operator-feature | Session Tracing Activation | sentinel-core-session-tracing-feature | Subscriber Data Lookup | sentinel-core-subscriber-data-lookup-feature | SIP Determine Network Operator | sentinel-sip-determine-network-operator-feature | AVP CDR Feature | sentinel-sip-avp-cdr-feature and sentinel-sip-avp-cdr-util | Interim CDR Feature | sentinel-sip-interim-cdr

=== Example Features [cols="1,1" options="header"]

| Feature | Module Pack | Sentinel SIP Example | sentinel-sip-example | VoLTE Example POJO | volte-example-pojo-feature | VoLTE Example SBB | volte-example-sbb-feature

:leveloffset!: :ocdoc_current_file: /mnt/volume-01/jenkins/workspace/product/sentinel/sentinel-volte-documentation/release-3.1.0/Auto/volte-documentation/target/generated/sentinel-volte-administration-guide/resource-adaptors/index.adoc :here: resource-adaptors/ :idprefix: resource-adaptors :leveloffset: 1 = Resource Adaptors :indexpage: :sortorder: 14 In Rhino, a resource adaptor (RA) provides the interface between the application (Sentinel VoLTE) and the network. Sentinel VoLTE makes use of a number of Resource Adaptors, for purposes ranging from database connections to network integration. == OpenCloud Resource Adaptors used by Sentinel VoLTE Sentinel VoLTE configures the following Resource Adaptor Entities out of the box. [cols="1a,2a,2a" options="header"]

| Resource Adaptor Entity | Deployment | Purpose

| cassandra-third-party-reg | All | communication with the Cassandra Database for Third Party Registrar

| cassandra-general | All | communication with the Cassandra Database for other purposes

| cdr | All | writing of call detail records (or 3GPP Charging Data Records)

| cginmapra | MMTel GSM, SCC GSM, Full GSM | unused by default

| cginra | MMTel GSM, SCC GSM, Full GSM | IMS Service Centralisation (i.e. Re-origination) for CAP traffic

| cgin-cdma-ra | SCC CDMA, Full CDMA | IMS Service Centralisation (i.e. Re-origination) for CDMA traffic

| dbquery-0 | All | communication with an SQL Database

| diameter-sentinel-internal | All | internal Ro communication between protocol handling front-ends and the internal mediation subsystem

| diameterro-0 | All | communication with Online Charging Systems

| etcari-correlation-ra | All | CAMEL features

| http | All | enabling queries to external systems (such as RESTful queries), or enabling `click to call` style scenarios

| imssf-cdr | MMTel GSM, SCC GSM, Full GSM | used by IMSSF

| imssf-diameterro | MMTel GSM, SCC GSM, Full GSM | used by IMSSF

| imssf_management | MMTel GSM, SCC GSM, Full GSM | used by IMSSF

| reorigination-correlation-ra | All | IMS Service Centralisation via CAMEL triggers

| rf-control-ra | All | Charging over Diameter Rf interface

| sentinel-management | All | management of Sentinel subsystems

| sh-cache-microservice-ra | All | communication with the HSS

| sip-sis-ra | All | SIP interface for the TAS

| sipra | All | utility mechanisms for the SIP protocol

| sis-in | MMTel GSM, SCC GSM, Full GSM | querying the HLR

| uid | All | allocation of globally unique IDs

NOTE: For explanation of the deployment types see Deployment Structure TIP: All these RAs can be viewed and configured using the Sentinel Element Manager. Future releases of Sentinel will have resource adaptors to support other protocols, such as Diameter CCA. Customers can also add their own resource adaptors, using the Sentinel VoLTE SDK. == Further information on specific Resource Adaptors Below are overviews of: * CDR Resource Adaptor * CGIN Resource Adaptor * Correlation Resource Adaptor * Diameter Resource Adaptor * HLR MAP Configuration * SIP SIS Resource Adaptor * Sh Cache Microservice Resource Adaptor Guide * Rf Control Resource Adaptor :leveloffset!: :ocdoc_current_file: /mnt/volume-01/jenkins/workspace/product/sentinel/sentinel-volte-documentation/release-3.1.0/Auto/volte-documentation/target/generated/sentinel-volte-administration-guide/resource-adaptors/cdr-resource-adaptor.adoc :here: resource-adaptors/ :idprefix: cdr-resource-adaptor :leveloffset: 1 = CDR Resource Adaptor == CDR resource adaptor entities The Sentinel installer creates a CDR resource adaptor entity called `cdr`. This resource adaptor entity is used by all Sentinel services. == CDR resource adaptor configuration NOTE: Refer to the CDR RA Documentation for more information about the CDR RA. The `cdr` resource adaptor entity is configured to use the `cdr-stream` profile of the `CdrStreamConfiguration` profile table by default. The output behaviour of the CDR resource adaptor can be customised by modifying this profile in accordance with the CDR RA Documentation. == Sentinel configuration requirements The `cdr` RA entity must be configured with `CdrFileType=Binary`.

For more information about CDRs in the Sentinel platform, refer to:

- Working with CDRs section of this administration guide to learn about the content of Sentinel CDRs.

- Customising CDRs in the Extending Sentinel with the SDK guide to learn how to customise the format of the CDRs that Sentinel creates, as well as customising the data included in the CDRs.

= CGIN Resource Adaptor

== CGIN resource adaptor entities

| Refer to the CGIN documentation for more information about the CGIN resource adaptor.

Depending on whether the deployment includes SCC-GSM or SCC-CDMA, there are three CGIN resource adaptor entities that may be created within VoLTE:

- `cginra`— for CAP dialogs

- `cgin-cdma-ra`— for CDMA dialogs

- `cginmapra`— unused by default.

== CAP CGIN RA entity (`cginra`)

The `cginra` RA entity is used in re-origination for CAP dialogs.

== CDMA CGIN RA entity (`cgin-cdma-ra`)

The `cgin-cdma-ra` RA entity is used in re-origination for CDMA dialogs.

== Customising the CGIN RA entities used by Sentinel It may be necessary to configure multiple RA entities to address specific operator network configuration requirements. Additional CGIN RA entities may be used in Sentinel for this purpose. Sentinel has the following link binding by default:

Link name | Default Bound RA entity
--- | ---
`sentinel-cgin` | `cginra`
`sentinel-cdma` | `cgin-cdma-ra`

A custom CGIN RA entity may be used by creating, configuring and binding the new RA entity.

= Correlation Resource Adaptor :indexpage:

= Correlation RA Overview

== What is the Correlation RA?

The Correlation RA provides a mechanism to correlate two otherwise independent sessions. The correlation data is replicated across the Rhino cluster. All nodes in the cluster have access to read/write correlation data.

This is used in the SCC-AS as part of IMS Service Centralisation via CAMEL triggers.

Below are procedures for [configuration], [monitoring], and [using].

= Configuring a Correlation RA entity

A Correlation RA entity configuration consists of:

- [ra-configuration]

- [entity-configuration]

- [pools-configuration]

The following diagram shows the Reorigination Correlation RA entity.

| The Correlation resource adaptor supports live re-configuration, so the administrator may update the configuration properties of a Correlation resource adaptor entity that has already been created.

== Correlation RA configuration properties

The Correlation RA configuration properties are:

Name | Type | Description
`ConfigProfileTable` | String | The SLEE profile table with an RA configuration profile for this RA entity.
`ConfigProfile` | String | The SLEE profile in the ConfigProfileTable with configuration for this RA entity.
`CorrelationIdPoolProfileTable` | String | The SLEE profile table with correlation ID pool definitions for this Correlation RA entity.

For example, the Reorigination Correlation RA entity has the following configuration:

    [Rhino@localhost (#9)] listraentityconfigproperties reorigination-correlation-ra
    Configuration properties for resource adaptor entity reorigination-correlation-ra:
     ConfigProfile (java.lang.String): ReoriginationCorrelationConfigProfile
     ConfigProfileTable (java.lang.String): CorrelationConfigTable
     CorrelationIdPoolTable (java.lang.String): ReoriginationCorrelationIdPools

== Correlation RA entity configuration profile

The Correlation RA configuration profile has the following attributes:

Name | Type | Description
`RequestTimeout` | Int | The maximum time (measured in ms) the Correlation RA will spend trying to allocate a correlation ID.
`CorrelationIDExpiryTimerPeriod` | Int | The maximum time (measured in ms) that an active correlation ID is considered to be still valid.
`NumberOfThreadPool` | Int | How many threads the Correlation RA entity should use.

For example, the Reorigination Correlation RA entity has the following configuration:

    [Rhino@localhost (#8)] listprofileattributes CorrelationConfigTable ReoriginationCorrelationConfigProfile
    CorrelationIDExpiryTimerPeriod=55000
    NumberOfThreadPool=5
    RequestTimeout=5000

== Correlation RA entity ID pools configuration

Each Correlation RA entity has one or more correlation ID pools.

- a default ID pool (optional)

- a set of named ID pools. Each named ID pool is identified by a set of prefixes for choosing/selecting the ID pool. From the Correlation RA standpoint, the prefixes can be any address string. The client to the RA provides an address that the RA uses via a longestPrefix match address list search to select the pool to use.

Each correlation ID pool is defined in a SLEE profile in an ID pools profile table. There is one correlation ID pools table per Correlation RA entity.

| The correlation resource adaptor entity will raise an alarm if there are no correlation ID pools configured, or if there are configuration errors with the correlation ID pools.

`addressPrefixes` | An array of address prefixes that corresponds to this pool. The default pool has an empty addressPrefixes array.
`nodeIds` | An array of node IDs for which this pool has correlation IDs.
`isPreconfiguredCorrelationIdSetUsed` | If true, configure this ID pool with a pre-configured set of correlation IDs, else derive the correlation IDs.
`preconfiguredCorrelationIdSet` | The preconfigured set of correlation IDs per node (delimited with ‘:’).
`minCorrelationIDInCluster` | The minimum correlation ID value used in the cluster. 0 to maxCorrelationIDInCluster
`maxCorrelationIDInCluster` | The maximum correlation ID value used in the cluster. 0 to (10^18-1)
`correlationIDNumberOfDigits` | The number of digits the correlation ID should have. Minimum of number of digits in maxCorrelationIDInCluster to 18 maximum.
`correlationIDRangePerNode` | The number of correlation IDs that can be used for each node in the cluster.

There are two possible configuration options for correlation ID pools.

=== A prescribed set of IDs for each node

Defines the prescribed correlation IDs for each node in the following way:

- `NodeIds[0]`—`PreconfiguredCorrelationIdSet[0]` which is a ‘:’ separated string containing all the correlation IDs for `NodeIds[0]`

- `NodeIds[1]`—`PreconfiguredCorrelationIdSet[1]` which is a ‘:’ separated string containing all the correlation IDs for `NodeIds[1]`

- etc.

| ‘:’ is used as a separator and not to specify a range. For example, to specify IDs `123`, `124`, `125` and `126` use a value of `123:124:125:126`.

=== A range of correlation IDs (min, max) for each node

Defines the range of values used in each node in conjunction with the `NodeIds` attribute in the following way:

- The node whose identifier is `NodeIds[i]` has a range of values of `CorrelationIDRangePerNode[i]`

- Each cluster has a range of CorrelationIDs defined by: `[MinCorrelationIDInCluster, MaxCorrelationIDInCluster]`

These values are allocated to the different cluster nodes in the following way:

- `NodeIds[0]`—`[MinCorrelationIDInCluster …​ MinCorrelationIDInCluster + CorrelationIDRangePerNode[0]]`

- `NodeIds[1]`—`[MinCorrelationIDInCluster + CorrelationIDRangePerNode[0] + 1 …​ MinCorrelationIDInCluster + +CorrelationIDRangePerNode[0] + 1 + CorrelationIDRangePerNode[1]]`

- etc.

The maximum number of correlation IDs defined in the range is 1,000,000.

=== Provisioning Interfaces

The Correlation RA configuration and ID pools are provisioned using the Sentinel REST API or web interface.

== Monitoring Correlation RA entity statistics

Each Correlation RA entity collects the following statistics that may be monitored via the Rhino statistics client.

Counters

Name | Description
--- | ---
`correlationGets` | Count of correlation IDs which have been requested via `findCorrelationEntry()`
`localGets` | Count of correlation queries which returned immediately (synchronous delivery) as the local RA had the data available.
`remoteGets` | Count of correlation queries which did not return immediately (asynchronous delivery) as the local RA did not have the data available.
`remoteDelivery` | Count of correlation queries which required delivering data to another correlation RA instance.
`unknown` | Count of correlation queries which could not be remotely delivered as the destination RA for a correlation ID was unknown.

| The count `correlationGets` should equal the sum of `localGets + remoteGets`.

These statistics can use used to create threshold-based alarms.

= Using the Correlation RA

A feature uses the Correlation RA by invoking methods on the provider interface.

- To store data for correlation, a feature calls either the `getNewCorrelationID(byte[] correlationData)` or the `getNewCorrelationID(String associatedAddress, byte[] correlationData)` method on the `CorrelationProvider`. These methods will store the correlation data locally, and return an identifier String (the correlation ID) which can later be used to access the data from elsewhere. This operation will flag the returned ID as ‘in use’ until it is freed (on query) or expires (on timeout).

- To query the correlation data (for example, from another session) a feature calls the `getCorrelationData(String correlationId)` method on the `CorrelationProvider`. This returns a `CorrelationResult` which will either contain the requested data (if it is available locally), or a flag indicating that the data is not available locally.

- If the data is available locally then it can be immediately access via the [synchronous] API call CorrelationResult.getCorrelationData()

- If the data is only available for asynchronous delivery, `CorrelationResult.isAvailableAsynchronously()` will be true, and `CorrelationResult.getCorrelationData()` will return null. See the following section for how to handle [asynchronous] result delivery.

CorrelationProvider interface:

    public interface CorrelationProvider {

        /**
         * Creates an activity used for async requests.
         *
         * @return
         * @throws StartActivityException
         */
        public CorrelationActivity createActivity() throws StartActivityException;

        /**
         * This returns immediately and will return a CorrelationResult. This will either contain the correlation data if this is available on
         * this node or else will contain a flag that says this is only available on another node. In the later case you should then call an
         * async request to get the data.
         *
         * @param correlationId the Correlation ID
         * @return the CorrelationResult
         * @throws UnknownCorrelationIdException if the correlation id is not known in this pool
         * @throws NoDataFoundException if there is no data found for the correlation id specified
         * @throws CorrelationIDExpiredException if the correlation id has expired
         */
        public CorrelationResult getCorrelationData(String correlationId) throws UnknownCorrelationIdException, NoDataFoundException, CorrelationIDExpiredException;

        /**
         * This will return the CorrelationResult. This method will block and only return when the CorrelationResult is available. If the data is only
         * available on a remote node this may take some time to return. This should only be used if synchronous behavior is required.
         *
         * @param correlationId
         * @return
         * @throws CorrelationRequestException
         */
        public CorrelationResult getCorrelationDataSynchronously(String correlationId) throws CorrelationRequestException;

        /**
         * Request a new Correlation ID from the default pool
         *
         * @param correlationData data to be correlated
         * @return a new Correlation ID with a correlation name that is not being used in any other session
         * @throws NoAvailableEntries if there is any problem accessing data
         */
        public String getNewCorrelationID(byte[] correlationData) throws NoAvailableEntriesException;

        /**
         * Request a new Correlation ID String from a correlation id pool associated with an address.
         *
         * @param associatedAddress an address that the correlation RA will use to select a pool from which to return a correlation id
         * @param correlationData data to be correlated
         * @return a new Correlation ID String with a correlation name that is not being used in any other session
         * @throws NoAvailableEntries if there is any problem accessing data
         */
        public String getNewCorrelationID(String associatedAddress, byte[] correlationData) throws NoAvailableEntriesException;

        /**
         * Determine if an id is a correlation id we know about
         * @param possibleCorrelationId an id we wish to check to see if it is a correlation id
         * @return true iff this id is a correlation id we know about
         */
        public boolean isValidCorrelationId(String possibleCorrelationId);
    }

CorrelationResult interface:

    public interface CorrelationResult {
        /**
         * Contains correlation data associated with the requested correlation ID or null if the
         * data is only available asynchronously.
         *
         * @return
         */
        public byte[] getCorrelationData();

        /**
         * String containing requested correlation ID.
         *
         * @return the String containing the Correlation ID
         */
        public String getCorrelationId();

        /**
         * If the correlation data is not available locally but is available via an asynchronous call.
         *
         * An asynchronous call can be made by creating a CorrelationActivity with the provider and then making
         * the asynchronous call on the CorrelationActivity.
         *
         * @return
         */
        public boolean isAvailableAsynchronously();
    }

CorrelationActivity interface:

    public interface CorrelationActivity {

        /**
         * Request the correlation data associated with the specified Correlation ID.
         *
         * The result will be fired as a {@link CorrelationResultEvent}
         * event on this activity.  Failed queries will be fired as a {@link CorrelationFailureEvent}.
         *
         * @param correlationId The Correlation ID
         */
        public void requestCorrelationData(String correlationId);

    }

== Handling synchronous results

Synchronous queries occur when the RA which is queried is also storing the queried information. In these circumstances, the data is included in the returned CorrelationResult from a query. The following example demonstrates how to handle synchronous return results:

    private void syncRequest(byte [] correlationData) {
        //
        // Store some data against a new correlation ID.
        //
        String correlationId;
        try {
            correlationId = corrProvider.getNewCorrelationID(correlationData);
        } catch (NoAvailableEntriesException e) {
            // ... handle exception ...
            return;
        }

        // ... do work until correlation data is required again.

        // In practice, the following will usually be done in another transaction which only knows the correlation ID.
        // It is done inline here for the sake of simplicity.

        //
        // Query the saved correlation data.
        //
        try {
            CorrelationResult result = corrProvider.getCorrelationData(correlationId);
            byte [] corrData = result.getCorrelationData();
            if (corrData != null) {
               // Do something with data
            } else {
               if (result.isAvailableAsynchronously()) {
                 // ... Here we could optionally proceed with an asynchronous correlation data query. See following example.
               }
            }
        } catch (UnknownCorrelationIdException e) {
            // ... handle exception ...
            return;
        } catch (NoDataFoundException e) {
            // ... handle exception ...
            return;
        } catch (CorrelationIDExpiredException e) {
            // ... handle exception ...
            return;
        }
    }

== Handling asynchronous results

Asynchronous result handling is required when the correlated data for the requested ID is only available from a non-local Correlation RA (that is, on a different Rhino node). After the correlation data is requested, the result is returned in a CorrelationEvent which is delivered to the service. This CorrelationEvents must be explicitly handled with a SLEE event handler.

Requesting correlation data asynchronously is done as follows:

- Create a new correlation activity using `CorrelationProvider.createActivity()`

- Get an `ActivityContextInterface` object for the activity.

- Attach the SBB local object to the ACI.

- Send the request using the `requestCorrelationData(String)` method on the activity.

- Handle the result in an event handler for the `com.opencloud.slee.resources.correlation.CorrelationResultEvent` event.

- Handle failures in an event handler for the `com.opencloud.slee.resources.correlation.CorrelationFailureEvent` event.

The follow example demonstrates the handling an asynchronous correlation query:

    private void asyncRequest(String correlationId) {
        try {
            CorrelationActivity corrActivity = corrProvider.createActivity();
            ActivityContextInterface corrAci = corrACIFactory.getActivityContextInterface(corrActivity);
            corrAci.attach(getSbbLocalObject());
            corrActivity.requestCorrelationData(correlationId);
        }
        catch (StartActivityException e) {
            // ... handle exception ...
        }
    }

    public void onCorrelationResult(CorrelationResultEvent result, ActivityContextInterface aci) {
        aci.detach(getSbbLocalObject());
        byte [] corrData = result.getCorrelationData()
        // ... do something with the data ...
    }

    public void onCorrelationFailure(CorrelationFailureEvent failure, ActivityContextInterface aci) {
        aci.detach(getSbbLocalObject());
        // ... handle failure ...
    }

== Javadoc API

Javadoc for the Correlation RA is available here: Sentinel Correlation RA API 1.0.

= Diameter Resource Adaptor

== Diameter RA documentation

View the Diameter RA documentation here.

== Diameter resource adaptors

There are currently 2 Diameter Ro Resource Adaptor Entities in Sentinel VoLTE:

- `diameterro-0`— for OCS connections

- `diameter-sentinel-internal`— used as a message factory by mappers in Sentinel’s Diameter mediation layer.

`diameterro-0` and `diameter-sentinel-internal` are used by all Sentinel services.

=== Session timeouts

The default Sentinel configuration has a 10 minute timeout for `diameterro-1` (client) and 13 minute timeout for `diameterro-0` (OCS). This configuration ensures that if there are events dropped due to overload, the ActivityEndEvents fired on the RA entities will cause the client side to end first. The 3 minute gap is set to allow time for all the ActivityEndEvents on the client side to be delivered before any are fired on the OCS side due.

=== Diameter version configuration The Diameter version spoken on the network to either the OCS or the Diameter client can be configured by setting two properties in the relevant resource adaptor. To change the version used in the OCS dialog, `diameterro-0` should be reconfigured. Likewise, to change the version used on the client dialog (`Sentinel Diameter` only), `diameterro-1` should be reconfigured. The Diameter version used by `diameter-sentinel-internal` should not be reconfigured, as it is tied to the internal implementation of Sentinel.

When reconfiguring the Diameter version of either of the external resource adaptors, two fields must be set - `Slee3GPPVersion` and `3GPPVersion`. `Slee3GPPVersion` should always be set to `Vcb0`. This is the version of Diameter used by Sentinel internally. `3GPPVersion` can be set to the desired protocol version to be used over the network, ranging from `V820` to `Vcb0`.

Alternatively, the Diameter version spoken to the OCS can be set during installation.

=== OCS load balancing

Load balancing of OCS connections can be achieved using the `diameterro-0` resource adaptor entity, by configuring multiple hosts within a realm and addressing messages to the realm only (not the host).

==== Example configuration for OCS load balancing

This example shows the `diameterro-0` resource adaptor entity configured to load balance across two OCS nodes.

- The resource adaptor entity config properties show that it is configured using a profile in the `DiameterConfig` table.

- The config profile shows that the known OCS nodes are named `diameterserver` and `diameterserver1`.

- The routing priority metric for both nodes is set to 1 to indicate equal priority, meaning that load balancing will be applied.

- The `DiameterMediationOcsConfigurationTable` configuration profile at platform scope does not specify a host, so all outbound Diameter messages will not have the destination host set, but only the realm. This means the resource adaptor entity will round robin among all the hosts configured for the specified realm (in this case `opencloud`). However this behaviour can be overridden on a per-session basis by setting the `OCSId` field in session state using, for example, `SubscriberDataLookup` or a custom feature added with the SDK.

The following `rhino-console` session shows the complete configuration:

    [Rhino@localhost (#0)] listraentityconfigproperties diameterro-0
    Configuration properties for resource adaptor entity diameterro-0:
     3GPPVersion (java.lang.String): Vcb0
     BaseMessageApplicationID (java.lang.Integer): 0
     CertificateKeyStore (java.lang.String):
     CertificateKeyStorePassword (java.lang.String):
     CipherSuites (java.lang.String):
     ConfigurationProfile (java.lang.String): DiameterConfig/DiameterRoOcsProfile
     ConfigurationProfilePollTime (java.lang.Integer): 0
     ConnectTimeout (java.lang.Long): 30000
     ExtendedTransportConfiguration (java.lang.String):
     ExtensionAvpSet (java.lang.String): DiameterExtensions/Charging
     ExtensionAvpSetPollTime (java.lang.Integer): 0
     ExtensionMessages (java.lang.Boolean): true
     FireToServiceID (java.lang.String):
     ForceReconnectAfterDPR (java.lang.Boolean): true
     IOClientWorkers (java.lang.Integer): 0
     IOServerWorkers (java.lang.Integer): 0
     Quirks (java.lang.String):
     ReconnectDelay (java.lang.Long): 5000
     RequestTimeout (java.lang.Long): 2000
     SSLSessionTimeout (java.lang.Integer): 0
     ServiceContextId (java.lang.String): session@opencloud.com
     SessionTimeout (java.lang.Long): 780000
     SupportedVendorIds (java.lang.String):
     ThreadPoolSize (java.lang.Integer): 0
     TrustKeyStore (java.lang.String):
     TrustKeyStorePassword (java.lang.String):
     WatchdogTimeout (java.lang.Long): 30000
     WorkQueueSize (java.lang.Integer): 0
     slee-vendor:com.opencloud.rhino_max_activities (java.lang.Integer): 0
     slee-vendor:com.opencloud.rhino_replicate_activities (java.lang.String): none
    [Rhino@localhost (#1)] listprofileattributes DiameterConfig DiameterRoOcsProfile
    Action=LOCAL
    AllowUnknownPeers=true
    ApplicationId=0
    ApplicationVendorId=0
    EnableMultiNodeConfig=false
    Host=diameterclient
    ListenAddress={null}
    NodeIDs={null}
    PeerAddress=127.0.0.1
    PeerConnectAtStartup=true
    PeerHost=diameterserver
    PeerPort=3868
    PeerTable=<?xml version="1.0" encoding="ISO-8859-1"?>

    <!DOCTYPE peer-table PUBLIC "-//Open Cloud Ltd.//DTD Diameter Peer Table Configuration 1.1.0//EN" "http://www.opencloud.com/dtd/diameter-peer-table-1.1.0.dtd">

    <peer-table allowUnknownPeers="true">
        <!-- If allowUnknownPeers is true, then any peer may connect to this node.
             If allowUnknownPeers is not true, peers connecting to this node as clients must be defined in the Peer Table.-->
        <peer connectAtStartup="true">
            <hostname>diameterserver</hostname> <!-- Will accept connections from this peer -->
            <port>3868</port>
            <address>127.0.0.1</address>
            <tls>false</tls>
            <option>
                <option-name>TCP_NODELAY</option-name>
                <option-type>java.lang.Boolean</option-type>
                <option-value>true</option-value>
            </option>
        </peer>
        <peer connectAtStartup="true">
            <hostname>diameterserver1</hostname> <!-- Will accept connections from this peer -->
            <port>3868</port>
            <address>192.168.2.100</address>
            <tls>false</tls>
            <option>
                <option-name>TCP_NODELAY</option-name>
                <option-type>java.lang.Boolean</option-type>
                <option-value>true</option-value>
            </option>
        </peer>
    </peer-table>
    PeerUri={null}
    PerNodeHosts={null}
    PerNodeListenAddresses={null}
    PerNodePorts={null}
    PerNodeSecondaryAddresses={null}
    Port=3869
    Product=OpenCloud Diameter
    ProductVendorId=19808
    Realm=opencloud
    RealmTable=<?xml version="1.0" encoding="UTF-8"?>
                     <!DOCTYPE realm-table PUBLIC "-//Open Cloud Ltd.//DTD Diameter Realm Table Configuration 1.1//EN"
                        "http://www.opencloud.com/dtd/diameter-realm-table-1.1.dtd">
                     <realm-table>
                        <realm>
                          <realm-name>opencloud</realm-name>
                          <application-route>
                            <application>
                              <application-id>4</application-id> <!-- 4=CCA -->
                              <vendor-id>0</vendor-id> <!-- optional, default is zero -->
                            </application>
                            <action>LOCAL</action>
                            <peer-ref>
                              <hostname>diameterserver</hostname>
                              <metric>1</metric>
                            </peer-ref>
                            <peer-ref>
                              <hostname>diameterserver1</hostname>
                              <metric>1</metric>
                            </peer-ref>
                          </application-route>
                        </realm>

                        <default-route>
                          <peer-ref>
                            <hostname>diameterserver</hostname>
                            <metric>1</metric>
                          </peer-ref>
                            <peer-ref>
                              <hostname>diameterserver1</hostname>
                              <metric>1</metric>
                            </peer-ref>
                        </default-route>

                      </realm-table>
    SecondaryAddresses={null}
    Transports=tcp
    UseTLS=false
    ValidDN={null}
    Version=1
    [Rhino@localhost (#2)] listprofileattributes DiameterMediationOcsConfigurationTable UNSET::::
    DestinationHost={null}
    DestinationRealm=opencloud
    TimeoutDuration=2000

= HLR MAP Configuration :toc: macro :toclevels: 4 :toc-title: On this page…​

Sentinel VoLTE uses the IN SIS Resource Adaptor `sis-in` entity for all of its interactions with an HLR over the MAP protocol.

== MAP usage

Within Sentinel VoLTE, the main users of MAP and the HLR are:

- FetchMSRN features --- Used to retrieve a subscriber’s MSRN from the HLR via a Send Routing Info request.

- SubscriberDataLookupFromHLR --- Used to retrieve supplementary service data used for applying MMTel services from the HLR via a Any Time Subscription Interrogation request.

Both features by default are bound to `sis-in` ra entity.

Link name | Default Bound RA entity
--- | ---
`sentinel-sis-in-msrnlookup` | `sis-in`
`sentinel-sis-in-hlrsubscriberdata` | `sis-in`

== IN SIS Resource Adaptor

| Refer to the Service Interaction SLEE (SIS) for more information about the IN SIS resource adaptor.

=== IN SIS resource adaptor entity (sis-in) Configuration

Use the `sis-console` or SIS REM Module to modify the default SIS and sis-in configuration properties; see the SIS Administration Guide and SIS REM Module User Guide for more details on managing the SIS instance.

By default the `sis-in` is not configured. It should be set to an external interface for network integration.

== Sentinel Configuration

Configuration for HLR communication is done via the `HLRConfigProfileTable`, which is initially configured using the installer. This profile has the following fields:

Parameter | Value | Description
--- | --- | ---
HLRSccpAddress | String encoding an SCCP Address | SCCP Address of the HLR, used when establishing the MAP dialog. Treated as a template when `UseMsisdnAsHlrAddress` is true.
SentinelSCCPAddress | String encoding an SCCP Address | SCCP Address of Sentinel, used when establishing the MAP dialog.
SentinelSCCPMscEndpointAddress | String encoding an SCCP Address | SCCP Address of Sentinel when Sentinel is acting as an MSC, used when establishing the MAP dialog. Will default to the value of SentinelSccpAddress if unset. Typically used to set a different originating SSN when sending a SendRoutingInformation message to the HLR.
SentinelAddressString | String encoding an Address String | Address of Sentinel included in MAP requests.
HLRInvokeTimeout | Long representing milliseconds | The timeout for waiting the HLR response. Used in the TCAP layer for the invoke timeout.
CallReferenceNumberSystemConstant | int between 0 and 65535 | A constant value used during the construction of the Call Reference Number
UseMsisdnAsHlrAddress | Boolean | Controls whether to address the outbound HLR leg using a GT address formed by adding the subscriber MSISDN digits to the `HLRSccpAddress` above

=== SCCP Address Format The configuration profile includes two SCCP addresses encoded in strings. Broadly speaking SCCP addresses come in two forms:

- Point-Code Subsystem Number (PC-SSN)

- Global Title Number (GT)

The string encoded format for an SCCP address takes the form of a comma separated series of key/value pairs. The exact set of valid keys varies between the two forms of SCCP address, and are outlined below.

==== Shared Key/Value Pairs These keys are required in all SCCP Addresses.

Key | Description | Valid Values
--- | --- | ---
`type` | SCCP Address Type | `A7`, `C7`, `CH7`, or `J7`
`ri` | Routing Indicator | `gt` for Global Title addresses, `pcssn` or `ssn` for Point-Code addresses.

==== PC-SSN Specific Key/Value Pairs These keys are required only in Point-Code Subsystem Number SCCP Addresses.

Key | Description | Valid Values
--- | --- | ---
`pc` | Point Code | Multiple formats (see below)
`ssn` | Subsystem Number | a number in the range 0-255

Point Code Formats Point codes can take the form of:

- A single decimal value in the range 0-16777215, which supports all addressing formats up to 24-bits long expressed as a single number.

- A '-' separated triple:

  - If `type=C7` has been specified, an x-y-z triple is taken to mean the 3-8-3 bit fields of the signal-area-zone point address format.

  - If `type=A7` or `type=CH7`, an x-y-z triple is taken to mean the 8-8-8 bit fields of the network-cluster-member address format.

Examples of a valid Point-Code SCCP Address

- `type=c7,ri=pcssn,pc=4012,ssn=123`

- `type=c7,ri=pcssn,pc=7-245-1,ssn=123`

==== GT Specific Key/Value Pairs These keys are used only in Global Title SCCP Addresses. Of these keys, it is only mandatory to include `digits` in the encoded string.

Key | Description | Valid Values
--- | --- | ---
`digits` | Address digits | Any digits string
`nature` | Address nature | `international` is the only value currently supported
`numbering` | Address numbering plan | `isdn` is the only value currently supported
`tt` | Translation type | a number in the range 0-255
`national` | National Indicator | `true` or `false`
`gti` | Global Tile Indicator | This value is automatically determined any may be omitted.

Examples of a valid GT SCCP Address

- `type=C7,ri=gt,digits=34607012345,nature=international,national=true`

- `type=C7,ri=gt,digits=654444444,nature=international,numbering=isdn,tt=0,national=true`

=== Address String Format

The configuration profile also includes an Address String encoded into a string. The string format is very similar to the GT SCCP Address format, however there are fewer keys and the key names are slightly different for equivalent value types.

==== Address String Key/Value Pairs

Key | Description | Valid Values
--- | --- | ---
`address` | Address digits | Any digits string
`nature` | Address nature | `INTERNATIONAL` is the only value currently supported
`numbering` | Address numbering plan | `ISDN` is the only value currently supported

Example of a valid Address String

- `address=653333333,nature=INTERNATIONAL,numberingPlan=ISDN`

= SIP SIS Resource Adaptor

== SIP SIS resource adaptor entity (sip-sis-ra)

| Refer to the Service Interaction SLEE (SIS) documentation for more information about the SIP SIS resource adaptor.

The `sip-sis-ra` is used for initiating and third-party SIP dialogs for both the Sentinel SIP Service and the Sentinel Subscription Service.

Link name | Default Bound RA entity
--- | ---
`sentinel-sip` | `sip-sis-ra`

== Sentinel and SIS

The `sip-sis-ra` interacts directly with the SIS, which is configured with compositions for the Sentinel SIP Service. The Sentinel SIP Service is triggered by all events from the SIP SIS RA entity. This behaviour is configurable. See the Service Interaction SLEE (SIS) documentation for more information about compositions and triggers.

=== Configuring SIS

Use the `sis-console` or SIS REM Module to modify the default SIS and sip-sis-ra configuration properties; see the SIS Administration Guide and SIS REM Module User Guide for more details on managing the SIS instance.

==== Configuring the network interface

By default the `sip-sis-ra` is set to listen on localhost ports `5061` (secure) and `5060`. It should be set to an external interface for network integration.

= System Statistics :sortorder: 14 :toc: macro :toclevels: 4 :toc-title: On this page…​

This page provides a summary of the statistics defined for Sentinel VoLTE features.

== General Features

=== DetermineChargeMode

DetermineChargeMode statistics are tracked by the sentinel.volte.sip SBB and can be found under the following parameter set in REM:
SLEE-Usage → sentinel.volte.sip service → sentinel.volte.sip SBB → feature → DetermineChargeMode
or with rhino-stats:
"SLEE-Usage.Services.ServiceID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].SbbID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].feature.DetermineChargeMode"

Name | Description
--- | ---
    Started
| Incremented each time the feature runs
    FailedToStart
| Incremented when a fatal error occurs before feature execution
    IssuedWarning
| Incremented when a non-fatal error occurs during feature execution
    FailedDuringExecution
| Incremented when a fatal error occurs during feature execution
    TimedOut
| Incremented when feature execution does not complete within a reasonable time frame
    MonitorOnly
| Incremented when the feature has set the MonitorCallOnly Session State field to true
    NonMonitorOnly
| Incremented when the feature has set the MonitorCallOnly Session State field to false
    Error
| Incremented when the feature was unable to determine the charge mode

=== DetermineInitialLegNames

DetermineInitialLegNames statistics are tracked by the sentinel.volte.sip SBB and can be found under the following parameter set in REM:
SLEE-Usage → sentinel.volte.sip service → sentinel.volte.sip SBB → feature → DetermineInitialLegNames
or with rhino-stats:
"SLEE-Usage.Services.ServiceID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].SbbID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].feature.DetermineInitialLegNames"

Name | Description
--- | ---
    FeatureStarted
| Incremented each time the feature runs
    FeatureFailedToStart
| Incremented when Sentinel VoLTE encounters an error while attempting to start the feature
    FeatureIssuedWarning
| Incremented when a non-fatal problem is encountered and the feature issues a warning
    FeatureFailedDuringExecution
| Incremented when a fatal problem is encountered and the feature cannot execute correctly
    FeatureTimedOut
| Incremented when the feature takes too long to complete and Sentinel VoLTE aborts execution
    FeatureCallingLegNameSet
| Incremented when calling leg name is found
    FeatureCalledLegNameSet
| Incremented when called leg name is found

=== Determine International and Roaming Status

DetermineInternationalAndRoamingStatus statistics are tracked by the volte.sentinel.sip SBB and can be found under the following parameter set in REM:
SLEE-Usage → volte.sentinel.sip service → volte.sentinel.sip SBB → feature → DetermineInternationalAndRoamingStatus
or with rhino-stats:
"SLEE-Usage.Services.ServiceID[name=volte.sentinel.sip,vendor=OpenCloud,version=3.1.0].SbbID[name=volte.sentinel.sip,vendor=OpenCloud,version=3.1.0].feature.DetermineInternationalAndRoamingStatus"

Parameter | Type | Description
--- | --- | ---
    Started
| Counter | Incremented each time the feature runs
    FailedToStart
| Counter | Incremented when a fatal error occurs before feature execution
    IssuedWarning
| Counter | Incremented when a non-fatal error occurs during feature execution
    FailedDuringExecution
| Counter | Incremented when a fatal error occurs during feature execution
    TimedOut
| Counter | Incremented when feature execution does not complete within a reasonable time frame
    VisitedNetworkHeaderFound
| Counter | Incremented when the requestURI identity is in RegistrationRecords list of public identities.
    AccessNetworkMccFound
| Counter | Incremented when the mobile-Country-Code is found in the P-Access-Network-Info header.
    DeterminedInternationalUsingAccessNetworkMcc
| Counter | Incremented when the MCC prefix address list is used to determine whether the call is international.
    DeterminedInternationalUsingVisitedNetworkId
| Counter | Incremented when the visited-network-id prefix address list is used to determine whether the call is international.
    CouldNotGetPVisitedNetworkID
| Counter | Incremented when no visited network ID information could be found.
    HomeNetworkIdSetForNetworkOperatorIsEmpty
| Counter | Incremented when the Sentinel SIP configuration for the network operator has an empty `home-network-id` set (the feature cannot determine if the subscriber is roaming).
    InternationalRoaming
| Counter | Incremented when the feature determines that the served user is roaming in a foreign country.
    NationalRoaming
| Counter | Incremented when the feature determines that the served user is roaming in their home country.
    NotRoaming
| Counter | Incremented when the feature determines that the served user is on their home network.
    UnknownRoaming
| Counter | Incremented when the feature is unable to determine the served user’s roaming status.
    AddressNotMinimumLength
| Counter | Incremented when destination address is less than the configured minimum length
    AddressOnBlackList
| Counter | Incremented when destination address matches an entry in the `SkipDIRSAddressList`
    StatusDeterminedFromHeader
| Counter | Incremented when the roaming status is determined from a OC-Roaming-Status header on the incoming request.
    NoActionRequired
| Counter | Incremented when the feature determines that it does not need to do anything for the current invocation.

=== DetermineVoltePlanId

DetermineVoltePlanId statistics are tracked by the sentinel.volte.sip SBB and can be found under the following parameter set in REM:
SLEE-Usage → sentinel.volte.sip service → sentinel.volte.sip SBB → feature → DetermineVoltePlanId
or with rhino-stats:
"SLEE-Usage.Services.ServiceID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].SbbID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].feature.DetermineVoltePlanId"

Name | Type | Description
--- | --- | ---
    Started
| Counter | Incremented each time the feature runs
    FailedToStart
| Counter | Incremented when a fatal error occurs before feature execution
    IssuedWarning
| Counter | Incremented when a non-fatal error occurs during feature execution
    FailedDuringExecution
| Counter | Incremented when a fatal error occurs during feature execution
    TimedOut
| Counter | Incremented when feature execution does not complete within a reasonable time frame
    NoPlanSelected
| Counter | Incremented when the feature fails to select an appropriate plan ID
    MmtelOriginatingPlanSelected
| Counter | Incremented when the feature selects the plan ID as “mmtel-orig”
    MmtelTerminatingPlanSelected
| Counter | Incremented when the feature selects the plan ID as “mmtel-term”
    MmtelConferencingPlanSelected
| Counter | Incremented when the feature selects the plan ID as “mmtel-conf”
    SccOriginatingPlanSelected
| Counter | Incremented when the feature selects the plan ID as “scc-orig”
    SccTerminatingPlanSelected
| Counter | Incremented when the feature selects the plan ID as “scc-term”
    SccTerminatingTadsOnlyPlanSelected
| Counter | Incremented when the feature selects the plan ID as “scc-term-tads”
    SccTerminatingAnchorOnlyPlanSelected
| Counter | Incremented when the feature selects the plan ID as “scc-term-anchor”
    SccReoriginationPlanSelected
| Counter | Incremented when the feature selects the plan ID as “scc-reorigination”
    SccAccessTransferPlanSelected
| Counter | Incremented when the feature selects the plan ID as “scc-access-transfer”
    ConferenceConfigurationNotFound
| Counter | Incremented when the feature is unable to find a valid conference PSI from configuration profiles
    PlanIDAlreadySet
| Counter | Incremented when the feature detects that a plan ID has already been selected

=== IMSIDLookup

IMSIDLookup statistics are tracked by the IMSIDLookup SBB and can be found under the following parameter set:
SLEE-Usage ▶ sentinel.volte.sip service ID ▶ IMSIDLookup SBB ID.

Name | Type | Description
--- | --- | ---
    Invoked
| Counter | Incremented when the feature runs.
    FeatureError
| Counter | Incremented when a fatal error occurs during feature execution.
    NoSubscriberSpecified
| Counter | Incremented when the feature is unable to determine which subscriber to retrieve IDs for.
    IMSIDRetrieveSuccess
| Counter | Incremented when IDs are successfully retrieved and decoded.
    IMSIDRetrieveFail
| Counter | Incremented when ID retrieval or decoding fails.
    CacheQueried
| Counter | Incremented when a query is made to the Sh Cache Microservice.
    CacheIndicatedQuerySuccess
| Counter | Incremented when a success response is received from the Sh Cache Microservice.
    CacheIndicatedQueryFailure
| Counter | Incremented when a failure response is received from the Sh Cache Microservice.
    SubscriberNotRegistered
| Counter | Incremented when the searched subscriber is not present in the Sh Cache Microservice or has no valid registration.
    RegistrationOutOfSync
| Counter | Incremented when the searched subscriber information is not consistent between the network and the Sh Cache Microservice.
    ResponseLatency
| Sampled | Records elapsed time between requesting data from the Sh Cache Microservice and getting a response (in milliseconds).

=== IMSIDLookupFromCassandraSIP

IMSIDLookupFromCassandraSIP statistics are tracked by the IMSIDLookupFromCassandraSIP feature and can be found under the following parameter set:
SLEE-Usage ▶ sentinel.volte.sip service ID ▶ sentinel.volte.sip SBB ID ▶ IMSIDLookupFromCassandraSIP.

Name | Type | Description
--- | --- | ---
    Started
| Counter | Incremented when the feature runs.
    FailedToStart
| Counter | Incremented when Sentinel VoLTE encounters an error while attempting to start the feature.
    IssuedWarning
| Counter | Incremented when a non-fatal problem is encountered and the feature issues a warning.
    FailedDuringExecution
| Counter | Incremented when a fatal problem is encountered and the feature cannot execute correctly.
    FeatureError
| Counter | Incremented when a feature error occurs.
    TimedOut
| Counter | Incremented when the feature takes too long to complete and Sentinel VoLTE aborts execution.
    NoSubscriberSpecified
| Counter | Incremented when the feature is unable to determine which subscriber to retrieve IDs for.
    IMSIDRetrieveSuccess
| Counter | Incremented when IDs are successfully retrieved and decoded.
    IMSIDRetrieveFail
| Counter | Incremented when ID retrieval or decoding fails.
    CassandraQueried
| Counter | Incremented when a query is made to Cassandra.
    MultipleDevicesRegistered
| Counter | Incremented when multiple registered devices have been detected.
    SubscriberNotRegistered
| Counter | Incremented when could not find an active subscriber.
    RegistrationOutOfSync
| Counter | Incremented when the searched subscriber information is not consistent between the network and the database.
    ResponseLatency
| Sampled | Records elapsed time between querying the Cassandra database and getting a response (in milliseconds).

=== IMSIDLookupFromCassandraIN

IMSIDLookupFromCassandraIN statistics are tracked by the IMSIDLookupFromCassandraIN feature and can be found under the following parameter sets:

SLEE-Usage ▶ sentinel.volte.ss7 service ID ▶ sentinel.volte.ss7 SBB ID ▶ IMSIDLookupFromCassandraIN feature.

Name | Type | Description
--- | --- | ---
    Started
| Counter | Incremented when the feature runs.
    FailedToStart
| Counter | Incremented when Sentinel VoLTE encounters an error while attempting to start the feature.
    IssuedWarning
| Counter | Incremented when a non-fatal problem is encountered and the feature issues a warning.
    FailedDuringExecution
| Counter | Incremented when a fatal problem is encountered and the feature cannot execute correctly.
    TimedOut
| Counter | Incremented when the feature takes too long to complete and Sentinel VoLTE aborts execution.

SLEE-Usage ▶ sentinel.volte.ss7 service ID ▶ volte.sentinel.volte-imsid-lookup-cassandra-ss7-feature SBB ID.

Name | Type | Description
--- | --- | ---
    Started
| Counter | Incremented when the feature runs.
    FailedToStart
| Counter | Incremented when Sentinel VoLTE encounters an error while attempting to start the feature.
    IssuedWarning
| Counter | Incremented when a non-fatal problem is encountered and the feature issues a warning.
    FailedDuringExecution
| Counter | Incremented when a fatal problem is encountered and the feature cannot execute correctly.
    TimedOut
| Counter | Incremented when the feature takes too long to complete and Sentinel VoLTE aborts execution.
    CassandraQueried
| Counter | Incremented when Cassandra is queried for a subscriber’s registration.
    NoSubscriberSpecified
| Counter | Incremented when no subscriber is specified for the query.
    SubscriberNotRegistered
| Counter | Incremented when the returned subscriber from Cassandra is not registered.
    IMSIDRetrieveFail
| Counter | Incremented when the Cassandra lookup fails.
    IMSIDRetrieveSuccess
| Counter | Incremented when the Cassandra lookup succeeds.
    FeatureError
| Counter | Incremented when a feature error occurs.
    ResponseLatency
| Sampled | Records elapsed time between querying the Cassandra database and getting a response (in milliseconds).

=== SubscriberDataLookupFromHSS

`SubscriberDataLookupFromHss` statistics are tracked by the `SubscriberDataLookupFromHss2` SBB and can be found under the following parameter set: SLEE-Usage → volte.sentinel.sip service ID → SubscriberDataLookupFromHss2 SBB ID.

Name | Type | Description
--- | --- | ---
    Invoked
| Counter | Incremented each time the feature runs.
    Failed
| Counter | Incremented if a fatal error occurs while the feature is running.
    SubscriberDataRetrieved
| Counter | Incremented when the feature receives subscriber data from the Sh Cache Microservice.
    SessionStatePopulated
| Counter | Incremented after the feature successfully processes the data it received, and loads it into session state fields.
    AdaptorClassError
| Counter | Incremented when Adaptor class is not of type SimservsSessionAdaptor or the feature fails to retrieve adaptor class.
    CodecClassError
| Counter | Incremented when Codec class is not of type ServiceDataCodec or the feature fails to retrieve codec class.
    Misconfigured
| Counter | Incremented when absent configuration data prevents the feature from running.
    SessionStateNotFound
| Counter | Incremented when the session state field the feature requires for operation is missing.
    ResponseLatency
| Sampled | Records elapsed time between sending the request to the HSS and getting a response (in milliseconds).

== MMTel Features

=== MMTel Conference

MMTelCONF statistics are tracked by the MMTelCONF SBB and can be found under the following parameter set:
SLEE-Usage → volte.sentinel.sip service ID → MMTelCONF SBB ID.

Statistic | Incremented when…​
--- | ---
    FeatureInvocations
| the conference feature runs
    FeatureFsmCompletions
| the main conference FSM reaches its end state
    SentinelAborts
| Sentinel VoLTE instructs the conference feature to abort execution
    SipParseMinorFailure
| a non-fatal error occurs while attempting to read the information in a SIP message
    SipDataAccessFailure
| a problem occurs while trying to access a SIP leg or message
    SipParticipantSentByeOnActiveConnection
| a `BYE` request is received on an active (join operation complete) participant connection
    SipParticipantSentByeOnInactiveConnection
| a `BYE` request is received on an inactive (join operation incomplete) participant connection
    SipMRFSentByeOnActiveConnection
| a `BYE` request is received on an active (join operation complete) media server connection.
    SipMRFSentByeOnInactiveConnection
| a `BYE` request is received on an inactive (join operation incomplete) media server connection
    ConferenceFeatureConfigurationFailure
| a problem occurs while trying to load the conference feature’s network-level configuration data
    ConferenceCoreError
| a fatal error occurs in the core conference feature FSM
    ConferenceConnectionError
| a fatal error occurs in the conference feature’s non-control connection management FSM
    ConferenceConnectionEstablished
| a non-control connection is successfully established between a conference participant and the MRF
    ConferenceConnectionMRFLegCreated
| a non-control leg to the MRF is successfully established
    ConferenceConnectionTerminated
| a fully established non-control conference connection is terminated
    ConferenceConnectionCreditCheckInitiated
| the conference feature triggers a credit check
    ConferenceConnectionParticipantSupportsVideo
| a participant has indicated that they support video in an SDP answer
    ConferenceControlConnectionError
| a fatal error occurs in the conference feature’s control connection management FSM
    ConferenceControlConnectionEstablished
| a control connection is successfully established between a conference moderator and the MRF.
    ConferenceControlConnectionTerminated
| a fully established conference control connection is terminated.
    ConferenceControlConnectionReceivedMalformedMessage
| a badly formed REFER request is received from the conference moderator.
    ConferenceControlConnectionQueuedNotify
| a NOTIFY is queued on the control connection
    ConferenceControlConnectionSentNotify
| a NOTIFY is sent to the conference moderator
    FromHeaderAnonymised
| the moderator has indicated they want privacy applied to the outgoing INVITE
    ConferenceMediaVideoSelected
| the moderator sets the conference up as a video session
    ConferenceMediaServerIsAccessedViaSCSCF
| the feature makes a call to the MRF via the S-CSCF

=== MMTelCDIV

MMTelCDIV statistics are tracked by the volte.sentinel.sip SBB and can be found under the following parameter set in REM:
SLEE-Usage → volte.sentinel.sip service → volte.sentinel.sip SBB → feature → MMTelCDIV
or with rhino-stats:
"SLEE-Usage.Services.ServiceID[name=volte.sentinel.sip,vendor=OpenCloud,version=3.1.0].SbbID[name=volte.sentinel.sip,vendor=OpenCloud,version=3.1.0].feature.MMTelCDIV"

Statistic | Incremented when…​
--- | ---
    Started
| the feature runs
    FailedToStart
| Sentinel VoLTE encounters an error while attempting to start the feature
    IssuedWarning
| a non-fatal problem is encountered and the feature issues a warning
    FailedDuringExecution
| a fatal problem is encountered and the feature cannot execute correctly
    TimedOut
| the feature takes too long to complete and Sentinel VoLTE aborts execution
    Misconfigured
| the feature configuration could not be loaded
    ProcessingSipResponse
| the feature is triggered on a SIP response
    ProcessingSipRequest
| the feature is triggered on a SIP request
    ProcessingChargingEvent
| the feature is triggered on a OCS event
    LegManagerError
| a problem occurs while trying to access data from the SIP leg manager
    ErrorProcessingSipRequest
| a problem occurs while trying to read or modify to a SIP request
    ErrorProcessingSipResponse
| a problem occurs while trying to read or modify to a SIP response
    DiversionLoopDetected
| diversion is aborted due to a diversion loop being detected
    DiversionLimitExceeded
| diversion is aborted due to the diversion limit being hit
    CancelledInviteRequest
| the CDIV feature cancels an `INVITE` on the terminating leg
    ErrorCancellingInviteRequest
| a problem occurs while attempting to cancel an `INVITE` request
    ReleasedDownstreamLeg
| caller is being diverted to voicemail
    TerminatedByResponse
| CDIV is aborted by sending an error response on the originating leg
    TerminatedByRetargeting
| CDIV is aborted by attempting to divert to a fixed final destination
    ErrorTerminatingByRetargeting
| diversion fails while trying to terminate by re-targeting
    NoReplyTimerSet
| the feature sets a timer for CFNR
    NoReplyTimerCancelled
| the feature cancels a timer for CFNR
    NoReplyTimerFired
| the feature is triggered by a CFNR timer expiring
    TimerSuppressedByResponseFromCSDomain
| timer is suppressed when parallel fork is done and the CS domain answers first
    CDIVSuppressedByResponseFromCSDomain
| CDIV service is suppressed when parallel fork is done and the CS domain answers first
    CallerNotifiedOfDiversion
| the feature notify the caller the session is being diverted
    FailedToNotifyCallerOfDiversion
| the feature fails to notify the caller the session is being diverted
    CFUSucceeded
| unconditional call forwarding is successfully executed
    CFUFailed
| a fatal problem occurs while trying to execute unconditional call forwarding
    CFNLSucceeded
| call forwarding due to the target user not being logged into IMS is successfully executed
    CFNLFailed
| a fatal problem occurs while trying to execute call forwarding due to the target user not being logged into IMS
    CFNRSucceeded
| call forwarding due to the target user not replying is successfully executed
    CFNRFailed
| a fatal problem occurs while trying to execute call forwarding due to the target user not replying
    CFBSucceeded
| call forwarding due to the target user being busy is successfully executed
    CFBFailed
| a fatal problem occurs while trying to execute call forwarding due to the target user being busy
    CFNRcSucceeded
| call forwarding due to the target user being unreachable is successfully executed
    CFNRcFailed
| a fatal problem occurs while trying to execute call forwarding due to the target user being unreachable
    CDImmediateSucceeded
| call forwarding due to immediate call deflection is successful.
    CDImmediateFailed
| a fatal problem occurs while trying to execute call forwarding due to immediate call deflection
    CDAlertingSucceeded
| call forwarding due to call deflection during alerting is successful
    CDAlertingFailed
| a fatal problem occurs while trying to execute call forwarding due to call deflection during alerting
    ToHeaderChanged
| 'To' header is set to diverted party or served user
    SubscriberCDIVAttempted
| call forwarding due to subscriber rules was attempted, either succesfully or unsuccesfully
    OperatorCDIVAttempted
| call forwarding due to operator rules was attempted, either succesfully or unsuccesfully
    DivertingCallToVoicemail
| call is being forwarded to voicemail
    ExecutingDefaultForwardToVoicemail
| call is being re-targeted to voicemail
    ErrorExecutingDefaultForwardToVoicemail
| a fatal problem occured while re-targeting to voicemail
    DefaultForwardToVoicemailTimerSet
| the default forward to voicemail timer has been started
    DefaultForwardToVoicemailTimerCancelled
| the default forward to voicemail timer has been cancelled
    DefaultForwardToVoicemailTimerFired
| the default forward to voicemail timer has fired, call will be diverted to voicemail

=== MMTelCW

MMTelCW statistics are tracked by the sentinel.volte.sip SBB and can be found under the following parameter set in REM:
SLEE-Usage → sentinel.volte.sip service → sentinel.volte.sip SBB → feature → MMTelCW
or with rhino-stats:
"SLEE-Usage.Services.ServiceID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].SbbID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].feature.MMTelCW"

Statistic | Incremented when…​
--- | ---
    Started
| the feature runs
    FailedToStart
| Sentinel VoLTE encounters an error while attempting to start the feature
    IssuedWarning
| a non-fatal problem is encountered and the feature issues a warning
    FailedDuringExecution
| a fatal problem is encountered and the feature cannot execute correctly
    TimedOut
| the feature takes too long to complete and Sentinel VoLTE aborts execution
    Misconfigured
| a fatal error if the feature configuration can not be loaded
    TimerError
| there is an error while trying to set a timer
    TimerCancelled
| a timer is cancelled by the feature
    TimerSet
| a timer is set by the feature
    ProcessingResponse
| the feature is invoked on receiving a SIP response
    ProcessingTimerEvent
| the feature is invoked on a timer firing
    OutgoingMessageContentChanged
| the feature changes the contents of an outgoing SIP message
    ReattemptedCallSetup
| the feature requests that call set up be reattempted
    Triggered180AUDUBResponse
| the feature requests a 180 response be sent back to the original caller, indicating call waiting service
    PlayAnnouncementTriggered
| the feature triggers an announcement to be played
    CancelledInviteRequest
| the feature cancels an outgoing `INVITE`
    FinalResponseChangedTo486
| the feature changes a SIP response status code to `486` before forwarding the response
    FinalResponseChangedTo480
| the feature changes a SIP response status code to `480` before forwarding the response

=== MMTelHold

MMTelHold statistics are tracked by the sentinel.volte.sip SBB and can be found under the following parameter set in REM:
SLEE-Usage → sentinel.volte.sip service → sentinel.volte.sip SBB → feature → MMTelHold
or with rhino-stats:
"SLEE-Usage.Services.ServiceID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].SbbID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].feature.MMTelHold"

Statistic | Incremented when…​
--- | ---
    Started
| the feature runs
    FailedToStart
| Sentinel VoLTE encounters an error while attempting to start the feature
    IssuedWarning
| a non-fatal problem is encountered and the feature issues a warning
    FailedDuringExecution
| a fatal problem is encountered and the feature cannot execute correctly
    TimedOut
| the feature takes too long to complete and Sentinel VoLTE aborts execution
    ProcessingRequest
| the feature is invoked on receiving a SIP request
    ProcessingResponse
| the feature is invoked on receiving a SIP response
    SipDataAccessError
| an error occurs while trying to access a SIP leg or message
    SipMessageSDPUpdated
| the feature changes the SDP content in a SIP message
    ReceivedHoldRequest
| the feature determines that an incoming message is a hold request
    ReceivedResumeRequest
| the feature determines that an incoming message is a resume request
    SessionBandwidthAdjusted
| any bandwidth information is adjusted in an SDP body
    MediaStreamBandwidthAdjusted
| bandwidth information is adjusted on a SDP media stream description
    MissingDataWarningTriggered
| an operation on SDP data fails due to the data being unavailable
    ReceivedMalformedMessage
| the feature determines that an incoming message is mal formed
    PlayAnnouncementTriggered
| the feature determines triggers the play announcement

=== MMTelICB

MMTelICB statistics are tracked by the sentinel.volte.sip SBB and can be found under the following parameter set in REM:
SLEE-Usage → sentinel.volte.sip service → sentinel.volte.sip SBB → feature → MMTelICB
or with rhino-stats:
"SLEE-Usage.Services.ServiceID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].SbbID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].feature.MMTelICB"

Statistic | Type | Incremented when…​
--- | --- | ---
    Started
| Counter | the feature runs
    FailedToStart
| Counter | Sentinel VoLTE encounters an error while attempting to start the feature
    IssuedWarning
| Counter | a non-fatal problem is encountered and the feature issues a warning
    FailedDuringExecution
| Counter | a fatal problem is encountered and the feature cannot execute correctly
    TimedOut
| Counter | the feature takes too long to complete and Sentinel VoLTE aborts execution
    CallBarred
| Counter | the feature bars a call (including when barring due to ACR)
    CallBarredByOdb
| Counter | the feature bars a call by Operator Determined Barring rule
    PlayAnnouncementTriggered
| Counter | the feature requests that an announcement be played to the calling party
    ACRTriggered
| Counter | a call is barred by ACR
    OdbRulesEvaluatedTrue
| Counter | a rule was evaluated to be True
    RulesEvaluatedTrue
| Counter | incremented by the number of rules which evaluated true

=== MMTelOCB

MMTelOCB statistics are tracked by the sentinel.volte.sip SBB and can be found under the following parameter set in REM:
SLEE-Usage → sentinel.volte.sip service → sentinel.volte.sip SBB → feature → MMTelOCB
or with rhino-stats:
"SLEE-Usage.Services.ServiceID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].SbbID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].feature.MMTelOCB"

Statistic | Type | Description
--- | --- | ---
    Started
| Counter | Incremented when the feature is invoked.
    FailedToStart
| Counter | Incremented when Sentinel VoLTE encounters an error while attempting to start the feature.
    IssuedWarning
| Counter | Incremented when a non-fatal problem is encountered and the feature issues a warning.
    FailedDuringExecution
| Counter | Incremented when a fatal problem is encountered and the feature cannot execute correctly.
    TimedOut
| Counter | Incremented when the feature takes too long to complete and Sentinel VoLTE aborts execution.
    CallBarred
| Counter | Incremented when the feature bars a call.
    CallExplicitlyAllowed
| Counter | Incremented when the feature finds a rule that explicitly allows the call to go through, thus preventing any barring.
    ODBRuleApplied
| Counter | Incremented when an ODB rule’s conditions were met and its action was executed.
    OCBRuleApplied
| Counter | Incremented when an OCB rule’s conditions were met and its action was executed.
    PrefixBasedRuleApplied
| Counter | Incremented when a rule was applied due to prefix barring. Either `CallBarred`, `CallExplicitlyAllowed` or `RedirectionRequested` will be incremented in tandem. `ODBRuleApplied` will not be incremented, even when the treatment is an OSBType rule.
    PlayAnnouncementTriggered
| Counter | Incremented when the feature requests that an announcement be played to the calling party.
    RedirectionRequested
| Counter | Incremented when an operator specific ODB rule’s conditions were met and it has been configured to redirect the call.
    RedirectionFailed
| Counter | Incremented when an attempt to redirect the outbound `INVITE` fails.
    RedirectionSuccessful
| Counter | Incremented when an attempt to redirect the outbound `INVITE` is successful.
    OdbSpecificTypeRulesNotFound
| Counter | Incremented when the subscriber data for the served user indicates that an operator specific ODB rule should be applied, but no configuration could be found for the specified rule.
    ClassifiedNumberByPrefix
| Counter | Incremented when prefix barring classifies the dialled number as triggering some barring treatment(s).
    FoundMultipleNonConflictingPrefixBarringClassifications
| Counter | Incremented when prefix barring classifies the dialled number and selects multiple classifications, all with separate treatments.
    FoundConflictingPrefixBarringClassifications
| Counter | Incremented when prefix barring classifies the dialled number and selects multiple classifications, with some duplicate treatments. Such as `classification1` `BarringTreatment=OperatorBar` `OverrideOCBAnnouncement=true` `announcementID=1` `classification2` `BarringTreatment=OperatorBar` `OverrideOCBAnnouncement=true` `announcementID=0`

=== MMTelOIP

MMTelOIP statistics are tracked by the `sentinel.volte.sip` SBB and can be found under the following parameter set:
SLEE-Usage → sentinel.volte.sip service → sentinel.volte.sip SBB → feature → MMTelOIP

Name | Type | Description
--- | --- | ---
    Started
| Counter | Incremented when the feature is triggered.
    FailedToStart
| Counter | Incremented when the feature fails to start.
    FailedDuringExecution
| Counter | Incremented when the feature fails while executing.
    IssuedWarning
| Counter | Incremented when the feature issues a warning.
    TimedOut
| Counter | Incremented when the feature times out during execution.
    Misconfigured
| Counter | Incremented when a fatal error if the feature configuration can not be loaded.
    ReceivedMalformedPrivacyHeader
| Counter | Incremented when a non-standard ‘Privacy’ header is found in an incoming SIP message.
    FromHeaderAnonymized
| Counter | Incremented when the feature anonymizes the ‘From’ header in an outgoing SIP request.
    ContactHeaderAnonymized
| Counter | Incremented when the feature anonymizes the ‘Contact’ header in an outgoing SIP message.
    ReferredByHeaderAnonymized
| Counter | Incremented when the feature anonymizes the ‘Referred-By’ header in an outgoing SIP message.
    PerformedUserLevelAnonymization
| Counter | Incremented when the feature applies user-level privacy to an outgoing SIP message.
    PerformedHeaderLevelAnonymization
| Counter | Incremented when the feature applies header-level privacy to an outgoing SIP message.
    PerformedSessionLevelAnonymization
| Counter | Incremented when the feature applies session-level privacy to an outgoing SIP message.
    PerformedCustomHeaderAnonymization
| Counter | Incremented when the feature finds and evaluates custom header privacy rules for a message.
    OverrideCategoryTriggered
| Counter | Incremented when the feature disregards requested privacy settings on an incoming SIP message (due to the subscriber having override category status).
    CriticalPrivacyCannotBeFulfilled
| Counter | Incremented when the feature refuses an incoming request due to a `Privacy` header including both the value `critical` and an unrecognised value.

=== MMTelOIR

MMTelOIR statistics are tracked by the sentinel.volte.sip SBB and can be found under the following parameter set:
SLEE-Usage → sentinel.volte.sip service → sentinel.volte.sip SBB

Statistic | Increments when…​
--- | ---
    Started
| the feature runs
    FailedToStart
| Sentinel VoLTE encounters an error while attempting to start the feature
    IssuedWarning
| a non-fatal problem is encountered and the feature issues a warning
    FailedDuringExecution
| a fatal problem is encountered and the feature cannot execute correctly
    TimedOut
| the feature takes too long to complete and Sentinel VoLTE aborts execution
    Misconfigured
| a fatal error if the feature configuration can not be loaded
    ReceivedMalformedPrivacyHeader
| a non-standard `Privacy` header is found in an incoming SIP message
    FromHeaderAnonymized
| the feature anonymizes the `From` header in an outgoing SIP message
    PrivacyHeaderChanged
| the feature changes the contents of the `Privacy` header on an outgoing SIP message

=== MMTelTIP

MMTelTIP statistics are tracked by the sentinel.volte.sip SBB and can be found under the following parameter set in REM:
SLEE-Usage → sentinel.volte.sip service → sentinel.volte.sip SBB → feature → MMTelTIP
or with rhino-stats:
SLEE-Usage → [sentinel.volte.sip service name] → [sentinel.volte.sip SBB name] → .feature.MMTelTIP

Statistic | Incremented when…​
--- | ---
    Started
| the feature runs
    FailedToStart
| Sentinel VoLTE encounters an error while attempting to start the feature
    IssuedWarning
| a non-fatal problem is encountered and the feature issues a warning
    FailedDuringExecution
| a fatal problem is encountered and the feature cannot execute correctly
    TimedOut
| the feature takes too long to complete and Sentinel VoLTE aborts execution
    ProcessingResponse
| the feature processes a SIP response
    ProcessingRequest
| the feature processes a SIP request
    OverrideCategoryTriggered
| the feature disregards requested privacy settings on an incoming SIP message (due to the subscriber having override category status)
    FromChangeTagRemoved
| the feature removes the `from-change` tag from a `Supported` header in the outgoing SIP message
    PrivacyHeaderChanged
| the feature changes the contents of the `Privacy` header on an outgoing SIP message

=== MMTelTIR

MMTelTIR statistics are tracked by the sentinel.volte.sip SBB and can be found under the following parameter set in REM:
SLEE-Usage → sentinel.volte.sip service → sentinel.volte.sip SBB → feature → MMTelTIR
or with rhino-stats:
SLEE-Usage → [sentinel.volte.sip service name] → [sentinel.volte.sip SBB name] → .feature.MMTelTIR

Statistic | Incremented when…​
--- | ---
    Started
| the feature runs
    FailedToStart
| Sentinel VoLTE encounters an error while attempting to start the feature
    IssuedWarning
| a non-fatal problem is encountered and the feature issues a warning
    FailedDuringExecution
| a fatal problem is encountered and the feature cannot execute correctly
    TimedOut
| the feature takes too long to complete and Sentinel VoLTE aborts execution
    ProcessingResponse
| the feature processes a SIP response
    ProcessingRequest
| the feature processes a SIP request
    FromChangeTagRemoved
| the feature removes the `from-change` tag from a `Supported` header in the outgoing SIP message
    ReceivedMalformedPrivacyHeader
| a non-standard `Privacy` header is found in an incoming SIP message
    PrivacyHeaderChanged
| the feature changes the contents of the `Privacy` header on an outgoing SIP message

=== MMTelWifiChargingFinalisation

MMTelWifiChargingFinalisation statistics are tracked by the sentinel.volte.sip SBB and can be found under the following parameter set:
SLEE-Usage → [sentinel.volte.sip service name] → [sentinel.volte.sip SBB name] → feature.MMTelWifiChargingFinalisation

Statistic | Increments when…​
--- | ---
    Started
| The feature is started.
    OCTerminatingDomainHeaderStripped
| An OC-Terminating-Domain header is found on an outgoing message and removed.
    ChargingInstanceFinalised
| A non-finalised reservation charging instance is found and finalised.
    Received2xxForOriginalInvite
| A SIP 2xx response for the initial INVITE is received by the feature.
    TerminatingDomainIsWifi
| The feature determines that terminating access is over WiFi.
    FailedToStart
| Sentinel VoLTE encounters an error while attempting to start the feature.
    IssuedWarning
| A non-fatal problem is encountered and the feature issues a warning.
    FailedDuringExecution
| A fatal problem is encountered and the feature cannot execute correctly.
    TimedOut
| The feature takes too long to complete and Sentinel VoLTE aborts execution.

=== MMTelParallelFA

MMTelParallelFA statistics are tracked by the sentinel.volte.sip SBB and can be found under the following parameter set in REM:
SLEE-Usage → sentinel.volte.sip service → sentinel.volte.sip SBB → feature → MMTelParallelFA
or with rhino-stats:
"SLEE-Usage.Services.ServiceID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].SbbID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].feature.MMTelParallelFA"

Name | Type | Incremented when …​
--- | --- | ---
Started | Counter | each time the feature runs
FailedDuringExecution | Counter | a fatal error occurs while the feature is executing
FailedToStart | Counter | Sentinel VoLTE encounters an error while attempting to start the feature.
IssuedWarning | Counter | a non-fatal problem is encountered and the feature issues a warning.
TimedOut | Counter | the feature takes too long to complete and Sentinel VoLTE aborts execution
ProcessingRequest | Counter | processing a request message.
ProcessingResponse | Counter | processing a response from the downstream forked legs.
InviteRequestReceived | Counter | the original INVITE is received.
CancelRequestReceived | Counter | a CANCEL message is received.
ProvisionalResponseReceived | Counter | a 1xx message is received.
GroupMemberAlerted | Counter | an INVITE request is sent to a group member.
LegReleased | Counter | a dialog leg is released.
UpstreamForkCreated | Counter | the feature creates a new leg towards the calling party. It happens on the provisional responses.
TriggeredOnResponse | Counter | the feature is triggered on a response message.
TriggeredOnRequest | Counter | the feature is triggered on a request message.
TriggeredOnTimer | Counter | the feature is triggered on a timmer.
TimeoutTimerCancelled | Counter | the feature cancel the timer.
TimeoutTimerSet | Counter | the feature sets the timer. The timer is set before the INVITE is sent to the first group member.
ExitedEarlyNoMembersToAlert | Counter | there is just one member in the group and it is the pilot number.
Received480 | Counter | receives a 480 (Temporarily Unavailable) response from a member
Received486 | Counter | receives a 486 (Busy Here) response from a member
Received408 | Counter | receives a 408 (Timeout) response from a member
Received404 | Counter | receives a 404 (Not found) response from a member
ReceivedSuccess | Counter | receives a 200 (OK) response from a member
RespondedUpstreamWith480 | Counter | the feature sends a 480 (Temporarily Unavailable) to the calling party.
RespondedUpstreamWith486 | Counter | the feature sends a 486 (Busy Here) to the calling party.
RespondedUpstreamWith408 | Counter | the feature sends a 408 (Timeout) to the calling party.
RespondedUpstreamWith404 | Counter | the feature sends a 404 (Not found) to the calling party.
RespondedUpstreamWithSuccess | Counter | the feature sends a 200 (OK) to the calling party.

=== MMTelSequentialFA

MMTelSequentialFA statistics are tracked by the sentinel.volte.sip SBB and can be found under the following parameter set in REM:
SLEE-Usage → sentinel.volte.sip service → sentinel.volte.sip SBB → feature → MMTelSequentialFA
or with rhino-stats:
"SLEE-Usage.Services.ServiceID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].SbbID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].feature.MMTelSequentialFA"

Name | Type | Incremented when …​
--- | --- | ---
Started | Counter | each time the feature runs
FailedDuringExecution | Counter | a fatal error occurs while the feature is executing
FailedToStart | Counter | Sentinel VoLTE encounters an error while attempting to start the feature.
IssuedWarning | Counter | a non-fatal problem is encountered and the feature issues a warning.
TimedOut | Counter | the feature takes too long to complete and Sentinel VoLTE aborts execution
ProcessingRequest | Counter | processing a request message.
ProcessingResponse | Counter | processing a response from a downstream forked leg.
InviteRequestReceived | Counter | the original invite is received.
CancelRequestReceived | Counter | a CANCEL message is received.
ProvisionalResponseReceived | Counter | a 1xx message is received.
SuccessResponseReceived | Counter | a 200 (OK) message is received.
GroupMemberAlerted | Counter | an INVITE message was sent to a group member.
GroupMemberAddedToQueue | Counter | a group member was queued for alerting.
MemberLegReleased | Counter | a dialog leg is released.
RespondedUpstreamManually | Counter | the feature created an upstream response.
TriggeredOnResponse | Counter | the feature is triggered on a response message.
TriggeredOnRequest | Counter | the feature is triggered on a request message.
TriggeredOnTimer | Counter | the feature is triggered on a timer event.
TriggeredOnLegEndEvent | Counter | the feature is triggered on a SIP leg end event.
AnyResponseTimerSet | Counter | the feature set a timer to wait for a response on a downstream leg.
FinalResponseTimerSet | Counter | the feature set a timer to wait for a final response on a downstream leg.
AnyResponseTimerCancelled | Counter | the timer waiting for a response on a downstream leg was cancelled.
FinalResponseTimerCancelled | Counter | the timer waiting for a final response on a downstream leg was cancelled.
TimerFired | Counter | the feature handled a timer event.
ExitedEarlyNoMembersToAlert | Counter | there is just one member in the group and it is the pilot number.

=== MMTelECT

Name | Increments when …​
--- | ---
Started | each time the feature runs
FailedDuringExecution | a fatal error occurs while the feature is executing
FailedToStart | Sentinel VoLTE encounters an error while attempting to start the feature.
IssuedWarning | a non-fatal problem is encountered and the feature issues a warning.
TimedOut | the feature takes too long to complete and Sentinel VoLTE aborts execution.
ReferReceivedFromServedUser | a REFER request has been received from the served user
ReferSuccessful | the transferee has responded to a processed REFER request with a 202 Accepted)
ReferProcessedAndForwarded | a REFER request has been received from the transferor, appropriately modified and sent to the transferee
EctInviteReceived | an INVITE request has been received from the transferor as a result of a previous REFER request
EctInviteProcessedAndForwarded | an ECT INVITE request has been received by the transferee, appropriately modified and sent to the transfer-target
ThirdPartyCallControlProceduresInvoked | the Third Party Call Control (3pcc) transfer procedures have been invoked
ThirdPartyCallControlProceduresFailed | the Third Party Call Control (3pcc) transfer procedures did not result in a successful dialogue between the transferee and transfer-target
OriginalCallResumed | the original dialogue between the transferee and the transferor has been resumed if the 3pcc procedures failed
CassandraInsertSucceeded | ECT session information has been successfully inserted into the Cassandra DB
CassandraInsertFailed | an error occurred attempting to insert ECT session information into the Cassandra DB
CassandraQuerySucceeded | ECT session information has been successfully retrieved from the Cassandra DB
CassandraQueryFailed | an error occurred attempting to retrieve ECT session information from the Cassandra DB
DeletedCassandraRow | REFER request was cancelled by user, and so the Cassandra ECT record was deleted.
StoppedHandlingAndAllowedB2BUA | an INVITE request with a Request URI matching the ECT URI pattern was received and forwarded without modification
TransferSuccessful | a 200 (OK) was received from the transfer-target as a result of the ECT procedures
ErrorOccurredDuringExecution | an error occurred attempting to execute the feature
NoAnswerTimerFired | The feature timed-out waiting for an answer from a sent request.

=== MMTel Session Transfer features

==== MMTelStodBind

MMTelBindAci statistics are tracked by the sentinel.volte.sip SBB and can be found under the following parameter set in REM:
SLEE-Usage → sentinel.volte.sip service → sentinel.volte.sip SBB → feature → MMTelBindAci
or with rhino-stats:
"SLEE-Usage.Services.ServiceID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].SbbID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].feature.MMTelBindAci"

Name | Incremented when…​
--- | ---
    Started
| the feature runs
    FailedToStart
| Sentinel VoLTE encounters an error while attempting to start the feature
    IssuedWarning
| a non-fatal problem is encountered and the feature issues a warning
    FailedDuringExecution
| a fatal problem is encountered and the feature cannot execute correctly
    TimedOut
| the feature takes too long to complete and Sentinel VoLTE aborts execution
    BoundAciToImpu
| the ACI is bound to an this is incremented.
    UsedLinkedAciForBinding
| the triggering ACI is not used for binding, i.e the call is not MobileTerminating then the linked ACI is used.
    UsedTriggeringAciForBinding
| the call is a MobileTerminating call the Triggering ACI is used for binding.

==== MMTelStodEnabled

Name | Incremented when…​
--- | ---
    Started
| the feature runs
    FailedToStart
| Sentinel VoLTE encounters an error while attempting to start the feature
    IssuedWarning
| a non-fatal problem is encountered and the feature issues a warning
    FailedDuringExecution
| a fatal problem is encountered and the feature cannot execute correctly
    TimedOut
| the feature takes too long to complete and Sentinel VoLTE aborts execution
    StodIsEnabled
| the Stod is enabled for a subscriber
    StodIsNotEnabled
| the Stod is not enabled for a subscriber
    StodEnableSessionTracking
| STOD session tracking is enabled for this session
    StodSessionTrackingDisabled
| STOD session tracking is disabled for this session
    FoundTrackingKey
| A tracking key has been created for this session and added to the set

==== MMTelStodProcessHandover

Name | Incremented when…​
--- | ---
    Started
| the feature runs
    FailedToStart
| Sentinel VoLTE encounters an error while attempting to start the feature
    IssuedWarning
| a non-fatal problem is encountered and the feature issues a warning
    FailedDuringExecution
| a fatal problem is encountered and the feature cannot execute correctly
    TimedOut
| the feature takes too long to complete and Sentinel VoLTE aborts execution
    SentRemoteUpdate
| a re-INVITE is sent to the called party.
    RemoteUpdateSuccess
| re-INVITE was accepted (200 OK).
    RemoteUpdateError
| re-INVITE was not accepted.
    CallAnsweredWith200
| the (200 OK) from the re-INVITE is sent to the new access leg
    ReleasedOldAccessLeg
| the previous calling leg is released
    LinkedNewAccessLegToRemoteLeg
| the transfer INVITE leg is linked to the existing called party leg
    TerminatedSession
| the session finishes
    AccessTransferComplete
| the session transfer was done successfully
    HandoverRequestReceived
| a session transfer INVITE is received
    StodEnableSessionTracking
| tries to mark the new transfered session to be tracked
    FoundTrackingKey
| the tracking key is set
    StodSessionTrackingDisabled
| when failed to set the new transfered session to be tracked

==== MMTelStodTriggerAnchor

MMTelStodTriggerAnchor statistics are tracked by the sentinel.volte.sip SBB and can be found under the following parameter set in REM:
SLEE-Usage → sentinel.volte.sip service → sentinel.volte.sip SBB → feature → MMTelStodTriggerAnchor
or with rhino-stats:
"SLEE-Usage.Services.ServiceID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].SbbID[name=sentinel.volte.sip,vendor=OpenCloud,version=3.1.0].feature.MMTelStodTriggerAnchor"

Name | Incremented when…​
--- | ---
    Started
| the feature runs
    FailedToStart
| Sentinel VoLTE encounters an error while attempting to start the feature
    IssuedWarning
| a non-fatal problem is encountered and the feature issues a warning
    FailedDuringExecution
| a fatal problem is encountered and the feature cannot execute correctly
    TimedOut
| the feature takes too long to complete and Sentinel VoLTE aborts execution
    FiredIncomingRequestEvent
| the transfer INVITE is sent to the session to be transfered.

== SCC Features

=== Service Centralisation Features

==== SCCCamelToIMSReOriginationIN

SCCCamelToIMSReOriginationIN statistics are tracked by the sentinel.volte.ss7 SBB and can be found under the following parameter set:
SLEE-Usage → sentinel.volte.ss7 service → sentinel.volte.ss7 SBB → feature → SCCCamelToIMSReOriginationIN

Parameter | Type | Description
--- | --- | ---
    Started
| Counter | Incremented when the feature starts.
    FailedToStart
| Counter | Incremented when the feature failed to start due to an error.
    IssuedWarning
| Counter | Incremented when the feature raised a warning.
    FailedDuringExecution
| Counter | Incremented when the feature failed due to a major error.
    TimedOut
| Counter | Incremented when the feature timed out during execution.
    CallReOriginated
| Counter | Incremented when the call is successfully reoriginated.
    CallReleased
| Counter | Incremented when reorigination fails and the call is released.
    Misconfigured
| Counter | Incremented when the feature has not been correctly configured.
    IdpVlrNumberPresent
| Counter | Incremented when the VLR number is found in the incoming InitialDP.
    IdpVlrNumberNotPresent
| Counter | Incremented when the VLR number is not found in the incoming InitialDP.
    VisitedNetworkIdNotFound
| Counter | Incremented when the feature is unable to determine the Visited Network ID.
    VisitedNetworkIdFound
| Counter | Incremented when the feature is able to determine the Visited Network ID based on the VLR address.
    PoolAllocationFailed
| Counter | Incremented when the feature fails to acquire a correlation ID from the correlation RA.
    PoolAllocationSucceeded
| Counter | Incremented when the feature acquires a correlation ID from the correlation RA.
    OriginatingIMRNAttempt
| Counter | Incremented when the feature executes reorigination for an originating call leg.
    TerminatingIMRNAttempt
| Counter | Incremented when the feature executes reorigination for a terminating call leg.
    ReoriginationBypassed
| Counter | Incremented when the feature bypasses reorigination for an unregistered subscriber.

==== SCCCamelToIMSReOriginationSIP

SCCCamelToIMSReOriginationSIP statistics are tracked by the volte.sentinel.sip SBB and can be found under the following parameter set:
SLEE-Usage → volte.sentinel.sip service → volte.sentinel.sip SBB → feature → SCCCamelToIMSReOriginationSIP

Statistic | Incremented when…​
--- | ---
Complete | The feature ran to completion
MultipleHistoryInfoHeadersFound | Multiple history-info headers found on the INVITE
NoHistoryInfoHeaderFound | no history-info header found on the INVITE
OneHistoryInfoHeaderFoundAndRemoved | One history-info header found on the INVITE and removed
HSSLookupFailed | HSS lookup failed
HSSLookupSuccess | HSS lookup succeeded
HSSLookupSkipped | HSS lookup was skipped due to SkipHSSLookup feature configuration flag
CorrelationRaQueried | Correlation RA was queried for the call information
CorrelationRaQuerySuccess | The Correlation RA query succeeded
CorrelationRaQueryFailure | The Correlation RA query failed
IdpVlrNumberPresent | The VLR number is present in the initial IDP
IdpVlrNumberNotPresent | The VLR number is not present in the initial IDP
VisitedNetworkIdFound | The feature could set the Visited Network Id based on the Location information or on the VLR address
VisitedNetworkIdNotFound | The feature could set the Visited Network Id
IdpCalledPartyNumberPresent | The initial IDP has a called party number or called party BCD number
IdpCalledPartyNumberNotPresent | The initial IDP does not have a called party number or called party BCD number
SCSCFAddressNotFound | The SCSCF could not be found in configuration, or retrieved from the HSS
AccessNetworkInfoFound | AccessNetworkInfo was found in the original InitialDP
AccessNetworkInfoNotFound | AccessNetworkInfo could not be found in the original InitialDP
CallingPartyAndPaiDoNotMatch | The request is rejected because of a mismatch between calling party and P-Asserted-Identity
Started | The feature starts
FailedToStart | The feature failed to start due to an error
IssuedWarning | The feature raised a warning
FailedDuringExecution | The feature failed due to a major error
TimedOut | The feature timed out during execution

=== Terminating Access Domain Selection Features

==== SCCTADSDataLookup

SCCTADSDataLookUp statistics are tracked by the SCCTADSDataLookUp SBB and can be found under the following parameter set: SLEE-Usage → volte.sentinel.sip service ID → SCCTADSDataLookUp SBB ID.

Name | Type | Description
--- | --- | ---
    Started
| Counter | Incremented when the feature is triggered.
    FailedToStart
| Counter | Incremented when the feature fails to start.
    FailedDuringExecution
| Counter | Incremented when the feature fails while executing.
    IssuedWarning
| Counter | Incremented when the feature issues a warning.
    TimedOut
| Counter | Incremented when the feature times out during execution.
    QueriedShCache
| Counter | Incremented when the Sh Cache Microservice RA is queried.
    ShCacheDataReceived
| Counter | Incremented when the Sh Cache Microservice RA returns data from the query.
    FoundValidCSRoute
| Counter | Incremented when the feature finds a valid route to the CS domain.
    FoundValidPSRoute
| Counter | Incremented when the feature finds a valid route to the PS domain.
    BlindPSRoutingRequested
| Counter | Incremented when the feature has set the BlindPSRouting Session State field.
    NoForkDispositionOverrodeRoutingMode
| Counter | Incremented when the feature does not fork due to disposition header.
    CompanionDeviceOverrodeRoutingMode
| Counter | Incremented when the feature selects `parallel` routing mode because the subscriber has a companion device.
    TriggeredEndSession
| Counter | Incremented when the feature rejects an `INVITE` request due to there being no valid routes to forward it on.
    ResponseLatency
| Sampled | Records elapsed time between requesting data from the Sh Cache Microservice RA and getting a response (in milliseconds).
    CompanionDeviceSipInstanceRoutingEnabled
| Counter | Incremented when enabling companion device sip instance routing override.

==== SCCTADSParallelRouting

`SCCTADSParallelRouting` statistics are tracked by the `volte.sentinel.sip` SBB and can be found under the following parameter set:
SLEE-Usage → volte.sentinel.sip service ID → volte.sentinel.sip SBB ID → feature.SCCTADSParallelRouting

Name | Description
--- | ---
    Started
| Incremented when the feature is triggered.
    FailedToStart
| Incremented when the feature fails to start.
    FailedDuringExecution
| Incremented when the feature fails while executing.
    IssuedWarning
| Incremented when the feature issues a warning.
    TimedOut
| Incremented when the feature times out during execution.
    TriggeredOnRequest
| Incremented when the feature is triggered on a SIP Request.
    TriggeredOnResponse
| Incremented when the feature is triggered on a SIP Response.
    TriggeredOnTimer
| Incremented when the feature is triggered on the timer firing.
    CSRNNotFound
| Incremented when the CS fork cannot be established because no CSRN can be found.
    MaxWaitTimerSet
| Incremented when the Max Wait Timer is started.
    MaxWaitTimerCancelled
| Incremented when the Max Wait Timer is cancelled.
    UpstreamForkCreated
| Incremented when an upstream forked leg is created to forward a provisional or success response from the CS leg or any secondary PS leg.
    ReceivedProvisionalResponse
| Incremented when a provisional 18x response is received.
    ReceivedFinalResponse
| Incremented when a final response is received for the initial INVITE.
    RouteToCSAttempted
| Incremented when an INVITE is routed down the CS forked leg.
    RouteToPSAttempted
| Incremented when an INVITE is routed down a PS forked leg.
    RouteToCSFailed
| Incremented when the CS leg is torn down without being answered.
    RouteToPSFailed
| Incremented when a PS leg is torn down without being answered.
    AnsweredOnCS
| Incremented when a success response is received on the CS leg.
    AnsweredOnPS
| Incremented when a success response is received on a PS leg.
    TADSTerminatingDomainsNotSet
| Incremented when the feature cannot retrieve the terminating domains for the active routes from session state.
    NoForkAdded
| Incremented when the feature adds the `Request-Disposition: no-fork` directive to an outgoing INVITE.
    NoForkRemoved
| Incremented when the feature removes the `Request-Disposition: no-fork` directive from an outgoing INVITE.

==== SCCTADSRouting

SCCTADSRouting statistics are tracked by the SCCTADSRouting SBB and can be found under the following parameter set: SLEE-Usage → sentinel.volte.sip service ID → SCCTADSRouting SBB ID.

Name | Description
--- | ---
    Started
| Incremented when the feature is triggered.
    FailedToStart
| Incremented when the feature fails to start.
    FailedDuringExecution
| Incremented when the feature fails while executing.
    IssuedWarning
| Incremented when the feature issues a warning.
    TimedOut
| Incremented when the feature times out during execution.
    RouteToPreferredPS
| Incremented when the feature successfully to routes to a preferred leg when PS is preferred.
    RouteToPreferredCS
| Incremented when the feature successfully to routes to a preferred leg when CS is preferred.
    RouteToFallbackPS
| Incremented when the feature successfully to routes to a fallback leg when PS is preferred.
    RouteToFallbackCS
| Incremented when the feature successfully to routes to a fallback leg when CS is preferred.
    ErrorResponseMatched
| Incremented when an error response received from a routing attempt triggers a new routing attempt.
    Error18xMatched
| Incremented when the PS call 18x response matches the SDP requirements outlined in 18x Response.
    Received18xResponse
| Incremented when the feature receives a 18x response to the initial `INVITE` request
    Received488Response
| Incremented when the feature receives a 488 message from the PS call.
    ReceivedPSToCSFallbackResponseCode
| Incremented when the feature receives a error message from the PS call that is contained in `PSToCSFallbackResponseCodes`.
    TerminatingDomainHeaderSet
| Incremented when the feature adds a terminating domain header to an upstream response
    TADSTimerFired
| Incremented when the Max Wait Timer for a response on a routing attempt is exceeded
    RouteToPreferredPSAnswered
| Incremented when a preferred PS leg is answered
    RouteToFallbackPSAnswered
| Incremented when a fallback PS leg is answered
    RouteToPreferredCSAnswered
| Incremented when a preferred CS leg is answered
    RouteToFallbackCSAnswered
| Incremented when a fallback CS leg is answered
    RouteToPreferredPSFailed
| Incremented when a preferred PS leg returns a failed SIP response e.g. >299
    RouteToPreferredCSFailed
| Incremented when a preferred CS leg returns a failed SIP response e.g. >299
    RouteToFallbackPSFailed
| Incremented when a fallback PS leg returns a failed SIP response e.g. >299
    RouteToFallbackCSFailed
| Incremented when a fallback CS leg returns a failed SIP response e.g. >299

= License Requirements :sortorder: 15 :toc: macro :toclevels: 4 :toc-title: On this page…​

This page gives information about license requirements for running Sentinel VoLTE.

== Required License Functions

All services and resource adaptors require the following license function:

License Function | Optional | Required For
--- | --- | ---
Rhino | No | Capacity

This following sections list the additional license functions required by certain components of Sentinel VoLTE. Some of the components listed below modify the Rhino license function to be only necessary for `Activation` instead of `Capacity`.

| Not all of the components listed below will be present in all Sentinel VoLTE deployments.

=== Services

==== Sentinel VoLTE SIP Service Component Name: `sip.sentinel.volte`

License Function | Optional | Required For
--- | --- | ---
Rhino | No | Activation
Sentinel | No | Activation
Sentinel-VoLTE | No | Capacity

==== Sentinel VoLTE SS7 Service Component Name: `sentinel.volte.ss7`

License Function | Optional | Required For
--- | --- | ---
Rhino | No | Activation
Sentinel | No | Activation
Sentinel-VoLTE | No | Capacity

==== Sentinel Registrar Service Component Name: `sentinel.registrar`

License Function | Optional | Required For
--- | --- | ---
Rhino | No | Activation

==== IMSSF Service Component Name: `IMSSF`

License Function | Optional | Required For
--- | --- | ---
Rhino | No | Activation

=== Resource Adaptors

==== SIS-SIP/EasySIP RA Component Name: `SIS-SIP/EasySIP RA`

License Function | Optional | Required For
--- | --- | ---
Rhino-SIS | No | Capacity
Rhino-SIS-SIP | No | Capacity
Rhino-SIS-SIP-External-Service | Yes | Capacity
Rhino-SIS-SIP-Local-Service | Yes | Capacity

==== SIS-IN Unified RA Component Name: `SIS-IN Unified`

License Function | Optional | Required For
--- | --- | ---
Rhino-SIS | No | Capacity
Rhino-SIS-IN | No | Capacity
Rhino-SIS-IN-External-Service | Yes | Capacity
Rhino-SIS-IN-Local-Service | Yes | Capacity
Rhino-SIS-IN-Protocol-CAP | Yes | Capacity
Rhino-SIS-IN-Protocol-ETSI-INAP-CS1 | Yes | Capacity
Rhino-SIS-IN-SMS | Yes | Capacity
Rhino-SIS-IN-SPS | Yes | Capacity
Rhino-SIS-IN-TPS | Yes | Capacity
Rhino-SIS-IN-IN-Voice | Yes | Capacity

==== CGIN Unified RA Component Name: `CGIN Unified RA`

License Function | Optional | Required For
--- | --- | ---
Rhino-CGIN | No | Activation
Rhino-CGIN-Base | No | Activation

==== IMSSF Management RA Component Name: `IMSSF Management RA`

License Function | Optional | Required For
--- | --- | ---
Rhino-IM-SSF | No | Activation

==== HTTP RA Component Name: `HTTP`

License Function | Optional | Required For
--- | --- | ---
Rhino-HTTP | No | Activation

= Enable Companion Device :toc: macro :toclevels: 4 :toc-title: On this page…​

This page describes the steps to enable companion device. For more detailed information on Companion Device refer to the architecture section.

| Part of the enabling process involves turning on a second query to the HSS to check if the serving subscriber is a companion device. This query takes place for orig, orig-cdiv, and term sescase calls. This can not be turned on per subscriber.

== Enable HSS Metaswitch-TAS-Services query

The `Metaswitch-TAS-Services` document is read by the MMTel SubscriberDataLookupFromHSS feature. If companion device information is present, it is saved in session state for use by subsequent features.

=== Enable query

    rhino-console> setprofileattributes Operator_SubscriberDataLookupFromHss2ServiceIndicationProfileTable Metaswitch-TAS-Services DisableQuery false

=== Disable query

    rhino-console> setprofileattributes Operator_SubscriberDataLookupFromHss2ServiceIndicationProfileTable Metaswitch-TAS-Services DisableQuery true

| If the subscriber does not have a `Metaswitch-TAS-Services` document, or the document’s companion device section is empty, then the call proceeds normally with no special companion device behaviour.

== Companion Device Feature Configuration

Companion Device related features are accessed from the REM Group Feature configuration page. These include Companion Device specific fields and other configuration that is related. To access the features.

- Select Sentinel from the main menu

- Select Feature Configuration to bring up Group Feature configuration page

- From the Group list select Companion Device Support.

For further information on the features listed, refer to.

- Determine Shared And Undisclosed Identities Feature

- Fetch CMSISDN

- SCC Fetch MSRN

- Hide Undisclosed Identity Feature

- SCC TADS Data Lookup

- SCC TADS Parallel Routing

- Strip Preconditions

- Subscriber Data Lookup from HSS

1 | Select Determine Shared and Undisclosed Identities Feature
2 | To enable hiding of the undisclosed identity when the Companion Device makes a call and blocking calls to the undisclosed identity. Select Hide and Block Undisclosed Identities?
3 | Click the Save button at the lower right.

1 | Select Hide Undisclosed Identity Feature
2 | This extra step is needed when hiding undisclosed identities. Select Hide Undisclosed Identities?
3 | Click the Save button at the lower right.

1 | Select SCC TADS Data Look Up
2 | The SCCTADSDataLookup feature determine PS and CS routes. The attribute `Sip Instance Routing` instructs T-ADS to fork the INVITE towards the available PS contact addresses, including the companion device, if any. The attribute `Companion Sip Instance Routing` instructs T-ADS to automatically perform forking to all available PS contacts, if the call is to a subscriber with Companion Devices. This will override the `Sip Instance Routing` attribute. Select Enable Sip Instance Routing? Select Enable Companion Sip Instance Routing?
3 | Click the Save button at the lower right.

1 | Select Strip Preconditions
2 | Enabling `Strip Preconditions` is required in deployments with Metaswitch Perimeta and where downstream forking is expected to occur. In this scenario if multiple forked 1xx responses are forwarded upstream, the upstream Perimeta will combine them into a single dialog for the calling UE. This means the UE cannot send UPDATEs on each forked dialog to complete precondition negotiations. To avoid this issue preconditions must be removed from the outgoing initial INVITE. Select Strip Preconditions
3 | Click the Save button at the lower right.

== UsePathForSipInstanceRouting

For devices that don’t include a `GRUU` inside `Contact` headers, the Path information from the REGISTER can be used for routing.

=== Enable UsePathForSipInstanceRouting

        rhino-console> setprofileattributes SCCTADSDataLookUpConfigProfileTable Operator:::: UsePathForSipInstanceRouting true

=== Disable UsePathForSipInstanceRouting

        rhino-console> setprofileattributes SCCTADSDataLookUpConfigProfileTable Operator:::: UsePathForSipInstanceRouting false

== Busy Behaviour

T-ADS can optionally terminate all forked legs when the first `486 (Busy Here)` response arrives from any device. This means if multiple devices are alerting, and one device declines the call, then all devices will stop alerting as well. For more information refer to SCCTADSParallelRouting feature.

=== Enable ReleaseAllLegsOnBusy

    rhino-console> setprofileattributes SCCTADSParallelRoutingConfigProfileTable Operator:::: ReleaseAllLegsOnBusy true

== Provision Subscribers with Companion Device

Companion Device information is stored in the subscriber’s `Metaswitch-TAS-Services` document in the HSS. REM can be used to add Companion Devices into the transparent data for the IMS public identities for both the Primary and Companion Devices. In other words the Primary and Companion devices use the same transparent data. This requires that the HSS supports `Alias Public User Identity Set`.

| Configuration of the `Metaswitch-TAS-Services` document and subsequent query to the HSS is outside the scope of this document. Please refer to your HSS vendor documentation.

=== Example Configuration

In this example, the called party has a `Metaswitch-TAS-Services` document that indicates they have a companion device with CS support, by the presence of the `device/radio-access/CS` element as shown in the XML fragment below:

    <metaswitch-services xmlns="http://metaswitch.com/XMLSchema/tas">
      <complete-companion-device>
        <operator-companion-device authorized="true">
          <shared-identity-sip>sip:+641234567@example.com</shared-identity-sip>
          <shared-identity-tel>tel:+641234567</shared-identity-tel>
          <devices>
            <device active="true">
              <model>Acme Watch</model>
              <radio-access>
                <PS/>
                <CS msisdn="641234568"/>
              </radio-access>
            </device>
          </devices>
        </operator-companion-device>
      </complete-companion-device>
    </metaswitch-services>

= Service Assurance Server (SAS) Tracing

Sentinel VoLTE is integrated with the MetaView Service Assurance Server (SAS) to give an end-to-end view of traces within the Metaswitch IMS solution. Along with the service and RA level SAS tracing, many features have additional specific SAS tracing relating to their feature logic. To determine if a feature has SAS support, refer to the feature documentation or the VoLTE changelog.

== Enabling VoLTE SAS tracing

To configure and enable Rhino to send events to MetaView Service Assurance Server (SAS), additional Rhino configuration is required. Please see Rhino MetaView Service Assurance Server (SAS) Tracing for more details.

== VoLTE SAS bundle

The VoLTE SAS bundle contains definitions of all SAS events that will be sent to the server. The SAS bundle is backwards compatible between minor versions.

=== Installing Rhino VoLTE SAS bundle

The VoLTE SAS bundle is installed with VoLTE as part of the standard installation into Rhino.

=== Exporting Rhino VoLTE SAS bundle

To export the VoLTE SAS bundle from a Rhino with VoLTE installed, refer to Rhino SAS Bundle Generation

1. Call-ID, Record-Route and Via headers are automatically anonymized by the B2BUA process
2. This is the equivalent of the Privacy Header not being present
3. History-Info header is only removed if AllowHistoryInfoDeletion is set to `true`