mirror of
https://gitlab.com/qemu-project/qemu
synced 2024-10-15 15:32:51 +00:00
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
This commit is contained in:
parent
a66b11bfcd
commit
764a4d1deb
36
net.c
36
net.c
|
@ -403,22 +403,46 @@ int qemu_can_send_packet(VLANClientState *vc1)
|
||||||
return 0;
|
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;
|
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;
|
return;
|
||||||
|
|
||||||
#ifdef DEBUG_NET
|
#ifdef DEBUG_NET
|
||||||
printf("vlan %d send:\n", vlan->id);
|
printf("vlan %d send:\n", vlan->id);
|
||||||
hex_dump(stdout, buf, size);
|
hex_dump(stdout, buf, size);
|
||||||
#endif
|
#endif
|
||||||
for(vc = vlan->first_client; vc != NULL; vc = vc->next) {
|
if (vlan->delivering) {
|
||||||
if (vc != vc1 && !vc->link_down) {
|
packet = qemu_malloc(sizeof(VLANPacket) + size);
|
||||||
vc->fd_read(vc->opaque, buf, 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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
11
net.h
11
net.h
|
@ -29,11 +29,22 @@ struct VLANClientState {
|
||||||
char info_str[256];
|
char info_str[256];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct VLANPacket VLANPacket;
|
||||||
|
|
||||||
|
struct VLANPacket {
|
||||||
|
struct VLANPacket *next;
|
||||||
|
VLANClientState *sender;
|
||||||
|
int size;
|
||||||
|
uint8_t data[0];
|
||||||
|
};
|
||||||
|
|
||||||
struct VLANState {
|
struct VLANState {
|
||||||
int id;
|
int id;
|
||||||
VLANClientState *first_client;
|
VLANClientState *first_client;
|
||||||
struct VLANState *next;
|
struct VLANState *next;
|
||||||
unsigned int nb_guest_devs, nb_host_devs;
|
unsigned int nb_guest_devs, nb_host_devs;
|
||||||
|
VLANPacket *send_queue;
|
||||||
|
int delivering;
|
||||||
};
|
};
|
||||||
|
|
||||||
VLANState *qemu_find_vlan(int id);
|
VLANState *qemu_find_vlan(int id);
|
||||||
|
|
Loading…
Reference in a new issue