diff --git a/feature/bgp/policybase/otg_tests/import_export_multi_test/import_export_multi_test.go b/feature/bgp/policybase/otg_tests/import_export_multi_test/import_export_multi_test.go index e4d35ff9bdf9..0e20c80a60c9 100644 --- a/feature/bgp/policybase/otg_tests/import_export_multi_test/import_export_multi_test.go +++ b/feature/bgp/policybase/otg_tests/import_export_multi_test/import_export_multi_test.go @@ -336,13 +336,6 @@ func configureImportExportMultifacetMatchActionsBGPPolicy(t *testing.T, dut *ond stmt3.GetOrCreateActions().SetPolicyResult(nextstatementResult) } - // Configure multi_policy:STATEMENT4: match_comm_and_prefix_add_2_community_sets statement - - stmt4, err := pdef1.AppendNewStatement(matchCommPrefixAddCommuStatement) - if err != nil { - t.Fatalf("AppendNewStatement(%s) failed: %v", matchCommPrefixAddCommuStatement, err) - } - // Configure my_community: [ "50:1" ] to match_comm_and_prefix_add_2_community_sets statement communitySetMatchCommPrefixAddCommu := rp.GetOrCreateDefinedSets().GetOrCreateBgpDefinedSets().GetOrCreateCommunitySet(myCommunitySet) @@ -355,15 +348,30 @@ func configureImportExportMultifacetMatchActionsBGPPolicy(t *testing.T, dut *ond communitySetMatchCommPrefixAddCommu.SetCommunityMember(cs4) communitySetMatchCommPrefixAddCommu.SetMatchSetOptions(matchAny) + // Configure multi_policy:STATEMENT4: match_comm_and_prefix_add_2_community_sets statement + + stmt4, err := pdef1.AppendNewStatement(matchCommPrefixAddCommuStatement) + if err != nil { + t.Fatalf("AppendNewStatement(%s) failed: %v", matchCommPrefixAddCommuStatement, err) + } + stmt6, err := pdef1.AppendNewStatement(matchCommPrefixAddCommuStatement + "_V6") + if err != nil { + t.Fatalf("AppendNewStatement(%s) failed: %v", matchCommPrefixAddCommuStatement, err) + } + if deviations.BGPConditionsMatchCommunitySetUnsupported(dut) { stmt4.GetOrCreateConditions().GetOrCreateBgpConditions().SetCommunitySet(myCommunitySet) + stmt6.GetOrCreateConditions().GetOrCreateBgpConditions().SetCommunitySet(myCommunitySet) } else { stmt4.GetOrCreateConditions().GetOrCreateBgpConditions().GetOrCreateMatchCommunitySet().SetCommunitySet(myCommunitySet) + stmt6.GetOrCreateConditions().GetOrCreateBgpConditions().GetOrCreateMatchCommunitySet().SetCommunitySet(myCommunitySet) } // configure match-prefix-set: prefix-set-5 to match_comm_and_prefix_add_2_community_sets statement stmt4.GetOrCreateConditions().GetOrCreateMatchPrefixSet().SetPrefixSet(prefixSetName) stmt4.GetOrCreateConditions().GetOrCreateMatchPrefixSet().SetMatchSetOptions(prefixSetNameSetOptions) + stmt6.GetOrCreateConditions().GetOrCreateMatchPrefixSet().SetPrefixSet(prefixSetName + "_V6") + stmt6.GetOrCreateConditions().GetOrCreateMatchPrefixSet().SetMatchSetOptions(prefixSetNameSetOptions) pset := rp.GetOrCreateDefinedSets().GetOrCreatePrefixSet(prefixSetName) pset.GetOrCreatePrefix(prefixesV4[4][0]+"/29", "29..30") @@ -387,12 +395,18 @@ func configureImportExportMultifacetMatchActionsBGPPolicy(t *testing.T, dut *ond 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) + + stmt6.GetOrCreateActions().GetOrCreateBgpActions().GetOrCreateSetCommunity().GetOrCreateReference().SetCommunitySetRefs(setCommunitySetRefs) + stmt6.GetOrCreateActions().GetOrCreateBgpActions().GetOrCreateSetCommunity().SetMethod(oc.SetCommunity_Method_REFERENCE) + stmt6.GetOrCreateActions().GetOrCreateBgpActions().GetOrCreateSetCommunity().SetOptions(oc.BgpPolicy_BgpSetCommunityOptionType_ADD) } // set-local-pref = 5 stmt4.GetOrCreateActions().GetOrCreateBgpActions().SetSetLocalPref(localPref) + stmt6.GetOrCreateActions().GetOrCreateBgpActions().SetSetLocalPref(localPref) if !deviations.SkipSettingStatementForPolicy(dut) { stmt4.GetOrCreateActions().SetPolicyResult(nextstatementResult) + stmt6.GetOrCreateActions().SetPolicyResult(nextstatementResult) } // Configure multi_policy:STATEMENT5: match_aspath_set_med statement 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 4e2aedf07a82..dcb0012b4938 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 @@ -23,6 +23,7 @@ import ( "github.com/open-traffic-generator/snappi/gosnappi" "github.com/openconfig/featureprofiles/internal/attrs" + "github.com/openconfig/featureprofiles/internal/cfgplugins" "github.com/openconfig/featureprofiles/internal/deviations" "github.com/openconfig/featureprofiles/internal/fptest" "github.com/openconfig/featureprofiles/internal/helpers" @@ -181,6 +182,9 @@ func TestBGPLinkBandwidth(t *testing.T) { } baseSetupConfigAndVerification(t, td) configureExtCommunityRoutingPolicy(t, dut) + if deviations.BgpExplicitExtendedCommunityEnable(dut) { + enableExtCommunityCLIConfig(t, dut) + } testCases := []testCase{ { name: "Policy set not_match_100_set_linkbw_1M", @@ -224,6 +228,17 @@ func TestBGPLinkBandwidth(t *testing.T) { } } +func enableExtCommunityCLIConfig(t *testing.T, dut *ondatra.DUTDevice) { + var extCommunityEnableCLIConfig string + switch dut.Vendor() { + case ondatra.CISCO: + extCommunityEnableCLIConfig = fmt.Sprintf("router bgp %v instance BGP neighbor-group %v \n ebgp-recv-extcommunity-dmz \n ebgp-send-extcommunity-dmz\n", dutAS, cfgplugins.BGPPeerGroup1) + default: + t.Fatalf("Unsupported vendor %s for deviation 'BgpExplicitExtendedCommunityEnable'", dut.Vendor()) + } + helpers.GnmiCLIConfig(t, dut, extCommunityEnableCLIConfig) +} + func applyPolicyDut(t *testing.T, dut *ondatra.DUTDevice, policyName string) { // Apply ipv4 policy to bgp neighbour. root := &oc.Root{} @@ -241,6 +256,17 @@ func applyPolicyDut(t *testing.T, dut *ondatra.DUTDevice, policyName string) { 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{policyName}) gnmi.Replace(t, dut, path.Config(), policy) + + ni := root.GetOrCreateNetworkInstance(deviations.DefaultNetworkInstance(dut)) + niProto := ni.GetOrCreateProtocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_BGP, "BGP") + bgp := niProto.GetOrCreateBgp() + bgp.GetOrCreatePeerGroup(cfgplugins.BGPPeerGroup1).GetOrCreateAfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV4_UNICAST).Enabled = ygot.Bool(true) + bgp.GetOrCreatePeerGroup(cfgplugins.BGPPeerGroup1).GetOrCreateAfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV6_UNICAST).Enabled = ygot.Bool(true) + bgpNbrV4 := bgp.GetOrCreateNeighbor(atePort1.IPv4) + bgpNbrV4.PeerGroup = ygot.String(cfgplugins.BGPPeerGroup1) + bgpNbrV6 := bgp.GetOrCreateNeighbor(atePort1.IPv6) + bgpNbrV6.PeerGroup = ygot.String(cfgplugins.BGPPeerGroup1) + gnmi.Update(t, dut, gnmi.OC().NetworkInstance(deviations.DefaultNetworkInstance(dut)).Protocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_BGP, "BGP").Config(), niProto) } func validatPolicyDut(t *testing.T, dut *ondatra.DUTDevice, policyName string) { @@ -292,6 +318,10 @@ func validateRouteCommunityV4Prefix(t *testing.T, td testData, community, v4Pref } } default: + if len(bgpPrefix.ExtendedCommunity) == 0 { + t.Errorf("ERROR extended community is empty, expected %v", community) + return + } for _, ec := range bgpPrefix.ExtendedCommunity { lbSubType := ec.Structured.NonTransitive_2OctetAsType.LinkBandwidthSubtype listCommunity := strings.Split(community, ":") @@ -359,6 +389,10 @@ func validateRouteCommunityV6Prefix(t *testing.T, td testData, community, v6Pref } } default: + if len(bgpPrefix.ExtendedCommunity) == 0 { + t.Errorf("ERROR extended community is empty, expected %v", community) + return + } for _, ec := range bgpPrefix.ExtendedCommunity { lbSubType := ec.Structured.NonTransitive_2OctetAsType.LinkBandwidthSubtype listCommunity := strings.Split(community, ":") diff --git a/feature/experimental/bgp/otg_tests/link_bandwidth_test/metadata.textproto b/feature/experimental/bgp/otg_tests/link_bandwidth_test/metadata.textproto index cad8f6e271fc..b991682d3ed9 100644 --- a/feature/experimental/bgp/otg_tests/link_bandwidth_test/metadata.textproto +++ b/feature/experimental/bgp/otg_tests/link_bandwidth_test/metadata.textproto @@ -35,6 +35,7 @@ platform_exceptions: { skip_bgp_send_community_type: true bgp_extended_community_index_unsupported: true bgp_conditions_match_community_set_unsupported: true + bgp_explicit_extended_community_enable: true } } tags: TAGS_AGGREGATION diff --git a/feature/gnoi/factory_reset/tests/factory_reset_test/README.md b/feature/gnoi/factory_reset/tests/factory_reset_test/README.md index 0bfcfb35233a..8c4a5e8fd9d1 100644 --- a/feature/gnoi/factory_reset/tests/factory_reset_test/README.md +++ b/feature/gnoi/factory_reset/tests/factory_reset_test/README.md @@ -1,16 +1,27 @@ -# gNOI-6.1: Factory Reset +# gNOI-6.1: Factory Reset ## Summary -Performs Factory Reset with and without disk-encryption + +Performs Factory Reset ## Procedure -* Create dummy files in the harddisk of the router using bash dd -* Checks for disk-encryption status and performs reset on both the scenarios -* Secure ZTP server should be up and running in the background for the router to boot up with the base config once factory reset command is sent on the box. -* Send out Factory reset via GNOI Raw API - * Wait for the box to boot up via Secure ZTP - * The base config is updated on the box via Secure ZTP -* Connect to the router and check if the files in the harddisk are removed as a part of verifying Factory reset. + +### Scenario 1 + +* Create a sample file in the harddisk of the router using gNOI PUT RPC +* Secure ZTP server should be up and running in the background for the router + to boot up with the base config once factory reset command is sent on the + box. +* Send out Factory reset via GNOI Raw API + * Wait for the box to boot up via Secure ZTP + * The base config is updated on the box via Secure ZTP +* Send a gNOI file STAT RPC to check if the file in the harddisk are removed + as a part of verifying Factory reset. + +### Scenario 2 + +* Check startup-config file exists in mount path. +* Perform the same steps are `Scenario 1` for startup-config file. ## OpenConfig Path and RPC Coverage @@ -21,4 +32,6 @@ paths used for test setup are not listed here. rpcs: gnoi: factory_reset.FactoryReset.Start: + file.File.Put: + file.File.Stat: ``` diff --git a/feature/gnoi/factory_reset/tests/factory_reset_test/factory_reset_test.go b/feature/gnoi/factory_reset/tests/factory_reset_test/factory_reset_test.go index 93d161332a57..4cc0240c1af8 100644 --- a/feature/gnoi/factory_reset/tests/factory_reset_test/factory_reset_test.go +++ b/feature/gnoi/factory_reset/tests/factory_reset_test/factory_reset_test.go @@ -1,26 +1,46 @@ -package factoryreset +// 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 factory_reset_test import ( "context" - "fmt" - "path" - "strings" + "crypto/md5" + "crypto/rand" + "io" + "path/filepath" + "regexp" "testing" "time" "github.com/openconfig/featureprofiles/internal/fptest" frpb "github.com/openconfig/gnoi/factory_reset" + fpb "github.com/openconfig/gnoi/file" + "github.com/openconfig/gnoi/types" + "github.com/openconfig/gnoigo" "github.com/openconfig/ondatra" "github.com/openconfig/ondatra/gnmi" "github.com/openconfig/testt" ) var ( - filesCreated = []string{} - fileCreateDevRand = "bash dd if=/dev/urandom of=%s bs=1M count=2" - checkFileExists = "bash [ -f \"%s\" ] && echo \"YES_exists\"" - fileExists = "YES_exists" - fileCreate = "bash fallocate -l %dM %s" + remoteFilePath = map[ondatra.Vendor]string{ + ondatra.CISCO: "/misc/disk1/", + ondatra.NOKIA: "/tmp/", + ondatra.JUNIPER: "/var/tmp/", + ondatra.ARISTA: "/mnt/flash/", + } ) const maxRebootTime = 40 // 40 mins wait time for the factory reset and sztp to kick in @@ -28,54 +48,6 @@ func TestMain(m *testing.M) { fptest.RunTests(m) } -type encryptionCommands struct { - EncryptionStatus string - EncryptionActivate string - EncryptionDeactivate string - DevicePaths []string -} - -var enCiscoCommands encryptionCommands - -// creating files before factory reset -func createFiles(t *testing.T, dut *ondatra.DUTDevice, devicePaths []string) { - for _, folderPath := range devicePaths { - fPath := path.Join(folderPath, "devrandom.log") - dut.CLI().Run(t, fmt.Sprintf(fileCreateDevRand, fPath)) - t.Log("Check if the file is created") - time.Sleep(30 * time.Second) - filesCreated = append(filesCreated, fPath) - fPath = path.Join(folderPath, ".devrandom.log") - dut.CLI().Run(t, fmt.Sprintf(fileCreateDevRand, fPath)) - - filesCreated = append(filesCreated, fPath) - fPath = path.Join(folderPath, "largeFile.log") - dut.CLI().Run(t, fmt.Sprintf(fileCreate, 100, fPath)) - - filesCreated = append(filesCreated, fPath) - } - for _, f := range filesCreated { - resp := dut.CLI().Run(t, fmt.Sprintf(checkFileExists, f)) - t.Logf("%v", resp) - if !strings.Contains(resp, fileExists) { - t.Fatalf("Unable to Create a file object %s in device %s", f, dut.Name()) - } - } - -} - -// checkFiles check if the files created are deleted from the device after factory reset -func checkFiles(t *testing.T, dut *ondatra.DUTDevice) { - for _, f := range filesCreated { - resp := dut.CLI().Run(t, fmt.Sprintf(checkFileExists, f)) - t.Logf(resp) - if strings.Contains(resp, fileExists) == true { - t.Fatalf("File %s not cleared by system Reset, in device %s", f, dut.Name()) - } - - } -} - func deviceBootStatus(t *testing.T, dut *ondatra.DUTDevice) { startReboot := time.Now() t.Logf("Wait for DUT to boot up by polling the telemetry output.") @@ -100,70 +72,153 @@ func deviceBootStatus(t *testing.T, dut *ondatra.DUTDevice) { t.Logf("Device boot time: %.2f minutes", time.Since(startReboot).Minutes()) } -// performs factory reset -func factoryReset(t *testing.T, dut *ondatra.DUTDevice, devicePaths []string) { - createFiles(t, dut, devicePaths) +func gNOIPutFile(t *testing.T, dut *ondatra.DUTDevice, gnoiClient gnoigo.Clients, fName string) { + dutVendor := dut.Vendor() + fullPath := filepath.Join(remoteFilePath[dutVendor], fName) + stream, err := gnoiClient.File().Put(context.Background()) + t.Logf("Attempting to send gNOI File Put here: %v", fullPath) + if err != nil { + t.Fatalf("Failed to create stream channel: %v", err) + } + defer stream.CloseSend() + h := md5.New() + fPutOpen := &fpb.PutRequest_Open{ + Open: &fpb.PutRequest_Details{ + RemoteFile: fullPath, + Permissions: 744, + }, + } + err = stream.Send(&fpb.PutRequest{ + Request: fPutOpen, + }) + if err != nil { + t.Fatalf("Stream failed to send PutRequest: %v", err) + } + + b := make([]byte, 64*1024) + n, err := rand.Read(b) + if err != nil && err != io.EOF { + t.Fatalf("Error reading bytes: %v", err) + } + h.Write(b[:n]) + req := &fpb.PutRequest{ + Request: &fpb.PutRequest_Contents{ + Contents: b[:n], + }, + } + err = stream.Send(req) + if err != nil { + t.Fatalf("Stream failed to send Req: %v", err) + } + + hashReq := &fpb.PutRequest{ + Request: &fpb.PutRequest_Hash{ + Hash: &types.HashType{ + Method: types.HashType_MD5, + Hash: h.Sum(nil), + }, + }, + } + err = stream.Send(hashReq) + if err != nil { + t.Fatalf("Stream failed to send hash: %v", err) + } + + _, err = stream.CloseAndRecv() + if err != nil { + t.Fatalf("Problem closing the stream: %v", err) + } +} + +func gNOIStatFile(t *testing.T, dut *ondatra.DUTDevice, fName string, reset bool) { + dutVendor := dut.Vendor() + fullPath := filepath.Join(remoteFilePath[dutVendor], fName) gnoiClient, err := dut.RawAPIs().BindingDUT().DialGNOI(context.Background()) if err != nil { t.Fatalf("Error dialing gNOI: %v", err) } - facRe, err := gnoiClient.FactoryReset().Start(context.Background(), &frpb.StartRequest{FactoryOs: false, ZeroFill: false}) + if _, ok := remoteFilePath[dutVendor]; !ok { + t.Fatalf("Please add support for vendor %v in var remoteFilePath ", dutVendor) + } + + in := &fpb.StatRequest{ + Path: remoteFilePath[dutVendor], + } + statResp, err := gnoiClient.File().Stat(context.Background(), in) if err != nil { - t.Fatalf("Failed to initiate Factory Reset on the device, Error : %v ", err) - } - t.Logf("Factory reset Response %v ", facRe) - time.Sleep(2 * time.Minute) - deviceBootStatus(t, dut) - dutNew := ondatra.DUT(t, "dut") - checkFiles(t, dutNew) - t.Log("Factory reset successfull") + t.Fatalf("Error fetching stat path %v for the created file on DUT. %v", remoteFilePath[dutVendor], err) + } + + if len(statResp.GetStats()) == 0 { + t.Log("gNOI STAT did not find any files") + } + + r := regexp.MustCompile(fName) + var isCreatedFile bool + + for _, fileStats := range statResp.GetStats() { + isCreatedFile = r.MatchString(fileStats.GetPath()) && (fileStats.GetSize() == uint64(64*1024)) + if isCreatedFile { + break + } + } + if isCreatedFile { + if !reset { + t.Logf("gNOI PUT successfully created file: %s", fullPath) + } else { + t.Errorf("gNOI PUT file was found after Factory Reset: %s", fullPath) + } + } + if !isCreatedFile { + if !reset { + t.Error("gNOI PUT file was never Created") + } else { + t.Logf("Did not find %s in the list of files", fullPath) + } + } } func TestFactoryReset(t *testing.T) { dut := ondatra.DUT(t, "dut") - switch dut.Vendor() { - case ondatra.CISCO: - enCiscoCommands = encryptionCommands{EncryptionStatus: "show disk-encryption status", EncryptionActivate: "disk-encryption activate", EncryptionDeactivate: "disk-encryption deactivate", DevicePaths: []string{"/misc/disk1"}} - t.Logf("Cisco commands for disk encryption %v ", enCiscoCommands) - default: - t.Fatalf("Disk Encryption commands is missing for %v ", dut.Vendor().String()) - } - - showDiskEncryptionStatus := dut.CLI().Run(t, enCiscoCommands.EncryptionStatus) - t.Logf("Disk encryption status %v", showDiskEncryptionStatus) - - if strings.Contains(showDiskEncryptionStatus, "Not Encrypted") { - t.Log("Performing Factory reset without Encryption\n") - factoryReset(t, dut, enCiscoCommands.DevicePaths) - t.Log("Stablise after factory reset\n") - time.Sleep(5 * time.Minute) - t.Log("Activate Encryption\n") - encrypt := dut.CLI().Run(t, enCiscoCommands.EncryptionActivate) - t.Logf("Sleep for 5 mins after disk-encryption activate") - time.Sleep(5 * time.Minute) - t.Logf("Device encryption acrivare: %v", encrypt) - deviceBootStatus(t, dut) - encrypt = dut.CLI().Run(t, enCiscoCommands.EncryptionStatus) - t.Logf("Show device encryption status: %v", encrypt) - t.Log("Wait for the system to stabilize\n") - time.Sleep(5 * time.Minute) - factoryReset(t, dut, enCiscoCommands.DevicePaths) - } else { - t.Log("Performing Factory reset with Encryption\n") - factoryReset(t, dut, enCiscoCommands.DevicePaths) - t.Log("Stablise after factory reset\n") - time.Sleep(5 * time.Minute) - t.Log("Deactivate Encryption\n") - encrypt := dut.CLI().Run(t, enCiscoCommands.EncryptionDeactivate) - t.Logf("Device encrytion deactivate: %v", encrypt) - t.Logf("Sleep for 5 mins after disk-encryption deactivate") - time.Sleep(5 * time.Minute) - deviceBootStatus(t, dut) - encrypt = dut.CLI().Run(t, enCiscoCommands.EncryptionStatus) - t.Logf("Show device encrytion status: %v", encrypt) - t.Logf("Wait for the system to stabilize\n") - time.Sleep(5 * time.Minute) - factoryReset(t, dut, enCiscoCommands.DevicePaths) + testCases := []struct { + name string + fileName string + fileExist bool + }{ + { + name: "Random file", + fileName: "devrandom.log", + fileExist: false, + }, + { + name: "Startup config", + fileName: "startup-config", + fileExist: true, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + gnoiClient, err := dut.RawAPIs().BindingDUT().DialGNOI(context.Background()) + if err != nil { + t.Fatalf("Error dialing gNOI: %v", err) + } + + if !tc.fileExist { + gNOIPutFile(t, dut, gnoiClient, tc.fileName) + } + gNOIStatFile(t, dut, tc.fileName, tc.fileExist) + + res, err := gnoiClient.FactoryReset().Start(context.Background(), &frpb.StartRequest{FactoryOs: false, ZeroFill: false}) + if err != nil { + t.Fatalf("Failed to initiate Factory Reset on the device, Error : %v ", err) + } + t.Logf("Factory reset Response %v ", res) + time.Sleep(2 * time.Minute) + + deviceBootStatus(t, dut) + gNOIStatFile(t, dut, tc.fileName, true) + }) } } diff --git a/feature/gnoi/factory_reset/tests/factory_reset_test/metadata.textproto b/feature/gnoi/factory_reset/tests/factory_reset_test/metadata.textproto index 231f9b845d80..9ce3bad8abe1 100644 --- a/feature/gnoi/factory_reset/tests/factory_reset_test/metadata.textproto +++ b/feature/gnoi/factory_reset/tests/factory_reset_test/metadata.textproto @@ -4,4 +4,4 @@ uuid: "15e3ade1-e3c4-4da3-8553-3a9ef5fba344" plan_id: "gNOI-6.1" description: "Factory Reset" -testbed: TESTBED_DUT_ATE_2LINKS +testbed: TESTBED_DUT 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 927b7be381af..fdc6908f5387 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 @@ -224,16 +224,16 @@ func TestBaseHierarchicalNHGUpdate(t *testing.T) { desc: "Usecase for NHG update in hierarchical resolution scenario", fn: testBaseHierarchialNHG, }, - { - name: "testRecursiveIPv4EntrywithVRFSelectionPolW", - desc: "Usecase for NHG update in hierarchical resolution scenario with VRF Selection Policy W", - fn: testBaseHierarchialNHGwithVrfPolW, - }, { name: "testImplementDrain", desc: "Usecase for Implementing Drain test", fn: testImplementDrain, }, + { + name: "testRecursiveIPv4EntrywithVRFSelectionPolW", + desc: "Usecase for NHG update in hierarchical resolution scenario with VRF Selection Policy W", + fn: testBaseHierarchialNHGwithVrfPolW, + }, } // Configure the gRIBI client client := gribi.Client{ @@ -285,6 +285,9 @@ func testBaseHierarchialNHGwithVrfPolW(ctx context.Context, t *testing.T, args * } vrfpolicy.ConfigureVRFSelectionPolicy(t, args.dut, vrfpolicy.VRFPolicyW) + // Remove interface from VRF-1. + gnmi.Delete(t, args.dut, gnmi.OC().NetworkInstance(vrfName).Config()) + ctx = context.WithValue(ctx, transitKey{}, true) testBaseHierarchialNHG(ctx, t, args) //Delete Policy-forwarding PolicyW from the ingress interface 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 e7bec8c5d062..2e0021e617ab 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 @@ -40,6 +40,9 @@ func configureDUTLinkLocalInterface(t *testing.T, dut *ondatra.DUTDevice, p *ond } s.GetOrCreateIpv6().GetOrCreateAutoconf() gnmi.Replace(t, dut, gnmi.OC().Interface(p.Name()).Config(), intf) + if deviations.ExplicitInterfaceInDefaultVRF(dut) { + fptest.AssignToNetworkInstance(t, dut, intf.GetName(), deviations.DefaultNetworkInstance(dut), 0) + } } func getAllIPv6Addresses(t *testing.T, dut *ondatra.DUTDevice, p *ondatra.Port) []string { 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 370703e6cacb..7cdc467c77e6 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 @@ -4,7 +4,7 @@ uuid: "22ba3cd3-0dcb-4aba-9a09-d7180785e92c" plan_id: "RT-5.10" description: "IPv6 Link Local generated by SLAAC" -testbed: TESTBED_DUT +testbed: TESTBED_DUT_ATE_2LINKS tags: TAGS_TRANSIT tags: TAGS_DATACENTER_EDGE @@ -32,6 +32,7 @@ platform_exceptions: { } deviations: { interface_enabled: true + explicit_interface_in_default_vrf: true } } platform_exceptions: { diff --git a/feature/isis/otg_tests/static_route_isis_redistribution/metadata.textproto b/feature/isis/otg_tests/static_route_isis_redistribution/metadata.textproto index 4f658288c55b..bbced9e82ee6 100644 --- a/feature/isis/otg_tests/static_route_isis_redistribution/metadata.textproto +++ b/feature/isis/otg_tests/static_route_isis_redistribution/metadata.textproto @@ -31,5 +31,6 @@ platform_exceptions: { ipv6_static_route_with_ipv4_next_hop_requires_static_arp: true routing_policy_tag_set_embedded: true same_policy_attached_to_all_afis: true + match_tag_set_condition_unsupported: 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 index 9501309f22e7..231b7b19aa5c 100644 --- 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 @@ -478,6 +478,10 @@ func TestStaticToISISRedistribution(t *testing.T) { }} for _, tc := range cases { + if deviations.MatchTagSetConditionUnsupported(ts.DUT) && tc.TagSetCondition { + t.Skipf("Skipping test case %s due to match tag set condition not supported", tc.desc) + } + dni := deviations.DefaultNetworkInstance(ts.DUT) t.Run(tc.desc, func(t *testing.T) { diff --git a/feature/mpls/otg_tests/static_lsp/README.md b/feature/mpls/otg_tests/static_lsp/README.md new file mode 100644 index 000000000000..ba2191e8cd13 --- /dev/null +++ b/feature/mpls/otg_tests/static_lsp/README.md @@ -0,0 +1,42 @@ +# TE-9.2: MPLS based forwarding Static LSP + +## Summary + +Validate static lsp functionality. + +## Procedure + +* Create topology ATE1–DUT1-ATE2 +* Enable MPLS forwarding and create egress static LSP to pop the label and forward to ATE2: +* Match incoming label (1000001) +* Set IP next-hop +* Set egress interface +* Set the action to pop label +* Start 2 traffic flows with specified MPLS tags IPv4-MPLS[1000002]-MPLS[1000001] +* Verify that traffic is received at ATE2 with MPLS label [1000001] removed + +## 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/mpls/lsps/static-lsps/static-lsp/egress/config/next-hop: + /network-instances/network-instance/mpls/lsps/static-lsps/static-lsp/egress/config/incoming-label: + /network-instances/network-instance/mpls/lsps/static-lsps/static-lsp/egress/config/push-label: + + ## State paths + /network-instances/network-instance/mpls/lsps/static-lsps/static-lsp/egress/state/next-hop: + /network-instances/network-instance/mpls/lsps/static-lsps/static-lsp/egress/state/incoming-label: + /network-instances/network-instance/mpls/lsps/static-lsps/static-lsp/egress/state/push-label: + /network-instances/network-instance/mpls/lsps/static-lsps/static-lsp/egress/state/metric: + /network-instances/network-instance/mpls/lsps/static-lsps/static-lsp/egress/state/interface: + /network-instances/network-instance/mpls/lsps/static-lsps/static-lsp/egress/state/subinterface: + +rpcs: + gnmi: + gNMI.Set: + gNMI.Subscribe: +``` diff --git a/feature/platform/tests/telemetry_inventory_test/metadata.textproto b/feature/platform/tests/telemetry_inventory_test/metadata.textproto index 7edce911e307..2f00560c835c 100644 --- a/feature/platform/tests/telemetry_inventory_test/metadata.textproto +++ b/feature/platform/tests/telemetry_inventory_test/metadata.textproto @@ -43,5 +43,6 @@ platform_exceptions: { backplane_facing_capacity_unsupported: true install_position_and_install_component_unsupported: true model_name_unsupported: true + skip_controller_card_power_admin: true } } diff --git a/feature/platform/tests/telemetry_inventory_test/telemetry_inventory_test.go b/feature/platform/tests/telemetry_inventory_test/telemetry_inventory_test.go index 119011417c26..22212c8ffd7b 100644 --- a/feature/platform/tests/telemetry_inventory_test/telemetry_inventory_test.go +++ b/feature/platform/tests/telemetry_inventory_test/telemetry_inventory_test.go @@ -1069,12 +1069,13 @@ func TestDefaultPowerAdminState(t *testing.T) { t.Errorf("Component %s PowerAdminState is unset", linecards[0].GetName()) } } - - if len(supervisors) != 0 { - pas := gnmi.Get(t, dut, gnmi.OC().Component(supervisors[0].GetName()).ControllerCard().PowerAdminState().Config()) - t.Logf("Component %s PowerAdminState: %v", supervisors[0].GetName(), pas) - if pas == oc.Platform_ComponentPowerType_UNSET { - t.Errorf("Component %s PowerAdminState is unset", supervisors[0].GetName()) + if !deviations.SkipControllerCardPowerAdmin(dut) { + if len(supervisors) != 0 { + pas := gnmi.Get(t, dut, gnmi.OC().Component(supervisors[0].GetName()).ControllerCard().PowerAdminState().Config()) + t.Logf("Component %s PowerAdminState: %v", supervisors[0].GetName(), pas) + if pas == oc.Platform_ComponentPowerType_UNSET { + t.Errorf("Component %s PowerAdminState is unset", supervisors[0].GetName()) + } } } } diff --git a/internal/deviations/deviations.go b/internal/deviations/deviations.go index 7dc84c6636ab..e2a1ff733ef3 100644 --- a/internal/deviations/deviations.go +++ b/internal/deviations/deviations.go @@ -1098,3 +1098,13 @@ func BgpDeleteLinkBandwidthUnsupported(dut *ondatra.DUTDevice) bool { func QOSInQueueDropCounterUnsupported(dut *ondatra.DUTDevice) bool { return lookupDUTDeviations(dut).GetQosInqueueDropCounterUnsupported() } + +// BgpExplicitExtendedCommunityEnable returns true if explicit extended community enable is needed +func BgpExplicitExtendedCommunityEnable(dut *ondatra.DUTDevice) bool { + return lookupDUTDeviations(dut).GetBgpExplicitExtendedCommunityEnable() +} + +// MatchTagSetConditionUnsupported returns true if match tag set condition is not supported +func MatchTagSetConditionUnsupported(dut *ondatra.DUTDevice) bool { + return lookupDUTDeviations(dut).GetMatchTagSetConditionUnsupported() +} diff --git a/proto/metadata.proto b/proto/metadata.proto index 531768af7483..497bfe67434e 100644 --- a/proto/metadata.proto +++ b/proto/metadata.proto @@ -594,6 +594,10 @@ message Metadata { // qos_inqueue_drop_counter_Unsupported is set to true for devices that do not support qos ingress queue drop counters. // Juniper: b/341130490 bool qos_inqueue_drop_counter_unsupported = 207; + // Devices that need bgp extended community enable explicitly + bool bgp_explicit_extended_community_enable = 208; + // devices that do not support match tag set condition + bool match_tag_set_condition_unsupported = 209; // Reserved field numbers and identifiers. reserved 84, 9, 28, 20, 90, 97, 55, 89, 19, 36, 35; diff --git a/proto/metadata_go_proto/metadata.pb.go b/proto/metadata_go_proto/metadata.pb.go index 74ecb4eaaa9d..a6e6e9a7546d 100644 --- a/proto/metadata_go_proto/metadata.pb.go +++ b/proto/metadata_go_proto/metadata.pb.go @@ -14,18 +14,19 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.27.1 -// protoc v3.12.4 +// protoc-gen-go v1.33.0 +// protoc v3.21.12 // source: metadata.proto package metadata_go_proto import ( + reflect "reflect" + sync "sync" + proto "github.com/openconfig/ondatra/proto" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" ) const ( @@ -688,7 +689,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 @@ -874,6 +876,10 @@ type Metadata_Deviations struct { // qos_inqueue_drop_counter_Unsupported is set to true for devices that do not support qos ingress queue drop counters. // Juniper: b/341130490 QosInqueueDropCounterUnsupported bool `protobuf:"varint,207,opt,name=qos_inqueue_drop_counter_unsupported,json=qosInqueueDropCounterUnsupported,proto3" json:"qos_inqueue_drop_counter_unsupported,omitempty"` + // Devices that need bgp extended community enable explicitly + BgpExplicitExtendedCommunityEnable bool `protobuf:"varint,208,opt,name=bgp_explicit_extended_community_enable,json=bgpExplicitExtendedCommunityEnable,proto3" json:"bgp_explicit_extended_community_enable,omitempty"` + // devices that do not support match tag set condition + MatchTagSetConditionUnsupported bool `protobuf:"varint,209,opt,name=match_tag_set_condition_unsupported,json=matchTagSetConditionUnsupported,proto3" json:"match_tag_set_condition_unsupported,omitempty"` } func (x *Metadata_Deviations) Reset() { @@ -2231,6 +2237,20 @@ func (x *Metadata_Deviations) GetQosInqueueDropCounterUnsupported() bool { return false } +func (x *Metadata_Deviations) GetBgpExplicitExtendedCommunityEnable() bool { + if x != nil { + return x.BgpExplicitExtendedCommunityEnable + } + return false +} + +func (x *Metadata_Deviations) GetMatchTagSetConditionUnsupported() bool { + if x != nil { + return x.MatchTagSetConditionUnsupported + } + return false +} + type Metadata_PlatformExceptions struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -2294,7 +2314,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, 0xfb, 0x74, 0x0a, 0x08, 0x4d, 0x65, 0x74, 0x61, + 0x64, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x9f, 0x76, 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, @@ -2328,7 +2348,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, 0xce, 0x6c, 0x0a, 0x0a, 0x44, 0x65, 0x76, 0x69, 0x61, 0x74, + 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x1a, 0xf2, 0x6d, 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, @@ -3193,44 +3213,55 @@ var file_metadata_proto_rawDesc = []byte{ 0x75, 0x6e, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x18, 0xcf, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x20, 0x71, 0x6f, 0x73, 0x49, 0x6e, 0x71, 0x75, 0x65, 0x75, 0x65, 0x44, 0x72, 0x6f, 0x70, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x55, 0x6e, 0x73, 0x75, 0x70, 0x70, 0x6f, - 0x72, 0x74, 0x65, 0x64, 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, 0x4a, 0x04, 0x08, 0x24, 0x10, 0x25, - 0x4a, 0x04, 0x08, 0x23, 0x10, 0x24, 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, + 0x72, 0x74, 0x65, 0x64, 0x12, 0x53, 0x0a, 0x26, 0x62, 0x67, 0x70, 0x5f, 0x65, 0x78, 0x70, 0x6c, + 0x69, 0x63, 0x69, 0x74, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x5f, 0x63, 0x6f, + 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x79, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x18, 0xd0, + 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x22, 0x62, 0x67, 0x70, 0x45, 0x78, 0x70, 0x6c, 0x69, 0x63, + 0x69, 0x74, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x43, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, + 0x69, 0x74, 0x79, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x4d, 0x0a, 0x23, 0x6d, 0x61, 0x74, + 0x63, 0x68, 0x5f, 0x74, 0x61, 0x67, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x64, 0x69, + 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x75, 0x6e, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, + 0x18, 0xd1, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x54, 0x61, + 0x67, 0x53, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x6e, 0x73, + 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 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, 0x4a, 0x04, + 0x08, 0x24, 0x10, 0x25, 0x4a, 0x04, 0x08, 0x23, 0x10, 0x24, 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 (