Skip to content

Commit

Permalink
add xconnectns, l2ovsconnect and mechanism chain elements
Browse files Browse the repository at this point in the history
Signed-off-by: Periyasamy Palanisamy <periyasamy.palanisamy@est.tech>
  • Loading branch information
pperiyasamy committed May 31, 2021
1 parent 4982523 commit 8ae1a4a
Show file tree
Hide file tree
Showing 15 changed files with 2,259 additions and 0 deletions.
14 changes: 14 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
module github.com/networkservicemesh/sdk-ovs

go 1.16

require (
github.com/Mellanox/sriovnet v1.0.2
github.com/golang/protobuf v1.4.3
github.com/networkservicemesh/api v0.0.0-20210527182901-ea452d7e044c
github.com/networkservicemesh/sdk v0.0.0-20210528062336-1864bcaad34d
github.com/networkservicemesh/sdk-kernel v0.0.0-20210528062716-20d39a8e1bc9
github.com/networkservicemesh/sdk-sriov v0.0.0-20210523200748-80fab22ffef1
github.com/ovn-org/ovn-kubernetes/go-controller v0.0.0-20210526211758-faa6b74b102b
github.com/pkg/errors v0.9.1
github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852
google.golang.org/grpc v1.35.0
k8s.io/utils v0.0.0-20201110183641-67b214c5f920
)
969 changes: 969 additions & 0 deletions go.sum

Large diffs are not rendered by default.

200 changes: 200 additions & 0 deletions pkg/networkservice/chains/xconnectns/server.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
// Copyright (c) 2021 Nordix Foundation.
//
// 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 xconnectns

import (
"context"
"net"
"net/url"
"sync"

"github.com/networkservicemesh/api/pkg/api/networkservice"
kernelmech "github.com/networkservicemesh/api/pkg/api/networkservice/mechanisms/kernel"
vxlanmech "github.com/networkservicemesh/api/pkg/api/networkservice/mechanisms/vxlan"
"github.com/networkservicemesh/sdk-kernel/pkg/kernel/networkservice/connectioncontextkernel"
"github.com/networkservicemesh/sdk-kernel/pkg/kernel/networkservice/inject"
"github.com/networkservicemesh/sdk-kernel/pkg/kernel/networkservice/rename"
"github.com/networkservicemesh/sdk-sriov/pkg/networkservice/common/resourcepool"
"github.com/networkservicemesh/sdk-sriov/pkg/sriov"
"github.com/networkservicemesh/sdk-sriov/pkg/sriov/config"
"github.com/networkservicemesh/sdk/pkg/networkservice/chains/client"
"github.com/networkservicemesh/sdk/pkg/networkservice/chains/endpoint"
"github.com/networkservicemesh/sdk/pkg/networkservice/common/clienturl"
"github.com/networkservicemesh/sdk/pkg/networkservice/common/connect"
"github.com/networkservicemesh/sdk/pkg/networkservice/common/mechanisms"
"github.com/networkservicemesh/sdk/pkg/networkservice/common/mechanisms/recvfd"
"github.com/networkservicemesh/sdk/pkg/networkservice/common/mechanisms/sendfd"
"github.com/networkservicemesh/sdk/pkg/networkservice/common/mechanismtranslation"
"github.com/networkservicemesh/sdk/pkg/networkservice/core/chain"
"github.com/networkservicemesh/sdk/pkg/networkservice/utils/metadata"
"github.com/networkservicemesh/sdk/pkg/tools/log"
"github.com/networkservicemesh/sdk/pkg/tools/token"
ovsutil "github.com/ovn-org/ovn-kubernetes/go-controller/pkg/util"
"google.golang.org/grpc"
kexec "k8s.io/utils/exec"

"github.com/networkservicemesh/sdk-ovs/pkg/networkservice/l2ovsconnect"
"github.com/networkservicemesh/sdk-ovs/pkg/networkservice/mechanisms/kernel"
"github.com/networkservicemesh/sdk-ovs/pkg/networkservice/mechanisms/vxlan"
"github.com/networkservicemesh/sdk-ovs/pkg/tools/util"
)

type ovsConnectNSServer struct {
endpoint.Endpoint
}

// NewSriovServer - returns sriov implementation of the ovsconnectns network service
func NewSriovServer(ctx context.Context, name string, authzServer networkservice.NetworkServiceServer,
tokenGenerator token.GeneratorFunc, clientURL *url.URL, bridgeName string, tunnelIpCidr net.IP,
pciPool resourcepool.PCIPool, resourcePool resourcepool.ResourcePool, sriovConfig *config.Config,
clientDialOptions ...grpc.DialOption) (endpoint.Endpoint, error) {
resourceLock := &sync.Mutex{}
tunnelIP, err := util.ParseTunnelIP(tunnelIpCidr)
if err != nil {
return nil, err
}
vxlanInterfacesMutex := &sync.Mutex{}
vxlanInterfaces := make(map[string]int)
rv := &ovsConnectNSServer{}
additionalFunctionality := []networkservice.NetworkServiceServer{
metadata.NewServer(),
recvfd.NewServer(),
// Statically set the url we use to the unix file socket for the NSMgr
clienturl.NewServer(clientURL),
connect.NewServer(
ctx,
func(ctx context.Context, cc grpc.ClientConnInterface) networkservice.NetworkServiceClient {
return client.NewClient(ctx,
cc,
client.WithName(name),
client.WithAdditionalFunctionality(
mechanismtranslation.NewClient(),
connectioncontextkernel.NewClient(),
// TODO: uncomment once inject chain element has NewClient
//inject.NewClient(),
// mechanisms
kernel.NewClient(bridgeName),
// TODO: uncomment once resourcepool chain element has NewClient
//resourcepool.NewClient(sriov.KernelDriver, resourceLock, pciPool, resourcePool, sriovConfig),
vxlan.NewClient(tunnelIP, bridgeName, vxlanInterfacesMutex, vxlanInterfaces),
recvfd.NewClient(),
sendfd.NewClient(),
),
)
},
connect.WithDialOptions(clientDialOptions...),
),
mechanisms.NewServer(map[string]networkservice.NetworkServiceServer{
kernelmech.MECHANISM: chain.NewNetworkServiceServer(
kernel.NewServer(bridgeName),
resourcepool.NewServer(sriov.KernelDriver, resourceLock, pciPool, resourcePool, sriovConfig),
rename.NewServer(),
),
vxlanmech.MECHANISM: vxlan.NewServer(tunnelIP, bridgeName, vxlanInterfacesMutex, vxlanInterfaces),
}),
inject.NewServer(),
connectioncontextkernel.NewServer(),
l2ovsconnect.NewServer(bridgeName),
sendfd.NewServer(),
}

rv.Endpoint = endpoint.NewServer(ctx, tokenGenerator,
endpoint.WithName(name),
endpoint.WithAuthorizeServer(authzServer),
endpoint.WithAdditionalFunctionality(additionalFunctionality...))

return rv, nil
}

// NewKernelServer - returns kernel implementation of the ovsconnectns network service
func NewKernelServer(ctx context.Context, name string, authzServer networkservice.NetworkServiceServer,
tokenGenerator token.GeneratorFunc, clientURL *url.URL, bridgeName string, tunnelIpCidr net.IP,
clientDialOptions ...grpc.DialOption) (endpoint.Endpoint, error) {
tunnelIP, err := util.ParseTunnelIP(tunnelIpCidr)
if err != nil {
return nil, err
}
vxlanInterfacesMutex := &sync.Mutex{}
vxlanInterfaces := make(map[string]int)
rv := &ovsConnectNSServer{}
additionalFunctionality := []networkservice.NetworkServiceServer{
metadata.NewServer(),
recvfd.NewServer(),
// Statically set the url we use to the unix file socket for the NSMgr
clienturl.NewServer(clientURL),
connect.NewServer(
ctx,
func(ctx context.Context, cc grpc.ClientConnInterface) networkservice.NetworkServiceClient {
return client.NewClient(ctx,
cc,
client.WithName(name),
client.WithAdditionalFunctionality(
mechanismtranslation.NewClient(),
connectioncontextkernel.NewClient(),
// TODO: uncomment once inject chain element has NewClient
//inject.NewClient(),
// mechanisms
kernel.NewClient(bridgeName),
vxlan.NewClient(tunnelIP, bridgeName, vxlanInterfacesMutex, vxlanInterfaces),
recvfd.NewClient(),
sendfd.NewClient(),
),
)
},
connect.WithDialOptions(clientDialOptions...),
),
mechanisms.NewServer(map[string]networkservice.NetworkServiceServer{
kernelmech.MECHANISM: chain.NewNetworkServiceServer(
kernel.NewServer(bridgeName),
rename.NewServer(),
),
vxlanmech.MECHANISM: vxlan.NewServer(tunnelIP, bridgeName, vxlanInterfacesMutex, vxlanInterfaces),
}),
inject.NewServer(),
connectioncontextkernel.NewServer(),
l2ovsconnect.NewServer(bridgeName),
sendfd.NewServer(),
}

rv.Endpoint = endpoint.NewServer(ctx, tokenGenerator,
endpoint.WithName(name),
endpoint.WithAuthorizeServer(authzServer),
endpoint.WithAdditionalFunctionality(additionalFunctionality...))

return rv, nil
}

func configureOvS(ctx context.Context, bridgeName string) {
// Initialize the ovs utility wrapper.
exec := kexec.New()
if err := ovsutil.SetExec(exec); err != nil {
log.FromContext(ctx).Warnf("failed to initialize ovs exec helper: %v", err)
}

// Create ovs bridge for client and endpoint connections
stdout, stderr, err := ovsutil.RunOVSVsctl("--", "--may-exist", "add-br", bridgeName)
if err != nil {
log.FromContext(ctx).Warnf("Failed to add bridge %s, stdout: %q, stderr: %q, error: %v", bridgeName, stdout, stderr, err)
}

// Clean the flows from the above created ovs bridge
stdout, stderr, err = ovsutil.RunOVSOfctl("del-flows", bridgeName)
if err != nil {
log.FromContext(ctx).Warnf("Failed to cleanup flows on %s "+
"stdout: %q, stderr: %q, error: %v", bridgeName, stdout, stderr, err)
}
}
74 changes: 74 additions & 0 deletions pkg/networkservice/l2ovsconnect/local.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// Copyright (c) 2021 Nordix Foundation.
//
// 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 l2ovsconnect

import (
"context"
"fmt"

"github.com/networkservicemesh/sdk/pkg/tools/log"
"github.com/ovn-org/ovn-kubernetes/go-controller/pkg/util"

"github.com/networkservicemesh/sdk-ovs/pkg/tools/ifnames"
)

func createLocalCrossConnect(ctx context.Context, logger log.Logger, bridgeName string, endpointOvsPortInfo,
clientOvsPortInfo ifnames.OvsPortInfo) error {
stdout, stderr, err := util.RunOVSOfctl("add-flow", bridgeName, fmt.Sprintf("priority=100, in_port=%d,"+
" actions=output:%d", endpointOvsPortInfo.PortNo, clientOvsPortInfo.PortNo))
if err != nil {
logger.Infof("Failed to add flow on %s for port %s stdout: %s"+
" stderr: %s, error: %v", bridgeName, endpointOvsPortInfo.PortName, stdout, stderr, err)
return err
}
if stderr != "" {
logger.Errorf("Failed to add flow on %s for port %s stdout: %s"+
" stderr: %s", bridgeName, endpointOvsPortInfo.PortName, stdout, stderr)
}

stdout, stderr, err = util.RunOVSOfctl("add-flow", bridgeName, fmt.Sprintf("priority=100, in_port=%d,"+
" actions=output:%d", clientOvsPortInfo.PortNo, endpointOvsPortInfo.PortNo))
if err != nil {
logger.Errorf("Failed to add flow on %s for port %s stdout: %s"+
" stderr: %s, error: %v", bridgeName, clientOvsPortInfo.PortName, stdout, stderr, err)
return err
}

if stderr != "" {
logger.Errorf("Failed to add flow on %s for port %s stdout: %s"+
" stderr: %s", bridgeName, clientOvsPortInfo.PortName, stdout, stderr)
}
return nil
}

func deleteLocalCrossConnect(ctx context.Context, logger log.Logger, bridgeName string, endpointOvsPortInfo,
clientOvsPortInfo ifnames.OvsPortInfo) error {
stdout, stderr, err := util.RunOVSOfctl("del-flows", bridgeName, fmt.Sprintf("in_port=%d",
endpointOvsPortInfo.PortNo))
if err != nil {
logger.Errorf("Failed to delete flow on %s for port "+
"%s, stdout: %q, stderr: %q, error: %v", bridgeName, endpointOvsPortInfo.PortName, stdout, stderr, err)
return err
}

stdout, stderr, err = util.RunOVSOfctl("del-flows", bridgeName, fmt.Sprintf("in_port=%d", clientOvsPortInfo.PortNo))
if err != nil {
logger.Errorf("Failed to delete flow on %s for port "+
"%s, stdout: %q, stderr: %q, error: %v", bridgeName, clientOvsPortInfo.PortName, stdout, stderr, err)
}
return nil
}
Loading

0 comments on commit 8ae1a4a

Please sign in to comment.