diff --git a/feature/gnoi/os/tests/osinstall/metadata.textproto b/feature/gnoi/os/tests/osinstall/metadata.textproto index b3af04b638b..0eb9dc4bed0 100644 --- a/feature/gnoi/os/tests/osinstall/metadata.textproto +++ b/feature/gnoi/os/tests/osinstall/metadata.textproto @@ -21,5 +21,7 @@ platform_exceptions: { deviations: { default_network_instance: "default" interface_enabled: true + missing_value_for_defaults: true + bgp_default_vrf_ipv4_unicast_afi_safi_enabled_leaf_missing: "true" } } diff --git a/feature/gnoi/os/tests/osinstall/osinstall_test.go b/feature/gnoi/os/tests/osinstall/osinstall_test.go index 3b06485c9ee..c8780150608 100644 --- a/feature/gnoi/os/tests/osinstall/osinstall_test.go +++ b/feature/gnoi/os/tests/osinstall/osinstall_test.go @@ -19,7 +19,6 @@ import ( "fmt" "io" "os" - "reflect" "strings" "testing" "time" @@ -449,15 +448,34 @@ func TestPushAndVerifyInterfaceConfig(t *testing.T) { } t.Logf("Fetch interface config from the DUT using Get RPC and verify it matches with the config that was pushed earlier") - if val, present := gnmi.LookupConfig(t, dut, dc).Val(); present { - if reflect.DeepEqual(val, in) { - t.Logf("Interface config Want and Got matched") - fptest.LogQuery(t, fmt.Sprintf("%s from Get", dutPort), dc, val) - } else { - t.Errorf("Config %v Get() value not matching with what was Set()", dc) + intfPath := gnmi.OC().Interface(dutPortName) + if got := gnmi.Get(t, dut, intfPath.Description().Config()); got != dutAttrs.Desc { + t.Errorf("Interface %v description: got %v, want %v", dutPortName, got, dutAttrs.Desc) + } + if got := gnmi.Get(t, dut, intfPath.Type().Config()); got != oc.IETFInterfaces_InterfaceType_ethernetCsmacd { + t.Errorf("Interface %v type: got %v, want ethernetCsmacd", dutPortName, got) + } + if deviations.InterfaceEnabled(dut) { + if got, present := gnmi.LookupConfig(t, dut, intfPath.Enabled().Config()).Val(); !present { + if !deviations.MissingValueForDefaults(dut) { + t.Errorf("Interface %v enabled: leaf absent, want true", dutPortName) + } + } else if !got { + t.Errorf("Interface %v enabled: got false, want true", dutPortName) + } + } + subPath := intfPath.Subinterface(0).Ipv4() + if got := gnmi.Get(t, dut, subPath.Address(dutAttrs.IPv4).PrefixLength().Config()); got != dutAttrs.IPv4Len { + t.Errorf("Interface %v subinterface 0 IPv4 prefix-length: got %v, want %v", dutPortName, got, dutAttrs.IPv4Len) + } + if deviations.InterfaceEnabled(dut) && !deviations.IPv4MissingEnabled(dut) { + if got, present := gnmi.LookupConfig(t, dut, subPath.Enabled().Config()).Val(); !present { + if !deviations.MissingValueForDefaults(dut) { + t.Errorf("Interface %v subinterface 0 IPv4 enabled: leaf absent, want true", dutPortName) + } + } else if !got { + t.Errorf("Interface %v subinterface 0 IPv4 enabled: got false, want true", dutPortName) } - } else { - t.Errorf("Config %v Get() failed", dc) } } @@ -495,15 +513,51 @@ func TestPushAndVerifyBGPConfig(t *testing.T) { gnmi.Replace(t, dut, dutConfPath.Config(), dutConf) t.Logf("Fetch BGP config from the DUT using Get RPC and verify it matches with the config that was pushed earlier") - if val, present := gnmi.LookupConfig(t, dut, dutConfPath.Config()).Val(); present { - if reflect.DeepEqual(val, dutConf) { - t.Logf("BGP config Want and Got matched") - fptest.LogQuery(t, "BGP fetched from DUT using Get()", dutConfPath.Config(), val) - } else { - t.Errorf("Config %v Get() value not matching with what was Set()", dutConfPath.Config()) + bgpPath := dutConfPath.Bgp() + nbr := bgpNbr1 + + // Global + if got := gnmi.Get(t, dut, bgpPath.Global().As().Config()); got != uint32(bgpGlobalAttrs.dutAS) { + t.Errorf("BGP global AS: got %v, want %v", got, bgpGlobalAttrs.dutAS) + } + if got := gnmi.Get(t, dut, bgpPath.Global().RouterId().Config()); got != dutSrc.IPv4 { + t.Errorf("BGP global router-id: got %v, want %v", got, dutSrc.IPv4) + } + afiSafiPath := bgpPath.Global().AfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV4_UNICAST) + implicitValue := deviations.BgpDefaultVrfIPv4UnicastAfiSafiEnabledLeafMissing(dut) + if got, present := gnmi.LookupConfig(t, dut, afiSafiPath.Enabled().Config()).Val(); !present { + if implicitValue == "" { + t.Errorf("BGP global afi-safi IPV4_UNICAST enabled: leaf absent, want true") + } else if implicitValue != "true" { + t.Errorf("BGP global afi-safi IPV4_UNICAST enabled: leaf absent, implicit value is false, want true") } - } else { - t.Errorf("Config %v Get() failed", dutConfPath.Config()) + } else if !got { + t.Errorf("BGP global afi-safi IPV4_UNICAST enabled: got false, want true") + } + + // PeerGroup + pgPath := bgpPath.PeerGroup(bgpGlobalAttrs.peerGrpNamev4) + if got := gnmi.Get(t, dut, pgPath.PeerAs().Config()); got != uint32(bgpGlobalAttrs.ateAS) { + t.Errorf("BGP peer-group %v peer-as: got %v, want %v", bgpGlobalAttrs.peerGrpNamev4, got, bgpGlobalAttrs.ateAS) + } + if got := gnmi.Get(t, dut, pgPath.PeerGroupName().Config()); got != bgpGlobalAttrs.peerGrpNamev4 { + t.Errorf("BGP peer-group name: got %v, want %v", got, bgpGlobalAttrs.peerGrpNamev4) + } + + // Neighbor + nbrPath := bgpPath.Neighbor(nbr.neighborip) + if got := gnmi.Get(t, dut, nbrPath.PeerAs().Config()); got != uint32(nbr.peerAs) { + t.Errorf("BGP neighbor %v peer-as: got %v, want %v", nbr.neighborip, got, nbr.peerAs) + } + if got := gnmi.Get(t, dut, nbrPath.PeerGroup().Config()); got != bgpGlobalAttrs.peerGrpNamev4 { + t.Errorf("BGP neighbor %v peer-group: got %v, want %v", nbr.neighborip, got, bgpGlobalAttrs.peerGrpNamev4) + } + if got, present := gnmi.LookupConfig(t, dut, nbrPath.Enabled().Config()).Val(); !present { + if !deviations.MissingValueForDefaults(dut) { + t.Errorf("BGP neighbor %v enabled: leaf absent, want true", nbr.neighborip) + } + } else if !got { + t.Errorf("BGP neighbor %v enabled: got false, want true", nbr.neighborip) } } diff --git a/internal/deviations/deviations.go b/internal/deviations/deviations.go index d2e09abee4d..79062f2b8c6 100644 --- a/internal/deviations/deviations.go +++ b/internal/deviations/deviations.go @@ -1693,6 +1693,14 @@ func MatchAsPathSetUnsupported(dut *ondatra.DUTDevice) bool { return lookupDUTDeviations(dut).GetMatchAsPathSetUnsupported() } +// BgpDefaultVrfIPv4UnicastAfiSafiEnabledLeafMissing returns the implicit value to assume for the +// enabled leaf under bgp/global/afi-safis/afi-safi[IPV4_UNICAST] config in the default VRF when +// it is absent from the device response. An empty string means the deviation is not set. +// Arista: https://issuetracker.google.com/493611623 +func BgpDefaultVrfIPv4UnicastAfiSafiEnabledLeafMissing(dut *ondatra.DUTDevice) string { + return lookupDUTDeviations(dut).GetBgpDefaultVrfIpv4UnicastAfiSafiEnabledLeafMissing() +} + // SameAfiSafiAndPeergroupPoliciesUnsupported returns true if configuring same apply-policy under peer-group and peer-group/afi-safi is unsupported func SameAfiSafiAndPeergroupPoliciesUnsupported(dut *ondatra.DUTDevice) bool { return lookupDUTDeviations(dut).GetSameAfiSafiAndPeergroupPoliciesUnsupported() diff --git a/proto/metadata.proto b/proto/metadata.proto index 98dafa0c0ea..d8f097410d3 100644 --- a/proto/metadata.proto +++ b/proto/metadata.proto @@ -1289,6 +1289,11 @@ message Metadata { // Cisco: https://partnerissuetracker.corp.google.com/issues/429166378 string fabric_ft = 412; + // Device does not return the enabled leaf under bgp/global/afi-safis/afi-safi[IPV4_UNICAST] + // config in the default VRF; the leaf is implicitly true when absent. + // Arista: https://issuetracker.google.com/493611623 + string bgp_default_vrf_ipv4_unicast_afi_safi_enabled_leaf_missing = 413; + // Reserved field numbers and identifiers. reserved 84, 9, 28, 20, 38, 43, 90, 97, 55, 89, 19, 36, 35, 40, 113, 131, 141, 173, 234, 254, 231, 300, 241, 49; } diff --git a/proto/metadata_go_proto/metadata.pb.go b/proto/metadata_go_proto/metadata.pb.go index afe3ef12f50..bb9d2d83654 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.36.11 -// protoc v3.21.12 +// protoc v6.33.1 // source: metadata.proto package metadata_go_proto @@ -1418,9 +1418,13 @@ type Metadata_Deviations struct { CarrierFt string `protobuf:"bytes,411,opt,name=carrier_ft,json=carrierFt,proto3" json:"carrier_ft,omitempty"` // Functional translator name for fabric error telemetry. // Cisco: https://partnerissuetracker.corp.google.com/issues/429166378 - FabricFt string `protobuf:"bytes,412,opt,name=fabric_ft,json=fabricFt,proto3" json:"fabric_ft,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + FabricFt string `protobuf:"bytes,412,opt,name=fabric_ft,json=fabricFt,proto3" json:"fabric_ft,omitempty"` + // Device does not return the enabled leaf under bgp/global/afi-safis/afi-safi[IPV4_UNICAST] + // config in the default VRF; the leaf is implicitly true when absent. + // Arista: https://issuetracker.google.com/493611623 + BgpDefaultVrfIpv4UnicastAfiSafiEnabledLeafMissing string `protobuf:"bytes,413,opt,name=bgp_default_vrf_ipv4_unicast_afi_safi_enabled_leaf_missing,json=bgpDefaultVrfIpv4UnicastAfiSafiEnabledLeafMissing,proto3" json:"bgp_default_vrf_ipv4_unicast_afi_safi_enabled_leaf_missing,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *Metadata_Deviations) Reset() { @@ -4092,6 +4096,13 @@ func (x *Metadata_Deviations) GetFabricFt() string { return "" } +func (x *Metadata_Deviations) GetBgpDefaultVrfIpv4UnicastAfiSafiEnabledLeafMissing() string { + if x != nil { + return x.BgpDefaultVrfIpv4UnicastAfiSafiEnabledLeafMissing + } + return "" +} + type Metadata_PlatformExceptions struct { state protoimpl.MessageState `protogen:"open.v1"` Platform *Metadata_Platform `protobuf:"bytes,1,opt,name=platform,proto3" json:"platform,omitempty"` @@ -4148,7 +4159,7 @@ var File_metadata_proto protoreflect.FileDescriptor const file_metadata_proto_rawDesc = "" + "\n" + - "\x0emetadata.proto\x12\x12openconfig.testing\x1a1github.com/openconfig/ondatra/proto/testbed.proto\"\xa9\xe5\x01\n" + + "\x0emetadata.proto\x12\x12openconfig.testing\x1a1github.com/openconfig/ondatra/proto/testbed.proto\"\xa1\xe6\x01\n" + "\bMetadata\x12\x12\n" + "\x04uuid\x18\x01 \x01(\tR\x04uuid\x12\x17\n" + "\aplan_id\x18\x02 \x01(\tR\x06planId\x12 \n" + @@ -4160,7 +4171,7 @@ const file_metadata_proto_rawDesc = "" + "\bPlatform\x12.\n" + "\x06vendor\x18\x01 \x01(\x0e2\x16.ondatra.Device.VendorR\x06vendor\x120\n" + "\x14hardware_model_regex\x18\x03 \x01(\tR\x12hardwareModelRegex\x124\n" + - "\x16software_version_regex\x18\x04 \x01(\tR\x14softwareVersionRegexJ\x04\b\x02\x10\x03R\x0ehardware_model\x1a\xf5\xda\x01\n" + + "\x16software_version_regex\x18\x04 \x01(\tR\x14softwareVersionRegexJ\x04\b\x02\x10\x03R\x0ehardware_model\x1a\xed\xdb\x01\n" + "\n" + "Deviations\x120\n" + "\x14ipv4_missing_enabled\x18\x01 \x01(\bR\x12ipv4MissingEnabled\x129\n" + @@ -4543,7 +4554,8 @@ const file_metadata_proto_rawDesc = "" + ",default_subinterface_packet_counters_missing\x18\x99\x03 \x01(\bR(defaultSubinterfacePacketCountersMissing\x12\x1e\n" + "\n" + "carrier_ft\x18\x9b\x03 \x01(\tR\tcarrierFt\x12\x1c\n" + - "\tfabric_ft\x18\x9c\x03 \x01(\tR\bfabricFtJ\x04\bT\x10UJ\x04\b\t\x10\n" + + "\tfabric_ft\x18\x9c\x03 \x01(\tR\bfabricFt\x12v\n" + + ":bgp_default_vrf_ipv4_unicast_afi_safi_enabled_leaf_missing\x18\x9d\x03 \x01(\tR1bgpDefaultVrfIpv4UnicastAfiSafiEnabledLeafMissingJ\x04\bT\x10UJ\x04\b\t\x10\n" + "J\x04\b\x1c\x10\x1dJ\x04\b\x14\x10\x15J\x04\b&\x10'J\x04\b+\x10,J\x04\bZ\x10[J\x04\ba\x10bJ\x04\b7\x108J\x04\bY\x10ZJ\x04\b\x13\x10\x14J\x04\b$\x10%J\x04\b#\x10$J\x04\b(\x10)J\x04\bq\x10rJ\x06\b\x83\x01\x10\x84\x01J\x06\b\x8d\x01\x10\x8e\x01J\x06\b\xad\x01\x10\xae\x01J\x06\b\xea\x01\x10\xeb\x01J\x06\b\xfe\x01\x10\xff\x01J\x06\b\xe7\x01\x10\xe8\x01J\x06\b\xac\x02\x10\xad\x02J\x06\b\xf1\x01\x10\xf2\x01J\x04\b1\x102\x1a\xa0\x01\n" + "\x12PlatformExceptions\x12A\n" + "\bplatform\x18\x01 \x01(\v2%.openconfig.testing.Metadata.PlatformR\bplatform\x12G\n" +