Net::MRT - Perl extension for decoding RFC6396 Multi-Threaded Routing Toolkit (MRT) Routing Information Export Format
Decode uncompressed MRT file:
use Net::MRT; open(C, '<', 'file'); binmode(C); while ($decode = Net::MRT::mrt_read_next(C)) { do_something_useful($decode); }
In-memory download/decode:
use LWP::Simple; use PerlIO::gzip; use Net::MRT; $LWP::Simple::ua->show_progress(1); $archive = get($url); open $mrt, "<:gzip", \$archive or die $!; while ($dd = Net::MRT::mrt_read_next($mrt)) { do_something_useful($decode); }
Note: In case of errors, reported message offset will be relative to Perl internal buffer
Decode some binary message of known type/subtype:
$hash = Net::MRT::mrt_decode_single($type, $subtype, $buffer);
Refer to t/ directory for a lot of examples, how each attribute decoded.
"Net::MRT::mrt_read_next" Decodes next message from filehandle
NOTE Always set binary mode before call to mrt_read_next or got unexpected results.
"Net::MRT::mrt_decode_single" Decodes message of specified type & subtype. See t/* for a lot of examples
TODO TODO
None by default.
{ 'timestamp' => 1222905597, 'type' => X, 'subtype' => Y, other decoded elements, };
In case of unsupported type/subtype an error message is returned in error.
error
{ 'timestamp' => Z, 'type' => X, 'subtype' => Y, 'error' => 'Unsupported MRT type X subtype Y in message at N', };
{ 'peers' => [ '1' => { 'peer_ip' => '2001:db8::dead:beef', 'bgp_id' => '10.11.12.13', 'as' => 35243 }, '0' => { 'peer_ip' => '5.6.7.8', 'bgp_id' => '1.2.3.4', 'as' => 2164197642 } ], 'collector_bgp_id' => '1.2.3.4', 'view_name' => 'testTEST', };
Peer index table decoded as HASH with peer's ARRAY allowing reference by peer's index.
NOTE: view_name marked with UTF8 flag, but this field is optional by RFC.
view_name
{ 'timestamp' => 1222905597, 'type' => 13, 'subtype' => 2, 'prefix' => '10.0.0.0' 'bits' => 8, 'sequence' => 1, 'entries' => [ { See Decoding of BGP attributes }, { See Decoding of BGP attributes }, ], };
NOTE: type subtype timestamp elements appended into HASH only while stream decode using Net::MRT::mrt_read_next.
type
subtype
timestamp
BGP attributes decoded into the same HASHREF where decoded entry resides.
{ 'peer_index' => 12, 'originated_time' => 1220989283 'ORIGIN' => 0, 'NEXT_HOP' => '10.68.129.132', 'AS_PATH' => [ 65501, 65502, [65503, 65504], 65505, ], 'unsupported7' => undef, }
peer_index is a reference to PEER_INDEX_TABLE.
peer_index
The originated_time contains the 4-octet time at which this prefix was heard. The value represents the time in seconds since 1 January 1970 00:00:00 UTC.
originated_time
Unsupported (by Net::MRT) attributes reported as 'unsupportedX' where X is a BGP attribute code.
{ 'ORIGIN' => 0 }, $Net::MRT::BGP_ORIGIN[$entry->{'ORIGIN'}]
The ORIGIN decoded as integer. Additional helper array can be used to decode into text representation.
{ 'AS_PATH' => [ 65501, 65502, 65505, [65503, 65504], ], }
The AS_PATH decoded as array of elements. Each of element can be an AS_SEQUENCE (single AS number) or AS_SET (array of AS numbers).
NOTE: Multiple AS_PATH attributes supported.
AS_PATH
- "The ability of a BGP speaker to include more than one instance of its own AS in the AS_PATH attribute for the purpose of inter-AS traffic engineering."
Determination of ORIGINATED AS is to skip trailing AS_SET and take single AS:
foreach (reverse @{$_->{'AS_PATH'}}) { next if ref($_); print "Originated AS = $_\n"; last; }
NOTE: MRT TABLE_DATA_V2 AS_PATH contain four-octet AS numbers in AS_PATH attribute. So, expect large numbers (> 65535).
RFC 6396: RIB ENTRIES
- "All AS numbers in the AS_PATH attribute MUST be encoded as 4-byte AS numbers."
IPv4 Next Hop:
{ 'NEXT_HOP' => [ '10.68.129.132' ], }
IPv6 Next Hop:
{ 'NEXT_HOP' => [ '2001:db8::1', 'fe80::dead:beef' ], }
MP_REACH_NLRI carries global and link-local next-hop addresses. As result, this attribute contains one or two entries in array.
In case, when entry will erroneously contain NEXT_HOP and MP_REACH_NLRI, then resulting array will contain all of NEXT_HOP entries in one array.
NEXT_HOP
MP_REACH_NLRI
{ 'MULTI_EXIT_DISC' => 2140, }
{ 'LOCAL_PREF' => 2140, }
{ 'ATOMIC_AGGREGATE' => 1, }
Atomic aggregate is a flag. So, hash element with undefined value will be present if this flag is set. Check for this flag using exists() function:
exists()
if (exists $_->{'ATOMIC_AGGREGATE'}) ...
{ 'AGGREGATOR_AS' => 65501, 'AGGREGATOR_BGPID' => '10.12.14.1', }
Aggregator decoded into two elements AGGREGATOR_AS & AGGREGATOR_BGPID. As per "AS_PATH", the AGGREGATOR_AS also have 4 octets.
AGGREGATOR_AS
AGGREGATOR_BGPID
{ 'COMMUNITY' => [ '1:2', '3:4', ], }
Communities decoded as array of communities (16 bit:16 bit)
Refer to NEXT_HOP attribute.
NOTE: The MP_REACH_NLRI attribute can be decoded as per RFC4760 or RFC6396.
Due to recent changes in Quagga/RIPE RIS, the collected MRT data does not follow RFC6396 and the MP_REACH_NLRI should be decoded as described in RFC4760
The $Net::MRT::USE_RFC4760 global variable control Net::MRT behavior:
$Net::MRT::USE_RFC4760
$Net::MRT::USE_RFC4760 = 1; - Decode as described in RFC4760
$Net::MRT::USE_RFC4760 = 1;
$Net::MRT::USE_RFC4760 = undef; - Decode as described in RFC6396 (default behavior). Please note that only NEXT-HOP will be decoded.
$Net::MRT::USE_RFC4760 = undef;
$Net::MRT::USE_RFC4760 = -1; - Do not decode MP_REACH_NLRI at all.
$Net::MRT::USE_RFC4760 = -1;
http://tools.ietf.org/html/rfc6396
http://www.ripe.net/data-tools/stats/ris/ris-raw-data
http://www.quagga.net
http://tools.ietf.org/html/rfc4760
MaxiM Basunov, <maxim.basunov@gmail.com>
See the Changes file.
Copyright (C) 2013 MaxiM Basunov <maxim.basunov@gmail.com> All rights reserved.
This program is free software; you may redistribute it and/or modify it under the same terms as Perl itself.
To install Net::MRT, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Net::MRT
CPAN shell
perl -MCPAN -e shell install Net::MRT
For more information on module installation, please visit the detailed CPAN module installation guide.