1
0
mirror of https://github.com/rtbrick/bngblaster.git synced 2024-05-06 15:54:57 +00:00
2022-04-06 23:09:40 +02:00

566 lines
17 KiB
ReStructuredText

.. _isis:
ISIS
----
Intermediate System to Intermediate System (ISIS, also written IS-IS)
is a routing protocol designed to move information efficiently within
a network.
The ISIS protocol is defined in ISO/IEC 10589:2002 as an international
standard within the Open Systems Interconnection (OSI) reference design.
The Internet Engineering Task Force (IETF) republished ISIS in RFC 1142,
but that RFC was later marked as historic by RFC 7142 because it republished
a draft rather than a final version of the ISO standard, causing confusion.
ISIS has been called the de facto standard for large service provider
network backbones.
The BNG Blaster is able to emulate multiple ISIS instances. An ISIS instance
is a virtual ISIS node with one or more network interfaces attached. Such a
node behaves like a "real router" including database synchronization and
flooding. Every instance generates a ``self`` originated LSP describing the
node itself.
Configuration
~~~~~~~~~~~~~
Following an example ISIS configuration with one instance
attached to two network interfaces.
.. code-block:: json
{
"interfaces": {
"network": [
{
"interface": "eth1",
"address": "10.0.1.2/24",
"gateway": "10.0.1.1",
"address-ipv6": "fc66:1337:7331:1::2/64",
"gateway-ipv6": "fc66:1337:7331:1::1",
"isis-instance-id": 1,
"isis-level": 1,
"isis-l1-metric": 100,
},
{
"interface": "eth2",
"address": "10.0.2.2/24",
"gateway": "10.0.2.1",
"address-ipv6": "fc66:1337:7331:2::2/64",
"gateway-ipv6": "fc66:1337:7331:2::1",
"isis-instance-id": 1
}
]
},
"isis": [
{
"instance-id": 1,
"system-id": "0100.1001.0010",
"router-id": "10.10.10.10",
"hostname": "R1",
"area": [
"49.0001/24",
"49.0002/24"
],
"hello-padding": true,
"lsp-lifetime": 65535,
"level1-auth-key": "secret",
"level1-auth-type": "md5",
"sr-base": 2000,
"sr-range": 3600
}
]
}
.. include:: ../configuration/isis.rst
The support for multiple instances allows different use cases. One example might
be to create two instances connected to the device or network under test. Now
inject a LSP on one instance and check if learned over the tested network on
the other instance.
Every ISIS instance can be also connected to an emulated link state graph loaded
by MRT files as shown in the example below.
.. image:: ../images/bbl_isis.png
:alt: ISIS
.. code-block:: json
{
"isis": [
{
"instance-id": 1,
"system-id": "0100.1001.0011",
"router-id": "10.10.10.11",
"hostname": "B1",
"external": {
"mrt-file": "test.mrt",
"connections": [
{
"system-id": "0000.0000.0001",
"l1-metric": 1000,
"l2-metric": 2000
}
]
}
},
{
"instance-id": 1,
"system-id": "0100.1001.0011",
"router-id": "10.10.10.12",
"hostname": "B2"
}
]
}
.. include:: ../configuration/isis_external.rst
The The node ``N1`` in this example also needs to advertise the
reachability to the node ``B1``.
.. include:: ../configuration/isis_external_connections.rst
Adjacencies
~~~~~~~~~~~
The BNG Blaster supports P2P adjacencies with 3-way-handshake only.
``$ sudo bngblaster-cli run.sock isis-adjacencies``
.. code-block:: json
{
"status": "ok",
"code": 200,
"isis-adjacencies": [
{
"interface": "eth1",
"type": "P2P",
"level": "L1",
"instance-id": 2,
"adjacency-state": "Up",
"peer": {
"system-id": "0100.1001.0022"
}
},
{
"interface": "eth2",
"type": "P2P",
"level": "L1",
"instance-id": 1,
"adjacency-state": "Up",
"peer": {
"system-id": "0100.1001.0021"
}
}
]
}
Database
~~~~~~~~
The BNG Blaster distinguishes between three different source types of
LSP entries in the ISIS database.
The type ``self`` is used for the self originated LSP describing the own
BNG Blaster ISIS instance. LSP entries of type ``adjacency`` are learned
via ISIS adjacencies. The type ``external`` is used for those LSP entries
learned via MRT files or injected via ``isis-lsp-update`` :ref:`command <api>`.
``$ sudo bngblaster-cli run.sock isis-database instance 1 level 1``
.. code-block:: json
{
"status": "ok",
"code": 200,
"isis-database": [
{
"id": "0000.0000.0001.00-00",
"seq": 1,
"lifetime": 65535,
"lifetime-remaining": 65529,
"source-type": "external"
},
{
"id": "0100.1001.0011.00-00",
"seq": 2,
"lifetime": 65535,
"lifetime-remaining": 65507,
"source-type": "self"
},
{
"id": "0100.1001.0021.00-00",
"seq": 2,
"lifetime": 65524,
"lifetime-remaining": 65506,
"source-type": "adjacency",
"source-system-id": "0100.1001.0021"
},
{
"id": "0100.1001.0022.00-00",
"seq": 2,
"lifetime": 65524,
"lifetime-remaining": 65506,
"source-type": "adjacency",
"source-system-id": "0100.1001.0021"
}
]
}
The BNG Blaster automatically purges all LSP's of type
``self`` and ``external`` during teardown. This is done by
generating LSP's with a newer sequence numbers and lifetime
of 30 seconds only. This lifetime is enough to flood the purge
LSP over te whole network under test.
Flooding
~~~~~~~~
The BNG Blaster floods LSP's received to all other active
adjacencies of the ISIS instance except to those with peer
system-id equal to the source system-id of the LSP.
Limitations
~~~~~~~~~~~
Currently only ISIS P2P links are supported. There is also
no support for route leaking between levels.
MRT Files
~~~~~~~~~
The BNG Blaster is able to load LSP's from a MRT file as defined in
[RFC6396](https://datatracker.ietf.org/doc/html/rfc6396).
.. code-block:: none
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Timestamp |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Type | Subtype |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Message... (variable)
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
The message field contains the complete ISIS LSP PDU including
the ISIS common header starting with ``0x83``.
Those files can be loaded at startup via configuration option
``"isis": { "external": { "mrt-file": "<file>" } }`` or alternative
via ``isis-load-mrt`` :ref:`command <api>`.
``$ sudo bngblaster-cli run.sock isis-load-mrt file test.mrt instance 1``
LSP Update Command
~~~~~~~~~~~~~~~~~~
It is also possible to inject external LSP's using the ``isis-lsp-update``
:ref:`command <api>`.
The :ref:`command <api>` expects a list of hex encoded PDU's including
the ISIS common header starting with ``0x83``,
``$ cat command.json | jq .``
.. code-block:: json
{
"command": "isis-lsp-update",
"arguments": {
"instance": 1,
"pdu": [
"831b0100120100000021ffff010203040506000000000003c0d103010403490001",
"831b0100120100000021ffff010203040506000100000003bad603010403490001"
]
}
}
LSP Update via Scapy
~~~~~~~~~~~~~~~~~~~~
The following example shows how to generate LSP's via Scapy
and inject them using the ``isis-lsp-update`` :ref:`command <api>`.
.. code-block:: python
import sys
import socket
import os
import json
from scapy.contrib.isis import *
def error(*args, **kwargs):
"""print error and exit"""
print(*args, file=sys.stderr, **kwargs)
sys.exit(1)
def execute_command(socket_path, request):
if os.path.exists(socket_path):
client = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
try:
client.connect(socket_path)
client.send(json.dumps(request).encode('utf-8'))
data = ""
while True:
junk = client.recv(1024)
if junk:
data += junk.decode('utf-8')
else:
break
print(json.dumps(json.loads(data), indent=4))
except Exception as e:
error(e)
finally:
client.close()
else:
error("socket %s not found" % socket_path)
def main():
"""main function"""
socket_path = sys.argv[1]
command = {
"command": "isis-lsp-update",
"arguments": {
"instance": 1,
"pdu": []
}
}
tlvs = ISIS_AreaTlv(areas=ISIS_AreaEntry(areaid='49.0001'))
pdu = ISIS_CommonHdr()/ISIS_L1_LSP(lifetime=65535, lspid='0102.0304.0506.00-00', seqnum=3, tlvs=tlvs)
command["arguments"]["pdu"].append(pdu.build().hex())
pdu = ISIS_CommonHdr()/ISIS_L1_LSP(lifetime=65535, lspid='0102.0304.0506.00-01', seqnum=3, tlvs=tlvs)
command["arguments"]["pdu"].append(pdu.build().hex())
execute_command(socket_path, command)
if __name__ == "__main__":
main()
LSPGEN
~~~~~~
The BNG Blaster includes a tool called ``lspgen`` which is able to generate
topologies and link state packets for export as MRT and PCAP files. This tool
is also able to inject LSP's directly using the ``isis-lsp-update``
:ref:`command <api>`.
.. code-block:: none
$ lspgen --help
____ __ ____ _ __ ,/
/ __ \ / /_ / __ ) _____ (_)_____ / /__ ,'/
/ /_/ // __// __ |/ ___// // ___// //_/ ,' /
/ _, _// /_ / /_/ // / / // /__ / ,< ,' /_____,
/_/ |_| \__//_____//_/ /_/ \___//_/|_| .'____ ,'
__ _____ ____ ______ / ,'
/ / / ___// __ \/ ____/__ ____ / ,'
/ / \__ \/ /_/ / / __/ _ \/ __ \ /,'
/ /______/ / ____/ /_/ / __/ / / / /
/_____/____/_/ \____/\___/_/ /_/
Usage: lspgen [OPTIONS]
-v --version
-a --area <args>
-K --authentication-key <args>
-T --authentication-type none|simple|md5
-r --read-config-file <args>
-w --write-config-file <args>
-C --connector <args>
-S --control-socket <args>
-l --ipv4-link-prefix <args>
-L --ipv6-link-prefix <args>
-n --ipv4-node-prefix <args>
-N --ipv6-node-prefix <args>
-x --ipv4-external-prefix <args>
-X --ipv6-external-prefix <args>
-M --lsp-lifetime <args>
-z --no-ipv4
-Z --no-ipv6
-e --external-count <args>
-g --graphviz-file <args>
-h --help
-m --mrt-file <args>
-c --node-count <args>
-p --pcap-file <args>
-f --stream-file <args>
-s --seed <args>
-q --sequence <args>
-V --level <args>
-t --log normal|debug|lsp|lsdb|timer|timer-detail|ctrl|error
You can generate random topologies or define a topology manually
using configuration files.
Random Topologies
^^^^^^^^^^^^^^^^^
The following example generates a random topology with 1000 nodes.
.. code-block:: none
lspgen -m isis.mrt -c 1000 -K <secret> -T md5
The arguments ``-K`` and ``-T`` add a valid authentication TLV
to the generated LSP's in the MRT file.
Those topologies could be even exported as configuration file
with the argument ``-w`` and later imported with the argument ``-r``.
This allows to generate a large random topology which can be modified
manually.
Topology from Configuration File
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The following example shows the configuration for a topology
with three nodes.
.. code-block:: json
{
"level1": [
{
"node_id": "1337.0000.0001",
"hostname": "R1",
"area_list": [
"49.1337/24"
],
"protocol_list": [
"ipv4"
],
"ipv4_address_list": [
"10.13.37.1"
],
"ipv4_prefix_list": [
{
"ipv4_prefix": "10.13.37.1/32",
"metric": 0,
"segment_id": 30005,
"node_flag": true
},
{
"ipv4_prefix": "10.0.1.0/24",
"metric": 1000
},
{
"ipv4_prefix": "10.0.2.0/24",
"metric": 1000
}
],
"capability_list": [
{
"router_id": "10.13.37.1",
"mpls_ipv4_flag": true,
"mpls_ipv6_flag": false,
"srgb_base": 100000,
"srgb_range": 36000
}
],
"neighbor_list": [
{
"remote_node_id": "1337.0000.0000.00",
"metric": 10
},
{
"remote_node_id": "1337.0000.0002.00",
"metric": 10
},
{
"remote_node_id": "0204.0000.0003.00",
"metric": 10
}
]
},
{
"node_id": "1337.0000.0002",
"hostname": "R2",
"area_list": [
"49.1337/24"
],
"protocol_list": [
"ipv4"
],
"ipv4_address_list": [
"10.13.37.2"
],
"ipv4_prefix_list": [
{
"ipv4_prefix": "10.13.37.2/32",
"metric": 0,
"segment_id": 30003,
"node_flag": true
}
],
"capability_list": [
{
"router_id": "10.13.37.2",
"mpls_ipv4_flag": true,
"mpls_ipv6_flag": false,
"srgb_base": 100000,
"srgb_range": 36000
}
],
"neighbor_list": [
{
"remote_node_id": "1337.0000.0001.00",
"metric": 10
}
]
},
{
"node_id": "1337.0000.3",
"hostname": "R3",
"area_list": [
"49.1337/24"
],
"protocol_list": [
"ipv4"
],
"ipv4_address_list": [
"10.13.37.3"
],
"ipv4_prefix_list": [
{
"ipv4_prefix": "10.13.37.3/32",
"metric": 0,
"segment_id": 30003,
"node_flag": true
}
],
"capability_list": [
{
"router_id": "10.13.37.3",
"mpls_ipv4_flag": true,
"mpls_ipv6_flag": false,
"srgb_base": 100000,
"srgb_range": 36000
}
],
"neighbor_list": [
{
"remote_node_id": "1337.0000.0001.00",
"metric": 10
}
]
}
]
}