+.. 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.
+
+
+space 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 will establish 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.
+
+
+Providing A Static Table
+========================
+
+For testing, or possibly bootstrapping purposes, a static
+route table can be supplied. During initialisation, RMR will
+check the ``RMR_SEED_RT`` environment variable. If it exists,
+and references a file, RMR will open and read the file
+expecting to find a static route table. This route table is
+used until an update is received from a *Route Manager*.
+Normally, when the RMR initialisation function is invoked, a
+listener is started to receive route table information from a
+route manager process. During testing it is often useful to
+supply a static table which is available should no route
+management process exist, or to provide a seed table to use
+before the first table is delivered. The environment variable
+``RMR_SEED_RT`` can be set to provide the RMR initialisation
+function with the name of the static table to use. If a
+static table is provided, it will be loaded only once, and
+will be overlaid if a dynamically delivered table is
+received.
+
+
+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
+ *message 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.
+
+ * - **Messgae 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 *message 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. &Term 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.
+
+
+