设置所需的风扇速度,该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是命令的请求和响应

三、 添加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) endend
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_mappingend
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文件里面找自己所需要的。
另外有错误的地方请大家评论指正




