diff mbox

Add qemu_send_raw() to vlan.

Message ID 20090526100302.GS3948@redhat.com (mailing list archive)
State New, archived
Headers show

Commit Message

Gleb Natapov May 26, 2009, 10:03 a.m. UTC
It gets packet without virtio header and adds it if needed.  Allows to
inject packets to vlan from outside. To send gracious arp for instance.

--
			Gleb.
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Comments

Avi Kivity May 26, 2009, 10:05 a.m. UTC | #1
Gleb Natapov wrote:
> It gets packet without virtio header and adds it if needed.  Allows to
> inject packets to vlan from outside. To send gracious arp for instance.
>   

This is for announce_self(), no?  If so, upstream has the same problems?
Gleb Natapov May 26, 2009, 10:08 a.m. UTC | #2
On Tue, May 26, 2009 at 01:05:35PM +0300, Avi Kivity wrote:
> Gleb Natapov wrote:
>> It gets packet without virtio header and adds it if needed.  Allows to
>> inject packets to vlan from outside. To send gracious arp for instance.
>>   
>
> This is for announce_self(), no?  If so, upstream has the same problems?
>
VNET_HDR is not upstream.

--
			Gleb.
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Avi Kivity May 26, 2009, 10:11 a.m. UTC | #3
Gleb Natapov wrote:
> On Tue, May 26, 2009 at 01:05:35PM +0300, Avi Kivity wrote:
>   
>> Gleb Natapov wrote:
>>     
>>> It gets packet without virtio header and adds it if needed.  Allows to
>>> inject packets to vlan from outside. To send gracious arp for instance.
>>>   
>>>       
>> This is for announce_self(), no?  If so, upstream has the same problems?
>>
>>     
> VNET_HDR is not upstream.
>
>   

Mark, how far are we from that?
Mark McLoughlin May 26, 2009, 10:28 a.m. UTC | #4
On Tue, 2009-05-26 at 13:11 +0300, Avi Kivity wrote:
> Gleb Natapov wrote:
> > On Tue, May 26, 2009 at 01:05:35PM +0300, Avi Kivity wrote:
> >   
> >> Gleb Natapov wrote:
> >>     
> >>> It gets packet without virtio header and adds it if needed.  Allows to
> >>> inject packets to vlan from outside. To send gracious arp for instance.
> >>>   
> >>>       
> >> This is for announce_self(), no?  If so, upstream has the same problems?
> >>
> >>     
> > VNET_HDR is not upstream.
> >
> >   
> 
> Mark, how far are we from that?

We first need to add support for paired devices (i.e. a tap/virtio-net
pair) rather than trying to munge this stuff into the VLAN code.

Cheers,
Mark.

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Mark McLoughlin May 26, 2009, 10:34 a.m. UTC | #5
On Tue, 2009-05-26 at 13:03 +0300, Gleb Natapov wrote:
> It gets packet without virtio header and adds it if needed.  Allows to
> inject packets to vlan from outside. To send gracious arp for instance.

Acked-by: Mark McLoughlin <markmc@redhat.com>

This isn't ideal, but neither is the current VNET_HDR stuff and it does
fix a genuine bug. At least it's not changing existing APIs and makes it
clear this is a problem we also need to solve when merging VNET_HDR
support upstream.

(Gleb - it might be worth patching qemu.git to use qemu_send_packet() in
announce_self(), that will reduce the delta between the trees)

Cheers,
Mark.

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Avi Kivity May 26, 2009, 11:15 a.m. UTC | #6
Mark McLoughlin wrote:
> On Tue, 2009-05-26 at 13:03 +0300, Gleb Natapov wrote:
>   
>> It gets packet without virtio header and adds it if needed.  Allows to
>> inject packets to vlan from outside. To send gracious arp for instance.
>>     
>
> Acked-by: Mark McLoughlin <markmc@redhat.com>
>
> This isn't ideal, but neither is the current VNET_HDR stuff and it does
> fix a genuine bug. At least it's not changing existing APIs and makes it
> clear this is a problem we also need to solve when merging VNET_HDR
> support upstream.
>
> (Gleb - it might be worth patching qemu.git to use qemu_send_packet() in
> announce_self(), that will reduce the delta between the trees)
>
>   

Okay.  Bug Gleb, please add a signoff.
Gleb Natapov May 26, 2009, 12:05 p.m. UTC | #7
On Tue, May 26, 2009 at 02:15:37PM +0300, Avi Kivity wrote:
> Mark McLoughlin wrote:
>> On Tue, 2009-05-26 at 13:03 +0300, Gleb Natapov wrote:
>>   
>>> It gets packet without virtio header and adds it if needed.  Allows to
>>> inject packets to vlan from outside. To send gracious arp for instance.
>>>     
>>
>> Acked-by: Mark McLoughlin <markmc@redhat.com>
>>
>> This isn't ideal, but neither is the current VNET_HDR stuff and it does
>> fix a genuine bug. At least it's not changing existing APIs and makes it
>> clear this is a problem we also need to solve when merging VNET_HDR
>> support upstream.
>>
>> (Gleb - it might be worth patching qemu.git to use qemu_send_packet() in
>> announce_self(), that will reduce the delta between the trees)
>>
>>   
>
> Okay.  Bug Gleb, please add a signoff.
>
Signed-off-by: Gleb Natapov <gleb@redhat.com>

--
			Gleb.
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Avi Kivity May 26, 2009, 12:20 p.m. UTC | #8
Gleb Natapov wrote:
> On Tue, May 26, 2009 at 02:15:37PM +0300, Avi Kivity wrote:
>   
>> Mark McLoughlin wrote:
>>     
>>> On Tue, 2009-05-26 at 13:03 +0300, Gleb Natapov wrote:
>>>   
>>>       
>>>> It gets packet without virtio header and adds it if needed.  Allows to
>>>> inject packets to vlan from outside. To send gracious arp for instance.
>>>>     
>>>>         
>>> Acked-by: Mark McLoughlin <markmc@redhat.com>
>>>
>>> This isn't ideal, but neither is the current VNET_HDR stuff and it does
>>> fix a genuine bug. At least it's not changing existing APIs and makes it
>>> clear this is a problem we also need to solve when merging VNET_HDR
>>> support upstream.
>>>
>>> (Gleb - it might be worth patching qemu.git to use qemu_send_packet() in
>>> announce_self(), that will reduce the delta between the trees)
>>>
>>>   
>>>       
>> Okay.  Bug Gleb, please add a signoff.
>>
>>     
> Signed-off-by: Gleb Natapov <gleb@redhat.com>
>
>   

Thanks, added the signoff and the patch.
diff mbox

Patch

diff --git a/hw/virtio-net.c b/hw/virtio-net.c
index 8e9178d..3c77b99 100644
--- a/hw/virtio-net.c
+++ b/hw/virtio-net.c
@@ -389,7 +389,7 @@  static int iov_fill(struct iovec *iov, int iovcnt, const void *buf, int count)
 }
 
 static int receive_header(VirtIONet *n, struct iovec *iov, int iovcnt,
-                          const void *buf, size_t size, size_t hdr_len)
+                          const void *buf, size_t size, size_t hdr_len, int raw)
 {
     struct virtio_net_hdr *hdr = (struct virtio_net_hdr *)iov[0].iov_base;
     int offset = 0;
@@ -399,7 +399,11 @@  static int receive_header(VirtIONet *n, struct iovec *iov, int iovcnt,
 
 #ifdef TAP_VNET_HDR
     if (tap_has_vnet_hdr(n->vc->vlan->first_client)) {
-        memcpy(hdr, buf, sizeof(*hdr));
+        if (!raw) {
+            memcpy(hdr, buf, sizeof(*hdr));
+        } else {
+            memset(hdr, 0, sizeof(*hdr));
+        }
         offset = sizeof(*hdr);
         work_around_broken_dhclient(hdr, buf + offset, size - offset);
     }
@@ -452,7 +456,7 @@  static int receive_filter(VirtIONet *n, const uint8_t *buf, int size)
     return 0;
 }
 
-static void virtio_net_receive(void *opaque, const uint8_t *buf, int size)
+static void virtio_net_receive2(void *opaque, const uint8_t *buf, int size, int raw)
 {
     VirtIONet *n = opaque;
     struct virtio_net_hdr_mrg_rxbuf *mhdr = NULL;
@@ -502,7 +506,7 @@  static void virtio_net_receive(void *opaque, const uint8_t *buf, int size)
                 mhdr = (struct virtio_net_hdr_mrg_rxbuf *)sg[0].iov_base;
 
             offset += receive_header(n, sg, elem.in_num,
-                                     buf + offset, size - offset, hdr_len);
+                                     buf + offset, size - offset, hdr_len, raw);
             total += hdr_len;
         }
 
@@ -524,6 +528,16 @@  static void virtio_net_receive(void *opaque, const uint8_t *buf, int size)
     virtio_notify(&n->vdev, n->rx_vq);
 }
 
+static void virtio_net_receive(void *opaque, const uint8_t *buf, int size)
+{
+    virtio_net_receive2(opaque, buf, size, 0);
+}
+
+static void virtio_net_receive_raw(void *opaque, const uint8_t *buf, int size)
+{
+    virtio_net_receive2(opaque, buf, size, 1);
+}
+
 /* TX */
 static void virtio_net_flush_tx(VirtIONet *n, VirtQueue *vq)
 {
@@ -721,6 +735,7 @@  VirtIODevice *virtio_net_init(DeviceState *dev)
                                  virtio_net_can_receive,
                                  virtio_net_cleanup, n);
     n->vc->link_status_changed = virtio_net_set_link_status;
+    n->vc->fd_read_raw = virtio_net_receive_raw;
 
     qemu_format_nic_info_str(n->vc, n->mac);
 
diff --git a/net.c b/net.c
index 3dfc728..01e31db 100644
--- a/net.c
+++ b/net.c
@@ -456,6 +456,31 @@  int qemu_send_packet(VLANClientState *vc, const uint8_t *buf, int size)
     return ret;
 }
 
+void qemu_send_packet_raw(VLANClientState *sender, const uint8_t *buf, int size)
+{
+    VLANState *vlan = sender->vlan;
+    VLANClientState *vc;
+
+    if (sender->link_down)
+        return;
+
+#ifdef DEBUG_NET
+    printf("vlan %d send raw:\n", vlan->id);
+    hex_dump(stdout, buf, size);
+#endif
+    for(vc = vlan->first_client; vc != NULL; vc = vc->next) {
+        if (vc == sender || vc->link_down) {
+            continue;
+        }
+        if (vc->fd_read_raw) {
+            vc->fd_read_raw(vc->opaque, buf, size);
+        } else {
+            vc->fd_read(vc->opaque, buf, size);
+        }
+    }
+    return;
+}
+
 static ssize_t vc_sendv_compat(VLANClientState *vc, const struct iovec *iov,
                                int iovcnt)
 {
@@ -823,6 +848,29 @@  static void tap_receive(void *opaque, const uint8_t *buf, int size)
     tap_receive_iov(opaque, iov, i);
 }
 
+static void tap_receive_raw(void *opaque, const uint8_t *buf, int size)
+{
+    struct iovec iov[2];
+    int i = 0;
+
+#ifdef IFF_VNET_HDR
+    TAPState *s = opaque;
+    struct virtio_net_hdr hdr = { 0, };
+
+    if (s->has_vnet_hdr && s->using_vnet_hdr) {
+        iov[i].iov_base = &hdr;
+        iov[i].iov_len  = sizeof(hdr);
+        i++;
+    }
+#endif
+
+    iov[i].iov_base = (char *) buf;
+    iov[i].iov_len  = size;
+    i++;
+
+    tap_receive_iov(opaque, iov, i);
+}
+
 static int tap_can_send(void *opaque)
 {
     TAPState *s = opaque;
@@ -992,6 +1040,7 @@  static TAPState *net_tap_fd_init(VLANState *vlan,
     s->vc = qemu_new_vlan_client(vlan, model, name, tap_receive,
                                  NULL, tap_cleanup, s);
     s->vc->fd_readv = tap_receive_iov;
+    s->vc->fd_read_raw = tap_receive_raw;
 #ifdef TUNSETOFFLOAD
     s->vc->set_offload = tap_set_offload;
     tap_set_offload(s->vc, 0, 0, 0, 0);
diff --git a/net.h b/net.h
index 931133b..3d0b6f2 100644
--- a/net.h
+++ b/net.h
@@ -15,6 +15,7 @@  typedef void (SetOffload)(VLANClientState *, int, int, int, int);
 
 struct VLANClientState {
     IOReadHandler *fd_read;
+    IOReadHandler *fd_read_raw;
     IOReadvHandler *fd_readv;
     /* Packets may still be sent if this returns zero.  It's used to
        rate-limit the slirp code.  */
@@ -63,6 +64,7 @@  int qemu_can_send_packet(VLANClientState *vc);
 ssize_t qemu_sendv_packet(VLANClientState *vc, const struct iovec *iov,
                           int iovcnt);
 int qemu_send_packet(VLANClientState *vc, const uint8_t *buf, int size);
+void qemu_send_packet_raw(VLANClientState *vc, const uint8_t *buf, int size);
 void qemu_format_nic_info_str(VLANClientState *vc, uint8_t macaddr[6]);
 void qemu_check_nic_model(NICInfo *nd, const char *model);
 void qemu_check_nic_model_list(NICInfo *nd, const char * const *models,