-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[WIP] Add initial utilities for link and namespace actions
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
Showing
4 changed files
with
177 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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") | ||
} |