The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

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.