diff options
author | Vlad Yasevich <vladislav.yasevich@hp.com> | 2006-10-09 21:34:04 -0700 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-10-11 23:59:44 -0700 |
commit | 331c4ee7faa4ee1e1404c872a139784753100498 (patch) | |
tree | c5bbae21fd17f7948ab2506cad4d6f2ecba911ee /include | |
parent | 6e8c751e07b34d73069e9333f67fbe5ffe31ec3a (diff) | |
download | linux-3.10-331c4ee7faa4ee1e1404c872a139784753100498.tar.gz linux-3.10-331c4ee7faa4ee1e1404c872a139784753100498.tar.bz2 linux-3.10-331c4ee7faa4ee1e1404c872a139784753100498.zip |
[SCTP]: Fix receive buffer accounting.
When doing receiver buffer accounting, we always used skb->truesize.
This is problematic when processing bundled DATA chunks because for
every DATA chunk that could be small part of one large skb, we would
charge the size of the entire skb. The new approach is to store the
size of the DATA chunk we are accounting for in the sctp_ulpevent
structure and use that stored value for accounting.
Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com>
Signed-off-by: Sridhar Samudrala <sri@us.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include')
-rw-r--r-- | include/net/sctp/sctp.h | 14 | ||||
-rw-r--r-- | include/net/sctp/ulpevent.h | 1 |
2 files changed, 15 insertions, 0 deletions
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h index ee68a312407..764e3af5be9 100644 --- a/include/net/sctp/sctp.h +++ b/include/net/sctp/sctp.h @@ -139,6 +139,7 @@ int sctp_inet_listen(struct socket *sock, int backlog); void sctp_write_space(struct sock *sk); unsigned int sctp_poll(struct file *file, struct socket *sock, poll_table *wait); +void sctp_sock_rfree(struct sk_buff *skb); /* * sctp/primitive.c @@ -444,6 +445,19 @@ static inline struct list_head *sctp_list_dequeue(struct list_head *list) return result; } +/* SCTP version of skb_set_owner_r. We need this one because + * of the way we have to do receive buffer accounting on bundled + * chunks. + */ +static inline void sctp_skb_set_owner_r(struct sk_buff *skb, struct sock *sk) +{ + struct sctp_ulpevent *event = sctp_skb2event(skb); + + skb->sk = sk; + skb->destructor = sctp_sock_rfree; + atomic_add(event->rmem_len, &sk->sk_rmem_alloc); +} + /* Tests if the list has one and only one entry. */ static inline int sctp_list_single_entry(struct list_head *head) { diff --git a/include/net/sctp/ulpevent.h b/include/net/sctp/ulpevent.h index 6c40cfc4832..1a4ddc1ec7d 100644 --- a/include/net/sctp/ulpevent.h +++ b/include/net/sctp/ulpevent.h @@ -63,6 +63,7 @@ struct sctp_ulpevent { __u32 cumtsn; int msg_flags; int iif; + unsigned int rmem_len; }; /* Retrieve the skb this event sits inside of. */ |