Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH 2/2] net: calexdaxgmac: fixup endian issues after __raw IO function change
From: Ben Dooks @ 2013-02-11 18:27 UTC (permalink / raw)
  To: Ben Hutchings; +Cc: netdev, David S. Miller, Rob Herring, linux-arm-kernel
In-Reply-To: <1360606656.2701.18.camel@bwh-desktop.uk.solarflarecom.com>

On 11/02/13 18:17, Ben Hutchings wrote:
> On Sun, 2013-02-10 at 15:38 +0000, Ben Dooks wrote:
>> When changing to __raw acccessors in 0ec6d343f7bcf9e0944aa9ff65287b987ec00c0f
>> ("net: calxedaxgmac: use raw i/o accessors in rx and tx paths"), the driver
>> is now broken on big endian systems as the readl/writel have an implict
>> endian swap in them.
>>
>> Change all the places where the __raw calls are used to correctly convert
>> the constants in big endian format to the little endian data that the
>> peripheral expects to see.
>
> You are using le32_to_cpu() and cpu_to_le32() the wrong way round, and
> then putting casts on the wrong side, i.e. it should be:
>
> 	value = le32_to_cpu((__force __le32)__raw_readl(addr));
> 	__raw_writel((__force u32)cpu_to_le32(value), addr);
>
> (I do wonder why __raw I/O functions aren't declared to take/return __le
> types... it would avoid the need to cast altogether.)

Because they do things with the order the cpu is working in, the
read{x} and write{x} transfer cpu to bus-endian so returning an __le
type would not be correct.

I think you are right about the conversions, it is a headache trying
to think through.

It may be easier to provide _relaxed IO variants for all systems so
that we can avoid this in future.

>> Signed-off-by: Ben Dooks<ben.dooks@codethink.co.uk>
>> ---
>>   drivers/net/ethernet/calxeda/xgmac.c |   10 +++++++---
>>   1 file changed, 7 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/net/ethernet/calxeda/xgmac.c b/drivers/net/ethernet/calxeda/xgmac.c
>> index f91d9b2..96fd538 100644
>> --- a/drivers/net/ethernet/calxeda/xgmac.c
>> +++ b/drivers/net/ethernet/calxeda/xgmac.c
>> @@ -1202,7 +1202,8 @@ static int xgmac_poll(struct napi_struct *napi, int budget)
>>
>>   	if (work_done<  budget) {
>>   		napi_complete(napi);
>> -		__raw_writel(DMA_INTR_DEFAULT_MASK, priv->base + XGMAC_DMA_INTR_ENA);
>> +		__raw_writel(le32_to_cpu((__force __le32)DMA_INTR_DEFAULT_MASK),
>> +			     priv->base + XGMAC_DMA_INTR_ENA);
>>   	}
>>   	return work_done;
>>   }
>> @@ -1348,7 +1349,7 @@ static irqreturn_t xgmac_pmt_interrupt(int irq, void *dev_id)
>>   	void __iomem *ioaddr = priv->base;
>>
>>   	intr_status = __raw_readl(ioaddr + XGMAC_INT_STAT);
>> -	if (intr_status&  XGMAC_INT_STAT_PMT) {
>> +	if (intr_status&  le32_to_cpu((__force __le32)XGMAC_INT_STAT_PMT)) {
>>   		netdev_dbg(priv->dev, "received Magic frame\n");
>>   		/* clear the PMT bits 5 and 6 by reading the PMT */
>>   		readl(ioaddr + XGMAC_PMT);
>> @@ -1369,6 +1370,8 @@ static irqreturn_t xgmac_interrupt(int irq, void *dev_id)
>>   	intr_status&= __raw_readl(priv->base + XGMAC_DMA_INTR_ENA);
>>   	__raw_writel(intr_status, priv->base + XGMAC_DMA_STATUS);
>>
>> +	intr_status = (__force u32)cpu_to_le32(intr_status);
>
> Perhaps intr_status should be split into two variables, for native and
> little-endian order.
>
> Ben.

That would be a possibility, although it would end up changing more code.

>>   	/* It displays the DMA process states (CSR5 register) */
>>   	/* ABNORMAL interrupts */
>>   	if (unlikely(intr_status&  DMA_STATUS_AIS)) {
>> @@ -1403,7 +1406,8 @@ static irqreturn_t xgmac_interrupt(int irq, void *dev_id)
>>
>>   	/* TX/RX NORMAL interrupts */
>>   	if (intr_status&  (DMA_STATUS_RI | DMA_STATUS_TU | DMA_STATUS_TI)) {
>> -		__raw_writel(DMA_INTR_ABNORMAL, priv->base + XGMAC_DMA_INTR_ENA);
>> +		__raw_writel(le32_to_cpu((__force __le32)DMA_INTR_ABNORMAL),
>> +			     priv->base + XGMAC_DMA_INTR_ENA);
>>   		napi_schedule(&priv->napi);
>>   	}
>>
>


-- 
Ben Dooks				http://www.codethink.co.uk/
Senior Engineer				Codethink - Providing Genius

^ permalink raw reply

* [PATCH] bridge: set priority of STP packets
From: Stephen Hemminger @ 2013-02-11 18:22 UTC (permalink / raw)
  To: David Miller; +Cc: netdev

Spanning Tree Protocol packets should have always been marked as
control packets, this causes them to get queued in the high prirority
FIFO. As Radia Perlman mentioned in her LCA talk, STP dies if bridge
gets overloaded and can't communicate. This is a long-standing bug back
to the first versions of Linux bridge.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>

---
Please consider adding to  stable as well.

--- a/net/bridge/br_stp_bpdu.c	2013-01-16 09:47:00.599539375 -0800
+++ b/net/bridge/br_stp_bpdu.c	2013-02-11 08:13:56.315979316 -0800
@@ -16,6 +16,7 @@
 #include <linux/etherdevice.h>
 #include <linux/llc.h>
 #include <linux/slab.h>
+#include <linux/pkt_sched.h>
 #include <net/net_namespace.h>
 #include <net/llc.h>
 #include <net/llc_pdu.h>
@@ -40,6 +41,7 @@ static void br_send_bpdu(struct net_brid
 
 	skb->dev = p->dev;
 	skb->protocol = htons(ETH_P_802_2);
+	skb->priority = TC_PRIO_CONTROL;
 
 	skb_reserve(skb, LLC_RESERVE);
 	memcpy(__skb_put(skb, length), data, length);

^ permalink raw reply

* Re: [PATCH 2/2] net: calexdaxgmac: fixup endian issues after __raw IO function change
From: Ben Hutchings @ 2013-02-11 18:17 UTC (permalink / raw)
  To: Ben Dooks; +Cc: netdev, David S. Miller, Rob Herring, linux-arm-kernel
In-Reply-To: <1360510721-17860-3-git-send-email-ben.dooks@codethink.co.uk>

On Sun, 2013-02-10 at 15:38 +0000, Ben Dooks wrote:
> When changing to __raw acccessors in 0ec6d343f7bcf9e0944aa9ff65287b987ec00c0f
> ("net: calxedaxgmac: use raw i/o accessors in rx and tx paths"), the driver
> is now broken on big endian systems as the readl/writel have an implict
> endian swap in them.
> 
> Change all the places where the __raw calls are used to correctly convert
> the constants in big endian format to the little endian data that the
> peripheral expects to see.

You are using le32_to_cpu() and cpu_to_le32() the wrong way round, and
then putting casts on the wrong side, i.e. it should be:

	value = le32_to_cpu((__force __le32)__raw_readl(addr));
	__raw_writel((__force u32)cpu_to_le32(value), addr);

(I do wonder why __raw I/O functions aren't declared to take/return __le
types... it would avoid the need to cast altogether.)

> Signed-off-by: Ben Dooks <ben.dooks@codethink.co.uk>
> ---
>  drivers/net/ethernet/calxeda/xgmac.c |   10 +++++++---
>  1 file changed, 7 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/net/ethernet/calxeda/xgmac.c b/drivers/net/ethernet/calxeda/xgmac.c
> index f91d9b2..96fd538 100644
> --- a/drivers/net/ethernet/calxeda/xgmac.c
> +++ b/drivers/net/ethernet/calxeda/xgmac.c
> @@ -1202,7 +1202,8 @@ static int xgmac_poll(struct napi_struct *napi, int budget)
>  
>  	if (work_done < budget) {
>  		napi_complete(napi);
> -		__raw_writel(DMA_INTR_DEFAULT_MASK, priv->base + XGMAC_DMA_INTR_ENA);
> +		__raw_writel(le32_to_cpu((__force __le32)DMA_INTR_DEFAULT_MASK),
> +			     priv->base + XGMAC_DMA_INTR_ENA);
>  	}
>  	return work_done;
>  }
> @@ -1348,7 +1349,7 @@ static irqreturn_t xgmac_pmt_interrupt(int irq, void *dev_id)
>  	void __iomem *ioaddr = priv->base;
>  
>  	intr_status = __raw_readl(ioaddr + XGMAC_INT_STAT);
> -	if (intr_status & XGMAC_INT_STAT_PMT) {
> +	if (intr_status & le32_to_cpu((__force __le32)XGMAC_INT_STAT_PMT)) {
>  		netdev_dbg(priv->dev, "received Magic frame\n");
>  		/* clear the PMT bits 5 and 6 by reading the PMT */
>  		readl(ioaddr + XGMAC_PMT);
> @@ -1369,6 +1370,8 @@ static irqreturn_t xgmac_interrupt(int irq, void *dev_id)
>  	intr_status &= __raw_readl(priv->base + XGMAC_DMA_INTR_ENA);
>  	__raw_writel(intr_status, priv->base + XGMAC_DMA_STATUS);
>  
> +	intr_status = (__force u32)cpu_to_le32(intr_status);

Perhaps intr_status should be split into two variables, for native and
little-endian order.

Ben.

>  	/* It displays the DMA process states (CSR5 register) */
>  	/* ABNORMAL interrupts */
>  	if (unlikely(intr_status & DMA_STATUS_AIS)) {
> @@ -1403,7 +1406,8 @@ static irqreturn_t xgmac_interrupt(int irq, void *dev_id)
>  
>  	/* TX/RX NORMAL interrupts */
>  	if (intr_status & (DMA_STATUS_RI | DMA_STATUS_TU | DMA_STATUS_TI)) {
> -		__raw_writel(DMA_INTR_ABNORMAL, priv->base + XGMAC_DMA_INTR_ENA);
> +		__raw_writel(le32_to_cpu((__force __le32)DMA_INTR_ABNORMAL),
> +			     priv->base + XGMAC_DMA_INTR_ENA);
>  		napi_schedule(&priv->napi);
>  	}
>  

-- 
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.

^ permalink raw reply

* Re: [PATCH] ip.7: Improve explanation about calling listen or connect
From: Flavio Leitner @ 2013-02-11 17:50 UTC (permalink / raw)
  To: Michael Kerrisk (man-pages); +Cc: Peter Schiffer, linux-man, netdev
In-Reply-To: <CAKgNAkjq3xwO7ZDH5twZdW-Onbwoim5asETPV-Zs6x73twSd7g@mail.gmail.com>

On Sun, Feb 10, 2013 at 03:00:03AM +0100, Michael Kerrisk (man-pages) wrote:
> On Wed, Jun 6, 2012 at 4:44 PM, Flavio Leitner <fbl@redhat.com> wrote:
> >
> > Hi,
> >
> > Could someone tell me what's the patch current state?
> > It has been a month already with no feedback.
> > thanks,
> > fbl
> 
> Following up, long after the fact.
> 
> Flavio, I had no time pack then to review this patch... One problem
> is, you never gave any rationle for the change ("Improve explanation
> of..." is not a rationale -- I need to know *why* you think the
> changes are needed.)

Because the current explanation is not detailed enough and/or the way
it is written may lead to a wrong interpretation, specially for non-English
users.  Therefore, it should be improved adding supporting details
and a better writing to clarify each case.

The patch adds the missing details and clarifies each use case.

Thanks,
fbl

> 
> Thanks,
> 
> Michael
> 
> 
> > On Fri, 25 May 2012 13:02:48 +0200
> > Peter Schiffer <pschiffe@redhat.com> wrote:
> >
> >> Hi Michael,
> >>
> >> do you have any comments for this update? Or do you need some supporting
> >> info?
> >>
> >> peter
> >>
> >> On 05/09/2012 02:30 PM, Flavio Leitner wrote:
> >> > Signed-off-by: Flavio Leitner<fbl@redhat.com>
> >> > ---
> >> >   man7/ip.7 |   15 +++++++++------
> >> >   1 files changed, 9 insertions(+), 6 deletions(-)
> >> >
> >> > diff --git a/man7/ip.7 b/man7/ip.7
> >> > index 9f560df..84fe32d 100644
> >> > --- a/man7/ip.7
> >> > +++ b/man7/ip.7
> >> > @@ -69,12 +69,11 @@ For
> >> >   you may specify a valid IANA IP protocol defined in
> >> >   RFC\ 1700 assigned numbers.
> >> >   .PP
> >> > -.\" FIXME ip current does an autobind in listen, but I'm not sure
> >> > -.\" if that should be documented.
> >> >   When a process wants to receive new incoming packets or connections, it
> >> >   should bind a socket to a local interface address using
> >> >   .BR bind (2).
> >> > -Only one IP socket may be bound to any given local (address, port) pair.
> >> > +In this case, only one IP socket may be bound to any given local
> >> > +(address, port) pair.
> >> >   When
> >> >   .B INADDR_ANY
> >> >   is specified in the bind call, the socket will be bound to
> >> > @@ -82,10 +81,14 @@ is specified in the bind call, the socket will be bound to
> >> >   local interfaces.
> >> >   When
> >> >   .BR listen (2)
> >> > -or
> >> > +is called on an unbound socket, the socket is automatically bound
> >> > +to a random free port with the local address set to
> >> > +.BR INADDR_ANY .
> >> > +When
> >> >   .BR connect (2)
> >> > -are called on an unbound socket, it is automatically bound to a
> >> > -random free port with the local address set to
> >> > +is called on an unbound socket, the socket is automatically bound
> >> > +to a random free port or an usable shared port with the local address
> >> > +set to
> >> >   .BR INADDR_ANY .
> >> >
> >> >   A TCP local socket address that has been bound is unavailable for
> >
> 
> 
> 
> -- 
> Michael Kerrisk
> Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
> Author of "The Linux Programming Interface"; http://man7.org/tlpi/
> 

-- 
fbl

^ permalink raw reply

* RE: atl1c DMA-API mapping errors in 3.8-rc6+
From: Huang, Xiong @ 2013-02-11 18:03 UTC (permalink / raw)
  To: Josh Boyer, Jay Cliburn, Chris Snook
  Cc: David S. Miller, netdev@vger.kernel.org, sgruszka@redhat.com,
	nic-devel
In-Reply-To: <157393863283F442885425D2C4542856489C67E4@nasanexd02f.na.qualcomm.com>

Josh

     Would you pls confirm if my patch fix this issue ? I have no platform on hand now and the office is closed due to CNY .

Thanks
Xiong

^ permalink raw reply

* RE: [PATCH v4 1/9] rdma/cm: define native IB address
From: Hefty, Sean @ 2013-02-11 18:02 UTC (permalink / raw)
  To: linux-rdma@vger.kernel.org, netdev@vger.kernel.org,
	David Miller (davem@davemloft.net), Roland Dreier
In-Reply-To: <1358891797-14625-2-git-send-email-sean.hefty@intel.com>

> Define AF_IB and sockaddr_ib to allow the rdma_cm to use native IB
> addressing.
> 
> Signed-off-by: Sean Hefty <sean.hefty@intel.com>
> ---
>  include/linux/socket.h |    2 +
>  include/rdma/ib.h      |   89 ++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 91 insertions(+), 0 deletions(-)
>  create mode 100644 include/rdma/ib.h
> 
> diff --git a/include/linux/socket.h b/include/linux/socket.h
> index 9a546ff..17a33f7 100644
> --- a/include/linux/socket.h
> +++ b/include/linux/socket.h
> @@ -167,6 +167,7 @@ struct ucred {
>  #define AF_PPPOX	24	/* PPPoX sockets		*/
>  #define AF_WANPIPE	25	/* Wanpipe API Sockets */
>  #define AF_LLC		26	/* Linux LLC			*/
> +#define AF_IB		27	/* Native InfiniBand address	*/

...

> diff --git a/include/rdma/ib.h b/include/rdma/ib.h

...

> +struct sockaddr_ib {
> +	unsigned short int	sib_family;	/* AF_IB */
> +	__be16			sib_pkey;
> +	__be32			sib_flowinfo;
> +	struct ib_addr		sib_addr;
> +	__be64			sib_sid;
> +	__be64			sib_sid_mask;
> +	__u64			sib_scope_id;
> +};

Dave/Roland/anyone, is there any feedback on this approach?

If there's hesitation to add new address families to socket.h, I could instead use definitions local to the rdma_cm.  This has the potential to result in conflicts if the rdma_cm is expanded for other address families, though such conflicts seem unlikely.

- Sean

^ permalink raw reply

* Re: Issue with Micrel PCI Network Driver.
From: Ben Hutchings @ 2013-02-11 17:47 UTC (permalink / raw)
  To: joseph.lutz; +Cc: netdev
In-Reply-To: <1360604764.2701.10.camel@bwh-desktop.uk.solarflarecom.com>

On Mon, 2013-02-11 at 17:46 +0000, Ben Hutchings wrote:
> On Fri, 2013-02-08 at 17:17 -0600, Joseph Lutz wrote:
> > I am having an issue with one of the network interface drivers. The 
> > driver in question is 'drivers/net/ethernet/micrel/ksz884x.c', the 
> > driver for the Micrel-Kendin device 8841.
> > I am trying to get systemd to rename the three network interfaces in my 
> > embedded atom system. I have one of the interfaces being renamed (an 
> > Intel Corporation 82574L), but the two Micrel interfaces are not being 
> > renamed. I traced this down to the driver not populating the 
> > /sys/devices/pci* information. Instead it places the driver into 
> > /sys/devices/virtual/net/.
> [...]
> 
> Right, this driver doesn't specify the parent device (PCI device) for
> the net devices it creates.
> 
> All you should need to is add:
> 	SET_NETDEV_DEV(dev, pdev);
> underneath the call to alloc_etherdev().

Or rather:
	SET_NETDEV_DEV(dev, &pdev->dev);

Ben.

-- 
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.

^ permalink raw reply

* Re: Issue with Micrel PCI Network Driver.
From: Ben Hutchings @ 2013-02-11 17:46 UTC (permalink / raw)
  To: joseph.lutz; +Cc: netdev
In-Reply-To: <51158774.8080405@novatechweb.com>

On Fri, 2013-02-08 at 17:17 -0600, Joseph Lutz wrote:
> I am having an issue with one of the network interface drivers. The 
> driver in question is 'drivers/net/ethernet/micrel/ksz884x.c', the 
> driver for the Micrel-Kendin device 8841.
> I am trying to get systemd to rename the three network interfaces in my 
> embedded atom system. I have one of the interfaces being renamed (an 
> Intel Corporation 82574L), but the two Micrel interfaces are not being 
> renamed. I traced this down to the driver not populating the 
> /sys/devices/pci* information. Instead it places the driver into 
> /sys/devices/virtual/net/.
[...]

Right, this driver doesn't specify the parent device (PCI device) for
the net devices it creates.

All you should need to is add:
	SET_NETDEV_DEV(dev, pdev);
underneath the call to alloc_etherdev().

Ben.

-- 
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.

^ permalink raw reply

* RE: [net-next 04/10] igb: Fix for sparse warning in igb_get_i2c_client
From: Wyborny, Carolyn @ 2013-02-11 17:27 UTC (permalink / raw)
  To: Ben Hutchings, Kirsher, Jeffrey T
  Cc: davem@davemloft.net, netdev@vger.kernel.org, gospo@redhat.com,
	sassmann@redhat.com
In-Reply-To: <1360602355.2701.5.camel@bwh-desktop.uk.solarflarecom.com>

> -----Original Message-----
> From: netdev-owner@vger.kernel.org [mailto:netdev-owner@vger.kernel.org]
> On Behalf Of Ben Hutchings
> Sent: Monday, February 11, 2013 9:06 AM
> To: Kirsher, Jeffrey T; Wyborny, Carolyn
> Cc: davem@davemloft.net; netdev@vger.kernel.org; gospo@redhat.com;
> sassmann@redhat.com
> Subject: Re: [net-next 04/10] igb: Fix for sparse warning in igb_get_i2c_client
> 
> On Fri, 2013-02-08 at 02:39 -0800, Jeff Kirsher wrote:
> > From: Carolyn Wyborny <carolyn.wyborny@intel.com>
> >
> > This patch changes definition of i2c_client in igb_get_i2c_client to
> > static to prevent sparse warning.
> 
> So, in order to fix the warning:
> 
> drivers/net/ethernet/intel/igb/igb_main.c:7611:19: warning: symbol
> 'igb_get_i2c_client' was not declared. Should it be static?
> 
> you don't touch the function declaration, but instead make a local variable
> static.  This doesn't fix the warning, but does introduce a race condition...
> 
> Ben.
> 
> > Reported-by: Fengguang Wu <fengguang.wu@intel.com>
> > Signed-off-by: Carolyn Wyborny <carolyn.wyborny@intel.com>
> > Tested-by: Aaron Brown <aaron.f.brown@intel.com>
> > Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
> > ---
> >  drivers/net/ethernet/intel/igb/igb_main.c | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> >
> > diff --git a/drivers/net/ethernet/intel/igb/igb_main.c
> > b/drivers/net/ethernet/intel/igb/igb_main.c
> > index c19a35c..ebf8384 100644
> > --- a/drivers/net/ethernet/intel/igb/igb_main.c
> > +++ b/drivers/net/ethernet/intel/igb/igb_main.c
> > @@ -7732,7 +7732,7 @@ igb_get_i2c_client(struct igb_adapter *adapter,
> > u8 dev_addr)  {
> >  	ulong flags;
> >  	struct igb_i2c_client_list *client_list;
> > -	struct i2c_client *client = NULL;
> > +	static struct i2c_client *client;
> >  	struct i2c_board_info client_info = {
> >  		I2C_BOARD_INFO("igb", 0x00),
> >  	};
> 
> --
> Ben Hutchings, Staff Engineer, Solarflare Not speaking for my employer; that's
> the marketing department's job.
> They asked us to note that Solarflare product names are trademarked.
> 
> --
> 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

Yes, my mistake in taking a quick suggestion without enough evaluation.  I'm in the process of completely redoing this to not allocate clients on the fly which will fully fix this problem and the initial one.

Thanks,

Carolyn

^ permalink raw reply

* Re: [PATCH iproute2] Use pkg-config to obtain xtables.h path
From: Stephen Hemminger @ 2013-02-11 17:25 UTC (permalink / raw)
  To: Benjamin Poirier; +Cc: netdev
In-Reply-To: <1360185564-29094-1-git-send-email-bpoirier@suse.de>

On Wed,  6 Feb 2013 16:19:24 -0500
Benjamin Poirier <bpoirier@suse.de> wrote:

> On openSUSE 12.2 (at least) xtables.h is not installed in the system-wide
> include dir but in /usr/include/iptables-1.4.16.3/. This results in the
> following build failure:
> em_ipset.c:26:21: fatal error: xtables.h: No such file or directory
> 
> Other includers of xtables.h already call out to pkg-config

Accepted

^ permalink raw reply

* Re: [PATCH v2 5/5] iproute2: improved error messages
From: Stephen Hemminger @ 2013-02-11 17:24 UTC (permalink / raw)
  To: Kees van Reeuwijk; +Cc: netdev
In-Reply-To: <E1U3o4C-0000c3-OZ@babylon.few.vu.nl>

On Fri, 08 Feb 2013 14:32:36 +0100
Kees van Reeuwijk <kees.van.reeuwijk@gmail.com> wrote:

> From: Kees van Reeuwijk <reeuwijk@few.vu.nl>
> 
> This patch improves many error messages as follows:
> - For incorrect parameters, show the value of the offending parameter, rather than just say that it is incorrect
> - Rephrased messages for clarity
> - Rephrased to more `mainstream' english
> 
> 
> Signed-off-by: Kees van Reeuwijk <reeuwijk@few.vu.nl>
> 
> ---

All five patches accepted.

^ permalink raw reply

* Re: [PATCH net-next] ethtool: fix sparse warning
From: Ben Hutchings @ 2013-02-11 17:21 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: David Miller, netdev
In-Reply-To: <20130211082228.1f1d7f88@nehalam.linuxnetplumber.net>

On Mon, 2013-02-11 at 08:22 -0800, Stephen Hemminger wrote:
> Fixes sparse complaints about dropping __user in casts.
>  warning: cast removes address space of expression
> 
> Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
Acked-by: Ben Hutchings <bhutchings@solarflare.com>

> 
> --- a/net/socket.c	2013-02-11 08:17:45.081011548 -0800
> +++ b/net/socket.c	2013-02-11 08:19:52.743355382 -0800
> @@ -2837,7 +2837,7 @@ static int ethtool_ioctl(struct net *net
>  	}
>  
>  	ifr = compat_alloc_user_space(buf_size);
> -	rxnfc = (void *)ifr + ALIGN(sizeof(struct ifreq), 8);
> +	rxnfc = (void __user *)ifr + ALIGN(sizeof(struct ifreq), 8);
>  
>  	if (copy_in_user(&ifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ))
>  		return -EFAULT;
> @@ -2861,12 +2861,12 @@ static int ethtool_ioctl(struct net *net
>  			offsetof(struct ethtool_rxnfc, fs.ring_cookie));
>  
>  		if (copy_in_user(rxnfc, compat_rxnfc,
> -				 (void *)(&rxnfc->fs.m_ext + 1) -
> -				 (void *)rxnfc) ||
> +				 (void __user *)(&rxnfc->fs.m_ext + 1) -
> +				 (void __user *)rxnfc) ||
>  		    copy_in_user(&rxnfc->fs.ring_cookie,
>  				 &compat_rxnfc->fs.ring_cookie,
> -				 (void *)(&rxnfc->fs.location + 1) -
> -				 (void *)&rxnfc->fs.ring_cookie) ||
> +				 (void __user *)(&rxnfc->fs.location + 1) -
> +				 (void __user *)&rxnfc->fs.ring_cookie) ||
>  		    copy_in_user(&rxnfc->rule_cnt, &compat_rxnfc->rule_cnt,
>  				 sizeof(rxnfc->rule_cnt)))
>  			return -EFAULT;
> @@ -2878,12 +2878,12 @@ static int ethtool_ioctl(struct net *net
>  
>  	if (convert_out) {
>  		if (copy_in_user(compat_rxnfc, rxnfc,
> -				 (const void *)(&rxnfc->fs.m_ext + 1) -
> -				 (const void *)rxnfc) ||
> +				 (const void __user *)(&rxnfc->fs.m_ext + 1) -
> +				 (const void __user *)rxnfc) ||
>  		    copy_in_user(&compat_rxnfc->fs.ring_cookie,
>  				 &rxnfc->fs.ring_cookie,
> -				 (const void *)(&rxnfc->fs.location + 1) -
> -				 (const void *)&rxnfc->fs.ring_cookie) ||
> +				 (const void __user *)(&rxnfc->fs.location + 1) -
> +				 (const void __user *)&rxnfc->fs.ring_cookie) ||
>  		    copy_in_user(&compat_rxnfc->rule_cnt, &rxnfc->rule_cnt,
>  				 sizeof(rxnfc->rule_cnt)))
>  			return -EFAULT;

-- 
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.

^ permalink raw reply

* Re: [PATCH iproute2] iplink_vlan: Add flag for Multiple VLAN Registration Protocol (MVRP)
From: Stephen Hemminger @ 2013-02-11 17:18 UTC (permalink / raw)
  To: David Ward; +Cc: netdev
In-Reply-To: <1360379828-16302-4-git-send-email-david.ward@ll.mit.edu>

The current iproute2 repository is open form 3.8 related features
changes at this time.

Please resubmit during 3.9 merge window, because I may forget this
patch otherwise.

^ permalink raw reply

* Re: IPv6 Address Resolution in Linux 2.6.27
From: Ben Hutchings @ 2013-02-11 17:13 UTC (permalink / raw)
  To: Mudric, Dusan (Dusan); +Cc: netdev@vger.kernel.org
In-Reply-To: <9142206A0C5BF24CB22755C8EC422E45384AEC24@AZ-US1EXMB03.global.avaya.com>

On Fri, 2013-02-08 at 20:23 +0000, Mudric, Dusan (Dusan) wrote:
> Hi,
> 
> I experience Address Resolution problem while using Linux 2.6.27.
[...]

This is quite an old version.  You should re-test on a current version
or, if this is a distribution kernel, use the distribution's support
channels.

Ben.

-- 
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.

^ permalink raw reply

* Re: [net-next 04/10] igb: Fix for sparse warning in igb_get_i2c_client
From: Ben Hutchings @ 2013-02-11 17:05 UTC (permalink / raw)
  To: Jeff Kirsher, Carolyn Wyborny; +Cc: davem, netdev, gospo, sassmann
In-Reply-To: <1360319958-10497-5-git-send-email-jeffrey.t.kirsher@intel.com>

On Fri, 2013-02-08 at 02:39 -0800, Jeff Kirsher wrote:
> From: Carolyn Wyborny <carolyn.wyborny@intel.com>
> 
> This patch changes definition of i2c_client in igb_get_i2c_client to static
> to prevent sparse warning.

So, in order to fix the warning:

drivers/net/ethernet/intel/igb/igb_main.c:7611:19: warning: symbol 'igb_get_i2c_client' was not declared. Should it be static?

you don't touch the function declaration, but instead make a local
variable static.  This doesn't fix the warning, but does introduce a
race condition...

Ben.

> Reported-by: Fengguang Wu <fengguang.wu@intel.com>
> Signed-off-by: Carolyn Wyborny <carolyn.wyborny@intel.com>
> Tested-by: Aaron Brown <aaron.f.brown@intel.com>
> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
> ---
>  drivers/net/ethernet/intel/igb/igb_main.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
> index c19a35c..ebf8384 100644
> --- a/drivers/net/ethernet/intel/igb/igb_main.c
> +++ b/drivers/net/ethernet/intel/igb/igb_main.c
> @@ -7732,7 +7732,7 @@ igb_get_i2c_client(struct igb_adapter *adapter, u8 dev_addr)
>  {
>  	ulong flags;
>  	struct igb_i2c_client_list *client_list;
> -	struct i2c_client *client = NULL;
> +	static struct i2c_client *client;
>  	struct i2c_board_info client_info = {
>  		I2C_BOARD_INFO("igb", 0x00),
>  	};

-- 
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.

^ permalink raw reply

* Re: kernel 3.7.6, l2tp, qdisc_tx circular locking
From: Eric Dumazet @ 2013-02-11 16:52 UTC (permalink / raw)
  To: Denys Fedoryshchenko; +Cc: netdev, davem, linux-kernel
In-Reply-To: <a0cb5c50926ca95b0ad64bde7535efa6@visp.net.lb>

On Mon, 2013-02-11 at 14:28 +0200, Denys Fedoryshchenko wrote:
> Hello,
> 
> I was running l2tp connections with accel-ppp as test, and got this:
> Nothing unusual in kernel, x86_64, 2 CPU, gentoo, gcc 4.6.3
> If you need more information - let me know please.
> 
> 
> [ 7575.690820]
> [ 7575.690834] ======================================================
> [ 7575.690850] [ INFO: possible circular locking dependency detected ]
> [ 7575.690870] 3.7.6-wbuild #6 Not tainted
> [ 7575.690882] -------------------------------------------------------
> [ 7575.690901] swapper/1/0 is trying to acquire lock:
> [ 7575.690916]  (dev->qdisc_tx_busylock ?: &qdisc_tx_busylock){+.-...}, 
> at: [<ffffffff812d8087>] dev_queue_xmit+0x90/0x34d
> [ 7575.690972]
> [ 7575.690972] but task is already holding lock:
> [ 7575.690988]  (l2tp_sock){+.-...}, at: [<ffffffffa05b0b2b>] 
> l2tp_xmit_skb+0x1b8/0x453 [l2tp_core]
> [ 7575.691037]
> [ 7575.691037] which lock already depends on the new lock.
> [ 7575.691037]
> [ 7575.691059]
> [ 7575.691059] the existing dependency chain (in reverse order) is:
> [ 7575.691082]
> [ 7575.691082] -> #4 (l2tp_sock){+.-...}:
> [ 7575.691119]        [<ffffffff81066c17>] lock_acquire+0x7e/0x94
> [ 7575.691141]        [<ffffffff81361ce8>] _raw_spin_lock+0x2c/0x3b
> [ 7575.691615]        [<ffffffffa05b0b2b>] l2tp_xmit_skb+0x1b8/0x453 
> [l2tp_core]
> [ 7575.692088]        [<ffffffffa05be93b>] pppol2tp_xmit+0x122/0x15d 
> [l2tp_ppp]
> [ 7575.692560]        [<ffffffff8126ec23>] ppp_channel_push+0x48/0xad
> [ 7575.693031]        [<ffffffff8126ed5d>] ppp_write+0xc1/0xcd
> [ 7575.693499]        [<ffffffff810c5c6a>] vfs_write+0xa3/0xca
> [ 7575.693969]        [<ffffffff810c5e24>] sys_write+0x54/0x78
> [ 7575.694436]        [<ffffffff81362e52>] 
> system_call_fastpath+0x16/0x1b
> [ 7575.694907]
> [ 7575.694907] -> #3 (&(&pch->downl)->rlock){+.-...}:
> [ 7575.695830]        [<ffffffff81066c17>] lock_acquire+0x7e/0x94
> [ 7575.696297]        [<ffffffff81361ece>] _raw_spin_lock_bh+0x31/0x40
> [ 7575.696767]        [<ffffffff8126c39a>] ppp_push+0x69/0x507
> [ 7575.697235]        [<ffffffff8126e9e3>] ppp_xmit_process+0x44a/0x4ff
> [ 7575.697703]        [<ffffffff8126ed53>] ppp_write+0xb7/0xcd
> [ 7575.698170]        [<ffffffff810c5c6a>] vfs_write+0xa3/0xca
> [ 7575.698638]        [<ffffffff810c5e24>] sys_write+0x54/0x78
> [ 7575.699105]        [<ffffffff81362e52>] 
> system_call_fastpath+0x16/0x1b
> [ 7575.699575]
> [ 7575.699575] -> #2 (&(&ppp->wlock)->rlock){+.-...}:
> [ 7575.700498]        [<ffffffff81066c17>] lock_acquire+0x7e/0x94
> [ 7575.700966]        [<ffffffff81361ece>] _raw_spin_lock_bh+0x31/0x40
> [ 7575.701435]        [<ffffffff8126e5bc>] ppp_xmit_process+0x23/0x4ff
> [ 7575.701905]        [<ffffffff8126ebc0>] ppp_start_xmit+0x128/0x143
> [ 7575.702373]        [<ffffffff812d7d3f>] 
> dev_hard_start_xmit+0x267/0x371
> [ 7575.702843]        [<ffffffff812eab61>] sch_direct_xmit+0x70/0x14f
> [ 7575.703312]        [<ffffffff812d8149>] dev_queue_xmit+0x152/0x34d
> [ 7575.703869]        [<ffffffff812de128>] neigh_direct_output+0xc/0xe
> [ 7575.704336]        [<ffffffff812fe943>] 
> ip_finish_output2+0x268/0x2e5
> [ 7575.704806]        [<ffffffff812ff8c8>] ip_finish_output+0x46/0x4b
> [ 7575.705274]        [<ffffffff812fffd4>] ip_output+0x63/0x67
> [ 7575.705742]        [<ffffffff812fcfce>] ip_forward_finish+0x6b/0x70
> [ 7575.706211]        [<ffffffff812fd1d8>] ip_forward+0x205/0x285
> [ 7575.706678]        [<ffffffff812fbaf1>] ip_rcv_finish+0x2b3/0x2cb
> [ 7575.707147]        [<ffffffff812fbb55>] 
> NF_HOOK.constprop.8+0x4c/0x55
> [ 7575.707617]        [<ffffffff812fbec6>] ip_rcv+0x22b/0x259
> [ 7575.708084]        [<ffffffff812d5649>] 
> __netif_receive_skb+0x458/0x4c5
> [ 7575.708556]        [<ffffffff812d5844>] netif_receive_skb+0x56/0x8b
> [ 7575.709026]        [<ffffffff812d69ae>] napi_skb_finish+0x21/0x53
> [ 7575.709495]        [<ffffffff812d6a0a>] napi_gro_receive+0x2a/0x2f
> [ 7575.709963]        [<ffffffff812618d6>] igb_poll+0x634/0x909
> [ 7575.710430]        [<ffffffff812d5e3c>] net_rx_action+0xa3/0x1b9
> [ 7575.710897]        [<ffffffff81030204>] __do_softirq+0xa8/0x157
> [ 7575.711368]        [<ffffffff81363f8c>] call_softirq+0x1c/0x26
> [ 7575.711835]        [<ffffffff81003f45>] do_softirq+0x38/0x83
> [ 7575.712304]        [<ffffffff810303b1>] irq_exit+0x4e/0xad
> [ 7575.712771]        [<ffffffff81003c55>] do_IRQ+0x89/0xa0
> [ 7575.713236]        [<ffffffff813625ef>] ret_from_intr+0x0/0x13
> [ 7575.713703]        [<ffffffff812b8b92>] cpuidle_enter+0x12/0x14
> [ 7575.714171]        [<ffffffff812b8fb8>] 
> cpuidle_enter_state+0x10/0x39
> [ 7575.714642]        [<ffffffff812b905f>] cpuidle_idle_call+0x7e/0xa4
> [ 7575.715112]        [<ffffffff81009bd2>] cpu_idle+0x58/0xa2
> [ 7575.715579]        [<ffffffff81355e88>] start_secondary+0x188/0x18d
> [ 7575.716049]
> [ 7575.716049] -> #1 (_xmit_PPP#2){+.-...}:
> [ 7575.716977]        [<ffffffff81066c17>] lock_acquire+0x7e/0x94
> [ 7575.717443]        [<ffffffff81361ce8>] _raw_spin_lock+0x2c/0x3b
> [ 7575.718000]        [<ffffffff812eab3a>] sch_direct_xmit+0x49/0x14f
> [ 7575.718467]        [<ffffffff812d8149>] dev_queue_xmit+0x152/0x34d
> [ 7575.718933]        [<ffffffff812de128>] neigh_direct_output+0xc/0xe
> [ 7575.719403]        [<ffffffff812fe943>] 
> ip_finish_output2+0x268/0x2e5
> [ 7575.719873]        [<ffffffff812ff8c8>] ip_finish_output+0x46/0x4b
> [ 7575.720344]        [<ffffffff812fffd4>] ip_output+0x63/0x67
> [ 7575.720812]        [<ffffffff812fcfce>] ip_forward_finish+0x6b/0x70
> [ 7575.721282]        [<ffffffff812fd1d8>] ip_forward+0x205/0x285
> [ 7575.721750]        [<ffffffff812fbaf1>] ip_rcv_finish+0x2b3/0x2cb
> [ 7575.722219]        [<ffffffff812fbb55>] 
> NF_HOOK.constprop.8+0x4c/0x55
> [ 7575.722689]        [<ffffffff812fbec6>] ip_rcv+0x22b/0x259
> [ 7575.723158]        [<ffffffff812d5649>] 
> __netif_receive_skb+0x458/0x4c5
> [ 7575.723628]        [<ffffffff812d5844>] netif_receive_skb+0x56/0x8b
> [ 7575.724098]        [<ffffffff812d69ae>] napi_skb_finish+0x21/0x53
> [ 7575.724566]        [<ffffffff812d6a0a>] napi_gro_receive+0x2a/0x2f
> [ 7575.725034]        [<ffffffff812618d6>] igb_poll+0x634/0x909
> [ 7575.725501]        [<ffffffff812d5e3c>] net_rx_action+0xa3/0x1b9
> [ 7575.725970]        [<ffffffff81030204>] __do_softirq+0xa8/0x157
> [ 7575.726439]        [<ffffffff81363f8c>] call_softirq+0x1c/0x26
> [ 7575.726907]        [<ffffffff81003f45>] do_softirq+0x38/0x83
> [ 7575.727375]        [<ffffffff810303b1>] irq_exit+0x4e/0xad
> [ 7575.727841]        [<ffffffff81003c55>] do_IRQ+0x89/0xa0
> [ 7575.728308]        [<ffffffff813625ef>] ret_from_intr+0x0/0x13
> [ 7575.728779]        [<ffffffff812b8b92>] cpuidle_enter+0x12/0x14
> [ 7575.740374]        [<ffffffff812b8fb8>] 
> cpuidle_enter_state+0x10/0x39
> [ 7575.740846]        [<ffffffff812b905f>] cpuidle_idle_call+0x7e/0xa4
> [ 7575.741315]        [<ffffffff81009bd2>] cpu_idle+0x58/0xa2
> [ 7575.741784]        [<ffffffff81355e88>] start_secondary+0x188/0x18d
> [ 7575.742256]
> [ 7575.742256] -> #0 (dev->qdisc_tx_busylock ?: 
> &qdisc_tx_busylock){+.-...}:
> [ 7575.743190]        [<ffffffff81066567>] __lock_acquire+0xaf1/0xdce
> [ 7575.743661]        [<ffffffff81066c17>] lock_acquire+0x7e/0x94
> [ 7575.744129]        [<ffffffff81361ce8>] _raw_spin_lock+0x2c/0x3b
> [ 7575.744605]        [<ffffffff812d8087>] dev_queue_xmit+0x90/0x34d
> [ 7575.745077]        [<ffffffff812fe935>] 
> ip_finish_output2+0x25a/0x2e5
> [ 7575.745548]        [<ffffffff812ff8c8>] ip_finish_output+0x46/0x4b
> [ 7575.746017]        [<ffffffff812fffd4>] ip_output+0x63/0x67
> [ 7575.746570]        [<ffffffff812fe549>] dst_output+0x18/0x1c
> [ 7575.747036]        [<ffffffff812ff972>] ip_local_out+0x1b/0x1f
> [ 7575.747502]        [<ffffffff812ffc49>] ip_queue_xmit+0x2d3/0x337
> [ 7575.747970]        [<ffffffffa05b0d77>] l2tp_xmit_skb+0x404/0x453 
> [l2tp_core]
> [ 7575.748442]        [<ffffffffa05be93b>] pppol2tp_xmit+0x122/0x15d 
> [l2tp_ppp]
> [ 7575.748916]        [<ffffffff8126c3b0>] ppp_push+0x7f/0x507
> [ 7575.749383]        [<ffffffff8126e9e3>] ppp_xmit_process+0x44a/0x4ff
> [ 7575.749852]        [<ffffffff8126ebc0>] ppp_start_xmit+0x128/0x143
> [ 7575.750320]        [<ffffffff812d7dc7>] 
> dev_hard_start_xmit+0x2ef/0x371
> [ 7575.750790]        [<ffffffff812eab61>] sch_direct_xmit+0x70/0x14f
> [ 7575.751258]        [<ffffffff812d8149>] dev_queue_xmit+0x152/0x34d
> [ 7575.751727]        [<ffffffff812de128>] neigh_direct_output+0xc/0xe
> [ 7575.752196]        [<ffffffff812fe943>] 
> ip_finish_output2+0x268/0x2e5
> [ 7575.752667]        [<ffffffff812ff8c8>] ip_finish_output+0x46/0x4b
> [ 7575.753136]        [<ffffffff812fffd4>] ip_output+0x63/0x67
> [ 7575.753604]        [<ffffffff812fcfce>] ip_forward_finish+0x6b/0x70
> [ 7575.754073]        [<ffffffff812fd1d8>] ip_forward+0x205/0x285
> [ 7575.754541]        [<ffffffff812fbaf1>] ip_rcv_finish+0x2b3/0x2cb
> [ 7575.755009]        [<ffffffff812fbb55>] 
> NF_HOOK.constprop.8+0x4c/0x55
> [ 7575.755478]        [<ffffffff812fbec6>] ip_rcv+0x22b/0x259
> [ 7575.755945]        [<ffffffff812d5649>] 
> __netif_receive_skb+0x458/0x4c5
> [ 7575.756414]        [<ffffffff812d5844>] netif_receive_skb+0x56/0x8b
> [ 7575.756884]        [<ffffffff812d594a>] napi_gro_complete+0xd1/0xdc
> [ 7575.757354]        [<ffffffff812d5d2f>] napi_gro_flush+0x4c/0x68
> [ 7575.757822]        [<ffffffff812d5d64>] napi_complete+0x19/0x4e
> [ 7575.758290]        [<ffffffff81261967>] igb_poll+0x6c5/0x909
> [ 7575.758759]        [<ffffffff812d5e3c>] net_rx_action+0xa3/0x1b9
> [ 7575.759228]        [<ffffffff81030204>] __do_softirq+0xa8/0x157
> [ 7575.759697]        [<ffffffff81363f8c>] call_softirq+0x1c/0x26
> [ 7575.760164]        [<ffffffff81003f45>] do_softirq+0x38/0x83
> [ 7575.760721]        [<ffffffff810303b1>] irq_exit+0x4e/0xad
> [ 7575.761184]        [<ffffffff81003c55>] do_IRQ+0x89/0xa0
> [ 7575.761648]        [<ffffffff813625ef>] ret_from_intr+0x0/0x13
> [ 7575.762117]        [<ffffffff812b8b92>] cpuidle_enter+0x12/0x14
> [ 7575.762585]        [<ffffffff812b8fb8>] 
> cpuidle_enter_state+0x10/0x39
> [ 7575.763056]        [<ffffffff812b905f>] cpuidle_idle_call+0x7e/0xa4
> [ 7575.763525]        [<ffffffff81009bd2>] cpu_idle+0x58/0xa2
> [ 7575.763992]        [<ffffffff81355e88>] start_secondary+0x188/0x18d
> [ 7575.764462]
> [ 7575.764462] other info that might help us debug this:
> [ 7575.764462]
> [ 7575.765817] Chain exists of:
> [ 7575.765817]   dev->qdisc_tx_busylock ?: &qdisc_tx_busylock --> 
> &(&pch->downl)->rlock --> l2tp_sock
> [ 7575.765817]
> [ 7575.767652]  Possible unsafe locking scenario:
> [ 7575.767652]
> [ 7575.768560]        CPU0                    CPU1
> [ 7575.769021]        ----                    ----
> [ 7575.769482]   lock(l2tp_sock);
> [ 7575.769948]                                
> lock(&(&pch->downl)->rlock);
> [ 7575.770422]                                lock(l2tp_sock);
> [ 7575.770895]   lock(dev->qdisc_tx_busylock ?: &qdisc_tx_busylock);
> [ 7575.771368]
> [ 7575.771368]  *** DEADLOCK ***
> [ 7575.771368]
> [ 7575.772824] 10 locks held by swapper/1/0:
> [ 7575.773283]  #0:  (rcu_read_lock){.+.+..}, at: [<ffffffff812d2b10>] 
> rcu_lock_acquire+0x0/0x29
> [ 7575.774223]  #1:  (rcu_read_lock_bh){.+....}, at: 
> [<ffffffff812fe4b1>] rcu_lock_acquire+0x0/0x29
> [ 7575.775248]  #2:  (rcu_read_lock_bh){.+....}, at: 
> [<ffffffff812d2b10>] rcu_lock_acquire+0x0/0x29
> [ 7575.776184]  #3:  (_xmit_PPP#2){+.-...}, at: [<ffffffff812eab3a>] 
> sch_direct_xmit+0x49/0x14f
> [ 7575.777133]  #4:  (&(&ppp->wlock)->rlock){+.-...}, at: 
> [<ffffffff8126e5bc>] ppp_xmit_process+0x23/0x4ff
> [ 7575.778072]  #5:  (&(&pch->downl)->rlock){+.-...}, at: 
> [<ffffffff8126c39a>] ppp_push+0x69/0x507
> [ 7575.779010]  #6:  (l2tp_sock){+.-...}, at: [<ffffffffa05b0b2b>] 
> l2tp_xmit_skb+0x1b8/0x453 [l2tp_core]
> [ 7575.779951]  #7:  (rcu_read_lock){.+.+..}, at: [<ffffffff812fe4b1>] 
> rcu_lock_acquire+0x0/0x29
> [ 7575.780891]  #8:  (rcu_read_lock_bh){.+....}, at: 
> [<ffffffff812fe4b1>] rcu_lock_acquire+0x0/0x29
> [ 7575.781830]  #9:  (rcu_read_lock_bh){.+....}, at: 
> [<ffffffff812d2b10>] rcu_lock_acquire+0x0/0x29
> [ 7575.782769]
> [ 7575.782769] stack backtrace:
> [ 7575.783674] Pid: 0, comm: swapper/1 Not tainted 3.7.6-wbuild #6
> [ 7575.784139] Call Trace:
> [ 7575.784596]  <IRQ>  [<ffffffff8135b67b>] 
> print_circular_bug+0x1f8/0x209
> [ 7575.785075]  [<ffffffff81066567>] __lock_acquire+0xaf1/0xdce
> [ 7575.785540]  [<ffffffff81066c17>] lock_acquire+0x7e/0x94
> [ 7575.786004]  [<ffffffff812d8087>] ? dev_queue_xmit+0x90/0x34d
> [ 7575.786470]  [<ffffffff812d2b10>] ? dev_seq_stop+0xb/0xb
> [ 7575.786935]  [<ffffffff81361ce8>] _raw_spin_lock+0x2c/0x3b
> [ 7575.787398]  [<ffffffff812d8087>] ? dev_queue_xmit+0x90/0x34d
> [ 7575.787864]  [<ffffffff812d8087>] dev_queue_xmit+0x90/0x34d
> [ 7575.788328]  [<ffffffff812fe935>] ip_finish_output2+0x25a/0x2e5
> [ 7575.788794]  [<ffffffff812ff8c8>] ip_finish_output+0x46/0x4b
> [ 7575.789347]  [<ffffffff812fffd4>] ip_output+0x63/0x67
> [ 7575.789808]  [<ffffffff812fe549>] dst_output+0x18/0x1c
> [ 7575.790271]  [<ffffffff812ff972>] ip_local_out+0x1b/0x1f
> [ 7575.790735]  [<ffffffff812ffc49>] ip_queue_xmit+0x2d3/0x337
> [ 7575.791200]  [<ffffffffa05b0d77>] l2tp_xmit_skb+0x404/0x453 
> [l2tp_core]
> [ 7575.791668]  [<ffffffffa05be93b>] pppol2tp_xmit+0x122/0x15d 
> [l2tp_ppp]
> [ 7575.792135]  [<ffffffff8126c3b0>] ppp_push+0x7f/0x507
> [ 7575.792600]  [<ffffffff81362259>] ? 
> _raw_spin_unlock_irqrestore+0x3a/0x41
> [ 7575.793069]  [<ffffffff8106700b>] ? 
> trace_hardirqs_on_caller+0x107/0x158
> [ 7575.793536]  [<ffffffff81067069>] ? trace_hardirqs_on+0xd/0xf
> [ 7575.794002]  [<ffffffff8126e9e3>] ppp_xmit_process+0x44a/0x4ff
> [ 7575.794467]  [<ffffffff8126ebc0>] ppp_start_xmit+0x128/0x143
> [ 7575.794933]  [<ffffffff812d7dc7>] dev_hard_start_xmit+0x2ef/0x371
> [ 7575.795400]  [<ffffffff812eab61>] sch_direct_xmit+0x70/0x14f
> [ 7575.795864]  [<ffffffff812d8149>] dev_queue_xmit+0x152/0x34d
> [ 7575.796328]  [<ffffffff812de128>] neigh_direct_output+0xc/0xe
> [ 7575.796795]  [<ffffffff812fe943>] ip_finish_output2+0x268/0x2e5
> [ 7575.797261]  [<ffffffff812ff8c8>] ip_finish_output+0x46/0x4b
> [ 7575.797726]  [<ffffffff812fffd4>] ip_output+0x63/0x67
> [ 7575.798190]  [<ffffffff812fcfce>] ip_forward_finish+0x6b/0x70
> [ 7575.798656]  [<ffffffff812fd1d8>] ip_forward+0x205/0x285
> [ 7575.799120]  [<ffffffff812fbaf1>] ip_rcv_finish+0x2b3/0x2cb
> [ 7575.799586]  [<ffffffff812fb83e>] ? skb_dst.isra.7+0x58/0x58
> [ 7575.800051]  [<ffffffff812fbb55>] NF_HOOK.constprop.8+0x4c/0x55
> [ 7575.800517]  [<ffffffff812fbec6>] ip_rcv+0x22b/0x259
> [ 7575.800981]  [<ffffffff812d5649>] __netif_receive_skb+0x458/0x4c5
> [ 7575.801448]  [<ffffffff812d5844>] netif_receive_skb+0x56/0x8b
> [ 7575.801913]  [<ffffffff812d594a>] napi_gro_complete+0xd1/0xdc
> [ 7575.802378]  [<ffffffff812d5d2f>] napi_gro_flush+0x4c/0x68
> [ 7575.802843]  [<ffffffff812d2af8>] ? rcu_read_unlock+0x1c/0x1e
> [ 7575.803395]  [<ffffffff812d5d64>] napi_complete+0x19/0x4e
> [ 7575.803856]  [<ffffffff81261967>] igb_poll+0x6c5/0x909
> [ 7575.804317]  [<ffffffff8106602f>] ? __lock_acquire+0x5b9/0xdce
> [ 7575.804783]  [<ffffffff812d5e3c>] net_rx_action+0xa3/0x1b9
> [ 7575.805247]  [<ffffffff810301cc>] ? __do_softirq+0x70/0x157
> [ 7575.805712]  [<ffffffff81030204>] __do_softirq+0xa8/0x157
> [ 7575.806176]  [<ffffffff81363f8c>] call_softirq+0x1c/0x26
> [ 7575.806641]  [<ffffffff81003f45>] do_softirq+0x38/0x83
> [ 7575.807106]  [<ffffffff810303b1>] irq_exit+0x4e/0xad
> [ 7575.807569]  [<ffffffff81003c55>] do_IRQ+0x89/0xa0
> [ 7575.808032]  [<ffffffff813625ef>] common_interrupt+0x6f/0x6f
> [ 7575.808495]  <EOI>  [<ffffffff8136269c>] ? 
> retint_restore_args+0xe/0xe
> [ 7575.808974]  [<ffffffff81197d0c>] ? intel_idle+0xeb/0x111
> [ 7575.809443]  [<ffffffff81197d05>] ? intel_idle+0xe4/0x111
> [ 7575.809909]  [<ffffffff812b8b92>] cpuidle_enter+0x12/0x14
> [ 7575.810373]  [<ffffffff812b8fb8>] cpuidle_enter_state+0x10/0x39
> [ 7575.810840]  [<ffffffff812b905f>] cpuidle_idle_call+0x7e/0xa4
> [ 7575.811306]  [<ffffffff81009bd2>] cpu_idle+0x58/0xa2
> [ 7575.811770]  [<ffffffff81355e88>] start_secondary+0x188/0x18d

Hmm...

It seems keeping the socket locked is not needed and painful for
LOCKDEP.

Could you try the following patch ?


diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c
index dcfd64e..7baf88f 100644
--- a/net/l2tp/l2tp_core.c
+++ b/net/l2tp/l2tp_core.c
@@ -1251,8 +1251,11 @@ int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb, int hdr_len
 	}
 
 	l2tp_skb_set_owner_w(skb, sk);
+	bh_unlock_sock(sk);
 
 	l2tp_xmit_core(session, skb, fl, data_len);
+	return ret;
+
 out_unlock:
 	bh_unlock_sock(sk);
 

^ permalink raw reply related

* [PATCH net-next] mrp: make mrp_rcv static
From: Stephen Hemminger @ 2013-02-11 16:25 UTC (permalink / raw)
  To: David Miller, David Ward; +Cc: netdev

Sparse spotted local function that could be static.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>


--- a/net/802/mrp.c	2013-02-11 08:13:10.324575963 -0800
+++ b/net/802/mrp.c	2013-02-11 08:23:13.076756457 -0800
@@ -744,8 +744,8 @@ static int mrp_pdu_parse_msg(struct mrp_
 	return 0;
 }
 
-int mrp_rcv(struct sk_buff *skb, struct net_device *dev,
-	    struct packet_type *pt, struct net_device *orig_dev)
+static int mrp_rcv(struct sk_buff *skb, struct net_device *dev,
+		   struct packet_type *pt, struct net_device *orig_dev)
 {
 	struct mrp_application *appl = container_of(pt, struct mrp_application,
 						    pkttype);

^ permalink raw reply

* [PATCH net-next] ethtool: fix sparse warning
From: Stephen Hemminger @ 2013-02-11 16:22 UTC (permalink / raw)
  To: David Miller, Ben Hutchings; +Cc: netdev

Fixes sparse complaints about dropping __user in casts.
 warning: cast removes address space of expression

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>


--- a/net/socket.c	2013-02-11 08:17:45.081011548 -0800
+++ b/net/socket.c	2013-02-11 08:19:52.743355382 -0800
@@ -2837,7 +2837,7 @@ static int ethtool_ioctl(struct net *net
 	}
 
 	ifr = compat_alloc_user_space(buf_size);
-	rxnfc = (void *)ifr + ALIGN(sizeof(struct ifreq), 8);
+	rxnfc = (void __user *)ifr + ALIGN(sizeof(struct ifreq), 8);
 
 	if (copy_in_user(&ifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ))
 		return -EFAULT;
@@ -2861,12 +2861,12 @@ static int ethtool_ioctl(struct net *net
 			offsetof(struct ethtool_rxnfc, fs.ring_cookie));
 
 		if (copy_in_user(rxnfc, compat_rxnfc,
-				 (void *)(&rxnfc->fs.m_ext + 1) -
-				 (void *)rxnfc) ||
+				 (void __user *)(&rxnfc->fs.m_ext + 1) -
+				 (void __user *)rxnfc) ||
 		    copy_in_user(&rxnfc->fs.ring_cookie,
 				 &compat_rxnfc->fs.ring_cookie,
-				 (void *)(&rxnfc->fs.location + 1) -
-				 (void *)&rxnfc->fs.ring_cookie) ||
+				 (void __user *)(&rxnfc->fs.location + 1) -
+				 (void __user *)&rxnfc->fs.ring_cookie) ||
 		    copy_in_user(&rxnfc->rule_cnt, &compat_rxnfc->rule_cnt,
 				 sizeof(rxnfc->rule_cnt)))
 			return -EFAULT;
@@ -2878,12 +2878,12 @@ static int ethtool_ioctl(struct net *net
 
 	if (convert_out) {
 		if (copy_in_user(compat_rxnfc, rxnfc,
-				 (const void *)(&rxnfc->fs.m_ext + 1) -
-				 (const void *)rxnfc) ||
+				 (const void __user *)(&rxnfc->fs.m_ext + 1) -
+				 (const void __user *)rxnfc) ||
 		    copy_in_user(&compat_rxnfc->fs.ring_cookie,
 				 &rxnfc->fs.ring_cookie,
-				 (const void *)(&rxnfc->fs.location + 1) -
-				 (const void *)&rxnfc->fs.ring_cookie) ||
+				 (const void __user *)(&rxnfc->fs.location + 1) -
+				 (const void __user *)&rxnfc->fs.ring_cookie) ||
 		    copy_in_user(&compat_rxnfc->rule_cnt, &rxnfc->rule_cnt,
 				 sizeof(rxnfc->rule_cnt)))
 			return -EFAULT;

^ permalink raw reply

* [PATCH v2 3/5] iproute2: clarifications in the tc-hfsc.7 man page
From: Kees van Reeuwijk @ 2013-02-11 16:11 UTC (permalink / raw)
  To: netdev

From: Kees van Reeuwijk <reeuwijk@few.vu.nl>

Improved man page as follows:
- Use more `mainstream' english
- Rephrased for clarity
- Use standard notation for units



Signed-off-by: Kees van Reeuwijk <reeuwijk@few.vu.nl>

---


 tc-hfsc.7 |  247 +++++++++++++++++++++++++++++++------------------------------
 1 files changed, 124 insertions(+), 123 deletions(-)

diff --git a/man/man7/tc-hfsc.7 b/man/man7/tc-hfsc.7
index d4e63f2..ca04961 100644
--- a/man/man7/tc-hfsc.7
+++ b/man/man7/tc-hfsc.7
@@ -4,13 +4,12 @@ tc-hfcs \- Hierarchical Fair Service Curve
 .
 .SH "HISTORY & INTRODUCTION"
 .
-HFSC \- \fBHierarchical Fair Service Curve\fR was first presented at
+HFSC (Hierarchical Fair Service Curve) is a network packet scheduling algorithm that was first presented at
 SIGCOMM'97. Developed as a part of ALTQ (ALTernative Queuing) on NetBSD, found
 its way quickly to other BSD systems, and then a few years ago became part of
 the linux kernel. Still, it's not the most popular scheduling algorithm \-
-especially if compared to HTB \- and it's not well documented from enduser's
-perspective. This introduction aims to explain how HFSC works without
-going to deep into math side of things (although some if it will be
+especially if compared to HTB \- and it's not well documented for the enduser. This introduction aims to explain how HFSC works without using
+too much math (although some math it will be
 inevitable).
 
 In short HFSC aims to:
@@ -30,10 +29,10 @@ service provided during linksharing
 .
 The main "selling" point of HFSC is feature \fB(1)\fR, which is achieved by
 using nonlinear service curves (more about what it actually is later). This is
-particularly useful in VoIP or games, where not only guarantee of consistent
-bandwidth is important, but initial delay of a data stream as well. Note that
+particularly useful in VoIP or games, where not only a guarantee of consistent
+bandwidth is important, but also limiting the initial delay of a data stream. Note that
 it matters only for leaf classes (where the actual queues are) \- thus class
-hierarchy is ignored in realtime case.
+hierarchy is ignored in the realtime case.
 
 Feature \fB(2)\fR is well, obvious \- any algorithm featuring class hierarchy
 (such as HTB or CBQ) strives to achieve that. HFSC does that well, although
@@ -44,8 +43,8 @@ Feature \fB(3)\fR is mentioned due to the nature of the problem. There may be
 situations where it's either not possible to guarantee service of all curves at
 the same time, and/or it's impossible to do so fairly. Both will be explained
 later. Note that this is mainly related to interior (aka aggregate) classes, as
-the leafs are already handled by \fB(1)\fR. Still \- it's perfectly possible to
-create a leaf class w/o realtime service, and in such case \- the caveats will
+the leafs are already handled by \fB(1)\fR. Still, it's perfectly possible to
+create a leaf class without realtime service, and in such a case the caveats will
 naturally extend to leaf classes as well.
 
 .SH ABBREVIATIONS
@@ -62,21 +61,22 @@ SC \- service curve
 .SH "BASICS OF HFSC"
 .
 To understand how HFSC works, we must first introduce a service curve.
-Overall, it's a nondecreasing function of some time unit, returning amount of
-service (allowed or allocated amount of bandwidth) by some specific point in
-time. The purpose of it should be subconsciously obvious \- if a class was
-allowed to transfer not less than the amount specified by its service curve \-
-then service curve is not violated.
-
-Still \- we need more elaborate criterion than just the above (although in
-most generic case it can be reduced to it). The criterion has to take two
+Overall, it's a nondecreasing function of some time unit, returning the amount
+of
+service (an allowed or allocated amount of bandwidth) at some specific point in
+time. The purpose of it should be subconsciously obvious: if a class was
+allowed to transfer not less than the amount specified by its service curve,
+then the service curve is not violated.
+
+Still, we need more elaborate criterion than just the above (although in
+the most generic case it can be reduced to it). The criterion has to take two
 things into account:
 .
 .RS 4
 .IP \(bu 4
 idling periods
 .IP \(bu
-ability to "look back", so if during current active period service curve is violated, maybe it
+the ability to "look back", so if during current active period the service curve is violated, maybe it
 isn't if we count excess bandwidth received during earlier active period(s)
 .RE
 .PP
@@ -102,9 +102,9 @@ as in (a), but with a larger gap
 .RE
 .
 .PP
-Consider \fB(a)\fR \- if the service received during both periods meets
-\fB(1)\fR, then all is good. But what if it doesn't do so during the 2nd
-period ? If the amount of service received during the 1st period is bigger
+Consider \fB(a)\fR: if the service received during both periods meets
+\fB(1)\fR, then all is well. But what if it doesn't do so during the 2nd
+period? If the amount of service received during the 1st period is larger
 than the service curve, then it might compensate for smaller service during
 the 2nd period \fIand\fR the gap \- if the gap is small enough.
 
@@ -172,42 +172,43 @@ curves and the above "utility" functions.
 .SH "REALTIME CRITERION"
 .
 RT criterion \fIignores class hierarchy\fR and guarantees precise bandwidth and
-delay allocation. We say that packet is eligible for sending, when current real
-time is bigger than eligible time. From all packets eligible, the one most
-suited for sending, is the one with the smallest deadline time. Sounds simply,
-but consider following example:
+delay allocation. We say that a packet is eligible for sending, when the
+current real
+time is later than the eligible time of the packet. From all eligible packets, the one most
+suited for sending is the one with the shortest deadline time. This sounds
+simple, but consider the following example:
 
-Interface 10mbit, two classes, both with two\-piece linear service curves:
+Interface 10Mbit, two classes, both with two\-piece linear service curves:
 .RS 4
 .IP \(bu 4
-1st class \- 2mbit for 100ms, then 7mbit (convex \- 1st slope < 2nd slope)
+1st class \- 2Mbit for 100ms, then 7Mbit (convex \- 1st slope < 2nd slope)
 .IP \(bu
-2nd class \- 7mbit for 100ms, then 2mbit (concave \- 1st slope > 2nd slope)
+2nd class \- 7Mbit for 100ms, then 2Mbit (concave \- 1st slope > 2nd slope)
 .RE
 .PP
 Assume for a moment, that we only use D() for both finding eligible packets,
 and choosing the most fitting one, thus eligible time would be computed as
 D^(\-1)(w) and deadline time would be computed as D^(\-1)(w+l). If the 2nd
 class starts sending packets 1 second after the 1st class, it's of course
-impossible to guarantee 14mbit, as the interface capability is only 10mbit.
+impossible to guarantee 14Mbit, as the interface capability is only 10Mbit.
 The only workaround in this scenario is to allow the 1st class to send the
 packets earlier that would normally be allowed. That's where separate E() comes
 to help. Putting all the math aside (see HFSC paper for details), E() for RT
 concave service curve is just like D(), but for the RT convex service curve \-
 it's constructed using \fIonly\fR RT service curve's 2nd slope (in our example
-\- 7mbit).
+ 7Mbit).
 
 The effect of such E() \- packets will be sent earlier, and at the same time
-D() \fIwill\fR be updated \- so current deadline time calculated from it will
-be bigger. Thus, when the 2nd class starts sending packets later, both the 1st
-and the 2nd class will be eligible, but the 2nd session's deadline time will be
-smaller and its packets will be sent first. When the 1st class becomes idle at
-some later point, the 2nd class will be able to "buffer" up again for later
-active period of the 1st class.
+D() \fIwill\fR be updated \- so the current deadline time calculated from it
+will be later. Thus, when the 2nd class starts sending packets later, both
+the 1st and the 2nd class will be eligible, but the 2nd session's deadline
+time will be smaller and its packets will be sent first. When the 1st class
+becomes idle at some later point, the 2nd class will be able to "buffer" up
+again for later active period of the 1st class.
 
 A short remark \- in a situation, where the total amount of bandwidth
-available on the interface is bigger than the allocated total realtime parts
-(imagine interface 10 mbit, but 1mbit/2mbit and 2mbit/1mbit classes), the sole
+available on the interface is larger than the allocated total realtime parts
+(imagine a 10 Mbit interface, but 1Mbit/2Mbit and 2Mbit/1Mbit classes), the sole
 speed of the interface could suffice to guarantee the times.
 
 Important part of RT criterion is that apart from updating its D() and E(),
@@ -233,18 +234,18 @@ real time and virtual time \- the decision is based solely on direct comparison
 of virtual times of all active subclasses \- the one with the smallest vt wins
 and gets scheduled. One immediate conclusion from this fact is that absolute
 values don't matter \- only ratios between them (so for example, two children
-classes with simple linear 1mbit service curves will get the same treatment
-from LS criterion's perspective, as if they were 5mbit). The other conclusion
+classes with simple linear 1Mbit service curves will get the same treatment
+from LS criterion's perspective, as if they were 5Mbit). The other conclusion
 is, that in perfectly fluid system with linear curves, all virtual times across
 whole class hierarchy would be equal.
 
-Why is VC defined in term of virtual time (and what is it) ?
+Why is VC defined in term of virtual time (and what is it)?
 
 Imagine an example: class A with two children \- A1 and A2, both with let's say
-10mbit SCs. If A2 is idle, A1 receives all the bandwidth of A (and update its
+10Mbit SCs. If A2 is idle, A1 receives all the bandwidth of A (and update its
 V() in the process). When A2 becomes active, A1's virtual time is already
-\fIfar\fR bigger than A2's one. Considering the type of decision made by LS
-criterion, A1 would become idle for a lot of time. We can workaround this
+\fIfar\fR later than A2's one. Considering the type of decision made by LS
+criterion, A1 would become idle for a long time. We can workaround this
 situation by adjusting virtual time of the class becoming active \- we do that
 by getting such time "up to date". HFSC uses a mean of the smallest and the
 biggest virtual time of currently active children fit for sending. As it's not
@@ -259,20 +260,20 @@ either it's impossible to guarantee service curves and satisfy fairness
 during certain time periods:
 
 .RS 4
-Recall the example from RT section, slightly modified (with 3mbit slopes
-instead of 2mbit ones):
+Recall the example from RT section, slightly modified (with 3Mbit slopes
+instead of 2Mbit ones):
 
 .IP \(bu 4
-1st class \- 3mbit for 100ms, then 7mbit (convex \- 1st slope < 2nd slope)
+1st class \- 3Mbit for 100ms, then 7Mbit (convex \- 1st slope < 2nd slope)
 .IP \(bu
-2nd class \- 7mbit for 100ms, then 3mbit (concave \- 1st slope > 2nd slope)
+2nd class \- 7Mbit for 100ms, then 3Mbit (concave \- 1st slope > 2nd slope)
 
 .PP
-They sum up nicely to 10mbit \- interface's capacity. But if we wanted to only
+They sum up nicely to 10Mbit \- the interface's capacity. But if we wanted to only
 use LS for guarantees and fairness \- it simply won't work. In LS context,
 only V() is used for making decision which class to schedule. If the 2nd class
 becomes active when the 1st one is in its second slope, the fairness will be
-preserved \- ratio will be 1:1 (7mbit:7mbit), but LS itself is of course
+preserved \- ratio will be 1:1 (7Mbit:7Mbit), but LS itself is of course
 unable to guarantee the absolute values themselves \- as it would have to go
 beyond of what the interface is capable of.
 .RE
@@ -287,28 +288,28 @@ This is similar to the above case, but a bit more subtle. We will consider two
 subtrees, arbitrated by their common (root here) parent:
 
 .nf
-R (root) -\ 10mbit
+R (root) -\ 10Mbit
 
-A  \- 7mbit, then 3mbit
-A1 \- 5mbit, then 2mbit
-A2 \- 2mbit, then 1mbit
+A  \- 7Mbit, then 3Mbit
+A1 \- 5Mbit, then 2Mbit
+A2 \- 2Mbit, then 1Mbit
 
-B  \- 3mbit, then 7mbit
+B  \- 3Mbit, then 7Mbit
 .fi
 
 R arbitrates between left subtree (A) and right (B). Assume that A2 and B are
 constantly backlogged, and at some later point A1 becomes backlogged (when all
 other classes are in their 2nd linear part).
 
-What happens now ? B (choice made by R) will \fIalways\fR get 7 mbit as R is
+What happens now? B (choice made by R) will \fIalways\fR get 7 Mbit as R is
 only (obviously) concerned with the ratio between its direct children. Thus A
-subtree gets 3mbit, but its children would want (at the point when A1 became
-backlogged) 5mbit + 1mbit. That's of course impossible, as they can only get
-3mbit due to interface limitation.
+subtree gets 3Mbit, but its children would want (at the point when A1 became
+backlogged) 5Mbit + 1Mbit. That's of course impossible, as they can only get
+3Mbit due to interface limitation.
 
 In the left subtree \- we have the same situation as previously (fair split
 between A1 and A2, but violated guarantees), but in the whole tree \- there's
-no fairness (B got 7mbit, but A1 and A2 have to fit together in 3mbit) and
+no fairness (B got 7Mbit, but A1 and A2 have to fit together in 3Mbit) and
 there's no guarantees for all classes (only B got what it wanted). Even if we
 violated fairness in the A subtree and set A2's service curve to 0, A1 would
 still not get the required bandwidth.
@@ -317,83 +318,83 @@ still not get the required bandwidth.
 .SH "UPPERLIMIT CRITERION"
 .
 UL criterion is an extensions to LS one, that permits sending packets only
-if current real time is bigger than fit\-time ('ft'). So the modified LS
+if current real time is later than fit\-time ('ft'). So the modified LS
 criterion becomes: choose the smallest virtual time from all active children,
 such that fit\-time < current real time also holds. Fit\-time is calculated
 from F(), which is based on UL service curve. As you can see, its role is
 kinda similar to E() used in RT criterion. Also, for obvious reasons \- you
 can't specify UL service curve without LS one.
 
-Main purpose of UL service curve is to limit HFSC to bandwidth available on the
+The main purpose of the UL service curve is to limit HFSC to bandwidth available on the
 upstream router (think adsl home modem/router, and linux server as
-nat/firewall/etc. with 100mbit+ connection to mentioned modem/router).
+NAT/firewall/etc. with 100Mbit+ connection to mentioned modem/router).
 Typically, it's used to create a single class directly under root, setting
-linear UL service curve to available bandwidth \- and then creating your class
-structure from that class downwards. Of course, you're free to add UL service
-(linear or not) curve to any class with LS criterion.
+a linear UL service curve to available bandwidth \- and then creating your class
+structure from that class downwards. Of course, you're free to add a UL service
+curve (linear or not) to any class with LS criterion.
 
-Important part about UL service curve is, that whenever at some point in time
+An important part about the UL service curve is that whenever at some point in time
 a class doesn't qualify for linksharing due to its fit\-time, the next time it
-does qualify, it will update its virtual time to the smallest virtual time of
-all active children fit for linksharing. This way, one of the main things LS
+does qualify it will update its virtual time to the smallest virtual time of
+all active children fit for linksharing. This way, one of the main things the LS
 criterion tries to achieve \- equality of all virtual times across whole
 hierarchy \- is preserved (in perfectly fluid system with only linear curves,
 all virtual times would be equal).
 
 Without that, 'vt' would lag behind other virtual times, and could cause
-problems. Consider interface with capacity 10mbit, and following leaf classes
+problems. Consider an interface with a capacity of 10Mbit, and the following leaf classes
 (just in case you're skipping this text quickly \- this example shows behavior
 that \f(BIdoesn't happen\fR):
 
 .nf
-A \- ls 5.0mbit
-B \- ls 2.5mbit
-C \- ls 2.5mbit, ul 2.5mbit
+A \- ls 5.0Mbit
+B \- ls 2.5Mbit
+C \- ls 2.5Mbit, ul 2.5Mbit
 .fi
 
-If B was idle, while A and C were constantly backlogged, they would normally
+If B was idle, while A and C were constantly backlogged, A and C would normally
 (as far as LS criterion is concerned) divide bandwidth in 2:1 ratio. But due
-to UL service curve in place, C would get at most 2.5mbit, and A would get the
-remaining 7.5mbit. The longer the backlogged period, the more virtual times of
+to UL service curve in place, C would get at most 2.5Mbit, and A would get the
+remaining 7.5Mbit. The longer the backlogged period, the more the virtual times of
 A and C would drift apart. If B became backlogged at some later point in time,
 its virtual time would be set to (A's\~vt\~+\~C's\~vt)/2, thus blocking A from
-sending any traffic, until B's virtual time catches up with A.
+sending any traffic until B's virtual time catches up with A.
 .
 .SH "SEPARATE LS / RT SCs"
 .
-Another difference from original HFSC paper, is that RT and LS SCs can be
-specified separately. Moreover \- leaf classes are allowed to have only either
-RT SC or LS SC. For interior classes, only LS SCs make sense \- Any RT SC will
+Another difference from the original HFSC paper is that RT and LS SCs can be
+specified separately. Moreover, leaf classes are allowed to have only either
+RT SC or LS SC. For interior classes, only LS SCs make sense: any RT SC will
 be ignored.
 .
 .SH "CORNER CASES"
 .
-Separate service curves for LS and RT criteria can lead to certain traps,
+Separate service curves for LS and RT criteria can lead to certain traps
 that come from "fighting" between ideal linksharing and enforced realtime
 guarantees. Those situations didn't exist in original HFSC paper, where
 specifying separate LS / RT service curves was not discussed.
 
-Consider interface with capacity 10mbit, with following leaf classes:
+Consider an interface with a 10Mbit capacity, with the following leaf classes:
 
 .nf
-A \- ls 5.0mbit, rt 8mbit
-B \- ls 2.5mbit
-C \- ls 2.5mbit
+A \- ls 5.0Mbit, rt 8Mbit
+B \- ls 2.5Mbit
+C \- ls 2.5Mbit
 .fi
 
 Imagine A and C are constantly backlogged. As B is idle, A and C would divide
 bandwidth in 2:1 ratio, considering LS service curve (so in theory \- 6.66 and
-3.33). Alas RT criterion takes priority, so A will get 8mbit and LS will be
-able to compensate class C for only 2 mbit \- this will cause discrepancy
+3.33). Alas RT criterion takes priority, so A will get 8Mbit and LS will be
+able to compensate class C for only 2 Mbit \- this will cause discrepancy
 between virtual times of A and C.
 
-Assume this situation lasts for a lot of time with no idle periods, and
+Assume this situation lasts for a long time with no idle periods, and
 suddenly B becomes active. B's virtual time will be updated to
 (A's\~vt\~+\~C's\~vt)/2, effectively landing in the middle between A's and C's
 virtual time. The effect \- B, having no RT guarantees, will be punished and
 will not be allowed to transfer until C's virtual time catches up.
 
-If the interface had higher capacity \- for example 100mbit, this example
+If the interface had a higher capacity, for example 100Mbit, this example
 would behave perfectly fine though.
 
 Let's look a bit closer at the above example \- it "cleverly" invalidates one
@@ -401,8 +402,8 @@ of the basic things LS criterion tries to achieve \- equality of all virtual
 times across class hierarchy. Leaf classes without RT service curves are
 literally left to their own fate (governed by messed up virtual times).
 
-Also - it doesn't make much sense. Class A will always be guaranteed up to
-8mbit, and this is more than any absolute bandwidth that could happen from its
+Also, it doesn't make much sense. Class A will always be guaranteed up to
+8Mbit, and this is more than any absolute bandwidth that could happen from its
 LS criterion (excluding trivial case of only A being active). If the bandwidth
 taken by A is smaller than absolute value from LS criterion, the unused part
 will be automatically assigned to other active classes (as A has idling periods
@@ -411,7 +412,7 @@ average, bursts would be handled at the speed defined by RT criterion. Still,
 if extra speed is needed (e.g. due to latency), non linear service curves
 should be used in such case.
 
-In the other words - LS criterion is meaningless in the above example.
+In the other words: the LS criterion is meaningless in the above example.
 
 You can quickly "workaround" it by making sure each leaf class has RT service
 curve assigned (thus guaranteeing all of them will get some bandwidth), but it
@@ -422,13 +423,13 @@ happen \fIonly\fR in the first segment, then there's little wrong with
 "overusing" RT curve a bit:
 
 .nf
-A \- ls 5.0mbit, rt 9mbit/30ms, then 1mbit
-B \- ls 2.5mbit
-C \- ls 2.5mbit
+A \- ls 5.0Mbit, rt 9Mbit/30ms, then 1Mbit
+B \- ls 2.5Mbit
+C \- ls 2.5Mbit
 .fi
 
 Here, the vt of A will "spike" in the initial period, but then A will never get more
-than 1mbit, until B & C catch up. Then everything will be back to normal.
+than 1Mbit until B & C catch up. Then everything will be back to normal.
 .
 .SH "LINUX AND TIMER RESOLUTION"
 .
@@ -457,43 +458,43 @@ or aren't available.
 
 This is important to keep those settings in mind, as in scenario like: no
 tickless, no HR timers, frequency set to 100hz \- throttling accuracy would be
-at 10ms. It doesn't automatically mean you would be limited to ~0.8mbit/s
+at 10ms. It doesn't automatically mean you would be limited to ~0.8Mbit/s
 (assuming packets at ~1KB) \- as long as your queues are prepared to cover for
-timer inaccuracy. Of course, in case of e.g. locally generated udp traffic \-
+timer inaccuracy. Of course, in case of e.g. locally generated UDP traffic \-
 appropriate socket size is needed as well. Short example to make it more
 understandable (assume hardcore anti\-schedule settings \- HZ=100, no HR
 timers, no tickless):
 
 .nf
 tc qdisc add dev eth0 root handle 1:0 hfsc default 1
-tc class add dev eth0 parent 1:0 classid 1:1 hfsc rt m2 10mbit
+tc class add dev eth0 parent 1:0 classid 1:1 hfsc rt m2 10Mbit
 .fi
 
-Assuming packet of ~1KB size and HZ=100, that averages to ~0.8mbit \- anything
-beyond it (e.g. the above example with specified rate over 10x bigger) will
+Assuming packet of ~1KB size and HZ=100, that averages to ~0.8Mbit \- anything
+beyond it (e.g. the above example with specified rate over 10x larger) will
 require appropriate queuing and cause bursts every ~10 ms. As you can
 imagine, any HFSC's RT guarantees will be seriously invalidated by that.
 Aforementioned example is mainly important if you deal with old hardware \- as
-it's particularly popular for home server chores. Even then, you can easily
+is particularly popular for home server chores. Even then, you can easily
 set HZ=1000 and have very accurate scheduling for typical adsl speeds.
 
 Anything modern (apic or even hpet msi based timers + \&'tickless system')
-will provide enough accuracy for superb 1gbit scheduling. For example, on one
-of basically cheap dual core AMD boards I have with following settings:
+will provide enough accuracy for superb 1Gbit scheduling. For example, on one
+of my cheap dual-core AMD boards I have the following settings:
 
 .nf
 tc qdisc add dev eth0 parent root handle 1:0 hfsc default 1
-tc class add dev eth0 paretn 1:0 classid 1:1 hfsc rt m2 300mbit
+tc class add dev eth0 parent 1:0 classid 1:1 hfsc rt m2 300mbit
 .fi
 
-And simple:
+And a simple:
 
 .nf
 nc \-u dst.host.com 54321 </dev/zero
 nc \-l \-p 54321 >/dev/null
 .fi
 
-\&...will yield following effects over period of ~10 seconds (taken from
+\&...will yield the following effects over a period of ~10 seconds (taken from
 /proc/interrupts):
 
 .nf
@@ -502,16 +503,16 @@ nc \-l \-p 54321 >/dev/null
 .fi
 
 That's roughly 31000/s. Now compare it with HZ=1000 setting. The obvious
-drawback of it is that cpu load can be rather extensive with servicing that
-many timer interrupts. Example with 300mbit RT service curve on 1gbit link is
+drawback of it is that cpu load can be rather high with servicing that
+many timer interrupts. The example with 300Mbit RT service curve on 1Gbit link is
 particularly ugly, as it requires a lot of throttling with minuscule delays.
 
-Also note that it's just an example showing capability of current hardware.
-The above example (essentially 300mbit TBF emulator) is pointless on internal
-interface to begin with \- you will pretty much always want regular LS service
-curve there, and in such scenario HFSC simply doesn't throttle at all.
+Also note that it's just an example showing the capabilities of current hardware.
+The above example (essentially a 300Mbit TBF emulator) is pointless on an internal
+interface to begin with: you will pretty much always want a regular LS service
+curve there, and in such a scenario HFSC simply doesn't throttle at all.
 
-300mbit RT service curve (selected columns from mpstat \-P ALL 1):
+300Mbit RT service curve (selected columns from mpstat \-P ALL 1):
 
 .nf
 10:56:43 PM  CPU  %sys     %irq   %soft   %idle
@@ -520,28 +521,28 @@ curve there, and in such scenario HFSC simply doesn't throttle at all.
 10:56:44 PM    1   4.95   12.87    6.93   73.27
 .fi
 
-So, in rare case you need those speeds with only RT service curve, or with UL
-service curve \- remember about drawbacks.
+So, in the rare case you need those speeds with only a RT service curve, or with a UL
+service curve: remember the drawbacks.
 .
 .SH "CAVEAT: RANDOM ONLINE EXAMPLES"
 .
 For reasons unknown (though well guessed), many examples you can google love to
 overuse UL criterion and stuff it in every node possible. This makes no sense
 and works against what HFSC tries to do (and does pretty damn well). Use UL
-where it makes sense - on the uppermost node to match upstream router's uplink
-capacity. Or - in special cases, such as testing (limit certain subtree to some
-speed) or customers that must never get more than certain speed. In the last
-case you can usually achieve the same by just using RT criterion without LS+UL
+where it makes sense: on the uppermost node to match upstream router's uplink
+capacity. Or in special cases, such as testing (limit certain subtree to some
+speed), or customers that must never get more than certain speed. In the last
+case you can usually achieve the same by just using a RT criterion without LS+UL
 on leaf nodes.
 
-As for router case - remember it's good to differentiate between "traffic to
+As for the router case - remember it's good to differentiate between "traffic to
 router" (remote console, web config, etc.) and "outgoing traffic", so for
 example:
 
 .nf
 tc qdisc add dev eth0 root handle 1:0 hfsc default 0x8002
-tc class add dev eth0 parent 1:0 classid 1:999 hfsc rt m2 50mbit
-tc class add dev eth0 parent 1:0 classid 1:1 hfsc ls m2 2mbit ul m2 2mbit
+tc class add dev eth0 parent 1:0 classid 1:999 hfsc rt m2 50Mbit
+tc class add dev eth0 parent 1:0 classid 1:1 hfsc ls m2 2Mbit ul m2 2Mbit
 .fi
 
 \&... so "internet" tree under 1:1 and "router itself" as 1:999

^ permalink raw reply related

* RE: atl1c DMA-API mapping errors in 3.8-rc6+
From: Huang, Xiong @ 2013-02-11 16:10 UTC (permalink / raw)
  To: Josh Boyer, Jay Cliburn, Chris Snook
  Cc: David S. Miller, netdev@vger.kernel.org, sgruszka@redhat.com,
	nic-devel
In-Reply-To: <20130211130812.GA21501@hansolo.jdub.homelinux.org>

> 
> We've had two different reports[1] in Fedora of users hitting DMA-API errors
> with the atl1c driver on 3.8-rc6+.  The errors are from different locations, but
> the problem is the same.  Essentially, the driver isn't doing any form of
> pci_dma_mapping_error checking after calling pci_map_single.
> 


Josh, I will add pci_dma_mapping_error checking, thanks for your help !


BR.
Xiong

^ permalink raw reply

* [PATCH 3/3] tcp: send packets with a socket timestamp
From: Andrey Vagin @ 2013-02-11 15:50 UTC (permalink / raw)
  To: netdev
  Cc: criu, linux-kernel, Andrey Vagin, David S. Miller,
	Alexey Kuznetsov, James Morris, Hideaki YOSHIFUJI,
	Patrick McHardy, Eric Dumazet, Pavel Emelyanov
In-Reply-To: <1360597819-23783-1-git-send-email-avagin@openvz.org>

A socket timestamp is a sum of the global tcp_time_stamp and
a per-socket offset.

A socket offset is added in places where externally visible
tcp timestamp option is parsed/initialized.

Connections in the SYN_RECV state are not supported, global
tcp_time_stamp is used for them, because repair mode doesn't support
this state. In a future it can be implemented by the similar way
as for TIME_WAIT sockets.

Cc: "David S. Miller" <davem@davemloft.net>
Cc: Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
Cc: James Morris <jmorris@namei.org>
Cc: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
Cc: Patrick McHardy <kaber@trash.net>
Cc: Eric Dumazet <edumazet@google.com>
Cc: Pavel Emelyanov <xemul@parallels.com>
Signed-off-by: Andrey Vagin <avagin@openvz.org>
---
 net/ipv4/tcp_input.c     |  8 +++++++-
 net/ipv4/tcp_ipv4.c      | 12 +++++++-----
 net/ipv4/tcp_minisocks.c |  1 +
 net/ipv4/tcp_output.c    |  4 ++--
 net/ipv6/tcp_ipv6.c      | 22 +++++++++++++---------
 5 files changed, 30 insertions(+), 17 deletions(-)

diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index a28e4db..dcb7a52 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -3872,7 +3872,7 @@ static bool tcp_parse_aligned_timestamp(struct tcp_sock *tp, const struct tcphdr
 		++ptr;
 		tp->rx_opt.rcv_tsval = ntohl(*ptr);
 		++ptr;
-		tp->rx_opt.rcv_tsecr = ntohl(*ptr);
+		tp->rx_opt.rcv_tsecr = ntohl(*ptr) - tp->tsoffset;
 		return true;
 	}
 	return false;
@@ -3896,7 +3896,11 @@ static bool tcp_fast_parse_options(const struct sk_buff *skb,
 		if (tcp_parse_aligned_timestamp(tp, th))
 			return true;
 	}
+
 	tcp_parse_options(skb, &tp->rx_opt, hvpp, 1, NULL);
+	if (tp->rx_opt.saw_tstamp)
+		tp->rx_opt.rcv_tsecr -= tp->tsoffset;
+
 	return true;
 }
 
@@ -5678,6 +5682,8 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
 	int saved_clamp = tp->rx_opt.mss_clamp;
 
 	tcp_parse_options(skb, &tp->rx_opt, &hash_location, 0, &foc);
+	if (tp->rx_opt.saw_tstamp)
+		tp->rx_opt.rcv_tsecr -= tp->tsoffset;
 
 	if (th->ack) {
 		/* rfc793:
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 54139fa..0679fb7 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -725,7 +725,7 @@ release_sk1:
  */
 
 static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack,
-			    u32 win, u32 ts, int oif,
+			    u32 win, u32 tsval, u32 tsecr, int oif,
 			    struct tcp_md5sig_key *key,
 			    int reply_flags, u8 tos)
 {
@@ -746,12 +746,12 @@ static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack,
 
 	arg.iov[0].iov_base = (unsigned char *)&rep;
 	arg.iov[0].iov_len  = sizeof(rep.th);
-	if (ts) {
+	if (tsecr) {
 		rep.opt[0] = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |
 				   (TCPOPT_TIMESTAMP << 8) |
 				   TCPOLEN_TIMESTAMP);
-		rep.opt[1] = htonl(tcp_time_stamp);
-		rep.opt[2] = htonl(ts);
+		rep.opt[1] = htonl(tsval);
+		rep.opt[2] = htonl(tsecr);
 		arg.iov[0].iov_len += TCPOLEN_TSTAMP_ALIGNED;
 	}
 
@@ -766,7 +766,7 @@ static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack,
 
 #ifdef CONFIG_TCP_MD5SIG
 	if (key) {
-		int offset = (ts) ? 3 : 0;
+		int offset = (tsecr) ? 3 : 0;
 
 		rep.opt[offset++] = htonl((TCPOPT_NOP << 24) |
 					  (TCPOPT_NOP << 16) |
@@ -801,6 +801,7 @@ static void tcp_v4_timewait_ack(struct sock *sk, struct sk_buff *skb)
 
 	tcp_v4_send_ack(skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt,
 			tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale,
+			tcp_time_stamp + tcptw->tw_ts_offset,
 			tcptw->tw_ts_recent,
 			tw->tw_bound_dev_if,
 			tcp_twsk_md5_key(tcptw),
@@ -820,6 +821,7 @@ static void tcp_v4_reqsk_send_ack(struct sock *sk, struct sk_buff *skb,
 	tcp_v4_send_ack(skb, (sk->sk_state == TCP_LISTEN) ?
 			tcp_rsk(req)->snt_isn + 1 : tcp_sk(sk)->snd_nxt,
 			tcp_rsk(req)->rcv_nxt, req->rcv_wnd,
+			tcp_time_stamp,
 			req->ts_recent,
 			0,
 			tcp_md5_do_lookup(sk, (union tcp_md5_addr *)&ip_hdr(skb)->daddr,
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
index b94940e..9f26eb3 100644
--- a/net/ipv4/tcp_minisocks.c
+++ b/net/ipv4/tcp_minisocks.c
@@ -102,6 +102,7 @@ tcp_timewait_state_process(struct inet_timewait_sock *tw, struct sk_buff *skb,
 		tcp_parse_options(skb, &tmp_opt, &hash_location, 0, NULL);
 
 		if (tmp_opt.saw_tstamp) {
+			tmp_opt.rcv_tsecr	-= tcptw->tw_ts_offset;
 			tmp_opt.ts_recent	= tcptw->tw_ts_recent;
 			tmp_opt.ts_recent_stamp	= tcptw->tw_ts_recent_stamp;
 			paws_reject = tcp_paws_reject(&tmp_opt, th->rst);
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 5d45159..5c6fc14 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -622,7 +622,7 @@ static unsigned int tcp_syn_options(struct sock *sk, struct sk_buff *skb,
 
 	if (likely(sysctl_tcp_timestamps && *md5 == NULL)) {
 		opts->options |= OPTION_TS;
-		opts->tsval = TCP_SKB_CB(skb)->when;
+		opts->tsval = TCP_SKB_CB(skb)->when + tp->tsoffset;
 		opts->tsecr = tp->rx_opt.ts_recent;
 		remaining -= TCPOLEN_TSTAMP_ALIGNED;
 	}
@@ -806,7 +806,7 @@ static unsigned int tcp_established_options(struct sock *sk, struct sk_buff *skb
 
 	if (likely(tp->rx_opt.tstamp_ok)) {
 		opts->options |= OPTION_TS;
-		opts->tsval = tcb ? tcb->when : 0;
+		opts->tsval = tcb ? tcb->when + tp->tsoffset : 0;
 		opts->tsecr = tp->rx_opt.ts_recent;
 		size += TCPOLEN_TSTAMP_ALIGNED;
 	}
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 93825dd..0aa0d1d 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -712,7 +712,8 @@ static const struct tcp_request_sock_ops tcp_request_sock_ipv6_ops = {
 #endif
 
 static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win,
-				 u32 ts, struct tcp_md5sig_key *key, int rst, u8 tclass)
+				 u32 tsval, u32 tsecr,
+				 struct tcp_md5sig_key *key, int rst, u8 tclass)
 {
 	const struct tcphdr *th = tcp_hdr(skb);
 	struct tcphdr *t1;
@@ -724,7 +725,7 @@ static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win,
 	struct dst_entry *dst;
 	__be32 *topt;
 
-	if (ts)
+	if (tsecr)
 		tot_len += TCPOLEN_TSTAMP_ALIGNED;
 #ifdef CONFIG_TCP_MD5SIG
 	if (key)
@@ -754,11 +755,11 @@ static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win,
 
 	topt = (__be32 *)(t1 + 1);
 
-	if (ts) {
+	if (tsecr) {
 		*topt++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |
 				(TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP);
-		*topt++ = htonl(tcp_time_stamp);
-		*topt++ = htonl(ts);
+		*topt++ = htonl(tsval);
+		*topt++ = htonl(tsecr);
 	}
 
 #ifdef CONFIG_TCP_MD5SIG
@@ -858,7 +859,7 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb)
 		ack_seq = ntohl(th->seq) + th->syn + th->fin + skb->len -
 			  (th->doff << 2);
 
-	tcp_v6_send_response(skb, seq, ack_seq, 0, 0, key, 1, 0);
+	tcp_v6_send_response(skb, seq, ack_seq, 0, 0, 0, key, 1, 0);
 
 #ifdef CONFIG_TCP_MD5SIG
 release_sk1:
@@ -869,10 +870,11 @@ release_sk1:
 #endif
 }
 
-static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 ts,
+static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack,
+			    u32 win, u32 tsval, u32 tsecr,
 			    struct tcp_md5sig_key *key, u8 tclass)
 {
-	tcp_v6_send_response(skb, seq, ack, win, ts, key, 0, tclass);
+	tcp_v6_send_response(skb, seq, ack, win, tsval, tsecr, key, 0, tclass);
 }
 
 static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb)
@@ -882,6 +884,7 @@ static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb)
 
 	tcp_v6_send_ack(skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt,
 			tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale,
+			tcp_time_stamp + tcptw->tw_ts_offset,
 			tcptw->tw_ts_recent, tcp_twsk_md5_key(tcptw),
 			tw->tw_tclass);
 
@@ -891,7 +894,8 @@ static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb)
 static void tcp_v6_reqsk_send_ack(struct sock *sk, struct sk_buff *skb,
 				  struct request_sock *req)
 {
-	tcp_v6_send_ack(skb, tcp_rsk(req)->snt_isn + 1, tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, req->ts_recent,
+	tcp_v6_send_ack(skb, tcp_rsk(req)->snt_isn + 1, tcp_rsk(req)->rcv_isn + 1,
+			req->rcv_wnd, tcp_time_stamp, req->ts_recent,
 			tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->daddr), 0);
 }
 
-- 
1.7.11.7

^ permalink raw reply related

* [PATCH 2/3] tcp: set and get per-socket timestamp
From: Andrey Vagin @ 2013-02-11 15:50 UTC (permalink / raw)
  To: netdev
  Cc: criu, linux-kernel, Andrey Vagin, David S. Miller,
	Alexey Kuznetsov, James Morris, Hideaki YOSHIFUJI,
	Patrick McHardy, Eric Dumazet, Pavel Emelyanov
In-Reply-To: <1360597819-23783-1-git-send-email-avagin@openvz.org>

A timestamp can be set, only if a socket is in the repair mode.

This patch adds a new socket option TCP_TIMESTAMP, which allows to
get and set current tcp times stamp.

Cc: "David S. Miller" <davem@davemloft.net>
Cc: Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
Cc: James Morris <jmorris@namei.org>
Cc: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
Cc: Patrick McHardy <kaber@trash.net>
Cc: Eric Dumazet <edumazet@google.com>
Cc: Pavel Emelyanov <xemul@parallels.com>
Signed-off-by: Andrey Vagin <avagin@openvz.org>
---
 include/uapi/linux/tcp.h | 1 +
 net/ipv4/tcp.c           | 9 +++++++++
 2 files changed, 10 insertions(+)

diff --git a/include/uapi/linux/tcp.h b/include/uapi/linux/tcp.h
index e962faa..6b1ead0 100644
--- a/include/uapi/linux/tcp.h
+++ b/include/uapi/linux/tcp.h
@@ -111,6 +111,7 @@ enum {
 #define TCP_QUEUE_SEQ		21
 #define TCP_REPAIR_OPTIONS	22
 #define TCP_FASTOPEN		23	/* Enable FastOpen on listeners */
+#define TCP_TIMESTAMP		24
 
 struct tcp_repair_opt {
 	__u32	opt_code;
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 60fab09..9e484fc 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -2706,6 +2706,12 @@ static int do_tcp_setsockopt(struct sock *sk, int level,
 		else
 			err = -EINVAL;
 		break;
+	case TCP_TIMESTAMP:
+		if (!tp->repair)
+			err = -EPERM;
+		else
+			tp->tsoffset = val - tcp_time_stamp;
+		break;
 	default:
 		err = -ENOPROTOOPT;
 		break;
@@ -2954,6 +2960,9 @@ static int do_tcp_getsockopt(struct sock *sk, int level,
 	case TCP_USER_TIMEOUT:
 		val = jiffies_to_msecs(icsk->icsk_user_timeout);
 		break;
+	case TCP_TIMESTAMP:
+		val = tcp_time_stamp + tp->tsoffset;
+		break;
 	default:
 		return -ENOPROTOOPT;
 	}
-- 
1.7.11.7

^ permalink raw reply related

* [PATCH 1/3] tcp: adding a per-socket timestamp offset
From: Andrey Vagin @ 2013-02-11 15:50 UTC (permalink / raw)
  To: netdev
  Cc: criu, linux-kernel, Andrey Vagin, David S. Miller,
	Alexey Kuznetsov, James Morris, Hideaki YOSHIFUJI,
	Patrick McHardy, Eric Dumazet, Pavel Emelyanov
In-Reply-To: <1360597819-23783-1-git-send-email-avagin@openvz.org>

This functionality is used for restoring tcp sockets. A tcp timestamp
depends on how long a system has been running, so it's differ for each
host. The solution is to set a per-socket offset.

A per-socket offset for a TIME_WAIT socket is inherited from a proper
tcp socket.

tcp_request_sock doesn't have a timestamp offset, because the repair
mode for them are not implemented.

Cc: "David S. Miller" <davem@davemloft.net>
Cc: Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
Cc: James Morris <jmorris@namei.org>
Cc: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
Cc: Patrick McHardy <kaber@trash.net>
Cc: Eric Dumazet <edumazet@google.com>
Cc: Pavel Emelyanov <xemul@parallels.com>
Signed-off-by: Andrey Vagin <avagin@openvz.org>
---
 include/linux/tcp.h      | 3 +++
 net/ipv4/tcp.c           | 2 ++
 net/ipv4/tcp_minisocks.c | 2 ++
 3 files changed, 7 insertions(+)

diff --git a/include/linux/tcp.h b/include/linux/tcp.h
index 4e1d228..974fb4a 100644
--- a/include/linux/tcp.h
+++ b/include/linux/tcp.h
@@ -162,6 +162,8 @@ struct tcp_sock {
 	u32	rcv_tstamp;	/* timestamp of last received ACK (for keepalives) */
 	u32	lsndtime;	/* timestamp of last sent data packet (for restart window) */
 
+	u32	tsoffset;	/* timestamp offset */
+
 	struct list_head tsq_node; /* anchor in tsq_tasklet.head list */
 	unsigned long	tsq_flags;
 
@@ -354,6 +356,7 @@ struct tcp_timewait_sock {
 	u32			  tw_rcv_nxt;
 	u32			  tw_snd_nxt;
 	u32			  tw_rcv_wnd;
+	u32			  tw_ts_offset;
 	u32			  tw_ts_recent;
 	long			  tw_ts_recent_stamp;
 #ifdef CONFIG_TCP_MD5SIG
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 1ca2536..60fab09 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -400,6 +400,8 @@ void tcp_init_sock(struct sock *sk)
 	tcp_enable_early_retrans(tp);
 	icsk->icsk_ca_ops = &tcp_init_congestion_ops;
 
+	tp->tsoffset = 0;
+
 	sk->sk_state = TCP_CLOSE;
 
 	sk->sk_write_space = sk_stream_write_space;
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
index f35f2df..b94940e 100644
--- a/net/ipv4/tcp_minisocks.c
+++ b/net/ipv4/tcp_minisocks.c
@@ -288,6 +288,7 @@ void tcp_time_wait(struct sock *sk, int state, int timeo)
 		tcptw->tw_rcv_wnd	= tcp_receive_window(tp);
 		tcptw->tw_ts_recent	= tp->rx_opt.ts_recent;
 		tcptw->tw_ts_recent_stamp = tp->rx_opt.ts_recent_stamp;
+		tcptw->tw_ts_offset	= tp->tsoffset;
 
 #if IS_ENABLED(CONFIG_IPV6)
 		if (tw->tw_family == PF_INET6) {
@@ -500,6 +501,7 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req,
 			newtp->rx_opt.ts_recent_stamp = 0;
 			newtp->tcp_header_len = sizeof(struct tcphdr);
 		}
+		newtp->tsoffset = 0;
 #ifdef CONFIG_TCP_MD5SIG
 		newtp->md5sig_info = NULL;	/*XXX*/
 		if (newtp->af_specific->md5_lookup(sk, newsk))
-- 
1.7.11.7

^ permalink raw reply related

* [PATCH net-next] tcp: add ability to set a timestamp offset
From: Andrey Vagin @ 2013-02-11 15:50 UTC (permalink / raw)
  To: netdev
  Cc: criu, linux-kernel, Andrey Vagin, David S. Miller,
	Alexey Kuznetsov, James Morris, Hideaki YOSHIFUJI,
	Patrick McHardy, Eric Dumazet, Pavel Emelyanov

If a TCP socket will get live-migrated from one box to another the
timestamps (which are typically ON) will get screwed up -- the new
kernel will generate TS values that has nothing to do with what they
were on dump. The solution is to yet again fix the kernel and put a
"timestamp offset" on a socket.

A socket offset is added in places where externally visible tcp
timestamp option is parsed/initialized.

Connections in the SYN_RECV state are not supported, global
tcp_time_stamp is used for them, because repair mode doesn't support
this state. In a future it can be implemented by the similar way as for
TIME_WAIT sockets.

For time-wait sockets offset is inhereted by a proper tcp_sock.

A per-socket offset can be set only for sockets in repair mode.

Cc: "David S. Miller" <davem@davemloft.net>
Cc: Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
Cc: James Morris <jmorris@namei.org>
Cc: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
Cc: Patrick McHardy <kaber@trash.net>
Cc: Eric Dumazet <edumazet@google.com>
Cc: Pavel Emelyanov <xemul@parallels.com>
Signed-off-by: Andrey Vagin <avagin@openvz.org>

Andrey Vagin (3):
  tcp: adding a per-socket timestamp offset
  tcp: set and get per-socket timestamp
  tcp: send packets with a socket timestamp

 include/linux/tcp.h      |  3 +++
 include/uapi/linux/tcp.h |  1 +
 net/ipv4/tcp.c           | 11 +++++++++++
 net/ipv4/tcp_input.c     |  8 +++++++-
 net/ipv4/tcp_ipv4.c      | 12 +++++++-----
 net/ipv4/tcp_minisocks.c |  3 +++
 net/ipv4/tcp_output.c    |  4 ++--
 net/ipv6/tcp_ipv6.c      | 22 +++++++++++++---------
 8 files changed, 47 insertions(+), 17 deletions(-)
-- 
1.7.11.7

^ permalink raw reply

* [PATCH] cfg80211: configuration for WoWLAN over TCP
From: Johannes Berg @ 2013-02-11 15:34 UTC (permalink / raw)
  To: linux-wireless; +Cc: netdev, Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

Intel Wireless devices are able to make a TCP connection
after suspending, sending some data and waking up when
the connection receives wakeup data (or breaks). Add the
WoWLAN configuration and feature advertising API for it.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 include/net/cfg80211.h       |  55 +++++++-
 include/uapi/linux/nl80211.h | 125 ++++++++++++++++++
 net/wireless/core.h          |   3 +
 net/wireless/nl80211.c       | 293 ++++++++++++++++++++++++++++++++++++++++++-
 4 files changed, 472 insertions(+), 4 deletions(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 825230c..423ea68 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -19,6 +19,7 @@
 #include <linux/nl80211.h>
 #include <linux/if_ether.h>
 #include <linux/ieee80211.h>
+#include <linux/net.h>
 #include <net/regulatory.h>
 
 /**
@@ -1586,6 +1587,41 @@ struct cfg80211_wowlan_trig_pkt_pattern {
 };
 
 /**
+ * struct cfg80211_wowlan_tcp - TCP connection parameters
+ *
+ * @sock: (internal) socket for source port allocation
+ * @src: source IP address
+ * @dst: destination IP address
+ * @dst_mac: destination MAC address
+ * @src_port: source port
+ * @dst_port: destination port
+ * @payload_len: data payload length
+ * @payload: data payload buffer
+ * @payload_seq: payload sequence stamping configuration
+ * @data_interval: interval at which to send data packets
+ * @wake_len: wakeup payload match length
+ * @wake_data: wakeup payload match data
+ * @wake_mask: wakeup payload match mask
+ * @tokens_size: length of the tokens buffer
+ * @payload_tok: payload token usage configuration
+ */
+struct cfg80211_wowlan_tcp {
+	struct socket *sock;
+	__be32 src, dst;
+	u16 src_port, dst_port;
+	u8 dst_mac[ETH_ALEN];
+	int payload_len;
+	const u8 *payload;
+	struct nl80211_wowlan_tcp_data_seq payload_seq;
+	u32 data_interval;
+	u32 wake_len;
+	const u8 *wake_data, *wake_mask;
+	u32 tokens_size;
+	/* must be last, variable member */
+	struct nl80211_wowlan_tcp_data_token payload_tok;
+};
+
+/**
  * struct cfg80211_wowlan - Wake on Wireless-LAN support info
  *
  * This structure defines the enabled WoWLAN triggers for the device.
@@ -1599,12 +1635,15 @@ struct cfg80211_wowlan_trig_pkt_pattern {
  * @eap_identity_req: wake up on EAP identity request packet
  * @four_way_handshake: wake up on 4-way handshake
  * @rfkill_release: wake up when rfkill is released
+ * @tcp: TCP connection establishment/wakeup parameters, see nl80211.h.
+ *	NULL if not configured.
  */
 struct cfg80211_wowlan {
 	bool any, disconnect, magic_pkt, gtk_rekey_failure,
 	     eap_identity_req, four_way_handshake,
 	     rfkill_release;
 	struct cfg80211_wowlan_trig_pkt_pattern *patterns;
+	struct cfg80211_wowlan_tcp *tcp;
 	int n_patterns;
 };
 
@@ -1624,11 +1663,15 @@ struct cfg80211_wowlan {
  *	frame triggers an 802.3 frame should be reported, for
  *	disconnect due to deauth 802.11 frame. This indicates which
  *	it is.
+ * @tcp_match: TCP wakeup packet received
+ * @tcp_connlost: TCP connection lost or failed to establish
+ * @tcp_nomoretokens: TCP data ran out of tokens
  */
 struct cfg80211_wowlan_wakeup {
 	bool disconnect, magic_pkt, gtk_rekey_failure,
 	     eap_identity_req, four_way_handshake,
-	     rfkill_release, packet_80211;
+	     rfkill_release, packet_80211,
+	     tcp_match, tcp_connlost, tcp_nomoretokens;
 	s32 pattern_idx;
 	u32 packet_present_len, packet_len;
 	const void *packet;
@@ -2283,6 +2326,14 @@ enum wiphy_wowlan_support_flags {
 	WIPHY_WOWLAN_RFKILL_RELEASE	= BIT(7),
 };
 
+struct wiphy_wowlan_tcp_support {
+	const struct nl80211_wowlan_tcp_data_token_feature *tok;
+	u32 data_payload_max;
+	u32 data_interval_max;
+	u32 wake_payload_max;
+	bool seq;
+};
+
 /**
  * struct wiphy_wowlan_support - WoWLAN support data
  * @flags: see &enum wiphy_wowlan_support_flags
@@ -2290,12 +2341,14 @@ enum wiphy_wowlan_support_flags {
  *	(see nl80211.h for the pattern definition)
  * @pattern_max_len: maximum length of each pattern
  * @pattern_min_len: minimum length of each pattern
+ * @tcp: TCP wakeup support information
  */
 struct wiphy_wowlan_support {
 	u32 flags;
 	int n_patterns;
 	int pattern_max_len;
 	int pattern_min_len;
+	const struct wiphy_wowlan_tcp_support *tcp;
 };
 
 /**
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 9a2ecdc..c9e3040 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -2985,6 +2985,17 @@ struct nl80211_wowlan_pattern_support {
  * @NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023_LEN: Original length of the 802.3
  *	packet, may be bigger than the @NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023
  *	attribute if the packet was truncated somewhere.
+ * @NL80211_WOWLAN_TRIG_TCP_CONNECTION: TCP connection wake, see DOC section
+ *	"TCP connection wakeup" for more details. This is a nested attribute
+ *	containing the exact information for establishing and keeping alive
+ *	the TCP connection.
+ * @NL80211_WOWLAN_TRIG_TCP_WAKEUP_MATCH: For wakeup reporting only, the
+ *	wakeup packet was received on the TCP connection
+ * @NL80211_WOWLAN_TRIG_WAKEUP_TCP_CONNLOST: For wakeup reporting only, the
+ *	TCP connection was lost or failed to be established
+ * @NL80211_WOWLAN_TRIG_WAKEUP_TCP_NOMORETOKENS: For wakeup reporting only,
+ *	the TCP connection ran out of tokens to use for data to send to the
+ *	service
  * @NUM_NL80211_WOWLAN_TRIG: number of wake on wireless triggers
  * @MAX_NL80211_WOWLAN_TRIG: highest wowlan trigger attribute number
  *
@@ -3006,6 +3017,10 @@ enum nl80211_wowlan_triggers {
 	NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211_LEN,
 	NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023,
 	NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023_LEN,
+	NL80211_WOWLAN_TRIG_TCP_CONNECTION,
+	NL80211_WOWLAN_TRIG_WAKEUP_TCP_MATCH,
+	NL80211_WOWLAN_TRIG_WAKEUP_TCP_CONNLOST,
+	NL80211_WOWLAN_TRIG_WAKEUP_TCP_NOMORETOKENS,
 
 	/* keep last */
 	NUM_NL80211_WOWLAN_TRIG,
@@ -3013,6 +3028,116 @@ enum nl80211_wowlan_triggers {
 };
 
 /**
+ * DOC: TCP connection wakeup
+ *
+ * Some devices can establish a TCP connection in order to be woken up by a
+ * packet coming in from outside their network segment, or behind NAT. If
+ * configured, the device will establish a TCP connection to the given
+ * service, and periodically send data to that service. The first data
+ * packet is usually transmitted after SYN/ACK, also ACKing the SYN/ACK.
+ * The data packets can optionally include a (little endian) sequence
+ * number (in the TCP payload!) that is generated by the device, and, also
+ * optionally, a token from a list of tokens. This serves as a keep-alive
+ * with the service, and for NATed connections, etc.
+ *
+ * During this keep-alive period, the server doesn't send any data to the
+ * client. When receiving data, it is compared against the wakeup pattern
+ * (and mask) and if it matches, the host is woken up. Similarly, if the
+ * connection breaks or cannot be established to start with, the host is
+ * also woken up.
+ *
+ * Developer's note: ARP offload is required for this, otherwise TCP
+ * response packets might not go through correctly.
+ */
+
+/**
+ * struct nl80211_wowlan_tcp_data_seq - WoWLAN TCP data sequence
+ * @start: starting value
+ * @offset: offset of sequence number in packet
+ * @len: length of the sequence value to write, 1 through 4
+ *
+ * Note: don't confuse with the TCP sequence number(s), this is for the
+ * keepalive packet payload. The actual value is written into the packet
+ * in little endian.
+ */
+struct nl80211_wowlan_tcp_data_seq {
+	__u32 start, offset, len;
+};
+
+/**
+ * struct nl80211_wowlan_tcp_data_token - WoWLAN TCP data token config
+ * @offset: offset of token in packet
+ * @len: length of each token
+ * @token_stream: stream of data to be used for the tokens, the length must
+ *	be a multiple of @len for this to make sense
+ */
+struct nl80211_wowlan_tcp_data_token {
+	__u32 offset, len;
+	__u8 token_stream[];
+};
+
+/**
+ * struct nl80211_wowlan_tcp_data_token_feature - data token features
+ * @min_len: minimum token length
+ * @max_len: maximum token length
+ * @bufsize: total available token buffer size (max size of @token_stream)
+ */
+struct nl80211_wowlan_tcp_data_token_feature {
+	__u32 min_len, max_len, bufsize;
+};
+
+/**
+ * enum nl80211_wowlan_tcp_attrs - WoWLAN TCP connection parameters
+ * @__NL80211_WOWLAN_TCP_INVALID: invalid number for nested attributes
+ * @NL80211_WOWLAN_TCP_SRC_IPV4: source IPv4 address (in network byte order)
+ * @NL80211_WOWLAN_TCP_DST_IPV4: destination IPv4 address
+ *	(in network byte order)
+ * @NL80211_WOWLAN_TCP_DST_MAC: destination MAC address, this is given because
+ *	route lookup when configured might be invalid by the time we suspend,
+ *	and doing a route lookup when suspending is no longer possible as it
+ *	might require ARP querying.
+ * @NL80211_WOWLAN_TCP_SRC_PORT: source port (u16); optional, if not given a
+ *	socket and port will be allocated
+ * @NL80211_WOWLAN_TCP_DST_PORT: destination port (u16)
+ * @NL80211_WOWLAN_TCP_DATA_PAYLOAD: data packet payload, at least one byte.
+ *	For feature advertising, a u32 attribute holding the maximum length
+ *	of the data payload.
+ * @NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ: data packet sequence configuration
+ *	(if desired), a &struct nl80211_wowlan_tcp_data_seq. For feature
+ *	advertising it is just a flag
+ * @NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN: data packet token configuration,
+ *	see &struct nl80211_wowlan_tcp_data_token and for advertising see
+ *	&struct nl80211_wowlan_tcp_data_token_feature.
+ * @NL80211_WOWLAN_TCP_DATA_INTERVAL: data interval in seconds, maximum
+ *	interval in feature advertising (u32)
+ * @NL80211_WOWLAN_TCP_WAKE_PAYLOAD: wake packet payload, for advertising a
+ *	u32 attribute holding the maximum length
+ * @NL80211_WOWLAN_TCP_WAKE_MASK: Wake packet payload mask, not used for
+ *	feature advertising. The mask works like @NL80211_WOWLAN_PKTPAT_MASK
+ *	but on the TCP payload only.
+ * @NUM_NL80211_WOWLAN_TCP: number of TCP attributes
+ * @MAX_NL80211_WOWLAN_TCP: highest attribute number
+ */
+enum nl80211_wowlan_tcp_attrs {
+	__NL80211_WOWLAN_TCP_INVALID,
+	NL80211_WOWLAN_TCP_SRC_IPV4,
+	NL80211_WOWLAN_TCP_DST_IPV4,
+	NL80211_WOWLAN_TCP_DST_MAC,
+	NL80211_WOWLAN_TCP_SRC_PORT,
+	NL80211_WOWLAN_TCP_DST_PORT,
+	NL80211_WOWLAN_TCP_DATA_PAYLOAD,
+	NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ,
+	NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN,
+	NL80211_WOWLAN_TCP_DATA_INTERVAL,
+	NL80211_WOWLAN_TCP_WAKE_PAYLOAD,
+	NL80211_WOWLAN_TCP_WAKE_MASK,
+
+	/* keep last */
+	NUM_NL80211_WOWLAN_TCP,
+	MAX_NL80211_WOWLAN_TCP = NUM_NL80211_WOWLAN_TCP - 1
+};
+
+/**
  * enum nl80211_iface_limit_attrs - limit attributes
  * @NL80211_IFACE_LIMIT_UNSPEC: (reserved)
  * @NL80211_IFACE_LIMIT_MAX: maximum number of interfaces that
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 37d70dc..949c957 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -108,6 +108,9 @@ cfg80211_rdev_free_wowlan(struct cfg80211_registered_device *rdev)
 	for (i = 0; i < rdev->wowlan->n_patterns; i++)
 		kfree(rdev->wowlan->patterns[i].mask);
 	kfree(rdev->wowlan->patterns);
+	if (rdev->wowlan->tcp && rdev->wowlan->tcp->sock)
+		sock_release(rdev->wowlan->tcp->sock);
+	kfree(rdev->wowlan->tcp);
 	kfree(rdev->wowlan);
 }
 
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 93bc63e..b0193fc 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -19,6 +19,7 @@
 #include <net/genetlink.h>
 #include <net/cfg80211.h>
 #include <net/sock.h>
+#include <net/inet_connection_sock.h>
 #include "core.h"
 #include "nl80211.h"
 #include "reg.h"
@@ -399,6 +400,26 @@ nl80211_wowlan_policy[NUM_NL80211_WOWLAN_TRIG] = {
 	[NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST] = { .type = NLA_FLAG },
 	[NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE] = { .type = NLA_FLAG },
 	[NL80211_WOWLAN_TRIG_RFKILL_RELEASE] = { .type = NLA_FLAG },
+	[NL80211_WOWLAN_TRIG_TCP_CONNECTION] = { .type = NLA_NESTED },
+};
+
+static const struct nla_policy
+nl80211_wowlan_tcp_policy[NUM_NL80211_WOWLAN_TCP] = {
+	[NL80211_WOWLAN_TCP_SRC_IPV4] = { .type = NLA_U32 },
+	[NL80211_WOWLAN_TCP_DST_IPV4] = { .type = NLA_U32 },
+	[NL80211_WOWLAN_TCP_DST_MAC] = { .len = ETH_ALEN },
+	[NL80211_WOWLAN_TCP_SRC_PORT] = { .type = NLA_U16 },
+	[NL80211_WOWLAN_TCP_DST_PORT] = { .type = NLA_U16 },
+	[NL80211_WOWLAN_TCP_DATA_PAYLOAD] = { .len = 1 },
+	[NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ] = {
+		.len = sizeof(struct nl80211_wowlan_tcp_data_seq)
+	},
+	[NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN] = {
+		.len = sizeof(struct nl80211_wowlan_tcp_data_token)
+	},
+	[NL80211_WOWLAN_TCP_DATA_INTERVAL] = { .type = NLA_U32 },
+	[NL80211_WOWLAN_TCP_WAKE_PAYLOAD] = { .len = 1 },
+	[NL80211_WOWLAN_TCP_WAKE_MASK] = { .len = 1 },
 };
 
 /* policy for GTK rekey offload attributes */
@@ -872,6 +893,48 @@ nla_put_failure:
 	return -ENOBUFS;
 }
 
+#ifdef CONFIG_PM
+static int nl80211_send_wowlan_tcp_caps(struct cfg80211_registered_device *rdev,
+					struct sk_buff *msg)
+{
+	const struct wiphy_wowlan_tcp_support *tcp = rdev->wiphy.wowlan.tcp;
+	struct nlattr *nl_tcp;
+
+	if (!tcp)
+		return 0;
+
+	nl_tcp = nla_nest_start(msg, NL80211_WOWLAN_TRIG_TCP_CONNECTION);
+	if (!nl_tcp)
+		return -ENOBUFS;
+
+	if (nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD,
+			tcp->data_payload_max))
+		return -ENOBUFS;
+
+	if (nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD,
+			tcp->data_payload_max))
+		return -ENOBUFS;
+
+	if (tcp->seq && nla_put_flag(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ))
+		return -ENOBUFS;
+
+	if (tcp->tok && nla_put(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN,
+				sizeof(*tcp->tok), tcp->tok))
+		return -ENOBUFS;
+
+	if (nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_INTERVAL,
+			tcp->data_interval_max))
+		return -ENOBUFS;
+
+	if (nla_put_u32(msg, NL80211_WOWLAN_TCP_WAKE_PAYLOAD,
+			tcp->wake_payload_max))
+		return -ENOBUFS;
+
+	nla_nest_end(msg, nl_tcp);
+	return 0;
+}
+#endif
+
 static int nl80211_send_wiphy(struct sk_buff *msg, u32 portid, u32 seq, int flags,
 			      struct cfg80211_registered_device *dev)
 {
@@ -1244,6 +1307,9 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 portid, u32 seq, int flag
 				goto nla_put_failure;
 		}
 
+		if (nl80211_send_wowlan_tcp_caps(dev, msg))
+			goto nla_put_failure;
+
 		nla_nest_end(msg, nl_wowlan);
 	}
 #endif
@@ -6895,16 +6961,67 @@ static int nl80211_leave_mesh(struct sk_buff *skb, struct genl_info *info)
 }
 
 #ifdef CONFIG_PM
+static int nl80211_send_wowlan_tcp(struct sk_buff *msg,
+				   struct cfg80211_wowlan_tcp *tcp)
+{
+	struct nlattr *nl_tcp;
+
+	if (!tcp)
+		return 0;
+
+	nl_tcp = nla_nest_start(msg, NL80211_WOWLAN_TRIG_TCP_CONNECTION);
+	if (!nl_tcp)
+		return -ENOBUFS;
+
+	if (nla_put_be32(msg, NL80211_WOWLAN_TCP_SRC_IPV4, tcp->src) ||
+	    nla_put_be32(msg, NL80211_WOWLAN_TCP_DST_IPV4, tcp->dst) ||
+	    nla_put(msg, NL80211_WOWLAN_TCP_DST_MAC, ETH_ALEN, tcp->dst_mac) ||
+	    nla_put_u16(msg, NL80211_WOWLAN_TCP_SRC_PORT, tcp->src_port) ||
+	    nla_put_u16(msg, NL80211_WOWLAN_TCP_DST_PORT, tcp->dst_port) ||
+	    nla_put(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD,
+		    tcp->payload_len, tcp->payload) ||
+	    nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_INTERVAL,
+			tcp->data_interval) ||
+	    nla_put(msg, NL80211_WOWLAN_TCP_WAKE_PAYLOAD,
+		    tcp->wake_len, tcp->wake_data) ||
+	    nla_put(msg, NL80211_WOWLAN_TCP_WAKE_MASK,
+		    DIV_ROUND_UP(tcp->wake_len, 8), tcp->wake_mask))
+		return -ENOBUFS;
+
+	if (tcp->payload_seq.len &&
+	    nla_put(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ,
+		    sizeof(tcp->payload_seq), &tcp->payload_seq))
+		return -ENOBUFS;
+
+	if (tcp->payload_tok.len &&
+	    nla_put(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN,
+		    sizeof(tcp->payload_tok) + tcp->tokens_size,
+		    &tcp->payload_tok))
+		return -ENOBUFS;
+
+	return 0;
+}
+
 static int nl80211_get_wowlan(struct sk_buff *skb, struct genl_info *info)
 {
 	struct cfg80211_registered_device *rdev = info->user_ptr[0];
 	struct sk_buff *msg;
 	void *hdr;
+	u32 size = NLMSG_DEFAULT_SIZE;
 
-	if (!rdev->wiphy.wowlan.flags && !rdev->wiphy.wowlan.n_patterns)
+	if (!rdev->wiphy.wowlan.flags && !rdev->wiphy.wowlan.n_patterns &&
+	    !rdev->wiphy.wowlan.tcp)
 		return -EOPNOTSUPP;
 
-	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+	if (rdev->wowlan && rdev->wowlan->tcp) {
+		/* adjust size to have room for all the data */
+		size += rdev->wowlan->tcp->tokens_size +
+			rdev->wowlan->tcp->payload_len +
+			rdev->wowlan->tcp->wake_len +
+			rdev->wowlan->tcp->wake_len / 8;
+	}
+
+	msg = nlmsg_new(size, GFP_KERNEL);
 	if (!msg)
 		return -ENOMEM;
 
@@ -6961,6 +7078,9 @@ static int nl80211_get_wowlan(struct sk_buff *skb, struct genl_info *info)
 			nla_nest_end(msg, nl_pats);
 		}
 
+		if (nl80211_send_wowlan_tcp(msg, rdev->wowlan->tcp))
+			goto nla_put_failure;
+
 		nla_nest_end(msg, nl_wowlan);
 	}
 
@@ -6972,6 +7092,150 @@ nla_put_failure:
 	return -ENOBUFS;
 }
 
+static int nl80211_parse_wowlan_tcp(struct cfg80211_registered_device *rdev,
+				    struct nlattr *attr,
+				    struct cfg80211_wowlan *trig)
+{
+	struct nlattr *tb[NUM_NL80211_WOWLAN_TCP];
+	struct cfg80211_wowlan_tcp *cfg;
+	struct nl80211_wowlan_tcp_data_token *tok = NULL;
+	struct nl80211_wowlan_tcp_data_seq *seq = NULL;
+	u32 size;
+	u32 data_size, wake_size, tokens_size = 0, wake_mask_size;
+	int err, port;
+
+	if (!rdev->wiphy.wowlan.tcp)
+		return -EINVAL;
+
+	err = nla_parse(tb, MAX_NL80211_WOWLAN_TCP,
+			nla_data(attr), nla_len(attr),
+			nl80211_wowlan_tcp_policy);
+	if (err)
+		return err;
+
+	if (!tb[NL80211_WOWLAN_TCP_SRC_IPV4] ||
+	    !tb[NL80211_WOWLAN_TCP_DST_IPV4] ||
+	    !tb[NL80211_WOWLAN_TCP_DST_MAC] ||
+	    !tb[NL80211_WOWLAN_TCP_DST_PORT] ||
+	    !tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD] ||
+	    !tb[NL80211_WOWLAN_TCP_DATA_INTERVAL] ||
+	    !tb[NL80211_WOWLAN_TCP_WAKE_PAYLOAD] ||
+	    !tb[NL80211_WOWLAN_TCP_WAKE_MASK])
+		return -EINVAL;
+
+	data_size = nla_len(tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD]);
+	if (data_size > rdev->wiphy.wowlan.tcp->data_payload_max)
+		return -EINVAL;
+
+	if (nla_get_u32(tb[NL80211_WOWLAN_TCP_DATA_INTERVAL]) >
+			rdev->wiphy.wowlan.tcp->data_interval_max)
+		return -EINVAL;
+
+	wake_size = nla_len(tb[NL80211_WOWLAN_TCP_WAKE_PAYLOAD]);
+	if (wake_size > rdev->wiphy.wowlan.tcp->wake_payload_max)
+		return -EINVAL;
+
+	wake_mask_size = nla_len(tb[NL80211_WOWLAN_TCP_WAKE_MASK]);
+	if (wake_mask_size != DIV_ROUND_UP(wake_size, 8))
+		return -EINVAL;
+
+	if (tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN]) {
+		u32 tokln = nla_len(tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN]);
+
+		tok = nla_data(tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN]);
+		tokens_size = tokln - sizeof(*tok);
+
+		if (!tok->len || tokens_size % tok->len)
+			return -EINVAL;
+		if (!rdev->wiphy.wowlan.tcp->tok)
+			return -EINVAL;
+		if (tok->len > rdev->wiphy.wowlan.tcp->tok->max_len)
+			return -EINVAL;
+		if (tok->len < rdev->wiphy.wowlan.tcp->tok->min_len)
+			return -EINVAL;
+		if (tokens_size > rdev->wiphy.wowlan.tcp->tok->bufsize)
+			return -EINVAL;
+		if (tok->offset + tok->len > data_size)
+			return -EINVAL;
+	}
+
+	if (tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ]) {
+		seq = nla_data(tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ]);
+		if (!rdev->wiphy.wowlan.tcp->seq)
+			return -EINVAL;
+		if (seq->len == 0 || seq->len > 4)
+			return -EINVAL;
+		if (seq->len + seq->offset > data_size)
+			return -EINVAL;
+	}
+
+	size = sizeof(*cfg);
+	size += data_size;
+	size += wake_size + wake_mask_size;
+	size += tokens_size;
+
+	cfg = kzalloc(size, GFP_KERNEL);
+	if (!cfg)
+		return -ENOMEM;
+	cfg->src = nla_get_be32(tb[NL80211_WOWLAN_TCP_SRC_IPV4]);
+	cfg->dst = nla_get_be32(tb[NL80211_WOWLAN_TCP_DST_IPV4]);
+	memcpy(cfg->dst_mac, nla_data(tb[NL80211_WOWLAN_TCP_DST_MAC]),
+	       ETH_ALEN);
+	if (tb[NL80211_WOWLAN_TCP_SRC_PORT])
+		port = nla_get_u16(tb[NL80211_WOWLAN_TCP_SRC_PORT]);
+	else
+		port = 0;
+#ifdef CONFIG_INET
+	/* allocate a socket and port for it and use it */
+	err = __sock_create(wiphy_net(&rdev->wiphy), PF_INET, SOCK_STREAM,
+			    IPPROTO_TCP, &cfg->sock, 1);
+	if (err) {
+		kfree(cfg);
+		return err;
+	}
+	if (inet_csk_get_port(cfg->sock->sk, port)) {
+		sock_release(cfg->sock);
+		kfree(cfg);
+		return -EADDRINUSE;
+	}
+	cfg->src_port = inet_sk(cfg->sock->sk)->inet_num;
+#else
+	if (!port) {
+		kfree(cfg);
+		return -EINVAL;
+	}
+	cfg->src_port = port;
+#endif
+
+	cfg->dst_port = nla_get_u16(tb[NL80211_WOWLAN_TCP_DST_PORT]);
+	cfg->payload_len = data_size;
+	cfg->payload = (u8 *)cfg + sizeof(*cfg) + tokens_size;
+	memcpy((void *)cfg->payload,
+	       nla_data(tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD]),
+	       data_size);
+	if (seq)
+		cfg->payload_seq = *seq;
+	cfg->data_interval = nla_get_u32(tb[NL80211_WOWLAN_TCP_DATA_INTERVAL]);
+	cfg->wake_len = wake_size;
+	cfg->wake_data = (u8 *)cfg + sizeof(*cfg) + tokens_size + data_size;
+	memcpy((void *)cfg->wake_data,
+	       nla_data(tb[NL80211_WOWLAN_TCP_WAKE_PAYLOAD]),
+	       wake_size);
+	cfg->wake_mask = (u8 *)cfg + sizeof(*cfg) + tokens_size +
+			 data_size + wake_size;
+	memcpy((void *)cfg->wake_mask,
+	       nla_data(tb[NL80211_WOWLAN_TCP_WAKE_MASK]),
+	       wake_mask_size);
+	if (tok) {
+		cfg->tokens_size = tokens_size;
+		memcpy(&cfg->payload_tok, tok, sizeof(*tok) + tokens_size);
+	}
+
+	trig->tcp = cfg;
+
+	return 0;
+}
+
 static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
 {
 	struct cfg80211_registered_device *rdev = info->user_ptr[0];
@@ -6982,7 +7246,8 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
 	int err, i;
 	bool prev_enabled = rdev->wowlan;
 
-	if (!rdev->wiphy.wowlan.flags && !rdev->wiphy.wowlan.n_patterns)
+	if (!rdev->wiphy.wowlan.flags && !rdev->wiphy.wowlan.n_patterns &&
+	    !rdev->wiphy.wowlan.tcp)
 		return -EOPNOTSUPP;
 
 	if (!info->attrs[NL80211_ATTR_WOWLAN_TRIGGERS]) {
@@ -7100,6 +7365,14 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
 		}
 	}
 
+	if (tb[NL80211_WOWLAN_TRIG_TCP_CONNECTION]) {
+		err = nl80211_parse_wowlan_tcp(
+			rdev, tb[NL80211_WOWLAN_TRIG_TCP_CONNECTION],
+			&new_triggers);
+		if (err)
+			goto error;
+	}
+
 	ntrig = kmemdup(&new_triggers, sizeof(new_triggers), GFP_KERNEL);
 	if (!ntrig) {
 		err = -ENOMEM;
@@ -7117,6 +7390,9 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
 	for (i = 0; i < new_triggers.n_patterns; i++)
 		kfree(new_triggers.patterns[i].mask);
 	kfree(new_triggers.patterns);
+	if (new_triggers.tcp && new_triggers.tcp->sock)
+		sock_release(new_triggers.tcp->sock);
+	kfree(new_triggers.tcp);
 	return err;
 }
 #endif
@@ -9398,6 +9674,17 @@ void cfg80211_report_wowlan_wakeup(struct wireless_dev *wdev,
 				wakeup->pattern_idx))
 			goto free_msg;
 
+		if (wakeup->tcp_match)
+			nla_put_flag(msg, NL80211_WOWLAN_TRIG_WAKEUP_TCP_MATCH);
+
+		if (wakeup->tcp_connlost)
+			nla_put_flag(msg,
+				     NL80211_WOWLAN_TRIG_WAKEUP_TCP_CONNLOST);
+
+		if (wakeup->tcp_nomoretokens)
+			nla_put_flag(msg,
+				NL80211_WOWLAN_TRIG_WAKEUP_TCP_NOMORETOKENS);
+
 		if (wakeup->packet) {
 			u32 pkt_attr = NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211;
 			u32 len_attr = NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211_LEN;
-- 
1.8.0

^ permalink raw reply related


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