From 49e28f218e34a3ead39ac7618f51f0912655e447 Mon Sep 17 00:00:00 2001 From: Siyuan Date: Tue, 7 Oct 2025 12:44:55 +0000 Subject: [PATCH] fix: dhcp not working --- pkg/nmlite/interface.go | 60 ++++++++++++++++++++------------------ pkg/nmlite/link/netlink.go | 39 +++++++++++++++++++++++-- 2 files changed, 68 insertions(+), 31 deletions(-) diff --git a/pkg/nmlite/interface.go b/pkg/nmlite/interface.go index 90c2e5df..a12b57cb 100644 --- a/pkg/nmlite/interface.go +++ b/pkg/nmlite/interface.go @@ -87,6 +87,9 @@ func NewInterfaceManager(ctx context.Context, ifaceName string, config *types.Ne // Set up DHCP client callbacks im.dhcpClient.SetOnLeaseChange(func(lease *types.DHCPLease) { + if err := im.applyDHCPLease(lease); err != nil { + im.logger.Error().Err(err).Msg("failed to apply DHCP lease") + } im.updateStateFromDHCPLease(lease) if im.onDHCPLeaseChange != nil { im.onDHCPLeaseChange(lease) @@ -588,44 +591,43 @@ func (im *InterfaceManager) updateStateFromDHCPLease(lease *types.DHCPLease) { } } -func (im *InterfaceManager) ReconcileLinkAddrs(ipv4Config *types.IPv4StaticConfig) error { - // nl := getNetlinkManager() - // return nl.ReconcileLinkAddrs(ipv4Config) - return nil +func (im *InterfaceManager) ReconcileLinkAddrs(addrs []*types.IPAddress) error { + nl := getNetlinkManager() + link, err := im.link() + if err != nil { + return fmt.Errorf("failed to get interface: %w", err) + } + if link == nil { + return fmt.Errorf("failed to get interface: %w", err) + } + return nl.ReconcileLinkAddrs(link, addrs) } // applyDHCPLease applies DHCP lease configuration using ReconcileLinkAddrs func (im *InterfaceManager) applyDHCPLease(lease *types.DHCPLease) error { // Convert DHCP lease to IPv4Config - // ipv4Config := im.convertDHCPLeaseToIPv4Config(lease) + ipv4Config := im.convertDHCPLeaseToIPv4Config(lease) // Apply the configuration using ReconcileLinkAddrs - // return im.ReconcileLinkAddrs(ipv4Config) - return nil + return im.ReconcileLinkAddrs([]*types.IPAddress{ipv4Config}) } // convertDHCPLeaseToIPv4Config converts a DHCP lease to IPv4Config -// func (im *InterfaceManager) convertDHCPLeaseToIPv4Config(lease *types.DHCPLease) *netif.IPv4Config { -// // Create IPNet from IP and netmask -// ipNet := &net.IPNet{ -// IP: lease.IPAddress, -// Mask: net.IPMask(lease.Netmask), -// } +func (im *InterfaceManager) convertDHCPLeaseToIPv4Config(lease *types.DHCPLease) *types.IPAddress { + // Create IPNet from IP and netmask + ipNet := &net.IPNet{ + IP: lease.IPAddress, + Mask: net.IPMask(lease.Netmask), + } -// // Create IPv4Address -// ipv4Addr := netif.IPv4Address{ -// Address: *ipNet, -// Gateway: lease.Gateway, -// Secondary: false, -// Permanent: false, -// } + // Create IPv4Address + ipv4Addr := types.IPAddress{ + Address: *ipNet, + Gateway: lease.Routers[0], + Secondary: false, + Permanent: false, + } -// // Create IPv4Config -// return &netif.IPv4Config{ -// Addresses: []netif.IPv4Address{ipv4Addr}, -// Nameservers: lease.DNS, -// SearchList: lease.SearchList, -// Domain: lease.Domain, -// Interface: im.ifaceName, -// } -// } + // Create IPv4Config + return &ipv4Addr +} diff --git a/pkg/nmlite/link/netlink.go b/pkg/nmlite/link/netlink.go index 7c252920..01adbe86 100644 --- a/pkg/nmlite/link/netlink.go +++ b/pkg/nmlite/link/netlink.go @@ -13,6 +13,7 @@ import ( "sync" "time" + "github.com/jetkvm/kvm/internal/network/types" "github.com/rs/zerolog" "github.com/vishvananda/netlink" ) @@ -239,8 +240,6 @@ func (nm *NetlinkManager) RemoveNonLinkLocalIPv6Addresses(link *Link) error { return nil } -// Route operations - // RouteList gets all routes func (nm *NetlinkManager) RouteList(link *Link, family int) ([]netlink.Route, error) { nm.mu.RLock() @@ -336,6 +335,42 @@ func (nm *NetlinkManager) RemoveDefaultRoute(family int) error { return nil } +func (nm *NetlinkManager) ReconcileLinkAddrs(link *Link, expected []*types.IPAddress) error { + existingAddr := make(map[string]bool) + + addrs, err := nm.AddrList(link, AfUnspec) + if err != nil { + return fmt.Errorf("failed to get addresses: %w", err) + } + + for _, addr := range addrs { + ipCidr := addr.IP.String() + "/" + addr.IPNet.Mask.String() + existingAddr[ipCidr] = true + } + + for _, addr := range expected { + ipCidr := addr.Address.IP.String() + "/" + addr.Address.Mask.String() + if ok := existingAddr[ipCidr]; ok { + continue + } + + ipNet := &net.IPNet{ + IP: addr.Address.IP, + Mask: addr.Address.Mask, + } + + addr := &netlink.Addr{ + IPNet: ipNet, + } + + if err := nm.AddrAdd(link, addr); err != nil { + return fmt.Errorf("failed to add address %s: %w", ipCidr, err) + } + } + + return nil +} + // Sysctl operations // SetSysctlValues sets sysctl values for the interface