Project Details

  ReadmeDownload 

Download Version 0.3


Download dev snapshot
View Licence

Introduction

Tangle is a tool to help you document networks.

It takes a text file that lists:

...and how they interconnect.

It can then convert that file into a heavily cross-referenced HTML document listing all the components of your network. Every device will list every cable that connects to it (specifying the VLAN(s), IPv4 addresses and so on), and clicking on a cable will lead to a list of all devices and VLANs on that cable; clicking on a VLAN will lead to a list of all devices and IPv4 subnets on the cable; and clicking on an IPv4 address or subnet will go to a list of all the IPv4 addresses on that subnet, and so on.

It also outputs several "dot" files for GraphViz. The default makefile produces three diagrams: one for physical network cabling, one for logical network connectivity (showing what devices are on which VLANs), and one showing management cabling (power, serial, and KVM).

It is written in Python, and consists of two layers: a network parser library which reads the network description file, checks it for errors (duplicate IP addresses, etc), and produces an in-memory cross-referenced object graph; and then a set of scripts that use that library to generate the HTML and "dot" output formats. You can write your own scripts that do other things with the data (such as generating reverse DNS zonefiles).

Using it

A simple (all too simple) driver shell script is supplied, called document-network.sh, that runs parts of Tangle to make a veritable soup of network documentation.

Try it out on the supplied examples. From this directory, run:

./document-network.sh examples/home-lan.tangle
./document-network.sh examples/office-lan.tangle

...then look at the HTML and PNG files that appear in the examples directory.

The tangle file format

The network consists of cables, vlans, devices, and ip4 subnets.

Cables

Each cable starts with a line of the form:

{utp|serial|fibre|power|kvm|virtual|usb|telephone|parallel|other|unused} <name> {

Cables all need unique names. Ideally, they should be numbered, with the number written on the cable (http://www.partex.com/ sell nice clip-on cable numbers). If you have a multi-location system you can reuse cable numbers within a location, and write the cable names in your Tangle file as ".".

Virtual cables are used for internal management interfaces in switches; they don't exist in the real world, but exist to show that a virtual port inside a device is connected to something, somehow.

Unused cables are special virtual cables used to group unused ports on devices together. Each unused declaration creates a pool of unused ports, which is connected with device statements to unused ports on devices. Within the system an unused port pool is really just a cable, but the display of the cable is modified slightly - it's not considered to actually link any ports together, and unused port pools are listed separately to cables in the table of contents. You don't have to declare your unused ports, but doing so makes it easy to see what ports you have spare.

A cable declaration is ended with a closing brace:

}

Within are lines defining the details of the cable:

device <name>/<port>

Declares that this cable goes to the given device on the given port. Since this is a cabling document, the device names should be in terms of people looking at the outside of the device - how the physical socket is labelled, or some other obvious designation; a server may refer to eth0 internally, but unless you stick a label saying eth0 on the outside of your server (which is a good idea!), a name like left might be more useful to the people who go to the datacenter to re-cable your server.

If you don't know what port it's plugged into, as you have incomplete information, just use ? as the port name. This will suppress errors about multiple cables going into the same port, as many cables will probably go to the ? port on a device.

Device names can be of the form <owner>:<device>. If so, the owning organisation can be declared with an organisation block, to attach metadata, as described below.

vlan <vlan>

For Ethernet cables, the untagged VLAN carried on this cable. VLAN names must be unique; if you reuse VLAN names or numbers in different contexts, name them <location>.<id>. It is suggested that you use the actual VLAN ID as the ID (eg, the number you configure into the switch), but you can use any alphanumeric string as the ID.

tagged vlans <vlan>,<vlan>,...

For Ethernet cables, the list of tagged VLANs carried on this cable.

note "<text>"

General notes to sysadmins. There can be more than one.

Devices

We can also optionally provide extra data about devices with a device declaration:

device <name> {
  ...
}

If a cable refers to a device with no device declaration, that's fine - we just don't know anything about the device other than what cables plug into it. It's a black box.

Within a device declaration, we allow note declarations, and these specialist declarations:

type {server|switch|router|manager|power|external|virtual|workstation|printer|telephone|firewall|other}

This declares the type of device, which affects how it is displayed in diagrams, and how it is categorised in the HTML output.

ip4 <port> [<vlan>] <ip> [shared|stub]

This declares that a given port of the device, optionally specifying a vlan for tagged ports, has a given IPv4 address. There can be more than one ip4 declaration for a given vlan on a given port, and more than one vlan on a port, as you would expect. An IP address that appears on more than one port (eg, HSRP / CARP) should be marked shared to suppress warnings about the duplication. An IP address that does not need to match a subnet (eg, a /32 address set up on a Cisco router's loopback interface) can be declared 'stub' to suppress warnings about that, too.

mac <port> [<vlan>] <mac> [shared]

This declares that a given port of the device (again, optionally specifying a vlan for tagged ports), has a given MAC address. The address should be in xx:xx:xx:xx:xx:xx form, but omitting the colons or using other characters (spaces, hypens) is also acceptable. Re-using the same MAC will cause warnings, unless shared is specified.

Some devices are virtual - VMs, for example. We can express this fact by declaring that the physical server hosts the virtual server like so:

hosts <device>

Note that the system makes no real distinction between physical and virtual devices. They can nest arbitrarily; you can have VMs within VMs.

VM host servers should declare a virtual cable that carries appropriate vlans to ports on virtual machines, and which plugs into an internal virtual port in the VM server, to explain how the VMs get network connectivity.

VLANs

Likewise, we can provide extra information about a VLAN with a vlan declaration:

vlan <name> {
  ...
}

Again, we can use note declarations within a VLAN.

title "<title>"

This gives the VLAN a meaningful title, since VLAN 'names' are usually just the VLAN numbers.

ip4 subnet <ip>/<prefixlen> "<title>" [multiple]

This declares that a given IPv4 subnet exists on the VLAN. There can be more than one. The same ip range can exist on different VLANs, too, but this will cause a warning unless the multiple flag is given, as this state of affairs is sometimes legitimate (eg, when doing BGP anycast routing, or an IPv4 subnet appears on different VLANs in different locations)

ip4 reserved <ip1>-<ip2> "<description>"

This declares that a range of ip4 addresses are reserved for something. This allocates the IP4s as being in use, as if a port on the vlan were assigned an IP, but without a port being required. It's perfect for IP ranges set aside for future use, or for DHCP / VPN / dialup address pools.

Organisations

Finally, we can declare information about organisations.

organisation <code> {

The code of the organisation is the short name used before the colon in the name of a device.

Within an organisation, we can specify a longer name using a title declaration:

title "<name>"

And general notes:

note "<text>"

And details of authorised and emergency contacts:

contact [authorised|emergency] "<text>"

History

Version 0.3

Added MAC address support

Version 0.2

Added the office-lan example, and improved the rendering logic

Version 0.1

Initial public release

TODOs

Generalise VLANs

Having multiple virtual circuits over one cable can be useful for:

We can currently create VLANs on non-Ethernet cables, just it looks odd; they should be renamed from "VLANs" to "virtual circuits" or some shorter phrasing.

Suggestion: s/vlan/circuit/ but keep "vlan" as a parser-level synonym.

And add a "type" declaration within a circuit declaration, with values matching the same types allowed for cables.

Generalise device/cable types

The core engine has a fixed list of device and cable types (and vlan types?), even though it doesn't really care what they are. Front-end scripts tend to care more, as they often invoke special rendering for particular types of object.

Adding to this list involves extending the parser regexps, extending the documentation, and then extending the various rendering scripts.

It might be nice to have a configuration file that lists all the types of typable things, and then listing key=value properties for them. The parser can generate its regexps from the lists, and then frontends can look up keys to find styling information for specific types.

Make better use of more node shapes:

http://www.graphviz.org/doc/info/shapes.html

Also, make use of colour to better distinguish node and link types in the graphviz outputs.

Minor issues