Skip to content

Commit

Permalink
e2e: fix duplicate random cidr
Browse files Browse the repository at this point in the history
Signed-off-by: zhangzujian <[email protected]>
  • Loading branch information
zhangzujian committed Jan 2, 2025
1 parent ac7cf40 commit b69f500
Showing 1 changed file with 97 additions and 39 deletions.
136 changes: 97 additions & 39 deletions test/e2e/framework/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ import (
"net"
"sort"
"strings"
"sync"

"github.com/scylladb/go-set/strset"
"k8s.io/utils/ptr"
"k8s.io/utils/set"

"github.com/onsi/ginkgo/v2"

Expand All @@ -25,42 +27,84 @@ func RandomSuffix() string {
return fmt.Sprintf("%d%04d%04d", ginkgo.GinkgoParallelProcess(), rand.IntN(10000), rand.IntN(10000))
}

func RandomCIDR(family string) string {
fnIPv4 := func() string {
cidr := net.IPNet{
IP: net.ParseIP("10.0.0.0").To4(),
Mask: net.CIDRMask(24, 32),
var (
randCIDRSeedLock4 sync.Mutex
randCIDRSeedLock6 sync.Mutex

usedRandCIDRSeeds4 = set.New[byte]()
usedRandCIDRSeeds6 = set.New[uint16]()
)

func randomCIDR4(seed *byte) string {
ginkgo.GinkgoHelper()

if seed == nil {
randCIDRSeedLock4.Lock()
defer randCIDRSeedLock4.Unlock()
for usedRandCIDRSeeds4.Len() < 0xff+1 {
seed = ptr.To(byte(rand.IntN(0xff + 1)))
if !usedRandCIDRSeeds4.Has(*seed) {
usedRandCIDRSeeds4.Insert(*seed)
break
}
}
cidr.IP[1] = 0xf0 | byte(ginkgo.GinkgoParallelProcess())
cidr.IP[2] = byte(rand.IntN(0xff + 1))
return cidr.String()
ExpectNotNil(seed, "failed to generate random ipv4 CIDR seed")
}

fnIPv6 := func() string {
cidr := net.IPNet{
IP: net.ParseIP("fc00:10:ff::").To16(),
Mask: net.CIDRMask(96, 128),
cidr := net.IPNet{
IP: net.ParseIP("10.0.0.0").To4(),
Mask: net.CIDRMask(24, 32),
}
cidr.IP[1] = 0xf0 | byte(ginkgo.GinkgoParallelProcess())
cidr.IP[2] = *seed
return cidr.String()
}

func randomCIDR6(seed *uint16) string {
ginkgo.GinkgoHelper()

if seed == nil {
randCIDRSeedLock6.Lock()
defer randCIDRSeedLock6.Unlock()
for usedRandCIDRSeeds6.Len() < 0xffff+1 {
seed = ptr.To(uint16(rand.IntN(0xffff + 1)))
if !usedRandCIDRSeeds6.Has(*seed) {
usedRandCIDRSeeds6.Insert(*seed)
break
}
}
cidr.IP[9] = byte(ginkgo.GinkgoParallelProcess())
cidr.IP[10] = byte(rand.IntN(0xff + 1))
cidr.IP[11] = byte(rand.IntN(0xff + 1))
return cidr.String()
ExpectNotNil(seed, "failed to generate random ipv4 CIDR seed")
}

cidr := net.IPNet{
IP: net.ParseIP("fc00:10:ff::").To16(),
Mask: net.CIDRMask(96, 128),
}
cidr.IP[9] = byte(ginkgo.GinkgoParallelProcess())
cidr.IP[10] = byte((*seed) >> 8)
cidr.IP[11] = byte((*seed) & 0xff)
return cidr.String()
}

func RandomCIDR(family string) string {
ginkgo.GinkgoHelper()

switch family {
case IPv4:
return fnIPv4()
return randomCIDR4(nil)
case IPv6:
return fnIPv6()
return randomCIDR6(nil)
case Dual:
return fnIPv4() + "," + fnIPv6()
return randomCIDR4(nil) + "," + randomCIDR6(nil)
default:
Failf("invalid ip family: %q", family)
return ""
}
}

func sortIPs(ips []string) {
ginkgo.GinkgoHelper()

sort.Slice(ips, func(i, j int) bool {
x, err := ipam.NewIP(ips[i])
ExpectNoError(err)
Expand All @@ -72,6 +116,8 @@ func sortIPs(ips []string) {

// ipv4/ipv6 only
func RandomExcludeIPs(cidr string, count int) []string {
ginkgo.GinkgoHelper()

if cidr == "" || count == 0 {
return nil
}
Expand Down Expand Up @@ -101,21 +147,23 @@ func RandomExcludeIPs(cidr string, count int) []string {

// ipv4/ipv6 only
func randomSortedIPs(cidr string, count int, sort bool) []string {
ginkgo.GinkgoHelper()

if cidr == "" {
return nil
}

_, ipNet, err := net.ParseCIDR(cidr)
ExpectNoError(err)

set := strset.NewWithSize(count)
s := set.New[string]()
r := ipam.NewIPRangeFromCIDR(*ipNet)
r = ipam.NewIPRange(r.Start().Add(2), r.End().Sub(1))
for set.Size() != count {
set.Add(r.Random().String())
for s.Len() != count {
s.Insert(r.Random().String())
}

ips := set.List()
ips := s.UnsortedList()
if sort {
sortIPs(ips)
}
Expand All @@ -124,6 +172,8 @@ func randomSortedIPs(cidr string, count int, sort bool) []string {
}

func RandomIPs(cidr, sep string, count int) string {
ginkgo.GinkgoHelper()

cidrV4, cidrV6 := util.SplitStringIP(cidr)
ipsV4 := randomSortedIPs(cidrV4, count, false)
ipsV6 := randomSortedIPs(cidrV6, count, false)
Expand All @@ -145,6 +195,8 @@ func RandomIPs(cidr, sep string, count int) string {

// ipv4/ipv6 only
func randomPool(cidr string, count int) []string {
ginkgo.GinkgoHelper()

if cidr == "" || count == 0 {
return nil
}
Expand All @@ -157,8 +209,8 @@ func randomPool(cidr string, count int) []string {

ones, bits := ipNet.Mask.Size()
rl := ipam.NewEmptyIPRangeList()
set := strset.NewWithSize(count)
for set.Size() != count/4 {
s := set.New[string]()
for s.Len() != count/4 {
prefix := (ones+bits)/2 + rand.IntN((bits-ones)/2+1)
_, ipNet, err = net.ParseCIDR(fmt.Sprintf("%s/%d", r.Random(), prefix))
ExpectNoError(err)
Expand All @@ -170,26 +222,26 @@ func randomPool(cidr string, count int) []string {
}

rl = rl.MergeRange(ipam.NewIPRange(start, end))
set.Add(ipNet.String())
s.Insert(ipNet.String())
}

count -= set.Size()
count -= s.Len()
m := count / 3 // <IP1>..<IP2>
n := count - m // <IP>
ips := make([]ipam.IP, 0, m*2+n)
ipSet := strset.NewWithSize(cap(ips))
ipSet := set.New[string]()
for len(ips) != cap(ips) {
ip := r.Random()
if rl.Contains(ip) {
continue
}

s := ip.String()
if ipSet.Has(s) {
ipStr := ip.String()
if ipSet.Has(ipStr) {
continue
}
ips = append(ips, ip)
ipSet.Add(s)
ipSet.Insert(ipStr)
}
sort.Slice(ips, func(i, j int) bool { return ips[i].LessThan(ips[j]) })

Expand All @@ -201,37 +253,43 @@ func randomPool(cidr string, count int) []string {
n1, _ := rl.Find(ips[x])
n2, _ := rl.Find(ips[y])
if n1 == n2 && ips[x].LessThan(ips[y]) {
set.Add(fmt.Sprintf("%s..%s", ips[x].String(), ips[y].String()))
s.Insert(fmt.Sprintf("%s..%s", ips[x].String(), ips[y].String()))
i, k = i+1, k+2
continue
}
}

if j != n {
set.Add(ips[k%len(ips)].String())
s.Insert(ips[k%len(ips)].String())
j, k = j+1, k+1
}
}

return set.List()
return s.UnsortedList()
}

func RandomIPPool(cidr string, count int) []string {
ginkgo.GinkgoHelper()

cidrV4, cidrV6 := util.SplitStringIP(cidr)
ipsV4, ipsV6 := randomPool(cidrV4, count), randomPool(cidrV6, count)
set := strset.NewWithSize(len(cidrV4) + len(cidrV6))
set.Add(ipsV4...)
set.Add(ipsV6...)
return set.List()
s := set.New[string]()
s.Insert(ipsV4...)
s.Insert(ipsV6...)
return s.UnsortedList()
}

func PrevIP(ip string) string {
ginkgo.GinkgoHelper()

v, err := ipam.NewIP(ip)
ExpectNoError(err)
return v.Sub(1).String()
}

func NextIP(ip string) string {
ginkgo.GinkgoHelper()

v, err := ipam.NewIP(ip)
ExpectNoError(err)
return v.Add(1).String()
Expand Down

0 comments on commit b69f500

Please sign in to comment.