]> git.proxmox.com Git - qemu.git/blobdiff - net/queue.c
Open 2.0 development tree
[qemu.git] / net / queue.c
index 1ab5247a327d9918c0227cdc13232e8cd2fe4d06..859d02a1362f5516075b1b06f99a18d637267cd0 100644 (file)
@@ -22,7 +22,8 @@
  */
 
 #include "net/queue.h"
-#include "qemu-queue.h"
+#include "qemu/queue.h"
+#include "net/net.h"
 
 /* The delivery handler may only return zero if it will call
  * qemu_net_queue_flush() when it determines that it is once again able
@@ -40,7 +41,7 @@
 
 struct NetPacket {
     QTAILQ_ENTRY(NetPacket) entry;
-    VLANClientState *sender;
+    NetClientState *sender;
     unsigned flags;
     int size;
     NetPacketSent *sent_cb;
@@ -48,26 +49,24 @@ struct NetPacket {
 };
 
 struct NetQueue {
-    NetPacketDeliver *deliver;
-    NetPacketDeliverIOV *deliver_iov;
     void *opaque;
+    uint32_t nq_maxlen;
+    uint32_t nq_count;
 
     QTAILQ_HEAD(packets, NetPacket) packets;
 
     unsigned delivering : 1;
 };
 
-NetQueue *qemu_new_net_queue(NetPacketDeliver *deliver,
-                             NetPacketDeliverIOV *deliver_iov,
-                             void *opaque)
+NetQueue *qemu_new_net_queue(void *opaque)
 {
     NetQueue *queue;
 
     queue = g_malloc0(sizeof(NetQueue));
 
-    queue->deliver = deliver;
-    queue->deliver_iov = deliver_iov;
     queue->opaque = opaque;
+    queue->nq_maxlen = 10000;
+    queue->nq_count = 0;
 
     QTAILQ_INIT(&queue->packets);
 
@@ -88,15 +87,18 @@ void qemu_del_net_queue(NetQueue *queue)
     g_free(queue);
 }
 
-static ssize_t qemu_net_queue_append(NetQueue *queue,
-                                     VLANClientState *sender,
-                                     unsigned flags,
-                                     const uint8_t *buf,
-                                     size_t size,
-                                     NetPacketSent *sent_cb)
+static void qemu_net_queue_append(NetQueue *queue,
+                                  NetClientState *sender,
+                                  unsigned flags,
+                                  const uint8_t *buf,
+                                  size_t size,
+                                  NetPacketSent *sent_cb)
 {
     NetPacket *packet;
 
+    if (queue->nq_count >= queue->nq_maxlen && !sent_cb) {
+        return; /* drop if queue full and no callback */
+    }
     packet = g_malloc(sizeof(NetPacket) + size);
     packet->sender = sender;
     packet->flags = flags;
@@ -104,22 +106,24 @@ static ssize_t qemu_net_queue_append(NetQueue *queue,
     packet->sent_cb = sent_cb;
     memcpy(packet->data, buf, size);
 
+    queue->nq_count++;
     QTAILQ_INSERT_TAIL(&queue->packets, packet, entry);
-
-    return size;
 }
 
-static ssize_t qemu_net_queue_append_iov(NetQueue *queue,
-                                         VLANClientState *sender,
-                                         unsigned flags,
-                                         const struct iovec *iov,
-                                         int iovcnt,
-                                         NetPacketSent *sent_cb)
+static void qemu_net_queue_append_iov(NetQueue *queue,
+                                      NetClientState *sender,
+                                      unsigned flags,
+                                      const struct iovec *iov,
+                                      int iovcnt,
+                                      NetPacketSent *sent_cb)
 {
     NetPacket *packet;
     size_t max_len = 0;
     int i;
 
+    if (queue->nq_count >= queue->nq_maxlen && !sent_cb) {
+        return; /* drop if queue full and no callback */
+    }
     for (i = 0; i < iovcnt; i++) {
         max_len += iov[i].iov_len;
     }
@@ -137,13 +141,12 @@ static ssize_t qemu_net_queue_append_iov(NetQueue *queue,
         packet->size += len;
     }
 
+    queue->nq_count++;
     QTAILQ_INSERT_TAIL(&queue->packets, packet, entry);
-
-    return packet->size;
 }
 
 static ssize_t qemu_net_queue_deliver(NetQueue *queue,
-                                      VLANClientState *sender,
+                                      NetClientState *sender,
                                       unsigned flags,
                                       const uint8_t *data,
                                       size_t size)
@@ -151,14 +154,14 @@ static ssize_t qemu_net_queue_deliver(NetQueue *queue,
     ssize_t ret = -1;
 
     queue->delivering = 1;
-    ret = queue->deliver(sender, flags, data, size, queue->opaque);
+    ret = qemu_deliver_packet(sender, flags, data, size, queue->opaque);
     queue->delivering = 0;
 
     return ret;
 }
 
 static ssize_t qemu_net_queue_deliver_iov(NetQueue *queue,
-                                          VLANClientState *sender,
+                                          NetClientState *sender,
                                           unsigned flags,
                                           const struct iovec *iov,
                                           int iovcnt)
@@ -166,14 +169,14 @@ static ssize_t qemu_net_queue_deliver_iov(NetQueue *queue,
     ssize_t ret = -1;
 
     queue->delivering = 1;
-    ret = queue->deliver_iov(sender, flags, iov, iovcnt, queue->opaque);
+    ret = qemu_deliver_packet_iov(sender, flags, iov, iovcnt, queue->opaque);
     queue->delivering = 0;
 
     return ret;
 }
 
 ssize_t qemu_net_queue_send(NetQueue *queue,
-                            VLANClientState *sender,
+                            NetClientState *sender,
                             unsigned flags,
                             const uint8_t *data,
                             size_t size,
@@ -181,8 +184,9 @@ ssize_t qemu_net_queue_send(NetQueue *queue,
 {
     ssize_t ret;
 
-    if (queue->delivering) {
-        return qemu_net_queue_append(queue, sender, flags, data, size, NULL);
+    if (queue->delivering || !qemu_can_send_packet(sender)) {
+        qemu_net_queue_append(queue, sender, flags, data, size, sent_cb);
+        return 0;
     }
 
     ret = qemu_net_queue_deliver(queue, sender, flags, data, size);
@@ -197,7 +201,7 @@ ssize_t qemu_net_queue_send(NetQueue *queue,
 }
 
 ssize_t qemu_net_queue_send_iov(NetQueue *queue,
-                                VLANClientState *sender,
+                                NetClientState *sender,
                                 unsigned flags,
                                 const struct iovec *iov,
                                 int iovcnt,
@@ -205,8 +209,9 @@ ssize_t qemu_net_queue_send_iov(NetQueue *queue,
 {
     ssize_t ret;
 
-    if (queue->delivering) {
-        return qemu_net_queue_append_iov(queue, sender, flags, iov, iovcnt, NULL);
+    if (queue->delivering || !qemu_can_send_packet(sender)) {
+        qemu_net_queue_append_iov(queue, sender, flags, iov, iovcnt, sent_cb);
+        return 0;
     }
 
     ret = qemu_net_queue_deliver_iov(queue, sender, flags, iov, iovcnt);
@@ -220,19 +225,20 @@ ssize_t qemu_net_queue_send_iov(NetQueue *queue,
     return ret;
 }
 
-void qemu_net_queue_purge(NetQueue *queue, VLANClientState *from)
+void qemu_net_queue_purge(NetQueue *queue, NetClientState *from)
 {
     NetPacket *packet, *next;
 
     QTAILQ_FOREACH_SAFE(packet, &queue->packets, entry, next) {
         if (packet->sender == from) {
             QTAILQ_REMOVE(&queue->packets, packet, entry);
+            queue->nq_count--;
             g_free(packet);
         }
     }
 }
 
-void qemu_net_queue_flush(NetQueue *queue)
+bool qemu_net_queue_flush(NetQueue *queue)
 {
     while (!QTAILQ_EMPTY(&queue->packets)) {
         NetPacket *packet;
@@ -240,6 +246,7 @@ void qemu_net_queue_flush(NetQueue *queue)
 
         packet = QTAILQ_FIRST(&queue->packets);
         QTAILQ_REMOVE(&queue->packets, packet, entry);
+        queue->nq_count--;
 
         ret = qemu_net_queue_deliver(queue,
                                      packet->sender,
@@ -247,8 +254,9 @@ void qemu_net_queue_flush(NetQueue *queue)
                                      packet->data,
                                      packet->size);
         if (ret == 0) {
+            queue->nq_count++;
             QTAILQ_INSERT_HEAD(&queue->packets, packet, entry);
-            break;
+            return false;
         }
 
         if (packet->sent_cb) {
@@ -257,4 +265,5 @@ void qemu_net_queue_flush(NetQueue *queue)
 
         g_free(packet);
     }
+    return true;
 }