Skip to content

Commit

Permalink
Merge pull request #2 from dj-nlx/main
Browse files Browse the repository at this point in the history
PR - More IPAM functionality
  • Loading branch information
UltraInstinct14 authored Jan 19, 2023
2 parents fd13c49 + fb7657f commit 22352b0
Show file tree
Hide file tree
Showing 3 changed files with 166 additions and 1 deletion.
19 changes: 19 additions & 0 deletions counter.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,22 @@ func (C *Counter) PutCounter(id uint64) error {
}
return nil
}

// ReserveCounter - Don't allocate this counter
func (C *Counter) ReserveCounter(id uint64) error {
if id < C.begin || id >= C.begin+C.len {
return errors.New("Range")
}

if C.cap <= 0 || C.start == ^uint64(0) || C.counters[id] == ^uint64(0) {
return errors.New("Overflow")
}

tmp := C.start
C.start = C.counters[id]
C.end = tmp
C.counters[id] = ^uint64(0)
C.cap--

return nil
}
64 changes: 63 additions & 1 deletion ipalloc.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,68 @@ func diffIPIndex(baseIP net.IP, IP net.IP) uint64 {
return index
}

// ReserveIP - Don't allocate this IP address/ID pair from the given cluster and CIDR range
// If id is 0, a new IP address will be allocated else IP addresses will be shared and
// it will be same as the first IP address allocted for this range
func (ipa *IPAllocator) ReserveIP(cluster string, cidr string, id uint32, IPString string) error {
var ipCPool *IPClusterPool
var ipr *IPRange
_, ipn, err := net.ParseCIDR(cidr)

if err != nil {
return errors.New("Invalid CIDR")
}

IP := net.ParseIP(IPString)
if IP == nil {
return errors.New("Invalid IP String")
}

if !ipn.Contains(IP) {
return errors.New("IP String out of bounds")
}

if ipCPool = ipa.ipBlocks[cluster]; ipCPool == nil {
if err := ipa.AddIPRange(cluster, cidr); err != nil {
return errors.New("No such IP Cluster Pool")
}
if ipCPool = ipa.ipBlocks[cluster]; ipCPool == nil {
return errors.New("IP Range allocation failure")
}
}

if ipr = ipCPool.pool[cidr]; ipr == nil {
return errors.New("No such IP Range")
}

if _, ok := ipr.ident[id]; ok {
if id != 0 {
return errors.New("IP Range,Ident exists")
}
}

if id == 0 || !ipr.fOK {
retIndex := diffIPIndex(ipr.ipNet.IP, IP)
if retIndex <= 0 {
if retIndex != 0 || (retIndex == 0 && ipr.first != 0) {
return errors.New("IP return index not found")
}
}
err = ipr.freeID.ReserveCounter(retIndex)
if err != nil {
return errors.New("IP reserve counter failure")
}
if !ipr.fOK {
ipr.first = retIndex
ipr.fOK = true
}
}

ipr.ident[id] = struct{}{}

return nil
}

// AllocateNewIP - Allocate a New IP address from the given cluster and CIDR range
// If id is 0, a new IP address will be allocated else IP addresses will be shared and
// it will be same as the first IP address allocted for this range
Expand Down Expand Up @@ -105,7 +167,7 @@ func (ipa *IPAllocator) AllocateNewIP(cluster string, cidr string, id uint32) (n

if _, ok := ipr.ident[id]; ok {
if id != 0 {
return net.IP{0, 0, 0, 0}, errors.New("IP Range,Ident exists")
return net.IP{0, 0, 0, 0}, errors.New("IP/Ident exists")
}
}

Expand Down
84 changes: 84 additions & 0 deletions lib_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,11 @@ func TestCounter(t *testing.T) {
t.Errorf("Able to put invalid Counter %d", 15)
}

err = cR.ReserveCounter(15)
if err == nil {
t.Errorf("Able to put reserve Counter %d:%s", 15, err)
}

var idx uint64
idx, err = cR.GetCounter()
if idx != 5 || err != nil {
Expand All @@ -273,6 +278,51 @@ func TestCounter(t *testing.T) {
if idx != 2 || err != nil {
t.Errorf("Counter get got %d of expected %d", idx, 2)
}

idx, err = cR.GetCounter()
if idx != ^uint64(0) || err == nil {
t.Errorf("Counter get got %d", idx)
}

err = cR.PutCounter(2)
if err != nil {
t.Errorf("failed to put valid Counter %d", 2)
}

err = cR.ReserveCounter(2)
if err != nil {
t.Errorf("failed to reserv valid Counter %d", 2)
}

_, err = cR.GetCounter()
if err == nil {
t.Errorf("Counter get passed unexpectedly %s", err)
}

err = cR.PutCounter(2)
if err != nil {
t.Errorf("failed to put valid Counter %d", 2)
}

_, err = cR.GetCounter()
if err != nil {
t.Errorf("Counter get failed unexpectedly %s", err)
}

cR = NewCounter(0, 5)
err = cR.ReserveCounter(0)
if err != nil {
t.Errorf("failed to reserve valid Counter %d", 0)
}

idx, err = cR.GetCounter()
if err != nil {
t.Errorf("failed to get valid Counter %d", 0)
}

if idx == 0 {
t.Errorf("reservation failed Counter %d", 1)
}
}

func TestIfStat(t *testing.T) {
Expand Down Expand Up @@ -435,4 +485,38 @@ func TestIPAlloc(t *testing.T) {
t.Fatalf("IP Alloc failed for 74.125.227.24:%s", ip1.String())
}

err = ipa.DeleteIPRange(IPClusterDefault, "74.125.227.24/29")
if err != nil {
t.Fatalf("IP Delete Range failed for 74.125.227.24/29:%s", err)
}

ipa.AddIPRange(IPClusterDefault, "71.71.71.0/31")
err = ipa.ReserveIP(IPClusterDefault, "71.71.71.0/31", 0, "71.71.71.0")
if err != nil {
t.Fatal("Failed to reserve IP 71.71.71.0 - Check Alloc Algo")
}

ip, err = ipa.AllocateNewIP(IPClusterDefault, "71.71.71.0/31", 0)
if err != nil {
t.Fatal("Failed IP Alloc for 71.71.71.0/31 - Check Alloc Algo")
}

if ip.String() != "71.71.71.1" {
t.Fatalf("Failed IP Alloc for 71.71.71.0/31: %s:%s", ip.String(), "71.71.71.1")
}

err = ipa.DeAllocateIP(IPClusterDefault, "71.71.71.0/31", 0, "71.71.71.0")
if err != nil {
t.Fatalf("Failed IP DeAlloc for 71.71.71.0/31:%s:%s", "71.71.71.0", err)
}

ip, err = ipa.AllocateNewIP(IPClusterDefault, "71.71.71.0/31", 0)
if err != nil {
t.Fatal("Failed IP Alloc for 71.71.71.0/31 - Check Alloc Algo")
}

if ip.String() != "71.71.71.0" {
t.Fatalf("Failed IP Alloc for 71.71.71.0/31: %s:%s", ip.String(), "71.71.71.0")
}

}

0 comments on commit 22352b0

Please sign in to comment.