添加一条IPMI命令实操分享——设置所需的风扇速度

设置所需的风扇速度,该ipmi命令在openUBMC目前还不支持,命令如下

接下来我们添加这一条命令。首先确认在组件thermal_mgmt下添加。

一、在mds/ipmi.json文件下添加该命令的定义

“SetDesiredFanSpeed”: {

“netfn”: “0x30”,

“cmd”: “0x92”,

“priority”: “Default”,

“role”: “Operator”,

“privilege”: [“BasicSetting”],

“req”: [

{ “data”: “ManufactureId”, “baseType”: “U32”, “len”: “3B”, “customizedRule”: “Manufacturer” },

{ “data”: “SubCommand”, “baseType”: “U8”, “len”: “1B”, “value”: “0x10” },

{ “data”: “Index”, “baseType”: “U8”, “len”: “1B” },

{ “data”: “FanSpeed”, “baseType”: “String”, “len”: “*”}

],

“rsp”: [

{ “data”: “CompletionCode”, “baseType”: “U8”, “len”: “1B” },

{ “data”: “ManufactureId”, “baseType”: “U32”, “len”: “3B”, “customizedRule”: “Manufacturer” }

]

},

1.这里要确保你的命令名字在该文件全局唯一,依据ipmi命令文档添加netfn、cmd、SubCommand分别为0x30、0x92、0x10;

2.ManufactureId就是0xDB0700

3.Index是添加FanId

4.FanSpeed是添加的是风扇的占空比,这里是个变长,所以我使用String

5.其余的可以参考其他的命令

二、 执行bingo gen -r openubmc_dev,自动生成代码

1.执行完命令后,会生成一个新文件,新文件以命令名字为文件名。

2.还有两个文件已生成新代码,ipmi.lua是命令对象的集合,是我们新加的命令内容

3.ipmi_message.lua是命令的请求和响应

image

三、 添加ipmi命令的回调函数

1.这里先要在ipmi注册的地方去加我们的函数名。

register_ipmi_func(cooling_ipmi_service.SetDesiredFanSpeed, function(…)

    return cooling_ipmi:SetDesiredFanSpeed(...)

end)

这里大家搜一下其他的ipmi命令就很容易找到这样的注册函数。

2.添加实现函数

local function set_single_fan_level_hw(self, ctx, device_id, level) – 设置单个风扇手动转速

local ctrl_mode_persist_type = self.air_config_instance:get_ctrl_mode_persist_type()

local l_range = self.fans_config_instance:get_level_range()

if level < l_range\[1\] or level > l_range\[2\] then

    log:error("Level(%s) of fan is out of range, the correct range is %d to %d", level, l_range\[1\], l_range\[2\])

    utils.ipmi_op(ctx, "Set fan level to (%d) failed", level)

    error(custom_msg.IPMIOutOfRange())

end

-- 单个风扇转速仅支持在手动模式下设置

local fan_ctrl_mode = self.fans_config_instance:get_ctrl_mode()

if fan_ctrl_mode \~= cooling_enums.modes.Manual then

    log:error('Set fan(%s) level(%s) failed, current mode: %s', device_id, level, fan_ctrl_mode)

    utils.ipmi_op(ctx, "Set fan(%d) level to (%d) failed", device_id, level)

    error(custom_msg.IPMIInvalidFieldRequest()) -- 仅在手动模式能设置单个风扇转速

end

if not self.fans_instance:set_single_cooling_device_manual_level(device_id, level, ctrl_mode_persist_type) or

    not self.mgmt_instance:set_fan_level_hw(device_id, level) then

    log:error("Set fan(%d) level to (%d) failed", device_id, level)

    utils.ipmi_op(ctx, "Set fan(%d) level to (%d) failed", device_id, level)

    error(custom_msg.IPMIOutOfRange()) -- 风扇id超出范围

else

    utils.ipmi_op(ctx, "Set fan(%d) level to (%d) successfully", device_id, level)

end

end

local function get_fan_speed_table(data, start_index)

local fan_speed_mapping = {}

local data_len = #data

-- 遍历字符串,每个字节取出

for i = 1, data_len do

    -- 取第 i 个字节的数值(0\~255)

    local speed = string.byte(data, i)

    fan_speed_mapping\[start_index + i - 1\] = speed

end

return fan_speed_mapping

end

function cooling_ipmi:SetDesiredFanSpeed(req, ctx)

local fan_num = self.fans_instance:get_obj_count()

if #req.FanSpeed \~= (fan_num - req.Index + 1) then

    error(custom_msg.IPMIOutOfRange())

end

local fan_speed_table = get_fan_speed_table(req.FanSpeed, req.Index)

for fan_id, duty in pairs(fan_speed_table) do

    if 255 == duty then

        goto continue

    end

    set_single_fan_level_hw(self, ctx, fan_id, duty)

    ::continue::

end

return ipmi_msg.SetDesiredFanSpeedRsp.new(0, MANUFACTURE_ID) 

end

主要逻辑就是处理传入的参数,去调用相关的风扇占空比下发接口。最后返回处理结果。

报错可以在mdb_interface/messages/custom.json文件里面找自己所需要的。

另外有错误的地方请大家评论指正

2 个赞