Skip to content

Commit

Permalink
OCPBUGS-29683: add DPLL phase offset
Browse files Browse the repository at this point in the history
Add DPLL pin notification parser and handle pin notifications.
Distinguish between pin notifications and device notifications.
Update DPLL phase offset if included for the pin belonging to the
DPLL instance.

Signed-off-by: Vitaly Grinberg <[email protected]>
  • Loading branch information
Vitaly Grinberg authored and josephdrichard committed Jun 15, 2024
1 parent e8febe5 commit 00ea19d
Show file tree
Hide file tree
Showing 6 changed files with 532 additions and 56 deletions.
20 changes: 20 additions & 0 deletions addons/intel/e810.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"fmt"
"os"
"os/exec"
"reflect"
"strconv"
"strings"

Expand All @@ -20,6 +21,7 @@ type E810Opts struct {
UblxCmds []E810UblxCmds `json:"ublxCmds"`
DevicePins map[string]map[string]string `json:"pins"`
DpllSettings map[string]uint64 `json:"settings"`
PhaseOffsetPins map[string]map[string]string `json:"phaseOffsetPins"`
}

type E810UblxCmds struct {
Expand Down Expand Up @@ -117,6 +119,24 @@ func OnPTPConfigChangeE810(data *interface{}, nodeProfile *ptpv1.PtpProfile) err
(*nodeProfile).PtpSettings[k] = strconv.FormatUint(v, 10)
}
}
for iface, properties := range e810Opts.PhaseOffsetPins {
ifaceFound := false
for dev := range e810Opts.DevicePins {
if strings.Compare(iface, dev) == 0 {
ifaceFound = true
break
}
}
if !ifaceFound {
glog.Errorf("e810 phase offset pin filter initialization failed: interface %s not found among %v",
iface, reflect.ValueOf(e810Opts.DevicePins).MapKeys())
break
}
for pinProperty, value := range properties {
key := strings.Join([]string{iface, "phaseOffsetFilter", strconv.FormatUint(getClockIdE810(iface), 10), pinProperty}, ".")
(*nodeProfile).PtpSettings[key] = value
}
}
}
}
return nil
Expand Down
33 changes: 31 additions & 2 deletions pkg/daemon/daemon/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,9 @@ func (dn *Daemon) applyNodePtpProfile(runID int, nodeProfile *ptpv1.PtpProfile)
output.profile_name = *nodeProfile.Name

if nodeProfile.Interface != nil && *nodeProfile.Interface != "" {
output.sections = append([]ptp4lConfSection{{options: map[string]string{}, sectionName: fmt.Sprintf("[%s]", *nodeProfile.Interface)}}, output.sections...)
output.sections = append([]ptp4lConfSection{{
options: map[string]string{},
sectionName: fmt.Sprintf("[%s]", *nodeProfile.Interface)}}, output.sections...)
} else {
iface := string("")
nodeProfile.Interface = &iface
Expand Down Expand Up @@ -493,10 +495,20 @@ func (dn *Daemon) applyNodePtpProfile(runID int, nodeProfile *ptpv1.PtpProfile)
var localHoldoverTimeout uint64 = dpll.LocalHoldoverTimeout
var maxInSpecOffset uint64 = dpll.MaxInSpecOffset
var clockId uint64
phaseOffsetPinFilter := map[string]string{}
for _, iface := range dprocess.ifaces {
var eventSource []event.EventSource
if iface.Source == event.GNSS || iface.Source == event.PPS {
glog.Info("Init dpll: ptp settings ", (*nodeProfile).PtpSettings)
for k, v := range (*nodeProfile).PtpSettings {
glog.Info("Init dpll: ptp kv ", k, " ", v)
if strings.Contains(k, strings.Join([]string{iface.Name, "phaseOffset"}, ".")) {
filterKey := strings.Split(k, ".")
property := filterKey[len(filterKey)-1]
phaseOffsetPinFilter[property] = v
glog.Infof("dpll phase offset filter property: %s[%s]=%s", iface.Name, property, v)
continue
}
i, err := strconv.ParseUint(v, 10, 64)
if err != nil {
continue
Expand All @@ -521,7 +533,7 @@ func (dn *Daemon) applyNodePtpProfile(runID int, nodeProfile *ptpv1.PtpProfile)
}
// pass array of ifaces which has source + clockId -
dpllDaemon := dpll.NewDpll(clockId, localMaxHoldoverOffSet, localHoldoverTimeout,
maxInSpecOffset, iface.Name, eventSource, dpll.NONE)
maxInSpecOffset, iface.Name, eventSource, dpll.NONE, dn.GetPhaseOffsetPinFilter(nodeProfile))
dpllDaemon.CmdInit()
dprocess.depProcess = append(dprocess.depProcess, dpllDaemon)
}
Expand All @@ -540,6 +552,23 @@ func (dn *Daemon) applyNodePtpProfile(runID int, nodeProfile *ptpv1.PtpProfile)
return nil
}

func (dn *Daemon) GetPhaseOffsetPinFilter(nodeProfile *ptpv1.PtpProfile) map[string]map[string]string {
phaseOffsetPinFilter := map[string]map[string]string{}
for k, v := range (*nodeProfile).PtpSettings {
if strings.Contains(k, "phaseOffsetFilter") {
filterKey := strings.Split(k, ".")
property := filterKey[len(filterKey)-1]
clockIdStr := filterKey[len(filterKey)-2]
if len(phaseOffsetPinFilter[clockIdStr]) == 0 {
phaseOffsetPinFilter[clockIdStr] = map[string]string{}
}
phaseOffsetPinFilter[clockIdStr][property] = v
continue
}
}
return phaseOffsetPinFilter
}

func (dn *Daemon) HandlePmcTicker() {
for _, p := range dn.processManager.process {
if p.name == ptp4lProcessName {
Expand Down
175 changes: 173 additions & 2 deletions pkg/daemon/dpll-netlink/dpll-uapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,14 @@

package dpll_netlink

import "fmt"
import (
"encoding/json"
"fmt"
)

const DPLL_MCGRP_MONITOR = "monitor"
const DPLL_PHASE_OFFSET_DIVIDER = 1000
const DPLL_TEMP_DIVIDER = 1000
const (
DPLL_A_TYPES = iota
DPLL_A_ID
Expand All @@ -17,10 +22,42 @@ const (
DPLL_A_LOCK_STATUS
DPLL_A_TEMP
DPLL_A_TYPE

__DPLL_A_MAX
DPLL_A_MAX = __DPLL_A_MAX - 1
)

const (
DPLL_A_PIN_TYPES = iota

DPLL_A_PIN_ID
DPLL_A_PIN_PARENT_ID
DPLL_A_PIN_MODULE_NAME
DPLL_A_PIN_PAD
DPLL_A_PIN_CLOCK_ID
DPLL_A_PIN_BOARD_LABEL
DPLL_A_PIN_PANEL_LABEL
DPLL_A_PIN_PACKAGE_LABEL
DPLL_A_PIN_TYPE
DPLL_A_PIN_DIRECTION
DPLL_A_PIN_FREQUENCY
DPLL_A_PIN_FREQUENCY_SUPPORTED
DPLL_A_PIN_FREQUENCY_MIN
DPLL_A_PIN_FREQUENCY_MAX
DPLL_A_PIN_PRIO
DPLL_A_PIN_STATE
DPLL_A_PIN_CAPABILITIES
DPLL_A_PIN_PARENT_DEVICE
DPLL_A_PIN_PARENT_PIN
DPLL_A_PIN_PHASE_ADJUST_MIN
DPLL_A_PIN_PHASE_ADJUST_MAX
DPLL_A_PIN_PHASE_ADJUST
DPLL_A_PIN_PHASE_OFFSET
DPLL_A_PIN_FRACTIONAL_FREQUENCY_OFFSET

__DPLL_A_PIN_MAX
DPLL_A_PIN_MAX = __DPLL_A_PIN_MAX - 1
)
const (
DPLL_CMDS = iota
DPLL_CMD_DEVICE_ID_GET
Expand All @@ -29,6 +66,12 @@ const (
DPLL_CMD_DEVICE_CREATE_NTF
DPLL_CMD_DEVICE_DELETE_NTF
DPLL_CMD_DEVICE_CHANGE_NTF
DPLL_CMD_PIN_ID_GET
DPLL_CMD_PIN_GET
DPLL_CMD_PIN_SET
DPLL_CMD_PIN_CREATE_NTF
DPLL_CMD_PIN_DELETE_NTF
DPLL_CMD_PIN_CHANGE_NTF

__DPLL_CMD_MAX
DPLL_CMD_MAX = (__DPLL_CMD_MAX - 1)
Expand Down Expand Up @@ -94,9 +137,137 @@ func GetDpllStatusHR(reply *DoDeviceGetReply) DpllStatusHR {
Id: reply.Id,
ModuleName: reply.ModuleName,
Mode: GetMode(reply.Mode),
// TODO: ModeSupported
LockStatus: GetLockStatus(reply.LockStatus),
ClockId: fmt.Sprintf("0x%x", reply.ClockId),
Type: GetDpllType(reply.Type),
}
}

// DoPinGetReply is used with the DoPinGet method.
type DoPinGetReplyHR struct {
Id uint32 `json:"id"`
ClockId uint64 `json:"clockId"`
BoardLabel string `json:"boardLabel"`
PanelLabel string `json:"panelLabel"`
PackageLabel string `json:"packageLabel"`
Type string `json:"type"`
Frequency uint64 `json:"frequency"`
FrequencySupported FrequencyRange `json:"frequencySupported"`
Capabilities string `json:"capabilities"`
ParentDevice PinParentDeviceHR `json:"pinParentDevice"`
ParentPin PinParentPinHR `json:"pinParentPin"`
PhaseAdjustMin int32 `json:"phaseAdjustMin"`
PhaseAdjustMax int32 `json:"phaseAdjustMax"`
PhaseAdjust int32 `json:"phaseAdjust"`
FractionalFrequencyOffset int `json:"fractionalFrequencyOffset"`
ModuleName string `json:"moduleName"`
}

// PinParentDevice contains nested netlink attributes.
type PinParentDeviceHR struct {
ParentId uint32 `json:"parentId"`
Direction string `json:"direction"`
Prio uint32 `json:"prio"`
State string `json:"state"`
PhaseOffset int64 `json:"phaseOffset"`
}

// PinParentPin contains nested netlink attributes.
type PinParentPinHR struct {
ParentId uint32 `json:"parentId"`
State string `json:"parentState"`
}

// GetPinState returns DPLL pin state as a string
func GetPinState(s uint32) string {
stateMap := map[int]string{
1: "connected",
2: "disconnected",
3: "selectable",
}
r, found := stateMap[int(s)]
if found {
return r
}
return ""
}

// GetPinType returns DPLL pin type as a string
func GetPinType(tp uint32) string {
typeMap := map[int]string{
1: "mux",
2: "ext",
3: "synce-eth-port",
4: "int-oscillator",
5: "gnss",
}
typ, found := typeMap[int(tp)]
if found {
return typ
}
return ""
}

// GetPinDirection returns DPLL pin direction as a string
func GetPinDirection(d uint32) string {
directionMap := map[int]string{
1: "input",
2: "output",
}
dir, found := directionMap[int(d)]
if found {
return dir
}
return ""
}

// GetPinCapabilities returns DPLL pin capabilities as a csv
func GetPinCapabilities(c uint32) string {
cMap := map[int]string{
0: "",
1: "direction-can-change",
2: "priority-can-change",
3: "direction-can-change,priority-can-change",
4: "state-can-change",
5: "state-can-change,direction-can-change",
6: "state-can-change,priority-can-change",
7: "state-can-change,direction-can-change,priority-can-change",
}
cap, found := cMap[int(c)]
if found {
return cap
}
return ""
}

// GetPinInfoHR returns human-readable pin status
func GetPinInfoHR(reply *DoPinGetReply) ([]byte, error) {
hr := DoPinGetReplyHR{
Id: reply.Id,
ClockId: reply.ClockId,
BoardLabel: reply.BoardLabel,
PanelLabel: reply.PanelLabel,
PackageLabel: reply.PackageLabel,
Type: GetPinType(reply.Type),
Frequency: reply.Frequency,
FrequencySupported: reply.FrequencySupported,
Capabilities: GetPinCapabilities(reply.Capabilities),
ParentDevice: PinParentDeviceHR{
ParentId: reply.ParentDevice.ParentId,
Direction: GetPinDirection(reply.ParentDevice.Direction),
Prio: reply.ParentDevice.Prio,
State: GetPinState(reply.ParentDevice.State),
PhaseOffset: reply.ParentDevice.PhaseOffset,
},
ParentPin: PinParentPinHR{
ParentId: reply.ParentPin.ParentId,
State: GetPinState(reply.ParentPin.State),
},
PhaseAdjustMin: reply.PhaseAdjustMin,
PhaseAdjustMax: reply.PhaseAdjustMax,
PhaseAdjust: reply.PhaseAdjust,
FractionalFrequencyOffset: reply.FractionalFrequencyOffset,
ModuleName: reply.ModuleName,
}
return json.Marshal(hr)
}
Loading

0 comments on commit 00ea19d

Please sign in to comment.