mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Move multicounter testutil functions out of network/ip
This is in preparation of having aggregated NIC stats at the stack level. These validation functions will be needed outside of the network layer packages to test aggregated NIC stats. PiperOrigin-RevId: 373180565
This commit is contained in:
@@ -47,7 +47,7 @@ go_test(
|
||||
library = ":arp",
|
||||
deps = [
|
||||
"//pkg/tcpip",
|
||||
"//pkg/tcpip/network/internal/testutil",
|
||||
"//pkg/tcpip/stack",
|
||||
"//pkg/tcpip/testutil",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -19,8 +19,8 @@ import (
|
||||
"testing"
|
||||
|
||||
"gvisor.dev/gvisor/pkg/tcpip"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/network/internal/testutil"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/stack"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/testutil"
|
||||
)
|
||||
|
||||
var _ stack.NetworkInterface = (*testInterface)(nil)
|
||||
|
||||
@@ -4,10 +4,7 @@ package(licenses = ["notice"])
|
||||
|
||||
go_library(
|
||||
name = "testutil",
|
||||
srcs = [
|
||||
"testutil.go",
|
||||
"testutil_unsafe.go",
|
||||
],
|
||||
srcs = ["testutil.go"],
|
||||
visibility = [
|
||||
"//pkg/tcpip/network/arp:__pkg__",
|
||||
"//pkg/tcpip/network/internal/fragmentation:__pkg__",
|
||||
|
||||
@@ -19,8 +19,6 @@ package testutil
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"gvisor.dev/gvisor/pkg/tcpip"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/buffer"
|
||||
@@ -129,69 +127,3 @@ func MakeRandPkt(transportHeaderLength int, extraHeaderReserveLength int, viewSi
|
||||
}
|
||||
return pkt
|
||||
}
|
||||
|
||||
func checkFieldCounts(ref, multi reflect.Value) error {
|
||||
refTypeName := ref.Type().Name()
|
||||
multiTypeName := multi.Type().Name()
|
||||
refNumField := ref.NumField()
|
||||
multiNumField := multi.NumField()
|
||||
|
||||
if refNumField != multiNumField {
|
||||
return fmt.Errorf("type %s has an incorrect number of fields: got = %d, want = %d (same as type %s)", multiTypeName, multiNumField, refNumField, refTypeName)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateField(ref reflect.Value, refName string, m tcpip.MultiCounterStat, multiName string) error {
|
||||
s, ok := ref.Addr().Interface().(**tcpip.StatCounter)
|
||||
if !ok {
|
||||
return fmt.Errorf("expected ref type's to be *StatCounter, but its type is %s", ref.Type().Elem().Name())
|
||||
}
|
||||
|
||||
// The field names are expected to match (case insensitive).
|
||||
if !strings.EqualFold(refName, multiName) {
|
||||
return fmt.Errorf("wrong field name: got = %s, want = %s", multiName, refName)
|
||||
}
|
||||
|
||||
base := (*s).Value()
|
||||
m.Increment()
|
||||
if (*s).Value() != base+1 {
|
||||
return fmt.Errorf("updates to the '%s MultiCounterStat' counters are not reflected in the '%s CounterStat'", multiName, refName)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ValidateMultiCounterStats verifies that every counter stored in multi is
|
||||
// correctly tracking its counterpart in the given counters.
|
||||
func ValidateMultiCounterStats(multi reflect.Value, counters []reflect.Value) error {
|
||||
for _, c := range counters {
|
||||
if err := checkFieldCounts(c, multi); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
for i := 0; i < multi.NumField(); i++ {
|
||||
multiName := multi.Type().Field(i).Name
|
||||
multiUnsafe := unsafeExposeUnexportedFields(multi.Field(i))
|
||||
|
||||
if m, ok := multiUnsafe.Addr().Interface().(*tcpip.MultiCounterStat); ok {
|
||||
for _, c := range counters {
|
||||
if err := validateField(unsafeExposeUnexportedFields(c.Field(i)), c.Type().Field(i).Name, *m, multiName); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var countersNextField []reflect.Value
|
||||
for _, c := range counters {
|
||||
countersNextField = append(countersNextField, c.Field(i))
|
||||
}
|
||||
if err := ValidateMultiCounterStats(multi.Field(i), countersNextField); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ go_test(
|
||||
library = ":ipv4",
|
||||
deps = [
|
||||
"//pkg/tcpip",
|
||||
"//pkg/tcpip/network/internal/testutil",
|
||||
"//pkg/tcpip/stack",
|
||||
"//pkg/tcpip/testutil",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -19,8 +19,8 @@ import (
|
||||
"testing"
|
||||
|
||||
"gvisor.dev/gvisor/pkg/tcpip"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/network/internal/testutil"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/stack"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/testutil"
|
||||
)
|
||||
|
||||
var _ stack.NetworkInterface = (*testInterface)(nil)
|
||||
|
||||
@@ -45,6 +45,7 @@ go_test(
|
||||
"//pkg/tcpip/link/sniffer",
|
||||
"//pkg/tcpip/network/internal/testutil",
|
||||
"//pkg/tcpip/stack",
|
||||
"//pkg/tcpip/testutil",
|
||||
"//pkg/tcpip/transport/icmp",
|
||||
"//pkg/tcpip/transport/tcp",
|
||||
"//pkg/tcpip/transport/udp",
|
||||
|
||||
@@ -31,8 +31,9 @@ import (
|
||||
"gvisor.dev/gvisor/pkg/tcpip/faketime"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/header"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/link/channel"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/network/internal/testutil"
|
||||
iptestutil "gvisor.dev/gvisor/pkg/tcpip/network/internal/testutil"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/stack"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/testutil"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/transport/icmp"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/transport/tcp"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/transport/udp"
|
||||
@@ -2603,7 +2604,7 @@ func TestWriteStats(t *testing.T) {
|
||||
t.Run(writer.name, func(t *testing.T) {
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
ep := testutil.NewMockLinkEndpoint(header.IPv6MinimumMTU, &tcpip.ErrInvalidEndpointState{}, test.allowPackets)
|
||||
ep := iptestutil.NewMockLinkEndpoint(header.IPv6MinimumMTU, &tcpip.ErrInvalidEndpointState{}, test.allowPackets)
|
||||
rt := buildRoute(t, ep)
|
||||
var pkts stack.PacketBufferList
|
||||
for i := 0; i < nPackets; i++ {
|
||||
@@ -2802,9 +2803,9 @@ func TestFragmentationWritePacket(t *testing.T) {
|
||||
|
||||
for _, ft := range fragmentationTests {
|
||||
t.Run(ft.description, func(t *testing.T) {
|
||||
pkt := testutil.MakeRandPkt(ft.transHdrLen, extraHeaderReserve+header.IPv6MinimumSize, []int{ft.payloadSize}, header.IPv6ProtocolNumber)
|
||||
pkt := iptestutil.MakeRandPkt(ft.transHdrLen, extraHeaderReserve+header.IPv6MinimumSize, []int{ft.payloadSize}, header.IPv6ProtocolNumber)
|
||||
source := pkt.Clone()
|
||||
ep := testutil.NewMockLinkEndpoint(ft.mtu, nil, math.MaxInt32)
|
||||
ep := iptestutil.NewMockLinkEndpoint(ft.mtu, nil, math.MaxInt32)
|
||||
r := buildRoute(t, ep)
|
||||
err := r.WritePacket(stack.NetworkHeaderParams{
|
||||
Protocol: tcp.ProtocolNumber,
|
||||
@@ -2858,7 +2859,7 @@ func TestFragmentationWritePackets(t *testing.T) {
|
||||
insertAfter: 1,
|
||||
},
|
||||
}
|
||||
tinyPacket := testutil.MakeRandPkt(header.TCPMinimumSize, extraHeaderReserve+header.IPv6MinimumSize, []int{1}, header.IPv6ProtocolNumber)
|
||||
tinyPacket := iptestutil.MakeRandPkt(header.TCPMinimumSize, extraHeaderReserve+header.IPv6MinimumSize, []int{1}, header.IPv6ProtocolNumber)
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.description, func(t *testing.T) {
|
||||
@@ -2868,14 +2869,14 @@ func TestFragmentationWritePackets(t *testing.T) {
|
||||
for i := 0; i < test.insertBefore; i++ {
|
||||
pkts.PushBack(tinyPacket.Clone())
|
||||
}
|
||||
pkt := testutil.MakeRandPkt(ft.transHdrLen, extraHeaderReserve+header.IPv6MinimumSize, []int{ft.payloadSize}, header.IPv6ProtocolNumber)
|
||||
pkt := iptestutil.MakeRandPkt(ft.transHdrLen, extraHeaderReserve+header.IPv6MinimumSize, []int{ft.payloadSize}, header.IPv6ProtocolNumber)
|
||||
source := pkt
|
||||
pkts.PushBack(pkt.Clone())
|
||||
for i := 0; i < test.insertAfter; i++ {
|
||||
pkts.PushBack(tinyPacket.Clone())
|
||||
}
|
||||
|
||||
ep := testutil.NewMockLinkEndpoint(ft.mtu, nil, math.MaxInt32)
|
||||
ep := iptestutil.NewMockLinkEndpoint(ft.mtu, nil, math.MaxInt32)
|
||||
r := buildRoute(t, ep)
|
||||
|
||||
wantTotalPackets := len(ft.wantFragments) + test.insertBefore + test.insertAfter
|
||||
@@ -2980,8 +2981,8 @@ func TestFragmentationErrors(t *testing.T) {
|
||||
|
||||
for _, ft := range tests {
|
||||
t.Run(ft.description, func(t *testing.T) {
|
||||
pkt := testutil.MakeRandPkt(ft.transHdrLen, extraHeaderReserve+header.IPv6MinimumSize, []int{ft.payloadSize}, header.IPv6ProtocolNumber)
|
||||
ep := testutil.NewMockLinkEndpoint(ft.mtu, ft.mockError, ft.allowPackets)
|
||||
pkt := iptestutil.MakeRandPkt(ft.transHdrLen, extraHeaderReserve+header.IPv6MinimumSize, []int{ft.payloadSize}, header.IPv6ProtocolNumber)
|
||||
ep := iptestutil.NewMockLinkEndpoint(ft.mtu, ft.mockError, ft.allowPackets)
|
||||
r := buildRoute(t, ep)
|
||||
err := r.WritePacket(stack.NetworkHeaderParams{
|
||||
Protocol: tcp.ProtocolNumber,
|
||||
|
||||
@@ -5,7 +5,10 @@ package(licenses = ["notice"])
|
||||
go_library(
|
||||
name = "testutil",
|
||||
testonly = True,
|
||||
srcs = ["testutil.go"],
|
||||
srcs = [
|
||||
"testutil.go",
|
||||
"testutil_unsafe.go",
|
||||
],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = ["//pkg/tcpip"],
|
||||
)
|
||||
|
||||
@@ -18,6 +18,8 @@ package testutil
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"gvisor.dev/gvisor/pkg/tcpip"
|
||||
)
|
||||
@@ -41,3 +43,69 @@ func MustParse6(addr string) tcpip.Address {
|
||||
}
|
||||
return tcpip.Address(ip)
|
||||
}
|
||||
|
||||
func checkFieldCounts(ref, multi reflect.Value) error {
|
||||
refTypeName := ref.Type().Name()
|
||||
multiTypeName := multi.Type().Name()
|
||||
refNumField := ref.NumField()
|
||||
multiNumField := multi.NumField()
|
||||
|
||||
if refNumField != multiNumField {
|
||||
return fmt.Errorf("type %s has an incorrect number of fields: got = %d, want = %d (same as type %s)", multiTypeName, multiNumField, refNumField, refTypeName)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateField(ref reflect.Value, refName string, m tcpip.MultiCounterStat, multiName string) error {
|
||||
s, ok := ref.Addr().Interface().(**tcpip.StatCounter)
|
||||
if !ok {
|
||||
return fmt.Errorf("expected ref type's to be *StatCounter, but its type is %s", ref.Type().Elem().Name())
|
||||
}
|
||||
|
||||
// The field names are expected to match (case insensitive).
|
||||
if !strings.EqualFold(refName, multiName) {
|
||||
return fmt.Errorf("wrong field name: got = %s, want = %s", multiName, refName)
|
||||
}
|
||||
|
||||
base := (*s).Value()
|
||||
m.Increment()
|
||||
if (*s).Value() != base+1 {
|
||||
return fmt.Errorf("updates to the '%s MultiCounterStat' counters are not reflected in the '%s CounterStat'", multiName, refName)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ValidateMultiCounterStats verifies that every counter stored in multi is
|
||||
// correctly tracking its counterpart in the given counters.
|
||||
func ValidateMultiCounterStats(multi reflect.Value, counters []reflect.Value) error {
|
||||
for _, c := range counters {
|
||||
if err := checkFieldCounts(c, multi); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
for i := 0; i < multi.NumField(); i++ {
|
||||
multiName := multi.Type().Field(i).Name
|
||||
multiUnsafe := unsafeExposeUnexportedFields(multi.Field(i))
|
||||
|
||||
if m, ok := multiUnsafe.Addr().Interface().(*tcpip.MultiCounterStat); ok {
|
||||
for _, c := range counters {
|
||||
if err := validateField(unsafeExposeUnexportedFields(c.Field(i)), c.Type().Field(i).Name, *m, multiName); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var countersNextField []reflect.Value
|
||||
for _, c := range counters {
|
||||
countersNextField = append(countersNextField, c.Field(i))
|
||||
}
|
||||
if err := ValidateMultiCounterStats(multi.Field(i), countersNextField); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user