271 lines
8.3 KiB
Bash
Executable File

#!/bin/sh
# Strict script
set -e
set -u
# Global variables
HOST=false
ROUTER=false
# Get options passed by user
getoption () {
if [ $# -ge 1 ]; then
FIRST_OPTION="$1"
else
usage
exit 1
fi
case "$FIRST_OPTION" in
host)
HOST=true
;;
router)
ROUTER=true
;;
help)
usage
exit 0
;;
esac
}
usage () {
# Display usage
echo "Usage: $0 option"
echo " option can be:"
echo " -host: tuning tips for end-host"
echo " -router: tuning tips for router"
echo " -help: display this help"
}
sysctl_atleast () {
# Check the sysctl parameter is at least configured to the value
# $1: sysctl parameter
# $2: recommended value
if [ `sysctl -n $1` -lt $2 ]; then
echo "$1=\"$2\""
fi
}
sysctl_equal () {
# Check the sysctl parameter match (equal) the value
# $1: sysctl parameter
# $2: recommended value
if [ `sysctl -n $1` -ne $2 ]; then
echo "$1=\"$2\""
fi
}
if_have_cap () {
# Check if the interface have capabilities and if it's enabled return true (0)
# $1: if
# $2: capability
ifconfig -m $1 | egrep -q "capabilities.*$2" && return 0 || return 1
}
if_is_cap_enabled () {
# Check if the interface capability is enabled: return true
# $1: if
# $2: capability
ifconfig -m $1 | egrep -q "options.*$2" && return 0 || return 1
}
tune () {
# Major function that call the others
# RO values need to be put in /boot/loader.conf.local
# RW values need to be put in /etc/sysctl.conf
echo "#==> Start of /boot/loader.conf.local"
echo "#TO DO All these values doesn't works here and need to be put in /etc/sysctl.conf"
net_nic
($ROUTER) && net_forward
($ROUTER) && net_inet
($ROUTER) && cpu_ht
net_netisr
# Autombuf tunning avoid the need fo checking them
# net_mbuf
echo "#<== End of /boot/loader.conf.local"
net_netstat
echo "#==> To be added to /etc/rc.conf"
#Need to replace this part by a list of modules (ichsmb coretemp aesni watchdog?)
if grep -q 'Feature.*AESNI' /var/run/dmesg.boot ; then
#CPU support, check if not allready loaded
if ! kldstat -n aesni 2>&1 | grep -q aesni; then
echo "#CPU has AESNI feature, you should load the modules"
echo 'kld_list="cryptodev aesni"'
fi
fi
for NIC in `ifconfig -l "ether"`; do
#skip loopback interfaces
echo $NIC | egrep -q "lo[[:digit:]]" && continue
# Check only interface with vlan configured on them
if egrep -q "ifconfig_vlan.*${NIC}" /etc/rc.conf; then
if if_have_cap ${NIC} VLAN_HWFILTER; then
if ! if_is_cap_enabled ${NIC} VLAN_HWFILTER; then
echo "${NIC} configured with vlan and support VLAN_HWFILTER"
echo " => add the vlanhwfilter option to ifconfig_${NIC} in /etc/rc.conf"
fi
fi # if_have_cap
fi # rc.conf
# Router should not have LRO/TSO4/TSO6 enabled
if ($ROUTER); then
for CAP in LRO TSO4 TSO6; do
if_is_cap_enabled ${NIC} ${CAP} && \
echo "A router MUST NOT have ${CAP} enabled on forwarding NIC"
done
fi
# Check for virtualized
if (${VM_DETECTED}); then
if if_have_cap ${NIC} POLLING; then
if ! if_is_cap_enabled ${NIC} POLLING; then
# http://lists.freebsd.org/pipermail/freebsd-net/2013-May/035626.html
echo "In VM, ${NIC} can have better behavior if POLLING was enabled"
echo " => Enable polling in /etc/rc.conf.misc"
fi
fi
# need disable hardware assisted features (need to found reference about this tip)
for CAP in RXCSUM TXCSUM TSO4 TSO6; do
if_is_cap_enabled ${NIC} ${CAP} && \
echo "${NIC} have ${CAP} enabled: Disable it in a VM"
done # end for CAP
fi
done
}
cpu_ht () {
# Check if HyperThreading is enabled
grep -q "^FreeBSD/SMP.*SMT" /var/run/dmesg.boot && echo "You should disable HyperThreading"
}
net_nic () {
# NIC drivers tuning
# em tuning
if ifconfig -l "ether" | egrep -q 'em[[:digit:]]'; then
# Need to check if there are not 82542 or 82543 (support 256 max)
for VALUE in hw.em.txd hw.em.rxd; do
sysctl_equal ${VALUE} 2048
done
# Disabling limit of rx frame
#sysctl_atleast hw.em.rx_process_limit 500
sysctl_equal hw.em.rx_process_limit -1
# Increasing interrupt delay is bad for a router because it add latency
# http://www.intel.com/design/network/applnots/ap450.htm
if ! ($ROUTER); then
for VALUE in hw.em.rx_abs_int_delay hw.em.tx_abs_int_delay; do
sysctl_equal ${VALUE} 1024
done
for VALUE in hw.em.rx_int_delay hw.em.tx_int_delay; do
sysctl_equal ${VALUE} 512
done
fi
fi
# igb tuning
if ifconfig -l "ether" | egrep -q 'igb[[:digit:]]'; then
for VALUE in hw.igb.txd hw.igb.rxd; do
sysctl_equal ${VALUE} 2048
done
# http://wiki.freebsd.org/NetworkPerformanceTuning
sysctl_atleast hw.igb.max_interrupt_rate 32000
# Need mbuf be increased if rx_process limit increased?
#sysctl_atleast hw.igb.rx_process_limit 500
# Disabling limit of rx frame
sysctl_equal hw.igb.rx_process_limit -1
# Default kern.ipc.nmbclusters is too small for multiple igb card and multicore
# Need to add a test [ `sysctl -n hw.ncpu` -gt 1 ] and arch (i386 don't like too much)
[ `sysctl -n hw.ncpu` -ge 4 ] && sysctl_atleast kern.ipc.nmbclusters 262144
fi
# ixgbe tuning
if ifconfig -l "ether" | egrep -q 'ix[[:digit:]]'; then
# source: README in drivers source
# When using the ixgbe driver with RSS autoconfigured based on the number of
# cores (the default setting) and that number is larger than 4, increase the
# memory resources allocated for the mbuf pool as follows:
# Warning: Where to put this valuedepends if drivers is a module or in kernel
if [ `sysctl -n hw.ncpu` -ge 4 ]; then
#loader.conf ?
sysctl_atleast kern.ipc.nmbclusters 262144
#sysctl.conf ?
sysctl_atleast kern.ipc.nmbjumbop 262144
fi
fi
# General
# default value of send interface queue length
# If em or igb were tunned, need to change this too
# http://lists.freebsd.org/pipermail/freebsd-net/2012-July/032712.html
sysctl_atleast net.link.ifqmaxlen 10240
# cxgbe (Chelsio) tuning
if ifconfig -l "ether" | egrep -q 'cxl[[:digit:]]'; then
# source: http://bsdrp.net/documentation/examples/forwarding_performance_lab_of_a_hp_proliant_dl360p_gen8_with_10-gigabit_with_10-gigabit_chelsio_t540-cr
# If ncpu=8 and drivers is using 8 queue (default), should reduce the NIC queue to 4
if [ `sysctl -n hw.ncpu` -eq 8 ]; then
[ `sysctl -n dev.cxl.0.nrxq` -eq 8 ] && echo 'echo hw.cxgbe.nrxq10g="4" >> /boot/loader.conf.local'
[ `sysctl -n dev.cxl.0.ntxq` -eq 8 ] && echo 'echo hw.cxgbe.ntxq10g="4" >> /boot/loader.conf.local'
fi
fi
}
net_netstat () {
# Analysing netstat -m output and provide advice regarding the result
echo "TODO: netstat"
}
net_forward () {
# http://wiki.freebsd.org/NetworkPerformanceTuning
sysctl_equal net.inet.ip.forwarding 1
if [ `sysrc -n ipsec_enable` == "YES" ]; then
sysctl_equal net.inet.ip.fastforwarding 0
echo "IPSec configuration detected"
echo "Check if your hardware support one of these crypto accelerator modules:"
echo " aesni(4), glxsb(4), hifn(4), ipsec(4), padlock(4), safe(4) or ubsec(4)"
fi
}
net_inet () {
# http://wiki.freebsd.org/NetworkPerformanceTuning
for VALUE in net.inet.raw.maxdgram net.inet.raw.recvspace; do
sysctl_atleast ${VALUE} 16384
done
for VALUE in net.inet.ip.redirect; do
sysctl_equal ${VALUE} 0
done
}
net_netisr () {
# http://wiki.freebsd.org/NetworkPerformanceTuning
sysctl_atleast net.route.netisr_maxqlen 2048
}
net_mbuf () {
# kern.ipc.nmbclusters must be increased if multiple igb (man igb)
# Need to calculate (regarding RAM size) this value
# Does vm.kmem_size should be upgraded too ?
# igb loads 8 rings, each of 1024 per NIC
sysctl_atleast kern.ipc.nmbclusters 262144
echo "On the following output, with all your NIC already configured"
echo " check the current and total"
netstat -m | grep "mbuf clusters in use"
}
timecounter () {
# Are the timecounter tuning usefull ?
TIMECOUTER_CHOICE=`sysctl -n sysctl kern.timecounter.choice`
if echo "${TIMECOUTER_CHOICE}" | grep -q "HPET" ; then
sysctl -n kern.timecounter.hardware | grep -q HPET || \
echo "sysctl kern.timecounter.hardware=HPET"
fi
}
###################
## Main function ##
###################
getoption $*
#system_inventory
# Look for VM environnement
sysctl -n kern.vm_guest | grep -q -v "none" && VM_DETECTED=true || VM_DETECTED=false
tune
echo "Done!"