#!/usr/bin/bash
#
# sysctl autotune prepared by Pieter Coetzee 2016/06/01
#

host=$(hostname)
domain=$(domainname)
if [ -z "$domain" ] || [ "$domain" == "(none)" ]; then
     domain=$(hostname -d)
fi
[ -z "$domain" ] && echo -e "WARNING: $(basename $0) - unable to determine system domain, assuming 'localdomain'" >&2

ARCH=$(uname -m)

if ! command -v bc &>/dev/null; then
    echo "This script require GNU bc, cf. http://www.gnu.org/software/bc/" >&2
    echo "On Linux Centos/Fedora/RedHat install by doing: yum or dnf install bc" >&2
fi

echo " * Update sysctl for $host"

shmmax=$(awk '/MemTotal:/ { printf "%0.f",$2 * 1024}' /proc/meminfo)
shmall=$(echo "($shmmax / 4096)*0.9" | bc | cut -f 1 -d '.')
max_orphan=$(echo "$shmmax * 0.10 / 65536" | bc | cut -f 1 -d '.')
file_max=$(echo "$shmmax / 4194304 * 256" | bc | cut -f 1 -d '.')
max_tw=$(($file_max*2))
min_free=$(echo "($shmmax / 1024) * 0.01" | bc | cut -f 1 -d '.')

if [ "$1" != "ssd" ]; then
    vm_dirty_bg_ratio=5
    vm_dirty_ratio=15
else
    # This setup is generally ok for ssd and highmem servers
    vm_dirty_bg_ratio=3
    vm_dirty_ratio=5
fi

>/usr/lib/sysctl.d/60-autotune.conf cat << EOF
#
# This file was automatically generated by $(readlink -f $0) at $(date '+%Y-%m-%d %T%z (%Z)') 
#
# Changes to this file will be overwritten automatically.
# To override values set in this file create /etc/sysctl.d/<override>.conf where <override>
# sorts after this file alphabetically
#

kernel.domainname =  ${domain:-localdomain}

kernel.printk = 4 4 1 7
kernel.core_uses_pid = 1
kernel.core_pattern = |/usr/lib/systemd/systemd-coredump %p %u %g %s %t %e
kernel.sysrq = 0
kernel.msgmax = 65536
kernel.msgmnb = 65536
kernel.msgmni = 1024
kernel.sem = 250 256000 32 1024

# Maximum shared segment size in bytes
kernel.shmmax = $shmmax
kernel.shmmni = 4096

# Maximum number of shared memory segments in pages
kernel.shmall = $shmall

# Enable syncookies  to protect against DOS
net.ipv4.tcp_syncookies = 1

# Basic TCP tuning
net.ipv4.tcp_keepalive_time = 300
net.ipv4.tcp_keepalive_intvl = 10
net.ipv4.tcp_keepalive_probes = 3
net.ipv4.tcp_syn_retries = 3
net.ipv4.tcp_retries2 = 15
net.ipv4.tcp_retries1 = 3

# Number of times SYNACKs for passive TCP connection.
net.ipv4.tcp_synack_retries = 2

# RFC1337 Protect Against TCP Time-Wait 
net.ipv4.tcp_rfc1337 = 1

# Defines the local port range that is used by TCP and UDP
# to choose the local port
net.ipv4.ip_local_port_range = 1024 65535

# Log packets with impossible addresses to kernel log
net.ipv4.conf.all.log_martians = 0

# Enable window scaling as defined in RFC1323
net.ipv4.tcp_window_scaling = 1

# Enable timestamps (RFC1323)
net.ipv4.tcp_timestamps = 0

# Enable select acknowledgments
net.ipv4.tcp_sack = 1

# Enable FACK congestion avoidance and fast restransmission
net.ipv4.tcp_fack = 1

# Allows TCP to send "duplicate" SACKs
net.ipv4.tcp_dsack = 1

# Controls IP packet forwarding
net.ipv4.ip_forward = 0

# Strict mode as defined in RFC3704 Strict Reverse Path
net.ipv4.conf.default.rp_filter = 1

# Enable fast recycling TIME-WAIT sockets
net.ipv4.tcp_tw_recycle = 0

# tells the kernel how many TCP sockets that are not attached
# to any user file handle to maintain
net.ipv4.tcp_max_orphans = $max_orphan

# How may times to retry before killing TCP connection, closed by our side
net.ipv4.tcp_orphan_retries = 1

# how long to keep sockets in the state FIN-WAIT-2
# if we were the one closing the socket. Decrease the time default value.
net.ipv4.tcp_fin_timeout = 8

# maximum number of sockets in TIME-WAIT to be held simultaneously
net.ipv4.tcp_max_tw_buckets = $max_tw

# don't cache ssthresh from previous connection
net.ipv4.tcp_no_metrics_save = 1
net.ipv4.tcp_moderate_rcvbuf = 1

# increase Linux autotuning TCP buffer limits

# Increase the read-buffer space allocatable (minimum size,
# initial size, and maximum size in bytes)
net.ipv4.tcp_rmem = 4096 87380 25165824
net.ipv4.udp_rmem_min = 16384

# Increase the send-buffer space allocatable (minimum size,
# initial size, and maximum size in bytes)
net.ipv4.tcp_wmem = 4096 65535 25165824

# increase TCP max buffer size
# Maximum Socket Receive Buffer
net.core.rmem_max = 25165824

# Default Socket Receive Buffer
net.core.rmem_default = 87380

# Maximum Socket Send Buffer 
net.core.wmem_max = 25165824

# Default Socket Send Buffer 
net.core.wmem_default = 65535

# Increase the maximum amount of option memory buffers
net.core.optmem_max = 25165824

net.core.dev_weight = 64

# Increase the maximum total buffer-space allocatable
# This is measured in units of pages (4096 bytes)
net.ipv4.tcp_mem = 65535 131072 262144
net.ipv4.udp_mem = 65535 131072 262144


# Increase number of incoming connections backlog queue
# Sets the maximum number of packets, queued on the INPUT
# side, when the interface receives packets faster than
# kernel can process them.
net.core.netdev_max_backlog = 65535

# Increase number of incoming connections
# somaxconn defines the number of request_sock structures
# allocated per each listen call. The
# queue is persistent through the life of the listen socket.
net.core.somaxconn = 1024

vm.swappiness = 5
vm.overcommit_memory = 2
vm.overcommit_ratio  = 125

# You can monitor the kernel behavior with regard to the dirty
# pages by using grep -A 1 dirty /proc/vmstat
vm.dirty_background_ratio = $vm_dirty_bg_ratio
vm.dirty_ratio = $vm_dirty_ratio

# required free memory (set to 1% of physical ram)
vm.min_free_kbytes = $min_free

# system open file limit
fs.file-max = $file_max

# Core dump suidsafe
fs.suid_dumpable = 2

########## IPv4 networking start ##############
# Send redirects, if router, but this is just server
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0

# Accept packets with SRR option? No
net.ipv4.conf.all.accept_source_route = 0

# Accept Redirects? No, this is not router
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.secure_redirects = 0
net.ipv6.conf.all.accept_redirects=0
net.ipv6.conf.default.accept_redirects=0

# Log packets with impossible addresses to kernel log? yes
net.ipv4.conf.all.log_martians = 1
net.ipv4.conf.default.log_martians = 1
net.ipv4.conf.default.accept_source_route = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.default.secure_redirects = 0

# Ignore all ICMP ECHO and TIMESTAMP requests sent to it via broadcast/multicast
net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.icmp_ignore_bogus_error_responses=1
net.ipv4.icmp_echo_ignore_all=0

# Prevent against the common 'syn flood attack'
net.ipv4.tcp_syncookies = 1

# Maximum number of remembered connection requests, which did not yet
# receive an acknowledgment from connecting client.
net.ipv4.tcp_max_syn_backlog = 10240

# recommended default congestion control is cubic
net.ipv4.tcp_congestion_control = cubic


# Other
net.ipv4.neigh.default.gc_thresh3 = 2048
net.ipv4.tcp_reordering = 5
net.ipv4.neigh.default.proxy_qlen = 96
net.ipv4.neigh.default.gc_thresh1 = 32
net.ipv4.tcp_tw_reuse = 0
net.ipv4.neigh.default.gc_interval = 30
net.ipv4.neigh.default.unres_qlen = 6
net.ipv4.neigh.default.gc_thresh2 = 1024
net.unix.max_dgram_qlen = 3240000

EOF

# Note that order of arguments matters --quiet needs to come first in
# order to be effective
/sbin/sysctl --quiet --system

exit $?
