Revision e94667b9
b/net.c | ||
---|---|---|
415 | 415 |
VLANClientState *vc; |
416 | 416 |
int ret = -1; |
417 | 417 |
|
418 |
sender->vlan->delivering = 1; |
|
419 |
|
|
418 | 420 |
for (vc = sender->vlan->first_client; vc != NULL; vc = vc->next) { |
419 | 421 |
ssize_t len; |
420 | 422 |
|
... | ... | |
432 | 434 |
ret = (ret >= 0) ? ret : len; |
433 | 435 |
} |
434 | 436 |
|
437 |
sender->vlan->delivering = 0; |
|
438 |
|
|
435 | 439 |
return ret; |
436 | 440 |
} |
437 | 441 |
|
442 |
static void qemu_flush_queued_packets(VLANClientState *vc) |
|
443 |
{ |
|
444 |
VLANPacket *packet; |
|
445 |
|
|
446 |
while ((packet = vc->vlan->send_queue) != NULL) { |
|
447 |
vc->vlan->send_queue = packet->next; |
|
448 |
qemu_deliver_packet(packet->sender, packet->data, packet->size); |
|
449 |
qemu_free(packet); |
|
450 |
} |
|
451 |
} |
|
452 |
|
|
453 |
static void |
|
454 |
qemu_enqueue_packet(VLANClientState *sender, const uint8_t *buf, int size) |
|
455 |
{ |
|
456 |
VLANPacket *packet; |
|
457 |
|
|
458 |
packet = qemu_malloc(sizeof(VLANPacket) + size); |
|
459 |
packet->next = sender->vlan->send_queue; |
|
460 |
packet->sender = sender; |
|
461 |
packet->size = size; |
|
462 |
memcpy(packet->data, buf, size); |
|
463 |
sender->vlan->send_queue = packet; |
|
464 |
} |
|
465 |
|
|
438 | 466 |
void qemu_send_packet(VLANClientState *vc, const uint8_t *buf, int size) |
439 | 467 |
{ |
440 | 468 |
VLANState *vlan = vc->vlan; |
441 |
VLANPacket *packet; |
|
442 | 469 |
|
443 | 470 |
if (vc->link_down) |
444 | 471 |
return; |
... | ... | |
448 | 475 |
hex_dump(stdout, buf, size); |
449 | 476 |
#endif |
450 | 477 |
if (vlan->delivering) { |
451 |
packet = qemu_malloc(sizeof(VLANPacket) + size); |
|
452 |
packet->next = vlan->send_queue; |
|
453 |
packet->sender = vc; |
|
454 |
packet->size = size; |
|
455 |
memcpy(packet->data, buf, size); |
|
456 |
vlan->send_queue = packet; |
|
457 |
} else { |
|
458 |
vlan->delivering = 1; |
|
459 |
qemu_deliver_packet(vc, buf, size); |
|
460 |
while ((packet = vlan->send_queue) != NULL) { |
|
461 |
vlan->send_queue = packet->next; |
|
462 |
qemu_deliver_packet(packet->sender, packet->data, packet->size); |
|
463 |
qemu_free(packet); |
|
464 |
} |
|
465 |
vlan->delivering = 0; |
|
478 |
qemu_enqueue_packet(vc, buf, size); |
|
479 |
return; |
|
466 | 480 |
} |
481 |
|
|
482 |
qemu_deliver_packet(vc, buf, size); |
|
483 |
qemu_flush_queued_packets(vc); |
|
467 | 484 |
} |
468 | 485 |
|
469 | 486 |
static ssize_t vc_sendv_compat(VLANClientState *vc, const struct iovec *iov, |
... | ... | |
496 | 513 |
return offset; |
497 | 514 |
} |
498 | 515 |
|
499 |
ssize_t qemu_sendv_packet(VLANClientState *sender, const struct iovec *iov,
|
|
500 |
int iovcnt) |
|
516 |
static int qemu_deliver_packet_iov(VLANClientState *sender,
|
|
517 |
const struct iovec *iov, int iovcnt)
|
|
501 | 518 |
{ |
502 |
VLANState *vlan = sender->vlan; |
|
503 | 519 |
VLANClientState *vc; |
520 |
int ret = -1; |
|
521 |
|
|
522 |
sender->vlan->delivering = 1; |
|
523 |
|
|
524 |
for (vc = sender->vlan->first_client; vc != NULL; vc = vc->next) { |
|
525 |
ssize_t len; |
|
526 |
|
|
527 |
if (vc == sender) { |
|
528 |
continue; |
|
529 |
} |
|
530 |
|
|
531 |
if (vc->link_down) { |
|
532 |
ret = calc_iov_length(iov, iovcnt); |
|
533 |
continue; |
|
534 |
} |
|
535 |
|
|
536 |
if (vc->receive_iov) { |
|
537 |
len = vc->receive_iov(vc, iov, iovcnt); |
|
538 |
} else { |
|
539 |
len = vc_sendv_compat(vc, iov, iovcnt); |
|
540 |
} |
|
541 |
|
|
542 |
ret = (ret >= 0) ? ret : len; |
|
543 |
} |
|
544 |
|
|
545 |
sender->vlan->delivering = 0; |
|
546 |
|
|
547 |
return ret; |
|
548 |
} |
|
549 |
|
|
550 |
static ssize_t qemu_enqueue_packet_iov(VLANClientState *sender, |
|
551 |
const struct iovec *iov, int iovcnt) |
|
552 |
{ |
|
504 | 553 |
VLANPacket *packet; |
505 |
ssize_t max_len = 0;
|
|
554 |
size_t max_len = 0; |
|
506 | 555 |
int i; |
507 | 556 |
|
508 |
if (sender->link_down) |
|
509 |
return calc_iov_length(iov, iovcnt); |
|
557 |
max_len = calc_iov_length(iov, iovcnt); |
|
510 | 558 |
|
511 |
if (vlan->delivering) { |
|
512 |
max_len = calc_iov_length(iov, iovcnt); |
|
559 |
packet = qemu_malloc(sizeof(VLANPacket) + max_len); |
|
560 |
packet->next = sender->vlan->send_queue; |
|
561 |
packet->sender = sender; |
|
562 |
packet->size = 0; |
|
513 | 563 |
|
514 |
packet = qemu_malloc(sizeof(VLANPacket) + max_len); |
|
515 |
packet->next = vlan->send_queue; |
|
516 |
packet->sender = sender; |
|
517 |
packet->size = 0; |
|
518 |
for (i = 0; i < iovcnt; i++) { |
|
519 |
size_t len = iov[i].iov_len; |
|
564 |
for (i = 0; i < iovcnt; i++) { |
|
565 |
size_t len = iov[i].iov_len; |
|
520 | 566 |
|
521 |
memcpy(packet->data + packet->size, iov[i].iov_base, len); |
|
522 |
packet->size += len; |
|
523 |
} |
|
524 |
vlan->send_queue = packet; |
|
525 |
} else { |
|
526 |
vlan->delivering = 1; |
|
567 |
memcpy(packet->data + packet->size, iov[i].iov_base, len); |
|
568 |
packet->size += len; |
|
569 |
} |
|
527 | 570 |
|
528 |
for (vc = vlan->first_client; vc != NULL; vc = vc->next) { |
|
529 |
ssize_t len = 0; |
|
571 |
sender->vlan->send_queue = packet; |
|
530 | 572 |
|
531 |
if (vc == sender) { |
|
532 |
continue; |
|
533 |
} |
|
534 |
if (vc->link_down) { |
|
535 |
len = calc_iov_length(iov, iovcnt); |
|
536 |
} else if (vc->receive_iov) { |
|
537 |
len = vc->receive_iov(vc, iov, iovcnt); |
|
538 |
} else if (vc->receive) { |
|
539 |
len = vc_sendv_compat(vc, iov, iovcnt); |
|
540 |
} |
|
541 |
max_len = MAX(max_len, len); |
|
542 |
} |
|
573 |
return packet->size; |
|
574 |
} |
|
543 | 575 |
|
544 |
while ((packet = vlan->send_queue) != NULL) { |
|
545 |
vlan->send_queue = packet->next; |
|
546 |
qemu_deliver_packet(packet->sender, packet->data, packet->size); |
|
547 |
qemu_free(packet); |
|
548 |
} |
|
549 |
vlan->delivering = 0; |
|
576 |
ssize_t qemu_sendv_packet(VLANClientState *sender, const struct iovec *iov, |
|
577 |
int iovcnt) |
|
578 |
{ |
|
579 |
int ret; |
|
580 |
|
|
581 |
if (sender->link_down) { |
|
582 |
return calc_iov_length(iov, iovcnt); |
|
583 |
} |
|
584 |
|
|
585 |
if (sender->vlan->delivering) { |
|
586 |
return qemu_enqueue_packet_iov(sender, iov, iovcnt); |
|
550 | 587 |
} |
551 | 588 |
|
552 |
return max_len; |
|
589 |
ret = qemu_deliver_packet_iov(sender, iov, iovcnt); |
|
590 |
|
|
591 |
qemu_flush_queued_packets(sender); |
|
592 |
|
|
593 |
return ret; |
|
553 | 594 |
} |
554 | 595 |
|
555 | 596 |
static void config_error(Monitor *mon, const char *fmt, ...) |
Also available in: Unified diff