From 57039f271e6501c973b9ae1eae871754bbab11c2 Mon Sep 17 00:00:00 2001 From: Ram Date: Fri, 31 May 2024 11:09:06 +0530 Subject: [PATCH] chained-policy deviations (#3042) * chained-policy deviations * fix imports in script and readme * fixed go fmt --- .../otg_tests/chained_policies_test/README.md | 12 +- .../chained_policies_test.go | 311 +++++++++++++----- .../chained_policies_test/metadata.textproto | 15 + internal/deviations/deviations.go | 5 + proto/metadata.proto | 7 +- proto/metadata_go_proto/metadata.pb.go | 96 +++--- 6 files changed, 315 insertions(+), 131 deletions(-) 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/internal/deviations/deviations.go b/internal/deviations/deviations.go index 2e50868558f..650331af322 100644 --- a/internal/deviations/deviations.go +++ b/internal/deviations/deviations.go @@ -1008,3 +1008,8 @@ func SkipSettingStatementForPolicy(dut *ondatra.DUTDevice) bool { 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/proto/metadata.proto b/proto/metadata.proto index 8af8e0f03e6..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. @@ -548,11 +549,15 @@ message Metadata { // 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 { + 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 1b1341b09e8..43178dd5a0a 100644 --- a/proto/metadata_go_proto/metadata.pb.go +++ b/proto/metadata_go_proto/metadata.pb.go @@ -830,6 +830,10 @@ type Metadata_Deviations struct { // 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() { @@ -2068,6 +2072,13 @@ func (x *Metadata_Deviations) GetSkipCheckingAttributeIndex() bool { 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 @@ -2131,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, 0xbf, 0x6a, 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, @@ -2165,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, 0x92, 0x62, 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, @@ -2947,44 +2958,49 @@ var file_metadata_proto_rawDesc = []byte{ 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, 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, + 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 (