diff options
| author | Neil Horman <nhorman@redhat.com> | 2005-04-28 15:02:04 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2005-04-28 15:02:04 -0400 |
| commit | 4eb701dfc618491c9b97377df6e61de36dfc39ce (patch) | |
| tree | b49f31ebecda19d071d3ae3777be2a6a8c9e5c34 /net/sctp | |
| parent | 594ccc14dfe4d61b476491758425a1c2ca4ec71b (diff) | |
[SCTP] Fix SCTP sendbuffer accouting.
- Include chunk and skb sizes in sendbuffer accounting.
- 2 policies are supported. 0: per socket accouting, 1: per association
accounting
DaveM: I've made the default per-socket.
Signed-off-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Sridhar Samudrala <sri@us.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sctp')
| -rw-r--r-- | net/sctp/endpointola.c | 1 | ||||
| -rw-r--r-- | net/sctp/protocol.c | 3 | ||||
| -rw-r--r-- | net/sctp/socket.c | 36 | ||||
| -rw-r--r-- | net/sctp/sysctl.c | 8 |
4 files changed, 43 insertions, 5 deletions
diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c index 544b75077dbd..334f61773e6d 100644 --- a/net/sctp/endpointola.c +++ b/net/sctp/endpointola.c | |||
| @@ -125,6 +125,7 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep, | |||
| 125 | sp->autoclose * HZ; | 125 | sp->autoclose * HZ; |
| 126 | 126 | ||
| 127 | /* Use SCTP specific send buffer space queues. */ | 127 | /* Use SCTP specific send buffer space queues. */ |
| 128 | ep->sndbuf_policy = sctp_sndbuf_policy; | ||
| 128 | sk->sk_write_space = sctp_write_space; | 129 | sk->sk_write_space = sctp_write_space; |
| 129 | sock_set_flag(sk, SOCK_USE_WRITE_QUEUE); | 130 | sock_set_flag(sk, SOCK_USE_WRITE_QUEUE); |
| 130 | 131 | ||
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 23c85a236c41..2e1f9c3556f5 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c | |||
| @@ -1043,6 +1043,9 @@ SCTP_STATIC __init int sctp_init(void) | |||
| 1043 | sctp_max_retrans_path = 5; | 1043 | sctp_max_retrans_path = 5; |
| 1044 | sctp_max_retrans_init = 8; | 1044 | sctp_max_retrans_init = 8; |
| 1045 | 1045 | ||
| 1046 | /* Sendbuffer growth - do per-socket accounting */ | ||
| 1047 | sctp_sndbuf_policy = 0; | ||
| 1048 | |||
| 1046 | /* HB.interval - 30 seconds */ | 1049 | /* HB.interval - 30 seconds */ |
| 1047 | sctp_hb_interval = 30 * HZ; | 1050 | sctp_hb_interval = 30 * HZ; |
| 1048 | 1051 | ||
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 32f2249411fa..0b338eca6dc0 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
| @@ -115,9 +115,17 @@ static inline int sctp_wspace(struct sctp_association *asoc) | |||
| 115 | struct sock *sk = asoc->base.sk; | 115 | struct sock *sk = asoc->base.sk; |
| 116 | int amt = 0; | 116 | int amt = 0; |
| 117 | 117 | ||
| 118 | amt = sk->sk_sndbuf - asoc->sndbuf_used; | 118 | if (asoc->ep->sndbuf_policy) { |
| 119 | /* make sure that no association uses more than sk_sndbuf */ | ||
| 120 | amt = sk->sk_sndbuf - asoc->sndbuf_used; | ||
| 121 | } else { | ||
| 122 | /* do socket level accounting */ | ||
| 123 | amt = sk->sk_sndbuf - atomic_read(&sk->sk_wmem_alloc); | ||
| 124 | } | ||
| 125 | |||
| 119 | if (amt < 0) | 126 | if (amt < 0) |
| 120 | amt = 0; | 127 | amt = 0; |
| 128 | |||
| 121 | return amt; | 129 | return amt; |
| 122 | } | 130 | } |
| 123 | 131 | ||
| @@ -138,12 +146,21 @@ static inline void sctp_set_owner_w(struct sctp_chunk *chunk) | |||
| 138 | /* The sndbuf space is tracked per association. */ | 146 | /* The sndbuf space is tracked per association. */ |
| 139 | sctp_association_hold(asoc); | 147 | sctp_association_hold(asoc); |
| 140 | 148 | ||
| 149 | skb_set_owner_w(chunk->skb, sk); | ||
| 150 | |||
| 141 | chunk->skb->destructor = sctp_wfree; | 151 | chunk->skb->destructor = sctp_wfree; |
| 142 | /* Save the chunk pointer in skb for sctp_wfree to use later. */ | 152 | /* Save the chunk pointer in skb for sctp_wfree to use later. */ |
| 143 | *((struct sctp_chunk **)(chunk->skb->cb)) = chunk; | 153 | *((struct sctp_chunk **)(chunk->skb->cb)) = chunk; |
| 144 | 154 | ||
| 145 | asoc->sndbuf_used += SCTP_DATA_SNDSIZE(chunk); | 155 | asoc->sndbuf_used += SCTP_DATA_SNDSIZE(chunk) + |
| 146 | sk->sk_wmem_queued += SCTP_DATA_SNDSIZE(chunk); | 156 | sizeof(struct sk_buff) + |
| 157 | sizeof(struct sctp_chunk); | ||
| 158 | |||
| 159 | sk->sk_wmem_queued += SCTP_DATA_SNDSIZE(chunk) + | ||
| 160 | sizeof(struct sk_buff) + | ||
| 161 | sizeof(struct sctp_chunk); | ||
| 162 | |||
| 163 | atomic_add(sizeof(struct sctp_chunk), &sk->sk_wmem_alloc); | ||
| 147 | } | 164 | } |
| 148 | 165 | ||
| 149 | /* Verify that this is a valid address. */ | 166 | /* Verify that this is a valid address. */ |
| @@ -4422,8 +4439,17 @@ static void sctp_wfree(struct sk_buff *skb) | |||
| 4422 | chunk = *((struct sctp_chunk **)(skb->cb)); | 4439 | chunk = *((struct sctp_chunk **)(skb->cb)); |
| 4423 | asoc = chunk->asoc; | 4440 | asoc = chunk->asoc; |
| 4424 | sk = asoc->base.sk; | 4441 | sk = asoc->base.sk; |
| 4425 | asoc->sndbuf_used -= SCTP_DATA_SNDSIZE(chunk); | 4442 | asoc->sndbuf_used -= SCTP_DATA_SNDSIZE(chunk) + |
| 4426 | sk->sk_wmem_queued -= SCTP_DATA_SNDSIZE(chunk); | 4443 | sizeof(struct sk_buff) + |
| 4444 | sizeof(struct sctp_chunk); | ||
| 4445 | |||
| 4446 | sk->sk_wmem_queued -= SCTP_DATA_SNDSIZE(chunk) + | ||
| 4447 | sizeof(struct sk_buff) + | ||
| 4448 | sizeof(struct sctp_chunk); | ||
| 4449 | |||
| 4450 | atomic_sub(sizeof(struct sctp_chunk), &sk->sk_wmem_alloc); | ||
| 4451 | |||
| 4452 | sock_wfree(skb); | ||
| 4427 | __sctp_write_space(asoc); | 4453 | __sctp_write_space(asoc); |
| 4428 | 4454 | ||
| 4429 | sctp_association_put(asoc); | 4455 | sctp_association_put(asoc); |
diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c index 89fa20c73a5c..7fc31849312b 100644 --- a/net/sctp/sysctl.c +++ b/net/sctp/sysctl.c | |||
| @@ -110,6 +110,14 @@ static ctl_table sctp_table[] = { | |||
| 110 | .proc_handler = &proc_dointvec | 110 | .proc_handler = &proc_dointvec |
| 111 | }, | 111 | }, |
| 112 | { | 112 | { |
| 113 | .ctl_name = NET_SCTP_SNDBUF_POLICY, | ||
| 114 | .procname = "sndbuf_policy", | ||
| 115 | .data = &sctp_sndbuf_policy, | ||
| 116 | .maxlen = sizeof(int), | ||
| 117 | .mode = 0644, | ||
| 118 | .proc_handler = &proc_dointvec | ||
| 119 | }, | ||
| 120 | { | ||
| 113 | .ctl_name = NET_SCTP_PATH_MAX_RETRANS, | 121 | .ctl_name = NET_SCTP_PATH_MAX_RETRANS, |
| 114 | .procname = "path_max_retrans", | 122 | .procname = "path_max_retrans", |
| 115 | .data = &sctp_max_retrans_path, | 123 | .data = &sctp_max_retrans_path, |
