mirror of
https://github.com/ipmitool/ipmitool.git
synced 2026-06-28 08:11:36 +00:00
ID:302 - HPM.2 long message support
This patch adds basic long message support for PICMG-based systems according to the HPM.2 specification. It also introduces APIs for setting inbound and outbound messages sizes per selected interface. This APIs are used in LAN and LAN+ interfaces to set autonomously detected inbound and outbound message sizes. The newly introduced APIs also replace the existing message size detection code in several ipmitool commands in order to leverage the advantages of long message support (HPM.1 upgrade, SDR acquring, FRU inventory read and write). The Kontron-specific long message support is moved under a OEM option. Commit for Dmitry Bazhenov
This commit is contained in:
@@ -53,6 +53,8 @@
|
||||
#include <ipmitool/ipmi_sdr.h>
|
||||
#include <ipmitool/log.h>
|
||||
|
||||
#define IPMI_DEFAULT_PAYLOAD_SIZE 25
|
||||
|
||||
#ifdef IPMI_INTF_OPEN
|
||||
extern struct ipmi_intf ipmi_open_intf;
|
||||
#endif
|
||||
@@ -497,3 +499,153 @@ ipmi_intf_socket_connect(struct ipmi_intf * intf)
|
||||
}
|
||||
#endif
|
||||
|
||||
uint16_t
|
||||
ipmi_intf_get_max_request_data_size(struct ipmi_intf * intf)
|
||||
{
|
||||
int16_t size;
|
||||
|
||||
size = intf->max_request_data_size;
|
||||
|
||||
/* check if request size is not specified */
|
||||
if (!size) {
|
||||
/*
|
||||
* The IPMB standard overall message length for ‘non -bridging’
|
||||
* messages is specified as 32 bytes, maximum, including slave
|
||||
* address. This sets the upper limit for typical IPMI messages.
|
||||
* With the exception of messages used for bridging messages to
|
||||
* other busses or interfaces (e.g. Master Write-Read and Send Message)
|
||||
* IPMI messages should be designed to fit within this 32-byte maximum.
|
||||
* In order to support bridging, the Master Write -Read and Send Message
|
||||
* commands are allowed to exceed the 32-byte maximum transaction on IPMB
|
||||
*/
|
||||
|
||||
size = IPMI_DEFAULT_PAYLOAD_SIZE;
|
||||
|
||||
/* check if message is forwarded */
|
||||
if (intf->target_addr && intf->target_addr != intf->my_addr) {
|
||||
/* add Send Message request size */
|
||||
size += 8;
|
||||
}
|
||||
}
|
||||
|
||||
/* check if message is forwarded */
|
||||
if (intf->target_addr && intf->target_addr != intf->my_addr) {
|
||||
/* subtract send message request size */
|
||||
size -= 8;
|
||||
|
||||
/*
|
||||
* Check that forwarded request size is not greater
|
||||
* than the default payload size.
|
||||
*/
|
||||
if (size > IPMI_DEFAULT_PAYLOAD_SIZE) {
|
||||
size = IPMI_DEFAULT_PAYLOAD_SIZE;
|
||||
}
|
||||
|
||||
/* check for double bridging */
|
||||
if (intf->transit_addr && intf->transit_addr != intf->target_addr) {
|
||||
/* subtract inner send message request size */
|
||||
size -= 8;
|
||||
}
|
||||
}
|
||||
|
||||
/* check for underflow */
|
||||
if (size < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
uint16_t
|
||||
ipmi_intf_get_max_response_data_size(struct ipmi_intf * intf)
|
||||
{
|
||||
int16_t size;
|
||||
|
||||
size = intf->max_response_data_size;
|
||||
|
||||
/* check if response size is not specified */
|
||||
if (!size) {
|
||||
/*
|
||||
* The IPMB standard overall message length for ‘non -bridging’
|
||||
* messages is specified as 32 bytes, maximum, including slave
|
||||
* address. This sets the upper limit for typical IPMI messages.
|
||||
* With the exception of messages used for bridging messages to
|
||||
* other busses or interfaces (e.g. Master Write-Read and Send Message)
|
||||
* IPMI messages should be designed to fit within this 32-byte maximum.
|
||||
* In order to support bridging, the Master Write -Read and Send Message
|
||||
* commands are allowed to exceed the 32-byte maximum transaction on IPMB
|
||||
*/
|
||||
|
||||
size = IPMI_DEFAULT_PAYLOAD_SIZE; /* response length with subtracted header and checksum byte */
|
||||
|
||||
/* check if message is forwarded */
|
||||
if (intf->target_addr && intf->target_addr != intf->my_addr) {
|
||||
/* add Send Message header size */
|
||||
size += 7;
|
||||
}
|
||||
}
|
||||
|
||||
/* check if message is forwarded */
|
||||
if (intf->target_addr && intf->target_addr != intf->my_addr) {
|
||||
/*
|
||||
* Some IPMI controllers like PICMG AMC Carriers embed responses
|
||||
* to the forwarded messages into the Send Message response.
|
||||
* In order to be sure that the response is not truncated,
|
||||
* subtract the internal message header size.
|
||||
*/
|
||||
size -= 8;
|
||||
|
||||
/*
|
||||
* Check that forwarded response is not greater
|
||||
* than the default payload size.
|
||||
*/
|
||||
if (size > IPMI_DEFAULT_PAYLOAD_SIZE) {
|
||||
size = IPMI_DEFAULT_PAYLOAD_SIZE;
|
||||
}
|
||||
|
||||
/* check for double bridging */
|
||||
if (intf->transit_addr && intf->transit_addr != intf->target_addr) {
|
||||
/* subtract inner send message header size */
|
||||
size -= 8;
|
||||
}
|
||||
}
|
||||
|
||||
/* check for underflow */
|
||||
if (size < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
void
|
||||
ipmi_intf_set_max_request_data_size(struct ipmi_intf * intf, uint16_t size)
|
||||
{
|
||||
if (size < IPMI_DEFAULT_PAYLOAD_SIZE) {
|
||||
lprintf(LOG_ERR, "Request size is too small (%d), leave default size",
|
||||
size);
|
||||
return;
|
||||
}
|
||||
|
||||
if (intf->set_max_request_data_size) {
|
||||
intf->set_max_request_data_size(intf, size);
|
||||
} else {
|
||||
intf->max_request_data_size = size;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ipmi_intf_set_max_response_data_size(struct ipmi_intf * intf, uint16_t size)
|
||||
{
|
||||
if (size < IPMI_DEFAULT_PAYLOAD_SIZE - 1) {
|
||||
lprintf(LOG_ERR, "Response size is too small (%d), leave default size",
|
||||
size);
|
||||
return;
|
||||
}
|
||||
|
||||
if (intf->set_max_response_data_size) {
|
||||
intf->set_max_response_data_size(intf, size);
|
||||
} else {
|
||||
intf->max_response_data_size = size;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
#include <ipmitool/ipmi_oem.h>
|
||||
#include <ipmitool/ipmi_strings.h>
|
||||
#include <ipmitool/ipmi_constants.h>
|
||||
#include <ipmitool/hpm2.h>
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
@@ -67,6 +68,13 @@
|
||||
#define IPMI_LAN_PORT 0x26f
|
||||
#define IPMI_LAN_CHANNEL_E 0x0e
|
||||
|
||||
/*
|
||||
* LAN interface is required to support 45 byte request transactions and
|
||||
* 42 byte response transactions.
|
||||
*/
|
||||
#define IPMI_LAN_MAX_REQUEST_SIZE 38 /* 45 - 7 */
|
||||
#define IPMI_LAN_MAX_RESPONSE_SIZE 34 /* 42 - 8 */
|
||||
|
||||
extern const struct valstr ipmi_privlvl_vals[];
|
||||
extern const struct valstr ipmi_authtype_session_vals[];
|
||||
extern int verbose;
|
||||
@@ -88,6 +96,8 @@ static int ipmi_lan_send_rsp(struct ipmi_intf * intf, struct ipmi_rs * rsp);
|
||||
static int ipmi_lan_open(struct ipmi_intf * intf);
|
||||
static void ipmi_lan_close(struct ipmi_intf * intf);
|
||||
static int ipmi_lan_ping(struct ipmi_intf * intf);
|
||||
static void ipmi_lan_set_max_rq_data_size(struct ipmi_intf * intf, uint16_t size);
|
||||
static void ipmi_lan_set_max_rp_data_size(struct ipmi_intf * intf, uint16_t size);
|
||||
|
||||
struct ipmi_intf ipmi_lan_intf = {
|
||||
name: "lan",
|
||||
@@ -100,6 +110,8 @@ struct ipmi_intf ipmi_lan_intf = {
|
||||
recv_sol: ipmi_lan_recv_sol,
|
||||
send_sol: ipmi_lan_send_sol,
|
||||
keepalive: ipmi_lan_keepalive,
|
||||
set_max_request_data_size: ipmi_lan_set_max_rq_data_size,
|
||||
set_max_response_data_size: ipmi_lan_set_max_rp_data_size,
|
||||
target_addr: IPMI_BMC_SLAVE_ADDR,
|
||||
};
|
||||
|
||||
@@ -2055,6 +2067,10 @@ ipmi_lan_open(struct ipmi_intf * intf)
|
||||
}
|
||||
|
||||
intf->manufacturer_id = ipmi_get_oem(intf);
|
||||
|
||||
/* automatically detect interface request and response sizes */
|
||||
hpm2_detect_max_payload_size(intf);
|
||||
|
||||
return intf->fd;
|
||||
}
|
||||
|
||||
@@ -2067,5 +2083,30 @@ ipmi_lan_setup(struct ipmi_intf * intf)
|
||||
return -1;
|
||||
}
|
||||
memset(intf->session, 0, sizeof(struct ipmi_session));
|
||||
|
||||
/* setup default LAN maximum request and response sizes */
|
||||
intf->max_request_data_size = IPMI_LAN_MAX_REQUEST_SIZE;
|
||||
intf->max_response_data_size = IPMI_LAN_MAX_RESPONSE_SIZE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
ipmi_lan_set_max_rq_data_size(struct ipmi_intf * intf, uint16_t size)
|
||||
{
|
||||
if (size + 7 > 0xFF) {
|
||||
size = 0xFF - 7;
|
||||
}
|
||||
|
||||
intf->max_request_data_size = size;
|
||||
}
|
||||
|
||||
static void
|
||||
ipmi_lan_set_max_rp_data_size(struct ipmi_intf * intf, uint16_t size)
|
||||
{
|
||||
if (size + 8 > 0xFF) {
|
||||
size = 0xFF - 8;
|
||||
}
|
||||
|
||||
intf->max_response_data_size = size;
|
||||
}
|
||||
|
||||
@@ -55,6 +55,7 @@
|
||||
#include <ipmitool/ipmi_channel.h>
|
||||
#include <ipmitool/ipmi_intf.h>
|
||||
#include <ipmitool/ipmi_strings.h>
|
||||
#include <ipmitool/hpm2.h>
|
||||
#include <ipmitool/bswap.h>
|
||||
#include <openssl/rand.h>
|
||||
|
||||
@@ -65,6 +66,13 @@
|
||||
#include "rmcp.h"
|
||||
#include "asf.h"
|
||||
|
||||
/*
|
||||
* LAN interface is required to support 45 byte request transactions and
|
||||
* 42 byte response transactions.
|
||||
*/
|
||||
#define IPMI_LAN_MAX_REQUEST_SIZE 38 /* 45 - 7 */
|
||||
#define IPMI_LAN_MAX_RESPONSE_SIZE 34 /* 42 - 8 */
|
||||
|
||||
extern const struct valstr ipmi_rakp_return_codes[];
|
||||
extern const struct valstr ipmi_priv_levels[];
|
||||
extern const struct valstr ipmi_auth_algorithms[];
|
||||
@@ -112,8 +120,10 @@ static int check_sol_packet_for_new_data(
|
||||
static void ack_sol_packet(
|
||||
struct ipmi_intf * intf,
|
||||
struct ipmi_rs * rsp);
|
||||
static void ipmi_lanp_set_max_rq_data_size(struct ipmi_intf * intf, uint16_t size);
|
||||
static void ipmi_lanp_set_max_rp_data_size(struct ipmi_intf * intf, uint16_t size);
|
||||
|
||||
static uint8_t bridgePossible = 0;
|
||||
static uint8_t bridgePossible = 0;
|
||||
|
||||
struct ipmi_intf ipmi_lanplus_intf = {
|
||||
name: "lanplus",
|
||||
@@ -125,6 +135,8 @@ struct ipmi_intf ipmi_lanplus_intf = {
|
||||
recv_sol: ipmi_lanplus_recv_sol,
|
||||
send_sol: ipmi_lanplus_send_sol,
|
||||
keepalive: ipmi_lanplus_keepalive,
|
||||
set_max_request_data_size: ipmi_lanp_set_max_rq_data_size,
|
||||
set_max_response_data_size: ipmi_lanp_set_max_rp_data_size,
|
||||
target_addr: IPMI_BMC_SLAVE_ADDR,
|
||||
};
|
||||
|
||||
@@ -3473,6 +3485,9 @@ ipmi_lanplus_open(struct ipmi_intf * intf)
|
||||
intf->manufacturer_id = ipmi_get_oem(intf);
|
||||
bridgePossible = 1;
|
||||
|
||||
/* automatically detect interface request and response sizes */
|
||||
hpm2_detect_max_payload_size(intf);
|
||||
|
||||
return intf->fd;
|
||||
|
||||
fail:
|
||||
@@ -3624,5 +3639,46 @@ static int ipmi_lanplus_setup(struct ipmi_intf * intf)
|
||||
return -1;
|
||||
}
|
||||
memset(intf->session, 0, sizeof(struct ipmi_session));
|
||||
|
||||
/* setup default LAN maximum request and response sizes */
|
||||
intf->max_request_data_size = IPMI_LAN_MAX_REQUEST_SIZE;
|
||||
intf->max_response_data_size = IPMI_LAN_MAX_RESPONSE_SIZE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ipmi_lanp_set_max_rq_data_size(struct ipmi_intf * intf, uint16_t size)
|
||||
{
|
||||
if (intf->session->cipher_suite_id == 3) {
|
||||
/*
|
||||
* encrypted payload can only be multiple of 16 bytes
|
||||
*/
|
||||
size &= ~15;
|
||||
|
||||
/*
|
||||
* decrement payload size on confidentiality header size
|
||||
* plus minimal confidentiality trailer size
|
||||
*/
|
||||
size -= (16 + 1);
|
||||
}
|
||||
|
||||
intf->max_request_data_size = size;
|
||||
}
|
||||
|
||||
static void ipmi_lanp_set_max_rp_data_size(struct ipmi_intf * intf, uint16_t size)
|
||||
{
|
||||
if (intf->session->cipher_suite_id == 3) {
|
||||
/*
|
||||
* encrypted payload can only be multiple of 16 bytes
|
||||
*/
|
||||
size &= ~15;
|
||||
|
||||
/*
|
||||
* decrement payload size on confidentiality header size
|
||||
* plus minimal confidentiality trailer size
|
||||
*/
|
||||
size -= (16 + 1);
|
||||
}
|
||||
|
||||
intf->max_response_data_size = size;
|
||||
}
|
||||
|
||||
@@ -65,6 +65,22 @@
|
||||
# include "open.h"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Maximum input message size for KCS/SMIC is 40 with 2 utility bytes and
|
||||
* 38 bytes of data.
|
||||
* Maximum input message size for BT is 42 with 4 utility bytes and
|
||||
* 38 bytes of data.
|
||||
*/
|
||||
#define IPMI_OPENIPMI_MAX_RQ_DATA_SIZE 38
|
||||
|
||||
/**
|
||||
* Maximum output message size for KCS/SMIC is 38 with 2 utility bytes, a byte
|
||||
* for completion code and 35 bytes of data.
|
||||
* Maximum output message size for BT is 40 with 4 utility bytes, a byte
|
||||
* for completion code and 35 bytes of data.
|
||||
*/
|
||||
#define IPMI_OPENIPMI_MAX_RS_DATA_SIZE 35
|
||||
|
||||
extern int verbose;
|
||||
|
||||
static int
|
||||
@@ -401,9 +417,19 @@ ipmi_openipmi_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req)
|
||||
return &rsp;
|
||||
}
|
||||
|
||||
int ipmi_openipmi_setup(struct ipmi_intf * intf)
|
||||
{
|
||||
/* set default payload size */
|
||||
intf->max_request_data_size = IPMI_OPENIPMI_MAX_RQ_DATA_SIZE;
|
||||
intf->max_response_data_size = IPMI_OPENIPMI_MAX_RS_DATA_SIZE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct ipmi_intf ipmi_open_intf = {
|
||||
name: "open",
|
||||
desc: "Linux OpenIPMI Interface",
|
||||
setup: ipmi_openipmi_setup,
|
||||
open: ipmi_openipmi_open,
|
||||
close: ipmi_openipmi_close,
|
||||
sendrecv: ipmi_openipmi_send_cmd,
|
||||
|
||||
@@ -189,6 +189,10 @@ serial_bm_setup(struct ipmi_intf * intf)
|
||||
return -1;
|
||||
}
|
||||
memset(intf->session, 0, sizeof(struct ipmi_session));
|
||||
|
||||
/* setup default LAN maximum request and response sizes */
|
||||
intf->max_request_data_size = SERIAL_BM_MAX_RQ_SIZE;
|
||||
intf->max_response_data_size = SERIAL_BM_MAX_RS_SIZE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -894,6 +894,10 @@ ipmi_serial_term_setup(struct ipmi_intf * intf)
|
||||
}
|
||||
|
||||
memset(intf->session, 0, sizeof(struct ipmi_session));
|
||||
|
||||
/* setup default LAN maximum request and response sizes */
|
||||
intf->max_request_data_size = IPMI_SERIAL_MAX_RQ_SIZE;
|
||||
intf->max_response_data_size = IPMI_SERIAL_MAX_RS_SIZE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user