|
@@ -40,6 +40,21 @@
|
|
|
#include <net/ip_vs.h>
|
|
|
|
|
|
|
|
|
+#ifndef CONFIG_IP_VS_TAB_BITS
|
|
|
+#define CONFIG_IP_VS_TAB_BITS 12
|
|
|
+#endif
|
|
|
+
|
|
|
+/*
|
|
|
+ * Connection hash size. Default is what was selected at compile time.
|
|
|
+*/
|
|
|
+int ip_vs_conn_tab_bits = CONFIG_IP_VS_TAB_BITS;
|
|
|
+module_param_named(conn_tab_bits, ip_vs_conn_tab_bits, int, 0444);
|
|
|
+MODULE_PARM_DESC(conn_tab_bits, "Set connections' hash size");
|
|
|
+
|
|
|
+/* size and mask values */
|
|
|
+int ip_vs_conn_tab_size;
|
|
|
+int ip_vs_conn_tab_mask;
|
|
|
+
|
|
|
/*
|
|
|
* Connection hash table: for input and output packets lookups of IPVS
|
|
|
*/
|
|
@@ -125,11 +140,11 @@ static unsigned int ip_vs_conn_hashkey(int af, unsigned proto,
|
|
|
if (af == AF_INET6)
|
|
|
return jhash_3words(jhash(addr, 16, ip_vs_conn_rnd),
|
|
|
(__force u32)port, proto, ip_vs_conn_rnd)
|
|
|
- & IP_VS_CONN_TAB_MASK;
|
|
|
+ & ip_vs_conn_tab_mask;
|
|
|
#endif
|
|
|
return jhash_3words((__force u32)addr->ip, (__force u32)port, proto,
|
|
|
ip_vs_conn_rnd)
|
|
|
- & IP_VS_CONN_TAB_MASK;
|
|
|
+ & ip_vs_conn_tab_mask;
|
|
|
}
|
|
|
|
|
|
|
|
@@ -760,7 +775,7 @@ static void *ip_vs_conn_array(struct seq_file *seq, loff_t pos)
|
|
|
int idx;
|
|
|
struct ip_vs_conn *cp;
|
|
|
|
|
|
- for(idx = 0; idx < IP_VS_CONN_TAB_SIZE; idx++) {
|
|
|
+ for (idx = 0; idx < ip_vs_conn_tab_size; idx++) {
|
|
|
ct_read_lock_bh(idx);
|
|
|
list_for_each_entry(cp, &ip_vs_conn_tab[idx], c_list) {
|
|
|
if (pos-- == 0) {
|
|
@@ -797,7 +812,7 @@ static void *ip_vs_conn_seq_next(struct seq_file *seq, void *v, loff_t *pos)
|
|
|
idx = l - ip_vs_conn_tab;
|
|
|
ct_read_unlock_bh(idx);
|
|
|
|
|
|
- while (++idx < IP_VS_CONN_TAB_SIZE) {
|
|
|
+ while (++idx < ip_vs_conn_tab_size) {
|
|
|
ct_read_lock_bh(idx);
|
|
|
list_for_each_entry(cp, &ip_vs_conn_tab[idx], c_list) {
|
|
|
seq->private = &ip_vs_conn_tab[idx];
|
|
@@ -976,8 +991,8 @@ void ip_vs_random_dropentry(void)
|
|
|
/*
|
|
|
* Randomly scan 1/32 of the whole table every second
|
|
|
*/
|
|
|
- for (idx = 0; idx < (IP_VS_CONN_TAB_SIZE>>5); idx++) {
|
|
|
- unsigned hash = net_random() & IP_VS_CONN_TAB_MASK;
|
|
|
+ for (idx = 0; idx < (ip_vs_conn_tab_size>>5); idx++) {
|
|
|
+ unsigned hash = net_random() & ip_vs_conn_tab_mask;
|
|
|
|
|
|
/*
|
|
|
* Lock is actually needed in this loop.
|
|
@@ -1029,7 +1044,7 @@ static void ip_vs_conn_flush(void)
|
|
|
struct ip_vs_conn *cp;
|
|
|
|
|
|
flush_again:
|
|
|
- for (idx=0; idx<IP_VS_CONN_TAB_SIZE; idx++) {
|
|
|
+ for (idx = 0; idx < ip_vs_conn_tab_size; idx++) {
|
|
|
/*
|
|
|
* Lock is actually needed in this loop.
|
|
|
*/
|
|
@@ -1060,10 +1075,15 @@ int __init ip_vs_conn_init(void)
|
|
|
{
|
|
|
int idx;
|
|
|
|
|
|
+ /* Compute size and mask */
|
|
|
+ ip_vs_conn_tab_size = 1 << ip_vs_conn_tab_bits;
|
|
|
+ ip_vs_conn_tab_mask = ip_vs_conn_tab_size - 1;
|
|
|
+
|
|
|
/*
|
|
|
* Allocate the connection hash table and initialize its list heads
|
|
|
*/
|
|
|
- ip_vs_conn_tab = vmalloc(IP_VS_CONN_TAB_SIZE*sizeof(struct list_head));
|
|
|
+ ip_vs_conn_tab = vmalloc(ip_vs_conn_tab_size *
|
|
|
+ sizeof(struct list_head));
|
|
|
if (!ip_vs_conn_tab)
|
|
|
return -ENOMEM;
|
|
|
|
|
@@ -1078,12 +1098,12 @@ int __init ip_vs_conn_init(void)
|
|
|
|
|
|
pr_info("Connection hash table configured "
|
|
|
"(size=%d, memory=%ldKbytes)\n",
|
|
|
- IP_VS_CONN_TAB_SIZE,
|
|
|
- (long)(IP_VS_CONN_TAB_SIZE*sizeof(struct list_head))/1024);
|
|
|
+ ip_vs_conn_tab_size,
|
|
|
+ (long)(ip_vs_conn_tab_size*sizeof(struct list_head))/1024);
|
|
|
IP_VS_DBG(0, "Each connection entry needs %Zd bytes at least\n",
|
|
|
sizeof(struct ip_vs_conn));
|
|
|
|
|
|
- for (idx = 0; idx < IP_VS_CONN_TAB_SIZE; idx++) {
|
|
|
+ for (idx = 0; idx < ip_vs_conn_tab_size; idx++) {
|
|
|
INIT_LIST_HEAD(&ip_vs_conn_tab[idx]);
|
|
|
}
|
|
|
|