diff --git a/board/common/qemu/ddi/run.sh b/board/common/qemu/ddi/run.sh index 4f57ae7d8e..1128e2764c 100755 --- a/board/common/qemu/ddi/run.sh +++ b/board/common/qemu/ddi/run.sh @@ -140,7 +140,11 @@ q_add_disk() q_sect_device_usb() { if [ -z "$usb_bus_added" ]; then - q sect usb + case "$IX_QEMU_MACHINE" in + q35*|pc*) + q sect device piix3-usb-uhci + ;; + esac q sect device usb-ehci q param id ehci usb_bus_added=YES diff --git a/src/yangerd/internal/collector/ntp.go b/src/yangerd/internal/collector/ntp.go index 75ea8dd230..7492403b91 100644 --- a/src/yangerd/internal/collector/ntp.go +++ b/src/yangerd/internal/collector/ntp.go @@ -245,8 +245,7 @@ func addAssociations(ntp map[string]interface{}, srcs []ntpSource) { for _, src := range srcs { d := src.data - // Skip reference clocks — they have refids, not addresses - if d.Mode == chrony.SourceModeRef { + if !resolved(d) { continue } @@ -320,6 +319,16 @@ var sourceModeMap = map[chrony.ModeType]string{ chrony.SourceModeRef: "local-clock", } +// resolved reports whether a chrony source has an IP address: refclocks +// carry a refid instead, and a server named by hostname has only a +// placeholder ID until DNS answers. +func resolved(d *chrony.ReplySourceData) bool { + if d.Mode == chrony.SourceModeRef || d.IPAddr == nil { + return false + } + return d.IPAddr.Family == chrony.IPAddrInet4 || d.IPAddr.Family == chrony.IPAddrInet6 +} + // addSources builds the infix-system:ntp/sources/source list. // Reference clocks and sources with invalid stratum are skipped, // matching the Python yanger ietf_system.py add_ntp() behaviour. @@ -328,7 +337,7 @@ func addSources(srcs []ntpSource) map[string]interface{} { for _, src := range srcs { d := src.data - if d.Mode == chrony.SourceModeRef { + if !resolved(d) { continue } if d.Stratum > 16 { diff --git a/src/yangerd/internal/collector/ntp_test.go b/src/yangerd/internal/collector/ntp_test.go index b4f479fdf9..1cf839330e 100644 --- a/src/yangerd/internal/collector/ntp_test.go +++ b/src/yangerd/internal/collector/ntp_test.go @@ -155,6 +155,16 @@ func fullFakeChrony() *fakeChrony { } } +// unresolvedSource is a server configured by hostname that chronyd has +// not resolved yet; cmdmon reports it with an ID placeholder address. +func unresolvedSource() *chrony.ReplySourceData { + d := sourceData(nil, chrony.SourceModeClient, chrony.SourceStateUnreach, + 0, 6, 0, 0, 0, 0) + d.IPAddr.Family = chrony.IPAddrID + d.IPAddr.IP[3] = 1 + return d +} + func unsyncFakeChrony() *fakeChrony { return &fakeChrony{ tracking: &chrony.ReplyTracking{ @@ -398,6 +408,26 @@ func ntpSourceCount(t *testing.T, tr *tree.Tree) int { return len(ntp.Sources.Source) } +func TestNTPUnresolvedSourceSkipped(t *testing.T) { + fake := fullFakeChrony() + fake.data = append(fake.data, unresolvedSource()) + fake.stats = append(fake.stats, nil) + + out, tr := ntpCollect(t, fake) + assocs := out["associations"].(map[string]interface{})["association"].([]interface{}) + if len(assocs) != 3 { + t.Fatalf("expected 3 associations, got %d", len(assocs)) + } + for _, a := range assocs { + if addr := a.(map[string]interface{})["address"].(string); addr == "ID#0000000001" { + t.Fatal("unresolved source leaked into associations") + } + } + if n := ntpSourceCount(t, tr); n != 4 { + t.Fatalf("expected 4 NTP sources, got %d", n) + } +} + func TestNTPSourcesEmpty(t *testing.T) { fake := &fakeChrony{tracking: fullFakeChrony().tracking} diff --git a/test/templates/inc/infix-usb.mustache b/test/templates/inc/infix-usb.mustache index 9dabb2ca17..e7f4aa8544 100644 --- a/test/templates/inc/infix-usb.mustache +++ b/test/templates/inc/infix-usb.mustache @@ -5,5 +5,5 @@ if [ -n "{{qn_usb}}" ]; then dd if=/dev/zero of={{qn_usb}} bs=8M count=1 >/dev/null 2>&1 mkfs.vfat {{qn_usb}} >/dev/null 2>&1 fi - usb_cmd=" -drive if=none,id=usbstick,format=raw,file={{qn_usb}} -usb -device usb-ehci,id=ehci -device usb-storage,bus=ehci.0,drive=usbstick " + usb_cmd=" -drive if=none,id=usbstick,format=raw,file={{qn_usb}} -device piix3-usb-uhci,id=uhci -device usb-ehci,id=ehci -device usb-storage,bus=ehci.0,drive=usbstick " fi