github.com/cloudfoundry-attic/garden-linux@v0.333.2-candidate/network/subnets/selectors.go (about)

     1  package subnets
     2  
     3  import (
     4  	"fmt"
     5  	"net"
     6  )
     7  
     8  // StaticSubnetSelector requests a specific ("static") subnet. Returns an error if the subnet is already allocated.
     9  type StaticSubnetSelector struct {
    10  	*net.IPNet
    11  }
    12  
    13  func (s StaticSubnetSelector) SelectSubnet(dynamic *net.IPNet, existing []*net.IPNet) (*net.IPNet, error) {
    14  	if overlaps(dynamic, s.IPNet) {
    15  		return nil, fmt.Errorf("the requested subnet (%v) overlaps the dynamic allocation range (%v)", s.IPNet.String(), dynamic.String())
    16  	}
    17  
    18  	for _, e := range existing {
    19  		if overlaps(s.IPNet, e) && !equals(s.IPNet, e) {
    20  			return nil, fmt.Errorf("the requested subnet (%v) overlaps an existing subnet (%v)", s.IPNet.String(), e.String())
    21  		}
    22  	}
    23  
    24  	return s.IPNet, nil
    25  }
    26  
    27  type dynamicSubnetSelector int
    28  
    29  // DynamicSubnetSelector requests the next unallocated ("dynamic") subnet from the dynamic range.
    30  // Returns an error if there are no remaining subnets in the dynamic range.
    31  var DynamicSubnetSelector dynamicSubnetSelector = 0
    32  
    33  func (dynamicSubnetSelector) SelectSubnet(dynamic *net.IPNet, existing []*net.IPNet) (*net.IPNet, error) {
    34  	exists := make(map[string]bool)
    35  	for _, e := range existing {
    36  		exists[e.String()] = true
    37  	}
    38  
    39  	min := dynamic.IP
    40  	mask := net.CIDRMask(30, 32) // /30
    41  	for ip := min; dynamic.Contains(ip); ip = next(ip) {
    42  		subnet := &net.IPNet{ip, mask}
    43  		ip = next(next(next(ip)))
    44  		if dynamic.Contains(ip) && !exists[subnet.String()] {
    45  			return subnet, nil
    46  		}
    47  	}
    48  
    49  	return nil, ErrInsufficientSubnets
    50  }
    51  
    52  // StaticIPSelector requests a specific ("static") IP address. Returns an error if the IP is already
    53  // allocated, or if it is outside the given subnet.
    54  type StaticIPSelector struct {
    55  	net.IP
    56  }
    57  
    58  func (s StaticIPSelector) SelectIP(subnet *net.IPNet, existing []net.IP) (net.IP, error) {
    59  	if BroadcastIP(subnet).Equal(s.IP) {
    60  		return nil, ErrIPEqualsBroadcast
    61  	}
    62  
    63  	if GatewayIP(subnet).Equal(s.IP) {
    64  		return nil, ErrIPEqualsGateway
    65  	}
    66  
    67  	if !subnet.Contains(s.IP) {
    68  		return nil, ErrInvalidIP
    69  	}
    70  
    71  	for _, e := range existing {
    72  		if e.Equal(s.IP) {
    73  			return nil, ErrIPAlreadyAcquired
    74  		}
    75  	}
    76  
    77  	return s.IP, nil
    78  }
    79  
    80  type dynamicIPSelector int
    81  
    82  // DynamicIPSelector requests the next available ("dynamic") IP address from a given subnet.
    83  // Returns an error if no more IP addresses remain in the subnet.
    84  var DynamicIPSelector dynamicIPSelector = 0
    85  
    86  func (dynamicIPSelector) SelectIP(subnet *net.IPNet, existing []net.IP) (net.IP, error) {
    87  	exists := make(map[string]bool)
    88  	for _, e := range existing {
    89  		exists[e.String()] = true
    90  	}
    91  
    92  	for i := subnet.IP; subnet.Contains(i); i = next(i) {
    93  		if !exists[i.String()] {
    94  			return i, nil
    95  		}
    96  	}
    97  
    98  	return nil, ErrInsufficientIPs
    99  }