Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH 4/5] drivers/net/ethernet/mellanox/mlx4/mcg.c: fix error return code
From: David Miller @ 2012-08-15  0:01 UTC (permalink / raw)
  To: Julia.Lawall; +Cc: netdev, kernel-janitors, linux-kernel
In-Reply-To: <1344949115-13266-5-git-send-email-Julia.Lawall@lip6.fr>

From: Julia Lawall <Julia.Lawall@lip6.fr>
Date: Tue, 14 Aug 2012 14:58:34 +0200

> From: Julia Lawall <Julia.Lawall@lip6.fr>
> 
> Convert a 0 error return code to a negative one, as returned elsewhere in the
> function.
> 
> A simplified version of the semantic match that finds this problem is as
> follows: (http://coccinelle.lip6.fr/)
 ...
> Signed-off-by: Julia Lawall <Julia.Lawall@lip6.fr>

Applied.

^ permalink raw reply

* Re: [PATCH net] ipv6: addrconf: Avoid calling netdevice notifiers with RCU read-side lock
From: David Miller @ 2012-08-15  0:02 UTC (permalink / raw)
  To: bhutchings
  Cc: netdev, john.r.fastabend, gregory.v.rose, tgraf, edumazet, amwang
In-Reply-To: <1344970491.2690.8.camel@bwh-desktop.uk.solarflarecom.com>

From: Ben Hutchings <bhutchings@solarflare.com>
Date: Tue, 14 Aug 2012 19:54:51 +0100

> Cong Wang reports that lockdep detected suspicious RCU usage while
> enabling IPV6 forwarding:
 ...
> addrconf_forward_change() uses RCU iteration over the netdev list,
> which is unnecessary since it already holds the RTNL lock.  We also
> cannot reasonably require netdevice notifier functions not to sleep.
> 
> Reported-by: Cong Wang <amwang@redhat.com>
> Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>

Applied and queued up for -stable, thanks Ben.

^ permalink raw reply

* Re: pull request: wireless 2012-08-14
From: David Miller @ 2012-08-15  0:04 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, netdev, linux-kernel
In-Reply-To: <20120814190245.GA22136@tuxdriver.com>

From: "John W. Linville" <linville@tuxdriver.com>
Date: Tue, 14 Aug 2012 15:02:46 -0400

> Alexey Khoroshilov provides a potential memory leak in rndis_wlan.
> 
> Bob Copeland gives us an ath5k fix for a lockdep problem.
> 
> Dan Carpenter fixes a signedness mismatch in at76c50x.
> 
> Felix Fietkau corrects a regression caused by an earlier commit that can
> lead to an IRQ storm.
> 
> Lorenzo Bianconi offers a fix for a bad variable initialization in ath9k
> that can cause it to improperly mark decrypted frames.
> 
> Rajkumar Manoharan fixes ath9k to prevent the btcoex time from running
> when the hardware is asleep.
> 
> The remainder are Bluetooth fixes, about which Gustavo says:
> 
> 	"Here goes some fixes for 3.6-rc1, there are a few fix to
> 	thte inquiry code by Ram Malovany, support for 2 new devices,
> 	and few others fixes for NULL dereference, possible deadlock
> 	and a memory leak."
> 
> Please let me know if there are problems!

Pulled, thanks John.

^ permalink raw reply

* Re: [REVIEW][PATCH 0/21] User namespace changes to the networking stack.
From: David Miller @ 2012-08-15  0:12 UTC (permalink / raw)
  To: ebiederm-aS9lmoZGLiVWk0Htik3J/w
  Cc: netdev-u79uwXL29TY76Z2rM5mHXA,
	containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA
In-Reply-To: <87ehnav9n5.fsf-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org>

From: ebiederm-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org (Eric W. Biederman)
Date: Mon, 13 Aug 2012 13:07:10 -0700

> 
> This is a modest set of changes against the current networking stack to
> enable basic user namespace support.  Allowing the code to compile with
> user namespaces enabled and removing the assumption that there is only
> the initial user namespace.
> 
> Work to relax the privilege checks in the networking stack from
> "capable(CAP_NET_ADMIN)" or "capable(CAP_NET_RAW)" to
> "ns_capable(net->user_ns, CAP_NET_ADMIN)" or 
> "ns_capable(net->user_ns, CAP_NET_RAW)" allowing root in a user
> namespace to control a network namespace will come later.
> 
> David there are just enough interdependencies between the user namespace
> bits that I intend to merge them all through my user namespace tree.
> After the review is complete I will add these patches to my for-next
> branch of my user-namespace.git tree where I do not intend to rebase.
> If it make sense to pull these into net-next to avoid or reduce
> conflicts that should not be a problem.

Looks fine to me, you can add:

Acked-by: David S. Miller <davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org>

to all of this stuff.  Let me know when something is stable in your
tree, and I can therefore pull from it into net-next.

^ permalink raw reply

* Re: [PATCH 01/16] hashtable: introduce a small and naive hashtable
From: Sasha Levin @ 2012-08-15  0:24 UTC (permalink / raw)
  To: NeilBrown
  Cc: snitzer-H+wXaHxf7aLQT0dZR+AlfA, fweisbec-Re5JQEeQqe8AvxtiuMwx3w,
	Trond.Myklebust-HgOvQuBEEgTQT0dZR+AlfA,
	bfields-uC3wQj2KruNg9hUCZPvPmw,
	paul.gortmaker-CWA4WttNNZF54TAoqtyWWQ,
	dm-devel-H+wXaHxf7aLQT0dZR+AlfA, agk-H+wXaHxf7aLQT0dZR+AlfA,
	aarcange-H+wXaHxf7aLQT0dZR+AlfA, rds-devel-N0ozoZBvEnrZJqsBc5GL+g,
	eric.dumazet-Re5JQEeQqe8AvxtiuMwx3w,
	venkat.x.venkatsubra-QHcLZuEGTsvQT0dZR+AlfA,
	ccaulfie-H+wXaHxf7aLQT0dZR+AlfA, mingo-X9Un+BFzKDI,
	dev-yBygre7rU0TnMu66kgdUjQ, ericvh-Re5JQEeQqe8AvxtiuMwx3w,
	josh-iaAMLnmF4UmaiuxdJuQwMA, rostedt-nx8X9YLhiw1AfugRpC6u6w,
	lw-BthXqXjhjHXQFUHtdCDX3A,
	mathieu.desnoyers-vg+e7yoeK/dWk0Htik3J/w,
	axboe-tSWWG44O7X1aa/9Udqfwiw, linux-nfs-u79uwXL29TY76Z2rM5mHXA,
	edumazet-hpIqsD4AKlfQT0dZR+AlfA, linux-mm-Bw31MaZKKs3YtjvyW6yDsg,
	netdev-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, ejt-H+wXaHxf7aLQT0dZR+AlfA,
	ebiederm-aS9lmoZGLiVWk0Htik3J/w, tj-DgEjT+Ai2ygdnm+yROfE0A,
	teigland-H+wXaHxf7aLQT0dZR+AlfA,
	akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b,
	torvalds-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b,
	davem-fT/PcQaiUtIeIZ0/mPfg9Q
In-Reply-To: <20120815092523.00a909ef-wvvUuzkyo1EYVZTmpyfIwg@public.gmane.org>

On 08/15/2012 01:25 AM, NeilBrown wrote:
> On Tue, 14 Aug 2012 18:24:35 +0200 Sasha Levin <levinsasha928-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> wrote:
> 
> 
>> +static inline void hash_init_size(struct hlist_head *hashtable, int bits)
>> +{
>> +	int i;
>> +
>> +	for (i = 0; i < HASH_SIZE(bits); i++)
>> +		INIT_HLIST_HEAD(hashtable + i);
>> +}
> 
> This seems like an inefficient way to do "memset(hashtable, 0, ...);".
> And in many cases it isn't needed as the hash table is static and initialised
> to zero.
> I note that in the SUNRPC/cache patch you call hash_init(), but in the lockd
> patch you don't.  You don't actually need to in either case.

Agreed that the code will run just fine if we wouldn't use hash_init().

> I realise that any optimisation here is for code that is only executed once
> per boot, so no big deal, and even the presence of extra code making the
> kernel bigger is unlikely to be an issue.  But I'd at least like to see
> consistency: Either use hash_init everywhere, even when not needed, or only
> use it where absolutely needed which might be no-where because static tables
> are already initialised, and dynamic tables can use GFP_ZERO.

This is a consistency problem. I didn't want to add a module_init() to modules that didn't have it just to get hash_init() in there.

I'll get it fixed.

> And if you keep hash_init_size I would rather see a memset(0)....

My concern with using a memset(0) is that I'm going to break layering.

The hashtable uses hlist. hlist provides us with an entire family of init functions which I'm supposed to use to initialize hlist heads.

So while a memset(0) will work perfectly here, I consider that cheating - it results in an uglier code that assumes to know about hlist internals, and will probably break as soon as someone tries to do something to hlist.

I can think of several alternatives here, and all of them involve changes to hlist instead of the hashtable:

 - Remove INIT_HLIST_HEAD()/HLIST_HEAD()/HLIST_HEAD_INIT() and introduce a CLEAR_HLIST instead, documenting that it's enough to memset(0) the hlist to initialize it properly.
 - Add a block initializer INIT_HLIST_HEADS() or something similar that would initialize an array of heads.

^ permalink raw reply

* Re: [PATCH 01/16] hashtable: introduce a small and naive hashtable
From: Tejun Heo @ 2012-08-15  0:28 UTC (permalink / raw)
  To: Sasha Levin
  Cc: NeilBrown, torvalds, akpm, linux-kernel, linux-mm, paul.gortmaker,
	davem, rostedt, mingo, ebiederm, aarcange, ericvh, netdev, josh,
	eric.dumazet, mathieu.desnoyers, axboe, agk, dm-devel, ccaulfie,
	teigland, Trond.Myklebust, bfields, fweisbec, jesse,
	venkat.x.venkatsubra, ejt, snitzer, edumazet, linux-nfs, dev,
	rds-devel, lw
In-Reply-To: <502AEC51.2010305@gmail.com>

Hello,

(Sasha, would it be possible to change your MUA so that it breaks long
 lines.  It's pretty difficult to reply to.)

On Wed, Aug 15, 2012 at 02:24:49AM +0200, Sasha Levin wrote:
> The hashtable uses hlist. hlist provides us with an entire family of
> init functions which I'm supposed to use to initialize hlist heads.
> 
> So while a memset(0) will work perfectly here, I consider that
> cheating - it results in an uglier code that assumes to know about
> hlist internals, and will probably break as soon as someone tries to
> do something to hlist.

I think we should stick with INIT_HLIST_HEAD().  It's not a hot path
and we might add, say, debug fields or initialization magics added
later.  If this really matters, the right thing to do would be adding
something like INIT_HLIST_HEAD_ARRAY().

Thanks.

-- 
tejun

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply

* Re: [PATCH 02/16] user_ns: use new hashtable implementation
From: Sasha Levin @ 2012-08-15  0:47 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: snitzer-H+wXaHxf7aLQT0dZR+AlfA, neilb-l3A5Bk7waGM,
	fweisbec-Re5JQEeQqe8AvxtiuMwx3w,
	Trond.Myklebust-HgOvQuBEEgTQT0dZR+AlfA,
	bfields-uC3wQj2KruNg9hUCZPvPmw,
	paul.gortmaker-CWA4WttNNZF54TAoqtyWWQ,
	dm-devel-H+wXaHxf7aLQT0dZR+AlfA, agk-H+wXaHxf7aLQT0dZR+AlfA,
	aarcange-H+wXaHxf7aLQT0dZR+AlfA, rds-devel-N0ozoZBvEnrZJqsBc5GL+g,
	eric.dumazet-Re5JQEeQqe8AvxtiuMwx3w,
	venkat.x.venkatsubra-QHcLZuEGTsvQT0dZR+AlfA,
	ccaulfie-H+wXaHxf7aLQT0dZR+AlfA, mingo-X9Un+BFzKDI,
	dev-yBygre7rU0TnMu66kgdUjQ, ericvh-Re5JQEeQqe8AvxtiuMwx3w,
	josh-iaAMLnmF4UmaiuxdJuQwMA, rostedt-nx8X9YLhiw1AfugRpC6u6w,
	lw-BthXqXjhjHXQFUHtdCDX3A,
	mathieu.desnoyers-vg+e7yoeK/dWk0Htik3J/w,
	axboe-tSWWG44O7X1aa/9Udqfwiw, linux-nfs-u79uwXL29TY76Z2rM5mHXA,
	edumazet-hpIqsD4AKlfQT0dZR+AlfA, linux-mm-Bw31MaZKKs3YtjvyW6yDsg,
	netdev-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, ejt-H+wXaHxf7aLQT0dZR+AlfA,
	tj-DgEjT+Ai2ygdnm+yROfE0A, teigland-H+wXaHxf7aLQT0dZR+AlfA,
	akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b,
	torvalds-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b,
	davem-fT/PcQaiUtIeIZ0/mPfg9Q
In-Reply-To: <87txw5hw0s.fsf-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org>

On 08/15/2012 01:52 AM, Eric W. Biederman wrote:
> Sasha Levin <levinsasha928-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> writes:
> 
>> Switch user_ns to use the new hashtable implementation. This reduces the amount of
>> generic unrelated code in user_ns.
> 
> Two concerns here.
> 1) When adding a new entry you recompute the hash where previously that
>    was not done.  I believe that will slow down adding of new entries.

I figured that the price for the extra hashing isn't significant since hash_32
is just a multiplication and a shift.

I'll modify the code to calculate the key just once.

> 2) Using hash_32 for uids is an interesting choice.  hash_32 discards
>    the low bits.  Last I checked for uids the low bits were the bits
>    that were most likely to be different and had the most entropy.
> 
>    I'm not certain how multiplying by the GOLDEN_RATION_PRIME_32 will
>    affect things but I would be surprised if it shifted all of the
>    randomness from the low bits to the high bits.

"Is hash_* good enough for our purpose?" - I was actually surprised that no one
raised that question during the RFC and assumed it was because everybody agreed
that it's indeed good enough.

I can offer the following: I'll write a small module that will hash 1...10000
into a hashtable which uses 7 bits (just like user_ns) and post the distribution
we'll get.

If the results of the above will be satisfactory we can avoid the discussion
about which hash function we should really be using. If not, I guess now is a
good time for that :)

^ permalink raw reply

* Re: [REVIEW][PATCH 0/21] User namespace changes to the networking stack.
From: Eric W. Biederman @ 2012-08-15  0:47 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, containers, serge
In-Reply-To: <20120814.171203.1784557890475348401.davem@davemloft.net>

David Miller <davem@davemloft.net> writes:

> From: ebiederm@xmission.com (Eric W. Biederman)
> Date: Mon, 13 Aug 2012 13:07:10 -0700
>
>> 
>> This is a modest set of changes against the current networking stack to
>> enable basic user namespace support.  Allowing the code to compile with
>> user namespaces enabled and removing the assumption that there is only
>> the initial user namespace.
>> 
>> Work to relax the privilege checks in the networking stack from
>> "capable(CAP_NET_ADMIN)" or "capable(CAP_NET_RAW)" to
>> "ns_capable(net->user_ns, CAP_NET_ADMIN)" or 
>> "ns_capable(net->user_ns, CAP_NET_RAW)" allowing root in a user
>> namespace to control a network namespace will come later.
>> 
>> David there are just enough interdependencies between the user namespace
>> bits that I intend to merge them all through my user namespace tree.
>> After the review is complete I will add these patches to my for-next
>> branch of my user-namespace.git tree where I do not intend to rebase.
>> If it make sense to pull these into net-next to avoid or reduce
>> conflicts that should not be a problem.
>
> Looks fine to me, you can add:
>
> Acked-by: David S. Miller <davem@davemloft.net>
>
> to all of this stuff.  Let me know when something is stable in your
> tree, and I can therefore pull from it into net-next.

Will do.  It doesn't look like anyone has any problems with this stuff,
so that should be shortly.

Eric

^ permalink raw reply

* Re: [PATCH 02/16] user_ns: use new hashtable implementation
From: Eric W. Biederman @ 2012-08-15  1:08 UTC (permalink / raw)
  To: Sasha Levin
  Cc: torvalds-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b,
	tj-DgEjT+Ai2ygdnm+yROfE0A, akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg,
	paul.gortmaker-CWA4WttNNZF54TAoqtyWWQ,
	davem-fT/PcQaiUtIeIZ0/mPfg9Q, rostedt-nx8X9YLhiw1AfugRpC6u6w,
	mingo-X9Un+BFzKDI, aarcange-H+wXaHxf7aLQT0dZR+AlfA,
	ericvh-Re5JQEeQqe8AvxtiuMwx3w, netdev-u79uwXL29TY76Z2rM5mHXA,
	josh-iaAMLnmF4UmaiuxdJuQwMA, eric.dumazet-Re5JQEeQqe8AvxtiuMwx3w,
	mathieu.desnoyers-vg+e7yoeK/dWk0Htik3J/w,
	axboe-tSWWG44O7X1aa/9Udqfwiw, agk-H+wXaHxf7aLQT0dZR+AlfA,
	dm-devel-H+wXaHxf7aLQT0dZR+AlfA, neilb-l3A5Bk7waGM,
	ccaulfie-H+wXaHxf7aLQT0dZR+AlfA, teigland-H+wXaHxf7aLQT0dZR+AlfA,
	Trond.Myklebust-HgOvQuBEEgTQT0dZR+AlfA,
	bfields-uC3wQj2KruNg9hUCZPvPmw, fweisbec-Re5JQEeQqe8AvxtiuMwx3w,
	jesse-l0M0P4e3n4LQT0dZR+AlfA,
	venkat.x.venkatsubra-QHcLZuEGTsvQT0dZR+AlfA,
	ejt-H+wXaHxf7aLQT0dZR+AlfA, snitzer-H+wXaHxf7aLQT0dZR+AlfA,
	edumazet-hpIqsD4AKlfQT0dZR+AlfA, linux-nfs-u79uwXL29TY76Z2rM5mHXA,
	dev-yBygre7rU0TnMu66kgdUjQ, rds-devel-N0ozoZBvEnrZJqsBc5GL+g,
	lw-BthXqXjhjHXQFUHtdCDX3A
In-Reply-To: <502AF184.4010907-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

Sasha Levin <levinsasha928-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> writes:

> On 08/15/2012 01:52 AM, Eric W. Biederman wrote:
>> Sasha Levin <levinsasha928-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> writes:
>> 
>>> Switch user_ns to use the new hashtable implementation. This reduces the amount of
>>> generic unrelated code in user_ns.
>> 
>> Two concerns here.
>> 1) When adding a new entry you recompute the hash where previously that
>>    was not done.  I believe that will slow down adding of new entries.
>
> I figured that the price for the extra hashing isn't significant since hash_32
> is just a multiplication and a shift.
>
> I'll modify the code to calculate the key just once.

Honestly I don't know either way, but it seemed a shame to give up a
common and trivial optimization.

>> 2) Using hash_32 for uids is an interesting choice.  hash_32 discards
>>    the low bits.  Last I checked for uids the low bits were the bits
>>    that were most likely to be different and had the most entropy.
>> 
>>    I'm not certain how multiplying by the GOLDEN_RATION_PRIME_32 will
>>    affect things but I would be surprised if it shifted all of the
>>    randomness from the low bits to the high bits.
>
> "Is hash_* good enough for our purpose?" - I was actually surprised that no one
> raised that question during the RFC and assumed it was because everybody agreed
> that it's indeed good enough.
>
> I can offer the following: I'll write a small module that will hash 1...10000
> into a hashtable which uses 7 bits (just like user_ns) and post the distribution
> we'll get.

That won't hurt.  I think 1-100 then 1000-1100 may actually be more
representative.  Not that I would mind seeing the larger range.
Especially since I am in the process of encouraging the use of more
uids.

> If the results of the above will be satisfactory we can avoid the discussion
> about which hash function we should really be using. If not, I guess now is a
> good time for that :)

Yes.  A small emperical test sounds good.

Eric

--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [RFC net-next 3/4] gianfar: Separate out the Rx and Tx coalescing functions
From: Paul Gortmaker @ 2012-08-15  1:29 UTC (permalink / raw)
  To: Claudiu Manoil; +Cc: netdev, David S. Miller
In-Reply-To: <1344428810-29923-4-git-send-email-claudiu.manoil@freescale.com>

[[RFC net-next 3/4] gianfar: Separate out the Rx and Tx coalescing functions] On 08/08/2012 (Wed 15:26) Claudiu Manoil wrote:

> Split the coalescing programming support by Rx and Tx h/w queues, in order to
> introduce a separate NAPI for the Tx confirmation path (next patch). This way,
> the Rx processing path will handle the coalescing settings for the Rx queues
> only, resp. the Tx confirmation processing path will handle the Tx queues.
> 
> Signed-off-by: Claudiu Manoil <claudiu.manoil@freescale.com>
> ---
>  drivers/net/ethernet/freescale/gianfar.c |   36 +++++++++++++++++++++++------
>  1 files changed, 28 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c
> index ddd350a..919acb3 100644
> --- a/drivers/net/ethernet/freescale/gianfar.c
> +++ b/drivers/net/ethernet/freescale/gianfar.c
> @@ -1794,8 +1794,8 @@ void gfar_start(struct net_device *dev)
>  	dev->trans_start = jiffies; /* prevent tx timeout */
>  }
>  
> -void gfar_configure_coalescing(struct gfar_private *priv,
> -			       unsigned long tx_mask, unsigned long rx_mask)
> +static inline void gfar_configure_tx_coalescing(struct gfar_private *priv,
> +						unsigned long mask)

Hi Claudiu,

I had it in mind to mention this earlier, but forgot.  Align line two
(and three, and four...) of args with the 1st arg in line one, and
you'll save yourself needing a resend for basic formatting issues.

In other words, you need:

void foo(int some_really_long_line, struct blah *more_long_line,
         int b, ... )

i.e. allowing for mail mangling, make sure you have the the two int
directly over each other, in the example above.

Thanks,
Paul.
--

>  {
>  	struct gfar __iomem *regs = priv->gfargrp[0].regs;
>  	u32 __iomem *baddr;
> @@ -1803,14 +1803,31 @@ void gfar_configure_coalescing(struct gfar_private *priv,
>  	if (priv->mode == MQ_MG_MODE) {
>  		int i;
>  		baddr = &regs->txic0;
> -		for_each_set_bit(i, &tx_mask, priv->num_tx_queues) {
> +		for_each_set_bit(i, &mask, priv->num_tx_queues) {
>  			gfar_write(baddr + i, 0);
>  			if (likely(priv->tx_queue[i]->txcoalescing))
>  				gfar_write(baddr + i, priv->tx_queue[i]->txic);
>  		}
> +	} else {
> +		/* Backward compatible case ---- even if we enable
> +		 * multiple queues, there's only single reg to program
> +		 */
> +		gfar_write(&regs->txic, 0);
> +		if (likely(priv->tx_queue[0]->txcoalescing))
> +			gfar_write(&regs->txic, priv->tx_queue[0]->txic);
> +	}
> +}
> +
> +static inline void gfar_configure_rx_coalescing(struct gfar_private *priv,
> +						unsigned long mask)
> +{
> +	struct gfar __iomem *regs = priv->gfargrp[0].regs;
> +	u32 __iomem *baddr;
>  
> +	if (priv->mode == MQ_MG_MODE) {
> +		int i;
>  		baddr = &regs->rxic0;
> -		for_each_set_bit(i, &rx_mask, priv->num_rx_queues) {
> +		for_each_set_bit(i, &mask, priv->num_rx_queues) {
>  			gfar_write(baddr + i, 0);
>  			if (likely(priv->rx_queue[i]->rxcoalescing))
>  				gfar_write(baddr + i, priv->rx_queue[i]->rxic);
> @@ -1819,16 +1836,19 @@ void gfar_configure_coalescing(struct gfar_private *priv,
>  		/* Backward compatible case ---- even if we enable
>  		 * multiple queues, there's only single reg to program
>  		 */
> -		gfar_write(&regs->txic, 0);
> -		if (likely(priv->tx_queue[0]->txcoalescing))
> -			gfar_write(&regs->txic, priv->tx_queue[0]->txic);
> -
>  		gfar_write(&regs->rxic, 0);
>  		if (likely(priv->rx_queue[0]->rxcoalescing))
>  			gfar_write(&regs->rxic, priv->rx_queue[0]->rxic);
>  	}
>  }
>  
> +void gfar_configure_coalescing(struct gfar_private *priv,
> +			       unsigned long tx_mask, unsigned long rx_mask)
> +{
> +	gfar_configure_tx_coalescing(priv, tx_mask);
> +	gfar_configure_rx_coalescing(priv, rx_mask);
> +}
> +
>  static int register_grp_irqs(struct gfar_priv_grp *grp)
>  {
>  	struct gfar_private *priv = grp->priv;
> -- 
> 1.6.6
> 
> 

^ permalink raw reply

* Re: [PATCH 02/16] user_ns: use new hashtable implementation
From: Sasha Levin @ 2012-08-15  1:35 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: torvalds, tj, akpm, linux-kernel, linux-mm, paul.gortmaker, davem,
	rostedt, mingo, aarcange, ericvh, netdev, josh, eric.dumazet,
	mathieu.desnoyers, axboe, agk, dm-devel, neilb, ccaulfie,
	teigland, Trond.Myklebust, bfields, fweisbec, jesse,
	venkat.x.venkatsubra, ejt, snitzer, edumazet, linux-nfs, dev,
	rds-devel, lw
In-Reply-To: <87393phshy.fsf@xmission.com>

On 08/15/2012 03:08 AM, Eric W. Biederman wrote:
>> I can offer the following: I'll write a small module that will hash 1...10000
>> > into a hashtable which uses 7 bits (just like user_ns) and post the distribution
>> > we'll get.
> That won't hurt.  I think 1-100 then 1000-1100 may actually be more
> representative.  Not that I would mind seeing the larger range.
> Especially since I am in the process of encouraging the use of more
> uids.
> 

Alrighty, the results are in (numbers are objects in bucket):

For the 0...10000 range:

Average: 78.125
Std dev: 1.4197704151
Min: 75
Max: 80


For the 1...100 range:

Average: 0.78125
Std dev: 0.5164613088
Min: 0
Max: 2


For the 1000...1100 range:

Average: 0.7890625
Std dev: 0.4964812206
Min: 0
Max: 2


Looks like hash_32 is pretty good with small numbers.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply

* [PATCH v2] XFRM: remove redundant parameter "int dir" in struct xfrm_mgr.acquire
From: Fan Du @ 2012-08-15  2:13 UTC (permalink / raw)
  To: davem; +Cc: netdev

Sematically speaking, xfrm_mgr.acquire is called when kernel intends to ask
user space IKE daemon to negotiate SAs with peers. IOW the direction will
*always* be XFRM_POLICY_OUT, so remove int dir for clarity.

Signed-off-by: Fan Du <fan.du@windriver.com>
---
Changelog for V2:
	- Remove "int dir" in build_acquire parameter suggested by Steffen Klassert.


 include/net/xfrm.h    |    2 +-
 net/key/af_key.c      |    4 ++--
 net/xfrm/xfrm_state.c |    2 +-
 net/xfrm/xfrm_user.c  |    9 ++++-----
 4 files changed, 8 insertions(+), 9 deletions(-)

diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 62b619e..5e1662d 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -571,7 +571,7 @@ struct xfrm_mgr {
 	struct list_head	list;
 	char			*id;
 	int			(*notify)(struct xfrm_state *x, const struct km_event *c);
-	int			(*acquire)(struct xfrm_state *x, struct xfrm_tmpl *, struct xfrm_policy *xp, int dir);
+	int			(*acquire)(struct xfrm_state *x, struct xfrm_tmpl *, struct xfrm_policy *xp);
 	struct xfrm_policy	*(*compile_policy)(struct sock *sk, int opt, u8 *data, int len, int *dir);
 	int			(*new_mapping)(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport);
 	int			(*notify_policy)(struct xfrm_policy *x, int dir, const struct km_event *c);
diff --git a/net/key/af_key.c b/net/key/af_key.c
index 34e4185..ec7d161 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -3024,7 +3024,7 @@ static u32 get_acqseq(void)
 	return res;
 }
 
-static int pfkey_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *xp, int dir)
+static int pfkey_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *xp)
 {
 	struct sk_buff *skb;
 	struct sadb_msg *hdr;
@@ -3105,7 +3105,7 @@ static int pfkey_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *t, struct
 	pol->sadb_x_policy_len = sizeof(struct sadb_x_policy)/sizeof(uint64_t);
 	pol->sadb_x_policy_exttype = SADB_X_EXT_POLICY;
 	pol->sadb_x_policy_type = IPSEC_POLICY_IPSEC;
-	pol->sadb_x_policy_dir = dir+1;
+	pol->sadb_x_policy_dir = XFRM_POLICY_OUT + 1;
 	pol->sadb_x_policy_id = xp->index;
 
 	/* Set sadb_comb's. */
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 87cd0e4..7856c33 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -1700,7 +1700,7 @@ int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol)
 
 	read_lock(&xfrm_km_lock);
 	list_for_each_entry(km, &xfrm_km_list, list) {
-		acqret = km->acquire(x, t, pol, XFRM_POLICY_OUT);
+		acqret = km->acquire(x, t, pol);
 		if (!acqret)
 			err = acqret;
 	}
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index e75d8e4..ab58034 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -2567,8 +2567,7 @@ static inline size_t xfrm_acquire_msgsize(struct xfrm_state *x,
 }
 
 static int build_acquire(struct sk_buff *skb, struct xfrm_state *x,
-			 struct xfrm_tmpl *xt, struct xfrm_policy *xp,
-			 int dir)
+			 struct xfrm_tmpl *xt, struct xfrm_policy *xp)
 {
 	__u32 seq = xfrm_get_acqseq();
 	struct xfrm_user_acquire *ua;
@@ -2583,7 +2582,7 @@ static int build_acquire(struct sk_buff *skb, struct xfrm_state *x,
 	memcpy(&ua->id, &x->id, sizeof(ua->id));
 	memcpy(&ua->saddr, &x->props.saddr, sizeof(ua->saddr));
 	memcpy(&ua->sel, &x->sel, sizeof(ua->sel));
-	copy_to_user_policy(xp, &ua->policy, dir);
+	copy_to_user_policy(xp, &ua->policy, XFRM_POLICY_OUT);
 	ua->aalgos = xt->aalgos;
 	ua->ealgos = xt->ealgos;
 	ua->calgos = xt->calgos;
@@ -2605,7 +2604,7 @@ static int build_acquire(struct sk_buff *skb, struct xfrm_state *x,
 }
 
 static int xfrm_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *xt,
-			     struct xfrm_policy *xp, int dir)
+			     struct xfrm_policy *xp)
 {
 	struct net *net = xs_net(x);
 	struct sk_buff *skb;
@@ -2614,7 +2613,7 @@ static int xfrm_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *xt,
 	if (skb == NULL)
 		return -ENOMEM;
 
-	if (build_acquire(skb, x, xt, xp, dir) < 0)
+	if (build_acquire(skb, x, xt, xp) < 0)
 		BUG();
 
 	return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_ACQUIRE, GFP_ATOMIC);
-- 
1.7.1

^ permalink raw reply related

* Re: [PATCH net] ipv6: addrconf: Avoid calling netdevice notifiers with RCU read-side lock
From: Cong Wang @ 2012-08-15  3:10 UTC (permalink / raw)
  To: Ben Hutchings
  Cc: David Miller, netdev, John Fastabend, Greg Rose, Thomas Graf,
	Eric Dumazet
In-Reply-To: <1344970491.2690.8.camel@bwh-desktop.uk.solarflarecom.com>

On Tue, 2012-08-14 at 19:54 +0100, Ben Hutchings wrote:
> Cong Wang reports that lockdep detected suspicious RCU usage while
> enabling IPV6 forwarding:
> 
>  [ 1123.310275] ===============================
>  [ 1123.442202] [ INFO: suspicious RCU usage. ]
>  [ 1123.558207] 3.6.0-rc1+ #109 Not tainted
>  [ 1123.665204] -------------------------------
>  [ 1123.768254] include/linux/rcupdate.h:430 Illegal context switch in RCU read-side critical section!
>  [ 1123.992320]
>  [ 1123.992320] other info that might help us debug this:
>  [ 1123.992320]
>  [ 1124.307382]
>  [ 1124.307382] rcu_scheduler_active = 1, debug_locks = 0
>  [ 1124.522220] 2 locks held by sysctl/5710:
>  [ 1124.648364]  #0:  (rtnl_mutex){+.+.+.}, at: [<ffffffff81768498>] rtnl_trylock+0x15/0x17
>  [ 1124.882211]  #1:  (rcu_read_lock){.+.+.+}, at: [<ffffffff81871df8>] rcu_lock_acquire+0x0/0x29
>  [ 1125.085209]
>  [ 1125.085209] stack backtrace:
>  [ 1125.332213] Pid: 5710, comm: sysctl Not tainted 3.6.0-rc1+ #109
>  [ 1125.441291] Call Trace:
>  [ 1125.545281]  [<ffffffff8109d915>] lockdep_rcu_suspicious+0x109/0x112
>  [ 1125.667212]  [<ffffffff8107c240>] rcu_preempt_sleep_check+0x45/0x47
>  [ 1125.781838]  [<ffffffff8107c260>] __might_sleep+0x1e/0x19b
> [...]
>  [ 1127.445223]  [<ffffffff81757ac5>] call_netdevice_notifiers+0x4a/0x4f
> [...]
>  [ 1127.772188]  [<ffffffff8175e125>] dev_disable_lro+0x32/0x6b
>  [ 1127.885174]  [<ffffffff81872d26>] dev_forward_change+0x30/0xcb
>  [ 1128.013214]  [<ffffffff818738c4>] addrconf_forward_change+0x85/0xc5
> [...]
> 
> addrconf_forward_change() uses RCU iteration over the netdev list,
> which is unnecessary since it already holds the RTNL lock.  We also
> cannot reasonably require netdevice notifier functions not to sleep.
> 
> Reported-by: Cong Wang <amwang@redhat.com>
> Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>

Thanks for your patch, Ben!

^ permalink raw reply

* Re: [PATCH 02/16] user_ns: use new hashtable implementation
From: Eric W. Biederman @ 2012-08-15  3:13 UTC (permalink / raw)
  To: Sasha Levin
  Cc: snitzer-H+wXaHxf7aLQT0dZR+AlfA, neilb-l3A5Bk7waGM,
	fweisbec-Re5JQEeQqe8AvxtiuMwx3w,
	Trond.Myklebust-HgOvQuBEEgTQT0dZR+AlfA,
	bfields-uC3wQj2KruNg9hUCZPvPmw,
	paul.gortmaker-CWA4WttNNZF54TAoqtyWWQ,
	dm-devel-H+wXaHxf7aLQT0dZR+AlfA, agk-H+wXaHxf7aLQT0dZR+AlfA,
	aarcange-H+wXaHxf7aLQT0dZR+AlfA, rds-devel-N0ozoZBvEnrZJqsBc5GL+g,
	eric.dumazet-Re5JQEeQqe8AvxtiuMwx3w,
	venkat.x.venkatsubra-QHcLZuEGTsvQT0dZR+AlfA,
	ccaulfie-H+wXaHxf7aLQT0dZR+AlfA, mingo-X9Un+BFzKDI,
	dev-yBygre7rU0TnMu66kgdUjQ, ericvh-Re5JQEeQqe8AvxtiuMwx3w,
	josh-iaAMLnmF4UmaiuxdJuQwMA, rostedt-nx8X9YLhiw1AfugRpC6u6w,
	lw-BthXqXjhjHXQFUHtdCDX3A,
	mathieu.desnoyers-vg+e7yoeK/dWk0Htik3J/w,
	axboe-tSWWG44O7X1aa/9Udqfwiw, linux-nfs-u79uwXL29TY76Z2rM5mHXA,
	edumazet-hpIqsD4AKlfQT0dZR+AlfA, linux-mm-Bw31MaZKKs3YtjvyW6yDsg,
	netdev-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, ejt-H+wXaHxf7aLQT0dZR+AlfA,
	tj-DgEjT+Ai2ygdnm+yROfE0A, teigland-H+wXaHxf7aLQT0dZR+AlfA,
	akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b,
	torvalds-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b,
	davem-fT/PcQaiUtIeIZ0/mPfg9Q
In-Reply-To: <502AFCD5.6070104-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

Sasha Levin <levinsasha928-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> writes:

> On 08/15/2012 03:08 AM, Eric W. Biederman wrote:
>>> I can offer the following: I'll write a small module that will hash 1...10000
>>> > into a hashtable which uses 7 bits (just like user_ns) and post the distribution
>>> > we'll get.
>> That won't hurt.  I think 1-100 then 1000-1100 may actually be more
>> representative.  Not that I would mind seeing the larger range.
>> Especially since I am in the process of encouraging the use of more
>> uids.
>> 
>
> Alrighty, the results are in (numbers are objects in bucket):
>
> For the 0...10000 range:
>
> Average: 78.125
> Std dev: 1.4197704151
> Min: 75
> Max: 80
>
>
> For the 1...100 range:
>
> Average: 0.78125
> Std dev: 0.5164613088
> Min: 0
> Max: 2
>
>
> For the 1000...1100 range:
>
> Average: 0.7890625
> Std dev: 0.4964812206
> Min: 0
> Max: 2
>
>
> Looks like hash_32 is pretty good with small numbers.

Yes hash_32 seems reasonable for the uid hash.   With those long hash
chains I wouldn't like to be on a machine with 10,000 processes with
each with a different uid, and a processes calling setuid in the fast
path.

The uid hash that we are playing with is one that I sort of wish that
the hash table could grow in size, so that we could scale up better.

Aw well.  Most of the time we only have a very small number of uids
in play, so it doesn't matter at this point.

Eric

^ permalink raw reply

* Re: [PATCH net-next 0/7] sctp: network namespace support Part 2: per net tunables
From: Vlad Yasevich @ 2012-08-15  3:16 UTC (permalink / raw)
  To: David Miller
  Cc: ebiederm, linux-sctp, netdev, linux-kernel, jan.ariyasu,
	jan.ariyasu, nhorman, tgraf, xi.wang
In-Reply-To: <20120814.141415.556937052577510995.davem@davemloft.net>

On 08/14/2012 05:14 PM, David Miller wrote:
>
> Come on Vlad, please review this stuff some time this century.  If you
> want inclusion to be dependent upon your review, then the onus is on
> you to review it in a timely manner.  And you are not doing so here.
>
> I'm not letting Eric's patches rot in patchwork for more than a week,
> this is completely unacceptable.
>


I swear I sent an ACK 2 days ago, but I now see it sitting in my draft 
folder.  My bad.  I'll go now and dust off the ACK...

-vlad

^ permalink raw reply

* Re: [PATCH net-next 1/9] sctp: Make the port hash table use struct net in it's key.
From: Vlad Yasevich @ 2012-08-15  3:18 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: David Miller, linux-sctp, netdev, linux-kernel, Jan Ariyasu,
	Jan Ariyasu, Neil Horman, Thomas Graf, Xi Wang
In-Reply-To: <87txwfq2z9.fsf_-_@xmission.com>

On 08/06/2012 02:39 PM, Eric W. Biederman wrote:
>
> - Add struct net into the port hash table hash calculation
> - Add struct net inot the struct sctp_bind_bucket so there
>    is a memory of which network namespace a port is allocated in.
>    No need for a ref count because sctp_bind_bucket only exists
>    when there are sockets in the hash table and sockets can not
>    change their network namspace, and sockets already ref count
>    their network namespace.
> - Add struct net into the key comparison when we are testing
>    to see if we have found the port hash table entry we are
>    looking for.
>
> With these changes lookups in the port hash table becomes
> safe to use in multiple network namespaces.
>
> Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>

Acked-by: Vlad Yasevich <vyasevich@gmail.com>


> ---
>   include/net/sctp/sctp.h    |    4 ++--
>   include/net/sctp/structs.h |    1 +
>   net/sctp/socket.c          |   22 +++++++++++++---------
>   3 files changed, 16 insertions(+), 11 deletions(-)
>
> diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
> index ff49964..7c05040 100644
> --- a/include/net/sctp/sctp.h
> +++ b/include/net/sctp/sctp.h
> @@ -632,9 +632,9 @@ static inline int sctp_sanity_check(void)
>
>   /* Warning: The following hash functions assume a power of two 'size'. */
>   /* This is the hash function for the SCTP port hash table. */
> -static inline int sctp_phashfn(__u16 lport)
> +static inline int sctp_phashfn(struct net *net, __u16 lport)
>   {
> -	return lport & (sctp_port_hashsize - 1);
> +	return (net_hash_mix(net) + lport) & (sctp_port_hashsize - 1);
>   }
>
>   /* This is the hash function for the endpoint hash table. */
> diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
> index fc5e600..c089bb1 100644
> --- a/include/net/sctp/structs.h
> +++ b/include/net/sctp/structs.h
> @@ -102,6 +102,7 @@ struct sctp_bind_bucket {
>   	unsigned short	fastreuse;
>   	struct hlist_node	node;
>   	struct hlist_head	owner;
> +	struct net	*net;
>   };
>
>   struct sctp_bind_hashbucket {
> diff --git a/net/sctp/socket.c b/net/sctp/socket.c
> index 5e25981..4316b0f 100644
> --- a/net/sctp/socket.c
> +++ b/net/sctp/socket.c
> @@ -5769,7 +5769,7 @@ static void sctp_unhash(struct sock *sk)
>    * a fastreuse flag (FIXME: NPI ipg).
>    */
>   static struct sctp_bind_bucket *sctp_bucket_create(
> -	struct sctp_bind_hashbucket *head, unsigned short snum);
> +	struct sctp_bind_hashbucket *head, struct net *, unsigned short snum);
>
>   static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr)
>   {
> @@ -5799,11 +5799,12 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr)
>   				rover = low;
>   			if (inet_is_reserved_local_port(rover))
>   				continue;
> -			index = sctp_phashfn(rover);
> +			index = sctp_phashfn(sock_net(sk), rover);
>   			head = &sctp_port_hashtable[index];
>   			sctp_spin_lock(&head->lock);
>   			sctp_for_each_hentry(pp, node, &head->chain)
> -				if (pp->port == rover)
> +				if ((pp->port == rover) &&
> +				    net_eq(sock_net(sk), pp->net))
>   					goto next;
>   			break;
>   		next:
> @@ -5827,10 +5828,10 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr)
>   		 * to the port number (snum) - we detect that with the
>   		 * port iterator, pp being NULL.
>   		 */
> -		head = &sctp_port_hashtable[sctp_phashfn(snum)];
> +		head = &sctp_port_hashtable[sctp_phashfn(sock_net(sk), snum)];
>   		sctp_spin_lock(&head->lock);
>   		sctp_for_each_hentry(pp, node, &head->chain) {
> -			if (pp->port == snum)
> +			if ((pp->port == snum) && net_eq(pp->net, sock_net(sk)))
>   				goto pp_found;
>   		}
>   	}
> @@ -5881,7 +5882,7 @@ pp_found:
>   pp_not_found:
>   	/* If there was a hash table miss, create a new port.  */
>   	ret = 1;
> -	if (!pp && !(pp = sctp_bucket_create(head, snum)))
> +	if (!pp && !(pp = sctp_bucket_create(head, sock_net(sk), snum)))
>   		goto fail_unlock;
>
>   	/* In either case (hit or miss), make sure fastreuse is 1 only
> @@ -6113,7 +6114,7 @@ unsigned int sctp_poll(struct file *file, struct socket *sock, poll_table *wait)
>    ********************************************************************/
>
>   static struct sctp_bind_bucket *sctp_bucket_create(
> -	struct sctp_bind_hashbucket *head, unsigned short snum)
> +	struct sctp_bind_hashbucket *head, struct net *net, unsigned short snum)
>   {
>   	struct sctp_bind_bucket *pp;
>
> @@ -6123,6 +6124,7 @@ static struct sctp_bind_bucket *sctp_bucket_create(
>   		pp->port = snum;
>   		pp->fastreuse = 0;
>   		INIT_HLIST_HEAD(&pp->owner);
> +		pp->net = net;
>   		hlist_add_head(&pp->node, &head->chain);
>   	}
>   	return pp;
> @@ -6142,7 +6144,8 @@ static void sctp_bucket_destroy(struct sctp_bind_bucket *pp)
>   static inline void __sctp_put_port(struct sock *sk)
>   {
>   	struct sctp_bind_hashbucket *head =
> -		&sctp_port_hashtable[sctp_phashfn(inet_sk(sk)->inet_num)];
> +		&sctp_port_hashtable[sctp_phashfn(sock_net(sk),
> +						  inet_sk(sk)->inet_num)];
>   	struct sctp_bind_bucket *pp;
>
>   	sctp_spin_lock(&head->lock);
> @@ -6809,7 +6812,8 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
>   	newsp->hmac = NULL;
>
>   	/* Hook this new socket in to the bind_hash list. */
> -	head = &sctp_port_hashtable[sctp_phashfn(inet_sk(oldsk)->inet_num)];
> +	head = &sctp_port_hashtable[sctp_phashfn(sock_net(oldsk),
> +						 inet_sk(oldsk)->inet_num)];
>   	sctp_local_bh_disable();
>   	sctp_spin_lock(&head->lock);
>   	pp = sctp_sk(oldsk)->bind_hash;
>

^ permalink raw reply

* Re: [PATCH net-next 2/9] sctp: Make the endpoint hashtable handle multiple network namespaces
From: Vlad Yasevich @ 2012-08-15  3:18 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: David Miller, linux-sctp, netdev, linux-kernel, Jan Ariyasu,
	Jan Ariyasu, Neil Horman, Thomas Graf, Xi Wang
In-Reply-To: <87obmnq2y2.fsf_-_@xmission.com>

On 08/06/2012 02:40 PM, Eric W. Biederman wrote:
>
> - Use struct net in the hash calculation
> - Use sock_net(endpoint.base.sk) in the endpoint lookups.
> - On receive calculate the network namespace from skb->dev.
>
> Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>

Acked-by: Vlad Yasevich <vyasevich@gmail.com>

> ---
>   include/net/sctp/sctp.h    |    4 ++--
>   include/net/sctp/structs.h |    2 +-
>   net/sctp/endpointola.c     |    4 +++-
>   net/sctp/input.c           |   19 ++++++++++++-------
>   4 files changed, 18 insertions(+), 11 deletions(-)
>
> diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
> index 7c05040..87b119f 100644
> --- a/include/net/sctp/sctp.h
> +++ b/include/net/sctp/sctp.h
> @@ -638,9 +638,9 @@ static inline int sctp_phashfn(struct net *net, __u16 lport)
>   }
>
>   /* This is the hash function for the endpoint hash table. */
> -static inline int sctp_ep_hashfn(__u16 lport)
> +static inline int sctp_ep_hashfn(struct net *net, __u16 lport)
>   {
> -	return lport & (sctp_ep_hashsize - 1);
> +	return (net_hash_mix(net) + lport) & (sctp_ep_hashsize - 1);
>   }
>
>   /* This is the hash function for the association hash table. */
> diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
> index c089bb1..9f9de55 100644
> --- a/include/net/sctp/structs.h
> +++ b/include/net/sctp/structs.h
> @@ -1426,7 +1426,7 @@ struct sctp_association *sctp_endpoint_lookup_assoc(
>   int sctp_endpoint_is_peeled_off(struct sctp_endpoint *,
>   				const union sctp_addr *);
>   struct sctp_endpoint *sctp_endpoint_is_match(struct sctp_endpoint *,
> -					const union sctp_addr *);
> +					struct net *, const union sctp_addr *);
>   int sctp_has_association(const union sctp_addr *laddr,
>   			 const union sctp_addr *paddr);
>
> diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c
> index 68a385d..50c87b4 100644
> --- a/net/sctp/endpointola.c
> +++ b/net/sctp/endpointola.c
> @@ -302,11 +302,13 @@ void sctp_endpoint_put(struct sctp_endpoint *ep)
>
>   /* Is this the endpoint we are looking for?  */
>   struct sctp_endpoint *sctp_endpoint_is_match(struct sctp_endpoint *ep,
> +					       struct net *net,
>   					       const union sctp_addr *laddr)
>   {
>   	struct sctp_endpoint *retval = NULL;
>
> -	if (htons(ep->base.bind_addr.port) == laddr->v4.sin_port) {
> +	if ((htons(ep->base.bind_addr.port) == laddr->v4.sin_port) &&
> +	    net_eq(sock_net(ep->base.sk), net)) {
>   		if (sctp_bind_addr_match(&ep->base.bind_addr, laddr,
>   					 sctp_sk(ep->base.sk)))
>   			retval = ep;
> diff --git a/net/sctp/input.c b/net/sctp/input.c
> index e64d521..c0ca893 100644
> --- a/net/sctp/input.c
> +++ b/net/sctp/input.c
> @@ -70,7 +70,8 @@ static struct sctp_association *__sctp_rcv_lookup(struct sk_buff *skb,
>   				      const union sctp_addr *laddr,
>   				      const union sctp_addr *paddr,
>   				      struct sctp_transport **transportp);
> -static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(const union sctp_addr *laddr);
> +static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(struct net *net,
> +						const union sctp_addr *laddr);
>   static struct sctp_association *__sctp_lookup_association(
>   					const union sctp_addr *local,
>   					const union sctp_addr *peer,
> @@ -129,6 +130,7 @@ int sctp_rcv(struct sk_buff *skb)
>   	union sctp_addr dest;
>   	int family;
>   	struct sctp_af *af;
> +	struct net *net = dev_net(skb->dev);
>
>   	if (skb->pkt_type!=PACKET_HOST)
>   		goto discard_it;
> @@ -181,7 +183,7 @@ int sctp_rcv(struct sk_buff *skb)
>   	asoc = __sctp_rcv_lookup(skb, &src, &dest, &transport);
>
>   	if (!asoc)
> -		ep = __sctp_rcv_lookup_endpoint(&dest);
> +		ep = __sctp_rcv_lookup_endpoint(net, &dest);
>
>   	/* Retrieve the common input handling substructure. */
>   	rcvr = asoc ? &asoc->base : &ep->base;
> @@ -723,12 +725,13 @@ discard:
>   /* Insert endpoint into the hash table.  */
>   static void __sctp_hash_endpoint(struct sctp_endpoint *ep)
>   {
> +	struct net *net = sock_net(ep->base.sk);
>   	struct sctp_ep_common *epb;
>   	struct sctp_hashbucket *head;
>
>   	epb = &ep->base;
>
> -	epb->hashent = sctp_ep_hashfn(epb->bind_addr.port);
> +	epb->hashent = sctp_ep_hashfn(net, epb->bind_addr.port);
>   	head = &sctp_ep_hashtable[epb->hashent];
>
>   	sctp_write_lock(&head->lock);
> @@ -747,12 +750,13 @@ void sctp_hash_endpoint(struct sctp_endpoint *ep)
>   /* Remove endpoint from the hash table.  */
>   static void __sctp_unhash_endpoint(struct sctp_endpoint *ep)
>   {
> +	struct net *net = sock_net(ep->base.sk);
>   	struct sctp_hashbucket *head;
>   	struct sctp_ep_common *epb;
>
>   	epb = &ep->base;
>
> -	epb->hashent = sctp_ep_hashfn(epb->bind_addr.port);
> +	epb->hashent = sctp_ep_hashfn(net, epb->bind_addr.port);
>
>   	head = &sctp_ep_hashtable[epb->hashent];
>
> @@ -770,7 +774,8 @@ void sctp_unhash_endpoint(struct sctp_endpoint *ep)
>   }
>
>   /* Look up an endpoint. */
> -static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(const union sctp_addr *laddr)
> +static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(struct net *net,
> +						const union sctp_addr *laddr)
>   {
>   	struct sctp_hashbucket *head;
>   	struct sctp_ep_common *epb;
> @@ -778,12 +783,12 @@ static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(const union sctp_addr *l
>   	struct hlist_node *node;
>   	int hash;
>
> -	hash = sctp_ep_hashfn(ntohs(laddr->v4.sin_port));
> +	hash = sctp_ep_hashfn(net, ntohs(laddr->v4.sin_port));
>   	head = &sctp_ep_hashtable[hash];
>   	read_lock(&head->lock);
>   	sctp_for_each_hentry(epb, node, &head->chain) {
>   		ep = sctp_ep(epb);
> -		if (sctp_endpoint_is_match(ep, laddr))
> +		if (sctp_endpoint_is_match(ep, net, laddr))
>   			goto hit;
>   	}
>
>

^ permalink raw reply

* Re: [PATCH net-next 3/9] sctp: Make the association hashtable handle multiple network namespaces
From: Vlad Yasevich @ 2012-08-15  3:18 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: David Miller, linux-sctp, netdev, linux-kernel, Jan Ariyasu,
	Jan Ariyasu, Neil Horman, Thomas Graf, Xi Wang
In-Reply-To: <87ipcvq2wm.fsf_-_@xmission.com>

On 08/06/2012 02:41 PM, Eric W. Biederman wrote:
>
> - Use struct net in the hash calculation
> - Use sock_net(association.base.sk) in the association lookups.
> - On receive calculate the network namespace from skb->dev.
> - Pass struct net from receive down to the functions that actually
>    do the association lookup.
>
> Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>

Acked-by: Vlad Yasevich <vyasevich@gmail.com>

> ---
>   include/net/sctp/sctp.h    |    6 ++--
>   include/net/sctp/structs.h |    3 +-
>   net/sctp/associola.c       |    4 ++-
>   net/sctp/endpointola.c     |    6 +++-
>   net/sctp/input.c           |   64 +++++++++++++++++++++++++++----------------
>   net/sctp/ipv6.c            |    3 +-
>   6 files changed, 54 insertions(+), 32 deletions(-)
>
> diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
> index 87b119f..640915a 100644
> --- a/include/net/sctp/sctp.h
> +++ b/include/net/sctp/sctp.h
> @@ -156,7 +156,7 @@ void sctp_hash_established(struct sctp_association *);
>   void sctp_unhash_established(struct sctp_association *);
>   void sctp_hash_endpoint(struct sctp_endpoint *);
>   void sctp_unhash_endpoint(struct sctp_endpoint *);
> -struct sock *sctp_err_lookup(int family, struct sk_buff *,
> +struct sock *sctp_err_lookup(struct net *net, int family, struct sk_buff *,
>   			     struct sctphdr *, struct sctp_association **,
>   			     struct sctp_transport **);
>   void sctp_err_finish(struct sock *, struct sctp_association *);
> @@ -644,9 +644,9 @@ static inline int sctp_ep_hashfn(struct net *net, __u16 lport)
>   }
>
>   /* This is the hash function for the association hash table. */
> -static inline int sctp_assoc_hashfn(__u16 lport, __u16 rport)
> +static inline int sctp_assoc_hashfn(struct net *net, __u16 lport, __u16 rport)
>   {
> -	int h = (lport << 16) + rport;
> +	int h = (lport << 16) + rport + net_hash_mix(net);
>   	h ^= h>>8;
>   	return h & (sctp_assoc_hashsize - 1);
>   }
> diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
> index 9f9de55..c0563d1 100644
> --- a/include/net/sctp/structs.h
> +++ b/include/net/sctp/structs.h
> @@ -1427,7 +1427,7 @@ int sctp_endpoint_is_peeled_off(struct sctp_endpoint *,
>   				const union sctp_addr *);
>   struct sctp_endpoint *sctp_endpoint_is_match(struct sctp_endpoint *,
>   					struct net *, const union sctp_addr *);
> -int sctp_has_association(const union sctp_addr *laddr,
> +int sctp_has_association(struct net *net, const union sctp_addr *laddr,
>   			 const union sctp_addr *paddr);
>
>   int sctp_verify_init(const struct sctp_association *asoc, sctp_cid_t,
> @@ -2014,6 +2014,7 @@ void sctp_assoc_control_transport(struct sctp_association *,
>   				  sctp_transport_cmd_t, sctp_sn_error_t);
>   struct sctp_transport *sctp_assoc_lookup_tsn(struct sctp_association *, __u32);
>   struct sctp_transport *sctp_assoc_is_match(struct sctp_association *,
> +					   struct net *,
>   					   const union sctp_addr *,
>   					   const union sctp_addr *);
>   void sctp_assoc_migrate(struct sctp_association *, struct sock *);
> diff --git a/net/sctp/associola.c b/net/sctp/associola.c
> index ebaef3e..a3601f3 100644
> --- a/net/sctp/associola.c
> +++ b/net/sctp/associola.c
> @@ -1089,13 +1089,15 @@ out:
>
>   /* Is this the association we are looking for? */
>   struct sctp_transport *sctp_assoc_is_match(struct sctp_association *asoc,
> +					   struct net *net,
>   					   const union sctp_addr *laddr,
>   					   const union sctp_addr *paddr)
>   {
>   	struct sctp_transport *transport;
>
>   	if ((htons(asoc->base.bind_addr.port) == laddr->v4.sin_port) &&
> -	    (htons(asoc->peer.port) == paddr->v4.sin_port)) {
> +	    (htons(asoc->peer.port) == paddr->v4.sin_port) &&
> +	    net_eq(sock_net(asoc->base.sk), net)) {
>   		transport = sctp_assoc_lookup_paddr(asoc, paddr);
>   		if (!transport)
>   			goto out;
> diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c
> index 50c87b4..6b76393 100644
> --- a/net/sctp/endpointola.c
> +++ b/net/sctp/endpointola.c
> @@ -345,7 +345,8 @@ static struct sctp_association *__sctp_endpoint_lookup_assoc(
>
>   	rport = ntohs(paddr->v4.sin_port);
>
> -	hash = sctp_assoc_hashfn(ep->base.bind_addr.port, rport);
> +	hash = sctp_assoc_hashfn(sock_net(ep->base.sk), ep->base.bind_addr.port,
> +				 rport);
>   	head = &sctp_assoc_hashtable[hash];
>   	read_lock(&head->lock);
>   	sctp_for_each_hentry(epb, node, &head->chain) {
> @@ -388,13 +389,14 @@ int sctp_endpoint_is_peeled_off(struct sctp_endpoint *ep,
>   {
>   	struct sctp_sockaddr_entry *addr;
>   	struct sctp_bind_addr *bp;
> +	struct net *net = sock_net(ep->base.sk);
>
>   	bp = &ep->base.bind_addr;
>   	/* This function is called with the socket lock held,
>   	 * so the address_list can not change.
>   	 */
>   	list_for_each_entry(addr, &bp->address_list, list) {
> -		if (sctp_has_association(&addr->a, paddr))
> +		if (sctp_has_association(net, &addr->a, paddr))
>   			return 1;
>   	}
>
> diff --git a/net/sctp/input.c b/net/sctp/input.c
> index c0ca893..a7e9a85 100644
> --- a/net/sctp/input.c
> +++ b/net/sctp/input.c
> @@ -66,13 +66,15 @@
>
>   /* Forward declarations for internal helpers. */
>   static int sctp_rcv_ootb(struct sk_buff *);
> -static struct sctp_association *__sctp_rcv_lookup(struct sk_buff *skb,
> +static struct sctp_association *__sctp_rcv_lookup(struct net *net,
> +				      struct sk_buff *skb,
>   				      const union sctp_addr *laddr,
>   				      const union sctp_addr *paddr,
>   				      struct sctp_transport **transportp);
>   static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(struct net *net,
>   						const union sctp_addr *laddr);
>   static struct sctp_association *__sctp_lookup_association(
> +					struct net *net,
>   					const union sctp_addr *local,
>   					const union sctp_addr *peer,
>   					struct sctp_transport **pt);
> @@ -180,7 +182,7 @@ int sctp_rcv(struct sk_buff *skb)
>   	    !af->addr_valid(&dest, NULL, skb))
>   		goto discard_it;
>
> -	asoc = __sctp_rcv_lookup(skb, &src, &dest, &transport);
> +	asoc = __sctp_rcv_lookup(net, skb, &src, &dest, &transport);
>
>   	if (!asoc)
>   		ep = __sctp_rcv_lookup_endpoint(net, &dest);
> @@ -476,7 +478,7 @@ void sctp_icmp_proto_unreachable(struct sock *sk,
>   }
>
>   /* Common lookup code for icmp/icmpv6 error handler. */
> -struct sock *sctp_err_lookup(int family, struct sk_buff *skb,
> +struct sock *sctp_err_lookup(struct net *net, int family, struct sk_buff *skb,
>   			     struct sctphdr *sctphdr,
>   			     struct sctp_association **app,
>   			     struct sctp_transport **tpp)
> @@ -505,7 +507,7 @@ struct sock *sctp_err_lookup(int family, struct sk_buff *skb,
>   	/* Look for an association that matches the incoming ICMP error
>   	 * packet.
>   	 */
> -	asoc = __sctp_lookup_association(&saddr, &daddr, &transport);
> +	asoc = __sctp_lookup_association(net, &saddr, &daddr, &transport);
>   	if (!asoc)
>   		return NULL;
>
> @@ -588,6 +590,7 @@ void sctp_v4_err(struct sk_buff *skb, __u32 info)
>   	struct inet_sock *inet;
>   	sk_buff_data_t saveip, savesctp;
>   	int err;
> +	struct net *net = dev_net(skb->dev);
>
>   	if (skb->len < ihlen + 8) {
>   		ICMP_INC_STATS_BH(&init_net, ICMP_MIB_INERRORS);
> @@ -599,7 +602,7 @@ void sctp_v4_err(struct sk_buff *skb, __u32 info)
>   	savesctp = skb->transport_header;
>   	skb_reset_network_header(skb);
>   	skb_set_transport_header(skb, ihlen);
> -	sk = sctp_err_lookup(AF_INET, skb, sctp_hdr(skb), &asoc, &transport);
> +	sk = sctp_err_lookup(net, AF_INET, skb, sctp_hdr(skb), &asoc, &transport);
>   	/* Put back, the original values. */
>   	skb->network_header = saveip;
>   	skb->transport_header = savesctp;
> @@ -803,13 +806,15 @@ hit:
>   /* Insert association into the hash table.  */
>   static void __sctp_hash_established(struct sctp_association *asoc)
>   {
> +	struct net *net = sock_net(asoc->base.sk);
>   	struct sctp_ep_common *epb;
>   	struct sctp_hashbucket *head;
>
>   	epb = &asoc->base;
>
>   	/* Calculate which chain this entry will belong to. */
> -	epb->hashent = sctp_assoc_hashfn(epb->bind_addr.port, asoc->peer.port);
> +	epb->hashent = sctp_assoc_hashfn(net, epb->bind_addr.port,
> +					 asoc->peer.port);
>
>   	head = &sctp_assoc_hashtable[epb->hashent];
>
> @@ -832,12 +837,13 @@ void sctp_hash_established(struct sctp_association *asoc)
>   /* Remove association from the hash table.  */
>   static void __sctp_unhash_established(struct sctp_association *asoc)
>   {
> +	struct net *net = sock_net(asoc->base.sk);
>   	struct sctp_hashbucket *head;
>   	struct sctp_ep_common *epb;
>
>   	epb = &asoc->base;
>
> -	epb->hashent = sctp_assoc_hashfn(epb->bind_addr.port,
> +	epb->hashent = sctp_assoc_hashfn(net, epb->bind_addr.port,
>   					 asoc->peer.port);
>
>   	head = &sctp_assoc_hashtable[epb->hashent];
> @@ -860,6 +866,7 @@ void sctp_unhash_established(struct sctp_association *asoc)
>
>   /* Look up an association. */
>   static struct sctp_association *__sctp_lookup_association(
> +					struct net *net,
>   					const union sctp_addr *local,
>   					const union sctp_addr *peer,
>   					struct sctp_transport **pt)
> @@ -874,12 +881,13 @@ static struct sctp_association *__sctp_lookup_association(
>   	/* Optimize here for direct hit, only listening connections can
>   	 * have wildcards anyways.
>   	 */
> -	hash = sctp_assoc_hashfn(ntohs(local->v4.sin_port), ntohs(peer->v4.sin_port));
> +	hash = sctp_assoc_hashfn(net, ntohs(local->v4.sin_port),
> +				 ntohs(peer->v4.sin_port));
>   	head = &sctp_assoc_hashtable[hash];
>   	read_lock(&head->lock);
>   	sctp_for_each_hentry(epb, node, &head->chain) {
>   		asoc = sctp_assoc(epb);
> -		transport = sctp_assoc_is_match(asoc, local, peer);
> +		transport = sctp_assoc_is_match(asoc, net, local, peer);
>   		if (transport)
>   			goto hit;
>   	}
> @@ -897,27 +905,29 @@ hit:
>
>   /* Look up an association. BH-safe. */
>   SCTP_STATIC
> -struct sctp_association *sctp_lookup_association(const union sctp_addr *laddr,
> +struct sctp_association *sctp_lookup_association(struct net *net,
> +						 const union sctp_addr *laddr,
>   						 const union sctp_addr *paddr,
>   					    struct sctp_transport **transportp)
>   {
>   	struct sctp_association *asoc;
>
>   	sctp_local_bh_disable();
> -	asoc = __sctp_lookup_association(laddr, paddr, transportp);
> +	asoc = __sctp_lookup_association(net, laddr, paddr, transportp);
>   	sctp_local_bh_enable();
>
>   	return asoc;
>   }
>
>   /* Is there an association matching the given local and peer addresses? */
> -int sctp_has_association(const union sctp_addr *laddr,
> +int sctp_has_association(struct net *net,
> +			 const union sctp_addr *laddr,
>   			 const union sctp_addr *paddr)
>   {
>   	struct sctp_association *asoc;
>   	struct sctp_transport *transport;
>
> -	if ((asoc = sctp_lookup_association(laddr, paddr, &transport))) {
> +	if ((asoc = sctp_lookup_association(net, laddr, paddr, &transport))) {
>   		sctp_association_put(asoc);
>   		return 1;
>   	}
> @@ -943,7 +953,8 @@ int sctp_has_association(const union sctp_addr *laddr,
>    * in certain circumstances.
>    *
>    */
> -static struct sctp_association *__sctp_rcv_init_lookup(struct sk_buff *skb,
> +static struct sctp_association *__sctp_rcv_init_lookup(struct net *net,
> +	struct sk_buff *skb,
>   	const union sctp_addr *laddr, struct sctp_transport **transportp)
>   {
>   	struct sctp_association *asoc;
> @@ -983,7 +994,7 @@ static struct sctp_association *__sctp_rcv_init_lookup(struct sk_buff *skb,
>
>   		af->from_addr_param(paddr, params.addr, sh->source, 0);
>
> -		asoc = __sctp_lookup_association(laddr, paddr, &transport);
> +		asoc = __sctp_lookup_association(net, laddr, paddr, &transport);
>   		if (asoc)
>   			return asoc;
>   	}
> @@ -1006,6 +1017,7 @@ static struct sctp_association *__sctp_rcv_init_lookup(struct sk_buff *skb,
>    * subsequent ASCONF Chunks. If found, proceed to rule D4.
>    */
>   static struct sctp_association *__sctp_rcv_asconf_lookup(
> +					struct net *net,
>   					sctp_chunkhdr_t *ch,
>   					const union sctp_addr *laddr,
>   					__be16 peer_port,
> @@ -1025,7 +1037,7 @@ static struct sctp_association *__sctp_rcv_asconf_lookup(
>
>   	af->from_addr_param(&paddr, param, peer_port, 0);
>
> -	return __sctp_lookup_association(laddr, &paddr, transportp);
> +	return __sctp_lookup_association(net, laddr, &paddr, transportp);
>   }
>
>
> @@ -1038,7 +1050,8 @@ static struct sctp_association *__sctp_rcv_asconf_lookup(
>   * This means that any chunks that can help us identify the association need
>   * to be looked at to find this association.
>   */
> -static struct sctp_association *__sctp_rcv_walk_lookup(struct sk_buff *skb,
> +static struct sctp_association *__sctp_rcv_walk_lookup(struct net *net,
> +				      struct sk_buff *skb,
>   				      const union sctp_addr *laddr,
>   				      struct sctp_transport **transportp)
>   {
> @@ -1080,7 +1093,8 @@ static struct sctp_association *__sctp_rcv_walk_lookup(struct sk_buff *skb,
>
>   		    case SCTP_CID_ASCONF:
>   			    if (have_auth || sctp_addip_noauth)
> -				    asoc = __sctp_rcv_asconf_lookup(ch, laddr,
> +				    asoc = __sctp_rcv_asconf_lookup(
> +							net, ch, laddr,
>   							sctp_hdr(skb)->source,
>   							transportp);
>   		    default:
> @@ -1103,7 +1117,8 @@ static struct sctp_association *__sctp_rcv_walk_lookup(struct sk_buff *skb,
>    * include looking inside of INIT/INIT-ACK chunks or after the AUTH
>    * chunks.
>    */
> -static struct sctp_association *__sctp_rcv_lookup_harder(struct sk_buff *skb,
> +static struct sctp_association *__sctp_rcv_lookup_harder(struct net *net,
> +				      struct sk_buff *skb,
>   				      const union sctp_addr *laddr,
>   				      struct sctp_transport **transportp)
>   {
> @@ -1123,11 +1138,11 @@ static struct sctp_association *__sctp_rcv_lookup_harder(struct sk_buff *skb,
>   	switch (ch->type) {
>   	case SCTP_CID_INIT:
>   	case SCTP_CID_INIT_ACK:
> -		return __sctp_rcv_init_lookup(skb, laddr, transportp);
> +		return __sctp_rcv_init_lookup(net, skb, laddr, transportp);
>   		break;
>
>   	default:
> -		return __sctp_rcv_walk_lookup(skb, laddr, transportp);
> +		return __sctp_rcv_walk_lookup(net, skb, laddr, transportp);
>   		break;
>   	}
>
> @@ -1136,21 +1151,22 @@ static struct sctp_association *__sctp_rcv_lookup_harder(struct sk_buff *skb,
>   }
>
>   /* Lookup an association for an inbound skb. */
> -static struct sctp_association *__sctp_rcv_lookup(struct sk_buff *skb,
> +static struct sctp_association *__sctp_rcv_lookup(struct net *net,
> +				      struct sk_buff *skb,
>   				      const union sctp_addr *paddr,
>   				      const union sctp_addr *laddr,
>   				      struct sctp_transport **transportp)
>   {
>   	struct sctp_association *asoc;
>
> -	asoc = __sctp_lookup_association(laddr, paddr, transportp);
> +	asoc = __sctp_lookup_association(net, laddr, paddr, transportp);
>
>   	/* Further lookup for INIT/INIT-ACK packets.
>   	 * SCTP Implementors Guide, 2.18 Handling of address
>   	 * parameters within the INIT or INIT-ACK.
>   	 */
>   	if (!asoc)
> -		asoc = __sctp_rcv_lookup_harder(skb, laddr, transportp);
> +		asoc = __sctp_rcv_lookup_harder(net, skb, laddr, transportp);
>
>   	return asoc;
>   }
> diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
> index ed7139e..2165a7e 100644
> --- a/net/sctp/ipv6.c
> +++ b/net/sctp/ipv6.c
> @@ -154,6 +154,7 @@ SCTP_STATIC void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
>   	struct ipv6_pinfo *np;
>   	sk_buff_data_t saveip, savesctp;
>   	int err;
> +	struct net *net = dev_net(skb->dev);
>
>   	idev = in6_dev_get(skb->dev);
>
> @@ -162,7 +163,7 @@ SCTP_STATIC void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
>   	savesctp = skb->transport_header;
>   	skb_reset_network_header(skb);
>   	skb_set_transport_header(skb, offset);
> -	sk = sctp_err_lookup(AF_INET6, skb, sctp_hdr(skb), &asoc, &transport);
> +	sk = sctp_err_lookup(net, AF_INET6, skb, sctp_hdr(skb), &asoc, &transport);
>   	/* Put back, the original pointers. */
>   	skb->network_header   = saveip;
>   	skb->transport_header = savesctp;
>

^ permalink raw reply

* Re: [PATCH net-next 4/9] sctp: Make the address lists per network namespace
From: Vlad Yasevich @ 2012-08-15  3:19 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: David Miller, linux-sctp, netdev, linux-kernel, Jan Ariyasu,
	Jan Ariyasu, Neil Horman, Thomas Graf, Xi Wang
In-Reply-To: <87d333q2v7.fsf_-_@xmission.com>

On 08/06/2012 02:42 PM, Eric W. Biederman wrote:
>
> - Move the address lists into struct net
> - Add per network namespace initialization and cleanup
> - Pass around struct net so it is everywhere I need it.
> - Rename all of the global variable references into references
>    to the variables moved into struct net
>
> Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>

Acked-by: Vlad Yasevich <vyasevich@gmail.com>

> ---
>   include/net/net_namespace.h |    4 +
>   include/net/netns/sctp.h    |   21 +++++++
>   include/net/sctp/sctp.h     |    4 +-
>   include/net/sctp/structs.h  |   22 +-------
>   net/sctp/associola.c        |    3 +-
>   net/sctp/bind_addr.c        |   14 ++--
>   net/sctp/ipv6.c             |   17 +++---
>   net/sctp/protocol.c         |  141 +++++++++++++++++++++++++------------------
>   net/sctp/socket.c           |    7 +-
>   9 files changed, 131 insertions(+), 102 deletions(-)
>   create mode 100644 include/net/netns/sctp.h
>
> diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
> index ae1cd6c..8ab5250 100644
> --- a/include/net/net_namespace.h
> +++ b/include/net/net_namespace.h
> @@ -15,6 +15,7 @@
>   #include <net/netns/packet.h>
>   #include <net/netns/ipv4.h>
>   #include <net/netns/ipv6.h>
> +#include <net/netns/sctp.h>
>   #include <net/netns/dccp.h>
>   #include <net/netns/x_tables.h>
>   #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
> @@ -80,6 +81,9 @@ struct net {
>   #if IS_ENABLED(CONFIG_IPV6)
>   	struct netns_ipv6	ipv6;
>   #endif
> +#if defined(CONFIG_IP_SCTP) || defined(CONFIG_IP_SCTP_MODULE)
> +	struct netns_sctp	sctp;
> +#endif
>   #if defined(CONFIG_IP_DCCP) || defined(CONFIG_IP_DCCP_MODULE)
>   	struct netns_dccp	dccp;
>   #endif
> diff --git a/include/net/netns/sctp.h b/include/net/netns/sctp.h
> new file mode 100644
> index 0000000..cbd684e
> --- /dev/null
> +++ b/include/net/netns/sctp.h
> @@ -0,0 +1,21 @@
> +#ifndef __NETNS_SCTP_H__
> +#define __NETNS_SCTP_H__
> +
> +struct netns_sctp {
> +	/* This is the global local address list.
> +	 * We actively maintain this complete list of addresses on
> +	 * the system by catching address add/delete events.
> +	 *
> +	 * It is a list of sctp_sockaddr_entry.
> +	 */
> +	struct list_head local_addr_list;
> +	struct list_head addr_waitq;
> +	struct timer_list addr_wq_timer;
> +	struct list_head auto_asconf_splist;
> +	spinlock_t addr_wq_lock;
> +
> +	/* Lock that protects the local_addr_list writers */
> +	spinlock_t local_addr_lock;
> +};
> +
> +#endif /* __NETNS_SCTP_H__ */
> diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
> index 640915a..00c9205 100644
> --- a/include/net/sctp/sctp.h
> +++ b/include/net/sctp/sctp.h
> @@ -115,12 +115,12 @@
>    * sctp/protocol.c
>    */
>   extern struct sock *sctp_get_ctl_sock(void);
> -extern int sctp_copy_local_addr_list(struct sctp_bind_addr *,
> +extern int sctp_copy_local_addr_list(struct net *, struct sctp_bind_addr *,
>   				     sctp_scope_t, gfp_t gfp,
>   				     int flags);
>   extern struct sctp_pf *sctp_get_pf_specific(sa_family_t family);
>   extern int sctp_register_pf(struct sctp_pf *, sa_family_t);
> -extern void sctp_addr_wq_mgmt(struct sctp_sockaddr_entry *, int);
> +extern void sctp_addr_wq_mgmt(struct net *, struct sctp_sockaddr_entry *, int);
>
>   /*
>    * sctp/socket.c
> diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
> index c0563d1..6bdfcab 100644
> --- a/include/net/sctp/structs.h
> +++ b/include/net/sctp/structs.h
> @@ -205,21 +205,7 @@ extern struct sctp_globals {
>   	int port_hashsize;
>   	struct sctp_bind_hashbucket *port_hashtable;
>
> -	/* This is the global local address list.
> -	 * We actively maintain this complete list of addresses on
> -	 * the system by catching address add/delete events.
> -	 *
> -	 * It is a list of sctp_sockaddr_entry.
> -	 */
> -	struct list_head local_addr_list;
>   	int default_auto_asconf;
> -	struct list_head addr_waitq;
> -	struct timer_list addr_wq_timer;
> -	struct list_head auto_asconf_splist;
> -	spinlock_t addr_wq_lock;
> -
> -	/* Lock that protects the local_addr_list writers */
> -	spinlock_t addr_list_lock;
>   	
>   	/* Flag to indicate if addip is enabled. */
>   	int addip_enable;
> @@ -278,12 +264,6 @@ extern struct sctp_globals {
>   #define sctp_assoc_hashtable		(sctp_globals.assoc_hashtable)
>   #define sctp_port_hashsize		(sctp_globals.port_hashsize)
>   #define sctp_port_hashtable		(sctp_globals.port_hashtable)
> -#define sctp_local_addr_list		(sctp_globals.local_addr_list)
> -#define sctp_local_addr_lock		(sctp_globals.addr_list_lock)
> -#define sctp_auto_asconf_splist		(sctp_globals.auto_asconf_splist)
> -#define sctp_addr_waitq			(sctp_globals.addr_waitq)
> -#define sctp_addr_wq_timer		(sctp_globals.addr_wq_timer)
> -#define sctp_addr_wq_lock		(sctp_globals.addr_wq_lock)
>   #define sctp_default_auto_asconf	(sctp_globals.default_auto_asconf)
>   #define sctp_scope_policy		(sctp_globals.ipv4_scope_policy)
>   #define sctp_addip_enable		(sctp_globals.addip_enable)
> @@ -1241,7 +1221,7 @@ struct sctp_bind_addr {
>
>   void sctp_bind_addr_init(struct sctp_bind_addr *, __u16 port);
>   void sctp_bind_addr_free(struct sctp_bind_addr *);
> -int sctp_bind_addr_copy(struct sctp_bind_addr *dest,
> +int sctp_bind_addr_copy(struct net *net, struct sctp_bind_addr *dest,
>   			const struct sctp_bind_addr *src,
>   			sctp_scope_t scope, gfp_t gfp,
>   			int flags);
> diff --git a/net/sctp/associola.c b/net/sctp/associola.c
> index a3601f3..ed4930b 100644
> --- a/net/sctp/associola.c
> +++ b/net/sctp/associola.c
> @@ -1544,7 +1544,8 @@ int sctp_assoc_set_bind_addr_from_ep(struct sctp_association *asoc,
>   	if (asoc->peer.ipv6_address)
>   		flags |= SCTP_ADDR6_PEERSUPP;
>
> -	return sctp_bind_addr_copy(&asoc->base.bind_addr,
> +	return sctp_bind_addr_copy(sock_net(asoc->base.sk),
> +				   &asoc->base.bind_addr,
>   				   &asoc->ep->base.bind_addr,
>   				   scope, gfp, flags);
>   }
> diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c
> index 4ece451..a85ce4b 100644
> --- a/net/sctp/bind_addr.c
> +++ b/net/sctp/bind_addr.c
> @@ -52,8 +52,8 @@
>   #include <net/sctp/sm.h>
>
>   /* Forward declarations for internal helpers. */
> -static int sctp_copy_one_addr(struct sctp_bind_addr *, union sctp_addr *,
> -			      sctp_scope_t scope, gfp_t gfp,
> +static int sctp_copy_one_addr(struct net *, struct sctp_bind_addr *,
> +			      union sctp_addr *, sctp_scope_t scope, gfp_t gfp,
>   			      int flags);
>   static void sctp_bind_addr_clean(struct sctp_bind_addr *);
>
> @@ -62,7 +62,7 @@ static void sctp_bind_addr_clean(struct sctp_bind_addr *);
>   /* Copy 'src' to 'dest' taking 'scope' into account.  Omit addresses
>    * in 'src' which have a broader scope than 'scope'.
>    */
> -int sctp_bind_addr_copy(struct sctp_bind_addr *dest,
> +int sctp_bind_addr_copy(struct net *net, struct sctp_bind_addr *dest,
>   			const struct sctp_bind_addr *src,
>   			sctp_scope_t scope, gfp_t gfp,
>   			int flags)
> @@ -75,7 +75,7 @@ int sctp_bind_addr_copy(struct sctp_bind_addr *dest,
>
>   	/* Extract the addresses which are relevant for this scope.  */
>   	list_for_each_entry(addr, &src->address_list, list) {
> -		error = sctp_copy_one_addr(dest, &addr->a, scope,
> +		error = sctp_copy_one_addr(net, dest, &addr->a, scope,
>   					   gfp, flags);
>   		if (error < 0)
>   			goto out;
> @@ -87,7 +87,7 @@ int sctp_bind_addr_copy(struct sctp_bind_addr *dest,
>   	 */
>   	if (list_empty(&dest->address_list) && (SCTP_SCOPE_GLOBAL == scope)) {
>   		list_for_each_entry(addr, &src->address_list, list) {
> -			error = sctp_copy_one_addr(dest, &addr->a,
> +			error = sctp_copy_one_addr(net, dest, &addr->a,
>   						   SCTP_SCOPE_LINK, gfp,
>   						   flags);
>   			if (error < 0)
> @@ -448,7 +448,7 @@ union sctp_addr *sctp_find_unmatch_addr(struct sctp_bind_addr	*bp,
>   }
>
>   /* Copy out addresses from the global local address list. */
> -static int sctp_copy_one_addr(struct sctp_bind_addr *dest,
> +static int sctp_copy_one_addr(struct net *net, struct sctp_bind_addr *dest,
>   			      union sctp_addr *addr,
>   			      sctp_scope_t scope, gfp_t gfp,
>   			      int flags)
> @@ -456,7 +456,7 @@ static int sctp_copy_one_addr(struct sctp_bind_addr *dest,
>   	int error = 0;
>
>   	if (sctp_is_any(NULL, addr)) {
> -		error = sctp_copy_local_addr_list(dest, scope, gfp, flags);
> +		error = sctp_copy_local_addr_list(net, dest, scope, gfp, flags);
>   	} else if (sctp_in_scope(addr, scope)) {
>   		/* Now that the address is in scope, check to see if
>   		 * the address type is supported by local sock as
> diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
> index 2165a7e..bbf1534 100644
> --- a/net/sctp/ipv6.c
> +++ b/net/sctp/ipv6.c
> @@ -99,6 +99,7 @@ static int sctp_inet6addr_event(struct notifier_block *this, unsigned long ev,
>   	struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr;
>   	struct sctp_sockaddr_entry *addr = NULL;
>   	struct sctp_sockaddr_entry *temp;
> +	struct net *net = dev_net(ifa->idev->dev);
>   	int found = 0;
>
>   	switch (ev) {
> @@ -110,27 +111,27 @@ static int sctp_inet6addr_event(struct notifier_block *this, unsigned long ev,
>   			addr->a.v6.sin6_addr = ifa->addr;
>   			addr->a.v6.sin6_scope_id = ifa->idev->dev->ifindex;
>   			addr->valid = 1;
> -			spin_lock_bh(&sctp_local_addr_lock);
> -			list_add_tail_rcu(&addr->list, &sctp_local_addr_list);
> -			sctp_addr_wq_mgmt(addr, SCTP_ADDR_NEW);
> -			spin_unlock_bh(&sctp_local_addr_lock);
> +			spin_lock_bh(&net->sctp.local_addr_lock);
> +			list_add_tail_rcu(&addr->list, &net->sctp.local_addr_list);
> +			sctp_addr_wq_mgmt(net, addr, SCTP_ADDR_NEW);
> +			spin_unlock_bh(&net->sctp.local_addr_lock);
>   		}
>   		break;
>   	case NETDEV_DOWN:
> -		spin_lock_bh(&sctp_local_addr_lock);
> +		spin_lock_bh(&net->sctp.local_addr_lock);
>   		list_for_each_entry_safe(addr, temp,
> -					&sctp_local_addr_list, list) {
> +					&net->sctp.local_addr_list, list) {
>   			if (addr->a.sa.sa_family == AF_INET6 &&
>   					ipv6_addr_equal(&addr->a.v6.sin6_addr,
>   						&ifa->addr)) {
> -				sctp_addr_wq_mgmt(addr, SCTP_ADDR_DEL);
> +				sctp_addr_wq_mgmt(net, addr, SCTP_ADDR_DEL);
>   				found = 1;
>   				addr->valid = 0;
>   				list_del_rcu(&addr->list);
>   				break;
>   			}
>   		}
> -		spin_unlock_bh(&sctp_local_addr_lock);
> +		spin_unlock_bh(&net->sctp.local_addr_lock);
>   		if (found)
>   			kfree_rcu(addr, rcu);
>   		break;
> diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
> index 1f89c4e..291e682 100644
> --- a/net/sctp/protocol.c
> +++ b/net/sctp/protocol.c
> @@ -201,29 +201,29 @@ static void sctp_v4_copy_addrlist(struct list_head *addrlist,
>   /* Extract our IP addresses from the system and stash them in the
>    * protocol structure.
>    */
> -static void sctp_get_local_addr_list(void)
> +static void sctp_get_local_addr_list(struct net *net)
>   {
>   	struct net_device *dev;
>   	struct list_head *pos;
>   	struct sctp_af *af;
>
>   	rcu_read_lock();
> -	for_each_netdev_rcu(&init_net, dev) {
> +	for_each_netdev_rcu(net, dev) {
>   		__list_for_each(pos, &sctp_address_families) {
>   			af = list_entry(pos, struct sctp_af, list);
> -			af->copy_addrlist(&sctp_local_addr_list, dev);
> +			af->copy_addrlist(&net->sctp.local_addr_list, dev);
>   		}
>   	}
>   	rcu_read_unlock();
>   }
>
>   /* Free the existing local addresses.  */
> -static void sctp_free_local_addr_list(void)
> +static void sctp_free_local_addr_list(struct net *net)
>   {
>   	struct sctp_sockaddr_entry *addr;
>   	struct list_head *pos, *temp;
>
> -	list_for_each_safe(pos, temp, &sctp_local_addr_list) {
> +	list_for_each_safe(pos, temp, &net->sctp.local_addr_list) {
>   		addr = list_entry(pos, struct sctp_sockaddr_entry, list);
>   		list_del(pos);
>   		kfree(addr);
> @@ -231,14 +231,14 @@ static void sctp_free_local_addr_list(void)
>   }
>
>   /* Copy the local addresses which are valid for 'scope' into 'bp'.  */
> -int sctp_copy_local_addr_list(struct sctp_bind_addr *bp, sctp_scope_t scope,
> -			      gfp_t gfp, int copy_flags)
> +int sctp_copy_local_addr_list(struct net *net, struct sctp_bind_addr *bp,
> +			      sctp_scope_t scope, gfp_t gfp, int copy_flags)
>   {
>   	struct sctp_sockaddr_entry *addr;
>   	int error = 0;
>
>   	rcu_read_lock();
> -	list_for_each_entry_rcu(addr, &sctp_local_addr_list, list) {
> +	list_for_each_entry_rcu(addr, &net->sctp.local_addr_list, list) {
>   		if (!addr->valid)
>   			continue;
>   		if (sctp_in_scope(&addr->a, scope)) {
> @@ -627,14 +627,15 @@ static void sctp_v4_ecn_capable(struct sock *sk)
>
>   void sctp_addr_wq_timeout_handler(unsigned long arg)
>   {
> +	struct net *net = (struct net *)arg;
>   	struct sctp_sockaddr_entry *addrw, *temp;
>   	struct sctp_sock *sp;
>
> -	spin_lock_bh(&sctp_addr_wq_lock);
> +	spin_lock_bh(&net->sctp.addr_wq_lock);
>
> -	list_for_each_entry_safe(addrw, temp, &sctp_addr_waitq, list) {
> +	list_for_each_entry_safe(addrw, temp, &net->sctp.addr_waitq, list) {
>   		SCTP_DEBUG_PRINTK_IPADDR("sctp_addrwq_timo_handler: the first ent in wq %p is ",
> -		    " for cmd %d at entry %p\n", &sctp_addr_waitq, &addrw->a, addrw->state,
> +		    " for cmd %d at entry %p\n", &net->sctp.addr_waitq, &addrw->a, addrw->state,
>   		    addrw);
>
>   #if IS_ENABLED(CONFIG_IPV6)
> @@ -648,7 +649,7 @@ void sctp_addr_wq_timeout_handler(unsigned long arg)
>   				goto free_next;
>
>   			in6 = (struct in6_addr *)&addrw->a.v6.sin6_addr;
> -			if (ipv6_chk_addr(&init_net, in6, NULL, 0) == 0 &&
> +			if (ipv6_chk_addr(net, in6, NULL, 0) == 0 &&
>   			    addrw->state == SCTP_ADDR_NEW) {
>   				unsigned long timeo_val;
>
> @@ -656,12 +657,12 @@ void sctp_addr_wq_timeout_handler(unsigned long arg)
>   				    SCTP_ADDRESS_TICK_DELAY);
>   				timeo_val = jiffies;
>   				timeo_val += msecs_to_jiffies(SCTP_ADDRESS_TICK_DELAY);
> -				mod_timer(&sctp_addr_wq_timer, timeo_val);
> +				mod_timer(&net->sctp.addr_wq_timer, timeo_val);
>   				break;
>   			}
>   		}
>   #endif
> -		list_for_each_entry(sp, &sctp_auto_asconf_splist, auto_asconf_list) {
> +		list_for_each_entry(sp, &net->sctp.auto_asconf_splist, auto_asconf_list) {
>   			struct sock *sk;
>
>   			sk = sctp_opt2sk(sp);
> @@ -679,31 +680,32 @@ free_next:
>   		list_del(&addrw->list);
>   		kfree(addrw);
>   	}
> -	spin_unlock_bh(&sctp_addr_wq_lock);
> +	spin_unlock_bh(&net->sctp.addr_wq_lock);
>   }
>
> -static void sctp_free_addr_wq(void)
> +static void sctp_free_addr_wq(struct net *net)
>   {
>   	struct sctp_sockaddr_entry *addrw;
>   	struct sctp_sockaddr_entry *temp;
>
> -	spin_lock_bh(&sctp_addr_wq_lock);
> -	del_timer(&sctp_addr_wq_timer);
> -	list_for_each_entry_safe(addrw, temp, &sctp_addr_waitq, list) {
> +	spin_lock_bh(&net->sctp.addr_wq_lock);
> +	del_timer(&net->sctp.addr_wq_timer);
> +	list_for_each_entry_safe(addrw, temp, &net->sctp.addr_waitq, list) {
>   		list_del(&addrw->list);
>   		kfree(addrw);
>   	}
> -	spin_unlock_bh(&sctp_addr_wq_lock);
> +	spin_unlock_bh(&net->sctp.addr_wq_lock);
>   }
>
>   /* lookup the entry for the same address in the addr_waitq
>    * sctp_addr_wq MUST be locked
>    */
> -static struct sctp_sockaddr_entry *sctp_addr_wq_lookup(struct sctp_sockaddr_entry *addr)
> +static struct sctp_sockaddr_entry *sctp_addr_wq_lookup(struct net *net,
> +					struct sctp_sockaddr_entry *addr)
>   {
>   	struct sctp_sockaddr_entry *addrw;
>
> -	list_for_each_entry(addrw, &sctp_addr_waitq, list) {
> +	list_for_each_entry(addrw, &net->sctp.addr_waitq, list) {
>   		if (addrw->a.sa.sa_family != addr->a.sa.sa_family)
>   			continue;
>   		if (addrw->a.sa.sa_family == AF_INET) {
> @@ -719,7 +721,7 @@ static struct sctp_sockaddr_entry *sctp_addr_wq_lookup(struct sctp_sockaddr_entr
>   	return NULL;
>   }
>
> -void sctp_addr_wq_mgmt(struct sctp_sockaddr_entry *addr, int cmd)
> +void sctp_addr_wq_mgmt(struct net *net, struct sctp_sockaddr_entry *addr, int cmd)
>   {
>   	struct sctp_sockaddr_entry *addrw;
>   	unsigned long timeo_val;
> @@ -730,9 +732,9 @@ void sctp_addr_wq_mgmt(struct sctp_sockaddr_entry *addr, int cmd)
>   	 * new address after a couple of addition and deletion of that address
>   	 */
>
> -	spin_lock_bh(&sctp_addr_wq_lock);
> +	spin_lock_bh(&net->sctp.addr_wq_lock);
>   	/* Offsets existing events in addr_wq */
> -	addrw = sctp_addr_wq_lookup(addr);
> +	addrw = sctp_addr_wq_lookup(net, addr);
>   	if (addrw) {
>   		if (addrw->state != cmd) {
>   			SCTP_DEBUG_PRINTK_IPADDR("sctp_addr_wq_mgmt offsets existing entry for %d ",
> @@ -741,27 +743,27 @@ void sctp_addr_wq_mgmt(struct sctp_sockaddr_entry *addr, int cmd)
>   			list_del(&addrw->list);
>   			kfree(addrw);
>   		}
> -		spin_unlock_bh(&sctp_addr_wq_lock);
> +		spin_unlock_bh(&net->sctp.addr_wq_lock);
>   		return;
>   	}
>
>   	/* OK, we have to add the new address to the wait queue */
>   	addrw = kmemdup(addr, sizeof(struct sctp_sockaddr_entry), GFP_ATOMIC);
>   	if (addrw == NULL) {
> -		spin_unlock_bh(&sctp_addr_wq_lock);
> +		spin_unlock_bh(&net->sctp.addr_wq_lock);
>   		return;
>   	}
>   	addrw->state = cmd;
> -	list_add_tail(&addrw->list, &sctp_addr_waitq);
> +	list_add_tail(&addrw->list, &net->sctp.addr_waitq);
>   	SCTP_DEBUG_PRINTK_IPADDR("sctp_addr_wq_mgmt add new entry for cmd:%d ",
> -	    " in wq %p\n", addrw->state, &addrw->a, &sctp_addr_waitq);
> +	    " in wq %p\n", addrw->state, &addrw->a, &net->sctp.addr_waitq);
>
> -	if (!timer_pending(&sctp_addr_wq_timer)) {
> +	if (!timer_pending(&net->sctp.addr_wq_timer)) {
>   		timeo_val = jiffies;
>   		timeo_val += msecs_to_jiffies(SCTP_ADDRESS_TICK_DELAY);
> -		mod_timer(&sctp_addr_wq_timer, timeo_val);
> +		mod_timer(&net->sctp.addr_wq_timer, timeo_val);
>   	}
> -	spin_unlock_bh(&sctp_addr_wq_lock);
> +	spin_unlock_bh(&net->sctp.addr_wq_lock);
>   }
>
>   /* Event handler for inet address addition/deletion events.
> @@ -776,11 +778,9 @@ static int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev,
>   	struct in_ifaddr *ifa = (struct in_ifaddr *)ptr;
>   	struct sctp_sockaddr_entry *addr = NULL;
>   	struct sctp_sockaddr_entry *temp;
> +	struct net *net = dev_net(ifa->ifa_dev->dev);
>   	int found = 0;
>
> -	if (!net_eq(dev_net(ifa->ifa_dev->dev), &init_net))
> -		return NOTIFY_DONE;
> -
>   	switch (ev) {
>   	case NETDEV_UP:
>   		addr = kmalloc(sizeof(struct sctp_sockaddr_entry), GFP_ATOMIC);
> @@ -789,27 +789,27 @@ static int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev,
>   			addr->a.v4.sin_port = 0;
>   			addr->a.v4.sin_addr.s_addr = ifa->ifa_local;
>   			addr->valid = 1;
> -			spin_lock_bh(&sctp_local_addr_lock);
> -			list_add_tail_rcu(&addr->list, &sctp_local_addr_list);
> -			sctp_addr_wq_mgmt(addr, SCTP_ADDR_NEW);
> -			spin_unlock_bh(&sctp_local_addr_lock);
> +			spin_lock_bh(&net->sctp.local_addr_lock);
> +			list_add_tail_rcu(&addr->list, &net->sctp.local_addr_list);
> +			sctp_addr_wq_mgmt(net, addr, SCTP_ADDR_NEW);
> +			spin_unlock_bh(&net->sctp.local_addr_lock);
>   		}
>   		break;
>   	case NETDEV_DOWN:
> -		spin_lock_bh(&sctp_local_addr_lock);
> +		spin_lock_bh(&net->sctp.local_addr_lock);
>   		list_for_each_entry_safe(addr, temp,
> -					&sctp_local_addr_list, list) {
> +					&net->sctp.local_addr_list, list) {
>   			if (addr->a.sa.sa_family == AF_INET &&
>   					addr->a.v4.sin_addr.s_addr ==
>   					ifa->ifa_local) {
> -				sctp_addr_wq_mgmt(addr, SCTP_ADDR_DEL);
> +				sctp_addr_wq_mgmt(net, addr, SCTP_ADDR_DEL);
>   				found = 1;
>   				addr->valid = 0;
>   				list_del_rcu(&addr->list);
>   				break;
>   			}
>   		}
> -		spin_unlock_bh(&sctp_local_addr_lock);
> +		spin_unlock_bh(&net->sctp.local_addr_lock);
>   		if (found)
>   			kfree_rcu(addr, rcu);
>   		break;
> @@ -1194,6 +1194,36 @@ static void sctp_v4_del_protocol(void)
>   	unregister_inetaddr_notifier(&sctp_inetaddr_notifier);
>   }
>
> +static int sctp_net_init(struct net *net)
> +{
> +	/* Initialize the local address list. */
> +	INIT_LIST_HEAD(&net->sctp.local_addr_list);
> +	spin_lock_init(&net->sctp.local_addr_lock);
> +	sctp_get_local_addr_list(net);
> +
> +	/* Initialize the address event list */
> +	INIT_LIST_HEAD(&net->sctp.addr_waitq);
> +	INIT_LIST_HEAD(&net->sctp.auto_asconf_splist);
> +	spin_lock_init(&net->sctp.addr_wq_lock);
> +	net->sctp.addr_wq_timer.expires = 0;
> +	setup_timer(&net->sctp.addr_wq_timer, sctp_addr_wq_timeout_handler,
> +		    (unsigned long)net);
> +
> +	return 0;
> +}
> +
> +static void sctp_net_exit(struct net *net)
> +{
> +	/* Free the local address list */
> +	sctp_free_addr_wq(net);
> +	sctp_free_local_addr_list(net);
> +}
> +
> +static struct pernet_operations sctp_net_ops = {
> +	.init = sctp_net_init,
> +	.exit = sctp_net_exit,
> +};
> +
>   /* Initialize the universe into something sensible.  */
>   SCTP_STATIC __init int sctp_init(void)
>   {
> @@ -1399,18 +1429,6 @@ SCTP_STATIC __init int sctp_init(void)
>   	sctp_v4_pf_init();
>   	sctp_v6_pf_init();
>
> -	/* Initialize the local address list. */
> -	INIT_LIST_HEAD(&sctp_local_addr_list);
> -	spin_lock_init(&sctp_local_addr_lock);
> -	sctp_get_local_addr_list();
> -
> -	/* Initialize the address event list */
> -	INIT_LIST_HEAD(&sctp_addr_waitq);
> -	INIT_LIST_HEAD(&sctp_auto_asconf_splist);
> -	spin_lock_init(&sctp_addr_wq_lock);
> -	sctp_addr_wq_timer.expires = 0;
> -	setup_timer(&sctp_addr_wq_timer, sctp_addr_wq_timeout_handler, 0);
> -
>   	status = sctp_v4_protosw_init();
>
>   	if (status)
> @@ -1426,6 +1444,10 @@ SCTP_STATIC __init int sctp_init(void)
>   		goto err_ctl_sock_init;
>   	}
>
> +	status = register_pernet_subsys(&sctp_net_ops);
> +	if (status)
> +		goto err_register_pernet_subsys;
> +
>   	status = sctp_v4_add_protocol();
>   	if (status)
>   		goto err_add_protocol;
> @@ -1441,13 +1463,14 @@ out:
>   err_v6_add_protocol:
>   	sctp_v4_del_protocol();
>   err_add_protocol:
> +	unregister_pernet_subsys(&sctp_net_ops);
> +err_register_pernet_subsys:
>   	inet_ctl_sock_destroy(sctp_ctl_sock);
>   err_ctl_sock_init:
>   	sctp_v6_protosw_exit();
>   err_v6_protosw_init:
>   	sctp_v4_protosw_exit();
>   err_protosw_init:
> -	sctp_free_local_addr_list();
>   	sctp_v4_pf_exit();
>   	sctp_v6_pf_exit();
>   	sctp_sysctl_unregister();
> @@ -1482,18 +1505,16 @@ SCTP_STATIC __exit void sctp_exit(void)
>   	/* Unregister with inet6/inet layers. */
>   	sctp_v6_del_protocol();
>   	sctp_v4_del_protocol();
> -	sctp_free_addr_wq();
>
>   	/* Free the control endpoint.  */
>   	inet_ctl_sock_destroy(sctp_ctl_sock);
>
> +	unregister_pernet_subsys(&sctp_net_ops);
> +
>   	/* Free protosw registrations */
>   	sctp_v6_protosw_exit();
>   	sctp_v4_protosw_exit();
>
> -	/* Free the local address list.  */
> -	sctp_free_local_addr_list();
> -
>   	/* Unregister with socket layer. */
>   	sctp_v6_pf_exit();
>   	sctp_v4_pf_exit();
> diff --git a/net/sctp/socket.c b/net/sctp/socket.c
> index 4316b0f..5b6dd0e 100644
> --- a/net/sctp/socket.c
> +++ b/net/sctp/socket.c
> @@ -3471,7 +3471,7 @@ static int sctp_setsockopt_auto_asconf(struct sock *sk, char __user *optval,
>   		sp->do_auto_asconf = 0;
>   	} else if (val && !sp->do_auto_asconf) {
>   		list_add_tail(&sp->auto_asconf_list,
> -		    &sctp_auto_asconf_splist);
> +		    &sock_net(sk)->sctp.auto_asconf_splist);
>   		sp->do_auto_asconf = 1;
>   	}
>   	return 0;
> @@ -3964,7 +3964,7 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk)
>   	sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
>   	if (sctp_default_auto_asconf) {
>   		list_add_tail(&sp->auto_asconf_list,
> -		    &sctp_auto_asconf_splist);
> +		    &sock_net(sk)->sctp.auto_asconf_splist);
>   		sp->do_auto_asconf = 1;
>   	} else
>   		sp->do_auto_asconf = 0;
> @@ -4653,9 +4653,10 @@ static int sctp_copy_laddrs(struct sock *sk, __u16 port, void *to,
>   	union sctp_addr temp;
>   	int cnt = 0;
>   	int addrlen;
> +	struct net *net = sock_net(sk);
>
>   	rcu_read_lock();
> -	list_for_each_entry_rcu(addr, &sctp_local_addr_list, list) {
> +	list_for_each_entry_rcu(addr, &net->sctp.local_addr_list, list) {
>   		if (!addr->valid)
>   			continue;
>
>

^ permalink raw reply

* Re: [PATCH net-next 5/9] sctp: Make the ctl_sock per network namespace
From: Vlad Yasevich @ 2012-08-15  3:19 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: David Miller, linux-sctp, netdev, linux-kernel, Jan Ariyasu,
	Jan Ariyasu, Neil Horman, Thomas Graf, Xi Wang
In-Reply-To: <877gtbq2th.fsf_-_@xmission.com>

On 08/06/2012 02:43 PM, Eric W. Biederman wrote:
>
> - Kill sctp_get_ctl_sock, it is useless now.
> - Pass struct net where needed so net->sctp.ctl_sock is accessible.
>
> Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>

Acked-by: Vlad Yasevich <vyasevich@gmail.com>

> ---
>   include/net/netns/sctp.h |    8 +++++++
>   include/net/sctp/sctp.h  |    1 -
>   net/sctp/input.c         |    4 +-
>   net/sctp/protocol.c      |   47 ++++++++++++++++++---------------------------
>   net/sctp/sm_statefuns.c  |   45 ++++++++++++++++++++++++++++++-------------
>   5 files changed, 60 insertions(+), 45 deletions(-)
>
> diff --git a/include/net/netns/sctp.h b/include/net/netns/sctp.h
> index cbd684e..29e36b4 100644
> --- a/include/net/netns/sctp.h
> +++ b/include/net/netns/sctp.h
> @@ -1,7 +1,15 @@
>   #ifndef __NETNS_SCTP_H__
>   #define __NETNS_SCTP_H__
>
> +struct sock;
> +
>   struct netns_sctp {
> +	/* This is the global socket data structure used for responding to
> +	 * the Out-of-the-blue (OOTB) packets.  A control sock will be created
> +	 * for this socket at the initialization time.
> +	 */
> +	struct sock *ctl_sock;
> +
>   	/* This is the global local address list.
>   	 * We actively maintain this complete list of addresses on
>   	 * the system by catching address add/delete events.
> diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
> index 00c9205..550a81b 100644
> --- a/include/net/sctp/sctp.h
> +++ b/include/net/sctp/sctp.h
> @@ -114,7 +114,6 @@
>   /*
>    * sctp/protocol.c
>    */
> -extern struct sock *sctp_get_ctl_sock(void);
>   extern int sctp_copy_local_addr_list(struct net *, struct sctp_bind_addr *,
>   				     sctp_scope_t, gfp_t gfp,
>   				     int flags);
> diff --git a/net/sctp/input.c b/net/sctp/input.c
> index a7e9a85..c9a0449 100644
> --- a/net/sctp/input.c
> +++ b/net/sctp/input.c
> @@ -204,7 +204,7 @@ int sctp_rcv(struct sk_buff *skb)
>   			sctp_endpoint_put(ep);
>   			ep = NULL;
>   		}
> -		sk = sctp_get_ctl_sock();
> +		sk = net->sctp.ctl_sock;
>   		ep = sctp_sk(sk)->ep;
>   		sctp_endpoint_hold(ep);
>   		rcvr = &ep->base;
> @@ -795,7 +795,7 @@ static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(struct net *net,
>   			goto hit;
>   	}
>
> -	ep = sctp_sk((sctp_get_ctl_sock()))->ep;
> +	ep = sctp_sk(net->sctp.ctl_sock)->ep;
>
>   hit:
>   	sctp_endpoint_hold(ep);
> diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
> index 291e682..6193d20 100644
> --- a/net/sctp/protocol.c
> +++ b/net/sctp/protocol.c
> @@ -78,12 +78,6 @@ struct proc_dir_entry	*proc_net_sctp;
>   struct idr sctp_assocs_id;
>   DEFINE_SPINLOCK(sctp_assocs_id_lock);
>
> -/* This is the global socket data structure used for responding to
> - * the Out-of-the-blue (OOTB) packets.  A control sock will be created
> - * for this socket at the initialization time.
> - */
> -static struct sock *sctp_ctl_sock;
> -
>   static struct sctp_pf *sctp_pf_inet6_specific;
>   static struct sctp_pf *sctp_pf_inet_specific;
>   static struct sctp_af *sctp_af_v4_specific;
> @@ -96,12 +90,6 @@ long sysctl_sctp_mem[3];
>   int sysctl_sctp_rmem[3];
>   int sysctl_sctp_wmem[3];
>
> -/* Return the address of the control sock. */
> -struct sock *sctp_get_ctl_sock(void)
> -{
> -	return sctp_ctl_sock;
> -}
> -
>   /* Set up the proc fs entry for the SCTP protocol. */
>   static __init int sctp_proc_init(void)
>   {
> @@ -822,7 +810,7 @@ static int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev,
>    * Initialize the control inode/socket with a control endpoint data
>    * structure.  This endpoint is reserved exclusively for the OOTB processing.
>    */
> -static int sctp_ctl_sock_init(void)
> +static int sctp_ctl_sock_init(struct net *net)
>   {
>   	int err;
>   	sa_family_t family = PF_INET;
> @@ -830,14 +818,14 @@ static int sctp_ctl_sock_init(void)
>   	if (sctp_get_pf_specific(PF_INET6))
>   		family = PF_INET6;
>
> -	err = inet_ctl_sock_create(&sctp_ctl_sock, family,
> -				   SOCK_SEQPACKET, IPPROTO_SCTP, &init_net);
> +	err = inet_ctl_sock_create(&net->sctp.ctl_sock, family,
> +				   SOCK_SEQPACKET, IPPROTO_SCTP, net);
>
>   	/* If IPv6 socket could not be created, try the IPv4 socket */
>   	if (err < 0 && family == PF_INET6)
> -		err = inet_ctl_sock_create(&sctp_ctl_sock, AF_INET,
> +		err = inet_ctl_sock_create(&net->sctp.ctl_sock, AF_INET,
>   					   SOCK_SEQPACKET, IPPROTO_SCTP,
> -					   &init_net);
> +					   net);
>
>   	if (err < 0) {
>   		pr_err("Failed to create the SCTP control socket\n");
> @@ -1196,6 +1184,14 @@ static void sctp_v4_del_protocol(void)
>
>   static int sctp_net_init(struct net *net)
>   {
> +	int status;
> +
> +	/* Initialize the control inode/socket for handling OOTB packets.  */
> +	if ((status = sctp_ctl_sock_init(net))) {
> +		pr_err("Failed to initialize the SCTP control sock\n");
> +		goto err_ctl_sock_init;
> +	}
> +
>   	/* Initialize the local address list. */
>   	INIT_LIST_HEAD(&net->sctp.local_addr_list);
>   	spin_lock_init(&net->sctp.local_addr_lock);
> @@ -1210,6 +1206,9 @@ static int sctp_net_init(struct net *net)
>   		    (unsigned long)net);
>
>   	return 0;
> +
> +err_ctl_sock_init:
> +	return status;
>   }
>
>   static void sctp_net_exit(struct net *net)
> @@ -1217,6 +1216,9 @@ static void sctp_net_exit(struct net *net)
>   	/* Free the local address list */
>   	sctp_free_addr_wq(net);
>   	sctp_free_local_addr_list(net);
> +
> +	/* Free the control endpoint.  */
> +	inet_ctl_sock_destroy(net->sctp.ctl_sock);
>   }
>
>   static struct pernet_operations sctp_net_ops = {
> @@ -1438,12 +1440,6 @@ SCTP_STATIC __init int sctp_init(void)
>   	if (status)
>   		goto err_v6_protosw_init;
>
> -	/* Initialize the control inode/socket for handling OOTB packets.  */
> -	if ((status = sctp_ctl_sock_init())) {
> -		pr_err("Failed to initialize the SCTP control sock\n");
> -		goto err_ctl_sock_init;
> -	}
> -
>   	status = register_pernet_subsys(&sctp_net_ops);
>   	if (status)
>   		goto err_register_pernet_subsys;
> @@ -1465,8 +1461,6 @@ err_v6_add_protocol:
>   err_add_protocol:
>   	unregister_pernet_subsys(&sctp_net_ops);
>   err_register_pernet_subsys:
> -	inet_ctl_sock_destroy(sctp_ctl_sock);
> -err_ctl_sock_init:
>   	sctp_v6_protosw_exit();
>   err_v6_protosw_init:
>   	sctp_v4_protosw_exit();
> @@ -1506,9 +1500,6 @@ SCTP_STATIC __exit void sctp_exit(void)
>   	sctp_v6_del_protocol();
>   	sctp_v4_del_protocol();
>
> -	/* Free the control endpoint.  */
> -	inet_ctl_sock_destroy(sctp_ctl_sock);
> -
>   	unregister_pernet_subsys(&sctp_net_ops);
>
>   	/* Free protosw registrations */
> diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
> index 9fca103..f2daf61 100644
> --- a/net/sctp/sm_statefuns.c
> +++ b/net/sctp/sm_statefuns.c
> @@ -74,7 +74,8 @@ static struct sctp_packet *sctp_abort_pkt_new(const struct sctp_endpoint *ep,
>   static int sctp_eat_data(const struct sctp_association *asoc,
>   			 struct sctp_chunk *chunk,
>   			 sctp_cmd_seq_t *commands);
> -static struct sctp_packet *sctp_ootb_pkt_new(const struct sctp_association *asoc,
> +static struct sctp_packet *sctp_ootb_pkt_new(struct net *net,
> +					     const struct sctp_association *asoc,
>   					     const struct sctp_chunk *chunk);
>   static void sctp_send_stale_cookie_err(const struct sctp_endpoint *ep,
>   				       const struct sctp_association *asoc,
> @@ -301,6 +302,7 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const struct sctp_endpoint *ep,
>   	struct sctp_chunk *err_chunk;
>   	struct sctp_packet *packet;
>   	sctp_unrecognized_param_t *unk_param;
> +	struct net *net;
>   	int len;
>
>   	/* 6.10 Bundling
> @@ -318,7 +320,8 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const struct sctp_endpoint *ep,
>   	/* If the packet is an OOTB packet which is temporarily on the
>   	 * control endpoint, respond with an ABORT.
>   	 */
> -	if (ep == sctp_sk((sctp_get_ctl_sock()))->ep) {
> +	net = sock_net(ep->base.sk);
> +	if (ep == sctp_sk(net->sctp.ctl_sock)->ep) {
>   		SCTP_INC_STATS(SCTP_MIB_OUTOFBLUES);
>   		return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands);
>   	}
> @@ -646,11 +649,13 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep,
>   	int error = 0;
>   	struct sctp_chunk *err_chk_p;
>   	struct sock *sk;
> +	struct net *net;
>
>   	/* If the packet is an OOTB packet which is temporarily on the
>   	 * control endpoint, respond with an ABORT.
>   	 */
> -	if (ep == sctp_sk((sctp_get_ctl_sock()))->ep) {
> +	net = sock_net(ep->base.sk);
> +	if (ep == sctp_sk(net->sctp.ctl_sock)->ep) {
>   		SCTP_INC_STATS(SCTP_MIB_OUTOFBLUES);
>   		return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands);
>   	}
> @@ -1171,7 +1176,7 @@ sctp_disposition_t sctp_sf_backbeat_8_3(const struct sctp_endpoint *ep,
>   /* Helper function to send out an abort for the restart
>    * condition.
>    */
> -static int sctp_sf_send_restart_abort(union sctp_addr *ssa,
> +static int sctp_sf_send_restart_abort(struct net *net, union sctp_addr *ssa,
>   				      struct sctp_chunk *init,
>   				      sctp_cmd_seq_t *commands)
>   {
> @@ -1197,7 +1202,7 @@ static int sctp_sf_send_restart_abort(union sctp_addr *ssa,
>   	errhdr->length = htons(len);
>
>   	/* Assign to the control socket. */
> -	ep = sctp_sk((sctp_get_ctl_sock()))->ep;
> +	ep = sctp_sk(net->sctp.ctl_sock)->ep;
>
>   	/* Association is NULL since this may be a restart attack and we
>   	 * want to send back the attacker's vtag.
> @@ -1240,6 +1245,7 @@ static int sctp_sf_check_restart_addrs(const struct sctp_association *new_asoc,
>   				       struct sctp_chunk *init,
>   				       sctp_cmd_seq_t *commands)
>   {
> +	struct net *net = sock_net(new_asoc->base.sk);
>   	struct sctp_transport *new_addr;
>   	int ret = 1;
>
> @@ -1258,7 +1264,7 @@ static int sctp_sf_check_restart_addrs(const struct sctp_association *new_asoc,
>   			    transports) {
>   		if (!list_has_sctp_addr(&asoc->peer.transport_addr_list,
>   					&new_addr->ipaddr)) {
> -			sctp_sf_send_restart_abort(&new_addr->ipaddr, init,
> +			sctp_sf_send_restart_abort(net, &new_addr->ipaddr, init,
>   						   commands);
>   			ret = 0;
>   			break;
> @@ -1650,10 +1656,11 @@ sctp_disposition_t sctp_sf_do_5_2_3_initack(const struct sctp_endpoint *ep,
>   					    const sctp_subtype_t type,
>   					    void *arg, sctp_cmd_seq_t *commands)
>   {
> +	struct net *net = sock_net(ep->base.sk);
>   	/* Per the above section, we'll discard the chunk if we have an
>   	 * endpoint.  If this is an OOTB INIT-ACK, treat it as such.
>   	 */
> -	if (ep == sctp_sk((sctp_get_ctl_sock()))->ep)
> +	if (ep == sctp_sk(net->sctp.ctl_sock)->ep)
>   		return sctp_sf_ootb(ep, asoc, type, arg, commands);
>   	else
>   		return sctp_sf_discard_chunk(ep, asoc, type, arg, commands);
> @@ -3163,8 +3170,10 @@ static sctp_disposition_t sctp_sf_tabort_8_4_8(const struct sctp_endpoint *ep,
>   	struct sctp_packet *packet = NULL;
>   	struct sctp_chunk *chunk = arg;
>   	struct sctp_chunk *abort;
> +	struct net *net;
>
> -	packet = sctp_ootb_pkt_new(asoc, chunk);
> +	net = sock_net(ep->base.sk);
> +	packet = sctp_ootb_pkt_new(net, asoc, chunk);
>
>   	if (packet) {
>   		/* Make an ABORT. The T bit will be set if the asoc
> @@ -3425,8 +3434,10 @@ static sctp_disposition_t sctp_sf_shut_8_4_5(const struct sctp_endpoint *ep,
>   	struct sctp_packet *packet = NULL;
>   	struct sctp_chunk *chunk = arg;
>   	struct sctp_chunk *shut;
> +	struct net *net;
>
> -	packet = sctp_ootb_pkt_new(asoc, chunk);
> +	net = sock_net(ep->base.sk);
> +	packet = sctp_ootb_pkt_new(net, asoc, chunk);
>
>   	if (packet) {
>   		/* Make an SHUTDOWN_COMPLETE.
> @@ -4262,6 +4273,7 @@ static sctp_disposition_t sctp_sf_abort_violation(
>   	struct sctp_packet *packet = NULL;
>   	struct sctp_chunk *chunk =  arg;
>   	struct sctp_chunk *abort = NULL;
> +	struct net *net;
>
>   	/* SCTP-AUTH, Section 6.3:
>   	 *    It should be noted that if the receiver wants to tear
> @@ -4282,6 +4294,7 @@ static sctp_disposition_t sctp_sf_abort_violation(
>   	if (!abort)
>   		goto nomem;
>
> +	net = sock_net(ep->base.sk);
>   	if (asoc) {
>   		/* Treat INIT-ACK as a special case during COOKIE-WAIT. */
>   		if (chunk->chunk_hdr->type == SCTP_CID_INIT_ACK &&
> @@ -4319,7 +4332,7 @@ static sctp_disposition_t sctp_sf_abort_violation(
>   			SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
>   		}
>   	} else {
> -		packet = sctp_ootb_pkt_new(asoc, chunk);
> +		packet = sctp_ootb_pkt_new(net, asoc, chunk);
>
>   		if (!packet)
>   			goto nomem_pkt;
> @@ -5825,8 +5838,10 @@ static struct sctp_packet *sctp_abort_pkt_new(const struct sctp_endpoint *ep,
>   {
>   	struct sctp_packet *packet;
>   	struct sctp_chunk *abort;
> +	struct net *net;
>
> -	packet = sctp_ootb_pkt_new(asoc, chunk);
> +	net = sock_net(ep->base.sk);
> +	packet = sctp_ootb_pkt_new(net, asoc, chunk);
>
>   	if (packet) {
>   		/* Make an ABORT.
> @@ -5858,7 +5873,8 @@ static struct sctp_packet *sctp_abort_pkt_new(const struct sctp_endpoint *ep,
>   }
>
>   /* Allocate a packet for responding in the OOTB conditions.  */
> -static struct sctp_packet *sctp_ootb_pkt_new(const struct sctp_association *asoc,
> +static struct sctp_packet *sctp_ootb_pkt_new(struct net *net,
> +					     const struct sctp_association *asoc,
>   					     const struct sctp_chunk *chunk)
>   {
>   	struct sctp_packet *packet;
> @@ -5919,7 +5935,7 @@ static struct sctp_packet *sctp_ootb_pkt_new(const struct sctp_association *asoc
>   	 * the source address.
>   	 */
>   	sctp_transport_route(transport, (union sctp_addr *)&chunk->dest,
> -			     sctp_sk(sctp_get_ctl_sock()));
> +			     sctp_sk(net->sctp.ctl_sock));
>
>   	packet = sctp_packet_init(&transport->packet, transport, sport, dport);
>   	packet = sctp_packet_config(packet, vtag, 0);
> @@ -5946,7 +5962,8 @@ static void sctp_send_stale_cookie_err(const struct sctp_endpoint *ep,
>   	struct sctp_packet *packet;
>
>   	if (err_chunk) {
> -		packet = sctp_ootb_pkt_new(asoc, chunk);
> +		struct net *net = sock_net(ep->base.sk);
> +		packet = sctp_ootb_pkt_new(net, asoc, chunk);
>   		if (packet) {
>   			struct sctp_signed_cookie *cookie;
>
>

^ permalink raw reply

* Re: [PATCH net-next 6/9] sctp: Move the percpu sockets counter out of sctp_proc_init
From: Vlad Yasevich @ 2012-08-15  3:19 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: David Miller, linux-sctp, netdev, linux-kernel, Jan Ariyasu,
	Jan Ariyasu, Neil Horman, Thomas Graf, Xi Wang
In-Reply-To: <87393zq2rb.fsf_-_@xmission.com>

On 08/06/2012 02:44 PM, Eric W. Biederman wrote:
>
> The percpu sctp socket counter has nothing at all to do with the sctp
> proc files, and having it in the wrong initialization is confusing,
> and makes network namespace support a pain.
>
> Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>

Acked-by: Vlad Yasevich <vyasevich@gmail.com>

> ---
>   net/sctp/protocol.c |   13 +++++++------
>   1 files changed, 7 insertions(+), 6 deletions(-)
>
> diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
> index 6193d20..976d765 100644
> --- a/net/sctp/protocol.c
> +++ b/net/sctp/protocol.c
> @@ -93,8 +93,6 @@ int sysctl_sctp_wmem[3];
>   /* Set up the proc fs entry for the SCTP protocol. */
>   static __init int sctp_proc_init(void)
>   {
> -	if (percpu_counter_init(&sctp_sockets_allocated, 0))
> -		goto out_nomem;
>   #ifdef CONFIG_PROC_FS
>   	if (!proc_net_sctp) {
>   		proc_net_sctp = proc_mkdir("sctp", init_net.proc_net);
> @@ -125,12 +123,9 @@ out_snmp_proc_init:
>   		remove_proc_entry("sctp", init_net.proc_net);
>   	}
>   out_free_percpu:
> -	percpu_counter_destroy(&sctp_sockets_allocated);
>   #else
>   	return 0;
>   #endif /* CONFIG_PROC_FS */
> -
> -out_nomem:
>   	return -ENOMEM;
>   }
>
> @@ -151,7 +146,6 @@ static void sctp_proc_exit(void)
>   		remove_proc_entry("sctp", init_net.proc_net);
>   	}
>   #endif
> -	percpu_counter_destroy(&sctp_sockets_allocated);
>   }
>
>   /* Private helper to extract ipv4 address and stash them in
> @@ -1261,6 +1255,10 @@ SCTP_STATIC __init int sctp_init(void)
>   	if (status)
>   		goto err_init_mibs;
>
> +	status = percpu_counter_init(&sctp_sockets_allocated, 0);
> +	if (status)
> +		goto err_percpu_counter_init;
> +
>   	/* Initialize proc fs directory.  */
>   	status = sctp_proc_init();
>   	if (status)
> @@ -1481,6 +1479,8 @@ err_ahash_alloc:
>   	sctp_dbg_objcnt_exit();
>   	sctp_proc_exit();
>   err_init_proc:
> +	percpu_counter_destroy(&sctp_sockets_allocated);
> +err_percpu_counter_init:
>   	cleanup_sctp_mibs();
>   err_init_mibs:
>   	kmem_cache_destroy(sctp_chunk_cachep);
> @@ -1521,6 +1521,7 @@ SCTP_STATIC __exit void sctp_exit(void)
>   			     sizeof(struct sctp_bind_hashbucket)));
>
>   	sctp_dbg_objcnt_exit();
> +	percpu_counter_destroy(&sctp_sockets_allocated);
>   	sctp_proc_exit();
>   	cleanup_sctp_mibs();
>
>

^ permalink raw reply

* Re: [PATCH net-next 7/9] sctp: Make the proc files per network namespace.
From: Vlad Yasevich @ 2012-08-15  3:19 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: David Miller, linux-sctp, netdev, linux-kernel, Jan Ariyasu,
	Jan Ariyasu, Neil Horman, Thomas Graf, Xi Wang
In-Reply-To: <87wr1boo5g.fsf_-_@xmission.com>

On 08/06/2012 02:45 PM, Eric W. Biederman wrote:
>
> - Convert all of the files under /proc/net/sctp to be per
>    network namespace.
>
> - Don't print anything for /proc/net/sctp/snmp except in
>    the initial network namespaces as the snmp counters still
>    have to be converted to be per network namespace.
>
> Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>

Acked-by: Vlad Yasevich <vyasevich@gmail.com>

> ---
>   include/net/netns/sctp.h |    5 +++
>   include/net/sctp/sctp.h  |   16 +++++-----
>   net/sctp/proc.c          |   59 +++++++++++++++++++++++------------
>   net/sctp/protocol.c      |   77 +++++++++++++++++++--------------------------
>   4 files changed, 85 insertions(+), 72 deletions(-)
>
> diff --git a/include/net/netns/sctp.h b/include/net/netns/sctp.h
> index 29e36b4..9c20a82 100644
> --- a/include/net/netns/sctp.h
> +++ b/include/net/netns/sctp.h
> @@ -2,8 +2,13 @@
>   #define __NETNS_SCTP_H__
>
>   struct sock;
> +struct proc_dir_entry;
>
>   struct netns_sctp {
> +#ifdef CONFIG_PROC_FS
> +	struct proc_dir_entry *proc_net_sctp;
> +#endif
> +
>   	/* This is the global socket data structure used for responding to
>   	 * the Out-of-the-blue (OOTB) packets.  A control sock will be created
>   	 * for this socket at the initialization time.
> diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
> index 550a81b..ca716da 100644
> --- a/include/net/sctp/sctp.h
> +++ b/include/net/sctp/sctp.h
> @@ -172,14 +172,14 @@ void sctp_backlog_migrate(struct sctp_association *assoc,
>   /*
>    * sctp/proc.c
>    */
> -int sctp_snmp_proc_init(void);
> -void sctp_snmp_proc_exit(void);
> -int sctp_eps_proc_init(void);
> -void sctp_eps_proc_exit(void);
> -int sctp_assocs_proc_init(void);
> -void sctp_assocs_proc_exit(void);
> -int sctp_remaddr_proc_init(void);
> -void sctp_remaddr_proc_exit(void);
> +int sctp_snmp_proc_init(struct net *net);
> +void sctp_snmp_proc_exit(struct net *net);
> +int sctp_eps_proc_init(struct net *net);
> +void sctp_eps_proc_exit(struct net *net);
> +int sctp_assocs_proc_init(struct net *net);
> +void sctp_assocs_proc_exit(struct net *net);
> +int sctp_remaddr_proc_init(struct net *net);
> +void sctp_remaddr_proc_exit(struct net *net);
>
>
>   /*
> diff --git a/net/sctp/proc.c b/net/sctp/proc.c
> index 1e2eee8..dc79a3a 100644
> --- a/net/sctp/proc.c
> +++ b/net/sctp/proc.c
> @@ -80,8 +80,12 @@ static const struct snmp_mib sctp_snmp_list[] = {
>   /* Display sctp snmp mib statistics(/proc/net/sctp/snmp). */
>   static int sctp_snmp_seq_show(struct seq_file *seq, void *v)
>   {
> +	struct net *net = seq->private;
>   	int i;
>
> +	if (!net_eq(net, &init_net))
> +		return 0;
> +
>   	for (i = 0; sctp_snmp_list[i].name != NULL; i++)
>   		seq_printf(seq, "%-32s\t%ld\n", sctp_snmp_list[i].name,
>   			   snmp_fold_field((void __percpu **)sctp_statistics,
> @@ -93,7 +97,7 @@ static int sctp_snmp_seq_show(struct seq_file *seq, void *v)
>   /* Initialize the seq file operations for 'snmp' object. */
>   static int sctp_snmp_seq_open(struct inode *inode, struct file *file)
>   {
> -	return single_open(file, sctp_snmp_seq_show, NULL);
> +	return single_open_net(inode, file, sctp_snmp_seq_show);
>   }
>
>   static const struct file_operations sctp_snmp_seq_fops = {
> @@ -105,11 +109,12 @@ static const struct file_operations sctp_snmp_seq_fops = {
>   };
>
>   /* Set up the proc fs entry for 'snmp' object. */
> -int __init sctp_snmp_proc_init(void)
> +int __net_init sctp_snmp_proc_init(struct net *net)
>   {
>   	struct proc_dir_entry *p;
>
> -	p = proc_create("snmp", S_IRUGO, proc_net_sctp, &sctp_snmp_seq_fops);
> +	p = proc_create("snmp", S_IRUGO, net->sctp.proc_net_sctp,
> +			&sctp_snmp_seq_fops);
>   	if (!p)
>   		return -ENOMEM;
>
> @@ -117,9 +122,9 @@ int __init sctp_snmp_proc_init(void)
>   }
>
>   /* Cleanup the proc fs entry for 'snmp' object. */
> -void sctp_snmp_proc_exit(void)
> +void sctp_snmp_proc_exit(struct net *net)
>   {
> -	remove_proc_entry("snmp", proc_net_sctp);
> +	remove_proc_entry("snmp", net->sctp.proc_net_sctp);
>   }
>
>   /* Dump local addresses of an association/endpoint. */
> @@ -197,6 +202,7 @@ static void * sctp_eps_seq_next(struct seq_file *seq, void *v, loff_t *pos)
>   /* Display sctp endpoints (/proc/net/sctp/eps). */
>   static int sctp_eps_seq_show(struct seq_file *seq, void *v)
>   {
> +	struct seq_net_private *priv = seq->private;
>   	struct sctp_hashbucket *head;
>   	struct sctp_ep_common *epb;
>   	struct sctp_endpoint *ep;
> @@ -213,6 +219,8 @@ static int sctp_eps_seq_show(struct seq_file *seq, void *v)
>   	sctp_for_each_hentry(epb, node, &head->chain) {
>   		ep = sctp_ep(epb);
>   		sk = epb->sk;
> +		if (!net_eq(sock_net(sk), priv->net))
> +			continue;
>   		seq_printf(seq, "%8pK %8pK %-3d %-3d %-4d %-5d %5d %5lu ", ep, sk,
>   			   sctp_sk(sk)->type, sk->sk_state, hash,
>   			   epb->bind_addr.port,
> @@ -238,7 +246,8 @@ static const struct seq_operations sctp_eps_ops = {
>   /* Initialize the seq file operations for 'eps' object. */
>   static int sctp_eps_seq_open(struct inode *inode, struct file *file)
>   {
> -	return seq_open(file, &sctp_eps_ops);
> +	return seq_open_net(inode, file, &sctp_eps_ops,
> +			    sizeof(struct seq_net_private));
>   }
>
>   static const struct file_operations sctp_eps_seq_fops = {
> @@ -249,11 +258,12 @@ static const struct file_operations sctp_eps_seq_fops = {
>   };
>
>   /* Set up the proc fs entry for 'eps' object. */
> -int __init sctp_eps_proc_init(void)
> +int __net_init sctp_eps_proc_init(struct net *net)
>   {
>   	struct proc_dir_entry *p;
>
> -	p = proc_create("eps", S_IRUGO, proc_net_sctp, &sctp_eps_seq_fops);
> +	p = proc_create("eps", S_IRUGO, net->sctp.proc_net_sctp,
> +			&sctp_eps_seq_fops);
>   	if (!p)
>   		return -ENOMEM;
>
> @@ -261,9 +271,9 @@ int __init sctp_eps_proc_init(void)
>   }
>
>   /* Cleanup the proc fs entry for 'eps' object. */
> -void sctp_eps_proc_exit(void)
> +void sctp_eps_proc_exit(struct net *net)
>   {
> -	remove_proc_entry("eps", proc_net_sctp);
> +	remove_proc_entry("eps", net->sctp.proc_net_sctp);
>   }
>
>
> @@ -300,6 +310,7 @@ static void * sctp_assocs_seq_next(struct seq_file *seq, void *v, loff_t *pos)
>   /* Display sctp associations (/proc/net/sctp/assocs). */
>   static int sctp_assocs_seq_show(struct seq_file *seq, void *v)
>   {
> +	struct seq_net_private *priv = seq->private;
>   	struct sctp_hashbucket *head;
>   	struct sctp_ep_common *epb;
>   	struct sctp_association *assoc;
> @@ -316,6 +327,8 @@ static int sctp_assocs_seq_show(struct seq_file *seq, void *v)
>   	sctp_for_each_hentry(epb, node, &head->chain) {
>   		assoc = sctp_assoc(epb);
>   		sk = epb->sk;
> +		if (!net_eq(sock_net(sk), priv->net))
> +			continue;
>   		seq_printf(seq,
>   			   "%8pK %8pK %-3d %-3d %-2d %-4d "
>   			   "%4d %8d %8d %7d %5lu %-5d %5d ",
> @@ -354,7 +367,8 @@ static const struct seq_operations sctp_assoc_ops = {
>   /* Initialize the seq file operations for 'assocs' object. */
>   static int sctp_assocs_seq_open(struct inode *inode, struct file *file)
>   {
> -	return seq_open(file, &sctp_assoc_ops);
> +	return seq_open_net(inode, file, &sctp_assoc_ops,
> +			    sizeof(struct seq_net_private));
>   }
>
>   static const struct file_operations sctp_assocs_seq_fops = {
> @@ -365,11 +379,11 @@ static const struct file_operations sctp_assocs_seq_fops = {
>   };
>
>   /* Set up the proc fs entry for 'assocs' object. */
> -int __init sctp_assocs_proc_init(void)
> +int __net_init sctp_assocs_proc_init(struct net *net)
>   {
>   	struct proc_dir_entry *p;
>
> -	p = proc_create("assocs", S_IRUGO, proc_net_sctp,
> +	p = proc_create("assocs", S_IRUGO, net->sctp.proc_net_sctp,
>   			&sctp_assocs_seq_fops);
>   	if (!p)
>   		return -ENOMEM;
> @@ -378,9 +392,9 @@ int __init sctp_assocs_proc_init(void)
>   }
>
>   /* Cleanup the proc fs entry for 'assocs' object. */
> -void sctp_assocs_proc_exit(void)
> +void sctp_assocs_proc_exit(struct net *net)
>   {
> -	remove_proc_entry("assocs", proc_net_sctp);
> +	remove_proc_entry("assocs", net->sctp.proc_net_sctp);
>   }
>
>   static void *sctp_remaddr_seq_start(struct seq_file *seq, loff_t *pos)
> @@ -412,6 +426,7 @@ static void sctp_remaddr_seq_stop(struct seq_file *seq, void *v)
>
>   static int sctp_remaddr_seq_show(struct seq_file *seq, void *v)
>   {
> +	struct seq_net_private *priv = seq->private;
>   	struct sctp_hashbucket *head;
>   	struct sctp_ep_common *epb;
>   	struct sctp_association *assoc;
> @@ -426,6 +441,8 @@ static int sctp_remaddr_seq_show(struct seq_file *seq, void *v)
>   	sctp_local_bh_disable();
>   	read_lock(&head->lock);
>   	sctp_for_each_hentry(epb, node, &head->chain) {
> +		if (!net_eq(sock_net(epb->sk), priv->net))
> +			continue;
>   		assoc = sctp_assoc(epb);
>   		list_for_each_entry(tsp, &assoc->peer.transport_addr_list,
>   					transports) {
> @@ -489,14 +506,15 @@ static const struct seq_operations sctp_remaddr_ops = {
>   };
>
>   /* Cleanup the proc fs entry for 'remaddr' object. */
> -void sctp_remaddr_proc_exit(void)
> +void sctp_remaddr_proc_exit(struct net *net)
>   {
> -	remove_proc_entry("remaddr", proc_net_sctp);
> +	remove_proc_entry("remaddr", net->sctp.proc_net_sctp);
>   }
>
>   static int sctp_remaddr_seq_open(struct inode *inode, struct file *file)
>   {
> -	return seq_open(file, &sctp_remaddr_ops);
> +	return seq_open_net(inode, file, &sctp_remaddr_ops,
> +			    sizeof(struct seq_net_private));
>   }
>
>   static const struct file_operations sctp_remaddr_seq_fops = {
> @@ -506,11 +524,12 @@ static const struct file_operations sctp_remaddr_seq_fops = {
>   	.release = seq_release,
>   };
>
> -int __init sctp_remaddr_proc_init(void)
> +int __net_init sctp_remaddr_proc_init(struct net *net)
>   {
>   	struct proc_dir_entry *p;
>
> -	p = proc_create("remaddr", S_IRUGO, proc_net_sctp, &sctp_remaddr_seq_fops);
> +	p = proc_create("remaddr", S_IRUGO, net->sctp.proc_net_sctp,
> +			&sctp_remaddr_seq_fops);
>   	if (!p)
>   		return -ENOMEM;
>   	return 0;
> diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
> index 976d765..72b3aa7 100644
> --- a/net/sctp/protocol.c
> +++ b/net/sctp/protocol.c
> @@ -71,10 +71,6 @@
>   struct sctp_globals sctp_globals __read_mostly;
>   DEFINE_SNMP_STAT(struct sctp_mib, sctp_statistics) __read_mostly;
>
> -#ifdef CONFIG_PROC_FS
> -struct proc_dir_entry	*proc_net_sctp;
> -#endif
> -
>   struct idr sctp_assocs_id;
>   DEFINE_SPINLOCK(sctp_assocs_id_lock);
>
> @@ -91,60 +87,52 @@ int sysctl_sctp_rmem[3];
>   int sysctl_sctp_wmem[3];
>
>   /* Set up the proc fs entry for the SCTP protocol. */
> -static __init int sctp_proc_init(void)
> +static __net_init int sctp_proc_init(struct net *net)
>   {
>   #ifdef CONFIG_PROC_FS
> -	if (!proc_net_sctp) {
> -		proc_net_sctp = proc_mkdir("sctp", init_net.proc_net);
> -		if (!proc_net_sctp)
> -			goto out_free_percpu;
> -	}
> -
> -	if (sctp_snmp_proc_init())
> +	net->sctp.proc_net_sctp = proc_net_mkdir(net, "sctp", net->proc_net);
> +	if (!net->sctp.proc_net_sctp)
> +		goto out_proc_net_sctp;
> +	if (sctp_snmp_proc_init(net))
>   		goto out_snmp_proc_init;
> -	if (sctp_eps_proc_init())
> +	if (sctp_eps_proc_init(net))
>   		goto out_eps_proc_init;
> -	if (sctp_assocs_proc_init())
> +	if (sctp_assocs_proc_init(net))
>   		goto out_assocs_proc_init;
> -	if (sctp_remaddr_proc_init())
> +	if (sctp_remaddr_proc_init(net))
>   		goto out_remaddr_proc_init;
>
>   	return 0;
>
>   out_remaddr_proc_init:
> -	sctp_assocs_proc_exit();
> +	sctp_assocs_proc_exit(net);
>   out_assocs_proc_init:
> -	sctp_eps_proc_exit();
> +	sctp_eps_proc_exit(net);
>   out_eps_proc_init:
> -	sctp_snmp_proc_exit();
> +	sctp_snmp_proc_exit(net);
>   out_snmp_proc_init:
> -	if (proc_net_sctp) {
> -		proc_net_sctp = NULL;
> -		remove_proc_entry("sctp", init_net.proc_net);
> -	}
> -out_free_percpu:
> -#else
> -	return 0;
> -#endif /* CONFIG_PROC_FS */
> +	remove_proc_entry("sctp", net->proc_net);
> +	net->sctp.proc_net_sctp = NULL;
> +out_proc_net_sctp:
>   	return -ENOMEM;
> +#endif /* CONFIG_PROC_FS */
> +	return 0;
>   }
>
>   /* Clean up the proc fs entry for the SCTP protocol.
>    * Note: Do not make this __exit as it is used in the init error
>    * path.
>    */
> -static void sctp_proc_exit(void)
> +static void sctp_proc_exit(struct net *net)
>   {
>   #ifdef CONFIG_PROC_FS
> -	sctp_snmp_proc_exit();
> -	sctp_eps_proc_exit();
> -	sctp_assocs_proc_exit();
> -	sctp_remaddr_proc_exit();
> -
> -	if (proc_net_sctp) {
> -		proc_net_sctp = NULL;
> -		remove_proc_entry("sctp", init_net.proc_net);
> -	}
> +	sctp_snmp_proc_exit(net);
> +	sctp_eps_proc_exit(net);
> +	sctp_assocs_proc_exit(net);
> +	sctp_remaddr_proc_exit(net);
> +
> +	remove_proc_entry("sctp", net->proc_net);
> +	net->sctp.proc_net_sctp = NULL;
>   #endif
>   }
>
> @@ -1180,6 +1168,11 @@ static int sctp_net_init(struct net *net)
>   {
>   	int status;
>
> +	/* Initialize proc fs directory.  */
> +	status = sctp_proc_init(net);
> +	if (status)
> +		goto err_init_proc;
> +
>   	/* Initialize the control inode/socket for handling OOTB packets.  */
>   	if ((status = sctp_ctl_sock_init(net))) {
>   		pr_err("Failed to initialize the SCTP control sock\n");
> @@ -1202,6 +1195,8 @@ static int sctp_net_init(struct net *net)
>   	return 0;
>
>   err_ctl_sock_init:
> +	sctp_proc_exit(net);
> +err_init_proc:
>   	return status;
>   }
>
> @@ -1213,6 +1208,8 @@ static void sctp_net_exit(struct net *net)
>
>   	/* Free the control endpoint.  */
>   	inet_ctl_sock_destroy(net->sctp.ctl_sock);
> +
> +	sctp_proc_exit(net);
>   }
>
>   static struct pernet_operations sctp_net_ops = {
> @@ -1259,11 +1256,6 @@ SCTP_STATIC __init int sctp_init(void)
>   	if (status)
>   		goto err_percpu_counter_init;
>
> -	/* Initialize proc fs directory.  */
> -	status = sctp_proc_init();
> -	if (status)
> -		goto err_init_proc;
> -
>   	/* Initialize object count debugging.  */
>   	sctp_dbg_objcnt_init();
>
> @@ -1477,8 +1469,6 @@ err_ehash_alloc:
>   			     sizeof(struct sctp_hashbucket)));
>   err_ahash_alloc:
>   	sctp_dbg_objcnt_exit();
> -	sctp_proc_exit();
> -err_init_proc:
>   	percpu_counter_destroy(&sctp_sockets_allocated);
>   err_percpu_counter_init:
>   	cleanup_sctp_mibs();
> @@ -1522,7 +1512,6 @@ SCTP_STATIC __exit void sctp_exit(void)
>
>   	sctp_dbg_objcnt_exit();
>   	percpu_counter_destroy(&sctp_sockets_allocated);
> -	sctp_proc_exit();
>   	cleanup_sctp_mibs();
>
>   	rcu_barrier(); /* Wait for completion of call_rcu()'s */
>

^ permalink raw reply

* Re: [PATCH net-next 8/9] sctp: Enable sctp in all network namespaces
From: Vlad Yasevich @ 2012-08-15  3:20 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: David Miller, linux-sctp, netdev, linux-kernel, Jan Ariyasu,
	Jan Ariyasu, Neil Horman, Thomas Graf, Xi Wang
In-Reply-To: <87r4rjoo3h.fsf_-_@xmission.com>

On 08/06/2012 02:46 PM, Eric W. Biederman wrote:
>
> - Fix the sctp_af operations to work in all namespaces
> - Enable sctp socket creation in all network namespaces.
>
> Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>

Acked-by: Vlad Yasevich <vyasevich@gmail.com>

> ---
>   net/sctp/ipv6.c     |   12 ++++++------
>   net/sctp/protocol.c |    8 +++++---
>   2 files changed, 11 insertions(+), 9 deletions(-)
>
> diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
> index bbf1534..a18cda6 100644
> --- a/net/sctp/ipv6.c
> +++ b/net/sctp/ipv6.c
> @@ -582,7 +582,7 @@ static int sctp_v6_available(union sctp_addr *addr, struct sctp_sock *sp)
>   	if (!(type & IPV6_ADDR_UNICAST))
>   		return 0;
>
> -	return ipv6_chk_addr(&init_net, in6, NULL, 0);
> +	return ipv6_chk_addr(sock_net(&sp->inet.sk), in6, NULL, 0);
>   }
>
>   /* This function checks if the address is a valid address to be used for
> @@ -859,14 +859,14 @@ static int sctp_inet6_bind_verify(struct sctp_sock *opt, union sctp_addr *addr)
>   		struct net_device *dev;
>
>   		if (type & IPV6_ADDR_LINKLOCAL) {
> +			struct net *net;
>   			if (!addr->v6.sin6_scope_id)
>   				return 0;
> +			net = sock_net(&opt->inet.sk);
>   			rcu_read_lock();
> -			dev = dev_get_by_index_rcu(&init_net,
> -						   addr->v6.sin6_scope_id);
> +			dev = dev_get_by_index_rcu(net, addr->v6.sin6_scope_id);
>   			if (!dev ||
> -			    !ipv6_chk_addr(&init_net, &addr->v6.sin6_addr,
> -					   dev, 0)) {
> +			    !ipv6_chk_addr(net, &addr->v6.sin6_addr, dev, 0)) {
>   				rcu_read_unlock();
>   				return 0;
>   			}
> @@ -899,7 +899,7 @@ static int sctp_inet6_send_verify(struct sctp_sock *opt, union sctp_addr *addr)
>   			if (!addr->v6.sin6_scope_id)
>   				return 0;
>   			rcu_read_lock();
> -			dev = dev_get_by_index_rcu(&init_net,
> +			dev = dev_get_by_index_rcu(sock_net(&opt->inet.sk),
>   						   addr->v6.sin6_scope_id);
>   			rcu_read_unlock();
>   			if (!dev)
> diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
> index 72b3aa7..ab35691 100644
> --- a/net/sctp/protocol.c
> +++ b/net/sctp/protocol.c
> @@ -367,7 +367,8 @@ static int sctp_v4_addr_valid(union sctp_addr *addr,
>   /* Should this be available for binding?   */
>   static int sctp_v4_available(union sctp_addr *addr, struct sctp_sock *sp)
>   {
> -	int ret = inet_addr_type(&init_net, addr->v4.sin_addr.s_addr);
> +	struct net *net = sock_net(&sp->inet.sk);
> +	int ret = inet_addr_type(net, addr->v4.sin_addr.s_addr);
>
>
>   	if (addr->v4.sin_addr.s_addr != htonl(INADDR_ANY) &&
> @@ -454,7 +455,7 @@ static void sctp_v4_get_dst(struct sctp_transport *t, union sctp_addr *saddr,
>   	SCTP_DEBUG_PRINTK("%s: DST:%pI4, SRC:%pI4 - ",
>   			  __func__, &fl4->daddr, &fl4->saddr);
>
> -	rt = ip_route_output_key(&init_net, fl4);
> +	rt = ip_route_output_key(sock_net(sk), fl4);
>   	if (!IS_ERR(rt))
>   		dst = &rt->dst;
>
> @@ -500,7 +501,7 @@ static void sctp_v4_get_dst(struct sctp_transport *t, union sctp_addr *saddr,
>   		    (AF_INET == laddr->a.sa.sa_family)) {
>   			fl4->saddr = laddr->a.v4.sin_addr.s_addr;
>   			fl4->fl4_sport = laddr->a.v4.sin_port;
> -			rt = ip_route_output_key(&init_net, fl4);
> +			rt = ip_route_output_key(sock_net(sk), fl4);
>   			if (!IS_ERR(rt)) {
>   				dst = &rt->dst;
>   				goto out_unlock;
> @@ -1033,6 +1034,7 @@ static const struct net_protocol sctp_protocol = {
>   	.handler     = sctp_rcv,
>   	.err_handler = sctp_v4_err,
>   	.no_policy   = 1,
> +	.netns_ok    = 1,
>   };
>
>   /* IPv4 address related functions.  */
>

^ permalink raw reply

* Re: [PATCH net-next 9/9] sctp: Make the mib per network namespace
From: Vlad Yasevich @ 2012-08-15  3:20 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: David Miller, linux-sctp, netdev, linux-kernel, Jan Ariyasu,
	Jan Ariyasu, Neil Horman, Thomas Graf, Xi Wang
In-Reply-To: <87lihroo10.fsf_-_@xmission.com>

On 08/06/2012 02:47 PM, Eric W. Biederman wrote:
>
> Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>

Acked-by: Vlad Yasevich <vyasevich@gmail.com>
> ---
>   include/net/netns/sctp.h |    3 +
>   include/net/sctp/sctp.h  |    9 +--
>   net/sctp/associola.c     |    2 +-
>   net/sctp/chunk.c         |    2 +-
>   net/sctp/endpointola.c   |    2 +-
>   net/sctp/input.c         |   22 +++---
>   net/sctp/ipv6.c          |    4 +-
>   net/sctp/output.c        |    2 +-
>   net/sctp/outqueue.c      |   18 +++--
>   net/sctp/proc.c          |    5 +-
>   net/sctp/protocol.c      |   27 ++++----
>   net/sctp/sm_statefuns.c  |  163 +++++++++++++++++++++++++++------------------
>   net/sctp/ulpqueue.c      |   18 ++++--
>   13 files changed, 158 insertions(+), 119 deletions(-)
>
> diff --git a/include/net/netns/sctp.h b/include/net/netns/sctp.h
> index 9c20a82..06ccddf 100644
> --- a/include/net/netns/sctp.h
> +++ b/include/net/netns/sctp.h
> @@ -3,8 +3,11 @@
>
>   struct sock;
>   struct proc_dir_entry;
> +struct sctp_mib;
>
>   struct netns_sctp {
> +	DEFINE_SNMP_STAT(struct sctp_mib, sctp_statistics);
> +
>   #ifdef CONFIG_PROC_FS
>   	struct proc_dir_entry *proc_net_sctp;
>   #endif
> diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
> index ca716da..b0e6fe5 100644
> --- a/include/net/sctp/sctp.h
> +++ b/include/net/sctp/sctp.h
> @@ -221,11 +221,10 @@ extern struct kmem_cache *sctp_bucket_cachep __read_mostly;
>   #define sctp_bh_unlock_sock(sk)  bh_unlock_sock(sk)
>
>   /* SCTP SNMP MIB stats handlers */
> -DECLARE_SNMP_STAT(struct sctp_mib, sctp_statistics);
> -#define SCTP_INC_STATS(field)      SNMP_INC_STATS(sctp_statistics, field)
> -#define SCTP_INC_STATS_BH(field)   SNMP_INC_STATS_BH(sctp_statistics, field)
> -#define SCTP_INC_STATS_USER(field) SNMP_INC_STATS_USER(sctp_statistics, field)
> -#define SCTP_DEC_STATS(field)      SNMP_DEC_STATS(sctp_statistics, field)
> +#define SCTP_INC_STATS(net, field)      SNMP_INC_STATS((net)->sctp.sctp_statistics, field)
> +#define SCTP_INC_STATS_BH(net, field)   SNMP_INC_STATS_BH((net)->sctp.sctp_statistics, field)
> +#define SCTP_INC_STATS_USER(net, field) SNMP_INC_STATS_USER((net)->sctp.sctp_statistics, field)
> +#define SCTP_DEC_STATS(net, field)      SNMP_DEC_STATS((net)->sctp.sctp_statistics, field)
>
>   #endif /* !TEST_FRAME */
>
> diff --git a/net/sctp/associola.c b/net/sctp/associola.c
> index ed4930b..8a1f27a 100644
> --- a/net/sctp/associola.c
> +++ b/net/sctp/associola.c
> @@ -1150,7 +1150,7 @@ static void sctp_assoc_bh_rcv(struct work_struct *work)
>   		if (sctp_chunk_is_data(chunk))
>   			asoc->peer.last_data_from = chunk->transport;
>   		else
> -			SCTP_INC_STATS(SCTP_MIB_INCTRLCHUNKS);
> +			SCTP_INC_STATS(sock_net(asoc->base.sk), SCTP_MIB_INCTRLCHUNKS);
>
>   		if (chunk->transport)
>   			chunk->transport->last_time_heard = jiffies;
> diff --git a/net/sctp/chunk.c b/net/sctp/chunk.c
> index 6c85564..7c2df9c 100644
> --- a/net/sctp/chunk.c
> +++ b/net/sctp/chunk.c
> @@ -257,7 +257,7 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
>   	offset = 0;
>
>   	if ((whole > 1) || (whole && over))
> -		SCTP_INC_STATS_USER(SCTP_MIB_FRAGUSRMSGS);
> +		SCTP_INC_STATS_USER(sock_net(asoc->base.sk), SCTP_MIB_FRAGUSRMSGS);
>
>   	/* Create chunks for all the full sized DATA chunks. */
>   	for (i=0, len=first_len; i < whole; i++) {
> diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c
> index 6b76393..3edca80 100644
> --- a/net/sctp/endpointola.c
> +++ b/net/sctp/endpointola.c
> @@ -478,7 +478,7 @@ normal:
>   		if (asoc && sctp_chunk_is_data(chunk))
>   			asoc->peer.last_data_from = chunk->transport;
>   		else
> -			SCTP_INC_STATS(SCTP_MIB_INCTRLCHUNKS);
> +			SCTP_INC_STATS(sock_net(ep->base.sk), SCTP_MIB_INCTRLCHUNKS);
>
>   		if (chunk->transport)
>   			chunk->transport->last_time_heard = jiffies;
> diff --git a/net/sctp/input.c b/net/sctp/input.c
> index c9a0449..5308301 100644
> --- a/net/sctp/input.c
> +++ b/net/sctp/input.c
> @@ -83,7 +83,7 @@ static int sctp_add_backlog(struct sock *sk, struct sk_buff *skb);
>
>
>   /* Calculate the SCTP checksum of an SCTP packet.  */
> -static inline int sctp_rcv_checksum(struct sk_buff *skb)
> +static inline int sctp_rcv_checksum(struct net *net, struct sk_buff *skb)
>   {
>   	struct sctphdr *sh = sctp_hdr(skb);
>   	__le32 cmp = sh->checksum;
> @@ -99,7 +99,7 @@ static inline int sctp_rcv_checksum(struct sk_buff *skb)
>
>   	if (val != cmp) {
>   		/* CRC failure, dump it. */
> -		SCTP_INC_STATS_BH(SCTP_MIB_CHECKSUMERRORS);
> +		SCTP_INC_STATS_BH(net, SCTP_MIB_CHECKSUMERRORS);
>   		return -1;
>   	}
>   	return 0;
> @@ -137,7 +137,7 @@ int sctp_rcv(struct sk_buff *skb)
>   	if (skb->pkt_type!=PACKET_HOST)
>   		goto discard_it;
>
> -	SCTP_INC_STATS_BH(SCTP_MIB_INSCTPPACKS);
> +	SCTP_INC_STATS_BH(net, SCTP_MIB_INSCTPPACKS);
>
>   	if (skb_linearize(skb))
>   		goto discard_it;
> @@ -149,7 +149,7 @@ int sctp_rcv(struct sk_buff *skb)
>   	if (skb->len < sizeof(struct sctphdr))
>   		goto discard_it;
>   	if (!sctp_checksum_disable && !skb_csum_unnecessary(skb) &&
> -		  sctp_rcv_checksum(skb) < 0)
> +		  sctp_rcv_checksum(net, skb) < 0)
>   		goto discard_it;
>
>   	skb_pull(skb, sizeof(struct sctphdr));
> @@ -220,7 +220,7 @@ int sctp_rcv(struct sk_buff *skb)
>   	 */
>   	if (!asoc) {
>   		if (sctp_rcv_ootb(skb)) {
> -			SCTP_INC_STATS_BH(SCTP_MIB_OUTOFBLUES);
> +			SCTP_INC_STATS_BH(net, SCTP_MIB_OUTOFBLUES);
>   			goto discard_release;
>   		}
>   	}
> @@ -276,9 +276,9 @@ int sctp_rcv(struct sk_buff *skb)
>   			skb = NULL; /* sctp_chunk_free already freed the skb */
>   			goto discard_release;
>   		}
> -		SCTP_INC_STATS_BH(SCTP_MIB_IN_PKT_BACKLOG);
> +		SCTP_INC_STATS_BH(net, SCTP_MIB_IN_PKT_BACKLOG);
>   	} else {
> -		SCTP_INC_STATS_BH(SCTP_MIB_IN_PKT_SOFTIRQ);
> +		SCTP_INC_STATS_BH(net, SCTP_MIB_IN_PKT_SOFTIRQ);
>   		sctp_inq_push(&chunk->rcvr->inqueue, chunk);
>   	}
>
> @@ -293,7 +293,7 @@ int sctp_rcv(struct sk_buff *skb)
>   	return 0;
>
>   discard_it:
> -	SCTP_INC_STATS_BH(SCTP_MIB_IN_PKT_DISCARDS);
> +	SCTP_INC_STATS_BH(net, SCTP_MIB_IN_PKT_DISCARDS);
>   	kfree_skb(skb);
>   	return 0;
>
> @@ -543,7 +543,7 @@ struct sock *sctp_err_lookup(struct net *net, int family, struct sk_buff *skb,
>   	 * servers this needs to be solved differently.
>   	 */
>   	if (sock_owned_by_user(sk))
> -		NET_INC_STATS_BH(&init_net, LINUX_MIB_LOCKDROPPEDICMPS);
> +		NET_INC_STATS_BH(net, LINUX_MIB_LOCKDROPPEDICMPS);
>
>   	*app = asoc;
>   	*tpp = transport;
> @@ -593,7 +593,7 @@ void sctp_v4_err(struct sk_buff *skb, __u32 info)
>   	struct net *net = dev_net(skb->dev);
>
>   	if (skb->len < ihlen + 8) {
> -		ICMP_INC_STATS_BH(&init_net, ICMP_MIB_INERRORS);
> +		ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS);
>   		return;
>   	}
>
> @@ -607,7 +607,7 @@ void sctp_v4_err(struct sk_buff *skb, __u32 info)
>   	skb->network_header = saveip;
>   	skb->transport_header = savesctp;
>   	if (!sk) {
> -		ICMP_INC_STATS_BH(&init_net, ICMP_MIB_INERRORS);
> +		ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS);
>   		return;
>   	}
>   	/* Warning:  The sock lock is held.  Remember to call
> diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
> index a18cda6..ea14cb4 100644
> --- a/net/sctp/ipv6.c
> +++ b/net/sctp/ipv6.c
> @@ -169,7 +169,7 @@ SCTP_STATIC void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
>   	skb->network_header   = saveip;
>   	skb->transport_header = savesctp;
>   	if (!sk) {
> -		ICMP6_INC_STATS_BH(dev_net(skb->dev), idev, ICMP6_MIB_INERRORS);
> +		ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_INERRORS);
>   		goto out;
>   	}
>
> @@ -243,7 +243,7 @@ static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport)
>   			  __func__, skb, skb->len,
>   			  &fl6.saddr, &fl6.daddr);
>
> -	SCTP_INC_STATS(SCTP_MIB_OUTSCTPPACKS);
> +	SCTP_INC_STATS(sock_net(sk), SCTP_MIB_OUTSCTPPACKS);
>
>   	if (!(transport->param_flags & SPP_PMTUD_ENABLE))
>   		skb->local_df = 1;
> diff --git a/net/sctp/output.c b/net/sctp/output.c
> index 838e18b..0c6359b 100644
> --- a/net/sctp/output.c
> +++ b/net/sctp/output.c
> @@ -597,7 +597,7 @@ out:
>   	return err;
>   no_route:
>   	kfree_skb(nskb);
> -	IP_INC_STATS_BH(&init_net, IPSTATS_MIB_OUTNOROUTES);
> +	IP_INC_STATS_BH(sock_net(asoc->base.sk), IPSTATS_MIB_OUTNOROUTES);
>
>   	/* FIXME: Returning the 'err' will effect all the associations
>   	 * associated with a socket, although only one of the paths of the
> diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
> index e7aa177c..072bf6a 100644
> --- a/net/sctp/outqueue.c
> +++ b/net/sctp/outqueue.c
> @@ -299,6 +299,7 @@ void sctp_outq_free(struct sctp_outq *q)
>   /* Put a new chunk in an sctp_outq.  */
>   int sctp_outq_tail(struct sctp_outq *q, struct sctp_chunk *chunk)
>   {
> +	struct net *net = sock_net(q->asoc->base.sk);
>   	int error = 0;
>
>   	SCTP_DEBUG_PRINTK("sctp_outq_tail(%p, %p[%s])\n",
> @@ -337,15 +338,15 @@ int sctp_outq_tail(struct sctp_outq *q, struct sctp_chunk *chunk)
>
>   			sctp_outq_tail_data(q, chunk);
>   			if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED)
> -				SCTP_INC_STATS(SCTP_MIB_OUTUNORDERCHUNKS);
> +				SCTP_INC_STATS(net, SCTP_MIB_OUTUNORDERCHUNKS);
>   			else
> -				SCTP_INC_STATS(SCTP_MIB_OUTORDERCHUNKS);
> +				SCTP_INC_STATS(net, SCTP_MIB_OUTORDERCHUNKS);
>   			q->empty = 0;
>   			break;
>   		}
>   	} else {
>   		list_add_tail(&chunk->list, &q->control_chunk_list);
> -		SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
> +		SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS);
>   	}
>
>   	if (error < 0)
> @@ -478,11 +479,12 @@ void sctp_retransmit_mark(struct sctp_outq *q,
>   void sctp_retransmit(struct sctp_outq *q, struct sctp_transport *transport,
>   		     sctp_retransmit_reason_t reason)
>   {
> +	struct net *net = sock_net(q->asoc->base.sk);
>   	int error = 0;
>
>   	switch(reason) {
>   	case SCTP_RTXR_T3_RTX:
> -		SCTP_INC_STATS(SCTP_MIB_T3_RETRANSMITS);
> +		SCTP_INC_STATS(net, SCTP_MIB_T3_RETRANSMITS);
>   		sctp_transport_lower_cwnd(transport, SCTP_LOWER_CWND_T3_RTX);
>   		/* Update the retran path if the T3-rtx timer has expired for
>   		 * the current retran path.
> @@ -493,15 +495,15 @@ void sctp_retransmit(struct sctp_outq *q, struct sctp_transport *transport,
>   			transport->asoc->unack_data;
>   		break;
>   	case SCTP_RTXR_FAST_RTX:
> -		SCTP_INC_STATS(SCTP_MIB_FAST_RETRANSMITS);
> +		SCTP_INC_STATS(net, SCTP_MIB_FAST_RETRANSMITS);
>   		sctp_transport_lower_cwnd(transport, SCTP_LOWER_CWND_FAST_RTX);
>   		q->fast_rtx = 1;
>   		break;
>   	case SCTP_RTXR_PMTUD:
> -		SCTP_INC_STATS(SCTP_MIB_PMTUD_RETRANSMITS);
> +		SCTP_INC_STATS(net, SCTP_MIB_PMTUD_RETRANSMITS);
>   		break;
>   	case SCTP_RTXR_T1_RTX:
> -		SCTP_INC_STATS(SCTP_MIB_T1_RETRANSMITS);
> +		SCTP_INC_STATS(net, SCTP_MIB_T1_RETRANSMITS);
>   		transport->asoc->init_retries++;
>   		break;
>   	default:
> @@ -1914,6 +1916,6 @@ static void sctp_generate_fwdtsn(struct sctp_outq *q, __u32 ctsn)
>
>   	if (ftsn_chunk) {
>   		list_add_tail(&ftsn_chunk->list, &q->control_chunk_list);
> -		SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
> +		SCTP_INC_STATS(sock_net(asoc->base.sk), SCTP_MIB_OUTCTRLCHUNKS);
>   	}
>   }
> diff --git a/net/sctp/proc.c b/net/sctp/proc.c
> index dc79a3a..3e62ee5 100644
> --- a/net/sctp/proc.c
> +++ b/net/sctp/proc.c
> @@ -83,12 +83,9 @@ static int sctp_snmp_seq_show(struct seq_file *seq, void *v)
>   	struct net *net = seq->private;
>   	int i;
>
> -	if (!net_eq(net, &init_net))
> -		return 0;
> -
>   	for (i = 0; sctp_snmp_list[i].name != NULL; i++)
>   		seq_printf(seq, "%-32s\t%ld\n", sctp_snmp_list[i].name,
> -			   snmp_fold_field((void __percpu **)sctp_statistics,
> +			   snmp_fold_field((void __percpu **)net->sctp.sctp_statistics,
>   				      sctp_snmp_list[i].entry));
>
>   	return 0;
> diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
> index ab35691..69bdc72 100644
> --- a/net/sctp/protocol.c
> +++ b/net/sctp/protocol.c
> @@ -69,7 +69,6 @@
>
>   /* Global data structures. */
>   struct sctp_globals sctp_globals __read_mostly;
> -DEFINE_SNMP_STAT(struct sctp_mib, sctp_statistics) __read_mostly;
>
>   struct idr sctp_assocs_id;
>   DEFINE_SPINLOCK(sctp_assocs_id_lock);
> @@ -961,7 +960,7 @@ static inline int sctp_v4_xmit(struct sk_buff *skb,
>   	inet->pmtudisc = transport->param_flags & SPP_PMTUD_ENABLE ?
>   			 IP_PMTUDISC_DO : IP_PMTUDISC_DONT;
>
> -	SCTP_INC_STATS(SCTP_MIB_OUTSCTPPACKS);
> +	SCTP_INC_STATS(sock_net(&inet->sk), SCTP_MIB_OUTSCTPPACKS);
>   	return ip_queue_xmit(skb, &transport->fl);
>   }
>
> @@ -1102,16 +1101,16 @@ int sctp_register_pf(struct sctp_pf *pf, sa_family_t family)
>   	return 1;
>   }
>
> -static inline int init_sctp_mibs(void)
> +static inline int init_sctp_mibs(struct net *net)
>   {
> -	return snmp_mib_init((void __percpu **)sctp_statistics,
> +	return snmp_mib_init((void __percpu **)net->sctp.sctp_statistics,
>   			     sizeof(struct sctp_mib),
>   			     __alignof__(struct sctp_mib));
>   }
>
> -static inline void cleanup_sctp_mibs(void)
> +static inline void cleanup_sctp_mibs(struct net *net)
>   {
> -	snmp_mib_free((void __percpu **)sctp_statistics);
> +	snmp_mib_free((void __percpu **)net->sctp.sctp_statistics);
>   }
>
>   static void sctp_v4_pf_init(void)
> @@ -1170,6 +1169,11 @@ static int sctp_net_init(struct net *net)
>   {
>   	int status;
>
> +	/* Allocate and initialise sctp mibs.  */
> +	status = init_sctp_mibs(net);
> +	if (status)
> +		goto err_init_mibs;
> +
>   	/* Initialize proc fs directory.  */
>   	status = sctp_proc_init(net);
>   	if (status)
> @@ -1199,6 +1203,8 @@ static int sctp_net_init(struct net *net)
>   err_ctl_sock_init:
>   	sctp_proc_exit(net);
>   err_init_proc:
> +	cleanup_sctp_mibs(net);
> +err_init_mibs:
>   	return status;
>   }
>
> @@ -1212,6 +1218,7 @@ static void sctp_net_exit(struct net *net)
>   	inet_ctl_sock_destroy(net->sctp.ctl_sock);
>
>   	sctp_proc_exit(net);
> +	cleanup_sctp_mibs(net);
>   }
>
>   static struct pernet_operations sctp_net_ops = {
> @@ -1249,11 +1256,6 @@ SCTP_STATIC __init int sctp_init(void)
>   	if (!sctp_chunk_cachep)
>   		goto err_chunk_cachep;
>
> -	/* Allocate and initialise sctp mibs.  */
> -	status = init_sctp_mibs();
> -	if (status)
> -		goto err_init_mibs;
> -
>   	status = percpu_counter_init(&sctp_sockets_allocated, 0);
>   	if (status)
>   		goto err_percpu_counter_init;
> @@ -1473,8 +1475,6 @@ err_ahash_alloc:
>   	sctp_dbg_objcnt_exit();
>   	percpu_counter_destroy(&sctp_sockets_allocated);
>   err_percpu_counter_init:
> -	cleanup_sctp_mibs();
> -err_init_mibs:
>   	kmem_cache_destroy(sctp_chunk_cachep);
>   err_chunk_cachep:
>   	kmem_cache_destroy(sctp_bucket_cachep);
> @@ -1514,7 +1514,6 @@ SCTP_STATIC __exit void sctp_exit(void)
>
>   	sctp_dbg_objcnt_exit();
>   	percpu_counter_destroy(&sctp_sockets_allocated);
> -	cleanup_sctp_mibs();
>
>   	rcu_barrier(); /* Wait for completion of call_rcu()'s */
>
> diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
> index f2daf61..bee5e2c 100644
> --- a/net/sctp/sm_statefuns.c
> +++ b/net/sctp/sm_statefuns.c
> @@ -213,6 +213,7 @@ sctp_disposition_t sctp_sf_do_4_C(const struct sctp_endpoint *ep,
>   {
>   	struct sctp_chunk *chunk = arg;
>   	struct sctp_ulpevent *ev;
> +	struct net *net;
>
>   	if (!sctp_vtag_verify_either(chunk, asoc))
>   		return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
> @@ -260,8 +261,9 @@ sctp_disposition_t sctp_sf_do_4_C(const struct sctp_endpoint *ep,
>   	sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
>   			SCTP_STATE(SCTP_STATE_CLOSED));
>
> -	SCTP_INC_STATS(SCTP_MIB_SHUTDOWNS);
> -	SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
> +	net = sock_net(asoc->base.sk);
> +	SCTP_INC_STATS(net, SCTP_MIB_SHUTDOWNS);
> +	SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB);
>
>   	sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL());
>
> @@ -322,7 +324,7 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const struct sctp_endpoint *ep,
>   	 */
>   	net = sock_net(ep->base.sk);
>   	if (ep == sctp_sk(net->sctp.ctl_sock)->ep) {
> -		SCTP_INC_STATS(SCTP_MIB_OUTOFBLUES);
> +		SCTP_INC_STATS(net, SCTP_MIB_OUTOFBLUES);
>   		return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands);
>   	}
>
> @@ -369,7 +371,7 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const struct sctp_endpoint *ep,
>   			if (packet) {
>   				sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT,
>   						SCTP_PACKET(packet));
> -				SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
> +				SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS);
>   				return SCTP_DISPOSITION_CONSUME;
>   			} else {
>   				return SCTP_DISPOSITION_NOMEM;
> @@ -540,7 +542,7 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const struct sctp_endpoint *ep,
>   			if (packet) {
>   				sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT,
>   						SCTP_PACKET(packet));
> -				SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
> +				SCTP_INC_STATS(sock_net(ep->base.sk), SCTP_MIB_OUTCTRLCHUNKS);
>   				error = SCTP_ERROR_INV_PARAM;
>   			}
>   		}
> @@ -559,7 +561,7 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const struct sctp_endpoint *ep,
>   		if (sctp_auth_recv_cid(SCTP_CID_ABORT, asoc))
>   			return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
>
> -		SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
> +		SCTP_INC_STATS(sock_net(ep->base.sk), SCTP_MIB_ABORTEDS);
>   		return sctp_stop_t1_and_abort(commands, error, ECONNREFUSED,
>   						asoc, chunk->transport);
>   	}
> @@ -656,7 +658,7 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep,
>   	 */
>   	net = sock_net(ep->base.sk);
>   	if (ep == sctp_sk(net->sctp.ctl_sock)->ep) {
> -		SCTP_INC_STATS(SCTP_MIB_OUTOFBLUES);
> +		SCTP_INC_STATS(net, SCTP_MIB_OUTOFBLUES);
>   		return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands);
>   	}
>
> @@ -809,8 +811,8 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep,
>   	sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC, SCTP_ASOC(new_asoc));
>   	sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
>   			SCTP_STATE(SCTP_STATE_ESTABLISHED));
> -	SCTP_INC_STATS(SCTP_MIB_CURRESTAB);
> -	SCTP_INC_STATS(SCTP_MIB_PASSIVEESTABS);
> +	SCTP_INC_STATS(net, SCTP_MIB_CURRESTAB);
> +	SCTP_INC_STATS(net, SCTP_MIB_PASSIVEESTABS);
>   	sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START, SCTP_NULL());
>
>   	if (new_asoc->autoclose)
> @@ -868,6 +870,7 @@ sctp_disposition_t sctp_sf_do_5_1E_ca(const struct sctp_endpoint *ep,
>   {
>   	struct sctp_chunk *chunk = arg;
>   	struct sctp_ulpevent *ev;
> +	struct net *net;
>
>   	if (!sctp_vtag_verify(chunk, asoc))
>   		return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
> @@ -897,8 +900,9 @@ sctp_disposition_t sctp_sf_do_5_1E_ca(const struct sctp_endpoint *ep,
>   			SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE));
>   	sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
>   			SCTP_STATE(SCTP_STATE_ESTABLISHED));
> -	SCTP_INC_STATS(SCTP_MIB_CURRESTAB);
> -	SCTP_INC_STATS(SCTP_MIB_ACTIVEESTABS);
> +	net = sock_net(ep->base.sk);
> +	SCTP_INC_STATS(net, SCTP_MIB_CURRESTAB);
> +	SCTP_INC_STATS(net, SCTP_MIB_ACTIVEESTABS);
>   	sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START, SCTP_NULL());
>   	if (asoc->autoclose)
>   		sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START,
> @@ -972,13 +976,15 @@ sctp_disposition_t sctp_sf_sendbeat_8_3(const struct sctp_endpoint *ep,
>   	struct sctp_transport *transport = (struct sctp_transport *) arg;
>
>   	if (asoc->overall_error_count >= asoc->max_retrans) {
> +		struct net *net;
>   		sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
>   				SCTP_ERROR(ETIMEDOUT));
>   		/* CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */
>   		sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
>   				SCTP_PERR(SCTP_ERROR_NO_ERROR));
> -		SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
> -		SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
> +		net = sock_net(ep->base.sk);
> +		SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS);
> +		SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB);
>   		return SCTP_DISPOSITION_DELETE_TCB;
>   	}
>
> @@ -1213,7 +1219,7 @@ static int sctp_sf_send_restart_abort(struct net *net, union sctp_addr *ssa,
>   		goto out;
>   	sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT, SCTP_PACKET(pkt));
>
> -	SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
> +	SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS);
>
>   	/* Discard the rest of the inbound packet. */
>   	sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET, SCTP_NULL());
> @@ -1427,7 +1433,7 @@ static sctp_disposition_t sctp_sf_do_unexpected_init(
>   			if (packet) {
>   				sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT,
>   						SCTP_PACKET(packet));
> -				SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
> +				SCTP_INC_STATS(sock_net(ep->base.sk), SCTP_MIB_OUTCTRLCHUNKS);
>   				retval = SCTP_DISPOSITION_CONSUME;
>   			} else {
>   				retval = SCTP_DISPOSITION_NOMEM;
> @@ -1791,7 +1797,7 @@ static sctp_disposition_t sctp_sf_do_dupcook_b(const struct sctp_endpoint *ep,
>   	sctp_add_cmd_sf(commands, SCTP_CMD_UPDATE_ASSOC, SCTP_ASOC(new_asoc));
>   	sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
>   			SCTP_STATE(SCTP_STATE_ESTABLISHED));
> -	SCTP_INC_STATS(SCTP_MIB_CURRESTAB);
> +	SCTP_INC_STATS(sock_net(new_asoc->base.sk), SCTP_MIB_CURRESTAB);
>   	sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START, SCTP_NULL());
>
>   	repl = sctp_make_cookie_ack(new_asoc, chunk);
> @@ -1883,7 +1889,7 @@ static sctp_disposition_t sctp_sf_do_dupcook_d(const struct sctp_endpoint *ep,
>   				SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE));
>   		sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
>   				SCTP_STATE(SCTP_STATE_ESTABLISHED));
> -		SCTP_INC_STATS(SCTP_MIB_CURRESTAB);
> +		SCTP_INC_STATS(sock_net(asoc->base.sk), SCTP_MIB_CURRESTAB);
>   		sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START,
>   				SCTP_NULL());
>
> @@ -2417,6 +2423,7 @@ static sctp_disposition_t __sctp_sf_do_9_1_abort(const struct sctp_endpoint *ep,
>   	struct sctp_chunk *chunk = arg;
>   	unsigned int len;
>   	__be16 error = SCTP_ERROR_NO_ERROR;
> +	struct net *net;
>
>   	/* See if we have an error cause code in the chunk.  */
>   	len = ntohs(chunk->chunk_hdr->length);
> @@ -2433,8 +2440,9 @@ static sctp_disposition_t __sctp_sf_do_9_1_abort(const struct sctp_endpoint *ep,
>   	sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, SCTP_ERROR(ECONNRESET));
>   	/* ASSOC_FAILED will DELETE_TCB. */
>   	sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, SCTP_PERR(error));
> -	SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
> -	SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
> +	net = sock_net(ep->base.sk);
> +	SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS);
> +	SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB);
>
>   	return SCTP_DISPOSITION_ABORT;
>   }
> @@ -2521,7 +2529,7 @@ static sctp_disposition_t sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands,
>   	SCTP_DEBUG_PRINTK("ABORT received (INIT).\n");
>   	sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
>   			SCTP_STATE(SCTP_STATE_CLOSED));
> -	SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
> +	SCTP_INC_STATS(sock_net(asoc->base.sk), SCTP_MIB_ABORTEDS);
>   	sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
>   			SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT));
>   	sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, SCTP_ERROR(sk_err));
> @@ -2904,11 +2912,11 @@ sctp_disposition_t sctp_sf_eat_data_6_2(const struct sctp_endpoint *ep,
>   		break;
>   	case SCTP_IERROR_HIGH_TSN:
>   	case SCTP_IERROR_BAD_STREAM:
> -		SCTP_INC_STATS(SCTP_MIB_IN_DATA_CHUNK_DISCARDS);
> +		SCTP_INC_STATS(sock_net(asoc->base.sk), SCTP_MIB_IN_DATA_CHUNK_DISCARDS);
>   		goto discard_noforce;
>   	case SCTP_IERROR_DUP_TSN:
>   	case SCTP_IERROR_IGNORE_TSN:
> -		SCTP_INC_STATS(SCTP_MIB_IN_DATA_CHUNK_DISCARDS);
> +		SCTP_INC_STATS(sock_net(asoc->base.sk), SCTP_MIB_IN_DATA_CHUNK_DISCARDS);
>   		goto discard_force;
>   	case SCTP_IERROR_NO_DATA:
>   		goto consume;
> @@ -3197,7 +3205,7 @@ static sctp_disposition_t sctp_sf_tabort_8_4_8(const struct sctp_endpoint *ep,
>   		sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT,
>   				SCTP_PACKET(packet));
>
> -		SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
> +		SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS);
>
>   		sctp_sf_pdiscard(ep, asoc, type, arg, commands);
>   		return SCTP_DISPOSITION_CONSUME;
> @@ -3260,6 +3268,7 @@ sctp_disposition_t sctp_sf_do_9_2_final(const struct sctp_endpoint *ep,
>   	struct sctp_chunk *chunk = arg;
>   	struct sctp_chunk *reply;
>   	struct sctp_ulpevent *ev;
> +	struct net *net;
>
>   	if (!sctp_vtag_verify(chunk, asoc))
>   		return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
> @@ -3299,8 +3308,9 @@ sctp_disposition_t sctp_sf_do_9_2_final(const struct sctp_endpoint *ep,
>
>   	sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
>   			SCTP_STATE(SCTP_STATE_CLOSED));
> -	SCTP_INC_STATS(SCTP_MIB_SHUTDOWNS);
> -	SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
> +	net = sock_net(asoc->base.sk);
> +	SCTP_INC_STATS(net, SCTP_MIB_SHUTDOWNS);
> +	SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB);
>   	sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(reply));
>
>   	/* ...and remove all record of the association. */
> @@ -3346,8 +3356,10 @@ sctp_disposition_t sctp_sf_ootb(const struct sctp_endpoint *ep,
>   	__u8 *ch_end;
>   	int ootb_shut_ack = 0;
>   	int ootb_cookie_ack = 0;
> +	struct net *net;
>
> -	SCTP_INC_STATS(SCTP_MIB_OUTOFBLUES);
> +	net = sock_net(asoc->base.sk);
> +	SCTP_INC_STATS(net, SCTP_MIB_OUTOFBLUES);
>
>   	ch = (sctp_chunkhdr_t *) chunk->chunk_hdr;
>   	do {
> @@ -3461,7 +3473,7 @@ static sctp_disposition_t sctp_sf_shut_8_4_5(const struct sctp_endpoint *ep,
>   		sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT,
>   				SCTP_PACKET(packet));
>
> -		SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
> +		SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS);
>
>   		/* If the chunk length is invalid, we don't want to process
>   		 * the reset of the packet.
> @@ -3508,7 +3520,7 @@ sctp_disposition_t sctp_sf_do_8_5_1_E_sa(const struct sctp_endpoint *ep,
>   	 * packet and the state function that handles OOTB SHUTDOWN_ACK is
>   	 * called with a NULL association.
>   	 */
> -	SCTP_INC_STATS(SCTP_MIB_OUTOFBLUES);
> +	SCTP_INC_STATS(sock_net(ep->base.sk), SCTP_MIB_OUTOFBLUES);
>
>   	return sctp_sf_shut_8_4_5(ep, NULL, type, arg, commands);
>   }
> @@ -3699,6 +3711,7 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep,
>   	 */
>   	if (ADDIP_SERIAL_gte(rcvd_serial, sent_serial + 1) &&
>   	    !(asoc->addip_last_asconf)) {
> +		struct net *net;
>   		abort = sctp_make_abort(asoc, asconf_ack,
>   					sizeof(sctp_errhdr_t));
>   		if (abort) {
> @@ -3716,12 +3729,14 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep,
>   				SCTP_ERROR(ECONNABORTED));
>   		sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
>   				SCTP_PERR(SCTP_ERROR_ASCONF_ACK));
> -		SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
> -		SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
> +		net = sock_net(asoc->base.sk);
> +		SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS);
> +		SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB);
>   		return SCTP_DISPOSITION_ABORT;
>   	}
>
>   	if ((rcvd_serial == sent_serial) && asoc->addip_last_asconf) {
> +		struct net *net;
>   		sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
>   				SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO));
>
> @@ -3750,8 +3765,9 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep,
>   				SCTP_ERROR(ECONNABORTED));
>   		sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
>   				SCTP_PERR(SCTP_ERROR_ASCONF_ACK));
> -		SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
> -		SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
> +		net = sock_net(asoc->base.sk);
> +		SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS);
> +		SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB);
>   		return SCTP_DISPOSITION_ABORT;
>   	}
>
> @@ -4222,7 +4238,7 @@ sctp_disposition_t sctp_sf_pdiscard(const struct sctp_endpoint *ep,
>   				    void *arg,
>   				    sctp_cmd_seq_t *commands)
>   {
> -	SCTP_INC_STATS(SCTP_MIB_IN_PKT_DISCARDS);
> +	SCTP_INC_STATS(sock_net(asoc->base.sk), SCTP_MIB_IN_PKT_DISCARDS);
>   	sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET, SCTP_NULL());
>
>   	return SCTP_DISPOSITION_CONSUME;
> @@ -4315,7 +4331,7 @@ static sctp_disposition_t sctp_sf_abort_violation(
>   		}
>
>   		sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort));
> -		SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
> +		SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS);
>
>   		if (asoc->state <= SCTP_STATE_COOKIE_ECHOED) {
>   			sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
> @@ -4329,7 +4345,7 @@ static sctp_disposition_t sctp_sf_abort_violation(
>   					SCTP_ERROR(ECONNABORTED));
>   			sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
>   					SCTP_PERR(SCTP_ERROR_PROTO_VIOLATION));
> -			SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
> +			SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB);
>   		}
>   	} else {
>   		packet = sctp_ootb_pkt_new(net, asoc, chunk);
> @@ -4347,10 +4363,10 @@ static sctp_disposition_t sctp_sf_abort_violation(
>   		sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT,
>   			SCTP_PACKET(packet));
>
> -		SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
> +		SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS);
>   	}
>
> -	SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
> +	SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS);
>
>   discard:
>   	sctp_sf_pdiscard(ep, asoc, SCTP_ST_CHUNK(0), arg, commands);
> @@ -4410,6 +4426,7 @@ static sctp_disposition_t sctp_sf_violation_paramlen(
>   	struct sctp_chunk *chunk =  arg;
>   	struct sctp_paramhdr *param = ext;
>   	struct sctp_chunk *abort = NULL;
> +	struct net *net;
>
>   	if (sctp_auth_recv_cid(SCTP_CID_ABORT, asoc))
>   		goto discard;
> @@ -4419,15 +4436,16 @@ static sctp_disposition_t sctp_sf_violation_paramlen(
>   	if (!abort)
>   		goto nomem;
>
> +	net = sock_net(asoc->base.sk);
>   	sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort));
> -	SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
> +	SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS);
>
>   	sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
>   			SCTP_ERROR(ECONNABORTED));
>   	sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
>   			SCTP_PERR(SCTP_ERROR_PROTO_VIOLATION));
> -	SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
> -	SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
> +	SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB);
> +	SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS);
>
>   discard:
>   	sctp_sf_pdiscard(ep, asoc, SCTP_ST_CHUNK(0), arg, commands);
> @@ -4757,6 +4775,7 @@ sctp_disposition_t sctp_sf_do_9_1_prm_abort(
>   	 */
>   	struct sctp_chunk *abort = arg;
>   	sctp_disposition_t retval;
> +	struct net *net;
>
>   	retval = SCTP_DISPOSITION_CONSUME;
>
> @@ -4772,8 +4791,9 @@ sctp_disposition_t sctp_sf_do_9_1_prm_abort(
>   	sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
>   			SCTP_PERR(SCTP_ERROR_USER_ABORT));
>
> -	SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
> -	SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
> +	net = sock_net(asoc->base.sk);
> +	SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS);
> +	SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB);
>
>   	return retval;
>   }
> @@ -4824,13 +4844,15 @@ sctp_disposition_t sctp_sf_cookie_wait_prm_shutdown(
>   	void *arg,
>   	sctp_cmd_seq_t *commands)
>   {
> +	struct net *net = sock_net(asoc->base.sk);
> +
>   	sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
>   			SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT));
>
>   	sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
>   			SCTP_STATE(SCTP_STATE_CLOSED));
>
> -	SCTP_INC_STATS(SCTP_MIB_SHUTDOWNS);
> +	SCTP_INC_STATS(net, SCTP_MIB_SHUTDOWNS);
>
>   	sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL());
>
> @@ -4886,6 +4908,7 @@ sctp_disposition_t sctp_sf_cookie_wait_prm_abort(
>   {
>   	struct sctp_chunk *abort = arg;
>   	sctp_disposition_t retval;
> +	struct net *net = sock_net(asoc->base.sk);
>
>   	/* Stop T1-init timer */
>   	sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
> @@ -4897,7 +4920,7 @@ sctp_disposition_t sctp_sf_cookie_wait_prm_abort(
>   	sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
>   			SCTP_STATE(SCTP_STATE_CLOSED));
>
> -	SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
> +	SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS);
>
>   	/* Even if we can't send the ABORT due to low memory delete the
>   	 * TCB.  This is a departure from our typical NOMEM handling.
> @@ -5318,8 +5341,9 @@ sctp_disposition_t sctp_sf_do_6_3_3_rtx(const struct sctp_endpoint *ep,
>   					sctp_cmd_seq_t *commands)
>   {
>   	struct sctp_transport *transport = arg;
> +	struct net *net = sock_net(asoc->base.sk);
>
> -	SCTP_INC_STATS(SCTP_MIB_T3_RTX_EXPIREDS);
> +	SCTP_INC_STATS(net, SCTP_MIB_T3_RTX_EXPIREDS);
>
>   	if (asoc->overall_error_count >= asoc->max_retrans) {
>   		if (asoc->state == SCTP_STATE_SHUTDOWN_PENDING) {
> @@ -5340,8 +5364,8 @@ sctp_disposition_t sctp_sf_do_6_3_3_rtx(const struct sctp_endpoint *ep,
>   			/* CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */
>   			sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
>   					SCTP_PERR(SCTP_ERROR_NO_ERROR));
> -			SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
> -			SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
> +			SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS);
> +			SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB);
>   			return SCTP_DISPOSITION_DELETE_TCB;
>   		}
>   	}
> @@ -5403,7 +5427,8 @@ sctp_disposition_t sctp_sf_do_6_2_sack(const struct sctp_endpoint *ep,
>   				       void *arg,
>   				       sctp_cmd_seq_t *commands)
>   {
> -	SCTP_INC_STATS(SCTP_MIB_DELAY_SACK_EXPIREDS);
> +	struct net *net = sock_net(asoc->base.sk);
> +	SCTP_INC_STATS(net, SCTP_MIB_DELAY_SACK_EXPIREDS);
>   	sctp_add_cmd_sf(commands, SCTP_CMD_GEN_SACK, SCTP_FORCE());
>   	return SCTP_DISPOSITION_CONSUME;
>   }
> @@ -5436,9 +5461,10 @@ sctp_disposition_t sctp_sf_t1_init_timer_expire(const struct sctp_endpoint *ep,
>   	struct sctp_chunk *repl = NULL;
>   	struct sctp_bind_addr *bp;
>   	int attempts = asoc->init_err_counter + 1;
> +	struct net *net = sock_net(asoc->base.sk);
>
>   	SCTP_DEBUG_PRINTK("Timer T1 expired (INIT).\n");
> -	SCTP_INC_STATS(SCTP_MIB_T1_INIT_EXPIREDS);
> +	SCTP_INC_STATS(net, SCTP_MIB_T1_INIT_EXPIREDS);
>
>   	if (attempts <= asoc->max_init_attempts) {
>   		bp = (struct sctp_bind_addr *) &asoc->base.bind_addr;
> @@ -5496,9 +5522,10 @@ sctp_disposition_t sctp_sf_t1_cookie_timer_expire(const struct sctp_endpoint *ep
>   {
>   	struct sctp_chunk *repl = NULL;
>   	int attempts = asoc->init_err_counter + 1;
> +	struct net *net = sock_net(asoc->base.sk);
>
>   	SCTP_DEBUG_PRINTK("Timer T1 expired (COOKIE-ECHO).\n");
> -	SCTP_INC_STATS(SCTP_MIB_T1_COOKIE_EXPIREDS);
> +	SCTP_INC_STATS(net, SCTP_MIB_T1_COOKIE_EXPIREDS);
>
>   	if (attempts <= asoc->max_init_attempts) {
>   		repl = sctp_make_cookie_echo(asoc, NULL);
> @@ -5543,9 +5570,10 @@ sctp_disposition_t sctp_sf_t2_timer_expire(const struct sctp_endpoint *ep,
>   					   sctp_cmd_seq_t *commands)
>   {
>   	struct sctp_chunk *reply = NULL;
> +	struct net *net = sock_net(asoc->base.sk);
>
>   	SCTP_DEBUG_PRINTK("Timer T2 expired.\n");
> -	SCTP_INC_STATS(SCTP_MIB_T2_SHUTDOWN_EXPIREDS);
> +	SCTP_INC_STATS(net, SCTP_MIB_T2_SHUTDOWN_EXPIREDS);
>
>   	((struct sctp_association *)asoc)->shutdown_retries++;
>
> @@ -5555,8 +5583,8 @@ sctp_disposition_t sctp_sf_t2_timer_expire(const struct sctp_endpoint *ep,
>   		/* Note:  CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */
>   		sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
>   				SCTP_PERR(SCTP_ERROR_NO_ERROR));
> -		SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
> -		SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
> +		SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS);
> +		SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB);
>   		return SCTP_DISPOSITION_DELETE_TCB;
>   	}
>
> @@ -5613,8 +5641,9 @@ sctp_disposition_t sctp_sf_t4_timer_expire(
>   {
>   	struct sctp_chunk *chunk = asoc->addip_last_asconf;
>   	struct sctp_transport *transport = chunk->transport;
> +	struct net *net = sock_net(asoc->base.sk);
>
> -	SCTP_INC_STATS(SCTP_MIB_T4_RTO_EXPIREDS);
> +	SCTP_INC_STATS(net, SCTP_MIB_T4_RTO_EXPIREDS);
>
>   	/* ADDIP 4.1 B1) Increment the error counters and perform path failure
>   	 * detection on the appropriate destination address as defined in
> @@ -5639,8 +5668,8 @@ sctp_disposition_t sctp_sf_t4_timer_expire(
>   				SCTP_ERROR(ETIMEDOUT));
>   		sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
>   				SCTP_PERR(SCTP_ERROR_NO_ERROR));
> -		SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
> -		SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
> +		SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS);
> +		SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB);
>   		return SCTP_DISPOSITION_ABORT;
>   	}
>
> @@ -5682,9 +5711,10 @@ sctp_disposition_t sctp_sf_t5_timer_expire(const struct sctp_endpoint *ep,
>   					   sctp_cmd_seq_t *commands)
>   {
>   	struct sctp_chunk *reply = NULL;
> +	struct net *net = sock_net(asoc->base.sk);
>
>   	SCTP_DEBUG_PRINTK("Timer T5 expired.\n");
> -	SCTP_INC_STATS(SCTP_MIB_T5_SHUTDOWN_GUARD_EXPIREDS);
> +	SCTP_INC_STATS(net, SCTP_MIB_T5_SHUTDOWN_GUARD_EXPIREDS);
>
>   	reply = sctp_make_abort(asoc, NULL, 0);
>   	if (!reply)
> @@ -5696,8 +5726,8 @@ sctp_disposition_t sctp_sf_t5_timer_expire(const struct sctp_endpoint *ep,
>   	sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
>   			SCTP_PERR(SCTP_ERROR_NO_ERROR));
>
> -	SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
> -	SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
> +	SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS);
> +	SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB);
>
>   	return SCTP_DISPOSITION_DELETE_TCB;
>   nomem:
> @@ -5716,9 +5746,10 @@ sctp_disposition_t sctp_sf_autoclose_timer_expire(
>   	void *arg,
>   	sctp_cmd_seq_t *commands)
>   {
> +	struct net *net = sock_net(asoc->base.sk);
>   	int disposition;
>
> -	SCTP_INC_STATS(SCTP_MIB_AUTOCLOSE_EXPIREDS);
> +	SCTP_INC_STATS(net, SCTP_MIB_AUTOCLOSE_EXPIREDS);
>
>   	/* From 9.2 Shutdown of an Association
>   	 * Upon receipt of the SHUTDOWN primitive from its upper
> @@ -5976,7 +6007,7 @@ static void sctp_send_stale_cookie_err(const struct sctp_endpoint *ep,
>   			sctp_packet_append_chunk(packet, err_chunk);
>   			sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT,
>   					SCTP_PACKET(packet));
> -			SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
> +			SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS);
>   		} else
>   			sctp_chunk_free (err_chunk);
>   	}
> @@ -5996,6 +6027,7 @@ static int sctp_eat_data(const struct sctp_association *asoc,
>   	__u32 tsn;
>   	struct sctp_tsnmap *map = (struct sctp_tsnmap *)&asoc->peer.tsn_map;
>   	struct sock *sk = asoc->base.sk;
> +	struct net *net;
>   	u16 ssn;
>   	u16 sid;
>   	u8 ordered = 0;
> @@ -6112,6 +6144,7 @@ static int sctp_eat_data(const struct sctp_association *asoc,
>   	 * No User Data:  This error cause is returned to the originator of a
>   	 * DATA chunk if a received DATA chunk has no user data.
>   	 */
> +	net = sock_net(sk);
>   	if (unlikely(0 == datalen)) {
>   		err = sctp_make_abort_no_data(asoc, chunk, tsn);
>   		if (err) {
> @@ -6126,8 +6159,8 @@ static int sctp_eat_data(const struct sctp_association *asoc,
>   				SCTP_ERROR(ECONNABORTED));
>   		sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
>   				SCTP_PERR(SCTP_ERROR_NO_DATA));
> -		SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
> -		SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
> +		SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS);
> +		SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB);
>   		return SCTP_IERROR_NO_DATA;
>   	}
>
> @@ -6137,9 +6170,9 @@ static int sctp_eat_data(const struct sctp_association *asoc,
>   	 * if we renege and the chunk arrives again.
>   	 */
>   	if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED)
> -		SCTP_INC_STATS(SCTP_MIB_INUNORDERCHUNKS);
> +		SCTP_INC_STATS(net, SCTP_MIB_INUNORDERCHUNKS);
>   	else {
> -		SCTP_INC_STATS(SCTP_MIB_INORDERCHUNKS);
> +		SCTP_INC_STATS(net, SCTP_MIB_INORDERCHUNKS);
>   		ordered = 1;
>   	}
>
> diff --git a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c
> index f5a6a4f..360d869 100644
> --- a/net/sctp/ulpqueue.c
> +++ b/net/sctp/ulpqueue.c
> @@ -326,7 +326,9 @@ static void sctp_ulpq_store_reasm(struct sctp_ulpq *ulpq,
>    * payload was fragmented on the way and ip had to reassemble them.
>    * We add the rest of skb's to the first skb's fraglist.
>    */
> -static struct sctp_ulpevent *sctp_make_reassembled_event(struct sk_buff_head *queue, struct sk_buff *f_frag, struct sk_buff *l_frag)
> +static struct sctp_ulpevent *sctp_make_reassembled_event(struct net *net,
> +	struct sk_buff_head *queue, struct sk_buff *f_frag,
> +	struct sk_buff *l_frag)
>   {
>   	struct sk_buff *pos;
>   	struct sk_buff *new = NULL;
> @@ -394,7 +396,7 @@ static struct sctp_ulpevent *sctp_make_reassembled_event(struct sk_buff_head *qu
>   	}
>
>   	event = sctp_skb2event(f_frag);
> -	SCTP_INC_STATS(SCTP_MIB_REASMUSRMSGS);
> +	SCTP_INC_STATS(net, SCTP_MIB_REASMUSRMSGS);
>
>   	return event;
>   }
> @@ -493,7 +495,8 @@ static struct sctp_ulpevent *sctp_ulpq_retrieve_reassembled(struct sctp_ulpq *ul
>   		cevent = sctp_skb2event(pd_first);
>   		pd_point = sctp_sk(asoc->base.sk)->pd_point;
>   		if (pd_point && pd_point <= pd_len) {
> -			retval = sctp_make_reassembled_event(&ulpq->reasm,
> +			retval = sctp_make_reassembled_event(sock_net(asoc->base.sk),
> +							     &ulpq->reasm,
>   							     pd_first,
>   							     pd_last);
>   			if (retval)
> @@ -503,7 +506,8 @@ static struct sctp_ulpevent *sctp_ulpq_retrieve_reassembled(struct sctp_ulpq *ul
>   done:
>   	return retval;
>   found:
> -	retval = sctp_make_reassembled_event(&ulpq->reasm, first_frag, pos);
> +	retval = sctp_make_reassembled_event(sock_net(ulpq->asoc->base.sk),
> +					     &ulpq->reasm, first_frag, pos);
>   	if (retval)
>   		retval->msg_flags |= MSG_EOR;
>   	goto done;
> @@ -563,7 +567,8 @@ static struct sctp_ulpevent *sctp_ulpq_retrieve_partial(struct sctp_ulpq *ulpq)
>   	 * further.
>   	 */
>   done:
> -	retval = sctp_make_reassembled_event(&ulpq->reasm, first_frag, last_frag);
> +	retval = sctp_make_reassembled_event(sock_net(ulpq->asoc->base.sk),
> +					&ulpq->reasm, first_frag, last_frag);
>   	if (retval && is_last)
>   		retval->msg_flags |= MSG_EOR;
>
> @@ -655,7 +660,8 @@ static struct sctp_ulpevent *sctp_ulpq_retrieve_first(struct sctp_ulpq *ulpq)
>   	 * further.
>   	 */
>   done:
> -	retval = sctp_make_reassembled_event(&ulpq->reasm, first_frag, last_frag);
> +	retval = sctp_make_reassembled_event(sock_net(ulpq->asoc->base.sk),
> +					&ulpq->reasm, first_frag, last_frag);
>   	return retval;
>   }
>
>

^ permalink raw reply

* Re: [PATCH net-next 1/7] sctp: Add infrastructure for per net sysctls
From: Vlad Yasevich @ 2012-08-15  3:20 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: David Miller, linux-sctp, netdev, linux-kernel, Jan Ariyasu,
	Jan Ariyasu, Neil Horman, Thomas Graf, Xi Wang
In-Reply-To: <87d332d39s.fsf_-_@xmission.com>

On 08/07/2012 01:23 PM, Eric W. Biederman wrote:
>
> Start with an empty sctp_net_table that will be populated as the various
> tunable sysctls are made per net.
>
> Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>

Acked-by: Vlad Yasevich <vyasevich@gmail.com>

> ---
>   include/net/netns/sctp.h |    6 +++++-
>   include/net/sctp/sctp.h  |    4 ++++
>   net/sctp/protocol.c      |    7 +++++++
>   net/sctp/sysctl.c        |   21 +++++++++++++++++++++
>   4 files changed, 37 insertions(+), 1 deletions(-)
>
> diff --git a/include/net/netns/sctp.h b/include/net/netns/sctp.h
> index 06ccddf..9576b60 100644
> --- a/include/net/netns/sctp.h
> +++ b/include/net/netns/sctp.h
> @@ -4,6 +4,7 @@
>   struct sock;
>   struct proc_dir_entry;
>   struct sctp_mib;
> +struct ctl_table_header;
>
>   struct netns_sctp {
>   	DEFINE_SNMP_STAT(struct sctp_mib, sctp_statistics);
> @@ -11,7 +12,9 @@ struct netns_sctp {
>   #ifdef CONFIG_PROC_FS
>   	struct proc_dir_entry *proc_net_sctp;
>   #endif
> -
> +#ifdef CONFIG_SYSCTL
> +	struct ctl_table_header *sysctl_header;
> +#endif
>   	/* This is the global socket data structure used for responding to
>   	 * the Out-of-the-blue (OOTB) packets.  A control sock will be created
>   	 * for this socket at the initialization time.
> @@ -32,6 +35,7 @@ struct netns_sctp {
>
>   	/* Lock that protects the local_addr_list writers */
>   	spinlock_t local_addr_lock;
> +
>   };
>
>   #endif /* __NETNS_SCTP_H__ */
> diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
> index b0e6fe5..15037e7 100644
> --- a/include/net/sctp/sctp.h
> +++ b/include/net/sctp/sctp.h
> @@ -375,9 +375,13 @@ static inline void sctp_dbg_objcnt_exit(void) { return; }
>   #if defined CONFIG_SYSCTL
>   void sctp_sysctl_register(void);
>   void sctp_sysctl_unregister(void);
> +int sctp_sysctl_net_register(struct net *net);
> +void sctp_sysctl_net_unregister(struct net *net);
>   #else
>   static inline void sctp_sysctl_register(void) { return; }
>   static inline void sctp_sysctl_unregister(void) { return; }
> +static inline int sctp_sysctl_net_register(struct net *net) { return 0; }
> +static inline void sctp_sysctl_net_unregister(struct net *net) { return; }
>   #endif
>
>   /* Size of Supported Address Parameter for 'x' address types. */
> diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
> index 69bdc72..de25d9c 100644
> --- a/net/sctp/protocol.c
> +++ b/net/sctp/protocol.c
> @@ -1169,6 +1169,10 @@ static int sctp_net_init(struct net *net)
>   {
>   	int status;
>
> +	status = sctp_sysctl_net_register(net);
> +	if (status)
> +		goto err_sysctl_register;
> +
>   	/* Allocate and initialise sctp mibs.  */
>   	status = init_sctp_mibs(net);
>   	if (status)
> @@ -1205,6 +1209,8 @@ err_ctl_sock_init:
>   err_init_proc:
>   	cleanup_sctp_mibs(net);
>   err_init_mibs:
> +	sctp_sysctl_net_unregister(net);
> +err_sysctl_register:
>   	return status;
>   }
>
> @@ -1219,6 +1225,7 @@ static void sctp_net_exit(struct net *net)
>
>   	sctp_proc_exit(net);
>   	cleanup_sctp_mibs(net);
> +	sctp_sysctl_net_unregister(net);
>   }
>
>   static struct pernet_operations sctp_net_ops = {
> diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c
> index 2b2bfe9..7528d59 100644
> --- a/net/sctp/sysctl.c
> +++ b/net/sctp/sysctl.c
> @@ -284,6 +284,27 @@ static ctl_table sctp_table[] = {
>   	{ /* sentinel */ }
>   };
>
> +static ctl_table sctp_net_table[] = {
> +	{ /* sentinel */ }	
> +};
> +
> +int sctp_sysctl_net_register(struct net *net)
> +{
> +	struct ctl_table *table;
> +
> +	table = kmemdup(sctp_net_table, sizeof(sctp_net_table), GFP_KERNEL);
> +	if (!table)
> +		return -ENOMEM;
> +
> +	net->sctp.sysctl_header = register_net_sysctl(net, "net/sctp", table);
> +	return 0;
> +}
> +
> +void sctp_sysctl_net_unregister(struct net *net)
> +{
> +	unregister_net_sysctl_table(net->sctp.sysctl_header);
> +}
> +
>   static struct ctl_table_header * sctp_sysctl_header;
>
>   /* Sysctl registration.  */
>

^ permalink raw reply


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