aft_operations_ordering_test - openconfig/featureprofiles GitHub Wiki

TE-3.9: gRIBI AFT Operations Ordering

Summary

Validates whether the Network Operating System (NOS) gRIBI daemon adheres to the OpenConfig gRIBI specification recommendation (gribi.proto:62):

"A gRIBI server SHOULD process AFTOperations per the received order."

The test executes sequences (up to 2,000 operations per test) of rapid AFT modifications, replacements, and deletions to verify that:

  1. Operations within a pipelined gRPC stream across multiple ModifyRequest messages without intermediate client-side await barriers are processed in exact arrival order (Inter-Request Stream Ordering).
  2. Operations batched within a single ModifyRequest array are processed in exact index order (Intra-Request Sequential Ordering).
  3. Cross-layer referential integrity is preserved during rapid Make-Before-Break (MBB) migrations ($\text{NH} \to \text{NHG} \to \text{TL}$ bottom-up creation and $\text{TL} \to \text{NHG} \to \text{NH}$ top-down teardown).
  4. The gRIBI server acknowledges each operation in the stream with RIB_ACK (fluent.InstalledInRIB / AFTResult_RIB_PROGRAMMED) without transport drops, out-of-order execution, or reference violations.

Testbed Type

  • TESTBED_DUT_ATE_2LINKS
    • DUT Port 1 (192.0.2.1/30) $\leftrightarrow$ ATE Port 1 (192.0.2.2/30)
    • DUT Port 2 (192.0.2.5/30) $\leftrightarrow$ ATE Port 2 (192.0.2.6/30) (Target for NextHop 1)
    • DUT Port 2 Secondary (192.0.2.10/30) $\leftrightarrow$ ATE Port 2 Secondary (Target for NextHop 2)

Procedure

Connect to the gRIBI server running on the DUT, negotiating RIB_ACK as the requested ack_type, persistence mode PRESERVE, and SINGLE_PRIMARY redundancy mode. Become leader. Between all subtests, perform gribi.FlushAll to ensure a completely clean baseline.

Group 1: Inter-Request Pipelined Stream (2,000 ModifyRequests, No Client-Side Await)

  • TE-3.9.1: Inter-Request NextHop Churn

    • Stream 1,000 consecutive pairs of $\langle \text{ADD}(\text{NH}_1), \text{DEL}(\text{NH}_1) \rangle$ ($2{,}000$ operations total), where each operation is sent in an independent ModifyRequest on the gRPC stream without waiting for intermediate responses.
    • Verify that all 2,000 operations are acknowledged with RIB_ACK (status OK).
  • TE-3.9.2: Inter-Request NextHopGroup Mutation

    • Pre-program static base NextHops $\text{NH}_1$ and $\text{NH}_2$.
    • Stream 666 consecutive triplets of $\langle \text{ADD}(\text{NHG}_1 \to [\text{NH}_1]), \text{REPLACE}(\text{NHG}_1 \to [\text{NH}_2]), \text{DEL}(\text{NHG}_1) \rangle$ ($1{,}998$ operations total) across independent ModifyRequest messages without awaiting intermediate responses.
    • Verify that all 1,998 operations receive RIB_ACK.
  • TE-3.9.3: Inter-Request Top-Level Route Mutation

    • Pre-program static base NextHops $\text{NH}_1, \text{NH}_2$ and NextHopGroups $\text{NHG}_1, \text{NHG}_2$.
    • Stream 666 consecutive triplets of $\langle \text{ADD}(\text{TL}_1 \to \text{NHG}_1), \text{REPLACE}(\text{TL}_1 \to \text{NHG}_2), \text{DEL}(\text{TL}_1) \rangle$ ($1{,}998$ operations total) across independent ModifyRequest messages without awaiting intermediate responses.
    • Verify that all 1,998 operations receive RIB_ACK.
  • TE-3.9.4: Inter-Request Cross-Layer Make-Before-Break Ping-Pong

    • Program base state $\text{NH}_1, \text{NHG}_1 \to [\text{NH}_1], \text{TL}_1 \to \text{NHG}_1$.
    • Stream 200 full round-trip cycles ($2{,}000$ operations total) where each round-trip comprises:
      1. Make/Break $1 \to 2$: $\langle \text{ADD}(\text{NH}_2), \text{ADD}(\text{NHG}_2 \to \text{NH}_2), \text{REPLACE}(\text{TL}_1 \to \text{NHG}_2), \text{DEL}(\text{NHG}_1), \text{DEL}(\text{NH}_1) \rangle$
      2. Make/Break $2 \to 1$: $\langle \text{ADD}(\text{NH}_1), \text{ADD}(\text{NHG}_1 \to \text{NH}_1), \text{REPLACE}(\text{TL}_1 \to \text{NHG}_1), \text{DEL}(\text{NHG}_2), \text{DEL}(\text{NH}_2) \rangle$
    • Verify that all 2,000 operations receive RIB_ACK with zero reference or in-use errors.

Group 2: Intra-Request Batching (Single ModifyRequest, 2,000 Operations)

  • TE-3.9.5: Intra-Request NextHop Churn

    • Send a single ModifyRequest containing 1,000 consecutive pairs of $\langle \text{ADD}(\text{NH}_1), \text{DEL}(\text{NH}_1) \rangle$ ($2{,}000$ operations in the array).
    • Await stream convergence and verify that all 2,000 operations receive RIB_ACK.
  • TE-3.9.6: Intra-Request NextHopGroup Mutation

    • Pre-program static base NextHops $\text{NH}_1$ and $\text{NH}_2$.
    • Send a single ModifyRequest containing 666 consecutive triplets of $\langle \text{ADD}(\text{NHG}_1 \to [\text{NH}_1]), \text{REPLACE}(\text{NHG}_1 \to [\text{NH}_2]), \text{DEL}(\text{NHG}_1) \rangle$ ($1{,}998$ operations in the array).
    • Await stream convergence and verify that all 1,998 operations receive RIB_ACK.
  • TE-3.9.7: Intra-Request Top-Level Route Mutation

    • Pre-program static base NextHops $\text{NH}_1, \text{NH}_2$ and NextHopGroups $\text{NHG}_1, \text{NHG}_2$.
    • Send a single ModifyRequest containing 666 consecutive triplets of $\langle \text{ADD}(\text{TL}_1 \to \text{NHG}_1), \text{REPLACE}(\text{TL}_1 \to \text{NHG}_2), \text{DEL}(\text{TL}_1) \rangle$ ($1{,}998$ operations in the array).
    • Await stream convergence and verify that all 1,998 operations receive RIB_ACK.
  • TE-3.9.8: Intra-Request Cross-Layer Make-Before-Break Ping-Pong

    • Program base state $\text{NH}_1, \text{NHG}_1 \to [\text{NH}_1], \text{TL}_1 \to \text{NHG}_1$.
    • Send a single ModifyRequest containing 200 full round-trip cycles ($2{,}000$ operations in the array):
      • Cycle $1 \to 2$: $\langle \text{ADD}(\text{NH}_2), \text{ADD}(\text{NHG}_2), \text{REPLACE}(\text{TL}_1 \to 2), \text{DEL}(\text{NHG}_1), \text{DEL}(\text{NH}_1) \rangle$
      • Cycle $2 \to 1$: $\langle \text{ADD}(\text{NH}_1), \text{ADD}(\text{NHG}_1), \text{REPLACE}(\text{TL}_1 \to 1), \text{DEL}(\text{NHG}_2), \text{DEL}(\text{NH}_2) \rangle$
    • Await stream convergence and verify that all 2,000 operations receive RIB_ACK.

Config Parameter Coverage

N/A

Telemetry Parameter Coverage

N/A

Protocol/RPC Parameter Coverage

Canonical OC

{
  "interfaces": {
    "interface": [
      {
        "config": {
          "description": "dutPort1",
          "enabled": true,
          "name": "port1",
          "type": "iana-if-type:ethernetCsmacd"
        },
        "name": "port1",
        "subinterfaces": {
          "subinterface": [
            {
              "config": {
                "index": 0
              },
              "index": 0,
              "ipv4": {
                "addresses": {
                  "address": [
                    {
                      "config": {
                        "ip": "192.0.2.1",
                        "prefix-length": 30
                      },
                      "ip": "192.0.2.1"
                    }
                  ]
                },
                "config": {
                  "enabled": true
                }
              }
            }
          ]
        }
      },
      {
        "config": {
          "description": "dutPort2",
          "enabled": true,
          "name": "port2",
          "type": "iana-if-type:ethernetCsmacd"
        },
        "name": "port2",
        "subinterfaces": {
          "subinterface": [
            {
              "config": {
                "index": 0
              },
              "index": 0,
              "ipv4": {
                "addresses": {
                  "address": [
                    {
                      "config": {
                        "ip": "192.0.2.5",
                        "prefix-length": 30
                      },
                      "ip": "192.0.2.5"
                    },
                    {
                      "config": {
                        "ip": "192.0.2.9",
                        "prefix-length": 30,
                        "type": "SECONDARY"
                      },
                      "ip": "192.0.2.9"
                    }
                  ]
                },
                "config": {
                  "enabled": true
                }
              }
            }
          ]
        }
      }
    ]
  }
}

OpenConfig Path and RPC Coverage

paths:
  /interfaces/interface/config/description:
  /interfaces/interface/config/enabled:
  /interfaces/interface/config/name:
  /interfaces/interface/subinterfaces/subinterface/ipv4/addresses/address/config/ip:
  /interfaces/interface/subinterfaces/subinterface/ipv4/addresses/address/config/prefix-length:
  /interfaces/interface/subinterfaces/subinterface/ipv4/config/enabled:
rpcs:
  gnmi:
    gNMI.Set:
    gNMI.Subscribe:
  gribi:
    gRIBI.Modify:
    gRIBI.Flush:
⚠️ **GitHub.com Fallback** ⚠️