Add support for in-container master for vlans

Signed-off-by: mmirecki <mmirecki@redhat.com>
This commit is contained in:
mmirecki 2022-11-10 14:56:54 +01:00
parent ac8673105a
commit 9fa80036d3
2 changed files with 324 additions and 239 deletions

View File

@ -20,12 +20,11 @@ import (
"fmt" "fmt"
"runtime" "runtime"
"github.com/vishvananda/netlink"
"github.com/containernetworking/cni/pkg/skel" "github.com/containernetworking/cni/pkg/skel"
"github.com/containernetworking/cni/pkg/types" "github.com/containernetworking/cni/pkg/types"
current "github.com/containernetworking/cni/pkg/types/100" current "github.com/containernetworking/cni/pkg/types/100"
"github.com/containernetworking/cni/pkg/version" "github.com/containernetworking/cni/pkg/version"
"github.com/vishvananda/netlink"
"github.com/containernetworking/plugins/pkg/ip" "github.com/containernetworking/plugins/pkg/ip"
"github.com/containernetworking/plugins/pkg/ipam" "github.com/containernetworking/plugins/pkg/ipam"
@ -35,9 +34,10 @@ import (
type NetConf struct { type NetConf struct {
types.NetConf types.NetConf
Master string `json:"master"` Master string `json:"master"`
VlanId int `json:"vlanId"` VlanId int `json:"vlanId"`
MTU int `json:"mtu,omitempty"` MTU int `json:"mtu,omitempty"`
LinkContNs bool `json:"linkInContainer,omitempty"`
} }
func init() { func init() {
@ -47,9 +47,9 @@ func init() {
runtime.LockOSThread() runtime.LockOSThread()
} }
func loadConf(bytes []byte) (*NetConf, string, error) { func loadConf(args *skel.CmdArgs) (*NetConf, string, error) {
n := &NetConf{} n := &NetConf{}
if err := json.Unmarshal(bytes, n); err != nil { if err := json.Unmarshal(args.StdinData, n); err != nil {
return nil, "", fmt.Errorf("failed to load netconf: %v", err) return nil, "", fmt.Errorf("failed to load netconf: %v", err)
} }
if n.Master == "" { if n.Master == "" {
@ -60,19 +60,34 @@ func loadConf(bytes []byte) (*NetConf, string, error) {
} }
// check existing and MTU of master interface // check existing and MTU of master interface
masterMTU, err := getMTUByName(n.Master) masterMTU, err := getMTUByName(n.Master, args.Netns, n.LinkContNs)
if err != nil { if err != nil {
return nil, "", err return nil, "", err
} }
if n.MTU < 0 || n.MTU > masterMTU { if n.MTU < 0 || n.MTU > masterMTU {
return nil, "", fmt.Errorf("invalid MTU %d, must be [0, master MTU(%d)]", n.MTU, masterMTU) return nil, "", fmt.Errorf("invalid MTU %d, must be [0, master MTU(%d)]", n.MTU, masterMTU)
} }
return n, n.CNIVersion, nil return n, n.CNIVersion, nil
} }
func getMTUByName(ifName string) (int, error) { func getMTUByName(ifName string, namespace string, inContainer bool) (int, error) {
link, err := netlink.LinkByName(ifName) var link netlink.Link
var err error
if inContainer {
netns, err := ns.GetNS(namespace)
if err != nil {
return 0, fmt.Errorf("failed to open netns %q: %v", netns, err)
}
defer netns.Close()
err = netns.Do(func(_ ns.NetNS) error {
link, err = netlink.LinkByName(ifName)
return err
})
} else {
link, err = netlink.LinkByName(ifName)
}
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -82,7 +97,17 @@ func getMTUByName(ifName string) (int, error) {
func createVlan(conf *NetConf, ifName string, netns ns.NetNS) (*current.Interface, error) { func createVlan(conf *NetConf, ifName string, netns ns.NetNS) (*current.Interface, error) {
vlan := &current.Interface{} vlan := &current.Interface{}
m, err := netlink.LinkByName(conf.Master) var m netlink.Link
var err error
if conf.LinkContNs {
err = netns.Do(func(_ ns.NetNS) error {
m, err = netlink.LinkByName(conf.Master)
return err
})
} else {
m, err = netlink.LinkByName(conf.Master)
}
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to lookup master %q: %v", conf.Master, err) return nil, fmt.Errorf("failed to lookup master %q: %v", conf.Master, err)
} }
@ -104,7 +129,14 @@ func createVlan(conf *NetConf, ifName string, netns ns.NetNS) (*current.Interfac
VlanId: conf.VlanId, VlanId: conf.VlanId,
} }
if err := netlink.LinkAdd(v); err != nil { if conf.LinkContNs {
err = netns.Do(func(_ ns.NetNS) error {
return netlink.LinkAdd(v)
})
} else {
err = netlink.LinkAdd(v)
}
if err != nil {
return nil, fmt.Errorf("failed to create vlan: %v", err) return nil, fmt.Errorf("failed to create vlan: %v", err)
} }
@ -133,7 +165,7 @@ func createVlan(conf *NetConf, ifName string, netns ns.NetNS) (*current.Interfac
} }
func cmdAdd(args *skel.CmdArgs) error { func cmdAdd(args *skel.CmdArgs) error {
n, cniVersion, err := loadConf(args.StdinData) n, cniVersion, err := loadConf(args)
if err != nil { if err != nil {
return err return err
} }
@ -191,7 +223,7 @@ func cmdAdd(args *skel.CmdArgs) error {
} }
func cmdDel(args *skel.CmdArgs) error { func cmdDel(args *skel.CmdArgs) error {
n, _, err := loadConf(args.StdinData) n, _, err := loadConf(args)
if err != nil { if err != nil {
return err return err
} }
@ -276,8 +308,16 @@ func cmdCheck(args *skel.CmdArgs) error {
return fmt.Errorf("Sandbox in prevResult %s doesn't match configured netns: %s", return fmt.Errorf("Sandbox in prevResult %s doesn't match configured netns: %s",
contMap.Sandbox, args.Netns) contMap.Sandbox, args.Netns)
} }
var m netlink.Link
if conf.LinkContNs {
err = netns.Do(func(_ ns.NetNS) error {
m, err = netlink.LinkByName(conf.Master)
return err
})
} else {
m, err = netlink.LinkByName(conf.Master)
}
m, err := netlink.LinkByName(conf.Master)
if err != nil { if err != nil {
return fmt.Errorf("failed to lookup master %q: %v", conf.Master, err) return fmt.Errorf("failed to lookup master %q: %v", conf.Master, err)
} }

View File

@ -25,9 +25,9 @@ import (
"github.com/containernetworking/cni/pkg/skel" "github.com/containernetworking/cni/pkg/skel"
"github.com/containernetworking/cni/pkg/types" "github.com/containernetworking/cni/pkg/types"
"github.com/containernetworking/cni/pkg/types/020" types020 "github.com/containernetworking/cni/pkg/types/020"
"github.com/containernetworking/cni/pkg/types/040" types040 "github.com/containernetworking/cni/pkg/types/040"
"github.com/containernetworking/cni/pkg/types/100" types100 "github.com/containernetworking/cni/pkg/types/100"
"github.com/containernetworking/plugins/pkg/ns" "github.com/containernetworking/plugins/pkg/ns"
"github.com/containernetworking/plugins/pkg/testutils" "github.com/containernetworking/plugins/pkg/testutils"
@ -39,6 +39,7 @@ import (
) )
const MASTER_NAME = "eth0" const MASTER_NAME = "eth0"
const MASTER_NAME_INCONTAINER = "eth1"
type Net struct { type Net struct {
Name string `json:"name"` Name string `json:"name"`
@ -51,6 +52,7 @@ type Net struct {
DNS types.DNS `json:"dns"` DNS types.DNS `json:"dns"`
RawPrevResult map[string]interface{} `json:"prevResult,omitempty"` RawPrevResult map[string]interface{} `json:"prevResult,omitempty"`
PrevResult types100.Result `json:"-"` PrevResult types100.Result `json:"-"`
LinkContNs bool `json:"linkInContainer"`
} }
func buildOneConfig(netName string, cniVersion string, orig *Net, prevResult types.Result) (*Net, error) { func buildOneConfig(netName string, cniVersion string, orig *Net, prevResult types.Result) (*Net, error) {
@ -198,6 +200,24 @@ var _ = Describe("vlan Operations", func() {
return nil return nil
}) })
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
err = targetNS.Do(func(ns.NetNS) error {
defer GinkgoRecover()
// Add master
err = netlink.LinkAdd(&netlink.Dummy{
LinkAttrs: netlink.LinkAttrs{
Name: MASTER_NAME_INCONTAINER,
},
})
Expect(err).NotTo(HaveOccurred())
m, err := netlink.LinkByName(MASTER_NAME_INCONTAINER)
Expect(err).NotTo(HaveOccurred())
err = netlink.LinkSetUp(m)
Expect(err).NotTo(HaveOccurred())
return nil
})
Expect(err).NotTo(HaveOccurred())
}) })
AfterEach(func() { AfterEach(func() {
@ -208,283 +228,308 @@ var _ = Describe("vlan Operations", func() {
Expect(testutils.UnmountNS(targetNS)).To(Succeed()) Expect(testutils.UnmountNS(targetNS)).To(Succeed())
}) })
for _, ver := range testutils.AllSpecVersions { for _, inContainer := range []bool{false, true} {
// Redefine ver inside for scope so real value is picked up by each dynamically defined It() masterInterface := MASTER_NAME
// See Gingkgo's "Patterns for dynamically generating tests" documentation. if inContainer {
ver := ver masterInterface = MASTER_NAME_INCONTAINER
}
isInContainer := inContainer // Tests need a local var with constant value
It(fmt.Sprintf("[%s] creates an vlan link in a non-default namespace with given MTU", ver), func() { for _, ver := range testutils.AllSpecVersions {
conf := &NetConf{ // Redefine ver inside for scope so real value is picked up by each dynamically defined It()
NetConf: types.NetConf{ // See Gingkgo's "Patterns for dynamically generating tests" documentation.
CNIVersion: ver, ver := ver
Name: "testConfig",
Type: "vlan",
},
Master: MASTER_NAME,
VlanId: 33,
MTU: 1500,
}
// Create vlan in other namespace It(fmt.Sprintf("[%s] creates an vlan link in a non-default namespace with given MTU", ver), func() {
err := originalNS.Do(func(ns.NetNS) error { conf := &NetConf{
defer GinkgoRecover() NetConf: types.NetConf{
CNIVersion: ver,
Name: "testConfig",
Type: "vlan",
},
Master: masterInterface,
VlanId: 33,
MTU: 1500,
LinkContNs: isInContainer,
}
_, err := createVlan(conf, "foobar0", targetNS) // Create vlan in other namespace
err := originalNS.Do(func(ns.NetNS) error {
defer GinkgoRecover()
_, err := createVlan(conf, "foobar0", targetNS)
Expect(err).NotTo(HaveOccurred())
return nil
})
Expect(err).NotTo(HaveOccurred())
// Make sure vlan link exists in the target namespace
err = targetNS.Do(func(ns.NetNS) error {
defer GinkgoRecover()
link, err := netlink.LinkByName("foobar0")
Expect(err).NotTo(HaveOccurred())
Expect(link.Attrs().Name).To(Equal("foobar0"))
Expect(link.Attrs().MTU).To(Equal(1500))
return nil
})
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
return nil
}) })
Expect(err).NotTo(HaveOccurred())
// Make sure vlan link exists in the target namespace It(fmt.Sprintf("[%s] creates an vlan link in a non-default namespace with master's MTU", ver), func() {
err = targetNS.Do(func(ns.NetNS) error { conf := &NetConf{
defer GinkgoRecover() NetConf: types.NetConf{
CNIVersion: ver,
Name: "testConfig",
Type: "vlan",
},
Master: masterInterface,
VlanId: 33,
LinkContNs: isInContainer,
}
link, err := netlink.LinkByName("foobar0") // Create vlan in other namespace
otherNs := originalNS
if isInContainer {
otherNs = targetNS
}
err := otherNs.Do(func(ns.NetNS) error {
defer GinkgoRecover()
m, err := netlink.LinkByName(masterInterface)
Expect(err).NotTo(HaveOccurred())
err = netlink.LinkSetMTU(m, 1200)
Expect(err).NotTo(HaveOccurred())
_, err = createVlan(conf, "foobar0", targetNS)
Expect(err).NotTo(HaveOccurred())
return nil
})
Expect(err).NotTo(HaveOccurred())
// Make sure vlan link exists in the target namespace
err = targetNS.Do(func(ns.NetNS) error {
defer GinkgoRecover()
link, err := netlink.LinkByName("foobar0")
Expect(err).NotTo(HaveOccurred())
Expect(link.Attrs().Name).To(Equal("foobar0"))
Expect(link.Attrs().MTU).To(Equal(1200))
return nil
})
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
Expect(link.Attrs().Name).To(Equal("foobar0"))
Expect(link.Attrs().MTU).To(Equal(1500))
return nil
}) })
Expect(err).NotTo(HaveOccurred())
})
It(fmt.Sprintf("[%s] creates an vlan link in a non-default namespace with master's MTU", ver), func() { It(fmt.Sprintf("[%s] configures and deconfigures a vlan link with ADD/CHECK/DEL", ver), func() {
conf := &NetConf{ const IFNAME = "ethX"
NetConf: types.NetConf{
CNIVersion: ver,
Name: "testConfig",
Type: "vlan",
},
Master: MASTER_NAME,
VlanId: 33,
}
// Create vlan in other namespace conf := fmt.Sprintf(`{
err := originalNS.Do(func(ns.NetNS) error {
defer GinkgoRecover()
m, err := netlink.LinkByName(MASTER_NAME)
Expect(err).NotTo(HaveOccurred())
err = netlink.LinkSetMTU(m, 1200)
Expect(err).NotTo(HaveOccurred())
_, err = createVlan(conf, "foobar0", targetNS)
Expect(err).NotTo(HaveOccurred())
return nil
})
Expect(err).NotTo(HaveOccurred())
// Make sure vlan link exists in the target namespace
err = targetNS.Do(func(ns.NetNS) error {
defer GinkgoRecover()
link, err := netlink.LinkByName("foobar0")
Expect(err).NotTo(HaveOccurred())
Expect(link.Attrs().Name).To(Equal("foobar0"))
Expect(link.Attrs().MTU).To(Equal(1200))
return nil
})
Expect(err).NotTo(HaveOccurred())
})
It(fmt.Sprintf("[%s] configures and deconfigures a vlan link with ADD/CHECK/DEL", ver), func() {
const IFNAME = "eth0"
conf := fmt.Sprintf(`{
"cniVersion": "%s", "cniVersion": "%s",
"name": "vlanTestv4", "name": "vlanTestv4",
"type": "vlan", "type": "vlan",
"master": "%s", "master": "%s",
"vlanId": 1234, "vlanId": 1234,
"linkInContainer": %t,
"ipam": { "ipam": {
"type": "host-local", "type": "host-local",
"subnet": "10.1.2.0/24", "subnet": "10.1.2.0/24",
"dataDir": "%s" "dataDir": "%s"
} }
}`, ver, MASTER_NAME, dataDir) }`, ver, masterInterface, isInContainer, dataDir)
args := &skel.CmdArgs{ args := &skel.CmdArgs{
ContainerID: "dummy", ContainerID: "dummy",
Netns: targetNS.Path(), Netns: targetNS.Path(),
IfName: IFNAME, IfName: IFNAME,
StdinData: []byte(conf), StdinData: []byte(conf),
}
t := newTesterByVersion(ver)
var result types.Result
var macAddress string
err := originalNS.Do(func(ns.NetNS) error {
defer GinkgoRecover()
var err error
result, _, err = testutils.CmdAddWithArgs(args, func() error {
return cmdAdd(args)
})
Expect(err).NotTo(HaveOccurred())
macAddress = t.verifyResult(result, IFNAME)
return nil
})
Expect(err).NotTo(HaveOccurred())
// Make sure vlan link exists in the target namespace
err = targetNS.Do(func(ns.NetNS) error {
defer GinkgoRecover()
link, err := netlink.LinkByName(IFNAME)
Expect(err).NotTo(HaveOccurred())
Expect(link.Attrs().Name).To(Equal(IFNAME))
if macAddress != "" {
hwaddr, err := net.ParseMAC(macAddress)
Expect(err).NotTo(HaveOccurred())
Expect(link.Attrs().HardwareAddr).To(Equal(hwaddr))
} }
addrs, err := netlink.AddrList(link, syscall.AF_INET) t := newTesterByVersion(ver)
Expect(err).NotTo(HaveOccurred())
Expect(len(addrs)).To(Equal(1))
return nil
})
Expect(err).NotTo(HaveOccurred())
// call CmdCheck var result types.Result
n := &Net{} var macAddress string
err = json.Unmarshal([]byte(conf), &n) err := originalNS.Do(func(ns.NetNS) error {
Expect(err).NotTo(HaveOccurred()) defer GinkgoRecover()
n.IPAM, _, err = allocator.LoadIPAMConfig([]byte(conf), "") var err error
Expect(err).NotTo(HaveOccurred()) result, _, err = testutils.CmdAddWithArgs(args, func() error {
return cmdAdd(args)
})
Expect(err).NotTo(HaveOccurred())
newConf, err := buildOneConfig("vlanTestv4", ver, n, result) macAddress = t.verifyResult(result, IFNAME)
Expect(err).NotTo(HaveOccurred()) return nil
confString, err := json.Marshal(newConf)
Expect(err).NotTo(HaveOccurred())
args.StdinData = confString
// CNI Check host-device in the target namespace
err = originalNS.Do(func(ns.NetNS) error {
defer GinkgoRecover()
return testutils.CmdCheckWithArgs(args, func() error { return cmdCheck(args) })
})
if testutils.SpecVersionHasCHECK(ver) {
Expect(err).NotTo(HaveOccurred())
} else {
Expect(err).To(MatchError("config version does not allow CHECK"))
}
args.StdinData = []byte(conf)
err = originalNS.Do(func(ns.NetNS) error {
defer GinkgoRecover()
err = testutils.CmdDelWithArgs(args, func() error {
return cmdDel(args)
}) })
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
return nil
})
Expect(err).NotTo(HaveOccurred())
// Make sure vlan link has been deleted // Make sure vlan link exists in the target namespace
err = targetNS.Do(func(ns.NetNS) error { err = targetNS.Do(func(ns.NetNS) error {
defer GinkgoRecover() defer GinkgoRecover()
link, err := netlink.LinkByName(IFNAME) link, err := netlink.LinkByName(IFNAME)
Expect(err).To(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
Expect(link).To(BeNil()) Expect(link.Attrs().Name).To(Equal(IFNAME))
return nil
})
Expect(err).NotTo(HaveOccurred())
// DEL can be called multiple times, make sure no error is returned if macAddress != "" {
// if the device is already removed. hwaddr, err := net.ParseMAC(macAddress)
err = originalNS.Do(func(ns.NetNS) error { Expect(err).NotTo(HaveOccurred())
defer GinkgoRecover() Expect(link.Attrs().HardwareAddr).To(Equal(hwaddr))
}
err = testutils.CmdDelWithArgs(args, func() error { addrs, err := netlink.AddrList(link, syscall.AF_INET)
return cmdDel(args) Expect(err).NotTo(HaveOccurred())
Expect(len(addrs)).To(Equal(1))
return nil
}) })
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
return nil
})
Expect(err).NotTo(HaveOccurred())
})
Describe("fails to create vlan link with invalid MTU", func() { // call CmdCheck
const confFmt = `{ n := &Net{}
err = json.Unmarshal([]byte(conf), &n)
Expect(err).NotTo(HaveOccurred())
n.IPAM, _, err = allocator.LoadIPAMConfig([]byte(conf), "")
Expect(err).NotTo(HaveOccurred())
newConf, err := buildOneConfig("vlanTestv4", ver, n, result)
Expect(err).NotTo(HaveOccurred())
if isInContainer {
newConf.LinkContNs = true
}
confString, err := json.Marshal(newConf)
Expect(err).NotTo(HaveOccurred())
args.StdinData = confString
// CNI Check host-device in the target namespace
err = originalNS.Do(func(ns.NetNS) error {
defer GinkgoRecover()
return testutils.CmdCheckWithArgs(args, func() error { return cmdCheck(args) })
})
if testutils.SpecVersionHasCHECK(ver) {
Expect(err).NotTo(HaveOccurred())
} else {
Expect(err).To(MatchError("config version does not allow CHECK"))
}
args.StdinData = []byte(conf)
err = originalNS.Do(func(ns.NetNS) error {
defer GinkgoRecover()
err = testutils.CmdDelWithArgs(args, func() error {
return cmdDel(args)
})
Expect(err).NotTo(HaveOccurred())
return nil
})
Expect(err).NotTo(HaveOccurred())
// Make sure vlan link has been deleted
err = targetNS.Do(func(ns.NetNS) error {
defer GinkgoRecover()
link, err := netlink.LinkByName(IFNAME)
Expect(err).To(HaveOccurred())
Expect(link).To(BeNil())
return nil
})
Expect(err).NotTo(HaveOccurred())
// DEL can be called multiple times, make sure no error is returned
// if the device is already removed.
err = originalNS.Do(func(ns.NetNS) error {
defer GinkgoRecover()
err = testutils.CmdDelWithArgs(args, func() error {
return cmdDel(args)
})
Expect(err).NotTo(HaveOccurred())
return nil
})
Expect(err).NotTo(HaveOccurred())
})
Describe("fails to create vlan link with invalid MTU", func() {
const confFmt = `{
"cniVersion": "%s", "cniVersion": "%s",
"name": "mynet", "name": "mynet",
"type": "vlan", "type": "vlan",
"master": "%s", "master": "%s",
"mtu": %d, "mtu": %d,
"linkInContainer": %t,
"ipam": { "ipam": {
"type": "host-local", "type": "host-local",
"subnet": "10.1.2.0/24", "subnet": "10.1.2.0/24",
"dataDir": "%s" "dataDir": "%s"
} }
}` }`
BeforeEach(func() { BeforeEach(func() {
var err error var err error
err = originalNS.Do(func(ns.NetNS) error { sourceNS := originalNS
defer GinkgoRecover() if isInContainer {
sourceNS = targetNS
}
// set master link's MTU to 1500 err = sourceNS.Do(func(ns.NetNS) error {
link, err := netlink.LinkByName(MASTER_NAME) defer GinkgoRecover()
Expect(err).NotTo(HaveOccurred())
err = netlink.LinkSetMTU(link, 1500)
Expect(err).NotTo(HaveOccurred())
return nil // set master link's MTU to 1500
}) link, err := netlink.LinkByName(masterInterface)
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
}) err = netlink.LinkSetMTU(link, 1500)
Expect(err).NotTo(HaveOccurred())
It(fmt.Sprintf("[%s] fails to create vlan link with greater MTU than master interface", ver), func() { return nil
var err error
args := &skel.CmdArgs{
ContainerID: "dummy",
Netns: "/var/run/netns/test",
IfName: "eth0",
StdinData: []byte(fmt.Sprintf(confFmt, ver, MASTER_NAME, 1600, dataDir)),
}
_ = originalNS.Do(func(netNS ns.NetNS) error {
defer GinkgoRecover()
_, _, err = testutils.CmdAddWithArgs(args, func() error {
return cmdAdd(args)
}) })
Expect(err).To(Equal(fmt.Errorf("invalid MTU 1600, must be [0, master MTU(1500)]"))) Expect(err).NotTo(HaveOccurred())
return nil
}) })
})
It(fmt.Sprintf("[%s] fails to create vlan link with negative MTU", ver), func() { It(fmt.Sprintf("[%s] fails to create vlan link with greater MTU than master interface", ver), func() {
var err error var err error
args := &skel.CmdArgs{
ContainerID: "dummy",
Netns: targetNS.Path(),
IfName: "ethX",
StdinData: []byte(fmt.Sprintf(confFmt, ver, masterInterface, 1600, isInContainer, dataDir)),
}
args := &skel.CmdArgs{ _ = originalNS.Do(func(netNS ns.NetNS) error {
ContainerID: "dummy", defer GinkgoRecover()
Netns: "/var/run/netns/test",
IfName: "eth0",
StdinData: []byte(fmt.Sprintf(confFmt, ver, MASTER_NAME, -100, dataDir)),
}
_ = originalNS.Do(func(netNS ns.NetNS) error { _, _, err = testutils.CmdAddWithArgs(args, func() error {
defer GinkgoRecover() return cmdAdd(args)
})
_, _, err = testutils.CmdAddWithArgs(args, func() error { Expect(err).To(Equal(fmt.Errorf("invalid MTU 1600, must be [0, master MTU(1500)]")))
return cmdAdd(args) return nil
})
})
It(fmt.Sprintf("[%s] fails to create vlan link with negative MTU", ver), func() {
var err error
args := &skel.CmdArgs{
ContainerID: "dummy",
Netns: targetNS.Path(),
IfName: "ethX",
StdinData: []byte(fmt.Sprintf(confFmt, ver, masterInterface, -100, isInContainer, dataDir)),
}
_ = originalNS.Do(func(netNS ns.NetNS) error {
defer GinkgoRecover()
_, _, err = testutils.CmdAddWithArgs(args, func() error {
return cmdAdd(args)
})
Expect(err).To(Equal(fmt.Errorf("invalid MTU -100, must be [0, master MTU(1500)]")))
return nil
}) })
Expect(err).To(Equal(fmt.Errorf("invalid MTU -100, must be [0, master MTU(1500)]")))
return nil
}) })
}) })
}) }
} }
}) })