Skip to content

Commit

Permalink
OCPBUGS-45866 : Fix GM State Transition Event Generation (#380)
Browse files Browse the repository at this point in the history
* Fix GM State Transition Event Generation

This is a cherrypick from #379
Previously, when the Grandmaster (GM) transitioned to the HOLDOVER state, an event was generated with the HOLDOVER status. However, subsequent state transitions from HOLDOVER to FREERUN or LOCKED did not trigger any events.
This bug fix ensures that events are now correctly generated for transitions from HOLDOVER to FREERUN or LOCKED states.

Signed-off-by: Vitaly Grinberg <[email protected]>

* add unit test for ParseGmLogs

Signed-off-by: Vitaly Grinberg <[email protected]>

---------

Signed-off-by: Vitaly Grinberg <[email protected]>
  • Loading branch information
vitus133 authored Dec 18, 2024
1 parent fdc29b1 commit 2a46db4
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 3 deletions.
24 changes: 21 additions & 3 deletions plugins/ptp_operator/metrics/logparser.go
Original file line number Diff line number Diff line change
Expand Up @@ -381,10 +381,28 @@ func (p *PTPEventManager) ParseGMLogs(processName, configName, output string, fi

// If GM is locked/Freerun/Holdover then ptp state change event
masterResource := fmt.Sprintf("%s/%s", alias, MasterClockType)
lastClockState := ptpStats[masterType].LastSyncState()

// When GM is enabled there is only event happening at GM level for now
p.GenPTPEvent(processName, ptpStats[masterType], masterResource, 0, clockState.State, ptp.PtpStateChange)
UpdateSyncStateMetrics(processName, alias, ptpStats[masterType].LastSyncState())
// When GM is enabled, there is only one event happening at the GM level for now, so it is not being sent to the state decision routine.
// LOCKED -->FREERUN
//LOCKED->HOLDOVER
/// HOLDOVER-->FREERUN
// HOLDOVER-->LOCKED

_, phaseOffset, _, err := ptpStats[types.IFace(iface)].GetDependsOnValueState(dpllProcessName, pointer.String(iface), phaseStatus)
if err != nil {
log.Errorf("error parsing phase offset %s", err.Error())
}
ptpStats[masterType].SetLastOffset(int64(phaseOffset))
lastOffset := ptpStats[masterType].LastOffset()

if clockState.State != lastClockState { // publish directly here
log.Infof("%s sync state %s, last ptp state is : %s", masterResource, clockState.State, lastClockState)
p.PublishEvent(clockState.State, lastOffset, masterResource, ptp.PtpStateChange)
ptpStats[masterType].SetLastSyncState(clockState.State)
UpdateSyncStateMetrics(processName, alias, ptpStats[masterType].LastSyncState())
UpdatePTPOffsetMetrics(processName, processName, alias, float64(lastOffset))
}
}

// ParseDPLLLogs ... parse logs for various events
Expand Down
53 changes: 53 additions & 0 deletions plugins/ptp_operator/metrics/logparser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"strings"
"testing"

"github.com/redhat-cne/cloud-event-proxy/plugins/ptp_operator/event"
"github.com/redhat-cne/cloud-event-proxy/plugins/ptp_operator/ptp4lconf"

"github.com/redhat-cne/cloud-event-proxy/plugins/ptp_operator/metrics"
Expand Down Expand Up @@ -264,3 +265,55 @@ func TestParseSyncELogs(t *testing.T) {
})
}
}

func Test_ParseGmLogs(t *testing.T) {
var ptpEventManager *metrics.PTPEventManager
tc := []testCase{
{
processName: "GM",
output: "GM 1689014431 ts2phc.0.config ens2f1 T-GM-STATUS s0",
expectedState: ptp.FREERUN,
interfaceName: "ens2f1",
},
{
processName: "GM",
output: "GM 1689014431 ts2phc.0.config ens2f1 T-GM-STATUS s1",
expectedState: ptp.HOLDOVER,
interfaceName: "ens2f1",
},
{
processName: "GM",
output: "GM 1689014431 ts2phc.0.config ens2f1 T-GM-STATUS s2",
expectedState: ptp.LOCKED,
interfaceName: "ens2f1",
},
}
ptpEventManager = metrics.NewPTPEventManager("", initPubSubTypes(), "tetsnode", nil)
ptpEventManager.MockTest(true)
ptpEventManager.Stats[types.ConfigName(ptp4lConfig.Name)] = make(stats.PTPStats)
ptpStats := ptpEventManager.GetStats(types.ConfigName(configName))
replacer := strings.NewReplacer("[", " ", "]", " ", ":", " ")
for _, tt := range tc {
output := replacer.Replace(tt.output)
fields := strings.Fields(output)
ptpStats[types.IFace(tt.interfaceName)] = &stats.Stats{}
ptpStats[types.IFace(tt.interfaceName)].SetPtpDependentEventState(
event.ClockState{
State: metrics.GetSyncState("s2"),
Offset: pointer.Float64(0),
IFace: &tt.interfaceName,
Process: "dpll",
ClockSource: event.DPLL,
Value: map[string]int64{"frequency_status": 2, "phase_status": int64(0), "pps_status": int64(2)},
Metric: map[string]*event.PMetric{},
NodeName: "tetsnode",
HelpText: map[string]string{"phase_status": "-1=UNKNOWN, 0=INVALID, 1=FREERUN, 2=LOCKED, 3=LOCKED_HO_ACQ, 4=HOLDOVER", "frequency_status": "-1=UNKNOWN, 0=INVALID, 1=FREERUN, 2=LOCKED, 3=LOCKED_HO_ACQ, 4=HOLDOVER", "pps_status": "0=UNAVAILABLE, 1=AVAILABLE"},
}, ptpStats.HasMetrics("dpll"), ptpStats.HasMetricHelp("dpll"))
masterType := types.IFace(metrics.MasterClockType)
ptpStats[masterType] = &stats.Stats{}
ptpEventManager.ParseGMLogs(tt.processName, configName, output, fields, ptpStats)
lastState, errState := ptpStats[masterType].GetStateState(tt.processName, pointer.String(tt.interfaceName))
assert.Equal(t, errState, nil)
assert.Equal(t, tt.expectedState, lastState)
}
}

0 comments on commit 2a46db4

Please sign in to comment.