[PATCH 08/13] SCTP: Make associations use per-namespace configuration.

From: Jan Ariyasu
Date: Sat Aug 04 2012 - 17:33:50 EST


These changes make associations namespace aware, including
association ID lists and their associated locks.

Signed-off-by: Jan Ariyasu <jan.ariyasu@xxxxxx>
---
include/net/sctp/sctp.h | 3 ---
include/net/sctp/structs.h | 3 ++-
net/sctp/associola.c | 37 ++++++++++++++++++++++++-------------
net/sctp/input.c | 25 +++++++++++++++----------
net/sctp/sm_sideeffect.c | 9 ++++-----
5 files changed, 45 insertions(+), 32 deletions(-)

diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index 8488d5e..363a786 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -601,9 +601,6 @@ extern struct proto sctp_prot;
extern struct proto sctpv6_prot;
void sctp_put_port(struct sock *sk);

-extern struct idr sctp_assocs_id;
-extern spinlock_t sctp_assocs_id_lock;
-
/* Static inline functions. */

/* Convert from an IP version number to an Address Family symbol. */
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 2034d53..72d473b 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -2153,7 +2153,8 @@ struct sctp_transport *sctp_assoc_is_match(struct sctp_association *,
const union sctp_addr *,
const union sctp_addr *);
void sctp_assoc_migrate(struct sctp_association *, struct sock *);
-void sctp_assoc_update(struct sctp_association *old,
+void sctp_assoc_update(struct net *net,
+ struct sctp_association *old,
struct sctp_association *new);

__u32 sctp_association_get_next_tsn(struct sctp_association *);
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index 1bd956b..5b4be66 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -86,6 +86,8 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
int i;
sctp_paramhdr_t *p;
int err;
+ struct sctp_net_params *net_params =
+ sctp_get_params(sock_net(sk));

/* Retrieve the SCTP per socket area. */
sp = sctp_sk((struct sock *)sk);
@@ -124,7 +126,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
* socket values.
*/
asoc->max_retrans = sp->assocparams.sasoc_asocmaxrxt;
- asoc->pf_retrans = sctp_pf_retrans;
+ asoc->pf_retrans = net_params->pf_retrans;

asoc->rto_initial = msecs_to_jiffies(sp->rtoinfo.srto_initial);
asoc->rto_max = msecs_to_jiffies(sp->rtoinfo.srto_max);
@@ -175,7 +177,8 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
asoc->timeouts[SCTP_EVENT_TIMEOUT_HEARTBEAT] = 0;
asoc->timeouts[SCTP_EVENT_TIMEOUT_SACK] = asoc->sackdelay;
asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE] =
- min_t(unsigned long, sp->autoclose, sctp_max_autoclose) * HZ;
+ min_t(unsigned long, sp->autoclose,
+ net_params->max_autoclose) * HZ;

/* Initializes the timers */
for (i = SCTP_EVENT_TIMEOUT_NONE; i < SCTP_NUM_TIMEOUT_TYPES; ++i)
@@ -281,7 +284,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
* and will revert old behavior.
*/
asoc->peer.asconf_capable = 0;
- if (sctp_addip_noauth)
+ if (net_params->addip_noauth_enable)
asoc->peer.asconf_capable = 1;
asoc->asconf_addr_del_pending = NULL;
asoc->src_out_of_asoc_ok = 0;
@@ -468,15 +471,18 @@ void sctp_association_free(struct sctp_association *asoc)
/* Cleanup and free up an association. */
static void sctp_association_destroy(struct sctp_association *asoc)
{
+ struct sctp_ns_globals *ns_globals =
+ sctp_get_ns_globals(sock_net(asoc->base.sk));
+
SCTP_ASSERT(asoc->base.dead, "Assoc is not dead", return);

sctp_endpoint_put(asoc->ep);
sock_put(asoc->base.sk);

if (asoc->assoc_id != 0) {
- spin_lock_bh(&sctp_assocs_id_lock);
- idr_remove(&sctp_assocs_id, asoc->assoc_id);
- spin_unlock_bh(&sctp_assocs_id_lock);
+ spin_lock_bh(&ns_globals->assocs_id_lock);
+ idr_remove(&ns_globals->assocs_id, asoc->assoc_id);
+ spin_unlock_bh(&ns_globals->assocs_id_lock);
}

WARN_ON(atomic_read(&asoc->rmem_alloc));
@@ -1204,7 +1210,8 @@ void sctp_assoc_migrate(struct sctp_association *assoc, struct sock *newsk)
}

/* Update an association (possibly from unexpected COOKIE-ECHO processing). */
-void sctp_assoc_update(struct sctp_association *asoc,
+void sctp_assoc_update(struct net *net,
+ struct sctp_association *asoc,
struct sctp_association *new)
{
struct sctp_transport *trans;
@@ -1416,6 +1423,8 @@ void sctp_assoc_sync_pmtu(struct sock *sk, struct sctp_association *asoc)
/* Should we send a SACK to update our peer? */
static inline int sctp_peer_needs_update(struct sctp_association *asoc)
{
+ struct sctp_net_params *net_params =
+ sctp_get_params(sock_net(asoc->base.sk));
switch (asoc->state) {
case SCTP_STATE_ESTABLISHED:
case SCTP_STATE_SHUTDOWN_PENDING:
@@ -1423,8 +1432,8 @@ static inline int sctp_peer_needs_update(struct sctp_association *asoc)
case SCTP_STATE_SHUTDOWN_SENT:
if ((asoc->rwnd > asoc->a_rwnd) &&
((asoc->rwnd - asoc->a_rwnd) >= max_t(__u32,
- (asoc->base.sk->sk_rcvbuf >> sctp_rwnd_upd_shift),
- asoc->pathmtu)))
+ (asoc->base.sk->sk_rcvbuf >>
+ net_params->rwnd_update_shift), asoc->pathmtu)))
return 1;
break;
default:
@@ -1582,23 +1591,25 @@ int sctp_assoc_set_id(struct sctp_association *asoc, gfp_t gfp)
{
int assoc_id;
int error = 0;
+ struct sctp_ns_globals *ns_globals =
+ sctp_get_ns_globals(sock_net(asoc->base.sk));

/* If the id is already assigned, keep it. */
if (asoc->assoc_id)
return error;
retry:
- if (unlikely(!idr_pre_get(&sctp_assocs_id, gfp)))
+ if (unlikely(!idr_pre_get(&ns_globals->assocs_id, gfp)))
return -ENOMEM;

- spin_lock_bh(&sctp_assocs_id_lock);
- error = idr_get_new_above(&sctp_assocs_id, (void *)asoc,
+ spin_lock_bh(&ns_globals->assocs_id_lock);
+ error = idr_get_new_above(&ns_globals->assocs_id, (void *)asoc,
idr_low, &assoc_id);
if (!error) {
idr_low = assoc_id + 1;
if (idr_low == INT_MAX)
idr_low = 1;
}
- spin_unlock_bh(&sctp_assocs_id_lock);
+ spin_unlock_bh(&ns_globals->assocs_id_lock);
if (error == -EAGAIN)
goto retry;
else if (error)
diff --git a/net/sctp/input.c b/net/sctp/input.c
index 1b92da2..9b53b95 100644
--- a/net/sctp/input.c
+++ b/net/sctp/input.c
@@ -70,7 +70,8 @@ static struct sctp_association *__sctp_rcv_lookup(struct sk_buff *skb,
const union sctp_addr *laddr,
const union sctp_addr *paddr,
struct sctp_transport **transportp);
-static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(const union sctp_addr *laddr);
+static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(struct net *net,
+ const union sctp_addr *laddr);
static struct sctp_association *__sctp_lookup_association(
const union sctp_addr *local,
const union sctp_addr *peer,
@@ -129,6 +130,7 @@ int sctp_rcv(struct sk_buff *skb)
union sctp_addr dest;
int family;
struct sctp_af *af;
+ struct net *net = dev_net(skb->dev);

if (skb->pkt_type!=PACKET_HOST)
goto discard_it;
@@ -181,7 +183,7 @@ int sctp_rcv(struct sk_buff *skb)
asoc = __sctp_rcv_lookup(skb, &src, &dest, &transport);

if (!asoc)
- ep = __sctp_rcv_lookup_endpoint(&dest);
+ ep = __sctp_rcv_lookup_endpoint(net, &dest);

/* Retrieve the common input handling substructure. */
rcvr = asoc ? &asoc->base : &ep->base;
@@ -200,7 +202,7 @@ int sctp_rcv(struct sk_buff *skb)
sctp_endpoint_put(ep);
ep = NULL;
}
- sk = *(sctp_get_ctl_sock(&init_net));
+ sk = *(sctp_get_ctl_sock(net));
ep = sctp_sk(sk)->ep;
sctp_endpoint_hold(ep);
rcvr = &ep->base;
@@ -539,7 +541,7 @@ struct sock *sctp_err_lookup(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(sock_net(sk), LINUX_MIB_LOCKDROPPEDICMPS);

*app = asoc;
*tpp = transport;
@@ -588,7 +590,7 @@ void sctp_v4_err(struct sk_buff *skb, __u32 info)
int err;

if (skb->len < ihlen + 8) {
- ICMP_INC_STATS_BH(&init_net, ICMP_MIB_INERRORS);
+ ICMP_INC_STATS_BH(dev_net(skb->dev), ICMP_MIB_INERRORS);
return;
}

@@ -602,7 +604,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(dev_net(skb->dev), ICMP_MIB_INERRORS);
return;
}
/* Warning: The sock lock is held. Remember to call
@@ -770,7 +772,8 @@ void sctp_unhash_endpoint(struct sctp_endpoint *ep)
}

/* Look up an endpoint. */
-static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(const union sctp_addr *laddr)
+static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(struct net *net,
+ const union sctp_addr *laddr)
{
struct sctp_hashbucket *head;
struct sctp_ep_common *epb;
@@ -787,7 +790,7 @@ static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(const union sctp_addr *l
goto hit;
}

- ep = sctp_sk(*(sctp_get_ctl_sock(&init_net)))->ep;
+ ep = sctp_sk(*(sctp_get_ctl_sock(net)))->ep;

hit:
sctp_endpoint_hold(ep);
@@ -1042,6 +1045,8 @@ static struct sctp_association *__sctp_rcv_walk_lookup(struct sk_buff *skb,
int have_auth = 0;
unsigned int chunk_num = 1;
__u8 *ch_end;
+ struct sctp_net_params *net_params =
+ sctp_get_params(dev_net(skb->dev));

/* Walk through the chunks looking for AUTH or ASCONF chunks
* to help us find the association.
@@ -1074,8 +1079,8 @@ static struct sctp_association *__sctp_rcv_walk_lookup(struct sk_buff *skb,
break;

case SCTP_CID_ASCONF:
- if (have_auth || sctp_addip_noauth)
- asoc = __sctp_rcv_asconf_lookup(ch, laddr,
+ if (have_auth || net_params->addip_noauth_enable)
+ asoc = __sctp_rcv_asconf_lookup(ch, laddr,
sctp_hdr(skb)->source,
transportp);
default:
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
index 2c895fd..35cbbe5 100644
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@ -1058,8 +1058,8 @@ static void sctp_cmd_send_asconf(struct sctp_association *asoc)

/* Hold the chunk until an ASCONF_ACK is received. */
sctp_chunk_hold(asconf);
- if (sctp_primitive_ASCONF(sock_net(asoc->base.sk), asoc,
- asconf))
+ if (sctp_primitive_ASCONF(sock_net(asoc->base.sk),
+ asoc, asconf))
sctp_chunk_free(asconf);
else
asoc->addip_last_asconf = asconf;
@@ -1277,7 +1277,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
break;

case SCTP_CMD_UPDATE_ASSOC:
- sctp_assoc_update(asoc, cmd->obj.ptr);
+ sctp_assoc_update(net, asoc, cmd->obj.ptr);
break;

case SCTP_CMD_PURGE_OUTQUEUE:
@@ -1354,8 +1354,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
* layer which will bail.
*/
error = sctp_cmd_process_init(net, commands, asoc,
- chunk, cmd->obj.ptr,
- gfp);
+ chunk, cmd->obj.ptr, gfp);
break;

case SCTP_CMD_GEN_COOKIE_ECHO:
--
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/