Driver Interface
This document describes the interface between user space applications and the Terragraph driver and firmware.
Architecture
The E2E minion is responsible for communicating with the Terragraph driver and
firmware via its DriverApp
thread. DriverApp
uses a ZMQ pair socket
(ZMQ_PAIR
) to send and receive messages with the driver interface
(driver-if
). driver-if
then communicates with the Terragraph driver over a
Netlink socket.
Implementation
Normally, driver-if
runs as another thread on the E2E minion process (spawned
by the Minion
main class). driver-if
can run also in daemon mode without
DriverApp
or other E2E minion modules by passing the --driver_if_only
flag.
A dedicated ZmqMonitor
instance is also spawned in a separate thread for
pushing driver and firmware stats (refer to
Stats, Events, Logs for further details).
driver-if
is a subclass of BaseDriverIf
, and holds a corresponding Netlink
socket subclass of BaseNetlinkSocket
. The subclasses are based on the
machine's architecture, listed in the table below. Note that the x86 classes
are intended for emulation only and are largely incomplete.
Architecture | BaseDriverIf | BaseNetlinkSocket |
---|---|---|
ARM | ArmDriverIf | ArmNetlinkSocket |
x86 | X86DriverIf | X86NetlinkSocket |
Message Handling
Upon receiving a message from the Netlink socket, driver-if
does the
following:
- Convert the Netlink message to a
DriverNlMessage
instance using theArmNetlinkSocket::recvFunc_()
callback. - Convert the
DriverNlMessage
to the correspondingthrift::Message
structure usingDriverIfUtil::driverNl2IfMessage()
. - Filter out and handle specific messages, including:
DR_RESP
- log driver acknowledgementsFW_STATS
,DR_STAT_PUSH
- publish stats from the firmware or driver toZmqMonitor
FW_HEALTHY
- write firmware health status for the watchdogFW_PPS_HTSF_INFO
- HTSF timing information
- Forward remaining messages through the pair socket using
BaseDriverIf::sendToDriverApp()
.
Upon receiving a message from the pair socket, driver-if
does the following:
- Handle the
thrift::Message
by invoking the corresponding function withinBaseDriverIf::processMessage()
. - Convert the
thrift::Message
structure to aDriverNlMessage
instance, then send it to the driver as a Netlink message usingArmNetlinkSocket::sendMessage()
.
driver-if
publishes the following stats related to Netlink I/O:
tgd.nl.recv_ok
- number of Netlink messages received successfullytgd.nl.recv_err
- number of Netlink messages received unsuccessfully
Features
Some other notable features of driver-if
are described below.
Firmware Codebook Management
The firmware downloads codebooks (tables of antenna weights) from driver-if
via FW_GET_CODEBOOK
requests (thrift::CodebookFetchReq
), which specify a
channel and range of beams. In order to respond with the correct codebook,
driver-if
maintains state learned from the NODE_INIT
and NODE_INIT_NOTIFY
message sequence for each radio, and captures relevant information (i.e. vendor,
initial beamforming procedure type, codebook variant) using the
ArmDriverIf::RadioProperties
struct. driver-if
will load codebooks on demand
and cache them for the lifecycle of the process.
GPS Management
driver-if
contains an optional feature (enabled via the node configuration
flag envParams.GPSD_ENABLED
) to connect to a local gpsd socket (on port
2947). When enabled, BaseDriverIf
creates a separate thread to read events
from gpsd using the GpsdClient
class, which does the following:
- Forwards all received timestamps to each firmware instance via
GPS_SEND_TIME
once per second (only iftimingParams.PPS_TIMESTAMP_SOURCE
is set to "GPS" in the node configuration). - Pushes GPS stats via
DR_STAT_PUSH
. - Forwards received location data to each firmware instance via
GPS_SET_POS_REQ
once only.
For more details, see Timing and Synchronization.
PPS Timestamp Forwarding
More generally, driver-if
can forward 1PPS timestamps to Terragraph firmware
from the following sources (timingParams.PPS_TIMESTAMP_SOURCE
in the node
configuration) to enable GPS/PPS sync mode:
- GPS, via
GpsdClient
(as described above). - PTP hardware clock, via
PTPClockHelper
. This utilizes a separate thread to read EXTTS events from a PTP device (timingParams.PTP_DEVICE
) using theioctl
commandPTP_EXTTS_REQUEST
. - Software HTSF messages from Terragraph firmware, via
BaseDriverIf
. On multi-radio nodes with a common PPS signal to all baseband sectors, the software HTSF PPS timestamps received from one RF sync sector are sent to the other sectors to enable PPS sync mode. When multiple sectors are publishing HTSF timestamps,driver-if
picks the "source" sector based on the first message received, and will not switch to a different source sector untiltimingParams.HTSF_MAX_LOOP_SIZE * 13
seconds have elapsed in order to avoid timing loops in the network; this delay is based on the number of missed seconds (PPS timestamps) before firmware will transition from PPS to RF sync (or bring down a link). Alternatively, the source sector can be hardcoded via the node configuration fieldtimingParams.HTSF_SRC_MAC
.
driver-if
publishes the following stats to help monitor the state of timestamp
forwarding:
tgd.gpsStat.MAC.numTsSent
- number of GPS timestamps forwarded toMAC
(only valid iftimingParams.PPS_TIMESTAMP_SOURCE
is set to "GPS")tgd.ptp.MAC.numTsSent
- number of PTP hardware clock timestamps forwarded toMAC
tgd.htsf.MAC.numTsSent
- number of software HTSF timestamps forwarded toMAC
PTP Hardware Clock Sync
driver-if
can be configured to synchronize a node's PTP (Precision Time
Protocol) hardware clock based on 1PPS messages from a given timing reference
(timingParams.PTP_TIMER_SOURCE
in the node configuration) by correcting for
phase offset and drift. The PTP clock is synchronized to GPS time (not UTC).
Possible timing sources include a GPS device and software/hardware HTSF messages
from Terragraph firmware.
Currently, the following clock types are supported:
- NXP DPAA2 (Data Path Acceleration Architecture Gen2) PTP clock, via direct register access.
- VSC 10G "Malibu" PHY LTC (local time counter) clock, via a custom datagram
socket protocol patched over the user-space "MESA" API. This can be enabled
by setting the node configuration field
envParams.PTP_VSC_CTRL_SOCKET
to any valid path, which will be used for communication betweene2e_minion
andmalibu_char
.
Performance Requirements
driver-if
must be able to process messages in a timely manner, and major
issues may emerge here if the host CPU is overloaded. Some common examples are
described below.
PPS timestamp forwarding. On PPS sync nodes,
driver-if
must reliably send timestamps to Terragraph firmware once per second, and 10 missed seconds may cause a link to go down.- Signs:
LINK_DOWN
events with reasonSYSTEM_GPS_SYNC_IN_PROG
; incrementing countertgf.MAC.gps.numMissedSec
(despite stable GPS fix, if applicable) - Workarounds: Increase scheduling priority of gpsd (if applicable) or
driver-if
, e.g. using thenice
command
- Signs:
Netlink communication.
driver-if
must receive northbound messages from Terragraph firmware faster than they are produced to avoid dropping any Netlink messages.- Signs: Netlink errors reported by
driver-if
and Terragraph driver (ex.ENOBUFS
), esp. as number of wireless links increases; incrementing countertgd.nl.recv_err
- Workarounds: Reduce firmware stats frequency
(
radioParamsBase.fwParams.statsLogInterval
); omit some firmware stats categories (radioParamsBase.fwStatsConfig.<category> = false
)
- Signs: Netlink errors reported by
Message Formats
driver-if
handles the translation between Thrift messages (user space) and
Netlink messages (driver).
Netlink
Netlink types are enumerated in tgd_nlsdn_commands
, defined inside
nl-driver-if/fb_tgd_nlsdn_common.h
. These are manually mapped to
DriverNlMessageType
enum values inside driver-if/DriverNlMessage.h
.
Thrift
All Thrift messages to and from the driver use the same thrift::DriverMessage
base structure defined in DriverMessage.thrift
:
struct DriverMessage {
1: binary value;
2: string radioMac;
}
value
contains the compact-serialized binary value of the actual Thrift
structure, and radioMac
is the origin or destination baseband MAC address
required for multi-baseband boards.
Note that this structure must be wrapped inside of a thrift::Message
structure, like with all other messages (refer to
Communication Protocol for further details). Thus,
the actual message type is double-serialized, and the mType
field in the outer
structure describes the message type of the actual message (i.e. innermost
structure).
Messages directly between driver-if
and firmware use the pass-through
(PassThru
) framework, with messages defined in PassThru.thrift
. The base
message type is thrift::PassThruMsg
, with all possible messages embedded as
nested structures and a separate message type field, msgType
, enumerated in
thrift::PtMsgTypes
. When sending pass-through messages over Netlink, the
DriverNlMessageType
type for southbound messages (i.e. towards firmware) is
PASSTHRU_SB
and the type for northbound messages (i.e. towards driver-if
) is
PASSTHRU_NB
.
Command-Line Interfaces
When run in daemon mode, interaction with driver-if
is typically done via CLI
applications, described below.
"r2d2" CLI
r2d2
is a Python-based command-line utility solely for communicating with
driver-if
and its ZmqMonitor
instance. This is mainly used for debugging and
automated testing purposes. For further implementation details, refer to
descriptions of the tg
CLI, which has a similar architecture (see
"tg" CLI).
"tg2" CLI
The majority of r2d2
functionality is also provided as part of the Lua-based
tg2
CLI. Commands and syntax are nearly identical, although there may be minor
differences between argument/option names, program output, description text,
etc. A table mapping r2d2
commands to tg2
commands is given below:
r2d2 command | tg2 command |
---|---|
r2d2 * | tg2 fw * |
r2d2 fw_stats | tg2 stats driver-if |
r2d2 fw_set_golay r2d2 sync_bf_slot_exclusion_req r2d2 sync_scan | unsupported |
Resources
- gpsd - GPS service daemon