in reply to Re^4: Allowed VLANs with SNMP
in thread Allowed VLANs with SNMP
OK, it's all down to representations.
I suggested Perl bit-vectors, so let's start there and work back up.
A Perl bit-vector should be viewed as an abstract entity, which for these purposes we're going to treat as a collection of bits, numbered from 0..'n'. We can read bit '$b' by: $v = vec($bits, 1, $b) ; where $bits contains the bit-vector, 1 indicates this is a vector of single bit values, and $b contains the number of the bit we want the value of. Similarly we can set a bit by: vec($bits, 1, $b) = $v ;.
What we want to do is to translate from the forms you have, to a Perl bit-vector, so that the bit number corresponds to a VLAN number.
The documentation tells us that a Perl bit-vector is a string of bytes, where (for single bit values) bit number 1 is stored as Bit0 of Byte0, bit number 7 as Bit7 of Byte0, bit number 8 as Bit0 of Byte1, and so on.
The second form you mentioned claimed to be in octets, with VLAN 0 represented by Bit7 of Byte0, VLAN 7 by Bit0 of Byte0, VLAN 8, by Bit7 of Byte1, and so on. This is similar to a Perl bit-vector, but with the bit numbers within each byte reversed.
The xlat routine translates between these two forms.
Now, what you appear to have in your hands is the second form, but not as raw (binary) octets, but in a hex representation of those octets. So the first step is to pack from there to the binary. That can be given to xlat and the result is the Perl bit-vector form, which the range subroutine can unpick.
Code below illustrates all the above. Output is:
01000000::00000100::::00000010::10000000:::::::::::00000010::::::11000000:00000100:... 00000010::00100000::::01000000::00000001:::::::::::01000000::::::00000011:00100000:... Ranges: 1, 21, 54, 64, 158, 200-201, 213, 231, 236, 248Hope this helps clarify.
use strict ; use warnings ; # This $test is the value of OID 'octets', rendered as hex characters #1234567890123456789012345678901234567890 my $test = '0x4000040000000200800000000000000000000002' .'0000000000c00400010800800000000000000000' ; # .'0000000000000000000000000000000000000000' # .'0000000000000000000000000000000000000000' # .'0000000000000000000000000000000000000000' # .'0000000000000000000000000000000000000000' # .'0000000000000000'; # This translates the hex characters to an 'octet' string my $octets = from_hex($test) ; # The untranslated octet string looks like this, in bits print showbits($octets), "\n" ; # Here we translate from the octet string to a Perl bit-vector my $bits = xlat($octets) ; print showbits($bits), "\n" ; # Here we work out and show the VLAN ranges my @s = ranges($bits); print "Ranges: ", join(', ', @s), "\n" ; # The various subroutines sub from_hex { my ($hex) = @_ ; $hex =~ s/^0x//i ; return pack('H*', $hex) ; } ; sub to_hex { my ($bytes) = @_ ; return '0x'.unpack('H*', $bytes) ; } ; sub xlat { my ($octets) = @_ ; return pack('B*', unpack('b*', $octets)) ; } ; sub ranges{ my $bits = shift; my $r = undef ; my @s = () ; for my $vn (1..length($bits) * 8) { if (vec($bits, $vn, 1)) { if (!defined($r)) { push @s, "$vn" ; $r = 0 ; } else { $r = $vn ; } ; } else { if (defined($r)) { if ($r) { $s[-1] .= "-$r" ; } ; $r = undef ; } ; } ; } ; return @s; } sub showbits { my ($octets) = @_ ; my $s = unpack('B*', $octets) ; $s =~ s/([01]{8})(?=[01])/$1:/g ; $s =~ s/(?<=:)0{8}(?=:)//g ; return $s ; } ;
|
|---|