Negative Overflow of 4-byte AS in Solarwinds Orion Output





2.00/5 (1 vote)
Negative Overflow of 4-byte AS in Solarwinds Orion Output
4-byte (32-bit) BGP Neighbor Information with AsDotNotation
A problem currently exists within Solarwinds where 4-byte (32-bit) ASNs overflow into a negative number when utilizing a portion of the private scoped ASN space specifically, the ranges 2,147,483,648 (32768.0) through 4,294,967,296 (65535.65535) overflow into -2,147,483,648 through -1 respectively.
To show the correct data, we created a custom table utilizing the following WSQL to generate the correct information. See past the snippet for an explanation as to how and why this works.
SELECT NeighborIP, ProtocolName, ProtocolStatus, -- AutonomousSystem is stored in a signed 32 bit integer, and will therefore -- overflow into a negative number when the number exceeds 2,147,483,648. -- High Bound of AS before this event is 32768.65535. -- NOTE: THIS FIELD IS FOR REFERENCE ONLY AND CAN BE DROPPED IN PRODUCTION. AutonomousSystem AS RawAS, -- AsPlainNotation represents the correct enumeration for 4-byte AS (as well -- as 2-byte AS by adding the Autonomous system to 4,294,967,296) CASE WHEN AutonomousSystem < 0 THEN ( -- NEGATIVE ASN INTEGER OVERFLOW ENCOUNTERED -- Add 64-bit CONST Integer representing positive offset to counteract -- negative overflow... 4294967296 + AutonomousSystem ) ELSE ( -- ASN WITHIN NORMAL BOUNDS -- Return RAW ASN. AutonomousSystem ) END AS AsPlainNotation, -- AsDotNotation represents the X.Y Dot Notation specified in RFC4893 for -- the 4-byte (or 32-bit) BGP Peer's AS. CASE WHEN AutonomousSystem < 0 THEN ( -- NEGATIVE ASN INTEGER OVERFLOW ENCOUNTERED -- Add 64-bit CONST Integer representing positive offset to counteract -- negative overflow... split components: -- + To get most significant 16-bits divide by 2^16 (65536) and -- truncate with FLOOR. -- + To get least significant 16-bits perform 'most significant bit -- calculation' and Left shift 16-bits by multiplying by 2^16 -- and subtracting from the full 32-bit value. TOSTRING( FLOOR( (4294967296 + AutonomousSystem) / 65536) ) + '.' + TOSTRING( (4294967296 + AutonomousSystem) - (FLOOR( (4294967296 + AutonomousSystem) / 65536) * 65536) ) ) WHEN AutonomousSystem < 0 THEN ( -- POSITIVE 4-BYTE ASN ENCOUNTERED -- Split components: -- + To get most significant 16-bits divide by 2^16 (65536) and -- truncate with FLOOR. -- + To get least significant 16-bits perform 'most significant bit -- calculation' and Left shift 16-bits by multiplying by 2^16 -- and subtracting from the full 32-bit value. WHEN AutonomousSystem > 65535 THEN ( TOSTRING( FLOOR( (AutonomousSystem) / 65536) ) + '.' + TOSTRING( (AutonomousSystem) - (FLOOR( (AutonomousSystem) / 65536) * 65536) ) ) ELSE ( -- POSITIVE 2-BYTE ASN ENCOUNTERED -- Append 0. to the autonomous system. '0.' + TOSTRING(AutonomousSystem) ) END AS AsDotNotation FROM Orion.Routing.Neighbors WHERE NodeID = ${NodeID}
NOTE: RFC6996 defines private scoped ASNs as 4,200,000,000 (64806.0) through 4294967294 (65535.65535) inclusive.
Linear assignment of Binary Symbol to Decimal Number for a 32-bit Signed Integer:
10000000 00000000 00000000 00000000 =Â -2,147,483,648
10000000 00000000 00000000 00000001 =Â -2,147,483,647
10000000 00000000 00000000 00000010 =Â -2,147,483,646
10000000 00000000 00000000 00000011 =Â -2,147,483,645
... lines removed for brevity ...
11111111 11111111 11111111 11111100 = -4
11111111 11111111 11111111 11111101 = -3
11111111 11111111 11111111 11111110 = -2
11111111 11111111 11111111 11111111 = -1
00000000 00000000 00000000 00000000Â = Â 0
00000000 00000000 00000000 00000001 = Â 1
00000000 00000000 00000000 00000010Â = Â 2
00000000 00000000 00000000 00000011 = Â 3
00000000 00000000 00000000 00000100Â = Â 4
... lines removed for brevity ...
â€01111111 11111111 11111111 11111100‬ =  2,147,483,644
â€01111111 11111111 11111111 11111101‬ =  2,147,483,645
â€01111111 11111111 11111111 11111110‬ =  2,147,483,646
â€01111111 11111111 11111111 11111111‬ =  2,147,483,647
â€10000000 00000000 00000000 00000000 = -2,147,483,648 NEGATIVE OVERFLOW
Details
Storage of a 4-byte/32-bit ASN in 32-bit signed integer causes
2,147,483,648 (32768.0) through 4,294,967,295 (65535.65535)
to be interpreted as:
-2,147,483,648 through -1
which do not represent legitimate ASNs.
We don’t care about negative numbers when dealing with ASNs, and so the better storage mechanism would be to keep these in Unsigned 32-bit Integers or 64-bit Signed integers. However, that is beyond the scope of this... I only note this to point out, we can easily fix the output by summing this 32-bit signed (negative) integer with a 64-bit signed integer in the amount of the offset needed.
Let's imagine we are using the AS Number of 32768.4 (2,147,483,652).
So what happens when we store this number in a 32-bit Singed Integer, the accumulator (in theory) would get to:
2,147,483,647 (32767.65535)
and increase the value by 1, which becomes:
-2,147,483,648 (32768.0) ... which should be 2,147,483,648
then the accumulator continues to increase the value by 1, 4 more times:
-2,147,483,647 (32768.1) ... which should be 2,147,483,649
-2,147,483,646 (32768.2) ... which should be 2,147,483,650
-2,147,483,645 (32768.3) ... which should be 2,147,483,651
-2,147,483,644 (32768.4) ... which should be 2,147,483,652
What you will notice is the result of -2,147,483,644
is always the total bit storage quantity offset from its intended value of 2,147,483,652
.
This total bit storage quantity of a 32-bit word provides 4,294,967,296
total symbols. By making the 32-bit Integer Signed, the system is simply using half of those symbols for negative integers.