ZMQAPI Protocol
The ZMQAPI protocol is used by yangcli-gw to communicate with client application programs.
Warning
The ZMQAPI Protocol definition is still preliminary and may change in the future.
ZMQAPI Roles
There are three operational roles supported in the protocol. Actual implementations may combine or somehow split these roles.
ZMQAPI Server Role
The yangcli-gw program is a ZMQAPI server. A ZMQAPI server has the following tasks:
It listens for commands from client applications.
It initiates and maintains network management sessions with managed devices on behalf of client applications
It sends notification messages to client applications
ZMQAPI Client Role
Your application program is a ZMQAPI client. A ZMQAPI client has the following tasks:
It connects to yangcli-gw as needed
It sends command requests to yangcli-gw
It listens for command responses from yangcli-gw
ZMQAPI Collector Role
Your application program is a ZMQAPI collector. It can be co-located with the ZMQAPI client role. Notification delivery usually needs to be configured first using the client role.
A ZMQAPI collector has the following tasks:
It listens for notifications from yangcli-gw
ZMQAPI Message Types
All ZMQAPI messages are ZeroMQ Multipart Messages. There are three message types defined:
Client Request Message (REQ):
Used to access the asynchronous command channel
Sent from the application to yangcli-gw
Requests may be serialized by yangcli-gw
Message definition: ZMQAPI REQ Message
Server Response Message (REP):
Sent by yangcli-gw to a client application after a client request message has been received
ZMQAPI header contains a simple command status field
Message definition: ZMQAPI REP Message
Payload section will depend on the return status
ok: The payload will be text
error: The payload format and contents will depend on the error information available to yangcli-gw
data: The payload format requested by the client application will be used for the returned data
Server Notification Message (PUB):
Sent by yangcli-gw when some event occurs that requires that the client application be notified of the event.
Must be setup using the <establish-subscription> operation or other mechanisms in order to receive NETCONF notifications.
There are three types of server notifications:
gw: Control messages from yangcli-gw
stream: Event stream subscription notification from a NETCONF server
data: YANG Push Datastore subscription notification from a NETCONF server
ZMQAPI Message Encoding
ZMQAPI uses a flexible message encoding scheme:
Messages are encoded as ZeroMQ MultiPart Messages.
Each part of the message represents a different 'layer' in the message.
The first header (the ZMQAPI Message Header) is encoded in UTF-8 text
Other headers such as the ZMQAPI SESSION Header are encoded in JSON
The ZMQAPI Response Format for the response payload must be specified in each request message
Refer to the ZMQAPI Response Format Examples section for an example of each response format
ZMQAPI Message Header
All ZMQAPI messages begin with a ZMQAPI Header.
Text format
Contains one line
Text fields are separated by one space ' ' character
Separator character between fields must be one space character.
Max Header Size: 4095 bytes
ZeroMQ message parts do not contain trailing zero bytes
The receive buffer must be 4096 bytes including one byte for a terminating zero byte.
ZMQAPI Header Fields
Header Field |
Description |
Protocol ID |
Text string representing the protocol version. |
Message ID |
Text code representing the ZMQAPI message type. |
Response Format |
Text code representing the payload format. Usage depends on the Message ID |
Message Specific |
Usage depends on the Message ID |
Example Header
ZMQAPI.1 REQ R2 client1 edb5debc-1dc7-11ee-be86-e9f635d13331
Protocol ID:
ZMQAPI.1
Message ID:
REQ
Response Format:
R2
Message Specific:
client1 edb5debc-1dc7-11ee-be86-e9f635d13331
ZMQAPI Protocol ID
This is always the first field in the ZMQAPI message header.
It contains the string ZMQAPI
, followed by a period character (.),
followed by the protocol version number.
The current protocol version is '1'
The string
ZMQAPI.1
must be used for this protocol versionThis field must be followed by one space ' ' character
ZMQAPI Message ID
This is always the second field in the ZMQAPI message header. It contains a 3 character string representing the ZMQAPI message type. The following values are defined in ZMQAPI.1:
REQ
: ZMQAPI REQ Message (client request)REP
: ZMQAPI REP Message (yangcli-gw response)PUB
: ZMQAPI PUB Message (yangcli-gw notification)
This field must be followed by one space ' ' character.
ZMQAPI Response Format
This is always the third field in the ZMQAPI message header. It contains a 2 character string representing the ZMQAPI payload encoding format.
In a
REQ
header this is the requested format for the response payload in theREP
message from the serverIn a
REP
orPUB
header this is the actual format of the payload in the message.
The response format consists of the letter 'R', followed by the numeric ID for the encoding format
The following values are defined in ZMQAPI.1:
R0
: No payload. In this mode only headers will be sent and no payload portions will follow.This value will not be used in a
PUB
message.It can be used in a
REQ
message by a client to suppress the actual payload response.It will be used in a
REP
message by yangcli-gw if no payload is included in the response.
R1
: Plain text payload. The default yangcli-pro display format will be used in the payload section.R2
: Plain JSON payload. The payload will be encoded in JSON without any module prefixes.R3
: IETF JSON payload. The payload will be encoded in JSON with module prefixes, as defined in RFC 7951.R4
: XML payload. The payload will be encoded in XML 1.0 format.
This field must be followed by one space ' ' character, only if there are any more fields in the ZMQAPI header for the specific message.
ZMQAPI Response Format Examples
This example shows the same data retrieval response payload in each of the four formats.
The request used in this example:
> sget /interfaces-state
Example: R1 Response Format (Plain)
rpc-reply {
{
interfaces-state {
interface lo {
name lo
type ianaift:softwareLoopback
admin-status up
oper-status up
if-index 1
phys-address 00:00:00:00:00:00
speed 0
statistics {
in-octets 12617816
in-unicast-pkts 109261
in-multicast-pkts 0
in-discards 0
in-errors 0
out-octets 12617816
out-unicast-pkts 109261
out-discards 0
out-errors 0
}
}
interface eno1 {
name eno1
type ianaift:ethernetCsmacd
admin-status up
oper-status up
if-index 2
phys-address 3c:7c:3f:1d:83:aa
speed 1000000000
statistics {
in-octets 8435787307
in-unicast-pkts 9992246
in-multicast-pkts 808894
in-discards 177033
in-errors 0
out-octets 19278785748
out-unicast-pkts 14440784
out-discards 0
out-errors 0
}
}
interface virbr0 {
name virbr0
type ianaift:ethernetCsmacd
admin-status up
oper-status down
if-index 3
phys-address 52:54:00:7e:68:35
speed 0
statistics {
in-octets 0
in-unicast-pkts 0
in-multicast-pkts 0
in-discards 0
in-errors 0
out-octets 0
out-unicast-pkts 0
out-discards 0
out-errors 0
}
}
}
}
}
Example: R2 Response Format (JSON)
{
"rpc-reply": {
"data": {
"interfaces-state": {
"interface": [
{
"name":"lo",
"type":"iana-if-type:softwareLoopback",
"admin-status":"up",
"oper-status":"up",
"if-index":1,
"phys-address":"00:00:00:00:00:00",
"speed":"0",
"statistics": {
"in-octets":"12627651",
"in-unicast-pkts":"109334",
"in-multicast-pkts":"0",
"in-discards":0,
"in-errors":0,
"out-octets":"12627651",
"out-unicast-pkts":"109334",
"out-discards":0,
"out-errors":0
}
},
{
"name":"eno1",
"type":"iana-if-type:ethernetCsmacd",
"admin-status":"up",
"oper-status":"up",
"if-index":2,
"phys-address":"3c:7c:3f:1d:83:aa",
"speed":"1000000000",
"statistics": {
"in-octets":"8444440799",
"in-unicast-pkts":"10001057",
"in-multicast-pkts":"809479",
"in-discards":177125,
"in-errors":0,
"out-octets":"19306372099",
"out-unicast-pkts":"14460132",
"out-discards":0,
"out-errors":0
}
},
{
"name":"virbr0",
"type":"iana-if-type:ethernetCsmacd",
"admin-status":"up",
"oper-status":"down",
"if-index":3,
"phys-address":"52:54:00:7e:68:35",
"speed":"0",
"statistics": {
"in-octets":"0",
"in-unicast-pkts":"0",
"in-multicast-pkts":"0",
"in-discards":0,
"in-errors":0,
"out-octets":"0",
"out-unicast-pkts":"0",
"out-discards":0,
"out-errors":0
}
}
]
}
}
}
}
Example: R3 Response Format (IETF-JSON)
{
"ietf-netconf:rpc-reply": {
"ietf-netconf:data": {
"ietf-interfaces:interfaces-state": {
"interface": [
{
"name":"lo",
"type":"iana-if-type:softwareLoopback",
"admin-status":"up",
"oper-status":"up",
"if-index":1,
"phys-address":"00:00:00:00:00:00",
"speed":"0",
"statistics": {
"in-octets":"12639445",
"in-unicast-pkts":"109414",
"in-multicast-pkts":"0",
"in-discards":0,
"in-errors":0,
"out-octets":"12639445",
"out-unicast-pkts":"109414",
"out-discards":0,
"out-errors":0
}
},
{
"name":"eno1",
"type":"iana-if-type:ethernetCsmacd",
"admin-status":"up",
"oper-status":"up",
"if-index":2,
"phys-address":"3c:7c:3f:1d:83:aa",
"speed":"1000000000",
"statistics": {
"in-octets":"8444701815",
"in-unicast-pkts":"10002184",
"in-multicast-pkts":"809818",
"in-discards":177231,
"in-errors":0,
"out-octets":"19306453840",
"out-unicast-pkts":"14460456",
"out-discards":0,
"out-errors":0
}
},
{
"name":"virbr0",
"type":"iana-if-type:ethernetCsmacd",
"admin-status":"up",
"oper-status":"down",
"if-index":3,
"phys-address":"52:54:00:7e:68:35",
"speed":"0",
"statistics": {
"in-octets":"0",
"in-unicast-pkts":"0",
"in-multicast-pkts":"0",
"in-discards":0,
"in-errors":0,
"out-octets":"0",
"out-unicast-pkts":"0",
"out-discards":0,
"out-errors":0
}
}
]
}
}
}
}
Example: R4 Response Format (XML)
<?xml version="1.0" encoding="UTF-8"?>
<rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
<data>
<interfaces-state xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces">
<interface>
<name>lo</name>
<type xmlns:ianaift="urn:ietf:params:xml:ns:yang:iana-if-type">ianaift:softwareLoopback</type>
<admin-status>up</admin-status>
<oper-status>up</oper-status>
<if-index>1</if-index>
<phys-address>00:00:00:00:00:00</phys-address>
<speed>0</speed>
<statistics>
<in-octets>12698433</in-octets>
<in-unicast-pkts>109946</in-unicast-pkts>
<in-multicast-pkts>0</in-multicast-pkts>
<in-discards>0</in-discards>
<in-errors>0</in-errors>
<out-octets>12698433</out-octets>
<out-unicast-pkts>109946</out-unicast-pkts>
<out-discards>0</out-discards>
<out-errors>0</out-errors>
</statistics>
</interface>
<interface>
<name>eno1</name>
<type xmlns:ianaift="urn:ietf:params:xml:ns:yang:iana-if-type">ianaift:ethernetCsmacd</type>
<admin-status>up</admin-status>
<oper-status>up</oper-status>
<if-index>2</if-index>
<phys-address>3c:7c:3f:1d:83:aa</phys-address>
<speed>1000000000</speed>
<statistics>
<in-octets>8462476977</in-octets>
<in-unicast-pkts>10020558</in-unicast-pkts>
<in-multicast-pkts>811254</in-multicast-pkts>
<in-discards>177452</in-discards>
<in-errors>0</in-errors>
<out-octets>19334939852</out-octets>
<out-unicast-pkts>14483261</out-unicast-pkts>
<out-discards>0</out-discards>
<out-errors>0</out-errors>
</statistics>
</interface>
<interface>
<name>virbr0</name>
<type xmlns:ianaift="urn:ietf:params:xml:ns:yang:iana-if-type">ianaift:ethernetCsmacd</type>
<admin-status>up</admin-status>
<oper-status>down</oper-status>
<if-index>3</if-index>
<phys-address>52:54:00:7e:68:35</phys-address>
<speed>0</speed>
<statistics>
<in-octets>0</in-octets>
<in-unicast-pkts>0</in-unicast-pkts>
<in-multicast-pkts>0</in-multicast-pkts>
<in-discards>0</in-discards>
<in-errors>0</in-errors>
<out-octets>0</out-octets>
<out-unicast-pkts>0</out-unicast-pkts>
<out-discards>0</out-discards>
<out-errors>0</out-errors>
</statistics>
</interface>
</interfaces-state>
</data>
</rpc-reply>
ZMQAPI Message Specific Parts
The format of the remaining parts of the ZMQAPI header depends on the message type.
[fill in with links to the specific message parts]
ZMQAPI SESSION Header
The SESSION header is a simple JSON object containing information about the current session. It is sent by yangcli-gw in server response (REP) and server notification (PUB) messages.
JSON format
Contains one line
Max Header Size: 4095 bytes
ZeroMQ message parts do not contain trailing zero bytes
The receive buffer must be 4096 bytes including one byte for a terminating zero byte.
SESSION Header Fields
Header Field |
Description |
count |
Current connected session count. |
sid |
Session ID or zero if not connected. |
name |
Session name or |
server |
Server address or empty string if not connected. |
port |
Server port or empty string if not connected. |
user |
User name or empty string if not connected. |
SESSION Header YANG
The YANG module yumaworks-zmqapi.yang contains the 'session-hdr' grouping, which defines the contents of this header.
grouping session-hdr {
description
"Represents the 'session' header contents sent in
all ZMQAPI.1 'REP' and 'PUB' messages.";
leaf count {
type uint32;
description
"Number of sessions currently active in the
yangcli-gw server.";
}
leaf sid {
type uint32;
description
"Session ID of the current session or 0 if
current session is not connected.";
}
leaf name {
type yang:yang-identifier;
description
"Session name of the current session.
This will be set to the value 'default' unless
named sessions are used.";
}
leaf server {
type string;
description
"Address of the server for the current session.
If the 'sid' is set to zero then this value
will be an empty string.";
}
leaf port {
type uint16;
description
"TCP port number of the server for the current session.
If the 'sid' is set to zero then this value will be zero.";
}
leaf user {
type string;
description
"User name string used for the current session.
If the 'sid' is set to zero then this value
will be an empty string.";
}
}
SESSION Header Examples
Example SESSION Header If No Session Connected
{"count":0,"sid":0,"name":"default","server":"","port":0,"user":""}
Example SESSION Header If Default Session Connected to Localhost
{"count":1,"sid":1,"name":"default","server":"localhost","port":830,"user":"andy"}
ZMQAPI EVENT Header
The EVENT header is a simple JSON object containing information about the event reported in a ZMQAPI PUB Message.
JSON format
Contains one line
Max Header Size: 4095 bytes
ZeroMQ message parts do not contain trailing zero bytes
The receive buffer must be 4096 bytes including one byte for a terminating zero byte.
EVENT Header Fields
Header Field |
Description |
type |
Event Type enumeration |
time |
event timestamp (e.g. eventTime) |
observer |
Observer ID (or 0 if none reported) |
module |
YANG module name containing event definition |
revision |
YANG module revision containing event definition |
name |
event identifier |
path |
YANG path to notification (/ for top-level) |
EVENT Header YANG
The YANG module yumaworks-zmqapi.yang contains the 'event-hdr' grouping, which defines the contents of this header.
grouping event-hdr {
description
"Represents the 'event' header sent in ZMQAPI.1
PUB messages.";
leaf type {
type enumeration {
enum gw {
description
"The event is from yangcli-gw, not a managed server";
}
enum stream {
description
"The event is from an event stream subscription.";
}
enum data {
description
"The event is from a datastore subscription.";
}
}
description
"The type of event that is contained in the event
payload section of the PUB message.";
}
leaf time {
type yang:date-and-time;
description
"The eventTime reported by the server or the
current time for a 'gw' event type.";
}
leaf observer {
type uint32;
description
"The observer identifier for the event source.
The value '0' is used for 'gw' and 'stream'
message types. It is possible the observer
identifier will be set for a 'data' event type.";
}
leaf module {
type yang:yang-identifier;
description
"The YANG module name containing the event
definition for the event payload portion
of the message.
Note that the module name for the top-level
element in a YANG 1.1 notification may not
be the same as the notification.";
}
leaf revision {
type string;
description
"The revision date for the 'module' leaf.
This is an empty string if no revision string
is available.";
}
leaf name {
type yang:yang-identifier;
description
"The event name for this PUB message.";
}
leaf path {
type string;
description
"The datastore path to the event.
The string format is a RESTCONF instance-identifier
as defined in RFC 7951.
- For 'gw' type events this will always be the root.
- For 'stream' and 'data' type events:
- this will be the root for top-level events.
- this will be the path to the parent of the nested
notification for YANG 1.1 nested notifications or
schema-mounted notifications.
";
}
}
EVENT Header Examples
TBD