mirror of
https://github.com/Telecominfraproject/wlan-lanforge-scripts.git
synced 2025-10-29 18:02:35 +00:00
354 lines
7.3 KiB
Perl
354 lines
7.3 KiB
Perl
package Packet;
|
|
|
|
use warnings;
|
|
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 => "",
|
|
seqno => -1, # block-ack will not have a seqno
|
|
bytes_on_wire => 0,
|
|
acked_by => -1,
|
|
block_acked_by => -1,
|
|
retrans => 0,
|
|
seen_ip => 0,
|
|
timestamp => 0,
|
|
datarate => 0,
|
|
dummy_tx_pkts => 0,
|
|
dummy_rx_pkts => 0,
|
|
is_last_ampdu => 0,
|
|
is_ampdu => 0,
|
|
is_msdu => 0,
|
|
is_malformed => 0,
|
|
type_subtype => "UNKNOWN",
|
|
receiver => "UNKNOWN",
|
|
transmitter => "UNKNOWN",
|
|
tid => 17, # anything that does not specify a tid gets this.
|
|
%options,
|
|
amsdu_frame_count => 0,
|
|
ssi_sig_found => 0,
|
|
};
|
|
|
|
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};
|
|
}
|
|
|
|
sub append {
|
|
my $self = shift;
|
|
my $ln = shift;
|
|
|
|
$self->{raw_pkt} .= $ln;
|
|
|
|
#print "ln: $ln\n";
|
|
|
|
if ($ln =~ /^\s*Internet Protocol Version/) {
|
|
$self->{seen_ip} = 1;
|
|
return;
|
|
}
|
|
|
|
if ($self->{seen_ip}) {
|
|
if ($ln =~ /^\s*A-MSDU Subframe/) {
|
|
$self->{seen_ip} = 0;
|
|
}
|
|
else {
|
|
# Ignore
|
|
return;
|
|
}
|
|
}
|
|
|
|
if ($ln =~ /^\s*Transmitter address: .*\((\S+)\)/) {
|
|
$self->{transmitter} = $1;
|
|
}
|
|
elsif ($ln =~ /^\s*Epoch Time:\s+(\S+)/) {
|
|
#print "timestamp: $1\n";
|
|
$self->{timestamp} = $1;
|
|
}
|
|
elsif ($ln =~ /^.* = This is the last subframe of this A-MPDU: True/) {
|
|
$self->{is_last_ampdu} = 1;
|
|
}
|
|
elsif ($ln =~ /^.* = Priority: (.*) \(.*/) {
|
|
$self->{priority} = " $1";
|
|
}
|
|
elsif ($ln =~ /^.* = Payload Type: A-MSDU/) {
|
|
$self->{is_ampdu} = 1;
|
|
}
|
|
elsif ($ln =~ /^.* = Payload Type: MSDU/) {
|
|
$self->{is_msdu} = 1;
|
|
}
|
|
elsif ($ln =~ /^\s*\[Time delta from previous captured frame:\s+(\S+)/) {
|
|
$self->{timedelta} = $1;
|
|
}
|
|
elsif ($ln =~ /^\s*Receiver address: .*\((\S+)\)/) {
|
|
$self->{receiver} = $1;
|
|
}
|
|
elsif (($ln =~ /^\s*Fragment number: (\d+)/) ||
|
|
($ln =~ /^.*\s+=\s+Fragment number: (\d+)/)) {
|
|
$self->{fragno} = $1;
|
|
}
|
|
elsif (($ln =~ /^\s*Sequence number: (\d+)/) ||
|
|
($ln =~ /^.*\s+=\s+Sequence number: (\d+)/)) {
|
|
$self->{seqno} = $1;
|
|
}
|
|
elsif ($ln =~ /^\s*Type\/Subtype: (.*)/) {
|
|
$self->{type_subtype} = $1;
|
|
}
|
|
elsif ($ln =~ /.* = Starting Sequence Number: (\d+)/) {
|
|
$self->{ba_starting_seq} = $1;
|
|
}
|
|
elsif ($ln =~ /.*Malformed Packet.*/) {
|
|
$self->{is_malformed} = 1;
|
|
}
|
|
elsif ($ln =~ /.* = TID for which a Basic BlockAck frame is requested: (\S+)/) {
|
|
#print STDERR "tid: $1\n";
|
|
$self->{ba_tid} = hex($1);
|
|
}
|
|
elsif ($ln =~ /^\s*Block Ack Bitmap: (\S+)/) {
|
|
#print "ba-bitmap: $1\n";
|
|
$self->{ba_bitmap} = $1;
|
|
}
|
|
elsif ($ln =~ /.* = Retry: Frame is being retransmitted/) {
|
|
$self->{retrans} = 1;
|
|
}
|
|
elsif ($ln =~ /^\s*VHT information/) {
|
|
$self->{is_vht} = 1;
|
|
}
|
|
elsif ($ln =~ /^\s*Bandwidth: (.*)/) {
|
|
$self->{bandwidth} = $1;
|
|
}
|
|
elsif ($ln =~ /^\s*User 0: MCS (.*)/) {
|
|
$self->{mcs} = $1;
|
|
}
|
|
elsif ($ln =~ /.* = Spatial streams 0: (.*)/) {
|
|
$self->{nss} = $1;
|
|
}
|
|
elsif ($ln =~ /.* = TID: (.*)/) {
|
|
$self->{tid} = $1;
|
|
}
|
|
elsif ($ln =~ /.* = Payload Type: (.*)/) {
|
|
$self->{payload_type} = $1;
|
|
}
|
|
elsif (($ln =~ /^\s+\[Data Rate: (.*)\]/) ||
|
|
($ln =~ /^\s*Data Rate: (.*)/)) {
|
|
my $dr = $1;
|
|
if ($dr =~ /(\S+) Mb/) {
|
|
$self->{datarate} = $1;
|
|
}
|
|
else {
|
|
print "ERROR: Unknown datarate: $dr for frame: " . $self->frame_num() . "\n";
|
|
$self->{datarate} = 0;
|
|
}
|
|
}
|
|
elsif (($ln =~ /^\s*SSI Signal: (.*)/) ||
|
|
($ln =~ /^\s*Antenna signal: (.*)/)) {
|
|
if ($self->{ssi_sig_found} == 0) {
|
|
$self->{ssi_combined} = $1;
|
|
$self->{ssi_sig_found}++;
|
|
}
|
|
elsif ($self->{ssi_sig_found} == 1) {
|
|
$self->{ssi_ant_0} = $1;
|
|
$self->{ssi_sig_found}++;
|
|
}
|
|
elsif ($self->{ssi_sig_found} == 2) {
|
|
$self->{ssi_ant_1} = $1;
|
|
$self->{ssi_sig_found}++;
|
|
}
|
|
elsif ($self->{ssi_sig_found} == 3) {
|
|
$self->{ssi_ant_2} = $1;
|
|
$self->{ssi_sig_found}++;
|
|
}
|
|
elsif ($self->{ssi_sig_found} == 4) {
|
|
$self->{ssi_ant_3} = $1;
|
|
$self->{ssi_sig_found}++;
|
|
}
|
|
}
|
|
# AMPDU and such...
|
|
elsif ($ln =~ /^\s*A-MSDU Subframe #(\d+)/) {
|
|
if ($1 > $self->{amsdu_frame_count}) {
|
|
$self->{amsdu_frame_count} = $1;
|
|
}
|
|
}
|
|
else {
|
|
if ($self->type_subtype() eq "Beacon frame (0x0008)") {
|
|
if ($ln =~ /^\s+(Ac Parameters ACI.*)/) {
|
|
$self->{wmm_info} .= $ln;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
sub frame_num {
|
|
my $self = shift;
|
|
return $self->{frame_num};
|
|
}
|
|
|
|
sub type_subtype {
|
|
my $self = shift;
|
|
return $self->{type_subtype};
|
|
}
|
|
|
|
sub transmitter {
|
|
my $self = shift;
|
|
return $self->{transmitter};
|
|
}
|
|
|
|
sub datarate {
|
|
my $self = shift;
|
|
return $self->{datarate};
|
|
}
|
|
|
|
sub retrans {
|
|
my $self = shift;
|
|
return $self->{retrans};
|
|
}
|
|
|
|
sub seqno {
|
|
my $self = shift;
|
|
return $self->{seqno};
|
|
}
|
|
|
|
sub block_acked_by {
|
|
my $self = shift;
|
|
return $self->{block_acked_by};
|
|
}
|
|
|
|
sub acked_by {
|
|
my $self = shift;
|
|
return $self->{acked_by};
|
|
}
|
|
|
|
sub set_block_acked_by {
|
|
my $self = shift;
|
|
$self->{block_acked_by} = shift;
|
|
}
|
|
|
|
sub set_acked_by {
|
|
my $self = shift;
|
|
$self->{acked_by} = shift;
|
|
}
|
|
|
|
sub was_acked {
|
|
my $self = shift;
|
|
|
|
if ($self->block_acked_by() != -1) {
|
|
return 1;
|
|
}
|
|
if ($self->acked_by() != -1) {
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
sub wants_ack {
|
|
my $self = shift;
|
|
my $rcvr_b0 = substr($self->receiver(), 0, 1);
|
|
if ($rcvr_b0 eq "U") {
|
|
#print STDERR "wants-ack, receiver: " . $self->receiver() . "\n";
|
|
#print STDERR $self->raw_pkt() . "\n";
|
|
#exit(1);
|
|
return 0;
|
|
}
|
|
my $rb0 = hex("$rcvr_b0");
|
|
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;
|
|
}
|
|
|
|
sub timestamp {
|
|
my $self = shift;
|
|
return $self->{timestamp};
|
|
}
|
|
|
|
sub receiver {
|
|
my $self = shift;
|
|
return $self->{receiver};
|
|
}
|
|
|
|
sub tid {
|
|
my $self = shift;
|
|
if (exists $self->{ba_tid}) {
|
|
return $self->{ba_tid};
|
|
}
|
|
return $self->{tid};
|
|
}
|
|
|
|
sub set_transmitter {
|
|
my $self = shift;
|
|
my $tx = shift;
|
|
$self->{transmitter} = $tx;
|
|
}
|
|
|
|
sub set_receiver {
|
|
my $self = shift;
|
|
my $rx = shift;
|
|
$self->{receiver} = $rx;
|
|
}
|
|
|
|
1;
|