mirror of https://github.com/jetkvm/kvm.git
use sync trace to track mutexes to make deadlock analysis easier
This commit is contained in:
parent
b04b148a4b
commit
aef26459d3
|
|
@ -3,5 +3,11 @@
|
|||
"cva",
|
||||
"cx"
|
||||
],
|
||||
"gopls": {
|
||||
"build.buildFlags": [
|
||||
"-tags",
|
||||
"synctrace"
|
||||
]
|
||||
},
|
||||
"git.ignoreLimitWarning": true
|
||||
}
|
||||
|
|
@ -45,6 +45,8 @@ type IPv6StaticConfig struct {
|
|||
|
||||
// NetworkConfig represents the complete network configuration for an interface
|
||||
type NetworkConfig struct {
|
||||
DHCPClient null.String `json:"dhcp_client,omitempty" one_of:"jetdhcpc,udhcpc" default:"jetdhcpc"`
|
||||
|
||||
Hostname null.String `json:"hostname,omitempty" validate_type:"hostname"`
|
||||
HTTPProxy null.String `json:"http_proxy,omitempty" validate_type:"proxy"`
|
||||
Domain null.String `json:"domain,omitempty" validate_type:"hostname"`
|
||||
|
|
@ -145,6 +147,7 @@ type DHCPLease struct {
|
|||
LeaseExpiry *time.Time `json:"lease_expiry,omitempty"` // The expiry time of the lease
|
||||
|
||||
InterfaceName string `json:"interface_name,omitempty"` // The name of the interface
|
||||
DHCPClient string `json:"dhcp_client,omitempty"` // The DHCP client that obtained the lease
|
||||
}
|
||||
|
||||
// InterfaceState represents the current state of a network interface
|
||||
|
|
@ -173,6 +176,31 @@ type NetworkConfigInterface interface {
|
|||
IPv6Addresses() []IPAddress
|
||||
}
|
||||
|
||||
// IsIPv6 returns true if the DHCP lease is for an IPv6 address
|
||||
func (d *DHCPLease) IsIPv6() bool {
|
||||
return d.IPAddress.To4() == nil
|
||||
}
|
||||
|
||||
// IPMask returns the IP mask for the DHCP lease
|
||||
func (d *DHCPLease) IPMask() net.IPMask {
|
||||
if d.IsIPv6() {
|
||||
// TODO: not implemented
|
||||
return nil
|
||||
}
|
||||
|
||||
mask := net.ParseIP(d.Netmask.String())
|
||||
return net.IPv4Mask(mask[12], mask[13], mask[14], mask[15])
|
||||
}
|
||||
|
||||
// IPNet returns the IP net for the DHCP lease
|
||||
func (d *DHCPLease) IPNet() *net.IPNet {
|
||||
if d.IsIPv6() {
|
||||
// TODO: not implemented
|
||||
return nil
|
||||
}
|
||||
|
||||
return &net.IPNet{
|
||||
IP: d.IPAddress,
|
||||
Mask: d.IPMask(),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ func (t *TimeSync) filterNTPServers(ntpServers []string) ([]string, error) {
|
|||
if ip == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if hasIPv4 && ip.To4() != nil {
|
||||
filteredServers = append(filteredServers, server)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -169,6 +169,9 @@ func (t *TimeSync) doTimeSync() {
|
|||
}
|
||||
|
||||
func (t *TimeSync) Sync() error {
|
||||
t.syncLock.Lock()
|
||||
defer t.syncLock.Unlock()
|
||||
|
||||
var (
|
||||
now *time.Time
|
||||
offset *time.Duration
|
||||
|
|
|
|||
|
|
@ -18,21 +18,19 @@ type DHCPClient struct {
|
|||
ifaceName string
|
||||
logger *zerolog.Logger
|
||||
client types.DHCPClient
|
||||
clientType string
|
||||
link netlink.Link
|
||||
|
||||
// Configuration
|
||||
ipv4Enabled bool
|
||||
ipv6Enabled bool
|
||||
|
||||
// State management
|
||||
// stateManager *DHCPStateManager
|
||||
|
||||
// Callbacks
|
||||
onLeaseChange func(lease *types.DHCPLease)
|
||||
}
|
||||
|
||||
// NewDHCPClient creates a new DHCP client
|
||||
func NewDHCPClient(ctx context.Context, ifaceName string, logger *zerolog.Logger) (*DHCPClient, error) {
|
||||
func NewDHCPClient(ctx context.Context, ifaceName string, logger *zerolog.Logger, clientType string) (*DHCPClient, error) {
|
||||
if ifaceName == "" {
|
||||
return nil, fmt.Errorf("interface name cannot be empty")
|
||||
}
|
||||
|
|
@ -45,6 +43,7 @@ func NewDHCPClient(ctx context.Context, ifaceName string, logger *zerolog.Logger
|
|||
ctx: ctx,
|
||||
ifaceName: ifaceName,
|
||||
logger: logger,
|
||||
clientType: clientType,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
@ -70,10 +69,13 @@ func (dc *DHCPClient) SetOnLeaseChange(callback func(lease *types.DHCPLease)) {
|
|||
}
|
||||
|
||||
func (dc *DHCPClient) initClient() (types.DHCPClient, error) {
|
||||
if false {
|
||||
switch dc.clientType {
|
||||
case "jetdhcpc":
|
||||
return dc.initJetDHCPC()
|
||||
} else {
|
||||
case "udhcpc":
|
||||
return dc.initUDHCPC()
|
||||
default:
|
||||
return nil, fmt.Errorf("invalid client type: %s", dc.clientType)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -204,8 +206,11 @@ func (dc *DHCPClient) handleLeaseChange(lease *types.DHCPLease, isIPv6 bool) {
|
|||
Str("ip", lease.IPAddress.String()).
|
||||
Msg("DHCP lease changed")
|
||||
|
||||
// copy the lease to avoid race conditions
|
||||
leaseCopy := *lease
|
||||
|
||||
// Notify callback
|
||||
if dc.onLeaseChange != nil {
|
||||
dc.onLeaseChange(lease)
|
||||
dc.onLeaseChange(&leaseCopy)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,8 @@ import (
|
|||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/jetkvm/kvm/internal/sync"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
"golang.org/x/net/idna"
|
||||
|
|
|
|||
|
|
@ -4,9 +4,11 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"sync"
|
||||
|
||||
"time"
|
||||
|
||||
"github.com/jetkvm/kvm/internal/sync"
|
||||
|
||||
"github.com/jetkvm/kvm/internal/confparser"
|
||||
"github.com/jetkvm/kvm/internal/logging"
|
||||
"github.com/jetkvm/kvm/internal/network/types"
|
||||
|
|
@ -78,7 +80,7 @@ func NewInterfaceManager(ctx context.Context, ifaceName string, config *types.Ne
|
|||
}
|
||||
|
||||
// create the dhcp client
|
||||
im.dhcpClient, err = NewDHCPClient(ctx, ifaceName, &scopedLogger)
|
||||
im.dhcpClient, err = NewDHCPClient(ctx, ifaceName, &scopedLogger, config.DHCPClient.String)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create DHCP client: %w", err)
|
||||
}
|
||||
|
|
@ -562,7 +564,6 @@ func (im *InterfaceManager) monitorInterfaceState() {
|
|||
defer im.wg.Done()
|
||||
|
||||
im.logger.Debug().Msg("monitoring interface state")
|
||||
|
||||
// TODO: use netlink subscription instead of polling
|
||||
ticker := time.NewTicker(5 * time.Second)
|
||||
defer ticker.Stop()
|
||||
|
|
@ -574,7 +575,6 @@ func (im *InterfaceManager) monitorInterfaceState() {
|
|||
case <-im.stopCh:
|
||||
return
|
||||
case <-ticker.C:
|
||||
im.logger.Debug().Msg("checking interface state")
|
||||
if err := im.updateInterfaceState(); err != nil {
|
||||
im.logger.Error().Err(err).Msg("failed to update interface state")
|
||||
}
|
||||
|
|
@ -727,12 +727,9 @@ func (im *InterfaceManager) applyDHCPLease(lease *types.DHCPLease) error {
|
|||
|
||||
// convertDHCPLeaseToIPv4Config converts a DHCP lease to IPv4Config
|
||||
func (im *InterfaceManager) convertDHCPLeaseToIPv4Config(lease *types.DHCPLease) *types.IPAddress {
|
||||
mask := lease.Netmask
|
||||
|
||||
// Create IPNet from IP and netmask
|
||||
ipNet := &net.IPNet{
|
||||
IP: lease.IPAddress,
|
||||
Mask: net.IPv4Mask(mask[12], mask[13], mask[14], mask[15]),
|
||||
ipNet := lease.IPNet()
|
||||
if ipNet == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Create IPv4Address
|
||||
|
|
|
|||
|
|
@ -6,9 +6,11 @@ import (
|
|||
"fmt"
|
||||
"net"
|
||||
"slices"
|
||||
"sync"
|
||||
|
||||
"time"
|
||||
|
||||
"github.com/jetkvm/kvm/internal/sync"
|
||||
|
||||
"github.com/go-co-op/gocron/v2"
|
||||
"github.com/insomniacslk/dhcp/dhcpv4"
|
||||
"github.com/insomniacslk/dhcp/dhcpv6"
|
||||
|
|
|
|||
|
|
@ -33,7 +33,9 @@ type Lease struct {
|
|||
|
||||
// ToDHCPLease converts a lease to a DHCP lease.
|
||||
func (l *Lease) ToDHCPLease() *types.DHCPLease {
|
||||
return &l.DHCPLease
|
||||
lease := &l.DHCPLease
|
||||
lease.DHCPClient = "jetdhcpc"
|
||||
return lease
|
||||
}
|
||||
|
||||
// fromNclient4Lease creates a lease from a nclient4.Lease.
|
||||
|
|
@ -45,9 +47,9 @@ func fromNclient4Lease(l *nclient4.Lease, iface string) *Lease {
|
|||
// only the fields that we need are set
|
||||
lease.Routers = l.ACK.Router()
|
||||
lease.IPAddress = l.ACK.YourIPAddr
|
||||
|
||||
lease.Netmask = net.IP(l.ACK.SubnetMask())
|
||||
lease.Broadcast = l.ACK.BroadcastAddress()
|
||||
// lease.MTU = int(resp.Options.Get(dhcpv4.OptionInterfaceMTU))
|
||||
|
||||
lease.NTPServers = l.ACK.NTPServers()
|
||||
|
||||
|
|
|
|||
|
|
@ -10,9 +10,10 @@ import (
|
|||
"path"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/jetkvm/kvm/internal/sync"
|
||||
|
||||
"github.com/jetkvm/kvm/internal/network/types"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/vishvananda/netlink"
|
||||
|
|
|
|||
|
|
@ -6,7 +6,8 @@ package nmlite
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/jetkvm/kvm/internal/sync"
|
||||
|
||||
"github.com/jetkvm/kvm/internal/logging"
|
||||
"github.com/jetkvm/kvm/internal/network/types"
|
||||
|
|
|
|||
|
|
@ -40,7 +40,9 @@ func (l *Lease) ToJSON() string {
|
|||
|
||||
// ToDHCPLease converts a lease to a DHCP lease.
|
||||
func (l *Lease) ToDHCPLease() *types.DHCPLease {
|
||||
return &l.DHCPLease
|
||||
lease := &l.DHCPLease
|
||||
lease.DHCPClient = "udhcpc"
|
||||
return lease
|
||||
}
|
||||
|
||||
// SetLeaseExpiry sets the lease expiry time.
|
||||
|
|
|
|||
|
|
@ -6,9 +6,11 @@ import (
|
|||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"sync"
|
||||
|
||||
"time"
|
||||
|
||||
"github.com/jetkvm/kvm/internal/sync"
|
||||
|
||||
"github.com/fsnotify/fsnotify"
|
||||
"github.com/jetkvm/kvm/internal/network/types"
|
||||
"github.com/rs/zerolog"
|
||||
|
|
|
|||
|
|
@ -221,6 +221,13 @@ export default function DhcpLeaseCard({
|
|||
</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{networkState?.dhcp_lease?.dhcp_client && (
|
||||
<div className="flex justify-between border-t border-slate-800/10 pt-2 dark:border-slate-300/20">
|
||||
<span className="text-sm text-slate-600 dark:text-slate-400">DHCP Client</span>
|
||||
<span className="text-sm font-medium">{networkState?.dhcp_lease?.dhcp_client}</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -690,6 +690,7 @@ export interface DhcpLease {
|
|||
message?: string;
|
||||
tftp?: string;
|
||||
bootfile?: string;
|
||||
dhcp_client?: string;
|
||||
}
|
||||
|
||||
export interface IPv6Address {
|
||||
|
|
|
|||
Loading…
Reference in New Issue