Files
WirelessNetworkingTechnologies/lab_3/task2.m
T
2026-05-22 19:16:08 +02:00

241 lines
6.7 KiB
Matlab

addpath("from_matlab_example");
rxFrame1 = trace1.iq(:);
rxFrame2 = trace2.iq(:);
rxFrame3 = trace3.iq(:);
rxFrame4 = trace4.iq(:);
beaconFrames1 = extractBeaconFrames(rxFrame1);
beaconFrames2 = extractBeaconFrames(rxFrame2);
beaconFrames3 = extractBeaconFrames(rxFrame3);
beaconFrames4 = extractBeaconFrames(rxFrame4);
% 1.
disp("Beacon Frame 1")
printBeaconTable(beaconFrames1);
disp("Beacon Frame 2")
printBeaconTable(beaconFrames2);
disp("Beacon Frame 3")
printBeaconTable(beaconFrames3);
disp("Beacon Frame 4")
printBeaconTable(beaconFrames4);
% 2.
%{
Address 1: used to announce the destination station, in a beacon frame its
FF:FF:FF:FF:FF:FF (meaning broadcast to all stations)
Address 2: used to remark the source device address of the frame,
the ap mac who sent the beacon is inserted
Address 3: used for the bssid of the device sending the beacon, means
usually address 2 equals address 3, when no virtual ap is used
Address 4: this field does not exists, after the seq ctrl the frame body
follows containing beacon data instead of an address, like
timestamp, beacon interval, capability info, ssid, potentially
the channel number, see the extracts from 2.1
%}
% 3.
%{
Downlink: AP -> Station
Address 1: MAC of the destination station
Address 2: MAC of the AP which transmits the frame
Address 3: MAC of the initial sender which has started the frame
Address 4: not used
Uplink: Station -> AP
Address 1: MAC of the AP that receives and potentially forwards the frame
Address 2: MAC of the sending station
Address 3: MAC of the final destination station
Address 4: not used
4 Address case: wireless bridge:
Address 1: MAC of the AP that should receive / transmit through the frame,
for example AP, bridge node, repeater or mesh node
Address 2: MAC of the transmitter (into the other network)
Address 3: MAC of the final destination
Address 4: MAC of the initial sender
%}
function beaconFrames = extractBeaconFrames(rxFrame)
beaconFrames = struct( ...
"SSID", {}, ...
"BSSID", {}, ...
"Offset", {}, ...
"MAC_Config", {}, ...
"Bits", {}, ...
"SNR_dB", {} ...
);
searchOffset = 0;
index = 1;
while searchOffset < length(rxFrame)
oldOffset = searchOffset;
[bitsData, decParams, searchOffset, res] = recoverOFDMBits(rxFrame, searchOffset);
if searchOffset <= oldOffset
searchOffset = oldOffset + 1;
end
if isempty(bitsData)
continue;
end
[cfgMAC, ~, decodeStatus] = wlanMPDUDecode(bitsData, SuppressWarnings=true);
if ~decodeStatus && matches(cfgMAC.FrameType, "Beacon")
if isempty(cfgMAC.ManagementConfig.SSID)
ssid = "Hidden";
else
ssid = string(cfgMAC.ManagementConfig.SSID);
end
if isfield(res, "PacketOffset")
beaconFrames(index).Offset = res.PacketOffset;
else
beaconFrames(index).Offset = oldOffset;
end
if isfield(res, "LLTFSNR")
beaconFrames(index).SNR_dB = res.LLTFSNR;
else
beaconFrames(index).SNR_dB = NaN;
end
beaconFrames(index).SSID = ssid;
beaconFrames(index).BSSID = string(cfgMAC.Address3);
beaconFrames(index).MAC_Config = cfgMAC;
beaconFrames(index).Bits = bitsData;
index = index + 1;
end
end
end
function printBeaconTable(beaconFrames)
beaconCount = numel(beaconFrames);
tableFormat = "%-20s %-18s %-10s %-8s %-8s %-8s %-12s %-8s %-80s\n";
if(beaconCount < 1)
disp("No valid beacons could be extracted")
return;
end
fprintf("\n");
fprintf(tableFormat, ...
"SSID", "BSSID", "Interval", "B. ch.", "Op. ch.", "SNR", "Vendor", "Std.", "Rates");
for i = 1 : beaconCount
mgmt = beaconFrames(i).MAC_Config.ManagementConfig;
ssid = string(beaconFrames(i).SSID);
bssid = toMACAddress(beaconFrames(i).BSSID);
interval = string(mgmt.BeaconInterval);
snr = sprintf("%.1f", beaconFrames(i).SNR_dB);
[bch, opch] = extractChannels(mgmt);
vendor = lookupVendor(beaconFrames(i).BSSID);
rates = getRates(mgmt);
std = getWifiStandard(mgmt);
fprintf(tableFormat, ...
ssid, bssid, interval, bch, opch, snr, vendor, std, rates);
end
fprintf("\n");
end
function mac = toMACAddress(mac)
mac = upper(string(mac));
if strlength(mac) ~= 12
return;
end
macChars = char(mac);
mac = string(sprintf("%s:%s:%s:%s:%s:%s", ...
macChars(1:2), ...
macChars(3:4), ...
macChars(5:6), ...
macChars(7:8), ...
macChars(9:10), ...
macChars(11:12)));
end
function rates = getRates(mgmt)
basicRates = string(mgmt.BasicRates);
additionalRates = string(mgmt.AdditionalRates);
if isempty(basicRates) && isempty(additionalRates)
rates = "-";
return;
end
basicRates = "[" + strjoin(basicRates, ", ") + "]";
rates = strjoin([basicRates, additionalRates], ", ");
end
function vendor = lookupVendor(bssid)
bssid = upper(string(bssid));
if strlength(bssid) < 6
vendor = "-";
return;
end
oui = extractBefore(bssid, 7);
switch oui
case { "C884A1", "5CE176" }
vendor = "Cisco";
case { "6466B3", "647002" }
vendor = "TP-Link";
otherwise
vendor = "Unknown";
end
end
function std = getWifiStandard(mgmt)
rates = [string(mgmt.BasicRates), string(mgmt.AdditionalRates)];
if any(contains(rates, ["6 Mbps", "9 Mbps", "12 Mbps", "18 Mbps", "24 Mbps", "36 Mbps", "48 Mbps", "54 Mbps"]))
std = "802.11g";
elseif any(contains(rates, ["1 Mbps", "2 Mbps", "5.5 Mbps", "11 Mbps"]))
std = "802.11b";
else
std = "Unknown";
end
end
function [b_ch, op_ch] = extractChannels(mgmt)
b_ch = "-";
op_ch = "-";
ies = mgmt.InformationElements;
if(isempty(ies))
return;
end
for i = 1 : size(ies, 1)
id = ies{i, 1};
value = ies{i, 2};
if isempty(id) || isempty(value)
continue;
end
switch id(1)
case 3
b_ch = string(double(value(1)));
case 61
op_ch = string(double(value(1)));
end
if ~strcmp(b_ch, "-") && ~strcmp(op_ch, "-")
return;
end
end
end