#include <string.h>
#include <errno.h>
+#include <rte_string_fns.h>
#include <rte_fbarray.h>
-#include <rte_eal_memconfig.h>
#include "vhost.h"
#include "virtio_user_dev.h"
#define VHOST_USER_VERSION_MASK 0x3
#define VHOST_USER_REPLY_MASK (0x1 << 2)
+#define VHOST_USER_NEED_REPLY_MASK (0x1 << 3)
uint32_t flags;
uint32_t size; /* the following payload size */
union {
struct vhost_memory memory;
} payload;
int fds[VHOST_MEMORY_MAX_NREGIONS];
-} __attribute((packed));
+} __rte_packed;
#define VHOST_USER_HDR_SIZE offsetof(struct vhost_user_msg, payload.u64)
#define VHOST_USER_PAYLOAD_SIZE \
[VHOST_USER_SET_VRING_KICK] = "VHOST_SET_VRING_KICK",
[VHOST_USER_SET_MEM_TABLE] = "VHOST_SET_MEM_TABLE",
[VHOST_USER_SET_VRING_ENABLE] = "VHOST_SET_VRING_ENABLE",
+ [VHOST_USER_GET_PROTOCOL_FEATURES] = "VHOST_USER_GET_PROTOCOL_FEATURES",
+ [VHOST_USER_SET_PROTOCOL_FEATURES] = "VHOST_USER_SET_PROTOCOL_FEATURES",
+ [VHOST_USER_SET_STATUS] = "VHOST_SET_STATUS",
+ [VHOST_USER_GET_STATUS] = "VHOST_GET_STATUS",
};
static int
struct vhost_user_msg msg;
struct vhost_vring_file *file = 0;
int need_reply = 0;
+ int has_reply_ack = 0;
int fds[VHOST_MEMORY_MAX_NREGIONS];
int fd_num = 0;
int len;
if (dev->is_server && vhostfd < 0)
return -1;
+ if (dev->protocol_features & (1ULL << VHOST_USER_PROTOCOL_F_REPLY_ACK))
+ has_reply_ack = 1;
+
msg.request = req;
msg.flags = VHOST_USER_VERSION;
msg.size = 0;
switch (req) {
+ case VHOST_USER_GET_STATUS:
+ if (!(dev->protocol_features &
+ (1ULL << VHOST_USER_PROTOCOL_F_STATUS)))
+ return 0;
+ /* Fallthrough */
case VHOST_USER_GET_FEATURES:
+ case VHOST_USER_GET_PROTOCOL_FEATURES:
need_reply = 1;
break;
+ case VHOST_USER_SET_STATUS:
+ if (!(dev->protocol_features &
+ (1ULL << VHOST_USER_PROTOCOL_F_STATUS)))
+ return 0;
+
+ if (has_reply_ack)
+ msg.flags |= VHOST_USER_NEED_REPLY_MASK;
+ /* Fallthrough */
case VHOST_USER_SET_FEATURES:
+ case VHOST_USER_SET_PROTOCOL_FEATURES:
case VHOST_USER_SET_LOG_BASE:
msg.payload.u64 = *((__u64 *)arg);
msg.size = sizeof(m.payload.u64);
msg.size = sizeof(m.payload.memory.nregions);
msg.size += sizeof(m.payload.memory.padding);
msg.size += fd_num * sizeof(struct vhost_memory_region);
+
+ if (has_reply_ack)
+ msg.flags |= VHOST_USER_NEED_REPLY_MASK;
break;
case VHOST_USER_SET_LOG_FD:
return -1;
}
- if (need_reply) {
+ if (need_reply || msg.flags & VHOST_USER_NEED_REPLY_MASK) {
if (vhost_user_read(vhostfd, &msg) < 0) {
PMD_DRV_LOG(ERR, "Received msg failed: %s",
strerror(errno));
switch (req) {
case VHOST_USER_GET_FEATURES:
+ case VHOST_USER_GET_STATUS:
+ case VHOST_USER_GET_PROTOCOL_FEATURES:
if (msg.size != sizeof(m.payload.u64)) {
PMD_DRV_LOG(ERR, "Received bad msg size");
return -1;
sizeof(struct vhost_vring_state));
break;
default:
- PMD_DRV_LOG(ERR, "Received unexpected msg type");
- return -1;
+ /* Reply-ack handling */
+ if (msg.size != sizeof(m.payload.u64)) {
+ PMD_DRV_LOG(ERR, "Received bad msg size");
+ return -1;
+ }
+
+ if (msg.payload.u64 != 0) {
+ PMD_DRV_LOG(ERR, "Slave replied NACK");
+ return -1;
+ }
+
+ break;
}
}
return -1;
flag = fcntl(fd, F_GETFL);
- fcntl(fd, F_SETFL, flag | O_NONBLOCK);
+ if (fcntl(fd, F_SETFL, flag | O_NONBLOCK) < 0) {
+ PMD_DRV_LOG(ERR, "fcntl failed, %s", strerror(errno));
+ return -1;
+ }
return 0;
}
memset(&un, 0, sizeof(un));
un.sun_family = AF_UNIX;
- snprintf(un.sun_path, sizeof(un.sun_path), "%s", dev->path);
+ strlcpy(un.sun_path, dev->path, sizeof(un.sun_path));
if (dev->is_server) {
dev->listenfd = fd;
{
int i;
+ if (dev->qp_enabled[pair_idx] == enable)
+ return 0;
+
for (i = 0; i < 2; ++i) {
struct vhost_vring_state state = {
.index = pair_idx * 2 + i,
return -1;
}
+ dev->qp_enabled[pair_idx] = enable;
return 0;
}