ipmi

package
v0.12.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 8, 2025 License: GPL-3.0 Imports: 11 Imported by: 0

Documentation

Overview

Package ipmi implements in-band communication with BMC using IPMI commands using `/dev/ipmi*` device.

Index

Constants

View Source
const (
	IPMICTL_SET_GETS_EVENTS_CMD     = 0x80046910 //nolint:stylecheck
	IPMICTL_SEND_COMMAND            = 0x8028690d //nolint:stylecheck
	IPMICTL_RECEIVE_MSG_TRUNC       = 0xc030690b //nolint:stylecheck
	IPMI_SYSTEM_INTERFACE_ADDR_TYPE = 0xC        //nolint:stylecheck
	IPMI_BMC_CHANNEL                = 0xF        //nolint:stylecheck
)

IPMI related constants.

View Source
const (
	IPMI_DCMI           = 0xDC //nolint:stylecheck
	IPMI_DCMI_GETRED    = 0x2  //nolint:stylecheck
	IPMI_NETFN_DCGRP    = 0x2C //nolint:stylecheck
	IPMI_DCMI_ACTIVATED = 0x40 //nolint:stylecheck
)

IPMI DCMI related constants.

View Source
const (
	IPMI_LAN             = 0x1 //nolint:stylecheck
	IPMI_LANP_IP_ADDR    = 0x2 //nolint:stylecheck
	IPMI_NETFN_TRANSPORT = 0xC //nolint:stylecheck
)

IPMI DCMI related constants.

View Source
const (
	IPMI_SENSOR_RECORD_CMD    = 0x23 //nolint:stylecheck
	IPMI_SENSOR_RECORD_NETFN  = 0xa  //nolint:stylecheck
	IPMI_SENSOR_READING_CMD   = 0x2d //nolint:stylecheck
	IPMI_SENSOR_READING_NETFN = 0x4  //nolint:stylecheck
)

IPMI sensor related constants.

View Source
const (
	// NFDBits is the amount of bits per mask.
	NFDBits = 8 * 8
)

Variables

View Source
var (
	// ErrNotLinearised is returned if Lineariser() is called on a linear or
	// non-linear linearisation. Linear sensors' values do not require any
	// transformation by virtue of the sensor already being linear. If the sensor
	// is non-linear, the conversion factors returned by Get Sensor Reading
	// Factors are all that are needed to obtain a real value: by being unique
	// to the raw sensor reading, there is no need for a separate linearisation
	// formula.
	//
	// Linearise() could return a no-op lineariser, however the current
	// implementation should never ask for one on a non-linearised sensor, so
	// instead we return an error to flag up a possible bug.
	ErrNotLinearised = errors.New(
		"only linearised sensors have a linearisation formula")
)

Functions

func FDClr

func FDClr(fd uintptr, p *unix.FdSet)

FDClr clear a fd of fdSet.

func FDIsSet

func FDIsSet(fd uintptr, p *unix.FdSet) bool

FDIsSet return true if fd is set.

func FDSet

func FDSet(fd uintptr, p *unix.FdSet)

FDSet set a fd of fdSet.

func FDZero

func FDZero(p *unix.FdSet)

FDZero set to zero the fdSet.

Types

type Client added in v0.11.0

type Client interface {
	Do(r *Request) (*Response, error)
	Close() error
	DCMIPowerReading() (*PowerReading, error)
	LanIP() (*string, error)
	SensorRecords() ([]*FullSensorRecord, error)
	SensorReadings(records []*FullSensorRecord) (map[*FullSensorRecord]float64, error)
}

func NewClient added in v0.11.0

func NewClient(c *Config) (Client, error)

NewClient returns a new instance of Client struct.

type Config added in v0.11.0

type Config struct {
	Logger  *slog.Logger
	DevNum  int
	Timeout time.Duration
}

type ConversionFactors added in v0.11.0

type ConversionFactors struct {
	// M is the constant multiplier. This is a 10-bit 2's complement number on
	// the wire.
	M int16

	// B is the additive offset. This is a 10-bit 2's complement number on the
	// wire.
	B int16

	// BExp is the exponent, controlling the location of the decimal point in B.
	// This is also referred to as K1 in the spec, and is a 4-bit 2's complement
	// number on the wire.
	BExp int8

	// RExp is the result exponent, controlling the location of the decimal
	// point in the result of the linear formula and hence input to the
	// linearisation function. This is also referred to as K2 in the spec, and
	// is a 4-bit 2's complement number on the wire.
	RExp int8
}

ConversionFactors contains inputs to the linear formula in 30.3 and 36.3 of v1.5 and v2.0 respectively. This struct exists as conversion factors can come from two sources: full sensor records, and the Get Sensor Reading Factors command response. In practice, we get them from the former for linear and linearised sensors, as these have constant factors. We need to obtain them from the Get Sensor Reading Factors command for non-linear sensors, as they vary by reading here. Both FullSensorRecord and GetSensorReadingFactorsRsp embed this type.

Note that we split application of the formula into "conversion" and "linearisation". Conversion happens first, and is the linear formula applied to the raw value. The linearisation step, which is a no-op for linear and non-linear sensors, applies one of the formulae in the specification to the result of the conversion. This struct only deals with conversion; see Lineariser for linearisation.

func (*ConversionFactors) ConvertReading added in v0.11.0

func (f *ConversionFactors) ConvertReading(raw int16) float64

ConvertReading applies the linear formula to a raw sensor reading, without the linearisation formula. It is independent of unit. This method takes an int16 rather than uint8 as raw values can be in 1 or 2's complement, or unsigned, so it must accept from -128 (lowest 2's complement) to 255 (highest unsigned). The conversion from the raw format to a native int must be done before calling this method.

type FullSensorRecord added in v0.11.0

type FullSensorRecord struct {
	ConversionFactors

	// Sensor number that will be used in request to get reading
	Number uint8

	// BaseUnit gives the primary unit of the sensor's reading, e.g. Celsius or
	// Fahrenheit for a temperature sensor.
	BaseUnit SensorUnit

	// ModifierUnit is contained in the Sensor Units 3 field. Note this is
	// distinct from the identically-named 2-bit field in Sensor Units 1. 0x0
	// means unused.
	ModifierUnit SensorUnit

	// Linearisation indicates whether the sensor is linear, linearised or
	// non-linear. This controls post-processing after applying the linear
	// conversion formula to the raw reading.
	Linearisation Linearisation

	// Tolerance gives the absolute accuracy of the sensor in +/- half raw
	// counts. This is a 6-bit uint on the wire.
	Tolerance uint8

	// Accuracy gives the sensor accuracy in 0.01% increments when raised to
	// AccuracyExp. This is a 10-bit int on the wire.
	Accuracy int16

	// AccuracyExp is the quantity Accuracy is raised to the power of to give
	// the final accuracy.
	AccuracyExp uint8

	// Identity is a descriptive string for the sensor. This can be up to 16
	// bytes long, which translates into 16-32 characters depending on the
	// format used. There are no conventions around this, and it is provided for
	// informational purposes only. Contrary to the name, attempting to identify
	// sensors based on this value is doomed to fail.
	Identity string
}

FullSensorRecord is specified in 37.1 and 43.1 of v1.5 and v2.0 respectively. It describes any type of sensor, and is the only record type that can describe a sensor generating analogue (i.e. non-enumerated/discrete) readings, e.g. a temperature sensor. It is specified as 64 bytes. This layer represents the record key and record body sections.

func (*FullSensorRecord) DecodeFromBytes added in v0.11.0

func (r *FullSensorRecord) DecodeFromBytes(data []uint8) error

type Linearisation added in v0.11.0

type Linearisation uint8

Linearisation indicates whether a sensor is linear, linearised, or non-linear. Values are specified in the Full Sensor Record wire format table in 37-1 and 43-1 of v1.5 and v2.0 respectively.

Linear sensors are the easiest to deal with. The sensor's raw readings are converted into real readings (e.g. Celsius) with a linear formula. Accuracy and resolution are constant in real terms across the entire range of values produced by the sensor.

Linearised are slightly more challenging. The same linear formula is applied as for linear sensors, however a final "linearisation formula" is applied to obtain the real reading. This transformation is one of 11 defined in the spec, e.g. log or sqrt, and obviously does not have to be linear itself. The tolerance (the spec misuses accuracy as a synonym) of linearised sensors is also constant for all values. This is possible despite the existence of the linearisation formula turning raw values into disproportionate real values, as tolerance is expressed relative to 0. This assumes the sensor's tolerance does not diminish in real, absolute terms at extreme values (positive or negative), as there is no way of representing it (you'd have to resort to declaring it a non-linear sensor). Note that tolerance can only be expressed in half-raw value increments, which is in itself quite coarse. Regarding resolution, this will vary with reading due to the linearisation formula. The recommended way to calculate it is to retrieve and calculate the real values (with the help of Get Sensor Reading Factors as necessary) corresponding to the raw values below and above the actual raw value observed. Subtracting the real reading for the raw value below the observed raw value from the real reading for the observed value gives the negative resolution, and the process is equivalent for the positive resolution using the raw value one above.

All consistency bets are off with non-linear sensors. Not only does resolution vary by reading (calculated in the same was as for linearised sensors), but so does tolerance. Get Sensor Reading Factors must be sent with each raw reading; applying the linear formula using the returned conversion factors yields the real reading, and can the same factors can be plugged into the tolerance and resolution formulae to calculate them.

const (
	LinearisationLinear Linearisation = iota
	LinearisationLn
	LinearisationLog10
	LinearisationLog2
	LinearisationE
	LinearisationExp10
	LinearisationExp2
	LinearisationInverse
	LinearisationSqr
	LinearisationCube
	LinearisationSqrt
	LinearisationCubeRt
	LinearisationNonLinear
)

func (Linearisation) Description added in v0.11.0

func (l Linearisation) Description() string

func (Linearisation) IsLinear added in v0.11.0

func (l Linearisation) IsLinear() bool

IsLinear returns whether the underlying sensor is linear. Calling Lineariser() will return an error, as there is no linearisation formula (it is effectively a no-op). Only the linear formula in the spec needs be applied to obtain a real reading.

func (Linearisation) IsLinearised added in v0.11.0

func (l Linearisation) IsLinearised() bool

IsLinearised returns whether the underlying sensor is linearised, meaning the value after conversion needs to be fed through a linearisation formula as a final step before being used. A suitable implementation of this function is returned by the Lineariser() method.

func (Linearisation) IsNonLinear added in v0.11.0

func (l Linearisation) IsNonLinear() bool

IsNonLinear returns whether the underlying sensor is not consistent enough for the constraints of linear and linearised. As for linear sensors, attempting to retrieve a Lineariser will return an error. Readings from these sensors require Get Sensor Reading Factors to convert them into usable values.

func (Linearisation) Lineariser added in v0.11.0

func (l Linearisation) Lineariser() (Lineariser, error)

Lineariser returns a suitable Lineariser implementation that will turn the converted raw value produced by the underlying sensor into a usable value. If the sensor is already linear, or non-linear, this will return ErrNotLinearised.

func (Linearisation) String added in v0.11.0

func (l Linearisation) String() string

type Lineariser added in v0.11.0

type Lineariser interface {
	// Linearise applies a linearisation formula to a converted value, returning
	// the final value in the correct unit. This is the last step in the "Sensor
	// Reading Conversion Formula" described in section 30.3 of IPMI v1.5 and
	// v2.0.
	Linearise(v float64) float64
}

Lineariser is implemented by formulae that can linearise a value returned by the Get Sensor Reading command that has gone through the linear formula containing M, B, K1 and K2, used for all sensors.

type LineariserFunc added in v0.11.0

type LineariserFunc func(float64) float64

LineariserFunc is the type of the function in the Lineariser interface. It allows us to create stateless Lineariser implementations from raw functions, including those in the math package.

func (LineariserFunc) Linearise added in v0.11.0

func (l LineariserFunc) Linearise(f float64) float64

Linearise invokes the wrapped function, passing through the input and result.

type PowerReading

type PowerReading struct {
	Minimum, Maximum, Average, Current float64
	Activated                          bool
}

type Request added in v0.11.0

type Request struct {
	Addr    uintptr
	AddrLen uint
	Msgid   int
	Msg     ipmiMsg
}

type Response added in v0.11.0

type Response struct {
	Ccode   uint8
	Data    [1024]uint8
	DataLen int32
}

type SensorUnit added in v0.11.0

type SensorUnit uint8

SensorUnit defines the unit of a sensor. It is specified in 37.17 and 43.17 of v1.5 and v2.0 respectively. It is an 8-bit uint on the wire.

const (
	SensorUnitCelsius SensorUnit
	SensorUnitFahrenheit
	SensorUnitKelvin
	SensorUnitVolts
	SensorUnitAmps
	SensorUnitWatts
	SensorUnitJoules
	SensorUnitCoulombs
	SensorUnitVoltamperes
	SensorUnitNits
	SensorUnitLumen
	SensorUnitLux
	SensorUnitCandela
	SensorUnitKilopascals
	SensorUnitPoundsPerSquareInch
	SensorUnitNewtons
	SensorUnitCubicFeetPerMinute
	SensorUnitRotationsPerMinute
	SensorUnitHertz
	SensorUnitMicroseconds
	SensorUnitMilliseconds
	SensorUnitSeconds
	SensorUnitMinutes
	SensorUnitHours
	SensorUnitDays
	SensorUnitWeeks
	SensorUnitMils
	SensorUnitInches
	SensorUnitFeet
	SensorUnitCubicInches
	SensorUnitCubicFeet
	SensorUnitMillimeters
	SensorUnitCentimeters
	SensorUnitMeters
	SensorUnitCubicCentimeters
	SensorUnitCubicMeters
	SensorUnitLiters
	SensorUnitFluidOunces
	SensorUnitRadians
	SensorUnitSteradians
	SensorUnitRevolutions
	SensorUnitCycles
	SensorUnitGravities
	SensorUnitOunces
	SensorUnitPounds
	SensorUnitFeetPounds
	SensorUnitOunceInches
	SensorUnitGauss
	SensorUnitGilberts
	SensorUnitHenry
	SensorUnitMillihenry
	SensorUnitFarad
	SensorUnitMicrofarad
	SensorUnitOhms
	SensorUnitSiemens
	SensorUnitMoles
	SensorUnitBecquerel
	SensorUnitPartsPerMillion

	SensorUnitDecibels
	SensorUnitDecibelsAFilter
	SensorUnitDecibelsCFilter
	SensorUnitGray
	SensorUnitSieverts
	SensorUnitColorTempKelvin
	SensorUnitBits
	SensorUnitKilobits
	SensorUnitMegabits
	SensorUnitGigabits
	SensorUnitBytes
	SensorUnitKilobytes
	SensorUnitMegabytes
	SensorUnitGigabytes
	SensorUnitWords
	SensorUnitDwords
	SensorUnitQwords
	SensorUnitMemoryLines
	SensorUnitHits
	SensorUnitMisses
	SensorUnitRetries
	SensorUnitResets
	SensorUnitOverflows
	SensorUnitUnderruns
	SensorUnitCollisions
	SensorUnitPackets
	SensorUnitMessages
	SensorUnitCharacters
	SensorUnitErrors
	SensorUnitCorrectableErrors
	SensorUnitUncorrectableErrors
	SensorUnitFatal
	SensorUnitGrams
)

func (SensorUnit) String added in v0.11.0

func (s SensorUnit) String() string

func (SensorUnit) Symbol added in v0.11.0

func (s SensorUnit) Symbol() string

type StringDecoder added in v0.11.0

type StringDecoder interface {
	// Decode parses the first c characters (0 <= c <= 30) in b in the expected
	// format (N.B. this could be a varying number of bytes depending on the
	// encoding), returning the resulting string and number of bytes consumed,
	// or an error if the data is too short or invalid.
	//
	// c was implemented as an int rather than uint8 to reduce the number of
	// conversions required.
	Decode(b []byte, c int) (string, int, error)
}

StringDecoder is implemented by things that know how to parse the final ID String field of full and compact SDRs.

type StringDecoderFunc added in v0.11.0

type StringDecoderFunc func([]byte, int) (string, int, error)

StringDecoderFunc eases implementation of stateless StringDecoders.

func (StringDecoderFunc) Decode added in v0.11.0

func (f StringDecoderFunc) Decode(b []byte, c int) (string, int, error)

Decode calls the contained function on the inputs, passing through the returned values verbatim.

type StringEncoding added in v0.11.0

type StringEncoding uint8

StringEncoding describes the most significant two bits of the SDR Type/Length Byte, specified in 37.15 and 43.15 of v1.5 and v2.0 respectively.

const (
	// StringEncodingUnicode, contrary to the name, typically suggests an
	// unspecified encoding. IPMItool displays a hex representation of the
	// underlying bytes, while OpenIPMI interprets it identically to
	// StringEncoding8BitAsciiLatin1. Given Unicode is only a character set and
	// the spec does not suggest any encoding, there is no right answer. The
	// resulting variety of implementations means use of this value by a BMC
	// should be regarded as a bug.
	StringEncodingUnicode StringEncoding = iota
	StringEncodingBCDPlus
	StringEncodingPacked6BitAscii
	StringEncoding8BitAsciiLatin1
)

func (StringEncoding) Decoder added in v0.11.0

func (e StringEncoding) Decoder() (StringDecoder, error)

func (StringEncoding) Description added in v0.11.0

func (e StringEncoding) Description() string

func (StringEncoding) String added in v0.11.0

func (e StringEncoding) String() string

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL