Commit e94667b91ccfdb70164ae320b1c4ded6b5b8a3ec
1 parent
3e021d40
net: split out packet queueing and flushing into separate functions
We'll be doing more packet queueing in later commits. Signed-off-by: Mark McLoughlin <markmc@redhat.com>
Showing
1 changed file
with
98 additions
and
57 deletions
net.c
| ... | ... | @@ -415,6 +415,8 @@ qemu_deliver_packet(VLANClientState *sender, const uint8_t *buf, int size) |
| 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,13 +434,38 @@ qemu_deliver_packet(VLANClientState *sender, const uint8_t *buf, int size) |
| 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,22 +475,12 @@ void qemu_send_packet(VLANClientState *vc, const uint8_t *buf, int size) |
| 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,60 +513,84 @@ static ssize_t calc_iov_length(const struct iovec *iov, int iovcnt) |
| 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, ...) | ... | ... |