Skip to content

Commit

Permalink
Enable use of multiple point2pointipam chain elements
Browse files Browse the repository at this point in the history
Minor shift so that multiple point2pointipam chain elements
may be used in a chain to allow assigning multiple IPs

Signed-off-by: Ed Warnicke <[email protected]>
  • Loading branch information
edwarnicke committed May 9, 2021
1 parent 1c92df8 commit d410975
Show file tree
Hide file tree
Showing 4 changed files with 180 additions and 20 deletions.
73 changes: 73 additions & 0 deletions pkg/networkservice/ipam/point2pointipam/connectionInfoMap.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2021 Doc.ai and/or its affiliates.
// Copyright (c) 2020 Cisco and/or its affiliates.
//
// SPDX-License-Identifier: Apache-2.0
//
Expand All @@ -14,23 +14,14 @@
// See the License for the specific language governing permissions and
// limitations under the License.

// Package clientmap provides a sync.Map for networkservicemesh.NetworkServiceClients and a refcounted sync.Map
package point2pointipam

import (
"context"

"github.com/networkservicemesh/sdk/pkg/networkservice/utils/metadata"
"sync"
)

type keyType struct{}

func storeConnInfo(ctx context.Context, connInfo *connectionInfo) {
metadata.Map(ctx, false).Store(keyType{}, connInfo)
}
//go:generate go-syncmap -output connectionInfoMap.gen.go -type Map<string,*connectionInfo>

func loadConnInfo(ctx context.Context) (*connectionInfo, bool) {
if raw, ok := metadata.Map(ctx, false).Load(keyType{}); ok {
return raw.(*connectionInfo), true
}
return nil, false
}
// Map - sync.Map with key == string and value == networkservice.NetworkServiceClient
type Map sync.Map
31 changes: 26 additions & 5 deletions pkg/networkservice/ipam/point2pointipam/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import (
)

type ipamServer struct {
Map
ipPools []*ippool.IPPool
prefixes []*net.IPNet
once sync.Once
Expand Down Expand Up @@ -90,10 +91,12 @@ func (s *ipamServer) Request(ctx context.Context, request *networkservice.Networ

excludeIP4, excludeIP6 := exclude(ipContext.GetExcludedPrefixes()...)

connInfo, loaded := loadConnInfo(ctx)
connInfo, loaded := s.Load(conn.GetId())
var err error
if loaded && (connInfo.shouldUpdate(excludeIP4) || connInfo.shouldUpdate(excludeIP6)) {
// some of the existing addresses are excluded
deleteAddr(&ipContext.SrcIpAddrs, connInfo.srcAddr)
deleteAddr(&ipContext.DstIpAddrs, connInfo.dstAddr)
deleteRoute(&ipContext.SrcRoutes, connInfo.dstAddr)
deleteRoute(&ipContext.DstRoutes, connInfo.srcAddr)
s.free(connInfo)
Expand All @@ -103,13 +106,13 @@ func (s *ipamServer) Request(ctx context.Context, request *networkservice.Networ
if connInfo, err = s.getP2PAddrs(excludeIP4, excludeIP6); err != nil {
return nil, err
}
storeConnInfo(ctx, connInfo)
s.Store(conn.GetId(), connInfo)
}

ipContext.SrcIpAddrs = []string{connInfo.srcAddr}
addAddr(&ipContext.SrcIpAddrs, connInfo.srcAddr)
addRoute(&ipContext.SrcRoutes, connInfo.dstAddr)

ipContext.DstIpAddrs = []string{connInfo.dstAddr}
addAddr(&ipContext.DstIpAddrs, connInfo.dstAddr)
addRoute(&ipContext.DstRoutes, connInfo.srcAddr)

conn, err = next.Server(ctx).Request(ctx, request)
Expand Down Expand Up @@ -157,13 +160,31 @@ func addRoute(routes *[]*networkservice.Route, prefix string) {
})
}

func deleteAddr(addrs *[]string, addr string) {
for i, a := range *addrs {
if a == addr {
*addrs = append((*addrs)[:i], (*addrs)[i+1:]...)
return
}
}
}

func addAddr(addrs *[]string, addr string) {
for _, a := range *addrs {
if a == addr {
return
}
}
*addrs = append(*addrs, addr)
}

func (s *ipamServer) Close(ctx context.Context, conn *networkservice.Connection) (_ *empty.Empty, err error) {
s.once.Do(s.init)
if s.initErr != nil {
return nil, s.initErr
}

if connInfo, ok := loadConnInfo(ctx); ok {
if connInfo, ok := s.Load(conn.GetId()); ok {
s.free(connInfo)
}

Expand Down
75 changes: 75 additions & 0 deletions pkg/networkservice/ipam/point2pointipam/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"net"
"testing"

"github.com/networkservicemesh/sdk/pkg/networkservice/core/chain"
"github.com/stretchr/testify/require"

"github.com/networkservicemesh/api/pkg/api/networkservice"
Expand Down Expand Up @@ -66,6 +67,17 @@ func validateConn(t *testing.T, conn *networkservice.Connection, dst, src string
})
}

func validateConns(t *testing.T, conn *networkservice.Connection, dsts, srcs []string) {
for i, dst := range dsts {
require.Equal(t, conn.Context.IpContext.DstIpAddrs[i], dst)
require.Equal(t, conn.Context.IpContext.SrcRoutes[i].Prefix, dst)
}
for i, src := range srcs {
require.Equal(t, conn.Context.IpContext.SrcIpAddrs[i], src)
require.Equal(t, conn.Context.IpContext.DstRoutes[i].Prefix, src)
}
}

//nolint:dupl
func TestServer(t *testing.T) {
_, ipNet, err := net.ParseCIDR("192.168.3.4/16")
Expand Down Expand Up @@ -347,3 +359,66 @@ func TestRefreshNextError(t *testing.T) {
require.NoError(t, err)
validateConn(t, conn, "192.168.0.2/32", "192.168.0.3/32")
}

//nolint:dupl
func TestServers(t *testing.T) {
_, ipNet1, err := net.ParseCIDR("192.168.3.4/16")
require.NoError(t, err)
_, ipNet2, err := net.ParseCIDR("fd00::/8")
require.NoError(t, err)

srv := chain.NewNetworkServiceServer(
newIpamServer(ipNet1),
newIpamServer(ipNet2),
)

conn1, err := srv.Request(context.Background(), newRequest())
require.NoError(t, err)
validateConns(t, conn1, []string{"192.168.0.0/32", "fd00::/128"}, []string{"192.168.0.1/32", "fd00::1/128"})

conn2, err := srv.Request(context.Background(), newRequest())
require.NoError(t, err)
validateConns(t, conn2, []string{"192.168.0.2/32", "fd00::2/128"}, []string{"192.168.0.3/32", "fd00::3/128"})

_, err = srv.Close(context.Background(), conn1)
require.NoError(t, err)

conn3, err := srv.Request(context.Background(), newRequest())
require.NoError(t, err)
validateConns(t, conn3, []string{"192.168.0.0/32", "fd00::/128"}, []string{"192.168.0.1/32", "fd00::1/128"})

conn4, err := srv.Request(context.Background(), newRequest())
require.NoError(t, err)
validateConns(t, conn4, []string{"192.168.0.4/32", "fd00::4/128"}, []string{"192.168.0.5/32", "fd00::5/128"})
}

//nolint:dupl
func TestRefreshRequestMultiServer(t *testing.T) {
_, ipNet1, err := net.ParseCIDR("192.168.3.4/16")
require.NoError(t, err)
_, ipNet2, err := net.ParseCIDR("fe80::/64")
require.NoError(t, err)

srv := chain.NewNetworkServiceServer(
newIpamServer(ipNet1),
newIpamServer(ipNet2),
)

req := newRequest()
req.Connection.Context.IpContext.ExcludedPrefixes = []string{"192.168.0.1/32", "fe80::1/128"}
conn, err := srv.Request(context.Background(), req)
require.NoError(t, err)
validateConns(t, conn, []string{"192.168.0.0/32", "fe80::/128"}, []string{"192.168.0.2/32", "fe80::2/128"})

req = newRequest()
req.Connection = conn
conn, err = srv.Request(context.Background(), req)
require.NoError(t, err)
validateConns(t, conn, []string{"192.168.0.0/32", "fe80::/128"}, []string{"192.168.0.2/32", "fe80::2/128"})

req.Connection = conn.Clone()
req.Connection.Context.IpContext.ExcludedPrefixes = []string{"192.168.0.1/30", "fe80::1/126"}
conn, err = srv.Request(context.Background(), req)
require.NoError(t, err)
validateConns(t, conn, []string{"192.168.0.4/32", "fe80::4/128"}, []string{"192.168.0.5/32", "fe80::5/128"})
}

0 comments on commit d410975

Please sign in to comment.