RFC 9222

Guidelines for Autonomic Service Agents

๐Ÿ“… published March 2022, from ietf

RFC 9222: Guidelines for Autonomic Service Agents ๐Ÿฆ‹ (Part 1 of 6)

okay bestie, let's start with the ID card ๐ŸŽ€

Number: RFC 9222 Title: Guidelines for Autonomic Service Agents Category: Informational ๐ŸŒธ ISSN: 2070-1721 Date: March 2022 ๐Ÿ“… Stream: IETF, which is the consensus of the IETF community ๐Ÿซถ

Authors: B. Carpenter (Univ. of Auckland), L. Ciavaglia (Rakuten Mobile), S. Jiang (Huawei Technologies Co., Ltd), and P. Peloso (Nokia) ๐Ÿ‘‘

The header doesn't list any Obsoletes or Updates entries, so this one isn't replacing or patching another RFC ๐Ÿ’…

Abstract โœจ

this doc proposes guidelines for designing Autonomic Service Agents (ASAs) for autonomic networks ๐Ÿงš ASAs, along with the Autonomic Network Infrastructure, the Autonomic Control Plane, and the GeneRic Autonomic Signaling Protocol, are the base pieces of an autonomic networking ecosystem ๐Ÿ’œ

Status of This Memo ๐ŸŒˆ

this one is not an Internet Standards Track spec. It's published just for info ๐Ÿ“

It's an IETF product. It reflects the consensus of the IETF community, got public review, and was approved for publication by the Internet Engineering Steering Group (IESG). Not every IESG-approved doc is a candidate for any level of Internet Standard, so check Section 2 of RFC 7841 if you want the details ๐Ÿค“

For the current status, errata, and where to send feedback, go to https://www.rfc-editor.org/info/rfc9222 ๐Ÿ”ฅ

Copyright (c) 2022 IETF Trust and the persons identified as the document authors. All rights reserved.

This doc is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) as they stand on the date it was published. Please read these carefully, because they spell out your rights and restrictions for this document. Code Components pulled out of this document must include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions, and they come without warranty as described in the Revised BSD License ๐Ÿ™ˆ


Table of Contents ๐Ÿงš

   1.  Introduction
   2.  Terminology
   3.  Logical Structure of an Autonomic Service Agent
   4.  Interaction with the Autonomic Networking Infrastructure
     4.1.  Interaction with the Security Mechanisms
     4.2.  Interaction with the Autonomic Control Plane
     4.3.  Interaction with GRASP and its API
     4.4.  Interaction with Policy Mechanisms
   5.  Interaction with Non-autonomic Components and Systems
   6.  Design of GRASP Objectives
   7.  Life Cycle
     7.1.  Installation Phase
       7.1.1.  Installation Phase Inputs and Outputs
     7.2.  Instantiation Phase
       7.2.1.  Operator's Goal
       7.2.2.  Instantiation Phase Inputs and Outputs
       7.2.3.  Instantiation Phase Requirements
     7.3.  Operation Phase
     7.4.  Removal Phase
   8.  Coordination and Data Models
     8.1.  Coordination between Autonomic Functions
     8.2.  Coordination with Traditional Management Functions
     8.3.  Data Models
   9.  Robustness
   10. Security Considerations
   11. IANA Considerations
   12. References
     12.1.  Normative References
     12.2.  Informative References
   Appendix A.  Example Logic Flows
   Acknowledgements
   Authors' Addresses

1. Introduction ๐ŸŽ€

okay so the big idea here is that this doc gives design guidelines for Autonomic Service Agents (ASAs) in an Autonomic Network (AN). That AN sits on the Autonomic Network Infrastructure (ANI) from the autonomic networking reference model [RFC8993] ๐Ÿฆ‹ The ANI uses the Autonomic Control Plane (ACP) [RFC8994] and the GeneRic Autonomic Signaling Protocol (GRASP) [RFC8990]. There's a chill intro with diagrams over at [IPJ], and the terms are in Section 2 ๐Ÿ’…

this doc is a contribution to describing an autonomic networking ecosystem, because a network that can actually be deployed needs more than just ACP and GRASP implementations ๐ŸŒธ The network has to do management stuff that a Network Operations Center (NOC) can't easily do by hand, like continuous resource optimization or automated fault detection and repair โœจ These goals are explained in full in [RFC7575]. The end result should be a big jump in operations ๐Ÿ”ฅ To get there, the ecosystem needs at least a library of ASAs plus matching GRASP technical objective definitions. A GRASP objective [RFC8990] is a data structure whose main contents are a name and a value. The value is either one configurable parameter or a set of parameters of some kind ๐Ÿ’œ

there also need to be tools to deploy and oversee ASAs, and they need to plug into existing operational mechanisms [RFC8368]. This doc focuses on designing ASAs, with a bit of talk about implementation and operations ๐Ÿงš

the autonomic literature is massive, with lots of different ideas about how agents should be characterized. A few examples are [DEMOLA06], [HUEBSCHER08], [MOVAHEDI12], and [GANA13]. For this doc, though, the basic definitions and goals for autonomic networking from [RFC7575] are what apply. In RFC 7575's words, an Autonomic Service Agent is "An agent implemented on an autonomic node that implements an autonomic function, either in part (in the case of a distributed function) or whole." ๐Ÿค“

ASAs have to be told apart from other software components. They're parts of network or service management, so they don't serve end users directly ๐Ÿ™ˆ They do provide management services to network operators and administrators, though. For example, services envisioned for network function virtualization (NFV) [NFV] or for service function chaining (SFC) [RFC7665] could be managed by an ASA instead of traditional config tools ๐Ÿ“

another example: an existing script running inside a router that monitors or configures functions or services locally could be upgraded into an ASA. That ASA could then talk to peer scripts on neighboring or remote routers ๐Ÿซถ A high-level API lets these upgraded scripts fully use the secure ACP and the discovery, negotiation, and synchronization features of GRASP. Stuff like configuring an Interior Gateway Protocol (IGP) on neighboring routers, or even swapping IGP security keys, could be done securely this way ๐Ÿ” This doc mostly deals with pretty complex ASAs, but the most useful ASAs at first might honestly just be simple upgrades of existing scripts ๐Ÿ’…

the reference model [RFC8993] goes further on what ASAs do, adding this:

[An ASA is] a process that makes use of the features provided by the ANI to achieve its own goals, usually including interaction with other ASAs via GRASP [RFC8990] or otherwise. Of course, it also interacts with the specific targets of its function, using any suitable mechanism. Unless its function is very simple, the ASA will need to handle overlapping asynchronous operations. It may therefore be a quite complex piece of software in its own right, forming part of the application layer above the ANI.

as I said, some ASAs are simple enough to manage one objective in a straightforward way and don't need asynchronous operations at all ๐ŸŒˆ On nodes with limited computing power and memory, ASAs should run at a much lower frequency than the primary workload. So CPU load shouldn't be a huge issue, but memory footprint on a constrained node is definitely a worry ๐Ÿ˜ญ ASAs on constrained devices will have limited functionality, and in that case lots of this doc doesn't apply. Still, in the general case an ASA can be a fairly complex software component that often controls and monitors simpler entities on the same host or on remote hosts. For instance, a device controller managing tens or hundreds of simple devices might contain a single ASA โœจ

the rest of this doc gives guidance on designing complex ASAs. Some of it will feel familiar to people who've worked with distributed fault-tolerant and real-time control systems ๐Ÿ‘‘ Robustness and security matter a lot in autonomic networks, and they're covered in Sections 9 and 10 ๐Ÿ”ฅ

2. Terminology ๐ŸŒธ

this section sums up the acronyms and terms used in the doc. Where no other reference is given, go check [RFC8993] or [RFC7575] ๐Ÿ’–

  • Autonomic: self-managing (self-configuring, self-protecting, self-healing, self-optimizing), but allowing high-level guidance by a central entity such as a NOC ๐Ÿฆ‹
  • Autonomic Function: a function that adapts on its own to a changing environment ๐Ÿงš
  • Autonomic Node: a node that employs autonomic functions ๐Ÿ“
  • ACP: Autonomic Control Plane [RFC8994] ๐Ÿซถ
  • AN: Autonomic Network; a network of autonomic nodes, which interact directly with each other ๐ŸŒˆ
  • ANI: Autonomic Network Infrastructure ๐Ÿ”
  • ASA: Autonomic Service Agent; an agent installed on an autonomic node that implements an autonomic function, either partially (in the case of a distributed function) or completely ๐Ÿ’…
  • BRSKI: Bootstrapping Remote Secure Key Infrastructure [RFC8995] ๐Ÿ™ˆ
  • CBOR: Concise Binary Object Representation[RFC8949] โœจ
  • GRASP: GeneRric Autonomic Signaling Protocol [RFC8990] ๐Ÿ‘‘
  • GRASP API: GRASP Application Programming Interface [RFC8991] ๐Ÿ’œ
  • NOC: Network Operations Center [RFC8368] ๐Ÿ”ฅ
  • Objective: A GRASP technical objective is a data structure whose main contents are a name and a value. The value consists of a single configurable parameter or a set of parameters of some kind [RFC8990]. ๐ŸŽ€

That's the end of part 1 of the rewrite, so the rest of the doc is coming next! ๐Ÿงš

3. Logical Structure of an Autonomic Service Agent โœจ

okay so, like I said up top, basically every ASA that isn't super simple is gonna need to handle asynchronous operations ๐Ÿซถ. Different programming environments do async in totally different ways (it's giving chaos ๐Ÿ˜ญ), so in this doc we use an explicit multi-threading model to describe stuff. That's just for illustration! The other options to multi-threading get a proper breakdown when we talk about the GRASP API (see Section 4.3) ๐Ÿ’….

A typical ASA has a main thread that handles a bunch of setup housekeeping, like:

  • obtain authorization credentials, if needed
  • register the ASA with GRASP
  • acquire relevant policy parameters
  • declare data structures for relevant GRASP objectives
  • register with GRASP those objectives that it will actively manage
  • launch a self-monitoring thread
  • enter its main loop

The main loop's logic depends on the details of the autonomic function concerned ๐ŸŒธ. Whenever async operations are required, extra threads may be launched. Examples of those threads include:

  • repeatedly flood an objective to the AN so that any ASA can receive the objective's latest value
  • accept incoming synchronization requests for an objective managed by this ASA
  • accept incoming negotiation requests for an objective managed by this ASA, and then conduct the resulting negotiation with the counterpart ASA
  • manage subsidiary non-autonomic devices directly

These threads should all either exit after their job is done or enter a wait state for new work, so they don't waste system resources. bestie, no wasting resources ๐Ÿ’€๐Ÿฆ‹

Depending on how much parallelism the application needs, some of these threads might be launched in multiple instances. In particular, if negotiation sessions with other ASAs are expected to be long or to involve wait states, the ASA designer might allow for multiple simultaneous negotiating threads, with appropriate use of queues and synchronization primitives to keep everything consistent ๐ŸŽ€.

The main loop itself could act as the initiator of synchronization requests or negotiation requests when the ASA needs data or resources from other ASAs. In particular, the main loop should watch for changes in policy parameters that affect its operation and, if appropriate, occasionally refresh authorization credentials. It should also do whatever is required to avoid unnecessary resource consumption, for example by limiting how often it runs ๐Ÿงš.

The self-monitoring thread is of considerable importance. Failure of autonomic service agents is highly undesirable (obviously, not on my watch ๐Ÿ˜ค). To a large extent this depends on careful coding and testing, with no unhandled error returns or exceptions. But if there is nevertheless some sort of failure, the self-monitoring thread should detect it, fix it if possible, and, in the worst case, restart the entire ASA. main character energy for that thread, fr fr ๐Ÿ‘‘

Appendix A presents some example logic flows in informal pseudocode ๐Ÿ“.


4. Interaction with the Autonomic Networking Infrastructure ๐ŸŒˆ

4.1. Interaction with the Security Mechanisms

okay the ANI part, so an ASA by definition runs in an autonomic node ๐Ÿฆ‹. Before any normal ASAs get started, those nodes must be bootstrapped into the autonomic network's secure key infrastructure, typically in accordance with [RFC8995]. This key infrastructure gets used to secure the ACP (more on that in the next section) and may be used by ASAs to set up additional secure interactions with their peers, if needed ๐Ÿ”.

Note that the secure bootstrap process itself includes simple special-purpose ASAs that use a restricted mode of GRASP (Section 4 of [RFC8995]). it's ASAs all the way down, iykyk ๐Ÿ’…

4.2. Interaction with the Autonomic Control Plane

In a normal autonomic network, ASAs will run as clients of the ACP. The ACP provides a fully secured network environment for all communication with other ASAs, mostly mediated by GRASP (next section) ๐Ÿซถ.

Note that the ACP formation process itself includes simple special-purpose ASAs that use a restricted mode of GRASP (Section 6.4 of [RFC8994]). the ACP literally builds itself with ASAs, not me ๐Ÿ˜ญโœจ

4.3. Interaction with GRASP and its API

In a node where a significant number of ASAs are installed, GRASP [RFC8990] is likely to run as a separate process, with its API [RFC8991] available in user space. So ASAs can operate without special privilege, unless they need it for other reasons ๐Ÿ“. The ASA's view of GRASP is built around GRASP objectives (Section 6). These are defined as data structures containing administrative information, such as the objective's unique name and its current value. The format and size of the value isn't restricted by the protocol, except that it must be possible to serialize it for transmission in Concise Binary Object Representation (CBOR) [RFC8949], subject only to GRASP's maximum message size as discussed in Section 6. so flexible, but make sure it can be serialized, bestie ๐Ÿ’œ

As discussed in Section 3, GRASP is an asynchronous protocol, and this document uses a multi-threading model to describe operations. In lots of programming environments an "event loop" model is used instead, where each thread is implemented as an event handler called in turn by the main loop. For this case, the GRASP API must provide non-blocking calls and possibly support callbacks. This topic is discussed in more detail in [RFC8991], and other asynchronicity models are also possible. Whenever necessary, the GRASP session identifier is used to tell simultaneous operations apart ๐ŸŒธ.

The GRASP API should offer the following features:

  • Registration functions, so that an ASA can register itself and the objectives that it manages.
  • A discovery function, by which an ASA can discover other ASAs supporting a given objective.
  • A negotiation request function, by which an ASA can start negotiation of an objective with a counterpart ASA. With this, there is a corresponding listening function for an ASA that wishes to respond to negotiation requests, plus a set of functions to support negotiating steps. Once a negotiation starts, it is a symmetric process, with both sides sending successive objective values to each other until agreement is reached (or the negotiation fails). ngl this one's giving two-way group chat ๐Ÿ’ฌ
  • A synchronization function, by which an ASA can request the current value of an objective from a counterpart ASA. With this, there is a corresponding listening function for an ASA that wishes to respond to synchronization requests. Unlike negotiation, synchronization is an asymmetric process, in which the listener sends a single objective value to the requester ๐ŸŽ€.
  • A flood function, by which an ASA can cause the current value of an objective to be flooded throughout the AN so that any ASA can receive it ๐ŸŒŠ.

For further details and some extra housekeeping functions, see [RFC8991] ๐Ÿ“š.

The GRASP API is meant to support the various interactions expected between most ASAs, such as the interactions outlined in Section 3. However, if ASAs need additional communication between themselves, they can do it directly over the ACP to benefit from its security ๐Ÿ”’. One option is to use GRASP discovery and synchronization as a rendezvous mechanism between two ASAs, passing communication parameters such as a TCP port number via GRASP. Using TLS over the ACP for those communications is advisable, as described in Section 6.9.2 of [RFC8994] ๐Ÿ’–.

4.4. Interaction with Policy Mechanisms

At the time of writing, the policy mechanisms for the ANI are undefined. In particular, using declarative policies (aka Intents) to define and manage an ASA's behaviors remains a research topic [IBN-CONCEPTS] ๐Ÿงช.

In cases where ASAs are defined as closed control loops, the specifications in [ZSM009-1] regarding imperative and declarative goal statements may be applicable ๐Ÿ”.

In the ANI, policy dissemination is expected to work through an information distribution mechanism (e.g., via GRASP [RFC8990]) that can reach all autonomic nodes and therefore every ASA. However, each ASA must be capable of operating "out of the box" without locally defined policy. So every ASA implementation must include carefully chosen default values and settings for all policy parameters ๐Ÿผโœจ.


5. Interaction with Non-autonomic Components and Systems ๐Ÿซง

To have any external effects, an ASA must also interact with non-autonomic components of the node where it's installed. For example, an ASA whose purpose is to manage a resource must interact with that resource. An ASA managing an entity that's also managed by local software must interact with that software. For example, if that management is performed by NETCONF [RFC6241], the ASA must interact with the NETCONF server as an independent NETCONF client in the same node. That way there's no inconsistency between configuration changes delivered via NETCONF and configuration changes made by the ASA ๐Ÿ™ˆ.

In an environment where systems are virtualized and specialized using techniques such as network function virtualization or network slicing, there will be a design choice: whether ASAs are deployed once per physical node or once per virtual context. A related issue is whether the ANI as a whole is deployed once on a physical network or whether several virtual ANIs are deployed. This aspect needs to be considered by the ASA designer, so put it on the list, periodt ๐ŸŒˆ๐Ÿ’…

6. Design of GRASP Objectives โœจ

Okay bestie, so when you're designing an ASA, you'll often need a brand new GRASP objective ๐Ÿ’…. The general rules for the format, the names, and IANA registration all live in [RFC8990]. That doc covers the general vibes of objective design too, so I'm not repeating all of it here. But listen up ๐Ÿ‘‚: GRASP, just like HTTP, does not give you transactional integrity ๐Ÿ™ˆ. Steps in a GRASP negotiation are not idempotent, so your objective and your ASA's logic flow have to plan for that. The best move, when you can, is designing objectives with idempotent semantics ๐Ÿซถ. If that's not possible (this usually happens when an ASA is handing out part of a shared resource to other ASAs), it needs to make sure the same piece of the resource doesn't get allocated twice ๐Ÿ˜ญ. The easiest way to do that is running only one negotiation at a time. If your ASA is juggling several negotiations at once, it must avoid interference between them.

Negotiations always end eventually, usually because one side declares success or failure ๐ŸŽ€. If that doesn't happen, you'll hit either a timeout or the loop count running out. If the negotiation policy isn't self-evident, the objective's definition should spell it out ๐Ÿ“.

GRASP also has a "dry run" mode ๐Ÿงช, where a negotiation runs its normal course but doesn't get committed on either end until a later live negotiation session. If an objective defines dry run mode, its specification and every implementation must think about what state needs saving after a dry run, so a later live negotiation can be expected to succeed. It must also be clear how long that state sticks around, and what happens if the live negotiation shows up after the state has been deleted ๐Ÿ’€. An ASA that asks for a dry run must keep in mind that a successful dry run can still be followed by a failed live negotiation. Because all of this is so complicated, the dry run mechanism should only be supported by objectives and ASAs where it's actually worth it ๐Ÿฅน.

The value field of an objective is limited by the GRASP protocol definition to any data structure that can be expressed in Concise Binary Object Representation (CBOR) [RFC8949] ๐ŸŒˆ. For some objectives, a single data item is enough, like an integer, a floating point number, a UTF-8 string, or an arbitrary byte string ๐Ÿ“. For fancier stuff, a simple tuple like [item1, item2, item3] could do the trick โœจ. Since CBOR is closely linked to JSON, it's also pretty easy to define an objective whose value is a JSON structure ๐Ÿ’œ. In practice, the formats the GRASP API accepts will limit your options. A generic solution is for the API to accept and deliver the value field as raw CBOR, with the ASA doing its own encoding and decoding using a CBOR library (Section 2.3.2.4 of [RFC8991]) ๐Ÿ”ฅ.

The maximum size of an objective's value field is capped by the GRASP maximum message size ๐Ÿ“. If the default maximum size, GRASP_DEF_MAX_SIZE (specified by [RFC8990]), isn't enough for you, the objective's specification must state the required maximum message size for both unicast and multicast messages ๐Ÿงš.

A mapping from YANG to CBOR is defined by [CBOR-YANG] ๐Ÿฆ‹. As long as it fits within the size limit for GRASP messages, nothing stops objectives from carrying YANG this way ๐Ÿ’….

CBOR is super flexible, which means the value field of many objectives can be extended while in service, to add extra information or alternative content ๐ŸŒธ. That's especially true if you're using JSON-like structures. This has consequences for how robust your ASAs are, as discussed in Section 9 ๐Ÿ™ˆ.


7. Life Cycle

The ASA life cycle is discussed in [AUTONOMIC-FUNCTION], and the following text was derived from it ๐Ÿ“š. It doesn't cover every single detail, and some of the terms would need precise definitions in any given implementation ๐Ÿค“.

In simple cases, autonomic functions could be permanent, meaning the ASAs ship as part of a product and stick around for the product's whole life ๐Ÿ’–. In complex cases, though, it's more likely that ASAs need to be installed or updated dynamically because of new requirements or bugs ๐Ÿ›. This section describes one approach to the resulting life cycle of individual ASAs. It doesn't consider bigger issues, like updates to shared libraries ๐Ÿซ .

Because continuity of service is fundamental to autonomic networking ๐Ÿ‘‘, the process of seamlessly replacing a running ASA instance with a new version needs to be part of the ASA's design โœจ. The impact of service continuity on ASA design can be illustrated across the three main phases of the ASA life cycle: installation, instantiation, and operation ๐ŸŽ€.

                 +--------------+
Undeployed ------>|              |------> Undeployed
                 |  Installed   |
             +-->|              |---+
    Mandate  |   +--------------+   | Receives a
  is revoked |   +--------------+   |  Mandate
             +---|              |<--+
                 | Instantiated |
             +-->|              |---+
         set |   +--------------+   | set
        down |   +--------------+   | up
             +---|              |<--+
                 |  Operational |
                 |              |
                 +--------------+

         Figure 1: Life Cycle of an Autonomic Service Agent

7.1. Installation Phase

We define "installation" to mean that a piece of software is loaded into a device, along with any necessary libraries, but isn't activated yet ๐Ÿ“ฆ.

Before you can instantiate and run ASAs, the operator first has to provision the infrastructure with the sets of ASA software that match its needs and objectives ๐Ÿ› ๏ธ. That software must be checked for integrity and authenticity before installation ๐Ÿ”. Provisioning happens in the installation phase, and it means installing (or checking the availability of) the software pieces for the different ASAs across a set of Installation Hosts within the autonomic network ๐Ÿ .

There are three properties that apply to installing ASAs ๐Ÿ’…:

  • The dynamic installation property lets you install an ASA on demand, on any hosts that are compatible with it โšก.
  • The decoupling property lets an ASA on one machine control resources on another machine (known as "decoupled mode") ๐Ÿฆ‹.
  • The multiplicity property lets you control multiple sets of resources from a single ASA ๐ŸŒˆ.

These three properties are a big deal in the installation phase, since how they vary decides how the ASA can get installed on the infrastructure ๐Ÿ˜ค.

7.1.1. Installation Phase Inputs and Outputs

Inputs are:

  • [ASA_type]: specifies which ASA to install ๐ŸŽฏ.
  • [Installation_target_infrastructure]: specifies the candidate installation Hosts ๐Ÿ˜๏ธ.
  • [ASA_placement_function]: specifies how the installation phase will meet the operator's needs and objectives for provisioning the infrastructure. This function is only useful in decoupled mode. It can be as simple as an explicit list of hosts where the ASAs are to be installed, or it could consist of operator-defined criteria and constraints ๐Ÿงฉ.

The main output of the installation phase is a [List_of_ASAs] installed on [List_of_hosts] ๐ŸŽ‰. This output is also handy for the coordination function, where it acts as a static interaction map (see Section 8.1) ๐Ÿ—บ๏ธ.

The condition to check before moving on to the next phase is making sure that [List_of_ASAs] are correctly installed on [List_of_hosts] โœ…. A minimum set of primitives to support installing ASAs could be the following: install (List_of_ASAs, Installation_target_infrastructure, ASA_placement_function) and uninstall (List_of_ASAs) ๐Ÿ’œ.

7.2. Instantiation Phase

We define "instantiation" as the operation of creating a single ASA instance from the corresponding piece of installed software ๐ŸŒŸ.

Once the ASAs are installed on the right hosts in the network, they may start operating ๐Ÿš€. From the operator's point of view, an operating ASA means the ASA manages network resources according to the objectives it was given ๐ŸŽฏ. At the ASA's local level, operating means executing its control loop algorithm ๐Ÿ”.

There are two things to keep in mind here ๐Ÿง . First, having a piece of code installed and ready to run on a host is not the same thing as having an agent based on that code actually running inside the host ๐Ÿ˜ฎ. Second, in the coupled case, figuring out which resources an ASA controls is easy, because the ASA runs on the same autonomic node as the resources it's controlling ๐Ÿฅฐ. In decoupled mode, it gets a bit trickier: a starting agent will either have to discover the set of resources it ought to control, or that information has to be communicated to the ASA ๐Ÿ•ต๏ธโ€โ™€๏ธ.

The instantiation phase of an ASA covers both of these aspects: starting the agent code (when that doesn't happen automatically) and determining which resources have to be controlled (when that isn't straightforward) ๐Ÿ’–.

7.2.1. Operator's Goal

Through this phase, the operator wants to control its autonomic network in at least two ways ๐Ÿ‘‘:

  1. Determine the scope of autonomic functions by instructing which network resources have to be managed by which autonomic function (and, more precisely, by which release of the ASA software code, e.g., version number or provider) ๐Ÿ”Ž.
  2. Determine how the autonomic functions are organized by instantiating a set of ASAs across one or more autonomic nodes, and instructing them accordingly about the other ASAs in the set as necessary ๐Ÿงต.

In this phase, the operator may also want to set goals for autonomic functions, for example by configuring GRASP objectives ๐ŸŽ€.

The operator's goal can be summed up as an instruction to the autonomic ecosystem that matches the following format, which gets explained in detail in the next subsection ๐Ÿ’…:

   [Instances_of_ASA_type] ready to control
   [Instantiation_target_infrastructure] with
   [Instantiation_target_parameters]

7.2.2. Instantiation Phase Inputs and Outputs

Inputs are:

  • [Instances_of_ASA_type]: specifies which ASAs to instantiate ๐Ÿฃ.
  • [Instantiation_target_infrastructure]: specifies which resources are to be managed by the autonomic function. This can be the whole network or a subset of it, like a domain, a physical segment, or even a specific list of resources ๐Ÿ—‚๏ธ.
  • [Instantiation_target_parameters]: specifies which GRASP objectives are to be sent to ASAs (for example, an optimization target) ๐ŸŽฏ.

Outputs are:

  • [Set_of_ASA_resources_relations]: describes which resources are managed by which ASA instances. This isn't a formal message, but a resulting configuration log for a set of ASAs ๐Ÿ“’โœจ.

7.2.3. Instantiation Phase Requirements ๐ŸŽ€

okay so the instructions from Section 7.2 could go one of two ways, bestie ๐Ÿ’…

  • Sent to a targeted ASA. The receiving Agent will have to manage the specified list of [Instantiation_target_infrastructure], with the [Instantiation_target_parameters].
  • Broadcast to all ASAs. The ASAs would work out from the list which ASAs would handle which [Instantiation_target_infrastructure], with the [Instantiation_target_parameters].

these instructions may get grouped into a data structure called an ASA Instance Mandate ๐Ÿฆ‹ the spec for that is beyond the scope of this document, so we're not going there, babe.

the endgame of this phase is a set of ASA instances that are ready to operate โœจ each one is characterized by the resources it manages, the metrics it monitors, and the actions it can run (like modifying certain parameter values). the description of an ASA instance may live in an ASA Instance Manifest data structure. again, the spec for that is beyond the scope of this document ๐Ÿ™ˆ

and the Manifest is not just for vibes. yes, it's an acknowledgement to the operator that instantiation worked, but it's also necessary for further autonomic operations with:

  • coordinated entities (see Section 8.1)
  • collaborative entities with purposes such as knowledge exchange (some ASAs may produce knowledge or monitor metrics that would be useful for other ASAs) ๐Ÿงš

7.3. Operation Phase ๐ŸŒธ

during the operation phase, the operator can:

  • activate/deactivate ASAs: enable/disable their autonomic loops
  • modify ASA targets: set different technical objectives
  • modify ASAs managed resources: update the Instance Mandate to specify a different set of resources to manage (only applicable to decoupled ASAs)

also during operation, running ASAs can interact with other ASAs:

  • in order to exchange knowledge (e.g., an ASA providing traffic predictions to a load balancing ASA)
  • in order to collaboratively reach an objective (e.g., ASAs pertaining to the same autonomic function will collaborate, e.g., in the case of a load balancing function, by modifying link metrics according to neighboring resource loads) ๐Ÿซถ

running ASAs are expected to apply coordination schemes as per Section 8.1. no skipping this one ๐Ÿ’€

7.4. Removal Phase ๐Ÿ“

when an ASA is removed from service and uninstalled, the above steps are reversed. it is important that its data, especially any security key material, is purged. ๐Ÿ”ฅ

8. Coordination and Data Models ๐Ÿ‘‘

8.1. Coordination between Autonomic Functions ๐Ÿฆ‹

some autonomic functions are totally independent of each other, iconic behaviour ๐Ÿ’… but others are at risk of interfering with each other. for example, two different optimization functions might both try to modify the same underlying parameter in different ways ๐Ÿ˜ญ in a complete system, you need a method for identifying ASAs that might interfere with each other and coordinating their actions when necessary.

8.2. Coordination with Traditional Management Functions ๐ŸŒˆ

some ASAs will have functions that overlap with existing configuration tools and network management mechanisms such as command-line interfaces, DHCP, DHCPv6, SNMP, NETCONF, and RESTCONF. this is, of course, an existing problem whenever multiple configuration tools are in use by the NOC, so it's not new drama. each ASA designer will need to consider this issue and how to avoid clashes and inconsistencies in various deployment scenarios. some specific considerations for interaction with OAM tools are given in [RFC8368]. as another example, [RFC8992] describes how autonomic management of IPv6 prefixes can interact with prefix delegation via DHCPv6. the description of a GRASP objective, and of an ASA using it, should include a discussion of any such interactions โœจ

8.3. Data Models ๐Ÿงš

management functions often include a shared data model, quite likely expressed in a formal notation such as YANG. this aspect should not be an afterthought in the design of an ASA ๐Ÿ™…โ€โ™€๏ธ to the contrary, the design of the ASA and of its GRASP objectives should match the data model. as noted in Section 6, YANG serialized as CBOR may be used directly as the value of a GRASP objective.

9. Robustness ๐Ÿ›ก๏ธ

it is of great importance that all components of an autonomic system are highly robust. ASA designers should aim for their component to never fail, but it is more important to design the ASA to assume that failures will happen and to gracefully recover from them when they occur. so this section lists various aspects of robustness that ASA designers should consider, bestie ๐Ÿ’–

  1. If despite all precautions, an ASA does encounter a fatal error, it should in any case restart automatically and try again. to mitigate a loop in case of persistent failure, a suitable pause should be inserted before such a restart. the length of the pause depends on the use case; randomization and exponential backoff should be considered.
  2. If a newly received or calculated value for a parameter falls out of bounds, the corresponding parameter should be either left unchanged or restored to a value known to be safe in all configurations.
  3. If a GRASP synchronization or negotiation session fails for any reason, it may be repeated after a suitable pause. the length of the pause depends on the use case; randomization and exponential backoff should be considered.
  4. If a session fails repeatedly, the ASA should consider that its peer has failed, and it should cause GRASP to flush its discovery cache and repeat peer discovery.
  5. In any case, it may be prudent to repeat discovery periodically, depending on the use case.
  6. Any received GRASP message should be checked. If it is wrongly formatted, it should be ignored. Within a unicast session, an Invalid message (M_INVALID) may be sent. this function may be provided by the GRASP implementation itself.
  7. Any received GRASP objective should be checked. basic formatting errors like invalid CBOR will likely be detected by GRASP itself, but the ASA is responsible for checking the precise syntax and semantics of a received objective. If it is wrongly formatted, it should be ignored. Within a negotiation session, a Negotiation End message (M_END) with a Decline option (O_DECLINE) should be sent. An ASA may log such events for diagnostic purposes.
  8. On the other hand, the definitions of GRASP objectives are very likely to be extended, using the flexibility of CBOR or JSON. Therefore, ASAs should be able to deal gracefully with unknown components within the values of objectives. The specification of an objective should describe how unknown components are to be handled (ignored, logged and ignored, or rejected as an error).
  9. If an ASA receives either an Invalid message (M_INVALID) or a Negotiation End message (M_END) with a Decline option (O_DECLINE), one possible reason is that the peer ASA does not support a new feature of either GRASP or the objective in question. In such a case, the ASA may choose to repeat the operation concerned without using that new feature.
  10. All other possible exceptions should be handled in an orderly way. There should be no such thing as an unhandled exception (but see point 1 above).

at a slightly more general level, ASAs are not services in themselves, but they automate services. this has a fundamental impact on how to design robust ASAs ๐Ÿซ  in general, when an ASA observes a particular state (1) of operations of the services/resources it controls, it typically aims to improve this state to a better state, say (2). ideally, the ASA is built so that it can ensure that any error encountered can still lead to returning to (1) instead of a state (3), which is worse than (1). one example of this principle is "make-before-break", used in reconfiguration of routing protocols in manual operations. this principle of operations can accordingly be coded into the operation of an ASA. the GRASP dry run option mentioned in Section 6 is another tool helpful for this ASA design goal of "test-before-make" ๐Ÿงช

10. Security Considerations ๐Ÿšจ

this section is SERIOUS, bestie. read every word. ๐Ÿ™ˆ

ASAs are intended to run in an environment that is protected by the Autonomic Control Plane [RFC8994], admission to which depends on an initial secure bootstrap process such as BRSKI [RFC8995]. those documents describe security considerations relating to the use of and properties provided by the ACP and BRSKI, respectively. such an ACP can provide keying material for mutual authentication between ASAs, as well as confidential communication channels for messages between ASAs. in some deployments, a secure partition of the link layer might be used instead. GRASP itself has significant security considerations [RFC8990]. however, this does not relieve ASAs of responsibility for security.

when ASAs configure or manage network elements outside the ACP, potentially in a different physical node, they must interact with other non-autonomic software components to perform their management functions. the details are specific to each case, but this has an important security implication. an ASA might act as a loophole by which the managed entity could penetrate the security boundary of the ANI. thus, ASAs must be designed to avoid loopholes such as passing on executable code or proxying unverified commands, and should, if possible, operate in an unprivileged mode. in particular, they must use secure coding practices, e.g., carefully validate all incoming information and avoid unnecessary elevation of privilege. this will apply in particular when an ASA interacts with a management component such as a NETCONF server. ๐Ÿ˜ญ

a similar situation will arise if an ASA acts as a gateway between two separate autonomic networks, i.e., it has access to two separate ACPs. such an ASA must also be designed to avoid loopholes and to validate incoming information from both sides.

as a reminder, GRASP does not intrinsically provide transactional integrity (Section 6). ๐Ÿ’…

as appropriate to their specific functions, ASAs should take account of relevant privacy considerations [RFC6973]. ๐Ÿ”’

the initial version of the autonomic infrastructure assumes that all autonomic nodes are trusted by virtue of their admission to the ACP. ASAs are therefore trusted to manipulate any GRASP objective simply because they are installed on a node that has successfully joined the ACP. in the general case, a node may have multiple roles, and a role may use multiple ASAs, each using multiple GRASP objectives. additional mechanisms for the fine-grained authorization of nodes and ASAs to manipulate specific GRASP objectives could be designed. meanwhile, we repeat that ASAs should run without special privilege if possible. independently of this, interfaces between ASAs and the router configuration and monitoring services of the node can be subject to authentication that provides more fine-grained authorization for specific services. these additional authentication parameters could be passed to an ASA during its instantiation phase.

11. IANA Considerations ๐ŸŽ€

this document has no IANA actions. nothing to do here, bestie โœจ

  1. References โœจ

12.1. Normative References

12.2. Informative References โœจ

Appendix A. Example Logic Flows โœจ

okay bestie, this appendix is all about generic logic flows that team up to act as an Autonomic Service Agent (ASA) for resource management ๐Ÿ’…. These are illustrative examples, not rules. As long as you follow the GRASP rules, a real implementation could look totally different ๐Ÿซถ. You're assumed to already know GRASP [RFC8990] and its conceptual API [RFC8991], so catch up on those first if you need to ๐Ÿ“š.

A complete autonomic function for a distributed resource is made of a bunch of ASA instances placed at relevant points in a network ๐Ÿฆ‹. The details depend on the resource, obviously. One example is IP address prefix management, as specified in [RFC8992]. There, an ASA instance lives in each delegating router ๐ŸŒธ.

Here's the underlying assumption: there's an initial source of the resource, called an origin ASA. The other ASAs, known as delegators, get supplies from the origin, delegate quantities to consumers who ask for them, and take the resource back when it's no longer needed ๐Ÿ”„.

Another assumption is that there's a set of network-wide policy parameters, which the origin hands out to the delegators ๐Ÿ‘‘. These parameters control how the delegators decide how much resource to give consumers. So the ASA logic has two operating modes: origin and delegator. When it runs as an origin, it starts by getting a quantity of the resource from the NOC. It then acts as a source of policy parameters, using both GRASP flooding and GRASP synchronization. (In some scenarios, flooding or synchronization alone might be enough, but this example includes both ๐Ÿ™ˆ.)

When it runs as a delegator, it starts with an empty resource pool, grabs the policy parameters through GRASP synchronization, and delegates quantities to consumers who request them ๐Ÿ“. Both as an origin and as a delegator, when its pool is low, it goes looking for more by requesting GRASP negotiation with peer ASAs. When its pool is sufficient, it hands resource out to peer ASAs in response to their negotiation requests. Over time, the origin's initial pool gets shared among all the delegators according to demand โœจ.

In theory, a network could have any number of origins and any number of delegators, as long as each origin's initial resource pool is unique ๐ŸŒˆ. A realistic scenario is exactly one origin and as many delegators as you like. A scenario with no origin is useless ๐Ÿ’€.

This is an implementation requirement: resource pools are kept in stable storage ๐Ÿ˜ญ. Otherwise, if a delegator exits for any reason, all the resources it has obtained or delegated are lost. If an origin exits, its entire spare pool is lost. The logic for using stable storage and for crash recovery isn't included in the pseudocode below, which focuses on communication between ASAs. Since GRASP operations are not intrinsically idempotent, data integrity during failure scenarios is the responsibility of the ASA designer. That's a complex topic in its own right, and this document doesn't discuss it.

The description below does not implement GRASP's dry run function. That would take temporarily marking any resource handed out in a dry run negotiation as reserved, until either the peer obtains it in a live run, or a suitable timeout occurs โณ.

The main data structures in each instance of the ASA are:

  • resource_pool: an ordered list of available resources, for example. Depending on the nature of the resource, units of resource are split when appropriate, and a background garbage collector recombines split resources if they're returned to the pool ๐Ÿงฉ.
  • delegated_list: where a delegator stores the resources it has given to subsidiary devices ๐ŸŽ€.

The possible main logic flows are below, using a threaded implementation model ๐Ÿงต. As noted above, alternative approaches to asynchronous operations are possible. The transformation to an event loop model should be apparent: each thread would correspond to one event in the event loop.

The GRASP objectives are as follows:

  • ["EX1.Resource", flags, loop_count, value], where the value depends on the resource concerned but will typically include its size and identification.
  • ["EX1.Params", flags, loop_count, value], where the value will be, for example, a JSON object defining the applicable parameters.

In the outline logic flows below, these objectives are represented simply by their names ๐Ÿ’œ.


Here's the MAIN PROGRAM logic, the bit that runs everything ๐Ÿ‘‘:

MAIN PROGRAM:

Create empty resource_pool (and an associated lock)
Create empty delegated_list
Determine whether to act as origin
if origin:
    Obtain initial resource_pool contents from NOC
    Obtain value of EX1.Params from NOC
Register ASA with GRASP
Register GRASP objectives EX1.Resource and EX1.Params
if origin:
    Start FLOODER thread to flood EX1.Params
    Start SYNCHRONIZER listener for EX1.Params
Start MAIN_NEGOTIATOR thread for EX1.Resource
if not origin:
    Obtain value of EX1.Params from GRASP flood or synchronization
    Start DELEGATOR thread
Start GARBAGE_COLLECTOR thread
good_peer = none
do forever:
    if resource_pool is low:
        Calculate amount A of resource needed
        Discover peers using GRASP M_DISCOVER / M_RESPONSE
        if good_peer in peers:
            peer = good_peer
        else:
            peer =  #any choice among peers
        grasp.request_negotiate("EX1.Resource", peer)
        #i.e., send negotiation request
        Wait for response (M_NEGOTIATE, M_END or M_WAIT)
        if OK:
            if offered amount of resource sufficient:
                Send M_END + O_ACCEPT #negotiation succeeded
                Add resource to pool
                good_peer = peer      #remember this choice
            else:
                Send M_END + O_DECLINE #negotiation failed
                good_peer = none       #forget this choice
    sleep() #periodic timer suitable for application scenario

Next up is the MAIN_NEGOTIATOR, which is always listening for requests ๐Ÿ‘‚:

MAIN_NEGOTIATOR thread:

do forever:
    grasp.listen_negotiate("EX1.Resource")
    #i.e., wait for negotiation request
    Start a separate new NEGOTIATOR thread for requested amount A

Then the NEGOTIATOR thread, which handles one request at a time ๐Ÿค:

NEGOTIATOR thread:

Request resource amount A from resource_pool
if not OK:
    while not OK and A > Amin:
        A = A-1
        Request resource amount A from resource_pool
if OK:
    Offer resource amount A to peer by GRASP M_NEGOTIATE
    if received M_END + O_ACCEPT:
        #negotiation succeeded
    elif received M_END + O_DECLINE or other error:
        #negotiation failed
        Return resource to resource_pool
else:
    Send M_END + O_DECLINE #negotiation failed
#thread exits

The DELEGATOR thread is the one that actually hands resource to consumers ๐ŸŽ:

DELEGATOR thread:

do forever:
    Wait for request or release for resource amount A
    if request:
        Get resource amount A from resource_pool
        if OK:
            Delegate resource to consumer #atomic
            Record in delegated_list      #operation
        else:
            Signal failure to consumer
            Signal main thread that resource_pool is low
    else:
        Delete resource from delegated_list
        Return resource amount A to resource_pool

The SYNCHRONIZER thread just answers sync requests for the parameters ๐Ÿ”:

SYNCHRONIZER thread:

do forever:
    Wait for  M_REQ_SYN message for EX1.Params
    Reply with M_SYNCH message for EX1.Params

The FLOODER thread keeps sending the parameters out on a timer ๐ŸŒŠ:

FLOODER thread:

do forever:
    Send M_FLOOD message for EX1.Params
    sleep() #periodic timer suitable for application scenario

And last but not least, the GARBAGE_COLLECTOR tidies up the pool so split pieces can be merged back together ๐Ÿงน:

GARBAGE_COLLECTOR thread:

do forever:
    Search resource_pool for adjacent resources
    Merge adjacent resources
    sleep() #periodic timer suitable for application scenario

Acknowledgements ๐Ÿ™

Valuable comments were received from Michael Behringer, Menachem Dodge, Martin Dรผrst, Toerless Eckert, Thomas Fossati, Alex Galis, Bing Liu, Benno Overeinder, Michael Richardson, Rob Wilton, and other IESG members. Huge thanks to all of them, they're literally the MVPs ๐Ÿ’–.

Authors' Addresses ๐Ÿ’Œ

Brian Carpenter

School of Computer Science
University of Auckland
PB 92019
Auckland 1142
New Zealand
Email: brian.e.carpenter@gmail.com

Laurent Ciavaglia

Rakuten Mobile
Paris
France
Email: laurent.ciavaglia@rakuten.com

Sheng Jiang

Huawei Technologies Co., Ltd
Q14 Huawei Campus
156 Beiqing Road
Hai-Dian District
Beijing
100095
China
Email: jiangsheng@huawei.com

Pierre Peloso

Nokia
Villarceaux
91460 Nozay
France
Email: pierre.peloso@nokia.com
๐Ÿ“ฆ where this page comes from