Dmitry Konyshev 1/23/09 lan-bridging patch to fix a double-bridging crash, issue with bridging multiple concurrent requests, and erroneous handling of raw Send Message

This commit is contained in:
Carol Hebert 2009-01-28 19:37:44 +00:00
parent 10f4a1a5c5
commit 928da786e5
2 changed files with 27 additions and 33 deletions

View File

@ -145,6 +145,7 @@ struct ipmi_rq_entry {
uint8_t rq_seq; uint8_t rq_seq;
uint8_t *msg_data; uint8_t *msg_data;
int msg_len; int msg_len;
int bridging_level;
struct ipmi_rq_entry *next; struct ipmi_rq_entry *next;
}; };

View File

@ -572,44 +572,36 @@ ipmi_lan_poll_recv(struct ipmi_intf * intf)
if (entry) { if (entry) {
lprintf(LOG_DEBUG+2, "IPMI Request Match found"); lprintf(LOG_DEBUG+2, "IPMI Request Match found");
if ((intf->target_addr != our_address) && bridge_possible) { if ((intf->target_addr != our_address) && bridge_possible) {
if ((rsp->data_len) && if ((rsp->data_len) && (rsp->payload.ipmi_response.netfn == 7) &&
(rsp->payload.ipmi_response.cmd != 0x34)) { (rsp->payload.ipmi_response.cmd != 0x34)) {
printbuf(&rsp->data[x], rsp->data_len-x, if (verbose > 2)
"bridge command response"); printbuf(&rsp->data[x], rsp->data_len-x,
"bridge command response");
} }
/* bridged command: lose extra header */ /* bridged command: lose extra header */
if (rsp->payload.ipmi_response.netfn == 7 && if (entry->bridging_level &&
rsp->payload.ipmi_response.cmd == 0x34) { rsp->payload.ipmi_response.netfn == 7 &&
rsp->payload.ipmi_response.cmd == 0x34) {
entry->bridging_level--;
if (rsp->data_len - x - 1 == 0) { if (rsp->data_len - x - 1 == 0) {
rsp = !rsp->ccode ? ipmi_lan_recv_packet(intf) : NULL; rsp = !rsp->ccode ? ipmi_lan_recv_packet(intf) : NULL;
if (rsp && !rsp->ccode && if (!entry->bridging_level)
intf->transit_addr != intf->my_addr && entry->req.msg.cmd = entry->req.msg.target_cmd;
intf->transit_addr != 0 &&
(rsp->data[x - 3] >> 2) == entry->rq_seq) {
/* double bridging: remove the Send Message prologue */
memmove(rsp->data + x - 7, rsp->data + x,
rsp->data_len - x - 1);
rsp->data[x - 8] -= 8;
rsp->data_len -= 8;
entry->rq_seq = rsp->data[x - 3] >> 2;
}
entry->req.msg.cmd = entry->req.msg.target_cmd;
if (rsp == NULL) { if (rsp == NULL) {
ipmi_req_remove_entry(entry->rq_seq, entry->req.msg.cmd); ipmi_req_remove_entry(entry->rq_seq, entry->req.msg.cmd);
} }
continue; continue;
} else { } else {
/* The bridged answer data are inside the incoming packet */ /* The bridged answer data are inside the incoming packet */
char bridge_cnt = memmove(rsp->data + x - 7,
1 + (intf->transit_addr != intf->my_addr && intf->transit_addr != 0); rsp->data + x,
memmove(rsp->data + x - 7, rsp->data_len - x - 1);
rsp->data + x + 7 * (bridge_cnt - 1), rsp->data[x - 8] -= 8;
rsp->data_len - (x + 7 * (bridge_cnt - 1))); rsp->data_len -= 8;
rsp->data[x - 8] -= 8 * bridge_cnt; entry->rq_seq = rsp->data[x - 3] >> 2;
rsp->data_len -= 8 * bridge_cnt; if (!entry->bridging_level)
entry->rq_seq = rsp->data[x - 3] >> 2; entry->req.msg.cmd = entry->req.msg.target_cmd;
entry->req.msg.cmd = entry->req.msg.target_cmd; continue;
continue;
} }
} else { } else {
//x += sizeof(rsp->payload.ipmi_response); //x += sizeof(rsp->payload.ipmi_response);
@ -688,7 +680,6 @@ ipmi_lan_build_cmd(struct ipmi_intf * intf, struct ipmi_rq * req)
struct ipmi_session * s = intf->session; struct ipmi_session * s = intf->session;
static int curr_seq = 0; static int curr_seq = 0;
uint8_t our_address = intf->my_addr; uint8_t our_address = intf->my_addr;
uint8_t bridge_request = 0;
if (our_address == 0) if (our_address == 0)
our_address = IPMI_BMC_SLAVE_ADDR; our_address = IPMI_BMC_SLAVE_ADDR;
@ -735,11 +726,12 @@ ipmi_lan_build_cmd(struct ipmi_intf * intf, struct ipmi_rq * req)
/* message length */ /* message length */
if ((intf->target_addr == our_address) || !bridge_possible) { if ((intf->target_addr == our_address) || !bridge_possible) {
entry->bridging_level = 0;
msg[len++] = req->msg.data_len + 7; msg[len++] = req->msg.data_len + 7;
cs = mp = len; cs = mp = len;
} else { } else {
/* bridged request: encapsulate w/in Send Message */ /* bridged request: encapsulate w/in Send Message */
bridge_request = 1; entry->bridging_level = 1;
msg[len++] = req->msg.data_len + 15 + msg[len++] = req->msg.data_len + 15 +
(intf->transit_addr != intf->my_addr && intf->transit_addr != 0 ? 8 : 0); (intf->transit_addr != intf->my_addr && intf->transit_addr != 0 ? 8 : 0);
cs = mp = len; cs = mp = len;
@ -757,6 +749,7 @@ ipmi_lan_build_cmd(struct ipmi_intf * intf, struct ipmi_rq * req)
if (intf->transit_addr == intf->my_addr || intf->transit_addr == 0) { if (intf->transit_addr == intf->my_addr || intf->transit_addr == 0) {
msg[len++] = (0x40|intf->target_channel); /* Track request*/ msg[len++] = (0x40|intf->target_channel); /* Track request*/
} else { } else {
entry->bridging_level++;
msg[len++] = (0x40|intf->transit_channel); /* Track request*/ msg[len++] = (0x40|intf->transit_channel); /* Track request*/
cs = len; cs = len;
msg[len++] = intf->transit_addr; msg[len++] = intf->transit_addr;
@ -779,7 +772,7 @@ ipmi_lan_build_cmd(struct ipmi_intf * intf, struct ipmi_rq * req)
msg[len++] = ipmi_csum(msg+cs, tmp); msg[len++] = ipmi_csum(msg+cs, tmp);
cs = len; cs = len;
if (!bridge_request) if (!entry->bridging_level)
msg[len++] = IPMI_REMOTE_SWID; msg[len++] = IPMI_REMOTE_SWID;
else /* Bridged message */ else /* Bridged message */
msg[len++] = intf->my_addr; msg[len++] = intf->my_addr;
@ -813,7 +806,7 @@ ipmi_lan_build_cmd(struct ipmi_intf * intf, struct ipmi_rq * req)
msg[len++] = ipmi_csum(msg+cs, tmp); msg[len++] = ipmi_csum(msg+cs, tmp);
/* bridged request: 2nd checksum */ /* bridged request: 2nd checksum */
if (bridge_request) { if (entry->bridging_level) {
if (intf->transit_addr != intf->my_addr && intf->transit_addr != 0) { if (intf->transit_addr != intf->my_addr && intf->transit_addr != 0) {
tmp = len - cs3; tmp = len - cs3;
msg[len++] = ipmi_csum(msg+cs3, tmp); msg[len++] = ipmi_csum(msg+cs3, tmp);