Supported P4Runtime RPCs

To support the use cases described in Overview, SR Linux supports the following P4Runtime RPCs:

  • StreamChannel RPC

    Allows for session management, client arbitration, and packet injection/extraction. See StreamChannel RPC for information about how SR Linux handles StreamChannel RPC messages.

  • Write RPC

    Injects rules to select packets to extract to the slow path.

  • Read RPC

    Provides uniformity with the Write RPC; that is, it gives the controller the ability to query which rules have been programmed.

  • SetForwardingPipelineConfig RPC

    Used for pushing a P4 program from a P4Runtime controller to a target SR Linux device. The P4 program must be the same program that is distributed with SR Linux.

  • GetForwardingPipelineConfig RPC

    Used for reading out the P4 forwarding pipeline configuration.

  • Capabilities RPC

    Allows a P4Runtime client to discover the capabilities of a target device, including the P4Runtime API version implemented by the SR Linux p4rt_server process.

StreamChannel RPC

The P4Runtime StreamChannel RPC is used for session management, arbitration, and packet I/O. It has the following definition:

rpc StreamChannel(stream StreamMessageRequest) returns (stream StreamMessageResponse)

The StreamChannel RPC has two top-level messages, StreamMessageRequest and StreamMessageResponse.

The following is an example of the StreamMessageRequest message.

message StreamMessageRequest {
    oneof update {
        MasterArbitrationUpdate arbitration = 1;
        PacketOut packet = 2;
        DigestListAck digest_ack = 3;
        .google.protobuf.Any other = 4;
    }
}
The SR Linux p4rt_server process uses fields in the StreamMessageRequest messages as follows:
  • MasterArbitrationUpdate

    P4Runtime clients send StreamMessageRequest messages to the p4rt_server on the SR Linux to perform arbitration via MasterArbitrationUpdate messages. See P4Runtime client arbitration.

  • PacketOut

    The P4Runtime client selected as primary transmits packets via PacketOut messages. See PacketIn and PacketOut messages.

  • The DigestListAck and .google.proto.Any messages within the digest_ack and other fields are not supported by SR Linux.

The following is an example of the StreamMessageResponse message:

message StreamMessageResponse {
    oneof update {
        MasterArbitrationUpdate arbitration = 1;
        PacketIn packet = 2;
        DigestList digest = 3;
        IdleTimeoutNotification idle_timeout_notification = 4;
        .google.protobuf.Any other = 5;
        // Used by the server to asynchronously report errors which occur when
        // processing StreamMessageRequest messages.
        StreamError error = 6;
    }
}
The SR Linux p4rt_server process uses fields in the StreamMessageResponse messages as follows:
  • MasterArbitrationUpdate

    The p4rt_server sends a StreamMessageResponse message to a P4Runtime client to respond to an arbitration request via a MasterArbitrationUpdate message. See P4Runtime client arbitration

  • PacketIn

    The p4rt_server transmits packets to the primary P4Runtime client via PacketIn messages. See PacketIn and PacketOut messages.

  • StreamError

    The p4rt_server transmits StreamError message within the error field based on any errors occurring. See Stream Error Reporting.

  • The DigestList, IdleTimeoutNotification, .google.proto.Any messages within the digest, idle_timeout_notification, and other fields are not are not supported by SR Linux.

P4Runtime client arbitration

P4Runtime client arbitration refers to the process by which a single P4Runtime controller becomes the "primary", with any other controllers serving as backups. Only one P4Runtime controller can be the primary. On SR Linux, P4Runtime arbitration works as described in the P4 Runtime specification: the primary is elected based on the election_id within the MasterArbitrationUpdate message in the StreamChannel RPC.

The MasterArbitrationUpdate message is defined as follows:
message MasterArbitrationUpdate {
    uint64 device_id = 1;
    // The role for which the primary client is being arbitrated. For use-cases
    // where multiple roles are not needed, the controller can leave this unset,
    // implying default role and full pipeline access.
    Role role = 2;
    // The stream RPC with the highest election_id is the primary. The 'primary'
    // controller instance populates this with its latest election_id. Switch
    // populates with the highest election ID it has received from all connected
    // controllers.
    Uint128 election_id = 3;
    // Switch populates this with OK for the client that is the primary, and
    // with an error status for all other connected clients (at every primary
    // client change). The controller does not populate this field.
    .google.rpc.Status status = 4;
}
 
message Role {
    // Uniquely identifies this role.
    string name = 3;
    // Describes the role configuration, i.e. what operations, P4 entities,
    // behaviors, etc. are in the scope of a given role. If config is not set
    // (default case), it implies all P4 objects and control behaviors are in
    // scope, i.e. full pipeline access. The format of this message is
    // out-of-scope of P4Runtime.
    .google.protobuf.Any config = 2;
}

Only the primary controller is allowed to send PacketOut messages and receive PacketIn messages for a specific ASIC.

In the event a controller with the highest election_id disconnects, the controller with the next-highest election_id is automatically used as the new primary, resulting in PacketIn messages being forwarded to the new primary, and p4rt_server only accepting PacketOut from the new primary. If a controller does not specify an election_id, it is considered to be the lowest election_id and never becomes the primary.

PacketIn and PacketOut messages

PacketIn messages are sent by p4rt_server to the P4Runtime client within StreamMessageResponse messages, and PacketOut messages are sent by the P4Runtime client to p4rt_server within StreamMessageRequest messages.

An ACL pushed to the device via the Write RPC is used to mark/extract packets for PacketIn handling by the p4rt_server.

PacketIn and PacketOut messages are defined as follows:
// Packet sent from the controller to the switch.
message PacketOut {
    bytes payload = 1;
    // This will be based on P4 header annotated as
    // @controller_header("packet_out").
    // At most one P4 header can have this annotation.
    repeated PacketMetadata metadata = 2;
}
 
// Packet sent from the switch to the controller.
message PacketIn {
    bytes payload = 1;
    // This will be based on P4 header annotated as
    // @controller_header("packet_in").
    // At most one P4 header can have this annotation.
    repeated PacketMetadata metadata = 2;
}
 
message PacketMetadata {
    // This refers to Metadata.id coming from P4Info ControllerPacketMetadata.
    uint32 metadata_id = 1;
    bytes value = 2;
}

The PacketIn and PacketOut messages require that the interface a packet is received on or transmitted out of be uniquely identified. To do this, unique identifiers are configured for SR Linux interfaces. See Identifying interfaces to P4Runtime.