qsfp_service
qsfp_service manages the pluggable transceivers (QSFP, OSFP, and similar, using the SFF and CMIS management interfaces) and the external PHYs (retimers, gearboxes) of a switch. The agent programs the ASIC side of each port; qsfp_service brings up the optic and any PHY in between, collects digital optical monitoring (DOM) data, handles insertion and removal, remediates stuck modules, and can upgrade module firmware. This page covers how it identifies the platform, its configuration, flags, state machines, how it works with the agent, and its tests.
Where It Fits
fboss_sw_agent / hw agent <--- Thrift ---> qsfp_service (5910) ---> transceivers (I2C via BSP)
| ---> external PHYs (PHY SAI / PAI)
+--> FSDB (state + stats)
- The agent tells
qsfp_servicewhich ports are enabled and at what profile;qsfp_serviceconfigures the matching transceiver (and PHY) and reports transceiver state back. wedge_qsfp_utilandfboss2 show transceiverare clients of its Thrift API (QsfpService, port 5910). See Diagnostic Tools.- On platforms with external PHYs,
qsfp_serviceis linked against the PHY vendor's SAI SDK (Broadcom PAI), built as a separate pass. See Building FBOSS.
Platform Identification
qsfp_service needs two mappings for the platform it runs on:
- Platform mapping: the ports, their lanes, and transceiver IDs. For
qsfp_servicethe relevant parts are the number of ports and transceivers. - BSP platform mapping: the device paths used to control each transceiver (presence, reset, I2C data access) and, for
led_service, the LEDs. It is derived from the platform'splatform_manager.json, and the paths are the/run/devmap/xcvrs/nodes PlatformManager creates.
Both are described in Platform Support. The platform type comes from /var/facebook/fboss/fruid.json (the --fruid_filepath flag). It can be overridden with the --mode flag, typically through defaultCommandLineArgs in the QSFP config, for platforms whose fruid.json is not reliable. For tests, --platform_mapping_override_path and --bsp_platform_mapping_override_path replace the built-in mappings.
Configuration: qsfp.conf
qsfp_service reads /etc/coop/qsfp.conf (--qsfp_config). --qsfp_config_current (/etc/coop/qsfp/current) is a deprecated older location. The file is the JSON form of QsfpServiceConfig in fboss/qsfp_service/if/qsfp_service_config.thrift:
| Key | Meaning |
|---|---|
defaultCommandLineArgs |
Flag defaults, applied the same way as the agent's |
transceiverConfigOverrides |
Per-transceiver setting overrides (for example by module type or speed) |
sdk_version |
QSFP/PHY SDK version information |
qsfpTestConfig |
Settings used by QSFP hardware tests |
transceiverFirmwareVersions |
Expected firmware versions per module, used by firmware upgrade |
transceiverI2cLogging |
I2C transaction logging settings |
transceiverValidationConfig |
Vendor/part combinations considered valid (with --enable_tcvr_validation) |
tunableOpticsConfig |
Optical channel configuration for tunable optics |
phyConfig |
External PHY configuration |
thriftApiToRateLimitInQps |
Per-API Thrift rate limits |
Test configs for many platforms are in fboss/oss/qsfp_test_configs/ and are packaged into /opt/fboss/share/qsfp_test_configs/.
Flags
| Flag | Default | Meaning |
|---|---|---|
--port |
5910 |
Thrift port (--migrated_port, default 5960, is the planned replacement) |
--qsfp_config |
/etc/coop/qsfp.conf |
Config file |
--qsfp_service_volatile_dir |
/dev/shm/fboss/qsfp_service |
Where the cold boot flag is stored |
--loop_interval |
5 |
Seconds between runs of the main loop that refreshes transceivers and drives the state machines |
--stats_publish_interval |
60 |
Seconds between stats publications |
--xphy_stats_loop_interval |
10 |
Seconds between external PHY stats updates |
--can_qsfp_service_warm_boot |
true |
Allow warm boot of qsfp_service |
--port_manager_mode |
false |
Let a PortManager object own all port-level logic, leaving TransceiverManager with transceiver-level logic only |
--firmware_upgrade_supported |
false |
Enable module firmware upgrade support |
--firmware_upgrade_on_coldboot, --firmware_upgrade_on_tcvr_insert |
false |
Upgrade firmware automatically on cold boot, or when a module is inserted |
--max_concurrent_evb_fw_upgrade |
1 |
Transceivers sharing one EVB that may upgrade at a time |
--firmware_upgrade_time_limit |
1080 |
Seconds before an upgrade counts as slow (an fb303 counter is incremented) |
--enable_tcvr_validation |
false |
Validate transceivers against transceiverValidationConfig |
--transceiver_properties_config |
Path to a transceiver_properties.json file |
|
--state_machine_update_thread_heartbeat_ms |
20000 |
Heartbeat for the state machine update threads |
--qsfp_enable_thrift_acceptor, --qsfp_trusted_subnets |
false, empty |
Only accept Thrift connections from loopback and the listed CIDR subnets |
--qsfp_thrift_rate_limit_shadow_mode |
true |
Rate limiting only logs and counts |
The MACsec-related flags (--sak_list_warmboot_config default /var/facebook/fboss/mka_service/sak_lists/, --sak_config_validity_in_secs default 3600) store SAK configuration across restarts for the MKA service.
How It Works
qsfp_service keeps a state machine per transceiver (TransceiverStateMachine) and, in port manager mode, per port (PortStateMachine). Every --loop_interval seconds the main loop:
- refreshes presence and data for all transceivers (in parallel across slots, using per-slot threads),
- advances each state machine: detect a newly present module, read its EEPROM, discover its type, program it for the port's profile, and mark it ready (or remediate it if it is stuck),
- updates the ports known from the agent, and
- publishes state, and periodically stats, to FSDB and fb303.
The repository's tests under fboss/qsfp_service/test/ (for example TransceiverStateMachineTest, PortStateMachineTest) document the exact transitions.
Warm boot: on a warm restart qsfp_service keeps modules programmed instead of resetting them. The cold boot flag in --qsfp_service_volatile_dir forces the next start to be a cold boot.
Running It
qsfp_service --qsfp_config /etc/coop/qsfp.conf
or as the qsfp_service systemd unit. run_test.py services start qsfp --qsfp-config <file> starts it with a test config (see Running Tests).
Tests
| Binary | What it tests | Hardware |
|---|---|---|
qsfp_hw_test |
qsfp_service features on real modules (run_test.py qsfp) |
Switch with optics |
qsfp_hal_test |
The transceiver hardware abstraction layer | Switch |
qsfp_hw_test_benchmark |
Transceiver refresh and programming speed (run_test.py benchmark --qsfp) |
Switch |
cmis_test, transceiver_manager_test, transceiver_state_machine_test |
Unit tests | None |
The T0 QSFP suite is share/hw_sanity_tests/t0_qsfp_hw_tests.conf; platforms without transceivers use t0_qsfp_hw_tests_without_transceivers.conf. Known-bad lists are keyed by <platform>/<phy_sdk> style keys. See Test Suites.
Adding a New Optic
The upstream guide is candid that adding support for a new optic is "not straightforward" yet. In practice it means extending the SFF or CMIS module code in fboss/qsfp_service/module/, adding any per-module overrides to transceiverConfigOverrides, and passing the QSFP hardware and link tests. The transceiver onboarding document in the repo describes Meta's process.