Skip to content

Commit

Permalink
Merge pull request #341 from vitus133/release-4.16-fix-gm-np-settings
Browse files Browse the repository at this point in the history
[release-4.16] OCPBUGS-37043: prevent writing uninitialized TimePropertiesDS
  • Loading branch information
openshift-merge-bot[bot] authored Jul 29, 2024
2 parents 7130727 + cf20036 commit 382c824
Show file tree
Hide file tree
Showing 7 changed files with 182 additions and 63 deletions.
1 change: 0 additions & 1 deletion cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,6 @@ func main() {
&refreshNodePtpDevice,
closeProcessManager,
cp.pmcPollInterval,
lm,
).Run()

tickerPull := time.NewTicker(time.Second * time.Duration(cp.updateInterval))
Expand Down
8 changes: 1 addition & 7 deletions pkg/daemon/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import (

"github.com/openshift/linuxptp-daemon/pkg/config"
"github.com/openshift/linuxptp-daemon/pkg/dpll"
"github.com/openshift/linuxptp-daemon/pkg/leap"

"github.com/openshift/linuxptp-daemon/pkg/event"
ptpnetwork "github.com/openshift/linuxptp-daemon/pkg/network"
Expand Down Expand Up @@ -172,8 +171,6 @@ type Daemon struct {

// Allow vendors to include plugins
pluginManager PluginManager

leapManager *leap.LeapManager
}

// New LinuxPTP is called by daemon to generate new linuxptp instance
Expand All @@ -189,7 +186,6 @@ func New(
refreshNodePtpDevice *bool,
closeManager chan bool,
pmcPollInterval int,
leapManager *leap.LeapManager,
) *Daemon {
if !stdoutToSocket {
RegisterMetrics(nodeName)
Expand All @@ -213,8 +209,7 @@ func New(
eventChannel: eventChannel,
ptpEventHandler: event.Init(nodeName, stdoutToSocket, eventSocket, eventChannel, closeManager, Offset, ClockState, ClockClassMetrics),
},
leapManager: leapManager,
stopCh: stopCh,
stopCh: stopCh,
}
}

Expand Down Expand Up @@ -560,7 +555,6 @@ func (dn *Daemon) applyNodePtpProfile(runID int, nodeProfile *ptpv1.PtpProfile)
gmInterface: gmInterface,
stopped: false,
messageTag: messageTag,
leapManager: dn.leapManager,
ublxTool: nil,
}
gpsDaemon.CmdInit()
Expand Down
15 changes: 7 additions & 8 deletions pkg/daemon/gpsd.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ type GPSD struct {
subscriber *GPSDSubscriber
monitorCtx context.Context
monitorCancel context.CancelFunc
leapManager *leap.LeapManager
}

// GPSDSubscriber ... event subscriber
Expand Down Expand Up @@ -278,13 +277,6 @@ retry:
} // loop ends
g.offset = nOffset
g.sourceLost = false
if timeLs != nil {
select {
case g.leapManager.UbloxLsInd <- *timeLs:
case <-time.After(100 * time.Millisecond):
glog.Infof("failied to send leap event updates")
}
}

switch nStatus >= 3 {
case true:
Expand Down Expand Up @@ -315,6 +307,13 @@ retry:
default:
glog.Error("failed to send gnss terminated event to eventHandler")
}
if timeLs != nil {
select {
case leap.LeapMgr.UbloxLsInd <- *timeLs:
case <-time.After(100 * time.Millisecond):
glog.Infof("failied to send Leap event updates")
}
}
case <-g.monitorCtx.Done():
doneFn()
return
Expand Down
19 changes: 7 additions & 12 deletions pkg/event/event.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"sync"
"time"

"github.com/openshift/linuxptp-daemon/pkg/leap"
"github.com/openshift/linuxptp-daemon/pkg/pmc"
"github.com/openshift/linuxptp-daemon/pkg/protocol"

Expand Down Expand Up @@ -689,15 +690,17 @@ func (e *EventHandler) updateCLockClass(cfgName string, clkClass fbprotocol.Cloc
}
switch clockType {
case GM:
g.TimePropertiesDS.TimeTraceable = true
g.TimePropertiesDS.PtpTimescale = true
g.TimePropertiesDS.FrequencyTraceable = true
g.TimePropertiesDS.CurrentUtcOffsetValid = true
g.TimePropertiesDS.CurrentUtcOffset = int32(leap.GetUtcOffset())
switch clkClass {
case fbprotocol.ClockClass6: // T-GM connected to a PRTC in locked mode (e.g., PRTC traceable to GNSS)
// update only when ClockClass is changed
if g.ClockQuality.ClockClass != fbprotocol.ClockClass6 {
g.ClockQuality.ClockClass = fbprotocol.ClockClass6
g.ClockQuality.ClockAccuracy = fbprotocol.ClockAccuracyNanosecond100
g.TimePropertiesDS.TimeTraceable = true
g.TimePropertiesDS.FrequencyTraceable = true
g.TimePropertiesDS.CurrentUtcOffsetValid = true
g.TimePropertiesDS.TimeSource = fbprotocol.TimeSourceGNSS
// T-REC-G.8275.1-202211-I section 6.3.5
g.ClockQuality.OffsetScaledLogVariance = 0x4e5d
Expand All @@ -708,9 +711,6 @@ func (e *EventHandler) updateCLockClass(cfgName string, clkClass fbprotocol.Cloc
g.ClockQuality.ClockClass = protocol.ClockClassOutOfSpec
g.ClockQuality.ClockAccuracy = fbprotocol.ClockAccuracyUnknown
g.TimePropertiesDS.TimeSource = fbprotocol.TimeSourceGNSS
g.TimePropertiesDS.TimeTraceable = false
g.TimePropertiesDS.FrequencyTraceable = false
g.TimePropertiesDS.CurrentUtcOffsetValid = false
// T-REC-G.8275.1-202211-I section 6.3.5
g.ClockQuality.OffsetScaledLogVariance = 0xffff
err = gmSetterFn(cfgName, g)
Expand All @@ -720,9 +720,6 @@ func (e *EventHandler) updateCLockClass(cfgName string, clkClass fbprotocol.Cloc
g.ClockQuality.ClockClass = fbprotocol.ClockClass7
g.ClockQuality.ClockAccuracy = fbprotocol.ClockAccuracyUnknown
g.TimePropertiesDS.TimeSource = fbprotocol.TimeSourceGNSS
g.TimePropertiesDS.TimeTraceable = true
g.TimePropertiesDS.FrequencyTraceable = true
g.TimePropertiesDS.CurrentUtcOffsetValid = true
// T-REC-G.8275.1-202211-I section 6.3.5
g.ClockQuality.OffsetScaledLogVariance = 0xffff
err = gmSetterFn(cfgName, g)
Expand All @@ -732,9 +729,7 @@ func (e *EventHandler) updateCLockClass(cfgName string, clkClass fbprotocol.Cloc
g.ClockQuality.ClockClass = protocol.ClockClassFreerun
g.ClockQuality.ClockAccuracy = fbprotocol.ClockAccuracyUnknown
g.TimePropertiesDS.TimeSource = fbprotocol.TimeSourceGNSS
g.TimePropertiesDS.TimeTraceable = false
g.TimePropertiesDS.FrequencyTraceable = false
g.TimePropertiesDS.CurrentUtcOffsetValid = false
g.TimePropertiesDS.TimeSource = fbprotocol.TimeSourceNTP
// T-REC-G.8275.1-202211-I section 6.3.5
g.ClockQuality.OffsetScaledLogVariance = 0xffff
err = gmSetterFn(cfgName, g)
Expand Down
32 changes: 29 additions & 3 deletions pkg/event/event_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,22 @@ package event_test

import (
"bufio"
fbprotocol "github.com/facebook/time/ptp/protocol"
"github.com/openshift/linuxptp-daemon/pkg/protocol"
"github.com/stretchr/testify/assert"
"log"
"net"
"os"
"strings"
"testing"
"time"

fbprotocol "github.com/facebook/time/ptp/protocol"
"github.com/golang/glog"
"github.com/openshift/linuxptp-daemon/pkg/event"
"github.com/openshift/linuxptp-daemon/pkg/leap"
"github.com/openshift/linuxptp-daemon/pkg/protocol"
"github.com/stretchr/testify/assert"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
fake "k8s.io/client-go/kubernetes/fake"
)

var (
Expand Down Expand Up @@ -203,6 +207,7 @@ func TestEventHandler_ProcessEvents(t *testing.T) {
eventManager := event.Init("node", true, "/tmp/go.sock", eChannel, closeChn, nil, nil, nil)
eventManager.MockEnable()
go eventManager.ProcessEvents()
assert.NoError(t, mockLeap())
time.Sleep(1 * time.Second)
for _, test := range tests {
select {
Expand Down Expand Up @@ -336,3 +341,24 @@ func sendEvents(cfgName string, processName event.EventSource, state event.PTPSt
Reset: false,
}
}

func mockLeap() error {
cm := &v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{Namespace: "openshift-ptp", Name: "leap-configmap"},
Data: map[string]string{
"test-node-name": `# Do not edit
# This file is generated automatically by linuxptp-daemon
#$ 3927775672
#@ 4291747200
3692217600 37 # 1 Jan 2017`,
},
}
os.Setenv("NODE_NAME", "test-node-name")
client := fake.NewSimpleClientset(cm)
lm, err := leap.New(client, "openshift-ptp")
if err != nil {
return err
}
go lm.Run()
return nil
}
107 changes: 75 additions & 32 deletions pkg/leap/leap-file.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"path/filepath"
"strconv"
"strings"
"sync"
"time"

"github.com/golang/glog"
Expand Down Expand Up @@ -47,6 +48,9 @@ type LeapManager struct {
// Default leap file path and name
leapFilePath string
leapFileName string
// UTC offset and its validity time
utcOffset int
utcOffsetTime time.Time
}

type LeapEvent struct {
Expand All @@ -61,21 +65,77 @@ type LeapFile struct {
Hash string `json:"hash"`
}

func New(kubeclient *kubernetes.Clientset, namespace string) (*LeapManager, error) {
lm := &LeapManager{
UbloxLsInd: make(chan ublox.TimeLs, 2),
Close: make(chan bool),
client: kubeclient,
namespace: namespace,
leapFile: LeapFile{},
leapFilePath: defaultLeapFilePath,
leapFileName: defaultLeapFileName,
var lock = &sync.Mutex{}

var LeapMgr *LeapManager

func New(kubeclient kubernetes.Interface, namespace string) (*LeapManager, error) {
if LeapMgr == nil {
lock.Lock()
defer lock.Unlock()
if LeapMgr == nil {
lm := &LeapManager{
UbloxLsInd: make(chan ublox.TimeLs, 2),
Close: make(chan bool),
client: kubeclient,
namespace: namespace,
leapFile: LeapFile{},
leapFilePath: defaultLeapFilePath,
leapFileName: defaultLeapFileName,
}
err := lm.populateLeapData()
if err != nil {
return nil, err
}
LeapMgr = lm
}
}
return LeapMgr, nil
}

func (l *LeapManager) Run() {
glog.Info("starting Leap file manager")
ticker := time.NewTicker(MaintenancePeriod)
defer ticker.Stop()
for {
select {
case v := <-l.UbloxLsInd:
l.handleLeapIndication(&v)
case <-l.Close:
LeapMgr = nil
return
case <-ticker.C:
if l.retryUpdate {
l.updateLeapConfigmap()
}
// TODO: if current time is within -12h ... +60s from leap event:
// Send PMC command
}
}
}

func GetUtcOffset() int {
if LeapMgr != nil {
if time.Now().UTC().After(LeapMgr.utcOffsetTime) {
return LeapMgr.utcOffset
} else if len(LeapMgr.leapFile.LeapEvents) > 1 {
return LeapMgr.leapFile.LeapEvents[len(LeapMgr.leapFile.LeapEvents)-2].LeapSec
}
}
err := lm.populateLeapData()
glog.Fatal("failed to get UTC offset")
return 0
}

func (l *LeapManager) setUtcOffset() error {
startTime := time.Date(1900, time.January, 1, 0, 0, 0, 0, time.UTC)
lastLeap := l.leapFile.LeapEvents[len(l.leapFile.LeapEvents)-1]
lastLeapTime, err := strconv.Atoi(lastLeap.LeapTime)
if err != nil {
return nil, err
return err
}
return lm, nil
l.utcOffsetTime = startTime.Add(time.Second * time.Duration(lastLeapTime))
l.utcOffset = lastLeap.LeapSec
return nil
}

func parseLeapFile(b []byte) (*LeapFile, error) {
Expand Down Expand Up @@ -145,7 +205,7 @@ func (l *LeapManager) populateLeapData() error {
lf, found := cm.Data[nodeName]
if !found {
glog.Info("Populate Leap data from file")
b, err := os.ReadFile(filepath.Join(defaultLeapFilePath, defaultLeapFileName))
b, err := os.ReadFile(filepath.Join(l.leapFilePath, l.leapFileName))
if err != nil {
return err
}
Expand Down Expand Up @@ -182,28 +242,10 @@ func (l *LeapManager) populateLeapData() error {
l.leapFile = *leapData
}
glog.Info("Leap file expiration is set to ", l.leapFile.ExpirationTime)
l.setUtcOffset()
return nil
}

func (l *LeapManager) Run() {
glog.Info("starting Leap file manager")
ticker := time.NewTicker(MaintenancePeriod)
for {
select {
case v := <-l.UbloxLsInd:
l.handleLeapIndication(&v)
case <-l.Close:
return
case <-ticker.C:
if l.retryUpdate {
l.updateLeapConfigmap()
}
// TODO: if current time is within -12h ... +60s from leap event:
// Send PMC command
}
}
}

// updateLeapFile updates a new leap event to the list of leap events, if provided
func (l *LeapManager) updateLeapFile(leapTime time.Time,
leapSec int, currentTime time.Time) {
Expand All @@ -222,6 +264,7 @@ func (l *LeapManager) updateLeapFile(leapTime time.Time,
}
l.leapFile.UpdateTime = fmt.Sprint(int(currentTime.Sub(startTime).Seconds()))
l.rehashLeapData()
l.setUtcOffset()
}

func (l *LeapManager) rehashLeapData() {
Expand Down
Loading

0 comments on commit 382c824

Please sign in to comment.