Hi Dmitry,
I have a similar approach to what you outlined, but I did not find the need to
do
anything different the the "-m" command line switch. I've attached a patch
I've
been using to resolve the issue I was having and would appreciate any feedback
you
might have on my approach. The patch is for the CVS ipmitool source code at
TOB
this morning.
I changed ipmi_main() to always open the interface using either 0x20 or the
address
specified with the "-m" switch. With the code as it exists today, open is
sometimes
done in main and sometimes done when the first IPMI request is made. I found
the
defer of the open quire problematic, so I changed the code to always do the
open prior
to the first IPMI request. After the initial open, I use the PICMG get
address info to
get the IPMB-0 address. If I was able to discover an address, I close and
re-open
the interface with the discovered IPMB-0 address as I found this was necessary
to make
sure that the open ipmi driver had the correct address of the target IPMB-0.
Then, if bridging is
specified with "-t" and/or "-T", I get the bridge target IPMB-0 address and
store that away to
determine when bridging is necessary for sensors identified in the SDR
repository accessed via
the bridging command line arguments.
Thanks,
Jim
-- Jim Mankovich | jm...@hp.com (US Mountain Time) --
On 4/15/2013 9:05 AM, Dmitry Bazhenov wrote:
Hello, Jim,
Your understanding is correct. Moreover, we already have a patch which
solves the issue (in our local IPMITool repo). We are going to submit
the patch for this issue shortly.
And to the topic raised.
The sensor owner ID in the SDR in my opinion shall match with the IPMC
slave address on the primary IPMB bus (channel #0).
Since there are cases when the IPMC accessed from other channels (than
channel #0), like LAN, the slave address of the IPMC on that channel may
not match with the primary IPMB address.
We solved this problem as follows:
- introduced a BMC address which can be overridden by "-m" command-line
parameter (default valuse is 20h). This address is used to access the
IPMC on which a session to establish a session (for LAN).
- then using Get PICMG Properties to check whether the board is a
PICMG-based system.
- use either Get Address Info for FRU #0 or fetch the Management
Controller Locator Record to query the IPMC slave address on the primary
IPMB.
- store the fetched slave address. it then used to match the sensor
owner ID to decide if the bridging to sensor is required on not.
- for the case when bridging is used, the stored slave address is used
to compose the Send Message command is return address.
Regards,
Dmitry
15.04.2013 20:47, Jim Mankovich пишет:
All,
I've been digging into various issue associated with ipmitool bridging
on a PICMG
system and I wouldappreciate some help with understanding what the
actual intended
use of the bridging command line arguments was. There are two
different bridging
argument specifications, -t target_address/-b target_channel (single
bridge), and
-T transit_address/-B transit_channel (dual bridge).
When only -t is specified, single level bridging will be used to read
the SDR repository
if the address specified by -t is not equivalent to the ipmitool
identified IPMB-0 address.
Note: The ipmitool identified IPMB-0 address is either the default of
0x20, or specified
on the command line via the -m address switch, or discovered via PICMG
get address
info.
In addition to -t, you may also specify a transit address via -T.If a
transit address is
specified, dual bridging will be used to read the SDR repository(via the
transit address
to get to the target identified via -t). The specification of a
transit address without a
target address is meaningless as the transit address is not used unless
there is a target
address specification with -t.
Does my description agree with your understanding of these switches and
their use?
Now, in addition to bridging to read the SDR repository, bridging will
also occur to access
an individual sensor if the sensor owner id identified in the SDR
repository does not match
the ipmitool identified IPMB-0 address. This bridging will override
the specified target address
identified via the -t switch, but will make use of the transit address
(and dual bridge) when
both -t and -T are specified.
This bridging implementation has issues on the PICMG system I have been
using when
addressing sensors whose owner id and channel specification in the SDR
repository do
not identify the exact same addressing that was used to read the SDR
repository.
For example:If a sensor identified in an SDR repository resides on
IPMB-0 (channel 0),
but the SDR repository was accessed via bridging on IPMB-L (channel 7),
the sensor can't
be accessed with the current code because the sensor will be addressed
via bridging using
channel 0 (from the SDR repository)instead of channel 7 (from the -b
channel specification).
The problem is that when using bridging to access an SDR repository, the
bridged SDR
repository destination may actually identify another IPMB-0 at the
bridged destination.
If this is the case, then the sensor can simply be read using the same
bridging as was
used to read the SDR repository.
On PICMG compliant systems, this issue can be resolved by getting the
IPMB-0 address
of the target and compare this target IPMB-0 address with the sensor
owner id/channel
number from the SDR repository.If the sensor owner id is equal to the
target IPMB-0
address and the sensor channel is 0, then the sensor can be accessed
using the same
addressing as was used to address the SDR repository.
I have some ipmitool changes in the works which resolve the sensor
bridging issue
I've described, but I need some insight from someone more familiar with
PICMG and
sensor bridging to make sure my analysis of the problem I'm seeing is
correct.
Thanks in advance,
Jim
--
-- Jim Mankovich |jm...@hp.com (US Mountain Time) --
------------------------------------------------------------------------------
Precog is a next-generation analytics platform capable of advanced
analytics on semi-structured data. The platform includes APIs for building
apps and a phenomenal toolset for data science. Developers can use
our toolset for easy data analysis & visualization. Get a free account!
http://www2.precog.com/precogplatform/slashdotnewsletter
_______________________________________________
Ipmitool-devel mailing list
Ipmitool-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/ipmitool-devel
------------------------------------------------------------------------------
Precog is a next-generation analytics platform capable of advanced
analytics on semi-structured data. The platform includes APIs for building
apps and a phenomenal toolset for data science. Developers can use
our toolset for easy data analysis & visualization. Get a free account!
http://www2.precog.com/precogplatform/slashdotnewsletter
_______________________________________________
Ipmitool-devel mailing list
Ipmitool-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/ipmitool-devel
>From 261e73d7644d15186225e3c36ebcc1ad0d4d34d4 Mon Sep 17 00:00:00 2001
From: Jim Mankovich <jm...@hp.com>
Date: Mon, 15 Apr 2013 08:24:22 -0600
Subject: [PATCH] PICMG Sensor Bridging
Signed-off-by: Jim Mankovich <jm...@hp.com>
---
include/ipmitool/ipmi_intf.h | 2 +
include/ipmitool/ipmi_picmg.h | 2 +
include/ipmitool/ipmi_sdr.h | 24 +++++++
lib/ipmi_fru.c | 20 ++++--
lib/ipmi_main.c | 149 ++++++++++++++++++-----------------------
lib/ipmi_picmg.c | 94 ++++++++++++++++++++++++++
lib/ipmi_sdr.c | 106 ++++++++++++++++-------------
lib/ipmi_sel.c | 4 +-
lib/ipmi_sensor.c | 44 +++++++-----
src/plugins/lanplus/lanplus.c | 26 +++++--
src/plugins/open/open.c | 3 +-
11 files changed, 312 insertions(+), 162 deletions(-)
diff --git a/include/ipmitool/ipmi_intf.h b/include/ipmitool/ipmi_intf.h
index 8b5b6f6..151573c 100644
--- a/include/ipmitool/ipmi_intf.h
+++ b/include/ipmitool/ipmi_intf.h
@@ -165,11 +165,13 @@ struct ipmi_intf {
int opened;
int abort;
int noanswer;
+ int picmg_avail;
IPMI_OEM manufacturer_id;
struct ipmi_session * session;
struct ipmi_oem_handle * oem;
struct ipmi_cmd * cmdlist;
+ uint8_t target_ipmb_addr;
uint32_t my_addr;
uint32_t target_addr;
uint8_t target_lun;
diff --git a/include/ipmitool/ipmi_picmg.h b/include/ipmitool/ipmi_picmg.h
index 5f73be2..4247e37 100644
--- a/include/ipmitool/ipmi_picmg.h
+++ b/include/ipmitool/ipmi_picmg.h
@@ -205,5 +205,7 @@ struct sAmcPortState {
int ipmi_picmg_main (struct ipmi_intf * intf, int argc, char ** argv);
+uint8_t picmg_ipmb_discover(struct ipmi_intf *intf);
+uint8_t ipmi_picmg_ipmb_address(struct ipmi_intf *intf);
#endif
diff --git a/include/ipmitool/ipmi_sdr.h b/include/ipmitool/ipmi_sdr.h
index 0f168d2..724d0cd 100644
--- a/include/ipmitool/ipmi_sdr.h
+++ b/include/ipmitool/ipmi_sdr.h
@@ -836,6 +836,30 @@ struct sensor_reading {
const char *s_a_units; /* analog value units string */
};
+/*
+ * Determine if bridging is necessary to address a sensor at the given
+ * address (_addr) and (_chan) via the interface (_intf).
+ *
+ * If the sensor is being addressed on channel zero, it resides on
+ * IPMB-0. If the interface target IPMB-0 address is exactly the same as
+ * the sensor address then the sensor resides on the target IPMB-0
+ * so we don't need extra levels of bridging to address the sensor.
+ * Or
+ * If the sensor target address and channel match the interface target address
+ * and channel then there is no extra levels of bridging required.
+ *
+ * Note:
+ * The target IPMB-0 address is the address of the SDR repository that was
+ * accessed using the user specified bridging command line arguments.
+ * Access to any sensor on the target IPMB-0 can be addressed using the
+ * target address and transit address in the interface.
+ */
+#define BRIDGE_TO_SENSOR(_intf, _addr, _chan) \
+ ( !((_chan == 0 && _intf->target_ipmb_addr && \
+ _intf->target_ipmb_addr == _addr) || \
+ (_addr == _intf->target_addr && _chan == _intf->target_channel)) )
+
+
struct ipmi_sdr_iterator *ipmi_sdr_start(struct ipmi_intf *intf,
int use_builtin);
struct sdr_get_rs *ipmi_sdr_get_next_header(struct ipmi_intf *intf,
diff --git a/lib/ipmi_fru.c b/lib/ipmi_fru.c
index 90da15b..07c8675 100644
--- a/lib/ipmi_fru.c
+++ b/lib/ipmi_fru.c
@@ -3006,7 +3006,8 @@ int
ipmi_fru_print(struct ipmi_intf * intf, struct sdr_record_fru_locator * fru)
{
char desc[17];
- uint32_t save_addr;
+ uint32_t save_addr = 0;
+ uint32_t save_channel;
int rc = 0;
if (fru == NULL)
@@ -3046,14 +3047,19 @@ ipmi_fru_print(struct ipmi_intf * intf, struct sdr_record_fru_locator * fru)
switch (fru->dev_type_modifier) {
case 0x00:
case 0x02:
- /* save current target address */
- save_addr = intf->target_addr;
- /* set new target address for bridged commands */
- intf->target_addr = fru->dev_slave_addr;
+ if (BRIDGE_TO_SENSOR(intf, fru->dev_slave_addr,
+ fru->channel_num)) {
+ save_addr = intf->target_addr;
+ intf->target_addr = fru->dev_slave_addr;
+ save_channel = intf->target_channel;
+ intf->target_channel = fru->channel_num;
+ }
/* print FRU */
rc = __ipmi_fru_print(intf, fru->device_id);
- /* restore previous target */
- intf->target_addr = save_addr;
+ if (save_addr) {
+ intf->target_addr = save_addr;
+ intf->target_channel = save_channel;
+ }
break;
case 0x01:
rc = ipmi_spd_print_fru(intf, fru->device_id);
diff --git a/lib/ipmi_main.c b/lib/ipmi_main.c
index cc04b51..ee31e9f 100644
--- a/lib/ipmi_main.c
+++ b/lib/ipmi_main.c
@@ -84,13 +84,6 @@ extern int csv_output;
extern const struct valstr ipmi_privlvl_vals[];
extern const struct valstr ipmi_authtype_session_vals[];
-/* defined in ipmishell.c */
-#ifdef HAVE_READLINE
-extern int ipmi_shell_main(struct ipmi_intf * intf, int argc, char ** argv);
-#endif
-extern int ipmi_set_main(struct ipmi_intf * intf, int argc, char ** argv);
-extern int ipmi_exec_main(struct ipmi_intf * intf, int argc, char ** argv);
-
static struct ipmi_intf * ipmi_main_intf = NULL;
/* ipmi_password_file_read - Open file and read password from it
@@ -245,7 +238,6 @@ ipmi_option_usage(const char * progname, struct ipmi_cmd * cmdlist, struct ipmi_
lprintf(LOG_NOTICE, " -m address Set local IPMB address");
lprintf(LOG_NOTICE, " -b channel Set destination channel for bridged request");
lprintf(LOG_NOTICE, " -t address Bridge request to remote target address");
- lprintf(LOG_NOTICE, " -M address Set transit local address for bridge request(dual bridge)");
lprintf(LOG_NOTICE, " -B channel Set transit channel for bridged request (dual bridge)");
lprintf(LOG_NOTICE, " -T address Set transit address for bridge request (dual bridge)");
lprintf(LOG_NOTICE, " -l lun Set destination lun for raw commands");
@@ -364,7 +356,7 @@ ipmi_main(int argc, char ** argv,
uint8_t transit_addr = 0;
uint8_t transit_channel = 0;
uint8_t target_lun = 0;
- uint8_t my_addr = 0;
+ uint8_t arg_addr = 0, addr;
uint16_t my_long_packet_size=0;
uint8_t my_long_packet_set=0;
uint8_t lookupbit = 0x10; /* use name-only lookup by default */
@@ -727,7 +719,7 @@ ipmi_main(int argc, char ** argv,
}
break;
case 'm':
- if (str2uchar(optarg, &my_addr) != 0) {
+ if (str2uchar(optarg, &arg_addr) != 0) {
lprintf(LOG_ERR, "Invalid parameter given or out of range for '-m'.");
rc = -1;
goto out_free;
@@ -880,94 +872,79 @@ ipmi_main(int argc, char ** argv,
ipmi_intf_session_set_sol_escape_char(ipmi_main_intf, sol_escape_char);
ipmi_intf_session_set_cipher_suite_id(ipmi_main_intf, cipher_suite_id);
- /* setup destination lun if given */
- ipmi_main_intf->target_lun = target_lun ;
+ ipmi_main_intf->devnum = devnum;
- /* setup destination channel if given */
- ipmi_main_intf->target_channel = target_channel ;
+ /* Open the interface with the default local or specified address */
+ ipmi_main_intf->my_addr = arg_addr ? arg_addr : IPMI_BMC_SLAVE_ADDR;
+ if (ipmi_main_intf->open != NULL)
+ ipmi_main_intf->open(ipmi_main_intf);
- ipmi_main_intf->devnum = devnum;
+ /* Attempt picmg discovery of the actual interface address */
+ addr = picmg_ipmb_discover(ipmi_main_intf);
- /* setup IPMB local and target address if given */
- if (my_addr) {
- ipmi_main_intf->my_addr = my_addr;
- } else {
- /* Use the default for the payload source address */
- my_addr = 0x20;
-
- /* Check if PICMG extension is available to use the function
- * GetDeviceLocator to retreive i2c address PICMG hack to set
- * right IPMB address, If extension is not supported, should
- * not give any problems
- * PICMG Extension Version 2.0 (PICMG 3.0 Revision 1.0 ATCA) to
- * PICMG Extension Version 2.3 (PICMG 3.0 Revision 3.0 ATCA)
- */
-
- /* First, check if PICMG extension is available and supported */
- struct ipmi_rq req;
- struct ipmi_rs *rsp;
- char msg_data;
- unsigned char version_accepted = 0;
-
- lprintf(LOG_INFO, "Running PICMG GetDeviceLocator" );
- memset(&req, 0, sizeof(req));
- req.msg.netfn = IPMI_NETFN_PICMG;
- req.msg.cmd = PICMG_GET_PICMG_PROPERTIES_CMD;
- msg_data = 0x00;
- req.msg.data = &msg_data;
- req.msg.data_len = 1;
- msg_data = 0;
-
- rsp = ipmi_main_intf->sendrecv(ipmi_main_intf, &req);
- if (rsp && !rsp->ccode) {
- if ( (rsp->data[0] == 0) &&
- ((rsp->data[1] & 0x0F) == PICMG_ATCA_MAJOR_VERSION) ) {
- version_accepted = 1;
- lprintf(LOG_INFO, "Discovered PICMG Extension %d.%d",
- (rsp->data[1] & 0x0f), (rsp->data[1] >> 4));
- }
+ /*
+ * If we discovered the ipmb address and it is not the same as what we
+ * used for open, close and re-open the interface with the discovered
+ * address.
+ *
+ * The re-open is necessary to make sure that the interface gets
+ * the correct ipmb address identified by the picmg ipmb discovery.
+ */
+ if (addr != 0 && addr != ipmi_main_intf->my_addr) {
+ ipmi_cleanup(ipmi_main_intf);
+ if (ipmi_main_intf->opened > 0 && ipmi_main_intf->close) {
+ ipmi_main_intf->close(ipmi_main_intf);
}
-
- if (version_accepted == 1) {
- lprintf(LOG_DEBUG, "Running PICMG GetDeviceLocator");
- memset(&req, 0, sizeof(req));
- req.msg.netfn = IPMI_NETFN_PICMG;
- req.msg.cmd = PICMG_GET_ADDRESS_INFO_CMD;
- msg_data = 0x00;
- req.msg.data = &msg_data;
- req.msg.data_len = 1;
- msg_data = 0;
-
- rsp = ipmi_main_intf->sendrecv(ipmi_main_intf, &req);
- if (rsp && !rsp->ccode) {
- ipmi_main_intf->my_addr = rsp->data[2];
- ipmi_main_intf->target_addr = ipmi_main_intf->my_addr;
- lprintf(LOG_INFO, "Discovered IPMB address = 0x%x",
- ipmi_main_intf->my_addr);
- }
- } else {
- lprintf(LOG_INFO,
- "No PICMG Extenstion discovered, keeping IPMB address 0x20");
+ /* Set the new interface address an re-open the interface */
+ ipmi_main_intf->my_addr = addr;
+ if (ipmi_main_intf->open) {
+ ipmi_main_intf->open(ipmi_main_intf);
}
}
- if ( target_addr > 0 && (target_addr != my_addr) ) {
- /* need to open the interface first */
- if (ipmi_main_intf->open != NULL)
- ipmi_main_intf->open(ipmi_main_intf);
-
+ /* If bridging addresses are specified, handle them */
+ if (transit_addr > 0 || target_addr > 0) {
+ /* sanity check, transit makes no sense without a target */
+ if ((transit_addr != 0 || transit_channel != 0) &&
+ target_addr == 0) {
+ lprintf(LOG_ERR,
+ "Transit address/channel %#x/%#x ignored. "
+ "Target address must be specified!",
+ transit_addr, transit_channel);
+ goto out_free;
+ }
ipmi_main_intf->target_addr = target_addr;
+ ipmi_main_intf->target_lun = target_lun ;
+ ipmi_main_intf->target_channel = target_channel ;
+
+ ipmi_main_intf->transit_addr = transit_addr;
+ ipmi_main_intf->transit_channel = transit_channel;
+
- if (transit_addr > 0) {
- ipmi_main_intf->transit_addr = transit_addr;
- ipmi_main_intf->transit_channel = transit_channel;
- } else {
- ipmi_main_intf->transit_addr = ipmi_main_intf->my_addr;
- }
/* must be admin level to do this over lan */
ipmi_intf_session_set_privlvl(ipmi_main_intf, IPMI_SESSION_PRIV_ADMIN);
+ /* Get the ipmb address of the targeted entity */
+ ipmi_main_intf->target_ipmb_addr =
+ ipmi_picmg_ipmb_address(ipmi_main_intf);
+ lprintf(LOG_DEBUG, "Specified addressing Target %#x:%#x Transit %#x:%#x",
+ ipmi_main_intf->target_addr,
+ ipmi_main_intf->target_channel,
+ ipmi_main_intf->transit_addr,
+ ipmi_main_intf->transit_channel);
+ lprintf(LOG_DEBUG, "Discovered Target IPMB-0 address %#x",
+ ipmi_main_intf->target_ipmb_addr);
}
+ lprintf(LOG_DEBUG, "Interface address: my_addr %#x "
+ "transit %#x:%#x target %#x:%#x "
+ "ipmb_target %#x\n",
+ ipmi_main_intf->my_addr,
+ ipmi_main_intf->transit_addr,
+ ipmi_main_intf->transit_channel,
+ ipmi_main_intf->target_addr,
+ ipmi_main_intf->target_channel,
+ ipmi_main_intf->target_ipmb_addr);
+
/* parse local SDR cache if given */
if (sdrcache != NULL) {
ipmi_sdr_list_cache_fromfile(ipmi_main_intf, sdrcache);
@@ -1048,3 +1025,5 @@ ipmi_main(int argc, char ** argv,
return rc;
}
+
+
diff --git a/lib/ipmi_picmg.c b/lib/ipmi_picmg.c
index ba43924..f33adce 100644
--- a/lib/ipmi_picmg.c
+++ b/lib/ipmi_picmg.c
@@ -141,6 +141,10 @@ ipmi_picmg_getaddr(struct ipmi_intf * intf, int argc, char ** argv)
req.msg.netfn = IPMI_NETFN_PICMG;
req.msg.cmd = PICMG_GET_ADDRESS_INFO_CMD;
req.msg.data = msg_data;
+ //
+ // Melanie says to fix this so we don't specify fruid (data_len == 1)
+ // unless it is specified on the command line
+ //
req.msg.data_len = 2;
msg_data[0] = 0; /* picmg identifier */
msg_data[1] = 0; /* default fru id */
@@ -1780,3 +1784,93 @@ ipmi_picmg_main (struct ipmi_intf * intf, int argc, char ** argv)
return rc;
}
+
+uint8_t
+ipmi_picmg_ipmb_address(struct ipmi_intf *intf) {
+ struct ipmi_rq req;
+ struct ipmi_rs *rsp;
+ char msg_data;
+
+ if (!intf->picmg_avail) {
+ return 0;
+ }
+ memset(&req, 0, sizeof(req));
+ req.msg.netfn = IPMI_NETFN_PICMG;
+ req.msg.cmd = PICMG_GET_ADDRESS_INFO_CMD;
+ msg_data = 0x00;
+ req.msg.data = &msg_data;
+ req.msg.data_len = 1;
+ msg_data = 0;
+
+ rsp = intf->sendrecv(intf, &req);
+ if (rsp && !rsp->ccode) {
+ return rsp->data[2];
+ }
+ if (rsp) {
+ lprintf(LOG_DEBUG, "Get Address Info failed: %#x %s",
+ rsp->ccode, val2str(rsp->ccode, completion_code_vals));
+ } else {
+ lprintf(LOG_DEBUG, "Get Address Info failed: No Response");
+ }
+ return 0;
+}
+
+uint8_t
+picmg_ipmb_discover(struct ipmi_intf *intf) {
+ /* Check if PICMG extension is available to use the function
+ * GetDeviceLocator to retreive i2c address PICMG hack to set
+ * right IPMB address, If extension is not supported, should
+ * not give any problems
+ * PICMG Extension Version 2.0 (PICMG 3.0 Revision 1.0 ATCA) to
+ * PICMG Extension Version 2.3 (PICMG 3.0 Revision 3.0 ATCA)
+ * PICMG Extension Version 4.1 (PICMG 3.0 Revision 3.0 AMC)
+ */
+
+ /* First, check if PICMG extension is available and supported */
+ struct ipmi_rq req;
+ struct ipmi_rs *rsp;
+ char msg_data;
+
+ if (intf->picmg_avail == 0) {
+ lprintf(LOG_INFO, "Running PICMG GetDeviceLocator" );
+ memset(&req, 0, sizeof(req));
+ req.msg.netfn = IPMI_NETFN_PICMG;
+ req.msg.cmd = PICMG_GET_PICMG_PROPERTIES_CMD;
+ msg_data = 0x00;
+ req.msg.data = &msg_data;
+ req.msg.data_len = 1;
+ msg_data = 0;
+
+ lprintf(LOG_DEBUG, "Get PICMG Properties my_addr %#x, transit %#x, target %#x",
+ intf->my_addr, intf->transit_addr, intf->target_addr);
+ rsp = intf->sendrecv(intf, &req);
+ if (rsp && !rsp->ccode) {
+ if ( (rsp->data[0] == 0) &&
+ ((rsp->data[1] & 0x0F) == PICMG_ATCA_MAJOR_VERSION
+ || (rsp->data[1] & 0x0F) == PICMG_AMC_MAJOR_VERSION) ) {
+ intf->picmg_avail = 1;
+ lprintf(LOG_INFO, "Discovered PICMG Extension %d.%d",
+ (rsp->data[1] & 0x0f), (rsp->data[1] >> 4));
+ }
+ } else {
+ if (rsp == NULL) {
+ lprintf(LOG_INFO,"No Response from Get PICMG Properties");
+ } else {
+ lprintf(LOG_INFO,"Error Response %#x from Get PICMG Properities", rsp->ccode);
+ }
+ }
+ }
+ if (intf->picmg_avail == 1) {
+ lprintf(LOG_DEBUG, "Running PICMG Get Address Info");
+ uint8_t addr = ipmi_picmg_ipmb_address(intf);
+ if (addr) {
+ lprintf(LOG_INFO, "Discovered IPMB-0 address = 0x%x", addr);
+ return addr;
+ }
+ } else {
+ lprintf(LOG_INFO,
+ "No PICMG Extenstion discovered, keeping IPMB address %#x",
+ intf->my_addr);
+ }
+ return 0;
+}
diff --git a/lib/ipmi_sdr.c b/lib/ipmi_sdr.c
index a2163e3..03334fb 100644
--- a/lib/ipmi_sdr.c
+++ b/lib/ipmi_sdr.c
@@ -456,13 +456,15 @@ ipmi_sdr_get_sensor_thresholds(struct ipmi_intf *intf, uint8_t sensor,
{
struct ipmi_rq req;
struct ipmi_rs *rsp;
- uint32_t save_addr;
+ uint32_t save_addr = 0;
uint32_t save_channel;
- save_addr = intf->target_addr;
- intf->target_addr = target;
- save_channel = intf->target_channel;
- intf->target_channel = channel;
+ if ( BRIDGE_TO_SENSOR(intf, target, channel) ) {
+ save_addr = intf->target_addr;
+ intf->target_addr = target;
+ save_channel = intf->target_channel;
+ intf->target_channel = channel;
+ }
memset(&req, 0, sizeof (req));
req.msg.netfn = IPMI_NETFN_SE;
@@ -471,8 +473,10 @@ ipmi_sdr_get_sensor_thresholds(struct ipmi_intf *intf, uint8_t sensor,
req.msg.data_len = sizeof (sensor);
rsp = intf->sendrecv(intf, &req);
- intf->target_addr = save_addr;
- intf->target_channel = save_channel;
+ if ( save_addr ) {
+ intf->target_addr = save_addr;
+ intf->target_channel = save_channel;
+ }
return rsp;
}
@@ -493,13 +497,15 @@ ipmi_sdr_get_sensor_hysteresis(struct ipmi_intf *intf, uint8_t sensor,
struct ipmi_rq req;
uint8_t rqdata[2];
struct ipmi_rs *rsp;
- uint32_t save_addr;
+ uint32_t save_addr = 0;
uint32_t save_channel;
- save_addr = intf->target_addr;
- intf->target_addr = target;
- save_channel = intf->target_channel;
- intf->target_channel = channel;
+ if ( BRIDGE_TO_SENSOR(intf, target, channel) ) {
+ save_addr = intf->target_addr;
+ intf->target_addr = target;
+ save_channel = intf->target_channel;
+ intf->target_channel = channel;
+ }
rqdata[0] = sensor;
rqdata[1] = 0xff; /* reserved */
@@ -511,8 +517,10 @@ ipmi_sdr_get_sensor_hysteresis(struct ipmi_intf *intf, uint8_t sensor,
req.msg.data_len = 2;
rsp = intf->sendrecv(intf, &req);
- intf->target_addr = save_addr;
- intf->target_channel = save_channel;
+ if ( save_addr ) {
+ intf->target_addr = save_addr;
+ intf->target_channel = save_channel;
+ }
return rsp;
}
@@ -537,6 +545,7 @@ ipmi_sdr_get_sensor_reading(struct ipmi_intf *intf, uint8_t sensor)
return intf->sendrecv(intf, &req);
}
+
/* ipmi_sdr_get_sensor_reading_ipmb - retrieve a raw sensor reading from ipmb
*
* @intf: ipmi interface
@@ -553,25 +562,15 @@ ipmi_sdr_get_sensor_reading_ipmb(struct ipmi_intf *intf, uint8_t sensor,
{
struct ipmi_rq req;
struct ipmi_rs *rsp;
- uint32_t save_addr;
+ uint32_t save_addr = 0;
uint32_t save_channel;
-#if 0
- /* Enabling this code will cause sensors with an SDR Owner ID
- * not equal to IPMI_BMC_SLAVE_ADDR to be not readable when
- * running over the lanplus interface. The
- * ipmi_sdr_get_sensor_reading function does not update the interface
- * target address or channel, so the failure makes sense. I believe
- * the following code and function being called should be removed.
- */
- if ((strncmp(intf->name, "ipmb", 4)) != 0)
- return ipmi_sdr_get_sensor_reading(intf, sensor);
-#endif
- save_addr = intf->target_addr;
- intf->target_addr = target;
- save_channel = intf->target_channel;
- intf->target_channel = channel;
-
+ if ( BRIDGE_TO_SENSOR(intf, target, channel) ) {
+ save_addr = intf->target_addr;
+ intf->target_addr = target;
+ save_channel = intf->target_channel;
+ intf->target_channel = channel;
+ }
memset(&req, 0, sizeof (req));
req.msg.netfn = IPMI_NETFN_SE;
req.msg.cmd = GET_SENSOR_READING;
@@ -579,8 +578,10 @@ ipmi_sdr_get_sensor_reading_ipmb(struct ipmi_intf *intf, uint8_t sensor,
req.msg.data_len = 1;
rsp = intf->sendrecv(intf, &req);
- intf->target_addr = save_addr;
- intf->target_channel = save_channel;
+ if ( save_addr ) {
+ intf->target_addr = save_addr;
+ intf->target_channel = save_channel;
+ }
return rsp;
}
@@ -600,14 +601,15 @@ ipmi_sdr_get_sensor_event_status(struct ipmi_intf *intf, uint8_t sensor,
{
struct ipmi_rq req;
struct ipmi_rs *rsp;
- uint32_t save_addr;
+ uint32_t save_addr = 0;
uint32_t save_channel;
- save_addr = intf->target_addr;
- intf->target_addr = target;
- save_channel = intf->target_channel;
- intf->target_channel = channel;
-
+ if ( BRIDGE_TO_SENSOR(intf, target, channel) ) {
+ save_addr = intf->target_addr;
+ intf->target_addr = target;
+ save_channel = intf->target_channel;
+ intf->target_channel = channel;
+ }
memset(&req, 0, sizeof (req));
req.msg.netfn = IPMI_NETFN_SE;
req.msg.cmd = GET_SENSOR_EVENT_STATUS;
@@ -615,8 +617,10 @@ ipmi_sdr_get_sensor_event_status(struct ipmi_intf *intf, uint8_t sensor,
req.msg.data_len = 1;
rsp = intf->sendrecv(intf, &req);
- intf->target_addr = save_addr;
- intf->target_channel = save_channel;
+ if ( save_addr ) {
+ intf->target_addr = save_addr;
+ intf->target_channel = save_channel;
+ }
return rsp;
}
@@ -636,13 +640,15 @@ ipmi_sdr_get_sensor_event_enable(struct ipmi_intf *intf, uint8_t sensor,
{
struct ipmi_rq req;
struct ipmi_rs *rsp;
- uint32_t save_addr;
+ uint32_t save_addr = 0;
uint32_t save_channel;
- save_addr = intf->target_addr;
- intf->target_addr = target;
- save_channel = intf->target_channel;
- intf->target_channel = channel;
+ if ( BRIDGE_TO_SENSOR(intf, target, channel) ) {
+ save_addr = intf->target_addr;
+ intf->target_addr = target;
+ save_channel = intf->target_channel;
+ intf->target_channel = channel;
+ }
memset(&req, 0, sizeof (req));
req.msg.netfn = IPMI_NETFN_SE;
@@ -651,8 +657,10 @@ ipmi_sdr_get_sensor_event_enable(struct ipmi_intf *intf, uint8_t sensor,
req.msg.data_len = 1;
rsp = intf->sendrecv(intf, &req);
- intf->target_addr = save_addr;
- intf->target_channel = save_channel;
+ if ( save_addr ) {
+ intf->target_addr = save_addr;
+ intf->target_channel = save_channel;
+ }
return rsp;
}
@@ -2838,6 +2846,8 @@ ipmi_sdr_start(struct ipmi_intf *intf, int use_builtin)
return NULL;
}
if (rsp->ccode > 0) {
+ lprintf(LOG_ERR, "Get Device ID command failed: %#x %s",
+ rsp->ccode, val2str(rsp->ccode, completion_code_vals));
free(itr);
itr = NULL;
return NULL;
diff --git a/lib/ipmi_sel.c b/lib/ipmi_sel.c
index 16c807b..b34499b 100644
--- a/lib/ipmi_sel.c
+++ b/lib/ipmi_sel.c
@@ -309,8 +309,8 @@ ipmi_get_oem(struct ipmi_intf * intf)
return IPMI_OEM_UNKNOWN;
}
if (rsp->ccode > 0) {
- lprintf(LOG_ERR, "Get Device ID command failed: %s",
- val2str(rsp->ccode, completion_code_vals));
+ lprintf(LOG_ERR, "Get Device ID command failed: %#x %s",
+ rsp->ccode, val2str(rsp->ccode, completion_code_vals));
return IPMI_OEM_UNKNOWN;
}
diff --git a/lib/ipmi_sensor.c b/lib/ipmi_sensor.c
index 41276b1..9abac00 100644
--- a/lib/ipmi_sensor.c
+++ b/lib/ipmi_sensor.c
@@ -104,12 +104,13 @@ struct ipmi_rs *
ipmi_sensor_set_sensor_thresholds(struct ipmi_intf *intf,
uint8_t sensor,
uint8_t threshold, uint8_t setting,
- uint8_t target, uint8_t lun)
+ uint8_t target, uint8_t lun, uint8_t channel)
{
struct ipmi_rq req;
static struct sensor_set_thresh_rq set_thresh_rq;
struct ipmi_rs *rsp;
- uint8_t save_addr;
+ uint32_t save_addr = 0;
+ uint32_t save_channel;
memset(&set_thresh_rq, 0, sizeof (set_thresh_rq));
set_thresh_rq.sensor_num = sensor;
@@ -129,9 +130,12 @@ ipmi_sensor_set_sensor_thresholds(struct ipmi_intf *intf,
else
return NULL;
- save_addr = intf->target_addr;
- intf->target_addr = target;
-
+ if (BRIDGE_TO_SENSOR(intf, target, channel)) {
+ save_addr = intf->target_addr;
+ intf->target_addr = target;
+ save_channel = intf->target_channel;
+ intf->target_channel = channel;
+ }
memset(&req, 0, sizeof (req));
req.msg.netfn = IPMI_NETFN_SE;
req.msg.cmd = SET_SENSOR_THRESHOLDS;
@@ -139,7 +143,10 @@ ipmi_sensor_set_sensor_thresholds(struct ipmi_intf *intf,
req.msg.data_len = sizeof (set_thresh_rq);
rsp = intf->sendrecv(intf, &req);
- intf->target_addr = save_addr;
+ if (save_addr) {
+ intf->target_addr = save_addr;
+ intf->target_channel = save_channel;
+ }
return rsp;
}
@@ -463,12 +470,12 @@ static const struct valstr threshold_vals[] = {
static int
__ipmi_sensor_set_threshold(struct ipmi_intf *intf,
uint8_t num, uint8_t mask, uint8_t setting,
- uint8_t target, uint8_t lun)
+ uint8_t target, uint8_t lun, uint8_t channel)
{
struct ipmi_rs *rsp;
rsp = ipmi_sensor_set_sensor_thresholds(intf, num, mask, setting,
- target, lun);
+ target, lun, channel);
if (rsp == NULL) {
lprintf(LOG_ERR, "Error setting threshold");
@@ -625,7 +632,8 @@ ipmi_sensor_set_threshold(struct ipmi_intf *intf, int argc, char **argv)
sensor_num, settingMask,
__ipmi_sensor_threshold_value_to_raw(sdr->record.full, setting1),
sdr->record.common->keys.owner_id,
- sdr->record.common->keys.lun);
+ sdr->record.common->keys.lun,
+ sdr->record.common->keys.channel);
settingMask = UPPER_CRIT_SPECIFIED;
printf("Setting sensor \"%s\" %s threshold to %.3f\n",
@@ -636,7 +644,8 @@ ipmi_sensor_set_threshold(struct ipmi_intf *intf, int argc, char **argv)
sensor_num, settingMask,
__ipmi_sensor_threshold_value_to_raw(sdr->record.full, setting2),
sdr->record.common->keys.owner_id,
- sdr->record.common->keys.lun);
+ sdr->record.common->keys.lun,
+ sdr->record.common->keys.channel);
settingMask = UPPER_NON_RECOV_SPECIFIED;
printf("Setting sensor \"%s\" %s threshold to %.3f\n",
@@ -647,7 +656,8 @@ ipmi_sensor_set_threshold(struct ipmi_intf *intf, int argc, char **argv)
sensor_num, settingMask,
__ipmi_sensor_threshold_value_to_raw(sdr->record.full, setting3),
sdr->record.common->keys.owner_id,
- sdr->record.common->keys.lun);
+ sdr->record.common->keys.lun,
+ sdr->record.common->keys.channel);
} else if (allLower) {
settingMask = LOWER_NON_RECOV_SPECIFIED;
printf("Setting sensor \"%s\" %s threshold to %.3f\n",
@@ -658,7 +668,8 @@ ipmi_sensor_set_threshold(struct ipmi_intf *intf, int argc, char **argv)
sensor_num, settingMask,
__ipmi_sensor_threshold_value_to_raw(sdr->record.full, setting1),
sdr->record.common->keys.owner_id,
- sdr->record.common->keys.lun);
+ sdr->record.common->keys.lun,
+ sdr->record.common->keys.channel);
settingMask = LOWER_CRIT_SPECIFIED;
printf("Setting sensor \"%s\" %s threshold to %.3f\n",
@@ -669,7 +680,8 @@ ipmi_sensor_set_threshold(struct ipmi_intf *intf, int argc, char **argv)
sensor_num, settingMask,
__ipmi_sensor_threshold_value_to_raw(sdr->record.full, setting2),
sdr->record.common->keys.owner_id,
- sdr->record.common->keys.lun);
+ sdr->record.common->keys.lun,
+ sdr->record.common->keys.channel);
settingMask = LOWER_NON_CRIT_SPECIFIED;
printf("Setting sensor \"%s\" %s threshold to %.3f\n",
@@ -680,7 +692,8 @@ ipmi_sensor_set_threshold(struct ipmi_intf *intf, int argc, char **argv)
sensor_num, settingMask,
__ipmi_sensor_threshold_value_to_raw(sdr->record.full, setting3),
sdr->record.common->keys.owner_id,
- sdr->record.common->keys.lun);
+ sdr->record.common->keys.lun,
+ sdr->record.common->keys.channel);
} else {
/*
@@ -778,7 +791,8 @@ ipmi_sensor_set_threshold(struct ipmi_intf *intf, int argc, char **argv)
sensor_num, settingMask,
__ipmi_sensor_threshold_value_to_raw(sdr->record.full, setting1),
sdr->record.common->keys.owner_id,
- sdr->record.common->keys.lun);
+ sdr->record.common->keys.lun,
+ sdr->record.common->keys.channel);
}
return ret;
diff --git a/src/plugins/lanplus/lanplus.c b/src/plugins/lanplus/lanplus.c
index 4288224..dc0e59a 100644
--- a/src/plugins/lanplus/lanplus.c
+++ b/src/plugins/lanplus/lanplus.c
@@ -1356,9 +1356,9 @@ void getIpmiPayloadWireRep(
len = 0;
/* IPMI Message Header -- Figure 13-4 of the IPMI v2.0 spec */
- if ((intf->target_addr == ourAddress) || (!bridgePossible))
+ if ((intf->target_addr == ourAddress) || (!bridgePossible)) {
cs = len;
- else {
+ } else {
bridgedRequest = 1;
if(intf->transit_addr != ourAddress && intf->transit_addr != 0)
@@ -1401,6 +1401,14 @@ void getIpmiPayloadWireRep(
entry->req.msg.target_cmd = entry->req.msg.cmd; /* Save target command */
entry->req.msg.cmd = 0x34; /* (fixup request entry) */
#endif
+// Test that sensors can be read correctly on Channel 7 when doulbe briding on
+// gemini. With this code, the sensors can be read without problem
+// 3/18/2013
+// src/ipmitool -I lanplus -U admin -P admin123 -H 16.85.18.239 -t 0x72 -T
+// 0xa4 -b 7 sdr list all
+// if (intf->target_channel == 0 && intf->target_addr == 0x72) {
+// intf->target_channel = 7;
+// }
msg[len++] = (0x40|intf->target_channel); /* Track request*/
payload->payload_length += 7;
@@ -1409,6 +1417,13 @@ void getIpmiPayloadWireRep(
}
}
+ lprintf(LOG_DEBUG,"%s RqAddr %#x transit %#x:%#x target %#x:%#x "
+ "bridgePossible %d",
+ bridgedRequest ? "Bridging" : "Local",
+ intf->my_addr, intf->transit_addr, intf->transit_channel,
+ intf->target_addr, intf->target_channel,
+ bridgePossible);
+
/* rsAddr */
msg[len++] = intf->target_addr; /* IPMI_BMC_SLAVE_ADDR; */
@@ -3296,6 +3311,7 @@ ipmi_set_session_privlvl_cmd(struct ipmi_intf * intf)
if (rsp == NULL) {
lprintf(LOG_ERR, "Set Session Privilege Level to %s failed",
val2str(privlvl, ipmi_privlvl_vals));
+ bridgePossible = backupBridgePossible;
return -1;
}
if (verbose > 2)
@@ -3305,6 +3321,7 @@ ipmi_set_session_privlvl_cmd(struct ipmi_intf * intf)
lprintf(LOG_ERR, "Set Session Privilege Level to %s failed: %s",
val2str(privlvl, ipmi_privlvl_vals),
val2str(rsp->ccode, completion_code_vals));
+ bridgePossible = backupBridgePossible;
return -1;
}
@@ -3453,13 +3470,14 @@ ipmi_lanplus_open(struct ipmi_intf * intf)
lprintf(LOG_DEBUG, "IPMIv2 / RMCP+ SESSION OPENED SUCCESSFULLY\n");
- bridgePossible = 1;
-
rc = ipmi_set_session_privlvl_cmd(intf);
+
if (rc < 0)
goto fail;
intf->manufacturer_id = ipmi_get_oem(intf);
+ bridgePossible = 1;
+
return intf->fd;
fail:
diff --git a/src/plugins/open/open.c b/src/plugins/open/open.c
index 34cb10c..d5b7ad9 100644
--- a/src/plugins/open/open.c
+++ b/src/plugins/open/open.c
@@ -179,7 +179,8 @@ ipmi_openipmi_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req)
ipmb_addr.slave_addr = intf->target_addr;
ipmb_addr.lun = req->msg.lun;
lprintf(LOG_DEBUG, "Sending request to "
- "IPMB target @ 0x%x (from 0x%x)", intf->target_addr,intf->my_addr);
+ "IPMB target @ 0x%x:0x%x (from 0x%x)",
+ intf->target_addr,intf->target_channel, intf->my_addr);
if(intf->transit_addr != 0 && intf->transit_addr != intf->my_addr) {
uint8_t index = 0;
--
1.7.9.5
------------------------------------------------------------------------------
Precog is a next-generation analytics platform capable of advanced
analytics on semi-structured data. The platform includes APIs for building
apps and a phenomenal toolset for data science. Developers can use
our toolset for easy data analysis & visualization. Get a free account!
http://www2.precog.com/precogplatform/slashdotnewsletter
_______________________________________________
Ipmitool-devel mailing list
Ipmitool-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/ipmitool-devel