ci: cram: add cram test for pwhm native APMLD feature

Add cram test to cover APMLD feature.
Actually only Freedom platform is supporting it.

References: FEAT-124
Closes: PPM-3347
Signed-off-by: Houssem Dafdouf <houssem.dafdouf_ext@softathome.com>
This commit is contained in:
Houssem Dafdouf 2025-11-24 16:02:47 +01:00 committed by Hela Saadani
parent 4b919347a3
commit 0dca07a46e
3 changed files with 495 additions and 0 deletions

View File

@ -2,6 +2,20 @@
# Common WiFi helpers: # Common WiFi helpers:
# #
# set/get wifi datamodel
# In : path under 'WiFi.'
# Out : print ba-cli output
wifi_dm() {
local path="$1"
local obj_name
# read object name
obj_name=$(printf '%s\n' "$path" | awk -F. '{print $NF}' | cut -d'=' -f1)
# remove any trailing '?' from next grep
obj_name=${obj_name%%\?*}
R logger -t cram "set_wifi_dm: command WiFi.$path object ${obj_name}"
R "ba-cli 'WiFi.${path}'" | grep "${obj_name}=" | sed '/^$/d' | grep -v '>' | sort
}
# Enable AccessPoints # Enable AccessPoints
# In : AccessPoint object index # In : AccessPoint object index
# Out : "enabled" if success, empty otherwise # Out : "enabled" if success, empty otherwise
@ -131,3 +145,141 @@ get_hapd_config() {
;; ;;
esac esac
} }
#
# APMLD helpers
#
# Print MLDUnit of private MLD based on default SSID (prplOS)
# In : N/A
# Out : MLDUNit
get_private_mldunit() {
R 'ba-cli -j -l "WiFi.SSID.[SSID==\"prplOS\"].MLDUnit?" | jsonfilter -e @[0]'[*].MLDUnit'' | head -n 1
}
# Print MLDUnit of private MLD based on default SSID (prplOS-guest)
# In : N/A
# Out : MLDUnit
get_guest_mldunit() {
R 'ba-cli -j -l "WiFi.SSID.[SSID==\"prplOS-guest\"].MLDUnit?" | jsonfilter -e @[0]'[*].MLDUnit'' | head -n 1
}
# validate mac address
is_valid_mac() {
printf '%s\n' "$1" | grep -Eq '^([0-9A-Fa-f]{2}[:\-]){5}[0-9A-Fa-f]{2}$'
}
# Print APMLD MACAddress
# In : MLDID (MLDUnit)
# Out : APMLD MACAddress. If an APMLD matches the MLDID with empty MACAddress return an error message
get_apmld_mac_from_dm() {
mac=$(R "ba-cli -l -j 'WiFi.APMLD.[MLDID == ${1}].MLDMACAddress?' | jsonfilter -e @[0]'[*].MLDMACAddress' | strings")
if ! is_valid_mac "$mac"; then
echo "not_found"
R logger -t cram "get_apmld_mac_from_dm: MLDMACAddress $mac of MLD ${1} not found"
#R "iw dev > /tmp/$(R date +'%Y_%m_%d_%H_%M_%S')_aplmd_iw_out.txt"
else
echo "$mac"
fi
}
# Print intefrace name from a MACAddress
# In : wlan MAC address
# Out : interface name
get_interface_name() {
R "ba-cli -l -j 'WiFi.SSID.[MACAddress==\"${1}\"].Name?' | jsonfilter -e @[0]'[*].Name' || echo 'Could not find SSID'"
}
# Print link number of an interface
# In : wlan interface
# Out : link number
get_link_info() {
R logger -t cram "get_link_info: interface ${1}"
R "iw dev ${1} info" | grep -e addr -e channe | sed 's/^[ \t]*//' | sort | uniq
}
# print main link interface name from MAC address
# In : interface MAC address
# Out : main link interface name
get_main_link_itf () {
local found=0
local ifaces
local mac=$1
ifaces=$(R ba-cli -l "WiFi.SSID.*.Name?0 | strings")
for iface in $ifaces; do
info=$(R iw dev "$iface" info 2>/dev/null)
if echo "$info" | grep -i ${mac} -B2 | grep -q "link"; then
R logger -t cram "MAC $1 found in main link interface $iface"
echo "$iface"
found=1
break
fi
done
if [ "$found" -eq 0 ]; then
R logger -t cram "MAC $1 not associated to any main link"
echo "MAC $1 not associated to any main link"
fi
}
# print link number from iw output
# In : APMLD index (ie MLDID)
# Out : link number from iw output
iw_affliated_link_info_from_mldid() {
# Detect main link interface
mac_address=$(get_apmld_mac_from_dm "$1")
if [ -z "$mac_address" ]; then
R logger -t cram "iw_affliated_link_info_from_mldid: empty mac_address !"
else
R logger -t cram "iw_affliated_link_info_from_mldid: mac_address = $mac_address"
itf_name=$(get_main_link_itf "$mac_address")
get_link_info "$itf_name"
fi
}
# print MAC addresses list of link interfaces from iw output
# In : main link interface name
# Out : LinkID and MAC addresses list of affiliated interfaces (format : link N addr xx:xx:xx:xx:xx)
iw_get_main_link_mac_list() {
local iface=$1
R logger -t cram "get_main_link_mac_list $iface"
R "iw dev $iface info" | grep link -A3 | grep -e 'addr ' -e link | sed -nE 'N;s/.*link ([0-9]+):\n[[:space:]]*addr ([0-9a-fA-F:]+)/link \1 addr \2/p' | LC_ALL=C sort
}
# print MAC addresses list of link interfaces from iw output
# In : MLDID
# Out : MAC addresses list of link interfaces
iw_affilated_mac_list_from_mldid() {
# Detect main link interface
mac_address=$(get_apmld_mac_from_dm "$1") && R logger -t cram "mac_address = $mac_address"
if [ -z "$mac_address" ]; then
R logger -t cram "iw_affliated_mac_from_mldid: empty mac_address !"
else
itf_name=$(get_main_link_itf "$mac_address")
iw_get_main_link_mac_list "$itf_name"
fi
}
# print MAC addresses list of link interfaces from WiFi DM
# In : MLDID
# Out : LinkID and MAC addresses list of affiliated interfaces (format : link N addr xx:xx:xx:xx:xx)
dm_affilated_mac_list_from_mldid() {
local output=""
local idx=1
local mld_id="$1"
local aff_ap_nb
local bssid
local link_id
aff_ap_nb=$(R "ba-cli -l 'WiFi.APMLD.[ MLDID == ${mld_id} ].AffiliatedAPNumberOfEntries?'" | sed '/^$/d')
while [ "$idx" -le "$aff_ap_nb" ]; do
bssid=$(R "ba-cli -j -l 'WiFi.APMLD.[ MLDID == ${mld_id} ].AffiliatedAP.${idx}.BSSID?' | jsonfilter -e @[0]'[*].BSSID'")
link_id=$(R "ba-cli -j -l 'WiFi.APMLD.[ MLDID == ${mld_id} ].AffiliatedAP.${idx}.LinkID?' | jsonfilter -e @[0]'[*].LinkID'")
output="link ${link_id} addr ${bssid}\n${output}"
idx=$((idx + 1))
done
printf "%b" "$output"
}

View File

@ -0,0 +1,342 @@
Create R alias:
$ alias R="${CRAM_REMOTE_COMMAND:-}"
$ . "${TESTDIR}/../scripts/wifi.sh"
$ R logger -t cram "Starting APMLD test ..."
Stop prplMesh:
$ R "/etc/init.d/prplmesh stop > /dev/null 2>&1"
Check default configuration:
$ R logger -t cram "Check default configuration"
$ wifi_dm "APMLDMaxLinks?"
WiFi.APMLDMaxLinks=\d+ (re)
$ R logger -t cram "Check default configuration"
$ wifi_dm "MaxNumMLDs?"
WiFi.MaxNumMLDs=\d+ (re)
$ wifi_dm "APMLD.?" | LC_ALL=C sort
WiFi.APMLD.1.APMLDConfig.EMLMREnabled=-1
WiFi.APMLD.1.APMLDConfig.EMLSREnabled=-1
WiFi.APMLD.1.APMLDConfig.NSTREnabled=-1
WiFi.APMLD.1.APMLDConfig.STREnabled=-1
WiFi.APMLD.1.AffiliatedAPNumberOfEntries=0
WiFi.APMLD.1.MLDID=0
WiFi.APMLD.1.MLDMACAddress=""
WiFi.APMLD.2.APMLDConfig.EMLMREnabled=-1
WiFi.APMLD.2.APMLDConfig.EMLSREnabled=-1
WiFi.APMLD.2.APMLDConfig.NSTREnabled=-1
WiFi.APMLD.2.APMLDConfig.STREnabled=-1
WiFi.APMLD.2.AffiliatedAPNumberOfEntries=0
WiFi.APMLD.2.MLDID=1
WiFi.APMLD.2.MLDMACAddress=""
Configure radio and enable all AccessPoints:
$ R logger -t cram "Enable all vaps"
$ wifi_dm "Radio.*.AutoChannelEnable=0"
WiFi.Radio.1.AutoChannelEnable=0
WiFi.Radio.2.AutoChannelEnable=0
WiFi.Radio.3.AutoChannelEnable=0
$ wifi_dm "Radio.[OperatingFrequencyBand==\"2.4GHz\"].Channel=1"
WiFi.Radio.\d+.Channel=1 (re)
$ wifi_dm "Radio.[OperatingFrequencyBand==\"5GHz\"].Channel=36"
WiFi.Radio.\d+.Channel=36 (re)
$ wifi_dm "Radio.[OperatingFrequencyBand==\"6GHz\"].Channel=37"
WiFi.Radio.\d+.Channel=37 (re)
$ wifi_dm "AccessPoint.*.Enable=1"
WiFi.AccessPoint.1.Enable=1
WiFi.AccessPoint.2.Enable=1
WiFi.AccessPoint.3.Enable=1
WiFi.AccessPoint.4.Enable=1
WiFi.AccessPoint.5.Enable=1
WiFi.AccessPoint.6.Enable=1
WiFi.AccessPoint.7.Enable=1
WiFi.AccessPoint.8.Enable=1
WiFi.AccessPoint.9.Enable=1
$ sleep 10
Check AccessPoints status:
$ wifi_dm "AccessPoint.*.Status?0"
WiFi.AccessPoint.1.Status="Enabled"
WiFi.AccessPoint.2.Status="Enabled"
WiFi.AccessPoint.3.Status="Enabled"
WiFi.AccessPoint.4.Status="Enabled"
WiFi.AccessPoint.5.Status="Enabled"
WiFi.AccessPoint.6.Status="Enabled"
WiFi.AccessPoint.7.Status="Enabled"
WiFi.AccessPoint.8.Status="Enabled"
WiFi.AccessPoint.9.Status="Enabled"
Read private and guest MLDUnit:
$ private_mldunit=$(get_private_mldunit)
$ guest_mldunit=$(get_guest_mldunit)
$ test_mldunit=12
Check private APMLD number of links:
$ iw_affliated_link_info_from_mldid ${private_mldunit}
addr ([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2} (re)
addr ([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2} (re)
addr ([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2} (re)
channel 1 .* (re)
channel 36 .* (re)
channel 37 .* (re)
Check APMLD 2 number (guest vaps) of links:
$ iw_affliated_link_info_from_mldid ${guest_mldunit}
addr ([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2} (re)
addr ([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2} (re)
addr ([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2} (re)
channel 1 .* (re)
channel 36 .* (re)
channel 37 .* (re)
Read all link IDs (3 links per MLD):
(LinkID values do not matter, uniqueness will be checked implicitly later)
$ wifi_dm "APMLD.*.AffiliatedAP.*.LinkID?"
WiFi.APMLD.1.AffiliatedAP.1.LinkID=\d+ (re)
WiFi.APMLD.1.AffiliatedAP.2.LinkID=\d+ (re)
WiFi.APMLD.1.AffiliatedAP.3.LinkID=\d+ (re)
WiFi.APMLD.2.AffiliatedAP.1.LinkID=\d+ (re)
WiFi.APMLD.2.AffiliatedAP.2.LinkID=\d+ (re)
WiFi.APMLD.2.AffiliatedAP.3.LinkID=\d+ (re)
Read AffiliatedAP MAC addresses from iw (private):
$ iw_affilated_mac_list=$(iw_affilated_mac_list_from_mldid ${private_mldunit})
$ echo "$iw_affilated_mac_list"
link \d+ addr ([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2} (re)
link \d+ addr ([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2} (re)
link \d+ addr ([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2} (re)
Read AffiliatedAP MAC addresses from pwhm (private):
$ dm_affilated_mac_list=$(dm_affilated_mac_list_from_mldid ${private_mldunit})
$ echo "$dm_affilated_mac_list"
link \d+ addr ([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2} (re)
link \d+ addr ([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2} (re)
link \d+ addr ([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2} (re)
Cross check Affilated MACs addresses (private):
$ merged_list=$(printf "%s\n%s\n" "$dm_affilated_mac_list" "$iw_affilated_mac_list" | tr '[:upper:]' '[:lower:]' | sort -u)
$ echo "$merged_list" | uniq
link \d+ addr ([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2} (re)
link \d+ addr ([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2} (re)
link \d+ addr ([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2} (re)
Read AffiliatedAP MAC addresses from iw (guest):
$ iw_affilated_mac_list=$(iw_affilated_mac_list_from_mldid ${guest_mldunit})
$ echo "$iw_affilated_mac_list"
link \d+ addr ([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2} (re)
link \d+ addr ([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2} (re)
link \d+ addr ([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2} (re)
Read AffiliatedAP MAC addresses from pwhm (guest):
$ dm_affilated_mac_list=$(dm_affilated_mac_list_from_mldid ${guest_mldunit})
$ echo "$dm_affilated_mac_list"
link \d+ addr ([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2} (re)
link \d+ addr ([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2} (re)
link \d+ addr ([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2} (re)
Cross check Affilated MACs addresses (guest):
$ merged_list=$(printf "%s\n%s\n" "$dm_affilated_mac_list" "$iw_affilated_mac_list" | tr '[:upper:]' '[:lower:]' | sort -u)
$ echo "$merged_list" | uniq
link \d+ addr ([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2} (re)
link \d+ addr ([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2} (re)
link \d+ addr ([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2} (re)
Remove AP1 (private) from its APMLD:
$ R logger -t cram "Remove AP1 from its APMLD"
$ wifi_dm "AccessPoint.1.SSIDReference+.MLDUnit=-1"
Device.WiFi.SSID.\d+.MLDUnit=-1 (re)
$ sleep 10
Check private APMLD number of links:
$ iw_affliated_link_info_from_mldid ${private_mldunit}
addr ([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2} (re)
addr ([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2} (re)
channel 36 .* (re)
channel 37 .* (re)
Read AffiliatedAP MAC addresses:
$ iw_affilated_mac_list_from_mldid ${private_mldunit}
link \d+ addr ([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2} (re)
link \d+ addr ([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2} (re)
Check link id of private MLD:
$ wifi_dm "APMLD.[ MLDID == ${private_mldunit} ].AffiliatedAP.*.LinkID?"
WiFi.APMLD.1.AffiliatedAP.1.LinkID=0
WiFi.APMLD.1.AffiliatedAP.2.LinkID=1
Move back AP1 to its previous APMLD:
$ R logger -t cram "Move back AP1 to its previous APMLD"
$ wifi_dm "AccessPoint.1.SSIDReference+.MLDUnit=${private_mldunit}"
Device.WiFi.SSID.\d+.MLDUnit=0 (re)
$ sleep 10
Check private APMLD number of links:
$ iw_affliated_link_info_from_mldid ${private_mldunit}
addr ([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2} (re)
addr ([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2} (re)
addr ([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2} (re)
channel 1 .* (re)
channel 36 .* (re)
channel 37 .* (re)
Move AP1 to a new APMLD:
$ R logger -t cram "Move AP1 to a new APMLD"
$ wifi_dm "AccessPoint.1.SSIDReference+.MLDUnit=${test_mldunit}"
Device.WiFi.SSID.1.MLDUnit=12
$ sleep 10
Check private APMLD number of links:
$ iw_affliated_link_info_from_mldid ${private_mldunit}
addr ([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2} (re)
addr ([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2} (re)
channel 36 .* (re)
channel 37 .* (re)
Check the new APMLD 3 number of links:
$ iw_affliated_link_info_from_mldid ${test_mldunit}
addr ([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2} (re)
channel 1 .* (re)
Read AffiliatedAP MAC addresses:
$ iw_affilated_mac_list_from_mldid ${private_mldunit}
link \d+ addr ([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2} (re)
link \d+ addr ([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2} (re)
$ iw_affilated_mac_list_from_mldid ${test_mldunit}
link \d+ addr ([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2} (re)
Move back AP1 to its APMLD
$ R logger -t cram "Move back AP1 to its previous APMLD"
$ wifi_dm "AccessPoint.1.SSIDReference+.MLDUnit=${private_mldunit}"
Device.WiFi.SSID.1.MLDUnit=0
$ sleep 10
Check private APMLD number of links:
$ iw_affliated_link_info_from_mldid ${private_mldunit}
addr ([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2} (re)
addr ([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2} (re)
addr ([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2} (re)
channel 1 .* (re)
channel 36 .* (re)
channel 37 .* (re)
Check if new APMLD was cleared:
$ get_apmld_mac_from_dm ${test_mldunit}
not_found
Disable guest vaps:
$ R logger -t cram "Disable guest vaps"
$ wifi_dm "AccessPoint.[DefaultDeviceType==\"Guest\"].Enable=0"
WiFi.AccessPoint.\d+.Enable=0 (re)
WiFi.AccessPoint.\d+.Enable=0 (re)
WiFi.AccessPoint.\d+.Enable=0 (re)
$ sleep 10
$ wifi_dm "AccessPoint.[DefaultDeviceType==\"Guest\"].Status?"
WiFi.AccessPoint.\d+.Status="Disabled" (re)
WiFi.AccessPoint.\d+.Status="Disabled" (re)
WiFi.AccessPoint.\d+.Status="Disabled" (re)
Check if guest apmld is cleared:
$ wifi_dm "APMLD.2.?"
WiFi.APMLD.2.APMLDConfig.EMLMREnabled=-1
WiFi.APMLD.2.APMLDConfig.EMLSREnabled=-1
WiFi.APMLD.2.APMLDConfig.NSTREnabled=-1
WiFi.APMLD.2.APMLDConfig.STREnabled=-1
WiFi.APMLD.2.AffiliatedAPNumberOfEntries=0
WiFi.APMLD.2.MLDID=1
WiFi.APMLD.2.MLDMACAddress=""
Disable all AP:
$ R logger -t cram "Disable all vaps"
$ wifi_dm "AccessPoint.*.Enable=0"
WiFi.AccessPoint.1.Enable=0
WiFi.AccessPoint.2.Enable=0
WiFi.AccessPoint.3.Enable=0
WiFi.AccessPoint.4.Enable=0
WiFi.AccessPoint.5.Enable=0
WiFi.AccessPoint.6.Enable=0
WiFi.AccessPoint.7.Enable=0
WiFi.AccessPoint.8.Enable=0
WiFi.AccessPoint.9.Enable=0
$ sleep 10
Check AccessPoints status:
$ wifi_dm "AccessPoint.*.Status?0"
WiFi.AccessPoint.1.Status="Disabled"
WiFi.AccessPoint.2.Status="Disabled"
WiFi.AccessPoint.3.Status="Disabled"
WiFi.AccessPoint.4.Status="Disabled"
WiFi.AccessPoint.5.Status="Disabled"
WiFi.AccessPoint.6.Status="Disabled"
WiFi.AccessPoint.7.Status="Disabled"
WiFi.AccessPoint.8.Status="Disabled"
WiFi.AccessPoint.9.Status="Disabled"
Check if private apmld is cleared:
$ sleep 10
$ wifi_dm "APMLD.1.?"
WiFi.APMLD.1.APMLDConfig.EMLMREnabled=-1
WiFi.APMLD.1.APMLDConfig.EMLSREnabled=-1
WiFi.APMLD.1.APMLDConfig.NSTREnabled=-1
WiFi.APMLD.1.APMLDConfig.STREnabled=-1
WiFi.APMLD.1.AffiliatedAPNumberOfEntries=0
WiFi.APMLD.1.MLDID=0
WiFi.APMLD.1.MLDMACAddress=""
Resume prplMesh:
$ R "/etc/init.d/prplmesh start 2>&1 > /dev/null"
$ sleep 10
$ R logger -t cram "Test finished!"

View File

@ -0,0 +1 @@
../wifi/wifi-apmld.t