When 'system_in_emergency' flag is set, drop any incoming packets that belong to non-critical sockets as soon as can determine the destination socket. This is necessary to prevent incoming non-critical packets to consume memory from critical page pool. -----------------------------------------------------------------------------
include/net/sock.h | 14 ++++++++++++++ net/dccp/ipv4.c | 4 ++++ net/ipv4/tcp_ipv4.c | 3 +++ net/ipv4/udp.c | 9 ++++++++- net/ipv6/tcp_ipv6.c | 3 +++ net/sctp/input.c | 3 +++ 6 files changed, 35 insertions(+), 1 deletions(-) diff --git a/include/net/sock.h b/include/net/sock.h index 982b4ec..8de8a8b 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -1391,4 +1391,18 @@ extern int sysctl_optmem_max; extern __u32 sysctl_wmem_default; extern __u32 sysctl_rmem_default; +extern int system_in_emergency; + +static inline int emergency_check(struct sock *sk, struct sk_buff *skb) +{ + if (system_in_emergency && !(sk->sk_allocation & __GFP_CRITICAL)) { + if (net_ratelimit()) + printk("discarding skb:%p len:%d sk:%p protocol:%d\n", + skb, skb->len, sk, sk->sk_protocol); + return 0; + } + + return 1; +} + #endif /* _SOCK_H */ diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index ca03521..405cdf8 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -1130,6 +1130,10 @@ int dccp_v4_rcv(struct sk_buff *skb) goto no_dccp_socket; } + if (!emergency_check(sk, skb)) { + goto discard_and_relse; + } + /* * Step 2: * ... or S.state == TIMEWAIT, diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 4d5021e..acfb9a1 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -1232,6 +1232,9 @@ int tcp_v4_rcv(struct sk_buff *skb) if (!sk) goto no_tcp_socket; + if (!emergency_check(sk, skb)) + goto discard_and_relse; + process: if (sk->sk_state == TCP_TIME_WAIT) goto do_time_wait; diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 2422a5f..f79cbfd 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -1150,7 +1150,14 @@ int udp_rcv(struct sk_buff *skb) sk = udp_v4_lookup(saddr, uh->source, daddr, uh->dest, skb->dev->ifindex); if (sk != NULL) { - int ret = udp_queue_rcv_skb(sk, skb); + int ret; + + if (!emergency_check(sk, skb)) { + sock_put(sk); + goto drop; + } else + ret = udp_queue_rcv_skb(sk, skb); + sock_put(sk); /* a return value > 0 means to resubmit the input, but diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 62c0e5b..d017181 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -1592,6 +1592,9 @@ static int tcp_v6_rcv(struct sk_buff **p if (!sk) goto no_tcp_socket; + if (!emergency_check(sk, skb)) + goto discard_and_relse; + process: if (sk->sk_state == TCP_TIME_WAIT) goto do_time_wait; diff --git a/net/sctp/input.c b/net/sctp/input.c index b24ff2c..553365b 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c @@ -181,6 +181,9 @@ int sctp_rcv(struct sk_buff *skb) rcvr = asoc ? &asoc->base : &ep->base; sk = rcvr->sk; + if (!emergency_check(sk, skb)) + goto discard_it; + /* * If a frame arrives on an interface and the receiving socket is * bound to another interface, via SO_BINDTODEVICE, treat it as OOTB - To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html