mirror of
https://github.com/soypat/lneto.git
synced 2026-09-14 10:39:31 +00:00
ICMP tests and various fixes (#68)
* various icmp fixes * improve existing tests
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
package xnet
|
||||
|
||||
import (
|
||||
"net/netip"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestStackAsync_ICMPEcho(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
pattern []byte
|
||||
size uint16
|
||||
}{
|
||||
{"1 EchoRequestReply", []byte("icmp-test"), 56},
|
||||
{"2 ReplyToManualRequest", []byte("manual-echo"), 32},
|
||||
}
|
||||
sender, receiver := newICMPStacks(t, 42, 1500) // seed 42 is arbitrary, stacks get unique IPs
|
||||
if err := sender.EnableICMP(true); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := receiver.EnableICMP(true); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
buf := make([]byte, 2048)
|
||||
n, err := sender.EgressEthernet(buf)
|
||||
if n > 0 || err != nil {
|
||||
t.Fatal("sender unexpected data sent or error", n, err)
|
||||
}
|
||||
n, err = receiver.EgressEthernet(buf)
|
||||
if n > 0 || err != nil {
|
||||
t.Fatal("receiver unexpected data sent or error", n, err)
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
|
||||
sender.SetGateway6(receiver.HardwareAddress())
|
||||
receiver.SetGateway6(sender.HardwareAddress())
|
||||
|
||||
key, err := sender.icmp.PingStart(receiver.Addr().As4(), tt.pattern, tt.size)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
echoSent := exchangeEthernetOnce(t, sender, receiver, buf)
|
||||
if !echoSent {
|
||||
t.Error("ECHO not sent")
|
||||
}
|
||||
echoReplySent := exchangeEthernetOnce(t, receiver, sender, buf)
|
||||
if !echoReplySent {
|
||||
t.Error("ECHOREPLY not sent")
|
||||
}
|
||||
n, err = sender.EgressEthernet(buf)
|
||||
if n > 0 || err != nil {
|
||||
t.Error("sender excess data sent or error", n, err)
|
||||
}
|
||||
n, err = receiver.EgressEthernet(buf)
|
||||
if n > 0 || err != nil {
|
||||
t.Error("receiver excess data sent or error", n, err)
|
||||
}
|
||||
|
||||
completed, ok := sender.icmp.PingPop(key)
|
||||
if !ok {
|
||||
t.Fatal("ping key not found")
|
||||
}
|
||||
if !completed {
|
||||
t.Fatal("expected ping to complete")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// exchangeEthernetOnce sends one Ethernet frame from src to dst if available.
|
||||
func exchangeEthernetOnce(t *testing.T, src, dst *StackAsync, buf []byte) bool {
|
||||
t.Helper()
|
||||
n, err := src.EgressEthernet(buf)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if n == 0 {
|
||||
return false
|
||||
}
|
||||
if err := dst.IngressEthernet(buf[:n]); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// newICMPStacks creates two test stacks with distinct static addresses and hardware addresses.
|
||||
func newICMPStacks(t testing.TB, randSeed int64, mtu int) (*StackAsync, *StackAsync) {
|
||||
const icmpQueue = 4
|
||||
s1, s2 := new(StackAsync), new(StackAsync)
|
||||
|
||||
// Use the seed to generate two adjacent IPs (10.0.0.x) and MACs.
|
||||
base := byte(randSeed & 0x7F) // keep in safe range 0..127
|
||||
addr1 := netip.AddrFrom4([4]byte{10, 0, 0, base})
|
||||
addr2 := netip.AddrFrom4([4]byte{10, 0, 0, base + 1})
|
||||
mac1 := [6]byte{0xbe, 0xef, 0, 0, 0, base}
|
||||
mac2 := [6]byte{0xbe, 0xef, 0, 0, 0, base + 1}
|
||||
|
||||
if err := s1.Reset(StackConfig{
|
||||
Hostname: "icmp-stack-1",
|
||||
RandSeed: randSeed,
|
||||
StaticAddress: addr1,
|
||||
HardwareAddress: mac1,
|
||||
MTU: uint16(mtu),
|
||||
ICMPQueueLimit: icmpQueue,
|
||||
}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := s2.Reset(StackConfig{
|
||||
Hostname: "icmp-stack-2",
|
||||
RandSeed: ^randSeed,
|
||||
StaticAddress: addr2,
|
||||
HardwareAddress: mac2,
|
||||
MTU: uint16(mtu),
|
||||
ICMPQueueLimit: icmpQueue,
|
||||
}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
return s1, s2
|
||||
}
|
||||
Reference in New Issue
Block a user