Skip to content

Commit

Permalink
fix: Filter mechanism chain element works incorrectly in remote case (n…
Browse files Browse the repository at this point in the history
…etworkservicemesh#575)

Signed-off-by: denis-tingajkin <denis.tingajkin@xored.com>
  • Loading branch information
denis-tingaikin authored Nov 6, 2020
1 parent 3216266 commit 39537ac
Show file tree
Hide file tree
Showing 5 changed files with 227 additions and 5 deletions.
94 changes: 94 additions & 0 deletions pkg/networkservice/common/filtermechanisms/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
## Intro

Package `filtermechanisms` filters out remote mechanisms if communicating by remote url
filters out local mechanisms otherwise. Can be used with eNSMGR.

## Options

Supported option `WithExternalThreshold` that sets max path segments count for eNSMgrs.

## Examples
Note: **Is local** true when path segment index less than localThreshold and nsmgr knows NSE url

1. Local:
```
Scheme: nsc-->NSMgr-->cross-nse-->NSMgr-->nse
NSMgr knows nse: true
filterMechanismsServer.localThreshold: 5
len(request.Connection.Path.PathSegments): 4
Is local: true
```

2. Local eNSM:
```
Scheme: nsc-->eNSMgr-->nse
eNSMgr knows nse: true
filterMechanismsServer.localThreshold: 3
len(request.Connection.Path.PathSegments): 2
Is local: true
```

3. Remote eNSM:
```
Scheme: nsc-->eNSMgr1-->eNSMgr2-->nse
eNSMgr1:
knows nse: false
filterMechanismsServer.localThreshold = 3
len(request.Connection.Path.PathSegments) = 2
Is local: false
eNSMgr2:
knows nse: true
filterMechanismsServer.localThreshold = 3
len(request.Connection.Path.PathSegments) = 3
Is local: false
```

4. Remote NSMgr + eNSMGR
```
Scheme: nsc-->NSMgr1-->cross-nse1-->NSMgr1-->eNSMgr1-->nse
NSMgr1:
knows nse: false
filterMechanismsServer.localThreshold = 5
len(request.Connection.Path.PathSegments) = 4
Is local: false
eNSMgr1:
knows nse: true
filterMechanismsServer.localThreshold = 3
len(request.Connection.Path.PathSegments) = 5
Is local: false
```

5. Remote eNSMGR + NSMgr
```
Scheme: nsc-->eNSMgr1-->NSMgr1-->cross-nse1-->NSMgr1-->eNSMgr2-->nse
eNSMgr1:
knows nse: false
filterMechanismsServer.localThreshold = 3
len(request.Connection.Path.PathSegments) = 2
Is local: false
NSMgr1:
knows nse: true
filterMechanismsServer.localThreshold = 5
len(request.Connection.Path.PathSegments) = 5
Is local: false
```

6. Remote

```
Scheme: nsc-->NSMgr1-->cross-nse1-->NSMgr1-->NSMgr2-->cross-nse2-->NSMgr2-->nse
NSMgr2:
knows nse: false
filterMechanismsServer.localThreshold = 5
len(request.Connection.Path.PathSegments) = 4
Is local: false
NSMgr1:
knows nse: true
filterMechanismsServer.localThreshold = 5
len(request.Connection.Path.PathSegments) = 7
Is local: false
```
23 changes: 23 additions & 0 deletions pkg/networkservice/common/filtermechanisms/const.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright (c) 2020 Doc.ai and/or its affiliates.
//
// SPDX-License-Identifier: Apache-2.0
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at:
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package filtermechanisms

const (
// See at examples section in README.md
defaultThreshold = 5
externalThreshold = 3
)
27 changes: 27 additions & 0 deletions pkg/networkservice/common/filtermechanisms/options.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright (c) 2020 Doc.ai and/or its affiliates.
//
// SPDX-License-Identifier: Apache-2.0
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at:
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package filtermechanisms

// Option is option applier for filterMechanismsServer
type Option func(server *filterMechanismsServer)

// WithExternalThreshold configures filterMechanismsServer to work with external NSMgr.
func WithExternalThreshold() Option {
return Option(func(server *filterMechanismsServer) {
server.localThreshold = externalThreshold
})
}
20 changes: 15 additions & 5 deletions pkg/networkservice/common/filtermechanisms/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,21 +33,31 @@ import (
)

type filterMechanismsServer struct {
urls endpointurls.Set
urls endpointurls.Set
localThreshold int
}

// NewServer - filters out remote mechanisms if connection is received from a unix file socket, otherwise filters
// out local mechanisms
func NewServer(registryServer *registry.NetworkServiceEndpointRegistryServer) networkservice.NetworkServiceServer {
result := &filterMechanismsServer{}
// out local mechanisms.
func NewServer(registryServer *registry.NetworkServiceEndpointRegistryServer, options ...Option) networkservice.NetworkServiceServer {
result := &filterMechanismsServer{
localThreshold: defaultThreshold,
}
for _, applyOption := range options {
applyOption(result)
}
*registryServer = endpointurls.NewNetworkServiceEndpointRegistryServer(&result.urls)
return result
}

func (f *filterMechanismsServer) Request(ctx context.Context, request *networkservice.NetworkServiceRequest) (*networkservice.Connection, error) {
u := clienturlctx.ClientURL(ctx)

if _, ok := f.urls.Load(*u); ok {
request.MechanismPreferences = filterMechanismsByCls(request.GetMechanismPreferences(), cls.LOCAL)
filteredMechanisms := filterMechanismsByCls(request.GetMechanismPreferences(), cls.LOCAL)
if len(filteredMechanisms) > 0 {
request.MechanismPreferences = filteredMechanisms
}
} else {
request.MechanismPreferences = filterMechanismsByCls(request.GetMechanismPreferences(), cls.REMOTE)
}
Expand Down
68 changes: 68 additions & 0 deletions pkg/networkservice/common/filtermechanisms/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import (
"net/url"
"testing"

"github.com/networkservicemesh/sdk/pkg/networkservice/core/next"

"github.com/networkservicemesh/api/pkg/api/networkservice"
"github.com/networkservicemesh/api/pkg/api/networkservice/mechanisms/cls"
"github.com/networkservicemesh/api/pkg/api/networkservice/mechanisms/kernel"
Expand All @@ -34,6 +36,72 @@ import (
"github.com/networkservicemesh/sdk/pkg/tools/clienturlctx"
)

func TestFilterMechanisms_RemoteExternal(t *testing.T) {
request := &networkservice.NetworkServiceRequest{
MechanismPreferences: []*networkservice.Mechanism{
{
Cls: cls.REMOTE,
Type: vxlan.MECHANISM,
},
{
Cls: cls.LOCAL,
Type: kernel.MECHANISM,
},
},
Connection: &networkservice.Connection{
Path: &networkservice.Path{
PathSegments: make([]*networkservice.PathSegment, 3),
},
},
}

var localRegistryServer registry.NetworkServiceEndpointRegistryServer
localServer := filtermechanisms.NewServer(&localRegistryServer)
var remoteRegistryServer registry.NetworkServiceEndpointRegistryServer
remoteServer := filtermechanisms.NewServer(&remoteRegistryServer, filtermechanisms.WithExternalThreshold())
u := &url.URL{Path: "test"}
_, _ = remoteRegistryServer.Register(context.Background(), &registry.NetworkServiceEndpoint{
Url: u.String(),
})
_, err := next.NewNetworkServiceServer(localServer, remoteServer).Request(clienturlctx.WithClientURL(context.Background(), u), request)
require.NoError(t, err)
require.Len(t, request.MechanismPreferences, 1)
require.Equal(t, cls.REMOTE, request.MechanismPreferences[0].Cls)
}

func TestFilterMechanisms_Remote(t *testing.T) {
request := &networkservice.NetworkServiceRequest{
MechanismPreferences: []*networkservice.Mechanism{
{
Cls: cls.REMOTE,
Type: vxlan.MECHANISM,
},
{
Cls: cls.LOCAL,
Type: kernel.MECHANISM,
},
},
Connection: &networkservice.Connection{
Path: &networkservice.Path{
PathSegments: make([]*networkservice.PathSegment, 5),
},
},
}

var localRegistryServer registry.NetworkServiceEndpointRegistryServer
localServer := filtermechanisms.NewServer(&localRegistryServer)
var remoteRegistryServer registry.NetworkServiceEndpointRegistryServer
remoteServer := filtermechanisms.NewServer(&remoteRegistryServer)
u := &url.URL{Path: "test"}
_, _ = remoteRegistryServer.Register(context.Background(), &registry.NetworkServiceEndpoint{
Url: u.String(),
})
_, err := next.NewNetworkServiceServer(localServer, remoteServer).Request(clienturlctx.WithClientURL(context.Background(), u), request)
require.NoError(t, err)
require.Len(t, request.MechanismPreferences, 1)
require.Equal(t, cls.REMOTE, request.MechanismPreferences[0].Cls)
}

func TestFilterMechanismsServer_Request(t *testing.T) {
request := func() *networkservice.NetworkServiceRequest {
return &networkservice.NetworkServiceRequest{
Expand Down

0 comments on commit 39537ac

Please sign in to comment.