mirror of
https://github.com/Telecominfraproject/wlan-lanforge-scripts.git
synced 2025-10-29 18:02:35 +00:00
wifi-diag: Better no-ack detection and some cleanup.
It now reports expected 'no-ack' frames at least in a fairly simplistic test case.
This commit is contained in:
@@ -6,11 +6,15 @@ use strict;
|
||||
use bignum;
|
||||
use bigint;
|
||||
|
||||
our $d_counter = 0;
|
||||
|
||||
sub new {
|
||||
my $class = shift;
|
||||
my %options = @_;
|
||||
|
||||
my $self = {
|
||||
ba_valid => 0,
|
||||
dbg => "NA",
|
||||
priority => "",
|
||||
wmm_info => "",
|
||||
raw_pkt => "",
|
||||
@@ -37,9 +41,28 @@ sub new {
|
||||
};
|
||||
|
||||
bless($self, $class);
|
||||
|
||||
if ($self->frame_num() == -1) {
|
||||
$self->{dummy_counter} = $d_counter;
|
||||
$d_counter++;
|
||||
print "Creating dummy pkt: " . $self->{dummy_counter} . "\n";
|
||||
}
|
||||
else {
|
||||
$self->{dummy_counter} = -1;
|
||||
}
|
||||
|
||||
return($self);
|
||||
}
|
||||
|
||||
sub desc {
|
||||
my $self = shift;
|
||||
my $rv = $self->frame_num() . " len: " . $self->{bytes_on_wire};
|
||||
if ($self->frame_num() == -1) {
|
||||
$rv = $rv . " dummy-counter: " . $self->{dummy_counter} . " dbg: " . $self->{dbg}
|
||||
}
|
||||
return $rv;
|
||||
}
|
||||
|
||||
sub raw_pkt {
|
||||
my $self = shift;
|
||||
return $self->{raw_pkt};
|
||||
@@ -248,6 +271,35 @@ sub wants_ack {
|
||||
if ($rb0 & 0x1) {
|
||||
return 0; # Don't ack bcast/bcast frames
|
||||
}
|
||||
|
||||
if ($self->type_subtype() eq "802.11 Block Ack (0x0019)") {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ($self->type_subtype() eq "802.11 Block Ack Req (0x0018)") {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ($self->type_subtype() eq "VHT NDP Announcement (0x0015)") {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ($self->type_subtype() eq "Clear-to-send (0x001c)") {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ($self->type_subtype() eq "Request-to-send (0x001b)") {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ($self->type_subtype() eq "Acknowledgement (0x001d)") {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ($self->type_subtype() eq "Action No Ack (0x000e)") {
|
||||
return 0;
|
||||
}
|
||||
|
||||
# TODO: Need to parse QoS no-ack frames too, this will return false positives currently
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -81,40 +81,65 @@ sub find_or_create_tid {
|
||||
return $tid;
|
||||
}
|
||||
|
||||
sub tx_no_ack_found {
|
||||
sub sum_tids {
|
||||
my $self = shift;
|
||||
my $var = shift;
|
||||
|
||||
my $tid_count = @{$self->{tids}};
|
||||
|
||||
my $rv = 0;
|
||||
|
||||
my $i;
|
||||
for ($i = 0; $i < $tid_count; $i++) {
|
||||
#print "Checking tid: $i\n";
|
||||
if (exists $self->{tids}[$i]) {
|
||||
#print "Printing tid: $i\n";
|
||||
$rv += $self->{tids}[$i]->tx_no_ack_found();
|
||||
#print "Done printing tid: $i\n";
|
||||
if ($var == 0) {
|
||||
$rv += $self->{tids}[$i]->tx_no_ack_found_all();
|
||||
}
|
||||
elsif ($var == 1) {
|
||||
$rv += $self->{tids}[$i]->tx_no_ack_found_big();
|
||||
}
|
||||
elsif ($var == 2) {
|
||||
$rv += $self->{tids}[$i]->rx_no_ack_found_all();
|
||||
}
|
||||
elsif ($var == 3) {
|
||||
$rv += $self->{tids}[$i]->rx_no_ack_found_big();
|
||||
}
|
||||
}
|
||||
}
|
||||
return $rv;
|
||||
}
|
||||
|
||||
sub rx_no_ack_found {
|
||||
sub tx_no_ack_found_all {
|
||||
my $self = shift;
|
||||
return $self->sum_tids(0);
|
||||
}
|
||||
|
||||
sub tx_no_ack_found_big {
|
||||
my $self = shift;
|
||||
return $self->sum_tids(1);
|
||||
}
|
||||
|
||||
sub rx_no_ack_found_all {
|
||||
my $self = shift;
|
||||
return $self->sum_tids(2);
|
||||
}
|
||||
|
||||
sub rx_no_ack_found_big {
|
||||
my $self = shift;
|
||||
return $self->sum_tids(3);
|
||||
}
|
||||
|
||||
sub notify_done {
|
||||
my $self = shift;
|
||||
my $tid_count = @{$self->{tids}};
|
||||
|
||||
my $rv = 0;
|
||||
|
||||
my $i;
|
||||
for ($i = 0; $i < $tid_count; $i++) {
|
||||
#print "Checking tid: $i\n";
|
||||
if (exists $self->{tids}[$i]) {
|
||||
#print "Printing tid: $i\n";
|
||||
$rv += $self->{tids}[$i]->rx_no_ack_found();
|
||||
#print "Done printing tid: $i\n";
|
||||
$self->{tids}[$i]->check_remaining_pkts();
|
||||
}
|
||||
}
|
||||
return $rv;
|
||||
}
|
||||
|
||||
sub printme {
|
||||
|
||||
@@ -15,8 +15,10 @@ sub new {
|
||||
|
||||
my $self = {
|
||||
pkts => [],
|
||||
rx_no_ack_found => 0,
|
||||
tx_no_ack_found => 0,
|
||||
rx_no_ack_found_all => 0,
|
||||
rx_no_ack_found_big => 0,
|
||||
tx_no_ack_found_all => 0,
|
||||
tx_no_ack_found_big => 0,
|
||||
tx_retrans_pkts => 0,
|
||||
rx_retrans_pkts => 0,
|
||||
tx_amsdu_retrans_pkts => 0,
|
||||
@@ -181,7 +183,8 @@ sub add_pkt {
|
||||
$missing_str .= $missing_seqno . " ";
|
||||
|
||||
# Add a dummy pkt
|
||||
my $dummy = Packet->new(frame_num => -1,
|
||||
my $dummy = Packet->new(dbg => "tid-add-pkt",
|
||||
frame_num => -1,
|
||||
receiver => $pkt->transmitter(),
|
||||
transmitter => $pkt->receiver(),
|
||||
data_subtype => "DUMMY_BA_ACKED",
|
||||
@@ -229,12 +232,25 @@ sub add_pkt {
|
||||
($pkt_count > $max_pkt_store)) {
|
||||
if (! $tmp->was_acked()) {
|
||||
if ($tmp->wants_ack()) {
|
||||
print "WARNING: did not find ack for frame: " . $tmp->frame_num() . ", removing after processing frame: " . $pkt->frame_num() . "\n";
|
||||
if ($tmp->transmitter() eq $self->{addr_a}) {
|
||||
$self->{tx_no_ack_found}++;
|
||||
$self->{tx_no_ack_found_all}++;
|
||||
if ($tmp->{bytes_on_wire} > 1000) {
|
||||
print "WARNING: did not find ack for BIG TX frame: " . $tmp->desc() . ", removing after processing frame: " . $pkt->frame_num() . "\n";
|
||||
$self->{tx_no_ack_found_big}++;
|
||||
}
|
||||
else {
|
||||
print "WARNING: did not find ack for small TX frame: " . $tmp->desc() . ", removing after processing frame: " . $pkt->frame_num() . "\n";
|
||||
}
|
||||
}
|
||||
else {
|
||||
$self->{rx_no_ack_found}++;
|
||||
$self->{rx_no_ack_found_all}++;
|
||||
if ($tmp->{bytes_on_wire} > 1000) {
|
||||
print "WARNING: did not find ack for BIG RX frame: " . $tmp->desc() . ", removing after processing frame: " . $pkt->frame_num() . "\n";
|
||||
$self->{rx_no_ack_found_big}++;
|
||||
}
|
||||
else {
|
||||
print "WARNING: did not find ack for small RX frame: " . $tmp->desc() . ", removing after processing frame: " . $pkt->frame_num() . "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -308,19 +324,65 @@ sub add_pkt {
|
||||
push(@{$self->{pkts}}, $pkt);
|
||||
}
|
||||
|
||||
sub check_remaining_pkts {
|
||||
my $self = shift;
|
||||
|
||||
my $pkt_count = @{$self->{pkts}};
|
||||
|
||||
# Shift off old frames.
|
||||
while ($pkt_count > 0) {
|
||||
my $tmp = shift(@{$self->{pkts}});
|
||||
if (! $tmp->was_acked()) {
|
||||
if ($tmp->wants_ack()) {
|
||||
if ($tmp->transmitter() eq $self->{addr_a}) {
|
||||
$self->{tx_no_ack_found_all}++;
|
||||
if ($tmp->{bytes_on_wire} > 1000) {
|
||||
print "WARNING: did not find ack for BIG TX frame: " . $tmp->desc() . ", removing at end of file.\n";
|
||||
$self->{tx_no_ack_found_big}++;
|
||||
}
|
||||
else {
|
||||
print "WARNING: did not find ack for small TX frame: " . $tmp->desc() . ", removing at end of file.\n";
|
||||
}
|
||||
}
|
||||
else {
|
||||
$self->{rx_no_ack_found_all}++;
|
||||
if ($tmp->{bytes_on_wire} > 1000) {
|
||||
print "WARNING: did not find ack for BIG RX frame: " . $tmp->desc() . ", removing at end of file.\n";
|
||||
$self->{rx_no_ack_found_big}++;
|
||||
}
|
||||
else {
|
||||
print "WARNING: did not find ack for small RX frame: " . $tmp->desc() . ", removing at end of file.\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$pkt_count--;
|
||||
}
|
||||
}
|
||||
|
||||
sub get_pkts {
|
||||
my $self = shift;
|
||||
return @{$self->{pkts}};
|
||||
}
|
||||
|
||||
sub tx_no_ack_found {
|
||||
sub tx_no_ack_found_all {
|
||||
my $self = shift;
|
||||
return $self->{tx_no_ack_found};
|
||||
return $self->{tx_no_ack_found_all};
|
||||
}
|
||||
|
||||
sub rx_no_ack_found {
|
||||
sub tx_no_ack_found_big {
|
||||
my $self = shift;
|
||||
return $self->{rx_no_ack_found};
|
||||
return $self->{tx_no_ack_found_big};
|
||||
}
|
||||
|
||||
sub rx_no_ack_found_all {
|
||||
my $self = shift;
|
||||
return $self->{rx_no_ack_found_all};
|
||||
}
|
||||
|
||||
sub rx_no_ack_found_big {
|
||||
my $self = shift;
|
||||
return $self->{rx_no_ack_found_big};
|
||||
}
|
||||
|
||||
sub printme {
|
||||
@@ -328,7 +390,8 @@ sub printme {
|
||||
print " tidno: " . $self->tidno() . " pkt-count: " . $self->get_pkts()
|
||||
. " tx-pkts: " . $self->{tx_pkts} . " tx-retrans: " . $self->{tx_retrans_pkts}
|
||||
. " rx-pkts: " . $self->{rx_pkts} . " rx-retrans: " . $self->{rx_retrans_pkts}
|
||||
. " tx-no-acks: " . $self->{tx_no_ack_found} . " rx-no-acks: " . $self->{rx_no_ack_found}
|
||||
. " tx-no-acks-all: " . $self->{tx_no_ack_found_all} . " tx-no-acks-big: " . $self->{tx_no_ack_found_big}
|
||||
. " rx-no-acks-all: " . $self->{rx_no_ack_found_all} . " rx-no-acks-big: " . $self->{rx_no_ack_found_big}
|
||||
. "\n";
|
||||
}
|
||||
|
||||
|
||||
@@ -37,11 +37,11 @@ my $input_line_count = 0;
|
||||
my $pkts_sofar = 0;
|
||||
my $start_time = time();
|
||||
|
||||
my $cur_pkt = Packet->new(raw_pkt => "", frame_num => -1);
|
||||
my $last_pkt = Packet->new(raw_pkt => "", frame_num => -1, is_rx => 0);
|
||||
my $first_ampdu_pkt = Packet->new(raw_pkt => "", frame_num => -1);
|
||||
my $last_ba_rx_pkt = Packet->new(raw_pkt => "", frame_num => -1);
|
||||
my $last_ba_tx_pkt = Packet->new(raw_pkt => "", frame_num => -1);
|
||||
my $cur_pkt = Packet->new(raw_pkt => "", frame_num => -1, dbg => "cur_pkt");
|
||||
my $last_pkt = Packet->new(raw_pkt => "", frame_num => -1, is_rx => 0, dbg => "last_pkt");
|
||||
my $first_ampdu_pkt = Packet->new(raw_pkt => "", frame_num => -1, dbg => "first_ampdu_pkt");
|
||||
my $last_ba_rx_pkt = Packet->new(raw_pkt => "", frame_num => -1, dbg => "last_ba_rx_pkt");
|
||||
my $last_ba_tx_pkt = Packet->new(raw_pkt => "", frame_num => -1, dbg => "last_ba_tx_pkt");
|
||||
|
||||
|
||||
my $glb_fh_ba_tx;
|
||||
@@ -52,8 +52,10 @@ my $glb_fh_mcs_rx;
|
||||
my $glb_fh_rtx_tx;
|
||||
my $glb_fh_rtx_rx;
|
||||
|
||||
my $tx_no_ack_found = 0;
|
||||
my $rx_no_ack_found = 0;
|
||||
my $tx_no_ack_found_big = 0;
|
||||
my $rx_no_ack_found_big = 0;
|
||||
my $tx_no_ack_found_all = 0;
|
||||
my $rx_no_ack_found_all = 0;
|
||||
|
||||
my %glb_mcs_tx_hash = ();
|
||||
my %glb_mcs_rx_hash = ();
|
||||
@@ -187,8 +189,9 @@ while (<>) {
|
||||
processPkt($cur_pkt);
|
||||
}
|
||||
$cur_pkt = Packet->new(frame_num => $1,
|
||||
bytes_on_write => $2,
|
||||
raw_pkt => $ln);
|
||||
bytes_on_wire => $2,
|
||||
raw_pkt => $ln,
|
||||
dbg => "main-$1");
|
||||
} else {
|
||||
$cur_pkt->append($ln);
|
||||
}
|
||||
@@ -202,8 +205,11 @@ printProgress();
|
||||
|
||||
# Sum up some stats
|
||||
for my $conn (values %peer_conns) {
|
||||
$tx_no_ack_found += $conn->tx_no_ack_found();
|
||||
$rx_no_ack_found += $conn->rx_no_ack_found();
|
||||
$conn->notify_done();
|
||||
$tx_no_ack_found_big += $conn->tx_no_ack_found_big();
|
||||
$rx_no_ack_found_big += $conn->rx_no_ack_found_big();
|
||||
$tx_no_ack_found_all += $conn->tx_no_ack_found_all();
|
||||
$rx_no_ack_found_all += $conn->rx_no_ack_found_all();
|
||||
}
|
||||
|
||||
$report_html .= genGlobalReports();
|
||||
@@ -341,8 +347,10 @@ sub htmlMcsHistogram {
|
||||
}
|
||||
$html .= "TX (Big) Retransmit count: $tx_retrans_pkts_big<br>\n";
|
||||
|
||||
$html .= "RX no-ack-found: $rx_no_ack_found<br>\n";
|
||||
$html .= "TX no-ack-found: $tx_no_ack_found<br>\n";
|
||||
$html .= "RX (All) no-ack-found: $rx_no_ack_found_all<br>\n";
|
||||
$html .= "RX (Big) no-ack-found: $rx_no_ack_found_big<br>\n";
|
||||
$html .= "TX (All) no-ack-found: $tx_no_ack_found_all<br>\n";
|
||||
$html .= "TX (Big) no-ack-found: $tx_no_ack_found_big<br>\n";
|
||||
|
||||
if ($delta_time_tx_count) {
|
||||
$html .= "TX average gap between AMPDU frames (ms): " . (($delta_time_tx * 1000.0) / $delta_time_tx_count) . "<br>\n";
|
||||
@@ -584,22 +592,22 @@ sub processPkt {
|
||||
if ($pkt->{is_ampdu} || $pkt->{is_msdu}) {
|
||||
if ($last_pkt->frame_num() != -1 && (!($last_pkt->{is_ampdu} || $last_pkt->{is_msdu}))) {
|
||||
# This is first ampdu since a non-ampdu frame. Calculate diff between that and last BA
|
||||
if ($pkt->{is_rx} && ($last_ba_tx_pkt->frame_num() != -1)) {
|
||||
if ($pkt->{is_rx} && ($last_ba_tx_pkt->{ba_valid})) {
|
||||
my $diff = $pkt->timestamp() - $last_ba_tx_pkt->timestamp();
|
||||
$ba_ampdu_gap_rx += $diff;
|
||||
$ba_ampdu_gap_rx_count++;
|
||||
if ($diff > 0.001) {
|
||||
print "INFO: TX BA to RX AMPDU gap: $diff between frames: " . $last_ba_tx_pkt->frame_num() . " and: " . $pkt->frame_num() . "\n";
|
||||
}
|
||||
$last_ba_tx_pkt->{frame_num} = -1;
|
||||
} elsif ((!$pkt->{is_rx}) && ($last_ba_rx_pkt->frame_num() != -1)) {
|
||||
$last_ba_tx_pkt->{ba_valid} = 0;
|
||||
} elsif ((!$pkt->{is_rx}) && ($last_ba_rx_pkt->{ba_valid})) {
|
||||
my $diff = $pkt->timestamp() - $last_ba_rx_pkt->timestamp();
|
||||
$ba_ampdu_gap_tx += $diff;
|
||||
$ba_ampdu_gap_tx_count++;
|
||||
if ($diff > 0.001) {
|
||||
print "INFO: RX BA to TX AMPDU gap: $diff between frames: " . $last_ba_rx_pkt->frame_num() . " and: " . $pkt->frame_num() . "\n";
|
||||
}
|
||||
$last_ba_rx_pkt->{frame_num} = -1;
|
||||
$last_ba_rx_pkt->{ba_valid} = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -642,18 +650,20 @@ sub processPkt {
|
||||
if ($pkt->type_subtype() eq "802.11 Block Ack (0x0019)") {
|
||||
# Only grab the initial BA in case we have one side ignoring BA
|
||||
if ($pkt->{is_rx}) {
|
||||
if ($last_ba_rx_pkt->{frame_num} == -1) {
|
||||
if (!$last_ba_rx_pkt->{ba_valid}) {
|
||||
$last_ba_rx_pkt = $pkt;
|
||||
$last_ba_rx_pkt->{ba_valid} = 1;
|
||||
} else {
|
||||
print "NOTE: Multiple RX block-acks seen without ampdu between them, first BA frame: " . $last_ba_rx_pkt->frame_num()
|
||||
. " this BA frame num: " . $pkt->frame_num() . "\n";
|
||||
$dup_ba_rx++;
|
||||
}
|
||||
} else {
|
||||
if ($last_ba_tx_pkt->{frame_num} == -1) {
|
||||
if (!$last_ba_tx_pkt->{ba_valid}) {
|
||||
$last_ba_tx_pkt = $pkt;
|
||||
$last_ba_tx_pkt->{ba_valid} = 1;
|
||||
} else {
|
||||
print "NOTE: Multiple TX block-acks seen without ampdu between them, first BA frame: " . $last_ba_rx_pkt->frame_num()
|
||||
print "NOTE: Multiple TX block-acks seen without ampdu between them, first BA frame: " . $last_ba_tx_pkt->frame_num()
|
||||
. " this BA frame num: " . $pkt->frame_num() . "\n";
|
||||
$dup_ba_tx++;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user