#!/bin/bash # script version: v2.2021.0408 nobackticks edition, with moar comments and clarifications # NOTE - check this code for EDITME and modify according to your environment # Parses man page, creates all supported types of encrypted datasets and copies an ISO file to ramdisk # RUN AS ROOT - tested on Linux Mint / Ubuntu 18.04 and 20.04 (rpool), should be fairly easily adaptable # NOTE Pass arg $1 = "cleanup" to delete test encryption datasets / cleanup ramdisk # REF: https://github.com/openzfs/zfs/issues/10363 # REF: https://www.cyberciti.biz/faq/how-to-find-out-aes-ni-advanced-encryption-enabled-on-linux-system/ ##Check for root priviliges if [ "$(id -u)" -ne 0 ]; then echo "Please run $0 as root." exit 1 fi # if we on OSX, you running the wrong version of this script # ex. OSTYPE=darwin17.7.0 if [ $(echo $OSTYPE |grep -c darwin) -gt 0 ]; then echo "You need to be running this on a non-OSX (e.g. Linux) box. There is an OSX version of this script available." echo "See: https://github.com/kneutron/ansitest/tree/master/OSX" exit 10 fi # DEFINE VARS zp=rpool # xxx TODO EDITME # NOTE this zpool is SSD-based logfile=~/zfs-test-encryption-speeds.log # will be copied to ramdisk (prep) - put "" to skip # NOTE nothing prevents you from copying an .iso over SMB or NFS ;-) isofile=/zdell500/shrcompr/ISO/bionic-desktop-amd64.iso # xxx TODO EDITME #isofile="/mnt/imac5/ISO/bionic-desktop-amd64.iso" # EDITME #isofile="" compr=lz4 # compr=zstd-2 # ^ for zfs 2.0.x # where are we storing the key for these test datasets (will be created if not exist) zfskeyloc=~/zek-testencr-zfs.key #===================================== # failexit.mrg function failexit () { echo '! Something failed! Code: '"$1 $2" # code # (and optional description) exit $1 } # Echo something to current console AND log # Can also handle piped input ( cmd |logecho ) # Warning: Has trouble echoing '*' even when quoted. function loggit () { args=$@ if [ -z "$args" ]; then args='tmp' while [ 1 ]; do read -e -t2 args if [ -n "$args" ]; then echo "$args" |tee -a $logfile; else break; fi done else echo "$args" |tee -a $logfile; fi } # END FUNC function ridmeofthesedatasets () { loggit "$0 - $(date) - Cleanup called" if [ "$zp" = "rpool" ]; then cd / else cd /$zp || failexit 404 "! Cleanup failed - /$zp not found" fi for zdel in $(echo Test-aes*); do loggit "$0 - Destroying encryption test dataset: $zp/$zdel"; time zfs destroy -rv "$zp/$zdel"; done # need only filename, not path - strippit isofile2=$(basename "$isofile") C_ALL=C; declare -i chklen # integer chklen=$(echo ${#isofile2}) if [ $chklen -gt 0 ] && [ -e "/dev/shm/$isofile2" ]; then loggit "Cleaning up $isofile2 from ramdisk" /bin/rm -fv "/dev/shm/$isofile2" fi # sanity, will give error if we try to remove /dev/shm if var=blank df -hT |head -n 1 df -hT |grep $zp df -hT |grep /dev/shm exit; } [ "$1" = "cleanup" ] && ridmeofthesedatasets # MAIN ==================================================================== mv -v $logfile $logfile-old 2>/dev/null echo "$(date) - $(hostname) - BEGIN encryption speed tests" |tee $logfile loggit "o Kernel: $(uname -r)" loggit "o Zpool version: $(zpool version)" loggit "$(dmesg |grep ZFS)" loggit "o CPU detected: $(grep -m1 "model name" /proc/cpuinfo |awk -F: '{print $2}')" loggit "o Number of CPU cores/hyperthreads: $(grep -c 'processor' /proc/cpuinfo)" loggit "o Actual number of $(grep -m1 cores /proc/cpuinfo)" loggit "o CPU supports AES acceleration (blank=NO): $(grep -m1 -o aes /proc/cpuinfo)" loggit "o Crypto modules loaded:" loggit "$(sort -u /proc/crypto |grep module)" loggit "o Check for openssl / run benchmarks" which openssl && loggit "$(openssl speed aes)" loggit "o Check for cryptsetup - please wait, this will take a few" which cryptsetup && loggit "$(cryptsetup benchmark)" loggit "o PREP - Copy ~1GB iso file to ramdisk if not already there" LC_ALL=C; declare -i chklen # integer chklen=$(echo ${#isofile}) [ $chklen -gt 0 ] && [ -e /dev/shm ] && [ -e "$isofile" ] && time cp -vn "$isofile" /dev/shm |tee -a $logfile [ -e "/dev/shm/*.iso" ] || loggit "o Skipped ISO -> RAMdisk" # get current zfs supported encryption types (NOTE depends on up-to-date man page) - output commasep # yes, this is 3 different replace methods ;-) who doesn't like to show off a bit now and then # read zfs man page, get ciphers, change pipe to comma, blank out unnec. stuff encrline=$(man zfs|grep "encryption=" |head -n 1 |sed 's/|/,/g') # |sed 's/off,on,//g') # NOTE on/off is REVERSED from osx manpage(!) so we process differently below in case they change it to match encrline=$(echo "$encrline" |tr -d '[:space:]') # strip blanks encrline=${encrline/on,/} # bash inline sed, replace string with blank encrline=${encrline/off,/} encrline=${encrline/encryption=/} loggit "o Supported ZFS encryption types (per ' man zfs ')" loggit "$encrline" # we expect something like: #aes-128-ccm,aes-192-ccm,aes-256-ccm,aes-128-gcm,aes-192-gcm,aes-256-gcm # REF: https://stackoverflow.com/questions/918886/how-do-i-split-a-string-on-a-delimiter-in-bash#tab-top # read string into bash array oIFS="$IFS" IFS="," declare -a encrtype=($encrline) IFS="$oIFS" unset oIFS #generate 32 byte passkey ONLY if not already exist [ -e $zfskeyloc ] || dd if=/dev/urandom of="$zfskeyloc" bs=1 count=32 # NOTE omit xattr=sa for freebsd as of 2020.0526, may change after support is added to their code # NOTE relatime and acltype=posixacl are missing from OSX zfs port as of 2020.0526 for testencr in "${encrtype[@]}"; do loggit "o Creating $zp dataset for $testencr (if it doesnt already exist)" # [ -e /$zp/Test-$testencr ] || \ # fails on rpool [ $(df |grep -c Test-$testencr) -gt 0 ] || \ zfs create -o \ atime=off -o relatime=off -o compression=$compr -o sharesmb=off -o recordsize=1024k \ -o encryption=$testencr \ -o keyformat=raw \ -o keylocation=file://"$zfskeyloc" \ -o acltype=posixacl -o normalization=formD \ -o xattr=sa \ $zp/Test-$testencr || failexit 99 "! Failed to create ZFS $zp/$testencr" loggit "$(zfs get encryption,keylocation $zp/Test-$testencr)" done #sync # may not want to do this if you have a long e.g. backup process running free echo 1 > /proc/sys/vm/drop_caches # free pagecache free df -hT |head -n 1 df -hT |grep -v '/ROOT/' |grep $zp df -hT |grep /dev/shm ls -lh /dev/shm/*.iso loggit "$(date) $0 - $(hostname) - Ready for testing" # from here you can test how long it takes to copy iso file, run fio, etc # time (cp -v $isofile /$zp/aesdataset; sync) echo "o $0 Logfile is: $logfile" exit; ################################################# 2020.0526 Author: Kneutron - knocked together a zfs test script to create datasets per encryption type, to test speeds of each cipher Tested OK on Ubuntu 18.04 / Ubuntu 20.04 / Linux Mint # Future changes will be in reverse-date order 2021.0408 backticks to $() 2020.0527 v2A - bugfix edition, chklen was ($ instead of $( 2020.0527 V2 - fixed minor bug in cleanup to fail if cant cd to /$zp, cd "/" if zp=rpool sanity - fixed check length of isofile var, skip if 0 zp=rpool related fixes + added ramdisk cleanup + sanity checks (will ONLY delete defined iso file) + tested on ubuntu 20.04 with zfs rpool NOTE if reboot or $thing happens to zpool such as export, you may need to: zfs load-key $zp/encrtype zfs mount -a NOTE if doing this on an ssd-based pool, you may want to "zpool trim $zp" after doing cleanup # note this does not work on osx (fixed in osx port) - REF: https://stackoverflow.com/questions/41489692/how-to-search-linux-man-pages-e-g-with-grep $ man zfs|grep "encryption=" |head -n 1 |sed 's/|/,/g' |sed 's/off,on,//g' encryption=off|on|aes-128-ccm|aes-192-ccm|aes-256-ccm|aes-128-gcm|aes-192-gcm|aes-256-gcm encryption=off,on,aes-128-ccm,aes-192-ccm,aes-256-ccm,aes-128-gcm,aes-192-gcm,aes-256-gcm encryption=aes-128-ccm,aes-192-ccm,aes-256-ccm,aes-128-gcm,aes-192-gcm,aes-256-gcm /zmsata480 # for z in `echo aes*`; do echo $z; zfs destroy zmsata480/$z;done