summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--net/slirp.c13
-rw-r--r--slirp/if.c69
-rw-r--r--slirp/slirp.h1
3 files changed, 39 insertions, 44 deletions
diff --git a/net/slirp.c b/net/slirp.c
index 01ed21c006..318a26e892 100644
--- a/net/slirp.c
+++ b/net/slirp.c
@@ -496,9 +496,11 @@ static int slirp_hostfwd(SlirpState *s, const char *redir_str,
     char buf[256];
     int is_udp;
     char *end;
+    const char *fail_reason = "Unknown reason";
 
     p = redir_str;
     if (!p || get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
+        fail_reason = "No : separators";
         goto fail_syntax;
     }
     if (!strcmp(buf, "tcp") || buf[0] == '\0') {
@@ -506,35 +508,43 @@ static int slirp_hostfwd(SlirpState *s, const char *redir_str,
     } else if (!strcmp(buf, "udp")) {
         is_udp = 1;
     } else {
+        fail_reason = "Bad protocol name";
         goto fail_syntax;
     }
 
     if (!legacy_format) {
         if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
+            fail_reason = "Missing : separator";
             goto fail_syntax;
         }
         if (buf[0] != '\0' && !inet_aton(buf, &host_addr)) {
+            fail_reason = "Bad host address";
             goto fail_syntax;
         }
     }
 
     if (get_str_sep(buf, sizeof(buf), &p, legacy_format ? ':' : '-') < 0) {
+        fail_reason = "Bad host port separator";
         goto fail_syntax;
     }
     host_port = strtol(buf, &end, 0);
     if (*end != '\0' || host_port < 0 || host_port > 65535) {
+        fail_reason = "Bad host port";
         goto fail_syntax;
     }
 
     if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
+        fail_reason = "Missing guest address";
         goto fail_syntax;
     }
     if (buf[0] != '\0' && !inet_aton(buf, &guest_addr)) {
+        fail_reason = "Bad guest address";
         goto fail_syntax;
     }
 
     guest_port = strtol(p, &end, 0);
     if (*end != '\0' || guest_port < 1 || guest_port > 65535) {
+        fail_reason = "Bad guest port";
         goto fail_syntax;
     }
 
@@ -547,7 +557,8 @@ static int slirp_hostfwd(SlirpState *s, const char *redir_str,
     return 0;
 
  fail_syntax:
-    error_setg(errp, "Invalid host forwarding rule '%s'", redir_str);
+    error_setg(errp, "Invalid host forwarding rule '%s' (%s)", redir_str,
+               fail_reason);
     return -1;
 }
 
diff --git a/slirp/if.c b/slirp/if.c
index 51ae0d0e9a..590753c658 100644
--- a/slirp/if.c
+++ b/slirp/if.c
@@ -30,7 +30,6 @@ if_init(Slirp *slirp)
 {
     slirp->if_fastq.qh_link = slirp->if_fastq.qh_rlink = &slirp->if_fastq;
     slirp->if_batchq.qh_link = slirp->if_batchq.qh_rlink = &slirp->if_batchq;
-    slirp->next_m = (struct mbuf *) &slirp->if_batchq;
 }
 
 /*
@@ -74,14 +73,16 @@ if_output(struct socket *so, struct mbuf *ifm)
 	 * We mustn't put this packet back on the fastq (or we'll send it out of order)
 	 * XXX add cache here?
 	 */
-	for (ifq = (struct mbuf *) slirp->if_batchq.qh_rlink;
-	     (struct quehead *) ifq != &slirp->if_batchq;
-	     ifq = ifq->ifq_prev) {
-		if (so == ifq->ifq_so) {
-			/* A match! */
-			ifm->ifq_so = so;
-			ifs_insque(ifm, ifq->ifs_prev);
-			goto diddit;
+	if (so) {
+		for (ifq = (struct mbuf *) slirp->if_batchq.qh_rlink;
+		     (struct quehead *) ifq != &slirp->if_batchq;
+		     ifq = ifq->ifq_prev) {
+			if (so == ifq->ifq_so) {
+				/* A match! */
+				ifm->ifq_so = so;
+				ifs_insque(ifm, ifq->ifs_prev);
+				goto diddit;
+			}
 		}
 	}
 
@@ -100,10 +101,6 @@ if_output(struct socket *so, struct mbuf *ifm)
 		}
         } else {
 		ifq = (struct mbuf *) slirp->if_batchq.qh_rlink;
-                /* Set next_m if the queue was empty so far */
-                if ((struct quehead *) slirp->next_m == &slirp->if_batchq) {
-                    slirp->next_m = ifm;
-                }
         }
 
 	/* Create a new doubly linked list for this session */
@@ -143,21 +140,18 @@ diddit:
 }
 
 /*
- * Send a packet
- * We choose a packet based on its position in the output queues;
+ * Send one packet from each session.
  * If there are packets on the fastq, they are sent FIFO, before
- * everything else.  Otherwise we choose the first packet from the
- * batchq and send it.  the next packet chosen will be from the session
- * after this one, then the session after that one, and so on..  So,
- * for example, if there are 3 ftp session's fighting for bandwidth,
+ * everything else.  Then we choose the first packet from each
+ * batchq session (socket) and send it.
+ * For example, if there are 3 ftp sessions fighting for bandwidth,
  * one packet will be sent from the first session, then one packet
- * from the second session, then one packet from the third, then back
- * to the first, etc. etc.
+ * from the second session, then one packet from the third.
  */
 void if_start(Slirp *slirp)
 {
     uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
-    bool from_batchq, next_from_batchq;
+    bool from_batchq = false;
     struct mbuf *ifm, *ifm_next, *ifqt;
 
     DEBUG_CALL("if_start");
@@ -167,26 +161,29 @@ void if_start(Slirp *slirp)
     }
     slirp->if_start_busy = true;
 
+    struct mbuf *batch_head = NULL;
+    if (slirp->if_batchq.qh_link != &slirp->if_batchq) {
+        batch_head = (struct mbuf *) slirp->if_batchq.qh_link;
+    }
+
     if (slirp->if_fastq.qh_link != &slirp->if_fastq) {
         ifm_next = (struct mbuf *) slirp->if_fastq.qh_link;
-        next_from_batchq = false;
-    } else if ((struct quehead *) slirp->next_m != &slirp->if_batchq) {
-        /* Nothing on fastq, pick up from batchq via next_m */
-        ifm_next = slirp->next_m;
-        next_from_batchq = true;
+    } else if (batch_head) {
+        /* Nothing on fastq, pick up from batchq */
+        ifm_next = batch_head;
+        from_batchq = true;
     } else {
         ifm_next = NULL;
     }
 
     while (ifm_next) {
         ifm = ifm_next;
-        from_batchq = next_from_batchq;
 
         ifm_next = ifm->ifq_next;
         if ((struct quehead *) ifm_next == &slirp->if_fastq) {
             /* No more packets in fastq, switch to batchq */
-            ifm_next = slirp->next_m;
-            next_from_batchq = true;
+            ifm_next = batch_head;
+            from_batchq = true;
         }
         if ((struct quehead *) ifm_next == &slirp->if_batchq) {
             /* end of batchq */
@@ -199,11 +196,6 @@ void if_start(Slirp *slirp)
             continue;
         }
 
-        if (ifm == slirp->next_m) {
-            /* Set which packet to send on next iteration */
-            slirp->next_m = ifm->ifq_next;
-        }
-
         /* Remove it from the queue */
         ifqt = ifm->ifq_prev;
         remque(ifm);
@@ -214,15 +206,8 @@ void if_start(Slirp *slirp)
 
             insque(next, ifqt);
             ifs_remque(ifm);
-
             if (!from_batchq) {
-                /* Next packet in fastq is from the same session */
                 ifm_next = next;
-                next_from_batchq = false;
-            } else if ((struct quehead *) slirp->next_m == &slirp->if_batchq) {
-                /* Set next_m and ifm_next if the session packet is now the
-                 * only one on batchq */
-                slirp->next_m = ifm_next = next;
             }
         }
 
diff --git a/slirp/slirp.h b/slirp/slirp.h
index 5af4f482b5..898ec9516d 100644
--- a/slirp/slirp.h
+++ b/slirp/slirp.h
@@ -183,7 +183,6 @@ struct Slirp {
     /* if states */
     struct quehead if_fastq;   /* fast queue (for interactive data) */
     struct quehead if_batchq;  /* queue for non-interactive data */
-    struct mbuf *next_m;    /* pointer to next mbuf to output */
     bool if_start_busy;     /* avoid if_start recursion */
 
     /* ip states */