aboutsummaryrefslogtreecommitdiffstats
path: root/net/sctp/socket.c
diff options
context:
space:
mode:
authorNeil Horman <nhorman@tuxdriver.com>2007-08-15 19:07:44 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-10 19:48:09 -0400
commit4d93df0abd50b9c9e2d4561439a1a1d21ec5e68f (patch)
tree47e5bde0c37ed7ce68032ffa9110f252533fc710 /net/sctp/socket.c
parent13c99b248f06e0b71d925f162d8e3b0084886a21 (diff)
[SCTP]: Rewrite of sctp buffer management code
This patch introduces autotuning to the sctp buffer management code similar to the TCP. The buffer space can be grown if the advertised receive window still has room. This might happen if small message sizes are used, which is common in telecom environmens. New tunables are introduced that provide limits to buffer growth and memory pressure is entered if to much buffer spaces is used. Signed-off-by: Neil Horman <nhorman@tuxdriver.com> Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sctp/socket.c')
-rw-r--r--net/sctp/socket.c69
1 files changed, 57 insertions, 12 deletions
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 772fbfb4bfda..b9952425c79a 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -107,23 +107,42 @@ static void sctp_sock_migrate(struct sock *, struct sock *,
107 struct sctp_association *, sctp_socket_type_t); 107 struct sctp_association *, sctp_socket_type_t);
108static char *sctp_hmac_alg = SCTP_COOKIE_HMAC_ALG; 108static char *sctp_hmac_alg = SCTP_COOKIE_HMAC_ALG;
109 109
110extern struct kmem_cache *sctp_bucket_cachep;
111extern int sysctl_sctp_mem[3];
112extern int sysctl_sctp_rmem[3];
113extern int sysctl_sctp_wmem[3];
114
115int sctp_memory_pressure;
116atomic_t sctp_memory_allocated;
117atomic_t sctp_sockets_allocated;
118
119static void sctp_enter_memory_pressure(void)
120{
121 sctp_memory_pressure = 1;
122}
123
124
110/* Get the sndbuf space available at the time on the association. */ 125/* Get the sndbuf space available at the time on the association. */
111static inline int sctp_wspace(struct sctp_association *asoc) 126static inline int sctp_wspace(struct sctp_association *asoc)
112{ 127{
113 struct sock *sk = asoc->base.sk; 128 int amt;
114 int amt = 0;
115 129
116 if (asoc->ep->sndbuf_policy) { 130 if (asoc->ep->sndbuf_policy)
117 /* make sure that no association uses more than sk_sndbuf */ 131 amt = asoc->sndbuf_used;
118 amt = sk->sk_sndbuf - asoc->sndbuf_used; 132 else
133 amt = atomic_read(&asoc->base.sk->sk_wmem_alloc);
134
135 if (amt >= asoc->base.sk->sk_sndbuf) {
136 if (asoc->base.sk->sk_userlocks & SOCK_SNDBUF_LOCK)
137 amt = 0;
138 else {
139 amt = sk_stream_wspace(asoc->base.sk);
140 if (amt < 0)
141 amt = 0;
142 }
119 } else { 143 } else {
120 /* do socket level accounting */ 144 amt = asoc->base.sk->sk_sndbuf - amt;
121 amt = sk->sk_sndbuf - atomic_read(&sk->sk_wmem_alloc);
122 } 145 }
123
124 if (amt < 0)
125 amt = 0;
126
127 return amt; 146 return amt;
128} 147}
129 148
@@ -155,6 +174,7 @@ static inline void sctp_set_owner_w(struct sctp_chunk *chunk)
155 sizeof(struct sctp_chunk); 174 sizeof(struct sctp_chunk);
156 175
157 atomic_add(sizeof(struct sctp_chunk), &sk->sk_wmem_alloc); 176 atomic_add(sizeof(struct sctp_chunk), &sk->sk_wmem_alloc);
177 sk_charge_skb(sk, chunk->skb);
158} 178}
159 179
160/* Verify that this is a valid address. */ 180/* Verify that this is a valid address. */
@@ -3293,6 +3313,7 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk)
3293 sp->hmac = NULL; 3313 sp->hmac = NULL;
3294 3314
3295 SCTP_DBG_OBJCNT_INC(sock); 3315 SCTP_DBG_OBJCNT_INC(sock);
3316 atomic_inc(&sctp_sockets_allocated);
3296 return 0; 3317 return 0;
3297} 3318}
3298 3319
@@ -3306,7 +3327,7 @@ SCTP_STATIC int sctp_destroy_sock(struct sock *sk)
3306 /* Release our hold on the endpoint. */ 3327 /* Release our hold on the endpoint. */
3307 ep = sctp_sk(sk)->ep; 3328 ep = sctp_sk(sk)->ep;
3308 sctp_endpoint_free(ep); 3329 sctp_endpoint_free(ep);
3309 3330 atomic_dec(&sctp_sockets_allocated);
3310 return 0; 3331 return 0;
3311} 3332}
3312 3333
@@ -5720,6 +5741,12 @@ static void sctp_wfree(struct sk_buff *skb)
5720 5741
5721 atomic_sub(sizeof(struct sctp_chunk), &sk->sk_wmem_alloc); 5742 atomic_sub(sizeof(struct sctp_chunk), &sk->sk_wmem_alloc);
5722 5743
5744 /*
5745 * This undoes what is done via sk_charge_skb
5746 */
5747 sk->sk_wmem_queued -= skb->truesize;
5748 sk->sk_forward_alloc += skb->truesize;
5749
5723 sock_wfree(skb); 5750 sock_wfree(skb);
5724 __sctp_write_space(asoc); 5751 __sctp_write_space(asoc);
5725 5752
@@ -5737,6 +5764,11 @@ void sctp_sock_rfree(struct sk_buff *skb)
5737 struct sctp_ulpevent *event = sctp_skb2event(skb); 5764 struct sctp_ulpevent *event = sctp_skb2event(skb);
5738 5765
5739 atomic_sub(event->rmem_len, &sk->sk_rmem_alloc); 5766 atomic_sub(event->rmem_len, &sk->sk_rmem_alloc);
5767
5768 /*
5769 * Mimic the behavior of sk_stream_rfree
5770 */
5771 sk->sk_forward_alloc += event->rmem_len;
5740} 5772}
5741 5773
5742 5774
@@ -6126,6 +6158,7 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
6126 sctp_release_sock(newsk); 6158 sctp_release_sock(newsk);
6127} 6159}
6128 6160
6161
6129/* This proto struct describes the ULP interface for SCTP. */ 6162/* This proto struct describes the ULP interface for SCTP. */
6130struct proto sctp_prot = { 6163struct proto sctp_prot = {
6131 .name = "SCTP", 6164 .name = "SCTP",
@@ -6148,6 +6181,12 @@ struct proto sctp_prot = {
6148 .unhash = sctp_unhash, 6181 .unhash = sctp_unhash,
6149 .get_port = sctp_get_port, 6182 .get_port = sctp_get_port,
6150 .obj_size = sizeof(struct sctp_sock), 6183 .obj_size = sizeof(struct sctp_sock),
6184 .sysctl_mem = sysctl_sctp_mem,
6185 .sysctl_rmem = sysctl_sctp_rmem,
6186 .sysctl_wmem = sysctl_sctp_wmem,
6187 .memory_pressure = &sctp_memory_pressure,
6188 .enter_memory_pressure = sctp_enter_memory_pressure,
6189 .memory_allocated = &sctp_memory_allocated,
6151}; 6190};
6152 6191
6153#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 6192#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
@@ -6172,5 +6211,11 @@ struct proto sctpv6_prot = {
6172 .unhash = sctp_unhash, 6211 .unhash = sctp_unhash,
6173 .get_port = sctp_get_port, 6212 .get_port = sctp_get_port,
6174 .obj_size = sizeof(struct sctp6_sock), 6213 .obj_size = sizeof(struct sctp6_sock),
6214 .sysctl_mem = sysctl_sctp_mem,
6215 .sysctl_rmem = sysctl_sctp_rmem,
6216 .sysctl_wmem = sysctl_sctp_wmem,
6217 .memory_pressure = &sctp_memory_pressure,
6218 .enter_memory_pressure = sctp_enter_memory_pressure,
6219 .memory_allocated = &sctp_memory_allocated,
6175}; 6220};
6176#endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */ 6221#endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */