[PATCH 08/13] SCTP: Make associations use per-namespace configuration.
From: Jan Ariyasu <hidden>
Date: 2012-08-04 21:33:55
Also in:
linux-sctp, lkml
Subsystem:
networking [general], sctp protocol, the rest · Maintainers:
"David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Marcelo Ricardo Leitner, Xin Long, Linus Torvalds
These changes make associations namespace aware, including association ID lists and their associated locks. Signed-off-by: Jan Ariyasu <redacted> --- 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