package xnet import ( "net/netip" "testing" "github.com/soypat/lneto/ethernet" "github.com/soypat/lneto/tcp" ) func BenchmarkARPExchange(b *testing.B) { const MTU = ethernet.MaxMTU const frameSize = ethernet.MaxFrameLength c1, c2 := new(StackAsync), new(StackAsync) queryAddr := netip.AddrFrom4([4]byte{192, 168, 1, 2}) err := c1.Reset(StackConfig{ Hostname: "C1", RandSeed: 1, StaticAddress4: [4]byte{192, 168, 1, 1}, HardwareAddress: [6]byte{0xde, 0xad, 0xbe, 0xef, 0x00, 0x00}, MTU: MTU, }) if err != nil { b.Fatal(err) } err = c2.Reset(StackConfig{ Hostname: "C2", RandSeed: 2, StaticAddress4: queryAddr.As4(), HardwareAddress: [6]byte{0xc0, 0xff, 0xee, 0xc0, 0xff, 0xee}, MTU: MTU, }) if err != nil { b.Fatal(err) } // Set gateways so ethernet frames are properly addressed. c1.SetGatewayHardwareAddr(c2.HardwareAddr()) c2.SetGatewayHardwareAddr(c1.HardwareAddr()) var buf [frameSize]byte b.ResetTimer() for b.Loop() { err = c1.StartResolveHardwareAddress6(queryAddr) if err != nil { b.Fatal(err) } n, err := c1.EgressEthernet(buf[:]) // Send Request. if err != nil { b.Fatal(err) } else if n == 0 { b.Fatal("expected send of data after first query") } err = c2.IngressEthernet(buf[:n]) // Receive request. if err != nil { b.Fatal(err) } n, err = c2.EgressEthernet(buf[:]) // Send response. if err != nil { b.Fatal(err) } else if n == 0 { b.Fatal("got no response to request") } err = c1.IngressEthernet(buf[:n]) // Receive response. if err != nil { b.Fatal(err) } _, err = c1.ResultResolveHardwareAddress6(queryAddr) if err != nil { b.Fatal("expected query result:", err) } // Discard query for next iteration. c1.DiscardResolveHardwareAddress6(queryAddr) } } func BenchmarkTCPHandshake(b *testing.B) { const MTU = ethernet.MaxMTU const frameSize = ethernet.MaxFrameLength const svPort = 8080 client, sv := new(StackAsync), new(StackAsync) clconn, svconn := new(tcp.Conn), new(tcp.Conn) err := sv.Reset(StackConfig{ Hostname: "Server", RandSeed: 1, StaticAddress4: [4]byte{10, 0, 0, 1}, MaxActiveTCPPorts: 1, HardwareAddress: [6]byte{0xbe, 0xef, 0, 0, 0, 1}, MTU: MTU, }) if err != nil { b.Fatal(err) } err = client.Reset(StackConfig{ Hostname: "Client", RandSeed: 2, StaticAddress4: [4]byte{10, 0, 0, 2}, MaxActiveTCPPorts: 1, HardwareAddress: [6]byte{0xbe, 0xef, 0, 0, 0, 2}, MTU: MTU, }) if err != nil { b.Fatal(err) } sv.SetGatewayHardwareAddr(client.HardwareAddr()) client.SetGatewayHardwareAddr(sv.HardwareAddr()) buf := make([]byte, MTU*4) err = clconn.Configure(tcp.ConnConfig{ RxBuf: buf[:MTU], TxBuf: buf[MTU : MTU*2], TxPacketQueueSize: 4, RWBackoff: backoffYield, }) if err != nil { b.Fatal(err) } err = svconn.Configure(tcp.ConnConfig{ RxBuf: buf[2*MTU : 3*MTU], TxBuf: buf[3*MTU : 4*MTU], TxPacketQueueSize: 4, RWBackoff: backoffYield, }) if err != nil { b.Fatal(err) } var pktbuf [frameSize]byte b.ResetTimer() for b.Loop() { // Setup connections. err = sv.ListenTCP4(svconn, svPort) if err != nil { b.Fatal(err) } err = client.DialTCP(clconn, 1337, netip.AddrPortFrom(netip.AddrFrom4(sv.Addr4()), svPort)) if err != nil { b.Fatal(err) } // SYN from client. n, err := client.EgressEthernet(pktbuf[:]) if err != nil { b.Fatal(err) } err = sv.IngressEthernet(pktbuf[:n]) if err != nil { b.Fatal(err) } // SYN-ACK from server. n, err = sv.EgressEthernet(pktbuf[:]) if err != nil { b.Fatal(err) } err = client.IngressEthernet(pktbuf[:n]) if err != nil { b.Fatal(err) } // ACK from client. n, err = client.EgressEthernet(pktbuf[:]) if err != nil { b.Fatal(err) } err = sv.IngressEthernet(pktbuf[:n]) if err != nil { b.Fatal(err) } // Abort connections for next iteration. clconn.Abort() svconn.Abort() } }