Getting Started: gRPC API¶
The gRPC API is how test infrastructure (DVaaS, sonic-pins) integrates with 4ward programmatically. Two services are exposed on the same port:
- P4Runtime — the standard P4Runtime gRPC API for pipeline management, table entries, and PacketIO.
- DataplaneService — 4ward-specific API for packet injection with trace trees.
Start the server¶
The server listens on port 9559 by default. Override with --port:
Typical workflow¶
1. Load a pipeline¶
Compile your P4 program, then load it via SetForwardingPipelineConfig:
SetForwardingPipelineConfigRequest {
device_id: 1
action: VERIFY_AND_COMMIT
config {
p4info: <from compiled output>
p4_device_config: <from compiled output>
}
}
2. Install table entries¶
Use Write to install entries. The request follows the standard P4Runtime
spec:
WriteRequest {
device_id: 1
updates {
type: INSERT
entity {
table_entry {
table_id: <from p4info>
match { field_id: 1 exact { value: "\x08\x00" } }
action { action { action_id: <from p4info> params { ... } } }
}
}
}
}
3. Inject a packet¶
Use the DataplaneService InjectPacket RPC:
The response contains possible outcomes (output packet sets) and a full trace tree:
InjectPacketResponse {
possible_outcomes { packets { dataplane_egress_port: 1 payload: <...> } }
trace { events { ... } packet_outcome { ... } }
}
4. Inject many packets (bulk / DVaaS)¶
For high throughput, use the streaming InjectPackets RPC with
SubscribeResults:
- Open a
SubscribeResultsstream. - Wait for the
active {}confirmation — this guarantees the subscription is registered and no results will be missed. - Send all packets via
InjectPackets(client-streaming). - Collect results from the subscription.
Packets process concurrently across available cores. This is the recommended pattern for DVaaS and any workload with many test packets.
// SubscribeResults delivers results from ALL sources.
SubscribeResultsResponse { active {} }
SubscribeResultsResponse { result { input_packet { ... } possible_outcomes { ... } trace { ... } } }
Tip
InjectPacket (singular) returns the result inline — simpler for
one-off debugging. InjectPackets (plural) processes concurrently
but results come via SubscribeResults.
Matching results to packets
Each result includes the full input packet (port + payload). With concurrent processing, results may arrive out of order — match by payload content, not position. See the reference for details on PacketIn interaction.
Dual port encoding¶
When the pipeline uses
@p4runtime_translation on port types,
both representations appear in responses:
OutputPacket {
dataplane_egress_port: 0 // raw port number
p4rt_egress_port: "Ethernet1" // P4Runtime name
}
You can also inject packets using P4Runtime port names:
What's next¶
- Reference — complete gRPC API reference with all RPCs, message types, and error codes.
- Type translation — how
@p4runtime_translationtypes flow through the API. - Trace trees — understanding the trace tree in the response.