コード例 #1
1
ファイル: util.go プロジェクト: kubernetes/kubernetes
// IPNetEqual checks if the two input IPNets are representing the same subnet.
// For example,
//	10.0.0.1/24 and 10.0.0.0/24 are the same subnet.
//	10.0.0.1/24 and 10.0.0.0/25 are not the same subnet.
func IPNetEqual(ipnet1, ipnet2 *net.IPNet) bool {
	if ipnet1 == nil || ipnet2 == nil {
		return false
	}
	if reflect.DeepEqual(ipnet1.Mask, ipnet2.Mask) && ipnet1.Contains(ipnet2.IP) && ipnet2.Contains(ipnet1.IP) {
		return true
	}
	return false
}
コード例 #2
0
ファイル: network_test.go プロジェクト: NetSys/quilt
func TestAllocate(t *testing.T) {
	subnet := net.IPNet{
		IP:   net.IPv4(0xab, 0xcd, 0xe0, 0x00),
		Mask: net.CIDRMask(20, 32),
	}
	conflicts := map[string]struct{}{}
	ipSet := map[string]struct{}{}

	// Only 4k IPs, in 0xfffff000. Guaranteed a collision
	for i := 0; i < 5000; i++ {
		ip, err := allocateIP(ipSet, subnet)
		if err != nil {
			continue
		}

		if _, ok := conflicts[ip]; ok {
			t.Fatalf("IP Double allocation: 0x%x", ip)
		}

		require.True(t, subnet.Contains(net.ParseIP(ip)),
			fmt.Sprintf("\"%s\" is not in %s", ip, subnet))
		conflicts[ip] = struct{}{}
	}

	assert.Equal(t, len(conflicts), len(ipSet))
	if len(conflicts) < 2500 || len(conflicts) > 4096 {
		// If the code's working, this is possible but *extremely* unlikely.
		// Probably a bug.
		t.Errorf("Too few conflicts: %d", len(conflicts))
	}
}
コード例 #3
0
ファイル: main.go プロジェクト: nyushi/ifaddr
func getSuitableAddrs(addrs []*address, v4, v6, linklocal, loopback bool, re *regexp.Regexp, mask *net.IPNet) ([]*address, error) {
	ret := []*address{}
	for _, a := range addrs {
		if a.IsLoopback() && !loopback {
			continue
		}
		if !v6 && a.IsV6() {
			continue
		}
		if !v4 && a.IsV4() {
			continue
		}
		if !linklocal && a.IsLinkLocalUnicast() {
			continue
		}
		if !loopback && a.IsLoopback() {
			continue
		}
		if re != nil {
			if !re.MatchString(a.String()) {
				continue
			}
		}
		if mask != nil {
			if !mask.Contains(a.IP) {
				continue
			}
		}
		ret = append(ret, a)
	}
	if len(ret) == 0 {
		return nil, errors.New("unable to find suitable address")
	}
	return ret, nil
}
コード例 #4
0
ファイル: iputils.go プロジェクト: bac/juju
// NextSubnetIP returns the next available IP address in a given subnet.
func NextSubnetIP(subnet *net.IPNet, ipsInUse []net.IP) (net.IP, error) {
	ones, bits := subnet.Mask.Size()
	subnetMaskUint32 := ipUint32(net.IP(subnet.Mask))

	inUse := big.NewInt(0)
	for _, ip := range ipsInUse {
		if !subnet.Contains(ip) {
			continue
		}
		index := ipIndex(ip, subnetMaskUint32)
		inUse = inUse.SetBit(inUse, index, 1)
	}

	// Now iterate through all addresses in the subnet and return the
	// first address that is not in use. We start at the first non-
	// reserved address, and stop short of the last address in the
	// subnet (i.e. all non-mask bits set), which is the broadcast
	// address for the subnet.
	n := ipUint32(subnet.IP)
	for i := reservedAddressRangeEnd + 1; i < (1<<uint64(bits-ones) - 1); i++ {
		ip := uint32IP(n + uint32(i))
		if !ip.IsGlobalUnicast() {
			continue
		}
		index := ipIndex(ip, subnetMaskUint32)
		if inUse.Bit(index) == 0 {
			return ip, nil
		}
	}
	return nil, errors.Errorf("no addresses available in %s", subnet)
}
コード例 #5
0
ファイル: netstat_linux.go プロジェクト: sneha29shukla/mig
// hasIP6Connected parses the list of remote addresses in /proc/net/{tcp,udp}6 or in
// /proc/<pid>/net/{tcp,udp}6 and returns addresses that are contained within
// the ipnet submitted. It always uses CIDR inclusion, even when only
// searching for a single IP (but assuming a /128 bitmask).
// Remote addresses exposed in /proc are in hexadecimal notation, and converted into byte slices
// to use in ipnet.Contains()
func hasIP6Connected(ip net.IP, ipnet *net.IPNet) (found bool, elements []element, err error) {
	defer func() {
		if e := recover(); e != nil {
			err = fmt.Errorf("hasIP6Connected(): %v", e)
		}
	}()
	lns, err := procIP6Entries()
	if err != nil {
		panic(err)
	}
	// if the ipnet is nil, assume that its a full 128bits mask
	if ipnet == nil {
		ipnet = new(net.IPNet)
		ipnet.IP = ip
		ipnet.Mask = net.CIDRMask(net.IPv6len*8, net.IPv6len*8)
	}
	for _, ipent := range lns {
		fields := strings.Fields(ipent.line)
		if len(fields) < 4 {
			panic("/proc doesn't respect the expected format")
		}
		remote := strings.Split(fields[2], ":")
		if len(remote) != 2 {
			panic("remote isn't in the form <ip>:<port>")
		}
		remoteIP := hexToIP6(remote[0])
		if remoteIP == nil {
			panic("failed to convert remote IP")
		}
		// if we've got a match, store the element
		if ipnet.Contains(remoteIP) {
			var el element
			el.RemoteAddr = remoteIP.String()
			remotePort, err := strconv.ParseUint(remote[1], 16, 16)
			if err != nil {
				panic("failed to convert remote port")
			}
			el.RemotePort = float64(remotePort)
			local := strings.Split(fields[1], ":")
			if len(local) != 2 {
				panic("local isn't in the form <ip>:<port>")
			}
			localAddr := hexToIP6(local[0])
			if localAddr == nil {
				panic("failed to convert local ip")
			}
			el.LocalAddr = localAddr.String()
			localPort, err := strconv.ParseUint(local[1], 16, 16)
			if err != nil {
				panic("failed to convert local port")
			}
			el.LocalPort = float64(localPort)
			el.Namespace = ipent.nsIdentifier
			elements = append(elements, el)
			found = true
		}
		stats.Examined++
	}
	return
}
コード例 #6
0
ファイル: allocator.go プロジェクト: qinguoan/vulcan
// GetIndexedIP returns a net.IP that is subnet.IP + index in the contiguous IP space.
func GetIndexedIP(subnet *net.IPNet, index int) (net.IP, error) {
	ip := addIPOffset(bigForIP(subnet.IP), index)
	if !subnet.Contains(ip) {
		return nil, fmt.Errorf("can't generate IP with index %d from subnet. subnet too small. subnet: %q", index, subnet)
	}
	return ip, nil
}
コード例 #7
0
ファイル: cidr_set.go プロジェクト: CodeJuan/kubernetes
func (s *cidrSet) getBeginingAndEndIndices(cidr *net.IPNet) (begin, end int, err error) {
	begin, end = 0, s.maxCIDRs
	cidrMask := cidr.Mask
	maskSize, _ := cidrMask.Size()

	if !s.clusterCIDR.Contains(cidr.IP.Mask(s.clusterCIDR.Mask)) && !cidr.Contains(s.clusterCIDR.IP.Mask(cidr.Mask)) {
		return -1, -1, fmt.Errorf("cidr %v is out the range of cluster cidr %v", cidr, s.clusterCIDR)
	}

	if s.clusterMaskSize < maskSize {
		subNetMask := net.CIDRMask(s.subNetMaskSize, 32)
		begin, err = s.getIndexForCIDR(&net.IPNet{
			IP:   cidr.IP.To4().Mask(subNetMask),
			Mask: subNetMask,
		})
		if err != nil {
			return -1, -1, err
		}

		ip := make([]byte, 4)
		ipInt := binary.BigEndian.Uint32(cidr.IP) | (^binary.BigEndian.Uint32(cidr.Mask))
		binary.BigEndian.PutUint32(ip, ipInt)
		end, err = s.getIndexForCIDR(&net.IPNet{
			IP:   net.IP(ip).To4().Mask(subNetMask),
			Mask: subNetMask,
		})
		if err != nil {
			return -1, -1, err
		}
	}
	return begin, end, nil
}
コード例 #8
0
ファイル: networks_utils.go プロジェクト: vahe/lxd
func networkAddressForSubnet(subnet *net.IPNet) (net.IP, string, error) {
	ifaces, err := net.Interfaces()
	if err != nil {
		return net.IP{}, "", err
	}

	for _, iface := range ifaces {
		addrs, err := iface.Addrs()
		if err != nil {
			continue
		}

		for _, addr := range addrs {
			ip, _, err := net.ParseCIDR(addr.String())
			if err != nil {
				continue
			}

			if subnet.Contains(ip) {
				return ip, iface.Name, nil
			}
		}
	}

	return net.IP{}, "", fmt.Errorf("No address found in subnet")
}
コード例 #9
0
ファイル: store.go プロジェクト: brianredbeard/astralboot
// NetList : subnet helper function
func NetList(ip net.IP, subnet net.IP) (IPlist []net.IP) {
	//ip, ipnet, err := net.ParseCIDR(cidrNet)
	mask := net.IPv4Mask(subnet[0], subnet[1], subnet[2], subnet[3])
	ipnet := net.IPNet{ip, mask}
	for ip := ip.Mask(mask); ipnet.Contains(ip); incIP(ip) {
		IPlist = append(IPlist, net.IP{ip[0], ip[1], ip[2], ip[3]})
	}
	return
}
コード例 #10
0
ファイル: utils.go プロジェクト: beginnor/docker
// Detects overlap between one IPNet and another
func NetworkOverlaps(netX *net.IPNet, netY *net.IPNet) bool {
	if firstIP, _ := NetworkRange(netX); netY.Contains(firstIP) {
		return true
	}
	if firstIP, _ := NetworkRange(netY); netX.Contains(firstIP) {
		return true
	}
	return false
}
コード例 #11
0
ファイル: structures.go プロジェクト: DaveDaCoda/docker
// Checks whether the passed subnet is a superset or subset of any of the subset in this config db
func (aSpace *addrSpace) contains(space string, nw *net.IPNet) bool {
	for k, v := range aSpace.subnets {
		if space == k.AddressSpace && k.ChildSubnet == "" {
			if nw.Contains(v.Pool.IP) || v.Pool.Contains(nw.IP) {
				return true
			}
		}
	}
	return false
}
コード例 #12
0
ファイル: cidr.go プロジェクト: hanjianwei/cidr-lite
// SpanningCIDR computes network covers given IP addresses
func SpanningCIDR(first, last net.IP) *net.IPNet {
	_, bits := last.DefaultMask().Size()

	var network net.IPNet
	for ones := bits; !network.Contains(first); ones-- {
		network.Mask = net.CIDRMask(ones, bits)
		network.IP = last.Mask(network.Mask)
	}
	return &network
}
コード例 #13
0
ファイル: network.go プロジェクト: keeb/docker
// Detects overlap between one IPNet and another
func networkOverlaps(netX *net.IPNet, netY *net.IPNet) bool {
	firstIP, _ := networkRange(netX)
	if netY.Contains(firstIP) {
		return true
	}
	firstIP, _ = networkRange(netY)
	if netX.Contains(firstIP) {
		return true
	}
	return false
}
コード例 #14
0
ファイル: device.go プロジェクト: ozym/zone
func (d *Device) InNetwork(network net.IPNet) bool {
	if network.Contains(d.IP) {
		return true
	}
	for _, a := range d.Reverse {
		if !network.Contains(a) {
			continue
		}
		return true
	}
	return false
}
コード例 #15
0
// Marks all CIDRs with subNetMaskSize that belongs to serviceCIDR as used,
// so that they won't be assignable.
func (r *rangeAllocator) filterOutServiceRange(serviceCIDR *net.IPNet) {
	// Checks if service CIDR has a nonempty intersection with cluster CIDR. It is the case if either
	// clusterCIDR contains serviceCIDR with clusterCIDR's Mask applied (this means that clusterCIDR contains serviceCIDR)
	// or vice versa (which means that serviceCIDR contains clusterCIDR).
	if !r.clusterCIDR.Contains(serviceCIDR.IP.Mask(r.clusterCIDR.Mask)) && !serviceCIDR.Contains(r.clusterCIDR.IP.Mask(serviceCIDR.Mask)) {
		return
	}

	if err := r.cidrs.occupy(serviceCIDR); err != nil {
		glog.Errorf("Error filtering out service cidr %v: %v", serviceCIDR, err)
	}
}
コード例 #16
0
ファイル: utils.go プロジェクト: souravbh/lattice-release
// NetworkOverlaps detects overlap between one IPNet and another
func NetworkOverlaps(netX *net.IPNet, netY *net.IPNet) bool {
	// Check if both netX and netY are ipv4 or ipv6
	if (netX.IP.To4() != nil && netY.IP.To4() != nil) ||
		(netX.IP.To4() == nil && netY.IP.To4() == nil) {
		if firstIP, _ := NetworkRange(netX); netY.Contains(firstIP) {
			return true
		}
		if firstIP, _ := NetworkRange(netY); netX.Contains(firstIP) {
			return true
		}
	}
	return false
}
コード例 #17
0
ファイル: setup_ipv4.go プロジェクト: msabansal/libnetwork
func selectIPv4Address(addresses []netlink.Addr, selector *net.IPNet) (netlink.Addr, error) {
	if len(addresses) == 0 {
		return netlink.Addr{}, fmt.Errorf("unable to select an address as the address pool is empty")
	}
	if selector != nil {
		for _, addr := range addresses {
			if selector.Contains(addr.IP) {
				return addr, nil
			}
		}
	}
	return addresses[0], nil
}
コード例 #18
0
ファイル: worker.go プロジェクト: NetSys/quilt
func filterOnSubnet(subnet net.IPNet, dkcs []docker.Container) (good []docker.Container,
	bad []interface{}) {

	for _, dkc := range dkcs {
		dkIP := net.ParseIP(dkc.IP)
		if subnet.Contains(dkIP) {
			good = append(good, dkc)
		} else {
			bad = append(bad, dkc)
		}
	}

	return good, bad
}
コード例 #19
0
ファイル: selectors.go プロジェクト: nagyistoce/garden-linux
func (dynamicIPSelector) SelectIP(subnet *net.IPNet, existing []net.IP) (net.IP, error) {
	exists := make(map[string]bool)
	for _, e := range existing {
		exists[e.String()] = true
	}

	for i := subnet.IP; subnet.Contains(i); i = next(i) {
		if !exists[i.String()] {
			return i, nil
		}
	}

	return nil, ErrInsufficientIPs
}
コード例 #20
0
ファイル: config.go プロジェクト: nealjc/ipreg
func generateAllInSubnet(ipNet *net.IPNet, subnet *scanner.Subnet) {
	inc := func(ip net.IP) {
		for j := len(ip) - 1; j >= 0; j-- {
			ip[j]++
			if ip[j] > 0 {
				break
			}
		}
	}
	for ip := ipNet.IP.Mask(ipNet.Mask); ipNet.Contains(ip); inc(ip) {
		subnet.Nodes[ip.String()] = &scanner.NodeStatus{scanner.UNKNOWN}
		subnet.OrderedAddresses = append(subnet.OrderedAddresses, ip.String())
	}
}
コード例 #21
0
func checkRouteConflict(nlh *netlink.Handle, address *net.IPNet, family int) error {
	routes, err := nlh.RouteList(nil, family)
	if err != nil {
		return err
	}
	for _, route := range routes {
		if route.Dst != nil {
			if route.Dst.Contains(address.IP) || address.Contains(route.Dst.IP) {
				return fmt.Errorf("cannot program address %v in sandbox interface because it conflicts with existing route %s",
					address, route)
			}
		}
	}
	return nil
}
コード例 #22
0
ファイル: allocator.go プロジェクト: juanluisvaladas/origin
// Ensures @ip is within @ipnet, and (if given) inclusive of @start and @end
func validateRangeIP(ip net.IP, ipnet *net.IPNet, start net.IP, end net.IP) error {
	var err error

	// Make sure we can compare IPv4 addresses directly
	ip, err = canonicalizeIP(ip)
	if err != nil {
		return err
	}

	if !ipnet.Contains(ip) {
		return fmt.Errorf("%s not in network: %s", ip, ipnet)
	}

	if start != nil {
		start, err = canonicalizeIP(start)
		if err != nil {
			return err
		}
		if len(ip) != len(start) {
			return fmt.Errorf("%s %d not same size IP address as start %s %d", ip, len(ip), start, len(start))
		}
		for i := 0; i < len(ip); i++ {
			if ip[i] > start[i] {
				break
			} else if ip[i] < start[i] {
				return fmt.Errorf("%s outside of network %s with start %s", ip, ipnet, start)
			}
		}
	}

	if end != nil {
		end, err = canonicalizeIP(end)
		if err != nil {
			return err
		}
		if len(ip) != len(end) {
			return fmt.Errorf("%s %d not same size IP address as end %s %d", ip, len(ip), end, len(end))
		}
		for i := 0; i < len(ip); i++ {
			if ip[i] < end[i] {
				break
			} else if ip[i] > end[i] {
				return fmt.Errorf("%s outside of network %s with end %s", ip, ipnet, end)
			}
		}
	}
	return nil
}
コード例 #23
0
ファイル: cni.go プロジェクト: n054/weave
func findBridgeIP(bridgeName string, subnet net.IPNet) (net.IP, error) {
	netdev, err := common.GetBridgeNetDev(bridgeName)
	if err != nil {
		return nil, fmt.Errorf("Failed to get netdev for %q bridge: %s", bridgeName, err)
	}
	if len(netdev.CIDRs) == 0 {
		return nil, errBridgeNoIP
	}
	for _, cidr := range netdev.CIDRs {
		if subnet.Contains(cidr.IP) {
			return cidr.IP, nil
		}
	}
	// None in the required subnet; just return the first one
	return netdev.CIDRs[0].IP, nil
}
コード例 #24
0
ファイル: url.go プロジェクト: davidscholberg/irkbot
// isCidrMatch tests if a given IP is in any of a given set of CIDR subnets.
func isCidrMatch(ip *net.IP, subnets []string) (bool, error) {
	var cidr *net.IPNet
	var err error

	for _, subnet := range subnets {
		_, cidr, err = net.ParseCIDR(subnet)
		if err != nil {
			return false, err
		}
		if cidr.Contains(*ip) {
			return true, nil
		}
	}

	return false, nil
}
コード例 #25
0
ファイル: iprange.go プロジェクト: wallyqs/util
// ParseIPRange creates an IPRange object based on the provided string
// representing the range. The string for a range is in the form of
// "192.168.1.1-100", to specify a range of IPs from 192.168.1.1 to
// 192.168.1.100. The string can also contain a network mask, such as
// "192.168.1.1-100/24". Strings can span over multiple octets, such as
// "192.168.1.1-2.1", and a range can also be just a single IP. An error will be
// returned if it fails to parse the IPs, if the end IP isn't after the start
// IP, and if a network mask is given, it will error if the mask is in valid, or
// the range does not fall within the bounds of the provided mask.
func ParseIPRange(s string) (*IPRange, error) {
	ipr := &IPRange{}

	// check if the string contains a network mask
	if strings.Contains(s, "/") {
		p := strings.Split(s, "/")
		if len(p) != 2 {
			return nil, fmt.Errorf("expected only one '/' within the provided string")
		}
		s = p[0]
		maskBits, err := strconv.Atoi(p[1])
		if err != nil {
			return nil, fmt.Errorf("failed to parse the network mask: %v", err)
		}
		ipr.Mask = net.CIDRMask(maskBits, 32)
	}

	// parse out the dash between the start-end IP portions
	ips := strings.Split(s, "-")
	if len(ips) > 2 {
		return nil, fmt.Errorf("unexpected number of IPs specified in the provided string")
	}
	ipr.Start = net.ParseIP(ips[0])
	if len(ips) > 1 {
		ipr.End = net.ParseIP(spliceIP(ips[0], ips[1]))
	} else {
		ipr.End = ipr.Start
	}

	// ensure the end is after the start
	if bytes.Compare([]byte(ipr.End), []byte(ipr.Start)) < 0 {
		return nil, fmt.Errorf("the end of the range cannot be less than the start of the range")
	}

	// if a subnet was given, then ensure the IPs are within it
	if len(ipr.Mask) > 0 {
		ipnet := net.IPNet{
			IP:   ipr.Start,
			Mask: ipr.Mask,
		}
		if !ipnet.Contains(ipr.End) {
			return nil, fmt.Errorf("the provided IP ranges are not within the provided network mask")
		}
	}

	return ipr, nil
}
コード例 #26
0
ファイル: equipment.go プロジェクト: ozym/zone
func (e *Equipment) ListByNetwork(network net.IPNet) ([]Device, error) {
	devices, err := e.List()
	if err != nil {
		return nil, err
	}

	res := make([]Device, 0, len(devices))
	for _, d := range devices {
		if !network.Contains(d.IP) {
			continue
		}

		res = append(res, d)
	}

	return res, nil
}
コード例 #27
0
ファイル: common.go プロジェクト: iconoeugen/origin
func (oc *OsdnController) validateNetworkConfig(clusterNetwork, serviceNetwork *net.IPNet) error {
	// TODO: Instead of hardcoding 'tun0' and 'lbr0', get it from common place.
	// This will ensure both the kube/multitenant scripts and master validations use the same name.
	hostIPNets, err := netutils.GetHostIPNetworks([]string{"tun0", "lbr0"})
	if err != nil {
		return err
	}

	errList := []error{}

	// Ensure cluster and service network don't overlap with host networks
	for _, ipNet := range hostIPNets {
		if ipNet.Contains(clusterNetwork.IP) {
			errList = append(errList, fmt.Errorf("Error: Cluster IP: %s conflicts with host network: %s", clusterNetwork.IP.String(), ipNet.String()))
		}
		if clusterNetwork.Contains(ipNet.IP) {
			errList = append(errList, fmt.Errorf("Error: Host network with IP: %s conflicts with cluster network: %s", ipNet.IP.String(), clusterNetwork.String()))
		}
		if ipNet.Contains(serviceNetwork.IP) {
			errList = append(errList, fmt.Errorf("Error: Service IP: %s conflicts with host network: %s", serviceNetwork.String(), ipNet.String()))
		}
		if serviceNetwork.Contains(ipNet.IP) {
			errList = append(errList, fmt.Errorf("Error: Host network with IP: %s conflicts with service network: %s", ipNet.IP.String(), serviceNetwork.String()))
		}
	}

	// Ensure each host subnet is within the cluster network
	subnets, err := oc.Registry.GetSubnets()
	if err != nil {
		return fmt.Errorf("Error in initializing/fetching subnets: %v", err)
	}
	for _, sub := range subnets {
		subnetIP, _, err := net.ParseCIDR(sub.Subnet)
		if err != nil {
			errList = append(errList, fmt.Errorf("Failed to parse network address: %s", sub.Subnet))
			continue
		}
		if !clusterNetwork.Contains(subnetIP) {
			errList = append(errList, fmt.Errorf("Error: Existing node subnet: %s is not part of cluster network: %s", sub.Subnet, clusterNetwork.String()))
		}
	}

	// Ensure each service is within the services network
	services, err := oc.Registry.GetServices()
	if err != nil {
		return err
	}
	for _, svc := range services {
		if !serviceNetwork.Contains(net.ParseIP(svc.Spec.ClusterIP)) {
			errList = append(errList, fmt.Errorf("Error: Existing service with IP: %s is not part of service network: %s", svc.Spec.ClusterIP, serviceNetwork.String()))
		}
	}

	return kerrors.NewAggregate(errList)
}
コード例 #28
0
ファイル: selectors.go プロジェクト: nagyistoce/garden-linux
func (dynamicSubnetSelector) SelectSubnet(dynamic *net.IPNet, existing []*net.IPNet) (*net.IPNet, error) {
	exists := make(map[string]bool)
	for _, e := range existing {
		exists[e.String()] = true
	}

	min := dynamic.IP
	mask := net.CIDRMask(30, 32) // /30
	for ip := min; dynamic.Contains(ip); ip = next(ip) {
		subnet := &net.IPNet{ip, mask}
		ip = next(next(next(ip)))
		if dynamic.Contains(ip) && !exists[subnet.String()] {
			return subnet, nil
		}
	}

	return nil, ErrInsufficientSubnets
}
コード例 #29
0
ファイル: allocator.go プロジェクト: nkwilson/libnetwork
// Release allows releasing the address from the specified address space
func (a *Allocator) Release(addrSpace AddressSpace, address net.IP) {
	var (
		space *bitseq.Handle
		sub   *net.IPNet
	)

	if address == nil {
		log.Debugf("Requested to remove nil address from address space %s", addrSpace)
		return
	}

	ver := getAddressVersion(address)
	if ver == v4 {
		address = address.To4()
	}

	// Find the subnet containing the address
	for _, subKey := range a.getSubnetList(addrSpace, ver) {
		sub = subKey.canonicalChildSubnet()
		if sub.Contains(address) {
			a.Lock()
			space = a.addresses[subKey]
			a.Unlock()
			break
		}
	}
	if space == nil {
		log.Debugf("Could not find subnet on address space %s containing %s on release", addrSpace, address.String())
		return
	}

	// Retrieve correspondent ordinal in the subnet
	hostPart, err := types.GetHostPartIP(address, sub.Mask)
	if err != nil {
		log.Warnf("Failed to release address %s on address space %s because of internal error: %v", address.String(), addrSpace, err)
		return
	}
	ordinal := ipToUint32(hostPart)

	// Release it
	if err := space.Unset(ordinal); err != nil {
		log.Warnf("Failed to release address %s on address space %s because of internal error: %v", address.String(), addrSpace, err)
	}
}
コード例 #30
0
func New(ipNet *net.IPNet) *RealNetworkPool {
	pool := []*network.Network{}

	_, startNet, err := net.ParseCIDR(ipNet.IP.String() + "/30")
	if err != nil {
		panic(err)
	}

	for subnet := startNet; ipNet.Contains(subnet.IP); subnet = nextSubnet(subnet) {
		pool = append(pool, network.New(subnet))
	}

	return &RealNetworkPool{
		ipNet: ipNet,

		pool:      pool,
		poolMutex: new(sync.Mutex),
	}
}