blob: 8493805e20211a4ba6dd7eac2cfccb8f988842ff [file] [log] [blame]
// 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
}