#!/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!"