Commit 764a4d1deb9304918f3b09b5da6f63fa3a6b4d86

Authored by aliguori
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
@@ -403,22 +403,46 @@ int qemu_can_send_packet(VLANClientState *vc1) @@ -403,22 +403,46 @@ int qemu_can_send_packet(VLANClientState *vc1)
403 return 0; 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 VLANClientState *vc; 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 return; 424 return;
413 425
414 #ifdef DEBUG_NET 426 #ifdef DEBUG_NET
415 printf("vlan %d send:\n", vlan->id); 427 printf("vlan %d send:\n", vlan->id);
416 hex_dump(stdout, buf, size); 428 hex_dump(stdout, buf, size);
417 #endif 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
@@ -29,11 +29,22 @@ struct VLANClientState { @@ -29,11 +29,22 @@ struct VLANClientState {
29 char info_str[256]; 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 struct VLANState { 41 struct VLANState {
33 int id; 42 int id;
34 VLANClientState *first_client; 43 VLANClientState *first_client;
35 struct VLANState *next; 44 struct VLANState *next;
36 unsigned int nb_guest_devs, nb_host_devs; 45 unsigned int nb_guest_devs, nb_host_devs;
  46 + VLANPacket *send_queue;
  47 + int delivering;
37 }; 48 };
38 49
39 VLANState *qemu_find_vlan(int id); 50 VLANState *qemu_find_vlan(int id);