Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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>

authored by

Neil Horman and committed by
David S. Miller
4eb701df 594ccc14

+54 -6
+1
include/linux/sysctl.h
··· 643 643 NET_SCTP_MAX_BURST = 12, 644 644 NET_SCTP_ADDIP_ENABLE = 13, 645 645 NET_SCTP_PRSCTP_ENABLE = 14, 646 + NET_SCTP_SNDBUF_POLICY = 15, 646 647 }; 647 648 648 649 /* /proc/sys/net/bridge */
+10 -1
include/net/sctp/structs.h
··· 154 154 int max_retrans_path; 155 155 int max_retrans_init; 156 156 157 + /* 158 + * Policy for preforming sctp/socket accounting 159 + * 0 - do socket level accounting, all assocs share sk_sndbuf 160 + * 1 - do sctp accounting, each asoc may use sk_sndbuf bytes 161 + */ 162 + int sndbuf_policy; 163 + 157 164 /* HB.interval - 30 seconds */ 158 165 int hb_interval; 159 166 ··· 214 207 #define sctp_valid_cookie_life (sctp_globals.valid_cookie_life) 215 208 #define sctp_cookie_preserve_enable (sctp_globals.cookie_preserve_enable) 216 209 #define sctp_max_retrans_association (sctp_globals.max_retrans_association) 210 + #define sctp_sndbuf_policy (sctp_globals.sndbuf_policy) 217 211 #define sctp_max_retrans_path (sctp_globals.max_retrans_path) 218 212 #define sctp_max_retrans_init (sctp_globals.max_retrans_init) 219 213 #define sctp_hb_interval (sctp_globals.hb_interval) ··· 1220 1212 /* Default timeouts. */ 1221 1213 int timeouts[SCTP_NUM_TIMEOUT_TYPES]; 1222 1214 1223 - /* Various thresholds. */ 1215 + /* sendbuf acct. policy. */ 1216 + __u32 sndbuf_policy; 1224 1217 1225 1218 /* Name for debugging output... */ 1226 1219 char *debug_name;
+1
net/sctp/endpointola.c
··· 125 125 sp->autoclose * HZ; 126 126 127 127 /* Use SCTP specific send buffer space queues. */ 128 + ep->sndbuf_policy = sctp_sndbuf_policy; 128 129 sk->sk_write_space = sctp_write_space; 129 130 sock_set_flag(sk, SOCK_USE_WRITE_QUEUE); 130 131
+3
net/sctp/protocol.c
··· 1043 1043 sctp_max_retrans_path = 5; 1044 1044 sctp_max_retrans_init = 8; 1045 1045 1046 + /* Sendbuffer growth - do per-socket accounting */ 1047 + sctp_sndbuf_policy = 0; 1048 + 1046 1049 /* HB.interval - 30 seconds */ 1047 1050 sctp_hb_interval = 30 * HZ; 1048 1051
+31 -5
net/sctp/socket.c
··· 115 115 struct sock *sk = asoc->base.sk; 116 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 126 if (amt < 0) 120 127 amt = 0; 128 + 121 129 return amt; 122 130 } 123 131 ··· 146 138 /* The sndbuf space is tracked per association. */ 147 139 sctp_association_hold(asoc); 148 140 141 + skb_set_owner_w(chunk->skb, sk); 142 + 149 143 chunk->skb->destructor = sctp_wfree; 150 144 /* Save the chunk pointer in skb for sctp_wfree to use later. */ 151 145 *((struct sctp_chunk **)(chunk->skb->cb)) = chunk; 152 146 153 - asoc->sndbuf_used += SCTP_DATA_SNDSIZE(chunk); 154 - sk->sk_wmem_queued += SCTP_DATA_SNDSIZE(chunk); 147 + asoc->sndbuf_used += SCTP_DATA_SNDSIZE(chunk) + 148 + sizeof(struct sk_buff) + 149 + sizeof(struct sctp_chunk); 150 + 151 + sk->sk_wmem_queued += SCTP_DATA_SNDSIZE(chunk) + 152 + sizeof(struct sk_buff) + 153 + sizeof(struct sctp_chunk); 154 + 155 + atomic_add(sizeof(struct sctp_chunk), &sk->sk_wmem_alloc); 155 156 } 156 157 157 158 /* Verify that this is a valid address. */ ··· 4439 4422 chunk = *((struct sctp_chunk **)(skb->cb)); 4440 4423 asoc = chunk->asoc; 4441 4424 sk = asoc->base.sk; 4442 - asoc->sndbuf_used -= SCTP_DATA_SNDSIZE(chunk); 4443 - sk->sk_wmem_queued -= SCTP_DATA_SNDSIZE(chunk); 4425 + asoc->sndbuf_used -= SCTP_DATA_SNDSIZE(chunk) + 4426 + sizeof(struct sk_buff) + 4427 + sizeof(struct sctp_chunk); 4428 + 4429 + sk->sk_wmem_queued -= SCTP_DATA_SNDSIZE(chunk) + 4430 + sizeof(struct sk_buff) + 4431 + sizeof(struct sctp_chunk); 4432 + 4433 + atomic_sub(sizeof(struct sctp_chunk), &sk->sk_wmem_alloc); 4434 + 4435 + sock_wfree(skb); 4444 4436 __sctp_write_space(asoc); 4445 4437 4446 4438 sctp_association_put(asoc);
+8
net/sctp/sysctl.c
··· 110 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 121 .ctl_name = NET_SCTP_PATH_MAX_RETRANS, 114 122 .procname = "path_max_retrans", 115 123 .data = &sctp_max_retrans_path,