#!/bin/sh
# Opportunistically look for interfaces with multiple transmit queues
# and hardware support for the mqprio queuing discipline. For every
# matching interface, set up mappings from kernel-internal packet
# priorities, via traffic classes, to transmit queues such that as
# many high priorities as possible are scheduled on separate queues.

set -e

map()
{
    case "$1" in
	2)
	    echo "map 0 0 0 0 0 0 1 1";;
	3)
	    echo "map 0 0 0 0 1 1 2 2";;
	4)
	    echo "map 0 0 1 1 2 2 3 3";;
	5)
	    echo "map 0 0 1 1 2 2 3 4";;
	6)
	    echo "map 0 0 1 1 2 3 4 5";;
	7)
	    echo "map 0 0 1 2 3 4 5 6";;
	8)
	    echo "map 0 1 2 3 4 5 6 7";;
    esac
}

queues()
{
    out="queues "
    for tc in $(seq 0 $(($1 - 1))); do
	out="$out 1@$tc"
    done

    echo "$out"
}

set $(ip -j -d link show | jq -r '.[] | .ifname, .num_tx_queues')
while [ "$1" ]; do
    iface="$1"
    txqs="$2"
    shift 2

    [ $(/usr/libexec/infix/has-quirk "broken-mqprio" "$iface") = "true" ] && echo "Skipping $iface, does not support mqprio" && continue
    [ $txqs -lt 2 ] && continue
    [ $txqs -gt 8 ] && txqs=8

    output=$(tc qdisc add dev $iface root mqprio hw 1 \
		num_tc $txqs $(map $txqs) $(queues $txqs) 2>&1) || true
    if echo "$output" | grep -q "does not support hardware offload"; then
        echo "Skipping $iface, hardware offload not supported."
    elif [ -n "$output" ]; then
	echo "$output"
    fi
done
