AT_BANNER([PMD Auto Load Balance])

m4_divert_push([PREPARE_TESTS])

get_log_next_line_num () {
    LINENUM=$(($(cat ovs-vswitchd.log | wc -l | tr -d [[:blank:]])+1))
}

m4_divert_pop([PREPARE_TESTS])

m4_define([DUMMY_NUMA], [--dummy-numa="0,0"])

dnl CHECK_ALB_PARAM([param], [value], [+line])
dnl
dnl Waits for ALB logs for 'param' in logs and checks if value matches
dnl 'value'. Checking starts from line number 'line' in ovs-vswithd.log.
m4_define([CHECK_ALB_PARAM], [
    line_st=$3
    if [[ -z "$line_st" ]]
    then
        line_st="+0"
    fi
    OVS_WAIT_UNTIL([tail -n $line_st ovs-vswitchd.log | grep "PMD auto load balance $1 set to"])
    AT_CHECK([tail -n $line_st ovs-vswitchd.log dnl
                | sed -n "s#.*\(PMD auto load balance $1 set to.*\)#\1#p" | tail -1], [0], [dnl
PMD auto load balance $1 set to $2
])
])

AT_SETUP([ALB - default state])
OVS_VSWITCHD_START
OVS_WAIT_UNTIL([grep "PMD auto load balance is disabled" ovs-vswitchd.log])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ALB - enable/disable])
OVS_VSWITCHD_START([add-port br0 p0 \
                    -- set Interface p0 type=dummy-pmd options:n_rxq=1 \
                    -- set Open_vSwitch . other_config:pmd-cpu-mask=1 \
                    -- set open_vswitch . other_config:pmd-auto-lb="true"],
                   [], [], [DUMMY_NUMA])
OVS_WAIT_UNTIL([grep "PMD auto load balance is enabled" ovs-vswitchd.log])

get_log_next_line_num
AT_CHECK([ovs-vsctl set open_vswitch . other_config:pmd-auto-lb="false"])
OVS_WAIT_UNTIL([tail -n +$LINENUM ovs-vswitchd.log | grep "PMD auto load balance is disabled"])

get_log_next_line_num
AT_CHECK([ovs-vsctl set open_vswitch . other_config:pmd-auto-lb="true"])
OVS_WAIT_UNTIL([tail -n +$LINENUM ovs-vswitchd.log | grep "PMD auto load balance is enabled"])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ALB - min num PMD/RxQ])
OVS_VSWITCHD_START([add-port br0 p0 \
                    -- set Interface p0 type=dummy-pmd options:n_rxq=2 \
                    -- set Open_vSwitch . other_config:pmd-cpu-mask=1 \
                    -- set open_vswitch . other_config:pmd-auto-lb="true" \
                    -- set open_vswitch . other_config:pmd-auto-lb-load-threshold=0],
                   [], [], [DUMMY_NUMA])
OVS_WAIT_UNTIL([grep "PMD auto load balance is enabled" ovs-vswitchd.log])
AT_CHECK([ovs-appctl vlog/set dpif_netdev:dbg])

# 1 pmds 2 rxqs
get_log_next_line_num
ovs-appctl time/warp 600000 10000
OVS_WAIT_UNTIL([tail -n +$LINENUM ovs-vswitchd.log | grep "PMD auto load balance nothing to do, not enough non-isolated PMDs or RxQs."])

# 2 pmds 2 rxq
get_log_next_line_num
AT_CHECK([ovs-vsctl set Open_vSwitch . other_config:pmd-cpu-mask=0x3])
OVS_WAIT_UNTIL([tail -n +$LINENUM ovs-vswitchd.log | grep "There are 2 pmd threads on numa node"])
ovs-appctl time/warp 600000 10000
OVS_WAIT_UNTIL([tail -n +$LINENUM ovs-vswitchd.log | grep "PMD auto load balance nothing to do, not enough non-isolated PMDs or RxQs."])

# 2 pmds 3 rxqs
get_log_next_line_num
AT_CHECK([ovs-vsctl set interface p0 options:n_rxq=3])
ovs-appctl time/warp 600000 10000
OVS_WAIT_UNTIL([tail -n +$LINENUM ovs-vswitchd.log | grep "PMD auto load balance performing dry run."])

# 1 pmds 3 rxqs
get_log_next_line_num
AT_CHECK([ovs-vsctl set Open_vSwitch . other_config:pmd-cpu-mask=0x1])
OVS_WAIT_UNTIL([tail -n +$LINENUM ovs-vswitchd.log | grep "There are 1 pmd threads on numa node"])
ovs-appctl time/warp 600000 10000
OVS_WAIT_UNTIL([tail -n +$LINENUM ovs-vswitchd.log | grep "PMD auto load balance nothing to do, not enough non-isolated PMDs or RxQs."])

# Same config as last time
get_log_next_line_num
ovs-appctl time/warp 600000 10000
OVS_WAIT_UNTIL([tail -n +$LINENUM ovs-vswitchd.log | grep "PMD auto load balance nothing to do, no configuration changes since last check."])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ALB - cross-numa])
OVS_VSWITCHD_START([add-port br0 p0 \
                    -- set Interface p0 type=dummy-pmd options:n_rxq=4 \
                    -- set Interface p0 options:numa_id=0 \
                    -- set Open_vSwitch . other_config:pmd-cpu-mask=0x3 \
                    -- set open_vswitch . other_config:pmd-rxq-assign=group \
                    -- set open_vswitch . other_config:pmd-rxq-isolate=false \
                    -- set open_vswitch . other_config:pmd-auto-lb="true" \
                    -- set open_vswitch . other_config:pmd-auto-lb-load-threshold=0],
                   [], [], [--dummy-numa 1,2,1,2])
OVS_WAIT_UNTIL([grep "PMD auto load balance is enabled" ovs-vswitchd.log])
AT_CHECK([ovs-appctl vlog/set dpif_netdev:dbg])

# no pinned rxqs - cross-numa pmd could change
get_log_next_line_num
ovs-appctl time/warp 600000 10000
OVS_WAIT_UNTIL([tail -n +$LINENUM ovs-vswitchd.log | grep "PMD auto load balance performing dry run."])
OVS_WAIT_UNTIL([tail -n +$LINENUM ovs-vswitchd.log | grep "PMD auto load balance detected cross-numa polling"])

# all pinned rxqs - cross-numa pmd will not change
AT_CHECK([ovs-vsctl set Interface p0 other_config:pmd-rxq-affinity='0:0,1:0,2:1,3:1'])
get_log_next_line_num
ovs-appctl time/warp 600000 10000
OVS_WAIT_UNTIL([tail -n +$LINENUM ovs-vswitchd.log | grep "PMD auto load balance performing dry run."])
OVS_WAIT_UNTIL([tail -n +$LINENUM ovs-vswitchd.log | grep "Variance improvement 0%."])

# mix of pinned (non-isolated) and non-pinned rxqs - cross-numa pmd could change
AT_CHECK([ovs-vsctl remove Interface p0 other_config pmd-rxq-affinity])
AT_CHECK([ovs-vsctl set Interface p0 other_config:pmd-rxq-affinity='0:0,1:0,2:1'])
get_log_next_line_num
ovs-appctl time/warp 600000 10000
OVS_WAIT_UNTIL([tail -n +$LINENUM ovs-vswitchd.log | grep "PMD auto load balance performing dry run."])
OVS_WAIT_UNTIL([tail -n +$LINENUM ovs-vswitchd.log | grep "PMD auto load balance detected cross-numa polling"])

# mix of pinned (isolated) and non-pinned rxqs - cross-numa pmd could change
AT_CHECK([ovs-vsctl set Open_vSwitch . other_config:pmd-cpu-mask=0xf])
AT_CHECK([ovs-vsctl set Interface p0 options:n_rxq=6])
AT_CHECK([ovs-vsctl set Open_vSwitch . other_config:pmd-rxq-isolate=true])
get_log_next_line_num
ovs-appctl time/warp 600000 10000
OVS_WAIT_UNTIL([tail -n +$LINENUM ovs-vswitchd.log | grep "PMD auto load balance performing dry run."])
OVS_WAIT_UNTIL([tail -n +$LINENUM ovs-vswitchd.log | grep "PMD auto load balance detected cross-numa polling"])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ALB - PMD/RxQ assignment type])
OVS_VSWITCHD_START([add-port br0 p0 \
                    -- set Interface p0 type=dummy-pmd options:n_rxq=3 \
                    -- set Open_vSwitch . other_config:pmd-cpu-mask=3 \
                    -- set open_vswitch . other_config:pmd-auto-lb="true" \
                    -- set open_vswitch . other_config:pmd-auto-lb-load-threshold=0],
                   [], [], [DUMMY_NUMA])
OVS_WAIT_UNTIL([grep "PMD auto load balance is enabled" ovs-vswitchd.log])

# Change assignment type
get_log_next_line_num
AT_CHECK([ovs-vsctl set Open_vSwitch . other_config:pmd-rxq-assign=roundrobin])
OVS_WAIT_UNTIL([tail -n +$LINENUM ovs-vswitchd.log | grep "mode changed to: 'roundrobin'"])

get_log_next_line_num
AT_CHECK([ovs-vsctl set open_vswitch . other_config:pmd-auto-lb="false"])
OVS_WAIT_UNTIL([tail -n +$LINENUM ovs-vswitchd.log | grep "PMD auto load balance is disabled"])
get_log_next_line_num
AT_CHECK([ovs-vsctl set open_vswitch . other_config:pmd-auto-lb="true"])
OVS_WAIT_UNTIL([tail -n +$LINENUM ovs-vswitchd.log | grep "PMD auto load balance is enabled"])

# Change back assignment type
get_log_next_line_num
AT_CHECK([ovs-vsctl set Open_vSwitch . other_config:pmd-rxq-assign=cycles])
OVS_WAIT_UNTIL([tail -n +$LINENUM ovs-vswitchd.log | grep "mode changed to: 'cycles'"])

get_log_next_line_num
AT_CHECK([ovs-vsctl set open_vswitch . other_config:pmd-auto-lb="false"])
OVS_WAIT_UNTIL([tail -n +$LINENUM ovs-vswitchd.log | grep "PMD auto load balance is disabled"])
get_log_next_line_num
AT_CHECK([ovs-vsctl set open_vswitch . other_config:pmd-auto-lb="true"])
OVS_WAIT_UNTIL([tail -n +$LINENUM ovs-vswitchd.log | grep "PMD auto load balance is enabled"])

get_log_next_line_num
AT_CHECK([ovs-vsctl set Open_vSwitch . other_config:pmd-rxq-assign=group])
OVS_WAIT_UNTIL([tail -n +$LINENUM ovs-vswitchd.log | grep "mode changed to: 'group'"])

get_log_next_line_num
AT_CHECK([ovs-vsctl set open_vswitch . other_config:pmd-auto-lb="false"])
OVS_WAIT_UNTIL([tail -n +$LINENUM ovs-vswitchd.log | grep "PMD auto load balance is disabled"])
get_log_next_line_num
AT_CHECK([ovs-vsctl set open_vswitch . other_config:pmd-auto-lb="true"])
OVS_WAIT_UNTIL([tail -n +$LINENUM ovs-vswitchd.log | grep "PMD auto load balance is enabled"])

# Enable debug and test dryrun config checks
AT_CHECK([ovs-appctl vlog/set dpif_netdev:dbg])

# Just to be sure it is still set to group
AT_CHECK([ovs-vsctl set Open_vSwitch . other_config:pmd-rxq-assign=group])
get_log_next_line_num
ovs-appctl time/warp 600000 10000
OVS_WAIT_UNTIL([tail -n +$LINENUM ovs-vswitchd.log | grep "PMD auto load balance performing dry run."])

get_log_next_line_num
AT_CHECK([ovs-vsctl set Open_vSwitch . other_config:pmd-rxq-assign=cycles])
OVS_WAIT_UNTIL([tail -n +$LINENUM ovs-vswitchd.log | grep "mode changed to: 'cycles'"])
ovs-appctl time/warp 600000 10000
OVS_WAIT_UNTIL([tail -n +$LINENUM ovs-vswitchd.log | grep "PMD auto load balance performing dry run."])

get_log_next_line_num
AT_CHECK([ovs-vsctl set Open_vSwitch . other_config:pmd-rxq-assign=roundrobin])
OVS_WAIT_UNTIL([tail -n +$LINENUM ovs-vswitchd.log | grep "mode changed to: 'roundrobin'"])
ovs-appctl time/warp 600000 10000
OVS_WAIT_UNTIL([tail -n +$LINENUM ovs-vswitchd.log | grep "PMD auto load balance nothing to do, pmd-rxq-assign=roundrobin assignment type configured."])

get_log_next_line_num
AT_CHECK([ovs-vsctl set Open_vSwitch . other_config:pmd-rxq-assign=group])
OVS_WAIT_UNTIL([tail -n +$LINENUM ovs-vswitchd.log | grep "mode changed to: 'group'"])
ovs-appctl time/warp 600000 10000
OVS_WAIT_UNTIL([tail -n +$LINENUM ovs-vswitchd.log | grep "PMD auto load balance performing dry run."])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ALB - interval param])
OVS_VSWITCHD_START
OVS_WAIT_UNTIL([grep "PMD auto load balance is disabled" ovs-vswitchd.log])

# Check default
CHECK_ALB_PARAM([interval], [1 mins], [])

# Set new value
get_log_next_line_num
AT_CHECK([ovs-vsctl set open_vswitch . other_config:pmd-auto-lb-rebal-interval="10"])
CHECK_ALB_PARAM([interval], [10 mins], [+$LINENUM])

# Set min value
get_log_next_line_num
AT_CHECK([ovs-vsctl set open_vswitch . other_config:pmd-auto-lb-rebal-interval="1"])
CHECK_ALB_PARAM([interval], [1 mins], [+$LINENUM])

# Set max value
get_log_next_line_num
AT_CHECK([ovs-vsctl set open_vswitch . other_config:pmd-auto-lb-rebal-interval="20000"])
CHECK_ALB_PARAM([interval], [20000 mins], [+$LINENUM])

# Set below min value
get_log_next_line_num
AT_CHECK([ovs-vsctl set open_vswitch . other_config:pmd-auto-lb-rebal-interval="0"])
CHECK_ALB_PARAM([interval], [1 mins], [+$LINENUM])

# No check for above max as it is only a documented max value and not a hard limit

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ALB - improvement param])
OVS_VSWITCHD_START
OVS_WAIT_UNTIL([grep "PMD auto load balance is disabled" ovs-vswitchd.log])

# Check default
CHECK_ALB_PARAM([improvement threshold], [25%], [])

# Set new value
get_log_next_line_num
AT_CHECK([ovs-vsctl set open_vswitch . other_config:pmd-auto-lb-improvement-threshold=60])
CHECK_ALB_PARAM([improvement threshold], [60%], [+$LINENUM])

# Set min value
get_log_next_line_num
AT_CHECK([ovs-vsctl set open_vswitch . other_config:pmd-auto-lb-improvement-threshold=0])
CHECK_ALB_PARAM([improvement threshold], [0%], [+$LINENUM])

# Set below min value
get_log_next_line_num
AT_CHECK([ovs-vsctl set open_vswitch . other_config:pmd-auto-lb-improvement-threshold=-1])
CHECK_ALB_PARAM([improvement threshold], [25%], [+$LINENUM])

# Set max value
get_log_next_line_num
AT_CHECK([ovs-vsctl set open_vswitch . other_config:pmd-auto-lb-improvement-threshold=100])
CHECK_ALB_PARAM([improvement threshold], [100%], [+$LINENUM])

# Set above max value
get_log_next_line_num
AT_CHECK([ovs-vsctl set open_vswitch . other_config:pmd-auto-lb-improvement-threshold=101])
CHECK_ALB_PARAM([improvement threshold], [25%], [+$LINENUM])

OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([ALB - load param])
OVS_VSWITCHD_START
OVS_WAIT_UNTIL([grep "PMD auto load balance is disabled" ovs-vswitchd.log])

# Check default
CHECK_ALB_PARAM([load threshold], [95%], [])

# Set to new value
get_log_next_line_num
AT_CHECK([ovs-vsctl set open_vswitch . other_config:pmd-auto-lb-load-threshold=70])
CHECK_ALB_PARAM([load threshold], [70%], [+$LINENUM])

# Set to min value
get_log_next_line_num
AT_CHECK([ovs-vsctl set open_vswitch . other_config:pmd-auto-lb-load-threshold=0])
CHECK_ALB_PARAM([load threshold], [0%], [+$LINENUM])

# Set to below min
get_log_next_line_num
AT_CHECK([ovs-vsctl set open_vswitch . other_config:pmd-auto-lb-load-threshold=-1])
CHECK_ALB_PARAM([load threshold], [95%], [+$LINENUM])

# Set to max
get_log_next_line_num
AT_CHECK([ovs-vsctl set open_vswitch . other_config:pmd-auto-lb-load-threshold=100])
CHECK_ALB_PARAM([load threshold], [100%], [+$LINENUM])

# Set above max value
get_log_next_line_num
AT_CHECK([ovs-vsctl set open_vswitch . other_config:pmd-auto-lb-load-threshold=101])
CHECK_ALB_PARAM([load threshold], [95%], [+$LINENUM])

OVS_VSWITCHD_STOP
AT_CLEANUP
