refactor max tcp port config values to uint16 to better represent their valid space

This commit is contained in:
Patricio Whittingslow
2026-04-09 20:13:45 -03:00
parent 548d96da95
commit 568ef2854f
12 changed files with 129 additions and 124 deletions
+12 -12
View File
@@ -104,11 +104,11 @@ func run() error {
var stack xnet.StackAsync var stack xnet.StackAsync
if err := stack.Reset(xnet.StackConfig{ if err := stack.Reset(xnet.StackConfig{
Hostname: "berkeley-http", Hostname: "berkeley-http",
RandSeed: softRand, RandSeed: softRand,
HardwareAddress: nicHW, HardwareAddress: nicHW,
MTU: uint16(mtu), MTU: uint16(mtu),
MaxTCPConns: 1024, MaxActiveTCPPorts: 1024,
}); err != nil { }); err != nil {
return err return err
} }
@@ -202,7 +202,7 @@ func run() error {
blocking := stack.StackBlocking(5 * time.Millisecond) blocking := stack.StackBlocking(5 * time.Millisecond)
berkeley := blocking.StackGo(xnet.StackGoConfig{ berkeley := blocking.StackGo(xnet.StackGoConfig{
ListenerPoolConfig: xnet.TCPPoolConfig{ ListenerPoolConfig: xnet.TCPPoolConfig{
PoolSize: flagPoolSize, PoolSize: uint16(flagPoolSize),
QueueSize: 3, QueueSize: 3,
TxBufSize: mtu, TxBufSize: mtu,
RxBufSize: mtu, RxBufSize: mtu,
@@ -328,12 +328,12 @@ func tryPoll(iface ltesto.Interface, poll time.Duration) (dataMayBeReady bool, _
func mockClient(stack *xnet.StackAsync, port uint16, subnet netip.Prefix) { func mockClient(stack *xnet.StackAsync, port uint16, subnet netip.Prefix) {
target := netip.AddrPortFrom(stack.Addr(), port) target := netip.AddrPortFrom(stack.Addr(), port)
err := mockStack.Reset(xnet.StackConfig{ err := mockStack.Reset(xnet.StackConfig{
StaticAddress: subnet.Addr().Next(), StaticAddress: subnet.Addr().Next(),
MaxTCPConns: 1, MaxActiveTCPPorts: 1,
HardwareAddress: stack.Gateway6(), HardwareAddress: stack.Gateway6(),
Hostname: "the-other", Hostname: "the-other",
MTU: uint16(stack.MTU()), MTU: uint16(stack.MTU()),
RandSeed: int64(stack.Prand32()), RandSeed: int64(stack.Prand32()),
}) })
if err != nil { if err != nil {
panic(err.Error()) panic(err.Error())
+5 -5
View File
@@ -101,11 +101,11 @@ func run() (err error) {
var stack xnet.StackAsync var stack xnet.StackAsync
err = stack.Reset(xnet.StackConfig{ err = stack.Reset(xnet.StackConfig{
Hostname: "httpserver", Hostname: "httpserver",
RandSeed: softRand, RandSeed: softRand,
HardwareAddress: nicHW, HardwareAddress: nicHW,
MTU: uint16(mtu), MTU: uint16(mtu),
MaxTCPConns: 1000, MaxActiveTCPPorts: 1000,
}) })
if err != nil { if err != nil {
return err return err
+1 -1
View File
@@ -64,7 +64,7 @@ func run(ctx context.Context, stack *xnet.StackAsync) error {
Hostname: "lneto-mwe", Hostname: "lneto-mwe",
RandSeed: time.Now().UnixNano(), RandSeed: time.Now().UnixNano(),
// A passive TCP listener to many remote ports takes up one spot, active TCP clients to one remote port take up a spot. // A passive TCP listener to many remote ports takes up one spot, active TCP clients to one remote port take up a spot.
MaxTCPConns: 1, MaxActiveTCPPorts: 1,
// MaxUDPConns: 1 , // For MDNS support. // MaxUDPConns: 1 , // For MDNS support.
// AcceptMulticast: true, // For MDNS. // AcceptMulticast: true, // For MDNS.
MTU: uint16(framelen - ethernet.MaxOverheadSize), MTU: uint16(framelen - ethernet.MaxOverheadSize),
+5 -5
View File
@@ -121,11 +121,11 @@ func run() (err error) {
var stack xnet.StackAsync var stack xnet.StackAsync
err = stack.Reset(xnet.StackConfig{ err = stack.Reset(xnet.StackConfig{
Hostname: "xnet-test", Hostname: "xnet-test",
RandSeed: softRand, RandSeed: softRand,
HardwareAddress: brHW, HardwareAddress: brHW,
MTU: uint16(mtu), MTU: uint16(mtu),
MaxTCPConns: 1, MaxActiveTCPPorts: 1,
}) })
if err != nil { if err != nil {
return err return err
+7 -7
View File
@@ -22,21 +22,21 @@ type StackPorts struct {
rstQueue tcp.RSTQueue rstQueue tcp.RSTQueue
} }
func (ps *StackPorts) ResetUDP(maxNodes int) error { func (ps *StackPorts) ResetUDP(maxNodes uint16) error {
return ps.Reset(uint64(lneto.IPProtoUDP), 2, maxNodes) return ps.Reset(uint64(lneto.IPProtoUDP), 2, maxNodes)
} }
func (ps *StackPorts) ResetTCP(maxNodes int) error { func (ps *StackPorts) ResetTCP(maxNodes uint16) error {
return ps.Reset(uint64(lneto.IPProtoTCP), 2, maxNodes) return ps.Reset(uint64(lneto.IPProtoTCP), 2, maxNodes)
} }
func (ps *StackPorts) Reset(protocol uint64, dstPortOffset uint16, maxNodes int) error { func (ps *StackPorts) Reset(protocol uint64, dstPortOffset, maxNodes uint16) error {
if protocol > math.MaxUint16 { if protocol > math.MaxUint16 {
return lneto.ErrInvalidConfig return lneto.ErrInvalidConfig
} else if maxNodes <= 0 { } else if maxNodes <= 0 {
return lneto.ErrInvalidConfig return lneto.ErrInvalidConfig
} }
ps.handlers.reset("StackPorts(proto="+strconv.Itoa(int(protocol))+")", maxNodes) ps.handlers.reset("StackPorts(proto="+strconv.Itoa(int(protocol))+")", int(maxNodes))
*ps = StackPorts{ *ps = StackPorts{
connID: ps.connID + 1, connID: ps.connID + 1,
handlers: ps.handlers, handlers: ps.handlers,
@@ -118,15 +118,15 @@ func (mfsp *StackPortsMACFiltered) Register(h lneto.StackNode, addr []byte) erro
return mfsp.sp.handlers.registerByPortProto(nodeFromStackNode(h, port, proto, addr)) return mfsp.sp.handlers.registerByPortProto(nodeFromStackNode(h, port, proto, addr))
} }
func (ps *StackPortsMACFiltered) ResetUDP(maxNodes int) error { func (ps *StackPortsMACFiltered) ResetUDP(maxNodes uint16) error {
return ps.sp.ResetUDP(maxNodes) return ps.sp.ResetUDP(maxNodes)
} }
func (ps *StackPortsMACFiltered) ResetTCP(maxNodes int) error { func (ps *StackPortsMACFiltered) ResetTCP(maxNodes uint16) error {
return ps.sp.ResetTCP(maxNodes) return ps.sp.ResetTCP(maxNodes)
} }
func (ps *StackPortsMACFiltered) Reset(protocol uint64, dstPortOffset uint16, maxNodes int) error { func (ps *StackPortsMACFiltered) Reset(protocol uint64, dstPortOffset, maxNodes uint16) error {
return ps.sp.Reset(protocol, dstPortOffset, maxNodes) return ps.sp.Reset(protocol, dstPortOffset, maxNodes)
} }
+15 -11
View File
@@ -62,13 +62,17 @@ type StackAsync struct {
} }
type StackConfig struct { type StackConfig struct {
StaticAddress netip.Addr StaticAddress netip.Addr
DNSServer netip.Addr DNSServer netip.Addr
NTPServer netip.Addr NTPServer netip.Addr
RandSeed int64 RandSeed int64
Hostname string Hostname string
MaxTCPConns int
MaxUDPConns int // MaxActiveTCPPorts and MaxActiveUDPPorts are a memory guardrail to limit
// number of simultaneous open TCP/UDP ports. The memory impact at the stack level
// of a port corresponds to ~64 bytes excluding the registered StackNode i.e: [tcp.Conn] or [udp.Conn].
MaxActiveTCPPorts, MaxActiveUDPPorts uint16
EthernetTxCRC32Update func(crc uint32, b []byte) uint32 EthernetTxCRC32Update func(crc uint32, b []byte) uint32
HardwareAddress [6]byte HardwareAddress [6]byte
@@ -170,16 +174,16 @@ func (s *StackAsync) Reset(cfg StackConfig) error {
if err != nil { if err != nil {
return err return err
} }
udpConns := 3 + cfg.MaxUDPConns // DHCP, DNS, NTP + user-registered. udpConns := 3 + cfg.MaxActiveUDPPorts // DHCP, DNS, NTP + user-registered.
err = s.udps.ResetUDP(udpConns) err = s.udps.ResetUDP(udpConns)
if err != nil { if err != nil {
return err return err
} }
internal.SliceReuse(&s.userUDPs, cfg.MaxUDPConns) internal.SliceReuse(&s.userUDPs, int(cfg.MaxActiveUDPPorts))
// Enable TCP if connections present. // Enable TCP if connections present.
if cfg.MaxTCPConns > 0 { if cfg.MaxActiveTCPPorts > 0 {
err = s.tcps.ResetTCP(cfg.MaxTCPConns) err = s.tcps.ResetTCP(cfg.MaxActiveTCPPorts)
if err != nil { if err != nil {
return err return err
} }
+3 -2
View File
@@ -32,7 +32,8 @@ func _() {
} }
type TCPPoolConfig struct { type TCPPoolConfig struct {
PoolSize int // PoolSize determines the maximum number of active incoming TCP connections to the pool.
PoolSize uint16
QueueSize int QueueSize int
TxBufSize int TxBufSize int
RxBufSize int RxBufSize int
@@ -58,7 +59,7 @@ func NewTCPPool(cfg TCPPoolConfig) (*TCPPool, error) {
if cfg.EstablishedTimeout <= 0 || cfg.ClosingTimeout <= 0 { if cfg.EstablishedTimeout <= 0 || cfg.ClosingTimeout <= 0 {
return nil, lneto.ErrInvalidConfig return nil, lneto.ErrInvalidConfig
} }
n := cfg.PoolSize n := int(cfg.PoolSize)
pool := &TCPPool{ pool := &TCPPool{
acquiredAt: make([]int64, n), acquiredAt: make([]int64, n),
closingAt: make([]int64, n), closingAt: make([]int64, n),
+12 -12
View File
@@ -83,23 +83,23 @@ func BenchmarkTCPHandshake(b *testing.B) {
clconn, svconn := new(tcp.Conn), new(tcp.Conn) clconn, svconn := new(tcp.Conn), new(tcp.Conn)
err := sv.Reset(StackConfig{ err := sv.Reset(StackConfig{
Hostname: "Server", Hostname: "Server",
RandSeed: 1, RandSeed: 1,
StaticAddress: netip.AddrFrom4([4]byte{10, 0, 0, 1}), StaticAddress: netip.AddrFrom4([4]byte{10, 0, 0, 1}),
MaxTCPConns: 1, MaxActiveTCPPorts: 1,
HardwareAddress: [6]byte{0xbe, 0xef, 0, 0, 0, 1}, HardwareAddress: [6]byte{0xbe, 0xef, 0, 0, 0, 1},
MTU: MTU, MTU: MTU,
}) })
if err != nil { if err != nil {
b.Fatal(err) b.Fatal(err)
} }
err = client.Reset(StackConfig{ err = client.Reset(StackConfig{
Hostname: "Client", Hostname: "Client",
RandSeed: 2, RandSeed: 2,
StaticAddress: netip.AddrFrom4([4]byte{10, 0, 0, 2}), StaticAddress: netip.AddrFrom4([4]byte{10, 0, 0, 2}),
MaxTCPConns: 1, MaxActiveTCPPorts: 1,
HardwareAddress: [6]byte{0xbe, 0xef, 0, 0, 0, 2}, HardwareAddress: [6]byte{0xbe, 0xef, 0, 0, 0, 2},
MTU: MTU, MTU: MTU,
}) })
if err != nil { if err != nil {
b.Fatal(err) b.Fatal(err)
+12 -12
View File
@@ -30,12 +30,12 @@ func TestTCPListener_ConcurrentEcho(t *testing.T) {
serverMAC := [6]byte{0xaa, 0xbb, 0xcc, 0x00, 0x00, 0x01} serverMAC := [6]byte{0xaa, 0xbb, 0xcc, 0x00, 0x00, 0x01}
serverIP := netip.AddrFrom4([4]byte{10, 0, 0, 1}) serverIP := netip.AddrFrom4([4]byte{10, 0, 0, 1})
err := serverStack.Reset(StackConfig{ err := serverStack.Reset(StackConfig{
Hostname: "Server", Hostname: "Server",
RandSeed: seed, RandSeed: seed,
StaticAddress: serverIP, StaticAddress: serverIP,
MaxTCPConns: numClients, MaxActiveTCPPorts: numClients,
HardwareAddress: serverMAC, HardwareAddress: serverMAC,
MTU: MTU, MTU: MTU,
}) })
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
@@ -72,12 +72,12 @@ func TestTCPListener_ConcurrentEcho(t *testing.T) {
clientMAC := [6]byte{0xaa, 0xbb, 0xcc, 0x00, 0x01, byte(i + 1)} clientMAC := [6]byte{0xaa, 0xbb, 0xcc, 0x00, 0x01, byte(i + 1)}
clientIP := netip.AddrFrom4([4]byte{10, 0, 0, byte(i + 10)}) clientIP := netip.AddrFrom4([4]byte{10, 0, 0, byte(i + 10)})
err := clientStacks[i].Reset(StackConfig{ err := clientStacks[i].Reset(StackConfig{
Hostname: fmt.Sprintf("Client%d", i), Hostname: fmt.Sprintf("Client%d", i),
RandSeed: int64(seed + i + 1), RandSeed: int64(seed + i + 1),
StaticAddress: clientIP, StaticAddress: clientIP,
MaxTCPConns: 1, MaxActiveTCPPorts: 1,
HardwareAddress: clientMAC, HardwareAddress: clientMAC,
MTU: MTU, MTU: MTU,
}) })
if err != nil { if err != nil {
t.Fatalf("client %d reset: %v", i, err) t.Fatalf("client %d reset: %v", i, err)
+24 -24
View File
@@ -19,23 +19,23 @@ func TestStackAsyncListener_SingleConnection(t *testing.T) {
// Create two stacks. // Create two stacks.
client, sv := new(StackAsync), new(StackAsync) client, sv := new(StackAsync), new(StackAsync)
err := client.Reset(StackConfig{ err := client.Reset(StackConfig{
Hostname: "Client", Hostname: "Client",
RandSeed: seed, RandSeed: seed,
StaticAddress: netip.AddrFrom4([4]byte{10, 0, 0, 1}), StaticAddress: netip.AddrFrom4([4]byte{10, 0, 0, 1}),
MaxTCPConns: 1, MaxActiveTCPPorts: 1,
HardwareAddress: [6]byte{0xbe, 0xef, 0, 0, 0, 1}, HardwareAddress: [6]byte{0xbe, 0xef, 0, 0, 0, 1},
MTU: MTU, MTU: MTU,
}) })
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
err = sv.Reset(StackConfig{ err = sv.Reset(StackConfig{
Hostname: "Server", Hostname: "Server",
RandSeed: ^seed, RandSeed: ^seed,
StaticAddress: netip.AddrFrom4([4]byte{10, 0, 0, 2}), StaticAddress: netip.AddrFrom4([4]byte{10, 0, 0, 2}),
MaxTCPConns: 1, // Note: We use listener, not direct TCP conn registration. MaxActiveTCPPorts: 1, // Note: We use listener, not direct TCP conn registration.
HardwareAddress: [6]byte{0xbe, 0xef, 0, 0, 0, 2}, HardwareAddress: [6]byte{0xbe, 0xef, 0, 0, 0, 2},
MTU: MTU, MTU: MTU,
}) })
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
@@ -131,12 +131,12 @@ func TestStackAsyncListener_MultiSequentialConn(t *testing.T) {
// Create two stacks. // Create two stacks.
sv := new(StackAsync) sv := new(StackAsync)
err := sv.Reset(StackConfig{ err := sv.Reset(StackConfig{
Hostname: "Server", Hostname: "Server",
RandSeed: ^seed, RandSeed: ^seed,
StaticAddress: netip.AddrFrom4([4]byte{10, 0, 0, 2}), StaticAddress: netip.AddrFrom4([4]byte{10, 0, 0, 2}),
MaxTCPConns: 1, // Note: We use listener, not direct TCP conn registration. MaxActiveTCPPorts: 1, // Note: We use listener, not direct TCP conn registration.
HardwareAddress: [6]byte{0xbe, 0xef, 0, 0, 0, 2}, HardwareAddress: [6]byte{0xbe, 0xef, 0, 0, 0, 2},
MTU: MTU, MTU: MTU,
}) })
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
@@ -171,12 +171,12 @@ func TestStackAsyncListener_MultiSequentialConn(t *testing.T) {
doRequest := func(caddrp netip.AddrPort, sleep time.Duration, data []byte) { doRequest := func(caddrp netip.AddrPort, sleep time.Duration, data []byte) {
var client StackAsync var client StackAsync
err := client.Reset(StackConfig{ err := client.Reset(StackConfig{
Hostname: "Client", Hostname: "Client",
RandSeed: seed, RandSeed: seed,
StaticAddress: caddrp.Addr(), StaticAddress: caddrp.Addr(),
MaxTCPConns: 1, MaxActiveTCPPorts: 1,
HardwareAddress: chw, HardwareAddress: chw,
MTU: MTU, MTU: MTU,
}) })
if err != nil { if err != nil {
panic(err) panic(err)
+21 -21
View File
@@ -43,13 +43,13 @@ func TestMDNS_QueryResponse(t *testing.T) {
// Setup responder stack with mDNS service. // Setup responder stack with mDNS service.
responderStack := new(StackAsync) responderStack := new(StackAsync)
err = responderStack.Reset(StackConfig{ err = responderStack.Reset(StackConfig{
Hostname: "responder", Hostname: "responder",
RandSeed: 1234, RandSeed: 1234,
StaticAddress: responderAddr, StaticAddress: responderAddr,
HardwareAddress: responderMAC, HardwareAddress: responderMAC,
MTU: MTU, MTU: MTU,
MaxUDPConns: 1, MaxActiveUDPPorts: 1,
AcceptMulticast: true, AcceptMulticast: true,
}) })
if err != nil { if err != nil {
t.Fatal("responder reset:", err) t.Fatal("responder reset:", err)
@@ -73,13 +73,13 @@ func TestMDNS_QueryResponse(t *testing.T) {
// Setup querier stack. // Setup querier stack.
querierStack := new(StackAsync) querierStack := new(StackAsync)
err = querierStack.Reset(StackConfig{ err = querierStack.Reset(StackConfig{
Hostname: "querier", Hostname: "querier",
RandSeed: 5678, RandSeed: 5678,
StaticAddress: querierAddr, StaticAddress: querierAddr,
HardwareAddress: querierMAC, HardwareAddress: querierMAC,
MTU: MTU, MTU: MTU,
MaxUDPConns: 1, MaxActiveUDPPorts: 1,
AcceptMulticast: true, AcceptMulticast: true,
}) })
if err != nil { if err != nil {
t.Fatal("querier reset:", err) t.Fatal("querier reset:", err)
@@ -278,13 +278,13 @@ func newMDNSStack(t *testing.T, hostname string, seed int64,
const MTU = 1500 const MTU = 1500
stack := new(StackAsync) stack := new(StackAsync)
err := stack.Reset(StackConfig{ err := stack.Reset(StackConfig{
Hostname: hostname, Hostname: hostname,
RandSeed: seed, RandSeed: seed,
StaticAddress: addr, StaticAddress: addr,
HardwareAddress: mac, HardwareAddress: mac,
MTU: MTU, MTU: MTU,
MaxUDPConns: 1, MaxActiveUDPPorts: 1,
AcceptMulticast: true, AcceptMulticast: true,
}) })
if err != nil { if err != nil {
t.Fatal(hostname, "reset:", err) t.Fatal(hostname, "reset:", err)
+12 -12
View File
@@ -175,12 +175,12 @@ func newTCPStacks(t testing.TB, randSeed int64, mtu int) (s1, s2 *StackAsync, c1
c1, c2 = new(tcp.Conn), new(tcp.Conn) c1, c2 = new(tcp.Conn), new(tcp.Conn)
byte1 := byte(randSeed)/4 - 1 byte1 := byte(randSeed)/4 - 1
err := s1.Reset(StackConfig{ err := s1.Reset(StackConfig{
Hostname: "Stack1", Hostname: "Stack1",
RandSeed: randSeed, RandSeed: randSeed,
StaticAddress: netip.AddrFrom4([4]byte{10, 0, 0, byte1}), StaticAddress: netip.AddrFrom4([4]byte{10, 0, 0, byte1}),
MaxTCPConns: 1, MaxActiveTCPPorts: 1,
HardwareAddress: [6]byte{0xbe, 0xef, 0, 0, 0, byte1}, HardwareAddress: [6]byte{0xbe, 0xef, 0, 0, 0, byte1},
MTU: uint16(mtu), MTU: uint16(mtu),
}) })
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
@@ -188,12 +188,12 @@ func newTCPStacks(t testing.TB, randSeed int64, mtu int) (s1, s2 *StackAsync, c1
byte2 := byte1 + 1 byte2 := byte1 + 1
err = s2.Reset(StackConfig{ err = s2.Reset(StackConfig{
Hostname: "Stack2", Hostname: "Stack2",
RandSeed: ^randSeed, RandSeed: ^randSeed,
StaticAddress: netip.AddrFrom4([4]byte{10, 0, 0, byte2}), StaticAddress: netip.AddrFrom4([4]byte{10, 0, 0, byte2}),
MaxTCPConns: 1, MaxActiveTCPPorts: 1,
HardwareAddress: [6]byte{0xbe, 0xef, 0, 0, 0, byte2}, HardwareAddress: [6]byte{0xbe, 0xef, 0, 0, 0, byte2},
MTU: uint16(mtu), MTU: uint16(mtu),
}) })
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)