Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions pkg/daemon/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -791,6 +791,8 @@ func (dn *Daemon) applyNodePtpProfile(runID int, nodeProfile *ptpv1.PtpProfile)
if controllingProfile, isControlled := (*nodeProfile).PtpSettings["controllingProfile"]; isControlled && controllingProfile != "" {
// See DownstreamIWF
glog.Infof("Skipping PMC monitoring for controlled profile %s", *nodeProfile.Name)
} else if clockType == event.GM {
glog.Infof("Skipping PMC monitoring for GM")
} else {
pmcClockType, clockTypeFound := (*nodeProfile).PtpSettings["clockType"]
if !clockTypeFound {
Expand Down
25 changes: 14 additions & 11 deletions pkg/event/event.go
Original file line number Diff line number Diff line change
Expand Up @@ -644,25 +644,28 @@ connect:
case <-e.closeCh:
return
case <-classTicker.C: // send clock class event 60 secs interval
if cfgName != "" {
parts := strings.SplitN(cfgName, ".", 2)
for clkCfgName, data := range e.clkSyncState {
clockClass := data.clockClass
parts := strings.SplitN(clkCfgName, ".", 2)
if len(parts) >= 2 {
cfgName = "ptp4l." + strings.Join(parts[1:], ".")
clkCfgName = "ptp4l." + strings.Join(parts[1:], ".")
}
utils.EmitClockClass(c, PTP4lProcessName, cfgName, e.clockClass)
if clockClass == 0 {
continue
}
if clkCfgName == cfgName {
// Stop double emit
cfgName = ""
}
utils.EmitClockClass(c, PTP4lProcessName, clkCfgName, clockClass)
}

for cfgName, data := range e.clkSyncState {
clockClass := data.clockClass
if cfgName != "" {
parts := strings.SplitN(cfgName, ".", 2)
if len(parts) >= 2 {
cfgName = "ptp4l." + strings.Join(parts[1:], ".")
}
if clockClass == 0 {
parentDS, _ := pmc.RunPMCExpGetParentDS(cfgName, true)
clockClass = fbprotocol.ClockClass(parentDS.GrandmasterClockClass)
}
utils.EmitClockClass(c, PTP4lProcessName, cfgName, clockClass)
utils.EmitClockClass(c, PTP4lProcessName, cfgName, e.clockClass)
}
}
}
Expand Down
58 changes: 50 additions & 8 deletions pkg/event/event_internal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"testing"
"time"

"github.com/k8snetworkplumbingwg/linuxptp-daemon/pkg/utils"
"github.com/stretchr/testify/assert"
)

Expand Down Expand Up @@ -274,6 +275,7 @@ func TestGetLargestOffset(t *testing.T) {
cfgName string
data map[string][]*Data
clkSyncState map[string]*clockSyncState
fillWindow bool
expected int64
}{
{
Expand Down Expand Up @@ -306,6 +308,24 @@ func TestGetLargestOffset(t *testing.T) {
},
expected: FaultyPhaseOffset,
},
{
name: "Window not full - should return FaultyPhaseOffset",
cfgName: "test",
data: map[string][]*Data{
"test": {
{ProcessName: DPLL, Details: []*DataDetails{
{IFace: "eth0", Offset: 15, time: recentTime},
{IFace: "eth1", Offset: 5, time: recentTime},
}},
},
},
clkSyncState: map[string]*clockSyncState{
"test": {
leadingIFace: "eth99",
},
},
expected: FaultyPhaseOffset,
},
{
name: "Single offset value",
cfgName: "test",
Expand All @@ -321,7 +341,8 @@ func TestGetLargestOffset(t *testing.T) {
leadingIFace: "eth99",
},
},
expected: 100,
fillWindow: true,
expected: 100,
},
{
name: "Multiple offsets - largest positive",
Expand All @@ -340,7 +361,8 @@ func TestGetLargestOffset(t *testing.T) {
leadingIFace: "eth99",
},
},
expected: 25,
fillWindow: true,
expected: 25,
},
{
name: "Multiple offsets - largest negative",
Expand All @@ -359,7 +381,8 @@ func TestGetLargestOffset(t *testing.T) {
leadingIFace: "eth99",
},
},
expected: -30,
fillWindow: true,
expected: -30,
},
{
name: "Mixed positive and negative - largest absolute value",
Expand All @@ -378,7 +401,8 @@ func TestGetLargestOffset(t *testing.T) {
leadingIFace: "eth99",
},
},
expected: -25,
fillWindow: true,
expected: -25,
},
{
name: "Stale data filtered out",
Expand All @@ -397,7 +421,8 @@ func TestGetLargestOffset(t *testing.T) {
leadingIFace: "eth99",
},
},
expected: 20,
fillWindow: true,
expected: 20,
},
{
name: "All data stale - should return FaultyPhaseOffset",
Expand Down Expand Up @@ -439,7 +464,8 @@ func TestGetLargestOffset(t *testing.T) {
leadingIFace: "eth99",
},
},
expected: -40,
fillWindow: true,
expected: -40,
},
{
name: "Zero offset values",
Expand All @@ -457,7 +483,8 @@ func TestGetLargestOffset(t *testing.T) {
leadingIFace: "eth99",
},
},
expected: 0,
fillWindow: true,
expected: 0,
},
{
name: "Mix of zero and non-zero offsets",
Expand All @@ -476,12 +503,27 @@ func TestGetLargestOffset(t *testing.T) {
leadingIFace: "eth99",
},
},
expected: 10,
fillWindow: true,
expected: 10,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.fillWindow {
for _, processData := range tt.data {
for _, d := range processData {
if len(d.Details) == 0 {
continue
}
d.window = *utils.NewWindow(WindowSize)
for i := 0; i < WindowSize; i++ {
offset := d.Details[i%len(d.Details)].Offset
d.window.Insert(float64(offset))
}
}
}
}
e := EventHandler{data: tt.data, clkSyncState: tt.clkSyncState}
result := e.getLargestOffset(tt.cfgName)
assert.Equal(t, tt.expected, result)
Expand Down
22 changes: 19 additions & 3 deletions pkg/event/event_tbc.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,9 @@ func (e *EventHandler) updateBCState(event EventChannel, c net.Conn) clockSyncSt
e.clkSyncState[cfgName].state)
return *e.clkSyncState[cfgName]
}

isTTSC := (e.LeadingClockData.clockID != "" && e.LeadingClockData.controlledPortsConfig == "")

glog.Info("current BC state: ", e.clkSyncState[cfgName].state)
switch e.clkSyncState[cfgName].state {
case PTP_NOTSET, PTP_FREERUN:
Expand Down Expand Up @@ -156,7 +159,9 @@ func (e *EventHandler) updateBCState(event EventChannel, c net.Conn) clockSyncSt
e.LeadingClockData.downstreamParentDataSet = e.LeadingClockData.upstreamParentDataSet
updateDownstreamData = true
}
if e.clkSyncState[cfgName].clockClass != fbprotocol.ClockClass(e.LeadingClockData.upstreamParentDataSet.GrandmasterClockClass) {
if e.LeadingClockData.upstreamParentDataSet.GrandmasterClockClass == uint8(protocol.ClockClassFreerun) {
updateDownstreamData = false // Don't propagate uptream free run and instead let future call move to holdover/freerun
} else if e.clkSyncState[cfgName].clockClass != fbprotocol.ClockClass(e.LeadingClockData.upstreamParentDataSet.GrandmasterClockClass) && !isTTSC {
e.clkSyncState[cfgName].clockClass = fbprotocol.ClockClass(e.LeadingClockData.upstreamParentDataSet.GrandmasterClockClass)
e.clkSyncState[cfgName].clockAccuracy = fbprotocol.ClockAccuracy(e.LeadingClockData.upstreamParentDataSet.GrandmasterClockAccuracy)
}
Expand Down Expand Up @@ -214,8 +219,15 @@ func (e *EventHandler) updateBCState(event EventChannel, c net.Conn) clockSyncSt
e.clkSyncState[cfgName].clockOffset = e.getLargestOffset(cfgName)
}

if updateDownstreamData {
go e.updateDownstreamData(cfgName, c)
if isTTSC && e.clkSyncState[cfgName].clockClass != fbprotocol.ClockClassSlaveOnly {
e.clkSyncState[cfgName].clockClass = fbprotocol.ClockClassSlaveOnly
}
if updateDownstreamData && e.clkSyncState[cfgName].clockClass != protocol.ClockClassUninitialized {
if isTTSC {
e.announceClockClass(e.clkSyncState[cfgName].clockClass, e.clkSyncState[cfgName].clockAccuracy, cfgName, c)
} else {
go e.updateDownstreamData(cfgName, c)
}
}
// this will reduce log noise and prints 1 per sec
logTime := time.Now().Unix()
Expand Down Expand Up @@ -427,6 +439,10 @@ func (e *EventHandler) getLargestOffset(cfgName string) int64 {
if dd.time < staleTime {
continue
}
if !d.window.IsFull() {
glog.Info("Largest offset ", FaultyPhaseOffset)
return FaultyPhaseOffset
}
if worstOffset == FaultyPhaseOffset {
if dd.IFace == e.clkSyncState[cfgName].leadingIFace {
worstOffset = int64(d.window.Mean())
Expand Down