// ConfigureIface takes the result of IPAM plugin and // applies to the ifName interface func ConfigureIface(ifName string, res *Result) error { link, err := netlink.LinkByName(ifName) if err != nil { return fmt.Errorf("failed to lookup %q: %v", ifName, err) } if err := netlink.LinkSetUp(link); err != nil { return fmt.Errorf("failed to set %q UP: %v", ifName, err) } // TODO(eyakubovich): IPv6 addr := &netlink.Addr{IPNet: &res.IP4.IP, Label: ""} if err = netlink.AddrAdd(link, addr); err != nil { return fmt.Errorf("failed to add IP addr to %q: %v", ifName, err) } for _, r := range res.IP4.Routes { gw := r.GW if gw == nil { gw = res.IP4.Gateway } if err = ip.AddRoute(&r.Dst, gw, link); err != nil { // we skip over duplicate routes as we assume the first one wins if !os.IsExist(err) { return fmt.Errorf("failed to add route '%v via %v dev %v': %v", r.Dst, gw, ifName, err) } } } return nil }
func setupHostVeth(vethName string, ipConf *types.IPConfig) error { // hostVeth moved namespaces and may have a new ifindex veth, err := netlink.LinkByName(vethName) if err != nil { return fmt.Errorf("failed to lookup %q: %v", vethName, err) } // TODO(eyakubovich): IPv6 ipn := &net.IPNet{ IP: ipConf.Gateway, Mask: net.CIDRMask(32, 32), } addr := &netlink.Addr{IPNet: ipn, Label: ""} if err = netlink.AddrAdd(veth, addr); err != nil { return fmt.Errorf("failed to add IP addr (%#v) to veth: %v", ipn, err) } ipn = &net.IPNet{ IP: ipConf.IP.IP, Mask: net.CIDRMask(32, 32), } // dst happens to be the same as IP/net of host veth if err = ip.AddHostRoute(ipn, nil, veth); err != nil && !os.IsExist(err) { return fmt.Errorf("failed to add route on host: %v", err) } return nil }
func ensureBridgeAddr(br *netlink.Bridge, ipn *net.IPNet) error { addrs, err := netlink.AddrList(br, syscall.AF_INET) if err != nil && err != syscall.ENOENT { return fmt.Errorf("could not get list of IP addresses: %v", err) } // if there're no addresses on the bridge, it's ok -- we'll add one if len(addrs) > 0 { ipnStr := ipn.String() for _, a := range addrs { // string comp is actually easiest for doing IPNet comps if a.IPNet.String() == ipnStr { return nil } } return fmt.Errorf("%q already has an IP address different from %v", br.Name, ipn.String()) } addr := &netlink.Addr{IPNet: ipn, Label: ""} if err := netlink.AddrAdd(br, addr); err != nil { return fmt.Errorf("could not add IP address to %q: %v", br.Name, err) } return nil }
// kvmSetup prepare new Networking to be used in kvm environment based on tuntap pair interfaces // to allow communication with virtual machine created by lkvm tool // right now it only supports default "ptp" network type (other types ends with error) func kvmSetup(podRoot string, podID types.UUID, fps []ForwardedPort, privateNetList common.PrivateNetList, localConfig string) (*Networking, error) { network := Networking{ podEnv: podEnv{ podRoot: podRoot, podID: podID, netsLoadList: privateNetList, localConfig: localConfig, }, } var e error network.nets, e = network.loadNets() if e != nil { return nil, fmt.Errorf("error loading network definitions: %v", e) } for _, n := range network.nets { switch n.conf.Type { case "ptp": link, err := setupTapDevice() if err != nil { return nil, err } ifName := link.Attrs().Name n.runtime.IfName = ifName err = kvmSetupNetAddressing(&network, n, ifName) if err != nil { return nil, err } // add address to host tap device err = netlink.AddrAdd( link, &netlink.Addr{ IPNet: &net.IPNet{ IP: n.runtime.HostIP, Mask: net.IPMask(n.runtime.Mask), }, Label: ifName, }) if err != nil { return nil, fmt.Errorf("cannot add address to host tap device %q: %v", ifName, err) } if n.conf.IPMasq { h := sha512.Sum512([]byte(podID.String())) chain := fmt.Sprintf("CNI-%s-%x", n.conf.Name, h[:8]) if err = ip.SetupIPMasq(&net.IPNet{ IP: n.runtime.IP, Mask: net.IPMask(n.runtime.Mask), }, chain); err != nil { return nil, err } } default: return nil, fmt.Errorf("network %q have unsupported type: %q", n.conf.Name, n.conf.Type) } } err := network.forwardPorts(fps, network.GetDefaultIP()) if err != nil { return nil, err } return &network, nil }