tap: allow for a tap device to be created as a bridge port
This extends the tap plugin API enabling the user to instruct the CNI plugin the created tap device must be set as a port of an *existing* linux bridge on the pod network namespace. This is helpful for KubeVirt, allowing network connectivity to be extended from the pod's interface into the Virtual Machine running inside the pod. Signed-off-by: Miguel Duarte Barroso <mdbarroso@redhat.com>
This commit is contained in:
parent
38f18d26ec
commit
edab9efdea
@ -47,6 +47,7 @@ type NetConf struct {
|
|||||||
Owner *uint32 `json:"owner,omitempty"`
|
Owner *uint32 `json:"owner,omitempty"`
|
||||||
Group *uint32 `json:"group,omitempty"`
|
Group *uint32 `json:"group,omitempty"`
|
||||||
SelinuxContext string `json:"selinuxContext,omitempty"`
|
SelinuxContext string `json:"selinuxContext,omitempty"`
|
||||||
|
Bridge string `json:"bridge,omitempty"`
|
||||||
Args *struct{} `json:"args,omitempty"`
|
Args *struct{} `json:"args,omitempty"`
|
||||||
RuntimeConfig struct {
|
RuntimeConfig struct {
|
||||||
Mac string `json:"mac,omitempty"`
|
Mac string `json:"mac,omitempty"`
|
||||||
@ -216,6 +217,18 @@ func createTap(conf *NetConf, ifName string, netns ns.NetNS) (*current.Interface
|
|||||||
return fmt.Errorf("failed to refetch tap %q: %v", ifName, err)
|
return fmt.Errorf("failed to refetch tap %q: %v", ifName, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if conf.Bridge != "" {
|
||||||
|
bridge, err := netlink.LinkByName(conf.Bridge)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get bridge %s: %v", conf.Bridge, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
tapDev := link
|
||||||
|
if err := netlink.LinkSetMaster(tapDev, bridge); err != nil {
|
||||||
|
return fmt.Errorf("failed to set tap %s as a port of bridge %s: %v", tap.Name, conf.Bridge, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
err = netlink.LinkSetUp(link)
|
err = netlink.LinkSetUp(link)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to set tap interface up: %v", err)
|
return fmt.Errorf("failed to set tap interface up: %v", err)
|
||||||
|
@ -314,5 +314,120 @@ var _ = Describe("Add, check, remove tap plugin", func() {
|
|||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It(fmt.Sprintf("[%s] add, check and remove a tap device as a bridge port", ver), func() {
|
||||||
|
const bridgeName = "br1"
|
||||||
|
conf := fmt.Sprintf(`{
|
||||||
|
"cniVersion": "%s",
|
||||||
|
"name": "tapTest",
|
||||||
|
"type": "tap",
|
||||||
|
"owner": 0,
|
||||||
|
"group": 0,
|
||||||
|
"bridge": %q,
|
||||||
|
"ipam": {
|
||||||
|
"type": "host-local",
|
||||||
|
"subnet": "10.1.2.0/24",
|
||||||
|
"dataDir": "%s"
|
||||||
|
}
|
||||||
|
}`, ver, bridgeName, dataDir)
|
||||||
|
|
||||||
|
args := &skel.CmdArgs{
|
||||||
|
ContainerID: "dummy",
|
||||||
|
Netns: targetNS.Path(),
|
||||||
|
IfName: IFNAME,
|
||||||
|
StdinData: []byte(conf),
|
||||||
|
}
|
||||||
|
|
||||||
|
t := newTesterByVersion(ver)
|
||||||
|
|
||||||
|
var bridge netlink.Link
|
||||||
|
var result types.Result
|
||||||
|
var macAddress string
|
||||||
|
var err error
|
||||||
|
|
||||||
|
Expect(
|
||||||
|
targetNS.Do(func(ns.NetNS) error {
|
||||||
|
if err := netlink.LinkAdd(&netlink.Bridge{
|
||||||
|
LinkAttrs: netlink.LinkAttrs{
|
||||||
|
Name: bridgeName,
|
||||||
|
},
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
bridge, err = netlink.LinkByName(bridgeName)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}),
|
||||||
|
).To(Succeed())
|
||||||
|
|
||||||
|
err = originalNS.Do(func(ns.NetNS) error {
|
||||||
|
defer GinkgoRecover()
|
||||||
|
|
||||||
|
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())
|
||||||
|
|
||||||
|
By("Make sure the tap 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))
|
||||||
|
Expect(link.Type()).To(Equal(TYPETAP))
|
||||||
|
Expect(link.Attrs().MasterIndex).To(Equal(bridge.Attrs().Index))
|
||||||
|
|
||||||
|
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)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(addrs).To(HaveLen(1))
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
By("Running cmdDel")
|
||||||
|
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())
|
||||||
|
|
||||||
|
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())
|
||||||
|
|
||||||
|
By("Running cmdDel more than once without error")
|
||||||
|
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())
|
||||||
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
Loading…
x
Reference in New Issue
Block a user