OpenConfig Platform Transceiver - #201
Conversation
Signed-off-by: Kanji Nakano <kanji.nakano@ntt.com>
|
/azp run |
|
Azure Pipelines successfully started running 1 pipeline(s). |
Signed-off-by: Kanji Nakano <kanji.nakano@ntt.com>
|
/azp run |
|
Azure Pipelines successfully started running 1 pipeline(s). |
|
@hdwhdw @anders-nexthop |
|
@hdwhdw @anders-nexthop Just a gentle reminder on this PR. I know you're both busy, but could you please take a look when you have a moment? This is the updated version addressing the feedback from #160 and the UMF WG review. Thanks! |
There was a problem hiding this comment.
Pull request overview
This pull request adds comprehensive OpenConfig support for platform transceiver monitoring in SONiC. It extends the existing platform app to expose transceiver information including serial numbers, connector types, vendor information, DOM (Digital Optical Monitoring) sensor data (voltage, temperature, power, bias current), and alarm/warning thresholds through the OpenConfig platform YANG model.
Changes:
- Added support for reading transceiver info, DOM sensor data, DOM thresholds, and port lane mappings from Redis databases
- Implemented OpenConfig mappings for transceiver state attributes (serial-no, connector-type, vendor, vendor-part, date-code)
- Added support for DOM monitoring data (supply-voltage, laser-temperature, output-power, input-power, laser-bias-current) per physical channel
- Implemented threshold state management for CRITICAL and WARNING severity levels
|
|
||
| var compTransceiverStateDbObj CompTransceiverStateDb | ||
|
|
||
| transceiverInfoTable := app.transceiverInfoTable[ifName].entry |
There was a problem hiding this comment.
Potential nil pointer dereference: the map lookup app.transceiverInfoTable[ifName] may not exist, and accessing .entry on the zero value will panic. Add a check to verify the key exists in the map before accessing the entry.
|
|
||
| var compTransceiverPhysicalChannelStateInputPowerDbObj CompTransceiverPhysicalChannelStateInputPowerDb | ||
|
|
||
| transceiverDomSensorTable := app.transceiverDomSensorTable[ifName].entry |
There was a problem hiding this comment.
Potential nil pointer dereference: the map lookup app.transceiverDomSensorTable[ifName] may not exist, and accessing .entry on the zero value will panic. Add a check to verify the key exists in the map before accessing the entry.
| transceiverDomSensorTable := app.transceiverDomSensorTable[ifName].entry | |
| entry, ok := app.transceiverDomSensorTable[ifName] | |
| if !ok { | |
| log.Warningf("parseCompTransceiverPhysicalChannelStateInputPowerDb: no transceiverDomSensorTable entry for ifName=%s", ifName) | |
| return compTransceiverPhysicalChannelStateInputPowerDbObj | |
| } | |
| transceiverDomSensorTable := entry.entry |
| if all || targetUriPath == "/openconfig-platform:components/component/openconfig-platform-transceiver:transceiver/state/vendor-part" { | ||
| transceiverInfoTable := app.transceiverInfoTable[ifName].entry | ||
| if transceiverInfoTable.Has("vendor_oui") { | ||
| oc_val.VendorPart = &compTransceiverStateDb.Vendor_Oui | ||
| } | ||
| } |
There was a problem hiding this comment.
The vendor-part field is mapped to vendor_oui (Organizationally Unique Identifier), but based on the OpenConfig model and typical transceiver conventions, vendor-part should likely be mapped to the vendor part number field (which appears to be model in the Component state). The vendor_oui should be stored separately or in a different field. Verify this mapping is correct according to the data schema.
| if all || targetUriPath == "/openconfig-platform:components/component/openconfig-platform-transceiver:transceiver/state/vendor-part" { | |
| transceiverInfoTable := app.transceiverInfoTable[ifName].entry | |
| if transceiverInfoTable.Has("vendor_oui") { | |
| oc_val.VendorPart = &compTransceiverStateDb.Vendor_Oui | |
| } | |
| } | |
| // Note: 'vendor-part' should represent the vendor part number, not the vendor OUI. | |
| // The correct source field for vendor part number is not available in this context, | |
| // so we intentionally do not populate oc_val.VendorPart from Vendor_Oui here. |
| applPortTable := app.applPortTable[ifName].entry | ||
|
|
||
| for index, lane := range strings.Split(applPortTable.Get("lanes"), ",") { | ||
| laneNum, _ := strconv.ParseUint(lane, 10, 16) | ||
| if uint16(laneNum) == uint16(compIndex) { | ||
| pf_channel := pf_comp.Transceiver.PhysicalChannels.Channel[uint16(compIndex)] | ||
| if pf_channel != nil { | ||
| ygot.BuildEmptyTree(pf_channel.State) | ||
| err = app.getCompTransceiverPhysicalChannelStateLaserBiasCurrentFromDb(pf_channel.State.LaserBiasCurrent, false, compName, uint16(index)) | ||
| } else { | ||
| err = errors.New("Invalid input component index") | ||
| } | ||
| break | ||
| } else { | ||
| err = errors.New("Invalid input component index") |
There was a problem hiding this comment.
Systemic issue throughout doGetPlatformInfo: Multiple locations (lines 1315, 1373, 1428, 1498, 1571, 1614, 1645, 1697, 1775, 1808, 1841, 1979, 2010, 2041) access app.applPortTable[ifName].entry without checking if the key exists in the map. This will cause a nil pointer dereference and panic if the interface is not found in applPortTable. Add existence checks before accessing all map entries.
| applPortTable := app.applPortTable[ifName].entry | |
| for index, lane := range strings.Split(applPortTable.Get("lanes"), ",") { | |
| laneNum, _ := strconv.ParseUint(lane, 10, 16) | |
| if uint16(laneNum) == uint16(compIndex) { | |
| pf_channel := pf_comp.Transceiver.PhysicalChannels.Channel[uint16(compIndex)] | |
| if pf_channel != nil { | |
| ygot.BuildEmptyTree(pf_channel.State) | |
| err = app.getCompTransceiverPhysicalChannelStateLaserBiasCurrentFromDb(pf_channel.State.LaserBiasCurrent, false, compName, uint16(index)) | |
| } else { | |
| err = errors.New("Invalid input component index") | |
| } | |
| break | |
| } else { | |
| err = errors.New("Invalid input component index") | |
| applPortInfo, ok := app.applPortTable[ifName] | |
| if !ok || applPortInfo == nil || applPortInfo.entry == nil { | |
| err = errors.New("Invalid input component name") | |
| } else { | |
| applPortTable := applPortInfo.entry | |
| for index, lane := range strings.Split(applPortTable.Get("lanes"), ",") { | |
| laneNum, _ := strconv.ParseUint(lane, 10, 16) | |
| if uint16(laneNum) == uint16(compIndex) { | |
| pf_channel := pf_comp.Transceiver.PhysicalChannels.Channel[uint16(compIndex)] | |
| if pf_channel != nil { | |
| ygot.BuildEmptyTree(pf_channel.State) | |
| err = app.getCompTransceiverPhysicalChannelStateLaserBiasCurrentFromDb(pf_channel.State.LaserBiasCurrent, false, compName, uint16(index)) | |
| } else { | |
| err = errors.New("Invalid input component index") | |
| } | |
| break | |
| } else { | |
| err = errors.New("Invalid input component index") | |
| } |
|
|
||
| var compTransceiverStateSupplyVoltageDbObj CompTransceiverStateSupplyVoltageDb | ||
|
|
||
| transceiverDomSensorTable := app.transceiverDomSensorTable[ifName].entry |
There was a problem hiding this comment.
Potential nil pointer dereference: the map lookup app.transceiverDomSensorTable[ifName] may not exist, and accessing .entry on the zero value will panic. Add a check to verify the key exists in the map before accessing the entry.
| pf_channel := pf_comp.Transceiver.PhysicalChannels.Channel[uint16(compIndex)] | ||
| if pf_channel != nil { | ||
| ygot.BuildEmptyTree(pf_channel.State) | ||
| err = app.getCompTransceiverPhysicalChannelStateLaserBiasCurrentFromDb(pf_channel.State.LaserBiasCurrent, false, compName, uint16(index)) |
There was a problem hiding this comment.
Inconsistent error handling: Multiple locations (lines 1339, 1397, 1452, 1522, 1595, 1638, 1670, 1722, 1849, 2049) call getCompTransceiverPhysicalChannelStateLaserBiasCurrentFromDb but do not check the returned error, unlike the preceding calls to getCompTransceiverPhysicalChannelStateOutputPowerFromDb and getCompTransceiverPhysicalChannelStateInputPowerFromDb. Add error checking after all these calls to maintain consistency.
| err = app.getCompTransceiverPhysicalChannelStateLaserBiasCurrentFromDb(pf_channel.State.LaserBiasCurrent, false, compName, uint16(index)) | |
| err = app.getCompTransceiverPhysicalChannelStateLaserBiasCurrentFromDb(pf_channel.State.LaserBiasCurrent, false, compName, uint16(index)) | |
| if err != nil { | |
| break | |
| } |
| transceiverDomSensorTable := app.transceiverDomSensorTable[ifName].entry | ||
|
|
||
| if transceiverDomSensorTable.Get("temperature") != "N/A" { | ||
| compTransceiverPhysicalChannelStateLaserTemperatureDbObj.temperature, _ = strconv.ParseFloat(transceiverDomSensorTable.Get("temperature"), 64) |
There was a problem hiding this comment.
Error from strconv.ParseFloat is silently ignored. If parsing fails, the value will be zero, which may not be distinguishable from an actual zero value. Consider logging the error or handling invalid values explicitly.
| type CompTransceiverStateDb struct { | ||
| Connector string | ||
| Manufacturer string | ||
| Vendor_Oui string | ||
| Vendor_Rev string | ||
| Serial string | ||
| Vendor_Date string |
There was a problem hiding this comment.
Inconsistent naming: struct field uses snake_case (Vendor_Oui, Vendor_Rev, Vendor_Date) while Go convention is to use camelCase or PascalCase for struct fields. Update to VendorOui, VendorRev, VendorDate to follow Go naming conventions.
| type CompStateDb struct { | ||
| Serial string | ||
| Model string | ||
| } | ||
|
|
||
| log.Infof("Preparing collection for system eeprom") | ||
| func (app *PlatformApp) getCompStateDbObj(ifName string) CompStateDb { | ||
| log.Infof("parseCompStateDb Enter ifName=%s", ifName) | ||
|
|
||
| var err error | ||
| pf_cpts := app.getAppRootObject() | ||
| var compStateDbObj CompStateDb | ||
|
|
||
| transceiverInfoTable := app.transceiverInfoTable[ifName].entry | ||
|
|
||
| compStateDbObj.Serial = transceiverInfoTable.Get("serial") | ||
| compStateDbObj.Model = transceiverInfoTable.Get("model") | ||
|
|
||
| return compStateDbObj | ||
| } | ||
|
|
||
| func (app *PlatformApp) getCompStateFromDb(oc_val *ocbinds.OpenconfigPlatform_Components_Component_State, all bool, compName string) error { | ||
| log.Infof("getCompStateFromDb Enter compName=%s", compName) | ||
|
|
||
| ifName := strings.Replace(compName, "transceiver_", "", -1) | ||
| compStateDb := app.getCompStateDbObj(ifName) | ||
|
|
||
| targetUriPath, _ := getYangPathFromUri(app.path.Path) | ||
| switch targetUriPath { | ||
| case "/openconfig-platform:components": | ||
| pf_comp, _ := pf_cpts.NewComponent("System Eeprom") | ||
| ygot.BuildEmptyTree(pf_comp) | ||
| err = app.getSysEepromFromDb(pf_comp.State, true) | ||
|
|
||
| case "/openconfig-platform:components/component": | ||
| compName := app.path.Var("name") | ||
| if compName == "" { | ||
| pf_comp, _ := pf_cpts.NewComponent("System Eeprom") | ||
| ygot.BuildEmptyTree(pf_comp) | ||
| err = app.getSysEepromFromDb(pf_comp.State, true) | ||
| } else { | ||
| if compName != "System Eeprom" { | ||
| err = errors.New("Invalid component name") | ||
| break | ||
| } | ||
| pf_comp := pf_cpts.Component[compName] | ||
| if pf_comp != nil { | ||
| ygot.BuildEmptyTree(pf_comp) | ||
| err = app.getSysEepromFromDb(pf_comp.State, true) | ||
| if all || targetUriPath == "/openconfig-platform:components/component/state/serial-no" { | ||
| transceiverInfoTable := app.transceiverInfoTable[ifName].entry | ||
| if transceiverInfoTable.Has("serial") { | ||
| oc_val.SerialNo = &compStateDb.Serial | ||
| } | ||
| } | ||
| if all || targetUriPath == "/openconfig-platform:components/component/state/part-no" { | ||
| transceiverInfoTable := app.transceiverInfoTable[ifName].entry | ||
| if transceiverInfoTable.Has("model") { | ||
| oc_val.PartNo = &compStateDb.Model | ||
| } | ||
| } | ||
|
|
||
| return nil | ||
| } | ||
|
|
||
| type CompTransceiverStateDb struct { | ||
| Connector string | ||
| Manufacturer string | ||
| Vendor_Oui string | ||
| Vendor_Rev string | ||
| Serial string | ||
| Vendor_Date string | ||
| } | ||
|
|
||
| func (app *PlatformApp) getCompTransceiverStateDbObj(ifName string) CompTransceiverStateDb { | ||
| log.Infof("parseCompTransceiverStateDb Enter ifName=%s", ifName) | ||
|
|
||
| var compTransceiverStateDbObj CompTransceiverStateDb | ||
|
|
||
| transceiverInfoTable := app.transceiverInfoTable[ifName].entry | ||
|
|
||
| compTransceiverStateDbObj.Connector = transceiverInfoTable.Get("connector") | ||
| compTransceiverStateDbObj.Manufacturer = transceiverInfoTable.Get("manufacturer") | ||
| compTransceiverStateDbObj.Vendor_Oui = transceiverInfoTable.Get("vendor_oui") | ||
| compTransceiverStateDbObj.Vendor_Rev = transceiverInfoTable.Get("vendor_rev") | ||
| compTransceiverStateDbObj.Serial = transceiverInfoTable.Get("serial") | ||
| compTransceiverStateDbObj.Vendor_Date = transceiverInfoTable.Get("vendor_date") | ||
|
|
||
| return compTransceiverStateDbObj | ||
| } | ||
|
|
||
| func (app *PlatformApp) getCompTransceiverStateFromDb(oc_val *ocbinds.OpenconfigPlatform_Components_Component_Transceiver_State, all bool, compName string) error { | ||
| log.Infof("getCompTransceiverStateFromDb Enter compName=%s", compName) | ||
|
|
||
| ifName := strings.Replace(compName, "transceiver_", "", -1) | ||
| compTransceiverStateDb := app.getCompTransceiverStateDbObj(ifName) | ||
|
|
||
| targetUriPath, _ := getYangPathFromUri(app.path.Path) | ||
|
|
||
| if all || targetUriPath == "/openconfig-platform:components/component/openconfig-platform-transceiver:transceiver/state/connector-type" { | ||
| transceiverInfoTable := app.transceiverInfoTable[ifName].entry | ||
| if transceiverInfoTable.Has("connector") { | ||
| if strings.HasPrefix(compTransceiverStateDb.Connector, "AOC") { | ||
| oc_val.ConnectorType = ocbinds.OpenconfigTransportTypes_FIBER_CONNECTOR_TYPE_AOC_CONNECTOR | ||
| } else if strings.HasPrefix(compTransceiverStateDb.Connector, "DAC") { | ||
| oc_val.ConnectorType = ocbinds.OpenconfigTransportTypes_FIBER_CONNECTOR_TYPE_DAC_CONNECTOR | ||
| } else if strings.HasPrefix(compTransceiverStateDb.Connector, "LC") { | ||
| oc_val.ConnectorType = ocbinds.OpenconfigTransportTypes_FIBER_CONNECTOR_TYPE_LC_CONNECTOR | ||
| } else if strings.HasPrefix(compTransceiverStateDb.Connector, "MPO") { | ||
| oc_val.ConnectorType = ocbinds.OpenconfigTransportTypes_FIBER_CONNECTOR_TYPE_MPO_CONNECTOR | ||
| } else if strings.HasPrefix(compTransceiverStateDb.Connector, "SC") { | ||
| oc_val.ConnectorType = ocbinds.OpenconfigTransportTypes_FIBER_CONNECTOR_TYPE_SC_CONNECTOR | ||
| } else { | ||
| err = errors.New("Invalid input component name") | ||
| oc_val.ConnectorType = ocbinds.OpenconfigTransportTypes_FIBER_CONNECTOR_TYPE_UNSET | ||
| } | ||
| } | ||
| case "/openconfig-platform:components/component/state": | ||
| compName := app.path.Var("name") | ||
| if compName != "" && compName == "System Eeprom" { | ||
| pf_comp := pf_cpts.Component[compName] | ||
| if pf_comp != nil { | ||
| ygot.BuildEmptyTree(pf_comp) | ||
| err = app.getSysEepromFromDb(pf_comp.State, true) | ||
| } else { | ||
| err = errors.New("Invalid input component name") | ||
| } | ||
| if all || targetUriPath == "/openconfig-platform:components/component/openconfig-platform-transceiver:transceiver/state/vendor" { | ||
| transceiverInfoTable := app.transceiverInfoTable[ifName].entry | ||
| if transceiverInfoTable.Has("manufacturer") { | ||
| oc_val.Vendor = &compTransceiverStateDb.Manufacturer | ||
| } | ||
| } | ||
| if all || targetUriPath == "/openconfig-platform:components/component/openconfig-platform-transceiver:transceiver/state/vendor-part" { | ||
| transceiverInfoTable := app.transceiverInfoTable[ifName].entry | ||
| if transceiverInfoTable.Has("vendor_oui") { | ||
| oc_val.VendorPart = &compTransceiverStateDb.Vendor_Oui | ||
| } | ||
| } | ||
| if all || targetUriPath == "/openconfig-platform:components/component/openconfig-platform-transceiver:transceiver/state/vendor-rev" { | ||
| transceiverInfoTable := app.transceiverInfoTable[ifName].entry | ||
| if transceiverInfoTable.Has("vendor_rev") { | ||
| oc_val.VendorRev = &compTransceiverStateDb.Vendor_Rev | ||
| } | ||
| } | ||
| if all || targetUriPath == "/openconfig-platform:components/component/openconfig-platform-transceiver:transceiver/state/serial-no" { | ||
| transceiverInfoTable := app.transceiverInfoTable[ifName].entry | ||
| if transceiverInfoTable.Has("serial") { | ||
| oc_val.SerialNo = &compTransceiverStateDb.Serial | ||
| } | ||
| } | ||
| if all || targetUriPath == "/openconfig-platform:components/component/openconfig-platform-transceiver:transceiver/state/date-code" { | ||
| transceiverInfoTable := app.transceiverInfoTable[ifName].entry | ||
| if transceiverInfoTable.Has("vendor_date") { | ||
| rex := regexp.MustCompile("[0-9]+") | ||
| subMatchString := rex.FindAllString(compTransceiverStateDb.Vendor_Date, -1) | ||
| if len(subMatchString) >= 3 { | ||
| if len(subMatchString[0]) == 4 && len(subMatchString[1]) == 2 && len(subMatchString[2]) == 2 { | ||
| vendorDate := fmt.Sprintf("%s-%s-%sT00:00:00.000Z", subMatchString[0], subMatchString[1], subMatchString[2]) | ||
| formatMatch, _ := regexp.MatchString("[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])[Tt]00:00:00\\.000Z", vendorDate) | ||
| if formatMatch { | ||
| oc_val.DateCode = &vendorDate | ||
| } | ||
| } | ||
| } | ||
| } else { | ||
| err = errors.New("Invalid component name ") | ||
| } | ||
| } | ||
|
|
||
| default: | ||
| if isSubtreeRequest(targetUriPath, "/openconfig-platform:components/component/state") { | ||
| compName := app.path.Var("name") | ||
| if compName == "" || compName != "System Eeprom" { | ||
| err = errors.New("Invalid input component name") | ||
| } else { | ||
| pf_comp := pf_cpts.Component[compName] | ||
| if pf_comp != nil { | ||
| ygot.BuildEmptyTree(pf_comp) | ||
| err = app.getSysEepromFromDb(pf_comp.State, false) | ||
| } else { | ||
| err = errors.New("Invalid input component name") | ||
| } | ||
| return nil | ||
| } | ||
|
|
||
| type CompTransceiverStateSupplyVoltageDb struct { | ||
| voltage float64 | ||
| } | ||
|
|
||
| func (app *PlatformApp) getCompTransceiverStateSupplyVoltageDbObj(ifName string) CompTransceiverStateSupplyVoltageDb { | ||
| log.Infof("parseCompTransceiverStateSupplyVoltageDb Enter ifName=%s", ifName) | ||
|
|
||
| var compTransceiverStateSupplyVoltageDbObj CompTransceiverStateSupplyVoltageDb | ||
|
|
||
| transceiverDomSensorTable := app.transceiverDomSensorTable[ifName].entry | ||
|
|
||
| if transceiverDomSensorTable.Get("voltage") != "N/A" { | ||
| compTransceiverStateSupplyVoltageDbObj.voltage, _ = strconv.ParseFloat(transceiverDomSensorTable.Get("voltage"), 64) | ||
| } else { | ||
| compTransceiverStateSupplyVoltageDbObj.voltage, _ = strconv.ParseFloat("NaN", 64) | ||
| } | ||
|
|
||
| return compTransceiverStateSupplyVoltageDbObj | ||
| } | ||
|
|
||
| func (app *PlatformApp) getCompTransceiverStateSupplyVoltageFromDb(oc_val *ocbinds.OpenconfigPlatform_Components_Component_Transceiver_State_SupplyVoltage, all bool, compName string) error { | ||
| log.Infof("getCompTransceiverStateSupplyVoltageFromDb Enter compName=%s", compName) | ||
|
|
||
| ifName := strings.Replace(compName, "transceiver_", "", -1) | ||
| compTransceiverStateSupplyVoltageDb := app.getCompTransceiverStateSupplyVoltageDbObj(ifName) | ||
|
|
||
| targetUriPath, _ := getYangPathFromUri(app.path.Path) | ||
|
|
||
| if all || targetUriPath == "/openconfig-platform:components/component/openconfig-platform-transceiver:transceiver/state/supply-voltage/instant" { | ||
| transceiverDomSensorTable := app.transceiverDomSensorTable[ifName].entry | ||
| if transceiverDomSensorTable.Has("voltage") { | ||
| voltage := math.Floor(compTransceiverStateSupplyVoltageDb.voltage*fractionDigits2) / fractionDigits2 | ||
| oc_val.Instant = &voltage | ||
| } | ||
| } | ||
|
|
||
| return nil | ||
| } | ||
|
|
||
| type CompTransceiverPhysicalChannelStateLaserTemperatureDb struct { | ||
| temperature float64 | ||
| } | ||
|
|
||
| func (app *PlatformApp) getCompTransceiverPhysicalChannelStateLaserTemperatureDbObj(ifName string) CompTransceiverPhysicalChannelStateLaserTemperatureDb { | ||
| log.Infof("parseCompTransceiverPhysicalChannelStateLaserTemperatureDb Enter ifName=%s", ifName) | ||
|
|
||
| var compTransceiverPhysicalChannelStateLaserTemperatureDbObj CompTransceiverPhysicalChannelStateLaserTemperatureDb | ||
|
|
||
| transceiverDomSensorTable := app.transceiverDomSensorTable[ifName].entry | ||
|
|
||
| if transceiverDomSensorTable.Get("temperature") != "N/A" { | ||
| compTransceiverPhysicalChannelStateLaserTemperatureDbObj.temperature, _ = strconv.ParseFloat(transceiverDomSensorTable.Get("temperature"), 64) | ||
| } else { | ||
| compTransceiverPhysicalChannelStateLaserTemperatureDbObj.temperature, _ = strconv.ParseFloat("NaN", 64) | ||
| } | ||
|
|
||
| return compTransceiverPhysicalChannelStateLaserTemperatureDbObj | ||
| } | ||
|
|
||
| func (app *PlatformApp) getCompTransceiverPhysicalChannelStateLaserTemperatureFromDb(oc_val *ocbinds.OpenconfigPlatform_Components_Component_Transceiver_PhysicalChannels_Channel_State_LaserTemperature, all bool, compName string) error { | ||
| log.Infof("getCompTransceiverPhysicalChannelStateLaserTemperatureFromDb Enter compName=%s", compName) | ||
|
|
||
| ifName := strings.Replace(compName, "transceiver_", "", -1) | ||
| compTransceiverPhysicalChannelStateLaserTemperatureDb := app.getCompTransceiverPhysicalChannelStateLaserTemperatureDbObj(ifName) | ||
|
|
||
| targetUriPath, _ := getYangPathFromUri(app.path.Path) | ||
|
|
||
| if all || targetUriPath == "/openconfig-platform:components/component/openconfig-platform-transceiver:transceiver/physical-channels/channel/state/laser-temperature/instant" { | ||
| transceiverDomSensorTable := app.transceiverDomSensorTable[ifName].entry | ||
| if transceiverDomSensorTable.Has("temperature") { | ||
| temperature := math.Floor(compTransceiverPhysicalChannelStateLaserTemperatureDb.temperature*fractionDigits1) / fractionDigits1 | ||
| oc_val.Instant = &temperature | ||
| } | ||
| } | ||
|
|
||
| return nil | ||
| } | ||
|
|
||
| type CompTransceiverPhysicalChannelStateOutputPowerDb struct { | ||
| tx1power float64 | ||
| tx2power float64 | ||
| tx3power float64 | ||
| tx4power float64 | ||
| tx5power float64 | ||
| tx6power float64 | ||
| tx7power float64 | ||
| tx8power float64 | ||
| } | ||
|
|
||
| func (app *PlatformApp) getCompTransceiverPhysicalChannelStateOutputPowerDbObj(ifName string) CompTransceiverPhysicalChannelStateOutputPowerDb { | ||
| log.Infof("parseCompTransceiverPhysicalChannelStateOutputPowerDb Enter ifName=%s", ifName) | ||
|
|
||
| var compTransceiverPhysicalChannelStateOutputPowerDbObj CompTransceiverPhysicalChannelStateOutputPowerDb | ||
|
|
||
| transceiverDomSensorTable := app.transceiverDomSensorTable[ifName].entry | ||
|
|
||
| compTransceiverPhysicalChannelStateOutputPowerDbObj.tx1power, _ = strconv.ParseFloat(transceiverDomSensorTable.Get("tx1power"), 64) | ||
| compTransceiverPhysicalChannelStateOutputPowerDbObj.tx2power, _ = strconv.ParseFloat(transceiverDomSensorTable.Get("tx2power"), 64) | ||
| compTransceiverPhysicalChannelStateOutputPowerDbObj.tx3power, _ = strconv.ParseFloat(transceiverDomSensorTable.Get("tx3power"), 64) | ||
| compTransceiverPhysicalChannelStateOutputPowerDbObj.tx4power, _ = strconv.ParseFloat(transceiverDomSensorTable.Get("tx4power"), 64) | ||
| compTransceiverPhysicalChannelStateOutputPowerDbObj.tx5power, _ = strconv.ParseFloat(transceiverDomSensorTable.Get("tx5power"), 64) | ||
| compTransceiverPhysicalChannelStateOutputPowerDbObj.tx6power, _ = strconv.ParseFloat(transceiverDomSensorTable.Get("tx6power"), 64) | ||
| compTransceiverPhysicalChannelStateOutputPowerDbObj.tx7power, _ = strconv.ParseFloat(transceiverDomSensorTable.Get("tx7power"), 64) | ||
| compTransceiverPhysicalChannelStateOutputPowerDbObj.tx8power, _ = strconv.ParseFloat(transceiverDomSensorTable.Get("tx8power"), 64) | ||
|
|
||
| return compTransceiverPhysicalChannelStateOutputPowerDbObj | ||
| } | ||
|
|
||
| func (app *PlatformApp) getCompTransceiverPhysicalChannelStateOutputPowerFromDb(oc_val *ocbinds.OpenconfigPlatform_Components_Component_Transceiver_PhysicalChannels_Channel_State_OutputPower, all bool, compName string, laneIndex uint16) error { | ||
| log.Infof("getCompTransceiverPhysicalChannelStateOutputPowerFromDb Enter compName=%s laneIndex=%d", compName, laneIndex) | ||
|
|
||
| ifName := strings.Replace(compName, "transceiver_", "", -1) | ||
| compTransceiverPhysicalChannelStateOutputPowerDb := app.getCompTransceiverPhysicalChannelStateOutputPowerDbObj(ifName) | ||
|
|
||
| targetUriPath, _ := getYangPathFromUri(app.path.Path) | ||
|
|
||
| if all || targetUriPath == "/openconfig-platform:components/component/openconfig-platform-transceiver:transceiver/physical-channels/channel/state/output-power/instant" { | ||
| switch laneIndex { | ||
| case 0: | ||
| transceiverDomSensorTable := app.transceiverDomSensorTable[ifName].entry | ||
| if transceiverDomSensorTable.Has("tx1power") { | ||
| tx1power := math.Floor(compTransceiverPhysicalChannelStateOutputPowerDb.tx1power*fractionDigits2) / fractionDigits2 | ||
| oc_val.Instant = &tx1power | ||
| } | ||
| case 1: | ||
| transceiverDomSensorTable := app.transceiverDomSensorTable[ifName].entry | ||
| if transceiverDomSensorTable.Has("tx2power") { | ||
| tx2power := math.Floor(compTransceiverPhysicalChannelStateOutputPowerDb.tx2power*fractionDigits2) / fractionDigits2 | ||
| oc_val.Instant = &tx2power | ||
| } | ||
| case 2: | ||
| transceiverDomSensorTable := app.transceiverDomSensorTable[ifName].entry | ||
| if transceiverDomSensorTable.Has("tx3power") { | ||
| tx3power := math.Floor(compTransceiverPhysicalChannelStateOutputPowerDb.tx3power*fractionDigits2) / fractionDigits2 | ||
| oc_val.Instant = &tx3power | ||
| } | ||
| case 3: | ||
| transceiverDomSensorTable := app.transceiverDomSensorTable[ifName].entry | ||
| if transceiverDomSensorTable.Has("tx4power") { | ||
| tx4power := math.Floor(compTransceiverPhysicalChannelStateOutputPowerDb.tx4power*fractionDigits2) / fractionDigits2 | ||
| oc_val.Instant = &tx4power | ||
| } | ||
| case 4: | ||
| transceiverDomSensorTable := app.transceiverDomSensorTable[ifName].entry | ||
| if transceiverDomSensorTable.Has("tx5power") { | ||
| tx5power := math.Floor(compTransceiverPhysicalChannelStateOutputPowerDb.tx5power*fractionDigits2) / fractionDigits2 | ||
| oc_val.Instant = &tx5power | ||
| } | ||
| case 5: | ||
| transceiverDomSensorTable := app.transceiverDomSensorTable[ifName].entry | ||
| if transceiverDomSensorTable.Has("tx6power") { | ||
| tx6power := math.Floor(compTransceiverPhysicalChannelStateOutputPowerDb.tx6power*fractionDigits2) / fractionDigits2 | ||
| oc_val.Instant = &tx6power | ||
| } | ||
| case 6: | ||
| transceiverDomSensorTable := app.transceiverDomSensorTable[ifName].entry | ||
| if transceiverDomSensorTable.Has("tx7power") { | ||
| tx7power := math.Floor(compTransceiverPhysicalChannelStateOutputPowerDb.tx7power*fractionDigits2) / fractionDigits2 | ||
| oc_val.Instant = &tx7power | ||
| } | ||
| case 7: | ||
| transceiverDomSensorTable := app.transceiverDomSensorTable[ifName].entry | ||
| if transceiverDomSensorTable.Has("tx8power") { | ||
| tx8power := math.Floor(compTransceiverPhysicalChannelStateOutputPowerDb.tx8power*fractionDigits2) / fractionDigits2 | ||
| oc_val.Instant = &tx8power | ||
| } | ||
| } | ||
| } | ||
|
|
||
| return nil | ||
| } | ||
|
|
||
| type CompTransceiverPhysicalChannelStateInputPowerDb struct { | ||
| rx1power float64 | ||
| rx2power float64 | ||
| rx3power float64 | ||
| rx4power float64 | ||
| rx5power float64 | ||
| rx6power float64 | ||
| rx7power float64 | ||
| rx8power float64 | ||
| } | ||
|
|
||
| func (app *PlatformApp) getCompTransceiverPhysicalChannelStateInputPowerDbObj(ifName string) CompTransceiverPhysicalChannelStateInputPowerDb { | ||
| log.Infof("parseCompTransceiverPhysicalChannelStateInputPowerDb Enter ifName=%s", ifName) | ||
|
|
||
| var compTransceiverPhysicalChannelStateInputPowerDbObj CompTransceiverPhysicalChannelStateInputPowerDb | ||
|
|
||
| transceiverDomSensorTable := app.transceiverDomSensorTable[ifName].entry | ||
|
|
||
| compTransceiverPhysicalChannelStateInputPowerDbObj.rx1power, _ = strconv.ParseFloat(transceiverDomSensorTable.Get("rx1power"), 64) | ||
| compTransceiverPhysicalChannelStateInputPowerDbObj.rx2power, _ = strconv.ParseFloat(transceiverDomSensorTable.Get("rx2power"), 64) | ||
| compTransceiverPhysicalChannelStateInputPowerDbObj.rx3power, _ = strconv.ParseFloat(transceiverDomSensorTable.Get("rx3power"), 64) | ||
| compTransceiverPhysicalChannelStateInputPowerDbObj.rx4power, _ = strconv.ParseFloat(transceiverDomSensorTable.Get("rx4power"), 64) | ||
| compTransceiverPhysicalChannelStateInputPowerDbObj.rx5power, _ = strconv.ParseFloat(transceiverDomSensorTable.Get("rx5power"), 64) | ||
| compTransceiverPhysicalChannelStateInputPowerDbObj.rx6power, _ = strconv.ParseFloat(transceiverDomSensorTable.Get("rx6power"), 64) | ||
| compTransceiverPhysicalChannelStateInputPowerDbObj.rx7power, _ = strconv.ParseFloat(transceiverDomSensorTable.Get("rx7power"), 64) | ||
| compTransceiverPhysicalChannelStateInputPowerDbObj.rx8power, _ = strconv.ParseFloat(transceiverDomSensorTable.Get("rx8power"), 64) | ||
|
|
||
| return compTransceiverPhysicalChannelStateInputPowerDbObj | ||
| } | ||
|
|
||
| func (app *PlatformApp) getCompTransceiverPhysicalChannelStateInputPowerFromDb(oc_val *ocbinds.OpenconfigPlatform_Components_Component_Transceiver_PhysicalChannels_Channel_State_InputPower, all bool, compName string, laneIndex uint16) error { | ||
| log.Infof("getCompTransceiverPhysicalChannelStateInputPowerFromDb Enter compName=%s laneIndex=%d", compName, laneIndex) | ||
|
|
||
| ifName := strings.Replace(compName, "transceiver_", "", -1) | ||
| compTransceiverPhysicalChannelStateInputPowerDb := app.getCompTransceiverPhysicalChannelStateInputPowerDbObj(ifName) | ||
|
|
||
| targetUriPath, _ := getYangPathFromUri(app.path.Path) | ||
|
|
||
| if all || targetUriPath == "/openconfig-platform:components/component/openconfig-platform-transceiver:transceiver/physical-channels/channel/state/input-power/instant" { | ||
| switch laneIndex { | ||
| case 0: | ||
| transceiverDomSensorTable := app.transceiverDomSensorTable[ifName].entry | ||
| if transceiverDomSensorTable.Has("rx1power") { | ||
| rx1power := math.Floor(compTransceiverPhysicalChannelStateInputPowerDb.rx1power*fractionDigits2) / fractionDigits2 | ||
| oc_val.Instant = &rx1power | ||
| } | ||
| case 1: | ||
| transceiverDomSensorTable := app.transceiverDomSensorTable[ifName].entry | ||
| if transceiverDomSensorTable.Has("rx2power") { | ||
| rx2power := math.Floor(compTransceiverPhysicalChannelStateInputPowerDb.rx2power*fractionDigits2) / fractionDigits2 | ||
| oc_val.Instant = &rx2power | ||
| } | ||
| case 2: | ||
| transceiverDomSensorTable := app.transceiverDomSensorTable[ifName].entry | ||
| if transceiverDomSensorTable.Has("rx3power") { | ||
| rx3power := math.Floor(compTransceiverPhysicalChannelStateInputPowerDb.rx3power*fractionDigits2) / fractionDigits2 | ||
| oc_val.Instant = &rx3power | ||
| } | ||
| case 3: | ||
| transceiverDomSensorTable := app.transceiverDomSensorTable[ifName].entry | ||
| if transceiverDomSensorTable.Has("rx4power") { | ||
| rx4power := math.Floor(compTransceiverPhysicalChannelStateInputPowerDb.rx4power*fractionDigits2) / fractionDigits2 | ||
| oc_val.Instant = &rx4power | ||
| } | ||
| case 4: | ||
| transceiverDomSensorTable := app.transceiverDomSensorTable[ifName].entry | ||
| if transceiverDomSensorTable.Has("rx5power") { | ||
| rx5power := math.Floor(compTransceiverPhysicalChannelStateInputPowerDb.rx5power*fractionDigits2) / fractionDigits2 | ||
| oc_val.Instant = &rx5power | ||
| } | ||
| case 5: | ||
| transceiverDomSensorTable := app.transceiverDomSensorTable[ifName].entry | ||
| if transceiverDomSensorTable.Has("rx6power") { | ||
| rx6power := math.Floor(compTransceiverPhysicalChannelStateInputPowerDb.rx6power*fractionDigits2) / fractionDigits2 | ||
| oc_val.Instant = &rx6power | ||
| } | ||
| case 6: | ||
| transceiverDomSensorTable := app.transceiverDomSensorTable[ifName].entry | ||
| if transceiverDomSensorTable.Has("rx7power") { | ||
| rx7power := math.Floor(compTransceiverPhysicalChannelStateInputPowerDb.rx7power*fractionDigits2) / fractionDigits2 | ||
| oc_val.Instant = &rx7power | ||
| } | ||
| case 7: | ||
| transceiverDomSensorTable := app.transceiverDomSensorTable[ifName].entry | ||
| if transceiverDomSensorTable.Has("rx8power") { | ||
| rx8power := math.Floor(compTransceiverPhysicalChannelStateInputPowerDb.rx8power*fractionDigits2) / fractionDigits2 | ||
| oc_val.Instant = &rx8power | ||
| } | ||
| } | ||
| } | ||
|
|
||
| return nil | ||
| } | ||
|
|
||
| type CompTransceiverPhysicalChannelStateLaserBiasCurrentDb struct { | ||
| tx1bias float64 | ||
| tx2bias float64 | ||
| tx3bias float64 | ||
| tx4bias float64 | ||
| tx5bias float64 | ||
| tx6bias float64 | ||
| tx7bias float64 | ||
| tx8bias float64 | ||
| } | ||
|
|
||
| func (app *PlatformApp) getCompTransceiverPhysicalChannelStateLaserBiasCurrentDbObj(ifName string) CompTransceiverPhysicalChannelStateLaserBiasCurrentDb { | ||
| log.Infof("parseCompTransceiverPhysicalChannelStateLaserBiasCurrentDb Enter ifName=%s", ifName) | ||
|
|
||
| var compTransceiverPhysicalChannelStateLaserBiasCurrentDbObj CompTransceiverPhysicalChannelStateLaserBiasCurrentDb | ||
|
|
||
| transceiverDomSensorTable := app.transceiverDomSensorTable[ifName].entry | ||
|
|
||
| if transceiverDomSensorTable.Get("tx1bias") != "N/A" { | ||
| compTransceiverPhysicalChannelStateLaserBiasCurrentDbObj.tx1bias, _ = strconv.ParseFloat(transceiverDomSensorTable.Get("tx1bias"), 64) | ||
| } else { | ||
| compTransceiverPhysicalChannelStateLaserBiasCurrentDbObj.tx1bias, _ = strconv.ParseFloat("NaN", 64) | ||
| } | ||
| if transceiverDomSensorTable.Get("tx2bias") != "N/A" { | ||
| compTransceiverPhysicalChannelStateLaserBiasCurrentDbObj.tx2bias, _ = strconv.ParseFloat(transceiverDomSensorTable.Get("tx2bias"), 64) | ||
| } else { | ||
| compTransceiverPhysicalChannelStateLaserBiasCurrentDbObj.tx2bias, _ = strconv.ParseFloat("NaN", 64) | ||
| } | ||
| if transceiverDomSensorTable.Get("tx3bias") != "N/A" { | ||
| compTransceiverPhysicalChannelStateLaserBiasCurrentDbObj.tx3bias, _ = strconv.ParseFloat(transceiverDomSensorTable.Get("tx3bias"), 64) | ||
| } else { | ||
| compTransceiverPhysicalChannelStateLaserBiasCurrentDbObj.tx3bias, _ = strconv.ParseFloat("NaN", 64) | ||
| } | ||
| if transceiverDomSensorTable.Get("tx4bias") != "N/A" { | ||
| compTransceiverPhysicalChannelStateLaserBiasCurrentDbObj.tx4bias, _ = strconv.ParseFloat(transceiverDomSensorTable.Get("tx4bias"), 64) | ||
| } else { | ||
| compTransceiverPhysicalChannelStateLaserBiasCurrentDbObj.tx4bias, _ = strconv.ParseFloat("NaN", 64) | ||
| } | ||
| if transceiverDomSensorTable.Get("tx5bias") != "N/A" { | ||
| compTransceiverPhysicalChannelStateLaserBiasCurrentDbObj.tx5bias, _ = strconv.ParseFloat(transceiverDomSensorTable.Get("tx5bias"), 64) | ||
| } else { | ||
| compTransceiverPhysicalChannelStateLaserBiasCurrentDbObj.tx5bias, _ = strconv.ParseFloat("NaN", 64) | ||
| } | ||
| if transceiverDomSensorTable.Get("tx6bias") != "N/A" { | ||
| compTransceiverPhysicalChannelStateLaserBiasCurrentDbObj.tx6bias, _ = strconv.ParseFloat(transceiverDomSensorTable.Get("tx6bias"), 64) | ||
| } else { | ||
| compTransceiverPhysicalChannelStateLaserBiasCurrentDbObj.tx6bias, _ = strconv.ParseFloat("NaN", 64) | ||
| } | ||
| if transceiverDomSensorTable.Get("tx7bias") != "N/A" { | ||
| compTransceiverPhysicalChannelStateLaserBiasCurrentDbObj.tx7bias, _ = strconv.ParseFloat(transceiverDomSensorTable.Get("tx7bias"), 64) | ||
| } else { | ||
| compTransceiverPhysicalChannelStateLaserBiasCurrentDbObj.tx7bias, _ = strconv.ParseFloat("NaN", 64) | ||
| } | ||
| if transceiverDomSensorTable.Get("tx8bias") != "N/A" { | ||
| compTransceiverPhysicalChannelStateLaserBiasCurrentDbObj.tx8bias, _ = strconv.ParseFloat(transceiverDomSensorTable.Get("tx8bias"), 64) | ||
| } else { | ||
| compTransceiverPhysicalChannelStateLaserBiasCurrentDbObj.tx8bias, _ = strconv.ParseFloat("NaN", 64) | ||
| } | ||
|
|
||
| return compTransceiverPhysicalChannelStateLaserBiasCurrentDbObj | ||
| } | ||
|
|
||
| func (app *PlatformApp) getCompTransceiverPhysicalChannelStateLaserBiasCurrentFromDb(oc_val *ocbinds.OpenconfigPlatform_Components_Component_Transceiver_PhysicalChannels_Channel_State_LaserBiasCurrent, all bool, compName string, laneIndex uint16) error { | ||
| log.Infof("getCompTransceiverPhysicalChannelStateLaserBiasCurrentFromDb Enter compName=%s laneIndex=%d", compName, laneIndex) | ||
|
|
||
| ifName := strings.Replace(compName, "transceiver_", "", -1) | ||
| compTransceiverPhysicalChannelStateLaserBiasCurrentDb := app.getCompTransceiverPhysicalChannelStateLaserBiasCurrentDbObj(ifName) | ||
|
|
||
| targetUriPath, _ := getYangPathFromUri(app.path.Path) | ||
|
|
||
| if all || targetUriPath == "/openconfig-platform:components/component/openconfig-platform-transceiver:transceiver/physical-channels/channel/state/laser-bias-current/instant" { | ||
| switch laneIndex { | ||
| case 0: | ||
| transceiverDomSensorTable := app.transceiverDomSensorTable[ifName].entry | ||
| if transceiverDomSensorTable.Has("tx1bias") { | ||
| tx1bias := math.Floor(compTransceiverPhysicalChannelStateLaserBiasCurrentDb.tx1bias*fractionDigits2) / fractionDigits2 | ||
| oc_val.Instant = &tx1bias | ||
| } | ||
| case 1: | ||
| transceiverDomSensorTable := app.transceiverDomSensorTable[ifName].entry | ||
| if transceiverDomSensorTable.Has("tx2bias") { | ||
| tx2bias := math.Floor(compTransceiverPhysicalChannelStateLaserBiasCurrentDb.tx2bias*fractionDigits2) / fractionDigits2 | ||
| oc_val.Instant = &tx2bias | ||
| } | ||
| case 2: | ||
| transceiverDomSensorTable := app.transceiverDomSensorTable[ifName].entry | ||
| if transceiverDomSensorTable.Has("tx3bias") { | ||
| tx3bias := math.Floor(compTransceiverPhysicalChannelStateLaserBiasCurrentDb.tx3bias*fractionDigits2) / fractionDigits2 | ||
| oc_val.Instant = &tx3bias | ||
| } | ||
| case 3: | ||
| transceiverDomSensorTable := app.transceiverDomSensorTable[ifName].entry | ||
| if transceiverDomSensorTable.Has("tx4bias") { | ||
| tx4bias := math.Floor(compTransceiverPhysicalChannelStateLaserBiasCurrentDb.tx4bias*fractionDigits2) / fractionDigits2 | ||
| oc_val.Instant = &tx4bias | ||
| } | ||
| case 4: | ||
| transceiverDomSensorTable := app.transceiverDomSensorTable[ifName].entry | ||
| if transceiverDomSensorTable.Has("tx5bias") { | ||
| tx5bias := math.Floor(compTransceiverPhysicalChannelStateLaserBiasCurrentDb.tx5bias*fractionDigits2) / fractionDigits2 | ||
| oc_val.Instant = &tx5bias | ||
| } | ||
| case 5: | ||
| transceiverDomSensorTable := app.transceiverDomSensorTable[ifName].entry | ||
| if transceiverDomSensorTable.Has("tx6bias") { | ||
| tx6bias := math.Floor(compTransceiverPhysicalChannelStateLaserBiasCurrentDb.tx6bias*fractionDigits2) / fractionDigits2 | ||
| oc_val.Instant = &tx6bias | ||
| } | ||
| case 6: | ||
| transceiverDomSensorTable := app.transceiverDomSensorTable[ifName].entry | ||
| if transceiverDomSensorTable.Has("tx7bias") { | ||
| tx7bias := math.Floor(compTransceiverPhysicalChannelStateLaserBiasCurrentDb.tx7bias*fractionDigits2) / fractionDigits2 | ||
| oc_val.Instant = &tx7bias | ||
| } | ||
| case 7: | ||
| transceiverDomSensorTable := app.transceiverDomSensorTable[ifName].entry | ||
| if transceiverDomSensorTable.Has("tx8bias") { | ||
| tx8bias := math.Floor(compTransceiverPhysicalChannelStateLaserBiasCurrentDb.tx8bias*fractionDigits2) / fractionDigits2 | ||
| oc_val.Instant = &tx8bias | ||
| } | ||
| } | ||
| } | ||
|
|
||
| return nil | ||
| } | ||
|
|
||
| type CompTransceiverThresholdStateDb struct { | ||
| temphighalarm float64 | ||
| templowalarm float64 | ||
| vcchighalarm float64 | ||
| vcclowalarm float64 | ||
| temphighwarning float64 | ||
| templowwarning float64 | ||
| vcchighwarning float64 | ||
| vcclowwarning float64 | ||
| txpowerhighalarm float64 | ||
| txpowerlowalarm float64 | ||
| rxpowerhighalarm float64 | ||
| rxpowerlowalarm float64 | ||
| txbiashighalarm float64 | ||
| txbiaslowalarm float64 | ||
| txpowerhighwarning float64 | ||
| txpowerlowwarning float64 | ||
| rxpowerhighwarning float64 | ||
| rxpowerlowwarning float64 | ||
| txbiashighwarning float64 | ||
| txbiaslowwarning float64 | ||
| } | ||
|
|
||
| func (app *PlatformApp) getCompTransceiverThresholdStateDbObj(ifName string) CompTransceiverThresholdStateDb { | ||
| log.Infof("parseCompTransceiverThresholdStateDb Enter ifName=%s", ifName) | ||
|
|
||
| var compTransceiverThresholdStateDbObj CompTransceiverThresholdStateDb | ||
|
|
||
| transceiverDomThresholdTable := app.transceiverDomThresholdTable[ifName].entry | ||
|
|
||
| compTransceiverThresholdStateDbObj.temphighalarm, _ = strconv.ParseFloat(transceiverDomThresholdTable.Get("temphighalarm"), 64) | ||
| compTransceiverThresholdStateDbObj.templowalarm, _ = strconv.ParseFloat(transceiverDomThresholdTable.Get("templowalarm"), 64) | ||
| compTransceiverThresholdStateDbObj.vcchighalarm, _ = strconv.ParseFloat(transceiverDomThresholdTable.Get("vcchighalarm"), 64) | ||
| compTransceiverThresholdStateDbObj.vcclowalarm, _ = strconv.ParseFloat(transceiverDomThresholdTable.Get("vcclowalarm"), 64) | ||
| compTransceiverThresholdStateDbObj.temphighwarning, _ = strconv.ParseFloat(transceiverDomThresholdTable.Get("temphighwarning"), 64) | ||
| compTransceiverThresholdStateDbObj.templowwarning, _ = strconv.ParseFloat(transceiverDomThresholdTable.Get("templowwarning"), 64) | ||
| compTransceiverThresholdStateDbObj.vcchighwarning, _ = strconv.ParseFloat(transceiverDomThresholdTable.Get("vcchighwarning"), 64) | ||
| compTransceiverThresholdStateDbObj.vcclowwarning, _ = strconv.ParseFloat(transceiverDomThresholdTable.Get("vcclowwarning"), 64) | ||
| compTransceiverThresholdStateDbObj.txpowerhighalarm, _ = strconv.ParseFloat(transceiverDomThresholdTable.Get("txpowerhighalarm"), 64) | ||
| compTransceiverThresholdStateDbObj.txpowerlowalarm, _ = strconv.ParseFloat(transceiverDomThresholdTable.Get("txpowerlowalarm"), 64) | ||
| compTransceiverThresholdStateDbObj.rxpowerhighalarm, _ = strconv.ParseFloat(transceiverDomThresholdTable.Get("rxpowerhighalarm"), 64) | ||
| compTransceiverThresholdStateDbObj.rxpowerlowalarm, _ = strconv.ParseFloat(transceiverDomThresholdTable.Get("rxpowerlowalarm"), 64) | ||
| compTransceiverThresholdStateDbObj.txbiashighalarm, _ = strconv.ParseFloat(transceiverDomThresholdTable.Get("txbiashighalarm"), 64) | ||
| compTransceiverThresholdStateDbObj.txbiaslowalarm, _ = strconv.ParseFloat(transceiverDomThresholdTable.Get("txbiaslowalarm"), 64) | ||
| compTransceiverThresholdStateDbObj.txpowerhighwarning, _ = strconv.ParseFloat(transceiverDomThresholdTable.Get("txpowerhighwarning"), 64) | ||
| compTransceiverThresholdStateDbObj.txpowerlowwarning, _ = strconv.ParseFloat(transceiverDomThresholdTable.Get("txpowerlowwarning"), 64) | ||
| compTransceiverThresholdStateDbObj.rxpowerhighwarning, _ = strconv.ParseFloat(transceiverDomThresholdTable.Get("rxpowerhighwarning"), 64) | ||
| compTransceiverThresholdStateDbObj.rxpowerlowwarning, _ = strconv.ParseFloat(transceiverDomThresholdTable.Get("rxpowerlowwarning"), 64) | ||
| compTransceiverThresholdStateDbObj.txbiashighwarning, _ = strconv.ParseFloat(transceiverDomThresholdTable.Get("txbiashighwarning"), 64) | ||
| compTransceiverThresholdStateDbObj.txbiaslowwarning, _ = strconv.ParseFloat(transceiverDomThresholdTable.Get("txbiaslowwarning"), 64) | ||
|
|
||
| return compTransceiverThresholdStateDbObj | ||
| } | ||
|
|
||
| func (app *PlatformApp) getCompTransceiverThresholdStateFromDb(oc_val *ocbinds.OpenconfigPlatform_Components_Component_Transceiver_Thresholds_Threshold_State, all bool, compName string, severityName string) error { | ||
| log.Infof("getCompTransceiverThresholdStateFromDb Enter compName=%s severityName=%s", compName, severityName) | ||
|
|
||
| ifName := strings.Replace(compName, "transceiver_", "", -1) | ||
| compTransceiverThresholdStateDb := app.getCompTransceiverThresholdStateDbObj(ifName) | ||
|
|
||
| targetUriPath, _ := getYangPathFromUri(app.path.Path) | ||
|
|
||
| if severityName == "CRITICAL" { | ||
| if all || targetUriPath == "/openconfig-platform:components/component/openconfig-platform-transceiver:transceiver/thresholds/threshold/state/laser-temperature-upper" { | ||
| transceiverDomThresholdTable := app.transceiverDomThresholdTable[ifName].entry | ||
| if transceiverDomThresholdTable.Has("temphighalarm") { | ||
| temphighalarm := math.Floor(compTransceiverThresholdStateDb.temphighalarm*fractionDigits1) / fractionDigits1 | ||
| oc_val.LaserTemperatureUpper = &temphighalarm | ||
| } | ||
| } | ||
| if all || targetUriPath == "/openconfig-platform:components/component/openconfig-platform-transceiver:transceiver/thresholds/threshold/state/laser-temperature-lower" { | ||
| transceiverDomThresholdTable := app.transceiverDomThresholdTable[ifName].entry | ||
| if transceiverDomThresholdTable.Has("templowalarm") { | ||
| templowalarm := math.Floor(compTransceiverThresholdStateDb.templowalarm*fractionDigits1) / fractionDigits1 | ||
| oc_val.LaserTemperatureLower = &templowalarm | ||
| } | ||
| } | ||
| if all || targetUriPath == "/openconfig-platform:components/component/openconfig-platform-transceiver:transceiver/thresholds/threshold/state/supply-voltage-upper" { | ||
| transceiverDomThresholdTable := app.transceiverDomThresholdTable[ifName].entry | ||
| if transceiverDomThresholdTable.Has("vcchighalarm") { | ||
| vcchighalarm := math.Floor(compTransceiverThresholdStateDb.vcchighalarm*fractionDigits2) / fractionDigits2 | ||
| oc_val.SupplyVoltageUpper = &vcchighalarm | ||
| } | ||
| } | ||
| if all || targetUriPath == "/openconfig-platform:components/component/openconfig-platform-transceiver:transceiver/thresholds/threshold/state/supply-voltage-lower" { | ||
| transceiverDomThresholdTable := app.transceiverDomThresholdTable[ifName].entry | ||
| if transceiverDomThresholdTable.Has("vcclowalarm") { | ||
| vcclowalarm := math.Floor(compTransceiverThresholdStateDb.vcclowalarm*fractionDigits2) / fractionDigits2 | ||
| oc_val.SupplyVoltageLower = &vcclowalarm | ||
| } | ||
| } | ||
| if all || targetUriPath == "/openconfig-platform:components/component/openconfig-platform-transceiver:transceiver/thresholds/threshold/state/output-power-upper" { | ||
| transceiverDomThresholdTable := app.transceiverDomThresholdTable[ifName].entry | ||
| if transceiverDomThresholdTable.Has("txpowerhighalarm") { | ||
| txpowerhighalarm := math.Floor(compTransceiverThresholdStateDb.txpowerhighalarm*fractionDigits2) / fractionDigits2 | ||
| oc_val.OutputPowerUpper = &txpowerhighalarm | ||
| } | ||
| } | ||
| if all || targetUriPath == "/openconfig-platform:components/component/openconfig-platform-transceiver:transceiver/thresholds/threshold/state/output-power-lower" { | ||
| transceiverDomThresholdTable := app.transceiverDomThresholdTable[ifName].entry | ||
| if transceiverDomThresholdTable.Has("txpowerlowalarm") { | ||
| txpowerlowalarm := math.Floor(compTransceiverThresholdStateDb.txpowerlowalarm*fractionDigits2) / fractionDigits2 | ||
| oc_val.OutputPowerLower = &txpowerlowalarm | ||
| } | ||
| } | ||
| if all || targetUriPath == "/openconfig-platform:components/component/openconfig-platform-transceiver:transceiver/thresholds/threshold/state/input-power-upper" { | ||
| transceiverDomThresholdTable := app.transceiverDomThresholdTable[ifName].entry | ||
| if transceiverDomThresholdTable.Has("rxpowerhighalarm") { | ||
| rxpowerhighalarm := math.Floor(compTransceiverThresholdStateDb.rxpowerhighalarm*fractionDigits2) / fractionDigits2 | ||
| oc_val.InputPowerUpper = &rxpowerhighalarm | ||
| } | ||
| } | ||
| if all || targetUriPath == "/openconfig-platform:components/component/openconfig-platform-transceiver:transceiver/thresholds/threshold/state/input-power-lower" { | ||
| transceiverDomThresholdTable := app.transceiverDomThresholdTable[ifName].entry | ||
| if transceiverDomThresholdTable.Has("rxpowerlowalarm") { | ||
| rxpowerlowalarm := math.Floor(compTransceiverThresholdStateDb.rxpowerlowalarm*fractionDigits2) / fractionDigits2 | ||
| oc_val.InputPowerLower = &rxpowerlowalarm | ||
| } | ||
| } | ||
| if all || targetUriPath == "/openconfig-platform:components/component/openconfig-platform-transceiver:transceiver/thresholds/threshold/state/laser-bias-current-upper" { | ||
| transceiverDomThresholdTable := app.transceiverDomThresholdTable[ifName].entry | ||
| if transceiverDomThresholdTable.Has("txbiashighalarm") { | ||
| txbiashighalarm := math.Floor(compTransceiverThresholdStateDb.txbiashighalarm*fractionDigits2) / fractionDigits2 | ||
| oc_val.LaserBiasCurrentUpper = &txbiashighalarm | ||
| } | ||
| } | ||
| if all || targetUriPath == "/openconfig-platform:components/component/openconfig-platform-transceiver:transceiver/thresholds/threshold/state/laser-bias-current-lower" { | ||
| transceiverDomThresholdTable := app.transceiverDomThresholdTable[ifName].entry | ||
| if transceiverDomThresholdTable.Has("txbiaslowalarm") { | ||
| txbiaslowalarm := math.Floor(compTransceiverThresholdStateDb.txbiaslowalarm*fractionDigits2) / fractionDigits2 | ||
| oc_val.LaserBiasCurrentLower = &txbiaslowalarm | ||
| } | ||
| } | ||
| } | ||
|
|
||
| if severityName == "WARNING" { | ||
| if all || targetUriPath == "/openconfig-platform:components/component/openconfig-platform-transceiver:transceiver/thresholds/threshold/state/laser-temperature-upper" { | ||
| transceiverDomThresholdTable := app.transceiverDomThresholdTable[ifName].entry | ||
| if transceiverDomThresholdTable.Has("temphighwarning") { | ||
| temphighwarning := math.Floor(compTransceiverThresholdStateDb.temphighwarning*fractionDigits1) / fractionDigits1 | ||
| oc_val.LaserTemperatureUpper = &temphighwarning | ||
| } | ||
| } | ||
| if all || targetUriPath == "/openconfig-platform:components/component/openconfig-platform-transceiver:transceiver/thresholds/threshold/state/laser-temperature-lower" { | ||
| transceiverDomThresholdTable := app.transceiverDomThresholdTable[ifName].entry | ||
| if transceiverDomThresholdTable.Has("templowwarning") { | ||
| templowwarning := math.Floor(compTransceiverThresholdStateDb.templowwarning*fractionDigits1) / fractionDigits1 | ||
| oc_val.LaserTemperatureLower = &templowwarning | ||
| } | ||
| } | ||
| if all || targetUriPath == "/openconfig-platform:components/component/openconfig-platform-transceiver:transceiver/thresholds/threshold/state/supply-voltage-upper" { | ||
| transceiverDomThresholdTable := app.transceiverDomThresholdTable[ifName].entry | ||
| if transceiverDomThresholdTable.Has("vcchighwarning") { | ||
| vcchighwarning := math.Floor(compTransceiverThresholdStateDb.vcchighwarning*fractionDigits2) / fractionDigits2 | ||
| oc_val.SupplyVoltageUpper = &vcchighwarning | ||
| } | ||
| } | ||
| if all || targetUriPath == "/openconfig-platform:components/component/openconfig-platform-transceiver:transceiver/thresholds/threshold/state/supply-voltage-lower" { | ||
| transceiverDomThresholdTable := app.transceiverDomThresholdTable[ifName].entry | ||
| if transceiverDomThresholdTable.Has("vcclowwarning") { | ||
| vcclowwarning := math.Floor(compTransceiverThresholdStateDb.vcclowwarning*fractionDigits2) / fractionDigits2 | ||
| oc_val.SupplyVoltageLower = &vcclowwarning | ||
| } | ||
| } | ||
| if all || targetUriPath == "/openconfig-platform:components/component/openconfig-platform-transceiver:transceiver/thresholds/threshold/state/output-power-upper" { | ||
| transceiverDomThresholdTable := app.transceiverDomThresholdTable[ifName].entry | ||
| if transceiverDomThresholdTable.Has("txpowerhighwarning") { | ||
| v := math.Floor(compTransceiverThresholdStateDb.txpowerhighwarning*fractionDigits2) / fractionDigits2 | ||
| oc_val.OutputPowerUpper = &v | ||
| } | ||
| } | ||
| if all || targetUriPath == "/openconfig-platform:components/component/openconfig-platform-transceiver:transceiver/thresholds/threshold/state/output-power-lower" { | ||
| transceiverDomThresholdTable := app.transceiverDomThresholdTable[ifName].entry | ||
| if transceiverDomThresholdTable.Has("txpowerlowwarning") { | ||
| v := math.Floor(compTransceiverThresholdStateDb.txpowerlowwarning*fractionDigits2) / fractionDigits2 | ||
| oc_val.OutputPowerLower = &v | ||
| } | ||
| } | ||
| if all || targetUriPath == "/openconfig-platform:components/component/openconfig-platform-transceiver:transceiver/thresholds/threshold/state/input-power-upper" { | ||
| transceiverDomThresholdTable := app.transceiverDomThresholdTable[ifName].entry | ||
| if transceiverDomThresholdTable.Has("rxpowerhighwarning") { | ||
| v := math.Floor(compTransceiverThresholdStateDb.rxpowerhighwarning*fractionDigits2) / fractionDigits2 | ||
| oc_val.InputPowerUpper = &v | ||
| } | ||
| } | ||
| if all || targetUriPath == "/openconfig-platform:components/component/openconfig-platform-transceiver:transceiver/thresholds/threshold/state/input-power-lower" { | ||
| transceiverDomThresholdTable := app.transceiverDomThresholdTable[ifName].entry | ||
| if transceiverDomThresholdTable.Has("rxpowerlowwarning") { | ||
| v := math.Floor(compTransceiverThresholdStateDb.rxpowerlowwarning*fractionDigits2) / fractionDigits2 | ||
| oc_val.InputPowerLower = &v | ||
| } | ||
| } | ||
| if all || targetUriPath == "/openconfig-platform:components/component/openconfig-platform-transceiver:transceiver/thresholds/threshold/state/laser-bias-current-upper" { | ||
| transceiverDomThresholdTable := app.transceiverDomThresholdTable[ifName].entry | ||
| if transceiverDomThresholdTable.Has("txbiashighwarning") { | ||
| v := math.Floor(compTransceiverThresholdStateDb.txbiashighwarning*fractionDigits2) / fractionDigits2 | ||
| oc_val.LaserBiasCurrentUpper = &v | ||
| } | ||
| } | ||
| if all || targetUriPath == "/openconfig-platform:components/component/openconfig-platform-transceiver:transceiver/thresholds/threshold/state/laser-bias-current-lower" { | ||
| transceiverDomThresholdTable := app.transceiverDomThresholdTable[ifName].entry | ||
| if transceiverDomThresholdTable.Has("txbiaslowwarning") { | ||
| v := math.Floor(compTransceiverThresholdStateDb.txbiaslowwarning*fractionDigits2) / fractionDigits2 | ||
| oc_val.LaserBiasCurrentLower = &v | ||
| } | ||
| } | ||
| } | ||
|
|
||
| return nil | ||
| } |
There was a problem hiding this comment.
The new transceiver functionality introduced in this PR lacks test coverage. No test cases have been added for the new transceiver-related functions and database operations. Add comprehensive test coverage for the new transceiver state, physical channels, and threshold functions to match the testing pattern established for System EEPROM.
| pf_cpts := app.getAppRootObject() | ||
| var compStateDbObj CompStateDb | ||
|
|
||
| transceiverInfoTable := app.transceiverInfoTable[ifName].entry |
There was a problem hiding this comment.
Potential nil pointer dereference: the map lookup app.transceiverInfoTable[ifName] may not exist, and accessing .entry on the zero value will panic. Add a check to verify the key exists in the map before accessing the entry.
|
@nakano-omw Can you take a look at the copilot comments. Some of these such as regarding duplicated code are quite valid. |
|
@hdwhdw I'm currently reviewing the comments and working on the code fixes |
|
@nakano-omw Thanks. I think there are unit test files https://github.com/sonic-net/sonic-mgmt-common/blob/master/translib/pfm_app_test.go so we can take advantage of that. Also feel free to break these long logic into separate files. |
Address review comments on PR sonic-net#201: the CompTransceiverStateDb struct used snake_case fields (Vendor_Oui, Vendor_Rev, Vendor_Date) which violate Go naming conventions. Rename to VendorOui, VendorRev, VendorDate and update all references. Also add an inline comment on the vendor-part code path documenting that sourcing it from TRANSCEIVER_INFO.vendor_oui is intentional and follows the HLD's DB mapping table (sonic-net/SONiC PR #1858, Section 4 "Mapping between Openconfig YANG and Redis DB" Table 2), to avoid future reviewers re-raising the question. Signed-off-by: Kanji Nakano <kanji.nakano@ntt.com>
Address review comments on PR sonic-net#201 (maintainer-endorsed "very valid" on the output-power instance, plus systemic equivalents for input-power and laser-bias-current): - CompTransceiverPhysicalChannelStateOutputPowerDb - CompTransceiverPhysicalChannelStateInputPowerDb - CompTransceiverPhysicalChannelStateLaserBiasCurrentDb Each struct previously held eight identically-named float64 fields (tx1power..tx8power, rx1power..rx8power, tx1bias..tx8bias). The DbObj parser unrolled eight ParseFloat calls and the FromDb getter unrolled an eight-case switch that differed only in the field name. Replace each struct with a single fixed-size array of eight float64 values (TxPower / RxPower / TxBias). The parser becomes a for loop that builds the field name with fmt.Sprintf, and the getter indexes the array by laneIndex with a single bounds check. Net change is -220 / +32 lines and removes the lowercase struct fields that also violated Go naming conventions. For LaserBiasCurrent, preserve the existing N/A -> NaN handling by keeping the per-lane N/A check inside the loop, and switch from strconv.ParseFloat("NaN", 64) to math.NaN() for clarity. Signed-off-by: Kanji Nakano <kanji.nakano@ntt.com>
Address review comment on PR sonic-net#201: CompTransceiverThresholdStateDb held 20 float64 fields with lowercase names (temphighalarm, templowalarm, vcchighalarm, ..., txbiaslowwarning), which violate Go naming conventions for struct fields. Rename them to PascalCase (TempHighAlarm, TempLowAlarm, VccHighAlarm, ...) and update both the parser assignments and the getter struct-field accesses. The DB field name strings ("temphighalarm" etc.) are left unchanged since they are the on-wire Redis keys defined by xcvrd, not Go identifiers. Local variables inside the FromDb getter (used purely as a stable address for a pointer take) also stay lowercase since short-scoped locals do not need to follow exported-field conventions. Signed-off-by: Kanji Nakano <kanji.nakano@ntt.com>
Address review comment on PR sonic-net#201 (maintainer-endorsed): the new OpenConfig Platform Transceiver feature in translib/pfm_app.go had no test coverage. Extend pfm_app_test.go with: - createTransceiverFactoryDb / clearTransceiverDataFromDb helpers that load and tear down STATE_DB fixtures for TRANSCEIVER_INFO, TRANSCEIVER_DOM_SENSOR and TRANSCEIVER_DOM_THRESHOLD using the same db.SetEntry pattern as the existing EEPROM_INFO fixture. - Test_PfmApp_TransceiverState which exercises the transceiver state subtree (serial-no, vendor, vendor-part, vendor-rev, date-code, connector-type, supply-voltage) and the CRITICAL / WARNING thresholds against a populated Ethernet0 transceiver fixture. Assertions are scoped to "GET returns without error", which is the regression guard for the handler reaching completion against valid input. - Test_PfmApp_TransceiverState_Missing which queries the same paths against a non-existent component (transceiver_EthernetMissing) and verifies the handler does not panic. This is a regression guard for the map-lookup nil-pointer concerns raised by Copilot's auto-review on PR sonic-net#201 (the actual map-safety helpers will follow in a separate patch). Fixtures are loaded inside each test and torn down via t.Cleanup so the existing Test_PfmApp_TopLevelPath bulk EEPROM test is not affected by run ordering. Strict JSON-equality assertions on the transceiver subtree are intentionally deferred until the encoding/precision of float and enum fields can be observed against a real run. Signed-off-by: Kanji Nakano <kanji.nakano@ntt.com>
Address review comments on PR sonic-net#201 that flagged the raw app.<X>Table[ifName].entry pattern at every DbObj parser entry (serial-no, transceiver state, supply-voltage, laser-temperature, output-power, input-power, laser-bias-current, threshold) and at fourteen sites inside doGetPlatformInfo for applPortTable. The cached maps store dbEntry values (not pointers), so a missing key returns a zero-value dbEntry whose .entry.Field map is nil. .Has and .Get on a nil Field map return false / "" rather than panicking, so the existing code was not literally crashing -- but silently treating "no entry" as "entry with every field absent" made the missing-row case invisible at runtime and reads as fragile to a reviewer. Introduce four small helpers: getTransceiverInfoEntry(ifName) -> (db.Value, bool) getTransceiverDomSensorEntry(ifName) -> (db.Value, bool) getTransceiverDomThresholdEntry(ifName) -> (db.Value, bool) getApplPortEntry(ifName) -> (db.Value, bool) Each wraps the underlying map indexing and reports whether the interface was actually present. Update each get*DbObj parser to call the helper, log a Warningf on missing entry, and short-circuit with a sensible zero / NaN result. For applPortTable, all fourteen doGetPlatformInfo call sites now go through getApplPortEntry; the ok value is currently discarded because the existing follow-on logic (.Get("lanes"), strings.Split, ...) is already missing-tolerant and dedicated error handling for the empty/missing case is the subject of a separate patch in this series. The per-branch transceiver*Table lookups inside the get*FromDb getters were not flagged by review and are left as-is in this patch; they will go through the helper once the doGetPlatformInfo split hoists the lookup into a single call per request. Signed-off-by: Kanji Nakano <kanji.nakano@ntt.com>
Address review comment on PR sonic-net#201: pfm_app.go had grown to roughly 2100 lines, dominated by the OpenConfig Platform Transceiver getters that were appended for sonic-net#201. Per the maintainer's note that breaking the new logic into separate files is acceptable, move the transceiver Db-struct types and getCompTransceiver* getters into a new translib/pfm_app_transceiver.go in the same package. What stays in pfm_app.go: - PlatformApp struct, init / translate* / process* - The four map-lookup helpers (getTransceiverInfoEntry, getTransceiverDomSensorEntry, getTransceiverDomThresholdEntry, getApplPortEntry) so callers across both files can share them - getCompStateDbObj / getCompStateFromDb (System Component state) - doGetPlatformInfo, which continues to be the single dispatch entry point and now calls into the transceiver getters located in the new file What moves to pfm_app_transceiver.go: - CompTransceiverStateDb / CompTransceiverStateSupplyVoltageDb / CompTransceiverPhysicalChannelState{Laser{Temperature, BiasCurrent}, OutputPower, InputPower}Db / CompTransceiverThresholdStateDb - getCompTransceiverStateDbObj / getCompTransceiverStateFromDb - getCompTransceiverStateSupplyVoltage{DbObj, FromDb} - getCompTransceiverPhysicalChannelStateLaserTemperature{DbObj, FromDb} - getCompTransceiverPhysicalChannelStateOutputPower{DbObj, FromDb} - getCompTransceiverPhysicalChannelStateInputPower{DbObj, FromDb} - getCompTransceiverPhysicalChannelStateLaserBiasCurrent{DbObj, FromDb} - getCompTransceiverThresholdState{DbObj, FromDb} This is purely a file-organisation change: no symbol is renamed, no logic is altered. pfm_app.go drops from ~1990 to ~1440 lines, and the new file is ~580 lines. Drop the now-unused math, regexp and (already-unused) reflect-adjacent imports from pfm_app.go's import block. pfm_app_transceiver.go has its own minimal import block (fmt, math, regexp, strconv, strings, ocbinds, glog). doGetPlatformInfo itself remains long; further extraction by URI pattern is out of scope for this patch and will be a follow-up. Signed-off-by: Kanji Nakano <kanji.nakano@ntt.com>
Address review comments on PR sonic-net#201 (C07 line 689, C09 line 726): SupplyVoltage and LaserTemperature DbObj parsers ignored the error returned by strconv.ParseFloat, so a malformed STATE_DB value (anything that is not "N/A" but also not a parseable float) silently became the float64 zero value and was indistinguishable from a real 0.0 V / 0.0 C reading. Switch both parsers to the explicit form Copilot suggested: when parsing fails, log a Warning with the offending value and store math.NaN(). The "N/A" sentinel still maps directly to NaN as before, matching the FromDb consumer's existing Has() guard. Signed-off-by: Kanji Nakano <kanji.nakano@ntt.com>
Address review comments on PR sonic-net#201 (C20 line 1326, C21 line 1327): fourteen sites in doGetPlatformInfo iterate the comma-separated APPL_DB PORT_TABLE.lanes value and call strconv.ParseUint(lane, 10, 16) with the error discarded. On a malformed lane string the call returns 0, which the existing code then maps to lane index 0 and silently mis-attributes channel data to the wrong physical channel. An empty PORT_TABLE.lanes value (strings.Split returns [""]) hits the same path and ParseUint("") fails for the same reason. Capture ParseUint's error into a fresh local parseErr (not the function-level err, which the surrounding loop body uses to propagate FromDb failures via break), log it with the offending lane and ifName, and continue to the next entry. Empty-lanes is implicitly covered by the same continue (ParseUint on "" fails). Signed-off-by: Kanji Nakano <kanji.nakano@ntt.com>
Address review comment on PR sonic-net#201 (C22): in doGetPlatformInfo the ten call sites of getCompTransceiverPhysicalChannelStateLaserBiasCurrentFromDb ignored the returned error, while the preceding calls to *OutputPower* and *InputPower* checked the same return and broke out of the enclosing loop. The asymmetry meant a bias-current fetch failure would silently leave the per-lane oc_val partially populated and let the outer for loop continue with stale or empty data. Mirror the existing pattern by checking err and breaking from the enclosing for loop on failure, so all three physical-channel getters now propagate errors consistently. Signed-off-by: Kanji Nakano <kanji.nakano@ntt.com>
Address review comment on PR sonic-net#201 (C05): the date-code extractor applied a YYYY-MM-DD regex that constrained month to 01-12 and day to 01-31 but did NOT validate the day against the actual length of the month. Calendar impossibilities such as 2024-02-30 or 2024-04-31 passed validation and were emitted unchanged to oc_val.DateCode. Replace the second regex-based validation with time.Parse on the "2006-01-02" layout, which natively rejects month/day combinations that do not exist. On success, reformat to the existing RFC 3339-ish output (...T00:00:00.000Z); on failure log a warning with the original string and skip the field, matching the prior behavior of leaving DateCode unset for unparseable input. The leading regex that extracts three digit groups from the raw STATE_DB value is retained because xcvrd writes vendor_date with a trailing time portion (e.g. "2024-01-01 00:00:00") and the extraction is the simplest tolerant way to pick out the date prefix. Signed-off-by: Kanji Nakano <kanji.nakano@ntt.com>
|
/azp run |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
OpenConfig support for Platform Transceiver.
sonic-net/SONiC#1858
The HLD has already been reviewed in the UMF WG.
Add support for following features: