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, ...) | ... | ... |