mirror of
https://github.com/luckfox-eng29/kvm.git
synced 2026-01-18 03:28:19 +01:00
Add support for Luckfox PicoKVM
Signed-off-by: luckfox-eng29 <eng29@luckfox.com>
This commit is contained in:
@@ -97,7 +97,7 @@ func (l *Logger) updateLogLevel() {
|
||||
finalDefaultLogLevel := l.defaultLogLevel
|
||||
|
||||
for name, level := range zerologLevels {
|
||||
env := os.Getenv(fmt.Sprintf("JETKVM_LOG_%s", name))
|
||||
env := os.Getenv(fmt.Sprintf("KVM_LOG_%s", name))
|
||||
|
||||
if env == "" {
|
||||
env = os.Getenv(fmt.Sprintf("PION_LOG_%s", name))
|
||||
|
||||
@@ -48,10 +48,17 @@ func (c pionLogger) Errorf(format string, args ...interface{}) {
|
||||
type pionLoggerFactory struct{}
|
||||
|
||||
func (c pionLoggerFactory) NewLogger(subsystem string) logging.LeveledLogger {
|
||||
logger := rootLogger.getLogger(subsystem).With().
|
||||
var logger zerolog.Logger
|
||||
|
||||
base := rootLogger.getLogger(subsystem).With().
|
||||
Str("scope", "pion").
|
||||
Str("component", subsystem).
|
||||
Logger()
|
||||
Str("component", subsystem)
|
||||
|
||||
if subsystem == "mdns" {
|
||||
logger = base.Logger().Level(zerolog.ErrorLevel) // 或 ErrorLevel
|
||||
} else {
|
||||
logger = base.Logger()
|
||||
}
|
||||
|
||||
return pionLogger{logger: &logger}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import "github.com/rs/zerolog"
|
||||
|
||||
var (
|
||||
rootZerologLogger = zerolog.New(defaultLogOutput).With().
|
||||
Str("scope", "jetkvm").
|
||||
Str("scope", "kvm").
|
||||
Timestamp().
|
||||
Stack().
|
||||
Logger()
|
||||
|
||||
@@ -7,7 +7,8 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/jetkvm/kvm/internal/logging"
|
||||
"kvm/internal/logging"
|
||||
|
||||
pion_mdns "github.com/pion/mdns/v2"
|
||||
"github.com/rs/zerolog"
|
||||
"golang.org/x/net/ipv4"
|
||||
|
||||
@@ -5,8 +5,9 @@ import (
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"kvm/internal/mdns"
|
||||
|
||||
"github.com/guregu/null/v6"
|
||||
"github.com/jetkvm/kvm/internal/mdns"
|
||||
"golang.org/x/net/idna"
|
||||
)
|
||||
|
||||
|
||||
@@ -5,9 +5,10 @@ import (
|
||||
"net"
|
||||
"sync"
|
||||
|
||||
"github.com/jetkvm/kvm/internal/confparser"
|
||||
"github.com/jetkvm/kvm/internal/logging"
|
||||
"github.com/jetkvm/kvm/internal/udhcpc"
|
||||
"kvm/internal/confparser"
|
||||
"kvm/internal/logging"
|
||||
"kvm/internal/udhcpc"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
|
||||
"github.com/vishvananda/netlink"
|
||||
@@ -58,7 +59,7 @@ func NewNetworkInterfaceState(opts *NetworkInterfaceOptions) (*NetworkInterfaceS
|
||||
}
|
||||
|
||||
if opts.DefaultHostname == "" {
|
||||
opts.DefaultHostname = "jetkvm"
|
||||
opts.DefaultHostname = "picokvm"
|
||||
}
|
||||
|
||||
err := confparser.SetDefaultsAndValidate(opts.NetworkConfig)
|
||||
|
||||
@@ -4,8 +4,8 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/jetkvm/kvm/internal/confparser"
|
||||
"github.com/jetkvm/kvm/internal/udhcpc"
|
||||
"kvm/internal/confparser"
|
||||
"kvm/internal/udhcpc"
|
||||
)
|
||||
|
||||
type RpcIPv6Address struct {
|
||||
|
||||
@@ -8,64 +8,64 @@ import (
|
||||
var (
|
||||
metricTimeSyncStatus = promauto.NewGauge(
|
||||
prometheus.GaugeOpts{
|
||||
Name: "jetkvm_timesync_status",
|
||||
Name: "kvm_timesync_status",
|
||||
Help: "The status of the timesync, 1 if successful, 0 if not",
|
||||
},
|
||||
)
|
||||
metricTimeSyncCount = promauto.NewCounter(
|
||||
prometheus.CounterOpts{
|
||||
Name: "jetkvm_timesync_total",
|
||||
Name: "kvm_timesync_total",
|
||||
Help: "The number of times the timesync has been run",
|
||||
},
|
||||
)
|
||||
metricTimeSyncSuccessCount = promauto.NewCounter(
|
||||
prometheus.CounterOpts{
|
||||
Name: "jetkvm_timesync_success_total",
|
||||
Name: "kvm_timesync_success_total",
|
||||
Help: "The number of times the timesync has been successful",
|
||||
},
|
||||
)
|
||||
metricRTCUpdateCount = promauto.NewCounter( //nolint:unused
|
||||
prometheus.CounterOpts{
|
||||
Name: "jetkvm_timesync_rtc_update_total",
|
||||
Name: "kvm_timesync_rtc_update_total",
|
||||
Help: "The number of times the RTC has been updated",
|
||||
},
|
||||
)
|
||||
metricNtpTotalSuccessCount = promauto.NewCounter(
|
||||
prometheus.CounterOpts{
|
||||
Name: "jetkvm_timesync_ntp_total_success_total",
|
||||
Name: "kvm_timesync_ntp_total_success_total",
|
||||
Help: "The total number of successful NTP requests",
|
||||
},
|
||||
)
|
||||
metricNtpTotalRequestCount = promauto.NewCounter(
|
||||
prometheus.CounterOpts{
|
||||
Name: "jetkvm_timesync_ntp_total_request_total",
|
||||
Name: "kvm_timesync_ntp_total_request_total",
|
||||
Help: "The total number of NTP requests sent",
|
||||
},
|
||||
)
|
||||
metricNtpSuccessCount = promauto.NewCounterVec(
|
||||
prometheus.CounterOpts{
|
||||
Name: "jetkvm_timesync_ntp_success_total",
|
||||
Name: "kvm_timesync_ntp_success_total",
|
||||
Help: "The number of successful NTP requests",
|
||||
},
|
||||
[]string{"url"},
|
||||
)
|
||||
metricNtpRequestCount = promauto.NewCounterVec(
|
||||
prometheus.CounterOpts{
|
||||
Name: "jetkvm_timesync_ntp_request_total",
|
||||
Name: "kvm_timesync_ntp_request_total",
|
||||
Help: "The number of NTP requests sent to the server",
|
||||
},
|
||||
[]string{"url"},
|
||||
)
|
||||
metricNtpServerLastRTT = promauto.NewGaugeVec(
|
||||
prometheus.GaugeOpts{
|
||||
Name: "jetkvm_timesync_ntp_server_last_rtt",
|
||||
Name: "kvm_timesync_ntp_server_last_rtt",
|
||||
Help: "The last RTT of the NTP server in milliseconds",
|
||||
},
|
||||
[]string{"url"},
|
||||
)
|
||||
metricNtpServerRttHistogram = promauto.NewHistogramVec(
|
||||
prometheus.HistogramOpts{
|
||||
Name: "jetkvm_timesync_ntp_server_rtt",
|
||||
Name: "kvm_timesync_ntp_server_rtt",
|
||||
Help: "The histogram of the RTT of the NTP server in milliseconds",
|
||||
Buckets: []float64{
|
||||
10, 25, 50, 100, 200, 300, 500, 1000,
|
||||
@@ -75,7 +75,7 @@ var (
|
||||
)
|
||||
metricNtpServerInfo = promauto.NewGaugeVec(
|
||||
prometheus.GaugeOpts{
|
||||
Name: "jetkvm_timesync_ntp_server_info",
|
||||
Name: "kvm_timesync_ntp_server_info",
|
||||
Help: "The info of the NTP server",
|
||||
},
|
||||
[]string{"url", "reference", "stratum", "precision"},
|
||||
@@ -83,53 +83,53 @@ var (
|
||||
|
||||
metricHttpTotalSuccessCount = promauto.NewCounter(
|
||||
prometheus.CounterOpts{
|
||||
Name: "jetkvm_timesync_http_total_success_total",
|
||||
Name: "kvm_timesync_http_total_success_total",
|
||||
Help: "The total number of successful HTTP requests",
|
||||
},
|
||||
)
|
||||
metricHttpTotalRequestCount = promauto.NewCounter(
|
||||
prometheus.CounterOpts{
|
||||
Name: "jetkvm_timesync_http_total_request_total",
|
||||
Name: "kvm_timesync_http_total_request_total",
|
||||
Help: "The total number of HTTP requests sent",
|
||||
},
|
||||
)
|
||||
metricHttpTotalCancelCount = promauto.NewCounter(
|
||||
prometheus.CounterOpts{
|
||||
Name: "jetkvm_timesync_http_total_cancel_total",
|
||||
Name: "kvm_timesync_http_total_cancel_total",
|
||||
Help: "The total number of HTTP requests cancelled",
|
||||
},
|
||||
)
|
||||
metricHttpSuccessCount = promauto.NewCounterVec(
|
||||
prometheus.CounterOpts{
|
||||
Name: "jetkvm_timesync_http_success_total",
|
||||
Name: "kvm_timesync_http_success_total",
|
||||
Help: "The number of successful HTTP requests",
|
||||
},
|
||||
[]string{"url"},
|
||||
)
|
||||
metricHttpRequestCount = promauto.NewCounterVec(
|
||||
prometheus.CounterOpts{
|
||||
Name: "jetkvm_timesync_http_request_total",
|
||||
Name: "kvm_timesync_http_request_total",
|
||||
Help: "The number of HTTP requests sent to the server",
|
||||
},
|
||||
[]string{"url"},
|
||||
)
|
||||
metricHttpCancelCount = promauto.NewCounterVec(
|
||||
prometheus.CounterOpts{
|
||||
Name: "jetkvm_timesync_http_cancel_total",
|
||||
Name: "kvm_timesync_http_cancel_total",
|
||||
Help: "The number of HTTP requests cancelled",
|
||||
},
|
||||
[]string{"url"},
|
||||
)
|
||||
metricHttpServerLastRTT = promauto.NewGaugeVec(
|
||||
prometheus.GaugeOpts{
|
||||
Name: "jetkvm_timesync_http_server_last_rtt",
|
||||
Name: "kvm_timesync_http_server_last_rtt",
|
||||
Help: "The last RTT of the HTTP server in milliseconds",
|
||||
},
|
||||
[]string{"url"},
|
||||
)
|
||||
metricHttpServerRttHistogram = promauto.NewHistogramVec(
|
||||
prometheus.HistogramOpts{
|
||||
Name: "jetkvm_timesync_http_server_rtt",
|
||||
Name: "kvm_timesync_http_server_rtt",
|
||||
Help: "The histogram of the RTT of the HTTP server in milliseconds",
|
||||
Buckets: []float64{
|
||||
10, 25, 50, 100, 200, 300, 500, 1000,
|
||||
@@ -139,7 +139,7 @@ var (
|
||||
)
|
||||
metricHttpServerInfo = promauto.NewGaugeVec(
|
||||
prometheus.GaugeOpts{
|
||||
Name: "jetkvm_timesync_http_server_info",
|
||||
Name: "kvm_timesync_http_server_info",
|
||||
Help: "The info of the HTTP server",
|
||||
},
|
||||
[]string{"url", "http_code"},
|
||||
|
||||
@@ -7,7 +7,8 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/jetkvm/kvm/internal/network"
|
||||
"kvm/internal/network"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
|
||||
@@ -4,12 +4,15 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"time"
|
||||
|
||||
"github.com/fsnotify/fsnotify"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/vishvananda/netlink"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -66,6 +69,36 @@ func (c *DHCPClient) getWatchPaths() []string {
|
||||
return paths
|
||||
}
|
||||
|
||||
func (c *DHCPClient) watchLink() {
|
||||
ch := make(chan netlink.LinkUpdate)
|
||||
done := make(chan struct{})
|
||||
|
||||
if err := netlink.LinkSubscribe(ch, done); err != nil {
|
||||
c.logger.Error().Err(err).Msg("failed to subscribe to netlink")
|
||||
return
|
||||
}
|
||||
|
||||
for update := range ch {
|
||||
if update.Link.Attrs().Name == c.InterfaceName {
|
||||
if update.IfInfomsg.Flags&unix.IFF_RUNNING != 0 {
|
||||
fmt.Printf("[watchLink]link is up, starting udhcpc")
|
||||
go c.runUDHCPC()
|
||||
} else {
|
||||
c.logger.Info().Msg("link is down")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *DHCPClient) runUDHCPC() {
|
||||
cmd := exec.Command("udhcpc", "-i", c.InterfaceName, "-t", "1")
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
if err := cmd.Run(); err != nil {
|
||||
c.logger.Error().Err(err).Msg("failed to run udhcpc")
|
||||
}
|
||||
}
|
||||
|
||||
// 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 {
|
||||
@@ -80,6 +113,8 @@ func (c *DHCPClient) Run() error {
|
||||
}
|
||||
defer watcher.Close()
|
||||
|
||||
go c.watchLink()
|
||||
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
|
||||
@@ -15,7 +15,7 @@ var (
|
||||
VendorId: "0x1d6b", //The Linux Foundation
|
||||
ProductId: "0x0104", //Multifunction Composite Gadget
|
||||
SerialNumber: "",
|
||||
Manufacturer: "JetKVM",
|
||||
Manufacturer: "KVM",
|
||||
Product: "USB Emulation Device",
|
||||
strictMode: true,
|
||||
}
|
||||
@@ -25,7 +25,7 @@ var (
|
||||
Keyboard: true,
|
||||
MassStorage: true,
|
||||
}
|
||||
usbGadgetName = "jetkvm"
|
||||
usbGadgetName = "kvm"
|
||||
usbGadget *UsbGadget
|
||||
)
|
||||
|
||||
@@ -109,7 +109,7 @@ func TestUsbGadgetUDCNotBoundAfterReportDescrChanged(t *testing.T) {
|
||||
udc := udcs[0]
|
||||
assert.NotNil(udc, "UDC should exist")
|
||||
|
||||
udcStr, err := os.ReadFile("/sys/kernel/config/usb_gadget/jetkvm/UDC")
|
||||
udcStr, err := os.ReadFile("/sys/kernel/config/usb_gadget/kvm/UDC")
|
||||
assert.Nil(err, "usb_gadget/UDC should exist")
|
||||
assert.Equal(strings.TrimSpace(udc), strings.TrimSpace(string(udcStr)), "UDC should be the same")
|
||||
}
|
||||
|
||||
@@ -34,7 +34,8 @@ var defaultGadgetConfig = map[string]gadgetConfigItem{
|
||||
"bcdDevice": "0100",
|
||||
},
|
||||
configAttrs: gadgetAttributes{
|
||||
"MaxPower": "250", // in unit of 2mA
|
||||
"MaxPower": "250", // in unit of 2mA
|
||||
"bmAttributes": "0xa0", // 0x80 = bus-powered, 0xa0 = bus-powered + remote wakeup
|
||||
},
|
||||
},
|
||||
"base_info": {
|
||||
@@ -43,8 +44,8 @@ var defaultGadgetConfig = map[string]gadgetConfigItem{
|
||||
configPath: []string{"strings", "0x409"},
|
||||
attrs: gadgetAttributes{
|
||||
"serialnumber": "",
|
||||
"manufacturer": "JetKVM",
|
||||
"product": "JetKVM USB Emulation Device",
|
||||
"manufacturer": "KVM",
|
||||
"product": "KVM USB Emulation Device",
|
||||
},
|
||||
configAttrs: gadgetAttributes{
|
||||
"configuration": "Config 1: HID",
|
||||
@@ -59,6 +60,23 @@ var defaultGadgetConfig = map[string]gadgetConfigItem{
|
||||
// mass storage
|
||||
"mass_storage_base": massStorageBaseConfig,
|
||||
"mass_storage_lun0": massStorageLun0Config,
|
||||
// audio
|
||||
"audio": {
|
||||
order: 4000,
|
||||
device: "uac1.usb0",
|
||||
path: []string{"functions", "uac1.usb0"},
|
||||
configPath: []string{"uac1.usb0"},
|
||||
attrs: gadgetAttributes{
|
||||
"p_chmask": "3",
|
||||
"p_srate": "48000",
|
||||
"p_ssize": "2",
|
||||
"p_volume_present": "0",
|
||||
"c_chmask": "3",
|
||||
"c_srate": "48000",
|
||||
"c_ssize": "2",
|
||||
"c_volume_present": "0",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func (u *UsbGadget) isGadgetConfigItemEnabled(itemKey string) bool {
|
||||
@@ -73,6 +91,8 @@ func (u *UsbGadget) isGadgetConfigItemEnabled(itemKey string) bool {
|
||||
return u.enabledDevices.MassStorage
|
||||
case "mass_storage_lun0":
|
||||
return u.enabledDevices.MassStorage
|
||||
case "audio":
|
||||
return u.enabledDevices.Audio
|
||||
default:
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -18,9 +18,8 @@ var massStorageLun0Config = gadgetConfigItem{
|
||||
"ro": "1",
|
||||
"removable": "1",
|
||||
"file": "\n",
|
||||
// the additional whitespace is intentional to avoid the "JetKVM V irtual Media" string
|
||||
// https://github.com/jetkvm/rv1106-system/blob/778133a1c153041e73f7de86c9c434a2753ea65d/sysdrv/source/uboot/u-boot/drivers/usb/gadget/f_mass_storage.c#L2556
|
||||
// the additional whitespace is intentional to avoid the "KVM V irtual Media" string
|
||||
// Vendor (8 chars), product (16 chars)
|
||||
"inquiry_string": "JetKVM Virtual Media",
|
||||
"inquiry_string": "KVM Virtual Media",
|
||||
},
|
||||
}
|
||||
|
||||
@@ -9,7 +9,8 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/jetkvm/kvm/internal/logging"
|
||||
"kvm/internal/logging"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
@@ -19,6 +20,7 @@ type Devices struct {
|
||||
RelativeMouse bool `json:"relative_mouse"`
|
||||
Keyboard bool `json:"keyboard"`
|
||||
MassStorage bool `json:"mass_storage"`
|
||||
Audio bool `json:"audio"`
|
||||
}
|
||||
|
||||
// Config is a struct that represents the customizations for a USB gadget.
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
package websecure
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var (
|
||||
fixtureEd25519Certificate = `-----BEGIN CERTIFICATE-----
|
||||
MIIBQDCB86ADAgECAhQdB4qB6dV0/u1lwhJofQgkmjjV1zAFBgMrZXAwLzELMAkG
|
||||
A1UEBhMCREUxIDAeBgNVBAMMF2VkMjU1MTktdGVzdC5qZXRrdm0uY29tMB4XDTI1
|
||||
MDUyMzEyNTkyN1oXDTI3MDQyMzEyNTkyN1owLzELMAkGA1UEBhMCREUxIDAeBgNV
|
||||
BAMMF2VkMjU1MTktdGVzdC5qZXRrdm0uY29tMCowBQYDK2VwAyEA9tLyoulJn7Ev
|
||||
bf8kuD1ZGdA092773pCRjFEDKpXHonyjITAfMB0GA1UdDgQWBBRkmrVMfsLY57iy
|
||||
r/0POP0S4QxCADAFBgMrZXADQQBfTRvqavLHDYQiKQTgbGod+Yn+fIq2lE584+1U
|
||||
C4wh9peIJDFocLBEAYTQpEMKxa4s0AIRxD+a7aCS5oz0e/0I
|
||||
-----END CERTIFICATE-----`
|
||||
|
||||
fixtureEd25519PrivateKey = `-----BEGIN PRIVATE KEY-----
|
||||
MC4CAQAwBQYDK2VwBCIEIKV08xUsLRHBfMXqZwxVRzIbViOp8G7aQGjPvoRFjujB
|
||||
-----END PRIVATE KEY-----`
|
||||
|
||||
certStore *CertStore
|
||||
certSigner *SelfSigner
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
tlsStorePath, err := os.MkdirTemp("", "jktls.*")
|
||||
if err != nil {
|
||||
defaultLogger.Fatal().Err(err).Msg("failed to create temp directory")
|
||||
}
|
||||
|
||||
certStore = NewCertStore(tlsStorePath, nil)
|
||||
certStore.LoadCertificates()
|
||||
|
||||
certSigner = NewSelfSigner(
|
||||
certStore,
|
||||
nil,
|
||||
"ci.jetkvm.com",
|
||||
"JetKVM",
|
||||
"JetKVM",
|
||||
"JetKVM",
|
||||
)
|
||||
|
||||
m.Run()
|
||||
|
||||
os.RemoveAll(tlsStorePath)
|
||||
}
|
||||
|
||||
func TestSaveEd25519Certificate(t *testing.T) {
|
||||
err, _ := certStore.ValidateAndSaveCertificate("ed25519-test.jetkvm.com", fixtureEd25519Certificate, fixtureEd25519PrivateKey, true)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to save certificate: %v", err)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user