| .. This work is licensed under a Creative Commons Attribution 4.0 International License. |
| .. SPDX-License-Identifier: CC-BY-4.0 |
| .. CAUTION: this document is generated from source in doc/src/rtd. |
| .. To make changes edit the source and recompile the document. |
| .. Do NOT make changes directly to .rst or .md files. |
| |
| ============================================================================================ |
| Route Table Guide |
| ============================================================================================ |
| -------------------------------------------------------------------------------------------- |
| RIC Message Router -- RMR |
| -------------------------------------------------------------------------------------------- |
| |
| |
| Overview |
| ======== |
| |
| Messages sent via the RIC Message Router (RMR) are routed to |
| an endpoint (another application) based on a combination of |
| the *message type* (MT) and *subscription ID* (SID) supplied |
| in the message. RMR determines the endpoint by matching the |
| MT and SID combination to an entry in a route table which has |
| been supplied dynamically by a *Route Manager* service, or as |
| a static table loaded during RMR initialisation. It is also |
| possible to route messages directly to an endpoint which is |
| the *managed entity* "owner," using the *managed entity ID* |
| (MEID). |
| |
| For most xAPP developers the format of the RMR route table is |
| not important beyond understanding how to create a static |
| table for local testing. For developers of a *Route Manager* |
| service, the need is certainly a requirement. This document |
| describes the overall syntax of a route table and the |
| interface between the *Route Manager* service and RMR. |
| |
| |
| Contents of a Route Table |
| ========================= |
| |
| The table consists of a start record, one or more entry |
| records, and an end record. Each entry record defines one |
| message type, with an optional sender application, and the |
| endpoint(s) which accept the indicated message type. All |
| table records contain fields separated with vertical bars |
| (|), and allow for trailing comments with the standard shell |
| comment symbol (hash, #) provided that the start of the |
| comment is separated from the last token on the record by one |
| or more spaces. Leading and trailing white space in each |
| field is ignored. Figure 1 illustrates a very basic route |
| table with two message types, 1000 and 2000, and two |
| subscription IDs for message type 1000. |
| |
| |
| :: |
| |
| newrt | start | rt-0928 |
| rte | 2000 | logger:30311 |
| mse | 1000 | 10 | forwarder:43086 |
| mse | 1000 | 21 | app0:43086,app1:43086 |
| newrt | end | 3 |
| |
| Figure 1: A basic route table. |
| |
| |
| Entry record syntax |
| ------------------- |
| |
| Two types of table entries are supported for compatibility |
| with the original RMR implementation, but only the *mse* |
| entry type is needed and that should be the entry used when |
| creating new tables. The following shows the syntax for both |
| entry types: |
| |
| |
| :: |
| |
| rte | <msg-type>[,<sender-endpoint>] | <endpoint-group>[;<endpoint-group>;...] |
| mse | <msg-type>[,<sender-endpoint>] | <sub-id> | <endpoint-group>[;<endpoint-group>;...] |
| |
| |
| Where: |
| |
| |
| .. list-table:: |
| :widths: 25,70 |
| :header-rows: 0 |
| :class: borderless |
| |
| * - **mse, rte** |
| - |
| is the table entry type |
| |
| * - **<msg-type>** |
| - |
| is the integer message type |
| |
| * - **<sender-endpoint>** |
| - |
| is the endpoint description of the message sender; only that |
| sender will read the entry from the table, so a single table |
| may be used for all senders when a common message type is |
| delivered to varying endpoints based on senders. If the |
| sender endpoint is omitted from the entry, then the entry |
| will be used by all applications. |
| |
| * - **<sub-id>** |
| - |
| is the subscription id (integer) for subscription-based |
| messages, or -1 if the message type is not |
| subscription-based. An *mse* entry with a sub-id of -1 is the |
| **same** as an *rte* entry with the same message type. |
| |
| * - **<endpoint-group>** |
| - |
| is one or more, comma separated, endpoint descriptions. |
| |
| |
| |
| When an application sends a message with the indicated type, |
| the message will be sent to one endpoint in the group in a |
| round-robin ordering. If multiple endpoint groups are given, |
| then the message is sent to a member selected from each |
| group; 3 groups, then three messages will be sent. The first |
| group is required. |
| |
| |
| Line separation |
| --------------- |
| |
| Table entries **must** end with a record termination sequence |
| which may be one of the following three sequences: |
| |
| |
| * a single newline (\\n) |
| * a DOS style CRLF pair (\\r\\n) |
| * a single carriage return (\\r) |
| |
| |
| Care must be taken when manually editing a static table; some |
| editors do **not** add a final record termination sequence to |
| the last line of a file. RMR expects the final record to have |
| a termination sequence to ensure that the record was not |
| truncated (especially important when receiving dynamic |
| tables). |
| |
| |
| Table framing |
| ------------- |
| |
| The route table parser within RMR assumes that route table |
| entries are sent via RMR messages as a stream. To ensure |
| synchronisation and prevent malformed tables because of |
| broken sessions or lost packets, each table must begin and |
| end with an *newrt* record. Each *newrt* record has one of |
| two possible syntax layouts as described below. |
| |
| |
| :: |
| |
| newrt | begin [| table-id-string] |
| newrt | end [| record-count] |
| |
| Figure 2: Illustration of the newrt records in the table. |
| |
| The *table-id-string* is an optional string which is used by |
| RMR when sending an acknowledgement back to the *Route |
| Manager* service (see the *Route Manager Interface* section |
| for more details). If a *record-count* is given as the final |
| field on the *end* record, RMR will verify that the number of |
| *mse* and *rte* entries in the table matches the count; if |
| there is a mismatch in values the table is not used. |
| |
| |
| Comments, spaces, and blank lines |
| --------------------------------- |
| |
| Comments may be placed to the right of any table entry line |
| using the standard shell comment symbol (#). The start of a |
| comment must be separated from any previous record content by |
| at least one space or tab. Complete lines are treated as |
| comments when the first non-whitespace character of a line is |
| a comment symbol. Blank lines are also ignored. |
| |
| Fields on table records are separated using the vertical bar |
| (|) character. Any white space (tabs or spaces) which appear |
| immediately before or after a separator are ignored. |
| |
| |
| Endpoint Description |
| -------------------- |
| |
| The endpoint description is either the hostname or IP address |
| followed by a port number; the two are separated by a single |
| colon. The illustration below assumes that host names (e.g. |
| forwarder and app1) are defined; they also make the tables |
| easier to read. The port number given is the port number that |
| the user application provides to RMR when the RMR |
| initialisation function is invoked (and thus is the port that |
| RMR is listening on). |
| |
| |
| Table Mechanics |
| =============== |
| |
| Creating a table from the two entry types is fairly simple, |
| however there are some subtleties which should be pointed out |
| to avoid unexpected behaviour. For this discussion the |
| following complete table will be used. |
| |
| .. list-table:: |
| :widths: 75,10 |
| :header-rows: 0 |
| :class: borderless |
| |
| |
| * - |
| |
| :: |
| |
| newrt | start | rt-0928 |
| rte | 2000 | logger:30311 |
| mse | 1000 | 10 | forwarder:43086 |
| mse | 1000,forwarder:43086 | 10 | app2:43086 |
| mse | 1000 | -1 | app0:43086,app1:43086; logger:20311 |
| newrt | end | 4 |
| |
| - |
| |
| :: |
| |
| (1) |
| (2) |
| (3) |
| (4) |
| (5) |
| (6) |
| |
| |
| Figure 3: A complete RMR routing table (line numbers to the |
| right for reference). |
| |
| |
| Table Entry Ordering |
| -------------------- |
| |
| Whether a table is read from a file on disk, or is received |
| from a *Route Manager* service, RMR parses the records to |
| build an internal route table keeping only the relevant |
| information. Entries are read in the order they appear (from |
| the file or in messages received), and RMR will use only one |
| entry for each MT/SID pair. |
| |
| For most tables, the ordering of entries is not important, |
| but when there are entries which duplicate the MT/SID pair |
| ordering becomes significant. RMR will use the **last** valid |
| entry for a MT/SID pair that it encounters. An entry is |
| considered valid if there is no sender identified with the |
| message type (line 3), and when the sender (host and port) |
| match the the applications' location and the port provided to |
| RMR for listening. |
| |
| Using the table in figure 3 as an example, there are two |
| entries which match the MT/SID pair of 1000/10. When this |
| table is parsed on any host, RMR will recognise and add the |
| first entry (line 3) to the internal representation; this |
| entry is valid for all applications. The second 1000/10 entry |
| (line 4) is valid when the table is parsed on the *forwarder* |
| host, and only by the application which is listening on port |
| 43086. For this application the entry will override the more |
| generic entry for the MT/SID combination. |
| |
| As a rule, the ordering of entries for a given MT/SID pair |
| should be from most generic to most specific. |
| |
| |
| Route Manager Communications |
| ============================ |
| |
| During initialisation RMR will use the value of the |
| ``RMR_RTG_SVC`` environment variable to connect to the *Route |
| Manager* service in order to request a route table. The |
| connection between RMR and the *Route Manager* is also an RMR |
| session and thus RMR messages will be used to exchange |
| requests and responses. |
| |
| |
| Table Request |
| ------------- |
| |
| During initialisation, RMR establishes a wormhole connection |
| to the *Route Manager* and sends a message type of 21 to |
| request a new table. RMR will continue to send table requests |
| until a table is received and accepted; in other words it is |
| fine for the *Route Manager* to ignore the requests if it is |
| not ready to respond. |
| |
| |
| Sending Tables To RMR |
| --------------------- |
| |
| Table entry data is expected to arrive via RMR message with a |
| message type of 20. The message may contain one or more |
| entries provided that the entries are newline separated. |
| Current versions of RMR support very large messages, however |
| to ensure compatibility with an xAPP built using an older |
| version of RMR (pre 3.8), messages should be limited to 4 |
| KiB. |
| |
| |
| Table Acceptance and Acknowledgement |
| ------------------------------------ |
| |
| When RMR receives the table end entry (newrt|end), it will |
| send a state message back to the *Route Manager* to indicate |
| the state of the received table. The message type is 22 and |
| the payload will contain UTF-8 tokens which indicate the |
| state. The second token will be the *table ID* supplied on |
| the start record, or the string "<id-missing>." When the |
| state is an error state, RMR might add a final set of tokens |
| which contain the reason for the failure. |
| |
| Upon receipt of a status message which indicates an "OK" |
| response, the *Route Manager* can assume that the table has |
| been installed and is in use. Any other response indicates |
| that RMR did not use the table and has dropped it; the |
| previous table is still in use. |
| |
| |
| Using A Static Route Table |
| -------------------------- |
| |
| A static route table can be provided to assist with testing, |
| or to provide a bootstrap set of route information until a |
| dynamic table is received from a routing manager. The |
| environment variable ``RMR_SEED_RT`` is checked during RMR |
| initialisation and if set is expected to reference a file |
| containing a route table. This table will be loaded and used |
| until overlaid by a table sent by the *Route Manager*. |
| |
| To simulate dynamic reloads during testing, and for some |
| specialised use cases, the static table will be reloaded |
| periodically if the ``RMR_RTG_SVC`` environment variable is |
| set to -1. When set to -1 RMR will not listen for *Route |
| Manager* connections, nor will it attempt to request a |
| dynamic table. |
| |
| If the file given by the ``RMR_SEED_RT`` variable does not |
| exist, and the ``RMR_RTG_SVC`` variable is set to -1, RMR |
| will block until the table is created. This simulates a |
| delayed dynamic load during testing, and can be used when the |
| xAPP is reading the route table saved by another local |
| process rather than one sent directly by the *Route Manager*. |
| |
| |
| Table Stashing |
| -------------- |
| |
| To assist with debugging, and to allow an application to |
| share the route table received from *Route Manager*, RMR will |
| stash the route table updates it received. Updates are |
| stashed in a file named by the ``RMR_STASH_RT`` environment |
| variable, and if that variable is not present, the |
| ``RR_SEED_RT`` variable will be used with an added |
| ``.stash`` extension. |
| |
| The primary use of route table stashing is to assist with |
| debugging of applications, and because there are risks for an |
| application to share its table, table sharing is **NOT** |
| recommended. Table sharing can be enabled by setting the |
| ``RMR_STASH_RT`` variable for the application that will be |
| the source of the route table updates, and using the file |
| named for tha application when defining the |
| ``RMR_SEED_RT`` variable for applications which are to read |
| the table information. Obviously, all applications must be |
| running in the same container, on the same host, or have a |
| common disk volum between their environments. Known risks to |
| using table sharing include |
| |
| |
| * An update to the table (not a complete table) may be |
| received prior to one or more readers accessing the file, |
| and thus the reader may not receive a valid or complete |
| table. |
| |
| * Any entry which has a sender:port associated with the |
| message type will likely be ignored by all readers. |
| |
| |
| |
| Routing Using MEID |
| ================== |
| |
| Starting with version 1.13.0, RMR provides the ability to |
| select the endpoint for a message based on the MEID (managed |
| entity ID) in the message, rather than selecting the endpoint |
| from the round-robin list for the matching route table entry. |
| When the MEID is used, the message is sent to the endpoint |
| which *owns,* or is responsible for the managed entity. |
| Should the *owner* change messages will be routed to the new |
| owner when the route table is updated. To make use of MEID |
| routing, there must be one or more route table entries which |
| list the special endpoint name ``%meid`` instead of providing |
| a round robin list. As an example, consider the following |
| route table entry: |
| |
| |
| :: |
| |
| mse| 1000,forwarder:43086 | 10 | %meid |
| |
| Figure 4: Sample route entry with the meid flag. |
| |
| The final field of the entry doesn't specify a round-robin |
| group which means that when an application attempts to send a |
| message with type 1000, and the subscription ID of 10, the |
| MEID in the message will be used to select the endpoint. |
| |
| |
| MEID endpoint selection |
| ----------------------- |
| |
| To select an endpoint for the message based on the MEID in a |
| message, RMR must know which endpoint owns the MEID. This |
| information, known as an MEID map, is provided by the *Route |
| Manager* over the same communication path as the route table |
| is supplied. The following is the syntax for an MEID map. |
| |
| |
| :: |
| |
| meid_map | start | <table-id> |
| mme_ar | <owner-endpoint> | <meid> [<meid>...] |
| mme_del | <meid> [<meid>...] |
| meid_map | end | <count> [| <md5sum> ] |
| |
| Figure 5: Meid map table. |
| |
| The mme_ar records are add/update records and allow for the |
| list of MEIDs to be associated with (owned by) the indicated |
| endpoint. The <owner-endpoint> is the hostname:port, or IP |
| address and port, of the application which owns the MEID and |
| thus should receive any messages which are routed based on a |
| route table entry with %meid as the round-robin group. The |
| mme_del records allow for MEIDs to be deleted from RMR's |
| view. Finally, the <count> is the number of add/replace and |
| delete records which were sent; if RMR does not match the |
| <count> value to the number of records, then it will not add |
| the data to the table. Updates only need to list the |
| ownership changes that are necessary; in other words, the |
| *Route Manager* does not need to supply all of the MEID |
| relationships with each update. |
| |
| The optional <md5sum> field on the end record should be the |
| MD5 hash of all of the records between the start and end |
| records. This allows for a precise verification that the |
| transmitted data was correctly received. |
| |
| If a static seed file is being used for the route table, a |
| second section can be given which supplies the MEID map. The |
| following is a small example of a seed file: |
| |
| |
| :: |
| |
| newrt|start | id-64306 |
| mse|0|-1| %meid |
| mse|1|-1|172.19.0.2:4560 |
| mse|2|-1|172.19.0.2:4560 |
| mse|3|-1|172.19.0.2:4560 |
| mse|4|-1|172.19.0.2:4560 |
| mse|5|-1|172.19.0.2:4560 |
| newrt|end |
| |
| meid_map | start | id-028919 |
| mme_ar| 172.19.0.2:4560 | meid000 meid001 meid002 meid003 meid004 meid005 |
| mme_ar| 172.19.0.42:4560 | meid100 meid101 meid102 meid103 |
| mme_del | meid1000 |
| meid_map | end | 1 |
| |
| Figure 6: Illustration of both a route table and meid map in |
| the same file. |
| |
| The tables above will route all messages with a message type |
| of 0 based on the MEID. There are 10 meids which are owned by |
| two different endpoints. The table also deletes the MEID |
| meid1000 from RMR's view. |
| |
| |
| Reserved Message Types |
| ====================== |
| |
| RMR is currently reserving message types in the range of 0 |
| through 99 (inclusive) for its own use. Please do not use |
| these types in any production or test environment as the |
| results may be undesired. |
| |
| |
| |
| Appendix A -- Glossary |
| ====================== |
| |
| Many terms in networking can be interpreted with multiple |
| meanings, and several terms used in various RMR documentation |
| are RMR specific. The following definitions are the meanings |
| of terms used within RMR documentation and should help the |
| reader to understand the intent of meaning. |
| |
| .. list-table:: |
| :widths: 25,70 |
| :header-rows: 0 |
| :class: borderless |
| |
| * - **application** |
| - |
| A programme which uses RMR to send and/or receive messages |
| to/from another RMR based application. |
| |
| * - **Critical error** |
| - |
| An error that RMR has encountered which will prevent further |
| successful processing by RMR. Critical errors usually |
| indicate that the application should abort. |
| |
| * - **Endpoint** |
| - |
| An RMR based application that is defined as being capable of |
| receiving one or more types of messages (as defined by a |
| *routing key.*) |
| |
| * - **Environment variable** |
| - |
| A key/value pair which is set externally to the application, |
| but which is available to the application (and referenced |
| libraries) through the ``getenv`` system call. Environment |
| variables are the main method of communicating information |
| such as port numbers to RMR. |
| |
| * - **Error** |
| - |
| An abnormal condition that RMR has encountered, but will not |
| affect the overall processing by RMR, but may impact certain |
| aspects such as the ability to communicate with a specific |
| endpoint. Errors generally indicate that something, usually |
| external to RMR, must be addressed. |
| |
| * - **Host name** |
| - |
| The name of the host as returned by the ``gethostbyname`` |
| system call. In a containerised environment this might be the |
| container or service name depending on how the container is |
| started. From RMR's point of view, a host name can be used to |
| resolve an *endpoint* definition in a *route* table.) |
| |
| * - **IP** |
| - |
| Internet protocol. A low level transmission protocol which |
| governs the transmission of datagrams across network |
| boundaries. |
| |
| * - **Listen socket** |
| - |
| A *TCP* socket used to await incoming connection requests. |
| Listen sockets are defined by an interface and port number |
| combination where the port number is unique for the |
| interface. |
| |
| * - **Message** |
| - |
| A series of bytes transmitted from the application to another |
| RMR based application. A message is comprised of RMR specific |
| data (a header), and application data (a payload). |
| |
| * - **Message buffer** |
| - |
| A data structure used to describe a message which is to be |
| sent or has been received. The message buffer includes the |
| payload length, message type, message source, and other |
| information. |
| |
| * - **Message type** |
| - |
| A signed integer (0-32000) which identifies the type of |
| message being transmitted, and is one of the two components |
| of a *routing key.* See *Subscription ID.* |
| |
| * - **Payload** |
| - |
| The portion of a message which holds the user data to be |
| transmitted to the remote *endpoint.* The payload contents |
| are completely application defined. |
| |
| * - **RMR context** |
| - |
| A set of information which defines the current state of the |
| underlying transport connections that RMR is managing. The |
| application will be give a context reference (pointer) that |
| is supplied to most RMR functions as the first parameter. |
| |
| * - **Round robin** |
| - |
| The method of selecting an *endpoint* from a list such that |
| all *endpoints* are selected before starting at the head of |
| the list. |
| |
| * - **Route table** |
| - |
| A series of "rules" which define the possible *endpoints* for |
| each *routing key.* |
| |
| * - **Route table manager** |
| - |
| An application responsible for building a *route table* and |
| then distributing it to all applicable RMR based |
| applications. |
| |
| * - **Routing** |
| - |
| The process of selecting an *endpoint* which will be the |
| recipient of a message. |
| |
| * - **Routing key** |
| - |
| A combination of *message type* and *subscription ID* which |
| RMR uses to select the destination *endpoint* when sending a |
| message. |
| |
| * - **Source** |
| - |
| The sender of a message. |
| |
| * - **Subscription ID** |
| - |
| A signed integer value (0-32000) which identifies the |
| subscription characteristic of a message. It is used in |
| conjunction with the *message type* to determine the *routing |
| key.* |
| |
| * - **Target** |
| - |
| The *endpoint* selected to receive a message. |
| |
| * - **TCP** |
| - |
| Transmission Control Protocol. A connection based internet |
| protocol which provides for lossless packet transportation, |
| usually over IP. |
| |
| * - **Thread** |
| - |
| Also called a *process thread, or pthread.* This is a |
| lightweight process which executes in concurrently with the |
| application and shares the same address space. RMR uses |
| threads to manage asynchronous functions such as route table |
| updates. |
| |
| * - **Trace information** |
| - |
| An optional portion of the message buffer that the |
| application may populate with data that allows for tracing |
| the progress of the transaction or application activity |
| across components. RMR makes no use of this data. |
| |
| * - **Transaction ID** |
| - |
| A fixed number of bytes in the *message* buffer) which the |
| application may populate with information related to the |
| transaction. RMR makes use of the transaction ID for matching |
| response messages with the &c function is used to send a |
| message. |
| |
| * - **Transient failure** |
| - |
| An error state that is believed to be short lived and that |
| the operation, if retried by the application, might be |
| successful. C programmers will recognise this as |
| ``EAGAIN.`` |
| |
| * - **Warning** |
| - |
| A warning occurs when RMR has encountered something that it |
| believes isn't correct, but has a defined work round. |
| |
| * - **Wormhole** |
| - |
| A direct connection managed by RMR between the user |
| application and a remote, RMR based, application. |
| |
| |
| |