12 "github.com/sirupsen/logrus"
14 "github.com/containernetworking/cni/pkg/skel"
15 "github.com/containernetworking/cni/pkg/types/current"
16 "github.com/containernetworking/plugins/pkg/ip"
17 "github.com/containernetworking/plugins/pkg/ns"
18 "github.com/vishvananda/netlink"
21 func renameLink(curName, newName string) error {
22 link, err := netlink.LinkByName(curName)
27 if err := netlink.LinkSetDown(link); err != nil {
30 if err := netlink.LinkSetName(link, newName); err != nil {
33 if err := netlink.LinkSetUp(link); err != nil {
40 func setupInterface(netns ns.NetNS, containerID, ifName, macAddress, ipAddress, gatewayIP, defaultGateway string, mtu int) (*current.Interface, *current.Interface, error) {
41 hostIface := ¤t.Interface{}
42 contIface := ¤t.Interface{}
44 var oldHostVethName string
45 err := netns.Do(func(hostNS ns.NetNS) error {
46 // create the veth pair in the container and move host end into host netns
47 hostVeth, containerVeth, err := ip.SetupVeth(ifName, mtu, hostNS)
49 return fmt.Errorf("failed to setup veth %s: %v", ifName, err)
52 hostIface.Mac = hostVeth.HardwareAddr.String()
53 contIface.Name = containerVeth.Name
55 link, err := netlink.LinkByName(contIface.Name)
57 return fmt.Errorf("failed to lookup %s: %v", contIface.Name, err)
60 hwAddr, err := net.ParseMAC(macAddress)
62 return fmt.Errorf("failed to parse mac address for %s: %v", contIface.Name, err)
64 err = netlink.LinkSetHardwareAddr(link, hwAddr)
66 return fmt.Errorf("failed to add mac address %s to %s: %v", macAddress, contIface.Name, err)
68 contIface.Mac = macAddress
69 contIface.Sandbox = netns.Path()
71 addr, err := netlink.ParseAddr(ipAddress)
75 err = netlink.AddrAdd(link, addr)
77 return fmt.Errorf("failed to add IP addr %s to %s: %v", ipAddress, contIface.Name, err)
80 if defaultGateway == "true" {
81 gw := net.ParseIP(gatewayIP)
83 return fmt.Errorf("parse ip of gateway failed")
85 err = ip.AddRoute(nil, gw, link)
87 logrus.Errorf("ip.AddRoute failed %v gw %v link %v", err, gw, link)
91 oldHostVethName = hostVeth.Name
99 // rename the host end of veth pair
100 re := regexp.MustCompile("(\\d+)\\D*\\z")
101 index := re.FindAllString(ifName, -1)
102 hostIface.Name = containerID[:14] + index[0]
103 if err := renameLink(oldHostVethName, hostIface.Name); err != nil {
104 return nil, nil, fmt.Errorf("failed to rename %s to %s: %v", oldHostVethName, hostIface.Name, err)
107 return hostIface, contIface, nil
110 // ConfigureInterface sets up the container interface
111 var ConfigureInterface = func(args *skel.CmdArgs, namespace, podName, macAddress, ipAddress, gatewayIP, interfaceName, defaultGateway string, mtu int) ([]*current.Interface, error) {
112 netns, err := ns.GetNS(args.Netns)
114 return nil, fmt.Errorf("failed to open netns %q: %v", args.Netns, err)
117 hostIface, contIface, err := setupInterface(netns, args.ContainerID, interfaceName, macAddress, ipAddress, gatewayIP, defaultGateway, mtu)
122 if interfaceName != "" {
123 ifaceID = fmt.Sprintf("%s_%s_%s", namespace, podName, interfaceName)
125 ifaceID = fmt.Sprintf("%s_%s", namespace, podName)
129 "add-port", "br-int", hostIface.Name, "--", "set",
130 "interface", hostIface.Name,
131 fmt.Sprintf("external_ids:attached_mac=%s", macAddress),
132 fmt.Sprintf("external_ids:iface-id=%s", ifaceID),
133 fmt.Sprintf("external_ids:ip_address=%s", ipAddress),
134 fmt.Sprintf("external_ids:sandbox=%s", args.ContainerID),
138 out, err = exec.Command("ovs-vsctl", ovsArgs...).CombinedOutput()
140 return nil, fmt.Errorf("failure in plugging pod interface: %v\n %q", err, string(out))
143 return []*current.Interface{hostIface, contIface}, nil
146 func setupRoute(netns ns.NetNS, dst, gw, dev string) error {
147 // Add Route to the namespace
148 err := netns.Do(func(_ ns.NetNS) error {
149 dstAddr, dstAddrNet, _ := net.ParseCIDR(dst)
150 ipNet := net.IPNet{IP: dstAddr, Mask: dstAddrNet.Mask}
151 link, err := netlink.LinkByName(dev)
152 err = ip.AddRoute(&ipNet, net.ParseIP(gw), link)
154 logrus.Errorf("ip.AddRoute failed %v dst %v gw %v", err, dst, gw)
161 // ConfigureRoute sets up the container routes
162 var ConfigureRoute = func(args *skel.CmdArgs, dst, gw, dev string) error {
163 netns, err := ns.GetNS(args.Netns)
165 return fmt.Errorf("failed to open netns %q: %v", args.Netns, err)
168 err = setupRoute(netns, dst, gw, dev)
172 // PlatformSpecificCleanup deletes the OVS port
173 func PlatformSpecificCleanup(ifaceName string) (bool, error) {
176 "del-port", "br-int", ifaceName,
178 out, err := exec.Command("ovs-vsctl", ovsArgs...).CombinedOutput()
179 if err != nil && !strings.Contains(string(out), "no port named") {
180 // DEL should be idempotent; don't return an error just log it
181 logrus.Warningf("failed to delete OVS port %s: %v\n %q", ifaceName, err, string(out))