Netdev List
 help / color / mirror / Atom feed
* RE: [PATCH 1/6] bna: Brocade 10Gb Ethernet device driver
From: Debashis Dutt @ 2010-08-07  3:23 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: netdev@vger.kernel.org


Hi Stephen, 

Thanks a lot for your comments. 

> +                   if (likely
> +                       (wis > BNA_QE_FREE_CNT(tcb, tcb->q_depth) ||
> +                        vectors > BNA_QE_FREE_CNT(unmap_q, unmap_q->q_depth))) {
> +                               BNAD_UPDATE_CTR(bnad, netif_queue_stop);
> +                               return NETDEV_TX_BUSY;

>The transmit routine should check for available space after
> queueing to device, so you can avoid having to return
>TX_BUSY.

However your above comment is not very clear to me.

Our Tx routine already cleans up the Tx buffers at the end, through a tasklet.

Cleaning of Tx buffers happens 
1) In the sending context at the end of the Tx routine.
2) In the IRQ context when we get a Tx completion interrupt.

Only thing that we could have done, is do this check again at the end of the Tx routine
and called netif_stop_queue() if required, so that the stack stops sending. Even then I am 
not sure that we could avoid the current check and returning TX_BUSY.

It would be nice if you clarify, so that I understand this better.

Thanks
--Debashis
Linux LL Driver Team.


-----Original Message-----
From: Stephen Hemminger [mailto:shemminger@vyatta.com] 
Sent: Wednesday, August 04, 2010 10:09 AM
To: Rasesh Mody
Cc: netdev@vger.kernel.org; Debashis Dutt; Jing Huang
Subject: Re: [PATCH 1/6] bna: Brocade 10Gb Ethernet device driver

On Tue, 3 Aug 2010 22:15:36 -0700
Rasesh Mody <rmody@brocade.com> wrote:

> From: Rasesh Mody <rmody@brocade.com>
> 
> This is patch 1/6 which contains linux driver source for
> Brocade's BR1010/BR1020 10Gb CEE capable ethernet adapter.
> Source is based against net-next-2.6.
> 
> We wish this patch to be considered for inclusion in net-next-2.6
> 
> Signed-off-by: Rasesh Mody <rmody@brocade.com>
> ---
>  bnad.c         | 3326 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  bnad.h         |  474 ++++++++
>  bnad_ethtool.c | 1269 +++++++++++++++++++++
>  3 files changed, 5069 insertions(+)
> 
> diff -ruP net-next-2.6.35-rc1-orig/drivers/net/bna/bnad.c net-next-2.6.35-rc1-mod/drivers/net/bna/bnad.c
> --- net-next-2.6.35-rc1-orig/drivers/net/bna/bnad.c         1969-12-31 16:00:00.000000000 -0800
> +++ net-next-2.6.35-rc1-mod/drivers/net/bna/bnad.c     2010-08-02 17:19:19.447239000 -0700
> @@ -0,0 +1,3326 @@
> +/*
> + * Linux network driver for Brocade Converged Network Adapter.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License (GPL) Version 2 as
> + * published by the Free Software Foundation
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * General Public License for more details.
> + */
> +/*
> + * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
> + * All rights reserved
> + * www.brocade.com
> + */
> +#include <linux/netdevice.h>
> +#include <linux/skbuff.h>
> +#include <linux/etherdevice.h>
> +#include <linux/in.h>
> +#include <linux/ethtool.h>
> +#include <linux/if_vlan.h>
> +#include <linux/if_ether.h>
> +#include <linux/ip.h>
> +
> +#include "bnad.h"
> +#include "bna.h"
> +#include "cna.h"
> +
> +DEFINE_MUTEX(bnad_fwimg_mutex);
> +
> +/*
> + * Module params
> + */
> +static uint bnad_msix_disable;
> +module_param(bnad_msix_disable, uint, 0444);
> +MODULE_PARM_DESC(bnad_msix_disable, "Disable MSIX mode");
> +
> +static uint bnad_ioc_auto_recover = 1;
> +module_param(bnad_ioc_auto_recover, uint, 0444);
> +MODULE_PARM_DESC(bnad_ioc_auto_recover, "Enable / Disable auto recovery");
> +
> +/*
> + * Global variables
> + */
> +u32 bna_id;
> +u32 bnad_rxqs_per_cq = 2;
> +
> +DECLARE_MUTEX(bnad_list_sem);
> +LIST_HEAD(bnad_list);
> +
> +const u8 bnad_bcast_addr[] =  {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};

Surprised this isn't defined somewhere else.

> +
> +/*
> + * Local MACROS
> + */
> +#define BNAD_TX_UNMAPQ_DEPTH (bnad->txq_depth * 2)
> +
> +#define BNAD_RX_UNMAPQ_DEPTH (bnad->rxq_depth)
> +
> +#define BNAD_GET_MBOX_IRQ(_bnad)                                            \
> +       (((_bnad)->cfg_flags & BNAD_CF_MSIX) ?                                 \
> +       ((_bnad)->msix_table[(_bnad)->msix_num - 1].vector) :   \
> +       ((_bnad)->pcidev->irq))
> +
> +#define BNAD_FILL_UNMAPQ_MEM_REQ(_res_info, _num, _depth)  \
> +do {                                                                                     \
> +       (_res_info)->res_type = BNA_RES_T_MEM;                               \
> +       (_res_info)->res_u.mem_info.mem_type = BNA_MEM_T_KVA;    \
> +       (_res_info)->res_u.mem_info.num = (_num);                   \
> +       (_res_info)->res_u.mem_info.len =                                 \
> +       sizeof(struct bnad_unmap_q) +                                      \
> +       (sizeof(struct bnad_skb_unmap) * ((_depth) - 1));            \
> +} while (0)
> +
> +void
> +bnad_add_to_list(struct bnad *bnad)
> +{
> +       down(&bnad_list_sem);
> +       list_add_tail(&bnad->list_entry, &bnad_list);
> +       bna_id++;
> +       up(&bnad_list_sem);
> +}

Why do you need to list semaphore? Isn't RTNL mutex held
when this is done. If you have to have own exclusion use
a mutex for this.

> +void
> +bnad_remove_from_list(struct bnad *bnad)
> +{
> +       down(&bnad_list_sem);
> +       list_del(&bnad->list_entry);
> +       up(&bnad_list_sem);
> +}
> +
> +const struct pci_device_id bnad_pci_id_table[] = {
> +       {
> +                   PCI_DEVICE(PCI_VENDOR_ID_BROCADE,
> +                               PCI_DEVICE_ID_BROCADE_CT),
> +                   .class = PCI_CLASS_NETWORK_ETHERNET << 8,
> +                   .class_mask =  0xffff00
> +       }, {0,  }
> +};

Why is this not static?


> +/* TX */
> +/* bnad_start_xmit : Netdev entry point for Transmit */
> +/*                      Called under lock held by net_device */
> +
> +netdev_tx_t
> +bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)

Should also be static...

> +{
> +       struct bnad *bnad = netdev_priv(netdev);
> +
> +       u16                   txq_prod, vlan_tag = 0;
> +       u32                   unmap_prod, wis, wis_used, wi_range;
> +       u32                   vectors, vect_id, i, acked;
> +       u32                   tx_id;
> +       int                                 err;
> +
> +       struct bnad_tx_info *tx_info;
> +       struct bna_tcb *tcb;
> +       struct bnad_unmap_q *unmap_q;
> +       dma_addr_t                  dma_addr;
> +       struct bna_txq_entry *txqent;
> +       bna_txq_wi_ctrl_flag_t   flags;
> +
> +       if (unlikely
> +           (skb->len <= ETH_HLEN || skb->len > BFI_TX_MAX_DATA_PER_PKT)) {
> +                   dev_kfree_skb(skb);
> +                   return NETDEV_TX_OK;
> +       }
> +
> +       /*
> +       * Takes care of the Tx that is scheduled between clearing the flag
> +       * and the netif_stop_queue() call.
> +       */
> +       if (unlikely(!test_bit(BNAD_RF_TX_STARTED, &bnad->run_flags))) {
> +                   dev_kfree_skb(skb);
> +                   return NETDEV_TX_OK;
> +       }
> +
> +       tx_id = BNAD_GET_TX_ID(skb);
> +
> +       tx_info = &bnad->tx_info[tx_id];
> +       tcb = tx_info->tcb[tx_id];
> +       unmap_q = tcb->unmap_q;
> +
> +       vectors = 1 + skb_shinfo(skb)->nr_frags;
> +       if (vectors > BFI_TX_MAX_VECTORS_PER_PKT) {
> +                   dev_kfree_skb(skb);
> +                   return NETDEV_TX_OK;
> +       }
> +       wis = BNA_TXQ_WI_NEEDED(vectors); /* 4 vectors per work item */
> +       acked = 0;
> +       if (unlikely
> +           (wis > BNA_QE_FREE_CNT(tcb, tcb->q_depth) ||
> +            vectors > BNA_QE_FREE_CNT(unmap_q, unmap_q->q_depth))) {
> +                   if ((u16) (*tcb->hw_consumer_index) !=
> +                       tcb->consumer_index &&
> +                       !test_and_set_bit(BNAD_TXQ_FREE_SENT, &tcb->flags)) {
> +                               acked = bnad_free_txbufs(bnad, tcb);
> +                               bna_ib_ack(tcb->i_dbell, acked);
> +                               smp_mb__before_clear_bit();
> +                               clear_bit(BNAD_TXQ_FREE_SENT, &tcb->flags);
> +                   } else {
> +                               netif_stop_queue(netdev);
> +                               BNAD_UPDATE_CTR(bnad, netif_queue_stop);
> +                   }
> +
> +                   smp_mb();
> +                   /*
> +                   * Check again to deal with race condition between
> +                   * netif_stop_queue here, and netif_wake_queue in
> +                   * interrupt handler which is not inside netif tx lock.
> +                   */
> +                   if (likely
> +                       (wis > BNA_QE_FREE_CNT(tcb, tcb->q_depth) ||
> +                        vectors > BNA_QE_FREE_CNT(unmap_q, unmap_q->q_depth))) {
> +                               BNAD_UPDATE_CTR(bnad, netif_queue_stop);
> +                               return NETDEV_TX_BUSY;

The transmit routine should check for available space after
queueing to device, so you can avoid having to return
TX_BUSY.

^ permalink raw reply

* Re: [RFC PATCH] platform: Faciliatate the creation of pseduo-platform busses
From: Greg KH @ 2010-08-06 23:46 UTC (permalink / raw)
  To: Grant Likely
  Cc: Patrick Pannuto, Patrick Pannuto, linux-kernel@vger.kernel.org,
	linux-arm-msm@vger.kernel.org, linux-omap@vger.kernel.org,
	damm@opensource.se, lethal@linux-sh.org, rjw@sisk.pl,
	dtor@mail.ru, eric.y.miao@gmail.com, netdev@vger.kernel.org,
	Kevin Hilman
In-Reply-To: <AANLkTi=VbVed09=u-Ea0L8c_CWZ_CLLjWH9ZjD2dyg6Y@mail.gmail.com>

On Fri, Aug 06, 2010 at 09:12:27AM -0600, Grant Likely wrote:
> On Fri, Aug 6, 2010 at 8:27 AM, Greg KH <gregkh@suse.de> wrote:
> > On Thu, Aug 05, 2010 at 04:59:35PM -0600, Grant Likely wrote:
> >> (On that point Greg, what is the reason for even having the
> >> /sys/devices/platform/ parent?  Why not just let the platform devices
> >> sit at the root of the device tree?  In the OF case (granted, I'm
> >> biased) all of the platform_device registrations reflect the actual
> >> device hierarchy expressed in the device tree data.)
> >
> > If we sat them at the "root", there would be a bunch of them there.  I
> > don't know, we could drop the parent, I guess whoever created the
> > platform device oh so long ago, decided that it would look nicer to be
> > in this type of structure.
> 
> Personally I'd rather see a meaningful structure used here.  Maybe
> having them all in the root will encourage people to find realistic
> parents for their platform devices.  :-)

That would be nice, but take your "standard" PC today:
	> ls /sys/devices/platform/
	Fixed MDIO bus.0  i8042  pcspkr  power  serial8250  uevent vesafb.0

There are tty devices below the serial port, which is nice to see, but
the others?  I don't know what type of bus they would be on, do you?

> Why don't I float a patch to remove this and see if anybody freaks
> out.  Should I wrap it with a CONFIG_ so that it can be configurable
> for a release or to, or just make it unconditional?

If you can figure out a structure for the desktop/server machines, sure,
I say just always enable it :)

thanks,

greg k-h

^ permalink raw reply

* Re: [PATCH] sfq: add dummy bind/unbind handles
From: Jarek Poplawski @ 2010-08-06 23:17 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: David Miller, netdev, Franchoze Eric
In-Reply-To: <20100806152313.43abc30b@nehalam>

Stephen Hemminger wrote, On 07.08.2010 00:23:

> Applying a filter to an SFQ qdisc would cause null dereference
> in tcf_bind_filter because although SFQ is classful it didn't
> have all the necessary equipment.
> 
> Better alternative to changing tcf_bind API is to just fix
> SFQ.  This should go to net-2.6 and stable.
> 

Hmm... FYI, actually I've sent already a similar patch to the
original bug report thread (except .unbind_tcf method which
doesn't matter for fixing this bug, so should be rather
implemented in a separate patch, if needed at all in this
case).

Jarek P.

> 
> Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
> 
> --- a/net/sched/sch_sfq.c	2010-08-06 15:07:26.552820159 -0700
> +++ b/net/sched/sch_sfq.c	2010-08-06 15:14:24.458287452 -0700
> @@ -502,6 +502,10 @@ static unsigned long sfq_get(struct Qdis
>  	return 0;
>  }
>  
> +static void sfq_put(struct Qdisc *q, unsigned long cl)
> +{
> +}
> +
>  static struct tcf_proto **sfq_find_tcf(struct Qdisc *sch, unsigned long cl)
>  {
>  	struct sfq_sched_data *q = qdisc_priv(sch);
> @@ -511,6 +515,12 @@ static struct tcf_proto **sfq_find_tcf(s
>  	return &q->filter_list;
>  }
>  
> +static unsigned long sfq_bind_tcf(struct Qdisc *sch, unsigned long parent,
> +				  u32 cl)
> +{
> +	return 0;
> +}
> +
>  static int sfq_dump_class(struct Qdisc *sch, unsigned long cl,
>  			  struct sk_buff *skb, struct tcmsg *tcm)
>  {
> @@ -556,6 +566,8 @@ static void sfq_walk(struct Qdisc *sch, 
>  static const struct Qdisc_class_ops sfq_class_ops = {
>  	.get		=	sfq_get,
>  	.tcf_chain	=	sfq_find_tcf,
> +	.bind_tcf	=	sfq_bind_tcf,
> +	.unbind_tcf	=	sfq_put,
>  	.dump		=	sfq_dump_class,
>  	.dump_stats	=	sfq_dump_class_stats,
> 



^ permalink raw reply

* [PATCH] sfq: add dummy bind/unbind handles
From: Stephen Hemminger @ 2010-08-06 22:23 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: Jarek Poplawski, David Miller, netdev, Franchoze Eric
In-Reply-To: <20100806145818.66d389eb@nehalam>

Applying a filter to an SFQ qdisc would cause null dereference
in tcf_bind_filter because although SFQ is classful it didn't
have all the necessary equipment.

Better alternative to changing tcf_bind API is to just fix
SFQ.  This should go to net-2.6 and stable.


Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>

--- a/net/sched/sch_sfq.c	2010-08-06 15:07:26.552820159 -0700
+++ b/net/sched/sch_sfq.c	2010-08-06 15:14:24.458287452 -0700
@@ -502,6 +502,10 @@ static unsigned long sfq_get(struct Qdis
 	return 0;
 }
 
+static void sfq_put(struct Qdisc *q, unsigned long cl)
+{
+}
+
 static struct tcf_proto **sfq_find_tcf(struct Qdisc *sch, unsigned long cl)
 {
 	struct sfq_sched_data *q = qdisc_priv(sch);
@@ -511,6 +515,12 @@ static struct tcf_proto **sfq_find_tcf(s
 	return &q->filter_list;
 }
 
+static unsigned long sfq_bind_tcf(struct Qdisc *sch, unsigned long parent,
+				  u32 cl)
+{
+	return 0;
+}
+
 static int sfq_dump_class(struct Qdisc *sch, unsigned long cl,
 			  struct sk_buff *skb, struct tcmsg *tcm)
 {
@@ -556,6 +566,8 @@ static void sfq_walk(struct Qdisc *sch, 
 static const struct Qdisc_class_ops sfq_class_ops = {
 	.get		=	sfq_get,
 	.tcf_chain	=	sfq_find_tcf,
+	.bind_tcf	=	sfq_bind_tcf,
+	.unbind_tcf	=	sfq_put,
 	.dump		=	sfq_dump_class,
 	.dump_stats	=	sfq_dump_class_stats,

^ permalink raw reply

* Re: [PATCH] net: convert to rcu_dereference_index_check()
From: Paul E. McKenney @ 2010-08-06 22:52 UTC (permalink / raw)
  To: Herbert Xu; +Cc: netdev, linux-kernel, davem, arnd
In-Reply-To: <20100806221520.GA31949@gondor.apana.org.au>

On Sat, Aug 07, 2010 at 06:15:20AM +0800, Herbert Xu wrote:
> On Fri, Aug 06, 2010 at 02:26:07PM -0700, Paul E. McKenney wrote:
> > Hello, Herbert!
> > 
> > At long last, the following is the final patch blocking acceptance
> > of Arnd's sparse annotations for RCU.  It was itself blocked behind
> > the definition of rcu_dereference_index_check(), which made it to
> > mainline only just today.
> > 
> > Would you be willing to ack this patch so that I can push it to -tip,
> > along with Arnd's work and a bunch of other stuff?
> 
> Sure,
> 
> Acked-by: Herbert Xu <herbert@gondor.apana.org.au>

Thank you, Herbert!!!

							Thanx, Paul

^ permalink raw reply

* Re: [PATCH 1/9] net classifier: dont allow filters on semi-classful qdisc
From: Jarek Poplawski @ 2010-08-06 22:26 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: David Miller, netdev
In-Reply-To: <20100806145818.66d389eb@nehalam>

Stephen Hemminger wrote, On 06.08.2010 23:58:

> On Fri, 06 Aug 2010 23:24:47 +0200
> Jarek Poplawski <jarkao2@gmail.com> wrote:
> 
>> Stephen Hemminger wrote, On -10.01.-28163 20:59:
>>
>>> There are several qdisc which only support a single class (sfq, mq, tbf)
>>> and the kernel would dereference a null pointer (bind_tcf), if a user
>>> attempted to apply a filter one of these classes.
>>
>>
>> mq and tbf can't have this issue because they don't have
>> .tcf_chain class method. sfq should support it on purpose
>> after this patch:
>>
>> http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=7d2681a6ff4f9ab5e48d02550b4c6338f1638998
>> and needs tiny fix only.
> 
> Probably best to fix both ways.  Fix sfq to allow filters to
> be chained, and fix API to prevent refuse to allow qdisc to
> register with tcf_chain && !bind_tcf
> 

Yes, but your patch needs a different changelog and I'm not sure
it's necessary for stable (there should be no other such cases
for now).

Jarek P.

^ permalink raw reply

* Re: [PATCH] net: convert to rcu_dereference_index_check()
From: Herbert Xu @ 2010-08-06 22:15 UTC (permalink / raw)
  To: Paul E. McKenney; +Cc: netdev, linux-kernel, davem, arnd
In-Reply-To: <20100806212607.GA9410@linux.vnet.ibm.com>

On Fri, Aug 06, 2010 at 02:26:07PM -0700, Paul E. McKenney wrote:
> Hello, Herbert!
> 
> At long last, the following is the final patch blocking acceptance
> of Arnd's sparse annotations for RCU.  It was itself blocked behind
> the definition of rcu_dereference_index_check(), which made it to
> mainline only just today.
> 
> Would you be willing to ack this patch so that I can push it to -tip,
> along with Arnd's work and a bunch of other stuff?

Sure,

Acked-by: Herbert Xu <herbert@gondor.apana.org.au>

Thanks,
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

^ permalink raw reply

* Re: [PATCH 1/9] net classifier: dont allow filters on semi-classful qdisc
From: Stephen Hemminger @ 2010-08-06 21:58 UTC (permalink / raw)
  To: Jarek Poplawski; +Cc: David Miller, netdev
In-Reply-To: <4C5C7D9F.4040303@gmail.com>

On Fri, 06 Aug 2010 23:24:47 +0200
Jarek Poplawski <jarkao2@gmail.com> wrote:

> Stephen Hemminger wrote, On -10.01.-28163 20:59:
> 
> > There are several qdisc which only support a single class (sfq, mq, tbf)
> > and the kernel would dereference a null pointer (bind_tcf), if a user
> > attempted to apply a filter one of these classes.
> 
> 
> mq and tbf can't have this issue because they don't have
> .tcf_chain class method. sfq should support it on purpose
> after this patch:
> 
> http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=7d2681a6ff4f9ab5e48d02550b4c6338f1638998
> and needs tiny fix only.

Probably best to fix both ways.  Fix sfq to allow filters to
be chained, and fix API to prevent refuse to allow qdisc to
register with tcf_chain && !bind_tcf

^ permalink raw reply

* Re: [PATCH] net: convert to rcu_dereference_index_check()
From: Paul E. McKenney @ 2010-08-06 21:54 UTC (permalink / raw)
  To: David Miller; +Cc: herbert, netdev, linux-kernel, arnd
In-Reply-To: <20100806.144901.184847372.davem@davemloft.net>

On Fri, Aug 06, 2010 at 02:49:01PM -0700, David Miller wrote:
> From: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
> Date: Fri, 6 Aug 2010 14:26:07 -0700
> 
> > At long last, the following is the final patch blocking acceptance
> > of Arnd's sparse annotations for RCU.  It was itself blocked behind
> > the definition of rcu_dereference_index_check(), which made it to
> > mainline only just today.
> > 
> > Would you be willing to ack this patch so that I can push it to -tip,
> > along with Arnd's work and a bunch of other stuff?
>  ...
> >     net: convert to rcu_dereference_index_check()
> >     
> >     The task_cls_classid() function applies rcu_dereference() to integers,
> >     which does not work with the shiny new sparse-based checking in
> >     rcu_dereference().  This commit therefore moves to the new RCU API
> >     rcu_dereference_index_check().
> >     
> >     Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
> >     Reviewed-by: Josh Triplett <josh@joshtriplett.org>
> 
> You should of course wait for Herbert's ACK too, but for
> the record:
> 
> Acked-by: David S. Miller <davem@davemloft.net>
> 
> :-)

Thank you, David!!!  ;-)

							Thanx, Paul

^ permalink raw reply

* Re: [PATCH] net: convert to rcu_dereference_index_check()
From: David Miller @ 2010-08-06 21:49 UTC (permalink / raw)
  To: paulmck; +Cc: herbert, netdev, linux-kernel, arnd
In-Reply-To: <20100806212607.GA9410@linux.vnet.ibm.com>

From: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
Date: Fri, 6 Aug 2010 14:26:07 -0700

> At long last, the following is the final patch blocking acceptance
> of Arnd's sparse annotations for RCU.  It was itself blocked behind
> the definition of rcu_dereference_index_check(), which made it to
> mainline only just today.
> 
> Would you be willing to ack this patch so that I can push it to -tip,
> along with Arnd's work and a bunch of other stuff?
 ...
>     net: convert to rcu_dereference_index_check()
>     
>     The task_cls_classid() function applies rcu_dereference() to integers,
>     which does not work with the shiny new sparse-based checking in
>     rcu_dereference().  This commit therefore moves to the new RCU API
>     rcu_dereference_index_check().
>     
>     Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
>     Reviewed-by: Josh Triplett <josh@joshtriplett.org>

You should of course wait for Herbert's ACK too, but for
the record:

Acked-by: David S. Miller <davem@davemloft.net>

:-)

^ permalink raw reply

* [PATCH] net: convert to rcu_dereference_index_check()
From: Paul E. McKenney @ 2010-08-06 21:26 UTC (permalink / raw)
  To: herbert; +Cc: netdev, linux-kernel, davem, arnd

Hello, Herbert!

At long last, the following is the final patch blocking acceptance
of Arnd's sparse annotations for RCU.  It was itself blocked behind
the definition of rcu_dereference_index_check(), which made it to
mainline only just today.

Would you be willing to ack this patch so that I can push it to -tip,
along with Arnd's work and a bunch of other stuff?

							Thanx, Paul

------------------------------------------------------------------------

commit 34ea15566530f8e4d0c1571cc8c3554fd91d5809
Author: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Date:   Mon Jun 14 17:06:21 2010 -0700

    net: convert to rcu_dereference_index_check()
    
    The task_cls_classid() function applies rcu_dereference() to integers,
    which does not work with the shiny new sparse-based checking in
    rcu_dereference().  This commit therefore moves to the new RCU API
    rcu_dereference_index_check().
    
    Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
    Reviewed-by: Josh Triplett <josh@joshtriplett.org>

 cls_cgroup.h |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/include/net/cls_cgroup.h b/include/net/cls_cgroup.h
index 726cc35..dd1fdb8 100644
--- a/include/net/cls_cgroup.h
+++ b/include/net/cls_cgroup.h
@@ -45,7 +45,8 @@ static inline u32 task_cls_classid(struct task_struct *p)
 		return 0;
 
 	rcu_read_lock();
-	id = rcu_dereference(net_cls_subsys_id);
+	id = rcu_dereference_index_check(net_cls_subsys_id,
+					 rcu_read_lock_held());
 	if (id >= 0)
 		classid = container_of(task_subsys_state(p, id),
 				       struct cgroup_cls_state, css)->classid;

^ permalink raw reply related

* Re: [PATCH 1/9] net classifier: dont allow filters on semi-classful qdisc
From: Jarek Poplawski @ 2010-08-06 21:24 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: David Miller, netdev
In-Reply-To: <20100806193558.580890552@vyatta.com>

Stephen Hemminger wrote, On -10.01.-28163 20:59:

> There are several qdisc which only support a single class (sfq, mq, tbf)
> and the kernel would dereference a null pointer (bind_tcf), if a user
> attempted to apply a filter one of these classes.


mq and tbf can't have this issue because they don't have
.tcf_chain class method. sfq should support it on purpose
after this patch:

http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=7d2681a6ff4f9ab5e48d02550b4c6338f1638998
and needs tiny fix only.


Jarek P.

> 
> This patch changes the tcf_bind_filter to return an error in
> these cases.
> 
> Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
> 
> 
> ---
> This needs to go in net-2.6 and stable.
> 
>  include/net/pkt_cls.h   |   12 +++++++++---
>  net/sched/cls_basic.c   |    4 +++-
>  net/sched/cls_fw.c      |    6 ++++--
>  net/sched/cls_route.c   |    4 +++-
>  net/sched/cls_tcindex.c |    4 +++-
>  net/sched/cls_u32.c     |    4 +++-
>  6 files changed, 25 insertions(+), 9 deletions(-)
> 
> --- a/include/net/pkt_cls.h	2010-08-06 11:51:18.903581556 -0700
> +++ b/include/net/pkt_cls.h	2010-08-06 12:20:02.072241508 -0700
> @@ -40,15 +40,21 @@ cls_set_class(struct tcf_proto *tp, unsi
>  	return old_cl;
>  }
>  
> -static inline void
> +static inline int
>  tcf_bind_filter(struct tcf_proto *tp, struct tcf_result *r, unsigned long base)
>  {
> +	const struct Qdisc_class_ops *cops = tp->q->ops->cl_ops;
>  	unsigned long cl;
>  
> -	cl = tp->q->ops->cl_ops->bind_tcf(tp->q, base, r->classid);
> +	if (!cops->bind_tcf)
> +		return -EINVAL;
> +
> +	cl = cops->bind_tcf(tp->q, base, r->classid);
>  	cl = cls_set_class(tp, &r->class, cl);
>  	if (cl)
> -		tp->q->ops->cl_ops->unbind_tcf(tp->q, cl);
> +		cops->unbind_tcf(tp->q, cl);
> +
> +	return 0;
>  }
>  
>  static inline void
> --- a/net/sched/cls_basic.c	2010-08-06 11:51:18.923582342 -0700
> +++ b/net/sched/cls_basic.c	2010-08-06 11:55:13.292553190 -0700
> @@ -153,7 +153,9 @@ static inline int basic_set_parms(struct
>  
>  	if (tb[TCA_BASIC_CLASSID]) {
>  		f->res.classid = nla_get_u32(tb[TCA_BASIC_CLASSID]);
> -		tcf_bind_filter(tp, &f->res, base);
> +		err = tcf_bind_filter(tp, &f->res, base);
> +		if (err)
> +			goto errout;
>  	}
>  
>  	tcf_exts_change(tp, &f->exts, &e);
> --- a/net/sched/cls_fw.c	2010-08-06 11:51:18.943583126 -0700
> +++ b/net/sched/cls_fw.c	2010-08-06 11:55:39.085476144 -0700
> @@ -206,10 +206,11 @@ fw_change_attrs(struct tcf_proto *tp, st
>  	if (err < 0)
>  		return err;
>  
> -	err = -EINVAL;
>  	if (tb[TCA_FW_CLASSID]) {
>  		f->res.classid = nla_get_u32(tb[TCA_FW_CLASSID]);
> -		tcf_bind_filter(tp, &f->res, base);
> +		err = tcf_bind_filter(tp, &f->res, base);
> +		if (err)
> +			goto errout;
>  	}
>  
>  #ifdef CONFIG_NET_CLS_IND
> @@ -220,6 +221,7 @@ fw_change_attrs(struct tcf_proto *tp, st
>  	}
>  #endif /* CONFIG_NET_CLS_IND */
>  
> +	err = -EINVAL;
>  	if (tb[TCA_FW_MASK]) {
>  		mask = nla_get_u32(tb[TCA_FW_MASK]);
>  		if (mask != head->mask)
> --- a/net/sched/cls_route.c	2010-08-06 11:51:18.959583757 -0700
> +++ b/net/sched/cls_route.c	2010-08-06 11:55:50.077870498 -0700
> @@ -412,7 +412,9 @@ static int route4_set_parms(struct tcf_p
>  
>  	if (tb[TCA_ROUTE4_CLASSID]) {
>  		f->res.classid = nla_get_u32(tb[TCA_ROUTE4_CLASSID]);
> -		tcf_bind_filter(tp, &f->res, base);
> +		err = tcf_bind_filter(tp, &f->res, base);
> +		if (err)
> +			goto errout;
>  	}
>  
>  	tcf_exts_change(tp, &f->exts, &e);
> --- a/net/sched/cls_tcindex.c	2010-08-06 11:51:18.999585326 -0700
> +++ b/net/sched/cls_tcindex.c	2010-08-06 11:56:01.486283847 -0700
> @@ -295,7 +295,9 @@ tcindex_set_parms(struct tcf_proto *tp, 
>  
>  	if (tb[TCA_TCINDEX_CLASSID]) {
>  		cr.res.classid = nla_get_u32(tb[TCA_TCINDEX_CLASSID]);
> -		tcf_bind_filter(tp, &cr.res, base);
> +		err = tcf_bind_filter(tp, &cr.res, base);
> +		if (err)
> +			goto errout;
>  	}
>  
>  	tcf_exts_change(tp, &cr.exts, &e);
> --- a/net/sched/cls_u32.c	2010-08-06 11:51:19.019586112 -0700
> +++ b/net/sched/cls_u32.c	2010-08-06 11:56:12.390678703 -0700
> @@ -528,7 +528,9 @@ static int u32_set_parms(struct tcf_prot
>  	}
>  	if (tb[TCA_U32_CLASSID]) {
>  		n->res.classid = nla_get_u32(tb[TCA_U32_CLASSID]);
> -		tcf_bind_filter(tp, &n->res, base);
> +		err = tcf_bind_filter(tp, &n->res, base);
> +		if (err)
> +			goto errout;
>  	}
>  
>  #ifdef CONFIG_NET_CLS_IND
> 
> 
> --
> 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
> 



^ permalink raw reply

* Re: pull request: wireless-2.6 2010-08-06
From: David Miller @ 2010-08-06 20:46 UTC (permalink / raw)
  To: linville-2XuSBdqkA4R54TAoqtyWWQ
  Cc: linux-wireless-u79uwXL29TY76Z2rM5mHXA,
	netdev-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20100806191443.GB2753-2XuSBdqkA4R54TAoqtyWWQ@public.gmane.org>

From: "John W. Linville" <linville-2XuSBdqkA4R54TAoqtyWWQ@public.gmane.org>
Date: Fri, 6 Aug 2010 15:14:43 -0400

> Here is the first round of fixes intended for 2.6.36.  It is bigger than
> I would prefer, but I hope you will still find it acceptable, especially
> as we are still so early in the cycle.

Pulled, thanks John.

As you know I'd prefer if things settle down from this point
forward, thanks :-)
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* [PATCH 10/18] isdn: hisax: call disable_pci_device() if pci_probe() failed
From: Kulikov Vasiliy @ 2010-08-06 20:02 UTC (permalink / raw)
  To: kernel-janitors
  Cc: Karsten Keil, Jesse Barnes, Tilman Schmidt, Tejun Heo, netdev,
	linux-kernel

Driver should call disable_pci_device() if it returns from pci_probe()
with error.

Signed-off-by: Kulikov Vasiliy <segooon@gmail.com>
---
 drivers/isdn/hisax/avm_pci.c   |    2 ++
 drivers/isdn/hisax/elsa.c      |    5 +++++
 drivers/isdn/hisax/nj_u.c      |    2 ++
 drivers/isdn/hisax/sedlbauer.c |    3 +++
 drivers/isdn/hisax/w6692.c     |    6 +++++-
 5 files changed, 17 insertions(+), 1 deletions(-)

diff --git a/drivers/isdn/hisax/avm_pci.c b/drivers/isdn/hisax/avm_pci.c
index fcf4ed1..c503d7f 100644
--- a/drivers/isdn/hisax/avm_pci.c
+++ b/drivers/isdn/hisax/avm_pci.c
@@ -845,12 +845,14 @@ static int __devinit avm_pci_setup(struct IsdnCardState *cs)
 		cs->irq = dev_avm->irq;
 		if (!cs->irq) {
 			printk(KERN_ERR "FritzPCI: No IRQ for PCI card found\n");
+			pci_disable_device(dev_avm);
 			return(0);
 		}
 
 		cs->hw.avm.cfg_reg = pci_resource_start(dev_avm, 1);
 		if (!cs->hw.avm.cfg_reg) {
 			printk(KERN_ERR "FritzPCI: No IO-Adr for PCI card found\n");
+			pci_disable_device(dev_avm);
 			return(0);
 		}
 
diff --git a/drivers/isdn/hisax/elsa.c b/drivers/isdn/hisax/elsa.c
index 5d9d338..452429a 100644
--- a/drivers/isdn/hisax/elsa.c
+++ b/drivers/isdn/hisax/elsa.c
@@ -1034,12 +1034,14 @@ static int __devinit
 setup_elsa_pci(struct IsdnCard *card)
 {
 	struct IsdnCardState *cs = card->cs;
+	struct pci_dev *pdev;
 
 	cs->subtyp = 0;
 	if ((dev_qs1000 = hisax_find_pci_device(PCI_VENDOR_ID_ELSA,
 		PCI_DEVICE_ID_ELSA_MICROLINK, dev_qs1000))) {
 		if (pci_enable_device(dev_qs1000))
 			return(0);
+		pdev = dev_qs1000;
 		cs->subtyp = ELSA_QS1000PCI;
 		cs->irq = dev_qs1000->irq;
 		cs->hw.elsa.cfg = pci_resource_start(dev_qs1000, 1);
@@ -1048,6 +1050,7 @@ setup_elsa_pci(struct IsdnCard *card)
 		PCI_DEVICE_ID_ELSA_QS3000, dev_qs3000))) {
 		if (pci_enable_device(dev_qs3000))
 			return(0);
+		pdev = dev_qs3000;
 		cs->subtyp = ELSA_QS3000PCI;
 		cs->irq = dev_qs3000->irq;
 		cs->hw.elsa.cfg = pci_resource_start(dev_qs3000, 1);
@@ -1058,11 +1061,13 @@ setup_elsa_pci(struct IsdnCard *card)
 	}
 	if (!cs->irq) {
 		printk(KERN_WARNING "Elsa: No IRQ for PCI card found\n");
+		pci_disable_device(pdev);
 		return(0);
 	}
 
 	if (!(cs->hw.elsa.base && cs->hw.elsa.cfg)) {
 		printk(KERN_WARNING "Elsa: No IO-Adr for PCI card found\n");
+		pci_disable_device(pdev);
 		return(0);
 	}
 	if ((cs->hw.elsa.cfg & 0xff) || (cs->hw.elsa.base & 0xf)) {
diff --git a/drivers/isdn/hisax/nj_u.c b/drivers/isdn/hisax/nj_u.c
index 095e974..bc5afbe 100644
--- a/drivers/isdn/hisax/nj_u.c
+++ b/drivers/isdn/hisax/nj_u.c
@@ -137,11 +137,13 @@ static int __devinit nju_pci_probe(struct pci_dev *dev_netjet,
 	cs->irq = dev_netjet->irq;
 	if (!cs->irq) {
 		printk(KERN_WARNING "NETspider-U: No IRQ for PCI card found\n");
+		pci_disable_device(dev_netjet);
 		return(0);
 	}
 	cs->hw.njet.base = pci_resource_start(dev_netjet, 0);
 	if (!cs->hw.njet.base) {
 		printk(KERN_WARNING "NETspider-U: No IO-Adr for PCI card found\n");
+		pci_disable_device(dev_netjet);
 		return(0);
 	}
 
diff --git a/drivers/isdn/hisax/sedlbauer.c b/drivers/isdn/hisax/sedlbauer.c
index 69dfc8d..dc9864b 100644
--- a/drivers/isdn/hisax/sedlbauer.c
+++ b/drivers/isdn/hisax/sedlbauer.c
@@ -614,6 +614,7 @@ setup_sedlbauer_pci(struct IsdnCard *card)
 		cs->irq = dev_sedl->irq;
 		if (!cs->irq) {
 			printk(KERN_WARNING "Sedlbauer: No IRQ for PCI card found\n");
+			pci_disable_device(dev_sedl);
 			return(0);
 		}
 		cs->hw.sedl.cfg_reg = pci_resource_start(dev_sedl, 0);
@@ -631,6 +632,7 @@ setup_sedlbauer_pci(struct IsdnCard *card)
 		cs->hw.sedl.cfg_reg);
 	if (sub_id != PCI_SUB_ID_SEDLBAUER) {
 		printk(KERN_ERR "Sedlbauer: unknown sub id %#x\n", sub_id);
+		pci_disable_device(dev_sedl);
 		return(0);
 	}
 	if (sub_vendor_id == PCI_SUBVENDOR_SPEEDFAX_PYRAMID) {
@@ -648,6 +650,7 @@ setup_sedlbauer_pci(struct IsdnCard *card)
 	} else {
 		printk(KERN_ERR "Sedlbauer: unknown sub vendor id %#x\n",
 			sub_vendor_id);
+		pci_disable_device(dev_sedl);
 		return(0);
 	}
 
diff --git a/drivers/isdn/hisax/w6692.c b/drivers/isdn/hisax/w6692.c
index e2cfb6f..4221cab 100644
--- a/drivers/isdn/hisax/w6692.c
+++ b/drivers/isdn/hisax/w6692.c
@@ -1012,8 +1012,10 @@ setup_w6692(struct IsdnCard *card)
 					    id_list[id_idx].device_id,
 					    dev_w6692);
 		if (dev_w6692) {
-			if (pci_enable_device(dev_w6692))
+			if (pci_enable_device(dev_w6692)) {
+				dev_w6692 = NULL;
 				continue;
+			}
 			cs->subtyp = id_idx;
 			break;
 		}
@@ -1040,10 +1042,12 @@ setup_w6692(struct IsdnCard *card)
 	cs->irq = pci_irq;
 	if (!cs->irq) {
 		printk(KERN_WARNING "W6692: No IRQ for PCI card found\n");
+		pci_disable_device(dev_w6692);
 		return (0);
 	}
 	if (!pci_ioaddr) {
 		printk(KERN_WARNING "W6692: NO I/O Base Address found\n");
+		pci_disable_device(dev_w6692);
 		return (0);
 	}
 	cs->hw.w6692.iobase = pci_ioaddr;
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH 09/18] isdn: mISDN: call disable_pci_device() if pci_probe() failed
From: Kulikov Vasiliy @ 2010-08-06 19:51 UTC (permalink / raw)
  To: kernel-janitors
  Cc: Karsten Keil, David S. Miller, Andrew Morton,
	Uwe Kleine-König, Peter Huewe, Tejun Heo, netdev

Driver should call disable_pci_device() if it returns from pci_probe()
with error. Also it must not be called if request_region() fails as
it means that somebody uses device resources and rules the device.

Signed-off-by: Kulikov Vasiliy <segooon@gmail.com>
---
 drivers/isdn/hardware/mISDN/mISDNinfineon.c |    7 ++++++-
 1 files changed, 6 insertions(+), 1 deletions(-)

diff --git a/drivers/isdn/hardware/mISDN/mISDNinfineon.c b/drivers/isdn/hardware/mISDN/mISDNinfineon.c
index d2dd61d..142744c 100644
--- a/drivers/isdn/hardware/mISDN/mISDNinfineon.c
+++ b/drivers/isdn/hardware/mISDN/mISDNinfineon.c
@@ -1094,6 +1094,7 @@ inf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 		pr_info("mISDN: do not have informations about adapter at %s\n",
 			pci_name(pdev));
 		kfree(card);
+		pci_disable_device(pdev);
 		return -EINVAL;
 	} else
 		pr_notice("mISDN: found adapter %s at %s\n",
@@ -1103,7 +1104,8 @@ inf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	pci_set_drvdata(pdev, card);
 	err = setup_instance(card);
 	if (err) {
-		pci_disable_device(card->pdev);
+		if (err != -EBUSY)
+			pci_disable_device(pdev);
 		kfree(card);
 		pci_set_drvdata(pdev, NULL);
 	} else if (ent->driver_data == INF_SCT_1) {
@@ -1114,6 +1116,7 @@ inf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 			sc = kzalloc(sizeof(struct inf_hw), GFP_KERNEL);
 			if (!sc) {
 				release_card(card);
+				pci_disable_device(pdev);
 				return -ENOMEM;
 			}
 			sc->irq = card->irq;
@@ -1121,6 +1124,8 @@ inf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 			sc->ci = card->ci + i;
 			err = setup_instance(sc);
 			if (err) {
+				if (err != -EBUSY)
+					pci_disable_device(pdev);
 				kfree(sc);
 				release_card(card);
 				break;
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH 08/18] isdn: eicon: call disable_pci_device() if pci_probe() failed
From: Kulikov Vasiliy @ 2010-08-06 19:51 UTC (permalink / raw)
  To: kernel-janitors
  Cc: Armin Schindler, Karsten Keil, David S. Miller, Peter Huewe,
	Arnd Bergmann, netdev

Driver should call disable_pci_device() if it returns from pci_probe()
with error.

Signed-off-by: Kulikov Vasiliy <segooon@gmail.com>
---
 drivers/isdn/hardware/eicon/divasmain.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/drivers/isdn/hardware/eicon/divasmain.c b/drivers/isdn/hardware/eicon/divasmain.c
index ed9c555..61e077e 100644
--- a/drivers/isdn/hardware/eicon/divasmain.c
+++ b/drivers/isdn/hardware/eicon/divasmain.c
@@ -743,6 +743,7 @@ static int __devinit divas_init_one(struct pci_dev *pdev,
 			CardProperties[ent->driver_data].
 			Name, pdev->bus->number,
 			pdev->devfn);
+		pci_disable_device(pdev);
 		return (-EIO);
 	}
 
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH 07/18] isdn: avm: call disable_pci_device() if pci_probe() failed
From: Kulikov Vasiliy @ 2010-08-06 19:51 UTC (permalink / raw)
  To: kernel-janitors
  Cc: Karsten Keil, David S. Miller, Alexey Dobriyan, Tilman Schmidt,
	netdev

Driver should call disable_pci_device() if it returns from pci_probe()
with error. Also it must not be called if request_region() fails as
it means that somebody uses device resources and rules the device.

Signed-off-by: Kulikov Vasiliy <segooon@gmail.com>
---
 drivers/isdn/hardware/avm/t1pci.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/drivers/isdn/hardware/avm/t1pci.c b/drivers/isdn/hardware/avm/t1pci.c
index 5a3f830..e891ed6 100644
--- a/drivers/isdn/hardware/avm/t1pci.c
+++ b/drivers/isdn/hardware/avm/t1pci.c
@@ -210,6 +210,8 @@ static int __devinit t1pci_probe(struct pci_dev *dev,
 	if (retval != 0) {
 		printk(KERN_ERR "t1pci: no AVM-T1-PCI at i/o %#x, irq %d detected, mem %#x\n",
 		       param.port, param.irq, param.membase);
+		if (retval != -EBUSY)
+			pci_disable_device(dev);
 		return -ENODEV;
 	}
 	return 0;
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH 06/18] isdn: avm: call disable_pci_device() if pci_probe() failed
From: Kulikov Vasiliy @ 2010-08-06 19:51 UTC (permalink / raw)
  To: kernel-janitors
  Cc: Karsten Keil, David S. Miller, Alexey Dobriyan, Tilman Schmidt,
	Tejun Heo, netdev

Driver should call disable_pci_device() if it returns from pci_probe()
with error. Also it must not be called if request_region() fails as
it means that somebody uses device resources and rules the device.

Signed-off-by: Kulikov Vasiliy <segooon@gmail.com>
---
 drivers/isdn/hardware/avm/c4.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/drivers/isdn/hardware/avm/c4.c b/drivers/isdn/hardware/avm/c4.c
index 7715d32..f255001 100644
--- a/drivers/isdn/hardware/avm/c4.c
+++ b/drivers/isdn/hardware/avm/c4.c
@@ -1273,6 +1273,8 @@ static int __devinit c4_probe(struct pci_dev *dev,
 	if (retval != 0) {
 		printk(KERN_ERR "c4: no AVM-C%d at i/o %#x, irq %d detected, mem %#x\n",
 		       nr, param.port, param.irq, param.membase);
+		if (retval != -EBUSY)
+			pci_disable_device(dev);
 		return -ENODEV;
 	}
 	return 0;
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH 4/9] netem: add locking around changes
From: Stephen Hemminger @ 2010-08-06 19:35 UTC (permalink / raw)
  To: David Miller; +Cc: netdev
In-Reply-To: <20100806193548.007978639@vyatta.com>

[-- Attachment #1: netem-cleanup.patch --]
[-- Type: text/plain, Size: 1480 bytes --]

Some safety improvements to netem to make it safer to change paramters
while queue is running.

Use sch_tree_lock() to block all packets during change.

Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>


--- a/net/sched/sch_netem.c	2010-08-02 16:22:42.389335747 -0700
+++ b/net/sched/sch_netem.c	2010-08-03 08:25:15.611820853 -0700
@@ -318,7 +318,6 @@ static int get_dist_table(struct Qdisc *
 	struct netem_sched_data *q = qdisc_priv(sch);
 	unsigned long n = nla_len(attr)/sizeof(__s16);
 	const __s16 *data = nla_data(attr);
-	spinlock_t *root_lock;
 	struct disttable *d;
 	int i;
 
@@ -333,12 +332,9 @@ static int get_dist_table(struct Qdisc *
 	for (i = 0; i < n; i++)
 		d->table[i] = data[i];
 
-	root_lock = qdisc_root_sleeping_lock(sch);
-
-	spin_lock_bh(root_lock);
 	kfree(q->delay_dist);
 	q->delay_dist = d;
-	spin_unlock_bh(root_lock);
+
 	return 0;
 }
 
@@ -412,6 +408,7 @@ static int netem_change(struct Qdisc *sc
 		return ret;
 	}
 
+	sch_tree_lock(sch);
 	q->latency = qopt->latency;
 	q->jitter = qopt->jitter;
 	q->limit = qopt->limit;
@@ -432,7 +429,7 @@ static int netem_change(struct Qdisc *sc
 	if (tb[TCA_NETEM_DELAY_DIST]) {
 		ret = get_dist_table(sch, tb[TCA_NETEM_DELAY_DIST]);
 		if (ret)
-			return ret;
+			goto out;
 	}
 
 	if (tb[TCA_NETEM_REORDER])
@@ -440,6 +437,8 @@ static int netem_change(struct Qdisc *sc
 
 	if (tb[TCA_NETEM_CORRUPT])
 		get_corrupt(sch, tb[TCA_NETEM_CORRUPT]);
+ out:
+	sch_tree_unlock(sch);
 
 	return 0;
 }



^ permalink raw reply

* [PATCH 3/9] u32 classifier: fix sparse warnings
From: Stephen Hemminger @ 2010-08-06 19:35 UTC (permalink / raw)
  To: David Miller; +Cc: netdev
In-Reply-To: <20100806193548.007978639@vyatta.com>

[-- Attachment #1: cls-u32-sparse.patch --]
[-- Type: text/plain, Size: 1454 bytes --]

The variable _data is used in asm-generic to define sections
which causes sparse warnings, so just rename the variable.

Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>

--- a/net/sched/cls_u32.c	2010-08-06 11:41:06.974527973 -0700
+++ b/net/sched/cls_u32.c	2010-08-06 12:20:03.508295989 -0700
@@ -135,12 +135,12 @@ next_knode:
 
 		for (i = n->sel.nkeys; i>0; i--, key++) {
 			int toff = off + key->off + (off2 & key->offmask);
-			__be32 *data, _data;
+			__be32 *data, hdata;
 
 			if (skb_headroom(skb) + toff < 0)
 				goto out;
 
-			data = skb_header_pointer(skb, toff, 4, &_data);
+			data = skb_header_pointer(skb, toff, 4, &hdata);
 			if (!data)
 				goto out;
 			if ((*data ^ key->val) & key->mask) {
@@ -188,10 +188,10 @@ check_terminal:
 		ht = n->ht_down;
 		sel = 0;
 		if (ht->divisor) {
-			__be32 *data, _data;
+			__be32 *data, hdata;
 
 			data = skb_header_pointer(skb, off + n->sel.hoff, 4,
-						  &_data);
+						  &hdata);
 			if (!data)
 				goto out;
 			sel = ht->divisor & u32_hash_fold(*data, &n->sel,
@@ -203,11 +203,11 @@ check_terminal:
 		if (n->sel.flags&(TC_U32_OFFSET|TC_U32_VAROFFSET)) {
 			off2 = n->sel.off + 3;
 			if (n->sel.flags & TC_U32_VAROFFSET) {
-				__be16 *data, _data;
+				__be16 *data, hdata;
 
 				data = skb_header_pointer(skb,
 							  off + n->sel.offoff,
-							  2, &_data);
+							  2, &hdata);
 				if (!data)
 					goto out;
 				off2 += ntohs(n->sel.offmask & *data) >>



^ permalink raw reply

* [PATCH 9/9] netem: restore no jitter option
From: Stephen Hemminger @ 2010-08-06 19:35 UTC (permalink / raw)
  To: David Miller; +Cc: netdev
In-Reply-To: <20100806193548.007978639@vyatta.com>

[-- Attachment #1: netem-queue.patch --]
[-- Type: text/plain, Size: 1366 bytes --]

Before netem was forced to be classless, it was possible to prevent
packet reordering by using a pure FIFO queue. This restores the option,
although now it has to be done as a module parameter.

Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>


--- a/net/sched/sch_netem.c	2010-08-02 15:02:36.654303844 -0700
+++ b/net/sched/sch_netem.c	2010-08-02 15:02:59.146459862 -0700
@@ -87,6 +87,10 @@ static inline struct netem_skb_cb *netem
 	return (struct netem_skb_cb *)qdisc_skb_cb(skb)->data;
 }
 
+static int jitter = 1;
+module_param(jitter, int, 0);
+MODULE_PARM_DESC(jitter, "reorder packets based on delay");
+
 /* init_crandom - initialize correlated random number generator
  * Use entropy source for initial seed.
  */
@@ -531,6 +535,7 @@ static struct Qdisc_ops tfifo_qdisc_ops 
 static int netem_init(struct Qdisc *sch, struct nlattr *opt)
 {
 	struct netem_sched_data *q = qdisc_priv(sch);
+	struct Qdisc_ops *ops = jitter ? &tfifo_qdisc_ops : &pfifo_qdisc_ops;
 	int ret;
 
 	if (!opt)
@@ -539,8 +544,7 @@ static int netem_init(struct Qdisc *sch,
 	qdisc_watchdog_init(&q->watchdog, sch);
 
 	q->qdisc = qdisc_create_dflt(qdisc_dev(sch), sch->dev_queue,
-				     &tfifo_qdisc_ops,
-				     TC_H_MAKE(sch->handle, 1));
+				     ops, TC_H_MAKE(sch->handle, 1));
 	if (!q->qdisc) {
 		pr_debug("netem: qdisc create failed\n");
 		return -ENOMEM;



^ permalink raw reply

* [PATCH 1/9] net classifier: dont allow filters on semi-classful qdisc
From: Stephen Hemminger @ 2010-08-06 19:35 UTC (permalink / raw)
  To: David Miller; +Cc: netdev
In-Reply-To: <20100806193548.007978639@vyatta.com>

[-- Attachment #1: cls-bind-tcf.patch --]
[-- Type: text/plain, Size: 3796 bytes --]

There are several qdisc which only support a single class (sfq, mq, tbf)
and the kernel would dereference a null pointer (bind_tcf), if a user
attempted to apply a filter one of these classes.

This patch changes the tcf_bind_filter to return an error in
these cases.

Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>


---
This needs to go in net-2.6 and stable.

 include/net/pkt_cls.h   |   12 +++++++++---
 net/sched/cls_basic.c   |    4 +++-
 net/sched/cls_fw.c      |    6 ++++--
 net/sched/cls_route.c   |    4 +++-
 net/sched/cls_tcindex.c |    4 +++-
 net/sched/cls_u32.c     |    4 +++-
 6 files changed, 25 insertions(+), 9 deletions(-)

--- a/include/net/pkt_cls.h	2010-08-06 11:51:18.903581556 -0700
+++ b/include/net/pkt_cls.h	2010-08-06 12:20:02.072241508 -0700
@@ -40,15 +40,21 @@ cls_set_class(struct tcf_proto *tp, unsi
 	return old_cl;
 }
 
-static inline void
+static inline int
 tcf_bind_filter(struct tcf_proto *tp, struct tcf_result *r, unsigned long base)
 {
+	const struct Qdisc_class_ops *cops = tp->q->ops->cl_ops;
 	unsigned long cl;
 
-	cl = tp->q->ops->cl_ops->bind_tcf(tp->q, base, r->classid);
+	if (!cops->bind_tcf)
+		return -EINVAL;
+
+	cl = cops->bind_tcf(tp->q, base, r->classid);
 	cl = cls_set_class(tp, &r->class, cl);
 	if (cl)
-		tp->q->ops->cl_ops->unbind_tcf(tp->q, cl);
+		cops->unbind_tcf(tp->q, cl);
+
+	return 0;
 }
 
 static inline void
--- a/net/sched/cls_basic.c	2010-08-06 11:51:18.923582342 -0700
+++ b/net/sched/cls_basic.c	2010-08-06 11:55:13.292553190 -0700
@@ -153,7 +153,9 @@ static inline int basic_set_parms(struct
 
 	if (tb[TCA_BASIC_CLASSID]) {
 		f->res.classid = nla_get_u32(tb[TCA_BASIC_CLASSID]);
-		tcf_bind_filter(tp, &f->res, base);
+		err = tcf_bind_filter(tp, &f->res, base);
+		if (err)
+			goto errout;
 	}
 
 	tcf_exts_change(tp, &f->exts, &e);
--- a/net/sched/cls_fw.c	2010-08-06 11:51:18.943583126 -0700
+++ b/net/sched/cls_fw.c	2010-08-06 11:55:39.085476144 -0700
@@ -206,10 +206,11 @@ fw_change_attrs(struct tcf_proto *tp, st
 	if (err < 0)
 		return err;
 
-	err = -EINVAL;
 	if (tb[TCA_FW_CLASSID]) {
 		f->res.classid = nla_get_u32(tb[TCA_FW_CLASSID]);
-		tcf_bind_filter(tp, &f->res, base);
+		err = tcf_bind_filter(tp, &f->res, base);
+		if (err)
+			goto errout;
 	}
 
 #ifdef CONFIG_NET_CLS_IND
@@ -220,6 +221,7 @@ fw_change_attrs(struct tcf_proto *tp, st
 	}
 #endif /* CONFIG_NET_CLS_IND */
 
+	err = -EINVAL;
 	if (tb[TCA_FW_MASK]) {
 		mask = nla_get_u32(tb[TCA_FW_MASK]);
 		if (mask != head->mask)
--- a/net/sched/cls_route.c	2010-08-06 11:51:18.959583757 -0700
+++ b/net/sched/cls_route.c	2010-08-06 11:55:50.077870498 -0700
@@ -412,7 +412,9 @@ static int route4_set_parms(struct tcf_p
 
 	if (tb[TCA_ROUTE4_CLASSID]) {
 		f->res.classid = nla_get_u32(tb[TCA_ROUTE4_CLASSID]);
-		tcf_bind_filter(tp, &f->res, base);
+		err = tcf_bind_filter(tp, &f->res, base);
+		if (err)
+			goto errout;
 	}
 
 	tcf_exts_change(tp, &f->exts, &e);
--- a/net/sched/cls_tcindex.c	2010-08-06 11:51:18.999585326 -0700
+++ b/net/sched/cls_tcindex.c	2010-08-06 11:56:01.486283847 -0700
@@ -295,7 +295,9 @@ tcindex_set_parms(struct tcf_proto *tp, 
 
 	if (tb[TCA_TCINDEX_CLASSID]) {
 		cr.res.classid = nla_get_u32(tb[TCA_TCINDEX_CLASSID]);
-		tcf_bind_filter(tp, &cr.res, base);
+		err = tcf_bind_filter(tp, &cr.res, base);
+		if (err)
+			goto errout;
 	}
 
 	tcf_exts_change(tp, &cr.exts, &e);
--- a/net/sched/cls_u32.c	2010-08-06 11:51:19.019586112 -0700
+++ b/net/sched/cls_u32.c	2010-08-06 11:56:12.390678703 -0700
@@ -528,7 +528,9 @@ static int u32_set_parms(struct tcf_prot
 	}
 	if (tb[TCA_U32_CLASSID]) {
 		n->res.classid = nla_get_u32(tb[TCA_U32_CLASSID]);
-		tcf_bind_filter(tp, &n->res, base);
+		err = tcf_bind_filter(tp, &n->res, base);
+		if (err)
+			goto errout;
 	}
 
 #ifdef CONFIG_NET_CLS_IND



^ permalink raw reply

* [PATCH 7/9] netem: dump distribution table
From: Stephen Hemminger @ 2010-08-06 19:35 UTC (permalink / raw)
  To: David Miller; +Cc: netdev
In-Reply-To: <20100806193548.007978639@vyatta.com>

[-- Attachment #1: netem-dump-dist.patch --]
[-- Type: text/plain, Size: 852 bytes --]

The existing netem API is not symmetric; the current distribution
table is not added to dump output.  Since distribution table is 
could be large, only add it if there space available (for compatiablity
with older applications).

Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>

--- a/net/sched/sch_netem.c	2010-08-03 08:29:43.926514463 -0700
+++ b/net/sched/sch_netem.c	2010-08-03 08:30:49.297380886 -0700
@@ -592,6 +592,13 @@ static int netem_dump(struct Qdisc *sch,
 	corrupt.correlation = q->corrupt_cor.rho;
 	NLA_PUT(skb, TCA_NETEM_CORRUPT, sizeof(corrupt), &corrupt);
 
+	/* dump table if exists and there is space available */
+	if (q->delay_dist) {
+		const struct disttable *d = q->delay_dist;
+		nla_put(skb, TCA_NETEM_DELAY_DIST,
+			d->size * sizeof(__s16), d->table);
+	}
+
 	return nla_nest_end(skb, nla);
 
 nla_put_failure:



^ permalink raw reply

* [PATCH 8/9] netem - revised correlated loss generator
From: Stephen Hemminger @ 2010-08-06 19:35 UTC (permalink / raw)
  To: David Miller; +Cc: netdev
In-Reply-To: <20100806193548.007978639@vyatta.com>

[-- Attachment #1: netem-clg.patch --]
[-- Type: text/plain, Size: 10275 bytes --]

Subject: [PATCH 8/9] netem: correlated loss genartor

This is a patch originated with Stefano Salsano and Fabio Ludovici.
It provides several alternative loss models for use with netem.
This patch adds two state machine based loss models.

To simplify the original code:
   * elminated the debugging messages and statistics
   * reformatted for clarity
   * changed API to nested attribute relating to loss
   * changed the table to always loop across bits
   * only allocate parameters needed

Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>

---
 include/linux/pkt_sched.h |   25 ++++
 net/sched/sch_netem.c     |  262 +++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 284 insertions(+), 3 deletions(-)

--- a/net/sched/sch_netem.c	2010-08-02 15:03:03.814479429 -0700
+++ b/net/sched/sch_netem.c	2010-08-02 15:03:04.746482821 -0700
@@ -47,6 +47,20 @@
 	 layering other disciplines.  It does not need to do bandwidth
 	 control either since that can be handled by using token
 	 bucket or other rate control.
+
+     Correlated Loss Generator models
+
+	Added generation of correlated loss according to the
+	"Gilbert-Elliot" model, a 4-state markov model.
+
+	References:
+	[1] NetemCLG Home http://netgroup.uniroma2.it/NetemCLG
+	[2] S. Salsano, F. Ludovici, A. Ordine, "Definition of a general
+	and intuitive loss model for packet networks and its implementation
+	in the Netem module in the Linux kernel", available in [1]
+
+	Authors: Stefano Salsano <stefano.salsano at uniroma2.it
+		 Fabio Ludovici <fabio.ludovici at yahoo.it>
 */
 
 struct netem_sched_data {
@@ -73,6 +87,26 @@ struct netem_sched_data {
 		u32  size;
 		s16 table[0];
 	} *delay_dist;
+
+	enum  {
+		CLG_RANDOM,
+		CLG_4_STATES,
+		CLG_GILB_ELL,
+	} loss_model;
+
+	/* Correlated Loss Generation models */
+	struct clgstate {
+		/* state of the Markov chain */
+		u8 state;
+
+		/* 4-states and Gilbert-Elliot models */
+		u32 a1;	/* p13 for 4-states or p for GE */
+		u32 a2;	/* p31 for 4-states or r for GE */
+		u32 a3;	/* p32 for 4-states or h for GE */
+		u32 a4;	/* p14 for 4-states or 1-k for GE */
+		u32 a5; /* p23 used only in 4-states */
+	} clg;
+
 };
 
 /* Time stamp put into socket buffer control block */
@@ -119,6 +153,122 @@ static u32 get_crandom(struct crndstate 
 	return answer;
 }
 
+/* loss_4state - 4-state model loss generator
+ * Generates losses according to the 4-state Markov chain adopted in
+ * the GI (General and Intuitive) loss model.
+ */
+static bool loss_4state(struct netem_sched_data *q)
+{
+	struct clgstate *clg = &q->clg;
+	u32 rnd = net_random();
+
+	/*
+	 * Makes a comparision between rnd and the transition
+	 * probabilities outgoing from the current state, then decides the
+	 * next state and if the next packet has to be transmitted or lost.
+	 * The four states correspond to:
+	 *   1 => successfully transmitted packets within a gap period
+	 *   4 => isolated losses within a gap period
+	 *   3 => lost packets within a burst period
+	 *   2 => successfully transmitted packets within a burst period
+	 */
+	switch (clg->state) {
+	case 1:
+		if (rnd < clg->a4) {
+			clg->state = 4;
+			return true;
+		} else if (clg->a4 < rnd && rnd < clg->a1) {
+			clg->state = 3;
+			return true;
+		} else if (clg->a1 < rnd)
+			clg->state = 1;
+
+		break;
+	case 2:
+		if (rnd < clg->a5) {
+			clg->state = 3;
+			return true;
+		} else
+			clg->state = 2;
+
+		break;
+	case 3:
+		if (rnd < clg->a3)
+			clg->state = 2;
+		else if (clg->a3 < rnd && rnd < clg->a2 + clg->a3) {
+			clg->state = 1;
+			return true;
+		} else if (clg->a2 + clg->a3 < rnd) {
+			clg->state = 3;
+			return true;
+		}
+		break;
+	case 4:
+		clg->state = 1;
+		break;
+	}
+
+	return false;
+}
+
+/* loss_gilb_ell - Gilbert-Elliot model loss generator
+ * Generates losses according to the Gilbert-Elliot loss model or
+ * its special cases  (Gilbert or Simple Gilbert)
+ *
+ * Makes a comparision between random number and the transition
+ * probabilities outgoing from the current state, then decides the
+ * next state. A second random number is extracted and the comparision
+ * with the loss probability of the current state decides if the next
+ * packet will be transmitted or lost.
+ */
+static bool loss_gilb_ell(struct netem_sched_data *q)
+{
+	struct clgstate *clg = &q->clg;
+
+	switch (clg->state) {
+	case 1:
+		if (net_random() < clg->a1)
+			clg->state = 2;
+		if (net_random() < clg->a4)
+			return true;
+	case 2:
+		if (net_random() < clg->a2)
+			clg->state = 1;
+		if (clg->a3 > net_random())
+			return true;
+	}
+
+	return false;
+}
+
+static bool loss_event(struct netem_sched_data *q)
+{
+	switch (q->loss_model) {
+	case CLG_RANDOM:
+		/* Random packet drop 0 => none, ~0 => all */
+		return q->loss && q->loss >= get_crandom(&q->loss_cor);
+
+	case CLG_4_STATES:
+		/* 4state loss model algorithm (used also for GI model)
+		* Extracts a value from the markov 4 state loss generator,
+		* if it is 1 drops a packet and if needed writes the event in
+		* the kernel logs
+		*/
+		return loss_4state(q);
+
+	case CLG_GILB_ELL:
+		/* Gilbert-Elliot loss model algorithm
+		* Extracts a value from the Gilbert-Elliot loss generator,
+		* if it is 1 drops a packet and if needed writes the event in
+		* the kernel logs
+		*/
+		return loss_gilb_ell(q);
+	}
+
+	return false;	/* not reached */
+}
+
+
 /* tabledist - return a pseudo-randomly distributed value with mean mu and
  * std deviation sigma.  Uses table lookup to approximate the desired
  * distribution, and a uniformly-distributed pseudo-random source.
@@ -171,8 +321,8 @@ static int netem_enqueue(struct sk_buff 
 	if (q->duplicate && q->duplicate >= get_crandom(&q->dup_cor))
 		++count;
 
-	/* Random packet drop 0 => none, ~0 => all */
-	if (q->loss && q->loss >= get_crandom(&q->loss_cor))
+	/* Drop packet? */
+	if (loss_event(q))
 		--count;
 
 	if (count == 0) {
@@ -370,10 +520,62 @@ static void get_corrupt(struct Qdisc *sc
 	init_crandom(&q->corrupt_cor, r->correlation);
 }
 
+static int get_loss_clg(struct Qdisc *sch, const struct nlattr *attr)
+{
+	struct netem_sched_data *q = qdisc_priv(sch);
+	struct nlattr *la;
+	int rem;
+
+	nla_for_each_nested(la, attr, rem) {
+		switch(nla_type(la)) {
+		case NETEM_LOSS_GI: {
+			const struct tc_netem_gimodel *gi = nla_data(la);
+
+			if (nla_len(la) != sizeof(struct tc_netem_gimodel)) {
+				pr_info("netem: incorrect gi model size\n");
+				return -EINVAL;
+			}
+
+			q->loss_model = CLG_4_STATES;
+
+			q->clg.state = 1;
+			q->clg.a1 = gi->p13;
+			q->clg.a2 = gi->p31;
+			q->clg.a3 = gi->p32;
+			q->clg.a4 = gi->p14;
+			q->clg.a5 = gi->p23;
+			break;
+		}
+		case NETEM_LOSS_GE: {
+			const struct tc_netem_gemodel *ge = nla_data(la);
+
+			if (nla_len(la) != sizeof(struct tc_netem_gemodel)) {
+				pr_info("netem: incorrect gi model size\n");
+				return -EINVAL;
+			}
+
+			q->loss_model = CLG_GILB_ELL;
+			q->clg.state = 1;
+			q->clg.a1 = ge->p;
+			q->clg.a2 = ge->r;
+			q->clg.a3 = ge->h;
+			q->clg.a4 = ge->k1;
+			break;
+		}
+		default:
+			pr_info("netem: unknown loss element %d\n",
+				nla_type(la));
+			return -EINVAL;
+		}
+	}
+	return 0;
+}
+
 static const struct nla_policy netem_policy[TCA_NETEM_MAX + 1] = {
 	[TCA_NETEM_CORR]	= { .len = sizeof(struct tc_netem_corr) },
 	[TCA_NETEM_REORDER]	= { .len = sizeof(struct tc_netem_reorder) },
 	[TCA_NETEM_CORRUPT]	= { .len = sizeof(struct tc_netem_corrupt) },
+	[TCA_NETEM_LOSS]	= { .type = NLA_NESTED },
 };
 
 static int parse_attr(struct nlattr *tb[], int maxtype, struct nlattr *nla,
@@ -441,10 +643,14 @@ static int netem_change(struct Qdisc *sc
 
 	if (tb[TCA_NETEM_CORRUPT])
 		get_corrupt(sch, tb[TCA_NETEM_CORRUPT]);
+
+	q->loss_model = CLG_RANDOM;
+	if (tb[TCA_NETEM_LOSS])
+		ret = get_loss_clg(sch, tb[TCA_NETEM_LOSS]);
  out:
 	sch_tree_unlock(sch);
 
-	return 0;
+	return ret;
 }
 
 /*
@@ -542,6 +748,7 @@ static int netem_init(struct Qdisc *sch,
 
 	qdisc_watchdog_init(&q->watchdog, sch);
 
+	q->loss_model = CLG_RANDOM;
 	q->qdisc = qdisc_create_dflt(qdisc_dev(sch), sch->dev_queue,
 				     ops, TC_H_MAKE(sch->handle, 1));
 	if (!q->qdisc) {
@@ -566,6 +773,52 @@ static void netem_destroy(struct Qdisc *
 	vfree(q->delay_dist);
 }
 
+static int dump_loss_model(const struct netem_sched_data *q, struct sk_buff *skb)
+{
+	struct nlattr *nest;
+
+	nest = nla_nest_start(skb, NETEM_LOSS_MAX);
+	if (nest == NULL)
+		goto nla_put_failure;
+
+	switch (q->loss_model) {
+	case CLG_RANDOM:
+		nla_nest_cancel(skb, nest);
+		return 0;	/* no data */
+
+	case CLG_4_STATES: {
+		struct tc_netem_gimodel gi = {
+			.p13 = q->clg.a1,
+			.p31 = q->clg.a2,
+			.p32 = q->clg.a3,
+			.p14 = q->clg.a4,
+			.p23 = q->clg.a5,
+		};
+
+		NLA_PUT(skb, NETEM_LOSS_GI, sizeof(gi), &gi);
+		break;
+	}
+	case CLG_GILB_ELL: {
+		struct tc_netem_gemodel ge = {
+			.p = q->clg.a1,
+			.r = q->clg.a2,
+			.h = q->clg.a3,
+			.k1 = q->clg.a4,
+		};
+
+		NLA_PUT(skb, NETEM_LOSS_GE, sizeof(ge), &ge);
+		break;
+	}
+	}
+
+	nla_nest_end(skb, nest);
+	return 0;
+
+nla_put_failure:
+	nla_nest_cancel(skb, nest);
+	return -1;
+}
+
 static int netem_dump(struct Qdisc *sch, struct sk_buff *skb)
 {
 	const struct netem_sched_data *q = qdisc_priv(sch);
@@ -603,6 +856,9 @@ static int netem_dump(struct Qdisc *sch,
 			d->size * sizeof(__s16), d->table);
 	}
 
+	if (dump_loss_model(q, skb) != 0)
+		goto nla_put_failure;
+
 	return nla_nest_end(skb, nla);
 
 nla_put_failure:
--- a/include/linux/pkt_sched.h	2010-08-02 15:03:03.038476487 -0700
+++ b/include/linux/pkt_sched.h	2010-08-02 15:03:04.746482821 -0700
@@ -435,6 +435,7 @@ enum {
 	TCA_NETEM_DELAY_DIST,
 	TCA_NETEM_REORDER,
 	TCA_NETEM_CORRUPT,
+	TCA_NETEM_LOSS,
 	__TCA_NETEM_MAX,
 };
 
@@ -465,6 +466,30 @@ struct tc_netem_corrupt {
 	__u32	correlation;
 };
 
+enum {
+	NETEM_LOSS_GI,		/* General Intuitive - 4 state model */
+	NETEM_LOSS_GE,		/* Gilbert Elliot models */
+	__NETEM_LOSS_MAX
+};
+#define NETEM_LOSS_MAX (__NETEM_LOSS_MAX - 1)
+
+/* State transition probablities for 4 state model */
+struct tc_netem_gimodel {
+	__u32	p13;
+	__u32	p31;
+	__u32	p32;
+	__u32	p14;
+	__u32	p23;
+};
+
+/* Gilbert-Elliot models */
+struct tc_netem_gemodel {
+	__u32 p;
+	__u32 r;
+	__u32 h;
+	__u32 k1;
+};
+
 #define NETEM_DIST_SCALE	8192
 #define NETEM_DIST_MAX		16384
 



^ permalink raw reply

* [PATCH 5/9] netem: cleanup dump code
From: Stephen Hemminger @ 2010-08-06 19:35 UTC (permalink / raw)
  To: David Miller; +Cc: netdev
In-Reply-To: <20100806193548.007978639@vyatta.com>

[-- Attachment #1: netem-dump.patch --]
[-- Type: text/plain, Size: 1021 bytes --]

Use nla_put_nested to update netlink attribute value.

Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>

--- a/net/sched/sch_netem.c	2010-08-03 08:28:28.031830483 -0700
+++ b/net/sched/sch_netem.c	2010-08-03 08:29:39.546593787 -0700
@@ -565,8 +565,7 @@ static void netem_destroy(struct Qdisc *
 static int netem_dump(struct Qdisc *sch, struct sk_buff *skb)
 {
 	const struct netem_sched_data *q = qdisc_priv(sch);
-	unsigned char *b = skb_tail_pointer(skb);
-	struct nlattr *nla = (struct nlattr *) b;
+	struct nlattr *nla = (struct nlattr *) skb_tail_pointer(skb);
 	struct tc_netem_qopt qopt;
 	struct tc_netem_corr cor;
 	struct tc_netem_reorder reorder;
@@ -593,12 +592,10 @@ static int netem_dump(struct Qdisc *sch,
 	corrupt.correlation = q->corrupt_cor.rho;
 	NLA_PUT(skb, TCA_NETEM_CORRUPT, sizeof(corrupt), &corrupt);
 
-	nla->nla_len = skb_tail_pointer(skb) - b;
-
-	return skb->len;
+	return nla_nest_end(skb, nla);
 
 nla_put_failure:
-	nlmsg_trim(skb, b);
+	nlmsg_trim(skb, nla);
 	return -1;
 }
 



^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox