diff options
author | Willem de Bruijn <willemb@google.com> | 2013-05-20 00:02:32 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-05-20 16:48:04 -0400 |
commit | 99bbc70741903c063b3ccad90a3e06fc55df9245 (patch) | |
tree | a3377d2461242bf1134464ce3fe6d69f82c907c2 /include/linux/netdevice.h | |
parent | 4a5bddf7ea6b6c5916eccbc2fa1950555073ff48 (diff) |
rps: selective flow shedding during softnet overflow
A cpu executing the network receive path sheds packets when its input
queue grows to netdev_max_backlog. A single high rate flow (such as a
spoofed source DoS) can exceed a single cpu processing rate and will
degrade throughput of other flows hashed onto the same cpu.
This patch adds a more fine grained hashtable. If the netdev backlog
is above a threshold, IRQ cpus track the ratio of total traffic of
each flow (using 4096 buckets, configurable). The ratio is measured
by counting the number of packets per flow over the last 256 packets
from the source cpu. Any flow that occupies a large fraction of this
(set at 50%) will see packet drop while above the threshold.
Tested:
Setup is a muli-threaded UDP echo server with network rx IRQ on cpu0,
kernel receive (RPS) on cpu0 and application threads on cpus 2--7
each handling 20k req/s. Throughput halves when hit with a 400 kpps
antagonist storm. With this patch applied, antagonist overload is
dropped and the server processes its complete load.
The patch is effective when kernel receive processing is the
bottleneck. The above RPS scenario is a extreme, but the same is
reached with RFS and sufficient kernel processing (iptables, packet
socket tap, ..).
Signed-off-by: Willem de Bruijn <willemb@google.com>
Acked-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include/linux/netdevice.h')
-rw-r--r-- | include/linux/netdevice.h | 17 |
1 files changed, 17 insertions, 0 deletions
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index a94a5a0ab122..7dd535d4b41e 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h | |||
@@ -1778,6 +1778,19 @@ static inline int unregister_gifconf(unsigned int family) | |||
1778 | return register_gifconf(family, NULL); | 1778 | return register_gifconf(family, NULL); |
1779 | } | 1779 | } |
1780 | 1780 | ||
1781 | #ifdef CONFIG_NET_FLOW_LIMIT | ||
1782 | #define FLOW_LIMIT_HISTORY (1 << 8) /* must be ^2 */ | ||
1783 | struct sd_flow_limit { | ||
1784 | u64 count; | ||
1785 | unsigned int num_buckets; | ||
1786 | unsigned int history_head; | ||
1787 | u16 history[FLOW_LIMIT_HISTORY]; | ||
1788 | u8 buckets[]; | ||
1789 | }; | ||
1790 | |||
1791 | extern int netdev_flow_limit_table_len; | ||
1792 | #endif /* CONFIG_NET_FLOW_LIMIT */ | ||
1793 | |||
1781 | /* | 1794 | /* |
1782 | * Incoming packets are placed on per-cpu queues | 1795 | * Incoming packets are placed on per-cpu queues |
1783 | */ | 1796 | */ |
@@ -1807,6 +1820,10 @@ struct softnet_data { | |||
1807 | unsigned int dropped; | 1820 | unsigned int dropped; |
1808 | struct sk_buff_head input_pkt_queue; | 1821 | struct sk_buff_head input_pkt_queue; |
1809 | struct napi_struct backlog; | 1822 | struct napi_struct backlog; |
1823 | |||
1824 | #ifdef CONFIG_NET_FLOW_LIMIT | ||
1825 | struct sd_flow_limit *flow_limit; | ||
1826 | #endif | ||
1810 | }; | 1827 | }; |
1811 | 1828 | ||
1812 | static inline void input_queue_head_incr(struct softnet_data *sd) | 1829 | static inline void input_queue_head_incr(struct softnet_data *sd) |