diff --git a/.gitlab/tests/cram/scripts/wifi.sh b/.gitlab/tests/cram/scripts/wifi.sh index 534d1b0465..79d2ff7677 100644 --- a/.gitlab/tests/cram/scripts/wifi.sh +++ b/.gitlab/tests/cram/scripts/wifi.sh @@ -2,6 +2,20 @@ # 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 # In : AccessPoint object index # Out : "enabled" if success, empty otherwise @@ -131,3 +145,141 @@ get_hapd_config() { ;; 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" +} diff --git a/.gitlab/tests/cram/wifi/wifi-apmld.t b/.gitlab/tests/cram/wifi/wifi-apmld.t new file mode 100644 index 0000000000..7b716fa9e0 --- /dev/null +++ b/.gitlab/tests/cram/wifi/wifi-apmld.t @@ -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!" diff --git a/.gitlab/tests/cram/wnc-freedom/103-apmld.t b/.gitlab/tests/cram/wnc-freedom/103-apmld.t new file mode 120000 index 0000000000..60987613d6 --- /dev/null +++ b/.gitlab/tests/cram/wnc-freedom/103-apmld.t @@ -0,0 +1 @@ +../wifi/wifi-apmld.t \ No newline at end of file