The TRex RPC Server
===================
:author: Itay Marom
:email: <imarom@cisco.com>
:revnumber: 1.70-0.0
:quotes.++:
:numbered:
:web_server_url: http://trex-tgn.cisco.com/trex
:local_web_server_url: csi-wiki-01:8181/trex



== RPC Support On TRex

TRex implements a RPC protocol in order to config, view and
in general execute remote calls on TRex

In this document we will provide information on
how a client can implement the protocol used to communicate with TRex

In general, we will describe the following:

* *Transport Layer* - The transport layer used to communicate with TRex server
* *RPC Reprensentation Protocol* - The format in which remote procedures are carried

=== Transport Layer

TRex server transport layer is implemented using ZMQ.

The default configuration is TCP on port 5555, however this is configurable.

{zwsp} +
The communication model is based on the request-reply ZMQ model:

http://zguide.zeromq.org/page:all#Ask-and-Ye-Shall-Receive

{zwsp} +

for more on ZMQ and implementation please refer to:
{zwsp} +
http://zeromq.org/intro:read-the-manual

=== RPC Reprensentation Protocol

The RPC reprensentation protocol is JSON RPC v2.0.
Every request and response will be encoded in a JSON RPC v2.0 format.

{zwsp} +

For more info on JSON RPC v2.0 spec please refer to:
{zwsp} +

http://www.jsonrpc.org/specification

{zwsp} +

Later on in the document we will describe all the supported commands.

=== TRex RPC Mock Server
Before we get into the commands, it's worth mentioning that TRex has a mock RPC server
designed to allow playing around with the server in order to understand the response
and perform adjustments to the request.

TRex also provides a Python based console that can connect to the server (mock or real) and
send various commands to the server.

==== Building The Mock Server
Building the mock server is performed like this:
[source,bash]
----
trex-core/linux>  ./b configure
trex-core/linux>  ./b --target=mock-rpc-server-64-debug
----

==== Running The Mock Server
Launching the mock server is performed like this:

[source,bash]
----
 
trex-core/scripts> ./mock-rpc-server-64-debug

-= Starting RPC Server Mock =-

Listening on tcp://localhost:5050 [ZMQ]

Setting Server To Full Verbose

Server Started

----

==== Using The TRex Console To Interact
When the mock server is up, you can already send commands to the server.
{zwsp} +
{zwsp} +

Let's demonstrate the operation with the Python based TRex console:

{zwsp} +

[source,bash]
----
trex-core/scripts> ./trex-console

Connecting To RPC Server On tcp://localhost:5050
[SUCCESS]


-=TRex Console V1.0=-

Type 'help' or '?' for supported actions

TRex >

----
As we will see later on, a basic RPC command supported by the server is 'ping'.
{zwsp} +
Let's issue a ping command to the server and see what happens on both sides:

{zwsp} +
{zwsp} +

On the 'client' side:

[source,bash]
----
TRex > verbose on

verbose set to on

TRex > ping

-> Pinging RPC server
[verbose] Sending Request To Server:

{
    "id": "l0tog11a",
    "jsonrpc": "2.0",
    "method": "ping",
    "params": {}
}

[verbose] Server Response:

{
    "id": "l0tog11a",
    "jsonrpc": "2.0",
    "result": "ACK"
}

[SUCCESS]

----
On the 'server' side:

[source,bash]
----

trex-core/scripts> ./mock-rpc-server-64-debug

-= Starting RPC Server Mock =-

Listening on tcp://localhost:5050 [ZMQ]

Setting Server To Full Verbose

Server Started


[verbose][req resp] Server Received:

{
   "id" : "maa5a3g1",
   "jsonrpc" : "2.0",
   "method" : "ping",
   "params" : {}
}

[verbose][req resp] Server Replied:

{
   "id" : "maa5a3g1",
   "jsonrpc" : "2.0",
   "result" : "ACK"
}

----

== RPC Commands
The following RPC commands are supported

=== Ping
* *Name* - 'ping'
* *Description* - Pings the TRex server
* *Paramters* - None
* *Result* - "ACK" On Sucess

Example:

[source,bash]
----
'Request':

{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "ping",
    "params": null
}

'Response':

{
   "jsonrpc" : "2.0",
   "id" : 1,
   "result" : "ACK"
}

----

=== Get Registered Commands
* *Name* - 'get_reg_cmds'
* *Description* - Queries the server for all the registered commands
* *Paramters* - None
* *Result* - A list of all the supported commands by the server

Example:

[source,bash]
----
'Request':

{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "get_reg_cmds",
    "params": null
}


'Response':

{
    "jsonrpc": "2.0",
    "id": 1,
    "result": [
        "remove_all_streams",
        "remove_stream",
        "add_stream",
        "get_reg_cmds",
        "ping",
        "test_sub",
        "get_status",
        "test_add"
    ]
}

----


=== Get Status
* *Name* - 'get_status'
* *Description* - Queries the server for general information
e.g.: user owning the device, number of ports configured
* *Paramters* - None
* *Result* - An object of all the supported commands by the server.

+++<u>Result Details:</u>+++

'general.version' - TRex version.

'general.build_date' - build date.

'general.build_time' - build time.

'general.built_by'   - who built this version

'general.uptime' - uptime of the server

'general.owner' - user currently owning the device or 'none' if no one has taken ownership.

{zwsp} +
'ports.count' - number of ports available on the server.

=== Add Stream
* *Name* - 'add_stream'
* *Description* - Adds a stream to a port
* *Paramters* 
** *port_id* - port id associated with this stream
** *stream_id* - stream id associated with the stream object
** *stream* - object of type xref:stream_obj['stream']
* *Result* - ACK in case of success

==== Object type 'stream' anchor:stream_obj[]

Add_stream gets a single parameter of type object.

The format of that object is as follows:

.Object type 'stream' 
[options="header",cols="1,1,3"]
|=================
| Field       | Type    | Description 
| enabled     | boolean | is this stream enabled
| self_start  | boolean | is this stream triggered by starting injection or triggered by another stream
| isg         | double  | ['usec'] inter stream gap - delay time in usec until the stream is started
| next_stream | int     | next stream to start after this stream. -1 means stop after this stream
| packet      | object  | object of type xref:packet_obj['packet']
| mode        | object  | object of type xref:mode_obj['mode']
| vm          | object  | object of type xref:vm_obj['vm']
| rx_stats    | object  | object of type xref:rx_stats_obj['rx_stats']
|=================

===== Object type 'packet' anchor:packet_obj[]
packet contains binary and meta data

.Object type 'packet'
[options="header",cols="1,1,3"]
|=================
| Field       | Type        | Description
| binary      | byte array  | binary dump of the packet to be used in the stream as array of bytes
| meta        | string      | meta data object. opaque to the RPC server. will be passed on queries
|=================

===== Object type 'mode' anchor:mode_obj[]
mode object can be 'one' of the following objects:

.Object type 'mode - continuous' 
[options="header",cols="1,1,3"]
|=================
| Field       | Type        | Description
| type        | string      | ''continuous''
| pps         | int         | rate in packets per second 
|=================

.Object type 'mode - single_burst' 
[options="header",cols="1,1,3"]
|=================
| Field         | Type        | Description
| type          | string      | ''single_burst''
| pps           | int         | rate in packets per second 
| total pkts    | int         | total packets in the burst
|=================

.Object type 'mode - multi_burst' 
[options="header",cols="1,1,3"]
|=================
| Field          | Type        | Description
| type           | string      | ''multi_burst''
| pps            | int         | rate in packets per second 
| pkts_per_burst | int         | packets in a single burst
| ibg            | double      | ['usec'] inter burst gap. delay between bursts in usec
| count          | int         | number of bursts. ''0'' means loop forever, ''1'' will fall back to single burst
|=================

===== Object type 'vm' anchor:vm_obj[]
Describes the VM instructions to be used with this stream

.Object type 'vm'
[options="header",cols="1,1,3"]
|=================
| Field       | Type        | Description
|=================

===== Object type 'rx_stats' anchor:rx_stats_obj[]
Describes rx stats for the stream

.Object type 'rx_stats'
[options="header",cols="1,1,3"]
|=================
| Field            | Type        | Description
| enabled          | boolean     | is rx_stats enabled for this stream
| rx_stream_id     | int         | 
| seq_enabled      | boolean     | should write 32 bit sequence
| latency_enabled  | boolean     | should write 32 bit latency
|=================

[source,bash]
----

'Request':

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "add_stream",
    "params": {
        "port_id": 1,
	"stream_id": 502
        "stream": {
            "enabled": true,
            "isg": 4.3,
            "mode": {
                "pps": 3,
                "total_pkts": 5000,
                "type": "single_burst"
            },
            "next_stream_id": -1,
            "packet": {
                "binary": [
                    4,
                    1,
                    255
                ],
                "meta": ""
            },
            "rx_stats": {
                "enabled": false
            },
            "self_start": true,
        }
    }
}

'Response':

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": "ACK"
}


----


=== Remove Stream
* *Name* - 'remove_stream'
* *Description* - Removes a stream from a port
* *Paramters*
** *port_id* - port assosicated with the stream.
** *stream_id* - stream to remove

* *Result* - ACK in case of success

[source,bash]
----

'Request':

{
    "id": 1
    "jsonrpc": "2.0",
    "method": "remove_stream",
    "params": {
        "port_id": 1,
        "stream_id": 502
    }
}


'Response':

{
    "id": 1
    "jsonrpc": "2.0",
    "result": "ACK"
}

----

=== Get Stream ID List
* *Name* - 'get_stream_list'
* *Description* - fetch all the assoicated streams for a port
* *Paramters*
** *port_id* - port to query for registered streams

* *Result* - array of 'stream_id'

[source,bash]
----

'Request':

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "get_stream_list",
    "params": {
        "port_id": 1
    }
}

'Response':

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": [
        502,
        18
    ]
}


----