diff --git a/.github/workflows/readme_oc_path_and_rpc.yml b/.github/workflows/readme_oc_path_and_rpc.yml index c9912c8c76d..1721090ed53 100644 --- a/.github/workflows/readme_oc_path_and_rpc.yml +++ b/.github/workflows/readme_oc_path_and_rpc.yml @@ -65,18 +65,27 @@ jobs: if [ ! -z "${HEAD}" ]; then readonly BASE="$(git merge-base origin/main "${HEAD}")" - echo "########## Changed READMEs to be validated:" - git diff --name-only "${BASE}" "${HEAD}" | grep -E '^\W*feature' | grep -E 'README.md$' | sort + affected_readmes=() + for f in $(git diff --name-only "${BASE}" "${HEAD}" | grep -E '^\W*feature' | xargs -r dirname | sort -u | sed 's/$/\/README.md/'); do + if [ -f "$f" ]; then + affected_readmes+=("$f") + fi + done - echo "########## Validating Changed READMEs:" - git diff --name-only "${BASE}" "${HEAD}" | grep -E '^\W*feature' | grep -E 'README.md$' | sort | xargs validate_readme_spec --alsologtostderr "${exemption_flags[@]}" + echo "########## READMEs in changed directories to be validated (including ones to be exempted):" + printf '%s\n' "${affected_readmes[@]}" + + echo "########## Validating READMEs in changed directories:" + for f in "${affected_readmes[@]}"; do + validate_readme_spec --alsologtostderr "${exemption_flags[@]}" "${f}" + done fi ##### END: Validate Changed Test READMEs ##### echo "########## Validating already-converted READMEs:" validate feature/aft - validate feature/bgp/policybase/otg_tests/import_export_multi + validate feature/bgp/policybase/otg_tests/import_export_multi_test validate feature/gnmi validate feature/gnoi validate feature/isis diff --git a/feature/aft/aft_summary/otg_tests/route_summary_counters_test/route_summary_counters_test.go b/feature/aft/aft_summary/otg_tests/route_summary_counters_test/route_summary_counters_test.go index 6d8a28e7880..e0a77d6d5e1 100644 --- a/feature/aft/aft_summary/otg_tests/route_summary_counters_test/route_summary_counters_test.go +++ b/feature/aft/aft_summary/otg_tests/route_summary_counters_test/route_summary_counters_test.go @@ -131,14 +131,12 @@ func TestRouteSummaryWithISIS(t *testing.T) { }).Await(t) dni := deviations.DefaultNetworkInstance(ts.DUT) - ipv4Entry := gnmi.Get(t, ts.DUT, gnmi.OC().NetworkInstance(dni).Afts().AftSummaries().Ipv4Unicast().Protocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_ISIS).Counters().AftEntries().State()) - if ipv4Entry == 0 { - t.Errorf("ipv4 BGP entries, got: %d, want: %d", ipv4Entry, prefixesCount) + if got, ok := gnmi.Await(t, ts.DUT, gnmi.OC().NetworkInstance(dni).Afts().AftSummaries().Ipv4Unicast().Protocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_ISIS).Counters().AftEntries().State(), 1*time.Minute, uint64(prefixesCount)).Val(); !ok { + t.Errorf("ipv4 isis entries, got: %d, want: %d", got, prefixesCount) } - ipv6Entry := gnmi.Get(t, ts.DUT, gnmi.OC().NetworkInstance(dni).Afts().AftSummaries().Ipv6Unicast().Protocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_ISIS).Counters().AftEntries().State()) - if ipv6Entry == 0 { - t.Errorf("ipv6 BGP entries, got: %d, want: %d", ipv6Entry, prefixesCount) + if got, ok := gnmi.Await(t, ts.DUT, gnmi.OC().NetworkInstance(dni).Afts().AftSummaries().Ipv6Unicast().Protocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_ISIS).Counters().AftEntries().State(), 1*time.Minute, uint64(prefixesCount)).Val(); !ok { + t.Errorf("ipv6 isis entries, got: %d, want: %d", got, prefixesCount) } } @@ -218,14 +216,12 @@ func TestRouteSummaryWithBGP(t *testing.T) { dni := deviations.DefaultNetworkInstance(dut) if tc.dut.ipv4 { - ipv4Entry := gnmi.Get(t, dut, gnmi.OC().NetworkInstance(dni).Afts().AftSummaries().Ipv4Unicast().Protocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_BGP).Counters().AftEntries().State()) - if ipv4Entry == 0 { - t.Errorf("ipv4 BGP entries, got: %d, want: %d", ipv4Entry, prefixesCount) + if got, ok := gnmi.Await(t, dut, gnmi.OC().NetworkInstance(dni).Afts().AftSummaries().Ipv4Unicast().Protocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_BGP).Counters().AftEntries().State(), 1*time.Minute, uint64(prefixesCount)).Val(); !ok { + t.Errorf("ipv4 BGP entries, got: %d, want: %d", got, prefixesCount) } } else { - ipv6Entry := gnmi.Get(t, dut, gnmi.OC().NetworkInstance(dni).Afts().AftSummaries().Ipv6Unicast().Protocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_BGP).Counters().AftEntries().State()) - if ipv6Entry == 0 { - t.Errorf("ipv4 BGP entries, got: %d, want: %d", ipv6Entry, prefixesCount) + if got, ok := gnmi.Await(t, dut, gnmi.OC().NetworkInstance(dni).Afts().AftSummaries().Ipv6Unicast().Protocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_BGP).Counters().AftEntries().State(), 1*time.Minute, uint64(prefixesCount)).Val(); !ok { + t.Errorf("ipv4 BGP entries, got: %d, want: %d", got, prefixesCount) } } }) diff --git a/feature/bgp/bgp_session_mode_configuration_test/README.md b/feature/bgp/bgp_session_mode_configuration_test/README.md new file mode 100644 index 00000000000..bba3cecb4d8 --- /dev/null +++ b/feature/bgp/bgp_session_mode_configuration_test/README.md @@ -0,0 +1,46 @@ +# RT-1.55: BGP session mode (active/passive) + +## Summary + +* Validate the correct behavior of BGP session establishment in both active and passive modes. +* Verify the accurate reflection of BGP transport mode in telemetry output. +* Confirm the functionality of passive mode configuration at both the neighbor and peer group levels. + +## Topology + +DUT Port1 (AS 65501) ---eBGP --- ATE Port1 (AS 65502) + +## Procedure + +* Configure both DUT and ATE to operate in BGP passive mode under the neighbor section. +* Verify that the BGP adjacency will not be established. +* Verify the telemetry path output to confirm that the neighbor's BGP transport mode is displayed as "passive for the DUT. +* Configure BGP session on ATE to operate in BGP active mode when interacting with DUT. +* Verify that a BGP adjacency is established between the ATE and DUT +* Verify the telemetry path output to confirm that the neighbor's BGP transport mode is displayed as "passive for the DUT. +* Redo the same above steps but configure the passive mode under the peer group instead of the bgp neighbor configuration. + +## OpenConfig Path and RPC Coverage + +This example yaml defines the OC paths intended to be covered by this test. OC paths used for test environment setup are not required to be listed here. + +```yaml +paths: + ## Config paths + /network-instances/network-instance/protocols/protocol/bgp/neighbors/neighbor/transport/config/passive-mode: + /network-instances/network-instance/protocols/protocol/bgp/peer-groups/peer-group/transport/config/passive-mode: + + ## State paths + /network-instances/network-instance/protocols/protocol/bgp/neighbors/neighbor/transport/state/passive-mode: + /network-instances/network-instance/protocols/protocol/bgp/peer-groups/peer-group/transport/state/passive-mode: + +rpcs: + gnmi: + gNMI.Set: + gNMI.Subscribe: +``` + +## Minimum DUT platform requirement + +* MFF - A modular form factor device containing LINECARDs, FABRIC and redundant CONTROLLER_CARD components +* FFF - fixed form factor diff --git a/feature/bgp/multipath/otg_tests/bgp_multipath_ecmp_test/README.md b/feature/bgp/multipath/otg_tests/bgp_multipath_ecmp_test/README.md index d45409e06bd..3c7f70a4789 100644 --- a/feature/bgp/multipath/otg_tests/bgp_multipath_ecmp_test/README.md +++ b/feature/bgp/multipath/otg_tests/bgp_multipath_ecmp_test/README.md @@ -82,11 +82,16 @@ Validate BGP in multipath scenario * /network-instances/network-instance/afts/next-hop-groups/next-hop-group[id=]/state * /network-instances/network-instance/afts/next-hop-groups/next-hop-group/next-hops -## Protocol/RPC Parameter Coverage +## OpenConfig Path and RPC Coverage -* gNMI - * Set - * Subscribe + +```yaml +rpcs: + gnmi: + gNMI.Get: + gNMI.Subscribe: + +``` ## Required DUT platform diff --git a/feature/bgp/multipath/otg_tests/bgp_multipath_ecmp_test/bgp_multipath_ecmp_test.go b/feature/bgp/multipath/otg_tests/bgp_multipath_ecmp_test/bgp_multipath_ecmp_test.go index 9af13da3fdd..379fd737c60 100644 --- a/feature/bgp/multipath/otg_tests/bgp_multipath_ecmp_test/bgp_multipath_ecmp_test.go +++ b/feature/bgp/multipath/otg_tests/bgp_multipath_ecmp_test/bgp_multipath_ecmp_test.go @@ -20,6 +20,8 @@ import ( "testing" "time" + "math/rand" + "github.com/open-traffic-generator/snappi/gosnappi" "github.com/openconfig/featureprofiles/internal/cfgplugins" "github.com/openconfig/featureprofiles/internal/deviations" @@ -37,8 +39,8 @@ const ( prefixesCount = 4 pathID = 1 maxPaths = 2 - trafficPps = 1000 - totalPackets = 120000 + trafficPps = 100000 + totalPackets = 12000000 lossTolerancePct = 0 lbToleranceFms = 20 ) @@ -69,10 +71,24 @@ func configureOTG(t *testing.T, bs *cfgplugins.BGPSession) { bgp4PeerRoute.AddPath().SetPathId(pathID) } - configureFlow(bs) + configureFlow(t, bs) +} + +func randRange(t *testing.T, start, end uint32, count int) []uint32 { + if count > int(end-start) { + t.Fatal("randRange: count greater than end-start.") + } + rand.New(rand.NewSource(time.Now().UnixNano())) + var result []uint32 + for len(result) < count { + diff := end - start + randomValue := rand.Int31n(int32(diff)) + int32(start) + result = append(result, uint32(randomValue)) + } + return result } -func configureFlow(bs *cfgplugins.BGPSession) { +func configureFlow(t *testing.T, bs *cfgplugins.BGPSession) { bs.ATETop.Flows().Clear() var rxNames []string @@ -91,6 +107,11 @@ func configureFlow(bs *cfgplugins.BGPSession) { e := flow.Packet().Add().Ethernet() e.Src().SetValue(bs.ATEPorts[0].MAC) v4 := flow.Packet().Add().Ipv4() + v4.Src().Increment().SetStart(bs.ATEPorts[0].IPv4).SetCount(prefixesCount) + v4.Dst().Increment().SetStart(prefixesStart).SetCount(prefixesCount) + udp := flow.Packet().Add().Udp() + udp.SrcPort().SetValues(randRange(t, 34525, 65535, 500)) + udp.DstPort().SetValues(randRange(t, 49152, 65535, 500)) v4.Src().SetValue(bs.ATEPorts[0].IPv4) v4.Dst().SetValue(prefixesStart) } @@ -174,15 +195,22 @@ func TestBGPSetup(t *testing.T) { gEBGP := bgp.GetOrCreateGlobal().GetOrCreateAfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV4_UNICAST).GetOrCreateUseMultiplePaths().GetOrCreateEbgp() pgUseMulitplePaths := bgp.GetOrCreatePeerGroup(cfgplugins.BGPPeerGroup1).GetOrCreateAfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV4_UNICAST).GetOrCreateUseMultiplePaths() if tc.enableMultipath { + t.Logf("Enable Multipath") pgUseMulitplePaths.Enabled = ygot.Bool(true) + t.Logf("Enable Maximum Paths") gEBGP.MaximumPaths = ygot.Uint32(maxPaths) } - if tc.enableMultiAS && !deviations.SkipSettingAllowMultipleAS(bs.DUT) { + if tc.enableMultiAS && !deviations.SkipSettingAllowMultipleAS(bs.DUT) && deviations.SkipAfiSafiPathForBgpMultipleAs(bs.DUT) { + t.Logf("Enable MultiAS ") + gEBGP := bgp.GetOrCreateGlobal().GetOrCreateUseMultiplePaths().GetOrCreateEbgp() + gEBGP.AllowMultipleAs = ygot.Bool(true) + } + if tc.enableMultiAS && !deviations.SkipSettingAllowMultipleAS(bs.DUT) && !deviations.SkipAfiSafiPathForBgpMultipleAs(bs.DUT) { + t.Logf("Enable MultiAS ") gEBGP.AllowMultipleAs = ygot.Bool(true) } configureOTG(t, bs) - bs.PushAndStart(t) t.Logf("Verify DUT BGP sessions up") diff --git a/feature/bgp/multipath/otg_tests/bgp_multipath_ecmp_test/metadata.textproto b/feature/bgp/multipath/otg_tests/bgp_multipath_ecmp_test/metadata.textproto index fee5c2c5594..c765fa5bd69 100644 --- a/feature/bgp/multipath/otg_tests/bgp_multipath_ecmp_test/metadata.textproto +++ b/feature/bgp/multipath/otg_tests/bgp_multipath_ecmp_test/metadata.textproto @@ -11,6 +11,7 @@ platform_exceptions: { } deviations: { ipv4_missing_enabled: true + skip_afi_safi_path_for_bgp_multiple_as: true } } platform_exceptions: { @@ -37,3 +38,4 @@ platform_exceptions: { } } tags: TAGS_DATACENTER_EDGE + diff --git a/feature/bgp/multipath/otg_tests/bgp_multipath_wecmp_lbw_community_test/bgp_multipath_wecmp_test.go b/feature/bgp/multipath/otg_tests/bgp_multipath_wecmp_lbw_community_test/bgp_multipath_wecmp_test.go index a83268751d1..aefb43d7c3a 100644 --- a/feature/bgp/multipath/otg_tests/bgp_multipath_wecmp_lbw_community_test/bgp_multipath_wecmp_test.go +++ b/feature/bgp/multipath/otg_tests/bgp_multipath_wecmp_lbw_community_test/bgp_multipath_wecmp_test.go @@ -69,7 +69,7 @@ func configureOTG(t *testing.T, bs *cfgplugins.BGPSession) { routeAddress.SetPrefix(prefixP4Len) routeAddress.SetCount(prefixesCount) bgp4PeerRoute.AddPath().SetPathId(pathID) - bgp4PeerRoute.ExtendedCommunities().Items()[0].NonTransitive2OctetAsType().LinkBandwidthSubtype().SetBandwidth(float32(linkBw[i-2] * 1000)) + bgp4PeerRoute.ExtendedCommunities().Add().NonTransitive2OctetAsType().LinkBandwidthSubtype().SetBandwidth(float32(linkBw[i-2] * 1000)) } configureFlow(bs) diff --git a/feature/bgp/policybase/otg_tests/chained_policies_test/README.md b/feature/bgp/policybase/otg_tests/chained_policies_test/README.md index eab34543721..4134cc9d86c 100644 --- a/feature/bgp/policybase/otg_tests/chained_policies_test/README.md +++ b/feature/bgp/policybase/otg_tests/chained_policies_test/README.md @@ -256,11 +256,15 @@ For each section of configuration below, prepare a gnmi.SetBatch with all the c * /network-instances/network-instance/protocols/protocol/bgp/rib/afi-safis/afi-safi/ipv4-unicast/loc-rib/routes/route/prefix * /network-instances/network-instance/protocols/protocol/bgp/rib/attr-sets/attr-set/state/med -## Protocol/RPC Parameter Coverage -* gNMI - * Subscribe (ONCE) - * Set (REPLACE) +## OpenConfig Path and RPC Coverage +```yaml +rpcs: + gnmi: + gNMI.Get: + gNMI.Subscribe: + +``` ## Required DUT platform diff --git a/feature/bgp/policybase/otg_tests/chained_policies_test/chained_policies_test.go b/feature/bgp/policybase/otg_tests/chained_policies_test/chained_policies_test.go index a1d1d75183c..2f388556041 100644 --- a/feature/bgp/policybase/otg_tests/chained_policies_test/chained_policies_test.go +++ b/feature/bgp/policybase/otg_tests/chained_policies_test/chained_policies_test.go @@ -17,6 +17,7 @@ package chained_policies_test import ( "fmt" "net" + "strings" "testing" "time" @@ -33,8 +34,6 @@ import ( "github.com/openconfig/ygot/ygot" ) -// go through OKRs - const ( ipv4PrefixLen = 30 ipv6PrefixLen = 126 @@ -263,23 +262,32 @@ func configureImportRoutingPolicy(t *testing.T, dut *ondatra.DUTDevice, operatio } stmt2.GetOrCreateActions().SetPolicyResult(oc.RoutingPolicy_PolicyResultType_ACCEPT_ROUTE) stmt2.GetOrCreateActions().GetOrCreateBgpActions().SetSetLocalPref(localPref) - if operation == "set" { - gnmi.BatchReplace(batch, gnmi.OC().RoutingPolicy().Config(), rp) - } else if operation == "delete" { - gnmi.BatchDelete(batch, gnmi.OC().RoutingPolicy().Config()) + if deviations.SkipSettingStatementForPolicy(dut) { + gnmi.Update(t, dut, gnmi.OC().RoutingPolicy().Config(), rp) + } else { + if operation == "set" { + gnmi.BatchReplace(batch, gnmi.OC().RoutingPolicy().Config(), rp) + } else if operation == "delete" { + gnmi.BatchDelete(batch, gnmi.OC().RoutingPolicy().Config()) + } } - dni := deviations.DefaultNetworkInstance(dut) path := gnmi.OC().NetworkInstance(dni).Protocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_BGP, bgpName).Bgp().Neighbor(atePort1.IPv4).AfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV4_UNICAST).ApplyPolicy() policy := root.GetOrCreateNetworkInstance(dni).GetOrCreateProtocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_BGP, bgpName).GetOrCreateBgp().GetOrCreateNeighbor(atePort1.IPv4).GetOrCreateAfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV4_UNICAST).GetOrCreateApplyPolicy() - policy.SetDefaultImportPolicy(oc.RoutingPolicy_DefaultPolicyType_REJECT_ROUTE) + if !deviations.DefaultImportExportPolicy(dut) { + policy.SetDefaultImportPolicy(oc.RoutingPolicy_DefaultPolicyType_REJECT_ROUTE) + } policy.SetImportPolicy([]string{v4PrefixPolicy, v4LPPolicy}) - if operation == "set" { - gnmi.BatchReplace(batch, path.Config(), policy) - } else if operation == "delete" { - gnmi.BatchDelete(batch, path.Config()) + if deviations.SkipSettingStatementForPolicy(dut) { + gnmi.Update(t, dut, path.Config(), policy) + } else { + if operation == "set" { + gnmi.BatchReplace(batch, path.Config(), policy) + } else if operation == "delete" { + gnmi.BatchDelete(batch, path.Config()) + } + batch.Set(t, dut) } - batch.Set(t, dut) } func validateImportRoutingPolicy(t *testing.T, dut *ondatra.DUTDevice, ate *ondatra.ATEDevice) { @@ -287,23 +295,41 @@ func validateImportRoutingPolicy(t *testing.T, dut *ondatra.DUTDevice, ate *onda path := gnmi.OC().NetworkInstance(dni).Protocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_BGP, bgpName).Bgp().Neighbor(atePort1.IPv4).AfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV4_UNICAST).ApplyPolicy() policy := gnmi.Get[*oc.NetworkInstance_Protocol_Bgp_Neighbor_AfiSafi_ApplyPolicy](t, dut, path.State()) importPolicies := policy.GetImportPolicy() - if len(importPolicies) != 2 { - t.Errorf("ImportPolicy = %v, want %v", importPolicies, []string{v4PrefixPolicy, v4LPPolicy}) + if !deviations.FlattenPolicyWithMultipleStatements(dut) { + if len(importPolicies) != 2 { + t.Errorf("ImportPolicy = %v, want %v", importPolicies, []string{v4PrefixPolicy, v4LPPolicy}) + } } - if !deviations.BGPRibOcPathUnsupported(dut) { bgpRIBPath := gnmi.OC().NetworkInstance(dni).Protocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_BGP, bgpName).Bgp().Rib() locRib := gnmi.Get[*oc.NetworkInstance_Protocol_Bgp_Rib_AfiSafi_Ipv4Unicast_LocRib](t, dut, bgpRIBPath.AfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV4_UNICAST).Ipv4Unicast().LocRib().State()) found := false for k, lr := range locRib.Route { - if lr.GetPrefix() == advertisedIPv41.address { + prefixAddr := strings.Split(lr.GetPrefix(), "/") + t.Logf("Route: %v, lr.GetPrefix() -> %v, advertisedIPv41.address: %s, prefixAddr[0]: %s", k, lr.GetPrefix(), advertisedIPv41.address, prefixAddr[0]) + if prefixAddr[0] == advertisedIPv41.address { found = true - t.Logf("Found Route(prefix %s, origin: %v, pathid: %d) => %s", k.Prefix, k.Origin, k.PathId, lr.GetPrefix()) - attrSet := gnmi.Get[*oc.NetworkInstance_Protocol_Bgp_Rib_AttrSet](t, dut, bgpRIBPath.AttrSet(lr.GetAttrIndex()).State()) - if attrSet == nil || attrSet.GetLocalPref() != localPref { - t.Errorf("No local pref found for prefix %s", advertisedIPv41.address) + if !deviations.SkipCheckingAttributeIndex(dut) { + t.Logf("Found Route(prefix %s, origin: %v, pathid: %d) => %s", k.Prefix, k.Origin, k.PathId, lr.GetPrefix()) + attrSet := gnmi.Get[*oc.NetworkInstance_Protocol_Bgp_Rib_AttrSet](t, dut, bgpRIBPath.AttrSet(lr.GetAttrIndex()).State()) + if attrSet == nil || attrSet.GetLocalPref() != localPref { + t.Errorf("No local pref found for prefix %s", advertisedIPv41.address) + } + break + } else { + attrSetList := gnmi.GetAll[*oc.NetworkInstance_Protocol_Bgp_Rib_AttrSet](t, dut, bgpRIBPath.AttrSetAny().State()) + foundLP := false + for _, attrSet := range attrSetList { + if attrSet.GetLocalPref() == localPref { + foundLP = true + t.Logf("Found local pref %d for prefix %s", attrSet.GetLocalPref(), advertisedIPv41.address) + break + } + } + if !foundLP { + t.Errorf("No local pref found for prefix %s", advertisedIPv41.address) + } } - break } } @@ -324,30 +350,55 @@ func configureExportRoutingPolicy(t *testing.T, dut *ondatra.DUTDevice, operatio } stmt1.GetOrCreateActions().GetOrCreateBgpActions().GetOrCreateSetAsPathPrepend().SetAsn(dutAS) - pdef2 := rp.GetOrCreatePolicyDefinition(v4MedPolicy) - stmt2, err := pdef2.AppendNewStatement(v4MedStatement) - if err != nil { - t.Fatalf("AppendNewStatement(%s) failed: %v", v4MedStatement, err) + if deviations.FlattenPolicyWithMultipleStatements(dut) { + stmt2, err := pdef1.AppendNewStatement(v4MedStatement) + stmt2.GetOrCreateActions().SetPolicyResult(oc.RoutingPolicy_PolicyResultType_ACCEPT_ROUTE) + stmt2.GetOrCreateActions().GetOrCreateBgpActions().SetSetMed(oc.UnionUint32(med)) + if err != nil { + t.Fatalf("AppendNewStatement(%s) failed: %v", v4MedStatement, err) + } + } else { + pdef2 := rp.GetOrCreatePolicyDefinition(v4MedPolicy) + stmt2, err := pdef2.AppendNewStatement(v4MedStatement) + stmt2.GetOrCreateActions().SetPolicyResult(oc.RoutingPolicy_PolicyResultType_ACCEPT_ROUTE) + stmt2.GetOrCreateActions().GetOrCreateBgpActions().SetSetMed(oc.UnionUint32(med)) + if err != nil { + t.Fatalf("AppendNewStatement(%s) failed: %v", v4MedStatement, err) + } } - stmt2.GetOrCreateActions().SetPolicyResult(oc.RoutingPolicy_PolicyResultType_ACCEPT_ROUTE) - stmt2.GetOrCreateActions().GetOrCreateBgpActions().SetSetMed(oc.UnionUint32(med)) - if operation == "set" { - gnmi.BatchReplace(batch, gnmi.OC().RoutingPolicy().Config(), rp) - } else if operation == "delete" { - gnmi.BatchDelete(batch, gnmi.OC().RoutingPolicy().Config()) + + if deviations.SkipSettingStatementForPolicy(dut) { + gnmi.Update(t, dut, gnmi.OC().RoutingPolicy().Config(), rp) + } else { + if operation == "set" { + gnmi.BatchReplace(batch, gnmi.OC().RoutingPolicy().Config(), rp) + } else if operation == "delete" { + gnmi.BatchDelete(batch, gnmi.OC().RoutingPolicy().Config()) + } } dni := deviations.DefaultNetworkInstance(dut) path := gnmi.OC().NetworkInstance(dni).Protocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_BGP, bgpName).Bgp().Neighbor(atePort1.IPv4).AfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV4_UNICAST).ApplyPolicy() policy := root.GetOrCreateNetworkInstance(dni).GetOrCreateProtocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_BGP, bgpName).GetOrCreateBgp().GetOrCreateNeighbor(atePort1.IPv4).GetOrCreateAfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV4_UNICAST).GetOrCreateApplyPolicy() - policy.SetDefaultExportPolicy(oc.RoutingPolicy_DefaultPolicyType_REJECT_ROUTE) - policy.SetExportPolicy([]string{v4ASPPolicy, v4MedPolicy}) - if operation == "set" { - gnmi.BatchReplace(batch, path.Config(), policy) - } else if operation == "delete" { - gnmi.BatchDelete(batch, path.Config()) - } - batch.Set(t, dut) + if !deviations.DefaultImportExportPolicy(dut) { + policy.SetDefaultExportPolicy(oc.RoutingPolicy_DefaultPolicyType_REJECT_ROUTE) + } + if deviations.FlattenPolicyWithMultipleStatements(dut) { + policy.SetExportPolicy([]string{v4ASPPolicy}) + } else { + policy.SetExportPolicy([]string{v4ASPPolicy, v4MedPolicy}) + } + if deviations.SkipSettingStatementForPolicy(dut) { + gnmi.Update(t, dut, path.Config(), policy) + } else { + if operation == "set" { + gnmi.BatchReplace(batch, path.Config(), policy) + } else if operation == "delete" { + gnmi.BatchDelete(batch, path.Config()) + } + batch.Set(t, dut) + } + time.Sleep(time.Second * 60) } func validateExportRoutingPolicy(t *testing.T, dut *ondatra.DUTDevice, ate *ondatra.ATEDevice) { @@ -355,20 +406,22 @@ func validateExportRoutingPolicy(t *testing.T, dut *ondatra.DUTDevice, ate *onda path := gnmi.OC().NetworkInstance(dni).Protocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_BGP, bgpName).Bgp().Neighbor(atePort1.IPv4).AfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV4_UNICAST).ApplyPolicy() policy := gnmi.Get[*oc.NetworkInstance_Protocol_Bgp_Neighbor_AfiSafi_ApplyPolicy](t, dut, path.State()) exportPolicies := policy.GetExportPolicy() - if len(exportPolicies) != 2 { - t.Errorf("ExportPolicy = %v, want %v", exportPolicies, []string{v4PrefixPolicy, v4LPPolicy}) + if !deviations.FlattenPolicyWithMultipleStatements(dut) { + if len(exportPolicies) != 2 { + t.Errorf("ExportPolicy = %v, want %v", exportPolicies, []string{v4ASPPolicy, v4MedPolicy}) + } } - bgpPrefixes := gnmi.GetAll[*otgtelemetry.BgpPeer_UnicastIpv4Prefix](t, ate.OTG(), gnmi.OTG().BgpPeer("atePort1.BGP4.peer").UnicastIpv4PrefixAny().State()) found := false for _, bgpPrefix := range bgpPrefixes { if bgpPrefix.Address != nil && bgpPrefix.GetAddress() == v42Route && bgpPrefix.PrefixLength != nil && bgpPrefix.GetPrefixLength() == v4RoutePrefix { found = true - t.Logf("Prefix recevied on OTG is correct, got prefix %v, want prefix %v", bgpPrefix, v42Route) + t.Logf("Prefix recevied on OTG is correct, got prefix %v, want prefix %v", bgpPrefix.GetAddress(), v42Route) if bgpPrefix.GetMultiExitDiscriminator() != med { t.Errorf("For Prefix %v, got MED %d want MED %d", bgpPrefix.GetAddress(), bgpPrefix.GetMultiExitDiscriminator(), med) } + t.Logf("For Prefix %v, got MED %d want MED %d", bgpPrefix.GetAddress(), bgpPrefix.GetMultiExitDiscriminator(), med) asPaths := bgpPrefix.AsPath for _, ap := range asPaths { count := 0 @@ -384,7 +437,6 @@ func validateExportRoutingPolicy(t *testing.T, dut *ondatra.DUTDevice, ate *onda break } } - if !found { t.Errorf("No Route found for prefix %s", v42Route) } @@ -417,23 +469,34 @@ func configureImportRoutingPolicyV6(t *testing.T, dut *ondatra.DUTDevice, operat } stmt2.GetOrCreateActions().SetPolicyResult(oc.RoutingPolicy_PolicyResultType_ACCEPT_ROUTE) stmt2.GetOrCreateActions().GetOrCreateBgpActions().SetSetLocalPref(localPref) - if operation == "set" { - gnmi.BatchReplace(batch, gnmi.OC().RoutingPolicy().Config(), rp) - } else if operation == "delete" { - gnmi.BatchDelete(batch, gnmi.OC().RoutingPolicy().Config()) + if deviations.SkipSettingStatementForPolicy(dut) { + gnmi.Update(t, dut, gnmi.OC().RoutingPolicy().Config(), rp) + } else { + if operation == "set" { + gnmi.BatchReplace(batch, gnmi.OC().RoutingPolicy().Config(), rp) + } else if operation == "delete" { + gnmi.BatchDelete(batch, gnmi.OC().RoutingPolicy().Config()) + } } dni := deviations.DefaultNetworkInstance(dut) path := gnmi.OC().NetworkInstance(dni).Protocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_BGP, bgpName).Bgp().Neighbor(atePort1.IPv6).AfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV6_UNICAST).ApplyPolicy() policy := root.GetOrCreateNetworkInstance(dni).GetOrCreateProtocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_BGP, bgpName).GetOrCreateBgp().GetOrCreateNeighbor(atePort1.IPv6).GetOrCreateAfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV6_UNICAST).GetOrCreateApplyPolicy() - policy.SetDefaultImportPolicy(oc.RoutingPolicy_DefaultPolicyType_REJECT_ROUTE) + if !deviations.DefaultImportExportPolicy(dut) { + policy.SetDefaultImportPolicy(oc.RoutingPolicy_DefaultPolicyType_REJECT_ROUTE) + } policy.SetImportPolicy([]string{v6PrefixPolicy, v6LPPolicy}) - if operation == "set" { - gnmi.BatchReplace(batch, path.Config(), policy) - } else if operation == "delete" { - gnmi.BatchDelete(batch, path.Config()) + if deviations.SkipSettingStatementForPolicy(dut) { + gnmi.Update(t, dut, path.Config(), policy) + } else { + if operation == "set" { + gnmi.BatchReplace(batch, path.Config(), policy) + } else if operation == "delete" { + gnmi.BatchDelete(batch, path.Config()) + } + batch.Set(t, dut) } - batch.Set(t, dut) + time.Sleep(time.Second * 60) } func validateImportRoutingPolicyV6(t *testing.T, dut *ondatra.DUTDevice, ate *ondatra.ATEDevice) { @@ -441,25 +504,42 @@ func validateImportRoutingPolicyV6(t *testing.T, dut *ondatra.DUTDevice, ate *on path := gnmi.OC().NetworkInstance(dni).Protocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_BGP, bgpName).Bgp().Neighbor(atePort1.IPv6).AfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV6_UNICAST).ApplyPolicy() policy := gnmi.Get[*oc.NetworkInstance_Protocol_Bgp_Neighbor_AfiSafi_ApplyPolicy](t, dut, path.State()) importPolicies := policy.GetImportPolicy() - if len(importPolicies) != 2 { - t.Errorf("ImportPolicy = %v, want %v", importPolicies, []string{v6PrefixPolicy, v6LPPolicy}) + if !deviations.FlattenPolicyWithMultipleStatements(dut) { + if len(importPolicies) != 2 { + t.Errorf("ImportPolicy = %v, want %v", importPolicies, []string{v6PrefixPolicy, v6LPPolicy}) + } } if !deviations.BGPRibOcPathUnsupported(dut) { bgpRIBPath := gnmi.OC().NetworkInstance(dni).Protocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_BGP, bgpName).Bgp().Rib() locRib := gnmi.Get[*oc.NetworkInstance_Protocol_Bgp_Rib_AfiSafi_Ipv6Unicast_LocRib](t, dut, bgpRIBPath.AfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV6_UNICAST).Ipv6Unicast().LocRib().State()) found := false for k, lr := range locRib.Route { - if lr.GetPrefix() == advertisedIPv61.address { + prefixAddr := strings.Split(lr.GetPrefix(), "/") + if prefixAddr[0] == advertisedIPv61.address { found = true t.Logf("Found Route(prefix %s, origin: %v, pathid: %d) => %s", k.Prefix, k.Origin, k.PathId, lr.GetPrefix()) - attrSet := gnmi.Get[*oc.NetworkInstance_Protocol_Bgp_Rib_AttrSet](t, dut, bgpRIBPath.AttrSet(lr.GetAttrIndex()).State()) - if attrSet == nil || attrSet.GetLocalPref() != localPref { - t.Errorf("No local pref found for prefix %s", advertisedIPv61.address) + if !deviations.SkipCheckingAttributeIndex(dut) { + attrSet := gnmi.Get[*oc.NetworkInstance_Protocol_Bgp_Rib_AttrSet](t, dut, bgpRIBPath.AttrSet(lr.GetAttrIndex()).State()) + if attrSet == nil || attrSet.GetLocalPref() != localPref { + t.Errorf("No local pref found for prefix %s", advertisedIPv61.address) + } + break + } else { + attrSetList := gnmi.GetAll[*oc.NetworkInstance_Protocol_Bgp_Rib_AttrSet](t, dut, bgpRIBPath.AttrSetAny().State()) + foundLP := false + for _, attrSet := range attrSetList { + if attrSet.GetLocalPref() == localPref { + foundLP = true + t.Logf("Found local pref %d for prefix %s", attrSet.GetLocalPref(), advertisedIPv61.address) + break + } + } + if !foundLP { + t.Errorf("No local pref found for prefix %s", advertisedIPv61.address) + } } - break } } - if !found { t.Errorf("No Route found for prefix %s", advertisedIPv61.address) } @@ -477,30 +557,54 @@ func configureExportRoutingPolicyV6(t *testing.T, dut *ondatra.DUTDevice, operat } stmt1.GetOrCreateActions().GetOrCreateBgpActions().GetOrCreateSetAsPathPrepend().SetAsn(dutAS) - pdef2 := rp.GetOrCreatePolicyDefinition(v6MedPolicy) - stmt2, err := pdef2.AppendNewStatement(v6MedStatement) - if err != nil { - t.Fatalf("AppendNewStatement(%s) failed: %v", v6MedStatement, err) - } - stmt2.GetOrCreateActions().SetPolicyResult(oc.RoutingPolicy_PolicyResultType_ACCEPT_ROUTE) - stmt2.GetOrCreateActions().GetOrCreateBgpActions().SetSetMed(oc.UnionUint32(med)) - if operation == "set" { - gnmi.BatchReplace(batch, gnmi.OC().RoutingPolicy().Config(), rp) - } else if operation == "delete" { - gnmi.BatchDelete(batch, gnmi.OC().RoutingPolicy().Config()) + if deviations.FlattenPolicyWithMultipleStatements(dut) { + stmt2, err := pdef1.AppendNewStatement(v6MedStatement) + if err != nil { + t.Fatalf("AppendNewStatement(%s) failed: %v", v6MedStatement, err) + } + stmt2.GetOrCreateActions().SetPolicyResult(oc.RoutingPolicy_PolicyResultType_ACCEPT_ROUTE) + stmt2.GetOrCreateActions().GetOrCreateBgpActions().SetSetMed(oc.UnionUint32(med)) + } else { + pdef2 := rp.GetOrCreatePolicyDefinition(v6MedPolicy) + stmt2, err := pdef2.AppendNewStatement(v6MedStatement) + if err != nil { + t.Fatalf("AppendNewStatement(%s) failed: %v", v6MedStatement, err) + } + stmt2.GetOrCreateActions().SetPolicyResult(oc.RoutingPolicy_PolicyResultType_ACCEPT_ROUTE) + stmt2.GetOrCreateActions().GetOrCreateBgpActions().SetSetMed(oc.UnionUint32(med)) + } + if deviations.SkipSettingStatementForPolicy(dut) { + gnmi.Update(t, dut, gnmi.OC().RoutingPolicy().Config(), rp) + } else { + if operation == "set" { + gnmi.BatchReplace(batch, gnmi.OC().RoutingPolicy().Config(), rp) + } else if operation == "delete" { + gnmi.BatchDelete(batch, gnmi.OC().RoutingPolicy().Config()) + } } dni := deviations.DefaultNetworkInstance(dut) path := gnmi.OC().NetworkInstance(dni).Protocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_BGP, bgpName).Bgp().Neighbor(atePort1.IPv6).AfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV6_UNICAST).ApplyPolicy() policy := root.GetOrCreateNetworkInstance(dni).GetOrCreateProtocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_BGP, bgpName).GetOrCreateBgp().GetOrCreateNeighbor(atePort1.IPv6).GetOrCreateAfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV6_UNICAST).GetOrCreateApplyPolicy() - policy.SetDefaultExportPolicy(oc.RoutingPolicy_DefaultPolicyType_REJECT_ROUTE) - policy.SetExportPolicy([]string{v6ASPPolicy, v6MedPolicy}) - if operation == "set" { - gnmi.BatchReplace(batch, path.Config(), policy) - } else if operation == "delete" { - gnmi.BatchDelete(batch, path.Config()) - } - batch.Set(t, dut) + if !deviations.DefaultImportExportPolicy(dut) { + policy.SetDefaultExportPolicy(oc.RoutingPolicy_DefaultPolicyType_REJECT_ROUTE) + } + if deviations.FlattenPolicyWithMultipleStatements(dut) { + policy.SetExportPolicy([]string{v6ASPPolicy}) + } else { + policy.SetExportPolicy([]string{v6ASPPolicy, v6MedPolicy}) + } + if deviations.SkipSettingStatementForPolicy(dut) { + gnmi.Update(t, dut, path.Config(), policy) + } else { + if operation == "set" { + gnmi.BatchReplace(batch, path.Config(), policy) + } else if operation == "delete" { + gnmi.BatchDelete(batch, path.Config()) + } + batch.Set(t, dut) + } + time.Sleep(time.Second * 60) } func validateExportRoutingPolicyV6(t *testing.T, dut *ondatra.DUTDevice, ate *ondatra.ATEDevice) { @@ -508,8 +612,10 @@ func validateExportRoutingPolicyV6(t *testing.T, dut *ondatra.DUTDevice, ate *on path := gnmi.OC().NetworkInstance(dni).Protocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_BGP, bgpName).Bgp().Neighbor(atePort1.IPv6).AfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV6_UNICAST).ApplyPolicy() policy := gnmi.Get[*oc.NetworkInstance_Protocol_Bgp_Neighbor_AfiSafi_ApplyPolicy](t, dut, path.State()) exportPolicies := policy.GetExportPolicy() - if len(exportPolicies) != 2 { - t.Errorf("ExportPolicy = %v, want %v", exportPolicies, []string{v6PrefixPolicy, v6LPPolicy}) + if !deviations.FlattenPolicyWithMultipleStatements(dut) { + if len(exportPolicies) != 2 { + t.Errorf("ExportPolicy = %v, want %v", exportPolicies, []string{v6ASPPolicy, v6MedPolicy}) + } } bgpPrefixes := gnmi.GetAll[*otgtelemetry.BgpPeer_UnicastIpv6Prefix](t, ate.OTG(), gnmi.OTG().BgpPeer("atePort1.BGP6.peer").UnicastIpv6PrefixAny().State()) @@ -519,6 +625,7 @@ func validateExportRoutingPolicyV6(t *testing.T, dut *ondatra.DUTDevice, ate *on bgpPrefix.PrefixLength != nil && bgpPrefix.GetPrefixLength() == v6RoutePrefix { found = true t.Logf("Prefix recevied on OTG is correct, got prefix %v, want prefix %v", bgpPrefix, v62Route) + t.Logf("For Prefix %v, got MED %d want MED %d", bgpPrefix.GetAddress(), bgpPrefix.GetMultiExitDiscriminator(), med) if bgpPrefix.GetMultiExitDiscriminator() != med { t.Errorf("For Prefix %v, got MED %d want MED %d", bgpPrefix.GetAddress(), bgpPrefix.GetMultiExitDiscriminator(), med) } @@ -537,7 +644,6 @@ func validateExportRoutingPolicyV6(t *testing.T, dut *ondatra.DUTDevice, ate *on break } } - if !found { t.Errorf("No Route found for prefix %s", v62Route) } @@ -624,27 +730,60 @@ func (td *testData) advertiseRoutesWithEBGP(t *testing.T) { g.GetOrCreateAfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV4_UNICAST).Enabled = ygot.Bool(true) g.GetOrCreateAfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV6_UNICAST).Enabled = ygot.Bool(true) + if deviations.DefaultImportExportPolicy(td.dut) { + t.Logf("Configuring default route-policy for BGP on DUT") + rp := root.GetOrCreateRoutingPolicy() + pdef := rp.GetOrCreatePolicyDefinition("PERMIT-ALL") + stmt, err := pdef.AppendNewStatement("20") + if err != nil { + t.Fatalf("AppendNewStatement(%s) failed: %v", "20", err) + } + stmt.GetOrCreateActions().PolicyResult = oc.RoutingPolicy_PolicyResultType_ACCEPT_ROUTE + gnmi.Update(t, td.dut, gnmi.OC().RoutingPolicy().Config(), rp) + } pgv4 := bgp.GetOrCreatePeerGroup(peerGrpNamev4) pgv4.PeerGroupName = ygot.String(peerGrpNamev4) pgv6 := bgp.GetOrCreatePeerGroup(peerGrpNamev6) pgv6.PeerGroupName = ygot.String(peerGrpNamev6) + pgv4.GetOrCreateAfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV4_UNICAST).Enabled = ygot.Bool(true) + pgv6.GetOrCreateAfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV6_UNICAST).Enabled = ygot.Bool(true) + nV41 := bgp.GetOrCreateNeighbor(atePort1.IPv4) nV41.SetPeerAs(ateAS1) nV41.GetOrCreateAfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV4_UNICAST).Enabled = ygot.Bool(true) nV41.PeerGroup = ygot.String(peerGrpNamev4) + if deviations.DefaultImportExportPolicy(td.dut) { + afisafiv41 := nV41.GetOrCreateAfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV4_UNICAST) + afisafiv41.GetOrCreateApplyPolicy().SetImportPolicy([]string{"PERMIT-ALL"}) + afisafiv41.GetOrCreateApplyPolicy().SetExportPolicy([]string{"PERMIT-ALL"}) + } nV42 := bgp.GetOrCreateNeighbor(atePort2.IPv4) nV42.SetPeerAs(ateAS2) nV42.GetOrCreateAfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV4_UNICAST).Enabled = ygot.Bool(true) nV42.PeerGroup = ygot.String(peerGrpNamev4) - + if deviations.DefaultImportExportPolicy(td.dut) { + afisafiv42 := nV42.GetOrCreateAfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV4_UNICAST) + afisafiv42.GetOrCreateApplyPolicy().SetImportPolicy([]string{"PERMIT-ALL"}) + afisafiv42.GetOrCreateApplyPolicy().SetExportPolicy([]string{"PERMIT-ALL"}) + } nV61 := bgp.GetOrCreateNeighbor(atePort1.IPv6) nV61.SetPeerAs(ateAS1) nV61.GetOrCreateAfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV6_UNICAST).Enabled = ygot.Bool(true) nV61.PeerGroup = ygot.String(peerGrpNamev6) + if deviations.DefaultImportExportPolicy(td.dut) { + afisafiv61 := nV61.GetOrCreateAfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV6_UNICAST) + afisafiv61.GetOrCreateApplyPolicy().SetImportPolicy([]string{"PERMIT-ALL"}) + afisafiv61.GetOrCreateApplyPolicy().SetExportPolicy([]string{"PERMIT-ALL"}) + } nV62 := bgp.GetOrCreateNeighbor(atePort2.IPv6) nV62.SetPeerAs(ateAS2) nV62.GetOrCreateAfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV6_UNICAST).Enabled = ygot.Bool(true) nV62.PeerGroup = ygot.String(peerGrpNamev6) + if deviations.DefaultImportExportPolicy(td.dut) { + afisafiv62 := nV62.GetOrCreateAfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV6_UNICAST) + afisafiv62.GetOrCreateApplyPolicy().SetImportPolicy([]string{"PERMIT-ALL"}) + afisafiv62.GetOrCreateApplyPolicy().SetExportPolicy([]string{"PERMIT-ALL"}) + } gnmi.Update(t, td.dut, gnmi.OC().NetworkInstance(deviations.DefaultNetworkInstance(td.dut)).Config(), ni) // configure eBGP on OTG port1 diff --git a/feature/bgp/policybase/otg_tests/chained_policies_test/metadata.textproto b/feature/bgp/policybase/otg_tests/chained_policies_test/metadata.textproto index 11bbfd9320d..2b3e7bedf9a 100644 --- a/feature/bgp/policybase/otg_tests/chained_policies_test/metadata.textproto +++ b/feature/bgp/policybase/otg_tests/chained_policies_test/metadata.textproto @@ -15,6 +15,8 @@ platform_exceptions: { default_network_instance: "default" missing_value_for_defaults: true skip_set_rp_match_set_options: true + default_import_export_policy: false + skip_setting_statement_for_policy: true } } platform_exceptions: { @@ -25,3 +27,16 @@ platform_exceptions: { bgp_rib_oc_path_unsupported: true } } +platform_exceptions: { + platform: { + vendor: CISCO + } + deviations: { + bgp_rib_oc_path_unsupported: true + default_import_export_policy: true + skip_setting_statement_for_policy: true + skip_checking_attribute_index: true + flatten_policy_with_multiple_statements: true + } +} + diff --git a/feature/bgp/policybase/otg_tests/comm_match_action_test/README.md b/feature/bgp/policybase/otg_tests/comm_match_action_test/README.md index 3767faa24ee..0f3f756d0d6 100644 --- a/feature/bgp/policybase/otg_tests/comm_match_action_test/README.md +++ b/feature/bgp/policybase/otg_tests/comm_match_action_test/README.md @@ -120,6 +120,15 @@ criteria. * /network-instances/network-instance/protocols/protocol/bgp/rib/afi-safis/afi-safi/ipv4-unicast/neighbors/neighbor/adj-rib-in-post/routes/route/state/community-index * /network-instances/network-instance/protocols/protocol/bgp/rib/afi-safis/afi-safi/ipv6-unicast/neighbors/neighbor/adj-rib-in-post/routes/route/state/community-index +## OpenConfig Path and RPC Coverage +```yaml +rpcs: + gnmi: + gNMI.Get: + gNMI.Set: + gNMI.Subscribe: +``` + ## Minimum DUT Required vRX - Virtual Router Device diff --git a/feature/bgp/policybase/otg_tests/comm_match_action_test/metadata.textproto b/feature/bgp/policybase/otg_tests/comm_match_action_test/metadata.textproto index c560af7dabd..d2237552f41 100644 --- a/feature/bgp/policybase/otg_tests/comm_match_action_test/metadata.textproto +++ b/feature/bgp/policybase/otg_tests/comm_match_action_test/metadata.textproto @@ -17,6 +17,15 @@ platform_exceptions: { bgp_actions_set_community_method_unsupported: true } } +platform_exceptions: { + platform: { + vendor: ARISTA + } + deviations: { + interface_enabled: true + default_network_instance: "default" + } +} tags: TAGS_AGGREGATION tags: TAGS_TRANSIT tags: TAGS_DATACENTER_EDGE diff --git a/feature/bgp/policybase/otg_tests/community_test/README.md b/feature/bgp/policybase/otg_tests/community_test/README.md index d3c2d2a496e..a068367488f 100644 --- a/feature/bgp/policybase/otg_tests/community_test/README.md +++ b/feature/bgp/policybase/otg_tests/community_test/README.md @@ -106,3 +106,53 @@ import-policy * /network-instances/network-instance/protocols/protocol/bgp/neighbors/neighbor/afi-safis/afi-safi/state/prefixes/received-pre-policy * /network-instances/network-instance/protocols/protocol/bgp/neighbors/neighbor/afi-safis/afi-safi/state/prefixes/received * /network-instances/network-instance/protocols/protocol/bgp/neighbors/neighbor/afi-safis/afi-safi/state/prefixes/installed + +## 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 + ### Policy definition + /routing-policy/policy-definitions/policy-definition/config/name: + /routing-policy/policy-definitions/policy-definition/statements/statement/config/name: + ### Policy for community-set match + /routing-policy/defined-sets/bgp-defined-sets/community-sets/community-set/config/community-set-name: + /routing-policy/defined-sets/bgp-defined-sets/community-sets/community-set/config/community-member: + /routing-policy/defined-sets/bgp-defined-sets/community-sets/community-set/config/match-set-options: + /routing-policy/policy-definitions/policy-definition/statements/statement/conditions/bgp-conditions/match-community-set/config/community-set: + /routing-policy/policy-definitions/policy-definition/statements/statement/conditions/bgp-conditions/match-community-set/config/match-set-options: + /routing-policy/policy-definitions/policy-definition/statements/statement/actions/config/policy-result: + /network-instances/network-instance/protocols/protocol/bgp/neighbors/neighbor/afi-safis/afi-safi/apply-policy/config/import-policy: + + ## State paths + ### Policy definition state + + /routing-policy/policy-definitions/policy-definition/state/name: + /routing-policy/policy-definitions/policy-definition/statements/statement/state/name: + + ### Policy for community-set match state + + /routing-policy/defined-sets/bgp-defined-sets/community-sets/community-set/state/community-set-name: + /routing-policy/defined-sets/bgp-defined-sets/community-sets/community-set/state/community-member: + /routing-policy/defined-sets/bgp-defined-sets/community-sets/community-set/state/match-set-options: + /routing-policy/policy-definitions/policy-definition/statements/statement/conditions/bgp-conditions/state/community-set: + + ### Paths to verify policy state + + /network-instances/network-instance/protocols/protocol/bgp/neighbors/neighbor/afi-safis/afi-safi/apply-policy/state/export-policy: + /network-instances/network-instance/protocols/protocol/bgp/neighbors/neighbor/afi-safis/afi-safi/apply-policy/state/import-policy: + + ### Paths to verify prefixes sent and received + + /network-instances/network-instance/protocols/protocol/bgp/neighbors/neighbor/afi-safis/afi-safi/state/prefixes/sent: + /network-instances/network-instance/protocols/protocol/bgp/neighbors/neighbor/afi-safis/afi-safi/state/prefixes/received-pre-policy: + /network-instances/network-instance/protocols/protocol/bgp/neighbors/neighbor/afi-safis/afi-safi/state/prefixes/received: + /network-instances/network-instance/protocols/protocol/bgp/neighbors/neighbor/afi-safis/afi-safi/state/prefixes/installed: +rpcs: + gnmi: + gNMI.Set: + gNMI.Subscribe: +``` \ No newline at end of file diff --git a/feature/bgp/policybase/otg_tests/community_test/community_test.go b/feature/bgp/policybase/otg_tests/community_test/community_test.go index 1086a26b0f7..f37293a40c3 100644 --- a/feature/bgp/policybase/otg_tests/community_test/community_test.go +++ b/feature/bgp/policybase/otg_tests/community_test/community_test.go @@ -1,4 +1,4 @@ -// Copyright 2023 Google LLC +/// Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -15,6 +15,7 @@ package community_test import ( + "fmt" "strconv" "testing" "time" @@ -23,6 +24,7 @@ import ( "github.com/openconfig/featureprofiles/internal/cfgplugins" "github.com/openconfig/featureprofiles/internal/deviations" "github.com/openconfig/featureprofiles/internal/fptest" + "github.com/openconfig/featureprofiles/internal/helpers" "github.com/openconfig/featureprofiles/internal/otgutils" "github.com/openconfig/ondatra" "github.com/openconfig/ondatra/gnmi" @@ -30,11 +32,13 @@ import ( ) const ( - prefixV4Len = 30 - prefixV6Len = 126 - trafficPps = 100 - totalPackets = 1200 - bgpName = "BGP" + prefixV4Len = 30 + prefixV6Len = 126 + trafficPps = 100 + totalPackets = 1200 + bgpName = "BGP" + RPLPermitAll = "PERMIT-ALL" + comunitySetNameRegex = "any_my_regex_comms" ) var prefixesV4 = [][]string{ @@ -65,16 +69,27 @@ func configureImportBGPPolicy(t *testing.T, dut *ondatra.DUTDevice, ipv4 string, } stmt1.GetOrCreateActions().SetPolicyResult(oc.RoutingPolicy_PolicyResultType_ACCEPT_ROUTE) - communitySet := rp.GetOrCreateDefinedSets().GetOrCreateBgpDefinedSets().GetOrCreateCommunitySet(communitySetName) - - cs := []oc.RoutingPolicy_DefinedSets_BgpDefinedSets_CommunitySet_CommunityMember_Union{} - for _, commMatch := range communityMatch { - if commMatch != "" { - cs = append(cs, oc.UnionString(commMatch)) + if !(deviations.CommunityMemberRegexUnsupported(dut) && communitySetName == comunitySetNameRegex) { + communitySet := rp.GetOrCreateDefinedSets().GetOrCreateBgpDefinedSets().GetOrCreateCommunitySet(communitySetName) + cs := []oc.RoutingPolicy_DefinedSets_BgpDefinedSets_CommunitySet_CommunityMember_Union{} + for _, commMatch := range communityMatch { + if commMatch != "" { + cs = append(cs, oc.UnionString(commMatch)) + } + } + communitySet.SetCommunityMember(cs) + communitySet.SetMatchSetOptions(matchSetOptions) + } + var communitySetCLIConfig string + if deviations.CommunityMemberRegexUnsupported(dut) && communitySetName == comunitySetNameRegex { + switch dut.Vendor() { + case ondatra.CISCO: + communitySetCLIConfig = fmt.Sprintf("community-set %v\n ios-regex '10[0-9]:1'\n end-set", communitySetName) + default: + t.Fatalf("Unsupported vendor %s for deviation 'CommunityMemberRegexUnsupported'", dut.Vendor()) } + helpers.GnmiCLIConfig(t, dut, communitySetCLIConfig) } - communitySet.SetCommunityMember(cs) - communitySet.SetMatchSetOptions(matchSetOptions) if deviations.BGPConditionsMatchCommunitySetUnsupported(dut) { stmt1.GetOrCreateConditions().GetOrCreateBgpConditions().SetCommunitySet(communitySetName) @@ -82,7 +97,17 @@ func configureImportBGPPolicy(t *testing.T, dut *ondatra.DUTDevice, ipv4 string, stmt1.GetOrCreateConditions().GetOrCreateBgpConditions().GetOrCreateMatchCommunitySet().SetCommunitySet(communitySetName) } - gnmi.Replace(t, dut, gnmi.OC().RoutingPolicy().Config(), rp) + if deviations.CommunityMemberRegexUnsupported(dut) && communitySetName == comunitySetNameRegex { + gnmi.Update(t, dut, gnmi.OC().RoutingPolicy().Config(), rp) + } else { + pdAllow := rp.GetOrCreatePolicyDefinition(RPLPermitAll) + st, err := pdAllow.AppendNewStatement("id-1") + if err != nil { + t.Fatal(err) + } + st.GetOrCreateActions().PolicyResult = oc.RoutingPolicy_PolicyResultType_ACCEPT_ROUTE + gnmi.Replace(t, dut, gnmi.OC().RoutingPolicy().Config(), rp) + } dni := deviations.DefaultNetworkInstance(dut) pathV6 := gnmi.OC().NetworkInstance(dni).Protocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_BGP, bgpName).Bgp().Neighbor(ipv6).AfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV6_UNICAST).ApplyPolicy() @@ -251,7 +276,7 @@ func TestCommunitySet(t *testing.T) { }, { desc: "Testing with any_my_regex_comms", - communitySetName: "any_my_regex_comms", + communitySetName: comunitySetNameRegex, communityMatch: [3]string{"10[0-9]:1"}, matchSetOptions: oc.BgpPolicy_MatchSetOptionsType_ANY, testResults: [4]bool{true, true, true, false}, @@ -270,6 +295,9 @@ func TestCommunitySet(t *testing.T) { } bs.PushAndStartATE(t) + // Verify BGP session after its reset with OTG push config & start + cfgplugins.VerifyDUTBGPEstablished(t, bs.DUT) + t.Logf("Starting traffic for IPv4 and v6") bs.ATE.OTG().StartTraffic(t) time.Sleep(sleepTime * time.Second) diff --git a/feature/bgp/policybase/otg_tests/community_test/metadata.textproto b/feature/bgp/policybase/otg_tests/community_test/metadata.textproto index 3e6e03b7079..0b6e57c3804 100644 --- a/feature/bgp/policybase/otg_tests/community_test/metadata.textproto +++ b/feature/bgp/policybase/otg_tests/community_test/metadata.textproto @@ -21,3 +21,12 @@ platform_exceptions: { bgp_conditions_match_community_set_unsupported: true } } +platform_exceptions: { + platform: { + vendor: CISCO + } + deviations: { + bgp_conditions_match_community_set_unsupported: true + community_member_regex_unsupported: true + } +} \ No newline at end of file diff --git a/feature/bgp/policybase/otg_tests/default_policies_test/bgp_default_policies_test.go b/feature/bgp/policybase/otg_tests/default_policies_test/bgp_default_policies_test.go index e0465b1344a..3e20da18c68 100644 --- a/feature/bgp/policybase/otg_tests/default_policies_test/bgp_default_policies_test.go +++ b/feature/bgp/policybase/otg_tests/default_policies_test/bgp_default_policies_test.go @@ -15,6 +15,8 @@ package bgp_default_policies_test import ( + "context" + "encoding/json" "fmt" "testing" "time" @@ -24,6 +26,7 @@ import ( "github.com/openconfig/featureprofiles/internal/attrs" "github.com/openconfig/featureprofiles/internal/deviations" "github.com/openconfig/featureprofiles/internal/fptest" + gpb "github.com/openconfig/gnmi/proto/gnmi" "github.com/openconfig/ondatra" "github.com/openconfig/ondatra/gnmi" "github.com/openconfig/ondatra/gnmi/oc" @@ -86,6 +89,7 @@ const ( ipv6Prefix7 = "2001:DB8:2::7" ipv6Prefix8 = "2001:DB8:2::8" maskLenExact = "exact" + replacePolicy = true ) var ( @@ -162,6 +166,17 @@ func configureDUT(t *testing.T, dut *ondatra.DUTDevice) { t.Logf("Got DUT IPv4 loopback address: %v", dutlo0Attrs.IPv4) t.Logf("Got DUT IPv6 loopback address: %v", dutlo0Attrs.IPv6) } + + if deviations.ExplicitPortSpeed(dut) { + fptest.SetPortSpeed(t, dut.Port(t, "port1")) + fptest.SetPortSpeed(t, dut.Port(t, "port2")) + } + if deviations.ExplicitInterfaceInDefaultVRF(dut) { + fptest.AssignToNetworkInstance(t, dut, dut.Port(t, "port1").Name(), deviations.DefaultNetworkInstance(dut), 0) + fptest.AssignToNetworkInstance(t, dut, dut.Port(t, "port2").Name(), deviations.DefaultNetworkInstance(dut), 0) + fptest.AssignToNetworkInstance(t, dut, loopbackIntfName, deviations.DefaultNetworkInstance(dut), 0) + } + } func verifyPortsUp(t *testing.T, dev *ondatra.Device) { @@ -437,7 +452,6 @@ func verifyBGPCapabilities(t *testing.T, dut *ondatra.DUTDevice) { func verifyPrefixesTelemetry(t *testing.T, dut *ondatra.DUTDevice, nbr string, wantInstalled, wantRx, wantSent uint32, isV4 bool) { t.Helper() - statePath := gnmi.OC().NetworkInstance(deviations.DefaultNetworkInstance(dut)).Protocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_BGP, "BGP").Bgp() t.Logf("Prefix telemetry on DUT for peer %v", nbr) @@ -447,15 +461,25 @@ func verifyPrefixesTelemetry(t *testing.T, dut *ondatra.DUTDevice, nbr string, w } else { prefixPath = statePath.Neighbor(nbr).AfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV6_UNICAST).Prefixes() } - if gotInstalled := gnmi.Get(t, dut, prefixPath.Installed().State()); gotInstalled != wantInstalled { + if gotInstalled, ok := gnmi.Watch(t, dut, prefixPath.Installed().State(), 10*time.Second, func(val *ygnmi.Value[uint32]) bool { + gotInstalled, ok := val.Val() + return ok && gotInstalled == wantInstalled + }).Await(t); !ok { t.Errorf("Installed prefixes mismatch: got %v, want %v", gotInstalled, wantInstalled) } + if !deviations.MissingPrePolicyReceivedRoutes(dut) { - if gotRx := gnmi.Get(t, dut, prefixPath.ReceivedPrePolicy().State()); gotRx != wantRx { + if gotRx, ok := gnmi.Watch(t, dut, prefixPath.ReceivedPrePolicy().State(), 10*time.Second, func(val *ygnmi.Value[uint32]) bool { + gotRx, ok := val.Val() + return ok && gotRx == wantRx + }).Await(t); !ok { t.Errorf("Received prefixes mismatch: got %v, want %v", gotRx, wantRx) } } - if gotSent := gnmi.Get(t, dut, prefixPath.Sent().State()); gotSent != wantSent { + if gotSent, ok := gnmi.Watch(t, dut, prefixPath.Sent().State(), 10*time.Second, func(val *ygnmi.Value[uint32]) bool { + gotSent, ok := val.Val() + return ok && gotSent == wantSent + }).Await(t); !ok { t.Errorf("Sent prefixes mismatch: got %v, want %v", gotSent, wantSent) } } @@ -559,70 +583,134 @@ func deleteBGPPolicy(t *testing.T, dut *ondatra.DUTDevice, nbrList []*bgpNbrList } } +func configureRoutingPolicyDefaultAction(t *testing.T, dut *ondatra.DUTDevice, action string, replace bool) { + + var routingPolicyDefaultAction = []any{ + map[string]any{ + "default-action": map[string]any{ + "policy-result": action, + }, + }, + } + defaultAction, err := json.Marshal(routingPolicyDefaultAction) + if err != nil { + t.Fatalf("Error with json Marshal: %v", err) + } + + var updates []*gpb.Update + for _, policy := range []string{ebgpExportIPv4, ebgpExportIPv6, ibgpExportIPv4, ibgpExportIPv6, ebgpImportIPv4, ebgpImportIPv6, ibgpImportIPv4, ibgpImportIPv6} { + update := gpb.Update{ + Path: &gpb.Path{ + Elem: []*gpb.PathElem{ + {Name: "routing-policy"}, + {Name: "policy", Key: map[string]string{"name": policy}}, + }, + }, + Val: &gpb.TypedValue{ + Value: &gpb.TypedValue_JsonIetfVal{ + JsonIetfVal: defaultAction, + }, + }, + } + updates = append(updates, &update) + } + gpbSetRequest := &gpb.SetRequest{ + Prefix: &gpb.Path{ + Origin: "native", + }, + Update: updates, + } + if replace { + gpbSetRequest = &gpb.SetRequest{ + Prefix: &gpb.Path{ + Origin: "native", + }, + Replace: updates, + } + } + + gnmiClient := dut.RawAPIs().GNMI(t) + if _, err := gnmiClient.Set(context.Background(), gpbSetRequest); err != nil { + t.Fatalf("Unexpected error updating SRL routing-policy default-action: %v", err) + } + time.Sleep(5 * time.Second) +} + func testDefaultPolicyRejectRouteAction(t *testing.T, dut *ondatra.DUTDevice) { t.Helper() t.Run("Create and apply default-policy REJECT-ALL with action as REJECT_ROUTE", func(t *testing.T) { - configureBGPDefaultPolicy(t, dut, rejectRoute) + if deviations.BgpDefaultPolicyUnsupported(dut) { + configureRoutingPolicyDefaultAction(t, dut, "reject", !replacePolicy) + } else { + configureBGPDefaultPolicy(t, dut, rejectRoute) + } }) verifyPostPolicyPrefixTelemetry(t, dut, &peerDetails{ipAddr: atePort1.IPv4, defExportPol: rejectRoute, defImportPol: rejectRoute, exportPol: []string{ebgpExportIPv4}, importPol: []string{ebgpImportIPv4}, - wantInstalled: 2, wantRx: 3, wantRxPrePoloicy: 3, wantSent: 1, isV4: true}) + wantInstalled: 2, wantRx: 2, wantRxPrePolicy: 3, wantSent: 1, isV4: true}) verifyPostPolicyPrefixTelemetry(t, dut, &peerDetails{ipAddr: atePort1.IPv6, defExportPol: rejectRoute, defImportPol: rejectRoute, exportPol: []string{ebgpExportIPv6}, importPol: []string{ebgpImportIPv6}, - wantInstalled: 2, wantRx: 3, wantRxPrePoloicy: 3, wantSent: 1, isV4: false}) + wantInstalled: 2, wantRx: 2, wantRxPrePolicy: 3, wantSent: 1, isV4: false}) verifyPostPolicyPrefixTelemetry(t, dut, &peerDetails{ipAddr: otgIsisPort2LoopV4, defExportPol: rejectRoute, defImportPol: rejectRoute, exportPol: []string{ibgpExportIPv4}, importPol: []string{ibgpImportIPv4}, - wantInstalled: 2, wantRx: 3, wantRxPrePoloicy: 3, wantSent: 1, isV4: true}) + wantInstalled: 2, wantRx: 2, wantRxPrePolicy: 3, wantSent: 1, isV4: true}) verifyPostPolicyPrefixTelemetry(t, dut, &peerDetails{ipAddr: otgIsisPort2LoopV6, defExportPol: rejectRoute, defImportPol: rejectRoute, exportPol: []string{ibgpExportIPv6}, importPol: []string{ibgpImportIPv6}, - wantInstalled: 2, wantRx: 3, wantRxPrePoloicy: 3, wantSent: 1, isV4: false}) + wantInstalled: 2, wantRx: 2, wantRxPrePolicy: 3, wantSent: 1, isV4: false}) } func testDefaultPolicyAcceptRouteAction(t *testing.T, dut *ondatra.DUTDevice) { t.Helper() t.Run("Create and apply default-policy ACCEPT-ALL with action as ACCEPT_ROUTE", func(t *testing.T) { - configureBGPDefaultPolicy(t, dut, acceptRoute) + if deviations.BgpDefaultPolicyUnsupported(dut) { + configureRoutingPolicyDefaultAction(t, dut, "accept", !replacePolicy) + } else { + configureBGPDefaultPolicy(t, dut, acceptRoute) + } }) verifyPostPolicyPrefixTelemetry(t, dut, &peerDetails{ipAddr: atePort1.IPv4, defExportPol: acceptRoute, defImportPol: acceptRoute, exportPol: []string{ebgpExportIPv4}, importPol: []string{ebgpImportIPv4}, - wantInstalled: 3, wantRx: 3, wantRxPrePoloicy: 3, wantSent: 3, isV4: true}) + wantInstalled: 3, wantRx: 3, wantRxPrePolicy: 3, wantSent: 3, isV4: true}) verifyPostPolicyPrefixTelemetry(t, dut, &peerDetails{ipAddr: atePort1.IPv6, defExportPol: acceptRoute, defImportPol: acceptRoute, exportPol: []string{ebgpExportIPv6}, importPol: []string{ebgpImportIPv6}, - wantInstalled: 3, wantRx: 3, wantRxPrePoloicy: 3, wantSent: 3, isV4: false}) + wantInstalled: 3, wantRx: 3, wantRxPrePolicy: 3, wantSent: 3, isV4: false}) verifyPostPolicyPrefixTelemetry(t, dut, &peerDetails{ipAddr: otgIsisPort2LoopV4, defExportPol: acceptRoute, defImportPol: acceptRoute, exportPol: []string{ibgpExportIPv4}, importPol: []string{ibgpImportIPv4}, - wantInstalled: 3, wantRx: 3, wantRxPrePoloicy: 3, wantSent: 3, isV4: true}) + wantInstalled: 3, wantRx: 3, wantRxPrePolicy: 3, wantSent: 3, isV4: true}) verifyPostPolicyPrefixTelemetry(t, dut, &peerDetails{ipAddr: otgIsisPort2LoopV6, defExportPol: acceptRoute, defImportPol: acceptRoute, exportPol: []string{ibgpExportIPv6}, importPol: []string{ibgpImportIPv6}, - wantInstalled: 3, wantRx: 3, wantRxPrePoloicy: 3, wantSent: 3, isV4: false}) + wantInstalled: 3, wantRx: 3, wantRxPrePolicy: 3, wantSent: 3, isV4: false}) } func testDefaultPolicyAcceptRouteActionOnly(t *testing.T, dut *ondatra.DUTDevice) { t.Helper() t.Run("Create and apply default-policy ACCEPT-ALL with action as ACCEPT_ROUTE", func(t *testing.T) { - configureBGPDefaultPolicy(t, dut, acceptRoute) - }) - - t.Run("Delete prefix set policies", func(t *testing.T) { - deleteBGPPolicy(t, dut, []*bgpNbrList{ebgpNbrV4, ebgpNbrV6, ibgpNbrV4, ibgpNbrV6}) + if deviations.BgpDefaultPolicyUnsupported(dut) { + configureRoutingPolicyDefaultAction(t, dut, "accept", replacePolicy) + } else { + configureBGPDefaultPolicy(t, dut, acceptRoute) + t.Run("Delete prefix set policies", func(t *testing.T) { + deleteBGPPolicy(t, dut, []*bgpNbrList{ebgpNbrV4, ebgpNbrV6, ibgpNbrV4, ibgpNbrV6}) + }) + } }) verifyPostPolicyPrefixTelemetry(t, dut, &peerDetails{ipAddr: atePort1.IPv4, defExportPol: acceptRoute, defImportPol: acceptRoute, exportPol: []string{}, importPol: []string{}, - wantInstalled: 3, wantRx: 3, wantRxPrePoloicy: 3, wantSent: 3, isV4: true}) + wantInstalled: 3, wantRx: 3, wantRxPrePolicy: 3, wantSent: 3, isV4: true}) verifyPostPolicyPrefixTelemetry(t, dut, &peerDetails{ipAddr: atePort1.IPv6, defExportPol: acceptRoute, defImportPol: acceptRoute, exportPol: []string{}, importPol: []string{}, - wantInstalled: 3, wantRx: 3, wantRxPrePoloicy: 3, wantSent: 3, isV4: false}) + wantInstalled: 3, wantRx: 3, wantRxPrePolicy: 3, wantSent: 3, isV4: false}) verifyPostPolicyPrefixTelemetry(t, dut, &peerDetails{ipAddr: otgIsisPort2LoopV4, defExportPol: acceptRoute, defImportPol: acceptRoute, exportPol: []string{}, importPol: []string{}, - wantInstalled: 3, wantRx: 3, wantRxPrePoloicy: 3, wantSent: 3, isV4: true}) + wantInstalled: 3, wantRx: 3, wantRxPrePolicy: 3, wantSent: 3, isV4: true}) verifyPostPolicyPrefixTelemetry(t, dut, &peerDetails{ipAddr: otgIsisPort2LoopV6, defExportPol: acceptRoute, defImportPol: acceptRoute, exportPol: []string{}, importPol: []string{}, - wantInstalled: 3, wantRx: 3, wantRxPrePoloicy: 3, wantSent: 3, isV4: false}) + wantInstalled: 3, wantRx: 3, wantRxPrePolicy: 3, wantSent: 3, isV4: false}) } func testNoPolicyConfiguredIBGPPeer(t *testing.T, dut *ondatra.DUTDevice) { @@ -641,21 +729,25 @@ func testDefaultPolicyRejectRouteActionOnly(t *testing.T, dut *ondatra.DUTDevice t.Helper() t.Run("Create and apply default-policy REJECT-ALL with action as REJECT_ROUTE", func(t *testing.T) { - configureBGPDefaultPolicy(t, dut, rejectRoute) + if deviations.BgpDefaultPolicyUnsupported(dut) { + configureRoutingPolicyDefaultAction(t, dut, "reject", replacePolicy) + } else { + configureBGPDefaultPolicy(t, dut, rejectRoute) + } }) verifyPostPolicyPrefixTelemetry(t, dut, &peerDetails{ipAddr: atePort1.IPv4, defExportPol: rejectRoute, defImportPol: rejectRoute, exportPol: []string{}, importPol: []string{}, - wantInstalled: 0, wantRx: 3, wantRxPrePoloicy: 3, wantSent: 0, isV4: true}) + wantInstalled: 0, wantRx: 0, wantRxPrePolicy: 3, wantSent: 0, isV4: true}) verifyPostPolicyPrefixTelemetry(t, dut, &peerDetails{ipAddr: atePort1.IPv6, defExportPol: rejectRoute, defImportPol: rejectRoute, exportPol: []string{}, importPol: []string{}, - wantInstalled: 0, wantRx: 3, wantRxPrePoloicy: 3, wantSent: 0, isV4: false}) + wantInstalled: 0, wantRx: 0, wantRxPrePolicy: 3, wantSent: 0, isV4: false}) verifyPostPolicyPrefixTelemetry(t, dut, &peerDetails{ipAddr: otgIsisPort2LoopV4, defExportPol: rejectRoute, defImportPol: rejectRoute, exportPol: []string{}, importPol: []string{}, - wantInstalled: 0, wantRx: 3, wantRxPrePoloicy: 3, wantSent: 0, isV4: true}) + wantInstalled: 0, wantRx: 0, wantRxPrePolicy: 3, wantSent: 0, isV4: true}) verifyPostPolicyPrefixTelemetry(t, dut, &peerDetails{ipAddr: otgIsisPort2LoopV6, defExportPol: rejectRoute, defImportPol: rejectRoute, exportPol: []string{}, importPol: []string{}, - wantInstalled: 0, wantRx: 3, wantRxPrePoloicy: 3, wantSent: 0, isV4: false}) + wantInstalled: 0, wantRx: 0, wantRxPrePolicy: 3, wantSent: 0, isV4: false}) } func configureRoutePolicies(t *testing.T, dut *ondatra.DUTDevice) { @@ -687,11 +779,11 @@ func configureRoutePolicies(t *testing.T, dut *ondatra.DUTDevice) { } type peerDetails struct { - ipAddr string - defExportPol, defImportPol oc.E_RoutingPolicy_DefaultPolicyType - exportPol, importPol []string - wantInstalled, wantRx, wantRxPrePoloicy, wantSent uint32 - isV4 bool + ipAddr string + defExportPol, defImportPol oc.E_RoutingPolicy_DefaultPolicyType + exportPol, importPol []string + wantInstalled, wantRx, wantRxPrePolicy, wantSent uint32 + isV4 bool } func verifyPostPolicyPrefixTelemetry(t *testing.T, dut *ondatra.DUTDevice, nbr *peerDetails) { @@ -709,12 +801,14 @@ func verifyPostPolicyPrefixTelemetry(t *testing.T, dut *ondatra.DUTDevice, nbr * peerTel := gnmi.Get(t, dut, afiSafiPath.State()) - if gotDefExPolicy := peerTel.GetApplyPolicy().GetDefaultExportPolicy(); gotDefExPolicy != nbr.defExportPol { - t.Errorf("Default export policy type mismatch: got %v, want %v", gotDefExPolicy, nbr.defExportPol) - } + if !deviations.BgpDefaultPolicyUnsupported(dut) { + if gotDefExPolicy := peerTel.GetApplyPolicy().GetDefaultExportPolicy(); gotDefExPolicy != nbr.defExportPol { + t.Errorf("Default export policy type mismatch: got %v, want %v", gotDefExPolicy, nbr.defExportPol) + } - if gotDefImPolicy := peerTel.GetApplyPolicy().GetDefaultImportPolicy(); gotDefImPolicy != nbr.defImportPol { - t.Errorf("Default import policy type mismatch: got %v, want %v", gotDefImPolicy, nbr.defImportPol) + if gotDefImPolicy := peerTel.GetApplyPolicy().GetDefaultImportPolicy(); gotDefImPolicy != nbr.defImportPol { + t.Errorf("Default import policy type mismatch: got %v, want %v", gotDefImPolicy, nbr.defImportPol) + } } if len(nbr.exportPol) != 0 { if gotExportPol := peerTel.GetApplyPolicy().GetExportPolicy(); cmp.Diff(gotExportPol, nbr.exportPol) != "" { @@ -727,19 +821,33 @@ func verifyPostPolicyPrefixTelemetry(t *testing.T, dut *ondatra.DUTDevice, nbr * } } - if gotInstalled := peerTel.GetPrefixes().GetInstalled(); gotInstalled != nbr.wantInstalled { + if gotInstalled, ok := gnmi.Watch(t, dut, afiSafiPath.Prefixes().Installed().State(), 10*time.Second, func(val *ygnmi.Value[uint32]) bool { + gotInstalled, ok := val.Val() + return ok && gotInstalled == nbr.wantInstalled + }).Await(t); !ok { t.Errorf("Installed prefixes mismatch: got %v, want %v", gotInstalled, nbr.wantInstalled) } + if !deviations.MissingPrePolicyReceivedRoutes(dut) { - if gotRxPrePol := peerTel.GetPrefixes().GetReceivedPrePolicy(); gotRxPrePol != nbr.wantRxPrePoloicy { - t.Errorf("Received pre policy prefixes mismatch: got %v, want %v", gotRxPrePol, nbr.wantRxPrePoloicy) + if gotRxPrePol, ok := gnmi.Watch(t, dut, afiSafiPath.Prefixes().ReceivedPrePolicy().State(), 10*time.Second, func(val *ygnmi.Value[uint32]) bool { + gotRxPrePol, ok := val.Val() + return ok && gotRxPrePol == nbr.wantRxPrePolicy + }).Await(t); !ok { + t.Errorf("Received pre policy prefixes mismatch: got %v, want %v", gotRxPrePol, nbr.wantRxPrePolicy) } } - if gotRx := peerTel.GetPrefixes().GetReceived(); gotRx != nbr.wantRx { - t.Errorf("Received pre policy prefixes mismatch: got %v, want %v", gotRx, nbr.wantRx) + if gotRx, ok := gnmi.Watch(t, dut, afiSafiPath.Prefixes().Received().State(), 10*time.Second, func(val *ygnmi.Value[uint32]) bool { + gotRx, ok := val.Val() + return ok && gotRx == nbr.wantRx + }).Await(t); !ok { + t.Errorf("Received prefixes mismatch: got %v, want %v", gotRx, nbr.wantRx) } + if nbr.defImportPol == oc.RoutingPolicy_DefaultPolicyType_ACCEPT_ROUTE && !deviations.SkipNonBgpRouteExportCheck(dut) { - if gotSent := peerTel.GetPrefixes().GetSent(); gotSent != nbr.wantSent { + if gotSent, ok := gnmi.Watch(t, dut, afiSafiPath.Prefixes().Sent().State(), 10*time.Second, func(val *ygnmi.Value[uint32]) bool { + gotSent, ok := val.Val() + return ok && gotSent == nbr.wantSent + }).Await(t); !ok { t.Errorf("Sent prefixes mismatch: got %v, want %v", gotSent, nbr.wantSent) } } @@ -789,6 +897,9 @@ func TestBGPDefaultPolicies(t *testing.T) { t.Run("Configure ISIS on DUT", func(t *testing.T) { dutIsisIntfNames := []string{dut.Port(t, "port2").Name(), loopbackIntfName} + if deviations.ExplicitInterfaceInDefaultVRF(dut) { + dutIsisIntfNames = []string{dut.Port(t, "port2").Name() + ".0", loopbackIntfName + ".0"} + } configureISIS(t, dut, dutIsisIntfNames, dutAreaAddress, dutSysID) }) @@ -823,10 +934,17 @@ func TestBGPDefaultPolicies(t *testing.T) { }) t.Run("Verify prefix telemetry on DUT for all iBGP and eBGP peers", func(t *testing.T) { - verifyPrefixesTelemetry(t, dut, atePort1.IPv4, 3, 3, 3, v4Prefixes) - verifyPrefixesTelemetry(t, dut, otgIsisPort2LoopV4, 3, 3, 3, v4Prefixes) - verifyPrefixesTelemetry(t, dut, atePort1.IPv6, 3, 3, 3, !v4Prefixes) - verifyPrefixesTelemetry(t, dut, otgIsisPort2LoopV6, 3, 3, 3, !v4Prefixes) + if deviations.DefaultImportExportPolicy(dut) { + verifyPrefixesTelemetry(t, dut, atePort1.IPv4, 3, 3, 3, v4Prefixes) + verifyPrefixesTelemetry(t, dut, otgIsisPort2LoopV4, 3, 3, 3, v4Prefixes) + verifyPrefixesTelemetry(t, dut, atePort1.IPv6, 3, 3, 3, !v4Prefixes) + verifyPrefixesTelemetry(t, dut, otgIsisPort2LoopV6, 3, 3, 3, !v4Prefixes) + } else { + verifyPrefixesTelemetry(t, dut, atePort1.IPv4, 0, 3, 0, v4Prefixes) + verifyPrefixesTelemetry(t, dut, otgIsisPort2LoopV4, 3, 3, 0, v4Prefixes) + verifyPrefixesTelemetry(t, dut, atePort1.IPv6, 0, 3, 0, !v4Prefixes) + verifyPrefixesTelemetry(t, dut, otgIsisPort2LoopV6, 3, 3, 0, !v4Prefixes) + } }) t.Run("Add static routes for ip prefixes IPv4/v6-prefix7 and IPv4/v6-prefix8", func(t *testing.T) { diff --git a/feature/bgp/policybase/otg_tests/default_policies_test/metadata.textproto b/feature/bgp/policybase/otg_tests/default_policies_test/metadata.textproto index a2f6c21c4cd..44cac34eaf7 100644 --- a/feature/bgp/policybase/otg_tests/default_policies_test/metadata.textproto +++ b/feature/bgp/policybase/otg_tests/default_policies_test/metadata.textproto @@ -12,6 +12,7 @@ platform_exceptions: { deviations: { isis_level_enabled: true skip_non_bgp_route_export_check: true + default_import_export_policy: true } } platform_exceptions: { @@ -24,6 +25,7 @@ platform_exceptions: { missing_isis_interface_afi_safi_enable: true isis_interface_afi_unsupported: true isis_instance_enabled_required: true + default_import_export_policy: true } } platform_exceptions: { @@ -31,6 +33,12 @@ platform_exceptions: { vendor: NOKIA } deviations: { + explicit_interface_in_default_vrf: true + explicit_port_speed: true interface_enabled: true + static_protocol_name: "static" + skip_non_bgp_route_export_check: true + missing_isis_interface_afi_safi_enable: true + bgp_default_policy_unsupported: true } } diff --git a/feature/bgp/policybase/otg_tests/import_export_multi/README.md b/feature/bgp/policybase/otg_tests/import_export_multi_test/README.md similarity index 100% rename from feature/bgp/policybase/otg_tests/import_export_multi/README.md rename to feature/bgp/policybase/otg_tests/import_export_multi_test/README.md diff --git a/feature/bgp/policybase/otg_tests/import_export_multi/import_export_multi.go b/feature/bgp/policybase/otg_tests/import_export_multi_test/import_export_multi_test.go similarity index 95% rename from feature/bgp/policybase/otg_tests/import_export_multi/import_export_multi.go rename to feature/bgp/policybase/otg_tests/import_export_multi_test/import_export_multi_test.go index c5132e21189..fcc29de6e15 100644 --- a/feature/bgp/policybase/otg_tests/import_export_multi/import_export_multi.go +++ b/feature/bgp/policybase/otg_tests/import_export_multi_test/import_export_multi_test.go @@ -13,7 +13,7 @@ // limitations under the License. // Package import_export_test covers RT-7.11: BGP Policy - Import/Export Policy Action Using Multiple Criteria -package import_export_test +package import_export_multi_test import ( "strconv" @@ -116,7 +116,7 @@ func configureImportExportAcceptAllBGPPolicy(t *testing.T, dut *ondatra.DUTDevic } stmt1.GetOrCreateActions().SetPolicyResult(oc.RoutingPolicy_PolicyResultType_ACCEPT_ROUTE) - gnmi.Replace(t, dut, gnmi.OC().RoutingPolicy().Config(), rp) + gnmi.Update(t, dut, gnmi.OC().RoutingPolicy().Config(), rp) dni := deviations.DefaultNetworkInstance(dut) pathV6 := gnmi.OC().NetworkInstance(dni).Protocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_BGP, bgpName).Bgp().Neighbor(ipv6).AfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV6_UNICAST).ApplyPolicy() @@ -130,17 +130,19 @@ func configureImportExportAcceptAllBGPPolicy(t *testing.T, dut *ondatra.DUTDevic policyV4.SetImportPolicy([]string{"routePolicy"}) policyV4.SetExportPolicy([]string{"routePolicy"}) gnmi.Replace(t, dut, pathV4.Config(), policyV4) - } func configureImportExportMultifacetMatchActionsBGPPolicy(t *testing.T, dut *ondatra.DUTDevice, ipv4 string, ipv6 string) { rejectCommunities := []string{"10:1"} acceptCommunities := []string{"20:1"} - regexCommunities := []string{"(^|\\s)30:[0-9]+($|\\s)"} + regexCommunities := []string{"^30:.*$"} addCommunitiesRefs := []string{"40:1", "40:2"} addCommunitiesSetRefsAction := []string{"add-communities"} setCommunitySetRefs := []string{"add_comm_60", "add_comm_70"} myCommunitySets := []string{"50:1"} + if deviations.BgpCommunityMemberIsAString(dut) { + regexCommunities = []string{"(^|\\s)30:[0-9]+($|\\s)"} + } root := &oc.Root{} rp := root.GetOrCreateRoutingPolicy() @@ -156,7 +158,7 @@ func configureImportExportMultifacetMatchActionsBGPPolicy(t *testing.T, dut *ond t.Fatalf("AppendNewStatement(%s) failed: %v", callPolicyStatement, err) } - // Configure regex_community:["(^|\\s)30:[0-9]+($|\\s)"] to match_community_regex statement + // Configure regex_community:["^30:.*$"] to match_community_regex statement communitySetRegex := rp.GetOrCreateDefinedSets().GetOrCreateBgpDefinedSets().GetOrCreateCommunitySet(regexCommunitySet) pd2cs1 := []oc.RoutingPolicy_DefinedSets_BgpDefinedSets_CommunitySet_CommunityMember_Union{} @@ -269,9 +271,9 @@ func configureImportExportMultifacetMatchActionsBGPPolicy(t *testing.T, dut *ond if deviations.BgpCommunitySetRefsUnsupported(dut) { t.Logf("TODO: community-set-refs not supported b/316833803") } else { - stmt3.GetOrCreateActions().GetOrCreateBgpActions().GetSetCommunity().GetOrCreateReference().SetCommunitySetRefs(addCommunitiesSetRefsAction) - stmt3.GetOrCreateActions().GetOrCreateBgpActions().GetSetCommunity().SetMethod(bgpActionMethod) - stmt3.GetOrCreateActions().GetOrCreateBgpActions().GetSetCommunity().SetOptions(bgpSetCommunityOptionType) + stmt3.GetOrCreateActions().GetOrCreateBgpActions().GetOrCreateSetCommunity().GetOrCreateReference().SetCommunitySetRefs(addCommunitiesSetRefsAction) + stmt3.GetOrCreateActions().GetOrCreateBgpActions().GetOrCreateSetCommunity().SetMethod(bgpActionMethod) + stmt3.GetOrCreateActions().GetOrCreateBgpActions().GetOrCreateSetCommunity().SetOptions(bgpSetCommunityOptionType) } stmt3.GetOrCreateActions().SetPolicyResult(nextstatementResult) @@ -324,9 +326,9 @@ func configureImportExportMultifacetMatchActionsBGPPolicy(t *testing.T, dut *ond t.Logf("TODO: community-set-refs not supported b/316833803") } else { // TODO: Add bgp-actions: community-set-refs to match_comm_and_prefix_add_2_community_sets statement - stmt4.GetOrCreateActions().GetOrCreateBgpActions().GetSetCommunity().GetOrCreateReference().SetCommunitySetRefs(setCommunitySetRefs) - stmt4.GetOrCreateActions().GetOrCreateBgpActions().GetSetCommunity().SetMethod(oc.SetCommunity_Method_REFERENCE) - stmt4.GetOrCreateActions().GetOrCreateBgpActions().GetSetCommunity().SetOptions(oc.BgpPolicy_BgpSetCommunityOptionType_ADD) + stmt4.GetOrCreateActions().GetOrCreateBgpActions().GetOrCreateSetCommunity().GetOrCreateReference().SetCommunitySetRefs(setCommunitySetRefs) + stmt4.GetOrCreateActions().GetOrCreateBgpActions().GetOrCreateSetCommunity().SetMethod(oc.SetCommunity_Method_REFERENCE) + stmt4.GetOrCreateActions().GetOrCreateBgpActions().GetOrCreateSetCommunity().SetOptions(oc.BgpPolicy_BgpSetCommunityOptionType_ADD) } // set-local-pref = 5 stmt4.GetOrCreateActions().GetOrCreateBgpActions().SetSetLocalPref(localPref) diff --git a/feature/bgp/policybase/otg_tests/import_export_multi/metadata.textproto b/feature/bgp/policybase/otg_tests/import_export_multi_test/metadata.textproto similarity index 94% rename from feature/bgp/policybase/otg_tests/import_export_multi/metadata.textproto rename to feature/bgp/policybase/otg_tests/import_export_multi_test/metadata.textproto index 82c296ae6d0..a1e6e2490a2 100644 --- a/feature/bgp/policybase/otg_tests/import_export_multi/metadata.textproto +++ b/feature/bgp/policybase/otg_tests/import_export_multi_test/metadata.textproto @@ -20,5 +20,6 @@ platform_exceptions: { 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 } } diff --git a/feature/bgp/policybase/otg_tests/nested_policies/README.md b/feature/bgp/policybase/otg_tests/nested_policies/README.md index 81191140c0e..393028ea104 100644 --- a/feature/bgp/policybase/otg_tests/nested_policies/README.md +++ b/feature/bgp/policybase/otg_tests/nested_policies/README.md @@ -291,11 +291,14 @@ For each section of configuration below, prepare a gnmi.SetBatch with all the c * /network-instances/network-instance/protocols/protocol/bgp/rib/afi-safis/afi-safi/ipv4-unicast/loc-rib/routes/route/prefix * /network-instances/network-instance/protocols/protocol/bgp/rib/attr-sets/attr-set/state/med -## Protocol/RPC Parameter Coverage - -* gNMI - * Subscribe (ONCE) - * Set (REPLACE) +## OpenConfig Path and RPC Coverage + +```yaml +rpcs: + gnmi: + gNMI.Get: + gNMI.Subscribe: +``` ## Required DUT platform diff --git a/feature/bgp/policybase/otg_tests/nested_policies/metadata.textproto b/feature/bgp/policybase/otg_tests/nested_policies/metadata.textproto index e6691f8f821..712cd851126 100644 --- a/feature/bgp/policybase/otg_tests/nested_policies/metadata.textproto +++ b/feature/bgp/policybase/otg_tests/nested_policies/metadata.textproto @@ -18,3 +18,13 @@ platform_exceptions: { } } +platform_exceptions: { + platform: { + vendor: CISCO + } + deviations: { + skip_setting_statement_for_policy: true + skip_checking_attribute_index: true + } +} + diff --git a/feature/bgp/policybase/otg_tests/nested_policies/nested_policies_test.go b/feature/bgp/policybase/otg_tests/nested_policies/nested_policies_test.go index d787c209d6e..662bb3f8957 100644 --- a/feature/bgp/policybase/otg_tests/nested_policies/nested_policies_test.go +++ b/feature/bgp/policybase/otg_tests/nested_policies/nested_policies_test.go @@ -162,10 +162,10 @@ type flowConfig struct { func TestBGPNestedPolicies(t *testing.T) { dut := ondatra.DUT(t, "dut") configureDUT(t, dut) - ate := ondatra.ATE(t, "ate") top := gosnappi.NewConfig() devs := configureOTG(t, ate, top) + td := testData{ dut: dut, ate: ate, @@ -235,6 +235,7 @@ func TestBGPNestedPolicies(t *testing.T) { // configureImportRoutingPolicy configures the dut for IPv4 BGP nested import policy test. func configureImportRoutingPolicy(t *testing.T, dut *ondatra.DUTDevice) { + batch := &gnmi.SetBatch{} root := &oc.Root{} rp := root.GetOrCreateRoutingPolicy() @@ -244,7 +245,10 @@ func configureImportRoutingPolicy(t *testing.T, dut *ondatra.DUTDevice) { if err != nil { t.Fatalf("AppendNewStatement(%s) failed: %v", v4LPStatement, err) } - stmt1.GetOrCreateActions().SetPolicyResult(oc.RoutingPolicy_PolicyResultType_ACCEPT_ROUTE) + if !deviations.SkipSettingStatementForPolicy(dut) { + t.Logf("Setting statement for policy") + stmt1.GetOrCreateActions().SetPolicyResult(oc.RoutingPolicy_PolicyResultType_ACCEPT_ROUTE) + } stmt1.GetOrCreateActions().GetOrCreateBgpActions().SetSetLocalPref(localPref) // Configure a route-policy to match the prefix. @@ -253,7 +257,10 @@ func configureImportRoutingPolicy(t *testing.T, dut *ondatra.DUTDevice) { if err != nil { t.Fatalf("AppendNewStatement(%s) failed: %v", v4PrefixStatement, err) } - stmt2.GetOrCreateActions().SetPolicyResult(oc.RoutingPolicy_PolicyResultType_ACCEPT_ROUTE) + if !deviations.SkipSettingStatementForPolicy(dut) { + stmt2.GetOrCreateActions().SetPolicyResult(oc.RoutingPolicy_PolicyResultType_ACCEPT_ROUTE) + } + t.Logf("Configuring nested policy") // Configure a prefix-set for route filtering/matching. prefixSet := rp.GetOrCreateDefinedSets().GetOrCreatePrefixSet(v4PrefixSet) @@ -264,7 +271,7 @@ func configureImportRoutingPolicy(t *testing.T, dut *ondatra.DUTDevice) { stmt2.GetOrCreateConditions().GetOrCreateMatchPrefixSet().SetMatchSetOptions(oc.RoutingPolicy_MatchSetOptionsRestrictedType_ANY) } stmt2.GetOrCreateConditions().GetOrCreateMatchPrefixSet().SetPrefixSet(v4PrefixSet) - gnmi.Replace(t, dut, gnmi.OC().RoutingPolicy().Config(), rp) + gnmi.BatchReplace(batch, gnmi.OC().RoutingPolicy().Config(), rp) // Configure the nested policy. dni := deviations.DefaultNetworkInstance(dut) @@ -290,14 +297,28 @@ func validateImportRoutingPolicy(t *testing.T, dut *ondatra.DUTDevice, ate *onda if prefixAddr[0] == advertisedIPv41.address { found = true t.Logf("Found Route(prefix %s, origin: %v, pathid: %d) => %s", k.Prefix, k.Origin, k.PathId, lr.GetPrefix()) - attrSet := gnmi.Get[*oc.NetworkInstance_Protocol_Bgp_Rib_AttrSet](t, dut, bgpRIBPath.AttrSet(lr.GetAttrIndex()).State()) - if attrSet == nil || attrSet.GetLocalPref() != localPref { - t.Errorf("No local pref found for prefix %s", advertisedIPv41.address) + if !deviations.SkipCheckingAttributeIndex(dut) { + attrSet := gnmi.Get[*oc.NetworkInstance_Protocol_Bgp_Rib_AttrSet](t, dut, bgpRIBPath.AttrSet(lr.GetAttrIndex()).State()) + if attrSet == nil || attrSet.GetLocalPref() != localPref { + t.Errorf("No local pref found for prefix %s", advertisedIPv41.address) + } + break + } else { + attrSetList := gnmi.GetAll[*oc.NetworkInstance_Protocol_Bgp_Rib_AttrSet](t, dut, bgpRIBPath.AttrSetAny().State()) + foundLP := false + for _, attrSet := range attrSetList { + if attrSet.GetLocalPref() == localPref { + foundLP = true + t.Logf("Found local pref %d for prefix %s", attrSet.GetLocalPref(), advertisedIPv41.address) + break + } + } + if !foundLP { + t.Errorf("No local pref found for prefix %s", advertisedIPv41.address) + } } - break } } - if !found { t.Errorf("No Route found for prefix %s", advertisedIPv41.address) } @@ -305,6 +326,7 @@ func validateImportRoutingPolicy(t *testing.T, dut *ondatra.DUTDevice, ate *onda // configureExportRoutingPolicy configures the dut for IPv4 BGP nested export policy test. func configureExportRoutingPolicy(t *testing.T, dut *ondatra.DUTDevice) { + batch := &gnmi.SetBatch{} root := &oc.Root{} rp := root.GetOrCreateRoutingPolicy() t.Logf("Configuring export routing policy") @@ -313,7 +335,9 @@ func configureExportRoutingPolicy(t *testing.T, dut *ondatra.DUTDevice) { if err != nil { t.Fatalf("AppendNewStatement(%s) failed: %v", v4ASPStatement, err) } - stmt1.GetOrCreateActions().SetPolicyResult(oc.RoutingPolicy_PolicyResultType_ACCEPT_ROUTE) + if !deviations.SkipSettingStatementForPolicy(dut) { + stmt1.GetOrCreateActions().SetPolicyResult(oc.RoutingPolicy_PolicyResultType_ACCEPT_ROUTE) + } stmt1.GetOrCreateActions().GetOrCreateBgpActions().GetOrCreateSetAsPathPrepend().SetAsn(dutAS) pdef2 := rp.GetOrCreatePolicyDefinition(v4MedPolicy) @@ -321,9 +345,12 @@ func configureExportRoutingPolicy(t *testing.T, dut *ondatra.DUTDevice) { if err != nil { t.Fatalf("AppendNewStatement(%s) failed: %v", v4MedStatement, err) } - stmt2.GetOrCreateActions().SetPolicyResult(oc.RoutingPolicy_PolicyResultType_ACCEPT_ROUTE) + + if !deviations.SkipSettingStatementForPolicy(dut) { + stmt2.GetOrCreateActions().SetPolicyResult(oc.RoutingPolicy_PolicyResultType_ACCEPT_ROUTE) + } stmt2.GetOrCreateActions().GetOrCreateBgpActions().SetSetMed(oc.UnionUint32(med)) - gnmi.Replace(t, dut, gnmi.OC().RoutingPolicy().Config(), rp) + gnmi.BatchReplace(batch, gnmi.OC().RoutingPolicy().Config(), rp) // Configure the nested policy. dni := deviations.DefaultNetworkInstance(dut) @@ -338,10 +365,12 @@ func configureExportRoutingPolicy(t *testing.T, dut *ondatra.DUTDevice) { policy := root.GetOrCreateNetworkInstance(dni).GetOrCreateProtocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_BGP, bgpName).GetOrCreateBgp().GetOrCreateNeighbor(atePort1.IPv4).GetOrCreateAfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV4_UNICAST).GetOrCreateApplyPolicy() policy.SetExportPolicy([]string{v4ASPPolicy}) gnmi.Update(t, dut, path.Config(), policy) - time.Sleep(time.Second * 60) + time.Sleep(time.Second * 120) } func validateExportRoutingPolicy(t *testing.T, dut *ondatra.DUTDevice, ate *ondatra.ATEDevice) { + t.Logf("Validating Export Routing Policy, waiting for 120 seconds") + time.Sleep(time.Second * 120) bgpPrefixes := gnmi.GetAll[*otgtelemetry.BgpPeer_UnicastIpv4Prefix](t, ate.OTG(), gnmi.OTG().BgpPeer("atePort1.BGP4.peer").UnicastIpv4PrefixAny().State()) found := false for _, bgpPrefix := range bgpPrefixes { @@ -376,6 +405,7 @@ func validateExportRoutingPolicy(t *testing.T, dut *ondatra.DUTDevice, ate *onda // configureImportRoutingPolicyV6 configures the dut for IPv6 BGP nested import policy test. func configureImportRoutingPolicyV6(t *testing.T, dut *ondatra.DUTDevice) { + batch := &gnmi.SetBatch{} root := &oc.Root{} rp := root.GetOrCreateRoutingPolicy() t.Logf("Configuring import routing policy") @@ -384,7 +414,10 @@ func configureImportRoutingPolicyV6(t *testing.T, dut *ondatra.DUTDevice) { if err != nil { t.Fatalf("AppendNewStatement(%s) failed: %v", v6LPStatement, err) } - stmt1.GetOrCreateActions().SetPolicyResult(oc.RoutingPolicy_PolicyResultType_ACCEPT_ROUTE) + if !deviations.SkipSettingStatementForPolicy(dut) { + t.Logf("Setting statement for policy") + stmt1.GetOrCreateActions().SetPolicyResult(oc.RoutingPolicy_PolicyResultType_ACCEPT_ROUTE) + } stmt1.GetOrCreateActions().GetOrCreateBgpActions().SetSetLocalPref(localPref) pdef2 := rp.GetOrCreatePolicyDefinition(v6PrefixPolicy) @@ -392,7 +425,9 @@ func configureImportRoutingPolicyV6(t *testing.T, dut *ondatra.DUTDevice) { if err != nil { t.Fatalf("AppendNewStatement(%s) failed: %v", v6PrefixStatement, err) } - stmt2.GetOrCreateActions().SetPolicyResult(oc.RoutingPolicy_PolicyResultType_ACCEPT_ROUTE) + if !deviations.SkipSettingStatementForPolicy(dut) { + stmt2.GetOrCreateActions().SetPolicyResult(oc.RoutingPolicy_PolicyResultType_ACCEPT_ROUTE) + } prefixSet := rp.GetOrCreateDefinedSets().GetOrCreatePrefixSet(v6PrefixSet) prefixSet.SetMode(oc.PrefixSet_Mode_IPV6) @@ -402,7 +437,7 @@ func configureImportRoutingPolicyV6(t *testing.T, dut *ondatra.DUTDevice) { stmt2.GetOrCreateConditions().GetOrCreateMatchPrefixSet().SetMatchSetOptions(oc.RoutingPolicy_MatchSetOptionsRestrictedType_ANY) } stmt2.GetOrCreateConditions().GetOrCreateMatchPrefixSet().SetPrefixSet(v6PrefixSet) - gnmi.Replace(t, dut, gnmi.OC().RoutingPolicy().Config(), rp) + gnmi.BatchReplace(batch, gnmi.OC().RoutingPolicy().Config(), rp) // Configure the nested policy. dni := deviations.DefaultNetworkInstance(dut) @@ -416,6 +451,7 @@ func configureImportRoutingPolicyV6(t *testing.T, dut *ondatra.DUTDevice) { policy := root.GetOrCreateNetworkInstance(dni).GetOrCreateProtocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_BGP, bgpName).GetOrCreateBgp().GetOrCreateNeighbor(atePort1.IPv6).GetOrCreateAfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV6_UNICAST).GetOrCreateApplyPolicy() policy.SetImportPolicy([]string{v6LPPolicy}) gnmi.Update(t, dut, path.Config(), policy) + } func validateImportRoutingPolicyV6(t *testing.T, dut *ondatra.DUTDevice, ate *ondatra.ATEDevice) { @@ -425,15 +461,29 @@ func validateImportRoutingPolicyV6(t *testing.T, dut *ondatra.DUTDevice, ate *on found := false for k, lr := range locRib.Route { prefixAddr := strings.Split(lr.GetPrefix(), "/") - t.Logf("lr.GetPrefix() -> %s, prefixAddr[0] -> %s, advertisedIPv61.address = %s", lr.GetPrefix(), prefixAddr[0], advertisedIPv61.address) if prefixAddr[0] == advertisedIPv61.address { found = true t.Logf("Found Route(prefix %s, origin: %v, pathid: %d) => %s", k.Prefix, k.Origin, k.PathId, lr.GetPrefix()) - attrSet := gnmi.Get[*oc.NetworkInstance_Protocol_Bgp_Rib_AttrSet](t, dut, bgpRIBPath.AttrSet(lr.GetAttrIndex()).State()) - if attrSet == nil || attrSet.GetLocalPref() != localPref { - t.Errorf("No local pref found for prefix %s", advertisedIPv61.address) + if !deviations.SkipCheckingAttributeIndex(dut) { + attrSet := gnmi.Get[*oc.NetworkInstance_Protocol_Bgp_Rib_AttrSet](t, dut, bgpRIBPath.AttrSet(lr.GetAttrIndex()).State()) + if attrSet == nil || attrSet.GetLocalPref() != localPref { + t.Errorf("No local pref found for prefix %s", advertisedIPv61.address) + } + break + } else { + attrSetList := gnmi.GetAll[*oc.NetworkInstance_Protocol_Bgp_Rib_AttrSet](t, dut, bgpRIBPath.AttrSetAny().State()) + foundLP := false + for _, attrSet := range attrSetList { + if attrSet.GetLocalPref() == localPref { + foundLP = true + t.Logf("Found local pref %d for prefix %s", attrSet.GetLocalPref(), advertisedIPv61.address) + break + } + } + if !foundLP { + t.Errorf("No local pref found for prefix %s", advertisedIPv41.address) + } } - break } } if !found { @@ -443,6 +493,7 @@ func validateImportRoutingPolicyV6(t *testing.T, dut *ondatra.DUTDevice, ate *on // configureExportRoutingPolicyV6 configures the dut for IPv6 BGP nested export policy test. func configureExportRoutingPolicyV6(t *testing.T, dut *ondatra.DUTDevice) { + batch := &gnmi.SetBatch{} root := &oc.Root{} rp := root.GetOrCreateRoutingPolicy() t.Logf("Configuring export routing policy") @@ -451,7 +502,9 @@ func configureExportRoutingPolicyV6(t *testing.T, dut *ondatra.DUTDevice) { if err != nil { t.Fatalf("AppendNewStatement(%s) failed: %v", v6ASPStatement, err) } - stmt1.GetOrCreateActions().SetPolicyResult(oc.RoutingPolicy_PolicyResultType_ACCEPT_ROUTE) + if !deviations.SkipSettingStatementForPolicy(dut) { + stmt1.GetOrCreateActions().SetPolicyResult(oc.RoutingPolicy_PolicyResultType_ACCEPT_ROUTE) + } stmt1.GetOrCreateActions().GetOrCreateBgpActions().GetOrCreateSetAsPathPrepend().SetAsn(dutAS) pdef2 := rp.GetOrCreatePolicyDefinition(v6MedPolicy) @@ -459,9 +512,11 @@ func configureExportRoutingPolicyV6(t *testing.T, dut *ondatra.DUTDevice) { if err != nil { t.Fatalf("AppendNewStatement(%s) failed: %v", v6MedStatement, err) } - stmt2.GetOrCreateActions().SetPolicyResult(oc.RoutingPolicy_PolicyResultType_ACCEPT_ROUTE) + if !deviations.SkipSettingStatementForPolicy(dut) { + stmt2.GetOrCreateActions().SetPolicyResult(oc.RoutingPolicy_PolicyResultType_ACCEPT_ROUTE) + } stmt2.GetOrCreateActions().GetOrCreateBgpActions().SetSetMed(oc.UnionUint32(med)) - gnmi.Replace(t, dut, gnmi.OC().RoutingPolicy().Config(), rp) + gnmi.BatchReplace(batch, gnmi.OC().RoutingPolicy().Config(), rp) // Configure the nested policy. dni := deviations.DefaultNetworkInstance(dut) @@ -580,7 +635,6 @@ func checkTraffic(t *testing.T, td testData, flowName string) { func (td *testData) advertiseRoutesWithEBGP(t *testing.T) { t.Helper() - root := &oc.Root{} ni := root.GetOrCreateNetworkInstance(deviations.DefaultNetworkInstance(td.dut)) bgpP := ni.GetOrCreateProtocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_BGP, bgpName) @@ -593,6 +647,16 @@ func (td *testData) advertiseRoutesWithEBGP(t *testing.T) { g.GetOrCreateAfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV4_UNICAST).Enabled = ygot.Bool(true) g.GetOrCreateAfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV6_UNICAST).Enabled = ygot.Bool(true) + t.Logf("Configuring route-policy for BGP on DUT") + rp := root.GetOrCreateRoutingPolicy() + pdef := rp.GetOrCreatePolicyDefinition("PERMIT-ALL") + stmt, err := pdef.AppendNewStatement("20") + if err != nil { + t.Fatalf("AppendNewStatement(%s) failed: %v", "20", err) + } + stmt.GetOrCreateActions().PolicyResult = oc.RoutingPolicy_PolicyResultType_ACCEPT_ROUTE + gnmi.Update(t, td.dut, gnmi.OC().RoutingPolicy().Config(), rp) + pgv4 := bgp.GetOrCreatePeerGroup(peerGrpNamev4) pgv4.PeerGroupName = ygot.String(peerGrpNamev4) pgv6 := bgp.GetOrCreatePeerGroup(peerGrpNamev6) @@ -601,19 +665,34 @@ func (td *testData) advertiseRoutesWithEBGP(t *testing.T) { nV41.SetPeerAs(ateAS1) nV41.GetOrCreateAfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV4_UNICAST).Enabled = ygot.Bool(true) nV41.PeerGroup = ygot.String(peerGrpNamev4) + afisafiv41 := nV41.GetOrCreateAfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV4_UNICAST) + afisafiv41.GetOrCreateApplyPolicy().SetImportPolicy([]string{"PERMIT-ALL"}) + afisafiv41.GetOrCreateApplyPolicy().SetExportPolicy([]string{"PERMIT-ALL"}) + nV42 := bgp.GetOrCreateNeighbor(atePort2.IPv4) nV42.SetPeerAs(ateAS2) nV42.GetOrCreateAfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV4_UNICAST).Enabled = ygot.Bool(true) nV42.PeerGroup = ygot.String(peerGrpNamev4) + afisafiv42 := nV42.GetOrCreateAfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV4_UNICAST) + afisafiv42.GetOrCreateApplyPolicy().SetImportPolicy([]string{"PERMIT-ALL"}) + afisafiv42.GetOrCreateApplyPolicy().SetExportPolicy([]string{"PERMIT-ALL"}) nV61 := bgp.GetOrCreateNeighbor(atePort1.IPv6) nV61.SetPeerAs(ateAS1) nV61.GetOrCreateAfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV6_UNICAST).Enabled = ygot.Bool(true) nV61.PeerGroup = ygot.String(peerGrpNamev6) + afisafiv61 := nV61.GetOrCreateAfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV6_UNICAST) + afisafiv61.GetOrCreateApplyPolicy().SetImportPolicy([]string{"PERMIT-ALL"}) + afisafiv61.GetOrCreateApplyPolicy().SetExportPolicy([]string{"PERMIT-ALL"}) + nV62 := bgp.GetOrCreateNeighbor(atePort2.IPv6) nV62.SetPeerAs(ateAS2) nV62.GetOrCreateAfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV6_UNICAST).Enabled = ygot.Bool(true) nV62.PeerGroup = ygot.String(peerGrpNamev6) + afisafiv62 := nV62.GetOrCreateAfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV6_UNICAST) + afisafiv62.GetOrCreateApplyPolicy().SetImportPolicy([]string{"PERMIT-ALL"}) + afisafiv62.GetOrCreateApplyPolicy().SetExportPolicy([]string{"PERMIT-ALL"}) + gnmi.Update(t, td.dut, gnmi.OC().NetworkInstance(deviations.DefaultNetworkInstance(td.dut)).Config(), ni) // Configure eBGP on OTG port1. @@ -693,6 +772,10 @@ func configureDUT(t *testing.T, dut *ondatra.DUTDevice) { gnmi.BatchReplace(b, gnmi.OC().Interface(p1.Name()).Config(), dutPort1.NewOCInterface(p1.Name(), dut)) gnmi.BatchReplace(b, gnmi.OC().Interface(p2.Name()).Config(), dutPort2.NewOCInterface(p2.Name(), dut)) b.Set(t, dut) + // bs := cfgplugins.NewBGPSession(t, cfgplugins.PortCount2, nil) + // bs.WithEBGP(t, []oc.E_BgpTypes_AFI_SAFI_TYPE{oc.BgpTypes_AFI_SAFI_TYPE_IPV4_UNICAST, oc.BgpTypes_AFI_SAFI_TYPE_IPV6_UNICAST}, []string{"port1", "port2"}, true, true) + // t.Logf("Wait for 2minutes for the OTG config to be created, now check in the DUT") + // time.Sleep(2 * time.Minute) if deviations.ExplicitPortSpeed(dut) { fptest.SetPortSpeed(t, p1) diff --git a/feature/bgp/policybase/otg_tests/prefix_set_test/README.md b/feature/bgp/policybase/otg_tests/prefix_set_test/README.md index 1991f58c16b..f4cdf076f65 100644 --- a/feature/bgp/policybase/otg_tests/prefix_set_test/README.md +++ b/feature/bgp/policybase/otg_tests/prefix_set_test/README.md @@ -48,4 +48,32 @@ N/A Protocol/RPC Parameter coverage N/A Minimum DUT platform requirement -vRX \ No newline at end of file +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 + /routing-policy/defined-sets/prefix-sets/prefix-set/config/mode: + /routing-policy/defined-sets/prefix-sets/prefix-set/config/name: + /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: + /routing-policy/policy-definitions/policy-definition/statements/statement/conditions/match-prefix-set/config/match-set-options: + /routing-policy/policy-definitions/policy-definition/statements/statement/conditions/match-prefix-set/config/prefix-set: + + ## State paths + /network-instances/network-instance/protocols/protocol/bgp/neighbors/neighbor/state/session-state: + /network-instances/network-instance/protocols/protocol/bgp/neighbors/neighbor/afi-safis/afi-safi/state/prefixes/installed: + /network-instances/network-instance/protocols/protocol/bgp/neighbors/neighbor/afi-safis/afi-safi/state/prefixes/received-pre-policy: + /network-instances/network-instance/protocols/protocol/bgp/neighbors/neighbor/afi-safis/afi-safi/state/prefixes/sent: + /routing-policy/policy-definitions/policy-definition/statements/statement/state/name: + +rpcs: + gnmi: + gNMI.Set: + gNMI.Subscribe: +``` diff --git a/feature/bgp/policybase/otg_tests/prefix_set_test/bgp_prefix_set_test.go b/feature/bgp/policybase/otg_tests/prefix_set_test/bgp_prefix_set_test.go index 1b0d1c21391..0175455dec8 100644 --- a/feature/bgp/policybase/otg_tests/prefix_set_test/bgp_prefix_set_test.go +++ b/feature/bgp/policybase/otg_tests/prefix_set_test/bgp_prefix_set_test.go @@ -15,6 +15,7 @@ package bgp_prefix_set_test import ( + "fmt" "testing" "time" @@ -22,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/helpers" "github.com/openconfig/ondatra" "github.com/openconfig/ondatra/gnmi" "github.com/openconfig/ondatra/gnmi/oc" @@ -38,6 +40,7 @@ const ( peerGrpName = "BGP-PEER-GROUP" dutAS = 65501 ateAS = 65502 + ateAS2 = 65503 plenIPv4 = 30 plenIPv6 = 126 v4Prefixes = true @@ -95,12 +98,12 @@ var ( nbrAddr: atePort2.IPv4, isV4: true, afiSafi: oc.BgpTypes_AFI_SAFI_TYPE_IPV4_UNICAST, - as: ateAS} + as: ateAS2} ebgp2NbrV6 = &bgpNeighbor{ nbrAddr: atePort2.IPv6, isV4: false, afiSafi: oc.BgpTypes_AFI_SAFI_TYPE_IPV6_UNICAST, - as: ateAS} + as: ateAS2} ebgpNbrs = []*bgpNeighbor{ebgp1NbrV4, ebgp1NbrV6, ebgp2NbrV4, ebgp2NbrV6} route1 = &route{prefix: "10.23.15.1", maskLen: 32, isV4: true} @@ -256,7 +259,7 @@ func bgpCreateNbr(localAs, peerAs uint32, dut *ondatra.DUTDevice) *oc.NetworkIns global.GetOrCreateAfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV6_UNICAST).Enabled = ygot.Bool(true) pg := bgp.GetOrCreatePeerGroup(peerGrpName) - pg.PeerAs = ygot.Uint32(ateAS) + pg.PeerAs = ygot.Uint32(peerAs) pg.PeerGroupName = ygot.String(peerGrpName) for _, nbr := range ebgpNbrs { @@ -340,11 +343,11 @@ func configureOTG(t *testing.T, otg *otg.OTG) { // eBGP v4 seesion on Port2. iDut2Bgp := iDut2Dev.Bgp().SetRouterId(iDut2Ipv4.Address()) iDut2Bgp4Peer := iDut2Bgp.Ipv4Interfaces().Add().SetIpv4Name(iDut2Ipv4.Name()).Peers().Add().SetName(atePort2.Name + ".BGP4.peer") - iDut2Bgp4Peer.SetPeerAddress(iDut2Ipv4.Gateway()).SetAsNumber(ateAS).SetAsType(gosnappi.BgpV4PeerAsType.EBGP) + iDut2Bgp4Peer.SetPeerAddress(iDut2Ipv4.Gateway()).SetAsNumber(ateAS2).SetAsType(gosnappi.BgpV4PeerAsType.EBGP) iDut2Bgp4Peer.LearnedInformationFilter().SetUnicastIpv4Prefix(true) // eBGP v6 seesion on Port2. iDut2Bgp6Peer := iDut2Bgp.Ipv6Interfaces().Add().SetIpv6Name(iDut2Ipv6.Name()).Peers().Add().SetName(atePort2.Name + ".BGP6.peer") - iDut2Bgp6Peer.SetPeerAddress(iDut2Ipv6.Gateway()).SetAsNumber(ateAS).SetAsType(gosnappi.BgpV6PeerAsType.EBGP) + iDut2Bgp6Peer.SetPeerAddress(iDut2Ipv6.Gateway()).SetAsNumber(ateAS2).SetAsType(gosnappi.BgpV6PeerAsType.EBGP) iDut2Bgp6Peer.LearnedInformationFilter().SetUnicastIpv6Prefix(true) // eBGP V4 routes from Port1. @@ -382,7 +385,7 @@ func validatePrefixCount(t *testing.T, dut *ondatra.DUTDevice, nbr bgpNeighbor, prefixPath := statePath.Neighbor(nbr.nbrAddr).AfiSafi(nbr.afiSafi).Prefixes() // Waiting for Installed count to get updated after session comes up or policy is applied - gotInstalled, ok := gnmi.Watch(t, dut, prefixPath.Installed().State(), 20*time.Second, func(val *ygnmi.Value[uint32]) bool { // increased wait time to 20s from 10s + gotInstalled, ok := gnmi.Watch(t, dut, prefixPath.Installed().State(), 40*time.Second, func(val *ygnmi.Value[uint32]) bool { // increased wait time to 20s from 10s gotInstalled, _ := val.Val() t.Logf("Prefix that are installed %v and want %v", gotInstalled, wantInstalled) return gotInstalled == wantInstalled @@ -391,20 +394,18 @@ func validatePrefixCount(t *testing.T, dut *ondatra.DUTDevice, nbr bgpNeighbor, t.Errorf("Installed prefixes mismatch: got %v, want %v", gotInstalled, wantInstalled) } - if !deviations.MissingPrePolicyReceivedRoutes(dut) { - // Waiting for Received count to get updated after session comes up or policy is applied - gotRx, ok := gnmi.Watch(t, dut, prefixPath.ReceivedPrePolicy().State(), 10*time.Second, func(val *ygnmi.Value[uint32]) bool { - gotRx, _ := val.Val() - t.Logf("Prefix that are received %v and want %v", gotRx, wantRx) - return gotRx == wantRx - }).Await(t) - if !ok { - t.Errorf("Received prefixes mismatch: got %v, want %v", gotRx, wantRx) - } + // Waiting for Received count to get updated after session comes up or policy is applied + gotRx, ok := gnmi.Watch(t, dut, prefixPath.ReceivedPrePolicy().State(), 40*time.Second, func(val *ygnmi.Value[uint32]) bool { + gotRx, _ := val.Val() + t.Logf("Prefix that are received %v and want %v", gotRx, wantRx) + return gotRx == wantRx + }).Await(t) + if !ok { + t.Errorf("Received prefixes mismatch: got %v, want %v", gotRx, wantRx) } // Waiting for Sent count to get updated after session comes up or policy is applied - gotSent, ok := gnmi.Watch(t, dut, prefixPath.Sent().State(), 10*time.Second, func(val *ygnmi.Value[uint32]) bool { + gotSent, ok := gnmi.Watch(t, dut, prefixPath.Sent().State(), 40*time.Second, func(val *ygnmi.Value[uint32]) bool { t.Logf("Prefix that are sent %v", prefixPath.Sent().State()) gotSent, _ := val.Val() t.Logf("Prefix that are sent %v and want %v", gotSent, wantSent) @@ -429,7 +430,7 @@ func testPrefixSet(t *testing.T, dut *ondatra.DUTDevice) { t.Run("Validate acceptance based on prefix-set policy - import policy on neighbor", func(t *testing.T) { applyPrefixSetPolicy(t, dut, []*prefixSetPolicy{prefixSet1V4, prefixSet2V4}, bgpImportIPv4, *ebgp1NbrV4, importPolicy) applyPrefixSetPolicy(t, dut, []*prefixSetPolicy{prefixSet1V6, prefixSet2V6}, bgpImportIPv6, *ebgp1NbrV6, importPolicy) - if !deviations.DefaultImportExportPolicy(dut) { + if deviations.DefaultImportExportPolicy(dut) { t.Logf("Validate for neighbour %v", ebgp1NbrV4) validatePrefixCount(t, dut, *ebgp1NbrV4, 3, 5, 0) validatePrefixCount(t, dut, *ebgp1NbrV6, 1, 5, 0) @@ -471,12 +472,22 @@ func TestBGPPrefixSet(t *testing.T) { dutConf := bgpCreateNbr(dutAS, ateAS, dut) gnmi.Replace(t, dut, dutConfPath.Config(), dutConf) + if deviations.MissingPrePolicyReceivedRoutes(dut) { + var enableSoftConfigInboundCLI string + switch dut.Vendor() { + case ondatra.CISCO: + enableSoftConfigInboundCLI = fmt.Sprintf("router bgp %v instance BGP neighbor-group %v \n address-family ipv4 unicast soft-reconfiguration inbound always \n address-family ipv6 unicast soft-reconfiguration inbound always", dutAS, peerGrpName) + default: + t.Fatalf("Unsupported vendor %s for deviation 'MissingPrePolicyReceivedRoutes'", dut.Vendor()) + } + helpers.GnmiCLIConfig(t, dut, enableSoftConfigInboundCLI) + } otg := ate.OTG() configureOTG(t, otg) verifyBgpState(t, dut) }) - if !deviations.DefaultImportExportPolicy(dut) { + if deviations.DefaultImportExportPolicy(dut) { t.Run("Validate initial prefix count", func(t *testing.T) { validatePrefixCount(t, dut, *ebgp1NbrV4, 5, 5, 0) validatePrefixCount(t, dut, *ebgp1NbrV6, 5, 5, 0) @@ -485,7 +496,7 @@ func TestBGPPrefixSet(t *testing.T) { }) } else { t.Run("Validate initial prefix count", func(t *testing.T) { - validatePrefixCount(t, dut, *ebgp1NbrV4, 0, 1, 0) + validatePrefixCount(t, dut, *ebgp1NbrV4, 0, 5, 0) validatePrefixCount(t, dut, *ebgp1NbrV6, 0, 5, 0) validatePrefixCount(t, dut, *ebgp2NbrV4, 0, 0, 0) validatePrefixCount(t, dut, *ebgp2NbrV6, 0, 0, 0) diff --git a/feature/bgp/policybase/otg_tests/prefix_set_test/metadata.textproto b/feature/bgp/policybase/otg_tests/prefix_set_test/metadata.textproto index 6b2bf873c36..cc69dc8d104 100644 --- a/feature/bgp/policybase/otg_tests/prefix_set_test/metadata.textproto +++ b/feature/bgp/policybase/otg_tests/prefix_set_test/metadata.textproto @@ -27,10 +27,18 @@ platform_exceptions: { default_network_instance: "default" missing_value_for_defaults: true skip_set_rp_match_set_options: true - default_import_export_policy: false + default_import_export_policy: true } } +platform_exceptions: { + platform: { + vendor: CISCO + } + deviations: { + prepolicy_received_routes: true + } +} tags: TAGS_AGGREGATION tags: TAGS_TRANSIT tags: TAGS_DATACENTER_EDGE diff --git a/feature/bgp/static_route_bgp_redistribution/otg_tests/static_route_bgp_redistribution_test/README.md b/feature/bgp/static_route_bgp_redistribution/otg_tests/static_route_bgp_redistribution_test/README.md index 6767c6cf0c5..4939440ceba 100644 --- a/feature/bgp/static_route_bgp_redistribution/otg_tests/static_route_bgp_redistribution_test/README.md +++ b/feature/bgp/static_route_bgp_redistribution/otg_tests/static_route_bgp_redistribution_test/README.md @@ -642,11 +642,13 @@ * /routing-policy/policy-definitions/policy-definition/statements/statement/conditions/match-tag-set/state/match-set-options * /routing-policy/policy-definitions/policy-definition/statements/statement/conditions/match-tag-set/state/tag-set -## Protocol/RPC Parameter Coverage - -* gNMI - * Get - * Set +## OpenConfig Path and RPC Coverage +```yaml +rpcs: + gnmi: + gNMI.Get: + gNMI.Set: +``` ## Required DUT platform diff --git a/feature/bgp/static_route_bgp_redistribution/otg_tests/static_route_bgp_redistribution_test/metadata.textproto b/feature/bgp/static_route_bgp_redistribution/otg_tests/static_route_bgp_redistribution_test/metadata.textproto index b128bfe709d..89b2354afb0 100644 --- a/feature/bgp/static_route_bgp_redistribution/otg_tests/static_route_bgp_redistribution_test/metadata.textproto +++ b/feature/bgp/static_route_bgp_redistribution/otg_tests/static_route_bgp_redistribution_test/metadata.textproto @@ -22,3 +22,14 @@ platform_exceptions: { skip_bgp_send_community_type: true } } +platform_exceptions: { + platform: { + vendor: ARISTA + } + deviations: { + omit_l2_mtu: true + default_network_instance: "default" + static_protocol_name: "STATIC" + skip_bgp_send_community_type: true + } +} diff --git a/feature/bgp/static_route_bgp_redistribution/otg_tests/static_route_bgp_redistribution_test/static_route_bgp_redistribution_test.go b/feature/bgp/static_route_bgp_redistribution/otg_tests/static_route_bgp_redistribution_test/static_route_bgp_redistribution_test.go index 846fd69d32d..49e72a7399b 100644 --- a/feature/bgp/static_route_bgp_redistribution/otg_tests/static_route_bgp_redistribution_test/static_route_bgp_redistribution_test.go +++ b/feature/bgp/static_route_bgp_redistribution/otg_tests/static_route_bgp_redistribution_test/static_route_bgp_redistribution_test.go @@ -181,7 +181,7 @@ func configureDUTStatic( dutOcRoot := &oc.Root{} networkInstance := dutOcRoot.GetOrCreateNetworkInstance(deviations.DefaultNetworkInstance(dut)) - networkInstanceProtocolStatic := networkInstance.GetOrCreateProtocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_STATIC, "static") + networkInstanceProtocolStatic := networkInstance.GetOrCreateProtocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_STATIC, deviations.StaticProtocolName(dut)) networkInstanceProtocolStatic.SetEnabled(true) ipv4StaticRoute := networkInstanceProtocolStatic.GetOrCreateStatic("192.168.10.0/24") @@ -1120,7 +1120,7 @@ func redistributeNullNextHopStaticRoute(t *testing.T, dut *ondatra.DUTDevice, at } policyPath := gnmi.OC().RoutingPolicy().PolicyDefinition(redistributeStaticPolicyName) - staticPath := gnmi.OC().NetworkInstance(deviations.DefaultNetworkInstance(dut)).Protocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_STATIC, "static") + staticPath := gnmi.OC().NetworkInstance(deviations.DefaultNetworkInstance(dut)).Protocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_STATIC, deviations.StaticProtocolName(dut)) otgConfig := configureOTG(t) if isV4 { @@ -1133,7 +1133,7 @@ func redistributeNullNextHopStaticRoute(t *testing.T, dut *ondatra.DUTDevice, at dutOcRoot := &oc.Root{} networkInstance := dutOcRoot.GetOrCreateNetworkInstance(deviations.DefaultNetworkInstance(dut)) - networkInstanceProtocolStatic := networkInstance.GetOrCreateProtocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_STATIC, "static") + networkInstanceProtocolStatic := networkInstance.GetOrCreateProtocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_STATIC, deviations.StaticProtocolName(dut)) networkInstanceProtocolStatic.SetEnabled(true) ipStaticRoute := networkInstanceProtocolStatic.GetOrCreateStatic(ipRoute) if !deviations.UseVendorNativeTagSetConfig(dut) { diff --git a/feature/experimental/bgp/otg_tests/bgp_override_as_path_split_horizon_test/README.md b/feature/experimental/bgp/otg_tests/bgp_override_as_path_split_horizon_test/README.md new file mode 100644 index 00000000000..b74ba3fad48 --- /dev/null +++ b/feature/experimental/bgp/otg_tests/bgp_override_as_path_split_horizon_test/README.md @@ -0,0 +1,64 @@ +# RT-1.54: BGP Override AS-path split-horizon + +## Summary + +BGP Override AS-path split-horizon + +## Topology + + ATE Port1 (AS 65502) --- DUT Port1 (AS 65501) DUT Port2 ---eBGP --- ATE Port2 (AS 65503) + +## Procedure + +* Establish BGP Session: Configure and establish an eBGP session between the DUT (Port1) and the ATE (Port1). +* Baseline Test (No "allow-own-in"): + * Advertise a prefix from the ATE (e.g., 192.168.1.0/24) with an AS-path that includes AS 65501 (DUT's AS) in the middle (e.g., AS-path: 65502 65500 65501 65499). + * Verify that the ATE Port2 doesn't receive the route. due to the presence of its own AS in the path. + * Validate session state and capabilities received on DUT using telemetry. +* Test "allow-own-as 1": + * Enable "allow-own-as 1" on the DUT. + * Re-advertise the prefix from the ATE with the same AS-path. + * Verify that the DUT accepts the route. + * Verify that the ATE Port2 receives the route. + * Validate session state and capabilities received on DUT using telemetry. +* Test "allow-own-as 3": + * Change the DUT's configuration to "allow-own-as 3". + * Test with the following AS-path occurrences: + * 1 Occurrence: 65502 65500 65501 65499 + * 3 Occurrences: 65502 65501 65501 65501 65499 + * 4 Occurrences: 65502 65501 65501 65501 65501 65499 (Should be rejected) + * Verify that the ATE Port2 receives the route with 1 and 3 occurrences of AS 65501 but rejects it with 4 occurrences. + * Validate session state and capabilities received on DUT using telemetry. +* Test "allow-own-as 4: + * Change the DUT's configuration to "allow-own-as 4". + * Test with the following AS-path occurrences: + * 1 Occurrence: 65502 65500 65501 65499 + * 3 Occurrences: 65502 65501 65501 65501 65499 + * 4 Occurrences: 65502 65501 65501 65501 65501 65499 + * Verify that the ATE Port2 receives the route with 1, 3 and 4 occurrences of AS 65501. + * Validate session state and capabilities received on DUT using telemetry. + +## OpenConfig Path and RPC Coverage + +The below example yaml defines the OC paths intended to be covered by this test. + +```yaml +paths: + ## Config paths + /network-instances/network-instance/protocols/protocol/bgp/peer-groups/peer-group/as-path-options/config/allow-own-as: + /network-instances/network-instance/protocols/protocol/bgp/neighbors/neighbor/as-path-options/config/allow-own-as: + + ## State paths + /network-instances/network-instance/protocols/protocol/bgp/peer-groups/peer-group/as-path-options/state/allow-own-as: + /network-instances/network-instance/protocols/protocol/bgp/neighbors/neighbor/as-path-options/state/allow-own-as: + +rpcs: + gnmi: + gNMI.Set: + gNMI.Subscribe: +``` + +## Minimum DUT platform requirement + +* MFF - A modular form factor device containing LINECARDs, FABRIC and redundant CONTROLLER_CARD components +* FFF - fixed form factor diff --git a/feature/experimental/bgp/otg_tests/link_bandwidth_test/README.md b/feature/experimental/bgp/otg_tests/link_bandwidth_test/README.md index 22ad233b580..5705fd88f82 100644 --- a/feature/experimental/bgp/otg_tests/link_bandwidth_test/README.md +++ b/feature/experimental/bgp/otg_tests/link_bandwidth_test/README.md @@ -143,45 +143,41 @@ bandwidth communities to routes based on a prefix match. * Other implementations consider value 0 invalid or not having link-bandwidth. These implementations create ECMP group with all routes including this one, and ignores link-bandwidth of all members - distribute traffic equally. * This policy intention is to overcome this implementation difference, by deprefering (LocPref) routes with link-bandwidth 0 (only this routes) to prevent them becoming part of multipath, and remove link-bandwidth community so route will not be treated with WCMP behavior. -## Config Parameter Coverage - -## Configuration to enable advertise communities to bgp peer - -* /network-instances/network-instance/protocols/protocol/bgp/neighbors/neighbor/config/send-community - -### Policy for community-set configuration - -* /routing-policy/defined-sets/bgp-defined-sets/ext-community-sets/ext-community-set/config/ext-community-set-name -* /routing-policy/defined-sets/bgp-defined-sets/ext-community-sets/ext-community-set/config/community-member - -### Policy action configuration - -* /routing-policy/policy-definitions/policy-definition/config/name -* /routing-policy/policy-definitions/policy-definition/statements/statement/config/name -* /routing-policy/policy-definitions/policy-definition/statements/statement/actions/config/policy-result -* /routing-policy/policy-definitions/policy-definition/statements/statement/actions/bgp-actions/set-ext-community/config/options -* /routing-policy/policy-definitions/policy-definition/statements/statement/actions/bgp-actions/set-community/config/method -* /routing-policy/policy-definitions/policy-definition/statements/statement/actions/bgp-actions/set-ext-community/reference/config/ext-community-set-refs -* /routing-policy/policy-definitions/policy-definition/statements/statement/actions/bgp-actions/config/set-local-pref - - -### Policy for community-set match configuration - -* /routing-policy/policy-definitions/policy-definition/statements/statement/conditions/bgp-conditions/match-ext-community-set/config/community-set -* /routing-policy/policy-definitions/policy-definition/statements/statement/conditions/bgp-conditions/match-ext-community-set/config/match-set-options - -### Policy attachment point configuration - -* /network-instances/network-instance/protocols/protocol/bgp/neighbors/neighbor/afi-safis/afi-safi/apply-policy/config/import-policy -* /network-instances/network-instance/protocols/protocol/bgp/neighbors/neighbor/afi-safis/afi-safi/apply-policy/config/export-policy -* /network-instances/network-instance/protocols/protocol/bgp/peer-groups/peer-group/apply-policy/config/import-policy -* /network-instances/network-instance/protocols/protocol/bgp/peer-groups/peer-group/apply-policy/config/export-policy - -## Telemetry Parameter Coverage - -* /network-instances/network-instance/protocols/protocol/bgp/rib/afi-safis/afi-safi/ipv4-unicast/neighbors/neighbor/adj-rib-in-post/routes/route/state/ext-community-index -* /network-instances/network-instance/protocols/protocol/bgp/rib/afi-safis/afi-safi/ipv6-unicast/neighbors/neighbor/adj-rib-in-post/routes/route/state/ext-community-index - +## 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 Parameter Coverage + ## Configuration to enable advertise communities to bgp peer + /network-instances/network-instance/protocols/protocol/bgp/neighbors/neighbor/config/send-community: + ## Policy for community-set configuration + /routing-policy/defined-sets/bgp-defined-sets/ext-community-sets/ext-community-set/config/ext-community-set-name: + /routing-policy/defined-sets/bgp-defined-sets/ext-community-sets/ext-community-set/config/ext-community-member: + ## Policy action configuration + /routing-policy/policy-definitions/policy-definition/config/name: + /routing-policy/policy-definitions/policy-definition/statements/statement/config/name: + /routing-policy/policy-definitions/policy-definition/statements/statement/actions/config/policy-result: + /routing-policy/policy-definitions/policy-definition/statements/statement/actions/bgp-actions/set-ext-community/config/options: + /routing-policy/policy-definitions/policy-definition/statements/statement/actions/bgp-actions/set-community/config/method: + /routing-policy/policy-definitions/policy-definition/statements/statement/actions/bgp-actions/set-ext-community/reference/config/ext-community-set-refs: + /routing-policy/policy-definitions/policy-definition/statements/statement/actions/bgp-actions/config/set-local-pref: + ## Policy for community-set match configuration + /routing-policy/policy-definitions/policy-definition/statements/statement/conditions/bgp-conditions/match-ext-community-set/config/ext-community-set: + /routing-policy/policy-definitions/policy-definition/statements/statement/conditions/bgp-conditions/match-ext-community-set/config/match-set-options: + ## Policy attachment point configuration + /network-instances/network-instance/protocols/protocol/bgp/neighbors/neighbor/afi-safis/afi-safi/apply-policy/config/import-policy: + /network-instances/network-instance/protocols/protocol/bgp/neighbors/neighbor/afi-safis/afi-safi/apply-policy/config/export-policy: + /network-instances/network-instance/protocols/protocol/bgp/peer-groups/peer-group/apply-policy/config/import-policy: + /network-instances/network-instance/protocols/protocol/bgp/peer-groups/peer-group/apply-policy/config/export-policy: + ## Telemetry Parameter Coverage + /network-instances/network-instance/protocols/protocol/bgp/rib/afi-safis/afi-safi/ipv4-unicast/neighbors/neighbor/adj-rib-in-post/routes/route/state/ext-community-index: + /network-instances/network-instance/protocols/protocol/bgp/rib/afi-safis/afi-safi/ipv6-unicast/neighbors/neighbor/adj-rib-in-post/routes/route/state/ext-community-index: +rpcs: + gnmi: + gNMI.Subscribe: +``` ## Minimum DUT Required vRX - Virtual Router Device 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 a45aaefada9..dddf7f24868 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 @@ -15,6 +15,8 @@ package link_bandwidth_test import ( + "strconv" + "strings" "testing" "time" @@ -32,29 +34,36 @@ import ( ) const ( - ipv4PrefixLen = 30 - ipv6PrefixLen = 126 - v41Route = "203.0.113.0" - v41TrafficStart = "203.0.113.1" - v42Route = "203.0.114.0" - v42TrafficStart = "203.0.114.1" - v43Route = "203.0.115.0" - v43TrafficStart = "203.0.115.1" - v4RoutePrefix = uint32(24) - v61Route = "2001:db8:128:128::0" - v61TrafficStart = "2001:db8:128:128::1" - v62Route = "2001:db8:128:129::0" - v62TrafficStart = "2001:db8:128:129::1" - v63Route = "2001:db8:128:130::0" - v63TrafficStart = "2001:db8:128:130::1" - v6RoutePrefix = uint32(64) - dutAS = uint32(65656) - ateAS = uint32(65657) - bgpName = "BGP" - maskLenExact = "exact" - localPref = 200 - v4Flow = "flow-v4" - v6Flow = "flow-v6" + ipv4PrefixLen = 30 + ipv6PrefixLen = 126 + v41Route = "203.0.113.0" + v41TrafficStart = "203.0.113.1" + v42Route = "203.0.114.0" + v42TrafficStart = "203.0.114.1" + v43Route = "203.0.115.0" + v43TrafficStart = "203.0.115.1" + v4RoutePrefix = uint32(24) + v61Route = "2001:db8:128:128::0" + v61RouteOtg = "2001:db8:128:128::" + v61RouteAdvertise = "2001:db8:128:128::/64" + v61TrafficStart = "2001:db8:128:128::1" + v62Route = "2001:db8:128:129::0" + v62RouteAdvertise = "2001:db8:128:129::/64" + v62RouteOtg = "2001:db8:128:129::" + v62TrafficStart = "2001:db8:128:129::1" + v63Route = "2001:db8:128:130::0" + v63RouteAdvertise = "2001:db8:128:130::/64" + v63RouteOtg = "2001:db8:128:130::" + v63TrafficStart = "2001:db8:128:130::1" + v6RoutePrefix = uint32(64) + dutAS = uint32(65656) + ateAS = uint32(65657) + bgpName = "BGP" + maskLenExact = "exact" + localPref = 200 + v4Flow = "flow-v4" + v6Flow = "flow-v6" + localPerfCfg = 5 ) var ( @@ -99,12 +108,14 @@ var ( advertisedIPv62 = ipAddr{address: v62Route, prefix: v6RoutePrefix} advertisedIPv63 = ipAddr{address: v63Route, prefix: v6RoutePrefix} extCommunitySet = map[string]string{ - "linkbw_0": "link-bandwidth:100:0", - "linkbw_1M": "link-bandwidth:100:1M", - "inkbw_2G": "link-bandwidth:100:2G", + "linkbw_0": "link-bandwidth:100:0", + "linkbw_1M": "link-bandwidth:100:1M", + "linkbw_2G": "link-bandwidth:100:2G", + "linkbw_any": "^link-bandwidth:.*:.$", + "linkbw_any_0": "^link-bandwidth:.*:0$", + } + CommunitySet = map[string]string{ "regex_match_comm100": "^100:.*$", - "linkbw_any": "^link-bandwidth:.*:.$", - "linkbw_any_0": "^link-bandwidth:.*:0$", } ) @@ -282,19 +293,34 @@ func validateRouteCommunityV4Prefix(t *testing.T, td testData, community, v4Pref t.Logf("Prefix recevied on OTG is correct, got Address %s, want prefix %v", bgpPrefix.GetAddress(), v4Prefix) switch community { case "none": - if len(bgpPrefix.Community) != 0 { - t.Fatalf("community is not empty it should be none") + if len(bgpPrefix.Community) != 0 || len(bgpPrefix.ExtendedCommunity) != 0 { + t.Errorf("community and ext communituy are not empty it should be none") + } + if localPerf && bgpPrefix.GetLocalPreference() != localPerfCfg && bgpPrefix.GetAddress() == v43Route { + t.Errorf("local preference is not %d got %d", localPerfCfg, bgpPrefix.GetLocalPreference()) } case "100:100": for _, gotCommunity := range bgpPrefix.Community { t.Logf("community AS:%d val: %d", gotCommunity.GetCustomAsNumber(), gotCommunity.GetCustomAsValue()) - if gotCommunity.GetCustomAsNumber() != 100 && gotCommunity.GetCustomAsValue() != 100 { - t.Fatalf("community is not 100:100 got AS number:%d AS value:%d", gotCommunity.GetCustomAsNumber(), gotCommunity.GetCustomAsValue()) + if gotCommunity.GetCustomAsNumber() != 100 || gotCommunity.GetCustomAsValue() != 100 { + t.Errorf("community is not 100:100 got AS number:%d AS value:%d", gotCommunity.GetCustomAsNumber(), gotCommunity.GetCustomAsValue()) } } default: - // TODO Verification as OTG not supported for Extended community/ - t.Logf("TODO: https://github.com/open-traffic-generator/snappi/issues/220 Verification as OTG not supported for Extended community") + for _, ec := range bgpPrefix.ExtendedCommunity { + lbSubType := ec.Structured.NonTransitive_2OctetAsType.LinkBandwidthSubtype + listCommunity := strings.Split(community, ":") + Bandwidth := listCommunity[2] + if Bandwidth == "0" { + if lbSubType.GetGlobal_2ByteAs() != 100 || ygot.BinaryToFloat32(lbSubType.GetBandwidth()) != 0 { + t.Errorf("ERROR lb AS want 100, got :%d, Bandwidth want 0, got:=%v", lbSubType.GetGlobal_2ByteAs(), ygot.BinaryToFloat32(lbSubType.GetBandwidth())) + } + } else { + if lbSubType.GetGlobal_2ByteAs() != 100 || ygot.BinaryToFloat32(lbSubType.GetBandwidth()) != 2000000000 { + t.Errorf("ERROR lb AS want 100, got :%d, Bandwidth want :2G, got=%v", lbSubType.GetGlobal_2ByteAs(), ygot.BinaryToFloat32(lbSubType.GetBandwidth())) + } + } + } if deviations.BgpExtendedCommunityIndexUnsupported(td.dut) { verifyExtCommunityIndexV4(t, td, v4Prefix) } @@ -306,9 +332,9 @@ func validateRouteCommunityV4Prefix(t *testing.T, td testData, community, v4Pref func validateRouteCommunityV6(t *testing.T, td testData, ec extCommunity, localPerf bool) { prefixes := map[string]string{ - v61Route: ec.prefixSet1Comm, - v62Route: ec.prefixSet2Comm, - v63Route: ec.prefixSet3Comm, + v61RouteOtg: ec.prefixSet1Comm, + v62RouteOtg: ec.prefixSet2Comm, + v63RouteOtg: ec.prefixSet3Comm, } for prefix, community := range prefixes { validateRouteCommunityV6Prefix(t, td, community, prefix, localPerf) @@ -330,23 +356,37 @@ func validateRouteCommunityV6Prefix(t *testing.T, td testData, community, v6Pref bgpPrefixes := gnmi.GetAll(t, td.ate.OTG(), gnmi.OTG().BgpPeer(td.otgP2.Name()+".BGP6.peer").UnicastIpv6PrefixAny().State()) for _, bgpPrefix := range bgpPrefixes { if bgpPrefix.GetAddress() == v6Prefix { - t.Logf("Prefix recevied on OTG is correct, got prefix:%v , want prefix %v", bgpPrefix, v6Prefix) + t.Logf("Prefix recevied on OTG is correct, got prefix:%v , want prefix %v", bgpPrefix.GetAddress(), v6Prefix) switch community { case "none": - if len(bgpPrefix.Community) != 0 { - t.Fatalf("community is not empty it should be none") + if len(bgpPrefix.Community) != 0 || len(bgpPrefix.ExtendedCommunity) != 0 { + t.Errorf("community and ext community are not empty it should be none") + } + if localPerf && bgpPrefix.GetLocalPreference() != localPerfCfg { + t.Errorf("local preference is not %d got %d", localPerfCfg, bgpPrefix.GetLocalPreference()) } case "100:100": for _, gotCommunity := range bgpPrefix.Community { t.Logf("community AS:%d val: %d", gotCommunity.GetCustomAsNumber(), gotCommunity.GetCustomAsValue()) - if gotCommunity.GetCustomAsNumber() != 100 && gotCommunity.GetCustomAsValue() != 100 { - t.Fatalf("community is not 100:100 got AS number:%d AS value:%d", gotCommunity.GetCustomAsNumber(), gotCommunity.GetCustomAsValue()) + if gotCommunity.GetCustomAsNumber() != 100 || gotCommunity.GetCustomAsValue() != 100 { + t.Errorf("community is not 100:100 got AS number:%d AS value:%d", gotCommunity.GetCustomAsNumber(), gotCommunity.GetCustomAsValue()) } } default: - - // TODO Verification as OTG not supported for Extended community. - t.Logf("TODO: https://github.com/open-traffic-generator/snappi/issues/220 Verification as OTG not supported for Extended community") + for _, ec := range bgpPrefix.ExtendedCommunity { + lbSubType := ec.Structured.NonTransitive_2OctetAsType.LinkBandwidthSubtype + listCommunity := strings.Split(community, ":") + Bandwidth := listCommunity[2] + if Bandwidth == "0" { + if lbSubType.GetGlobal_2ByteAs() != 100 || ygot.BinaryToFloat32(lbSubType.GetBandwidth()) != 0 { + t.Errorf("ERROR lb AS want 100, got :%d, Bandwidth want 0, got:=%v", lbSubType.GetGlobal_2ByteAs(), ygot.BinaryToFloat32(lbSubType.GetBandwidth())) + } + } else { + if lbSubType.GetGlobal_2ByteAs() != 100 || ygot.BinaryToFloat32(lbSubType.GetBandwidth()) != 2000000000 { + t.Errorf("ERROR lb AS want 100, got :%d, Bandwidth want :2G, got=%v", lbSubType.GetGlobal_2ByteAs(), ygot.BinaryToFloat32(lbSubType.GetBandwidth())) + } + } + } if deviations.BgpExtendedCommunityIndexUnsupported(td.dut) { verifyExtCommunityIndexV6(t, td, v6Prefix) } @@ -400,12 +440,11 @@ func validateImportRoutingPolicyAllowAll(t *testing.T, dut *ondatra.DUTDevice, a bgpRIBPath := gnmi.OC().NetworkInstance(dni).Protocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_BGP, bgpName).Bgp().Rib() locRib := gnmi.Get[*oc.NetworkInstance_Protocol_Bgp_Rib_AfiSafi_Ipv4Unicast_LocRib](t, dut, bgpRIBPath. AfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV4_UNICAST).Ipv4Unicast().LocRib().State()) - found := 0 expected := map[string]bool{ - advertisedIPv41.address: true, - advertisedIPv42.address: true, - advertisedIPv43.address: true, + advertisedIPv41.address + "/" + strconv.Itoa(int(advertisedIPv41.prefix)): true, + advertisedIPv42.address + "/" + strconv.Itoa(int(advertisedIPv42.prefix)): true, + advertisedIPv43.address + "/" + strconv.Itoa(int(advertisedIPv43.prefix)): true, } for route, prefix := range locRib.Route { if expected[prefix.GetPrefix()] { @@ -414,7 +453,7 @@ func validateImportRoutingPolicyAllowAll(t *testing.T, dut *ondatra.DUTDevice, a } } if found != len(expected) { - t.Errorf("Not all V4 routes found. expected:%d got:%d", len(expected), found) + t.Fatalf("Not all V4 routes found. expected:%d got:%d", len(expected), found) } // Verify ipv6 policy. @@ -428,9 +467,9 @@ func validateImportRoutingPolicyAllowAll(t *testing.T, dut *ondatra.DUTDevice, a locRibv6 := gnmi.Get[*oc.NetworkInstance_Protocol_Bgp_Rib_AfiSafi_Ipv6Unicast_LocRib](t, dut, bgpRIBPathV6.AfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV6_UNICAST).Ipv6Unicast().LocRib().State()) found = 0 expectedV6 := map[string]bool{ - advertisedIPv61.address: true, - advertisedIPv62.address: true, - advertisedIPv63.address: true, + v61RouteAdvertise: true, + v62RouteAdvertise: true, + v63RouteAdvertise: true, } for route, prefix := range locRibv6.Route { if expectedV6[prefix.GetPrefix()] { @@ -439,7 +478,7 @@ func validateImportRoutingPolicyAllowAll(t *testing.T, dut *ondatra.DUTDevice, a } } if found != len(expectedV6) { - t.Errorf("Not all v6 Routes found expected:%d got:%d", len(expectedV6), found) + t.Fatalf("Not all v6 Routes found expected: %d got: %d", len(expectedV6), found) } } @@ -455,6 +494,18 @@ func configureExtCommunityRoutingPolicy(t *testing.T, dut *ondatra.DUTDevice) { stmt.SetExtCommunityMember([]string{community}) gnmi.Update(t, dut, gnmi.OC().RoutingPolicy().Config(), rp) } + for name, community := range CommunitySet { + rp := root.GetOrCreateRoutingPolicy() + pdef := rp.GetOrCreateDefinedSets().GetOrCreateBgpDefinedSets() + stmt, err := pdef.NewCommunitySet(name) + if err != nil { + t.Fatalf("NewCommunitySet failed: %v", err) + } + cs := []oc.RoutingPolicy_DefinedSets_BgpDefinedSets_CommunitySet_CommunityMember_Union{} + cs = append(cs, oc.UnionString(community)) + stmt.SetCommunityMember(cs) + gnmi.Update(t, dut, gnmi.OC().RoutingPolicy().Config(), rp) + } // Configure routing policy link bandwidth zero. rpSetLinkBwZero := root.GetOrCreateRoutingPolicy() @@ -464,7 +515,7 @@ func configureExtCommunityRoutingPolicy(t *testing.T, dut *ondatra.DUTDevice) { t.Fatalf("AppendNewStatement zero_linkbw failed: %v", err) } ref := pdef1Stmt1.GetOrCreateActions().GetOrCreateBgpActions().GetOrCreateSetExtCommunity() - ref.GetOrCreateReference().SetExtCommunitySetRef("linkbw_0") + ref.GetOrCreateReference().SetExtCommunitySetRefs([]string{"linkbw_0"}) ref.SetOptions(oc.BgpPolicy_BgpSetCommunityOptionType_ADD) ref.SetMethod(oc.SetCommunity_Method_REFERENCE) pdef1Stmt1.GetOrCreateActions().SetPolicyResult(oc.RoutingPolicy_PolicyResultType_NEXT_STATEMENT) @@ -483,11 +534,14 @@ func configureExtCommunityRoutingPolicy(t *testing.T, dut *ondatra.DUTDevice) { t.Fatalf("AppendNewStatement 1-megabit-match failed: %v", err) } ref = pdef2Stmt1.GetOrCreateActions().GetOrCreateBgpActions().GetOrCreateSetExtCommunity() - ref.GetOrCreateReference().SetExtCommunitySetRef("linkbw_1M") + ref.GetOrCreateReference().SetExtCommunitySetRefs([]string{"linkbw_1M"}) ref.SetOptions(oc.BgpPolicy_BgpSetCommunityOptionType_ADD) - ref1 := pdef2Stmt1.GetOrCreateConditions().GetOrCreateBgpConditions().GetMatchExtCommunitySet() - ref1.SetExtCommunitySet("regex_match_comm100") - ref1.SetMatchSetOptions(oc.RoutingPolicy_MatchSetOptionsType_INVERT) + ref.SetMethod(oc.SetCommunity_Method_REFERENCE) + if !deviations.BGPConditionsMatchCommunitySetUnsupported(dut) { + ref1 := pdef2Stmt1.GetOrCreateConditions().GetOrCreateBgpConditions().GetOrCreateMatchCommunitySet() + ref1.SetCommunitySet("regex_match_comm100") + ref1.SetMatchSetOptions(oc.RoutingPolicy_MatchSetOptionsType_INVERT) + } pdef2Stmt1.GetOrCreateActions().SetPolicyResult(oc.RoutingPolicy_PolicyResultType_NEXT_STATEMENT) pdef2Stmt2, err := pdef2.AppendNewStatement("accept_all_routes") if err != nil { @@ -504,11 +558,14 @@ func configureExtCommunityRoutingPolicy(t *testing.T, dut *ondatra.DUTDevice) { t.Fatalf("AppendNewStatement match_100_set_linkbw_2G failed: %v", err) } ref = pdef3Stmt1.GetOrCreateActions().GetOrCreateBgpActions().GetOrCreateSetExtCommunity() - ref.GetOrCreateReference().SetExtCommunitySetRef("linkbw_2G") + ref.GetOrCreateReference().SetExtCommunitySetRefs([]string{"linkbw_2G"}) ref.SetOptions(oc.BgpPolicy_BgpSetCommunityOptionType_ADD) - ref1 = pdef3Stmt1.GetOrCreateConditions().GetOrCreateBgpConditions().GetMatchExtCommunitySet() - ref1.SetExtCommunitySet("regex_match_comm100") - ref1.SetMatchSetOptions(oc.RoutingPolicy_MatchSetOptionsType_ANY) + ref.SetMethod(oc.SetCommunity_Method_REFERENCE) + if !deviations.BGPConditionsMatchCommunitySetUnsupported(dut) { + ref1 := pdef3Stmt1.GetOrCreateConditions().GetOrCreateBgpConditions().GetMatchCommunitySet() + ref1.SetCommunitySet("regex_match_comm100") + ref1.SetMatchSetOptions(oc.RoutingPolicy_MatchSetOptionsType_ANY) + } pdef3Stmt1.GetOrCreateActions().SetPolicyResult(oc.RoutingPolicy_PolicyResultType_NEXT_STATEMENT) pdef3Stmt2, err := pdef3.AppendNewStatement("accept_all_routes") if err != nil { @@ -525,7 +582,7 @@ func configureExtCommunityRoutingPolicy(t *testing.T, dut *ondatra.DUTDevice) { t.Fatalf("AppendNewStatement del_linkbw failed: %v", err) } ref = pdef4Stmt1.GetOrCreateActions().GetOrCreateBgpActions().GetOrCreateSetExtCommunity() - ref.GetOrCreateReference().SetExtCommunitySetRef("linkbw_any") + ref.GetOrCreateReference().SetExtCommunitySetRefs([]string{"linkbw_any"}) ref.SetOptions(oc.BgpPolicy_BgpSetCommunityOptionType_REMOVE) ref.SetMethod(oc.SetCommunity_Method_REFERENCE) pdef4Stmt1.GetOrCreateActions().SetPolicyResult(oc.RoutingPolicy_PolicyResultType_NEXT_STATEMENT) @@ -544,17 +601,20 @@ func configureExtCommunityRoutingPolicy(t *testing.T, dut *ondatra.DUTDevice) { t.Fatalf("AppendNewStatement match_and_remove_linkbw_any_0 failed: %v", err) } ref = pdef5Stmt1.GetOrCreateActions().GetOrCreateBgpActions().GetOrCreateSetExtCommunity() - ref.GetOrCreateReference().SetExtCommunitySetRef("linkbw_any_0") + ref.GetOrCreateReference().SetExtCommunitySetRefs([]string{"linkbw_any_0"}) ref.SetOptions(oc.BgpPolicy_BgpSetCommunityOptionType_REMOVE) ref.SetMethod(oc.SetCommunity_Method_REFERENCE) - ref1 = pdef5Stmt1.GetOrCreateConditions().GetOrCreateBgpConditions().GetMatchExtCommunitySet() - ref1.SetExtCommunitySet("linkbw_any_0") + if !deviations.BGPConditionsMatchCommunitySetUnsupported(dut) { + ref1 := pdef5Stmt1.GetOrCreateConditions().GetOrCreateBgpConditions().GetMatchExtCommunitySet() + ref1.SetExtCommunitySet("linkbw_any_0") + } pdef5Stmt1.GetOrCreateActions().SetPolicyResult(oc.RoutingPolicy_PolicyResultType_NEXT_STATEMENT) pdef5Stmt1.GetOrCreateActions().GetOrCreateBgpActions().SetLocalPref = ygot.Uint32(5) pdef5Stmt2, err := pdef5.AppendNewStatement("accept_all_routes") if err != nil { t.Fatalf("AppendNewStatement accept_all_routes failed: %v", err) } + pdef5Stmt2.GetOrCreateActions().SetPolicyResult(oc.RoutingPolicy_PolicyResultType_ACCEPT_ROUTE) gnmi.Update(t, dut, gnmi.OC().RoutingPolicy().Config(), rpMatchLB0Perf5) } @@ -644,6 +704,7 @@ func (td *testData) advertiseRoutesWithEBGP(t *testing.T) { nV61.GetOrCreateAfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV6_UNICAST).Enabled = ygot.Bool(true) nV62 := bgp.GetOrCreateNeighbor(atePort2.IPv6) nV62.SetPeerAs(dutAS) + nV62.SetSendCommunity(oc.Bgp_CommunityType_BOTH) nV62.GetOrCreateAfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV6_UNICAST).Enabled = ygot.Bool(true) gnmi.Update(t, td.dut, gnmi.OC().NetworkInstance(deviations.DefaultNetworkInstance(td.dut)).Config(), ni) diff --git a/feature/experimental/gribi/otg_tests/backup_nhg_action_pbf/README.md b/feature/experimental/gribi/otg_tests/backup_nhg_action_pbf/README.md index 8da26c31dd2..a9e511a5fa8 100644 --- a/feature/experimental/gribi/otg_tests/backup_nhg_action_pbf/README.md +++ b/feature/experimental/gribi/otg_tests/backup_nhg_action_pbf/README.md @@ -99,15 +99,18 @@ Different test scenarios requires different setups. traffic with decapsulated traffic with destination IP as `InnerDstIP_1` at ATE port-4. -## Config Parameter coverage - -No new configuration covered. - -## Telemetry Parameter coverage - -No new telemetry covered. - -## Protocol/RPC Parameter coverage +## OpenConfig Path and RPC Coverage +```yaml +rpcs: + gnmi: + gNMI.Get: + gNMI.Set: + gNMI.Subscribe: + gribi: + gRIBI.Get: + gRIBI.Modify: + gRIBI.Flush: +``` ## Minimum DUT platform requirement diff --git a/feature/experimental/gribi/otg_tests/backup_nhg_action_pbf/backup_nhg_action_pbf_test.go b/feature/experimental/gribi/otg_tests/backup_nhg_action_pbf/backup_nhg_action_pbf_test.go index 79af18985dd..81885d754ca 100644 --- a/feature/experimental/gribi/otg_tests/backup_nhg_action_pbf/backup_nhg_action_pbf_test.go +++ b/feature/experimental/gribi/otg_tests/backup_nhg_action_pbf/backup_nhg_action_pbf_test.go @@ -479,7 +479,7 @@ func testBackupDecapWithVrfPolW(ctx context.Context, t *testing.T, args *testArg if deviations.SkipPbfWithDecapEncapVrf(args.dut) { t.Skip("Skipping test as PBF with decap encap vrf is not supported") } - vrfpolicy.ConfigureVRFSelectionPolicyW(t, args.dut) + vrfpolicy.ConfigureVRFSelectionPolicy(t, args.dut, vrfpolicy.VRFPolicyW) testBackupDecap(ctx, t, args) } @@ -487,7 +487,7 @@ func testDecapEncapWithVrfPolW(ctx context.Context, t *testing.T, args *testArgs if deviations.SkipPbfWithDecapEncapVrf(args.dut) { t.Skip("Skipping test as PBF with decap encap vrf is not supported") } - vrfpolicy.ConfigureVRFSelectionPolicyW(t, args.dut) + vrfpolicy.ConfigureVRFSelectionPolicy(t, args.dut, vrfpolicy.VRFPolicyW) testDecapEncap(ctx, t, args) } diff --git a/feature/experimental/gribi/otg_tests/route_addition_during_failover_test/README.md b/feature/experimental/gribi/otg_tests/route_addition_during_failover_test/README.md index afb33fb929e..c2e05fd3e6c 100644 --- a/feature/experimental/gribi/otg_tests/route_addition_during_failover_test/README.md +++ b/feature/experimental/gribi/otg_tests/route_addition_during_failover_test/README.md @@ -36,11 +36,18 @@ Validate gRIBI route persistence during SSO * Send traffic from ATE port-1 to prefixes in `IPBlock2` and ensure traffic flows 100% and reaches ATE port-2. -## Protocol/RPC Parameter coverage - -* gNOI: - * System - * SwitchControlProcessor +## OpenConfig Path and RPC Coverage +```yaml +rpcs: + gnmi: + gNMI.Get: + gNMI.Set: + gNMI.Subscribe: + gribi: + gRIBI.Get: + gRIBI.Modify: + gRIBI.Flush: +``` ## Config parameter coverage diff --git a/feature/experimental/gribi/otg_tests/route_addition_during_failover_test/route_addition_during_failover_test.go b/feature/experimental/gribi/otg_tests/route_addition_during_failover_test/route_addition_during_failover_test.go index 8cd803f96a7..fb92e0f4856 100644 --- a/feature/experimental/gribi/otg_tests/route_addition_during_failover_test/route_addition_during_failover_test.go +++ b/feature/experimental/gribi/otg_tests/route_addition_during_failover_test/route_addition_during_failover_test.go @@ -661,6 +661,7 @@ func TestRouteAdditionDuringFailover(t *testing.T) { // SINGLE_PRIMARY mode, with FIB ACK requested. Specify gRIBI as the leader. // Check vars for WithInitialElectionID. + client.Stop(t) t.Log("Reconnect gRIBi client after switchover on new master.") client.Connection().WithStub(gribic).WithPersistence().WithInitialElectionID(eID.Low, eID.High). WithFIBACK().WithRedundancyMode(fluent.ElectedPrimaryClient) diff --git a/feature/experimental/gribi/otg_tests/route_removal_during_failover_test/README.md b/feature/experimental/gribi/otg_tests/route_removal_during_failover_test/README.md index 0ff42794cf1..da9a134e0d0 100644 --- a/feature/experimental/gribi/otg_tests/route_removal_during_failover_test/README.md +++ b/feature/experimental/gribi/otg_tests/route_removal_during_failover_test/README.md @@ -30,11 +30,18 @@ Validate gRIBI route flush during SSO * Send traffic from ATE port-1 to prefixes in IPBlock1 and ensure traffic flows 100% and reaches ATE port-2. -## Protocol/RPC Parameter coverage - -* gNOI: - * System - * SwitchControlProcessor +## OpenConfig Path and RPC Coverage +```yaml +rpcs: + gnmi: + gNMI.Get: + gNMI.Set: + gNMI.Subscribe: + gribi: + gRIBI.Get: + gRIBI.Modify: + gRIBI.Flush: +``` ## Config parameter coverage diff --git a/feature/experimental/gribi/otg_tests/route_removal_during_failover_test/route_removal_during_failover_test.go b/feature/experimental/gribi/otg_tests/route_removal_during_failover_test/route_removal_during_failover_test.go index 62933c1c4fd..db63e96f39d 100644 --- a/feature/experimental/gribi/otg_tests/route_removal_during_failover_test/route_removal_during_failover_test.go +++ b/feature/experimental/gribi/otg_tests/route_removal_during_failover_test/route_removal_during_failover_test.go @@ -622,6 +622,7 @@ func TestRouteRemovalDuringFailover(t *testing.T) { // SINGLE_PRIMARY mode, with FIB ACK requested. Specify gRIBI as the leader. // Check vars for WithInitialElectionID. + client.Stop(t) t.Log("Reconnect gRIBi client after switchover on new master.") client.Connection().WithStub(gribic).WithPersistence().WithInitialElectionID(eID.Low, eID.High). WithFIBACK().WithRedundancyMode(fluent.ElectedPrimaryClient) diff --git a/feature/experimental/gribi/otg_tests/vrf_policy_driven_te/README.md b/feature/experimental/gribi/otg_tests/vrf_policy_driven_te/README.md index 68a6eb6628a..7fa0f46bec3 100644 --- a/feature/experimental/gribi/otg_tests/vrf_policy_driven_te/README.md +++ b/feature/experimental/gribi/otg_tests/vrf_policy_driven_te/README.md @@ -807,7 +807,7 @@ Tests support for TE disabled IPinIP IPv4 (IP protocol 4) cluster traffic arrivi * network-instances/network-instance/policy-forwarding/policies/policy/rules/rule/ipv6/dscp-set * network-instances/network-instance/policy-forwarding/policies/policy/rules/rule/ipv6/source-address * network-instances/network-instance/policy-forwarding/policies/policy/rules/rule/action/decap-network-instance -* network-instances/network-instance/policy-forwarding/policies/policy/rules/rule/action/post-network-instance +* network-instances/network-instance/policy-forwarding/policies/policy/rules/rule/action/post-decap-network-instance * network-instances/network-instance/policy-forwarding/policies/policy/rules/rule/action/decap-fallback-network-instance ## Telemetry Parameter Coverage @@ -833,4 +833,37 @@ Tests support for TE disabled IPinIP IPv4 (IP protocol 4) cluster traffic arrivi ## Required DUT platform -vRX \ No newline at end of file +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 + /network-instances/network-instance/policy-forwarding/policies/policy/config/policy-id: + /network-instances/network-instance/policy-forwarding/policies/policy/rules/rule/config/sequence-id: + /network-instances/network-instance/policy-forwarding/policies/policy/rules/rule/ipv4/config/protocol: + /network-instances/network-instance/policy-forwarding/policies/policy/rules/rule/ipv4/config/dscp-set: + /network-instances/network-instance/policy-forwarding/policies/policy/rules/rule/ipv4/config/source-address: + /network-instances/network-instance/policy-forwarding/policies/policy/rules/rule/ipv6/config/protocol: + /network-instances/network-instance/policy-forwarding/policies/policy/rules/rule/ipv6/config/dscp-set: + /network-instances/network-instance/policy-forwarding/policies/policy/rules/rule/ipv6/config/source-address: + /network-instances/network-instance/policy-forwarding/policies/policy/rules/rule/action/config/decap-network-instance: + /network-instances/network-instance/policy-forwarding/policies/policy/rules/rule/action/config/post-decap-network-instance: + /network-instances/network-instance/policy-forwarding/policies/policy/rules/rule/action/config/decap-fallback-network-instance: + + ## State paths + /network-instances/network-instance/protocols/protocol/isis/interfaces/interface/levels/level/adjacencies/adjacency/state/adjacency-state: + /network-instances/network-instance/protocols/protocol/bgp/neighbors/neighbor/state/session-state: + +rpcs: + gnmi: + gNMI.Set: + gNMI.Subscribe: + gribi: + gRIBI.Modify: + gRIBI.Flush: +``` \ No newline at end of file diff --git a/feature/experimental/gribi/otg_tests/vrf_policy_driven_te/metadata.textproto b/feature/experimental/gribi/otg_tests/vrf_policy_driven_te/metadata.textproto index 72bd2337297..08cdce07060 100644 --- a/feature/experimental/gribi/otg_tests/vrf_policy_driven_te/metadata.textproto +++ b/feature/experimental/gribi/otg_tests/vrf_policy_driven_te/metadata.textproto @@ -10,9 +10,12 @@ platform_exceptions: { vendor: CISCO } deviations: { - ipv4_missing_enabled: true gribi_mac_override_with_static_arp: true interface_ref_interface_id_format: true + pf_require_match_default_rule: true + pf_require_sequential_order_pbr_rules: true + ttl_copy_unsupported: true + isis_single_topology_required: true } } platform_exceptions: { diff --git a/feature/experimental/gribi/otg_tests/vrf_policy_driven_te/vrf_policy_driven_te_test.go b/feature/experimental/gribi/otg_tests/vrf_policy_driven_te/vrf_policy_driven_te_test.go index 3553efafb3b..136cf377d60 100644 --- a/feature/experimental/gribi/otg_tests/vrf_policy_driven_te/vrf_policy_driven_te_test.go +++ b/feature/experimental/gribi/otg_tests/vrf_policy_driven_te/vrf_policy_driven_te_test.go @@ -125,6 +125,7 @@ const ( otgIsisPort8LoopV6 = "2001:db8::203:0:113:10" dutAS = 65501 peerGrpName1 = "BGP-PEER-GROUP1" + seqIDBase = uint32(10) ) var ( @@ -255,6 +256,75 @@ var ( IPv4Len: 32, IPv6Len: 128, } + dutPort2DummyIP = attrs.Attributes{ + Desc: "dutPort2", + IPv4Sec: "192.0.2.33", + IPv4LenSec: plenIPv4, + } + + otgPort2DummyIP = attrs.Attributes{ + Desc: "otgPort2", + IPv4: "192.0.2.34", + IPv4Len: plenIPv4, + } + + dutPort3DummyIP = attrs.Attributes{ + Desc: "dutPort3", + IPv4Sec: "192.0.2.37", + IPv4LenSec: plenIPv4, + } + + otgPort3DummyIP = attrs.Attributes{ + Desc: "otgPort3", + IPv4: "192.0.2.38", + IPv4Len: plenIPv4, + } + + dutPort4DummyIP = attrs.Attributes{ + Desc: "dutPort4", + IPv4Sec: "192.0.2.41", + IPv4LenSec: plenIPv4, + } + + otgPort4DummyIP = attrs.Attributes{ + Desc: "otgPort4", + IPv4: "192.0.2.42", + IPv4Len: plenIPv4, + } + + dutPort5DummyIP = attrs.Attributes{ + Desc: "dutPort5", + IPv4Sec: "192.0.2.45", + IPv4LenSec: plenIPv4, + } + + otgPort5DummyIP = attrs.Attributes{ + Desc: "otgPort5", + IPv4: "192.0.2.46", + IPv4Len: plenIPv4, + } + dutPort6DummyIP = attrs.Attributes{ + Desc: "dutPort5", + IPv4Sec: "192.0.2.49", + IPv4LenSec: plenIPv4, + } + + otgPort6DummyIP = attrs.Attributes{ + Desc: "otgPort5", + IPv4: "192.0.2.50", + IPv4Len: plenIPv4, + } + dutPort7DummyIP = attrs.Attributes{ + Desc: "dutPort5", + IPv4Sec: "192.0.2.53", + IPv4LenSec: plenIPv4, + } + + otgPort7DummyIP = attrs.Attributes{ + Desc: "otgPort5", + IPv4: "192.0.2.54", + IPv4Len: plenIPv4, + } loopbackIntfName string // TODO : https://github.com/open-traffic-generator/fp-testbed-juniper/issues/42 // Below code will be uncommented once ixia issue is fixed. @@ -334,7 +404,7 @@ func configureVrfSelectionPolicyW(t *testing.T, dut *ondatra.DUTDevice) { niPf.SetType(oc.Policy_Type_VRF_SELECTION_POLICY) for _, pfRule := range pfRuleList { - pfR := niPf.GetOrCreateRule(pfRule.SeqId) + pfR := niPf.GetOrCreateRule(seqIDOffset(dut, pfRule.SeqId)) pfRProtoIPv4 := pfR.GetOrCreateIpv4() pfRProtoIPv4.Protocol = oc.UnionUint8(pfRule.protocol) if pfRule.dscpSet != nil { @@ -346,9 +416,20 @@ func configureVrfSelectionPolicyW(t *testing.T, dut *ondatra.DUTDevice) { pfRAction.PostDecapNetworkInstance = ygot.String(pfRule.postDecapNi) pfRAction.DecapFallbackNetworkInstance = ygot.String(pfRule.decapFallbackNi) } - pfR := niPf.GetOrCreateRule(13) - pfRAction := pfR.GetOrCreateAction() - pfRAction.NetworkInstance = ygot.String(niDefault) + if deviations.PfRequireMatchDefaultRule(dut) { + pfR13 := niPf.GetOrCreateRule(seqIDOffset(dut, 13)) + pfR13.GetOrCreateL2().SetEthertype(oc.PacketMatchTypes_ETHERTYPE_ETHERTYPE_IPV4) + pfRAction := pfR13.GetOrCreateAction() + pfRAction.NetworkInstance = ygot.String(niDefault) + pfR14 := niPf.GetOrCreateRule(seqIDOffset(dut, 14)) + pfR14.GetOrCreateL2().SetEthertype(oc.PacketMatchTypes_ETHERTYPE_ETHERTYPE_IPV6) + pfRAction = pfR14.GetOrCreateAction() + pfRAction.NetworkInstance = ygot.String(niDefault) + } else { + pfR := niPf.GetOrCreateRule(13) + pfRAction := pfR.GetOrCreateAction() + pfRAction.NetworkInstance = ygot.String(niDefault) + } p1 := dut.Port(t, "port1") interfaceID := p1.Name() @@ -406,11 +487,10 @@ func configureVrfSelectionPolicyC(t *testing.T, dut *ondatra.DUTDevice) { ni: niEncapTeVrfB} pfRule16 := &policyFwRule{SeqId: 16, family: "ipv6", dscpSet: []uint8{dscpEncapA1, dscpEncapA2}, ni: niEncapTeVrfB} - pfRule17 := &policyFwRule{SeqId: 17, ni: niDefault} pfRuleList := []*policyFwRule{pfRule1, pfRule2, pfRule3, pfRule4, pfRule5, pfRule6, pfRule7, pfRule8, pfRule9, pfRule10, pfRule11, pfRule12, pfRule13, pfRule14, - pfRule15, pfRule16, pfRule17} + pfRule15, pfRule16} ni := d.GetOrCreateNetworkInstance(deviations.DefaultNetworkInstance(dut)) niP := ni.GetOrCreatePolicyForwarding() @@ -418,7 +498,7 @@ func configureVrfSelectionPolicyC(t *testing.T, dut *ondatra.DUTDevice) { niPf.SetType(oc.Policy_Type_VRF_SELECTION_POLICY) for _, pfRule := range pfRuleList { - pfR := niPf.GetOrCreateRule(pfRule.SeqId) + pfR := niPf.GetOrCreateRule(seqIDOffset(dut, pfRule.SeqId)) if pfRule.family == "ipv4" { pfRProtoIP := pfR.GetOrCreateIpv4() @@ -453,6 +533,21 @@ func configureVrfSelectionPolicyC(t *testing.T, dut *ondatra.DUTDevice) { } } + if deviations.PfRequireMatchDefaultRule(dut) { + pfR17 := niPf.GetOrCreateRule(seqIDOffset(dut, 17)) + pfR17.GetOrCreateL2().SetEthertype(oc.PacketMatchTypes_ETHERTYPE_ETHERTYPE_IPV4) + pfRAction := pfR17.GetOrCreateAction() + pfRAction.NetworkInstance = ygot.String(niDefault) + pfR18 := niPf.GetOrCreateRule(seqIDOffset(dut, 18)) + pfR18.GetOrCreateL2().SetEthertype(oc.PacketMatchTypes_ETHERTYPE_ETHERTYPE_IPV6) + pfRAction = pfR18.GetOrCreateAction() + pfRAction.NetworkInstance = ygot.String(niDefault) + } else { + pfR := niPf.GetOrCreateRule(17) + pfRAction := pfR.GetOrCreateAction() + pfRAction.NetworkInstance = ygot.String(niDefault) + } + p1 := dut.Port(t, "port1") interfaceID := p1.Name() if deviations.InterfaceRefInterfaceIDFormat(dut) { @@ -506,6 +601,39 @@ func staticARPWithMagicUniversalIP(t *testing.T, dut *ondatra.DUTDevice) { } } +// staticARPWithSpecificIP configures secondary IPs and static ARP. +func staticARPWithSpecificIP(t *testing.T, dut *ondatra.DUTDevice) { + t.Helper() + p2 := dut.Port(t, "port2") + p3 := dut.Port(t, "port3") + p4 := dut.Port(t, "port4") + p5 := dut.Port(t, "port5") + p6 := dut.Port(t, "port6") + p7 := dut.Port(t, "port7") + gnmi.Update(t, dut, gnmi.OC().Interface(p2.Name()).Config(), dutPort2DummyIP.NewOCInterface(p2.Name(), dut)) + gnmi.Update(t, dut, gnmi.OC().Interface(p3.Name()).Config(), dutPort3DummyIP.NewOCInterface(p3.Name(), dut)) + gnmi.Update(t, dut, gnmi.OC().Interface(p4.Name()).Config(), dutPort4DummyIP.NewOCInterface(p4.Name(), dut)) + gnmi.Update(t, dut, gnmi.OC().Interface(p5.Name()).Config(), dutPort5DummyIP.NewOCInterface(p5.Name(), dut)) + gnmi.Update(t, dut, gnmi.OC().Interface(p6.Name()).Config(), dutPort6DummyIP.NewOCInterface(p6.Name(), dut)) + gnmi.Update(t, dut, gnmi.OC().Interface(p7.Name()).Config(), dutPort7DummyIP.NewOCInterface(p7.Name(), dut)) + gnmi.Update(t, dut, gnmi.OC().Interface(p2.Name()).Config(), configStaticArp(p2.Name(), otgPort2DummyIP.IPv4, magicMac)) + gnmi.Update(t, dut, gnmi.OC().Interface(p3.Name()).Config(), configStaticArp(p3.Name(), otgPort3DummyIP.IPv4, magicMac)) + gnmi.Update(t, dut, gnmi.OC().Interface(p4.Name()).Config(), configStaticArp(p4.Name(), otgPort4DummyIP.IPv4, magicMac)) + gnmi.Update(t, dut, gnmi.OC().Interface(p5.Name()).Config(), configStaticArp(p5.Name(), otgPort5DummyIP.IPv4, magicMac)) + gnmi.Update(t, dut, gnmi.OC().Interface(p6.Name()).Config(), configStaticArp(p6.Name(), otgPort6DummyIP.IPv4, magicMac)) + gnmi.Update(t, dut, gnmi.OC().Interface(p7.Name()).Config(), configStaticArp(p7.Name(), otgPort7DummyIP.IPv4, magicMac)) +} + +// seqIDOffset returns sequence ID offset added with seqIDBase (10), to avoid sequences +// like 1, 10, 11, 12,..., 2, 21, 22, ... while being sent by Ondatra to the DUT. +// It now generates sequences like 11, 12, 13, ..., 19, 20, 21,..., 99. +func seqIDOffset(dut *ondatra.DUTDevice, i uint32) uint32 { + if deviations.PfRequireSequentialOrderPbrRules(dut) { + return i + seqIDBase + } + return i +} + // configureNetworkInstance configures vrfs DECAP_TE_VRF,ENCAP_TE_VRF_A,ENCAP_TE_VRF_B, // TE_VRF_222, TE_VRF_111. func configNonDefaultNetworkInstance(t *testing.T, dut *ondatra.DUTDevice) { @@ -538,7 +666,7 @@ func configureDUT(t *testing.T, dut *ondatra.DUTDevice) { for idx, a := range []attrs.Attributes{dutPort1, dutPort2, dutPort3, dutPort4, dutPort5, dutPort6, dutPort7, dutPort8} { p := portList[idx] intf := a.NewOCInterface(p.Name(), dut) - if p.PMD() == ondatra.PMD100GBASEFR { + if p.PMD() == ondatra.PMD100GBASEFR && dut.Vendor() != ondatra.CISCO { e := intf.GetOrCreateEthernet() e.AutoNegotiate = ygot.Bool(false) e.DuplexMode = oc.Ethernet_DuplexMode_FULL @@ -581,6 +709,8 @@ func configureDUT(t *testing.T, dut *ondatra.DUTDevice) { } if deviations.GRIBIMACOverrideStaticARPStaticRoute(dut) { staticARPWithMagicUniversalIP(t, dut) + } else if deviations.GRIBIMACOverrideWithStaticARP(dut) { + staticARPWithSpecificIP(t, dut) } } @@ -596,6 +726,11 @@ func configureISIS(t *testing.T, dut *ondatra.DUTDevice, intfList []string, dutA globalISIS.LevelCapability = oc.Isis_LevelType_LEVEL_2 globalISIS.Net = []string{fmt.Sprintf("%v.%v.00", dutAreaAddress, dutSysID)} globalISIS.GetOrCreateAf(oc.IsisTypes_AFI_TYPE_IPV4, oc.IsisTypes_SAFI_TYPE_UNICAST).Enabled = ygot.Bool(true) + if deviations.ISISSingleTopologyRequired(dut) { + afv6 := globalISIS.GetOrCreateAf(oc.IsisTypes_AFI_TYPE_IPV6, oc.IsisTypes_SAFI_TYPE_UNICAST) + afv6.GetOrCreateMultiTopology().SetAfiName(oc.IsisTypes_AFI_TYPE_IPV4) + afv6.GetOrCreateMultiTopology().SetSafiName(oc.IsisTypes_SAFI_TYPE_UNICAST) + } if deviations.ISISInstanceEnabledRequired(dut) { globalISIS.Instance = ygot.String(isisInstance) } @@ -610,14 +745,18 @@ func configureISIS(t *testing.T, dut *ondatra.DUTDevice, intfList []string, dutA isisIntf.CircuitType = oc.Isis_CircuitType_POINT_TO_POINT isisIntfLevel := isisIntf.GetOrCreateLevel(2) isisIntfLevel.Enabled = ygot.Bool(true) - isisIntfLevelAfi := isisIntfLevel.GetOrCreateAf(oc.IsisTypes_AFI_TYPE_IPV4, oc.IsisTypes_SAFI_TYPE_UNICAST) - isisIntfLevelAfi.Metric = ygot.Uint32(200) - isisIntfLevelAfi.Enabled = ygot.Bool(true) + isisIntfLevelAfiv4 := isisIntfLevel.GetOrCreateAf(oc.IsisTypes_AFI_TYPE_IPV4, oc.IsisTypes_SAFI_TYPE_UNICAST) + isisIntfLevelAfiv4.Metric = ygot.Uint32(200) + isisIntfLevelAfiv4.Enabled = ygot.Bool(true) + isisIntfLevelAfiv6 := isisIntfLevel.GetOrCreateAf(oc.IsisTypes_AFI_TYPE_IPV6, oc.IsisTypes_SAFI_TYPE_UNICAST) + isisIntfLevelAfiv6.Metric = ygot.Uint32(200) + isisIntfLevelAfiv6.Enabled = ygot.Bool(true) if deviations.ISISInterfaceAfiUnsupported(dut) { isisIntf.Af = nil } if deviations.MissingIsisInterfaceAfiSafiEnable(dut) { - isisIntfLevelAfi.Enabled = nil + isisIntfLevelAfiv4.Enabled = nil + isisIntfLevelAfiv6.Enabled = nil } } gnmi.Replace(t, dut, dutConfIsisPath.Config(), prot) @@ -643,7 +782,11 @@ func bgpCreateNbr(localAs uint32, dut *ondatra.DUTDevice) *oc.NetworkInstance_Pr bgpNbr.PeerAs = ygot.Uint32(localAs) bgpNbr.Enabled = ygot.Bool(true) bgpNbrT := bgpNbr.GetOrCreateTransport() - bgpNbrT.LocalAddress = ygot.String(dutlo0Attrs.IPv4) + localAddressLeaf := dutlo0Attrs.IPv4 + if dut.Vendor() == ondatra.CISCO { + localAddressLeaf = loopbackIntfName + } + bgpNbrT.LocalAddress = ygot.String(localAddressLeaf) af4 := bgpNbr.GetOrCreateAfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV4_UNICAST) af4.Enabled = ygot.Bool(true) af6 := bgpNbr.GetOrCreateAfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV6_UNICAST) @@ -709,6 +852,9 @@ func createFlow(flowValues *flowArgs) gosnappi.Flow { // if len(flowValues.inHdrDscp) != 0 { // innerIpHdr.Priority().Dscp().Phb().SetValues(flowValues.inHdrDscp) // } + UDPHeader := flow.Packet().Add().Udp() + UDPHeader.DstPort().Increment().SetStart(1).SetCount(50000).SetStep(1) + UDPHeader.SrcPort().Increment().SetStart(1).SetCount(50000).SetStep(1) } else { innerIpv6Hdr := flow.Packet().Add().Ipv6() innerIpv6Hdr.Src().SetValue(flowValues.InnHdrSrcIPv6) @@ -718,6 +864,9 @@ func createFlow(flowValues *flowArgs) gosnappi.Flow { // if len(flowValues.inHdrDscp) != 0 { // innerIpv6Hdr.FlowLabel().SetValues(flowValues.inHdrDscp) // } + UDPHeader := flow.Packet().Add().Udp() + UDPHeader.DstPort().Increment().SetStart(1).SetCount(50000).SetStep(1) + UDPHeader.SrcPort().Increment().SetStart(1).SetCount(50000).SetStep(1) } } return flow @@ -794,11 +943,60 @@ func programAftWithMagicIp(t *testing.T, dut *ondatra.DUTDevice, args *testArgs) ) } +func programGRIBIWithDummyIP(t *testing.T, dut *ondatra.DUTDevice, args *testArgs) { + args.client.Modify().AddEntry(t, + fluent.NextHopEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). + WithIndex(11).WithMacAddress(magicMac).WithInterfaceRef(dut.Port(t, "port2").Name()). + WithIPAddress(otgPort2DummyIP.IPv4), + fluent.NextHopEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). + WithIndex(12).WithMacAddress(magicMac).WithInterfaceRef(dut.Port(t, "port3").Name()). + WithIPAddress(otgPort3DummyIP.IPv4), + fluent.NextHopGroupEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). + WithID(11).AddNextHop(11, 1).AddNextHop(12, 3), + fluent.IPv4Entry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). + WithPrefix(gribiIPv4EntryDefVRF1+"/"+maskLen32).WithNextHopGroup(11), + + fluent.NextHopEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). + WithIndex(13).WithMacAddress(magicMac).WithInterfaceRef(dut.Port(t, "port4").Name()). + WithIPAddress(otgPort4DummyIP.IPv4), + fluent.NextHopGroupEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). + WithID(12).AddNextHop(13, 2), + fluent.IPv4Entry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). + WithPrefix(gribiIPv4EntryDefVRF2+"/"+maskLen32).WithNextHopGroup(12), + + fluent.NextHopEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). + WithIndex(14).WithMacAddress(magicMac).WithInterfaceRef(dut.Port(t, "port5").Name()). + WithIPAddress(otgPort5DummyIP.IPv4), + fluent.NextHopGroupEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). + WithID(13).AddNextHop(14, 1), + fluent.IPv4Entry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). + WithPrefix(gribiIPv4EntryDefVRF3+"/"+maskLen32).WithNextHopGroup(13), + + fluent.NextHopEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). + WithIndex(15).WithMacAddress(magicMac).WithInterfaceRef(dut.Port(t, "port6").Name()). + WithIPAddress(otgPort6DummyIP.IPv4), + fluent.NextHopGroupEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). + WithID(14).AddNextHop(15, 1), + fluent.IPv4Entry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). + WithPrefix(gribiIPv4EntryDefVRF4+"/"+maskLen32).WithNextHopGroup(14), + + fluent.NextHopEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). + WithIndex(16).WithMacAddress(magicMac).WithInterfaceRef(dut.Port(t, "port7").Name()). + WithIPAddress(otgPort7DummyIP.IPv4), + fluent.NextHopGroupEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). + WithID(15).AddNextHop(16, 1), + fluent.IPv4Entry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). + WithPrefix(gribiIPv4EntryDefVRF5+"/"+maskLen32).WithNextHopGroup(15), + ) +} + func configGribiBaselineAFT(ctx context.Context, t *testing.T, dut *ondatra.DUTDevice, args *testArgs) { t.Helper() if deviations.GRIBIMACOverrideStaticARPStaticRoute(dut) { programAftWithMagicIp(t, dut, args) + } else if deviations.GRIBIMACOverrideWithStaticARP(dut) { + programGRIBIWithDummyIP(t, dut, args) } else { // Programming AFT entries for prefixes in DEFAULT VRF args.client.Modify().AddEntry(t, @@ -1336,7 +1534,7 @@ func sendTraffic(t *testing.T, args *testArgs, capturePortList []string, flowLis args.otg.PushConfig(t, args.otgConfig) time.Sleep(30 * time.Second) args.otg.StartProtocols(t) - time.Sleep(30 * time.Second) + time.Sleep(60 * time.Second) cs := gosnappi.NewControlState() cs.Port().Capture().SetState(gosnappi.StatePortCaptureState.START) @@ -1735,19 +1933,20 @@ func testGribiDecapMixedLenPref(ctx context.Context, t *testing.T, dut *ondatra. // v4 header stripped and are forwarded according to the route in the DEFAULT // VRF that matches the inner IP address. portList := []string{"port8"} + t.Run("Verify packets are decap & forward with Default vrf", func(t *testing.T) { + flow1 := createFlow(&flowArgs{flowName: "flow1", + outHdrSrcIP: ipv4OuterSrc111, outHdrDstIP: traffiDstIP1, InnHdrSrcIPv6: atePort1.IPv6, + InnHdrDstIPv6: ipv6InnerDst, isInnHdrV4: false, outHdrDscp: []uint32{dscpEncapNoMatch}}) - flow1 := createFlow(&flowArgs{flowName: "flow1", - outHdrSrcIP: ipv4OuterSrc111, outHdrDstIP: traffiDstIP1, InnHdrSrcIPv6: atePort1.IPv6, - InnHdrDstIPv6: ipv6InnerDst, isInnHdrV4: false, outHdrDscp: []uint32{dscpEncapNoMatch}}) - - flow2 := createFlow(&flowArgs{flowName: "flow2", - outHdrSrcIP: ipv4OuterSrc111, outHdrDstIP: traffiDstIP2, InnHdrSrcIP: atePort1.IPv4, - InnHdrDstIP: ipv4InnerDst, isInnHdrV4: true, outHdrDscp: []uint32{dscpEncapNoMatch}}) + flow2 := createFlow(&flowArgs{flowName: "flow2", + outHdrSrcIP: ipv4OuterSrc111, outHdrDstIP: traffiDstIP2, InnHdrSrcIP: atePort1.IPv4, + InnHdrDstIP: ipv4InnerDst, isInnHdrV4: true, outHdrDscp: []uint32{dscpEncapNoMatch}}) - sendTraffic(t, args, portList, []gosnappi.Flow{flow1, flow2}) - verifyTraffic(t, args, []string{"flow1", "flow2"}, !wantLoss) - captureAndValidatePackets(t, args, &packetValidation{portName: portList[0], - outDstIP: []string{traffiDstIP1}, inHdrIP: ipv4InnerDst, validateTTL: false, validateDecap: true}) + sendTraffic(t, args, portList, []gosnappi.Flow{flow1, flow2}) + verifyTraffic(t, args, []string{"flow1", "flow2"}, !wantLoss) + captureAndValidatePackets(t, args, &packetValidation{portName: portList[0], + outDstIP: []string{traffiDstIP1}, inHdrIP: ipv4InnerDst, validateTTL: false, validateDecap: true}) + }) // Test with packets with a destination address that does not match // the decap route, and verify that such packets are not decapped. diff --git a/feature/experimental/isis/otg_tests/isis_interface_hello_padding_enable_test/isis_interface_hello_padding_enable_test.go b/feature/experimental/isis/otg_tests/isis_interface_hello_padding_enable_test/isis_interface_hello_padding_enable_test.go index 3e5ed1a4a69..8823ec9e638 100644 --- a/feature/experimental/isis/otg_tests/isis_interface_hello_padding_enable_test/isis_interface_hello_padding_enable_test.go +++ b/feature/experimental/isis/otg_tests/isis_interface_hello_padding_enable_test/isis_interface_hello_padding_enable_test.go @@ -110,9 +110,11 @@ func configureISIS(t *testing.T, ts *isissession.TestSession) { isisIntfLevelTimers.HelloInterval = ygot.Uint32(5) isisIntfLevelTimers.HelloMultiplier = ygot.Uint8(3) - isisIntfLevel.GetOrCreateAf(oc.IsisTypes_AFI_TYPE_IPV4, oc.IsisTypes_SAFI_TYPE_UNICAST).Enabled = ygot.Bool(true) + if !deviations.ISISInterfaceAfiUnsupported(ts.DUT) { + isisIntfLevel.GetOrCreateAf(oc.IsisTypes_AFI_TYPE_IPV4, oc.IsisTypes_SAFI_TYPE_UNICAST).Enabled = ygot.Bool(true) + isisIntfLevel.GetOrCreateAf(oc.IsisTypes_AFI_TYPE_IPV6, oc.IsisTypes_SAFI_TYPE_UNICAST).Enabled = ygot.Bool(true) + } isisIntfLevel.GetOrCreateAf(oc.IsisTypes_AFI_TYPE_IPV4, oc.IsisTypes_SAFI_TYPE_UNICAST).Metric = ygot.Uint32(v4Metric) - isisIntfLevel.GetOrCreateAf(oc.IsisTypes_AFI_TYPE_IPV6, oc.IsisTypes_SAFI_TYPE_UNICAST).Enabled = ygot.Bool(true) isisIntfLevel.GetOrCreateAf(oc.IsisTypes_AFI_TYPE_IPV6, oc.IsisTypes_SAFI_TYPE_UNICAST).Metric = ygot.Uint32(v6Metric) } @@ -347,28 +349,42 @@ func TestIsisInterfaceHelloPaddingEnable(t *testing.T) { 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 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) + if !deviations.ISISCounterManualAddressDropFromAreasUnsupported(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) + } } - 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) + if !deviations.ISISCounterPartChangesUnsupported(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) + } } if got := gnmi.Get(t, ts.DUT, statePath.Level(2).SystemLevelCounters().SpfRuns().State()); got == 0 { t.Errorf("FAIL- Not expecting spf runs counter to be 0, got %d, want non zero", got) } }) t.Run("Route checks", func(t *testing.T) { - if got := gnmi.Get(t, ts.DUT, statePath.Level(2).Lsp(ateLspID).Tlv(oc.IsisLsdbTypes_ISIS_TLV_TYPE_EXTENDED_IPV4_REACHABILITY).ExtendedIpv4Reachability().Prefix(v4Route).Prefix().State()); got != v4Route { - t.Errorf("FAIL- Expected v4 route not found in isis, got %v, want %v", got, v4Route) - } - if got := gnmi.Get(t, ts.DUT, statePath.Level(2).Lsp(ateLspID).Tlv(oc.IsisLsdbTypes_ISIS_TLV_TYPE_IPV6_REACHABILITY).Ipv6Reachability().Prefix(v6Route).Prefix().State()); got != v6Route { - t.Errorf("FAIL- Expected v6 route not found in isis, got %v, want %v", got, v6Route) - } - if got := gnmi.Get(t, ts.DUT, gnmi.OC().NetworkInstance(deviations.DefaultNetworkInstance(ts.DUT)).Afts().Ipv4Entry(v4Route).State()).GetPrefix(); got != v4Route { - t.Errorf("FAIL- Expected v4 route not found in aft, got %v, want %v", got, v4Route) - } - if got := gnmi.Get(t, ts.DUT, gnmi.OC().NetworkInstance(deviations.DefaultNetworkInstance(ts.WithISIS().DUT)).Afts().Ipv6Entry(v6Route).State()).GetPrefix(); got != v6Route { - t.Errorf("FAIL- Expected v6 route not found in aft, got %v, want %v", got, v6Route) + _, ok := gnmi.Await(t, ts.DUT, statePath.Level(2).Lsp(ateLspID).Tlv(oc.IsisLsdbTypes_ISIS_TLV_TYPE_EXTENDED_IPV4_REACHABILITY).ExtendedIpv4Reachability().Prefix(v4Route).Prefix().State(), 1*time.Minute, v4Route).Val() + if !ok { + t.Errorf("FAIL- Couldn't find v4Route in dut LSP TLV") + } + _, ok = gnmi.Await(t, ts.DUT, statePath.Level(2).Lsp(ateLspID).Tlv(oc.IsisLsdbTypes_ISIS_TLV_TYPE_IPV6_REACHABILITY).Ipv6Reachability().Prefix(v6Route).Prefix().State(), 1*time.Minute, v6Route).Val() + if !ok { + t.Errorf("FAIL- Couldn't find v6Route in dut LSP TLV") + } + ipv4Path := gnmi.OC().NetworkInstance(deviations.DefaultNetworkInstance(ts.DUT)).Afts().Ipv4Entry(v4Route) + if got, ok := gnmi.Watch(t, ts.DUT, ipv4Path.State(), time.Minute, func(val *ygnmi.Value[*oc.NetworkInstance_Afts_Ipv4Entry]) bool { + ipv4Entry, present := val.Val() + return present && ipv4Entry.GetPrefix() == v4Route + }).Await(t); !ok { + t.Errorf("ipv4-entry/state/prefix got %v, want %s", got, v4Route) + } + ipv6Path := gnmi.OC().NetworkInstance(deviations.DefaultNetworkInstance(ts.DUT)).Afts().Ipv6Entry(v6Route) + if got, ok := gnmi.Watch(t, ts.DUT, ipv6Path.State(), time.Minute, func(val *ygnmi.Value[*oc.NetworkInstance_Afts_Ipv6Entry]) bool { + ipv6Entry, present := val.Val() + return present && ipv6Entry.GetPrefix() == v6Route + }).Await(t); !ok { + t.Errorf("ipv6-entry/state/prefix got %v, want %s", got, v6Route) } }) t.Run("Traffic checks", func(t *testing.T) { diff --git a/feature/experimental/isis/otg_tests/isis_interface_hello_padding_enable_test/metadata.textproto b/feature/experimental/isis/otg_tests/isis_interface_hello_padding_enable_test/metadata.textproto index d80b6324c7e..b534b4ef211 100644 --- a/feature/experimental/isis/otg_tests/isis_interface_hello_padding_enable_test/metadata.textproto +++ b/feature/experimental/isis/otg_tests/isis_interface_hello_padding_enable_test/metadata.textproto @@ -41,6 +41,7 @@ platform_exceptions: { isis_timers_csnp_interval_unsupported: true isis_counter_manual_address_drop_from_areas_unsupported: true isis_counter_part_changes_unsupported: true + isis_interface_afi_unsupported: true } } platform_exceptions: { diff --git a/feature/experimental/isis/otg_tests/isis_metric_style_wide_enabled_test/README.md b/feature/experimental/isis/otg_tests/isis_metric_style_wide_enabled_test/README.md index 7d563c2c2f9..1a08deafff6 100644 --- a/feature/experimental/isis/otg_tests/isis_metric_style_wide_enabled_test/README.md +++ b/feature/experimental/isis/otg_tests/isis_metric_style_wide_enabled_test/README.md @@ -16,83 +16,78 @@ * Ensure that IPv4 and IPv6 prefixes that are advertised as part of an (emulated) neighboring system are installed into the DUT routing table, and validate that packets are sent and received to them. -## Config Parameter coverage +## OpenConfig Path and RPC Coverage -* For prefix: - - * /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/config/metric-style - * 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: - - * levels/level/state/metric-style - * 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 +```yaml +paths: + # isis 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/config/metric-style: + /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: + # isis telemetry + /network-instances/network-instance/protocols/protocol/isis/levels/level/state/metric-style: + /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-areas: + /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: + +rpcs: + gnmi: + gNMI.Get: + gNMI.Set: + gNMI.Subscribe: +``` diff --git a/feature/experimental/isis/otg_tests/isis_metric_style_wide_enabled_test/isis_metric_style_wide_enabled_test.go b/feature/experimental/isis/otg_tests/isis_metric_style_wide_enabled_test/isis_metric_style_wide_enabled_test.go index 637993169b5..2ed2ac22d73 100644 --- a/feature/experimental/isis/otg_tests/isis_metric_style_wide_enabled_test/isis_metric_style_wide_enabled_test.go +++ b/feature/experimental/isis/otg_tests/isis_metric_style_wide_enabled_test/isis_metric_style_wide_enabled_test.go @@ -27,6 +27,7 @@ import ( "github.com/openconfig/featureprofiles/internal/otgutils" "github.com/openconfig/ondatra/gnmi" "github.com/openconfig/ondatra/gnmi/oc" + "github.com/openconfig/ygnmi/ygnmi" "github.com/openconfig/ygot/ygot" ) @@ -331,36 +332,44 @@ func TestISISWideMetricEnabled(t *testing.T) { t.Errorf("FAIL- Expected metric style not found, got %s, want %s", got, oc.E_Isis_MetricStyle(2)) } } - if got := gnmi.Get(t, ts.DUT, statePath.Level(2).Lsp(ateLspID).Tlv(oc.IsisLsdbTypes_ISIS_TLV_TYPE_EXTENDED_IPV4_REACHABILITY).ExtendedIpv4Reachability().Prefix(ateV4Route).Prefix().State()); got != ateV4Route { + if got, ok := gnmi.Await(t, ts.DUT, statePath.Level(2).Lsp(ateLspID).Tlv(oc.IsisLsdbTypes_ISIS_TLV_TYPE_EXTENDED_IPV4_REACHABILITY).ExtendedIpv4Reachability().Prefix(ateV4Route).Prefix().State(), 1*time.Minute, ateV4Route).Val(); !ok { t.Errorf("FAIL- Expected ate v4 route not found, got %v, want %v", got, ateV4Route) } - if got := gnmi.Get(t, ts.DUT, statePath.Level(2).Lsp(ateLspID).Tlv(oc.IsisLsdbTypes_ISIS_TLV_TYPE_EXTENDED_IPV4_REACHABILITY).ExtendedIpv4Reachability().Prefix(ateV4Route).Metric().State()); got != ateV4Metric { + if got, ok := gnmi.Await(t, ts.DUT, statePath.Level(2).Lsp(ateLspID).Tlv(oc.IsisLsdbTypes_ISIS_TLV_TYPE_EXTENDED_IPV4_REACHABILITY).ExtendedIpv4Reachability().Prefix(ateV4Route).Metric().State(), 1*time.Minute, ateV4Metric).Val(); !ok { t.Errorf("FAIL- Expected metric for ate v4 route not found, got %v, want %v", got, ateV4Metric) } - if got := gnmi.Get(t, ts.DUT, statePath.Level(2).Lsp(ateLspID).Tlv(oc.IsisLsdbTypes_ISIS_TLV_TYPE_IPV6_REACHABILITY).Ipv6Reachability().Prefix(ateV6Route).Prefix().State()); got != ateV6Route { + if got, ok := gnmi.Await(t, ts.DUT, statePath.Level(2).Lsp(ateLspID).Tlv(oc.IsisLsdbTypes_ISIS_TLV_TYPE_IPV6_REACHABILITY).Ipv6Reachability().Prefix(ateV6Route).Prefix().State(), 1*time.Minute, ateV6Route).Val(); !ok { t.Errorf("FAIL- Expected ate v6 route not found, got %v, want %v", got, ateV6Route) } - if got := gnmi.Get(t, ts.DUT, statePath.Level(2).Lsp(ateLspID).Tlv(oc.IsisLsdbTypes_ISIS_TLV_TYPE_IPV6_REACHABILITY).Ipv6Reachability().Prefix(ateV6Route).Metric().State()); got != ateV6Metric { + if got, ok := gnmi.Await(t, ts.DUT, statePath.Level(2).Lsp(ateLspID).Tlv(oc.IsisLsdbTypes_ISIS_TLV_TYPE_IPV6_REACHABILITY).Ipv6Reachability().Prefix(ateV6Route).Metric().State(), 1*time.Minute, ateV6Metric).Val(); !ok { t.Errorf("FAIL- Expected metric for ate v6 route not found, got %v, want %v", got, ateV6Metric) } - if got := gnmi.Get(t, ts.DUT, gnmi.OC().NetworkInstance(deviations.DefaultNetworkInstance(ts.DUT)).Afts().Ipv4Entry(ateV4Route).State()).GetPrefix(); got != ateV4Route { - t.Errorf("FAIL- Expected ate v4 route not found in aft, got %v, want %v", got, ateV4Route) - } - if got := gnmi.Get(t, ts.DUT, gnmi.OC().NetworkInstance(deviations.DefaultNetworkInstance(ts.DUT)).Afts().Ipv6Entry(ateV6Route).State()).GetPrefix(); got != ateV6Route { - t.Errorf("FAIL- Expected ate v6 route not found in aft, got %v, want %v", got, ateV6Route) - } - if got := gnmi.Get(t, ts.DUT, statePath.Level(2).Lsp(dutLspID).Tlv(oc.IsisLsdbTypes_ISIS_TLV_TYPE_EXTENDED_IPV4_REACHABILITY).ExtendedIpv4Reachability().Prefix(dutV4Route).Prefix().State()); got != dutV4Route { + if got, ok := gnmi.Await(t, ts.DUT, statePath.Level(2).Lsp(dutLspID).Tlv(oc.IsisLsdbTypes_ISIS_TLV_TYPE_EXTENDED_IPV4_REACHABILITY).ExtendedIpv4Reachability().Prefix(dutV4Route).Prefix().State(), 1*time.Minute, dutV4Route).Val(); !ok { t.Errorf("FAIL- Expected dut v4 route not found, got %v, want %v", got, dutV4Route) } - if got := gnmi.Get(t, ts.DUT, statePath.Level(2).Lsp(dutLspID).Tlv(oc.IsisLsdbTypes_ISIS_TLV_TYPE_EXTENDED_IPV4_REACHABILITY).ExtendedIpv4Reachability().Prefix(dutV4Route).Metric().State()); got != dutV4Metric { + if got, ok := gnmi.Await(t, ts.DUT, statePath.Level(2).Lsp(dutLspID).Tlv(oc.IsisLsdbTypes_ISIS_TLV_TYPE_EXTENDED_IPV4_REACHABILITY).ExtendedIpv4Reachability().Prefix(dutV4Route).Metric().State(), 1*time.Minute, dutV4Metric).Val(); !ok { t.Errorf("FAIL- Expected metric for dut v4 route not found, got %v, want %v", got, dutV4Metric) } - if got := gnmi.Get(t, ts.DUT, statePath.Level(2).Lsp(dutLspID).Tlv(oc.IsisLsdbTypes_ISIS_TLV_TYPE_IPV6_REACHABILITY).Ipv6Reachability().Prefix(dutV6Route).Prefix().State()); got != dutV6Route { + if got, ok := gnmi.Await(t, ts.DUT, statePath.Level(2).Lsp(dutLspID).Tlv(oc.IsisLsdbTypes_ISIS_TLV_TYPE_IPV6_REACHABILITY).Ipv6Reachability().Prefix(dutV6Route).Prefix().State(), 1*time.Minute, dutV6Route).Val(); !ok { t.Errorf("FAIL- Expected dut v6 route not found, got %v, want %v", got, dutV6Route) } - if got := gnmi.Get(t, ts.DUT, statePath.Level(2).Lsp(dutLspID).Tlv(oc.IsisLsdbTypes_ISIS_TLV_TYPE_IPV6_REACHABILITY).Ipv6Reachability().Prefix(dutV6Route).Metric().State()); got != dutV6Metric { + if got, ok := gnmi.Await(t, ts.DUT, statePath.Level(2).Lsp(dutLspID).Tlv(oc.IsisLsdbTypes_ISIS_TLV_TYPE_IPV6_REACHABILITY).Ipv6Reachability().Prefix(dutV6Route).Metric().State(), 1*time.Minute, dutV6Metric).Val(); !ok { t.Errorf("FAIL- Expected metric for dut v6 route not found, got %v, want %v", got, dutV6Metric) } + ipv4Path := gnmi.OC().NetworkInstance(deviations.DefaultNetworkInstance(ts.DUT)).Afts().Ipv4Entry(ateV4Route) + if got, ok := gnmi.Watch(t, ts.DUT, ipv4Path.State(), time.Minute, func(val *ygnmi.Value[*oc.NetworkInstance_Afts_Ipv4Entry]) bool { + ipv4Entry, present := val.Val() + return present && ipv4Entry.GetPrefix() == ateV4Route + }).Await(t); !ok { + t.Errorf("ipv4-entry/state/prefix got %v, want %s", got, ateV4Route) + } + ipv6Path := gnmi.OC().NetworkInstance(deviations.DefaultNetworkInstance(ts.DUT)).Afts().Ipv6Entry(ateV6Route) + if got, ok := gnmi.Watch(t, ts.DUT, ipv6Path.State(), time.Minute, func(val *ygnmi.Value[*oc.NetworkInstance_Afts_Ipv6Entry]) bool { + ipv6Entry, present := val.Val() + return present && ipv6Entry.GetPrefix() == ateV6Route + }).Await(t); !ok { + t.Errorf("ipv6-entry/state/prefix got %v, want %s", got, ateV6Route) + } }) t.Run("Traffic checks", func(t *testing.T) { t.Logf("Starting traffic") diff --git a/feature/experimental/isis/otg_tests/lsp_updates_test/metadata.textproto b/feature/experimental/isis/otg_tests/lsp_updates_test/metadata.textproto index 824cd42db30..f9ac6a76780 100644 --- a/feature/experimental/isis/otg_tests/lsp_updates_test/metadata.textproto +++ b/feature/experimental/isis/otg_tests/lsp_updates_test/metadata.textproto @@ -24,7 +24,6 @@ platform_exceptions: { } deviations: { ipv4_missing_enabled: true - isis_interface_level1_disable_required: true } } platform_exceptions: { diff --git a/feature/gnmi/otg_tests/telemetry_port_speed_test/telemetry_port_speed_test.go b/feature/gnmi/otg_tests/telemetry_port_speed_test/telemetry_port_speed_test.go index eb50c2eea38..90f4f8d72fb 100644 --- a/feature/gnmi/otg_tests/telemetry_port_speed_test/telemetry_port_speed_test.go +++ b/feature/gnmi/otg_tests/telemetry_port_speed_test/telemetry_port_speed_test.go @@ -352,9 +352,10 @@ func TestGNMIPortDown(t *testing.T) { portStateAction.Port().Link().SetPortNames([]string{atePort.ID()}).SetState(gosnappi.StatePortLinkState.DOWN) ate.OTG().SetControlState(t, portStateAction) + want := oc.Interface_OperStatus_DOWN + gnmi.Await(t, dut, gnmi.OC().Interface(dutPort.Name()).OperStatus().State(), 1*time.Minute, want) dutPortStatus := gnmi.Get(t, dut, gnmi.OC().Interface(dutPort.Name()).OperStatus().State()) - - if want := oc.Interface_OperStatus_DOWN; dutPortStatus != want { + if dutPortStatus != want { t.Errorf("Get(DUT port1 status): got %v, want %v", dutPortStatus, want) } diff --git a/feature/gnoi/system/tests/copying_debug_files_test/README.md b/feature/gnoi/system/tests/copying_debug_files_test/README.md index 2efcb4b742e..4a18174032a 100644 --- a/feature/gnoi/system/tests/copying_debug_files_test/README.md +++ b/feature/gnoi/system/tests/copying_debug_files_test/README.md @@ -21,9 +21,10 @@ * gNOI-5.3.3 - Chassis Component Health Check * Issue Healthz Check RPC to the DUT for Chassis component to trigger the generation of Artifact ID(s). Artifacts returned should be sufficient for vendor tech support teams to determine if any of the field replaceable components are faulty and must be replaced for that device. - * Verify that the DUT returns the artifact IDs in the Check RPC's response. - * Invoke ArtifactRequest to transfer the requested Artifact ID(s). - * Verify that the DUT returns the artifacts requested. + * Verify that the DUT returns the artifact IDs in the [Check RPC's](https://github.com/openconfig/gnoi/blob/main/healthz/README.md#healthzcheck) response. + * Invoke ArtifactRequest to transfer the requested Artifact ID(s) via [Artifact RPC](https://github.com/openconfig/gnoi/blob/main/healthz/README.md#healthzartifact) + * Verify that the DUT returns the artifacts requested. TODO: (https://github.com/openconfig/featureprofiles/issues/3013) Test has gap and does not retrieve artifacts. + * If ArtifactHeader is of FileArtifactType and a hash field is populated, the hash should be calculated against the Artifact body. TODO: (https://github.com/openconfig/featureprofiles/issues/3013) Test has gap and doesn't validate FileArtifactType hash against artifact body content. ## Process names by vendor * BGP Process diff --git a/feature/gnpsi/otg_tests/sampling_test/README.md b/feature/gnpsi/otg_tests/sampling_test/README.md new file mode 100644 index 00000000000..46a38506db1 --- /dev/null +++ b/feature/gnpsi/otg_tests/sampling_test/README.md @@ -0,0 +1,68 @@ +# gNPSI-1: Sampling and Subscription Check + +## Summary + +The goal is to validate that packet sampling is working as expected, clients can connect to the gNPSI service and receive samples. + +## Procedure + +### Common Test Setup + * Configure DUT with two ports with IPv4/IPv6 addresses + * Configure sFlow and gNPSI on DUT with following parameters: + * Sample size = 256 bytes + * Sampling rate is 1:1M + * Configure OTG traffic with different traffic profiles. + * IPv4 and Ipv6 + * Varying packet sizes (64, 512, 1500) + * Start OTG traffic + +TODO: Add gNPSI client support to OTG. + +### gNPSI 1.1: Validate DUT configuration of gNPSI server, connect OTG client and verify samples. + +* Start the gRPC client and subscribe to the gNPSI service on the DUT. + +* Verify the samples received by the client are as per expectations: + * Samples are formatted as per the sFLOW datagram specifications. + * Appropriate number of samples are received based on the sampling raste. e.g. ~1 in 1M samples is received for a sampling rate of 1:1M. + * Datagram contents are set correctly. + * Sampling rate is correct + * Ingress and egress interfaces are correct + * Inner packets can be parsed correctly + +### gNPSI 1.2: Verify multiple clients can connect to the gNPSI Service and receive samples. + +1. Start 2 gRPC clients and subscribe to the gNPSI service on the DUT. + +2. Verify each client receives ~1 sample for every 1M packet through the DUT. + + +### gNPSI 1.3: Verify client reconnection to the gNPSI service. + +* Start a gRPC client and subscribe to the gRPC service on the DUT, and verify the connection is healthy and samples are received. + +* Disconnect and reconnect the client, and verifying the reconnection is successful, and samples are received. + + +### gNPSI 1.4: Verify client connection after gNPSI service restart. + +* Start a gRPC client and subscribe to the gRPC service on the DUT, and verify the connection is healthy and samples are received. + +* Restart the gNPSI service (This can be done by a switch reboot). + +* Let the gRPC client try to reconnect to gNPSI service every few seconds. The gRPC client should successfully connect to gNPSI service after gNPSI service is up. + +* Verify that the samples are received. + + +## OpenConfig Path and RPC Coverage + +```yaml +rpcs: + gnpsi: + gNPSI.Subscribe: +``` + +## Minimum DUT platform requirement + +N/A diff --git a/feature/gribi/ate_tests/hierarchical_weight_resolution_pbf_test/README.md b/feature/gribi/ate_tests/hierarchical_weight_resolution_pbf_test/README.md index 3dbc48f28fc..d2d65948ea1 100644 --- a/feature/gribi/ate_tests/hierarchical_weight_resolution_pbf_test/README.md +++ b/feature/gribi/ate_tests/hierarchical_weight_resolution_pbf_test/README.md @@ -125,24 +125,18 @@ WCMP width of 16 nexthops: * A tolerance of 0.2% is allowed for each VLAN for now, since we only test for 2 mins. -## Config Parameter Coverage - -N/A - -## Telemetry Parameter Coverage - -TODO: -/network-instances/network-instance/afts/next-hop-groups/next-hop-group/next-hops/next-hop/state/weight - -## Protocol/RPC Parameter coverage - -* gRIBI: - * Modify() - * ModifyRequest: - * AFTOperation: - * next_hop_group - * NextHopGroupKey: id - * NextHopGroup: weight +## OpenConfig Path and RPC Coverage +```yaml +rpcs: + gnmi: + gNMI.Get: + gNMI.Set: + gNMI.Subscribe: + gribi: + gRIBI.Get: + gRIBI.Modify: + gRIBI.Flush: +``` ## Minimum DUT platform requirement diff --git a/feature/gribi/ate_tests/hierarchical_weight_resolution_pbf_test/hierarchical_weight_resolution_pbf_test.go b/feature/gribi/ate_tests/hierarchical_weight_resolution_pbf_test/hierarchical_weight_resolution_pbf_test.go index 27839cf32d6..78883a0158c 100644 --- a/feature/gribi/ate_tests/hierarchical_weight_resolution_pbf_test/hierarchical_weight_resolution_pbf_test.go +++ b/feature/gribi/ate_tests/hierarchical_weight_resolution_pbf_test/hierarchical_weight_resolution_pbf_test.go @@ -692,12 +692,12 @@ func TestHierarchicalWeightResolution(t *testing.T) { } t.Run("TestBasicHierarchicalWeightWithVrfPolW", func(t *testing.T) { - vrfpolicy.ConfigureVRFSelectionPolicyW(t, dut) + vrfpolicy.ConfigureVRFSelectionPolicy(t, dut, vrfpolicy.VRFPolicyW) testBasicHierarchicalWeight(ctx, t, dut, ate, top, gRIBI) }) t.Run("TestHierarchicalWeightBoundaryScenarioWithVrfPolW", func(t *testing.T) { - vrfpolicy.ConfigureVRFSelectionPolicyW(t, dut) + vrfpolicy.ConfigureVRFSelectionPolicy(t, dut, vrfpolicy.VRFPolicyW) testHierarchicalWeightBoundaryScenario(ctx, t, dut, ate, top, gRIBI) }) diff --git a/feature/gribi/otg_tests/backup_ngp_multiple_nh_pbf_test/README.md b/feature/gribi/otg_tests/backup_ngp_multiple_nh_pbf_test/README.md index 4feb5156dcd..eeda23362c3 100644 --- a/feature/gribi/otg_tests/backup_ngp_multiple_nh_pbf_test/README.md +++ b/feature/gribi/otg_tests/backup_ngp_multiple_nh_pbf_test/README.md @@ -32,21 +32,18 @@ Ensure that backup NHGs are honoured with NextHopGroup entries containing >1 NH. * Disable ATE port-3. Ensure that traffic for the destination is received at ATE port-4. -## Config Parameter coverage - -* No new configuration covered. - -## Telemetry Parameter coverage - -* No new telemetry covered. - -## Protocol/RPC Parameter coverage - -* gRIBI: - * Modify - * ModifyRequest - * NextHopGroup - * backup_nexthop_group +## OpenConfig Path and RPC Coverage +```yaml +rpcs: + gnmi: + gNMI.Get: + gNMI.Set: + gNMI.Subscribe: + gribi: + gRIBI.Get: + gRIBI.Modify: + gRIBI.Flush: +``` ## Minimum DUT platform requirement diff --git a/feature/gribi/otg_tests/backup_ngp_multiple_nh_pbf_test/backup_nhg_multiple_nh_pbf_test.go b/feature/gribi/otg_tests/backup_ngp_multiple_nh_pbf_test/backup_nhg_multiple_nh_pbf_test.go index 9eeb31f7b7d..68e2fedaf56 100644 --- a/feature/gribi/otg_tests/backup_ngp_multiple_nh_pbf_test/backup_nhg_multiple_nh_pbf_test.go +++ b/feature/gribi/otg_tests/backup_ngp_multiple_nh_pbf_test/backup_nhg_multiple_nh_pbf_test.go @@ -274,7 +274,7 @@ func TestBackup(t *testing.T) { top: top, } - vrfpolicy.ConfigureVRFSelectionPolicyW(t, dut) + vrfpolicy.ConfigureVRFSelectionPolicy(t, dut, vrfpolicy.VRFPolicyW) tcArgs.testIPv4BackUpSwitch(t) } diff --git a/feature/gribi/otg_tests/base_hierarchical_nhg_update/README.md b/feature/gribi/otg_tests/base_hierarchical_nhg_update/README.md index 6cb9726073e..85eda40e170 100644 --- a/feature/gribi/otg_tests/base_hierarchical_nhg_update/README.md +++ b/feature/gribi/otg_tests/base_hierarchical_nhg_update/README.md @@ -43,10 +43,6 @@ and it should not change the expected test result. * Replace the existing VRF selection policy with `vrf_selection_policy_w` as in -## Config Parameter coverage - -No configuration relevant. - ## Telemetry Parameter coverage For prefix: @@ -77,30 +73,18 @@ Parameters: * next-hops/next-hop/state/ip-address * next-hops/next-hop/state/mac-address -## Protocol/RPC Parameter coverage - -* gRIBI: - * Modify() - * ModifyRequest: - * AFTOperation: - * id - * network_instance - * op - * Ipv4 - * Ipv4EntryKey: prefix - * Ipv4Entry: next_hop_group - * next_hop_group - * NextHopGroupKey: id - * NextHopGroup: next_hop - * next_hop - * NextHopKey: id - * NextHop: - * mac_address - * interface_ref - * ModifyResponse: - * AFTResult: - * id - * status +## OpenConfig Path and RPC Coverage +```yaml +rpcs: + gnmi: + gNMI.Get: + gNMI.Set: + gNMI.Subscribe: + gribi: + gRIBI.Get: + gRIBI.Modify: + gRIBI.Flush: +``` ## Minimum DUT platform requirement diff --git a/feature/gribi/otg_tests/base_hierarchical_nhg_update/base_hierarchical_nhg_update_test.go b/feature/gribi/otg_tests/base_hierarchical_nhg_update/base_hierarchical_nhg_update_test.go index c705b00528b..16c26bfcead 100644 --- a/feature/gribi/otg_tests/base_hierarchical_nhg_update/base_hierarchical_nhg_update_test.go +++ b/feature/gribi/otg_tests/base_hierarchical_nhg_update/base_hierarchical_nhg_update_test.go @@ -283,7 +283,7 @@ func testBaseHierarchialNHGwithVrfPolW(ctx context.Context, t *testing.T, args * if deviations.SkipPbfWithDecapEncapVrf(args.dut) { t.Skip("Skipping test as pbf with decap encap vrf is not supported") } - vrfpolicy.ConfigureVRFSelectionPolicyW(t, args.dut) + vrfpolicy.ConfigureVRFSelectionPolicy(t, args.dut, vrfpolicy.VRFPolicyW) ctx = context.WithValue(ctx, transitKey{}, true) testBaseHierarchialNHG(ctx, t, args) diff --git a/feature/gribi/otg_tests/basic_encap_test/README.md b/feature/gribi/otg_tests/basic_encap_test/README.md index fbe71d04030..e21fd5f9000 100644 --- a/feature/gribi/otg_tests/basic_encap_test/README.md +++ b/feature/gribi/otg_tests/basic_encap_test/README.md @@ -386,4 +386,36 @@ this test we’ll focus on tunnel traffic identification using ## Required DUT platform -vRX \ No newline at end of file +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 + /network-instances/network-instance/policy-forwarding/policies/policy/config/policy-id: + /network-instances/network-instance/policy-forwarding/policies/policy/rules/rule/config/sequence-id: + /network-instances/network-instance/policy-forwarding/policies/policy/rules/rule/ipv4/config/protocol: + /network-instances/network-instance/policy-forwarding/policies/policy/rules/rule/ipv4/config/dscp-set: + /network-instances/network-instance/policy-forwarding/policies/policy/rules/rule/ipv4/config/source-address: + /network-instances/network-instance/policy-forwarding/policies/policy/rules/rule/ipv6/config/protocol: + /network-instances/network-instance/policy-forwarding/policies/policy/rules/rule/ipv6/config/dscp-set: + /network-instances/network-instance/policy-forwarding/policies/policy/rules/rule/ipv6/config/source-address: + /network-instances/network-instance/policy-forwarding/policies/policy/rules/rule/action/config/decap-network-instance: + /network-instances/network-instance/policy-forwarding/policies/policy/rules/rule/action/config/post-decap-network-instance: + /network-instances/network-instance/policy-forwarding/policies/policy/rules/rule/action/config/decap-fallback-network-instance: + + ## State paths + /interfaces/interface/subinterfaces/subinterface/ipv4/neighbors/neighbor/state/link-layer-address: + +rpcs: + gnmi: + gNMI.Set: + gNMI.Subscribe: + gribi: + gRIBI.Modify: + gRIBI.Flush: +``` diff --git a/feature/gribi/otg_tests/basic_encap_test/basic_encap_test.go b/feature/gribi/otg_tests/basic_encap_test/basic_encap_test.go index a9d33bea3e2..5e9548e7507 100644 --- a/feature/gribi/otg_tests/basic_encap_test/basic_encap_test.go +++ b/feature/gribi/otg_tests/basic_encap_test/basic_encap_test.go @@ -209,9 +209,9 @@ var ( } dutPort2DummyIP = attrs.Attributes{ - Desc: "dutPort2", - IPv4: "192.0.2.21", - IPv4Len: ipv4PrefixLen, + Desc: "dutPort2", + IPv4Sec: "192.0.2.21", + IPv4LenSec: ipv4PrefixLen, } otgPort2DummyIP = attrs.Attributes{ @@ -221,9 +221,9 @@ var ( } dutPort3DummyIP = attrs.Attributes{ - Desc: "dutPort3", - IPv4: "192.0.2.25", - IPv4Len: ipv4PrefixLen, + Desc: "dutPort3", + IPv4Sec: "192.0.2.25", + IPv4LenSec: ipv4PrefixLen, } otgPort3DummyIP = attrs.Attributes{ @@ -233,9 +233,9 @@ var ( } dutPort4DummyIP = attrs.Attributes{ - Desc: "dutPort4", - IPv4: "192.0.2.29", - IPv4Len: ipv4PrefixLen, + Desc: "dutPort4", + IPv4Sec: "192.0.2.29", + IPv4LenSec: ipv4PrefixLen, } otgPort4DummyIP = attrs.Attributes{ @@ -245,9 +245,9 @@ var ( } dutPort5DummyIP = attrs.Attributes{ - Desc: "dutPort5", - IPv4: "192.0.2.33", - IPv4Len: ipv4PrefixLen, + Desc: "dutPort5", + IPv4Sec: "192.0.2.33", + IPv4LenSec: ipv4PrefixLen, } otgPort5DummyIP = attrs.Attributes{ diff --git a/feature/gribi/otg_tests/encap_frr/README.md b/feature/gribi/otg_tests/encap_frr/README.md index e15d20946a7..3ae508d48a6 100644 --- a/feature/gribi/otg_tests/encap_frr/README.md +++ b/feature/gribi/otg_tests/encap_frr/README.md @@ -494,11 +494,18 @@ be routed to the DEFAULT VRF for further lookup. * network-instances/network-instance/policy-forwarding/policies/policy/rules/rule/action/post-network-instance * network-instances/network-instance/policy-forwarding/policies/policy/rules/rule/action/decap-fallback-network-instance -## Protocol/RPC Parameter Coverage - -* gRIBI: - * Modify - * ModifyRequest +## OpenConfig Path and RPC Coverage +```yaml +rpcs: + gnmi: + gNMI.Get: + gNMI.Set: + gNMI.Subscribe: + gribi: + gRIBI.Get: + gRIBI.Modify: + gRIBI.Flush: +``` ## Required DUT platform 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 46e80f2bef2..04a9d884de3 100644 --- a/feature/gribi/otg_tests/encap_frr/encap_frr_test.go +++ b/feature/gribi/otg_tests/encap_frr/encap_frr_test.go @@ -36,6 +36,8 @@ import ( "github.com/openconfig/featureprofiles/internal/deviations" "github.com/openconfig/featureprofiles/internal/fptest" "github.com/openconfig/featureprofiles/internal/gribi" + "github.com/openconfig/featureprofiles/internal/vrfpolicy" + spb "github.com/openconfig/gnoi/system" "github.com/openconfig/gribigo/chk" "github.com/openconfig/gribigo/constants" "github.com/openconfig/gribigo/fluent" @@ -44,6 +46,7 @@ import ( "github.com/openconfig/ondatra/gnmi/oc" "github.com/openconfig/ondatra/netutil" "github.com/openconfig/ondatra/otg" + "github.com/openconfig/testt" "github.com/openconfig/ygnmi/ygnmi" "github.com/openconfig/ygot/ygot" ) @@ -90,6 +93,7 @@ const ( niEncapTeVrfB = "ENCAP_TE_VRF_B" niTeVrf111 = "TE_VRF_111" niTeVrf222 = "TE_VRF_222" + niDefault = "DEFAULT" tolerancePct = 2 tolerance = 0.2 encapFlow = "encapFlow" @@ -129,6 +133,14 @@ const ( checkEncap = true wantLoss = true + + // Chassis reboot variables + oneSecondInNanoSecond = 1e9 + rebootDelay = 120 + // Maximum reboot time is 900 seconds (15 minutes). + maxRebootTime = 900 + // Maximum wait time for all components to be in responsive state + maxCompWaitTime = 600 ) var ( @@ -190,6 +202,75 @@ var ( IPv4Len: 32, IPv6Len: 128, } + dutPort2DummyIP = attrs.Attributes{ + Desc: "dutPort2", + IPv4Sec: "192.0.2.33", + IPv4LenSec: plenIPv4, + } + + otgPort2DummyIP = attrs.Attributes{ + Desc: "otgPort2", + IPv4: "192.0.2.34", + IPv4Len: plenIPv4, + } + + dutPort3DummyIP = attrs.Attributes{ + Desc: "dutPort3", + IPv4Sec: "192.0.2.37", + IPv4LenSec: plenIPv4, + } + + otgPort3DummyIP = attrs.Attributes{ + Desc: "otgPort3", + IPv4: "192.0.2.38", + IPv4Len: plenIPv4, + } + + dutPort4DummyIP = attrs.Attributes{ + Desc: "dutPort4", + IPv4Sec: "192.0.2.41", + IPv4LenSec: plenIPv4, + } + + otgPort4DummyIP = attrs.Attributes{ + Desc: "otgPort4", + IPv4: "192.0.2.42", + IPv4Len: plenIPv4, + } + + dutPort5DummyIP = attrs.Attributes{ + Desc: "dutPort5", + IPv4Sec: "192.0.2.45", + IPv4LenSec: plenIPv4, + } + + otgPort5DummyIP = attrs.Attributes{ + Desc: "otgPort5", + IPv4: "192.0.2.46", + IPv4Len: plenIPv4, + } + dutPort6DummyIP = attrs.Attributes{ + Desc: "dutPort5", + IPv4Sec: "192.0.2.49", + IPv4LenSec: plenIPv4, + } + + otgPort6DummyIP = attrs.Attributes{ + Desc: "otgPort5", + IPv4: "192.0.2.50", + IPv4Len: plenIPv4, + } + dutPort7DummyIP = attrs.Attributes{ + Desc: "dutPort5", + IPv4Sec: "192.0.2.53", + IPv4LenSec: plenIPv4, + } + + otgPort7DummyIP = attrs.Attributes{ + Desc: "otgPort5", + IPv4: "192.0.2.54", + IPv4Len: plenIPv4, + } loopbackIntfName string atePortNamelist []string ) @@ -213,18 +294,6 @@ type testArgs struct { otg *otg.OTG } -type policyFwRule struct { - SeqID uint32 - family string - protocol oc.UnionUint8 - dscpSet []uint8 - sourceAddr string - decapNi string - postDecapNi string - decapFallbackNi string - networkInstance string -} - // incrementMAC increments the MAC by i. Returns error if the mac cannot be parsed or overflows the mac address space func incrementMAC(mac string, i int) (string, error) { macAddr, err := net.ParseMAC(mac) @@ -268,7 +337,7 @@ func dutInterface(p *ondatra.Port, dut *ondatra.DUTDevice) *oc.Interface { i.Enabled = ygot.Bool(true) } - if p.PMD() == ondatra.PMD100GBASEFR { + if p.PMD() == ondatra.PMD100GBASEFR && dut.Vendor() != ondatra.CISCO { e := i.GetOrCreateEthernet() e.AutoNegotiate = ygot.Bool(false) e.DuplexMode = oc.Ethernet_DuplexMode_FULL @@ -301,6 +370,29 @@ func dutInterface(p *ondatra.Port, dut *ondatra.DUTDevice) *oc.Interface { return i } +// staticARPWithSecondaryIP configures secondary IPs and static ARP. +func staticARPWithSpecificIP(t *testing.T, dut *ondatra.DUTDevice) { + t.Helper() + p2 := dut.Port(t, "port2") + p3 := dut.Port(t, "port3") + p4 := dut.Port(t, "port4") + p5 := dut.Port(t, "port5") + p6 := dut.Port(t, "port6") + p7 := dut.Port(t, "port7") + gnmi.Update(t, dut, gnmi.OC().Interface(p2.Name()).Config(), dutPort2DummyIP.NewOCInterface(p2.Name(), dut)) + gnmi.Update(t, dut, gnmi.OC().Interface(p3.Name()).Config(), dutPort3DummyIP.NewOCInterface(p3.Name(), dut)) + gnmi.Update(t, dut, gnmi.OC().Interface(p4.Name()).Config(), dutPort4DummyIP.NewOCInterface(p4.Name(), dut)) + gnmi.Update(t, dut, gnmi.OC().Interface(p5.Name()).Config(), dutPort5DummyIP.NewOCInterface(p5.Name(), dut)) + gnmi.Update(t, dut, gnmi.OC().Interface(p6.Name()).Config(), dutPort6DummyIP.NewOCInterface(p6.Name(), dut)) + gnmi.Update(t, dut, gnmi.OC().Interface(p7.Name()).Config(), dutPort7DummyIP.NewOCInterface(p7.Name(), dut)) + gnmi.Update(t, dut, gnmi.OC().Interface(p2.Name()).Config(), configStaticArp(p2.Name(), otgPort2DummyIP.IPv4, magicMac)) + gnmi.Update(t, dut, gnmi.OC().Interface(p3.Name()).Config(), configStaticArp(p3.Name(), otgPort3DummyIP.IPv4, magicMac)) + gnmi.Update(t, dut, gnmi.OC().Interface(p4.Name()).Config(), configStaticArp(p4.Name(), otgPort4DummyIP.IPv4, magicMac)) + gnmi.Update(t, dut, gnmi.OC().Interface(p5.Name()).Config(), configStaticArp(p5.Name(), otgPort5DummyIP.IPv4, magicMac)) + gnmi.Update(t, dut, gnmi.OC().Interface(p6.Name()).Config(), configStaticArp(p6.Name(), otgPort6DummyIP.IPv4, magicMac)) + gnmi.Update(t, dut, gnmi.OC().Interface(p7.Name()).Config(), configStaticArp(p7.Name(), otgPort7DummyIP.IPv4, magicMac)) +} + // configureDUT configures all the interfaces on the DUT. func configureDUT(t *testing.T, dut *ondatra.DUTDevice, dutPortList []*ondatra.Port) { dc := gnmi.OC() @@ -343,116 +435,8 @@ func configureDUT(t *testing.T, dut *ondatra.DUTDevice, dutPortList []*ondatra.P t.Logf("Got DUT IPv4 loopback address: %v", dutlo0Attrs.IPv4) t.Logf("Got DUT IPv6 loopback address: %v", dutlo0Attrs.IPv6) } -} - -func configureVrfSelectionPolicy(t *testing.T, dut *ondatra.DUTDevice) { - t.Helper() - d := &oc.Root{} - dutPolFwdPath := gnmi.OC().NetworkInstance(deviations.DefaultNetworkInstance(dut)).PolicyForwarding() - - pfRule1 := &policyFwRule{SeqID: 1, family: "ipv4", protocol: 4, dscpSet: []uint8{dscpEncapA1, dscpEncapA2}, sourceAddr: ipv4OuterSrc222Addr + "/32", - decapNi: niDecapTeVrf, postDecapNi: niEncapTeVrfA, decapFallbackNi: niTeVrf222} - pfRule2 := &policyFwRule{SeqID: 2, family: "ipv4", protocol: 41, dscpSet: []uint8{dscpEncapA1, dscpEncapA2}, sourceAddr: ipv4OuterSrc222Addr + "/32", - decapNi: niDecapTeVrf, postDecapNi: niEncapTeVrfA, decapFallbackNi: niTeVrf222} - pfRule3 := &policyFwRule{SeqID: 3, family: "ipv4", protocol: 4, dscpSet: []uint8{dscpEncapA1, dscpEncapA2}, sourceAddr: ipv4OuterSrc111Addr + "/32", - decapNi: niDecapTeVrf, postDecapNi: niEncapTeVrfA, decapFallbackNi: niTeVrf111} - pfRule4 := &policyFwRule{SeqID: 4, family: "ipv4", protocol: 41, dscpSet: []uint8{dscpEncapA1, dscpEncapA2}, sourceAddr: ipv4OuterSrc111Addr + "/32", - decapNi: niDecapTeVrf, postDecapNi: niEncapTeVrfA, decapFallbackNi: niTeVrf111} - - pfRule5 := &policyFwRule{SeqID: 5, family: "ipv4", protocol: 4, dscpSet: []uint8{dscpEncapB1, dscpEncapB2}, sourceAddr: ipv4OuterSrc222Addr + "/32", - decapNi: niDecapTeVrf, postDecapNi: niEncapTeVrfB, decapFallbackNi: niTeVrf222} - pfRule6 := &policyFwRule{SeqID: 6, family: "ipv4", protocol: 41, dscpSet: []uint8{dscpEncapB1, dscpEncapB2}, sourceAddr: ipv4OuterSrc222Addr + "/32", - decapNi: niDecapTeVrf, postDecapNi: niEncapTeVrfB, decapFallbackNi: niTeVrf222} - pfRule7 := &policyFwRule{SeqID: 7, family: "ipv4", protocol: 4, dscpSet: []uint8{dscpEncapB1, dscpEncapB2}, sourceAddr: ipv4OuterSrc111Addr + "/32", - decapNi: niDecapTeVrf, postDecapNi: niEncapTeVrfB, decapFallbackNi: niTeVrf111} - pfRule8 := &policyFwRule{SeqID: 8, family: "ipv4", protocol: 41, dscpSet: []uint8{dscpEncapB1, dscpEncapB2}, sourceAddr: ipv4OuterSrc111Addr + "/32", - decapNi: niDecapTeVrf, postDecapNi: niEncapTeVrfB, decapFallbackNi: niTeVrf111} - - pfRule9 := &policyFwRule{SeqID: 9, family: "ipv4", protocol: 4, sourceAddr: ipv4OuterSrc222Addr + "/32", - decapNi: niDecapTeVrf, postDecapNi: deviations.DefaultNetworkInstance(dut), decapFallbackNi: niTeVrf222} - pfRule10 := &policyFwRule{SeqID: 10, family: "ipv4", protocol: 41, sourceAddr: ipv4OuterSrc222Addr + "/32", - decapNi: niDecapTeVrf, postDecapNi: deviations.DefaultNetworkInstance(dut), decapFallbackNi: niTeVrf222} - pfRule11 := &policyFwRule{SeqID: 11, family: "ipv4", protocol: 4, sourceAddr: ipv4OuterSrc111Addr + "/32", - decapNi: niDecapTeVrf, postDecapNi: deviations.DefaultNetworkInstance(dut), decapFallbackNi: niTeVrf111} - pfRule12 := &policyFwRule{SeqID: 12, family: "ipv4", protocol: 41, sourceAddr: ipv4OuterSrc111Addr + "/32", - decapNi: niDecapTeVrf, postDecapNi: deviations.DefaultNetworkInstance(dut), decapFallbackNi: niTeVrf111} - - pfRule13 := &policyFwRule{SeqID: 13, family: "ipv4", dscpSet: []uint8{dscpEncapA1, dscpEncapA2}, - networkInstance: niEncapTeVrfA} - pfRule14 := &policyFwRule{SeqID: 14, family: "ipv6", dscpSet: []uint8{dscpEncapA1, dscpEncapA2}, - networkInstance: niEncapTeVrfA} - pfRule15 := &policyFwRule{SeqID: 15, family: "ipv4", dscpSet: []uint8{dscpEncapB1, dscpEncapB2}, - networkInstance: niEncapTeVrfB} - pfRule16 := &policyFwRule{SeqID: 16, family: "ipv6", dscpSet: []uint8{dscpEncapB1, dscpEncapB2}, - networkInstance: niEncapTeVrfB} - pfRule17 := &policyFwRule{SeqID: 17, networkInstance: deviations.DefaultNetworkInstance(dut)} - - pfRuleList := []*policyFwRule{pfRule1, pfRule2, pfRule3, pfRule4, pfRule5, pfRule6, - pfRule7, pfRule8, pfRule9, pfRule10, pfRule11, pfRule12, pfRule13, pfRule14, - pfRule15, pfRule16, pfRule17} - - ni := d.GetOrCreateNetworkInstance(deviations.DefaultNetworkInstance(dut)) - niP := ni.GetOrCreatePolicyForwarding() - niPf := niP.GetOrCreatePolicy(polName) - niPf.SetType(oc.Policy_Type_VRF_SELECTION_POLICY) - - for _, pfRule := range pfRuleList { - pfR := niPf.GetOrCreateRule(pfRule.SeqID) - - if pfRule.family == "ipv4" { - pfRProtoIP := pfR.GetOrCreateIpv4() - if pfRule.protocol != 0 { - pfRProtoIP.Protocol = oc.UnionUint8(pfRule.protocol) - } - if pfRule.sourceAddr != "" { - pfRProtoIP.SourceAddress = ygot.String(pfRule.sourceAddr) - } - if pfRule.dscpSet != nil { - pfRProtoIP.DscpSet = pfRule.dscpSet - } - } else if pfRule.family == "ipv6" { - pfRProtoIP := pfR.GetOrCreateIpv6() - if pfRule.dscpSet != nil { - pfRProtoIP.DscpSet = pfRule.dscpSet - } - } - - pfRAction := pfR.GetOrCreateAction() - if pfRule.decapNi != "" { - pfRAction.DecapNetworkInstance = ygot.String(pfRule.decapNi) - } - if pfRule.postDecapNi != "" { - pfRAction.PostDecapNetworkInstance = ygot.String(pfRule.postDecapNi) - } - if pfRule.decapFallbackNi != "" { - pfRAction.DecapFallbackNetworkInstance = ygot.String(pfRule.decapFallbackNi) - } - if pfRule.networkInstance != "" { - pfRAction.NetworkInstance = ygot.String(pfRule.networkInstance) - } - } - - p1 := dut.Port(t, "port1") - intf := niP.GetOrCreateInterface(p1.Name()) - intf.ApplyVrfSelectionPolicy = ygot.String(polName) - intf.GetOrCreateInterfaceRef().Interface = ygot.String(p1.Name()) - intf.GetOrCreateInterfaceRef().Subinterface = ygot.Uint32(0) - if deviations.InterfaceRefConfigUnsupported(dut) { - intf.InterfaceRef = nil - } - gnmi.Replace(t, dut, dutPolFwdPath.Config(), niP) -} - -// configureNetworkInstance configures vrfs DECAP_TE_VRF,ENCAP_TE_VRF_A,ENCAP_TE_VRF_B, -// TE_VRF_222, TE_VRF_111. -func configNonDefaultNetworkInstance(t *testing.T, dut *ondatra.DUTDevice) { - t.Helper() - c := &oc.Root{} - vrfs := []string{"DECAP_TE_VRF", niEncapTeVrfA, niEncapTeVrfB, niTeVrf222, niTeVrf111} - for _, vrf := range vrfs { - ni := c.GetOrCreateNetworkInstance(vrf) - ni.Type = oc.NetworkInstanceTypes_NETWORK_INSTANCE_TYPE_L3VRF - gnmi.Replace(t, dut, gnmi.OC().NetworkInstance(vrf).Config(), ni) + if deviations.GRIBIMACOverrideWithStaticARP(dut) { + staticARPWithSpecificIP(t, dut) } } @@ -496,6 +480,53 @@ func staticARPWithMagicUniversalIP(t *testing.T, dut *ondatra.DUTDevice) { sb.Set(t, dut) } +func programAftWithDummyIP(t *testing.T, dut *ondatra.DUTDevice, args *testArgs) { + args.client.Modify().AddEntry(t, + fluent.NextHopEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). + WithIndex(11).WithMacAddress(magicMac).WithInterfaceRef(dut.Port(t, "port2").Name()). + WithIPAddress(otgPort2DummyIP.IPv4), + fluent.NextHopEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). + WithIndex(12).WithMacAddress(magicMac).WithInterfaceRef(dut.Port(t, "port3").Name()). + WithIPAddress(otgPort3DummyIP.IPv4), + fluent.NextHopGroupEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). + WithID(11).AddNextHop(11, 1).AddNextHop(12, 3), + fluent.IPv4Entry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). + WithPrefix(gribiIPv4EntryDefVRF1+"/"+maskLen32).WithNextHopGroup(11), + + fluent.NextHopEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). + WithIndex(13).WithMacAddress(magicMac).WithInterfaceRef(dut.Port(t, "port4").Name()). + WithIPAddress(otgPort4DummyIP.IPv4), + fluent.NextHopGroupEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). + WithID(12).AddNextHop(13, 2), + fluent.IPv4Entry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). + WithPrefix(gribiIPv4EntryDefVRF2+"/"+maskLen32).WithNextHopGroup(12), + + fluent.NextHopEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). + WithIndex(14).WithMacAddress(magicMac).WithInterfaceRef(dut.Port(t, "port5").Name()). + WithIPAddress(otgPort5DummyIP.IPv4), + fluent.NextHopGroupEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). + WithID(13).AddNextHop(14, 1), + fluent.IPv4Entry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). + WithPrefix(gribiIPv4EntryDefVRF3+"/"+maskLen32).WithNextHopGroup(13), + + fluent.NextHopEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). + WithIndex(15).WithMacAddress(magicMac).WithInterfaceRef(dut.Port(t, "port6").Name()). + WithIPAddress(otgPort6DummyIP.IPv4), + fluent.NextHopGroupEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). + WithID(14).AddNextHop(15, 1), + fluent.IPv4Entry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). + WithPrefix(gribiIPv4EntryDefVRF4+"/"+maskLen32).WithNextHopGroup(14), + + fluent.NextHopEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). + WithIndex(16).WithMacAddress(magicMac).WithInterfaceRef(dut.Port(t, "port7").Name()). + WithIPAddress(otgPort7DummyIP.IPv4), + fluent.NextHopGroupEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). + WithID(15).AddNextHop(16, 1), + fluent.IPv4Entry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). + WithPrefix(gribiIPv4EntryDefVRF5+"/"+maskLen32).WithNextHopGroup(15), + ) +} + func configureGribiRoute(ctx context.Context, t *testing.T, dut *ondatra.DUTDevice, args *testArgs) { t.Helper() @@ -529,6 +560,8 @@ func configureGribiRoute(ctx context.Context, t *testing.T, dut *ondatra.DUTDevi fluent.NextHopGroupEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). WithID(15).AddNextHop(16, 1), ) + } else if deviations.GRIBIMACOverrideWithStaticARP(dut) { + programAftWithDummyIP(t, dut, args) } else { args.client.Modify().AddEntry(t, fluent.NextHopEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). @@ -699,7 +732,7 @@ func configureGribiRoute(ctx context.Context, t *testing.T, dut *ondatra.DUTDevi WithIPinIP(ipv4OuterSrc111Addr, gribiIPv4EntryVRF1112). WithNextHopNetworkInstance(niTeVrf111), fluent.NextHopGroupEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithID(101).AddNextHop(101, 1).AddNextHop(102, 3).WithBackupNHG(18), + WithID(101).AddNextHop(101, 1).AddNextHop(102, 3), fluent.IPv4Entry().WithNetworkInstance(niEncapTeVrfA).WithNextHopGroupNetworkInstance(deviations.DefaultNetworkInstance(dut)). WithPrefix(gribiIPv4EntryEncapVRF+"/"+maskLen24).WithNextHopGroup(101), ) @@ -774,7 +807,11 @@ func bgpCreateNbr(localAs uint32, dut *ondatra.DUTDevice) *oc.NetworkInstance_Pr bgpNbr.PeerAs = ygot.Uint32(localAs) bgpNbr.Enabled = ygot.Bool(true) bgpNbrT := bgpNbr.GetOrCreateTransport() - bgpNbrT.LocalAddress = ygot.String(dutlo0Attrs.IPv4) + localAddressLeaf := dutlo0Attrs.IPv4 + if dut.Vendor() == ondatra.CISCO { + localAddressLeaf = loopbackIntfName + } + bgpNbrT.LocalAddress = ygot.String(localAddressLeaf) af4 := bgpNbr.GetOrCreateAfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV4_UNICAST) af4.Enabled = ygot.Bool(true) af6 := bgpNbr.GetOrCreateAfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV6_UNICAST) @@ -1160,10 +1197,169 @@ func validateTrafficDistribution(t *testing.T, ate *ondatra.ATEDevice, wantWeigh } } +func FetchUniqueItems(t *testing.T, s []string) []string { + itemExisted := make(map[string]bool) + var uniqueList []string + for _, item := range s { + if _, ok := itemExisted[item]; !ok { + itemExisted[item] = true + uniqueList = append(uniqueList, item) + } else { + t.Logf("Detected duplicated item: %v", item) + } + } + return uniqueList +} + +func ChassisReboot(t *testing.T) { + dut := ondatra.DUT(t, "dut") + + cases := []struct { + desc string + rebootRequest *spb.RebootRequest + }{ + { + desc: "Reboot chassis with delay", + rebootRequest: &spb.RebootRequest{ + Method: spb.RebootMethod_COLD, + Delay: rebootDelay * oneSecondInNanoSecond, + Message: "Reboot chassis with delay", + Force: true, + }}, + } + + versions := gnmi.GetAll(t, dut, gnmi.OC().ComponentAny().SoftwareVersion().State()) + expectedVersion := FetchUniqueItems(t, versions) + sort.Strings(expectedVersion) + t.Logf("DUT software version: %v", expectedVersion) + + preRebootCompStatus := gnmi.GetAll(t, dut, gnmi.OC().ComponentAny().OperStatus().State()) + t.Logf("DUT components status pre reboot: %v", preRebootCompStatus) + + preRebootCompDebug := gnmi.GetAll(t, dut, gnmi.OC().ComponentAny().State()) + preCompMatrix := []string{} + for _, preComp := range preRebootCompDebug { + if preComp.GetOperStatus() != oc.PlatformTypes_COMPONENT_OPER_STATUS_UNSET { + preCompMatrix = append(preCompMatrix, preComp.GetName()+":"+preComp.GetOperStatus().String()) + } + } + for _, tc := range cases { + t.Run(tc.desc, func(t *testing.T) { + t.Logf("Starting reboot: %v", tc.desc) + gnoiClient, err := dut.RawAPIs().BindingDUT().DialGNOI(context.Background()) + if err != nil { + t.Fatalf("Error dialing gNOI: %v", err) + } + bootTimeBeforeReboot := gnmi.Get(t, dut, gnmi.OC().System().BootTime().State()) + t.Logf("DUT boot time before reboot: %v", bootTimeBeforeReboot) + prevTime, err := time.Parse(time.RFC3339, gnmi.Get(t, dut, gnmi.OC().System().CurrentDatetime().State())) + if err != nil { + t.Fatalf("Failed parsing current-datetime: %s", err) + } + start := time.Now() + + t.Logf("Send reboot request: %v", tc.rebootRequest) + rebootResponse, err := gnoiClient.System().Reboot(context.Background(), tc.rebootRequest) + defer gnoiClient.System().CancelReboot(context.Background(), &spb.CancelRebootRequest{}) + t.Logf("Got reboot response: %v, err: %v", rebootResponse, err) + if err != nil { + t.Fatalf("Failed to reboot chassis with unexpected err: %v", err) + } + + if tc.rebootRequest.GetDelay() > 1 { + t.Logf("Validating DUT remains reachable for at least %d seconds", rebootDelay) + for { + time.Sleep(10 * time.Second) + t.Logf("Time elapsed %.2f seconds since reboot was requested.", time.Since(start).Seconds()) + if time.Since(start).Seconds() > rebootDelay { + t.Logf("Time elapsed %.2f seconds > %d reboot delay", time.Since(start).Seconds(), rebootDelay) + break + } + latestTime, err := time.Parse(time.RFC3339, gnmi.Get(t, dut, gnmi.OC().System().CurrentDatetime().State())) + if err != nil { + t.Fatalf("Failed parsing current-datetime: %s", err) + } + if latestTime.Before(prevTime) || latestTime.Equal(prevTime) { + t.Errorf("Get latest system time: got %v, want newer time than %v", latestTime, prevTime) + } + prevTime = latestTime + } + } + + startReboot := time.Now() + t.Logf("Wait for DUT to boot up by polling the telemetry output.") + for { + var currentTime string + t.Logf("Time elapsed %.2f seconds since reboot started.", time.Since(startReboot).Seconds()) + time.Sleep(30 * time.Second) + if errMsg := testt.CaptureFatal(t, func(t testing.TB) { + currentTime = gnmi.Get(t, dut, gnmi.OC().System().CurrentDatetime().State()) + }); errMsg != nil { + t.Logf("Got testt.CaptureFatal errMsg: %s, keep polling ...", *errMsg) + } else { + t.Logf("Device rebooted successfully with received time: %v", currentTime) + break + } + + if uint64(time.Since(startReboot).Seconds()) > maxRebootTime { + t.Errorf("Check boot time: got %v, want < %v", time.Since(startReboot), maxRebootTime) + } + } + t.Logf("Device boot time: %.2f seconds", time.Since(startReboot).Seconds()) + + bootTimeAfterReboot := gnmi.Get(t, dut, gnmi.OC().System().BootTime().State()) + t.Logf("DUT boot time after reboot: %v", bootTimeAfterReboot) + if bootTimeAfterReboot <= bootTimeBeforeReboot { + t.Errorf("Get boot time: got %v, want > %v", bootTimeAfterReboot, bootTimeBeforeReboot) + } + + startComp := time.Now() + t.Logf("Wait for all the components on DUT to come up") + + for { + postRebootCompStatus := gnmi.GetAll(t, dut, gnmi.OC().ComponentAny().OperStatus().State()) + postRebootCompDebug := gnmi.GetAll(t, dut, gnmi.OC().ComponentAny().State()) + postCompMatrix := []string{} + for _, postComp := range postRebootCompDebug { + if postComp.GetOperStatus() != oc.PlatformTypes_COMPONENT_OPER_STATUS_UNSET { + postCompMatrix = append(postCompMatrix, postComp.GetName()+":"+postComp.GetOperStatus().String()) + } + } + + if len(preRebootCompStatus) == len(postRebootCompStatus) { + t.Logf("All components on the DUT are in responsive state") + time.Sleep(10 * time.Second) + break + } + + if uint64(time.Since(startComp).Seconds()) > maxCompWaitTime { + t.Logf("DUT components status post reboot: %v", postRebootCompStatus) + if rebootDiff := cmp.Diff(preCompMatrix, postCompMatrix); rebootDiff != "" { + t.Logf("[DEBUG] Unexpected diff after reboot (-component missing from pre reboot, +component added from pre reboot): %v ", rebootDiff) + } + t.Fatalf("There's a difference in components obtained in pre reboot: %v and post reboot: %v.", len(preRebootCompStatus), len(postRebootCompStatus)) + } + time.Sleep(10 * time.Second) + } + + versions = gnmi.GetAll(t, dut, gnmi.OC().ComponentAny().SoftwareVersion().State()) + swVersion := FetchUniqueItems(t, versions) + sort.Strings(swVersion) + t.Logf("DUT software version after reboot: %v", swVersion) + if diff := cmp.Diff(expectedVersion, swVersion); diff != "" { + t.Errorf("Software version differed (-want +got):\n%v", diff) + } + }) + } +} + // TestEncapFrr is to test Test FRR behaviors with encapsulation scenarios func TestEncapFrr(t *testing.T) { ctx := context.Background() dut := ondatra.DUT(t, "dut") + if dut.Vendor() == ondatra.CISCO { + ChassisReboot(t) + } gribic := dut.RawAPIs().GRIBI(t) ate := ondatra.ATE(t, "ate") @@ -1174,9 +1370,6 @@ func TestEncapFrr(t *testing.T) { t.Log("Configure Default Network Instance") fptest.ConfigureDefaultNetworkInstance(t, dut) - t.Log("Configure Non-Default Network Instances") - configNonDefaultNetworkInstance(t, dut) - if deviations.BackupNHGRequiresVrfWithDecap(dut) { d := &oc.Root{} ni := d.GetOrCreateNetworkInstance(deviations.DefaultNetworkInstance(dut)) @@ -1194,7 +1387,7 @@ func TestEncapFrr(t *testing.T) { configureDUT(t, dut, dutPorts) t.Log("Apply vrf selection policy to DUT port-1") - configureVrfSelectionPolicy(t, dut) + vrfpolicy.ConfigureVRFSelectionPolicy(t, dut, vrfpolicy.VRFPolicyC) if deviations.GRIBIMACOverrideStaticARPStaticRoute(dut) { staticARPWithMagicUniversalIP(t, dut) diff --git a/feature/gribi/otg_tests/encap_frr/metadata.textproto b/feature/gribi/otg_tests/encap_frr/metadata.textproto index a0b9f7a1b75..7837a2abc82 100644 --- a/feature/gribi/otg_tests/encap_frr/metadata.textproto +++ b/feature/gribi/otg_tests/encap_frr/metadata.textproto @@ -12,6 +12,10 @@ platform_exceptions: { } deviations: { ipv4_missing_enabled: true + gribi_mac_override_with_static_arp: true + interface_ref_interface_id_format: true + pf_require_match_default_rule: true + pf_require_sequential_order_pbr_rules: true } } platform_exceptions: { diff --git a/feature/gribi/otg_tests/gribi_scaling/README.md b/feature/gribi/otg_tests/gribi_scaling/README.md index cc55075e625..f286dec9da6 100644 --- a/feature/gribi/otg_tests/gribi_scaling/README.md +++ b/feature/gribi/otg_tests/gribi_scaling/README.md @@ -38,3 +38,16 @@ Validate gRIBI scaling requirements. * Validate that the entries are installed as FIB_PROGRAMMED * TODO: Add flows destinating to IPBlocks and ensure ATEPort2 receives it with no loss + +## OpenConfig Path and RPC Coverage +```yaml +rpcs: + gnmi: + gNMI.Get: + gNMI.Set: + gNMI.Subscribe: + gribi: + gRIBI.Get: + gRIBI.Modify: + gRIBI.Flush: +``` 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 c8ed4bf9571..1acc9728a5d 100644 --- a/feature/gribi/otg_tests/gribi_scaling/gribi_scaling_test.go +++ b/feature/gribi/otg_tests/gribi_scaling/gribi_scaling_test.go @@ -20,16 +20,18 @@ import ( "encoding/binary" "fmt" "net" + "strings" "testing" "time" "github.com/open-traffic-generator/snappi/gosnappi" + fpargs "github.com/openconfig/featureprofiles/internal/args" "github.com/openconfig/featureprofiles/internal/attrs" "github.com/openconfig/featureprofiles/internal/deviations" "github.com/openconfig/featureprofiles/internal/fptest" "github.com/openconfig/featureprofiles/internal/gribi" - "github.com/openconfig/gribigo/chk" - "github.com/openconfig/gribigo/constants" + "github.com/openconfig/featureprofiles/internal/otgutils" + "github.com/openconfig/featureprofiles/internal/tescale" "github.com/openconfig/gribigo/fluent" "github.com/openconfig/ondatra" "github.com/openconfig/ondatra/gnmi" @@ -46,30 +48,19 @@ func TestMain(m *testing.M) { // // The testbed consists of ate:port1 -> dut:port1 // and dut:port2 -> ate:port2. -// There are 64 SubInterfaces between dut:port2 +// There are 16 SubInterfaces between dut:port2 // and ate:port2 // // - ate:port1 -> dut:port1 subnet 192.0.2.0/30 -// - ate:port2 -> dut:port2 64 Sub interfaces: +// - ate:port2 -> dut:port2 16 Sub interfaces: // - ate:port2.0 -> dut:port2.0 VLAN-ID: 0 subnet 198.51.100.0/30 // - ate:port2.1 -> dut:port2.1 VLAN-ID: 1 subnet 198.51.100.4/30 // - ate:port2.2 -> dut:port2.2 VLAN-ID: 2 subnet 198.51.100.8/30 // - ate:port2.i -> dut:port2.i VLAN-ID i subnet 198.51.100.(4*i)/30 -// - ate:port2.63 -> dut:port2.63 VLAN-ID 63 subnet 198.51.100.252/30 +// - ate:port2.16 -> dut:port2.16 VLAN-ID 16 subnet 198.51.100.60/30 const ( ipv4PrefixLen = 30 // ipv4PrefixLen is the ATE and DUT interface IP prefix length. - vrf1 = "vrf1" - vrf2 = "vrf2" - vrf3 = "vrf3" - IPBlock1 = "198.18.0.1/18" // IPBlock1 represents the ipv4 entries in VRF1 - IPBlock2 = "198.18.64.1/18" // IPBlock2 represents the ipv4 entries in VRF2 - IPBlock3 = "198.18.128.1/18" // IPBlock3 represents the ipv4 entries in VRF3 - nhID1 = 65 // nhID1 is the starting nh index for entries in VRF1 - nhID2 = 1065 // nhID2 is the starting nh index for entries in VRF2 - nhID3 = 18565 // nhID3 is the starting nh index for entries in VRF3 - tunnelSrcIP = "198.18.204.1" // tunnelSrcIP represents Source IP of IPinIP Tunnel - tunnelDstIP = "198.18.208.1" // tunnelDstIP represents Dest IP of IPinIP Tunnel - policyName = "redirect-to-VRF1" + policyName = "redirect-to-vrf_t" ) var ( @@ -87,219 +78,12 @@ var ( } ) -// entryIndex captures all the parameters required for specifying : -// -// a. number of nextHops in a nextHopGroup -// b. number of IPEntries per nextHopGroup -type routesParam struct { - nhgIndex int // nhgIndex is the starting nhg Index for each IPBlock - maxNhCount int // maxNhCount is the max number of nexthops per nextHopGroup - maxIPCount int // maxIPCount is the max numbver of IPs per nextHopGroup - vrf string // vrf represents the name of the vrf string - nhID int // nhID is the starting nh Index for each nextHop range -} - -// pushIPv4Entries pushes IP entries in a specified VRF in the target DUT. -// It uses the parameters from entryIndex and virtualVIPs for programming entries. -func pushIPv4Entries(t *testing.T, virtualVIPs []string, indices []*routesParam, args *testArgs) { - - IPBlocks := make(map[string][]string) - IPBlocks[vrf1] = createIPv4Entries(IPBlock1) - IPBlocks[vrf2] = createIPv4Entries(IPBlock2) - IPBlocks[vrf3] = createIPv4Entries(IPBlock3) - nextHops := make(map[string][]string) - nextHops[vrf2] = buildL3NextHops(17500, virtualVIPs) - nextHops[vrf1] = virtualVIPs - nextHops[vrf3] = IPBlocks[vrf1][:500] - - for _, index := range indices { - installEntries(t, IPBlocks[index.vrf], nextHops[index.vrf], *index, args) - } -} - -// buildIndexList returns all indices required for installing entries in each VRF. -func buildIndexList() []*routesParam { - index1v4 := &routesParam{nhgIndex: 3, maxNhCount: 10, maxIPCount: 200, vrf: vrf1, nhID: nhID1} - index2v4 := &routesParam{nhgIndex: 103, maxNhCount: 35, maxIPCount: 60, vrf: vrf2, nhID: nhID2} - index3v4 := &routesParam{nhgIndex: 605, maxNhCount: 1, maxIPCount: 40, vrf: vrf3, nhID: nhID3} - - return []*routesParam{index1v4, index2v4, index3v4} -} - -// buildL3NextHop buids N number of NHs each reference (squentially) an IP from the provided IP block. -func buildL3NextHops(n int, ips []string) []string { - // repeatedNextHops will store the "n" times repeated ips []string - repeatedNextHops := []string{} - if n > len(ips) { - repeatCount := len(ips) / n - for min, max := 1, repeatCount; min < max; { - repeatedNextHops = append(repeatedNextHops, ips...) - min = min + 1 - } - repeatCount = len(ips) % n - if repeatCount > 0 { - repeatedNextHops = append(repeatedNextHops, ips[:repeatCount]...) - } - } - return repeatedNextHops -} - -// createIPv4Entries creates IPv4 Entries given the totalCount and starting prefix -func createIPv4Entries(startIP string) []string { - - _, netCIDR, _ := net.ParseCIDR(startIP) - netMask := binary.BigEndian.Uint32(netCIDR.Mask) - firstIP := binary.BigEndian.Uint32(netCIDR.IP) - lastIP := (firstIP & netMask) | (netMask ^ 0xffffffff) - entries := []string{} - for i := firstIP; i <= lastIP; i++ { - ip := make(net.IP, 4) - binary.BigEndian.PutUint32(ip, i) - - entries = append(entries, fmt.Sprint(ip)) - } - return entries -} - -// installEntries installs IPv4 Entries in the VRF with the given nextHops and nextHopGroups using gRIBI. -func installEntries(t *testing.T, ips []string, nexthops []string, index routesParam, args *testArgs) { - nextCount := 0 - localIndex := index.nhgIndex - for i, ateAddr := range nexthops { - ind := uint64(index.nhID + i) - if index.vrf == "vrf3" { - nh := fluent.NextHopEntry(). - WithNetworkInstance(deviations.DefaultNetworkInstance(args.dut)). - WithIndex(ind). - WithIPinIP(tunnelSrcIP, ateAddr). - WithDecapsulateHeader(fluent.IPinIP). - WithEncapsulateHeader(fluent.IPinIP). - WithNextHopNetworkInstance(vrf1). - WithElectionID(args.electionID.Low, args.electionID.High) - args.client.Modify().AddEntry(t, nh) - } else { - nh := fluent.NextHopEntry(). - WithNetworkInstance(deviations.DefaultNetworkInstance(args.dut)). - WithIndex(ind). - WithIPAddress(ateAddr). - WithElectionID(args.electionID.Low, args.electionID.High) - args.client.Modify().AddEntry(t, nh) - } - - nhg := fluent.NextHopGroupEntry(). - WithNetworkInstance(deviations.DefaultNetworkInstance(args.dut)). - WithID(uint64(localIndex)). - AddNextHop(ind, uint64(index.maxNhCount)). - WithElectionID(args.electionID.Low, args.electionID.High) - args.client.Modify().AddEntry(t, nhg) - nextCount = nextCount + 1 - if nextCount == index.maxNhCount { - localIndex = localIndex + 1 - nextCount = 0 - } - } - nhgCount := localIndex - index.nhgIndex - if nextCount == 0 { // last nhg without no nh needs to be ignored - nhgCount-- - } - // maxIPCount should be set based on the number of added nhg, - // otherwise ipv4entry may be added with invalid nhg id (Note. forward refrencing is not allowed) - index.maxIPCount = (len(ips) / nhgCount) + 1 - nextCount = 0 - localIndex = index.nhgIndex - for ip := range ips { - args.client.Modify().AddEntry(t, - fluent.IPv4Entry(). - WithPrefix(ips[ip]+"/32"). - WithNetworkInstance(index.vrf). - WithNextHopGroup(uint64(localIndex)). - WithNextHopGroupNetworkInstance(deviations.DefaultNetworkInstance(args.dut))) - nextCount = nextCount + 1 - if nextCount == index.maxIPCount { - localIndex = localIndex + 1 - nextCount = 0 - } - } - - time.Sleep(1 * time.Minute) - if err := awaitTimeout(args.ctx, args.client, t, 2*time.Minute); err != nil { - t.Fatalf("Could not program entries via clientA, got err: %v", err) - } - gr, err := args.client.Get(). - WithNetworkInstance(index.vrf). - WithAFT(fluent.IPv4). - Send() - if err != nil { - t.Fatalf("got unexpected error from get, got: %v", err) - } - nextCount = 0 - for ip := range ips { - chk.GetResponseHasEntries(t, gr, - fluent.IPv4Entry(). - WithNetworkInstance(index.vrf). - WithNextHopGroup(uint64(index.nhgIndex)). - WithPrefix(ips[ip]+"/32"), - ) - nextCount = nextCount + 1 - if nextCount == index.maxIPCount { - index.nhgIndex = index.nhgIndex + 1 - nextCount = 0 - } - } -} - -// pushDefaultEntries creates NextHopGroup entries using the 64 SubIntf address and creates 1000 IPV4 Entries. -func pushDefaultEntries(t *testing.T, args *testArgs, nextHops []string) []string { - for i := range nextHops { - index := uint64(i + 1) - args.client.Modify().AddEntry(t, - fluent.NextHopEntry(). - WithNetworkInstance(deviations.DefaultNetworkInstance(args.dut)). - WithIndex(index). - WithIPAddress(nextHops[i]). - WithElectionID(args.electionID.Low, args.electionID.High)) - - args.client.Modify().AddEntry(t, - fluent.NextHopGroupEntry(). - WithNetworkInstance(deviations.DefaultNetworkInstance(args.dut)). - WithID(uint64(2)). - AddNextHop(index, 64). - WithElectionID(args.electionID.Low, args.electionID.High)) - } - time.Sleep(time.Minute) - virtualVIPs := createIPv4Entries("198.18.196.1/22") - - for ip := range virtualVIPs { - args.client.Modify().AddEntry(t, - fluent.IPv4Entry(). - WithPrefix(virtualVIPs[ip]+"/32"). - WithNetworkInstance(deviations.DefaultNetworkInstance(args.dut)). - WithNextHopGroup(uint64(2)). - WithElectionID(args.electionID.Low, args.electionID.High)) - } - if err := awaitTimeout(args.ctx, args.client, t, time.Minute); err != nil { - t.Fatalf("Could not program entries via clientA, got err: %v", err) - } - - for ip := range virtualVIPs { - chk.HasResult(t, args.client.Results(t), - fluent.OperationResult(). - WithIPv4Operation(virtualVIPs[ip]+"/32"). - WithOperationType(constants.Add). - WithProgrammingResult(fluent.InstalledInFIB). - AsResult(), - chk.IgnoreOperationID(), - ) - } - return virtualVIPs -} - func configureDUT(t *testing.T, dut *ondatra.DUTDevice) { dp1 := dut.Port(t, "port1") dp2 := dut.Port(t, "port2") d := &oc.Root{} - vrfs := []string{deviations.DefaultNetworkInstance(dut), vrf1, vrf2, vrf3} + vrfs := []string{deviations.DefaultNetworkInstance(dut), tescale.VRFT, tescale.VRFR, tescale.VRFRD} createVrf(t, dut, vrfs) // configure Ethernet interfaces first @@ -314,7 +98,7 @@ func configureDUT(t *testing.T, dut *ondatra.DUTDevice) { applyForwardingPolicy(t, dp1.Name()) - // configure 64 L3 subinterfaces under DUT port#2 and assign them to DEFAULT vrf + // configure 16 L3 subinterfaces under DUT port#2 and assign them to DEFAULT vrf configureDUTSubIfs(t, d, dut, dp2) } @@ -344,7 +128,7 @@ func configurePBF(dut *ondatra.DUTDevice) *oc.NetworkInstance_PolicyForwarding { vrfPolicy := pf.GetOrCreatePolicy(policyName) vrfPolicy.SetType(oc.Policy_Type_VRF_SELECTION_POLICY) vrfPolicy.GetOrCreateRule(1).GetOrCreateIpv4().SourceAddress = ygot.String(atePort1.IPv4 + "/32") - vrfPolicy.GetOrCreateRule(1).GetOrCreateAction().NetworkInstance = ygot.String(vrf1) + vrfPolicy.GetOrCreateRule(1).GetOrCreateAction().NetworkInstance = ygot.String(tescale.VRFT) return pf } @@ -405,9 +189,9 @@ func createSubifDUT(t *testing.T, d *oc.Root, dut *ondatra.DUTDevice, dutPort *o gnmi.Replace(t, dut, gnmi.OC().Interface(ifName).Subinterface(index).Config(), s) } -// configureDUTSubIfs configures 64 DUT subinterfaces on the target device +// configureDUTSubIfs configures 16 DUT subinterfaces on the target device func configureDUTSubIfs(t *testing.T, d *oc.Root, dut *ondatra.DUTDevice, dutPort *ondatra.Port) { - for i := 0; i < 64; i++ { + for i := 0; i < 16; i++ { index := uint32(i) vlanID := uint16(i) if deviations.NoMixOfTaggedAndUntaggedSubinterfaces(dut) { @@ -421,11 +205,11 @@ func configureDUTSubIfs(t *testing.T, d *oc.Root, dut *ondatra.DUTDevice, dutPor } } -// configureATESubIfs configures 64 ATE subinterfaces on the target device +// configureATESubIfs configures 16 ATE subinterfaces on the target device // It returns a slice of the corresponding ATE IPAddresses. func configureATESubIfs(t *testing.T, top gosnappi.Config, atePort *ondatra.Port, dut *ondatra.DUTDevice) []string { nextHops := []string{} - for i := 0; i < 64; i++ { + for i := 0; i < 16; i++ { vlanID := uint16(i) if deviations.NoMixOfTaggedAndUntaggedSubinterfaces(dut) { vlanID = uint16(i) + 1 @@ -460,16 +244,6 @@ func awaitTimeout(ctx context.Context, c *fluent.GRIBIClient, t testing.TB, time return c.Await(subctx, t) } -// testArgs holds the objects needed by a test case. -type testArgs struct { - ctx context.Context - client *fluent.GRIBIClient - dut *ondatra.DUTDevice - ate *ondatra.ATEDevice - top gosnappi.Config - electionID gribi.Uint128 -} - // incrementMAC increments the MAC by i. Returns error if the mac cannot be parsed or overflows the mac address space func incrementMAC(mac string, i int) (string, error) { macAddr, err := net.ParseMAC(mac) @@ -528,20 +302,79 @@ func TestScaling(t *testing.T) { if err := awaitTimeout(ctx, client, t, time.Minute); err != nil { t.Fatalf("Await got error during session negotiation for clientA: %v", err) } - eID := gribi.BecomeLeader(t, client) - - args := &testArgs{ - ctx: ctx, - client: client, - dut: dut, - ate: ate, - top: top, - electionID: eID, + gribi.BecomeLeader(t, client) + + // pushIPv4EntriesRefactored(t, args, subIntfIPs) + vrfConfigs := tescale.BuildVRFConfig(dut, subIntfIPs, + tescale.Param{ + V4TunnelCount: *fpargs.V4TunnelCount, + V4TunnelNHGCount: *fpargs.V4TunnelNHGCount, + V4TunnelNHGSplitCount: *fpargs.V4TunnelNHGSplitCount, + EgressNHGSplitCount: *fpargs.EgressNHGSplitCount, + V4ReEncapNHGCount: *fpargs.V4ReEncapNHGCount, + }, + ) + for _, vrfConfig := range vrfConfigs { + entries := append(vrfConfig.NHs, vrfConfig.NHGs...) + entries = append(entries, vrfConfig.V4Entries...) + client.Modify().AddEntry(t, entries...) + if err := awaitTimeout(ctx, client, t, 2*time.Minute); err != nil { + t.Fatalf("Could not program entries, got err: %v", err) + } + t.Logf("Created %d NHs, %d NHGs, %d IPv4Entries in %s VRF", len(vrfConfig.NHs), len(vrfConfig.NHGs), len(vrfConfig.V4Entries), vrfConfig.Name) + } + + createFlow(t, ate, top, vrfConfigs[1]) + checkTraffic(t, ate, top) +} + +func createFlow(t *testing.T, ate *ondatra.ATEDevice, top gosnappi.Config, vrfTConf *tescale.VRFConfig) { + dstIPs := []string{} + for _, v4Entry := range vrfTConf.V4Entries { + ep, _ := v4Entry.EntryProto() + dstIPs = append(dstIPs, strings.Split(ep.GetIpv4().GetPrefix(), "/")[0]) + } + rxNames := []string{} + for i := 0; i < 16; i++ { + rxNames = append(rxNames, fmt.Sprintf(`dst%d.IPv4`, i)) + } + + top.Flows().Clear() + flow := top.Flows().Add().SetName("flow") + flow.Metrics().SetEnable(true) + flow.Size().SetFixed(512) + flow.Rate().SetPps(100) + flow.Duration().Continuous() + flow.TxRx().Device(). + SetTxNames([]string{"src.IPv4"}). + SetRxNames(rxNames) + ethHeader := flow.Packet().Add().Ethernet() + ethHeader.Src().SetValue(atePort1.MAC) + v4 := flow.Packet().Add().Ipv4() + v4.Src().SetValue(atePort1.IPv4) + v4.Dst().SetValues(dstIPs) + + ate.OTG().PushConfig(t, top) + ate.OTG().StartProtocols(t) + otgutils.WaitForARP(t, ate.OTG(), top, "flow") +} + +func checkTraffic(t *testing.T, ate *ondatra.ATEDevice, top gosnappi.Config) { + ate.OTG().StartTraffic(t) + time.Sleep(time.Second * 30) + ate.OTG().StopTraffic(t) + + otgutils.LogFlowMetrics(t, ate.OTG(), top) + otgutils.LogPortMetrics(t, ate.OTG(), top) + + t.Log("Checking flow telemetry...") + recvMetric := gnmi.Get(t, ate.OTG(), gnmi.OTG().Flow("flow").State()) + txPackets := recvMetric.GetCounters().GetOutPkts() + rxPackets := recvMetric.GetCounters().GetInPkts() + lostPackets := txPackets - rxPackets + lossPct := lostPackets * 100 / txPackets + + if lossPct > 1 { + t.Errorf("FAIL- Got %v%% packet loss for %s ; expected < 1%%", lossPct, "flow") } - // nextHops are ipv4 entries used for deriving nextHops for IPBlock1 and IPBlock2 - nextHops := pushDefaultEntries(t, args, subIntfIPs) - // indexList is the metadata of number of NH/NHG/IP count/VRF for each IPBlock - indexList := buildIndexList() - // pushIPv4Entries builds the scaling topology. - pushIPv4Entries(t, nextHops, indexList, args) } diff --git a/feature/gribi/otg_tests/gribi_scaling/metadata.textproto b/feature/gribi/otg_tests/gribi_scaling/metadata.textproto index c77d9563f11..9d8d3c39135 100644 --- a/feature/gribi/otg_tests/gribi_scaling/metadata.textproto +++ b/feature/gribi/otg_tests/gribi_scaling/metadata.textproto @@ -43,5 +43,6 @@ platform_exceptions: { deprecated_vlan_id: true interface_enabled: true default_network_instance: "default" + omit_l2_mtu: true } } diff --git a/feature/gribi/otg_tests/hierarchical_weight_resolution_pbf_test/README.md b/feature/gribi/otg_tests/hierarchical_weight_resolution_pbf_test/README.md index 3dbc48f28fc..d2d65948ea1 100644 --- a/feature/gribi/otg_tests/hierarchical_weight_resolution_pbf_test/README.md +++ b/feature/gribi/otg_tests/hierarchical_weight_resolution_pbf_test/README.md @@ -125,24 +125,18 @@ WCMP width of 16 nexthops: * A tolerance of 0.2% is allowed for each VLAN for now, since we only test for 2 mins. -## Config Parameter Coverage - -N/A - -## Telemetry Parameter Coverage - -TODO: -/network-instances/network-instance/afts/next-hop-groups/next-hop-group/next-hops/next-hop/state/weight - -## Protocol/RPC Parameter coverage - -* gRIBI: - * Modify() - * ModifyRequest: - * AFTOperation: - * next_hop_group - * NextHopGroupKey: id - * NextHopGroup: weight +## OpenConfig Path and RPC Coverage +```yaml +rpcs: + gnmi: + gNMI.Get: + gNMI.Set: + gNMI.Subscribe: + gribi: + gRIBI.Get: + gRIBI.Modify: + gRIBI.Flush: +``` ## Minimum DUT platform requirement diff --git a/feature/gribi/otg_tests/hierarchical_weight_resolution_pbf_test/hierarchical_weight_resolution_pbf_test.go b/feature/gribi/otg_tests/hierarchical_weight_resolution_pbf_test/hierarchical_weight_resolution_pbf_test.go index 2291b2aad96..14e31ed3229 100644 --- a/feature/gribi/otg_tests/hierarchical_weight_resolution_pbf_test/hierarchical_weight_resolution_pbf_test.go +++ b/feature/gribi/otg_tests/hierarchical_weight_resolution_pbf_test/hierarchical_weight_resolution_pbf_test.go @@ -738,12 +738,12 @@ func TestHierarchicalWeightResolution(t *testing.T) { } t.Run("TestBasicHierarchicalWeightWithVrfPolW", func(t *testing.T) { - vrfpolicy.ConfigureVRFSelectionPolicyW(t, dut) + vrfpolicy.ConfigureVRFSelectionPolicy(t, dut, vrfpolicy.VRFPolicyW) testBasicHierarchicalWeight(ctx, t, dut, ate, top, gRIBI) }) t.Run("TestHierarchicalWeightBoundaryScenarioWithVrfPolW", func(t *testing.T) { - vrfpolicy.ConfigureVRFSelectionPolicyW(t, dut) + vrfpolicy.ConfigureVRFSelectionPolicy(t, dut, vrfpolicy.VRFPolicyW) testHierarchicalWeightBoundaryScenario(ctx, t, dut, ate, top, gRIBI) }) diff --git a/feature/interface/ip/ipv6_link_local/otg_tests/ipv6_link_local_test/README.md b/feature/interface/ip/ipv6_link_local/otg_tests/ipv6_link_local_test/README.md index 5a8e6dcbbe0..61691865a35 100644 --- a/feature/interface/ip/ipv6_link_local/otg_tests/ipv6_link_local_test/README.md +++ b/feature/interface/ip/ipv6_link_local/otg_tests/ipv6_link_local_test/README.md @@ -46,9 +46,14 @@ Configure an IPv6 address which is in link local scope. Verify the link local IP /interfaces/interface/subinterfaces/subinterface/ipv6/addresses/address/state/type ``` -## Protocol/RPC Parameter Coverage - -None +## OpenConfig Path and RPC Coverage +```yaml +rpcs: + gnmi: + gNMI.Get: + gNMI.Set: + gNMI.Subscribe: +``` ## Required DUT platform diff --git a/feature/interface/ip/ipv6_link_local/otg_tests/ipv6_link_local_test/ipv6_link_local_test.go b/feature/interface/ip/ipv6_link_local/otg_tests/ipv6_link_local_test/ipv6_link_local_test.go index 616a26da2d6..670ec45cc49 100644 --- a/feature/interface/ip/ipv6_link_local/otg_tests/ipv6_link_local_test/ipv6_link_local_test.go +++ b/feature/interface/ip/ipv6_link_local/otg_tests/ipv6_link_local_test/ipv6_link_local_test.go @@ -177,6 +177,10 @@ func configureDUTLinkLocalInterface(t *testing.T, dut *ondatra.DUTDevice) { p1 := dut.Port(t, "port1") srcIntf := dutSrc.NewOCInterface(p1.Name(), dut) subInt := srcIntf.GetOrCreateSubinterface(0) + subInt4 := subInt.GetOrCreateIpv4() + if deviations.InterfaceEnabled(dut) && !deviations.IPv4MissingEnabled(dut) { + subInt4.Enabled = ygot.Bool(true) + } subInt.GetOrCreateIpv6().Enabled = ygot.Bool(true) subInt.GetOrCreateIpv6().GetOrCreateAddress(dutSrc.IPv6).SetType(oc.IfIp_Ipv6AddressType_LINK_LOCAL_UNICAST) gnmi.Replace(t, dut, gnmi.OC().Interface(p1.Name()).Config(), srcIntf) @@ -184,7 +188,11 @@ func configureDUTLinkLocalInterface(t *testing.T, dut *ondatra.DUTDevice) { p2 := dut.Port(t, "port2") dstIntf := dutDst.NewOCInterface(p2.Name(), dut) dstSubInt := dstIntf.GetOrCreateSubinterface(0) + dstSubInt4 := dstSubInt.GetOrCreateIpv4() dstSubInt.GetOrCreateIpv6().Enabled = ygot.Bool(true) + if deviations.InterfaceEnabled(dut) && !deviations.IPv4MissingEnabled(dut) { + dstSubInt4.Enabled = ygot.Bool(true) + } dstSubInt.GetOrCreateIpv6().GetOrCreateAddress(dutDst.IPv6).SetType(oc.IfIp_Ipv6AddressType_LINK_LOCAL_UNICAST) gnmi.Replace(t, dut, gnmi.OC().Interface(p2.Name()).Config(), dstIntf) if deviations.ExplicitInterfaceInDefaultVRF(dut) { diff --git a/feature/interface/ip/ipv6_slaac_link_local/otg_tests/ipv6_slaac_link_local_test/README.md b/feature/interface/ip/ipv6_slaac_link_local/otg_tests/ipv6_slaac_link_local_test/README.md index 2009b5991b2..b29dfea2418 100644 --- a/feature/interface/ip/ipv6_slaac_link_local/otg_tests/ipv6_slaac_link_local_test/README.md +++ b/feature/interface/ip/ipv6_slaac_link_local/otg_tests/ipv6_slaac_link_local_test/README.md @@ -12,14 +12,19 @@ Enable IPv6 on interface level so ipv6 address of link-local scope is generated/ * Configure DUT port 1 with IPv6 so that link local scope IP address is assigned by SLAAC * Validate config and state paths are auto-populated -## Config Parameter Coverage -``` -/interfaces/interface/subinterfaces/subinterface/ipv6/addresses/address/config/ip -``` - -## Telemetry Parameter Coverage -``` -/interfaces/interface/subinterfaces/subinterface/ipv6/addresses/address/state/ip +## OpenConfig Path and RPC Coverage + +```yaml +paths: + ## Config paths + /interfaces/interface/subinterfaces/subinterface/ipv6/addresses/address/config/ip: + ## State paths + /interfaces/interface/subinterfaces/subinterface/ipv6/addresses/address/state/ip: + +rpcs: + gnmi: + gNMI.Subscribe: + gNMI.Set: ``` ## Protocol/RPC Parameter Coverage diff --git a/feature/interface/ip/ipv6_slaac_link_local/otg_tests/ipv6_slaac_link_local_test/ipv6_slaac_link_local_test.go b/feature/interface/ip/ipv6_slaac_link_local/otg_tests/ipv6_slaac_link_local_test/ipv6_slaac_link_local_test.go index 4f20af5993d..f4f005b8985 100644 --- a/feature/interface/ip/ipv6_slaac_link_local/otg_tests/ipv6_slaac_link_local_test/ipv6_slaac_link_local_test.go +++ b/feature/interface/ip/ipv6_slaac_link_local/otg_tests/ipv6_slaac_link_local_test/ipv6_slaac_link_local_test.go @@ -6,6 +6,7 @@ import ( "testing" "time" + "github.com/openconfig/featureprofiles/internal/deviations" "github.com/openconfig/featureprofiles/internal/fptest" "github.com/openconfig/ondatra" "github.com/openconfig/ondatra/gnmi" @@ -29,8 +30,14 @@ func configureDUTLinkLocalInterface(t *testing.T, dut *ondatra.DUTDevice, p *ond intf := &oc.Interface{Name: ygot.String(p.Name())} intf.Description = ygot.String(intfDesc) - intf.GetOrCreateSubinterface(0).GetOrCreateIpv4().SetEnabled(true) - intf.GetOrCreateSubinterface(0).GetOrCreateIpv6().SetEnabled(true) + intf.Type = oc.IETFInterfaces_InterfaceType_ethernetCsmacd + s := intf.GetOrCreateSubinterface(0) + if deviations.InterfaceEnabled(dut) && !deviations.IPv4MissingEnabled(dut) { + s.GetOrCreateIpv4().SetEnabled(true) + } + if deviations.InterfaceEnabled(dut) { + s.GetOrCreateIpv6().SetEnabled(true) + } gnmi.Replace(t, dut, gnmi.OC().Interface(p.Name()).Config(), intf) } diff --git a/feature/interface/ip/ipv6_slaac_link_local/otg_tests/ipv6_slaac_link_local_test/metadata.textproto b/feature/interface/ip/ipv6_slaac_link_local/otg_tests/ipv6_slaac_link_local_test/metadata.textproto index dbbff005f05..ce3c7cd234b 100644 --- a/feature/interface/ip/ipv6_slaac_link_local/otg_tests/ipv6_slaac_link_local_test/metadata.textproto +++ b/feature/interface/ip/ipv6_slaac_link_local/otg_tests/ipv6_slaac_link_local_test/metadata.textproto @@ -8,3 +8,19 @@ testbed: TESTBED_DUT tags: TAGS_AGGREGATION tags: TAGS_TRANSIT tags: TAGS_DATACENTER_EDGE +platform_exceptions: { + platform: { + vendor: CISCO + } + deviations: { + ipv4_missing_enabled: true + } +} +platform_exceptions: { + platform: { + vendor: ARISTA + } + deviations: { + interface_enabled: true + } +} diff --git a/feature/isis/static_route_isis_redistribution/README.md b/feature/isis/otg_tests/static_route_isis_redistribution/README.md similarity index 100% rename from feature/isis/static_route_isis_redistribution/README.md rename to feature/isis/otg_tests/static_route_isis_redistribution/README.md diff --git a/feature/isis/otg_tests/static_route_isis_redistribution/metadata.textproto b/feature/isis/otg_tests/static_route_isis_redistribution/metadata.textproto new file mode 100644 index 00000000000..4f658288c55 --- /dev/null +++ b/feature/isis/otg_tests/static_route_isis_redistribution/metadata.textproto @@ -0,0 +1,35 @@ +# proto-file: github.com/openconfig/featureprofiles/proto/metadata.proto +# proto-message: Metadata + +uuid: "1d0a79c7-7aa8-43a8-b83f-620d40fa1e1a" +plan_id: "RT-2.12" +description: "Static route to IS-IS redistribution" +testbed: TESTBED_DUT_ATE_2LINKS +platform_exceptions: { + platform: { + vendor: CISCO + } + deviations: { + ipv4_missing_enabled: true + missing_isis_interface_afi_safi_enable: true + } +} +platform_exceptions: { + platform: { + vendor: ARISTA + } + deviations: { + interface_enabled: true + default_network_instance: "default" + omit_l2_mtu: true + static_protocol_name: "STATIC" + isis_interface_afi_unsupported: true + isis_instance_enabled_required: true + missing_value_for_defaults: true + skip_isis_set_level: true + skip_setting_disable_metric_propagation: true + ipv6_static_route_with_ipv4_next_hop_requires_static_arp: true + routing_policy_tag_set_embedded: true + same_policy_attached_to_all_afis: true + } +} diff --git a/feature/isis/otg_tests/static_route_isis_redistribution/static_route_isis_redistribution_test.go b/feature/isis/otg_tests/static_route_isis_redistribution/static_route_isis_redistribution_test.go new file mode 100644 index 00000000000..9501309f22e --- /dev/null +++ b/feature/isis/otg_tests/static_route_isis_redistribution/static_route_isis_redistribution_test.go @@ -0,0 +1,546 @@ +// 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 static_route_isis_redistribution_test + +import ( + "context" + "encoding/json" + "fmt" + "strconv" + "testing" + "time" + + "github.com/open-traffic-generator/snappi/gosnappi" + "github.com/openconfig/featureprofiles/internal/deviations" + "github.com/openconfig/featureprofiles/internal/fptest" + "github.com/openconfig/featureprofiles/internal/isissession" + "github.com/openconfig/featureprofiles/internal/otgutils" + gpb "github.com/openconfig/gnmi/proto/gnmi" + "github.com/openconfig/ondatra" + "github.com/openconfig/ondatra/gnmi" + "github.com/openconfig/ondatra/gnmi/oc" + "github.com/openconfig/ygnmi/ygnmi" + "github.com/openconfig/ygot/ygot" +) + +const ( + lossTolerance = float64(1) + ipv4PrefixLen = 30 + ipv6PrefixLen = 126 + v4Route = "192.168.10.0" + v4TrafficStart = "192.168.10.1" + v4RoutePrefix = uint32(24) + v6Route = "2024:db8:128:128::" + v6TrafficStart = "2024:db8:128:128::1" + v6RoutePrefix = uint32(64) + dp2v4Route = "192.168.1.4" + dp2v4Prefix = uint32(30) + dp2v6Route = "2001:DB8::0" + dp2v6Prefix = uint32(126) + v4Flow = "v4Flow" + v6Flow = "v6Flow" + trafficDuration = 30 * time.Second + prefixMatch = "exact" + v4RoutePolicy = "route-policy-v4" + v4Statement = "statement-v4" + v4PrefixSet = "prefix-set-v4" + v6RoutePolicy = "route-policy-v6" + v6Statement = "statement-v6" + v6PrefixSet = "prefix-set-v6" + protoSrc = oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_STATIC + protoDst = oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_ISIS + dummyV6 = "2001:db8::192:0:2:d" + dummyMAC = "00:1A:11:00:0A:BC" + tagValue = 100 +) + +var ( + advertisedIPv4 = ipAddr{address: dp2v4Route, prefix: dp2v4Prefix} + advertisedIPv6 = ipAddr{address: dp2v6Route, prefix: dp2v6Prefix} +) + +func TestMain(m *testing.M) { + fptest.RunTests(m) +} + +type ipAddr struct { + address string + prefix uint32 +} + +type TableConnectionConfig struct { + ImportPolicy []string `json:"import-policy"` + DisableMetricPropagation bool `json:"disable-metric-propagation"` + DstProtocol string `json:"dst-protocol"` + AddressFamily string `json:"address-family"` + SrcProtocol string `json:"src-protocol"` +} + +func getAndVerifyIsisImportPolicy(t *testing.T, + dut *ondatra.DUTDevice, DisableMetricValue bool, + RplName string, addressFamily string) { + + gnmiClient := dut.RawAPIs().GNMI(t) + getResponse, err := gnmiClient.Get(context.Background(), &gpb.GetRequest{ + Path: []*gpb.Path{{ + Elem: []*gpb.PathElem{ + {Name: "network-instances"}, + {Name: "network-instance", Key: map[string]string{"name": "DEFAULT"}}, + {Name: "table-connections"}, + {Name: "table-connection", Key: map[string]string{ + "src-protocol": "STATIC", + "dst-protocol": "ISIS", + "address-family": addressFamily}}, + {Name: "config"}, + }, + }}, + Type: gpb.GetRequest_CONFIG, + Encoding: gpb.Encoding_JSON_IETF, + }) + + if err != nil { + t.Fatalf("failed due to %v", err) + } + t.Log(getResponse) + + t.Log("Verify Get outputs ") + for _, notification := range getResponse.Notification { + for _, update := range notification.Update { + if update.Path != nil { + var config TableConnectionConfig + err = json.Unmarshal(update.Val.GetJsonIetfVal(), &config) + if err != nil { + t.Fatalf("Failed to unmarshal JSON: %v", err) + } + if config.SrcProtocol != "openconfig-policy-types:STATIC" { + t.Fatalf("src-protocol is not set to STATIC as expected") + } + if config.DstProtocol != "openconfig-policy-types:ISIS" { + t.Fatalf("dst-protocol is not set to ISIS as expected") + } + addressFamilyMatchString := fmt.Sprintf("openconfig-types:%s", addressFamily) + if config.AddressFamily != addressFamilyMatchString { + t.Fatalf("address-family is not set to %s as expected", addressFamily) + } + if config.DisableMetricPropagation != DisableMetricValue { + t.Fatalf("disable-metric-propagation is not set to %v as expected", DisableMetricValue) + } + for _, i := range config.ImportPolicy { + if i != RplName { + t.Fatalf("import-policy is not set to %s as expected", RplName) + } + } + t.Logf("Table Connection Details:"+ + "SRC PROTO GOT %v WANT STATIC\n"+ + "DST PRTO GOT %v WANT ISIS\n"+ + "ADDRESS FAMILY GOT %v WANT %v\n"+ + "DISABLEMETRICPROPAGATION GOT %v WANT %v\n", config.SrcProtocol, + config.DstProtocol, config.AddressFamily, addressFamily, + config.DisableMetricPropagation, DisableMetricValue) + } + } + } +} + +func isisImportPolicyConfig(t *testing.T, dut *ondatra.DUTDevice, policyName string, + srcProto oc.E_PolicyTypes_INSTALL_PROTOCOL_TYPE, + dstProto oc.E_PolicyTypes_INSTALL_PROTOCOL_TYPE, + addfmly oc.E_Types_ADDRESS_FAMILY, + metricPropagation bool) { + + t.Log("configure redistribution under isis") + + dni := deviations.DefaultNetworkInstance(dut) + + batchSet := &gnmi.SetBatch{} + d := oc.Root{} + tableConn := d.GetOrCreateNetworkInstance(dni).GetOrCreateTableConnection(srcProto, dstProto, addfmly) + tableConn.SetImportPolicy([]string{policyName}) + if !deviations.SkipSettingDisableMetricPropagation(dut) { + tableConn.SetDisableMetricPropagation(metricPropagation) + } + gnmi.BatchReplace(batchSet, gnmi.OC().NetworkInstance(dni).TableConnection(srcProto, dstProto, addfmly).Config(), tableConn) + + if deviations.SamePolicyAttachedToAllAfis(dut) { + if addfmly == oc.Types_ADDRESS_FAMILY_IPV4 { + addfmly = oc.Types_ADDRESS_FAMILY_IPV6 + } else { + addfmly = oc.Types_ADDRESS_FAMILY_IPV4 + } + tableConn1 := d.GetOrCreateNetworkInstance(dni).GetOrCreateTableConnection(srcProto, dstProto, addfmly) + tableConn1.SetImportPolicy([]string{policyName}) + if !deviations.SkipSettingDisableMetricPropagation(dut) { + tableConn1.SetDisableMetricPropagation(metricPropagation) + } + gnmi.BatchReplace(batchSet, gnmi.OC().NetworkInstance(dni).TableConnection(srcProto, dstProto, addfmly).Config(), tableConn1) + } + + batchSet.Set(t, dut) +} + +func configureRoutePolicy(dut *ondatra.DUTDevice, rplName string, statement string, prefixSetCond, tagSetCond bool, + rplType oc.E_RoutingPolicy_PolicyResultType) (*oc.RoutingPolicy, error) { + + d := &oc.Root{} + rp := d.GetOrCreateRoutingPolicy() + pdef := rp.GetOrCreatePolicyDefinition(rplName) + + if prefixSetCond { + // Condition for prefix set configuration + stmt1, err := pdef.AppendNewStatement(v4Statement) + if err != nil { + return nil, err + } + v4Prefix := v4Route + "/" + strconv.FormatUint(uint64(v4RoutePrefix), 10) + pset := rp.GetOrCreateDefinedSets().GetOrCreatePrefixSet(v4PrefixSet) + pset.GetOrCreatePrefix(v4Prefix, prefixMatch) + pset.SetMode(oc.PrefixSet_Mode_IPV4) + stmt1.GetOrCreateConditions().GetOrCreateMatchPrefixSet().SetPrefixSet(v4PrefixSet) + stmt1.GetOrCreateActions().SetPolicyResult(rplType) + + stmt2, err := pdef.AppendNewStatement(v6Statement) + if err != nil { + return nil, err + } + v6Prefix := v6Route + "/" + strconv.FormatUint(uint64(v6RoutePrefix), 10) + pset = rp.GetOrCreateDefinedSets().GetOrCreatePrefixSet(v6PrefixSet) + pset.GetOrCreatePrefix(v6Prefix, prefixMatch) + pset.SetMode(oc.PrefixSet_Mode_IPV6) + stmt2.GetOrCreateConditions().GetOrCreateMatchPrefixSet().SetPrefixSet(v6PrefixSet) + stmt2.GetOrCreateActions().SetPolicyResult(rplType) + } else if tagSetCond { + // Condition for tag set configuration + stmt1, err := pdef.AppendNewStatement(v4Statement) + if err != nil { + return nil, err + } + v4tagSet := getTagSetName(dut, rplName, v4Statement, "v4") + tagSet1 := rp.GetOrCreateDefinedSets().GetOrCreateTagSet(v4tagSet) + tagSet1.SetTagValue([]oc.RoutingPolicy_DefinedSets_TagSet_TagValue_Union{oc.UnionUint32(tagValue)}) + stmt1.GetOrCreateConditions().GetOrCreateMatchTagSet().SetTagSet(v4tagSet) + stmt1.GetOrCreateActions().SetPolicyResult(rplType) + + stmt2, err := pdef.AppendNewStatement(v6Statement) + if err != nil { + return nil, err + } + v6tagSet := getTagSetName(dut, rplName, v6Statement, "v6") + tagSet2 := rp.GetOrCreateDefinedSets().GetOrCreateTagSet(v6tagSet) + tagSet2.SetTagValue([]oc.RoutingPolicy_DefinedSets_TagSet_TagValue_Union{oc.UnionUint32(tagValue)}) + stmt2.GetOrCreateConditions().GetOrCreateMatchTagSet().SetTagSet(v6tagSet) + stmt2.GetOrCreateActions().SetPolicyResult(rplType) + } else { + // Create a common statement + stmt, err := pdef.AppendNewStatement(statement) + if err != nil { + return nil, err + } + stmt.GetOrCreateActions().SetPolicyResult(rplType) + } + + return rp, nil +} + +func configureStaticRoute(t *testing.T, + dut *ondatra.DUTDevice, + ipv4Route string, + ipv4Mask string, + tagValueV4 uint32, + metricValueV4 uint32, + ipv6Route string, + ipv6Mask string, + tagValueV6 uint32, + metricValueV6 uint32) { + + staticRoute1 := ipv4Route + "/" + ipv4Mask + staticRoute2 := ipv6Route + "/" + ipv6Mask + + ni := oc.NetworkInstance{Name: ygot.String(deviations.DefaultNetworkInstance(dut))} + static := ni.GetOrCreateProtocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_STATIC, deviations.StaticProtocolName(dut)) + sr := static.GetOrCreateStatic(staticRoute1) + sr.SetTag, _ = sr.To_NetworkInstance_Protocol_Static_SetTag_Union(tagValueV4) + nh := sr.GetOrCreateNextHop("0") + nh.NextHop = oc.UnionString(isissession.ATEISISAttrs.IPv4) + nh.Metric = ygot.Uint32(metricValueV4) + + sr2 := static.GetOrCreateStatic(staticRoute2) + sr2.SetTag, _ = sr.To_NetworkInstance_Protocol_Static_SetTag_Union(tagValueV6) + nh2 := sr2.GetOrCreateNextHop("0") + nh2.NextHop = oc.UnionString(isissession.ATEISISAttrs.IPv6) + nh2.Metric = ygot.Uint32(metricValueV6) + + gnmi.Update(t, dut, gnmi.OC().NetworkInstance(deviations.DefaultNetworkInstance(dut)).Protocol( + oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_STATIC, + deviations.StaticProtocolName(dut)).Config(), + static) +} + +func configureOTGFlows(t *testing.T, top gosnappi.Config, ts *isissession.TestSession) { + t.Helper() + + srcV4 := ts.ATEIntf2.Ethernets().Items()[0].Ipv4Addresses().Items()[0] + srcV6 := ts.ATEIntf2.Ethernets().Items()[0].Ipv6Addresses().Items()[0] + + dst1V4 := ts.ATEIntf1.Ethernets().Items()[0].Ipv4Addresses().Items()[0] + dst1V6 := ts.ATEIntf1.Ethernets().Items()[0].Ipv6Addresses().Items()[0] + + v4F := top.Flows().Add() + v4F.SetName(v4Flow).Metrics().SetEnable(true) + v4F.TxRx().Device().SetTxNames([]string{srcV4.Name()}).SetRxNames([]string{dst1V4.Name()}) + + v4FEth := v4F.Packet().Add().Ethernet() + v4FEth.Src().SetValue(isissession.ATETrafficAttrs.MAC) + + v4FIp := v4F.Packet().Add().Ipv4() + v4FIp.Src().SetValue(srcV4.Address()) + v4FIp.Dst().Increment().SetStart(v4TrafficStart).SetCount(254) + + eth := v4F.EgressPacket().Add().Ethernet() + ethTag := eth.Dst().MetricTags().Add() + ethTag.SetName("MACTrackingv4").SetOffset(36).SetLength(12) + + v6F := top.Flows().Add() + v6F.SetName(v6Flow).Metrics().SetEnable(true) + v6F.TxRx().Device().SetTxNames([]string{srcV6.Name()}).SetRxNames([]string{dst1V6.Name()}) + + v6FEth := v6F.Packet().Add().Ethernet() + v6FEth.Src().SetValue(isissession.ATETrafficAttrs.MAC) + + v6FIP := v6F.Packet().Add().Ipv6() + v6FIP.Src().SetValue(srcV6.Address()) + v6FIP.Dst().Increment().SetStart(v6TrafficStart).SetCount(1) + + eth = v6F.EgressPacket().Add().Ethernet() + ethTag = eth.Dst().MetricTags().Add() + ethTag.SetName("MACTrackingv6").SetOffset(36).SetLength(12) +} + +func advertiseRoutesWithISIS(t *testing.T, ts *isissession.TestSession) { + t.Helper() + + // configure emulated network params + net2v4 := ts.ATEIntf1.Isis().V4Routes().Add().SetName("v4-isisNet-dev1").SetLinkMetric(10) + net2v4.Addresses().Add().SetAddress(advertisedIPv4.address).SetPrefix(advertisedIPv4.prefix) + net2v6 := ts.ATEIntf1.Isis().V6Routes().Add().SetName("v6-isisNet-dev1").SetLinkMetric(10) + net2v6.Addresses().Add().SetAddress(advertisedIPv6.address).SetPrefix(advertisedIPv6.prefix) +} + +func verifyRplConfig(t *testing.T, dut *ondatra.DUTDevice, tagSetName string, tagValue oc.UnionUint32) { + tagSetState := gnmi.Get(t, dut, gnmi.OC().RoutingPolicy().DefinedSets().TagSet(tagSetName).TagValue().State()) + tagNameState := gnmi.Get(t, dut, gnmi.OC().RoutingPolicy().DefinedSets().TagSet(tagSetName).Name().State()) + + setTagValue := []oc.RoutingPolicy_DefinedSets_TagSet_TagValue_Union{tagValue} + + for _, value := range tagSetState { + configuredTagValue := []oc.RoutingPolicy_DefinedSets_TagSet_TagValue_Union{value} + if setTagValue[0] == configuredTagValue[0] { + t.Logf("Passed: setTagValue is %v and configuredTagValue is %v", setTagValue[0], configuredTagValue[0]) + } else { + t.Errorf("Failed: setTagValue is %v and configuredTagValue is %v", setTagValue[0], configuredTagValue[0]) + } + } + t.Logf("verify tag name matches expected") + if tagNameState != tagSetName { + t.Errorf("Failed to get tag-set name got %s wanted %s", tagNameState, tagSetName) + } else { + t.Logf("Passed Found tag-set name got %s wanted %s", tagNameState, tagSetName) + } +} + +func getTagSetName(dut *ondatra.DUTDevice, policyName, stmtName, afStr string) string { + if deviations.RoutingPolicyTagSetEmbedded(dut) { + return fmt.Sprintf("%s %s", policyName, stmtName) + } + return fmt.Sprintf("tag-set-%s", afStr) +} + +func TestStaticToISISRedistribution(t *testing.T) { + var ts *isissession.TestSession + + t.Run("Initial Setup", func(t *testing.T) { + t.Run("Configure ISIS on DUT", func(t *testing.T) { + ts = isissession.MustNew(t).WithISIS() + if err := ts.PushDUT(context.Background(), t); err != nil { + t.Fatalf("Unable to push initial DUT config: %v", err) + } + }) + + t.Run("Configure Static Route on DUT", func(t *testing.T) { + ipv4Mask := strconv.FormatUint(uint64(v4RoutePrefix), 10) + ipv6Mask := strconv.FormatUint(uint64(v6RoutePrefix), 10) + configureStaticRoute(t, ts.DUT, v4Route, ipv4Mask, 40, 104, v6Route, ipv6Mask, 60, 106) + }) + + t.Run("OTG Configuration", func(t *testing.T) { + configureOTGFlows(t, ts.ATETop, ts) + advertiseRoutesWithISIS(t, ts) + ts.PushAndStart(t) + ts.MustAdjacency(t) + + otgutils.WaitForARP(t, ts.ATE.OTG(), ts.ATETop, "IPv4") + otgutils.WaitForARP(t, ts.ATE.OTG(), ts.ATETop, "IPv6") + }) + }) + + cases := []struct { + desc string + policyStmtType oc.E_RoutingPolicy_PolicyResultType + metricPropogation bool + protoAf oc.E_Types_ADDRESS_FAMILY + RplName string + RplStatement string + verifyTrafficStats bool + trafficFlows []string + TagSetCondition bool + PrefixSetCondition bool + }{{ + desc: "RT-2.12.1: Redistribute IPv4 static route to IS-IS with metric propagation disabled", + metricPropogation: false, + protoAf: oc.Types_ADDRESS_FAMILY_IPV4, + RplName: "DEFAULT-POLICY-PASS-ALL-V4", + RplStatement: "PASS-ALL", + policyStmtType: oc.RoutingPolicy_PolicyResultType_ACCEPT_ROUTE, + }, { + desc: "RT-2.12.2: Redistribute IPv6 static route to IS-IS with metric propagation disabled", + metricPropogation: false, + protoAf: oc.Types_ADDRESS_FAMILY_IPV6, + RplName: "DEFAULT-POLICY-PASS-ALL-V6", + RplStatement: "PASS-ALL", + policyStmtType: oc.RoutingPolicy_PolicyResultType_ACCEPT_ROUTE, + }, { + desc: "RT-2.12.3: Redistribute IPv4 static route to IS-IS with metric propagation enabled", + metricPropogation: true, + protoAf: oc.Types_ADDRESS_FAMILY_IPV4, + RplName: "DEFAULT-POLICY-PASS-ALL-V4", + RplStatement: "PASS-ALL", + policyStmtType: oc.RoutingPolicy_PolicyResultType_ACCEPT_ROUTE, + }, { + desc: "RT-2.12.4: Redistribute IPv6 static route to IS-IS with metric propogation enabled", + metricPropogation: true, + protoAf: oc.Types_ADDRESS_FAMILY_IPV6, + RplName: "DEFAULT-POLICY-PASS-ALL-V6", + RplStatement: "PASS-ALL", + policyStmtType: oc.RoutingPolicy_PolicyResultType_ACCEPT_ROUTE, + }, { + desc: "RT-2.12.5: Redistribute IPv4 and IPv6 static route to IS-IS with default-import-policy set to reject", + metricPropogation: false, + protoAf: oc.Types_ADDRESS_FAMILY_IPV4, + RplName: "DEFAULT-POLICY-PASS-ALL-V4", + RplStatement: "PASS-ALL", + policyStmtType: oc.RoutingPolicy_PolicyResultType_REJECT_ROUTE, + }, { + desc: "RT-2.12.6: Redistribute IPv4 static route to IS-IS matching a prefix using a route-policy", + protoAf: oc.Types_ADDRESS_FAMILY_IPV4, + RplName: v4RoutePolicy, + metricPropogation: true, + policyStmtType: oc.RoutingPolicy_PolicyResultType_ACCEPT_ROUTE, + verifyTrafficStats: true, + trafficFlows: []string{v4Flow}, + PrefixSetCondition: true, + }, { + desc: "RT-2.12.7: Redistribute IPv4 static route to IS-IS matching a tag", + protoAf: oc.Types_ADDRESS_FAMILY_IPV4, + RplName: v4RoutePolicy, + metricPropogation: true, + policyStmtType: oc.RoutingPolicy_PolicyResultType_ACCEPT_ROUTE, + verifyTrafficStats: true, + trafficFlows: []string{v4Flow}, + TagSetCondition: true, + }, { + desc: "RT-2.12.8: Redistribute IPv6 static route to IS-IS matching a prefix using a route-policy", + protoAf: oc.Types_ADDRESS_FAMILY_IPV6, + RplName: v6RoutePolicy, + policyStmtType: oc.RoutingPolicy_PolicyResultType_ACCEPT_ROUTE, + verifyTrafficStats: true, + trafficFlows: []string{v6Flow}, + PrefixSetCondition: true, + }, { + desc: "RT-2.12.9: Redistribute IPv6 static route to IS-IS matching a prefix using a tag", + protoAf: oc.Types_ADDRESS_FAMILY_IPV4, + RplName: v6RoutePolicy, + metricPropogation: true, + policyStmtType: oc.RoutingPolicy_PolicyResultType_ACCEPT_ROUTE, + verifyTrafficStats: true, + trafficFlows: []string{v4Flow}, + TagSetCondition: true, + }} + + for _, tc := range cases { + dni := deviations.DefaultNetworkInstance(ts.DUT) + + t.Run(tc.desc, func(t *testing.T) { + t.Run(fmt.Sprintf("Configure Policy Type %s", tc.policyStmtType.String()), func(t *testing.T) { + rpl, err := configureRoutePolicy(ts.DUT, tc.RplName, tc.RplStatement, tc.PrefixSetCondition, + tc.TagSetCondition, tc.policyStmtType) + if err != nil { + fmt.Println("Error configuring route policy:", err) + return + } + gnmi.Update(t, ts.DUT, gnmi.OC().RoutingPolicy().Config(), rpl) + }) + + if tc.TagSetCondition { + t.Run("Verify Configuration for RPL TagSet", func(t *testing.T) { + verifyRplConfig(t, ts.DUT, getTagSetName(ts.DUT, tc.RplName, v4Statement, "v4"), oc.UnionUint32(tagValue)) + verifyRplConfig(t, ts.DUT, getTagSetName(ts.DUT, tc.RplName, v6Statement, "v6"), oc.UnionUint32(tagValue)) + }) + } + + t.Run(fmt.Sprintf("Attach RPL %v Type %v to ISIS %v", tc.RplName, tc.policyStmtType.String(), dni), func(t *testing.T) { + isisImportPolicyConfig(t, ts.DUT, tc.RplName, protoSrc, protoDst, tc.protoAf, tc.metricPropogation) + }) + + t.Run(fmt.Sprintf("Verify RPL %v Attributes", tc.RplName), func(t *testing.T) { + getAndVerifyIsisImportPolicy(t, ts.DUT, tc.metricPropogation, tc.RplName, tc.protoAf.String()) + }) + + if tc.verifyTrafficStats { + t.Run(fmt.Sprintf("Verify traffic for %s", tc.trafficFlows), func(t *testing.T) { + + ts.ATE.OTG().StartTraffic(t) + time.Sleep(trafficDuration) + ts.ATE.OTG().StopTraffic(t) + + for _, flow := range tc.trafficFlows { + loss := otgutils.GetFlowLossPct(t, ts.ATE.OTG(), flow, 20*time.Second) + if loss > lossTolerance { + t.Errorf("Traffic loss too high for flow %s", flow) + } else { + t.Logf("Traffic loss for flow %s is %v", flow, loss) + } + } + }) + } + + t.Run("Verify Route on OTG", func(t *testing.T) { + configuredMetric := uint32(10) + _, ok := gnmi.WatchAll(t, ts.ATE.OTG(), gnmi.OTG().IsisRouter("devIsis").LinkStateDatabase().LspsAny().Tlvs().ExtendedIpv4Reachability().PrefixAny().Metric().State(), time.Minute, func(v *ygnmi.Value[uint32]) bool { + metric, present := v.Val() + if present { + if metric == configuredMetric { + return true + } + } + return false + }).Await(t) + + metricInReceivedLsp := gnmi.GetAll(t, ts.ATE.OTG(), gnmi.OTG().IsisRouter("devIsis").LinkStateDatabase().LspsAny().Tlvs().ExtendedIpv4Reachability().PrefixAny().Metric().State())[0] + if !ok { + t.Fatalf("Metric not matched. Expected %d got %d ", configuredMetric, metricInReceivedLsp) + } + }) + }) + } +} diff --git a/feature/isis/otg_tests/weighted_ecmp_test/weighted_ecmp_test.go b/feature/isis/otg_tests/weighted_ecmp_test/weighted_ecmp_test.go index ad05d96cad3..0b6f7fa2942 100644 --- a/feature/isis/otg_tests/weighted_ecmp_test/weighted_ecmp_test.go +++ b/feature/isis/otg_tests/weighted_ecmp_test/weighted_ecmp_test.go @@ -441,7 +441,7 @@ func configureDUT(t *testing.T, dut *ondatra.DUTDevice) []string { if deviations.InterfaceEnabled(dut) { i.Enabled = ygot.Bool(true) } - if port.PMD() == ondatra.PMD100GBASEFR { + if port.PMD() == ondatra.PMD100GBASEFR && deviations.ExplicitPortSpeed(dut) { e.AutoNegotiate = ygot.Bool(false) e.DuplexMode = oc.Ethernet_DuplexMode_FULL e.PortSpeed = oc.IfEthernet_ETHERNET_SPEED_SPEED_100GB @@ -453,7 +453,7 @@ func configureDUT(t *testing.T, dut *ondatra.DUTDevice) []string { } // Wait for LAG interfaces to be UP for _, aggID := range aggIDs { - gnmi.Await(t, dut, gnmi.OC().Interface(aggID).AdminStatus().State(), 30*time.Second, oc.Interface_AdminStatus_UP) + gnmi.Await(t, dut, gnmi.OC().Interface(aggID).AdminStatus().State(), 60*time.Second, oc.Interface_AdminStatus_UP) } configureStaticRouteToATELoopbacks(t, dut) configureRoutingPolicy(t, dut) diff --git a/feature/platform/controllercard/tests/port/README.md b/feature/platform/controllercard/tests/port/README.md new file mode 100644 index 00000000000..f66189a90dd --- /dev/null +++ b/feature/platform/controllercard/tests/port/README.md @@ -0,0 +1,64 @@ +# gNMI-1.22: Controller card port attributes + +## Summary + +Validate PORT components attached to a CONTROLLER_CARD are modeled with the +expected OC paths. The operational use case is: + +1. As an automated network repair tool, I want to ensure at least one + interface between redundant CONTROLLER_CARD components is fully + operational. Before performing a power off or reboot of a CONTROLLER_CARD + or a network device wired to a CONTROLLER_CARD PORT, I want to use the OC + component tree to trace the subject PORT to it's associated redundant PORT. + +## Testbed type + +* [Single DUT](https://github.com/openconfig/featureprofiles/blob/main/topologies/dut.testbed) + +## Testbed prerequisites + +There are no DUT configuration pre-requisites for this test. The DUT must +contain the following component types: + 2 `CONTROLLER_CARD` components + Each CONTROLLER_CARD contains at least one `PORT` + +## Procedure + +* gNMI-1.22: Validate component PORT attributes attached to a CONTROLLER_CARD + * gNMI Subscribe to the /components and /interfaces tree using ONCE option. + * Verify each PORT present on a CONTROLLER_CARD has the following paths set: + * Search the components to to find components of type PORT with parent = CONTROLLER_CARD + * /components/component/state/parent = the appropriate component of type CONTROLLER_CARD + * Search the /interfaces/interface/state/hardware-port values to find the expected /components/component/name for the physical port on the CONTROLLER_CARD + * For each of these interfaces, verify /interfaces/interface/state/cpu = TRUE + +## OpenConfig Path and RPC Coverage + +The below yaml defines the OC paths and RPC intended to be covered by this test. + +```yaml +paths: + ## State Paths ## + /components/component/state/name: + platform_type: [ + "CONTROLLER_CARD", + "PORT" + ] + /components/component/state/type: + platform_type: [ + "CONTROLLER_CARD", + "PORT" + ] + /interfaces/interface/state/name: + /interfaces/interface/state/cpu: + /interfaces/interface/state/hardware-port: + +rpcs: + gnmi: + gNMI.Subscribe: + ONCE: true +``` + +## Minimum DUT platform requirement + +MFF - Modular form factor is specified to ensure coverage for redundant `CONTROLLER_CARD` platform_types. diff --git a/feature/platform/controllercard/tests/port/metadata.textproto b/feature/platform/controllercard/tests/port/metadata.textproto new file mode 100644 index 00000000000..74408b28d30 --- /dev/null +++ b/feature/platform/controllercard/tests/port/metadata.textproto @@ -0,0 +1,12 @@ +# proto-file: github.com/openconfig/featureprofiles/proto/metadata.proto +# proto-message: Metadata + +plan_id: "gNMI-1.22" +description: "Controller card port attributes" +uuid: "89333073-196f-4de3-9cd4-5c6f11f64905" + +testbed: TESTBED_DUT + +tags: TAGS_AGGREGATION +tags: TAGS_TRANSIT +tags: TAGS_DATACENTER_EDGE diff --git a/feature/platform/fabric/otg_tests/sampled_backplane_capacity_counters_test/README.md b/feature/platform/fabric/otg_tests/sampled_backplane_capacity_counters_test/README.md index 6887a4d4d79..0f026d1ced4 100644 --- a/feature/platform/fabric/otg_tests/sampled_backplane_capacity_counters_test/README.md +++ b/feature/platform/fabric/otg_tests/sampled_backplane_capacity_counters_test/README.md @@ -34,7 +34,7 @@ This test if to verify that DUT supports gNMI Subscribe with ON_CHANGE for backp * Validate that we recieve a changed consumed-capacity metric matching the initial value -### gNMI-1.18.2 [TODO: https://github.com/openconfig/featureprofiles/issues/2323] +### gNMI-1.18.2 * Use gNMI subscribe with "ON_CHANGE" mode for the below telemetry paths @@ -70,26 +70,34 @@ This test if to verify that DUT supports gNMI Subscribe with ON_CHANGE for backp * /components/component/integrated-circuit/backplane-facing-capacity/state/total -## Config parameter coverage - -* /interfaces/interface/config/enabled -* /interfaces/interface/subinterfaces/subinterface/ipv4/config/enabled -* /interfaces/interface/subinterfaces/subinterface/ipv6/config/enabled -* /components/component/{fabric}/config/power-admin-state - -## Telemetry parameter coverage - -* /components/component/integrated-circuit/backplane-facing-capacity/state/available-pct -* /components/component/integrated-circuit/backplane-facing-capacity/state/consumed-capacity -* /components/component/integrated-circuit/backplane-facing-capacity/state/total -* /components/component/integrated-circuit/backplane-facing-capacity/state/total-operational-capacity - -## Protocol/RPC Parameter Coverage - -* gNMI - * Set - * Update - * Subscribe +## OpenConfig Path and RPC Coverage + +This example yaml defines the OC paths intended to be covered by this test. OC paths used for test environment setup are not required to be listed here. +```yaml +paths: + ## Config parameter coverage + /interfaces/interface/config/enabled: + /interfaces/interface/subinterfaces/subinterface/ipv4/config/enabled: + /interfaces/interface/subinterfaces/subinterface/ipv6/config/enabled: + /components/component/fabric/config/power-admin-state: + platform_type: ["FABRIC"] + + ## Telemetry parameter coverage + /components/component/integrated-circuit/backplane-facing-capacity/state/available-pct: + platform_type: ["INTEGRATED_CIRCUIT"] + /components/component/integrated-circuit/backplane-facing-capacity/state/consumed-capacity: + platform_type: [ "INTEGRATED_CIRCUIT" ] + /components/component/integrated-circuit/backplane-facing-capacity/state/total: + platform_type: [ "INTEGRATED_CIRCUIT" ] + /components/component/integrated-circuit/backplane-facing-capacity/state/total-operational-capacity: + platform_type: [ "INTEGRATED_CIRCUIT" ] + +rpcs: + gnmi: + gNMI.Set: + gNMI.Subscribe: + Mode: [ "ON_CHANGE", "SAMPLE" ] +``` ## Required DUT platform diff --git a/feature/platform/fabric/otg_tests/sampled_backplane_capacity_counters_test/metadata.textproto b/feature/platform/fabric/otg_tests/sampled_backplane_capacity_counters_test/metadata.textproto index 7c618627449..f62de8c426e 100644 --- a/feature/platform/fabric/otg_tests/sampled_backplane_capacity_counters_test/metadata.textproto +++ b/feature/platform/fabric/otg_tests/sampled_backplane_capacity_counters_test/metadata.textproto @@ -32,7 +32,6 @@ platform_exceptions: { explicit_interface_in_default_vrf: true qos_queue_requires_id: true missing_value_for_defaults: true - backplane_facing_capacity_unsupported: true } } platform_exceptions: { diff --git a/feature/platform/healthz/tests/status/README.md b/feature/platform/healthz/tests/status/README.md new file mode 100644 index 00000000000..961564d350c --- /dev/null +++ b/feature/platform/healthz/tests/status/README.md @@ -0,0 +1,103 @@ +# Health-1.2: Healthz component status paths + +## Summary + +Validate healthz status paths exist for select OC component types. There +are two operational use cases for this test. + +1. As a network operator, I want to know if a device is healthy. If the + device is unhealthy, I may choose to execute a mitigation or repair action. + The choice of action is influenced by which component(s) are not healthy. +2. As a SDN controller, I want to know if a device is ready to be programmed + for traffic forwarding. + +## Testbed type + +* [Single DUT](https://github.com/openconfig/featureprofiles/blob/main/topologies/dut.testbed) + +## Testbed prerequisites + +There are no DUT configuration pre-requisites for this test. The DUT must +contain the following component types: + "CONTROLLER_CARD", + "LINECARD", + "FABRIC", + "POWER_SUPPLY", + "INTEGRATED_CIRCUIT" + +The DUT should have a HEALTHY state for all the above components. + +## Procedure + +* Healthz-1.2.1: Validate healthz status + * gNMI Subscribe to the /components tree using ON_CHANGE option. + * Validate `/components/component/healthz/state/status` returns `HEALTHY` + for each of the following component types: + "CONTROLLER_CARD", + "LINECARD", + "FABRIC", + "POWER_SUPPLY", + "INTEGRATED_CIRCUIT" + * Validate the following paths return a valid value: + * /components/component/healthz/state/last-unhealthy + * /components/component/healthz/state/unhealthy-count + +* Healthz-1.2.3: Reboot DUT and validate status converges to healthy + * Use gnoi.System.Reboot to reboot the DUT + * Repeatedly attempt to open a gNMI subscribe request to the DUT + * Upon success, subscribe to the /components tree using ON_CHANGE option. + * Validate `/components/component/healthz/state/status` exists for each of + the following component types: + "CONTROLLER_CARD", + "LINECARD", + "FABRIC", + "POWER_SUPPLY", + "INTEGRATED_CIRCUIT" + * Validate status transitions to `HEALTHY` within a timeout of 15 minutes + from the reboot start time. + +## OpenConfig Path and RPC Coverage + +The below yaml defines the OC paths and RPC intended to be covered by this test. + +```yaml +paths: + ## State Paths ## + /components/component/healthz/state/status: + platform_type: [ + "CONTROLLER_CARD", + "LINECARD", + "FABRIC", + "POWER_SUPPLY", + "INTEGRATED_CIRCUIT" + ] + /components/component/healthz/state/last-unhealthy: + platform_type: [ + "CONTROLLER_CARD", + "LINECARD", + "FABRIC", + "POWER_SUPPLY", + "INTEGRATED_CIRCUIT" + ] + /components/component/healthz/state/unhealthy-count: + platform_type: [ + "CONTROLLER_CARD", + "LINECARD", + "FABRIC", + "POWER_SUPPLY", + "INTEGRATED_CIRCUIT" + ] + +rpcs: + gnmi: + gNMI.Subscribe: + ON_CHANGE: true + + gnoi: + system.System.Reboot: + +``` + +## Minimum DUT platform requirement + +MFF - Modular form factor is specified to ensure coverage for `CONTROLLER_CARD` and `FABRIC` platform_types. diff --git a/feature/platform/healthz/tests/status/metadata.textproto b/feature/platform/healthz/tests/status/metadata.textproto new file mode 100644 index 00000000000..76248c3fb88 --- /dev/null +++ b/feature/platform/healthz/tests/status/metadata.textproto @@ -0,0 +1,12 @@ +# proto-file: github.com/openconfig/featureprofiles/proto/metadata.proto +# proto-message: Metadata + +plan_id: "Health-1.2" +description: "Healthz component status paths" +uuid: "6935156f-d42f-4bb0-9926-79235859c029" + +testbed: TESTBED_DUT + +tags: TAGS_AGGREGATION +tags: TAGS_TRANSIT +tags: TAGS_DATACENTER_EDGE diff --git a/feature/platform/transceiver/tests/zr_cd_test/README.md b/feature/platform/transceiver/tests/zr_cd_test/README.md index 1a9f6e127ab..2c56e6d87d7 100644 --- a/feature/platform/transceiver/tests/zr_cd_test/README.md +++ b/feature/platform/transceiver/tests/zr_cd_test/README.md @@ -75,4 +75,13 @@ to fiber measured in ps/nm * /platform/components/component/optical-channel/state/chromatic-dispersion/instant * /platform/components/component/optical-channel/state/chromatic-dispersion/avg * /platform/components/component/optical-channel/state/chromatic-dispersion/min -* /platform/components/component/optical-channel/state/chromatic-dispersion/max \ No newline at end of file +* /platform/components/component/optical-channel/state/chromatic-dispersion/max + +## OpenConfig Path and RPC Coverage +```yaml +rpcs: + gnmi: + gNMI.Get: + gNMI.Set: + gNMI.Subscribe: +``` diff --git a/feature/platform/transceiver/tests/zr_cd_test/zr_cd_test.go b/feature/platform/transceiver/tests/zr_cd_test/zr_cd_test.go index 235db2506f2..08bf2f7e209 100644 --- a/feature/platform/transceiver/tests/zr_cd_test/zr_cd_test.go +++ b/feature/platform/transceiver/tests/zr_cd_test/zr_cd_test.go @@ -1,11 +1,10 @@ package zr_cd_test import ( - "fmt" "testing" "time" - "github.com/openconfig/featureprofiles/internal/deviations" + "github.com/openconfig/featureprofiles/internal/components" "github.com/openconfig/featureprofiles/internal/fptest" "github.com/openconfig/featureprofiles/internal/samplestream" "github.com/openconfig/ondatra" @@ -46,7 +45,7 @@ func interfaceConfig(t *testing.T, dut1 *ondatra.DUTDevice, dp *ondatra.Port, fr i.Enabled = ygot.Bool(true) i.Type = oc.IETFInterfaces_InterfaceType_ethernetCsmacd gnmi.Replace(t, dut1, gnmi.OC().Interface(dp.Name()).Config(), i) - OCcomponent := opticalChannelComponentFromPort(t, dut1, dp) + OCcomponent := components.OpticalChannelComponentFromPort(t, dut1, dp) gnmi.Replace(t, dut1, gnmi.OC().Component(OCcomponent).OpticalChannel().Config(), &oc.Component_OpticalChannel{ TargetOutputPower: ygot.Float64(targetOutputPower), Frequency: ygot.Uint64(frequency), @@ -151,30 +150,3 @@ func TestCDValue(t *testing.T) { } } } - -func opticalChannelComponentFromPort(t *testing.T, dut *ondatra.DUTDevice, p *ondatra.Port) string { - t.Helper() - if deviations.MissingPortToOpticalChannelMapping(dut) { - switch dut.Vendor() { - case ondatra.ARISTA: - transceiverName := gnmi.Get(t, dut, gnmi.OC().Interface(p.Name()).Transceiver().State()) - return fmt.Sprintf("%s-Optical0", transceiverName) - default: - t.Fatal("Manual Optical channel name required when deviation missing_port_to_optical_channel_component_mapping applied.") - } - } - compName := gnmi.Get(t, dut, gnmi.OC().Interface(p.Name()).HardwarePort().State()) - for { - comp, ok := gnmi.Lookup(t, dut, gnmi.OC().Component(compName).State()).Val() - if !ok { - t.Fatalf("Recursive optical channel lookup failed for port: %s, component %s not found.", p.Name(), compName) - } - if comp.GetType() == oc.PlatformTypes_OPENCONFIG_HARDWARE_COMPONENT_OPTICAL_CHANNEL { - return compName - } - if comp.GetParent() == "" { - t.Fatalf("Recursive optical channel lookup failed for port: %s, parent of component %s not found.", p.Name(), compName) - } - compName = comp.GetParent() - } -} diff --git a/feature/platform/transceiver/tests/zr_fec_uncorrectable_frames_test/README.md b/feature/platform/transceiver/tests/zr_fec_uncorrectable_frames_test/README.md index 751768fde32..49966402fd2 100644 --- a/feature/platform/transceiver/tests/zr_fec_uncorrectable_frames_test/README.md +++ b/feature/platform/transceiver/tests/zr_fec_uncorrectable_frames_test/README.md @@ -29,11 +29,20 @@ This is a post-FEC decoder error metric. verify relevant FEC uncorrectable frame count is streamed. If there are no errors a value of 0 should be streamed for no FEC uncorrectable frames. -## Config Parameter coverage - -* /components/component/transceiver/config/enabled -* /interfaces/interface/config/enabled - -## Telemetry Parameter coverage - -* /terminal-device/logical-channels/channel/otn/state/fec-uncorrectable-blocks +## OpenConfig Path and RPC Coverage + +```yaml +paths: + # Config Parameter coverage + /interfaces/interface/config/enabled: + /components/component/transceiver/config/enabled: + platform_type: ["OPTICAL_CHANNEL"] + # Telemetry Parameter coverage + /terminal-device/logical-channels/channel/otn/state/fec-uncorrectable-blocks: + +rpcs: + gnmi: + gNMI.Get: + gNMI.Set: + gNMI.Subscribe: +``` \ No newline at end of file diff --git a/feature/platform/transceiver/tests/zr_fec_uncorrectable_frames_test/metadata.textproto b/feature/platform/transceiver/tests/zr_fec_uncorrectable_frames_test/metadata.textproto index 5c9c9aea535..501d2cce28f 100644 --- a/feature/platform/transceiver/tests/zr_fec_uncorrectable_frames_test/metadata.textproto +++ b/feature/platform/transceiver/tests/zr_fec_uncorrectable_frames_test/metadata.textproto @@ -5,3 +5,13 @@ uuid: "6f9059c8-e49c-4ff6-8bd2-f474cd4fcfce" plan_id: "TRANSCEIVER-10" description: "Telemetry: 400ZR Optics FEC(Forward Error Correction) Uncorrectable Frames Streaming." testbed: TESTBED_DUT_400ZR +platform_exceptions: { + platform: { + vendor: ARISTA + } + deviations: { + interface_enabled: true + default_network_instance: "default" + missing_port_to_optical_channel_component_mapping: true + } +} diff --git a/feature/platform/transceiver/tests/zr_fec_uncorrectable_frames_test/zr_fec_uncorrectable_frames_test.go b/feature/platform/transceiver/tests/zr_fec_uncorrectable_frames_test/zr_fec_uncorrectable_frames_test.go index 2779d56a4d6..590fa814e86 100644 --- a/feature/platform/transceiver/tests/zr_fec_uncorrectable_frames_test/zr_fec_uncorrectable_frames_test.go +++ b/feature/platform/transceiver/tests/zr_fec_uncorrectable_frames_test/zr_fec_uncorrectable_frames_test.go @@ -20,18 +20,18 @@ import ( "testing" "time" + "github.com/openconfig/featureprofiles/internal/cfgplugins" "github.com/openconfig/featureprofiles/internal/fptest" "github.com/openconfig/featureprofiles/internal/samplestream" "github.com/openconfig/ondatra" "github.com/openconfig/ondatra/gnmi" "github.com/openconfig/ondatra/gnmi/oc" + "github.com/openconfig/ygot/ygot" ) const ( - sampleInterval = 10 * time.Second - targetOutputPowerdBm = -10 - targetFrequencyHz = 193100000 - intUpdateTime = 2 * time.Minute + sampleInterval = 10 * time.Second + intUpdateTime = 2 * time.Minute ) func TestMain(m *testing.M) { @@ -57,33 +57,34 @@ func validateFecUncorrectableBlocks(t *testing.T, stream *samplestream.SampleStr func TestZrUncorrectableFrames(t *testing.T) { dut := ondatra.DUT(t, "dut") + cfgplugins.InterfaceConfig(t, dut, dut.Port(t, "port1")) + cfgplugins.InterfaceConfig(t, dut, dut.Port(t, "port2")) for _, port := range []string{"port1", "port2"} { t.Run(fmt.Sprintf("Port:%s", port), func(t *testing.T) { dp := dut.Port(t, "port1") gnmi.Await(t, dut, gnmi.OC().Interface(dp.Name()).OperStatus().State(), intUpdateTime, oc.Interface_OperStatus_UP) - // Derive transceiver names from ports. - tr := gnmi.Get(t, dut, gnmi.OC().Interface(dp.Name()).Transceiver().State()) - component := gnmi.OC().Component(tr) - - outputPower := gnmi.Get(t, dut, component.OpticalChannel().TargetOutputPower().State()) - if outputPower != targetOutputPowerdBm { - t.Fatalf("Output power does not match target output power, got: %v want :%v", outputPower, targetOutputPowerdBm) - } - - frequency := gnmi.Get(t, dut, component.OpticalChannel().Frequency().State()) - if frequency != targetFrequencyHz { - t.Fatalf("Frequency does not match target frequency, got: %v want :%v", frequency, targetFrequencyHz) - } - streamFec := samplestream.New(t, dut, gnmi.OC().TerminalDevice().Channel(0).Otn().FecUncorrectableBlocks().State(), sampleInterval) defer streamFec.Close() validateFecUncorrectableBlocks(t, streamFec) // Toggle interface enabled - gnmi.Update(t, dut, gnmi.OC().Interface(dp.Name()).Enabled().Config(), bool(false)) - gnmi.Update(t, dut, gnmi.OC().Interface(dp.Name()).Enabled().Config(), bool(true)) + d := &oc.Root{} + i := d.GetOrCreateInterface(dp.Name()) + i.Type = oc.IETFInterfaces_InterfaceType_ethernetCsmacd + + // Disable interface + i.Enabled = ygot.Bool(false) + gnmi.Replace(t, dut, gnmi.OC().Interface(dp.Name()).Config(), i) + // Wait for the cooling off period + gnmi.Await(t, dut, gnmi.OC().Interface(dp.Name()).OperStatus().State(), intUpdateTime, oc.Interface_OperStatus_DOWN) + + // Enable interface + i.Enabled = ygot.Bool(true) + gnmi.Replace(t, dut, gnmi.OC().Interface(dp.Name()).Config(), i) + // Wait for the cooling off period + gnmi.Await(t, dut, gnmi.OC().Interface(dp.Name()).OperStatus().State(), intUpdateTime, oc.Interface_OperStatus_UP) validateFecUncorrectableBlocks(t, streamFec) }) diff --git a/feature/platform/transceiver/tests/zr_firmware_version_test/README.md b/feature/platform/transceiver/tests/zr_firmware_version_test/README.md index 3f0a074f0ec..283a3a83c14 100644 --- a/feature/platform/transceiver/tests/zr_firmware_version_test/README.md +++ b/feature/platform/transceiver/tests/zr_firmware_version_test/README.md @@ -28,3 +28,12 @@ Validate 400ZR optics module reports correct firmware version. ## Telemetry Parameter coverage * /platform/components/component/state/firmware-version + +## OpenConfig Path and RPC Coverage +```yaml +rpcs: + gnmi: + gNMI.Get: + gNMI.Set: + gNMI.Subscribe: +``` diff --git a/feature/platform/transceiver/tests/zr_firmware_version_test/zr_firmware_version_test.go b/feature/platform/transceiver/tests/zr_firmware_version_test/zr_firmware_version_test.go index d89ac708fe8..ce879e31d9c 100644 --- a/feature/platform/transceiver/tests/zr_firmware_version_test/zr_firmware_version_test.go +++ b/feature/platform/transceiver/tests/zr_firmware_version_test/zr_firmware_version_test.go @@ -15,12 +15,11 @@ package zr_firmware_version_test import ( - "fmt" "reflect" "testing" "time" - "github.com/openconfig/featureprofiles/internal/deviations" + "github.com/openconfig/featureprofiles/internal/components" "github.com/openconfig/featureprofiles/internal/fptest" "github.com/openconfig/featureprofiles/internal/samplestream" "github.com/openconfig/ondatra" @@ -47,12 +46,13 @@ func configInterface(t *testing.T, dut1 *ondatra.DUTDevice, dp *ondatra.Port, en i.Enabled = ygot.Bool(enable) i.Type = oc.IETFInterfaces_InterfaceType_ethernetCsmacd gnmi.Replace(t, dut1, gnmi.OC().Interface(dp.Name()).Config(), i) - component := opticalChannelComponentFromPort(t, dut1, dp) + component := components.OpticalChannelComponentFromPort(t, dut1, dp) gnmi.Replace(t, dut1, gnmi.OC().Component(component).OpticalChannel().Config(), &oc.Component_OpticalChannel{ TargetOutputPower: ygot.Float64(targetOutputPower), Frequency: ygot.Uint64(frequency), }) } + func verifyFirmwareVersionValue(t *testing.T, dut1 *ondatra.DUTDevice, pStream *samplestream.SampleStream[string]) { firmwareVersionSample := pStream.Next() if firmwareVersionSample == nil { @@ -90,6 +90,7 @@ func TestZRFirmwareVersionState(t *testing.T) { p1Stream.Close() } + func TestZRFirmwareVersionStateInterfaceFlap(t *testing.T) { dut1 := ondatra.DUT(t, "dut") dp1 := dut1.Port(t, "port1") @@ -119,30 +120,3 @@ func TestZRFirmwareVersionStateInterfaceFlap(t *testing.T) { gnmi.Await(t, dut1, gnmi.OC().Interface(dp1.Name()).OperStatus().State(), time.Minute, oc.Interface_OperStatus_UP) verifyFirmwareVersionValue(t, dut1, p1Stream) } - -func opticalChannelComponentFromPort(t *testing.T, dut *ondatra.DUTDevice, p *ondatra.Port) string { - t.Helper() - if deviations.MissingPortToOpticalChannelMapping(dut) { - switch dut.Vendor() { - case ondatra.ARISTA: - transceiverName := gnmi.Get(t, dut, gnmi.OC().Interface(p.Name()).Transceiver().State()) - return fmt.Sprintf("%s-Optical0", transceiverName) - default: - t.Fatal("Manual Optical channel name required when deviation missing_port_to_optical_channel_component_mapping applied.") - } - } - compName := gnmi.Get(t, dut, gnmi.OC().Interface(p.Name()).HardwarePort().State()) - for { - comp, ok := gnmi.Lookup(t, dut, gnmi.OC().Component(compName).State()).Val() - if !ok { - t.Fatalf("Recursive optical channel lookup failed for port: %s, component %s not found.", p.Name(), compName) - } - if comp.GetType() == oc.PlatformTypes_OPENCONFIG_HARDWARE_COMPONENT_OPTICAL_CHANNEL { - return compName - } - if comp.GetParent() == "" { - t.Fatalf("Recursive optical channel lookup failed for port: %s, parent of component %s not found.", p.Name(), compName) - } - compName = comp.GetParent() - } -} diff --git a/feature/platform/transceiver/tests/zr_inventory_test/README.md b/feature/platform/transceiver/tests/zr_inventory_test/README.md index d1cecb19411..9576331082b 100644 --- a/feature/platform/transceiver/tests/zr_inventory_test/README.md +++ b/feature/platform/transceiver/tests/zr_inventory_test/README.md @@ -84,3 +84,12 @@ Validate 400ZR modules report correct inventory information. * /platform/components/component/state/mfg-date * /platform/components/component/state/hardware-version * /platform/components/component/state/firmware-version + +## OpenConfig Path and RPC Coverage +```yaml +rpcs: + gnmi: + gNMI.Get: + gNMI.Set: + gNMI.Subscribe: +``` diff --git a/feature/platform/transceiver/tests/zr_inventory_test/metadata.textproto b/feature/platform/transceiver/tests/zr_inventory_test/metadata.textproto index 1a64604ac45..224ebd16ed8 100644 --- a/feature/platform/transceiver/tests/zr_inventory_test/metadata.textproto +++ b/feature/platform/transceiver/tests/zr_inventory_test/metadata.textproto @@ -10,5 +10,6 @@ platform_exceptions: { } deviations: { interface_enabled: true + missing_port_to_optical_channel_component_mapping: true } } diff --git a/feature/platform/transceiver/tests/zr_inventory_test/zr_inventory_test.go b/feature/platform/transceiver/tests/zr_inventory_test/zr_inventory_test.go index 9e09d65b9c1..fcd271c36e1 100644 --- a/feature/platform/transceiver/tests/zr_inventory_test/zr_inventory_test.go +++ b/feature/platform/transceiver/tests/zr_inventory_test/zr_inventory_test.go @@ -1,11 +1,10 @@ package zr_inventory_test import ( - "fmt" "testing" "time" - "github.com/openconfig/featureprofiles/internal/deviations" + "github.com/openconfig/featureprofiles/internal/components" "github.com/openconfig/featureprofiles/internal/fptest" "github.com/openconfig/featureprofiles/internal/samplestream" "github.com/openconfig/ondatra" @@ -36,7 +35,7 @@ func configInterface(t *testing.T, dut1 *ondatra.DUTDevice, dp *ondatra.Port, fr i.Enabled = ygot.Bool(true) i.Type = oc.IETFInterfaces_InterfaceType_ethernetCsmacd gnmi.Replace(t, dut1, gnmi.OC().Interface(dp.Name()).Config(), i) - c := opticalChannelComponentFromPort(t, dut1, dp) + c := components.OpticalChannelComponentFromPort(t, dut1, dp) gnmi.Replace(t, dut1, gnmi.OC().Component(c).OpticalChannel().Config(), &oc.Component_OpticalChannel{ TargetOutputPower: ygot.Float64(targetOutputPower), Frequency: ygot.Uint64(frequency), @@ -129,30 +128,3 @@ func TestInventory(t *testing.T) { t.Logf("Interfaces are up: %v, %v", dp1.Name(), dp2.Name()) verifyAllInventoryValues(t, p1StreamsStr, p1StreamsUnion) } - -func opticalChannelComponentFromPort(t *testing.T, dut *ondatra.DUTDevice, p *ondatra.Port) string { - t.Helper() - if deviations.MissingPortToOpticalChannelMapping(dut) { - switch dut.Vendor() { - case ondatra.ARISTA: - transceiverName := gnmi.Get(t, dut, gnmi.OC().Interface(p.Name()).Transceiver().State()) - return fmt.Sprintf("%s-Optical0", transceiverName) - default: - t.Fatal("Manual Optical channel name required when deviation missing_port_to_optical_channel_component_mapping applied.") - } - } - compName := gnmi.Get(t, dut, gnmi.OC().Interface(p.Name()).HardwarePort().State()) - for { - comp, ok := gnmi.Lookup(t, dut, gnmi.OC().Component(compName).State()).Val() - if !ok { - t.Fatalf("Recursive optical channel lookup failed for port: %s, component %s not found.", p.Name(), compName) - } - if comp.GetType() == oc.PlatformTypes_OPENCONFIG_HARDWARE_COMPONENT_OPTICAL_CHANNEL { - return compName - } - if comp.GetParent() == "" { - t.Fatalf("Recursive optical channel lookup failed for port: %s, parent of component %s not found.", p.Name(), compName) - } - compName = comp.GetParent() - } -} diff --git a/feature/platform/transceiver/tests/zr_laser_bias_current_test/README.md b/feature/platform/transceiver/tests/zr_laser_bias_current_test/README.md index cc87c088fd5..05823ee7047 100644 --- a/feature/platform/transceiver/tests/zr_laser_bias_current_test/README.md +++ b/feature/platform/transceiver/tests/zr_laser_bias_current_test/README.md @@ -86,14 +86,27 @@ specified operating temperature and voltage. updated to the value in the normal range again. * Typical measurement range 0 to 131 mA. -## Config Parameter coverage - -* /components/component/transceiver/config/enabled -* /interfaces/interface/config/enabled - -## Telemetry Parameter coverage - -* /components/component/optical-channel/state/laser-bias-current/instant -* /components/component/optical-channel/state/laser-bias-current/avg -* /components/component/optical-channel/state/laser-bias-current/min -* /components/component/optical-channel/state/laser-bias-current/max \ No newline at end of file +## 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 ## + /components/component/transceiver/config/enabled: + platform_type: [ "OPTICAL_CHANNEL" ] + /interfaces/interface/config/enabled: + ## State Paths ## + /components/component/optical-channel/state/laser-bias-current/instant: + platform_type: [ "OPTICAL_CHANNEL" ] + /components/component/optical-channel/state/laser-bias-current/avg: + platform_type: [ "OPTICAL_CHANNEL" ] + /components/component/optical-channel/state/laser-bias-current/min: + platform_type: [ "OPTICAL_CHANNEL" ] + /components/component/optical-channel/state/laser-bias-current/max: + platform_type: [ "OPTICAL_CHANNEL" ] + +rpcs: + gnmi: + gNMI.Subscribe: +``` diff --git a/feature/platform/transceiver/tests/zr_laser_bias_current_test/metadata.textproto b/feature/platform/transceiver/tests/zr_laser_bias_current_test/metadata.textproto index 66bb18f7316..a16fa3b71a1 100644 --- a/feature/platform/transceiver/tests/zr_laser_bias_current_test/metadata.textproto +++ b/feature/platform/transceiver/tests/zr_laser_bias_current_test/metadata.textproto @@ -13,5 +13,6 @@ platform_exceptions: { interface_enabled: true default_network_instance: "default" missing_port_to_optical_channel_component_mapping: true + missing_zr_optical_channel_tunable_parameters_telemetry: true } } diff --git a/feature/platform/transceiver/tests/zr_laser_bias_current_test/zr_laser_bias_current_test.go b/feature/platform/transceiver/tests/zr_laser_bias_current_test/zr_laser_bias_current_test.go index 0044d117154..80e67d6649b 100644 --- a/feature/platform/transceiver/tests/zr_laser_bias_current_test/zr_laser_bias_current_test.go +++ b/feature/platform/transceiver/tests/zr_laser_bias_current_test/zr_laser_bias_current_test.go @@ -15,11 +15,11 @@ package zr_laser_bias_current_test import ( - "fmt" "reflect" "testing" "time" + "github.com/openconfig/featureprofiles/internal/components" "github.com/openconfig/featureprofiles/internal/deviations" "github.com/openconfig/featureprofiles/internal/fptest" "github.com/openconfig/featureprofiles/internal/samplestream" @@ -32,7 +32,7 @@ import ( const ( dp16QAM = 1 targetOutputPower = -10 - frequency = 193100000 + frequency = 193500000 ) func TestMain(m *testing.M) { @@ -62,33 +62,39 @@ func verifyLaserBiasCurrent(t *testing.T, pStream *samplestream.SampleStream[flo return laserBiasVal } -func verifyLaserBiasCurrentAll(t *testing.T, pStreamInstant *samplestream.SampleStream[float64], pStreamAvg *samplestream.SampleStream[float64], pStreamMax *samplestream.SampleStream[float64], pStreamMin *samplestream.SampleStream[float64]) { +func verifyLaserBiasCurrentAll(t *testing.T, pStreamInstant *samplestream.SampleStream[float64], pStreamAvg *samplestream.SampleStream[float64], pStreamMax *samplestream.SampleStream[float64], pStreamMin *samplestream.SampleStream[float64], dut1 *ondatra.DUTDevice) { laserbiasInstant := verifyLaserBiasCurrent(t, pStreamInstant, "laserbiasInstant") t.Logf("laserBias Instant value: %f", laserbiasInstant) - laserbiasMin := verifyLaserBiasCurrent(t, pStreamMin, "laserbiasMin") - t.Logf("laserBias Min value: %f", laserbiasMin) - laserbiasMax := verifyLaserBiasCurrent(t, pStreamMax, "laserbiasMax") - t.Logf("laserBias Max value: %f", laserbiasMax) - laserbiasAvg := verifyLaserBiasCurrent(t, pStreamAvg, "laserbiasAvg") - t.Logf("laserBias Avg value: %f", laserbiasAvg) - if laserbiasAvg >= laserbiasMin && laserbiasAvg <= laserbiasMax { - t.Logf("The average is between the maximum and minimum values") + if deviations.MissingZROpticalChannelTunableParametersTelemetry(dut1) { + t.Log("Skipping Min/Max/Avg Tunable Parameters Telemetry validation. Deviation MissingZROpticalChannelTunableParametersTelemetry enabled.") } else { - t.Fatalf("The average is not between the maximum and minimum values Avg:%f Min:%f Max:%f", laserbiasAvg, laserbiasMin, laserbiasMax) + laserbiasMin := verifyLaserBiasCurrent(t, pStreamMin, "laserbiasMin") + t.Logf("laserBias Min value: %f", laserbiasMin) + laserbiasMax := verifyLaserBiasCurrent(t, pStreamMax, "laserbiasMax") + t.Logf("laserBias Max value: %f", laserbiasMax) + laserbiasAvg := verifyLaserBiasCurrent(t, pStreamAvg, "laserbiasAvg") + t.Logf("laserBias Avg value: %f", laserbiasAvg) + if laserbiasAvg >= laserbiasMin && laserbiasAvg <= laserbiasMax { + t.Logf("The average is between the maximum and minimum values") + } else { + t.Fatalf("The average is not between the maximum and minimum values Avg:%f Min:%f Max:%f", laserbiasAvg, laserbiasMin, laserbiasMax) + } } } + func interfaceConfig(t *testing.T, dut1 *ondatra.DUTDevice, dp *ondatra.Port) { d := &oc.Root{} i := d.GetOrCreateInterface(dp.Name()) i.Enabled = ygot.Bool(true) i.Type = oc.IETFInterfaces_InterfaceType_ethernetCsmacd gnmi.Replace(t, dut1, gnmi.OC().Interface(dp.Name()).Config(), i) - OCcomponent := opticalChannelComponentFromPort(t, dut1, dp) + OCcomponent := components.OpticalChannelComponentFromPort(t, dut1, dp) gnmi.Replace(t, dut1, gnmi.OC().Component(OCcomponent).OpticalChannel().Config(), &oc.Component_OpticalChannel{ TargetOutputPower: ygot.Float64(targetOutputPower), Frequency: ygot.Uint64(frequency), }) } + func TestZRLaserBiasCurrentState(t *testing.T) { dut1 := ondatra.DUT(t, "dut") dp1 := dut1.Port(t, "port1") @@ -103,7 +109,7 @@ func TestZRLaserBiasCurrentState(t *testing.T) { if dp1.PMD() != ondatra.PMD400GBASEZR { t.Fatalf("%s Transceiver is not 400ZR its of type: %v", transceiverState, dp1.PMD()) } - OCcomponent := opticalChannelComponentFromPort(t, dut1, dp1) + OCcomponent := components.OpticalChannelComponentFromPort(t, dut1, dp1) component1 := gnmi.OC().Component(OCcomponent) p1StreamInstant := samplestream.New(t, dut1, component1.OpticalChannel().LaserBiasCurrent().Instant().State(), 10*time.Second) p1StreamMin := samplestream.New(t, dut1, component1.OpticalChannel().LaserBiasCurrent().Min().State(), 10*time.Second) @@ -113,8 +119,9 @@ func TestZRLaserBiasCurrentState(t *testing.T) { defer p1StreamMax.Close() defer p1StreamMin.Close() defer p1StreamInstant.Close() - verifyLaserBiasCurrentAll(t, p1StreamInstant, p1StreamAvg, p1StreamMax, p1StreamMin) + verifyLaserBiasCurrentAll(t, p1StreamInstant, p1StreamAvg, p1StreamMax, p1StreamMin, dut1) } + func TestZRLaserBiasCurrentStateInterface_Flap(t *testing.T) { dut1 := ondatra.DUT(t, "dut") dp1 := dut1.Port(t, "port1") @@ -137,7 +144,7 @@ func TestZRLaserBiasCurrentStateInterface_Flap(t *testing.T) { i.Enabled = ygot.Bool(false) i.Type = oc.IETFInterfaces_InterfaceType_ethernetCsmacd gnmi.Replace(t, dut1, gnmi.OC().Interface(dp1.Name()).Config(), i) - OCcomponent := opticalChannelComponentFromPort(t, dut1, dp1) + OCcomponent := components.OpticalChannelComponentFromPort(t, dut1, dp1) component1 := gnmi.OC().Component(OCcomponent) p1StreamInstant := samplestream.New(t, dut1, component1.OpticalChannel().LaserBiasCurrent().Instant().State(), 10*time.Second) p1StreamMin := samplestream.New(t, dut1, component1.OpticalChannel().LaserBiasCurrent().Min().State(), 10*time.Second) @@ -147,16 +154,17 @@ func TestZRLaserBiasCurrentStateInterface_Flap(t *testing.T) { defer p1StreamMin.Close() defer p1StreamMax.Close() defer p1StreamAvg.Close() - verifyLaserBiasCurrentAll(t, p1StreamInstant, p1StreamAvg, p1StreamMax, p1StreamMin) + verifyLaserBiasCurrentAll(t, p1StreamInstant, p1StreamAvg, p1StreamMax, p1StreamMin, dut1) // Wait 120 sec cooling off period gnmi.Await(t, dut1, gnmi.OC().Interface(dp1.Name()).OperStatus().State(), intUpdateTime, oc.Interface_OperStatus_DOWN) // Enable interface - verifyLaserBiasCurrentAll(t, p1StreamInstant, p1StreamAvg, p1StreamMax, p1StreamMin) + verifyLaserBiasCurrentAll(t, p1StreamInstant, p1StreamAvg, p1StreamMax, p1StreamMin, dut1) i.Enabled = ygot.Bool(true) gnmi.Replace(t, dut1, gnmi.OC().Interface(dp1.Name()).Config(), i) gnmi.Await(t, dut1, gnmi.OC().Interface(dp1.Name()).OperStatus().State(), intUpdateTime, oc.Interface_OperStatus_UP) - verifyLaserBiasCurrentAll(t, p1StreamInstant, p1StreamAvg, p1StreamMax, p1StreamMin) + verifyLaserBiasCurrentAll(t, p1StreamInstant, p1StreamAvg, p1StreamMax, p1StreamMin, dut1) } + func TestZRLaserBiasCurrentStateTransceiverOnOff(t *testing.T) { dut1 := ondatra.DUT(t, "dut") dp1 := dut1.Port(t, "port1") @@ -172,7 +180,7 @@ func TestZRLaserBiasCurrentStateTransceiverOnOff(t *testing.T) { if dp1.PMD() != ondatra.PMD400GBASEZR { t.Fatalf("%s Transceiver is not 400ZR its of type: %v", transceiverState, dp1.PMD()) } - OCcomponent := opticalChannelComponentFromPort(t, dut1, dp1) + OCcomponent := components.OpticalChannelComponentFromPort(t, dut1, dp1) component1 := gnmi.OC().Component(OCcomponent) p1StreamInstant := samplestream.New(t, dut1, component1.OpticalChannel().LaserBiasCurrent().Instant().State(), 10*time.Second) p1StreamMin := samplestream.New(t, dut1, component1.OpticalChannel().LaserBiasCurrent().Min().State(), 10*time.Second) @@ -184,35 +192,9 @@ func TestZRLaserBiasCurrentStateTransceiverOnOff(t *testing.T) { defer p1StreamAvg.Close() // Disable interface transceiver power off gnmi.Update(t, dut1, gnmi.OC().Component(dp1.Name()).Transceiver().Enabled().Config(), false) - verifyLaserBiasCurrentAll(t, p1StreamInstant, p1StreamAvg, p1StreamMax, p1StreamMin) + verifyLaserBiasCurrentAll(t, p1StreamInstant, p1StreamAvg, p1StreamMax, p1StreamMin, dut1) // Enable interface transceiver power on gnmi.Update(t, dut1, gnmi.OC().Component(dp1.Name()).Transceiver().Enabled().Config(), true) gnmi.Await(t, dut1, gnmi.OC().Interface(dp1.Name()).OperStatus().State(), intUpdateTime, oc.Interface_OperStatus_UP) - verifyLaserBiasCurrentAll(t, p1StreamInstant, p1StreamAvg, p1StreamMax, p1StreamMin) -} -func opticalChannelComponentFromPort(t *testing.T, dut *ondatra.DUTDevice, p *ondatra.Port) string { - t.Helper() - if deviations.MissingPortToOpticalChannelMapping(dut) { - switch dut.Vendor() { - case ondatra.ARISTA: - transceiverState := gnmi.Get(t, dut, gnmi.OC().Interface(p.Name()).Transceiver().State()) - return fmt.Sprintf("%s-Optical0", transceiverState) - default: - t.Fatal("Manual Optical channel name required when deviation missing_port_to_optical_channel_component_mapping applied.") - } - } - compName := gnmi.Get(t, dut, gnmi.OC().Interface(p.Name()).HardwarePort().State()) - for { - comp, ok := gnmi.Lookup(t, dut, gnmi.OC().Component(compName).State()).Val() - if !ok { - t.Fatalf("Recursive optical channel lookup failed for port: %s, component %s not found.", p.Name(), compName) - } - if comp.GetType() == oc.PlatformTypes_OPENCONFIG_HARDWARE_COMPONENT_OPTICAL_CHANNEL { - return compName - } - if comp.GetParent() == "" { - t.Fatalf("Recursive optical channel lookup failed for port: %s, parent of component %s not found.", p.Name(), compName) - } - compName = comp.GetParent() - } + verifyLaserBiasCurrentAll(t, p1StreamInstant, p1StreamAvg, p1StreamMax, p1StreamMin, dut1) } diff --git a/feature/platform/transceiver/tests/zr_logical_channels_test/README.md b/feature/platform/transceiver/tests/zr_logical_channels_test/README.md index 56121dcfc4f..eb5081775f2 100644 --- a/feature/platform/transceiver/tests/zr_logical_channels_test/README.md +++ b/feature/platform/transceiver/tests/zr_logical_channels_test/README.md @@ -130,4 +130,13 @@ Once the ZR link is estabished proceed to configure the following entities: * /terminal-device/logical-channels/channel/logical-channel-assignments/assignment/state/description * /terminal-device/logical-channels/channel/logical-channel-assignments/assignment/state/index * /terminal-device/logical-channels/channel/logical-channel-assignments/assignment/state/logical-channel -* /terminal-device/logical-channels/channel/logical-channel-assignments/assignment/state/optical-channel \ No newline at end of file +* /terminal-device/logical-channels/channel/logical-channel-assignments/assignment/state/optical-channel + +## OpenConfig Path and RPC Coverage +```yaml +rpcs: + gnmi: + gNMI.Get: + gNMI.Set: + gNMI.Subscribe: +``` diff --git a/feature/platform/transceiver/tests/zr_logical_channels_test/zr_logical_channels_test.go b/feature/platform/transceiver/tests/zr_logical_channels_test/zr_logical_channels_test.go index 5ca9be69189..f7ad7308c3c 100644 --- a/feature/platform/transceiver/tests/zr_logical_channels_test/zr_logical_channels_test.go +++ b/feature/platform/transceiver/tests/zr_logical_channels_test/zr_logical_channels_test.go @@ -1,13 +1,12 @@ package zr_logical_channels_test import ( - "fmt" "testing" "time" "github.com/google/go-cmp/cmp" "github.com/openconfig/featureprofiles/internal/attrs" - "github.com/openconfig/featureprofiles/internal/deviations" + "github.com/openconfig/featureprofiles/internal/components" "github.com/openconfig/featureprofiles/internal/fptest" "github.com/openconfig/featureprofiles/internal/samplestream" "github.com/openconfig/ondatra" @@ -51,8 +50,8 @@ func Test400ZRLogicalChannels(t *testing.T) { gnmi.Replace(t, dut, gnmi.OC().Interface(p1.Name()).Config(), dutPort1.NewOCInterface(p1.Name(), dut)) gnmi.Replace(t, dut, gnmi.OC().Interface(p2.Name()).Config(), dutPort2.NewOCInterface(p2.Name(), dut)) - oc1 := opticalChannelFromPort(t, dut, p1) - oc2 := opticalChannelFromPort(t, dut, p2) + oc1 := components.OpticalChannelComponentFromPort(t, dut, p1) + oc2 := components.OpticalChannelComponentFromPort(t, dut, p2) configureLogicalChannels(t, dut, 40000, 40001, oc1) configureLogicalChannels(t, dut, 40002, 40003, oc2) @@ -269,34 +268,3 @@ func validateCoherentChannelTelemetry(t *testing.T, coherentChIdx uint32, optica }) } } - -// opticalChannelFromPort returns the connected optical channel component name for a given ondatra port. -func opticalChannelFromPort(t *testing.T, dut *ondatra.DUTDevice, p *ondatra.Port) string { - t.Helper() - - if deviations.MissingPortToOpticalChannelMapping(dut) { - switch dut.Vendor() { - case ondatra.ARISTA: - return fmt.Sprintf("%s-Optical0", p.Name()) - default: - t.Fatal("Manual Optical channel name required when deviation missing_port_to_optical_channel_component_mapping applied.") - } - } - compName := gnmi.Get(t, dut, gnmi.OC().Interface(p.Name()).HardwarePort().State()) - - for { - comp, ok := gnmi.Lookup(t, dut, gnmi.OC().Component(compName).State()).Val() - if !ok { - t.Fatalf("Recursive optical channel lookup failed for port: %s, component %s not found.", p.Name(), compName) - } - if comp.GetType() == oc.PlatformTypes_OPENCONFIG_HARDWARE_COMPONENT_OPTICAL_CHANNEL { - return compName - } - - if comp.GetParent() == "" { - t.Fatalf("Recursive optical channel lookup failed for port: %s, parent of component %s not found.", p.Name(), compName) - } - - compName = comp.GetParent() - } -} diff --git a/feature/platform/transceiver/tests/zr_low_power_mode_test/README.md b/feature/platform/transceiver/tests/zr_low_power_mode_test/README.md index 912a137f5a2..c3403986887 100644 --- a/feature/platform/transceiver/tests/zr_low_power_mode_test/README.md +++ b/feature/platform/transceiver/tests/zr_low_power_mode_test/README.md @@ -94,21 +94,41 @@ Once the ZR link is estabished proceed with the following: stream any invalid string values like "nil" or "-inf" until valid values are available for streaming. -## Config Parameter coverage - -* /interfaces/interface/config/enabled - -## Telemetry Parameter coverage - -* /platform/components/component/state/serial-no -* /platform/components/component/state/part-no -* /platform/components/component/state/type -* /platform/components/component/state/description -* /platform/components/component/state/mfg-name -* /platform/components/component/state/mfg-date -* /platform/components/component/state/hardware-version -* /platform/components/component/state/firmware-version -* /components/component/optical-channel/state/output-power/instant -* /components/component/optical-channel/state/output-power/avg -* /components/component/optical-channel/state/output-power/min -* /components/component/optical-channel/state/output-power/max \ No newline at end of file +## OpenConfig Path and RPC Coverage + +```yaml +paths: + # Configure parameter + /interfaces/interface/config/enabled: + # Telemetry Parameter coverage + /components/component/state/serial-no: + platform_type: ["OPTICAL_CHANNEL"] + /components/component/state/part-no: + platform_type: ["OPTICAL_CHANNEL"] + /components/component/state/type: + platform_type: ["OPTICAL_CHANNEL"] + /components/component/state/description: + platform_type: ["OPTICAL_CHANNEL"] + /components/component/state/mfg-name: + platform_type: ["OPTICAL_CHANNEL"] + /components/component/state/mfg-date: + platform_type: ["OPTICAL_CHANNEL"] + /components/component/state/hardware-version: + platform_type: ["OPTICAL_CHANNEL"] + /components/component/state/firmware-version: + platform_type: ["OPTICAL_CHANNEL"] + /components/component/optical-channel/state/output-power/instant: + platform_type: ["OPTICAL_CHANNEL"] + /components/component/optical-channel/state/output-power/avg: + platform_type: ["OPTICAL_CHANNEL"] + /components/component/optical-channel/state/output-power/min: + platform_type: ["OPTICAL_CHANNEL"] + /components/component/optical-channel/state/output-power/max: + platform_type: ["OPTICAL_CHANNEL"] + +rpcs: + gnmi: + gNMI.Get: + gNMI.Set: + gNMI.Subscribe: +``` \ No newline at end of file diff --git a/feature/platform/transceiver/tests/zr_low_power_mode_test/metadata.textproto b/feature/platform/transceiver/tests/zr_low_power_mode_test/metadata.textproto index 8236fb587cf..011a0b7bb63 100644 --- a/feature/platform/transceiver/tests/zr_low_power_mode_test/metadata.textproto +++ b/feature/platform/transceiver/tests/zr_low_power_mode_test/metadata.textproto @@ -5,3 +5,13 @@ uuid: "92fbb383-47b3-40e6-ab33-77be99e450b3" plan_id: "TRANSCEIVER-13" description: "Configuration: 400ZR Transceiver Low Power Mode Setting." testbed: TESTBED_DUT_400ZR +platform_exceptions: { + platform: { + vendor: ARISTA + } + deviations: { + interface_enabled: true + default_network_instance: "default" + missing_port_to_optical_channel_component_mapping: true + } +} diff --git a/feature/platform/transceiver/tests/zr_low_power_mode_test/zr_low_power_mode_test.go b/feature/platform/transceiver/tests/zr_low_power_mode_test/zr_low_power_mode_test.go index 4d655bdd815..b8bdc687167 100644 --- a/feature/platform/transceiver/tests/zr_low_power_mode_test/zr_low_power_mode_test.go +++ b/feature/platform/transceiver/tests/zr_low_power_mode_test/zr_low_power_mode_test.go @@ -16,23 +16,22 @@ package zr_low_power_mode_test import ( "fmt" - "math" "reflect" "testing" "time" + "github.com/openconfig/featureprofiles/internal/cfgplugins" "github.com/openconfig/featureprofiles/internal/fptest" "github.com/openconfig/featureprofiles/internal/samplestream" "github.com/openconfig/ondatra" "github.com/openconfig/ondatra/gnmi" + "github.com/openconfig/ondatra/gnmi/oc" + "github.com/openconfig/ygot/ygot" ) const ( - samplingInterval = 10 * time.Second - targetOutputPowerdBm = -10 - targetOutputPowerTolerancedBm = 1 - targetFrequencyHz = 193100000 - targetFrequencyToleranceHz = 100000 + samplingInterval = 10 * time.Second + intUpdateTime = 2 * time.Minute ) func TestMain(m *testing.M) { @@ -81,16 +80,16 @@ func validateOutputPower(t *testing.T, streams map[string]*samplestream.SampleSt func TestLowPowerMode(t *testing.T) { dut := ondatra.DUT(t, "dut") + cfgplugins.InterfaceConfig(t, dut, dut.Port(t, "port1")) + cfgplugins.InterfaceConfig(t, dut, dut.Port(t, "port2")) for _, port := range []string{"port1", "port2"} { t.Run(fmt.Sprintf("Port:%s", port), func(t *testing.T) { dp := dut.Port(t, port) - - gnmi.Update(t, dut, gnmi.OC().Interface(dp.Name()).Enabled().Config(), bool(false)) + gnmi.Await(t, dut, gnmi.OC().Interface(dp.Name()).OperStatus().State(), intUpdateTime, oc.Interface_OperStatus_UP) // Derive transceiver names from ports. tr := gnmi.Get(t, dut, gnmi.OC().Interface(dp.Name()).Transceiver().State()) - // Stream all inventory information. streamSerialNo := samplestream.New(t, dut, gnmi.OC().Component(tr).SerialNo().State(), samplingInterval) defer streamSerialNo.Close() @@ -120,6 +119,17 @@ func TestLowPowerMode(t *testing.T) { } validateStreamOutput(t, allStream) + d := &oc.Root{} + i := d.GetOrCreateInterface(dp.Name()) + i.Type = oc.IETFInterfaces_InterfaceType_ethernetCsmacd + // Disable interface + i.Enabled = ygot.Bool(false) + gnmi.Replace(t, dut, gnmi.OC().Interface(dp.Name()).Config(), i) + // Wait for interface to go down. + gnmi.Await(t, dut, gnmi.OC().Interface(dp.Name()).OperStatus().State(), intUpdateTime, oc.Interface_OperStatus_DOWN) + + validateStreamOutput(t, allStream) + opInst := samplestream.New(t, dut, gnmi.OC().Component(tr).OpticalChannel().OutputPower().Instant().State(), samplingInterval) defer opInst.Close() if opInstN := opInst.Next(); opInstN != nil { @@ -152,7 +162,10 @@ func TestLowPowerMode(t *testing.T) { } } - gnmi.Update(t, dut, gnmi.OC().Interface(dp.Name()).Enabled().Config(), bool(true)) + // Enable interface + i.Enabled = ygot.Bool(true) + gnmi.Replace(t, dut, gnmi.OC().Interface(dp.Name()).Config(), i) + gnmi.Await(t, dut, gnmi.OC().Interface(dp.Name()).OperStatus().State(), intUpdateTime, oc.Interface_OperStatus_UP) powerStreamMap := map[string]*samplestream.SampleStream[float64]{ "inst": opInst, @@ -162,19 +175,7 @@ func TestLowPowerMode(t *testing.T) { } validateOutputPower(t, powerStreamMap) - - // Derive transceiver names from ports. - component := gnmi.OC().Component(tr) - - outputPower := gnmi.Get(t, dut, component.OpticalChannel().TargetOutputPower().State()) - if math.Abs(float64(outputPower)-float64(targetOutputPowerdBm)) > targetOutputPowerTolerancedBm { - t.Fatalf("Output power is not within expected tolerance, got: %v want: %v tolerance: %v", outputPower, targetOutputPowerdBm, targetOutputPowerTolerancedBm) - } - - frequency := gnmi.Get(t, dut, component.OpticalChannel().Frequency().State()) - if math.Abs(float64(frequency)-float64(targetFrequencyHz)) > targetFrequencyToleranceHz { - t.Fatalf("Frequency is not within expected tolerance, got: %v want: %v tolerance: %v", frequency, targetFrequencyHz, targetFrequencyToleranceHz) - } + cfgplugins.ValidateInterfaceConfig(t, dut, dp) }) } } diff --git a/feature/platform/transceiver/tests/zr_supply_voltage_test/README.md b/feature/platform/transceiver/tests/zr_supply_voltage_test/README.md index 84092157f21..7624af5654c 100644 --- a/feature/platform/transceiver/tests/zr_supply_voltage_test/README.md +++ b/feature/platform/transceiver/tests/zr_supply_voltage_test/README.md @@ -24,28 +24,16 @@ https://www.oiforum.com/wp-content/uploads/CMIS5p0_Third_Party_Spec.pdf ports to a second DUT2. For most tests this setup should be sufficient. Ref: [Typical ATE<>DUT Test bed](https://github.com/openconfig/featureprofiles/blob/main/topologies/atedut_2.testbed) * A and Z ends of the link should have same 400ZR PMD. For this test a - single DUT ZR port connected to a single ZR ATE port is also sufficient. + single DUT ZR port connected to a single ZR ATE port is also sufficient. Once the ZR link is estabished proceed with the following: * verify that the following ZR transceiver telemetry paths exist and are streamed for both the ZR optics. * /components/component/transceiver/state/supply-voltage/instant - * /components/component/transceiver/state/supply-voltage/min - * /components/component/transceiver/state/supply-voltage/max - * /components/component/transceiver/state/supply-voltage/avg -* For reported data check for validity min <= avg/instant <= max * If the modules or the devices are in a boot stage, they must not stream any invalid string values like "nil" or "-inf". * Reported supply voltage value must always be of type decimal64. - - -**Note:** For min, max, and avg values, 10 second sampling is preferred. If the - min, max average values or the 10 seconds sampling is not supported, - the sampling interval used must be specified and this must be - captured by adding a deviation to the test. - - * Verify the module supply voltage is reported correctly with optics interface in disabled state. @@ -58,13 +46,19 @@ Once the ZR link is estabished proceed with the following: any invalid string values like "nil" or "-inf". * Reported supply voltage value must always be of type decimal64. -## Config Parameter coverage - -* /interfaces/interface/config/enabled - -## Telemetry Parameter coverage - - * /components/component/transceiver/state/supply-voltage/instant - * /components/component/transceiver/state/supply-voltage/min - * /components/component/transceiver/state/supply-voltage/max - * /components/component/transceiver/state/supply-voltage/avg \ No newline at end of file +## OpenConfig Path and RPC Coverage + +```yaml +paths: + # Config Parameter coverage + /interfaces/interface/config/enabled: + # Telemetry Parameter coverage + /components/component/transceiver/state/supply-voltage/instant: + platform_type: ["OPTICAL_CHANNEL"] + +rpcs: + gnmi: + gNMI.Get: + gNMI.Set: + gNMI.Subscribe: +``` \ No newline at end of file diff --git a/feature/platform/transceiver/tests/zr_supply_voltage_test/metadata.textproto b/feature/platform/transceiver/tests/zr_supply_voltage_test/metadata.textproto index c645ec9f682..ce02315ba93 100644 --- a/feature/platform/transceiver/tests/zr_supply_voltage_test/metadata.textproto +++ b/feature/platform/transceiver/tests/zr_supply_voltage_test/metadata.textproto @@ -5,3 +5,13 @@ uuid: "7e0251e4-8c5c-4dff-9683-8c21c817816c" plan_id: "TRANSCEIVER-12" description: "Telemetry: 400ZR Transceiver Supply Voltage streaming." testbed: TESTBED_DUT_400ZR +platform_exceptions: { + platform: { + vendor: ARISTA + } + deviations: { + interface_enabled: true + default_network_instance: "default" + missing_port_to_optical_channel_component_mapping: true + } +} diff --git a/feature/platform/transceiver/tests/zr_supply_voltage_test/zr_supply_voltage_test.go b/feature/platform/transceiver/tests/zr_supply_voltage_test/zr_supply_voltage_test.go index 39497170da3..ce9383143a7 100644 --- a/feature/platform/transceiver/tests/zr_supply_voltage_test/zr_supply_voltage_test.go +++ b/feature/platform/transceiver/tests/zr_supply_voltage_test/zr_supply_voltage_test.go @@ -20,18 +20,18 @@ import ( "testing" "time" + "github.com/openconfig/featureprofiles/internal/cfgplugins" "github.com/openconfig/featureprofiles/internal/fptest" "github.com/openconfig/featureprofiles/internal/samplestream" "github.com/openconfig/ondatra" "github.com/openconfig/ondatra/gnmi" "github.com/openconfig/ondatra/gnmi/oc" + "github.com/openconfig/ygot/ygot" ) const ( - samplingInterval = 10 * time.Second - targetOutputPowerdBm = -10 - targetFrequencyHz = 193100000 - intUpdateTime = 2 * time.Minute + samplingInterval = 10 * time.Second + intUpdateTime = 2 * time.Minute ) func TestMain(m *testing.M) { @@ -57,10 +57,13 @@ func verifyVoltageValue(t *testing.T, pStream *samplestream.SampleStream[float64 func TestZrSupplyVoltage(t *testing.T) { dut := ondatra.DUT(t, "dut") + cfgplugins.InterfaceConfig(t, dut, dut.Port(t, "port1")) + cfgplugins.InterfaceConfig(t, dut, dut.Port(t, "port2")) for _, port := range []string{"port1", "port2"} { t.Run(fmt.Sprintf("Port:%s", port), func(t *testing.T) { dp := dut.Port(t, port) + t.Logf("Port %s", dp.Name()) gnmi.Await(t, dut, gnmi.OC().Interface(dp.Name()).OperStatus().State(), intUpdateTime, oc.Interface_OperStatus_UP) @@ -68,58 +71,23 @@ func TestZrSupplyVoltage(t *testing.T) { tr := gnmi.Get(t, dut, gnmi.OC().Interface(dp.Name()).Transceiver().State()) component := gnmi.OC().Component(tr) - outputPower := gnmi.Get(t, dut, component.OpticalChannel().TargetOutputPower().State()) - if outputPower != targetOutputPowerdBm { - t.Fatalf("Output power does not match target output power, got: %v want :%v", outputPower, targetOutputPowerdBm) - } - - frequency := gnmi.Get(t, dut, component.OpticalChannel().Frequency().State()) - if frequency != targetFrequencyHz { - t.Fatalf("Frequency does not match target frequency, got: %v want :%v", frequency, targetFrequencyHz) - } - streamInst := samplestream.New(t, dut, component.Transceiver().SupplyVoltage().Instant().State(), samplingInterval) defer streamInst.Close() - streamAvg := samplestream.New(t, dut, component.Transceiver().SupplyVoltage().Avg().State(), samplingInterval) - defer streamAvg.Close() - streamMin := samplestream.New(t, dut, component.Transceiver().SupplyVoltage().Min().State(), samplingInterval) - defer streamMin.Close() - streamMax := samplestream.New(t, dut, component.Transceiver().SupplyVoltage().Max().State(), samplingInterval) - defer streamMax.Close() volInst := verifyVoltageValue(t, streamInst, "Instant") t.Logf("Port %s instant voltage: %v", dp.Name(), volInst) - volAvg := verifyVoltageValue(t, streamAvg, "Avg") - t.Logf("Port %s average voltage: %v", dp.Name(), volAvg) - volMin := verifyVoltageValue(t, streamMin, "Min") - t.Logf("Port %s minimum voltage: %v", dp.Name(), volMin) - volMax := verifyVoltageValue(t, streamMax, "Max") - t.Logf("Port %s maximum voltage: %v", dp.Name(), volMax) - - if volAvg >= volMin && volAvg <= volMax { - t.Logf("The average is between the maximum and minimum values") - } else { - t.Fatalf("The average is not between the maximum and minimum values, Avg:%v Max:%v Min:%v", volAvg, volMax, volMin) - } + d := &oc.Root{} + i := d.GetOrCreateInterface(dp.Name()) + i.Type = oc.IETFInterfaces_InterfaceType_ethernetCsmacd + // Disable interface + i.Enabled = ygot.Bool(false) + gnmi.Replace(t, dut, gnmi.OC().Interface(dp.Name()).Config(), i) // Wait for the cooling off period gnmi.Await(t, dut, gnmi.OC().Interface(dp.Name()).OperStatus().State(), intUpdateTime, oc.Interface_OperStatus_DOWN) volInstNew := verifyVoltageValue(t, streamInst, "Instant") t.Logf("Port %s instant voltage after port down: %v", dp.Name(), volInstNew) - volAvgNew := verifyVoltageValue(t, streamAvg, "Avg") - t.Logf("Port %s average voltage after port down: %v", dp.Name(), volAvgNew) - volMinNew := verifyVoltageValue(t, streamMin, "Min") - t.Logf("Port %s minimum voltage after port down: %v", dp.Name(), volMinNew) - volMaxNew := verifyVoltageValue(t, streamMax, "Max") - t.Logf("Port %s maximum voltage after port down: %v", dp.Name(), volMaxNew) - - if volAvgNew >= volMinNew && volAvgNew <= volMaxNew { - t.Logf("The average voltage after port down is between the maximum and minimum values") - } else { - t.Fatalf("The average voltage after port down is not between the maximum and minimum values, Avg:%v Max:%v Min:%v", volAvgNew, volMaxNew, volMinNew) - } }) } - } diff --git a/feature/platform/transceiver/tests/zr_temperature_test/README.md b/feature/platform/transceiver/tests/zr_temperature_test/README.md index 57a4ab52bbb..750acf0bcb5 100644 --- a/feature/platform/transceiver/tests/zr_temperature_test/README.md +++ b/feature/platform/transceiver/tests/zr_temperature_test/README.md @@ -54,13 +54,26 @@ https://www.oiforum.com/wp-content/uploads/CMIS5p0_Third_Party_Spec.pdf any invalid string values like "nil" or "-inf". * Reported temperature value must always be of type decimal64. -## Config Parameter coverage +## OpenConfig Path and RPC Coverage -* /interfaces/interface/config/enabled +The below yaml defines the OC paths intended to be covered by this test. OC paths used for test setup are not listed here. -## Telemetry Parameter coverage +```yaml +paths: + ## Config Paths ## + /interfaces/interface/config/enabled: + ## State Paths ## + /components/component/state/temperature/instant: + platform_type: [ "TRANSCEIVER" ] + /components/component/state/temperature/min: + platform_type: [ "TRANSCEIVER" ] + /components/component/state/temperature/max: + platform_type: [ "TRANSCEIVER" ] + /components/component/state/temperature/avg: + platform_type: [ "TRANSCEIVER" ] + +rpcs: + gnmi: + gNMI.Subscribe: +``` -* /platform/components/component/state/temperature/instant -* /platform/components/component/state/temperature/min -* /platform/components/component/state/temperature/max -* /platform/components/component/state/temperature/avg \ No newline at end of file diff --git a/feature/platform/transceiver/tests/zr_temperature_test/metadata.textproto b/feature/platform/transceiver/tests/zr_temperature_test/metadata.textproto index d44ab59ae60..cf055bacbc7 100644 --- a/feature/platform/transceiver/tests/zr_temperature_test/metadata.textproto +++ b/feature/platform/transceiver/tests/zr_temperature_test/metadata.textproto @@ -13,5 +13,6 @@ platform_exceptions: { interface_enabled: true default_network_instance: "default" missing_port_to_optical_channel_component_mapping: true + missing_zr_optical_channel_tunable_parameters_telemetry: true } } diff --git a/feature/platform/transceiver/tests/zr_temperature_test/zr_temperature_test.go b/feature/platform/transceiver/tests/zr_temperature_test/zr_temperature_test.go index a3850f1cb7b..d23599054c9 100644 --- a/feature/platform/transceiver/tests/zr_temperature_test/zr_temperature_test.go +++ b/feature/platform/transceiver/tests/zr_temperature_test/zr_temperature_test.go @@ -15,11 +15,11 @@ package zr_temperature_test import ( - "fmt" "reflect" "testing" "time" + "github.com/openconfig/featureprofiles/internal/components" "github.com/openconfig/featureprofiles/internal/deviations" "github.com/openconfig/featureprofiles/internal/fptest" "github.com/openconfig/featureprofiles/internal/samplestream" @@ -33,7 +33,7 @@ const ( sensorType = oc.PlatformTypes_OPENCONFIG_HARDWARE_COMPONENT_SENSOR dp16QAM = 1 targetOutputPower = -10 - frequency = 193100000 + frequency = 193500000 ) func TestMain(m *testing.M) { @@ -50,12 +50,13 @@ func interfaceConfig(t *testing.T, dut1 *ondatra.DUTDevice, dp *ondatra.Port) { i.Enabled = ygot.Bool(true) i.Type = oc.IETFInterfaces_InterfaceType_ethernetCsmacd gnmi.Replace(t, dut1, gnmi.OC().Interface(dp.Name()).Config(), i) - OCcomponent := opticalChannelComponentFromPort(t, dut1, dp) + OCcomponent := components.OpticalChannelComponentFromPort(t, dut1, dp) gnmi.Replace(t, dut1, gnmi.OC().Component(OCcomponent).OpticalChannel().Config(), &oc.Component_OpticalChannel{ TargetOutputPower: ygot.Float64(targetOutputPower), Frequency: ygot.Uint64(frequency), }) } + func verifyTemperatureSensorValue(t *testing.T, pStream *samplestream.SampleStream[float64], sensorName string) float64 { temperatureSample := pStream.Next() if temperatureSample == nil { @@ -105,27 +106,33 @@ func TestZRTemperatureState(t *testing.T) { } } p1StreamInstant := samplestream.New(t, dut1, component1.Temperature().Instant().State(), 10*time.Second) - p1StreamAvg := samplestream.New(t, dut1, component1.Temperature().Avg().State(), 10*time.Second) - p1StreamMin := samplestream.New(t, dut1, component1.Temperature().Min().State(), 10*time.Second) - p1StreamMax := samplestream.New(t, dut1, component1.Temperature().Max().State(), 10*time.Second) temperatureInstant := verifyTemperatureSensorValue(t, p1StreamInstant, "Instant") t.Logf("Port1 dut1 %s Instant Temperature: %v", dp1.Name(), temperatureInstant) - temperatureMax := verifyTemperatureSensorValue(t, p1StreamMax, "Max") - t.Logf("Port1 dut1 %s Max Temperature: %v", dp1.Name(), temperatureMax) - temperatureMin := verifyTemperatureSensorValue(t, p1StreamMin, "Min") - t.Logf("Port1 dut1 %s Min Temperature: %v", dp1.Name(), temperatureMin) - temperatureAvg := verifyTemperatureSensorValue(t, p1StreamAvg, "Avg") - t.Logf("Port1 dut1 %s Avg Temperature: %v", dp1.Name(), temperatureAvg) - if temperatureAvg >= temperatureMin && temperatureAvg <= temperatureMax { - t.Logf("The average is between the maximum and minimum values") + if deviations.MissingZROpticalChannelTunableParametersTelemetry(dut1) { + t.Log("Skipping Min/Max/Avg Tunable Parameters Telemetry validation. Deviation MissingZROpticalChannelTunableParametersTelemetry enabled.") } else { - t.Fatalf("The average is not between the maximum and minimum values, Avg:%v Max:%v Min:%v", temperatureAvg, temperatureMax, temperatureMin) + p1StreamAvg := samplestream.New(t, dut1, component1.Temperature().Avg().State(), 10*time.Second) + p1StreamMin := samplestream.New(t, dut1, component1.Temperature().Min().State(), 10*time.Second) + p1StreamMax := samplestream.New(t, dut1, component1.Temperature().Max().State(), 10*time.Second) + + temperatureMax := verifyTemperatureSensorValue(t, p1StreamMax, "Max") + t.Logf("Port1 dut1 %s Max Temperature: %v", dp1.Name(), temperatureMax) + temperatureMin := verifyTemperatureSensorValue(t, p1StreamMin, "Min") + t.Logf("Port1 dut1 %s Min Temperature: %v", dp1.Name(), temperatureMin) + temperatureAvg := verifyTemperatureSensorValue(t, p1StreamAvg, "Avg") + t.Logf("Port1 dut1 %s Avg Temperature: %v", dp1.Name(), temperatureAvg) + if temperatureAvg >= temperatureMin && temperatureAvg <= temperatureMax { + t.Logf("The average is between the maximum and minimum values") + } else { + t.Fatalf("The average is not between the maximum and minimum values, Avg:%v Max:%v Min:%v", temperatureAvg, temperatureMax, temperatureMin) + } + p1StreamMin.Close() + p1StreamMax.Close() + p1StreamAvg.Close() } - p1StreamMin.Close() - p1StreamMax.Close() - p1StreamAvg.Close() p1StreamInstant.Close() } + func TestZRTemperatureStateInterfaceFlap(t *testing.T) { dut1 := ondatra.DUT(t, "dut") dp1 := dut1.Port(t, "port1") @@ -168,12 +175,16 @@ func TestZRTemperatureStateInterfaceFlap(t *testing.T) { gnmi.Await(t, dut1, gnmi.OC().Interface(dp1.Name()).OperStatus().State(), intUpdateTime, oc.Interface_OperStatus_DOWN) temperatureInstant := verifyTemperatureSensorValue(t, p1StreamInstant, "Instant") t.Logf("Port1 dut1 %s Instant Temperature: %v", dp1.Name(), temperatureInstant) - temperatureMax := verifyTemperatureSensorValue(t, p1StreamMax, "Max") - t.Logf("Port1 dut1 %s Max Temperature: %v", dp1.Name(), temperatureMax) - temperatureMin := verifyTemperatureSensorValue(t, p1StreamMin, "Min") - t.Logf("Port1 dut1 %s Min Temperature: %v", dp1.Name(), temperatureMin) - temperatureAvg := verifyTemperatureSensorValue(t, p1StreamAvg, "Avg") - t.Logf("Port1 dut1 %s Avg Temperature: %v", dp1.Name(), temperatureAvg) + if deviations.MissingZROpticalChannelTunableParametersTelemetry(dut1) { + t.Log("Skipping Min/Max/Avg Tunable Parameters Telemetry validation. Deviation MissingZROpticalChannelTunableParametersTelemetry enabled.") + } else { + temperatureMax := verifyTemperatureSensorValue(t, p1StreamMax, "Max") + t.Logf("Port1 dut1 %s Max Temperature: %v", dp1.Name(), temperatureMax) + temperatureMin := verifyTemperatureSensorValue(t, p1StreamMin, "Min") + t.Logf("Port1 dut1 %s Min Temperature: %v", dp1.Name(), temperatureMin) + temperatureAvg := verifyTemperatureSensorValue(t, p1StreamAvg, "Avg") + t.Logf("Port1 dut1 %s Avg Temperature: %v", dp1.Name(), temperatureAvg) + } i = d.GetOrCreateInterface(dp1.Name()) i.Enabled = ygot.Bool(true) i.Type = oc.IETFInterfaces_InterfaceType_ethernetCsmacd @@ -182,42 +193,19 @@ func TestZRTemperatureStateInterfaceFlap(t *testing.T) { gnmi.Await(t, dut1, gnmi.OC().Interface(dp1.Name()).OperStatus().State(), intUpdateTime, oc.Interface_OperStatus_UP) temperatureInstant = verifyTemperatureSensorValue(t, p1StreamInstant, "Instant") t.Logf("Port1 dut1 %s Instant Temperature: %v", dp1.Name(), temperatureInstant) - temperatureMax = verifyTemperatureSensorValue(t, p1StreamMax, "Max") - t.Logf("Port1 dut1 %s Max Temperature: %v", dp1.Name(), temperatureMax) - temperatureMin = verifyTemperatureSensorValue(t, p1StreamMin, "Min") - t.Logf("Port1 dut1 %s Min Temperature: %v", dp1.Name(), temperatureMin) - temperatureAvg = verifyTemperatureSensorValue(t, p1StreamAvg, "Avg") - t.Logf("Port1 dut1 %s Avg Temperature: %v", dp1.Name(), temperatureAvg) - if temperatureAvg >= temperatureMin && temperatureAvg <= temperatureMax { - t.Logf("The average is between the maximum and minimum values") + if deviations.MissingZROpticalChannelTunableParametersTelemetry(dut1) { + t.Log("Skipping Min/Max/Avg Tunable Parameters Telemetry validation. Deviation MissingZROpticalChannelTunableParametersTelemetry enabled.") } else { - t.Fatalf("The average is not between the maximum and minimum values") - } -} - -func opticalChannelComponentFromPort(t *testing.T, dut *ondatra.DUTDevice, p *ondatra.Port) string { - t.Helper() - if deviations.MissingPortToOpticalChannelMapping(dut) { - switch dut.Vendor() { - case ondatra.ARISTA: - transceiverName := gnmi.Get(t, dut, gnmi.OC().Interface(p.Name()).Transceiver().State()) - return fmt.Sprintf("%s-Optical0", transceiverName) - default: - t.Fatal("Manual Optical channel name required when deviation missing_port_to_optical_channel_component_mapping applied.") - } - } - compName := gnmi.Get(t, dut, gnmi.OC().Interface(p.Name()).HardwarePort().State()) - for { - comp, ok := gnmi.Lookup(t, dut, gnmi.OC().Component(compName).State()).Val() - if !ok { - t.Fatalf("Recursive optical channel lookup failed for port: %s, component %s not found.", p.Name(), compName) - } - if comp.GetType() == oc.PlatformTypes_OPENCONFIG_HARDWARE_COMPONENT_OPTICAL_CHANNEL { - return compName - } - if comp.GetParent() == "" { - t.Fatalf("Recursive optical channel lookup failed for port: %s, parent of component %s not found.", p.Name(), compName) + temperatureMax := verifyTemperatureSensorValue(t, p1StreamMax, "Max") + t.Logf("Port1 dut1 %s Max Temperature: %v", dp1.Name(), temperatureMax) + temperatureMin := verifyTemperatureSensorValue(t, p1StreamMin, "Min") + t.Logf("Port1 dut1 %s Min Temperature: %v", dp1.Name(), temperatureMin) + temperatureAvg := verifyTemperatureSensorValue(t, p1StreamAvg, "Avg") + t.Logf("Port1 dut1 %s Avg Temperature: %v", dp1.Name(), temperatureAvg) + if temperatureAvg >= temperatureMin && temperatureAvg <= temperatureMax { + t.Logf("The average is between the maximum and minimum values") + } else { + t.Fatalf("The average is not between the maximum and minimum values") } - compName = comp.GetParent() } } diff --git a/feature/platform/transceiver/tests/zr_tunable_parameters_test/README.md b/feature/platform/transceiver/tests/zr_tunable_parameters_test/README.md index b396ae4612d..0e47ff590d9 100644 --- a/feature/platform/transceiver/tests/zr_tunable_parameters_test/README.md +++ b/feature/platform/transceiver/tests/zr_tunable_parameters_test/README.md @@ -1,76 +1,78 @@ -# TRANSCEIVER-5: Configuration: 400ZR channel frequency, output TX launch power and operational mode setting. +# TRANSCEIVER-5: Configuration: 400ZR channel frequency, output TX launch power and operational mode setting. ## Summary -Validate setting 400ZR tunable parameters channel frequency, output TX -launch power and operational mode and verify corresponding telemetry values. +Validate setting 400ZR tunable parameters channel frequency, output TX launch +power and operational mode and verify corresponding telemetry values. ### Goals -* Verify full C band frequency tunability for 100GHz line system grid. -* Verify full C band frequency tunability for 75GHz line system grid. -* Verify adjustable range of transmit output power across -13 to -9 dBm - in steps of 1 dB. -* Verify that the ZR module Host Interface ID and Media Interface ID - combination to ZR module AppSel mapping can be configured through the OC - `operational-mode`. `operational-mode` is a construct in OpenConfig that masks - features related to line port transmission. OC operational modes provides a - platform-defined summary of information such as symbol rate, modulation, - pulse shaping, etc. + +* Verify full C band frequency tunability for 100GHz line system grid. +* Verify full C band frequency tunability for 75GHz line system grid. +* Verify adjustable range of transmit output power across -13 to -9 dBm in + steps of 1 dB. +* Verify that the ZR module Host Interface ID and Media Interface ID + combination to ZR module AppSel mapping can be configured through the OC + `operational-mode`. `operational-mode` is a construct in OpenConfig that + masks features related to line port transmission. OC operational modes + provides a platform-defined summary of information such as symbol rate, + modulation, pulse shaping, etc. **Note** For standard ZR, OIF 400ZR with C-FEC is the default mode however as we move to 400ZR++ and 800ZR, optic AppSel code would need to be configured explicitly through OC operational mode. - ## TRANSCEIVER-5.1 -* Connect two ZR interfaces using a duplex LC fiber jumper such that TX - output power of one is the RX input power of the other module. Connection - between the modules should pass through an optical switch that can be - controlled through automation to simulate a fiber cut. +* Connect two ZR interfaces using a duplex LC fiber jumper such that TX output + power of one is the RX input power of the other module. Connection between + the modules should pass through an optical switch that can be controlled + through automation to simulate a fiber cut. * To establish a point to point ZR link ensure the following: - * Both transceivers states are enabled. - * Validate setting 400ZR optics module tunable laser center frequency + + * Both transceivers states are enabled. + * Validate setting 400ZR optics module tunable laser center frequency across frequency range 196.100 - 191.400 THz for 100GHz grid. - * Validate setting 400ZR optics module tunable laser center frequency - across frequency range 196.100 - 191.375 THz for 75GHz grid. - * Specific frequency details can be found in 400ZR implementation + * Validate setting 400ZR optics module tunable laser center frequency + across frequency range 196.100 - 191.375 THz for 75GHz grid. + * Specific frequency details can be found in 400ZR implementation agreement under sections 15.1 ad 15.2 Operating frequency channel definitions. Link to IA below, - * https://www.oiforum.com/wp-content/uploads/OIF-400ZR-01.0_reduced2.pdf - * Validate adjustable range of transmit output power across -13 to -9 dBm + * https://www.oiforum.com/wp-content/uploads/OIF-400ZR-01.0_reduced2.pdf + * Validate adjustable range of transmit output power across -13 to -9 dBm range in steps of 1dB. So the module’s output power will be set to -13, -12, -11, -10, -9 dBm in each step. As an example this can be validated - for the module's default frequency of 193.1 THz. + for the module's default frequency of 193.1 THz. * With the ZR link established as explained above, for each configured - frequency and TX output power value verify that the following ZR - transceiver telemetry paths exist and are streamed for both the ZR optics. - * Frequency + frequency and TX output power value verify that the following ZR transceiver + telemetry paths exist and are streamed for both the ZR optics. + + * Frequency * /components/component/optical-channel/state/frequency * /components/component/optical-channel/state/carrier-frequency-offset/instant * /components/component/optical-channel/state/carrier-frequency-offset/avg * /components/component/optical-channel/state/carrier-frequency-offset/min * /components/component/optical-channel/state/carrier-frequency-offset/max - * TX Output Power + * TX Output Power * /components/component/optical-channel/state/output-power/instant * /components/component/optical-channel/state/output-power/avg * /components/component/optical-channel/state/output-power/min * /components/component/optical-channel/state/output-power/max - * Operational Mode + * Operational Mode * /components/component/optical-channel/state/operational-mode -* With above streamed data verify - * For each center frequency, laser frequency offset should not be more than - +/- 1.8 GHz max. - * For each center frequency, streamed value should be in Mhz units. Test - should fail if the streamed value is in Hz or THz units. As an example - 193.1 THz would be 193100000 in MHz. - * When set to a specific target output power, transmit power control - absolute accuracy should be within +/- 1 dBm of the target value. - * For reported data check for validity: min <= avg/instant <= max - - +* With above streamed data verify + + * For each center frequency, laser frequency offset should not be more + than +/- 1.8 GHz max. + * For each center frequency, streamed value should be in Mhz units. Test + should fail if the streamed value is in Hz or THz units. As an example + 193.1 THz would be 193100000 in MHz. + * When set to a specific target output power, transmit power control + absolute accuracy should be within +/- 1 dBm of the target value. + * For reported data check for validity: min <= avg/instant <= max + ## TRANSCEIVER-5.2 * When the modules or the devices are still in a boot stage, they must not @@ -90,8 +92,8 @@ explicitly through OC operational mode. * Verify the ZR optics frequency and TX output power telemetry values are set in the normal range. * Disable or shut down the interface on the DUT. - * Verify with interfaces in down state both optics are streaming uint 0 - value for frequency. + * Verify with interfaces in down state both optics are still streaming + configured value for frequency. * Verify for the TX output power with interface in down state a decimal64 value of -40 dB is streamed. * Re-enable the interfaces on the DUT. @@ -99,13 +101,14 @@ explicitly through OC operational mode. power as per the configuration and related telemetry values are updated to the value in the normal range again. -* With above test also verify - * Laser frequency offset should not be more than +/- 1.8 GHz max from the - configured centre frequency. - * When set to a specific target output power, transmit power control - absolute accuracy should be within +/- 1 dBm of the target configured - output power. - * For reported data check for validity: min <= avg/instant <= max +* With above test also verify + + * Laser frequency offset should not be more than +/- 1.8 GHz max from the + configured centre frequency. + * When set to a specific target output power, transmit power control + absolute accuracy should be within +/- 1 dBm of the target configured + output power. + * For reported data check for validity: min <= avg/instant <= max ## TRANSCEIVER-5.4 @@ -117,44 +120,65 @@ explicitly through OC operational mode. in the normal range. * Simulate a fiber cut using the optical switch that sits in-between the DUT ports. - * Verify with link in down state due to fiber cut both optics are streaming - uint64 for frequency and decimal64 for TX output power. + * Verify with link in down state due to fiber cut both optics are + streaming uint64 for frequency and decimal64 for TX output power. * Re-enable the optical switch connection to clear the fiber cut fault. * Verify the ZR optics is able to stay tuned to the correct frequency and TX output power as per the configuration. -* With above test also verify - * Laser frequency offset should not be more than +/- 1.8 GHz max from the - configured centre frequency. - * When set to a specific target output power, transmit power control - absolute accuracy should be within +/- 1 dBm of the target configured - output power. - * For reported data check for validity: min <= avg/instant <= max - -**Note:** For min, max, and avg values, 10 second sampling is preferred. If - 10 seconds is not supported, the sampling interval used must be - communicated. - -## Config Parameter coverage - -* /components/component/transceiver/config/enabled -* /components/component/optical-channel/config/frequency -* /components/component/optical-channel/config/target-output-power -* /components/component/optical-channel/config/operational-mode - -## Telemetry Parameter coverage - -* Frequency - * /components/component/optical-channel/state/frequency - * /components/component/optical-channel/state/carrier-frequency-offset/instant - * /components/component/optical-channel/state/carrier-frequency-offset/avg - * /components/component/optical-channel/state/carrier-frequency-offset/min - * /components/component/optical-channel/state/carrier-frequency-offset/max -* TX Output Power - * /components/component/optical-channel/state/output-power/instant - * /components/component/optical-channel/state/output-power/avg - * /components/component/optical-channel/state/output-power/min - * /components/component/optical-channel/state/output-power/max -* Operational Mode - * /components/component/optical-channel/config/operational-mode - * /components/component/optical-channel/state/operational-mode \ No newline at end of file +* With above test also verify + + * Laser frequency offset should not be more than +/- 1.8 GHz max from the + configured centre frequency. + * When set to a specific target output power, transmit power control + absolute accuracy should be within +/- 1 dBm of the target configured + output power. + * For reported data check for validity: min <= avg/instant <= max + +**Note:** For min, max, and avg values, 10 second sampling is preferred. If 10 +seconds is not supported, the sampling interval used must be communicated. + +## OpenConfig Path and RPC Coverage + +```yaml +paths: + /components/component/transceiver/config/enabled: + platform_type: ["TRANSCEIVER"] + /components/component/optical-channel/config/frequency: + platform_type: ["OPTICAL_CHANNEL"] + /components/component/optical-channel/config/target-output-power: + platform_type: ["OPTICAL_CHANNEL"] + /components/component/optical-channel/config/operational-mode: + platform_type: ["OPTICAL_CHANNEL"] + /components/component/optical-channel/state/frequency: + platform_type: ["OPTICAL_CHANNEL"] + /components/component/optical-channel/state/carrier-frequency-offset/instant: + platform_type: ["OPTICAL_CHANNEL"] + /components/component/optical-channel/state/carrier-frequency-offset/avg: + platform_type: ["OPTICAL_CHANNEL"] + /components/component/optical-channel/state/carrier-frequency-offset/min: + platform_type: ["OPTICAL_CHANNEL"] + /components/component/optical-channel/state/carrier-frequency-offset/max: + platform_type: ["OPTICAL_CHANNEL"] + /components/component/optical-channel/state/output-power/instant: + platform_type: ["OPTICAL_CHANNEL"] + /components/component/optical-channel/state/output-power/avg: + platform_type: ["OPTICAL_CHANNEL"] + /components/component/optical-channel/state/output-power/min: + platform_type: ["OPTICAL_CHANNEL"] + /components/component/optical-channel/state/output-power/max: + platform_type: ["OPTICAL_CHANNEL"] + /components/component/optical-channel/state/operational-mode: + platform_type: ["OPTICAL_CHANNEL"] + +rpcs: + gnmi: + gNMI.Set: + replace: true + gNMI.Subscribe: + on_change: true +``` + +## Required DUT platform + +FFF diff --git a/feature/platform/transceiver/tests/zr_tunable_parameters_test/zr_tunable_parameters_test.go b/feature/platform/transceiver/tests/zr_tunable_parameters_test/zr_tunable_parameters_test.go index 04c40b069f1..fe01013e2be 100644 --- a/feature/platform/transceiver/tests/zr_tunable_parameters_test/zr_tunable_parameters_test.go +++ b/feature/platform/transceiver/tests/zr_tunable_parameters_test/zr_tunable_parameters_test.go @@ -182,12 +182,12 @@ func Test400ZRInterfaceFlap(t *testing.T) { // Disable or shut down the interface on the DUT. gnmi.Replace(t, dut, gnmi.OC().Interface(p1.Name()).Enabled().Config(), false) gnmi.Replace(t, dut, gnmi.OC().Interface(p2.Name()).Enabled().Config(), false) - // Verify with interfaces in down state both optics are streaming uint 0 - // value for frequency. + // Verify with interfaces in down state both optics are still streaming + // configured value for frequency. // Verify for the TX output power with interface in down state a decimal64 // value of -40 dB is streamed. t.Run("Telemetry during interface disabled", func(t *testing.T) { - validateOpticsTelemetry(t, []*samplestream.SampleStream[*oc.Component]{streamOC1, streamOC2}, 0, -40) + validateOpticsTelemetry(t, []*samplestream.SampleStream[*oc.Component]{streamOC1, streamOC2}, frequency, -40) }) // Re-enable the interfaces on the DUT. gnmi.Replace(t, dut, gnmi.OC().Interface(p1.Name()).Enabled().Config(), true) diff --git a/feature/staticroute/otg_tests/basic_static_route_support_test/basic_static_route_support_test.go b/feature/staticroute/otg_tests/basic_static_route_support_test/basic_static_route_support_test.go index f801c2fbdc8..396ddfbaea4 100644 --- a/feature/staticroute/otg_tests/basic_static_route_support_test/basic_static_route_support_test.go +++ b/feature/staticroute/otg_tests/basic_static_route_support_test/basic_static_route_support_test.go @@ -22,33 +22,34 @@ import ( ) const ( - ipv4PrefixLen = 30 - ipv6PrefixLen = 126 - isisName = "DEFAULT" - dutAreaAddr = "49.0001" - ateAreaAddr = "49.0002" - dutSysID = "1920.0000.2001" - ate1SysID = "640000000001" - ate2SysID = "640000000002" - v4Route = "203.0.113.0" - v4TrafficStart = "203.0.113.1" - v4RoutePrefix = uint32(24) - v6Route = "2001:db8:128:128::0" - v6TrafficStart = "2001:db8:128:128::1" - v6RoutePrefix = uint32(64) - v4LoopbackRoute = "198.51.100.100" - v4LoopbackRoutePrefix = uint32(32) - v6LoopbackRoute = "2001:db8:64:64::1" - v6LoopbackRoutePrefix = uint32(128) - v4Flow = "v4Flow" - v6Flow = "v6Flow" - trafficDuration = 2 * time.Minute - lossTolerance = float64(1) - ecmpTolerance = uint64(2) - port1Tag = "0x101" - port2Tag = "0x102" - dummyV6 = "2001:db8::192:0:2:d" - dummyMAC = "00:1A:11:00:0A:BC" + ipv4PrefixLen = 30 + ipv6PrefixLen = 126 + isisName = "DEFAULT" + dutAreaAddr = "49.0001" + ateAreaAddr = "49.0002" + dutSysID = "1920.0000.2001" + ate1SysID = "640000000001" + ate2SysID = "640000000002" + v4Route = "203.0.113.0" + v4TrafficStart = "203.0.113.1" + v4RoutePrefix = uint32(24) + v6Route = "2001:db8:128:128::0" + v6TrafficStart = "2001:db8:128:128::1" + v6RoutePrefix = uint32(64) + v4LoopbackRoute = "198.51.100.100" + v4LoopbackRoutePrefix = uint32(32) + v6LoopbackRoute = "2001:db8:64:64::1" + v6LoopbackRoutePrefix = uint32(128) + v4Flow = "v4Flow" + v6Flow = "v6Flow" + trafficDuration = 2 * time.Minute + lossTolerance = float64(1) + ecmpTolerance = uint64(2) + port1Tag = "0x101" + port2Tag = "0x102" + dummyV6 = "2001:db8::192:0:2:d" + dummyMAC = "00:1A:11:00:0A:BC" + explicitMetricTolerance = float64(2) ) var ( @@ -428,9 +429,10 @@ func (td *testData) testStaticRouteECMP(t *testing.T) { defer td.deleteStaticRoutes(t) t.Run("Telemetry", func(t *testing.T) { + sp := gnmi.OC().NetworkInstance(deviations.DefaultNetworkInstance(td.dut)).Protocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_STATIC, deviations.StaticProtocolName(td.dut)) - gnmi.Await(t, td.dut, sp.Static(td.staticIPv4.cidr(t)).Prefix().State(), 30*time.Second, td.staticIPv4.cidr(t)) - gnmi.Await(t, td.dut, sp.Static(td.staticIPv6.cidr(t)).Prefix().State(), 30*time.Second, td.staticIPv6.cidr(t)) + gnmi.Await(t, td.dut, sp.Static(td.staticIPv4.cidr(t)).Prefix().State(), 120*time.Second, td.staticIPv4.cidr(t)) + gnmi.Await(t, td.dut, sp.Static(td.staticIPv6.cidr(t)).Prefix().State(), 120*time.Second, td.staticIPv6.cidr(t)) // Validate both the routes i.e. ipv4-route-[a|b] are configured and reported // correctly @@ -518,12 +520,21 @@ func (td *testData) testStaticRouteWithMetric(t *testing.T) { td.configureStaticRouteToATEP1AndP2(t) defer td.deleteStaticRoutes(t) - const port2Metric = uint32(100) - + var port2Metric = uint32(100) sp := gnmi.OC().NetworkInstance(deviations.DefaultNetworkInstance(td.dut)).Protocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_STATIC, deviations.StaticProtocolName(td.dut)) // Configure metric of ipv4-route-b and ipv6-route-b to 100 batch := &gnmi.SetBatch{} + if deviations.StaticRouteWithExplicitMetric(td.dut) { + // per the cisco specifications setting the metric is equivlent to setting the weight, so in this case + // we want the majority of the traffic to go over port 1 so setting the metric to 100 and port 2 as 1 + var port1Metric = uint32(100) + port2Metric = uint32(1) + gnmi.BatchReplace(batch, sp.Static(td.staticIPv4.cidr(t)).NextHop("0").Metric().Config(), port1Metric) + gnmi.BatchReplace(batch, sp.Static(td.staticIPv6.cidr(t)).NextHop("0").Metric().Config(), port1Metric) + + } + gnmi.BatchReplace(batch, sp.Static(td.staticIPv4.cidr(t)).NextHop("1").Metric().Config(), port2Metric) gnmi.BatchReplace(batch, sp.Static(td.staticIPv6.cidr(t)).NextHop("1").Metric().Config(), port2Metric) batch.Set(t, td.dut) @@ -567,9 +578,21 @@ func (td *testData) testStaticRouteWithMetric(t *testing.T) { if !ok { t.Errorf("Port1 IPv4 egress tracking counter not found: %v", portCounters) } - if got, want := float64(port1Counter)*100/float64(rxV4), float64(100); got+lossTolerance < want { - t.Errorf("IPv4 traffic on port1, got: %v, want: %v", got, want) + + if deviations.StaticRouteWithExplicitMetric(td.dut) { + // validate traffic + got, want := float64(port1Counter)*100/float64(rxV4), float64(100) + expectedMinTraffic := want * (1 - explicitMetricTolerance/100) + if got < expectedMinTraffic { + t.Errorf("IPv4 traffic on port1, got: %v%%, expected to be at least %v%%", got, expectedMinTraffic) + } + } else { + // validate traffic default behavior + if got, want := float64(port1Counter)*100/float64(rxV4), float64(100); got+lossTolerance < want { + t.Errorf("IPv4 traffic on port1, got: %v, want: %v", got, want) + } } + // Validate that traffic is received from DUT on port-1 and not on port-2 portCounters = egressTrackingCounters(t, td.ate, v6Flow) _, rxV6 := otgutils.GetFlowStats(t, td.ate.OTG(), v6Flow, 20*time.Second) @@ -577,9 +600,21 @@ func (td *testData) testStaticRouteWithMetric(t *testing.T) { if !ok { t.Errorf("Port1 IPv6 egress tracking counter not found: %v", portCounters) } - if got, want := float64(port1Counter)*100/float64(rxV6), float64(100); got+lossTolerance < want { - t.Errorf("IPv6 traffic on port1, got: %v, want: %v", got, want) + if deviations.StaticRouteWithExplicitMetric(td.dut) { + // validate traffic + got, want := float64(port1Counter)*100/float64(rxV6), float64(100) + expectedMinTraffic := want * (1 - explicitMetricTolerance/100) + if got < expectedMinTraffic { + t.Errorf("IPv6 traffic on port1, got: %v%%, expected to be at least %v%%", got, expectedMinTraffic) + } + + } else { + // validate traffic default behavior + if got, want := float64(port1Counter)*100/float64(rxV6), float64(100); got+lossTolerance < want { + t.Errorf("IPv6 traffic on port1, got: %v, want: %v", got, want) + } } + }) } @@ -726,6 +761,9 @@ func (td *testData) testIPv6StaticRouteWithIPv4NextHop(t *testing.T) { // IPv4 address of ATE port-1 // Change the IPv6 next-hop of the ipv6-route-b with the next hop set to the // IPv4 address of ATE port-2 + if deviations.IPv6StaticRouteWithIPv4NextHopUnsupported(td.dut) { + t.Skip("Skipping Ipv6 with Ipv4 route unsupported. Deviation IPv4StaticRouteWithIPv6NextHopUnsupported enabled.") + } b := &gnmi.SetBatch{} var v6Cfg *cfgplugins.StaticRouteCfg if deviations.IPv6StaticRouteWithIPv4NextHopRequiresStaticARP(td.dut) { @@ -853,6 +891,9 @@ func (td *testData) testIPv4StaticRouteWithIPv6NextHop(t *testing.T) { // IPv6 address of ATE port-1 // Change the IPv4 next-hop of the ipv4-route-b with the next hop set to the // IPv6 address of ATE port-2 + if deviations.IPv4StaticRouteWithIPv6NextHopUnsupported(td.dut) { + t.Skip("Skipping Ipv4 with Ipv6 route unsupported. Deviation IPv4StaticRouteWithIPv6NextHopUnsupported enabled.") + } v4Cfg := &cfgplugins.StaticRouteCfg{ NetworkInstance: deviations.DefaultNetworkInstance(td.dut), Prefix: td.staticIPv4.cidr(t), @@ -921,7 +962,9 @@ func (td *testData) testIPv4StaticRouteWithIPv6NextHop(t *testing.T) { } func (td *testData) testStaticRouteWithDropNextHop(t *testing.T) { - + if deviations.StaticRouteWithDropNhUnsupported(td.dut) { + t.Skip("Skipping test static route with drop nexthop. Deviation StaticRouteWithDropNhUnsupported enabled.") + } b := &gnmi.SetBatch{} // Configure IPv4 static routes: // * Configure one IPv4 static route i.e. ipv4-route-a on the DUT for diff --git a/feature/staticroute/otg_tests/basic_static_route_support_test/metadata.textproto b/feature/staticroute/otg_tests/basic_static_route_support_test/metadata.textproto index 1fce39fd6f2..af2d54b1fdc 100644 --- a/feature/staticroute/otg_tests/basic_static_route_support_test/metadata.textproto +++ b/feature/staticroute/otg_tests/basic_static_route_support_test/metadata.textproto @@ -25,4 +25,18 @@ platform_exceptions: { missing_static_route_drop_next_hop_telemetry: true } } +platform_exceptions: { + platform: { + vendor: CISCO + } + deviations: { + ipv4_static_route_with_ipv6_nh_unsupported: true + ipv6_static_route_with_ipv4_nh_unsupported: true + static_route_with_drop_nh: true + unsupported_static_route_next_hop_recurse: true + static_route_with_explicit_metric: true + interface_ref_config_unsupported: true + + } +} tags: TAGS_DATACENTER_EDGE diff --git a/feature/system/gnmi/metadata/tests/large_set_consistency_test/large_set_consistency_test.go b/feature/system/gnmi/metadata/tests/large_set_consistency_test/large_set_consistency_test.go index 2b0763f68b6..84b7e7af943 100644 --- a/feature/system/gnmi/metadata/tests/large_set_consistency_test/large_set_consistency_test.go +++ b/feature/system/gnmi/metadata/tests/large_set_consistency_test/large_set_consistency_test.go @@ -240,17 +240,21 @@ func getNotificationsUsingGNMIGet(t *testing.T, gnmiClient gpb.GNMIClient, dut * return getResponse.GetNotification() } -// checkMetadata checks protobuf-metadata -func checkMetadata(t *testing.T, gnmiClient gpb.GNMIClient, dut *ondatra.DUTDevice, done *atomic.Int64) { +func checkMetadata1(t *testing.T, gnmiClient gpb.GNMIClient, dut *ondatra.DUTDevice, done *atomic.Int64) { t.Helper() - got, getRespTimeStamp := extractMetadataAnnotation(t, gnmiClient, dut) - want := metadata1 - t.Logf("SetResp: %v, getResp: %v ", done.Load(), getRespTimeStamp) - if done.Load() > 0 && done.Load() < getRespTimeStamp { - want = metadata2 + t.Logf("getResp: %v ", getRespTimeStamp) + if got != want && done.Load() == 0 { + t.Errorf("extractMetadataAnnotation: got %v, want %v", got, want) } +} + +func checkMetadata2(t *testing.T, gnmiClient gpb.GNMIClient, dut *ondatra.DUTDevice) { + t.Helper() + got, getRespTimeStamp := extractMetadataAnnotation(t, gnmiClient, dut) + want := metadata2 + t.Logf("getResp: %v ", getRespTimeStamp) if got != want { t.Errorf("extractMetadataAnnotation: got %v, want %v", got, want) } @@ -280,7 +284,7 @@ func TestLargeSetConsistency(t *testing.T) { if _, err := gnmiClient.Set(context.Background(), gpbSetRequest); err != nil { t.Fatalf("gnmi.Set unexpected error: %v", err) } - checkMetadata(t, gnmiClient, dut, done) + checkMetadata1(t, gnmiClient, dut, done) var wg sync.WaitGroup ch := make(chan struct{}, 1) @@ -300,7 +304,6 @@ func TestLargeSetConsistency(t *testing.T) { done.Store(setResp.GetTimestamp()) }() - // sending 4 Get requests concurrently every 5 seconds. for i := 0; i < 4; i++ { wg.Add(1) go func(i int) { @@ -312,14 +315,14 @@ func TestLargeSetConsistency(t *testing.T) { return default: t.Logf("[%d - running] checking config protobuf-metadata", i) - checkMetadata(t, gnmiClient, dut, done) - time.Sleep(5 * time.Second) + time.Sleep(5 * time.Millisecond) + checkMetadata1(t, gnmiClient, dut, done) } } }(i) } wg.Wait() - - checkMetadata(t, gnmiClient, dut, done) + time.Sleep(5 * time.Second) + checkMetadata2(t, gnmiClient, dut) } diff --git a/feature/system/management/otg_tests/management_ha_test/management_ha_test.go b/feature/system/management/otg_tests/management_ha_test/management_ha_test.go index a6cf984cecc..56dc565f366 100644 --- a/feature/system/management/otg_tests/management_ha_test/management_ha_test.go +++ b/feature/system/management/otg_tests/management_ha_test/management_ha_test.go @@ -41,7 +41,6 @@ const ( prefixesCount = 1 pathID = 1 defaultRoute = "0:0:0:0:0:0:0:0" - dutAS = 65501 ) var ( @@ -53,7 +52,7 @@ var ( IPv6Len: 128, } - mgmtVRF = "mgmtvrf1" + mgmtVRF = "mvrf1" bgpPorts = []string{"port1", "port2"} lossTolerance = float64(1) @@ -91,11 +90,12 @@ func TestManagementHA1(t *testing.T) { configureEmulatedNetworks(bs) - bs.DUTConf.GetOrCreateNetworkInstance(mgmtVRF).GetOrCreateProtocol(cfgplugins.PTBGP, "BGP").GetOrCreateBgp().GetOrCreateGlobal().SetAs(dutAS) + if deviations.ExplicitEnableBGPOnDefaultVRF(dut) { + bs.DUTConf.GetOrCreateNetworkInstance(deviations.DefaultNetworkInstance(dut)).GetOrCreateProtocol(cfgplugins.PTBGP, "BGP").GetOrCreateBgp().GetOrCreateGlobal().SetAs(cfgplugins.DutAS) + } if dut.Vendor() != ondatra.NOKIA { - bs.DUTConf.GetOrCreateNetworkInstance(mgmtVRF).SetRouteDistinguisher(fmt.Sprintf("%d:%d", dutAS, 100)) + bs.DUTConf.GetOrCreateNetworkInstance(mgmtVRF).SetRouteDistinguisher(fmt.Sprintf("%d:%d", cfgplugins.DutAS, 100)) } - bs.DUTConf.GetOrCreateNetworkInstance(mgmtVRF).GetOrCreateProtocol(cfgplugins.PTBGP, "BGP").GetOrCreateBgp().GetOrCreateGlobal().GetOrCreateAfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV4_UNICAST).Enabled = ygot.Bool(true) bs.PushAndStart(t) if verfied := verifyDUTBGPEstablished(t, bs.DUT, mgmtVRF); verfied { t.Log("DUT BGP sessions established") @@ -172,6 +172,10 @@ func TestManagementHA1(t *testing.T) { t.Errorf("Frames sent/received: got: %d, want: %d", framesRx, framesTx) } }) + + defer func() { + gnmi.Delete(t, dut, gnmi.OC().NetworkInstance(mgmtVRF).Config()) + }() } func createFlowV6(t *testing.T, bs *cfgplugins.BGPSession) { @@ -310,7 +314,6 @@ func advertiseDUTLoopbackToATE(t *testing.T, dut *ondatra.DUTDevice, bs *cfgplug stmt.GetOrCreateConditions().GetOrCreateMatchPrefixSet().SetPrefixSet("ps") gnmi.BatchUpdate(batchSet, gnmi.OC().RoutingPolicy().Config(), rp) - batchSet.Set(t, dut) if deviations.TableConnectionsUnsupported(dut) { stmt.GetOrCreateConditions().SetInstallProtocolEq(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_DIRECTLY_CONNECTED) stmt.GetOrCreateActions().PolicyResult = oc.RoutingPolicy_PolicyResultType_ACCEPT_ROUTE @@ -332,9 +335,8 @@ func advertiseDUTLoopbackToATE(t *testing.T, dut *ondatra.DUTDevice, bs *cfgplug tableConn1 := root.GetOrCreateNetworkInstance(mgmtVRF).GetOrCreateTableConnection(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_DIRECTLY_CONNECTED, oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_BGP, oc.Types_ADDRESS_FAMILY_IPV4) tableConn1.SetImportPolicy([]string{"rp"}) gnmi.BatchUpdate(batchSet, gnmi.OC().NetworkInstance(mgmtVRF).TableConnection(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_DIRECTLY_CONNECTED, oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_BGP, oc.Types_ADDRESS_FAMILY_IPV4).Config(), tableConn1) - - batchSet.Set(t, dut) } + batchSet.Set(t, dut) } func configureImportExportBGPPolicy(t *testing.T, bs *cfgplugins.BGPSession, dut *ondatra.DUTDevice) { diff --git a/feature/system/management/otg_tests/management_ha_test/metadata.textproto b/feature/system/management/otg_tests/management_ha_test/metadata.textproto index 4d10f5ec113..e9db4bd8c9f 100644 --- a/feature/system/management/otg_tests/management_ha_test/metadata.textproto +++ b/feature/system/management/otg_tests/management_ha_test/metadata.textproto @@ -17,8 +17,8 @@ platform_exceptions: { default_network_instance: "default" skip_set_rp_match_set_options: true skip_setting_disable_metric_propagation: true - set_metric_as_preference: true set_no_peer_group: true + explicit_enable_bgp_on_default_vrf: true } } platform_exceptions: { diff --git a/go.mod b/go.mod index 217b05894c9..f353236dae9 100644 --- a/go.mod +++ b/go.mod @@ -25,9 +25,9 @@ require ( github.com/openconfig/goyang v1.4.5 github.com/openconfig/gribi v1.0.0 github.com/openconfig/gribigo v0.0.0-20231213034307-d0abeba7f432 - github.com/openconfig/kne v0.1.17 + github.com/openconfig/kne v0.1.18 github.com/openconfig/models-ci v1.0.2-0.20231113233730-f0986391428e - github.com/openconfig/ondatra v0.5.6 + github.com/openconfig/ondatra v0.5.8 github.com/openconfig/replayer v0.0.0-20240110192655-4e9cf83d8d30 github.com/openconfig/testt v0.0.0-20220311054427-efbb1a32ec07 github.com/openconfig/ygnmi v0.11.1 @@ -35,6 +35,9 @@ require ( github.com/p4lang/p4runtime v1.4.0-rc.5.0.20220728214547-13f0d02a521e github.com/pborman/uuid v1.2.1 github.com/protocolbuffers/txtpbfmt v0.0.0-20220608084003-fc78c767cd6a + github.com/spf13/cobra v1.8.0 + github.com/spf13/pflag v1.0.5 + github.com/spf13/viper v1.18.2 github.com/yoheimuta/go-protoparser/v4 v4.9.0 github.com/yuin/goldmark v1.4.13 golang.org/x/crypto v0.21.0 @@ -62,7 +65,7 @@ require ( cloud.google.com/go/iam v1.1.6 // indirect dario.cat/mergo v1.0.0 // indirect github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 // indirect - github.com/aristanetworks/arista-ceoslab-operator/v2 v2.0.2 // indirect + github.com/aristanetworks/arista-ceoslab-operator/v2 v2.1.2 // indirect github.com/carlmontanari/difflibgo v0.0.0-20210718194309-31b9e131c298 // indirect github.com/cenkalti/backoff/v4 v4.1.3 // indirect github.com/census-instrumentation/opencensus-proto v0.4.1 // indirect @@ -72,6 +75,7 @@ require ( github.com/creack/pty v1.1.18 // indirect github.com/cyphar/filepath-securejoin v0.2.4 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/drivenets/cdnos-controller v1.7.4 // indirect github.com/emicklei/go-restful/v3 v3.10.2 // indirect github.com/emirpasic/gods v1.18.1 // indirect github.com/envoyproxy/go-control-plane v0.12.0 // indirect @@ -114,7 +118,8 @@ require ( github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/networkop/meshnet-cni v0.3.1-0.20230525201116-d7c306c635cf // indirect - github.com/open-traffic-generator/keng-operator v0.3.15 // indirect + github.com/open-traffic-generator/keng-operator v0.3.28 // indirect + github.com/openconfig/attestz v0.2.0 // indirect github.com/openconfig/grpctunnel v0.0.0-20220819142823-6f5422b8ca70 // indirect github.com/openconfig/lemming/operator v0.2.0 // indirect github.com/patrickmn/go-cache v2.1.0+incompatible // indirect @@ -132,9 +137,6 @@ require ( github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.11.0 // indirect github.com/spf13/cast v1.6.0 // indirect - github.com/spf13/cobra v1.8.0 // indirect - github.com/spf13/pflag v1.0.5 // indirect - github.com/spf13/viper v1.18.2 // indirect github.com/srl-labs/srl-controller v0.6.1 // indirect github.com/srl-labs/srlinux-scrapli v0.6.0 // indirect github.com/subosito/gotenv v1.6.0 // indirect diff --git a/go.sum b/go.sum index 037ee5d349d..02850480f71 100644 --- a/go.sum +++ b/go.sum @@ -1227,8 +1227,8 @@ github.com/apache/arrow/go/v11 v11.0.0/go.mod h1:Eg5OsL5H+e299f7u5ssuXsuHQVEGC4x github.com/apache/arrow/go/v12 v12.0.0/go.mod h1:d+tV/eHZZ7Dz7RPrFKtPK02tpr+c9/PEd/zm8mDS9Vg= github.com/apache/arrow/go/v12 v12.0.1/go.mod h1:weuTY7JvTG/HDPtMQxEUp7pU73vkLWMLpY67QwZ/WWw= github.com/apache/thrift v0.16.0/go.mod h1:PHK3hniurgQaNMZYaCLEqXKsYK8upmhPbmdP2FXSqgU= -github.com/aristanetworks/arista-ceoslab-operator/v2 v2.0.2 h1:KQL1evr4NM4ZQOLRs1bbmD0kYPmLRAMqvRrNSpYAph4= -github.com/aristanetworks/arista-ceoslab-operator/v2 v2.0.2/go.mod h1:/mvSt2fEmlVEU7dppip3UNz/MUt380f50dFsZRGn83o= +github.com/aristanetworks/arista-ceoslab-operator/v2 v2.1.2 h1:1aAxwwu4xyfiU1/FX2D5x/jsF/sxFVkjVhvF661isM4= +github.com/aristanetworks/arista-ceoslab-operator/v2 v2.1.2/go.mod h1:/mvSt2fEmlVEU7dppip3UNz/MUt380f50dFsZRGn83o= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= @@ -1291,6 +1291,8 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8Yc github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= +github.com/drivenets/cdnos-controller v1.7.4 h1:UI6aJGfu1jny9sR1tC1+TNWVA+fuzsaedMyikqECrL4= +github.com/drivenets/cdnos-controller v1.7.4/go.mod h1:s+rGGwx3UZ8TECpeC3htXJv+3sF+VK7fFiYgesxD0vA= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/eapache/channels v1.1.0 h1:F1taHcn7/F0i8DYqKXJnyhJcVpp2kgFcNePxXtnyu4k= @@ -1383,6 +1385,8 @@ github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+ github.com/go-pdf/fpdf v0.5.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M= github.com/go-pdf/fpdf v0.6.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= @@ -1483,6 +1487,7 @@ github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/protobuf v3.11.4+incompatible/go.mod h1:lUQ9D1ePzbH2PrIS7ob/bjm9HXyH5WHB0Akwh7URreM= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= @@ -1623,14 +1628,16 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8m github.com/networkop/meshnet-cni v0.3.1-0.20230525201116-d7c306c635cf h1:9Pe9L0QCovb9o82inAVQitCo3IRnG9u45lRRm8QvgbU= github.com/networkop/meshnet-cni v0.3.1-0.20230525201116-d7c306c635cf/go.mod h1:VMkJl7N6e14GTWS0AnCDrnvJOT67hwOFVUcxTzt/EtE= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= -github.com/onsi/ginkgo/v2 v2.6.0 h1:9t9b9vRUbFq3C4qKFCGkVuq/fIHji802N1nrtkh1mNc= -github.com/onsi/ginkgo/v2 v2.6.0/go.mod h1:63DOGlLAH8+REH8jUGdL3YpCpu7JODesutUjdENfUAc= +github.com/onsi/ginkgo/v2 v2.9.2 h1:BA2GMJOtfGAfagzYtrAlufIP0lq6QERkFmHLMLPwFSU= +github.com/onsi/ginkgo/v2 v2.9.2/go.mod h1:WHcJJG2dIlcCqVfBAwUCrJxSPFb6v4azBwgxeMeDuts= github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= -github.com/open-traffic-generator/keng-operator v0.3.15 h1:4qMC8MaCfV7TmmrfqI7rTusOChkHpiA8maih88aLaqY= -github.com/open-traffic-generator/keng-operator v0.3.15/go.mod h1:+koaOnSyrJHdzxnaye+M6k+ZbszQlWI9u3tMxSpORNA= +github.com/open-traffic-generator/keng-operator v0.3.28 h1:FpDe1wtGODN7ByAhF2LxMIlbDqb5yVmbSE5Y49nyc28= +github.com/open-traffic-generator/keng-operator v0.3.28/go.mod h1:+koaOnSyrJHdzxnaye+M6k+ZbszQlWI9u3tMxSpORNA= github.com/open-traffic-generator/snappi/gosnappi v1.3.0 h1:6SFSuZLTuncLW1xMcBG5HEvVCWh9wVuxiYb71C3yj7s= github.com/open-traffic-generator/snappi/gosnappi v1.3.0/go.mod h1:CaE4nisXftNXdXWvTSqb4eiW2WMFIXkJsH5rqPoipcg= +github.com/openconfig/attestz v0.2.0 h1:VuksFIG1OlGnRuUpdTFAkMyAY59ITvyLbp4AtiTXV64= +github.com/openconfig/attestz v0.2.0/go.mod h1:byY6H68zm3VXmQHEb4O4OZtRtFyHEjkmzrvIljYc79Y= github.com/openconfig/entity-naming v0.0.0-20230912181021-7ac806551a31 h1:K/9O+J20+liIof8WjquMydnebD0N1U9ItjhJYF6H4hg= github.com/openconfig/entity-naming v0.0.0-20230912181021-7ac806551a31/go.mod h1:ZRUrfwYYY+pLaOoWPad3p/8J4LLQcSqtXhBCkD2pXJc= github.com/openconfig/gnmi v0.0.0-20200414194230-1597cc0f2600/go.mod h1:M/EcuapNQgvzxo1DDXHK4tx3QpYM/uG4l591v33jG2A= @@ -1658,16 +1665,16 @@ github.com/openconfig/gribigo v0.0.0-20231213034307-d0abeba7f432 h1:LADwzfGipdbq github.com/openconfig/gribigo v0.0.0-20231213034307-d0abeba7f432/go.mod h1:fW2+Z2NiQ5L3hY/wrDsZBIvGYrM5ryHIzjHeVTiPzuM= github.com/openconfig/grpctunnel v0.0.0-20220819142823-6f5422b8ca70 h1:t6SvvdfWCMlw0XPlsdxO8EgO+q/fXnTevDjdYREKFwU= github.com/openconfig/grpctunnel v0.0.0-20220819142823-6f5422b8ca70/go.mod h1:OmTWe7RyZj2CIzIgy4ovEBzCLBJzRvWSZmn7u02U9gU= -github.com/openconfig/kne v0.1.17 h1:n2yuAoUndnheTahF/HoxIDrNdg51nQbvaXKp3aLbg8c= -github.com/openconfig/kne v0.1.17/go.mod h1:6UM7rCFpTSG+/OyxMBrY1zunojXLbwoUSPmkBQqpSg4= +github.com/openconfig/kne v0.1.18 h1:8D9SexWhj6knxfvEficyVj0F13GIvF1pQz7TKwVDSUI= +github.com/openconfig/kne v0.1.18/go.mod h1:VMKjKI9FoVTLh4uN94uoaFZCp1CDkml2Ms2qOi1B2WM= github.com/openconfig/lemming v0.3.2-0.20230914210403-c6484d12af0a h1:JNiu6/3IWtESSq6N+dH65MYaeiDi5CF1Jck5YGvf3JE= github.com/openconfig/lemming v0.3.2-0.20230914210403-c6484d12af0a/go.mod h1:fC8o1NYR9yEmDmoIVaCZQY+iP9RSxujYzckUGSkpWD8= github.com/openconfig/lemming/operator v0.2.0 h1:dovZnR6lQkOHXcODli1NDOr/GVYrBY05KS5X11jxVbw= github.com/openconfig/lemming/operator v0.2.0/go.mod h1:LKgEXSR5VK2CAeh2uKijKAXFj42uQuwakrCHVPF0iII= github.com/openconfig/models-ci v1.0.2-0.20231113233730-f0986391428e h1:6N4jXpZa/SXYcNpJFjjZvenxO/xnTwuUCgCEinhNLfU= github.com/openconfig/models-ci v1.0.2-0.20231113233730-f0986391428e/go.mod h1:w38G/kObu95PbtwMYVp6SKhkHCegJFwL8B58Ns84g4s= -github.com/openconfig/ondatra v0.5.6 h1:1NkkmyPG8To5+aoAO1bIGEstfHB4My/Szc13IM+Kup8= -github.com/openconfig/ondatra v0.5.6/go.mod h1:hFxrMsLsOmvOzHeUDDJZcypenZIo6lt6NrPOdDmnHHM= +github.com/openconfig/ondatra v0.5.8 h1:hTkewcIRtOC6FOpcGThFZPS38EgCbfqh+uwlppMotiA= +github.com/openconfig/ondatra v0.5.8/go.mod h1:6vT2uWz1neH/hDa4ZX8H8pT6sYZHvIftrUugQyG9RrA= github.com/openconfig/replayer v0.0.0-20240110192655-4e9cf83d8d30 h1:KcHS08m7nFHq/D03ZfZKKNCSaS1jsuvdF3lCyDjPWJc= github.com/openconfig/replayer v0.0.0-20240110192655-4e9cf83d8d30/go.mod h1:VQ8FdPVaHwxKtamhcrwkPsvTeeoEgFYNK1xE8nHD0S8= github.com/openconfig/testt v0.0.0-20220311054427-efbb1a32ec07 h1:X631iD/B0ximGFb5P9LY5wHju4SiedxUhc5UZEo7VSw= @@ -1860,8 +1867,8 @@ go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9i go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= -go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= -go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= +go.uber.org/zap v1.25.0 h1:4Hvk6GtkucQ790dqmj7l1eEnRdKm3k3ZUrUMS2d5+5c= +go.uber.org/zap v1.25.0/go.mod h1:JIAUzQIH94IC4fOJQm7gMmBJP5k7wQfdcnYdPoEXJYk= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= diff --git a/internal/args/args.go b/internal/args/args.go index 4af787f7f0e..75f1abfb8a7 100644 --- a/internal/args/args.go +++ b/internal/args/args.go @@ -49,4 +49,10 @@ var ( NonDefaultVRFIPv4NHGWeightSum = flag.Int("arg_non_default_vrf_ipv4_nhg_weight_sum", 32, "In gRIBI scaling tests, the sum of weights to assign to next-hops within a next-hop-group referenced from IPv4 entries in non-default VRFs") DecapEncapCount = flag.Int("arg_decap_encap_count", 64, "In gRIBI scaling tests, number of next-hop-groups with decap+encap next-hops") DefaultVRFPrimarySubifCount = flag.Int("arg_default_vrf_primary_subif_count", 64, "In gRIBI scaling tests, number of subinterfaces to use for \"primary\" (i.e. non-backup) next-hop forwarding. Set such that DefaultVRFPrimarySubifCount <= (DefaultVRFIPv4NHCount - DefaultVRFIPv4NHSize)") + + V4TunnelCount = flag.Int("arg_v4_tunnel_count", 20000, "In gRIBI scaling tests, the number of tunnel IPs.") + V4TunnelNHGCount = flag.Int("arg_v4_tunnel_nhg_count", 256, "In gRIBI scaling tests, the number of next-hop-groups associated to the v4 tunnels.") + V4TunnelNHGSplitCount = flag.Int("arg_v4_tunnel_nhg_split_count", 2, "In gRIBI scaling tests, the number of next-hop per next-hop-group for the v4 tunnels.") + EgressNHGSplitCount = flag.Int("arg_egress_nhg_split_count", 16, "In gRIBI scaling tests, the number of next-hop per next-hop-group for the egress traffic.") + V4ReEncapNHGCount = flag.Int("arg_v4_re_encap_nhg_count", 256, "In gRIBI scaling tests, the number of next-hop-groups for re-encapping v4 tunnels.") ) diff --git a/internal/attrs/attrs.go b/internal/attrs/attrs.go index a502e35c4ab..d8f42e2c644 100644 --- a/internal/attrs/attrs.go +++ b/internal/attrs/attrs.go @@ -34,15 +34,17 @@ import ( // and for an ATETopology. All fields are optional; only those that are // non-empty will be set when configuring an interface. type Attributes struct { - IPv4 string - IPv6 string - MAC string - Name string // Interface name, only applied to ATE ports. - Desc string // Description, only applied to DUT interfaces. - IPv4Len uint8 // Prefix length for IPv4. - IPv6Len uint8 // Prefix length for IPv6. - MTU uint16 - ID uint32 // /interfaces/interface/state/id p4rt interface id + IPv4 string + IPv4Sec string // Secondary IPv4 address + IPv6 string + MAC string + Name string // Interface name, only applied to ATE ports. + Desc string // Description, only applied to DUT interfaces. + IPv4Len uint8 // Prefix length for IPv4. + IPv4LenSec uint8 // Prefix length for Secondary IPv4 address. + IPv6Len uint8 // Prefix length for IPv6. + MTU uint16 + ID uint32 // /interfaces/interface/state/id p4rt interface id } // IPv4CIDR constructs the IPv4 CIDR notation with the given prefix @@ -89,6 +91,18 @@ func (a *Attributes) ConfigOCInterface(intf *oc.Interface, dut *ondatra.DUTDevic } } + if a.IPv4Sec != "" { + s4 := s.GetOrCreateIpv4() + if deviations.InterfaceEnabled(dut) && !deviations.IPv4MissingEnabled(dut) { + s4.Enabled = ygot.Bool(true) + } + a4 := s4.GetOrCreateAddress(a.IPv4Sec) + if a.IPv4LenSec > 0 { + a4.PrefixLength = ygot.Uint8(a.IPv4LenSec) + a4.Type = oc.IfIp_Ipv4AddressType_SECONDARY + } + } + if a.IPv6 != "" { s6 := s.GetOrCreateIpv6() if a.MTU > 0 { diff --git a/internal/cfgplugins/bgp.go b/internal/cfgplugins/bgp.go index 0a72d34e13b..c5ff799f29d 100644 --- a/internal/cfgplugins/bgp.go +++ b/internal/cfgplugins/bgp.go @@ -449,7 +449,7 @@ func BuildBGPOCConfig(t *testing.T, dut *ondatra.DUTDevice, routerID string, afi }, } - peerGroups[nc.PeerGroup] = getPeerGroup(nc.PeerGroup, dut, afiType) + peerGroups[nc.PeerGroup] = getPeerGroup(nc.PeerGroup, dut, afiTypes) } } @@ -461,7 +461,7 @@ func BuildBGPOCConfig(t *testing.T, dut *ondatra.DUTDevice, routerID string, afi } // getPeerGroup build peer-config -func getPeerGroup(pgn string, dut *ondatra.DUTDevice, afiType oc.E_BgpTypes_AFI_SAFI_TYPE) *oc.NetworkInstance_Protocol_Bgp_PeerGroup { +func getPeerGroup(pgn string, dut *ondatra.DUTDevice, afiType []oc.E_BgpTypes_AFI_SAFI_TYPE) *oc.NetworkInstance_Protocol_Bgp_PeerGroup { bgp := &oc.NetworkInstance_Protocol_Bgp{} pg := bgp.GetOrCreatePeerGroup(pgn) @@ -474,11 +474,13 @@ func getPeerGroup(pgn string, dut *ondatra.DUTDevice, afiType oc.E_BgpTypes_AFI_ } // policy under peer group AFI - afisafi := pg.GetOrCreateAfiSafi(afiType) - afisafi.Enabled = ygot.Bool(true) - rpl := afisafi.GetOrCreateApplyPolicy() - rpl.SetExportPolicy([]string{RPLPermitAll}) - rpl.SetImportPolicy([]string{RPLPermitAll}) + for _, afi := range afiType { + afisafi := pg.GetOrCreateAfiSafi(afi) + afisafi.Enabled = ygot.Bool(true) + rpl := afisafi.GetOrCreateApplyPolicy() + rpl.SetExportPolicy([]string{RPLPermitAll}) + rpl.SetImportPolicy([]string{RPLPermitAll}) + } return pg } diff --git a/internal/cfgplugins/interface.go b/internal/cfgplugins/interface.go new file mode 100644 index 00000000000..7567518c89e --- /dev/null +++ b/internal/cfgplugins/interface.go @@ -0,0 +1,91 @@ +// 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 cfgplugins + +import ( + "fmt" + "math" + "testing" + + "github.com/openconfig/featureprofiles/internal/deviations" + "github.com/openconfig/ondatra" + "github.com/openconfig/ondatra/gnmi" + "github.com/openconfig/ondatra/gnmi/oc" + "github.com/openconfig/ygot/ygot" +) + +const ( + targetOutputPowerdBm = -10 + targetOutputPowerTolerancedBm = 1 + targetFrequencyMHz = 193100000 + targetFrequencyToleranceMHz = 100000 +) + +// opticalChannelComponentFromPort returns the name of the optical channel component for the given +// port. +func opticalChannelComponentFromPort(t *testing.T, dut *ondatra.DUTDevice, p *ondatra.Port) string { + t.Helper() + if deviations.MissingPortToOpticalChannelMapping(dut) { + transceiverName := gnmi.Get(t, dut, gnmi.OC().Interface(p.Name()).Transceiver().State()) + return fmt.Sprintf("%s-Optical0", transceiverName) + } + compName := gnmi.Get(t, dut, gnmi.OC().Interface(p.Name()).HardwarePort().State()) + for { + comp, ok := gnmi.Lookup(t, dut, gnmi.OC().Component(compName).State()).Val() + if !ok { + t.Fatalf("Recursive optical channel lookup failed for port: %s, component %s not found.", p.Name(), compName) + } + if comp.GetType() == oc.PlatformTypes_OPENCONFIG_HARDWARE_COMPONENT_OPTICAL_CHANNEL { + return compName + } + if comp.GetParent() == "" { + t.Fatalf("Recursive optical channel lookup failed for port: %s, parent of component %s not found.", p.Name(), compName) + } + compName = comp.GetParent() + } +} + +// InterfaceConfig configures the interface with the given port. +func InterfaceConfig(t *testing.T, dut *ondatra.DUTDevice, dp *ondatra.Port) { + t.Helper() + d := &oc.Root{} + i := d.GetOrCreateInterface(dp.Name()) + i.Enabled = ygot.Bool(true) + i.Type = oc.IETFInterfaces_InterfaceType_ethernetCsmacd + gnmi.Replace(t, dut, gnmi.OC().Interface(dp.Name()).Config(), i) + ocComponent := opticalChannelComponentFromPort(t, dut, dp) + t.Logf("Got opticalChannelComponent from port: %s", ocComponent) + gnmi.Replace(t, dut, gnmi.OC().Component(ocComponent).OpticalChannel().Config(), &oc.Component_OpticalChannel{ + TargetOutputPower: ygot.Float64(targetOutputPowerdBm), + Frequency: ygot.Uint64(targetFrequencyMHz), + }) +} + +// ValidateInterfaceConfig validates the output power and frequency for the given port. +func ValidateInterfaceConfig(t *testing.T, dut *ondatra.DUTDevice, dp *ondatra.Port) { + t.Helper() + ocComponent := opticalChannelComponentFromPort(t, dut, dp) + t.Logf("Got opticalChannelComponent from port: %s", ocComponent) + + outputPower := gnmi.Get(t, dut, gnmi.OC().Component(ocComponent).OpticalChannel().TargetOutputPower().State()) + if math.Abs(float64(outputPower)-float64(targetOutputPowerdBm)) > targetOutputPowerTolerancedBm { + t.Fatalf("Output power is not within expected tolerance, got: %v want: %v tolerance: %v", outputPower, targetOutputPowerdBm, targetOutputPowerTolerancedBm) + } + + frequency := gnmi.Get(t, dut, gnmi.OC().Component(ocComponent).OpticalChannel().Frequency().State()) + if math.Abs(float64(frequency)-float64(targetFrequencyMHz)) > targetFrequencyToleranceMHz { + t.Fatalf("Frequency is not within expected tolerance, got: %v want: %v tolerance: %v", frequency, targetFrequencyMHz, targetFrequencyToleranceMHz) + } +} diff --git a/internal/components/components.go b/internal/components/components.go index 3e666357082..a3d6b90a304 100644 --- a/internal/components/components.go +++ b/internal/components/components.go @@ -22,6 +22,7 @@ import ( "testing" "time" + "github.com/openconfig/featureprofiles/internal/deviations" tpb "github.com/openconfig/gnoi/types" "github.com/openconfig/ondatra" "github.com/openconfig/ondatra/gnmi" @@ -175,3 +176,32 @@ func FindStandbyRP(t *testing.T, dut *ondatra.DUTDevice, supervisors []string) ( return standbyRP, activeRP } + +// OpticalChannelComponentFromPort finds the optical channel component for a port. +func OpticalChannelComponentFromPort(t *testing.T, dut *ondatra.DUTDevice, p *ondatra.Port) string { + t.Helper() + + if deviations.MissingPortToOpticalChannelMapping(dut) { + switch dut.Vendor() { + case ondatra.ARISTA: + transceiverName := gnmi.Get(t, dut, gnmi.OC().Interface(p.Name()).Transceiver().State()) + return fmt.Sprintf("%s-Optical0", transceiverName) + default: + t.Fatal("Manual Optical channel name required when deviation missing_port_to_optical_channel_component_mapping applied.") + } + } + compName := gnmi.Get(t, dut, gnmi.OC().Interface(p.Name()).HardwarePort().State()) + for { + comp, ok := gnmi.Lookup(t, dut, gnmi.OC().Component(compName).State()).Val() + if !ok { + t.Fatalf("Recursive optical channel lookup failed for port: %s, component %s not found.", p.Name(), compName) + } + if comp.GetType() == oc.PlatformTypes_OPENCONFIG_HARDWARE_COMPONENT_OPTICAL_CHANNEL { + return compName + } + if comp.GetParent() == "" { + t.Fatalf("Recursive optical channel lookup failed for port: %s, parent of component %s not found.", p.Name(), compName) + } + compName = comp.GetParent() + } +} diff --git a/internal/deviations/deviations.go b/internal/deviations/deviations.go index 690761efed9..650331af322 100644 --- a/internal/deviations/deviations.go +++ b/internal/deviations/deviations.go @@ -935,9 +935,81 @@ func SkipBgpSendCommunityType(dut *ondatra.DUTDevice) bool { // BgpActionsSetCommunityMethodUnsupported return true if BGP actions set-community method is unsupported func BgpActionsSetCommunityMethodUnsupported(dut *ondatra.DUTDevice) bool { return lookupDUTDeviations(dut).GetBgpActionsSetCommunityMethodUnsupported() + } -// Ensure that no BGP configurations exists under PeerGroups. +// SetNoPeerGroup Ensure that no BGP configurations exists under PeerGroups. func SetNoPeerGroup(dut *ondatra.DUTDevice) bool { return lookupDUTDeviations(dut).GetSetNoPeerGroup() } + +// BgpCommunityMemberIsAString returns true if device community member is not a list +func BgpCommunityMemberIsAString(dut *ondatra.DUTDevice) bool { + return lookupDUTDeviations(dut).GetBgpCommunityMemberIsAString() +} + +// IPv4StaticRouteWithIPv6NextHopUnsupported unsupported ipv4 with ipv6 nexthop +func IPv4StaticRouteWithIPv6NextHopUnsupported(dut *ondatra.DUTDevice) bool { + return lookupDUTDeviations(dut).GetIpv4StaticRouteWithIpv6NhUnsupported() +} + +// IPv6StaticRouteWithIPv4NextHopUnsupported unsported ipv6 with ipv4 nexthop +func IPv6StaticRouteWithIPv4NextHopUnsupported(dut *ondatra.DUTDevice) bool { + return lookupDUTDeviations(dut).GetIpv6StaticRouteWithIpv4NhUnsupported() +} + +// StaticRouteWithDropNhUnsupported unsuported drop nexthop +func StaticRouteWithDropNhUnsupported(dut *ondatra.DUTDevice) bool { + return lookupDUTDeviations(dut).GetStaticRouteWithDropNh() +} + +// StaticRouteWithExplicitMetric set explict metric +func StaticRouteWithExplicitMetric(dut *ondatra.DUTDevice) bool { + return lookupDUTDeviations(dut).GetStaticRouteWithExplicitMetric() +} + +// BgpDefaultPolicyUnsupported return true if BGP default-import/export-policy is not supported. +func BgpDefaultPolicyUnsupported(dut *ondatra.DUTDevice) bool { + return lookupDUTDeviations(dut).GetBgpDefaultPolicyUnsupported() +} + +// ExplicitEnableBGPOnDefaultVRF return true if BGP needs to be explicity enabled on default VRF +func ExplicitEnableBGPOnDefaultVRF(dut *ondatra.DUTDevice) bool { + return lookupDUTDeviations(dut).GetExplicitEnableBgpOnDefaultVrf() +} + +// RoutingPolicyTagSetEmbedded returns true if the implementation does not support tag-set(s) as a +// separate entity, but embeds it in the policy statement +func RoutingPolicyTagSetEmbedded(dut *ondatra.DUTDevice) bool { + return lookupDUTDeviations(dut).GetRoutingPolicyTagSetEmbedded() +} + +// SkipAfiSafiPathForBgpMultipleAs return true if device do not support afi/safi path to enable allow multiple-as for eBGP +func SkipAfiSafiPathForBgpMultipleAs(dut *ondatra.DUTDevice) bool { + return lookupDUTDeviations(dut).GetSkipAfiSafiPathForBgpMultipleAs() +} + +// CommunityMemberRegexUnsupported return true if device do not support community member regex +func CommunityMemberRegexUnsupported(dut *ondatra.DUTDevice) bool { + return lookupDUTDeviations(dut).GetCommunityMemberRegexUnsupported() +} + +// SamePolicyAttachedToAllAfis returns true if same import policy has to be applied for all AFIs +func SamePolicyAttachedToAllAfis(dut *ondatra.DUTDevice) bool { + return lookupDUTDeviations(dut).GetSamePolicyAttachedToAllAfis() +} + +// SkipSettingStatementForPolicy return true if device do not support afi/safi path to enable allow multiple-as for eBGP +func SkipSettingStatementForPolicy(dut *ondatra.DUTDevice) bool { + return lookupDUTDeviations(dut).GetSkipSettingStatementForPolicy() +} + +// SkipCheckingAttributeIndex return true if device do not return bgp attribute for the bgp session specifying the index +func SkipCheckingAttributeIndex(dut *ondatra.DUTDevice) bool { + return lookupDUTDeviations(dut).GetSkipCheckingAttributeIndex() +} + +// FlattenPolicyWithMultipleStatements return true if devices does not support policy-chaining +func FlattenPolicyWithMultipleStatements(dut *ondatra.DUTDevice) bool { + return lookupDUTDeviations(dut).GetFlattenPolicyWithMultipleStatements() +} diff --git a/internal/helpers/helpers.go b/internal/helpers/helpers.go index cb2fefb4228..0667886c46e 100644 --- a/internal/helpers/helpers.go +++ b/internal/helpers/helpers.go @@ -16,6 +16,7 @@ package helpers import ( + "context" "fmt" "sort" "strings" @@ -121,3 +122,35 @@ func GNMINotifString(n *gpb.Notification) string { } return build.String() } + +// GnmiCLIConfig sets config built with buildCliConfigRequest. +func GnmiCLIConfig(t testing.TB, dut *ondatra.DUTDevice, config string) { + gnmiClient := dut.RawAPIs().GNMI(t) + gpbSetRequest, err := buildCliConfigRequest(config) + if err != nil { + t.Fatalf("Cannot build a gNMI SetRequest: %v", err) + } + + t.Log("gnmiClient Set CLI config") + if _, err = gnmiClient.Set(context.Background(), gpbSetRequest); err != nil { + t.Fatalf("gnmiClient.Set() with unexpected error: %v", err) + } +} + +// buildCliConfigRequest Build config with Origin set to cli and Ascii encoded config. +func buildCliConfigRequest(config string) (*gpb.SetRequest, error) { + gpbSetRequest := &gpb.SetRequest{ + Update: []*gpb.Update{{ + Path: &gpb.Path{ + Origin: "cli", + Elem: []*gpb.PathElem{}, + }, + Val: &gpb.TypedValue{ + Value: &gpb.TypedValue_AsciiVal{ + AsciiVal: config, + }, + }, + }}, + } + return gpbSetRequest, nil +} diff --git a/internal/iputil/iputil.go b/internal/iputil/iputil.go new file mode 100644 index 00000000000..a9a291eab9b --- /dev/null +++ b/internal/iputil/iputil.go @@ -0,0 +1,43 @@ +// 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 iputil provides utilities for IPv4/IPv6 related utils +package iputil + +import ( + "encoding/binary" + "fmt" + "net" +) + +// GenerateIPs creates list of n IPs using ipBlock +func GenerateIPs(ipBlock string, n int) []string { + var entries []string + _, netCIDR, err := net.ParseCIDR(ipBlock) + if err != nil { + return entries + } + netMask := binary.BigEndian.Uint32(netCIDR.Mask) + firstIP := binary.BigEndian.Uint32(netCIDR.IP) + lastIP := (firstIP & netMask) | (netMask ^ 0xffffffff) + + for i := firstIP; i <= lastIP && n > 0; i++ { + ip := make(net.IP, 4) + binary.BigEndian.PutUint32(ip, i) + entries = append(entries, fmt.Sprint(ip)) + n-- + } + + return entries +} diff --git a/internal/iputil/iputil_test.go b/internal/iputil/iputil_test.go new file mode 100644 index 00000000000..6e77738492b --- /dev/null +++ b/internal/iputil/iputil_test.go @@ -0,0 +1,45 @@ +package iputil + +import ( + "testing" + + "github.com/google/go-cmp/cmp" +) + +func TestGenerateIPs(t *testing.T) { + tests := []struct { + name string + prefix string + count int + want []string + }{{ + name: "IPv4/24", + prefix: "192.168.0.0/24", + count: 3, + want: []string{"192.168.0.0", "192.168.0.1", "192.168.0.2"}, + }, { + name: "IPv4/31", + prefix: "192.168.0.0/31", + count: 3, + want: []string{"192.168.0.0", "192.168.0.1"}, + }, { + name: "Invalid prefix", + prefix: "192.168.0.0/24/24", + count: 3, + want: nil, + }, { + name: "Invalid count", + prefix: "192.168.0.0/24", + count: 0, + want: nil, + }} + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := GenerateIPs(tt.prefix, tt.count) + if diff := cmp.Diff(tt.want, got); diff != "" { + t.Errorf("GenerateIPs() returned diff (-want +got):\n%s", diff) + } + }) + } +} diff --git a/internal/tescale/scale.go b/internal/tescale/scale.go new file mode 100644 index 00000000000..a2006f7ef0e --- /dev/null +++ b/internal/tescale/scale.go @@ -0,0 +1,268 @@ +// 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 tescale provides functions for tescale +package tescale + +import ( + "sync" + + "github.com/openconfig/featureprofiles/internal/deviations" + "github.com/openconfig/featureprofiles/internal/iputil" + "github.com/openconfig/gribigo/fluent" + "github.com/openconfig/ondatra" +) + +const ( + // VRFT vrf t + VRFT = "vrf_t" + // VRFR vrf r + VRFR = "vrf_r" + // VRFRD vrf rd + VRFRD = "vrf_rd" + + // V4TunnelIPBlock tunnel IP block + V4TunnelIPBlock = "198.18.0.1/16" + // V4VIPIPBlock vip IP block + V4VIPIPBlock = "198.18.196.1/22" + + tunnelSrcIP = "198.18.204.1" +) + +// IPPool for IPs +type IPPool struct { + ips []string + index int + rw sync.RWMutex +} + +// NewIPPool creates a new IPPool +func NewIPPool(entries []string) *IPPool { + return &IPPool{ + ips: entries, + index: -1, + } +} + +// NextIP returns the next IP +func (p *IPPool) NextIP() string { + p.rw.Lock() + defer p.rw.Unlock() + + p.index++ + return p.ips[p.index] +} + +// AllIPs returns all IPs in the pool +func (p *IPPool) AllIPs() []string { + return append([]string{}, p.ips...) +} + +// IDPool for NH and NHG IDs +type IDPool struct { + nhIndex uint64 + nhgIndex uint64 + rw sync.RWMutex +} + +// NewIDPool creates a new IDPool +func NewIDPool(base uint64) *IDPool { + return &IDPool{ + nhIndex: base, + nhgIndex: base, + } +} + +// NextNHID returns the next NHID +func (p *IDPool) NextNHID() uint64 { + p.rw.Lock() + defer p.rw.Unlock() + + p.nhIndex++ + return p.nhIndex +} + +// NextNHGID returns the next NHGID +func (p *IDPool) NextNHGID() uint64 { + p.rw.Lock() + defer p.rw.Unlock() + + p.nhgIndex++ + return p.nhgIndex +} + +// VRFConfig holds NH, NHG and IPv4 entries for the VRF. +type VRFConfig struct { + Name string + NHs []fluent.GRIBIEntry + NHGs []fluent.GRIBIEntry + V4Entries []fluent.GRIBIEntry +} + +// Param TE holds scale parameters. +type Param struct { + V4TunnelCount int + V4TunnelNHGCount int + V4TunnelNHGSplitCount int + EgressNHGSplitCount int + V4ReEncapNHGCount int +} + +// BuildVRFConfig creates scale new scale VRF configurations. +func BuildVRFConfig(dut *ondatra.DUTDevice, egressIPs []string, param Param) []*VRFConfig { + v4TunnelIPAddrs := NewIPPool(iputil.GenerateIPs(V4TunnelIPBlock, param.V4TunnelCount)) + v4VIPAddrs := NewIPPool(iputil.GenerateIPs(V4VIPIPBlock, (param.V4TunnelNHGCount*param.V4TunnelNHGSplitCount)+2)) + v4EgressIPAddrs := NewIPPool(egressIPs) + + defaultVRF := deviations.DefaultNetworkInstance(dut) + vrfTConf := &VRFConfig{Name: VRFT} + vrfRConf := &VRFConfig{Name: VRFR} + vrfRDConf := &VRFConfig{Name: VRFRD} + vrfDefault := &VRFConfig{Name: defaultVRF} + idPool := NewIDPool(10000) + + // VRF_T: + + nhgID := idPool.NextNHGID() + nhID := idPool.NextNHID() + nhgRedirectToVrfR := nhgID + // build backup NHG and NH. + vrfDefault.NHs = append(vrfDefault.NHs, + fluent.NextHopEntry().WithIndex(nhID).WithNetworkInstance(defaultVRF).WithNextHopNetworkInstance(VRFR), + ) + vrfDefault.NHGs = append(vrfDefault.NHGs, + fluent.NextHopGroupEntry().WithID(nhgRedirectToVrfR).AddNextHop(nhID, 1).WithNetworkInstance(defaultVRF), + ) + + // Build IPv4 entry and related NHGs and NHs. + // * Mapping tunnel IP per the IP -> NHG ratio + // * Each NHG has unique NHs. + // * Each NHG has the same backup to Repair VRF. + tunnelNHGRatio := param.V4TunnelCount / param.V4TunnelNHGCount + for idx, ip := range v4TunnelIPAddrs.AllIPs() { + nhgEntry := fluent.NextHopGroupEntry().WithID(nhgID).WithNetworkInstance(defaultVRF).WithBackupNHG(nhgRedirectToVrfR) + if idx%tunnelNHGRatio == 0 { + nhgID = idPool.NextNHGID() + + // Build NHs and link NHs to NHG. + for i := 0; i < param.V4TunnelNHGSplitCount; i++ { + vip := v4VIPAddrs.NextIP() + nhID = idPool.NextNHID() + vrfDefault.NHs = append(vrfDefault.NHs, + fluent.NextHopEntry().WithIndex(nhID).WithNetworkInstance(defaultVRF).WithIPAddress(vip), + ) + nhgEntry = nhgEntry.AddNextHop(nhID, 1) + } + vrfDefault.NHGs = append(vrfDefault.NHGs, nhgEntry) + } + + // Build IPv4 entry + vrfTConf.V4Entries = append(vrfTConf.V4Entries, + fluent.IPv4Entry().WithPrefix(ip+"/32").WithNextHopGroup(nhgID).WithNetworkInstance(VRFT).WithNextHopGroupNetworkInstance(defaultVRF), + ) + } + + // Default VRF: + + // * each VIP 1:1 map to a NHG + // * each NHG points to unique NHs + for _, ip := range v4VIPAddrs.AllIPs() { + nhgID := idPool.NextNHGID() + nhgEntry := fluent.NextHopGroupEntry().WithID(nhgID).WithNetworkInstance(defaultVRF) + // Build NHs and link NHs to NHG. + for i := 0; i < param.EgressNHGSplitCount; i++ { + vip := v4EgressIPAddrs.AllIPs()[i] + nhID = idPool.NextNHID() + vrfDefault.NHs = append(vrfDefault.NHs, + fluent.NextHopEntry().WithIndex(nhID).WithNetworkInstance(defaultVRF).WithIPAddress(vip), + ) + nhgEntry = nhgEntry.AddNextHop(nhID, 1) + } + + vrfDefault.NHGs = append(vrfDefault.NHGs, nhgEntry) + // Build IPv4 entry + vrfDefault.V4Entries = append(vrfDefault.V4Entries, + fluent.IPv4Entry().WithPrefix(ip+"/32").WithNextHopGroup(nhgID).WithNetworkInstance(defaultVRF).WithNextHopGroupNetworkInstance(defaultVRF), + ) + } + + // VRF_R + + // build backup NHG and NH. + nhID = idPool.NextNHID() + nhgID = idPool.NextNHGID() + nhgDecapToDefault := nhgID + vrfDefault.NHs = append(vrfDefault.NHs, + fluent.NextHopEntry().WithIndex(nhID).WithDecapsulateHeader(fluent.IPinIP).WithNetworkInstance(defaultVRF).WithNextHopNetworkInstance(defaultVRF), + ) + vrfDefault.NHGs = append(vrfDefault.NHGs, + fluent.NextHopGroupEntry().WithID(nhgID).AddNextHop(nhID, 1).WithNetworkInstance(defaultVRF), + ) + + // build IP entries and related NHG and NHs. + // * Each NHG 1:1 mapping to NH + // * Each NH has one entry for decap and encap + // * All NHG has a backup for decap then goto default VRF. + reEncapNHGRatio := param.V4TunnelCount / param.V4ReEncapNHGCount + nhgEntry := fluent.NextHopGroupEntry().WithID(nhgID).WithNetworkInstance(defaultVRF).WithBackupNHG(nhgDecapToDefault) + nhgID = idPool.NextNHGID() + for idx, ip := range v4TunnelIPAddrs.AllIPs() { + nhID = idPool.NextNHID() + vrfDefault.NHs = append(vrfDefault.NHs, + fluent.NextHopEntry().WithIndex(nhID).WithDecapsulateHeader(fluent.IPinIP).WithEncapsulateHeader(fluent.IPinIP). + WithNetworkInstance(defaultVRF).WithIPinIP(tunnelSrcIP, v4TunnelIPAddrs.AllIPs()[(idx+1)%len(v4TunnelIPAddrs.AllIPs())]), + ) + if idx != 0 && idx%reEncapNHGRatio == 0 { + vrfDefault.NHGs = append(vrfDefault.NHGs, nhgEntry) + nhgID = idPool.NextNHGID() + nhgEntry = fluent.NextHopGroupEntry().WithID(nhgID).WithNetworkInstance(defaultVRF).WithBackupNHG(nhgDecapToDefault) + } + nhgEntry = nhgEntry.AddNextHop(nhID, 1) + vrfRConf.V4Entries = append(vrfRConf.V4Entries, + fluent.IPv4Entry().WithPrefix(ip+"/32").WithNextHopGroup(nhgID).WithNetworkInstance(VRFR).WithNextHopGroupNetworkInstance(defaultVRF), + ) + } + vrfDefault.NHGs = append(vrfDefault.NHGs, nhgEntry) + + v4VIPAddrs = NewIPPool(iputil.GenerateIPs(V4VIPIPBlock, (param.V4TunnelNHGCount*param.V4TunnelNHGSplitCount)+2)) + + // VRF_RP + + // * do the same as Transit VRF + // * but with decap to default NHG + for idx, ip := range v4TunnelIPAddrs.AllIPs() { + nhgEntry := fluent.NextHopGroupEntry().WithID(nhgID).WithNetworkInstance(defaultVRF).WithBackupNHG(nhgRedirectToVrfR) + if idx%tunnelNHGRatio == 0 { + nhgID = idPool.NextNHGID() + + // Build NHs and link NHs to NHG. + for i := 0; i < param.V4TunnelNHGSplitCount; i++ { + vip := v4VIPAddrs.NextIP() + nhID = idPool.NextNHID() + vrfDefault.NHs = append(vrfDefault.NHs, + fluent.NextHopEntry().WithIndex(nhID).WithNetworkInstance(defaultVRF).WithIPAddress(vip), + ) + nhgEntry = nhgEntry.AddNextHop(nhID, 1) + } + vrfDefault.NHGs = append(vrfDefault.NHGs, nhgEntry) + } + + // Build IPv4 entry + vrfRDConf.NHs = append(vrfRDConf.NHs, + fluent.IPv4Entry().WithPrefix(ip+"/32").WithNextHopGroup(nhgID).WithNetworkInstance(VRFRD).WithNextHopGroupNetworkInstance(defaultVRF), + ) + } + + return []*VRFConfig{vrfDefault, vrfTConf, vrfRConf, vrfRDConf} +} diff --git a/internal/vrfpolicy/vrfpolicy.go b/internal/vrfpolicy/vrfpolicy.go index c4580303c8c..603a836b89e 100644 --- a/internal/vrfpolicy/vrfpolicy.go +++ b/internal/vrfpolicy/vrfpolicy.go @@ -26,12 +26,16 @@ import ( ) const ( + // VRFPolicyW is the policy name + VRFPolicyW = "vrf_selection_policy_w" + // VRFPolicyC is the policy name + VRFPolicyC = "vrf_selection_policy_c" + niDecapTeVrf = "DECAP_TE_VRF" niEncapTeVrfA = "ENCAP_TE_VRF_A" niEncapTeVrfB = "ENCAP_TE_VRF_B" niEncapTeVrfC = "ENCAP_TE_VRF_C" niEncapTeVrfD = "ENCAP_TE_VRF_D" - vrfPolW = "vrf_selection_policy_w" niDefault = "DEFAULT" dscpEncapA1 = 10 dscpEncapA2 = 18 @@ -45,7 +49,7 @@ const ( decapFlowSrc = "198.51.100.111" ) -type ipv4 struct { +type ipInfo struct { protocol oc.UnionUint8 dscpSet []uint8 sourceAddr string @@ -55,12 +59,14 @@ type action struct { decapNI string postDecapNI string decapFallbackNI string + networkInstance string } type policyFwRule struct { seqID uint32 - ipv4 ipv4 - action action + ipv4 *ipInfo + ipv6 *ipInfo + action *action } // configureNetworkInstance configures vrfs DECAP_TE_VRF, ENCAP_TE_VRF_A, ENCAP_TE_VRF_B, @@ -79,70 +85,69 @@ func configNonDefaultNetworkInstance(t *testing.T, dut *ondatra.DUTDevice) { // BuildVRFSelectionPolicyW vrf selection policy rule // Reference: https://github.com/openconfig/featureprofiles/blob/main/feature/gribi/vrf_policy_driven_te/README.md?plain=1#L252 func BuildVRFSelectionPolicyW(t *testing.T, dut *ondatra.DUTDevice, niName string) *oc.NetworkInstance_PolicyForwarding { - d := &oc.Root{} configNonDefaultNetworkInstance(t, dut) pfRule1 := &policyFwRule{ seqID: 1, - ipv4: ipv4{protocol: 4, dscpSet: []uint8{dscpEncapA1, dscpEncapA2}, sourceAddr: ipv4OuterSrc222WithMask}, - action: action{decapNI: niDecapTeVrf, postDecapNI: niEncapTeVrfA, decapFallbackNI: niTeVrf222}, + ipv4: &ipInfo{protocol: 4, dscpSet: []uint8{dscpEncapA1, dscpEncapA2}, sourceAddr: ipv4OuterSrc222WithMask}, + action: &action{decapNI: niDecapTeVrf, postDecapNI: niEncapTeVrfA, decapFallbackNI: niTeVrf222}, } pfRule2 := &policyFwRule{ seqID: 2, - ipv4: ipv4{protocol: 41, dscpSet: []uint8{dscpEncapA1, dscpEncapA2}, sourceAddr: ipv4OuterSrc222WithMask}, - action: action{decapNI: niDecapTeVrf, postDecapNI: niEncapTeVrfA, decapFallbackNI: niTeVrf222}, + ipv4: &ipInfo{protocol: 41, dscpSet: []uint8{dscpEncapA1, dscpEncapA2}, sourceAddr: ipv4OuterSrc222WithMask}, + action: &action{decapNI: niDecapTeVrf, postDecapNI: niEncapTeVrfA, decapFallbackNI: niTeVrf222}, } pfRule3 := &policyFwRule{ seqID: 3, - ipv4: ipv4{protocol: 4, dscpSet: []uint8{dscpEncapA1, dscpEncapA2}, sourceAddr: ipv4OuterSrc111WithMask}, - action: action{decapNI: niDecapTeVrf, postDecapNI: niEncapTeVrfA, decapFallbackNI: niTeVrf111}, + ipv4: &ipInfo{protocol: 4, dscpSet: []uint8{dscpEncapA1, dscpEncapA2}, sourceAddr: ipv4OuterSrc111WithMask}, + action: &action{decapNI: niDecapTeVrf, postDecapNI: niEncapTeVrfA, decapFallbackNI: niTeVrf111}, } pfRule4 := &policyFwRule{ seqID: 4, - ipv4: ipv4{protocol: 41, dscpSet: []uint8{dscpEncapA1, dscpEncapA2}, sourceAddr: ipv4OuterSrc111WithMask}, - action: action{decapNI: niDecapTeVrf, postDecapNI: niEncapTeVrfA, decapFallbackNI: niTeVrf111}, + ipv4: &ipInfo{protocol: 41, dscpSet: []uint8{dscpEncapA1, dscpEncapA2}, sourceAddr: ipv4OuterSrc111WithMask}, + action: &action{decapNI: niDecapTeVrf, postDecapNI: niEncapTeVrfA, decapFallbackNI: niTeVrf111}, } pfRule5 := &policyFwRule{ seqID: 5, - ipv4: ipv4{protocol: 4, dscpSet: []uint8{dscpEncapB1, dscpEncapB2}, sourceAddr: ipv4OuterSrc222WithMask}, - action: action{decapNI: niDecapTeVrf, postDecapNI: niEncapTeVrfB, decapFallbackNI: niTeVrf222}, + ipv4: &ipInfo{protocol: 4, dscpSet: []uint8{dscpEncapB1, dscpEncapB2}, sourceAddr: ipv4OuterSrc222WithMask}, + action: &action{decapNI: niDecapTeVrf, postDecapNI: niEncapTeVrfB, decapFallbackNI: niTeVrf222}, } pfRule6 := &policyFwRule{ seqID: 6, - ipv4: ipv4{protocol: 41, dscpSet: []uint8{dscpEncapB1, dscpEncapB2}, sourceAddr: ipv4OuterSrc222WithMask}, - action: action{decapNI: niDecapTeVrf, postDecapNI: niEncapTeVrfB, decapFallbackNI: niTeVrf222}, + ipv4: &ipInfo{protocol: 41, dscpSet: []uint8{dscpEncapB1, dscpEncapB2}, sourceAddr: ipv4OuterSrc222WithMask}, + action: &action{decapNI: niDecapTeVrf, postDecapNI: niEncapTeVrfB, decapFallbackNI: niTeVrf222}, } pfRule7 := &policyFwRule{ seqID: 7, - ipv4: ipv4{protocol: 4, dscpSet: []uint8{dscpEncapB1, dscpEncapB2}, sourceAddr: ipv4OuterSrc111WithMask}, - action: action{decapNI: niDecapTeVrf, postDecapNI: niEncapTeVrfB, decapFallbackNI: niTeVrf111}, + ipv4: &ipInfo{protocol: 4, dscpSet: []uint8{dscpEncapB1, dscpEncapB2}, sourceAddr: ipv4OuterSrc111WithMask}, + action: &action{decapNI: niDecapTeVrf, postDecapNI: niEncapTeVrfB, decapFallbackNI: niTeVrf111}, } pfRule8 := &policyFwRule{ seqID: 8, - ipv4: ipv4{protocol: 41, dscpSet: []uint8{dscpEncapB1, dscpEncapB2}, sourceAddr: ipv4OuterSrc111WithMask}, - action: action{decapNI: niDecapTeVrf, postDecapNI: niEncapTeVrfB, decapFallbackNI: niTeVrf111}, + ipv4: &ipInfo{protocol: 41, dscpSet: []uint8{dscpEncapB1, dscpEncapB2}, sourceAddr: ipv4OuterSrc111WithMask}, + action: &action{decapNI: niDecapTeVrf, postDecapNI: niEncapTeVrfB, decapFallbackNI: niTeVrf111}, } pfRule9 := &policyFwRule{ seqID: 9, - ipv4: ipv4{protocol: 4, sourceAddr: ipv4OuterSrc222WithMask}, - action: action{decapNI: niDecapTeVrf, postDecapNI: niDefault, decapFallbackNI: niTeVrf222}, + ipv4: &ipInfo{protocol: 4, sourceAddr: ipv4OuterSrc222WithMask}, + action: &action{decapNI: niDecapTeVrf, postDecapNI: niDefault, decapFallbackNI: niTeVrf222}, } pfRule10 := &policyFwRule{ seqID: 10, - ipv4: ipv4{protocol: 41, sourceAddr: ipv4OuterSrc222WithMask}, - action: action{decapNI: niDecapTeVrf, postDecapNI: niDefault, decapFallbackNI: niTeVrf222}, + ipv4: &ipInfo{protocol: 41, sourceAddr: ipv4OuterSrc222WithMask}, + action: &action{decapNI: niDecapTeVrf, postDecapNI: niDefault, decapFallbackNI: niTeVrf222}, } pfRule11 := &policyFwRule{ seqID: 11, - ipv4: ipv4{protocol: 4, sourceAddr: ipv4OuterSrc111WithMask}, - action: action{decapNI: niDecapTeVrf, postDecapNI: niDefault, decapFallbackNI: niTeVrf111}, + ipv4: &ipInfo{protocol: 4, sourceAddr: ipv4OuterSrc111WithMask}, + action: &action{decapNI: niDecapTeVrf, postDecapNI: niDefault, decapFallbackNI: niTeVrf111}, } pfRule12 := &policyFwRule{ seqID: 12, - ipv4: ipv4{protocol: 41, sourceAddr: ipv4OuterSrc111WithMask}, - action: action{decapNI: niDecapTeVrf, postDecapNI: niDefault, decapFallbackNI: niTeVrf111}, + ipv4: &ipInfo{protocol: 41, sourceAddr: ipv4OuterSrc111WithMask}, + action: &action{decapNI: niDecapTeVrf, postDecapNI: niDefault, decapFallbackNI: niTeVrf111}, } pfRuleList := []*policyFwRule{ @@ -156,24 +161,8 @@ func BuildVRFSelectionPolicyW(t *testing.T, dut *ondatra.DUTDevice, niName strin pfRule12.seqID = 912 } - ni := d.GetOrCreateNetworkInstance(niName) - niP := ni.GetOrCreatePolicyForwarding() - niPf := niP.GetOrCreatePolicy(vrfPolW) - niPf.SetType(oc.Policy_Type_VRF_SELECTION_POLICY) - - for _, pfRule := range pfRuleList { - pfR := niPf.GetOrCreateRule(pfRule.seqID) - pfRProtoIPv4 := pfR.GetOrCreateIpv4() - pfRProtoIPv4.Protocol = oc.UnionUint8(pfRule.ipv4.protocol) - if pfRule.ipv4.dscpSet != nil { - pfRProtoIPv4.DscpSet = pfRule.ipv4.dscpSet - } - pfRProtoIPv4.SourceAddress = ygot.String(pfRule.ipv4.sourceAddr) - pfRAction := pfR.GetOrCreateAction() - pfRAction.DecapNetworkInstance = ygot.String(pfRule.action.decapNI) - pfRAction.PostDecapNetworkInstance = ygot.String(pfRule.action.postDecapNI) - pfRAction.DecapFallbackNetworkInstance = ygot.String(pfRule.action.decapFallbackNI) - } + niP := buildVRFSelectionPolicy(niName, VRFPolicyW, pfRuleList) + niPf := niP.GetPolicy(VRFPolicyW) if deviations.PfRequireMatchDefaultRule(dut) { pfR13 := niPf.GetOrCreateRule(913) @@ -193,8 +182,133 @@ func BuildVRFSelectionPolicyW(t *testing.T, dut *ondatra.DUTDevice, niName strin return niP } -// ConfigureVRFSelectionPolicyW configures vrf selection policy W on default NI and applies to DUT port1 -func ConfigureVRFSelectionPolicyW(t *testing.T, dut *ondatra.DUTDevice) { +// BuildVRFSelectionPolicyC vrf selection policy rule +// Reference: https://github.com/openconfig/featureprofiles/blob/main/feature/gribi/vrf_policy_driven_te/README.md?plain=1#L40 +func BuildVRFSelectionPolicyC(t *testing.T, dut *ondatra.DUTDevice, niName string) *oc.NetworkInstance_PolicyForwarding { + configNonDefaultNetworkInstance(t, dut) + + pfRule1 := &policyFwRule{ + seqID: 1, + ipv4: &ipInfo{protocol: 4, dscpSet: []uint8{dscpEncapA1, dscpEncapA2}, sourceAddr: ipv4OuterSrc222WithMask}, + action: &action{decapNI: niDecapTeVrf, postDecapNI: niEncapTeVrfA, decapFallbackNI: niTeVrf222}, + } + pfRule2 := &policyFwRule{ + seqID: 2, + ipv4: &ipInfo{protocol: 41, dscpSet: []uint8{dscpEncapA1, dscpEncapA2}, sourceAddr: ipv4OuterSrc222WithMask}, + action: &action{decapNI: niDecapTeVrf, postDecapNI: niEncapTeVrfA, decapFallbackNI: niTeVrf222}, + } + pfRule3 := &policyFwRule{ + seqID: 3, + ipv4: &ipInfo{protocol: 4, dscpSet: []uint8{dscpEncapA1, dscpEncapA2}, sourceAddr: ipv4OuterSrc111WithMask}, + action: &action{decapNI: niDecapTeVrf, postDecapNI: niEncapTeVrfA, decapFallbackNI: niTeVrf111}, + } + pfRule4 := &policyFwRule{ + seqID: 4, + ipv4: &ipInfo{protocol: 41, dscpSet: []uint8{dscpEncapA1, dscpEncapA2}, sourceAddr: ipv4OuterSrc111WithMask}, + action: &action{decapNI: niDecapTeVrf, postDecapNI: niEncapTeVrfA, decapFallbackNI: niTeVrf111}, + } + + pfRule5 := &policyFwRule{ + seqID: 5, + ipv4: &ipInfo{protocol: 4, dscpSet: []uint8{dscpEncapB1, dscpEncapB2}, sourceAddr: ipv4OuterSrc222WithMask}, + action: &action{decapNI: niDecapTeVrf, postDecapNI: niEncapTeVrfB, decapFallbackNI: niTeVrf222}, + } + pfRule6 := &policyFwRule{ + seqID: 6, + ipv4: &ipInfo{protocol: 41, dscpSet: []uint8{dscpEncapB1, dscpEncapB2}, sourceAddr: ipv4OuterSrc222WithMask}, + action: &action{decapNI: niDecapTeVrf, postDecapNI: niEncapTeVrfB, decapFallbackNI: niTeVrf222}, + } + pfRule7 := &policyFwRule{ + seqID: 7, + ipv4: &ipInfo{protocol: 4, dscpSet: []uint8{dscpEncapB1, dscpEncapB2}, sourceAddr: ipv4OuterSrc111WithMask}, + action: &action{decapNI: niDecapTeVrf, postDecapNI: niEncapTeVrfB, decapFallbackNI: niTeVrf111}, + } + pfRule8 := &policyFwRule{ + seqID: 8, + ipv4: &ipInfo{protocol: 41, dscpSet: []uint8{dscpEncapB1, dscpEncapB2}, sourceAddr: ipv4OuterSrc111WithMask}, + action: &action{decapNI: niDecapTeVrf, postDecapNI: niEncapTeVrfB, decapFallbackNI: niTeVrf111}, + } + + pfRule9 := &policyFwRule{ + seqID: 9, + ipv4: &ipInfo{protocol: 4, sourceAddr: ipv4OuterSrc222WithMask}, + action: &action{decapNI: niDecapTeVrf, postDecapNI: niDefault, decapFallbackNI: niTeVrf222}, + } + pfRule10 := &policyFwRule{ + seqID: 10, + ipv4: &ipInfo{protocol: 41, sourceAddr: ipv4OuterSrc222WithMask}, + action: &action{decapNI: niDecapTeVrf, postDecapNI: niDefault, decapFallbackNI: niTeVrf222}, + } + pfRule11 := &policyFwRule{ + seqID: 11, + ipv4: &ipInfo{protocol: 4, sourceAddr: ipv4OuterSrc111WithMask}, + action: &action{decapNI: niDecapTeVrf, postDecapNI: niDefault, decapFallbackNI: niTeVrf111}, + } + pfRule12 := &policyFwRule{ + seqID: 12, + ipv4: &ipInfo{protocol: 41, sourceAddr: ipv4OuterSrc111WithMask}, + action: &action{decapNI: niDecapTeVrf, postDecapNI: niDefault, decapFallbackNI: niTeVrf111}, + } + + pfRule13 := &policyFwRule{ + seqID: 13, + ipv4: &ipInfo{dscpSet: []uint8{dscpEncapA1, dscpEncapA2}}, + action: &action{networkInstance: niEncapTeVrfA}, + } + pfRule14 := &policyFwRule{ + seqID: 14, + ipv6: &ipInfo{dscpSet: []uint8{dscpEncapA1, dscpEncapA2}}, + action: &action{networkInstance: niEncapTeVrfA}, + } + pfRule15 := &policyFwRule{ + seqID: 15, + ipv4: &ipInfo{dscpSet: []uint8{dscpEncapB1, dscpEncapB2}}, + action: &action{networkInstance: niEncapTeVrfB}, + } + pfRule16 := &policyFwRule{ + seqID: 16, + ipv6: &ipInfo{dscpSet: []uint8{dscpEncapB1, dscpEncapB2}}, + action: &action{networkInstance: niEncapTeVrfB}, + } + + pfRuleList := []*policyFwRule{ + pfRule1, pfRule2, pfRule3, pfRule4, pfRule5, pfRule6, pfRule7, pfRule8, + pfRule9, pfRule10, pfRule11, pfRule12, pfRule13, pfRule14, pfRule15, pfRule16, + } + + if deviations.PfRequireSequentialOrderPbrRules(dut) { + pfRule10.seqID = 910 + pfRule11.seqID = 911 + pfRule12.seqID = 912 + pfRule13.seqID = 913 + pfRule14.seqID = 914 + pfRule15.seqID = 915 + pfRule16.seqID = 916 + } + + niP := buildVRFSelectionPolicy(niName, VRFPolicyC, pfRuleList) + niPf := niP.GetPolicy(VRFPolicyC) + + if deviations.PfRequireMatchDefaultRule(dut) { + pfR17 := niPf.GetOrCreateRule(917) + pfR17.GetOrCreateL2().SetEthertype(oc.PacketMatchTypes_ETHERTYPE_ETHERTYPE_IPV4) + pfRAction := pfR17.GetOrCreateAction() + pfRAction.NetworkInstance = ygot.String(niDefault) + pfR18 := niPf.GetOrCreateRule(918) + pfR18.GetOrCreateL2().SetEthertype(oc.PacketMatchTypes_ETHERTYPE_ETHERTYPE_IPV6) + pfRAction = pfR18.GetOrCreateAction() + pfRAction.NetworkInstance = ygot.String(niDefault) + } else { + pfR := niPf.GetOrCreateRule(17) + pfRAction := pfR.GetOrCreateAction() + pfRAction.NetworkInstance = ygot.String(niDefault) + } + + return niP +} + +// ConfigureVRFSelectionPolicy configures vrf selection policy on default NI and applies to DUT port1 +func ConfigureVRFSelectionPolicy(t *testing.T, dut *ondatra.DUTDevice, policyName string) { t.Helper() port1 := dut.Port(t, "port1") @@ -203,12 +317,21 @@ func ConfigureVRFSelectionPolicyW(t *testing.T, dut *ondatra.DUTDevice) { interfaceID = interfaceID + ".0" } - niForwarding := BuildVRFSelectionPolicyW(t, dut, deviations.DefaultNetworkInstance(dut)) + var niForwarding *oc.NetworkInstance_PolicyForwarding + switch policyName { + case VRFPolicyC: + niForwarding = BuildVRFSelectionPolicyC(t, dut, deviations.DefaultNetworkInstance(dut)) + case VRFPolicyW: + niForwarding = BuildVRFSelectionPolicyW(t, dut, deviations.DefaultNetworkInstance(dut)) + default: + t.Fatalf("unsupported policy name: %s", policyName) + } + dutForwardingPath := gnmi.OC().NetworkInstance(deviations.DefaultNetworkInstance(dut)).PolicyForwarding() gnmi.Replace(t, dut, dutForwardingPath.Config(), niForwarding) interface1 := niForwarding.GetOrCreateInterface(interfaceID) - interface1.ApplyVrfSelectionPolicy = ygot.String(vrfPolW) + interface1.ApplyVrfSelectionPolicy = ygot.String(policyName) interface1.GetOrCreateInterfaceRef().Interface = ygot.String(port1.Name()) interface1.GetOrCreateInterfaceRef().Subinterface = ygot.Uint32(0) if deviations.InterfaceRefConfigUnsupported(dut) { @@ -217,6 +340,51 @@ func ConfigureVRFSelectionPolicyW(t *testing.T, dut *ondatra.DUTDevice) { gnmi.Replace(t, dut, dutForwardingPath.Interface(interfaceID).Config(), interface1) } +func buildVRFSelectionPolicy(niName string, policyName string, pfRules []*policyFwRule) *oc.NetworkInstance_PolicyForwarding { + r := &oc.Root{} + ni := r.GetOrCreateNetworkInstance(niName) + niP := ni.GetOrCreatePolicyForwarding() + niPf := niP.GetOrCreatePolicy(policyName) + niPf.SetType(oc.Policy_Type_VRF_SELECTION_POLICY) + + for _, pfRule := range pfRules { + pfR := niPf.GetOrCreateRule(pfRule.seqID) + if pfRule.ipv4 != nil { + pfRProtoIP := pfR.GetOrCreateIpv4() + if pfRule.ipv4.dscpSet != nil { + pfRProtoIP.DscpSet = pfRule.ipv4.dscpSet + } + if pfRule.ipv4.protocol != 0 { + pfRProtoIP.Protocol = oc.UnionUint8(pfRule.ipv4.protocol) + } + if pfRule.ipv4.sourceAddr != "" { + pfRProtoIP.SourceAddress = ygot.String(pfRule.ipv4.sourceAddr) + } + } else { + pfRProtoIP := pfR.GetOrCreateIpv4() + if pfRule.ipv6.dscpSet != nil { + pfRProtoIP.DscpSet = pfRule.ipv6.dscpSet + } + } + + pfRAction := pfR.GetOrCreateAction() + if pfRule.action.decapNI != "" { + pfRAction.DecapNetworkInstance = ygot.String(pfRule.action.decapNI) + } + if pfRule.action.postDecapNI != "" { + pfRAction.PostDecapNetworkInstance = ygot.String(pfRule.action.postDecapNI) + } + if pfRule.action.decapFallbackNI != "" { + pfRAction.DecapFallbackNetworkInstance = ygot.String(pfRule.action.decapFallbackNI) + } + if pfRule.action.networkInstance != "" { + pfRAction.NetworkInstance = ygot.String(pfRule.action.networkInstance) + } + } + + return niP +} + // DeletePolicyForwarding deletes policy configured under given interface. func DeletePolicyForwarding(t *testing.T, dut *ondatra.DUTDevice, portID string) { t.Helper() diff --git a/proto/metadata.proto b/proto/metadata.proto index d95bf4ac224..3264364a028 100644 --- a/proto/metadata.proto +++ b/proto/metadata.proto @@ -18,6 +18,7 @@ package openconfig.testing; import "github.com/openconfig/ondatra/proto/testbed.proto"; + // Metadata about a Feature Profiles test. message Metadata { // UUID of the test. @@ -279,7 +280,8 @@ message Metadata { // Devices require configuring subinterface with tagged vlan for p4rt // packet in. bool p4rt_gdp_requires_dot1q_subinterface = 93; - // ATE port link state operations are a no-op in KNE/virtualized environments. + // ATE port link state operations are a no-op in KNE/virtualized + // environments. bool ate_port_link_state_operations_unsupported = 94; // Creates a user and assigns role/rbac to said user via native model. bool set_native_user = 95; @@ -298,7 +300,8 @@ message Metadata { bool controller_card_cpu_utilization_unsupported = 100; // Device does not support counter for fabric block lost packets. bool fabric_drop_counter_unsupported = 101; - // Device does not support memory utilization related leaves for linecard components. + // Device does not support memory utilization related leaves for linecard + // components. bool linecard_memory_utilization_unsupported = 102; // Device does not support telemetry path // /qos/interfaces/interface/input/virtual-output-queues/voq-interface/queues/queue/state/dropped-pkts. @@ -315,12 +318,13 @@ message Metadata { // Devices do not support telemetry for isis counter: part-changes. // Arista: partnerissuetracker.corp.google.com/317086576 bool isis_counter_part_changes_unsupported = 107; - // Devices do not support threshold container under /components/component/transceiver. + // Devices do not support threshold container under + // /components/component/transceiver. bool transceiver_thresholds_unsupported = 108; // Update interface loopback mode using raw gnmi API due to server version. bool interface_loopback_mode_raw_gnmi = 109; - // Devices do not support showing negotiated tcp mss value in bgp tcp mss telemetry. - // Juniper: b/300499125 + // Devices do not support showing negotiated tcp mss value in bgp tcp mss + // telemetry. Juniper: b/300499125 bool skip_tcp_negotiated_mss_check = 110; // Devices don't support ISIS-Lsp metadata paths: checksum, sequence-number, // remaining-lifetime. @@ -331,8 +335,9 @@ message Metadata { bool skip_fib_failed_traffic_forwarding_check = 113; // QOS requires buffer-allocation-profile configuration bool qos_buffer_allocation_config_required = 114; - // Devices do not support configuring ExtendedNextHopEncoding at the BGP global level. - // Arista: https://partnerissuetracker.corp.google.com/issues/203683090 + // Devices do not support configuring ExtendedNextHopEncoding at the BGP + // global level. Arista: + // https://partnerissuetracker.corp.google.com/issues/203683090 bool bgp_global_extended_next_hop_encoding_unsupported = 115; // OC unsupported for BGP LLGR disable. // Juniper: b/303479602 @@ -340,21 +345,24 @@ message Metadata { // Device does not support tunnel interfaces state paths // Juniper: partnerissuetracker.corp.google.com/300111031 bool tunnel_state_path_unsupported = 117; - // Device does not support tunnel interfaces source and destination address config paths - // Juniper: partnerissuetracker.corp.google.com/300111031 + // Device does not support tunnel interfaces source and destination address + // config paths Juniper: partnerissuetracker.corp.google.com/300111031 bool tunnel_config_path_unsupported = 118; - // Cisco: Device does not support same minimun and maximum threshold value in QOS ECN config. + // Cisco: Device does not support same minimun and maximum threshold value + // in QOS ECN config. bool ecn_same_min_max_threshold_unsupported = 119; // Cisco: QOS requires scheduler configuration. bool qos_scheduler_config_required = 120; - // Cisco: Device does not support set weight config under QOS ECN configuration. + // Cisco: Device does not support set weight config under QOS ECN + // configuration. bool qos_set_weight_config_unsupported = 121; // Cisco: Device does not support these get state path. bool qos_get_state_path_unsupported = 122; // Devices requires enabled leaf under isis level // Juniper: partnerissuetracker.corp.google.com/302661486 bool isis_level_enabled = 123; - // Devices which require to use interface-id format of interface name + .subinterface index with Interface-ref container + // Devices which require to use interface-id format of interface name + + // .subinterface index with Interface-ref container bool interface_ref_interface_id_format = 124; // Devices does not support member link loopback // Juniper: b/307763669 @@ -362,8 +370,8 @@ message Metadata { // Device does not support PLQ operational status check on interface // Juniper: b/308990185 bool skip_plq_interface_oper_status_check = 126; - // Device set received prefix limits explicitly under prefix-limit-received rather than - // "prefix-limit" + // Device set received prefix limits explicitly under prefix-limit-received + // rather than "prefix-limit" bool bgp_explicit_prefix_limit_received = 127; // Device does not configure BGP maximum routes correctly when max-prefixes // leaf is configured @@ -379,14 +387,15 @@ message Metadata { bool missing_hardware_resource_telemetry_before_config = 131; // Device does not support reboot status check on subcomponents. bool gnoi_subcomponent_reboot_status_unsupported = 132; - // Devices exports routes from all protocols to BGP if the export-policy is ACCEPT - // Juniper: b/308970803 + // Devices exports routes from all protocols to BGP if the export-policy is + // ACCEPT Juniper: b/308970803 bool skip_non_bgp_route_export_check = 133; // Devices do not support path // /network-instances/network-instance/protocols/protocol/isis/levels/level/state/metric-style // Arista: https://partnerissuetracker.corp.google.com/issues/317064733 bool isis_metric_style_telemetry_unsupported = 134; - // Devices do not support configuring Interface-ref under Static-Route Next-Hop + // Devices do not support configuring Interface-ref under Static-Route + // Next-Hop bool static_route_next_hop_interface_ref_unsupported = 135; // Devices which does not support nexthop index state // Juniper: b/304729237 @@ -395,7 +404,7 @@ message Metadata { // Juniper: b/319202763 bool enable_flowctrl_flag = 137; // Device doesn't support router advertisement enable and mode config - // Juniper: b/316173974 + // Juniper: b/316173974 bool ipv6_router_advertisement_config_unsupported = 138; // Devices does not support setting prefix limit exceeded flag. // Juniper : b/317181227 @@ -403,27 +412,32 @@ message Metadata { // Skip setting allow-multiple-as while configuring eBGP // Arista: partnerissuetracker.corp.google.com/issues/317422300 bool skip_setting_allow_multiple_as = 140; - //Skip tests with decap encap vrf as PBF action - // Nokia: partnerissuetracker.corp.google.com/issues/323251581 - bool skip_pbf_with_decap_encap_vrf = 141; + // Skip tests with decap encap vrf as PBF action + // Nokia: partnerissuetracker.corp.google.com/issues/323251581 + bool skip_pbf_with_decap_encap_vrf = 141; // Devices which does not support copying TTL. // Juniper: b/307258544 bool ttl_copy_unsupported = 142; // Devices does not support mixed prefix length in gribi. // Juniper: b/307824407 bool gribi_decap_mixed_plen_unsupported = 143; - // Skip setting isis-actions set-level while configuring routing-policy statement action + // Skip setting isis-actions set-level while configuring routing-policy + // statement action bool skip_isis_set_level = 144; - // Skip setting isis-actions set-metric-style-type while configuring routing-policy statement action + // Skip setting isis-actions set-metric-style-type while configuring + // routing-policy statement action bool skip_isis_set_metric_style_type = 145; - // Skip setting match-prefix-set match-set-options while configuring routing-policy statement condition + // Skip setting match-prefix-set match-set-options while configuring + // routing-policy statement condition bool skip_set_rp_match_set_options = 146; - // Skip setting disable-metric-propagation while configuring table-connection + // Skip setting disable-metric-propagation while configuring + // table-connection bool skip_setting_disable_metric_propagation = 147; // Devices do not support BGP conditions match-community-set bool bgp_conditions_match_community_set_unsupported = 148; - // Device requires match condition for ethertype v4 and v6 for default rule with network-instance default-vrf in policy-forwarding. - bool pf_require_match_default_rule = 149; + // Device requires match condition for ethertype v4 and v6 for default rule + // with network-instance default-vrf in policy-forwarding. + bool pf_require_match_default_rule = 149; // Devices missing component tree mapping from hardware port // to optical channel. bool missing_port_to_optical_channel_component_mapping = 150; @@ -436,8 +450,9 @@ message Metadata { // Add missing base config using cli. // Cisco: https://partnerissuetracker.corp.google.com/issues/322291556 bool add_missing_base_config_via_cli = 153; - // skip_macaddress_check returns true if mac address for an interface via gNMI needs to be skipped. - // Cisco: https://partnerissuetracker.corp.google.com/issues/322291556 + // skip_macaddress_check returns true if mac address for an interface via + // gNMI needs to be skipped. Cisco: + // https://partnerissuetracker.corp.google.com/issues/322291556 bool skip_macaddress_check = 154; // Devices are having native telemetry paths for BGP RIB verification. // Juniper : b/306144372 @@ -450,7 +465,8 @@ message Metadata { // as next hop and requires configuring a static ARP entry. // Arista: https://partnerissuetracker.corp.google.com/issues/316593298 bool ipv6_static_route_with_ipv4_next_hop_requires_static_arp = 158; - // Device requires policy-forwarding rules to be in sequential order in the gNMI set-request. + // Device requires policy-forwarding rules to be in sequential order in the + // gNMI set-request. bool pf_require_sequential_order_pbr_rules = 159; // Device telemetry missing next hop metric value. // Arista: https://partnerissuetracker.corp.google.com/issues/321010782 @@ -465,12 +481,14 @@ message Metadata { // min/max/avg. // Arista: https://partnerissuetracker.corp.google.com/issues/319314781 bool missing_zr_optical_channel_tunable_parameters_telemetry = 163; - // Device that does not support packet link qualification reflector packet sent/received stats. + // Device that does not support packet link qualification reflector packet + // sent/received stats. bool plq_reflector_stats_unsupported = 164; // Device that does not support PLQ Generator max_mtu to be atleast >= 8184. - uint32 plq_generator_capabilities_max_mtu = 165; - // Device that does not support PLQ Generator max_pps to be atleast >= 100000000. - uint64 plq_generator_capabilities_max_pps = 166; + uint32 plq_generator_capabilities_max_mtu = 165; + // Device that does not support PLQ Generator max_pps to be atleast >= + // 100000000. + uint64 plq_generator_capabilities_max_pps = 166; // Support for bgp extended community index bool bgp_extended_community_index_unsupported = 167; // Support for bgp community set refs @@ -483,16 +501,62 @@ message Metadata { bool use_vendor_native_tag_set_config = 171; // Skip setting send-community-type in bgp global config bool skip_bgp_send_community_type = 172; - // Device does not have a default deny action in the absence of a route policy + // Device does not have a default deny action in the absence of a route + // policy bool default_import_export_policy = 173; // Support for bgp actions set-community method bool bgp_actions_set_community_method_unsupported = 174; // Ensure no configurations exist under BGP Peer Groups bool set_no_peer_group = 175; + // Bgp community member is a string + bool bgp_community_member_is_a_string = 176; + // Flag to indicate whether IPv4 static routes with IPv6 next-hops are + // unsupported. + bool ipv4_static_route_with_ipv6_nh_unsupported = 177; + // Flag to indicate whether IPv6 static routes with IPv4 next-hops are + // unsupported. + bool ipv6_static_route_with_ipv4_nh_unsupported = 178; + // Flag to indicate support for static routes that simply drop packets + bool static_route_with_drop_nh = 179; + // Flag to indicate support for static routes that can be configured with an + // explicit metric. + bool static_route_with_explicit_metric = 180; + // Support for bgp default import/export policy + bool bgp_default_policy_unsupported = 181; + // Flag to enable bgp explicity on default vrf + // Arista: b/329094094#comment9 + bool explicit_enable_bgp_on_default_vrf = 182; + // tag-set is not a real separate entity, but is embedded in the policy + // statement. this implies that 1. routing policy tag set name needs to be + // ' ' + // 2. only one policy statement can make use of a tag-set, and 3. tag must + // be refered by a policy + bool routing_policy_tag_set_embedded = 183; + // Devices does not support allow multiple as under AFI/SAFI. + // CISCO: b/340859662 + bool skip_afi_safi_path_for_bgp_multiple_as = 184; + // Device does not support regex with routing-policy community-member. + bool community_member_regex_unsupported = 185; + // Support for same import policy attached to all AFIs for given + // (src-protocol, dst-protocol, network-instance) triple Arista: + // b/339645876#comment4 + bool same_policy_attached_to_all_afis = 186; + // Devices needs to skip setting statement for policy to be applied as + // action pass otherwise it will be configured as action done. + // CISCO: b/338523730 + bool skip_setting_statement_for_policy = 187; + // Devices does not support index specific attribute fetching and hence + // wildcards has to be used. + // CISCO: b/338523730 + bool skip_checking_attribute_index = 188; + // Devices does not suppport policy-chaining, so needs to flatten policies + // with multiple statements. + // CISCO: b/338526243 + bool flatten_policy_with_multiple_statements = 189; + // Reserved field numbers and identifiers. reserved 84, 9, 28, 20, 90, 97, 55, 89, 19; } - message PlatformExceptions { Platform platform = 1; Deviations deviations = 2; diff --git a/proto/metadata_go_proto/metadata.pb.go b/proto/metadata_go_proto/metadata.pb.go index 0e09523ea1e..43178dd5a0a 100644 --- a/proto/metadata_go_proto/metadata.pb.go +++ b/proto/metadata_go_proto/metadata.pb.go @@ -14,7 +14,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.33.0 +// protoc-gen-go v1.34.1 // protoc v3.21.12 // source: metadata.proto @@ -560,7 +560,8 @@ type Metadata_Deviations struct { // Devices require configuring subinterface with tagged vlan for p4rt // packet in. P4RtGdpRequiresDot1QSubinterface bool `protobuf:"varint,93,opt,name=p4rt_gdp_requires_dot1q_subinterface,json=p4rtGdpRequiresDot1qSubinterface,proto3" json:"p4rt_gdp_requires_dot1q_subinterface,omitempty"` - // ATE port link state operations are a no-op in KNE/virtualized environments. + // ATE port link state operations are a no-op in KNE/virtualized + // environments. AtePortLinkStateOperationsUnsupported bool `protobuf:"varint,94,opt,name=ate_port_link_state_operations_unsupported,json=atePortLinkStateOperationsUnsupported,proto3" json:"ate_port_link_state_operations_unsupported,omitempty"` // Creates a user and assigns role/rbac to said user via native model. SetNativeUser bool `protobuf:"varint,95,opt,name=set_native_user,json=setNativeUser,proto3" json:"set_native_user,omitempty"` @@ -579,7 +580,8 @@ type Metadata_Deviations struct { ControllerCardCpuUtilizationUnsupported bool `protobuf:"varint,100,opt,name=controller_card_cpu_utilization_unsupported,json=controllerCardCpuUtilizationUnsupported,proto3" json:"controller_card_cpu_utilization_unsupported,omitempty"` // Device does not support counter for fabric block lost packets. FabricDropCounterUnsupported bool `protobuf:"varint,101,opt,name=fabric_drop_counter_unsupported,json=fabricDropCounterUnsupported,proto3" json:"fabric_drop_counter_unsupported,omitempty"` - // Device does not support memory utilization related leaves for linecard components. + // Device does not support memory utilization related leaves for linecard + // components. LinecardMemoryUtilizationUnsupported bool `protobuf:"varint,102,opt,name=linecard_memory_utilization_unsupported,json=linecardMemoryUtilizationUnsupported,proto3" json:"linecard_memory_utilization_unsupported,omitempty"` // Device does not support telemetry path // /qos/interfaces/interface/input/virtual-output-queues/voq-interface/queues/queue/state/dropped-pkts. @@ -596,12 +598,13 @@ type Metadata_Deviations struct { // Devices do not support telemetry for isis counter: part-changes. // Arista: partnerissuetracker.corp.google.com/317086576 IsisCounterPartChangesUnsupported bool `protobuf:"varint,107,opt,name=isis_counter_part_changes_unsupported,json=isisCounterPartChangesUnsupported,proto3" json:"isis_counter_part_changes_unsupported,omitempty"` - // Devices do not support threshold container under /components/component/transceiver. + // Devices do not support threshold container under + // /components/component/transceiver. TransceiverThresholdsUnsupported bool `protobuf:"varint,108,opt,name=transceiver_thresholds_unsupported,json=transceiverThresholdsUnsupported,proto3" json:"transceiver_thresholds_unsupported,omitempty"` // Update interface loopback mode using raw gnmi API due to server version. InterfaceLoopbackModeRawGnmi bool `protobuf:"varint,109,opt,name=interface_loopback_mode_raw_gnmi,json=interfaceLoopbackModeRawGnmi,proto3" json:"interface_loopback_mode_raw_gnmi,omitempty"` - // Devices do not support showing negotiated tcp mss value in bgp tcp mss telemetry. - // Juniper: b/300499125 + // Devices do not support showing negotiated tcp mss value in bgp tcp mss + // telemetry. Juniper: b/300499125 SkipTcpNegotiatedMssCheck bool `protobuf:"varint,110,opt,name=skip_tcp_negotiated_mss_check,json=skipTcpNegotiatedMssCheck,proto3" json:"skip_tcp_negotiated_mss_check,omitempty"` // Devices don't support ISIS-Lsp metadata paths: checksum, sequence-number, // remaining-lifetime. @@ -612,8 +615,9 @@ type Metadata_Deviations struct { SkipFibFailedTrafficForwardingCheck bool `protobuf:"varint,113,opt,name=skip_fib_failed_traffic_forwarding_check,json=skipFibFailedTrafficForwardingCheck,proto3" json:"skip_fib_failed_traffic_forwarding_check,omitempty"` // QOS requires buffer-allocation-profile configuration QosBufferAllocationConfigRequired bool `protobuf:"varint,114,opt,name=qos_buffer_allocation_config_required,json=qosBufferAllocationConfigRequired,proto3" json:"qos_buffer_allocation_config_required,omitempty"` - // Devices do not support configuring ExtendedNextHopEncoding at the BGP global level. - // Arista: https://partnerissuetracker.corp.google.com/issues/203683090 + // Devices do not support configuring ExtendedNextHopEncoding at the BGP + // global level. Arista: + // https://partnerissuetracker.corp.google.com/issues/203683090 BgpGlobalExtendedNextHopEncodingUnsupported bool `protobuf:"varint,115,opt,name=bgp_global_extended_next_hop_encoding_unsupported,json=bgpGlobalExtendedNextHopEncodingUnsupported,proto3" json:"bgp_global_extended_next_hop_encoding_unsupported,omitempty"` // OC unsupported for BGP LLGR disable. // Juniper: b/303479602 @@ -621,21 +625,24 @@ type Metadata_Deviations struct { // Device does not support tunnel interfaces state paths // Juniper: partnerissuetracker.corp.google.com/300111031 TunnelStatePathUnsupported bool `protobuf:"varint,117,opt,name=tunnel_state_path_unsupported,json=tunnelStatePathUnsupported,proto3" json:"tunnel_state_path_unsupported,omitempty"` - // Device does not support tunnel interfaces source and destination address config paths - // Juniper: partnerissuetracker.corp.google.com/300111031 + // Device does not support tunnel interfaces source and destination address + // config paths Juniper: partnerissuetracker.corp.google.com/300111031 TunnelConfigPathUnsupported bool `protobuf:"varint,118,opt,name=tunnel_config_path_unsupported,json=tunnelConfigPathUnsupported,proto3" json:"tunnel_config_path_unsupported,omitempty"` - // Cisco: Device does not support same minimun and maximum threshold value in QOS ECN config. + // Cisco: Device does not support same minimun and maximum threshold value + // in QOS ECN config. EcnSameMinMaxThresholdUnsupported bool `protobuf:"varint,119,opt,name=ecn_same_min_max_threshold_unsupported,json=ecnSameMinMaxThresholdUnsupported,proto3" json:"ecn_same_min_max_threshold_unsupported,omitempty"` // Cisco: QOS requires scheduler configuration. QosSchedulerConfigRequired bool `protobuf:"varint,120,opt,name=qos_scheduler_config_required,json=qosSchedulerConfigRequired,proto3" json:"qos_scheduler_config_required,omitempty"` - // Cisco: Device does not support set weight config under QOS ECN configuration. + // Cisco: Device does not support set weight config under QOS ECN + // configuration. QosSetWeightConfigUnsupported bool `protobuf:"varint,121,opt,name=qos_set_weight_config_unsupported,json=qosSetWeightConfigUnsupported,proto3" json:"qos_set_weight_config_unsupported,omitempty"` // Cisco: Device does not support these get state path. QosGetStatePathUnsupported bool `protobuf:"varint,122,opt,name=qos_get_state_path_unsupported,json=qosGetStatePathUnsupported,proto3" json:"qos_get_state_path_unsupported,omitempty"` // Devices requires enabled leaf under isis level // Juniper: partnerissuetracker.corp.google.com/302661486 IsisLevelEnabled bool `protobuf:"varint,123,opt,name=isis_level_enabled,json=isisLevelEnabled,proto3" json:"isis_level_enabled,omitempty"` - // Devices which require to use interface-id format of interface name + .subinterface index with Interface-ref container + // Devices which require to use interface-id format of interface name + + // .subinterface index with Interface-ref container InterfaceRefInterfaceIdFormat bool `protobuf:"varint,124,opt,name=interface_ref_interface_id_format,json=interfaceRefInterfaceIdFormat,proto3" json:"interface_ref_interface_id_format,omitempty"` // Devices does not support member link loopback // Juniper: b/307763669 @@ -643,8 +650,8 @@ type Metadata_Deviations struct { // Device does not support PLQ operational status check on interface // Juniper: b/308990185 SkipPlqInterfaceOperStatusCheck bool `protobuf:"varint,126,opt,name=skip_plq_interface_oper_status_check,json=skipPlqInterfaceOperStatusCheck,proto3" json:"skip_plq_interface_oper_status_check,omitempty"` - // Device set received prefix limits explicitly under prefix-limit-received rather than - // "prefix-limit" + // Device set received prefix limits explicitly under prefix-limit-received + // rather than "prefix-limit" BgpExplicitPrefixLimitReceived bool `protobuf:"varint,127,opt,name=bgp_explicit_prefix_limit_received,json=bgpExplicitPrefixLimitReceived,proto3" json:"bgp_explicit_prefix_limit_received,omitempty"` // Device does not configure BGP maximum routes correctly when max-prefixes // leaf is configured @@ -660,14 +667,15 @@ type Metadata_Deviations struct { MissingHardwareResourceTelemetryBeforeConfig bool `protobuf:"varint,131,opt,name=missing_hardware_resource_telemetry_before_config,json=missingHardwareResourceTelemetryBeforeConfig,proto3" json:"missing_hardware_resource_telemetry_before_config,omitempty"` // Device does not support reboot status check on subcomponents. GnoiSubcomponentRebootStatusUnsupported bool `protobuf:"varint,132,opt,name=gnoi_subcomponent_reboot_status_unsupported,json=gnoiSubcomponentRebootStatusUnsupported,proto3" json:"gnoi_subcomponent_reboot_status_unsupported,omitempty"` - // Devices exports routes from all protocols to BGP if the export-policy is ACCEPT - // Juniper: b/308970803 + // Devices exports routes from all protocols to BGP if the export-policy is + // ACCEPT Juniper: b/308970803 SkipNonBgpRouteExportCheck bool `protobuf:"varint,133,opt,name=skip_non_bgp_route_export_check,json=skipNonBgpRouteExportCheck,proto3" json:"skip_non_bgp_route_export_check,omitempty"` // Devices do not support path // /network-instances/network-instance/protocols/protocol/isis/levels/level/state/metric-style // Arista: https://partnerissuetracker.corp.google.com/issues/317064733 IsisMetricStyleTelemetryUnsupported bool `protobuf:"varint,134,opt,name=isis_metric_style_telemetry_unsupported,json=isisMetricStyleTelemetryUnsupported,proto3" json:"isis_metric_style_telemetry_unsupported,omitempty"` - // Devices do not support configuring Interface-ref under Static-Route Next-Hop + // Devices do not support configuring Interface-ref under Static-Route + // Next-Hop StaticRouteNextHopInterfaceRefUnsupported bool `protobuf:"varint,135,opt,name=static_route_next_hop_interface_ref_unsupported,json=staticRouteNextHopInterfaceRefUnsupported,proto3" json:"static_route_next_hop_interface_ref_unsupported,omitempty"` // Devices which does not support nexthop index state // Juniper: b/304729237 @@ -685,7 +693,8 @@ type Metadata_Deviations struct { // Arista: partnerissuetracker.corp.google.com/issues/317422300 SkipSettingAllowMultipleAs bool `protobuf:"varint,140,opt,name=skip_setting_allow_multiple_as,json=skipSettingAllowMultipleAs,proto3" json:"skip_setting_allow_multiple_as,omitempty"` // Skip tests with decap encap vrf as PBF action - // Nokia: partnerissuetracker.corp.google.com/issues/323251581 + // + // Nokia: partnerissuetracker.corp.google.com/issues/323251581 SkipPbfWithDecapEncapVrf bool `protobuf:"varint,141,opt,name=skip_pbf_with_decap_encap_vrf,json=skipPbfWithDecapEncapVrf,proto3" json:"skip_pbf_with_decap_encap_vrf,omitempty"` // Devices which does not support copying TTL. // Juniper: b/307258544 @@ -693,17 +702,22 @@ type Metadata_Deviations struct { // Devices does not support mixed prefix length in gribi. // Juniper: b/307824407 GribiDecapMixedPlenUnsupported bool `protobuf:"varint,143,opt,name=gribi_decap_mixed_plen_unsupported,json=gribiDecapMixedPlenUnsupported,proto3" json:"gribi_decap_mixed_plen_unsupported,omitempty"` - // Skip setting isis-actions set-level while configuring routing-policy statement action + // Skip setting isis-actions set-level while configuring routing-policy + // statement action SkipIsisSetLevel bool `protobuf:"varint,144,opt,name=skip_isis_set_level,json=skipIsisSetLevel,proto3" json:"skip_isis_set_level,omitempty"` - // Skip setting isis-actions set-metric-style-type while configuring routing-policy statement action + // Skip setting isis-actions set-metric-style-type while configuring + // routing-policy statement action SkipIsisSetMetricStyleType bool `protobuf:"varint,145,opt,name=skip_isis_set_metric_style_type,json=skipIsisSetMetricStyleType,proto3" json:"skip_isis_set_metric_style_type,omitempty"` - // Skip setting match-prefix-set match-set-options while configuring routing-policy statement condition + // Skip setting match-prefix-set match-set-options while configuring + // routing-policy statement condition SkipSetRpMatchSetOptions bool `protobuf:"varint,146,opt,name=skip_set_rp_match_set_options,json=skipSetRpMatchSetOptions,proto3" json:"skip_set_rp_match_set_options,omitempty"` - // Skip setting disable-metric-propagation while configuring table-connection + // Skip setting disable-metric-propagation while configuring + // table-connection SkipSettingDisableMetricPropagation bool `protobuf:"varint,147,opt,name=skip_setting_disable_metric_propagation,json=skipSettingDisableMetricPropagation,proto3" json:"skip_setting_disable_metric_propagation,omitempty"` // Devices do not support BGP conditions match-community-set BgpConditionsMatchCommunitySetUnsupported bool `protobuf:"varint,148,opt,name=bgp_conditions_match_community_set_unsupported,json=bgpConditionsMatchCommunitySetUnsupported,proto3" json:"bgp_conditions_match_community_set_unsupported,omitempty"` - // Device requires match condition for ethertype v4 and v6 for default rule with network-instance default-vrf in policy-forwarding. + // Device requires match condition for ethertype v4 and v6 for default rule + // with network-instance default-vrf in policy-forwarding. PfRequireMatchDefaultRule bool `protobuf:"varint,149,opt,name=pf_require_match_default_rule,json=pfRequireMatchDefaultRule,proto3" json:"pf_require_match_default_rule,omitempty"` // Devices missing component tree mapping from hardware port // to optical channel. @@ -717,8 +731,9 @@ type Metadata_Deviations struct { // Add missing base config using cli. // Cisco: https://partnerissuetracker.corp.google.com/issues/322291556 AddMissingBaseConfigViaCli bool `protobuf:"varint,153,opt,name=add_missing_base_config_via_cli,json=addMissingBaseConfigViaCli,proto3" json:"add_missing_base_config_via_cli,omitempty"` - // skip_macaddress_check returns true if mac address for an interface via gNMI needs to be skipped. - // Cisco: https://partnerissuetracker.corp.google.com/issues/322291556 + // skip_macaddress_check returns true if mac address for an interface via + // gNMI needs to be skipped. Cisco: + // https://partnerissuetracker.corp.google.com/issues/322291556 SkipMacaddressCheck bool `protobuf:"varint,154,opt,name=skip_macaddress_check,json=skipMacaddressCheck,proto3" json:"skip_macaddress_check,omitempty"` // Devices are having native telemetry paths for BGP RIB verification. // Juniper : b/306144372 @@ -731,7 +746,8 @@ type Metadata_Deviations struct { // as next hop and requires configuring a static ARP entry. // Arista: https://partnerissuetracker.corp.google.com/issues/316593298 Ipv6StaticRouteWithIpv4NextHopRequiresStaticArp bool `protobuf:"varint,158,opt,name=ipv6_static_route_with_ipv4_next_hop_requires_static_arp,json=ipv6StaticRouteWithIpv4NextHopRequiresStaticArp,proto3" json:"ipv6_static_route_with_ipv4_next_hop_requires_static_arp,omitempty"` - // Device requires policy-forwarding rules to be in sequential order in the gNMI set-request. + // Device requires policy-forwarding rules to be in sequential order in the + // gNMI set-request. PfRequireSequentialOrderPbrRules bool `protobuf:"varint,159,opt,name=pf_require_sequential_order_pbr_rules,json=pfRequireSequentialOrderPbrRules,proto3" json:"pf_require_sequential_order_pbr_rules,omitempty"` // Device telemetry missing next hop metric value. // Arista: https://partnerissuetracker.corp.google.com/issues/321010782 @@ -746,11 +762,13 @@ type Metadata_Deviations struct { // min/max/avg. // Arista: https://partnerissuetracker.corp.google.com/issues/319314781 MissingZrOpticalChannelTunableParametersTelemetry bool `protobuf:"varint,163,opt,name=missing_zr_optical_channel_tunable_parameters_telemetry,json=missingZrOpticalChannelTunableParametersTelemetry,proto3" json:"missing_zr_optical_channel_tunable_parameters_telemetry,omitempty"` - // Device that does not support packet link qualification reflector packet sent/received stats. + // Device that does not support packet link qualification reflector packet + // sent/received stats. PlqReflectorStatsUnsupported bool `protobuf:"varint,164,opt,name=plq_reflector_stats_unsupported,json=plqReflectorStatsUnsupported,proto3" json:"plq_reflector_stats_unsupported,omitempty"` // Device that does not support PLQ Generator max_mtu to be atleast >= 8184. PlqGeneratorCapabilitiesMaxMtu uint32 `protobuf:"varint,165,opt,name=plq_generator_capabilities_max_mtu,json=plqGeneratorCapabilitiesMaxMtu,proto3" json:"plq_generator_capabilities_max_mtu,omitempty"` - // Device that does not support PLQ Generator max_pps to be atleast >= 100000000. + // Device that does not support PLQ Generator max_pps to be atleast >= + // 100000000. PlqGeneratorCapabilitiesMaxPps uint64 `protobuf:"varint,166,opt,name=plq_generator_capabilities_max_pps,json=plqGeneratorCapabilitiesMaxPps,proto3" json:"plq_generator_capabilities_max_pps,omitempty"` // Support for bgp extended community index BgpExtendedCommunityIndexUnsupported bool `protobuf:"varint,167,opt,name=bgp_extended_community_index_unsupported,json=bgpExtendedCommunityIndexUnsupported,proto3" json:"bgp_extended_community_index_unsupported,omitempty"` @@ -764,12 +782,58 @@ type Metadata_Deviations struct { UseVendorNativeTagSetConfig bool `protobuf:"varint,171,opt,name=use_vendor_native_tag_set_config,json=useVendorNativeTagSetConfig,proto3" json:"use_vendor_native_tag_set_config,omitempty"` // Skip setting send-community-type in bgp global config SkipBgpSendCommunityType bool `protobuf:"varint,172,opt,name=skip_bgp_send_community_type,json=skipBgpSendCommunityType,proto3" json:"skip_bgp_send_community_type,omitempty"` - // Device does not have a default deny action in the absence of a route policy + // Device does not have a default deny action in the absence of a route + // policy DefaultImportExportPolicy bool `protobuf:"varint,173,opt,name=default_import_export_policy,json=defaultImportExportPolicy,proto3" json:"default_import_export_policy,omitempty"` // Support for bgp actions set-community method BgpActionsSetCommunityMethodUnsupported bool `protobuf:"varint,174,opt,name=bgp_actions_set_community_method_unsupported,json=bgpActionsSetCommunityMethodUnsupported,proto3" json:"bgp_actions_set_community_method_unsupported,omitempty"` // Ensure no configurations exist under BGP Peer Groups SetNoPeerGroup bool `protobuf:"varint,175,opt,name=set_no_peer_group,json=setNoPeerGroup,proto3" json:"set_no_peer_group,omitempty"` + // Bgp community member is a string + BgpCommunityMemberIsAString bool `protobuf:"varint,176,opt,name=bgp_community_member_is_a_string,json=bgpCommunityMemberIsAString,proto3" json:"bgp_community_member_is_a_string,omitempty"` + // Flag to indicate whether IPv4 static routes with IPv6 next-hops are + // unsupported. + Ipv4StaticRouteWithIpv6NhUnsupported bool `protobuf:"varint,177,opt,name=ipv4_static_route_with_ipv6_nh_unsupported,json=ipv4StaticRouteWithIpv6NhUnsupported,proto3" json:"ipv4_static_route_with_ipv6_nh_unsupported,omitempty"` + // Flag to indicate whether IPv6 static routes with IPv4 next-hops are + // unsupported. + Ipv6StaticRouteWithIpv4NhUnsupported bool `protobuf:"varint,178,opt,name=ipv6_static_route_with_ipv4_nh_unsupported,json=ipv6StaticRouteWithIpv4NhUnsupported,proto3" json:"ipv6_static_route_with_ipv4_nh_unsupported,omitempty"` + // Flag to indicate support for static routes that simply drop packets + StaticRouteWithDropNh bool `protobuf:"varint,179,opt,name=static_route_with_drop_nh,json=staticRouteWithDropNh,proto3" json:"static_route_with_drop_nh,omitempty"` + // Flag to indicate support for static routes that can be configured with an + // explicit metric. + StaticRouteWithExplicitMetric bool `protobuf:"varint,180,opt,name=static_route_with_explicit_metric,json=staticRouteWithExplicitMetric,proto3" json:"static_route_with_explicit_metric,omitempty"` + // Support for bgp default import/export policy + BgpDefaultPolicyUnsupported bool `protobuf:"varint,181,opt,name=bgp_default_policy_unsupported,json=bgpDefaultPolicyUnsupported,proto3" json:"bgp_default_policy_unsupported,omitempty"` + // Flag to enable bgp explicity on default vrf + // Arista: b/329094094#comment9 + ExplicitEnableBgpOnDefaultVrf bool `protobuf:"varint,182,opt,name=explicit_enable_bgp_on_default_vrf,json=explicitEnableBgpOnDefaultVrf,proto3" json:"explicit_enable_bgp_on_default_vrf,omitempty"` + // tag-set is not a real separate entity, but is embedded in the policy + // statement. this implies that 1. routing policy tag set name needs to be + // ' ' + // 2. only one policy statement can make use of a tag-set, and 3. tag must + // be refered by a policy + RoutingPolicyTagSetEmbedded bool `protobuf:"varint,183,opt,name=routing_policy_tag_set_embedded,json=routingPolicyTagSetEmbedded,proto3" json:"routing_policy_tag_set_embedded,omitempty"` + // Devices does not support allow multiple as under AFI/SAFI. + // CISCO: b/340859662 + SkipAfiSafiPathForBgpMultipleAs bool `protobuf:"varint,184,opt,name=skip_afi_safi_path_for_bgp_multiple_as,json=skipAfiSafiPathForBgpMultipleAs,proto3" json:"skip_afi_safi_path_for_bgp_multiple_as,omitempty"` + // Device does not support regex with routing-policy community-member. + CommunityMemberRegexUnsupported bool `protobuf:"varint,185,opt,name=community_member_regex_unsupported,json=communityMemberRegexUnsupported,proto3" json:"community_member_regex_unsupported,omitempty"` + // Support for same import policy attached to all AFIs for given + // (src-protocol, dst-protocol, network-instance) triple Arista: + // b/339645876#comment4 + SamePolicyAttachedToAllAfis bool `protobuf:"varint,186,opt,name=same_policy_attached_to_all_afis,json=samePolicyAttachedToAllAfis,proto3" json:"same_policy_attached_to_all_afis,omitempty"` + // Devices needs to skip setting statement for policy to be applied as + // action pass otherwise it will be configured as action done. + // CISCO: b/338523730 + SkipSettingStatementForPolicy bool `protobuf:"varint,187,opt,name=skip_setting_statement_for_policy,json=skipSettingStatementForPolicy,proto3" json:"skip_setting_statement_for_policy,omitempty"` + // Devices does not support index specific attribute fetching and hence + // wildcards has to be used. + // CISCO: b/338523730 + SkipCheckingAttributeIndex bool `protobuf:"varint,188,opt,name=skip_checking_attribute_index,json=skipCheckingAttributeIndex,proto3" json:"skip_checking_attribute_index,omitempty"` + // Devices does not suppport policy-chaining, so needs to flatten policies + // with multiple statements. + // CISCO: b/338526243 + FlattenPolicyWithMultipleStatements bool `protobuf:"varint,189,opt,name=flatten_policy_with_multiple_statements,json=flattenPolicyWithMultipleStatements,proto3" json:"flatten_policy_with_multiple_statements,omitempty"` } func (x *Metadata_Deviations) Reset() { @@ -1917,6 +1981,104 @@ func (x *Metadata_Deviations) GetSetNoPeerGroup() bool { return false } +func (x *Metadata_Deviations) GetBgpCommunityMemberIsAString() bool { + if x != nil { + return x.BgpCommunityMemberIsAString + } + return false +} + +func (x *Metadata_Deviations) GetIpv4StaticRouteWithIpv6NhUnsupported() bool { + if x != nil { + return x.Ipv4StaticRouteWithIpv6NhUnsupported + } + return false +} + +func (x *Metadata_Deviations) GetIpv6StaticRouteWithIpv4NhUnsupported() bool { + if x != nil { + return x.Ipv6StaticRouteWithIpv4NhUnsupported + } + return false +} + +func (x *Metadata_Deviations) GetStaticRouteWithDropNh() bool { + if x != nil { + return x.StaticRouteWithDropNh + } + return false +} + +func (x *Metadata_Deviations) GetStaticRouteWithExplicitMetric() bool { + if x != nil { + return x.StaticRouteWithExplicitMetric + } + return false +} + +func (x *Metadata_Deviations) GetBgpDefaultPolicyUnsupported() bool { + if x != nil { + return x.BgpDefaultPolicyUnsupported + } + return false +} + +func (x *Metadata_Deviations) GetExplicitEnableBgpOnDefaultVrf() bool { + if x != nil { + return x.ExplicitEnableBgpOnDefaultVrf + } + return false +} + +func (x *Metadata_Deviations) GetRoutingPolicyTagSetEmbedded() bool { + if x != nil { + return x.RoutingPolicyTagSetEmbedded + } + return false +} + +func (x *Metadata_Deviations) GetSkipAfiSafiPathForBgpMultipleAs() bool { + if x != nil { + return x.SkipAfiSafiPathForBgpMultipleAs + } + return false +} + +func (x *Metadata_Deviations) GetCommunityMemberRegexUnsupported() bool { + if x != nil { + return x.CommunityMemberRegexUnsupported + } + return false +} + +func (x *Metadata_Deviations) GetSamePolicyAttachedToAllAfis() bool { + if x != nil { + return x.SamePolicyAttachedToAllAfis + } + return false +} + +func (x *Metadata_Deviations) GetSkipSettingStatementForPolicy() bool { + if x != nil { + return x.SkipSettingStatementForPolicy + } + return false +} + +func (x *Metadata_Deviations) GetSkipCheckingAttributeIndex() bool { + if x != nil { + return x.SkipCheckingAttributeIndex + } + return false +} + +func (x *Metadata_Deviations) GetFlattenPolicyWithMultipleStatements() bool { + if x != nil { + return x.FlattenPolicyWithMultipleStatements + } + return false +} + type Metadata_PlatformExceptions struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1980,7 +2142,7 @@ var file_metadata_proto_rawDesc = []byte{ 0x74, 0x69, 0x6e, 0x67, 0x1a, 0x31, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x6f, 0x6e, 0x64, 0x61, 0x74, 0x72, 0x61, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x62, 0x65, - 0x64, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xeb, 0x62, 0x0a, 0x08, 0x4d, 0x65, 0x74, 0x61, + 0x64, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x96, 0x6b, 0x0a, 0x08, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x75, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x75, 0x69, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x70, 0x6c, 0x61, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x6c, 0x61, 0x6e, 0x49, @@ -2014,7 +2176,7 @@ var file_metadata_proto_rawDesc = []byte{ 0x67, 0x65, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x14, 0x73, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x67, 0x65, 0x78, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x52, 0x0e, 0x68, 0x61, 0x72, 0x64, 0x77, 0x61, 0x72, 0x65, 0x5f, - 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x1a, 0xbe, 0x5a, 0x0a, 0x0a, 0x44, 0x65, 0x76, 0x69, 0x61, 0x74, + 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x1a, 0xe9, 0x62, 0x0a, 0x0a, 0x44, 0x65, 0x76, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x30, 0x0a, 0x14, 0x69, 0x70, 0x76, 0x34, 0x5f, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x69, 0x70, 0x76, 0x34, 0x4d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x45, @@ -2735,43 +2897,110 @@ var file_metadata_proto_rawDesc = []byte{ 0x72, 0x74, 0x65, 0x64, 0x12, 0x2a, 0x0a, 0x11, 0x73, 0x65, 0x74, 0x5f, 0x6e, 0x6f, 0x5f, 0x70, 0x65, 0x65, 0x72, 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0xaf, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x73, 0x65, 0x74, 0x4e, 0x6f, 0x50, 0x65, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, - 0x4a, 0x04, 0x08, 0x54, 0x10, 0x55, 0x4a, 0x04, 0x08, 0x09, 0x10, 0x0a, 0x4a, 0x04, 0x08, 0x1c, - 0x10, 0x1d, 0x4a, 0x04, 0x08, 0x14, 0x10, 0x15, 0x4a, 0x04, 0x08, 0x5a, 0x10, 0x5b, 0x4a, 0x04, - 0x08, 0x61, 0x10, 0x62, 0x4a, 0x04, 0x08, 0x37, 0x10, 0x38, 0x4a, 0x04, 0x08, 0x59, 0x10, 0x5a, - 0x4a, 0x04, 0x08, 0x13, 0x10, 0x14, 0x1a, 0xa0, 0x01, 0x0a, 0x12, 0x50, 0x6c, 0x61, 0x74, 0x66, - 0x6f, 0x72, 0x6d, 0x45, 0x78, 0x63, 0x65, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x41, 0x0a, - 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x25, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x74, 0x65, 0x73, - 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x50, 0x6c, - 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x52, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, - 0x12, 0x47, 0x0a, 0x0a, 0x64, 0x65, 0x76, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x0a, 0x64, - 0x65, 0x76, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xfa, 0x01, 0x0a, 0x07, 0x54, 0x65, - 0x73, 0x74, 0x62, 0x65, 0x64, 0x12, 0x17, 0x0a, 0x13, 0x54, 0x45, 0x53, 0x54, 0x42, 0x45, 0x44, - 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0f, - 0x0a, 0x0b, 0x54, 0x45, 0x53, 0x54, 0x42, 0x45, 0x44, 0x5f, 0x44, 0x55, 0x54, 0x10, 0x01, 0x12, - 0x1a, 0x0a, 0x16, 0x54, 0x45, 0x53, 0x54, 0x42, 0x45, 0x44, 0x5f, 0x44, 0x55, 0x54, 0x5f, 0x44, - 0x55, 0x54, 0x5f, 0x34, 0x4c, 0x49, 0x4e, 0x4b, 0x53, 0x10, 0x02, 0x12, 0x1a, 0x0a, 0x16, 0x54, - 0x45, 0x53, 0x54, 0x42, 0x45, 0x44, 0x5f, 0x44, 0x55, 0x54, 0x5f, 0x41, 0x54, 0x45, 0x5f, 0x32, - 0x4c, 0x49, 0x4e, 0x4b, 0x53, 0x10, 0x03, 0x12, 0x1a, 0x0a, 0x16, 0x54, 0x45, 0x53, 0x54, 0x42, - 0x45, 0x44, 0x5f, 0x44, 0x55, 0x54, 0x5f, 0x41, 0x54, 0x45, 0x5f, 0x34, 0x4c, 0x49, 0x4e, 0x4b, - 0x53, 0x10, 0x04, 0x12, 0x1e, 0x0a, 0x1a, 0x54, 0x45, 0x53, 0x54, 0x42, 0x45, 0x44, 0x5f, 0x44, - 0x55, 0x54, 0x5f, 0x41, 0x54, 0x45, 0x5f, 0x39, 0x4c, 0x49, 0x4e, 0x4b, 0x53, 0x5f, 0x4c, 0x41, - 0x47, 0x10, 0x05, 0x12, 0x1e, 0x0a, 0x1a, 0x54, 0x45, 0x53, 0x54, 0x42, 0x45, 0x44, 0x5f, 0x44, - 0x55, 0x54, 0x5f, 0x44, 0x55, 0x54, 0x5f, 0x41, 0x54, 0x45, 0x5f, 0x32, 0x4c, 0x49, 0x4e, 0x4b, - 0x53, 0x10, 0x06, 0x12, 0x1a, 0x0a, 0x16, 0x54, 0x45, 0x53, 0x54, 0x42, 0x45, 0x44, 0x5f, 0x44, - 0x55, 0x54, 0x5f, 0x41, 0x54, 0x45, 0x5f, 0x38, 0x4c, 0x49, 0x4e, 0x4b, 0x53, 0x10, 0x07, 0x12, - 0x15, 0x0a, 0x11, 0x54, 0x45, 0x53, 0x54, 0x42, 0x45, 0x44, 0x5f, 0x44, 0x55, 0x54, 0x5f, 0x34, - 0x30, 0x30, 0x5a, 0x52, 0x10, 0x08, 0x22, 0x6d, 0x0a, 0x04, 0x54, 0x61, 0x67, 0x73, 0x12, 0x14, - 0x0a, 0x10, 0x54, 0x41, 0x47, 0x53, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, - 0x45, 0x44, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x54, 0x41, 0x47, 0x53, 0x5f, 0x41, 0x47, 0x47, - 0x52, 0x45, 0x47, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x01, 0x12, 0x18, 0x0a, 0x14, 0x54, 0x41, - 0x47, 0x53, 0x5f, 0x44, 0x41, 0x54, 0x41, 0x43, 0x45, 0x4e, 0x54, 0x45, 0x52, 0x5f, 0x45, 0x44, - 0x47, 0x45, 0x10, 0x02, 0x12, 0x0d, 0x0a, 0x09, 0x54, 0x41, 0x47, 0x53, 0x5f, 0x45, 0x44, 0x47, - 0x45, 0x10, 0x03, 0x12, 0x10, 0x0a, 0x0c, 0x54, 0x41, 0x47, 0x53, 0x5f, 0x54, 0x52, 0x41, 0x4e, - 0x53, 0x49, 0x54, 0x10, 0x04, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x12, 0x46, 0x0a, 0x20, 0x62, 0x67, 0x70, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, + 0x79, 0x5f, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x69, 0x73, 0x5f, 0x61, 0x5f, 0x73, 0x74, + 0x72, 0x69, 0x6e, 0x67, 0x18, 0xb0, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1b, 0x62, 0x67, 0x70, + 0x43, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x79, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x49, + 0x73, 0x41, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x59, 0x0a, 0x2a, 0x69, 0x70, 0x76, 0x34, + 0x5f, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x77, 0x69, + 0x74, 0x68, 0x5f, 0x69, 0x70, 0x76, 0x36, 0x5f, 0x6e, 0x68, 0x5f, 0x75, 0x6e, 0x73, 0x75, 0x70, + 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x18, 0xb1, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x24, 0x69, + 0x70, 0x76, 0x34, 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x57, 0x69, + 0x74, 0x68, 0x49, 0x70, 0x76, 0x36, 0x4e, 0x68, 0x55, 0x6e, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, + 0x74, 0x65, 0x64, 0x12, 0x59, 0x0a, 0x2a, 0x69, 0x70, 0x76, 0x36, 0x5f, 0x73, 0x74, 0x61, 0x74, + 0x69, 0x63, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x69, 0x70, + 0x76, 0x34, 0x5f, 0x6e, 0x68, 0x5f, 0x75, 0x6e, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, + 0x64, 0x18, 0xb2, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x24, 0x69, 0x70, 0x76, 0x36, 0x53, 0x74, + 0x61, 0x74, 0x69, 0x63, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x57, 0x69, 0x74, 0x68, 0x49, 0x70, 0x76, + 0x34, 0x4e, 0x68, 0x55, 0x6e, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x12, 0x39, + 0x0a, 0x19, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x77, + 0x69, 0x74, 0x68, 0x5f, 0x64, 0x72, 0x6f, 0x70, 0x5f, 0x6e, 0x68, 0x18, 0xb3, 0x01, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x15, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x57, + 0x69, 0x74, 0x68, 0x44, 0x72, 0x6f, 0x70, 0x4e, 0x68, 0x12, 0x49, 0x0a, 0x21, 0x73, 0x74, 0x61, + 0x74, 0x69, 0x63, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x65, + 0x78, 0x70, 0x6c, 0x69, 0x63, 0x69, 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x18, 0xb4, + 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1d, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x52, 0x6f, 0x75, + 0x74, 0x65, 0x57, 0x69, 0x74, 0x68, 0x45, 0x78, 0x70, 0x6c, 0x69, 0x63, 0x69, 0x74, 0x4d, 0x65, + 0x74, 0x72, 0x69, 0x63, 0x12, 0x44, 0x0a, 0x1e, 0x62, 0x67, 0x70, 0x5f, 0x64, 0x65, 0x66, 0x61, + 0x75, 0x6c, 0x74, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5f, 0x75, 0x6e, 0x73, 0x75, 0x70, + 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x18, 0xb5, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1b, 0x62, + 0x67, 0x70, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x55, + 0x6e, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x12, 0x4a, 0x0a, 0x22, 0x65, 0x78, + 0x70, 0x6c, 0x69, 0x63, 0x69, 0x74, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x62, 0x67, + 0x70, 0x5f, 0x6f, 0x6e, 0x5f, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x76, 0x72, 0x66, + 0x18, 0xb6, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1d, 0x65, 0x78, 0x70, 0x6c, 0x69, 0x63, 0x69, + 0x74, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x42, 0x67, 0x70, 0x4f, 0x6e, 0x44, 0x65, 0x66, 0x61, + 0x75, 0x6c, 0x74, 0x56, 0x72, 0x66, 0x12, 0x45, 0x0a, 0x1f, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, + 0x67, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5f, 0x74, 0x61, 0x67, 0x5f, 0x73, 0x65, 0x74, + 0x5f, 0x65, 0x6d, 0x62, 0x65, 0x64, 0x64, 0x65, 0x64, 0x18, 0xb7, 0x01, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x1b, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x54, + 0x61, 0x67, 0x53, 0x65, 0x74, 0x45, 0x6d, 0x62, 0x65, 0x64, 0x64, 0x65, 0x64, 0x12, 0x50, 0x0a, + 0x26, 0x73, 0x6b, 0x69, 0x70, 0x5f, 0x61, 0x66, 0x69, 0x5f, 0x73, 0x61, 0x66, 0x69, 0x5f, 0x70, + 0x61, 0x74, 0x68, 0x5f, 0x66, 0x6f, 0x72, 0x5f, 0x62, 0x67, 0x70, 0x5f, 0x6d, 0x75, 0x6c, 0x74, + 0x69, 0x70, 0x6c, 0x65, 0x5f, 0x61, 0x73, 0x18, 0xb8, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1f, + 0x73, 0x6b, 0x69, 0x70, 0x41, 0x66, 0x69, 0x53, 0x61, 0x66, 0x69, 0x50, 0x61, 0x74, 0x68, 0x46, + 0x6f, 0x72, 0x42, 0x67, 0x70, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x41, 0x73, 0x12, + 0x4c, 0x0a, 0x22, 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x79, 0x5f, 0x6d, 0x65, 0x6d, + 0x62, 0x65, 0x72, 0x5f, 0x72, 0x65, 0x67, 0x65, 0x78, 0x5f, 0x75, 0x6e, 0x73, 0x75, 0x70, 0x70, + 0x6f, 0x72, 0x74, 0x65, 0x64, 0x18, 0xb9, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1f, 0x63, 0x6f, + 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x79, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x65, 0x67, + 0x65, 0x78, 0x55, 0x6e, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x12, 0x46, 0x0a, + 0x20, 0x73, 0x61, 0x6d, 0x65, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5f, 0x61, 0x74, 0x74, + 0x61, 0x63, 0x68, 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x61, 0x6c, 0x6c, 0x5f, 0x61, 0x66, 0x69, + 0x73, 0x18, 0xba, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1b, 0x73, 0x61, 0x6d, 0x65, 0x50, 0x6f, + 0x6c, 0x69, 0x63, 0x79, 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, 0x65, 0x64, 0x54, 0x6f, 0x41, 0x6c, + 0x6c, 0x41, 0x66, 0x69, 0x73, 0x12, 0x49, 0x0a, 0x21, 0x73, 0x6b, 0x69, 0x70, 0x5f, 0x73, 0x65, + 0x74, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, + 0x66, 0x6f, 0x72, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0xbb, 0x01, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x1d, 0x73, 0x6b, 0x69, 0x70, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x74, + 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x46, 0x6f, 0x72, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x12, 0x42, 0x0a, 0x1d, 0x73, 0x6b, 0x69, 0x70, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x69, 0x6e, + 0x67, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x5f, 0x69, 0x6e, 0x64, 0x65, + 0x78, 0x18, 0xbc, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1a, 0x73, 0x6b, 0x69, 0x70, 0x43, 0x68, + 0x65, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x49, + 0x6e, 0x64, 0x65, 0x78, 0x12, 0x55, 0x0a, 0x27, 0x66, 0x6c, 0x61, 0x74, 0x74, 0x65, 0x6e, 0x5f, + 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x6d, 0x75, 0x6c, 0x74, + 0x69, 0x70, 0x6c, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, + 0xbd, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x23, 0x66, 0x6c, 0x61, 0x74, 0x74, 0x65, 0x6e, 0x50, + 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x57, 0x69, 0x74, 0x68, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, + 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x4a, 0x04, 0x08, 0x54, 0x10, + 0x55, 0x4a, 0x04, 0x08, 0x09, 0x10, 0x0a, 0x4a, 0x04, 0x08, 0x1c, 0x10, 0x1d, 0x4a, 0x04, 0x08, + 0x14, 0x10, 0x15, 0x4a, 0x04, 0x08, 0x5a, 0x10, 0x5b, 0x4a, 0x04, 0x08, 0x61, 0x10, 0x62, 0x4a, + 0x04, 0x08, 0x37, 0x10, 0x38, 0x4a, 0x04, 0x08, 0x59, 0x10, 0x5a, 0x4a, 0x04, 0x08, 0x13, 0x10, + 0x14, 0x1a, 0xa0, 0x01, 0x0a, 0x12, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x45, 0x78, + 0x63, 0x65, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x41, 0x0a, 0x08, 0x70, 0x6c, 0x61, 0x74, + 0x66, 0x6f, 0x72, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x6f, 0x70, 0x65, + 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, + 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, + 0x6d, 0x52, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x12, 0x47, 0x0a, 0x0a, 0x64, + 0x65, 0x76, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x27, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x74, 0x65, 0x73, + 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x44, 0x65, + 0x76, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x0a, 0x64, 0x65, 0x76, 0x69, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xfa, 0x01, 0x0a, 0x07, 0x54, 0x65, 0x73, 0x74, 0x62, 0x65, 0x64, + 0x12, 0x17, 0x0a, 0x13, 0x54, 0x45, 0x53, 0x54, 0x42, 0x45, 0x44, 0x5f, 0x55, 0x4e, 0x53, 0x50, + 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x45, 0x53, + 0x54, 0x42, 0x45, 0x44, 0x5f, 0x44, 0x55, 0x54, 0x10, 0x01, 0x12, 0x1a, 0x0a, 0x16, 0x54, 0x45, + 0x53, 0x54, 0x42, 0x45, 0x44, 0x5f, 0x44, 0x55, 0x54, 0x5f, 0x44, 0x55, 0x54, 0x5f, 0x34, 0x4c, + 0x49, 0x4e, 0x4b, 0x53, 0x10, 0x02, 0x12, 0x1a, 0x0a, 0x16, 0x54, 0x45, 0x53, 0x54, 0x42, 0x45, + 0x44, 0x5f, 0x44, 0x55, 0x54, 0x5f, 0x41, 0x54, 0x45, 0x5f, 0x32, 0x4c, 0x49, 0x4e, 0x4b, 0x53, + 0x10, 0x03, 0x12, 0x1a, 0x0a, 0x16, 0x54, 0x45, 0x53, 0x54, 0x42, 0x45, 0x44, 0x5f, 0x44, 0x55, + 0x54, 0x5f, 0x41, 0x54, 0x45, 0x5f, 0x34, 0x4c, 0x49, 0x4e, 0x4b, 0x53, 0x10, 0x04, 0x12, 0x1e, + 0x0a, 0x1a, 0x54, 0x45, 0x53, 0x54, 0x42, 0x45, 0x44, 0x5f, 0x44, 0x55, 0x54, 0x5f, 0x41, 0x54, + 0x45, 0x5f, 0x39, 0x4c, 0x49, 0x4e, 0x4b, 0x53, 0x5f, 0x4c, 0x41, 0x47, 0x10, 0x05, 0x12, 0x1e, + 0x0a, 0x1a, 0x54, 0x45, 0x53, 0x54, 0x42, 0x45, 0x44, 0x5f, 0x44, 0x55, 0x54, 0x5f, 0x44, 0x55, + 0x54, 0x5f, 0x41, 0x54, 0x45, 0x5f, 0x32, 0x4c, 0x49, 0x4e, 0x4b, 0x53, 0x10, 0x06, 0x12, 0x1a, + 0x0a, 0x16, 0x54, 0x45, 0x53, 0x54, 0x42, 0x45, 0x44, 0x5f, 0x44, 0x55, 0x54, 0x5f, 0x41, 0x54, + 0x45, 0x5f, 0x38, 0x4c, 0x49, 0x4e, 0x4b, 0x53, 0x10, 0x07, 0x12, 0x15, 0x0a, 0x11, 0x54, 0x45, + 0x53, 0x54, 0x42, 0x45, 0x44, 0x5f, 0x44, 0x55, 0x54, 0x5f, 0x34, 0x30, 0x30, 0x5a, 0x52, 0x10, + 0x08, 0x22, 0x6d, 0x0a, 0x04, 0x54, 0x61, 0x67, 0x73, 0x12, 0x14, 0x0a, 0x10, 0x54, 0x41, 0x47, + 0x53, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, + 0x14, 0x0a, 0x10, 0x54, 0x41, 0x47, 0x53, 0x5f, 0x41, 0x47, 0x47, 0x52, 0x45, 0x47, 0x41, 0x54, + 0x49, 0x4f, 0x4e, 0x10, 0x01, 0x12, 0x18, 0x0a, 0x14, 0x54, 0x41, 0x47, 0x53, 0x5f, 0x44, 0x41, + 0x54, 0x41, 0x43, 0x45, 0x4e, 0x54, 0x45, 0x52, 0x5f, 0x45, 0x44, 0x47, 0x45, 0x10, 0x02, 0x12, + 0x0d, 0x0a, 0x09, 0x54, 0x41, 0x47, 0x53, 0x5f, 0x45, 0x44, 0x47, 0x45, 0x10, 0x03, 0x12, 0x10, + 0x0a, 0x0c, 0x54, 0x41, 0x47, 0x53, 0x5f, 0x54, 0x52, 0x41, 0x4e, 0x53, 0x49, 0x54, 0x10, 0x04, + 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/testregistry.textproto b/testregistry.textproto index 883d2bfcdba..92451754997 100644 --- a/testregistry.textproto +++ b/testregistry.textproto @@ -317,6 +317,12 @@ test: { readme: "https://github.com/openconfig/featureprofiles/blob/d26ac7fac5406af29c9a582b8d8ee73d56953e3b/feature/experimental/system/health/tests/system_generic_health_check/README.md" exec: " " } +test: { + id: "Health-1.1" + description: "Healthz component status paths" + readme: "https://github.com/openconfig/featureprofiles/blob/main/feature/platform/healthz/tests/status/README.md" + exec: " " +} test: { id: "IC-1" description: "Integrated Circuit Utilization and Thresholds" @@ -555,6 +561,12 @@ test: { readme: "https://github.com/openconfig/featureprofiles/blob/main/feature/bgp/multipath/otg_tests/bgp_multipath_wecmp_lbw_community_test/README.md" exec: " " } +test: { + id: "RT-1.55" + description: "BGP session mode (active/passive)" + readme: "https://github.com/openconfig/featureprofiles/blob/main/feature/bgp/bgp_session_mode_configuration_test/README.md" + exec: " " +} test: { id: "RT-1.7" description: "Local BGP Test" @@ -792,7 +804,7 @@ test: { test: { id: "RT-7.11" description: "RT-7.11: BGP Policy - Import/Export Policy Action Using Multiple Criteria" - readme: "https://github.com/openconfig/featureprofiles/blob/main/feature/bgp/policybase/otg_tests/import-export-multi/README.md" + readme: "https://github.com/openconfig/featureprofiles/blob/main/feature/bgp/policybase/otg_tests/import_export_multi_test/README.md" exec: " " } test: { @@ -1240,6 +1252,11 @@ test: { description: "Integrated Circuit Hardware Resource Utilization Test" readme: "https://github.com/openconfig/featureprofiles/blob/main/feature/platform/integrated_circuit/otg_tests/utilization_test/README.md" } +test: { + id: "gNMI-1.22" + description: "Controller card port attributes" + readme: "https://github.com/openconfig/featureprofiles/blob/main/feature/platform/controllercard/tests/port/README.md" +} test: { id: "gNMI-1.4" description: "Telemetry: Inventory" @@ -1334,6 +1351,12 @@ test: { id: "gNOI-6.1" readme: "https://github.com/openconfig/featureprofiles/blob/main/feature/gnoi/factory_reset/tests/factory_reset_test/README.md" } +test: { + id: "gNPSI-1" + description: "Sampling and Subscription Test" + readme: "https://github.com/openconfig/featureprofiles/blob/main/feature/gnpsi/otg_tests/sampling_test/README.md" + exec: " " +} test: { id: "TRANSCEIVER-1" description: "400ZR Chromatic Dispersion(CD) telemetry values streaming" diff --git a/tools/fpcli/README.md b/tools/fpcli/README.md new file mode 100644 index 00000000000..c553032636e --- /dev/null +++ b/tools/fpcli/README.md @@ -0,0 +1,21 @@ +fpcli is an OpenConfig helper CLI for featureprofile-related use cases. + +For example, you can use it to show what RPCs exist for a particular OpenConfig +protocol: + +### Example + +```bash +go install ./tools/fpcli +fpcli show rpcs gnoi -d tmp +``` + +Output: + +``` +gnoi.bgp.BGP.ClearBGPNeighbor gnoi.bootconfig.BootConfig.GetBootConfig +gnoi.bootconfig.BootConfig.SetBootConfig +gnoi.certificate.CertificateManagement.CanGenerateCSR +gnoi.certificate.CertificateManagement.GenerateCSR +... +``` diff --git a/tools/internal/mdocspec/ocspec.go b/tools/internal/mdocspec/ocspec.go index 416ebf136b0..5535272d763 100644 --- a/tools/internal/mdocspec/ocspec.go +++ b/tools/internal/mdocspec/ocspec.go @@ -30,7 +30,7 @@ import ( // ErrNotFound indicates the OpenConfig Path and RPC Coverage YAML block was // not found or was invalid. -var ErrNotFound = fmt.Errorf(`did not detect valid yaml block under a heading titled %q, please see https://github.com/openconfig/featureprofiles/blob/main/doc/test-requirements-template.md for example`, OCSpecHeading) +var ErrNotFound = fmt.Errorf(`did not detect valid yaml block under a heading titled %q, please see https://github.com/openconfig/featureprofiles/blob/main/doc/test-requirements-template.md#openconfig-path-and-rpc-coverage for example, and https://github.com/openconfig/featureprofiles/tree/main/tools/fpcli/README.md for a tool for viewing the full names of all extant OC RPCs`, OCSpecHeading) // Parse extracts sorted OpenConfig Path and RPC Coverage from a // featureprofiles README. diff --git a/tools/validate_readme_spec/validate_readme_spec.go b/tools/validate_readme_spec/validate_readme_spec.go index df9f792746f..39ad92b4d22 100644 --- a/tools/validate_readme_spec/validate_readme_spec.go +++ b/tools/validate_readme_spec/validate_readme_spec.go @@ -87,7 +87,7 @@ func init() { config = New(nil) } -func readmeFiles(featureDir string, nonTestREADMEs stringMap) ([]string, error) { +func readmeFiles(featureDir string) ([]string, error) { var files []string err := filepath.WalkDir(featureDir, func(path string, d fs.DirEntry, err error) error { if err != nil { @@ -96,10 +96,6 @@ func readmeFiles(featureDir string, nonTestREADMEs stringMap) ([]string, error) if d.Name() != fpciutil.READMEname { return nil } - if _, ok := nonTestREADMEs[path]; ok { - // Allowlist - return nil - } files = append(files, path) return nil @@ -127,7 +123,7 @@ func main() { fallthrough case config.FeatureDir != "": var err error - files, err = readmeFiles(config.FeatureDir, config.NonTestREADMEs) + files, err = readmeFiles(config.FeatureDir) if err != nil { log.Exitf("Error gathering README.md files for validation: %v", err) } @@ -145,6 +141,11 @@ func main() { erredFiles := map[string]struct{}{} for _, file := range files { + if _, ok := config.NonTestREADMEs[file]; ok { + // Allowlist + continue + } + log.Infof("Validating %q", file) b, err := os.ReadFile(file) if err != nil {