* [PATCH 0/2] hw/ipmi/ipmi_bmc_sim: Get/set fake LAN config
@ 2025-10-28 18:01 Yunpeng Yang
2025-10-28 18:01 ` [PATCH 1/2] hw/ipmi/ipmi_bmc_sim: Support getting fake LAN channel config Yunpeng Yang
` (2 more replies)
0 siblings, 3 replies; 7+ messages in thread
From: Yunpeng Yang @ 2025-10-28 18:01 UTC (permalink / raw)
To: minyard@acm.org
Cc: farosas@suse.de, lvivier@redhat.com, pbonzini@redhat.com,
qemu-devel@nongnu.org, Mark Cave-Ayland, corey@minyard.net,
Jonathan Davies, cornelia.huck@de.ibm.com
Support for a fake LAN channel is added to the device `ipmi_bmc_sim`.
Although there is no real LAN channel, some testing processes which
require interactions with BMC LAN channel will become easier.
There's another device `ipmi_bmc_extern` which works together with some
external BMC simulator, e.g., `ipmi_sim`. More comprehensive BMC
simulation can be achieved with `ipmi_bmc_extern`. However,
`ipmi_bmc_sim` is more light-weight and is built into QEMU.
Yunpeng Yang (2):
hw/ipmi/ipmi_bmc_sim: Support getting fake LAN channel config
hw/ipmi/ipmi_bmc_sim: Support setting fake LAN channel config
hw/ipmi/ipmi_bmc_sim.c | 407 +++++++++++++++++++++++++++++++++++-
include/hw/ipmi/ipmi.h | 1 +
qemu-options.hx | 26 +++
tests/qtest/ipmi-kcs-test.c | 143 +++++++++++++
4 files changed, 567 insertions(+), 10 deletions(-)
--
2.43.7
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 1/2] hw/ipmi/ipmi_bmc_sim: Support getting fake LAN channel config
2025-10-28 18:01 [PATCH 0/2] hw/ipmi/ipmi_bmc_sim: Get/set fake LAN config Yunpeng Yang
@ 2025-10-28 18:01 ` Yunpeng Yang
2025-12-01 20:18 ` Philippe Mathieu-Daudé
2025-10-28 18:01 ` [PATCH 2/2] hw/ipmi/ipmi_bmc_sim: Support setting " Yunpeng Yang
2025-11-24 20:54 ` [PATCH 0/2] hw/ipmi/ipmi_bmc_sim: Get/set fake LAN config Corey Minyard
2 siblings, 1 reply; 7+ messages in thread
From: Yunpeng Yang @ 2025-10-28 18:01 UTC (permalink / raw)
To: minyard@acm.org
Cc: farosas@suse.de, lvivier@redhat.com, pbonzini@redhat.com,
qemu-devel@nongnu.org, Mark Cave-Ayland, corey@minyard.net,
Jonathan Davies, cornelia.huck@de.ibm.com
The following IPMI commands are added or modified to support getting
fake LAN channel configurations from the `ipmi_bmc_sim` device:
* Get Channel Access;
* Get Channel Info Command;
* Get LAN Configuration Parameters.
The fake LAN channel configurations can be specified from QEMU
commandline options for device `ipmi_bmc_sim`. Inside the guest OS, the
configurations can be retrieved from the device using some IPMI tools,
e.g., `ipmitool lan print`.
Note, there is not a real LAN channel. The fake LAN channel is suitable
for testing purposes.
Signed-off-by: Yunpeng Yang <yunpeng.yang@nutanix.com>
---
hw/ipmi/ipmi_bmc_sim.c | 297 ++++++++++++++++++++++++++++++++++--
include/hw/ipmi/ipmi.h | 1 +
qemu-options.hx | 26 ++++
tests/qtest/ipmi-kcs-test.c | 60 ++++++++
4 files changed, 374 insertions(+), 10 deletions(-)
diff --git a/hw/ipmi/ipmi_bmc_sim.c b/hw/ipmi/ipmi_bmc_sim.c
index 04e1dcd0e7..2ead46ee55 100644
--- a/hw/ipmi/ipmi_bmc_sim.c
+++ b/hw/ipmi/ipmi_bmc_sim.c
@@ -27,11 +27,13 @@
#include "qemu/timer.h"
#include "hw/ipmi/ipmi.h"
#include "qemu/error-report.h"
+#include "qapi/error.h"
#include "qemu/module.h"
#include "hw/loader.h"
#include "hw/qdev-properties.h"
#include "hw/qdev-properties-system.h"
#include "migration/vmstate.h"
+#include "net/net.h"
#define IPMI_NETFN_CHASSIS 0x00
@@ -70,6 +72,7 @@
#define IPMI_CMD_GET_MSG 0x33
#define IPMI_CMD_SEND_MSG 0x34
#define IPMI_CMD_READ_EVT_MSG_BUF 0x35
+#define IPMI_CMD_GET_CHANNEL_ACCESS 0x41
#define IPMI_CMD_GET_CHANNEL_INFO 0x42
#define IPMI_NETFN_STORAGE 0x0a
@@ -101,6 +104,10 @@
#define IPMI_CMD_GET_SEL_TIME 0x48
#define IPMI_CMD_SET_SEL_TIME 0x49
+#define IPMI_NETFN_TRANSPORT 0x0c
+
+#define IPMI_CMD_GET_LAN_CONFIG 0x02
+
/* Same as a timespec struct. */
struct ipmi_time {
@@ -170,6 +177,23 @@ typedef struct IPMISensor {
#define MAX_SENSORS 20
#define IPMI_WATCHDOG_SENSOR 0
+#define NBYTES_IP 4
+#define NBYTES_MAC 6
+
+typedef struct IPMILan {
+ uint8_t channel;
+ uint8_t ipaddr[NBYTES_IP];
+ uint8_t ipsrc;
+ MACAddr macaddr;
+ uint8_t netmask[NBYTES_IP];
+ uint8_t defgw_ipaddr[NBYTES_IP];
+ MACAddr defgw_macaddr;
+
+ char *arg_ipaddr;
+ char *arg_netmask;
+ char *arg_defgw_ipaddr;
+} IPMILan;
+
#define MAX_NETFNS 64
typedef struct IPMIRcvBufEntry {
@@ -215,6 +239,7 @@ struct IPMIBmcSim {
IPMIFru fru;
IPMISensor sensors[MAX_SENSORS];
char *sdr_filename;
+ IPMILan lan;
/* Odd netfns are for responses, so we only need the even ones. */
const IPMINetfn *netfns[MAX_NETFNS / 2];
@@ -265,6 +290,36 @@ struct IPMIBmcSim {
#define IPMI_BMC_WATCHDOG_ACTION_POWER_DOWN 2
#define IPMI_BMC_WATCHDOG_ACTION_POWER_CYCLE 3
+#define IPMI_CHANNEL_IMPLEMENTATION_MIN 0x1
+#define IPMI_CHANNEL_IMPLEMENTATION_MAX 0xb
+#define IPMI_CHANNEL_IS_IMPLEMENTATION_SPECIFIC(c) \
+ (IPMI_CHANNEL_IMPLEMENTATION_MIN <= (c) && \
+ (c) <= IPMI_CHANNEL_IMPLEMENTATION_MAX)
+
+#define IPMI_BMC_CHANNEL_IS_LAN(ibs, c) \
+ ((ibs)->lan.channel != 0 && (ibs)->lan.channel == (c))
+
+#define IPMI_BMC_LAN_CFG_CC_PARAM_NOT_SUPPORTED 0x80
+
+#define IPMI_BMC_LAN_CFG_PARAM_SET_IN_PROGRESS 0x00
+#define IPMI_BMC_LAN_CFG_PARAM_AUTH_TYPE_SUPPORT 0x01
+#define IPMI_BMC_LAN_CFG_PARAM_AUTH_TYPE_ENABLES 0x02
+#define IPMI_BMC_LAN_CFG_PARAM_IP_ADDR 0x03
+#define IPMI_BMC_LAN_CFG_PARAM_IP_ADDR_SOURCE 0x04
+#define IPMI_BMC_LAN_CFG_PARAM_MAC_ADDR 0x05
+#define IPMI_BMC_LAN_CFG_PARAM_SUBNET_MASK 0x06
+#define IPMI_BMC_LAN_CFG_PARAM_IPV4_HDR_PARAMS 0x07
+#define IPMI_BMC_LAN_CFG_PARAM_DEFAULT_GW_IP_ADDR 0x0c
+#define IPMI_BMC_LAN_CFG_PARAM_DEFAULT_GW_MAC_ADDR 0x0d
+#define IPMI_BMC_LAN_CFG_PARAM_BACKUP_GW_ADDR 0x0e
+#define IPMI_BMC_LAN_CFG_PARAM_BACKUP_GW_MAC_ADDR 0x0f
+#define IPMI_BMC_LAN_CFG_PARAM_COMMUNITY_STRING 0x10
+#define IPMI_BMC_LAN_CFG_PARAM_NUM_DESTINATIONS 0x11
+
+#define IPMI_BMC_LAN_CFG_PARAMETER_REVISION 0x11
+
+#define IPMI_BMC_LAN_CFG_IS_VALID_IP_SOURCE(v) (0x0 <= (v) && (v) <= 0x4)
+
#define RSP_BUFFER_INITIALIZER { }
static inline void rsp_buffer_pushmore(RspBuffer *rsp, uint8_t *bytes,
@@ -1231,6 +1286,25 @@ static void get_watchdog_timer(IPMIBmcSim *ibs,
}
}
+static void get_channel_access(IPMIBmcSim *ibs,
+ uint8_t *cmd, unsigned int cmd_len,
+ RspBuffer *rsp)
+{
+ uint8_t channel = cmd[2] & 0xf;
+
+ if (channel == IPMI_CHANNEL_IPMB || channel == IPMI_CHANNEL_SYSTEM ||
+ IPMI_BMC_CHANNEL_IS_LAN(ibs, channel)) {
+ /* alerting disabled */
+ /* per message authentication disabled */
+ /* user level authentication disabled */
+ /* channel always available */
+ rsp_buffer_push(rsp, 0x20 | 0x10 | 0x08 | 0x02);
+ rsp_buffer_push(rsp, 0x04); /* privilege limit: ADMINISTRATOR */
+ } else {
+ rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
+ }
+}
+
static void get_channel_info(IPMIBmcSim *ibs,
uint8_t *cmd, unsigned int cmd_len,
RspBuffer *rsp)
@@ -1240,29 +1314,29 @@ static void get_channel_info(IPMIBmcSim *ibs,
IPMIFwInfo info = {};
uint8_t ch = cmd[2] & 0x0f;
- /* Only define channel 0h (IPMB) and Fh (system interface) */
-
if (ch == 0x0e) { /* "This channel" */
ch = IPMI_CHANNEL_SYSTEM;
}
rsp_buffer_push(rsp, ch);
- if (ch != IPMI_CHANNEL_IPMB && ch != IPMI_CHANNEL_SYSTEM) {
- /* Not a supported channel */
- rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
- return;
- }
-
if (k->get_fwinfo) {
k->get_fwinfo(s, &info);
}
+ /* Only define channel 0h (IPMB), LAN, and Fh (system interface) */
if (ch == IPMI_CHANNEL_IPMB) {
rsp_buffer_push(rsp, IPMI_CHANNEL_MEDIUM_IPMB);
rsp_buffer_push(rsp, IPMI_CHANNEL_PROTOCOL_IPMB);
- } else { /* IPMI_CHANNEL_SYSTEM */
+ } else if (IPMI_BMC_CHANNEL_IS_LAN(ibs, ch)) {
+ rsp_buffer_push(rsp, IPMI_CHANNEL_MEDIUM_802_3_LAN);
+ rsp_buffer_push(rsp, IPMI_CHANNEL_PROTOCOL_IPMB);
+ } else if (ch == IPMI_CHANNEL_SYSTEM) {
rsp_buffer_push(rsp, IPMI_CHANNEL_MEDIUM_SYSTEM);
rsp_buffer_push(rsp, info.ipmi_channel_protocol);
+ } else {
+ /* Not a supported channel */
+ rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
+ return;
}
rsp_buffer_push(rsp, 0x00); /* Session-less */
@@ -2045,6 +2119,140 @@ static void set_sensor_reading(IPMIBmcSim *ibs,
}
}
+static inline bool is_valid_netmask(const uint8_t *netmask)
+{
+ uint32_t mask = netmask[3];
+ uint32_t inverted;
+
+ mask |= (uint32_t) netmask[2] << 8;
+ mask |= (uint32_t) netmask[1] << 16;
+ mask |= (uint32_t) netmask[0] << 24;
+ inverted = ~mask;
+ return mask != 0 && (inverted & (inverted + 1)) == 0;
+}
+
+/*
+ * Request data (from cmd[2] to cmd[5] inclusive):
+ * bytes meaning
+ * 1 [bit 7] revision only flag, [bits 3:0] channel number
+ * 2 parameter selector
+ * 3 set selector
+ * 4 block selector
+ */
+static void get_lan_config(IPMIBmcSim *ibs,
+ uint8_t *cmd, unsigned int cmd_len,
+ RspBuffer *rsp)
+{
+ uint8_t channel;
+
+ if (ibs->lan.channel == 0) {
+ /* LAN channel disabled. Fail as if this command were not defined. */
+ rsp_buffer_set_error(rsp, IPMI_CC_INVALID_CMD);
+ return;
+ }
+ if (cmd_len < 6) {
+ rsp_buffer_set_error(rsp, IPMI_CC_REQUEST_DATA_LENGTH_INVALID);
+ return;
+ }
+ channel = cmd[2] & 0xf;
+
+ rsp_buffer_push(rsp, IPMI_BMC_LAN_CFG_PARAMETER_REVISION);
+ if (cmd[2] & 0x80) {
+ /* The requester only requests parameter revision, not the parameter */
+ return;
+ }
+ if (!IPMI_BMC_CHANNEL_IS_LAN(ibs, channel)) {
+ rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
+ return;
+ }
+
+ switch (cmd[3]) {
+ case IPMI_BMC_LAN_CFG_PARAM_SET_IN_PROGRESS:
+ rsp_buffer_push(rsp, 0x0); /* set complete */
+ break;
+
+ case IPMI_BMC_LAN_CFG_PARAM_AUTH_TYPE_SUPPORT:
+ rsp_buffer_push(rsp, 0x01); /* Authentication type "none" supported */
+ break;
+
+ case IPMI_BMC_LAN_CFG_PARAM_AUTH_TYPE_ENABLES:
+ /* Only authentication type "none" enabled */
+ rsp_buffer_push(rsp, 0x01); /* for privilege level "Callback" */
+ rsp_buffer_push(rsp, 0x01); /* for privilege level "User" */
+ rsp_buffer_push(rsp, 0x01); /* for privilege level "Operator" */
+ rsp_buffer_push(rsp, 0x01); /* for privilege level "Administrator" */
+ rsp_buffer_push(rsp, 0x01); /* for privilege level "OEM" */
+ break;
+
+ case IPMI_BMC_LAN_CFG_PARAM_IP_ADDR:
+ rsp_buffer_pushmore(rsp, ibs->lan.ipaddr, NBYTES_IP);
+ break;
+
+ case IPMI_BMC_LAN_CFG_PARAM_IP_ADDR_SOURCE:
+ rsp_buffer_push(rsp, ibs->lan.ipsrc);
+ break;
+
+ case IPMI_BMC_LAN_CFG_PARAM_MAC_ADDR:
+ rsp_buffer_pushmore(rsp, ibs->lan.macaddr.a, NBYTES_MAC);
+ break;
+
+ case IPMI_BMC_LAN_CFG_PARAM_SUBNET_MASK:
+ rsp_buffer_pushmore(rsp, ibs->lan.netmask, NBYTES_IP);
+ break;
+
+ case IPMI_BMC_LAN_CFG_PARAM_IPV4_HDR_PARAMS:
+ /* TTL 0x40 */
+ rsp_buffer_push(rsp, 0x40);
+ /* don't fragment */
+ rsp_buffer_push(rsp, 0x40);
+ /* precedence 0x0, minimize delay */
+ rsp_buffer_push(rsp, 0x10);
+ break;
+
+ case IPMI_BMC_LAN_CFG_PARAM_DEFAULT_GW_IP_ADDR:
+ rsp_buffer_pushmore(rsp, ibs->lan.defgw_ipaddr, NBYTES_IP);
+ break;
+
+ case IPMI_BMC_LAN_CFG_PARAM_DEFAULT_GW_MAC_ADDR:
+ rsp_buffer_pushmore(rsp, ibs->lan.defgw_macaddr.a, NBYTES_MAC);
+ break;
+
+ case IPMI_BMC_LAN_CFG_PARAM_BACKUP_GW_ADDR:
+ /* 0.0.0.0 */
+ rsp_buffer_push(rsp, 0x00);
+ rsp_buffer_push(rsp, 0x00);
+ rsp_buffer_push(rsp, 0x00);
+ rsp_buffer_push(rsp, 0x00);
+ break;
+
+ case IPMI_BMC_LAN_CFG_PARAM_BACKUP_GW_MAC_ADDR:
+ /* 00:00:00:00:00:00 */
+ rsp_buffer_push(rsp, 0x00);
+ rsp_buffer_push(rsp, 0x00);
+ rsp_buffer_push(rsp, 0x00);
+ rsp_buffer_push(rsp, 0x00);
+ rsp_buffer_push(rsp, 0x00);
+ rsp_buffer_push(rsp, 0x00);
+ break;
+
+ case IPMI_BMC_LAN_CFG_PARAM_COMMUNITY_STRING:
+ {
+ static uint8_t community_str[18] = "public";
+
+ rsp_buffer_pushmore(rsp, community_str, sizeof(community_str));
+ }
+ break;
+
+ case IPMI_BMC_LAN_CFG_PARAM_NUM_DESTINATIONS:
+ rsp_buffer_push(rsp, 0x00); /* LAN Alerting not supported */
+ break;
+
+ default:
+ rsp_buffer_set_error(rsp, IPMI_BMC_LAN_CFG_CC_PARAM_NOT_SUPPORTED);
+ return;
+ };
+}
+
static const IPMICmdHandler chassis_cmds[] = {
[IPMI_CMD_GET_CHASSIS_CAPABILITIES] = { chassis_capabilities },
[IPMI_CMD_GET_CHASSIS_STATUS] = { chassis_status },
@@ -2089,6 +2297,7 @@ static const IPMICmdHandler app_cmds[] = {
[IPMI_CMD_RESET_WATCHDOG_TIMER] = { reset_watchdog_timer },
[IPMI_CMD_SET_WATCHDOG_TIMER] = { set_watchdog_timer, 8 },
[IPMI_CMD_GET_WATCHDOG_TIMER] = { get_watchdog_timer },
+ [IPMI_CMD_GET_CHANNEL_ACCESS] = { get_channel_access, 4 },
[IPMI_CMD_GET_CHANNEL_INFO] = { get_channel_info, 3 },
};
static const IPMINetfn app_netfn = {
@@ -2119,12 +2328,22 @@ static const IPMINetfn storage_netfn = {
.cmd_handlers = storage_cmds
};
+static const IPMICmdHandler transport_cmds[] = {
+ [IPMI_CMD_GET_LAN_CONFIG] = { get_lan_config },
+};
+static const IPMINetfn transport_netfn = {
+ .cmd_nums = ARRAY_SIZE(transport_cmds),
+ .cmd_handlers = transport_cmds
+};
+
+
static void register_cmds(IPMIBmcSim *s)
{
ipmi_sim_register_netfn(s, IPMI_NETFN_CHASSIS, &chassis_netfn);
ipmi_sim_register_netfn(s, IPMI_NETFN_SENSOR_EVENT, &sensor_event_netfn);
ipmi_sim_register_netfn(s, IPMI_NETFN_APP, &app_netfn);
ipmi_sim_register_netfn(s, IPMI_NETFN_STORAGE, &storage_netfn);
+ ipmi_sim_register_netfn(s, IPMI_NETFN_TRANSPORT, &transport_netfn);
}
static uint8_t init_sdrs[] = {
@@ -2176,7 +2395,7 @@ static void ipmi_sdr_init(IPMIBmcSim *ibs)
static const VMStateDescription vmstate_ipmi_sim = {
.name = TYPE_IPMI_BMC_SIMULATOR,
- .version_id = 1,
+ .version_id = 2,
.minimum_version_id = 1,
.fields = (const VMStateField[]) {
VMSTATE_UINT8(bmc_global_enables, IPMIBmcSim),
@@ -2198,6 +2417,13 @@ static const VMStateDescription vmstate_ipmi_sim = {
VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].deassert_states,
IPMIBmcSim),
VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].assert_enable, IPMIBmcSim),
+ VMSTATE_UINT8_V(lan.channel, IPMIBmcSim, 2),
+ VMSTATE_UINT8_ARRAY_V(lan.ipaddr, IPMIBmcSim, NBYTES_IP, 2),
+ VMSTATE_UINT8_V(lan.ipsrc, IPMIBmcSim, 2),
+ VMSTATE_UINT8_ARRAY_V(lan.macaddr.a, IPMIBmcSim, NBYTES_MAC, 2),
+ VMSTATE_UINT8_ARRAY_V(lan.netmask, IPMIBmcSim, NBYTES_IP, 2),
+ VMSTATE_UINT8_ARRAY_V(lan.defgw_ipaddr, IPMIBmcSim, NBYTES_IP, 2),
+ VMSTATE_UINT8_ARRAY_V(lan.defgw_macaddr.a, IPMIBmcSim, NBYTES_MAC, 2),
VMSTATE_END_OF_LIST()
}
};
@@ -2232,6 +2458,47 @@ out:
fru->nentries = size / fru->areasize;
}
+static void ipmi_lan_init(IPMILan *lan, Error **errp)
+{
+ struct in_addr ip;
+
+ /*
+ * `lan->channel` can be either 0 (meaning LAN channel disabled) or
+ * a valid IPMI implementation-specific channel.
+ */
+ if (lan->channel != 0 &&
+ !IPMI_CHANNEL_IS_IMPLEMENTATION_SPECIFIC(lan->channel)) {
+ error_setg(errp, "invalid LAN channel %d", lan->channel);
+ return;
+ }
+ if (lan->arg_ipaddr) {
+ if (inet_pton(AF_INET, lan->arg_ipaddr, &ip) != 1) {
+ error_setg(errp, "invalid ip address '%s'", lan->arg_ipaddr);
+ return;
+ }
+ memcpy(lan->ipaddr, &ip.s_addr, NBYTES_IP);
+ }
+ if (!IPMI_BMC_LAN_CFG_IS_VALID_IP_SOURCE(lan->ipsrc)) {
+ error_setg(errp, "invalid ip source %d", lan->ipsrc);
+ return;
+ }
+ if (lan->arg_netmask) {
+ if (inet_pton(AF_INET, lan->arg_netmask, &ip) != 1 ||
+ !is_valid_netmask((const uint8_t *) &ip.s_addr)) {
+ error_setg(errp, "invalid subnet mask '%s'", lan->arg_netmask);
+ return;
+ }
+ memcpy(lan->netmask, &ip.s_addr, NBYTES_IP);
+ }
+ if (lan->arg_defgw_ipaddr) {
+ if (inet_pton(AF_INET, lan->arg_defgw_ipaddr, &ip) != 1) {
+ error_setg(errp, "invalid ip address '%s'", lan->arg_defgw_ipaddr);
+ return;
+ }
+ memcpy(lan->defgw_ipaddr, &ip.s_addr, NBYTES_IP);
+ }
+}
+
static void ipmi_sim_realize(DeviceState *dev, Error **errp)
{
IPMIBmc *b = IPMI_BMC(dev);
@@ -2259,6 +2526,9 @@ static void ipmi_sim_realize(DeviceState *dev, Error **errp)
ibs->acpi_power_state[1] = 0;
ipmi_init_sensors_from_sdrs(ibs);
+
+ ipmi_lan_init(&ibs->lan, errp);
+
register_cmds(ibs);
ibs->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, ipmi_timeout, ibs);
@@ -2276,6 +2546,13 @@ static const Property ipmi_sim_properties[] = {
DEFINE_PROP_UINT32("mfg_id", IPMIBmcSim, mfg_id, 0),
DEFINE_PROP_UINT16("product_id", IPMIBmcSim, product_id, 0),
DEFINE_PROP_UUID_NODEFAULT("guid", IPMIBmcSim, uuid),
+ DEFINE_PROP_UINT8("lan.channel", IPMIBmcSim, lan.channel, 0),
+ DEFINE_PROP_STRING("lan.ipaddr", IPMIBmcSim, lan.arg_ipaddr),
+ DEFINE_PROP_UINT8("lan.ipsrc", IPMIBmcSim, lan.ipsrc, 0),
+ DEFINE_PROP_MACADDR("lan.macaddr", IPMIBmcSim, lan.macaddr),
+ DEFINE_PROP_STRING("lan.netmask", IPMIBmcSim, lan.arg_netmask),
+ DEFINE_PROP_STRING("lan.defgw_ipaddr", IPMIBmcSim, lan.arg_defgw_ipaddr),
+ DEFINE_PROP_MACADDR("lan.defgw_macaddr", IPMIBmcSim, lan.defgw_macaddr),
};
static void ipmi_sim_class_init(ObjectClass *oc, const void *data)
diff --git a/include/hw/ipmi/ipmi.h b/include/hw/ipmi/ipmi.h
index cd581aa134..3435d84178 100644
--- a/include/hw/ipmi/ipmi.h
+++ b/include/hw/ipmi/ipmi.h
@@ -45,6 +45,7 @@ enum ipmi_op {
#define IPMI_CHANNEL_IPMB 0x00
#define IPMI_CHANNEL_SYSTEM 0x0f
#define IPMI_CHANNEL_MEDIUM_IPMB 0x01
+#define IPMI_CHANNEL_MEDIUM_802_3_LAN 0x04
#define IPMI_CHANNEL_MEDIUM_SYSTEM 0x0c
#define IPMI_CHANNEL_PROTOCOL_IPMB 0x01
#define IPMI_CHANNEL_PROTOCOL_KCS 0x05
diff --git a/qemu-options.hx b/qemu-options.hx
index 0223ceffeb..100226d84b 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -1142,6 +1142,32 @@ SRST
is set, get "Get GUID" command to the BMC will return it.
Otherwise "Get GUID" will return an error.
+ ``lan.channel=val``
+ channel number of the fake LAN channel. It can be 0 or any
+ integer from 0x1 to 0xb inclusive. If set to 0, the LAN channel
+ is disabled, otherwise the LAN channel is enabled at the
+ specified channel number. The default is 0.
+
+ ``lan.ipaddr=addr``
+ the ipv4 address of the BMC LAN channel.
+
+ ``lan.ipsrc=val``
+ the ipv4 address source of the BMC LAN channel. It can be 0
+ (unspecified source), 1 (static address), 2 (DHCP), 3 (BIOS or
+ system software), or 4 (other source). The default is 0.
+
+ ``lan.macaddr=mac``
+ the mac address of the BMC LAN channel.
+
+ ``lan.netmask=mask``
+ the ipv4 subnet mask for the BMC LAN channel.
+
+ ``lan.defgw_ipaddr=addr``
+ the default gateway ipv4 address for the BMC LAN channel.
+
+ ``lan.defgw_macaddr=mac``
+ the default gateway mac address for the BMC LAN channel.
+
``-device ipmi-bmc-extern,id=id,chardev=id[,slave_addr=val]``
Add a connection to an external IPMI BMC simulator. Instead of
locally emulating the BMC like the above item, instead connect to an
diff --git a/tests/qtest/ipmi-kcs-test.c b/tests/qtest/ipmi-kcs-test.c
index 3186c6ad64..d0a207477e 100644
--- a/tests/qtest/ipmi-kcs-test.c
+++ b/tests/qtest/ipmi-kcs-test.c
@@ -262,6 +262,62 @@ static void test_enable_irq(void)
kcs_ints_enabled = 1;
}
+
+static uint8_t get_channel_access_cmd[] = { 0x18, 0x41, 0x01, 0x40 };
+static uint8_t get_channel_access_rsp[] = { 0x1c, 0x41, 0x00, 0x3a, 0x04 };
+
+/*
+ * Get channel access
+ */
+static void test_kcs_channel_access(void)
+{
+ uint8_t rsp[20];
+ unsigned int rsplen = sizeof(rsp);
+
+ kcs_cmd(get_channel_access_cmd, sizeof(get_channel_access_cmd),
+ rsp, &rsplen);
+ g_assert(rsplen == sizeof(get_channel_access_rsp));
+ g_assert(memcmp(get_channel_access_rsp, rsp, rsplen) == 0);
+}
+
+
+static uint8_t get_channel_info_cmd[] = { 0x18, 0x42, 0x01 };
+static uint8_t get_channel_info_rsp[] = { 0x1c, 0x42, 0x00, 0x01, 0x04, 0x01,
+ 0x00, 0xf2, 0x1b, 0x00, 0x00, 0x00 };
+
+/*
+ * Get channel info
+ */
+static void test_kcs_channel_info(void)
+{
+ uint8_t rsp[20];
+ unsigned int rsplen = sizeof(rsp);
+
+ kcs_cmd(get_channel_info_cmd, sizeof(get_channel_info_cmd), rsp, &rsplen);
+ g_assert(rsplen == sizeof(get_channel_info_rsp));
+ g_assert(memcmp(get_channel_info_rsp, rsp, rsplen) == 0);
+}
+
+
+/* get ip address (specified in cmdline): 10.0.0.2 */
+static uint8_t get_ipaddr_cmd[] = { 0x30, 0x02, 0x01, 0x03, 0x00, 0x00 };
+static uint8_t get_ipaddr_rsp[] = { 0x34, 0x02, 0x00, 0x11,
+ 0x0a, 0x00, 0x00, 0x02 };
+
+/*
+ * Get LAN configurations
+ */
+static void test_kcs_lan_get(void)
+{
+ uint8_t rsp[20];
+ unsigned int rsplen = sizeof(rsp);
+
+ kcs_cmd(get_ipaddr_cmd, sizeof(get_ipaddr_cmd), rsp, &rsplen);
+ g_assert(rsplen == sizeof(get_ipaddr_rsp));
+ g_assert(memcmp(get_ipaddr_rsp, rsp, rsplen) == 0);
+}
+
+
int main(int argc, char **argv)
{
char *cmdline;
@@ -271,6 +327,7 @@ int main(int argc, char **argv)
g_test_init(&argc, &argv, NULL);
cmdline = g_strdup_printf("-device ipmi-bmc-sim,id=bmc0"
+ ",lan.channel=1,lan.ipaddr=10.0.0.2"
" -device isa-ipmi-kcs,bmc=bmc0");
qtest_start(cmdline);
g_free(cmdline);
@@ -280,6 +337,9 @@ int main(int argc, char **argv)
qtest_add_func("/ipmi/local/kcs_enable_irq", test_enable_irq);
qtest_add_func("/ipmi/local/kcs_base_irq", test_kcs_base);
qtest_add_func("/ipmi/local/kcs_abort_irq", test_kcs_abort);
+ qtest_add_func("/ipmi/local/kcs_channel_access", test_kcs_channel_access);
+ qtest_add_func("/ipmi/local/kcs_channel_info", test_kcs_channel_info);
+ qtest_add_func("/ipmi/local/kcs_lan_get", test_kcs_lan_get);
ret = g_test_run();
qtest_quit(global_qtest);
--
2.43.7
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 2/2] hw/ipmi/ipmi_bmc_sim: Support setting fake LAN channel config
2025-10-28 18:01 [PATCH 0/2] hw/ipmi/ipmi_bmc_sim: Get/set fake LAN config Yunpeng Yang
2025-10-28 18:01 ` [PATCH 1/2] hw/ipmi/ipmi_bmc_sim: Support getting fake LAN channel config Yunpeng Yang
@ 2025-10-28 18:01 ` Yunpeng Yang
2025-11-24 20:54 ` [PATCH 0/2] hw/ipmi/ipmi_bmc_sim: Get/set fake LAN config Corey Minyard
2 siblings, 0 replies; 7+ messages in thread
From: Yunpeng Yang @ 2025-10-28 18:01 UTC (permalink / raw)
To: minyard@acm.org
Cc: farosas@suse.de, lvivier@redhat.com, pbonzini@redhat.com,
qemu-devel@nongnu.org, Mark Cave-Ayland, corey@minyard.net,
Jonathan Davies, cornelia.huck@de.ibm.com
The "Set LAN Configuration Parameters" IPMI command is added to the
`ipmi_bmc_sim` device to support dynamically setting fake LAN channel
configurations. With the fake LAN channel enabled, inside the guest OS,
tools such as `ipmitool` can be used to modify the configurations.
Signed-off-by: Yunpeng Yang <yunpeng.yang@nutanix.com>
---
hw/ipmi/ipmi_bmc_sim.c | 110 ++++++++++++++++++++++++++++++++++++
tests/qtest/ipmi-kcs-test.c | 83 +++++++++++++++++++++++++++
2 files changed, 193 insertions(+)
diff --git a/hw/ipmi/ipmi_bmc_sim.c b/hw/ipmi/ipmi_bmc_sim.c
index 2ead46ee55..f4cea91fde 100644
--- a/hw/ipmi/ipmi_bmc_sim.c
+++ b/hw/ipmi/ipmi_bmc_sim.c
@@ -106,6 +106,7 @@
#define IPMI_NETFN_TRANSPORT 0x0c
+#define IPMI_CMD_SET_LAN_CONFIG 0x01
#define IPMI_CMD_GET_LAN_CONFIG 0x02
@@ -300,6 +301,7 @@ struct IPMIBmcSim {
((ibs)->lan.channel != 0 && (ibs)->lan.channel == (c))
#define IPMI_BMC_LAN_CFG_CC_PARAM_NOT_SUPPORTED 0x80
+#define IPMI_BMC_LAN_CFG_CC_PARAM_READONLY 0x82
#define IPMI_BMC_LAN_CFG_PARAM_SET_IN_PROGRESS 0x00
#define IPMI_BMC_LAN_CFG_PARAM_AUTH_TYPE_SUPPORT 0x01
@@ -2131,6 +2133,113 @@ static inline bool is_valid_netmask(const uint8_t *netmask)
return mask != 0 && (inverted & (inverted + 1)) == 0;
}
+/*
+ * Request data (from cmd[2] on):
+ * bytes meaning
+ * 1 [bits 3:0] channel number
+ * 2 parameter selector
+ * [3:N] configuration parameter data (from cmd[4] on)
+ */
+static void set_lan_config(IPMIBmcSim *ibs,
+ uint8_t *cmd, unsigned int cmd_len,
+ RspBuffer *rsp)
+{
+ uint8_t channel;
+ uint8_t *param; /* pointer to configuration parameter data */
+ unsigned int param_len;
+
+ if (ibs->lan.channel == 0) {
+ /* LAN channel disabled. Fail as if this command were not defined. */
+ rsp_buffer_set_error(rsp, IPMI_CC_INVALID_CMD);
+ return;
+ }
+ if (cmd_len < 5) {
+ rsp_buffer_set_error(rsp, IPMI_CC_REQUEST_DATA_LENGTH_INVALID);
+ return;
+ }
+ channel = cmd[2] & 0xf;
+ param = cmd + 4;
+ param_len = cmd_len - 4;
+
+ if (!IPMI_BMC_CHANNEL_IS_LAN(ibs, channel)) {
+ rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
+ return;
+ }
+
+ switch (cmd[3]) {
+ case IPMI_BMC_LAN_CFG_PARAM_IP_ADDR:
+ if (param_len < NBYTES_IP) {
+ rsp_buffer_set_error(rsp, IPMI_CC_REQUEST_DATA_LENGTH_INVALID);
+ return;
+ }
+ memcpy(ibs->lan.ipaddr, param, NBYTES_IP);
+ break;
+
+ case IPMI_BMC_LAN_CFG_PARAM_IP_ADDR_SOURCE:
+ if (param_len < 1) {
+ rsp_buffer_set_error(rsp, IPMI_CC_REQUEST_DATA_LENGTH_INVALID);
+ return;
+ }
+ if (!IPMI_BMC_LAN_CFG_IS_VALID_IP_SOURCE(*param)) {
+ rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
+ return;
+ }
+ ibs->lan.ipsrc = *param;
+ break;
+
+ case IPMI_BMC_LAN_CFG_PARAM_MAC_ADDR:
+ if (param_len < NBYTES_MAC) {
+ rsp_buffer_set_error(rsp, IPMI_CC_REQUEST_DATA_LENGTH_INVALID);
+ return;
+ }
+ memcpy(ibs->lan.macaddr.a, param, NBYTES_MAC);
+ break;
+
+ case IPMI_BMC_LAN_CFG_PARAM_SUBNET_MASK:
+ if (param_len < NBYTES_IP) {
+ rsp_buffer_set_error(rsp, IPMI_CC_REQUEST_DATA_LENGTH_INVALID);
+ return;
+ }
+ if (!is_valid_netmask(param)) {
+ rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
+ return;
+ }
+ memcpy(ibs->lan.netmask, param, NBYTES_IP);
+ break;
+
+ case IPMI_BMC_LAN_CFG_PARAM_DEFAULT_GW_IP_ADDR:
+ if (param_len < NBYTES_IP) {
+ rsp_buffer_set_error(rsp, IPMI_CC_REQUEST_DATA_LENGTH_INVALID);
+ return;
+ }
+ memcpy(ibs->lan.defgw_ipaddr, param, NBYTES_IP);
+ break;
+
+ case IPMI_BMC_LAN_CFG_PARAM_DEFAULT_GW_MAC_ADDR:
+ if (param_len < NBYTES_MAC) {
+ rsp_buffer_set_error(rsp, IPMI_CC_REQUEST_DATA_LENGTH_INVALID);
+ return;
+ }
+ memcpy(ibs->lan.defgw_macaddr.a, param, NBYTES_MAC);
+ break;
+
+ case IPMI_BMC_LAN_CFG_PARAM_SET_IN_PROGRESS:
+ case IPMI_BMC_LAN_CFG_PARAM_AUTH_TYPE_SUPPORT:
+ case IPMI_BMC_LAN_CFG_PARAM_AUTH_TYPE_ENABLES:
+ case IPMI_BMC_LAN_CFG_PARAM_IPV4_HDR_PARAMS:
+ case IPMI_BMC_LAN_CFG_PARAM_BACKUP_GW_ADDR:
+ case IPMI_BMC_LAN_CFG_PARAM_BACKUP_GW_MAC_ADDR:
+ case IPMI_BMC_LAN_CFG_PARAM_COMMUNITY_STRING:
+ case IPMI_BMC_LAN_CFG_PARAM_NUM_DESTINATIONS:
+ rsp_buffer_set_error(rsp, IPMI_BMC_LAN_CFG_CC_PARAM_READONLY);
+ return;
+
+ default:
+ rsp_buffer_set_error(rsp, IPMI_BMC_LAN_CFG_CC_PARAM_NOT_SUPPORTED);
+ return;
+ }
+}
+
/*
* Request data (from cmd[2] to cmd[5] inclusive):
* bytes meaning
@@ -2329,6 +2438,7 @@ static const IPMINetfn storage_netfn = {
};
static const IPMICmdHandler transport_cmds[] = {
+ [IPMI_CMD_SET_LAN_CONFIG] = { set_lan_config },
[IPMI_CMD_GET_LAN_CONFIG] = { get_lan_config },
};
static const IPMINetfn transport_netfn = {
diff --git a/tests/qtest/ipmi-kcs-test.c b/tests/qtest/ipmi-kcs-test.c
index d0a207477e..9bab0d84ad 100644
--- a/tests/qtest/ipmi-kcs-test.c
+++ b/tests/qtest/ipmi-kcs-test.c
@@ -318,6 +318,88 @@ static void test_kcs_lan_get(void)
}
+/* set/get ip address: 192.0.2.2 */
+static uint8_t lan_set_ipaddr_cmd[] = { 0x30, 0x01, 0x01, 0x03,
+ 0xc0, 0x00, 0x02, 0x02 };
+static uint8_t lan_set_ipaddr_rsp[] = { 0x34, 0x01, 0x00 };
+static uint8_t lan_get_ipaddr_cmd[] = { 0x30, 0x02, 0x01, 0x03, 0x00, 0x00 };
+static uint8_t lan_get_ipaddr_rsp[] = { 0x34, 0x02, 0x00, 0x11,
+ 0xc0, 0x00, 0x02, 0x02 };
+/* set ip address source: static */
+static uint8_t lan_set_ipsrc_cmd[] = { 0x30, 0x01, 0x01, 0x04, 0x01 };
+static uint8_t lan_set_ipsrc_rsp[] = { 0x34, 0x01, 0x00 };
+
+/* set/get subnet mask: 255.255.255.0 */
+static uint8_t lan_set_netmask_cmd[] = { 0x30, 0x01, 0x01, 0x06,
+ 0xff, 0xff, 0xff, 0x00 };
+static uint8_t lan_set_netmask_rsp[] = { 0x34, 0x01, 0x00 };
+static uint8_t lan_get_netmask_cmd[] = { 0x30, 0x02, 0x01, 0x06, 0x00, 0x00 };
+static uint8_t lan_get_netmask_rsp[] = { 0x34, 0x02, 0x00, 0x11,
+ 0xff, 0xff, 0xff, 0x00 };
+
+/* set/get default gateway ip address: 192.0.2.1 */
+static uint8_t lan_set_defgw_ipaddr_cmd[] = { 0x30, 0x01, 0x01, 0x0c,
+ 0xc0, 0x00, 0x02, 0x01 };
+static uint8_t lan_set_defgw_ipaddr_rsp[] = { 0x34, 0x01, 0x00 };
+static uint8_t lan_get_defgw_ipaddr_cmd[] = { 0x30, 0x02, 0x01, 0x0c,
+ 0x00, 0x00 };
+static uint8_t lan_get_defgw_ipaddr_rsp[] = { 0x34, 0x02, 0x00, 0x11,
+ 0xc0, 0x00, 0x02, 0x01 };
+
+/*
+ * Set and then get LAN configurations
+ */
+static void test_kcs_lan_set_get(void)
+{
+ uint8_t rsp[20];
+ unsigned int rsplen = 0;
+
+ /* set ip address */
+ rsplen = sizeof(rsp);
+ kcs_cmd(lan_set_ipaddr_cmd, sizeof(lan_set_ipaddr_cmd), rsp, &rsplen);
+ g_assert(rsplen == sizeof(lan_set_ipaddr_rsp));
+ g_assert(memcmp(lan_set_ipaddr_rsp, rsp, rsplen) == 0);
+
+ /* get ip address */
+ rsplen = sizeof(rsp);
+ kcs_cmd(lan_get_ipaddr_cmd, sizeof(lan_get_ipaddr_cmd), rsp, &rsplen);
+ g_assert(rsplen == sizeof(lan_get_ipaddr_rsp));
+ g_assert(memcmp(lan_get_ipaddr_rsp, rsp, rsplen) == 0);
+
+ /* set ip address source */
+ rsplen = sizeof(rsp);
+ kcs_cmd(lan_set_ipsrc_cmd, sizeof(lan_set_ipsrc_cmd), rsp, &rsplen);
+ g_assert(rsplen == sizeof(lan_set_ipsrc_rsp));
+ g_assert(memcmp(lan_set_ipsrc_rsp, rsp, rsplen) == 0);
+
+ /* set subnet mask */
+ rsplen = sizeof(rsp);
+ kcs_cmd(lan_set_netmask_cmd, sizeof(lan_set_netmask_cmd), rsp, &rsplen);
+ g_assert(rsplen == sizeof(lan_set_netmask_rsp));
+ g_assert(memcmp(lan_set_netmask_rsp, rsp, rsplen) == 0);
+
+ /* get subnet mask */
+ rsplen = sizeof(rsp);
+ kcs_cmd(lan_get_netmask_cmd, sizeof(lan_get_netmask_cmd), rsp, &rsplen);
+ g_assert(rsplen == sizeof(lan_get_netmask_rsp));
+ g_assert(memcmp(lan_get_netmask_rsp, rsp, rsplen) == 0);
+
+ /* set default gateway ip address */
+ rsplen = sizeof(rsp);
+ kcs_cmd(lan_set_defgw_ipaddr_cmd, sizeof(lan_set_defgw_ipaddr_cmd),
+ rsp, &rsplen);
+ g_assert(rsplen == sizeof(lan_set_defgw_ipaddr_rsp));
+ g_assert(memcmp(lan_set_defgw_ipaddr_rsp, rsp, rsplen) == 0);
+
+ /* get default gateway ip address */
+ rsplen = sizeof(rsp);
+ kcs_cmd(lan_get_defgw_ipaddr_cmd, sizeof(lan_get_defgw_ipaddr_cmd),
+ rsp, &rsplen);
+ g_assert(rsplen == sizeof(lan_get_defgw_ipaddr_rsp));
+ g_assert(memcmp(lan_get_defgw_ipaddr_rsp, rsp, rsplen) == 0);
+}
+
+
int main(int argc, char **argv)
{
char *cmdline;
@@ -340,6 +422,7 @@ int main(int argc, char **argv)
qtest_add_func("/ipmi/local/kcs_channel_access", test_kcs_channel_access);
qtest_add_func("/ipmi/local/kcs_channel_info", test_kcs_channel_info);
qtest_add_func("/ipmi/local/kcs_lan_get", test_kcs_lan_get);
+ qtest_add_func("/ipmi/local/kcs_lan_set_get", test_kcs_lan_set_get);
ret = g_test_run();
qtest_quit(global_qtest);
--
2.43.7
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH 0/2] hw/ipmi/ipmi_bmc_sim: Get/set fake LAN config
2025-10-28 18:01 [PATCH 0/2] hw/ipmi/ipmi_bmc_sim: Get/set fake LAN config Yunpeng Yang
2025-10-28 18:01 ` [PATCH 1/2] hw/ipmi/ipmi_bmc_sim: Support getting fake LAN channel config Yunpeng Yang
2025-10-28 18:01 ` [PATCH 2/2] hw/ipmi/ipmi_bmc_sim: Support setting " Yunpeng Yang
@ 2025-11-24 20:54 ` Corey Minyard
2025-11-26 18:04 ` Yunpeng Yang
2 siblings, 1 reply; 7+ messages in thread
From: Corey Minyard @ 2025-11-24 20:54 UTC (permalink / raw)
To: Yunpeng Yang
Cc: minyard@acm.org, farosas@suse.de, lvivier@redhat.com,
pbonzini@redhat.com, qemu-devel@nongnu.org, Mark Cave-Ayland,
Jonathan Davies, cornelia.huck@de.ibm.com
On Tue, Oct 28, 2025 at 06:01:18PM +0000, Yunpeng Yang wrote:
> Support for a fake LAN channel is added to the device `ipmi_bmc_sim`.
> Although there is no real LAN channel, some testing processes which
> require interactions with BMC LAN channel will become easier.
>
> There's another device `ipmi_bmc_extern` which works together with some
> external BMC simulator, e.g., `ipmi_sim`. More comprehensive BMC
> simulation can be achieved with `ipmi_bmc_extern`. However,
> `ipmi_bmc_sim` is more light-weight and is built into QEMU.
I apologize for the time on this, it slipped between the cracks.
These both look good. I can give a:
Reviewed-by: Corey Minyard <corey@minyard.net>
or
Acked-by: Corey Minyard <corey@minyard.net>
or I can take it into my tree if you aren't bringing it in any place
else.
One thing you should try is doing a migration between a version 1 and
version 2 device, and between two version 2 devices, just to be sure
migration still works. Assuming you haven't done this already.
-corey
>
> Yunpeng Yang (2):
> hw/ipmi/ipmi_bmc_sim: Support getting fake LAN channel config
> hw/ipmi/ipmi_bmc_sim: Support setting fake LAN channel config
>
> hw/ipmi/ipmi_bmc_sim.c | 407 +++++++++++++++++++++++++++++++++++-
> include/hw/ipmi/ipmi.h | 1 +
> qemu-options.hx | 26 +++
> tests/qtest/ipmi-kcs-test.c | 143 +++++++++++++
> 4 files changed, 567 insertions(+), 10 deletions(-)
>
> --
> 2.43.7
>
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 0/2] hw/ipmi/ipmi_bmc_sim: Get/set fake LAN config
2025-11-24 20:54 ` [PATCH 0/2] hw/ipmi/ipmi_bmc_sim: Get/set fake LAN config Corey Minyard
@ 2025-11-26 18:04 ` Yunpeng Yang
2025-11-27 17:28 ` Yunpeng Yang
0 siblings, 1 reply; 7+ messages in thread
From: Yunpeng Yang @ 2025-11-26 18:04 UTC (permalink / raw)
To: corey@minyard.net
Cc: minyard@acm.org, farosas@suse.de, lvivier@redhat.com,
pbonzini@redhat.com, qemu-devel@nongnu.org, Mark Cave-Ayland,
Jonathan Davies, cornelia.huck@de.ibm.com
[-- Attachment #1: Type: text/plain, Size: 2594 bytes --]
Hello Corey,
Thank you for your reply.
Please add tags or take the patches into your tree at your discretion.
I'm not bringing the patches in any place else.
I haven't tested migration between a version 1 and a version 2 device.
I'll do a test and tell you the result. Thank you for your suggestion.
Kind regards,
Yunpeng
________________________________
From: Corey Minyard <corey@minyard.net>
Sent: Monday, November 24, 2025 20:54
To: Yunpeng Yang <yunpeng.yang@nutanix.com>
Cc: minyard@acm.org <minyard@acm.org>; farosas@suse.de <farosas@suse.de>; lvivier@redhat.com <lvivier@redhat.com>; pbonzini@redhat.com <pbonzini@redhat.com>; qemu-devel@nongnu.org <qemu-devel@nongnu.org>; Mark Cave-Ayland <mark.caveayland@nutanix.com>; Jonathan Davies <jond@nutanix.com>; cornelia.huck@de.ibm.com <cornelia.huck@de.ibm.com>
Subject: Re: [PATCH 0/2] hw/ipmi/ipmi_bmc_sim: Get/set fake LAN config
!-------------------------------------------------------------------|
CAUTION: External Email
|-------------------------------------------------------------------!
On Tue, Oct 28, 2025 at 06:01:18PM +0000, Yunpeng Yang wrote:
> Support for a fake LAN channel is added to the device `ipmi_bmc_sim`.
> Although there is no real LAN channel, some testing processes which
> require interactions with BMC LAN channel will become easier.
>
> There's another device `ipmi_bmc_extern` which works together with some
> external BMC simulator, e.g., `ipmi_sim`. More comprehensive BMC
> simulation can be achieved with `ipmi_bmc_extern`. However,
> `ipmi_bmc_sim` is more light-weight and is built into QEMU.
I apologize for the time on this, it slipped between the cracks.
These both look good. I can give a:
Reviewed-by: Corey Minyard <corey@minyard.net>
or
Acked-by: Corey Minyard <corey@minyard.net>
or I can take it into my tree if you aren't bringing it in any place
else.
One thing you should try is doing a migration between a version 1 and
version 2 device, and between two version 2 devices, just to be sure
migration still works. Assuming you haven't done this already.
-corey
>
> Yunpeng Yang (2):
> hw/ipmi/ipmi_bmc_sim: Support getting fake LAN channel config
> hw/ipmi/ipmi_bmc_sim: Support setting fake LAN channel config
>
> hw/ipmi/ipmi_bmc_sim.c | 407 +++++++++++++++++++++++++++++++++++-
> include/hw/ipmi/ipmi.h | 1 +
> qemu-options.hx | 26 +++
> tests/qtest/ipmi-kcs-test.c | 143 +++++++++++++
> 4 files changed, 567 insertions(+), 10 deletions(-)
>
> --
> 2.43.7
>
[-- Attachment #2: Type: text/html, Size: 6133 bytes --]
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 0/2] hw/ipmi/ipmi_bmc_sim: Get/set fake LAN config
2025-11-26 18:04 ` Yunpeng Yang
@ 2025-11-27 17:28 ` Yunpeng Yang
0 siblings, 0 replies; 7+ messages in thread
From: Yunpeng Yang @ 2025-11-27 17:28 UTC (permalink / raw)
To: corey@minyard.net
Cc: minyard@acm.org, farosas@suse.de, lvivier@redhat.com,
pbonzini@redhat.com, qemu-devel@nongnu.org, Mark Cave-Ayland,
Jonathan Davies, cornelia.huck@de.ibm.com
[-- Attachment #1: Type: text/plain, Size: 3464 bytes --]
Hello Corey,
I have done a VM migration test from a v1 `ipmi_bmc_sim` qemu to a v2 `ipmi_bmc_sim` qemu. The migration was successful. The VM had `ipmi_bmc_sim` configured but with no LAN channel.
A v2 to v2 migration with LAN channel was also successful.
Kind regards,
Yunpeng
________________________________
From: Yunpeng Yang <yunpeng.yang@nutanix.com>
Sent: Wednesday, November 26, 2025 18:04
To: corey@minyard.net <corey@minyard.net>
Cc: minyard@acm.org <minyard@acm.org>; farosas@suse.de <farosas@suse.de>; lvivier@redhat.com <lvivier@redhat.com>; pbonzini@redhat.com <pbonzini@redhat.com>; qemu-devel@nongnu.org <qemu-devel@nongnu.org>; Mark Cave-Ayland <mark.caveayland@nutanix.com>; Jonathan Davies <jond@nutanix.com>; cornelia.huck@de.ibm.com <cornelia.huck@de.ibm.com>
Subject: Re: [PATCH 0/2] hw/ipmi/ipmi_bmc_sim: Get/set fake LAN config
Hello Corey,
Thank you for your reply.
Please add tags or take the patches into your tree at your discretion.
I'm not bringing the patches in any place else.
I haven't tested migration between a version 1 and a version 2 device.
I'll do a test and tell you the result. Thank you for your suggestion.
Kind regards,
Yunpeng
________________________________
From: Corey Minyard <corey@minyard.net>
Sent: Monday, November 24, 2025 20:54
To: Yunpeng Yang <yunpeng.yang@nutanix.com>
Cc: minyard@acm.org <minyard@acm.org>; farosas@suse.de <farosas@suse.de>; lvivier@redhat.com <lvivier@redhat.com>; pbonzini@redhat.com <pbonzini@redhat.com>; qemu-devel@nongnu.org <qemu-devel@nongnu.org>; Mark Cave-Ayland <mark.caveayland@nutanix.com>; Jonathan Davies <jond@nutanix.com>; cornelia.huck@de.ibm.com <cornelia.huck@de.ibm.com>
Subject: Re: [PATCH 0/2] hw/ipmi/ipmi_bmc_sim: Get/set fake LAN config
!-------------------------------------------------------------------|
CAUTION: External Email
|-------------------------------------------------------------------!
On Tue, Oct 28, 2025 at 06:01:18PM +0000, Yunpeng Yang wrote:
> Support for a fake LAN channel is added to the device `ipmi_bmc_sim`.
> Although there is no real LAN channel, some testing processes which
> require interactions with BMC LAN channel will become easier.
>
> There's another device `ipmi_bmc_extern` which works together with some
> external BMC simulator, e.g., `ipmi_sim`. More comprehensive BMC
> simulation can be achieved with `ipmi_bmc_extern`. However,
> `ipmi_bmc_sim` is more light-weight and is built into QEMU.
I apologize for the time on this, it slipped between the cracks.
These both look good. I can give a:
Reviewed-by: Corey Minyard <corey@minyard.net>
or
Acked-by: Corey Minyard <corey@minyard.net>
or I can take it into my tree if you aren't bringing it in any place
else.
One thing you should try is doing a migration between a version 1 and
version 2 device, and between two version 2 devices, just to be sure
migration still works. Assuming you haven't done this already.
-corey
>
> Yunpeng Yang (2):
> hw/ipmi/ipmi_bmc_sim: Support getting fake LAN channel config
> hw/ipmi/ipmi_bmc_sim: Support setting fake LAN channel config
>
> hw/ipmi/ipmi_bmc_sim.c | 407 +++++++++++++++++++++++++++++++++++-
> include/hw/ipmi/ipmi.h | 1 +
> qemu-options.hx | 26 +++
> tests/qtest/ipmi-kcs-test.c | 143 +++++++++++++
> 4 files changed, 567 insertions(+), 10 deletions(-)
>
> --
> 2.43.7
>
[-- Attachment #2: Type: text/html, Size: 8745 bytes --]
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 1/2] hw/ipmi/ipmi_bmc_sim: Support getting fake LAN channel config
2025-10-28 18:01 ` [PATCH 1/2] hw/ipmi/ipmi_bmc_sim: Support getting fake LAN channel config Yunpeng Yang
@ 2025-12-01 20:18 ` Philippe Mathieu-Daudé
0 siblings, 0 replies; 7+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-12-01 20:18 UTC (permalink / raw)
To: Yunpeng Yang, minyard@acm.org
Cc: farosas@suse.de, lvivier@redhat.com, pbonzini@redhat.com,
qemu-devel@nongnu.org, Mark Cave-Ayland, corey@minyard.net,
Jonathan Davies, cornelia.huck@de.ibm.com
Hi Yunpeng,
On 28/10/25 19:01, Yunpeng Yang wrote:
> The following IPMI commands are added or modified to support getting
> fake LAN channel configurations from the `ipmi_bmc_sim` device:
> * Get Channel Access;
> * Get Channel Info Command;
> * Get LAN Configuration Parameters.
>
> The fake LAN channel configurations can be specified from QEMU
> commandline options for device `ipmi_bmc_sim`. Inside the guest OS, the
> configurations can be retrieved from the device using some IPMI tools,
> e.g., `ipmitool lan print`.
> Note, there is not a real LAN channel. The fake LAN channel is suitable
> for testing purposes.
>
> Signed-off-by: Yunpeng Yang <yunpeng.yang@nutanix.com>
> ---
> hw/ipmi/ipmi_bmc_sim.c | 297 ++++++++++++++++++++++++++++++++++--
> include/hw/ipmi/ipmi.h | 1 +
> qemu-options.hx | 26 ++++
> tests/qtest/ipmi-kcs-test.c | 60 ++++++++
> 4 files changed, 374 insertions(+), 10 deletions(-)
> /* Same as a timespec struct. */
> struct ipmi_time {
> @@ -170,6 +177,23 @@ typedef struct IPMISensor {
> #define MAX_SENSORS 20
> #define IPMI_WATCHDOG_SENSOR 0
>
> +#define NBYTES_IP 4
> +#define NBYTES_MAC 6
> +
> +typedef struct IPMILan {
> + uint8_t channel;
> + uint8_t ipaddr[NBYTES_IP];
> + uint8_t ipsrc;
> + MACAddr macaddr;
> + uint8_t netmask[NBYTES_IP];
> + uint8_t defgw_ipaddr[NBYTES_IP];
> + MACAddr defgw_macaddr;
> +
> + char *arg_ipaddr;
> + char *arg_netmask;
> + char *arg_defgw_ipaddr;
> +} IPMILan;
> +
> #define MAX_NETFNS 64
>
> typedef struct IPMIRcvBufEntry {
> @@ -215,6 +239,7 @@ struct IPMIBmcSim {
> IPMIFru fru;
> IPMISensor sensors[MAX_SENSORS];
> char *sdr_filename;
> + IPMILan lan;
>
[...]
> +static inline bool is_valid_netmask(const uint8_t *netmask)
> +{
> + uint32_t mask = netmask[3];
> + uint32_t inverted;
> +
> + mask |= (uint32_t) netmask[2] << 8;
> + mask |= (uint32_t) netmask[1] << 16;
> + mask |= (uint32_t) netmask[0] << 24;
Why manually byteswap?
I'd expect such helper already available in include/net/ somewhere,
otherwise what about:
static bool is_ipv4_netmask_valid(const void *buf)
{
uint32_t netmask = ldl_be_p(buf);
return clo32(netmask) + ctz32(netmask) == 32;
}
> + inverted = ~mask;
> + return mask != 0 && (inverted & (inverted + 1)) == 0;
> +}
> @@ -2176,7 +2395,7 @@ static void ipmi_sdr_init(IPMIBmcSim *ibs)
>
> static const VMStateDescription vmstate_ipmi_sim = {
> .name = TYPE_IPMI_BMC_SIMULATOR,
> - .version_id = 1,
> + .version_id = 2,
> .minimum_version_id = 1,
> .fields = (const VMStateField[]) {
> VMSTATE_UINT8(bmc_global_enables, IPMIBmcSim),
> @@ -2198,6 +2417,13 @@ static const VMStateDescription vmstate_ipmi_sim = {
> VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].deassert_states,
> IPMIBmcSim),
> VMSTATE_UINT16(sensors[IPMI_WATCHDOG_SENSOR].assert_enable, IPMIBmcSim),
> + VMSTATE_UINT8_V(lan.channel, IPMIBmcSim, 2),
> + VMSTATE_UINT8_ARRAY_V(lan.ipaddr, IPMIBmcSim, NBYTES_IP, 2),
> + VMSTATE_UINT8_V(lan.ipsrc, IPMIBmcSim, 2),
> + VMSTATE_UINT8_ARRAY_V(lan.macaddr.a, IPMIBmcSim, NBYTES_MAC, 2),
> + VMSTATE_UINT8_ARRAY_V(lan.netmask, IPMIBmcSim, NBYTES_IP, 2),
> + VMSTATE_UINT8_ARRAY_V(lan.defgw_ipaddr, IPMIBmcSim, NBYTES_IP, 2),
> + VMSTATE_UINT8_ARRAY_V(lan.defgw_macaddr.a, IPMIBmcSim, NBYTES_MAC, 2),
Safer would be to add a VMStateDescription for the new IPMILan
structure and link it as subsections, so other code using could just
link as subsection, not duplicating the VMSTATE_FOO() macros.
> VMSTATE_END_OF_LIST()
> }
> };
Regards,
Phil.
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2025-12-01 20:18 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-10-28 18:01 [PATCH 0/2] hw/ipmi/ipmi_bmc_sim: Get/set fake LAN config Yunpeng Yang
2025-10-28 18:01 ` [PATCH 1/2] hw/ipmi/ipmi_bmc_sim: Support getting fake LAN channel config Yunpeng Yang
2025-12-01 20:18 ` Philippe Mathieu-Daudé
2025-10-28 18:01 ` [PATCH 2/2] hw/ipmi/ipmi_bmc_sim: Support setting " Yunpeng Yang
2025-11-24 20:54 ` [PATCH 0/2] hw/ipmi/ipmi_bmc_sim: Get/set fake LAN config Corey Minyard
2025-11-26 18:04 ` Yunpeng Yang
2025-11-27 17:28 ` Yunpeng Yang
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).