mirror of
https://github.com/soypat/lneto.git
synced 2026-08-29 10:59:03 +00:00
ethernet: MTU semantic meaning corrections, add FCS logic (#28)
This commit is contained in:
@@ -0,0 +1,47 @@
|
|||||||
|
package ethernet
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"hash/crc32"
|
||||||
|
)
|
||||||
|
|
||||||
|
//
|
||||||
|
// CRC API.
|
||||||
|
//
|
||||||
|
|
||||||
|
// crcTable is the IEEE CRC-32 table used for Ethernet FCS calculation.
|
||||||
|
var crcTable = crc32.MakeTable(crc32.IEEE)
|
||||||
|
|
||||||
|
// CRC32 calculates the Ethernet Frame Check Sequence (FCS) for the given data.
|
||||||
|
// The CRC is computed using the IEEE 802.3 CRC-32 polynomial.
|
||||||
|
// The input should be the frame data from destination MAC through payload,
|
||||||
|
// excluding any existing FCS.
|
||||||
|
func CRC32(data []byte) uint32 {
|
||||||
|
return crc32.Checksum(data, crcTable)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CRC32Search searches for a valid CRC32 in data starting from minOffCRC.
|
||||||
|
// It computes the CRC incrementally from minOffCRC, checking at each position
|
||||||
|
// if the CRC matches the next 4 bytes (little-endian FCS).
|
||||||
|
// Returns the offset where a valid CRC was found, or -1 if no valid CRC exists.
|
||||||
|
// This is useful when the exact frame length is unknown but bounded by minOffCRC.
|
||||||
|
func CRC32Search(data []byte, minOffCRC int) (foundOffOrNegative int) {
|
||||||
|
if minOffCRC < 0 {
|
||||||
|
minOffCRC = 0
|
||||||
|
}
|
||||||
|
if len(data) < minOffCRC+4 {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
// Calculate CRC up to minOffCRC
|
||||||
|
crc := crc32.Checksum(data[:minOffCRC], crcTable)
|
||||||
|
// Incrementally extend and check at each position
|
||||||
|
for off := minOffCRC; off <= len(data)-4; off++ {
|
||||||
|
got := binary.LittleEndian.Uint32(data[off:])
|
||||||
|
if crc == got {
|
||||||
|
return off
|
||||||
|
}
|
||||||
|
// Extend CRC by one byte for next iteration
|
||||||
|
crc = crc32.Update(crc, crcTable, data[off:off+1])
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
package ethernet
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestCRC32Search(t *testing.T) {
|
||||||
|
// Helper to create test data with CRC appended at a specific position.
|
||||||
|
makeDataWithCRC := func(payloadLen int) []byte {
|
||||||
|
data := make([]byte, payloadLen+4)
|
||||||
|
for i := range data[:payloadLen] {
|
||||||
|
data[i] = byte(i)
|
||||||
|
}
|
||||||
|
crc := CRC32(data[:payloadLen])
|
||||||
|
binary.LittleEndian.PutUint32(data[payloadLen:], crc)
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Run("finds CRC at end", func(t *testing.T) {
|
||||||
|
data := makeDataWithCRC(100)
|
||||||
|
off := CRC32Search(data, 0)
|
||||||
|
if off != 100 {
|
||||||
|
t.Errorf("expected offset 100, got %d", off)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("finds CRC with minOff before CRC", func(t *testing.T) {
|
||||||
|
data := makeDataWithCRC(100)
|
||||||
|
off := CRC32Search(data, 50)
|
||||||
|
if off != 100 {
|
||||||
|
t.Errorf("expected offset 100, got %d", off)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("finds CRC with minOff exactly at CRC", func(t *testing.T) {
|
||||||
|
data := makeDataWithCRC(100)
|
||||||
|
off := CRC32Search(data, 100)
|
||||||
|
if off != 100 {
|
||||||
|
t.Errorf("expected offset 100, got %d", off)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("returns -1 when minOff past CRC", func(t *testing.T) {
|
||||||
|
data := makeDataWithCRC(100)
|
||||||
|
off := CRC32Search(data, 101)
|
||||||
|
if off != -1 {
|
||||||
|
t.Errorf("expected -1, got %d", off)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("returns -1 when no valid CRC", func(t *testing.T) {
|
||||||
|
data := make([]byte, 100)
|
||||||
|
for i := range data {
|
||||||
|
data[i] = byte(i)
|
||||||
|
}
|
||||||
|
off := CRC32Search(data, 0)
|
||||||
|
if off != -1 {
|
||||||
|
t.Errorf("expected -1, got %d", off)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("returns -1 when data too short", func(t *testing.T) {
|
||||||
|
data := []byte{1, 2, 3}
|
||||||
|
off := CRC32Search(data, 0)
|
||||||
|
if off != -1 {
|
||||||
|
t.Errorf("expected -1, got %d", off)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("handles negative minOff", func(t *testing.T) {
|
||||||
|
data := makeDataWithCRC(20)
|
||||||
|
off := CRC32Search(data, -5)
|
||||||
|
if off != 20 {
|
||||||
|
t.Errorf("expected offset 20, got %d", off)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("finds CRC at position 0", func(t *testing.T) {
|
||||||
|
// Empty payload, just CRC
|
||||||
|
data := make([]byte, 4)
|
||||||
|
crc := CRC32(nil)
|
||||||
|
binary.LittleEndian.PutUint32(data, crc)
|
||||||
|
off := CRC32Search(data, 0)
|
||||||
|
if off != 0 {
|
||||||
|
t.Errorf("expected offset 0, got %d", off)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("finds first valid CRC when multiple could match", func(t *testing.T) {
|
||||||
|
// Create data where CRC is at position 50
|
||||||
|
data := makeDataWithCRC(50)
|
||||||
|
// Extend with more bytes (the search should still find first match)
|
||||||
|
data = append(data, make([]byte, 50)...)
|
||||||
|
off := CRC32Search(data, 0)
|
||||||
|
if off != 50 {
|
||||||
|
t.Errorf("expected offset 50 (first match), got %d", off)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -5,6 +5,12 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
// MaxOverheadSize is the maximum overhead a packet can incur
|
||||||
|
// from transmitting an ethernet frame. Includes:
|
||||||
|
// - 14 bytes of Ethernet header containing MAC addresses and ethernet type, always present
|
||||||
|
// - 4 bytes of VLAN tag, if present.
|
||||||
|
// - 4 bytes of the 32 bit trailing CRC, if required by PHY.
|
||||||
|
MaxOverheadSize = 14 + 4 + 4
|
||||||
sizeHeaderNoVLAN = 14
|
sizeHeaderNoVLAN = 14
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ import (
|
|||||||
"net/url"
|
"net/url"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/soypat/lneto/ethernet"
|
||||||
)
|
)
|
||||||
|
|
||||||
const minMTU = 256
|
const minMTU = 256
|
||||||
@@ -58,7 +60,7 @@ func (h *HTTPTapClient) IPMask() (netip.Prefix, error) {
|
|||||||
|
|
||||||
func (h *HTTPTapClient) MTU() (int, error) {
|
func (h *HTTPTapClient) MTU() (int, error) {
|
||||||
err := h.ensureMTU()
|
err := h.ensureMTU()
|
||||||
return len(h.buf), err
|
return len(h.buf) - ethernet.MaxOverheadSize, err // Return payload MTU, not buffer size
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *HTTPTapClient) HardwareAddress6() ([6]byte, error) {
|
func (h *HTTPTapClient) HardwareAddress6() ([6]byte, error) {
|
||||||
@@ -85,7 +87,7 @@ func (h *HTTPTapClient) ensureMTU() (err error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
h.buf = make([]byte, info.MTU)
|
h.buf = make([]byte, info.MTU+ethernet.MaxOverheadSize)
|
||||||
hw, err := net.ParseMAC(info.HardwareAddr)
|
hw, err := net.ParseMAC(info.HardwareAddr)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
copy(h.hwaddr[:], hw)
|
copy(h.hwaddr[:], hw)
|
||||||
@@ -215,7 +217,7 @@ func NewHTTPTapServer(iface Interface, minMTU, queueOut, queueIn int) (*HTTPTapS
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
bufferSize := max(mtu, minMTU)
|
bufferSize := max(mtu, minMTU) + ethernet.MaxOverheadSize
|
||||||
netmask, err := iface.IPMask()
|
netmask, err := iface.IPMask()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
+63
-10
@@ -1,6 +1,7 @@
|
|||||||
package internet
|
package internet
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
@@ -11,12 +12,35 @@ import (
|
|||||||
"github.com/soypat/lneto/ethernet"
|
"github.com/soypat/lneto/ethernet"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// StackEthernetConfig contains configuration parameters for [StackEthernet].
|
||||||
|
type StackEthernetConfig struct {
|
||||||
|
// MTU is the Maximum Transmission Unit, representing the maximum ethernet
|
||||||
|
// payload size in bytes (excluding the 14-byte ethernet header).
|
||||||
|
// Standard ethernet MTU is 1500. Must be between 256 and 65535.
|
||||||
|
MTU int
|
||||||
|
// MaxNodes is the maximum number of protocol handlers (e.g., IP, ARP)
|
||||||
|
// that can be registered with the stack. Must be greater than 0.
|
||||||
|
MaxNodes int
|
||||||
|
// MAC is the local hardware (MAC) address for this ethernet interface.
|
||||||
|
MAC [6]byte
|
||||||
|
// Gateway is the hardware (MAC) address of the default gateway.
|
||||||
|
// Outgoing frames will be addressed to this MAC.
|
||||||
|
Gateway [6]byte
|
||||||
|
// AppendCRC32, if true, appends a 32-bit CRC to outgoing frames.
|
||||||
|
// Only needed if the PHY does not handle CRC generation.
|
||||||
|
AppendCRC32 bool
|
||||||
|
// CRC32Update is a IEEE CRC32 implementation that should be provided if AppendCRC32 is set.
|
||||||
|
CRC32Update func(crc uint32, p []byte) uint32
|
||||||
|
}
|
||||||
|
|
||||||
type StackEthernet struct {
|
type StackEthernet struct {
|
||||||
connID uint64
|
connID uint64
|
||||||
handlers handlers
|
handlers handlers
|
||||||
mac [6]byte
|
mac [6]byte
|
||||||
gwmac [6]byte
|
gwmac [6]byte
|
||||||
mtu uint16
|
mtu uint16
|
||||||
|
// crcupdate set when crc32 has been configured to be appended.
|
||||||
|
crcupdate func(crc uint32, p []byte) uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ls *StackEthernet) SetGateway6(gw [6]byte) {
|
func (ls *StackEthernet) SetGateway6(gw [6]byte) {
|
||||||
@@ -35,19 +59,39 @@ func (ls *StackEthernet) HardwareAddr6() [6]byte {
|
|||||||
return ls.mac
|
return ls.mac
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reset6 resets the stack with the given parameters.
|
||||||
|
//
|
||||||
|
// Deprecated: Use [StackEthernet.Configure] instead.
|
||||||
func (ls *StackEthernet) Reset6(mac, gateway [6]byte, mtu, maxNodes int) error {
|
func (ls *StackEthernet) Reset6(mac, gateway [6]byte, mtu, maxNodes int) error {
|
||||||
if mtu > math.MaxUint16 || mtu < 256 {
|
return ls.Configure(StackEthernetConfig{
|
||||||
|
MTU: mtu,
|
||||||
|
MaxNodes: maxNodes,
|
||||||
|
MAC: mac,
|
||||||
|
Gateway: gateway,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configure resets and configures the ethernet stack with the given configuration.
|
||||||
|
// It validates the configuration parameters and resets internal state.
|
||||||
|
// The connection ID is incremented on each call to invalidate existing connections.
|
||||||
|
func (ls *StackEthernet) Configure(cfg StackEthernetConfig) error {
|
||||||
|
if cfg.MTU > (math.MaxUint16-ethernet.MaxOverheadSize) || cfg.MTU < 256 {
|
||||||
return errors.New("invalid MTU")
|
return errors.New("invalid MTU")
|
||||||
} else if maxNodes <= 0 {
|
} else if cfg.MaxNodes <= 0 {
|
||||||
return errZeroMaxNodesArg
|
return errZeroMaxNodesArg
|
||||||
|
} else if cfg.AppendCRC32 && cfg.CRC32Update == nil {
|
||||||
|
return errors.New("need CRC32Update to append ethernet CRC")
|
||||||
}
|
}
|
||||||
ls.handlers.reset("StackEthernet", maxNodes)
|
ls.handlers.reset("StackEthernet", cfg.MaxNodes)
|
||||||
*ls = StackEthernet{
|
*ls = StackEthernet{
|
||||||
connID: ls.connID + 1,
|
connID: ls.connID + 1,
|
||||||
handlers: ls.handlers,
|
handlers: ls.handlers,
|
||||||
mac: mac,
|
mac: cfg.MAC,
|
||||||
gwmac: gateway,
|
gwmac: cfg.Gateway,
|
||||||
mtu: uint16(mtu),
|
mtu: uint16(cfg.MTU),
|
||||||
|
}
|
||||||
|
if cfg.AppendCRC32 {
|
||||||
|
ls.crcupdate = cfg.CRC32Update
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -95,7 +139,11 @@ DROP:
|
|||||||
func (ls *StackEthernet) Encapsulate(carrierData []byte, offsetToIP, offsetToFrame int) (n int, err error) {
|
func (ls *StackEthernet) Encapsulate(carrierData []byte, offsetToIP, offsetToFrame int) (n int, err error) {
|
||||||
mtu := ls.mtu
|
mtu := ls.mtu
|
||||||
dst := carrierData[offsetToFrame:]
|
dst := carrierData[offsetToFrame:]
|
||||||
if len(dst) < int(mtu) {
|
requiredSize := int(mtu) + 14
|
||||||
|
if ls.crcupdate != nil {
|
||||||
|
requiredSize += 4
|
||||||
|
}
|
||||||
|
if len(dst) < requiredSize {
|
||||||
return 0, io.ErrShortBuffer
|
return 0, io.ErrShortBuffer
|
||||||
}
|
}
|
||||||
efrm, err := ethernet.NewFrame(dst)
|
efrm, err := ethernet.NewFrame(dst)
|
||||||
@@ -108,9 +156,9 @@ func (ls *StackEthernet) Encapsulate(carrierData []byte, offsetToIP, offsetToFra
|
|||||||
// For IP: offsetToIP=14, offsetToFrame=14
|
// For IP: offsetToIP=14, offsetToFrame=14
|
||||||
// For ARP: offsetToIP=-1, offsetToFrame=14 (but ARP ignores offsetToIP)
|
// For ARP: offsetToIP=-1, offsetToFrame=14 (but ARP ignores offsetToIP)
|
||||||
// Clip carrierData to MTU to prevent writes beyond MTU limit.
|
// Clip carrierData to MTU to prevent writes beyond MTU limit.
|
||||||
offsetToFrame += 14
|
payloadOffset := offsetToFrame + 14
|
||||||
mtuLimit := offsetToFrame + int(mtu)
|
mtuLimit := payloadOffset + int(mtu)
|
||||||
h, n, err = ls.handlers.encapsulateAny(carrierData[:mtuLimit], offsetToFrame, offsetToFrame)
|
h, n, err = ls.handlers.encapsulateAny(carrierData[:mtuLimit], payloadOffset, payloadOffset)
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
return n, err
|
return n, err
|
||||||
}
|
}
|
||||||
@@ -118,5 +166,10 @@ func (ls *StackEthernet) Encapsulate(carrierData []byte, offsetToIP, offsetToFra
|
|||||||
*efrm.SourceHardwareAddr() = ls.mac
|
*efrm.SourceHardwareAddr() = ls.mac
|
||||||
efrm.SetEtherType(ethernet.Type(h.proto))
|
efrm.SetEtherType(ethernet.Type(h.proto))
|
||||||
n += 14
|
n += 14
|
||||||
|
if ls.crcupdate != nil {
|
||||||
|
crc := ls.crcupdate(0, carrierData[offsetToFrame:offsetToFrame+n])
|
||||||
|
binary.LittleEndian.PutUint32(carrierData[offsetToFrame+n:], crc)
|
||||||
|
n += 4
|
||||||
|
}
|
||||||
return n, err
|
return n, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -325,6 +325,8 @@ func (s *StackAsync) StartLookupIP(host string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EDNS0 buffer size: MTU minus overhead for IP+UDP headers and safety margin.
|
||||||
|
// 100 bytes covers IPv4 max header (60) + UDP (8) + 32 byte margin.
|
||||||
s.ednsopt.SetEDNS0(uint16(s.link.MTU())-100, 0, 0, nil)
|
s.ednsopt.SetEDNS0(uint16(s.link.MTU())-100, 0, 0, nil)
|
||||||
rand := s.prand32()
|
rand := s.prand32()
|
||||||
err = s.dns.StartResolve(uint16(rand>>1)+1024, uint16(rand), dns.ResolveConfig{
|
err = s.dns.StartResolve(uint16(rand>>1)+1024, uint16(rand), dns.ResolveConfig{
|
||||||
|
|||||||
@@ -11,15 +11,18 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/soypat/lneto/ethernet"
|
||||||
"github.com/soypat/lneto/tcp"
|
"github.com/soypat/lneto/tcp"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestTCPListener_ConcurrentEcho(t *testing.T) {
|
func TestTCPListener_ConcurrentEcho(t *testing.T) {
|
||||||
const (
|
const (
|
||||||
numClients = 10
|
numClients = 10
|
||||||
serverPort = 8080
|
serverPort = 8080
|
||||||
MTU = 1500
|
MTU = 1500
|
||||||
seed = 1
|
carrierSize = MTU + ethernet.MaxOverheadSize
|
||||||
|
tcpBufSize = MTU
|
||||||
|
seed = 1
|
||||||
)
|
)
|
||||||
|
|
||||||
// 1. Setup server stack with tcp.Listener.
|
// 1. Setup server stack with tcp.Listener.
|
||||||
@@ -63,7 +66,7 @@ func TestTCPListener_ConcurrentEcho(t *testing.T) {
|
|||||||
// 2. Setup client stacks (one per client).
|
// 2. Setup client stacks (one per client).
|
||||||
clientStacks := make([]StackAsync, numClients)
|
clientStacks := make([]StackAsync, numClients)
|
||||||
clientConns := make([]tcp.Conn, numClients)
|
clientConns := make([]tcp.Conn, numClients)
|
||||||
connBufs := make([]byte, numClients*MTU*2) // RX+TX buffer space for all clients
|
connBufs := make([]byte, numClients*tcpBufSize*2) // RX+TX buffer space for all clients
|
||||||
|
|
||||||
for i := range clientStacks {
|
for i := range clientStacks {
|
||||||
clientMAC := [6]byte{0xaa, 0xbb, 0xcc, 0x00, 0x01, byte(i + 1)}
|
clientMAC := [6]byte{0xaa, 0xbb, 0xcc, 0x00, 0x01, byte(i + 1)}
|
||||||
@@ -83,10 +86,10 @@ func TestTCPListener_ConcurrentEcho(t *testing.T) {
|
|||||||
clientStacks[i].SetGateway6(serverMAC)
|
clientStacks[i].SetGateway6(serverMAC)
|
||||||
|
|
||||||
// Configure client connection buffers.
|
// Configure client connection buffers.
|
||||||
bufOff := i * MTU * 2
|
bufOff := i * tcpBufSize * 2
|
||||||
err = clientConns[i].Configure(tcp.ConnConfig{
|
err = clientConns[i].Configure(tcp.ConnConfig{
|
||||||
RxBuf: connBufs[bufOff : bufOff+MTU],
|
RxBuf: connBufs[bufOff : bufOff+tcpBufSize],
|
||||||
TxBuf: connBufs[bufOff+MTU : bufOff+2*MTU],
|
TxBuf: connBufs[bufOff+tcpBufSize : bufOff+2*tcpBufSize],
|
||||||
TxPacketQueueSize: 4,
|
TxPacketQueueSize: 4,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -140,7 +143,7 @@ func TestTCPListener_ConcurrentEcho(t *testing.T) {
|
|||||||
|
|
||||||
func kernelLoop(ctx context.Context, server *StackAsync, clients []StackAsync) {
|
func kernelLoop(ctx context.Context, server *StackAsync, clients []StackAsync) {
|
||||||
const MTU = 1500
|
const MTU = 1500
|
||||||
const carrierDataSize = MTU + 14
|
const carrierDataSize = MTU + ethernet.MaxOverheadSize
|
||||||
buf := make([]byte, carrierDataSize)
|
buf := make([]byte, carrierDataSize)
|
||||||
rng := rand.New(rand.NewSource(1)) // Seed 1 for deterministic but randomized order
|
rng := rand.New(rand.NewSource(1)) // Seed 1 for deterministic but randomized order
|
||||||
order := make([]int, len(clients))
|
order := make([]int, len(clients))
|
||||||
@@ -174,7 +177,7 @@ func kernelLoop(ctx context.Context, server *StackAsync, clients []StackAsync) {
|
|||||||
|
|
||||||
func routePacketToClient(pkt []byte, clients []StackAsync) {
|
func routePacketToClient(pkt []byte, clients []StackAsync) {
|
||||||
// Extract destination IP from IPv4 header (offset 16-19 in IP header, after 14 byte Ethernet header).
|
// Extract destination IP from IPv4 header (offset 16-19 in IP header, after 14 byte Ethernet header).
|
||||||
if len(pkt) < 34 { // 14 ethernet + 20 min IP header
|
if len(pkt) < 20+ethernet.MaxOverheadSize { // 20 min IP header
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
dstIP := netip.AddrFrom4([4]byte{pkt[30], pkt[31], pkt[32], pkt[33]})
|
dstIP := netip.AddrFrom4([4]byte{pkt[30], pkt[31], pkt[32], pkt[33]})
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ func TestDNS_QueryReceivesAnswer(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Client sends DNS query.
|
// Client sends DNS query.
|
||||||
const carrierDataSize = MTU + 14
|
const carrierDataSize = MTU + ethernet.MaxOverheadSize
|
||||||
var buf [carrierDataSize]byte
|
var buf [carrierDataSize]byte
|
||||||
n, err := client.Encapsulate(buf[:], -1, 0)
|
n, err := client.Encapsulate(buf[:], -1, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -5,12 +5,14 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/soypat/lneto/ethernet"
|
||||||
"github.com/soypat/lneto/tcp"
|
"github.com/soypat/lneto/tcp"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestStackAsyncListener_SingleConnection(t *testing.T) {
|
func TestStackAsyncListener_SingleConnection(t *testing.T) {
|
||||||
const seed int64 = 1234
|
const seed int64 = 1234
|
||||||
const MTU = 1500
|
const MTU = 1500
|
||||||
|
const carrierSize = MTU + ethernet.MaxOverheadSize
|
||||||
const svPort = 80
|
const svPort = 80
|
||||||
const clPort = 1337
|
const clPort = 1337
|
||||||
|
|
||||||
@@ -121,6 +123,7 @@ func TestStackAsyncListener_SingleConnection(t *testing.T) {
|
|||||||
func TestStackAsyncListener_MultiSequentialConn(t *testing.T) {
|
func TestStackAsyncListener_MultiSequentialConn(t *testing.T) {
|
||||||
const seed int64 = 1234
|
const seed int64 = 1234
|
||||||
const MTU = 1500
|
const MTU = 1500
|
||||||
|
const carrierSize = MTU + ethernet.MaxOverheadSize
|
||||||
const svPort = 80
|
const svPort = 80
|
||||||
const clPort = 1337
|
const clPort = 1337
|
||||||
const poolsize = 10
|
const poolsize = 10
|
||||||
|
|||||||
+1
-1
@@ -217,7 +217,7 @@ func newTCPStacks(t *testing.T, randSeed int64, mtu int) (s1, s2 *StackAsync, c1
|
|||||||
}
|
}
|
||||||
|
|
||||||
func testerFrom(t *testing.T, mtu int) *tester {
|
func testerFrom(t *testing.T, mtu int) *tester {
|
||||||
carrierDataSize := mtu + 14
|
carrierDataSize := mtu + ethernet.MaxOverheadSize
|
||||||
return &tester{
|
return &tester{
|
||||||
t: t,
|
t: t,
|
||||||
buf: make([]byte, carrierDataSize),
|
buf: make([]byte, carrierDataSize),
|
||||||
|
|||||||
Reference in New Issue
Block a user