renew dhcp lease on link up

This commit is contained in:
Siyuan 2025-10-07 17:45:44 +00:00
parent 456ee66fc2
commit 50469c1fb6
4 changed files with 69 additions and 21 deletions

View File

@ -7,6 +7,7 @@ import (
"github.com/jetkvm/kvm/internal/network/types"
"github.com/jetkvm/kvm/pkg/nmlite/jetdhcpc"
"github.com/jetkvm/kvm/pkg/nmlite/udhcpc"
"github.com/rs/zerolog"
"github.com/vishvananda/netlink"
)
@ -68,17 +69,16 @@ func (dc *DHCPClient) SetOnLeaseChange(callback func(lease *types.DHCPLease)) {
dc.onLeaseChange = callback
}
// Start starts the DHCP client
func (dc *DHCPClient) Start() error {
if dc.client != nil {
dc.logger.Warn().Msg("DHCP client already started")
return nil
func (dc *DHCPClient) initClient() (types.DHCPClient, error) {
if false {
return dc.initJetDHCPC()
} else {
return dc.initUDHCPC()
}
}
dc.logger.Info().Msg("starting DHCP client")
// Create the underlying DHCP client
client, err := jetdhcpc.NewClient(dc.ctx, []string{dc.ifaceName}, &jetdhcpc.Config{
func (dc *DHCPClient) initJetDHCPC() (types.DHCPClient, error) {
return jetdhcpc.NewClient(dc.ctx, []string{dc.ifaceName}, &jetdhcpc.Config{
IPv4: dc.ipv4Enabled,
IPv6: dc.ipv6Enabled,
OnLease4Change: func(lease *types.DHCPLease) {
@ -95,6 +95,31 @@ func (dc *DHCPClient) Start() error {
return nil
},
}, dc.logger)
}
func (dc *DHCPClient) initUDHCPC() (types.DHCPClient, error) {
c := udhcpc.NewDHCPClient(&udhcpc.DHCPClientOptions{
InterfaceName: dc.ifaceName,
PidFile: "",
Logger: dc.logger,
OnLeaseChange: func(lease *types.DHCPLease) {
dc.handleLeaseChange(lease, false)
},
})
return c, nil
}
// Start starts the DHCP client
func (dc *DHCPClient) Start() error {
if dc.client != nil {
dc.logger.Warn().Msg("DHCP client already started")
return nil
}
dc.logger.Info().Msg("starting DHCP client")
// Create the underlying DHCP client
client, err := dc.initClient()
if err != nil {
return fmt.Errorf("failed to create DHCP client: %w", err)

View File

@ -493,6 +493,10 @@ func (im *InterfaceManager) handleLinkUp() {
im.logger.Info().Msg("link up")
im.applyConfiguration()
if im.config.IPv4Mode.String == "dhcp" {
im.dhcpClient.Renew()
}
}
func (im *InterfaceManager) handleLinkDown() {

View File

@ -38,6 +38,11 @@ func (l *Lease) ToJSON() string {
return string(json)
}
// ToDHCPLease converts a lease to a DHCP lease.
func (l *Lease) ToDHCPLease() *types.DHCPLease {
return &l.DHCPLease
}
// SetLeaseExpiry sets the lease expiry time.
func (l *Lease) SetLeaseExpiry() (time.Time, error) {
if l.Uptime == 0 || l.LeaseTime == 0 {

View File

@ -6,6 +6,7 @@ import (
"os"
"path/filepath"
"reflect"
"sync"
"time"
"github.com/fsnotify/fsnotify"
@ -26,14 +27,15 @@ type DHCPClient struct {
lease *Lease
logger *zerolog.Logger
process *os.Process
onLeaseChange func(lease *Lease)
runOnce sync.Once
onLeaseChange func(lease *types.DHCPLease)
}
type DHCPClientOptions struct {
InterfaceName string
PidFile string
Logger *zerolog.Logger
OnLeaseChange func(lease *Lease)
OnLeaseChange func(lease *types.DHCPLease)
}
var defaultLogger = zerolog.New(os.Stdout).Level(zerolog.InfoLevel)
@ -69,8 +71,8 @@ func (c *DHCPClient) getWatchPaths() []string {
}
// Run starts the DHCP client and watches the lease file for changes.
// this isn't a blocking call, and the lease file is reloaded when a change is detected.
func (c *DHCPClient) Run() error {
// this is a blocking call.
func (c *DHCPClient) run() error {
err := c.loadLeaseFile()
if err != nil && !errors.Is(err, os.ErrNotExist) {
return err
@ -127,7 +129,7 @@ func (c *DHCPClient) Run() error {
// c.logger.Error().Msg("udhcpc process not found")
// }
// block the goroutine until the lease file is updated
// block the goroutine
<-make(chan struct{})
return nil
@ -184,7 +186,7 @@ func (c *DHCPClient) loadLeaseFile() error {
Msg("current dhcp lease expiry time calculated")
}
c.onLeaseChange(lease)
c.onLeaseChange(lease.ToDHCPLease())
c.logger.Info().
Str("ip", lease.IPAddress.String()).
@ -203,12 +205,16 @@ func (c *DHCPClient) Domain() string {
return c.lease.Domain
}
func (c *DHCPClient) Lease4() *Lease {
return c.lease
func (c *DHCPClient) Lease4() *types.DHCPLease {
if c.lease == nil {
return nil
}
return c.lease.ToDHCPLease()
}
func (c *DHCPClient) Lease6() *Lease {
return c.lease
func (c *DHCPClient) Lease6() *types.DHCPLease {
// TODO: implement
return nil
}
func (c *DHCPClient) SetIPv4(enabled bool) {
@ -219,12 +225,20 @@ func (c *DHCPClient) SetIPv6(enabled bool) {
// TODO: implement
}
func (c *DHCPClient) SetOnLeaseChange(callback func(lease *Lease)) {
func (c *DHCPClient) SetOnLeaseChange(callback func(lease *types.DHCPLease)) {
c.onLeaseChange = callback
}
func (c *DHCPClient) Start() error {
return c.Run() // udhcpc already has Run()
c.runOnce.Do(func() {
go func() {
err := c.run()
if err != nil {
c.logger.Error().Err(err).Msg("failed to run udhcpc")
}
}()
})
return nil
}
func (c *DHCPClient) Stop() error {