Merge remote-tracking branch 'upstream/master' into dev/static-args
This commit is contained in:
@@ -128,7 +128,7 @@ func (d *DHCP) clearLease(contID, netName string) {
|
||||
}
|
||||
|
||||
func getListener() (net.Listener, error) {
|
||||
l, err := activation.Listeners(true)
|
||||
l, err := activation.Listeners()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -44,7 +44,8 @@ func main() {
|
||||
os.Exit(1)
|
||||
}
|
||||
} else {
|
||||
skel.PluginMain(cmdAdd, cmdDel, version.All)
|
||||
// TODO: implement plugin version
|
||||
skel.PluginMain(cmdAdd, cmdGet, cmdDel, version.All, "TODO")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,6 +73,11 @@ func cmdDel(args *skel.CmdArgs) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func cmdGet(args *skel.CmdArgs) error {
|
||||
// TODO: implement
|
||||
return fmt.Errorf("not implemented")
|
||||
}
|
||||
|
||||
func rpcCall(method string, args *skel.CmdArgs, result interface{}) error {
|
||||
client, err := rpc.DialHTTP("unix", socketPath)
|
||||
if err != nil {
|
||||
|
||||
@@ -372,7 +372,7 @@ var _ = Describe("IPAM config", func() {
|
||||
"type": "host-local",
|
||||
"ranges": [
|
||||
[{"subnet": "10.1.2.0/24"}],
|
||||
[{"subnet": "2001:db8:1::/24"}]
|
||||
[{"subnet": "2001:db8:1::/48"}]
|
||||
]
|
||||
}
|
||||
}`
|
||||
|
||||
@@ -40,6 +40,12 @@ func (r *Range) Canonicalize() error {
|
||||
return fmt.Errorf("IPNet IP and Mask version mismatch")
|
||||
}
|
||||
|
||||
// Ensure Subnet IP is the network address, not some other address
|
||||
networkIP := r.Subnet.IP.Mask(r.Subnet.Mask)
|
||||
if !r.Subnet.IP.Equal(networkIP) {
|
||||
return fmt.Errorf("Network has host bits set. For a subnet mask of length %d the network address is %s", ones, networkIP.String())
|
||||
}
|
||||
|
||||
// If the gateway is nil, claim .1
|
||||
if r.Gateway == nil {
|
||||
r.Gateway = ip.NextIP(r.Subnet.IP)
|
||||
|
||||
@@ -25,7 +25,7 @@ import (
|
||||
)
|
||||
|
||||
var _ = Describe("IP ranges", func() {
|
||||
It("should generate sane defaults for ipv4", func() {
|
||||
It("should generate sane defaults for ipv4 with a clean prefix", func() {
|
||||
snstr := "192.0.2.0/24"
|
||||
r := Range{Subnet: mustSubnet(snstr)}
|
||||
|
||||
@@ -33,7 +33,7 @@ var _ = Describe("IP ranges", func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
Expect(r).To(Equal(Range{
|
||||
Subnet: mustSubnet(snstr),
|
||||
Subnet: networkSubnet(snstr),
|
||||
RangeStart: net.IP{192, 0, 2, 1},
|
||||
RangeEnd: net.IP{192, 0, 2, 254},
|
||||
Gateway: net.IP{192, 0, 2, 1},
|
||||
@@ -47,13 +47,41 @@ var _ = Describe("IP ranges", func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
Expect(r).To(Equal(Range{
|
||||
Subnet: mustSubnet(snstr),
|
||||
Subnet: networkSubnet(snstr),
|
||||
RangeStart: net.IP{192, 0, 2, 1},
|
||||
RangeEnd: net.IP{192, 0, 2, 126},
|
||||
Gateway: net.IP{192, 0, 2, 1},
|
||||
}))
|
||||
})
|
||||
It("should generate sane defaults for ipv6", func() {
|
||||
It("should reject ipv4 subnet using a masked address", func() {
|
||||
snstr := "192.0.2.12/24"
|
||||
r := Range{Subnet: mustSubnet(snstr)}
|
||||
|
||||
err := r.Canonicalize()
|
||||
Expect(err).Should(MatchError("Network has host bits set. For a subnet mask of length 24 the network address is 192.0.2.0"))
|
||||
})
|
||||
It("should reject ipv6 subnet using a masked address", func() {
|
||||
snstr := "2001:DB8:1::24:19ff:fee1:c44a/64"
|
||||
r := Range{Subnet: mustSubnet(snstr)}
|
||||
|
||||
err := r.Canonicalize()
|
||||
Expect(err).Should(MatchError("Network has host bits set. For a subnet mask of length 64 the network address is 2001:db8:1::"))
|
||||
})
|
||||
It("should reject ipv6 prefix with host bit set", func() {
|
||||
snstr := "2001:DB8:24:19ff::/63"
|
||||
r := Range{Subnet: mustSubnet(snstr)}
|
||||
|
||||
err := r.Canonicalize()
|
||||
Expect(err).Should(MatchError("Network has host bits set. For a subnet mask of length 63 the network address is 2001:db8:24:19fe::"))
|
||||
})
|
||||
It("should reject ipv4 network with host bit set", func() {
|
||||
snstr := "192.168.127.0/23"
|
||||
r := Range{Subnet: mustSubnet(snstr)}
|
||||
|
||||
err := r.Canonicalize()
|
||||
Expect(err).Should(MatchError("Network has host bits set. For a subnet mask of length 23 the network address is 192.168.126.0"))
|
||||
})
|
||||
It("should generate sane defaults for ipv6 with a clean prefix", func() {
|
||||
snstr := "2001:DB8:1::/64"
|
||||
r := Range{Subnet: mustSubnet(snstr)}
|
||||
|
||||
@@ -61,7 +89,7 @@ var _ = Describe("IP ranges", func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
Expect(r).To(Equal(Range{
|
||||
Subnet: mustSubnet(snstr),
|
||||
Subnet: networkSubnet(snstr),
|
||||
RangeStart: net.ParseIP("2001:DB8:1::1"),
|
||||
RangeEnd: net.ParseIP("2001:DB8:1::ffff:ffff:ffff:ffff"),
|
||||
Gateway: net.ParseIP("2001:DB8:1::1"),
|
||||
@@ -75,16 +103,17 @@ var _ = Describe("IP ranges", func() {
|
||||
})
|
||||
|
||||
It("should reject invalid RangeStart and RangeEnd specifications", func() {
|
||||
r := Range{Subnet: mustSubnet("192.0.2.0/24"), RangeStart: net.ParseIP("192.0.3.0")}
|
||||
snstr := "192.0.2.0/24"
|
||||
r := Range{Subnet: mustSubnet(snstr), RangeStart: net.ParseIP("192.0.3.0")}
|
||||
err := r.Canonicalize()
|
||||
Expect(err).Should(MatchError("RangeStart 192.0.3.0 not in network 192.0.2.0/24"))
|
||||
|
||||
r = Range{Subnet: mustSubnet("192.0.2.0/24"), RangeEnd: net.ParseIP("192.0.4.0")}
|
||||
r = Range{Subnet: mustSubnet(snstr), RangeEnd: net.ParseIP("192.0.4.0")}
|
||||
err = r.Canonicalize()
|
||||
Expect(err).Should(MatchError("RangeEnd 192.0.4.0 not in network 192.0.2.0/24"))
|
||||
|
||||
r = Range{
|
||||
Subnet: mustSubnet("192.0.2.0/24"),
|
||||
Subnet: networkSubnet(snstr),
|
||||
RangeStart: net.ParseIP("192.0.2.50"),
|
||||
RangeEnd: net.ParseIP("192.0.2.40"),
|
||||
}
|
||||
@@ -99,8 +128,9 @@ var _ = Describe("IP ranges", func() {
|
||||
})
|
||||
|
||||
It("should parse all fields correctly", func() {
|
||||
snstr := "192.0.2.0/24"
|
||||
r := Range{
|
||||
Subnet: mustSubnet("192.0.2.0/24"),
|
||||
Subnet: mustSubnet(snstr),
|
||||
RangeStart: net.ParseIP("192.0.2.40"),
|
||||
RangeEnd: net.ParseIP("192.0.2.50"),
|
||||
Gateway: net.ParseIP("192.0.2.254"),
|
||||
@@ -109,7 +139,7 @@ var _ = Describe("IP ranges", func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
Expect(r).To(Equal(Range{
|
||||
Subnet: mustSubnet("192.0.2.0/24"),
|
||||
Subnet: networkSubnet(snstr),
|
||||
RangeStart: net.IP{192, 0, 2, 40},
|
||||
RangeEnd: net.IP{192, 0, 2, 50},
|
||||
Gateway: net.IP{192, 0, 2, 254},
|
||||
@@ -207,3 +237,9 @@ func mustSubnet(s string) types.IPNet {
|
||||
canonicalizeIP(&n.IP)
|
||||
return types.IPNet(*n)
|
||||
}
|
||||
|
||||
func networkSubnet(s string) types.IPNet {
|
||||
net := mustSubnet(s)
|
||||
net.IP = net.IP.Mask(net.Mask)
|
||||
return net
|
||||
}
|
||||
|
||||
@@ -444,7 +444,7 @@ var _ = Describe("host-local Operations", func() {
|
||||
"dataDir": "%s",
|
||||
"ranges": [
|
||||
[{"subnet":"172.16.1.0/24"}, { "subnet": "10.1.2.0/24" }],
|
||||
[{ "subnet": "2001:db8:1::/24" }]
|
||||
[{ "subnet": "2001:db8:1::/48" }]
|
||||
]
|
||||
},
|
||||
"args": {
|
||||
|
||||
@@ -29,7 +29,13 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
skel.PluginMain(cmdAdd, cmdDel, version.All)
|
||||
// TODO: implement plugin version
|
||||
skel.PluginMain(cmdAdd, cmdGet, cmdDel, version.All, "TODO")
|
||||
}
|
||||
|
||||
func cmdGet(args *skel.CmdArgs) error {
|
||||
// TODO: implement
|
||||
return fmt.Errorf("not implemented")
|
||||
}
|
||||
|
||||
func cmdAdd(args *skel.CmdArgs) error {
|
||||
|
||||
@@ -57,7 +57,13 @@ type Address struct {
|
||||
}
|
||||
|
||||
func main() {
|
||||
skel.PluginMain(cmdAdd, cmdDel, version.All)
|
||||
// TODO: implement plugin version
|
||||
skel.PluginMain(cmdAdd, cmdGet, cmdDel, version.All, "TODO")
|
||||
}
|
||||
|
||||
func cmdGet(args *skel.CmdArgs) error {
|
||||
// TODO: implement
|
||||
return fmt.Errorf("not implemented")
|
||||
}
|
||||
|
||||
// canonicalizeIP makes sure a provided ip is in standard form
|
||||
@@ -72,7 +78,9 @@ func canonicalizeIP(ip *net.IP) error {
|
||||
return fmt.Errorf("IP %s not v4 nor v6", *ip)
|
||||
}
|
||||
|
||||
// NewIPAMConfig creates a NetworkConfig from the given network name.
|
||||
// LoadIPAMConfig creates IPAMConfig using json encoded configuration provided
|
||||
// as `bytes`. At the moment values provided in envArgs are ignored so there
|
||||
// is no possibility to overload the json configuration using envArgs
|
||||
func LoadIPAMConfig(bytes []byte, envArgs string) (*IPAMConfig, string, error) {
|
||||
n := Net{}
|
||||
if err := json.Unmarshal(bytes, &n); err != nil {
|
||||
@@ -167,7 +175,6 @@ func cmdAdd(args *skel.CmdArgs) error {
|
||||
Gateway: v.Gateway})
|
||||
}
|
||||
|
||||
result.Routes = ipamConf.Routes
|
||||
return types.PrintResult(result, confVersion)
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"runtime"
|
||||
"syscall"
|
||||
|
||||
@@ -36,6 +37,9 @@ import (
|
||||
"github.com/vishvananda/netlink"
|
||||
)
|
||||
|
||||
// For testcases to force an error after IPAM has been performed
|
||||
var debugPostIPAMError error
|
||||
|
||||
const defaultBrName = "cni0"
|
||||
|
||||
type NetConf struct {
|
||||
@@ -323,6 +327,8 @@ func enableIPForward(family int) error {
|
||||
}
|
||||
|
||||
func cmdAdd(args *skel.CmdArgs) error {
|
||||
var success bool = false
|
||||
|
||||
n, cniVersion, err := loadNetConf(args.StdinData)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -358,6 +364,15 @@ func cmdAdd(args *skel.CmdArgs) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// release IP in case of failure
|
||||
defer func() {
|
||||
if !success {
|
||||
os.Setenv("CNI_COMMAND", "DEL")
|
||||
ipam.ExecDel(n.IPAM.Type, args.StdinData)
|
||||
os.Setenv("CNI_COMMAND", "ADD")
|
||||
}
|
||||
}()
|
||||
|
||||
// Convert whatever the IPAM result was into the current Result type
|
||||
result, err := current.NewResultFromResult(r)
|
||||
if err != nil {
|
||||
@@ -454,6 +469,13 @@ func cmdAdd(args *skel.CmdArgs) error {
|
||||
|
||||
result.DNS = n.DNS
|
||||
|
||||
// Return an error requested by testcases, if any
|
||||
if debugPostIPAMError != nil {
|
||||
return debugPostIPAMError
|
||||
}
|
||||
|
||||
success = true
|
||||
|
||||
return types.PrintResult(result, cniVersion)
|
||||
}
|
||||
|
||||
@@ -502,5 +524,11 @@ func cmdDel(args *skel.CmdArgs) error {
|
||||
}
|
||||
|
||||
func main() {
|
||||
skel.PluginMain(cmdAdd, cmdDel, version.All)
|
||||
// TODO: implement plugin version
|
||||
skel.PluginMain(cmdAdd, cmdGet, cmdDel, version.All, "TODO")
|
||||
}
|
||||
|
||||
func cmdGet(args *skel.CmdArgs) error {
|
||||
// TODO: implement
|
||||
return fmt.Errorf("not implemented")
|
||||
}
|
||||
|
||||
@@ -16,7 +16,9 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/containernetworking/cni/pkg/skel"
|
||||
@@ -83,6 +85,9 @@ const (
|
||||
"ipam": {
|
||||
"type": "host-local"`
|
||||
|
||||
ipamDataDirStr = `,
|
||||
"dataDir": "%s"`
|
||||
|
||||
// Single subnet configuration (legacy)
|
||||
subnetConfStr = `,
|
||||
"subnet": "%s"`
|
||||
@@ -110,10 +115,13 @@ const (
|
||||
|
||||
// netConfJSON() generates a JSON network configuration string
|
||||
// for a test case.
|
||||
func (tc testCase) netConfJSON() string {
|
||||
func (tc testCase) netConfJSON(dataDir string) string {
|
||||
conf := fmt.Sprintf(netConfStr, tc.cniVersion, BRNAME)
|
||||
if tc.subnet != "" || tc.ranges != nil {
|
||||
conf += ipamStartStr
|
||||
if dataDir != "" {
|
||||
conf += fmt.Sprintf(ipamDataDirStr, dataDir)
|
||||
}
|
||||
if tc.subnet != "" {
|
||||
conf += tc.subnetConfig()
|
||||
}
|
||||
@@ -152,8 +160,8 @@ var counter uint
|
||||
|
||||
// createCmdArgs generates network configuration and creates command
|
||||
// arguments for a test case.
|
||||
func (tc testCase) createCmdArgs(targetNS ns.NetNS) *skel.CmdArgs {
|
||||
conf := tc.netConfJSON()
|
||||
func (tc testCase) createCmdArgs(targetNS ns.NetNS, dataDir string) *skel.CmdArgs {
|
||||
conf := tc.netConfJSON(dataDir)
|
||||
defer func() { counter += 1 }()
|
||||
return &skel.CmdArgs{
|
||||
ContainerID: fmt.Sprintf("dummy-%d", counter),
|
||||
@@ -213,9 +221,27 @@ func ipVersion(ip net.IP) string {
|
||||
return "6"
|
||||
}
|
||||
|
||||
func countIPAMIPs(path string) (int, error) {
|
||||
count := 0
|
||||
files, err := ioutil.ReadDir(path)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
for _, file := range files {
|
||||
if file.IsDir() {
|
||||
continue
|
||||
}
|
||||
|
||||
if net.ParseIP(file.Name()) != nil {
|
||||
count++
|
||||
}
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
type cmdAddDelTester interface {
|
||||
setNS(testNS ns.NetNS, targetNS ns.NetNS)
|
||||
cmdAddTest(tc testCase)
|
||||
cmdAddTest(tc testCase, dataDir string)
|
||||
cmdDelTest(tc testCase)
|
||||
}
|
||||
|
||||
@@ -240,9 +266,9 @@ func (tester *testerV03x) setNS(testNS ns.NetNS, targetNS ns.NetNS) {
|
||||
tester.targetNS = targetNS
|
||||
}
|
||||
|
||||
func (tester *testerV03x) cmdAddTest(tc testCase) {
|
||||
func (tester *testerV03x) cmdAddTest(tc testCase, dataDir string) {
|
||||
// Generate network config and command arguments
|
||||
tester.args = tc.createCmdArgs(tester.targetNS)
|
||||
tester.args = tc.createCmdArgs(tester.targetNS, dataDir)
|
||||
|
||||
// Execute cmdADD on the plugin
|
||||
var result *current.Result
|
||||
@@ -419,9 +445,9 @@ func (tester *testerV01xOr02x) setNS(testNS ns.NetNS, targetNS ns.NetNS) {
|
||||
tester.targetNS = targetNS
|
||||
}
|
||||
|
||||
func (tester *testerV01xOr02x) cmdAddTest(tc testCase) {
|
||||
func (tester *testerV01xOr02x) cmdAddTest(tc testCase, dataDir string) {
|
||||
// Generate network config and calculate gateway addresses
|
||||
tester.args = tc.createCmdArgs(tester.targetNS)
|
||||
tester.args = tc.createCmdArgs(tester.targetNS, dataDir)
|
||||
|
||||
// Execute cmdADD on the plugin
|
||||
err := tester.testNS.Do(func(ns.NetNS) error {
|
||||
@@ -537,7 +563,7 @@ func (tester *testerV01xOr02x) cmdDelTest(tc testCase) {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
}
|
||||
|
||||
func cmdAddDelTest(testNS ns.NetNS, tc testCase) {
|
||||
func cmdAddDelTest(testNS ns.NetNS, tc testCase, dataDir string) {
|
||||
// Get a Add/Del tester based on test case version
|
||||
tester := testerByVersion(tc.cniVersion)
|
||||
|
||||
@@ -547,7 +573,7 @@ func cmdAddDelTest(testNS ns.NetNS, tc testCase) {
|
||||
tester.setNS(testNS, targetNS)
|
||||
|
||||
// Test IP allocation
|
||||
tester.cmdAddTest(tc)
|
||||
tester.cmdAddTest(tc, dataDir)
|
||||
|
||||
// Test IP Release
|
||||
tester.cmdDelTest(tc)
|
||||
@@ -558,15 +584,23 @@ func cmdAddDelTest(testNS ns.NetNS, tc testCase) {
|
||||
|
||||
var _ = Describe("bridge Operations", func() {
|
||||
var originalNS ns.NetNS
|
||||
var dataDir string
|
||||
|
||||
BeforeEach(func() {
|
||||
// Create a new NetNS so we don't modify the host
|
||||
var err error
|
||||
originalNS, err = testutils.NewNS()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
dataDir, err = ioutil.TempDir("", "bridge_test")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
// Do not emulate an error, each test will set this if needed
|
||||
debugPostIPAMError = nil
|
||||
})
|
||||
|
||||
AfterEach(func() {
|
||||
Expect(os.RemoveAll(dataDir)).To(Succeed())
|
||||
Expect(originalNS.Close()).To(Succeed())
|
||||
})
|
||||
|
||||
@@ -661,7 +695,7 @@ var _ = Describe("bridge Operations", func() {
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
tc.cniVersion = "0.3.0"
|
||||
cmdAddDelTest(originalNS, tc)
|
||||
cmdAddDelTest(originalNS, tc, dataDir)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -691,7 +725,7 @@ var _ = Describe("bridge Operations", func() {
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
tc.cniVersion = "0.3.1"
|
||||
cmdAddDelTest(originalNS, tc)
|
||||
cmdAddDelTest(originalNS, tc, dataDir)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -707,7 +741,7 @@ var _ = Describe("bridge Operations", func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
defer targetNS.Close()
|
||||
tester.setNS(originalNS, targetNS)
|
||||
tester.args = tc.createCmdArgs(targetNS)
|
||||
tester.args = tc.createCmdArgs(targetNS, dataDir)
|
||||
|
||||
// Execute cmdDEL on the plugin, expect no errors
|
||||
tester.cmdDelTest(tc)
|
||||
@@ -739,7 +773,7 @@ var _ = Describe("bridge Operations", func() {
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
tc.cniVersion = "0.1.0"
|
||||
cmdAddDelTest(originalNS, tc)
|
||||
cmdAddDelTest(originalNS, tc, dataDir)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -909,11 +943,44 @@ var _ = Describe("bridge Operations", func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
origMac := link.Attrs().HardwareAddr
|
||||
|
||||
cmdAddDelTest(originalNS, tc)
|
||||
cmdAddDelTest(originalNS, tc, dataDir)
|
||||
|
||||
link, err = netlink.LinkByName(BRNAME)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(link.Attrs().HardwareAddr).To(Equal(origMac))
|
||||
}
|
||||
})
|
||||
|
||||
It("checks ip release in case of error", func() {
|
||||
err := originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
tc := testCase{
|
||||
cniVersion: "0.3.1",
|
||||
subnet: "10.1.2.0/24",
|
||||
}
|
||||
|
||||
_, _, err := setupBridge(tc.netConf())
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
args := tc.createCmdArgs(originalNS, dataDir)
|
||||
|
||||
// get number of allocated IPs before asking for a new one
|
||||
before, err := countIPAMIPs(dataDir)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
debugPostIPAMError = fmt.Errorf("debugPostIPAMError")
|
||||
_, _, err = testutils.CmdAddWithArgs(args, func() error {
|
||||
return cmdAdd(args)
|
||||
})
|
||||
Expect(err).To(MatchError("debugPostIPAMError"))
|
||||
|
||||
// get number of allocated IPs after failure
|
||||
after, err := countIPAMIPs(dataDir)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
Expect(before).To(Equal(after))
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
})
|
||||
|
||||
@@ -217,5 +217,11 @@ func getLink(devname, hwaddr, kernelpath string) (netlink.Link, error) {
|
||||
}
|
||||
|
||||
func main() {
|
||||
skel.PluginMain(cmdAdd, cmdDel, version.All)
|
||||
// TODO: implement plugin version
|
||||
skel.PluginMain(cmdAdd, cmdGet, cmdDel, version.All, "TODO")
|
||||
}
|
||||
|
||||
func cmdGet(args *skel.CmdArgs) error {
|
||||
// TODO: implement
|
||||
return fmt.Errorf("not implemented")
|
||||
}
|
||||
|
||||
@@ -245,5 +245,11 @@ func cmdDel(args *skel.CmdArgs) error {
|
||||
}
|
||||
|
||||
func main() {
|
||||
skel.PluginMain(cmdAdd, cmdDel, version.All)
|
||||
// TODO: implement plugin version
|
||||
skel.PluginMain(cmdAdd, cmdGet, cmdDel, version.All, "TODO")
|
||||
}
|
||||
|
||||
func cmdGet(args *skel.CmdArgs) error {
|
||||
// TODO: implement
|
||||
return fmt.Errorf("not implemented")
|
||||
}
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/containernetworking/cni/pkg/skel"
|
||||
"github.com/containernetworking/cni/pkg/types/current"
|
||||
"github.com/containernetworking/cni/pkg/version"
|
||||
@@ -68,5 +70,11 @@ func cmdDel(args *skel.CmdArgs) error {
|
||||
}
|
||||
|
||||
func main() {
|
||||
skel.PluginMain(cmdAdd, cmdDel, version.All)
|
||||
// TODO: implement plugin version
|
||||
skel.PluginMain(cmdAdd, cmdGet, cmdDel, version.All, "TODO")
|
||||
}
|
||||
|
||||
func cmdGet(args *skel.CmdArgs) error {
|
||||
// TODO: implement
|
||||
return fmt.Errorf("not implemented")
|
||||
}
|
||||
|
||||
@@ -58,6 +58,8 @@ var _ = Describe("Loopback", func() {
|
||||
|
||||
Context("when given a network namespace", func() {
|
||||
It("sets the lo device to UP", func() {
|
||||
|
||||
Skip("TODO: add network name")
|
||||
command.Env = append(environ, fmt.Sprintf("CNI_COMMAND=%s", "ADD"))
|
||||
|
||||
session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter)
|
||||
@@ -78,6 +80,8 @@ var _ = Describe("Loopback", func() {
|
||||
})
|
||||
|
||||
It("sets the lo device to DOWN", func() {
|
||||
|
||||
Skip("TODO: add network name")
|
||||
command.Env = append(environ, fmt.Sprintf("CNI_COMMAND=%s", "DEL"))
|
||||
|
||||
session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter)
|
||||
|
||||
@@ -255,5 +255,11 @@ func cmdDel(args *skel.CmdArgs) error {
|
||||
}
|
||||
|
||||
func main() {
|
||||
skel.PluginMain(cmdAdd, cmdDel, version.All)
|
||||
// TODO: implement plugin version
|
||||
skel.PluginMain(cmdAdd, cmdGet, cmdDel, version.All, "TODO")
|
||||
}
|
||||
|
||||
func cmdGet(args *skel.CmdArgs) error {
|
||||
// TODO: implement
|
||||
return fmt.Errorf("not implemented")
|
||||
}
|
||||
|
||||
@@ -285,5 +285,11 @@ func cmdDel(args *skel.CmdArgs) error {
|
||||
}
|
||||
|
||||
func main() {
|
||||
skel.PluginMain(cmdAdd, cmdDel, version.All)
|
||||
// TODO: implement plugin version
|
||||
skel.PluginMain(cmdAdd, cmdGet, cmdDel, version.All, "TODO")
|
||||
}
|
||||
|
||||
func cmdGet(args *skel.CmdArgs) error {
|
||||
// TODO: implement
|
||||
return fmt.Errorf("not implemented")
|
||||
}
|
||||
|
||||
@@ -192,5 +192,11 @@ func cmdDel(args *skel.CmdArgs) error {
|
||||
}
|
||||
|
||||
func main() {
|
||||
skel.PluginMain(cmdAdd, cmdDel, version.All)
|
||||
// TODO: implement plugin version
|
||||
skel.PluginMain(cmdAdd, cmdGet, cmdDel, version.All, "TODO")
|
||||
}
|
||||
|
||||
func cmdGet(args *skel.CmdArgs) error {
|
||||
// TODO: implement
|
||||
return fmt.Errorf("not implemented")
|
||||
}
|
||||
|
||||
@@ -48,10 +48,10 @@ The following is an example [json configuration list](https://github.com/contain
|
||||
The result is an `ifb` device in the host namespace redirecting to the `host-interface`, with `tc tbf` applied on the `ifb` device and the `container-interface`
|
||||
|
||||
## Network configuration reference
|
||||
* ingressRate: is the rate in Kbps at which traffic can enter an interface. (See http://man7.org/linux/man-pages/man8/tbf.8.html)
|
||||
* ingressBurst: is the maximum amount in Kb that tokens can be made available for instantaneously. (See http://man7.org/linux/man-pages/man8/tbf.8.html)
|
||||
* egressRate: is the rate in Kbps at which traffic can leave an interface. (See http://man7.org/linux/man-pages/man8/tbf.8.html)
|
||||
* egressBurst: is the maximum amount in Kb that tokens can be made available for instantaneously. (See http://man7.org/linux/man-pages/man8/tbf.8.html)
|
||||
* ingressRate: is the rate in bps at which traffic can enter an interface. (See http://man7.org/linux/man-pages/man8/tbf.8.html)
|
||||
* ingressBurst: is the maximum amount in bits that tokens can be made available for instantaneously. (See http://man7.org/linux/man-pages/man8/tbf.8.html)
|
||||
* egressRate: is the rate in bps at which traffic can leave an interface. (See http://man7.org/linux/man-pages/man8/tbf.8.html)
|
||||
* egressBurst: is the maximum amount in bits that tokens can be made available for instantaneously. (See http://man7.org/linux/man-pages/man8/tbf.8.html)
|
||||
|
||||
Both ingressRate and ingressBurst must be set in order to limit ingress bandwidth. If neither one is set, then ingress bandwidth is not limited.
|
||||
Both egressRate and egressBurst must be set in order to limit egress bandwidth. If neither one is set, then egress bandwidth is not limited.
|
||||
|
||||
@@ -80,7 +80,7 @@ var _ = Describe("bandwidth test", func() {
|
||||
"ingressRate": 8,
|
||||
"ingressBurst": 8,
|
||||
"egressRate": 16,
|
||||
"egressBurst": 9,
|
||||
"egressBurst": 8,
|
||||
"prevResult": {
|
||||
"interfaces": [
|
||||
{
|
||||
@@ -135,7 +135,7 @@ var _ = Describe("bandwidth test", func() {
|
||||
|
||||
Expect(qdiscs[0]).To(BeAssignableToTypeOf(&netlink.Tbf{}))
|
||||
Expect(qdiscs[0].(*netlink.Tbf).Rate).To(Equal(uint64(2)))
|
||||
Expect(qdiscs[0].(*netlink.Tbf).Limit).To(Equal(uint32(9)))
|
||||
Expect(qdiscs[0].(*netlink.Tbf).Limit).To(Equal(uint32(1)))
|
||||
|
||||
hostVethLink, err := netlink.LinkByName(hostIfname)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
@@ -163,7 +163,7 @@ var _ = Describe("bandwidth test", func() {
|
||||
|
||||
Expect(qdiscs[0]).To(BeAssignableToTypeOf(&netlink.Tbf{}))
|
||||
Expect(qdiscs[0].(*netlink.Tbf).Rate).To(Equal(uint64(1)))
|
||||
Expect(qdiscs[0].(*netlink.Tbf).Limit).To(Equal(uint32(8)))
|
||||
Expect(qdiscs[0].(*netlink.Tbf).Limit).To(Equal(uint32(1)))
|
||||
return nil
|
||||
})).To(Succeed())
|
||||
|
||||
@@ -176,8 +176,8 @@ var _ = Describe("bandwidth test", func() {
|
||||
"type": "bandwidth",
|
||||
"ingressRate": 0,
|
||||
"ingressBurst": 0,
|
||||
"egressRate": 8,
|
||||
"egressBurst": 1,
|
||||
"egressRate": 8000,
|
||||
"egressBurst": 80,
|
||||
"prevResult": {
|
||||
"interfaces": [
|
||||
{
|
||||
@@ -245,8 +245,8 @@ var _ = Describe("bandwidth test", func() {
|
||||
"type": "bandwidth",
|
||||
"egressRate": 0,
|
||||
"egressBurst": 0,
|
||||
"ingressRate": 8,
|
||||
"ingressBurst": 1,
|
||||
"ingressRate": 8000,
|
||||
"ingressBurst": 80,
|
||||
"prevResult": {
|
||||
"interfaces": [
|
||||
{
|
||||
@@ -302,8 +302,8 @@ var _ = Describe("bandwidth test", func() {
|
||||
Expect(qdiscs[0].Attrs().LinkIndex).To(Equal(containerIfLink.Attrs().Index))
|
||||
|
||||
Expect(qdiscs[0]).To(BeAssignableToTypeOf(&netlink.Tbf{}))
|
||||
Expect(qdiscs[0].(*netlink.Tbf).Rate).To(Equal(uint64(1)))
|
||||
Expect(qdiscs[0].(*netlink.Tbf).Limit).To(Equal(uint32(1)))
|
||||
Expect(qdiscs[0].(*netlink.Tbf).Rate).To(Equal(uint64(1000)))
|
||||
Expect(qdiscs[0].(*netlink.Tbf).Limit).To(Equal(uint32(35)))
|
||||
return nil
|
||||
})).To(Succeed())
|
||||
|
||||
@@ -426,7 +426,7 @@ var _ = Describe("bandwidth test", func() {
|
||||
|
||||
Expect(qdiscs[0]).To(BeAssignableToTypeOf(&netlink.Tbf{}))
|
||||
Expect(qdiscs[0].(*netlink.Tbf).Rate).To(Equal(uint64(2)))
|
||||
Expect(qdiscs[0].(*netlink.Tbf).Limit).To(Equal(uint32(9)))
|
||||
Expect(qdiscs[0].(*netlink.Tbf).Limit).To(Equal(uint32(1)))
|
||||
|
||||
hostVethLink, err := netlink.LinkByName(hostIfname)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
@@ -454,7 +454,7 @@ var _ = Describe("bandwidth test", func() {
|
||||
|
||||
Expect(qdiscs[0]).To(BeAssignableToTypeOf(&netlink.Tbf{}))
|
||||
Expect(qdiscs[0].(*netlink.Tbf).Rate).To(Equal(uint64(1)))
|
||||
Expect(qdiscs[0].(*netlink.Tbf).Limit).To(Equal(uint32(8)))
|
||||
Expect(qdiscs[0].(*netlink.Tbf).Limit).To(Equal(uint32(1)))
|
||||
return nil
|
||||
})).To(Succeed())
|
||||
|
||||
@@ -625,7 +625,7 @@ var _ = Describe("bandwidth test", func() {
|
||||
defer GinkgoRecover()
|
||||
|
||||
containerWithTbfRes, _, err = testutils.CmdAdd(containerWithTbfNS.Path(), "dummy", containerWithTbfIFName, []byte(ptpConf), func() error {
|
||||
r, err := invoke.DelegateAdd("ptp", []byte(ptpConf))
|
||||
r, err := invoke.DelegateAdd("ptp", []byte(ptpConf), nil)
|
||||
Expect(r.Print()).To(Succeed())
|
||||
|
||||
return err
|
||||
@@ -633,7 +633,7 @@ var _ = Describe("bandwidth test", func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
containerWithoutTbfRes, _, err = testutils.CmdAdd(containerWithoutTbfNS.Path(), "dummy2", containerWithoutTbfIFName, []byte(ptpConf), func() error {
|
||||
r, err := invoke.DelegateAdd("ptp", []byte(ptpConf))
|
||||
r, err := invoke.DelegateAdd("ptp", []byte(ptpConf), nil)
|
||||
Expect(r.Print()).To(Succeed())
|
||||
|
||||
return err
|
||||
|
||||
@@ -125,9 +125,10 @@ func createTBF(rateInBits, burstInBits, linkIndex int) error {
|
||||
return fmt.Errorf("invalid burst: %d", burstInBits)
|
||||
}
|
||||
rateInBytes := rateInBits / 8
|
||||
bufferInBytes := buffer(uint64(rateInBytes), uint32(burstInBits))
|
||||
burstInBytes := burstInBits / 8
|
||||
bufferInBytes := buffer(uint64(rateInBytes), uint32(burstInBytes))
|
||||
latency := latencyInUsec(latencyInMillis)
|
||||
limitInBytes := limit(uint64(rateInBytes), latency, uint32(bufferInBytes))
|
||||
limitInBytes := limit(uint64(rateInBytes), latency, uint32(burstInBytes))
|
||||
|
||||
qdisc := &netlink.Tbf{
|
||||
QdiscAttrs: netlink.QdiscAttrs{
|
||||
@@ -159,7 +160,7 @@ func buffer(rate uint64, burst uint32) uint32 {
|
||||
}
|
||||
|
||||
func limit(rate uint64, latency float64, buffer uint32) uint32 {
|
||||
return uint32(float64(rate) / float64(netlink.TIME_UNITS_PER_SEC) * (latency + float64(tick2Time(buffer))))
|
||||
return uint32(float64(rate)*latency/float64(netlink.TIME_UNITS_PER_SEC)) + buffer
|
||||
}
|
||||
|
||||
func latencyInUsec(latencyInMillis float64) float64 {
|
||||
|
||||
@@ -32,11 +32,11 @@ import (
|
||||
// BandwidthEntry corresponds to a single entry in the bandwidth argument,
|
||||
// see CONVENTIONS.md
|
||||
type BandwidthEntry struct {
|
||||
IngressRate int `json:"ingressRate"` //Bandwidth rate in Kbps for traffic through container. 0 for no limit. If ingressRate is set, ingressBurst must also be set
|
||||
IngressBurst int `json:"ingressBurst"` //Bandwidth burst in Kb for traffic through container. 0 for no limit. If ingressBurst is set, ingressRate must also be set
|
||||
IngressRate int `json:"ingressRate"` //Bandwidth rate in bps for traffic through container. 0 for no limit. If ingressRate is set, ingressBurst must also be set
|
||||
IngressBurst int `json:"ingressBurst"` //Bandwidth burst in bits for traffic through container. 0 for no limit. If ingressBurst is set, ingressRate must also be set
|
||||
|
||||
EgressRate int `json:"egressRate"` //Bandwidth rate in Kbps for traffic through container. 0 for no limit. If egressRate is set, egressBurst must also be set
|
||||
EgressBurst int `json:"egressBurst"` //Bandwidth burst in Kb for traffic through container. 0 for no limit. If egressBurst is set, egressRate must also be set
|
||||
EgressRate int `json:"egressRate"` //Bandwidth rate in bps for traffic through container. 0 for no limit. If egressRate is set, egressBurst must also be set
|
||||
EgressBurst int `json:"egressBurst"` //Bandwidth burst in bits for traffic through container. 0 for no limit. If egressBurst is set, egressRate must also be set
|
||||
}
|
||||
|
||||
func (bw *BandwidthEntry) isZero() bool {
|
||||
@@ -232,5 +232,11 @@ func cmdDel(args *skel.CmdArgs) error {
|
||||
}
|
||||
|
||||
func main() {
|
||||
skel.PluginMain(cmdAdd, cmdDel, version.PluginSupports("0.3.0", "0.3.1", version.Current()))
|
||||
// TODO: implement plugin version
|
||||
skel.PluginMain(cmdAdd, cmdGet, cmdDel, version.PluginSupports("0.3.0", "0.3.1", version.Current()), "TODO")
|
||||
}
|
||||
|
||||
func cmdGet(args *skel.CmdArgs) error {
|
||||
// TODO: implement
|
||||
return fmt.Errorf("not implemented")
|
||||
}
|
||||
|
||||
@@ -159,7 +159,7 @@ func delegateAdd(cid, dataDir string, netconf map[string]interface{}) error {
|
||||
return err
|
||||
}
|
||||
|
||||
result, err := invoke.DelegateAdd(netconf["type"].(string), netconfBytes)
|
||||
result, err := invoke.DelegateAdd(netconf["type"].(string), netconfBytes, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -261,9 +261,15 @@ func cmdDel(args *skel.CmdArgs) error {
|
||||
return fmt.Errorf("failed to parse netconf: %v", err)
|
||||
}
|
||||
|
||||
return invoke.DelegateDel(n.Type, netconfBytes)
|
||||
return invoke.DelegateDel(n.Type, netconfBytes, nil)
|
||||
}
|
||||
|
||||
func main() {
|
||||
skel.PluginMain(cmdAdd, cmdDel, version.All)
|
||||
// TODO: implement plugin version
|
||||
skel.PluginMain(cmdAdd, cmdGet, cmdDel, version.All, "TODO")
|
||||
}
|
||||
|
||||
func cmdGet(args *skel.CmdArgs) error {
|
||||
// TODO: implement
|
||||
return fmt.Errorf("not implemented")
|
||||
}
|
||||
|
||||
@@ -118,7 +118,13 @@ func cmdDel(args *skel.CmdArgs) error {
|
||||
}
|
||||
|
||||
func main() {
|
||||
skel.PluginMain(cmdAdd, cmdDel, version.PluginSupports("", "0.1.0", "0.2.0", "0.3.0", version.Current()))
|
||||
// TODO: implement plugin version
|
||||
skel.PluginMain(cmdAdd, cmdGet, cmdDel, version.All, "TODO")
|
||||
}
|
||||
|
||||
func cmdGet(args *skel.CmdArgs) error {
|
||||
// TODO: implement
|
||||
return fmt.Errorf("not implemented")
|
||||
}
|
||||
|
||||
// parseConfig parses the supplied configuration (and prevResult) from stdin.
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
@@ -29,6 +30,7 @@ import (
|
||||
"github.com/containernetworking/cni/pkg/types/current"
|
||||
"github.com/containernetworking/cni/pkg/version"
|
||||
"github.com/containernetworking/plugins/pkg/ns"
|
||||
"github.com/vishvananda/netlink"
|
||||
)
|
||||
|
||||
// TuningConf represents the network tuning configuration.
|
||||
@@ -37,14 +39,35 @@ type TuningConf struct {
|
||||
SysCtl map[string]string `json:"sysctl"`
|
||||
RawPrevResult map[string]interface{} `json:"prevResult,omitempty"`
|
||||
PrevResult *current.Result `json:"-"`
|
||||
Mac string `json:"mac,omitempty"`
|
||||
Promisc bool `json:"promisc,omitempty"`
|
||||
Mtu int `json:"mtu,omitempty"`
|
||||
}
|
||||
|
||||
func parseConf(data []byte) (*TuningConf, error) {
|
||||
conf := TuningConf{}
|
||||
type MACEnvArgs struct {
|
||||
types.CommonArgs
|
||||
MAC types.UnmarshallableString `json:"mac,omitempty"`
|
||||
}
|
||||
|
||||
func parseConf(data []byte, envArgs string) (*TuningConf, error) {
|
||||
conf := TuningConf{Promisc: false}
|
||||
if err := json.Unmarshal(data, &conf); err != nil {
|
||||
return nil, fmt.Errorf("failed to load netconf: %v", err)
|
||||
}
|
||||
|
||||
// Parse custom MAC from both env args
|
||||
if envArgs != "" {
|
||||
e := MACEnvArgs{}
|
||||
err := types.LoadArgs(envArgs, &e)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if e.MAC != "" {
|
||||
conf.Mac = string(e.MAC)
|
||||
}
|
||||
}
|
||||
|
||||
// Parse previous result.
|
||||
if conf.RawPrevResult != nil {
|
||||
resultBytes, err := json.Marshal(conf.RawPrevResult)
|
||||
@@ -65,8 +88,58 @@ func parseConf(data []byte) (*TuningConf, error) {
|
||||
return &conf, nil
|
||||
}
|
||||
|
||||
func changeMacAddr(ifName string, newMacAddr string) error {
|
||||
addr, err := net.ParseMAC(newMacAddr)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid args %v for MAC addr: %v", newMacAddr, err)
|
||||
}
|
||||
|
||||
link, err := netlink.LinkByName(ifName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get %q: %v", ifName, err)
|
||||
}
|
||||
|
||||
err = netlink.LinkSetDown(link)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to set %q down: %v", ifName, err)
|
||||
}
|
||||
err = netlink.LinkSetHardwareAddr(link, addr)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to set %q address to %q: %v", ifName, newMacAddr, err)
|
||||
}
|
||||
return netlink.LinkSetUp(link)
|
||||
}
|
||||
|
||||
func updateResultsMacAddr(config TuningConf, ifName string, newMacAddr string) {
|
||||
for _, i := range config.PrevResult.Interfaces {
|
||||
if i.Name == ifName {
|
||||
i.Mac = newMacAddr
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func changePromisc(ifName string, val bool) error {
|
||||
link, err := netlink.LinkByName(ifName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get %q: %v", ifName, err)
|
||||
}
|
||||
|
||||
if val {
|
||||
return netlink.SetPromiscOn(link)
|
||||
}
|
||||
return netlink.SetPromiscOff(link)
|
||||
}
|
||||
|
||||
func changeMtu(ifName string, mtu int) error {
|
||||
link, err := netlink.LinkByName(ifName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get %q: %v", ifName, err)
|
||||
}
|
||||
return netlink.LinkSetMTU(link, mtu)
|
||||
}
|
||||
|
||||
func cmdAdd(args *skel.CmdArgs) error {
|
||||
tuningConf, err := parseConf(args.StdinData)
|
||||
tuningConf, err := parseConf(args.StdinData, args.Args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -90,6 +163,25 @@ func cmdAdd(args *skel.CmdArgs) error {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if tuningConf.Mac != "" {
|
||||
if err = changeMacAddr(args.IfName, tuningConf.Mac); err != nil {
|
||||
return err
|
||||
}
|
||||
updateResultsMacAddr(*tuningConf, args.IfName, tuningConf.Mac)
|
||||
}
|
||||
|
||||
if tuningConf.Promisc != false {
|
||||
if err = changePromisc(args.IfName, true); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if tuningConf.Mtu != 0 {
|
||||
if err = changeMtu(args.IfName, tuningConf.Mtu); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
@@ -107,5 +199,11 @@ func cmdDel(args *skel.CmdArgs) error {
|
||||
}
|
||||
|
||||
func main() {
|
||||
skel.PluginMain(cmdAdd, cmdDel, version.All)
|
||||
// TODO: implement plugin version
|
||||
skel.PluginMain(cmdAdd, cmdGet, cmdDel, version.All, "TODO")
|
||||
}
|
||||
|
||||
func cmdGet(args *skel.CmdArgs) error {
|
||||
// TODO: implement
|
||||
return fmt.Errorf("not implemented")
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import (
|
||||
"github.com/containernetworking/cni/pkg/types/current"
|
||||
"github.com/containernetworking/plugins/pkg/ns"
|
||||
"github.com/containernetworking/plugins/pkg/testutils"
|
||||
"net"
|
||||
|
||||
"github.com/vishvananda/netlink"
|
||||
|
||||
@@ -109,4 +110,236 @@ var _ = Describe("tuning plugin", func() {
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
It("configures and deconfigures promiscas mode with ADD/DEL", func() {
|
||||
conf := []byte(`{
|
||||
"name": "test",
|
||||
"type": "iplink",
|
||||
"cniVersion": "0.3.1",
|
||||
"promisc": true,
|
||||
"prevResult": {
|
||||
"interfaces": [
|
||||
{"name": "dummy0", "sandbox":"netns"}
|
||||
],
|
||||
"ips": [
|
||||
{
|
||||
"version": "4",
|
||||
"address": "10.0.0.2/24",
|
||||
"gateway": "10.0.0.1",
|
||||
"interface": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
}`)
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
Netns: originalNS.Path(),
|
||||
IfName: IFNAME,
|
||||
StdinData: conf,
|
||||
}
|
||||
|
||||
err := originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
r, _, err := testutils.CmdAddWithArgs(args, func() error {
|
||||
return cmdAdd(args)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
result, err := current.GetResult(r)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
Expect(len(result.Interfaces)).To(Equal(1))
|
||||
Expect(result.Interfaces[0].Name).To(Equal(IFNAME))
|
||||
Expect(len(result.IPs)).To(Equal(1))
|
||||
Expect(result.IPs[0].Address.String()).To(Equal("10.0.0.2/24"))
|
||||
|
||||
link, err := netlink.LinkByName(IFNAME)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(link.Attrs().Promisc).To(Equal(1))
|
||||
|
||||
err = testutils.CmdDel(originalNS.Path(),
|
||||
args.ContainerID, "", func() error { return cmdDel(args) })
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
It("configures and deconfigures mtu with ADD/DEL", func() {
|
||||
conf := []byte(`{
|
||||
"name": "test",
|
||||
"type": "iplink",
|
||||
"cniVersion": "0.3.1",
|
||||
"mtu": 1454,
|
||||
"prevResult": {
|
||||
"interfaces": [
|
||||
{"name": "dummy0", "sandbox":"netns"}
|
||||
],
|
||||
"ips": [
|
||||
{
|
||||
"version": "4",
|
||||
"address": "10.0.0.2/24",
|
||||
"gateway": "10.0.0.1",
|
||||
"interface": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
}`)
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
Netns: originalNS.Path(),
|
||||
IfName: IFNAME,
|
||||
StdinData: conf,
|
||||
}
|
||||
|
||||
err := originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
r, _, err := testutils.CmdAddWithArgs(args, func() error {
|
||||
return cmdAdd(args)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
result, err := current.GetResult(r)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
Expect(len(result.Interfaces)).To(Equal(1))
|
||||
Expect(result.Interfaces[0].Name).To(Equal(IFNAME))
|
||||
Expect(len(result.IPs)).To(Equal(1))
|
||||
Expect(result.IPs[0].Address.String()).To(Equal("10.0.0.2/24"))
|
||||
|
||||
link, err := netlink.LinkByName(IFNAME)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(link.Attrs().MTU).To(Equal(1454))
|
||||
|
||||
err = testutils.CmdDel(originalNS.Path(),
|
||||
args.ContainerID, "", func() error { return cmdDel(args) })
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
It("configures and deconfigures mac address (from conf file) with ADD/DEL", func() {
|
||||
conf := []byte(`{
|
||||
"name": "test",
|
||||
"type": "iplink",
|
||||
"cniVersion": "0.3.1",
|
||||
"mac": "c2:11:22:33:44:55",
|
||||
"prevResult": {
|
||||
"interfaces": [
|
||||
{"name": "dummy0", "sandbox":"netns"}
|
||||
],
|
||||
"ips": [
|
||||
{
|
||||
"version": "4",
|
||||
"address": "10.0.0.2/24",
|
||||
"gateway": "10.0.0.1",
|
||||
"interface": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
}`)
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
Netns: originalNS.Path(),
|
||||
IfName: IFNAME,
|
||||
StdinData: conf,
|
||||
}
|
||||
|
||||
err := originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
r, _, err := testutils.CmdAddWithArgs(args, func() error {
|
||||
return cmdAdd(args)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
result, err := current.GetResult(r)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
Expect(len(result.Interfaces)).To(Equal(1))
|
||||
Expect(result.Interfaces[0].Name).To(Equal(IFNAME))
|
||||
Expect(len(result.IPs)).To(Equal(1))
|
||||
Expect(result.IPs[0].Address.String()).To(Equal("10.0.0.2/24"))
|
||||
|
||||
link, err := netlink.LinkByName(IFNAME)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
hw, err := net.ParseMAC("c2:11:22:33:44:55")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(link.Attrs().HardwareAddr).To(Equal(hw))
|
||||
|
||||
err = testutils.CmdDel(originalNS.Path(),
|
||||
args.ContainerID, "", func() error { return cmdDel(args) })
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
It("configures and deconfigures mac address (from CNI_ARGS) with ADD/DEL", func() {
|
||||
conf := []byte(`{
|
||||
"name": "test",
|
||||
"type": "iplink",
|
||||
"cniVersion": "0.3.1",
|
||||
"prevResult": {
|
||||
"interfaces": [
|
||||
{"name": "dummy0", "sandbox":"netns"}
|
||||
],
|
||||
"ips": [
|
||||
{
|
||||
"version": "4",
|
||||
"address": "10.0.0.2/24",
|
||||
"gateway": "10.0.0.1",
|
||||
"interface": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
}`)
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
Netns: originalNS.Path(),
|
||||
IfName: IFNAME,
|
||||
StdinData: conf,
|
||||
Args: "IgnoreUnknown=true;MAC=c2:11:22:33:44:66",
|
||||
}
|
||||
|
||||
err := originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
r, _, err := testutils.CmdAddWithArgs(args, func() error {
|
||||
return cmdAdd(args)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
result, err := current.GetResult(r)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
Expect(len(result.Interfaces)).To(Equal(1))
|
||||
Expect(result.Interfaces[0].Name).To(Equal(IFNAME))
|
||||
Expect(len(result.IPs)).To(Equal(1))
|
||||
Expect(result.IPs[0].Address.String()).To(Equal("10.0.0.2/24"))
|
||||
|
||||
link, err := netlink.LinkByName(IFNAME)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
hw, err := net.ParseMAC("c2:11:22:33:44:66")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(link.Attrs().HardwareAddr).To(Equal(hw))
|
||||
|
||||
err = testutils.CmdDel(originalNS.Path(),
|
||||
args.ContainerID, "", func() error { return cmdDel(args) })
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
})
|
||||
|
||||
@@ -141,5 +141,11 @@ func cmdDel(args *skel.CmdArgs) error {
|
||||
}
|
||||
|
||||
func main() {
|
||||
skel.PluginMain(cmdAdd, cmdDel, version.PluginSupports("", "0.1.0", "0.2.0", version.Current()))
|
||||
// TODO: implement plugin version
|
||||
skel.PluginMain(cmdAdd, cmdGet, cmdDel, version.All, "TODO")
|
||||
}
|
||||
|
||||
func cmdGet(args *skel.CmdArgs) error {
|
||||
// TODO: implement
|
||||
return fmt.Errorf("not implemented")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user