RFC 7409

Forwarding and Control Element Separation (ForCES) Packet Parallelization

πŸ“… published November 2014, from ietf

RFC 7409: Forwarding and Control Element Separation (ForCES) Packet Parallelization πŸ’–

Okay bestie, this one is from the Internet Engineering Task Force (IETF) 🌸. The authors are E. Haleplidis (University of Patras) and J. Halpern (Ericsson) 🫢. It's dated November 2014 and filed under Category: Experimental πŸ§ͺ. The ISSN is 2070-1721. It's experimental, so it's not a standards-track spec yet. It's a "try it and see" doc πŸ”¬.


Abstract ✨

Lots of network devices can process packets in parallel πŸ”₯. This document explains how Forwarding and Control Element Separation (ForCES) can model a network device's parallelization datapath. It uses the constructs from the ForCES model (RFC 5812) and is controlled through the ForCES protocol (RFC 5810) πŸ’….

Status of This Memo πŸ“œ

This document is not an Internet Standards Track spec. It's being published so people can examine it, try it out in experimental implementations, and evaluate it 🧐.

It defines an Experimental Protocol for the Internet community. It's a product of the IETF, it reflects the IETF community's consensus, and it has had public review. The Internet Engineering Steering Group (IESG) approved it for publication. Not everything the IESG approves is up for any level of Internet Standard, so see Section 2 of RFC 5741 for that πŸ€“.

For the latest status, errata, and feedback info, check http://www.rfc-editor.org/info/rfc7409 πŸ”—.

Copyright (c) 2014 IETF Trust and the people listed as document authors. All rights reserved πŸ’œ.

This doc is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (http://trustee.ietf.org/license-info) as they stood on the publication date. Read those carefully, because they spell out your rights and restrictions πŸ™ˆ. Any Code Components pulled out of this doc have to include Simplified BSD License text, as described in Section 4.e of the Trust Legal Provisions. They come with no warranty, same as the Simplified BSD License says ✨.

Table of Contents πŸ—‚οΈ

1.  Introduction  . . . . . . . . . . . . . . . . . . . . . . . .   4
  1.1.  Requirements Language . . . . . . . . . . . . . . . . . .   4
  1.2.  Definitions . . . . . . . . . . . . . . . . . . . . . . .   4
2.  Packet Parallelization  . . . . . . . . . . . . . . . . . . .   5
  2.1.  CoreParallelization LFB . . . . . . . . . . . . . . . . .   7
  2.2.  Parallelization Metadata  . . . . . . . . . . . . . . . .  10
3.  Parallel Base Types . . . . . . . . . . . . . . . . . . . . .  11
  3.1.  Frame Types . . . . . . . . . . . . . . . . . . . . . . .  11
  3.2.  Data Types  . . . . . . . . . . . . . . . . . . . . . . .  11
  3.3.  Metadata Types  . . . . . . . . . . . . . . . . . . . . .  12
4.  Parallel LFBs . . . . . . . . . . . . . . . . . . . . . . . .  12
  4.1.  Splitter  . . . . . . . . . . . . . . . . . . . . . . . .  12
    4.1.1.  Data Handling . . . . . . . . . . . . . . . . . . . .  13
    4.1.2.  Components  . . . . . . . . . . . . . . . . . . . . .  13
    4.1.3.  Capabilities  . . . . . . . . . . . . . . . . . . . .  13
    4.1.4.  Events  . . . . . . . . . . . . . . . . . . . . . . .  13
  4.2.  Merger  . . . . . . . . . . . . . . . . . . . . . . . . .  14
    4.2.1.  Data Handling . . . . . . . . . . . . . . . . . . . .  14
    4.2.2.  Components  . . . . . . . . . . . . . . . . . . . . .  15
    4.2.3.  Capabilities  . . . . . . . . . . . . . . . . . . . .  15
    4.2.4.  Events  . . . . . . . . . . . . . . . . . . . . . . .  16
  4.3.  CoreParallelization . . . . . . . . . . . . . . . . . . .  16
    4.3.1.  Data Handling . . . . . . . . . . . . . . . . . . . .  16
    4.3.2.  Components  . . . . . . . . . . . . . . . . . . . . .  16
    4.3.3.  Capabilities  . . . . . . . . . . . . . . . . . . . .  16
    4.3.4.  Events  . . . . . . . . . . . . . . . . . . . . . . .  17
5.  XML for Parallel LFB Library  . . . . . . . . . . . . . . . .  17
6.  IANA Considerations . . . . . . . . . . . . . . . . . . . . .  25
  6.1.  LFB Class Names and LFB Class Identifiers . . . . . . . .  25
  6.2.  Metadata ID . . . . . . . . . . . . . . . . . . . . . . .  26
7.  Security Considerations . . . . . . . . . . . . . . . . . . .  26
8.  References  . . . . . . . . . . . . . . . . . . . . . . . . .  26
  8.1.  Normative References  . . . . . . . . . . . . . . . . . .  26
  8.2.  Informative References  . . . . . . . . . . . . . . . . .  27
Acknowledgments   . . . . . . . . . . . . . . . . . . . . . . . .  27
Authors' Addresses  . . . . . . . . . . . . . . . . . . . . . . .  27

1. Introduction 🌈

Tons of network devices can process packets in parallel, and that's the whole vibe here 🧚. The ForCES model [RFC5812] gives a formal way to describe the Forwarding Plane's datapath using Logical Function Blocks (LFBs) written in XML πŸ“. This doc shows how packet parallelization can be described with the ForCES model πŸ’–.

The modeling concept was influenced by Cilk [Cilk] πŸ“. Cilk is a programming language that has been in development since 1994 at the Massachusetts Institute of Technology (MIT) Laboratory. It lets programmers mark which elements can run in parallel πŸ™Œ. This doc uses two Cilk concepts, "spawn" and "sync". Spawn is where parallel tasks can start, and sync is where a parallel task finishes and has to collect all of its parallel output. (Check Section 1.2 for the definitions of "task" and "task correlator" πŸ¦‹.)

This doc is Experimental, so the LFB Class IDs aren't going to be part of the Standard Action's values πŸ§ͺ. That means LFB Class IDs have to be larger than 65535, and LFB names have to start with the prefix Ext-. When this doc talks about LFB Class names in the text (not the formal definitions), it drops the Ext- prefix to keep things short πŸ’….

1.1. Requirements Language πŸ“£

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC2119] 🫢.

1.2. Definitions πŸ“–

This doc follows the terminology from the ForCES model in [RFC5812] ✨. In particular, you're expected to already know these terms:

  • FE
  • CE
  • FE Model
  • LFB Class (or type)
  • LFB Instance
  • LFB Model
  • Element
  • Attribute
  • LFB Metadata
  • ForCES Component
  • LFB Class Library

This doc also brings in these new terms πŸŽ€:

  • Chunk: Pieces of a packet.
  • Task: A grouping of packets or chunks that belong to the same packet and get processed in parallel.
  • Task Correlator: A 32-bit identifier that uniquely tells tasks apart πŸ”‘.
  • Split Type: A parallel type where packets get split into chunks that are processed in parallel. Every task in a split type is made up only of chunks 🍰.
  • Flood Type: A parallel type where packets get copied as-is to downstream LFBs to be processed in parallel. Every task in a flood type is made up only of packets 🌊.

2. Packet Parallelization ✨

okay so bestie, this section is about running packets through multiple paths at the same time 🧚 There are two flavors of parallelization:

  1. Flood: a copy of a packet gets sent to multiple LFBs so they can all process it in parallel πŸ’…
  2. Split: the packet gets chopped into chunks of equal size (the size is specified by the CE) and those chunks get sent to multiple LFB instances, probably of the same LFB class, to be processed in parallel πŸŽ€

It must be noted that the copying in flood parallelization is up to the implementation and is only loosely defined here πŸ™ˆ An implementer can physically copy the packet and send every copy down the parallel paths, or logically copy it by sending pointers to the same packet, as long as the necessary interlocks are handled. The implementer has to look at the device's characteristics to figure out which approach fits best. ✨

Split parallelization is trickier, but the implementer can also split the packet logically and send pointers to the parts of the packet, as long as the necessary interlocks are managed πŸ¦‹ How the chunks get distributed (like which chunk goes to which LFB) is also implementation dependent. Usually chunks go to the same LFB class, but the number of LFB instances doesn't have to match the number of chunks. It's up to the implementer to decide how the chunks get sent, for example in a round-robin fashion 🌈

This document introduces two LFBs that show up before and after the parallelization happens:

  1. Splitter: kinda like Cilk's spawn, a splitter is an LFB that splits the path of a packet that's going to be sent to multiple downstream LFBs for parallel processing πŸ“
  2. Merger: kinda like Cilk's sync, a merger is an LFB that receives packets or chunks of the same initial packet, then merges them (and their results) into one packet πŸ‘‘

Both parallel distribution types can be done with the ForCES model right now 🫢 The Splitter LFB has one group output that produces either chunks or packets to send to LFBs for processing, and the Merger LFB has one group input that expects either packets or chunks so it can aggregate all the parallel packets or chunks into a single packet. ✨

Figure 1 is a simple split parallel datapath with the Splitter and Merger LFBs. This one shows multiple regular expression (regex) match LFBs that each do match operations on parts of the original packet πŸ’œ Figure 2 is a flood parallel datapath with the Splitter and Merger LFBs. This example classifies an IPv4 packet while also doing metering, and on the other path, the IPv4 Time to Live (TTL) field gets decremented 🌸

                  C1+M   +------------+  C1+M
                   +---->| Regex LFB  |----+
    +----------+   |     +------------+    |       +----------+
    |          |---+                       +------>|          |
 P  |          |  C2+M   +------------+  C2+M      |          | P
--->| Splitter |-------->| Regex LFB  |----------->|  Merger  |--->
    |   LFB    |  CN+M   +------------+  CN+M      |   LFB    |
    |          |---+                       +------>|          |
    +----------+   |     +------------+    |       +----------+
                   +---->| Regex LFB  |----+
                         +------------+

Figure 1: Simple Split Parallel Processing

    +----------+    +------------+    +-------+    +----------+
    |          |P+M | Classifier |P+M | Meter |P+M |          |
 P  |          |--->|     LFB    |--->|  LFB  |--->|          | P
--->| Splitter |    +------------+    +-------+    |  Merger  |--->
    |   LFB    |                                   |   LFB    |
    |          |P+M       +------------+       P+M |          |
    |          |--------->|  IPv4 TTL  |---------->|          |
    +----------+          |  Decrement |           +----------+
                          |    LFB     |
                          +------------+

Figure 2: Simple Flood Parallel Processing

This version of the modeling framework does not allow nested parallel datapath topologies πŸ™…β€β™€οΈ The authors and the ForCES working group made that call because there wasn't a strong use case or need for it when they decided. Because of that, the metadata definition stayed simpler, and it is required to be transported between the splitter and its corresponding merger. If nested parallel datapaths ever become necessary, a new version of splitter and merger will need to be defined, along with an augmentation to the defined metadata. Future bestie problem, but noted πŸ“

2.1. CoreParallelization LFB

One important thing for a developer is being able to define which LFBs can be used in parallel mode, which LFBs can be parallelized with which, and the order in which parallel LFBs can be assembled 🧩

To get at the parallelization details, they went with a new LFB class: the CoreParallelization LFB πŸ’– This was chosen over making another change to the core FEObject LFB. The CoreParallelization exists only to define the capabilities for an FE's LFB parallelization. A CE using the ForCES protocol [RFC5810] can check for this LFB class in the FEObject's SupportedLFBs component. If it's there, that tells the CE the specific FE supports parallelization. There MUST be only one instance of the CoreParallelization LFB per FE πŸ”₯

The topology of the parallel datapath can be deferred and manipulated from the FEObject LFB's LFBTopology ✨

The CoreParallelization needs only one capability to specify each LFB that can be used in parallel mode:

  • The Name of the LFB.
  • The Class ID of the LFB.
  • The Version of the LFB.
  • The number of instances that class can support in parallel.
  • A list of LFB classes that can follow this LFB class in a pipeline for a parallel path.
  • A list of LFB classes that can exist before this LFB class in a pipeline for a parallel path.
  • A list of LFB classes that can process packets or chunks in parallel with this LFB class.

Here's the XML for it (yes it's a lot, but it's giving very organized 😭):

      <!-- Datatype -->
      <dataTypeDef>
         <name>ParallelLFBType</name>
         <synopsis>Table entry for parallel LFBs</synopsis>
         <struct>
            <component componentID="1">
               <name>LFBName</name>
               <synopsis>The name of an LFB Class</synopsis>
               <typeRef>string</typeRef>
            </component>
            <component componentID="2">
               <name>LFBClassID</name>
               <synopsis>The id of the LFB Class</synopsis>
               <typeRef>uint32</typeRef>
            </component>
            <component componentID="3">
               <name>LFBVersion</name>
               <synopsis>The version of the LFB Class used by this FE
               </synopsis>
               <typeRef>string</typeRef>
            </component>
            <component componentID="4">
               <name>LFBParallelOccurrenceLimit</name>
               <synopsis>The upper limit of instances of the same
                  parallel LFBs of this class</synopsis>
               <optional />
               <typeRef>uint32</typeRef>
            </component>
            <component componentID="5">
               <name>AllowedParallelAfters</name>
               <synopsis>List of LFB Classes that can follow this LFB
                  in a parallel pipeline</synopsis>
               <optional />
               <array>
                  <typeRef>uint32</typeRef>
               </array>
            </component>
            <component componentID="6">
               <name>AllowedParallelBefores</name>
               <synopsis>List of LFB Classes that this LFB class can
                  follow in a parallel pipeline</synopsis>
               <optional />
               <array>
                  <typeRef>uint32</typeRef>
               </array>
            </component>
            <component componentID="7">
               <name>AllowedParallel</name>
               <synopsis>List of LFB Classes that this LFB class can run
                  in parallel with</synopsis>
               <array>
                  <typeRef>uint32</typeRef>
               </array>
            </component>
         </struct>
      </dataTypeDef>

      <!-- Capability -->
            <capability componentID="32">
               <name>ParallelLFBs</name>
               <synopsis>List of all supported parallel LFBs</synopsis>
               <array type="Variable-size">
                  <typeRef>ParallelLFBType</typeRef>
               </array>
            </capability>

Figure 3: XML Definitions for CoreParallelization LFB

2.2. Parallelization Metadata

The splitting and merging mechanisms are expected to be an implementation issue πŸ€·β€β™€οΈ What this document does is define the operational parameters for splitting and merging: namely, the size of the chunks, what happens if a packet or chunk has been marked as invalid, and whether the merge LFB should wait for all packets or chunks to arrive. The following metadata set is defined as a struct:

  1. ParallelType - Flood or split
  2. TaskCorrelator - Identifies packets or chunks that belonged to the initial packet that entered the Splitter LFB
  3. ParallelNum - Sequence number of the packet or the chunk for a specific task
  4. ParallelPartsCount - Total number of packets or chunks for a specific task

This metadata is produced by the Splitter LFB, is opaque to LFBs on the parallel paths, and gets passed along to the Merger LFB without being consumed πŸ¦‹

If an LFB decides that a packet/chunk has to be dropped, the LFB MAY drop the packet/chunk, but the metadata MUST be sent to the Merger LFB's InvalidIn input port so merging can happen πŸ₯Ί

Additional metadata produced by LFBs inside a datapath MAY be aggregated within the Merger LFB and sent on after the merging process. If the same metadata definition shows up with multiple values, the Merger LFB MUST keep the first one it received from a valid packet or chunk πŸ’…


3. Parallel Base Types πŸŽ€

3.1. Frame Types

One frame type has been defined in this library 🌷

+-----------+-------------------------------------------------------+
| Frame     | Synopsis                                              |
| Name      |                                                       |
+-----------+-------------------------------------------------------+
| Chunk     | A chunk is a frame that is part of an original larger |
|           | frame.                                                |
+-----------+-------------------------------------------------------+

Parallel Frame Types

3.2. Data Types

One data type has been defined in this library πŸ’œ

+---------------+------------------------+--------------------------+
| DataType Name | Type                   | Synopsis                 |
+---------------+------------------------+--------------------------+
| ParallelTypes | Atomic uchar.  Special | The type of              |
|               | Values Flood (0),      | parallelization this     |
|               | Split (1).             | packet will go through.  |
+---------------+------------------------+--------------------------+

Parallel Data Types

3.3. Metadata Types ✨

okay bestie, this part is giving metadata πŸŽ€ the parallelization library gets its own metadata structure with ID 16, built using the ForCES model extension [RFC7408]. here's the whole table πŸ’œ

   +--------------------+--------+----+--------------------------------+
   |   Metadata Name    |  Type  | ID |            Synopsis            |
   +--------------------+--------+----+--------------------------------+
   |    ParallelType    | uchar  | 1  |  The type of parallelization   |
   |                    |        |    | this packet will go through. 0 |
   |                    |        |    |    for flood, 1 for split.     |
   |                    |        |    |                                |
   |   TaskCorrelator   | uint32 | 2  |  An identification number to   |
   |                    |        |    |   specify that a packet or a   |
   |                    |        |    |    chunk belongs to the same   |
   |                    |        |    |         parallel task.         |
   |                    |        |    |                                |
   |    ParallelNum     | uint32 | 3  |    Defines the number of a     |
   |                    |        |    | specific packet or chunk of a  |
   |                    |        |    |         specific task.         |
   |                    |        |    |                                |
   | ParallelPartsCount | uint32 | 4  |  Defines the total number of   |
   |                    |        |    |    packets or chunks for a     |
   |                    |        |    |         specific task.         |
   +--------------------+--------+----+--------------------------------+

                      Metadata Structure for Merging

4. Parallel LFBs πŸ”₯

4.1. Splitter πŸ¦‹

okay so the Splitter LFB is the one that gets the parallelizing party started πŸ₯³ it sends either the same packet (Figure 2) or chunks (Figure 1) of the same packet to multiple LFBs. iconic.

                         +---------------+
              SplitterIn |               | SplitterOut
              ---------->| Splitter LFB  |------------->
                         |               |
                         +---------------+

                      Figure 4: Splitter LFB

4.1.1. Data Handling πŸ’…

the Splitter LFB takes in any kind of packet through the singleton input, Input. it depends on what the CE configured for the ParallelType component. if the parallel type is flood (0), the same packet MUST be sent through all instances of the group output "SplitterOut" 🌊. if the parallel type is split (1), the packet gets cut into same-size chunks, except the last one, which MAY be smaller. the max size is set by the ChunkSize component βœ‚οΈ. chunks MAY be sent out in a round-robin fashion through instances of the group output "ParallelOut", or in any other way the implementer picks πŸŽ€. each packet or chunk comes with the following metadata, set up as a struct:

  • ParallelType - The parallel type: split or flood.
  • ParallelID - Generated by the Splitter LFB to identify which chunks or packets belong to the same parallel task.
  • ParallelNum - Each chunk or packet of a parallel ID gets a number, so the Merger LFB knows when it has gathered them all along with the ParallelPartsCount metadata 🧩.
  • ParallelPartsCount - The number of chunks or packets for the specific task.

4.1.2. Components πŸ“

the Splitter LFB has only two components. the first is ParallelType, a uint32 that defines how the packet gets processed by the Splitter LFB. the second is ChunkSize, a uint32 that specifies the size of each chunk when a packet is split into multiple same-size chunks. the last chunk MAY be smaller than the value of ChunkSize πŸ’–.

4.1.3. Capabilities 🌸

this LFB has only one capability specified: MinMaxChunkSize, a struct of two uint32s that set the minimum and maximum chunk size.

4.1.4. Events πŸ™ˆ

this LFB has no events specified. quiet girl era ✨

4.2. Merger 🌈

the Merger LFB is the synchronization point 🫢 it's where multiple packets or packet chunks of the same task come back together after the parallel path, as shown in Figure 1 and Figure 2.

                             +-------------+
                    MergerIn |             |
                   --------->|             | MergerOut
                             | Merger LFB  |----------->
                   InvalidIn |             |
                   --------->|             |
                             +-------------+

                         Figure 5: Merger LFB

4.2.1. Data Handling 🧠

the Merger LFB receives either a packet or a chunk through the group input ParallelIn, along with the ParallelType metadata, the TaskCorrelator, the ParallelNum, and the ParallelPartsCount.

if an upstream LFB has dropped a packet or a chunk, the Merger LFB MAY receive only the metadata, both the metadata and the packet, or the chunk through the InvalidIn group input port 😭. it SHOULD receive a metadata specifying the error code. the currently defined metadata in the Base LFB Library [RFC6956] is the ExceptionID and the ValidateErrorID.

if the MergeWaitType is set to false, the Merger LFB will start the merge process as soon as it gets the first packet. if false, then for each task identified by the task correlator, it waits for all packets/chunks to arrive, unless the MergeWaitTimeoutTimer timer expires ⏰. once the MergeWaitTimeoutTimer has expired, the Merger MUST consider the rest of the packets/chunks that haven't been received as invalid, and it MUST handle the packets according to the InvalidAction value. no skipping this part 🚨

if one packet or chunk has come in through the InvalidIn port, the merging procedure handles the packets/chunks according to the InvalidAction value. if the InvalidAction component is set to 0, then if one packet or chunk is not valid, all of them get dropped. otherwise the process initiates. once the merging process is completed, the resulting packet is sent out through the singleton output port MergerOut πŸ’Œ.

if the Merger LFB receives different values for the same metadata from different packets or chunks that share the same task correlator, it uses the first metadata from a packet or chunk that entered the LFB through the MergerIn input port 🎯.

4.2.2. Components πŸ’œ

this LFB has the following components specified:

  1. InvalidAction: A uchar that defines what the Merge LFB does when an invalid chunk or packet comes in. if set to 0 (DropAll), the merge is considered invalid and all chunks or packets get dropped. if set to 1 (Continue), the merge continues.
  2. MergeWaitTimeoutTimer: A uint32 that defines how long, in milliseconds, the Merger waits for all packets or chunks within the same task to arrive before it calls them invalid. this timer starts the moment the first chunk or packet of a parallel task arrives ⏱️.
  3. MergeWaitType: A boolean. if true, the Merger LFB waits for all packets or chunks to be received before doing the merge. if false, the moment one packet or a chunk with a response is received by the merge LFB, it starts the merge process 🌟.
  4. InvalidMergesCounter: A uint32 that counts the number of merges where at least one packet or chunk entered the Merger LFB through the InvalidIn input port.
  5. InvalidTotalCounter: A uint32 that counts the number of merges where all packets/chunks entered the Merger LFB through the InvalidIn input port.
  6. InvalidIDCounters: A struct of two arrays. each array has a uint32 per row. each array counts the number of invalid merges where at least one packet or chunk entered through InvalidID, per error ID. the first array is the InvalidExceptionID and the second is the InvalidValidateErrorID πŸ“Š.

4.2.3. Capabilities 🫧

this LFB has no capabilities specified.

4.2.4. Events 🚨

this LFB specifies only two events. the first detects whether the InvalidMergesCounter has gone over a specific value, and the second detects whether the InvalidAllCounter has gone over a specific value. both error reports send the respective counter value. Event Filters can be used to limit the number of messages

4.3. CoreParallelization πŸ‘‘

this is a core LFB that says the FE supports parallelization, instead of updating the FEObject LFB. main character energy πŸŽ€

4.3.1. Data Handling πŸ¦‹

the CoreParallelization doesn't handle data. it just vibes ✨

4.3.2. Components πŸ“

this LFB has no components specified.

4.3.3. Capabilities πŸ’–

this LFB has only one capability specified. ParallelLFBs is a table that lists all the LFBs that can be parallelized. each row of the table contains:

  1. LFBName: A string. The name of the parallel LFB.
  2. LFBClassID: A uint32. The Class ID of the parallel LFB.
  3. LFBVersion: A string. The version of the parallel LFB.
  4. LFBParallelOccurrenceLimit: A uint32. The upper limit of instances of the same parallel LFBs of this class.
  5. AllowedParallelAfters: A table of uint32s (LFB Class IDs). A list of LFB classes that can follow this LFB class in a pipeline for a parallel path.
  6. AllowedParallelBefores: A table of uint32s (LFB Class IDs). A list of LFB classes that can exist before this LFB class in a pipeline for a parallel path.
  7. AllowedParallel: A table of uint32s (LFB Class IDs). A list of LFB classes that can process packets or chunks in parallel with this LFB class.

4.3.4. Events 🧚

this LFB specifies no events.

5. XML for Parallel LFB Library 🌷

  <?xml version="1.0" encoding="UTF-8"?>
  <LFBLibrary xmlns="urn:ietf:params:xml:ns:forces:lfbmodel:1.1"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="urn:ietf:params:xml:ns:forces:lfbmodel:1.1"
     provides="Parallel">
    <load library="BaseTypeLibrary" location="BaseTypeLibrary.LFB"/>
    <frameDefs>
      <frameDef>
        <name>Chunk</name>
        <synopsis>A chunk is a frame that is part of an original
              larger frame</synopsis>
      </frameDef>
    </frameDefs>
    <dataTypeDefs>
      <dataTypeDef>
        <name>ParallelTypes</name>
        <synopsis>The type of parallelization this packet will go
              through</synopsis>
        <atomic>
          <baseType>uchar</baseType>
          <specialValues>
            <specialValue value="0">
              <name>Flood</name>
              <synopsis>The packet/chunk has been sent as a whole
                       to multiple recipients</synopsis>
            </specialValue>
            <specialValue value="1">
              <name>Split</name>
              <synopsis>The packet/chunk has been split into
                       multiple chunks and sent to recipients</synopsis>
            </specialValue>
          </specialValues>
        </atomic>
      </dataTypeDef>
      <dataTypeDef>
        <name>ParallelLFBType</name>
        <synopsis>Table entry for parallel LFBs</synopsis>
        <struct>
          <component componentID="1">
            <name>LFBName</name>
            <synopsis>The name of an LFB Class</synopsis>
            <typeRef>string</typeRef>

okay bestie, the XML keeps going and it's giving LFB realness πŸ’– here's the next chunk, every tag and value exactly as it is πŸŽ€

          </component>
          <component componentID="2">
            <name>LFBClassID</name>
            <synopsis>The ID of the LFB Class</synopsis>
            <typeRef>uint32</typeRef>
          </component>
          <component componentID="3">
            <name>LFBVersion</name>
            <synopsis>The version of the LFB Class used by this FE
               </synopsis>
            <typeRef>string</typeRef>
          </component>
          <component componentID="4">
            <name>LFBParallelOccurrenceLimit</name>
            <synopsis>The upper limit of instances of the same
                  parallel LFBs of this class</synopsis>
            <optional/>
            <typeRef>uint32</typeRef>
          </component>
          <component componentID="5">
            <name>AllowedParallelAfters</name>
            <synopsis>List of LFB Classes that can follow this LFB
                  in a parallel pipeline</synopsis>
            <optional/>
            <array>
              <typeRef>uint32</typeRef>
            </array>
          </component>
          <component componentID="6">
            <name>AllowedParallelBefores</name>
            <synopsis>List of LFB Classes that this LFB Class can
                  follow in a parallel pipeline</synopsis>
            <optional/>
            <array>
              <typeRef>uint32</typeRef>
            </array>
          </component>
          <component componentID="7">
            <name>AllowedParallel</name>
            <synopsis>List of LFB Classes that this LFB Class can be run
                  in parallel with</synopsis>
            <array>
              <typeRef>uint32</typeRef>
            </array>
          </component>
        </struct>
      </dataTypeDef>
    </dataTypeDefs>
    <metadataDefs>
      <metadataDef>
        <name>ParallelMetadataSet</name>
        <synopsis>A metadata set for parallelization-related LFBs
           </synopsis>
        <metadataID>32</metadataID>
        <struct>
          <component componentID="1">
            <name>ParallelType</name>
            <synopsis>The type of parallelization this packet/chunk
                    has gone through</synopsis>
            <typeRef>ParallelTypes</typeRef>
          </component>
          <component componentID="2">
            <name>TaskCorrelator</name>
            <synopsis>An identification number to specify that
                    packets or chunks originate from the same packet.
                 </synopsis>
            <typeRef>uint32</typeRef>
          </component>
          <component componentID="3">
            <name>ParallelNum</name>
            <synopsis>Defines the number of the specific packet or
                    chunk of the specific parallel ID.</synopsis>
            <typeRef>uint32</typeRef>
          </component>
          <component componentID="4">
            <name>ParallelPartsCount</name>
            <synopsis>Defines the total number of packets or chunks
                    for the specific parallel ID.</synopsis>
            <typeRef>uint32</typeRef>
          </component>
        </struct>
      </metadataDef>
    </metadataDefs>
    <LFBClassDefs>
      <LFBClassDef LFBClassID="65537">
        <name>Ext-Splitter</name>
        <synopsis>A Splitter LFB takes part in parallelizing the
              processing datapath.  It will either send the same packet
              or chunks of one packet to multiple LFBs</synopsis>
        <version>1.0</version>
        <inputPorts>
          <inputPort>
            <name>SplitterIn</name>
            <synopsis>An input port expecting any kind of frame
                 </synopsis>
            <expectation>

              <frameExpected>
                <ref>Arbitrary</ref>
              </frameExpected>
            </expectation>
          </inputPort>
        </inputPorts>
        <outputPorts>
          <outputPort group="true">
            <name>SplitterOut</name>
            <synopsis>A parallel output port that sends the same
                    packet to all output instances or chunks of the same
                    packet to output instances.  Each chunk is sent only
                    once by the LFB.</synopsis>
            <product>
              <frameProduced>
                <ref>Arbitrary</ref>
                <ref>Chunk</ref>
              </frameProduced>
              <metadataProduced>
                <ref>ParallelMetadataSet</ref>
              </metadataProduced>
            </product>
          </outputPort>
        </outputPorts>
        <components>
          <component componentID="1" access="read-write">
            <name>ParallelType</name>
            <synopsis>The type of parallelization this packet will
                    go through</synopsis>
            <typeRef>ParallelTypes</typeRef>
          </component>
          <component componentID="2" access="read-write">
            <name>ChunkSize</name>
            <synopsis>The size of a chunk when a packet is split
                    into multiple chunks of the same size</synopsis>
            <typeRef>uint32</typeRef>
          </component>
        </components>
        <capabilities>
          <capability componentID="31">
            <name>MinMaxChunkSize</name>
            <synopsis>The minimum and maximum size of a chunk
                    capable of split by this LFB</synopsis>
            <struct>
              <component componentID="1">
                <name>MinChunkSize</name>
                <synopsis>Minimum chunk size</synopsis>
                <optional/>
                <typeRef>uint32</typeRef>
              </component>
              <component componentID="2">
                <name>MaxChunkSize</name>
                <synopsis>Maximum chunk size</synopsis>
                <typeRef>uint32</typeRef>
              </component>
            </struct>
          </capability>
        </capabilities>
      </LFBClassDef>
      <LFBClassDef LFBClassID="65538">
        <name>Ext-Merger</name>
        <synopsis>A Merger LFB receives multiple packets or multiple
              chunks of the same packet and merge them into one merged
              packet</synopsis>
        <version>1.0</version>
        <inputPorts>
          <inputPort group="true">
            <name>MergerIn</name>
            <synopsis>A parallel input port that accepts packets
                    or chunks from all output instances</synopsis>
            <expectation>
              <frameExpected>
                <ref>Arbitrary</ref>
                <ref>Chunk</ref>
              </frameExpected>
              <metadataExpected>
                <ref>ParallelMetadataSet</ref>
              </metadataExpected>
            </expectation>
          </inputPort>
          <inputPort group="true">
            <name>InvalidIn</name>
            <synopsis>When a packet is sent out of an error port of
                    an LFB in a parallel path, it will be sent to this
                    output port in the Merger LFB</synopsis>
            <expectation>
              <frameExpected>
                <ref>Arbitrary</ref>
                <ref>Chunk</ref>
              </frameExpected>
              <metadataExpected>
                <one-of>
                  <ref>ExceptionID</ref>
                  <ref>ValidateErrorID</ref>
                </one-of>
              </metadataExpected>

            </expectation>
          </inputPort>
        </inputPorts>
        <outputPorts>
          <outputPort>
            <name>MergerOut</name>
            <synopsis>An output port expecting any kind of frame
                 </synopsis>
            <product>
              <frameProduced>
                <ref>Arbitrary</ref>
              </frameProduced>
            </product>
          </outputPort>
        </outputPorts>
        <components>
          <component componentID="1" access="read-write">
            <name>InvalidAction</name>
            <synopsis>What the Merge LFB will do if an invalid
                    chunk or packet is received</synopsis>
            <atomic>
              <baseType>uchar</baseType>
              <specialValues>
                <specialValue value="0">
                  <name>DropAll</name>
                  <synopsis>Drop all packets or chunks
                          </synopsis>
                </specialValue>
                <specialValue value="1">
                  <name>Continue</name>
                  <synopsis>Continue with the merge</synopsis>
                </specialValue>
              </specialValues>
            </atomic>
          </component>
          <component componentID="2" access="read-write">
            <name>MergeWaitType</name>
            <synopsis>Whether the Merge LFB will wait for all
                    packets or chunks to be received prior to sending
                    out a response</synopsis>
            <typeRef>boolean</typeRef>
          </component>
          <component componentID="3" access="read-write">
            <name>MergeWaitTimeoutTimer</name>
            <synopsis>The time that the Merger will wait
            for all packets or chunks within the same task to arrive
            before considering them invalid.</synopsis>
            <typeRef>uint32</typeRef>

          </component>
          <component componentID="4" access="read-reset">
            <name>InvalidMergesCounter</name>
            <synopsis>Counts the number of merges where there is at
                    least one packet/chunk that entered the Merger LFB
                    through the InvalidIn input port</synopsis>
            <typeRef>uint32</typeRef>
          </component>
          <component componentID="5" access="read-reset">
            <name>InvalidTotalCounter</name>
            <synopsis>Counts the number of merges where all
                    packets/chunks entered the Merger LFB through the
                    InvalidIn input port</synopsis>
            <typeRef>uint32</typeRef>
          </component>
          <component componentID="6" access="read-reset">
            <name>InvalidIDCounters</name>
            <synopsis>Counts the number of invalid merges where at
                    least one packet/chunk entered through InvalidID per
                    error ID</synopsis>
            <struct>
              <component componentID="1">
                <name>InvalidExceptionID</name>
                <synopsis>Per Exception ID</synopsis>
                <array>
                  <typeRef>uint32</typeRef>
                </array>
              </component>
              <component componentID="2">
                <name>InvalidValidateErrorID</name>
                <synopsis>Per Validate Error ID</synopsis>
                <array>
                  <typeRef>uint32</typeRef>
                </array>
              </component>
            </struct>
          </component>
        </components>
        <events baseID="30">
          <event eventID="1">
            <name>ManyInvalids</name>
            <synopsis>An event that specifies if there are too many
                    invalids</synopsis>
            <eventTarget>
              <eventField>InvalidCounter</eventField>
            </eventTarget>
            <eventGreaterThan/>
            <eventReports>
              <eventReport>
                <eventField>InvalidMergesCounter</eventField>
              </eventReport>
            </eventReports>
          </event>
          <event eventID="2">
            <name>ManyTotalInvalids</name>
            <synopsis>An event that specifies if there are too many
                    invalids</synopsis>
            <eventTarget>
              <eventField>InvalidTotalCounter</eventField>
            </eventTarget>
            <eventGreaterThan/>
            <eventReports>
              <eventReport>
                <eventField>InvalidTotalCounter</eventField>
              </eventReport>
            </eventReports>
          </event>
        </events>
      </LFBClassDef>
      <LFBClassDef LFBClassID="65539">
        <name>Ext-CoreParallelization</name>
        <synopsis>A core LFB that specifies that the FE supports
          parallelization instead of updating the FEObject
          LFB</synopsis>
        <version>1.0</version>
        <capabilities>
          <capability componentID="10">
            <name>ParallelLFBs</name>
            <synopsis>A table that lists all the LFBs that can be
                parallelized</synopsis>
            <array>
              <typeRef>ParallelLFBType</typeRef>
            </array>
          </capability>
        </capabilities>
      </LFBClassDef>
    </LFBClassDefs>
  </LFBLibrary>

Figure 6: Parallel LFB Library πŸ’–

6. IANA Considerations ✨

6.1. LFB Class Names and LFB Class Identifiers

okay bestie, so the LFB classes defined in this document are not Standards Action LFBs πŸ™ˆ which means their values live way up in the IANA registry at <http://www.iana.org/assignments/forces>. Their numbers are all above 65535, so they don't crash into the official ones. Super organized, I love it πŸŽ€

Here's everything this specification adds to the "Logical Functional Block (LFB) Class Names and Class Identifiers" registry πŸ¦‹

+-------+---------------------+-------+-----------------+---------+
| LFB   |  LFB Class Name     |  LFB  |  Description    |   Ref   |
| Class |                     |Version|                 |         |
| ID    |                     |       |                 |         |
+-------+---------------------+-------+-----------------+---------+
| 65537 |   Ext-Splitter      |  1.0  | A Splitter LFB  |   RFC   |
|       |                     |       |  will send      |   7409  |
|       |                     |       |either the same  |         |
|       |                     |       |   packet or     |         |
|       |                     |       | chunks of one   |         |
|       |                     |       |   packet to     |         |
|       |                     |       | multiple LFBs.  |         |
+-------+---------------------+-------+-----------------+---------+
| 65538 |    Ext-Merger       |   1.0 |  A Merger LFB   |   RFC   |
|       |                     |       |    receives     |   7409  |
|       |                     |       |    multiple     |         |
|       |                     |       |   packets or    |         |
|       |                     |       |    multiple     |         |
|       |                     |       | chunks of the   |         |
|       |                     |       |  same packet    |         |
|       |                     |       |   and merges    |         |
|       |                     |       | them into one.  |         |
+-------+---------------------+-------+-----------------+---------+
| 65539 | Ext-                |   1.0 | A core LFB to   |   RFC   |
|       | CoreParallelization |       | signify the     |   7409  |
|       |                     |       | parallelization |         |
|       |                     |       |   capability    |         |
+-------+---------------------+-------+-----------------+---------+

     Logical Functional Block (LFB) Class Names and Class Identifiers

6.2. Metadata ID

The Metadata ID namespace is 32-bits long πŸ“ The only value this specification assigns is the one below, so it's a pretty chill list ✨

         +------------+---------------------+-----------+
         |   Value    |         Name        | Reference |
         +------------+---------------------+-----------+
         | 0x00000010 | ParallelMetadataSet |  RFC 7409 |
         +------------+---------------------+-----------+

            Metadata ID Assigned by this Specification

7. Security Considerations πŸ”₯

Okay, this section is kind of the serious one, so listen up 🫢 This document does not change either the ForCES model [RFC5812] or the ForCES protocol [RFC5810]. Because of that, it has no impact on their security considerations. Bestie, that's a whole lot of nothing to worry about from this doc, which is iconic πŸ’…

What this document actually does is define the operational parameters and capabilities of LFBs that do parallelization. It does not define how parallelization gets implemented. And it also does not try to analyze whether allowing parallel operations on packets creates any security interactions. If there are any issues there, they are for the designers of the particular data path to deal with, not the general mechanism. So if you're building one, that's your responsibility, babe πŸ˜­πŸ™ˆ

8. References πŸ¦‹

8.1. Normative References

[RFC2119]  Bradner, S., "Key words for use in RFCs to Indicate
           Requirement Levels", BCP 14, RFC 2119, March 1997,
           <http://www.rfc-editor.org/info/rfc2119>.

[RFC5810]  Doria, A., Hadi Salim, J., Haas, R., Khosravi, H., Wang,
           W., Dong, L., Gopal, R., and J. Halpern, "Forwarding and
           Control Element Separation (ForCES) Protocol
           Specification", RFC 5810, March 2010,
           <http://www.rfc-editor.org/info/rfc5810>.

[RFC5812]  Halpern, J. and J. Hadi Salim, "Forwarding and Control
           Element Separation (ForCES) Forwarding Element Model", RFC
           5812, March 2010,
           <http://www.rfc-editor.org/info/rfc5812>.

[RFC6956]  Wang, W., Haleplidis, E., Ogawa, K., Li, C., and J.
           Halpern, "Forwarding and Control Element Separation
           (ForCES) Logical Function Block (LFB) Library", RFC 6956,
           June 2013, <http://www.rfc-editor.org/info/rfc6956>.

[RFC7408]  Haleplidis, E., "Forwarding and Control Element Separation
           (ForCES) Model Extension", RFC 7408, November 2014,
           <http://www.rfc-editor.org/info/rfc7408>.

8.2. Informative References

[Cilk]     Massachusetts Institute of Technology, "The Cilk Project",
           <http://supertech.csail.mit.edu/cilk/>.

Acknowledgments 🌸

The authors would like to thank Edward Crabbe for the initial discussion that got this whole document started πŸ’œ They also thank Jamal Hadi Salim and Dave Hood for their comments and discussions, and Adrian Farrel for his AD review that made the document even better ✨ Finally, the authors thank Francis Dupont for his Gen-Art review and Magnus Nystroem for his security review. Both of those reviews refined the document into its final shape πŸ‘‘

Authors' Addresses 🧚

Evangelos Haleplidis
University of Patras
Department of Electrical and Computer Engineering
Patras  26500
Greece

EMail: ehalep@ece.upatras.gr


Joel Halpern
Ericsson
P.O. Box 6049
Leesburg, VA  20178
United States

Phone: +1 703 371 3043
EMail: joel.halpern@ericsson.com
πŸ“¦ where this page comes from