Mesh and BGP¶
With annet you can configure device BGP session and interfaces based on common rules and connections with other devices.
Configuring mesh¶
To setup configuration you need create an instance of MeshRulesRegistry and attach handlers of 3 types:
.devicehandlers setup device global configuration.directhandlers can be used to setup relation between directly connected devices.indirecthandlers can be used to setup configuration related to devices which do not have direct connection
The naming .indirect reflects the uses cases, it doesn’t control to connection of devices: neither they are rechable or connected directly.
from annet.mesh import (
MeshRulesRegistry, GlobalOptions, MeshSession, DirectPeer, IndirectPeer,
)
registry = MeshRulesRegistry()
@registry.device("{name:.*}")
def foo(global_opts: GlobalOptions):
...
@registry.direct("{name:.*}.left.example.com", "{name:.*}.right.example.com")
def bar(local: DirectPeer, neighbor: DirectPeer, session: MeshSession):
...
@registry.indirect("{name:.*}.left.example.com", "{name:.*}.other.example.com")
def baz(device: IndirectPeer, neighbor: IndirectPeer, session: MeshSession):
...
Filtering devices¶
To select handler you set the device filters. They consist of two parts: name mask and filter expression.
name mask is a string which describes device FQDN, optionally containing placeholders for captured variables. Place holders can be of two forms:
{var}means a variable containing any non-negative integer number. You will be abel to access it in your handler as an integer attribute.{var:regex}means a string matching regular expression. You will be abel to access it in your handler as an string attribute.
Additionally, you can set a filter expression based on captured variables using magic filters.
Use Match for device handler, and Left and Right for direct/indirect handlers.
For example, here
foofunction will be applied to any device with number from 0 to 100 afterhost-prefix in subdomain.barwill be applied to the pair of hosts with same top level domain and where the left number is less than right one
from annet.mesh import Match, Left, Right
@registry.device("host-{num}.{domain:.*}", Match.num<100)
def foo(global_opts: GlobalOptions):
...
@registry.direct(
"host-{num}.{domain:.*}", "host-{num}.{domain:.*}",
Left.num < Right.num,
Left.domain == Right.domain,
)
def bar(local: DirectPeer, neighbor: DirectPeer, session: MeshSession):
...
If you need more complex filters or check not only the FQDN, you should do the check inside handler and return from it without any modifications.
Short name filters¶
Devices are normally filtered based on FQDN, but can set registry to use only short name (subdomain). This is done setting match_short_name in the registry constructor.
Note, that is only applied for specific registry and does not affect others, even included.
registry = MeshRulesRegistry(match_short_name=True)
Accessing captured variables¶
Variables captured from hostname are available via .match attribute of GlobalOptions, DirectPeer and IndirectPeer objects.
@registry.device("host-{num}.{domain:.*}")
def foo(global_opts: GlobalOptions):
print(global_opts.match.num)
Accessing device data¶
Device instance is accessible via .device attribute of GlobalOptions, DirectPeer and IndirectPeer objects.
DirectPeer additionally has ports field with names of interfaces used for a connection between devices
(the order is preserved for both sides)
@registry.direct("host-{num}.{domain:.*}", "host-{num}.{domain:.*}")
def bar(local: DirectPeer, neighbor: DirectPeer, session: MeshSession):
print(local.device.fqdn)
print(local.device.ports)
Filling mesh data¶
Each handler can fill predefined attributes in GlobalOptions, DirectPeer, IndirectPeer and Session objects,
this includes peer groups, vrf, interfaces used for BGP session and various options.
Configuration, received from different handlers will be merged together.
You cannot set different values for the same option in different handlers, but complex objects are merged recursively.
Session object contains data which is applied to both peers.
Minimum of data required to be filled is DirectPeer and IndirectPeer
addrremote_asfamilies
Bgp session is expected to be set on single interface and you can choose it from these options:
(default) the single physical interface through which the connection is made (with validation if it is the only one)
sub-interface in case it is the one interface available
lag, containing all interfaces holding the connection between devices
subif for the lag
svi
The selection is done using lag, svi or subif attributes correspondingly.
Accessing mesh data from generators¶
Mesh is not processed automatically, to use it from generator you need:
Import your
MeshRulesRegistryinstance. You can useregistry.includeto combine rules from multiple registries.Create executor:
MeshExecutor(registry, device.storage)Run it against the device
res = executor.execute_for(device). Additionally to the result, the device can be modified to store additional interfacesUse the result or patched device to generate BGP configuration.