diff --git a/feature/platform/transceiver/tests/zr_logical_channels_test/metadata.textproto b/feature/platform/transceiver/tests/zr_logical_channels_test/metadata.textproto index caa9410e80a..fb942581ff5 100644 --- a/feature/platform/transceiver/tests/zr_logical_channels_test/metadata.textproto +++ b/feature/platform/transceiver/tests/zr_logical_channels_test/metadata.textproto @@ -14,3 +14,14 @@ platform_exceptions: { missing_port_to_optical_channel_component_mapping: true } } +platform_exceptions: { + platform: { + vendor: CISCO + } + deviations: { + otn_channel_trib_unsupported: true + eth_channel_ingress_parameters_unsupported: true + eth_channel_assignment_cisco_numbering: true + otn_channel_assignment_cisco_numbering: true + } +} \ No newline at end of file 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 06dca4f91ed..fdf5d9220e8 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,6 +1,8 @@ package zr_logical_channels_test import ( + "flag" + "strings" "testing" "time" @@ -8,6 +10,7 @@ import ( "github.com/openconfig/featureprofiles/internal/attrs" "github.com/openconfig/featureprofiles/internal/cfgplugins" "github.com/openconfig/featureprofiles/internal/components" + "github.com/openconfig/featureprofiles/internal/deviations" "github.com/openconfig/featureprofiles/internal/fptest" "github.com/openconfig/featureprofiles/internal/samplestream" "github.com/openconfig/ondatra" @@ -18,7 +21,6 @@ import ( const ( targetOutputPower = -9 frequency = 193100000 - dp16QAM = 1 samplingInterval = 10 * time.Second timeout = 10 * time.Minute otnIndex1 = uint32(4001) @@ -33,21 +35,32 @@ var ( IPv4: "192.0.2.1", IPv4Len: 30, } - dutPort2 = attrs.Attributes{ Desc: "dutPort2", IPv4: "192.0.2.5", IPv4Len: 30, } + operationalModeFlag = flag.Int("operational_mode", 1, "vendor-specific operational-mode for the channel") + operationalMode uint16 ) +type testcase struct { + desc string + got any + want any +} + func TestMain(m *testing.M) { fptest.RunTests(m) } func Test400ZRLogicalChannels(t *testing.T) { dut := ondatra.DUT(t, "dut") - + if operationalModeFlag != nil { + operationalMode = uint16(*operationalModeFlag) + } else { + t.Fatalf("Please specify the vendor-specific operational-mode flag") + } p1 := dut.Port(t, "port1") p2 := dut.Port(t, "port2") @@ -61,10 +74,10 @@ func Test400ZRLogicalChannels(t *testing.T) { tr1 := gnmi.Get(t, dut, gnmi.OC().Interface(p1.Name()).Transceiver().State()) tr2 := gnmi.Get(t, dut, gnmi.OC().Interface(p2.Name()).Transceiver().State()) - cfgplugins.ConfigOpticalChannel(t, dut, oc1, frequency, targetOutputPower, dp16QAM) + cfgplugins.ConfigOpticalChannel(t, dut, oc1, frequency, targetOutputPower, operationalMode) cfgplugins.ConfigOTNChannel(t, dut, oc1, otnIndex1, ethernetIndex1) cfgplugins.ConfigETHChannel(t, dut, p1.Name(), tr1, otnIndex1, ethernetIndex1) - cfgplugins.ConfigOpticalChannel(t, dut, oc2, frequency, targetOutputPower, dp16QAM) + cfgplugins.ConfigOpticalChannel(t, dut, oc2, frequency, targetOutputPower, operationalMode) cfgplugins.ConfigOTNChannel(t, dut, oc2, otnIndex2, ethernetIndex2) cfgplugins.ConfigETHChannel(t, dut, p2.Name(), tr2, otnIndex2, ethernetIndex2) @@ -80,13 +93,13 @@ func Test400ZRLogicalChannels(t *testing.T) { gnmi.Await(t, dut, gnmi.OC().Interface(p1.Name()).OperStatus().State(), timeout, oc.Interface_OperStatus_UP) gnmi.Await(t, dut, gnmi.OC().Interface(p2.Name()).OperStatus().State(), timeout, oc.Interface_OperStatus_UP) - validateEthernetChannelTelemetry(t, otnIndex1, ethernetIndex1, ethChan1) - validateEthernetChannelTelemetry(t, otnIndex2, ethernetIndex2, ethChan2) - validateOTNChannelTelemetry(t, otnIndex1, ethernetIndex1, oc1, otnChan1) - validateOTNChannelTelemetry(t, otnIndex2, ethernetIndex2, oc2, otnChan2) + validateEthernetChannelTelemetry(t, dut, otnIndex1, ethernetIndex1, ethChan1) + validateEthernetChannelTelemetry(t, dut, otnIndex2, ethernetIndex2, ethChan2) + validateOTNChannelTelemetry(t, dut, otnIndex1, ethernetIndex1, oc1, otnChan1) + validateOTNChannelTelemetry(t, dut, otnIndex2, ethernetIndex2, oc2, otnChan2) } -func validateEthernetChannelTelemetry(t *testing.T, otnChIdx, ethernetChIdx uint32, stream *samplestream.SampleStream[*oc.TerminalDevice_Channel]) { +func validateEthernetChannelTelemetry(t *testing.T, dut *ondatra.DUTDevice, otnChIdx, ethernetChIdx uint32, stream *samplestream.SampleStream[*oc.TerminalDevice_Channel]) { val := stream.Next() // value received in the gnmi subscription within 10 seconds if val == nil { t.Fatalf("Ethernet Channel telemetry stream not received in last 10 seconds") @@ -95,11 +108,7 @@ func validateEthernetChannelTelemetry(t *testing.T, otnChIdx, ethernetChIdx uint if !ok { t.Fatalf("Ethernet Channel telemetry stream empty in last 10 seconds") } - tcs := []struct { - desc string - got any - want any - }{ + tcs := []testcase{ { desc: "Index", got: ec.GetIndex(), @@ -120,32 +129,64 @@ func validateEthernetChannelTelemetry(t *testing.T, otnChIdx, ethernetChIdx uint got: ec.GetTribProtocol().String(), want: oc.TransportTypes_TRIBUTARY_PROTOCOL_TYPE_PROT_400GE.String(), }, - { - desc: "Assignment: Index", - got: ec.GetAssignment(0).GetIndex(), - want: uint32(0), - }, - { - desc: "Assignment: Logical Channel", - got: ec.GetAssignment(0).GetLogicalChannel(), - want: otnChIdx, - }, - { - desc: "Assignment: Description", - got: ec.GetAssignment(0).GetDescription(), - want: "ETH to OTN", - }, - { - desc: "Assignment: Allocation", - got: ec.GetAssignment(0).GetAllocation(), - want: float64(400), - }, - { - desc: "Assignment: Type", - got: ec.GetAssignment(0).GetAssignmentType().String(), - want: oc.Assignment_AssignmentType_LOGICAL_CHANNEL.String(), - }, } + var assignmentIndexTestcases []testcase + + if deviations.EthChannelAssignmentCiscoNumbering(dut) { + assignmentIndexTestcases = []testcase{ + { + desc: "Assignment: Index", + got: ec.GetAssignment(1).GetIndex(), + want: uint32(1)}, + { + desc: "Assignment: Logical Channel", + got: ec.GetAssignment(1).GetLogicalChannel(), + want: otnChIdx, + }, + { + desc: "Assignment: Description", + got: ec.GetAssignment(1).GetDescription(), + want: "ETH to OTN", + }, + { + desc: "Assignment: Allocation", + got: ec.GetAssignment(1).GetAllocation(), + want: float64(400), + }, + { + desc: "Assignment: Type", + got: ec.GetAssignment(1).GetAssignmentType().String(), + want: oc.Assignment_AssignmentType_LOGICAL_CHANNEL.String(), + }} + } else { + assignmentIndexTestcases = []testcase{ + { + desc: "Assignment: Index", + got: ec.GetAssignment(0).GetIndex(), + want: uint32(0), + }, + { + desc: "Assignment: Logical Channel", + got: ec.GetAssignment(0).GetLogicalChannel(), + want: otnChIdx, + }, + { + desc: "Assignment: Description", + got: ec.GetAssignment(0).GetDescription(), + want: "ETH to OTN", + }, + { + desc: "Assignment: Allocation", + got: ec.GetAssignment(0).GetAllocation(), + want: float64(400), + }, + { + desc: "Assignment: Type", + got: ec.GetAssignment(0).GetAssignmentType().String(), + want: oc.Assignment_AssignmentType_LOGICAL_CHANNEL.String(), + }} + } + tcs = append(tcs, assignmentIndexTestcases...) for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { if diff := cmp.Diff(tc.got, tc.want); diff != "" { @@ -155,7 +196,7 @@ func validateEthernetChannelTelemetry(t *testing.T, otnChIdx, ethernetChIdx uint } } -func validateOTNChannelTelemetry(t *testing.T, otnChIdx uint32, ethChIdx uint32, opticalChannel string, stream *samplestream.SampleStream[*oc.TerminalDevice_Channel]) { +func validateOTNChannelTelemetry(t *testing.T, dut *ondatra.DUTDevice, otnChIdx uint32, ethChIdx uint32, opticalChannel string, stream *samplestream.SampleStream[*oc.TerminalDevice_Channel]) { val := stream.Next() // value received in the gnmi subscription within 10 seconds if val == nil { t.Fatalf("OTN Channel telemetry stream not received in last 10 seconds") @@ -164,11 +205,7 @@ func validateOTNChannelTelemetry(t *testing.T, otnChIdx uint32, ethChIdx uint32, if !ok { t.Fatalf("OTN Channel telemetry stream empty in last 10 seconds") } - tcs := []struct { - desc string - got any - want any - }{ + tcs := []testcase{ { desc: "Description", got: cc.GetDescription(), @@ -184,56 +221,97 @@ func validateOTNChannelTelemetry(t *testing.T, otnChIdx uint32, ethChIdx uint32, got: cc.GetLogicalChannelType().String(), want: oc.TransportTypes_LOGICAL_ELEMENT_PROTOCOL_TYPE_PROT_OTN.String(), }, - { - desc: "Optical Channel Assignment: Index", - got: cc.GetAssignment(0).GetIndex(), - want: uint32(0), - }, - { - desc: "Optical Channel Assignment: Optical Channel", - got: cc.GetAssignment(0).GetOpticalChannel(), - want: opticalChannel, - }, - { - desc: "Optical Channel Assignment: Description", - got: cc.GetAssignment(0).GetDescription(), - want: "OTN to Optical Channel", - }, - { - desc: "Optical Channel Assignment: Allocation", - got: cc.GetAssignment(0).GetAllocation(), - want: float64(400), - }, - { - desc: "Optical Channel Assignment: Type", - got: cc.GetAssignment(0).GetAssignmentType().String(), - want: oc.Assignment_AssignmentType_OPTICAL_CHANNEL.String(), - }, - { - desc: "Ethernet Assignment: Index", - got: cc.GetAssignment(1).GetIndex(), - want: uint32(1), - }, - { - desc: "Ethernet Assignment: Logical Channel", - got: cc.GetAssignment(1).GetLogicalChannel(), - want: ethChIdx, - }, - { - desc: "Ethernet Assignment: Description", - got: cc.GetAssignment(1).GetDescription(), - want: "OTN to ETH", - }, - { - desc: "Ethernet Assignment: Allocation", - got: cc.GetAssignment(1).GetAllocation(), - want: float64(400), - }, - { - desc: "Ethernet Assignment: Type", - got: cc.GetAssignment(1).GetAssignmentType().String(), - want: oc.Assignment_AssignmentType_LOGICAL_CHANNEL.String(), - }, + } + var opticalChannelAssignmentIndexTestcases []testcase + + if deviations.OTNChannelAssignmentCiscoNumbering(dut) { + ciscoOpticalChannelFormat := strings.ReplaceAll(opticalChannel, "/", "_") // Ex: OpticalChannel0_0_0_18 + opticalChannelAssignmentIndexTestcases = []testcase{ + { + desc: "Assignment: Index", + got: cc.GetAssignment(1).GetIndex(), + want: uint32(1), + }, + { + desc: "Optical Channel Assignment: Optical Channel", + got: cc.GetAssignment(1).GetOpticalChannel(), + want: ciscoOpticalChannelFormat, + }, + { + desc: "Optical Channel Assignment: Description", + got: cc.GetAssignment(1).GetDescription(), + want: "OTN to Optical Channel", + }, + { + desc: "Optical Channel Assignment: Allocation", + got: cc.GetAssignment(1).GetAllocation(), + want: float64(400), + }, + { + desc: "Optical Channel Assignment: Type", + got: cc.GetAssignment(1).GetAssignmentType().String(), + want: oc.Assignment_AssignmentType_OPTICAL_CHANNEL.String(), + }, + } + } else { + opticalChannelAssignmentIndexTestcases = []testcase{ + { + desc: "Assignment: Index", + got: cc.GetAssignment(0).GetIndex(), + want: uint32(0)}, + { + desc: "Optical Channel Assignment: Optical Channel", + got: cc.GetAssignment(0).GetOpticalChannel(), + want: opticalChannel, + }, + { + desc: "Optical Channel Assignment: Description", + got: cc.GetAssignment(0).GetDescription(), + want: "OTN to Optical Channel", + }, + { + desc: "Optical Channel Assignment: Allocation", + got: cc.GetAssignment(0).GetAllocation(), + want: float64(400), + }, + { + desc: "Optical Channel Assignment: Type", + got: cc.GetAssignment(0).GetAssignmentType().String(), + want: oc.Assignment_AssignmentType_OPTICAL_CHANNEL.String(), + }, + } + } + tcs = append(tcs, opticalChannelAssignmentIndexTestcases...) + + if !deviations.OTNChannelTribUnsupported(dut) { + logicalChannelAssignmentTestcases := []testcase{ + { + desc: "Ethernet Assignment: Index", + got: cc.GetAssignment(1).GetIndex(), + want: uint32(1), + }, + { + desc: "Ethernet Assignment: Logical Channel", + got: cc.GetAssignment(1).GetLogicalChannel(), + want: ethChIdx, + }, + { + desc: "Ethernet Assignment: Description", + got: cc.GetAssignment(1).GetDescription(), + want: "OTN to ETH", + }, + { + desc: "Ethernet Assignment: Allocation", + got: cc.GetAssignment(1).GetAllocation(), + want: float64(400), + }, + { + desc: "Ethernet Assignment: Type", + got: cc.GetAssignment(1).GetAssignmentType().String(), + want: oc.Assignment_AssignmentType_LOGICAL_CHANNEL.String(), + }, + } + tcs = append(tcs, logicalChannelAssignmentTestcases...) } for _, tc := range tcs { diff --git a/internal/deviations/deviations.go b/internal/deviations/deviations.go index 5f582318d60..2487a2f6a29 100644 --- a/internal/deviations/deviations.go +++ b/internal/deviations/deviations.go @@ -1208,8 +1208,14 @@ func BgpAllowownasDiffDefaultValue(dut *ondatra.DUTDevice) bool { return lookupDUTDeviations(dut).GetBgpAllowownasDiffDefaultValue() } +// OTNChannelAssignmentCiscoNumbering returns true if OTN channel assignment index starts from 1 instead of 0 +func OTNChannelAssignmentCiscoNumbering(dut *ondatra.DUTDevice) bool { + return lookupDUTDeviations(dut).GetOtnChannelAssignmentCiscoNumbering() +} + // BgpSetmedUnionTypeUnsupported returns true if devices which are not // supporting bgp set med union type in OC. func BgpSetmedUnionTypeUnsupported(dut *ondatra.DUTDevice) bool { return lookupDUTDeviations(dut).GetBgpSetmedUnionTypeUnsupported() } + diff --git a/proto/metadata.proto b/proto/metadata.proto index c2505807478..dbbabdff0d2 100644 --- a/proto/metadata.proto +++ b/proto/metadata.proto @@ -643,9 +643,11 @@ message Metadata { // Device have different default value for allow own as. // Juniper : b/373559004 bool bgp_allowownas_diff_default_value = 231; + // Cisco numbering for OTN channel assignment starts from 1 instead of 0 + bool otn_channel_assignment_cisco_numbering = 232; // Juniper: b/358534837 // Devices that do not support setting med value using union type in OC. - bool bgp_setmed_union_type_unsupported = 232; + bool bgp_setmed_union_type_unsupported = 233; // Reserved field numbers and identifiers. reserved 84, 9, 28, 20, 90, 97, 55, 89, 19, 36, 35, 40, 173; diff --git a/proto/metadata_go_proto/metadata.pb.go b/proto/metadata_go_proto/metadata.pb.go index b90b093f7bc..f322dd40d19 100644 --- a/proto/metadata_go_proto/metadata.pb.go +++ b/proto/metadata_go_proto/metadata.pb.go @@ -15,7 +15,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.34.2 -// protoc v3.6.1 +// protoc v5.28.0 // source: metadata.proto package metadata_go_proto @@ -928,6 +928,8 @@ type Metadata_Deviations struct { // Juniper: b/358534837 // Devices that do not support setting med value using union type in OC. BgpSetmedUnionTypeUnsupported bool `protobuf:"varint,232,opt,name=bgp_setmed_union_type_unsupported,json=bgpSetmedUnionTypeUnsupported,proto3" json:"bgp_setmed_union_type_unsupported,omitempty"` + // Cisco numbering for OTN channel assignment starts from 1 instead of 0 + OtnChannelAssignmentCiscoNumbering bool `protobuf:"varint,232,opt,name=otn_channel_assignment_cisco_numbering,json=otnChannelAssignmentCiscoNumbering,proto3" json:"otn_channel_assignment_cisco_numbering,omitempty"` } func (x *Metadata_Deviations) Reset() { @@ -2435,6 +2437,9 @@ func (x *Metadata_Deviations) GetBgpAllowownasDiffDefaultValue() bool { func (x *Metadata_Deviations) GetBgpSetmedUnionTypeUnsupported() bool { if x != nil { return x.BgpSetmedUnionTypeUnsupported +func (x *Metadata_Deviations) GetOtnChannelAssignmentCiscoNumbering() bool { + if x != nil { + return x.OtnChannelAssignmentCiscoNumbering } return false } @@ -2503,6 +2508,7 @@ var file_metadata_proto_rawDesc = []byte{ 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, 0x85, 0x83, 0x01, 0x0a, 0x08, 0x4d, 0x65, 0x74, + 0x64, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x8f, 0x83, 0x01, 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, @@ -2537,6 +2543,7 @@ var file_metadata_proto_rawDesc = []byte{ 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, 0xd8, 0x7a, 0x0a, 0x0a, 0x44, 0x65, 0x76, 0x69, 0x61, + 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x1a, 0xe2, 0x7a, 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, @@ -3552,6 +3559,51 @@ var file_metadata_proto_rawDesc = []byte{ 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, + 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x53, 0x0a, 0x26, 0x6f, 0x74, 0x6e, 0x5f, 0x63, 0x68, + 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x5f, 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, + 0x5f, 0x63, 0x69, 0x73, 0x63, 0x6f, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x69, 0x6e, 0x67, + 0x18, 0xe8, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x22, 0x6f, 0x74, 0x6e, 0x43, 0x68, 0x61, 0x6e, + 0x6e, 0x65, 0x6c, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x43, 0x69, 0x73, + 0x63, 0x6f, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x69, 0x6e, 0x67, 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, 0x4a, 0x04, 0x08, + 0x28, 0x10, 0x29, 0x4a, 0x06, 0x08, 0xad, 0x01, 0x10, 0xae, 0x01, 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 (