aboutsummaryrefslogtreecommitdiff
path: root/net.c
diff options
context:
space:
mode:
Diffstat (limited to 'net.c')
-rw-r--r--net.c36
1 files changed, 30 insertions, 6 deletions
diff --git a/net.c b/net.c
index ac89f876ba..531833ed8e 100644
--- a/net.c
+++ b/net.c
@@ -403,22 +403,46 @@ int qemu_can_send_packet(VLANClientState *vc1)
return 0;
}
-void qemu_send_packet(VLANClientState *vc1, const uint8_t *buf, int size)
+static void
+qemu_deliver_packet(VLANClientState *sender, const uint8_t *buf, int size)
{
- VLANState *vlan = vc1->vlan;
VLANClientState *vc;
- if (vc1->link_down)
+ for (vc = sender->vlan->first_client; vc != NULL; vc = vc->next) {
+ if (vc != sender && !vc->link_down) {
+ vc->fd_read(vc->opaque, buf, size);
+ }
+ }
+}
+
+void qemu_send_packet(VLANClientState *vc, const uint8_t *buf, int size)
+{
+ VLANState *vlan = vc->vlan;
+ VLANPacket *packet;
+
+ if (vc->link_down)
return;
#ifdef DEBUG_NET
printf("vlan %d send:\n", vlan->id);
hex_dump(stdout, buf, size);
#endif
- for(vc = vlan->first_client; vc != NULL; vc = vc->next) {
- if (vc != vc1 && !vc->link_down) {
- vc->fd_read(vc->opaque, buf, size);
+ if (vlan->delivering) {
+ packet = qemu_malloc(sizeof(VLANPacket) + size);
+ packet->next = vlan->send_queue;
+ packet->sender = vc;
+ packet->size = size;
+ memcpy(packet->data, buf, size);
+ vlan->send_queue = packet;
+ } else {
+ vlan->delivering = 1;
+ qemu_deliver_packet(vc, buf, size);
+ while ((packet = vlan->send_queue) != NULL) {
+ qemu_deliver_packet(packet->sender, packet->data, packet->size);
+ vlan->send_queue = packet->next;
+ qemu_free(packet);
}
+ vlan->delivering = 0;
}
}