Annotation of qemu/net/queue.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 2003-2008 Fabrice Bellard
        !             3:  * Copyright (c) 2009 Red Hat, Inc.
        !             4:  *
        !             5:  * Permission is hereby granted, free of charge, to any person obtaining a copy
        !             6:  * of this software and associated documentation files (the "Software"), to deal
        !             7:  * in the Software without restriction, including without limitation the rights
        !             8:  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        !             9:  * copies of the Software, and to permit persons to whom the Software is
        !            10:  * furnished to do so, subject to the following conditions:
        !            11:  *
        !            12:  * The above copyright notice and this permission notice shall be included in
        !            13:  * all copies or substantial portions of the Software.
        !            14:  *
        !            15:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        !            16:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        !            17:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
        !            18:  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        !            19:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        !            20:  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
        !            21:  * THE SOFTWARE.
        !            22:  */
        !            23: 
        !            24: #include "net/queue.h"
        !            25: #include "qemu-queue.h"
        !            26: 
        !            27: /* The delivery handler may only return zero if it will call
        !            28:  * qemu_net_queue_flush() when it determines that it is once again able
        !            29:  * to deliver packets. It must also call qemu_net_queue_purge() in its
        !            30:  * cleanup path.
        !            31:  *
        !            32:  * If a sent callback is provided to send(), the caller must handle a
        !            33:  * zero return from the delivery handler by not sending any more packets
        !            34:  * until we have invoked the callback. Only in that case will we queue
        !            35:  * the packet.
        !            36:  *
        !            37:  * If a sent callback isn't provided, we just drop the packet to avoid
        !            38:  * unbounded queueing.
        !            39:  */
        !            40: 
        !            41: struct NetPacket {
        !            42:     QTAILQ_ENTRY(NetPacket) entry;
        !            43:     VLANClientState *sender;
        !            44:     unsigned flags;
        !            45:     int size;
        !            46:     NetPacketSent *sent_cb;
        !            47:     uint8_t data[0];
        !            48: };
        !            49: 
        !            50: struct NetQueue {
        !            51:     NetPacketDeliver *deliver;
        !            52:     NetPacketDeliverIOV *deliver_iov;
        !            53:     void *opaque;
        !            54: 
        !            55:     QTAILQ_HEAD(packets, NetPacket) packets;
        !            56: 
        !            57:     unsigned delivering : 1;
        !            58: };
        !            59: 
        !            60: NetQueue *qemu_new_net_queue(NetPacketDeliver *deliver,
        !            61:                              NetPacketDeliverIOV *deliver_iov,
        !            62:                              void *opaque)
        !            63: {
        !            64:     NetQueue *queue;
        !            65: 
        !            66:     queue = qemu_mallocz(sizeof(NetQueue));
        !            67: 
        !            68:     queue->deliver = deliver;
        !            69:     queue->deliver_iov = deliver_iov;
        !            70:     queue->opaque = opaque;
        !            71: 
        !            72:     QTAILQ_INIT(&queue->packets);
        !            73: 
        !            74:     queue->delivering = 0;
        !            75: 
        !            76:     return queue;
        !            77: }
        !            78: 
        !            79: void qemu_del_net_queue(NetQueue *queue)
        !            80: {
        !            81:     NetPacket *packet, *next;
        !            82: 
        !            83:     QTAILQ_FOREACH_SAFE(packet, &queue->packets, entry, next) {
        !            84:         QTAILQ_REMOVE(&queue->packets, packet, entry);
        !            85:         qemu_free(packet);
        !            86:     }
        !            87: 
        !            88:     qemu_free(queue);
        !            89: }
        !            90: 
        !            91: static ssize_t qemu_net_queue_append(NetQueue *queue,
        !            92:                                      VLANClientState *sender,
        !            93:                                      unsigned flags,
        !            94:                                      const uint8_t *buf,
        !            95:                                      size_t size,
        !            96:                                      NetPacketSent *sent_cb)
        !            97: {
        !            98:     NetPacket *packet;
        !            99: 
        !           100:     packet = qemu_malloc(sizeof(NetPacket) + size);
        !           101:     packet->sender = sender;
        !           102:     packet->flags = flags;
        !           103:     packet->size = size;
        !           104:     packet->sent_cb = sent_cb;
        !           105:     memcpy(packet->data, buf, size);
        !           106: 
        !           107:     QTAILQ_INSERT_TAIL(&queue->packets, packet, entry);
        !           108: 
        !           109:     return size;
        !           110: }
        !           111: 
        !           112: static ssize_t qemu_net_queue_append_iov(NetQueue *queue,
        !           113:                                          VLANClientState *sender,
        !           114:                                          unsigned flags,
        !           115:                                          const struct iovec *iov,
        !           116:                                          int iovcnt,
        !           117:                                          NetPacketSent *sent_cb)
        !           118: {
        !           119:     NetPacket *packet;
        !           120:     size_t max_len = 0;
        !           121:     int i;
        !           122: 
        !           123:     for (i = 0; i < iovcnt; i++) {
        !           124:         max_len += iov[i].iov_len;
        !           125:     }
        !           126: 
        !           127:     packet = qemu_malloc(sizeof(NetPacket) + max_len);
        !           128:     packet->sender = sender;
        !           129:     packet->sent_cb = sent_cb;
        !           130:     packet->flags = flags;
        !           131:     packet->size = 0;
        !           132: 
        !           133:     for (i = 0; i < iovcnt; i++) {
        !           134:         size_t len = iov[i].iov_len;
        !           135: 
        !           136:         memcpy(packet->data + packet->size, iov[i].iov_base, len);
        !           137:         packet->size += len;
        !           138:     }
        !           139: 
        !           140:     QTAILQ_INSERT_TAIL(&queue->packets, packet, entry);
        !           141: 
        !           142:     return packet->size;
        !           143: }
        !           144: 
        !           145: static ssize_t qemu_net_queue_deliver(NetQueue *queue,
        !           146:                                       VLANClientState *sender,
        !           147:                                       unsigned flags,
        !           148:                                       const uint8_t *data,
        !           149:                                       size_t size)
        !           150: {
        !           151:     ssize_t ret = -1;
        !           152: 
        !           153:     queue->delivering = 1;
        !           154:     ret = queue->deliver(sender, flags, data, size, queue->opaque);
        !           155:     queue->delivering = 0;
        !           156: 
        !           157:     return ret;
        !           158: }
        !           159: 
        !           160: static ssize_t qemu_net_queue_deliver_iov(NetQueue *queue,
        !           161:                                           VLANClientState *sender,
        !           162:                                           unsigned flags,
        !           163:                                           const struct iovec *iov,
        !           164:                                           int iovcnt)
        !           165: {
        !           166:     ssize_t ret = -1;
        !           167: 
        !           168:     queue->delivering = 1;
        !           169:     ret = queue->deliver_iov(sender, flags, iov, iovcnt, queue->opaque);
        !           170:     queue->delivering = 0;
        !           171: 
        !           172:     return ret;
        !           173: }
        !           174: 
        !           175: ssize_t qemu_net_queue_send(NetQueue *queue,
        !           176:                             VLANClientState *sender,
        !           177:                             unsigned flags,
        !           178:                             const uint8_t *data,
        !           179:                             size_t size,
        !           180:                             NetPacketSent *sent_cb)
        !           181: {
        !           182:     ssize_t ret;
        !           183: 
        !           184:     if (queue->delivering) {
        !           185:         return qemu_net_queue_append(queue, sender, flags, data, size, NULL);
        !           186:     }
        !           187: 
        !           188:     ret = qemu_net_queue_deliver(queue, sender, flags, data, size);
        !           189:     if (ret == 0) {
        !           190:         qemu_net_queue_append(queue, sender, flags, data, size, sent_cb);
        !           191:         return 0;
        !           192:     }
        !           193: 
        !           194:     qemu_net_queue_flush(queue);
        !           195: 
        !           196:     return ret;
        !           197: }
        !           198: 
        !           199: ssize_t qemu_net_queue_send_iov(NetQueue *queue,
        !           200:                                 VLANClientState *sender,
        !           201:                                 unsigned flags,
        !           202:                                 const struct iovec *iov,
        !           203:                                 int iovcnt,
        !           204:                                 NetPacketSent *sent_cb)
        !           205: {
        !           206:     ssize_t ret;
        !           207: 
        !           208:     if (queue->delivering) {
        !           209:         return qemu_net_queue_append_iov(queue, sender, flags, iov, iovcnt, NULL);
        !           210:     }
        !           211: 
        !           212:     ret = qemu_net_queue_deliver_iov(queue, sender, flags, iov, iovcnt);
        !           213:     if (ret == 0) {
        !           214:         qemu_net_queue_append_iov(queue, sender, flags, iov, iovcnt, sent_cb);
        !           215:         return 0;
        !           216:     }
        !           217: 
        !           218:     qemu_net_queue_flush(queue);
        !           219: 
        !           220:     return ret;
        !           221: }
        !           222: 
        !           223: void qemu_net_queue_purge(NetQueue *queue, VLANClientState *from)
        !           224: {
        !           225:     NetPacket *packet, *next;
        !           226: 
        !           227:     QTAILQ_FOREACH_SAFE(packet, &queue->packets, entry, next) {
        !           228:         if (packet->sender == from) {
        !           229:             QTAILQ_REMOVE(&queue->packets, packet, entry);
        !           230:             qemu_free(packet);
        !           231:         }
        !           232:     }
        !           233: }
        !           234: 
        !           235: void qemu_net_queue_flush(NetQueue *queue)
        !           236: {
        !           237:     while (!QTAILQ_EMPTY(&queue->packets)) {
        !           238:         NetPacket *packet;
        !           239:         int ret;
        !           240: 
        !           241:         packet = QTAILQ_FIRST(&queue->packets);
        !           242:         QTAILQ_REMOVE(&queue->packets, packet, entry);
        !           243: 
        !           244:         ret = qemu_net_queue_deliver(queue,
        !           245:                                      packet->sender,
        !           246:                                      packet->flags,
        !           247:                                      packet->data,
        !           248:                                      packet->size);
        !           249:         if (ret == 0) {
        !           250:             QTAILQ_INSERT_HEAD(&queue->packets, packet, entry);
        !           251:             break;
        !           252:         }
        !           253: 
        !           254:         if (packet->sent_cb) {
        !           255:             packet->sent_cb(packet->sender, ret);
        !           256:         }
        !           257: 
        !           258:         qemu_free(packet);
        !           259:     }
        !           260: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.