aft_operations_ordering_test - openconfig/featureprofiles GitHub Wiki
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:
- Operations within a pipelined gRPC stream across multiple
ModifyRequestmessages without intermediate client-sideawaitbarriers are processed in exact arrival order (Inter-Request Stream Ordering). - Operations batched within a single
ModifyRequestarray are processed in exact index order (Intra-Request Sequential Ordering). - 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). - 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_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)
- DUT Port 1 (
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.
-
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 independentModifyRequeston the gRPC stream without waiting for intermediate responses. - Verify that all 2,000 operations are acknowledged with
RIB_ACK(statusOK).
- Stream 1,000 consecutive pairs of
-
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 independentModifyRequestmessages without awaiting intermediate responses. - Verify that all 1,998 operations receive
RIB_ACK.
- Pre-program static base NextHops
-
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 independentModifyRequestmessages without awaiting intermediate responses. - Verify that all 1,998 operations receive
RIB_ACK.
- Pre-program static base NextHops
-
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:- 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$ - 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$
- Make/Break
- Verify that all 2,000 operations receive
RIB_ACKwith zero reference or in-use errors.
- Program base state
-
TE-3.9.5: Intra-Request NextHop Churn
- Send a single
ModifyRequestcontaining 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.
- Send a single
-
TE-3.9.6: Intra-Request NextHopGroup Mutation
- Pre-program static base NextHops
$\text{NH}_1$ and$\text{NH}_2$ . - Send a single
ModifyRequestcontaining 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.
- Pre-program static base NextHops
-
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
ModifyRequestcontaining 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.
- Pre-program static base NextHops
-
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
ModifyRequestcontaining 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$
- Cycle
- Await stream convergence and verify that all 2,000 operations receive
RIB_ACK.
- Program base state
N/A
N/A
{
"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
}
}
}
]
}
}
]
}
}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: