#!/bin/bash

set -eu

usage() {
	echo "Usage: $0 <dev> [cpu socket]"
	echo "Example: $0 eth1"
	echo "Example: $0 eth1 0"
	echo "Example: $0 eth2 1"
}

socket_cpu_list() {
	local socket="$1"
	lscpu --extended=CPU,SOCKET | grep -v CPU | egrep "[0-9]+[ ]+$socket$" | awk '{print $1}'
}

interrtupts() {
	local dev="$1"
	local postfix="$2"
	grep "$dev$postfix" /proc/interrupts
}

set_affinity() {
	local dev="$1"
	local cpu_bound="$2"
	local irq queue cpu
	# shellcheck disable=SC2046
	while read _ irq $(socket_cpu_list $cpu_bound | sed 's/.*/cpu&/') _ queue cpu _; do
		irq="${irq//:}"
		echo "  - $dev: irq $irq $queue -> $cpu"
		echo $cpu > /proc/irq/$irq/smp_affinity_list
	done
}

tune() {
	local dev="$1"
	local cpu_bound="$2"
	local postfix="$3"
	echo "- Распределение прерываний $dev на сокете $cpu_bound"
	interrtupts "$dev" "$postfix" | cat -n > /tmp/interrupts.$dev
	socket_cpu_list $cpu_bound | cat -n > /tmp/cpu.$cpu_bound
	join /tmp/interrupts.$dev /tmp/cpu.$cpu_bound > /tmp/irq.$dev
	set_affinity "$dev" "$cpu_bound" < /tmp/irq.$dev
}

igb() {
	tune "$1" "$2" "-TxRx-"
}

ixgbe() {
	tune "$1" "$2" "-TxRx-"
}

vmxnet3() {
	tune "$1" "$2" "-rxtx-"
}

# mlnx eth2-0 eth2-1 eth2-2 eth2-3

main() {
	local dev="$1"
	local cpu_bound="${2:-0}"
	local driver
	local postfix
	if [ "$dev" = '--help' ]; then
		usage
		exit 0
	fi
	driver="$(ethtool -i "$dev" | grep driver | awk '{print $2}')"
	case $driver in
		igb | ixgbe | vmxnet3 )
			$driver $dev $cpu_bound
			;;
		* )
			echo "Driver $driver for dev $dev not supported"
			exit 1
			;;
	esac
}

main "$@"
