-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
30691f0
commit 0a07892
Showing
3 changed files
with
129 additions
and
113 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
package dhcpsvc | ||
|
||
import ( | ||
"fmt" | ||
"net/netip" | ||
"slices" | ||
"strings" | ||
) | ||
|
||
// leaseIndex is the set of leases indexed by their identifiers for quick | ||
// lookup. | ||
type leaseIndex struct { | ||
// byAddr is a lookup shortcut for leases by their IP addresses. | ||
byAddr map[netip.Addr]*Lease | ||
|
||
// byName is a lookup shortcut for leases by their hostnames. | ||
// | ||
// TODO(e.burkov): Use a slice of leases with the same hostname? | ||
byName map[string]*Lease | ||
} | ||
|
||
func newLeaseIndex() *leaseIndex { | ||
return &leaseIndex{ | ||
byAddr: map[netip.Addr]*Lease{}, | ||
byName: map[string]*Lease{}, | ||
} | ||
} | ||
|
||
// leaseByAddr returns a lease by its IP address. | ||
func (idx *leaseIndex) leaseByAddr(addr netip.Addr) (l *Lease, ok bool) { | ||
l, ok = idx.byAddr[addr] | ||
|
||
return l, ok | ||
} | ||
|
||
// leaseByName returns a lease by its hostname. | ||
func (idx *leaseIndex) leaseByName(name string) (l *Lease, ok bool) { | ||
// TODO(e.burkov): Probably, use a case-insensitive comparison and store in | ||
// slice. This would require a benchmark. | ||
l, ok = idx.byName[strings.ToLower(name)] | ||
|
||
return l, ok | ||
} | ||
|
||
// clear removes all leases from idx. | ||
func (idx *leaseIndex) clear() { | ||
clear(idx.byAddr) | ||
clear(idx.byName) | ||
} | ||
|
||
// add adds l into idx and into iface. l must be valid, iface should be | ||
// responsible for l's IP. It returns an error if l duplicates at least a | ||
// single value of another lease. | ||
func (idx *leaseIndex) add(l *Lease, iface *netInterface) (err error) { | ||
loweredName := strings.ToLower(l.Hostname) | ||
|
||
if _, ok := idx.byAddr[l.IP]; ok { | ||
return fmt.Errorf("lease for ip %s already exists", l.IP) | ||
} else if _, ok = idx.byName[loweredName]; ok { | ||
return fmt.Errorf("lease for hostname %s already exists", l.Hostname) | ||
} | ||
|
||
err = iface.insertLease(l) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
idx.byAddr[l.IP] = l | ||
idx.byName[loweredName] = l | ||
|
||
return nil | ||
} | ||
|
||
// remove removes l from idx and from iface. l must be valid, iface should | ||
// contain the same lease or the lease itself. It returns an error if the lease | ||
// not found. | ||
func (idx *leaseIndex) remove(l *Lease, iface *netInterface) (err error) { | ||
loweredName := strings.ToLower(l.Hostname) | ||
|
||
if _, ok := idx.byAddr[l.IP]; !ok { | ||
return fmt.Errorf("no lease for ip %s", l.IP) | ||
} else if _, ok = idx.byName[loweredName]; !ok { | ||
return fmt.Errorf("no lease for hostname %s", l.Hostname) | ||
} | ||
|
||
err = iface.removeLease(l) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
delete(idx.byAddr, l.IP) | ||
delete(idx.byName, loweredName) | ||
|
||
return nil | ||
} | ||
|
||
// update updates l in idx and in iface. l must be valid, iface should be | ||
// responsible for l's IP. It returns an error if l duplicates at least a | ||
// single value of another lease, except for the updated lease itself. | ||
func (idx *leaseIndex) update(l *Lease, iface *netInterface) (err error) { | ||
loweredName := strings.ToLower(l.Hostname) | ||
|
||
existing, ok := idx.byAddr[l.IP] | ||
if ok && !slices.Equal(l.HWAddr, existing.HWAddr) { | ||
return fmt.Errorf("lease for ip %s already exists", l.IP) | ||
} | ||
|
||
existing, ok = idx.byName[loweredName] | ||
if ok && !slices.Equal(l.HWAddr, existing.HWAddr) { | ||
return fmt.Errorf("lease for hostname %s already exists", l.Hostname) | ||
} | ||
|
||
prev, err := iface.updateLease(l) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
delete(idx.byAddr, prev.IP) | ||
delete(idx.byName, strings.ToLower(prev.Hostname)) | ||
|
||
idx.byAddr[l.IP] = l | ||
idx.byName[loweredName] = l | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters