summaryrefslogtreecommitdiff
path: root/doc/developer
diff options
context:
space:
mode:
Diffstat (limited to 'doc/developer')
-rw-r--r--doc/developer/index.rst1
-rw-r--r--doc/developer/path-internals-daemon.rst115
-rw-r--r--doc/developer/path-internals-pcep.rst193
-rw-r--r--doc/developer/path-internals.rst11
-rw-r--r--doc/developer/path.rst11
-rw-r--r--doc/developer/subdir.am4
6 files changed, 335 insertions, 0 deletions
diff --git a/doc/developer/index.rst b/doc/developer/index.rst
index 5a7da806ff..60a7d505a7 100644
--- a/doc/developer/index.rst
+++ b/doc/developer/index.rst
@@ -18,3 +18,4 @@ FRRouting Developer's Guide
ospf
zebra
vtysh
+ pathd
diff --git a/doc/developer/path-internals-daemon.rst b/doc/developer/path-internals-daemon.rst
new file mode 100644
index 0000000000..29f017284f
--- /dev/null
+++ b/doc/developer/path-internals-daemon.rst
@@ -0,0 +1,115 @@
+PATHD Internals
+===============
+
+Architecture
+------------
+
+Overview
+........
+
+The pathd deamon manages the segment routing policies, it owns the data
+structures representing them and can load modules that manipulate them like the
+PCEP module. Its responsibility is to select a candidate path for each
+configured policy and to install it into Zebra.
+
+Zebra
+.....
+
+Zebra manages policies that are active or pending to be activated due to the
+next hop not being available yet. In zebra, policy data structures and APIs are
+defined in `zebra_srte.[hc]`.
+
+The responsibilities of Zebra are:
+
+ - Store the policies' segment list.
+ - Install the policies when their next-hop is available.
+ - Notify other daemons of the status of the policies.
+
+Adding and removing policies is done using the commands `ZEBRA_SR_POLICY_SET`
+and `ZEBRA_SR_POLICY_DELETE` as parameter of the function `zebra_send_sr_policy`
+all defined in `zclient.[hc]`.
+
+If the first segment of the policy is an unknown label, it is kept until
+notified by the mpls hooks `zebra_mpls_label_created`, and then it is installed.
+
+To get notified when a policy status changes, a client can implement the
+`sr_policy_notify_status` callback defined in `zclient.[hc]`.
+
+For encoding/decoding the various data structures used to comunicate with zebra,
+the following functions are available from `zclient.[hc]`:
+`zapi_sr_policy_encode`, `zapi_sr_policy_decode` and
+`zapi_sr_policy_notify_status_decode`.
+
+
+Pathd
+.....
+
+
+The pathd daemon manages all the possible candidate paths for the segment
+routing policies and selects the best one following the
+`segment routing policy draft <https://tools.ietf.org/html/draft-ietf-spring-segment-routing-policy-06#section-2.9>`_.
+It also supports loadable modules for handling dynamic candidate paths and the
+creation of new policies and candidate paths at runtime.
+
+The responsibilities of the pathd base daemon, not including any optional
+modules, are:
+
+ - Store the policies and all the possible candidate paths for them.
+ - Select the best candidate path for each policy and send it to Zebra.
+ - Provide VTYSH configuration to set up policies and candidate paths.
+ - Provide a Northbound API to manipulate **configured** policies and candidate paths.
+ - Handle loadable modules for extending the functionality.
+ - Provide an API to the loadable module to manipulate policies and candidate paths.
+
+
+Threading Model
+---------------
+
+The daemon runs completely inside the main thread using FRR event model, there
+is no threading involved.
+
+
+Source Code
+-----------
+
+Internal Data Structures
+........................
+
+The main data structures for policies and candidate paths are defined in
+`pathd.h` and implemented in `pathd.c`.
+
+When modifying these structures, either directly or through the functions
+exported by `pathd.h`, nothing should be deleted/freed right away. The deletion
+or modification flags must be set and when all the changes are done, the
+function `srte_apply_changes` must be called. When called, a new candidate path
+may be elected and sent to Zebra, and all the structures flagged as deleted
+will be freed. In addition, a hook will be called so dynamic modules can perform
+any required action when the elected candidate path changes.
+
+
+Northbound API
+..............
+
+The northbound API is defined in `path_nb.[ch]` and implemented in
+`path_nb_config.c` for configuration data and `path_nb_state.c` for operational
+data.
+
+
+Command Line Client
+...................
+
+The command-line client (VTYSH) is implemented in `path_cli.c`.
+
+
+Interface with Zebra
+....................
+
+All the functions interfacing with Zebra are defined and implemented in
+`path_zebra.[hc]`.
+
+
+Loadable Module API
+...................
+
+For the time being, the API the loadable module uses is defined by `pathd.h`,
+but in the future, it should be moved to a dedicated include file.
diff --git a/doc/developer/path-internals-pcep.rst b/doc/developer/path-internals-pcep.rst
new file mode 100644
index 0000000000..ca318314f1
--- /dev/null
+++ b/doc/developer/path-internals-pcep.rst
@@ -0,0 +1,193 @@
+PCEP Module Internals
+=====================
+
+Introduction
+------------
+
+The PCEP module for the pathd daemon implements the PCEP protocol described in
+:rfc:`5440` to update the policies and candidate paths.
+
+The protocol encoding/decoding and the basic session management is handled by
+the `pceplib external library 1.2 <https://github.com/volta-networks/pceplib/tree/devel-1.2>`_.
+
+Together with pceplib, this module supports at least partially:
+
+ - :rfc:`5440`
+
+ Most of the protocol defined in the RFC is implemented.
+ All the messages can be parsed, but this was only tested in the context
+ of segment routing. Only a very small subset of metric types can be
+ configured, and there is a known issue with some Cisco routers not
+ following the IANA numbers for metrics.
+
+ - :rfc:`8231`
+
+ Support delegation of candidate path after performing the initial
+ computation request. If the PCE does not respond or cannot compute
+ a path, an empty candidate path is delegated to the PCE.
+ Only tested in the context of segment routing.
+
+ - :rfc:`8408`
+
+ Only used to comunicate the support for segment routing to the PCE.
+
+ - :rfc:`8664`
+
+ All the NAI types are implemented, but only the MPLS NAI are supported.
+ If the PCE provide segments that are not MPLS labels, the PCC will
+ return an error.
+
+Note that pceplib supports more RFCs and drafts, see pceplib
+`README <https://github.com/volta-networks/pceplib/blob/master/README.md>`_
+for more details.
+
+
+Architecture
+------------
+
+Overview
+........
+
+The module is separated into multiple layers:
+
+ - pathd interface
+ - command-line console
+ - controller
+ - PCC
+ - pceplib interface
+
+The pathd interface handles all the interactions with the daemon API.
+
+The command-line console handles all the VTYSH configuration commands.
+
+The controller manages the multiple PCC connections and the interaction between
+them and the daemon interface.
+
+The PCC handles a single connection to a PCE through a pceplib session.
+
+The pceplib interface abstracts the API of the pceplib.
+
+.. figure:: ../figures/pcep_module_threading_overview.svg
+
+
+Threading Model
+---------------
+
+The module requires multiple threads to cooperate:
+
+ - The main thread used by the pathd daemon.
+ - The controller pthread used to isolate the PCC from the main thread.
+ - The possible threads started in the pceplib library.
+
+To ensure thread safety, all the controller and PCC state data structures can
+only be read and modified in the controller thread, and all the global data
+structures can only be read and modified in the main thread. Most of the
+interactions between these threads are done through FRR timers and events.
+
+The controller is the bridge between the two threads, all the functions that
+**MUST** be called from the main thread start with the prefix `pcep_ctrl_` and
+all the functions that **MUST** be called from the controller thread start
+with the prefix `pcep_thread_`. When an asynchronous action must be taken in
+a different thread, an FRR event is sent to the thread. If some synchronous
+operation is needed, the calling thread will block and run a callback in the
+other thread, there the result is **COPIED** and returned to the calling thread.
+
+No function other than the controller functions defined for it should be called
+from the main thread. The only exception being some utility functions from
+`path_pcep_lib.[hc]`.
+
+All the calls to pathd API functions **MUST** be performed in the main thread,
+for that, the controller sends FRR events handled in function
+`path_pcep.c:pcep_main_event_handler`.
+
+For the same reason, the console client only runs in the main thread. It can
+freely use the global variable, but **MUST** use controller's `pcep_ctrl_`
+functions to interact with the PCCs.
+
+
+Source Code
+-----------
+
+Generic Data Structures
+.......................
+
+The data structures are defined in multiple places, and where they are defined
+dictates where they can be used.
+
+The data structures defined in `path_pcep.h` can be used anywhere in the module.
+
+Internally, throughout the module, the `struct path` data structure is used
+to describe PCEP messages. It is a simplified flattened structure that can
+represent multiple complex PCEP message types. The conversion from this
+structure to the PCEP data structures used by pceplib is done in the pceplib
+interface layer.
+
+The data structures defined in `path_pcep_controller.h` should only be used
+in `path_pcep_controller.c`. Even if a structure pointer is passed as a parameter
+to functions defined in `path_pcep_pcc.h`, these should consider it as an opaque
+data structure only used to call back controller functions.
+
+The same applies to the structures defined in `path_pcep_pcc.h`, even if the
+controller owns a reference to this data structure, it should never read or
+modify it directly, it should be considered an opaque structure.
+
+The global data structure can be accessed from the pathd interface layer
+`path_pcep.c` and the command line client code `path_pcep_cli.c`.
+
+
+Interface With Pathd
+....................
+
+All the functions calling or called by the pathd daemon are implemented in
+`path_pcep.c`. These functions **MUST** run in the main FRR thread, and
+all the interactions with the controller and the PCCs **MUST** pass through
+the controller's `pcep_ctrl_` prefixed functions.
+
+To handle asynchronous events from the PCCs, a callback is passed to
+`pcep_ctrl_initialize` that is called in the FRR main thread context.
+
+
+Command Line Client
+...................
+
+All the command line configuration commands (VTYSH) are implemented in
+`path_pcep_cli.c`. All the functions there run in the main FRR thread and
+can freely access the global variables. All the interaction with the
+controller's and the PCCs **MUST** pass through the controller `pcep_ctrl_`
+prefixed functions.
+
+
+Debugging Helpers
+.................
+
+All the functions formating data structures for debugging and logging purposes
+are implemented in `path_pcep_debug.[hc]`.
+
+
+Interface with pceplib
+......................
+
+All the functions calling the pceplib external library are defined in
+`path_pcep_lib.[hc]`. Some functions are called from the main FRR thread, like
+`pcep_lib_initialize`, `pcep_lib_finalize`; some can be called from either
+thread, like `pcep_lib_free_counters`; some function must be called from the
+controller thread, like `pcep_lib_connect`. This will probably be formalized
+later on with function prefix like done in the controller.
+
+
+Controller
+..........
+
+The controller is defined and implemented in `path_pcep_controller.[hc]`.
+Part of the controller code runs in FRR main thread and part runs in its own
+FRR pthread started to isolate the main thread from the PCCs' event loop.
+To communicate between the threads it uses FRR events, timers and
+`thread_execute` calls.
+
+
+PCC
+...
+
+Each PCC instance owns its state and runs in the controller thread. They are
+defined and implemented in `path_pcep_pcc.[hc]`. All the interactions with
+the daemon must pass through some controller's `pcep_thread_` prefixed function.
diff --git a/doc/developer/path-internals.rst b/doc/developer/path-internals.rst
new file mode 100644
index 0000000000..2c2df0f378
--- /dev/null
+++ b/doc/developer/path-internals.rst
@@ -0,0 +1,11 @@
+.. _path_internals:
+
+*********
+Internals
+*********
+
+.. toctree::
+ :maxdepth: 2
+
+ path-internals-daemon
+ path-internals-pcep
diff --git a/doc/developer/path.rst b/doc/developer/path.rst
new file mode 100644
index 0000000000..b6d2438c58
--- /dev/null
+++ b/doc/developer/path.rst
@@ -0,0 +1,11 @@
+.. _path:
+
+*****
+PATHD
+*****
+
+.. toctree::
+ :maxdepth: 2
+
+ path-internals
+
diff --git a/doc/developer/subdir.am b/doc/developer/subdir.am
index 3c0d203007..f131ba89d9 100644
--- a/doc/developer/subdir.am
+++ b/doc/developer/subdir.am
@@ -46,6 +46,10 @@ dev_RSTFILES = \
doc/developer/packaging-debian.rst \
doc/developer/packaging-redhat.rst \
doc/developer/packaging.rst \
+ doc/developer/path-internals-daemon.rst \
+ doc/developer/path-internals-pcep.rst \
+ doc/developer/path-internals.rst \
+ doc/developer/path.rst \
doc/developer/rcu.rst \
doc/developer/static-linking.rst \
doc/developer/testing.rst \