[NET_SCHED] sch_sfq: fix queue limiting while enqueuing
Current way to use q->limit both as per flow and total queue limit
doesn't make much sense. There would be no reason for sfq's limit
parameter if the same could be done with ifconfig's txqueuelen, and
it's too small for this anyway: with a number of flow queues around
maximum (SFQ_DEPTH) each queue would be ~1 packet long, which means
no queuing...
There is also changed a place for checking the total limit: let's do
it at the beginning (like in pfifo_fast_enqueue()). IMHO current way
is especially wrong during congestion: cpu & time costly classifying
and enqueuing is done under queue_lock, to end with dropping of
enqueued packets while adding newer ones. This means reordering and
usually more resending. (I think, similar changes should be done in
a few more qdiscs.)
Signed-off-by: Jarek Poplawski <jarkao2@gmail.com>
---
net/sched/sch_sfq.c | 29 +++++++++++++----------------
1 files changed, 13 insertions(+), 16 deletions(-)
diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c
index a20e2ef..b4fd592 100644
--- a/net/sched/sch_sfq.c
+++ b/net/sched/sch_sfq.c
@@ -283,6 +283,9 @@ sfq_enqueue(struct sk_buff *skb, struct Qdisc *sch)
sfq_index x;
int ret;
+ if (unlikely(sch->q.qlen >= max_t(__u32, sch->dev->tx_queue_len, 1)))
+ return qdisc_drop(skb, sch);
+
hash = sfq_classify(skb, sch, &ret);
if (hash == 0) {
if (ret == NET_XMIT_BYPASS)
@@ -319,14 +322,11 @@ sfq_enqueue(struct sk_buff *skb, struct Qdisc *sch)
q->tail = x;
}
}
- if (++sch->q.qlen <= q->limit) {
- sch->bstats.bytes += skb->len;
- sch->bstats.packets++;
- return 0;
- }
- sfq_drop(sch);
- return NET_XMIT_CN;
+ sch->q.qlen++;
+ sch->bstats.bytes += skb->len;
+ sch->bstats.packets++;
+ return 0;
}
static int
@@ -337,6 +337,9 @@ sfq_requeue(struct sk_buff *skb, struct Qdisc *sch)
sfq_index x;
int ret;
+ if (unlikely(sch->q.qlen >= max_t(__u32, sch->dev->tx_queue_len, 1)))
+ return qdisc_drop(skb, sch);
+
hash = sfq_classify(skb, sch, &ret);
if (hash == 0) {
if (ret == NET_XMIT_BYPASS)
@@ -381,14 +384,8 @@ sfq_requeue(struct sk_buff *skb, struct Qdisc *sch)
}
}
- if (++sch->q.qlen <= q->limit) {
- sch->qstats.requeues++;
- return 0;
- }
-
- sch->qstats.drops++;
- sfq_drop(sch);
- return NET_XMIT_CN;
+ sch->qstats.requeues++;
+ return 0;
}
@@ -467,7 +464,7 @@ static int sfq_change(struct Qdisc *sch, struct nlattr *opt)
q->limit = min_t(u32, ctl->limit, SFQ_DEPTH - 1);
qlen = sch->q.qlen;
- while (sch->q.qlen > q->limit)
+ while (q->max_depth > q->limit)
sfq_drop(sch);
qdisc_tree_decrease_qlen(sch, qlen - sch->q.qlen);
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
| Justin Piszcz | Linux Software RAID 5 Performance Optimizations: 2.6.19.1: (211MB/s read & 195... |
| Vu Pham | Re: [Scst-devel] Integration of SCST in the mainstream Linux kernel |
| David P. Quigley | [RFC v3] Security Label Support for NFSv4 |
| Greg Kroah-Hartman | [PATCH 004/196] Chinese: add translation of SubmittingPatches |
| YOSHIFUJI Hideaki / | [GIT PULL] [IPV6] COMPAT: Fix SSM applications on 64bit kernels. |
| Pavel Emelyanov | [PATCH][CAN]: Fix copy_from_user() results interpretation. |
| Krzysztof Halasa | Re: [PATCH v2] Re: WAN: new PPP code for generic HDLC |
| Roel Kluin | [PATCH 1] net: fix and typo's |
git: | |
| Peter Stahlir | Git as a filesystem |
| Miklos Vajna | [rfc] git submodules howto |
| Dan Zwell | $GIT_DIR usage |
| Wink Saville | Resolving conflicts |
| GVG GVG | ssh_exchange_identification: Connection closed by remote host |
| Xavier Mertens | newfs: cg 0: bad magic number |
| Laurent CARON | IPSEC VPN between OpenBSD and Linux (OpenSwan) |
| Didier Wiroth | win32-codecs, avi and amd64 question |
| Netfilter kernel module | 8 hours ago | Linux kernel |
| serial driver xmit problem | 11 hours ago | Linux kernel |
| Why Windows is better than Linux | 11 hours ago | Linux general |
| How can I see my kernel messages in vt12? | 18 hours ago | Linux kernel |
| Grub | 1 day ago | Linux general |
| vmalloc_fault handling in x86_64 | 1 day ago | Linux kernel |
| epoll_wait()ing on epoll FD | 1 day ago | Linux kernel |
| Framebuffer in x86_64 causes problems to multiseat | 1 day ago | Linux kernel |
| Difference between 2.4 and 2.6 regarding thread creation | 1 day ago | Linux general |
| Compiling gfs2 on kernel 2.6.27 | 2 days ago | Linux kernel |
