1
0
mirror of https://github.com/bgp/stayrtr.git synced 2024-05-06 15:54:54 +00:00
Files
2023-12-21 15:45:52 +01:00

267 lines
6.8 KiB
Go

package rtrlib
import (
"fmt"
"net/netip"
"runtime"
"testing"
"unsafe"
"github.com/google/go-cmp/cmp"
"github.com/stretchr/testify/assert"
)
func GenerateVrps(size uint32, offset uint32) []SendableData {
vrps := make([]SendableData, size)
for i := uint32(0); i < size; i++ {
ipFinal := i+offset
vrps[i] = &VRP{
Prefix: netip.MustParsePrefix(fmt.Sprintf("fd00::%04x:%04x/128", ipFinal >> 16, ipFinal & 0xffff)),
MaxLen: 128,
ASN: 64496,
}
}
return vrps
}
func BaseBench(base int, multiplier int) {
benchSize1 := base * multiplier
newVrps := GenerateVrps(uint32(benchSize1), uint32(0))
benchSize2 := base
prevVrps := GenerateVrps(uint32(benchSize2), uint32(benchSize1-benchSize2/2))
ComputeDiff(newVrps, prevVrps, false)
}
func BenchmarkComputeDiff1000x10(b *testing.B) {
BaseBench(1000, 10)
}
func BenchmarkComputeDiff10000x10(b *testing.B) {
BaseBench(10000, 10)
}
func BenchmarkComputeDiff100000x1(b *testing.B) {
BaseBench(100000, 1)
}
func TestComputeDiff(t *testing.T) {
newVrps := []VRP{
{
Prefix: netip.MustParsePrefix("fd00::3/128"),
MaxLen: 128,
ASN: 65003,
},
{
Prefix: netip.MustParsePrefix("fd00::2/128"),
MaxLen: 128,
ASN: 65002,
},
}
prevVrps := []VRP{
{
Prefix: netip.MustParsePrefix("fd00::1/128"),
MaxLen: 128,
ASN: 65001,
},
{
Prefix: netip.MustParsePrefix("fd00::2/128"),
MaxLen: 128,
ASN: 65002,
},
}
newVrpsSD, prevVrpsAsSD := make([]SendableData, 0), make([]SendableData, 0)
for _, v := range newVrps {
newVrpsSD = append(newVrpsSD, v.Copy())
}
for _, v := range prevVrps {
prevVrpsAsSD = append(prevVrpsAsSD, v.Copy())
}
added, removed, unchanged := ComputeDiff(newVrpsSD, prevVrpsAsSD, true)
assert.Len(t, added, 1)
assert.Len(t, removed, 1)
assert.Len(t, unchanged, 1)
assert.Equal(t, added[0].(*VRP).ASN, uint32(65003))
assert.Equal(t, removed[0].(*VRP).ASN, uint32(65001))
assert.Equal(t, unchanged[0].(*VRP).ASN, uint32(65002))
}
func TestApplyDiff(t *testing.T) {
diff := []VRP{
{
Prefix: netip.MustParsePrefix("fd00::3/128"),
MaxLen: 128,
ASN: 65003,
Flags: FLAG_ADDED,
},
{
Prefix: netip.MustParsePrefix("fd00::2/128"),
MaxLen: 128,
ASN: 65002,
Flags: FLAG_REMOVED,
},
{
Prefix: netip.MustParsePrefix("fd00::4/128"),
MaxLen: 128,
ASN: 65004,
Flags: FLAG_REMOVED,
},
{
Prefix: netip.MustParsePrefix("fd00::6/128"),
MaxLen: 128,
ASN: 65006,
Flags: FLAG_REMOVED,
},
{
Prefix: netip.MustParsePrefix("fd00::7/128"),
MaxLen: 128,
ASN: 65007,
Flags: FLAG_ADDED,
},
}
prevVrps := []VRP{
{
Prefix: netip.MustParsePrefix("fd00::1/128"),
MaxLen: 128,
ASN: 65001,
Flags: FLAG_ADDED,
},
{
Prefix: netip.MustParsePrefix("fd00::2/128"),
MaxLen: 128,
ASN: 65002,
Flags: FLAG_ADDED,
},
{
Prefix: netip.MustParsePrefix("fd00::5/128"),
MaxLen: 128,
ASN: 65005,
Flags: FLAG_REMOVED,
},
{
Prefix: netip.MustParsePrefix("fd00::6/128"),
MaxLen: 128,
ASN: 65006,
Flags: FLAG_REMOVED,
},
{
Prefix: netip.MustParsePrefix("fd00::7/128"),
MaxLen: 128,
ASN: 65007,
Flags: FLAG_REMOVED,
},
}
diffSD, prevVrpsAsSD := make([]SendableData, 0), make([]SendableData, 0)
for _, v := range diff {
diffSD = append(diffSD, v.Copy())
}
for _, v := range prevVrps {
prevVrpsAsSD = append(prevVrpsAsSD, v.Copy())
}
vrps := ApplyDiff(diffSD, prevVrpsAsSD)
assert.Len(t, vrps, 6)
assert.Equal(t, vrps[0].(*VRP).ASN, uint32(65001))
assert.Equal(t, vrps[0].(*VRP).GetFlag(), uint8(FLAG_ADDED))
assert.Equal(t, vrps[1].(*VRP).ASN, uint32(65005))
assert.Equal(t, vrps[1].(*VRP).GetFlag(), uint8(FLAG_REMOVED))
assert.Equal(t, vrps[2].(*VRP).ASN, uint32(65003))
assert.Equal(t, vrps[2].(*VRP).GetFlag(), uint8(FLAG_ADDED))
assert.Equal(t, vrps[3].(*VRP).ASN, uint32(65004))
assert.Equal(t, vrps[3].(*VRP).GetFlag(), uint8(FLAG_REMOVED))
assert.Equal(t, vrps[4].(*VRP).ASN, uint32(65006))
assert.Equal(t, vrps[4].(*VRP).GetFlag(), uint8(FLAG_REMOVED))
assert.Equal(t, vrps[5].(*VRP).ASN, uint32(65007))
assert.Equal(t, vrps[5].(*VRP).GetFlag(), uint8(FLAG_ADDED))
}
func TestComputeDiffBGPSEC(t *testing.T) {
newVrps := []BgpsecKey{
{
ASN: 65003,
Pubkey: []byte("hurr"),
Ski: []byte("durr"),
},
{
Pubkey: []byte("abc"),
Ski: []byte("dce"),
ASN: 65002,
},
}
prevVrps := []BgpsecKey{
{
Pubkey: []byte("murr"),
Ski: []byte("durr"),
ASN: 65001,
},
{
Pubkey: []byte("abc"),
Ski: []byte("dce"),
ASN: 65002,
},
}
newVrpsSD, prevVrpsAsSD := make([]SendableData, 0), make([]SendableData, 0)
for _, v := range newVrps {
newVrpsSD = append(newVrpsSD, v.Copy())
}
for _, v := range prevVrps {
prevVrpsAsSD = append(prevVrpsAsSD, v.Copy())
}
added, removed, unchanged := ComputeDiff(newVrpsSD, prevVrpsAsSD, true)
assert.Len(t, added, 1)
assert.Len(t, removed, 1)
assert.Len(t, unchanged, 1)
assert.Equal(t, added[0].(*BgpsecKey).ASN, uint32(65003))
assert.Equal(t, removed[0].(*BgpsecKey).ASN, uint32(65001))
assert.Equal(t, unchanged[0].(*BgpsecKey).ASN, uint32(65002))
}
func TestVRPStructSize(t *testing.T) {
if a := runtime.GOARCH; a != "amd64" {
t.Skipf("skipping, running on %s but this test is hard-coded for amd64 architecture", a)
}
// This test verifies that the size of a VRP and its component structures
// do not change unexpectedly due to other code modifications.
//
// For reference, the tool structlayout can be used to examine struct sizes
// and structlayout-optimize to recommend ordering of members to minimize memory utilization.
// Whenever a constant is changed here, be sure to update the associated
// comment with the output of the tools.
//
// $ go install honnef.co/go/tools/cmd/structlayout@latest
// $ go install honnef.co/go/tools/cmd/structlayout-optimize@latest
const (
// $ structlayout -json . VRP
// VRP.Prefix.ip.addr.hi uint64: 0-8 (size 8, align 8)
// VRP.Prefix.ip.addr.lo uint64: 8-16 (size 8, align 8)
// VRP.Prefix.ip.z *internal/intern.Value: 16-24 (size 8, align 8)
// VRP.Prefix.bitsPlusOne uint8: 24-25 (size 1, align 1)
// padding: 25-32 (size 7, align 0)
// VRP.ASN uint32: 32-36 (size 4, align 4)
// VRP.MaxLen uint8: 36-37 (size 1, align 1)
// VRP.Flags uint8: 37-38 (size 1, align 1)
// padding: 38-40 (size 2, align 0)
//
// NOTE: we could actually reduce this to 32 if netip.Prefix
// were properly aligned. Ex:
// $ structlayout -json . VRP | structlayout-optimize
// VRP.Prefix struct: 0-24 (size 24, align 8)
// VRP.ASN uint32: 24-28 (size 4, align 4)
// VRP.MaxLen uint8: 28-29 (size 1, align 1)
// VRP.Flags uint8: 29-30 (size 1, align 1)
// padding: 30-32 (size 2, align 0)
//
vrpSize = 40
)
if diff := cmp.Diff(int(unsafe.Sizeof(VRP{})), vrpSize); diff != "" {
t.Fatalf("unexpected VRPs struct size (-want +got):\n%s", diff)
}
}