[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>
This commit is contained in:
Родитель
594ccc14df
Коммит
4eb701dfc6
|
@ -643,6 +643,7 @@ enum {
|
||||||
NET_SCTP_MAX_BURST = 12,
|
NET_SCTP_MAX_BURST = 12,
|
||||||
NET_SCTP_ADDIP_ENABLE = 13,
|
NET_SCTP_ADDIP_ENABLE = 13,
|
||||||
NET_SCTP_PRSCTP_ENABLE = 14,
|
NET_SCTP_PRSCTP_ENABLE = 14,
|
||||||
|
NET_SCTP_SNDBUF_POLICY = 15,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* /proc/sys/net/bridge */
|
/* /proc/sys/net/bridge */
|
||||||
|
|
|
@ -154,6 +154,13 @@ extern struct sctp_globals {
|
||||||
int max_retrans_path;
|
int max_retrans_path;
|
||||||
int max_retrans_init;
|
int max_retrans_init;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Policy for preforming sctp/socket accounting
|
||||||
|
* 0 - do socket level accounting, all assocs share sk_sndbuf
|
||||||
|
* 1 - do sctp accounting, each asoc may use sk_sndbuf bytes
|
||||||
|
*/
|
||||||
|
int sndbuf_policy;
|
||||||
|
|
||||||
/* HB.interval - 30 seconds */
|
/* HB.interval - 30 seconds */
|
||||||
int hb_interval;
|
int hb_interval;
|
||||||
|
|
||||||
|
@ -207,6 +214,7 @@ extern struct sctp_globals {
|
||||||
#define sctp_valid_cookie_life (sctp_globals.valid_cookie_life)
|
#define sctp_valid_cookie_life (sctp_globals.valid_cookie_life)
|
||||||
#define sctp_cookie_preserve_enable (sctp_globals.cookie_preserve_enable)
|
#define sctp_cookie_preserve_enable (sctp_globals.cookie_preserve_enable)
|
||||||
#define sctp_max_retrans_association (sctp_globals.max_retrans_association)
|
#define sctp_max_retrans_association (sctp_globals.max_retrans_association)
|
||||||
|
#define sctp_sndbuf_policy (sctp_globals.sndbuf_policy)
|
||||||
#define sctp_max_retrans_path (sctp_globals.max_retrans_path)
|
#define sctp_max_retrans_path (sctp_globals.max_retrans_path)
|
||||||
#define sctp_max_retrans_init (sctp_globals.max_retrans_init)
|
#define sctp_max_retrans_init (sctp_globals.max_retrans_init)
|
||||||
#define sctp_hb_interval (sctp_globals.hb_interval)
|
#define sctp_hb_interval (sctp_globals.hb_interval)
|
||||||
|
@ -1212,7 +1220,8 @@ struct sctp_endpoint {
|
||||||
/* Default timeouts. */
|
/* Default timeouts. */
|
||||||
int timeouts[SCTP_NUM_TIMEOUT_TYPES];
|
int timeouts[SCTP_NUM_TIMEOUT_TYPES];
|
||||||
|
|
||||||
/* Various thresholds. */
|
/* sendbuf acct. policy. */
|
||||||
|
__u32 sndbuf_policy;
|
||||||
|
|
||||||
/* Name for debugging output... */
|
/* Name for debugging output... */
|
||||||
char *debug_name;
|
char *debug_name;
|
||||||
|
|
|
@ -125,6 +125,7 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep,
|
||||||
sp->autoclose * HZ;
|
sp->autoclose * HZ;
|
||||||
|
|
||||||
/* Use SCTP specific send buffer space queues. */
|
/* Use SCTP specific send buffer space queues. */
|
||||||
|
ep->sndbuf_policy = sctp_sndbuf_policy;
|
||||||
sk->sk_write_space = sctp_write_space;
|
sk->sk_write_space = sctp_write_space;
|
||||||
sock_set_flag(sk, SOCK_USE_WRITE_QUEUE);
|
sock_set_flag(sk, SOCK_USE_WRITE_QUEUE);
|
||||||
|
|
||||||
|
|
|
@ -1043,6 +1043,9 @@ SCTP_STATIC __init int sctp_init(void)
|
||||||
sctp_max_retrans_path = 5;
|
sctp_max_retrans_path = 5;
|
||||||
sctp_max_retrans_init = 8;
|
sctp_max_retrans_init = 8;
|
||||||
|
|
||||||
|
/* Sendbuffer growth - do per-socket accounting */
|
||||||
|
sctp_sndbuf_policy = 0;
|
||||||
|
|
||||||
/* HB.interval - 30 seconds */
|
/* HB.interval - 30 seconds */
|
||||||
sctp_hb_interval = 30 * HZ;
|
sctp_hb_interval = 30 * HZ;
|
||||||
|
|
||||||
|
|
|
@ -115,9 +115,17 @@ static inline int sctp_wspace(struct sctp_association *asoc)
|
||||||
struct sock *sk = asoc->base.sk;
|
struct sock *sk = asoc->base.sk;
|
||||||
int amt = 0;
|
int amt = 0;
|
||||||
|
|
||||||
|
if (asoc->ep->sndbuf_policy) {
|
||||||
|
/* make sure that no association uses more than sk_sndbuf */
|
||||||
amt = sk->sk_sndbuf - asoc->sndbuf_used;
|
amt = sk->sk_sndbuf - asoc->sndbuf_used;
|
||||||
|
} else {
|
||||||
|
/* do socket level accounting */
|
||||||
|
amt = sk->sk_sndbuf - atomic_read(&sk->sk_wmem_alloc);
|
||||||
|
}
|
||||||
|
|
||||||
if (amt < 0)
|
if (amt < 0)
|
||||||
amt = 0;
|
amt = 0;
|
||||||
|
|
||||||
return amt;
|
return amt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,12 +146,21 @@ static inline void sctp_set_owner_w(struct sctp_chunk *chunk)
|
||||||
/* The sndbuf space is tracked per association. */
|
/* The sndbuf space is tracked per association. */
|
||||||
sctp_association_hold(asoc);
|
sctp_association_hold(asoc);
|
||||||
|
|
||||||
|
skb_set_owner_w(chunk->skb, sk);
|
||||||
|
|
||||||
chunk->skb->destructor = sctp_wfree;
|
chunk->skb->destructor = sctp_wfree;
|
||||||
/* Save the chunk pointer in skb for sctp_wfree to use later. */
|
/* Save the chunk pointer in skb for sctp_wfree to use later. */
|
||||||
*((struct sctp_chunk **)(chunk->skb->cb)) = chunk;
|
*((struct sctp_chunk **)(chunk->skb->cb)) = chunk;
|
||||||
|
|
||||||
asoc->sndbuf_used += SCTP_DATA_SNDSIZE(chunk);
|
asoc->sndbuf_used += SCTP_DATA_SNDSIZE(chunk) +
|
||||||
sk->sk_wmem_queued += SCTP_DATA_SNDSIZE(chunk);
|
sizeof(struct sk_buff) +
|
||||||
|
sizeof(struct sctp_chunk);
|
||||||
|
|
||||||
|
sk->sk_wmem_queued += SCTP_DATA_SNDSIZE(chunk) +
|
||||||
|
sizeof(struct sk_buff) +
|
||||||
|
sizeof(struct sctp_chunk);
|
||||||
|
|
||||||
|
atomic_add(sizeof(struct sctp_chunk), &sk->sk_wmem_alloc);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Verify that this is a valid address. */
|
/* Verify that this is a valid address. */
|
||||||
|
@ -4422,8 +4439,17 @@ static void sctp_wfree(struct sk_buff *skb)
|
||||||
chunk = *((struct sctp_chunk **)(skb->cb));
|
chunk = *((struct sctp_chunk **)(skb->cb));
|
||||||
asoc = chunk->asoc;
|
asoc = chunk->asoc;
|
||||||
sk = asoc->base.sk;
|
sk = asoc->base.sk;
|
||||||
asoc->sndbuf_used -= SCTP_DATA_SNDSIZE(chunk);
|
asoc->sndbuf_used -= SCTP_DATA_SNDSIZE(chunk) +
|
||||||
sk->sk_wmem_queued -= SCTP_DATA_SNDSIZE(chunk);
|
sizeof(struct sk_buff) +
|
||||||
|
sizeof(struct sctp_chunk);
|
||||||
|
|
||||||
|
sk->sk_wmem_queued -= SCTP_DATA_SNDSIZE(chunk) +
|
||||||
|
sizeof(struct sk_buff) +
|
||||||
|
sizeof(struct sctp_chunk);
|
||||||
|
|
||||||
|
atomic_sub(sizeof(struct sctp_chunk), &sk->sk_wmem_alloc);
|
||||||
|
|
||||||
|
sock_wfree(skb);
|
||||||
__sctp_write_space(asoc);
|
__sctp_write_space(asoc);
|
||||||
|
|
||||||
sctp_association_put(asoc);
|
sctp_association_put(asoc);
|
||||||
|
|
|
@ -109,6 +109,14 @@ static ctl_table sctp_table[] = {
|
||||||
.mode = 0644,
|
.mode = 0644,
|
||||||
.proc_handler = &proc_dointvec
|
.proc_handler = &proc_dointvec
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.ctl_name = NET_SCTP_SNDBUF_POLICY,
|
||||||
|
.procname = "sndbuf_policy",
|
||||||
|
.data = &sctp_sndbuf_policy,
|
||||||
|
.maxlen = sizeof(int),
|
||||||
|
.mode = 0644,
|
||||||
|
.proc_handler = &proc_dointvec
|
||||||
|
},
|
||||||
{
|
{
|
||||||
.ctl_name = NET_SCTP_PATH_MAX_RETRANS,
|
.ctl_name = NET_SCTP_PATH_MAX_RETRANS,
|
||||||
.procname = "path_max_retrans",
|
.procname = "path_max_retrans",
|
||||||
|
|
Загрузка…
Ссылка в новой задаче