Esempio n. 1
0
int hservice_ipmi_msg(uint8_t netfn, uint8_t cmd,
		void *tx_buf, size_t tx_size,
		void *rx_buf, size_t *rx_size)
{
	struct timeval start, now, delta;
	struct pollfd pollfds[1];
	static long seq;
	size_t size;
	int rc, fd;

	size = be64toh(*rx_size);

	fd = open(ipmi_devnode, O_RDWR);
	if (fd < 0) {
		pr_log(LOG_WARNING, "IPMI: Failed to open IPMI device %s: %m",
				ipmi_devnode);
		return -1;
	}

	seq++;
	pr_debug("IPMI: sending %zd bytes (netfn 0x%02x, cmd 0x%02x)",
			tx_size, netfn, cmd);

	rc = ipmi_send(fd, netfn, cmd, seq, tx_buf, tx_size);
	if (rc) {
		pr_log(LOG_WARNING, "IPMI: send failed");
		goto out;
	}

	gettimeofday(&start, NULL);

	pollfds[0].fd = fd;
	pollfds[0].events = POLLIN;

	for (;;) {
		long rx_seq;
		int timeout;

		gettimeofday(&now, NULL);
		timersub(&now, &start, &delta);
		timeout = ipmi_timeout_ms - ((delta.tv_sec * 1000) +
				(delta.tv_usec / 1000));
		if (timeout < 0)
			timeout = 0;

		rc = poll(pollfds, 1, timeout);
		if (rc < 0) {
			pr_log(LOG_ERR, "IPMI: poll(%s) failed: %m",
					ipmi_devnode);
			break;
		}

		if (rc == 0) {
			pr_log(LOG_WARNING, "IPMI: response timeout (>%dms)",
					ipmi_timeout_ms);
			rc = -1;
			break;
		}

		rc = ipmi_recv(fd, &netfn, &cmd, &rx_seq, rx_buf, &size);
		if (rc)
			break;

		if (seq != rx_seq) {
			pr_log(LOG_NOTICE, "IPMI: out-of-sequence reply: %ld, "
					"expected %ld. Dropping message.",
					rx_seq, seq);
			continue;
		}

		pr_debug("IPMI: received %zd bytes", tx_size);
		*rx_size = be64toh(size);
		rc = 0;
		break;
	}

out:
	close(fd);
	return rc;
}
Esempio n. 2
0
int ipmi_transaction(struct ipmi *ipmi, uint8_t netfn, uint8_t cmd,
		uint8_t *req_buf, uint16_t req_len,
		uint8_t *resp_buf, uint16_t *resp_len,
		int timeout_ms)
{
	struct timeval start, now, delta;
	struct pollfd pollfds[1];
	struct flock lock;
	int expired_ms, rc;

	memset(&lock, 0, sizeof(lock));
	lock.l_type = F_WRLCK;
	lock.l_whence = SEEK_SET;
	rc = fcntl(ipmi->fd, F_SETLKW, &lock);
	if (rc == -1) {
		pb_log("IPMI: error locking IPMI device: %m\n");
		return rc;
	}

	rc = ipmi_send(ipmi, netfn, cmd, req_buf, req_len);
	if (rc)
		goto out;

	pollfds[0].fd = ipmi->fd;
	pollfds[0].events = POLLIN;

	gettimeofday(&start, NULL);
	expired_ms = 0;

	for (;;) {
		uint8_t resp_netfn, resp_cmd;
		long seq;

		rc = poll(pollfds, 1, timeout_ms - expired_ms);

		if (rc < 0) {
			pb_log("IPMI: poll() error %m");
			break;
		}
		if (rc == 0) {
			pb_log("IPMI: timeout waiting for response "
					"(netfn %d, cmd %d)\n", netfn, cmd);
			rc = -1;
			break;
		}

		if (!(pollfds[0].revents & POLLIN)) {
			pb_log("IPMI: unexpected fd status from poll?\n");
			rc = -1;
			break;
		}

		rc = ipmi_recv(ipmi, &resp_netfn, &resp_cmd, &seq,
				resp_buf, resp_len);
		if (rc)
			break;

		if (seq != ipmi->seq - 1) {
			pb_log("IPMI: out-of-sequence reply: "
					"exp %ld, got %ld\n",
					ipmi->seq, seq);

			if (timeout_ms) {
				gettimeofday(&now, NULL);
				timersub(&now, &start, &delta);
				expired_ms = (delta.tv_sec * 1000) +
						(delta.tv_usec / 1000);

				if (expired_ms >= timeout_ms) {
					rc = -1;
					break;
				}
			}
		} else {
			pb_debug("IPMI: netfn(%x->%x), cmd(%x->%x)\n",
					netfn, resp_netfn, cmd, resp_cmd);
			rc = 0;
			goto out;
		}
	}

out:
	lock.l_type = F_UNLCK;
	if (fcntl(ipmi->fd, F_SETLKW, &lock) == -1)
		pb_log("IPMI: error unlocking IPMI device: %m\n");
	return rc ? -1 : 0;
}