send router solicitation

This commit is contained in:
Siyuan 2025-10-08 10:57:31 +00:00
parent 638949c289
commit 8310077af6
5 changed files with 83 additions and 10 deletions

View File

@ -325,11 +325,8 @@ func startBacklightTickers() {
dimTicker = time.NewTicker(time.Duration(config.DisplayDimAfterSec) * time.Second) dimTicker = time.NewTicker(time.Duration(config.DisplayDimAfterSec) * time.Second)
go func() { go func() {
for { //nolint:staticcheck for range dimTicker.C {
select { tick_displayDim()
case <-dimTicker.C:
tick_displayDim()
}
} }
}() }()
} }
@ -339,11 +336,8 @@ func startBacklightTickers() {
offTicker = time.NewTicker(time.Duration(config.DisplayOffAfterSec) * time.Second) offTicker = time.NewTicker(time.Duration(config.DisplayOffAfterSec) * time.Second)
go func() { go func() {
for { //nolint:staticcheck for range offTicker.C {
select { tick_displayOff()
case <-offTicker.C:
tick_displayOff()
}
} }
}() }()
} }

1
go.mod
View File

@ -61,6 +61,7 @@ require (
github.com/leodido/go-urn v1.4.0 // indirect github.com/leodido/go-urn v1.4.0 // indirect
github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-colorable v0.1.14 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mdlayher/ndp v1.1.0 // indirect
github.com/mdlayher/packet v1.1.2 // indirect github.com/mdlayher/packet v1.1.2 // indirect
github.com/mdlayher/socket v0.4.1 // indirect github.com/mdlayher/socket v0.4.1 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect

2
go.sum
View File

@ -99,6 +99,8 @@ github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mdlayher/ndp v1.1.0 h1:QylGKGVtH60sKZUE88+IW5ila1Z/M9/OXhWdsVKuscs=
github.com/mdlayher/ndp v1.1.0/go.mod h1:FmgESgemgjl38vuOIyAHWUUL6vQKA/pQNkvXdWsdQFM=
github.com/mdlayher/packet v1.1.2 h1:3Up1NG6LZrsgDVn6X4L9Ge/iyRyxFEFD9o6Pr3Q1nQY= github.com/mdlayher/packet v1.1.2 h1:3Up1NG6LZrsgDVn6X4L9Ge/iyRyxFEFD9o6Pr3Q1nQY=
github.com/mdlayher/packet v1.1.2/go.mod h1:GEu1+n9sG5VtiRE4SydOmX5GTwyyYlteZiFU+x0kew4= github.com/mdlayher/packet v1.1.2/go.mod h1:GEu1+n9sG5VtiRE4SydOmX5GTwyyYlteZiFU+x0kew4=
github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U= github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U=

View File

@ -4,6 +4,7 @@ import (
"context" "context"
"fmt" "fmt"
"net" "net"
"net/netip"
"time" "time"
@ -13,6 +14,7 @@ import (
"github.com/jetkvm/kvm/internal/logging" "github.com/jetkvm/kvm/internal/logging"
"github.com/jetkvm/kvm/internal/network/types" "github.com/jetkvm/kvm/internal/network/types"
"github.com/jetkvm/kvm/pkg/nmlite/link" "github.com/jetkvm/kvm/pkg/nmlite/link"
"github.com/mdlayher/ndp"
"github.com/rs/zerolog" "github.com/rs/zerolog"
"github.com/vishvananda/netlink" "github.com/vishvananda/netlink"
) )
@ -453,6 +455,10 @@ func (im *InterfaceManager) applyIPv6SLAAC() error {
return fmt.Errorf("failed to remove non-link-local IPv6 addresses: %w", err) return fmt.Errorf("failed to remove non-link-local IPv6 addresses: %w", err)
} }
if err := im.SendRouterSolicitation(); err != nil {
return fmt.Errorf("failed to send router solicitation: %w", err)
}
// Enable SLAAC // Enable SLAAC
return im.staticConfig.EnableIPv6SLAAC() return im.staticConfig.EnableIPv6SLAAC()
} }
@ -545,6 +551,48 @@ func (im *InterfaceManager) handleLinkStateChange(link *link.Link) {
} }
} }
// SendRouterSolicitation sends a router solicitation
func (im *InterfaceManager) SendRouterSolicitation() error {
im.logger.Info().Msg("sending router solicitation")
m := &ndp.RouterSolicitation{}
l, err := im.link()
if err != nil {
return fmt.Errorf("failed to get interface: %w", err)
}
iface := l.Interface()
if iface == nil {
return fmt.Errorf("failed to get net.Interface for %s", im.ifaceName)
}
hwAddr := l.HardwareAddr()
if hwAddr == nil {
return fmt.Errorf("failed to get hardware address for %s", im.ifaceName)
}
c, _, err := ndp.Listen(iface, ndp.LinkLocal)
defer c.Close()
if err != nil {
return fmt.Errorf("failed to create NDP listener on %s: %w", im.ifaceName, err)
}
m.Options = append(m.Options, &ndp.LinkLayerAddress{
Addr: hwAddr,
Direction: ndp.Source,
})
targetAddr := netip.MustParseAddr("ff02::2")
if err := c.WriteTo(m, nil, targetAddr); err != nil {
return fmt.Errorf("failed to write to %s: %w", targetAddr.String(), err)
}
im.logger.Info().Msg("router solicitation sent")
return nil
}
func (im *InterfaceManager) handleLinkUp() { func (im *InterfaceManager) handleLinkUp() {
im.logger.Info().Msg("link up") im.logger.Info().Msg("link up")
@ -553,6 +601,11 @@ func (im *InterfaceManager) handleLinkUp() {
if im.config.IPv4Mode.String == "dhcp" { if im.config.IPv4Mode.String == "dhcp" {
im.dhcpClient.Renew() im.dhcpClient.Renew()
} }
if im.config.IPv6Mode.String == "slaac" {
im.staticConfig.EnableIPv6SLAAC()
im.SendRouterSolicitation()
}
} }
func (im *InterfaceManager) handleLinkDown() { func (im *InterfaceManager) handleLinkDown() {

View File

@ -37,6 +37,7 @@ type Link struct {
netlink.Link netlink.Link
} }
// Refresh refreshes the link
func (l *Link) Refresh() error { func (l *Link) Refresh() error {
linkName := l.Link.Attrs().Name linkName := l.Link.Attrs().Name
link, err := netlink.LinkByName(linkName) link, err := netlink.LinkByName(linkName)
@ -50,6 +51,28 @@ func (l *Link) Refresh() error {
return nil return nil
} }
// Interface returns the interface of the link
func (l *Link) Interface() *net.Interface {
attrs := l.Attrs()
if attrs.Name == "" {
return nil
}
iface, err := net.InterfaceByName(attrs.Name)
if err != nil {
return nil
}
return iface
}
// HardwareAddr returns the hardware address of the link
func (l *Link) HardwareAddr() net.HardwareAddr {
attrs := l.Attrs()
if attrs.HardwareAddr == nil {
return nil
}
return attrs.HardwareAddr
}
// Attrs returns the attributes of the link // Attrs returns the attributes of the link
func (l *Link) Attrs() *netlink.LinkAttrs { func (l *Link) Attrs() *netlink.LinkAttrs {
return l.Link.Attrs() return l.Link.Attrs()