Skip to content

Adding test for AFT-6.2#5523

Open
Steubert wants to merge 1 commit into
openconfig:mainfrom
open-traffic-generator:FPT_OTG_AFT-6.2
Open

Adding test for AFT-6.2#5523
Steubert wants to merge 1 commit into
openconfig:mainfrom
open-traffic-generator:FPT_OTG_AFT-6.2

Conversation

@Steubert Steubert requested review from a team as code owners May 29, 2026 14:18
@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces a new test case for AFT-6.2, focusing on dual-stack prefix filtering within the AFT (Abstract Forwarding Table). It includes the necessary test logic to configure routing policies, static routes, and verify filtering outcomes. Additionally, it adds infrastructure support for platform-specific deviations, allowing the test to run on hardware that requires CLI-based configuration for global filter policies instead of standard gNMI/OpenConfig paths.

Highlights

  • New Test Implementation: Added a new test suite to validate AFT-6.2: AFT Prefix Filtering Dual-Stack, ensuring correct filtering behavior for both IPv4 and IPv6 prefixes.
  • Infrastructure Support: Introduced a new deviation 'afts_global_filter_policy_oc_unsupported' to handle platforms (like Arista) that do not support the standard OpenConfig path for AFT global filter policies.
  • Policy Swap Validation: Implemented verification for cross-family policy swap behavior, ensuring that prefix filtering updates are correctly applied and reflected in the AFT state.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize the Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counterproductive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request implements the AFT Prefix Filtering Dual-Stack test (AFT-6.2), adding a new test file, metadata, and a deviation for Arista devices where the AFT global filter policy OC path is unsupported. The feedback recommends replacing t.Context() with context.Background() for Go compatibility, verifying IPv6 prefixes directly from the streamed prefixes rather than querying the DUT state, optimizing the state polling loop using gnmiC.Get instead of repeated ONCE subscriptions, and reusing existing sessions to verify prefix deletion. Additionally, the deviation comment should be updated to fix a path typo and include the required issue tracker URL tracking its removal.

*aftcache.AFTStreamSession, *aftcache.AFTStreamSession, aftcache.PeriodicHook,
) {
t.Helper()
ctx := t.Context()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

t.Context() was introduced in Go 1.24. Since the repository may be compiled in environments running older Go versions (such as Go 1.22 or 1.23), using t.Context() will cause compilation failures. Use context.Background() or pass a context to ensure compatibility.

Suggested change
ctx := t.Context()
ctx := context.Background()

// mustRunAFTSessions runs both sessions concurrently and returns the converged AFTData from session1.
func mustRunAFTSessions(t *testing.T, cfg aftSessionConfig) *aftcache.AFTData {
t.Helper()
ctx := t.Context()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

t.Context() was introduced in Go 1.24. Since the repository may be compiled in environments running older Go versions (such as Go 1.22 or 1.23), using t.Context() will cause compilation failures. Use context.Background() or pass a context to ensure compatibility.

Suggested change
ctx := t.Context()
ctx := context.Background()

Comment on lines +506 to +518
// Verify IPv6 prefixes exist in AFT state.
t.Log("Step 4: Verifying IPv6 entries present in AFT state")
niAfts := gnmi.OC().NetworkInstance(deviations.DefaultNetworkInstance(dut)).Afts()
for _, pfx := range ipv6MatchPrefixes {
_, ok := gnmi.Watch(t, dut, niAfts.Ipv6Entry(pfx).State(), operationTimeout,
func(v *ygnmi.Value[*oc.NetworkInstance_Afts_Ipv6Entry]) bool {
entry, present := v.Val()
return present && entry != nil
}).Await(t)
if !ok {
t.Errorf("ipv6 prefix %s not found in AFT state", pfx)
}
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The test is designed to validate dual-stack AFT prefix filtering over the streamed gNMI ON_CHANGE subscription. However, in Step 4, the IPv6 prefixes are verified by querying the DUT's state directly using gnmi.Watch instead of verifying them from the streamed aft.Prefixes (as done for IPv4 in Step 3). This bypasses the streaming validation for IPv6. Verify the IPv6 prefixes from the streamed aft.Prefixes to ensure the streaming filter works correctly for both address families.

	// Verify IPv6 prefixes matched by POLICY-PREFIX-SET-B.
	t.Log("Step 4: Verifying IPv6 entries match POLICY-PREFIX-SET-B")
	for _, pfx := range ipv6MatchPrefixes {
		if _, ok := aft.Prefixes[pfx]; !ok {
			t.Errorf("ipv6 prefix %s expected in AFT stream but not received", pfx)
		}
	}

Comment on lines +375 to +408
for time.Now().Before(deadline) {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
stream, err := gnmiC.Subscribe(ctx)
if err != nil {
cancel()
time.Sleep(pollInterval)
continue
}
err = stream.Send(&gpb.SubscribeRequest{
Request: &gpb.SubscribeRequest_Subscribe{
Subscribe: &gpb.SubscriptionList{
Mode: gpb.SubscriptionList_ONCE,
Subscription: []*gpb.Subscription{{Path: statePath}},
},
},
})
if err != nil {
cancel()
time.Sleep(pollInterval)
continue
}
resp, err := stream.Recv()
cancel()
if err != nil {
time.Sleep(pollInterval)
continue
}
for _, u := range resp.GetUpdate().GetUpdate() {
if u.GetVal().GetStringVal() == wantVal {
t.Logf("global-filter state/%s = %q confirmed", leaf, wantVal)
return nil
}
}
time.Sleep(pollInterval)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using gnmiC.Subscribe with ONCE mode inside a manual polling loop is highly inefficient as it repeatedly establishes and tears down gNMI subscription streams. Instead, use gnmiC.Get to retrieve the state value directly in each iteration of the loop.

	for time.Now().Before(deadline) {
		ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
		resp, err := gnmiC.Get(ctx, &gpb.GetRequest{
			Path: []*gpb.Path{statePath},
			Type: gpb.GetRequest_STATE,
		})
		cancel()
		if err != nil {
			time.Sleep(pollInterval)
			continue
		}
		for _, n := range resp.GetNotification() {
			for _, u := range n.GetUpdate() {
				if u.GetVal().GetStringVal() == wantVal {
					t.Logf("global-filter state/%s = %q confirmed", leaf, wantVal)
					return nil
				}
			}
		}
		time.Sleep(pollInterval)
	}

Comment on lines +540 to +543
// Open a new subscription and verify matched prefixes are removed.
t.Log("Step 7: Opening AFT subscription with swapped policy")
session1Swapped, session2Swapped, stoppingCondSwapped := mustOpenAFTSessions(t, dut, map[string]bool{})
aftSwapped := mustRunAFTSessions(t, aftSessionConfig{session1: session1Swapped, session2: session2Swapped, stop: stoppingCondSwapped, dut: dut})
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Opening a new gNMI subscription to verify that prefixes are removed is inefficient and adds unnecessary overhead. Since the existing sessions (session1 and session2) are ON_CHANGE subscriptions, they will automatically receive delete notifications when the policy is swapped. You can reuse the existing sessions and use aftcache.DeletionStoppingCondition to verify that the prefixes are deleted. This is faster, more efficient, and directly validates the deletion streaming behavior of the existing subscription.

Suggested change
// Open a new subscription and verify matched prefixes are removed.
t.Log("Step 7: Opening AFT subscription with swapped policy")
session1Swapped, session2Swapped, stoppingCondSwapped := mustOpenAFTSessions(t, dut, map[string]bool{})
aftSwapped := mustRunAFTSessions(t, aftSessionConfig{session1: session1Swapped, session2: session2Swapped, stop: stoppingCondSwapped, dut: dut})
// Verify prefixes are deleted from the existing AFT stream.
t.Log("Step 7: Verifying prefixes are deleted from the existing AFT stream")
stopDelete := aftcache.DeletionStoppingCondition(t, dut, wantPrefixes)
aftSwapped := mustRunAFTSessions(t, aftSessionConfig{session1: session1, session2: session2, stop: stopDelete, dut: dut})

Comment on lines +2230 to +2231
// AftsGlobalFilterPolicyOCUnsupported returns true if "/network-instances/network-instance/afts/global-filter-policy" OC path is not supported.
func AftsGlobalFilterPolicyOCUnsupported(dut *ondatra.DUTDevice) bool {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The comment for the deviation accessor function AftsGlobalFilterPolicyOCUnsupported is missing the required issue tracker URL tracking its removal, which violates the Repository Style Guide (Deviation Guidelines). Additionally, the path in the comment contains a typo: /network-instances/network-instance/afts/global-filter-policy should be /network-instances/network-instance/afts/global-filter. Please use the standard issue tracker URL format: https://issuetracker.google.com/xxxxx.

Suggested change
// AftsGlobalFilterPolicyOCUnsupported returns true if "/network-instances/network-instance/afts/global-filter-policy" OC path is not supported.
func AftsGlobalFilterPolicyOCUnsupported(dut *ondatra.DUTDevice) bool {
// AftsGlobalFilterPolicyOCUnsupported returns true if "/network-instances/network-instance/afts/global-filter" OC path is not supported.
// Tracked at: https://issuetracker.google.com/514565554
func AftsGlobalFilterPolicyOCUnsupported(dut *ondatra.DUTDevice) bool {
References
  1. Deviation accessor functions must have a comment containing a URL link to an issue tracker tracking its removal. (link)
  2. Issue tracker URLs in deviation comments are acceptable in the format 'https://issuetracker.google.com/xxxxx' (omitting the '/issues/' segment), provided they are validated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants