| // Copyright 2020 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| library fuchsia.hardware.network; |
| |
| using zx; |
| |
| /// Represents a session with a Network device. |
| /// |
| /// A session has a data plane and a control plane. The `Session` protocol |
| /// represents the control plane of the session and the FIFOs and VMOs exchanged |
| /// during the [`Device.OpenSession`] call are the data plane. Lifetime of the |
| /// session is controlled by a `Session` protocol handle. |
| /// |
| /// Sessions must attach to ports of interest to start receiving and sending |
| /// data. Sessions are always created with no ports attached. |
| /// |
| /// If a port is destroyed from the underlying device, it is automatically |
| /// detached from the session. |
| /// |
| /// Inbound traffic is dispatched to all open sessions. Devices typically |
| /// operate with a single primary session, see [`SessionFlags.PRIMARY`]. Each |
| /// additional open session to the same device causes data copy overhead on the |
| /// device's data path. |
| /// |
| /// The session is closed with an error epitaph if an invalid buffer descriptor |
| /// is sent over either the tx or rx FIFOs. Invalid descriptors include: |
| /// - Descriptor index larger than [`SessionInfo.descriptor_count`]. |
| /// - Descriptor chains larger than [`MAX_DESCRIPTOR_CHAIN`]. |
| /// - rx buffers smaller than [`Info.min_rx_buffer_length`]. |
| /// - tx buffers smaller than [`Info.min_tx_buffer_length`]. |
| /// - tx buffers not respecting [`Info.min_tx_buffer_head`] or |
| /// [`Info.min_tx_buffer_tail`]. |
| @available(added=HEAD) |
| closed protocol Session { |
| /// Attaches the session to `port`. |
| /// |
| /// Once attached, the session starts to receive the subscribed frames over |
| /// the data FIFOs and it may send frames destined to the specified `port`. |
| /// |
| /// + request `port` port to subscribe to. |
| /// + request `rx_frames` Frame types of interest on the port. |
| /// * error `ZX_ERR_NOT_FOUND` if `port` is not valid. |
| /// * error `ZX_ERR_INVALID_ARGS` if `rx_frames` is not a subset of the |
| /// port's supported frames. |
| /// * error `ZX_ERR_ALREADY_BOUND` if `port` is already attached. |
| strict Attach(struct { |
| port PortId; |
| rx_frames vector<FrameType>:MAX_FRAME_TYPES; |
| }) -> () error zx.Status; |
| /// Detaches the session from `port`. |
| /// |
| /// Once detached, the session stops receiving frames from `port`. Frames |
| /// sent to a detached port may be returned with an error. It is not |
| /// necessary to call `Detach` on ports that are removed from the device, |
| /// doing so causes `ZX_ERR_NOT_FOUND` to be returned. |
| /// |
| /// + request `port` port to subscribe to. |
| /// * error `ZX_ERR_NOT_FOUND` if the session is not currently attached to |
| /// the port. |
| strict Detach(struct { |
| port PortId; |
| }) -> () error zx.Status; |
| /// Cleanly closes a session. |
| /// |
| /// This will cause the session to send a `ZX_ERR_CANCELLED` epitaph and |
| /// proceed to close the Session channel. Clients may only assume that they |
| /// own all the buffers that are currently owned by the session (sent over |
| /// either the rx or tx FIFOs) once the epitaph is received. Closing the rx |
| /// or tx FIFO is equivalent to calling `Close`. |
| strict Close(); |
| /// Watchers for delegated receive wakeup leases. |
| /// |
| /// Calls block until a lease is delegated by the device. If a call to |
| /// `WatchDelegatedRxLease` is made while a previous call is blocking, the |
| /// session is closed with `ZX_ERR_BAD_STATE`. Will never yield any values |
| /// for sessions created without [`SessionFlags.RECEIVE_RX_POWER_LEASES`]. |
| /// |
| /// Given a single lease is assumed sufficient to keep the system awake, the |
| /// server only keeps a single lease in its buffer. If a new delegated lease |
| /// becomes available and the client hasn't popped the previous one with a |
| /// call to `WatchDelegatedRxLease`, the server drops the previously pending |
| /// lease. |
| /// |
| /// See [`DelegatedRxLease`] for how to handle delegated leases. |
| strict WatchDelegatedRxLease() -> (resource struct { |
| lease DelegatedRxLease; |
| }); |
| }; |
| |
| /// Additional session options. |
| @available(added=HEAD) |
| type SessionFlags = strict bits : uint16 { |
| /// Attach as primary session. |
| /// |
| /// Sessions marked with the `PRIMARY` bit get the following different |
| /// treatment: |
| /// - If no PRIMARY sessions are attached, the device will *not* serve rx |
| /// frames to non-PRIMARY sessions. |
| /// - If there's only one PRIMARY session active, it may get a zero-copy |
| /// data path from the the backing hardware, if the underlying |
| /// implementation supports it. |
| PRIMARY = 0x0001; |
| /// Listen for outgoing frames. |
| /// |
| /// `LISTEN_TX` sessions receive any outgoing frames (from all sessions) on |
| /// its rx path. Can be used for snooping traffic. Sessions marked with |
| /// `LISTEN_TX` may also send frames, but they should keep in mind that |
| /// they'll ALWAYS receive those frames back on their rx path (no origin |
| /// session filtering is performed). |
| LISTEN_TX = 0x0002; |
| /// Receive invalid rx frames. |
| /// |
| /// Sessions marked with `REPORT_INVALID_RX` are interested in receiving |
| /// frames that were rejected by internal device checks or payload |
| /// validation performed by hardware. Due to the nature of some hardware |
| /// platforms, sessions marked with `REPORT_INVALID_RX` may still not |
| /// receive frames that fail validation if the hardware implementation |
| /// simply drops the frame and doesn't expose it to the software stack. |
| /// Sessions NOT marked with `REPORT_INVALID_RX`, in contrast, will NEVER |
| /// receive an rx frame with the `RX_VALIDATION_ERROR` flag set. |
| REPORT_INVALID_RX = 0x0004; |
| /// Receive rx power leases. |
| /// |
| /// Sessions marked with `RECEIVE_RX_POWER_LEASES` receive |
| /// [`DelegatedRxLease`]s through [`Session.WatchDelegatedRxLease`] calls. |
| RECEIVE_RX_POWER_LEASES = 0x0008; |
| }; |
| |
| /// Data-plane FIFOs. |
| @available(added=HEAD) |
| type Fifos = resource struct { |
| /// Handle for the rx FIFO. |
| /// |
| /// Clients must write 16-bit descriptor indexes to this FIFO to be able to |
| /// receive frames. |
| rx zx.Handle:FIFO; |
| /// Handle for the tx FIFO. |
| /// |
| /// Clients write 16-bit descriptor indexes to this FIFO to enqueue outgoing |
| /// frames. |
| tx zx.Handle:FIFO; |
| }; |
| |
| /// Session configuration. |
| @available(added=HEAD) |
| type SessionInfo = resource table { |
| /// VMO containing the descriptors. Required. |
| /// |
| /// 16-bit indices transmitted over the FIFOs index a descriptor in this VMO |
| /// (byte offset = descriptor_length * 8 * index). |
| 1: descriptors zx.Handle:VMO; |
| /// VMO containing frame data. Required. |
| /// |
| /// Descriptors contain byte-offsets that are used to index arbitrary |
| /// regions in `data`. |
| 2: data zx.Handle:VMO; |
| /// Requested descriptor version. Required. |
| /// |
| /// If the network device does not support the requested descriptor version, |
| /// [`Device.OpenSession`] fails with `ZX_ERR_NOT_SUPPORTED`. |
| 3: descriptor_version uint8; |
| /// Descriptor length, in 64-bit words. Required. |
| /// |
| /// The length of each descriptor in the `descriptors` VMO. This is used as |
| /// a multiplier to find byte offsets in `descriptors` given a descriptor |
| /// index passed through the rx or tx FIFOs. |
| 4: descriptor_length uint8; |
| /// Total number of descriptors that can be used by this session. Required. |
| /// |
| /// Descriptor indices transferred through either the rx or tx FIFO must be |
| /// in the range [0, `descriptor_count`). |
| 5: descriptor_count uint16; |
| /// Extra options. Interpreted as empty bitmask if absent. |
| 6: options SessionFlags; |
| }; |
| |
| /// An acquired lease that is propagated up to applications. |
| @available(added=HEAD) |
| type DelegatedRxLease = resource table { |
| /// The frame after which the lease in `handle` can be released. |
| /// |
| /// Agents observing leases must keep track of received frames with an |
| /// increasing counter to be able to properly relinquish leases after the |
| /// frame `hold_until_frame` is fully processed. |
| /// |
| /// This value can be interpreted as either the 1-based index of a given |
| /// frame or as the total number of exchanged frames so far, which are |
| /// mathematically equivalent. |
| /// |
| /// This mechanism allows for wake lease handles from received frames to be |
| /// passed up and keep the system from suspension until the frame is fully |
| /// processed. |
| /// |
| /// Required. |
| 1: hold_until_frame uint64; |
| /// A handle representing the held lease. |
| /// |
| /// Required. |
| // NOTE: Lease handles are flexible to accomodate for PF evolution on lease |
| // representations. |
| 2: handle @generated_name("DelegatedRxLeaseHandle") flexible resource union { |
| /// An untyped channel representing a lease. |
| /// |
| /// Close the channel to release the lease. |
| 1: channel zx.Handle:CHANNEL; |
| }; |
| }; |