diff options
author | aliguori <aliguori@c046a42c-6fe2-441c-8c8c-71466251a162> | 2009-04-21 19:56:41 +0000 |
---|---|---|
committer | aliguori <aliguori@c046a42c-6fe2-441c-8c8c-71466251a162> | 2009-04-21 19:56:41 +0000 |
commit | 764a4d1deb9304918f3b09b5da6f63fa3a6b4d86 (patch) | |
tree | 49ae329805a4441b2b13dbdc1a1319137fd302f7 | |
parent | a66b11bfcd1b04c1c8420c6afc4b63f32ef27127 (diff) |
net: Untangle nested qemu_send_packet (Jan Kiszka)
Queue packets that are send during an ongoing packet delivery. This
ensures that packets will always arrive in their logical order at each
client of a VLAN. Currently, slirp generates such immediate relies, and
e.g. packet-sniffing clients on the same VLAN may get confused.
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@7203 c046a42c-6fe2-441c-8c8c-71466251a162
-rw-r--r-- | net.c | 36 | ||||
-rw-r--r-- | net.h | 11 |
2 files changed, 41 insertions, 6 deletions
@@ -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; } } @@ -29,11 +29,22 @@ struct VLANClientState { char info_str[256]; }; +typedef struct VLANPacket VLANPacket; + +struct VLANPacket { + struct VLANPacket *next; + VLANClientState *sender; + int size; + uint8_t data[0]; +}; + struct VLANState { int id; VLANClientState *first_client; struct VLANState *next; unsigned int nb_guest_devs, nb_host_devs; + VLANPacket *send_queue; + int delivering; }; VLANState *qemu_find_vlan(int id); |