diff --git a/feature/bgp/policybase/otg_tests/import_export_multi_test/metadata.textproto b/feature/bgp/policybase/otg_tests/import_export_multi_test/metadata.textproto index 64ea71ae4e6..ec09b76414c 100644 --- a/feature/bgp/policybase/otg_tests/import_export_multi_test/metadata.textproto +++ b/feature/bgp/policybase/otg_tests/import_export_multi_test/metadata.textproto @@ -19,7 +19,6 @@ platform_exceptions: { skip_set_rp_match_set_options: true bgp_community_set_refs_unsupported: true bgp_conditions_match_community_set_unsupported: true - skip_prefix_set_mode: true bgp_community_member_is_a_string: true skip_bgp_send_community_type: true } diff --git a/feature/container/containerz/tests/container_lifecycle/containerz_test.go b/feature/container/containerz/tests/container_lifecycle/containerz_test.go index f7be52e16b7..4d14062b228 100644 --- a/feature/container/containerz/tests/container_lifecycle/containerz_test.go +++ b/feature/container/containerz/tests/container_lifecycle/containerz_test.go @@ -1,4 +1,4 @@ -package container_lifecycle +package container_lifecycle_test import ( "context" diff --git a/feature/experimental/bgp/ate_tests/bgp_long_lived_graceful_restart/bgp_long_lived_graceful_restart_test.go b/feature/experimental/bgp/ate_tests/bgp_long_lived_graceful_restart/bgp_long_lived_graceful_restart_test.go index bdbb469bdc1..0c7f1460f0d 100644 --- a/feature/experimental/bgp/ate_tests/bgp_long_lived_graceful_restart/bgp_long_lived_graceful_restart_test.go +++ b/feature/experimental/bgp/ate_tests/bgp_long_lived_graceful_restart/bgp_long_lived_graceful_restart_test.go @@ -23,14 +23,12 @@ import ( "github.com/openconfig/featureprofiles/internal/attrs" "github.com/openconfig/featureprofiles/internal/deviations" "github.com/openconfig/featureprofiles/internal/fptest" + "github.com/openconfig/featureprofiles/internal/gnoi" gpb "github.com/openconfig/gnmi/proto/gnmi" - gnps "github.com/openconfig/gnoi/system" - "github.com/openconfig/gnoigo/system" "github.com/openconfig/ondatra" "github.com/openconfig/ondatra/gnmi" "github.com/openconfig/ondatra/gnmi/oc" "github.com/openconfig/ondatra/gnmi/oc/acl" - "github.com/openconfig/ondatra/gnoi" "github.com/openconfig/ondatra/ixnet" "github.com/openconfig/ygnmi/ygnmi" "github.com/openconfig/ygot/ygot" @@ -192,12 +190,6 @@ var ( IPv4Len: plenIPv4, IPv6Len: plenIPv6, } - routingDaemon = map[ondatra.Vendor]string{ - ondatra.JUNIPER: "rpd", - ondatra.ARISTA: "Bgp-main", - ondatra.CISCO: "emsd", - ondatra.NOKIA: "sr_bgp_mgr", - } ) func configureRoutePolicy(t *testing.T, dut *ondatra.DUTDevice, name string, pr oc.E_RoutingPolicy_PolicyResultType) { @@ -652,56 +644,6 @@ func removeNewPeers(t *testing.T, dut *ondatra.DUTDevice, nbrs []*bgpNeighbor) { fptest.LogQuery(t, "DUT BGP Config", dutConfPath.Config(), gnmi.Get(t, dut, dutConfPath.Config())) } -func restartRoutingProcess(t *testing.T, dut *ondatra.DUTDevice) { - t.Helper() - if _, ok := routingDaemon[dut.Vendor()]; !ok { - t.Fatalf("Please add support for vendor %v in var routingDaemon", dut.Vendor()) - } - t.Run("KillGRIBIDaemon", func(t *testing.T) { - // Find the PID of routing Daemon. - var pId uint64 - pName := routingDaemon[dut.Vendor()] - t.Run("FindroutingDaemonPid", func(t *testing.T) { - pId = findProcessByName(t, dut, pName) - if pId == 0 { - t.Fatalf("Couldn't find pid of routing daemon '%s'", pName) - } else { - t.Logf("Pid of routing daemon '%s' is '%d'", pName, pId) - } - }) - - // Kill routing daemon through gNOI Kill Request. - t.Run("ExecuteGnoiKill", func(t *testing.T) { - // TODO - pid type is uint64 in oc-system model, but uint32 in gNOI Kill Request proto. - // Until the models are brought in line, typecasting the uint64 to uint32. - gNOIKillProcess(t, dut, pName, uint32(pId)) - // Wait for a bit for routing daemon on the DUT to restart. - time.Sleep(30 * time.Second) - }) - }) -} - -// findProcessByName uses telemetry to find out the PID of a process -func findProcessByName(t *testing.T, dut *ondatra.DUTDevice, pName string) uint64 { - t.Helper() - pList := gnmi.GetAll(t, dut, gnmi.OC().System().ProcessAny().State()) - var pID uint64 - for _, proc := range pList { - if proc.GetName() == pName { - pID = proc.GetPid() - t.Logf("Pid of daemon '%s' is '%d'", pName, pID) - } - } - return pID -} - -// gNOIKillProcess kills a daemon on the DUT, given its name and pid. -func gNOIKillProcess(t *testing.T, dut *ondatra.DUTDevice, pName string, pID uint32) { - t.Helper() - killResponse := gnoi.Execute(t, dut, system.NewKillProcessOperation().Name(pName).PID(pID).Signal(gnps.KillProcessRequest_SIGNAL_TERM).Restart(true)) - t.Logf("Got kill process response: %v\n\n", killResponse) -} - // setBgpPolicy is used to configure routing policy on DUT. func setBgpPolicy(t *testing.T, dut *ondatra.DUTDevice, d *oc.Root) { t.Helper() @@ -943,7 +885,7 @@ func TestTrafficWithGracefulRestartLLGR(t *testing.T) { }) t.Run("Restart routing", func(t *testing.T) { - restartRoutingProcess(t, dut) + gnoi.KillProcess(t, dut, gnoi.ROUTING, true) }) var bgpIxPeer []*ixnet.BGP diff --git a/feature/experimental/bgp/otg_tests/link_bandwidth_test/link_bandwidth_test.go b/feature/experimental/bgp/otg_tests/link_bandwidth_test/link_bandwidth_test.go index dcb0012b493..e240cd817d6 100644 --- a/feature/experimental/bgp/otg_tests/link_bandwidth_test/link_bandwidth_test.go +++ b/feature/experimental/bgp/otg_tests/link_bandwidth_test/link_bandwidth_test.go @@ -339,7 +339,7 @@ func validateRouteCommunityV4Prefix(t *testing.T, td testData, community, v4Pref t.Errorf("ERROR lb Bandwidth want :2G, got=%v", ygot.BinaryToFloat32(lbSubType.GetBandwidth())) } } - if deviations.BgpExtendedCommunityIndexUnsupported(td.dut) { + if !deviations.BgpExtendedCommunityIndexUnsupported(td.dut) { verifyExtCommunityIndexV4(t, td, v4Prefix) } } @@ -410,7 +410,7 @@ func validateRouteCommunityV6Prefix(t *testing.T, td testData, community, v6Pref t.Errorf("ERROR lb Bandwidth want :2G, got=%v", ygot.BinaryToFloat32(lbSubType.GetBandwidth())) } } - if deviations.BgpExtendedCommunityIndexUnsupported(td.dut) { + if !deviations.BgpExtendedCommunityIndexUnsupported(td.dut) { verifyExtCommunityIndexV6(t, td, v6Prefix) } } @@ -621,7 +621,7 @@ func configureExtCommunityRoutingPolicy(t *testing.T, dut *ondatra.DUTDevice) { case ondatra.CISCO: var communityCLIConfig string communityCLIConfig = fmt.Sprintf("community-set %v\n dfa-regex '%v', \n match invert \n end-set", "regex_match_comm100", CommunitySet["regex_match_comm100"]) - policySetCLIConfig := fmt.Sprintf("route-policy %v \n #statement-1 1-megabit-match \n if 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") + 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") helpers.GnmiCLIConfig(t, dut, communityCLIConfig) helpers.GnmiCLIConfig(t, dut, policySetCLIConfig) default: diff --git a/feature/experimental/gribi/otg_tests/dut_daemon_failure/README.md b/feature/experimental/gribi/otg_tests/dut_daemon_failure/README.md index a27b42da6d7..6cd0a79e2a2 100644 --- a/feature/experimental/gribi/otg_tests/dut_daemon_failure/README.md +++ b/feature/experimental/gribi/otg_tests/dut_daemon_failure/README.md @@ -29,11 +29,14 @@ Ensure that gRIBI entries are persisted over daemon failure. * Issuing a gRIBI Get RPC results in 203.0.113.0/24 being returned. -## Protocol/RPC Parameter Coverage - -* gRIBI - * ModifyRequest - * GetRequest +## OpenConfig Path and RPC Coverage +```yaml +rpcs: + gribi: + gRIBI.Get: + gRIBI.Modify: + gRIBI.Flush: +``` ## Telemetry Parameter Coverage diff --git a/feature/experimental/gribi/otg_tests/dut_daemon_failure/dut_daemon_failure_test.go b/feature/experimental/gribi/otg_tests/dut_daemon_failure/dut_daemon_failure_test.go index a07108c8c39..d0b63b30c00 100644 --- a/feature/experimental/gribi/otg_tests/dut_daemon_failure/dut_daemon_failure_test.go +++ b/feature/experimental/gribi/otg_tests/dut_daemon_failure/dut_daemon_failure_test.go @@ -23,16 +23,14 @@ import ( "github.com/openconfig/featureprofiles/internal/attrs" "github.com/openconfig/featureprofiles/internal/deviations" "github.com/openconfig/featureprofiles/internal/fptest" + "github.com/openconfig/featureprofiles/internal/gnoi" "github.com/openconfig/featureprofiles/internal/gribi" "github.com/openconfig/featureprofiles/internal/otgutils" - gnps "github.com/openconfig/gnoi/system" - "github.com/openconfig/gnoigo/system" - grps "github.com/openconfig/gribi/v1/proto/service" + grpb "github.com/openconfig/gribi/v1/proto/service" "github.com/openconfig/gribigo/fluent" "github.com/openconfig/ondatra" "github.com/openconfig/ondatra/gnmi" "github.com/openconfig/ondatra/gnmi/oc" - "github.com/openconfig/ondatra/gnoi" "github.com/openconfig/ygnmi/ygnmi" "github.com/openconfig/ygot/ygot" ) @@ -88,13 +86,6 @@ var ( IPv4: "192.0.2.6", IPv4Len: ipv4PrefixLen, } - - gRIBIDaemons = map[ondatra.Vendor]string{ - ondatra.ARISTA: "Gribi", - ondatra.CISCO: "emsd", - ondatra.JUNIPER: "rpd", - ondatra.NOKIA: "sr_grpc_server", - } ) // configInterfaceDUT configures the DUT interfaces. @@ -235,7 +226,7 @@ func verifyGRIBIGet(ctx context.Context, t *testing.T, clientA *gribi.Client, du entries := getResponse.GetEntry() var found bool for _, entry := range entries { - v := entry.Entry.(*grps.AFTEntry_Ipv4) + v := entry.Entry.(*grpb.AFTEntry_Ipv4) if prefix := v.Ipv4.GetPrefix(); prefix != "" { if prefix == ateDstNetCIDR { found = true @@ -249,36 +240,12 @@ func verifyGRIBIGet(ctx context.Context, t *testing.T, clientA *gribi.Client, du } } -// gNOIKillProcess kills a daemon on the DUT, given its name and pid. -func gNOIKillProcess(ctx context.Context, t *testing.T, args *testArgs, pName string, pID uint32) { - killResponse := gnoi.Execute(t, args.dut, system.NewKillProcessOperation().Name(pName).PID(pID).Signal(gnps.KillProcessRequest_SIGNAL_TERM).Restart(true)) - t.Logf("Got kill process response: %v\n\n", killResponse) -} - -// findProcessByName uses telemetry to find out the PID of a process -func findProcessByName(ctx context.Context, t *testing.T, dut *ondatra.DUTDevice, pName string) uint64 { - pList := gnmi.GetAll(t, dut, gnmi.OC().System().ProcessAny().State()) - var pID uint64 - for _, proc := range pList { - if proc.GetName() == pName { - pID = proc.GetPid() - t.Logf("Pid of daemon '%s' is '%d'", pName, pID) - } - } - return pID -} - func TestDUTDaemonFailure(t *testing.T) { start := time.Now() dut := ondatra.DUT(t, "dut") ctx := context.Background() - // Check if vendor specific gRIBI daemon name has been added to gRIBIDaemons var - if _, ok := gRIBIDaemons[dut.Vendor()]; !ok { - t.Fatalf("Please add support for vendor %v in var gRIBIDaemons", dut.Vendor()) - } - // Configure the DUT. t.Logf("Configure DUT") configureDUT(t, dut) @@ -343,30 +310,7 @@ func TestDUTDaemonFailure(t *testing.T) { }) t.Run("KillGRIBIDaemon", func(t *testing.T) { - - // Find the PID of gRIBI Daemon. - var pId uint64 - pName := gRIBIDaemons[dut.Vendor()] - t.Run("FindGRIBIDaemonPid", func(t *testing.T) { - - pId = findProcessByName(ctx, t, dut, pName) - if pId == 0 { - t.Fatalf("Couldn't find pid of gRIBI daemon '%s'", pName) - } else { - t.Logf("Pid of gRIBI daemon '%s' is '%d'", pName, pId) - } - }) - - // Kill gRIBI daemon through gNOI Kill Request. - t.Run("ExecuteGnoiKill", func(t *testing.T) { - // TODO - pid type is uint64 in oc-system model, but uint32 in gNOI Kill Request proto. - // Until the models are brought in line, typecasting the uint64 to uint32. - gNOIKillProcess(ctx, t, args, pName, uint32(pId)) - - // Wait for a bit for gRIBI daemon on the DUT to restart. - time.Sleep(30 * time.Second) - - }) + gnoi.KillProcess(t, dut, gnoi.GRIBI, true) t.Logf("Time check: %s", time.Since(start)) diff --git a/feature/experimental/isis/otg_tests/isis_interface_passive_test/README.md b/feature/experimental/isis/otg_tests/isis_interface_passive_test/README.md index ce29ac4d93c..cd87a3ba503 100644 --- a/feature/experimental/isis/otg_tests/isis_interface_passive_test/README.md +++ b/feature/experimental/isis/otg_tests/isis_interface_passive_test/README.md @@ -14,83 +14,78 @@ * Ensure that IS-IS adjacency is not coming up on the passive interface. * TODO-Verify the output of ST path displaying the interface as passive in ISIS database/adj table -## Config Parameter coverage +# OpenConfig Path and RPC Coverage +```yaml +paths: +# config +/network-instances/network-instance/protocols/protocol/isis/global/config/authentication-check: +/network-instances/network-instance/protocols/protocol/isis/global/config/net: +/network-instances/network-instance/protocols/protocol/isis/global/config/level-capability: +/network-instances/network-instance/protocols/protocol/isis/global/config/hello-padding: +/network-instances/network-instance/protocols/protocol/isis/global/afi-safi/af/config/enabled: +/network-instances/network-instance/protocols/protocol/isis/levels/level/config/level-number: +/network-instances/network-instance/protocols/protocol/isis/levels/level/config/enabled: +/network-instances/network-instance/protocols/protocol/isis/levels/level/authentication/config/enabled: +/network-instances/network-instance/protocols/protocol/isis/levels/level/authentication/config/auth-mode: +/network-instances/network-instance/protocols/protocol/isis/levels/level/authentication/config/auth-password: +/network-instances/network-instance/protocols/protocol/isis/levels/level/authentication/config/auth-type: +/network-instances/network-instance/protocols/protocol/isis/interfaces/interface/config/interface-id: +/network-instances/network-instance/protocols/protocol/isis/interfaces/interface/config/enabled: +/network-instances/network-instance/protocols/protocol/isis/interfaces/interface/config/circuit-type: +/network-instances/network-instance/protocols/protocol/isis/interfaces/interface/config/passive: +/network-instances/network-instance/protocols/protocol/isis/interfaces/interface/timers/config/csnp-interval: +/network-instances/network-instance/protocols/protocol/isis/interfaces/interface/timers/config/lsp-pacing-interval: +/network-instances/network-instance/protocols/protocol/isis/interfaces/interface/levels/level/config/level-number: +/network-instances/network-instance/protocols/protocol/isis/interfaces/interface/levels/level/config/passive: +/network-instances/network-instance/protocols/protocol/isis/interfaces/interface/levels/level/timers/config/hello-interval: +/network-instances/network-instance/protocols/protocol/isis/interfaces/interface/levels/level/timers/config/hello-multiplier: +/network-instances/network-instance/protocols/protocol/isis/interfaces/interface/levels/level/hello-authentication/config/auth-mode: +/network-instances/network-instance/protocols/protocol/isis/interfaces/interface/levels/level/hello-authentication/config/auth-password: +/network-instances/network-instance/protocols/protocol/isis/interfaces/interface/levels/level/hello-authentication/config/auth-type: +/network-instances/network-instance/protocols/protocol/isis/interfaces/interface/levels/level/hello-authentication/config/enabled: +/network-instances/network-instance/protocols/protocol/isis/interfaces/interface/afi-safi/af/config/afi-name: +/network-instances/network-instance/protocols/protocol/isis/interfaces/interface/afi-safi/af/config/safi-name: +/network-instances/network-instance/protocols/protocol/isis/interfaces/interface/afi-safi/af/config/enabled: -* For prefix: +# isis telemetry +/network-instances/network-instance/protocols/protocol/isis/interfaces/interface/state/passive: +/network-instances/network-instance/protocols/protocol/isis/interfaces/interface/levels/level/state/passive: +/network-instances/network-instance/protocols/protocol/isis/interfaces/interface/levels/level/adjacencies/adjacency/state/adjacency-state: +/network-instances/network-instance/protocols/protocol/isis/interfaces/interface/levels/level/adjacencies/adjacency/state/neighbor-ipv4-address: +/network-instances/network-instance/protocols/protocol/isis/interfaces/interface/levels/level/adjacencies/adjacency/state/neighbor-ipv6-address: +/network-instances/network-instance/protocols/protocol/isis/interfaces/interface/levels/level/adjacencies/adjacency/state/system-id: +/network-instances/network-instance/protocols/protocol/isis/interfaces/interface/levels/level/adjacencies/adjacency/state/area-address: +/network-instances/network-instance/protocols/protocol/isis/interfaces/interface/levels/level/adjacencies/adjacency/state/dis-system-id: +/network-instances/network-instance/protocols/protocol/isis/interfaces/interface/levels/level/adjacencies/adjacency/state/local-extended-circuit-id: +/network-instances/network-instance/protocols/protocol/isis/interfaces/interface/levels/level/adjacencies/adjacency/state/multi-topology: +/network-instances/network-instance/protocols/protocol/isis/interfaces/interface/levels/level/adjacencies/adjacency/state/neighbor-circuit-type: +/network-instances/network-instance/protocols/protocol/isis/interfaces/interface/levels/level/adjacencies/adjacency/state/neighbor-extended-circuit-id: +/network-instances/network-instance/protocols/protocol/isis/interfaces/interface/levels/level/adjacencies/adjacency/state/neighbor-snpa: +/network-instances/network-instance/protocols/protocol/isis/interfaces/interface/levels/level/adjacencies/adjacency/state/nlpid: +/network-instances/network-instance/protocols/protocol/isis/interfaces/interface/levels/level/adjacencies/adjacency/state/priority: +/network-instances/network-instance/protocols/protocol/isis/interfaces/interface/levels/level/adjacencies/adjacency/state/restart-status: +/network-instances/network-instance/protocols/protocol/isis/interfaces/interface/levels/level/adjacencies/adjacency/state/restart-support: +/network-instances/network-instance/protocols/protocol/isis/interfaces/interface/levels/level/adjacencies/adjacency/state/restart-suppress: +/network-instances/network-instance/protocols/protocol/isis/interfaces/interface/levels/level/afi-safi/af/state/afi-name: +/network-instances/network-instance/protocols/protocol/isis/interfaces/interface/levels/level/afi-safi/af/state/metric: +/network-instances/network-instance/protocols/protocol/isis/interfaces/interface/levels/level/afi-safi/af/state/safi-name: +/network-instances/network-instance/protocols/protocol/isis/levels/level/system-level-counters/state/auth-fails: +/network-instances/network-instance/protocols/protocol/isis/levels/level/system-level-counters/state/auth-type-fails: +/network-instances/network-instance/protocols/protocol/isis/levels/level/system-level-counters/state/corrupted-lsps: +/network-instances/network-instance/protocols/protocol/isis/levels/level/system-level-counters/state/database-overloads: +/network-instances/network-instance/protocols/protocol/isis/levels/level/system-level-counters/state/exceed-max-seq-nums: +/network-instances/network-instance/protocols/protocol/isis/levels/level/system-level-counters/state/id-len-mismatch: +/network-instances/network-instance/protocols/protocol/isis/levels/level/system-level-counters/state/lsp-errors: +/network-instances/network-instance/protocols/protocol/isis/levels/level/system-level-counters/state/manual-address-drop-from-area : +/network-instances/network-instance/protocols/protocol/isis/levels/level/system-level-counters/state/max-area-address-mismatches: +/network-instances/network-instance/protocols/protocol/isis/levels/level/system-level-counters/state/own-lsp-purges: +/network-instances/network-instance/protocols/protocol/isis/levels/level/system-level-counters/state/part-changes : +/network-instances/network-instance/protocols/protocol/isis/levels/level/system-level-counters/state/seq-num-skips: +/network-instances/network-instance/protocols/protocol/isis/levels/level/system-level-counters/state/spf-runs: - * /network-instances/network-instance/protocols/protocol/isis/ - -* Parameters: - - * global/config/authentication-check - * global/config/net - * global/config/level-capability - * global/config/hello-padding - * global/afi-safi/af/config/enabled - * levels/level/config/level-number - * levels/level/config/enabled - * levels/level/authentication/config/enabled - * levels/level/authentication/config/auth-mode - * levels/level/authentication/config/auth-password - * levels/level/authentication/config/auth-type - * interfaces/interface/config/interface-id - * interfaces/interface/config/enabled - * interfaces/interface/config/circuit-type - * interfaces/interface/config/passive - * interfaces/interface/timers/config/csnp-interval - * interfaces/interface/timers/config/lsp-pacing-interval - * interfaces/interface/levels/level/config/level-number - * interfaces/interface/levels/level/config/passive - * interfaces/interface/levels/level/timers/config/hello-interval - * interfaces/interface/levels/level/timers/config/hello-multiplier - * interfaces/interface/levels/level/hello-authentication/config/auth-mode - * interfaces/interface/levels/level/hello-authentication/config/auth-password - * interfaces/interface/levels/level/hello-authentication/config/auth-type - * interfaces/interface/levels/level/hello-authentication/config/enabled - * interfaces/interface/afi-safi/af/config/afi-name - * interfaces/interface/afi-safi/af/config/safi-name - * interfaces/interface/afi-safi/af/config/enabled - -## Telemetry Parameter coverage - -* For prefix: - - * /network-instances/network-instance/protocols/protocol/isis/ - -* Parameters: - - * interfaces/interface/state/passive - * interfaces/interface/levels/level/state/passive - * interfaces/interface/levels/level/adjacencies/adjacency/state/adjacency-state - * interfaces/interface/levels/level/adjacencies/adjacency/state/neighbor-ipv4-address - * interfaces/interface/levels/level/adjacencies/adjacency/state/neighbor-ipv6-address - * interfaces/interface/levels/level/adjacencies/adjacency/state/system-id - * interfaces/interface/levels/level/adjacencies/adjacency/state/area-address - * interfaces/interface/levels/level/adjacencies/adjacency/state/dis-system-id - * interfaces/interface/levels/level/adjacencies/adjacency/state/local-extended-circuit-id - * interfaces/interface/levels/level/adjacencies/adjacency/state/multi-topology - * interfaces/interface/levels/level/adjacencies/adjacency/state/neighbor-circuit-type - * interfaces/interface/levels/level/adjacencies/adjacency/state/neighbor-extended-circuit-id - * interfaces/interface/levels/level/adjacencies/adjacency/state/neighbor-snpa - * interfaces/interface/levels/level/adjacencies/adjacency/state/nlpid - * interfaces/interface/levels/level/adjacencies/adjacency/state/priority - * interfaces/interface/levels/level/adjacencies/adjacency/state/restart-status - * interfaces/interface/levels/level/adjacencies/adjacency/state/restart-support - * interfaces/interface/levels/level/adjacencies/adjacency/state/restart-suppress - * interfaces/interface/levels/level/afi-safi/af/state/afi-name - * interfaces/interface/levels/level/afi-safi/af/state/metric - * interfaces/interface/levels/level/afi-safi/af/state/safi-name - * interfaces/interface/levels/level/afi-safi/af/state/metric - * levels/level/system-level-counters/state/auth-fails - * levels/level/system-level-counters/state/auth-type-fails - * levels/level/system-level-counters/state/corrupted-lsps - * levels/level/system-level-counters/state/database-overloads - * levels/level/system-level-counters/state/exceed-max-seq-nums - * levels/level/system-level-counters/state/id-len-mismatch - * levels/level/system-level-counters/state/lsp-errors - * levels/level/system-level-counters/state/manual-address-drop-from-area - * levels/level/system-level-counters/state/max-area-address-mismatches - * levels/level/system-level-counters/state/own-lsp-purges - * levels/level/system-level-counters/state/part-changes - * levels/level/system-level-counters/state/seq-num-skips - * levels/level/system-level-counters/state/spf-runs +rpcs: + gnmi: + gNMI.Get: + gNMI.Set: + gNMI.Subscribe: +``` diff --git a/feature/experimental/isis/otg_tests/isis_interface_passive_test/isis_interface_passive_test.go b/feature/experimental/isis/otg_tests/isis_interface_passive_test/isis_interface_passive_test.go index 48200bfbf3b..725c6fab80a 100644 --- a/feature/experimental/isis/otg_tests/isis_interface_passive_test/isis_interface_passive_test.go +++ b/feature/experimental/isis/otg_tests/isis_interface_passive_test/isis_interface_passive_test.go @@ -58,6 +58,9 @@ func configureISIS(t *testing.T, ts *isissession.TestSession) { globalIsis.GetOrCreateAf(oc.IsisTypes_AFI_TYPE_IPV6, oc.IsisTypes_SAFI_TYPE_UNICAST).Enabled = ygot.Bool(true) globalIsis.LevelCapability = oc.Isis_LevelType_LEVEL_2 globalIsis.AuthenticationCheck = ygot.Bool(true) + if deviations.ISISGlobalAuthenticationNotRequired(ts.DUT) { + globalIsis.AuthenticationCheck = nil + } globalIsis.HelloPadding = oc.Isis_HelloPaddingType_ADAPTIVE // Level configs. @@ -69,6 +72,11 @@ func configureISIS(t *testing.T, ts *isissession.TestSession) { auth.AuthMode = oc.IsisTypes_AUTH_MODE_MD5 auth.AuthType = oc.KeychainTypes_AUTH_TYPE_SIMPLE_KEY auth.AuthPassword = ygot.String(password) + if deviations.ISISExplicitLevelAuthenticationConfig(ts.DUT) { + auth.DisableCsnp = ygot.Bool(false) + auth.DisableLsp = ygot.Bool(false) + auth.DisablePsnp = ygot.Bool(false) + } // Interface configs. intfName := ts.DUTPort1.Name() @@ -188,16 +196,20 @@ func TestIsisInterfacePassive(t *testing.T) { t.Errorf("FAIL- Expected area address not found, got %s, want %s", got, want) } // Checking dis system id. - if got := gnmi.Get(t, ts.DUT, adjPath.DisSystemId().State()); got != "0000.0000.0000" { - t.Errorf("FAIL- Expected dis system id not found, got %s, want %s", got, "0000.0000.0000") + if !deviations.MissingValueForDefaults(ts.DUT) { + if got := gnmi.Get(t, ts.DUT, adjPath.DisSystemId().State()); got != "0000.0000.0000" { + t.Errorf("FAIL- Expected dis system id not found, got %s, want %s", got, "0000.0000.0000") + } } // Checking isis local extended circuit id. if got := gnmi.Get(t, ts.DUT, adjPath.LocalExtendedCircuitId().State()); got == 0 { t.Errorf("FAIL- Expected local extended circuit id not found,expected non-zero value, got %d", got) } // Checking multitopology. - if got := gnmi.Get(t, ts.DUT, adjPath.MultiTopology().State()); got != false { - t.Errorf("FAIL- Expected value for multi topology not found, got %t, want %t", got, false) + if !deviations.MissingValueForDefaults(ts.DUT) { + if got := gnmi.Get(t, ts.DUT, adjPath.MultiTopology().State()); got != false { + t.Errorf("FAIL- Expected value for multi topology not found, got %t, want %t", got, false) + } } // Checking neighbor circuit type. if got := gnmi.Get(t, ts.DUT, adjPath.NeighborCircuitType().State()); got != oc.Isis_LevelType_LEVEL_2 { @@ -240,59 +252,81 @@ func TestIsisInterfacePassive(t *testing.T) { t.Errorf("FAIL- Restart support not present") } // Checking isis restart suppress. - if _, ok := gnmi.Lookup(t, ts.DUT, adjPath.RestartStatus().State()).Val(); !ok { - t.Errorf("FAIL- Restart suppress not present") + if !deviations.MissingValueForDefaults(ts.DUT) { + if _, ok := gnmi.Lookup(t, ts.DUT, adjPath.RestartStatus().State()).Val(); !ok { + t.Errorf("FAIL- Restart suppress not present") + } } }) t.Run("System level counter checks", func(t *testing.T) { // Checking authFail counters. - if got := gnmi.Get(t, ts.DUT, statePath.Level(2).SystemLevelCounters().AuthFails().State()); got != 0 { - t.Errorf("FAIL- Not expecting any authentication key failure, got %d, want %d", got, 0) + if !deviations.MissingValueForDefaults(ts.DUT) { + if got := gnmi.Get(t, ts.DUT, statePath.Level(2).SystemLevelCounters().AuthFails().State()); got != 0 { + t.Errorf("FAIL- Not expecting any authentication key failure, got %d, want %d", got, 0) + } } // Checking authTypeFail counters. - if got := gnmi.Get(t, ts.DUT, statePath.Level(2).SystemLevelCounters().AuthTypeFails().State()); got != 0 { - t.Errorf("FAIL- Not expecting any authentication type mismatches, got %d, want %d", got, 0) + if !deviations.MissingValueForDefaults(ts.DUT) { + if got := gnmi.Get(t, ts.DUT, statePath.Level(2).SystemLevelCounters().AuthTypeFails().State()); got != 0 { + t.Errorf("FAIL- Not expecting any authentication type mismatches, got %d, want %d", got, 0) + } } // Checking corrupted lsps counters. - if got := gnmi.Get(t, ts.DUT, statePath.Level(2).SystemLevelCounters().CorruptedLsps().State()); got != 0 { - t.Errorf("FAIL- Not expecting any corrupted lsps, got %d, want %d", got, 0) + if !deviations.MissingValueForDefaults(ts.DUT) { + if got := gnmi.Get(t, ts.DUT, statePath.Level(2).SystemLevelCounters().CorruptedLsps().State()); got != 0 { + t.Errorf("FAIL- Not expecting any corrupted lsps, got %d, want %d", got, 0) + } } // Checking database_overloads counters. - if got := gnmi.Get(t, ts.DUT, statePath.Level(2).SystemLevelCounters().DatabaseOverloads().State()); got != 0 { - t.Errorf("FAIL- Not expecting non zero database_overloads, got %d, want %d", got, 0) + if !deviations.MissingValueForDefaults(ts.DUT) { + if got := gnmi.Get(t, ts.DUT, statePath.Level(2).SystemLevelCounters().DatabaseOverloads().State()); got != 0 { + t.Errorf("FAIL- Not expecting non zero database_overloads, got %d, want %d", got, 0) + } } // Checking execeeded maximum seq number counters"). - if got := gnmi.Get(t, ts.DUT, statePath.Level(2).SystemLevelCounters().ExceedMaxSeqNums().State()); got != 0 { - t.Errorf("FAIL- Not expecting non zero max_seqnum counter, got %d, want %d", got, 0) + if !deviations.MissingValueForDefaults(ts.DUT) { + if got := gnmi.Get(t, ts.DUT, statePath.Level(2).SystemLevelCounters().ExceedMaxSeqNums().State()); got != 0 { + t.Errorf("FAIL- Not expecting non zero max_seqnum counter, got %d, want %d", got, 0) + } } // Checking IdLenMismatch counters. - if got := gnmi.Get(t, ts.DUT, statePath.Level(2).SystemLevelCounters().IdLenMismatch().State()); got != 0 { - t.Errorf("FAIL- Not expecting non zero IdLen_Mismatch counter, got %d, want %d", got, 0) + if !deviations.MissingValueForDefaults(ts.DUT) { + if got := gnmi.Get(t, ts.DUT, statePath.Level(2).SystemLevelCounters().IdLenMismatch().State()); got != 0 { + t.Errorf("FAIL- Not expecting non zero IdLen_Mismatch counter, got %d, want %d", got, 0) + } } // Checking LspErrors counters. - if got := gnmi.Get(t, ts.DUT, statePath.Level(2).SystemLevelCounters().LspErrors().State()); got != 0 { - t.Errorf("FAIL- Not expecting any lsp errors, got %d, want %d", got, 0) + if !deviations.MissingValueForDefaults(ts.DUT) { + if got := gnmi.Get(t, ts.DUT, statePath.Level(2).SystemLevelCounters().LspErrors().State()); got != 0 { + t.Errorf("FAIL- Not expecting any lsp errors, got %d, want %d", got, 0) + } } // Checking MaxAreaAddressMismatches counters. - if got := gnmi.Get(t, ts.DUT, statePath.Level(2).SystemLevelCounters().MaxAreaAddressMismatches().State()); got != 0 { - t.Errorf("FAIL- Not expecting non zero MaxAreaAddressMismatches counter, got %d, want %d", got, 0) + if !deviations.MissingValueForDefaults(ts.DUT) { + if got := gnmi.Get(t, ts.DUT, statePath.Level(2).SystemLevelCounters().MaxAreaAddressMismatches().State()); got != 0 { + t.Errorf("FAIL- Not expecting non zero MaxAreaAddressMismatches counter, got %d, want %d", got, 0) + } } // Checking OwnLspPurges counters. - if got := gnmi.Get(t, ts.DUT, statePath.Level(2).SystemLevelCounters().OwnLspPurges().State()); got != 0 { - t.Errorf("FAIL- Not expecting non zero OwnLspPurges counter, got %d, want %d", got, 0) + if !deviations.MissingValueForDefaults(ts.DUT) { + if got := gnmi.Get(t, ts.DUT, statePath.Level(2).SystemLevelCounters().OwnLspPurges().State()); got != 0 { + t.Errorf("FAIL- Not expecting non zero OwnLspPurges counter, got %d, want %d", got, 0) + } } // Checking SeqNumSkips counters. - if got := gnmi.Get(t, ts.DUT, statePath.Level(2).SystemLevelCounters().SeqNumSkips().State()); got != 0 { - t.Errorf("FAIL- Not expecting non zero SeqNumber skips, got %d, want %d", got, 0) + if !deviations.MissingValueForDefaults(ts.DUT) { + if got := gnmi.Get(t, ts.DUT, statePath.Level(2).SystemLevelCounters().SeqNumSkips().State()); got != 0 { + t.Errorf("FAIL- Not expecting non zero SeqNumber skips, got %d, want %d", got, 0) + } } // Checking ManualAddressDropFromAreas counters. - if !deviations.ISISCounterManualAddressDropFromAreasUnsupported(ts.DUT) { + if !(deviations.ISISCounterManualAddressDropFromAreasUnsupported(ts.DUT) || deviations.MissingValueForDefaults(ts.DUT)) { if got := gnmi.Get(t, ts.DUT, statePath.Level(2).SystemLevelCounters().ManualAddressDropFromAreas().State()); got != 0 { t.Errorf("FAIL- Not expecting non zero ManualAddressDropFromAreas counter, got %d, want %d", got, 0) } } // Checking PartChanges counters. - if !deviations.ISISCounterPartChangesUnsupported(ts.DUT) { + if !(deviations.ISISCounterPartChangesUnsupported(ts.DUT) || deviations.MissingValueForDefaults(ts.DUT)) { if got := gnmi.Get(t, ts.DUT, statePath.Level(2).SystemLevelCounters().PartChanges().State()); got != 0 { t.Errorf("FAIL- Not expecting partition changes, got %d, want %d", got, 0) } diff --git a/feature/experimental/isis/otg_tests/isis_interface_passive_test/metadata.textproto b/feature/experimental/isis/otg_tests/isis_interface_passive_test/metadata.textproto index f14063d5dc4..75bc2932d0e 100644 --- a/feature/experimental/isis/otg_tests/isis_interface_passive_test/metadata.textproto +++ b/feature/experimental/isis/otg_tests/isis_interface_passive_test/metadata.textproto @@ -10,6 +10,8 @@ platform_exceptions: { vendor: NOKIA } deviations: { + isis_global_authentication_not_required: true + isis_explicit_level_authentication_config: true isis_interface_level1_disable_required: true missing_isis_interface_afi_safi_enable: true explicit_port_speed: true diff --git a/feature/experimental/p4rt/otg_tests/traceroute_packetout_test/traceroute_packetout_test.go b/feature/experimental/p4rt/otg_tests/traceroute_packetout_test/traceroute_packetout_test.go index 7656153cd25..74b7b98b949 100644 --- a/feature/experimental/p4rt/otg_tests/traceroute_packetout_test/traceroute_packetout_test.go +++ b/feature/experimental/p4rt/otg_tests/traceroute_packetout_test/traceroute_packetout_test.go @@ -238,9 +238,9 @@ func TestPacketOut(t *testing.T) { otg := ate.OTG() otg.PushConfig(t, top) + otg.StartProtocols(t) otgutils.WaitForARP(t, ate.OTG(), top, "IPv4") otgutils.WaitForARP(t, ate.OTG(), top, "IPv6") - otg.StartProtocols(t) configureDeviceID(ctx, t, dut) diff --git a/feature/experimental/policy/otg_tests/prefix_set_test/README.md b/feature/experimental/policy/otg_tests/prefix_set_test/README.md index a2193a6c0c1..20ccedcaaa8 100644 --- a/feature/experimental/policy/otg_tests/prefix_set_test/README.md +++ b/feature/experimental/policy/otg_tests/prefix_set_test/README.md @@ -2,7 +2,9 @@ ## Summary -- Prefix list is updated and replaced correctly +- Prefix list is updated and replaced correctly after restarting the process + with supports gNOI to validate that internal state of OC agent is in sync + with the running configuration. ## Testbed type @@ -12,10 +14,14 @@ ### Applying configuration -For each section of configuration below, prepare a gnmi.SetBatch with all the configuration items appended to one SetBatch. Then apply the configuration to the DUT in one gnmi.Set using the `replace` option +For each section of configuration below, prepare a gnmi.SetBatch with all the +configuration items appended to one SetBatch. Then apply the configuration to +the DUT in one gnmi.Set using the `replace` option ### RT-1.53.1 [TODO:https://github.com/openconfig/featureprofiles/issues/3306] + #### Create a prefix-set with 2 prefixes + * Create a prefix-set with name "prefix-set-a" * /routing-policy/defined-sets/prefix-sets/prefix-set/config/name * Set the mode to IPv4 @@ -23,36 +29,91 @@ For each section of configuration below, prepare a gnmi.SetBatch with all the c * Define two prefixes 10.240.31.48/28 and 173.36.128.0/20 with mask "exact" * /routing-policy/defined-sets/prefix-sets/prefix-set/prefixes/prefix/config/ip-prefix * /routing-policy/defined-sets/prefix-sets/prefix-set/prefixes/prefix/config/masklength-range -* Validate that the prefix-list is created correctly with two prefixes i.e. 10.240.31.48/28 and 173.36.128.0/20 +* Validate that the prefix-list is created correctly with two prefixes i.e. + 10.240.31.48/28 and 173.36.128.0/20 * /routing-policy/defined-sets/prefix-sets/prefix-set/state/name * /routing-policy/defined-sets/prefix-sets/prefix-set/state/mode * /routing-policy/defined-sets/prefix-sets/prefix-set/prefixes/prefix/state/ip-prefix * /routing-policy/defined-sets/prefix-sets/prefix-set/prefixes/prefix/state/masklength-range ### RT-1.53.2 [TODO:https://github.com/openconfig/featureprofiles/issues/3306] + #### Replace the prefix-set by replacing an existing prefix with new prefix + * Define two prefixes 10.240.31.48/28 and 173.36.144.0/20 with mask "exact" * /routing-policy/defined-sets/prefix-sets/prefix-set/prefixes/prefix/config/ip-prefix * /routing-policy/defined-sets/prefix-sets/prefix-set/prefixes/prefix/config/masklength-range -* Relpace the previous prefix-list -* Validate that the prefix-list is created correctly with two prefixes i.e. 10.240.31.48/28 and 173.36.144.0/20 +* Replace the previous prefix-list +* Validate that the prefix-list is created correctly with two prefixes i.e. + 10.240.31.48/28 and 173.36.144.0/20 * /routing-policy/defined-sets/prefix-sets/prefix-set/state/name * /routing-policy/defined-sets/prefix-sets/prefix-set/state/mode * /routing-policy/defined-sets/prefix-sets/prefix-set/prefixes/prefix/state/ip-prefix * /routing-policy/defined-sets/prefix-sets/prefix-set/prefixes/prefix/state/masklength-range ### RT-1.53.3 [TODO:https://github.com/openconfig/featureprofiles/issues/3306] + ### Replace the prefix-set with 2 existing and a new prR -* Define three prefixes 10.240.31.48/28, 10.240.31.64/28 and 173.36.144.0/20 with mask "exact" + +* Define three prefixes 10.240.31.48/28, 10.240.31.64/28 and 173.36.144.0/20 + with mask "exact" * /routing-policy/defined-sets/prefix-sets/prefix-set/prefixes/prefix/config/ip-prefix * /routing-policy/defined-sets/prefix-sets/prefix-set/prefixes/prefix/config/masklength-range * Replace the previous prefix-list -* Validate that the prefix-list is created correctly with three prefixes 10.240.31.48/28, 10.240.31.64/28 and 173.36.144.0/20 +* Validate that the prefix-list is created correctly with three prefixes + 10.240.31.48/28, 10.240.31.64/28 and 173.36.144.0/20 * /routing-policy/defined-sets/prefix-sets/prefix-set/state/name * /routing-policy/defined-sets/prefix-sets/prefix-set/state/mode * /routing-policy/defined-sets/prefix-sets/prefix-set/prefixes/prefix/state/ip-prefix * /routing-policy/defined-sets/prefix-sets/prefix-set/prefixes/prefix/state/masklength-range +### RT-1.53.4 [TODO:https://github.com/openconfig/featureprofiles/issues/3306] + +### Create prefix list and replace with gnmi. + +* Send a gNMI SET request that contains below prefixes under TAG_3_IPV4 prefix-set + ``` + 10.240.31.48/28 + 10.244.187.32/28 + 173.36.128.0/20 + 173.37.128.0/20 + 173.38.128.0/20 + 173.39.128.0/20 + 173.40.128.0/20 + 173.41.128.0/20 + 173.42.128.0/20 + 173.43.128.0/20 + ``` +* Validate that the prefix-list is created correctly with 10 prefixes. +* Use gNOI to kill the process supporting gNMI. +* Send a gNMI SET request that contains additional prefixes within the same + prefix-set, TAG_3_IPV4. + ``` + 173.49.128.0/20 + 173.46.128.0/20 + 10.240.31.48/28 + 173.44.128.0/20 + 173.43.128.0/20 + 173.47.128.0/20 + 173.40.128.0/20 + 173.37.128.0/20 + 173.39.128.0/20 + 173.38.128.0/20 + 173.42.128.0/20 + 10.244.187.32/28 + 173.41.128.0/20 + 173.36.128.0/20 + 173.50.128.0/20 + 173.51.128.0/20 + 173.52.128.0/20 + 173.53.128.0/20 + 173.54.128.0/20 + 173.55.128.0/20 + 173.48.128.0/20 + 173.45.128.0/20 + ``` +* Validate that the prefix-list is created correctly with 22 prefixes. + ## OpenConfig Path and RPC Coverage The below yaml defines the OC paths intended to be covered by this test. OC @@ -78,4 +139,10 @@ rpcs: gnmi: gNMI.Set: gNMI.Subscribe: + gnoi: + system.System.KillProcess: ``` + +## Required DUT platform + +- vRX diff --git a/feature/experimental/policy/otg_tests/prefix_set_test/metadata.textproto b/feature/experimental/policy/otg_tests/prefix_set_test/metadata.textproto index e9f4e28871f..b47a1749263 100644 --- a/feature/experimental/policy/otg_tests/prefix_set_test/metadata.textproto +++ b/feature/experimental/policy/otg_tests/prefix_set_test/metadata.textproto @@ -5,3 +5,11 @@ uuid: "619040ac-21a0-403f-b38e-6d5d0aed433a" plan_id: "RT-1.53" description: "prefix-list test" testbed: TESTBED_DUT +platform_exceptions: { + platform: { + vendor: NOKIA + } + deviations: { + skip_prefix_set_mode: true + } + } \ No newline at end of file diff --git a/feature/experimental/policy/otg_tests/prefix_set_test/prefix_set_test.go b/feature/experimental/policy/otg_tests/prefix_set_test/prefix_set_test.go index f4860256f65..d6196b434b7 100644 --- a/feature/experimental/policy/otg_tests/prefix_set_test/prefix_set_test.go +++ b/feature/experimental/policy/otg_tests/prefix_set_test/prefix_set_test.go @@ -17,7 +17,9 @@ package prefix_set_test import ( "testing" + "github.com/openconfig/featureprofiles/internal/deviations" "github.com/openconfig/featureprofiles/internal/fptest" + "github.com/openconfig/featureprofiles/internal/gnoi" "github.com/openconfig/ondatra" "github.com/openconfig/ondatra/gnmi" "github.com/openconfig/ondatra/gnmi/oc" @@ -25,6 +27,7 @@ import ( const ( prefixSetA = "PFX_SET_A" + tag3IPv4 = "TAG_3_IPV4" pfx1 = "10.240.31.48/28" pfx2 = "173.36.128.0/20" pfx3 = "173.36.144.0/20" @@ -45,7 +48,9 @@ func TestPrefixSet(t *testing.T) { // create a prefix-set with 2 prefixes v4PrefixSet := ds.GetOrCreatePrefixSet(prefixSetA) - v4PrefixSet.SetMode(oc.PrefixSet_Mode_IPV4) + if !deviations.SkipPrefixSetMode(dut) { + v4PrefixSet.SetMode(oc.PrefixSet_Mode_IPV4) + } v4PrefixSet.GetOrCreatePrefix(pfx1, mskLen) v4PrefixSet.GetOrCreatePrefix(pfx2, mskLen) @@ -62,9 +67,12 @@ func TestPrefixSet(t *testing.T) { // replace the prefix-set by replacing an existing prefix with new prefix v4PrefixSet = ds.GetOrCreatePrefixSet(prefixSetA) - v4PrefixSet.SetMode(oc.PrefixSet_Mode_IPV4) + if !deviations.SkipPrefixSetMode(dut) { + v4PrefixSet.SetMode(oc.PrefixSet_Mode_IPV4) + } v4PrefixSet.GetOrCreatePrefix(pfx1, mskLen) v4PrefixSet.GetOrCreatePrefix(pfx3, mskLen) + v4PrefixSet.DeletePrefix(pfx2, mskLen) gnmi.Replace(t, dut, gnmi.OC().RoutingPolicy().DefinedSets().PrefixSet(prefixSetA).Config(), v4PrefixSet) prefixSet = gnmi.Get[*oc.RoutingPolicy_DefinedSets_PrefixSet](t, dut, gnmi.OC().RoutingPolicy().DefinedSets().PrefixSet(prefixSetA).State()) @@ -79,10 +87,13 @@ func TestPrefixSet(t *testing.T) { // replace the prefix-set with 2 existing and a new prefix v4PrefixSet = ds.GetOrCreatePrefixSet(prefixSetA) - v4PrefixSet.SetMode(oc.PrefixSet_Mode_IPV4) + if !deviations.SkipPrefixSetMode(dut) { + v4PrefixSet.SetMode(oc.PrefixSet_Mode_IPV4) + } v4PrefixSet.GetOrCreatePrefix(pfx1, mskLen) v4PrefixSet.GetOrCreatePrefix(pfx3, mskLen) v4PrefixSet.GetOrCreatePrefix(pfx4, mskLen) + v4PrefixSet.DeletePrefix(pfx2, mskLen) gnmi.Replace(t, dut, gnmi.OC().RoutingPolicy().DefinedSets().PrefixSet(prefixSetA).Config(), v4PrefixSet) prefixSet = gnmi.Get[*oc.RoutingPolicy_DefinedSets_PrefixSet](t, dut, gnmi.OC().RoutingPolicy().DefinedSets().PrefixSet(prefixSetA).State()) @@ -95,3 +106,65 @@ func TestPrefixSet(t *testing.T) { } } } + +func TestPrefixSetWithOCAgentRestart(t *testing.T) { + dut := ondatra.DUT(t, "dut") + + dutOcRoot := &oc.Root{} + rp := dutOcRoot.GetOrCreateRoutingPolicy() + ds := rp.GetOrCreateDefinedSets() + v4PrefixSet := ds.GetOrCreatePrefixSet(tag3IPv4) + if !deviations.SkipPrefixSetMode(dut) { + v4PrefixSet.SetMode(oc.PrefixSet_Mode_IPV4) + } + v4PrefixSet.GetOrCreatePrefix("10.240.31.48/28", mskLen) + v4PrefixSet.GetOrCreatePrefix("10.244.187.32/28", mskLen) + v4PrefixSet.GetOrCreatePrefix("173.36.128.0/20", mskLen) + v4PrefixSet.GetOrCreatePrefix("173.37.128.0/20", mskLen) + v4PrefixSet.GetOrCreatePrefix("173.38.128.0/20", mskLen) + v4PrefixSet.GetOrCreatePrefix("173.39.128.0/20", mskLen) + v4PrefixSet.GetOrCreatePrefix("173.40.128.0/20", mskLen) + v4PrefixSet.GetOrCreatePrefix("173.41.128.0/20", mskLen) + v4PrefixSet.GetOrCreatePrefix("173.42.128.0/20", mskLen) + v4PrefixSet.GetOrCreatePrefix("173.43.128.0/20", mskLen) + gnmi.Replace(t, dut, gnmi.OC().RoutingPolicy().DefinedSets().PrefixSet(tag3IPv4).Config(), v4PrefixSet) + prefixSet := gnmi.Get[*oc.RoutingPolicy_DefinedSets_PrefixSet](t, dut, gnmi.OC().RoutingPolicy().DefinedSets().PrefixSet(tag3IPv4).State()) + if got, want := len(prefixSet.Prefix), 10; got != want { + t.Errorf("Prefix set has %v prefixes, want %v", got, want) + } + + gnoi.KillProcess(t, dut, gnoi.OCAGENT, true) + + v4PrefixSet = ds.GetOrCreatePrefixSet(tag3IPv4) + if !deviations.SkipPrefixSetMode(dut) { + v4PrefixSet.SetMode(oc.PrefixSet_Mode_IPV4) + } + v4PrefixSet.GetOrCreatePrefix("173.49.128.0/20", mskLen) + v4PrefixSet.GetOrCreatePrefix("173.46.128.0/20", mskLen) + v4PrefixSet.GetOrCreatePrefix("10.240.31.48/28", mskLen) + v4PrefixSet.GetOrCreatePrefix("173.44.128.0/20", mskLen) + v4PrefixSet.GetOrCreatePrefix("173.43.128.0/20", mskLen) + v4PrefixSet.GetOrCreatePrefix("173.47.128.0/20", mskLen) + v4PrefixSet.GetOrCreatePrefix("173.40.128.0/20", mskLen) + v4PrefixSet.GetOrCreatePrefix("173.37.128.0/20", mskLen) + v4PrefixSet.GetOrCreatePrefix("173.39.128.0/20", mskLen) + v4PrefixSet.GetOrCreatePrefix("173.38.128.0/20", mskLen) + v4PrefixSet.GetOrCreatePrefix("173.42.128.0/20", mskLen) + v4PrefixSet.GetOrCreatePrefix("10.244.187.32/28", mskLen) + v4PrefixSet.GetOrCreatePrefix("173.41.128.0/20", mskLen) + v4PrefixSet.GetOrCreatePrefix("173.36.128.0/20", mskLen) + v4PrefixSet.GetOrCreatePrefix("173.50.128.0/20", mskLen) + v4PrefixSet.GetOrCreatePrefix("173.51.128.0/20", mskLen) + v4PrefixSet.GetOrCreatePrefix("173.52.128.0/20", mskLen) + v4PrefixSet.GetOrCreatePrefix("173.53.128.0/20", mskLen) + v4PrefixSet.GetOrCreatePrefix("173.54.128.0/20", mskLen) + v4PrefixSet.GetOrCreatePrefix("173.55.128.0/20", mskLen) + v4PrefixSet.GetOrCreatePrefix("173.48.128.0/20", mskLen) + v4PrefixSet.GetOrCreatePrefix("173.45.128.0/20", mskLen) + + gnmi.Replace(t, dut, gnmi.OC().RoutingPolicy().DefinedSets().PrefixSet(tag3IPv4).Config(), v4PrefixSet) + prefixSet = gnmi.Get[*oc.RoutingPolicy_DefinedSets_PrefixSet](t, dut, gnmi.OC().RoutingPolicy().DefinedSets().PrefixSet(tag3IPv4).State()) + if got, want := len(prefixSet.Prefix), 22; got != want { + t.Errorf("Prefix set has %v prefixes, want %v", got, want) + } +} diff --git a/feature/gnmi/subscribe/tests/gnmi_sample_mode_test/README.md b/feature/gnmi/subscribe/tests/gnmi_sample_mode_test/README.md index efeacde8591..cc08bec8a9b 100644 --- a/feature/gnmi/subscribe/tests/gnmi_sample_mode_test/README.md +++ b/feature/gnmi/subscribe/tests/gnmi_sample_mode_test/README.md @@ -44,10 +44,15 @@ Test to validate basic gNMI streaming telemetry works with `SAMPLE` mode. The below yaml defines the OC paths intended to be covered by this test. OC paths used for test setup are not listed here. -TODO(OCPATHS): Add paths ```yaml + paths: +## Config Paths ## +/interfaces/interface/config/description: + +## State Paths ## +/interfaces/interface/state/description: rpcs: gnmi: diff --git a/feature/gnmi/subscribe/tests/gnmi_sample_mode_test/gnmi_sample_mode_test.go b/feature/gnmi/subscribe/tests/gnmi_sample_mode_test/gnmi_sample_mode_test.go index 1b31e0a73d4..e7f72c9e4ea 100644 --- a/feature/gnmi/subscribe/tests/gnmi_sample_mode_test/gnmi_sample_mode_test.go +++ b/feature/gnmi/subscribe/tests/gnmi_sample_mode_test/gnmi_sample_mode_test.go @@ -35,24 +35,14 @@ func TestGNMISampleMode(t *testing.T) { p1Stream := samplestream.New(t, dut, gnmi.OC().Interface(p1.Name()).Description().State(), 10*time.Second) defer p1Stream.Close() - desc := p1Stream.Next() - if desc == nil { - t.Errorf("Interface %q telemetry not received before config", p1.Name()) - } else { - v, ok := desc.Val() - if !ok { - t.Errorf("Interface %q telemetry empty before config", p1.Name()) - } - t.Logf("Description before config: %s", v) - } - gnmi.Replace(t, dut, gnmi.OC().Interface(p1.Name()).Config(), dutPort1.NewOCInterface(p1.Name(), dut)) - desc = p1Stream.Next() + desc := p1Stream.Next() if desc == nil { t.Errorf("Interface %q telemetry not received after config", p1.Name()) } else { v, ok := desc.Val() + t.Logf("Description from stream : %s", v) if !ok { t.Errorf("Interface %q telemetry empty after config", p1.Name()) } @@ -69,6 +59,7 @@ func TestGNMISampleMode(t *testing.T) { t.Errorf("Interface %q telemetry not received after description update", p1.Name()) } else { v, ok := desc.Val() + t.Logf("Description from stream : %s", v) if !ok { t.Errorf("Interface %q telemetry empty after description update", p1.Name()) } diff --git a/feature/gnmi/subscribe/tests/gnmi_sample_mode_test/metadata.textproto b/feature/gnmi/subscribe/tests/gnmi_sample_mode_test/metadata.textproto index 87d02fedf47..9f4c6a67ba7 100644 --- a/feature/gnmi/subscribe/tests/gnmi_sample_mode_test/metadata.textproto +++ b/feature/gnmi/subscribe/tests/gnmi_sample_mode_test/metadata.textproto @@ -4,7 +4,7 @@ uuid: "abcc6890-c3e1-4b0e-984e-749c85b54e5a" plan_id: "gNMI-1.27" description: "gNMI Sample Mode Test" -testbed: TESTBED_DUT +testbed: TESTBED_DUT_ATE_2LINKS platform_exceptions: { platform: { vendor: ARISTA @@ -18,3 +18,11 @@ platform_exceptions: { isis_interface_afi_unsupported: true } } +platform_exceptions: { + platform: { + vendor: NOKIA + } + deviations: { + explicit_interface_in_default_vrf: true + } +} diff --git a/feature/gnoi/system/tests/copying_debug_files_test/copying_debug_files_test.go b/feature/gnoi/system/tests/copying_debug_files_test/copying_debug_files_test.go index 5fe2605d143..39c752d9f74 100644 --- a/feature/gnoi/system/tests/copying_debug_files_test/copying_debug_files_test.go +++ b/feature/gnoi/system/tests/copying_debug_files_test/copying_debug_files_test.go @@ -19,11 +19,11 @@ import ( "time" "github.com/openconfig/featureprofiles/internal/fptest" + "github.com/openconfig/featureprofiles/internal/system" hpb "github.com/openconfig/gnoi/healthz" spb "github.com/openconfig/gnoi/system" tpb "github.com/openconfig/gnoi/types" "github.com/openconfig/ondatra" - "github.com/openconfig/ondatra/gnmi" ) var ( @@ -53,7 +53,7 @@ func TestMain(m *testing.M) { // DUT // // Test notes: -//. Note: Initiating checkin to experimental +// Note: Initiating checkin to experimental // - KillProcess system call is used to kill a process. // - The healthz call needs to be modified to reflect the right component and its path. // @@ -67,10 +67,14 @@ func TestCopyingDebugFiles(t *testing.T) { if _, ok := processName[dut.Vendor()]; !ok { t.Fatalf("Please add support for vendor %v in var processName", dut.Vendor()) } + pID := system.FindProcessIDByName(t, dut, processName[dut.Vendor()]) + if pID == 0 { + t.Fatalf("process %v not found on device", processName[dut.Vendor()]) + } killProcessRequest := &spb.KillProcessRequest{ Signal: spb.KillProcessRequest_SIGNAL_KILL, Name: processName[dut.Vendor()], - Pid: findProcessByName(context.Background(), t, dut, processName[dut.Vendor()]), + Pid: uint32(pID), Restart: true, } processKillResponse, err := gnoiClient.System().KillProcess(context.Background(), killProcessRequest) @@ -109,19 +113,6 @@ func TestCopyingDebugFiles(t *testing.T) { } } -// findProcessByName uses telemetry to find out the PID of a process -func findProcessByName(ctx context.Context, t *testing.T, dut *ondatra.DUTDevice, pName string) uint32 { - pList := gnmi.GetAll(t, dut, gnmi.OC().System().ProcessAny().State()) - var pID uint32 - for _, proc := range pList { - if proc.GetName() == pName { - pID = uint32(proc.GetPid()) - t.Logf("Pid of daemon '%s' is '%d'", pName, pID) - } - } - return pID -} - func TestChassisComponentArtifacts(t *testing.T) { dut := ondatra.DUT(t, "dut") gnoiClient := dut.RawAPIs().GNOI(t) @@ -153,10 +144,10 @@ func TestChassisComponentArtifacts(t *testing.T) { t.Logf("Artifacts received for component %v: %v", componentName["name"], artifacts) // Fetch artifact details by executing ArtifactRequest and passing the artifact ID along. for _, artifact := range artifacts { - artId := artifact.GetId() - t.Logf("Executing ArtifactRequest for artifact ID %v", artId) + artID := artifact.GetId() + t.Logf("Executing ArtifactRequest for artifact ID %v", artID) artReq := &hpb.ArtifactRequest{ - Id: artId, + Id: artID, } // Verify that a valid response is received. artRes, err := gnoiClient.Healthz().Artifact(context.Background(), artReq) @@ -164,9 +155,9 @@ func TestChassisComponentArtifacts(t *testing.T) { t.Fatalf("Unexpected error on executing Healthz Artifact RPC: %v", err) } h1, err := artRes.Header() - t.Logf("Header of artifact %v: %v", artId, h1) + t.Logf("Header of artifact %v: %v", artID, h1) if err != nil { - t.Fatalf("Unexpected error when fetching the header of artifact %v: %v", artId, err) + t.Fatalf("Unexpected error when fetching the header of artifact %v: %v", artID, err) } } } diff --git a/feature/gribi/otg_tests/encap_decap_scale/encap_decap_scale_test.go b/feature/gribi/otg_tests/encap_decap_scale/encap_decap_scale_test.go index ec63b556f03..2c8f437f929 100644 --- a/feature/gribi/otg_tests/encap_decap_scale/encap_decap_scale_test.go +++ b/feature/gribi/otg_tests/encap_decap_scale/encap_decap_scale_test.go @@ -457,46 +457,43 @@ func createAndSendTrafficFlows(t *testing.T, args *testArgs, decapEntries []stri t.Helper() flow1 := createFlow(&flowArgs{flowName: "flow1", isInnHdrV4: true, - InnHdrSrcIP: atePort1.IPv4, InnHdrDstIP: encapVrfAIPv4Enries, inHdrDscp: []uint32{dscpEncapA1}, - outHdrSrcIP: ipv4OuterSrc111, outHdrDstIPs: decapEntries, outHdrDscp: []uint32{dscpEncapA1}, + InnHdrSrcIP: atePort1.IPv4, InnHdrDstIP: encapVrfAIPv4Enries, inHdrDscp: dscpEncapA1, + outHdrSrcIP: ipv4OuterSrc111, outHdrDstIPs: decapEntries, outHdrDscp: dscpEncapA1, }) flow2 := createFlow(&flowArgs{flowName: "flow2", isInnHdrV4: true, - InnHdrSrcIP: atePort1.IPv4, InnHdrDstIP: encapVrfBIPv4Enries, inHdrDscp: []uint32{dscpEncapB1}, - outHdrSrcIP: ipv4OuterSrc222, outHdrDstIPs: decapEntries, outHdrDscp: []uint32{dscpEncapB1}, + InnHdrSrcIP: atePort1.IPv4, InnHdrDstIP: encapVrfBIPv4Enries, inHdrDscp: dscpEncapB1, + outHdrSrcIP: ipv4OuterSrc222, outHdrDstIPs: decapEntries, outHdrDscp: dscpEncapB1, }) flow3 := createFlow(&flowArgs{flowName: "flow3", isInnHdrV4: true, - InnHdrSrcIP: atePort1.IPv4, InnHdrDstIP: encapVrfCIPv4Enries, inHdrDscp: []uint32{dscpEncapC1}, - outHdrSrcIP: ipv4OuterSrc111, outHdrDstIPs: decapEntries, outHdrDscp: []uint32{dscpEncapC1}, + InnHdrSrcIP: atePort1.IPv4, InnHdrDstIP: encapVrfCIPv4Enries, inHdrDscp: dscpEncapC1, + outHdrSrcIP: ipv4OuterSrc111, outHdrDstIPs: decapEntries, outHdrDscp: dscpEncapC1, }) flow4 := createFlow(&flowArgs{flowName: "flow4", isInnHdrV4: true, - InnHdrSrcIP: atePort1.IPv4, InnHdrDstIP: encapVrfDIPv4Enries, inHdrDscp: []uint32{dscpEncapD1}, - outHdrSrcIP: ipv4OuterSrc222, outHdrDstIPs: decapEntries, outHdrDscp: []uint32{dscpEncapD1}, + InnHdrSrcIP: atePort1.IPv4, InnHdrDstIP: encapVrfDIPv4Enries, inHdrDscp: dscpEncapD1, + outHdrSrcIP: ipv4OuterSrc222, outHdrDstIPs: decapEntries, outHdrDscp: dscpEncapD1, }) - // Below v6 flows will fail due to ixia issue. - // https://github.com/open-traffic-generator/fp-testbed-juniper/issues/49 - flow5 := createFlow(&flowArgs{flowName: "flow5", isInnHdrV4: false, - InnHdrSrcIPv6: atePort1.IPv6, InnHdrDstIPv6: encapVrfAIPv6Enries, inHdrDscp: []uint32{dscpEncapA2}, - outHdrSrcIP: ipv4OuterSrc111, outHdrDstIPs: decapEntries, outHdrDscp: []uint32{dscpEncapA2}, + InnHdrSrcIPv6: atePort1.IPv6, InnHdrDstIPv6: encapVrfAIPv6Enries, inHdrDscp: dscpEncapA2, + outHdrSrcIP: ipv4OuterSrc111, outHdrDstIPs: decapEntries, outHdrDscp: dscpEncapA2, }) flow6 := createFlow(&flowArgs{flowName: "flow6", isInnHdrV4: false, - InnHdrSrcIPv6: atePort1.IPv6, InnHdrDstIPv6: encapVrfBIPv6Enries, inHdrDscp: []uint32{dscpEncapB2}, - outHdrSrcIP: ipv4OuterSrc222, outHdrDstIPs: decapEntries, outHdrDscp: []uint32{dscpEncapB2}, + InnHdrSrcIPv6: atePort1.IPv6, InnHdrDstIPv6: encapVrfBIPv6Enries, inHdrDscp: dscpEncapB2, + outHdrSrcIP: ipv4OuterSrc222, outHdrDstIPs: decapEntries, outHdrDscp: dscpEncapB2, }) flow7 := createFlow(&flowArgs{flowName: "flow7", isInnHdrV4: false, - InnHdrSrcIPv6: atePort1.IPv6, InnHdrDstIPv6: encapVrfCIPv6Enries, inHdrDscp: []uint32{dscpEncapC2}, - outHdrSrcIP: ipv4OuterSrc111, outHdrDstIPs: decapEntries, outHdrDscp: []uint32{dscpEncapC2}, + InnHdrSrcIPv6: atePort1.IPv6, InnHdrDstIPv6: encapVrfCIPv6Enries, inHdrDscp: dscpEncapC2, + outHdrSrcIP: ipv4OuterSrc111, outHdrDstIPs: decapEntries, outHdrDscp: dscpEncapC2, }) flow8 := createFlow(&flowArgs{flowName: "flow8", isInnHdrV4: false, - InnHdrSrcIPv6: atePort1.IPv6, InnHdrDstIPv6: encapVrfDIPv6Enries, inHdrDscp: []uint32{dscpEncapD2}, - outHdrSrcIP: ipv4OuterSrc222, outHdrDstIPs: decapEntries, outHdrDscp: []uint32{dscpEncapD2}, + InnHdrSrcIPv6: atePort1.IPv6, InnHdrDstIPv6: encapVrfDIPv6Enries, inHdrDscp: dscpEncapD2, + outHdrSrcIP: ipv4OuterSrc222, outHdrDstIPs: decapEntries, outHdrDscp: dscpEncapD2, }) flowList := []gosnappi.Flow{flow1, flow2, flow3, flow4, flow5, flow6, flow7, flow8} @@ -507,6 +504,7 @@ func createAndSendTrafficFlows(t *testing.T, args *testArgs, decapEntries []stri } args.ate.OTG().PushConfig(t, args.top) + time.Sleep(30 * time.Second) args.ate.OTG().StartProtocols(t) // wait for glean adjacencies to be resolved time.Sleep(240 * time.Second) @@ -599,7 +597,8 @@ func pushDecapScaleEntries(t *testing.T, args *testArgs, decapEntries []string) func installDecapEntry(t *testing.T, args *testArgs, nhIndex, nhgIndex uint64, prefix string) { args.client.Modify().AddEntry(t, fluent.NextHopEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(args.dut)). - WithIndex(nhIndex).WithDecapsulateHeader(fluent.IPinIP), + WithIndex(nhIndex).WithDecapsulateHeader(fluent.IPinIP). + WithNextHopNetworkInstance(deviations.DefaultNetworkInstance(args.dut)), fluent.NextHopGroupEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(args.dut)). WithID(nhgIndex).AddNextHop(nhIndex, 1), fluent.IPv4Entry().WithNetworkInstance(niDecapTeVrf). @@ -617,8 +616,8 @@ type flowArgs struct { InnHdrSrcIPv6 string InnHdrDstIPv6 []string isInnHdrV4 bool - outHdrDscp []uint32 - inHdrDscp []uint32 + outHdrDscp uint32 + inHdrDscp uint32 } func createFlow(flowValues *flowArgs) gosnappi.Flow { @@ -638,22 +637,18 @@ func createFlow(flowValues *flowArgs) gosnappi.Flow { outerIPHdr := flow.Packet().Add().Ipv4() outerIPHdr.Src().SetValue(flowValues.outHdrSrcIP) outerIPHdr.Dst().SetValues(flowValues.outHdrDstIPs) - outerIPHdr.Priority().Dscp().Phb().SetValues(flowValues.outHdrDscp) + outerIPHdr.Priority().Dscp().Phb().SetValue(flowValues.outHdrDscp) if flowValues.isInnHdrV4 { innerIPHdr := flow.Packet().Add().Ipv4() innerIPHdr.Src().SetValue(flowValues.InnHdrSrcIP) innerIPHdr.Dst().SetValues(flowValues.InnHdrDstIP) - if len(flowValues.inHdrDscp) != 0 { - innerIPHdr.Priority().Dscp().Phb().SetValues(flowValues.inHdrDscp) - } + innerIPHdr.Priority().Dscp().Phb().SetValue(flowValues.inHdrDscp) } else { innerIpv6Hdr := flow.Packet().Add().Ipv6() innerIpv6Hdr.Src().SetValue(flowValues.InnHdrSrcIPv6) innerIpv6Hdr.Dst().SetValues(flowValues.InnHdrDstIPv6) - if len(flowValues.inHdrDscp) != 0 { - innerIpv6Hdr.TrafficClass().SetValues(flowValues.inHdrDscp) - } + innerIpv6Hdr.TrafficClass().SetValue(flowValues.inHdrDscp << 2) } return flow } @@ -791,7 +786,7 @@ func configureInterfaceDUT(t *testing.T, d *oc.Root, dut *ondatra.DUTDevice, dut func createSubifDUT(t *testing.T, d *oc.Root, dut *ondatra.DUTDevice, dutPort *ondatra.Port, index uint32, vlanID uint16, ipv4Addr string, ipv4SubintfPrefixLen int) *oc.Interface_Subinterface { i := d.GetOrCreateInterface(dutPort.Name()) s := i.GetOrCreateSubinterface(index) - if vlanID != 0 && index != 0 { + if vlanID != 0 { if deviations.DeprecatedVlanID(dut) { s.GetOrCreateVlan().VlanId = oc.UnionUint16(vlanID) } else { diff --git a/feature/gribi/otg_tests/encap_decap_scale/metadata.textproto b/feature/gribi/otg_tests/encap_decap_scale/metadata.textproto index af820161552..f1338dfb909 100644 --- a/feature/gribi/otg_tests/encap_decap_scale/metadata.textproto +++ b/feature/gribi/otg_tests/encap_decap_scale/metadata.textproto @@ -34,6 +34,7 @@ platform_exceptions: { vendor: JUNIPER } deviations: { + no_mix_of_tagged_and_untagged_subinterfaces: true explicit_interface_ref_definition: true gribi_decap_mixed_plen_unsupported: true } @@ -48,4 +49,3 @@ platform_exceptions: { omit_l2_mtu: true } } - diff --git a/feature/gribi/otg_tests/encap_frr/encap_frr_test.go b/feature/gribi/otg_tests/encap_frr/encap_frr_test.go index 8a9fec793ae..621a680fd91 100644 --- a/feature/gribi/otg_tests/encap_frr/encap_frr_test.go +++ b/feature/gribi/otg_tests/encap_frr/encap_frr_test.go @@ -1196,15 +1196,15 @@ func TestEncapFrr(t *testing.T) { if tc.TestID == "primaryBackupRoutingAll" { args.client.Modify().AddEntry(t, fluent.NextHopEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithIndex(1100).WithDecapsulateHeader(fluent.IPinIP). + WithIndex(1200).WithDecapsulateHeader(fluent.IPinIP). WithNextHopNetworkInstance(deviations.DefaultNetworkInstance(dut)), - fluent.NextHopGroupEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithID(1000).AddNextHop(1100, 1), fluent.NextHopEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithIndex(1101).WithDecapsulateHeader(fluent.IPinIP). + WithIndex(1201).WithDecapsulateHeader(fluent.IPinIP). WithNextHopNetworkInstance(deviations.DefaultNetworkInstance(dut)), fluent.NextHopGroupEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithID(1001).AddNextHop(1101, 1), + WithID(1000).AddNextHop(1200, 1), + fluent.NextHopGroupEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). + WithID(1001).AddNextHop(1201, 1), ) if err := awaitTimeout(ctx, t, args.client, time.Minute); err != nil { t.Logf("Could not program entries via client, got err, check error codes: %v", err) diff --git a/feature/gribi/otg_tests/encap_frr_with_reencap_vrf_test/encap_frr_with_reencap_vrf_test.go b/feature/gribi/otg_tests/encap_frr_with_reencap_vrf_test/encap_frr_with_reencap_vrf_test.go index f90726d54f8..fdd5e3329a7 100644 --- a/feature/gribi/otg_tests/encap_frr_with_reencap_vrf_test/encap_frr_with_reencap_vrf_test.go +++ b/feature/gribi/otg_tests/encap_frr_with_reencap_vrf_test/encap_frr_with_reencap_vrf_test.go @@ -197,7 +197,6 @@ func awaitTimeout(ctx context.Context, t testing.TB, c *fluent.GRIBIClient, time } type testArgs struct { - ctx context.Context client *fluent.GRIBIClient dut *ondatra.DUTDevice ate *ondatra.ATEDevice @@ -1111,18 +1110,17 @@ func TestEncapFrr(t *testing.T) { if tc.TestID == "primaryBackupRoutingAll" { args.client.Modify().AddEntry(t, fluent.NextHopEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithIndex(1200). + WithIndex(1200).WithDecapsulateHeader(fluent.IPinIP). WithNextHopNetworkInstance(deviations.DefaultNetworkInstance(dut)), fluent.NextHopEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithIndex(1201). + WithIndex(1201).WithDecapsulateHeader(fluent.IPinIP). WithNextHopNetworkInstance(deviations.DefaultNetworkInstance(dut)), - fluent.NextHopGroupEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). WithID(1000).AddNextHop(1200, 1), fluent.NextHopGroupEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). WithID(1001).AddNextHop(1201, 1), ) - if err := awaitTimeout(args.ctx, t, args.client, 2*time.Minute); err != nil { + if err := awaitTimeout(ctx, t, args.client, 2*time.Minute); err != nil { t.Logf("Could not program entries via client, got err, check error codes: %v", err) } } @@ -1135,7 +1133,7 @@ func TestEncapFrr(t *testing.T) { fluent.IPv4Entry().WithNetworkInstance(niEncapTeVrfA). WithPrefix("0.0.0.0/0").WithNextHopGroup(1003).WithNextHopGroupNetworkInstance(deviations.DefaultNetworkInstance(dut)), ) - if err := awaitTimeout(args.ctx, t, args.client, 2*time.Minute); err != nil { + if err := awaitTimeout(ctx, t, args.client, 2*time.Minute); err != nil { t.Logf("Could not program entries via client, got err, check error codes: %v", err) } createFlow(t, otgConfig, otg, noMatchEncapDest) @@ -1154,7 +1152,7 @@ func TestEncapFrr(t *testing.T) { fluent.NextHopGroupEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). WithID(1001).AddNextHop(1301, 1), ) - if err := awaitTimeout(args.ctx, t, args.client, 2*time.Minute); err != nil { + if err := awaitTimeout(ctx, t, args.client, 2*time.Minute); err != nil { t.Logf("Could not program entries via client, got err, check error codes: %v", err) } } @@ -1169,8 +1167,7 @@ func TestEncapFrr(t *testing.T) { fluent.NextHopGroupEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). WithID(101).AddNextHop(201, 1).AddNextHop(202, 3).WithBackupNHG(2001), ) - - if err := awaitTimeout(args.ctx, t, args.client, 2*time.Minute); err != nil { + if err := awaitTimeout(ctx, t, args.client, 2*time.Minute); err != nil { t.Logf("Could not program entries via client, got err, check error codes: %v", err) } } diff --git a/feature/gribi/otg_tests/gribi_scaling/gribi_scaling_test.go b/feature/gribi/otg_tests/gribi_scaling/gribi_scaling_test.go index ec4b9f81cc3..0d601a390aa 100644 --- a/feature/gribi/otg_tests/gribi_scaling/gribi_scaling_test.go +++ b/feature/gribi/otg_tests/gribi_scaling/gribi_scaling_test.go @@ -263,6 +263,7 @@ func incrementMAC(mac string, i int) (string, error) { func TestScaling(t *testing.T) { dut := ondatra.DUT(t, "dut") + overrideScaleParams(dut) ate := ondatra.ATE(t, "ate") ctx := context.Background() @@ -378,3 +379,12 @@ func checkTraffic(t *testing.T, ate *ondatra.ATEDevice, top gosnappi.Config) { t.Errorf("FAIL- Got %v%% packet loss for %s ; expected < 1%%", lossPct, "flow") } } + +// overrideScaleParams allows to override the default scale parameters based on the DUT vendor. +func overrideScaleParams(dut *ondatra.DUTDevice) { + if deviations.OverrideDefaultNhScale(dut) { + if dut.Vendor() == ondatra.CISCO { + *fpargs.V4TunnelCount = 3328 + } + } +} diff --git a/feature/gribi/otg_tests/gribi_scaling/metadata.textproto b/feature/gribi/otg_tests/gribi_scaling/metadata.textproto index 7877fc7e26a..981e65d1ab9 100644 --- a/feature/gribi/otg_tests/gribi_scaling/metadata.textproto +++ b/feature/gribi/otg_tests/gribi_scaling/metadata.textproto @@ -12,6 +12,7 @@ platform_exceptions: { deviations: { ipv4_missing_enabled: true interface_ref_interface_id_format: true + override_default_nh_scale: true } } platform_exceptions: { diff --git a/feature/gribi/otg_tests/gribigo_compliance_test/README.md b/feature/gribi/otg_tests/gribigo_compliance_test/README.md index 03a1b975784..f5fb9926170 100644 --- a/feature/gribi/otg_tests/gribigo_compliance_test/README.md +++ b/feature/gribi/otg_tests/gribigo_compliance_test/README.md @@ -21,3 +21,22 @@ For each compliance test case in the test suite: * If the case expects a t.Fatal result, use testt.ExpectFatal. * If the case expects a t.Error result, use testt.ExpectError. * Otherwise, call the test case function directly. + +## OpenConfig Path and RPC Coverage + +The below yaml defines the OC paths and RPC intended to be covered by this test. + +```yaml +paths: + /interfaces/interface/config/enabled: + + +rpcs: + gnmi: + gNMI.Subscribe: + ON_CHANGE: true + + gnoi: + system.System.Reboot: + +``` diff --git a/feature/gribi/otg_tests/gribigo_compliance_test/gribigo_compliance_test.go b/feature/gribi/otg_tests/gribigo_compliance_test/gribigo_compliance_test.go index 398959eae6a..1792e620550 100644 --- a/feature/gribi/otg_tests/gribigo_compliance_test/gribigo_compliance_test.go +++ b/feature/gribi/otg_tests/gribigo_compliance_test/gribigo_compliance_test.go @@ -16,8 +16,10 @@ package gribigo_compliance_test import ( + "context" "strings" "testing" + "time" "flag" @@ -27,12 +29,15 @@ import ( "github.com/openconfig/featureprofiles/internal/fptest" "github.com/openconfig/featureprofiles/internal/gribi" "github.com/openconfig/featureprofiles/internal/otgutils" + "github.com/openconfig/gribigo/chk" "github.com/openconfig/gribigo/compliance" + "github.com/openconfig/gribigo/constants" "github.com/openconfig/gribigo/fluent" "github.com/openconfig/ondatra" "github.com/openconfig/ondatra/gnmi" "github.com/openconfig/ondatra/gnmi/oc" "github.com/openconfig/testt" + "github.com/openconfig/ygot/ygot" ) var ( @@ -82,6 +87,14 @@ var ( } ) +type testArgs struct { + ctx context.Context + dut *ondatra.DUTDevice + ate *ondatra.ATEDevice + client *fluent.GRIBIClient + electionID gribi.Uint128 +} + func TestMain(m *testing.M) { fptest.RunTests(m) } @@ -177,6 +190,58 @@ func TestCompliance(t *testing.T) { tt.In.Fn(c, t, opts...) }) } + ctx := context.Background() + c := fluent.NewClient() + c.Connection().WithStub(gribic).WithPersistence().WithInitialElectionID(1, 0). + WithFIBACK().WithRedundancyMode(fluent.ElectedPrimaryClient) + c.Start(ctx, t) + c.StartSending(ctx, t) + eID := gribi.BecomeLeader(t, c) + tcArgs := &testArgs{ + ctx: ctx, + client: c, + dut: dut, + ate: ate, + electionID: eID, + } + testAdditionalCompliance(tcArgs, t) +} + +// testAdditionalCompliance tests has additional compliance tests that are not covered by the compliance +// test suite. +func testAdditionalCompliance(tcArgs *testArgs, t *testing.T) { + + tests := []struct { + desc string + fn func(*testArgs, fluent.ProgrammingResult, testing.TB) + }{ + { + desc: "Add IPv4 Entry with NHG which point to NH IP which doesn't resolved with in topology", + fn: addNHGReferencingToUnresolvedNH, + }, + { + desc: "Add IPv4 Entry with NHG which point to NH with Down port", + fn: addNHGReferencingToDownPort, + }, + } + for _, tt := range tests { + t.Run(tt.desc, func(t *testing.T) { + if err := gribi.FlushAll(tcArgs.client); err != nil { + t.Fatal(err) + } + tt.fn(tcArgs, fluent.InstalledInFIB, t) + }) + } +} + +func setDUTInterfaceWithState(t testing.TB, dut *ondatra.DUTDevice, p *ondatra.Port, state bool) { + dc := gnmi.OC() + i := &oc.Interface{} + i.Enabled = ygot.Bool(state) + i.Type = oc.IETFInterfaces_InterfaceType_ethernetCsmacd + i.Name = ygot.String(p.Name()) + gnmi.Update(t, dut, dc.Interface(p.Name()).Config(), i) + } // configureDUT configures port1-3 on the DUT. @@ -225,3 +290,70 @@ func configureATE(t *testing.T, ate *ondatra.ATEDevice) gosnappi.Config { return top } + +// addNHGReferencingToUnresolvedNH tests a case where a nexthop group references a nexthop IP 1.0.0.1 +// that does not Resolved with in the topology +func addNHGReferencingToUnresolvedNH(tcArgs *testArgs, wantACK fluent.ProgrammingResult, t testing.TB) { + t.Log("Flush existing gRIBI routes before test.") + if err := gribi.FlushAll(tcArgs.client); err != nil { + t.Fatal(err) + } + tcArgs.client.Modify().AddEntry(t, + fluent.NextHopEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(tcArgs.dut)). + WithIndex(2000).WithIPAddress("1.0.0.1"), + fluent.NextHopGroupEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(tcArgs.dut)). + WithID(2000).AddNextHop(2000, 1), + fluent.IPv4Entry().WithNetworkInstance(deviations.DefaultNetworkInstance(tcArgs.dut)). + WithPrefix("203.0.113.101/32").WithNextHopGroup(2000)) + + if err := awaitTimeout(tcArgs.ctx, t, tcArgs.client, 2*time.Minute); err != nil { + t.Logf("Could not program entries via client, got err, check error codes: %v", err) + } + chk.HasResult(t, tcArgs.client.Results(t), + fluent.OperationResult(). + WithNextHopGroupOperation(2000). + WithOperationType(constants.Add). + WithProgrammingResult(wantACK). + AsResult(), + chk.IgnoreOperationID()) +} + +// addNHGReferencingToDownPort tests a case where a nexthop group references to nexthop port that is down. +// Entry must be expected to be installed in FIB. +func addNHGReferencingToDownPort(tcArgs *testArgs, wantACK fluent.ProgrammingResult, t testing.TB) { + t.Log("Setting port2 to down...") + p := tcArgs.dut.Port(t, "port2") + t.Log("Flush existing gRIBI routes before test.") + if err := gribi.FlushAll(tcArgs.client); err != nil { + t.Fatal(err) + } + setDUTInterfaceWithState(t, tcArgs.dut, p, false) + + tcArgs.client.Modify().AddEntry(t, + fluent.NextHopEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(tcArgs.dut)). + WithIndex(2000).WithIPAddress(atePort2.IPv4), + fluent.NextHopGroupEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(tcArgs.dut)). + WithID(2000).AddNextHop(2000, 1), + fluent.IPv4Entry().WithNetworkInstance(deviations.DefaultNetworkInstance(tcArgs.dut)). + WithPrefix("203.0.113.100/32").WithNextHopGroup(2000), + ) + if err := awaitTimeout(tcArgs.ctx, t, tcArgs.client, 2*time.Minute); err != nil { + t.Logf("Could not program entries via client, got err, check error codes: %v", err) + } + chk.HasResult(t, tcArgs.client.Results(t), + fluent.OperationResult(). + WithIPv4Operation("203.0.113.100/32"). + WithOperationType(constants.Add). + WithProgrammingResult(fluent.InstalledInFIB). + AsResult(), + chk.IgnoreOperationID(), + ) +} + +// awaitTimeout calls a fluent client Await, adding a timeout to the context. +func awaitTimeout(ctx context.Context, t testing.TB, c *fluent.GRIBIClient, timeout time.Duration) error { + t.Helper() + subctx, cancel := context.WithTimeout(ctx, timeout) + defer cancel() + return c.Await(subctx, t) +} diff --git a/feature/gribi/otg_tests/supervisor_failure_test/supervisor_failure_test.go b/feature/gribi/otg_tests/supervisor_failure_test/supervisor_failure_test.go index 634a45c0de6..4dd22321943 100644 --- a/feature/gribi/otg_tests/supervisor_failure_test/supervisor_failure_test.go +++ b/feature/gribi/otg_tests/supervisor_failure_test/supervisor_failure_test.go @@ -220,9 +220,10 @@ func findSecondaryController(t *testing.T, dut *ondatra.DUTDevice, controllers [ } // validateTelemetry validates telemetry sensors -func validateTelemetry(t *testing.T, dut *ondatra.DUTDevice, primaryAfterSwitch string) { +func validateTelemetry(t *testing.T, dut *ondatra.DUTDevice, primaryAfterSwitch, secondaryAfterSwitch string) { t.Log("Validate OC Switchover time/reason.") primary := gnmi.OC().Component(primaryAfterSwitch) + secondary := gnmi.OC().Component(secondaryAfterSwitch) if !gnmi.Lookup(t, dut, primary.LastSwitchoverTime().State()).IsPresent() { t.Errorf("primary.LastSwitchoverTime().Lookup(t).IsPresent(): got false, want true") } else { @@ -244,16 +245,16 @@ func validateTelemetry(t *testing.T, dut *ondatra.DUTDevice, primaryAfterSwitch t.Errorf("primary.GetLastSwitchoverReason().GetTrigger(): got %s, want %s.", got, want) } - if !gnmi.Lookup(t, dut, primary.LastRebootTime().State()).IsPresent() { - t.Errorf("primary.LastRebootTime.().Lookup(t).IsPresent(): got false, want true") + if !gnmi.Lookup(t, dut, secondary.LastRebootTime().State()).IsPresent() { + t.Errorf("secondary.LastRebootTime.().Lookup(t).IsPresent(): got false, want true") } else { - lastrebootTime := gnmi.Get(t, dut, primary.LastRebootTime().State()) + lastrebootTime := gnmi.Get(t, dut, secondary.LastRebootTime().State()) t.Logf("Found lastRebootTime.GetDetails(): %v", lastrebootTime) } - if !gnmi.Lookup(t, dut, primary.LastRebootReason().State()).IsPresent() { - t.Errorf("primary.LastRebootReason.().Lookup(t).IsPresent(): got false, want true") + if !gnmi.Lookup(t, dut, secondary.LastRebootReason().State()).IsPresent() { + t.Errorf("secondary.LastRebootReason.().Lookup(t).IsPresent(): got false, want true") } else { - lastrebootReason := gnmi.Get(t, dut, primary.LastRebootReason().State()) + lastrebootReason := gnmi.Get(t, dut, secondary.LastRebootReason().State()) t.Logf("Found lastRebootReason.GetDetails(): %v", lastrebootReason) } } @@ -354,8 +355,8 @@ func TestSupFailure(t *testing.T) { // Old secondary controller becomes primary after switchover. primaryAfterSwitch := secondaryBeforeSwitch - - validateTelemetry(t, dut, primaryAfterSwitch) + secondaryAfterSwitch := secondaryBeforeSwitch + validateTelemetry(t, dut, primaryAfterSwitch, secondaryAfterSwitch) // Assume Controller Switchover happened, ensure traffic flows without loss. // Verify the entry for 203.0.113.0/24 is active through AFT Telemetry. // Try starting the gribi client twice as switchover may reset the connection. diff --git a/feature/interface/aggregate/otg_tests/aggregate_all_not_viable_test/aggregate_all_not_forwarding_viable_test.go b/feature/interface/aggregate/otg_tests/aggregate_all_not_viable_test/aggregate_all_not_forwarding_viable_test.go index 81157a8e260..48cacf68dd8 100644 --- a/feature/interface/aggregate/otg_tests/aggregate_all_not_viable_test/aggregate_all_not_forwarding_viable_test.go +++ b/feature/interface/aggregate/otg_tests/aggregate_all_not_viable_test/aggregate_all_not_forwarding_viable_test.go @@ -176,13 +176,15 @@ func TestAggregateAllNotForwardingViable(t *testing.T) { changeMetric(t, dut, aggIDs[2], 30) top := configureATE(t, ate) installGRIBIRoutes(t, dut, ate, top) - flows := createFlows(t, dut, top, aggIDs) ate.OTG().PushConfig(t, top) ate.OTG().StartProtocols(t) for _, aggID := range aggIDs { - gnmi.Await(t, dut, gnmi.OC().Interface(aggID).OperStatus().State(), 30*time.Second, oc.Interface_OperStatus_UP) + gnmi.Await(t, dut, gnmi.OC().Interface(aggID).OperStatus().State(), 60*time.Second, oc.Interface_OperStatus_UP) } + flows := createFlows(t, ate, top) + ate.OTG().PushConfig(t, top) + ate.OTG().StartProtocols(t) for _, agg := range []*aggPortData{agg1, agg2, agg3} { bgpPath := ocpath.Root().NetworkInstance(deviations.DefaultNetworkInstance(dut)).Protocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_BGP, "BGP").Bgp() gnmi.Await(t, dut, bgpPath.Neighbor(agg.ateIPv4).SessionState().State(), time.Minute, oc.Bgp_Neighbor_SessionState_ESTABLISHED) @@ -215,7 +217,9 @@ func TestAggregateAllNotForwardingViable(t *testing.T) { // Ensure ISIS Adjacency is Down on LAG_2 if ok := awaitAdjacency(t, dut, aggIDs[1], oc.Isis_IsisInterfaceAdjState_DOWN); !ok { - t.Fatal("ISIS Adjacency is Established on LAG_2") + if presence := gnmi.LookupAll(t, dut, ocpath.Root().NetworkInstance(deviations.DefaultNetworkInstance(dut)).Protocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_ISIS, isisInstance).Isis().Interface(aggIDs[1]).LevelAny().AdjacencyAny().AdjacencyState().State()); len(presence) > 0 { + t.Fatalf("ISIS Adjacency is Established on LAG_2 ") + } } startTraffic(t, dut, ate, top) if err := confirmNonViableForwardingTraffic(t, dut, ate, atePortList[1:agg2.ateLagCount+1], dutPortList[1:agg2.ateLagCount+1]); err != nil { @@ -292,7 +296,9 @@ func TestAggregateAllNotForwardingViable(t *testing.T) { configForwardingViable(t, dut, dutPortList[1:2], false) // Ensure ISIS Adjacency is Down on LAG_2 if ok := awaitAdjacency(t, dut, aggIDs[1], oc.Isis_IsisInterfaceAdjState_DOWN); !ok { - t.Fatal("ISIS Adjacency is Established on LAG_2") + if presence := gnmi.LookupAll(t, dut, ocpath.Root().NetworkInstance(deviations.DefaultNetworkInstance(dut)).Protocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_ISIS, isisInstance).Isis().Interface(aggIDs[1]).LevelAny().AdjacencyAny().AdjacencyState().State()); len(presence) > 0 { + t.Fatalf("ISIS Adjacency is Established on LAG_2") + } } startTraffic(t, dut, ate, top) if err := confirmNonViableForwardingTraffic(t, dut, ate, atePortList[1:(agg2.ateLagCount+1)], dutPortList[1:(agg2.ateLagCount+1)]); err != nil { @@ -394,7 +400,7 @@ func configureDUT(t *testing.T, dut *ondatra.DUTDevice) []string { configureRoutingPolicy(t, dut) configureDUTISIS(t, dut, aggIDs) - if deviations.MaxEcmpPaths(dut) { + if !deviations.MaxEcmpPaths(dut) { isisPath := gnmi.OC().NetworkInstance(deviations.DefaultNetworkInstance(dut)).Protocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_ISIS, isisInstance).Isis() gnmi.Update(t, dut, isisPath.Global().MaxEcmpPaths().Config(), 2) } @@ -805,9 +811,9 @@ func incrementMAC(mac string, i int) (string, error) { return newMac.String(), nil } -func createFlows(t *testing.T, dut *ondatra.DUTDevice, top gosnappi.Config, aggIDs []string) []gosnappi.Flow { - for _, aggID := range aggIDs { - dutAggMac = append(dutAggMac, gnmi.Get(t, dut, gnmi.OC().Lacp().Interface(aggID).SystemIdMac().State())) +func createFlows(t *testing.T, ate *ondatra.ATEDevice, top gosnappi.Config) []gosnappi.Flow { + for _, aggID := range []*aggPortData{agg1, agg2, agg3} { + dutAggMac = append(dutAggMac, gnmi.Get(t, ate.OTG(), gnmi.OTG().Interface(aggID.ateAggName+".Eth").Ipv4Neighbor(aggID.dutIPv4).LinkLayerAddress().State())) } f1V4 := configureFlows(t, top, pfx1AdvV4, pfx2AdvV4, "pfx1ToPfx2_3", agg1, []*aggPortData{agg2, agg3}, dutAggMac[0], ipRange[1]) f2V4 := configureFlows(t, top, pfx1AdvV4, pfx4AdvV4, "pfx1ToPfx4", agg1, []*aggPortData{agg2, agg3}, dutAggMac[0], ipRange[0]) @@ -958,7 +964,7 @@ func awaitAdjacency(t *testing.T, dut *ondatra.DUTDevice, intfName string, state isisPath := ocpath.Root().NetworkInstance(deviations.DefaultNetworkInstance(dut)).Protocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_ISIS, isisInstance).Isis() intf := isisPath.Interface(intfName) query := intf.LevelAny().AdjacencyAny().AdjacencyState().State() - _, ok := gnmi.WatchAll(t, dut, query, time.Minute, func(val *ygnmi.Value[oc.E_Isis_IsisInterfaceAdjState]) bool { + _, ok := gnmi.WatchAll(t, dut, query, 90*time.Second, func(val *ygnmi.Value[oc.E_Isis_IsisInterfaceAdjState]) bool { v, ok := val.Val() return v == state && ok }).Await(t) diff --git a/feature/interface/aggregate/otg_tests/aggregate_all_not_viable_test/metadata.textproto b/feature/interface/aggregate/otg_tests/aggregate_all_not_viable_test/metadata.textproto index 71c189d4df0..0896d869a61 100644 --- a/feature/interface/aggregate/otg_tests/aggregate_all_not_viable_test/metadata.textproto +++ b/feature/interface/aggregate/otg_tests/aggregate_all_not_viable_test/metadata.textproto @@ -36,7 +36,7 @@ platform_exceptions: { static_protocol_name: "STATIC" aggregate_atomic_update: true missing_value_for_defaults: true - max_ecmp_paths: false + max_ecmp_paths: true explicit_interface_in_default_vrf: false } } diff --git a/feature/lldp/ate_tests/core_lldp_tlv_population_test/README.md b/feature/lldp/ate_tests/core_lldp_tlv_population_test/README.md index 6e0e134a35d..e40267537ed 100644 --- a/feature/lldp/ate_tests/core_lldp_tlv_population_test/README.md +++ b/feature/lldp/ate_tests/core_lldp_tlv_population_test/README.md @@ -17,29 +17,31 @@ Determine LLDP advertisement and reception operates correctly. configuration of lldp/interfaces/interface/config/enabled (TRUE or FALSE) on any interface. -## Config Parameter coverage - -* /lldp/config/enabled -* /lldp/interfaces/interface/config/enabled - -## Telemetry Parameter coverage - -* /lldp/interfaces/interface/neighbors/neighbor/state/chassis-id -* /lldp/interfaces/interface/neighbors/neighbor/state/chassis-id-subtype -* /lldp/interfaces/interface/neighbors/neighbor/state/port-id -* /lldp/interfaces/interface/neighbors/neighbor/state/port-id-subtype -* /lldp/interfaces/interface/neighbors/neighbor/state/system-name -* /lldp/interfaces/interface/state/name -* /lldp/state/chassis-id -* /lldp/state/chassis-id-type -* /lldp/state/system-name - -## Protocol/RPC Parameter coverage - -LLDP: - -* /lldp/config/enabled = true -* /lldp/interfaces/interface/config/enabled = true +## OpenConfig Path and RPC Coverage + +The below yaml defines the OC paths intended to be covered by this test. OC paths used for test setup are not listed here. + +```yaml +paths: + ## Config Paths ## + /lldp/config/enabled: + /lldp/interfaces/interface/config/enabled: + + ## State Paths ## + /lldp/interfaces/interface/neighbors/neighbor/state/chassis-id: + /lldp/interfaces/interface/neighbors/neighbor/state/port-id: + /lldp/interfaces/interface/neighbors/neighbor/state/system-name: + /lldp/interfaces/interface/state/name: + /lldp/state/chassis-id: + /lldp/state/chassis-id-type: + /lldp/state/system-name: + +rpcs: + gnmi: + gNMI.Get: + gNMI.Set: + +``` ## Minimum DUT platform requirement diff --git a/feature/lldp/ate_tests/core_lldp_tlv_population_test/core_lldp_tlv_population_test.go b/feature/lldp/ate_tests/core_lldp_tlv_population_test/core_lldp_tlv_population_test.go index 61532d41ea1..73498534b12 100644 --- a/feature/lldp/ate_tests/core_lldp_tlv_population_test/core_lldp_tlv_population_test.go +++ b/feature/lldp/ate_tests/core_lldp_tlv_population_test/core_lldp_tlv_population_test.go @@ -94,19 +94,21 @@ func TestCoreLLDPTLVPopulation(t *testing.T) { func configureNode(t *testing.T, name string, lldpEnabled bool) (*ondatra.DUTDevice, *oc.Lldp) { node := ondatra.DUT(t, name) p := node.Port(t, portName) - lldp := gnmi.OC().Lldp() + d := &oc.Root{} + lldp := d.GetOrCreateLldp() + llint := lldp.GetOrCreateInterface(p.Name()) - gnmi.Replace(t, node, lldp.Enabled().Config(), lldpEnabled) + gnmi.Replace(t, node, gnmi.OC().Lldp().Enabled().Config(), lldpEnabled) if lldpEnabled { - gnmi.Replace(t, node, lldp.Interface(p.Name()).Enabled().Config(), lldpEnabled) + gnmi.Replace(t, node, gnmi.OC().Lldp().Interface(p.Name()).Config(), llint) } if deviations.InterfaceEnabled(node) { gnmi.Replace(t, node, gnmi.OC().Interface(p.Name()).Enabled().Config(), true) } - return node, gnmi.Get(t, node, lldp.Config()) + return node, gnmi.Get(t, node, gnmi.OC().Lldp().Config()) } // verifyNodeConfig verifies the config by comparing against the telemetry state object. diff --git a/feature/lldp/otg_tests/core_lldp_tlv_population_test/README.md b/feature/lldp/otg_tests/core_lldp_tlv_population_test/README.md index 6e0e134a35d..e40267537ed 100644 --- a/feature/lldp/otg_tests/core_lldp_tlv_population_test/README.md +++ b/feature/lldp/otg_tests/core_lldp_tlv_population_test/README.md @@ -17,29 +17,31 @@ Determine LLDP advertisement and reception operates correctly. configuration of lldp/interfaces/interface/config/enabled (TRUE or FALSE) on any interface. -## Config Parameter coverage - -* /lldp/config/enabled -* /lldp/interfaces/interface/config/enabled - -## Telemetry Parameter coverage - -* /lldp/interfaces/interface/neighbors/neighbor/state/chassis-id -* /lldp/interfaces/interface/neighbors/neighbor/state/chassis-id-subtype -* /lldp/interfaces/interface/neighbors/neighbor/state/port-id -* /lldp/interfaces/interface/neighbors/neighbor/state/port-id-subtype -* /lldp/interfaces/interface/neighbors/neighbor/state/system-name -* /lldp/interfaces/interface/state/name -* /lldp/state/chassis-id -* /lldp/state/chassis-id-type -* /lldp/state/system-name - -## Protocol/RPC Parameter coverage - -LLDP: - -* /lldp/config/enabled = true -* /lldp/interfaces/interface/config/enabled = true +## OpenConfig Path and RPC Coverage + +The below yaml defines the OC paths intended to be covered by this test. OC paths used for test setup are not listed here. + +```yaml +paths: + ## Config Paths ## + /lldp/config/enabled: + /lldp/interfaces/interface/config/enabled: + + ## State Paths ## + /lldp/interfaces/interface/neighbors/neighbor/state/chassis-id: + /lldp/interfaces/interface/neighbors/neighbor/state/port-id: + /lldp/interfaces/interface/neighbors/neighbor/state/system-name: + /lldp/interfaces/interface/state/name: + /lldp/state/chassis-id: + /lldp/state/chassis-id-type: + /lldp/state/system-name: + +rpcs: + gnmi: + gNMI.Get: + gNMI.Set: + +``` ## Minimum DUT platform requirement diff --git a/feature/lldp/otg_tests/core_lldp_tlv_population_test/core_lldp_tlv_population_test.go b/feature/lldp/otg_tests/core_lldp_tlv_population_test/core_lldp_tlv_population_test.go index 532595c9e28..e34e217dcd9 100644 --- a/feature/lldp/otg_tests/core_lldp_tlv_population_test/core_lldp_tlv_population_test.go +++ b/feature/lldp/otg_tests/core_lldp_tlv_population_test/core_lldp_tlv_population_test.go @@ -138,18 +138,21 @@ func TestLLDPDisabled(t *testing.T) { func configureDUT(t *testing.T, name string, lldpEnabled bool) (*ondatra.DUTDevice, *oc.Lldp) { node := ondatra.DUT(t, name) p := node.Port(t, portName) - lldp := gnmi.OC().Lldp() + d := &oc.Root{} + lldp := d.GetOrCreateLldp() + llint := lldp.GetOrCreateInterface(p.Name()) - gnmi.Replace(t, node, lldp.Enabled().Config(), lldpEnabled) + gnmi.Replace(t, node, gnmi.OC().Lldp().Enabled().Config(), lldpEnabled) if lldpEnabled { - gnmi.Replace(t, node, lldp.Interface(p.Name()).Enabled().Config(), lldpEnabled) + gnmi.Replace(t, node, gnmi.OC().Lldp().Interface(p.Name()).Config(), llint) } + if deviations.InterfaceEnabled(node) { gnmi.Replace(t, node, gnmi.OC().Interface(p.Name()).Enabled().Config(), true) } - return node, gnmi.Get(t, node, lldp.Config()) + return node, gnmi.Get(t, node, gnmi.OC().Lldp().Config()) } func configureATE(t *testing.T, otg *otg.OTG) gosnappi.Config { diff --git a/feature/p4rt/otg_tests/p4rt_daemon_failure_test/README.md b/feature/p4rt/otg_tests/p4rt_daemon_failure_test/README.md index c9ad228379e..4719f77f44b 100644 --- a/feature/p4rt/otg_tests/p4rt_daemon_failure_test/README.md +++ b/feature/p4rt/otg_tests/p4rt_daemon_failure_test/README.md @@ -23,13 +23,16 @@ Ensure that data plane traffic is not interrupted by P4RT daemon failure. test tables only configure the control plane traffic. Instead, this test configures the data plane using gRIBI. -## Protocol/RPC Parameter Coverage - -* gRIBI - * ModifyRequest - * GetRequest +## OpenConfig Path and RPC Coverage +```yaml +rpcs: + gribi: + gRIBI.Get: + gRIBI.Modify: + gRIBI.Flush: +``` ## Telemetry Parameter Coverage * /network-instances/network-instance/afts/ipv4-unicast/ipv4-entry/state/prefix/ * /interfaces/interface/state/id -* /interfaces/interface/state/name \ No newline at end of file +* /interfaces/interface/state/name diff --git a/feature/p4rt/otg_tests/p4rt_daemon_failure_test/p4rt_daemon_failure_test.go b/feature/p4rt/otg_tests/p4rt_daemon_failure_test/p4rt_daemon_failure_test.go index 239ea5ba306..e0b93542926 100644 --- a/feature/p4rt/otg_tests/p4rt_daemon_failure_test/p4rt_daemon_failure_test.go +++ b/feature/p4rt/otg_tests/p4rt_daemon_failure_test/p4rt_daemon_failure_test.go @@ -15,7 +15,6 @@ package p4rt_daemon_failure_test import ( - "context" "fmt" "testing" "time" @@ -24,6 +23,7 @@ import ( "github.com/openconfig/featureprofiles/internal/attrs" "github.com/openconfig/featureprofiles/internal/deviations" "github.com/openconfig/featureprofiles/internal/fptest" + "github.com/openconfig/featureprofiles/internal/gnoi" "github.com/openconfig/featureprofiles/internal/gribi" "github.com/openconfig/featureprofiles/internal/p4rtutils" "github.com/openconfig/gribigo/fluent" @@ -34,7 +34,6 @@ import ( "github.com/openconfig/ygot/ygot" gpb "github.com/openconfig/gnmi/proto/gnmi" - syspb "github.com/openconfig/gnoi/system" ) func TestMain(m *testing.M) { @@ -80,13 +79,6 @@ var ( IPv4: "192.0.2.6", IPv4Len: ipv4PrefixLen, } - - p4rtDaemons = map[ondatra.Vendor]string{ - ondatra.ARISTA: "P4Runtime", - ondatra.CISCO: "emsd", - ondatra.JUNIPER: "p4-switch", - ondatra.NOKIA: "sr_grpc_server", - } ) // configInterfaceDUT returns the OC Interface config for a given port. @@ -192,18 +184,6 @@ func startTraffic(t *testing.T, ate *ondatra.ATEDevice, top gosnappi.Config) gos return flow } -// pidByName uses telemetry to find out the PID of a process -func pidByName(t *testing.T, dut *ondatra.DUTDevice, process string) (uint64, error) { - t.Helper() - ps := gnmi.GetAll(t, dut, gnmi.OC().System().ProcessAny().State()) - for _, p := range ps { - if p.GetName() == process { - return p.GetPid(), nil - } - } - return 0, fmt.Errorf("could not find PID for process: %s", process) -} - func installRoutes(t *testing.T, dut *ondatra.DUTDevice) error { t.Helper() @@ -299,11 +279,6 @@ func subscribeOnChangeInterfaceName(t *testing.T, dut *ondatra.DUTDevice, p *ond func TestP4RTDaemonFailure(t *testing.T) { dut := ondatra.DUT(t, "dut") - p4rtD, ok := p4rtDaemons[dut.Vendor()] - if !ok { - t.Fatalf("Please add support for vendor %v in var p4rtDaemons", dut.Vendor()) - } - t.Logf("Configure DUT") configureDUT(t, dut) @@ -334,23 +309,7 @@ func TestP4RTDaemonFailure(t *testing.T) { flow := startTraffic(t, ate, top) - pID, err := pidByName(t, dut, p4rtD) - if err != nil { - t.Fatal(err) - } - - c := dut.RawAPIs().GNOI(t) - req := &syspb.KillProcessRequest{ - Name: p4rtD, - Pid: uint32(pID), - Signal: syspb.KillProcessRequest_SIGNAL_TERM, - Restart: true, - } - resp, err := c.System().KillProcess(context.Background(), req) - t.Logf("Got kill process response: %v", resp) - if err != nil { - t.Fatalf("FAIL: to execute gNOI.KillProcess, error received: %v", err) - } + gnoi.KillProcess(t, dut, gnoi.P4RT, false) // let traffic keep running for another 10 seconds. time.Sleep(10 * time.Second) diff --git a/feature/platform/fabric/otg_tests/sampled_backplane_capacity_counters_test/sampled_backplane_capacity_counters_test.go b/feature/platform/fabric/otg_tests/sampled_backplane_capacity_counters_test/sampled_backplane_capacity_counters_test.go index 3e7f39995df..33dcb791517 100644 --- a/feature/platform/fabric/otg_tests/sampled_backplane_capacity_counters_test/sampled_backplane_capacity_counters_test.go +++ b/feature/platform/fabric/otg_tests/sampled_backplane_capacity_counters_test/sampled_backplane_capacity_counters_test.go @@ -126,6 +126,11 @@ func TestOnChangeBackplaneCapacityCounters(t *testing.T) { fc := (len(fabrics) / 2) + 1 for _, f := range fabrics[:fc] { + empty, ok := gnmi.Lookup(t, dut, gnmi.OC().Component(f).Empty().State()).Val() + if ok && empty { + t.Logf("Fabric Component %s is empty, hence skipping", f) + continue + } gnmi.Replace(t, dut, gnmi.OC().Component(f).Fabric().PowerAdminState().Config(), oc.Platform_ComponentPowerType_POWER_DISABLED) gnmi.Await(t, dut, gnmi.OC().Component(f).Fabric().PowerAdminState().State(), time.Minute, oc.Platform_ComponentPowerType_POWER_DISABLED) } @@ -134,6 +139,11 @@ func TestOnChangeBackplaneCapacityCounters(t *testing.T) { ts2, tocs2, apct2 := getBackplaneCapacityCounters(t, dut, ics) for _, f := range fabrics[:fc] { + empty, ok := gnmi.Lookup(t, dut, gnmi.OC().Component(f).Empty().State()).Val() + if ok && empty { + t.Logf("Fabric Component %s is empty, hence skipping", f) + continue + } gnmi.Replace(t, dut, gnmi.OC().Component(f).Fabric().PowerAdminState().Config(), oc.Platform_ComponentPowerType_POWER_ENABLED) if deviations.MissingValueForDefaults(dut) { time.Sleep(time.Minute) diff --git a/feature/platform/integrated_circuit/otg_tests/utilization_test/metadata.textproto b/feature/platform/integrated_circuit/otg_tests/utilization_test/metadata.textproto index 1fe40a1b24b..45d28a4dcdf 100644 --- a/feature/platform/integrated_circuit/otg_tests/utilization_test/metadata.textproto +++ b/feature/platform/integrated_circuit/otg_tests/utilization_test/metadata.textproto @@ -17,4 +17,13 @@ platform_exceptions: { missing_hardware_resource_telemetry_before_config: true } } +platform_exceptions: { + platform: { + vendor: NOKIA + } + deviations: { + explicit_interface_in_default_vrf: true + interface_enabled: true + } +} tags: TAGS_TRANSIT diff --git a/feature/platform/integrated_circuit/otg_tests/utilization_test/utilization_test.go b/feature/platform/integrated_circuit/otg_tests/utilization_test/utilization_test.go index c0cbe08e166..db1719b5c3f 100644 --- a/feature/platform/integrated_circuit/otg_tests/utilization_test/utilization_test.go +++ b/feature/platform/integrated_circuit/otg_tests/utilization_test/utilization_test.go @@ -20,6 +20,7 @@ import ( "github.com/open-traffic-generator/snappi/gosnappi" "github.com/openconfig/featureprofiles/internal/attrs" + "github.com/openconfig/featureprofiles/internal/components" "github.com/openconfig/featureprofiles/internal/deviations" "github.com/openconfig/featureprofiles/internal/fptest" "github.com/openconfig/featureprofiles/internal/otgutils" @@ -45,6 +46,7 @@ const ( var ( fibResource = map[ondatra.Vendor]string{ ondatra.ARISTA: "Routing/Resource6", + ondatra.NOKIA: "ip-lpm-routes", } dutPort1 = attrs.Attributes{ Desc: "dutPort1", @@ -105,46 +107,22 @@ func TestResourceUtilization(t *testing.T) { otgV6Peer, otgPort1, otgConfig := configureOTG(t, otg) verifyBgpTelemetry(t, dut) - - val, ok := gnmi.Watch(t, dut, gnmi.OC().System().Utilization().Resource(fibResource[dut.Vendor()]).ActiveComponentList().State(), time.Minute, func(v *ygnmi.Value[[]string]) bool { - cs, present := v.Val() - return present && len(cs) > 0 - }).Await(t) - if !ok { - switch { - case deviations.MissingHardwareResourceTelemetryBeforeConfig(dut): - t.Log("FIB resource is not active in any available components") - default: - t.Fatalf("FIB resource is not active in any available components") - } - } - comps, _ := val.Val() - gnmi.Replace(t, dut, gnmi.OC().System().Utilization().Resource(fibResource[dut.Vendor()]).Config(), &oc.System_Utilization_Resource{ Name: ygot.String(fibResource[dut.Vendor()]), UsedThresholdUpper: ygot.Uint8(usedThresholdUpper), UsedThresholdUpperClear: ygot.Uint8(usedThresholdUpperClear), }) - - val, ok = gnmi.Watch(t, dut, gnmi.OC().System().Utilization().Resource(fibResource[dut.Vendor()]).ActiveComponentList().State(), time.Minute, func(v *ygnmi.Value[[]string]) bool { - cs, present := v.Val() - return present && len(cs) > 0 - }).Await(t) - if !ok { - t.Fatalf("FIB resource is not active in any available components") - } - comps, _ = val.Val() - + comps := components.FindActiveComponentsByType(t, dut, oc.PlatformTypes_OPENCONFIG_HARDWARE_COMPONENT_INTEGRATED_CIRCUIT) beforeUtzs := componentUtilizations(t, dut, comps) if len(beforeUtzs) != len(comps) { - t.Fatalf("Couldn't retrieve Utilization information for all Components in active-component-list") + t.Fatalf("Couldn't retrieve Utilization information for all Active Components") } injectBGPRoutes(t, otg, otgV6Peer, otgPort1, otgConfig) afterUtzs := componentUtilizations(t, dut, comps) if len(afterUtzs) != len(comps) { - t.Fatalf("Couldn't retrieve Utilization information for all Components in active-component-list") + t.Fatalf("Couldn't retrieve Utilization information for all Active Components") } t.Run("Utilization after BGP route installation", func(t *testing.T) { @@ -162,7 +140,7 @@ func TestResourceUtilization(t *testing.T) { afterClearUtzs := componentUtilizations(t, dut, comps) if len(afterClearUtzs) != len(comps) { - t.Fatalf("Couldn't retrieve Utilization information for all Components in active-component-list") + t.Fatalf("Couldn't retrieve Utilization information for all Active Components") } t.Run("Utilization after BGP route clear", func(t *testing.T) { diff --git a/feature/platform/tests/telemetry_inventory_test/metadata.textproto b/feature/platform/tests/telemetry_inventory_test/metadata.textproto index 2f00560c835..74c89711589 100644 --- a/feature/platform/tests/telemetry_inventory_test/metadata.textproto +++ b/feature/platform/tests/telemetry_inventory_test/metadata.textproto @@ -40,7 +40,6 @@ platform_exceptions: { vendor: NOKIA } deviations: { - backplane_facing_capacity_unsupported: true install_position_and_install_component_unsupported: true model_name_unsupported: true skip_controller_card_power_admin: true diff --git a/feature/qos/tests/qos_ecn_config_test/README.md b/feature/qos/tests/qos_ecn_config_test/README.md index 025b4b5a595..adb5a3f2d79 100644 --- a/feature/qos/tests/qos_ecn_config_test/README.md +++ b/feature/qos/tests/qos_ecn_config_test/README.md @@ -60,7 +60,7 @@ Verify QoS ECN feature configuration. * ECN * [TODO] qos/queue-management-profiles/queue-management-profile/wred/uniform/config/min-threshold-percent - * [TODO] qos/queue-management-profiles/queue-management-profile/wred/uniform/config/max-threshold-percent + * [TODO] qos/queue-management-profiles/queue-management-profile/wred/uniform/config/max-threshold-percent * qos/queue-management-profiles/queue-management-profile/wred/uniform/config/min-threshold * qos/queue-management-profiles/queue-management-profile/wred/uniform/config/max-threshold * qos/queue-management-profiles/queue-management-profile/wred/uniform/config/enable-ecn @@ -79,7 +79,7 @@ Verify QoS ECN feature configuration. * ECN * [TODO] qos/queue-management-profiles/queue-management-profile/wred/uniform/state/min-threshold-percent - * [TODO] qos/queue-management-profiles/queue-management-profile/wred/uniform/state/max-threshold-percent + * [TODO] qos/queue-management-profiles/queue-management-profile/wred/uniform/state/max-threshold-percent * qos/queue-management-profiles/queue-management-profile/wred/uniform/state/min-threshold * qos/queue-management-profiles/queue-management-profile/wred/uniform/state/max-threshold * qos/queue-management-profiles/queue-management-profile/wred/uniform/state/enable-ecn @@ -96,3 +96,39 @@ Verify QoS ECN feature configuration. ## platform * vRX + +## OpenConfig Path and RPC Coverage + +The below yaml defines the OC paths intended to be covered by this test. OC +paths used for test setup are not listed here. + +```yaml +paths: + ## Config paths + /qos/queue-management-profiles/queue-management-profile/wred/uniform/config/min-threshold: + /qos/queue-management-profiles/queue-management-profile/wred/uniform/config/max-threshold: + /qos/queue-management-profiles/queue-management-profile/wred/uniform/config/enable-ecn: + /qos/queue-management-profiles/queue-management-profile/wred/uniform/config/weight: + /qos/queue-management-profiles/queue-management-profile/wred/uniform/config/drop: + /qos/queue-management-profiles/queue-management-profile/wred/uniform/config/max-drop-probability-percent: + /qos/interfaces/interface/input/classifiers/classifier/config/name: + /qos/interfaces/interface/output/queues/queue/config/name: + /qos/interfaces/interface/output/queues/queue/config/queue-management-profile: + + ## State paths: + + /qos/queue-management-profiles/queue-management-profile/wred/uniform/state/min-threshold: + /qos/queue-management-profiles/queue-management-profile/wred/uniform/state/max-threshold: + /qos/queue-management-profiles/queue-management-profile/wred/uniform/state/enable-ecn: + /qos/queue-management-profiles/queue-management-profile/wred/uniform/state/weight: + /qos/queue-management-profiles/queue-management-profile/wred/uniform/state/drop: + /qos/queue-management-profiles/queue-management-profile/wred/uniform/state/max-drop-probability-percent: + /qos/interfaces/interface/input/classifiers/classifier/state/name: + /qos/interfaces/interface/output/queues/queue/state/name: + /qos/interfaces/interface/output/queues/queue/state/queue-management-profile: + +rpcs: + gnmi: + gNMI.Set: + Replace: +``` \ No newline at end of file diff --git a/feature/qos/tests/qos_ecn_config_test/metadata.textproto b/feature/qos/tests/qos_ecn_config_test/metadata.textproto index 729421003ce..2a2d548b8bb 100644 --- a/feature/qos/tests/qos_ecn_config_test/metadata.textproto +++ b/feature/qos/tests/qos_ecn_config_test/metadata.textproto @@ -9,10 +9,6 @@ platform_exceptions: { platform: { vendor: JUNIPER } - deviations: { - state_path_unsupported: true - drop_weight_leaves_unsupported: true - } } platform_exceptions: { platform: { diff --git a/feature/qos/tests/qos_ecn_config_test/qos_ecn_config_test.go b/feature/qos/tests/qos_ecn_config_test/qos_ecn_config_test.go index 0e9f12ffedf..ae94ee7fb04 100644 --- a/feature/qos/tests/qos_ecn_config_test/qos_ecn_config_test.go +++ b/feature/qos/tests/qos_ecn_config_test/qos_ecn_config_test.go @@ -302,46 +302,114 @@ func testQoSOutputIntfConfig(t *testing.T, q *oc.Qos) { dp := dut.Port(t, "port2") queues := netutil.CommonTrafficQueues(t, dut) + ecnConfig := struct { + ecnEnabled bool + dropEnabled bool + minThreshold uint64 + maxThreshold uint64 + maxDropProbabilityPercent uint8 + weight uint32 + }{ + ecnEnabled: true, + dropEnabled: false, + minThreshold: uint64(80000), + maxThreshold: uint64(80000), + maxDropProbabilityPercent: uint8(100), + weight: uint32(0), + } + + queueMgmtProfile := q.GetOrCreateQueueManagementProfile("DropProfile") + queueMgmtProfile.SetName("DropProfile") + wred := queueMgmtProfile.GetOrCreateWred() + uniform := wred.GetOrCreateUniform() + uniform.SetEnableEcn(ecnConfig.ecnEnabled) + uniform.SetDrop(ecnConfig.dropEnabled) + wantMinThreshold := ecnConfig.minThreshold + wantMaxThreshold := ecnConfig.maxThreshold + if deviations.EcnSameMinMaxThresholdUnsupported(dut) { + wantMinThreshold = CiscoMinThreshold + wantMaxThreshold = CiscoMaxThreshold + } + uniform.SetMinThreshold(wantMinThreshold) + uniform.SetMaxThreshold(wantMaxThreshold) + uniform.SetMaxDropProbabilityPercent(ecnConfig.maxDropProbabilityPercent) + if !deviations.QosSetWeightConfigUnsupported(dut) { + uniform.SetWeight(ecnConfig.weight) + } + cases := []struct { desc string queueName string ecnProfile string scheduler string + sequence uint32 + priority oc.E_Scheduler_Priority + inputID string + inputType oc.E_Input_InputType + weight uint64 }{{ desc: "output-interface-BE1", queueName: queues.BE1, ecnProfile: "DropProfile", scheduler: "scheduler", + sequence: uint32(1), + priority: oc.Scheduler_Priority_UNSET, + inputType: oc.Input_InputType_QUEUE, + weight: uint64(1), }, { desc: "output-interface-BE0", queueName: queues.BE0, ecnProfile: "DropProfile", scheduler: "scheduler", + sequence: uint32(1), + priority: oc.Scheduler_Priority_UNSET, + inputType: oc.Input_InputType_QUEUE, + weight: uint64(4), }, { desc: "output-interface-AF1", queueName: queues.AF1, ecnProfile: "DropProfile", scheduler: "scheduler", + sequence: uint32(1), + priority: oc.Scheduler_Priority_UNSET, + inputType: oc.Input_InputType_QUEUE, + weight: uint64(8), }, { desc: "output-interface-AF2", queueName: queues.AF2, ecnProfile: "DropProfile", scheduler: "scheduler", + sequence: uint32(1), + priority: oc.Scheduler_Priority_UNSET, + inputType: oc.Input_InputType_QUEUE, + weight: uint64(16), }, { desc: "output-interface-AF3", queueName: queues.AF3, ecnProfile: "DropProfile", scheduler: "scheduler", + sequence: uint32(1), + priority: oc.Scheduler_Priority_UNSET, + inputType: oc.Input_InputType_QUEUE, + weight: uint64(32), }, { desc: "output-interface-AF4", queueName: queues.AF4, ecnProfile: "DropProfile", scheduler: "scheduler", + sequence: uint32(0), + priority: oc.Scheduler_Priority_STRICT, + inputType: oc.Input_InputType_QUEUE, + weight: uint64(6), }, { desc: "output-interface-NC1", queueName: queues.NC1, ecnProfile: "DropProfile", scheduler: "scheduler", + sequence: uint32(0), + priority: oc.Scheduler_Priority_STRICT, + inputType: oc.Input_InputType_QUEUE, + weight: uint64(7), }} i := q.GetOrCreateInterface(dp.Name()) @@ -366,6 +434,14 @@ func testQoSOutputIntfConfig(t *testing.T, q *oc.Qos) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { qoscfg.SetForwardingGroup(t, dut, q, tc.queueName, tc.queueName) + s := schedulerPolicy.GetOrCreateScheduler(tc.sequence) + s.SetSequence(tc.sequence) + s.SetPriority(tc.priority) + input := s.GetOrCreateInput(tc.queueName) + input.SetId(tc.queueName) + input.SetInputType(tc.inputType) + input.SetQueue(tc.queueName) + input.SetWeight(tc.weight) output := i.GetOrCreateOutput() schedulerPolicy := output.GetOrCreateSchedulerPolicy() schedulerPolicy.SetName(tc.scheduler) diff --git a/internal/components/components.go b/internal/components/components.go index a3d6b90a304..6878df539d0 100644 --- a/internal/components/components.go +++ b/internal/components/components.go @@ -58,6 +58,28 @@ func FindComponentsByType(t *testing.T, dut *ondatra.DUTDevice, cType oc.E_Platf return s } +// FindActiveComponentsByType finds the list of active components based on hardware type. +func FindActiveComponentsByType(t *testing.T, dut *ondatra.DUTDevice, cType oc.E_PlatformTypes_OPENCONFIG_HARDWARE_COMPONENT) []string { + components := gnmi.GetAll[*oc.Component](t, dut, gnmi.OC().ComponentAny().State()) + var s []string + for _, c := range components { + if c.GetType() == nil { + t.Logf("Component %s type is missing from telemetry", c.GetName()) + continue + } + t.Logf("Component %s has type: %v", c.GetName(), c.GetType()) + switch v := c.GetType().(type) { + case oc.E_PlatformTypes_OPENCONFIG_HARDWARE_COMPONENT: + if v == cType && c.OperStatus == oc.PlatformTypes_COMPONENT_OPER_STATUS_ACTIVE { + s = append(s, c.GetName()) + } + default: + t.Logf("Detected non-hardware component: (%T, %v)", c.GetType(), c.GetType()) + } + } + return s +} + // FindSWComponentsByType finds the list of SW components based on a type. func FindSWComponentsByType(t *testing.T, dut *ondatra.DUTDevice, cType oc.E_PlatformTypes_OPENCONFIG_SOFTWARE_COMPONENT) []string { components := gnmi.GetAll[*oc.Component](t, dut, gnmi.OC().ComponentAny().State()) diff --git a/internal/gnoi/gnoi.go b/internal/gnoi/gnoi.go new file mode 100644 index 00000000000..f308fb956d0 --- /dev/null +++ b/internal/gnoi/gnoi.go @@ -0,0 +1,124 @@ +// Copyright 2024 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package gnoi provides utilities for interacting with the gNOI API. +package gnoi + +import ( + "context" + "fmt" + "testing" + "time" + + "github.com/openconfig/featureprofiles/internal/system" + gpb "github.com/openconfig/gnmi/proto/gnmi" + spb "github.com/openconfig/gnoi/system" + "github.com/openconfig/ondatra" + "github.com/openconfig/ondatra/gnmi" + "github.com/openconfig/ondatra/gnmi/oc" + "github.com/openconfig/ygnmi/ygnmi" +) + +var ( + daemonProcessNames = map[ondatra.Vendor]map[Daemon]string{ + ondatra.ARISTA: { + GRIBI: "Gribi", + OCAGENT: "Octa", + P4RT: "P4Runtime", + ROUTING: "Bgp-main", + }, + ondatra.CISCO: { + GRIBI: "emsd", + P4RT: "emsd", + ROUTING: "emsd", + }, + ondatra.JUNIPER: { + GRIBI: "rpd", + P4RT: "p4-switch", + ROUTING: "rpd", + }, + ondatra.NOKIA: { + GRIBI: "sr_grpc_server", + OCAGENT: "oc_mgmt_server", + P4RT: "sr_grpc_server", + ROUTING: "sr_bgp_mgr", + }, + } +) + +// Daemon is the type of the daemon on the device. +type Daemon string + +const ( + // GRIBI is the gRIBI daemon. + GRIBI Daemon = "GRIBI" + // OCAGENT is the OpenConfig agent daemon. + OCAGENT Daemon = "OCAGENT" + // P4RT is the P4RT daemon. + P4RT Daemon = "P4RT" + // ROUTING is the routing daemon. + ROUTING Daemon = "ROUTING" +) + +// KillProcess terminates the daemon on the DUT. +func KillProcess(t *testing.T, dut *ondatra.DUTDevice, daemon Daemon, waitForRestart bool) { + t.Helper() + + daemonName, err := FetchProcessName(dut, daemon) + if err != nil { + t.Fatalf("Daemon %s not defined for vendor %s", daemon, dut.Vendor().String()) + } + pid := system.FindProcessIDByName(t, dut, daemonName) + if pid == 0 { + t.Fatalf("process %s not found on device", daemonName) + } + + gnoiClient := dut.RawAPIs().GNOI(t) + killProcessRequest := &spb.KillProcessRequest{ + Signal: spb.KillProcessRequest_SIGNAL_KILL, + Name: daemonName, + Pid: uint32(pid), + Restart: true, + } + gnoiClient.System().KillProcess(context.Background(), killProcessRequest) + + if waitForRestart { + gnmi.WatchAll( + t, + dut.GNMIOpts().WithYGNMIOpts(ygnmi.WithSubscriptionMode(gpb.SubscriptionMode_ON_CHANGE)), + gnmi.OC().System().ProcessAny().State(), + time.Minute, + func(p *ygnmi.Value[*oc.System_Process]) bool { + val, ok := p.Val() + if !ok { + return false + } + return val.GetName() == daemonName && val.GetPid() != pid + }, + ) + } +} + +// FetchProcessName returns the name of the daemon on the DUT based on the vendor. +func FetchProcessName(dut *ondatra.DUTDevice, daemon Daemon) (string, error) { + daemons, ok := daemonProcessNames[dut.Vendor()] + if !ok { + return "", fmt.Errorf("unsupported vendor: %s", dut.Vendor().String()) + } + d, ok := daemons[daemon] + if !ok { + return "", fmt.Errorf("daemon %s not defined for vendor %s", daemon, dut.Vendor().String()) + } + return d, nil +} diff --git a/internal/system/system.go b/internal/system/system.go new file mode 100644 index 00000000000..d21116e2750 --- /dev/null +++ b/internal/system/system.go @@ -0,0 +1,39 @@ +// Copyright 2024 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package system provides helper functions for gNMI system related operations. +package system + +import ( + "testing" + + "github.com/openconfig/ondatra" + "github.com/openconfig/ondatra/gnmi" + "github.com/openconfig/ondatra/gnmi/oc" +) + +// FindProcessIDByName uses telemetry to find out the PID of a process. +func FindProcessIDByName(t *testing.T, dut *ondatra.DUTDevice, pName string) uint64 { + t.Helper() + + var pid uint64 + pList := gnmi.GetAll[*oc.System_Process](t, dut, gnmi.OC().System().ProcessAny().State()) + for _, proc := range pList { + if proc.GetName() == pName { + pid = proc.GetPid() + break + } + } + return pid +}