Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH 1/6] hash: Introduce ptr_hash_mix routine
From: David Miller @ 2012-08-06 20:44 UTC (permalink / raw)
  To: xemul; +Cc: eric.dumazet, ebiederm, netdev
In-Reply-To: <501FD11B.6000006@parallels.com>

From: Pavel Emelyanov <xemul@parallels.com>
Date: Mon, 06 Aug 2012 18:13:47 +0400

> @@ -67,4 +68,13 @@ static inline unsigned long hash_ptr(const void *ptr, unsigned int bits)
>  {
>  	return hash_long((unsigned long)ptr, bits);
>  }
> +
> +static inline u32 ptr_hash_mix(const void *ptr)
> +{
> +#if BITS_PER_LONG == 32
> +	return (u32)(unsigned long)ptr;
> +#else
> +	return (u32)((unsigned long)ptr >> L1_CACHE_SHIFT);
> +#endif
> +}
>  #endif /* _LINUX_HASH_H */

This doesn't make much sense to me.

If the whole 32-bits of the pointer is useful for entropy on 32-bit
why isn't the whole 64-bits useful on 64-bit?

I would, instead, expect something like:

	ptr ^ (ptr >> 32)

for the 64-bit case.

Also, that L1_CACHE_SHIFT is something callers can decide to do.

Only they know the size of their structure, the alignment used to
allocate such objects, and thus what bits are "less relevant" and
therefore profitable to elide from the bottom of the value.

^ permalink raw reply

* Re: [PATCH RFC] net: tcp: GRO should be ECN friendly
From: David Miller @ 2012-08-06 20:41 UTC (permalink / raw)
  To: herbert; +Cc: eric.dumazet, netdev
In-Reply-To: <20120806090150.GB18425@gondor.apana.org.au>

From: Herbert Xu <herbert@gondor.apana.org.au>
Date: Mon, 6 Aug 2012 17:01:50 +0800

> On Mon, Aug 06, 2012 at 10:34:50AM +0200, Eric Dumazet wrote:
>> From: Eric Dumazet <edumazet@google.com>
>> 
>> While doing TCP ECN tests, I discovered GRO was reordering packets if it
>> receives one packet with CE set, while previous packets in same NAPI run
>> have ECT(0) for the same flow :
>> 
>> 09:25:25.857620 IP (tos 0x2,ECT(0), ttl 64, id 27893, offset 0, flags
>> [DF], proto TCP (6), length 4396)
>>     172.30.42.19.54550 > 172.30.42.13.44139: Flags [.], seq
>> 233801:238145, ack 1, win 115, options [nop,nop,TS val 3397779 ecr
>> 1990627], length 4344
>> 
>> 09:25:25.857626 IP (tos 0x3,CE, ttl 64, id 27892, offset 0, flags [DF],
>> proto TCP (6), length 1500)
>>     172.30.42.19.54550 > 172.30.42.13.44139: Flags [.], seq
>> 232353:233801, ack 1, win 115, options [nop,nop,TS val 3397779 ecr
>> 1990627], length 1448
>> 
>> 09:25:25.857638 IP (tos 0x0, ttl 64, id 34581, offset 0, flags [DF],
>> proto TCP (6), length 64)
>>     172.30.42.13.44139 > 172.30.42.19.54550: Flags [.], cksum 0xac8f
>> (incorrect -> 0xca69), ack 232353, win 1271, options [nop,nop,TS val
>> 1990627 ecr 3397779,nop,nop,sack 1 {233801:238145}], length 0
>> 
>> We have two problems here :
>> 
>> 1) GRO reorders packets
>> 
>>   If NIC gave packet1, then packet2, which happen to be from "different
>> flows"  GRO feeds stack with packet2, then packet1. I have yet to
>> understand how to solve this problem.
>> 
>> 2) GRO is not ECN friendly
>> 
>> Delivering packets out of order makes TCP stack not as fast as it could
>> be.
>> 
>> In this patch I suggest we make the tos test not part of the 'same_flow'
>> determination, but part of the 'should flush' logic
>> 
>> Signed-off-by: Eric Dumazet <edumazet@google.com>
> 
> Acked-by: Herbert Xu <herbert@gondor.apana.org.au>
> 
> Good catch, thanks Eric!

Applied to net-next, thanks Eric.

^ permalink raw reply

* Re: [PATCH net-next] net: reorganize IP MIB values
From: David Miller @ 2012-08-06 20:41 UTC (permalink / raw)
  To: eric.dumazet; +Cc: netdev
In-Reply-To: <1344148439.9299.1570.camel@edumazet-glaptop>

From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Sun, 05 Aug 2012 08:33:59 +0200

> From: Eric Dumazet <edumazet@google.com>
> 
> Reduce IP latencies by placing hot MIB IP fields in a single cache line.
> 
> Signed-off-by: Eric Dumazet <edumazet@google.com>

Applied.

^ permalink raw reply

* Re: [PATCH] net: avoid reloads in SNMP_UPD_PO_STATS
From: David Miller @ 2012-08-06 20:40 UTC (permalink / raw)
  To: eric.dumazet; +Cc: netdev
In-Reply-To: <1344147973.9299.1563.camel@edumazet-glaptop>

From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Sun, 05 Aug 2012 08:26:13 +0200

> From: Eric Dumazet <edumazet@google.com>
> 
> Avoid two instructions to reload dev->nd_net->mib.ip_statistics pointer,
> unsing a temp variable, in ip_rcv(), ip_output() paths for example.
> 
> Signed-off-by: Eric Dumazet <edumazet@google.com>

Applied to net-next

^ permalink raw reply

* Re: [PATCH] net: ipv6: fix TCP early demux
From: David Miller @ 2012-08-06 20:33 UTC (permalink / raw)
  To: eric.dumazet; +Cc: netdev
In-Reply-To: <1344265773.26674.27.camel@edumazet-glaptop>

From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Mon, 06 Aug 2012 17:09:33 +0200

> From: Eric Dumazet <edumazet@google.com>
> 
> IPv6 needs a cookie in dst_check() call.
> 
> We need to add rx_dst_cookie and provide a family independent
> sk_rx_dst_set(sk, skb) method to properly support IPv6 TCP early demux.
> 
> Signed-off-by: Eric Dumazet <edumazet@google.com>

Applied, thanks.

> ---
> Note: we could group sk_rx_dst/rx_dst_ifindex/rx_dst_cookie
> in same cache line (in sk)

I don't think this is necessary, for now.

^ permalink raw reply

* Re: [PATCH net] net_sched: act: Delete estimator in error path.
From: David Miller @ 2012-08-06 20:32 UTC (permalink / raw)
  To: shimoda.hiroaki; +Cc: netdev
In-Reply-To: <20120807004548.6f9e7b6d1e566d7eead73497@gmail.com>

From: Hiroaki SHIMODA <shimoda.hiroaki@gmail.com>
Date: Tue, 7 Aug 2012 00:45:48 +0900

> Some action modules free struct tcf_common in their error path
> while estimator is still active. This results in est_timer()
> dereference freed memory.
> Add gen_kill_estimator() in ipt, pedit and simple action.
> 
> Signed-off-by: Hiroaki SHIMODA <shimoda.hiroaki@gmail.com>

Applied.

^ permalink raw reply

* Re: [PATCH] ip: fix error handling in ip_finish_output2()
From: David Miller @ 2012-08-06 20:32 UTC (permalink / raw)
  To: segoon; +Cc: kuznet, jmorris, yoshfuji, kaber, netdev, linux-kernel
In-Reply-To: <20120806135529.GA30699@albatros>

From: Vasily Kulikov <segoon@openwall.com>
Date: Mon, 6 Aug 2012 17:55:29 +0400

> __neigh_create() returns either a pointer to struct neighbour or PTR_ERR().
> But the caller expects it to return either a pointer or NULL.  Replace
> the NULL check with IS_ERR() check.
> 
> The bug was introduced in a263b3093641fb1ec377582c90986a7fd0625184.
> 
> Signed-off-by: Vasily Kulikov <segoon@openwall.com>

Applied.

Please provide the proper commit log header line text when referencing
another commit, otherwise in trees where the SHA1 IDs are different,
nobody will be able to figure out what you are trying to refer to.

Thanks.

^ permalink raw reply

* Re: [PATCH] llc: free the right skb
From: David Miller @ 2012-08-06 20:31 UTC (permalink / raw)
  To: sdumitru; +Cc: netdev, acme
In-Reply-To: <1344256558-22649-1-git-send-email-sdumitru@ixiacom.com>

From: Sorin Dumitru <sdumitru@ixiacom.com>
Date: Mon, 6 Aug 2012 15:35:58 +0300

> We are freeing skb instead of nskb, resulting in a double
> free on skb and a leak from nskb.
> 
> Signed-off-by: Sorin Dumitru <sdumitru@ixiacom.com>

Applied.

^ permalink raw reply

* Re: [patch 1/1] ixp4xx_eth: fix ptp_ixp46x build failure
From: David Miller @ 2012-08-06 20:31 UTC (permalink / raw)
  To: arnaud.patard; +Cc: netdev, khc
In-Reply-To: <20120805203042.509148064@rtp-net.org>

From: Arnaud Patard (Rtp) <arnaud.patard@rtp-net.org>
Date: Sun, 05 Aug 2012 22:30:11 +0200

> When building with ixp4xx_eth and ptp_ixp46x as module, one is getting the
> following error:
> 
> ERROR: "ixp46x_phc_index" [drivers/ptp/ptp_ixp46x.ko] undefined!
> 
> This has been introduced by commit 509a7c25729feab353502e1b544c614772a1d49a.
> 
> Signed-off-by: Arnaud Patard <arnaud.patard@rtp-net.org>

Applied.

^ permalink raw reply

* Re: Subject: [PATCH] sched: add missing group change to qfq_change_class
From: David Miller @ 2012-08-06 20:31 UTC (permalink / raw)
  To: paolo.valente; +Cc: shemminger, jhs, fchecconi, rizzo, netdev, linux-kernel
In-Reply-To: <501ECD61.5090209@unimore.it>

From: Paolo Valente <paolo.valente@unimore.it>
Date: Sun, 05 Aug 2012 21:45:37 +0200

> To speed up operations, QFQ internally divides classes into
> groups. Which group a class belongs to depends on the ratio between
> the maximum packet length and the weight of the class. Unfortunately
> the function qfq_change_class lacks the steps for changing the group
> of a class when the ratio max_pkt_len/weight of the class changes.
> 
> For example, when the last of the following three commands is
> executed, the group of class 1:1 is not correctly changed:
> 
> tc disc add dev XXX root handle 1: qfq
> tc class add dev XXX parent 1: qfq classid 1:1 weight 1
> tc class change dev XXX parent 1: classid 1:1 qfq weight 4
> 
> Not changing the group of a class does not affect the long-term
> bandwidth guaranteed to the class, as the latter is independent of the
> maximum packet length, and correctly changes (only) if the weight of
> the class changes. In contrast, if the group of the class is not
> updated, the class is still guaranteed the short-term bandwidth and
> packet delay related to its old group, and not the guarantees that it
> should receive according to its new weight and/or maximum packet
> length. This may also break service guarantees for other classes.
> This patch adds the missing operations.
> 
> Signed-off-by: Paolo Valente <paolo.valente@unimore.it>

Please provide clean Subject lines with patch submissions.

Also, this patch doesn't apply cleanly at all.  Email the patch
to yourself, and verify that you can in fact apply it to the
current networking GIT tree just as I will have to.

^ permalink raw reply

* Re: [PATCH 6/6] drivers/atm/iphase.c: fix error return code
From: David Miller @ 2012-08-06 20:30 UTC (permalink / raw)
  To: Julia.Lawall
  Cc: chas, kernel-janitors, linux-atm-general, netdev, linux-kernel,
	julia
In-Reply-To: <1344160356-387-7-git-send-email-Julia.Lawall@lip6.fr>

From: Julia Lawall <Julia.Lawall@lip6.fr>
Date: Sun,  5 Aug 2012 11:52:36 +0200

> From: Julia Lawall <julia@diku.dk>
> 
> 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@diku.dk>

Applied.

^ permalink raw reply

* Re: [PATCH] tcp_output: fix sparse warning for tcp_wfree
From: David Miller @ 2012-08-06 20:30 UTC (permalink / raw)
  To: silviupopescu1990; +Cc: netdev, kuznet, jmorris, yoshfuji, kaber, linux-kernel
In-Reply-To: <1344108689-17896-1-git-send-email-silviupopescu1990@gmail.com>

From: Silviu-Mihai Popescu <silviupopescu1990@gmail.com>
Date: Sat,  4 Aug 2012 22:31:29 +0300

> Fix sparse warning:
> 	* symbol 'tcp_wfree' was not declared. Should it be static?
> 
> Signed-off-by: Silviu-Mihai Popescu <silviupopescu1990@gmail.com>

Applied.

^ permalink raw reply

* Re: [PATCH 6/6] drivers/net/phy/mdio-mux-gpio.c: drop devm_kfree of devm_kzalloc'd data
From: David Miller @ 2012-08-06 20:28 UTC (permalink / raw)
  To: Julia.Lawall; +Cc: netdev, kernel-janitors, linux-kernel
In-Reply-To: <1344099049-15212-6-git-send-email-Julia.Lawall@lip6.fr>

From: Julia Lawall <Julia.Lawall@lip6.fr>
Date: Sat,  4 Aug 2012 18:50:49 +0200

> From: Julia Lawall <Julia.Lawall@lip6.fr>
> 
> devm_kfree should not have to be explicitly used.
> 
> The semantic patch that fixes this problem is as follows:
> (http://coccinelle.lip6.fr/)
> 
> // <smpl>
> @@
> expression x,d;
> @@
> 
> x = devm_kzalloc(...)
> ...
> ?-devm_kfree(d,x);
> // </smpl>
> 
> Signed-off-by: Julia Lawall <Julia.Lawall@lip6.fr>

Applied.

^ permalink raw reply

* Re: [PATCH net] batman-adv: select an internet gateway if none was chosen
From: David Miller @ 2012-08-06 20:28 UTC (permalink / raw)
  To: ordex-GaUfNO9RBHfsrOwW+9ziJQ
  Cc: netdev-u79uwXL29TY76Z2rM5mHXA,
	b.a.t.m.a.n-ZwoEplunGu2X36UT3dwllkB+6BGkLq7r,
	lindner_marek-LWAfsSFWpa4
In-Reply-To: <1344089606-9573-1-git-send-email-ordex-GaUfNO9RBHfsrOwW+9ziJQ@public.gmane.org>

From: Antonio Quartulli <ordex-GaUfNO9RBHfsrOwW+9ziJQ@public.gmane.org>
Date: Sat,  4 Aug 2012 16:13:26 +0200

> From: Marek Lindner <lindner_marek-LWAfsSFWpa4@public.gmane.org>
> 
> This is a regression introduced by: 2265c141086474bbae55a5bb3afa1ebb78ccaa7c
> 
> Reported-by: Nicolás Echániz <nicoechaniz-A9NS9UNFlhlrovVCs/uTlw@public.gmane.org>
> Signed-off-by: Marek Lindner <lindner_marek-LWAfsSFWpa4@public.gmane.org>
> Acked-by: Antonio Quartulli <ordex-GaUfNO9RBHfsrOwW+9ziJQ@public.gmane.org>
> Signed-off-by: Antonio Quartulli <ordex-GaUfNO9RBHfsrOwW+9ziJQ@public.gmane.org>

Applied.

Please, when referencing commits in a log message, provide the commit
header text ("LIKE THIS").  Otherwise in trees where the SHA1 IDs are
different, it will ambiguous what commit you are referencing.

^ permalink raw reply

* Re: [PATCH] mISDN: Bugfix for layer2 fixed TEI mode
From: David Miller @ 2012-08-06 20:27 UTC (permalink / raw)
  To: keil; +Cc: netdev, stable, isdn4linux
In-Reply-To: <1344075265-18999-1-git-send-email-keil@b1-systems.de>

From: Karsten Keil <keil@b1-systems.de>
Date: Sat,  4 Aug 2012 12:14:25 +0200

> If a fixed TEI is used, the initial state of the layer 2 statmachine need to be
> 4 (TEI assigned). This was true only for Point to Point connections, but not
> for the other fixed TEIs. It was not found before, because usually only the
> TEI 0 is used as fixed TEI for PtP mode, but if you try X31 packet mode
> connections with SAPI 16, TEI 1, it did fail.
> 
> Signed-off-by: Karsten Keil <keil@b1-systems.de>
> Cc: <stable@vger.kernel.org> # 3.5.x

Applied.

^ permalink raw reply

* Re: [PATCH 00/13] SCTP: Enable netns
From: Vlad Yasevich @ 2012-08-06 20:06 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: Jan Ariyasu, David S. Miller, linux-sctp, netdev, linux-kernel,
	Jan Ariyasu
In-Reply-To: <874noflrzd.fsf@xmission.com>

On 08/06/2012 03:50 PM, Eric W. Biederman wrote:
> Vlad Yasevich <vyasevich@gmail.com> writes:
>
>
>> Hi Eric
>>
>> Associations are looked up by ports, but then verifyed by addresses.
>> Also, associations belong to sockets and simply validating the socket
>> namespace should be sufficient.
>
> True.  Your set of patches isn't quite as likely to malfunction as it
> looked at first glance.  It requires address reuse which happens accross
> namespaces but not too frequently.

Last time I looked at Jan's patches, I though she took care of the 
address re-use issue.  It isn't technically necessary to include 
namespace into the hash mix, but I think it will make chains shorter 
when namespaces are involved.  Might be interesting to look.

>
> As for validating the socket namespace I agree that is the fix and my
> patchset winds up doing it.

Yes, I saw that.

>
>>> The downside with my version is that it does not make all of the sctp
>>> tunables per network namespace the way yours does, but making all of
>>> the tunables per network namespace should be straight forward from
>>> my base.
>>>
>>> My patchset also misses some nice to haves like making the association
>>> id allocation per network namespace.  It is not important for
>>> correctness of the code but it might allow an information leak between
>>> namespaces.
>>
>> Hmm.. this one might be nice to have not from the perspective of leak,
>> but from resource limitation.  Without this, once the id space is
>> global is can be exhausted faster.
>
> It takes a lot of associtations to exhaust the id space, but I have no
> fundamental problems problems with the id allocation being per
> namespace.  I had actually overlooked the local association id when I
> did my patches.   After looking it became clear that making the
> association id global was not necessary so I left it.
>
> The sctp association id is a strange beast.  My personal inclination is
> that the sctp association id really ought to be per sctp socket, but I
> have not looked enough at the sctp userspace API to see if that works in
> practice.  Shrug.
>
> Mostly I am in favor of simple and correct.

Technically association id must be unique within a namespace.  Having 
global id space may be simpler and correct enough as there would be no 
duplication of ids between namespaces.  The only thing of value the 
per/namespace id space provides is that it restored the theoretical 
maximum on sctp associations one can have.

However, this means teaching IDR about namespaces... :)

We can skip it for now.

-vlad
>
> Eric
>

^ permalink raw reply

* Re: [PATCH 00/13] SCTP: Enable netns
From: Eric W. Biederman @ 2012-08-06 19:50 UTC (permalink / raw)
  To: Vlad Yasevich
  Cc: Jan Ariyasu, David S. Miller, linux-sctp, netdev, linux-kernel,
	Jan Ariyasu
In-Reply-To: <50201928.2030802@gmail.com>

Vlad Yasevich <vyasevich@gmail.com> writes:


> Hi Eric
>
> Associations are looked up by ports, but then verifyed by addresses.
> Also, associations belong to sockets and simply validating the socket
> namespace should be sufficient.

True.  Your set of patches isn't quite as likely to malfunction as it
looked at first glance.  It requires address reuse which happens accross
namespaces but not too frequently.

As for validating the socket namespace I agree that is the fix and my
patchset winds up doing it.

>> The downside with my version is that it does not make all of the sctp
>> tunables per network namespace the way yours does, but making all of
>> the tunables per network namespace should be straight forward from
>> my base.
>>
>> My patchset also misses some nice to haves like making the association
>> id allocation per network namespace.  It is not important for
>> correctness of the code but it might allow an information leak between
>> namespaces.
>
> Hmm.. this one might be nice to have not from the perspective of leak,
> but from resource limitation.  Without this, once the id space is
> global is can be exhausted faster.

It takes a lot of associtations to exhaust the id space, but I have no
fundamental problems problems with the id allocation being per
namespace.  I had actually overlooked the local association id when I
did my patches.   After looking it became clear that making the
association id global was not necessary so I left it.

The sctp association id is a strange beast.  My personal inclination is
that the sctp association id really ought to be per sctp socket, but I
have not looked enough at the sctp userspace API to see if that works in
practice.  Shrug.

Mostly I am in favor of simple and correct.

Eric

^ permalink raw reply

* Re: [PATCH 01/13] SCTP: Preparation for namespace enablement
From: Eric W. Biederman @ 2012-08-06 19:31 UTC (permalink / raw)
  To: Jan Ariyasu
  Cc: Vlad Yasevich, David S. Miller, linux-sctp, netdev, linux-kernel,
	Jan Ariyasu
In-Reply-To: <1344115866-6183-1-git-send-email-jan.ariyasu@hp.com>

Jan Ariyasu <jan.ariyasu@gmail.com> writes:

> Introduce data structures and break up module initialization and
> exit into subroutines with common functionality for namespace
> registration.

Jan there is an issue with the way your patch is orgainized.  You create
a structure holding all of the variables before making all of your per
net variables before making the variables per network namespace.

Some of the variables like ep_hashtable, assoc_hashtable, port_hastable
you never make per network namespace.

That make review and reading the code harder than it has to be as it
makes the code hard to understand.

The normal procedure is to move the variables in the same patch that
changes the code.

Eric



> Signed-off-by: Jan Ariyasu <jan.ariyasu@hp.com>
> ---
>  include/net/sctp/structs.h |  150 ++++++++++++++++++++
>  net/sctp/protocol.c        |  332 +++++++++++++++++++++++++++-----------------
>  2 files changed, 353 insertions(+), 129 deletions(-)
>
> diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
> index fc5e600..bc65718 100644
> --- a/include/net/sctp/structs.h
> +++ b/include/net/sctp/structs.h
> @@ -77,6 +77,8 @@ union sctp_addr {
>  
>  /* Forward declarations for data structures. */
>  struct sctp_globals;
> +struct sctp_ns_globals;
> +struct sctp_net_params;
>  struct sctp_endpoint;
>  struct sctp_association;
>  struct sctp_transport;
> @@ -293,6 +295,135 @@ extern struct sctp_globals {
>  #define sctp_rwnd_upd_shift		(sctp_globals.rwnd_update_shift)
>  #define sctp_max_autoclose		(sctp_globals.max_autoclose)
>  
> +struct sctp_net_params {
> +	/* RFC2960 Section 14. Suggested SCTP Protocol Parameter Values
> +	 *
> +	 * The following protocol parameters are RECOMMENDED:
> +	 *
> +	 * RTO.Initial		    - 3	 seconds
> +	 * RTO.Min		    - 1	 second
> +	 * RTO.Max		   -  60 seconds
> +	 * RTO.Alpha		    - 1/8  (3 when converted to right shifts.)
> +	 * RTO.Beta		    - 1/4  (2 when converted to right shifts.)
> +	 */
> +	unsigned int rto_initial;
> +	unsigned int rto_min;
> +	unsigned int rto_max;
> +
> +	/* Note: rto_alpha and rto_beta are really defined as inverse
> +	 * powers of two to facilitate integer operations.
> +	 */
> +	int rto_alpha;
> +	int rto_beta;
> +
> +	/* Max.Burst		    - 4 */
> +	int max_burst;
> +
> +	/* Whether Cookie Preservative is enabled(1) or not(0) */
> +	int cookie_preserve_enable;
> +
> +	/* Valid.Cookie.Life	    - 60  seconds  */
> +	unsigned int valid_cookie_life;
> +
> +	/* Delayed SACK timeout  200ms default*/
> +	unsigned int sack_timeout;
> +
> +	/* HB.interval		    - 30 seconds  */
> +	unsigned int hb_interval;
> +
> +	/* Association.Max.Retrans  - 10 attempts
> +	 * Path.Max.Retrans	    - 5	 attempts (per destination address)
> +	 * Max.Init.Retransmits	    - 8	 attempts
> +	 */
> +	int max_retrans_association;
> +	int max_retrans_path;
> +	int max_retrans_init;
> +
> +	/* Potentially-Failed.Max.Retrans sysctl value
> +	 * taken from:
> +	 * http://tools.ietf.org/html/draft-nishida-tsvwg-sctp-failover-05
> +	 */
> +	int pf_retrans;
> +
> +	/*
> +	 * Policy for preforming sctp/socket accounting
> +	 * 0   - do socket level accounting, all assocs share sk_sndbuf
> +	 * 1   - do sctp accounting, each asoc may use sk_sndbuf bytes
> +	 */
> +	int sndbuf_policy;
> +
> +	/*
> +	 * Policy for preforming sctp/socket accounting
> +	 * 0   - do socket level accounting, all assocs share sk_rcvbuf
> +	 * 1   - do sctp accounting, each asoc may use sk_rcvbuf bytes
> +	 */
> +	int rcvbuf_policy;
> +
> +	/* The following variables are implementation specific.	 */
> +
> +	/* Default initialization values to be applied to new associations. */
> +	__u16 max_instreams;
> +	__u16 max_outstreams;
> +
> +
> +	/* This is the hash of all endpoints. */
> +	int ep_hashsize;
> +	struct sctp_hashbucket *ep_hashtable;
> +
> +	/* This is the hash of all associations. */
> +	int assoc_hashsize;
> +	struct sctp_hashbucket *assoc_hashtable;
> +
> +	/* This is the sctp port control hash.	*/
> +	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;
> +
> +	/* Lock that protects the local_addr_list writers */
> +	spinlock_t addr_list_lock;
> +
> +	/* Address Event Parameters */
> +	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;
> +
> +	/* Flag to indicate if addip is enabled. */
> +	int addip_enable;
> +	int addip_noauth_enable;
> +
> +	/* Flag to indicate if PR-SCTP is enabled. */
> +	int prsctp_enable;
> +
> +	/* Flag to idicate if SCTP-AUTH is enabled */
> +	int auth_enable;
> +
> +	/*
> +	 * Policy to control SCTP IPv4 address scoping
> +	 * 0   - Disable IPv4 address scoping
> +	 * 1   - Enable IPv4 address scoping
> +	 * 2   - Selectively allow only IPv4 private addresses
> +	 * 3   - Selectively allow only IPv4 link local address
> +	 */
> +	int ipv4_scope_policy;
> +
> +	/* Threshold for rwnd update SACKS.  Receive buffer shifted this many
> +	 * bits is an indicator of when to send and window update SACK.
> +	 */
> +	int rwnd_update_shift;
> +
> +	/* Threshold for autoclose timeout, in seconds. */
> +	unsigned long max_autoclose;
> +};
> +
>  /* SCTP Socket type: UDP or TCP style. */
>  typedef enum {
>  	SCTP_SOCKET_UDP = 0,
> @@ -2056,4 +2187,23 @@ typedef struct {
>  	atomic_t *counter;
>  } sctp_dbg_objcnt_entry_t;
>  
> +
> +/* Structure for keeping track of namespace globals */
> +struct sctp_ns_globals {
> +	struct sock *sctp_ctl_sock;
> +	struct sctp_net_params protocol_params;
> +	struct idr assocs_id;
> +	spinlock_t assocs_id_lock;
> +#ifdef CONFIG_SYSCTL
> +	struct ctl_table_header *sctp_sysctl_tbl;
> +#endif
> +#ifdef CONFIG_PROC_FS
> +	struct proc_dir_entry *sctp_proc_dir;
> +	struct proc_dir_entry *sctp_proc_snmp;
> +	struct proc_dir_entry *sctp_proc_assocs;
> +	struct proc_dir_entry *sctp_proc_eps;
> +	struct proc_dir_entry *sctp_proc_remaddr;
> +#endif
> +};
> +
>  #endif /* __sctp_structs_h__ */
> diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
> index 1f89c4e..cafdaac 100644
> --- a/net/sctp/protocol.c
> +++ b/net/sctp/protocol.c
> @@ -105,13 +105,11 @@ struct sock *sctp_get_ctl_sock(void)
>  /* 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);
>  		if (!proc_net_sctp)
> -			goto out_free_percpu;
> +			goto out_nomem;
>  	}
>  
>  	if (sctp_snmp_proc_init())
> @@ -136,14 +134,12 @@ out_snmp_proc_init:
>  		proc_net_sctp = NULL;
>  		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;
> +#else
> +	return 0;
> +#endif /* CONFIG_PROC_FS */
>  }
>  
>  /* Clean up the proc fs entry for the SCTP protocol.
> @@ -163,7 +159,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
> @@ -1194,105 +1189,91 @@ static void sctp_v4_del_protocol(void)
>  	unregister_inetaddr_notifier(&sctp_inetaddr_notifier);
>  }
>  
> -/* Initialize the universe into something sensible.  */
> -SCTP_STATIC __init int sctp_init(void)
> +static void sctp_global_param_init(void)
>  {
> -	int i;
> -	int status = -EINVAL;
> -	unsigned long goal;
> -	unsigned long limit;
> -	int max_share;
> -	int order;
> -
> -	/* SCTP_DEBUG sanity check. */
> -	if (!sctp_sanity_check())
> -		goto out;
> -
> -	/* Allocate bind_bucket and chunk caches. */
> -	status = -ENOBUFS;
> -	sctp_bucket_cachep = kmem_cache_create("sctp_bind_bucket",
> -					       sizeof(struct sctp_bind_bucket),
> -					       0, SLAB_HWCACHE_ALIGN,
> -					       NULL);
> -	if (!sctp_bucket_cachep)
> -		goto out;
> -
> -	sctp_chunk_cachep = kmem_cache_create("sctp_chunk",
> -					       sizeof(struct sctp_chunk),
> -					       0, SLAB_HWCACHE_ALIGN,
> -					       NULL);
> -	if (!sctp_chunk_cachep)
> -		goto err_chunk_cachep;
> -
> -	/* Allocate and initialise sctp mibs.  */
> -	status = init_sctp_mibs();
> -	if (status)
> -		goto err_init_mibs;
> -
> -	/* Initialize proc fs directory.  */
> -	status = sctp_proc_init();
> -	if (status)
> -		goto err_init_proc;
> -
> -	/* Initialize object count debugging.  */
> -	sctp_dbg_objcnt_init();
> -
>  	/*
>  	 * 14. Suggested SCTP Protocol Parameter Values
>  	 */
>  	/* The following protocol parameters are RECOMMENDED:  */
> -	/* RTO.Initial              - 3  seconds */
> -	sctp_rto_initial		= SCTP_RTO_INITIAL;
> -	/* RTO.Min                  - 1  second */
> -	sctp_rto_min	 		= SCTP_RTO_MIN;
> -	/* RTO.Max                 -  60 seconds */
> -	sctp_rto_max 			= SCTP_RTO_MAX;
> -	/* RTO.Alpha                - 1/8 */
> -	sctp_rto_alpha	        	= SCTP_RTO_ALPHA;
> -	/* RTO.Beta                 - 1/4 */
> -	sctp_rto_beta			= SCTP_RTO_BETA;
> -
> -	/* Valid.Cookie.Life        - 60  seconds */
> -	sctp_valid_cookie_life		= SCTP_DEFAULT_COOKIE_LIFE;
> +	/* RTO.Initial			- 3  seconds */
> +	sctp_rto_initial			= SCTP_RTO_INITIAL;
> +	/* RTO.Min			- 1  second */
> +	sctp_rto_min				= SCTP_RTO_MIN;
> +	/* RTO.Max			- 60 seconds */
> +	sctp_rto_max				= SCTP_RTO_MAX;
> +	/* RTO.Alpha			- 1/8 */
> +	sctp_rto_alpha				= SCTP_RTO_ALPHA;
> +	/* RTO.Beta			- 1/4 */
> +	sctp_rto_beta				= SCTP_RTO_BETA;
> +
> +	/* Valid.Cookie.Life		- 60  seconds */
> +	sctp_valid_cookie_life			= SCTP_DEFAULT_COOKIE_LIFE;
>  
>  	/* Whether Cookie Preservative is enabled(1) or not(0) */
> -	sctp_cookie_preserve_enable 	= 1;
> +	sctp_cookie_preserve_enable		= 1;
>  
> -	/* Max.Burst		    - 4 */
> -	sctp_max_burst 			= SCTP_DEFAULT_MAX_BURST;
> +	/* Max.Burst			- 4 */
> +	sctp_max_burst				= SCTP_DEFAULT_MAX_BURST;
>  
> -	/* Association.Max.Retrans  - 10 attempts
> -	 * Path.Max.Retrans         - 5  attempts (per destination address)
> -	 * Max.Init.Retransmits     - 8  attempts
> +	/* Association.Max.Retrans	- 10 attempts
> +	 * Path.Max.Retrans		- 5  attempts (per destination address)
> +	 * Max.Init.Retransmits		- 8  attempts
>  	 */
> -	sctp_max_retrans_association 	= 10;
> -	sctp_max_retrans_path		= 5;
> -	sctp_max_retrans_init		= 8;
> +	sctp_max_retrans_association			= 10;
> +	sctp_max_retrans_path				= 5;
> +	sctp_max_retrans_init			= 8;
>  
> -	/* Sendbuffer growth	    - do per-socket accounting */
> -	sctp_sndbuf_policy		= 0;
> +	/* Sendbuffer growth	- do per-socket accounting */
> +	sctp_sndbuf_policy			= 0;
>  
> -	/* Rcvbuffer growth	    - do per-socket accounting */
> -	sctp_rcvbuf_policy		= 0;
> +	/* Rcvbuffer growth	 - do per-socket accounting */
> +	sctp_rcvbuf_policy			= 0;
>  
> -	/* HB.interval              - 30 seconds */
> +	/* HB.interval		- 30 seconds */
>  	sctp_hb_interval		= SCTP_DEFAULT_TIMEOUT_HEARTBEAT;
>  
>  	/* delayed SACK timeout */
> -	sctp_sack_timeout		= SCTP_DEFAULT_TIMEOUT_SACK;
> +	sctp_sack_timeout			= SCTP_DEFAULT_TIMEOUT_SACK;
>  
>  	/* Implementation specific variables. */
>  
>  	/* Initialize default stream count setup information. */
> -	sctp_max_instreams    		= SCTP_DEFAULT_INSTREAMS;
> -	sctp_max_outstreams   		= SCTP_DEFAULT_OUTSTREAMS;
> +	sctp_max_instreams			= SCTP_DEFAULT_INSTREAMS;
> +	sctp_max_outstreams			= SCTP_DEFAULT_OUTSTREAMS;
>  
>  	/* Initialize maximum autoclose timeout. */
> -	sctp_max_autoclose		= INT_MAX / HZ;
> +	sctp_max_autoclose			= INT_MAX / HZ;
> +
> +	/* Disable ADDIP by default. */
> +	sctp_addip_enable			= 0;
> +	sctp_addip_noauth			= 0;
> +	sctp_default_auto_asconf		= 0;
>  
> -	/* Initialize handle used for association ids. */
> -	idr_init(&sctp_assocs_id);
> +	/* Enable PR-SCTP by default. */
> +	sctp_prsctp_enable			= 1;
> +
> +	/* Disable AUTH by default. */
> +	sctp_auth_enable			= 0;
>  
> +	/* Set SCOPE policy to enabled */
> +	sctp_scope_policy			= SCTP_SCOPE_POLICY_ENABLE;
> +
> +	/* Set the default rwnd update threshold */
> +	sctp_rwnd_upd_shift			= SCTP_DEFAULT_RWND_SHIFT;
> +	return;
> +}
> +
> +static void sctp_memory_globals_init(void)
> +{
> +	unsigned long limit;
> +	int max_share;
> +
> +	/* Set the pressure threshold to be a fraction of global memory that
> +	 * is up to 1/2 at 256 MB, decreasing toward zero with the amount of
> +	 * memory, with a floor of 128 pages.
> +	 * Note this initializes the data in sctpv6_prot too
> +	 * Unabashedly stolen from tcp_init
> +	 */
>  	limit = nr_free_buffer_pages() / 8;
>  	limit = max(limit, 128UL);
>  	sysctl_sctp_mem[0] = limit / 4 * 3;
> @@ -1310,6 +1291,14 @@ SCTP_STATIC __init int sctp_init(void)
>  	sysctl_sctp_wmem[0] = SK_MEM_QUANTUM;
>  	sysctl_sctp_wmem[1] = 16*1024;
>  	sysctl_sctp_wmem[2] = max(64*1024, max_share);
> +}
> +
> +static int sctp_hashtable_globals_init(void)
> +{
> +	unsigned long goal;
> +	int status = -ENOMEM;
> +	int order;
> +	int i;
>  
>  	/* Size and allocate the association hash table.
>  	 * The methodology is similar to that of the tcp hash tables.
> @@ -1325,11 +1314,13 @@ SCTP_STATIC __init int sctp_init(void)
>  	do {
>  		sctp_assoc_hashsize = (1UL << order) * PAGE_SIZE /
>  					sizeof(struct sctp_hashbucket);
> -		if ((sctp_assoc_hashsize > (64 * 1024)) && order > 0)
> -			continue;
> +		if ((sctp_assoc_hashsize > (64 * 1024)) && (order > 0))
> +				continue;
>  		sctp_assoc_hashtable = (struct sctp_hashbucket *)
> -			__get_free_pages(GFP_ATOMIC|__GFP_NOWARN, order);
> -	} while (!sctp_assoc_hashtable && --order > 0);
> +			__get_free_pages(GFP_ATOMIC|__GFP_NOWARN|__GFP_ZERO,
> +				order);
> +	} while (!sctp_assoc_hashtable && (--order > 0));
> +
>  	if (!sctp_assoc_hashtable) {
>  		pr_err("Failed association hash alloc\n");
>  		status = -ENOMEM;
> @@ -1358,11 +1349,12 @@ SCTP_STATIC __init int sctp_init(void)
>  	do {
>  		sctp_port_hashsize = (1UL << order) * PAGE_SIZE /
>  					sizeof(struct sctp_bind_hashbucket);
> -		if ((sctp_port_hashsize > (64 * 1024)) && order > 0)
> +		if ((sctp_port_hashsize > (64 * 1024)) && (order > 0))
>  			continue;
>  		sctp_port_hashtable = (struct sctp_bind_hashbucket *)
>  			__get_free_pages(GFP_ATOMIC|__GFP_NOWARN, order);
> -	} while (!sctp_port_hashtable && --order > 0);
> +	} while (!sctp_port_hashtable && (--order > 0));
> +
>  	if (!sctp_port_hashtable) {
>  		pr_err("Failed bind hash alloc\n");
>  		status = -ENOMEM;
> @@ -1376,25 +1368,111 @@ SCTP_STATIC __init int sctp_init(void)
>  	pr_info("Hash tables configured (established %d bind %d)\n",
>  		sctp_assoc_hashsize, sctp_port_hashsize);
>  
> -	/* Disable ADDIP by default. */
> -	sctp_addip_enable = 0;
> -	sctp_addip_noauth = 0;
> -	sctp_default_auto_asconf = 0;
> +	goto out;
>  
> -	/* Enable PR-SCTP by default. */
> -	sctp_prsctp_enable = 1;
>  
> -	/* Disable AUTH by default. */
> -	sctp_auth_enable = 0;
> +err_bhash_alloc:
> +	kfree(sctp_ep_hashtable);
> +err_ehash_alloc:
> +	free_pages((unsigned long)sctp_assoc_hashtable,
> +		   get_order(sctp_assoc_hashsize *
> +			     sizeof(struct sctp_hashbucket)));
> +err_ahash_alloc:
> +	sctp_proc_exit();
> +out:
> +	return status;
> +}
>  
> -	/* Set SCOPE policy to enabled */
> -	sctp_scope_policy = SCTP_SCOPE_POLICY_ENABLE;
> +static void sctp_hashtable_globals_free(void)
> +{
> +	free_pages((unsigned long)sctp_assoc_hashtable,
> +		   get_order(sctp_assoc_hashsize *
> +			     sizeof(struct sctp_hashbucket)));
>  
> -	/* Set the default rwnd update threshold */
> -	sctp_rwnd_upd_shift		= SCTP_DEFAULT_RWND_SHIFT;
> +	kfree(sctp_ep_hashtable);
> +
> +	free_pages((unsigned long)sctp_port_hashtable,
> +		   get_order(sctp_port_hashsize *
> +			     sizeof(struct sctp_bind_hashbucket)));
> +}
> +
> +static int sctp_kmem_cache_create(void)
> +{
> +	/* Allocate bind_bucket and chunk caches. */
> +	sctp_bucket_cachep = kmem_cache_create("sctp_bind_bucket",
> +					       sizeof(struct sctp_bind_bucket),
> +					       0, SLAB_HWCACHE_ALIGN,
> +					       NULL);
> +
> +	if (!sctp_bucket_cachep) {
> +		pr_err("failed to allocate bucket cache\n");
> +		goto err_bucket_cachep;
> +	}
> +	sctp_chunk_cachep = kmem_cache_create("sctp_chunk",
> +					       sizeof(struct sctp_chunk),
> +					       0, SLAB_HWCACHE_ALIGN,
> +					       NULL);
> +	if (!sctp_chunk_cachep) {
> +		pr_err("failed to allocate chunk cache\n");
> +		goto err_chunk_cachep;
> +	}
> +
> +	return 0;
> +
> +err_chunk_cachep:
> +	kmem_cache_destroy(sctp_bucket_cachep);
> +err_bucket_cachep:
> +	return -ENOBUFS;
> +}
> +
> +static void sctp_kmem_cache_destroy(void)
> +{
> +	/* deallocate bind_bucket and chunk caches. */
> +	kmem_cache_destroy(sctp_chunk_cachep);
> +	kmem_cache_destroy(sctp_bucket_cachep);
> +}
> +
> +/* Initialize the universe into something sensible.  */
> +SCTP_STATIC __init int sctp_init(void)
> +{
> +	int status = -EINVAL;
> +
> +	/* SCTP_DEBUG sanity check. */
> +	if (!sctp_sanity_check())
> +		goto out;
> +
> +	/* Allocate bind_bucket and chunk caches. */
> +	status = sctp_kmem_cache_create();
> +	if (status)
> +		return status;
> +
> +	/* Initialize sockets counter */
> +	if (percpu_counter_init(&sctp_sockets_allocated, 0)) {
> +		status = -ENOMEM;
> +		goto err_percpu_counter_init;
> +	}
> +
> +	/* Allocate and initialise sctp mibs.  */
> +	status = init_sctp_mibs();
> +	if (status)
> +		goto err_init_mibs;
> +
> +	/* Initialize proc fs directory.  */
> +	status = sctp_proc_init();
> +	if (status)
> +		goto err_init_proc;
> +
> +	/* Initialize object count debugging.  */
> +	sctp_dbg_objcnt_init();
> +
> +	/* Initialize global parameters */
> +	sctp_global_param_init();
> +	sctp_memory_globals_init();
> +	sctp_hashtable_globals_init();
>  
>  	sctp_sysctl_register();
>  
> +	/* Register the routines for different a-f handling */
>  	INIT_LIST_HEAD(&sctp_address_families);
>  	sctp_v4_pf_init();
>  	sctp_v6_pf_init();
> @@ -1411,8 +1489,8 @@ SCTP_STATIC __init int sctp_init(void)
>  	sctp_addr_wq_timer.expires = 0;
>  	setup_timer(&sctp_addr_wq_timer, sctp_addr_wq_timeout_handler, 0);
>  
> +	/* Register SCTP protocol */
>  	status = sctp_v4_protosw_init();
> -
>  	if (status)
>  		goto err_protosw_init;
>  
> @@ -1435,9 +1513,20 @@ SCTP_STATIC __init int sctp_init(void)
>  	if (status)
>  		goto err_v6_add_protocol;
>  
> +	/* Set up sysctl parameters. */
> +	sctp_sysctl_register();
> +
> +	/* Allocate and initialise sctp mibs.  */
> +	status = init_sctp_mibs();
> +	if (status)
> +		goto err_mib_init;
> +
>  	status = 0;
> -out:
> -	return status;
> +	goto out;
> +
> +err_mib_init:
> +	sctp_sysctl_unregister();
> +	sctp_v6_del_protocol();
>  err_v6_add_protocol:
>  	sctp_v4_del_protocol();
>  err_add_protocol:
> @@ -1451,25 +1540,17 @@ err_protosw_init:
>  	sctp_v4_pf_exit();
>  	sctp_v6_pf_exit();
>  	sctp_sysctl_unregister();
> -	free_pages((unsigned long)sctp_port_hashtable,
> -		   get_order(sctp_port_hashsize *
> -			     sizeof(struct sctp_bind_hashbucket)));
> -err_bhash_alloc:
> -	kfree(sctp_ep_hashtable);
> -err_ehash_alloc:
> -	free_pages((unsigned long)sctp_assoc_hashtable,
> -		   get_order(sctp_assoc_hashsize *
> -			     sizeof(struct sctp_hashbucket)));
> -err_ahash_alloc:
> +	sctp_hashtable_globals_free();
>  	sctp_dbg_objcnt_exit();
>  	sctp_proc_exit();
>  err_init_proc:
>  	cleanup_sctp_mibs();
>  err_init_mibs:
> -	kmem_cache_destroy(sctp_chunk_cachep);
> -err_chunk_cachep:
> -	kmem_cache_destroy(sctp_bucket_cachep);
> -	goto out;
> +	percpu_counter_destroy(&sctp_sockets_allocated);
> +err_percpu_counter_init:
> +	sctp_kmem_cache_destroy();
> +out:
> +	return status;
>  }
>  
>  /* Exit handler for the SCTP protocol.  */
> @@ -1500,22 +1581,15 @@ SCTP_STATIC __exit void sctp_exit(void)
>  
>  	sctp_sysctl_unregister();
>  
> -	free_pages((unsigned long)sctp_assoc_hashtable,
> -		   get_order(sctp_assoc_hashsize *
> -			     sizeof(struct sctp_hashbucket)));
> -	kfree(sctp_ep_hashtable);
> -	free_pages((unsigned long)sctp_port_hashtable,
> -		   get_order(sctp_port_hashsize *
> -			     sizeof(struct sctp_bind_hashbucket)));
> +	sctp_hashtable_globals_free();
>  
>  	sctp_dbg_objcnt_exit();
>  	sctp_proc_exit();
> +	percpu_counter_destroy(&sctp_sockets_allocated);
>  	cleanup_sctp_mibs();
>  
>  	rcu_barrier(); /* Wait for completion of call_rcu()'s */
> -
> -	kmem_cache_destroy(sctp_chunk_cachep);
> -	kmem_cache_destroy(sctp_bucket_cachep);
> +	sctp_kmem_cache_destroy();
>  }
>  
>  module_init(sctp_init);

^ permalink raw reply

* Re: [PATCH 00/13] SCTP: Enable netns
From: Vlad Yasevich @ 2012-08-06 19:21 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: Jan Ariyasu, David S. Miller, linux-sctp, netdev, linux-kernel,
	Jan Ariyasu
In-Reply-To: <87mx27rig7.fsf@xmission.com>

On 08/06/2012 02:20 PM, Eric W. Biederman wrote:
> Jan Ariyasu <jan.ariyasu@gmail.com> writes:
>
>> The following set of patches enable network-namespaces for the SCTP protocol.
>>
>> The multitude of global parameters are stored in a net_generic
>> structure, and the bulk of the patches enable the protocol to access
>> the parameters on a per-namespace basis.  The first five patches
>> enable netns handling of the protocol, procfs and sysfs.
>
> I am going to do something to muddy the waters here, that I had hoped to
> avoid when I saw your patchset.
>
> A few weeks ago I wanted to play with sctp and also made a network
> namespace enabled version.  I am not deeply attached to my changes,
> however when comparing the differences I realized that your code fails
> to make the lookup of associations per network namespace.
>
> Given that we only have source and destination port to lookup
> assoications by this almost guarantees one network namespace can
> accidentially use the association of another network namespace meerly
> by reusing the same ports.
>

Hi Eric

Associations are looked up by ports, but then verifyed by addresses.
Also, associations belong to sockets and simply validating the socket 
namespace should be sufficient.


> The downside with my version is that it does not make all of the sctp
> tunables per network namespace the way yours does, but making all of
> the tunables per network namespace should be straight forward from
> my base.
>
> My patchset also misses some nice to haves like making the association
> id allocation per network namespace.  It is not important for
> correctness of the code but it might allow an information leak between
> namespaces.

Hmm.. this one might be nice to have not from the perspective of leak, 
but from resource limitation.  Without this, once the id space is global 
is can be exhausted faster.

-vlad

>
> So Jan I am going to send my patchset and hopefully you can rebase your
> changes to make all of the tunables per network namespace on top of
> mine.
>
> Since my patchset is half the size of your I think that is the most
> reasonable way to go.
>
> Eric
>

^ permalink raw reply

* Re: [PATCH] net:appletalk:ddp:fixed coding style issue relating to
From: David Miller @ 2012-08-06 19:03 UTC (permalink / raw)
  To: ahiliation; +Cc: acme, netdev, linux-kernel
In-Reply-To: <1344274298-4711-1-git-send-email-ahiliation@yahoo.co.in>

From: Jeffrin Jose <ahiliation@yahoo.co.in>
Date: Mon,  6 Aug 2012 23:01:38 +0530

> Fixed coding style issue relating to indentation
> in net/appletalk/ddp.c found by checkpatch.pl tool.
> 
> Signed-off-by: Jeffrin Jose <ahiliation@yahoo.co.in>
> ---
>  net/appletalk/ddp.c |   26 +++++++++++++-------------
>  1 file changed, 13 insertions(+), 13 deletions(-)
> 
> diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c
> index 8685296..4023fca 100644
> --- a/net/appletalk/ddp.c
> +++ b/net/appletalk/ddp.c
> @@ -1796,7 +1796,7 @@ static int atalk_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
>  
>  	switch (cmd) {
>  		/* Protocol layer */
> -		case TIOCOUTQ: {
> +	case TIOCOUTQ: {
>  			long amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk);

Only moving the case statement back one TAB and but not any of the
surrounding code is utterly rediculous.

This is why we hate purely coding style fixing patches.

^ permalink raw reply

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


Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.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;
 }
 
-- 
1.7.5.4

^ permalink raw reply related

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


- 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>
---
 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.  */
-- 
1.7.5.4

^ permalink raw reply related

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


- 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>
---
 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 */
-- 
1.7.5.4

^ permalink raw reply related

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


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>
---
 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();
 
-- 
1.7.5.4

^ permalink raw reply related

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


- 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>
---
 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;
 
-- 
1.7.5.4

^ permalink raw reply related


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