Skip to content

Commit

Permalink
[WIP] Add initial utilities for link and namespace actions
Browse files Browse the repository at this point in the history
This change introduces basic utilities for managing interfaces,
routes, and namespaces. See
#2

Signed-off-by: Ryan Tidwell <[email protected]>
  • Loading branch information
Ryan Tidwell committed Jan 23, 2020
1 parent 8e5425a commit bbfbfde
Show file tree
Hide file tree
Showing 4 changed files with 177 additions and 0 deletions.
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,6 @@ module github.com/networkservicemesh/sdk-kernel
go 1.13

require (
github.com/vishvananda/netlink v1.0.0
github.com/vishvananda/netns v0.0.0-20190625233234-7109fa855b0f
)
89 changes: 89 additions & 0 deletions pkg/networkservice/kernelutils/common.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// Copyright 2019 SUSE LLC.
// 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 kernelutils

import (
"github.com/networkservicemesh/networkservicemesh/controlplane/api/connectioncontext"

"net"

"github.com/sirupsen/logrus"
"github.com/vishvananda/netlink"
)

// Kernel forwarding plane related constants
const (
cLOCAL = iota
cINCOMING = iota
cOUTGOING = iota
)

const (
/* VETH pairs are used only for local connections(same node), so we can use a larger MTU size as there's no multi-node connection */
cVETHMTU = 16000
cCONNECT = true
cDISCONNECT = false
)

type connectionConfig struct {
id string
srcNetNsInode string
dstNetNsInode string
srcName string
dstName string
srcIP string
dstIP string
srcIPVXLAN net.IP
dstIPVXLAN net.IP
srcRoutes []*connectioncontext.Route
dstRoutes []*connectioncontext.Route
neighbors []*connectioncontext.IpNeighbor
vni int
}

// addNeighbors adds neighbors
func AddNeighbors(link netlink.Link, neighbors []*connectioncontext.IpNeighbor) error {
for _, neighbor := range neighbors {
mac, err := net.ParseMAC(neighbor.GetHardwareAddress())
if err != nil {
logrus.Error("common: failed parsing the MAC address for IP neighbors:", err)
return err
}
neigh := netlink.Neigh{
LinkIndex: link.Attrs().Index,
State: 0x02, // netlink.NUD_REACHABLE, // the constant is somehow not being found in the package in case of using a darwin based machine
IP: net.ParseIP(neighbor.GetIp()),
HardwareAddr: mac,
}
if err = netlink.NeighAdd(&neigh); err != nil {
logrus.Error("common: failed adding neighbor:", err)
return err
}
}
return nil
}

// newVETH returns a VETH interface instance
func NewVETH(srcName, dstName string) *netlink.Veth {
/* Populate the VETH interface configuration */
return &netlink.Veth{
LinkAttrs: netlink.LinkAttrs{
Name: srcName,
MTU: cVETHMTU,
},
PeerName: dstName,
}
}
37 changes: 37 additions & 0 deletions pkg/networkservice/kernelutils/namespaceutils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Copyright 2019 SUSE LLC.
// 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 kernelutils

import (
"github.com/sirupsen/logrus"
"github.com/vishvananda/netlink"
"github.com/vishvananda/netns"
)

func InjectLinkInNamespace(containerNs netns.NsHandle, ifaceName string) error {
/* Get a link object for the interface */
ifaceLink, err := netlink.LinkByName(ifaceName)
if err != nil {
logrus.Errorf("common: failed to get link for %q - %v", ifaceName, err)
return err
}
/* Inject the interface into the desired namespace */
if err = netlink.LinkSetNsFd(ifaceLink, int(containerNs)); err != nil {
logrus.Errorf("common: failed to inject %q in namespace - %v", ifaceName, err)
return err
}
return nil
}
49 changes: 49 additions & 0 deletions test/integration/namespace_utils_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package sdk_kernel_tests

import (
"testing"

. "github.com/onsi/gomega"

"github.com/networkservicemesh/sdk-kernel/pkg/networkservice/kernelutils"

"github.com/sirupsen/logrus"
"github.com/vishvananda/netlink"
"github.com/vishvananda/netns"
)

const testVethSrcName = "sdk-kernel-src"
const testVethDstName = "sdk-kernel-dst"

func TestInjectLinkInNamespace(t *testing.T) {
g := NewWithT(t)

// set up the basic resources for the test
currns, _ := netns.Get()
testns, _ := netns.New()
_ = netns.Set(currns)
vethErr := netlink.LinkAdd(kernelutils.NewVETH(testVethSrcName, testVethDstName))
g.Expect(vethErr).To(BeNil())

// clean up after ourselves
defer func(rootns netns.NsHandle, testns netns.NsHandle, veth *netlink.Veth) {
_ = netns.Set(rootns)
testns.Close()
netlink.LinkDel(veth)
}(currns, testns, kernelutils.NewVETH(testVethSrcName, testVethDstName))

// move one end of the veth into testns and run assertions
injectError := kernelutils.InjectLinkInNamespace(testns, testVethDstName)

_ = netns.Set(testns)
nsLinks, _ := netlink.LinkList()
_, linkErr := netlink.LinkByName(testVethDstName)

// assert no error on link injection
g.Expect(injectError).To(BeNil())
// assert only loopback and the interface we inject exist in the namespace
g.Expect(len(nsLinks)).To(Equal(2))
g.Expect(linkErr).To(BeNil())

logrus.Printf("Done")
}

0 comments on commit bbfbfde

Please sign in to comment.