Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) # Common functions used by pktgen scripts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3) #  - Depending on bash 3 (or higher) syntax
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5) # Author: Jesper Dangaaard Brouer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6) # License: GPL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) set -o errexit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) ## -- General shell logging cmds --
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) function err() {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12)     local exitcode=$1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13)     shift
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14)     echo "ERROR: $@" >&2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15)     exit $exitcode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) function warn() {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19)     echo "WARN : $@" >&2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) function info() {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23)     if [[ -n "$VERBOSE" ]]; then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 	echo "INFO : $@" >&2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25)     fi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) ## -- Pktgen proc config commands -- ##
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) export PROC_DIR=/proc/net/pktgen
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) # Three different shell functions for configuring the different
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) # components of pktgen:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) #   pg_ctrl(), pg_thread() and pg_set().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) # These functions correspond to pktgens different components.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) # * pg_ctrl()   control "pgctrl" (/proc/net/pktgen/pgctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) # * pg_thread() control the kernel threads and binding to devices
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) # * pg_set()    control setup of individual devices
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) function pg_ctrl() {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40)     local proc_file="pgctrl"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41)     proc_cmd ${proc_file} "$@"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) function pg_thread() {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45)     local thread=$1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46)     local proc_file="kpktgend_${thread}"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47)     shift
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48)     proc_cmd ${proc_file} "$@"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) function pg_set() {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52)     local dev=$1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53)     local proc_file="$dev"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54)     shift
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55)     proc_cmd ${proc_file} "$@"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) # More generic replacement for pgset(), that does not depend on global
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) # variable for proc file.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) function proc_cmd() {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61)     local result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62)     local proc_file=$1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63)     local status=0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64)     # after shift, the remaining args are contained in $@
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65)     shift
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66)     local proc_ctrl=${PROC_DIR}/$proc_file
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67)     if [[ ! -e "$proc_ctrl" ]]; then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 	err 3 "proc file:$proc_ctrl does not exists (dev added to thread?)"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69)     else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 	if [[ ! -w "$proc_ctrl" ]]; then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 	    err 4 "proc file:$proc_ctrl not writable, not root?!"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	fi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73)     fi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75)     if [[ "$DEBUG" == "yes" ]]; then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 	echo "cmd: $@ > $proc_ctrl"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77)     fi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78)     # Quoting of "$@" is important for space expansion
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79)     echo "$@" > "$proc_ctrl" || status=$?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81)     if [[ "$proc_file" != "pgctrl" ]]; then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82)         result=$(grep "Result: OK:" $proc_ctrl) || true
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83)         if [[ "$result" == "" ]]; then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84)             grep "Result:" $proc_ctrl >&2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85)         fi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86)     fi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87)     if (( $status != 0 )); then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	err 5 "Write error($status) occurred cmd: \"$@ > $proc_ctrl\""
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89)     fi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) # Old obsolete "pgset" function, with slightly improved err handling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) function pgset() {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94)     local result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96)     if [[ "$DEBUG" == "yes" ]]; then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	echo "cmd: $1 > $PGDEV"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98)     fi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99)     echo $1 > $PGDEV
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)     local status=$?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)     result=`cat $PGDEV | fgrep "Result: OK:"`
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)     if [[ "$result" == "" ]]; then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)          cat $PGDEV | fgrep Result:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)     fi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)     if (( $status != 0 )); then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	err 5 "Write error($status) occurred cmd: \"$1 > $PGDEV\""
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)     fi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) [[ $EUID -eq 0 ]] && trap 'pg_ctrl "reset"' EXIT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) ## -- General shell tricks --
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) function root_check_run_with_sudo() {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)     # Trick so, program can be run as normal user, will just use "sudo"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)     #  call as root_check_run_as_sudo "$@"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)     if [ "$EUID" -ne 0 ]; then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	if [ -x $0 ]; then # Directly executable use sudo
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 	    info "Not root, running with sudo"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)             sudo "$0" "$@"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)             exit $?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 	fi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 	err 4 "cannot perform sudo run of $0"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)     fi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) # Exact input device's NUMA node info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) function get_iface_node()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)     local node=$(</sys/class/net/$1/device/numa_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)     if [[ $node == -1 ]]; then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)         echo 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)     else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)         echo $node
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)     fi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) # Given an Dev/iface, get its queues' irq numbers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) function get_iface_irqs()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 	local IFACE=$1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 	local queues="${IFACE}-.*TxRx"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 	irqs=$(grep "$queues" /proc/interrupts | cut -f1 -d:)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 	[ -z "$irqs" ] && irqs=$(grep $IFACE /proc/interrupts | cut -f1 -d:)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	[ -z "$irqs" ] && irqs=$(for i in `ls -Ux /sys/class/net/$IFACE/device/msi_irqs` ;\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 	    do grep "$i:.*TxRx" /proc/interrupts | grep -v fdir | cut -f 1 -d : ;\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 	    done)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 	[ -z "$irqs" ] && err 3 "Could not find interrupts for $IFACE"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 	echo $irqs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) # Given a NUMA node, return cpu ids belonging to it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) function get_node_cpus()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 	local node=$1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 	local node_cpu_list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 	local node_cpu_range_list=`cut -f1- -d, --output-delimiter=" " \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 	                  /sys/devices/system/node/node$node/cpulist`
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 	for cpu_range in $node_cpu_range_list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 	do
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 	    node_cpu_list="$node_cpu_list "`seq -s " " ${cpu_range//-/ }`
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 	done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 	echo $node_cpu_list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) # Check $1 is in between $2, $3 ($2 <= $1 <= $3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) function in_between() { [[ ($1 -ge $2) && ($1 -le $3) ]] ; }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) # Extend shrunken IPv6 address.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) # fe80::42:bcff:fe84:e10a => fe80:0:0:0:42:bcff:fe84:e10a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) function extend_addr6()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)     local addr=$1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)     local sep=: sep2=::
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)     local sep_cnt=$(tr -cd $sep <<< $1 | wc -c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)     local shrink
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)     # separator count should be (2 <= $sep_cnt <= 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)     if ! (in_between $sep_cnt 2 7); then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)         err 5 "Invalid IP6 address: $1"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)     fi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)     # if shrink '::' occurs multiple, it's malformed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)     shrink=( $(egrep -o "$sep{2,}" <<< $addr) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)     if [[ ${#shrink[@]} -ne 0 ]]; then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)         if [[ ${#shrink[@]} -gt 1 || ( ${shrink[0]} != $sep2 ) ]]; then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)             err 5 "Invalid IP6 address: $1"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)         fi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)     fi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)     # add 0 at begin & end, and extend addr by adding :0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)     [[ ${addr:0:1} == $sep ]] && addr=0${addr}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)     [[ ${addr: -1} == $sep ]] && addr=${addr}0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)     echo "${addr/$sep2/$(printf ':0%.s' $(seq $[8-sep_cnt])):}"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) # Given a single IP(v4/v6) address, whether it is valid.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) function validate_addr()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)     # check function is called with (funcname)6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)     [[ ${FUNCNAME[1]: -1} == 6 ]] && local IP6=6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)     local bitlen=$[ IP6 ? 128 : 32 ]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)     local len=$[ IP6 ? 8 : 4 ]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)     local max=$[ 2**(len*2)-1 ]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)     local net prefix
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)     local addr sep
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)     IFS='/' read net prefix <<< $1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)     [[ $IP6 ]] && net=$(extend_addr6 $net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)     # if prefix exists, check (0 <= $prefix <= $bitlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)     if [[ -n $prefix ]]; then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)         if ! (in_between $prefix 0 $bitlen); then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)             err 5 "Invalid prefix: /$prefix"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)         fi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)     fi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)     # set separator for each IP(v4/v6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)     [[ $IP6 ]] && sep=: || sep=.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)     IFS=$sep read -a addr <<< $net
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)     # array length
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)     if [[ ${#addr[@]} != $len ]]; then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)         err 5 "Invalid IP$IP6 address: $1"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)     fi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)     # check each digit (0 <= $digit <= $max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)     for digit in "${addr[@]}"; do
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)         [[ $IP6 ]] && digit=$[ 16#$digit ]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)         if ! (in_between $digit 0 $max); then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)             err 5 "Invalid IP$IP6 address: $1"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)         fi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)     done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)     return 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) function validate_addr6() { validate_addr $@ ; }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) # Given a single IP(v4/v6) or CIDR, return minimum and maximum IP addr.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) function parse_addr()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)     # check function is called with (funcname)6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)     [[ ${FUNCNAME[1]: -1} == 6 ]] && local IP6=6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)     local net prefix
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)     local min_ip max_ip
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)     IFS='/' read net prefix <<< $1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)     [[ $IP6 ]] && net=$(extend_addr6 $net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)     if [[ -z $prefix ]]; then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)         min_ip=$net
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)         max_ip=$net
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)     else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)         # defining array for converting Decimal 2 Binary
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)         # 00000000 00000001 00000010 00000011 00000100 ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)         local d2b='{0..1}{0..1}{0..1}{0..1}{0..1}{0..1}{0..1}{0..1}'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)         [[ $IP6 ]] && d2b+=$d2b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)         eval local D2B=($d2b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)         local bitlen=$[ IP6 ? 128 : 32 ]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)         local remain=$[ bitlen-prefix ]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)         local octet=$[ IP6 ? 16 : 8 ]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)         local min_mask max_mask
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)         local min max
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)         local ip_bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)         local ip sep
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)         # set separator for each IP(v4/v6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)         [[ $IP6 ]] && sep=: || sep=.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)         IFS=$sep read -ra ip <<< $net
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)         min_mask="$(printf '1%.s' $(seq $prefix))$(printf '0%.s' $(seq $remain))"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)         max_mask="$(printf '0%.s' $(seq $prefix))$(printf '1%.s' $(seq $remain))"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)         # calculate min/max ip with &,| operator
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)         for i in "${!ip[@]}"; do
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)             digit=$[ IP6 ? 16#${ip[$i]} : ${ip[$i]} ]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)             ip_bit=${D2B[$digit]}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)             idx=$[ octet*i ]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)             min[$i]=$[ 2#$ip_bit & 2#${min_mask:$idx:$octet} ]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)             max[$i]=$[ 2#$ip_bit | 2#${max_mask:$idx:$octet} ]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)             [[ $IP6 ]] && { min[$i]=$(printf '%X' ${min[$i]});
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)                             max[$i]=$(printf '%X' ${max[$i]}); }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)         done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)         min_ip=$(IFS=$sep; echo "${min[*]}")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)         max_ip=$(IFS=$sep; echo "${max[*]}")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)     fi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)     echo $min_ip $max_ip
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) function parse_addr6() { parse_addr $@ ; }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) # Given a single or range of port(s), return minimum and maximum port number.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) function parse_ports()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)     local port_str=$1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)     local port_list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)     local min_port
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)     local max_port
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)     IFS="-" read -ra port_list <<< $port_str
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)     min_port=${port_list[0]}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)     max_port=${port_list[1]:-$min_port}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)     echo $min_port $max_port
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) # Given a minimum and maximum port, verify port number.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) function validate_ports()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)     local min_port=$1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)     local max_port=$2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)     # 1 <= port <= 65535
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)     if (in_between $min_port 1 65535); then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 	if (in_between $max_port 1 65535); then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 	    if [[ $min_port -le $max_port ]]; then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 		return 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 	    fi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 	fi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)     fi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)     err 5 "Invalid port(s): $min_port-$max_port"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) }