freebsd-410_Backfill.patch 5.06 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11
diff -u -r /share/freebsd/4.10-release/src/sys/netinet/ip_dummynet.c /tmp/ip_dummynet.c
--- /share/freebsd/4.10-release/src/sys/netinet/ip_dummynet.c	Tue Dec 30 05:28:09 2003
+++ /tmp/ip_dummynet.c	Wed Dec 17 16:34:51 2008
@@ -513,6 +513,18 @@
 
     pkt->output_time = curr_time + p->delay ;
 
+#ifdef DN_BACKFILL
+    /*
+     * Backfill dummy packet.  The packet has served its purpose and we
+     * don't want to actually put it out on the wire, so drop it now.
12
+     */
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
+    if (pkt->isDummy) {
+	m_freem(pkt->dn_m);
+        free(pkt, M_DUMMYNET);
+        return;
+    }
+#endif
+
     if (p->head == NULL)
 	p->head = pkt;
     else
@@ -746,6 +758,93 @@
 		transmit_event(p);
 	}
     }
+
+#ifdef DN_BACKFILL
+    /* sweep pipes and insert dummy packets into BackFill 'enabled' ones */
+    for (pe = all_pipes; pe ; pe = pe->next ) {
+	if (pe->startBackFill) {
+	    int ticksElapsed;
+	    struct dn_flow_queue *pipeQueue = pe->fs.rq[0];
+	    int numPackets = 0;
+
+	    if (pe->lastFillTick != 0)
+		ticksElapsed = curr_time - pe->lastFillTick;
+	    else
+		ticksElapsed = 1;
+
+	    pe->lastFillTick = curr_time;
+	    pe->outStandingBackFillBits += ((pe->backfill*ticksElapsed) / hz);
+
+	    /* Determine the number of full size packets to be sent. */
+	    numPackets = pe->outStandingBackFillBits / 12000;
+	    pe->outStandingBackFillBits %= 12000;
+
+	    while (numPackets > 0) {
+		struct mbuf *backFillBuf = NULL;
+		struct dn_pkt *backFillPkt = NULL;
+		int packetLen = 1500;
+
+		/*
+		 * We filled up the entire queue with dummy packets.
+		 * Assume that the rest of the backfill packets have
+		 * been dropped.
+		 */
+		if (pe->fs.flags_fs & DN_QSIZE_IS_BYTES) {
+		    if (pipeQueue->len_bytes > pipeQueue->fs->qsize)
+			break;
+		} else {
+		    if (pipeQueue->len > pipeQueue->fs->qsize)
+			break;
+		}
+
+		backFillBuf = m_get(M_DONTWAIT, MT_DATA);
+
+		backFillPkt = (struct dn_pkt *)malloc(sizeof(*backFillPkt),
+				M_DUMMYNET, M_NOWAIT|M_ZERO);
+
+		/*if (backFillPkt != NULL && backFillBuf != NULL)*/
+		{
+		    backFillPkt->hdr.mh_type = MT_TAG;
+		    backFillPkt->hdr.mh_flags = PACKET_TAG_DUMMYNET;
+		    DN_NEXT(backFillPkt) = NULL;
+		    backFillPkt->dn_m = backFillBuf;
+		    backFillPkt->isDummy = 1;
+
+		    backFillBuf->m_nextpkt = NULL;
+		    backFillBuf->m_pkthdr.len = packetLen;
+		}
+
+		if (pipeQueue->head == NULL)
+		    pipeQueue->head = backFillPkt;
+		else
+		    DN_NEXT(pipeQueue->tail) = backFillPkt;
+
+		pipeQueue->tail = backFillPkt;
+		pipeQueue->len++;
+		pipeQueue->len_bytes += packetLen;
+
+		/*
+		 * If we reach this point the flow was previously idle,
+		 * so we need to schedule it.
+		 */
+		if (pipeQueue->head == backFillPkt) {
+		    /* Fixed-rate queue: just insert into the ready_heap. */
+		    dn_key t = 0 ;
+		    if (pe->bandwidth)
+			t = SET_TICKS(backFillPkt, pipeQueue, pe);
+		    pipeQueue->sched_time = curr_time ;
+		    if (t == 0) /* must process it now */
+			ready_event(pipeQueue);
+		    else
+			heap_insert(&ready_heap, curr_time + t, pipeQueue);
+		}
+
+		numPackets--;
+	    }
+	}
+    }
+#endif
+
     /* sweep pipes trying to expire idle flow_queues */
     for (pe = all_pipes; pe ; pe = pe->next )
 	if (pe->idle_heap.elements > 0 &&
@@ -1132,6 +1231,17 @@
     q = find_queue(fs, &(fwa->f_id));
     if ( q == NULL )
 	goto dropit ;		/* cannot allocate queue		*/
+
+#ifdef DN_BACKFILL
+    /*
+     * If Backfill has been enabled for this pipe, we now
+     * have a queue to fill up. Start putting dummy packets
+     * into this queue from the next tick.
+     */
+    if (fs->pipe->enableBackFill)
+	fs->pipe->startBackFill = 1;
+#endif
+
     /*
      * update statistics, then check reasons to drop pkt
      */
@@ -1578,6 +1688,15 @@
 	x->delay = p->delay ;
 	set_fs_parms(&(x->fs), pfs);
 
+#ifdef DN_BACKFILL
+	x->enableBackFill = 0;
+	x->startBackFill = 0;
+	x->backfill = p->backfill;
+	if (x->backfill > 0) {
+	    x->enableBackFill = 1;
+	    /*x->lastFillTick = 0; */
+	}
+#endif
 
 	if ( x->fs.rq == NULL ) { /* a new pipe */
 	    r = alloc_hash(&(x->fs), pfs) ;
diff -u -r /share/freebsd/4.10-release/src/sys/netinet/ip_dummynet.h /tmp/ip_dummynet.h
--- /share/freebsd/4.10-release/src/sys/netinet/ip_dummynet.h	Tue May 13 03:31:06 2003
+++ /tmp/ip_dummynet.h	Wed Dec 17 16:35:35 2008
@@ -141,6 +141,9 @@
     struct sockaddr_in *dn_dst ;
     struct route ro;		/* route, for ip_output. MUST COPY	*/
     int flags ;			/* flags, for ip_output (IPv6 ?)	*/
+    /* #ifdef DN_BACKFILL */
+    int isDummy ;		/* this is a dummy packet               */
+    /* #endif */
 };
 
 /*
@@ -350,8 +353,19 @@
     int ready ; /* set if ifp != NULL and we got a signal from it */
 
     struct dn_flow_set fs ; /* used with fixed-rate flows */
+
+    /* #ifdef DN_BACKFILL */
+    long backfill;
+    int enableBackFill;
+    int startBackFill;
+    int outStandingBackFillBits;
+    dn_key lastFillTick;
+    /* #endif */
 };
 
+/* Argh, why are there internal fields in the user interface struct!? */
+#define DN_HAVE_BACKFILL	1
+ 
 #ifdef _KERNEL
 typedef	int ip_dn_ctl_t(struct sockopt *); /* raw_ip.c */
 typedef	void ip_dn_ruledel_t(void *); /* ip_fw.c */