NAME

SNMP::Info::VRF - SNMP Interface to VRF (virtual routing and forwarding) instances

AUTHOR

SNMP::Info Developers

SYNOPSIS

# Let SNMP::Info determine the correct subclass for you.
my $vrf = new SNMP::Info(
    AutoSpecify => 1,
    Debug       => 1,
    DestHost    => 'myrouter',
    Community   => 'public',
    Version     => 2
) or die "Can't connect to DestHost.\n";

my $instances = $vrf->vrf_instances();
foreach my $name ( sort keys %$instances ) {
    my $subnets = $vrf->vrf_subnets($name);
    print "$name: $_\n" foreach sort keys %$subnets;
}

DESCRIPTION

SNMP::Info::VRF is a role that reports a device's routing instances: which instances exist, which ports belong to each, and each instance's neighbors, interface addresses and subnets. It lists them from MPLS-L3VPN-STD-MIB, or from a vendor MIB a device class reads, and reads their rows from the standard address, neighbor and route tables.

The global routing table is always the instance default, of kind default. A row the device returns named default is that same instance, not a second one.

The role reports only what the device returns. It never invents an instance. The one exception is names you pass to vrf_instances(), which are marked as yours. Data the device does not return is undef or a missing key, never a guessed value.

This class is inherited by SNMP::Info::Layer3.

Terms

instance

One routing table on the device: the global table (default), a VRF, or a virtual router.

context

An SNMP context, as "SNMP Contexts" in SNMP::Info describes. A session reads one context at a time.

default context

The context that serves the global routing table. SNMPv3 reaches it with an empty Context. SNMPv1 and SNMPv2c reach it with the constructor's Community, unless the device maps that community to a VRF context.

served

Returned by the device in an SNMP response.

list source

The MIB that lists the instances: MPLS-L3VPN-STD-MIB, or, where that serves no instance row, a vendor MIB the device class reads. Each record names it in sources{list}.

membership table

The table that maps ports to instances: mplsL3VpnIfConfTable, plus the class's vendor table where that vendor table is the list source (MPLS-L3VPN-STD-MIB served no instance row). In attribution mode i_vrf() returns it.

attribution mode

The default context serves every instance's rows. The readers keep the rows on the instance's ports, as the membership table gives them. This class uses attribution mode.

context mode

Each instance's rows are read in that instance's own context. The readers keep the rows on that context's ports. A device class selects this mode.

leaking default context

In context mode, a default context that also serves other instances' rows on their ports.

caller names

Instance names you pass to vrf_instances(\@names).

reader

vrf_neighbors(), vrf_addresses() and vrf_subnets(), which take an instance name.

internal instance

A name the platform uses for itself, which the device class never lists.

Inherited Classes

None.

Required MIBs

MPLS-L3VPN-STD-MIB
IP-FORWARD-MIB

Instance Records

vrf_instances() returns a hash of records keyed by instance name. Every record has these keys:

name

The instance name, as the device names it.

kind

default for the global routing table, vrf for a VRF, and virtual-router for a Junos virtual router or management instance (SNMP::Info::Layer3::Juniper). A caller name is kind vrf.

description

The description MPLS-L3VPN-STD-MIB serves, or undef. An empty string is undef.

oper

The instance's operational state, up or down, where the device reports one (MPLS-L3VPN-STD-MIB mplsL3VpnVrfOperStatus only); undef otherwise.

rd

The route distinguisher, such as 64512:30. A printable value is kept as served; a binary one is shown as colon-separated hex octets. Undef when the device serves none, an empty string or 0:0.

rt_import, rt_export

Array references of route targets, sorted. A target of type both is in each list. Empty when none are served.

l3_vni

Reserved; always undef.

l3_isid

On VOSS, the I-SID of the instance's IP VPN; undef elsewhere (SNMP::Info::Layer3::Extreme).

listed_by

device when the device listed the instance; caller when it came from the names you passed to vrf_instances().

sources

Where each fact came from: a hash of fact to the MIB that served it. A fact the device did not serve has no key. A caller name has no keys.

list

The list source that listed the instance. The record default has this key when a list source served any row, or, for some vendor sources, answered with none; see "Completeness".

members

The membership table's MIB, when that table gives the instance at least one port.

rd

Present when rd is defined.

rt

Present when the instance has a route target.

l3_isid

Present when l3_isid is defined.

contexts

How to reach the instance's rows, as an array of contexts in the form snmp_context() in SNMP::Info returns. { kind => 'none' } is the default context. See "Reading Instances".

An example record:

red => {
    name        => 'red',
    kind        => 'vrf',
    description => undef,
    oper        => 'up',
    rd          => '64512:30',
    rt_import   => [ '64512:30' ],
    rt_export   => [ '64512:30' ],
    l3_vni      => undef,
    l3_isid     => undef,
    listed_by   => 'device',
    sources     => {
        list    => 'MPLS-L3VPN-STD-MIB',
        members => 'MPLS-L3VPN-STD-MIB',
        rd      => 'MPLS-L3VPN-STD-MIB',
        rt      => 'MPLS-L3VPN-STD-MIB',
    },
    contexts    => [ { kind => 'none' } ],
}

Row Shapes

i_vrf() maps ifIndex to instance name:

{ 2 => 'red', 3 => 'blue' }

vrf_neighbors($name) and vrf_addresses($name) key their rows by ifIndex then address. An address two instances share has one row in each. One instance can hold the same address on several ports, as with link-local addresses. Key rows by ifIndex and address, never by address alone:

# vrf_neighbors('red')
'2.10.40.0.2' => { ifindex => 2, ip => '10.40.0.2',
                   mac => '02:00:00:00:04:01', family => 'ipv4' }

# vrf_addresses('blue')
'3.10.40.0.1' => { ifindex => 3, ip => '10.40.0.1',
                   prefix_len => 24, family => 'ipv4' }

vrf_subnets($name) keys its rows by prefix and length. sources holds address, route, or both:

'10.40.0.0/24' => { prefix => '10.40.0.0', len => 24,
                    family => 'ipv4', ifindex => 3,
                    sources => [ 'address' ] }

An IPv6 address is eight groups of four hex digits, as ipv6_n2p_addr() in SNMP::Info::IPv6 returns it, with no zone.

Reading Instances

The per-instance readers work in one of two modes. The device class fixes the mode; see "Terms". context_kinds('vrf') tells them apart: it returns ['vrf'] in context mode and nothing in attribution mode.

In both modes, read vrf_instances() in the default context, and keep it. update() clears the cache.

Attribution mode

  • Every reader runs in the default context. You never switch contexts.

  • A reader keeps the rows on the ports i_vrf() gives the instance. A port i_vrf() does not list belongs to default.

  • A reader takes only names the device lists. A caller name returns nothing, with error() set.

  • Every record's contexts is [ { kind => 'none' } ], the default context.

my $instances = $vrf->vrf_instances();
my $complete  = $vrf->vrf_instances_complete();
my $ports     = $vrf->i_vrf();
foreach my $name ( sort keys %$instances ) {
    my $neighbors = $vrf->vrf_neighbors($name);
    my $addresses = $vrf->vrf_addresses($name);
    my $subnets   = $vrf->vrf_subnets($name);
    my $whole     = $vrf->vrf_read_complete($name);
}

Context mode

  • Read the instance default in the default context. Read every other instance in its own context: switch to it, read, then switch back.

  • The record default has contexts [ { kind => 'none' } ]. Every other record holds the one context snmp_context('vrf', $name) gives, or [] when that gives none. A record with contexts [] has no context, and no context serves its rows.

  • A context can serve rows of other instances, such as neighbors on their ports. The readers keep only the rows on the context's ports. By default those are the ports holding an address in the context's ipAddressTable or ipAdEntTable, or in a vendor address table the class reads.

  • A port with no address in its context, such as an unnumbered one, is in no instance, and its neighbors are dropped.

  • Some devices serve the whole address table in every context. There the context's ports are the interfaces its inetCidrRouteTable routes use (SNMP::Info::Layer3::Extreme).

  • In a leaking default context, the readers of default drop the rows on each port the membership table gives another instance (SNMP::Info::Layer3::Juniper).

  • The readers accept a caller name, provided the session is in the context snmp_context('vrf', $name) gives.

my $instances = $vrf->vrf_instances();
foreach my $name ( sort keys %$instances ) {
    # No context: the device gives this instance none to read in
    my $context = $instances->{$name}{contexts}[0] or next;
    # switch to $context->{v3} unless $name is default, then update()
    my $neighbors = $vrf->vrf_neighbors($name);
    my $whole     = $vrf->vrf_read_complete($name);
}

"SNMP Contexts" in SNMP::Info has a complete example that switches contexts.

Wrong context

A reader called in the wrong context returns nothing, with error() set to a message saying how to switch. The right context is:

  • In attribution mode, the default context, for every instance.

  • In context mode, the default context for default, and for any other instance the context snmp_context('vrf', $name) names.

The session's context

The readers take the session's context from, in order:

  1. The SNMPv3 Context.

  2. Over SNMPv1 or SNMPv2c, the part of the community beyond the constructor's Community and an @, on either side (public@red, red@public). Not where the device ignores the suffix and serves the default context (SNMP::Info::Layer3::Extreme on VOSS); there item 3 decides.

  3. Over SNMPv1 or SNMPv2c, the context the device maps the community to, where the class can read that mapping from the device (SNMP::Info::Layer3::Nexus, SNMP::Info::Layer3::Extreme on VOSS, where a community::vrfid community such as public::1 reaches a VRF).

Otherwise the session is in the default context. Where the class cannot read a community mapping, a mapped community reads as the default context, so use SNMPv3.

Completeness

vrf_instances_complete() returns one of four states:

unsupported, undef

No list source served a row, the device serves no configured VRF count, you passed no caller names, and every walk of a list source's tables finished. vrf_instances() lists only default.

none, 1

The device has no VRF. Either:

  • The device reports zero configured VRFs and no list source served a row.

  • A list source served rows, but none is a VRF: only the global row or an internal instance's. The device serves no configured VRF count, or a count of zero. The record default then names that list source in sources{list}, and caller names are ignored.

If you pass caller names in the first case, they are used, and the state is incomplete, 0.

In both cases vrf_instances() lists only default. Some list sources never serve a global row; see the class, such as SNMP::Info::Layer3::Arista.

incomplete, 0

The list may be short. Any one of these:

  • The list holds a caller name.

  • A walk of the list source's tables ended early: the VRF, route target or membership table of MPLS-L3VPN-STD-MIB, or the vendor tables a class reads. This holds even when the walk failed before returning a row, so no instance is listed: the device is not unsupported, it could not be read.

  • The device's configured VRF count is greater than the number of VRFs it lists.

  • In attribution mode, a listed VRF holds no port in i_vrf(), and the device either serves no configured VRF count or maps no port to any VRF.

complete, 1

None of the above: the list is whole, as far as the list source lists instances.

Completeness measures the list source only. Some platforms hold instances it does not list, such as virtual routers. Unless the class lists them from another source, even when vrf_instances_complete() returns 1:

  • They are absent from vrf_instances().

  • Their ports are absent from i_vrf().

  • Their rows are read as the instance default.

  • vrf_read_complete('default') does not detect those rows, since it checks only listed instances.

Collapsed Subnets

Some devices list an address that two instances share on only one of the ports in ipAddressTable and ipAdEntTable. The other instance then has no such address, and vrf_subnets() omits its subnet.

A class that reads routes restores the subnet. It adds each instance's connected routes with the source route: from mplsL3VpnVrfRteTable in attribution mode, or from inetCidrRouteTable in context mode. This class does not read routes.

For Class Authors

A device class shapes the readers by overriding private hooks of this role. Each item names the hook and a class that uses it.

Context mode

_vrf_context_filters returns true. Answer context_kinds('vrf') with ['vrf'] and snmp_context('vrf', $name) with each instance's context, through _context_kinds and _snmp_context (SNMP::Info::Layer3::Arista).

Leaking default context

_vrf_default_context_leaks returns true. The readers of default then drop the rows on ports the membership table gives another instance, and i_vrf() in the default context returns the membership table. An instance the membership table does not cover, such as a virtual router, cannot be told apart there: its rows stay in default, and vrf_read_complete('default') returns 0 while it is listed. A VRF MPLS-L3VPN-STD-MIB lists with no port has no rows to leak (SNMP::Info::Layer3::Juniper).

Membership in the default context

_vrf_default_context_members returns true where the default context serves only the default instance's rows but holds the membership table. i_vrf() there returns the membership table (SNMP::Info::Layer3::Arista).

Context named for its instance

_vrf_context_is_instance_name returns true where a context's name is its instance's name and the context serves no instance list. i_vrf() then takes the instance from the context name without reading the list (SNMP::Info::Layer3::Arista).

Ports from routes

_vrf_context_ports_from_routes returns true where every context serves the whole address table. The context's ports are then the interfaces of its inetCidrRouteTable routes. Override _vrf_route_ports to add ports a route's interface stands for (SNMP::Info::Layer3::Extreme, for an EXOS router interface).

Subnets from routes

_vrf_subnets_from_routes returns true to add connected routes to vrf_subnets(); see "Collapsed Subnets" (SNMP::Info::Layer3::Cisco).

_vrf_nd_from_ipv6_mib returns true where host link-local neighbors are only in IPV6-MIB ipv6NetToMediaTable. vrf_neighbors() then adds those rows, one per port and address, keeping the ipNetToPhysicalTable row where both tables list one (SNMP::Info::Layer3::H3C).

Vendor instance list

_vrf_vendor_instances returns records built with _vrf_record, each with sources{list} set. It is called only when MPLS-L3VPN-STD-MIB serves no instance row. Call _vrf_list_default when the vendor table served any row, so a device with no VRF reads none, not unsupported. _vrf_vendor_list_methods names the table methods it walks, which count toward vrf_instances_complete(). _vrf_vendor_membership returns the vendor table's { ifIndex => name }, used only when that vendor list is the list source (SNMP::Info::Layer3::Cisco).

Vendor addresses

_vrf_vendor_address_rows($name) returns address rows keyed and shaped as vrf_addresses() rows. They fill in a port and address the standard tables lack. Walk them with _vrf_column so they count toward vrf_read_complete() (SNMP::Info::Layer3::H3C).

Internal instances

_vrf_internal_instance($name) returns true for an instance name the platform uses internally, which is never listed (SNMP::Info::Layer3::Juniper).

Community-mapped contexts

_vrf_community_context returns the context the device maps an SNMPv1 or SNMPv2c session's community to: a name, '' for the default context, or undef when the class cannot tell (SNMP::Info::Layer3::Nexus).

Community suffixes

_vrf_community_suffix_is_context returns false where the device ignores a community suffix such as public@vrf1 and serves the default context. The session's context then comes from _vrf_community_context only (SNMP::Info::Layer3::Extreme). The base returns true.

GLOBALS

$vrf->vrf_configured()

Returns the number of VRFs the device says it configures.

(mplsL3VpnConfiguredVrfs)

TABLE METHODS

VRF Instances

vrf_instances() and vrf_instances_complete() read the default context only, since only the default context serves the whole list. In any other context they return nothing, with error() set. i_vrf() follows the same rule in attribution mode; in context mode it works in any context.

$vrf->vrf_instances( [ \@names ] )

Returns a hash of instance records keyed by name, always including default. See "Instance Records".

Some devices do not list their VRFs over SNMP (ExtremeXOS). For those, pass the names you know in \@names. They are used only when the device lists no instance at all, and each is returned with listed_by set to caller, so you can tell your names from the device's. When the device lists instances, \@names is ignored.

A list source that served only a global or internal row still lists default, so \@names is ignored there too; see "Completeness". In attribution mode the readers return nothing for a caller name; see "Reading Instances".

(mplsL3VpnVrfDescription, mplsL3VpnVrfRD, mplsL3VpnVrfOperStatus, mplsL3VpnVrfRT, mplsL3VpnIfConfRowStatus, or a class's vendor tables where MPLS-L3VPN-STD-MIB serves no instance row)

$vrf->vrf_instances_complete( [ \@names ] )

Returns 1, 0 or undef, as "Completeness" describes. Pass the same names you gave vrf_instances(). 0 includes a list walk that failed before returning a row; undef means the walks finished and nothing was listed.

(mplsL3VpnConfiguredVrfs and the walk_status() of the list source's tables)

$vrf->i_vrf()

Returns reference to hash of instance name, keyed by ifIndex.

In attribution mode, it returns the membership table: the active rows of mplsL3VpnIfConfTable, plus the class's vendor table where that vendor table is the list source (MPLS-L3VPN-STD-MIB served no instance row). MPLS-L3VPN-STD-MIB wins for a port both name. Ports of default are absent.

In context mode, it maps the ports of the instance whose context the session is in:

  • In the default context, it maps the context's ports to default. Where the class's default context leaks, or maps every instance's ports from the membership table, it returns that table instead.

  • In another context, it maps the context's ports to the instance the device lists with this context. Caller names are not consulted. In a context no device-listed instance has, it returns nothing, with error() set.

  • Where the class names each context for its instance, it maps the ports to the context name instead, without reading the list.

The context's ports are those "Reading Instances" describes for context mode.

(mplsL3VpnIfConfRowStatus, with a class's vendor table where MPLS-L3VPN-STD-MIB lists no instance (see "For Class Authors"); in context mode ipAddressIfIndex, ipAddressType, ipAddressPrefix, ipAdEntIfIndex and ipAdEntNetMask, or inetCidrRouteIfIndex with the class's tables)

Instance Readers

Each reader takes an instance name. It returns nothing, with error() set:

  • in the wrong context; see "Reading Instances";

  • in attribution mode, for a name vrf_instances() does not list.

A class with no source table for a reader contributes no rows to it.

$vrf->vrf_neighbors($name)

Returns reference to hash of the ARP and IPv6 neighbor rows of instance $name, keyed as at_paddr() and ipv6_n2p_mac() key them. Each row holds ifindex, ip, mac and family (ipv4 or ipv6). Rows a class adds from ipv6NetToMediaTable are keyed by ifIndex then the sixteen address octets, as that table indexes them.

These rows are not returned:

  • A row whose MAC is undef, empty or all zeros. It names no hardware address; devices serve their own addresses that way.

  • A row at the broadcast MAC, such as a subnet broadcast address.

  • A row for an address other than a link-local one that vrf_addresses($name) holds on any port.

  • A row for a link-local address vrf_addresses($name) holds on the row's port.

  • A row whose MAC is the ifPhysAddress of the row's port. This drops the device's own row on a port whose address table does not list the address, such as the other instance's copy of a shared address (see "Collapsed Subnets").

The neighbor type is not used: some devices type a host's link-local local, and others type their own addresses static.

Which rows belong to $name:

  • In attribution mode, the rows on the ports i_vrf() gives the instance.

  • In context mode, the rows on the context's ports (see "Reading Instances"). For default in a leaking default context, the rows on ports the membership table gives another instance are dropped.

(at_paddr() and at_netaddr(), with the fallbacks to atTable and ipNetToPhysicalTable of SNMP::Info::Layer3, the ipv6_n2p_* methods of SNMP::Info::IPv6, ipv6NetToMediaPhysAddress where the class reads it, vrf_addresses() and i_mac())

$vrf->vrf_addresses($name)

Returns reference to hash of the interface addresses of instance $name, keyed by ifIndex and address. Each row holds ifindex, ip, prefix_len (undef when the device gives none) and family.

The rows come from ipAddressTable. ipAdEntTable is read for IPv4 only when ipAddressTable serves no IPv4 row. A class may add vendor rows for a port and address the standard tables lack.

  • Rows typed unicast or anycast are kept. An anycast address is still the device's own, and some devices type their IPv6 interface addresses so. A class that reads IPV6-MIB ipv6AddrTable keeps its anycast rows as well.

  • Two rows on one port that differ only by zone are one address. The row first in sorted index order is kept.

  • The unspecified address, IPv4 0.0.0.0 or IPv6 ::, is no interface address and is dropped.

Which rows belong to $name:

  • In attribution mode, the rows on the ports i_vrf() gives the instance.

  • In context mode, every row the context serves. For default in a leaking default context, the rows on ports the membership table gives another instance are dropped.

  • In context mode where routes decide a context's ports, only the rows on the context's ports.

(ipAddressIfIndex, ipAddressType, ipAddressPrefix, ipAdEntIfIndex, ipAdEntNetMask)

$vrf->vrf_subnets($name)

Returns reference to hash of the subnets of instance $name, keyed prefix/len. Each holds prefix, len, family, ifindex and sources. sources lists:

  • address, for the network of an interface address that has a prefix length;

  • route, for a connected route, where the class reads routes (see "Collapsed Subnets").

address comes first when both apply. ifindex is undef for a route with no interface. These are not subnets:

  • an IPv6 link-local network (fe80::/10), from an address or a route;

  • a host route;

  • a route-only prefix in special-purpose space: IPv4 0.0.0.0/8, 127.0.0.0/8, 224.0.0.0/4 and 255.255.255.255/32, IPv6 ::/127 and ff00::/8.

An interface address in IPv4 or IPv6 special-purpose space other than link-local still gives a subnet.

(vrf_addresses(), mplsL3VpnVrfRteInetCidrProto, mplsL3VpnVrfRteInetCidrIfIndex, inetCidrRouteProto, inetCidrRouteIfIndex)

$vrf->vrf_read_complete($name)

Says whether the readers saw the whole of every table they walked for $name. Call it after the readers, in the same context: clear_cache(), and so update(), forgets which tables were walked.

whole, 1

Every table walked for $name was read whole. A table the device does not implement counts as whole.

partial, 0

A table walked for $name was cut short (see "Incomplete Walks" in SNMP::Info).

In the default context of a class whose default context leaks, vrf_read_complete('default') is also 0 when:

  • a listed instance, not listed by MPLS-L3VPN-STD-MIB, holds no port in the membership table;

  • a walk of the instance list ended early.

unknown, undef

No table has been recorded as walked for $name since the cache was last cleared. The readers record their walks. In context mode, so does i_vrf(), except where it returns the membership table in the default context.

(walk_status() of the tables walked for $name: the readers' source tables, ifPhysAddress, and the tables that decide membership: mplsL3VpnIfConfRowStatus and the class's vendor tables in attribution mode; in context mode the address tables, or where routes decide a context's ports, inetCidrRouteIfIndex and the class's tables, and for default in a leaking default context mplsL3VpnIfConfRowStatus)

MPLS-L3VPN VRF Table (mplsL3VpnVrfTable)

$vrf->vrf_l3vpn_descr()

(mplsL3VpnVrfDescription)

$vrf->vrf_l3vpn_rd()

(mplsL3VpnVrfRD)

$vrf->vrf_l3vpn_oper()

(mplsL3VpnVrfOperStatus)

MPLS-L3VPN Interface Table (mplsL3VpnIfConfTable)

$vrf->vrf_l3vpn_if()

(mplsL3VpnIfConfRowStatus)

MPLS-L3VPN Route Target Table (mplsL3VpnVrfRTTable)

$vrf->vrf_l3vpn_rt()

(mplsL3VpnVrfRT)

MPLS-L3VPN VRF Route Table (mplsL3VpnVrfRteTable)

$vrf->vrf_l3vpn_rte_if()

(mplsL3VpnVrfRteInetCidrIfIndex)

$vrf->vrf_l3vpn_rte_proto()

(mplsL3VpnVrfRteInetCidrProto)

IP Forwarding Table (inetCidrRouteTable)

Read only in context mode.

$vrf->vrf_cidr_if()

(inetCidrRouteIfIndex)

$vrf->vrf_cidr_proto()

(inetCidrRouteProto)