mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-11-03 19:54:35 +00:00
Merge pull request #4176 from qlyoung/doc-cleanup-ospf-apiserver
Cleanup OSPF API server docs
This commit is contained in:
commit
850af7ac4a
@ -4,76 +4,76 @@ OSPF API Documentation
|
||||
Disclaimer
|
||||
----------
|
||||
|
||||
The OSPF daemon contains an API for application access to the LSA
|
||||
database. This API was created by Ralph Keller, originally as patch for
|
||||
Zebra. Unfortunately, the page containing documentation of the API is no
|
||||
longer online. This page is an attempt to recreate documentation for the
|
||||
API (with lots of help of the WayBackMachine)
|
||||
The OSPF daemon contains an API for application access to the LSA database.
|
||||
This API and documentation was created by Ralph Keller, originally as patch for
|
||||
Zebra. Unfortunately, the page containing documentation for the API is no
|
||||
longer online. This page is an attempt to recreate documentation for the API
|
||||
(with lots of help from the WayBackMachine).
|
||||
|
||||
Ralph has kindly licensed this documentation under GPLv2+. Please preserve the
|
||||
acknowledgements at the bottom of this document.
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
This page describes an API that allows external applications to access
|
||||
the link-state database (LSDB) of the OSPF daemon. The implementation is
|
||||
based on the OSPF code from FRRouting (forked from Quagga and formerly
|
||||
Zebra) routing protocol suite and is subject to the GNU General Public
|
||||
License. The OSPF API provides you with the following functionality:
|
||||
This page describes an API that allows external applications to access the
|
||||
link-state database (LSDB) of the OSPF daemon. The implementation is based on
|
||||
the OSPF code from FRRouting (forked from Quagga and formerly Zebra) routing
|
||||
protocol suite and is subject to the GNU General Public License. The OSPF API
|
||||
provides you with the following functionality:
|
||||
|
||||
- Retrieval of the full or partial link-state database of the OSPF
|
||||
daemon. This allows applications to obtain an exact copy of the LSDB
|
||||
including router LSAs, network LSAs and so on. Whenever a new LSA
|
||||
arrives at the OSPF daemon, the API module immediately informs the
|
||||
application by sending a message. This way, the application is always
|
||||
synchronized with the LSDB of the OSPF daemon.
|
||||
- Origination of own opaque LSAs (of type 9, 10, or 11) which are then
|
||||
distributed transparently to other routers within the flooding scope
|
||||
and received by other applications through the OSPF API.
|
||||
- Retrieval of the full or partial link-state database of the OSPF daemon.
|
||||
This allows applications to obtain an exact copy of the LSDB including router
|
||||
LSAs, network LSAs and so on. Whenever a new LSA arrives at the OSPF daemon,
|
||||
the API module immediately informs the application by sending a message. This
|
||||
way, the application is always synchronized with the LSDB of the OSPF daemon.
|
||||
- Origination of own opaque LSAs (of type 9, 10, or 11) which are then
|
||||
distributed transparently to other routers within the flooding scope and
|
||||
received by other applications through the OSPF API.
|
||||
|
||||
Opaque LSAs, which are described in RFC 2370 , allow you to distribute
|
||||
application-specific information within a network using the OSPF
|
||||
protocol. The information contained in opaque LSAs is transparent for
|
||||
the routing process but it can be processed by other modules such as
|
||||
traffic engineering (e.g., MPLS-TE).
|
||||
Opaque LSAs, which are described in :rfc:`2370`, allow you to distribute
|
||||
application-specific information within a network using the OSPF protocol. The
|
||||
information contained in opaque LSAs is transparent for the routing process but
|
||||
it can be processed by other modules such as traffic engineering (e.g.,
|
||||
MPLS-TE).
|
||||
|
||||
Architecture
|
||||
------------
|
||||
|
||||
The following picture depicts the architecture of the Quagga/Zebra
|
||||
protocol suite. The OSPF daemon is extended with opaque LSA capabilities
|
||||
and an API for external applications. The OSPF core module executes the
|
||||
OSPF protocol by discovering neighbors and exchanging neighbor state.
|
||||
The opaque module, implemented by Masahiko Endo, provides functions to
|
||||
exchange opaque LSAs between routers. Opaque LSAs can be generated by
|
||||
several modules such as the MPLS-TE module or the API server module.
|
||||
These modules then invoke the opaque module to flood their data to
|
||||
neighbors within the flooding scope.
|
||||
The following picture depicts the architecture of the Quagga/Zebra protocol
|
||||
suite. The OSPF daemon is extended with opaque LSA capabilities and an API for
|
||||
external applications. The OSPF core module executes the OSPF protocol by
|
||||
discovering neighbors and exchanging neighbor state. The opaque module,
|
||||
implemented by Masahiko Endo, provides functions to exchange opaque LSAs
|
||||
between routers. Opaque LSAs can be generated by several modules such as the
|
||||
MPLS-TE module or the API server module. These modules then invoke the opaque
|
||||
module to flood their data to neighbors within the flooding scope.
|
||||
|
||||
The client, which is an application potentially running on a different
|
||||
node than the OSPF daemon, links against the OSPF API client library.
|
||||
This client library establishes a socket connection with the API server
|
||||
module of the OSPF daemon and uses this connection to retrieve LSAs and
|
||||
originate opaque LSAs.
|
||||
The client, which is an application potentially running on a different node
|
||||
than the OSPF daemon, links against the OSPF API client library. This client
|
||||
library establishes a socket connection with the API server module of the OSPF
|
||||
daemon and uses this connection to retrieve LSAs and originate opaque LSAs.
|
||||
|
||||
.. figure:: ../figures/ospf_api_architecture.png
|
||||
:alt: image
|
||||
|
||||
image
|
||||
|
||||
The OSPF API server module works like any other internal opaque module
|
||||
(such as the MPLS-TE module), but listens to connections from external
|
||||
applications that want to communicate with the OSPF daemon. The API
|
||||
server module can handle multiple clients concurrently.
|
||||
The OSPF API server module works like any other internal opaque module (such as
|
||||
the MPLS-TE module), but listens to connections from external applications that
|
||||
want to communicate with the OSPF daemon. The API server module can handle
|
||||
multiple clients concurrently.
|
||||
|
||||
One of the main objectives of the implementation is to make as little
|
||||
changes to the existing Zebra code as possible.
|
||||
One of the main objectives of the implementation is to make as little changes
|
||||
to the existing Zebra code as possible.
|
||||
|
||||
Installation & Configuration
|
||||
----------------------------
|
||||
|
||||
Download FRRouting and unpack
|
||||
Download FRRouting and unpack it.
|
||||
|
||||
Configure your frr version (note that --enable-opaque-lsa also enables
|
||||
the ospfapi server and ospfclient).
|
||||
Configure and build FRR (note that ``--enable-opaque-lsa`` also enables the
|
||||
ospfapi server and ospfclient).
|
||||
|
||||
::
|
||||
|
||||
@ -83,8 +83,8 @@ the ospfapi server and ospfclient).
|
||||
This should also compile the client library and sample application in
|
||||
ospfclient.
|
||||
|
||||
Make sure that you have enabled opaque LSAs in your configuration. Add
|
||||
the ospf opaque-lsa statement to your ospfd.conf:
|
||||
Make sure that you have enabled opaque LSAs in your configuration. Add the
|
||||
``ospf opaque-lsa`` statement to your :file:`ospfd.conf`:
|
||||
|
||||
::
|
||||
|
||||
@ -108,171 +108,165 @@ Usage
|
||||
-----
|
||||
|
||||
In the following we describe how you can use the sample application to
|
||||
originate opaque LSAs. The sample application first registers with the
|
||||
OSPF daemon the opaque type it wants to inject and then waits until the
|
||||
OSPF daemon is ready to accept opaque LSAs of that type. Then the client
|
||||
application originates an opaque LSA, waits 10 seconds and then updates
|
||||
the opaque LSA with new opaque data. After another 20 seconds, the
|
||||
client application deletes the opaque LSA from the LSDB. If the clients
|
||||
terminates unexpectedly, the OSPF API module will remove all the opaque
|
||||
LSAs that the application registered. Since the opaque LSAs are flooded
|
||||
to other routers, we will see the opaque LSAs in all routers according
|
||||
to the flooding scope of the opaque LSA.
|
||||
originate opaque LSAs. The sample application first registers with the OSPF
|
||||
daemon the opaque type it wants to inject and then waits until the OSPF daemon
|
||||
is ready to accept opaque LSAs of that type. Then the client application
|
||||
originates an opaque LSA, waits 10 seconds and then updates the opaque LSA with
|
||||
new opaque data. After another 20 seconds, the client application deletes the
|
||||
opaque LSA from the LSDB. If the clients terminates unexpectedly, the OSPF API
|
||||
module will remove all the opaque LSAs that the application registered. Since
|
||||
the opaque LSAs are flooded to other routers, we will see the opaque LSAs in
|
||||
all routers according to the flooding scope of the opaque LSA.
|
||||
|
||||
We have a very simple demo setup, just two routers connected with an ATM
|
||||
point-to-point link. Start the modified OSPF daemons on two adjacent
|
||||
routers. First run on msr2:
|
||||
point-to-point link. Start the modified OSPF daemons on two adjacent routers.
|
||||
First run on msr2:
|
||||
|
||||
::
|
||||
.. code-block:: console
|
||||
|
||||
> msr2:/home/keller/ospfapi/zebra/ospfd# ./ospfd -f /usr/local/etc/ospfd.conf
|
||||
# ./ospfd --apiserver -f /usr/local/etc/ospfd.conf
|
||||
|
||||
And on the neighboring router msr3:
|
||||
|
||||
::
|
||||
.. code-block:: console
|
||||
|
||||
> msr3:/home/keller/ospfapi/zebra/ospfd# ./ospfd -f /usr/local/etc/ospfd.conf
|
||||
# ./ospfd --apiserver -f /usr/local/etc/ospfd.conf
|
||||
|
||||
Now the two routers form adjacency and start exchanging their databases.
|
||||
Looking at the OSPF daemon of msr2 (or msr3), you see this:
|
||||
|
||||
::
|
||||
.. code-block:: console
|
||||
|
||||
ospfd> show ip ospf database
|
||||
ospfd> show ip ospf database
|
||||
|
||||
OSPF Router with ID (10.0.0.1)
|
||||
OSPF Router with ID (10.0.0.1)
|
||||
|
||||
Router Link States (Area 0.0.0.1)
|
||||
Router Link States (Area 0.0.0.1)
|
||||
|
||||
Link ID ADV Router Age Seq# CkSum Link count
|
||||
10.0.0.1 10.0.0.1 55 0x80000003 0xc62f 2
|
||||
10.0.0.2 10.0.0.2 55 0x80000003 0xe3e4 3
|
||||
Link ID ADV Router Age Seq# CkSum Link count
|
||||
10.0.0.1 10.0.0.1 55 0x80000003 0xc62f 2
|
||||
10.0.0.2 10.0.0.2 55 0x80000003 0xe3e4 3
|
||||
|
||||
Net Link States (Area 0.0.0.1)
|
||||
Net Link States (Area 0.0.0.1)
|
||||
|
||||
Link ID ADV Router Age Seq# CkSum
|
||||
10.0.0.2 10.0.0.2 60 0x80000001 0x5fcb
|
||||
Link ID ADV Router Age Seq# CkSum
|
||||
10.0.0.2 10.0.0.2 60 0x80000001 0x5fcb
|
||||
|
||||
Now we start the sample main application that originates an opaque LSA.
|
||||
|
||||
::
|
||||
.. code-block:: console
|
||||
|
||||
> cd ospfapi/apiclient
|
||||
> ./main msr2 10 250 20 0.0.0.0 0.0.0.1
|
||||
# cd ospfapi/apiclient
|
||||
# ./main msr2 10 250 20 0.0.0.0 0.0.0.1
|
||||
|
||||
This originates an opaque LSA of type 10 (area local), with opaque type
|
||||
250 (experimental), opaque id of 20 (chosen arbitrarily), interface
|
||||
address 0.0.0.0 (which is used only for opaque LSAs type 9), and area
|
||||
0.0.0.1
|
||||
This originates an opaque LSA of type 10 (area local), with opaque type 250
|
||||
(experimental), opaque id of 20 (chosen arbitrarily), interface address 0.0.0.0
|
||||
(which is used only for opaque LSAs type 9), and area 0.0.0.1
|
||||
|
||||
Again looking at the OSPF database you see:
|
||||
|
||||
::
|
||||
.. code-block:: console
|
||||
|
||||
ospfd> show ip ospf database
|
||||
ospfd> show ip ospf database
|
||||
|
||||
OSPF Router with ID (10.0.0.1)
|
||||
OSPF Router with ID (10.0.0.1)
|
||||
|
||||
Router Link States (Area 0.0.0.1)
|
||||
Router Link States (Area 0.0.0.1)
|
||||
|
||||
Link ID ADV Router Age Seq# CkSum Link count
|
||||
10.0.0.1 10.0.0.1 437 0x80000003 0xc62f 2
|
||||
10.0.0.2 10.0.0.2 437 0x80000003 0xe3e4 3
|
||||
Link ID ADV Router Age Seq# CkSum Link count
|
||||
10.0.0.1 10.0.0.1 437 0x80000003 0xc62f 2
|
||||
10.0.0.2 10.0.0.2 437 0x80000003 0xe3e4 3
|
||||
|
||||
Net Link States (Area 0.0.0.1)
|
||||
Net Link States (Area 0.0.0.1)
|
||||
|
||||
Link ID ADV Router Age Seq# CkSum
|
||||
10.0.0.2 10.0.0.2 442 0x80000001 0x5fcb
|
||||
Link ID ADV Router Age Seq# CkSum
|
||||
10.0.0.2 10.0.0.2 442 0x80000001 0x5fcb
|
||||
|
||||
Area-Local Opaque-LSA (Area 0.0.0.1)
|
||||
Area-Local Opaque-LSA (Area 0.0.0.1)
|
||||
|
||||
Opaque-Type/Id ADV Router Age Seq# CkSum
|
||||
250.0.0.20 10.0.0.1 0 0x80000001 0x58a6 <=== opaque LSA
|
||||
Opaque-Type/Id ADV Router Age Seq# CkSum
|
||||
250.0.0.20 10.0.0.1 0 0x80000001 0x58a6 <=== opaque LSA
|
||||
|
||||
You can take a closer look at this opaque LSA:
|
||||
|
||||
::
|
||||
.. code-block:: console
|
||||
|
||||
ospfd> show ip ospf database opaque-area
|
||||
ospfd> show ip ospf database opaque-area
|
||||
|
||||
OSPF Router with ID (10.0.0.1)
|
||||
OSPF Router with ID (10.0.0.1)
|
||||
|
||||
|
||||
Area-Local Opaque-LSA (Area 0.0.0.1)
|
||||
Area-Local Opaque-LSA (Area 0.0.0.1)
|
||||
|
||||
LS age: 4
|
||||
Options: 66
|
||||
LS Type: Area-Local Opaque-LSA
|
||||
Link State ID: 250.0.0.20 (Area-Local Opaque-Type/ID)
|
||||
Advertising Router: 10.0.0.1
|
||||
LS Seq Number: 80000001
|
||||
Checksum: 0x58a6
|
||||
Length: 24
|
||||
Opaque-Type 250 (Private/Experimental)
|
||||
Opaque-ID 0x14
|
||||
Opaque-Info: 4 octets of data
|
||||
Added using OSPF API: 4 octets of opaque data
|
||||
Opaque data: 1 0 0 0 <==== counter is 1
|
||||
LS age: 4
|
||||
Options: 66
|
||||
LS Type: Area-Local Opaque-LSA
|
||||
Link State ID: 250.0.0.20 (Area-Local Opaque-Type/ID)
|
||||
Advertising Router: 10.0.0.1
|
||||
LS Seq Number: 80000001
|
||||
Checksum: 0x58a6
|
||||
Length: 24
|
||||
Opaque-Type 250 (Private/Experimental)
|
||||
Opaque-ID 0x14
|
||||
Opaque-Info: 4 octets of data
|
||||
Added using OSPF API: 4 octets of opaque data
|
||||
Opaque data: 1 0 0 0 <==== counter is 1
|
||||
|
||||
Note that the main application updates the opaque LSA after 10 seconds,
|
||||
then it looks as follows:
|
||||
Note that the main application updates the opaque LSA after 10 seconds, then it
|
||||
looks as follows:
|
||||
|
||||
::
|
||||
.. code-block:: console
|
||||
|
||||
ospfd> show ip ospf database opaque-area
|
||||
ospfd> show ip ospf database opaque-area
|
||||
|
||||
OSPF Router with ID (10.0.0.1)
|
||||
OSPF Router with ID (10.0.0.1)
|
||||
|
||||
|
||||
Area-Local Opaque-LSA (Area 0.0.0.1)
|
||||
Area-Local Opaque-LSA (Area 0.0.0.1)
|
||||
|
||||
LS age: 1
|
||||
Options: 66
|
||||
LS Type: Area-Local Opaque-LSA
|
||||
Link State ID: 250.0.0.20 (Area-Local Opaque-Type/ID)
|
||||
Advertising Router: 10.0.0.1
|
||||
LS Seq Number: 80000002
|
||||
Checksum: 0x59a3
|
||||
Length: 24
|
||||
Opaque-Type 250 (Private/Experimental)
|
||||
Opaque-ID 0x14
|
||||
Opaque-Info: 4 octets of data
|
||||
Added using OSPF API: 4 octets of opaque data
|
||||
Opaque data: 2 0 0 0 <==== counter is now 2
|
||||
LS age: 1
|
||||
Options: 66
|
||||
LS Type: Area-Local Opaque-LSA
|
||||
Link State ID: 250.0.0.20 (Area-Local Opaque-Type/ID)
|
||||
Advertising Router: 10.0.0.1
|
||||
LS Seq Number: 80000002
|
||||
Checksum: 0x59a3
|
||||
Length: 24
|
||||
Opaque-Type 250 (Private/Experimental)
|
||||
Opaque-ID 0x14
|
||||
Opaque-Info: 4 octets of data
|
||||
Added using OSPF API: 4 octets of opaque data
|
||||
Opaque data: 2 0 0 0 <==== counter is now 2
|
||||
|
||||
Note that the payload of the opaque LSA has changed as you can see
|
||||
above.
|
||||
Note that the payload of the opaque LSA has changed as you can see above.
|
||||
|
||||
Then, again after another 20 seconds, the opaque LSA is flushed from the
|
||||
LSDB.
|
||||
Then, again after another 20 seconds, the opaque LSA is flushed from the LSDB.
|
||||
|
||||
Important note:
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
In order to originate an opaque LSA, there must be at least one active
|
||||
opaque-capable neighbor. Thus, you cannot originate opaque LSAs of no
|
||||
neighbors are present. If you try to originate even so no neighbor is
|
||||
ready, you will receive a not ready error message. The reason for this
|
||||
restriction is that it might be possible that some routers have an
|
||||
identical opaque LSA from a previous origination in their LSDB that
|
||||
unfortunately could not be flushed due to a crash, and now if the router
|
||||
comes up again and starts originating a new opaque LSA, the new opaque
|
||||
LSA is considered older since it has a lower sequence number and is
|
||||
ignored by other routers (that consider the stalled opaque LSA as more
|
||||
recent). However, if the originating router first synchronizes the
|
||||
database before originating opaque LSAs, it will detect the older opaque
|
||||
LSA and can flush it first.
|
||||
opaque-capable neighbor. Thus, you cannot originate opaque LSAs if no neighbors
|
||||
are present. If you try to originate when no neighbors are ready, you will
|
||||
receive a not ready error message. The reason for this restriction is that it
|
||||
might be possible that some routers have an identical opaque LSA from a
|
||||
previous origination in their LSDB that unfortunately could not be flushed due
|
||||
to a crash, and now if the router comes up again and starts originating a new
|
||||
opaque LSA, the new opaque LSA is considered older since it has a lower
|
||||
sequence number and is ignored by other routers (that consider the stalled
|
||||
opaque LSA as more recent). However, if the originating router first
|
||||
synchronizes the database before originating opaque LSAs, it will detect the
|
||||
older opaque LSA and can flush it first.
|
||||
|
||||
Protocol and Message Formats
|
||||
----------------------------
|
||||
|
||||
If you are developing your own client application and you don't want to
|
||||
make use of the client library (due to the GNU license restriction or
|
||||
whatever reason), you can implement your own client-side message
|
||||
handling. The OSPF API uses two connections between the client and the
|
||||
OSPF API server: One connection is used for a synchronous request /reply
|
||||
protocol and another connection is used for asynchronous notifications
|
||||
(e.g., LSA update, neighbor status change).
|
||||
If you are developing your own client application and you don't want to make
|
||||
use of the client library (due to the GNU license restriction or whatever
|
||||
reason), you can implement your own client-side message handling. The OSPF API
|
||||
uses two connections between the client and the OSPF API server: One connection
|
||||
is used for a synchronous request /reply protocol and another connection is
|
||||
used for asynchronous notifications (e.g., LSA update, neighbor status change).
|
||||
|
||||
Each message begins with the following header:
|
||||
|
||||
@ -326,8 +320,8 @@ The synchronous requests and replies have the following message formats:
|
||||
|
||||
image
|
||||
|
||||
The origin field allows to select according to the following types of
|
||||
origins:
|
||||
The origin field allows origin-based filtering using the following origin
|
||||
types:
|
||||
|
||||
+-------------------------+---------+
|
||||
| Origin | Value |
|
||||
@ -339,7 +333,7 @@ origins:
|
||||
| ANY\_ORIGIN | 2 |
|
||||
+-------------------------+---------+
|
||||
|
||||
The reply message has on of the following error codes:
|
||||
The reply message has one of the following error codes:
|
||||
|
||||
+--------------------------+---------+
|
||||
| Error code | Value |
|
||||
@ -372,16 +366,18 @@ The asynchronous notifications have the following message formats:
|
||||
|
||||
image
|
||||
|
||||
|
||||
.. Do not delete these acknowledgements!
|
||||
|
||||
Original Acknowledgments from Ralph Keller
|
||||
------------------------------------------
|
||||
|
||||
I would like to thank Masahiko Endo, the author of the opaque LSA
|
||||
extension module, for his great support. His wonderful ASCII graphs
|
||||
explaining the internal workings of this code, and his invaluable input
|
||||
proved to be crucial in designing a useful API for accessing the link
|
||||
state database of the OSPF daemon. Once, he even decided to take the
|
||||
plane from Tokyo to Zurich so that we could actually meet and have
|
||||
face-to-face discussions, which was a lot of fun. Clearly, without
|
||||
Masahiko no API would ever be completed. I also would like to thank
|
||||
Daniel Bauer who wrote an opaque LSA implementation too and was willing
|
||||
I would like to thank Masahiko Endo, the author of the opaque LSA extension
|
||||
module, for his great support. His wonderful ASCII graphs explaining the
|
||||
internal workings of this code, and his invaluable input proved to be crucial
|
||||
in designing a useful API for accessing the link state database of the OSPF
|
||||
daemon. Once, he even decided to take the plane from Tokyo to Zurich so that we
|
||||
could actually meet and have face-to-face discussions, which was a lot of fun.
|
||||
Clearly, without Masahiko no API would ever be completed. I also would like to
|
||||
thank Daniel Bauer who wrote an opaque LSA implementation too and was willing
|
||||
to test the OSPF API code in one of his projects.
|
||||
|
||||
@ -22,6 +22,10 @@ OPTIONS available for the |DAEMON| command:
|
||||
|
||||
.. include:: common-options.rst
|
||||
|
||||
.. option:: -a, --apiserver
|
||||
|
||||
Enable the OSPF API server.
|
||||
|
||||
FILES
|
||||
=====
|
||||
|
||||
|
||||
@ -26,7 +26,7 @@ Configuring OSPF
|
||||
|
||||
.. option:: -a, --apiserver
|
||||
|
||||
Enable the OSPF API server
|
||||
Enable the OSPF API server. This is required to use ``ospfclient``.
|
||||
|
||||
*ospfd* must acquire interface information from *zebra* in order to function.
|
||||
Therefore *zebra* must be running before invoking *ospfd*. Also, if *zebra* is
|
||||
|
||||
Loading…
Reference in New Issue
Block a user