From: Gleb Natapov <gleb@redhat.com>
To: avi@redhat.com
Cc: kvm@vger.kernel.org, Mark McLoughlin <markmc@redhat.com>
Subject: Add qemu_send_raw() to vlan.
Date: Tue, 26 May 2009 13:03:02 +0300 [thread overview]
Message-ID: <20090526100302.GS3948@redhat.com> (raw)
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.
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,
--
Gleb.
next reply other threads:[~2009-05-26 10:03 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-05-26 10:03 Gleb Natapov [this message]
2009-05-26 10:05 ` Add qemu_send_raw() to vlan Avi Kivity
2009-05-26 10:08 ` Gleb Natapov
2009-05-26 10:11 ` Avi Kivity
2009-05-26 10:28 ` Mark McLoughlin
2009-05-26 10:34 ` Mark McLoughlin
2009-05-26 11:15 ` Avi Kivity
2009-05-26 12:05 ` Gleb Natapov
2009-05-26 12:20 ` Avi Kivity
2009-10-15 7:04 ` Mark McLoughlin
2009-10-15 7:33 ` Gleb Natapov
2009-10-15 7:36 ` Mark McLoughlin
2009-10-15 22:46 ` Marcelo Tosatti
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20090526100302.GS3948@redhat.com \
--to=gleb@redhat.com \
--cc=avi@redhat.com \
--cc=kvm@vger.kernel.org \
--cc=markmc@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.