Skip to content

Commit

Permalink
dhcpsvc: imp code
Browse files Browse the repository at this point in the history
  • Loading branch information
EugeneOne1 committed Feb 19, 2024
1 parent 30691f0 commit 0a07892
Show file tree
Hide file tree
Showing 3 changed files with 129 additions and 113 deletions.
106 changes: 0 additions & 106 deletions internal/dhcpsvc/lease.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,9 @@ package dhcpsvc

import (
"bytes"
"fmt"
"net"
"net/netip"
"slices"
"strings"
"time"
)

Expand Down Expand Up @@ -52,107 +50,3 @@ func (l *Lease) Clone() (clone *Lease) {
func compareLeaseMAC(a, b *Lease) (res int) {
return bytes.Compare(a.HWAddr, b.HWAddr)
}

// 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
}

// 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.
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.
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.
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
}
125 changes: 125 additions & 0 deletions internal/dhcpsvc/leaseindex.go
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
}
11 changes: 4 additions & 7 deletions internal/dhcpsvc/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,10 @@ func New(conf *Config) (srv *DHCPServer, err error) {
enabled.Store(conf.Enabled)

srv = &DHCPServer{
enabled: enabled,
localTLD: conf.LocalDomainName,
leasesMu: &sync.RWMutex{},
leases: &leaseIndex{
byAddr: map[netip.Addr]*Lease{},
byName: map[string]*Lease{},
},
enabled: enabled,
localTLD: conf.LocalDomainName,
leasesMu: &sync.RWMutex{},
leases: newLeaseIndex(),
interfaces4: ifaces4,
interfaces6: ifaces6,
icmpTimeout: conf.ICMPTimeout,
Expand Down

0 comments on commit 0a07892

Please sign in to comment.