Skip to content

Commit

Permalink
net: add a limit parameter to sk_add_backlog()
Browse files Browse the repository at this point in the history
sk_add_backlog() & sk_rcvqueues_full() hard coded sk_rcvbuf as the
memory limit. We need to make this limit a parameter for TCP use.

No functional change expected in this patch, all callers still using the
old sk_rcvbuf limit.

Signed-off-by: Eric Dumazet <[email protected]>
Cc: Neal Cardwell <[email protected]>
Cc: Tom Herbert <[email protected]>
Cc: Maciej Żenczykowski <[email protected]>
Cc: Yuchung Cheng <[email protected]>
Cc: Ilpo Järvinen <[email protected]>
Cc: Rick Jones <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
Eric Dumazet authored and davem330 committed Apr 24, 2012
1 parent b989850 commit f545a38
Show file tree
Hide file tree
Showing 10 changed files with 21 additions and 19 deletions.
10 changes: 6 additions & 4 deletions include/net/sock.h
Original file line number Diff line number Diff line change
Expand Up @@ -709,17 +709,19 @@ static inline void __sk_add_backlog(struct sock *sk, struct sk_buff *skb)
* Do not take into account this skb truesize,
* to allow even a single big packet to come.
*/
static inline bool sk_rcvqueues_full(const struct sock *sk, const struct sk_buff *skb)
static inline bool sk_rcvqueues_full(const struct sock *sk, const struct sk_buff *skb,
unsigned int limit)
{
unsigned int qsize = sk->sk_backlog.len + atomic_read(&sk->sk_rmem_alloc);

return qsize > sk->sk_rcvbuf;
return qsize > limit;
}

/* The per-socket spinlock must be held here. */
static inline __must_check int sk_add_backlog(struct sock *sk, struct sk_buff *skb)
static inline __must_check int sk_add_backlog(struct sock *sk, struct sk_buff *skb,
unsigned int limit)
{
if (sk_rcvqueues_full(sk, skb))
if (sk_rcvqueues_full(sk, skb, limit))
return -ENOBUFS;

__sk_add_backlog(sk, skb);
Expand Down
4 changes: 2 additions & 2 deletions net/core/sock.c
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,7 @@ int sk_receive_skb(struct sock *sk, struct sk_buff *skb, const int nested)

skb->dev = NULL;

if (sk_rcvqueues_full(sk, skb)) {
if (sk_rcvqueues_full(sk, skb, sk->sk_rcvbuf)) {
atomic_inc(&sk->sk_drops);
goto discard_and_relse;
}
Expand All @@ -406,7 +406,7 @@ int sk_receive_skb(struct sock *sk, struct sk_buff *skb, const int nested)
rc = sk_backlog_rcv(sk, skb);

mutex_release(&sk->sk_lock.dep_map, 1, _RET_IP_);
} else if (sk_add_backlog(sk, skb)) {
} else if (sk_add_backlog(sk, skb, sk->sk_rcvbuf)) {
bh_unlock_sock(sk);
atomic_inc(&sk->sk_drops);
goto discard_and_relse;
Expand Down
2 changes: 1 addition & 1 deletion net/ipv4/tcp_ipv4.c
Original file line number Diff line number Diff line change
Expand Up @@ -1752,7 +1752,7 @@ int tcp_v4_rcv(struct sk_buff *skb)
if (!tcp_prequeue(sk, skb))
ret = tcp_v4_do_rcv(sk, skb);
}
} else if (unlikely(sk_add_backlog(sk, skb))) {
} else if (unlikely(sk_add_backlog(sk, skb, sk->sk_rcvbuf))) {
bh_unlock_sock(sk);
NET_INC_STATS_BH(net, LINUX_MIB_TCPBACKLOGDROP);
goto discard_and_relse;
Expand Down
4 changes: 2 additions & 2 deletions net/ipv4/udp.c
Original file line number Diff line number Diff line change
Expand Up @@ -1479,7 +1479,7 @@ int udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
goto drop;


if (sk_rcvqueues_full(sk, skb))
if (sk_rcvqueues_full(sk, skb, sk->sk_rcvbuf))
goto drop;

rc = 0;
Expand All @@ -1488,7 +1488,7 @@ int udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
bh_lock_sock(sk);
if (!sock_owned_by_user(sk))
rc = __udp_queue_rcv_skb(sk, skb);
else if (sk_add_backlog(sk, skb)) {
else if (sk_add_backlog(sk, skb, sk->sk_rcvbuf)) {
bh_unlock_sock(sk);
goto drop;
}
Expand Down
2 changes: 1 addition & 1 deletion net/ipv6/tcp_ipv6.c
Original file line number Diff line number Diff line change
Expand Up @@ -1654,7 +1654,7 @@ static int tcp_v6_rcv(struct sk_buff *skb)
if (!tcp_prequeue(sk, skb))
ret = tcp_v6_do_rcv(sk, skb);
}
} else if (unlikely(sk_add_backlog(sk, skb))) {
} else if (unlikely(sk_add_backlog(sk, skb, sk->sk_rcvbuf))) {
bh_unlock_sock(sk);
NET_INC_STATS_BH(net, LINUX_MIB_TCPBACKLOGDROP);
goto discard_and_relse;
Expand Down
8 changes: 4 additions & 4 deletions net/ipv6/udp.c
Original file line number Diff line number Diff line change
Expand Up @@ -611,14 +611,14 @@ static void flush_stack(struct sock **stack, unsigned int count,

sk = stack[i];
if (skb1) {
if (sk_rcvqueues_full(sk, skb1)) {
if (sk_rcvqueues_full(sk, skb1, sk->sk_rcvbuf)) {
kfree_skb(skb1);
goto drop;
}
bh_lock_sock(sk);
if (!sock_owned_by_user(sk))
udpv6_queue_rcv_skb(sk, skb1);
else if (sk_add_backlog(sk, skb1)) {
else if (sk_add_backlog(sk, skb1, sk->sk_rcvbuf)) {
kfree_skb(skb1);
bh_unlock_sock(sk);
goto drop;
Expand Down Expand Up @@ -790,14 +790,14 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable,

/* deliver */

if (sk_rcvqueues_full(sk, skb)) {
if (sk_rcvqueues_full(sk, skb, sk->sk_rcvbuf)) {
sock_put(sk);
goto discard;
}
bh_lock_sock(sk);
if (!sock_owned_by_user(sk))
udpv6_queue_rcv_skb(sk, skb);
else if (sk_add_backlog(sk, skb)) {
else if (sk_add_backlog(sk, skb, sk->sk_rcvbuf)) {
atomic_inc(&sk->sk_drops);
bh_unlock_sock(sk);
sock_put(sk);
Expand Down
2 changes: 1 addition & 1 deletion net/llc/llc_conn.c
Original file line number Diff line number Diff line change
Expand Up @@ -828,7 +828,7 @@ void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb)
else {
dprintk("%s: adding to backlog...\n", __func__);
llc_set_backlog_type(skb, LLC_PACKET);
if (sk_add_backlog(sk, skb))
if (sk_add_backlog(sk, skb, sk->sk_rcvbuf))
goto drop_unlock;
}
out:
Expand Down
4 changes: 2 additions & 2 deletions net/sctp/input.c
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ int sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb)
sctp_bh_lock_sock(sk);

if (sock_owned_by_user(sk)) {
if (sk_add_backlog(sk, skb))
if (sk_add_backlog(sk, skb, sk->sk_rcvbuf))
sctp_chunk_free(chunk);
else
backloged = 1;
Expand Down Expand Up @@ -376,7 +376,7 @@ static int sctp_add_backlog(struct sock *sk, struct sk_buff *skb)
struct sctp_ep_common *rcvr = chunk->rcvr;
int ret;

ret = sk_add_backlog(sk, skb);
ret = sk_add_backlog(sk, skb, sk->sk_rcvbuf);
if (!ret) {
/* Hold the assoc/ep while hanging on the backlog queue.
* This way, we know structures we need will not disappear
Expand Down
2 changes: 1 addition & 1 deletion net/tipc/socket.c
Original file line number Diff line number Diff line change
Expand Up @@ -1330,7 +1330,7 @@ static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf)
if (!sock_owned_by_user(sk)) {
res = filter_rcv(sk, buf);
} else {
if (sk_add_backlog(sk, buf))
if (sk_add_backlog(sk, buf, sk->sk_rcvbuf))
res = TIPC_ERR_OVERLOAD;
else
res = TIPC_OK;
Expand Down
2 changes: 1 addition & 1 deletion net/x25/x25_dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ static int x25_receive_data(struct sk_buff *skb, struct x25_neigh *nb)
if (!sock_owned_by_user(sk)) {
queued = x25_process_rx_frame(sk, skb);
} else {
queued = !sk_add_backlog(sk, skb);
queued = !sk_add_backlog(sk, skb, sk->sk_rcvbuf);
}
bh_unlock_sock(sk);
sock_put(sk);
Expand Down

0 comments on commit f545a38

Please sign in to comment.