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 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  
... ...
... ... @@ -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);
... ...