macvlan: make master config as optional
To ease of config, make master config as optional parameter. In default case, default route interface will be used for master.
This commit is contained in:
@ -23,7 +23,7 @@ Since each macvlan interface has its own MAC address, it makes it easy to use wi
|
|||||||
|
|
||||||
* `name` (string, required): the name of the network
|
* `name` (string, required): the name of the network
|
||||||
* `type` (string, required): "macvlan"
|
* `type` (string, required): "macvlan"
|
||||||
* `master` (string, required): name of the host interface to enslave
|
* `master` (string, optional): name of the host interface to enslave. Defaults to default route interace.
|
||||||
* `mode` (string, optional): one of "bridge", "private", "vepa", "passthru". Defaults to "bridge".
|
* `mode` (string, optional): one of "bridge", "private", "vepa", "passthru". Defaults to "bridge".
|
||||||
* `mtu` (integer, optional): explicitly set MTU to the specified value. Defaults to the value chosen by the kernel.
|
* `mtu` (integer, optional): explicitly set MTU to the specified value. Defaults to the value chosen by the kernel.
|
||||||
* `ipam` (dictionary, required): IPAM configuration to be used for this network.
|
* `ipam` (dictionary, required): IPAM configuration to be used for this network.
|
||||||
|
@ -51,13 +51,33 @@ func init() {
|
|||||||
runtime.LockOSThread()
|
runtime.LockOSThread()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getDefaultRouteInterfaceName() string {
|
||||||
|
routeToDstIP, err := netlink.RouteList(nil, netlink.FAMILY_ALL)
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, v := range routeToDstIP {
|
||||||
|
l, _ := netlink.LinkByIndex(v.LinkIndex)
|
||||||
|
if v.Dst == nil {
|
||||||
|
return l.Attrs().Name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
func loadConf(bytes []byte) (*NetConf, string, error) {
|
func loadConf(bytes []byte) (*NetConf, string, error) {
|
||||||
n := &NetConf{}
|
n := &NetConf{}
|
||||||
if err := json.Unmarshal(bytes, n); err != nil {
|
if err := json.Unmarshal(bytes, 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 == "" {
|
||||||
return nil, "", fmt.Errorf(`"master" field is required. It specifies the host interface name to virtualize`)
|
defaultRouteInterface := getDefaultRouteInterfaceName()
|
||||||
|
if defaultRouteInterface == "" {
|
||||||
|
return nil, "", fmt.Errorf(`cannot get default route interface for master`)
|
||||||
|
}
|
||||||
|
n.Master = defaultRouteInterface
|
||||||
}
|
}
|
||||||
return n, n.CNIVersion, nil
|
return n, n.CNIVersion, nil
|
||||||
}
|
}
|
||||||
|
@ -399,4 +399,115 @@ var _ = Describe("macvlan Operations", func() {
|
|||||||
})
|
})
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("configures and deconfigures a macvlan link with ADD/DEL, without master config", func() {
|
||||||
|
const IFNAME = "macvl0"
|
||||||
|
|
||||||
|
conf := `{
|
||||||
|
"cniVersion": "0.3.1",
|
||||||
|
"name": "mynet",
|
||||||
|
"type": "macvlan",
|
||||||
|
"ipam": {
|
||||||
|
"type": "host-local",
|
||||||
|
"subnet": "10.1.2.0/24"
|
||||||
|
}
|
||||||
|
}`
|
||||||
|
|
||||||
|
targetNs, err := testutils.NewNS()
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
defer targetNs.Close()
|
||||||
|
|
||||||
|
args := &skel.CmdArgs{
|
||||||
|
ContainerID: "dummy",
|
||||||
|
Netns: targetNs.Path(),
|
||||||
|
IfName: IFNAME,
|
||||||
|
StdinData: []byte(conf),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make MASTER_NAME as default route interface
|
||||||
|
err = originalNS.Do(func(ns.NetNS) error {
|
||||||
|
defer GinkgoRecover()
|
||||||
|
|
||||||
|
link, err := netlink.LinkByName(MASTER_NAME)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
err = netlink.LinkSetUp(link)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
var address = &net.IPNet{IP: net.IPv4(192, 0, 0, 1), Mask: net.CIDRMask(24, 32)}
|
||||||
|
var addr = &netlink.Addr{IPNet: address}
|
||||||
|
err = netlink.AddrAdd(link, addr)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
// add default gateway into MASTER
|
||||||
|
dst := &net.IPNet{
|
||||||
|
IP: net.IPv4(0, 0, 0, 0),
|
||||||
|
Mask: net.CIDRMask(0, 0),
|
||||||
|
}
|
||||||
|
ip := net.IPv4(192, 0, 0, 254)
|
||||||
|
route := netlink.Route{LinkIndex: link.Attrs().Index, Dst: dst, Gw: ip}
|
||||||
|
err = netlink.RouteAdd(&route)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
var result *current.Result
|
||||||
|
err = originalNS.Do(func(ns.NetNS) error {
|
||||||
|
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))
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
// Make sure macvlan 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))
|
||||||
|
|
||||||
|
hwaddr, err := net.ParseMAC(result.Interfaces[0].Mac)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(link.Attrs().HardwareAddr).To(Equal(hwaddr))
|
||||||
|
|
||||||
|
addrs, err := netlink.AddrList(link, syscall.AF_INET)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(len(addrs)).To(Equal(1))
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
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 macvlan 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())
|
||||||
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
|
Reference in New Issue
Block a user