* vhost question
@ 2012-03-18 12:43 Steve Glass
0 siblings, 0 replies; 5+ messages in thread
From: Steve Glass @ 2012-03-18 12:43 UTC (permalink / raw)
To: virtualization
[-- Attachment #1.1: Type: text/plain, Size: 3086 bytes --]
Hi,
I'm using virtio to implement a mac80211 device in the guest. On the host
side I plan to use a simple network simulation to control delivery of
frames between guests. Right now I've used the vhost approach on the host
side and can pass buffers from guest to host and back using virtio.
My immediate problem is how to have the host-side tx kick handler get the
host-side rx kick handler to run in order to deliver a frame? In the tx
kick handler I copy the frame into a queue for the receiving guest. In the
rx_handler I take queued frames and copy them into the rx buffers and wake
the guest. The problem is that if no frames are ready for delivery when the
guest rx kick handler runs then it has to exit and somehow I have to
arrange that it runs again (in the receiver's process context) when there
are frames to deliver.
How can I get my host-side tx kick handler to wake the host-side rx kick
handler to deliver frames to the guest?
Steve
--
static void
handle_rx(struct vhost_work *work)
{
int n;
unsigned out, in;
struct transmission *t;
u16 frames = 0;
struct vhost_poll *p = container_of(work, struct vhost_poll, work);
struct vhost_virtqueue *vq = container_of(p, struct vhost_virtqueue, poll);
struct vhost_node *node = container_of(vq, struct vhost_node,
vqs[WLAN_VQ_RX]);
struct vhost_dev *dev = &node->vdev;
mutex_lock(&vq->mutex);
vhost_disable_notify(dev, vq);
while (!queue_empty(&node->rxq)) {
n = vhost_get_vq_desc(dev, vq, vq->iov, ARRAY_SIZE(vq->iov), &out, &in,
NULL, NULL);
if (0 < n || n == vq->num)
break;
if ((t = queue_pop(&node->rxq))) {
BUG_ON(copy_to_user(vq->iov[0].iov_base, t->buf, t->buf_sz));
vq->iov[0].iov_len = t->buf_sz;
// ToDo: copy_to_user the rx_status
vhost_add_used(vq, n, out);
transmission_free(t);
++frames;
}
}
if (frames)
vhost_signal(dev, vq);
vhost_enable_notify(dev, vq);
mutex_unlock(&vq->mutex);
}
static void
handle_tx(struct vhost_work *work)
{
int n;
unsigned out, in;
struct transmission *t;
struct vhost_poll *p = container_of(work, struct vhost_poll, work);
struct vhost_virtqueue *vq = container_of(p, struct vhost_virtqueue, poll);
struct vhost_node *w = container_of(vq, struct vhost_node, vqs[WLAN_VQ_TX]);
struct vhost_dev *dev = &w->vdev;
mutex_lock(&vq->mutex);
do {
vhost_disable_notify(dev, vq);
n = vhost_get_vq_desc(dev, vq, vq->iov, ARRAY_SIZE(vq->iov), &out, &in,
NULL, NULL);
while (n >= 0 && n != vq->num) {
struct vhost_node *receiver = net_get_receiver(w);
if(receiver) {
if((t = transmission_alloc())) {
BUG_ON(copy_from_user(t->buf, vq->iov[1].iov_base, vq->iov[1].iov_len));
t->buf_sz = vq->iov[1].iov_len;
queue_push(&receiver->rxq, t);
// ToDo: kick receiver's handle_rx
// ToDo: populate TX status
} else {
pr_warn("%s: out of memory - packet dropped!", __func__);
// ToDo: populate TX status
}
} else {
pr_debug("%s: no receivers in range!", __func__);
// ToDo: populate TX status
}
vhost_add_used(vq, n, out);
n = vhost_get_vq_desc(dev, vq, vq->iov, ARRAY_SIZE(vq->iov), &out, &in,
NULL, NULL);
}
vhost_signal(dev, vq);
} while (vhost_enable_notify(dev, vq));
mutex_unlock(&vq->mutex);
}
[-- Attachment #1.2: Type: text/html, Size: 11189 bytes --]
[-- Attachment #2: Type: text/plain, Size: 183 bytes --]
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
^ permalink raw reply [flat|nested] 5+ messages in thread
* vhost question
@ 2012-03-19 3:11 Steve Glass
0 siblings, 0 replies; 5+ messages in thread
From: Steve Glass @ 2012-03-19 3:11 UTC (permalink / raw)
To: virtualization
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Hi,
I'm using virtio to implement a mac80211 device in the guest. On the
host side I plan to use a simple network simulation to control
delivery of frames between guests. Right now I've used the vhost
approach on the host side and can pass buffers from guest to host and
back using virtio.
My immediate problem is how to have the host-side tx kick handler get
the host-side rx kick handler to run in order to deliver a frame? In
the tx kick handler I copy the frame into a queue for the receiving
guest. In the rx_handler I take queued frames and copy them into the
rx buffers and wake the guest. The problem is that if no frames are
ready for delivery when the guest rx kick handler runs then it has to
exit and somehow I have to arrange that it runs again (in the
receiver's process context) when there are frames to deliver.
How can I get my host-side tx kick handler to wake the host-side rx
kick handler to deliver frames to the guest?
Steve
static void
handle_rx(struct vhost_work *work)
{
int n;
unsigned out, in;
struct transmission *t;
u16 frames = 0;
struct vhost_poll *p = container_of(work, struct vhost_poll, work);
struct vhost_virtqueue *vq = container_of(p, struct vhost_virtqueue,
poll);
struct vhost_node *node = container_of(vq, struct vhost_node,
vqs[WLAN_VQ_RX]);
struct vhost_dev *dev = &node->vdev;
mutex_lock(&vq->mutex);
vhost_disable_notify(dev, vq);
while (!queue_empty(&node->rxq)) {
n = vhost_get_vq_desc(dev, vq, vq->iov, ARRAY_SIZE(vq->iov), &out,
&in, NULL, NULL);
if (0 < n || n == vq->num)
break;
if ((t = queue_pop(&node->rxq))) {
BUG_ON(copy_to_user(vq->iov[0].iov_base, t->buf, t->buf_sz));
vq->iov[0].iov_len = t->buf_sz;
// ToDo: copy_to_user the rx_status
vhost_add_used(vq, n, out);
transmission_free(t);
++frames;
}
}
if (frames)
vhost_signal(dev, vq);
vhost_enable_notify(dev, vq);
mutex_unlock(&vq->mutex);
}
static void
handle_tx(struct vhost_work *work)
{
int n;
unsigned out, in;
struct transmission *t;
struct vhost_poll *p = container_of(work, struct vhost_poll, work);
struct vhost_virtqueue *vq = container_of(p, struct vhost_virtqueue,
poll);
struct vhost_node *w = container_of(vq, struct vhost_node,
vqs[WLAN_VQ_TX]);
struct vhost_dev *dev = &w->vdev;
mutex_lock(&vq->mutex);
do {
vhost_disable_notify(dev, vq);
n = vhost_get_vq_desc(dev, vq, vq->iov, ARRAY_SIZE(vq->iov), &out,
&in, NULL, NULL);
while (n >= 0 && n != vq->num) {
struct vhost_node *receiver = net_get_receiver(w);
if(receiver) {
if((t = transmission_alloc())) {
BUG_ON(copy_from_user(t->buf, vq->iov[1].iov_base, vq->iov[1].iov_len));
t->buf_sz = vq->iov[1].iov_len;
queue_push(&receiver->rxq, t);
// ToDo: kick receiver's handle_rx
// ToDo: populate TX status
} else {
pr_warn("%s: out of memory - packet dropped!", __func__);
// ToDo: populate TX status
}
} else {
pr_debug("%s: no receivers in range!", __func__);
// ToDo: populate TX status
}
vhost_add_used(vq, n, out);
n = vhost_get_vq_desc(dev, vq, vq->iov, ARRAY_SIZE(vq->iov), &out,
&in, NULL, NULL);
}
vhost_signal(dev, vq);
} while (vhost_enable_notify(dev, vq));
mutex_unlock(&vq->mutex);
}
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/
iEYEARECAAYFAk9mo9cACgkQW7aAm65EWy4tagCgvsGxQM7Hhgjqc8/OAN5EsRrg
xW0An1jqNVvTICA5yhhj+6S9LtdkyHJi
=XGVm
-----END PGP SIGNATURE-----
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: vhost question
@ 2012-03-22 1:48 Steve Glass
0 siblings, 0 replies; 5+ messages in thread
From: Steve Glass @ 2012-03-22 1:48 UTC (permalink / raw)
To: virtualization, kvm, netdev
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Just some further information concerning my earlier question
concerning vhost and virtio.
I'm using virtio to implement an emulated mac80211 device in the
guest. A simple network simulation will be used to control delivery of
frames between guests and for this I am using the vhost approach.
A simple first-cut attempt at the tx and rx kick handlers are given
below. When the guest transmits frames the vhost's TX kick handler is
executed and copies the buffers onto a queue for the intended
recipient(s). When the vhost's RX kick handler is run it copies the
buffer from the queue and notifies the client that the buffers have
been used.
The problem is that if there are no frames in the queue when the guest
rx kick handler runs then it has to exit and I have to arrange that it
runs again. That's done in the current prototype by having the guests
poll using a timer - which is ugly and inefficient. Can I get the
vhost tx kick handler to wake the appropriate vhost rx kick handler?
How can I achieve this?
Many thanks,
Steve
static void
handle_rx(struct vhost_work *work)
{
int n;
unsigned out, in, frames;
struct transmission *t;
struct vhost_poll *p = container_of(work, struct vhost_poll,
work);
struct vhost_virtqueue *vq =
container_of(p, struct vhost_virtqueue, poll);
struct vhost_node *node =
container_of(vq, struct vhost_node, vqs[WLAN_VQ_RX]);
struct vhost_dev *dev = &node->vdev;
mutex_lock(&vq->mutex);
vhost_disable_notify(dev, vq);
while (!queue_empty(&node->rxq)) {
n = vhost_get_vq_desc(dev,
vq,
vq->iov,
ARRAY_SIZE(vq->iov),
&out,
&in,
NULL,
NULL);
if (0 < n || n == vq->num)
break;
t = queue_pop(&node->rxq);
BUG_ON(copy_to_user(vq->iov[0].iov_base, t->buf,
t->buf_sz));
vq->iov[0].iov_len = t->buf_sz;
vhost_add_used(vq, n, out);
transmission_free(t);
++frames;
}
if (frames)
vhost_signal(dev, vq);
vhost_enable_notify(dev, vq);
mutex_unlock(&vq->mutex);
}
static void
handle_tx(struct vhost_work *work)
{
int n;
unsigned out, in;
struct transmission *t;
struct vhost_node *receiver;
struct vhost_poll *p =
container_of(work, struct vhost_poll, work);
struct vhost_virtqueue *vq =
container_of(p, struct vhost_virtqueue, poll);
struct vhost_node *w =
container_of(vq, struct vhost_node, vqs[WLAN_VQ_TX]);
struct vhost_dev *dev = &w->vdev;
mutex_lock(&vq->mutex);
do {
vhost_disable_notify(dev, vq);
n = vhost_get_vq_desc(dev,
vq,
vq->iov,
ARRAY_SIZE(vq->iov),
&out,
&in,
NULL,
NULL);
while (n >= 0 && n != vq->num) {
receiver = net_get_receiver(w);
if ((receiver) && (t = transmission_alloc())) {
BUG_ON(copy_from_user(t->buf,
vq->iov[1].iov_base,
vq->iov[1].iov_len));
t->buf_sz = vq->iov[1].iov_len;
queue_push(&receiver->rxq, t);
// ToDo: kick receiver's handle_rx
}
vhost_add_used(vq, n, out);
n = vhost_get_vq_desc(dev,
vq,
vq->iov,
ARRAY_SIZE(vq->iov),
&out,
&in,
NULL,
NULL);
}
vhost_signal(dev, vq);
} while (vhost_enable_notify(dev, vq));
mutex_unlock(&vq->mutex);
}
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.12 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/
iEYEARECAAYFAk9qhO4ACgkQW7aAm65EWy7w4wCgrzGB2Zit4rWUzMjwpJEJnIfj
xDsAoLBDMj+4MVrjPS5upgDSIGOi4IzL
=Ms/+
-----END PGP SIGNATURE-----
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: vhost question
[not found] <4F6A84EF.9060105@gmail.com>
@ 2012-03-22 9:52 ` Stefan Hajnoczi
[not found] ` <CADC0ay0ZRL79uMq72kAewOBTMCgMe1_1BLotdH9QnOwosJkTYQ@mail.gmail.com>
0 siblings, 1 reply; 5+ messages in thread
From: Stefan Hajnoczi @ 2012-03-22 9:52 UTC (permalink / raw)
To: Steve Glass; +Cc: netdev, kvm, virtualization
On Thu, Mar 22, 2012 at 1:48 AM, Steve Glass <stevie.glass@gmail.com> wrote:
>
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
>
> Just some further information concerning my earlier question
> concerning vhost and virtio.
>
> I'm using virtio to implement an emulated mac80211 device in the
> guest. A simple network simulation will be used to control delivery of
> frames between guests and for this I am using the vhost approach.
>
> A simple first-cut attempt at the tx and rx kick handlers are given
> below. When the guest transmits frames the vhost's TX kick handler is
> executed and copies the buffers onto a queue for the intended
> recipient(s). When the vhost's RX kick handler is run it copies the
> buffer from the queue and notifies the client that the buffers have
> been used.
>
> The problem is that if there are no frames in the queue when the guest
> rx kick handler runs then it has to exit and I have to arrange that it
> runs again. That's done in the current prototype by having the guests
> poll using a timer - which is ugly and inefficient. Can I get the
> vhost tx kick handler to wake the appropriate vhost rx kick handler?
> How can I achieve this?
Can you queue a tx->rx kick on the vhost work queue with vhost_work_queue()?
Stefan
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: vhost question
[not found] ` <CADC0ay0ZRL79uMq72kAewOBTMCgMe1_1BLotdH9QnOwosJkTYQ@mail.gmail.com>
@ 2012-03-25 16:18 ` Stefan Hajnoczi
0 siblings, 0 replies; 5+ messages in thread
From: Stefan Hajnoczi @ 2012-03-25 16:18 UTC (permalink / raw)
To: Steve Glass
On Sun, Mar 25, 2012 at 1:29 PM, Steve Glass <stevie.glass@gmail.com> wrote:
> On 22 March 2012 19:52, Stefan Hajnoczi <stefanha@gmail.com> wrote:
>>
>>
>> Can you queue a tx->rx kick on the vhost work queue with
>> vhost_work_queue()?
>>
>> Stefan
>
>
> I've been looking at this and trying to work out how to achieve that. I can
> see how I can enqueue some work on the vhost queue but the rx_handler needs
> to run in the process context of the receiving VM (or else it can't access
> the ring). I don't think that's true of the work queue (doesn't it run with
> the qemu process context?)
The vhost worker thread has the mm of the process, see use_mm(dev->mm)
in drivers/vhost/vhost.c:vhost_worker(). It sounds like you need
vhost worker A (tx) to schedule work for vhost worker B (rx).
Stefan
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2012-03-25 16:18 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-03-19 3:11 vhost question Steve Glass
[not found] <4F6A84EF.9060105@gmail.com>
2012-03-22 9:52 ` Stefan Hajnoczi
[not found] ` <CADC0ay0ZRL79uMq72kAewOBTMCgMe1_1BLotdH9QnOwosJkTYQ@mail.gmail.com>
2012-03-25 16:18 ` Stefan Hajnoczi
-- strict thread matches above, loose matches on Subject: below --
2012-03-22 1:48 Steve Glass
2012-03-18 12:43 Steve Glass
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).