Skip to content

Commit

Permalink
Add tap interface restoring
Browse files Browse the repository at this point in the history
Signed-off-by: Artem Glazychev <[email protected]>
  • Loading branch information
glazychev-art committed Apr 4, 2022
1 parent 6e9221c commit 87a5436
Show file tree
Hide file tree
Showing 16 changed files with 575 additions and 35 deletions.
4 changes: 4 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ jobs:
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Setup Go
uses: actions/setup-go@v1
with:
go-version: 1.16
- name: golangci-lint
uses: golangci/golangci-lint-action@v2
with:
Expand Down
26 changes: 17 additions & 9 deletions pkg/networkservice/chains/forwarder/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,16 @@ import (
)

type forwarderOptions struct {
name string
authorizeServer networkservice.NetworkServiceServer
clientURL *url.URL
dialTimeout time.Duration
domain2Device map[string]string
statsOpts []stats.Option
cleanupOpts []cleanup.Option
vxlanOpts []vxlan.Option
dialOpts []grpc.DialOption
name string
authorizeServer networkservice.NetworkServiceServer
clientURL *url.URL
dialTimeout time.Duration
dumpCleanupTimeout time.Duration
domain2Device map[string]string
statsOpts []stats.Option
cleanupOpts []cleanup.Option
vxlanOpts []vxlan.Option
dialOpts []grpc.DialOption
}

// Option is an option pattern for forwarder chain elements
Expand Down Expand Up @@ -77,6 +78,13 @@ func WithDialTimeout(dialTimeout time.Duration) Option {
}
}

// WithDumpCleanupTimeout sets timeout to remove unused dumped interfaces
func WithDumpCleanupTimeout(timeout time.Duration) Option {
return func(o *forwarderOptions) {
o.dumpCleanupTimeout = timeout
}
}

// WithVlanDomain2Device sets vlan option
func WithVlanDomain2Device(domain2Device map[string]string) Option {
return func(o *forwarderOptions) {
Expand Down
22 changes: 15 additions & 7 deletions pkg/networkservice/chains/forwarder/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ import (
"github.com/networkservicemesh/sdk-vpp/pkg/networkservice/tag"
"github.com/networkservicemesh/sdk-vpp/pkg/networkservice/up"
"github.com/networkservicemesh/sdk-vpp/pkg/networkservice/xconnect"
"github.com/networkservicemesh/sdk-vpp/pkg/tools/dumptool"
)

// Connection aggregates the api.Connection and api.ChannelProvider interfaces
Expand All @@ -78,15 +79,22 @@ type xconnectNSServer struct {
// NewServer - returns an implementation of the xconnectns network service
func NewServer(ctx context.Context, tokenGenerator token.GeneratorFunc, vppConn Connection, tunnelIP net.IP, options ...Option) endpoint.Endpoint {
opts := &forwarderOptions{
name: "forwarder-vpp-" + uuid.New().String(),
authorizeServer: authorize.NewServer(authorize.Any()),
clientURL: &url.URL{Scheme: "unix", Host: "connect.to.socket"},
dialTimeout: time.Millisecond * 200,
domain2Device: make(map[string]string),
name: "forwarder-vpp-" + uuid.New().String(),
authorizeServer: authorize.NewServer(authorize.Any()),
clientURL: &url.URL{Scheme: "unix", Host: "connect.to.socket"},
dialTimeout: time.Millisecond * 200,
dumpCleanupTimeout: time.Minute * 10,
domain2Device: make(map[string]string),
}
for _, opt := range options {
opt(opts)
}

dumpOption := &dumptool.DumpOption{
PodName: opts.name,
Timeout: opts.dumpCleanupTimeout,
}

nseClient := registryclient.NewNetworkServiceEndpointRegistryClient(ctx, opts.clientURL,
registryclient.WithNSEAdditionalFunctionality(
registryrecvfd.NewNetworkServiceEndpointRegistryClient(),
Expand All @@ -113,7 +121,7 @@ func NewServer(ctx context.Context, tokenGenerator token.GeneratorFunc, vppConn
memif.MECHANISM: memif.NewServer(ctx, vppConn,
memif.WithDirectMemif(),
memif.WithChangeNetNS()),
kernel.MECHANISM: kernel.NewServer(vppConn),
kernel.MECHANISM: kernel.NewServer(vppConn, kernel.WithDump(dumpOption)),
vxlan.MECHANISM: vxlan.NewServer(vppConn, tunnelIP, opts.vxlanOpts...),
wireguard.MECHANISM: wireguard.NewServer(vppConn, tunnelIP),
}),
Expand All @@ -136,7 +144,7 @@ func NewServer(ctx context.Context, tokenGenerator token.GeneratorFunc, vppConn
memif.NewClient(vppConn,
memif.WithChangeNetNS(),
),
kernel.NewClient(vppConn),
kernel.NewClient(vppConn, kernel.WithDump(dumpOption)),
vxlan.NewClient(vppConn, tunnelIP, opts.vxlanOpts...),
wireguard.NewClient(vppConn, tunnelIP),
vlan.NewClient(vppConn, opts.domain2Device),
Expand Down
11 changes: 8 additions & 3 deletions pkg/networkservice/mechanisms/kernel/client.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2020-2021 Cisco and/or its affiliates.
// Copyright (c) 2020-2022 Cisco and/or its affiliates.
//
// SPDX-License-Identifier: Apache-2.0
//
Expand Down Expand Up @@ -30,9 +30,14 @@ import (
)

// NewClient - returns a new Client chain element implementing the kernel mechanism with vpp
func NewClient(vppConn api.Connection) networkservice.NetworkServiceClient {
func NewClient(vppConn api.Connection, opts ...Option) networkservice.NetworkServiceClient {
o := &options{}
for _, opt := range opts {
opt(o)
}

if _, err := os.Stat(vnetFilename); err == nil {
return kerneltap.NewClient(vppConn)
return kerneltap.NewClient(vppConn, kerneltap.WithDump(o.dumpOpt))
}
return kernelvethpair.NewClient(vppConn)
}
27 changes: 23 additions & 4 deletions pkg/networkservice/mechanisms/kernel/kerneltap/client.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2020-2021 Cisco and/or its affiliates.
// Copyright (c) 2020-2022 Cisco and/or its affiliates.
//
// SPDX-License-Identifier: Apache-2.0
//
Expand Down Expand Up @@ -32,16 +32,35 @@ import (
"github.com/networkservicemesh/sdk/pkg/networkservice/utils/metadata"
"github.com/networkservicemesh/sdk/pkg/tools/log"
"github.com/networkservicemesh/sdk/pkg/tools/postpone"

"github.com/networkservicemesh/sdk-vpp/pkg/tools/dumptool"
)

type kernelTapClient struct {
vppConn api.Connection
dumpMap *dumptool.Map
}

// NewClient - return a new Client chain element implementing the kernel mechanism with vpp using tapv2
func NewClient(vppConn api.Connection) networkservice.NetworkServiceClient {
func NewClient(vppConn api.Connection, opts ...Option) networkservice.NetworkServiceClient {
o := &options{}
for _, opt := range opts {
opt(o)
}

ctx := context.Background()
dumpMap := dumptool.NewMap(ctx, 0)
if o.dumpOpt != nil {
var err error
dumpMap, err = dump(ctx, vppConn, o.dumpOpt.PodName, o.dumpOpt.Timeout, true)
if err != nil {
log.FromContext(ctx).Errorf("failed to Dump: %v", err)
}
}

return &kernelTapClient{
vppConn: vppConn,
dumpMap: dumpMap,
}
}

Expand All @@ -60,7 +79,7 @@ func (k *kernelTapClient) Request(ctx context.Context, request *networkservice.N
return nil, err
}

if err := create(ctx, conn, k.vppConn, metadata.IsClient(k)); err != nil {
if err := create(ctx, conn, k.vppConn, k.dumpMap, metadata.IsClient(k)); err != nil {
closeCtx, cancelClose := postponeCtxFunc()
defer cancelClose()

Expand All @@ -75,7 +94,7 @@ func (k *kernelTapClient) Request(ctx context.Context, request *networkservice.N
}

func (k *kernelTapClient) Close(ctx context.Context, conn *networkservice.Connection, opts ...grpc.CallOption) (*empty.Empty, error) {
err := del(ctx, conn, k.vppConn, metadata.IsClient(k))
err := del(ctx, conn, k.vppConn, k.dumpMap, metadata.IsClient(k))
if err != nil {
log.FromContext(ctx).Error(err)
}
Expand Down
31 changes: 28 additions & 3 deletions pkg/networkservice/mechanisms/kernel/kerneltap/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,16 @@ import (
kernellink "github.com/networkservicemesh/sdk-kernel/pkg/kernel"
"github.com/networkservicemesh/sdk/pkg/tools/log"

"github.com/networkservicemesh/sdk-vpp/pkg/tools/dumptool"
"github.com/networkservicemesh/sdk-vpp/pkg/tools/ifindex"
"github.com/networkservicemesh/sdk-vpp/pkg/tools/mechutils"
)

func create(ctx context.Context, conn *networkservice.Connection, vppConn api.Connection, isClient bool) error {
func create(ctx context.Context, conn *networkservice.Connection, vppConn api.Connection, dumpMap *dumptool.Map, isClient bool) error {
if mechanism := kernel.ToMechanism(conn.GetMechanism()); mechanism != nil {
if val, loaded := dumpMap.LoadAndDelete(conn.GetId()); loaded {
ifindex.Store(ctx, isClient, val.(interface_types.InterfaceIndex))
}
// Construct the netlink handle for the target namespace for this kernel interface
handle, err := kernellink.GetNetlinkHandle(mechanism.GetNetNSURL())
if err != nil {
Expand All @@ -53,7 +57,7 @@ func create(ctx context.Context, conn *networkservice.Connection, vppConn api.Co
}
}
// Delete the kernel interface if there is one in the target namespace
_ = del(ctx, conn, vppConn, isClient)
_ = del(ctx, conn, vppConn, dumpMap, isClient)

nsFilename, err := mechutils.ToNSFilename(mechanism)
if err != nil {
Expand Down Expand Up @@ -141,8 +145,11 @@ func create(ctx context.Context, conn *networkservice.Connection, vppConn api.Co
return nil
}

func del(ctx context.Context, conn *networkservice.Connection, vppConn api.Connection, isClient bool) error {
func del(ctx context.Context, conn *networkservice.Connection, vppConn api.Connection, dumpMap *dumptool.Map, isClient bool) error {
if mechanism := kernel.ToMechanism(conn.GetMechanism()); mechanism != nil {
if val, loaded := dumpMap.LoadAndDelete(conn.GetId()); loaded {
ifindex.Store(ctx, isClient, val.(interface_types.InterfaceIndex))
}
swIfIndex, ok := ifindex.LoadAndDelete(ctx, isClient)
if !ok {
return nil
Expand All @@ -162,3 +169,21 @@ func del(ctx context.Context, conn *networkservice.Connection, vppConn api.Conne
}
return nil
}

func dump(ctx context.Context, vppConn api.Connection, podName string, timeout time.Duration, isClient bool) (*dumptool.Map, error) {
return dumptool.DumpVppInterfaces(ctx, vppConn, podName, timeout, isClient,
/* Function on dump */
func(details *interfaces.SwInterfaceDetails) (interface{}, error) {
if details.InterfaceDevType == dumptool.DevTypeTap {
return details.SwIfIndex, nil
}
return nil, errors.New("Doesn't match the tap interface")
},
/* Function on delete */
func(ifindex interface{}) error {
_, err := tapv2.NewServiceClient(vppConn).TapDeleteV2(ctx, &tapv2.TapDeleteV2{
SwIfIndex: ifindex.(interface_types.InterfaceIndex),
})
return err
})
}
35 changes: 35 additions & 0 deletions pkg/networkservice/mechanisms/kernel/kerneltap/options.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright (c) 2022 Cisco 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.

// +build linux

package kerneltap

import "github.com/networkservicemesh/sdk-vpp/pkg/tools/dumptool"

type options struct {
dumpOpt *dumptool.DumpOption
}

// Option is an option pattern for kernel
type Option func(o *options)

// WithDump - sets dump parameters
func WithDump(dump *dumptool.DumpOption) Option {
return func(o *options) {
o.dumpOpt = dump
}
}
27 changes: 23 additions & 4 deletions pkg/networkservice/mechanisms/kernel/kerneltap/server.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2020-2021 Cisco and/or its affiliates.
// Copyright (c) 2020-2022 Cisco and/or its affiliates.
//
// SPDX-License-Identifier: Apache-2.0
//
Expand All @@ -25,6 +25,8 @@ import (
"github.com/golang/protobuf/ptypes/empty"
"github.com/pkg/errors"

"github.com/networkservicemesh/sdk-vpp/pkg/tools/dumptool"

"github.com/networkservicemesh/api/pkg/api/networkservice"
"github.com/networkservicemesh/sdk/pkg/networkservice/core/next"
"github.com/networkservicemesh/sdk/pkg/networkservice/utils/metadata"
Expand All @@ -34,12 +36,29 @@ import (

type kernelTapServer struct {
vppConn api.Connection
dumpMap *dumptool.Map
}

// NewServer - return a new Server chain element implementing the kernel mechanism with vpp using tapv2
func NewServer(vppConn api.Connection) networkservice.NetworkServiceServer {
func NewServer(vppConn api.Connection, opts ...Option) networkservice.NetworkServiceServer {
o := &options{}
for _, opt := range opts {
opt(o)
}

ctx := context.Background()
dumpMap := dumptool.NewMap(ctx, 0)
if o.dumpOpt != nil {
var err error
dumpMap, err = dump(ctx, vppConn, o.dumpOpt.PodName, o.dumpOpt.Timeout, false)
if err != nil {
log.FromContext(ctx).Errorf("failed to Dump: %v", err)
}
}

return &kernelTapServer{
vppConn: vppConn,
dumpMap: dumpMap,
}
}

Expand All @@ -51,7 +70,7 @@ func (k *kernelTapServer) Request(ctx context.Context, request *networkservice.N
return nil, err
}

if err := create(ctx, conn, k.vppConn, metadata.IsClient(k)); err != nil {
if err := create(ctx, conn, k.vppConn, k.dumpMap, metadata.IsClient(k)); err != nil {
closeCtx, cancelClose := postponeCtxFunc()
defer cancelClose()

Expand All @@ -66,7 +85,7 @@ func (k *kernelTapServer) Request(ctx context.Context, request *networkservice.N
}

func (k *kernelTapServer) Close(ctx context.Context, conn *networkservice.Connection) (*empty.Empty, error) {
err := del(ctx, conn, k.vppConn, metadata.IsClient(k))
err := del(ctx, conn, k.vppConn, k.dumpMap, metadata.IsClient(k))
if err != nil {
log.FromContext(ctx).Error(err)
}
Expand Down
35 changes: 35 additions & 0 deletions pkg/networkservice/mechanisms/kernel/options.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright (c) 2022 Cisco 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.

// +build linux

package kernel

import "github.com/networkservicemesh/sdk-vpp/pkg/tools/dumptool"

type options struct {
dumpOpt *dumptool.DumpOption
}

// Option is an option pattern for kernel
type Option func(o *options)

// WithDump - sets dump parameters
func WithDump(dump *dumptool.DumpOption) Option {
return func(o *options) {
o.dumpOpt = dump
}
}
Loading

0 comments on commit 87a5436

Please sign in to comment.