diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
index 6e1032f..55d5456 100644
--- a/hw/net/vhost_net.c
+++ b/hw/net/vhost_net.c
@@ -296,6 +296,7 @@ int vhost_net_start(VirtIODevice *dev, NetClientState *ncs,
         if (net->nc->info->type == NET_CLIENT_OPTIONS_KIND_VHOST_USER) {
                 dev->use_guest_notifier_mask = false;
         }
+        put_vhost_net(ncs[i].peer);
      }
 
     r = k->set_guest_notifiers(qbus->parent, total_queues * 2, true);
@@ -306,7 +307,7 @@ int vhost_net_start(VirtIODevice *dev, NetClientState *ncs,
 
     for (i = 0; i < total_queues; i++) {
         r = vhost_net_start_one(get_vhost_net(ncs[i].peer), dev);
-
+        put_vhost_net(ncs[i].peer);
         if (r < 0) {
             goto err_start;
         }
@@ -317,6 +318,7 @@ int vhost_net_start(VirtIODevice *dev, NetClientState *ncs,
 err_start:
     while (--i >= 0) {
         vhost_net_stop_one(get_vhost_net(ncs[i].peer), dev);
+        put_vhost_net(ncs[i].peer);
     }
     e = k->set_guest_notifiers(qbus->parent, total_queues * 2, false);
     if (e < 0) {
@@ -337,6 +339,7 @@ void vhost_net_stop(VirtIODevice *dev, NetClientState *ncs,
 
     for (i = 0; i < total_queues; i++) {
         vhost_net_stop_one(get_vhost_net(ncs[i].peer), dev);
+        put_vhost_net(ncs[i].peer);
     }
 
     r = k->set_guest_notifiers(qbus->parent, total_queues * 2, false);
@@ -398,16 +401,25 @@ VHostNetState *get_vhost_net(NetClientState *nc)
     return vhost_net;
 }
 
+void put_vhost_net(NetClientState *nc)
+{
+    if (nc && nc->info->type == NET_CLIENT_OPTIONS_KIND_VHOST_USER) {
+        vhost_user_put_vhost_net(nc);
+    }
+}
+
 int vhost_set_vring_enable(NetClientState *nc, int enable)
 {
     VHostNetState *net = get_vhost_net(nc);
     const VhostOps *vhost_ops = net->dev.vhost_ops;
+    int res = 0;
 
     if (vhost_ops->vhost_set_vring_enable) {
-        return vhost_ops->vhost_set_vring_enable(&net->dev, enable);
+        res = vhost_ops->vhost_set_vring_enable(&net->dev, enable);
     }
 
-    return 0;
+    put_vhost_net(nc);
+    return res;
 }
 
 #else
@@ -466,6 +478,10 @@ VHostNetState *get_vhost_net(NetClientState *nc)
     return 0;
 }
 
+void put_vhost_net(NetClientState *nc)
+{
+}
+
 int vhost_set_vring_enable(NetClientState *nc, int enable)
 {
     return 0;
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 5798f87..e5456ef 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -121,6 +121,7 @@ static void virtio_net_vhost_status(VirtIONet *n, uint8_t status)
     if (!get_vhost_net(nc->peer)) {
         return;
     }
+    put_vhost_net(nc->peer);
 
     if ((virtio_net_started(n, status) && !nc->peer->link_down) ==
         !!n->vhost_started) {
@@ -521,6 +522,8 @@ static uint64_t virtio_net_get_features(VirtIODevice *vdev, uint64_t features,
 {
     VirtIONet *n = VIRTIO_NET(vdev);
     NetClientState *nc = qemu_get_queue(n->nic);
+    VHostNetState *net;
+    uint64_t res;
 
     /* Firstly sync all virtio-net possible supported features */
     features |= n->host_features;
@@ -544,10 +547,15 @@ static uint64_t virtio_net_get_features(VirtIODevice *vdev, uint64_t features,
         virtio_clear_feature(&features, VIRTIO_NET_F_HOST_UFO);
     }
 
-    if (!get_vhost_net(nc->peer)) {
-        return features;
+    net = get_vhost_net(nc->peer);
+    if (!net) {
+        res = features;
+    } else {
+        res = vhost_net_get_features(net, features);
+        put_vhost_net(nc->peer);
     }
-    return vhost_net_get_features(get_vhost_net(nc->peer), features);
+
+    return res;
 }
 
 static uint64_t virtio_net_bad_features(VirtIODevice *vdev)
@@ -615,11 +623,13 @@ static void virtio_net_set_features(VirtIODevice *vdev, uint64_t features)
 
     for (i = 0;  i < n->max_queues; i++) {
         NetClientState *nc = qemu_get_subqueue(n->nic, i);
+        VHostNetState *net = get_vhost_net(nc->peer);
 
-        if (!get_vhost_net(nc->peer)) {
+        if (!net) {
             continue;
         }
-        vhost_net_ack_features(get_vhost_net(nc->peer), features);
+        vhost_net_ack_features(net, features);
+        put_vhost_net(nc->peer);
     }
 
     if (virtio_has_feature(features, VIRTIO_NET_F_CTRL_VLAN)) {
@@ -1698,8 +1708,13 @@ static bool virtio_net_guest_notifier_pending(VirtIODevice *vdev, int idx)
 {
     VirtIONet *n = VIRTIO_NET(vdev);
     NetClientState *nc = qemu_get_subqueue(n->nic, vq2q(idx));
+    VHostNetState *net = get_vhost_net(nc->peer);
+    bool res;
+
     assert(n->vhost_started);
-    return vhost_net_virtqueue_pending(get_vhost_net(nc->peer), idx);
+    res = vhost_net_virtqueue_pending(net, idx);
+    put_vhost_net(nc->peer);
+    return res;
 }
 
 static void virtio_net_guest_notifier_mask(VirtIODevice *vdev, int idx,
@@ -1707,9 +1722,10 @@ static void virtio_net_guest_notifier_mask(VirtIODevice *vdev, int idx,
 {
     VirtIONet *n = VIRTIO_NET(vdev);
     NetClientState *nc = qemu_get_subqueue(n->nic, vq2q(idx));
+    VHostNetState *net = get_vhost_net(nc->peer);
     assert(n->vhost_started);
-    vhost_net_virtqueue_mask(get_vhost_net(nc->peer),
-                             vdev, idx, mask);
+    vhost_net_virtqueue_mask(net, vdev, idx, mask);
+    put_vhost_net(nc->peer);
 }
 
 static void virtio_net_set_config_size(VirtIONet *n, uint64_t host_features)
diff --git a/include/net/vhost-user.h b/include/net/vhost-user.h
index 85109f6..6bdaa1a 100644
--- a/include/net/vhost-user.h
+++ b/include/net/vhost-user.h
@@ -13,5 +13,6 @@
 
 struct vhost_net;
 struct vhost_net *vhost_user_get_vhost_net(NetClientState *nc);
+void vhost_user_put_vhost_net(NetClientState *nc);
 
 #endif /* VHOST_USER_H_ */
diff --git a/include/net/vhost_net.h b/include/net/vhost_net.h
index 3389b41..577bfa8 100644
--- a/include/net/vhost_net.h
+++ b/include/net/vhost_net.h
@@ -29,6 +29,7 @@ void vhost_net_virtqueue_mask(VHostNetState *net, VirtIODevice *dev,
                               int idx, bool mask);
 int vhost_net_notify_migration_done(VHostNetState *net, char* mac_addr);
 VHostNetState *get_vhost_net(NetClientState *nc);
+void put_vhost_net(NetClientState *nc);
 
 int vhost_set_vring_enable(NetClientState * nc, int enable);
 #endif
diff --git a/net/filter.c b/net/filter.c
index 1c4fc5a..28403aa 100644
--- a/net/filter.c
+++ b/net/filter.c
@@ -214,6 +214,7 @@ static void netfilter_complete(UserCreatable *uc, Error **errp)
 
     if (get_vhost_net(ncs[0])) {
         error_setg(errp, "Vhost is not supported");
+        put_vhost_net(ncs[0]);
         return;
     }
 
diff --git a/net/vhost-user.c b/net/vhost-user.c
index 1b9e73a..9026df3 100644
--- a/net/vhost-user.c
+++ b/net/vhost-user.c
@@ -22,6 +22,7 @@ typedef struct VhostUserState {
     NetClientState nc;
     CharDriverState *chr;
     VHostNetState *vhost_net;
+    int refcnt;
 } VhostUserState;
 
 typedef struct VhostUserChardevProps {
@@ -29,13 +30,41 @@ typedef struct VhostUserChardevProps {
     bool is_unix;
 } VhostUserChardevProps;
 
+static void vhost_user_net_ref(VhostUserState *s)
+{
+    if (!s->vhost_net) {
+        return;
+    }
+    s->refcnt++;
+}
+
+static void vhost_user_net_unref(VhostUserState *s)
+{
+    if (!s->vhost_net) {
+        return;
+    }
+
+    if (--s->refcnt == 0) {
+        vhost_net_cleanup(s->vhost_net);
+        s->vhost_net = NULL;
+    }
+}
+
 VHostNetState *vhost_user_get_vhost_net(NetClientState *nc)
 {
     VhostUserState *s = DO_UPCAST(VhostUserState, nc, nc);
     assert(nc->info->type == NET_CLIENT_OPTIONS_KIND_VHOST_USER);
+    vhost_user_net_ref(s);
     return s->vhost_net;
 }
 
+void vhost_user_put_vhost_net(NetClientState *nc)
+{
+    VhostUserState *s = DO_UPCAST(VhostUserState, nc, nc);
+    assert(nc->info->type == NET_CLIENT_OPTIONS_KIND_VHOST_USER);
+    vhost_user_net_unref(s);
+}
+
 static int vhost_user_running(VhostUserState *s)
 {
     return (s->vhost_net) ? 1 : 0;
@@ -54,10 +83,7 @@ static void vhost_user_stop(int queues, NetClientState *ncs[])
             continue;
         }
 
-        if (s->vhost_net) {
-            vhost_net_cleanup(s->vhost_net);
-            s->vhost_net = NULL;
-        }
+        vhost_user_net_unref(s);
     }
 }
 
@@ -81,6 +107,7 @@ static int vhost_user_start(int queues, NetClientState *ncs[])
         options.net_backend = ncs[i];
         options.opaque      = s->chr;
         s->vhost_net = vhost_net_init(&options);
+        vhost_user_net_ref(s);
         if (!s->vhost_net) {
             error_report("failed to init vhost_net for queue %d", i);
             goto err;
@@ -119,7 +146,9 @@ static ssize_t vhost_user_receive(NetClientState *nc, const uint8_t *buf,
         /* extract guest mac address from the RARP message */
         memcpy(mac_addr, &buf[6], 6);
 
+        vhost_user_net_ref(s);
         r = vhost_net_notify_migration_done(s->vhost_net, mac_addr);
+        vhost_user_net_unref(s);
 
         if ((r != 0) && (display_rarp_failure)) {
             fprintf(stderr,
@@ -136,11 +165,7 @@ static void vhost_user_cleanup(NetClientState *nc)
 {
     VhostUserState *s = DO_UPCAST(VhostUserState, nc, nc);
 
-    if (s->vhost_net) {
-        vhost_net_cleanup(s->vhost_net);
-        s->vhost_net = NULL;
-    }
-
+    vhost_user_net_unref(s);
     qemu_purge_queued_packets(nc);
 }
 
