From d73caa70342d63ca9d08e06eb6f158231d77464b Mon Sep 17 00:00:00 2001 From: Vitaly Grinberg Date: Thu, 2 Jan 2025 11:52:35 +0200 Subject: [PATCH] OCPBUGS-45308: Fix gm states 4.14 (#399) * 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 * fix backport mistake Fixes backport mistake that caused ptpStateChange event never to be sent --------- Signed-off-by: Vitaly Grinberg --- plugins/ptp_operator/metrics/logparser.go | 26 +++++++-- .../ptp_operator/metrics/logparser_test.go | 53 +++++++++++++++++++ plugins/ptp_operator/metrics/metrics_test.go | 1 + 3 files changed, 75 insertions(+), 5 deletions(-) diff --git a/plugins/ptp_operator/metrics/logparser.go b/plugins/ptp_operator/metrics/logparser.go index d5ed66e1..9e2043af 100644 --- a/plugins/ptp_operator/metrics/logparser.go +++ b/plugins/ptp_operator/metrics/logparser.go @@ -394,16 +394,32 @@ func (p *PTPEventManager) ParseGMLogs(processName, configName, output string, fi SyncState.With(map[string]string{"process": processName, "node": ptpNodeName, "iface": alias}).Set(GetSyncStateID(syncState)) // status metrics ptpStats[masterType].SetPtpDependentEventState(clockState, ptpStats.HasMetrics(processName), ptpStats.HasMetricHelp(processName)) - ptpStats[masterType].SetLastSyncState(clockState.State) ptpStats[masterType].SetAlias(alias) // 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) - ptpStats[masterType].SetLastSyncState(clockState.State) - 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 diff --git a/plugins/ptp_operator/metrics/logparser_test.go b/plugins/ptp_operator/metrics/logparser_test.go index de0ac194..37672ac4 100644 --- a/plugins/ptp_operator/metrics/logparser_test.go +++ b/plugins/ptp_operator/metrics/logparser_test.go @@ -4,6 +4,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" @@ -145,3 +146,55 @@ func TestPTPEventManager_ParseDPLLLogs(t *testing.T) { assert.Equal(t, tt.expectedState, lastState) } } + +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) + } +} diff --git a/plugins/ptp_operator/metrics/metrics_test.go b/plugins/ptp_operator/metrics/metrics_test.go index 52058992..c0f528e1 100644 --- a/plugins/ptp_operator/metrics/metrics_test.go +++ b/plugins/ptp_operator/metrics/metrics_test.go @@ -280,6 +280,7 @@ var testCases = []TestCase{ expectedNmeaStatus: SKIP, expectedPpsStatus: SKIP, expectedClockClassMetrics: SKIP, + expectedEvent: ptp.PtpStateChange, }, { log: "gnss[1000000500]:[ts2phc.0.config] ens2f1 gnss_status 3 offset 5 s2",