From owner-svn-src-all@FreeBSD.ORG Tue Nov 3 08:41:15 2009 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 22CFF1065670; Tue, 3 Nov 2009 08:41:15 +0000 (UTC) (envelope-from oleg@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id ECCFE8FC1E; Tue, 3 Nov 2009 08:41:14 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id nA38fEw3084565; Tue, 3 Nov 2009 08:41:14 GMT (envelope-from oleg@svn.freebsd.org) Received: (from oleg@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id nA38fEg3084563; Tue, 3 Nov 2009 08:41:14 GMT (envelope-from oleg@svn.freebsd.org) Message-Id: <200911030841.nA38fEg3084563@svn.freebsd.org> From: Oleg Bulyzhin Date: Tue, 3 Nov 2009 08:41:14 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r198845 - head/sys/netinet/ipfw X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 03 Nov 2009 08:41:15 -0000 Author: oleg Date: Tue Nov 3 08:41:14 2009 New Revision: 198845 URL: http://svn.freebsd.org/changeset/base/198845 Log: Fix two issues that can lead to exceeding configured pipe bandwidth: - do not expire queues which are not ready to be expired. - properly calculate available burst size. MFC after: 3 days Modified: head/sys/netinet/ipfw/ip_dummynet.c Modified: head/sys/netinet/ipfw/ip_dummynet.c ============================================================================== --- head/sys/netinet/ipfw/ip_dummynet.c Tue Nov 3 07:29:58 2009 (r198844) +++ head/sys/netinet/ipfw/ip_dummynet.c Tue Nov 3 08:41:14 2009 (r198845) @@ -244,6 +244,17 @@ void dummynet_drain(void); static int dummynet_io(struct mbuf **, int , struct ip_fw_args *); /* + * Flow queue is idle if: + * 1) it's empty for at least 1 tick + * 2) it has invalid timestamp (WF2Q case) + * 3) parent pipe has no 'exhausted' burst. + */ +#define QUEUE_IS_IDLE(q) ((q)->head == NULL && (q)->S == (q)->F + 1 && \ + curr_time > (q)->idle_time + 1 && \ + ((q)->numbytes + (curr_time - (q)->idle_time - 1) * \ + (q)->fs->pipe->bandwidth >= q->fs->pipe->burst)) + +/* * Heap management functions. * * In the heap, first node is element 0. Children of i are 2i+1 and 2i+2. @@ -1004,7 +1015,7 @@ expire_queues(struct dn_flow_set *fs) fs->last_expired = time_uptime ; for (i = 0 ; i <= fs->rq_size ; i++) /* last one is overflow */ for (prev=NULL, q = fs->rq[i] ; q != NULL ; ) - if (q->head != NULL || q->S != q->F+1) { + if (!QUEUE_IS_IDLE(q)) { prev = q ; q = q->next ; } else { /* entry is idle, expire it */ @@ -1134,7 +1145,7 @@ find_queue(struct dn_flow_set *fs, struc break ; /* found */ /* No match. Check if we can expire the entry */ - if (pipe_expire && q->head == NULL && q->S == q->F+1 ) { + if (pipe_expire && QUEUE_IS_IDLE(q)) { /* entry is idle and not in any heap, expire it */ struct dn_flow_queue *old_q = q ; @@ -1408,7 +1419,7 @@ dummynet_io(struct mbuf **m0, int dir, s if (q->idle_time < curr_time) { /* Calculate available burst size. */ q->numbytes += - (curr_time - q->idle_time) * pipe->bandwidth; + (curr_time - q->idle_time - 1) * pipe->bandwidth; if (q->numbytes > pipe->burst) q->numbytes = pipe->burst; if (io_fast) @@ -1418,8 +1429,8 @@ dummynet_io(struct mbuf **m0, int dir, s if (pipe->idle_time < curr_time) { /* Calculate available burst size. */ pipe->numbytes += - (curr_time - pipe->idle_time) * pipe->bandwidth; - if (pipe->numbytes > pipe->burst) + (curr_time - pipe->idle_time - 1) * pipe->bandwidth; + if (pipe->numbytes > 0 && pipe->numbytes > pipe->burst) pipe->numbytes = pipe->burst; if (io_fast) pipe->numbytes += pipe->bandwidth;