Skip to content

Commit

Permalink
DPDK: fix vRouter and Agent restart keeping the VM connectivity
Browse files Browse the repository at this point in the history
vRouter restart: recover vring base after a crash from a shared memory.

Agent restart: close both the FD we listen and the FD we have accepted,
so QEMU detect the chardev disconnection, reconnects and replays all
the virtio messages.

Other minor changes (logs, typos, includes, renames, etc)

Change-Id: I4ebab47d40c162f3b31aa7c3782becece38bdae5
Closes-bug: #1537043
  • Loading branch information
semihalf-berestovskyy-andriy committed Jan 27, 2016
1 parent 7ab7135 commit eb108bf
Show file tree
Hide file tree
Showing 8 changed files with 238 additions and 118 deletions.
3 changes: 3 additions & 0 deletions dpdk/vr_dpdk_netlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ dpdk_netlink_receive(void *usockp, char *nl_buf,
int ret;
struct vr_message request;

memset(&request, 0, sizeof(request));
request.vr_message_buf = nl_buf + HDR_LEN;
request.vr_message_len = nl_len - HDR_LEN;

Expand Down Expand Up @@ -159,6 +160,7 @@ vr_netlink_uvhost_vif_del(unsigned int vif_idx)
{
vrnu_msg_t msg;

memset(&msg, 0, sizeof(msg));
msg.vrnum_type = VRNU_MSG_VIF_DEL;
msg.vrnum_vif_del.vrnu_vif_idx = vif_idx;

Expand Down Expand Up @@ -188,6 +190,7 @@ vr_netlink_uvhost_vif_add(char *vif_name, unsigned int vif_idx,
{
vrnu_msg_t msg;

memset(&msg, 0, sizeof(msg));
msg.vrnum_type = VRNU_MSG_VIF_ADD;
strncpy(msg.vrnum_vif_add.vrnu_vif_name, vif_name,
sizeof(msg.vrnum_vif_add.vrnu_vif_name) - 1);
Expand Down
50 changes: 44 additions & 6 deletions dpdk/vr_dpdk_virtio.c
Original file line number Diff line number Diff line change
Expand Up @@ -217,8 +217,8 @@ vr_dpdk_virtio_uvh_get_blk_size(int fd, uint64_t *const blksize)
if (!ret){
*blksize = (uint64_t)fd_stat.st_blksize;
} else {
RTE_LOG(DEBUG, UVHOST, "Function fstat() failed: %s %s \n",
__func__, strerror(errno));
RTE_LOG(DEBUG, UVHOST, "Error getting file status for FD %d: %s (%d)\n",
fd, strerror(errno), errno);
}

return ret;
Expand All @@ -242,8 +242,8 @@ vr_dpdk_virtio_uvh_vif_munmap(vr_dpdk_uvh_vif_mmap_addr_t *const vif_mmap_addrs)
ret = vr_dpdk_virtio_uvh_vif_region_munmap(vif_data_mmap);
if (ret) {
RTE_LOG(INFO, UVHOST,
"munmap() failed: %s , memleak: vif_idx_region %d %s\n",
strerror(errno), i, __func__);
"Error unmapping memory region %d: %s (%d)\n",
i, strerror(errno), errno);
}
memset(vif_data_mmap, 0, sizeof(vr_dpdk_uvh_mmap_addr_t));
}
Expand Down Expand Up @@ -619,6 +619,8 @@ dpdk_virtio_from_vm_rx(void *port, struct rte_mbuf **pkts, uint32_t max_pkts)
vq->vdv_last_used_idx += pkts_sent;
rte_wmb();
vq->vdv_used->idx += pkts_sent;
RTE_LOG(DEBUG, VROUTER, "%s: vif %d vq %p last_used_idx %d used->idx %d\n",
__func__, vq->vdv_vif_idx, vq, vq->vdv_last_used_idx, vq->vdv_used->idx);
/* call guest if required (fixes iperf issue) */
if (unlikely(!(vq->vdv_avail->flags & VRING_AVAIL_F_NO_INTERRUPT))) {
p->nb_syscalls++;
Expand Down Expand Up @@ -829,6 +831,8 @@ dpdk_virtio_dev_to_vm_tx_burst(struct dpdk_virtio_writer *p,

*(volatile uint16_t *)&vq->vdv_used->idx += count;
vq->vdv_last_used_idx = res_end_idx;
RTE_LOG(DEBUG, VROUTER, "%s: vif %d vq %p last_used_idx %d used->idx %d\n",
__func__, vq->vdv_vif_idx, vq, vq->vdv_last_used_idx, vq->vdv_used->idx);

/* flush used->idx update before we read avail->flags. */
rte_mb();
Expand Down Expand Up @@ -969,10 +973,44 @@ vr_dpdk_virtio_get_vring_base(unsigned int vif_idx, unsigned int vring_idx,
}

/*
* vr_dpdk_set_vring_addr - Sets the address of the virtio descruptor and
* vr_dpdk_virtio_recover_vring_base - recovers the vring base from the shared
* memory after vRouter crash.
*
* Returns 0 on success, -1 otherwise.
*/
int
vr_dpdk_virtio_recover_vring_base(unsigned int vif_idx, unsigned int vring_idx)
{
vr_dpdk_virtioq_t *vq;

if ((vif_idx >= VR_MAX_INTERFACES)
|| (vring_idx >= (2 * VR_DPDK_VIRTIO_MAX_QUEUES))) {
return -1;
}

if (vring_idx & 1) {
vq = &vr_dpdk_virtio_rxqs[vif_idx][vring_idx/2];
} else {
vq = &vr_dpdk_virtio_txqs[vif_idx][vring_idx/2];
}

if (vq->vdv_used) {
/* Reading base index from the shared memory. */
if (vq->vdv_last_used_idx != vq->vdv_used->idx) {
RTE_LOG(INFO, UVHOST, " recovering vring base %d -> %d\n",
vq->vdv_last_used_idx, vq->vdv_used->idx);
vr_dpdk_virtio_set_vring_base(vif_idx, vring_idx, vq->vdv_used->idx);
}
}

return 0;
}

/*
* vr_dpdk_set_vring_addr - Sets the address of the virtio descriptor and
* available/used rings based on messages sent by the vhost client.
*
* Returns 0 on suucess, -1 otherwise.
* Returns 0 on success, -1 otherwise.
*/
int
vr_dpdk_set_vring_addr(unsigned int vif_idx, unsigned int vring_idx,
Expand Down
1 change: 1 addition & 0 deletions dpdk/vr_dpdk_virtio.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ int vr_dpdk_virtio_set_vring_base(unsigned int vif_idx, unsigned int vring_idx,
unsigned int vring_base);
int vr_dpdk_virtio_get_vring_base(unsigned int vif_idx, unsigned int vring_idx,
unsigned int *vring_basep);
int vr_dpdk_virtio_recover_vring_base(unsigned int vif_idx, unsigned int vring_idx);
int vr_dpdk_set_vring_addr(unsigned int vif_idx, unsigned int vring_idx,
struct vring_desc *vrucv_desc,
struct vring_avail *vrucv_avail,
Expand Down
2 changes: 0 additions & 2 deletions dpdk/vr_uvhost.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
* Copyright (c) 2014 Juniper Networks, Inc. All rights reserved.
*/

#include <sys/poll.h>

#include "vr_dpdk.h"
#include "vr_dpdk_usocket.h"
#include "vr_uvhost.h"
Expand Down
7 changes: 4 additions & 3 deletions dpdk/vr_uvhost_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include "vr_dpdk.h"
#include "vr_uvhost_client.h"
#include "vr_uvhost_util.h"

static vr_uvh_client_t vr_uvh_clients[VR_UVH_MAX_CLIENTS];

Expand Down Expand Up @@ -57,9 +58,9 @@ vr_uvhost_new_client(int fd, char *path, int cidx)
void
vr_uvhost_del_client(vr_uvh_client_t *vru_cl)
{
if (vru_cl->vruc_fd > 0) {
close(vru_cl->vruc_fd);
}
/* Remove both the socket we listen for and the socket we have accepted */
vr_uvhost_del_fds_by_arg(vru_cl);

vru_cl->vruc_fd = -1;
unlink(vru_cl->vruc_path);

Expand Down

0 comments on commit eb108bf

Please sign in to comment.