Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

remote-vlan-nse fix; Singlepoint IPAM should not allocate broadcast address #1431

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions pkg/networkservice/ipam/singlepointipam/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Single point IPAM

This chain element is used to provide IPAM functionality for the nse-remote-vlan.

Per request allocates a single IP address in the given subnet and provides static routes. Request can set some exclude IP prefixes for the allocated IP.

The first IP address from the specified IP range and the broadcast IPv4 address will be witheld.
8 changes: 8 additions & 0 deletions pkg/networkservice/ipam/singlepointipam/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import (
"github.com/networkservicemesh/api/pkg/api/networkservice"

"github.com/networkservicemesh/sdk/pkg/networkservice/core/next"
"github.com/networkservicemesh/sdk/pkg/tools/cidr"
"github.com/networkservicemesh/sdk/pkg/tools/ippool"
)

Expand Down Expand Up @@ -78,6 +79,13 @@ func (sipam *singlePIpam) init() {
mask := fmt.Sprintf("/%d", ones)
sipam.masks = append(sipam.masks, mask)
ipPool := ippool.NewWithNet(prefix)
if prefix.IP.To4() != nil {
// Remove the broadcast address from the pool
_, sipam.initErr = ipPool.PullIP(cidr.BroadcastAddress(prefix))
if sipam.initErr != nil {
return
}
}
sipam.ipPools = append(sipam.ipPools, ipPool)
}
}
Expand Down
45 changes: 34 additions & 11 deletions pkg/networkservice/ipam/singlepointipam/server_test.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Copyright (c) 2020-2021 Doc.ai and/or its affiliates.
// Copyright (c) 2020-2022 Nordix and its affiliates.
// Copyright (c) 2020-2023 Nordix and its affiliates.
//
// SPDX-License-Identifier: Apache-2.0
//
Expand Down Expand Up @@ -201,20 +201,43 @@ func TestExclude128PrefixIPv6(t *testing.T) {
validateConn(t, conn3, "fe80::1:6/112")
}

func TestBroadCastIP(t *testing.T) {
_, ipNet, err := net.ParseCIDR("10.143.248.96/28")
require.NoError(t, err)

srv := newIpamServer(ipNet)

conn1, err := srv.Request(context.Background(), newRequest())
require.NoError(t, err)
validateConn(t, conn1, "10.143.248.97/28")

conn2, err := srv.Request(context.Background(), newRequest())
require.NoError(t, err)
validateConn(t, conn2, "10.143.248.98/28")

for i := 0; i < 11; i++ {
_, err = srv.Request(context.Background(), newRequest())
require.NoError(t, err)
}

conn3, err := srv.Request(context.Background(), newRequest())
require.NoError(t, err)
validateConn(t, conn3, "10.143.248.110/28")

// Broadcast
_, err = srv.Request(context.Background(), newRequest())
require.EqualError(t, err, "IPPool is empty")
}

func TestOutOfIPs(t *testing.T) {
_, ipNet, err := net.ParseCIDR("192.168.1.2/31")
require.NoError(t, err)

srv := newIpamServer(ipNet)

req1 := newRequest()
conn1, err := srv.Request(context.Background(), req1)
require.NoError(t, err)
validateConn(t, conn1, "192.168.1.3/31")

req2 := newRequest()
_, err = srv.Request(context.Background(), req2)
require.Error(t, err)
_, err = srv.Request(context.Background(), req1)
require.EqualError(t, err, "IPPool is empty")
}

func TestOutOfIPsIPv6(t *testing.T) {
Expand All @@ -230,7 +253,7 @@ func TestOutOfIPsIPv6(t *testing.T) {

req2 := newRequest()
_, err = srv.Request(context.Background(), req2)
require.Error(t, err)
require.EqualError(t, err, "IPPool is empty")
}

func TestAllIPsExcluded(t *testing.T) {
Expand All @@ -243,7 +266,7 @@ func TestAllIPsExcluded(t *testing.T) {
req1.Connection.Context.IpContext.ExcludedPrefixes = []string{"192.168.1.2/30"}
conn1, err := srv.Request(context.Background(), req1)
require.Nil(t, conn1)
require.Error(t, err)
require.EqualError(t, err, "IPPool is empty")
}

func TestAllIPsExcludedIPv6(t *testing.T) {
Expand All @@ -256,7 +279,7 @@ func TestAllIPsExcludedIPv6(t *testing.T) {
req1.Connection.Context.IpContext.ExcludedPrefixes = []string{"fe80::1:2/126"}
conn1, err := srv.Request(context.Background(), req1)
require.Nil(t, conn1)
require.Error(t, err)
require.EqualError(t, err, "IPPool is empty")
}

//nolint:dupl
Expand Down