Skip to content

Commit 3084ac6

Browse files
committed
Merge branch 'main' into otg-rt-5.14
2 parents ea05d0d + 3a3b703 commit 3084ac6

File tree

64 files changed

+3456
-2139
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+3456
-2139
lines changed

.github/workflows/test_gap_analysis.yaml

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
# .github/workflows/test_gap_analysis.yaml
21
name: FNT Gap Analysis
32

43
on:
@@ -10,29 +9,36 @@ permissions: {}
109
jobs:
1110
gap_analysis_test:
1211
runs-on: ubuntu-latest
12+
env:
13+
GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
1314
permissions:
1415
contents: read
1516
pull-requests: read
1617
steps:
18+
- name: Show skip message
19+
if: ${{ env.GEMINI_API_KEY == '' }}
20+
run: echo "No access to Gemini, skipping test."
1721
- name: Checkout code
22+
if: ${{ env.GEMINI_API_KEY != '' }}
1823
uses: actions/checkout@v4
1924
with:
2025
fetch-depth: 0 # Needed for changed-files action to diff against base branch
2126

2227
- name: Set up Go
28+
if: ${{ env.GEMINI_API_KEY != '' }}
2329
uses: actions/setup-go@v5
2430
with:
2531
go-version: '1.21'
2632

2733
- name: Get changed files
34+
if: ${{ env.GEMINI_API_KEY != '' }}
2835
id: changed-files-pr
2936
uses: tj-actions/changed-files@v44
3037
with:
3138
separator: ','
3239

3340
- name: Run Gap Analysis Script
34-
env:
35-
GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
41+
if: ${{ env.GEMINI_API_KEY != '' }}
3642
run: |
3743
echo "--- Building and Running FNT Gap Analysis ---"
3844
go build -o gap-analyzer tools/gap-analyzer/read_fnttests.go

feature/acl/otg_tests/acl_large_scale/acl_large_scale_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -918,7 +918,7 @@ func testv4AddressScale(t *testing.T, dut *ondatra.DUTDevice, ate *ondatra.ATEDe
918918
}
919919

920920
for _, acl := range aclConfigs {
921-
if deviations.ConfigAclOcUnsupported(dut) {
921+
if deviations.ConfigACLOcUnsupported(dut) {
922922
switch dut.Vendor() {
923923
case ondatra.ARISTA:
924924
aclTarfficPolicy := cfgplugins.ACLTrafficPolicyParams{
@@ -945,7 +945,7 @@ func testv4AddressScale(t *testing.T, dut *ondatra.DUTDevice, ate *ondatra.ATEDe
945945
}
946946

947947
// Verification of ACL on interfaces as Ingress & Egress
948-
if !deviations.ConfigAclOcUnsupported(dut) {
948+
if !deviations.ConfigACLOcUnsupported(dut) {
949949
var expectedACLs = []struct {
950950
Name string
951951
Ingress bool
@@ -1152,7 +1152,7 @@ func testv6AddressScale(t *testing.T, dut *ondatra.DUTDevice, ate *ondatra.ATEDe
11521152
}
11531153

11541154
for _, acl := range aclConfigs {
1155-
if deviations.ConfigAclOcUnsupported(dut) {
1155+
if deviations.ConfigACLOcUnsupported(dut) {
11561156
switch dut.Vendor() {
11571157
case ondatra.ARISTA:
11581158
aclTarfficPolicy := cfgplugins.ACLTrafficPolicyParams{
@@ -1179,7 +1179,7 @@ func testv6AddressScale(t *testing.T, dut *ondatra.DUTDevice, ate *ondatra.ATEDe
11791179
}
11801180

11811181
// Verify ACL is applied on the interfaces
1182-
if !deviations.ConfigAclOcUnsupported(dut) {
1182+
if !deviations.ConfigACLOcUnsupported(dut) {
11831183
var expectedACLs = []struct {
11841184
Name string
11851185
Ingress bool
@@ -1317,7 +1317,7 @@ func testv6AddressScale(t *testing.T, dut *ondatra.DUTDevice, ate *ondatra.ATEDe
13171317
}
13181318

13191319
func testv4PrefixList(t *testing.T, dut *ondatra.DUTDevice, ate *ondatra.ATEDevice, otgConfig *otg.OTG, config gosnappi.Config) {
1320-
if !deviations.ConfigAclOcUnsupported(dut) {
1320+
if !deviations.ConfigACLOcUnsupported(dut) {
13211321
// Remove the ACL configs from interface
13221322
removeAClOnInterface(t, dut, "port1")
13231323
removeAClOnInterface(t, dut, "port2")

feature/afts/otg_tests/afts_atomic/afts_atomic_test.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,9 @@ func (tc *testCase) waitForISISAdjacency(t *testing.T) error {
241241
}
242242

243243
dutPort := tc.dut.Port(t, port1Name).Name()
244+
if deviations.InterfaceRefInterfaceIDFormat(tc.dut) {
245+
dutPort = dutPort + ".0"
246+
}
244247
adjPath := isisPath.Interface(dutPort).Level(2).AdjacencyAny()
245248
if _, ok := gnmi.WatchAll(t, tc.dut, adjPath.AdjacencyState().State(), gnmiTimeout, verifyAdjacencyState).Await(t); !ok {
246249
return fmt.Errorf("no ISIS adjacency formed for port1 (%s)", dutPort)

feature/afts/otg_tests/afts_atomic/metadata.textproto

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ platform_exceptions: {
4141
isis_level_enabled: true
4242
multipath_unsupported_neighbor_or_afisafi: true
4343
explicit_interface_in_default_vrf: true
44+
interface_ref_interface_id_format: true
4445
}
4546
}
4647

feature/afts/otg_tests/afts_reboot/afts_reboot_test.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,9 @@ func (tc *testCase) waitForISISAdjacency(t *testing.T) error {
244244
return state == oc.Isis_IsisInterfaceAdjState_UP
245245
}
246246
dutPort := tc.dut.Port(t, port1Name).Name()
247+
if deviations.InterfaceRefInterfaceIDFormat(tc.dut) {
248+
dutPort = dutPort + ".0"
249+
}
247250
adjPath := isisPath.Interface(dutPort).Level(2).AdjacencyAny()
248251
if _, ok := gnmi.WatchAll(t, tc.dut, adjPath.AdjacencyState().State(), gnmiTimeout, verifyAdjacencyState).Await(t); !ok {
249252
return fmt.Errorf("no ISIS adjacency formed for port1 (%s)", dutPort)

feature/afts/otg_tests/afts_reboot/metadata.textproto

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,5 +41,6 @@ platform_exceptions: {
4141
isis_level_enabled: true
4242
multipath_unsupported_neighbor_or_afisafi: true
4343
explicit_interface_in_default_vrf: true
44+
interface_ref_interface_id_format: true
4445
}
4546
}
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
# RT-1.71: BGP Disable Peer AS Filter (`disable-peer-as-filter`)
2+
3+
## Summary
4+
5+
Verifies BGP disable-peer-as-filter functionality for both IPv4 and IPv6 Unicast sessions. This feature ensures that a router can accept routes from an eBGP peer even if the receiving router's own AS is present in the AS-PATH.
6+
7+
## Testbed type
8+
9+
* [TESTBED_DUT_ATE_2LINKS](https://github.com/openconfig/featureprofiles/blob/main/topologies/ate_tests/base_2link_topology.testbed)
10+
11+
## Topology
12+
13+
```mermaid
14+
flowchart LR
15+
subgraph ATE ["Automated Test Equipment"]
16+
ATE1(["Port 1 AS 64496"])
17+
ATE2(["Port 2 AS 64497"])
18+
end
19+
20+
subgraph DUT_Domain ["Device Under Test"]
21+
DUT(["DUT AS 64498"])
22+
end
23+
24+
ATE1 <-->|eBGP| DUT
25+
DUT <-->|eBGP| ATE2
26+
```
27+
28+
* **ATE Port 1** (AS 64496) connects to the **DUT** (AS 64498) via eBGP.
29+
* **DUT** (AS 64498) connects to **ATE Port 2** (AS 64497) via eBGP.
30+
31+
## Test environment setup
32+
33+
1. Configure eBGP sessions (IPv4 and IPv6) between ATE Port 1, DUT, and ATE Port 2.
34+
2. Use the following RFC-compliant addresses:
35+
* **Link 1 (ATE1 - DUT):** `192.0.2.0/30`, `2001:db8::1/126`
36+
* **Link 2 (ATE2 - DUT):** `198.51.100.0/30`, `2001:db8::5/126`
37+
38+
39+
## Procedure
40+
41+
### RT-1.71.1: Baseline Test (Default Filtering)
42+
43+
1. Establish eBGP sessions (IPv4 and IPv6) between ATE Port 1, DUT, and ATE Port 2.
44+
2. Advertise a prefix (e.g., `192.0.2.100/32` and `2001:db8:64:64::1/64`) from ATE Port 1 with an AS-PATH containing the target peer's AS (`64497`) in the middle (e.g., AS-PATH: `64496 64497 64499`).
45+
3. Verify that the DUT **does not advertise** the route to ATE Port 2.
46+
4. Verify that ATE Port 2 **does not receive** the route.
47+
48+
### RT-1.71.2: Test `disable-peer-as-filter = TRUE` (Transit AS)
49+
50+
1. Enable `disable-peer-as-filter` on the DUT's neighbor/peer-group configuration towards ATE Port 2 (AS 64497).
51+
2. Re-advertise the prefixes from ATE Port 1 with the same AS-PATH (`64496 64497 64499`).
52+
3. Verify that the DUT **advertises** the route to ATE Port 2.
53+
4. Verify that ATE Port 2 **receives** the route.
54+
5. Validate for both IPv4 and IPv6 families.
55+
56+
### RT-1.71.3: Test "Originating Peer AS"
57+
58+
1. Ensure `disable-peer-as-filter` is enabled on the DUT's neighbor configuration towards ATE Port 2.
59+
2. Advertise a prefix from ATE Port 1 with an AS-PATH where the target peer's AS (`64497`) is the **originating AS** (e.g., AS-PATH: `64496 64499 64497`).
60+
3. Verify that the DUT **advertises** the route to ATE Port 2.
61+
4. Verify that ATE Port 2 **receives** the route.
62+
5. Validate session state and capabilities received on DUT using telemetry.
63+
64+
65+
### RT-1.71.4: Private AS Number Scenario
66+
67+
```mermaid
68+
graph LR
69+
subgraph ATE ["ATE"]
70+
direction TB
71+
ATE1["Port 1<br/>(AS 64496)"]
72+
ATE2["Port 2<br/>(AS 64512)"]
73+
end
74+
75+
subgraph DUT_Domain ["DUT"]
76+
DUT["DUT<br/>(AS 64498)"]
77+
end
78+
79+
%% Advertisement Flow for RT-1.71.4
80+
ATE1 -- "Advertise Prefix<br/>(AS-PATH: 64496 64499 64512)" --> DUT
81+
DUT -- "Propagate to Peer with<br/>AS 64512 in PATH" --> ATE2
82+
```
83+
84+
1. Configure **ATE Port 2** with a private AS number (e.g., `64512`).
85+
2. Configure the **DUT** (AS `64498`) with `disable-peer-as-filter = TRUE` on the neighbor configuration towards ATE Port 2.
86+
3. Advertise a prefix from **ATE Port 1** with an AS-PATH that includes ATE Port 2's AS (e.g., AS-PATH: `64496 64499 64512`).
87+
4. Verify that the DUT **advertises** the route to ATE Port 2 (AS 64512).
88+
5. Verify that ATE Port 2 **receives** the route.
89+
90+
### RT-1.71.5: Test "Peer-group and Neighbor level"
91+
92+
Ensure the tests are performed for BGP configuration at the Peer-group as well as at the Neighbor levels
93+
94+
## Canonical OC
95+
96+
```json
97+
{
98+
"network-instances": {
99+
"network-instance": [
100+
{
101+
"name": "DEFAULT",
102+
"config": {
103+
"name": "DEFAULT"
104+
},
105+
"protocols": {
106+
"protocol": [
107+
{
108+
"identifier": "BGP",
109+
"name": "BGP",
110+
"config": {
111+
"identifier": "BGP",
112+
"name": "BGP"
113+
},
114+
"bgp": {
115+
"peer-groups": {
116+
"peer-group": [
117+
{
118+
"peer-group-name": "BGP-PEER-GROUP1",
119+
"config": {
120+
"peer-group-name": "BGP-PEER-GROUP1"
121+
},
122+
"as-path-options": {
123+
"config": {
124+
"disable-peer-as-filter": true
125+
}
126+
}
127+
}
128+
]
129+
}
130+
}
131+
}
132+
]
133+
}
134+
}
135+
]
136+
}
137+
}
138+
```
139+
140+
## OpenConfig Path and RPC Coverage
141+
142+
```yaml
143+
paths:
144+
## Config paths
145+
/network-instances/network-instance/protocols/protocol/bgp/peer-groups/peer-group/as-path-options/config/disable-peer-as-filter:
146+
/network-instances/network-instance/protocols/protocol/bgp/neighbors/neighbor/as-path-options/config/disable-peer-as-filter:
147+
148+
## State paths
149+
/network-instances/network-instance/protocols/protocol/bgp/peer-groups/peer-group/as-path-options/state/disable-peer-as-filter:
150+
/network-instances/network-instance/protocols/protocol/bgp/neighbors/neighbor/as-path-options/state/disable-peer-as-filter:
151+
/network-instances/network-instance/protocols/protocol/bgp/neighbors/neighbor/state/session-state:
152+
153+
rpcs:
154+
gnmi:
155+
gNMI.Set:
156+
union_replace: true
157+
gNMI.Subscribe:
158+
on_change: true
159+
```
160+
161+
## Required DUT platform
162+
163+
* vRX - virtual router device
164+
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# proto-file: github.com/openconfig/featureprofiles/proto/metadata.proto
2+
# proto-message: Metadata
3+
4+
uuid: "0a9bd744-53e0-4152-bb30-ef23d5c3fe78"
5+
plan_id: "RT-1.71"
6+
description: "BGP Disable Peer AS Filter (`disable-peer-as-filter`)"
7+
testbed: TESTBED_DUT_ATE_2LINKS

feature/bgp/otg_tests/bgp_remove_private_as/bgp_remove_private_as_test.go

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -140,9 +140,12 @@ func configureDUT(t *testing.T, dut *ondatra.DUTDevice) {
140140
func verifyPortsUp(t *testing.T, dev *ondatra.Device) {
141141
t.Helper()
142142
for _, p := range dev.Ports() {
143-
status := gnmi.Get(t, dev, gnmi.OC().Interface(p.Name()).OperStatus().State())
144-
if want := oc.Interface_OperStatus_UP; status != want {
145-
t.Errorf("%s Status: got %v, want %v", p, status, want)
143+
_, ok := gnmi.Watch(t, dev, gnmi.OC().Interface(p.Name()).OperStatus().State(), time.Minute, func(val *ygnmi.Value[oc.E_Interface_OperStatus]) bool {
144+
state, ok := val.Val()
145+
return ok && state == oc.Interface_OperStatus_UP
146+
}).Await(t)
147+
if !ok {
148+
t.Errorf("Interface not UP for port %s", p.Name())
146149
}
147150
}
148151
}
@@ -254,11 +257,19 @@ func verifyPrefixesTelemetry(t *testing.T, dut *ondatra.DUTDevice, nbr string, w
254257
t.Helper()
255258
statePath := gnmi.OC().NetworkInstance(deviations.DefaultNetworkInstance(dut)).Protocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_BGP, "BGP").Bgp()
256259
prefixesv4 := statePath.Neighbor(nbr).AfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV4_UNICAST).Prefixes()
257-
if gotInstalled := gnmi.Get(t, dut, prefixesv4.Installed().State()); gotInstalled != wantInstalled {
258-
t.Errorf("Installed prefixes mismatch on %v: got %v, want %v", nbr, gotInstalled, wantInstalled)
260+
_, ok := gnmi.Watch(t, dut, prefixesv4.Installed().State(), 2*time.Minute, func(val *ygnmi.Value[uint32]) bool {
261+
gotInstalled, ok := val.Val()
262+
return ok && gotInstalled == wantInstalled
263+
}).Await(t)
264+
if !ok {
265+
t.Errorf("Installed prefixes mismatch on %v, got %v, want %v", nbr, gnmi.Get(t, dut, prefixesv4.Installed().State()), wantInstalled)
259266
}
260-
if gotSent := gnmi.Get(t, dut, prefixesv4.Sent().State()); gotSent != wantSent {
261-
t.Errorf("Sent prefixes mismatch on %v: got %v, want %v", nbr, gotSent, wantSent)
267+
_, ok = gnmi.Watch(t, dut, prefixesv4.Sent().State(), 2*time.Minute, func(val *ygnmi.Value[uint32]) bool {
268+
gotSent, ok := val.Val()
269+
return ok && gotSent == wantSent
270+
}).Await(t)
271+
if !ok {
272+
t.Errorf("Sent prefixes mismatch on %v:, got %v, want %v", nbr, gnmi.Get(t, dut, prefixesv4.Sent().State()), wantSent)
262273
}
263274
}
264275

feature/bgp/policybase/otg_tests/link_bandwidth_test/link_bandwidth_test.go

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -277,11 +277,14 @@ func enableExtCommunityCLIConfig(t *testing.T, dut *ondatra.DUTDevice) {
277277
var extCommunityEnableCLIConfig string
278278
switch dut.Vendor() {
279279
case ondatra.CISCO:
280-
extCommunityEnableCLIConfig = fmt.Sprintf("router bgp %v instance BGP neighbor-group %v \n ebgp-recv-extcommunity-dmz \n ebgp-send-extcommunity-dmz\n", dutAS, cfgplugins.BGPPeerGroup1)
280+
extCommunityEnableCLIConfig = fmt.Sprintf("router bgp %v instance BGP neighbor %v \n ebgp-recv-extcommunity-dmz \n ebgp-send-extcommunity-dmz\n", dutAS, atePort1.IPv4)
281+
helpers.GnmiCLIConfig(t, dut, extCommunityEnableCLIConfig)
282+
time.Sleep(10 * time.Second)
283+
extCommunityEnableCLIConfig = fmt.Sprintf("router bgp %v instance BGP neighbor %v \n ebgp-recv-extcommunity-dmz \n ebgp-send-extcommunity-dmz\n", dutAS, atePort1.IPv6)
284+
helpers.GnmiCLIConfig(t, dut, extCommunityEnableCLIConfig)
281285
default:
282286
t.Fatalf("Unsupported vendor %s for deviation 'BgpExplicitExtendedCommunityEnable'", dut.Vendor())
283287
}
284-
helpers.GnmiCLIConfig(t, dut, extCommunityEnableCLIConfig)
285288
}
286289
}
287290

@@ -333,6 +336,9 @@ func applyExportPolicyDut(t *testing.T, dut *ondatra.DUTDevice, policyName strin
333336
root := &oc.Root{}
334337
dni := deviations.DefaultNetworkInstance(dut)
335338
removeImportAndExportPolicy(t, dut)
339+
if deviations.ExplicitlyApplyAllowAllImportPolicy(dut) {
340+
applyImportPolicyDut(t, dut, "allow-all")
341+
}
336342

337343
// Apply ipv4 policy to bgp neighbour.
338344
path := gnmi.OC().NetworkInstance(dni).Protocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_BGP, bgpName).Bgp().Neighbor(atePort2.IPv4).AfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV4_UNICAST).ApplyPolicy()
@@ -361,7 +367,7 @@ func applyExportPolicyDut(t *testing.T, dut *ondatra.DUTDevice, policyName strin
361367
func validateImportPolicyDut(t *testing.T, dut *ondatra.DUTDevice, td testData, policyName string) {
362368
dni := deviations.DefaultNetworkInstance(dut)
363369
path := gnmi.OC().NetworkInstance(dni).Protocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_BGP, bgpName).Bgp().Neighbor(atePort1.IPv4).AfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV4_UNICAST).ApplyPolicy()
364-
_, ok := gnmi.Watch(t, dut, path.State(), 30*time.Second, func(v *ygnmi.Value[*oc.NetworkInstance_Protocol_Bgp_Neighbor_AfiSafi_ApplyPolicy]) bool {
370+
_, ok := gnmi.Watch(t, dut, path.State(), 2*time.Minute, func(v *ygnmi.Value[*oc.NetworkInstance_Protocol_Bgp_Neighbor_AfiSafi_ApplyPolicy]) bool {
365371
value, ok := v.Val()
366372
if !ok {
367373
return false
@@ -817,7 +823,20 @@ func configureExtCommunityRoutingPolicy(t *testing.T, dut *ondatra.DUTDevice) {
817823
case ondatra.CISCO:
818824
var communityCLIConfig string
819825
communityCLIConfig = fmt.Sprintf("community-set %v\n dfa-regex '%v', \n match invert \n end-set", "regex_match_comm100", communitySet["regex_match_comm100"])
820-
policySetCLIConfig := fmt.Sprintf("route-policy %v \n #statement-1 1-megabit-match \n if community is-empty then \n pass \n elseif community in %v then \n set extcommunity bandwidth %v \n endif \n pass \n #statement-2 accept_all_routes \n done \n end-policy", "not_match_100_set_linkbw_1M", "regex_match_comm100", "linkbw_1M")
826+
policySetCLIConfig := fmt.Sprintf(
827+
"route-policy %v \n"+
828+
" #statement-1 1-megabit-match \n"+
829+
" if community in %v then \n"+
830+
" set extcommunity bandwidth %v \n"+
831+
" endif \n"+
832+
" pass \n"+
833+
" #statement-2 accept_all_routes \n"+
834+
" done \n"+
835+
"end-policy",
836+
"not_match_100_set_linkbw_1M",
837+
"regex_match_comm100",
838+
"linkbw_1M",
839+
)
821840
helpers.GnmiCLIConfig(t, dut, communityCLIConfig)
822841
helpers.GnmiCLIConfig(t, dut, policySetCLIConfig)
823842
default:

0 commit comments

Comments
 (0)