NAME

Net::MRT - Perl extension for decoding RFC6396 Multi-Threaded Routing Toolkit (MRT) Routing Information Export Format

SYNOPSIS

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.

DESCRIPTION

"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

EXPORT

None by default.

Methods

Net::MRT::mrt_read_next

{
    'timestamp' => 1222905597,
    'type' => X,
    'subtype' => Y,
    other decoded elements,
};

In case of unsupported type/subtype an error message is returned in error.

{
    'timestamp' => Z,
    'type' => X,
    'subtype' => Y,
    'error' => 'Unsupported MRT type X subtype Y in message at N',
};

TODO TODO

Net::MRT::mrt_decode_single

TODO TODO

Examples of decoded messages

Type=13 TABLE_DUMP_V2

Subtype=1 PEER_INDEX_TABLE

{
    '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.

Subtype=2 RIB_IPV4_UNICAST & Subtype=4 RIB_IPV6_UNICAST

{
    '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.

Decoding of BGP attributes

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.

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.

Unsupported (by Net::MRT) attributes reported as 'unsupportedX' where X is a BGP attribute code.

ORIGIN

{ '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

{
  '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.

- "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."

NEXT_HOP

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.

MULTI_EXIT_DISC

{ 'MULTI_EXIT_DISC' => 2140, }

LOCAL_PREF

{ 'LOCAL_PREF' => 2140, }

ATOMIC_AGGREGATE

{ '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:

if (exists $_->{'ATOMIC_AGGREGATE'}) ...

AGGREGATOR

{ '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.

COMMUNITY

{ 'COMMUNITY' => [
    '1:2',
    '3:4',
], }

Communities decoded as array of communities (16 bit:16 bit)

MP_REACH_NLRI

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 = 1; - Decode as described in RFC4760

  • $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 = -1; - Do not decode MP_REACH_NLRI at all.

SEE ALSO

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

AUTHOR

MaxiM Basunov, <maxim.basunov@gmail.com>

MODIFICATION HISTORY

See the Changes file.

COPYRIGHT AND LICENSE

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.