func (a *Allocator) getPredefinedPool(as string, ipV6 bool) (*net.IPNet, error) { var v ipVersion v = v4 if ipV6 { v = v6 } if as != localAddressSpace && as != globalAddressSpace { return nil, types.NotImplementedErrorf("no default pool availbale for non-default addresss spaces") } aSpace, err := a.getAddrSpace(as) if err != nil { return nil, err } for _, nw := range a.getPredefineds(as) { if v != getAddressVersion(nw.IP) { continue } aSpace.Lock() _, ok := aSpace.subnets[SubnetKey{AddressSpace: as, Subnet: nw.String()}] aSpace.Unlock() if ok { continue } if !aSpace.contains(as, nw) { return nw, nil } } return nil, types.NotFoundErrorf("could not find an available, non-overlapping IPv%d address pool among the defaults to assign to the network", v) }
func (c *controller) loadIPAMDriver(name string) error { if _, err := plugins.Get(name, ipamapi.PluginEndpointType); err != nil { if err == plugins.ErrNotFound { return types.NotFoundErrorf(err.Error()) } return err } return nil }
func (d *driver) getNetwork(id string) (*hnsNetwork, error) { d.Lock() defer d.Unlock() if nw, ok := d.networks[id]; ok { return nw, nil } return nil, types.NotFoundErrorf("network not found: %s", id) }
func (n *hnsNetwork) getEndpoint(eid string) (*hnsEndpoint, error) { n.Lock() defer n.Unlock() if ep, ok := n.endpoints[eid]; ok { return ep, nil } return nil, types.NotFoundErrorf("Endpoint not found: %s", eid) }
func (n *network) deriveAddressSpace() (string, error) { local, global, err := n.getController().drvRegistry.IPAMDefaultAddressSpaces(n.ipamType) if err != nil { return "", types.NotFoundErrorf("failed to get default address space: %v", err) } if n.DataScope() == datastore.GlobalScope { return global, nil } return local, nil }
func (d *driver) EndpointOperInfo(nid, eid types.UUID) (map[string]interface{}, error) { // Get the network handler and make sure it exists d.Lock() n, ok := d.networks[nid] d.Unlock() if !ok { return nil, types.NotFoundErrorf("network %s does not exist", nid) } if n == nil { return nil, driverapi.ErrNoNetwork(nid) } // Sanity check n.Lock() if n.id != nid { n.Unlock() return nil, InvalidNetworkIDError(nid) } n.Unlock() // Check if endpoint id is good and retrieve correspondent endpoint ep, err := n.getEndpoint(eid) if err != nil { return nil, err } if ep == nil { return nil, driverapi.ErrNoEndpoint(eid) } m := make(map[string]interface{}) if ep.config.ExposedPorts != nil { // Return a copy of the config data epc := make([]types.TransportPort, 0, len(ep.config.ExposedPorts)) for _, tp := range ep.config.ExposedPorts { epc = append(epc, tp.GetCopy()) } m[netlabel.ExposedPorts] = epc } if ep.portMapping != nil { // Return a copy of the operational data pmc := make([]types.PortBinding, 0, len(ep.portMapping)) for _, pm := range ep.portMapping { pmc = append(pmc, pm.GetCopy()) } m[netlabel.PortMap] = pmc } if len(ep.macAddress) != 0 { m[netlabel.MacAddress] = ep.macAddress } return m, nil }
// ReleaseAddress releases the address from the specified pool ID func (a *Allocator) ReleaseAddress(poolID string, address net.IP) error { logrus.Debugf("ReleaseAddress(%s, %v)", poolID, address) k := SubnetKey{} if err := k.FromString(poolID); err != nil { return types.BadRequestErrorf("invalid pool id: %s", poolID) } if err := a.refresh(k.AddressSpace); err != nil { return err } aSpace, err := a.getAddrSpace(k.AddressSpace) if err != nil { return err } aSpace.Lock() p, ok := aSpace.subnets[k] if !ok { aSpace.Unlock() return types.NotFoundErrorf("cannot find address pool for poolID:%s", poolID) } if address == nil { aSpace.Unlock() return types.BadRequestErrorf("invalid address: nil") } if !p.Pool.Contains(address) { aSpace.Unlock() return ipamapi.ErrIPOutOfRange } c := p for c.Range != nil { k = c.ParentKey c = aSpace.subnets[k] } aSpace.Unlock() mask := p.Pool.Mask h, err := types.GetHostPartIP(address, mask) if err != nil { return types.InternalErrorf("failed to release address %s: %v", address.String(), err) } bm, err := a.retrieveBitmask(k, c.Pool) if err != nil { return types.InternalErrorf("could not find bitmask in datastore for %s on address %v release from pool %s: %v", k.String(), address, poolID, err) } return bm.Unset(ipToUint64(h)) }
func (nDB *NetworkDB) getEntry(tname, nid, key string) (*entry, error) { nDB.RLock() defer nDB.RUnlock() e, ok := nDB.indexes[byTable].Get(fmt.Sprintf("/%s/%s/%s", tname, nid, key)) if !ok { return nil, types.NotFoundErrorf("could not get entry in table %s with network id %s and key %s", tname, nid, key) } return e.(*entry), nil }
func (d *Driver) getNetwork(id string) (*network, error) { d.Lock() defer d.Unlock() if id == "" { return nil, types.BadRequestErrorf("invalid network id: %s", id) } if nw, ok := d.networks[id]; ok { return nw, nil } return nil, types.NotFoundErrorf("network not found: %s", id) }
func (c *controller) isDriverGlobalScoped(networkType string) (bool, error) { c.Lock() dd, ok := c.drivers[networkType] c.Unlock() if !ok { return false, types.NotFoundErrorf("driver not found for %s", networkType) } if dd.capability.Scope == driverapi.GlobalScope { return true, nil } return false, nil }
func (c *controller) SandboxByID(id string) (Sandbox, error) { if id == "" { return nil, ErrInvalidID(id) } c.Lock() s, ok := c.sandboxes[id] c.Unlock() if !ok { return nil, types.NotFoundErrorf("sandbox %s not found", id) } return s, nil }
func (c *controller) loadDriver(networkType string) error { // Plugins pkg performs lazy loading of plugins that acts as remote drivers. // As per the design, this Get call will result in remote driver discovery if there is a corresponding plugin available. _, err := plugins.Get(networkType, driverapi.NetworkPluginEndpointType) if err != nil { if err == plugins.ErrNotFound { return types.NotFoundErrorf(err.Error()) } return err } return nil }
func (n *network) deriveAddressSpace() (string, error) { c := n.getController() c.Lock() ipd, ok := c.ipamDrivers[n.ipamType] c.Unlock() if !ok { return "", types.NotFoundErrorf("could not find ipam driver %s to get default address space", n.ipamType) } if n.DataScope() == datastore.GlobalScope { return ipd.defaultGlobalAddressSpace, nil } return ipd.defaultLocalAddressSpace, nil }
func (c *controller) loadIpamDriver(name string) (*ipamData, error) { if _, err := plugins.Get(name, ipamapi.PluginEndpointType); err != nil { if err == plugins.ErrNotFound { return nil, types.NotFoundErrorf(err.Error()) } return nil, err } c.Lock() id, ok := c.ipamDrivers[name] c.Unlock() if !ok { return nil, ErrInvalidNetworkDriver(name) } return id, nil }
// RequestAddress returns an address from the specified pool ID func (a *Allocator) RequestAddress(poolID string, prefAddress net.IP, opts map[string]string) (*net.IPNet, map[string]string, error) { logrus.Debugf("RequestAddress(%s, %v, %v)", poolID, prefAddress, opts) k := SubnetKey{} if err := k.FromString(poolID); err != nil { return nil, nil, types.BadRequestErrorf("invalid pool id: %s", poolID) } if err := a.refresh(k.AddressSpace); err != nil { return nil, nil, err } aSpace, err := a.getAddrSpace(k.AddressSpace) if err != nil { return nil, nil, err } aSpace.Lock() p, ok := aSpace.subnets[k] if !ok { aSpace.Unlock() return nil, nil, types.NotFoundErrorf("cannot find address pool for poolID:%s", poolID) } if prefAddress != nil && !p.Pool.Contains(prefAddress) { aSpace.Unlock() return nil, nil, ipamapi.ErrIPOutOfRange } c := p for c.Range != nil { k = c.ParentKey c, ok = aSpace.subnets[k] } aSpace.Unlock() bm, err := a.retrieveBitmask(k, c.Pool) if err != nil { return nil, nil, types.InternalErrorf("could not find bitmask in datastore for %s on address %v request from pool %s: %v", k.String(), prefAddress, poolID, err) } ip, err := a.getAddress(p.Pool, bm, prefAddress, p.Range) if err != nil { return nil, nil, err } return &net.IPNet{IP: ip, Mask: p.Pool.Mask}, nil, nil }
func (c *controller) loadDriver(networkType string) error { var err error if pg := c.GetPluginGetter(); pg != nil { _, err = pg.Get(networkType, driverapi.NetworkPluginEndpointType, plugingetter.Lookup) } else { _, err = plugins.Get(networkType, driverapi.NetworkPluginEndpointType) } if err != nil { if err == plugins.ErrNotFound { return types.NotFoundErrorf(err.Error()) } return err } return nil }
func (c *controller) loadDriver(networkType string) (*driverData, error) { // Plugins pkg performs lazy loading of plugins that acts as remote drivers. // As per the design, this Get call will result in remote driver discovery if there is a corresponding plugin available. _, err := plugins.Get(networkType, driverapi.NetworkPluginEndpointType) if err != nil { if err == plugins.ErrNotFound { return nil, types.NotFoundErrorf(err.Error()) } return nil, err } c.Lock() defer c.Unlock() dd, ok := c.drivers[networkType] if !ok { return nil, ErrInvalidNetworkDriver(networkType) } return dd, nil }
func (c *controller) loadIPAMDriver(name string) error { var err error if pg := c.GetPluginGetter(); pg != nil { _, err = pg.Get(name, ipamapi.PluginEndpointType, plugingetter.LOOKUP) } else { _, err = plugins.Get(name, ipamapi.PluginEndpointType) } if err != nil { if err == plugins.ErrNotFound { return types.NotFoundErrorf(err.Error()) } return err } return nil }
func (a *Allocator) getPredefinedPool(as string, ipV6 bool) (*net.IPNet, error) { var v ipVersion v = v4 if ipV6 { v = v6 } if as != localAddressSpace && as != globalAddressSpace { return nil, types.NotImplementedErrorf("no default pool availbale for non-default addresss spaces") } aSpace, err := a.getAddrSpace(as) if err != nil { return nil, err } for _, nw := range a.getPredefineds(as) { if v != getAddressVersion(nw.IP) { continue } aSpace.Lock() _, ok := aSpace.subnets[SubnetKey{AddressSpace: as, Subnet: nw.String()}] aSpace.Unlock() if ok { continue } if !aSpace.contains(as, nw) { if as == localAddressSpace { // Check if nw overlap with system routes, name servers if _, err := ipamutils.FindAvailableNetwork([]*net.IPNet{nw}); err == nil { return nw, nil } continue } return nw, nil } } return nil, types.NotFoundErrorf("could not find an available predefined network") }
func (a *Allocator) getPredefinedPool(as string, ipV6 bool) (*net.IPNet, error) { var v ipVersion v = v4 if ipV6 { v = v6 } if as != localAddressSpace && as != globalAddressSpace { return nil, fmt.Errorf("no default pool availbale for non-default addresss spaces") } cfg, err := a.getPoolsConfig(as) if err != nil { return nil, err } for _, nw := range a.getPredefineds(as) { if v != getAddressVersion(nw.IP) { continue } cfg.Lock() _, ok := cfg.subnets[SubnetKey{AddressSpace: as, Subnet: nw.String()}] cfg.Unlock() if ok { continue } if !cfg.contains(as, nw) { if as == localAddressSpace { if err := netutils.CheckRouteOverlaps(nw); err == nil { return nw, nil } continue } return nw, nil } } return nil, types.NotFoundErrorf("could not find an available predefined network") }
func (d *driver) DeleteEndpoint(nid, eid types.UUID) error { var err error defer sandbox.InitOSContext()() // Get the network handler and make sure it exists d.Lock() n, ok := d.networks[nid] d.Unlock() if !ok { return types.NotFoundErrorf("network %s does not exist", nid) } if n == nil { return driverapi.ErrNoNetwork(nid) } // Sanity Check n.Lock() if n.id != nid { n.Unlock() return InvalidNetworkIDError(nid) } n.Unlock() // Check endpoint id and if an endpoint is actually there ep, err := n.getEndpoint(eid) if err != nil { return err } if ep == nil { return EndpointNotFoundError(eid) } // Remove it n.Lock() delete(n.endpoints, eid) n.Unlock() // On failure make sure to set back ep in n.endpoints, but only // if it hasn't been taken over already by some other thread. defer func() { if err != nil { n.Lock() if _, ok := n.endpoints[eid]; !ok { n.endpoints[eid] = ep } n.Unlock() } }() // Remove port mappings. Do not stop endpoint delete on unmap failure n.releasePorts(ep) // Release the v4 address allocated to this endpoint's sandbox interface err = ipAllocator.ReleaseIP(n.bridge.bridgeIPv4, ep.addr.IP) if err != nil { return err } n.Lock() config := n.config n.Unlock() // Release the v6 address allocated to this endpoint's sandbox interface if config.EnableIPv6 { network := n.bridge.bridgeIPv6 if config.FixedCIDRv6 != nil { network = config.FixedCIDRv6 } err := ipAllocator.ReleaseIP(network, ep.addrv6.IP) if err != nil { return err } } // Try removal of link. Discard error: link pair might have // already been deleted by sandbox delete. link, err := netlink.LinkByName(ep.srcName) if err == nil { netlink.LinkDel(link) } return nil }
func (d *driver) CreateEndpoint(nid, eid types.UUID, epInfo driverapi.EndpointInfo, epOptions map[string]interface{}) error { var ( ipv6Addr *net.IPNet err error ) if epInfo == nil { return errors.New("invalid endpoint info passed") } if len(epInfo.Interfaces()) != 0 { return errors.New("non empty interface list passed to bridge(local) driver") } // Get the network handler and make sure it exists d.Lock() n, ok := d.networks[nid] if !ok { d.Unlock() return types.NotFoundErrorf("network %s does not exist", nid) } config := n.config d.Unlock() if n == nil { return driverapi.ErrNoNetwork(nid) } // Sanity check n.Lock() if n.id != nid { n.Unlock() return InvalidNetworkIDError(nid) } n.Unlock() // Check if endpoint id is good and retrieve correspondent endpoint ep, err := n.getEndpoint(eid) if err != nil { return err } // Endpoint with that id exists either on desired or other sandbox if ep != nil { return driverapi.ErrEndpointExists(eid) } // Try to convert the options to endpoint configuration epConfig, err := parseEndpointOptions(epOptions) if err != nil { return err } // Create and add the endpoint n.Lock() endpoint := &bridgeEndpoint{id: eid, config: epConfig} n.endpoints[eid] = endpoint n.Unlock() // On failure make sure to remove the endpoint defer func() { if err != nil { n.Lock() delete(n.endpoints, eid) n.Unlock() } }() // Generate a name for what will be the host side pipe interface name1, err := generateIfaceName() if err != nil { return err } // Generate a name for what will be the sandbox side pipe interface name2, err := generateIfaceName() if err != nil { return err } // Generate and add the interface pipe host <-> sandbox veth := &netlink.Veth{ LinkAttrs: netlink.LinkAttrs{Name: name1, TxQLen: 0}, PeerName: name2} if err = netlink.LinkAdd(veth); err != nil { return err } // Get the host side pipe interface handler host, err := netlink.LinkByName(name1) if err != nil { return err } defer func() { if err != nil { netlink.LinkDel(host) } }() // Get the sandbox side pipe interface handler sbox, err := netlink.LinkByName(name2) if err != nil { return err } defer func() { if err != nil { netlink.LinkDel(sbox) } }() // Set the sbox's MAC. If specified, use the one configured by user, otherwise use a random one mac := electMacAddress(epConfig) err = netlink.LinkSetHardwareAddr(sbox, mac) if err != nil { return err } endpoint.macAddress = mac // Add bridge inherited attributes to pipe interfaces if config.Mtu != 0 { err = netlink.LinkSetMTU(host, config.Mtu) if err != nil { return err } err = netlink.LinkSetMTU(sbox, config.Mtu) if err != nil { return err } } // Attach host side pipe interface into the bridge if err = netlink.LinkSetMaster(host, &netlink.Bridge{LinkAttrs: netlink.LinkAttrs{Name: config.BridgeName}}); err != nil { return err } // v4 address for the sandbox side pipe interface ip4, err := ipAllocator.RequestIP(n.bridge.bridgeIPv4, nil) if err != nil { return err } ipv4Addr := &net.IPNet{IP: ip4, Mask: n.bridge.bridgeIPv4.Mask} // v6 address for the sandbox side pipe interface ipv6Addr = &net.IPNet{} if config.EnableIPv6 { var ip6 net.IP network := n.bridge.bridgeIPv6 if config.FixedCIDRv6 != nil { network = config.FixedCIDRv6 } ones, _ := network.Mask.Size() if ones <= 80 { ip6 = make(net.IP, len(network.IP)) copy(ip6, network.IP) for i, h := range mac { ip6[i+10] = h } } ip6, err := ipAllocator.RequestIP(network, ip6) if err != nil { return err } ipv6Addr = &net.IPNet{IP: ip6, Mask: network.Mask} } // Create the sandbox side pipe interface intf := &sandbox.Interface{} intf.SrcName = name2 intf.DstName = containerVethPrefix intf.Address = ipv4Addr if config.EnableIPv6 { intf.AddressIPv6 = ipv6Addr } // Store the interface in endpoint, this is needed for cleanup on DeleteEndpoint() endpoint.intf = intf err = epInfo.AddInterface(ifaceID, endpoint.macAddress, *ipv4Addr, *ipv6Addr) if err != nil { return err } // Program any required port mapping and store them in the endpoint endpoint.portMapping, err = allocatePorts(epConfig, intf, config.DefaultBindingIP, config.EnableUserlandProxy) if err != nil { return err } return nil }
func (d *driver) DeleteEndpoint(nid, eid string) error { var err error defer osl.InitOSContext()() // Get the network handler and make sure it exists d.Lock() n, ok := d.networks[nid] d.Unlock() if !ok { return types.NotFoundErrorf("network %s does not exist", nid) } if n == nil { return driverapi.ErrNoNetwork(nid) } // Sanity Check n.Lock() if n.id != nid { n.Unlock() return InvalidNetworkIDError(nid) } n.Unlock() // Check endpoint id and if an endpoint is actually there ep, err := n.getEndpoint(eid) if err != nil { return err } if ep == nil { return EndpointNotFoundError(eid) } // Remove it n.Lock() delete(n.endpoints, eid) n.Unlock() // On failure make sure to set back ep in n.endpoints, but only // if it hasn't been taken over already by some other thread. defer func() { if err != nil { n.Lock() if _, ok := n.endpoints[eid]; !ok { n.endpoints[eid] = ep } n.Unlock() } }() // Remove port mappings. Do not stop endpoint delete on unmap failure n.releasePorts(ep) // Try removal of link. Discard error: link pair might have // already been deleted by sandbox delete. Make sure defer // does not see this error either. if link, err := netlink.LinkByName(ep.srcName); err == nil { netlink.LinkDel(link) } return nil }
func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, epOptions map[string]interface{}) error { if ifInfo == nil { return errors.New("invalid interface passed") } // Get the network handler and make sure it exists d.Lock() n, ok := d.networks[nid] d.Unlock() if !ok { return types.NotFoundErrorf("network %s does not exist", nid) } if n == nil { return driverapi.ErrNoNetwork(nid) } // Sanity check n.Lock() if n.id != nid { n.Unlock() return InvalidNetworkIDError(nid) } n.Unlock() // Check if endpoint id is good and retrieve correspondent endpoint ep, err := n.getEndpoint(eid) if err != nil { return err } // Endpoint with that id exists either on desired or other sandbox if ep != nil { return driverapi.ErrEndpointExists(eid) } // Try to convert the options to endpoint configuration epConfig, err := parseEndpointOptions(epOptions) if err != nil { return err } // Create and add the endpoint n.Lock() endpoint := &bridgeEndpoint{id: eid, config: epConfig} n.endpoints[eid] = endpoint n.Unlock() // On failure make sure to remove the endpoint defer func() { if err != nil { n.Lock() delete(n.endpoints, eid) n.Unlock() } }() // Create the sandbox side pipe interface if ifInfo.MacAddress() == nil { // No MAC address assigned to interface. Generate a random MAC to assign endpoint.macAddress = netutils.GenerateRandomMAC() if err := ifInfo.SetMacAddress(endpoint.macAddress); err != nil { logrus.Warnf("Unable to set mac address: %s to endpoint: %s", endpoint.macAddress.String(), endpoint.id) return err } } else { endpoint.macAddress = ifInfo.MacAddress() } endpoint.addr = ifInfo.Address() endpoint.addrv6 = ifInfo.AddressIPv6() c := n.config // Program any required port mapping and store them in the endpoint endpoint.portMapping, err = n.allocatePorts(endpoint, c.DefaultBindingIntf, c.DefaultBindingIP, true) if err != nil { return err } return nil }
func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, epOptions map[string]interface{}) error { defer osl.InitOSContext()() if ifInfo == nil { return errors.New("invalid interface info passed") } // Get the network handler and make sure it exists d.Lock() n, ok := d.networks[nid] dconfig := d.config d.Unlock() if !ok { return types.NotFoundErrorf("network %s does not exist", nid) } if n == nil { return driverapi.ErrNoNetwork(nid) } // Sanity check n.Lock() if n.id != nid { n.Unlock() return InvalidNetworkIDError(nid) } n.Unlock() // Check if endpoint id is good and retrieve correspondent endpoint ep, err := n.getEndpoint(eid) if err != nil { return err } // Endpoint with that id exists either on desired or other sandbox if ep != nil { return driverapi.ErrEndpointExists(eid) } // Try to convert the options to endpoint configuration epConfig, err := parseEndpointOptions(epOptions) if err != nil { return err } // Create and add the endpoint n.Lock() endpoint := &bridgeEndpoint{id: eid, config: epConfig} n.endpoints[eid] = endpoint n.Unlock() // On failure make sure to remove the endpoint defer func() { if err != nil { n.Lock() delete(n.endpoints, eid) n.Unlock() } }() // Generate a name for what will be the host side pipe interface hostIfName, err := netutils.GenerateIfaceName(vethPrefix, vethLen) if err != nil { return err } // Generate a name for what will be the sandbox side pipe interface containerIfName, err := netutils.GenerateIfaceName(vethPrefix, vethLen) if err != nil { return err } // Generate and add the interface pipe host <-> sandbox veth := &netlink.Veth{ LinkAttrs: netlink.LinkAttrs{Name: hostIfName, TxQLen: 0}, PeerName: containerIfName} if err = netlink.LinkAdd(veth); err != nil { return types.InternalErrorf("failed to add the host (%s) <=> sandbox (%s) pair interfaces: %v", hostIfName, containerIfName, err) } // Get the host side pipe interface handler host, err := netlink.LinkByName(hostIfName) if err != nil { return types.InternalErrorf("failed to find host side interface %s: %v", hostIfName, err) } defer func() { if err != nil { netlink.LinkDel(host) } }() // Get the sandbox side pipe interface handler sbox, err := netlink.LinkByName(containerIfName) if err != nil { return types.InternalErrorf("failed to find sandbox side interface %s: %v", containerIfName, err) } defer func() { if err != nil { netlink.LinkDel(sbox) } }() n.Lock() config := n.config n.Unlock() // Add bridge inherited attributes to pipe interfaces if config.Mtu != 0 { err = netlink.LinkSetMTU(host, config.Mtu) if err != nil { return types.InternalErrorf("failed to set MTU on host interface %s: %v", hostIfName, err) } err = netlink.LinkSetMTU(sbox, config.Mtu) if err != nil { return types.InternalErrorf("failed to set MTU on sandbox interface %s: %v", containerIfName, err) } } // Attach host side pipe interface into the bridge if err = addToBridge(hostIfName, config.BridgeName); err != nil { return fmt.Errorf("adding interface %s to bridge %s failed: %v", hostIfName, config.BridgeName, err) } if !dconfig.EnableUserlandProxy { err = setHairpinMode(host, true) if err != nil { return err } } // Store the sandbox side pipe interface parameters endpoint.srcName = containerIfName endpoint.macAddress = ifInfo.MacAddress() endpoint.addr = ifInfo.Address() endpoint.addrv6 = ifInfo.AddressIPv6() // Set the sbox's MAC if not provided. If specified, use the one configured by user, otherwise generate one based on IP. if endpoint.macAddress == nil { endpoint.macAddress = electMacAddress(epConfig, endpoint.addr.IP) if err = ifInfo.SetMacAddress(endpoint.macAddress); err != nil { return err } } // Up the host interface after finishing all netlink configuration if err = netlink.LinkSetUp(host); err != nil { return fmt.Errorf("could not set link up for host interface %s: %v", hostIfName, err) } if endpoint.addrv6 == nil && config.EnableIPv6 { var ip6 net.IP network := n.bridge.bridgeIPv6 if config.AddressIPv6 != nil { network = config.AddressIPv6 } ones, _ := network.Mask.Size() if ones > 80 { err = types.ForbiddenErrorf("Cannot self generate an IPv6 address on network %v: At least 48 host bits are needed.", network) return err } ip6 = make(net.IP, len(network.IP)) copy(ip6, network.IP) for i, h := range endpoint.macAddress { ip6[i+10] = h } endpoint.addrv6 = &net.IPNet{IP: ip6, Mask: network.Mask} if err = ifInfo.SetIPAddress(endpoint.addrv6); err != nil { return err } } return nil }
func (d *driver) CreateEndpoint(nid, eid types.UUID, epInfo driverapi.EndpointInfo, epOptions map[string]interface{}) error { var ( ipv6Addr *net.IPNet err error ) defer sandbox.InitOSContext()() if epInfo == nil { return errors.New("invalid endpoint info passed") } if len(epInfo.Interfaces()) != 0 { return errors.New("non empty interface list passed to bridge(local) driver") } // Get the network handler and make sure it exists d.Lock() n, ok := d.networks[nid] d.Unlock() if !ok { return types.NotFoundErrorf("network %s does not exist", nid) } if n == nil { return driverapi.ErrNoNetwork(nid) } // Sanity check n.Lock() if n.id != nid { n.Unlock() return InvalidNetworkIDError(nid) } n.Unlock() // Check if endpoint id is good and retrieve correspondent endpoint ep, err := n.getEndpoint(eid) if err != nil { return err } // Endpoint with that id exists either on desired or other sandbox if ep != nil { return driverapi.ErrEndpointExists(eid) } // Try to convert the options to endpoint configuration epConfig, err := parseEndpointOptions(epOptions) if err != nil { return err } // Create and add the endpoint n.Lock() endpoint := &bridgeEndpoint{id: eid, config: epConfig} n.endpoints[eid] = endpoint n.Unlock() // On failure make sure to remove the endpoint defer func() { if err != nil { n.Lock() delete(n.endpoints, eid) n.Unlock() } }() // Generate a name for what will be the host side pipe interface hostIfName, err := netutils.GenerateIfaceName(vethPrefix, vethLen) if err != nil { return err } // Generate a name for what will be the sandbox side pipe interface containerIfName, err := netutils.GenerateIfaceName(vethPrefix, vethLen) if err != nil { return err } // Generate and add the interface pipe host <-> sandbox veth := &netlink.Veth{ LinkAttrs: netlink.LinkAttrs{Name: hostIfName, TxQLen: 0}, PeerName: containerIfName} if err = netlink.LinkAdd(veth); err != nil { return err } // Get the host side pipe interface handler host, err := netlink.LinkByName(hostIfName) if err != nil { return err } defer func() { if err != nil { netlink.LinkDel(host) } }() // Get the sandbox side pipe interface handler sbox, err := netlink.LinkByName(containerIfName) if err != nil { return err } defer func() { if err != nil { netlink.LinkDel(sbox) } }() n.Lock() config := n.config n.Unlock() // Add bridge inherited attributes to pipe interfaces if config.Mtu != 0 { err = netlink.LinkSetMTU(host, config.Mtu) if err != nil { return err } err = netlink.LinkSetMTU(sbox, config.Mtu) if err != nil { return err } } // Attach host side pipe interface into the bridge if err = addToBridge(hostIfName, config.BridgeName); err != nil { return fmt.Errorf("adding interface %s to bridge %s failed: %v", hostIfName, config.BridgeName, err) } if !config.EnableUserlandProxy { err = setHairpinMode(host, true) if err != nil { return err } } // v4 address for the sandbox side pipe interface ip4, err := ipAllocator.RequestIP(n.bridge.bridgeIPv4, nil) if err != nil { return err } ipv4Addr := &net.IPNet{IP: ip4, Mask: n.bridge.bridgeIPv4.Mask} // Down the interface before configuring mac address. if err = netlink.LinkSetDown(sbox); err != nil { return fmt.Errorf("could not set link down for container interface %s: %v", containerIfName, err) } // Set the sbox's MAC. If specified, use the one configured by user, otherwise generate one based on IP. mac := electMacAddress(epConfig, ip4) err = netlink.LinkSetHardwareAddr(sbox, mac) if err != nil { return fmt.Errorf("could not set mac address for container interface %s: %v", containerIfName, err) } endpoint.macAddress = mac // Up the host interface after finishing all netlink configuration if err = netlink.LinkSetUp(host); err != nil { return fmt.Errorf("could not set link up for host interface %s: %v", hostIfName, err) } // v6 address for the sandbox side pipe interface ipv6Addr = &net.IPNet{} if config.EnableIPv6 { var ip6 net.IP network := n.bridge.bridgeIPv6 if config.FixedCIDRv6 != nil { network = config.FixedCIDRv6 } ones, _ := network.Mask.Size() if ones <= 80 { ip6 = make(net.IP, len(network.IP)) copy(ip6, network.IP) for i, h := range mac { ip6[i+10] = h } } ip6, err := ipAllocator.RequestIP(network, ip6) if err != nil { return err } ipv6Addr = &net.IPNet{IP: ip6, Mask: network.Mask} } // Create the sandbox side pipe interface endpoint.srcName = containerIfName endpoint.addr = ipv4Addr if config.EnableIPv6 { endpoint.addrv6 = ipv6Addr } err = epInfo.AddInterface(ifaceID, endpoint.macAddress, *ipv4Addr, *ipv6Addr) if err != nil { return err } // Program any required port mapping and store them in the endpoint endpoint.portMapping, err = n.allocatePorts(epConfig, endpoint, config.DefaultBindingIP, config.EnableUserlandProxy) if err != nil { return err } return nil }
func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, epOptions map[string]interface{}) error { defer osl.InitOSContext()() if ifInfo == nil { return errors.New("invalid interface info passed") } // Get the network handler and make sure it exists d.Lock() n, ok := d.networks[nid] dconfig := d.config d.Unlock() if !ok { return types.NotFoundErrorf("network %s does not exist", nid) } if n == nil { return driverapi.ErrNoNetwork(nid) } // Sanity check n.Lock() if n.id != nid { n.Unlock() return InvalidNetworkIDError(nid) } n.Unlock() // Check if endpoint id is good and retrieve correspondent endpoint ep, err := n.getEndpoint(eid) if err != nil { return err } // Endpoint with that id exists either on desired or other sandbox if ep != nil { return driverapi.ErrEndpointExists(eid) } // Try to convert the options to endpoint configuration epConfig, err := parseEndpointOptions(epOptions) if err != nil { return err } // Create and add the endpoint n.Lock() endpoint := &bridgeEndpoint{id: eid, config: epConfig} n.endpoints[eid] = endpoint n.Unlock() // On failure make sure to remove the endpoint defer func() { if err != nil { n.Lock() delete(n.endpoints, eid) n.Unlock() } }() // Generate a name for what will be the host side pipe interface hostIfName, err := netutils.GenerateIfaceName(vethPrefix, vethLen) if err != nil { return err } // Generate a name for what will be the sandbox side pipe interface containerIfName, err := netutils.GenerateIfaceName(vethPrefix, vethLen) if err != nil { return err } // Generate and add the interface pipe host <-> sandbox veth := &netlink.Veth{ LinkAttrs: netlink.LinkAttrs{Name: hostIfName, TxQLen: 0}, PeerName: containerIfName} if err = netlink.LinkAdd(veth); err != nil { return types.InternalErrorf("failed to add the host (%s) <=> sandbox (%s) pair interfaces: %v", hostIfName, containerIfName, err) } // Get the host side pipe interface handler host, err := netlink.LinkByName(hostIfName) if err != nil { return types.InternalErrorf("failed to find host side interface %s: %v", hostIfName, err) } defer func() { if err != nil { netlink.LinkDel(host) } }() // Get the sandbox side pipe interface handler sbox, err := netlink.LinkByName(containerIfName) if err != nil { return types.InternalErrorf("failed to find sandbox side interface %s: %v", containerIfName, err) } defer func() { if err != nil { netlink.LinkDel(sbox) } }() n.Lock() config := n.config n.Unlock() // Add bridge inherited attributes to pipe interfaces if config.Mtu != 0 { err = netlink.LinkSetMTU(host, config.Mtu) if err != nil { return types.InternalErrorf("failed to set MTU on host interface %s: %v", hostIfName, err) } err = netlink.LinkSetMTU(sbox, config.Mtu) if err != nil { return types.InternalErrorf("failed to set MTU on sandbox interface %s: %v", containerIfName, err) } } // Attach host side pipe interface into the bridge if err = addToBridge(hostIfName, config.BridgeName); err != nil { return fmt.Errorf("adding interface %s to bridge %s failed: %v", hostIfName, config.BridgeName, err) } if !dconfig.EnableUserlandProxy { err = setHairpinMode(host, true) if err != nil { return err } } // Create the sandbox side pipe interface endpoint.srcName = containerIfName endpoint.macAddress = ifInfo.MacAddress() endpoint.addr = ifInfo.Address() endpoint.addrv6 = ifInfo.AddressIPv6() // Down the interface before configuring mac address. if err = netlink.LinkSetDown(sbox); err != nil { return fmt.Errorf("could not set link down for container interface %s: %v", containerIfName, err) } // Set the sbox's MAC. If specified, use the one configured by user, otherwise generate one based on IP. if endpoint.macAddress == nil { endpoint.macAddress = electMacAddress(epConfig, endpoint.addr.IP) if err := ifInfo.SetMacAddress(endpoint.macAddress); err != nil { return err } } err = netlink.LinkSetHardwareAddr(sbox, endpoint.macAddress) if err != nil { return fmt.Errorf("could not set mac address for container interface %s: %v", containerIfName, err) } // Up the host interface after finishing all netlink configuration if err = netlink.LinkSetUp(host); err != nil { return fmt.Errorf("could not set link up for host interface %s: %v", hostIfName, err) } if endpoint.addrv6 == nil && config.EnableIPv6 { var ip6 net.IP network := n.bridge.bridgeIPv6 if config.AddressIPv6 != nil { network = config.AddressIPv6 } ones, _ := network.Mask.Size() if ones > 80 { err = types.ForbiddenErrorf("Cannot self generate an IPv6 address on network %v: At least 48 host bits are needed.", network) return err } ip6 = make(net.IP, len(network.IP)) copy(ip6, network.IP) for i, h := range endpoint.macAddress { ip6[i+10] = h } endpoint.addrv6 = &net.IPNet{IP: ip6, Mask: network.Mask} if err := ifInfo.SetIPAddress(endpoint.addrv6); err != nil { return err } } // Add a neighbor proxy if using NDP proxying if config.NDPProxyInterface != "" && config.EnableIPv6 { link, err := netlink.LinkByName(config.NDPProxyInterface) if err != nil { return err } neighbor := netlink.Neigh{ LinkIndex: link.Attrs().Index, Family: netlink.FAMILY_V6, State: netlink.NUD_PERMANENT, Type: netlink.NDA_UNSPEC, Flags: netlink.NTF_PROXY, IP: endpoint.addrv6.IP, HardwareAddr: endpoint.macAddress, } if err := netlink.NeighAdd(&neighbor); err != nil { logrus.Warnf("could not add the neighbor proxy: %v", err) return err } if endpoint.config != nil { for _, port := range endpoint.config.ExposedPorts { insert := []string{ string(iptables.Insert), DockerChain, "-p", port.Proto.String(), "-d", endpoint.addrv6.String(), "--dport", strconv.Itoa(int(port.Port)), "-j", "ACCEPT", } iptables.Raw(iptables.IP6Tables, insert...) } } } // Program any required port mapping and store them in the endpoint endpoint.portMapping, err = n.allocatePorts(epConfig, endpoint, config.DefaultBindingIP, d.config.EnableUserlandProxy) if err != nil { return err } return nil }