libnetwork/ipam: move PoolID.FromString() to a PoolIDFromString() func

This makes it easier to consume, without first having to create an empty
PoolID.

Performance is the same:

    BenchmarkPoolIDFromString-10   6100345   196.5 ns/op  112 B/op   3 allocs/op
    BenchmarkPoolIDFromString-10   6252750   192.0 ns/op  112 B/op   3 allocs/op

Note that I opted not to change the return-type to a pointer, as that seems
to perform less;

    BenchmarkPoolIDFromString-10   6252750   192.0 ns/op  112 B/op   3 allocs/op
    BenchmarkPoolIDFromString-10   5288682   226.6 ns/op  192 B/op   4 allocs/op

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
Sebastiaan van Stijn 2023-07-22 16:21:48 +02:00
parent 808fed550d
commit df03357d19
No known key found for this signature in database
GPG key ID: 76698F39D527CE8C
3 changed files with 54 additions and 46 deletions

View file

@ -117,8 +117,8 @@ func (a *Allocator) RequestPool(addressSpace, requestedPool, requestedSubPool st
// ReleasePool releases the address pool identified by the passed id
func (a *Allocator) ReleasePool(poolID string) error {
log.G(context.TODO()).Debugf("ReleasePool(%s)", poolID)
k := PoolID{}
if err := k.FromString(poolID); err != nil {
k, err := PoolIDFromString(poolID)
if err != nil {
return types.BadRequestErrorf("invalid pool id: %s", poolID)
}
@ -226,8 +226,8 @@ func (aSpace *addrSpace) allocatePredefinedPool(ipV6 bool) (netip.Prefix, error)
// RequestAddress returns an address from the specified pool ID
func (a *Allocator) RequestAddress(poolID string, prefAddress net.IP, opts map[string]string) (*net.IPNet, map[string]string, error) {
log.G(context.TODO()).Debugf("RequestAddress(%s, %v, %v)", poolID, prefAddress, opts)
k := PoolID{}
if err := k.FromString(poolID); err != nil {
k, err := PoolIDFromString(poolID)
if err != nil {
return nil, nil, types.BadRequestErrorf("invalid pool id: %s", poolID)
}
@ -286,8 +286,8 @@ func (aSpace *addrSpace) requestAddress(nw, sub netip.Prefix, prefAddress netip.
// ReleaseAddress releases the address from the specified pool ID
func (a *Allocator) ReleaseAddress(poolID string, address net.IP) error {
log.G(context.TODO()).Debugf("ReleaseAddress(%s, %v)", poolID, address)
k := PoolID{}
if err := k.FromString(poolID); err != nil {
k, err := PoolIDFromString(poolID)
if err != nil {
return types.BadRequestErrorf("invalid pool id: %s", poolID)
}

View file

@ -29,8 +29,7 @@ func TestKeyString(t *testing.T) {
t.Fatalf("Unexpected key string: %s", k.String())
}
k2 := &PoolID{}
err := k2.FromString(expected)
k2, err := PoolIDFromString(expected)
if err != nil {
t.Fatal(err)
}
@ -44,7 +43,7 @@ func TestKeyString(t *testing.T) {
t.Fatalf("Unexpected key string: %s", k.String())
}
err = k2.FromString(expected)
k2, err = PoolIDFromString(expected)
if err != nil {
t.Fatal(err)
}
@ -133,7 +132,6 @@ func TestAddReleasePoolID(t *testing.T) {
a, err := NewAllocator(ipamutils.GetLocalScopeDefaultNetworks(), ipamutils.GetGlobalScopeDefaultNetworks())
assert.NilError(t, err)
var k0, k1 PoolID
_, err = a.getAddrSpace(localAddressSpace)
if err != nil {
t.Fatal(err)
@ -143,7 +141,8 @@ func TestAddReleasePoolID(t *testing.T) {
if err != nil {
t.Fatalf("Unexpected failure in adding pool: %v", err)
}
if err := k0.FromString(pid0); err != nil {
k0, err := PoolIDFromString(pid0)
if err != nil {
t.Fatal(err)
}
@ -160,7 +159,8 @@ func TestAddReleasePoolID(t *testing.T) {
if err != nil {
t.Fatalf("Unexpected failure in adding sub pool: %v", err)
}
if err := k1.FromString(pid1); err != nil {
k1, err := PoolIDFromString(pid1)
if err != nil {
t.Fatal(err)
}
@ -1279,11 +1279,25 @@ func TestParallelPredefinedRequest5(t *testing.T) {
func BenchmarkPoolIDToString(b *testing.B) {
const poolIDString = "default/172.27.0.0/16/172.27.3.0/24"
k := PoolID{}
_ = k.FromString(poolIDString)
k, err := PoolIDFromString(poolIDString)
if err != nil {
b.Fatal(err)
}
b.ReportAllocs()
for i := 0; i < b.N; i++ {
_ = k.String()
}
}
func BenchmarkPoolIDFromString(b *testing.B) {
const poolIDString = "default/172.27.0.0/16/172.27.3.0/24"
b.ReportAllocs()
for i := 0; i < b.N; i++ {
_, err := PoolIDFromString(poolIDString)
if err != nil {
b.Fatal(err)
}
}
}

View file

@ -43,6 +43,32 @@ type addrSpace struct {
sync.Mutex
}
// PoolIDFromString creates a new PoolID and populates the SubnetKey object
// reading it from the given string.
func PoolIDFromString(str string) (pID PoolID, err error) {
if str == "" {
return pID, types.BadRequestErrorf("invalid string form for subnetkey: %s", str)
}
p := strings.Split(str, "/")
if len(p) != 3 && len(p) != 5 {
return pID, types.BadRequestErrorf("invalid string form for subnetkey: %s", str)
}
pID.AddressSpace = p[0]
pID.Subnet, err = netip.ParsePrefix(p[1] + "/" + p[2])
if err != nil {
return pID, types.BadRequestErrorf("%v", err)
}
if len(p) == 5 {
pID.ChildSubnet, err = netip.ParsePrefix(p[3] + "/" + p[4])
if err != nil {
return pID, types.BadRequestErrorf("%v", err)
}
}
return pID, nil
}
// String returns the string form of the SubnetKey object
func (s *PoolID) String() string {
if s.ChildSubnet == (netip.Prefix{}) {
@ -52,38 +78,6 @@ func (s *PoolID) String() string {
}
}
// FromString populates the SubnetKey object reading it from string
func (s *PoolID) FromString(str string) error {
if str == "" || !strings.Contains(str, "/") {
return types.BadRequestErrorf("invalid string form for subnetkey: %s", str)
}
p := strings.Split(str, "/")
if len(p) != 3 && len(p) != 5 {
return types.BadRequestErrorf("invalid string form for subnetkey: %s", str)
}
sub, err := netip.ParsePrefix(p[1] + "/" + p[2])
if err != nil {
return types.BadRequestErrorf("%v", err)
}
var child netip.Prefix
if len(p) == 5 {
child, err = netip.ParsePrefix(p[3] + "/" + p[4])
if err != nil {
return types.BadRequestErrorf("%v", err)
}
}
*s = PoolID{
AddressSpace: p[0],
SubnetKey: SubnetKey{
Subnet: sub,
ChildSubnet: child,
},
}
return nil
}
// String returns the string form of the PoolData object
func (p *PoolData) String() string {
return fmt.Sprintf("PoolData[Children: %d]", len(p.children))