From patchwork Mon Jan 18 16:30:58 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hagen Paul Pfeifer X-Patchwork-Id: 43081 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 46232B7CA0 for ; Tue, 19 Jan 2010 03:31:13 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751293Ab0ARQbB (ORCPT ); Mon, 18 Jan 2010 11:31:01 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1751135Ab0ARQbB (ORCPT ); Mon, 18 Jan 2010 11:31:01 -0500 Received: from alternativer.internetendpunkt.de ([88.198.24.89]:56516 "EHLO geheimer.internetendpunkt.de" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1751137Ab0ARQbA (ORCPT ); Mon, 18 Jan 2010 11:31:00 -0500 Received: by geheimer.internetendpunkt.de (Postfix, from userid 1000) id 7E06FF44128; Mon, 18 Jan 2010 17:30:58 +0100 (CET) From: Hagen Paul Pfeifer To: netdev@vger.kernel.org Cc: kaber@trash.net Subject: [PATCH 1/1] sched: add head drop fifo queue Date: Mon, 18 Jan 2010 17:30:58 +0100 Message-Id: <1263832258-30297-1-git-send-email-hagen@jauu.net> X-Mailer: git-send-email 1.6.6.196.g1f735.dirty In-Reply-To: <4B546F24.6070404@trash.net> References: <4B546F24.6070404@trash.net> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org This add an additional queuing strategy, called pfifo_head_drop, to remove the oldest skb in the case of an overflow within the queue - the head element - instead of the last skb (tail). To remove the oldest skb in a congested situations is useful for sensor network environments where newer packets reflects the superior information. Reviewed-by: Florian Westphal Signed-off-by: Hagen Paul Pfeifer Acked-by: Patrick McHardy --- include/net/pkt_sched.h | 1 + net/sched/sch_api.c | 1 + net/sched/sch_fifo.c | 37 +++++++++++++++++++++++++++++++++++++ 3 files changed, 39 insertions(+), 0 deletions(-) diff --git a/include/net/pkt_sched.h b/include/net/pkt_sched.h index 2d56726..b6cdc33 100644 --- a/include/net/pkt_sched.h +++ b/include/net/pkt_sched.h @@ -71,6 +71,7 @@ extern void qdisc_watchdog_cancel(struct qdisc_watchdog *wd); extern struct Qdisc_ops pfifo_qdisc_ops; extern struct Qdisc_ops bfifo_qdisc_ops; +extern struct Qdisc_ops pfifo_head_drop_qdisc_ops; extern int fifo_set_limit(struct Qdisc *q, unsigned int limit); extern struct Qdisc *fifo_create_dflt(struct Qdisc *sch, struct Qdisc_ops *ops, diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index 75fd1c6..6cd4910 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c @@ -1707,6 +1707,7 @@ static int __init pktsched_init(void) { register_qdisc(&pfifo_qdisc_ops); register_qdisc(&bfifo_qdisc_ops); + register_qdisc(&pfifo_head_drop_qdisc_ops); register_qdisc(&mq_qdisc_ops); proc_net_fops_create(&init_net, "psched", 0, &psched_fops); diff --git a/net/sched/sch_fifo.c b/net/sched/sch_fifo.c index 69188e8..44f80ca 100644 --- a/net/sched/sch_fifo.c +++ b/net/sched/sch_fifo.c @@ -43,6 +43,28 @@ static int pfifo_enqueue(struct sk_buff *skb, struct Qdisc* sch) return qdisc_reshape_fail(skb, sch); } +static int pfifo_front_enqueue(struct sk_buff *skb, struct Qdisc* sch) +{ + struct sk_buff *skb_head; + struct fifo_sched_data *q = qdisc_priv(sch); + + if (likely(skb_queue_len(&sch->q) < q->limit)) + return qdisc_enqueue_tail(skb, sch); + + /* queue full, remove one skb to fulfill the limit */ + skb_head = qdisc_dequeue_head(sch); + sch->bstats.bytes -= qdisc_pkt_len(skb_head); + sch->bstats.packets--; + sch->q.qlen--; + sch->qstats.drops++; + kfree_skb(skb_head); + + qdisc_enqueue_tail(skb, sch); + + return NET_XMIT_CN; +} + + static int fifo_init(struct Qdisc *sch, struct nlattr *opt) { struct fifo_sched_data *q = qdisc_priv(sch); @@ -108,6 +130,21 @@ struct Qdisc_ops bfifo_qdisc_ops __read_mostly = { }; EXPORT_SYMBOL(bfifo_qdisc_ops); +struct Qdisc_ops pfifo_head_drop_qdisc_ops __read_mostly = { + .id = "pfifo_head_drop", + .priv_size = sizeof(struct fifo_sched_data), + .enqueue = pfifo_front_enqueue, + .dequeue = qdisc_dequeue_head, + .peek = qdisc_peek_head, + .drop = qdisc_queue_drop, + .init = fifo_init, + .reset = qdisc_reset_queue, + .change = fifo_init, + .dump = fifo_dump, + .owner = THIS_MODULE, +}; +EXPORT_SYMBOL(pfifo_head_drop_qdisc_ops); + /* Pass size change message down to embedded FIFO */ int fifo_set_limit(struct Qdisc *q, unsigned int limit) {