| // 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. |
| |
| //go:build !build_with_native_toolchain |
| // +build !build_with_native_toolchain |
| |
| package netdevice |
| |
| import ( |
| "fmt" |
| |
| "fidl/fuchsia/hardware/network" |
| ) |
| |
| // SessionConfigFactory creates session configurations from device information. |
| type SessionConfigFactory interface { |
| MakeSessionConfig(deviceInfo network.DeviceInfo) (SessionConfig, error) |
| } |
| |
| // SessionConfig holds configuration used to open a session with a network |
| // device. |
| type SessionConfig struct { |
| // Length of each buffer. |
| BufferLength uint32 |
| // Buffer stride on VMO. |
| BufferStride uint32 |
| // Descriptor length, in bytes. |
| DescriptorLength uint64 |
| // Tx header length, in bytes. |
| TxHeaderLength uint16 |
| // Tx tail length, in bytes. |
| TxTailLength uint16 |
| // Number of rx descriptors to allocate. |
| RxDescriptorCount uint16 |
| // Number of tx descriptors to allocate. |
| TxDescriptorCount uint16 |
| // Session flags. |
| Options network.SessionFlags |
| } |
| |
| // DefaultBufferLength is the buffer length used by SimpleSessionConfigFactory. |
| const DefaultBufferLength uint32 = 2048 |
| |
| // SimpleSessionConfigFactory is the default configuration factory. |
| type SimpleSessionConfigFactory struct{} |
| |
| // MakeSessionConfig implements SessionConfigFactory. |
| func (c *SimpleSessionConfigFactory) MakeSessionConfig(deviceInfo network.DeviceInfo) (SessionConfig, error) { |
| bufferLength := DefaultBufferLength |
| if deviceInfo.HasMaxBufferLength() && bufferLength > deviceInfo.MaxBufferLength { |
| bufferLength = deviceInfo.MaxBufferLength |
| } |
| if bufferLength < deviceInfo.MinRxBufferLength { |
| bufferLength = deviceInfo.MinRxBufferLength |
| } |
| |
| config := SessionConfig{ |
| BufferLength: bufferLength, |
| BufferStride: bufferLength, |
| DescriptorLength: descriptorLength, |
| TxHeaderLength: deviceInfo.MinTxBufferHead, |
| TxTailLength: deviceInfo.MinTxBufferTail, |
| RxDescriptorCount: deviceInfo.RxDepth, |
| TxDescriptorCount: deviceInfo.TxDepth, |
| Options: network.SessionFlagsPrimary, |
| } |
| align := deviceInfo.BufferAlignment |
| if config.BufferStride%align != 0 { |
| // Align up. |
| config.BufferStride += align - (config.BufferStride % align) |
| } |
| return config, nil |
| } |
| |
| type insufficientBufferLengthError struct { |
| bufferLength uint32 |
| bufferHeader uint16 |
| bufferTail uint16 |
| mtu uint32 |
| } |
| |
| func (e *insufficientBufferLengthError) Error() string { |
| return fmt.Sprintf("buffer=%d < header=%d + tail=%d + mtu=%d", e.bufferLength, e.bufferHeader, e.bufferTail, e.mtu) |
| } |
| |
| func (c *SessionConfig) checkValidityForPort(portStatus network.PortStatus) error { |
| mtu := portStatus.GetMtu() |
| if c.BufferLength < uint32(c.TxHeaderLength)+uint32(c.TxTailLength)+mtu { |
| return &insufficientBufferLengthError{ |
| bufferLength: c.BufferLength, |
| bufferHeader: c.TxHeaderLength, |
| bufferTail: c.TxTailLength, |
| mtu: mtu, |
| } |
| } |
| return nil |
| } |