Commit 764a4d1deb9304918f3b09b5da6f63fa3a6b4d86
1 parent
a66b11bf
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
Showing
2 changed files
with
41 additions
and
6 deletions
net.c
... | ... | @@ -403,22 +403,46 @@ int qemu_can_send_packet(VLANClientState *vc1) |
403 | 403 | return 0; |
404 | 404 | } |
405 | 405 | |
406 | -void qemu_send_packet(VLANClientState *vc1, const uint8_t *buf, int size) | |
406 | +static void | |
407 | +qemu_deliver_packet(VLANClientState *sender, const uint8_t *buf, int size) | |
407 | 408 | { |
408 | - VLANState *vlan = vc1->vlan; | |
409 | 409 | VLANClientState *vc; |
410 | 410 | |
411 | - if (vc1->link_down) | |
411 | + for (vc = sender->vlan->first_client; vc != NULL; vc = vc->next) { | |
412 | + if (vc != sender && !vc->link_down) { | |
413 | + vc->fd_read(vc->opaque, buf, size); | |
414 | + } | |
415 | + } | |
416 | +} | |
417 | + | |
418 | +void qemu_send_packet(VLANClientState *vc, const uint8_t *buf, int size) | |
419 | +{ | |
420 | + VLANState *vlan = vc->vlan; | |
421 | + VLANPacket *packet; | |
422 | + | |
423 | + if (vc->link_down) | |
412 | 424 | return; |
413 | 425 | |
414 | 426 | #ifdef DEBUG_NET |
415 | 427 | printf("vlan %d send:\n", vlan->id); |
416 | 428 | hex_dump(stdout, buf, size); |
417 | 429 | #endif |
418 | - for(vc = vlan->first_client; vc != NULL; vc = vc->next) { | |
419 | - if (vc != vc1 && !vc->link_down) { | |
420 | - vc->fd_read(vc->opaque, buf, size); | |
430 | + if (vlan->delivering) { | |
431 | + packet = qemu_malloc(sizeof(VLANPacket) + size); | |
432 | + packet->next = vlan->send_queue; | |
433 | + packet->sender = vc; | |
434 | + packet->size = size; | |
435 | + memcpy(packet->data, buf, size); | |
436 | + vlan->send_queue = packet; | |
437 | + } else { | |
438 | + vlan->delivering = 1; | |
439 | + qemu_deliver_packet(vc, buf, size); | |
440 | + while ((packet = vlan->send_queue) != NULL) { | |
441 | + qemu_deliver_packet(packet->sender, packet->data, packet->size); | |
442 | + vlan->send_queue = packet->next; | |
443 | + qemu_free(packet); | |
421 | 444 | } |
445 | + vlan->delivering = 0; | |
422 | 446 | } |
423 | 447 | } |
424 | 448 | ... | ... |
net.h
... | ... | @@ -29,11 +29,22 @@ struct VLANClientState { |
29 | 29 | char info_str[256]; |
30 | 30 | }; |
31 | 31 | |
32 | +typedef struct VLANPacket VLANPacket; | |
33 | + | |
34 | +struct VLANPacket { | |
35 | + struct VLANPacket *next; | |
36 | + VLANClientState *sender; | |
37 | + int size; | |
38 | + uint8_t data[0]; | |
39 | +}; | |
40 | + | |
32 | 41 | struct VLANState { |
33 | 42 | int id; |
34 | 43 | VLANClientState *first_client; |
35 | 44 | struct VLANState *next; |
36 | 45 | unsigned int nb_guest_devs, nb_host_devs; |
46 | + VLANPacket *send_queue; | |
47 | + int delivering; | |
37 | 48 | }; |
38 | 49 | |
39 | 50 | VLANState *qemu_find_vlan(int id); | ... | ... |