Hello, Zdenek,The attached patch adds basic long message support for PICMG-based systems according to the HPM.2 specification.
The patch introduces APIs for setting inbound and outbound messages sizes per selected interface. These 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 patch also moves the Kontron-specific long message support under a OEM option.
Please, review. Unless, there are comments to address, I would like this patch to be submitted into the source tree.
Regards, Dmitry
diff --git a/include/ipmitool/ipmi_hpm2.h b/include/ipmitool/ipmi_hpm2.h --- /dev/null +++ b/include/ipmitool/ipmi_hpm2.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2012 Pigeon Point Systems. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Pigeon Point Systems nor the names of + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. + * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. + * PIGEON POINT SYSTEMS ("PPS") AND ITS LICENSORS SHALL NOT BE LIABLE + * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING + * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL + * PPS OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, + * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR + * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF + * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, + * EVEN IF PPS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +#include <stdint.h> +#include <ipmitool/ipmi_intf.h> + +/* Global HPM.2 defines */ +#define HPM2_REVISION 0x01 +#define HPM3_REVISION 0x01 +#define HPM2_LAN_PARAMS_REV 0x01 +#define HPM2_SOL_PARAMS_REV 0x01 +#define HPM3_LAN_PARAMS_REV 0x01 + +/* HPM.2 capabilities */ +#define HPM2_CAPS_SOL_EXTENSION 0x01 +#define HPM2_CAPS_PACKET_TRACE 0x02 +#define HPM2_CAPS_EXT_MANAGEMENT 0x04 +#define HPM2_CAPS_VERSION_SENSOR 0x08 +#define HPM2_CAPS_DYNAMIC_SESSIONS 0x10 + +#if HAVE_PRAGMA_PACK +#pragma pack(push, 1) +#endif + +/* HPM.2 LAN attach capabilities */ +struct hpm2_lan_attach_capabilities { + uint8_t hpm2_revision_id; + uint16_t lan_channel_mask; + uint8_t hpm2_caps; + uint8_t hpm2_lan_params_start; + uint8_t hpm2_lan_params_rev; + uint8_t hpm2_sol_params_start; + uint8_t hpm2_sol_params_rev; +} ATTRIBUTE_PACKING; + +/* HPM.2 LAN channel capabilities */ +struct hpm2_lan_channel_capabilities { + uint8_t capabilities; + uint8_t attach_type; + uint8_t bandwidth_class; + uint16_t max_inbound_pld_size; + uint16_t max_outbound_pld_size; +} ATTRIBUTE_PACKING; + +#if HAVE_PRAGMA_PACK +#pragma pack(pop) +#endif + +/* HPM.2 command assignments */ +#define HPM2_GET_LAN_ATTACH_CAPABILITIES 0x3E + +extern int hpm2_get_capabilities(struct ipmi_intf * intf, + struct hpm2_lan_attach_capabilities * caps); +extern int hpm2_get_lan_channel_capabilities(struct ipmi_intf * intf, + uint8_t hpm2_lan_params_start, + struct hpm2_lan_channel_capabilities * caps); +extern int hpm2_detect_max_payload_size(struct ipmi_intf * intf); diff --git a/include/ipmitool/ipmi_intf.h b/include/ipmitool/ipmi_intf.h --- a/include/ipmitool/ipmi_intf.h +++ b/include/ipmitool/ipmi_intf.h @@ -180,7 +180,8 @@ struct ipmi_intf { uint8_t target_channel; uint32_t transit_addr; uint8_t transit_channel; - uint8_t channel_buf_size; + uint16_t max_request_data_size; + uint16_t max_response_data_size; uint8_t devnum; @@ -193,6 +194,8 @@ struct ipmi_intf { struct ipmi_rs *(*send_sol)(struct ipmi_intf * intf, struct ipmi_v2_payload * payload); int (*keepalive)(struct ipmi_intf * intf); int (*set_my_addr)(struct ipmi_intf * intf, uint8_t addr); + void (*set_max_request_data_size)(struct ipmi_intf * intf, uint16_t size); + void (*set_max_response_data_size)(struct ipmi_intf * intf, uint16_t size); }; struct ipmi_intf * ipmi_intf_load(char * name); diff --git a/lib/Makefile.am b/lib/Makefile.am --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -39,7 +39,7 @@ libipmitool_la_SOURCES = helper.c ipmi_sdr.c ipmi_sel.c ipmi_sol.c ipmi_pef.c \ ipmi_oem.c ipmi_isol.c ipmi_sunoem.c ipmi_fwum.c ipmi_picmg.c \ ipmi_main.c ipmi_tsol.c ipmi_firewall.c ipmi_kontronoem.c \ ipmi_hpmfwupg.c ipmi_sdradd.c ipmi_ekanalyzer.c ipmi_gendev.c \ - ipmi_ime.c ipmi_delloem.c ipmi_dcmi.c \ + ipmi_ime.c ipmi_delloem.c ipmi_dcmi.c ipmi_hpm2.c \ ../src/plugins/lan/md5.c ../src/plugins/lan/md5.h libipmitool_la_LDFLAGS = -export-dynamic diff --git a/lib/ipmi_fru.c b/lib/ipmi_fru.c --- a/lib/ipmi_fru.c +++ b/lib/ipmi_fru.c @@ -454,13 +454,8 @@ write_fru_area(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id, /* initialize request size only once */ if (fru->max_write_size == 0) { - if (intf->channel_buf_size != 0) { - /* subtract 1 byte for FRU ID an 2 bytes for offset */ - fru->max_write_size = intf->channel_buf_size - 3; - } else { - /* subtract 1 byte for FRU ID an 2 bytes for offset */ - fru->max_write_size = 32 - 3; - } + /* subtract 1 byte for FRU ID an 2 bytes for offset */ + fru->max_write_size = ipmi_intf_get_max_request_data_size(intf) - 3; /* check word access */ if (fru->access) { @@ -611,8 +606,8 @@ read_fru_area(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id, req.msg.data_len = 4; if (fru->max_read_size == 0) { - /* subtract 1 byte for completion code and 1 for byte count */ - fru->max_read_size = 32 - 2; + /* subtract 1 byte for byte count */ + fru->max_read_size = ipmi_intf_get_max_response_data_size(intf) - 1; /* check word access */ if (fru->access) { diff --git a/lib/ipmi_hpm2.c b/lib/ipmi_hpm2.c --- /dev/null +++ b/lib/ipmi_hpm2.c @@ -0,0 +1,279 @@ +/* + * Copyright (c) 2012 Pigeon Point Systems. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Pigeon Point Systems nor the names of + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. + * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. + * PIGEON POINT SYSTEMS ("PPS") AND ITS LICENSORS SHALL NOT BE LIABLE + * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING + * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL + * PPS OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, + * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR + * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF + * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, + * EVEN IF PPS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +#include <ipmitool/ipmi_hpm2.h> +#include <ipmitool/ipmi_intf.h> +#include <ipmitool/log.h> + +#if HAVE_PRAGMA_PACK +#pragma pack(push, 1) +#endif + +/* HPM.x Get Capabilities request */ +struct hpmx_cmd_get_capabilities_rq { + uint8_t picmg_id; + uint8_t hpmx_id; +} ATTRIBUTE_PACKING; + +/* HPM.2 Get Capabilities response */ +struct hpm2_cmd_get_capabilities_rp { + uint8_t picmg_id; + struct hpm2_lan_attach_capabilities caps; +} ATTRIBUTE_PACKING; + +#if HAVE_PRAGMA_PACK +#pragma pack(pop) +#endif + +/* IPMI Get LAN Configuration Parameters command */ +#define IPMI_LAN_GET_CONFIG 0x02 + +int hpm2_get_capabilities(struct ipmi_intf * intf, + struct hpm2_lan_attach_capabilities * caps) +{ + struct ipmi_rq req; + struct ipmi_rs * rsp; + struct hpmx_cmd_get_capabilities_rq rq; + + /* reset result */ + memset(caps, 0, sizeof (struct hpm2_lan_attach_capabilities)); + + /* prepare request */ + rq.picmg_id = 0; + rq.hpmx_id = 2; + + /* prepare request */ + memset(&req, 0, sizeof(req)); + req.msg.netfn = IPMI_NETFN_PICMG; + req.msg.cmd = HPM2_GET_LAN_ATTACH_CAPABILITIES; + req.msg.data = (uint8_t *) &rq; + req.msg.data_len = sizeof(rq); + + + /* send */ + rsp = intf->sendrecv(intf, &req); + + if (rsp) { + if (rsp->ccode == 0xC1) { + lprintf(LOG_DEBUG,"IPM Controller is not HPM.2 compatible"); + return rsp->ccode; + } else if (rsp->ccode) { + lprintf(LOG_NOTICE,"Get HPM.x Capabilities request failed," + " compcode = %x\n", rsp->ccode); + return rsp->ccode; + } + } else { + lprintf(LOG_NOTICE,"Error sending request\n"); + return -1; + } + + /* check response length */ + if (rsp->data_len < 2 || rsp->data_len > 10) { + lprintf(LOG_NOTICE,"Bad response length, len=%d\n", rsp->data_len); + return -1; + } + + /* check HPM.x identifier */ + if (rsp->data[1] != 2) { + lprintf(LOG_NOTICE,"Bad HPM.x ID, id=%d\n", rsp->data[1]); + return rsp->ccode; + } + + /* + * this hardly can happen, since completion code is already checked. + * but check for safety + */ + if (rsp->data_len < 4) { + lprintf(LOG_NOTICE,"Bad response length, len=%d\n", rsp->data_len); + return -1; + } + + /* copy HPM.2 capabilities */ + memcpy(caps, rsp->data + 2, rsp->data_len - 2); + +#if WORDS_BIGENDIAN + /* swap bytes to convert from little-endian format */ + caps->lan_channel_mask = BSWAP_16(caps->lan_channel_mask); +#endif + + /* check HPM.2 revision */ + if (caps->hpm2_revision_id != HPM2_REVISION) { + lprintf(LOG_NOTICE,"Bad HPM.2 revision, rev=%d\n", + caps->hpm2_revision_id); + return -1; + } + + if (caps->lan_channel_mask) { + /* check response length */ + if (rsp->data_len < 8) { + lprintf(LOG_NOTICE,"Bad response length, len=%d\n", rsp->data_len); + return -1; + } + + /* check HPM.2 LAN parameters start */ + if (caps->hpm2_lan_params_start < 0xC0) { + lprintf(LOG_NOTICE,"Bad HPM.2 LAN params start, start=%x\n", + caps->hpm2_lan_params_start); + return -1; + } + + /* check HPM.2 LAN parameters revision */ + if (caps->hpm2_lan_params_rev != HPM2_LAN_PARAMS_REV) { + lprintf(LOG_NOTICE,"Bad HPM.2 LAN params revision, rev=%d\n", + caps->hpm2_lan_params_rev); + return -1; + } + + /* check for HPM.2 SOL extension */ + if (caps->hpm2_caps & HPM2_CAPS_SOL_EXTENSION) { + /* check response length */ + if (rsp->data_len < 10) { + lprintf(LOG_NOTICE,"Bad response length, len=%d\n", rsp->data_len); + return -1; + } + + /* check HPM.2 SOL parameters start */ + if (caps->hpm2_sol_params_start < 0xC0) { + lprintf(LOG_NOTICE,"Bad HPM.2 SOL params start, start=%x\n", + caps->hpm2_sol_params_start); + return -1; + } + + /* check HPM.2 SOL parameters revision */ + if (caps->hpm2_sol_params_rev != HPM2_SOL_PARAMS_REV) { + lprintf(LOG_NOTICE,"Bad HPM.2 SOL params revision, rev=%d\n", + caps->hpm2_sol_params_rev); + return -1; + } + } + } + + return 0; +} + +int hpm2_get_lan_channel_capabilities(struct ipmi_intf * intf, + uint8_t hpm2_lan_params_start, + struct hpm2_lan_channel_capabilities * caps) +{ + struct ipmi_rq req; + struct ipmi_rs * rsp; + uint8_t rq[4]; + + /* reset result */ + memset(caps, 0, sizeof (struct hpm2_lan_channel_capabilities)); + + /* prepare request */ + memset(&req, 0, sizeof(req)); + req.msg.netfn = IPMI_NETFN_TRANSPORT; + req.msg.cmd = IPMI_LAN_GET_CONFIG; + req.msg.data = (uint8_t *) &rq; + req.msg.data_len = sizeof(rq); + + /* prepare request data */ + rq[0] = 0xE; /* sending channel */ + rq[1] = hpm2_lan_params_start; /* HPM.2 Channel Caps */ + rq[2] = rq[3] = 0; + + /* send */ + rsp = intf->sendrecv(intf, &req); + + if (rsp) { + if (rsp->ccode == 0x80) { + lprintf(LOG_DEBUG,"HPM.2 Channel Caps parameter is not supported\n"); + return rsp->ccode; + } else if (rsp->ccode) { + lprintf(LOG_NOTICE,"Get LAN Configuration Parameters request failed," + " compcode = %x\n", rsp->ccode); + return rsp->ccode; + } + } else { + lprintf(LOG_NOTICE,"Error sending request\n"); + return -1; + } + + /* check response length */ + if (rsp->data_len != sizeof (struct hpm2_lan_channel_capabilities) + 1) { + lprintf(LOG_NOTICE,"Bad response length, len=%d\n", rsp->data_len); + return -1; + } + + /* check parameter revision */ + if (rsp->data[0] != HPM2_LAN_PARAMS_REV) { + lprintf(LOG_NOTICE,"Bad HPM.2 LAN parameter revision, rev=%d\n", + rsp->data[0]); + return -1; + } + + /* copy parameter data */ + memcpy(caps, &rsp->data[1], sizeof (struct hpm2_lan_channel_capabilities)); + +#if WORDS_BIGENDIAN + /* swap bytes to convert from little-endian format */ + caps->max_inbound_pld_size = BSWAP_16(caps->max_inbound_pld_size); + caps->max_outbound_pld_size = BSWAP_16(caps->max_outbound_pld_size); +#endif + + return 0; +} + +int hpm2_detect_max_payload_size(struct ipmi_intf * intf) +{ + struct hpm2_lan_attach_capabilities attach_caps; + struct hpm2_lan_channel_capabilities channel_caps; + int err; + + /* query HPM.2 support */ + err = hpm2_get_capabilities(intf, &attach_caps); + + /* check if HPM.2 is supported */ + if (err == 0 && attach_caps.lan_channel_mask) { + /* query channel capabilities */ + err = hpm2_get_lan_channel_capabilities(intf, + attach_caps.hpm2_lan_params_start, &channel_caps); + + /* check if succeeded */ + if (err == 0) { + /* update request and response sizes */ + ipmi_intf_set_max_request_data_size(intf, + channel_caps.max_inbound_pld_size - 7); + ipmi_intf_set_max_response_data_size(intf, + channel_caps.max_outbound_pld_size - 8); + + /* print debug info */ + lprintf(LOG_DEBUG,"Set maximum request size to %d\n" + "Set maximum response size to %d\n", + intf->max_request_data_size, intf->max_response_data_size); + } + } + + return err; +} diff --git a/lib/ipmi_hpmfwupg.c b/lib/ipmi_hpmfwupg.c --- a/lib/ipmi_hpmfwupg.c +++ b/lib/ipmi_hpmfwupg.c @@ -1073,38 +1073,6 @@ HpmfwupgUpgradeStage(struct ipmi_intf *intf, } int -get_max_rq_data_size(struct ipmi_intf *intf) -{ - int bufLength; - /* Check if we receive size in parameters */ - if(intf->channel_buf_size != 0) { - /* Plan for overhead */ - if (intf->target_addr == intf->my_addr) { - bufLength = intf->channel_buf_size - 9; - } else { - bufLength = intf->channel_buf_size - 11; - } - } else if (strstr(intf->name,"lan") != NULL) { - /* Find max buffer length according the connection - * parameters - */ - bufLength = HPMFWUPG_SEND_DATA_COUNT_LAN - 2; - if (intf->transit_addr != intf->my_addr - && intf->transit_addr != 0) { - bufLength -= 8; - } - } else if (strstr(intf->name,"open") != NULL - && intf->target_addr == intf->my_addr) { - bufLength = HPMFWUPG_SEND_DATA_COUNT_KCS - 2; - } else if (intf->target_channel == 7) { - bufLength = HPMFWUPG_SEND_DATA_COUNT_IPMBL; - } else { - bufLength = HPMFWUPG_SEND_DATA_COUNT_IPMB; - } - return bufLength; -} - -int HpmFwupgActionUploadFirmware(struct HpmfwupgComponentBitMask components, struct HpmfwupgUpgradeCtx *pFwupgCtx, unsigned char **pImagePtr, @@ -1151,7 +1119,9 @@ HpmFwupgActionUploadFirmware(struct HpmfwupgComponentBitMask components, + sizeof(struct HpmfwupgFirmwareImage)); pData = pDataInitial; /* Find max buffer length according the connection parameters */ - bufLength = get_max_rq_data_size(intf); + bufLength = ipmi_intf_get_max_request_data_size(intf) + - sizeof(struct HpmfwupgUploadFirmwareBlockReq); + /* Get firmware length */ firmwareLength = pFwImage->length[0]; firmwareLength|= (pFwImage->length[1] << 8) & 0xff00; @@ -1178,8 +1148,7 @@ HpmFwupgActionUploadFirmware(struct HpmfwupgComponentBitMask components, if (!skip) { HpmDisplayUpgrade(0,0,1,0); /* Initialize parameters */ - uploadCmd.req = malloc(get_max_rq_data_size(intf) - + sizeof(struct HpmfwupgUploadFirmwareBlockReq)); + uploadCmd.req = malloc(ipmi_intf_get_max_request_data_size(intf)); if (!uploadCmd.req) { lprintf(LOG_ERR, "ipmitool: malloc failure"); return HPMFWUPG_ERROR; diff --git a/lib/ipmi_main.c b/lib/ipmi_main.c --- a/lib/ipmi_main.c +++ b/lib/ipmi_main.c @@ -979,13 +979,16 @@ ipmi_main(int argc, char ** argv, } /* Enable Big Buffer when requested */ - ipmi_main_intf->channel_buf_size = 0; if ( my_long_packet_size != 0 ) { - printf("Setting large buffer to %i\n", my_long_packet_size); - if (ipmi_kontronoem_set_large_buffer( ipmi_main_intf, my_long_packet_size ) == 0) + /* Enable Big Buffer when requested */ + if (!ipmi_oem_active(ipmi_main_intf, "kontron") || + ipmi_kontronoem_set_large_buffer(ipmi_main_intf, + my_long_packet_size ) == 0) { + printf("Setting large buffer to %i\n", my_long_packet_size); my_long_packet_set = 1; - ipmi_main_intf->channel_buf_size = my_long_packet_size; + ipmi_intf_set_max_request_data_size(ipmi_main_intf, + my_long_packet_size); } } @@ -999,8 +1002,11 @@ ipmi_main(int argc, char ** argv, rc = ipmi_cmd_run(ipmi_main_intf, NULL, 0, NULL); if (my_long_packet_set == 1) { + if (ipmi_oem_active(ipmi_main_intf, "kontron")) + { /* Restore defaults */ ipmi_kontronoem_set_large_buffer( ipmi_main_intf, 0 ); + } } /* clean repository caches */ diff --git a/lib/ipmi_oem.c b/lib/ipmi_oem.c --- a/lib/ipmi_oem.c +++ b/lib/ipmi_oem.c @@ -67,6 +67,10 @@ static struct ipmi_oem_handle ipmi_oem_list[] = { name: "i82571spt", desc: "Intel 82571 MAC with integrated RMCP+ support in super pass-through mode", }, + { + name: "kontron", + desc: "Kontron OEM big buffer support" + }, { 0 } }; diff --git a/lib/ipmi_sdr.c b/lib/ipmi_sdr.c --- a/lib/ipmi_sdr.c +++ b/lib/ipmi_sdr.c @@ -59,7 +59,7 @@ extern int verbose; static int use_built_in; /* Uses DeviceSDRs instead of SDRR */ -static int sdr_max_read_len = GET_SDR_ENTIRE_RECORD; +static int sdr_max_read_len = 0; static int sdr_extended = 0; static long sdriana = 0; @@ -3024,6 +3024,17 @@ ipmi_sdr_get_record(struct ipmi_intf * intf, struct sdr_get_rs * header, req.msg.data = (uint8_t *) & sdr_rq; req.msg.data_len = sizeof (sdr_rq); + /* check if max length is null */ + if ( sdr_max_read_len == 0 ) { + /* get maximum response size */ + sdr_max_read_len = ipmi_intf_get_max_response_data_size(intf) - 2; + + /* cap the number of bytes to read */ + if (sdr_max_read_len > 0xFE) { + sdr_max_read_len = 0xFE; + } + } + /* read SDR record with partial reads * because a full read usually exceeds the maximum * transport buffer size. (completion code 0xca) diff --git a/src/plugins/ipmi_intf.c b/src/plugins/ipmi_intf.c --- a/src/plugins/ipmi_intf.c +++ b/src/plugins/ipmi_intf.c @@ -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,131 @@ ipmi_intf_socket_connect(struct ipmi_intf * intf) } #endif +uint16_t +ipmi_intf_get_max_request_data_size(struct ipmi_intf * intf) +{ + uint16_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 for double bridging */ + if (intf->transit_addr && intf->transit_addr != intf->target_addr) { + /* subtract inner 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) { + return IPMI_DEFAULT_PAYLOAD_SIZE; + } + } + + return size; +} + +uint16_t +ipmi_intf_get_max_response_data_size(struct ipmi_intf * intf) +{ + uint16_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 for double bridging */ + if (intf->transit_addr && intf->transit_addr != intf->target_addr) { + /* subtract inner send message header size */ + size -= 8; + } + + /* + * Check that forwarded response is not greater + * than the default payload size. + */ + if (size > IPMI_DEFAULT_PAYLOAD_SIZE) { + return IPMI_DEFAULT_PAYLOAD_SIZE; + } + } + + return size; +} + +void +ipmi_intf_set_max_request_data_size(struct ipmi_intf * intf, uint16_t size) +{ + 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 (intf->set_max_response_data_size) { + intf->set_max_response_data_size(intf, size); + } else { + intf->max_response_data_size = size; + } +} diff --git a/src/plugins/lan/lan.c b/src/plugins/lan/lan.c --- a/src/plugins/lan/lan.c +++ b/src/plugins/lan/lan.c @@ -52,6 +52,7 @@ #include <ipmitool/ipmi_oem.h> #include <ipmitool/ipmi_strings.h> #include <ipmitool/ipmi_constants.h> +#include <ipmitool/ipmi_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; +} diff --git a/src/plugins/lanplus/lanplus.c b/src/plugins/lanplus/lanplus.c --- a/src/plugins/lanplus/lanplus.c +++ b/src/plugins/lanplus/lanplus.c @@ -55,6 +55,7 @@ #include <ipmitool/ipmi_channel.h> #include <ipmitool/ipmi_intf.h> #include <ipmitool/ipmi_strings.h> +#include <ipmitool/ipmi_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,6 +120,8 @@ 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; @@ -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, }; @@ -3444,6 +3456,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: @@ -3595,5 +3610,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; +} diff --git a/src/plugins/open/open.c b/src/plugins/open/open.c --- a/src/plugins/open/open.c +++ b/src/plugins/open/open.c @@ -65,6 +65,8 @@ # include "open.h" #endif +#define IPMI_OPENIPMI_DEFAULT_PAYLOAD_SIZE 37 + extern int verbose; static int @@ -401,9 +403,19 @@ ipmi_openipmi_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req) return &rsp; } +int ipmi_openipmi_setup(struct ipmi_intf * intf) +{ + /* set defaul payload size */ + intf->max_request_data_size = IPMI_OPENIPMI_DEFAULT_PAYLOAD_SIZE; + intf->max_response_data_size = IPMI_OPENIPMI_DEFAULT_PAYLOAD_SIZE - 1; + + 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, diff --git a/src/plugins/serial/serial_basic.c b/src/plugins/serial/serial_basic.c --- a/src/plugins/serial/serial_basic.c +++ b/src/plugins/serial/serial_basic.c @@ -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; } diff --git a/src/plugins/serial/serial_terminal.c b/src/plugins/serial/serial_terminal.c --- a/src/plugins/serial/serial_terminal.c +++ b/src/plugins/serial/serial_terminal.c @@ -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; }
------------------------------------------------------------------------------ Managing the Performance of Cloud-Based Applications Take advantage of what the Cloud has to offer - Avoid Common Pitfalls. Read the Whitepaper. http://pubads.g.doubleclick.net/gampad/clk?id=121051231&iu=/4140/ostg.clktrk
_______________________________________________ Ipmitool-devel mailing list Ipmitool-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/ipmitool-devel